summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Monnier <monnier@iro.umontreal.ca>2017-10-18 13:31:44 -0400
committerStefan Monnier <monnier@iro.umontreal.ca>2017-10-18 13:31:44 -0400
commit802cdf3d4b8dfa6c67f9b836036d27150d90e362 (patch)
tree7ad5973aeaa4465164f42e7406fca44029c14fe2
parentcd645247b0aa67bd230aaec1674e31934b153c50 (diff)
downloademacs-18.59.tar.gz
Release 18.59emacs-18.59
-rw-r--r--ChangeLog94
-rw-r--r--GETTING.GNU.SOFTWARE84
-rw-r--r--INSTALL208
-rw-r--r--Makefile150
-rw-r--r--PROBLEMS771
-rw-r--r--README42
-rw-r--r--VMSINSTALL129
-rw-r--r--VMSNOTES70
-rw-r--r--allrename.com39
-rwxr-xr-xbuild-install38
-rw-r--r--cpp/Makefile20
-rw-r--r--cpp/cccp.c2483
-rw-r--r--cpp/cexp.y591
-rw-r--r--emacs.com19
-rw-r--r--etc/3B-MAXMEM75
-rw-r--r--etc/AIX.DUMP218
-rw-r--r--etc/APOLLO39
-rw-r--r--etc/APPLE57
-rw-r--r--etc/BABYL127
-rw-r--r--etc/CCADIFF159
-rw-r--r--etc/CHARACTERS54
-rw-r--r--etc/COOKIES157
-rw-r--r--etc/COPYING249
-rw-r--r--etc/ChangeLog294
-rw-r--r--etc/DEBUG113
-rw-r--r--etc/DIFF779
-rw-r--r--etc/DISTRIB427
-rw-r--r--etc/FAQ5757
-rw-r--r--etc/FTP266
-rw-r--r--etc/GNU475
-rw-r--r--etc/GNU.JOKES38
-rw-r--r--etc/GOSDIFF614
-rw-r--r--etc/INTERVAL.IDEAS30
-rw-r--r--etc/INTERVIEW434
-rw-r--r--etc/LEDIT77
-rw-r--r--etc/LPF122
-rw-r--r--etc/MACHINES444
-rw-r--r--etc/MAILINGLISTS743
-rw-r--r--etc/MOTIVATION176
-rw-r--r--etc/Makefile87
-rw-r--r--etc/NEWS1655
-rw-r--r--etc/NICKLES.WORTH188
-rw-r--r--etc/ONEWS1346
-rw-r--r--etc/OONEWS1165
-rw-r--r--etc/OPTIONS190
-rw-r--r--etc/SERVICE968
-rw-r--r--etc/SUN-SUPPORT318
-rw-r--r--etc/SUNBUG41
-rw-r--r--etc/TERMS229
-rw-r--r--etc/TO-DO26
-rw-r--r--etc/TUTORIAL4
-rw-r--r--etc/XDOC461
-rw-r--r--etc/XENIX116
-rw-r--r--etc/Xkeymap.txt98
-rw-r--r--etc/celibacy.112
-rw-r--r--etc/complink.com41
-rw-r--r--etc/cvtmail.c (renamed from lib-src/cvtmail.c)1
-rw-r--r--etc/digest-doc.c (renamed from lib-src/digest-doc.c)0
-rw-r--r--etc/echo.msg207
-rw-r--r--etc/emacs.1513
-rw-r--r--etc/emacs.icon34
-rw-r--r--etc/emacs.names442
-rw-r--r--etc/emacsclient.c278
-rw-r--r--etc/emacstool.1134
-rw-r--r--etc/emacstool.c520
-rw-r--r--etc/env.c326
-rw-r--r--etc/etags-vmslib.c (renamed from lib-src/etags-vmslib.c)60
-rw-r--r--etc/etags.c1631
-rw-r--r--etc/etags.vms15
-rw-r--r--etc/fakemail.c (renamed from lib-src/fakemail.c)65
-rw-r--r--etc/faq2texi.perl220
-rw-r--r--etc/ledit.l150
-rw-r--r--etc/leditcfns.c (renamed from lib-src/leditcfns.c)0
-rw-r--r--etc/make-docfile.c (renamed from lib-src/make-docfile.c)271
-rw-r--r--etc/makedoc.com48
-rw-r--r--etc/movemail.c (renamed from lib-src/movemail.c)156
-rw-r--r--etc/ms-kermit167
-rw-r--r--etc/ms-kermit-7bit312
-rw-r--r--etc/qsort.c226
-rw-r--r--etc/refcard.tex627
-rw-r--r--etc/server.c (renamed from lib-src/emacsserver.c)50
-rw-r--r--etc/sex.6111
-rw-r--r--etc/sorted-doc.c (renamed from lib-src/sorted-doc.c)0
-rw-r--r--etc/spook.linesbin0 -> 733 bytes
-rw-r--r--etc/termcap.dat10
-rw-r--r--etc/termcap.ucb2667
-rw-r--r--etc/test-distrib.c (renamed from lib-src/test-distrib.c)0
-rw-r--r--etc/testfilebin0 -> 222 bytes
-rw-r--r--etc/ulimit.hack38
-rw-r--r--etc/vipcard.tex680
-rw-r--r--etc/vmslink.opt2
-rw-r--r--etc/wakeup.c (renamed from lib-src/wakeup.c)3
-rw-r--r--etc/xmouse.doc31
-rw-r--r--etc/yow.c (renamed from lib-src/yow.c)90
-rw-r--r--info/COPYING249
-rw-r--r--info/dir32
-rw-r--r--info/emacs369
-rw-r--r--info/emacs-11007
-rw-r--r--info/emacs-101131
-rw-r--r--info/emacs-111173
-rw-r--r--info/emacs-121216
-rw-r--r--info/emacs-131330
-rw-r--r--info/emacs-141335
-rw-r--r--info/emacs-15503
-rw-r--r--info/emacs-16797
-rw-r--r--info/emacs-17538
-rw-r--r--info/emacs-18949
-rw-r--r--info/emacs-19445
-rw-r--r--info/emacs-21133
-rw-r--r--info/emacs-31220
-rw-r--r--info/emacs-41133
-rw-r--r--info/emacs-51123
-rw-r--r--info/emacs-61204
-rw-r--r--info/emacs-71132
-rw-r--r--info/emacs-81191
-rw-r--r--info/emacs-91136
-rw-r--r--info/info628
-rw-r--r--info/regex601
-rw-r--r--info/termcap76
-rw-r--r--info/termcap-11147
-rw-r--r--info/termcap-21004
-rw-r--r--info/termcap-31429
-rw-r--r--info/texinfo147
-rw-r--r--info/texinfo-11283
-rw-r--r--info/texinfo-21405
-rw-r--r--info/texinfo-31410
-rw-r--r--info/texinfo-4861
-rw-r--r--info/vip73
-rw-r--r--info/vip-11514
-rw-r--r--info/vip-2665
-rwxr-xr-xinstall.sh119
-rw-r--r--kepteditor.com88
-rw-r--r--lib-src/emacstool.c340
-rw-r--r--lib-src/hexl.c219
-rw-r--r--lib-src/timer.c155
-rw-r--r--lisp/COPYING249
-rw-r--r--lisp/ChangeLog5068
-rw-r--r--lisp/abbrev.el269
-rw-r--r--lisp/abbrev.elcbin0 -> 7437 bytes
-rw-r--r--lisp/abbrevlist.el2
-rw-r--r--lisp/abbrevlist.elcbin0 -> 457 bytes
-rw-r--r--lisp/ada.el175
-rw-r--r--lisp/ada.elcbin0 -> 16382 bytes
-rw-r--r--lisp/add-log.el87
-rw-r--r--lisp/add-log.elcbin0 -> 1552 bytes
-rw-r--r--lisp/array.el957
-rw-r--r--lisp/autoinsert.el8
-rw-r--r--lisp/backquote.el (renamed from lisp/emacs-lisp/backquote.el)70
-rw-r--r--lisp/backquote.elcbin0 -> 3718 bytes
-rw-r--r--lisp/bg-mouse.el (renamed from lisp/term/bg-mouse.el)11
-rw-r--r--lisp/bibtex.el426
-rw-r--r--lisp/bibtex.elcbin0 -> 11087 bytes
-rw-r--r--lisp/blackbox.el229
-rw-r--r--lisp/blackbox.elcbin0 -> 4404 bytes
-rw-r--r--lisp/buff-menu.el59
-rw-r--r--lisp/buff-menu.elcbin0 -> 7306 bytes
-rw-r--r--lisp/bytecomp.el1165
-rw-r--r--lisp/bytecomp.elcbin0 -> 29155 bytes
-rw-r--r--lisp/c-fill.el269
-rw-r--r--lisp/c-fill.elcbin0 -> 3309 bytes
-rw-r--r--lisp/c-mode.el662
-rw-r--r--lisp/c-mode.elcbin0 -> 12459 bytes
-rw-r--r--lisp/cal.el242
-rw-r--r--lisp/cal.elcbin0 -> 5054 bytes
-rw-r--r--lisp/calendar/appt.el500
-rw-r--r--lisp/case-table.el101
-rw-r--r--lisp/chistory.el151
-rw-r--r--lisp/chistory.elcbin0 -> 4185 bytes
-rw-r--r--lisp/cl-indent.el461
-rw-r--r--lisp/cl-indent.elcbin0 -> 5841 bytes
-rw-r--r--lisp/cl.el2018
-rw-r--r--lisp/cl.elcbin0 -> 46948 bytes
-rw-r--r--lisp/cmacexp.el45
-rw-r--r--lisp/comint.el866
-rw-r--r--lisp/compare-w.el59
-rw-r--r--lisp/compare-w.elcbin0 -> 659 bytes
-rw-r--r--lisp/compile.el318
-rw-r--r--lisp/compile.elcbin0 -> 6602 bytes
-rw-r--r--lisp/completion.el3113
-rw-r--r--lisp/dabbrev.el221
-rw-r--r--lisp/dabbrev.elcbin0 -> 3375 bytes
-rw-r--r--lisp/dbx.el165
-rw-r--r--lisp/dbx.elcbin0 -> 4515 bytes
-rw-r--r--lisp/debug.el261
-rw-r--r--lisp/debug.elcbin0 -> 6098 bytes
-rw-r--r--lisp/dired.el633
-rw-r--r--lisp/dired.elcbin0 -> 16161 bytes
-rw-r--r--lisp/disass.el446
-rw-r--r--lisp/disass.elcbin0 -> 6599 bytes
-rw-r--r--lisp/disp-table.el115
-rw-r--r--lisp/dissociate.el (renamed from lisp/play/dissociate.el)6
-rw-r--r--lisp/dissociate.elcbin0 -> 1198 bytes
-rw-r--r--lisp/doctex.el189
-rw-r--r--lisp/doctor.el1614
-rw-r--r--lisp/doctor.elcbin0 -> 43542 bytes
-rw-r--r--lisp/ebuff-menu.el244
-rw-r--r--lisp/ebuff-menu.elcbin0 -> 7038 bytes
-rw-r--r--lisp/echistory.el34
-rw-r--r--lisp/echistory.elcbin0 -> 5590 bytes
-rw-r--r--lisp/edmacro.el640
-rw-r--r--lisp/edt-doc.el106
-rw-r--r--lisp/edt.el (renamed from lisp/emulation/edt.el)53
-rw-r--r--lisp/edt.elcbin0 -> 12296 bytes
-rw-r--r--lisp/ehelp.el133
-rw-r--r--lisp/ehelp.elcbin0 -> 7393 bytes
-rw-r--r--lisp/electric.el9
-rw-r--r--lisp/electric.elcbin0 -> 2376 bytes
-rw-r--r--lisp/emacs-lisp/ring.el101
-rw-r--r--lisp/emacsbug.el (renamed from lisp/mail/emacsbug.el)2
-rw-r--r--lisp/files.el1080
-rw-r--r--lisp/files.elcbin0 -> 31068 bytes
-rw-r--r--lisp/fill.el287
-rw-r--r--lisp/fill.elcbin0 -> 4406 bytes
-rw-r--r--lisp/find-gc.el127
-rw-r--r--lisp/flame.el306
-rw-r--r--lisp/flame.elcbin0 -> 9125 bytes
-rw-r--r--lisp/float-sup.el52
-rw-r--r--lisp/float.el (renamed from lisp/emacs-lisp/float.el)31
-rw-r--r--lisp/float.elcbin0 -> 8128 bytes
-rw-r--r--lisp/fortran.el654
-rw-r--r--lisp/fortran.elc242
-rw-r--r--lisp/ftp.el142
-rw-r--r--lisp/ftp.elcbin0 -> 8730 bytes
-rw-r--r--lisp/gdb.el397
-rw-r--r--lisp/gdb.elcbin0 -> 7626 bytes
-rw-r--r--lisp/gnusmail.el148
-rw-r--r--lisp/gnusmisc.el214
-rw-r--r--lisp/gosmacs.el4
-rw-r--r--lisp/hanoi.el (renamed from lisp/play/hanoi.el)2
-rw-r--r--lisp/hanoi.elcbin0 -> 2236 bytes
-rw-r--r--lisp/help.el295
-rw-r--r--lisp/help.elcbin0 -> 8434 bytes
-rw-r--r--lisp/helper.el (renamed from lisp/emacs-lisp/helper.el)4
-rw-r--r--lisp/helper.elcbin0 -> 3044 bytes
-rw-r--r--lisp/hexl.el659
-rw-r--r--lisp/hideif.el (renamed from lisp/progmodes/hideif.el)144
-rw-r--r--lisp/hideif.elcbin0 -> 17884 bytes
-rw-r--r--lisp/icon.el (renamed from lisp/progmodes/icon.el)90
-rw-r--r--lisp/icon.elcbin0 -> 10882 bytes
-rw-r--r--lisp/inc-vers.el15
-rw-r--r--lisp/indent.el225
-rw-r--r--lisp/indent.elcbin0 -> 4961 bytes
-rw-r--r--lisp/info.el708
-rw-r--r--lisp/info.elcbin0 -> 16140 bytes
-rw-r--r--lisp/informat.el411
-rw-r--r--lisp/informat.elcbin0 -> 6734 bytes
-rw-r--r--lisp/isearch.el385
-rw-r--r--lisp/isearch.elcbin0 -> 4780 bytes
-rw-r--r--lisp/kermit.el86
-rw-r--r--lisp/keypad.el152
-rw-r--r--lisp/keypad.elcbin0 -> 2451 bytes
-rw-r--r--lisp/ledit.el24
-rw-r--r--lisp/life.el (renamed from lisp/play/life.el)8
-rw-r--r--lisp/life.elcbin0 -> 5219 bytes
-rw-r--r--lisp/lisp-mode.el (renamed from lisp/emacs-lisp/lisp-mode.el)191
-rw-r--r--lisp/lisp-mode.elcbin0 -> 11917 bytes
-rw-r--r--lisp/lisp.el (renamed from lisp/emacs-lisp/lisp.el)105
-rw-r--r--lisp/lisp.elcbin0 -> 5285 bytes
-rw-r--r--lisp/loaddefs.el1942
-rw-r--r--lisp/loadup.el56
-rw-r--r--lisp/lpr.el65
-rw-r--r--lisp/lpr.elcbin0 -> 1548 bytes
-rw-r--r--lisp/ls-lisp.el132
-rw-r--r--lisp/macros.el37
-rw-r--r--lisp/macros.elcbin0 -> 2356 bytes
-rw-r--r--lisp/mail-utils.el (renamed from lisp/mail/mail-utils.el)140
-rw-r--r--lisp/mail-utils.elcbin0 -> 3317 bytes
-rw-r--r--lisp/mail/rmailout.el182
-rw-r--r--lisp/mail/rmailsort.el203
-rw-r--r--lisp/mailalias.el (renamed from lisp/mail/mailalias.el)24
-rw-r--r--lisp/mailalias.elcbin0 -> 2037 bytes
-rw-r--r--lisp/mailpost.el (renamed from lisp/mail/mailpost.el)6
-rw-r--r--lisp/makesum.elcbin0 -> 1285 bytes
-rw-r--r--lisp/man.el54
-rw-r--r--lisp/man.elcbin0 -> 2143 bytes
-rw-r--r--lisp/medit.el4
-rw-r--r--lisp/medit.elcbin0 -> 2763 bytes
-rw-r--r--lisp/meese.el (renamed from lisp/play/meese.el)0
-rw-r--r--lisp/mh-e.el2910
-rw-r--r--lisp/mh-e.elc1128
-rw-r--r--lisp/mhspool.el404
-rw-r--r--lisp/mim-mode.el72
-rw-r--r--lisp/mim-mode.elcbin0 -> 20097 bytes
-rw-r--r--lisp/mim-syntax.elcbin0 -> 1276 bytes
-rw-r--r--lisp/misc.el51
-rw-r--r--lisp/mlconvert.el (renamed from lisp/emulation/mlconvert.el)0
-rw-r--r--lisp/mlconvert.elcbin0 -> 9065 bytes
-rw-r--r--lisp/mlsupport.el (renamed from lisp/emulation/mlsupport.el)5
-rw-r--r--lisp/mlsupport.elcbin0 -> 10191 bytes
-rw-r--r--lisp/modula2.el (renamed from lisp/progmodes/modula2.el)126
-rw-r--r--lisp/modula2.elcbin0 -> 9910 bytes
-rw-r--r--lisp/mouse.el524
-rw-r--r--lisp/netunam.el152
-rw-r--r--lisp/nnspool.el374
-rw-r--r--lisp/nntp.el667
-rw-r--r--lisp/nroff-mode.el (renamed from lisp/textmodes/nroff-mode.el)19
-rw-r--r--lisp/nroff-mode.elcbin0 -> 4631 bytes
-rw-r--r--lisp/options.el28
-rw-r--r--lisp/options.elcbin0 -> 2742 bytes
-rw-r--r--lisp/outline.el (renamed from lisp/textmodes/ooutline.el)139
-rw-r--r--lisp/outline.elcbin0 -> 9516 bytes
-rw-r--r--lisp/page.el (renamed from lisp/textmodes/page.el)6
-rw-r--r--lisp/page.elcbin0 -> 2186 bytes
-rw-r--r--lisp/paragraphs.el (renamed from lisp/textmodes/paragraphs.el)59
-rw-r--r--lisp/paragraphs.elcbin0 -> 4416 bytes
-rw-r--r--lisp/paths.el76
-rw-r--r--lisp/picture.el (renamed from lisp/textmodes/picture.el)82
-rw-r--r--lisp/picture.elcbin0 -> 19654 bytes
-rw-r--r--lisp/play/gomoku.el1161
-rw-r--r--lisp/play/mpuz.el448
-rw-r--r--lisp/progmodes/compile.el478
-rw-r--r--lisp/prolog.el (renamed from lisp/progmodes/prolog.el)50
-rw-r--r--lisp/prolog.elcbin0 -> 6261 bytes
-rw-r--r--lisp/rect.el13
-rw-r--r--lisp/rect.elcbin0 -> 5003 bytes
-rw-r--r--lisp/register.el39
-rw-r--r--lisp/register.elcbin0 -> 4126 bytes
-rw-r--r--lisp/replace.el307
-rw-r--r--lisp/replace.elcbin0 -> 6083 bytes
-rw-r--r--lisp/reposition.el185
-rw-r--r--lisp/resume.el160
-rw-r--r--lisp/rfc822.el (renamed from lisp/mail/rfc822.el)3
-rw-r--r--lisp/rfc822.elcbin0 -> 4324 bytes
-rw-r--r--lisp/rmail.el1433
-rw-r--r--lisp/rmail.elcbin0 -> 30112 bytes
-rw-r--r--lisp/rmailedit.el (renamed from lisp/mail/rmailedit.el)2
-rw-r--r--lisp/rmailedit.elcbin0 -> 2258 bytes
-rw-r--r--lisp/rmailkwd.el (renamed from lisp/mail/rmailkwd.el)14
-rw-r--r--lisp/rmailkwd.elcbin0 -> 4576 bytes
-rw-r--r--lisp/rmailmsc.el (renamed from lisp/mail/rmailmsc.el)6
-rw-r--r--lisp/rmailmsc.elcbin0 -> 728 bytes
-rw-r--r--lisp/rmailout.el126
-rw-r--r--lisp/rmailout.elcbin0 -> 2296 bytes
-rw-r--r--lisp/rmailsum.el (renamed from lisp/mail/rmailsum.el)51
-rw-r--r--lisp/rmailsum.elcbin0 -> 9655 bytes
-rw-r--r--lisp/rnews.el (renamed from lisp/mail/rnews.el)38
-rw-r--r--lisp/rnews.elcbin0 -> 23722 bytes
-rw-r--r--lisp/rnewspost.el (renamed from lisp/mail/rnewspost.el)15
-rw-r--r--lisp/rnewspost.elcbin0 -> 8941 bytes
-rw-r--r--lisp/saveconf.el240
-rw-r--r--lisp/scheme.el (renamed from lisp/progmodes/scheme.el)140
-rw-r--r--lisp/scheme.elcbin0 -> 10747 bytes
-rw-r--r--lisp/scribe.el (renamed from lisp/textmodes/scribe.el)26
-rw-r--r--lisp/scribe.elcbin0 -> 7839 bytes
-rw-r--r--lisp/sendmail.el469
-rw-r--r--lisp/sendmail.elcbin0 -> 9885 bytes
-rw-r--r--lisp/server.el60
-rw-r--r--lisp/server.elcbin0 -> 5497 bytes
-rw-r--r--lisp/shell.el726
-rw-r--r--lisp/shell.elcbin0 -> 12048 bytes
-rw-r--r--lisp/simple.el1431
-rw-r--r--lisp/simple.elcbin0 -> 36869 bytes
-rw-r--r--lisp/simula.defns185
-rw-r--r--lisp/simula.el827
-rw-r--r--lisp/simula.elcbin0 -> 17293 bytes
-rw-r--r--lisp/sort.el258
-rw-r--r--lisp/sort.elcbin0 -> 8884 bytes
-rw-r--r--lisp/spell.el (renamed from lisp/textmodes/spell.el)0
-rw-r--r--lisp/spell.elcbin0 -> 2616 bytes
-rw-r--r--lisp/spook.el (renamed from lisp/play/spook.el)2
-rw-r--r--lisp/startup.el238
-rw-r--r--lisp/startup.elcbin0 -> 4319 bytes
-rw-r--r--lisp/studly.el (renamed from lisp/play/studly.el)0
-rw-r--r--lisp/studly.elcbin0 -> 774 bytes
-rw-r--r--lisp/subr.el154
-rw-r--r--lisp/subr.elcbin0 -> 5669 bytes
-rw-r--r--lisp/sun-cursors.el (renamed from lisp/sun-curs.el)2
-rw-r--r--lisp/sun-fns.el223
-rw-r--r--lisp/sun-fns.elcbin0 -> 25003 bytes
-rw-r--r--lisp/sun-keys.el3
-rw-r--r--lisp/sun-mouse.el (renamed from lisp/term/sun-mouse.el)144
-rw-r--r--lisp/sun-mouse.elcbin0 -> 19797 bytes
-rw-r--r--lisp/sup-mouse.el (renamed from lisp/term/sup-mouse.el)0
-rw-r--r--lisp/sup-mouse.elcbin0 -> 3036 bytes
-rw-r--r--lisp/superyank.el1212
-rw-r--r--lisp/tabify.elcbin0 -> 786 bytes
-rw-r--r--lisp/tags.el304
-rw-r--r--lisp/tags.elcbin0 -> 7375 bytes
-rw-r--r--lisp/tar-mode.el1117
-rw-r--r--lisp/telnet.el204
-rw-r--r--lisp/telnet.elcbin0 -> 5416 bytes
-rw-r--r--lisp/term-nasty.el21
-rw-r--r--lisp/term/COPYING249
-rw-r--r--lisp/term/apollo.el1
-rw-r--r--lisp/term/at386.el101
-rw-r--r--lisp/term/bbn.el1
-rw-r--r--lisp/term/bg.el6
-rw-r--r--lisp/term/bgnv.el1
-rw-r--r--lisp/term/bgrv.el1
-rw-r--r--lisp/term/bobcat.el11
-rw-r--r--lisp/term/news.el85
-rw-r--r--lisp/term/s4.el142
-rw-r--r--lisp/term/sun.el333
-rw-r--r--lisp/term/supdup.el81
-rw-r--r--lisp/term/unixpc.el148
-rw-r--r--lisp/term/vt100.el66
-rw-r--r--lisp/term/vt101.el1
-rw-r--r--lisp/term/vt102.el1
-rw-r--r--lisp/term/vt125.el1
-rw-r--r--lisp/term/vt131.el1
-rw-r--r--lisp/term/vt200.el90
-rw-r--r--lisp/term/vt220.el1
-rw-r--r--lisp/term/vt240.el1
-rw-r--r--lisp/term/vt300.el1
-rw-r--r--lisp/term/wyse50.el235
-rw-r--r--lisp/term/x-win.el817
-rw-r--r--lisp/term/xterm.el2
-rw-r--r--lisp/terminal.el228
-rw-r--r--lisp/terminal.elcbin0 -> 23792 bytes
-rw-r--r--lisp/tex-mode.el465
-rw-r--r--lisp/tex-mode.elcbin0 -> 12135 bytes
-rw-r--r--lisp/tex-start.el11
-rw-r--r--lisp/texinfmt.el (renamed from lisp/textmodes/texinfmt.el)1015
-rw-r--r--lisp/texinfmt.elcbin0 -> 37533 bytes
-rw-r--r--lisp/texinfo.el175
-rw-r--r--lisp/texinfo.elc84
-rw-r--r--lisp/text-mode.el (renamed from lisp/textmodes/text-mode.el)42
-rw-r--r--lisp/text-mode.elcbin0 -> 3041 bytes
-rw-r--r--lisp/textmodes/bib-mode.el233
-rw-r--r--lisp/textmodes/fill.el246
-rw-r--r--lisp/textmodes/ispell4.el541
-rw-r--r--lisp/textmodes/page-ext.el745
-rw-r--r--lisp/textmodes/refbib.el715
-rw-r--r--lisp/textmodes/tex-mode.el799
-rw-r--r--lisp/textmodes/texinfo.el414
-rw-r--r--lisp/textmodes/texnfo-upd.el1726
-rw-r--r--lisp/time.el48
-rw-r--r--lisp/time.elcbin0 -> 2230 bytes
-rw-r--r--lisp/timer.el92
-rw-r--r--lisp/uncompress.el26
-rw-r--r--lisp/underline.el (renamed from lisp/textmodes/underline.el)2
-rw-r--r--lisp/underline.elcbin0 -> 739 bytes
-rw-r--r--lisp/undigest.el (renamed from lisp/mail/undigest.el)3
-rw-r--r--lisp/undigest.elcbin0 -> 1380 bytes
-rw-r--r--lisp/userlock.el9
-rw-r--r--lisp/userlock.elcbin0 -> 3234 bytes
-rw-r--r--lisp/version.el45
-rw-r--r--lisp/vi.el (renamed from lisp/emulation/vi.el)2
-rw-r--r--lisp/vi.elcbin0 -> 48241 bytes
-rw-r--r--lisp/view.el150
-rw-r--r--lisp/view.elcbin0 -> 12843 bytes
-rw-r--r--lisp/vip.el (renamed from lisp/emulation/vip.el)39
-rw-r--r--lisp/vip.elcbin0 -> 69338 bytes
-rw-r--r--lisp/vms-patch.el29
-rw-r--r--lisp/vms-patch.elcbin0 -> 1972 bytes
-rw-r--r--lisp/vmsproc.el98
-rw-r--r--lisp/vmsproc.elcbin0 -> 2255 bytes
-rw-r--r--lisp/vmsx.el137
-rw-r--r--lisp/window.el69
-rw-r--r--lisp/window.elcbin0 -> 1161 bytes
-rw-r--r--lisp/x-menu.elcbin0 -> 3126 bytes
-rw-r--r--lisp/x-mouse.el295
-rw-r--r--lisp/x-mouse.elcbin0 -> 9230 bytes
-rw-r--r--lisp/xscheme.el15
-rw-r--r--lisp/xscheme.elcbin0 -> 25651 bytes
-rw-r--r--lisp/yow.el (renamed from lisp/play/yow.el)17
-rw-r--r--lisp/yow.elcbin0 -> 1233 bytes
-rw-r--r--lispref/book-spine.texinfo25
-rw-r--r--man/ChangeLog46
-rw-r--r--man/Makefile8
-rw-r--r--man/README23
-rw-r--r--man/cl.texinfo853
-rw-r--r--man/emacs.aux706
-rw-r--r--man/emacs.cps400
-rw-r--r--man/emacs.fns686
-rw-r--r--man/emacs.kys497
-rw-r--r--man/emacs.pgs0
-rw-r--r--man/emacs.texi19241
-rw-r--r--man/emacs.vrs217
-rw-r--r--man/regex.texinfo588
-rwxr-xr-xman/split-man14
-rw-r--r--man/termcap.aux135
-rw-r--r--man/termcap.cps61
-rw-r--r--man/termcap.fns16
-rw-r--r--man/termcap.kys153
-rw-r--r--man/termcap.texi3417
-rw-r--r--man/texindex.c1594
-rw-r--r--man/texinfo.aux345
-rw-r--r--man/texinfo.cps211
-rw-r--r--man/texinfo.fns97
-rwxr-xr-xman/texinfo.tex2665
-rw-r--r--man/texinfo.texi5141
-rw-r--r--man/vip.texinfo1960
-rw-r--r--oldXMenu/Activate.c531
-rw-r--r--oldXMenu/AddPane.c103
-rw-r--r--oldXMenu/AddSel.c93
-rw-r--r--oldXMenu/ChangeLog69
-rw-r--r--oldXMenu/ChgPane.c66
-rw-r--r--oldXMenu/ChgSel.c88
-rw-r--r--oldXMenu/Create.c746
-rw-r--r--oldXMenu/DelPane.c88
-rw-r--r--oldXMenu/DelSel.c72
-rw-r--r--oldXMenu/Destroy.c116
-rw-r--r--oldXMenu/Error.c30
-rw-r--r--oldXMenu/EvHand.c26
-rw-r--r--oldXMenu/FindPane.c64
-rw-r--r--oldXMenu/FindSel.c72
-rw-r--r--oldXMenu/Imakefile87
-rw-r--r--oldXMenu/InsPane.c111
-rw-r--r--oldXMenu/InsSel.c105
-rw-r--r--oldXMenu/Internal.c988
-rw-r--r--oldXMenu/Locate.c78
-rw-r--r--oldXMenu/Makefile90
-rw-r--r--oldXMenu/Post.c85
-rw-r--r--oldXMenu/README4
-rw-r--r--oldXMenu/Recomp.c104
-rw-r--r--oldXMenu/SetAEQ.c29
-rw-r--r--oldXMenu/SetFrz.c28
-rw-r--r--oldXMenu/SetPane.c43
-rw-r--r--oldXMenu/SetSel.c50
-rw-r--r--oldXMenu/X10.h78
-rw-r--r--oldXMenu/XCrAssoc.c67
-rw-r--r--oldXMenu/XDelAssoc.c72
-rw-r--r--oldXMenu/XDestAssoc.c49
-rw-r--r--oldXMenu/XLookAssoc.c67
-rw-r--r--oldXMenu/XMakeAssoc.c107
-rw-r--r--oldXMenu/XMenu.h262
-rw-r--r--oldXMenu/XMenuInt.h60
-rw-r--r--oldXMenu/copyright.h19
-rw-r--r--oldXMenu/insque.c38
-rw-r--r--shortnames/COPYING249
-rw-r--r--shortnames/Makefile44
-rw-r--r--shortnames/defines.c14
-rw-r--r--shortnames/dups.c62
-rw-r--r--shortnames/header.h10
-rw-r--r--shortnames/names.c99
-rw-r--r--shortnames/reserved34
-rw-r--r--shortnames/special23
-rw-r--r--src/.dbxinit15
-rw-r--r--src/COPYING249
-rw-r--r--src/ChangeLog4372
-rw-r--r--src/Makefile (renamed from src/Makefile.in)17
-rw-r--r--src/README26
-rw-r--r--src/TAGS6961
-rw-r--r--src/VMSBUILD67
-rw-r--r--src/XTests.c189
-rw-r--r--src/abbrev.c121
-rw-r--r--src/acldef.h40
-rw-r--r--src/alloc.c1581
-rw-r--r--src/alloca.c194
-rw-r--r--src/alloca.s320
-rw-r--r--src/buffer.c1359
-rw-r--r--src/buffer.h165
-rw-r--r--src/build.com5
-rw-r--r--src/bytecode.c734
-rw-r--r--src/callint.c522
-rw-r--r--src/callproc.c487
-rw-r--r--src/casefiddle.c57
-rw-r--r--src/casetab.c250
-rw-r--r--src/ccom.com2
-rw-r--r--src/chpdef.h38
-rw-r--r--src/cm.c405
-rw-r--r--src/cm.h100
-rw-r--r--src/cmds.c82
-rw-r--r--src/commands.h20
-rw-r--r--src/compile.com91
-rw-r--r--src/config.h-dist (renamed from src/config.in)81
-rw-r--r--src/crt0.c535
-rw-r--r--src/data.c1635
-rw-r--r--src/dir.h105
-rw-r--r--src/dired.c143
-rw-r--r--src/dispextern.h91
-rw-r--r--src/dispnew.c1671
-rw-r--r--src/doc.c434
-rw-r--r--src/doprnt.c70
-rw-r--r--src/editfns.c1111
-rw-r--r--src/emacs.c779
-rw-r--r--src/emacssignal.h57
-rw-r--r--src/environ.c5
-rw-r--r--src/eval.c2222
-rw-r--r--src/fileio.c914
-rw-r--r--src/filelock.c103
-rw-r--r--src/filemode.c196
-rw-r--r--src/filetypes.h13
-rw-r--r--src/floatfns.c558
-rw-r--r--src/fns.c224
-rw-r--r--src/getpagesize.h34
-rw-r--r--src/gettime.h36
-rw-r--r--src/hftctl.c421
-rw-r--r--src/indent.c358
-rw-r--r--src/indent.h (renamed from src/mocklisp.h)26
-rw-r--r--src/insdel.c228
-rw-r--r--src/ioctl.h1
-rw-r--r--src/keyboard.c2288
-rw-r--r--src/keymap.c1329
-rw-r--r--src/lastfile.c43
-rw-r--r--src/link.com7
-rw-r--r--src/lisp.h993
-rw-r--r--src/lread.c1328
-rw-r--r--src/m-7300.h87
-rw-r--r--src/m-all2800.h146
-rw-r--r--src/m-alliant.h144
-rw-r--r--src/m-alliant1.h5
-rw-r--r--src/m-alliant4.h20
-rw-r--r--src/m-altos.h58
-rw-r--r--src/m-amdahl.h202
-rw-r--r--src/m-apollo.h97
-rw-r--r--src/m-att3b.h160
-rw-r--r--src/m-aviion.h150
-rw-r--r--src/m-bullx20.h125
-rw-r--r--src/m-celerity.h69
-rw-r--r--src/m-convex.h172
-rw-r--r--src/m-cydra5.h135
-rw-r--r--src/m-delta.h164
-rw-r--r--src/m-delta88.h168
-rw-r--r--src/m-dpx2-200.h4
-rw-r--r--src/m-dpx2-300.h4
-rw-r--r--src/m-dpx2.h286
-rw-r--r--src/m-dual.h67
-rw-r--r--src/m-elxsi.h132
-rw-r--r--src/m-gec63.h79
-rw-r--r--src/m-gould.h127
-rw-r--r--src/m-hp9000s300.h202
-rw-r--r--src/m-hp9000s800.h189
-rw-r--r--src/m-ibmps2-aix.h235
-rw-r--r--src/m-ibmrs6000.h151
-rw-r--r--src/m-ibmrt-aix.h196
-rw-r--r--src/m-ibmrt.h135
-rw-r--r--src/m-intel386.h184
-rw-r--r--src/m-intel860.h116
-rw-r--r--src/m-iris4d.h190
-rw-r--r--src/m-irist.h147
-rw-r--r--src/m-is386.h12
-rw-r--r--src/m-isi-ov.h97
-rw-r--r--src/m-masscomp.h146
-rw-r--r--src/m-mega68.h57
-rw-r--r--src/m-mg1.h113
-rw-r--r--src/m-mips.h241
-rw-r--r--src/m-mips4.h34
-rw-r--r--src/m-news-risc.h74
-rw-r--r--src/m-news.h68
-rw-r--r--src/m-next.h125
-rw-r--r--src/m-ns16000.h53
-rw-r--r--src/m-ns32000.h116
-rw-r--r--src/m-nu.h80
-rw-r--r--src/m-orion.h80
-rw-r--r--src/m-orion105.h76
-rw-r--r--src/m-pfa50.h117
-rw-r--r--src/m-plexus.h124
-rw-r--r--src/m-pmax.h36
-rw-r--r--src/m-pyramid.h72
-rw-r--r--src/m-pyrmips.h123
-rw-r--r--src/m-seq386.h11
-rw-r--r--src/m-sequent.h176
-rw-r--r--src/m-sgi3000.h1
-rw-r--r--src/m-sparc.h113
-rw-r--r--src/m-stride.h130
-rw-r--r--src/m-sun1.h68
-rw-r--r--src/m-sun2.h89
-rw-r--r--src/m-sun3.h26
-rw-r--r--src/m-sun386.h63
-rw-r--r--src/m-tad68k.h134
-rw-r--r--src/m-tahoe.h83
-rw-r--r--src/m-tandem-s2.h90
-rw-r--r--src/m-targon31.h119
-rw-r--r--src/m-tek4300.h96
-rw-r--r--src/m-template.h106
-rw-r--r--src/m-tower32.h130
-rw-r--r--src/m-tower32v3.h134
-rw-r--r--src/m-triton88.h51
-rw-r--r--src/m-ustation.h137
-rw-r--r--src/m-vax.h104
-rw-r--r--src/m-wicat.h164
-rw-r--r--src/m/next.h92
-rw-r--r--src/macros.c243
-rw-r--r--src/macros.h31
-rw-r--r--src/malloc.c856
-rw-r--r--src/marker.c36
-rw-r--r--src/minibuf.c1181
-rw-r--r--src/mocklisp.c19
-rw-r--r--src/ndir.h51
-rw-r--r--src/old-ralloc.c1069
-rw-r--r--src/param.h2
-rw-r--r--src/paths.h-dist19
-rw-r--r--src/pre-crt0.c9
-rw-r--r--src/precomp.com6
-rw-r--r--src/print.c706
-rw-r--r--src/process.c2769
-rw-r--r--src/process.h76
-rw-r--r--src/ralloc.c426
-rw-r--r--src/recomp.com21
-rw-r--r--src/regex.c1725
-rw-r--r--src/regex.h184
-rw-r--r--src/s-386bsd.h48
-rw-r--r--src/s-386ix.h22
-rw-r--r--src/s-aix3-1.h233
-rw-r--r--src/s-aix3-2.h11
-rw-r--r--src/s-bsd4-1.h145
-rw-r--r--src/s-bsd4-2.h124
-rw-r--r--src/s-bsd4-3.h124
-rw-r--r--src/s-dgux.h292
-rw-r--r--src/s-dgux4-31.h5
-rw-r--r--src/s-esix.h29
-rw-r--r--src/s-esix5r4.h13
-rw-r--r--src/s-hpux7.h268
-rw-r--r--src/s-hpux8.h21
-rw-r--r--src/s-iris3-5.h188
-rw-r--r--src/s-iris3-6.h189
-rw-r--r--src/s-irix3-3.h186
-rw-r--r--src/s-irix4-0.h45
-rw-r--r--src/s-isc2-2.h51
-rw-r--r--src/s-isc3-0.h7
-rw-r--r--src/s-mach2.h53
-rw-r--r--src/s-newsos5.h37
-rw-r--r--src/s-osf1.h14
-rw-r--r--src/s-rtu.h160
-rw-r--r--src/s-sco.h98
-rw-r--r--src/s-sco3-2-1.h17
-rw-r--r--src/s-sco3-2-2.h18
-rw-r--r--src/s-sco3-2-4.h3
-rw-r--r--src/s-sol2.h18
-rw-r--r--src/s-sunos4-0.h12
-rw-r--r--src/s-sunos4-1.h34
-rw-r--r--src/s-template.h142
-rw-r--r--src/s-umax.h174
-rw-r--r--src/s-unipl5-0.h188
-rw-r--r--src/s-unipl5-2.h182
-rw-r--r--src/s-usg5-0.h183
-rw-r--r--src/s-usg5-2-2.h186
-rw-r--r--src/s-usg5-2.h186
-rw-r--r--src/s-usg5-3.h220
-rw-r--r--src/s-usg5-4.h171
-rw-r--r--src/s-vms.h251
-rw-r--r--src/s-vms4-0.h2
-rw-r--r--src/s-vms4-2.h3
-rw-r--r--src/s-vms4-4.h3
-rw-r--r--src/s-vms5-5.h8
-rw-r--r--src/s-xenix.h233
-rw-r--r--src/scroll.c389
-rw-r--r--src/search.c1329
-rw-r--r--src/sink.h39
-rw-r--r--src/sink11.h51
-rw-r--r--src/sink11mask.h51
-rw-r--r--src/sinkmask.h39
-rw-r--r--src/sunfns.c54
-rw-r--r--src/syntax.c244
-rw-r--r--src/syntax.h84
-rw-r--r--src/sysdep.c4300
-rw-r--r--src/temacs.opt59
-rw-r--r--src/term.c1240
-rw-r--r--src/termcap.c661
-rw-r--r--src/termchar.h48
-rw-r--r--src/termhooks.h53
-rw-r--r--src/terminfo.c50
-rw-r--r--src/termopts.h47
-rw-r--r--src/testemacs.com4
-rw-r--r--src/tparam.c277
-rw-r--r--src/uaf.h23
-rw-r--r--src/undo.c87
-rw-r--r--src/unexaix.c1053
-rw-r--r--src/unexconvex.c603
-rw-r--r--src/unexec.c107
-rw-r--r--src/unexelf.c639
-rw-r--r--src/unexenix.c263
-rw-r--r--src/unexfx2800.c16
-rw-r--r--src/unexhp9k800.c6
-rw-r--r--src/unexmips.c317
-rw-r--r--src/unexnext.c432
-rw-r--r--src/unexshm.c285
-rw-r--r--src/vlimit.h2
-rw-r--r--src/vms-pp.c4
-rw-r--r--src/vms-pp.trans10
-rw-r--r--src/vms-pwd.h34
-rw-r--r--src/vmsfns.c71
-rw-r--r--src/vmsmap.c235
-rw-r--r--src/vmspaths.h15
-rw-r--r--src/vmsproc.c784
-rw-r--r--src/window.c2063
-rw-r--r--src/window.h204
-rw-r--r--src/x11fns.c1019
-rw-r--r--src/x11term.c2709
-rw-r--r--src/x11term.h22
-rw-r--r--src/xdisp.c2131
-rw-r--r--src/xfns.c1400
-rw-r--r--src/xkeys-aix.h163
-rw-r--r--src/xmenu.c338
-rw-r--r--src/xrdb.c477
-rw-r--r--src/xselect.c.old666
-rw-r--r--src/xterm.c1933
-rw-r--r--src/xterm.h58
-rw-r--r--src/ymakefile535
-rw-r--r--vmsdist.com87
782 files changed, 223519 insertions, 37567 deletions
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 00000000000..97a2a860df7
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,94 @@
+Fri Oct 30 19:36:38 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * Version 18.59 released.
+
+Wed Oct 28 19:30:14 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * vmsdist.com: Don't copy vaxcrtl.olb into distribution.
+ Assume VMS version 5.5 or newer.
+
+Sat Oct 3 01:32:44 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * build-install: Use sh -c pwd, not just pwd.
+
+Fri Oct 2 19:14:07 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * Makefile (install.xenix): Delete spurious space.
+
+Tue Aug 25 18:04:27 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * Makefile (src/paths.h): Use just `sed', not `/bin/sed'.
+
+Sun Jun 7 14:21:01 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * Makefile (install): Get rid of -s from install commands.
+
+Thu Feb 13 14:53:26 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * Makefile (install): Use INSTALL to install programs.
+ (INSTALL): New variable.
+
+Sun Feb 9 21:41:17 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * Makefile (mkdir): Create BINDIR and MANDIR if nec.
+ Don't chmod LIBDIR.
+
+ * build-install: Use normal convention for EMACS dir.
+ Fix syntax in directory name comparison.
+ Install emacsclient. Deleted the chmod for executables.
+ Start with #! to force use of sh.
+
+Sat Feb 1 17:40:30 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * install.sh: New file.
+
+Fri Jan 31 23:46:51 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * Makefile (clean, distclean): Clean oldXMenu subdir.
+
+Mon Jan 27 16:29:53 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * Makefile (install): Remove `B' from tar xf command.
+
+ * Makefile (CLEANDIR): Add oldXMenu.
+
+Sat Jan 25 00:06:59 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * build-install: Finish updating to sh syntax.
+
+Fri Jan 17 22:56:27 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * Makefile (LIBDIR): Change back to /usr/local/emacs.
+ (It got changed recently but I don't know why.)
+
+Sat Mar 9 23:21:20 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * Makefile (clean): Use /bin/pwd, not pwd.
+
+Fri Sep 28 22:36:32 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * Makefile (install, install.sysv, install.xenix):
+ Install wakeup instead of loadst. No need for setuid or setgid.
+
+Tue Aug 7 13:19:35 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * Makefile (clean): Clean etc if that's not the installation dir.
+
+Thu Apr 26 13:36:18 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * Makefile (paths.h): Make sed alter each name in the path.
+
+Tue Aug 30 13:43:43 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * Makefile (install.sysv): Use cpio, not tar.
+
+Wed Aug 3 19:20:13 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * Makefile (lockdir): Rename `lock' target.
+ Depend on it from install*, not from `all'.
+
+Mon May 16 02:08:08 1988 Richard Stallman (rms at frosted-flakes.ai.mit.edu)
+
+ * Makefile: Changed LIBDIR and BINDIR back to /usr/local/{emacs,bin}
+ to match build-install and paths.h.
+
diff --git a/GETTING.GNU.SOFTWARE b/GETTING.GNU.SOFTWARE
deleted file mode 100644
index e3c18449044..00000000000
--- a/GETTING.GNU.SOFTWARE
+++ /dev/null
@@ -1,84 +0,0 @@
--*- text -*-
- Getting GNU Software, 19 Sep 90
-Copyright (C) 1986, 1987, 1988, 1989, 1990 Free Software Foundation, Inc.
-
- Permission is granted to anyone to make or distribute
- verbatim copies of this document provided that the
- copyright notice and this permission notice are preserved.
-
-* GNU and the Free Software Foundation
-
-Project GNU is organized as part of the Free Software Foundation, Inc.
-The Free Software Foundation has the following goals:
- 1) to create GNU as a full development/operating system.
- 2) to distribute GNU and other useful software with source code and
-permission to copy and redistribute.
-
-Further information on the rationale for GNU is in file
-/pub/gnu/etc/GNU (All files referred to are on the Internet host
-prep.ai.mit.edu.
-
-Information on GNU Internet mailing lists and gnUSENET newsgroupscan
-be found in file /pub/gnu/etc/MAILINGLISTS.
-
-* How To Get The Software
-
-The easiest way to get a copy of the distribution is from someone else
-who has it. You need not ask for permission to do so, or tell any one
-else; just copy it. The second easiest is to ftp it over the
-Internet. The third easiest way is to uucp it. Ftp and uucp
-information is in file /pub/gnu/etc/FTP.
-
-If you cannot get a copy any of these ways, or if you would feel more
-confident getting copies straight from us, or if you would like to get
-some funds to us to help in our efforts, you can order one from the
-Free Software Foundation. See file /pub/gnu/etc/DISTRIB.
-
-* Available Software
-
-** GNU Emacs
-
-The GNU Emacs distribution includes:
- - manual source in TeX format.
- - an enhanced regex (regular expression) library.
-
-See file /pub/gnu/etc/MACHINES for the status of porting Emacs to
-various machines and operating systems.
-
-** C Scheme - a block structured dialect of LISP.
-
-The Free Software Foundation distributes C Scheme for the MIT Scheme
-Project on it tapes. A partial ftp distribution can be found on
-prep.ai.mit.edu. The full ftp distribution can be found on
-zurich.ai.mit.edu.
-
-Problems with the C Scheme distribution and it's ftp distribution
-should be referred to: <bug-cscheme@prep.ai.mit.edu>. There are two
-general mailing lists: <scheme@mc.lcs.mit.edu> and
-<info-cscheme@prep.ai.mit.edu>. Requests to join either list to:
-<info-cscheme-request@prep.ai.mit.edu> or
-<scheme-request@mc.lcs.mit.edu>.
-
-** Other GNU Software
-
-A fuller list of available software are in the files
-/pub/gnu/etc/DISTRIB and /pub/gnu/etc/FTP.
-
-* No Warranties
-
-We distribute software in the hope that it will be useful, but without
-any warranty. No author or distributor of this software accepts
-responsibility to anyone for the consequences of using it or for
-whether it serves any particular purpose or works at all, unless he
-says so in writing.
-
-* If You Like The Software
-
-If you like the software developed and distributed by the Free
-Software Foundation, please express your satisfaction with a donation.
-Your donations will help to support the foundation and make our future
-efforts successful, including a complete development and operating
-system, called GNU (Gnu's Not Un*x), which will run Un*x user
-programs. For more information on GNU and the Foundation, contact us
-at Internet address <gnu@prep.ai.mit.edu> or the foundation's US Mail
-address found in file /pub/gnu/etc/DISTRIB.
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 00000000000..96199f683ba
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,208 @@
+GNU Emacs Installation Guide
+Copyright (c) 1988 Free software Foundation, Inc.
+
+ Permission is granted to anyone to make or distribute verbatim copies
+ of this document as received, in any medium, provided that the
+ copyright notice and permission notice are preserved,
+ and that the distributor grants the recipient permission
+ for further redistribution as permitted by this notice.
+
+ Permission is granted to distribute modified versions
+ of this document, or of portions of it,
+ under the above conditions, provided also that they
+ carry prominent notices stating who last changed them,
+ and that any new or changed statements about the activities
+ of the Free Software Foundation are approved by the Foundation.
+
+
+PREPARATION
+
+0) Make sure your system has enough swapping space allocated
+ to handle a program whose pure code is 400k bytes or
+ and whose data area is at least 150k and can reach 600k
+ bytes or much more. If the swapping space is insufficient, you
+ will get an error in the command temacs -l loadup inc dump,
+ found in $BUILD/src/ymakefile, or possibly when running the
+ final dumped Emacs.
+
+1) Choose a place in the file structure for the main directory
+ of Emacs code to reside. This will ultimately have
+ subdirectories named src, lisp, etc, etc. Call this name
+ $EMACS. Let $BUILD stand for the name the directory has now.
+
+2) Copy $BUILD/src/config.h-dist to $BUILD/src/config.h,
+ and edit it to set the right options for your system. The file
+ $BUILD/etc/MACHINES may help you decide what to put there.
+ If you need to override any of the definitions in the s- and m-
+ files for your system and machine, do so by editing config.h,
+ not by changing the s- and m- files. Occasionally you may
+ need to redefine parameters used in etc/movemail.c.
+
+3) Declare the place in the file system where Emacs will
+ be once installed. This is done in the file `src/paths.h'.
+ But you don't have to change it yourself. `build-install' and `make'
+ edit `src/paths.h' automatically.
+
+ If you are using the shell-script `build-install'
+ edit the assignment that sets the variable `EMACS'.
+ If you are using `make' in the main Emacs directory to do
+ the installation, edit the definition of `LIBDIR' in `Makefile'
+ in that directory.
+
+ If you are doing the building by hand (not using `build-install' or
+ `make') then you yourself must copy $BUILD/src/paths.h-dist to
+ paths.h, and edit it to contain the correct directory names:
+ $EMACS/lisp for the directory for Lisp libraries, and $EMACS/etc for
+ the directory for executables and text files.
+
+ Emacs will use these names once it has been built.
+ During building, Emacs searches the directory ../lisp for
+ Lisp files before the directories specified in paths.h, and
+ executable files are found in ../etc. So the main Emacs
+ directory $BUILD can be anywhere while Emacs is built, but
+ must be renamed to $EMACS afterwards in order for Emacs to
+ work properly.
+
+4) Look at $BUILD/lisp/paths.el; if some of those values
+ are not right for your system, create a file
+ $BUILD/lisp/site-init.el containing Lisp code to override them.
+ You would use the Lisp function `setq'. For example,
+
+ (setq news-inews-program "/usr/bin/inews")
+
+ is how you would override the default value of the
+ variable news-inews-program (which is "/usr/local/inews").
+
+5) Put into $BUILD/lisp/site-init.el any Lisp code
+ you want loaded into Emacs before it is dumped out.
+
+ This file is nonexistent in the distribution.
+ You do not need to create it, if you have nothing
+ to put in it.
+
+6) Decide what compiler switches to use.
+ For example, if you would like to compile with optimization,
+ you might want to change the definition of CFLAGS in
+ the file $BUILD/src/ymakefile to use C_OPTIMIZE_SWITCH
+ instead of C_DEBUG_SWITCH.
+
+ Note that many Unix compilers have bugs that affect -O; if you use
+ -O, be prepared to recompile without -O if you have any trouble.
+
+ Note that many (most?) versions of debuggers
+ other than GDB do not know how to handle programs like Emacs
+ that use raw or cbreak mode, change other terminal status bits,
+ and use asynchronous SIGIO signals for terminal input.
+ However, most debuggers may work if Emacs uses a separate terminal
+ from the one being used by the debugger, or if Emacs is using
+ its own X window.
+
+ If you do have a debugger that works, it is probably best to use `-g'
+ so that you are not helpless in the face of a problem.
+
+ With GCC, you can use -O and -g together. The easiest way to do this
+ is to change C_DEBUG_SWITCH to include both -O and -g. GCC is probably
+ more reliable with -O than without, as it is tested more with -O.
+
+ The way to specify use of GCC is to set the environment variable CC
+ to `gcc' before you do `make install'
+
+7) If you wish to compile with GCC, you may need to use -traditional
+ or run fixincludes. This is needed if your system's header files
+ are incompatible with ANSI C. If your system header files are designed
+ for ANSI C, then GCC should handle them properly. For more info, refer
+ the INSTALL file of GCC.
+
+ If your system header files are non-ANSI and you don't use -traditional
+ or fixincludes to compensate, the usual effect is that the ioctl
+ system call does not work. The result is an Emacs that almost completely
+ fails to work.
+
+8) Refer to the file $BUILD/etc/TERMS for information on
+ fields you may wish to add to various termcap entries.
+
+9) Run `make install' in the main directory of the Emacs distribution
+ to finish building and installing Emacs in the standard way.
+ You are done!
+
+(On system V, you need to use `make install.sysv' instead of `make install'.
+On Xenix, use `make install.xenix'.
+On AIX, use `make install.aix'.
+You can also try `make INSTALL=./install.sh install'
+on any kind of system.)
+
+The last step of building Emacs involves running Emacs in a special
+way. At this time, if the directories that Emacs will refer to during
+use for Lisp code and executables do not already exist, Emacs will
+print a warning to this effect. If you plan to have `make' create
+these directories while it installs Emacs, then do not be alarmed by
+the warnings.
+
+The shell script `build-install' is an alternative to `make install'.
+It is a little less sophisticated than the makefile, but probably
+easier to customize for nonstandard kinds of installation. If you
+want to install in precisely the usual fashion, we recommend using
+`make' rather than `build-install'.
+
+
+BUILDING GNU EMACS
+`make install' and its variants start with these steps to compile Emacs.
+
+1) Cd to $BUILD/etc and run `make'.
+ This creates files named `ctags' and `etags' and `wakeup'
+ and `make-docfile' and `digest-doc' and `test-distrib'. And others.
+
+2) Cd to $BUILD/src and Run `make'
+ This refers to files in the $BUILD/lisp and $BUILD/etc subdirectories
+ using names ../lisp and ../etc.
+
+ This creates a file $BUILD/src/xemacs which is the runnable Emacs,
+ assigning it a new version number by incrementing the version
+ stored in $BUILD/lisp/version.el.
+
+ It also creates a file in $BUILD/etc, whose name is
+ DOC followed by the current Emacs version.
+ This file contains documentation strings for all the
+ functions in Emacs. Each time you run make to make a new xemacs,
+ a new DOC file with a new name is made. You must keep
+ the DOC file for an Emacs version as long as you keep using
+ that Emacs version.
+
+
+INSTALLATION
+
+After compilation, `make install' and its variants continue with these steps
+to install the Emacs already compiled.
+
+0) Move files from $BUILD to $EMACS if they are not the same directory.
+ The files that you need include at least the subdirectories
+ lisp, etc and info. After this, the directory in which you said
+ (in paths.h) Emacs would be installed actually contains the necessary
+ parts of Emacs.
+
+1) Move the file $EMACS/xemacs to /usr/local/bin/emacs,
+ or some other name in users' search paths.
+ `xemacs' has an alternate name $EMACS/src/emacs-EMACSVERSION;
+ you may wish to make a symbolic link
+ named /usr/local/bin/emacs pointing to that alternate name,
+ as an easy way of installing different versions.
+
+ You can delete $EMACS/src/temacs.
+
+3) Move the programs ctags, etags and emacsclient from $EMACS/etc
+ to /usr/local/bin. These programs are run by users as shell commands.
+
+ The program $EMACS/etc/wakeup is invoked by Emacs when appropriate.
+
+ The programs $EMACS/etc/make-docfile and $EMACS/etc/test-distrib
+ are not used any more; they were used in building Emacs.
+
+ $EMACS/etc/digest-doc can be used to convert DOC into a
+ file for users to read. There is no important reason to move it.
+
+4) The files in $EMACS/src subdirectory, except for xemacs,
+ are not used by Emacs once it is built.
+
+
+See the file PROBLEMS in this directory for a list of various
+problems sometimes encountered, and what to do about them.
diff --git a/Makefile b/Makefile
new file mode 100644
index 00000000000..917d4d44f01
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,150 @@
+# make all to compile and build Emacs
+# make install to install it
+# make install.sysv to install on system V.
+# make install.xenix to install on Xenix
+# make install.aix to install on AIX.
+# make tags to update tags tables
+#
+# make distclean to delete everything that wasn't in the distribution
+# This is a very dangerous thing to do!
+# make clean
+# This is a little less dangerous.
+
+SHELL = /bin/sh
+
+# Where to install things
+# Note that on system V you must change MANDIR to /use/local/man/man1.
+# This got changed in late 1991 to say /usr/local/lib/emacs,
+# but there was no explanation of why, so it seems better to keep this stable.
+LIBDIR= /usr/local/emacs
+BINDIR= /usr/local/bin
+MANDIR= /usr/local/man/man1
+
+# Flags passed down to subdirectory makefiles.
+MFLAGS=
+
+# Command used for installation.
+# If `install' doesn't work on your system, try `./install.sh'.
+INSTALL=install
+
+# Subdirectories to make recursively. `lisp' is not included
+# because the compiled lisp files are part of the distribution
+# and you cannot remake them without installing Emacs first.
+SUBDIR= etc src
+
+# Subdirectories to install
+COPYDIR= etc info lisp
+
+# Subdirectories to clean
+CLEANDIR= ${COPYDIR} lisp/term oldXMenu
+
+all: src/paths.h ${SUBDIR}
+
+src/paths.h: Makefile src/paths.h-dist
+ sed 's;/usr/local/emacs;${LIBDIR};g' < src/paths.h-dist > src/paths.h
+
+src: etc
+
+.RECURSIVE: ${SUBDIR}
+
+${SUBDIR}: FRC
+ cd $@; make ${MFLAGS} all
+
+install: all mkdir lockdir
+# B option to tar xf removed because some systems don't have it.
+# It should work without that as long as the same tar program
+# is running on both sides of the pipe.
+ -if [ `/bin/pwd` != `(cd ${LIBDIR}; /bin/pwd)` ] ; then \
+ tar cf - ${COPYDIR} | (cd ${LIBDIR}; umask 0; tar xf - ) ;\
+ for i in ${CLEANDIR}; do \
+ (rm -rf ${LIBDIR}/$$i/RCS; \
+ rm -f ${LIBDIR}/$$i/\#*; \
+ rm -f ${LIBDIR}/$$i/*~); \
+ done \
+ else true; \
+ fi
+ $(INSTALL) -c etc/emacsclient ${BINDIR}/emacsclient
+ $(INSTALL) -c etc/etags ${BINDIR}/etags
+ $(INSTALL) -c etc/ctags ${BINDIR}/ctags
+ $(INSTALL) -c -m 1755 src/xemacs ${BINDIR}/xemacs
+ $(INSTALL) -c -m 444 etc/emacs.1 ${MANDIR}/emacs.1
+ -rm -f ${BINDIR}/emacs
+ mv ${BINDIR}/xemacs ${BINDIR}/emacs
+
+install.sysv: all mkdir lockdir
+ -if [ `/bin/pwd` != `(cd ${LIBDIR}; /bin/pwd)` ] ; then \
+ find ${COPYDIR} -print | cpio -pdum ${LIBDIR} ;\
+ for i in ${CLEANDIR}; do \
+ (rm -rf ${LIBDIR}/$$i/RCS; \
+ rm -f ${LIBDIR}/$$i/\#*; \
+ rm -f ${LIBDIR}/$$i/*~); \
+ done \
+ else true; \
+ fi
+ -cpset etc/emacsclient ${BINDIR}/emacsclient 755 bin bin
+ -cpset etc/etags ${BINDIR}/etags 755 bin bin
+ -cpset etc/ctags ${BINDIR}/ctags 755 bin bin
+ -cpset etc/emacs.1 ${MANDIR}/emacs.1 444 bin bin
+ -/bin/rm -f ${BINDIR}/emacs
+ -cpset src/xemacs ${BINDIR}/emacs 1755 bin bin
+
+install.xenix: all mkdir lockdir
+ if [ `pwd` != `(cd ${LIBDIR}; pwd)` ] ; then \
+ tar cf - ${COPYDIR} | (cd ${LIBDIR}; umask 0; tar xpf - ) ;\
+ for i in ${CLEANDIR}; do \
+ (rm -rf ${LIBDIR}/$$i/RCS; \
+ rm -f ${LIBDIR}/$$i/\#*; \
+ rm -f ${LIBDIR}/$$i/*~); \
+ done \
+ else true; \
+ fi
+ cp etc/etags etc/ctags etc/emacsclient ${BINDIR}
+ chmod 755 ${BINDIR}/etags ${BINDIR}/ctags ${BINDIR}/emacsclient
+ cp etc/emacs.1 ${MANDIR}/emacs.1
+ chmod 444 ${MANDIR}/emacs.1
+ -mv -f ${BINDIR}/emacs ${BINDIR}/emacs.old
+ cp src/xemacs ${BINDIR}/emacs
+ chmod 1755 ${BINDIR}/emacs
+ -rm -f ${BINDIR}/emacs.old
+
+install.aix: all mkdir lockdir
+ -if [ `/bin/pwd` != `(cd ${LIBDIR}; /bin/pwd)` ] ; then \
+ tar cf - ${COPYDIR} | (cd ${LIBDIR}; umask 0; tar xBf - ) ;\
+ for i in ${CLEANDIR}; do \
+ (rm -rf ${LIBDIR}/$$i/RCS; \
+ rm -f ${LIBDIR}/$$i/\#*; \
+ rm -f ${LIBDIR}/$$i/*~); \
+ done \
+ else true; \
+ fi
+ install -f ${BINDIR} etc/emacsclient
+ install -f ${BINDIR} etc/etags
+ install -f ${BINDIR} etc/ctags
+ install -M 1755 -f ${BINDIR} src/xemacs
+ install -M 444 -f ${MANDIR} etc/emacs.1
+ -rm -f ${BINDIR}/emacs
+ mv ${BINDIR}/xemacs ${BINDIR}/emacs
+
+mkdir: FRC
+ -mkdir ${LIBDIR} ${BINDIR} ${MANDIR}
+
+distclean:
+ for i in ${SUBDIR}; do (cd $$i; make ${MFLAGS} distclean); done
+ cd oldXMenu; make ${MFLAGS} distclean
+
+clean:
+ cd src; make clean
+ cd oldXMenu; make ${MFLAGS} clean
+ if [ `/bin/pwd` != `(cd ${LIBDIR}; /bin/pwd)` ] ; then \
+ cd etc; make clean; \
+ else true; \
+ fi
+
+lockdir:
+ -mkdir ${LIBDIR}/lock
+ -chmod 777 ${LIBDIR}/lock
+
+FRC:
+
+tags: etc
+ cd src; ../etc/etags *.[ch] ../lisp/*.el ../lisp/term/*.el
diff --git a/PROBLEMS b/PROBLEMS
new file mode 100644
index 00000000000..333321c78d8
--- /dev/null
+++ b/PROBLEMS
@@ -0,0 +1,771 @@
+This file describes various problems that have been encountered
+in compiling, installing and running GNU Emacs.
+
+* If you have trouble building Emacs in Solaris, it is likely to be
+that you've put /usr/ucb ahead of /usr/ccs/bin in PATH. Try changing
+that for building Emacs. (The problem may really come from
+/usr/ucb/ld.)
+
+* M-x manual command does not work on Solaris when you specify a
+manual section number. You can make it work by setting manual-program
+to "/usr/ucb/man".
+
+* On some variants of SVR4, Emacs does not work at all with X.
+
+Try defining BROKEN_FIONREAD in your config.h file. If this solves
+the problem, please send a bug report to tell us this is needed; be
+sure to say exactly what type of machine and system you are using.
+
+* On some MIPS systems, division by zero crashes Emacs.
+
+Some operating systems on MIPS machines give SIGTRAP for division by
+zero instead of the usual signals. The only real solution is to fix
+the system to give a proper signal.
+
+In the meantime, you can change init_data in data.c if you wish.
+Change it to handle SIGTRAP as well as SIGFPE. But this will have a
+great disadvantage: you will not be able to run Emacs under a
+debugger. I think crashing on division by zero is a lesser problem.
+
+* Linking says that the functions insque and remque are undefined.
+
+Change oldXMenu/Makefile by adding insque.o to the variable OBJS.
+
+* Emacs fails to understand most Internet host names, even though
+the names work properly with other programs on the same system.
+
+This typically happens on Suns and other systems that use shared
+libraries. The cause is that the site has installed a version of the
+shared library which uses a name server--but has not installed a
+similiar version of the unshared library which Emacs uses.
+
+The result is that most programs, using the shared library, work with
+the nameserver, but Emacs does not.
+
+The fix is to install an unshared library that corresponds to what you
+installed in the shared library, and then relink Emacs.
+
+* On a Sun running SunOS 4.1.1, you get this error message from GNU ld:
+
+ /lib/libc.a(_Q_sub.o): Undefined symbol __Q_get_rp_rd referenced from text segment
+
+The problem is in the Sun shared C library, not in GNU ld.
+
+The solution is to install Patch-ID# 100267-03 from Sun.
+
+* Self documentation messages are garbled.
+
+This means that the file `etc/DOC-...' doesn't properly correspond
+with the Emacs executable. Redumping Emacs and then installing the
+corresponding pair of files should fix the problem.
+
+* M-x shell immediately responds "Process shell exited abnormally with code 1".
+
+This is often due to inability to run the program `env'.
+This should be in the `etc' subdirectory of the directory
+where Emacs is installed, and it should be marked executable.
+
+* Trouble using ptys on AIX.
+
+People often instll the pty devices on AIX incorrectly.
+Use `smit pty' to reinstall them properly.
+
+* Shell mode on HP/UX gives the message, "`tty`: Ambiguous".
+
+christos@theory.tn.cornell.edu says:
+
+The problem is that in your .cshrc you have something that tries to
+execute `tty`. If you are not running the shell on a real tty then
+tty will print "not a tty". Csh expects one word in some places,
+but tty is giving it back 3.
+
+The solution is to add a pair of quotes around `tty` to make it a single
+word:
+
+if (`tty` == "/dev/console")
+
+should be changed to:
+
+if ("`tty`" == "/dev/console")
+
+Even better, move things that set up terminal sections out of .cshrc
+and into .login.
+
+* Using X Windows, control-shift-leftbutton makes Emacs hang.
+
+Use the shell command `xset bc' to make the old X Menu package work.
+
+* Emacs running under X Windows does not handle mouse clicks.
+* `emacs -geometry 80x20' finds a file named `80x20'.
+
+One cause of such problems is having (setq term-file-prefix nil) in
+your .emacs file. Another cause is a bad value of EMACSLOADPATH in
+the environment.
+
+* Emacs gets error message from linker on Sun.
+
+If the error message says that a symbol such as `f68881_used' or
+`ffpa_used' or `start_float' is undefined, this probably indicates
+that you have compiled some libraries, such as the X libraries,
+with a floating point option other than the default.
+
+It's not terribly hard to make this work with small changes in
+crt0.c together with linking with Fcrt1.o, Wcrt1.o or Mcrt1.o.
+However, the easiest approach is to build Xlib with the default
+floating point option: to decide at run time what hardware is
+available.
+
+* Emacs fails to get default settings from X Windows server.
+
+The X library in X11R4 has a bug; it interchanges the 2nd and 3rd
+arguments to XGetDefaults. Define the macro XBACKWARDS in config.h to
+tell Emacs to compensate for this.
+
+I don't believe there is any way Emacs can determine for itself
+whether this problem is present on a given system.
+
+* Keyboard input gets confused after a beep when using a DECserver
+ as a concentrator.
+
+This problem seems to be a matter of configuring the DECserver to use
+7 bit characters rather than 8 bit characters.
+
+* M-x shell persistently reports "Process shell exited abnormally with code 1".
+
+This happened on Suns as a result of what is said to be a bug in Sunos
+version 4.0.x. The only fix was to reboot the machine.
+
+* Programs running under terminal emulator do not recognize `emacs'
+ terminal type.
+
+The cause of this is a shell startup file that sets the TERMCAP
+environment variable. The terminal emulator uses that variable to
+provide the information on the special terminal type that Emacs
+emulates.
+
+Rewrite your shell startup file so that it does not change TERMCAP
+in such a case. You could use the following conditional which sets
+it only if it is undefined.
+
+ if ( ! ${?TERMCAP} ) setenv TERMCAP ~/my-termcap-file
+
+Or you could set TERMCAP only when you set TERM--which should not
+happen in a non-login shell.
+
+* Error compiling sysdep.c, "sioctl.h: no such file or directory".
+
+Among USG systems with TIOCGWINSZ, some require sysdep.c to include
+the file sioctl.h; on others, sioctl.h does not exist. We don't know
+how to distinguish these two kind of systems, so currently we try to
+include sioctl.h on all of them. If this #include gets an error, just
+delete it.
+
+* X Windows doesn't work if DISPLAY uses a hostname.
+
+People have reported kernel bugs in certain systems that cause Emacs
+not to work with X Windows if DISPLAY is set using a host name. But
+the problem does not occur if DISPLAY is set to `unix:0.0'. I think
+the bug has to do with SIGIO or FIONREAD.
+
+You may be able to compensate for the bug by doing (set-input-mode nil nil).
+However, that has the disadvantage of turning off interrupts, so that
+you are unable to quit out of a Lisp program by typing C-g.
+
+The easy way to do this is to put
+
+ (setq x-sigio-bug t)
+
+in your site-init.el file.
+
+* Problem with remote X server on Suns.
+
+On a Sun, running Emacs on one machine with the X server on another
+may not work if you have used the unshared system libraries. This
+is because the unshared libraries fail to use YP for host name lookup.
+As a result, the host name you specify may not be recognized.
+
+* Watch out for .emacs files and EMACSLOADPATH environment vars
+
+These control the actions of Emacs.
+~/.emacs is your Emacs init file.
+EMACSLOADPATH overrides which directories the function
+"load" will search.
+
+If you observe strange problems, check for these and get rid
+of them, then try again.
+
+* Shell mode ignores interrupts on Apollo Domain
+
+You may find that M-x shell prints the following message:
+
+ Warning: no access to tty; thus no job control in this shell...
+
+This can happen if there are not enough ptys on your system.
+Here is how to make more of them.
+
+ % cd /dev
+ % ls pty*
+ # shows how many pty's you have. I had 8, named pty0 to pty7)
+ % /etc/crpty 8
+ # creates eight new pty's
+
+* Fatal signal in the command temacs -l loadup inc dump
+
+This command is the final stage of building Emacs. It is run by the
+Makefile in the src subdirectory, or by build.com on VMS.
+
+It has been known to get fatal errors due to insufficient swapping
+space available on the machine.
+
+On 68000's, it has also happened because of bugs in the
+subroutine `alloca'. Verify that `alloca' works right, even
+for large blocks (many pages).
+
+* test-distrib says that the distribution has been clobbered
+* or, temacs prints "Command key out of range 0-127"
+* or, temacs runs and dumps xemacs, but xemacs totally fails to work.
+* or, temacs gets errors dumping xemacs
+
+This can be because the .elc files have been garbled. Do not be
+fooled by the fact that most of a .elc file is text: these are
+binary files and can contain all 256 byte values.
+
+In particular `shar' cannot be used for transmitting GNU Emacs.
+It typically truncates "lines". What appear to be "lines" in
+a binary file can of course be of any length. Even once `shar'
+itself is made to work correctly, `sh' discards null characters
+when unpacking the shell archive.
+
+I have also seen character \177 changed into \377. I do not know
+what transfer means caused this problem. Various network
+file transfer programs are suspected of clobbering the high bit.
+
+The only verified ways to transfer GNU Emacs are `tar', kermit (in
+binary mode on Unix), and rcp or internet ftp between two Unix systems,
+or chaosnet cftp using raw mode.
+
+If you have a copy of Emacs that has been damaged in its
+nonprinting characters, you can fix them:
+
+ 1) Record the names of all the .elc files.
+ 2) Delete all the .elc files.
+ 3) Recompile alloc.c with a value of PURESIZE twice as large.
+ You might as well save the old alloc.o.
+ 4) Remake xemacs. It should work now.
+ 5) Running xemacs, do Meta-x byte-compile-file repeatedly
+ to recreate all the .elc files that used to exist.
+ You may need to increase the value of the variable
+ max-lisp-eval-depth to succeed in running the compiler interpreted
+ on certain .el files. 400 was sufficient as of last report.
+ 6) Reinstall the old alloc.o (undoing changes to alloc.c if any)
+ and remake temacs.
+ 7) Remake xemacs. It should work now, with valid .elc files.
+
+* temacs prints "Pure Lisp storage exhausted"
+
+This means that the Lisp code loaded from the .elc and .el
+files during temacs -l loadup inc dump took up more
+space than was allocated.
+
+This could be caused by
+ 1) adding code to the preloaded Lisp files
+ 2) adding more preloaded files in loadup.el
+ 3) having a site-init.el or site-load.el which loads files.
+ Note that ANY site-init.el or site-load.el is nonstandard;
+ if you have received Emacs from some other site
+ and it contains a site-init.el or site-load.el file, consider
+ deleting that file.
+ 4) getting the wrong .el or .elc files
+ (not from the directory you expected).
+ 5) deleting some .elc files that are supposed to exist.
+ This would cause the source files (.el files) to be
+ loaded instead. They take up more room, so you lose.
+ 6) a bug in the Emacs distribution which underestimates
+ the space required.
+
+If the need for more space is legitimate, change the definition
+of PURESIZE in config.h.
+
+But in some of the cases listed above, this problem is a consequence
+of something else that is wrong. Be sure to check and fix the real
+problem.
+
+* Changes made to .el files do not take effect.
+
+You may have forgotten to recompile them into .elc files.
+Then the old .elc files will be loaded, and your changes
+will not be seen. To fix this, do M-x byte-recompile-directory
+and specify the directory that contains the Lisp files.
+
+* The dumped Emacs (xemacs) crashes when run, trying to write pure data.
+
+Two causes have been seen for such problems.
+
+1) On a system where getpagesize is not a system call, it is defined
+as a macro. If the definition (in both unexec.c and malloc.c) is wrong,
+it can cause problems like this. You might be able to find the correct
+value in the man page for a.out (5).
+
+2) Some systems allocate variables declared static among the
+initialized variables. Emacs makes all initialized variables in most
+of its files pure after dumping, but the variables declared static and
+not initialized are not supposed to be pure. On these systems you
+may need to add "#define static" to the m- or the s- file.
+
+* Compilation errors on VMS.
+
+You will get warnings when compiling on VMS because there are
+variable names longer than 32 (or whatever it is) characters.
+This is not an error. Ignore it.
+
+VAX C does not support #if defined(foo). Uses of this construct
+were removed, but some may have crept back in. They must be rewritten.
+
+There is a bug in the C compiler which fails to sign extend characters
+in conditional expressions. The bug is:
+ char c = -1, d = 1;
+ int i;
+
+ i = d ? c : d;
+The result is i == 255; the fix is to typecast the char in the
+conditional expression as an (int). Known occurrences of such
+constructs in Emacs have been fixed.
+
+* rmail gets error getting new mail
+
+rmail gets new mail from /usr/spool/mail/$USER using a program
+called `movemail'. This program interlocks with /bin/mail using
+the protocol defined by /bin/mail.
+
+There are two different protocols in general use. One of them uses
+the `flock' system call. The other involves creating a lock file;
+`movemail' must be able to write in /usr/spool/mail in order to do
+this. You control which one is used by defining, or not defining,
+the macro MAIL_USE_FLOCK in config.h or the m- or s- file it includes.
+IF YOU DON'T USE THE FORM OF INTERLOCKING THAT IS NORMAL ON YOUR
+SYSTEM, YOU CAN LOSE MAIL!
+
+If your system uses the lock file protocol, and fascist restrictions
+prevent ordinary users from writing the lock files in /usr/spool/mail,
+you may need to make `movemail' setgid to a suitable group such as
+`mail'. You can use these commands (as root):
+
+ chgrp mail movemail
+ chmod 2755 movemail
+
+* Emacs won't work with X-windows if the value of DISPLAY is HOSTNAME:0.
+* GNUs can't make contact with the specified host for nntp.
+
+Some people have found that Emacs was unable to connect to the local
+host by name, as in DISPLAY=prep:0 if you are running on prep, but
+could handle DISPLAY=unix:0. Here is what tale@rpi.edu said:
+
+ Seems as
+ though gethostbyname was bombing somewhere along the way. Well, we
+ had just upgrade from SunOS 3.5 (which X11 was built under) to SunOS
+ 4.0.1. Any new X applications which tried to be built with the pre
+ OS-upgrade libraries had the same problems which Emacs was having.
+ Missing /etc/resolv.conf for a little while (when one of the libraries
+ was built?) also might have had a hand in it.
+
+ The result of all of this (with some speculation) was that we rebuilt
+ X and then rebuilt Emacs with the new libraries. Works as it should
+ now. Hoorah.
+
+If you have already installed the name resolver in the file libresolv.a,
+then you need to compile Emacs to use that library. The easiest way to
+do this is to add to config.h a definition of LIBS_SYSTEM, LIBS_MACHINE
+or LIB_STANDARD which uses -lresolv. Watch out! If you redefine a macro
+that is already in use in your configuration to supply some other libraries,
+be careful not to lose the others.
+
+Thus, you could start by adding this to config.h:
+
+#define LIBS_SYSTEM -lresolv
+
+Then if this gives you an error for redefining a macro, and you see that
+the s- file defines LIBS_SYSTEM as -lfoo -lbar, you could change config.h
+again to say this:
+
+#define LIBS_SYSTEM -lresolv -lfoo -lbar
+
+* Emacs spontaneously displays "I-search: " at the bottom of the screen.
+
+This means that Control-S/Control-Q "flow control" is being used.
+C-s/C-q flow control is bad for Emacs editors because it takes away
+C-s and C-q as user commands. Since editors do not output long streams
+of text without user commands, there is no need for a user-issuable
+"stop output" command in an editor; therefore, a properly designed
+flow control mechanism would transmit all possible input characters
+without interference. Designing such a mechanism is easy, for a person
+with at least half a brain.
+
+There are three possible reasons why flow control could be taking place:
+
+ 1) Terminal has not been told to disable flow control
+ 2) Insufficient padding for the terminal in use
+ 3) Some sort of terminal concentrator or line switch is responsible
+
+First of all, many terminals have a set-up mode which controls
+whether they generate flow control characters. This must be
+set to "no flow control" in order for Emacs to work. Sometimes
+there is an escape sequence that the computer can send to turn
+flow control off and on. If so, perhaps the termcap `ti' string
+should turn flow control off, and the `te' string should turn it on.
+
+Once the terminal has been told "no flow control", you may find it
+needs more padding. The amount of padding Emacs sends is controlled
+by the termcap entry for the terminal in use, and by the output baud
+rate as known by the kernel. The shell command `stty' will print
+your output baud rate; `stty' with suitable arguments will set it if
+it is wrong. Setting to a higher speed causes increased padding. If
+the results are wrong for the correct speed, there is probably a
+problem in the termcap entry. You must speak to a local Unix wizard
+to fix this. Perhaps you are just using the wrong terminal type.
+
+For terminals that lack a "no flow control" mode, sometimes just
+giving lots of padding will prevent actual generation of flow control
+codes. You might as well try it.
+
+If you are really unlucky, your terminal is connected to the computer
+through a concentrator which sends flow control to the computer, or it
+insists on sending flow control itself no matter how much padding you
+give it. You are screwed! You should replace the terminal or
+concentrator with a properly designed one. In the mean time,
+some drastic measures can make Emacs semi-work.
+
+One drastic measure to ignore C-s and C-q, while sending enough
+padding that the terminal will not really lose any output.
+Ignoring C-s and C-q can be done by using keyboard-translate-table
+to map them into an undefined character such as C-^ or C-\. Sending
+lots of padding is done by changing the termcap entry. Here is how
+to make such a keyboard-translate-table:
+
+ (let ((the-table (make-string 128 0)))
+ ;; Default is to translate each character into itself.
+ (let ((i 0))
+ (while (< i 128)
+ (aset the-table i i)
+ (setq i (1+ i))))
+ ;; Swap C-s with C-\
+ (aset the-table ?\C-\\ ?\C-s)
+ (aset the-table ?\C-s ?\C-\\)
+ ;; Swap C-q with C-^
+ (aset the-table ?\C-^ ?\C-q)
+ (aset the-table ?\C-q ?\C-^)
+ (setq keyboard-translate-table the-table))
+
+An even more drastic measure is to make Emacs use flow control.
+To do this, evaluate the Lisp expression (set-input-mode nil t).
+Emacs will then interpret C-s and C-q as flow control commands. (More
+precisely, it will allow the kernel to do so as it usually does.) You
+will lose the ability to use them for Emacs commands. Also, as a
+consequence of using CBREAK mode, the terminal's Meta-key, if any,
+will not work, and C-g will be liable to cause a loss of output which
+will produce garbage on the screen. (These problems apply to 4.2BSD;
+they may not happen in 4.3 or VMS, and I don't know what would happen
+in sysV.) You can use keyboard-translate-table, as shown above,
+to map two other input characters (such as C-^ and C-\) into C-s and
+C-q, so that you can still search and quote.
+
+I have no intention of ever redisigning the Emacs command set for
+the assumption that terminals use C-s/C-q flow control. This
+flow control technique is a bad design, and terminals that need
+it are bad merchandise and should not be purchased. If you can
+get some use out of GNU Emacs on inferior terminals, I am glad,
+but I will not make Emacs worse for properly designed systems
+for the sake of inferior systems.
+
+* Control-S and Control-Q commands are ignored completely.
+
+For some reason, your system is using brain-damaged C-s/C-q flow
+control despite Emacs's attempts to turn it off. Perhaps your
+terminal is connected to the computer through a concentrator
+that wants to use flow control.
+
+You should first try to tell the concentrator not to use flow control.
+If you succeed in this, try making the terminal work without
+flow control, as described in the preceding section.
+
+If that line of approach is not successful, map some other characters
+into C-s and C-q using keyboard-translate-table. The example above
+shows how to do this with C-^ and C-\.
+
+* Control-S and Control-Q commands are ignored completely on a net connection.
+
+Some versions of rlogin (and possibly telnet) do not pass flow
+control characters to the remote system to which they connect.
+On such systems, emacs on the remote system cannot disable flow
+control on the local system.
+
+One way to cure this is to disable flow control on the local host
+(the one running rlogin, not the one running rlogind) using the
+stty command, before starting the rlogin process. On many systems,
+"stty start u stop u" will do this.
+
+Some versions of tcsh will prevent even this from working. One way
+around this is to start another shell before starting rlogin, and
+issue the stty command to disable flow control from that shell.
+
+* Screen is updated wrong, but only on one kind of terminal.
+
+This could mean that the termcap entry you are using for that
+terminal is wrong, or it could mean that Emacs has a bug handing
+the combination of features specified for that terminal.
+
+The first step in tracking this down is to record what characters
+Emacs is sending to the terminal. Execute the Lisp expression
+(open-termscript "./emacs-script") to make Emacs write all
+terminal output into the file ~/emacs-script as well; then do
+what makes the screen update wrong, and look at the file
+and decode the characters using the manual for the terminal.
+There are several possibilities:
+
+1) The characters sent are correct, according to the terminal manual.
+
+In this case, there is no obvious bug in Emacs, and most likely you
+need more padding, or possibly the terminal manual is wrong.
+
+2) The characters sent are incorrect, due to an obscure aspect
+ of the terminal behavior not described in an obvious way
+ by termcap.
+
+This case is hard. It will be necessary to think of a way for
+Emacs to distinguish between terminals with this kind of behavior
+and other terminals that behave subtly differently but are
+classified the same by termcap; or else find an algorithm for
+Emacs to use that avoids the difference. Such changes must be
+tested on many kinds of terminals.
+
+3) The termcap entry is wrong.
+
+See the file etc/TERMS for information on changes
+that are known to be needed in commonly used termcap entries
+for certain terminals.
+
+4) The characters sent are incorrect, and clearly cannot be
+ right for any terminal with the termcap entry you were using.
+
+This is unambiguously an Emacs bug, and can probably be fixed
+in termcap.c, tparam.c, term.c, scroll.c, cm.c or dispnew.c.
+
+* Output from Control-V is slow.
+
+On many bit-map terminals, scrolling operations are fairly slow.
+Often the termcap entry for the type of terminal in use fails
+to inform Emacs of this. The two lines at the bottom of the screen
+before a Control-V command are supposed to appear at the top after
+the Control-V command. If Emacs thinks scrolling the lines is fast,
+it will scroll them to the top of the screen.
+
+If scrolling is slow but Emacs thinks it is fast, the usual reason is
+that the termcap entry for the terminal you are using does not
+specify any padding time for the `al' and `dl' strings. Emacs
+concludes that these operations take only as much time as it takes to
+send the commands at whatever line speed you are using. You must
+fix the termcap entry to specify, for the `al' and `dl', as much
+time as the operations really take.
+
+Currently Emacs thinks in terms of serial lines which send characters
+at a fixed rate, so that any operation which takes time for the
+terminal to execute must also be padded. With bit-map terminals
+operated across networks, often the network provides some sort of
+flow control so that padding is never needed no matter how slow
+an operation is. You must still specify a padding time if you want
+Emacs to realize that the operation takes a long time. This will
+cause padding characters to be sent unnecessarily, but they do
+not really cost much. They will be transmitted while the scrolling
+is happening and then discarded quickly by the terminal.
+
+Most bit-map terminals provide commands for inserting or deleting
+multiple lines at once. Define the `AL' and `DL' strings in the
+termcap entry to say how to do these things, and you will have
+fast output without wasted padding characters. These strings should
+each contain a single %-spec saying how to send the number of lines
+to be scrolled. These %-specs are like those in the termcap
+`cm' string.
+
+You should also define the `IC' and `DC' strings if your terminal
+has a command to insert or delete multiple characters. These
+take the number of positions to insert or delete as an argument.
+
+A `cs' string to set the scrolling region will reduce the amount
+of motion you see on the screen when part of the screen is scrolled.
+
+* Your Delete key sends a Backspace to the terminal, using an AIXterm.
+
+The solution is to include in your .Xdefaults the lines:
+
+ *aixterm.Translations: #override <Key>BackSpace: string(0x7f)
+ aixterm*ttyModes: erase ^?
+
+This makes your Backspace key send DEL (ASCII 127).
+
+* You type Control-H (Backspace) expecting to delete characters.
+
+Put `stty dec' in your .login file and your problems will disappear
+after a day or two.
+
+The choice of Backspace for erasure was based on confusion, caused by
+the fact that backspacing causes erasure (later, when you type another
+character) on most display terminals. But it is a mistake. Deletion
+of text is not the same thing as backspacing followed by failure to
+overprint. I do not wish to propagate this confusion by conforming
+to it.
+
+For this reason, I believe `stty dec' is the right mode to use,
+and I have designed Emacs to go with that. If there were a thousand
+other control characters, I would define Control-h to delete as well;
+but there are not very many other control characters, and I think
+that providing the most mnemonic possible Help character is more
+important than adapting to people who don't use `stty dec'.
+
+If you are obstinate about confusing buggy overprinting with deletion,
+you can redefine Backspace in your .emacs file:
+ (global-set-key "\b" 'delete-backward-char)
+You may then wish to put the function help-command on some
+other key. I leave to you the task of deciding which key.
+
+* Editing files through RFS gives spurious "file has changed" warnings.
+It is possible that a change in Emacs 18.37 gets around this problem,
+but in case not, here is a description of how to fix the RFS bug that
+causes it.
+
+ There was a serious pair of bugs in the handling of the fsync() system
+ call in the RFS server.
+
+ The first is that the fsync() call is handled as another name for the
+ close() system call (!!). It appears that fsync() is not used by very
+ many programs; Emacs version 18 does an fsync() before closing files
+ to make sure that the bits are on the disk.
+
+ This is fixed by the enclosed patch to the RFS server.
+
+ The second, more serious problem, is that fsync() is treated as a
+ non-blocking system call (i.e., it's implemented as a message that
+ gets sent to the remote system without waiting for a reply). Fsync is
+ a useful tool for building atomic file transactions. Implementing it
+ as a non-blocking RPC call (when the local call blocks until the sync
+ is done) is a bad idea; unfortunately, changing it will break the RFS
+ protocol. No fix was supplied for this problem.
+
+ (as always, your line numbers may vary)
+
+ % rcsdiff -c -r1.2 serversyscall.c
+ RCS file: RCS/serversyscall.c,v
+ retrieving revision 1.2
+ diff -c -r1.2 serversyscall.c
+ *** /tmp/,RCSt1003677 Wed Jan 28 15:15:02 1987
+ --- serversyscall.c Wed Jan 28 15:14:48 1987
+ ***************
+ *** 163,169 ****
+ /*
+ * No return sent for close or fsync!
+ */
+ ! if (syscall == RSYS_close || syscall == RSYS_fsync)
+ proc->p_returnval = deallocate_fd(proc, msg->m_args[0]);
+ else
+ {
+ --- 166,172 ----
+ /*
+ * No return sent for close or fsync!
+ */
+ ! if (syscall == RSYS_close)
+ proc->p_returnval = deallocate_fd(proc, msg->m_args[0]);
+ else
+ {
+
+* ld complains because `alloca' is not defined on your system.
+
+Alloca is a library function in 4.2bsd, which is used very heavily by
+GNU Emacs. Use of malloc instead is very difficult, as you would have
+to arrange for the storage to be freed, and do so even in the case of
+a longjmp happening inside a subroutine. Many subroutines in Emacs
+can do longjmp.
+
+If your system does not support alloca, try defining the symbol
+C_ALLOCA in the m-...h file for that machine. This will enable the use
+in Emacs of a portable simulation for alloca. But you will find that
+Emacs's performance and memory use improve if you write a true
+alloca in assembler language.
+
+alloca (N) should return the address of an N-byte block of memory
+added dynamically to the current stack frame.
+
+* Vax C compiler bugs affecting Emacs.
+
+You may get one of these problems compiling Emacs:
+
+ foo.c line nnn: compiler error: no table entry for op STASG
+ foo.c: fatal error in /lib/ccom
+
+These are due to bugs in the C compiler; the code is valid C.
+Unfortunately, the bugs are unpredictable: the same construct
+may compile properly or trigger one of these bugs, depending
+on what else is in the source file being compiled. Even changes
+in header files that should not affect the file being compiled
+can affect whether the bug happens. In addition, sometimes files
+that compile correctly on one machine get this bug on another machine.
+
+As a result, it is hard for me to make sure this bug will not affect
+you. I have attempted to find and alter these constructs, but more
+can always appear. However, I can tell you how to deal with it if it
+should happen. The bug comes from having an indexed reference to an
+array of Lisp_Objects, as an argument in a function call:
+ Lisp_Object *args;
+ ...
+ ... foo (5, args[i], ...)...
+putting the argument into a temporary variable first, as in
+ Lisp_Object *args;
+ Lisp_Object tem;
+ ...
+ tem = args[i];
+ ... foo (r, tem, ...)...
+causes the problem to go away.
+The `contents' field of a Lisp vector is an array of Lisp_Objects,
+so you may see the problem happening with indexed references to that.
+
+* 68000 C compiler problems
+
+Various 68000 compilers have different problems.
+These are some that have been observed.
+
+** Using value of assignment expression on union type loses.
+This means that x = y = z; or foo (x = z); does not work
+if x is of type Lisp_Object.
+
+** "cannot reclaim" error.
+
+This means that an expression is too complicated. You get the correct
+line number in the error message. The code must be rewritten with
+simpler expressions.
+
+** XCONS, XSTRING, etc macros produce incorrect code.
+
+If temacs fails to run at all, this may be the cause.
+Compile this test program and look at the assembler code:
+
+struct foo { char x; unsigned int y : 24; };
+
+lose (arg)
+ struct foo arg;
+{
+ test ((int *) arg.y);
+}
+
+If the code is incorrect, your compiler has this problem.
+In the XCONS, etc., macros in lisp.h you must replace (a).u.val with
+((a).u.val + coercedummy) where coercedummy is declared as int.
+
+This problem will not happen if the m-...h file for your type
+of machine defines NO_UNION_TYPE. That is the recommended setting now.
+
+* C compilers lose on returning unions
+
+I hear that some C compilers cannot handle returning
+a union type. Most of the functions in GNU Emacs return
+type Lisp_Object, which is currently defined as a union.
+
+This problem will not happen if the m-...h file for your type
+of machine defines NO_UNION_TYPE. That is the recommended setting now.
+
diff --git a/README b/README
new file mode 100644
index 00000000000..b0646c96ac3
--- /dev/null
+++ b/README
@@ -0,0 +1,42 @@
+This directory holds the latest distribution version of GNU Emacs.
+ The subdirectory `src' holds the C code,
+ `lisp' holds the Lisp code for the editing commands,
+ `etc' holds various associated documentation files
+ and programs that Emacs runs,
+ `info' holds the Info documentation tree.
+ `man' holds the source of the Emacs manual.
+ `cpp' holds a C preprocessor for use instead of the installed one
+ when the installed one fails to distinguish more than 8 characters
+ in a symbol name.
+ `shortnames' holds programs and data files for creating files of #define's
+ used to convert long symbol names to distinct short ones
+ for C compiles that cannot distinguish more than 8 characters.
+
+The file INSTALL in this directory says how to bring up
+ GNU Emacs on Unix, once you have loaded the entire subtree of this
+ directory.
+
+The files `build-install' and `Makefile' help automate the process of
+ building and installing emacs. The former is a shell script. See
+ INSTALL for more info.
+
+The file PROBLEMS contains information on many common
+ problems that occur in building, installing and running Emacs.
+
+The `etc' subdirectory contains several other files,
+ named in capital letters, which you should look at
+ when installing GNU Emacs.
+
+The file 'emacs.com' in this directory is for VMS. It defines
+ logical names and commands such as `emacs', so you must edit
+ it to specify the file and directory names used on your machine.
+ This file must be executed in each session to enable you to run
+ the installed Emacs. It should be executed by your `login.com' file,
+ or else perhaps it can be executed once at system boot time.
+
+The file `kepteditor.com' in this directory is also for VMS.
+ When a user says to run Emacs, it really runs this command file.
+
+See the files VMSINSTALL and VMSNOTES for more information on VMS use.
+
+
diff --git a/VMSINSTALL b/VMSINSTALL
new file mode 100644
index 00000000000..d71ef0aa3da
--- /dev/null
+++ b/VMSINSTALL
@@ -0,0 +1,129 @@
+* Installing GNU Emacs from a VMS install kit
+
+If you receive a VMS distribution tape containing an install kit, you
+can restore Emacs and run it immediately on any VMS system 4.2 or newer.
+The installation command file will automatically rename certain files
+whose names must vary according to the version of VMS in use.
+
+However, it is not certain we will have the install kit developed
+soon, so until that is done, you may receive an ordinary BACKUP
+saveset instead.
+
+* Installing GNU Emacs from an ordinary VMS BACKUP saveset
+
+If you receive a VMS distribution tape in VMS BACKUP interchange
+format you can restore Emacs and run it on VMS versions 4.2 or newer
+after executing a few commands. What you must do depends on the
+VMS version (one procedure for VMS 4.2 or 4.3; another procedure
+for newer VMS versions).
+
+For VMS versions 4.4 and up, make sure the file
+SYS$SYSTEM:RIGHTSLIST.DAT has WORLD:R access. Emacs reads this file
+to check file access.
+
+In order to compile Emacs with the VMS C compiler, you will need a
+pagefile quota of around 22000 pages, plus enough swap space to handle
+that. (This was in VMS 5.1-1, with 5 meg of physical memory.) See
+HELP SYSGEN CREATE and HELP SYSGEN INSTALL for more information.
+
+Choose a directory to restore to, say DEV:[LIB]. Do:
+
+ $ mount/foreign mta0:
+ $ backup/log mta0: dev:[lib...]
+
+Now, if you are using VMS version 4.4 or later, set your default to
+the directory DEV:[LIB.EMACS] and run the command file
+DEV:[LIB.EMACS]ALLRENAME.COM:
+
+ $ set default dev:[lib.emacs]
+ $ @allrename [...] "_" "-"
+
+This renames all files in the Emacs distribution from their old-VMS
+names (containing `_' characters) to their new-VMS names (containing
+`-' instead).
+
+Now, edit DEV:[LIB.EMACS]EMACS.COM. Replace the definition of
+EMACS_LIBRARY with the appropriate device and directory. The
+definition initially reads as follows:
+
+ $ define /translation=concealed emacs_library sys$device:[emacs.]
+
+You would replace this with:
+
+ $ define /translation=concealed emacs_library dev:[lib.emacs.]
+
+Now execute the command file DEV:[LIB.EMACS]EMACS.COM. This defines
+a command EMACS that runs a suspendable permanent Emacs. To
+fully install Emacs, you must arrange for users to run this file
+on login, or arrange for this file to be run when the system boots.
+
+The distribution contains an Emacs executable in
+DEV:[LIB.EMACS]EMACS.EXE. It uses DEV:[LIB.EMACS]EMACS.DUMP every time
+it runs. The EMACS.EXE has been linked with the non-sharable C
+library, so it should run on any VMS V4.4+ system, whether or not the
+C compiler exists. The .OBJ files are all there, so you can relink
+with /debug if you want to have fun.
+
+A few C source files contain compilation conditionals that depend
+on the version of VMS. We have compiled these files specially for
+VMS version 4.2 (or 4.3) in object files with extension .JBO.
+So to run on VMS 4.2, rename all the .JBO files to .OBJ, then
+link and build Emacs as described in DEV:[LIB.EMACS.SRC]VMSBUILD.
+
+ $ set def [.src]
+ $ rename *.jbo *.obj
+ $ @precomp
+ $ @link
+ $ @build
+ $ rename temacs.exe [-]emacs.exe
+ $ rename temacs.dump [-]emacs.dump
+
+To be clean, you should also edit the file [.SRC]CONFIG.H to #include
+the file S_VMS4_2.H. Then the proper conditionals will be activated
+if you ever recompile.
+
+* Moving a Unix distribution to VMS.
+
+Moving a Unix distribution to VMS is mostly a matter of transferring
+the files to the VMS system, but with old versions of VMS (prior to
+4.4) it is a little more complicated because some of the file names
+used on Unix are not supported by VMS. Every `-' in a Unix file name
+must be changed to a `_' on VMS. (In VMS versions 4.4 and up, this is
+not necessary, since `-' is allowed in file names.)
+
+A few other changes must be made regardless of the version of VMS:
+
+1) Copy the file [.SRC]VMSPATHS.H to [.SRC]PATHS.H, replacing any existing
+file PATHS.H in that directory.
+
+2) Delete any file [.SRC]CONFIG.H and replace it with a copy of
+CONFIG.H-DIST. Then edit this file so it specifies `m-vax.h' as the
+second include file and for the first include file one of
+`s-vms4-0.h', `s-vms4-2.h', `s-vms4-4.h' or `s-vms5-5.h'. (Use the
+highest version not greater than the VMS version you are running. For
+VMS versions prior to 4.4, the `-' characters must be replaced with
+`_'.)
+
+You can now compile, link, build and install Emacs as described in
+[.SRC]VMSBUILD..
+
+* Moving a VMS distribution to Unix.
+
+Delete all .OBJ files, and PATHS.H and CONFIG.H. Then copy the
+remaining files, changing each `_' in a file name to `-`. Unix will
+allow filenames with `_' but Emacs will not work with them!
+
+Names which on VMS end in a period (have a null extension) should
+have no period on Unix. Thus, "YMAKEFILE." becomes "ymakefile".
+
+VMS file names are case-insensitive. On Unix, case is significant.
+Most of the file names must be in lower case or they will not work.
+There are only a few exceptions:
+
+1) CHANGELOG. becomes ChangeLog
+2) MAKEFILE. becomes Makefile
+3) TAGS. becomes TAGS
+4) Files of English text with null extensions keep their names
+ in upper case. For example, README. becomes README and
+ [.ETC]GNU. becomes GNU
+
diff --git a/VMSNOTES b/VMSNOTES
new file mode 100644
index 00000000000..ad7cbd780c3
--- /dev/null
+++ b/VMSNOTES
@@ -0,0 +1,70 @@
+See the file VMSINSTALL for VMS installation information.
+
+* Deficiencies of VMS GNU Emacs
+
+All GNU Emacs features which on Unix work by running a Unix utility
+in a subprocess currently do not work on VMS.
+
+These include reading and sending mail, reading and posting netnews,
+spelling correction, displaying the time and load in the mode line,
+and the `sort-columns' command. (dired and sending output to printers
+don't work in version 18, but will in version 19.) Naturally, the
+commands to view Unix manual pages and execute Unix shell commands
+also do not work.
+
+It is not possible to fix these problems in a general way on VMS
+because they involve interfaces to parts of the operating system which
+work very differently on VMS. Each feature must be reimplemented
+individually.
+
+I hope that someone will send me an implementation for directory listing
+on VMS. This should not be very hard to do. Most of the code you need
+is already provided in [.src]dired.c.
+
+The normal commands for running an inferior shell or lisp with I/O
+through an Emacs buffer do not work on VMS in Emacs version 18, but
+will work in version 19. For the meanwhile, you can create a DCL
+subprocess which does I/O through an Emacs buffer and get a similar
+effect. See the file [.lisp]vms-patch.el.
+
+* Specifying terminal type.
+
+To specify a terminal type for Emacs that is not known to VMS,
+define the logical name EMACS_TERM with the terminal type as value.
+Terminal types are looked up in the termcap data base, which is
+found as the file `[etc]termcap.dat' in the Emacs distribution.
+
+* Specifying file names.
+
+GNU Emacs accepts both Unix and VMS file name syntax. Most Lisp
+code that runs in Emacs uses Unix syntax so it can run everywhere.
+Users on VMS will generally type file names with VMS syntax.
+
+The EMACSLOADPATH logical name, if you use it, should contain
+directory names in Unix syntax, separated by commas.
+
+find-file prompts with the current directory. You can then type a
+relative directory spec to get somewhere else in the hirearchy. For
+instance:
+
+Find File: emacs_library:[src][-.lisp]startup.el
+
+is converted to emacs_library:[lisp]startup.el by
+expand-file-name. The basic rule is:
+][- is treated like /.. (dir:[file.sub][-.other] ==> dir:[file.other],
+ dir:[file.sub][-] ==> dir:[file])
+][. elides the ][ (dir:[file][.sub] ==> dir:[file.sub])
+][alpha backs up to the previous [ (dir:[file][other] ==> dir:[other])
+a colon appearing after a ] forces a new "root" disk.
+ (dev:[file]dev2:[other] ==> dev2:[other])
+expand-file-name also tries to be smart about decnet node names,
+but this is not yet known to work.
+
+* A possible problem.
+
+For VMS versions 4.4 and up, make sure the file
+SYS$SYSTEM:RIGHTSLIST.DAT has WORLD:R access. Emacs reads this file
+to check file access. If this file does not have appropriate access,
+Emacs may think that you cannot write any files.
+
+
diff --git a/allrename.com b/allrename.com
new file mode 100644
index 00000000000..554a2ea6a28
--- /dev/null
+++ b/allrename.com
@@ -0,0 +1,39 @@
+$! Command file to rename many files at once
+$! performing a global string substitution on each name.
+$!Example:
+$! @allrename [...] "-" "_"
+$!changes each `-' in a name into a `_'.
+$!
+$!The device and directory names are not altered.
+$!
+$ p2_length = f$length (p2)
+$ p3_length = f$length (p3)
+$
+$file_loop:
+$ full_name = f$search("''p1'*.*;*")
+$ if ("''full_name'" .eqs. "") then goto done
+$ original_device = f$parse("''full_name'",,,"DEVICE")
+$ original_dir = f$parse("''full_name'",,,"DIRECTORY")
+$ original_file_name = f$parse("''full_name'",,,"NAME")
+$ original_file_type = f$parse("''full_name'",,,"TYPE")
+$ original_file_version = f$parse("''full_name'",,,"VERSION")
+$ original_file = original_file_name -
+ + original_file_type + original_file_version
+$ new_file = original_file
+$ something_done = "false"
+$name_loop:
+$ max_length = f$length(new_file)
+$ index = f$locate("''p2'", new_file)
+$ if (index .ge. max_length) then goto end_of_name
+$ something_done = "true"
+$ new_file = f$extract (0,index,new_file) + p3 -
+ + f$extract(index+p2_length,max_length-index,new_file)
+$ goto name_loop
+$end_of_name:
+$ original_file = original_device + original_dir + original_file
+$ new_file = original_device + original_dir + new_file
+$ if (something_done) then -
+ rename 'original_file' 'new_file'
+$ goto file_loop
+$done:
+$ exit
diff --git a/build-install b/build-install
new file mode 100755
index 00000000000..da469684d99
--- /dev/null
+++ b/build-install
@@ -0,0 +1,38 @@
+#!/bin/sh
+# Shell script for building and installing Emacs.
+# This is an alternative to `make install',
+# and it still exists just because it always has.
+set -x
+
+EMACS=/usr/local/emacs
+BIN=/usr/local/bin
+
+/bin/sed "s;/usr/local/emacs;$EMACS;" < src/paths.h-dist > src/paths.h
+
+(cd etc; make) || exit 1
+(cd src; make) || exit 1
+
+# The double quotes prevent an error from sh on Suns
+# when the directory does not exist yet.
+# We use sh -c pwd instead of just pwd because on some systems (Suns?)
+# plan pwd tends to give back the specified name sometimes.
+if [ `sh -c pwd` != "`(cd $EMACS; sh -c pwd)`" ]
+then
+ mv `pwd` $EMACS
+ if [ $? != '0' ]
+ then
+ mkdir $EMACS
+ echo mv `pwd` to $EMACS failed--using tar to copy.
+ tar cf - . | (cd $EMACS; umask 0; tar xf -)
+ if [ $? != '0' ]
+ then
+ echo tar-copying `pwd` to $EMACS failed.
+ exit 1
+ fi
+ fi
+fi
+
+cp $EMACS/etc/[ce]tags $BIN
+cp $EMACS/etc/emacsclient $BIN
+mv $EMACS/src/xemacs $BIN/emacs
+rm $EMACS/src/temacs
diff --git a/cpp/Makefile b/cpp/Makefile
new file mode 100644
index 00000000000..38385a72809
--- /dev/null
+++ b/cpp/Makefile
@@ -0,0 +1,20 @@
+# Makefile for cccp in the Emacs distribution only.
+# Here we assume that you are using sys V.0
+# (since cccp is used by Emacs only to deal with shortnames lossage).
+# Therefore, we add -DEMACS to CFLAGS and add -lPW to linking.
+
+CFLAGS=-g -I. -DEMACS
+cpp: cccp
+ -rm cpp
+ ln cccp cpp
+cccp: cccp.o y.tab.o
+ cc -o cccp -g cccp.o y.tab.o -lPW
+testexp: y.tab.c
+ cc -g -DTEST_EXP_READER y.tab.c -o testexp
+y.tab.c: cexp.y
+ echo expect 40 shift/reduce conflicts
+ yacc cexp.y
+cccp.o: cccp.c
+y.tab.o: y.tab.c
+lint: y.tab.c
+ lint -p y.tab.c cccp.c
diff --git a/cpp/cccp.c b/cpp/cccp.c
new file mode 100644
index 00000000000..11b4b4759d4
--- /dev/null
+++ b/cpp/cccp.c
@@ -0,0 +1,2483 @@
+/* C Compatible Compiler Preprocessor (CCCP)
+Copyright (C) 1986, Free Software Foundation, Inc.
+ Written by Paul Rubin, June 1986
+
+ NO WARRANTY
+
+ BECAUSE THIS PROGRAM IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY
+NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT
+WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC,
+RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE THIS PROGRAM "AS IS"
+WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY
+AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE
+DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
+CORRECTION.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M.
+STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY
+WHO MAY MODIFY AND REDISTRIBUTE THIS PROGRAM AS PERMITTED BELOW, BE
+LIABLE TO YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR
+OTHER SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR
+DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR
+A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) THIS
+PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY.
+
+ GENERAL PUBLIC LICENSE TO COPY
+
+ 1. You may copy and distribute verbatim copies of this source file
+as you receive it, in any medium, provided that you conspicuously
+and appropriately publish on each copy a valid copyright notice
+"Copyright (C) 1986 Free Software Foundation"; and include
+following the copyright notice a verbatim copy of the above disclaimer
+of warranty and of this License.
+
+ 2. You may modify your copy or copies of this source file or
+any portion of it, and copy and distribute such modifications under
+the terms of Paragraph 1 above, provided that you also do the following:
+
+ a) cause the modified files to carry prominent notices stating
+ that you changed the files and the date of any change; and
+
+ b) cause the whole of any work that you distribute or publish,
+ that in whole or in part contains or is a derivative of this
+ program or any part thereof, to be licensed at no charge to all
+ third parties on terms identical to those contained in this
+ License Agreement (except that you may choose to grant more extensive
+ warranty protection to some or all third parties, at your option).
+
+ c) You may charge a distribution fee for the physical act of
+ transferring a copy, and you may at your option offer warranty
+ protection in exchange for a fee.
+
+Mere aggregation of another unrelated program with this program (or its
+derivative) on a volume of a storage or distribution medium does not bring
+the other program under the scope of these terms.
+
+ 3. You may copy and distribute this program (or a portion or derivative
+of it, under Paragraph 2) in object code or executable form under the terms
+of Paragraphs 1 and 2 above provided that you also do one of the following:
+
+ a) accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of
+ Paragraphs 1 and 2 above; or,
+
+ b) accompany it with a written offer, valid for at least three
+ years, to give any third party free (except for a nominal
+ shipping charge) a complete machine-readable copy of the
+ corresponding source code, to be distributed under the terms of
+ Paragraphs 1 and 2 above; or,
+
+ c) accompany it with the information you received as to where the
+ corresponding source code may be obtained. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form alone.)
+
+For an executable file, complete source code means all the source code for
+all modules it contains; but, as a special exception, it need not include
+source code for modules which are standard libraries that accompany the
+operating system on which the executable file runs.
+
+ 4. You may not copy, sublicense, distribute or transfer this program
+except as expressly provided under this License Agreement. Any attempt
+otherwise to copy, sublicense, distribute or transfer this program is void and
+your rights to use the program under this License agreement shall be
+automatically terminated. However, parties who have received computer
+software programs from you with this License Agreement will not have
+their licenses terminated so long as such parties remain in full compliance.
+
+ In other words, you are welcome to use, share and improve this program.
+ You are forbidden to forbid anyone else to use, share and improve
+ what you give them. Help stamp out software-hoarding! */
+
+typedef unsigned char U_CHAR;
+
+#ifdef EMACS
+#define NO_SHORTNAMES
+#include "../src/config.h"
+#ifdef static
+#undef static
+#endif
+#ifdef open
+#undef open
+#undef close
+#undef read
+#undef write
+#endif /* open */
+#endif /* EMACS */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <ctype.h>
+#include <stdio.h>
+#ifndef USG
+#include <sys/time.h> /* for __DATE__ and __TIME__ */
+#else
+#define index strchr
+#define rindex strrchr
+#include <time.h>
+#include <fcntl.h>
+#endif /* USG */
+
+void bcopy (), bzero ();
+int bcmp ();
+
+char *xmalloc (), *xrealloc (), *xcalloc ();
+void fatal (), pfatal_with_name (), perror_with_name ();
+
+char *progname;
+
+#define FATAL_EXIT_CODE 33 /* gnu cc command understands this */
+
+struct directory_stack
+ {
+ struct directory_stack *next;
+ char *fname;
+ };
+
+/* #include "file" starts with the first entry in the stack */
+/* #include <file> starts with the second. */
+/* -I directories are added after the first */
+struct directory_stack default_includes[2] =
+ {
+ { &default_includes[1], "." },
+ { 0, "/usr/include" }
+ };
+struct directory_stack *include = &default_includes[0];
+
+int max_include_len = 14; /* strlen (default_include) + 2
+ (for / and null) */
+
+char STDIN_FILE[] = ""; /* Empty, like real cpp */
+int put_out_comments = 0; /* JF non-zero means leave comments in the
+ output file. Used by lint */
+
+/* table to tell if char can be part of a C identifier. */
+U_CHAR is_idchar[256];
+/* table to tell if char can be first char of a c identifier. */
+U_CHAR is_idstart[256];
+/* table to tell if c is horizontal space. isspace() thinks that
+ newline is space; this is not a good idea for this program. */
+U_CHAR is_hor_space[256];
+
+/* I/O buffer structure. Ought to be used for the output file too.
+ These are also used when there is no file present, for example,
+ when rescanning a definition. Then, the fname field is null. */
+#define INPUT_STACK_MAX 100
+struct file_buf {
+ struct infile *next; /* for making stacks of file ptrs */
+ char *fname;
+ int lineno;
+ int length;
+ U_CHAR *buf;
+ U_CHAR *bufp;
+} instack[INPUT_STACK_MAX];
+int indepth = 0;
+
+typedef struct file_buf FILE_BUF;
+
+/* The output buffer. Its LENGTH field is the amount of room allocated
+ for the buffer, not the number of chars actually present. To get
+ that, subtract outbuf.buf from outbuf.bufp. */
+
+#define OUTBUF_SIZE 10 /* initial size of output buffer */
+FILE_BUF outbuf;
+
+/* Structure allocated for every #define. For a simple replacement
+ such as
+ #define foo bar ,
+ nargs = -1, the `pattern' list is null, and the expansion is just
+ the replacement text. Nargs = 0 means a real macro with no args,
+ e.g.,
+ #define getchar() getc(stdin) .
+ When there are args, the expansion is the replacement text with the
+ args squashed out, and the reflist is a list describing how to
+ build the output from the input: e.g., "3 chars, then the 1st arg,
+ then 9 chars, then the 3rd arg, then 0 chars, then the 2nd arg".
+ The chars here come from the expansion. Thus, for any definition
+ d , strlen(d->expansion) should equal the sum of all the
+ d->pattern->nchars. Note that the list can be arbitrarily long---
+ its length depends on the number of times the arguements appear in
+ the replacement text, not how many args there are. Example:
+ #define f(x) x+x+x+x+x+x+x would have replacement text "++++++" and
+ pattern list
+ { (0, 1), (1, 1), (1, 1), ..., (1, 1), NULL }
+ where (x, y) means (nchars, argno). */
+
+typedef struct definition DEFINITION;
+struct definition {
+ int nargs;
+ int length; /* length of expansion string */
+ U_CHAR *expansion;
+ struct reflist {
+ struct reflist *next;
+ int nchars;
+ int argno;
+ } *pattern;
+};
+
+/* different kinds of things that can appear in the value field
+ of a hash node. Actually, this may be useless now. */
+union hashval {
+ int ival;
+ char *cpval;
+ DEFINITION *defn;
+};
+
+
+/* The structure of a node in the hash table. The hash table
+ has entries for all tokens defined by #define commands (type T_MACRO),
+ plus some special tokens like __LINE__ (these each have their own
+ type, and the appropriate code is run when that type of node is seen.
+ It does not contain control words like "#define", which are recognized
+ by a separate piece of code. */
+typedef struct hashnode HASHNODE;
+struct hashnode {
+ HASHNODE *next; /* double links for easy deletion */
+ HASHNODE *prev;
+ HASHNODE **bucket_hdr; /* also, a back pointer to this node's hash
+ chain is kept, in case the node is the head
+ of the chain and gets deleted. */
+ int type; /* type of special token */
+ int length; /* length of token, for quick comparison */
+ U_CHAR *name; /* the actual name */
+ union hashval value; /* pointer to expansion, or whatever */
+};
+
+
+HASHNODE *install();
+/* different flavors of hash nodes --- also used in keyword table */
+#define T_DEFINE 1 /* the "#define" keyword */
+#define T_INCLUDE 2 /* the "#include" keyword */
+#define T_IFDEF 3 /* the "#ifdef" keyword */
+#define T_IF 4 /* the "#if" keyword */
+#define T_EXPAND 5 /* argument to be expanded (now unused) */
+#define T_MACRO 6 /* macro defined by "#define" */
+#define T_ELSE 7 /* "#else" */
+#define T_PRAGMA 8 /* "#pragma" */
+#define T_ELIF 9 /* "#else" */
+#define T_UNDEF 10 /* "#undef" */
+#define T_LINE 11 /* "#line" */
+#define T_ERROR 12 /* "#error" */
+#define T_IFNDEF 13 /* "#ifndef"; forgot this earlier */
+#define T_ENDIF 14 /* "#endif" */
+#define T_SPECLINE 15 /* special symbol "__LINE__" */
+#define T_DATE 16 /* "__DATE__" */
+#define T_FILE 17 /* "__FILE__" */
+#define T_TIME 18 /* "__TIME__" */
+
+#define T_SPEC_DEFINED 19 /* special macro for use in #if statements */
+
+
+
+/* some more different types will be needed --- no longer bloody likely */
+
+
+int do_define(), do_line(), do_include(), do_undef(), do_error(),
+ do_pragma(), do_if(), do_xifdef(), do_else(),
+ do_elif(), do_endif();
+
+
+/* table of control words, along with code to execute when the keyword
+ is seen. For now, it is searched linearly, so put the most frequently
+ found keywords at the beginning of the list. */
+
+struct keyword_table {
+ int length;
+ int (*func)();
+ char *name;
+ int type;
+} keyword_table[] = {
+ { 6, do_define, "define", T_DEFINE},
+ { 4, do_line, "line", T_LINE},
+ { 7, do_include, "include", T_INCLUDE},
+ { 5, do_undef, "undef", T_UNDEF},
+ { 5, do_error, "error", T_ERROR},
+ { 2, do_if, "if", T_IF},
+ { 5, do_xifdef, "ifdef", T_IFDEF},
+ { 6, do_xifdef, "ifndef", T_IFNDEF},
+ { 4, do_else, "else", T_ELSE},
+ { 4, do_elif, "elif", T_ELIF},
+ { 5, do_endif, "endif", T_ENDIF},
+ { 6, do_pragma, "pragma", T_PRAGMA},
+ { -1, 0, "", -1},
+};
+
+/* Some definitions for the hash table. The hash function MUST be
+ computed as shown in hashf() below. That is because the rescan
+ loop computes the hash value `on the fly' for most tokens,
+ in order to avoid the overhead of a lot of procedure calls to
+ the hashf() function. Hashf() only exists for the sake of
+ politeness, for use when speed isn't so important. */
+
+#define HASHSIZE 1009
+HASHNODE *hashtab[HASHSIZE];
+#define HASHSTEP(old, c) ((old << 1) + c)
+#define MAKE_POS(v) (v & ~0x80000000) /* make number positive */
+
+#define SKIP_WHITE_SPACE(p) { while (is_hor_space[*p]) p++; }
+
+
+
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ struct stat sbuf;
+ char *in_fname, *out_fname;
+ int out_fd = 1; /* default to stdout */
+ int f, i;
+ FILE_BUF *fp;
+
+ progname = argv[0];
+ in_fname = NULL;
+ out_fname = NULL;
+ initialize_random_junk ();
+
+ fp = &instack[indepth++];
+
+/* if (argc < 2) JF no args means work as filter
+ return FATAL_EXIT_CODE; */
+
+ for (i = 1; i < argc; i++) {
+ if (argv[i][0] != '-') {
+ if (out_fname != NULL)
+ fatal ("Usage: %s [switches] input output\n", argv[0]);
+ else if (in_fname != NULL) {
+ out_fname = argv[i];
+ if ((out_fd = creat (out_fname, 0666)) < 0)
+ pfatal_with_name (out_fname);
+ } else
+ in_fname = argv[i];
+ } else {
+ switch (argv[i][1]) {
+ U_CHAR *p;
+ struct directory_stack *dirtmp;
+ case 'D':
+ if ((p = (U_CHAR *) index(argv[i]+2, '=')) != NULL)
+ *p = ' ';
+ make_definition (argv[i] + 2);
+ break;
+ case 'U': /* JF #undef something */
+ make_undef(argv[i] + 2);
+ break;
+ case 'C': /* JF do later -C means leave comments alone! */
+ put_out_comments++;
+ break;
+ case 'E': /* -E comes from cc -E; ignore it. */
+ break;
+ case 'M': /* Makefile dependencies or something like
+ that. Not implimented yet */
+ break;
+ case 'I': /* JF handle directory path right */
+ dirtmp = (struct directory_stack *)
+ xmalloc (sizeof (struct directory_stack));
+ dirtmp->next = include->next;
+ include->next = dirtmp;
+ dirtmp->fname = argv[i]+2;
+ include = dirtmp;
+ if (strlen (argv[i]) > max_include_len)
+ max_include_len = strlen (argv[i]);
+ break;
+
+ case '\0': /* JF handle '-' as file name meaning stdin or stdout */
+ if (in_fname == NULL) {
+ in_fname = STDIN_FILE;
+ break;
+ } else if (out_fname == NULL) {
+ out_fname = "stdout";
+ break;
+ } /* else fall through into error */
+
+ default:
+ fatal ("Illegal option %s\n", argv[i]);
+ }
+ }
+ }
+
+ /* JF check for stdin */
+ if (in_fname == STDIN_FILE || in_fname == NULL)
+ f = 0;
+ else if ((f = open (in_fname, O_RDONLY)) < 0)
+ goto perror;
+
+ fstat (f, &sbuf);
+ fp->fname = in_fname;
+ fp->lineno = 1;
+ /* JF all this is mine about reading pipes and ttys */
+ if ((sbuf.st_mode & S_IFMT) != S_IFREG) {
+ int size;
+ int bsize;
+ int cnt;
+ U_CHAR *bufp;
+
+ bsize = 2000;
+ size = 0;
+ fp->buf = (U_CHAR *) xmalloc (bsize + 1);
+ bufp = fp->buf;
+ for (;;) {
+ cnt = read (f, bufp, bsize - size);
+ if (cnt < 0) goto perror; /* error! */
+ if (cnt == 0) break; /* End of file */
+ size += cnt;
+ bufp += cnt;
+ if (bsize-size == 0) { /* Buffer is full! */
+ bsize *= 2;
+ fp->buf = (U_CHAR *) xrealloc (fp->buf, bsize + 1);
+ bufp = fp->buf + size; /* May have moved */
+ }
+ }
+ fp->buf[size] = '\0';
+ fp->length = size;
+ } else {
+ fp->length = sbuf.st_size;
+ fp->buf = (U_CHAR *) alloca (sbuf.st_size + 1);
+
+ if (read (f, fp->buf, sbuf.st_size) != sbuf.st_size)
+ goto perror;
+
+ fp->buf[sbuf.st_size] = '\0';
+ }
+
+ /* initialize output buffer */
+ outbuf.buf = (U_CHAR *) xmalloc (OUTBUF_SIZE);
+ outbuf.bufp = outbuf.buf;
+ outbuf.length = OUTBUF_SIZE;
+
+ output_line_command (fp, &outbuf);
+ rescan (fp, &outbuf);
+
+ /* do something different than this later */
+ fflush (stdout);
+ write (out_fd, outbuf.buf, outbuf.bufp - outbuf.buf);
+ exit (0);
+
+ perror:
+ pfatal_with_name (argv[1]);
+}
+
+/*
+ * The main loop of the program. Try to examine and move past most
+ * ordinary input chars as fast as possible. Call appropriate routines
+ * when something special (such as a macro expansion) has to happen.
+
+IP is the source of input to scan.
+OP is the place to put input. */
+
+rescan (ip, op)
+ FILE_BUF *ip, *op;
+{
+ register int c;
+ register int ident_length = 0, hash = 0;
+ register U_CHAR *limit;
+ U_CHAR *check_expand ();
+ struct keyword_table *handle_directive ();
+ int excess_newlines = 0;
+ int escaped = 0;
+
+ U_CHAR *bp;
+
+ check_expand(op, ip->length);
+
+ ip->bufp = ip->buf;
+ limit = ip->buf + ip->length;
+ while (1) {
+ if (ip->bufp < limit) {
+ c = *ip->bufp++;
+ *op->bufp++ = c;
+ } else {
+ c = -1;
+ }
+
+ --escaped;
+ /* Now ESCAPED is 0 if and only if this character is escaped. */
+
+ switch (c) {
+ case '\\':
+ if (escaped == 0)
+ goto randomchar;
+ if (*ip->bufp != '\n')
+ {
+ escaped = 1;
+ goto randomchar;
+ }
+ /* always merge lines ending with backslash-newline */
+ ++ip->bufp;
+ ++ip->lineno;
+ ++excess_newlines;
+ --op->bufp; /* remove backslash from obuf */
+ continue; /* back to top of while loop */
+
+ case '#':
+ /* # keyword: a # must be first nonblank char on the line */
+ for (bp = ip->bufp - 1; bp >= ip->buf; bp--)
+ if (*bp == '\n')
+ break;
+ bp++; /* skip nl or move back into buffer */
+ SKIP_WHITE_SPACE (bp);
+ if (*bp != '#')
+ goto randomchar;
+ ident_length = hash = 0;
+ --op->bufp; /* don't copy the '#' */
+
+ if (handle_directive (ip, op, &excess_newlines) == NULL) {
+ ++op->bufp; /* copy the '#' after all */
+ goto randomchar;
+ }
+ break;
+
+ case '\"': /* skip quoted string */
+ case '\'':
+ /* a single quoted string is treated like a double -- some
+ programs (e.g., troff) are perverse this way */
+
+ if (escaped == 0)
+ goto randomchar; /* false alarm-- it's escaped. */
+
+ /* skip ahead to a matching quote. */
+
+ bp = ip->bufp;
+ while (bp < limit) {
+ *op->bufp++ = *bp;
+ switch (*bp++) {
+ case '\n':
+ ++ip->lineno;
+ break;
+ case '\\':
+ if (bp >= limit)
+ break;
+ if (*bp == '\n')
+ {
+ /* backslash newline is replaced by nothing at all,
+ but remember that the source line count is out of synch. */
+ --op->bufp;
+ ++bp;
+ ++excess_newlines;
+ ++ip->lineno;
+ }
+ else
+ *op->bufp++ = *bp++;
+ break;
+ case '\"':
+ case '\'':
+ if (bp[-1] == c)
+ goto while2end;
+ break;
+ }
+ }
+ while2end:
+ ip->bufp = bp;
+ break;
+
+ case '/': /* possible comment */
+ if (*ip->bufp != '*')
+ goto randomchar;
+ if (put_out_comments) {
+ bp = ip->bufp;
+ *op->bufp++ = *bp++;
+ } else {
+ bp = ip->bufp + 1;
+ --op->bufp; /* don't leave initial slash in buffer */
+ }
+
+ for (;;) {
+ while (bp < limit) {
+ if (put_out_comments)
+ *op->bufp++ = *bp;
+ switch (*bp++) {
+ case '*':
+ goto whileend;
+ case '\n':
+ /* copy the newline into the output buffer, in order to
+ avoid the pain of a #line every time a multiline comment
+ is seen. This means keywords with embedded comments
+ that contain newlines (blucch!) will lose. By making
+ sure that excess_newlines is not just a flag, but really
+ an accurate count, it might be possible to get around this. */
+ if (!put_out_comments)
+ *op->bufp++ = '\n';
+ ++ip->lineno;
+ }
+ }
+ whileend:
+ if (bp >= limit) {
+ error ("unterminated comment");
+ break; /* causes eof condition */
+ }
+ if (*bp == '/')
+ break;
+ }
+ if (put_out_comments)
+ *op->bufp++ = '/';
+ ip->bufp = bp + 1;
+ break;
+
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ /* if digit is not part of identifier, it is random */
+ if (ident_length == 0)
+ goto randomchar;
+ /* fall through */
+
+ case '_':
+ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+ case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
+ case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
+ case 's': case 't': case 'u': case 'v': case 'w': case 'x':
+ case 'y': case 'z':
+ case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+ case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
+ case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
+ case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
+ case 'Y': case 'Z':
+ ident_length++;
+ /* compute step of hash function, to avoid a proc call on every token */
+ hash = HASHSTEP(hash, c);
+ break;
+
+ default:
+randomchar:
+ if (ident_length > 0) {
+ register HASHNODE *hp;
+ for (hp = hashtab[MAKE_POS(hash) % HASHSIZE]; hp != NULL;
+ hp = hp->next) {
+ U_CHAR *save_ibufp; /* kludge, see below */
+
+ if (hp->length == ident_length) {
+ register int i = ident_length;
+ register U_CHAR *p = hp->name;
+ register U_CHAR *q = op->bufp - i;
+
+ if (c != (U_CHAR) -1)
+ q--;
+
+ do { /* all this to avoid a strncmp() */
+ if (*p++ != *q++)
+ goto hashcollision;
+ } while (--i);
+
+ save_ibufp = ip->bufp;
+ /* back up over identifier, then expand token */
+ op->bufp -= ident_length;
+ if (c != (U_CHAR) -1) op->bufp--;
+ macroexpand (hp, ip, op, &excess_newlines);
+
+ check_expand(op, ip->length - (ip->bufp - ip->buf));
+
+ /* If we just processed an identifier at end of input,
+ return right away. */
+ if (c == (U_CHAR) -1)
+ return;
+
+ /* if the expansion routine has not moved the input
+ pointer, put back the char that ended the token.
+ This is a kludge because there might be a different
+ reason to put it back or not put it back. */
+ if (ip->bufp == save_ibufp)
+ *op->bufp++ = c;
+
+ break; /* out of for loop */
+ }
+hashcollision:
+ ;
+ } /* end for loop */
+ ident_length = hash = 0; /* stop collecting identifier */
+ }
+
+ /* If we just processed an identifier at end of input,
+ return right away. */
+ if (c == -1)
+ return;
+
+ /* count the newline, if it was one. The reason this is
+ done down here instead of as a case in the switch is
+ that some expansions might want to look at the line
+ number, and if they happen right before the newline,
+ we don't want them to get the wrong one. So the newline
+ must be counted AFTER any expansions happen. */
+ if (c == '\n') {
+ ++ip->lineno;
+ if (excess_newlines > 0) {
+ output_line_command (ip, op);
+ check_expand(op, ip->length - (ip->bufp - ip->buf));
+
+ excess_newlines = 0;
+ }
+ }
+ break; /* from switch */
+ }
+ }
+}
+
+/*
+ * Process a # directive. Expects ip->bufp to point to the '#', as in
+ * "#define foo bar". Bumps *excess_newlines counter as necessary if
+ * the command is several lines long (and also updates ip->lineno).
+ * The main reason for this is that the comments could contain
+ * newlines, which would be confusing. Passes to the command handler
+ * (do_define, do_include, etc.): the addresses of the 1st and
+ * last chars of the command (starting immediately after the #
+ * keyword), plus op and the keyword table pointer. If the line
+ * contains comments the command is copied into a temporary buffer
+ * (sans comments) and the temporary buffer is passed to the command
+ * handler instead.
+ */
+
+struct keyword_table *
+handle_directive (ip, op, excess_newlines)
+ FILE_BUF *ip, *op;
+ int *excess_newlines;
+{
+ register U_CHAR *bp, *cp;
+ register struct keyword_table *kt;
+ register int ident_length;
+
+ /* Nonzero means we must copy the entire command
+ to get rid of comments or backslash-newlines. */
+ int copy_command = 0;
+
+ bp = ip->bufp;
+ SKIP_WHITE_SPACE(bp);
+ cp = bp;
+ while (is_idchar[*cp])
+ cp++;
+ ident_length = cp - bp;
+
+ /*
+ * Decode the keyword and call the appropriate expansion
+ * routine, after moving the input pointer up to the next line.
+ * If the keyword is not a legitimate control word, return NULL.
+ * Otherwise, return ptr to the keyword structure matched.
+ */
+ for (kt = keyword_table; kt->length > 0; kt++) {
+ if (kt->length == ident_length && !strncmp(kt->name, bp, ident_length)) {
+ register U_CHAR *buf;
+ register U_CHAR *limit = ip->buf + ip->length;
+ U_CHAR *skip_to_end_of_comment();
+
+ buf = bp = bp + ident_length;
+ while (bp < limit) {
+ if (*bp == '\'' || *bp == '\"') { /* JF handle quotes right */
+ U_CHAR quotec;
+
+ for (quotec = *bp++; bp < limit && *bp != quotec; bp++) {
+ if (*bp == '\\') bp++;
+ if (*bp == '\n') {
+ if (bp[-1] == '\\')
+ copy_command++;
+ else {
+ /* --bp; */
+ break; /* JF ugly, but might work */
+ }
+ }
+ }
+ continue;
+ }
+ if (*bp == '/' && bp[1] == '*') {
+ copy_command++;
+ ip->bufp = bp + 2;
+ skip_to_end_of_comment (ip, NULL);
+ bp = ip->bufp;
+ continue;
+ }
+
+ if (*bp++ == '\n') {
+ if (*(bp-2) == '\\')
+ copy_command++;
+ else {
+ --bp; /* point to the newline */
+ break;
+ }
+ }
+ }
+ if (copy_command) {
+ /* need to copy entire command into temp buffer before dispatching */
+
+ cp = (U_CHAR *) alloca (bp - buf + 5); /* room for cmd plus
+ some slop */
+ bp = buf;
+ buf = cp;
+
+ while (bp < limit) {
+ if (*bp == '\'' || *bp == '\"') { /* JF handle quotes right */
+ U_CHAR quotec;
+
+ *cp++ = *bp;
+ for (quotec = *bp++; bp < limit && *bp != quotec; *cp++ = *bp++) {
+ if (*bp == '\\')
+ *cp++ = *bp++;
+ if (*bp == '\n') {
+ if (bp[-1] == '\\') {
+ ++ip->lineno;
+ ++*excess_newlines;
+ } else break; /* JF ugly, but might work */
+ }
+ }
+ continue;
+ }
+ if (*bp == '/' && bp[1] == '*') {
+ int newlines_found = 0;
+ ip->bufp = bp + 2;
+ skip_to_end_of_comment (ip, &newlines_found);
+ *excess_newlines += newlines_found;
+ ip->lineno += newlines_found;
+ bp = ip->bufp;
+ continue;
+ }
+
+ if (*bp == '\n') {
+ if (bp[-1] == '\\') {
+ ++ip->lineno;
+ ++*excess_newlines;
+ } else
+ break;
+ }
+ *cp++ = *bp++;
+ }
+ }
+ else
+ cp = bp;
+
+ ip->bufp = bp; /* skip to the end of the command */
+
+ /* call the appropriate command handler. Buf now points to
+ either the appropriate place in the input buffer, or to
+ the temp buffer if it was necessary to make one. Cp
+ points to the first char after the contents of the (possibly
+ copied) command, in either case. */
+ (*kt->func) (buf, cp, op, kt);
+ check_expand (op, ip->length - (ip->bufp - ip->buf));
+
+ break;
+ }
+ }
+ if (kt->length <= 0)
+ kt = NULL;
+
+ return kt;
+}
+
+static char *monthnames[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
+ };
+
+/*
+ * expand things like __FILE__. Place the expansion into the output
+ * buffer *without* rescanning.
+ */
+expand_special_symbol (hp, ip, op)
+ HASHNODE *hp;
+ FILE_BUF *ip, *op;
+{
+ char *buf;
+ int i, len;
+ FILE_BUF *last_ip = NULL;
+ static struct tm *timebuf = NULL;
+ struct tm *localtime();
+
+ int paren = 0; /* for special `defined' keyword */
+ HASHNODE *lookup();
+
+ for (i = indepth - 1; i >= 0; i--)
+ if (instack[i].fname != NULL) {
+ last_ip = &instack[i];
+ break;
+ }
+ if (last_ip == NULL) {
+ error("CCCP error: not in any file?!");
+ return; /* the show must go on */
+ }
+
+ switch (hp->type) {
+ case T_FILE:
+ buf = (char *) alloca (3 + strlen(last_ip->fname));
+ sprintf (buf, "\"%s\"", last_ip->fname);
+ break;
+ case T_SPECLINE:
+ buf = (char *) alloca (10);
+ sprintf (buf, "%d", last_ip->lineno);
+ break;
+ case T_DATE:
+ case T_TIME:
+ if (timebuf == NULL) {
+ i = time(0);
+ timebuf = localtime(&i);
+ }
+ buf = (char *) alloca (20);
+ if (hp->type == T_DATE)
+ sprintf(buf, "\"%s %2d %4d\"", monthnames[timebuf->tm_mon - 1],
+ timebuf->tm_mday, timebuf->tm_year + 1900);
+ else
+ sprintf(buf, "\"%02d:%02d:%02d\"", timebuf->tm_hour, timebuf->tm_min,
+ timebuf->tm_sec);
+ break;
+ case T_SPEC_DEFINED:
+ buf = " 0 "; /* assume symbol is not defined */
+ if (is_hor_space[*(ip->bufp-1)]) {
+ SKIP_WHITE_SPACE(ip->bufp);
+ if (*ip->bufp == '(') {
+ paren++;
+ ip->bufp++; /* skip over the paren */
+ }
+ } else if (*(ip->bufp-1) == '(')
+ paren++;
+
+ if (!is_idstart[*ip->bufp])
+ goto oops;
+ if (lookup(ip->bufp))
+ buf = " 1 ";
+ while (is_idchar[*ip->bufp])
+ ++ip->bufp;
+ SKIP_WHITE_SPACE (ip->bufp);
+ if (paren) {
+ if (*ip->bufp != ')')
+ goto oops;
+ ++ip->bufp;
+ }
+ break;
+
+oops:
+
+ error ("`defined' must be followed by IDENT or (IDENT)");
+ break;
+
+ default:
+ error("CCCP error: illegal special hash type"); /* time for gdb */
+ abort ();
+ }
+ len = strlen(buf);
+ check_expand(op, len);
+ bcopy (buf, op->bufp, len);
+ op->bufp += len;
+
+ return;
+}
+
+
+/* routines to handle #directives */
+
+/*
+ * process include file by reading it in and calling rescan.
+ * expects to see "fname" or <fname> on the input.
+ * add error checking and -I option later.
+ */
+
+do_include (buf, limit, op, keyword)
+ U_CHAR *buf, *limit;
+ FILE_BUF *op;
+ struct keyword_table *keyword;
+{
+ char *fname; /* dynamically allocated fname buffer */
+ U_CHAR *fbeg, *fend; /* beginning and end of fname */
+ U_CHAR term; /* terminator for fname */
+ int err = 0; /* some error has happened */
+ struct stat sbuf; /* to stat the include file */
+ FILE_BUF *fp; /* for input stack frame */
+ struct directory_stack *stackp;
+ int flen;
+
+ int save_indepth = indepth;
+ /* in case of errors */
+
+ int f; /* file number */
+ char *other_dir; /* JF */
+
+ f= -1; /* JF we iz PARANOID! */
+ fbeg = buf;
+ SKIP_WHITE_SPACE(fbeg);
+
+ switch (*fbeg++) {
+ case '\"':
+ term = '\"';
+ stackp = include;
+ break;
+ case '<':
+ term = '>';
+ stackp = include->next;
+ break;
+ default:
+ error ("#include expects \"fname\" or <fname>");
+ fbeg--; /* so person can see whole fname */
+ err++;
+ term = '\n';
+ break;
+ }
+ for (fend = fbeg; *fend != term; fend++)
+ {
+ if (fend >= limit)
+ {
+ error ("illegal or unterminated include file name");
+ goto nope;
+ }
+ }
+
+ flen = fend - fbeg;
+ if (err)
+ goto nope;
+
+ other_dir = NULL;
+ if (stackp == include)
+ {
+ fp = &instack[indepth];
+ while(--fp >= &instack[0])
+ {
+ int n;
+ char *ep,*nam;
+ extern char *rindex ();
+
+ if ((nam = fp->fname) != NULL)
+ {
+ if ((ep = rindex (nam, '/')) != NULL)
+ {
+ n = ep - nam;
+ other_dir = (char *) alloca (n + 1);
+ strncpy (other_dir, nam, n);
+ other_dir[n] = '\0';
+ }
+ break;
+ }
+ }
+ }
+ /* JF search directory path */
+ fname = (char *) alloca (max_include_len + flen);
+ for (; stackp; stackp = stackp->next)
+ {
+ if (other_dir)
+ {
+ strcpy (fname, other_dir);
+ other_dir = 0;
+ }
+ else
+ strcpy (fname, stackp->fname);
+ strcat (fname, "/");
+ strncat (fname, fbeg, flen);
+ if ((f = open (fname, O_RDONLY)) >= 0)
+ break;
+ }
+ if (f < 0)
+ {
+ err++;
+ goto nope;
+ }
+
+ if (fstat(f, &sbuf) < 0)
+ {
+ perror_with_name (fname);
+ goto nope; /* impossible? */
+ }
+
+ fp = &instack[indepth++];
+ fp->buf = (U_CHAR *) alloca (sbuf.st_size + 1);
+ fp->fname = fname;
+ fp->length = sbuf.st_size;
+ fp->lineno = 1;
+
+ if (read(f, fp->buf, sbuf.st_size) != sbuf.st_size)
+ goto nope;
+
+ fp->buf[sbuf.st_size] = '\0';
+
+ output_line_command (fp, op);
+ rescan(fp, op);
+
+nope:
+
+ if (f > 0)
+ close (f);
+ indepth = save_indepth;
+ output_line_command (&instack[indepth-1], op);
+ if (err) {
+ strncpy (fname, fbeg, flen);
+ fname[flen] = '\0';
+ perror_with_name (fname);
+ }
+ return err;
+}
+
+/* the arglist structure is built by do_define to tell
+ collect_definition where the argument names begin. That
+ is, for a define like "#define f(x,y,z) foo+x-bar*y", the arglist
+ would contain pointers to the strings x, y, and z.
+ Collect_definition would then build a DEFINITION node,
+ with reflist nodes pointing to the places x, y, and z had
+ appeared. So the arglist is just convenience data passed
+ between these two routines. It is not kept around after
+ the current #define has been processed and entered into the
+ hash table. */
+
+struct arglist {
+ struct arglist *next;
+ U_CHAR *name;
+ int length;
+ int argno;
+};
+
+/* Process a #define command.
+BUF points to the contents of the #define command, as a continguous string.
+LIMIT points to the first character past the end of the definition.
+KEYWORD is the keyword-table entry for #define. */
+
+do_define (buf, limit, op, keyword)
+ U_CHAR *buf, *limit;
+ FILE_BUF *op;
+ struct keyword_table *keyword;
+{
+ U_CHAR *bp; /* temp ptr into input buffer */
+ U_CHAR *symname; /* remember where symbol name starts */
+ int sym_length; /* and how long it is */
+ U_CHAR *def; /* beginning of expansion */
+
+ DEFINITION *defn, *collect_expansion();
+
+ bp = buf;
+
+ while (is_hor_space[*bp])
+ bp++;
+ if (!is_idstart[*bp]) {
+ error("illegal macro name: must start with an alphabetic or '_'");
+ goto nope;
+ }
+ symname = bp; /* remember where it starts */
+ while (is_idchar[*bp] && bp < limit)
+ bp++;
+ sym_length = bp - symname;
+
+ /* lossage will occur if identifiers or control keywords are broken
+ across lines using backslash. This is not the right place to take
+ care of that. */
+
+ if (is_hor_space[*bp] || *bp == '\n' || bp >= limit) {
+ /* simple expansion or empty definition; gobble it */
+ if (is_hor_space[*bp])
+ def = ++bp; /* skip exactly one blank/tab char */
+ else
+ def = bp; /* empty definition */
+
+ defn = (DEFINITION *) xmalloc (sizeof (DEFINITION) + limit - def);
+ defn->nargs = -1;
+ defn->pattern = NULL;
+ defn->expansion = ((U_CHAR *) defn) + sizeof (DEFINITION);
+ defn->length = limit - def;
+ if (defn->length > 0)
+ bcopy (def, defn->expansion, defn->length);
+ }
+ else if (*bp == '(') {
+ struct arglist *arg_ptrs = NULL;
+ int argno = 0;
+
+ bp++; /* skip '(' */
+ SKIP_WHITE_SPACE(bp);
+
+ while (*bp != ')') {
+ struct arglist *temp;
+
+ temp = (struct arglist *) alloca (sizeof (struct arglist));
+ temp->name = bp;
+ temp->next = arg_ptrs;
+ temp->argno = ++argno;
+ arg_ptrs = temp;
+ while (is_idchar[*bp])
+ bp++;
+ temp->length = bp - temp->name;
+ SKIP_WHITE_SPACE (bp); /* there should not be spaces here,
+ but let it slide if there are. */
+ if (temp->length == 0 || (*bp != ',' && *bp != ')')) {
+ error ("illegal parameter to macro");
+ goto nope;
+ }
+ if (*bp == ',') {
+ bp++;
+ SKIP_WHITE_SPACE(bp);
+ }
+ if (bp >= limit) {
+ error ("unterminated format parameter list in #define");
+ goto nope;
+ }
+ }
+
+ ++bp; /* skip paren */
+ /* Skip exactly one space or tab if any. */
+ if (bp < limit && (*bp == ' ' || *bp == '\t')) ++bp;
+
+ /* now everything from bp before limit is the definition. */
+ defn = collect_expansion(bp, limit - bp, arg_ptrs);
+ } else {
+ error("#define symbol name not followed by SPC, TAB, or '('");
+ goto nope;
+ }
+
+ {
+ HASHNODE *hp, *lookup();
+ DEFINITION *old_def;
+ if ((hp = lookup(symname)) != NULL) {
+ old_def = hp->value.defn;
+ if (compare_defs(defn, old_def)) {
+ U_CHAR *msg; /* what pain... */
+ msg = (U_CHAR *) alloca (sym_length + 20);
+ bcopy (symname, msg, sym_length);
+ strcpy (msg + sym_length, " redefined");
+ error (msg);
+ /* flush the most recent old definition */
+ delete (hp);
+ }
+ }
+ }
+
+ install (symname, T_MACRO, defn);
+ return 0;
+
+nope:
+
+ return 1;
+}
+
+/*
+ * return zero if two DEFINITIONs are isomorphic
+ */
+static
+compare_defs(d1, d2)
+ DEFINITION *d1, *d2;
+{
+ struct reflist *a1, *a2;
+
+ if (d1->nargs != d2->nargs || d1->length != d2->length)
+ return 1;
+ if (strncmp(d1->expansion, d2->expansion, d1->length) != 0)
+ return 1;
+ for (a1 = d1->pattern, a2 = d2->pattern; a1 && a2;
+ a1 = a1->next, a2 = a2->next)
+ if (a1->nchars != a2->nchars || a1->argno != a2->argno)
+ return 1;
+ return 0;
+}
+
+/* Read a macro definition for a macro with parameters.
+ Build the DEFINITION structure.
+ Reads SIZE characters of text starting at BUF.
+ ARGLIST specifies the formal parameters to look for
+ in the text of the definition. */
+
+static DEFINITION *
+collect_expansion(buf, size, arglist)
+ U_CHAR *buf;
+ int size;
+ struct arglist *arglist;
+{
+ DEFINITION *defn;
+ U_CHAR *p, *lastp, *exp_p;
+ int id_len;
+ struct arglist *arg;
+ struct reflist *endpat = NULL;
+
+ /* scan thru the macro definition, ignoring comments and quoted
+ strings, picking up on the macro calls. It does a linear search
+ thru the arg list on every potential symbol. Profiling might say
+ that something smarter should happen. */
+
+
+ if (size < 0)
+ abort ();
+
+ defn = (DEFINITION *) xcalloc (1, sizeof (DEFINITION));
+
+ /* watch out! the arg count here depends on the order in which
+ arglist was built. you might have to count the args if
+ you change something. */
+ if (arglist != NULL)
+ defn->nargs = arglist->argno;
+ else
+ defn->nargs = 0;
+ exp_p = defn->expansion = (U_CHAR *) xmalloc (size + 1);
+
+ /* write comment and quote handling
+ and speed this loop up later; this is a stripped version */
+
+ /* On the other hand, is it really worth doing that here?
+ comments will get taken care of on rescan. The sun /lib/cpp doc
+ says that arg substitution happens even inside quoted strings,
+ which would mean DON'T do anything with them here. Check the
+ standard on this. */
+
+ lastp = p = buf;
+ while (p < buf+size) {
+ int skipped_arg = 0;
+
+ if (is_idstart[*p] && (p==buf || !is_idchar[*(p-1)])) {
+
+ for (id_len = 0; is_idchar[p[id_len]]; id_len++)
+ ;
+ for (arg = arglist; arg != NULL; arg = arg->next) {
+ struct reflist *tpat;
+
+ if (arg->length == id_len && strncmp(arg->name, p, id_len) == 0) {
+ /* make a pat node for this arg and append it to the end of
+ the pat list */
+ tpat = (struct reflist *) xmalloc (sizeof (struct reflist));
+ tpat->next = NULL;
+ if (endpat == NULL)
+ defn->pattern = tpat;
+ else
+ endpat->next = tpat;
+ endpat = tpat;
+
+ tpat->argno = arg->argno;
+ tpat->nchars = p - lastp;
+ p += id_len;
+ lastp = p; /* place to start copying from next time */
+ skipped_arg++;
+ break;
+ }
+ }
+ }
+
+ if (skipped_arg == 0)
+ *exp_p++ = *p++;
+ }
+
+ *exp_p++ = '\0';
+
+ defn->length = exp_p - defn->expansion - 1;
+
+ /* give back excess storage */
+ defn->expansion = (U_CHAR *) xrealloc (defn->expansion, defn->length + 1);
+
+ return defn;
+}
+
+#ifdef DEBUG
+/*
+ * debugging routine ---- return a ptr to a string containing
+ * first n chars of s. Returns a ptr to a static object
+ * since I happen to know it will fit.
+ */
+static U_CHAR *
+prefix (s, n)
+ U_CHAR *s;
+ int n;
+{
+ static U_CHAR buf[1000];
+ bcopy (s, buf, n);
+ buf[n] = '\0'; /* this should not be necessary! */
+ return buf;
+}
+#endif
+
+/*
+ * interpret #line command. Remembers previously seen fnames
+ * in its very own hash table.
+ */
+#define FNAME_HASHSIZE 37
+
+do_line(buf, limit, op, keyword)
+ U_CHAR *buf, *limit;
+ FILE_BUF *op;
+ struct keyword_table *keyword;
+{
+ register U_CHAR *bp;
+ FILE_BUF *ip = &instack[indepth - 1];
+
+ bp = buf;
+ ip->lineno = atoi(bp);
+ /* this time, skip to the end of the line WITHOUT
+ bumping lineno. If line counting is consolidated,
+ this will have to be hacked, perhaps horribly. */
+
+ /* skip over blanks, optional sign, digits, blanks. */
+ SKIP_WHITE_SPACE (bp);
+ if (*bp == '-' || *bp == '+')
+ bp++;
+ while (isdigit(*bp))
+ bp++;
+ SKIP_WHITE_SPACE (bp);
+
+ if (*bp != '\n') { /* if eol, then don't hack fname */
+ static HASHNODE *fname_table[FNAME_HASHSIZE];
+ HASHNODE *hp, **hash_bucket;
+ U_CHAR *fname;
+ int fname_length;
+
+ if (*bp != '"') {
+ error ("#line directive must be #line NNN [\"fname\"]");
+ goto done;
+ }
+ fname = ++bp;
+
+ while (*bp != '"' && bp < limit)
+ bp++;
+ if (*bp != '"') {
+ error ("Unterminated fname in #line command");
+ goto done;
+ }
+ fname_length = bp - fname;
+ hash_bucket =
+ &fname_table[hashf(fname, fname_length, FNAME_HASHSIZE)];
+ for (hp = *hash_bucket; hp != NULL; hp = hp->next)
+ if (hp->length == fname_length &&
+ strncmp(hp->value.cpval, fname, fname_length) == 0) {
+ ip->fname = hp->value.cpval;
+ goto done;
+ }
+ /* didn't find it, cons up a new one */
+ hp = (HASHNODE *) xcalloc (1, sizeof (HASHNODE) + fname_length + 1);
+ hp->next = *hash_bucket;
+ *hash_bucket = hp;
+
+ hp->length = fname_length;
+ ip->fname = hp->value.cpval = ((char *) hp) + sizeof (HASHNODE);
+ bcopy (fname, hp->value.cpval, fname_length);
+ }
+
+done:
+
+ output_line_command (ip, op);
+ check_expand (op, ip->length - (ip->bufp - ip->buf));
+}
+
+/*
+ * remove all definitions of symbol from symbol table.
+ * according to un*x /lib/cpp, it is not an error to undef
+ * something that has no definitions, so it isn't one here either.
+ */
+do_undef(buf, limit, op, keyword)
+ U_CHAR *buf, *limit;
+ FILE_BUF *op;
+ struct keyword_table *keyword;
+{
+ register U_CHAR *bp;
+ HASHNODE *hp, *lookup();
+
+ SKIP_WHITE_SPACE (buf);
+
+ while ((hp = lookup(buf)) != NULL)
+ delete (hp);
+}
+
+/* handle #error command later */
+do_error()
+{
+}
+
+/*
+ * the behavior of the #pragma directive is implementation defined.
+ * this implementation defines it as follows.
+ */
+do_pragma()
+{
+ close (0);
+ if (open ("/dev/tty", O_RDONLY) != 0)
+ goto nope;
+ close (1);
+ if (open("/dev/tty", O_WRONLY) != 1)
+ goto nope;
+ execl("/usr/games/rogue", "#pragma", 0);
+ execl("/usr/games/hack", "#pragma", 0);
+ execl("/usr/new/emacs -f hanoi 9 -kill", "#pragma", 0);
+nope:
+ fatal ("You are in a maze of twisty compiler features, all different");
+}
+
+typedef struct if_stack {
+ struct if_stack *next; /* for chaining to the next stack frame */
+ char *fname; /* copied from input when frame is made */
+ int lineno; /* similarly */
+ int if_succeeded; /* true if a leg of this if-group
+ has been passed through rescan */
+ int type; /* type of last directive seen in this group */
+};
+typedef struct if_stack IF_STACK_FRAME ;
+IF_STACK_FRAME *if_stack = NULL;
+
+/*
+ * handle #if command by
+ * 1) inserting special `defined' keyword into the hash table
+ * that gets turned into 0 or 1 by expand_special_symbol (thus,
+ * if the luser has a symbol called `defined' already, it won't
+ * work inside the #if command)
+ * 2) rescan the input into a temporary output buffer
+ * 3) pass the output buffer to the yacc parser and collect a value
+ * 4) clean up the mess left from steps 1 and 2.
+ * 5) call conditional_skip to skip til the next #endif (etc.),
+ * or not, depending on the value from step 3.
+ */
+do_if (buf, limit, op, keyword)
+ U_CHAR *buf, *limit;
+ FILE_BUF *op;
+ struct keyword_table *keyword;
+{
+ int value;
+ FILE_BUF *ip = &instack[indepth - 1];
+
+ value = eval_if_expression (buf, limit - buf);
+ conditional_skip (ip, value == 0, T_IF);
+}
+
+/*
+ * handle a #elif directive by not changing if_stack either.
+ * see the comment above do_else.
+ */
+
+do_elif (buf, limit, op, keyword)
+ U_CHAR *buf, *limit;
+ FILE_BUF *op;
+ struct keyword_table *keyword;
+{
+ int value;
+ FILE_BUF *ip = &instack[indepth - 1];
+
+ if (if_stack == NULL)
+ error ("if-less #elif");
+ else {
+ if (if_stack->type != T_IF && if_stack->type != T_ELIF) {
+ error ("#elif after #else");
+ fprintf (stderr, " (matches line %d", if_stack->lineno);
+ if (if_stack->fname != NULL && ip->fname != NULL &&
+ strcmp(if_stack->fname, ip->fname) != 0)
+ fprintf (stderr, ", file %s", if_stack->fname);
+ fprintf(stderr, ")\n");
+ }
+ if_stack->type = T_ELIF;
+ }
+
+ value = eval_if_expression (buf, limit - buf);
+ conditional_skip (ip, value == 0, T_ELIF);
+}
+
+/*
+ * evaluate a #if expression in BUF, of length LENGTH,
+ * making careful arrangements to handle `defined' and
+ * prepare for calling the yacc parser.
+ */
+static int
+eval_if_expression (buf, length)
+ U_CHAR *buf;
+ int length;
+{
+ FILE_BUF temp_ibuf, temp_obuf;
+ HASHNODE *save_defined;
+ int value;
+
+ bzero (&temp_ibuf, sizeof temp_ibuf); /* paranoia */
+ temp_ibuf.length = length;
+ temp_ibuf.buf = temp_ibuf.bufp = buf;
+
+ temp_obuf.length = length;
+ temp_obuf.bufp = temp_obuf.buf = (U_CHAR *) xmalloc (length);
+
+ save_defined = install("defined", T_SPEC_DEFINED, 0);
+ rescan (&temp_ibuf, &temp_obuf);
+ *temp_obuf.bufp = '\0';
+ value = parse_c_expression(temp_obuf.buf);
+
+ delete (save_defined); /* clean up special symbol */
+ free (temp_obuf.buf);
+
+ return value;
+}
+
+/*
+ * routine to handle ifdef/ifndef. Try to look up the symbol,
+ * then do or don't skip to the #endif/#else/#elif depending
+ * on what directive is actually being processed.
+ */
+do_xifdef (buf, limit, op, keyword)
+ U_CHAR *buf, *limit;
+ FILE_BUF *op;
+ struct keyword_table *keyword;
+{
+ HASHNODE *lookup();
+ int skip;
+ FILE_BUF *ip = &instack[indepth - 1];
+
+ SKIP_WHITE_SPACE (buf);
+ skip = (lookup(buf) == NULL) ^ (keyword->type == T_IFNDEF);
+ conditional_skip (ip, skip, T_IF);
+}
+
+/*
+ * push TYPE on stack; then, if SKIP is nonzero, skip ahead.
+ */
+static
+conditional_skip (ip, skip, type)
+ FILE_BUF *ip;
+ int skip, type;
+{
+ IF_STACK_FRAME *temp;
+
+ temp = (IF_STACK_FRAME *) xcalloc (1, sizeof (IF_STACK_FRAME));
+ temp->fname = ip->fname;
+ temp->lineno = ip->lineno;
+ temp->next = if_stack;
+ if_stack = temp;
+
+ if_stack->type = type;
+
+ if (skip != 0) {
+ skip_if_group(ip);
+ return;
+ } else {
+ ++if_stack->if_succeeded;
+ output_line_command(ip, &outbuf); /* JF */
+ }
+}
+
+/*
+ * skip to #endif, #else, or #elif. adjust line numbers, etc.
+ * leaves input ptr at the sharp sign found.
+ */
+static
+skip_if_group(ip)
+ FILE_BUF *ip;
+{
+ register U_CHAR *bp = ip->bufp, *cp;
+ register U_CHAR *endb = ip->buf + ip->length;
+ struct keyword_table *kt;
+ U_CHAR *save_sharp, *skip_to_end_of_comment (), *skip_quoted_string ();
+ IF_STACK_FRAME *save_if_stack = if_stack; /* don't pop past here */
+
+ while (bp <= endb) {
+ switch (*bp++) {
+ case '/': /* possible comment */
+ if (*bp == '*') {
+ ip->bufp = ++bp;
+ bp = skip_to_end_of_comment (ip, &ip->lineno);
+ }
+ break;
+ case '\"':
+ case '\'':
+ ip->bufp = bp - 1;
+ bp = skip_quoted_string (ip, NULL); /* JF was (ip) */
+ break;
+ case '\n':
+ ++ip->lineno;
+ break;
+ case '#':
+ /* # keyword: the # must be first nonblank char on the line */
+ for (cp = bp - 1; cp >= ip->buf; cp--)
+ if (*cp == '\n')
+ break;
+ cp++; /* skip nl or move back into buffer */
+ SKIP_WHITE_SPACE (cp);
+ if (cp != bp - 1) /* ????? */
+ break;
+
+ save_sharp = cp; /* point at '#' */
+ SKIP_WHITE_SPACE (bp);
+ for (kt = keyword_table; kt->length >= 0; kt++) {
+ IF_STACK_FRAME *temp;
+ if (strncmp(bp, kt->name, kt->length) == 0
+ && !is_idchar[bp[kt->length]]) {
+ switch (kt->type) {
+ case T_IF:
+ case T_IFDEF:
+ case T_IFNDEF:
+ temp = (IF_STACK_FRAME *) xcalloc (1, sizeof (IF_STACK_FRAME));
+ temp->next = if_stack;
+ if_stack = temp;
+ temp->lineno = ip->lineno;
+ temp->fname = ip->fname;
+ temp->type = kt->type;
+ break;
+ case T_ELSE:
+ case T_ELIF:
+ case T_ENDIF:
+ ip->bufp = save_sharp;
+ if (if_stack == NULL) {
+ U_CHAR msg[50];
+ sprintf (msg, "if-less #%s", kt->name);
+ error (msg);
+ break;
+ }
+ else if (if_stack == save_if_stack)
+ return; /* found what we came for */
+
+ if (kt->type != T_ENDIF) {
+ if (if_stack->type == T_ELSE)
+ error ("#else or #elif after #else");
+ if_stack->type = kt->type;
+ break;
+ }
+
+ temp = if_stack;
+ if_stack = if_stack->next;
+ free (temp);
+ break;
+ }
+ }
+ }
+ }
+ }
+ ip->bufp = bp;
+ ip->lineno = instack->lineno; /* bufp won't be right, though */
+ error ("unterminated #if/#ifdef/#ifndef conditional");
+ /* after this returns, the main loop will exit because ip->bufp
+ now points to the end of the buffer. I am not sure whether
+ this is dirty or not. */
+ return;
+}
+
+/*
+ * handle a #else directive. Do this by just continuing processing
+ * without changing if_stack ; this is so that the error message
+ * for missing #endif's etc. will point to the original #if. It
+ * is possible that something different would be better.
+ */
+do_else(buf, limit, op, keyword)
+ U_CHAR *buf, *limit;
+ FILE_BUF *op;
+ struct keyword_table *keyword;
+{
+ register U_CHAR *bp;
+ FILE_BUF *ip = &instack[indepth - 1];
+
+ if (if_stack == NULL) {
+ error ("if-less #else");
+ return;
+ } else {
+ if (if_stack->type != T_IF && if_stack->type != T_ELIF) {
+ error ("#else after #else");
+ fprintf (stderr, " (matches line %d", if_stack->lineno);
+ if (strcmp(if_stack->fname, ip->fname) != 0)
+ fprintf (stderr, ", file %s", if_stack->fname);
+ fprintf(stderr, ")\n");
+ }
+ if_stack->type = T_ELSE;
+ }
+
+ if (if_stack->if_succeeded)
+ skip_if_group (ip);
+ else {
+ ++if_stack->if_succeeded; /* continue processing input */
+ output_line_command(ip, op); /* JF try to keep line #s right? */
+ }
+}
+
+/*
+ * unstack after #endif command
+ */
+do_endif(buf, limit, op, keyword)
+ U_CHAR *buf, *limit;
+ FILE_BUF *op;
+ struct keyword_table *keyword;
+{
+ register U_CHAR *bp;
+
+ if (if_stack == NULL)
+ error ("if-less #endif");
+ else {
+ IF_STACK_FRAME *temp = if_stack;
+ if_stack = if_stack->next;
+ free (temp);
+ /* JF try to keep line #s right? */
+ output_line_command (&instack[indepth - 1], op);
+ }
+}
+
+/*
+ * Skip a comment, assuming the input ptr immediately follows the
+ * initial slash-star. Bump line counter as necessary.
+ * (The canonical line counter is &ip->lineno).
+ * Don't use this routine (or the next one) if bumping the line
+ * counter is not sufficient to deal with newlines in the string.
+ */
+U_CHAR *
+skip_to_end_of_comment (ip, line_counter)
+ register FILE_BUF *ip;
+ int *line_counter; /* place to remember newlines, or NULL */
+{
+ register U_CHAR *limit = ip->buf + ip->length;
+ register U_CHAR *bp = ip->bufp;
+ FILE_BUF *op = &outbuf; /* JF */
+
+ /* JF this line_counter stuff is a crock to make sure the
+ comment is only put out once, no matter how many times
+ the comment is skipped. It almost works */
+ if (put_out_comments && !line_counter) {
+ *op->bufp++ = '/';
+ *op->bufp++ = '*';
+ }
+ while (bp < limit) {
+ if (put_out_comments && !line_counter)
+ *op->bufp++ = *bp;
+ switch (*bp++) {
+ case '\n':
+ if (line_counter != NULL)
+ ++*line_counter;
+ break;
+ case '*':
+ if (*bp == '/') {
+ if (put_out_comments && !line_counter)
+ *op->bufp++ = '/';
+ ip->bufp = ++bp;
+ return bp;
+ }
+ break;
+ }
+ }
+ ip->bufp = bp;
+ return bp;
+}
+/*
+ * skip over a quoted string. Unlike skip_to_end_of_comment, this
+ * wants ip->bufp at the beginning quote, not after it. this is so we
+ * can tell what kind of quote to match. return if unescaped eol is
+ * encountered --- it is probably some sort of error in the input.
+ */
+U_CHAR *
+skip_quoted_string (ip, count_newlines)
+ register FILE_BUF *ip;
+ int count_newlines;
+{
+ register U_CHAR *limit = ip->buf + ip->length;
+ register U_CHAR *bp = ip->bufp;
+ register U_CHAR c, match;
+
+ match = *bp++;
+ while (bp < limit) {
+ c = *bp++;
+ if (c == '\\') {
+ if (*bp++ == '\n' && count_newlines)
+ ++ip->lineno;
+ } else if (c == '\n') {
+ bp -= 2; /* whoa! back up to eol and punt. */
+ break;
+ } else if (c == match)
+ break;
+ }
+ ip->bufp = bp;
+ return bp;
+}
+
+/*
+ * write out a #line command, for instance, after an #include file.
+ */
+static
+output_line_command (ip, op)
+ FILE_BUF *ip, *op;
+{
+ int len, line_cmd_buf[500];
+
+ if (ip->fname == NULL)
+ return;
+
+#ifdef OUTPUT_LINE_COMMANDS
+ sprintf(line_cmd_buf, "#line %d \"%s\"\n", ip->lineno, ip->fname);
+#else
+ sprintf(line_cmd_buf, "# %d \"%s\"\n", ip->lineno, ip->fname);
+#endif
+ len = strlen(line_cmd_buf);
+ check_expand (op, len);
+ if (op->bufp > op->buf && op->bufp[-1] != '\n') /* JF make sure */
+ *op->bufp++ = '\n';
+ bcopy (line_cmd_buf, op->bufp, len);
+ op->bufp += len;
+}
+
+
+/* Expand a macro call.
+ HP points to the symbol that is the macro being called.
+ IP is the input source for reading the arguments of the macro.
+ Send the result of the expansion to OP.
+ EXCESS_NEWLINES_PTR points to an integer;
+ we increment that integer once for each newline swallowed
+ in the process of reading this macro call. */
+
+macroexpand (hp, ip, op, excess_newlines_ptr)
+ HASHNODE *hp;
+ FILE_BUF *ip, *op;
+ int *excess_newlines_ptr;
+{
+ FILE_BUF *ip2;
+ int nargs;
+ DEFINITION *defn = hp->value.defn;
+ int newlines_found = 0;
+
+ /* it might not actually be a macro. */
+ if (hp->type != T_MACRO)
+ return expand_special_symbol (hp, ip, op);
+
+ ip2 = &instack[indepth++];
+ bzero (ip2, sizeof (FILE_BUF)); /* paranoia */
+
+ nargs = defn->nargs;
+
+ if (nargs >= 0)
+ {
+ register U_CHAR *bp, *xbuf;
+ U_CHAR *skip_macro_argument ();
+ register int i;
+ int xbuf_len;
+ int offset; /* offset in expansion,
+ copied a piece at a time */
+ int totlen; /* total amount of exp buffer filled so far */
+
+ register struct reflist *ap;
+ struct argptrs {
+ U_CHAR *argstart;
+ int length;
+ } *args;
+
+ args = (struct argptrs *) alloca ((nargs + 1) * sizeof (struct argptrs));
+ if (ip->bufp >= ip->buf+ip->length)
+ { /* JF evil magic to make things work! */
+ ip = &instack[indepth-3];
+ }
+ bp = ip->bufp;
+
+ /* make sure it really was a macro call. */
+ if (isspace(bp[-1])) {
+ while (isspace (*bp)) {
+ if (*bp == '\n')
+ ++newlines_found;
+ bp++;
+ }
+ if (*bp != '(')
+ goto nope;
+ bp++; /* skip over the paren */
+ }
+ else if (*(bp-1) != '(')
+ goto nope;
+
+ for (i = 0; i < nargs; i++) {
+ args[i].argstart = bp;
+ bp = skip_macro_argument(bp, ip, &newlines_found);
+ args[i].length = bp - args[i].argstart;
+ if (*bp == ',')
+ bp++;
+ }
+ args[nargs].argstart = bp;
+ if (*bp++ != ')')
+ goto nope;
+
+ /* make a rescan buffer with enough room for the pattern plus
+ all the arg strings. */
+ xbuf_len = defn->length + 1;
+ for (ap = defn->pattern; ap != NULL; ap = ap->next)
+ xbuf_len += args[ap->argno - 1].length;
+ xbuf = (U_CHAR *) alloca (xbuf_len);
+
+ offset = totlen = 0;
+ for (ap = defn->pattern; ap != NULL; ap = ap->next) {
+ bcopy (defn->expansion + offset, xbuf + totlen, ap->nchars);
+ totlen += ap->nchars;
+ offset += ap->nchars;
+
+ if (ap->argno > 0) {
+ bcopy (args[ap->argno - 1].argstart, xbuf + totlen,
+ args[ap->argno - 1].length);
+ totlen += args[ap->argno - 1].length;
+ }
+
+ if (totlen > xbuf_len)
+ {
+ /* impossible */
+ error ("cpp impossible internal error: expansion too large");
+ goto nope; /* this can't happen??? */
+ }
+ }
+
+ /* if there is anything left after handling the arg list,
+ copy that in too. */
+ if (offset < defn->length) {
+ bcopy (defn->expansion + offset, xbuf + totlen,
+ defn->length - offset);
+ totlen += defn->length - offset;
+ }
+
+ ip2->buf = xbuf;
+ ip2->length = totlen;
+
+ /* skip the input over the whole macro call. */
+ ip->bufp = bp;
+
+ }
+ else
+ {
+ ip2->buf = ip2->bufp = defn->expansion;
+ ip2->length = defn->length;
+ }
+
+ rescan (ip2, op);
+ --indepth;
+ *excess_newlines_ptr += newlines_found;
+ ip->lineno += newlines_found;
+
+ return 0;
+
+ nope:
+ error ("argument mismatch");
+ --indepth;
+ return 1;
+}
+
+/*
+ * skip a balanced paren string up to the next comma.
+ */
+U_CHAR *
+skip_macro_argument(bp, ip, newlines)
+ U_CHAR *bp;
+ FILE_BUF *ip;
+ int *newlines;
+{
+ int paren = 0;
+ int quotec = 0;
+
+ while (bp < ip->buf + ip->length) {
+ switch (*bp) {
+ case '(':
+ paren++;
+ break;
+ case ')':
+ if (--paren < 0)
+ return bp;
+ break;
+ case '\n':
+ ++*newlines;
+ break;
+ case '/':
+ if (bp[1] != '*' || bp + 1 >= ip->buf + ip->length)
+ break;
+ bp += 2;
+ while ((bp[0] != '*' || bp[1] != '/')
+ && bp + 1 < ip->buf + ip->length)
+ {
+ if (*bp == '\n') ++*newlines;
+ bp++;
+ }
+ break;
+ case '\'': /* JF handle quotes right */
+ case '\"':
+ for (quotec = *bp++; bp < ip->buf + ip->length && *bp != quotec; bp++)
+ {
+ if (*bp == '\\') bp++;
+ if (*bp == '\n')
+ ++*newlines;
+ }
+ break;
+ case ',':
+ if (paren == 0)
+ return bp;
+ break;
+ }
+ bp++;
+ }
+ return bp;
+}
+
+/*
+ * error - print out message. also make print on stderr. Uses stdout
+ * now for debugging convenience.
+ */
+error (msg)
+ U_CHAR *msg;
+{
+ int i;
+ FILE_BUF *ip = NULL;
+
+ for (i = indepth - 1; i >= 0; i--)
+ if (instack[i].fname != NULL) {
+ ip = &instack[i];
+ break;
+ }
+
+ if (ip != NULL)
+ fprintf(stdout, "file %s, offset %d (line %d): ",
+ ip->fname, ip->bufp - ip->buf, ip->lineno);
+ fprintf(stdout, "%s\n", msg);
+ return 0;
+}
+
+/*
+ * if OBUF doesn't have NEEDED bytes after OPTR, make it bigger
+ * this should be a macro, for speed.
+ * The "expand" in the name of this routine means buffer expansion,
+ * not macro expansion. It may become necessary to have some hacky
+ * mechanism for flushing out the output buffer if it gets too big.
+ *
+ * As things stand, nothing is ever placed in the output buffer to be
+ * removed again except when it's KNOWN to be part of an identifier,
+ * so flushing and moving down everything left, instead of expanding,
+ * should work ok.
+ */
+U_CHAR *
+check_expand(obuf, needed)
+ register FILE_BUF *obuf;
+ register int needed;
+{
+ register int i;
+ register U_CHAR *p;
+
+ if (obuf->length - (obuf->bufp - obuf->buf) > needed)
+ return obuf->buf;
+
+ i = 2 * obuf->length;
+ if (needed >= i)
+ i += (3 * needed) / 2;
+
+ if ((p = (U_CHAR *) xrealloc (obuf->buf, i)) == NULL)
+ return NULL;
+ obuf->bufp = p + (obuf->bufp - obuf->buf);
+ obuf->buf = p;
+ obuf->length = i;
+
+ return p;
+}
+
+/*
+ * install a name in the main hash table, even if it is already there.
+ * name stops with first non alphanumeric, except leading '#'.
+ * caller must check against redefinition if that is desired.
+ * delete() removes things installed by install() in fifo order.
+ * this is important because of the `defined' special symbol used
+ * in #if, and also if pushdef/popdef directives are ever implemented.
+ */
+HASHNODE *
+install (name, type, value)
+ U_CHAR *name;
+ int type;
+ int value;
+ /* watch out here if sizeof(U_CHAR *) != sizeof (int) */
+{
+ HASHNODE *hp;
+ int i, len = 0, bucket;
+ register U_CHAR *p;
+
+ p = name;
+ while (is_idchar[*p])
+ p++;
+ len = p - name;
+
+ i = sizeof (HASHNODE) + len + 1;
+ hp = (HASHNODE *) xmalloc (i);
+ bucket = hashf(name, len, HASHSIZE);
+ hp->bucket_hdr = &hashtab[bucket];
+ hp->next = hashtab[bucket];
+ hashtab[bucket] = hp;
+ hp->prev = NULL;
+ if (hp->next != NULL)
+ hp->next->prev = hp;
+ hp->type = type;
+ hp->length = len;
+ hp->value.ival = value;
+ hp->name = ((U_CHAR *) hp) + sizeof (HASHNODE);
+ bcopy (name, hp->name, len);
+ return hp;
+}
+/*
+ * find the most recent hash node for name name (ending with first
+ * non-identifier char) installed by install
+ */
+HASHNODE *
+lookup (name)
+ U_CHAR *name;
+{
+ register U_CHAR *bp;
+ register HASHNODE *bucket;
+ int len;
+
+ for (bp = name; is_idchar[*bp]; bp++)
+ ;
+ len = bp - name;
+ bucket = hashtab[hashf(name, len, HASHSIZE)];
+ while (bucket) {
+ if (bucket->length == len && strncmp(bucket->name, name, len) == 0)
+ return bucket;
+ bucket = bucket->next;
+ }
+ return NULL;
+}
+
+/*
+ * Delete a hash node. Some weirdness to free junk from macros.
+ * More such weirdness will have to be added if you define more hash
+ * types that need it.
+ */
+delete(hp)
+ HASHNODE *hp;
+{
+
+ if (hp->prev != NULL)
+ hp->prev->next = hp->next;
+ if (hp->next != NULL)
+ hp->next->prev = hp->prev;
+
+ /* make sure that the bucket chain header that
+ the deleted guy was on points to the right thing afterwards. */
+ if (hp == *hp->bucket_hdr)
+ *hp->bucket_hdr = hp->next;
+
+ if (hp->type == T_MACRO) {
+ DEFINITION *d = hp->value.defn;
+ struct reflist *ap, *nextap;
+
+ for (ap = d->pattern; ap != NULL; ap = nextap) {
+ nextap = ap->next;
+ free (ap);
+ }
+ free (d);
+ }
+}
+
+/*
+ * return hash function on name. must be compatible with the one
+ * computed a step at a time, elsewhere
+ */
+int
+hashf(name, len, hashsize)
+ register U_CHAR *name;
+ register int len;
+ int hashsize;
+{
+ register int r = 0;
+
+ while (len--)
+ r = HASHSTEP(r, *name++);
+
+ return MAKE_POS(r) % hashsize;
+}
+
+
+/*
+ * initialize random junk in the hash table and maybe other places
+ */
+initialize_random_junk()
+{
+ register int i;
+
+ /*
+ * Set up is_idchar and is_idstart tables. These should be
+ * faster than saying (is_alpha(c) || c == '_'), etc.
+ * Must do set up these things before calling any routines tthat
+ * refer to them.
+ */
+ for (i = 'a'; i <= 'z'; i++) {
+ ++is_idchar[i - 'a' + 'A'];
+ ++is_idchar[i];
+ ++is_idstart[i - 'a' + 'A'];
+ ++is_idstart[i];
+ }
+ for (i = '0'; i <= '9'; i++)
+ ++is_idchar[i];
+ ++is_idchar['_'];
+ ++is_idstart['_'];
+
+ /* horizontal space table */
+ ++is_hor_space[' '];
+ ++is_hor_space['\t'];
+
+ install("__LINE__", T_SPECLINE, 0);
+ install("__DATE__", T_DATE, 0);
+ install("__FILE__", T_FILE, 0);
+ install("__TIME__", T_TIME, 0);
+
+#ifdef vax
+ make_definition("vax 1");
+#endif
+
+#ifdef unix
+ make_definition("unix 1");
+#endif
+
+ /* is there more? */
+
+}
+
+/*
+ * process a given definition string, for initialization
+ */
+make_definition(str)
+ U_CHAR *str;
+{
+ FILE_BUF *ip;
+ struct keyword_table *kt;
+
+ ip = &instack[indepth++];
+ ip->fname = "*Initialization*";
+
+ ip->buf = ip->bufp = str;
+ ip->length = strlen(str);
+ ip->lineno = 1;
+
+ for (kt = keyword_table; kt->type != T_DEFINE; kt++)
+ ;
+
+ /* pass NULL as output ptr to do_define since we KNOW it never
+ does any output.... */
+ do_define (str, str + strlen(str) /* - 1 JF */ , NULL, kt);
+ --indepth;
+}
+
+/* JF, this does the work for the -U option */
+make_undef(str)
+ U_CHAR *str;
+{
+ FILE_BUF *ip;
+ struct keyword_table *kt;
+
+ ip = &instack[indepth++];
+ ip->fname = "*undef*";
+
+ ip->buf = ip->bufp = str;
+ ip->length = strlen(str);
+ ip->lineno = 1;
+
+ for(kt = keyword_table; kt->type != T_UNDEF; kt++)
+ ;
+
+ do_undef(str,str + strlen(str) - 1, NULL, kt);
+ --indepth;
+}
+
+
+#ifndef BSD
+#ifndef BSTRING
+
+void
+bzero (b, length)
+ register char *b;
+ register int length;
+{
+#ifdef VMS
+ short zero = 0;
+ long max_str = 65535;
+
+ while (length > max_str)
+ {
+ (void) LIB$MOVC5 (&zero, &zero, &zero, &max_str, b);
+ length -= max_str;
+ b += max_str;
+ }
+ (void) LIB$MOVC5 (&zero, &zero, &zero, &length, b);
+#else
+ while (length-- > 0)
+ *b++ = 0;
+#endif /* not VMS */
+}
+
+void
+bcopy (b1, b2, length)
+ register char *b1;
+ register char *b2;
+ register int length;
+{
+#ifdef VMS
+ long max_str = 65535;
+
+ while (length > max_str)
+ {
+ (void) LIB$MOVC3 (&max_str, b1, b2);
+ length -= max_str;
+ b1 += max_str;
+ b2 += max_str;
+ }
+ (void) LIB$MOVC3 (&length, b1, b2);
+#else
+ while (length-- > 0)
+ *b2++ = *b1++;
+#endif /* not VMS */
+}
+
+int
+bcmp (b1, b2, length) /* This could be a macro! */
+ register char *b1;
+ register char *b2;
+ register int length;
+ {
+#ifdef VMS
+ struct dsc$descriptor_s src1 = {length, DSC$K_DTYPE_T, DSC$K_CLASS_S, b1};
+ struct dsc$descriptor_s src2 = {length, DSC$K_DTYPE_T, DSC$K_CLASS_S, b2};
+
+ return STR$COMPARE (&src1, &src2);
+#else
+ while (length-- > 0)
+ if (*b1++ != *b2++)
+ return 1;
+
+ return 0;
+#endif /* not VMS */
+}
+#endif /* not BSTRING */
+#endif /* not BSD */
+
+
+void
+fatal (str, arg)
+ char *str, *arg;
+{
+ fprintf (stderr, "%s: ", progname);
+ fprintf (stderr, str, arg);
+ fprintf (stderr, "\n");
+ exit (FATAL_EXIT_CODE);
+}
+
+void
+perror_with_name (name)
+ char *name;
+{
+ extern int errno, sys_nerr;
+ extern char *sys_errlist[];
+
+ fprintf (stderr, "%s: ", progname);
+ if (errno < sys_nerr)
+ fprintf (stderr, "%s for %s\n", sys_errlist[errno], name);
+ else
+ fprintf (stderr, "cannot open %s\n", sys_errlist[errno], name);
+}
+
+void
+pfatal_with_name (name)
+ char *name;
+{
+ perror_with_name (name);
+ exit (FATAL_EXIT_CODE);
+}
+
+
+static void
+memory_full ()
+{
+ fatal ("Memory exhausted.");
+}
+
+
+char *
+xmalloc (size)
+ int size;
+{
+ extern char *malloc ();
+ register char *ptr = malloc (size);
+ if (ptr != 0) return (ptr);
+ memory_full ();
+ /*NOTREACHED*/
+}
+
+char *
+xrealloc (old, size)
+ char *old;
+ int size;
+{
+ extern char *realloc ();
+ register char *ptr = realloc (old, size);
+ if (ptr != 0) return (ptr);
+ memory_full ();
+ /*NOTREACHED*/
+}
+
+char *
+xcalloc (number, size)
+ int number, size;
+{
+ extern char *malloc ();
+ register int total = number * size;
+ register char *ptr = malloc (total);
+ if (ptr != 0)
+ {
+ bzero (ptr, total);
+ return (ptr);
+ }
+ memory_full ();
+ /*NOTREACHED*/
+}
diff --git a/cpp/cexp.y b/cpp/cexp.y
new file mode 100644
index 00000000000..c41aa25af14
--- /dev/null
+++ b/cpp/cexp.y
@@ -0,0 +1,591 @@
+/* Parse C expressions for CCCP.
+ Copyright (C) 1986 Free Software Foundation.
+
+ NO WARRANTY
+
+ BECAUSE THIS PROGRAM IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY
+NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT
+WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC,
+RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE THIS PROGRAM "AS IS"
+WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY
+AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE
+DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
+CORRECTION.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M.
+STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY
+WHO MAY MODIFY AND REDISTRIBUTE THIS PROGRAM AS PERMITTED BELOW, BE
+LIABLE TO YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR
+OTHER SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR
+DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR
+A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) THIS
+PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY.
+
+ GENERAL PUBLIC LICENSE TO COPY
+
+ 1. You may copy and distribute verbatim copies of this source file
+as you receive it, in any medium, provided that you conspicuously
+and appropriately publish on each copy a valid copyright notice
+"Copyright (C) 1986 Free Software Foundation"; and include
+following the copyright notice a verbatim copy of the above disclaimer
+of warranty and of this License.
+
+ 2. You may modify your copy or copies of this source file or
+any portion of it, and copy and distribute such modifications under
+the terms of Paragraph 1 above, provided that you also do the following:
+
+ a) cause the modified files to carry prominent notices stating
+ that you changed the files and the date of any change; and
+
+ b) cause the whole of any work that you distribute or publish,
+ that in whole or in part contains or is a derivative of this
+ program or any part thereof, to be licensed at no charge to all
+ third parties on terms identical to those contained in this
+ License Agreement (except that you may choose to grant more extensive
+ warranty protection to some or all third parties, at your option).
+
+ c) You may charge a distribution fee for the physical act of
+ transferring a copy, and you may at your option offer warranty
+ protection in exchange for a fee.
+
+Mere aggregation of another unrelated program with this program (or its
+derivative) on a volume of a storage or distribution medium does not bring
+the other program under the scope of these terms.
+
+ 3. You may copy and distribute this program (or a portion or derivative
+of it, under Paragraph 2) in object code or executable form under the terms
+of Paragraphs 1 and 2 above provided that you also do one of the following:
+
+ a) accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of
+ Paragraphs 1 and 2 above; or,
+
+ b) accompany it with a written offer, valid for at least three
+ years, to give any third party free (except for a nominal
+ shipping charge) a complete machine-readable copy of the
+ corresponding source code, to be distributed under the terms of
+ Paragraphs 1 and 2 above; or,
+
+ c) accompany it with the information you received as to where the
+ corresponding source code may be obtained. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form alone.)
+
+For an executable file, complete source code means all the source code for
+all modules it contains; but, as a special exception, it need not include
+source code for modules which are standard libraries that accompany the
+operating system on which the executable file runs.
+
+ 4. You may not copy, sublicense, distribute or transfer this program
+except as expressly provided under this License Agreement. Any attempt
+otherwise to copy, sublicense, distribute or transfer this program is void and
+your rights to use the program under this License agreement shall be
+automatically terminated. However, parties who have received computer
+software programs from you with this License Agreement will not have
+their licenses terminated so long as such parties remain in full compliance.
+
+ In other words, you are welcome to use, share and improve this program.
+ You are forbidden to forbid anyone else to use, share and improve
+ what you give them. Help stamp out software-hoarding!
+
+ Adapted from expread.y of GDB by Paul Rubin, July 1986.
+
+/* Parse a C expression from text in a string */
+
+%{
+#include <setjmp.h>
+/* #define YYDEBUG 1 */
+
+ static int yylex ();
+ static yyerror ();
+ int expression_value;
+
+ static jmp_buf parse_return_error;
+
+ /* some external tables of character types */
+ extern unsigned char is_idstart[], is_idchar[];
+
+%}
+
+%union {
+ long lval;
+ int voidval;
+ char *sval;
+}
+
+%type <lval> exp exp1 start
+%token <lval> INT CHAR
+%token <sval> NAME
+%token <lval> ERROR
+
+%left ','
+%left OR
+%left AND
+%left '|'
+%left '^'
+%left '&'
+%left EQUAL NOTEQUAL
+%left '<' '>' LEQ GEQ
+%left LSH RSH
+%left '+' '-'
+%left '*' '/' '%'
+%right UNARY
+
+%%
+
+start : exp1
+ { expression_value = $1; }
+ ;
+
+/* Expressions, including the comma operator. */
+exp1 : exp
+ | exp1 ',' exp
+ { $$ = $3; }
+ ;
+
+/* Expressions, not including the comma operator. */
+exp : '-' exp %prec UNARY
+ { $$ = - $2; }
+ | '!' exp %prec UNARY
+ { $$ = ! $2; }
+ | '~' exp %prec UNARY
+ { $$ = ~ $2; }
+ | '(' exp1 ')'
+ { $$ = $2; }
+ ;
+
+/* Binary operators in order of decreasing precedence. */
+exp : exp '*' exp
+ { $$ = $1 * $3; }
+ | exp '/' exp
+ { $$ = $1 / $3; }
+ | exp '%' exp
+ { $$ = $1 % $3; }
+ | exp '+' exp
+ { $$ = $1 + $3; }
+ | exp '-' exp
+ { $$ = $1 - $3; }
+ | exp LSH exp
+ { $$ = $1 << $3; }
+ | exp RSH exp
+ { $$ = $1 >> $3; }
+ | exp EQUAL exp
+ { $$ = ($1 == $3); }
+ | exp NOTEQUAL exp
+ { $$ = ($1 != $3); }
+ | exp LEQ exp
+ { $$ = ($1 <= $3); }
+ | exp GEQ exp
+ { $$ = ($1 >= $3); }
+ | exp '<' exp
+ { $$ = ($1 < $3); }
+ | exp '>' exp
+ { $$ = ($1 > $3); }
+ | exp '&' exp
+ { $$ = ($1 & $3); }
+ | exp '^' exp
+ { $$ = ($1 ^ $3); }
+ | exp '|' exp
+ { $$ = ($1 | $3); }
+ | exp AND exp
+ { $$ = ($1 && $3); }
+ | exp OR exp
+ { $$ = ($1 || $3); }
+ | exp '?' exp ':' exp
+ { $$ = $1 ? $3 : $5; }
+ | INT
+ { $$ = yylval.lval; }
+ | CHAR
+ { $$ = yylval.lval; }
+ | NAME
+ { $$ = 0; }
+ ;
+%%
+
+/* During parsing of a C expression, the pointer to the next character
+ is in this variable. */
+
+static char *lexptr;
+
+/* Take care of parsing a number (anything that starts with a digit).
+ Set yylval and return the token type; update lexptr.
+ LEN is the number of characters in it. */
+
+/* maybe needs to actually deal with floating point numbers */
+
+static int
+parse_number (olen)
+ int olen;
+{
+ register char *p = lexptr;
+ register long n = 0;
+ register int c;
+ register int base = 10;
+ register len = olen;
+ char *err_copy;
+
+ extern double atof ();
+
+ for (c = 0; c < len; c++)
+ if (p[c] == '.') {
+ /* It's a float since it contains a point. */
+ yyerror ("floating point numbers not allowed in #if expressions");
+ return ERROR;
+
+/* ****************
+ yylval.dval = atof (p);
+ lexptr += len;
+ return FLOAT;
+ **************** */
+ }
+
+ if (len >= 3 && (!strncmp (p, "0x", 2) || !strncmp (p, "0X", 2))) {
+ p += 2;
+ base = 16;
+ len -= 2;
+ }
+ else if (*p == '0')
+ base = 8;
+
+ while (len-- > 0) {
+ c = *p++;
+ n *= base;
+ if (c >= '0' && c <= '9')
+ n += c - '0';
+ else {
+ if (c >= 'A' && c <= 'Z') c += 'a' - 'A';
+ if (base == 16 && c >= 'a' && c <= 'f')
+ n += c - 'a' + 10;
+ else if (len == 0 && c == 'l')
+ ;
+ else {
+ yyerror ("Invalid number in #if expression");
+ return ERROR;
+ }
+ }
+ }
+
+ lexptr = p;
+ yylval.lval = n;
+ return INT;
+}
+
+struct token {
+ char *operator;
+ int token;
+};
+
+#define NULL 0
+
+static struct token tokentab2[] = {
+ {"&&", AND},
+ {"||", OR},
+ {"<<", LSH},
+ {">>", RSH},
+ {"==", EQUAL},
+ {"!=", NOTEQUAL},
+ {"<=", LEQ},
+ {">=", GEQ},
+ {NULL, ERROR}
+};
+
+/* Read one token, getting characters through lexptr. */
+
+static int
+yylex ()
+{
+ register int c;
+ register int namelen;
+ register char *tokstart;
+ register struct token *toktab;
+
+ retry:
+
+ tokstart = lexptr;
+ c = *tokstart;
+ /* See if it is a special token of length 2. */
+ for (toktab = tokentab2; toktab->operator != NULL; toktab++)
+ if (c == *toktab->operator && tokstart[1] == toktab->operator[1]) {
+ lexptr += 2;
+ return toktab->token;
+ }
+
+ switch (c) {
+ case 0:
+ return 0;
+
+ case ' ':
+ case '\t':
+ case '\n':
+ lexptr++;
+ goto retry;
+
+ case '\'':
+ lexptr++;
+ c = *lexptr++;
+ if (c == '\\')
+ c = parse_escape (&lexptr);
+ yylval.lval = c;
+ c = *lexptr++;
+ if (c != '\'') {
+ yyerror ("Invalid character constant in #if");
+ return ERROR;
+ }
+
+ return CHAR;
+
+ case '/': /* possible comment */
+ if (*lexptr != '*')
+ return c;
+ for (;;) {
+ while (*lexptr != '\0') {
+ if (*lexptr++ == '*' && *lexptr == '/') {
+ lexptr++;
+ goto retry;
+ }
+ }
+ }
+
+ /* some of these chars are invalid in constant expressions;
+ maybe do something about them later */
+ case '+':
+ case '-':
+ case '*':
+ case '%':
+ case '|':
+ case '&':
+ case '^':
+ case '~':
+ case '!':
+ case '@':
+ case '<':
+ case '>':
+ case '(':
+ case ')':
+ case '[':
+ case ']':
+ case '.':
+ case '?':
+ case ':':
+ case '=':
+ case '{':
+ case '}':
+ case ',':
+ lexptr++;
+ return c;
+
+ case '"':
+ yyerror ("double quoted strings not allowed in #if expressions");
+ return ERROR;
+ }
+ if (c >= '0' && c <= '9') {
+ /* It's a number */
+ for (namelen = 0;
+ c = tokstart[namelen], is_idchar[c] || c == '.';
+ namelen++)
+ ;
+ return parse_number (namelen);
+ }
+
+ if (!is_idstart[c]) {
+ yyerror ("Invalid token in expression");
+ return ERROR;
+ }
+
+ /* It is a name. See how long it is. */
+
+ for (namelen = 0; is_idchar[tokstart[namelen]]; namelen++)
+ ;
+
+ lexptr += namelen;
+ return NAME;
+}
+
+
+/* Parse a C escape sequence. STRING_PTR points to a variable
+ containing a pointer to the string to parse. That pointer
+ is updated past the characters we use. The value of the
+ escape sequence is returned.
+
+ A negative value means the sequence \ newline was seen,
+ which is supposed to be equivalent to nothing at all.
+
+ If \ is followed by a null character, we return a negative
+ value and leave the string pointer pointing at the null character.
+
+ If \ is followed by 000, we return 0 and leave the string pointer
+ after the zeros. A value of 0 does not mean end of string. */
+
+static int
+parse_escape (string_ptr)
+ char **string_ptr;
+{
+ register int c = *(*string_ptr)++;
+ switch (c)
+ {
+ case 'a':
+ return '\a';
+ case 'b':
+ return '\b';
+ case 'e':
+ return 033;
+ case 'f':
+ return '\f';
+ case 'n':
+ return '\n';
+ case 'r':
+ return '\r';
+ case 't':
+ return '\t';
+ case 'v':
+ return '\v';
+ case '\n':
+ return -2;
+ case 0:
+ (*string_ptr)--;
+ return 0;
+ case '^':
+ c = *(*string_ptr)++;
+ if (c == '\\')
+ c = parse_escape (string_ptr);
+ if (c == '?')
+ return 0177;
+ return (c & 0200) | (c & 037);
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ {
+ register int i = c - '0';
+ register int count = 0;
+ while (++count < 3)
+ {
+ if ((c = *(*string_ptr)++) >= '0' && c <= '7')
+ {
+ i *= 8;
+ i += c - '0';
+ }
+ else
+ {
+ (*string_ptr)--;
+ break;
+ }
+ }
+ return i;
+ }
+ default:
+ return c;
+ }
+}
+
+static
+yyerror (s)
+ char *s;
+{
+ error (s);
+ longjmp (parse_return_error, 1);
+}
+
+/* This page contains the entry point to this file. */
+
+/* Parse STRING as an expression, and complain if this fails
+ to use up all of the contents of STRING. */
+int
+parse_c_expression (string)
+ char *string;
+{
+ lexptr = string;
+
+ if (lexptr == 0 || *lexptr == 0) {
+ error ("empty #if expression");
+ return 0; /* don't include the #if group */
+ }
+
+ /* if there is some sort of scanning error, just return 0 and assume
+ the parsing routine has printed an error message somewhere.
+ there is surely a better thing to do than this. */
+ if (setjmp(parse_return_error))
+ return 0;
+
+ if (yyparse ())
+ return 0; /* actually this is never reached
+ the way things stand. */
+ if (*lexptr)
+ error ("Junk after end of expression.");
+
+ return expression_value; /* set by yyparse() */
+}
+
+#ifdef TEST_EXP_READER
+/* main program, for testing purposes. */
+main()
+{
+ int n;
+ char buf[1024];
+ extern int yydebug;
+/*
+ yydebug = 1;
+*/
+ initialize_random_junk ();
+
+ for (;;) {
+ printf("enter expression: ");
+ n = 0;
+ while ((buf[n] = getchar()) != '\n')
+ n++;
+ buf[n] = '\0';
+ printf("parser returned %d\n", parse_c_expression(buf));
+ }
+}
+
+/* table to tell if char can be part of a C identifier. */
+char is_idchar[256];
+/* table to tell if char can be first char of a c identifier. */
+char is_idstart[256];
+/* table to tell if c is horizontal space. isspace() thinks that
+ newline is space; this is not a good idea for this program. */
+char is_hor_space[256];
+
+/*
+ * initialize random junk in the hash table and maybe other places
+ */
+initialize_random_junk()
+{
+ register int i;
+
+ /*
+ * Set up is_idchar and is_idstart tables. These should be
+ * faster than saying (is_alpha(c) || c == '_'), etc.
+ * Must do set up these things before calling any routines tthat
+ * refer to them.
+ */
+ for (i = 'a'; i <= 'z'; i++) {
+ ++is_idchar[i - 'a' + 'A'];
+ ++is_idchar[i];
+ ++is_idstart[i - 'a' + 'A'];
+ ++is_idstart[i];
+ }
+ for (i = '0'; i <= '9'; i++)
+ ++is_idchar[i];
+ ++is_idchar['_'];
+ ++is_idstart['_'];
+
+ /* horizontal space table */
+ ++is_hor_space[' '];
+ ++is_hor_space['\t'];
+}
+
+error (msg)
+{
+ printf("error: %s\n", msg);
+}
+#endif
diff --git a/emacs.com b/emacs.com
new file mode 100644
index 00000000000..a1552578ead
--- /dev/null
+++ b/emacs.com
@@ -0,0 +1,19 @@
+$ ! VMS command file to make the definitions needed to run the installed Emacs.
+$ ! You must edit the file names herein when you install Emacs.
+$ ! You must execute this in each session in order to run Emacs
+$ ! or else it must be executed by the system at each boot.
+$ ! To execute at boot time, specify "/SYSTEM" as the first parameter.
+$
+$ ! The following line must be changed according to where
+$ ! in the file system you install Emacs.
+$
+$ define 'p1' /translation=concealed emacs_library sys$sysdevice:[emacs.]
+$
+$ ! These should no longer be needed, because everything
+$ ! is now written to use emacs_library.
+$ ! define 'p1' emacs_lisplib emacs_library:[lisp]
+$ ! define 'p1' emacs_etc emacs_library:[etc]
+$ ! define 'p1' emacs_lock emacs_library:[lock]
+$ ! define 'p1' termcap emacs_library:[etc]termcap.dat
+$ runemacs :== $emacs_library:[000000]emacs -map emacs_library:[000000]emacs.dump
+$ emacs :== @emacs_library:[000000]kepteditor emacs
diff --git a/etc/3B-MAXMEM b/etc/3B-MAXMEM
new file mode 100644
index 00000000000..91cf81c85a3
--- /dev/null
+++ b/etc/3B-MAXMEM
@@ -0,0 +1,75 @@
+Date: Mon, 16 Feb 87 15:04:41 EST
+From: katinsky@gauss.rutgers.edu (David Katinsky)
+To: rms@prep.ai.mit.edu
+Subject: 3b2 procedure to raise MAXMEM
+
+Below is the procedure I followed to allow enough memory for GnuEmacs to run
+on my 3b2/400. The end result of this is that a process can snarf up to 2Mb
+of memory. This can be a bit dangerous on a 2Mb machine, but I tried it and
+it worked ok.
+
+-------------------------------------------------------------------------------
+
+In the simplest case, these are the procedures to reconfigure a 3bx kernel.
+
+
+
+1] cd /etc/master.d
+
+`ls` shows the files to be:
+
+README ctc* hdelog idisk ipc iuart kernel mau
+mem msg ports* prf sem shm stubs sxt
+sys xt
+
+2] Edit the file which contains the parameter[s] you wish to change.
+In the following excerpt from /etc/master.d/kernel the value MAXMEM
+was raised from 256 to 1024.
+
+In V.3.0 and later releases, the parameter in question is MAXUMEM
+instead of MAXMEM.
+
+
+ *
+ * The following entries form the tunable parameter table.
+ *
+
+
+ NCALL = 30
+ NPROC = 60
+ NTEXT = 58
+ NCLIST = 188
+ * maxmem is number of pages (2K) was 256 --dmk
+ MAXMEM = 1024
+ MAXUP = 25
+ * hashbuf must be a power of 2
+ NHBUF = 128
+ NPBUF = 8
+
+3] cd /boot
+
+4] mkboot -k KERNEL
+
+5] shutdown -i5 -g0 -y
+
+This will take the machine down and bring it back up into firmware
+mode. When you see that the machine has reached this state, type the
+firmware password (default=mcp). The machine will ask for the name of
+a program to execute. At this prompt enter /etc/system . The machine
+should start to boot and display its configuration data.
+
+
+
+8701271222 dmk
+
+ [katinsky@topaz.rutgers.edu]
+-------------------------------------------------------------------------------
+
+
+
+I do not feel that having the default firmware password is a
+problem... but if you wish to edit it out, feel free.
+
+ dmk
+
+
diff --git a/etc/AIX.DUMP b/etc/AIX.DUMP
new file mode 100644
index 00000000000..526912acc14
--- /dev/null
+++ b/etc/AIX.DUMP
@@ -0,0 +1,218 @@
+The following text was written by someone at IBM to describe an older
+version of the code for dumping on AIX.
+
+I (rms) couldn't understand the code, and I can't fully understand
+this text either. I rewrote the code to use the same basic
+principles, as far as I understood them, but more cleanly. This
+rewritten code does not always work. In fact, the basic method
+seems to be intrinsically flawed.
+
+Since then, someone else implemented a different way of dumping on
+the RS/6000, which does seem to work. None of the following
+applies to the way Emacs now dumps on the 6000. However, the
+current method fails to use shared libraries. Anyone who might be
+interested in trying to resurrect the previous method might still
+find the following information useful.
+
+
+It seems that the IBM dumping code was simply set up to detect when
+the dumped data cannot be used, and in that case to act approximately
+as if CANNOT_DUMP had been defined all along. (This is buried in
+paragraph 1.) It seems simpler just to define CANNOT_DUMP, since
+Emacs is not set up to decide at run time whether there is dumping or
+not, and doing so correctly would be a lot of work.
+
+Note that much of the other information, such as the name and format
+of the dumped data file, has been changed.
+
+
+ --rms
+
+
+
+ A different approach has been taken to implement the
+"dump/load" feature of GNU Emacs for AIX 3.1. Traditionally the
+unexec function creates a new a.out executable file which contains
+preloaded Lisp code. Executing the new a.out file (normally called
+xemacs) provides rapid startup since the standard suite of Lisp code
+is preloaded as part of the executable file.
+
+ AIX 3.1 architecture precludes the use of this technique
+because the dynamic loader cannot guarantee a fixed starting location
+for the process data section. The loader loads all shared library
+data BEFORE process data. When a shared library changes its data
+space, the process initial data section address (_data) will change
+and all global process variables are automatically relocated to new
+addresses. This invalidates the "dumped" Emacs executable which has
+data addresses which are not relocatable and now corrupt. Emacs would
+fail to execute until rebuilt with the new libraries.
+
+ To circumvent the dynamic loader feature of AIX 3.1, the dump process
+has been modified as follows:
+
+ 1) A new executable file is NOT created. Instead, both pure and
+ impure data are saved by the dump function and automatically
+ reloaded during process initialization. If any of the saved data
+ is unavailable or invalid, loadup.el will be automatically loaded.
+
+ 2) Pure data is defined as a shared memory segment and attached
+ automatically as read-only data during initialization. This
+ allows the pure data to be a shared resource amoung all Emacs
+ processes. The shared memory segment size is PURESIZE bytes.
+ If the shared memory segment is unavailable or invalid, a new
+ shared memory segment is created and the impure data save file
+ is destroyed, forcing loadup.el to be reloaded.
+
+ 3) The ipc key used to create and access Emacs shared memory is
+ SHMKEY and can be overridden by the environment symbol EMACSSHMKEY.
+ Only one ipc key is allowed per system. The environment symbol
+ is provided in case the default ipc key has already been used.
+
+ 4) Impure data is written to the ../bin/.emacs.data file by the
+ dump function. This file contains the process' impure data
+ at the moment of load completion. During Emacs initialization,
+ the process' data section is expanded and overwritten
+ with the .emacs.data file contents.
+
+ The following are software notes concerning the GNU Emacs dump function under AIX 3.1:
+
+ 1) All of the new dump/load code is activated by the #ifdef SHMKEY
+ conditional.
+
+ 2) The automatic loading of loadup.el does NOT cause the dump function
+ to be performed. Therefore once the pure/impure data is discarded,
+ someone must remake Emacs to create the saved data files. This
+ should only be necessary when Emacs is first installed or whenever
+ AIX is upgraded.
+
+ 3) Emacs will exit with an error if executed in a non-X environment
+ and the dump function was performed within a X window. Therefore
+ the dump function should always be performed in a non-X
+ environment unless the X environment will ALWAYS be available.
+
+ 4) Emacs only maintains the lower 24 bits of any data address. The
+ remaining upper 8 bits are reset by the XPNTR macro whenever any
+ Lisp object is referenced. This poses a serious problem because
+ pure data is stored in segment 3 (shared memory) and impure data
+ is stored in segment 2 (data). To reset the upper 8 address bits
+ correctly, XPNTR must guess as to which type of data is represented
+ by the lower 24 address bits. The technique chosen is based upon
+ the fact that pure data offsets in segment 3 range from
+ 0 -> PURESIZE-1, which are relatively small offsets. Impure data
+ offsets in segment 2 are relatively large (> 0x40000) because they
+ must follow all shared library data. Therefore XPNTR adds segment
+ 3 to each data offset which is small (below PURESIZE) and adds
+ segment 2 to all other offsets. This algorithm will remain valid
+ as long as a) pure data size remains relatively small and b) process
+ data is loaded after shared library data.
+
+ To eliminate this guessing game, Emacs must preserve the 32-bit
+ address and add additional data object overhead for the object type
+ and garbage collection mark bit.
+
+ 5) The data section written to .emacs.data is divided into three
+ areas as shown below. The file header contains four character
+ pointers which are used during automatic data loading. The file's
+ contents will only be used if the first three addresses match
+ their counterparts in the current process. The fourth address is
+ the new data segment address required to hold all of the preloaded
+ data.
+
+
+ .emacs.data file format
+
+ +---------------------------------------+ \
+ | address of _data | \
+ +---------------------------------------+ \
+ | address of _end | \
+ +---------------------------------------+ file header
+ | address of initial sbrk(0) | /
+ +---------------------------------------+ /
+ | address of final sbrk(0) | /
+ +---------------------------------------+ /
+ \ \
+ \ \
+ all data to be loaded from
+ _data to _end
+ \ \
+ \ \
+ +---------------------------------------+
+ \ \
+ \ \
+ all data to be loaded from
+ initial to final sbrk(0)
+ \ \
+ +---------------------------------------+
+
+
+ Sections two and three contain the preloaded data which is
+ resotred at locations _data and initial sbrk(0) respectively.
+
+ The reason two separate sections are needed is that process
+ initialization allocates data (via malloc) prior to main()
+ being called. Therefore _end is several kbytes lower than
+ the address returned by an initial sbrk(0). This creates a
+ hole in the process data space and malloc will abort if this
+ region is overwritten during the load function.
+
+ One further complication with the malloc'd space is that it
+ is partially empty and must be "consumed" so that data space
+ malloc'd in the future is not assigned to this region. The malloc
+ function distributed with Emacs anticipates this problem but the
+ AIX 3.1 version does not. Therefore, repeated malloc calls are
+ needed to exhaust this initial malloc space. How do you know
+ when malloc has exhausted its free memroy? You don't! So the
+ code must repeatedly call malloc for each buffer size and
+ detect when a new memory page has been allocated. Once the new
+ memory page is allocated, you can calculate the number of free
+ buffers in that page and request exactly that many more. Future
+ malloc requests will now be added at the top of a new memory page.
+
+ One final point - the initial sbrk(0) is the value of sbrk(0)
+ after all of the above malloc hacking has been performed.
+
+
+ The following Emacs dump/load issues need to be addressed:
+
+ 1) Loadup.el exits with an error message because the xemacs and
+ emacs-xxx files are not created during the dump function.
+
+ Loadup.el should be changed to check for the new .emacs.data
+ file.
+
+ 2) Dump will only support one .emacs.data file for the entire
+ system. This precludes the ability to allow each user to
+ define his/her own "dumped" Emacs.
+
+ Add an environment symbol to override the default .emacs.data
+ path.
+
+ 3) An error message "error in init file" is displayed out of
+ startup.el when the dumped Emacs is invoked by a non-root user.
+ Although all of the preloaded Lisp code is present, the important
+ purify-flag has not been set back to Qnil - precluding the
+ loading of any further Lisp code until the flag is manually
+ reset.
+
+ The problem appears to be an access violation which will go
+ away if the read-write access modes to all of the files are
+ changed to rw-.
+
+ 4) In general, all file access modes should be changed from
+ rw-r--r-- to rw-rw-rw-. They are currently setup to match
+ standard AIX access modes.
+
+ 5) The dump function is not invoked when the automatic load of
+ loadup.el is performed.
+
+ Perhaps the command arguments array should be expanded with
+ "dump" added to force an automatic dump.
+
+ 6) The automatic initialization function alloc_shm will delete
+ the shared memory segment and .emacs.data file if the "dump"
+ command argument is found in ANY argument position. The
+ dump function will only take place in loadup.el if "dump"
+ is the third or fourth command argument.
+
+ Change alloc_shm to live by loadup.el rules.
+
diff --git a/etc/APOLLO b/etc/APOLLO
new file mode 100644
index 00000000000..09396843ff7
--- /dev/null
+++ b/etc/APOLLO
@@ -0,0 +1,39 @@
+The Apollo has a bizarre operating system which does not permit
+Emacs to be dumped with preloaded pure Lisp code. Therefore, each
+time you start Emacs on this system, the standard Lisp code is loaded
+into it. Expect it to take a long time. You can prevent loading of
+the standard Lisp code by specifying the -nl switch. It must
+come at the beginning of the command line; only the -t and -batch
+switches may come before it.
+
+You must use m-apollo.h in the config.h file, together with
+s-bsd4.2.h.
+
+There is one remaining problem on the Apollo. You must replace
+the CPP line in src/Makefile with "CPP = /usr/lib/cpp".
+The C preprocessor lives there rather than in /lib/cpp because the
+Aegis OS uses the /lib directory as the repository for shared libraries.
+
+
+Here is a design for a method of dumping and reloading the relevant
+necessary impure areas of Emacs.
+
+On dumping, you need to dump only the array `pure' plus the
+locations that contain values of forwarded Lisp variables or that are
+protected for garbage collection. The former can be found by a
+garbage- collection-like technique, and the latter are in the
+staticprolist vector (see alloc.c for both things).
+
+Reloading would work in an Emacs that has just been started; except
+when a switch is specified to inhibit this, it would read the dump
+file and set all the appropriate locations. The data loaded must be
+relocated, but that's not hard. Those locations that are of type
+Lisp_Object can be found by a technique like garbage-collection, and
+those of them that point to storage can be relocated. The other data
+read from the file will not need to be relocated.
+
+The switch to inhibit loading the data base would be used when it
+is time to dump a new data base.
+
+This would take a few seconds, which is much faster than loading
+the Lisp code of Emacs from scratch.
diff --git a/etc/APPLE b/etc/APPLE
new file mode 100644
index 00000000000..0af08c7a406
--- /dev/null
+++ b/etc/APPLE
@@ -0,0 +1,57 @@
+
+@unnumbered Special Report: Apple's New Look and Feel
+
+You might have read about the new look-and-feel copyright lawsuit,
+Apple vs. Hewlett Packard and Microsoft. Apple claims the power to
+stop people from writing any program that works even vaguely like a
+Macintosh. If they and other look-and-feel plaintiffs triumph, they
+will use this new power over the public to put an end to free software
+that could substitute for commercial software.
+
+In the weeks after the suit was filed, USENET reverberated with
+condemnation for Apple. GNU supporters Richard Stallman, John Gilmore, and
+Paul Rubin decided to take action against Apple's no-longer-deserved
+reputation as a force for progress. Apple's reputation comes from having
+made better computers; but now, Apple is working to make all non-Apple
+computers worse. If this deprives the public of the future work of many
+companies, the harm done would be many times the good that any one company
+does. Our hope was that if the user community realizes how destructive
+Apple's present actions are, Apple would lose customers and have more
+trouble finding employees.
+
+Our method of action was to print 5000 buttons that say ``Keep Your Lawyers
+Off My Computer'' and hand them out at the West Coast Computer Faire. The
+center of the button shows the rainbow-apple logo with a Gigeresque mouth
+full of ferocious teeth. The picture was drawn by Etienne Suvasa, who also
+drew the cover for the GNU Emacs manual. We call the picture ``Apple's New
+Look and Feel''.
+
+We gave out nearly 4000 buttons at the show (saving the rest for
+afterwards). The result was a great success: the extent of anger at Apple
+was apparent to everyone at the show. Many of the invited speakers at the
+show wore our buttons, spoke about them, or even waved them from the
+podium. The press noticed this: at least one Macintosh user's magazine
+carried a photo of the button afterwards.
+
+Some of you may be considering using, buying, or recommending Macintoshes;
+you might even be writing programs for them or thinking about it. Please
+think twice and look for an alternative. Doing those things means more
+success for Apple, and this could encourage Apple to persist in its
+aggression. It also encourages other companies to try similar
+obstructionism.
+
+[It is because of this boycott that we don't include support for Macintosh
+Unix in GNU software.]
+
+You might think that your current project ``needs'' a Macintosh now. If
+you find yourself thinking this way, consider the far future. You probably
+plan to be alive a year or two from now, and working on some other project.
+You will want to get good computers for that, too. But an Apple monopoly
+could easily make the price of such computers at that time several times
+what it would otherwise be. Your decision to use some other kind of
+machine, or to defer your purchases now, might make sure that the machines
+your next project needs are affordable when you need them.
+
+Newspapers report that Macintosh clones will be available soon. If
+you must buy a Macintosh-like machine, buy a clone. Don't feed the
+lawyers!
diff --git a/etc/BABYL b/etc/BABYL
new file mode 100644
index 00000000000..3c0c3e16020
--- /dev/null
+++ b/etc/BABYL
@@ -0,0 +1,127 @@
+>From rlk@think.COM (Robert Krawitz) Mon Nov 30 10:56:46 1987
+
+Let's see if I remember my BNF for babyl files; this corresponds to
+version 5:
+
+
+File := <header>
+ <message>* ; Some say there must be at least one message.
+
+Header := Babyl Options:\n
+ <header-option>*
+ |^_
+
+Header-option := <header-token> ; See note [5]
+ : *
+ <value>
+
+header-token := [^\000-\017:\177-\377]* ; Not these characters [tab is OK]
+header-value := ditto, if a list, each element separated by a comma and
+ a space.
+
+message := \^L\n
+ [01], ; See note [1] below
+ ( <attribute>,)* ; Note space before and comma after token
+ ,
+ ( <label>,)* ; ditto, see note [4] below
+ \n
+ <header>* ; See note [1] and [2] below
+ *** EOOH ***\n
+ <header>* ; See note [2] below
+ \n
+ <body>
+ \^_
+
+attribute := unseen |
+ last | ; Not all programs implement this. It
+ ; generally only gets used internally, and
+ ; isn't written out to a file.
+ >last | ; Babyl uses this for a deleted message at the
+ ; end. It shouldn't be written out to a file.
+ deleted |
+ recent | ; Not all programs implement this. It refers
+ ; to a message in the last batch of new mail;
+ ; thus it probably shouldn't be written out to
+ ; a file during a normal save although it
+ ; makes sense to write it out in an emergency save.
+ filed |
+ answered |
+ forwarded |
+ redistributed |
+ badheader | ; Not all programs implement this
+ filed ; Not all programs implement this
+
+label := [^\000-\020,\177-\377]* ; No control chars,
+ ; whitespace, commas, rubout, or high bit set
+
+header := [^\000-\020:\177-\377]*:
+ <header-line>
+ <header-line>*
+
+header-line := [ \t][^\n]*\n ; Continuation lines must be indented
+
+body := (.*\n)* ; See note [3] below
+
+
+[1] A zero means that the headers have not been cleaned up,
+reprocessed, toggled, or whatever. In this case there should be no
+headers before the EOOH line. A one means that the headers have been
+reprocessed. In this case, the original headers will typically be
+before the EOOH line and the reformatted or whatever subset of headers
+that the user should see will be after it. Note that in this case
+it's permissible to garbage collect all headers before the EOOH line.
+No one's defined what it means to garbage collect SOME of the headers
+before this line, or what that means.
+
+[2] It's apparently permissible to add headers of the program's own
+choosing before the EOOH line. Or at least, Rmail does so (it caches
+a summary line) and nothing seems to object. There's no particular
+guarantee that something else won't step all over it, though. Headers
+after the EOOH line can be reformatted as the program wishes (e. g.
+indent the header lines to the same distance, canonicalize machine
+names) for display to the user. It's generally best for programs that
+read a babyl file to look at the headers before the EOOH line if they
+exist, since these should be untouched by the user. Remember, the
+user can edit anything after the EOOH line.
+
+[3] A \^_ at the beginning of a line should be quoted somehow. The
+normal way seems to be to decompose it into 2 characters: a ^ and a _.
+Strictly speaking, it doesn't always have to be, since the following
+text would have to be parsable as a message, but some programs don't
+try to use that much intelligence. Oh well.
+
+[4] Labels, or keywords as they are often called, are generally
+defined by the user, although it's not entirely impermissible for a
+program to use these for its own purpose (e. g. a keyword named
+RemindMe might be used to automatically find important messages).
+Some people also want these used to cache other state implemented by
+certain programs; this use is undefined. Note that all keywords used
+should be inserted in a header-option named Keywords:. Can a keyword
+have the same name as an attribute? Who knows? It's probably not a
+good idea, since some programs use the concept of <labels> =
+<keywords> + <attributes>. Sigh.
+
+[5] Some tokens are standardized in meaning. Common tokens are Mail
+inboxes, babyl file version number, which is currently 5, labels used
+in messages, window format for Zmail, anything else you want to be
+associated with a file. Be warned that labels should be a complete
+list of all user-defined keywords used in the file, so if you add a
+new label to a message, you should add it to this list. You should
+also have a Babyl version: 5 file attribute (look in a babyl file for
+details).
+
+Anyone know if there actually is a "formal" standard? This was done
+quickly from memory and a Zmail manual, but there are at least three
+programs around that use Babyl files (zmail, babyl, and emacs/rmail)
+and someone at SIPB was going to write a command-based mail reader
+similar to Unix Mail but operating on babyl files, and someone (of
+course not me :-)) should probably write xbabyl :-)
+
+References:
+
+ITS/Tops-20 INFO file on babyl (who wrote it? ECC? GZ?)
+
+Zmail manual (the MIT version was written by RMS; ECC wrote the
+section on Babyl file format)
+--
+
diff --git a/etc/CCADIFF b/etc/CCADIFF
new file mode 100644
index 00000000000..8fd780ffefb
--- /dev/null
+++ b/etc/CCADIFF
@@ -0,0 +1,159 @@
+Differences between GNU Emacs and CCA Emacs.
+Copyright (c) 1985 Richard M. Stallman
+
+ Permission is granted to anyone to make or distribute verbatim copies
+ of this document as received, in any medium, provided that the
+ copyright notice and permission notice are preserved,
+ and that the distributor grants the recipient permission
+ for further redistribution as permitted by this notice.
+
+* GNU Emacs Lisp vs CCA Elisp.
+
+GNU Emacs Lisp does not have a distinction between Lisp functions
+and Emacs functions, or between Lisp variables and Emacs variables.
+The Lisp and the editor are integrated. A Lisp function defined
+with defun is callable as an editor command if you put an
+interactive calling spec in it; for example,
+ (defun forward-character (n)
+ (interactive "p")
+ (goto-char (+ (point) n)))
+defines a function of one argument that moves point forward by
+a specified number of characters. Programs could call this function,
+as in (forward-character 6), or it could be assigned to a key,
+in which case the "p" says to pass the prefix numeric arg as
+the function's argument. As a result of this feature, you often
+need not have two different functions, one to be called by programs
+and another to read arguments from the user conveniently; the same
+function can do both.
+
+CCA Elisp tries to be a subset of Common Lisp and tries to
+have as many Common Lisp functions as possible (though it is still
+only a small fraction of full Common Lisp). GNU Emacs Lisp
+is somewhat similar to Common Lisp just because of my Maclisp
+and Lisp Machine background, but it has several distinct incompatibilities
+in both syntax and semantics. Also, I have not attempted to
+provide many Common Lisp functions that you could write in Lisp,
+or others that provide no new capability in the circumstances.
+
+GNU Emacs Lisp does not have packages, readtables, or character objects
+(it uses integers to represent characters).
+
+On the other hand, windows, buffers, relocatable markers and processes
+are first class objects in GNU Emacs Lisp. You can get information about them
+and do things to them in a Lispy fashion. Not so in CCA Emacs.
+
+In GNU Emacs Lisp, you cannot open a file and read or write characters
+or Lisp objects from it. This feature is painful to support, and
+is not fundamentally necessary in an Emacs, because instead you
+can read the file into a buffer, read or write characters or
+Lisp objects in the buffer, and then write the buffer into the file.
+
+On the other hand, GNU Emacs Lisp does allow you to rename, delete, add
+names to, and copy files; also to find out whether a file is a
+directory, whether it is a symbolic link and to what name, whether
+you can read it or write it, find out its directory component,
+expand a relative pathname, find completions of a file name, etc.,
+which you cannot do in CCA Elisp.
+
+GNU Emacs Lisp uses dynamic scope exclusively. This enables you to
+bind variables which affect the execution of the editor, such as
+indent-tabs-mode.
+
+GNU Emacs Lisp code is normally compiled into byte code. Most of the
+standard editing commands are written in Lisp, and many are
+dumped, pure, in the Emacs that users normally run.
+
+GNU Emacs allows you to interrupt a runaway Lisp program with
+Control-g.
+
+* GNU Emacs Editing Advantages
+
+GNU Emacs is faster for many things, especially insertion of text
+and file I/O.
+
+GNU Emacs allows you to undo more than just the last command
+with the undo command (C-x u, or C-_). You can undo quite a ways back.
+Undo information is separate for each buffer; changes in one buffer
+do not affect your ability to undo in another buffer.
+
+GNU Emacs commands that want to display some output do so by putting
+it in a buffer and displaying that buffer in a window. This
+technique comes from Gosling Emacs. It has both advantages and
+disadvantages when compared with the technique, copied by CCA Emacs
+from my original Emacs which inherited it from TECO, of having "type
+out" which appears on top of the text in the current window but
+disappears automatically at the next input character.
+
+GNU Emacs does not use the concept of "subsystems". Instead, it uses
+highly specialized major modes. For example, dired in GNU Emacs has
+the same commands as dired does in other versions of Emacs, give or
+take a few, but it is a major mode, not a subsystem. The advantage
+of this is that you do not have to "exit" from dired and lose the
+state of dired in order to edit files again. You can simply switch
+to another buffer, and switch back to the dired buffer later. You
+can also have several dired buffers, looking at different directories.
+
+It is still possible to write a subsystem--your own command loop--
+in GNU Emacs, but it is not recommended, since writing a major mode
+for a special buffer is better.
+
+Recursive edits are also rarely used, for the same reason: it is better
+to make a new buffer and put it in a special major mode. Sending
+mail is done this way.
+
+GNU Emacs expects everyone to use find-file (C-x C-f) for reading
+in files; its C-x C-v command kills the current buffer and then finds
+the specified file.
+
+As a result, users do not need to think about the complexities
+of subsystems, recursive edits, and various ways to read in files
+or what to do if a buffer contains changes to some other file.
+
+GNU Emacs uses its own format of tag table, made by the "etags"
+program. This format makes finding a tag much faster.
+
+Dissociated Press is supported.
+
+
+* GNU Emacs Editing Disadvantages.
+
+GNU Emacs does not display the location of the mark.
+
+GNU Emacs does not have a concept of numbers of buffers,
+or a permanent ordering of buffers, or searching through multiple
+buffers. The tags-search command provides a way to search
+through several buffers automatically.
+
+GNU Emacs does not provide commands to visit files without
+setting the buffer's default directory. Users can write such
+commands in Lisp by copying the code of the standard file
+visiting commands and modifying them.
+
+GNU Emacs does not support "plus options" in the command
+arguments or in buffer-selection commands, except for line numbers.
+
+GNU Emacs does not support encryption. Down with security!
+
+GNU Emacs does not support replaying keystroke files,
+and does not normally write keystroke files.
+
+
+* Neutral Differences
+
+GNU Emacs uses TAB, not ESC, to complete file names, buffer names,
+command names, etc.
+
+GNU Emacs uses ESC to terminate searches, instead of
+the C-d uses by CCA Emacs. (Actually, this character is controlled
+by a parameter in GNU Emacs.) C-M-s in GNU Emacs is an interactive
+regular expression search, but you can get to a noninteractive
+one by typing ESC right after the C-M-s.
+
+In GNU Emacs, C-x s asks, for each modified file buffer, whether
+to save it.
+
+GNU Emacs indicates line continuation with "\" and line
+truncation (at either margin) with "$".
+
+The command to resume a tags-search or tags-query-replace in
+GNU Emacs is Meta-Comma.
diff --git a/etc/CHARACTERS b/etc/CHARACTERS
new file mode 100644
index 00000000000..9c4f7b61845
--- /dev/null
+++ b/etc/CHARACTERS
@@ -0,0 +1,54 @@
+ Ideas for extending GNU Emacs to deal with arbitrary character sets.
+
+I would like GNU Emacs to be extended to handle all the world's alphabets
+and word signs. I don't expect to have time to do such a thing in the next
+few years, so here are my ideas on the best way to do it.
+
+* Each graphic is represented by a sequence of ordinary 8-bit characters.
+
+* All the characters that make up such a sequence have codes >= 0200.
+
+* The first character of such a sequence is between 0200 and 0237.
+
+* The remaining characters of such a sequence are all 0240 or higher.
+
+* The first character of the sequence determines the number of characters
+in the sequence. Thus, 0200...0207 could start two-character sequences,
+0210...0227 could start three-character sequences, and 0230 could start
+four-character sequences. (Codes 0231...0237 would be reserved.)
+
+* Several common alphabets, and some mathematical symbols, would get
+two-character sequences. (Probably Greek, Russian, Hebrew(?), Arabic(?),
+Korean, and Japanese kana). The remaining alphabets, and some versions of
+Chinese, would get three-character sequences. Other sets of Chinese
+characters would get four-character sequences.
+
+Each country that uses Chinese characters has its own standard character
+set, and it is not easy to correlate them to avoid overlap. So there may
+need to be several sets of Chinese characters. That is why they need so
+much code space.
+
+True support for Hebrew and Arabic requires dealing with the problem of
+writing direction for mixed text; I don't know what to do for that.
+
+* The functions that use syntax table would determine the
+syntax of a sequence from its first character.
+
+* Functions in indent.c for computing widths and columns would
+determine the width of a sequence from its first character.
+So would display routines.
+
+* Only a few other editing routines would need any change. In
+particular, searching and regexp matching might not need any change.
+
+* Most of the work required would be in redisplay. The only case that
+needs to be supported is with X windows, since ordinary terminals
+can't display all these characters anyway.
+
+* There might need to be code to translate files from this format
+to whatever format is typically stored on disk.
+
+
+I would be very unhappy with half-measures, such as support for
+Japanese only.
+
diff --git a/etc/COOKIES b/etc/COOKIES
new file mode 100644
index 00000000000..d1c4ece914d
--- /dev/null
+++ b/etc/COOKIES
@@ -0,0 +1,157 @@
+[Someone sent this in from California, and we decided to extend
+our campaign against information hoarding to recipes as well
+as software. (Recipes are the closest thing, not involving computers,
+to software.)
+
+The story appears to be a myth, according to the Chicago Tribune,
+which says that Mrs Fields Cookies hoards the information completely.
+Therefore, this recipe can be thought of as a compatible replacement.
+We have reports that the cookies it makes are pretty good.]
+
+Someone at PG&E called the Mrs. Fields Cookie office
+and requested the recipe for her cookies. They asked
+her for her charge card number, and she gave it to them
+thinking the cost would be $15 to $25. It turned out
+to be $200!
+
+Therefore, this person is giving the recipe to anyone
+and everyone she knows (and doesn't know) so that
+someone can get use of her $200. Anyway, just keep
+passing it on.
+
+Cream together: 2 cups butter
+ 2 cups sugar
+ 2 cups brown sugar
+
+Add: 4 eggs
+ 2 tsp. vanilla
+
+Mis together in
+separate bowl: 4 cups flour
+ 5 cups oatmeal (put small
+ amounts of oatmeal in blender until it turns to
+ powder. Measure out 5 cups of oatmeal and only
+ "powderize" that, NOT 5 cups "powderized" oatmeal)
+
+ 1 tsp salt
+ 2 tsp baking powder
+ 2 tsp baking soda
+
+Mix: All of the above
+
+Add: 24 oz. bag of chocolate chips and
+ 1 finely grated 8 oz Hershey bar (plain)
+
+Add: 3 cups chopped nuts (any kind)
+
+Bake on greased cookie sheet (make golf ball sized balls) and
+bake about two inches apart. Bake at 350 degrees for 8 - 10
+minutes. DO NOT OVERBAKE. Makes 112.
+
+From: ucdavis!lll-lcc!hplabs!parcvax!bane@ucbvax.berkeley.edu (John R. Bane)
+Subject: Re: free cookie foundation?
+
+Hi! I "stole" your very expensive cookie recipe off the net. If you
+want to send me your SnailMail address, I'll be glad to send you a
+dollar (I would like to suggest this to the net, but I think there is
+some netiquette rule against asking for money - or is that only money
+for oneself?) to help defray the cost (it's not much, but if EVERYone
+who took the recipe sent you a dollar, it would help).
+
+Here also is another cookie recipe which I'm very fond of.
+
+Makes 6-8 dozen
+Bake at 375 degrees for ~10 min.
+
+Cream together:
+
+1 cup shortening (I use Weight Watcher's Reduced Calorie Margarine!)
+1/4 cup peanut butter (I recommend the non-sugared kind)
+1/2 cup sugar
+1/2 cup brown sugar
+2 eggs
+1 teaspoon vanilla
+
+Add:
+
+1/2 cup flour
+1 teaspoon soda
+1/2 teaspoon salt
+2 cups rolled oats (I use the 5-min variety)
+1-2 cups chocolate chips (I use 2 cups semi-sweet - ummmm!)
+1 cup nuts (I use pecan pieces - don't get them crushed, or the extra
+ oil will make greasy cookies)
+1 cup shredded or flaked coconut
+
+(The nuts were listed as optional and I added the coconut myself, but
+I really love them there! You could also add things like m&m's, or
+raisons (I don't care for raisons in cookies, but you might). I've
+always wanted to try banana chips.)
+
+Mix well. Drop by teaspoonfuls on greased cookie sheet (I use pam).
+Bake at 375 degrees for approx. 10 min.
+
+My aunt found this recipe in an Amish book called something like
+"Eating Well When The Whole World Is Starving," and although I thought
+a cookie recipe was a bit odd for a book like that, they are about the
+healthiest a cookie is ever likely to get.
+
+They are also very easy to make (no blending, sifting, rolling, etc.)
+and extrememly delicious. I get rave reviews and recipe requests whenever
+I make them.
+
+ - rene
+
+Chocolate Chip Cookies - Glamorous, crunchy, rich with chocolate bits & nuts.
+
+Also known as "Toll House" Cookies ... from Kenneth and Ruth Wakefield's
+charming New England Toll House on the outskirts of Whitman, Massachusetts.
+These cookies were first introduced to American homemakers in 1939 through
+our series of radio talks on "Famous Foods From Famous Eating Places."
+
+Mix Thoroughly :
+ 2/3 cup soft shortening ( part butter )
+ 1/2 cup granulated sugar
+ 1/2 cup brown sugar ( packed )
+ 1 egg
+ 1 tsp vanilla
+
+Sift together and stir in :
+ 1-1/2 cups sifted flour (*)
+ 1/2 tsp soda
+ 1/2 tsp salt
+
+Stir in :
+ 1/2 cup cut-up nuts
+ 6 oz package of semi-sweet chocolate pieces ( about 1-1/4 cups )
+
+
+(*) for a softer, more rounded cookie, use 1-3/4 cups sifted flour.
+
+
+Drop rounded teaspoonfuls about 2" apart on ungreased baking sheet. Bake until
+delicately browned ... cookies should still be soft. Cool slightly before you
+remove them from the baking sheet.
+
+Temperature: 375 F. ( modern oven )
+Time: bake 8 - 10 minutes
+Amount: 4 - 5 dozen 2" cookies
+
+
+=====
+
+Personal comments :
+
+I find it tastes better with a mixture of shortening and butter, as they say.
+
+You don't need << all >> of that sugar, and it can be whatever color you want.
+
+The nuts are optional. Feel free to play with the recipe. I put oatmeal in it,
+reducing flour accordingly, and sometimes cinnamon.
+
+I also find it useful to grease the cookie sheets.
+
+I think I'm going to go bake some now ...
+
+-- richard
+
diff --git a/etc/COPYING b/etc/COPYING
new file mode 100644
index 00000000000..9a170375811
--- /dev/null
+++ b/etc/COPYING
@@ -0,0 +1,249 @@
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 1, February 1989
+
+ Copyright (C) 1989 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The license agreements of most software companies try to keep users
+at the mercy of those companies. By contrast, our General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. The
+General Public License applies to the Free Software Foundation's
+software and to any other program whose authors commit to using it.
+You can use it for your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Specifically, the General Public License is designed to make
+sure that you have the freedom to give away or sell copies of free
+software, that you receive source code or can get it if you want it,
+that you can change the software or use pieces of it in new free
+programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of a such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must tell them their rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any program or other work which
+contains a notice placed by the copyright holder saying it may be
+distributed under the terms of this General Public License. The
+"Program", below, refers to any such program or work, and a "work based
+on the Program" means either the Program or any work containing the
+Program or a portion of it, either verbatim or with modifications. Each
+licensee is addressed as "you".
+
+ 1. You may copy and distribute verbatim copies of the Program's source
+code as you receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice and
+disclaimer of warranty; keep intact all the notices that refer to this
+General Public License and to the absence of any warranty; and give any
+other recipients of the Program a copy of this General Public License
+along with the Program. You may charge a fee for the physical act of
+transferring a copy.
+
+ 2. You may modify your copy or copies of the Program or any portion of
+it, and copy and distribute such modifications under the terms of Paragraph
+1 above, provided that you also do the following:
+
+ a) cause the modified files to carry prominent notices stating that
+ you changed the files and the date of any change; and
+
+ b) cause the whole of any work that you distribute or publish, that
+ in whole or in part contains the Program or any part thereof, either
+ with or without modifications, to be licensed at no charge to all
+ third parties under the terms of this General Public License (except
+ that you may choose to grant warranty protection to some or all
+ third parties, at your option).
+
+ c) If the modified program normally reads commands interactively when
+ run, you must cause it, when started running for such interactive use
+ in the simplest and most usual way, to print or display an
+ announcement including an appropriate copyright notice and a notice
+ that there is no warranty (or else, saying that you provide a
+ warranty) and that users may redistribute the program under these
+ conditions, and telling the user how to view a copy of this General
+ Public License.
+
+ d) You may charge a fee for the physical act of transferring a
+ copy, and you may at your option offer warranty protection in
+ exchange for a fee.
+
+Mere aggregation of another independent work with the Program (or its
+derivative) on a volume of a storage or distribution medium does not bring
+the other work under the scope of these terms.
+
+ 3. You may copy and distribute the Program (or a portion or derivative of
+it, under Paragraph 2) in object code or executable form under the terms of
+Paragraphs 1 and 2 above provided that you also do one of the following:
+
+ a) accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of
+ Paragraphs 1 and 2 above; or,
+
+ b) accompany it with a written offer, valid for at least three
+ years, to give any third party free (except for a nominal charge
+ for the cost of distribution) a complete machine-readable copy of the
+ corresponding source code, to be distributed under the terms of
+ Paragraphs 1 and 2 above; or,
+
+ c) accompany it with the information you received as to where the
+ corresponding source code may be obtained. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form alone.)
+
+Source code for a work means the preferred form of the work for making
+modifications to it. For an executable file, complete source code means
+all the source code for all modules it contains; but, as a special
+exception, it need not include source code for modules which are standard
+libraries that accompany the operating system on which the executable
+file runs, or for standard header files or definitions files that
+accompany that operating system.
+
+ 4. You may not copy, modify, sublicense, distribute or transfer the
+Program except as expressly provided under this General Public License.
+Any attempt otherwise to copy, modify, sublicense, distribute or transfer
+the Program is void, and will automatically terminate your rights to use
+the Program under this License. However, parties who have received
+copies, or rights to use copies, from you under this General Public
+License will not have their licenses terminated so long as such parties
+remain in full compliance.
+
+ 5. By copying, distributing or modifying the Program (or any work based
+on the Program) you indicate your acceptance of this license to do so,
+and all its terms and conditions.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the original
+licensor to copy, distribute or modify the Program subject to these
+terms and conditions. You may not impose any further restrictions on the
+recipients' exercise of the rights granted herein.
+
+ 7. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of the license which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+the license, you may choose any version ever published by the Free Software
+Foundation.
+
+ 8. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to humanity, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these
+terms.
+
+ To do so, attach the following notices to the program. It is safest to
+attach them to the start of each source file to most effectively convey
+the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19xx name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the
+appropriate parts of the General Public License. Of course, the
+commands you use may be called something other than `show w' and `show
+c'; they could even be mouse-clicks or menu items--whatever suits your
+program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ program `Gnomovision' (a program to direct compilers to make passes
+ at assemblers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/etc/ChangeLog b/etc/ChangeLog
new file mode 100644
index 00000000000..d21a47a349b
--- /dev/null
+++ b/etc/ChangeLog
@@ -0,0 +1,294 @@
+Wed Oct 21 18:21:39 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * Makefile: Emacstool and other Sun-only targets replaced.
+ * emacstool.c: New file.
+
+Sat Aug 22 03:09:48 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * emacsclient.c (main): Set IPC_CREAT in msgget call.
+
+Thu Aug 20 01:09:32 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * etags.c (TEX_funcs): Keep just 1 of two redundant nested loops.
+ (TEX_decode_env): Make `tab' one element longer.
+
+Sat May 9 16:24:08 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * etags.c (getit): Allow _ and $ in fortran symbol.
+
+Thu May 7 16:11:26 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * movemail.c [POP]: Get user name via getpwuid.
+
+Sat Mar 28 15:59:12 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * movemail.c: Allocate tempname dynamically.
+
+Sun Mar 22 23:21:21 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * server.c: Include sys/types.h before signal.h.
+
+Thu Mar 12 16:45:36 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * termcap.dat: Added vt101*, vt102*, vt131* and vt300.
+
+Sat Jan 25 16:20:41 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * env.c: Include errno.h.
+
+Sun Jan 19 11:29:00 1992 (Eric Youngdale at youngdale@v6550c.nrl.navy.mil)
+
+ * etags-vmslib.c (fn_exp): Add type cast.
+
+Tue Dec 31 16:16:05 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * server.c: Include sys/signal.h before config.h.
+
+Sat Dec 7 17:04:17 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * movemail.c: Copied from Emacs 19.
+ (pfatal_and_delete): New function.
+ (main, popmail): Use it.
+ (popmail): Close output before deleting messages.
+ Check for error on close and on fsync.
+ Use `fatal' where appropriate.
+ (main): Remove (void).
+ (MAIL_USE_MMDF): New compilation flag
+ (main): Report failure of flock.
+
+Fri Oct 25 14:43:33 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * server.c (msgcatch): Declare return type void.
+
+ * make-docfile.c: Fix comment on #endif.
+
+Tue Sep 17 18:15:42 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * etags.c (main): Don't make actions depend on programmer name.
+
+Sat Sep 14 01:42:39 1991 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * etags.c (C_entries): Clear tydef and next_token_is_func at start.
+ (consider_token): Move next_token_is_func to global.
+
+Mon Sep 2 16:22:04 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * server.c, emacsclient.c [not SERVER_HOME_DIR]:
+ Include host name in the name of the socket.
+
+Tue Jul 30 17:03:41 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * wakeup.c: Terminate if parent goes away.
+
+Fri Mar 29 19:00:10 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * server.c [USG]: Terminate if msgrcv fails.
+
+Sun Mar 3 22:05:52 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * server.c [BSD]: Check for errors on stdin after scanf.
+
+Tue Feb 26 15:55:07 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * etags.c (TEX_mode): Skip comment line at beg of file.
+
+Mon Dec 31 17:52:55 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * refcard.tex: Change am fonts to cm.
+
+Thu Nov 29 17:34:14 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * movemail.c (mbx_delimit_begin): Put space before `unseen'.
+
+Sun Nov 18 17:09:07 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * server.c, emacsclient.c [BSD]: Put socket in /tmp.
+
+Tue Nov 13 00:01:54 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * movemail.c (error): Handle 3 args.
+ (main): Don't check input access if using pop.
+
+Tue Oct 30 12:38:39 1990 David J. MacKenzie (djm at apple-gunkies)
+
+ * emacs.1: Give the mouse bindings for X11 instead of X10.
+
+Tue Oct 16 14:04:05 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * etags.c (find_entries): Check for numbers after Scheme suffix.
+
+Sun Oct 14 18:46:21 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * termcap.dat (vt200-80): Fix ke and ks to frob flag 1.
+
+Tue Oct 9 15:22:16 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * Makefile (nemacstool, xvetool): New targets.
+
+Wed Sep 26 18:42:18 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * emacsclient.c (errno): Declare it explicitly.
+
+Tue Aug 14 21:34:50 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * emacsclient.c [USG]: Pass msgsnd only 4 args.
+
+Tue Aug 7 13:17:58 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * Makefile (clean): New target.
+
+Sun Jul 8 18:18:00 1990 Richard Stallman (rms at geech)
+
+ * emacsclient.c [BSD]: Include errno.h.
+ Declare sys_nerr and sys_errlist.
+
+Wed Jul 4 15:40:33 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * wakeup.c: New file.
+ * Makefile (wakeup): New rule.
+
+Wed May 30 15:40:59 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * emacsclient.c: Print program name in error messages.
+ Handle failure of getwd.
+ Handle +LINE arguments in SYSVIPC case.
+ These are most of the changes already in the version 19 file.
+
+Mon May 28 21:54:59 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * loadst.c (main): Conditional to get load average on Apollo.
+
+Sun Dec 24 23:54:28 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * etags.c (readline): Separate out init of `pend'.
+
+Thu Jun 15 12:53:43 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * movemail.c [USG]: Define F_OK, etc., if not in header.
+
+Fri May 12 22:08:09 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * etags.c (readline): Split call to xrealloc for 3b1 cc bug.
+
+Tue Apr 18 21:31:25 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * loadst.c: on bsd4.3, use gettimeofday instead of CPUSTATES.
+
+Thu Mar 16 13:43:07 1989 Randall Smith (randy at sugar-bombs.ai.mit.edu)
+
+ * MACHINES: m-sequent.h works for symmetry also.
+
+Mon Mar 13 17:03:06 1989 Randall Smith (randy at sugar-bombs.ai.mit.edu)
+
+ * MACHINES: Added note mentioning m-news3.0.h.
+
+Tue Feb 21 12:58:55 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * movemail.c: On sysv, include unistd.h.
+
+Tue Jan 3 13:29:46 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * movemail.c: Check access before doing real work.
+ Check that outfile is in a writable directory.
+ On fatal error, delete the lock file.
+
+Fri Dec 30 16:37:27 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * movemail.c: Use `access' to check input and output files.
+
+Wed Dec 28 23:16:28 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * emacsclient.c [USG]: Don't append cwd if abs pathname is spec'd.
+
+Wed Nov 30 15:21:13 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * movemail.c: Do fsync before closing output.
+
+Tue Nov 29 09:59:54 1988 Richard Mlynarik (mly at pickled-brain.ai.mit.edu)
+
+ * movemail.c: Better error message when can't create tempname.
+ This file needs a great deal of extra error-checking and lucid reporting...
+
+Tue Nov 15 10:00:21 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * movemail.c: Close output and check errors before deleting input.
+
+Thu Aug 4 19:42:45 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * emacsclient.c: Args like +DIGITS are passed through unchanged.
+
+Tue Jul 12 22:08:00 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * server.c: If both BSD and HAVE_SYSVIPC, use the latter.
+ * emacsclient.c: Likewise.
+ In the HAVE_SYSVIPC alternative, if BSD, use getwd instead of getcwd.
+
+Thu Jun 23 08:40:53 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * etags.c: Handle `typedef struct foo {' (price@mcc.com).
+ (istoken) New string-comparison macro.
+ (consider_token): New arg `level'. New state `tag_ok' in `tydef'.
+
+Tue Jun 14 04:25:58 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * etags.c: Changes for VMS.
+ Always define ETAGS on VMS.
+ Define macros GOOD and BAD for success and failure exit codes.
+ (begtk, intk): Allow `$' in identifiers
+ (main): Don't support -B, -F or -u on VMS.
+ Alternate loop for scanning filename arguments.
+ (system): Delete definition of this function.
+
+ * etags-vmslib.c (system): Undefine this; VMS now provides it.
+
+Wed Jun 8 08:18:21 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * loadst.c: Prevent multiple-def errors on BSD and BSD4_3
+ around include of param.h. (Like fns.c.)
+
+Mon May 16 01:06:26 1988 Richard Stallman (rms at frosted-flakes.ai.mit.edu)
+
+ * loadst.c (load_average): Move load-average code to this new fn.
+ Add conditionals to compute load ave on UMAX.
+
+Sat May 14 01:24:53 1988 Richard Stallman (rms at lucky-charms.ai.mit.edu)
+
+ * loadst.c: Change DK_HEADER_FILE to DKSTAT_HEADER_FILE
+ with opposite sense.
+
+Fri May 13 18:09:39 1988 Chris Hanson (cph at kleph)
+
+ * emacsclient.c: Delete references to unused variable `out'. This
+ caused a bus error when used under hp-ux.
+
+Fri May 6 10:42:31 1988 Richard Stallman (rms at frosted-flakes.ai.mit.edu)
+
+ * loadst.c: Control dk.h conditional with DK_HEADER_FILE.
+
+Wed May 4 16:08:43 1988 Richard Stallman (rms at rice-krispies.ai.mit.edu)
+
+ * etags.c (find_entries): `.t' or `.sch' means scheme code.
+
+Fri Apr 29 00:22:26 1988 Richard Stallman (rms at frosted-flakes.ai.mit.edu)
+
+ * loadst.c: Add BSD4_3 conditional for file dk.h instead of dkstat.h.
+
+Thu Apr 28 08:55:46 1988 Richard Stallman (rms at frosted-flakes.ai.mit.edu)
+
+ * movemail.c: #undef close, since config can #define it on V.3.
+ * emacsclient.c, fakemail.c, loadst.c, server.c: likewise.
+
+Tue Apr 26 07:33:01 1988 Richard Stallman (rms at lucky-charms.ai.mit.edu)
+
+ * etags.c (TEX_mode, etc.): Remove superfluous backslashes from
+ invalid escape sequences such as `\{'.
+
+ * loadst.c: Add `sequent' conditional for file dk.h.
+
+Sun Mar 20 13:17:13 1988 Richard M. Stallman (rms at wilson)
+
+ * server.c [not BSD and not HAVE_SYSVIPC]: fix error message.
+
+ * loadst.c (main) [XENIX]: use /usr/spool/mail, not /usr/mail.
+
+
diff --git a/etc/DEBUG b/etc/DEBUG
new file mode 100644
index 00000000000..2fc878234c5
--- /dev/null
+++ b/etc/DEBUG
@@ -0,0 +1,113 @@
+Debugging GNU Emacs
+Copyright (c) 1985 Richard M. Stallman.
+
+ Permission is granted to anyone to make or distribute verbatim copies
+ of this document as received, in any medium, provided that the
+ copyright notice and permission notice are preserved,
+ and that the distributor grants the recipient permission
+ for further redistribution as permitted by this notice.
+
+ Permission is granted to distribute modified versions
+ of this document, or of portions of it,
+ under the above conditions, provided also that they
+ carry prominent notices stating who last changed them.
+
+On 4.2 you will probably find that dbx does not work for
+debugging GNU Emacs. For one thing, dbx does not keep the
+inferior process's terminal modes separate from its own.
+For another, dbx does not put the inferior in a separate
+process group, which makes trouble when an inferior uses
+interrupt input, which GNU Emacs must do on 4.2.
+
+dbx has also been observed to have other problems,
+such as getting incorrect values for register variables
+in stack frames other than the innermost one.
+
+The Emacs distribution now contains GDB, the new source-level
+debugger for the GNU system. GDB works for debugging Emacs.
+GDB currently runs on vaxes under 4.2 and on Sun 2 and Sun 3
+systems.
+
+
+** Some useful techniques
+
+`Fsignal' is a very useful place to stop in.
+All Lisp errors go through there.
+
+It is useful, when debugging, to have a guaranteed way
+to return to the debugger at any time. If you are using
+interrupt-drived input, which is the default, then Emacs is using
+RAW mode and the only way you can do it is to store
+the code for some character into the variable stop_character:
+
+ set stop_character = 29
+
+makes Control-] (decimal code 29) the stop character.
+Typing Control-] will cause immediate stop. You cannot
+use the set command until the inferior process has been started.
+Put a breakpoint early in `main', or suspend the Emacs,
+to get an opportunity to do the set command.
+
+If you are using cbreak input (see the Lisp function set-input-mode),
+then typing Control-g will cause a SIGINT, which will return control
+to the debugger immediately unless you have done
+
+ ignore 3 (in dbx)
+or handle 3 nostop noprint (in gdb)
+
+You will note that most of GNU Emacs is written to avoid
+declaring a local variable in an inner block, even in
+cases where using one would be the cleanest thing to do.
+This is because dbx cannot access any of the variables
+in a function which has even one variable defined in an
+inner block. A few functions in GNU Emacs do have variables
+in inner blocks, only because I wrote them before realizing
+that dbx had this problem and never rewrote them to avoid it.
+
+I believe that GDB does not have such a problem.
+
+
+** If GDB does not run and your debuggers can't load Emacs.
+
+On some systems, no debugger can load Emacs with a symbol table,
+perhaps because they all have fixed limits on the number of symbols
+and Emacs exceeds the limits. Here is a method that can be used
+in such an extremity. Do
+
+ nm -n temacs > nmout
+ strip temacs
+ adb temacs
+ 0xd:i
+ 0xe:i
+ 14:i
+ 17:i
+ :r -l loadup (or whatever)
+
+It is necessary to refer to the file `nmout' to convert
+numeric addresses into symbols and vice versa.
+
+It is useful to be running under a window system.
+Then, if Emacs becomes hopelessly wedged, you can create
+another window to do kill -9 in. kill -ILL is often
+useful too, since that may make Emacs dump core or return
+to adb.
+
+
+** Debugging incorrect screen updating.
+
+To debug Emacs problems that update the screen wrong, it is useful
+to have a record of what input you typed and what Emacs sent to the
+screen. To make these records, do
+
+(open-dribble-file "~/.dribble")
+(open-termscript "~/.termscript")
+
+The dribble file contains all characters read by Emacs from the
+terminal, and the termscript file contains all characters it sent to
+the terminal. The use of the directory `~/' prevents interference
+with any other user.
+
+If you have unreproduceable display problems, put those two expressions
+in your ~/.emacs file. When the problem happens, exit the Emacs that
+you were running, kill it, and rename the two files. Then you can start
+another Emacs without clobbering those files, and use it to examine them.
diff --git a/etc/DIFF b/etc/DIFF
new file mode 100644
index 00000000000..2a21ee8a562
--- /dev/null
+++ b/etc/DIFF
@@ -0,0 +1,779 @@
+How is this Emacs different from all other Emacses? -*-Outline-*-
+ (Actually, from Twenex Emacs)
+
+* Copyright (c) 1985 Richard M. Stallman
+
+ Permission is granted to anyone to make or distribute verbatim copies
+ of this document as received, in any medium, provided that the
+ copyright notice and permission notice are preserved,
+ and that the distributor grants the recipient permission
+ for further redistribution as permitted by this notice.
+
+ Permission is granted to distribute modified versions
+ of this document, or of portions of it,
+ under the above conditions, provided also that they
+ carry prominent notices stating who last changed them.
+
+* Fundamental concepts.
+
+** There is no concept of "typeout" in GNU Emacs.
+
+Any time that a command wants to display some output,
+it creates a buffer (usually with a name surrounded by asterisks)
+and displays it in a window.
+
+This provides some advantages:
+ you can edit some more while looking at the output;
+ you can copy parts of the output into other buffers.
+
+It also has a disadvantage that you must type a command
+in order to make the output disappear.
+You can use C-x 1 to get rid of all windows except the
+selected one. To be more selective, you can switch to
+the window you want to get rid of and then type C-x 0
+(delete-window).
+
+You also need to type a command to scroll the other
+window if not all the output fits in it. Meta-Control-v
+will usually do the job.
+
+** There is no concept of a "subsystem" in GNU Emacs.
+
+Where Twenex Emacs would use a subsystem, GNU Emacs
+instead creates a buffer and redefines commands in it.
+
+For example, when you send mail in GNU Emacs, you use
+a buffer named *mail* which is in Mail Mode. You can
+switch away from this buffer to any other buffer and
+resume normal editing; then switch back and resume
+composing mail. You do not have to "exit" from
+composing mail in order to do ordinary editing.
+
+This has many advantages, but it also has a disadvantage:
+Subsystems in Emacs tend to have "exit" commands that return you
+to whatever you were doing before entering the subsystem.
+In GNU Emacs the idea of what to return to is not well defined,
+so it is not clear what an "exit" command should do.
+The only way to "exit" in general is to type C-x b, C-x C-f, or
+some other suitable command to switch buffers. Some
+subsystem-like major modes, such as Info and Mail mode, provide
+commands to "exit" by switching to the previously selected
+buffer.
+
+** Files are always visited in their own buffers.
+
+Beginning users of Twenex Emacs were told how to edit
+using a single buffer and reading one file after another
+into that buffer. Use of a new buffer for each file was
+regarded as a more advanced mode.
+
+In GNU Emacs, the idea of using a single buffer for various
+files, one by one, has been dropped, given that the address
+space is expected to be large enough for many buffers. C-x
+C-f (find-file), which behaves nearly the same as in Twenex
+Emacs, is in GNU Emacs the canonical way for all users to
+visit files.
+
+Various commands need to read files into Emacs in the course
+of their execution. In Twenex Emacs the user must tell them
+whether to reuse buffers or create new ones, using the variable
+Tags Find File. In GNU Emacs, these commands always use
+C-x C-f.
+
+The command C-x C-v does still exist; it kills the current
+buffer and reads the specified file into a new buffer.
+It is equivalent to kill-buffer followed by find-file.
+
+Since there is no reusing of buffers, there is no point in
+calling the initial buffer "main". So the initial buffer
+in GNU Emacs is called "*scratch*" and is intended for typing
+Lisp expressions to be evaluated.
+
+** File name defaulting.
+
+GNU Emacs records a separate working directory for each buffer.
+Normally this is the directory on which the buffer's file
+resides; for buffers not visiting any file, it is copied from
+the buffer that was current when it was created. The current buffer's
+working directory can be printed with M-x pwd and set with M-x cd.
+
+GNU Emacs shows you the default directory by inserting it in
+the minibuffer when a file name is being read. You can type
+the filename you want at the end of the default as if the
+default were not there, or you can edit and alter the default.
+
+If you want file /lose/big when the default /foo/defaultdir/
+has been inserted for you, you need not kill the default; simply
+type at the end of it: /foo/defaultdir//lose/big. Such a file
+name is not ordinarily considered valid, but GNU Emacs
+considers it equivalent to /lose/big.
+
+Likewise, if you want file quux in your home directory, just add
+~/quux to the end of the supplied text, to get
+/foo/defaultdir/~/quux. GNU Emacs sees "/~" and throws away
+everything before the "~".
+
+You can refer to environment variables also within file names.
+$ followed by the environment variable name is replaced by the
+variable's value. The variable name should either be followed
+by a nonalphanumeric character (which counts as part of the
+file name) or be surrounded by braces {...} (which do not count
+as part of the file name). Thus, if variable USER has value "rms",
+"x/$USER-foo" is expanded to "x/rms-foo", and "x${USER}foo"
+is expanded to "xrmsfoo". Note that this substitution is not
+performed by the primitive file operation functions of GNU Emacs,
+but rather by the interactive file name reader. It is also
+available as a separate primitive, in the function
+substitute-in-file-name.
+
+** Exit commands C-z, C-x C-c and C-x C-z.
+
+There are two ways to exit GNU Emacs: killing and suspending.
+Killing is like what Control-c does to ordinary Unix programs.
+In GNU Emacs, you type C-x C-c to kill it. (This offers to
+save any modified file buffers before really killing Emacs.)
+Suspending is like what Control-z does to ordinary Unix programs.
+To suspend GNU Emacs, type C-x C-z, or type just C-z.
+Note that C-z suspends ordinary programs instantly, but
+Emacs does not suspend until it reads the C-z.
+
+Usually it is better to suspend: once a system is smart
+enough to have job control, why ever kill an editor?
+You'll just have to make a new one in a minute.
+This is why the convenient command C-z is provided for
+suspending.
+
+C-c is used as a prefix key for mode-specific commands and for users'
+own commands. We deliberately do not make C-c ever kill Emacs,
+because it should not be so easy to do something irreversible.
+
+** Quitting with C-g.
+
+If you type C-g while GNU Emacs is waiting for input, it
+is an ordinary command (which is defined to beep). If you
+type C-g while Lisp code is executing, it sets a flag which
+causes a special signal, nearly the same as an error, to
+happen atthe next safe place in Lisp execution. This usually
+has the effect of aborting the current command in a safe way.
+
+Because at times there have been bugs causing GNU Emacs to loop
+without checking the quit flag, a special feature causes
+GNU Emacs to be suspended immediately if you type a second C-g
+while the flag is already set. So you can always get out
+of GNU Emacs. Normally GNU Emacs recognizes and clears the quit flag
+quickly enough to prevent this from happening.
+
+When you resume GNU Emacs after a suspension caused by multiple C-g, it
+asks two questions before resuming execution:
+ Checkpoint?
+ Dump core?
+Answer each one with `y' or `n' and a Return.
+ `y' to Checkpoint? causes immediate auto-saving of all
+ buffers in which auto-saving is enabled.
+ `y' to Dump core? causes an illegal instruction to be executed.
+ This is to enable a wizard to figure out why GNU Emacs was
+ looping without checking for quits. Execution does not continue
+ after a core dump. If you answer `n', execution continues.
+With luck, GNU Emacs will ultimately check the quit flag,
+and quit normally. If not, and you type another C-g, it
+is suspended again.
+
+If GNU Emacs is not really hung, just slow, you may invoke
+the double C-g feature without really meaning to. Then just
+resume and answer `n' to both questions, and you will
+arrive at your former state. Presumably the quit you
+wanted will finish happening soon.
+
+These questions are not asked if you suspend GNU Emacs with the C-z
+command. Continuing GNU Emacs after a C-z takes you straight back
+into editing.
+
+** Undoing with C-x u or C-_
+
+You can undo many commands--up to 10,000 characters worth.
+Each time you type C-x u or C-_, another command or batch of change
+is undone. Undo information is stored per buffer, and the undo
+command always applies to the current buffer. A numeric argument
+serves as a repeat count.
+
+Consecutive self-inserting characters are undone in groups of twenty.
+
+** Different character set.
+
+GNU Emacs does not expect anyone ever to have a keyboard in which
+the Control key sets an independent bit which may accompany any
+character. The only control characters that can exist are the
+ASCII control characters.
+
+There is, as a result, no "control prefix" character.
+
+** Control-h is the Help character.
+
+I'm amazed it took me so long to get this idea. In Twenex Emacs, C-h
+and C-b are equivalent commands, making C-h redundant. C-h is not
+only easy to type, it is mnemonic for "Help". So in GNU Emacs the
+Help character is C-h.
+
+** Completion is done by TAB, not ESC.
+
+ESC in the minibuffer is a Meta prefix, same as at top level.
+
+** The string-argument reader is the minibuffer is an editor window.
+
+In GNU Emacs, the line at the bottom of the screen is the minibuffer.
+Commands that want string arguments always use this line to read them,
+and you can use the ordinary Emacs editing commands to edit the
+input. You can terminate input with Return because Return is defined
+as the exit-minibuffer command when in the minibuffer. If you
+are using a command that needs several arguments, terminate each
+one with Return. You cannot separate arguments with Escape
+the way you would in Twenex Emacs.
+
+The minibuffer window does not overlay other editor windows;
+it is a nearly ordinary editor window which lacks a mode line
+and is "turned off" when not in use. While it IS in use, you
+can switch windows to and from the minibuffer, kill text in other
+windows and yank in the minibuffer, etc.
+
+You can even issue a command that uses the minibuffer while in the
+minibuffer. This gets you temporarily into a recursive minibuffer.
+However, this is allowed only if you enable it, since it could be
+confusing for beginners.
+
+When you exit the minibuffer, the cursor immediately moves back to
+column zero of the minibuffer line, to show you that the exit
+command has been obeyed. The minibuffer contents remain on the screen
+until the end of the command, unless some other text is displayed there.
+
+A single Control-g exits the minibuffer.
+
+** There are no &'s or ^R's or spaces in function names.
+
+For example, the function which is called ^R Forward Word
+in Twenex Emacs is called forward-word in GNU Emacs.
+
+** The extension language is Lisp rather than TECO.
+
+Libraries must be written in Lisp. Meta-ESC reads a Lisp
+expression, evaluates it, and prints the result. Note that
+Meta-ESC is "disabled" by default, so that beginning users
+do not get into the minibuffer by accident in a confusing way.
+
+Data types available include integers (which double as characters),
+strings, symbols, lists, vectors, buffers, buffer pointers,
+windows, and process channels.
+
+For now, to learn about writing Lisp code for GNU Emacs, read some of
+the source code, which is in directory ../lisp. Also, all Lisp
+primitives have self-documentation you can read with C-h f.
+
+** Enabling the error handler.
+
+GNU Emacs has a Lisp debugger/stepper/trace package, but normally
+errors do not enter the debugger because that is slow, and unlikely to
+be of interest to most users. Set the variable debug-on-error to t to
+cause errors to invoke the debugger. Set debug-on-quit to cause quit
+signals (caused by C-g) to invoke the debugger.
+
+* Other changes.
+
+** More than two windows are allowed.
+
+C-x 2 splits the current window into two windows,
+ one above the other. Initially they both display
+ the same buffer.
+
+ C-x 2 now accepts a numeric argument to specify the number of
+ lines to give to the uppermost of the two windows it makes.
+
+C-x 0 kills the current window, making all others larger.
+C-x 1 kills all windows except the current one.
+C-x O switches to the next window down.
+ It rotates from the bottom one to the top one.
+ An argument serves as a repeat count; negative arguments
+ circulate in the reverse order.
+
+If the same buffer is displayed in several windows,
+changes made in it are redisplayed in all of them.
+
+** Side by side windows are supported.
+
+The command C-x 5 splits the current window into
+two side-by-side windows.
+
+C-x } makes the selected window ARG columns wider at the
+expense of the windows at its sides. C-x { makes the selected
+window ARG columns narrower. An argument to C-x 5 specifies
+how many columns to give to the leftmost of the two windows made.
+
+** Horizontal scrolling of the lines in a window is implemented.
+
+C-x < (scroll-left) scrolls all displayed lines left,
+with the numeric argument (default 1) saying how far to scroll.
+When the window is scrolled left, some amount of the beginning
+of each nonempty line is replaced by an "$".
+C-x > scrolls right. If a window has no text hidden at the left
+margin, it cannot be scrolled any farther right than that.
+When nonzero leftwards scrolling is in effect in a window.
+lines are automatically truncated at the window's right margin
+regardless of the value of the variable truncate-lines in the
+buffer being displayed.
+
+** Return key does not use up empty lines.
+
+In Twenex Emacs, the Return command advances over an existing
+empty line in some cases. In GNU Emacs, the Return command always
+makes inserts a newline. Twenex Emacs was designed at a time when
+most display terminals did not have the ability to scroll part
+of the screen, and using existing empty lines made redisplay faster.
+Nowadays, terminals that cannot scroll part of the screen are rare,
+so there is no need to make Return behave in a more complicated manner.
+
+** Help m.
+
+Typing C-h m displays documentation of the current major mode.,
+telling you what special commands and features are available
+and how to use them or get more information on them.
+
+This is simply the documentation, as a function, of the
+symbol which is the value of major-mode. Each major mode
+function has been given documentation intended for C-h m.
+
+** Display-hiding features.
+
+*** Hiding indented lines
+
+The command C-x $ with numeric argument N causes lines indented by N
+or more columns to become invisible. All you see is " ..." appended
+to the previous line, in place of any number of consecutive invisible
+lines.
+
+*** Outline Mode.
+
+Outline mode is designed for editing outline-structured
+files, such as this one.
+
+Headings should be lines starting with one or more asterisks.
+Major headings have one asterisk, subheadings two, etc.
+Lines not starting with asterisks are body text.
+
+You can make the body under a heading, or the subheadings
+under a heading, temporarily invisible, or visible again.
+Invisible lines are attached to the end of the previous line
+so they go with it if you kill it and yank it back.
+
+Commands:
+Meta-} next-visible-heading move by visible headings
+Meta-{ previous-visible-heading move by visible headings
+
+Meta-x hide-body make all body text invisible (not headings).
+Meta-x show-all make everything in buffer visible.
+
+The remaining commands are used when dot is on a heading line.
+They apply to some of the body or subheadings of that heading.
+C-c C-h hide-subtree make text and subheadings invisible.
+C-c C-s show-subtree make text and subheadings visible.
+C-c C-i show-children make direct subheadings visible.
+ No effect on body, or subheadings 2 or more levels down.
+ With arg N, affects subheadings N levels down.
+M-x hide-entry make immediately following body invisible.
+M-x show-entry make it visible.
+M-x hide-leaves make text under heading and under its subheadings invisible.
+ The subheadings remain visible.
+M-x show-branches make all subheadings at all levels visible.
+
+** C mode is fancy.
+
+C mode assumes that you put the initial open-brace of
+a function definition at the beginning of a line.
+If you use the popular indenting style that puts this
+open-brace at the end of a line containing a type declaration,
+YOU WILL LOSE: C mode does not know a function starts there.
+
+Open-brace at the beginning of a line makes it possible
+for C mode to find function boundaries with total reliability;
+something I consider vital and which cannot be done
+if the other style is used.
+
+The Tab command indents C code very cleverly.
+I know of only one cases in which Tab does not indent C code nicely:
+ Expressions continued over several lines with few parentheses.
+ Tab does not know the precedences of C operators, so it does
+ not know which lines of the expression should go where.
+ Using parentheses to indicate the nesting of operators
+ except within a line makes this problem go away.
+
+The indenting algorithm is entirely written in Lisp.
+
+Tab with a numeric argument in Twenex Emacs indents
+that many lines. It is different in GNU Emacs: it means
+to shift all the lines of a bracketed expression by the
+same amount as the line being indented. For example, if you have
+ if (foo)
+ {
+ hack ();
+ /** Well? */
+ }
+and type C-u Tab on the line with the open brace, you get
+ if (foo)
+ {
+ hack ();
+ /* Well? */
+ }
+from indenting the brace line and then shifting the
+lines within the braces rigidly with the first one.
+
+Meta-Control-q works as in Lisp mode; it should be
+used with dot just before a bracketed grouping, and
+indents each line INSIDE that grouping using Tab.
+If used instead of C-u Tab in the previous example, it makes
+ if (foo)
+ {
+ hack ();
+ /* Well? */
+ }
+
+Meta-Control-h puts mark at the end of the current C function
+and puts dot before it.
+
+Most other Meta-Control commands intended for Lisp expressions
+work usefully in C mode as well.
+
+** Meta-g (fill-region) is different.
+
+In Twenex Emacs, Meta-g fills the region with no paragraph
+boundaries except for blank and indented lines. In GNU Emacs,
+it divides the region into paragraphs in the same manner as
+Meta-], and fills each paragraph separately. There is also
+the function fill-region-as-paragraph which fills the region
+regarding at as a single paragraph regardless even of blank
+or indented lines.
+
+** Indented Text Mode instead of Edit Indented Text.
+
+Twenex Emacs has a command Edit Indented Text which temporarily
+alters some commands for editing indented paragraphs.
+GNU Emacs has instead a separate major mode, Indented Text Mode,
+which is different from ordinary Text Mode in just the same
+alterations. Specifically, in Indented Text Mode,
+Tab runs the function indent-relative, and auto filling indents
+the newly created lines.
+
+** But rectangle commands are implemented.
+
+C-x r stores the rectangle described by dot and mark
+into a register; it reads the register name from the keyboard.
+C-x g, the command to insert the contents of a register,
+can be used to reinsert the rectangle elsewhere.
+
+Other rectangle commands include
+ open-rectangle:
+ insert a blank rectangle in the position and size
+ described by dot and mark, at its corners;
+ the existing text is pushed to the right.
+ clear-rectangle:
+ replace the rectangle described by dot ane mark
+ with blanks. The previous text is deleted.
+ delete-rectangle:
+ delete the text of the specified rectangle,
+ moving the text beyond it on each line leftward.
+ kill-rectangle
+ like delete-rectangle but also stores the text of
+ the rectangle in the "rectangle kill buffer".
+ More precisely, it stores the text as a list of strings
+ (one string for each line) in the variable killed-rectangle.
+ yank-rectangle
+ inserts the text of the last killed rectangle.
+ extract-rectangle and delete-extract-rectangle
+ these functions return the text of a rectangle
+ as a list of strings. They are for use in writing
+ other functions that operate on rectangles.
+
+** Keyboard Macros
+
+The C-x ( command for defining a keyboard macro can in GNU Emacs
+be given a numeric argument, which means that the new macro
+starts out not empty but rather as the same as the last
+keyboard macro entered. In addition, that last keyboard
+macro is replayed when the C-x ( is typed. C-x ( with an
+argument is thus equivalent to typing plain C-x ( and then
+retyping the last keyboard macro entered.
+
+The command write-kbd-macro and append-kbd-macro can be used to
+save a keyboard macro definition in a file. It is represented as
+a Lisp expression which, when evaluated, will define the keyboard
+macro. write-kbd-macro writes the specified file from scratch,
+whereas append-kbd-macro adds to any existing text in the file.
+Both expect the keyboard macro to be saved to be specified by
+name; this means you must use the command name-last-kbd-macro to
+give the macro a name before you can save it.
+
+** The command to resume a terminated tags-search or tags-query-replace
+
+is Meta-comma in GNU Emacs.
+
+** Auto Save is on by default.
+
+Auto Save mode is enabled by default in all buffers
+that are visiting files.
+
+The file name used for auto saving is made by prepending
+"#" to the file name visited.
+
+** Backup files.
+
+Since Unix stupidly fails to have file version numbers,
+GNU Emacs compensates slightly in the customary fashion:
+when a file is modified and saved for the first time in
+a particular GNU Emacs run, the original file is renamed,
+appending "~" to its name. Thus, foo.c becomes foo.c~.
+
+Emacs can also put a version number into the name of the backup file,
+as in foo.c.~69~ for version number 69. This is an optional feature
+that the user has to enable.
+
+** Mode Line differences.
+
+Each window in GNU Emacs has its own mode line, which always
+displays the status of that window's buffer and nothing else.
+The mode line appears at the bottom of the window. It is
+full of dashes, to emphasize the boundaries between windows,
+and is displayed in inverse video if the terminal supports it.
+The information usually available includes:
+
+** Local Modes feature changed slightly.
+
+GNU Emacs supports local mode lists much like those in Twenex Emacs,
+but you can only set variables, not commands. You write
+
+Local variables:
+tab-width: 10
+end:
+
+in the last page of a file, if you want to make tab-width be ten in a
+file's buffer. The value you specify must be a Lisp object!
+It will be read, but not evaluated. So, to specify a string,
+you MUST use doublequotes. For "false", in variables whose
+meanings are true or false, you MUST write nil .
+
+Two variable names are special: "mode" and "eval".
+Mode is used for specifying the major mode (as in Twenex Emacs).
+
+mode: text
+
+specifies text mode. Eval is used for requesting the evaluation
+of a Lisp expression; its value is ignored. Thus,
+
+eval: (set-syntax-table lisp-mode-syntax-table)
+
+causes Lisp Mode syntax to be used.
+
+
+Note that GNU Emacs looks for the string "Local variables:"
+whereas Twenex Emacs looks for "Local modes:". This incompatibility
+id deliberate, so that neither one will see local settings
+intended for the other.
+
+** Lisp code libraries.
+
+Libraries of commands, and init files, are written in Lisp.
+libraries conventionally have names ending in .el, while the
+init file is named .emacs and is in your home directory.
+
+Use Meta-x load-library to load a library. Most standard libraries
+load automatically if you try to use the commands in them.
+
+Meta-x byte-compile-file filename
+compiles the file into byte code which loads and runs faster
+than Lisp source code. The file of byte code is given a name
+made by appending "c" to the end of the input file name.
+
+Meta-x byte-recompile-directory directoryname
+compiles all files in the specified directory (globbing not allowed)
+which have been compiled before but have been changed since then.
+
+Meta-x load-library automatically checks for a compiled file
+before loading the source file.
+
+Libraries once loaded do not retain their identity within GNU
+Emacs. Therefore, you cannot tell just what was loaded from a
+library, and you cannot un-load a library. Normally, libraries
+are written so that loading one has no effect on the editing
+operations that you would have used if you had not loaded the
+library.
+
+** Dired features.
+
+You can do dired on partial directories --- any pattern
+the shell can glob. Dired creates a buffer named after
+the directory or pattern, so you can dired several different
+directories. If you repeat dired on the same directory or
+pattern, it just reselects the same buffer. Use Meta-x Revert
+on that buffer to read in the current contents of the directory.
+
+** Directory listing features.
+
+C-x C-d now uses the default output format of `ls',
+which gives just file names in multiple columns.
+C-u C-x C-d passes the -l switch to `ls'.
+
+Both read a directory spec from the minibuffer. It can
+be any pattern that the shell can glob.
+
+** Compiling other programs.
+
+Meta-x compile allows you to run make, or any other compilation
+command, underneath GNU Emacs. Error messages go into a buffer whose
+name is *compilation*. If you get error messages, you can use the
+command C-x ` (that is a backquote) to find the text of the next
+error message.
+
+You must specify the command to be run as an argument to M-x compile.
+A default is placed in the minibuffer; you can kill it and start
+fresh, edit it, or just type Return if it is what you want.
+The default is the last compilation command you used; initially,
+it is "make -k".
+
+** Searching multiple files.
+
+Meta-x grep searches many files for a regexp by invoking grep
+and reading the output of grep into a buffer. You can then
+move to the text lines that grep found, using the C-x ` command
+just as after M-x compile.
+
+** Running inferior shells.
+
+Do Meta-x shell to make an inferior shell together with a buffer
+which serves to hold "terminal" input and output of the shell.
+The shell used is specified by the environment variable ESHELL,
+or by SHELL if ESHELL is not set.
+
+Use C-h m whilst in the *shell* buffer to get more detailed info.
+
+The inferior shell loads the file .emacs_csh or.emacs_sh
+(or similar using whatever name the shell has) when it starts up.
+
+M-! executes a shell command in an inferior shell
+and displays the output from it. With a prefix argument,
+it inserts the output in the current buffer after dot
+and sets the mark after the output. The shell command
+gets /dev/null as its standard input.
+
+M-| is like M-! but passes the contents of the region
+as input to the shell command. A prefix argument makes
+the output from the command replace the contents of the region.
+
+** Sending mail.
+
+Once you enter Mail Mode using C-x m or C-x 4 m or M-x mail,
+C-c becomes a prefix character for mail-related editing commands.
+C-c C-s is vital; that's how you send the message. C-c C-c sends
+and then switches buffers or kills the current window.
+Use C-h m to get a list of the others.
+
+** Regular expressions.
+
+GNU Emacs has regular expression facilities like those of most
+Unix editors, but more powerful:
+
+*** -- + --
+
++ specifies repetition of the preceding expression 1 or more
+times. It is in other respect like *, which specifies repetition
+0 or more times.
+
+*** -- ? --
+
+? is like * but matches at most one repetition of the preceding
+expression.
+
+*** -- \| --
+
+\| specifies an alternative. Two regular expressions A and B with \| in
+between form an expression that matches anything that either A or B will
+match. Thus, "foo\|bar" matches either "foo" or "bar" but no other
+string.
+
+\| applies to the larges possible surrounding expressions. Only a
+surrounding \( ... \) grouping can limit the grouping power of \|.
+
+Full backtracking capability exists when multiple \|'s are used.
+
+*** -- \( ... \) --
+
+\( ... \) are a grouping construct that serves three purposes:
+
+1. To enclose a set of \| alternatives for other operations.
+ Thus, "\(foo\|bar\)x" matches either "foox" or "barx".
+2. To enclose a complicated expression for * to operate on.
+ Thus, "ba\(na\)*" matches "bananana", etc., with any number
+ of na's (zero or more).
+3. To mark a matched substring for future reference.
+
+Application 3 is not a consequence of the idea of a parenthetical
+grouping; it is a separate feature which happens to be assigned as a
+second meaning to the same \( ... \) construct because there is no
+conflict in practice between the two meanings. Here is an explanation
+of this feature.
+
+ -- \digit --
+
+After the end of a \( ... \) construct, the matcher remembers the
+beginning and end of the text matched by that construct. Then, later on
+in the regular expression, you can use \ followed by a digit to mean,
+``match the same text matched this time by the \( ... \) construct.''
+The first nine \( ... \) constructs that appear in a regular expression
+are assigned numbers 1 through 9 in order of their beginnings. \1
+through \9 can be used to refer to the text matched by the corresponding
+\( ... \) construct.
+
+For example, "\(.*\)\1" matches any string that is composed of two
+identical halves. The "\(.*\)" matches the first half, which can be
+anything, but the \1 that follows must match the same exact text.
+
+*** -- \` --
+
+Matches the empty string, but only if it is at the beginning of the buffer.
+
+*** -- \' --
+
+Matches the empty string, but only if it is at the end of the buffer.
+
+*** -- \b --
+
+Matches the empty string, but only if it is at the beginning or end of
+a word. Thus, "\bfoo\b" matches any occurrence of "foo" as a separate word.
+"\bball\(s\|\)\b" matches "ball" or "balls" as a separate word.
+
+*** -- \B --
+
+Matches the empty string, provided it is NOT at the beginning or end of
+a word.
+
+*** -- \< --
+
+Matches the empty string, provided it is at the beginning of a word.
+
+*** -- \> --
+
+Matches the empty string, provided it is at the end of a word.
+
+*** -- \w --
+
+Matches any word-constituent character. The editor syntax table determines
+which characters these are.
+
+*** -- \W --
+
+Matches any character that is not a word-constituent.
+
+*** -- \s<code> --
+
+Matches any character whose syntax is <code>. <code> is a letter that
+represents a syntax code: thus, "w" for word constituent, "-" for
+whitespace, "(" for open-parenthesis, etc. Thus, "\s(" matches any
+character with open-parenthesis syntax.
+
+*** -- \S<code> --
+
+Matches any character whose syntax is not <code>.
diff --git a/etc/DISTRIB b/etc/DISTRIB
new file mode 100644
index 00000000000..520958e88c4
--- /dev/null
+++ b/etc/DISTRIB
@@ -0,0 +1,427 @@
+-*- text -*-
+ The prices on the order form below EXPIRE on 30 June 1992
+
+ GNU Emacs availability information, January 1992
+Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+
+ Permission is granted to anyone to make or distribute
+ verbatim copies of this document provided that the
+ copyright notice and this permission notice are preserved.
+
+GNU Emacs is legally owned by the Free Software Foundation, but we
+regard the foundation actually as its custodian on behalf of the
+public, since all software ought to be the common property of mankind.
+
+The foundation permits everyone to have and run copies of GNU Emacs,
+at no charge, and to redistribute copies under certain conditions
+which are designed to make sure that that all modified versions of GNU
+Emacs remain as free as the versions we distribute. These conditions
+are stated in the document "GNU Emacs General Public License," a copy
+of which is required to be distributed with every copy of GNU Emacs.
+It is usually in a file named COPYING in the same directory as this
+file.
+
+If you do not know anyone to get a copy of GNU Emacs from, you can
+order a tape from the Free Software Foundation. We distribute Emacs
+version 18 on mag tape in different formats for many machines. We also
+distribute nicely typeset copies of the Emacs user manual, Emacs Lisp
+Reference Manual, the Emacs reference card, etc. See the order form at
+the end of this file.
+
+If you have Internet access, you can copy the latest Emacs
+distribution from host prep.ai.mit.edu. There are several ways to do
+this; see the file `FTP' in the same directory as this file for more
+information. Even better, get the latest version of the file from
+`/pub/gnu/GNUinfo/FTP' on prep.ai.mit.edu for the most current
+arrangements. It may also be possible to copy Emacs via uucp; the
+file `FTP' contains information on that too.
+
+Emacs has been run on both Berkeley Unix and System V Unix, on a
+variety of types of cpu. It also works on VMS and on Apollo
+computers, though with some deficiencies that reflect problems in
+these operating systems. See the file MACHINES in this directory for
+a full list of machines that GNU Emacs has been tested on, with
+machine-specific installation notes and warnings.
+
+Note that there is significant variation between Unix systems
+supposedly running the same version of Unix; it is possible that what
+works in GNU Emacs for me does not work on your system due to such an
+incompatibility. Since I must avoid reading Unix source code, I
+cannot even guess what such problems may exist.
+
+GNU Emacs is distributed with no warranty (see the General Public
+License for full details, in the file COPYING in this directory), and
+neither I nor the Free Software Foundation promises any kind of
+support or assistance to users. The foundation keeps a list of people
+who are willing to offer support and assistance for hire. It is
+usually in a file named SERVICE in the same directory as this file.
+You get the latest version of the file from `/pub/gnu/GNUinfo/SERVICE' on
+prep.ai.mit.edu.
+
+However, we plan to continue to improve GNU Emacs and keep it
+reliable, so please send me any complaints and suggestions you have.
+I will probably fix anything that I consider a malfunction. I may
+make improvements that are suggested, but I may choose not to.
+Improving Emacs is not my highest priority now.
+
+If you are on the Internet, report bugs to
+bug-gnu-emacs@prep.ai.mit.edu; on UUCP, use the address
+...!uunet!prep.ai.mit.edu!bug-gnu-emacs. Otherwise, phone the
+foundation at the number listed below, or write to the address listed
+below. General questions about the GNU Project can be asked of
+gnu@prep.ai.mit.edu.
+
+If you are a computer manufacturer, I encourage you to ship a copy of
+GNU Emacs with every computer you deliver. The same copying
+permission terms apply to computer manufacturers as to everyone else.
+You should consider making a donation to help support the GNU project;
+if you estimate what it would cost to distribute some commercial
+product and divide it by five, that is a good amount.
+
+If you like GNU Emacs, please express your satisfaction with a
+donation: send me or the Foundation what you feel Emacs has been worth
+to you. If you are glad that I developed GNU Emacs and distribute it
+as freeware, rather than following the obstructive and antisocial
+practices typical of software developers, reward me. If you would
+like the Foundation to develop more free software, contribute.
+
+Your donations will help to support the development of more useful
+software to be distributed on the same basis as GNU Emacs. Eventually
+we will have a complete imitation of the Unix operating system, called
+GNU (Gnu's Not Unix), which will run Unix user programs. For more
+information on GNU, see the file GNU in this directory.
+
+ Richard M Stallman
+ Chief GNUisance,
+ President of the Free Software Foundation
+
+ Free Software Foundation Order Form
+
+ This order form is effective 1 January 1992 - 30 June 1992
+
+Prices and contents may change without notice.
+
+Please allow six weeks for delivery (though it won't usually take that long).
+
+All software and publications are distributed with permission to copy and to
+redistribute.
+
+Texinfo source for each manual is on the appropriate tape. The prices for
+tapes do not include printed manuals.
+
+All software and documentation from the Free Software Foundation is provided
+on an "as is" basis, with no warranty of any kind.
+
+Contents of Tapes:
+
+GNU Emacs Tape
+
+The tape includes source code for:
+* GNU Emacs (the extensible, customizable, self-documenting, real-time display
+ editor)
+* The GNU Emacs Manual, as Texinfo source
+* The GNU Termcap Manual, as Texinfo source (the GNU termcap library is
+ included with GNU Emacs)
+* The GNU Emacs Lisp Reference Manual, as Texinfo source
+* Calc (the extensible, advanced desk calculator and mathematical tool that
+ runs as part of GNU Emacs)
+* The Calc Manual, as Texinfo source
+* MIT Scheme (a dialect of Lisp)
+* T (Yale's implementation of Scheme)
+* Texinfo (beta-test of an enhanced Texinfo. Texinfo is GNU's structured
+ documentation system, included with GNU Emacs. Texinfo is used to produce
+ both on-line and printed documents.)
+* The Texinfo Manual, as Texinfo source
+* texi2roff (for printing Texinfo source with [nt]roff)
+* Data Compression Software (to uncompress source on the tape)
+
+GNU Languages Tape
+
+The tape includes source code for:
+* GCC 1 (the GNU C Compiler, including COFF support)
+* The GCC Manual, as Texinfo source (not yet on our order form)
+* G++ (the C++ front end to GCC)
+* The GNU G++ Users Guide, as Texinfo source (not yet published on paper)
+* libg++ (the G++ class library)
+* NIH Class Library (formerly known as OOPS)
+* Gas (the GNU Assembler)
+* GNU binary file utilities (ar, gprof, ld, nm, size, strip, & ranlib)
+* dld (a dynamic linker)
+* COFF support for GNU software tools
+* Flex (Vern Paxson's fast rewrite of lex)
+* Bison (a free, compatible replacement for yacc)
+* The Bison Manual, as Texinfo source
+* GDB 3.5 (The GNU source-level C debugger)
+* The GDB Manual, as Texinfo source
+* GNU make
+* The GNU Make Manual, as Texinfo source
+* GNU indent
+* Gawk (the GNU implementation of the AWK programming language)
+* The Gawk Manual, as Texinfo source
+* GNU Smalltalk (the GNU implementation of this programming language system)
+* Perl (a programming language interpreter)
+* gperf (a perfect hash-table generator)
+* ae (works with GCC to produce more complete profiling information)
+* f2c (a FORTRAN to C translator)
+* gdbm library (GNU implementation of the standard dbm & ndbm libraries)
+* texi2roff (for printing Texinfo source with [nt]roff)
+* Data Compression Software (to uncompress source on the tape)
+
+GNU Experimental Tape
+
+This tape will not be ready until March 1992. The tape's source code
+will include:
+* GCC 2 (the GNU C/C++/Objective-C Compiler with many new features)
+* GDB 4 (The GNU source-level C debugger)
+* BFD ((Binary File Descriptor Library)
+* GNU C Library (POSIX.1 compliant, upward compatible with 4.3 BSD & System V)
+* GNU Graphics (graph, plot, plot2ps, et al.)
+
+GNU Utilities Tape
+
+The tape includes source code for:
+* Bash (GNU's Bourne Again SHell)
+* Groff (GNU troff & pic, eqn, tbl, refer; -man, -ms, -mm macros; & drivers)
+* GNU tar & cpio
+* GNU diff, grep, egrep, fgrep
+* patch
+* RCS (Revision Control System)
+* CVS (Concurrent Version System)
+* GNU fileutils (chgrp, chmod, chown, cp, dd, df, du, install, ln, ls, mkdir,
+ mkfifo, mknod, mv, mvdir, rm, rmdir, & touch)
+* GNU shellutils (basename, date, dirname, env, expr, groups, id, logname,
+ nice, nohup, pathchk, printenv, printf, sleep, stty, tee, test, tty, uname,
+ whoami, & yes)
+* GNU textutils (cat, cmp, comm, csplit, cut, expand, fold, head, join, paste,
+ pr, sort, split, sum, tac, tail, unexpand, uniq, & wc)
+* Ghostscript (a Postscript interpreter)
+* Gnuplot (an interactive mathematical plotting program)
+* GNU m4, sed, & find
+* elvis (a clone of the vi/ex Unix editor)
+* screen (a terminal multiplexor that allows you to handle several independent
+ ``screens'' (ttys) on a single physical terminal)
+* GNU time & tput
+* ms (MandelSpawn, a parallel Mandelbrot program for the X window system)
+* GNU Chess (a chess playing program with an interface to X)
+* Nethack (a rogue-like game)
+* GNU GO (the GNU implementation of the game of GO)
+* the freed files from the 4.3BSD-Tahoe distribution
+* GNU make
+* The GNU Make Manual, as Texinfo source
+* texi2roff (for printing Texinfo source with [nt]roff)
+* Data Compression Software (to uncompress source on the tape)
+
+X11R5 Required Tape
+
+This tape has source code for the required MIT X Window System X11R5,
+including core software and documentation, and contributed client software.
+
+X11R5 Optional Tape
+
+This tape has source code for the optional MIT X Window System X11R5,
+including contributed software, libraries, games, Andrew and toolkits.
+
+Quantity Price Item
+
+
+For Unix systems, on 1600 bpi reel-to-reel 9-track 1/2" tape in Unix tar format
+(tape contents described above):
+
+________ $200 GNU Emacs Tape
+
+________ $200 GNU Languages Tape
+
+________ $200 GNU Experimental Tape (not ready until March 1992)
+
+________ $200 GNU Utilities Tape
+
+________ $200 X11R5 Required Tape
+
+________ $200 X11R5 Optional Tape
+
+
+For Suns and some other Unix Systems, on QIC-24 DC300XLP 1/4 inch
+cartridge tape, Unix tar format (tape contents described above):
+
+________ $210 GNU Emacs Tape
+
+________ $210 GNU Languages Tape
+
+________ $210 GNU Experimental Tape (not ready until March 1992)
+
+________ $210 GNU Utilities Tape
+
+________ $210 X11R5 Required Tape
+
+________ $210 X11R5 Optional Tape
+
+
+For HP Systems, on 16-track DC600HC 1/4 inch cartridge tape, Unix tar format
+(tape contents described above):
+
+________ $230 GNU Emacs Tape
+
+________ $230 GNU Languages Tape
+
+________ $230 GNU Experimental Tape (not ready until March 1992)
+
+________ $230 GNU Utilities Tape
+
+________ $230 X11R5 Required Tape
+
+________ $230 X11R5 Optional Tape
+
+
+For IBM RS/6000 Systems, on DC600A 1/4 inch cartridge tape Unix tar format
+(tape contents described above) (the GNU Languages Tape is not yet available
+for the RS/6000):
+
+________ $215 GNU Emacs Tape, plus executable files of Emacs
+
+________ $215 GNU Experimental Tape (not ready until March 1992)
+
+________ $215 GNU Utilities Tape
+
+________ $215 X11R5 Required Tape
+
+________ $215 X11R5 Optional Tape
+
+
+For VMS systems, on 1600 bpi reel-to-reel 9-track 1/2" tape in VMS BACKUP (aka
+interchange format):
+
+________ $195 GNU Emacs source code and binaries. None of the other
+ software on the GNU Emacs Tape, described above, is included.
+
+________ $195 GNU C compiler source code and binaries. Includes Bison and
+ GAS. None of the other software on the GNU Languages Tape,
+ described above, is included.
+
+
+The following manuals are all bound to lie open, flat on a table:
+
+________ $20 GNU Emacs manual, unit price for 1 to 5 copies.
+ ~280 pages with a reference card, phototypeset and
+ offset printed.
+
+________ $13 GNU Emacs manuals, unit price for 6 or more.
+
+________ $50 A single GNU Emacs Lisp Reference Manual, ~550 pages,
+ offset printed, spiral bound.
+
+________ $200 A box of 5 GNU Emacs Lisp Reference Manuals.
+
+________ $50 Calc Manual, ~590 pages. Calc is an extensible, advanced desk
+ calculator and mathematical tool that runs under GNU Emacs.
+
+________ $15 GDB Manual, ~170 pages, with a reference card.
+
+________ $15 Texinfo Manual, ~220 pages. Texinfo is GNU's structured
+ documentation system, included with GNU Emacs. Texinfo is
+ used to produce both on-line and printed documents. This
+ manual describes how to write Texinfo documents.
+
+________ $10 Termcap Manual, ~60 pages. Documents the termcap library and
+ GNU's extensions to it. The GNU termcap library is included
+ with GNU Emacs.
+
+________ $10 Bison Manual, ~100 pages.
+
+________ $15 Gawk Manual, ~200 pages.
+
+________ $15 Make Manual, ~120 pages.
+
+
+The following reference cards:
+
+________ $1 One GNU Emacs reference card, without the manual.
+
+________ $5 Packet of ten GNU Emacs reference cards.
+
+________ $1 One GDB reference card, without the manual.
+
+________ $5 Packet of ten GDB reference cards.
+
+
+________ Subtotal
+--------
+
+________ In Massachusetts: add 5% sales tax, or give tax exempt number.
+
+We pay for shipping via UPS ground transportation in the contiguous 48 states
+and Canada.
+
+________ In Alaska, Hawaii, or Puerto Rico, for shipping:
+ - For Emacs Lisp Reference and Emacs Calc manuals, add $5 each,
+ or $20 per box. For all other items, add $5 base charge,
+ then $1 per item except reference cards.
+
+ If outside of U.S., Canada and Puerto Rico, for shipping costs:
+ - for tapes or unboxed manuals, please add $15 base
+ charge, and then add $15 more for each tape or unboxed
+ manual (not reference cards) in the order:
+________ Shipping cost for tapes and unboxed manuals = $15 + $15 * n;
+ - for each box of Emacs Lisp Reference manuals,
+________ please add $70.
+
+________ Optional tax deductible donation.
+
+
+________ Total paid
+--------
+
+Orders are filled upon receipt of check or money order. We do not have the
+staff to handle the billing of unpaid orders. Please help keep our lives
+simple by including your payment with your order.
+
+Please make checks payable to: "Free Software Foundation".
+
+Please mail orders to:
+
+ Free Software Foundation, Inc.
+ 675 Massachusetts Avenue
+ Cambridge, MA 02139
+ USA
+
+ +1 617-876-3296
+
+
+This Order Form is EFFECTIVE 1 January 1992 - 30 June 1992
+
+
+
+Name:
+ ----------------------------------------------------------------
+
+Mail Stop/Dept. Name
+ -------------------------------------------------
+
+Organization:
+ --------------------------------------------------------
+
+Street Address:
+ ------------------------------------------------------
+
+
+----------------------------------------------------------------------
+
+City / State / Province:
+ ---------------------------------------------
+
+Zip Code / Postal Code / Country:
+ ------------------------------------
+
+In case of a problem with your order, or for overseas customs agents,
+please add your voice telephone number (not your FAX number):
+
+
+ ----------------------------------------
+
+For orders outside the US: Orders MUST be paid in US dollars. You are
+responsible for paying all duties, tariffs, and taxes. If you refuse
+to pay the charges, the shipper will return or abandon your order.
+
+Please write the telephone number that you want custom agents to call
+in the space provided above.
+
+This Order Form is EFFECTIVE 1 January 1992 - 30 June 1992
diff --git a/etc/FAQ b/etc/FAQ
index 643fd6051ee..cfd6639b591 100644
--- a/etc/FAQ
+++ b/etc/FAQ
@@ -1,350 +1,763 @@
-This is a list of frequently asked questions (FAQ) about GNU Emacs with
-answers. This list is designed to cut down on the noise in the
-gnu.emacs.help newsgroup (which is also the help-gnu-emacs mailing list)
-that results from people repeatedly asking many of the same questions.
-
-This list is maintained by me, Joe Wells. My e-mail address is
-jbw@bu.edu. If jbw@bu.edu doesn't work try jbw@bucsf.bu.edu.
-
-Feel free to contribute text for the answers that I haven't written yet,
-to suggest new questions, to suggest changes in the wording, to suggest
-deletions, etc. Please include either "FAQ" or "frequently asked
-questions" in the subject of messages you send to me to help keep me from
-accidentally filing your message in the wrong mail folder.
-
-Here is a short list of new questions and questions that are now answered:
-
-New questions:
-
- Why doesn't "C-c C-c" interrupt subprocesses under HP/UX?
- How do I make Emacs send 8-bit characters to my terminal?
- Why does ispell sometimes ignore the local dictionary?
- Where can I get Emacs with NeWS support?
-
-Questions with improved answers:
-
- Has someone written an GNU Emacs Lisp package that does XXX?
- How do I get Emacs running on VMS under DECwindows?
- Why does Emacs crash from a bus error in XLookupString under OpenLook?
- Why does Emacs hang with message "Unknown XMenu" with X11R4?
- How do I use regexps (regular expressions) in Emacs?
- How do I make Emacs "typeover" or "overwrite" when I type instead of
- always inserting?
- How do I get Emacs for my PC?
- How can I highlight a region?
- Where can I get GNU Emacs Lisp packages that don't come with Emacs?
- Where can I get the latest VM, Supercite, GNUS, Calc, Calendar, or Patch?
-
-Minor changes:
-
- Where does the name "Emacs" come from?
- In C mode, can I show just the lines that will be left after #ifdef
- commands are handled by the compiler?
- What does "M-x command" mean?
- How do I get a printed copy of the GNU Emacs manual?
- What do things like this mean: C-h, M-C-a, RET, etc.?
- Why doesn't GNUS work anymore via NNTP?
- What does Emacs do every time it starts up?
-
-Enjoy,
+ GNU Emacs FAQ: Introduction
+
+[To find what has changed, see the "diff" posting.]
+
+[Joe Wells plans to quit soon as FAQ coordinator. Steven Byrnes says he can
+ take over this portion of the FAQ responsibility. We still need more
+ volunteers to help by taking charge of a section of the FAQ list. Send e-mail
+ if you are interested.]
+
+This is the introduction to a list of frequently asked questions (FAQ) about
+GNU Emacs with answers. This article contains a listing of the questions;
+subsequent articles contain the questions and answers.
+
+The FAQ list is posted to reduce the noise level in the `gnu.emacs.help'
+newsgroup (which is also the `help-gnu-emacs' mailing list) which results from
+the repetition of frequently asked questions, wrong answers to these questions,
+corrections to the wrong answers, corrections to the corrections, debate, name
+calling, etc. Also, it serves as a repository of the canonical "best" answers
+to these questions. However, if you know a better answer or even a slight
+change that improves an answer, please tell us!
+
+If you know the answer of a question is in the FAQ list, please reply to the
+question by e-mail instead of posting. Help reduce noise!
+
+The FAQ list is crossposted to `comp.emacs' because some sites do not receive
+the `gnu.*' newsgroups. The FAQ list is also crossposted to `news.answers'.
+
+Please suggest new questions, answers, wording changes, deletions, etc. The
+most helpful form for suggestions is a context diff (ie., the output of `diff
+-c'). Include `FAQ' in the subject of messages sent to us about the FAQ list.
+
+Please do not send questions to us just because you do not want to disturb a
+lot of people and you think we would know the answer. We do not have time to
+answer questions individually. :-(
+
+Full instructions for getting the latest FAQ are in question 22. Also see the
+`Introduction to news.answers' posting in the `news.answers' newsgroup, or send
+e-mail to `mail-server@rtfm.mit.edu' with `help' on a body line, or use FTP,
+WAIS, or Prospero to rtfm.mit.edu.
+
+These ideas have already been suggested, but we have not had time to
+implement them:
+
+ * A Texinfo version.
+ * Marking questions in the table of contents that have been changed
+ recently.
--
-Joe Wells <jbw@bu.edu>
--------------------------------------------------
-GNU Emacs Frequently Asked Questions with Answers (part 1 of 2)
+Joe Wells <jbw@cs.bu.edu> and Steven Byrnes <sbyrnes@rice.edu>
-Sat Dec 8 01:30:53 1990
+E-mail jbw@cs.bu.edu for details about the League for Programming Freedom.
+----------------------------------------------------------------------
-If you are viewing this file in a GNU Emacs Buffer, you can type "M-2 C-x
-$" to get an overview of just the questions. Then, when you want to look
-at the text of the answers, just type "C-x $".
+ GNU Emacs FAQ: Table of Contents
-To search for a question numbered XXX, type "M-C-s ^XXX:", followed by a
-C-r if that doesn't work, then type ESC to end the search.
+Notation Used in FAQ
+1: What do these mean: C-h, M-C-a, RET, "ESC a", etc.?
+2: What does "M-x command" mean?
+3: How do I read topic XXX in the on-line manual?
+4: What do these mean: etc/SERVICE, src/config.h, lisp/default.el?
+5: What are FSF, LPF, OSF, GNU, RMS, FTP, and GPL?
-Notation Used in the Answers (READ THIS SECTION FIRST!)
+General Questions
- You may skip this section if you are reasonably familiar with GNU Emacs.
- Some of these are not actually frequently asked questions, but knowing
- them is important for understanding the answers to the rest of the
- questions.
+6: What is the LPF and why should I join it?
+7: What is the real legal meaning of the GNU copyleft?
+8: What are appropriate messages for gnu.emacs.help, gnu.emacs.bug,
+ comp.emacs, etc.?
+9: Where can I get old postings to gnu.emacs.help and other GNU groups?
+10: Where should I report bugs and other problems with GNU Emacs?
+11: How do I unsubscribe to this mailing list?
+12: What is the current address of the FSF?
-1: What do things like this mean: C-h, M-C-a, RET, etc.?
-
- C-a means while holding down the "Control" key press the "a" key. The
- ASCII code this sends will generally be the value that would be sent by
- pressing just "a" minus 96 or 64. Either way it will be a number from 0
- to 31.
-
- M-a means while holding down the "Meta" key press the "a" key. The
- ASCII code this sends is the sum of the ASCII code that would be sent by
- pressing just "a" and 128.
-
- M-C-a means while holding down both the "Control" key and the "Meta" key
- press the "a" key.
-
- C-M-a is a synonym for M-C-a.
-
- RET means press the "Return" key. RET is the same as C-m. This sends
- ASCII code 13.
-
- LFD means press the "Linefeed" key. LFD is also the same as C-j. This
- sends ASCII code 10. Under Unix, ASCII code 10 is more often called
- "Newline".
+On-line Help, Printed Manuals, Other Sources of Help
+
+13: I'm just starting GNU Emacs; how do I do basic editing?
+14: How do I find out how to do something in GNU Emacs?
+15: How do I get a printed copy of the GNU Emacs manual?
+16: Where can I get documentation on GNU Emacs Lisp?
+17: How do I install a piece of Texinfo documentation?
+18: How do I print a Texinfo file?
+19: Can I view Info files without using GNU Emacs?
+20: What informational files are available for GNU Emacs?
+21: Where can I get help in installing GNU Emacs?
+22: Where can I get the latest version of this document (the FAQ list)?
+
+Status of Emacs
+
+23: Where does the name "Emacs" come from?
+24: What is the latest version of GNU Emacs?
+25: When will GNU Emacs 19 be available?
+26: What is different about GNU Emacs 19?
+27: What variants of GNU Emacs exist?
+
+Common Things People Want To Do
+
+28: How do I set up a .emacs file properly?
+29: How do I debug a .emacs file?
+30: How do I make Emacs display the current line (or column) number?
+31: How do I turn on Abbrevs by default just in mode XXX?
+32: How do I turn on Auto-Fill mode by default?
+33: How do I make Emacs use a certain major mode for certain files?
+34: How do I search for, delete, or replace unprintable (8-bit or control)
+ characters?
+35: How can I highlight a region of text in Emacs?
+36: How do I control Emacs's case-sensitivity when searching/replacing?
+37: How do I make Emacs wrap words for me?
+38: Where can I get a better spelling checker for Emacs?
+39: How can I spell-check TeX or *roff documents?
+40: How do I change load-path?
+41: How do I use an already running Emacs from another window?
+42: How do I make Emacs recognize my compiler's funny error messages?
+43: How do I indent switch statements like this?
+44: How can I make Emacs automatically scroll horizontally?
+45: How do I make Emacs "typeover" or "overwrite" instead of inserting?
+46: How do I stop Emacs from beeping on a terminal?
+47: How do I turn down the bell volume in Emacs running under X Windows?
+48: How do I tell Emacs to automatically indent a new line to the
+ indentation of the previous line?
+49: How do I show which parenthesis matches the one I'm looking at?
+50: In C mode, can I show just the lines that will be left after #ifdef
+ commands are handled by the compiler?
+51: Is there an equivalent to the `.' (dot) command of vi?
+52: What are the valid X resource settings (ie., stuff in .Xdefaults)?
+53: How do I execute a piece of Emacs Lisp code?
+54: How do I change Emacs's idea of the tab character's length?
+55: How do I insert `>' at the beginning of every line?
+56: How do I insert `_^H' before each character in a paragraph to get an
+ underlined paragraph?
+57: How do I repeat a command as many times as possible?
+58: How do I make Emacs behave like this: when I go up or down, the cursor
+ should stay in the same column even if the line is too short?
+59: How do I tell Emacs to iconify itself?
+60: How do I use regexps (regular expressions) in Emacs?
+61: How do I perform a replace operation across more than one file?
+62: Where is the documentation for `etags'?
+
+Bugs/Problems
+
+63: Does Emacs have problems with files larger than 8 megabytes?
+64: Why can't Emacs find files in current directory on startup?
+65: How do I get rid of the ^M junk in my Shell buffer?
+66: Why do I get `Process shell exited abnormally with code 1'?
+67: Why can't I cut from Emacs and paste in other X programs?
+68: Where is the termcap/terminfo entry for terminal type `emacs'?
+69: Why does Emacs spontaneously start displaying `I-search:' and beeping?
+70: Why can't Emacs talk to certain hosts (or certain hostnames)?
+71: Why does Emacs say `Error in init file'?
+72: Why does Emacs ignore my X resources (my .Xdefaults file)?
+73: Why does Emacs take 20 seconds to visit a file?
+74: How do I edit a file with a `$' in its name?
+75: Why does Shell mode lose track of the shell's current directory?
+76: Why doesn't my change to load-path work?
+77: Why does the cursor always go to the wrong column when I move up or
+ down one line?
+78: Why does Emacs hang with message `Unknown XMenu error' with X11R4?
+79: Why doesn't display-time show the load average in the mode line
+ anymore?
+80: Why does ispell sometimes ignore the local dictionary?
+81: Why does Ispell treat each line as a single word?
+82: Are there any security risks in GNU Emacs?
+
+Difficulties Building/Installing/Porting Emacs
+
+83: What should I do if I have trouble building Emacs?
+84: How do I stop Emacs from failing when the executable is stripped?
+85: Why does linking Emacs with -lX11 fail?
+86: Why does Emacs 18.55 say `Fatal error (6).Abort' under SunOS 4.1?
+
+Finding/Getting Emacs and Related Packages
+
+87: Where can I get GNU Emacs on the net (or by snail mail)?
+88: How do I find a GNU Emacs Lisp package that does XXX?
+89: Where can I get GNU Emacs Lisp packages that don't come with Emacs?
+90: How do I submit code to the Emacs Lisp Archive?
+91: Where can I get other up-to-date GNU stuff?
+92: Where can I get an Emacs with better mouse and X window support?
+93: What is the difference between GNU Emacs and Epoch?
+94: What is the difference between GNU Emacs and Lucid GNU Emacs?
+95: Where can I get the "unofficial HP GNU Emacs"?
+96: Where can I get Emacs for my PC running MS-DOS?
+97: Where can I get Emacs for my PC running Windows?
+98: Where can I get Emacs for my PC running OS/2?
+99: Where can I get Emacs for my Atari ST?
+100: Where can I get Emacs for my Amiga?
+101: Where can I get Emacs for my Apple computer?
+102: Where can I get Emacs with NeWS support?
+103: Where do I get Emacs that runs on VMS under DECwindows?
+104: Where can I get modes for Lex, Yacc/Bison, Bourne Shell, Csh, C++,
+ Objective C, Pascal, Awk?
+105: What is the IP address of XXX.YYY.ZZZ?
+
+Major Emacs Lisp Packages, Emacs Extensions, and Related Programs
+
+106: VM (View Mail) -- another mail reader within Emacs
+107: Supercite -- mail and news citation package within Emacs
+108: GNUS -- news reader within Emacs
+109: Calc -- poor man's Mathematica within Emacs
+110: Calendar/Diary -- calendar manager within Emacs
+111: Ange-FTP -- transparent FTP access for Emacs's file access routines
+112: VIP -- vi emulation for Emacs
+113: Dired -- better directory editor for Emacs
+114: AUC TeX -- enhanced LaTeX mode with debugging facilities
+115: Hyperbole -- extensible hypertext management system within Emacs
+116: Byte Compiler -- enhanced version of Emacs's byte compiler
+117: comint -- hugely enhanced shell mode and other derived modes
+118: BBDB -- personal info rolodex integrated with mail/news readers
+119: Ispell -- spell checker in C with interface for Emacs
+120: Epoch -- enhanced GNU Emacs with better X interface
+121: Lucid GNU Emacs -- alternative Emacs 19 with better X interface
+122: Demacs -- GNU Emacs altered to run on MS-DOS on 386/486 machines
+123: Freemacs -- a small Emacs for MS-DOS
+124: Patch -- program to apply "diffs" for updating files
+
+Changing Key Bindings and Handling Key Binding Problems
+
+125: How do I bind keys (including function keys) to commands?
+126: Why does Emacs say `Key sequence XXX uses invalid prefix characters'?
+127: Why doesn't this [terminal or window-system setup] code work in my
+ .emacs file, but it works just fine after Emacs starts up?
+128: How do I use function keys under X Windows?
+129: How do I tell what characters my function or arrow keys emit?
+130: How do I set the X key "translations" for Emacs?
+131: How do I handle C-s and C-q being used for flow control?
+132: How do I use commands bound to C-s and C-q (or any key) if these keys
+ are filtered out?
+133: Why does the `BackSpace' key invoke help?
+134: Why doesn't Emacs look at the stty settings for Backspace vs. Delete?
+135: Why don't the arrow keys work?
+136: How do I "swap" two keys?
+137: How do I produce C-XXX with my keyboard?
+138: What if I don't have a Meta key?
+139: What if I don't have an Escape key?
+140: How do I type DEL on PC terminal emulators?
+141: Can I make my `Compose Character' key behave like a Meta key?
+142: How do I bind a combination of modifier key and function key?
+143: Why doesn't my Meta key work in an xterm window?
+144: Why doesn't my ExtendChar key work as a Meta key under HP-UX 8.0?
+145: Where can I get key bindings to make Emacs emulate WordStar?
+146: Where can I get an XEDIT emulator for Emacs?
+
+Using Emacs with Alternate Character Sets
+
+147: How do I make Emacs display 8-bit characters?
+148: How do I input 8-bit characters?
+149: Where can I get an Emacs that can handle kanji characters?
+150: Where can I get an Emacs that can handle Chinese?
+151: Where is an Emacs that can handle Semitic (right-to-left) alphabets?
+
+Mail and News
+
+152: How do I change the included text prefix in mail/news followups?
+153: How do I save a copy of outgoing mail?
+154: Why doesn't Emacs expand my aliases when sending mail?
+155: Why does RMAIL think all my saved messages are one big message?
+156: How can I sort the messages in my RMAIL folder?
+157: Why does RMAIL need to write to /usr/spool/mail?
+158: How do I recover my mail files after RMAIL munges their format?
+159: How do I make Emacs automatically start my mail/news reader?
+160: How do I read news under Emacs?
+161: Why does `rnews' say "No News is good news" when there is news?
+162: Why doesn't GNUS work anymore via NNTP?
+163: How do I view text with embedded underlining (eg., ClariNews)?
+164: When I try to post a long article in GNUS (about 10K or longer), I get
+ the error, "Writing to process: no more processes, nntpd"
+165: How do I save all the items of a multi-part posting in GNUS?
+166: Why does GNUS put the subjects in replies beyond the 80th column?
+167: Why is GNUS so slow to start up?
+168: How do I catch up all newsgroups in GNUS?
+169: Why can't I kill in GNUS on the Newsgroups/Keywords/Control line?
+170: How do I get rid of flashing messages in GNUS for slow connections?
+171: Why is catch up slow in Gnews/GNUS?
+172: Why does GNUS hang for a long time when posting?
+173: Why don't my news postings in GNUS get past the local machine?
+174: Why is the GNUS-generated `Date:' header invalid?
+175: Why doesn't GNUS generate the `Lines:' header?
+176: Why do I get "Cannot open load file" "nntp" when compiling GNUS?
+177: How do I kill all articles in GNUS but those matching a pattern?
+
+ GNU Emacs FAQ: Notation/General/Help/Status
+
+If you are viewing this text in a GNU Emacs Buffer, you can type "M-2 C-x $" to
+get an overview of just the questions. Then, when you want to look at the text
+of the answers, just type "C-x $".
+
+To search for a question numbered XXX, type "M-C-s ^XXX:", followed by a C-r if
+that doesn't work, then type ESC to end the search.
+
+A `+' in the 78th column means something was inserted on the line. A `-' means
+something was deleted and a `!' means some combination of insertions and
+deletions occurred.
+
+Full instructions for getting the latest FAQ are in question 22. Also see the
+`Introduction to news.answers' posting in the `news.answers' newsgroup, or send
+e-mail to `mail-server@rtfm.mit.edu' with `help' on a body line, or use FTP,
+WAIS, or Prospero to rtfm.mit.edu.
+
+
+
+Notation Used in FAQ
+
+ Skip this section and then come back if you don't understand some of the
+ later answers.
- DEL means press the "Delete" key. DEL is the same as C-?. This sends
- ASCII code 127.
+1: What do these mean: C-h, M-C-a, RET, "ESC a", etc.?
- ESC means press the "Escape" key. ESC is the same as C-[. This sends
- ASCII code 27.
+ C-x means press the `x' key while holding down the Control key. M-x means
+ press the `x' key while holding down the Meta key. M-C-x means press the
+ `x' key while holding down both the Control key and the Meta key. C-M-a
+ is a synonym for M-C-a. RET, LFD, DEL, ESC, and TAB respectively refer to
+ pressing the Return, Linefeed (aka Newline), Delete, Escape, and Tab keys
+ and are equivalent to C-m, C-j, C-?, C-[, and C-i. SPC means press the
+ Space bar.
- SPC means press the "Space" key. This send ASCII code 32.
+ I put any key sequence that is longer than one key (and some single-key
+ sequences) inside double quotes or on a line by itself. Any real spaces
+ in such a key sequence should be ignored; only SPC really means press the
+ space key.
- TAB means press the "Tab" key. TAB is the same as C-i. This send ASCII
- code 9.
+ The ASCII code sent by C-x (except for C-?) is the value that would be
+ sent by pressing just `x' minus 96 (or 64 for uppercase `X') and will be
+ from 0 to 31. The ASCII code sent by M-x is the sum of 128 and the ASCII
+ code that would be sent by pressing just the `x' key. Essentially, the
+ Control key turns off bits 5 and 6 and the Meta key turns on bit 7.
- To read more about this online, type "C-h i m emacs RET m characters
- RET", and also "C-h i m emacs RET m keys RET".
+ For further information, see `Characters' and `Keys' in the online manual.
-2: What do you mean when you write things like this: type "ESC a"?
+ NOTE: C-? (aka DEL) is ASCII code 127. It is a misnomer to call C-? a
+ "control" key, since 127 has both bits 5 and 6 turned ON. Also, on very
+ few keyboards does Control-? generate ASCII code 127.
- I will enclose key sequences that are longer than one key inside double
- quotes. These notations refer to single keys (some with modifiers):
+2: What does "M-x command" mean?
- C-x, M-x, M-C-x
- RET, LFD, DEL, ESC, SPC, TAB
+ "M-x command" means type M-x, then type the name of the command, then
+ type RET.
- I separate these from other keys within double quotes by spaces. Any
- real spaces that I write inside double quotes can be ignored, only SPC
- means press the space key. All other characters within double quotes
- represent single keys (some shifted).
+ M-x (by default) invokes the command `execute-extended-command'. This
+ command allows you to run any Emacs command if you can remember the
+ command's name. If you can't remember the command's name, you can type
+ TAB and SPC for completion, and "?" for a list of possibilities. An Emacs
+ "command" is any "interactive" Emacs function.
-3: What if I don't have a Meta key?
+ NOTE: Your system administrator may have bound other key sequences to
+ invoke execute-extended-command. A function key labeled `Do' is a good
+ candidate for this.
- Instead of typing M-a, you can type "ESC a" instead. In fact, Emacs
- converts M-a internally into "ESC a" anyway.
+ To run non-interactive Emacs functions, see question 53.
-4: What if I don't have an Escape key?
+3: How do I read topic XXX in the on-line manual?
- Type C-[ instead. This should send ASCII code 27 just like an Escape
- key would.
+ When I refer you to topic XXX in the on-line manual, you can read this
+ manual node inside Emacs (assuming nothing is broken) by typing this:
-5: What does "M-x command" mean?
+ C-h i m emacs RET m XXX RET
- "M-x command" means type M-x, then type the name of the command, then
- type RET.
+ This invokes the Info facility. If you don't already know how to use
+ Info, type "?" from within Info.
- M-x is simply the default key sequence that invokes the command
- "execute-extended-command". This command allows you to run any Emacs
- command if you can remember the command's name. If you can't remember
- the command's name, you can type TAB and SPC for completion, and ? for a
- list of possibilities. An Emacs "command" is any "interactive" Emacs
- function.
+ If I refer you to topic XXX:YYY, you need to type this:
- NOTE: Your system administrator may have bound other key sequences to
- invoke execute-extended-command. A function key labeled "Do" is a good
- candidate for this.
+ C-h i m emacs RET m XXX RET m YYY RET
- To run non-interactive Emacs functions, use M-ESC instead and type a
- Lisp form.
+ WARNING: Your system administrator may not have installed the Info files,
+ or may have installed them properly. In this case you should complain.
-6: What do things like this mean: etc/SERVICE, src/config.h,
- lisp/default.el?
+4: What do these mean: etc/SERVICE, src/config.h, lisp/default.el?
- These are the names of files that are part of the GNU Emacs
- distribution. The GNU Emacs distribution is so big that it is divided
- into several subdirectories; the important subdirectories are named
- "etc", "lisp", and "src".
+ These are files that come with GNU Emacs. The GNU Emacs distribution is
+ divided into subdirectories; the important ones are `etc', `lisp', and
+ `src'.
If you use GNU Emacs, but don't know where it is kept on your system,
start Emacs, then type "C-h v exec-directory RET". The directory name
- that is displayed by this will be the full pathname of the "etc"
- directory of your installed GNU Emacs distribution.
+ displayed by this will be the full pathname of the installed `etc'
+ directory.
Some of these files are available individually via FTP or e-mail, see
- question 16.
+ question 20. All are available in the source distribution.
-7: What are FSF, LPF, OSF, GNU, RMS, FTP, BTW, and GPL?
+5: What are FSF, LPF, OSF, GNU, RMS, FTP, and GPL?
FSF == Free Software Foundation
LPF == League for Programming Freedom
OSF == Open Software Foundation
GNU == GNU's Not Unix
- RMS == Richard M. Stallman
+ RMS == Richard Matthew Stallman
FTP == File Transfer Protocol
- BTW == By the way
GPL == GNU General Public Licence
- NOTE: Avoid confusing the FSF, the LPF, and the OSF. The LPF only
- opposes look-and-feel copyrights and software patents. The FSF aims to
- make high quality free software available for everyone. The OSF is a
- commercial organization which wants to provide an alternative,
- standardized version of Unix not controlled by AT&T.
+ NOTE: Avoid confusing the FSF, the LPF, and the OSF. The LPF opposes
+ look-and-feel copyrights and software patents. The FSF aims to make high
+ quality free software available for everyone. The OSF is a commercial
+ organization which wants to provide an alternative, standardized version
+ of Unix not controlled by AT&T.
+
+ NOTE: The word "free" in the title of the Free Software Foundation refers
+ to "freedom", not "zero dollars". Anyone can charge any price for
+ GPL-covered software that they want to. However, in practice, the freedom
+ enforced by the GPL leads to low prices, because you can always get the
+ software for less money from someone else, because everyone has the right
+ to resell or give away GPL-covered software.
-Sources of Information and Help
+General Questions
-8: I'm just starting GNU Emacs; how do I do basic editing?
+6: What is the LPF and why should I join it?
+
+ The LPF opposes the expanding danger of software patents and look-and-feel
+ copyrights. To get more information, feel free to contact the LPF via
+ e-mail or otherwise. {You may also contact me, jbw@cs.bu.edu; I will be
+ happy to talk with you about the LPF.} Here is the contact information: !
+
+ E-mail address: league@prep.ai.mit.edu
+ Phone number: (617) 243-4091 !
+ Postal address:
+ League for Programming Freedom
+ 1 Kendall Square, Number 143
+ Post Office Box 9171
+ Cambridge, MA 02139, USA
+
+ Papers describing the LPF's views are available on the internet and also !
+ from the LPF: !
+
+ Anonymous FTP:
+ /prep.ai.mit.edu:/pub/lpf/ +
+ /archive.cis.ohio-state.edu:pub/lpf/ !
+ Anonymous UUCP:
+ osu-cis!~/lpf/* -
+
+7: What is the real legal meaning of the GNU copyleft?
+
+ The real legal meaning of the GNU General Public Licence (copyleft) is
+ however it is interpreted by a judge. There has never been a copyright
+ infringment case involving the GPL to set any precedents. Please take any
+ discussion regarding this issue to the newsgroup gnu.misc.discuss, which
+ was created to hold the extensive flame wars on the subject.
- Type "C-h t" to invoke the self-paced tutorial. Typing just C-h is
- how to enter the help system.
+ RMS writes:
- WARNING: your system administrator may have changed C-h to act like DEL.
- You can use M-x help-for-help instead to invoke help. To discover what
- key (if any) invokes help on your system, type "M-x where-is RET
- help-for-help RET". This will print a comma-separated list of key
- sequences in the echo area. Ignore the last character in each key
- sequence listed. Each of the resulting key sequences invokes help.
+ The legal meaning of the GNU copyleft is less important than the spirit,
+ which is that Emacs is a free software project and that work pertaining
+ to Emacs should also be free software. "Free" means that all users have
+ the freedom to study, share, change and improve Emacs. To make sure
+ everyone has this freedom, pass along source code when you distribute
+ any version of Emacs or a related program, and give the recipients the
+ same freedom that you enjoyed.
- NOTE: Emacs's help facility works best if help is invoked by a single
- key. The variable help-char should hold the value of this character.
+8: What are appropriate messages for gnu.emacs.help, gnu.emacs.bug,
+ comp.emacs, etc.?
-9: How do I find out how to do something in GNU Emacs?
+ The file etc/MAILINGLISTS discusses the purpose of each GNU mailing-list.
+ (See question 20 on how to get a copy.) For those which are gatewayed
+ with newsgroups, it lists both the newsgroup name and the mailing list
+ address.
- There are several methods for finding out how to do things in Emacs.
+ comp.emacs is for discussion of Emacs programs in general. This
+ includes GNU Emacs along with various other implementations like JOVE,
+ MicroEmacs, Freemacs, MG, Unipress, CCA, Epsilon, etc.
- You should become familiar with the online documentation for Emacs. The
- complete text of the Emacs manual is available online in a hypertext
- format via the "Info" manual reader. Type "C-h i" to invoke Info.
+ Many people post GNU Emacs questions to comp.emacs because they don't
+ receive any of the gnu.* newsgroups. Arguments have been made both for
+ and against posting GNU-Emacs-specific material to comp.emacs. You have
+ to decide for yourself.
- You can order a hardcopy of the manual from the FSF. See question 12.
+ Messages advocating "non-free" software are considered unacceptable on any
+ of the gnu.* newsgroups except for gnu.misc.discuss, which was created to
+ hold the extensive flame-wars on the subject. "non-free" software
+ includes any software for which the end user can't freely modify the
+ source code and exchange enhancements. Be careful to remove the gnu.*
+ groups from the `Newsgroups:' line when posting a followup that recommends
+ such software.
- You can list all of the commands whose names contain a certain word
- (actually which match a regular expression) using the "command-apropos"
- command. Type "C-h a" to invoke this command.
+ gnu.emacs.bug is a place where bug reports appear, but avoid posting bug
+ reports to this newsgroup, instead see question 10.
- You can list all of the functions and variables whose names contain a
- certain word using the "apropos" command. M-x apropos invokes this
- command.
+9: Where can I get old postings to gnu.emacs.help and other GNU groups?
- You may find that command-apropos and apropos are extremely slow on your
- system. This will be fixed in Emacs 19. If you can't wait that long,
- I can send you the "fast-apropos.el" file that contains the fix. This
- file also contains a "super-apropos" command that will list all the
- functions and variables whose documentation strings contain a certain
- word.
+ The FSF has maintained archives of all of the GNU mailing lists for many
+ years, although there may be some unintentional gaps in coverage. The
+ archive is not particularly well organized or easy to retrieve individual
+ postings from, but pretty much everything is there.
- There are many other commands in Emacs for getting help and information.
- To get a list of these commands, type "C-h C-h C-h".
+ Anonymous FTP:
+ /prep.ai.mit.edu:/pub/gnu/emacs/MailingListArchives/ !
-10: Where can I get GNU Emacs on the net (or by snail mail)?
+ {There was a WAIS database named `comp-emacs' on lambada.oit.unc.edu that
+ makes available the last 10 days of articles in comp.emacs. It appears to
+ have died. Anyone know if it moved?}
- Look in the files etc/DISTRIB and etc/FTP for information. If you don't
- already have GNU Emacs, see question 16.
+10: Where should I report bugs and other problems with GNU Emacs?
-11: Where can I get help in installing GNU Emacs?
+ The correct way to report GNU Emacs bugs is by e-mail to
+ bug-gnu-emacs@prep.ai.mit.edu. Anything sent here also appears in the
+ newsgroup gnu.emacs.bug, but please use e-mail instead of news to submit
+ the bug report. This way a reliable return address is available so you
+ can be contacted for further details.
- Look in the file etc/SERVICE for names of companies and individuals who
- will sell you this type of service.
+ RMS explains:
- This file in the version 18.55 distribution is not completely up to
- date. The imminent release of 18.56 will help that. An up-to-date
- version of the SERVICE file is available on prep.ai.mit.edu. See
- question 16 for how to retrieve this file.
+ Sending bug reports to help-gnu-emacs (which has the effect of posting
+ on gnu.emacs.help) is undesirable because it takes the time of an
+ unnecessarily large group of people, most of whom are just users and
+ have no idea how to fix these problem. bug-gnu-emacs reaches a much
+ smaller group of people who are more likely to know what to do and have
+ expressed a wish to receive more messages about Emacs than the others.
-12: How do I get a printed copy of the GNU Emacs manual?
+ However, RMS says there are circumstances when it is okay to post to
+ gnu.emacs.help:
- You can order a printed copy of the GNU Emacs manual from the FSF for
- $15. A set of 6 manuals is $60.
+ If you have reported a bug and you don't hear about a possible fix, then
+ after a suitable delay (such as a week) it is okay to post on
+ gnu.emacs.help asking if anyone can help you.
- The full TeX source for the manual also comes with Emacs, if you're
- daring enough to try to print out this 300 page manual yourself. (We're
- talking about killing an entire tree here. This kind of printer usage
- can make you very unpopular. Besides, if you order it from the FSF, the
- price may be tax-deductible as a business expense.)
+ If you are unsure whether you have a bug, RMS describes how to tell:
- If you absolutely have to print your own copy, and you don't have TeX,
- you can get a PostScript version from:
+ ... if Emacs crashes, that is a bug. If Emacs gets compilation errors
+ while building, that is a bug. If Emacs crashes while building, that is
+ a bug. If Lisp code does not do what the documentation says it does,
+ that is a bug.
- Anonymous FTP:
- site: abcfd20.larc.nasa.gov
- file: /pub/docs/emacs-18.55.PS.Z (size: 472K)
+11: How do I unsubscribe to this mailing list?
- Carl Witty <cwitty@cs.stanford.edu> writes:
+ If you are receiving a GNU mailing list named `XXX', you might be able
+ to unsubscribe to it by sending a request to the address
+ `XXX-request@prep.ai.mit.edu'. However, this will not work if you are
+ not listed on the main mailing list, but instead recieve the mail from a
+ distribution point. In that case, you will have to track down at which
+ distribution point you are listed. Inspecting the `Received:' headers
+ on the mail messages may help, along with liberal use of the `EXPN' or
+ `VRFY' sendmail commands through `telnet <site-address> smtp'. Ask your
+ postmaster for help.
- The Emacs manual is also available online in the Info system, which is
- available by typing "C-h i". In this form, it has hypertext links and
- is very easy to browse or search; many people prefer it to the printed
- manual.
+12: What is the current address of the FSF?
-13: Has someone written an GNU Emacs Lisp package that does XXX?
+ E-mail address: gnu@prep.ai.mit.edu +
+ Phone number: (617) 876-3296 +
+ Postal address:
+ Free Software Foundation, Inc.
+ 675 Massachusetts Avenue
+ Cambridge, MA 02139, USA -
- Probably. A listing of Emacs Lisp packages, called the Lisp Code
- Directory, is being maintained by Dave Brennan <brennan@dg-rtp.dg.com>.
- You can search through this list to find if someone has written
- something that fits your needs.
+
+
+On-line Help, Printed Manuals, Other Sources of Help
+
+13: I'm just starting GNU Emacs; how do I do basic editing?
- This list is file "LCD-datafile.Z" in the Emacs Lisp Archive. (See
- question 14.) The files "lispdir.el.Z" and "lispdir.doc.Z"
- in the archive contain information to help you use the list.
+ Type "C-h t" to invoke the self-paced tutorial. Typing just C-h is
+ how to enter the help system.
-14: Where can I get GNU Emacs Lisp packages that don't come with Emacs?
+ WARNING: Your system administrator may have changed C-h to act like DEL to
+ deal local keyboards. You can use M-x help-for-help instead to invoke
+ help. To discover what key (if any) invokes help on your system, type
+ "M-x where-is RET help-for-help RET". This will print a comma-separated
+ list of key sequences in the echo area. Ignore the last character in each
+ key sequence listed. Each of the resulting key sequences invokes help.
- First, check the Lisp Code Directory to find the name of the package you
- are looking for. (See question 13). Then check local archives and
- the Emacs Lisp Archive to find a copy of the relevant files. Then, if
- you still haven't found it, you can send e-mail to the author asking for
- a copy.
+ NOTE: Emacs's help facility works best if help is invoked by a single key
+ whose value should be stored in the variable help-char. Andrew
+ Arensburger <arensb@kong.gsfc.nasa.gov> wrote a patch that allows the help
+ facility to work properly when invoked by multiple character sequences.
- You can access the Emacs Lisp Archive via:
+14: How do I find out how to do something in GNU Emacs?
- Anonymous FTP:
- site: tut.cis.ohio-state.edu
- directory: /pub/gnu/emacs/elisp-archive
- file: README.Z
+ There are several methods for finding out how to do things in Emacs.
+
+ * The complete text of the Emacs manual is available online via the Info
+ hypertext reader. Type "C-h i" to invoke Info.
+
+ * You can order a hardcopy of the manual from the FSF. See question 15.
+
+ * You can get a printed reference card listing commands and keys to invoke
+ them. You can order one from the FSF for $1 (or 10 for $5), or you can
+ print your own from the etc/refcard.tex file in the Emacs distribution.
+ {Are PostScript versions of this available for FTP?}
+
+ * You can list all of the commands whose names contain a certain word
+ (actually which match a regular expression) using "C-h a"
+ (M-x command-apropos).
- NOTE: Any files with names ending in ".Z" are compressed, and you should
- use "binary" mode in FTP to retrive them. You should also use binary
- mode whenever you retrieve any files with names ending in ".elc".
+ * You can list all of the functions and variables whose names contain a
+ certain word using M-x apropos.
- Submissions for the archive should be sent to Dave Sill <de5@ornl.gov>.
- If you have ftp access, the submission can be deposited in the directory
- /pub/gnu/emacs/elisp-archive/incoming on tut.cis.ohio-state.edu.
- Whenever possible submissions should contain an LCD-datafile entry since
- this helps reduce administrative overhead for the maintainers. Before
- submitting anything, first read the file "guidelines.Z", which is
- available in the archive.
+ * There are many other commands in Emacs for getting help and information.
+ To get a list of these commands, type "C-h C-h C-h".
-15: Where can I get documentation on GNU Emacs Lisp?
+ NOTE: You may find that command-apropos and apropos are extremely slow
+ on your system. This will be fixed in Emacs 19. If you can't wait that
+ long, there is a fast-apropos.el file available in the Emacs Lisp
+ Archive (see question 89) that contains the fix.
- Obtain the GNU Emacs Lisp Reference Manual for Emacs 18 under Unix. It
- is available from the FSF for $50. The latest revision is edition 1.02
- dated July 1990.
+15: How do I get a printed copy of the GNU Emacs manual?
+
+ You can order a printed copy of the GNU Emacs manual from the FSF for
+ $20. For 6 or more manuals the price is $13 each. The price may be -
+ tax-deductible as a business expense. -
+
+ The full TeX source for the manual also comes in the `man' directory of
+ the Emacs distribution, if you're daring enough to try to print out this
+ 300 page manual yourself (see question 18).
+
+ If you absolutely have to print your own copy, and you don't have TeX, you
+ can get a PostScript version via anonymous FTP: !
+ !
+ /cs.ubc.ca:src/gnu/manuals_ps/emacs-18.57.ps.Z !
+
+ which site requests that you please CONFINE ANY MAJOR FTPING TO LATE
+ EVENINGS OR EARLY MORNINGS OUR TIME (pacific time zone, GMT-8)). A DVI
+ version is also available via FTP: !
+ !
+ /prep.ai.mit.edu:pub/gnu/emacs-manual-6.0.dvi.Z !
+
+ If you don't have TeX you can convert the Texinfo sources into
+ {t,n,ps}roff format with the `texi2roff' program, which is available via
+ anonymous FTP: !
+ !
+ /archive.cis.ohio-state.edu:pub/gnu/texi2roff/texi2roff.shar.Z !
+
+ See also question 14 for how to view the manual online.
+
+16: Where can I get documentation on GNU Emacs Lisp?
Within Emacs, you can type "C-h f" to get the documentation for a
function, "C-h v" for a variable.
+ For more information, obtain the GNU Emacs Lisp Reference Manual for Emacs
+ 18 under Unix. It is available from the FSF for $50 (or 5 for $200). The
+ latest revision available for FTP is edition 1.03 dated 28 January 1991.
+
+ For online use, a set of pregenerated Info files is available with the
+ Texinfo source for the Emacs Lisp manual via anonymous FTP: !
+ !
+ /archive.cis.ohio-state.edu:pub/gnu/emacs/ !
+ /prep.ai.mit.edu:pub/gnu/elisp-manual-1.03.tar.Z !
+
+ (You can also create the Info files from the Texinfo source.) See
+ question 17 for details on how to install these files online.
+
+ If you are daring enough to try to print this 550 page manual out
+ yourself, for instructions see question 18.
+
Also, as a popular USENET saying goes, "Use the Force, Read the Source".
- You can also get the Texinfo source for the manual, if you are daring
- enough to try to print this 550 page manual out yourself. This is
- available in the Emacs Lisp Archive and also via:
+17: How do I install a piece of Texinfo documentation?
- Anonymous FTP:
- site: prep.ai.mit.edu
- file: /pub/gnu/elisp.tar.Z
+ First create Info files from the Texinfo files with the `makeinfo'
+ program. makeinfo is available as part of the latest Texinfo package: !
+ !
+ /prep.ai.mit.edu:pub/gnu/texinfo-2.14.tar.Z !
+
+ For information about the Texinfo format, read the Texinfo manual which
+ comes with Emacs. This manual also comes installed in Info format, so you
+ can read it online.
+
+ Neither texinfo-format-buffer nor the makeinfo program install the
+ resulting Info files in Emacs's Info tree. To install Info files:
- A set of pregenerated Info files comes with the Texinfo source for the
- Emacs Lisp manual, so you don't have to format it yourself for online
- use. (You can create the Info files from the Texinfo source.) See
- question 21 for details on how to install these files online.
+ 1. Move the files to the `info' directory in the installed Emacs
+ distribution. See question 4 if you don't know where that
+ is.
-16: What informational files are available?
+ 2. Edit the file info/dir in the installed Emacs distribution, and add a
+ line for the top level node in the Info package that you are
+ installing. Follow the examples are already in this file. The format
+ is:
- This isn't a frequently asked question, but it should be!
+ * Topic: (relative-pathname). Short description of topic.
- The following files are available in the "etc" directory of the GNU
- Emacs distribution, and also the latest versions are available
- individually via:
+ If you want to install Info files and you don't have the necessary
+ privileges, you have several options:
- Anonymous FTP:
- site: prep.ai.mit.edu
- directory: /pub/gnu/etc
+ * Info files don't actually need to be installed before being used. You
+ can feed a file name to the Info-goto-node command (invoked by pressing
+ "g" in Info mode) by typing the name of the file in parentheses. This
+ goes to the node named `Top' in that file. For example, to view a Info
+ file named `XXX' in your home directory, you can type this:
+
+ C-h i g (~/XXX) RET
+
+ * You can create your own Info directory. You can tell Emacs where the
+ Info directory is by setting the value of the variable Info-directory
+ to its pathname. For example, to use a private Info directory which
+ is a subdirectory of your home directory named `Info', you could do
+ this:
+
+ (setq Info-directory (expand-file-name "~/Info"))
+
+ You will need a top-level Info file named `dir' in this directory.
+ You can include the system-wide Info directory in your private Info
+ directory with symbolic links or by copying it.
+
+ * You can use an enhanced version of lisp/info.el that handles multiple
+ Info directories. Then you can more easily use a mix of private and
+ shared Info files. Dave Gillespie <daveg@synaptics.com,
+ daveg@csvax.cs.caltech.edu> has written one such enhancement and I
+ believe there are others. Dave's info.el also handles compressed Info
+ files.
+
+ Anonymous FTP:
+ /archive.cis.ohio-state.edu:modes/info.el.Z !
+ /cs.umn.edu:pub/gnu/emacs/info.el.Z +
+
+ According to Jay Bourland <jayb@math.stanford.edu>, a version of Dave's
+ info.el comes with `xinfo' (see question 19).
+
+18: How do I print a Texinfo file?
+
+ NOTE: You can't get nice printed output from Info files; you must still
+ have the original Texinfo source file for the manual you want to print.
+
+ 1. Make sure the first line of the Texinfo file looks like this:
+
+ \input texinfo
+
+ You may need to alter `texinfo' to the full pathname of the
+ texinfo.tex file, which comes with Emacs as man/texinfo.tex (or copy
+ or link it into the current directory).
- APPLE -- Special Report: Apple's New Look and Feel
+ 2. tex XXX.texinfo
+
+ 3. texindex XXX.??
+
+ The `texindex' program comes with Emacs as man/texindex.c.
+
+ 4. tex XXX.texinfo
+
+ 5. Print the DVI file XXX.dvi in the normal way for printing DVI files
+ at your site.
+
+ To get more general instructions, retrieve the latest Texinfo package
+ mentioned in question 17.
+
+19: Can I view Info files without using GNU Emacs?
+
+ Yes, the `info', `xinfo', and `ivinfo' programs do this. info uses
+ curses, xinfo uses standard X11 libraries, and ivinfo uses InterViews.
+ You can get info as part of the latest Texinfo package (see question
+ 17). xinfo is available separately: !
+ !
+ /prep.ai.mit.edu:pub/gnu/xinfo-1.01.01.tar.Z !
+ /export.lcs.mit.edu: !
+
+ ivinfo is available in a comp.sources.misc archive or from Tom Horsley
+ <tom@ssd.csd.harris.com>. For ivinfo, you need Stanford's InterViews C++
+ X library, available via anonymous FTP (interviews.stanford.edu).
+
+20: What informational files are available for GNU Emacs?
+
+ This isn't a frequently asked question, but it should be! A variety of
+ informational files about GNU Emacs and relevant aspects of the GNU
+ project are available for you to read.
+
+ The following files are available in the `etc' directory of the GNU
+ Emacs distribution, and also the latest versions are available
+ individually via anonymous FTP (prep.ai.mit.edu:/pub/gnu/GNUinfo/):
+
+ APPLE -- Why the FSF doen't support GNU Emacs on Apple computers
DISTRIB -- GNU Emacs Availability Information,
including the popular "Free Software Foundation Order Form"
FTP -- How to get GNU Software by Internet FTP or by UUCP
@@ -355,9 +768,9 @@ Sources of Information and Help
MACHINES -- Status of GNU Emacs on Various Machines and Systems
MAILINGLISTS -- GNU Project Electronic Mailing Lists
SERVICE -- GNU Service Directory
- SUN-SUPPORT -- includes the popular "Using Emacstool with GNU Emacs"
+ SUN-SUPPORT -- including "Using Emacstool with GNU Emacs"
- These files are available in the "etc" directory of the GNU Emacs
+ These files are available in the `etc' directory of the GNU Emacs
distribution:
DIFF -- Differences between GNU Emacs and Twenex Emacs
@@ -365,459 +778,2439 @@ Sources of Information and Help
GOSDIFF -- Differences between GNU Emacs and Gosling (Unipress??) Emacs
COPYING -- GNU Emacs General Public License
NEWS -- GNU Emacs News, a history of user-visible changes
+ LPF -- Why you should join the League for Programming Freedom
+ FAQ -- GNU Emacs Frequently Asked Questions (You're reading it)
+ OPTIONS -- a complete explanation of startup option handling
+
+ These files are available via anonymous FTP (prep.ai.mit.edu:/pub/gnu/):
+
+ tasks -- GNU Task List
+ standards.text -- GNU Coding Standards
In addition, all of the above files are available directly from the FSF
via e-mail. Of course, please try to get them from a local source
first.
- These files are available from the FSF via e-mail:
-
- * GNU's Bulletin, June, 1990 -- this file includes:
- GNU'S Who
- What Is the Free Software Foundation?
- What Is Copyleft?
- GNUs Flashes
- Possible New Terms for GNU Libraries by Richard Stallman
- "League for Programming Freedom" by Michael Bloom and Richard Stallman
- Free Software Support
- GNU Project Status Report
- GNU Wish List
- GNU Documentation
- GNU Software Available Now
- Contents of the Emacs Release Tape
- Contents of the Pre-Release Tape
- Contents of the X11 Tapes
- VMS Emacs and Compiler Tapes
- How to Get GNU Software
- Freemacs, an Extensible Editor for MS-DOS
- Thank GNUs
- FSF Order Form
- * GNU Task List
- * GNU Coding Standards
- * Legal issues about contributing code to GNU
- * GNU Project Status Report
-
-17: What is the current address of the FSF?
-
- Snail mail address:
- Free Software Foundation
- 675 Massachusetts Avenue
- Cambridge, MA 02139, USA
+ These additional files are available from the FSF via e-mail:
+
+ * GNU's Bulletin, June, 1991 -- this file includes:
+ GNU'S Who
+ What Is the Free Software Foundation?
+ What Is Copyleft?
+ A Small Way to Help Free Software
+ GNUs Flashes (important recent developments for project GNU)
+ Free Software Support (and how to get it!)
+ Copyrighted Programming Languages
+ AT&T Threatens Users of X Windows (and other software patent threats)
+ Project Gutenberg
+ GNU Project Status Report
+ GNU in Japan
+ GNU Wish List
+ Help Keep Government Software Free
+ GNU Software Available Now
+ Contents of the Emacs Tape
+ Contents of the Compiler Tape
+ Contents of the X11 Tapes
+ VMS Emacs and Compiler Tapes
+ GNU Documentation
+ How to Get GNU Software
+ Free Software for Microcomputers
+ GNU Software on Apple computers
+ GNU Software on the Amiga
+ GNU Software on the Atari
+ GNUish MS-DOS project
+ Freemacs, an Extensible Editor for MS-DOS
+ GNU in Japan
+ FSF Order Form
+ Thank GNUs
+ * Legal issues about contributing code to GNU
+ * GNU Project Status Report
+
+ A collection of past GNU's Bulletins is available via anonymous FTP: +
+ +
+ /ftp.funet.fi:pub/gnu/Bulletins/ +
+
+21: Where can I get help in installing GNU Emacs?
+
+ Look in etc/SERVICE for names of companies and individuals who will sell
+ you this type of service. An up-to-date version of the SERVICE file is
+ available on prep.ai.mit.edu (also see question 20).
+
+22: Where can I get the latest version of this document (the FAQ list)?
+
+ The GNU Emacs FAQ is available in several ways:
+
+ * Via USENET. If you can read news, the FAQ should be available in your
+ news spool, in both the gnu.emacs.help and comp.emacs newsgroups. Every
+ news reader of which I know will allow you to read any news article that
+ is still in the news spool, even if you have read the article before.
+ You may need to read the instructions for your news reader to discover
+ how to do this. In `rn', this command will do this for you at the
+ article selection level:
+
+ ?GNU Emacs FAQ?rc:m
+
+ In GNUS, you should type "C-u G" from the *Subject* buffer or "C-u SPC"
+ from the *Newsgroup* buffer to view all articles in a newsgroup.
+
+ The FAQ articles' message IDs are:
+
+ <GNU-Emacs-FAQ-0.1992.09.22.011020@bigbird.bu.edu> !
+ <GNU-Emacs-FAQ-1.1992.09.22.011020@bigbird.bu.edu> !
+ <GNU-Emacs-FAQ-2.1992.09.22.011020@bigbird.bu.edu> !
+ <GNU-Emacs-FAQ-3.1992.09.22.011020@bigbird.bu.edu> !
+ <GNU-Emacs-FAQ-4.1992.09.22.011020@bigbird.bu.edu> !
+ <GNU-Emacs-FAQ-5.1992.09.22.011020@bigbird.bu.edu> !
+
+ If you are viewing this in the GNUS *Article* buffer, you can move point
+ within one of the above message IDs and type "r" to fetch the referenced
+ article. Type "o" in the *Article* buffer to restore the previous
+ contents. If this text is not in the GNUS *Article* buffer, use M-r
+ from the *Subject* buffer instead.
+
+ If the FAQ articles have expired and been deleted from your news spool,
+ it might (or might not) do some good to complain to your news
+ administrator, because the most recent FAQ should not expire before
+ November 21, 1992. !
+
+ * Via anonymous FTP. You can fetch the FAQ articles via anonymous FTP
+
+ /rtfm.mit.edu:pub/usenet/news.answers/GNU-Emacs-FAQ/ part* !
+
+ * Via e-mail. You can send the following magical incantation in the body
+ of a message to mail-server@rtfm.mit.edu:
+
+ send usenet/news.answers/GNU-Emacs-FAQ/part0
+ send usenet/news.answers/GNU-Emacs-FAQ/part1
+ send usenet/news.answers/GNU-Emacs-FAQ/part2
+ send usenet/news.answers/GNU-Emacs-FAQ/part3
+ send usenet/news.answers/GNU-Emacs-FAQ/part4
+ send usenet/news.answers/GNU-Emacs-FAQ/part5
+
+ * Via WAIS. The GNU Emacs FAQ is available via WAIS indexed on a
+ per-question basis from the `faq' database on bigbird.bu.edu on the
+ non-standard IP port number of 2210. This is probably the best way to
+ find out if there is something in the FAQ related to your question. I
+ use this myself to answer questions I see posted on gnu.emacs.help.
+
+ The articles of the GNU Emacs FAQ are also available from the `usenet'
+ database on rtfm.mit.edu (on the standard IP port: 210), along with a
+ lot of other FAQ articles. However, these are all indexed at the whole
+ article level instead of at the question level. This is a better place
+ to look if you want to fetch the entire FAQ.
+
+ * In the GNU Emacs distribution. Since GNU Emacs 18.56, the latest
+ available version of the FAQ at the time of release has been part of the
+ GNU Emacs distribution as file etc/FAQ. 18.58 is the latest version,
+ and it was released in February 1992.
+
+ * There is an old version of the FAQ list available for FTP in the GNU +
+ archives at MIT: +
+ +
+ /prep.ai.mit.edu:pub/gnu/GNUinfo/FAQ.emacs +
+ +
+ * As the very last resort, you can e-mail a request to +
+ gnu-emacs-faq-maintainers@bigbird.bu.edu. Don't do this unless you have
+ made a serious effort to obtain the FAQ list via one of the methods
+ listed above.
- Phone number:
- (617) 876-3296
+
+
+Status of Emacs
+
+23: Where does the name "Emacs" come from?
- E-mail addresses:
- gnu@prep.ai.mit.edu {probably read by Len Tower}
- gnulists@prep
+ Emacs originally was an acronym for Editor MACroS. RMS says he "picked
+ the name `Emacs' because `E' was not in use as an abbreviation on ITS at
+ the time.". The first Emacs was a set of macros written in 1976 at MIT by
+ RMS for the editor TECO (Text Editor and COrrector (originally Tape Editor
+ and COrrector)) under ITS on a PDP-10. RMS had already extended TECO with
+ a "real-time" full screen mode with active keys. Emacs was started by Guy
+ Steele <gls@think.com> as a project to unify the many divergent TECO
+ command sets and keybindings at MIT.
-18: What is the current address of the LPF?
+ Many people have told me that TECO code looks a lot like line noise. See
+ alt.lang.teco if you are interested. I think someone has written a TECO
+ implementation in Emacs Lisp. It would be an interesting project to run
+ the original TECO Emacs inside of GNU Emacs.
- Snail mail address:
- League for Programming Freedom
- 1 Kendall Square, Number 143
- Post Office Box 9171
- Cambridge, MA 02139, USA
+24: What is the latest version of GNU Emacs?
- Phone number:
- (617) 243-4061 { or 243-4091, I'm not sure ... }
+ GNU Emacs 18.58 is the current version. Fixes from 18.57 include better
+ mail address parsing, an X visual bell speedup, a call-process
+ enhancement, a regexp matching change, the ability to apply a numeric
+ argument to a self-inserting digit, getting X resource values from the
+ RESOURCE_MANAGER property, more reliable shell mode job control, and a
+ change to copy-keymap. Also, support has been added for many new system
+ types. Fixes from 18.55 include the removal of arbitrary limits on the
+ undo facility.
- E-mail address:
- league@prep.ai.mit.edu
+ According to the January 1992 GNU's Bulletin, "Emacs 18 maintenance
+ continues for simple bug fixes.".
-19: Where can I get the up-to-date GNU stuff?
+ To visit a file with information about what has changed in recent
+ versions, type "C-h n".
- The most up-to-date official GNU stuff is normally kept on
- prep.ai.mit.edu and is available for anonymous FTP. See the files
- etc/DISTRIB and etc/FTP for more information. (To get copies of these
- files, see question 16.)
+25: When will GNU Emacs 19 be available?
-20: Where can I get the latest VM, Supercite, GNUS, Calc, Calendar, or Patch?
+ There are strong indications that Emacs 19 will be available in 1992. The
+ FSF has recently gone through a spate of copyright disclaimer checking,
+ which is a good sign.
- 1. VM:
+ Lucid has released Lucid GNU Emacs 19.2, which is based on an early
+ unreleased version of GNU Emacs 19. This will be similar to Emacs 19 when
+ it finally arrives, but they are not the same. See question 121.
- Author: Kyle Jones <kyle@xanth.cs.odu.edu>
+ Work has begun on features for Emacs 20.
- Mailing lists: info-vm-request@uunet.uu.net
- info-vm@uunet.uu.net
- bug-vm-request@uunet.uu.net
- bug-vm@uunet.uu.net
+26: What is different about GNU Emacs 19?
- Anonymous FTP:
+ From the January 1992 GNU's Bulletin:
- Last released version: 4.41
- site: tut.cis.ohio-state.edu
- file: /pub/gnu/vm/vm-4.41.tar.Z
+ Version 19 will enter beta test late this year. Among its new features
+ are: before and after change hooks, source-level debugging of Emacs Lisp
+ programs, X selection processing (including clipboard selections),
+ scrollbars, support for European character sets, floating point numbers,
+ per-buffer mouse commands, X resource manager interfacing,
+ mouse-tracking, Lisp-level binding of function keys, multiple X windows
+ (`screens' to Emacs), a new input system, and buffer allocation, which
+ uses a new mechanism capable of returning storage to the system when a
+ buffer is killed.
- Beta test version: 5.18
- site: abcfd20.larc.nasa.gov
- directory: /pub/vm
+ The input stream is now a sequence of Lisp objects, instead of a
+ sequence of characters. This allows a reasonable representation for
+ mouse clicks, function keys, menu selections, etc.
- 2. Supercite:
+ Thanks go to Alan Carroll and the people who worked on Epoch for
+ generating initial feedback to a multi-windowed Emacs, and to Eric
+ Raymond for help in polishing the Emacs 19 Lisp libraries.
- Author: Barry Warsaw <warsaw@warsaw.nlm.nih.gov>
+ The June 1991 GNU's bulletin had this to say about future plans for Emacs:
- Latest version: 2.1
+ Features being considered for later releases of Emacs include:
+ associating property lists with regions of text in a buffer; multiple
+ fonts, color, and pixmaps defined by those properties; different
+ visibility conditions for the regions, and for various windows showing
+ one buffer; hooks to be run if point or mouse moves outside a certain
+ range; incrementally saving undo history in a file; static menu bars;
+ and better pop-up menus.
- Mailing lists: supercite@warsaw.nlm.nih.gov
- supercite-request@warsaw.nlm.nih.gov
+ Mention of this feature disappeared in the January 1992 GNU's bulletin:
- Anonymous FTP:
- site: durer.cme.nist.gov [129.6.32.4]
- files:/pub/gnu/elisp/supercite-2.1.shar.0# (where # is replaced by 1 or 2)
+ Emacs 19 supports two styles of multiple windows, one with a separate
+ screen for the minibuffer, and another with a minibuffer attached to
+ each screen.
- NOTE: Superyank is an old version of Supercite.
+ Mention of these two proposed features disappeared in the January 1991
+ GNU's bulletin:
- 3. GNUS:
+ * Incremental syntax analysis for various programming languages (Leif).
+ * A more sophisticated emacsclient/server model, which would provide
+ network transparent Emacs widget functionality.
- Author: Masanobu Umeda
+27: What variants of GNU Emacs exist?
+
+ * Nemacs (Nihongo Emacs), which can handle Japanese text, is derived from +
+ GNU Emacs 18.55. See question 149.
+
+ * Demacs, which can run under MS-DOS on 386 machines, is derived from
+ Nemacs. See question 122.
+
+ * Epoch, which has better X support, is derived from GNU Emacs 18.58.
+ See question 120 and 92.
+
+ * Nepoch (Nihongo Epoch), which can handle Japanese text, is derived from +
+ Epoch. +
+ +
+ * Mule (the MULtilingual Enhancement of GNU Emacs) can handle many +
+ character sets simultaneously. It is derived from Emacs 18.58. It is +
+ available for FTP: +
+ +
+ /sh.wide.ad.jp:/JAPAN/mule/ +
+ /etlport.etl.go.jp:/pub/mule/ +
+ +
+ * Lucid GNU Emacs is derived from an early unreleased version of GNU Emacs +
+ 19. See question 121 and 92.
+
+ GNU Emacs FAQ: Common Requests/Problems
+
+If you are viewing this text in a GNU Emacs Buffer, you can type "M-2 C-x $" to
+get an overview of just the questions. Then, when you want to look at the text
+of the answers, just type "C-x $".
+
+To search for a question numbered XXX, type "M-C-s ^XXX:", followed by a C-r if
+that doesn't work, then type ESC to end the search.
+
+A `+' in the 78th column means something was inserted on the line. A `-' means
+something was deleted and a `!' means some combination of insertions and
+deletions occurred.
+
+Full instructions for getting the latest FAQ are in question 22. Also see the
+`Introduction to news.answers' posting in the `news.answers' newsgroup, or send
+e-mail to `mail-server@rtfm.mit.edu' with `help' on a body line, or use FTP,
+WAIS, or Prospero to rtfm.mit.edu.
+
+
+
+Common Things People Want To Do
+
+28: How do I set up a .emacs file properly?
- Latest version: 3.13
+ See `Init File' in the on-line manual.
- Anonymous FTP:
- site: tut.cis.ohio-state.edu
- files: /pub/gnu/gnus/3.13.##-of-11.Z (where ## is replaced by 00 -- 11)
+ WARNING: In general, new Emacs users should not have .emacs files, because
+ it causes confusing non-standard behavior. Then they send questions to
+ help-gnu-emacs asking why Emacs isn't behaving as documented. :-)
- 4. Calc:
+29: How do I debug a .emacs file?
- Author: Dave Gillespie <daveg@csvax.cs.caltech.edu>
+ First start Emacs with the `-q' command line option. Then, in the
+ *scratch* buffer, type the following:
- Latest version: 1.06
+ (setq debug-on-error t) LFD
+ (load-file "~/.emacs") LFD
- Anonymous FTP:
- site: csvax.cs.caltech.edu [131.215.131.131]
- or any comp.sources.misc archive
+ (Type LFD by pressing C-j.)
- 5. Calendar/Diary
+ If you have an error in your .emacs file, this will invoke the debugger
+ when the error occurs. If you don't know how to use the debugger do
+ (setq stack-trace-on-error t) instead.
- Author: Ed Reingold <reingold@cs.uiuc.edu>
+ WARNING: this will not discover errors caused by trying to do something
+ that requires the terminal/window-system initialization code to have
+ been loaded. See question 127.
- Latest version: 4
+30: How do I make Emacs display the current line (or column) number?
- E-mail:
- Subject: send-emacs-cal
- body: your best internet e-mail address
+ To find out what line of the buffer you are on right now, do "M-x
+ what-line". Use "M-x goto-line" to go to a specific line. To find the
+ current column number, type "M-ESC (current-column)".
- 6. Patch
+ Typing "C-x l" will also tell you what line you are on, provided the
+ buffer isn't separated into "pages" with C-l characters. In that case, it
+ will only tell you what line of the current "page" you are on. WARNING:
+ "C-x l" gives the wrong value when point is at the beginning of a line.
- Author: Larry Wall <lwall@jpl-devvax.jpl.nasa.gov>
+ There is no "correct" way to constantly display the current (or total)
+ line (or column) number on the mode line in Emacs 18, or to display the
+ line numbers next to the lines like vi can. Emacs is not a line-oriented
+ editor, and really has no idea what "lines" of the buffer are displayed in
+ the window. It would require a lot of work at the C code level to make
+ Emacs keep track of this. It would not be that hard to get the column
+ number, but it would still require changes at the C code level.
- Latest version: 2.0 patchlevel 12
+ None of the vi emulation modes provide the `set number' capability of vi
+ (as far as I know).
- Anonymous FTP:
- site: any comp.sources.unix archive
+ Emacs 19 will probably be able to show the line number on the mode-line,
+ but probably very inefficiently.
- or, for Europeans:
+ People have written various kludges to display line numbers. One is
+ `display-line-numbers' by Wayne Mesard <wmesard@tofu.oracle.com,
+ Mesard@bbn.com>. Look in the Lisp Code Directory. (See question
+ 88.)
- site: archive.cs.ruu.nl [131.211.80.5]
- file: /pub/UNIX/patch-2.0.tar.Z
+31: How do I turn on Abbrevs by default just in mode XXX?
-21: How do I install a piece of Texinfo documentation?
+ Put this in your .emacs file:
- First create Info files from the Texinfo files with M-x
- texinfo-format-buffer. There is also a program called "makeinfo" that
- provides better error checking and runs faster. Currently, it comes
- with the Emacs Lisp manual (which comes on the GNU Emacs tape).
+ (condition-case ()
+ (read-abbrev-file nil t)
+ (file-error nil))
- For information about the Texinfo format, read the Texinfo manual which
- comes with Emacs. This manual also comes installed in Info format, so
- you can read it online.
+ (setq XXX-mode-hook
+ (function
+ (lambda ()
+ (setq abbrev-mode t))))
- Neither texinfo-format-buffer nor the makeinfo program install the
- resulting Info files in Emacs's Info tree. To install Info files:
+32: How do I turn on Auto-Fill mode by default?
- 1. Move the files to the "info" directory in the installed Emacs
- distribution. See question 6 if you don't know where that
- is.
+ To turn on Auto-Fill mode just once for one buffer, use "M-x
+ auto-fill-mode". To turn it on for every buffer in, for example, Text
+ mode, do this:
- 2. Edit the file info/dir in the installed Emacs distribution, and add a
- line for the top level node in the Info package that you are
- installing.
+ (setq text-mode-hook 'turn-on-auto-fill)
-22: What is the real legal meaning of the GNU copyleft?
+ If you want Auto-Fill mode on in all major modes, do this:
- RMS writes:
+ (setq-default auto-fill-hook 'do-auto-fill)
- The legal meaning of the GNU copyleft is less important than the spirit,
- which is that Emacs is a free software project and that work pertaining
- to Emacs should also be free software. "Free" means that all users have
- the freedom to study, share, change and improve Emacs. To make sure
- everyone has this freedom, pass along source code when you distribute
- any version of Emacs or a related program, and give the recipients the
- same freedom that you enjoyed.
+33: How do I make Emacs use a certain major mode for certain files?
- If you still want to find out about the legal meaning of the copyleft,
- please ask yourself if this means you are not paying attention to the
- spirit.
+ If you want to use XXX mode for all files which end with the extension
+ `.YYY', this will do it for you:
-23: What are appropriate messages for gnu.emacs.help/gnu.emacs.bug/comp.emacs
- etc.?
+ (setq auto-mode-alist (cons '("\\.YYY\\'" . XXX-mode) auto-mode-alist))
- The file etc/MAILINGLISTS discusses the purpose of each GNU
- mailing-list. (See question 16 on how to get a copy.) For
- those which are gatewayed with newsgroups, it lists both the newsgroup
- name and the mailing list address.
+ Otherwise put this somewhere in the first line of any file you want to
+ edit in XXX mode:
- comp.emacs is for discussion of Emacs programs in general. This
- includes GNU Emacs along with various other implementations like JOVE,
- MicroEmacs, Freemacs, MG, Unipress, CCA, etc.
+ -*-XXX-*-
- Many people post GNU Emacs questions to comp.emacs because they don't
- receive any of the gnu.* newsgroups. Arguments have been made both for
- and against posting GNU-Emacs-specific material to comp.emacs. You have
- to decide for yourself.
+34: How do I search for, delete, or replace unprintable (8-bit or control)
+ characters?
+
+ To search for a single character that appears in the buffer as, for
+ example, `\237', you can type "C-s C-q 2 3 7". (This assumes the value of
+ search-quote-char is 17 (ie., C-q).) Searching for ALL unprintable
+ characters is best done with a "regexp" search. The easiest regexp to use
+ for the unprintable chars is the complement of the regexp for the
+ printable chars.
+
+ Regexp for the printable chars: [\t\n\r\f -~]
+
+ Regexp for the unprintable chars: [^\t\n\r\f -~]
+
+ To type some of these special characters in an interactive argument to
+ isearch-forward-regexp or re-search-forward, you need to use C-q. (`\t',
+ `\n', `\r', and `\f' stand respectively for TAB, LFD, RET, and C-l.) So,
+ to search for unprintable characters using re-search-forward:
+
+ M-x re-search-forward RET [^ TAB C-q LFD C-q RET C-q C-l SPC -~] RET
+
+ Using isearch-forward-regexp:
+
+ M-C-s [^ TAB RET C-q RET C-q C-l SPC -~]
+
+ To delete all unprintable characters, simply use a replace-regexp:
+
+ M-x replace-regexp RET [^ TAB C-q LFD C-q RET C-q C-l SPC -~] RET RET
+
+ Replacing is similar to the above. {I need to write the text for this
+ part of the answer!}
+
+ Notes:
+
+ * With isearch, you can type RET to get a quoted LFD (not a quoted RET).
+
+ * You don't need to quote TAB with either isearch or typing something in
+ the minibuffer.
-24: Should I send questions directly to people who post a lot on the net,
- instead of posting myself?
+ Here are the Emacs Lisp forms of the above regexps:
- I don't know about the others, but please don't send such messages to me
- just because you don't want to disturb a lot of people. Send messages
- to individuals that concern things that individual has written.
+ ;; regexp matching all printable characters:
+ "[\t\n\r\f -~]"
+
+ ;; regexp matching all unprintable characters:
+ "[^\t\n\r\f -~]"
+
+35: How can I highlight a region of text in Emacs?
+
+ There are ways to get highlighting (reverse video, inverse video) in GNU
+ Emacs 18.58, but either they require patching the C code of Emacs and
+ rebuilding, or they are slow and the highlighting disappears if you scroll
+ or redraw the screen and it can not follow the point. Howard Gayle's
+ patches for 8-bit output appear to allow highlighting (see question
+ ^8-bit-output). Another patch for highlighting is by Kenichi Handa
+ <handa@etl.go.jp>. There is a patch for use with X by Andy Norman
+ <ange@hplb.hpl.hp.com> (and modified for 18.57 by Matthieu Herrb
+ <matthieu@laas.fr>), which is available for FTP: !
+ !
+ /laas.laas.fr:pub/emacs/patch-X11-18.5{5,7} !
+
+ You can highlight regions in a variety of ways in Epoch and Lucid Emacs.
+ GNU Emacs 19 may not be able to just temporarily highlight a region. !
+
+ Similar comments apply to displaying text in different fonts, except that
+ it is even harder.
+
+36: How do I control Emacs's case-sensitivity when searching/replacing?
+
+ For searching, the value of the variable case-fold-search determines
+ whether they are case sensitive:
+
+ (setq case-fold-search nil) ; make searches case sensitive
+ (setq case-fold-search t) ; make searches case insensitive
+
+ Similarly, for replacing the variable case-replace determines whether
+ replacements preserve case.
+
+ To change the case sensitivity just for one major mode, use the major
+ mode's hook. For example:
+
+ (setq XXX-mode-hook
+ (function
+ (lambda ()
+ (setq case-fold-search nil))))
+
+37: How do I make Emacs wrap words for me?
+
+ M-x auto-fill-mode. The default maximum line width is 74, determined by
+ the variable fill-column. To find how to turn this on automatically see
+ question 32.
+
+38: Where can I get a better spelling checker for Emacs?
+
+ Use Ispell. See question 119.
+
+39: How can I spell-check TeX or *roff documents?
+
+ If you want to spell-check TeX or *roff documents with Ispell, you need to
+ arrange for a filter program that understands how to strip TeX or *roff
+ formatting commands to be run. In the TeX distribution, there are several
+ different programs named `detex', all with incompatible options, and a
+ very old pair of programs named `detex' and `delatex', which should
+ probably be avoided. The most useful one for Ispell is `detex' by Daniel
+ Trinkle. A more recent version is available via FTP: !
+ !
+ /arthur.cs.purdue.edu:pub/trinkle/detex-2.3.tar.Z !
+
+ Raphael Cerf <cerf@clipper.ens.fr> recently released a program for this +
+ named `xetal': !
+ !
+ /spi.ens.fr:pub/unix/tex/ !
+
+ There is a program that comes with Unix named `deroff' for stripping
+ formatting commands from *roff files.
+
+ Here is an example of code you can put in a .emacs file to use these
+ programs:
+
+ ;; Based on suggestions by David G. Grubbs <dgg@ksr.com> and Paul Palmer
+ ;; <palmerp@math.orst.edu>.
+
+ ;; Assuming the use of detex 2.3 by Daniel Trinkle:
+ ;; -w means one word per line.
+ ;; -n means don't expand \input or \include commands.
+ ;; -l means force LaTeX mode.
+
+ (require 'ispell) ; for the make-variable-buffer-local statements
+ (setq plain-TeX-mode-hook
+ (function
+ (lambda ()
+ (setq ispell-filter-hook "detex")
+ (setq ispell-filter-hook-args '("-nw")))))
+ (setq LaTeX-mode-hook
+ (function
+ (lambda ()
+ (setq ispell-filter-hook "detex")
+ (setq ispell-filter-hook-args '("-lnw")))))
+ (setq nroff-mode-hook
+ (function
+ (lambda ()
+ (setq ispell-filter-hook "deroff")
+ (setq ispell-filter-hook-args '("-w")))))
+
+ You will have to adjust the arguments for programs other than Trinkle's
+ detex or for other versions of deroff. Experiment running the command
+ from the shell to find the correct options. If you don't have a filter
+ that knows how to output one word per line, you must pipe its output
+ through another filter to break up the output.
+
+40: How do I change load-path?
+
+ In general, you should only *add* to the load-path. You can add
+ directory /XXX/YYY to the load path like this:
+
+ (setq load-path (append load-path '("/XXX/YYY/")))
+
+ To do this relative to your home directory:
+
+ (setq load-path (append load-path (list (expand-file-name "~/YYY/"))))
+
+41: How do I use an already running Emacs from another window?
+
+ The `emacsclient' program is for editing a file using an already running
+ Emacs rather than starting up a new Emacs. It does this by sending a
+ request to the already running Emacs, which must be expecting the request.
+
+ * Setup
+
+ Emacs must have executed the `server-start' function for emacsclient to
+ work. This can be done either by a command line option:
+
+ emacs -f server-start
+
+ or by invoking server-start from the .emacs file:
+
+ (if (some conditions are met) (server-start))
+
+ When this is done, Emacs starts a subprocess running a program called
+ `server'. `server' creates a Unix domain socket in the user's home
+ directory named `.emacs_server'.
+
+ To get your news reader, mail reader, etc., to invoke emacsclient, try
+ setting the environment variable EDITOR (or sometimes VISUAL) to the
+ value `emacsclient'. You may have to specify the full pathname of the
+ emacsclient program instead. Examples:
+
+ # csh commands:
+ setenv EDITOR emacsclient
+ setenv EDITOR /usr/local/emacs/etc/emacsclient # using full pathname
+
+ # sh command:
+ EDITOR=emacsclient export EDITOR
+
+ * Normal use
+
+ When emacsclient is run, it connects to the `.emacs_server' socket and
+ passes its command line options to `server'. When `server' receives
+ these requests, it sends this information on the the Emacs process,
+ which at the next opportunity will visit the files specified. (Line
+ numbers can be specified just like with Emacs.) The user will have to
+ switch to the Emacs window by hand. When the user is done editing a
+ file, the user can type "C-x #" to indicate this. This will switch to
+ another buffer created at the request of emacsclient if there are any.
+ When "C-x #" has been invoked on all of the files that the emacsclient
+ requested to be edited, Emacs will send notification of this to `server'
+ which will pass this on to the emacsclient, which will then exit.
+
+ NOTE: `emacsclient' and `server' must be running on machines which share
+ the same filesystem for this to work. The pathnames that emacsclient
+ specifies should be correct for the filesystem that the Emacs process
+ sees. The Emacs process should not be suspended at the time emacsclient
+ is invoked. emacsclient should either be invoked from another X window or
+ from a shell window inside Emacs itself.
+
+ There is an enhanced version of emacsclient/server called `gnuserv' by
+ Andy Norman <ange@hplb.hpl.hp.com> which is available in the Emacs Lisp
+ Archive. gnuserv uses Internet domain sockets, so it can work across most
+ network connections. It also supports the execution of arbitrary Emacs
+ Lisp forms and also does not require the client program to wait for
+ completion. It is available via anonymous FTP (Emacs Lisp Archive:
+ packages/gnuserv.shar).
+
+42: How do I make Emacs recognize my compiler's funny error messages?
+
+ Write a program which runs the compiler as a child and filters its output,
+ rearranging as necessary. Install with same name as compiler somewhere in
+ path.
+
+ Keith Moore <moore@cs.utk.edu> wrote one such for a C compiler under AIX.
+ Available via FTP: !
+ !
+ /cs.utk.edu:readonly/aixcc.lex !
+
+ Jim Frost <jimf@saber.com> wrote another for the IBM xlc compiler on the
+ RS/6000. (I don't know if these are both for the same compiler.)
+ Johnathan Vail <vail@tegra.COM> wrote something for a High C compiler
+ (`hc', which is one of the compilers on the RS/6000, although I think
+ Johnathan wrote his program for hc on a different computer).
+
+43: How do I indent switch statements like this?
+
+ Many people want to indent their switch statements like this:
+
+ f()
+ {
+ switch(x) {
+ case A:
+ x1;
+ break;
+ case B:
+ x2;
+ break;
+ default:
+ x3;
+ }
+ }
+
+ I don't believe there is any way to do this exactly without modifying the
+ Lisp code in c-mode.el. You can set c-indent-level to 4 and
+ c-label-offset to -2, but this has bad effects elsewhere. {Anyone have a
+ solution?}
+
+44: How can I make Emacs automatically scroll horizontally?
+
+ There is no completely correct way of doing this that does not involve !
+ rewriting all commands or writing your own top-level command loop (not a !
+ completely bad idea). Wayne Mesard <wmesard@pescadero.stanford.edu> has !
+ written a particularly advanced kludge called `hscroll.el' that checks !
+ once a second to make sure point is visible. !
+
+45: How do I make Emacs "typeover" or "overwrite" instead of inserting?
+
+ M-x overwrite-mode (a minor mode).
+
+46: How do I stop Emacs from beeping on a terminal?
+
+ Martin R. Frank <martin@cc.gatech.edu> writes:
+
+ Tell Emacs to use the 'visible bell' instead of the audible bell, and
+ set the visible bell to nothing.
+
+ Put this in your TERMCAP environment variable:
+
+ ... :vb=: ...
+
+ And evaluate this:
+
+ (setq visible-bell t)
+
+47: How do I turn down the bell volume in Emacs running under X Windows?
+
+ Under versions of Emacs before 18.58, the bell volume was annoying loud
+ and difficult to turn off. So upgrading to 18.58 will reduce the volume.
+ If you want to turn it off completely, use `xset'. There is no way to
+ turn the bell off just for Emacs without affecting all other programs.
+
+ Under Epoch you can do:
+
+ (setq epoch::bell-volume 20)
+
+ Stu Grossman <grossman@sunburn.stanford.edu> wrote a patch that allows the
+ bell volume to be adjusted from inside Emacs just for Emacs.
+
+48: How do I tell Emacs to automatically indent a new line to the
+ indentation of the previous line?
+
+ One solution is Indented Text Mode (M-x indented-text-mode).
+
+ If you have Auto-Fill mode on (a minor mode, see question 32), you can
+ tell Emacs to prefix every line with a certain character sequence, the
+ "fill prefix". Type the prefix at the beginning of a line, position point
+ after it, and then type "C-x ." (set-fill-prefix) to set the fill prefix.
+ Thereafter, auto-filling will automatically put the fill prefix at the
+ beginning of new lines, and M-q (fill-paragraph) will maintain any fill
+ prefix when refilling the paragraph.
+
+ NOTE: If you have paragraphs with different levels of indentation, you
+ will have to set the fill prefix to the correct value each time you move
+ to a new paragraph. To avoid this hassle, try one of the many packages
+ available from the Emacs Lisp Archive. Look up `fill' and `indent' in the
+ Lisp Code Directory for guidance.
+
+49: How do I show which parenthesis matches the one I'm looking at?
+
+ If you're looking at a right parenthesis (or brace or bracket) you can
+ delete it and reinsert it. Emacs will blink the cursor on the matching
+ parenthesis.
+
+ M-C-f (forward-sexp) and M-C-b (backward-sexp) will skip over balanced
+ parentheses, so you can see which parentheses match. (You can train it to
+ skip over balanced brackets and braces at the same time by modifying the
+ syntax table.)
+
+ Here is some Emacs Lisp that will make the % key show the matching
+ parenthesis, like in vi. In addition, if the cursor isn't over a
+ parenthesis, it simply inserts a % like normal.
+
+ ;; By an unknown contributor
+
+ (global-set-key "%" 'match-paren)
+
+ (defun match-paren (arg)
+ "Go to the matching parenthesis if on parenthesis otherwise insert %."
+ (interactive "p")
+ (cond ((looking-at "\\s\(") (forward-list 1) (backward-char 1))
+ ((looking-at "\\s\)") (forward-char 1) (backward-list 1))
+ (t (self-insert-command (or arg 1)))))
+
+50: In C mode, can I show just the lines that will be left after #ifdef
+ commands are handled by the compiler?
+
+ M-x hide-ifdef-mode. (This is a minor mode.)
+
+ You may have to (load "hideif") first. If you want to do this regularly,
+ put this in your .emacs file:
+
+ (autoload 'hide-ifdef-mode "hideif" nil t)
+
+ {Yes, I know, this should be in lisp/loaddefs.el already.}
+
+51: Is there an equivalent to the `.' (dot) command of vi?
+
+ (`.' is the redo command in vi. It redoes the last insertion/deletion.)
+
+ No, not really.
+
+ You can type "C-x ESC" (repeat-complex-command) to reinvoke commands that
+ used the minibuffer to get arguments. In repeat-complex-command you can
+ type M-p and M-n to scan through all the different complex commands you've
+ typed.
+
+ To repeat something on each line I recommend using keyboard macros.
+
+52: What are the valid X resource settings (ie., stuff in .Xdefaults)?
+
+ See the Emacs man page, or the etc/OPTIONS file. Ignore the information
+ in etc/XDOC which is way out of date.
+
+53: How do I execute a piece of Emacs Lisp code?
+
+ There are a number of ways to execute (called "evaluate") an Emacs Lisp
+ "form":
+
+ * If you want it evaluated every time you run Emacs, put it in a file
+ named `.emacs' in your home directory.
+
+ * You can type the form in the *scratch* buffer, and then type LFD (or
+ C-j) after it. The result of evaluating the form will be inserted in
+ the buffer.
+
+ * In Emacs-Lisp mode, typing M-C-x evaluates a top-level form before or
+ around point.
+
+ * Typing "C-x C-e" in any buffer evaluates the Lisp form immediately
+ before point and prints its value in the echo area.
+
+ * Typing M-ESC or M-x eval-expression allows you to type a Lisp form in
+ the minibuffer which will be evaluated.
+
+ * You can use M-x load-file to have Emacs evaluate all the Lisp forms in
+ a file. (To do this from Lisp use the function `load' instead.)
+
+ These functions are also used for evaluating Lisp forms:
+
+ load-library, eval-region, eval-current-buffer, require, autoload
+
+54: How do I change Emacs's idea of the tab character's length?
+
+ Example: (setq default-tab-width 10).
+
+55: How do I insert `>' at the beginning of every line?
+
+ Type "M-x replace-regexp RET ^ RET > RET".
+
+ To do this only in the region, type "C-x n M-x replace-regexp RET ^ RET
+ > RET C-x w".
+
+ WARNING: The command narrow-to-region (C-x n) is disabled by default
+ because it can be very confusing (ie., "Oh no! Where did my file go?").
+
+56: How do I insert `_^H' before each character in a paragraph to get an
+ underlined paragraph?
+
+ M-x underline-region.
+
+57: How do I repeat a command as many times as possible?
+
+ Use "C-x (" and "C-x )" to make a keyboard macro that invokes the command
+ and then type "M-0 C-x e".
+
+ WARNING: any messages your command prints in the echo area will be
+ suppressed.
+
+58: How do I make Emacs behave like this: when I go up or down, the cursor
+ should stay in the same column even if the line is too short?
+
+ M-x picture-mode. (This is a minor mode, in theory anyway ...)
+
+59: How do I tell Emacs to iconify itself?
+
+ You need to modify C source and recompile. Either that or get Epoch or
+ Lucid Emacs instead. Patches have been written by Robert Forsman
+ <thoth@reef.cis.ufl.edu> and Johan Vromans <jv@mh.nl> to allow Emacs to
+ iconify itself and by Matt Wette <mwette@mr-ed.jpl.nasa.gov> and
+ Manavendra K. Thakur <thakur@zerkalo.harvard.edu> (for 18.57, plus icon
+ geometry) to allow Emacs to start up iconified. I don't know which of
+ these patches work together.
+
+ Anonymous FTP:
+ /csi.jpl.nasa.gov:pub/emacs.patch1 (Matt Wette) +
+ /ftp.eu.net:gnu/emacs/FP-Xfun.Z (Johan Vromans) +
+ /ftp.urc.tue.nl:pub/tex/emacs/FP-Xfun (Johan Vromans) +
+
+60: How do I use regexps (regular expressions) in Emacs?
+
+ See `Regexps' in the online manual.
+
+ WARNING: The "or" operator is `\|', not `|', and the grouping operators
+ are `\(' and `\)'. Also, the string syntax for a backslash is "\\".
+ Thus, the string syntax for a regular expression like xxx\(foo\|bar\) is
+ "xxx\\(foo\\|bar\\)". Notice the duplicated backslashes!
+
+ WARNING: Unlike in Unix grep, sed, etc., a complement character set
+ ([^...]) can match a newline character (LFD aka C-j aka \n), unless
+ newline is mentioned as one of the characters not to match.
+
+ WARNING: The character syntax regexps (eg. `\sw') are not meaningful
+ inside character set regexps (eg. `[aeiou]'). (This is actually typical
+ for regexp syntax.)
+
+61: How do I perform a replace operation across more than one file?
+
+ The "tags" feature of Emacs includes the command tags-query-replace which
+ performs a query-replace across all the files mentioned in the TAGS file.
+ See `Tags:Tags Search' in the online manual.
+
+ In addition, Martin Boyer has written a package named global-replace which
+ will perform a query-replace across all the files mentioned in the
+ *compilation* buffer (usually done after a `grep'), which is available via
+ anonymous FTP: !
+ !
+ /ireq-robot.hydro.qc.ca:pub/emacs/lisp/compile.el.Z !
+ /ireq-robot.hydro.qc.ca:pub/emacs/lisp/global-replace.el.Z !
+ /ireq-robot.hydro.qc.ca:pub/emacs/lisp/query.el.Z !
+
+62: Where is the documentation for `etags'?
+
+ `etags' takes options just like a prior version of ctags, so your ctags
+ manual (if any) may be useful. {Can someone send me the details on this?}
-GNU Emacs, all its Variants, and other Editors
+Bugs/Problems
-25: Where does the name "Emacs" come from?
+63: Does Emacs have problems with files larger than 8 megabytes?
+
+ Most installed versions of GNU Emacs will use 24-bit signed integers (and
+ 24-bit pointers) internally. This limits the file size that Emacs can
+ handle to 8,388,607 bytes (2^23 - 1).
+
+ Leonard N. Zubkoff <lnz@lucid.com> suggests putting the following two
+ lines in src/config.h before compiling Emacs to allow for 26-bit integers
+ and pointers (and thus filesizes of up to 33,554,431 bytes):
+
+ #define VALBITS 26
+ #define GCTYPEBITS 5
- EMACS originally was an acronym for Editor MACroS. The first Emacs was
- a set of macros written by Richard Stallman for the editor TECO (Tape
- Editor and COrrector {Text Editor and COrrector?}) on a PDP-10.
- (Amusing fact: many people have told me that TECO code looks a lot like
- line noise.)
+ WARNING: This method may result in `ILLEGAL DATATYPE' and other random
+ errors on some machines.
-26: What is the latest version of GNU Emacs?
+ David Gillespie <daveg@csvax.cs.caltech.edu> gives an explanation of why
+ Emacs uses 24 bit integers and pointers:
- GNU Emacs 18.55. GNU Emacs 18.56 is coming out with some bug fixes, but
- no additional functionality.
+ Emacs is largely written in a dialect of Lisp; Lisp is a freely-typed
+ language in the sense that you can put any value of any type into any
+ variable, or return it from a function, and so on. So each value must
+ carry a "tag" along with it identifying what kind of thing it is, eg.,
+ integer, pointer to a list, pointer to an editing buffer, and so on.
+ Emacs uses standard 32-bit integers for data objects, taking the top 8
+ bits for the tag and the bottom 24 bits for the value. So integers (and
+ pointers) are somewhat restricted compared to true C integers and
+ pointers.
-27: When will GNU Emacs 19 be available?
+ Emacs uses 8-bit tags because that's a little faster on byte-oriented
+ machines, but there are only really enough tags to require 6 bits.
- Good question, I don't know. For that matter, neither do the
- developers. It will undoubtedly be available sometime in the 1990s.
+64: Why can't Emacs find files in current directory on startup?
-28: What will be different about GNU Emacs 19?
+ Most likely, you have an environment variable named PWD that is set to a
+ value other than the name of your current directory. This is most
+ likely caused by using two different shell programs. `ksh' and (some
+ versions of) `csh' set and maintain the value of the PWD environment
+ variable, but `sh' doesn't. If you start sh from ksh, change your
+ current directory inside sh, and then start Emacs from inside sh, PWD
+ will have the wrong value but Emacs will use this value. See the
+ etc/OPTIONS file for more details.
- From the latest "GNU's Bulletin":
+ Perhaps an easier solution is not to use two shells. The `chsh' program
+ can often be used to change one's default login shell.
- Version 19 approaches release with a host of new features: before and
- after change hooks; X selection processing (including CLIPBOARD
- selections); scrollbars; support for European character sets; floating
- point numbers; per-buffer mouse commands; interfacing with the X
- resource manager; mouse-tracking; Lisp-level binding of function keys;
- and multiple X windows (`screens' to Emacs).
+ You may have PWD set for other reasons. Another possibility is that you
+ are setting default-directory from your .emacs file.
- Thanks go to Alan Carroll and the people who worked on Epoch for
- generating initial feedback to a multi-windowed Emacs. Emacs 19
- supports two styles of multiple windows, one with a separate screen for
- the minibuffer, and another with a minibuffer attached to each screen.
+ Here is a fix by Jim Blandy <jimb@occs.cs.oberlin.edu>:
- More features of Version 19 are buffer allocation, which uses a new
- mechanism capable of returning storage to the system when a buffer is
- killed, and a new input system---all input now arrives in the form of
- Lisp objects.
+ >--- emacs/jjj/emacs-18.58/lisp/startup.el Tue Jan 15 23:19:04 1991
+ >+++ startup.el Mon Apr 20 00:21:01 1992
+ >@@ -81,5 +81,7 @@
+ > ;; In presence of symlinks, switch to cleaner form of default directory.
+ > (if (and (not (eq system-type 'vax-vms))
+ >- (getenv "PWD"))
+ >+ (getenv "PWD")
+ >+ (equal (nthcdr 10 (file-attributes default-directory))
+ >+ (nthcdr 10 (file-attributes (getenv "PWD")))))
+ > (setq default-directory (file-name-as-directory (getenv "PWD"))))
+ > (unwind-protect
- Other features being considered for Version 19 include:
+65: How do I get rid of the ^M junk in my Shell buffer?
- * Associating property lists with regions of text in a buffer.
- * Multiple font, color, and pixmaps defined by those properties.
- * Different visibility conditions for the regions, and for the various
- windows showing one buffer.
- * Incremental syntax analysis for various programming languages.
- * Hooks to be run if point or mouse moves outside a certain range.
- * Source-level debugging for Emacs Lisp.
- * Incrementally saving undo history in a file, so that recover-file also
- reinstalls buffer's undo history.
- * Static menu bars, and better pop-up menus.
- * A more sophisticated emacsclient/server model, which would provide
- network transparent Emacs widget functionality.
+ For tcsh, put this in your `.cshrc' (or `.tcshrc') file:
+
+ if ($?EMACS) then
+ if ("$EMACS" == t) then
+ if ($?tcsh) unset edit
+ stty nl
+ endif
+ endif
+
+ Or put this in your .emacs_tcsh file:
+
+ unset edit
+ stty nl
+
+ Alternatively, use csh in your Shell buffers instead of tcsh. One way
+ is:
+
+ (setq explicit-shell-file-name "/bin/csh")
+
+ and another is to do this in your .cshrc (or .tcshrc) file:
+
+ setenv ESHELL /bin/csh
+
+ (You must start Emacs over again with the environment variable properly
+ set for this to take effect.)
+
+66: Why do I get `Process shell exited abnormally with code 1'?
+
+ The most likely reason for this message is that the `env' program is not
+ properly installed. This program should be compiled (for the correct
+ architecture!) and installed with execute permission for everyone in
+ Emacs's program directory, which is normally /usr/local/emacs/etc. You
+ can find what this directory is at your site by inspecting the value of
+ the variable exec-directory by typing "C-h v exec-directory RET". `env'
+ should also be for the correct architecture (check using `file' command).
+
+ You should also check for other programs named `env' in your path (eg.,
+ SunOS has a program named /usr/bin/env). I don't understand why this can
+ cause a failure and I don't know a general solution for working around the
+ problem in this case.
+
+ The `make clean' command will remove `env' and other vital programs, so be
+ careful when using it.
- Also, Emacs 19 will have a Emacs Lisp source code debugger.
+ It has been reported that this sometimes happened when Emacs was started
+ as an X client from an xterm window (ie. had a controlling tty) but the
+ xterm was later terminated.
-29: Is there an Emacs that has better mouse and X window support?
+ See also etc/PROBLEMS for other possible causes of this message.
+
+67: Why can't I cut from Emacs and paste in other X programs?
+
+ Emacs stores things you "cut" in the X "cut buffers". It also pastes from
+ the cut buffer `CUT_BUFFER0'. This is obsolete. Most modern X programs
+ now expect to work with "selections" instead of cut buffers, although some
+ like `xterm' will try to use the cut buffers if the selection is null.
+
+ Emacs 18.58 contains a "fix" that makes xterm work by default. This
+ "fix" is that Emacs clears the `PRIMARY' selection when it stores
+ something in the cut buffer. By making the selection null, xterm will
+ then fetch from the cut buffer when you try to paste.
+
+ For versions of Emacs prior to 18.58, you can make pasting from Emacs into
+ xterm work with the following X resources:
+
+ ! Solution by Thomas Narten, should work under X11R3 and later GNU
+ ! Emacs only copies to CUT_BUFFER0. xterm by default wants to paste
+ ! from the PRIMARY selection.
+ XTerm*VT100.Translations: #override \
+ ~Meta <Btn2Up>: insert-selection(CUT_BUFFER0,PRIMARY)
+
+ You may have problems copying between Emacs and programs other than xterm
+ that won't store cut text in the cut buffers or look in the cut buffers
+ for text to paste (for backwards compatibility with obsolete applications
+ like Emacs :-). The best workaround is to use the `xcutsel' program as an
+ intermediary. -
+
+ This problem does not exist for Epoch or Lucid Emacs.
+
+68: Where is the termcap/terminfo entry for terminal type `emacs'?
+
+ The termcap entry for terminal type `emacs' is ordinarily put in the
+ TERMCAP environment variable of subshells. It may help in certain
+ situations (eg., using rlogin from shell buffer) to add an entry for
+ `emacs' to the system-wide termcap file. Here is a correct termcap entry
+ for `emacs':
+
+ emacs:tc=unknown:
+
+ To make a terminfo entry for `emacs', use `tic' or `captoinfo'. You need
+ to generate /usr/lib/terminfo/e/emacs. It may work to simply copy
+ /usr/lib/terminfo/d/dumb to /usr/lib/terminfo/e/emacs.
+
+ Having a termcap/terminfo entry will not enable the use of full screen
+ programs in shell buffers. Use M-x terminal-emulator for that instead.
+
+ A workaround to the problem of missing termcap/terminfo entries is to
+ change terminal type `emacs' to type `dumb' or `unknown' in your shell
+ start up file. `csh' users could put this in their .cshrc files:
+
+ if ("$term" == emacs) set term=dumb
+
+69: Why does Emacs spontaneously start displaying `I-search:' and beeping?
+
+ Your terminal (or something between your terminal and the computer) is
+ sending C-s and C-q for flow control, and Emacs is receiving these
+ characters and interpreting them as commands. (The C-s character normally
+ invokes the isearch-forward command.) For possible solutions, see
+ question 131.
+
+70: Why can't Emacs talk to certain hosts (or certain hostnames)?
+
+ The problem may be that Emacs is linked with a wimpier version of
+ gethostbyname than the rest of the programs on the machine. This is often
+ manifested as a message on startup of `X server not responding. Check
+ your DISPLAY environment variable.' or a message of `Unknown host' from
+ open-network-stream.
+
+ On a Sun, this may be because Emacs had to be linked with the static C
+ library. The version of gethostbyname in the static C library may only
+ look in /etc/hosts and the NIS (YP) maps, while the version in the dynamic
+ C library may be smart enough to check DNS in addition to or instead of
+ NIS. On a Motorola Delta running System V R3.6, the version of
+ gethosbyname in the standard library works, but the one that works with
+ NIS doesn't (the one you get with -linet). Other operating systems have
+ similar problems.
+
+ Try these options:
+
+ * Explicitly add the host you want to communicate with to /etc/hosts.
+
+ * Relink Emacs with this line in src/config.h:
+
+ #define LIBS_SYSTEM -lresolv
+
+ * Replace gethostbyname and friends in libc.a with more useful versions
+ such as the ones in libresolv.a. Then relink Emacs.
+
+ * If you are actually running NIS, make sure that `ypbind' is properly
+ told to do DNS lookups with the correct command line switch.
+
+ * Use tcp.el and tcp.c from GNUS. This has the additional advantage that
+ you can use numeric IP addresses instead of names. open-network-stream
+ currently can't handle numeric addresses. Brian Thomson
+ <thomson@hub.toronto.edu> has a enhancement to open-network-stream to
+ allow it to handle numeric addresses.
+
+71: Why does Emacs say `Error in init file'?
+
+ An error occurred while loading either your .emacs file or the system-wide
+ lisp/default.el file. For information on how to debug your .emacs file,
+ see question 29.
+
+ It may be the case that you may need to load some package first, or use a
+ hook that will be evaluated after the package is loaded. A common case of
+ this is explained in question 127.
+
+72: Why does Emacs ignore my X resources (my .Xdefaults file)?
+
+ * Try compiling Emacs with the XBACKWARDS macro defined. There is a bug
+ in some implementations of XGetDefault, which do not correspond to the
+ documentation or the header files.
+
+ * Make sure you are either using the class name of `Emacs' (oops,
+ apparently this is buggy in Emacs 18.58!) or the correct instance name.
+ The instance name is normally the same as the name of the file Emacs is
+ in (ie., the last part of argv[0]), but this can be overridden by -rn
+ command line option or the WM_RES_NAME environment variable.
+
+ WARNING: Reports say using the class name fails in Emacs 18.58.
+
+ WARNING: The advice the man page gives to use `emacs' is often wrong.
+
+ WARNING: Older versions of Emacs got the class name wrong.
+
+ * Emacs currently ignores the -xrm command line argument.
+
+ * Emacs does not yet handle X11R5 screen-specific resources.
+
+ * Emacs has a bug where it ignores color specifications if running on a
+ 1-bit display (ie. a non-color display).
+
+ * I don't think Emacs will use either of the application-specific resource
+ files. Thus these environment variables don't affect it: XAPPLRESDIR,
+ XUSERFILESEARCHPATH, XFILESEARCHPATH. {Correct?}
+
+73: Why does Emacs take 20 seconds to visit a file?
+
+ The usual cause is that the master lock file, `!!!SuperLock!!!' has been
+ left in the lock directory somehow. Delete it.
+
+ Mark Meuer <meuer@geom.umn.edu> says that NeXT NFS has a bug where an
+ exclusive create succeeds but returns an error status. This can cause the
+ same problem. Since Emacs's file locking doesn't work over NFS anyway,
+ the best solution is to recompile Emacs with CLASH_DETECTION undefined.
+
+74: How do I edit a file with a `$' in its name?
+
+ When entering a filename in the minibuffer, Emacs will attempt to expand
+ a `$' followed by a word as an environment variable. To suppress this
+ behavior, type "$$" instead.
+
+75: Why does Shell mode lose track of the shell's current directory?
+
+ Emacs has no way of knowing when the shell actually changes its directory.
+ This is an intrinsic limitation of Unix. So it tries to guess by
+ recognizing `cd' commands. If you type `cd' followed by a directory name
+ with a variable reference (`cd $HOME/bin') or with a shell metacharacter
+ (`cd ../lib*'), Emacs will fail to correctly guess the shell's new current
+ directory. A huge variety of fixes and enhancements to Shell mode for
+ this problem have been written to handle this problem. Check the Lisp
+ Code Directory (see question 88).
+
+76: Why doesn't my change to load-path work?
+
+ If you added a directory name containing a tilde (~) to your load-path,
+ expecting the tilde to be interpreted as your home directory, then you
+ need to do something like this:
+
+ (setq load-path (mapcar 'expand-file-name load-path))
+
+77: Why does the cursor always go to the wrong column when I move up or
+ down one line?
+
+ You have inadvertently typed "C-x C-n" (set-goal-column) which sets the
+ "goal column" to the column where the cursor was. To undo this type
+ "C-u C-x C-n".
+
+ If you make this mistake frequently, you might want to unbind or disable
+ this command by doing one of these two:
+
+ (define-key ctl-x-map "\C-n" nil)
+ (put 'set-goal-column 'disabled t)
+
+78: Why does Emacs hang with message `Unknown XMenu error' with X11R4?
+
+ Many different X errors can produce this message. Here is the solution
+ to one problem:
+
+ X11 Release 4 (and later, including OpenWindows) enforces some conditions
+ in the X protocol that were previously allowed to pass unnoticed. You
+ need to put the X11R4 server into X11R3 bug compatibility mode for Emacs's
+ Xmenu code to work. You can do this with the command `xset bc'.
+
+79: Why doesn't display-time show the load average in the mode line
+ anymore?
+
+ In GNU Emacs 18.56, a change was made in the display-time code.
+ Formerly, in version 18.55, Emacs used a program named `loadst' to
+ notify Emacs of the change in time every minute. loadst also sent Emacs
+ the system load average if it was installed with sufficient privilege to
+ get that information (or was on a system where no such privilege was
+ needed). Emacs then displayed this information in the mode line.
+
+ In version 18.56, this code was changed to use a program named `wakeup'.
+ wakeup doesn't send Emacs any information, it's only purpose is to send
+ Emacs *something* every minute, thus invoking the filter function in
+ Emacs once a minute. The filter function in Emacs does all the work of
+ finding the time, date, and load average. However, getting the load
+ average requires the privilege to read kernel memory on most systems.
+ Since giving Emacs this privilege would destroy any security a system
+ might have, for almost everyone this is not an option. In addition,
+ Emacs does not have the code built into it to get this information on
+ the systems which have special system calls for this purpose, even
+ though loadst had code for this.
+
+ The solution I use is to get the files lisp/display-time.el and
+ etc/loadst.c from version 18.55 and use those with 18.58. (I have heard
+ a rumor that loadst disappeared because of the legal action Unipress
+ threatened against IBM.)
+
+ WARNING: Do not install Emacs setgid kmem unless you wish to destroy
+ any security your system might have!!!!!!!!!!
+
+ If you are using Emacs 18.55 or earlier, or already using the solution I
+ describe above, read further:
+
+ The most likely cause of the problem is that `loadst' can't read the
+ special file /dev/kmem. To properly install loadst, it should be either
+ setuid to the owner of /dev/kmem, or is should be setgid to the group to
+ which /dev/kmem belongs. In either case, /dev/kmem should be readable by
+ its owner or its group, respectively. Assuming the existence of a group
+ named `kmem', here is an example of how to do this:
+
+ chgrp kmem /dev/kmem
+ chmod g+r /dev/kmem
+ chgrp kmem /usr/local/emacs/etc/loadst
+ chmod g+s /usr/local/emacs/etc/loadst
+
+ Another possibility is that your version of Unix doesn't have the load
+ average data available in /dev/kmem. Your version of Unix might have a
+ special system call to retrieve this information (eg., inq_stats under
+ UMAX), and loadst might not have been enhanced to cope with this.
+
+80: Why does ispell sometimes ignore the local dictionary?
+
+ You need to update the version of Ispell to 2.0.02. (Or you can switch to
+ version 3.0 which is still in beta-testing.) A patch is available via
+ anonymous FTP: !
+ !
+ /archive.cis.ohio-state.edu:pub/gnu/ispell/patch2.Z !
+
+ You also need to change a line in ispell.el from:
+
+ (defconst ispell-version "2.0.01") ; Check against output of "ispell -v".
+
+ to:
+
+ (defconst ispell-version "2.0.02") ; Check against output of "ispell -v".
+
+81: Why does Ispell treat each line as a single word?
+
+ Ispell expects to get its input one word per line. The ispell filter,
+ which is specified by the variables ispell-filter-hook and
+ ispell-filter-hook-args, should output at most one word per line.
+
+82: Are there any security risks in GNU Emacs?
+
+ * the `movemail' incident (No, this is not a risk.)
+
+ Cliff Stoll in his book `The Cuckoo's Egg' describes this in chapter 4.
+ The site at LBL had installed the `etc/movemail' program setuid root.
+ Since `movemail' had not been designed for this situation, a security
+ hole was created and users could get root priveleges.
+
+ `movemail' has since been changed so that even if it is installed setuid
+ root this security hole will not be a result.
+
+ I have heard unverified reports that the Internet worm took advantage of
+ this configuration problem.
+
+ * the file-local-variable feature (Yes, a risk, but easy to change.)
+
+ There is an Emacs feature that allows the setting of local values for
+ variables when editing a file by including specially formatted text near
+ the end of the file. This feature also includes the ability to have
+ arbitrary Emacs Lisp code evaluated when the file is visited.
+ Obviously, there is a potential for Trojan horses to exploit this
+ feature.
+
+ If you set the variable inhibit-local-variables to a non-nil value,
+ Emacs will display the special local variable settings of a file that
+ you visit and ask you if you really want them. This variable is not
+ mentioned in the manual.
+
+ It is wise to do this in lisp/site-init.el before building Emacs:
+
+ (setq inhibit-local-variables t)
+
+ If Emacs has already been built, the expression can be put in
+ lisp/default.el instead, or an individual can put it in their own .emacs
+ file.
+
+ The ability to exploit this feature by sending e-mail to an RMAIL user
+ was fixed sometime after Emacs 18.52. However, any new package that
+ uses find-file or find-file-noselect has to be careful about this.
+
+ For more information, see `File Variables' in the online manual (which,
+ incidentally, does not describe how to disable the feature).
+
+ There is a new variable in Emacs 18.58 named ignore-local-eval which
+ turns out to be useless as currently implemented. Ignore it.
+
+ * synthetic X events (Yes, a risk, use MIT-MAGIC-COOKIE-1 or better.)
+
+ Emacs accepts synthetic X events generated by the SendEvent request as
+ though they were regular events. As a result, if you are using the
+ trivial host-based authentication, other users who can open X
+ connections to your X workstatation can make your Emacs process do
+ anything, including run other processes with your priveleges.
+
+ The only fix for this is to prevent other users from being able to open
+ X connections. The standard way to prevent this is to use a real
+ authentication mechanism, such as MIT-MAGIC-COOKIE-1. If using the
+ `xauth' program has any effect, then you are probably using
+ MIT-MAGIC-COOKIE-1. Your site may be using a superior authentication
+ method; ask your system administrator.
+
+ If real authentication is not a possibility, you may be satisfied by
+ just allowing hosts access for brief intervals while you start your X
+ programs, then removing the access. This reduces the risk somewhat by
+ narrowing the time window when hostile users would have access, but DOES
+ NOT ELIMINATE THE RISK.
+
+ Lucid GNU Emacs does not accept synthetic X events unless you set a +
+ variable. +
+
+ * autosave file permissions (Yes, a risk, hard to work around.)
+
+ The file permissions for autosave files are determined solely by the
+ Emacs process's `umask' value. The permissions of the file being
+ autosaved are not used. The easiest workaround is to keep sensitive
+ files in protected directories. Sebastian Kremer has written an
+ enhanced version of the autosave file name picking code that can avoid
+ this problem by keeping autosave files in a protected directory. {FTP
+ information please?} This problem will be fixed in Emacs 19.
+
+
+
+Difficulties Building/Installing/Porting Emacs
+
+83: What should I do if I have trouble building Emacs?
+
+ First look in the file etc/PROBLEMS to see if there is already a solution
+ for your problem. Next check the FAQ (you're reading it). If you don't
+ find a solution, then report your problem via e-mail to
+ bug-gnu-emacs@prep.ai.mit.edu. Please do not post it to gnu.emacs.help or
+ e-mail it to help-gnu-emacs@prep.ai.mit.edu. For further guidelines, see
+ question 8.
+
+84: How do I stop Emacs from failing when the executable is stripped?
+
+ Don't do that.
+
+ This problem has been reported on SGI Indigo machines running Irix 4.0.*
+ and RS/6000 machines. Scott Henry <scotth@hoshi.corp.SGi.COM> posted a
+ patch that fixes the problem for Irix.
+
+85: Why does linking Emacs with -lX11 fail? !
+ !
+ Emacs needs to be linked with the static version of the X11 library, !
+ libX11.a. This may be missing. !
+ !
+ Under OpenWindows, you may need to use `add_services' to add the !
+ `OpenWindows Programmers' optional software category from the CD-ROM. -
+
+ Under HP-UX 8.0, you may need to run `update' again to load the -
+ X11-PRG `fileset'. This may be missing even if you specified `all
+ filesets' the first time. If libcurses.a is missing, you may need to load
+ the `Berkeley Development Option' {???}.
+
+ If you are building the MIT X11 sources, you may need to modify your +
+ `site.cf' file to get static versions of the libraries. (Info from David +
+ Zuhn <zoo@cygnus.com>.) +
+ +
+ Other systems may have similar problems. You can always define +
+ CANNOT_DUMP and link with the shared libraries instead.
+
+ To get the Xmenu stuff to work, you need to find a copy of MIT's +
+ liboldX.a. +
+
+86: Why does Emacs 18.55 say `Fatal error (6).Abort' under SunOS 4.1?
+
+ I had hoped this question would go away after Emacs 18.57 was released,
+ but people continue to compile 18.55. Easiest solution: upgrade.
+
+ This is a result of the SunOS localtime/tzsetwall malloc bug, which was
+ (finally!) fixed in SunOS 4.1.2. If you actually need the full
+ explanation, send me e-mail. If you absolutely must compile Emacs 18.55
+ (eg., you are compiling Nemacs), the easiest workaround was to put
+ `#define SYSTEM_MALLOC' in src/config.h. -
+
+ GNU Emacs FAQ: Getting Emacs/Packages
+
+If you are viewing this text in a GNU Emacs Buffer, you can type "M-2 C-x $" to
+get an overview of just the questions. Then, when you want to look at the text
+of the answers, just type "C-x $".
+
+To search for a question numbered XXX, type "M-C-s ^XXX:", followed by a C-r if
+that doesn't work, then type ESC to end the search.
+
+A `+' in the 78th column means something was inserted on the line. A `-' means
+something was deleted and a `!' means some combination of insertions and
+deletions occurred.
+
+Full instructions for getting the latest FAQ are in question 22. Also see the
+`Introduction to news.answers' posting in the `news.answers' newsgroup, or send
+e-mail to `mail-server@rtfm.mit.edu' with `help' on a body line, or use FTP,
+WAIS, or Prospero to rtfm.mit.edu.
+
+
+
+Finding/Getting Emacs and Related Packages
+
+87: Where can I get GNU Emacs on the net (or by snail mail)?
+
+ Look in the files etc/DISTRIB and etc/FTP for information on nearby
+ archive sites. If you don't already have GNU Emacs, see question 20
+ for how to get these two files.
+
+ The latest version is always available via anonymous FTP at MIT: !
+ !
+ /prep.ai.mit.edu:pub/gnu/emacs-18.58.tar.Z !
+
+ See question 91.
+
+88: How do I find a GNU Emacs Lisp package that does XXX?
+
+ A listing of Emacs Lisp packages, called the Lisp Code Directory, is being
+ maintained by Dave Brennan <brennan@hal.com> and Dave Sill <de5@ornl.gov>.
+ You can search through this list to find if someone has written something
+ that fits your needs.
+
+ This list is file LCD-datafile.Z in the Emacs Lisp Archive. (See
+ question 89 for methods for getting this file.) The files lispdir.el.Z
+ and lispdir.doc.Z in the archive contain information to help you use the
+ list. Once you have installed lispdir.el and LCD-datafile, then you can
+ use the "M-x lisp-dir-apropos" command to look things up in the database.
+ For example, the command "M-x lisp-dir-apropos RET ange-ftp RET" produces
+ this (outdated) output:
+
+ GNU Emacs Lisp Code Apropos -- "ange-ftp"
+
+ ange-ftp (3.112) 91-08-12
+ Andy Norman, <ange@hplb.hpl.hp.com>
+ archive.cis.ohio-state.edu:
+ /pub/gnu/emacs/elisp-archive/as-is/ange-ftp.el.Z
+ transparent FTP Support for GNU Emacs
+
+89: Where can I get GNU Emacs Lisp packages that don't come with Emacs?
+
+ First, check the Lisp Code Directory to find the name of the package you
+ are looking for. (See question 88). Then check local archives and
+ the Emacs Lisp Archive to find a copy of the relevant files. Then, if
+ you still haven't found it, you can send e-mail to the author asking for
+ a copy.
+
+ You can access the Emacs Lisp Archive via anonymous FTP: !
+ !
+ /archive.cis.ohio-state.edu:/pub/gnu/emacs/elisp-archive/ !
+
+ Fetch the file README first.
+
+ NOTE: The archive maintainers do not have time to answer individual
+ requests for packages or the list of packages in the archive. If you
+ cannot use FTP or UUCP to access the archive yourself, try to find a
+ friend who can, but please don't ask the maintainers.
+
+ NOTE: Any files with names ending in `.Z' are compressed, and you should
+ use `binary' mode in FTP to retrieve them. You should also use binary
+ mode whenever you retrieve any files with names ending in `.elc'.
+
+90: How do I submit code to the Emacs Lisp Archive?
+
+ Submissions should be mailed to elisp-archive@cis.ohio-state.edu. The
+ lispdir.el package has a function named submit-lcd-entry which will help
+ you with this. Mail messages (submissions) are automatically saved and
+ periodically archived. Urgent mail may be sent directly to Dave Sill
+ <de5@ornl.gov> or Dave Brennan <brennan@hal.com> or should contain the
+ string `urgent' in the subject. The incoming ftp directory is no longer
+ available at the request of Ohio State. {Is this still true?}
+
+ However, if someone has a submission with multiple files (which would be
+ archived as a tar file) or binary files, then FTP transfer is preferred
+ and can be arranged via an anonymous FTP site. This is faster than
+ uudecoding, unsharing, etc., and re-packaging files.
+
+ Before submitting anything, please read the file guidelines.Z, which is
+ available in the archive. Whenever possible, submissions should contain a
+ complete LCD entry since this helps reduce administrative overhead for the
+ maintainers. You can include an entry in this format:
+
+ ;; LCD Archive Entry:
+ ;; package name|author's name|email address
+ ;; |description
+ ;; |date|version|archive path
+
+ For example:
+
+ ;; LCD Archive Entry:
+ ;; tex-complete|Sebastian Kremer|sk@thp.Uni-Koeln.DE
+ ;; |Minibuffer name completion for editing [La]TeX.
+ ;; |91-03-26|$Revision: 1.12 $|~/packages/tex-complete.el.Z
+
+ Dave Brennan has software which automatically looks for data in this
+ format. The format is fairly flexible. The entry ends when a line is
+ reached with a different prefix or the seventh field terminator is
+ seen.
+
+ If you are submitting a multi-file submission you should include a file
+ named "LCD-entry" which contains the archive entry, instead of placing
+ it in one or more of the individual files.
+
+91: Where can I get other up-to-date GNU stuff?
+
+ The most up-to-date official GNU stuff is normally kept on prep.ai.mit.edu
+ and is available for anonymous FTP in the pub/gnu directory. See the
+ files etc/DISTRIB and etc/FTP for more information. (To get copies of
+ these files, see question 20.)
+
+ The following sites are all mirror images of the GNU distribution area:
+
+ /prep.ai.mit.edu:pub/gnu/ +
+ /ftp.uu.net:packages/gnu/ +
+ /src.doc.ic.ac.uk:gnu/ (available via FTP, NIFTP, FTAM) +
+ /ftp.win.tue.nl:pub/gnu/ !
+ /utsun.s.u-tokyo.ac.jp:ftpsync/prep/ +
+ /nic.funet.fi:pub/gnu/ +
+
+ The directory at ftp.uu.net is a mirror of prep.ai.mit.edu:pub/gnu,
+ except that files larger than 1 megabyte {right?} are automatically
+ split into multiple parts. If you have trouble transferring large
+ files, you should try here. A file normally named `XXX' is split into
+ files XXX-split/part[0-9][0-9], and there will be a file named
+ XXX-split/README which contains the list of parts (especially helpful
+ when FTP-ing by e-mail), their checksums, and reassembly instructions.
+ Some of the other mirror sites may have the same property. {Can someone
+ check this out? Thanks!}
+
+ Information was provided by Lee McLoughlin <lmjm@doc.ic.ac.uk>, Jonathan
+ R. Ferro <jf41+@ANDREW.CMU.EDU>, Arjan de Vet <devet@win.tue.nl>, and -
+ Simon Marshall <S.Marshall@sequent.cc.hull.ac.uk>.
+
+92: Where can I get an Emacs with better mouse and X window support?
Emacs 18 has some limited X Window System support, but there are
problems. Emacs 19 will have amazing mouse and window support. Right
- now, there is a modified version of Emacs 18.55 called "Epoch" which has
- greatly improved mouse and window support. The latest version of Epoch
- is available via:
+ now, there are Epoch which is derived from GNU Emacs 18.58 and Lucid GNU
+ Emacs which is derived from an early unreleased version of GNU Emacs 19,
+ both of which have greatly improved mouse and window support. See
+ questions 120 and 121.
+
+ The HP unofficial GNU Emacs also has nice mouse support. See question
+ 95.
+
+ There are numerous Emacs Lisp packages that have been written to extend
+ Emacs 18's mouse handling capabilities. Some of these packages also have
+ patches to the C code to provide enhanced capabilities. Look up `mouse'
+ in the Lisp Code Directory (see question 88).
+
+ There is a package called BAM (Born Again Menus) which provides menus for +
+ GNU Emacs via an external C program. It does not provide mouse support in +
+ the Emacs window such as scrollbars, cut-and-paste, etc. +
+
+ NOTE: Epoch only works with the X Window System; it works on ordinary
+ terminals by invoking regular GNU Emacs. Lucid Emacs does not currently
+ work on ordinary terminals, although there are plans to fix this.
+
+93: What is the difference between GNU Emacs and Epoch?
+
+ Marc Andreessen <marca@ncsa.uiuc.edu> writes:
+
+ Epoch is GNU Emacs on steroids: an adaptation of GNU Emacs with lots of
+ additional support for features made possible by the X11 windowing
+ system. These features include multiple editing windows, arbitrary
+ colors and fonts (fixed-width and proportional), selectable zones per
+ buffer with arbitrary display styles (font, color, underline, stipple,
+ pixmap), an optional separate minibuffer window, improved keyboard and
+ mouse handling, full 8-bit character set support, and more.
+
+94: What is the difference between GNU Emacs and Lucid GNU Emacs?
+
+ This information is condensed from the release notice:
+
+ Lucid GNU Emacs is based on an early version of GNU Emacs version 19
+ with many enhancements. It currently requires X Windows to run. For
+ information on where to get Lucid GNU Emacs see 121. X Windows support
+ is greatly enhanced over GNU Emacs version 18, including support for
+ multiple X Windows (a.k.a. screens in Emacs), Zmacs/Lispm style region
+ highlighting, a customizable, Motif-like menubar, more powerful keymap
+ support (allowing different actions to be associated with Backspace,
+ Control-h, etc.), flexible text attribute (e.g. font, color) support on
+ regional and screen-local basis through X resources and/or lisp, and
+ support for the X11 selection mechanism. Some other features include
+ run-time computation of the load-path, support for floating point
+ numbers, native timer support, and sound file support on Sun
+ SPARCstations. To build Lucid GNU Emacs, an ANSI C compiler (e.g. gcc)
+ is required.
+
+95: Where can I get the "unofficial HP GNU Emacs"?
+
+ The unofficial HP GNU Emacs is available via anonymous FTP: !
+ !
+ /me10.lbl.gov:pub/interex/HUGE/ !
+ /ee.utah.edu:HUGE/ (PLEASE FTP DURING NON-WORK HOURS!!!) !
+
+ and takes about 35 megabytes of disk space to build. It is useful for
+ non-HP machines, but some of the added features will only work under
+ HP-UX.
+
+ You will need to get patches to work with HP-UX 8.0 or on 700 series
+ machines via e-mail from Darryl Okahata <darrylo@sr.hp.com>.
+
+96: Where can I get Emacs for my PC running MS-DOS?
+
+ * Demacs
+
+ For 386 or 486 PCs running MS-DOS, there is a version of GNU Emacs
+ called Demacs. To get Demacs see question 122.
+
+ From the announcement message:
+
+ Demacs is almost a full set of GNU Emacs but does not support some
+ features: asynchronous process, locking a file, etc.
+
+ Demacs provides following DOS specific features:
+
+ * File type: text or binary file translation.
+ * "8-bit clean" display mode.
+ * 8086 software interrupt call by int86 lisp function.
+ * Machine specific features such as function key support.
+ * File name completion with drive name.
+ * Child process (suspend-emacs, call-process).
+ * Enhanced dired mode which can work without 'ls.exe'.
+
+ To our regret `shell-mode' does not work, but `compile' command works
+ properly.
+
+ Demacs was developed using an MS-DOS version of gcc called djgpp by
+ D. J. Delorie <dj@ctron.com> which can compile and run large programs
+ under MS-DOS, but not under MS Windows. Demacs was derived from Nemacs
+ rather than straight from GNU Emacs.
+
+ There are a variety of other Emacses for MS-DOS including among them the
+ following.
+
+ * Freemacs
+
+ Russ Nelson <nelson@sun.soe.clarkson.edu>, the author, describes
+ Freemacs:
+
+ * Freemacs is free, and it was designed from the start to be
+ programmable.
+ * Freemacs is the only IBM-PC editor that tries to be like GNU Emacs.
+ * Freemacs can only edit files less than 64K in length.
+ * Freemacs doesn't have undo.
+
+ Carl Witty <cwitty@cs.stanford.edu> reviews Freemacs:
+
+ Better is Freemacs, which follows the tradition of ITS and GNU Emacs
+ by having an full, turing-complete extension language which is
+ incompatible with everything else. In fact, it's even closer to ITS
+ Emacs than GNU Emacs is, because Mint (Freemacs' extension language)
+ is absolutely illegible without weeks of study, much like TECO.
+
+ To get Freemacs see question 123.
+
+ * MicroEmacs
+
+ MicroEmacs is a descendant of Microemacs {originally by Dave Conroy?}.
+ It is programmable in a BASIC-like language. Many of the keybindings
+ are different from GNU Emacs. It is rumored that MicroEmacs can not
+ correctly edit files larger than memory. The author is Daniel Lawrence
+ <dan@mdbs.uucp, dan@midas.mgmt.purdue.edu, nwd@j.cc.purdue.edu>. The
+ latest version is 3.10 and it is available via anonymous FTP: !
+ !
+ /midas.mgmt.purdue.edu: (non-working hours only) !
+ /durer.cme.nist.gov: !
+ /wuarchive.wustl.edu:/mirrors/msdos/memacs/ !
+
+ Version 3.11 is in beta test.
+
+ * JOVE
+
+ Another Emacs for small machines is JOVE (Jonathan's Own Version of
+ Emacs). The latest official version is 4.14. There appears to be a
+ newer version. People rumored to be working on JOVE include Mark Moraes
+ <moraes@cs.toronto.edu> and Bill Marsh <bmarsh@cod.nosc.mil>. It is
+ available via anonymous FTP: !
+ !
+ /cs.rochester.edu:/pub/jove.tar.4.14.Z !
+ /cs.toronto.edu:/pub/moraes/jove4.14.3.tar.Z !
+ /ftp.uu.net: !
+
+ * MG
+
+ MG is another descendant of Microemacs. MG used to stand for
+ MicroGNUEmacs, but now just stands for MG. The look-and-feel of MG is
+ intended to be close to that of GNU Emacs. It is rumored that MG can
+ not correctly edit files larger than memory. The current version is
+ rumored to be 2. There is a version 3 in beta which works on the Amiga.
+ It is also available via anonymous FTP: !
+ !
+ /ftp.white.toronto.edu:pub/mg/ !
+ /wuarchive.wustl.edu:/mirrors/unix-c/editors/ !
+ /procyon.cis.ksu.edu: (source and executable) !
+
+97: Where can I get Emacs for my PC running Windows?
+
+ I believe that no version of GNU Emacs runs under Windows. Pierre Perret
+ <pap@myths.az05.bull.com> has ported MicroEMACS 3.11c to Windows.
+
+ Anonymous FTP:
+ /ftp.cica.indiana.edu:pub/pc/win3/util/mewin10.zip !
+ /ftp.cica.indiana.edu:pub/pc/win3/util/mewin10s.zip !
+ /ftp.cica.indiana.edu:pub/pc/win3/util/mewri.zip !
+
+98: Where can I get Emacs for my PC running OS/2?
+
+ From the OS/2 Programmer's FAQ: !
+ !
+ GNU Emacs 18.58 is available. It requires you to have EMX installed !
+ on your machine, but it comes with all the EMX files you will need. !
+ Emacs is available on ftp-os2 in /pub/os2/2.0/gnu/emacs. (If you want !
+ to recompile emacs, you will need the full EMX distribution see !
+ question 1.2.) !
+ !
+ The above quote may be out of date. See the latest OS/2 Programmer's FAQ !
+ {perhaps in comp.os.os2.misc?} for the latest news. Anonymous FTP info: !
+ !
+ /ftp-os2.nmsu.edu:pub/os2/2.0/gnu/emacs/ !
+ ("ftp-os2" was formerly named "hobbes") !
+ !
+ Thanks go to Stephen Simpson <simpson@symcom.math.uiuc.edu>, Jonathan !
+ Miller <jem+@andrew.cmu.edu>, Terry Kane <terryk@cc.gatech.edu>, J. D. !
+ Baldwin <baldwin@csservera.usna.navy.mil>, and Ken Bass !
+ <kbass@gmuvax2.gmu.edu>. !
+
+99: Where can I get Emacs for my Atari ST?
+
+ Emacs 18.57 is the latest version for TOS. Stefan Mueller-Pfeiffer
+ <iff327@zam001.zam.kfa-juelich.de> says:
+
+ There is also a version for MiNT, the multitasking enhancement for
+ ATARI's TOS, which behaves almost like EMACS on a "real computer". This
+ port was done by Erling Henanger <erlingh@idt.unit.no>.
+
+ Anonymous FTP:
+ /atari.archive.umich.edu:atari/gnustuff/tos/ (TOS Emacs 18.57) +
+ /atari.archive.umich.edu:atari/new/mntemacs.zoo (MiNT Emacs) +
+ /cs.uni-sb.de:/pub/atari/emacs/ +
+
+100: Where can I get Emacs for my Amiga?
+
+ All of the files are lharc-ed.
Anonymous FTP:
- site: cs.uiuc.edu
- directory: pub/epoch-files/epoch
- file: epoch-3.2b (b stands for beta)
+ /oes.orst.edu:/pub/almanac/comp/amiga/software/gnuemacs-1.10/ !
+
+ Via e-mail:
+ To: almanac@oes.orst.edu -
+ body:
+ mode uuencode
+ send computer amiga software gnuemacs <file>
+ <file> is replaced by one of the following:
+ Required: d1.lzh d2.lzh
+ Recommended: d3_info.lzh d3_infolisp.lzh
+ Optional: d3_autoloaded.lzh d3_entertainmentetc.lzh
+ d3_entertainmentlisp.lzh d4_src.lzh d5_languagelisp.lzh
+ d5_viclone.lzh d6_gnulibsrc.lzh d6_mailpackage.lzh
+ d6_mathpackage.lzh d6_misc.lzh d6_textformat.lzh
+ The `d#' at the beginning of each file is its disk number, which is
+ referred to by the documentation.
+
+101: Where can I get Emacs for my Apple computer?
+
+ The FSF is a participant in a boycott of Apple because of Apple's "look
+ and feel" copyright suits. See the file etc/APPLE for more details.
+ Because of this boycott, the FSF doesn't include support in GNU software
+ for Apple computers such as the Macintosh.
+
+ Please don't help people port or develop software for Apple computers.
- NOTE: Epoch only works with the X Window System; it does not work on
- ordinary terminals.
+102: Where can I get Emacs with NeWS support?
-30: How do I get Emacs for my PC?
+ Chris Maio's NeWS support package for GNU Emacs is available via anonymous
+ FTP: !
+ !
+ /columbia.edu:pub/ps-emacs.tar.Z !
+ /archive.cis.ohio-state.edu:pub/gnu/emacs/ps-emacs.tar.Z !
+
+ and via e-mail: !
+
+ To: archive-server@columbia.edu
+ body: send NeWS emacs-support !
+
+103: Where do I get Emacs that runs on VMS under DECwindows?
+
+ Hal R. Brand <BRAND@addvax.llnl.gov> is said to have a VMS save set with a
+ ready-to-run VMS version of Emacs 18.55 for X Windows. It is available
+ via anonymous FTP (addvax.llnl.gov). It is possible that the VMS versions
+ of Emacs at other sites have X support compiled in. See etc/FTP for
+ locations.
+
+ Johan Vromans <jv@mh.nl> writes:
- GNU Emacs won't run on a PC directly under MS-DOS. There have been
- reports of people running GNU Emacs under a special program under MS-DOS
- on 286 or 386 machines, but I don't know the details.
+ Getting Emacs to run on VMS with DECwindows requires a number of changes
+ to the sources. Fortunately this has been done already. Joshua Marantz
+ <josh@viewlogic.com> did most of the work for Emacs 18.52, and the mods
+ were ported to 18.55 by Johan Vromans <jv@mh.nl>. Also included is the
+ handling of DEC's LK201 keyboard. You need to apply the changes to a
+ fresh Emacs 18.55 distribution on a Unix system, and then you can copy
+ the sources to VMS to perform the compile/link/build.
- You can try a variety of similar programs such as MG, MicroEmacs,
- Freemacs, etc.
+ The set of changes have been posted a number of times three times the
+ last 12 months, so they should be widely available.
- Russ Nelson <nelson@sun.soe.clarkson.edu>, the author, describes
- Freemacs:
+ Richard Levitte <levitte@e.kth.se> tells us that there are patches for +
+ Emacs 18.57 and 18.58 available via e-mail: +
+ +
+ To: fileserv@ttt.kth.se +
+ body: SEND EMACS-1857-PATCHES +
+ or: SEND EMACS-1858-PATCHES +
- * Freemacs is free, and it was designed from the start to be
- programmable.
- * Freemacs is the only IBM-PC editor that tries to be like GNU Emacs.
- * Freemacs can only edit files less than 64K in length.
- * Freemacs doesn't have undo.
+104: Where can I get modes for Lex, Yacc/Bison, Bourne Shell, Csh, C++,
+ Objective C, Pascal, Awk?
- Carl Witty <cwitty@cs.stanford.edu> writes about Freemacs:
+ As usual, look in the Lisp Code Directory (see question 88). For C++,
+ if you use lisp-dir-apropos, you must specify the pattern like this:
- Better is Freemacs, which follows the tradition of ITS and GNU Emacs
- by having an full, turing-complete extension language which is
- incompatible with everything else. In fact, it's even closer to ITS
- Emacs than GNU Emacs is, because Mint (Freemacs' extension language)
- is absolutely illegible without weeks of study, much like TECO.
+ M-x lisp-dir-apropos RET c\+\+ RET
- You can get Freemacs several ways:
+105: What is the IP address of XXX.YYY.ZZZ?
- 1. Anonymous FTP:
- site: simtel20.army.mil, directory: PD:<MSDOS.FREEMACS>
- site: grape.ecs.clarkson.edu [128.153.13.196], directory: /e/freemacs
+ If you are at a site with a deficient nameserver, you may need to know
+ the IP address of a host to FTP files from it. You can get this
+ information in two ways: -
- 2. E-mail:
- address: archive-server@sun.soe.clarkson.edu, or
- archive-server%sun.soe@omnigate (BITNET), or
- {smart-host}!sun.soe.clarkson.edu!archive-server (UUCP)
- body: help
+ * By telnet:
- 3. Snail mail:
- address: Russell Nelson, 11 Grant St., Potsdam, NY 13676
- Send $15 copying fee, and specify preferred floppy disk format:
- 5.25", 1.2 Meg, or 5.25", 360K, or 3.50", 720K
+ telnet nic.ddn.mil hostnames (or `telnet 192.112.36.5 101')
+ hname XXX.YYY.ZZZ -
- I don't know much about MicroEmacs. All I know is that the latest
- version is 3.10 and it is available via:
+ * By e-mail:
+ To: service@nic.ddn.mil
+ Subject: host XXX.YYY.ZZZ
+ or: whois XXX.YYY.ZZZ
+ or: help
+
+ or: +
+ +
+ To: resolve@cs.widener.edu +
+ body: site XXX.YYY.ZZZ +
+ +
+ Information from Brendan Kehoe <brendan@cs.widener.edu>. +
+
+
+
+
+Major Emacs Lisp Packages, Emacs Extensions, and Related Programs
+
+ This section lists version numbers, FTP sites, mailing lists, newsgroups,
+ and other information for many important packages, extensions, and related
+ programs. There is some overlap with the Lisp Code Directory, but these
+ entries give more detailed information.
+
+ If you know of any other packages that are so substantial that they
+ deserve to be mentioned here, please tell me. Having its own mailing list
+ or newsgroup or more than half a megabyte of source code are good signs.
+
+106: VM (View Mail) -- another mail reader within Emacs
+
+ Author: Kyle Jones <kyle@uunet.uu.net>
+ Latest released version: 4.41
+ Beta test version: 5.32
+ Anonymous FTP:
+ /archive.cis.ohio-state.edu:pub/gnu/emacs/elisp-archive/packages/vm-4.41.tar.Z !
+ /archive.cis.ohio-state.edu:pub/gnu/emacs/elisp-archive/as-is/timer.shar.Z !
+ /ftp.uu.net:mail/vm-4.41.tar.Z !
+ /ftp.uu.net:mail/vm-5.32beta.tar.Z +
+ Newsgroups and mailing lists:
+ Info-VM:
+ gnu.emacs.vm.info
+ info-vm-request@uunet.uu.net (for subscriptions)
+ info-vm@uunet.uu.net (for submissions)
+ Bug-VM:
+ gnu.emacs.vm.bug
+ bug-vm-request@uunet.uu.net (for subscriptions)
+ bug-vm@uunet.uu.net (for submissions)
+
+107: Supercite -- mail and news citation package within Emacs
+
+ Author: Barry Warsaw <bwarsaw@cen.com>
+ Mailing list: supercite-request@anthem.nlm.nih.gov (for subscriptions)
+ supercite@anthem.nlm.nih.gov (for submissions)
+ Latest version: 2.2
+ Anonymous FTP:
+ /archive.cis.ohio-state.edu:pub/gnu/emacs/elisp-archive/packages/sc-2.2.tar.Z !
+ /ftp.cme.nist.gov:pub/gnu/sc2.2.tar.Z +
+ Via e-mail:
+ To: library@cme.nist.gov
+ Subject: help
+ NOTE: Superyank is an old version of Supercite.
+
+108: GNUS -- news reader within Emacs
+
+ Author: Masanobu Umeda <umerin@mse.kyutech.ac.jp>
+ Latest official version: 3.13
+ Unofficial test version: 3.14.1
+ Anonymous FTP:
+ /cs.umn.edu:pub/gnu/emacs/gnus-3.14.1.tar.Z. +
+ /aun.uninett.no:pub/gnus-3.14.1.tar.Z +
+ /wnoc-fuk.wide.ad.jp:pub/GNU/etc/gnus-3.14.1.tar.Z +
+ /liasun3.epfl.ch:pub/gnu/emacs/gnus-3.14.1.tar.Z +
+ /aix370.rrz.uni-koeln.de:/pub/gnu/emacs/gnus-3.14.1.tar.Z +
+ /funet.fi:/networking/news/gnus-3.14.1.tar.Z +
+ /src.doc.ic.ac.uk:/gnu/EmacsBits/gnus/gnus-3.14.1.tar.Z +
+ /archive.cis.ohio-state.edu:pub/gnu/emacs/elisp-archive/packages/gnus-3.13.tar.Z !
+ Newsgroups and mailing lists:
+ English-only:
+ gnu.emacs.gnus
+ info-gnus-english-request@cis.ohio-state.edu (for subscriptions)
+ info-gnus-english@cis.ohio-state.edu (for submissions)
+ Japanese (and some English):
+ info-gnus-request@flab.fujitsu.co.jp (for subscriptions)
+ info-gnus@flab.fujitsu.co.jp (for submissions)
+
+109: Calc -- poor man's Mathematica within Emacs
+
+ Author: Dave Gillespie <daveg@csvax.cs.caltech.edu>
+ Latest released version: 2.02
Anonymous FTP:
- site: durer.cme.nist.gov
+ /csvax.cs.caltech.edu:pub/calc-2.02.tar.Z +
+ /prep.ai.mit.edu:pub/gnu/calc-2.02.tar.Z +
+ NOTE: Unlike Wolfram Research, Dave has never threatened to sue anyone
+ for having a program with a similar command language to Calc. :-)
- Another Emacs for small machines is Jove (Jonathan's Own Version of
- Emacs). The latest version is 4.9. It is available via:
+110: Calendar/Diary -- calendar manager within Emacs
+ Author: Edward M. Reingold <reingold@cs.uiuc.edu>
+ Latest version: 4.02
Anonymous FTP:
- sites: hipl.psych.nyu.edu, cs.toronto.edu, cayuga.cs.rochester.edu
+ /emr.cs.uiuc.edu:pub/emacs/calendar {???} +
+ Via e-mail:
+ To: reingold@cs.uiuc.edu
+ Subject: send-emacs-cal
+ Put your best internet e-mail address in the body.
- Yet another Emacs is "mg", which used to stand for MicroGNUEmacs, but
- now just stands for "mg". It is available via:
+111: Ange-FTP -- transparent FTP access for Emacs's file access routines
+ Author: Andy Norman <ange@hplb.hpl.hp.com>
+ Latest official version: 4.20 !
Anonymous FTP:
- site: snow.white.toronto.edu
+ /alpha.gnu.ai.mit.edu:ange-ftp/ange-ftp.tar.Z !
+ /archive.cis.ohio-state.edu:pub/gnu/emacs/elisp-archive/packages/ange-ftp.tar.Z !
+ ugle.unit.no:pub/gnu/emacs-lisp/ange-ftp.tar.Z -
+ Mailing lists:
+ ange-ftp-lovers-request@anorman.hpl.hp.com (for subscriptions)
+ Ange-FTP Lovers:
+ ange-ftp-lovers@anorman.hpl.hp.com (for submissions)
+ /ftp.reed.edu:pub/mailing-lists/ange-ftp/ (archives) !
+ Ange-FTP Announcements:
+ ange-ftp-lovers-announce@anorman.hpl.hp.com
+ NOTE: now with support for accessing VMS, CMS, and MTS systems
+
+112: VIP -- vi emulation for Emacs
+
+ Author: Aamod Sane <sane@cs.uiuc.edu>
+ Latest released version: 4.3
+ Anonymous FTP:
+ /cs.uiuc.edu:pub/vip4.3.tar.Z +
+ /archive.cis.ohio-state.edu:pub/gnu/emacs/elisp-archive/modes/vip-mode.tar.Z !
+ NOTE: This version much more closely emulates vi than the one
+ distributed with Emacs.
+
+113: Dired -- better directory editor for Emacs
-31: Where can I get Emacs for my Atari ST?
+ Author: Sebastian Kremer <sk@thp.uni-koeln.de>
+ Latest released version: 5.239
+ Anonymous FTP: /ftp.cs.buffalo.edu:pub/Emacs/diredall.tar.Z +
+ /ftp.uni-koeln.de:pub/gnu/emacs/diredall.tar.Z +
+ NOTE: This is a huge improvement over the Dired distributed with Emacs.
+ This version will be in Emacs 19.
- The latest version for the ST is available via:
+114: AUC TeX -- enhanced LaTeX mode with debugging facilities
+ Author: Kresten Krab Thorup <krab@iesd.auc.dk>
+ Latest released version: 6.1 {???} !
Anonymous FTP:
- site: cs.uni-sb.de [134.96.7.254]
- directory: /pub/atari/emacs
+ /iesd.auc.dk:pub/emacs-lisp/auctex_5_6e.tar.Z {wrong} !
+ /iesd.auc.dk:pub/emacs-lisp/auc-tex.tar.Z !
+ Mailing list:
+ auc-tex-request@iesd.auc.dk (for subscriptions)
+ auc-tex@iesd.auc.dk (for submissions)
+ auc-tex_mgr@iesd.auc.dk (auc-tex development team)
+
+115: Hyperbole -- extensible hypertext management system within Emacs
-32: Where can I get Emacs with NeWS support?
+ Author: Bob Weiner <rsw@cs.brown.edu>
+ Anonymous FTP:
+ /wilma.cs.brown.edu:pub/hyperbole/ h*.tar.Z +
+ Mailing lists:
+ hyperbole-announce -- Hyperbole release announcements only.
+ Subscriptions:
+ To: hyperbole-request@cs.brown.edu
+ Subject: Add <mailbox@domain.name> to hyperbole-announce
+ hyperbole -- Hyperbole discussion.
+ Subscriptions:
+ To: hyperbole-request@cs.brown.edu
+ Subject: Add <mailbox@domain.name> to hyperbole
+ Submissions:
+ hyperbole@cs.brown.edu
+ NOTE: Any member of the hyperbole mailing list is automatically a
+ member of the hyperbole-announce mailing list.
+ NOTE: No .UUCP or ! addresses are allowed on these mailing lists.
+
+116: Byte Compiler -- enhanced version of Emacs's byte compiler
+
+ Author: Jamie Zawinski <jwz@lucid.com>,
+ Hallvard B. Furuseth <hallvard@ifi.uio.no>
+ Anonymous FTP:
+ /archive.cis.ohio-state.edu:pub/gnu/emacs/elisp-archive/packages/bytecomp.tar.Z !
+ /ftp.uu.net:languages/elisp/packages/bytecomp.tar.Z +
+ /src.doc.ic.ac.uk:gnu/EmacsBits/elisp-archive/packages/bytecomp.tar.Z +
- Chris Maio's NeWS support package for GNU Emacs is available via:
+117: comint -- hugely enhanced shell mode and other derived modes
+ Author: Olin Shivers <Olin.Shivers@cs.cmu.edu>
Anonymous FTP:
- site: columbia.edu
- file: /pub/ps-emacs.tar.Z
+ /cs.cmu.edu:/afs/cs.cmu.edu/user/shivers/lib/emacs/ +
+ {comint,cmu{tex,shell,scheme,lisp},ml}.el
+ (anonymous password must contain `@',
+ cannot cd to intermediate directories)
- site: tut.cis.ohio-state.edu
- file: /pub/gnu/emacs/ps-emacs.tar.Z
+118: BBDB -- personal info rolodex integrated with mail/news readers
+ Author: Jamie Zawinski <jwz@lucid.com>
+ Latest released version: 1.47 !
+ Anonymous FTP:
+ /archive.cis.ohio-state.edu:pub/gnu/emacs/elisp-archive/packages/bbdb.tar.Z !
+ Mailing list:
+ info-bbdb-request@lucid.com (for subscriptions)
+ info-bbdb@lucid.com -
+ bbdb-announce-request@lucid.com (to be informed of new releases)
+ Note: BBDB does not work with VM 4. It does work with VM 5, RMAIL, GNUS, !
+ and MH-E. !
+
+119: Ispell -- spell checker in C with interface for Emacs
+
+ Author: Geoff Kuenning <geoff@itcorp.com>
+ Latest released version: 2.0.02
+ Beta test version: 3.0 (9 patches)
+ Anonymous FTP:
+ /archive.cis.ohio-state.edu:/pub/gnu/ispell/ (version 2.0.02) !
+ /ftp.cs.ucla.edu:/pub/ispell/ (version 3.0, patches, dictionaries) !
+ /argus.math.orst.edu:pub/ispell/ (version 3.0, patches, dictionaries) !
+ /ftp.th-darmstadt.de:pub/dicts/ispell/ (mirror of argus) !
+ NOTE: Do not send mail to Geoff asking him to send you the latest
+ version of Ispell. He does not have free e-mail.
+
+120: Epoch -- enhanced GNU Emacs with better X interface
+
+ Latest released version: 4.2 !
+ Anonymous FTP:
+ /cs.uiuc.edu:pub/epoch-files/epoch/epoch-4.2.tar.Z !
+ /cs.uiuc.edu:pub/epoch-files/epoch/epoch-diff-4.1-4.2.tar.Z +
+ /src.doc.ic.ac.uk:gnu/epoch/ +
+ /aix370.rrz.uni-koeln.de:gnu/emacs/epoch/ +
+ Newsgroup and mailing lists:
+ Epoch:
+ gnu.emacs.epoch
+ epoch-request@cs.uiuc.edu (for subscriptions)
+ epoch@cs.uiuc.edu (for submissions)
+ Epoch-Design:
+ epoch-design-request@cs.uiuc.edu (for subscriptions)
+ epoch-design@cs.uiuc.edu (for submissions)
+ FAQ list:
+ Maintainer: Marc Andreessen <marca@ncsa.uiuc.edu>
+ Anonymous FTP:
+ /rtfm.mit.edu:pub/usenet/news.answers/epoch-faq +
+ /ftp.ncsa.uiuc.edu:outgoing/marca/epoch/Epoch.FAQ +
+
+121: Lucid GNU Emacs -- alternative Emacs 19 with better X interface
+
+ Primary Maintainer: Jamie Zawinski <jwz@lucid.com> +
+ Other Developers: Eric Benson <eb@lucid.com> !
+ Matthieu Devin <devin@lucid.com> !
+ Harlan Sexton <hbs@lucid.com> !
+ Latest released version: 19.3 !
+ Anonymous FTP:
+ /labrea.stanford.edu:pub/gnu/lucid/lemacs-19.3.tar.Z (source) !
+ /labrea.stanford.edu:pub/gnu/lucid/lemacs-19.3-sun4.tar.Z (Sun4binaries) !
+ Newsgroup and mailing lists:
+ Bugs:
+ bug-lucid-emacs-request@lucid.com (for subscriptions)
+ bug-lucid-emacs@lucid.com (for submissions)
+ Help:
+ help-lucid-emacs-request@lucid.com (for subscriptions)
+ help-lucid-emacs@lucid.com (for submissions)
+
+122: Demacs -- GNU Emacs altered to run on MS-DOS on 386/486 machines
+
+ Authors: Manabu Higashida <manabu@sigmath.osaka-u.ac.jp>
+ HIRANO Satoshi <hirano@tkl.iis.u-tokyo.ac.jp>
+ Latest released version: 1.2.0
+ Anonymous FTP:
+ /utsun.s.u-tokyo.ac.jp:GNU/demacs/ (nearest to U.S.A.) !
+ /ftp.sigmath.osaka-u.ac.jp:pub/Msdos/Demacs/ +
+ /wnoc-fuk.wide.ad.jp:pub/msdos/Demacs/ !
+ /ftp.3com.com:pub/gnu/msdos/demacs/ !
+ /mindseye.berkeley.edu:pub/kanji/demacs/ !
+ /ftp.hawaii.edu:pub/editors/demacs.tar.Z !
+ /ftp.math.ksu.edu:pub/pc/demacs/ +
+ /wsmr-simtel20.army.mil:pd1:<msdos.demacs> {ange-ftp syntax?} !
+ /ftp.uni-koeln.de:msdos/gnuprogs/dem120e.zip (executables, lisp-code, doc) !
+ (PLEASE USE ONLY OUTSIDE WORKING HOURS!) +
+ /ftp.uni-koeln.de:msdos/gnuprogs/dem120s.zip (sources, diffs) +
+ (PLEASE USE ONLY OUTSIDE WORKING HOURS!) +
+ /ftp.lysator.liu.se:pub/msdos/gnu/emacs/ +
+ /mizar.docs.uu.se:pub/gnu/demacs/ !
+ /iamsun.unibe.ch:PC/demacs/ !
+ /flop.informatik.tu-muenchen.de:outgoing/demacs.tar !
+ /ftp.funet.fi:pub/gnu/emacs/demacs/ +
+ /garbo.uwasa.fi:pc/editor/dem120e.zip !
+ /garbo.uwasa.fi:pc/editor/dem120s.zip !
+ /ftp.win.tue.nl:pub/gnu/demacs/ !
+ /ugle.unit.no:pub/gnu/Demacs/ !
+ {Does anyone know which sites have the Kanji version?}
+ Via e-mail:
+ From garbo.uwasa.fi:
+ To: mailserv@garbo.uwasa.fi
+ Subject: garbo-request
+ Body: send pc/editor/dem120e.zip
+ send pc/editor/dem120s.zip
+ quit
+ Downloading:
+ EXEC-PC (Milwaukee, WI) 414-789-4210 (2400 bps)
+ in the Mahoney MS-DOS file area in its Editors/wordprocessors
+ library (F), named GNUEMACS.ZIP
+ Channel 1 (Cambridge, MA) 617-345-8873 (9600 bps)
+ in the New Uploads file area, named GNUEMACS.ZIP
+ NOTE: Use the -d option of [pk]unzip for all .zip archives. Some sites
+ have Demacs lharc'ed. If you need to find programs to unpack lharc and -
+ zip format archives, Chris Dean <ctdean@talaris.com> points out that you
+ should see the comp.compression FAQ, available for FTP: !
+ /rtfm.mit.edu:pub/usenet/comp.compression/ !
+ Mailing list:
+ NOTE: There is no mailing list for Demacs. However, there is a list
+ for DJGPP, which is the environment that Demacs runs in. Many
+ Demacs problems are actually issues with DJGPP.
+ DJGPP:
+ Subscriptions:
+ To: listserv@sun.soe.clarkson.edu
+ body: add <your-address> djgpp
+ or put `help' in the body.
+ If this fails, mail to djgpp-request@sun.soe.clarkson.edu.
+ Submissions:
+ djgpp@sun.soe.clarkson.edu
+ FAQ list:
+ Maintainer: Dave Steibel <steibel@cs.umbc.edu>
+ Anonymous FTP: algol.cs.umbc.edu:pub/demacs/demacs.faq
+
+123: Freemacs -- a small Emacs for MS-DOS
+
+ Author: Russ Nelson <nelson@sun.soe.clarkson.edu>
+ Latest released version: 1.6a
+ Anonymous FTP:
+ /simtel20.army.mil:PD:<MSDOS.FREEMACS> {ange-ftp syntax?} !
+ /grape.ecs.clarkson.edu:pub/msdos/freemacs/ !
+ Via e-mail:
+ To: archive-server@sun.soe.clarkson.edu
+ body: help
+ Via snail mail:
+ address: Russell Nelson, 11 Grant St., Potsdam, NY 13676
+ Send $15 copying fee, and specify preferred floppy disk format:
+ 5.25", 360K, or 3.50", 720K
+ Mailing lists:
+ Subscriptions:
+ To: listserv@sun.soe.clarkson.edu
+ body: add <your-address> <name-of-list>
+ or put `help' in the body.
+ List distribution addresses:
+ freemacs-announce@sun.soe.clarkson.edu
+ freemacs-help@sun.soe.clarkson.edu
+ freemacs-workers@sun.soe.clarkson.edu (send bug reports here)
+
+124: Patch -- program to apply "diffs" for updating files
+
+ Author: Larry Wall <lwall@netlabs.com>
+ Latest version: 2.0 patchlevel 12u8 !
+ (This is the version that supports the new unified diff format.)
+ Anonymous FTP:
+ /prep.ai.mit.edu:pub/gnu/patch-2.0.12u8.tar.Z !
+ /prep.ai.mit.edu:pub/gnu/patch-2.0.12g8.tar.Z (GNU version) +
+
+ GNU Emacs FAQ: Keybindings/Output
+
+If you are viewing this text in a GNU Emacs Buffer, you can type "M-2 C-x $" to
+get an overview of just the questions. Then, when you want to look at the text
+of the answers, just type "C-x $".
+
+To search for a question numbered XXX, type "M-C-s ^XXX:", followed by a C-r if
+that doesn't work, then type ESC to end the search.
+A `+' in the 78th column means something was inserted on the line. A `-' means
+something was deleted and a `!' means some combination of insertions and
+deletions occurred.
-Binding Keys to Commands
+Full instructions for getting the latest FAQ are in question 22. Also see the
+`Introduction to news.answers' posting in the `news.answers' newsgroup, or send
+e-mail to `mail-server@rtfm.mit.edu' with `help' on a body line, or use FTP,
+WAIS, or Prospero to rtfm.mit.edu.
-33: Why does my key binding fail?
+
+
+Changing Key Bindings and Handling Key Binding Problems
+
+125: How do I bind keys (including function keys) to commands?
+
+ 1. Find out what character sequence is generated by the keystroke sequence
+ you wish to bind to a command. See question 129 for how to do this.
+ Keep in mind that the character sequences generated by a keystroke
+ sequence varies from one terminal to another. You may also get
+ different results depending on what type of machine you are running on
+ (see question 128). For example, these keystrokes may generate these
+ character sequences:
+
+ F1 ---> ESC [ 2 2 4 z
+ Shift-R10 ---> ESC O t
+ L7 ---> ESC [ 3 1 ~
+ Remove ---> C-@
+
+ 2. Figure out what the Emacs Lisp syntax is for this character sequence.
+ Inside an Emacs Lisp string, RET, LFD, DEL, ESC, SPC, and TAB are
+ specified with `\r', `\n', `\C-?', `\e', ` ', and `\t'. C-x is
+ specified by `\C-x'. M-x is specified the same was as "ESC x".
+ (Control characters may also be specified as themselves, but I don't
+ recommend it.) An Emacs Lisp string begins and ends with the double
+ quote character, `"'. Here are some examples:
- Most likely, it failed because "ESC [" was already defined. Evaluate
- this form first:
+ ESC [ D ---> "\e[D"
+ ESC [ 2 2 7 z ---> "\e[227z"
+ ESC [ 1 8 ~ ---> "\e[18~"
+ C-M-r ---> "\e\C-r"
+
+ 3. If some prefix of the character sequence is already bound, you must
+ unbind it by binding it to `nil'. For example:
+
+ (global-set-key "\e[" nil)
+
+ 4. Pick a command to bind your key sequence to. A command can be a
+ "symbol" with a function definition, or a "lambda list", or a string
+ (which is treated as a macro). For example:
+
+ (global-set-key "\e[D" 'backward-char)
+ (global-set-key "\e[227~" "\exgoto-line\r") ; macro
+
+ See `Key Bindings' and `Rebinding' in the online manual.
+
+ In Emacs 19 (including Lucid Emacs), you can bind function key F24 like +
+ this: +
+ +
+ (global-set-key 'f24 'some-command) +
+
+126: Why does Emacs say `Key sequence XXX uses invalid prefix characters'?
+
+ A prefix of the character sequence you were trying to bind was already
+ bound. Usually, the sequence is "ESC [", in which case you should
+ evaluate this form first:
(define-key esc-map "[" nil)
-34: Why doesn't this [terminal or window-system setup] code work in my
+ NOTE: By default, "ESC [" is bound to backward-paragraph, and if you do
+ this you will lose this key binding. For most people, this is not a
+ problem.
+
+ See question 125.
+
+127: Why doesn't this [terminal or window-system setup] code work in my
.emacs file, but it works just fine after Emacs starts up?
This is because you're trying to do something in your .emacs file that
needs to be postponed until after the terminal/window-system setup code
is loaded. This is a result of the order in which things are done
- during the startup of Emacs.
+ during the startup of Emacs. For more details see question 135.
In order to postpone the execution of Emacs Lisp code until after the
terminal/window-system setup, set the value of the variable
term-setup-hook or window-setup-hook to be a function which does what
you want.
- See question 72 for a complete explanation of what Emacs
- does every time it is started.
+ See etc/OPTIONS for a complete explanation of what Emacs does every time
+ it is started.
Here is a simple example of how to set term-setup-hook:
(setq term-setup-hook
(function
(lambda ()
- (if (string-match "^vt220" (or (getenv "TERM") ""))
- ;; Make vt220's "Do" key behave like M-x:
- (define-key CSI-map "29~" 'execute-extended-command)))))
-
-35: How do I use function keys under X Windows?
-
- If compiled on a Sun, Emacs recognizes the function keys that are
- normally on a Sun keyboard, and you can bind them the same way you
- normally bind Sun keys. Each function key will generate a key sequence
- that looks like "ESC [ ### z", where ### is replaced by a number.
-
- If not compiled on a Sun, the function keys will appear to Emacs in a
- way remarkably similar to the keys of a VT220 terminal. Each function
- key will generate a key sequence that looks like "ESC [ ### ~".
+ (cond ((string-match "\\`vt220" (or (getenv "TERM") ""))
+ ;; Make vt220's "Do" key behave like M-x:
+ (define-key CSI-map "29~" 'execute-extended-command))
+ ))))
+
+128: How do I use function keys under X Windows?
+
+ This depends on whether you are running Emacs inside a terminal emulator
+ window, or whether you are allowing Emacs to create its own X window.
+ You can tell which you are doing by noticing whether Emacs creates a new
+ window when you start it.
+
+ If you are running Emacs inside a terminal emulator window, then it
+ behaves exactly as it does on any other tty. In this case, for function
+ keys to be useful, they must generate character sequences that are sent
+ to the programs running inside the window as input. The `xterm' program
+ has two different sets of character sequences that it generates when
+ function keys are pressed, depending on the sunFunctionKeys X resource
+ and the -sf and +sf command line options. (To find out what these key
+ sequences are, see question 129.) In addition, with xterm,
+ you can override what key sequence a specific function key (or any other
+ key) will generate with the `translations' resource. This, for example:
+
+ XTerm.VT100.Translations: #override \
+ <KeyPress>F1: string(0x1b) string("[xyzzy")
+
+ makes the function key F1 generate the character sequence "ESC [xyzzy".
+
+ On the other hand, if Emacs is managing its own X window, the following
+ description applies. Emacs receives `KeyPress' events from the X server
+ when a key is pressed while the keyboard focus is in its window. The
+ KeyPress event contains an X "keysym" code, which is simply an arbitrary
+ number corresponding to the name of the keysym, and information on which
+ "modifiers" such as `control' and `shift' are active. For example, the
+ `Tab' keysym is 0xff09. (Generally, a key on the keyboard will generate a
+ keysym whose name is the same as the label on the key, ie. the `Tab' key
+ will normally generate the `Tab' keysym. This can be changed with the
+ xmodmap program.) Emacs recognizes all the keysyms that correspond to
+ standard ASCII characters and internally uses the ASCII character instead.
+
+ (WARNING: I am about to describe a gross, disgusting hack to you, have
+ your barf bag ready.)
+
+ When Emacs receives the X keysym of one of the arrow keys, it behaves
+ the same as if it had received a letter key with the control modifier
+ down as follows (this is hard-coded):
+
+ Up becomes C-p
+ Down becomes C-n
+ Right becomes C-f
+ Left becomes C-b
+
+ The way Emacs treats other keysyms depends on what kind of machine it was
+ compiled on. The type of the display machine is irrelevant! Function
+ keys are mapped internally to escape sequences, while other keys are
+ completely ignored.
+
+ 1. If compiled on a Sun, Emacs recognizes these X keysyms that
+ are normally on a Sun keyboard:
+
+ F1 through F9
+ L1 through L10 (same as F11 through F20)
+ R1 through R15 (same as F21 through F35)
+ (The keys labelled R8, R10, R12, and R14 usually are mapped to the
+ X keysyms Up, Left, Right, and Down.)
+ Break (the `Alternate' key is given this keysym)
+
+ These keys work like Sun function keys. When Emacs recieves the
+ keysym, it will internally use character sequences that look like "ESC
+ [ ### z", where ### is replaced by a number. The character sequences
+ are identical to those generated by Sun's keyboard under SunView. Any
+ function key not listed above generates "ESC [ - 1 z".
+
+ In order to use these key sequences, they should be bound to commands
+ using the standard key binding methods, just as if Emacs were running
+ on a regular terminal.
+
+ WARNING: F11 and L1 are the same keysym in X, as are F12 and L2, etc.
+ {Yes, this is stupid. Complain to the X consortium.}
+
+ 2. If not compiled on a Sun, the function keys will appear to Emacs in a
+ way remarkably similar to the keys of a DEC LK201 keyboard (used on
+ some VT series terminals). These X keysyms will be recognized:
+
+ F1 through F20
+ Help (treated same as F15)
+ Menu (treated same as F16, is the LK201 `Do' key)
+ Find
+ Insert (LK201 `Insert Here' key)
+ Select
+ Prior (LK201 `Prev Screen' key *** ONLY IN 18.58 AND LATER ***)
+ Next (LK201 `Next Screen' key *** ONLY IN 18.58 AND LATER ***)
+
+ And finally, the LK201 key labelled `Remove' (or `Delete') is often
+ mapped to the Delete keysym which generates the DEL character (C-?)
+ instead of the key sequence given by the LK201 `Remove' key. It may
+ also be mapped to some other keysym, such as `_Remove', in which case
+ you can't use it from within Emacs at all.
+
+ Each function key will be internally converted to a character sequence
+ that looks like "ESC [ ## ~", where ## is replaced by a number. The
+ character sequences are identical to those generated by a LK201
+ keyboard. Any function key not listed above generates "ESC [ - 1 ~".
For the complete list of the numbers which are generated by the function
- keys, look in the file src/x11term.c.
-
- However, this may be inadequate for you if you have function keys Emacs
- doesn't know about. Johan Vromans <jv@mh.nl> explains:
-
- There are a number of tricks that can be helpful. The most elegant
- solution, however, is to use the function "x-rebind-key". This function
- is commented out in the source for good reasons --- it's buggy.
-
- It is rather easy to replace this function with the function
- epoch:rebind-key from the Epoch distribution.
-
- After implementing this, all keyboard keys can be configured to send
- user definable sequences, e.g.
+ keys, look in the file src/x11term.c at the definitions of the function
+ stringFuncVal.
+
+ If you are running Emacs on a Sun machine, even if your X display is
+ running on a non-Sun machine (eg., an X terminal), you get the setup
+ described above for Suns. The determining factor is what type of
+ machine Emacs is running (was compiled) on, not what type of machine
+ your X display is on.
+
+ If you have function keys not listed above on your keyboard, you can use
+ `xmodmap' to change their keysym assignments to get keys that Emacs will
+ recognize, but that may screw up other programs.
+
+ X resources are not used by Emacs to affect the key sequences generated.
+ In particular, there are no X key "translations" for Emacs.
+
+ If you have function keys not listed above and you don't want to use
+ xmodmap to change their names, you might want to make a modification to
+ your Emacs. Johan Vromans <jv@mh.nl> has made available a patch for Emacs
+ that adds the x-rebind-key function of Epoch to Emacs 18.58. This allows
+ another layer of key rebinding before Emacs even sees the keys, and in
+ this layer you can rebind all of the keys and modifier combinations as
+ well.
- (x-rebind-key "KP_F1" 0 "\033OP")
-
- This will have the keypad key PF1 send the sequence \eOP, just like an
- ordinary VTxxx terminal.
+ Anonymous FTP:
+ /ftp.eu.net:gnu/emacs/FP-Xfun.Z +
+ /ftp.urc.tue.nl:pub/tex/emacs/FP-Xfun +
- Another method is to handle the keys in the C source. Although this may
- be slightly more efficient, it is much less flexible.
+ Johan Vromans explains what this buys for you:
- Finally, some people have established a convention to have the special
- keys send a sequence of characters that indicate the key and its
- modifiers instead of a plain escape sequence. This is also a good
- method. The advantage of sending the plain escape sequences is that you
- require only one setup for Emacs running under X and on normal
- terminals, e.g.
+ After implementing this, all keyboard keys can be configured to send
+ user definable sequences, eg.,
(x-rebind-key "KP_F1" 0 "\033OP")
- will have key PF1 send \eOP, and, probably in another setup file:
+ This will have the keypad key PF1 send the sequence "ESC O P", just like
+ an ordinary VT series terminal.
- (global-set-key "\eOP" 'specific-function)
-
- to bind PF1 to a function. The last statement applies for normal VTxxx
- terminal also.
-
-36: How do I tell what characters my function keys emit?
+129: How do I tell what characters my function or arrow keys emit?
Use this function by Randal L. Schwartz <merlyn@iwarp.intel.com>:
@@ -832,1569 +3225,1153 @@ Binding Keys to Commands
quit-flag nil)) ; quit-flag maybe set by C-g
(message "Characters entered: %s" (key-description chars))))
-
-
-Problems with Key Bindings and Input
-
-37: Why does Emacs spontaneously go into "I-search:" mode?
+ Alternatively, use the "C-h l" view-lossage command, which will display
+ the last 100 characters Emacs has seen in its input stream. Kevin
+ Gallagher <kgallagh@digi.lonestar.org> suggests typing some unique string
+ like "wxyz", typing the key in question, then typing "C-h l". The
+ characters that appear between "wxyz" and "C-h l" were generated by the
+ key.
- Your terminal (or something between your terminal and the computer) is
- sending C-s and C-q for flow control, and Emacs is receiving these
- characters and interpreting them as commands. (The C-s character
- normally invokes the isearch-forward command.)
+130: How do I set the X key "translations" for Emacs?
- For a more detailed discussion, read the file PROBLEMS in the Emacs
- distribution.
+ Sorry, you can't; there are no "translations" to be set. Emacs is not
+ written using the Xt library. The only way to affect the behavior of keys
+ within Emacs is through `xmodmap' (outside Emacs) or `define-key' (inside
+ Emacs).
-38: What do I do if my terminal is sending C-s and C-q for flow control and
- I can't disable it?
+131: How do I handle C-s and C-q being used for flow control?
- Use this piece of Emacs Lisp:
+ C-s and C-q are used in the XON/XOFF flow control protocol. This screws
+ up Emacs because it binds these characters to commands. Also, by default
+ Emacs will not honor them as flow control characters and may overwhelm
+ output buffers. Sometimes, intermediate software using XON/XOFF flow
+ control will prevent Emacs from ever seeing C-s and C-q.
- (set-input-mode nil t)
+ Possible solutions:
-39: How do I make Emacs use C-s and C-q for flow control instead of for
- commands?
+ * Disable the use of C-s and C-q for flow control.
- Same answer as previous question.
+ You need to determine what is the cause of the flow control.
-40: How do I use commands bound to C-s and C-q (or any key) if these keys
- are filtered out?
+ * your terminal
- I suggest swapping C-s with C-\ and C-q with C-^:
+ Your terminal may use XON/XOFF flow control to have time to display
+ all the characters it receives. For example, VT series terminals do
+ this. It may be possible to turn this off from a setup menu. For
+ example, on a VT220 you may select `No XOFF' in the setup menu. This
+ is also true for some terminal emulation programs on PCs.
- (swap-keys ?\C-s ?\C-\\)
- (swap-keys ?\C-q ?\C-^)
+ When you turn off flow control at the terminal, you will also need to
+ turn it off at the other end, which might be at the computer you are
+ logged in to or at some terminal server in between.
- See question 41 for the implementation of swap-keys.
+ If you turn off flow control, characters may be lost; using a printer
+ connected to the terminal may fail. You may be able to get around
+ this problem by modifying the `termcap' entry for your terminal to
+ include extra NUL padding characters.
-41: How do I "swap" two keys?
+ * a modem
- When Emacs receives a character, you can make Emacs behave as though it
- received another character by setting the value of
- keyboard-translate-table. The following Emacs Lisp will do this for
- you, allowing you to "swap" keys.
+ If you are using a dialup connection, the modems may be using XON/XOFF
+ flow control. I don't know how to get around this.
- WARNING: the value of C-g (7) is hard coded in several places both
- before and after the translation specified by keyboard-translate-table
- is carried out. Thus, swapping C-g with another key may cause problems;
- rebinding C-g may also cause problems. (Well, I've never done it, so I
- don't know for sure.)
+ * a router or terminal server
- (defun swap-keys (key1 key2)
- "Swap keys KEY1 and KEY2 using map-key."
- (map-key key1 key2 t)
- (map-key key2 key1))
+ Some network box between the terminal and your computer may be using
+ XON/XOFF flow control. It may be possible to make it use some other
+ kind of flow control. You will probably have to ask your local
+ network experts for help with this.
- (defvar map-keys-alist nil
- "Association list of key mappings currently in effect.
- If (FROM . TO) is an element, that means key FROM is currently mapped to TO.")
-
- (defun map-key (from to &optional no-update)
- "Make key FROM behave as though key TO was typed instead.
- If optional argument NO-UPDATE is non-nil, the key-mapping does not take
- effect until a subsequent map-key or unmap-key."
- (let ((alist-entry (assq from map-keys-alist)))
- (if alist-entry
- (setcdr alist-entry to)
- (setq map-keys-alist (cons (cons from to) map-keys-alist))))
- (or no-update (map-keys-update)))
+ * tty and/or pty devices
- (defun unmap-key (key)
- "Undo any mapping of key KEY."
- (setq map-keys-alist (delq (assq key map-keys-alist) map-keys-alist))
- (map-keys-update))
+ If your connection to Emacs goes through multiple tty and/or pty
+ devices, they may be using XON/XOFF flow control even when it is not
+ necessary.
- ;; Makes keyboard-translate-table reflect the key mappings in
- ;; map-keys-alist.
+ Eirik Fuller <eirik@theory.tn.cornell.edu> writes:
- (defun map-keys-update ()
- (if (null map-keys-alist)
- ;; Emacs runs fasted if keyboard-translate-table is nil
- (setq keyboard-translate-table nil)
- (let ((max-key-mapped
- ;; Find the mapped key with largest value
- (apply 'max
- (mapcar
- (function
- (lambda (x)
- (car x)))
- map-keys-alist)))
- (i 0))
- ;; keyboard-translate-table doesn't have to be any longer than
- ;; necessary. This speeds up Emacs.
- (setq keyboard-translate-table (make-string (1+ max-key-mapped) 0))
- (while (<= i max-key-mapped)
- (aset keyboard-translate-table i (or (cdr (assq i map-keys-alist)) i))
- (setq i (1+ i))))))
-
-42: Why does the "Backspace" key invoke help?
-
- The Backspace key (on every keyboard I've used) sends ASCII code 8. C-h
- sends the same code. In Emacs by default C-h invokes "help-command".
- The easiest solution to this problem is to use C-h (and Backspace) for
- help and DEL (the Delete key) for deleting the previous character.
+ Some versions of `rlogin' (and possibly telnet) do not pass flow
+ control characters to the remote system to which they connect. On
+ such systems, Emacs on the remote system cannot disable flow control
+ on the local system. Sometimes `rlogin -8' will avoid this problem.
- For some people this solution may be problematic:
-
- 1. They normally use Backspace outside of Emacs for deleting the
- previous character typed. This can be solved by making DEL be the
- command for deleting the previous character outside of Emacs. This
- command will do this on many Unix systems:
-
- stty erase ^?
-
- 2. The person may prefer using the Backspace key for deleting the
- previous character because it is more conveniently located on their
- keyboard or because they don't even have a separate Delete key. In
- this case, the best solution is to swap C-h and DEL:
-
- (swap-keys ?\C-h ?\C-?)
-
- See question 41 for the implementation of swap-keys.
-
-43: How do I type DEL on PC terminal emulators?
-
- Someone whose name I forgot wrote:
-
- Most PCs have deficient keyboards that don't have both Backspace and
- Delete keys. Whether C-h (backspace) or DEL is generated by the
- "Backspace" key varies from one terminal emulator to another. If you're
- lucky, you can reconfigure the keyboard so that it generates DEL. If
- not, you will have to hunt to figure out what keystroke will do it ---
- possibilities include various shifted and controlled versions of
- "Backspace", the "Del" key on the numeric keypad (which might depend on
- "Shift" or "NumLock"), or perhaps C-? (Control-?).
-
- If this is too hard, you may want to swap the delete key with some other
- key. See question 42.
-
-
-
-Building/Installing/Porting Emacs and Machine/OS-Specific Bugs:
-
-44: Why do I get an "f68881_used undefined" error, when I build Emacs on my
- Sun 3?
-
- Barry A. Warsaw <warsaw@cme.nist.gov> writes:
-
- Some of the code that is being linked on the "ld" line of emacs'
- build command has been compiled with the -f68881 option. Most
- common reason is that you're linking with X libraries which were
- built with -f68881 option set. You need to either remove all
- dependencies to the 68881 (may mean a recompile of the X libraries
- with -fswitch or -fsoft option), or you need to link emacs with
- the 68881 startup file /usr/lib/Mcrt1.o. Make this change to
- src/ymakefile:
-
- change: #define START_FILES crt0.o
- to: #define START_FILES crt0.o /usr/lib/Mcrt1.o
-
- The order of these start files is critical.
-
-45: Why does Emacs crash under SunOS 4.1?
-
- Under SunOS 4.1, Emacs dies with this message:
-
- Fatal error (6).Abort
-
- There is a bug in the "localtime" routine supplied with SunOS 4.1.
- A private function called by tzsetwall zeroes the byte just past an
- eight byte region it mallocs. This corrupts GNU malloc's memory pool.
-
- Put "#define SYSTEM_MALLOC" in src/config.h.
+ One way to cure this is to disable flow control on the local host
+ (the one running rlogin, not the one running rlogind) using the stty
+ command, before starting the rlogin process. On many systems, `stty
+ start u stop u' will do this.
- Or, for the purists:
-
- Put "#define SUNOS_LOCALTIME_BUG" in src/config.h and apply the following
- patch to src/malloc.c.
-
- (Patch by Eirik Fuller <eirik@elf.tn.cornell.edu>.)
+ Some versions of `tcsh' will prevent even this from working. One
+ way around this is to start another shell before starting rlogin,
+ and issue the stty command to disable flow control from that shell.
- >*** malloc.c~ Fri Apr 7 22:12:10 1989
- >--- malloc.c Tue May 8 07:07:22 1990
- >***************
- >*** 476,482 ****
- >--- 476,487 ----
- > multiple of 8, then figure out which nestf[] area to use.
- > Both the beginning of the header and the beginning of the
- > block should be on an eight byte boundary. */
- >+ #ifdef SUNOS_LOCALTIME_BUG
- >+ /* SunOS 4.1 localtime scribbles on the ninth byte. */
- >+ nbytes = (n + ((sizeof *p + 15) & ~15) + EXTRA + 15) & ~15;
- >+ #else
- > nbytes = (n + ((sizeof *p + 7) & ~7) + EXTRA + 7) & ~7;
- >+ #endif
- > {
- > register unsigned int shiftr = (nbytes - 1) >> 2;
- >
+ Use `stty -ixon' instead of `stty start u stop u' on some systems.
-46: Why does Emacs occasionally cause segmentation faults and machine
- panics on my DECstation 3100?
+ * Make Emacs speak the XON/XOFF flow control protocol.
- Bruce Cole <cole@dip.cs.wisc.edu> writes:
+ You can make Emacs treat C-s and C-q as flow control characters by
+ evaluating this form:
- > We're running Emacs 18.54 on an Ultrix Risc DECsystem 5400. Three
- > times we've had the machine hang with the following message:
- >
- > panic: tblmod on invalid pte
- >
- > Ultrix support tells us this is caused by Emacs. Has anyone
- > experienced this? DEC says it only happens on RISC boxes.
+ (set-input-mode nil t)
- This is due to a MIPS specific Ultrix kernel bug. I sent DEC a
- description of the bug with a bug fix. The Kernel bug manifests itself
- with Emacs since Emacs uses a non-standard data start address on Ultrix
- MIPS machines.
+ If you are fixing this for yourself, simply put the form in your .emacs
+ file. If you are fixing this for your entire site, the best place to
+ put it is unclear. I don't know if this has any effect when used in
+ lisp/site-init.el when building Emacs; I've never tried that. {Can
+ someone tell me whether it works?} Putting things in users' .emacs files
+ has a number of problems.
- I haven't often seen Emacs cause MIPS machines to panic. Usually you
- just see one of the following errors when you try to start up Emacs:
+ Putting this form in lisp/default.el has the problem that if the user's
+ .emacs file has an error, this will prevent lisp/default.el from being
+ loaded and Emacs may be unusable for the user, even for correcting their
+ .emacs file (unless they're smart enough to move it to another name). A
+ possible solution is to initially disable C-s and C-q by setting
+ keyboard-translate-table in lisp/site-init.el, either with swap-keys
+ (see question 136) or with the following form:
- segmentation fault (core dumped)
- emacs: Bad address
- Out of memory
- data size rlimit exceeded, pid 6523, process tcsh (for example)
+ ;; by Roger Crew <crew@cs.stanford.edu>:
+ (setq keyboard-translate-table
+ "\C-@\C-a\C-b\C-c\C-d\C-e\C-f\C-g\C-h\C-i\C-j\C-k\C-l\C-m\C-n\C-o\C-p\C-^\C-r\C-\\\C-t\C-u\C-v\C-w\C-x\C-y\C-z\C-[\C-s\C-]\C-q\C-_")
- Until DEC fixes their kernel, you can avoid the bug by changing the data
- start address used by Emacs.
+ This will at least prevent Emacs from being confused by the flow control
+ characters, even if lisp/default.el cannot be loaded. Then, in
+ lisp/default.el, enable XON/XOFF flow control with set-input-mode.
- > I have built two newer versions of GNU Emacs and it still happens. I
- > should also mention that these faults happen quite rarely to some
- > users (I may see it once a month), while other users see it a few
- > times a week or even daily!
+ For further discussion of this issue, read the file PROBLEMS in the
+ Emacs distribution.
- The problem only occurs when a MIPS machine is doing a lot of paging.
- Users who don't cause their workstation to page will not see this
- problem.
+132: How do I use commands bound to C-s and C-q (or any key) if these keys
+ are filtered out?
- Patch to GNU Emacs 18.55:
+ I suggest swapping C-s with C-\ and C-q with C-^:
- >*** m-pmax.h Thu Jun 8 11:53:55 1989
- >--- m-pmax.h.new Mon Jul 9 10:21:21 1990
- >***************
- >*** 1,3 ****
- >--- 1,7 ----
- > #include "m-mips.h"
- > #undef LIBS_MACHINE
- > #undef BIG_ENDIAN
- >+ #undef LD_SWITCH_MACHINE
- >+ #undef DATA_START
- >+ #define DATA_START 0x10000000
- >+ #define DATA_SEG_BITS 0x10000000
+ (swap-keys ?\C-s ?\C-\\)
+ (swap-keys ?\C-q ?\C-^)
-47: How do I get Emacs running on VMS under DECwindows?
+ See question 136 for the implementation of swap-keys. This method
+ has the advantage that it simultaneously swaps the characters everywhere
+ throughout Emacs, while just switching the keybindings will miss important
+ places where the character codes are stored (eg., the search-repeat-char
+ variable, major mode keymaps, etc.).
- Hal R. Brand <BRAND@addvax.llnl.gov> is said to have a VMS save set with
- a ready-to-run VMS version of Emacs for X Windows. It is available via:
+ To do this for an entire site, you may want to swap the keys in
+ lisp/default.el. If only some of your users are connecting through
+ XON/XOFF flow-controlled connections, you will want to do this
+ conditionally. I suggest pre-swapping them in lisp/site-init.el when
+ Emacs is built, and then in lisp/default.el, if it is determined to be
+ safe, they can be reenabled (being careful not to screw up any other key
+ mappings users might have established using keyboard-translate-table).
+ See question 131 for an easy way to pre-swap these keys.
- Anonymous FTP:
- site: addvax.llnl.gov
+ WARNING: If you do this for an entire site, the users will be confused by
+ the disparity between what the documentation says and how Emacs actually
+ behaves.
- Johan Vromans <jv@mh.nl> writes:
+133: Why does the `BackSpace' key invoke help?
- Getting Emacs to run on VMS with DECwindows requires a number of changes
- to the sources. Fortunately this has been done already. Joshua Marantz
- <josh@viewlogic.com> did most of the work for Emacs 18.52, and the mods
- were ported to 18.55 by Johan Vromans <jv@mh.nl>. Also included is the
- handling of DEC's LK201 keyboard. You need to apply the changes to a
- fresh Emacs 18.55 distribution on a Unix system, and then you can copy
- the sources to VMS to perform the compile/link/build.
-
- The set of changes have been posted a number of times three times the
- last 12 months, so they should be widely available.
-
-48: Why won't src/alloc.c compile on a SPARCstation?
-
- {Could someone send me a better description of the symptoms ... Does it
- really not compile, or does it refuse to link, or does it die when it's
- run?}
-
- An object in src/alloc.c is declared as an array of char. However, on a
- SPARCstation, this object must be aligned on a longword boundary.
- gcc will align this object not on a longword boundary because it thinks
- this is ok because the object is an array of char.
-
- Here is a solution:
-
- (Patch from the Epoch source code.)
-
- >*** dist-18.55.dist/src/alloc.c Mon Feb 13 05:23:35 1989
- >--- dist-18.55/src/alloc.c Mon Nov 27 23:30:13 1989
- >***************
- >*** 665,673 ****
- > #define NSTATICS 200
- >
- >- char staticvec1[NSTATICS * sizeof (Lisp_Object *)] = {0};
- >-
- > int staticidx = 0;
- >
- > #define staticvec ((Lisp_Object **) staticvec1)
- >
- > /* Put an entry in staticvec, pointing at the variable whose address is given */
- >--- 665,676 ----
- > #define NSTATICS 200
- >
- > int staticidx = 0;
- >
- >+ #ifdef __GNUC__
- >+ Lisp_Object *staticvec[NSTATICS] = {0};
- >+ #else
- >+ char staticvec1[NSTATICS * sizeof (Lisp_Object *)] = {0};
- > #define staticvec ((Lisp_Object **) staticvec1)
- >+ #endif
- >
- > /* Put an entry in staticvec, pointing at the variable whose address is given */
-
- {Does anyone understand why one might want to declare staticvec as an
- array of char instead of an array of LispObject?}
-
-49: Why do shells started from Emacs suspend themselves under SunOS 4.1?
-
- In SunOS 4.1, when subprocesses are started by an Emacs process started
- by "rsh", the process stops with a message like this:
-
- Process shell stopped (tty input)
-
- SunOS 4.1 uses the POSIX standard's specification for job control.
- Basically, a process must be a session leader to acquire a new
- controlling terminal.
-
- A quick fix is to run Emacs as "/usr/etc/setsid emacs" instead.
-
- To fix it in Emacs, use this patch:
-
- (Patch by Eirik Fuller <eirik@elf.tn.cornell.edu>.)
-
- >*** /tmp/,RCSt1a12635 Fri Jul 6 11:29:10 1990
- >--- process.c Sat Jun 16 14:04:55 1990
- >***************
- >*** 1031,1036 ****
- >--- 1031,1039 ----
- > int j = open ("/dev/tty", O_RDWR, 0);
- > ioctl (j, TIOCNOTTY, 0);
- > close (j);
- >+ #ifndef USG
- >+ setpgrp (0, 0);
- >+ #endif
- > }
- > #endif /* TIOCNOTTY */
- >
-
-50: Why does Emacs crash from a bus error in XLookupString under OpenLook?
-
- The Sun OpenLook libraries use the XComposeStatus parameter on
- XLookupString for composing key sequences. I'm told this is actually
- supposed to be an optional parameter.
-
- (Patch by David J. MacKenzie <djm@eng.umd.edu>.)
-
- >*** dist-18.55.dist/src/x11term.c Wed Aug 2 21:56:42 1989
- >--- dist-18.55/src/x11term.c Fri Jul 13 19:22:32 1990
- >***************
- >*** 1213,1216 ****
- >--- 1213,1218 ----
- > #endif /* not sun */
- >
- >+ static XComposeStatus status;
- >+
- > internal_socket_read(bufp, numchars)
- > register unsigned char *bufp;
- >***************
- >*** 1223,1227 ****
- > BLOCK_INPUT_DECLARE ();
- > XEvent event;
- >- XComposeStatus status;
- > KeySym keysym;
- >
- >--- 1225,1228 ----
- >***************
- >*** 1330,1334 ****
- > nbytes = XLookupString (&event,
- > mapping_buf, 20, &keysym,
- >! 0);
- > /* Someday this will be unnecessary as we will
- > be able to use XRebindKeysym so XLookupString
- >--- 1331,1335 ----
- > nbytes = XLookupString (&event,
- > mapping_buf, 20, &keysym,
- >! &status);
- > /* Someday this will be unnecessary as we will
- > be able to use XRebindKeysym so XLookupString
-
-51: Why doesn't "C-c C-c" interrupt subprocesses under HP/UX?
-
- Paul Stravers <stravers@dutentb.tudelft.nl> writes:
-
- In HP/UX we can (must) combine the two distinct calls
- 1. ioctl (fildes, TIOCGPGRP, &gid);
- 2. kill (-gid, signo);
- into the single call
- 1+2. ioctl (fildes, TIOCSIGSEND, signo);
-
- This is apparently the case under at least HP/UX versions 6.5 and 7.0.
-
- Here is a set of patches courtesy of Piet van Oostrum <piet@cs.ruu.nl>
- that fixes these problems:
-
- 1. Signals to child processes work now (like the C-c C-c mentioned above)
-
- 2. When running under X11, C-g now correctly interrupts long-running commands
-
- 3. When running under X11, the window is redislayed even if emacs is doing
- some work (e.g. if your window becomes visible after being behind another
- one.
-
- 4. A nasty bug in alloca is solved. This bug is very infrequent unless you
- apply the other patches.
-
- {I don't know for sure whether all of these patches are applicable only
- under HP/UX. Perhaps someone can tell me.}
-
- >*** alloca.s.~1~ Fri Sep 15 16:35:39 1989
- >--- alloca.s Tue May 1 17:18:08 1990
- >***************
- >*** 92,103 ****
- > sub.l &MAXREG*4,%d1 # space for saving registers
- > mov.l %d1,%sp # save new value of sp
- > tst.b PROBE(%sp) # create pages (sigh)
- > move.w &MAXREG-1,%d0
- > copy_regs_loop: /* save caller's saved registers */
- >! mov.l (%a1)+,(%sp)+
- > dbra %d0,copy_regs_loop
- >! mov.l %sp,%d0 # return value
- >! mov.l %d1,%sp
- > add.l &-4,%sp # adjust tos
- > jmp (%a0) # rts
- > #endif /* new hp assembler */
- >--- 92,105 ----
- > sub.l &MAXREG*4,%d1 # space for saving registers
- > mov.l %d1,%sp # save new value of sp
- > tst.b PROBE(%sp) # create pages (sigh)
- >+ mov.l %a2,%d1 # save reg a2
- >+ mov.l %sp,%a2
- > move.w &MAXREG-1,%d0
- > copy_regs_loop: /* save caller's saved registers */
- >! mov.l (%a1)+,(%a2)+
- > dbra %d0,copy_regs_loop
- >! mov.l %a2,%d0 # return value
- >! mov.l %d1,%a2 # restore a2
- > add.l &-4,%sp # adjust tos
- > jmp (%a0) # rts
- > #endif /* new hp assembler */
-
- >*** keyboard.c.~1~ Wed Apr 4 14:53:49 1990
- >--- keyboard.c Thu Apr 26 14:46:27 1990
- >***************
- >*** 719,724 ****
- >--- 719,773 ----
- > errno = old_errno;
- > }
- >
- >+ #ifdef HPUX
- >+ /* tells if an alarm is outstanding for emptying the socket */
- >+ int socket_alarm;
- >+
- >+ static void
- >+ empty_socket_interrupt()
- >+ {
- >+ int nread;
- >+ char buf[256 * BUFFER_SIZE_FACTOR];
- >+ register int i;
- >+ int old_errno = errno;
- >+
- >+ if (waiting_for_input) return;
- >+
- >+ fcntl (fileno (stdin), F_SETFL, O_NDELAY);
- >+
- >+ /* Read what is waiting. */
- >+
- >+ nread = (*read_socket_hook) (0, buf, sizeof buf);
- >+
- >+ #ifdef EBADSLT
- >+ if (nread == -1 && (errno == EAGAIN || errno == EBADSLT))
- >+ #else
- >+ if (nread == -1 && errno == EAGAIN)
- >+ #endif
- >+ nread = 0;
- >+
- >+ fcntl (fileno (stdin), F_SETFL, 0);
- >+
- >+ /* Scan the chars for C-g and store them in kbd_buffer. */
- >+ kbd_ptr = kbd_buffer;
- >+ for (i = 0; i < nread; i++)
- >+ {
- >+ kbd_buffer_store_char (buf[i]);
- >+ /* Don't look at input that follows a C-g too closely.
- >+ This reduces lossage due to autorepeat on C-g. */
- >+ if (buf[i] == Ctl ('G'))
- >+ break;
- >+ }
- >+
- >+ /* reestablish interrupt */
- >+ signal (SIGALRM, empty_socket_interrupt);
- >+ alarm (1);
- >+
- >+ errno = old_errno;
- >+ }
- >+
- >+ #endif /* HPUX */
- >+
- > /* read a character from the keyboard; call the redisplay if needed */
- > /* commandflag 0 means do not do auto-saving, but do do redisplay.
- > -1 means do not do redisplay, but do do autosaving.
- >***************
- >*** 733,738 ****
- >--- 782,794 ----
- > Lisp_Object tem;
- > extern request_echo ();
- >
- >+ #ifdef HPUX
- >+ if (socket_alarm) {
- >+ alarm (0);
- >+ socket_alarm = 0;
- >+ }
- >+ #endif
- >+
- > if ((c = unread_command_char) >= 0)
- > {
- > unread_command_char = -1;
- >***************
- >*** 869,874 ****
- >--- 925,938 ----
- > }
- > }
- >
- >+ #ifdef HPUX
- >+ if (read_socket_hook) {
- >+ socket_alarm = 1;
- >+ signal (SIGALRM, empty_socket_interrupt);
- >+ alarm (1);
- >+ }
- >+ #endif
- >+
- > return c;
- > }
- >
- >***************
- >*** 1094,1119 ****
- >
- > #else /* no FIONREAD */
- > #ifdef USG
- > if (kbd_count)
- > abort ();
- >
- > fcntl (fileno (stdin), F_SETFL, O_NDELAY);
- >! kbd_ptr = kbd_buffer;
- > if (read_socket_hook)
- >! {
- >! kbd_count = (*read_socket_hook) (0, kbd_buffer, sizeof kbd_buffer);
- >! }
- > else
- >! {
- >! kbd_count = read (fileno (stdin), kbd_buffer, sizeof kbd_buffer);
- >! }
- > #ifdef EBADSLT
- >! if (kbd_count == -1 && (errno == EAGAIN || errno == EBADSLT))
- > #else
- >! if (kbd_count == -1 && errno == EAGAIN)
- > #endif
- >! kbd_count = 0;
- > fcntl (fileno (stdin), F_SETFL, 0);
- > #else /* not USG */
- > you lose
- > #endif /* not USG */
- >--- 1158,1209 ----
- >
- > #else /* no FIONREAD */
- > #ifdef USG
- >+ char buf[256 * BUFFER_SIZE_FACTOR];
- >+ register int i;
- >+ #ifdef HPUX
- >+ int mask;
- >+ #endif
- >+
- > if (kbd_count)
- > abort ();
- >
- >+ #ifdef HPUX
- >+ if (socket_alarm)
- >+ mask = sigblock (sigmask (SIGALRM));
- >+ #endif
- >+
- > fcntl (fileno (stdin), F_SETFL, O_NDELAY);
- >!
- >! /* Read what is waiting. */
- > if (read_socket_hook)
- >! nread = (*read_socket_hook) (0, buf, sizeof buf);
- > else
- >! nread = read (fileno(stdin), buf, sizeof buf);
- > #ifdef EBADSLT
- >! if (nread == -1 && (errno == EAGAIN || errno == EBADSLT))
- > #else
- >! if (nread == -1 && errno == EAGAIN)
- > #endif
- >! nread = 0;
- >!
- > fcntl (fileno (stdin), F_SETFL, 0);
- >+
- >+ /* Scan the chars for C-g and store them in kbd_buffer. */
- >+ kbd_ptr = kbd_buffer;
- >+ for (i = 0; i < nread; i++)
- >+ {
- >+ kbd_buffer_store_char (buf[i]);
- >+ /* Don't look at input that follows a C-g too closely.
- >+ This reduces lossage due to autorepeat on C-g. */
- >+ if (buf[i] == Ctl ('G'))
- >+ break;
- >+ }
- >+
- >+ #ifdef HPUX
- >+ if (socket_alarm)
- >+ sigsetmask(mask);
- >+ #endif
- >+
- > #else /* not USG */
- > you lose
- > #endif /* not USG */
-
- >*** x11term.h~ Fri Sep 15 15:20:26 1989
- >--- x11term.h Thu Apr 26 14:03:25 1990
- >***************
- >*** 11,17 ****
- >--- 11,22 ----
- > #define sigmask(no) (1L << ((no) - 1))
- > #endif
- >
- >+ #ifdef HPUX
- > #define BLOCK_INPUT_DECLARE() int BLOCK_INPUT_mask
- >+ #define BLOCK_INPUT() BLOCK_INPUT_mask = sigblock (sigmask (SIGALRM))
- >+ #define UNBLOCK_INPUT() sigsetmask (BLOCK_INPUT_mask)
- >+ #else /* not HPUX */
- >+ #define BLOCK_INPUT_DECLARE() int BLOCK_INPUT_mask
- > #ifdef SIGIO
- > #define BLOCK_INPUT() BLOCK_INPUT_mask = sigblock (sigmask (SIGIO))
- > #define UNBLOCK_INPUT() sigsetmask (BLOCK_INPUT_mask)
- >***************
- >*** 19,23 ****
- >--- 24,29 ----
- > #define BLOCK_INPUT()
- > #define UNBLOCK_INPUT()
- > #endif /* SIGIO */
- >+ #endif /* HPUX */
- >
- > #define CLASS "emacs" /* class id for GNU Emacs, used in .Xdefaults, etc. */
-
- >*** process.c.orig Fri Sep 15 16:28:36 1989
- >--- process.c Fri Apr 20 13:17:06 1990
- >***************
- >*** 1057,1062 ****
- >--- 1057,1079 ----
- > signal (SIGHUP, SIG_DFL);
- > #endif
- > #endif /* HAVE_PTYS */
- >+
- >+ /* Give child clean slate for signals */
- >+ #ifdef SIGCHLD
- >+ #ifdef BSD4_1
- >+ sigrelse (SIGCHLD);
- >+ #else /* not BSD4_1 */
- >+ #ifdef HPUX
- >+ sigsetmask (0);
- >+ #endif /* HPUX */
- >+ #if defined (BSD) || defined (UNIPLUS)
- >+ sigsetmask (0);
- >+ #else /* ordinary USG */
- >+ signal (SIGCHLD, sigchld);
- >+ #endif /* ordinary USG */
- >+ #endif /* not BSD4_1 */
- >+ #endif /* SIGCHLD */
- >+
- > child_setup_tty (xforkout);
- > child_setup (xforkin, xforkout, xforkout, new_argv, env);
- > }
- >***************
- >*** 1413,1427 ****
- > if (read_kbd && kbd_count)
- > nfds = 0;
- > else
- >! #ifdef IBMRTAIX
- > nfds = select (MAXDESC, &Available, 0, 0, &timeout);
- > #else
- >- #ifdef HPUX
- >- nfds = select (MAXDESC, &Available, 0, 0, &timeout);
- >- #else
- > nfds = select (MAXDESC, &Available, 0, &Exception, &timeout);
- > #endif
- >- #endif
- > xerrno = errno;
- >
- > if (fix_screen_hook)
- >--- 1430,1440 ----
- > if (read_kbd && kbd_count)
- > nfds = 0;
- > else
- >! #if defined (IBMRTAIX) || defined (HPUX)
- > nfds = select (MAXDESC, &Available, 0, 0, &timeout);
- > #else
- > nfds = select (MAXDESC, &Available, 0, &Exception, &timeout);
- > #endif
- > xerrno = errno;
- >
- > if (fix_screen_hook)
- >***************
- >*** 1771,1776 ****
- >--- 1784,1790 ----
- > error ("Process %s is not active",
- > XSTRING (p->name)->data);
- >
- >+ #ifndef HPUX /* Can't get gid of tty's controlling session */
- > #ifdef TIOCGPGRP /* Not sure about this! (fnf) */
- > /* If we are using pgrps, get a pgrp number and make it negative. */
- > if (!NULL (current_group))
- >***************
- >*** 1785,1790 ****
- >--- 1799,1805 ----
- > the child itself heads the pgrp. */
- > gid = - XFASTINT (p->pid);
- > #endif /* not using pgrps */
- >+ #endif /* not HPUX */
- >
- > switch (signo)
- > {
- >***************
- >*** 1800,1805 ****
- >--- 1815,1827 ----
- > flush_pending_output (XFASTINT (p->infd));
- > break;
- > }
- >+
- >+ #ifdef HPUX
- >+ if (!NULL (current_group))
- >+ ioctl (XFASTINT (p->infd), TIOCSIGSEND, signo);
- >+ else
- >+ kill (XFASTINT (p->pid), signo);
- >+ #else /* not HPUX */
- > /* gid may be a pid, or minus a pgrp's number */
- > #ifdef BSD
- > /* On bsd, [man says] kill does not accept a negative number to kill a pgrp.
- >***************
- >*** 1808,1813 ****
- >--- 1830,1836 ----
- > #else /* Not BSD. */
- > kill (gid, signo);
- > #endif /* Not BSD. */
- >+ #endif /* Not HPUX */
- >
- > /* Put notices in buffers now, since it is safe now.
- > Because of this, we know that a process we have just killed
- >%
-
- This is a separate patch to process.c, distinct from the immediately
- preceding one. Both should be applied.
-
- >*** process.c.~1~ Fri Apr 20 13:17:06 1990
- >--- process.c Wed Oct 24 16:38:15 1990
- >***************
- >*** 1085,1095 ****
- > /* If the subfork execv fails, and it exits,
- > this close hangs. I don't know why.
- > So have an interrupt jar it loose. */
- >! signal (SIGALRM, create_process_1);
- >! alarm (1);
- >! if (forkin >= 0)
- >! close (forkin);
- >! alarm (0);
- > if (forkin != forkout && forkout >= 0)
- > close (forkout);
- >
- >--- 1085,1100 ----
- > /* If the subfork execv fails, and it exits,
- > this close hangs. I don't know why.
- > So have an interrupt jar it loose. */
- >!
- >! { int old_trap = signal (SIGALRM, create_process_1);
- >! int old_alarm = alarm (1);
- >! if (forkin >= 0)
- >! close (forkin);
- >! alarm (0);
- >! signal (SIGALRM, old_trap);
- >! /* don't bother with possible 1 sec loss */
- >! if (old_alarm) alarm (old_alarm);
- >! }
- > if (forkin != forkout && forkout >= 0)
- > close (forkout);
-
-52: What should I do if I have trouble building Emacs?
+ The BackSpace key (on every keyboard I've used) generates ASCII code 8.
+ C-h sends the same code. In Emacs by default C-h invokes help-command.
+ This is intended to be easy to remember since the first letter of "help"
+ is "h". The easiest solution to this problem is to use C-h (and
+ BackSpace) for help and DEL (the Delete key) for deleting the previous
+ character.
- RMS writes:
+ For many people this solution may be problematic:
- If you try to build Emacs and it does not run, the first thing to do is
- look in the file called PROBLEMS to see if a solution is given there.
+ * They normally use BackSpace outside of Emacs for deleting the previous
+ character typed. This can be solved by making DEL be the command for
+ deleting the previous character outside of Emacs. This command will do
+ this on many Unix systems:
- If none is given, then please send a report by mail to
- bug-gnu-emacs@prep.ai.mit.edu. Please do not send it to
- help-gnu-emacs@prep.ai.mit.edu.
+ stty erase '^?'
- Sending to help-gnu-emacs (which has the effect of posting on
- gnu.emacs.help) is undesirable because it takes the time of an
- unnecessarily large group of people, most of whom are just users and
- have no idea how to fix these problem. bug-gnu-emacs reaches a much
- smaller group of people who are more likely to know what to do and have
- expressed a wish to receive more messages about Emacs than the others.
-
-Weird/Confusing Problems:
-
-53: Does Emacs have problems with files larger than 8 Megs?
+ * The person may prefer using the BackSpace key for deleting the previous
+ character because it is more conveniently located on their keyboard or
+ because they don't even have a separate Delete key. In this case, the
+ BackSpace key should be made to behave like Delete. There are several
+ methods.
- Most installed versions of GNU Emacs will use 24 bit signed integers
- (and 24 bit pointers!) internally. This limits the file size that Emacs
- can handle to 8388608 bytes.
+ * Under X Windows, the easiest solution is to change the BackSpace key
+ into a Delete key like this:
- Leonard N. Zubkoff <lnz@lucid.com> writes:
+ xmodmap -e "keysym BackSpace = Delete"
- Putting the following two lines in src/config.h before compiling Emacs
- allows for 26 bit integers and pointers:
+ * Some terminals (eg., VT3## terminals) allow the character generated by
+ the BackSpace key to be changed from a setup menu.
- #define VALBITS 26
- #define GCTYPEBITS 5
+ * You may be able to get a keyboard that is completely programmable.
- See question 54 for an explanation.
+ * Under X or on a dumb terminal, it is possible to swap the BackSpace
+ and Delete keys inside Emacs:
-54: Why does Emacs use 24 bit integers and pointers?
+ (swap-keys ?\C-h ?\C-?)
- David Gillespie <daveg@csvax.cs.caltech.edu> writes:
+ See question 136 for the implementation of swap-keys.
- Emacs is largely written in a dialect of Lisp; Lisp is a freely-typed
- language in the sense that you can put any value of any type into any
- variable, or return it from a function, and so on. So each value must
- carry a "tag" along with it identifying what kind of thing it is, e.g.,
- integer, pointer to a list, pointer to an editing buffer, and so on.
- Emacs uses standard 32-bit integers for data objects, taking the top 8
- bits for the tag and the bottom 24 bits for the value. So integers (and
- pointers) are somewhat restricted compared to true C integers and
- pointers.
+ * Another approach is to switch keybindings and put help on "C-x h"
+ instead:
- Emacs uses 8-bit tags because that's a little faster on byte-oriented
- machines, but there are only really enough tags to require 6 bits. See
- question 53 to find how to recompile Emacs with 6-bit tags and
- 26-bit integers and pointers if space is at a premium for you.
+ (global-set-key "\C-h" 'delete-backward-char)
+ (global-set-key "\C-xh" 'help-command) ; override mark-whole-buffer
-55: Why does Emacs start up using the wrong directory?
+ Other popular key bindings for help are M-? and "C-x ?".
- Most likely, you have an environment variable named PWD that is set to a
- value other than the name of your current directory. This is most
- likely caused by using two different shell programs. "ksh" and (some
- versions of) "csh" set and maintain the value of the PWD environment
- variable, but "sh" doesn't. If you start sh from ksh, change your
- current directory inside sh, and then start Emacs from inside sh, PWD
- will have the wrong value but Emacs will use this value. See question
- 72.
+ WARNING: Don't try to bind DEL to help-command, because there are many
+ modes that have local bindings of DEL that will interfere. -
-56: How do I edit a file with a "$" in its name?
+134: Why doesn't Emacs look at the stty settings for Backspace vs. Delete?
- When entering a filename in the minibuffer, Emacs will attempt to expand
- a "$" followed by a word as an environment variable. To suppress this
- behavior, type "$$" instead.
+ Good question!
-57: Why does Shell Mode lose track of the shell's current directory?
+135: Why don't the arrow keys work?
- Emacs has no way of knowing when the shell actually changes its
- directory. So it tries to guess by recognizing cd commands. A number
- of fixes and enhancements to Shell Mode have been written, check the
- Emacs Lisp Archive (question 14).
+ When Emacs starts up, it doesn't know anything about arrow keys at all
+ (except when running under X, see question 128). During the process of
+ starting up, Emacs will load a terminal-specific initialization file for
+ your terminal type (as determined by the environment variable TERM), if
+ one exists. This file has the responsibility for enabling the arrow keys.
-58: Why doesn't Emacs expand my aliases when sending mail?
+ There are several things that can go wrong:
- First, you must separate multiple addresses with commas.
+ 1. There is no initialization file for your terminal.
- Emacs normally only reads the ".mailrc" file once per session, when you
- start to compose your first mail message. If you edit .mailrc, you can
- type "M-ESC (build-mail-aliases) RET" to make Emacs reread .mailrc.
+ You can determine this by looking in the lisp/term directory. If your
+ terminal type (as determined by the TERM environment variable) is
+ xxx-yy-z, then the first of these files in the lisp/term directory will
+ be loaded as the terminal-specific initialization file: xxx-yy-z.el,
+ xxx-yy.el, or xxx.el.
-59: Why doesn't setting default-directory always work?
+ There are two major cases of this problem:
- There is a separate value of default-directory for each Emacs buffer.
- The value in the current buffer is the one that is used.
+ * Your terminal type is very similar to one that has an init file.
-60: Why does my change to load-path not work?
+ In this case, there are several techniques suggested by Colin Jensen
+ <cjensen@ampex.com>, Ben Liblit <Liblit@cs.psu.edu>, and Marc
+ Auslander <marc@watson.ibm.com>:
- If you added file names with tildes (~) in them to your load-path,
- you'll need to do something like this:
+ A. Add a symbolic link in lisp/term for your terminal type that
+ points to the similar type. For example, you could make VT102
+ terminals work with this command:
- (setq-default load-path (mapcar 'expand-file-name load-path))
+ ln -s vt100.el vt102.el
-61: Why does the cursor always go to the wrong column when I move up or
- down one line?
+ This fixes things for everyone on the system who uses the terminal
+ type.
- You have inadvertently typed "C-x C-n" (set-goal-column) which sets the
- "goal-column" to the column where the cursor was. To undo this type
- "C-u C-x C-n".
+ B. If you can't do the solution in part A, you can add code to your
+ term-setup-hook that loads the correct file like this:
- If you make this mistake frequently, you might want to unbind this
- command by doing (define-key ctl-x-map "\C-n" nil).
-
-62: Why don't the command line switches documented in the man page work?
-
- The "man page", ie. the file etc/emacs.1, hasn't been updated in a
- while. The command line switches that it says work with X Windows are
- for X10. See question 72 for details on what switches are
- available using X11. {Would someone like to rewrite the man page? RMS
- asked me and I haven't had time yet.}
-
-63: Why does gnus-Subject-mail-reply chop off the last character of the
- article headers?
-
- There is a bug in some rnews functions that GNUS uses. Here is a patch:
-
- (Patch supplied by Karl Kleinpaste <karl_kleinpaste@cis.ohio-state.edu>.)
-
- >*** rnewspost.el.orig Thu Oct 5 10:32:47 1989
- >--- rnewspost.el Thu Oct 5 10:32:47 1989
- >***************
- >*** 252,258 ****
- > (save-restriction
- > (narrow-to-region (point-min) (progn (goto-line (point-min))
- > (search-forward "\n\n")
- >! (- (point) 2)))
- > (setq from (mail-fetch-field "from")
- > subject (mail-fetch-field "subject")
- > reply-to (mail-fetch-field "reply-to")
- >--- 252,258 ----
- > (save-restriction
- > (narrow-to-region (point-min) (progn (goto-line (point-min))
- > (search-forward "\n\n")
- >! (- (point) 1)))
- > (setq from (mail-fetch-field "from")
- > subject (mail-fetch-field "subject")
- > reply-to (mail-fetch-field "reply-to")
- >***************
- >*** 289,295 ****
- > ;@@ but rnews.el lacks support
- > (narrow-to-region (point-min) (progn (goto-char (point-min))
- > (search-forward "\n\n")
- >! (- (point) 2)))))
- > (setq from (mail-fetch-field "from")
- > news-reply-yank-from from
- > ;; @@ not handling old Title: field
- >--- 289,295 ----
- > ;@@ but rnews.el lacks support
- > (narrow-to-region (point-min) (progn (goto-char (point-min))
- > (search-forward "\n\n")
- >! (- (point) 1)))))
- > (setq from (mail-fetch-field "from")
- > news-reply-yank-from from
- > ;; @@ not handling old Title: field
- >***************
- >*** 365,371 ****
- > ;@@ but rnews.el lacks support
- > (narrow-to-region (point-min) (progn (goto-char (point-min))
- > (search-forward "\n\n")
- >! (- (point) 2)))))
- > (setq news-reply-yank-from (mail-fetch-field "from")
- > ;; @@ not handling old Article-I.D.: field
- > news-reply-yank-message-id (mail-fetch-field "message-id")))
- >--- 365,371 ----
- > ;@@ but rnews.el lacks support
- > (narrow-to-region (point-min) (progn (goto-char (point-min))
- > (search-forward "\n\n")
- >! (- (point) 1)))))
- > (setq news-reply-yank-from (mail-fetch-field "from")
- > ;; @@ not handling old Article-I.D.: field
- > news-reply-yank-message-id (mail-fetch-field "message-id")))
-
-64: Why does Emacs hang with message "Unknown XMenu" with X11R4?
+ (setq term-setup-hook
+ (function
+ (lambda ()
+ (cond ((equal "vt102" (or (getenv "TERM") ""))
+ (load (concat term-file-prefix "vt100")))
+ (;; Code for other terminal types goes here ...
+ )))))
- Many different X errors can produce this message. Here is the solution
- to one problem:
+ C. If you use `tset' to set your TERM environment variable when you
+ login, you can use the `-m' switch to tell tset to use a terminal
+ type known by Emacs instead of another similar one. For example,
+ specifying this:
- X11 Release 4 now enforces some conditions in the X protocol that were
- previously allowed to pass unnoticed. You need to put the X11R4 server
- into X11R3 bug compatibility mode for Emacs's Xmenu code to work. You
- can do this with the command "xset bc".
+ tset ... -m 'dec-vt220:vt220' ...
-65: Why isn't the load average displayed by display-time?
+ will make tset say you are on a `vt220' instead of a `dec-vt220'.
- The most likely cause of the problem is that "loadst" can't read the
- special file /dev/kmem. To properly install loadst, it should be either
- setuid to the owner of /dev/kmem, or is should be setgid to the group to
- which /dev/kmem belongs. In either case, /dev/kmem should be readable by
- its owner or its group, respectively.
+ D. Interactively, you can type "M-x load-library RET term/vt100" to
+ load the terminal-specific initialization files for VT100
+ terminals.
- Another possibility is that your version of Unix doesn't have the load
- average data available in /dev/kmem. Your version of Unix might have a
- special system call to retrieve this information (eg., inq_stats under
- UMAX).
+ * Your terminal type is not similar to one that has an init file.
-66: Why doesn't GNUS work anymore via NNTP?
+ One can be made for your terminal, or you can just add code to your
+ own .emacs to handle this problem for yourself. For example, if your
+ terminal's arrow keys send these character sequences:
- There is a bug in NNTP version 1.5.10, such that when multiple requests
- are sent to the NNTP server, the server only handles the first one before
- blocking waiting for more input which never comes.
+ Up: ESC [ A
+ Down: ESC [ B
+ Right: ESC [ C
+ Left: ESC [ D
- You can work around the bug inside Emacs like this:
+ then you can bind these keys to the appropriate commands with code in
+ your .emacs like this:
- (setq nntp-maximum-request 1)
- (setq nntp-buggy-select t)
+ (setq term-setup-hook
+ (function
+ (lambda ()
+ (cond ((string-match "\\`xyzzy" (or (getenv "TERM") ""))
+ ;; First, must unmap the binding for left bracket
+ (or (keymapp (lookup-key global-map "\e\["))
+ (define-key global-map "\e\[" nil))
+ ;; Enable terminal type xyzzy's arrow keys:
+ (define-key global-map "\e\[A" 'previous-line)
+ (define-key global-map "\e\[B" 'next-line)
+ (define-key global-map "\e\[C" 'forward-char)
+ (define-key global-map "\e\[D" 'backward-char))
+ ((string-match "\\`abcde" (or (getenv "TERM") ""))
+ ;; Do something different for terminal type abcde
+ ;; .....
+ )))))
- Or you could fix the NNTP server in one of these ways:
+ NOTE: You may have to restart Emacs to get changes to take effect.
- 1. Test whether there is data in stdin's stdio buffer before calling
- "select" using something like "((fileptr)->_cnt > 0)". Best choice.
- 2. Remove call to select by not defining "TIMEOUT" in "common/conf.h".
- 3. Put "setbuf (stdin, NULL)" in the NNTP server in the right spot.
- This would be very inefficient.
- 4. Rewrite the server to use an alarm instead of "select".
+ NOTE: Your arrow keys may send sequences beginning with "ESC O" when
+ Emacs is running, even if they send sequences beginning with "ESC [" at
+ all other times. This is because Emacs uses any command there may be
+ in your terminal's termcap entry for putting the terminal into
+ "Application Keypad Mode". Just map these sequences the same way as
+ above.
-67: Why can't I paste a selection I made in Emacs into my xterm window?
+ The next two cases are problems even if there is a initialization file for
+ your terminal type.
+
+ 2. The initialization file for your terminal doesn't bind arrow keys.
+
+ If your terminal type is `xterm', you will have to bind the arrow keys
+ as in part 1 above, since the xterm.el file doesn't do anything useful.
+ There may be other terminal types with the same problem.
- A person whose name I lost writes:
+ 3. Your terminal's arrow keys send individual control characters.
+
+ For example, the arrow keys on an ADM-3 send C-h, C-j, C-k, and C-l.
+
+ There is not much Emacs can do in this situation, since all the control
+ characters except for C-^ and C-\ are already used as Emacs commands.
+ It may be possible to convince the terminal to send something else when
+ you press the arrow keys; it is worth investigating.
+
+ You have to make the hard choices of how to rebind keys to commands to
+ make things work the way you want. Another alternative is to start
+ learning the standard Emacs keybindings for moving point around: C-b,
+ C-f, C-p, and C-n. Personally, I no longer use the arrow keys when
+ editing because I have switched keyboards so many times.
+
+ 4. Your terminal's arrow keys send sequences beginning with "ESC [".
+
+ Due to an extremely poor design decision (ie., these sequences are ANSI
+ standard), none of the the terminal-specific initialization files that
+ are distributed with Emacs will bind these character sequences to the
+ appropriate commands by default. (This also applies to any other
+ function keys which generate character sequences starting with "ESC
+ [".) This is because it was deemed far more important to preserve the
+ binding of M-[ to the backward-paragraph command. It appears that this
+ will change in Emacs 19.
+
+ Some of the terminal-specific initialization files that come with Emacs
+ provide a command enable-arrow-keys that will fix this problem. To get
+ this automatically invoked, put this in your .emacs:
+
+ (setq term-setup-hook
+ (function
+ (lambda ()
+ (if (fboundp 'enable-arrow-keys) (enable-arrow-keys)))))
+
+ We put this in our lisp/default.el file, so users don't have to worry
+ about it:
+
+ ;; don't override a user's term-setup-hook
+ (or term-setup-hook
+ (setq term-setup-hook
+ (function
+ (lambda ()
+ (and (fboundp 'enable-arrow-keys)
+ ;; don't override a user key mapping
+ (eq 'backward-paragraph (lookup-key esc-map "["))
+ (enable-arrow-keys))))))
+
+ If your terminal type is `sun', you should put this in your .emacs
+ instead (or in addition to the above):
+
+ (setq sun-esc-bracket t)
+
+ It is possible that the terminal-specific initialization file for your
+ terminal type was written locally and does not follow the rule
+ mentioned above. In this case you may need to inspect it to find out
+ how to enable the arrow keys. (Actually, if it was written locally, it
+ probably enables the arrow keys by default.)
+
+136: How do I "swap" two keys?
- The strange interaction between Emacs, xterm, and the cut buffers is
- because most xterm clients use selections instead of (well, superceding)
- cut buffers. If there is a selection around, xterms will use that
- instead of the cut buffer. Emacs doesn't know about selections, but you
- can convince xterm to always use the cut buffer instead of selections by
- adding this to your .Xdefaults:
+ When Emacs receives a character, you can make Emacs behave as though it
+ received another character by setting the value of
+ keyboard-translate-table. The following Emacs Lisp will do this for you,
+ allowing you to "swap" keys. After arranging for this Lisp to be
+ evaluated by Emacs, you can evaluate `(swap-keys ?A ?B)' to swap A and B.
- ! Solution by Thomas Narten, should work under X11R3 and later
- ! GNU Emacs only copies to CUT_BUFFER0. xterm by default wants to paste
- ! from the PRIMARY selection.
- XTerm*VT100.Translations: #override \
- ~Meta <Btn2Up>: insert-selection(CUT_BUFFER0)
+ (defun swap-keys (key1 key2)
+ "Swap keys KEY1 and KEY2 using map-key."
+ (map-key key1 key2)
+ (map-key key2 key1))
-
-68: Why does ispell sometimes ignore the local dictionary?
+ (defun map-key (from to)
+ "Make key FROM behave as though key TO was typed instead."
+ (setq keyboard-translate-table
+ (concat keyboard-translate-table
+ (let* ((i (length keyboard-translate-table))
+ (j from)
+ (k i)
+ (str (make-string (max 0 (- j (1- i))) ?X)))
+ (while (<= k j)
+ (aset str (- k i) k)
+ (setq k (1+ k)))
+ str)))
+ (aset keyboard-translate-table from to)
+ (let ((i (1- (length keyboard-translate-table))))
+ (while (and (>= i 0) (eq (aref keyboard-translate-table i) i))
+ (setq i (1- i)))
+ (setq keyboard-translate-table
+ (if (eq i -1)
+ nil
+ (substring keyboard-translate-table 0 (1+ i))))))
+
+ NOTE: You must evaluate the definition of these functions before calling
+ them! For example, list the function definitions before their use in your
+ .emacs file.
+
+ NOTE: These functions take two numbers as arguments. The example above,
+ `(swap-keys ?A ?B)' is actually `(swap-keys 65 66)', because `?A' is
+ merely notation for 65, the ASCII value of `A'.
+
+ NOTE: These functions only work for single characters. You cannot swap
+ two multi-character sequences.
+
+137: How do I produce C-XXX with my keyboard?
+
+ For C-@ and C-^, often you can just type Control-2 and Control-6. For
+ C-_, you may have to hold down the shift key, typing Control-Shift-Hyphen.
+ C-@ can often be generated by typing Control-Space. C-@ is often called
+ the NUL character, and has ASCII value 0. C-_ can often be generated by
+ typing Control-7 or Control-/. C-? (aka DEL) may be generated by typing
+ Shift-BackSpace or Control-BackSpace or a key labelled Delete or Del.
+
+ Try Control with all of the digits on your keyboard to see what gets
+ generated.
+
+138: What if I don't have a Meta key?
- You need to update the version of ispell to 2.0.02. A patch is
- available via:
+ Instead of typing M-a, you can type "ESC a" instead. In fact, Emacs
+ converts M-a internally into "ESC a" anyway (depending on the value of
+ meta-prefix-char).
- Anonymous FTP:
- site: tut.cis.ohio-state.edu
- file: /pub/gnu/ispell/patch2.Z
+139: What if I don't have an Escape key?
- You also need to change a line in ispell.el from:
+ Type C-[ instead. This should send ASCII code 27 just like an Escape
+ key would. Try also C-;.
- (defconst ispell-version "2.0.01") ;; Check against output of "ispell -v".
+140: How do I type DEL on PC terminal emulators?
- to:
+ Some IBM PC compatibles do not have a key labeled `Del' or `Delete' {is
+ this true?}. Those that do generally have it in an inconvenient location.
+ (Also, in some terminal emulators, the `Del' key does not transmit DEL.)
+ The result is the standard "BackSpace invoking help" problem (see question
+ 133).
- (defconst ispell-version "2.0.02") ;; Check against output of "ispell -v".
+ The usual solution, suggested by Michael Covington
+ <mcovingt@aisun1.ai.uga.edu>, is to somehow tell the terminal emulator
+ program that BackSpace should transmit DEL. Read the program's manual.
+ Shift-BackSpace or Control-BackSpace may send DEL. The `Del' key may only
+ send DEL if the NumLock key hasn't been pressed.
-
-
-Configuring Emacs for yourself:
-
-69: How do I set up a .emacs file properly?
+141: Can I make my `Compose Character' key behave like a Meta key?
- I'm going to be sending out a sample .emacs file in a separate message
- later this month. It will be based largely on AT&T's sample .emacs
- file, which was sent to me by Dan Jacobson. In fact it might be
- identical.
+ On a dumb terminal such as a VT220, no. It is rumored that certain VT220
+ clones could have their Compose key configured this way. If you're using
+ X, you might be able to do this with the `xmodmap' program (this is
+ what I do).
-70: How do you debug a .emacs file?
+142: How do I bind a combination of modifier key and function key?
- First start Emacs with the "-q" command line option. Then, in the
- *scratch* buffer, type the following:
+ Unless you're using Emacs under emacstool (or xvetool?), have a working !
+ version of x-rebind-key (see question 128), or are using Emacs 19 (Lucid +
+ Emacs), you can't do this with Emacs alone. +
- (setq debug-on-error t) C-j
- (load-file "~/.emacs") C-j
+ If you are using emacstool, Emacs sees different character sequences for
+ the combination of a modifier and a function key from what it sees for the
+ function key alone. See etc/emacstool.1 for more information. Since
+ Emacs sees different character sequences, you can bind these different
+ sequences to different commands.
- (C-j stands for Control-J, ie., hold the control key and press J.)
+ If you are running Emacs inside a terminal emulator window like xterm, you
+ can modify its translation tables to make it generate different character
+ sequences for the combination of a modifier and a function key. For
+ example, this X resource setting:
- If you have an error in your .emacs file, this will invoke the debugger
- when the error occurs. If you don't know how to use the debugger do
- (setq stack-trace-on-error t) instead.
+ XTerm.VT100.Translations: #override \
+ Shift<KeyPress>F1: string(0x1b) string("[xyzzy")
- WARNING: this will not discover errors caused by trying to do something
- that requires the terminal/window-system initialization code to have
- been loaded. See question 34.
+ makes Shift-F1 generate the character sequence "ESC [ xyzzy". You can
+ bind these character sequences in Emacs as normal. Nick Ruprecht
+ <ruprecht@informatik.uni-freiburg.de> has written an extensive X
+ translation mapping for xterm that does this. {Does this have an FTP
+ site?}
-71: How do I turn on abbrevs by default just in mode XXX?
+ If you have x-rebind-key, you can have any arbitrary combination of +
+ modifiers with a key replaced by any sequence of "normal" characters. For +
+ example, this makes Shift-Return behave as though you had typed "C-x C-e" +
+ (example from Jerry Graves): +
+ +
+ (x-rebind-key "Return" 'shift "\C-x\C-e") +
+ +
+ In Emacs 19 (Lucid Emacs), you can bind Meta-Left-Arrow like this (example +
+ from Jamie Zawinski): +
+ +
+ (global-set-key '(meta left) 'backward-word) +
+ +
+ With the last two methods, use `xmodmap' and `xev' to discover the keysym +
+ and modifier names. +
- Put this in your .emacs file:
+143: Why doesn't my Meta key work in an xterm window?
- (condition-case ()
- (read-abbrev-file nil t)
- (file-error nil))
+ Try all of these methods before asking for further help:
- (setq XXX-mode-hook
- (function
- (lambda ()
- (setq abbrev-mode t))))
+ * You may have big problems using `mwm' as your window manager. {Does
+ anyone know a good generic solution to allow the use of the Meta key in
+ Emacs with mwm?}
-72: What does Emacs do every time it starts up?
+ * For X11R4: Make sure it really is a Meta key. Use `xev' to find out
+ what keysym your Meta key generates. It should be either Meta_L or
+ Meta_R. If it isn't, use xmodmap to fix the situation.
- This question is not itself frequently asked, but helps to answer other
- questions.
+ * Make sure the pty the xterm is using is passing 8 bit characters.
+ `stty -a' (or `stty everything') should show `cs8' somewhere. If it
+ shows `cs7' instead, use `stty cs8 -istrip' (or `stty pass8') to fix
+ it.
- Here is a complete explanation of the order in which things are done
- during startup.
+ * If there is an rlogin connection between the xterm and the Emacs, the
+ `-8' argument may need to be given to rlogin to make it pass all 8
+ bits of every character.
- 1. These command line switches are handled, only if they appear before
- all other command line arguments, and only if they appear in this
- order:
+ * If the Emacs is running under Ultrix, it is reported that evaluating
+ (set-input-mode t nil) helps.
- "-map". Only under VMS. Instead of "undumping", under VMS the
- contents of a dump file are mapped over a section of memory (very
- quickly initializing lots of variables).
+ * If all else fails, you can make xterm generate "ESC W" when you type
+ M-W, which is the same conversion Emacs would make if it got the M-W
+ anyway. In X11R4, the following resource specification will do this:
- "-t". The next argument is treated as the name of a terminal to use
- instead of whatever is connected to the stdin, stdout, and stderr
- FILE pointers.
+ XTerm.VT100.EightBitInput: false
- "-display" (synonym: "-d"). The next argument is treated as the
- name of an X Window System server with which to connect. This
- overrides the DISPLAY environment variable.
+ (This changes the behavior of the insert-eight-bit action.)
- "-nw". This means don't connect to an X Window server even if the
- DISPLAY environment variable was set or the "-display" switch was
- specified. Instead, Emacs talks to a regular dumb terminal.
+ With older xterms, you can specify this behavior with a translation:
- "-batch". Emacs is noninteractive. The variable "noninteractive"
- is t. This disables any full screen interaction either with a
- dumb terminal or with a window system. In addition, Emacs will
- die after processing all command line arguments.
+ XTerm.VT100.Translations: #override \
+ Meta<KeyPress>: string(0x1b) insert()
- All of Emacs's internal data structures are initialized between steps 2
- and 5.
+ You might have to replace `Meta' with `Alt'.
- 2. The "*scratch*" buffer is created and its value of default-directory
- is set from the result of calling the "getwd" library routine.
- (getwd does what the "pwd" program does.)
+144: Why doesn't my ExtendChar key work as a Meta key under HP-UX 8.0?
- 3. If X11 is being used, Emacs determines the name under which it looks
- for X resource values. (I haven't checked how it does this under
- X10.)
+ This is a result of an internationalization extension in X11R4 and the
+ fact that HP is now using this extension. Emacs assumes that
+ XLookupString returns the same result regardless of the Meta key state
+ which is no longer necessarily true. Until Emacs is fixed, the temporary
+ kludge is to run this command after each time the X server is started but
+ preferably before any xterm clients are:
- 1. If there is a "-rn" command line switch, it is handled now, no
- matter where it is on the command line. (Later it will be
- processed again and ignored.) The next argument is used as
- Emacs's resource name.
+ xmodmap -e 'remove mod1 = Mode_switch'
- 2. If the "-rn" switch was missing, Emacs looks for the WM_RES_NAME
- environment variable.
+ NOTE: This will disable the use of the extra keysyms systemwide, which
+ may be undesirable if you actually intend to use them.
- 3. If neither of the previous two steps succeed, Emacs uses the
- filename with which it was invoked as its resource name.
+145: Where can I get key bindings to make Emacs emulate WordStar?
- 4. If X11 is being used, these command line switches are handled now,
- no matter where they appear in the command line. (Under X10, they
- are not handled until step 13.) WARNING: this can cause strange
- interactions with the processing of the remaining command line
- arguments in step 13.
+ There is a package `wordstar' by Jim Frost <jimf@saber.com> and
+ `ws-mode.el' by Juergen Nickelsen <nickel@cs.tu-berlin.de>. Check in the
+ Emacs Lisp Archive (see question 89).
- In addition, under both X11 and X10, X resources (ie. the stuff in
- an .Xdefaults file) are handled now. Command line switches take
- precedence over resources.
+146: Where can I get an XEDIT emulator for Emacs?
- After each command line switch are given the equivalent resource
- names in this format: (X10 name / X11 instance name / X11 class name).
+ This question comes up once every couple of months. I have never seen a
+ positive reply, so I presume no one has ever written one.
- "-r". Reverse video. (ReverseVideo/reverseVideo/ReverseVideo)
- "-font" (synonym: "-fn"). Font. (BodyFont/font/Font)
- "-wn". Window name (X11 only). (/title/Title)
- "-in". Icon name (X11 only). (/iconName/Title)
- "-i". Use built-in icon bitmap. (BitMapIcon//)
+
+
+Using Emacs with Alternate Character Sets
+
+147: How do I make Emacs display 8-bit characters?
- "-b". Border width (in pixels).
- (BorderWidth/borderWidth/BorderWidth)
+ There is a patch called the `8-bit ctl-arrow patch' that allows Emacs to
+ display characters with codes from 128 to 255. {The original appears to
+ have been by Kenneth Cline <cline@proof.ergo.cs.cmu.edu>.} Partially based
+ on Johan Widen's earlier work, Johan Vromans <jv@mh.nl> has updated this
+ patch for Emacs 18.58 along with some other 8-bit improvements.
- "-ib". Internal border width (in pixels) (default: 1).
- (/internalBorder/BorderWidth)
+ Anonymous FTP:
+ /ftp.eu.net:gnu/emacs/FP-EightBit.Z +
+ /ftp.urc.tue.nl:pub/tex/emacs/FP-EightBit +
+ /cs.purdue.edu:pub/ygz/cemacs.tar.Z:cemacs/8bit-patch-18.57 +
+ /sics.se:archive/emacs-18.55-8bit-diff +
+ /laas.laas.fr:pub/emacs/patch-8bit-18.55 !
+ /laas.laas.fr:pub/emacs/patch-8bit-18.57 !
- "-geometry" (synonym: "-w"). Window shape and size. "-geometry" is
- X11 only, but its synonym "-w" was available under X10.
- (/geometry/Geometry)
+ Via e-mail:
+ To: mail-server@sics.se
+ body: send emacs-18.55-8bit-diff
- Color options only:
+ Anders Edenbrandt <anderse@dna.lth.se> has produced a more comprehensive
+ patch for Emacs 18.57 that allows for 8-bit input and output.
- "-fg". Foreground color. (Foreground/foreground/Foreground)
- "-bg". Background color. (Background/background/Background)
- "-bd". Border color. (Border/borderColor/BorderColor)
- "-cr". Cursor color. (Cursor/cursorColor/Foreground)
- "-ms". Mouse pointer color. (Mouse/pointerColor/Foreground)
+ Anonymous FTP:
+ /sics.se:archive/emacs-8bit-diff-lth +
+ /gatekeeper.dec.com:pub/GNU/DS-emacs-18.57-8bit-diff-lth +
- In addition, under X10, the resource "Keymap" was handled now.
+ The most comprehensive patches for 8-bit output are by Howard Gayle
+ (originally for Emacs 18.55. These patches allow displaying any arbitrary
+ string for a given 8-bit character (except TAB and C-j). Also supported
+ is defining the sorting order and the uppercase and lowercase
+ translations. It is reported that the 8-bit character support in Emacs 19
+ is largely based on these patches. Thomas Bellman
+ <Bellman@lysator.liu.se> has updated these patches for Emacs 18.57.
- 5. If your Emacs isn't "dumped", the default Lisp libraries are
- "loaded" now.
+ Anonymous FTP:
+ /sics.se:archive/emacs-gayle.tar.Z (patches for 18.55) +
+ /ftp.lysator.liu.se:pub/emacs/gayle-18.57.diff.tar.Z (patches) +
+ /ftp.lysator.liu.se:pub/emacs/emacs-18.57-gayle.tar.Z (patched Emacs) +
+
+ I am not sure if Epoch can display 8-bit characters as is. Lucid Emacs
+ has the ctl-arrow patch installed. Nemacs displays 8-bit characters, and
+ it may be useful for displaying the 8-bit ISO-8859 alphabet, but I don't
+ know for sure (see question 149).
+
+148: How do I input 8-bit characters?
+
+ Minor modes for ISO Latin-1 that allow one to easily input this character
+ set have been written by several people. Such modes have been written by
+ Matthieu Herrb <matthieu@laas.fr> (laas.laas.fr:pub/emacs/iso-latin-1.el),
+ Johan Vromans <jv@mh.nl> {FTP site??}, and Marc Shapiro
+ <shapiro@sor.inria.fr> {FTP site??}.
+
+ These approaches differ from the one taken by Anders Edenbrandt in that
+ his method uses direct 8-bit input, while these methods use a compose
+ sequence for 8-bit characters. {I have heard conflicting reports on
+ whether this results in losing the Meta key. Perhaps this depends on
+ whether Emacs is running under X. Can someone resolve this?}
+
+ Karl Heuer <karl@haddock.ima.isc.com> is said to have a patch to allow
+ 8-bit input. Georg-Wilhelm Koltermann <gwk@crmunich0.cray.com> also has a
+ patch for either 18.57 or 18.58 that allows 8-bit input.
+
+ Epoch comes with a patch that allows it to input 8-bit characters, but it
+ is not enabled by default. {Is this right?}
+
+ Jamie Zawinski says: +
+ +
+ Lucid GNU Emacs allows the input of any ISO-8859/1 keysyms that your +
+ keyboard generates (see xmodmap), and contains a package that implements +
+ a DEC/OpenWindows-like "Compose" key for systems which don't have one. +
+
+149: Where can I get an Emacs that can handle kanji characters?
+
+ Nemacs 3.3.2 (Nihongo GNU Emacs) is a modified version of GNU Emacs 18.55
+ that handles kanji characters. It is available via anonymous FTP: !
+ !
+ /crl.nmsu.edu:pub/misc/nemacs-3.3.2.tar.Z !
+ /uhccux.uhcc.hawaii.edu:editors/Nemacs-3.3.2/ !
+ /miki.cs.titech.ac.jp:JAPAN/nemacs/nemacs-3.3.2.tar.Z !
+
+ You might also need files for "wnn", a kanji input method
+ (wnn-4.0.3{-README,.tar.Z} {on which machine?}). You need a terminal (or
+ terminal emulator) that can display text encoded in JIS, Shift-JIS, or EUC
+ (Extended Unix Code), or the ability to run Nemacs as a direct X Window
+ client.
+
+150: Where can I get an Emacs that can handle Chinese?
+
+ `cemacs' by Stephen G. Simpson <simpson@math.psu.edu> is a patch to Emacs
+ 18.57 (the ctl-arrow patch) and some Emacs Lisp code that combined with
+ Cxterm allows using Chinese characters. It is available via anonymous
+ FTP: !
+ !
+ /crl.nmsu.edu:pub/chinese/cemacs.tar.Z !
+ /cs.purdue.edu:pub/ygz/cemacs.tar.Z !
+
+ Cxterm is available from the same place: !
+ !
+ /cs.purdue.edu:pub/ygz/cxterm-11.5.1.tar.Z !
+
+151: Where is an Emacs that can handle Semitic (right-to-left) alphabets?
+
+ Joel M. Hoffman <joel@wam.umd.edu> writes:
+
+ A couple of years ago a wrote a hebrew.el file that allows right-to-left
+ editing of Hebrew. I relied on the hardware to display the Hebrew
+ letters, given the right codes, but not for any right-to-left support;
+ the hardware also doesn't have to send any specific char. codes. Emacs
+ keeps track of when the user is typing Hebrew vs. English. (The VT-*
+ terminals in Israel contain built-in support for Hebrew.)
+
+ To get it to work I had to modify only a few lines of GNU Emacs's source
+ code --- just enough to make it 8-bit clean.
+
+ [and in a separate message:]
+
+ It doesn't produce time-order ["sefer" format] (I wouldn't recommend
+ trying that with emacs, because converting time-order to screen-order
+ with arbitrarily long lines is a bit tricky), but I also concocted a
+ quick filter to convert screen-order into time-order. I'll be happy to
+ send you the requisite files if you want them. If you're using it for
+ anything large, however, you'll want something that works better.
+
+ Joel Hoffman has also written a "bi-directional bi-lingual Emacs-like"
+ editor for MS-DOS named Ibelbe (Itty Bitty Emacs-Like Bidirectional
+ Editor). Ibelbe is written in Turbo Pascal and comes with source code.
+ Here is the description:
+
+ Ibelbe looks like emacs (it even has a minibuffer and filename
+ completion), and fully supports both right-to-left and left-to-right
+ editing. Other than an EGA monitor or better, no special hardware is
+ required. You will need an EGA Hebrew font to use Ibelbe with Hebrew.
- 6. Emacs enters a "recursive edit". The first time Emacs does a
- recursive edit, steps 7 through 15 are followed, and then Emacs
- enters its normal editing mode.
+ Anonymous FTP:
+ /israel.nysernet.org:israel/msdos/ibelbe.zip !
+ /israel.nysernet.org:israel/msdos/hebfont.zip !
- 7. If the environment variable PWD exists, the value of
- default-directory in the *scratch* buffer is set to the value of
- PWD. This often causes problems and confusion when the value of PWD
- doesn't actually contain the pathname of the current directory.
+ Joseph Friedman <yossi@deshaw.com, yossi@Neon.Stanford.EDU> has written
+ patches for Emacs 18.55 and 18.58 that provide Semitic language support
+ under X Windows.
- 8. Now the "-no-init-file" (synonym: "-q") and "-user" (synonym: "-u")
- command line switches are handled. They must follow the switches
- mentioned in step 1, and must precede any other command line
- arguments. Actually, both of these options can be specified;
- whichever is last on the command line wins.
+ Warren Burstein <warren@itex.jct.ac.il> says he has mapped 7-bit keys by
+ modifying self-insert-command "for Hebrew input on 7-bit keyboards".
- 9. The user's ".emacs" file is loaded now, if the -no-init-file option
- was not specified. If the -user option was specified, that user's
- .emacs file is loaded instead. A user's .emacs file is a file named
- ".emacs" in the user's "home" directory. If no such file exists,
- this step has no effect.
+ A good suggestion is to query archie for files named with `hebrew'.
- 10. The system wide "default" file is loaded now, if the variable
- inhibit-default-init is nil. The user can set this variable in the
- .emacs file to skip this step.
+
+ GNU Emacs FAQ: Mail and News
+
+This portion of the GNU Emacs FAQ list is cross-posted to `gnu.emacs.gnus'
+because many of the questions herein deal with GNUS. See `gnu.emacs.help' for
+the rest of the FAQ list.
+
+If you are viewing this text in a GNU Emacs Buffer, you can type "M-2 C-x $" to
+get an overview of just the questions. Then, when you want to look at the text
+of the answers, just type "C-x $".
+
+To search for a question numbered XXX, type "M-C-s ^XXX:", followed by a C-r if
+that doesn't work, then type ESC to end the search.
+
+A `+' in the 78th column means something was inserted on the line. A `-' means
+something was deleted and a `!' means some combination of insertions and
+deletions occurred.
+
+Full instructions for getting the latest FAQ are in question 22. Also see the
+`Introduction to news.answers' posting in the `news.answers' newsgroup, or send
+e-mail to `mail-server@rtfm.mit.edu' with `help' on a body line, or use FTP,
+WAIS, or Prospero to rtfm.mit.edu.
+
+
+
+Mail and News
+
+152: How do I change the included text prefix in mail/news followups?
- 11. If the *scratch* buffer still exists now, the value of
- initial-major-mode is called as a function in this buffer.
- Normally, this puts this buffer in Lisp Interaction mode.
+ Many people want Emacs to prefix included text with something like ` > '
+ instead of with three spaces. One way is to change the code of the
+ function `mail-yank-original' in lisp/sendmail.el that prefixes with
+ spaces. A more flexible solution is to use Supercite, which provides wide
+ configurability in how you format included text in replies. See question
+ 107. Both of these solutions work for RMAIL and GNUS.
- 12. Now the terminal/window-system setup file is loaded. The name of
- this file is determined as follows:
+ A related problem is how to prevent Emacs from including various headers
+ of the replied-to message. For this, you should set the value of
+ mail-yank-ignored-headers, which takes a regexp value.
- 1. It starts with the value of term-file-prefix. Normally this is
- "term/", but the user can set it to another value. If this
- variable is nil, this entire step is skipped.
+153: How do I save a copy of outgoing mail?
- 2. For a window system, the prefix is followed by the name of the
- value of the variable window-system, followed by "-win". For X
- Windows, this means the name is "term/x-win".
+ Two methods:
- 3. For a terminal, the prefix is followed by the value of the
- environment variable TERM, for example, "term/vt200". If Emacs
- cannot find such a file to load, it retries by stripping off
- suffixes that begin with a hyphen. For example, if TERM is
- "vt200-40", first Emacs will try "term/vt200-40", and if that
- fails it will try "term/vt200".
+ 1. (setq mail-self-blind t) will result in a `BCC:' header line with your
+ address being added to mail composition buffers. This will cause the
+ mail system to send a copy of the mail back to you.
- 13. The rest of the command line arguments are handled at this point, in
- the order they appear:
+ 2. (setq mail-archive-file-name (expand-file-name "~/outgoing")) will
+ result in an `FCC:' header line with the pathname of ~/outgoing being
+ added to mail composition buffers. When you send the mail, Emacs will
+ save a copy of the mail in the file ~/outgoing and then strip off the
+ `FCC:' line before actually sending.
- "-funcall" (synonyms: "-f", "-e"). The next argument is treated as
- the name of a function, which is called with no arguments.
+ WARNING: There is a bug in Emacs 18.58 that prevents mail readers such
+ as RMAIL from reading the saved mail messages individually. See
+ question 155.
- "-load" (synonym: "-l"). The next argument is treated as the name
- of a file to load. NOTE: the value of the variable load-path
- will be restored after this file is done loading. Thus, trying
- to change load-path in such a file will fail!!
+ WARNING: If you are visiting the file ~/outgoing at the time you send
+ the mail, this can cause a variety of horrible problems. Jamie +
+ Zawinski has written a solution for this. +
- "-kill". When this argument is handled, Emacs kills itself.
+ It does not work to put `set record filename' in the .mailrc file.
- "+DDD", where D is a digit. DDD is used as a line number to go to.
- When the next ordinary file argument on the command line is
- handled, Emacs positions point in that file on line DDD.
+154: Why doesn't Emacs expand my aliases when sending mail?
- An ordinary filename. Emacs edits this file using the function
- find-file. If the filename is not an "absolute" filename, it is
- expanded relative to the value that default-directory in the
- *scratch* buffer had at the beginning of step 11. The buffer
- visiting this file becomes the current buffer.
+ * You must separate multiple addresses in the headers of the mail buffer
+ with commas. This is because Emacs supports RFC822 standard addresses
+ like this one:
- "-insert" (synonym: "-i"). The next argument is treated as the name
- of a file. This file is inserted in the current buffer.
- Initially, this is the *scratch* buffer. Otherwise it is the
- buffer visiting the file most recently specified on the command
- line. WARNING: the synonym "-i" doesn't work under X11.
+ To: Willy Smith <wks@xpnsv.lwyrs.com>
- Other command line switches may have been created by modifying the
- value of the variable command-switch-alist. If X Windows is being
- used, all X-specific switches mentioned above in steps 3 and 4 will
- be processed. Under X11, they will have already been handled, and
- will be ignored now. Under X10, they are being handled for the
- first time.
+ However, you do not need to separate addresses with commas in your
+ .mailrc file.
- 14. The values of the variables term-setup-hook and window-setup-hook
- are called as functions with no arguments, in the order listed.
+ WARNING: Emacs breaks up aliases in the .mailrc file into multiple
+ addresses both on commas and on whitespace, regardless of any use of
+ quotes. This is probably a bug. You can get around this by directly
+ setting the value of mail-aliases.
- 15. If the user did not specify any of the command line options handled
- in step 13, and the variable inhibit-startup-message is still nil,
- the familiar Emacs startup message is displayed.
+ * Emacs normally only reads the `.mailrc' file once per session, when you
+ start to compose your first mail message. If you edit .mailrc, you can
+ type "M-ESC (build-mail-aliases) RET" to make Emacs reread .mailrc.
+ (You have to include the parentheses where they are shown!)
-73: What are the valid X resource settings (ie., stuff in .Xdefaults file)?
+ * Emacs does not interpret vendor-specific additions to the format of the
+ .mailrc file such as the `source' command. It also ignores any `set'
+ commands. The only commands it looks at are `alias' and `group'
+ commands.
- See question 72.
+155: Why does RMAIL think all my saved messages are one big message?
- WARNING: Don't pay any attention to the documentation in etc/XDOC or
- etc/emacs.1. It's way out of date. {Would someone like to rewrite it?
- RMS asked me and I haven't had time yet.}
+ There is a bug for FCC-ed messages in Emacs 18.58 where it adds a timezone
+ on the "From " line after the year instead of before the year. (Before it
+ didn't add the timezone at all.) This is incompatible with the standard
+ format for the "From " line, and RMAIL in particular can no longer
+ distinguish between the messages. Karl Berry <karl@cs.umb.edu>, Felix Lee
+ <flee@cs.psu.edu>, Nick Gianniotis <nico@japan.sbi.com> and many
+ others have all posted patches for this. Karl's is the simplest and just
+ stops Emacs from adding the timezone:
-74: How do I turn down the bell volume in Emacs running under X Windows?
+ >*** ./ORIG/sendmail.el Tue Jan 28 16:22:56 1992
+ >--- ./sendmail.el Thu May 14 18:23:48 1992
+ >***************
+ >*** 285,287 ****
+ > (insert "\nFrom " (user-login-name) " "
+ >! (current-time-string) " " timezone "\n")
+ > (insert-buffer-substring rmailbuf)
+ >--- 285,287 ----
+ > (insert "\nFrom " (user-login-name) " "
+ >! (current-time-string) "\n")
+ > (insert-buffer-substring rmailbuf)
- Under Epoch you can do:
+156: How can I sort the messages in my RMAIL folder?
- (setq epoch::bell-volume 20)
+ Use rmailsort.el by Masanobu Umeda.
- Under normal GNU Emacs you must modify the XTfeep function in
- src/x11term.c, and change the number 50 to some other number:
+157: Why does RMAIL need to write to /usr/spool/mail?
- XTfeep ()
- {
- BLOCK_INPUT_DECLARE ();
- #ifdef XDEBUG
- fprintf (stderr, "XTfeep\n");
- #endif
- BLOCK_INPUT ();
- XBell (XXdisplay,50); /* change this 50 */
- UNBLOCK_INPUT ();
- }
+ This is the behavior of the `movemail' program which RMAIL uses. This
+ indicates that movemail is configured to use lock files.
-75: How do I make Emacs send 8-bit characters to my terminal?
+ RMS writes:
- Johan Widen <jw@sics.se> writes:
+ Certain systems require lock files to interlock access to mail files.
+ On these systems, movemail must write lock files, or you risk losing
+ mail. You simply must arrange to let movemail write them.
- A patch for emacs-18.55 is available by ftp and mail-server from
- sics.se.
+ Other systems use the flock system call to interlock access. On these
+ systems, you should configure movemail to use flock.
- Anonymous FTP:
- site: sics.se [192.16.123.90]
- file: archive/emacs-18.55-8bit-diff
+158: How do I recover my mail files after RMAIL munges their format?
- E-mail:
- To: mail-server@sics.se
- body: send emacs-18.55-8bit-diff
+ Users who just want to try RMAIL out to see how it works end up trapped
+ using it because saved mail in their `mbox' file has been converted into
+ an incompatible format (BABYL) that only RMAIL understands. RMAIL
+ provides no obvious way to reverse this transformation. Kyle Jones has +
+ aptly named this "the great Emacs Mail Eating Monster". To convert a mail +
+ file back to standard Unix format, there are several methods:
-
-
-Emacs Lisp programming:
-
-76: What dialect of Lisp is Emacs Lisp?
+ * Use the rmail-output ("C-o") command within RMAIL on each message in the
+ file. First use M-x rmail or M-x rmail-input to visit the RMAIL file in
+ Rmail mode. Type "1 j" to go to the first message. Use the C-o command
+ to output the message to a Unix format file. Type "n" to go to the next
+ message. Repeat.
- It's the dialect of Lisp called Emacs Lisp. (No joke!) People also
- call it elisp or e-lisp. (NOTE: The term "Elisp" is trademarked by
- someone else.)
+ * If the file contains hundreds of messages, you may not want to repeat
+ this for all of them. Instead of the above, after getting to the first
+ message type this (where "mbox" is the file you want to put the messages
+ in):
-77: How close is Emacs Lisp to Common Lisp?
+ C-x ( C-o mbox RET M-s ^From: RET M-0 C-x )
- Pretty far. GNU Emacs Lisp is case-sensitive, uses dynamic scoping,
- doesn't have packages, doesn't have multiple return values, doesn't have
- reader macros, etc. For people used to Common Lisp, some of the
- functions in Common Lisp that are not in Emacs Lisp by default are
- provided in the file lisp/cl.el. There is a Texinfo manual describing
- these functions in man/cl.texinfo.
+ (The rmail-search command ("M-s") is used instead of just "n" because it
+ is the only command which will cause an error when it reaches the last
+ message in the file, which is necessary to terminate the keyboard macro.
+ This will fail if there are messages in the file that don't have a
+ `From:' header. This assumes rmail-delete-after-output is nil.)
-78: How do I execute a piece of Emacs Lisp code?
+ It is wise to save a copy of the RMAIL file first, in case you make a
+ mistake.
- There are a number of ways to execute (called "evaluate") an Emacs Lisp
- "form":
+ * There are software packages available for converting files or even
+ entire directories of BABYL files to standard Unix format. These are
+ helpful in this situation, but are intended mainly for people who have
+ used RMAIL for a long time and are converting to some other mail reader.
+ Lookup `rmail', `vm', and `babyl' in the Emacs Lisp Archive (see
+ question 89).
- * If you want it evaluated every time you run Emacs, put it in a file
- named ".emacs" in your home directory.
+ You may wish to disable RMAIL to avoid accidentally destroying your mbox
+ file (I have this in my .emacs):
- * You can type the form in the "*scratch*" buffer, and then type C-j
- after it. The result of evaluating the form will be inserted in the
- buffer.
+ (put 'rmail 'disabled t) ; avoid mbox destruction
- * In in Emacs-Lisp mode, typing M-C-x evaluates a top-level form before
- or around point.
+159: How do I make Emacs automatically start my mail/news reader?
- * Typing "C-x C-e" in any buffer evaluates the Lisp form immediately
- before point and prints its value in the echo area.
+ Example:
- * Typing M-ESC or M-x eval-expression allows you to type a Lisp form in
- the minibuffer which will be evaluated.
+ emacs -f gnus
- * You can use M-x load-file to have Emacs evaluate all the Lisp forms in
- a file. (To do this from Lisp use the function "load" instead.)
+ Also:
-79: How do I make a set of operations fully local to a region?
+ alias gnus 'emacs -f gnus'
- Use narrow-to-region inside of save-restriction.
+ It is probably unwise to automatically start your mail or news reader from
+ your .emacs file. This would cause problems if you needed to run two
+ copies of Emacs at one time. Also, this would make it difficult for you
+ to start Emacs quickly when you needed to.
-80: How can I highlight a region?
+160: How do I read news under Emacs?
- There are ways to get highlighting in GNU Emacs 18.55, but they all
- require patching the C code of Emacs and rebuilding. They are also slow
- and the highlighting disappears if you scroll or redraw the screen. One
- patch is by Kenichi Handa <handa@etl.go.jp>.
+ There are at least three news reading packages that operate inside Emacs.
+ `rnews' comes with Emacs. GNUS and Gnews come separately. rnews will
+ be replaced by GNUS in Emacs 19.
- You can hightlight regions in a variety of ways in Epoch. GNU Emacs 19
- will have everything you need, but won't be out soon.
+ rnews works only with a local news spool directory. Both GNUS and Gnews
+ handle reading news remotely via NNTP in addition to reading from a local
+ news spool. GNUS supports reading mail stored in MH folders or articles
+ saved by GNUS.
-81: How do I change Emacs's idea of the tab character's length?
+ Gnews is styled after `rn' and seems to work like RMAIL. GNUS feels more
+ like VM. People have complained that GNUS uses a lot of CPU time (it
+ does). Some people have complained that Gnews is slower than GNUS.
- Example: (setq default-tab-width 10).
+ For more information about GNUS, see question 108.
-82: What is the difference between (interactive "P") and (interactive "p")?
+ Gnews was written by Matthew P. Wiener <weemba@libra.wistar.upenn.edu>.
+ The latest version seems to be 2.0, posted October 3, 1988. Matthew
+ posted some fixes on October 26, 1988. Gnews does not appear to have been
+ supported after this date. In particular, it has been reported that Gnews
+ does not work with Emacs 18.57. There is a newsgroup for Gnews called
+ gnu.emacs.gnews.
- The value that is a result of "P" can be a list, a symbol, or an
- integer; the value that is a result of "p" is always an integer:
+161: Why does `rnews' say "No News is good news" when there is news?
- Prefix keys typed result of: "P" "p"
- nothing nil 1
- "M-1" 1 1
- "C-u 1" 1 1
- "M--" '- -1
- "C-u -" '- -1
- "C-u" (4) 4
- "C-u C-u" (16) 16
+ rnews doesn't speak NNTP. You may need to use GNUS or Gnews.
-
-
-Carrying Out Common Tasks:
-
-83: How do I insert ">"'s in the beginning of every line in a buffer?
+162: Why doesn't GNUS work anymore via NNTP?
- Type "M-x replace-regexp RET ^ RET > RET". ("replace-regexp" can be
- shortened to "repl TAB r".)
+ There is a bug in NNTP version 1.5.10, such that when multiple requests
+ are sent to the NNTP server, the server only handles the first one before
+ blocking waiting for more input which never comes. NNTP version 1.5.11
+ claims to fix this.
- To do this only in the region, type "C-x n M-x replace-regexp RET ^ RET
- > RET C-x w". (You're going to remember that, right?)
+ You can work around the bug inside Emacs like this:
-84: How do I insert "_^H" characters before each character in a
- paragraph to get an underlined paragraph?
+ (setq nntp-maximum-request 1)
- M-x underline-region.
+ I also have a patch for NNTP 1.5.10 by Mike Pelletier
+ <stealth@engin.umich.edu> that is based on the timeout code that was in
+ 1.5.9. However, please try to upgrade to 1.5.11 first.
-85: How do I repeat a command as many times as possible?
+ You can find out what version of NNTP your news server is running by
+ telnetting to the NNTP port (usually 119) on the news server machine (ie.,
+ `telnet server-machine 119'). The server should give its version number
+ in the welcome message. Type `quit' to get out.
- Make a keyboard macro that invokes the command and then type "M-0 C-x
- e". WARNING: any messages your command prints in the echo area will be
- suppressed.
+163: How do I view text with embedded underlining (eg., ClariNews)?
-86: How do I search for an unprintable (8-bit) character that appears
- in a buffer as \237?
+ Underlining appears like this:
- C-s C-q 2 3 7
+ _^Hu_^Hn_^Hd_^He_^Hr_^Hl_^Hi_^Hn_^Hi_^Hn_^Hg
- (This assumes the value of search-quote-char is 17 (C-q).)
+ You can destructively remove underlining with M-x ununderline-region.
-87: How do I tell Emacs to automatically indent a new line to the
- indentation of the previous line?
+ For ClariNews articles, clari-clean.el by David N. Blank-Edelman
+ <dnb@meshugge.media.mit.edu> will remove both underlining and overstriking
+ automatically.
- M-x indented-text-mode. (This is a major mode.)
+164: When I try to post a long article in GNUS (about 10K or longer), I get
+ the error, "Writing to process: no more processes, nntpd"
- If you have auto-fill mode on (minor mode), you can tell Emacs to prefix
- every line with a certain character sequence, the "fill prefix". Type
- the prefix at the beginning of a line, position point after it, and then
- type "C-x ." (set-fill-prefix) to set the fill prefix. Thereafter,
- auto-filling will automatically put the fill prefix at the beginning of
- new lines, and M-q (fill-paragraph) will maintain any fill prefix when
- refilling the paragraph.
+ Upgrade to Emacs 18.58.
-88: How do I make Emacs "typeover" or "overwrite" when I type instead of
- always inserting?
+165: How do I save all the items of a multi-part posting in GNUS?
- M-x overwrite-mode (minor mode).
+ Use gnus-mark.el by Jamie Zawinski <jwz@lucid.com>.
- WARNING: delete-backward-char (usually the delete key) doesn't work
- properly in overwrite mode. It deletes the character to the left,
- rather than replacing it with a space.
+166: Why does GNUS put the subjects in replies beyond the 80th column?
-89: How do I show which parenthesis matches the one I'm looking at?
+ This is a feature. If you set gnus-thread-hide-subject to non-nil, GNUS
+ will only display the subject of the first posting in a thread, even if
+ some of the replies use different subjects. It hides the subjects by
+ putting them past the edge of the window and setting truncate lines to t.
- If you're looking at a right parenthesis (or brace or bracket) you can
- delete it and reinsert it.
+ If your screen looks messed up, then for some reason truncate-lines in
+ your `*Subject*' buffer has been set to nil. It should be set to t.
- M-C-f (forward-sexp) and M-C-b (backward-sexp) will skip over balanced
- parentheses, so you can see which parentheses match. (You can train it
- to skip over balanced brackets and braces at the same time by modifying
- the syntax table.)
+ (I have an enhancement to GNUS 3.13 that will make it only hide the subject
+ of a posting when it is unchanged from the followed-up-to posting. Thus,
+ you can use the subject hiding feature and still know when someone changes
+ the subject. (I have forgotten who originally gave me the idea for this.))
- Here is some Emacs Lisp that will make the % key show the matching
- parenthese, like in vi. In addition, if the cursor isn't over a
- parenthese, it simply inserts a % like normal.
+167: Why is GNUS so slow to start up?
- (By an unknown contributor.)
+ GNUS does several things that take quadratic time of the number of
+ newsgroups that are listed in .newsrc. The quick fix for this is to
+ remove all the newsgroups in which you have no interest from your .newrc
+ file by using GNUS's C-k command in the `*Newsgroup*' buffer after
+ displaying all newsgroups with the L command. If you were to directly
+ edit your .newsrc to remove the newsgroups, GNUS would add them back.
- (global-set-key "%" 'match-paren)
+ GNUS uses a quadratic algorithm to check for duplicates when the .newsrc
+ file is newer than the .newsrc.el file (ie., you edited your .newsrc).
+ GNUS uses a quadratic algorithm to check for new newsgroups every time it
+ connects to the news server. {There may be other quadratic algorithms
+ that I am not aware of.}
- (defun match-paren (arg)
- "Go to the matching parenthesis if on parenthesis otherwise insert %."
- (interactive "p")
- (cond ((looking-at "[([{]") (forward-sexp 1) (backward-char))
- ((looking-at "[])}]") (forward-char) (backward-sexp 1))
- (t (self-insert-command (or arg 1)))))
+ You can speed up GNUS by using the C-k command in the *Newsgroup* buffer
+ to remove newsgroups from your .newsrc file.
-90: How do I make Emacs behave like this: when I go up or down, the cursor
- should stay in the same column even if the line is too short?
+ Of course, GNUS will run faster if you make sure it is byte-compiled.
- M-x picture-mode. (This is a minor mode, in theory anyway ...)
+ Felix Lee wrote some enhancements called `gnus-speedups.el' that fix some +
+ of the problems. See the Emacs Lisp Archive. +
-91: How do I read news under Emacs?
+168: How do I catch up all newsgroups in GNUS?
- There are at least three news reading packages that operate inside
- Emacs. "rnews" comes with Emacs. "GNUS" and "Gnews" come separately.
+ In the `*Newsgroup*' buffer, type the following magical incantation:
- {I've never used rnews; could someone write a description? BTW, rnews
- will be replaced with GNUS in Emacs 19.}
+ M-< C-x ( C-@ c y C-u C-@ C-e C-f C-f M-0 C-x )
- Both GNUS and Gnews handle reading news over NNTP. I think both can
- also read from a local news spool. GNUS also supports reading mail
- stored in MH folders or articles saved by GNUS.
+ Leave off the "M-<" if you only want to catch up from point to the end of
+ the `*Newsgroup' buffer.
- GNUS is written (mostly) by Masanobu Umeda. His (?) latest e-mail
- address was umerin@tc.nagasaki.go.jp, but I don't think he has an e-mail
- address right now. The latest version is GNUS 3.13. There is a
- newsgroup for discussion of GNUS called gnu.emacs.gnus. This newsgroup
- is gatewayed with the mailing list info-gnus-english to subscribe send
- mail to info-gnus-english-request@cis.ohio-state.edu. There is also a
- mailing list called info-gnus, which includes discussion in Japanese.
+169: Why can't I kill in GNUS on the Newsgroups/Keywords/Control line?
- Gnews was written by Matthew Wiener <e-mail address?>. {Could someone
- tell me the # of the latest version, and how long it has been since
- anyone has heard from Matthew?}. There is a newsgroup for Gnews called
- gnu.emacs.gnews.
+ GNUS 3.14.1 will complain that the `Newsgroups:', `Keywords:', and
+ `Control:' headers are `Unknown header field's.
-92: In C mode, can I show just the lines that will be left after #ifdef
- commands are handled by the compiler?
+ For the `Newsgroups:' header, there is an easy workaround: kill on the
+ `Xref' header instead, which will be present on any cross-posted article.
- M-x hide-ifdef-mode. (This is a minor mode.)
+ If you really want to kill on one of these headers, you can do it like
+ this:
- You may have to (load "hideif") first. If you want to do this
- regularly, put this in your .emacs file:
+ (gnus-kill nil "^Newsgroups: .*\\(bad\\.group\\|worse\\.group\\)")
- (autoload 'hide-ifdef-mode "hideif" nil t)
+ Various people (eg., Greg Holley <holley@acuson.com>) have posted
+ solutions to allow more efficient killing on these headers than the
+ preceding solution. Masanobu Umeda plans to fix this problem.
-93: Is there an equivalent to the "." (dot) command of vi?
+170: How do I get rid of flashing messages in GNUS for slow connections?
- ("." is the redo command in vi. It redoes the last insertion/deletion.)
+ GNUS outputs "NNTP: Reading..." message and then clears them, over and
+ over. In version 3.14.1 there is a variable named nntp-debug-read that
+ can help. Johan Vromans <jv@mh.nl> wrote a fix. Others have also written
+ fixes.
- No, not really.
+171: Why is catch up slow in Gnews/GNUS?
- You can type "C-x ESC" (repeat-complex-command) to reinvoke commands
- that used the minibuffer to get arguments. In repeat-complex-command
- you can type M-p and M-n to scan through all the different complex
- commands you've typed.
+ Because GNUS is marking crosspostings read. {I think it should do this at
+ the time the article is read to spread out the load. Maybe someone will
+ write the code to do this.}
- To repeat something on each line I recommend using keyboard macros.
+172: Why does GNUS hang for a long time when posting?
-94: How do I use emacstool under SunView?
+ David Lawrence <tale@uunet.uu.net> explains: !
+ !
+ The problem is almost always interaction between NNTP and C News. NNTP !
+ POST asks C News's inews to not background itself but rather hang around !
+ and give its exit status so it knows whether the post was successful. !
+ (That wait will on some systems not return the exit status of the !
+ waited for job is a different sort of problem.) It ends up taking a !
+ long time because inews is calling relaynews, which often waits for !
+ another relaynews to free the lock on the news system so it can file the !
+ article. !
+ !
+ My preferred solution is to change inews to not call relaynews, but !
+ rather use newsspool. This loses some error-catching functionality, but !
+ is for the most part safe as inews will detect a lot of the errors on !
+ its own. The C News folks have sped up inews, too, so speed should look !
+ better to most folks as that update propagates around. !
- The file etc/SUN-SUPPORT includes the document "Using Emacstool with GNU
- Emacs". Also read the man page for emacstool (etc/emacstool.1).
+173: Why don't my news postings in GNUS get past the local machine?
-95: How do I get Emacs to display the current line number on the mode line?
+ Three possible reasons: local distribution, C News date problem (see
+ question 174, and the path problem. This piece of code may fix the path !
+ problem for you: !
+ !
+ (setq gnus-use-generic-path t) !
- There is no "correct" way to constantly display the current line number
- on the mode line in Emacs 18. Emacs is not a line-oriented editor, and
- really has no idea what "lines" of the buffer are displayed in the
- window. It would require a lot of work at the C code level to make
- Emacs keep track of this.
+174: Why is the GNUS-generated `Date:' header invalid?
- Emacs 19 will probably be able to do this, but probably not with great
- efficiency.
+ GNUS generates `Date:' headers without time zones. C-News's `inews'
+ doesn't replace it with a valid header, but will generate it if not
+ already there. If it is invalid, the article will not be forwarded
+ properly. Quick fix:
- To find out what line of the buffer you are on right now, do "M-x
- what-line". Typing "C-x l" will also tell you what line you are on,
- provided the buffer isn't separated into "pages" with C-l characters.
- In that case, it will only tell you what line of the current "page" you
- are on. WARNING: "C-x l" gives the wrong value when point is at the
- beginning of a line.
+ (defun gnus-inews-date () nil)
- People have written various kludges to display the current line number
- on the mode line. Look in the Lisp Code Directory. (See question 13.)
+ I think this is fixed in GNUS 3.14.1 if you set gnus-news-system {?} to +
+ Cnews. +
-96: How do I tell Emacs to iconify itself?
+175: Why doesn't GNUS generate the `Lines:' header?
- You need to modify C source and recompile. Either that or get Epoch
- instead. For the interested I have a patch to allow Emacs to iconify
- itself.
+ GNUS was written for B news, which would generate the `Lines:' header. C
+ news doesn't. There is a comment in C news's `inews' that you can
+ uncomment to enable this functionality. Or you can have GNUS generate the
+ header, for example:
-97: How do I use regexps (regular expressions) in Emacs?
+ ;; idea by jbryans@beach.csulb.edu (Jack Bryans)
+ (defun add-lines-header ()
+ ;; Count the number of lines in the current posting and insert the
+ ;; header line Lines into the message.
+ (save-excursion
+ (goto-char (point-min))
+ (if (search-forward "\n\n") ;; ***** I suspect this is wrong *****
+ (let ((lines (count-lines (point) (point-max))))
+ (forward-line -1)
+ (insert-string "Lines: " lines "\n")))))
- This is documented in the Emacs manual. To read the manual section
- online, type "C-h i m emacs RET m regexps RET".
+ Mike Williams <mike-w@cs.aukuni.ac.nz> has written something similar.
+
+ Ronald Florence <ron@mlfarm.com> has a patch for GNUS that makes it
+ calculate the `Lines:' header for incoming articles when necessary that
+ works for sites with local news spools.
+
+ David Lawrence <tale@uunet.uu.net> says that GNUS 3.14.1 generates Lines +
+ if gnus-news-system is Cnews. +
+
+176: Why do I get "Cannot open load file" "nntp" when compiling GNUS?
+
+ Specifically, the error message is this:
+
+ Error occurred processing gnus.el: File error (("Cannot open load file" "nntp"))
+
+ This means that nntp.el is not in Emacs's load-path, which is easy to
+ happen when compiling using the Makefile.
+
+ Easiest solution: set EMACSLOADPATH in Makefile (idea from Glenn Gribble
+ <glenn@netcom.com>):
+
+ EMACSLOADPATH=/usr/local/emacs/lisp:.
+ ELC= env EMACSLOADPATH=$(EMACSLOADPATH) emacs -batch -f batch-byte-compile
+
+ Another solution, in hack.el put this:
+
+ (defun gross-hack () (setq load-path (cons "/directory" load-path)))
+
+ Then in Makefile:
+
+ ELC= emacs -batch -l hack.el -f gross-hack -f batch-byte-compile
+
+177: How do I kill all articles in GNUS but those matching a pattern?
+
+ Example:
+
+ ;; kill everything
+ (gnus-kill "subject" "" nil nil)
+ ;; then restore stuff by our favorite poster
+ (gnus-kill "from" "good-guy"
+ (function
+ (lambda ()
+ (if (eq ?X (char-after (save-excursion
+ (beginning-of-line 1)
+ (point))))
+ (gnus-Subject-clear-mark-forward 1))))
+ t)
- WARNING: Unlike in Unix grep, sed, etc., a complement character set
- ([^...]) can match a Newline, unless Newline is mentioned as one of the
- characters not to match.
diff --git a/etc/FTP b/etc/FTP
new file mode 100644
index 00000000000..b5d2f1d785f
--- /dev/null
+++ b/etc/FTP
@@ -0,0 +1,266 @@
+ -*- text -*-
+How to get GNU Software by Internet FTP or by UUCP. Last updated 20 Jan 92.
+
+* No Warranties
+
+We distribute software in the hope that it will be useful, but
+without any warranty. No author or distributor of this software
+accepts responsibility to anyone for the consequences of using it or
+for whether it serves any particular purpose or works at all, unless
+he says so in writing.
+
+* Updates
+
+If you find this file in the Emacs distribution, there is a chance
+it is out of date. If you plan to FTP files from prep.ai.mit.edu,
+you might as well start by FTPing the current version of this file,
+which is `/pub/gnu/GNUinfo/FTP'.
+
+* FTPing GNU Software
+
+** GNU Emacs and How To FTP It
+
+If you are on the Internet (see also "** Alternative Internet FTP
+Sources" below), you can at present copy the latest distribution
+version of GNU Emacs from the file /pub/gnu/emacs-M.N.tar on host
+prep.ai.mit.edu (or the file /pub/gnu/emacs-M.N.tar.Z which has been
+run through compress after tar). M and N standard for version
+numbers; look at a listing of the directory through ftp to see what
+version is available. These files are about 11 and 4 megabytes long,
+respectively. After you unpack the distribution, be sure to look at
+the files README and INSTALL.
+
+Because of difficulties in transferring large files, sometimes a split
+version of the tar file is created. This is a directory named
+/pub/gnu/emacs-M.N.tar-split or perhaps
+/pub/gnu/emacs-M.N.tar.Z-split, containing files of 100000 characters
+each. There is generally no trouble in ftping files of this size.
+They can be combined with cat to make a tar file or compressed tar
+file.
+
+ALWAYS USE BINARY/IMAGE MODE TO TRANSFER THESE FILES!
+Text mode does not work for tar files or compressed files.
+
+Some ftp'ers have found it necessary for successful file transfer:
+ - to explicitly use prep.ai.mit.edu internet address:
+18.71.0.38 (as of 11 April 89)
+
+Files of differences from previous widely distributed GNU Emacs
+versions to the present version are also available on prep.ai.mit.edu
+under names of the form emacs.diff-OO.OO-NN.NN in directory /pub/gnu.
+These are made with diff -rc2. Sometimes there are compressed
+versions of these difference files as well; their names have .Z
+appended.
+
+The Emacs manual in source form is included in the distribution.
+The dvi file produced by TeX is not included, but a copy may be
+available for ftp under the name /pub/gnu/emacs.dvi.
+
+The Emacs Lisp Reference Manual is in a separate file:
+/pub/gnu/lispref.tar.Z.
+
+** VMS versions of GNU Emacs and How To FTP It.
+You can anonymously ftp a VMS version of GNU emacs from:
+ - ddvax.llnl.gov.
+ - VMSA.OAC.UCI.EDU or VMSD.OAC.UCI.EDU.
+ - RIGEL.EFD.LTH.SE [130.235.48.3].
+ - ctrsci.cc.utah.edu. The 00readme.txt file gives details.
+ - cc.utah.edu [128.110.8.24]. User anonymous, pass guest. It
+has already been compiled and linked so it is ready to run. You will
+need to ftp the reblock.for program to reblock the saveset so that the
+backup utility can restore that saveset. Do a backup/list on the
+ftp'd saveset and catch the header info that backup puts out. It
+contains the correct block size to reblock the file to. Remember to
+ftp it in binary mode.
+
+** A VMS version of G++ and How To FTP It.
+
+mango.rsmas.miami.edu has a VMS version of the G++ compiler. Contact
+angel@flipper.miami.edu (angel li) for details.
+
+** A VMS version of GCC and How To FTP It.
+
+Jonathan Corbet has made the "bootstrap files" for the GNU C compiler
+available for pseudo-anonymous FTP on rdss.ucar.edu. The full gcc
+sources are also available, for anybody who wants to start from scratch.
+
+Jonathan Corbet also requests that you please limit your access to
+outside the hours of 8-6 (mountain time) on weekdays. RDSS is a
+*very* busy machine during the day. Jonathan notes, "I don't think I
+have to tell you what will happen if my users feel they are being
+slowed down by outside people grabbing software."
+
+The procedure is this: FTP to rdss.ucar.edu (128.117.80.1), and log in
+with a username of FTP, password FTP. Cd into the [.gcc] directory,
+and grab either or both of these files:
+ bootstrap.bck The bootstrap files -- not much more than the
+ .exe files. About 1.3 mb.
+ gcc.bck The full-blown gcc source code. About 5mb.
+Both of these files are backup savesets, and should thus be grabbed
+in binary mode.
+
+SPAN people can grab the same files from rdss::du:[ftp.gcc]. If your
+node database does not know about rdss, use 9452 instead.
+
+Jonathan Corbet is with the
+National Center for Atmospheric Research, Field Observing Facility
+Internet: corbet@rdss.ucar.edu
+SPAN: rdss::corbet (rdss = 9452)
+Usenet: ...!ncar!rdss!corbet
+
+** Other GNU Software and How To FTP It.
+
+This software is available on prep.ai.mit.edu under directory
+/pub/gnu. Files containing diff from previous versions are often
+available. Compressed versions of the tar or diff files are often
+available (indicated by a .Z suffix). Much of this software is in
+beta test (probably still buggy), and is being made available for use
+by hackers who like to test software. M.N indicates a version number.
+diff files to convert between versions (like those used for GNU
+Emacs), exist for some of these programs. Some programs have misc
+suport files as well. Have a look on prep.ai.mit.edu to see which
+ones.
+
+GNU Assembler (gas) gas-M.N.tar.Z Released
+GNU Bash bash-M.N.tar.Z BETA TEST
+GNU Bison bison-M.N.tar.Z Released
+GNU C Compiler (gcc) gcc.tar-M.N.Z Late BETA TEST
+GNU C++ Compiler (g++) g++.tar-M.N.Z BETA TEST
+GNU C++ Library libg++-M.N.tar.Z BETA TEST
+GNU cpio cpio-M.N.tar.Z BETA TEST
+GNU Emacs Lisp Reference Manual lispref.tar.Z Released
+GNU AWK (gawk) gawk-M.N.tar.Z Released
+GNU debugger (gdb) gdb-M.N.tar.Z Released
+GNU Make make-M.N.tar.Z Released
+GNU ld, ar, gprof, size, nm and strip
+ binutils.tar.Z Released
+GNU cat chmod cmp cp cut dd dir du head install ln ls
+ mkdir mkfifo mv paste rm rmdir tac tail touch vdir
+ fileutils-M.N.tar.Z BETA TEST
+GNU Diff diff-M.N.tar.Z Released
+GNU e?grep grep-M.N.tar.Z Released
+GNU fgrep fgrep-M.N.tar.Z BETA TEST
+GNU find find-M.N.tar.Z BETA TEST
+GNU finger finger-M.N.tar.Z BETA TEST
+GNU Ghostscript ghostscript-M.N.tar.Z
+ & font ghostscript*tar.Z files BETA TEST
+GNU gdbm gdbm-M.N.tar.Z BETA TEST
+GNU Go gnugo-M.N.tar.Z BETA TEST
+GNU groff groff-M.N.tar.Z BETA TEST
+GNU indent indent-M.N.tar.Z BETA TEST
+GNU malloc malloc.tar.Z BETA TEST
+GNU tar (to unpacl .tar files) tar-M.N.tar.Z
+ and tar-M-N.shar BETA TEST
+GNU m4 m4.tar.Z BETA TEST
+GNU sed sed-M.N.tar.Z BETA TEST
+GNU Smalltalk smalltalk-M.N.tar.Z BETA TEST
+GNU Chess gnuchess-M.N.tar.Z Released
+GNU Buttons & Designs button.M.N.ps Released
+
+and these packages which are not FSF software but work with
+them and are part of GNU:
+
+Concurrent Version System cvs-M.N.tar.Z
+compress (to undo .Z files) compress.shar and compress.tar
+dirent dirent.tar.Z
+ (directory reader for sysV 3.2)
+elvis (a vi clone) elvis.M.N.O.tar.Z
+Flex (a faster lex) flex-M.N.tar.Z
+gnuplot gnuplot-M.N.tar.Z
+The jargon file jargon.text.Z
+ (definitions of terms used by hackers)
+NIH C++ Class Library nihcl-M.N.tar.Z
+Perl perl-M.N.tar.Z
+Revision Control System rcs.tar.Z
+Texi2roff texi2roff.shar.Z
+
+** TeX and How to FTP It
+
+We don't distribute TeX now, but it is free software.
+
+You can get TeX sources via anonymous FTP from labrea.stanford.edu in
+pub/tex. The directory pub/tex/unix3.0 probably contains what you
+want, but see pub/tex/README to be sure. The most recent incarnation
+of the LaTeX macros are in labrea:pub/tex/latex. If you'd like to
+support TUG and/or don't have access to the Internet, then write to
+elisabet@max.acs.washington.edu about getting their tape distribution.
+
+** Scheme and How to FTP It
+
+The latest distribution version of C Scheme is on the machine
+zurich.ai.mit.edu. To obtain a "tarred" copy of this directory,
+telnet to zurich.ai.mit.edu and log in as scheme (password: scheme).
+A file called dist.tar will be created (if there isn't one already),
+and you will be given a choice of the file transfer program to run (of
+all the ones supported by zurich). It should be self-explanatory (ha,
+ha! [try ? for help]).
+
+Read the files INSTALL and README in the top level C Scheme directory.
+
+** Alternative Internet FTP Sources
+
+The administrators of louie.udel.edu maintains copies of GNU Emacs and
+the compress program. The files are available via anonymous ftp under
+directory ~ftp/gnu.
+
+Emacs and other GNU programs may be available via anonymous ftp from
+these US sites: gatekeeper.dec.com, labrea.stanford.edu,
+wuarchive.wustl.edu, a.cs.uiuc.edu, itstd.sri.com, scam.berkeley.edu,
+jaguar.utah.edu, archive.cis.ohio-state.edu, and ftp.uu.net. And
+these foreign sites: mcsun.eu.net (Europe - Internet address
+192.16.202.1), sunic.sunet.se (Sweden), hp4nl.nluug.nl (Netherlands -
+192.16.202.2), funic.funet.fi (Finland - 128.214.6.100), freja.diku.dk
+(Denmark - 129.142.96.1), ftp.cs.titech.ac.jp (Japan - nemacs, the
+japanese port of GNU Emacs, is under ~ftp/JAPAN). Please do NOT use a
+site outside your country, until you have checked all sites inside
+your country, and then your continent. Trans-ocean TCP/IP links are
+very expensive and usually very low speed.
+
+* Getting GNU software in Great Britain
+
+jpo@cs.nott.ac.uk is willing to distribute those GNU sources he has
+available. The smaller items are available from the info-server (send
+to info-server@cs.nott.ac.uk) the larger items by negotiation. Due to
+communication costs this service is only available within the UK.
+
+BattenIG@computer-science.birmingham.ac.uk (aka
+I.G.Batten@fulcrum.bt.co.uk) is also willing to distribute those GNU
+sources he has available. He can also write tapes in qic-21 and
+qic-24 formats.
+
+lmjm@doc.ic.ac.uk is willing to distribute those GNU sources he has
+available along with comp.sources.unix, comp.sources.x, X windows et
+al. The archive, on src.doc.ic.ac.uk in directory /gnu, is available
+via ftp (on 146.169.3.7), niftp over janet (000005102000), ftam and
+uucp. All items are available using uucp, NIFTP over JANET to
+src.doc.ic.ac.uk:/gnu. Due to communication costs this service is
+only available within the UK. Mail to info-server@doc.ic.ac.uk for
+details. He can also write sun cartridge or exabyte tapes.
+
+* Getting GNU software via UUCP
+
+OSU is distributing via UUCP: most GNU software, MIT C Scheme,
+Compress, News, RN, NNTP, Patch, some Appletalk stuff, some of the
+Internet Requests For Comment (RFC) et al.. See their periodic
+postings on the Usenet newsgroup comp.sources.d for informational
+updates. Current details from <staff@cis.ohio-state.edu> or
+<...!osu-cis!uucp>.
+
+Information on how to uucp some GNU programs is available via
+electronic mail from: uunet!hutch!barber, hqda-ai!merlin, acornrc!bob,
+hao!scicom!qetzal!upba!ugn!nepa!denny, bigtex!james (aka
+james@bigtex.cactus.org), ncar!noao!asuvax!hrc!dan, oli-stl!root,
+src@scuzzy.in-berlin.de (in Germany) and info@ftp.uu.net.
+
+* If You Like The Software
+
+If you like the software developed and distributed by the Free
+Software Foundation, please express your satisfaction with a donation.
+Your donations will help to support the Foundation and make our future
+efforts successful, including a complete development and operating
+system, called GNU (Gnu's Not Un*x), which will run Un*x user
+programs. For more information on GNU and the Foundation, contact us
+at the above address.
+
+Ordering a distribution tape from the Foundation is often a good
+way to bring your company or university to make a donation.
diff --git a/etc/GNU b/etc/GNU
new file mode 100644
index 00000000000..70aa36ddcd8
--- /dev/null
+++ b/etc/GNU
@@ -0,0 +1,475 @@
+ The GNU Manifesto
+
+Copyright (C) 1985 Richard M. Stallman
+ (Copying permission notice at the end.)
+
+What's GNU? Gnu's Not Unix!
+
+GNU, which stands for Gnu's Not Unix, is the name for the complete
+Unix-compatible software system which I am writing so that I can give it
+away free to everyone who can use it. Several other volunteers are helping
+me. Contributions of time, money, programs and equipment are greatly
+needed.
+
+So far we have an Emacs text editor with Lisp for writing editor commands,
+a source level debugger, a yacc-compatible parser generator, a linker, and
+around 35 utilities. A shell (command interpreter) is nearly completed. A
+new portable optimizing C compiler has compiled itself and may be released
+this year. An initial kernel exists but many more features are needed to
+emulate Unix. When the kernel and compiler are finished, it will be
+possible to distribute a GNU system suitable for program development. We
+will use @TeX{} as our text formatter, but an nroff is being worked on. We
+will use the free, portable X window system as well. After this we will
+add a portable Common Lisp, an Empire game, a spreadsheet, and hundreds of
+other things, plus on-line documentation. We hope to supply, eventually,
+everything useful that normally comes with a Unix system, and more.
+
+GNU will be able to run Unix programs, but will not be identical to Unix.
+We will make all improvements that are convenient, based on our experience
+with other operating systems. In particular, we plan to have longer
+filenames, file version numbers, a crashproof file system, filename
+completion perhaps, terminal-independent display support, and perhaps
+eventually a Lisp-based window system through which several Lisp programs
+and ordinary Unix programs can share a screen. Both C and Lisp will be
+available as system programming languages. We will try to support UUCP,
+MIT Chaosnet, and Internet protocols for communication.
+
+GNU is aimed initially at machines in the 68000/16000 class with virtual
+memory, because they are the easiest machines to make it run on. The extra
+effort to make it run on smaller machines will be left to someone who wants
+to use it on them.
+
+To avoid horrible confusion, please pronounce the `G' in the word `GNU'
+when it is the name of this project.
+
+
+Who Am I?
+
+I am Richard Stallman, inventor of the original much-imitated EMACS editor,
+formerly at the Artificial Intelligence Lab at MIT. I have worked
+extensively on compilers, editors, debuggers, command interpreters, the
+Incompatible Timesharing System and the Lisp Machine operating system. I
+pioneered terminal-independent display support in ITS. Since then I have
+implemented one crashproof file system and two window systems for Lisp
+machines, and designed a third window system now being implemented; this
+one will be ported to many systems including use in GNU. [Historical note:
+The window system project was not completed; GNU now plans to use the
+X window system.]
+
+
+Why I Must Write GNU
+
+I consider that the golden rule requires that if I like a program I must
+share it with other people who like it. Software sellers want to divide
+the users and conquer them, making each user agree not to share with
+others. I refuse to break solidarity with other users in this way. I
+cannot in good conscience sign a nondisclosure agreement or a software
+license agreement. For years I worked within the Artificial Intelligence
+Lab to resist such tendencies and other inhospitalities, but eventually
+they had gone too far: I could not remain in an institution where such
+things are done for me against my will.
+
+So that I can continue to use computers without dishonor, I have decided to
+put together a sufficient body of free software so that I will be able to
+get along without any software that is not free. I have resigned from the
+AI lab to deny MIT any legal excuse to prevent me from giving GNU away.
+
+
+Why GNU Will Be Compatible with Unix
+
+Unix is not my ideal system, but it is not too bad. The essential features
+of Unix seem to be good ones, and I think I can fill in what Unix lacks
+without spoiling them. And a system compatible with Unix would be
+convenient for many other people to adopt.
+
+
+How GNU Will Be Available
+
+GNU is not in the public domain. Everyone will be permitted to modify and
+redistribute GNU, but no distributor will be allowed to restrict its
+further redistribution. That is to say, proprietary modifications will not
+be allowed. I want to make sure that all versions of GNU remain free.
+
+
+Why Many Other Programmers Want to Help
+
+I have found many other programmers who are excited about GNU and want to
+help.
+
+Many programmers are unhappy about the commercialization of system
+software. It may enable them to make more money, but it requires them to
+feel in conflict with other programmers in general rather than feel as
+comrades. The fundamental act of friendship among programmers is the
+sharing of programs; marketing arrangements now typically used essentially
+forbid programmers to treat others as friends. The purchaser of software
+must choose between friendship and obeying the law. Naturally, many decide
+that friendship is more important. But those who believe in law often do
+not feel at ease with either choice. They become cynical and think that
+programming is just a way of making money.
+
+By working on and using GNU rather than proprietary programs, we can be
+hospitable to everyone and obey the law. In addition, GNU serves as an
+example to inspire and a banner to rally others to join us in sharing.
+This can give us a feeling of harmony which is impossible if we use
+software that is not free. For about half the programmers I talk to, this
+is an important happiness that money cannot replace.
+
+
+How You Can Contribute
+
+I am asking computer manufacturers for donations of machines and money.
+I'm asking individuals for donations of programs and work.
+
+One consequence you can expect if you donate machines is that GNU will run
+on them at an early date. The machines should be complete, ready to use
+systems, approved for use in a residential area, and not in need of
+sophisticated cooling or power.
+
+I have found very many programmers eager to contribute part-time work for
+GNU. For most projects, such part-time distributed work would be very hard
+to coordinate; the independently-written parts would not work together.
+But for the particular task of replacing Unix, this problem is absent. A
+complete Unix system contains hundreds of utility programs, each of which
+is documented separately. Most interface specifications are fixed by Unix
+compatibility. If each contributor can write a compatible replacement for
+a single Unix utility, and make it work properly in place of the original
+on a Unix system, then these utilities will work right when put together.
+Even allowing for Murphy to create a few unexpected problems, assembling
+these components will be a feasible task. (The kernel will require closer
+communication and will be worked on by a small, tight group.)
+
+If I get donations of money, I may be able to hire a few people full or
+part time. The salary won't be high by programmers' standards, but I'm
+looking for people for whom building community spirit is as important as
+making money. I view this as a way of enabling dedicated people to devote
+their full energies to working on GNU by sparing them the need to make a
+living in another way.
+
+
+Why All Computer Users Will Benefit
+
+Once GNU is written, everyone will be able to obtain good system software
+free, just like air.
+
+This means much more than just saving everyone the price of a Unix license.
+It means that much wasteful duplication of system programming effort will
+be avoided. This effort can go instead into advancing the state of the
+art.
+
+Complete system sources will be available to everyone. As a result, a user
+who needs changes in the system will always be free to make them himself,
+or hire any available programmer or company to make them for him. Users
+will no longer be at the mercy of one programmer or company which owns the
+sources and is in sole position to make changes.
+
+Schools will be able to provide a much more educational environment by
+encouraging all students to study and improve the system code. Harvard's
+computer lab used to have the policy that no program could be installed on
+the system if its sources were not on public display, and upheld it by
+actually refusing to install certain programs. I was very much inspired by
+this.
+
+Finally, the overhead of considering who owns the system software and what
+one is or is not entitled to do with it will be lifted.
+
+Arrangements to make people pay for using a program, including licensing of
+copies, always incur a tremendous cost to society through the cumbersome
+mechanisms necessary to figure out how much (that is, which programs) a
+person must pay for. And only a police state can force everyone to obey
+them. Consider a space station where air must be manufactured at great
+cost: charging each breather per liter of air may be fair, but wearing the
+metered gas mask all day and all night is intolerable even if everyone can
+afford to pay the air bill. And the TV cameras everywhere to see if you
+ever take the mask off are outrageous. It's better to support the air
+plant with a head tax and chuck the masks.
+
+Copying all or parts of a program is as natural to a programmer as
+breathing, and as productive. It ought to be as free.
+
+
+Some Easily Rebutted Objections to GNU's Goals
+
+ "Nobody will use it if it is free, because that means
+ they can't rely on any support."
+ "You have to charge for the program
+ to pay for providing the support."
+
+If people would rather pay for GNU plus service than get GNU free without
+service, a company to provide just service to people who have obtained GNU
+free ought to be profitable.
+
+We must distinguish between support in the form of real programming work
+and mere handholding. The former is something one cannot rely on from a
+software vendor. If your problem is not shared by enough people, the
+vendor will tell you to get lost.
+
+If your business needs to be able to rely on support, the only way is to
+have all the necessary sources and tools. Then you can hire any available
+person to fix your problem; you are not at the mercy of any individual.
+With Unix, the price of sources puts this out of consideration for most
+businesses. With GNU this will be easy. It is still possible for there to
+be no available competent person, but this problem cannot be blamed on
+distribution arrangements. GNU does not eliminate all the world's problems,
+only some of them.
+
+Meanwhile, the users who know nothing about computers need handholding:
+doing things for them which they could easily do themselves but don't know
+how.
+
+Such services could be provided by companies that sell just hand-holding
+and repair service. If it is true that users would rather spend money and
+get a product with service, they will also be willing to buy the service
+having got the product free. The service companies will compete in quality
+and price; users will not be tied to any particular one. Meanwhile, those
+of us who don't need the service should be able to use the program without
+paying for the service.
+
+ "You cannot reach many people without advertising,
+ and you must charge for the program to support that."
+ "It's no use advertising a program people can get free."
+
+There are various forms of free or very cheap publicity that can be used to
+inform numbers of computer users about something like GNU. But it may be
+true that one can reach more microcomputer users with advertising. If this
+is really so, a business which advertises the service of copying and
+mailing GNU for a fee ought to be successful enough to pay for its
+advertising and more. This way, only the users who benefit from the
+advertising pay for it.
+
+On the other hand, if many people get GNU from their friends, and such
+companies don't succeed, this will show that advertising was not really
+necessary to spread GNU. Why is it that free market advocates don't want
+to let the free market decide this?
+
+ "My company needs a proprietary operating system
+ to get a competitive edge."
+
+GNU will remove operating system software from the realm of competition.
+You will not be able to get an edge in this area, but neither will your
+competitors be able to get an edge over you. You and they will compete in
+other areas, while benefitting mutually in this one. If your business is
+selling an operating system, you will not like GNU, but that's tough on
+you. If your business is something else, GNU can save you from being
+pushed into the expensive business of selling operating systems.
+
+I would like to see GNU development supported by gifts from many
+manufacturers and users, reducing the cost to each.
+
+ "Don't programmers deserve a reward for their creativity?"
+
+If anything deserves a reward, it is social contribution. Creativity can
+be a social contribution, but only in so far as society is free to use the
+results. If programmers deserve to be rewarded for creating innovative
+programs, by the same token they deserve to be punished if they restrict
+the use of these programs.
+
+ "Shouldn't a programmer be able to ask for a reward for his creativity?"
+
+There is nothing wrong with wanting pay for work, or seeking to maximize
+one's income, as long as one does not use means that are destructive. But
+the means customary in the field of software today are based on
+destruction.
+
+Extracting money from users of a program by restricting their use of it is
+destructive because the restrictions reduce the amount and the ways that
+the program can be used. This reduces the amount of wealth that humanity
+derives from the program. When there is a deliberate choice to restrict,
+the harmful consequences are deliberate destruction.
+
+The reason a good citizen does not use such destructive means to become
+wealthier is that, if everyone did so, we would all become poorer from the
+mutual destructiveness. This is Kantian ethics; or, the Golden Rule.
+Since I do not like the consequences that result if everyone hoards
+information, I am required to consider it wrong for one to do so.
+Specifically, the desire to be rewarded for one's creativity does not
+justify depriving the world in general of all or part of that creativity.
+
+ "Won't programmers starve?"
+
+I could answer that nobody is forced to be a programmer. Most of us cannot
+manage to get any money for standing on the street and making faces. But
+we are not, as a result, condemned to spend our lives standing on the
+street making faces, and starving. We do something else.
+
+But that is the wrong answer because it accepts the questioner's implicit
+assumption: that without ownership of software, programmers cannot possibly
+be paid a cent. Supposedly it is all or nothing.
+
+The real reason programmers will not starve is that it will still be
+possible for them to get paid for programming; just not paid as much as
+now.
+
+Restricting copying is not the only basis for business in software. It is
+the most common basis because it brings in the most money. If it were
+prohibited, or rejected by the customer, software business would move to
+other bases of organization which are now used less often. There are
+always numerous ways to organize any kind of business.
+
+Probably programming will not be as lucrative on the new basis as it is
+now. But that is not an argument against the change. It is not considered
+an injustice that sales clerks make the salaries that they now do. If
+programmers made the same, that would not be an injustice either. (In
+practice they would still make considerably more than that.)
+
+ "Don't people have a right to control how their creativity is used?"
+
+"Control over the use of one's ideas" really constitutes control over other
+people's lives; and it is usually used to make their lives more difficult.
+
+People who have studied the issue of intellectual property rights carefully
+(such as lawyers) say that there is no intrinsic right to intellectual
+property. The kinds of supposed intellectual property rights that the
+government recognizes were created by specific acts of legislation for
+specific purposes.
+
+For example, the patent system was established to encourage inventors to
+disclose the details of their inventions. Its purpose was to help society
+rather than to help inventors. At the time, the life span of 17 years for
+a patent was short compared with the rate of advance of the state of the
+art. Since patents are an issue only among manufacturers, for whom the
+cost and effort of a license agreement are small compared with setting up
+production, the patents often do not do much harm. They do not obstruct
+most individuals who use patented products.
+
+The idea of copyright did not exist in ancient times, when authors
+frequently copied other authors at length in works of non-fiction. This
+practice was useful, and is the only way many authors' works have survived
+even in part. The copyright system was created expressly for the purpose
+of encouraging authorship. In the domain for which it was invented--books,
+which could be copied economically only on a printing press--it did little
+harm, and did not obstruct most of the individuals who read the books.
+
+All intellectual property rights are just licenses granted by society
+because it was thought, rightly or wrongly, that society as a whole would
+benefit by granting them. But in any particular situation, we have to ask:
+are we really better off granting such license? What kind of act are we
+licensing a person to do?
+
+The case of programs today is very different from that of books a hundred
+years ago. The fact that the easiest way to copy a program is from one
+neighbor to another, the fact that a program has both source code and
+object code which are distinct, and the fact that a program is used rather
+than read and enjoyed, combine to create a situation in which a person who
+enforces a copyright is harming society as a whole both materially and
+spiritually; in which a person should not do so regardless of whether the
+law enables him to.
+
+ "Competition makes things get done better."
+
+The paradigm of competition is a race: by rewarding the winner, we
+encourage everyone to run faster. When capitalism really works this way,
+it does a good job; but its defenders are wrong in assuming it always works
+this way. If the runners forget why the reward is offered and become
+intent on winning, no matter how, they may find other strategies--such as,
+attacking other runners. If the runners get into a fist fight, they will
+all finish late.
+
+Proprietary and secret software is the moral equivalent of runners in a
+fist fight. Sad to say, the only referee we've got does not seem to
+object to fights; he just regulates them ("For every ten yards you run, you
+are allowed one kick."). He really ought to break them up, and penalize
+runners for even trying to fight.
+
+ "Won't everyone stop programming without a monetary incentive?"
+
+Actually, many people will program with absolutely no monetary incentive.
+Programming has an irresistible fascination for some people, usually the
+people who are best at it. There is no shortage of professional musicians
+who keep at it even though they have no hope of making a living that way.
+
+But really this question, though commonly asked, is not appropriate to the
+situation. Pay for programmers will not disappear, only become less. So
+the right question is, will anyone program with a reduced monetary
+incentive? My experience shows that they will.
+
+For more than ten years, many of the world's best programmers worked at the
+Artificial Intelligence Lab for far less money than they could have had
+anywhere else. They got many kinds of non-monetary rewards: fame and
+appreciation, for example. And creativity is also fun, a reward in itself.
+
+Then most of them left when offered a chance to do the same interesting
+work for a lot of money.
+
+What the facts show is that people will program for reasons other than
+riches; but if given a chance to make a lot of money as well, they will
+come to expect and demand it. Low-paying organizations do poorly in
+competition with high-paying ones, but they do not have to do badly if the
+high-paying ones are banned.
+
+ "We need the programmers desperately. If they demand that we
+ stop helping our neighbors, we have to obey."
+
+You're never so desperate that you have to obey this sort of demand.
+Remember: millions for defense, but not a cent for tribute!
+
+ "Programmers need to make a living somehow."
+
+In the short run, this is true. However, there are plenty of ways that
+programmers could make a living without selling the right to use a program.
+This way is customary now because it brings programmers and businessmen the
+most money, not because it is the only way to make a living. It is easy to
+find other ways if you want to find them. Here are a number of examples.
+
+A manufacturer introducing a new computer will pay for the porting of
+operating systems onto the new hardware.
+
+The sale of teaching, hand-holding and maintenance services could also
+employ programmers.
+
+People with new ideas could distribute programs as freeware, asking for
+donations from satisfied users, or selling hand-holding services. I have
+met people who are already working this way successfully.
+
+Users with related needs can form users' groups, and pay dues. A group
+would contract with programming companies to write programs that the
+group's members would like to use.
+
+All sorts of development can be funded with a Software Tax:
+
+ Suppose everyone who buys a computer has to pay x percent of
+ the price as a software tax. The government gives this to
+ an agency like the NSF to spend on software development.
+
+ But if the computer buyer makes a donation to software development
+ himself, he can take a credit against the tax. He can donate to
+ the project of his own choosing--often, chosen because he hopes to
+ use the results when it is done. He can take a credit for any amount
+ of donation up to the total tax he had to pay.
+
+ The total tax rate could be decided by a vote of the payers of
+ the tax, weighted according to the amount they will be taxed on.
+
+ The consequences:
+ * the computer-using community supports software development.
+ * this community decides what level of support is needed.
+ * users who care which projects their share is spent on
+ can choose this for themselves.
+
+In the long run, making programs free is a step toward the post-scarcity
+world, where nobody will have to work very hard just to make a living.
+People will be free to devote themselves to activities that are fun,
+such as programming, after spending the necessary ten hours a week
+on required tasks such as legislation, family counseling, robot
+repair and asteroid prospecting. There will be no need to be able
+to make a living from programming.
+
+We have already greatly reduced the amount of work that the whole
+society must do for its actual productivity, but only a little of this
+has translated itself into leisure for workers because much
+nonproductive activity is required to accompany productive activity.
+The main causes of this are bureaucracy and isometric struggles
+against competition. Free software will greatly reduce these
+drains in the area of software production. We must do this,
+in order for technical gains in productivity to translate into
+less work for us.
+
+Copyright (C) 1985 Richard M. Stallman
+
+ Permission is granted to anyone to make or distribute verbatim copies
+ of this document as received, in any medium, provided that the
+ copyright notice and permission notice are preserved,
+ and that the distributor grants the recipient permission
+ for further redistribution as permitted by this notice.
+
+ Modified versions may not be made.
+
diff --git a/etc/GNU.JOKES b/etc/GNU.JOKES
new file mode 100644
index 00000000000..29a458de1ad
--- /dev/null
+++ b/etc/GNU.JOKES
@@ -0,0 +1,38 @@
+From: Don Chiasson <G.CHIASSON@DREA-XX.ARPA>
+Subject: Some gnu jokes
+To: jokes@DREA-XX.ARPA, gergely@DREA-XX.ARPA, broome@DREA-XX.ARPA
+cc: G.CHIASSON@DREA-XX.ARPA
+Message-ID: <12329394624.13.G.CHIASSON@DREA-XX.ARPA>
+
+ Richard M. Stallman (RMS, widely known for creating EMACS) is writing
+a UNIX clone called GNU (which means Gnu's Not Unix--a recursive acronym).
+This seems to open the way to a whole gnu class of jokes. For example:
+
+Q: What do you call a person who hacks while wearing no clothes?
+A: A gnudist.
+
+Q: What do you call an eligible young hacker?
+A: Gnubile.
+
+Q: What is a hacker's favorite candy?
+A: Gnugat. (Though it contains little gnutrition.)
+
+Q: What do you call a computer filled with air?
+A: Gnumatic.
+
+Q: What do you call a novice hacker who keeps pestering you
+ with foolish questions?
+A: A gnuisance.
+
+Q: What do you call a subtle, clever hack in the favorite language?
+A: A gnuanCe.
+
+Q: What do you use a supercomputer for?
+A: Gnumerical analysis.
+
+Q: What do you call a hacker who collects coins?
+A: A gnumismatist.
+
+ Well, there are more, just too gnumerous to tell all at once. I think
+I'd better go before someone starts firing gnuclear weapons at me.
+ Don
diff --git a/etc/GOSDIFF b/etc/GOSDIFF
new file mode 100644
index 00000000000..a283c1a3f1f
--- /dev/null
+++ b/etc/GOSDIFF
@@ -0,0 +1,614 @@
+Advantages of Gosling Emacs:
+
+1. The program itself is much smaller.
+GNU Emacs uses about 250k more pure storage.
+As a result, Gosling Emacs can run on machines
+that cannot run GNU Emacs. There is not much difference
+in the amount of impure storage in the two programs.
+
+2. In some versions there is support for other forks to
+establish communications channels to Emacs (using sockets?).
+
+3. There is a direct interface to dbm (data bases).
+
+
+Advantages of GNU Emacs:
+
+* True Lisp, not Mocklisp.
+
+GNU Emacs's extension language has real symbols, lists
+and vectors. Many extensions are much simpler, and some
+become possible that were nearly impossible in Gosling Emacs.
+Many primitives can have cleaner interfaces, and some features
+need not be put in as special primitives because you can do
+them easily yourself.
+
+* But Mocklisp still works.
+
+An automatic conversion package plus a run-time library
+allows you to convert a Mocklisp library into a Lisp library.
+
+* Commands are better crafted.
+
+For example, nearly every editing function for which a
+numeric argument would make sense as a repeat count does
+accept a repeat count, and does handle a negative argument
+in the way you would expect.
+
+* The manual is clearer.
+
+Everyone tells me it is a very good manual.
+
+* Better on-line documentation.
+
+Both functions and variables have documentation strings that
+describe exactly how to use them.
+
+* C mode is smart.
+
+It really knows how to indent each line correctly,
+for most popular indentation styles. (Some variables
+control which style is used.)
+
+* Compatible with PDP-10 Emacs, Multics Emacs and Zmacs.
+
+The commands in GNU Emacs are nearly the same as in the
+original Emacs and the other Emacses which imitated it.
+(A few have been changed to fit the Unix environment better.)
+
+* Support for Gosling's Emacs commands.
+
+M-x set-gosmacs-bindings rebinds many editing commands for
+compatibility with Gosling's Emacs.
+M-x set-gnu-bindings reverses the change.
+
+* Side-by-side windows.
+
+You can split a GNU Emacs window either horizontally or
+vertically.
+
+* Redisplay is faster.
+
+GNU Emacs sends about the same stuff to the terminal that
+Gosling's does, but GNU Emacs uses much less CPU time to
+decide what to do.
+
+* Entirely termcap-driven.
+
+GNU Emacs has nearly no special code for any terminal type. Various
+new termcap strings make it possible to handle all terminals nearly as
+fast as they could be handled by special-case code.
+
+* Display-hiding features.
+
+For example, Outline Mode makes it possible for you to edit
+an outline, making entire sub-branches of the outline visible
+or invisible when you wish.
+
+* You can interrupt with Control-G.
+
+Even a looping Lisp program can be stopped this way.
+And even a loop in C code does not stop you from killing
+Emacs and getting back to your shell.
+
+* Per-buffer Undo.
+
+You can undo the last several changes, in each buffer
+independently.
+
+* The editor code itself is clean.
+
+Many people have remarked on how much they enjoy reading
+the code for GNU Emacs.
+
+
+One other note: The program etc/cvtmail that comes with GNU Emacs can
+be used to convert a mail directory for Gosling Emacs's Rmail into a
+Unix mail file that you could read into GNU Emacs's Rmail.
+
+
+A detailed comparison by Rodney Zykowitz (rtgvax!ramin@eddie.mit.edu)
+
+Enclosed are two difference listings. The first one is a cross-reference
+by Key bindings. The second is by alphabetized function name.
+Only those functions normally bound to keys in a
+"standard" version are included. As far as I know it excludes
+bindings added here locally (but what do I know...)
+
+The Gosling's is version 2.02 and runs on VMS 4.2. The Gnu is
+version 16.56.1 running under Ultrix 1.1.
+
+
+And could someone send me some info on Gnu on VMS. I seem to have entirely
+missed that posting. If it is hopeless, I just might sit down and write
+a Gnu emulator for Unipress and a Unipress emulator for Gnu... But the
+thought of that already makes me wanna....
+
+
+ramin...
+Standard disclaimer excluded for humanitarian purposes.
+
+
+
+Command Binding Cross-references. By key code:
+
+ VMS (Unipress) GNU Emacs
+Key Binding Binding
+--- ------- ---------------
+^@ set-mark set-mark-command
+^A beginning-of-line beginning-of-line
+^B backward-character backward-char
+^C exit-emacs exit-recursive-edit
+^D delete-next-character delete-char
+^E end-of-line end-of-line
+^F forward-character forward-char
+^G illegal-operation
+^H delete-previous-character help-command
+^H-v describe-variable
+^H-w where-is
+^H-t help-with-tutorial
+^H-s describe-syntax
+^H-n view-emacs-news
+^H-^N view-emacs-news
+^H-m describe-mode
+^H-l view-lossage
+^H-i info
+^H-f describe-function
+^H-d describe-function
+^H-k describe-key
+^H-c describe-key-briefly
+^H-b describe-bindings
+^H-a command-apropos
+^H-^D describe-distribution
+^H-^C describe-copying
+^H-? help-for-help
+^H-^H help-for-help
+^I self-insert indent-for-tab-command
+^J newline-and-indent newline-and-indent
+^K kill-to-end-of-line kill-line
+^L redraw-display recenter
+^M newline newline
+^N next-line next-line
+^O newline-and-backup open-line
+^P previous-line previous-line
+^Q quote-character quoted-insert
+^R search-reverse isearch-backward
+^S search-forward isearch-forward
+^T transpose-characters transpose-chars
+^U argument-prefix universal-argument
+^V next-page scroll-up
+^W delete-to-killbuffer kill-region
+^X ^X-prefix Control-x-prefix
+^X-^A add-mode-abbrev
+^X-^B list-buffers list-buffers
+^X-^C exit-emacs save-buffers-kill-emacs
+^X-^D describe-word-in-buffer list-directory
+^X-^E compile-it eval-last-sexp
+^X-^F write-pause-or-exit find-file
+^X-^H inverse-add-mode-abbrev
+^X-^I insert-file indent-rigidly
+^X-^L downcase-region
+^X-^M write-modified-files
+^X-^N next-error set-goal-column
+^X-^O use-old-buffer delete-blank-linkes
+^X-^P mark-page
+^X-^Q toggle-read-only
+^X-^R read-file find-file-read-only
+^X-^S write-current-file save-buffer
+^X-^T transpose-lines
+^X-^U new-undo upcase-region
+^X-^V visit-file find-alternate-file
+^X-^W write-named-file write-file
+^X-^X exchange-dot-and-mark exchange-dot-and-mark
+^X-^Z shrink-window suspend-emacs
+^X-ESC repeat-complex-command
+^X-! execute-monitor-command
+^X-$ set-selective-display
+^X-( start-remembering start-kbd-macro
+^X-) stop-remembering end-kbd-macro
+^X-+ add-global-abbrev
+^X-- inverse-add-global-abbrev
+^X-. set-fill-prefix
+^X-/ dot-to-register
+^X-0 delete-window
+^X-1 delete-other-windows delete-other-windows
+^X-2 split-current-window split-window-vertically
+^X-4 ctl-x-4-prefix
+^X-4-^F find-file-other-window
+^X-4-. find-tag-other-window
+^X-4-b pop-to-buffer
+^X-4-d dired-other-window
+^X-4-f find-file-other-window
+^X-4-m mail-other-window
+^X-5 split-window-horizontally
+^X-; set-comment-column
+^X-< scroll-left
+^X-= what-cursor-position
+^X-> scroll-right
+^X-[ backward-page
+^X-] forward-page
+^X-^ enlarge-window
+^X-` next-error
+^X-a append-to-buffer
+^X-b switch-to-buffer switch-to-buffer
+^X-d delete-window dired
+^X-e execute-keyboard-macro call-last-kbd-macro
+^X-f set-fill-column
+^X-g insert-register
+^X-h mark-whole-buffer
+^X-i insert-file
+^X-j register-to-dot
+^X-k kill-buffer
+^X-l count-lines-page
+^X-m mail
+^X-n next-window narrow-to-region
+^X-o other-window
+^X-p previous-window narrow-to-page
+^X-q kbd-macro-query
+^X-r copy-rectangle-to-register
+^X-s save-some-buffers
+^X-u advertised-undo
+^X-w widen
+^X-x copy-to-register
+^X-z enlarge-window
+^X-{ shrink-window-horizontally
+^X-} enlarge-window-horizontally
+^X-DEL backward-kill-sentence
+^Y yank-from-killbuffer yank
+^Z scroll-one-line-up suspend-emacs
+ESC ESC-prefix
+ESC-^@ mark-sexp
+ESC-^A beginning-of-defun
+ESC-^B backward-sexp
+ESC-^C exit-emacs exit-recursive-edit
+ESC-^D down-list
+ESC-^E end-of-defun
+ESC-^F forward-sexp
+ESC-^H mark-defun
+ESC-^J indent-new-comment-line
+ESC-^K kill-sexp
+ESC-^N forward-list
+ESC-^O split-line
+ESC-^P backward-list
+ESC-^S isearch-forward-regexp
+ESC-^T transpose-sexps
+ESC-^U backward-up-list
+ESC-^V page-next-window scroll-other-window
+ESC-^W delete-region-to-buffer append-next-kill
+ESC-^Y yank-buffer
+ESC-ESC execute-mlisp-line eval-expression
+ESC-^^ case-region-invert
+ESC-^\ indent-region
+ESC-<SP> just-one-space
+ESC-! line-to-top-of-window shell-command
+ESC-$ spell-word
+ESC-% query-replace
+ESC-' abbrev-prefix-mark
+ESC-( backward-paragraph insert-parentheses
+ESC-) forward-paragraph move-past-close-and-reindent
+ESC-, beginning-of-window tags-loop-continue
+ESC-- meta-minus negative-argument
+ESC-. end-of-window find-tag
+ESC-0..ESC-9 meta-digit digit-argument
+ESC-; indent-for-comment
+ESC-< beginning-of-file beginning-of-buffer
+ESC-= count-lines-region
+ESC-> end-of-file end-of-buffer
+ESC-@ mark-word
+ESC-[ backward-paragraph
+ESC-\ delete-horizontal-space
+ESC-] forward-paragraph
+ESC-? apropos
+ESC-^ case-word-invert delete-indentation
+ESC-a backward-sentence backward-sentence
+ESC-b backward-word backward-word
+ESC-d delete-next-word kill-word
+ESC-e forward-sentence forward-sentence
+ESC-f forward-word forward-word
+ESC-g fill-region
+ESC-h delete-previous-word mark-paragraph
+ESC-j indent-C-procedure indent-new-comment-line
+ESC-k kill-sentence
+ESC-l case-word-lower downcase-word
+ESC-q query-replace-string fill-paragraph
+ESC-r replace-string move-to-window-line
+ESC-t transpose-words
+ESC-u case-word-upper upcase-word
+ESC-v previous-page scroll-down
+ESC-w copy-region-as-kill
+ESC-x execute-extended-command execute-extended-command
+ESC-y yank-pop
+ESC-z scroll-one-line-down zap-to-char
+ESC-| shell-command-on-region
+ESC-~ not-modified
+ESC-DEL backward-kill-word
+^_ return-to-monitor
+ .., self-insert
+- minus
+.../ self-insert
+0..9 digit
+:..~ self-insert
+^? delete-previous-character
+
+
+
+
+Command Binding Cross-references. By name:
+
+Command VMS (Unipress) Key GNU Key
+----------------------------- --------------------- ------------
+abbrev-prefix-mark ESC-'
+add-global-abbrev ^X-+
+add-mode-abbrev ^X-^A
+advertised-undo ^X-u
+append-next-kill ESC-^W
+append-to-buffer ^X-a
+apropos ESC-?
+argument-prefix ^U
+backward-char ^B
+backward-character ^B
+backward-kill-sentence ^X-DEL
+backward-kill-word ESC-DEL
+backward-list ESC-^P
+backward-page ^X-[
+backward-paragraph ESC-(
+backward-paragraph ESC-[
+backward-sentence ESC-a
+backward-sentence ESC-a
+backward-sexp ESC-^B
+backward-up-list ESC-^U
+backward-word ESC-b
+backward-word ESC-b
+beginning-of-buffer ESC-<
+beginning-of-defun ESC-^A
+beginning-of-file ESC-<
+beginning-of-line ^A
+beginning-of-line ^A
+beginning-of-window ESC-,
+call-last-kbd-macro ^X-e
+case-region-invert ESC-^^
+case-word-invert ESC-^
+case-word-lower ESC-l
+case-word-upper ESC-u
+command-apropos ^H-a
+compile-it ^X-^E
+control-x-prefix ^X
+control-x-prefix ^X
+copy-rectangle-to-register ^X-r
+copy-region-as-kill ESC-w
+copy-to-register ^X-x
+count-lines-page ^X-l
+count-lines-region ESC-=
+ctl-x-4-prefix ^X-4
+delete-blank-linkes ^X-^O
+delete-char ^D
+delete-horizontal-space ESC-\
+delete-indentation ESC-^
+delete-next-character ^D
+delete-next-word ESC-d
+delete-other-windows ^X-1
+delete-other-windows ^X-1
+delete-previous-character ^H ^?
+delete-previous-character ^?
+delete-previous-word ESC-h
+delete-region-to-buffer ESC-^W
+delete-to-killbuffer ^W
+delete-window ^X-0
+delete-window ^X-d
+describe-bindings ^H-b
+describe-copying ^H-^C
+describe-distribution ^H-^D
+describe-function ^H-f
+describe-function ^H-d
+describe-key ^H-k
+describe-key-briefly ^H-c
+describe-mode ^H-m
+describe-syntax ^H-s
+describe-variable ^H-v
+describe-word-in-buffer ^X-^D
+digit 0..9
+digit 0..9
+digit-argument ESC-0..ESC-9
+dired ^X-d
+dired-other-window ^X-4-d
+dot-to-register ^X-/
+down-list ESC-^D
+downcase-region ^X-^L
+downcase-word ESC-l
+end-kbd-macro ^X-)
+end-of-buffer ESC->
+end-of-defun ESC-^E
+end-of-file ESC->
+end-of-line ^E
+end-of-line ^E
+end-of-window ESC-.
+enlarge-window ^X-^
+enlarge-window ^X-z
+enlarge-window-horizontally ^X-}
+esc-prefix ESC
+esc-prefix ESC
+eval-expression ESC-ESC
+eval-last-sexp ^X-^E
+exchange-dot-and-mark ^X-^X
+exchange-dot-and-mark ^X-^X
+execute-extended-command ESC-x
+execute-extended-command ESC-x
+execute-keyboard-macro ^X-e
+execute-mlisp-line ESC-ESC
+execute-monitor-command ^X-!
+exit-emacs ^C
+exit-emacs ^X-^C
+exit-emacs ESC-^C
+exit-recursive-edit ^C
+exit-recursive-edit ESC-^C
+fill-paragraph ESC-q
+fill-region ESC-g
+find-alternate-file ^X-^V
+find-file ^X-^F
+find-file-other-window ^X-4-^F
+find-file-other-window ^X-4-f
+find-file-read-only ^X-^R
+find-tag ESC-.
+find-tag-other-window ^X-4-.
+forward-char ^F
+forward-character ^F
+forward-list ESC-^N
+forward-page ^X-]
+forward-paragraph ESC-)
+forward-paragraph ESC-]
+forward-sentence ESC-e
+forward-sentence ESC-e
+forward-sexp ESC-^F
+forward-word ESC-f
+forward-word ESC-f
+help-command ^H
+help-for-help ^H-?
+help-for-help ^H-^H
+help-with-tutorial ^H-t
+illegal-operation ^G
+indent-C-procedure ESC-j
+indent-for-comment ESC-;
+indent-for-tab-command ^I
+indent-new-comment-line ESC-^J
+indent-new-comment-line ESC-j
+indent-region ESC-^\
+indent-rigidly ^X-^I
+info ^H-i
+insert-file ^X-^I
+insert-file ^X-i
+insert-parentheses ESC-(
+insert-register ^X-g
+inverse-add-global-abbrev ^X--
+inverse-add-mode-abbrev ^X-^H
+isearch-backward ^R
+isearch-forward ^S
+isearch-forward-regexp ESC-^S
+just-one-space ESC-<SP>
+kbd-macro-query ^X-q
+kill-buffer ^X-k
+kill-line ^K
+kill-region ^W
+kill-sentence ESC-k
+kill-sexp ESC-^K
+kill-to-end-of-line ^K
+kill-word ESC-d
+line-to-top-of-window ESC-!
+list-buffers ^X-^B
+list-buffers ^X-^B
+list-directory ^X-^D
+mail ^X-m
+mail-other-window ^X-4-m
+mark-defun ^X-^H
+mark-page ^X-^P
+mark-paragraph ESC-h
+mark-sexp ESC-^@
+mark-whole-buffer ^X-h
+mark-word ESC-@
+meta-digit ESC-0..ESC-9
+meta-minus ESC--
+minus -
+minus -
+move-past-close-and-reindent ESC-)
+move-to-window-line ESC-r
+narrow-to-page ^X-p
+narrow-to-region ^X-n
+negative-argument ESC--
+new-undo ^X-^U
+newline ^M
+newline ^M
+newline-and-backup ^O
+newline-and-indent ^J
+newline-and-indent ^J
+next-error ^X-^N
+next-error ^X-`
+next-line ^N
+next-line ^N
+next-page ^V
+next-window ^X-n
+not-modified ESC-~
+open-line ^O
+other-window ^X-o
+page-next-window ESC-^V
+pop-to-buffer ^X-4-b
+previous-line ^P
+previous-line ^P
+previous-page ESC-v
+previous-window ^X-p
+query-replace ESC-%
+query-replace-string ESC-q
+quote-character ^Q
+quoted-insert ^Q
+read-file ^X-^R
+recenter ^L
+redraw-display ^L
+register-to-dot ^X-j
+repeat-complex-command ^X-ESC
+replace-string ESC-r
+return-to-monitor ^_(CTL-/)
+save-buffer ^X-^S
+save-buffers-kill-emacs ^X-^C
+save-some-buffers ^X-s
+scroll-down ESC-v
+scroll-left ^X-<
+scroll-one-line-down ESC-z
+scroll-one-line-up ^Z
+scroll-other-window ESC-^V
+scroll-right ^X->
+scroll-up ^V
+search-forward ^S
+search-reverse ^R
+self-insert ^I
+self-insert <SP>..,
+self-insert .../
+self-insert :..~
+set-comment-column ^X-;
+set-fill-column ^X-f
+set-fill-prefix ^X-.
+set-goal-column ^X-^N
+set-mark ^@
+set-mark-command ^@
+set-selective-display ^X-$
+shell-command ESC-!
+shell-command-on-region ESC-|
+shrink-window ^X-^Z
+shrink-window-horizontally ^X-{
+spell-word ESC-$
+split-current-window ^X-2
+split-line ESC-^O
+split-window-horizontally ^X-5
+split-window-vertically ^X-2
+start-kbd-macro ESC-(
+start-remembering ^X-(
+stop-remembering ^X-)
+suspend-emacs ^X-^Z
+suspend-emacs ^Z
+switch-to-buffer ^X-b
+switch-to-buffer ^X-b
+tags-loop-continue ESC-,
+toggle-read-only ^X-^Q
+transpose-characters ^T
+transpose-chars ^T
+transpose-lines ^X-^T
+transpose-sexps ESC-^T
+transpose-words ESC-t
+universal-argument ^U
+upcase-region ^X-^U
+upcase-word ESC-u
+use-old-buffer ^X-^O
+view-emacs-news ^H-^N
+view-emacs-news ^H-n
+view-lossage ^H-l
+visit-file ^X-^V
+what-cursor-position ^X-=
+where-is ^H-w
+widen ^X-w
+write-current-file ^X-^S
+write-file ^X-^W
+write-modified-files ^X-^M
+write-named-file ^X-^W
+write-pause-or-exit ^X-^F
+yank ^Y
+yank-buffer ESC-^Y
+yank-from-killbuffer ^Y
+yank-pop ESC-y
+zap-to-char ESC-z
diff --git a/etc/INTERVAL.IDEAS b/etc/INTERVAL.IDEAS
new file mode 100644
index 00000000000..c056a249218
--- /dev/null
+++ b/etc/INTERVAL.IDEAS
@@ -0,0 +1,30 @@
+This idea comes from Andrew. The basic part is to represent a division
+of the buffer into disjoint intervals by means of a binary tree. Each
+interval has one node. The tree has the effect of a large ordered
+collection of markers, but no Lisp_Marker objects appear in the tree.
+
+Each node has two subnodes, a left and a right, each of which can be
+nil instead. The subnodes' intervals are disjoint from their parent's
+interval--the tree structure is for binary searching.
+
+Each node in the tree is implicitly associated with a region of the
+buffer, but I don't think it actually stores the positions; I think it
+has the length of that node, or perhaps its own length and separately
+the length of it plus all its subnodes.
+
+I forget the details of this, but the idea is that you can figure out
+the position of a node, or find the node containing a position, by
+examining just its superiors in the tree, and you can also update the
+tree for changes in the buffer by tracing just one path down the tree.
+So the amount of work for nearly any operation goes with the log of
+the number of intervals.
+
+If it is desirable to be able to subdivide the intervals, each interval
+can have another such tree dividing it into disjoint subintervals. And
+subintervals can have trees, too. So it becomes a tree of trees.
+
+The idea is to associate an alist with each interval or subinterval.
+The complete alist associated with any spot is the append of the
+alists of the containing intervals at all levels of subdivision,
+smallest ones first. It would also be useful to get the bounds of the
+innermost interval.
diff --git a/etc/INTERVIEW b/etc/INTERVIEW
new file mode 100644
index 00000000000..db04936c443
--- /dev/null
+++ b/etc/INTERVIEW
@@ -0,0 +1,434 @@
+
+ GNU'S NOT UNIX
+
+ Conducted by David Betz and Jon Edwards
+
+ Richard Stallman discusses his public-domain
+ UNIX-compatible software system
+ with BYTE editors
+ (July 1986)
+
+Copyright (C) 1986 Richard Stallman. Permission is granted to make and
+distribute copies of this article as long as the copyright and this notice
+appear on all copies.
+
+Richard Stallman has undertaken probably the most ambitious free software
+development project to date, the GNU system. In his GNU Manifesto,
+published in the March 1985 issue of Dr. Dobb's Journal, Stallman described
+GNU as a "complete Unix-compatible software system which I am writing so
+that I can give it away free to everyone who can use it... Once GNU is
+written, everyone will be able to obtain good system software free, just
+like air." (GNU is an acronym for GNU's Not UNIX; the "G" is pronounced.)
+
+ Stallman is widely known as the author of EMACS, a powerful text editor
+that he developed at the MIT Artificial Intelligence Laboratory. It is no
+coincidence that the first piece of software produced as part of the GNU
+project was a new implementation of EMACS. GNU EMACS has already achieved a
+reputation as one of the best implementations of EMACS currently available
+at any price.
+
+BYTE: We read your GNU Manifesto in the March 1985 issue of Dr. Dobb's.
+What has happened since? Was that really the beginning, and how have you
+progressed since then?
+
+Stallman: The publication in Dr. Dobb's wasn't the beginning of the
+project. I wrote the GNU Manifesto when I was getting ready to start the
+project, as a proposal to ask computer manufacturers for funding. They
+didn't want to get involved, and I decided that rather than spend my time
+trying to pursue funds, I ought to spend it writing code. The manifesto was
+published about a year and a half after I had written it, when I had barely
+begun distributing the GNU EMACS. Since that time, in addition to making
+GNU EMACS more complete and making it run on many more computers, I have
+nearly finished the optimizing C compiler and all the other software that
+is needed for running C programs. This includes a source-level debugger
+that has many features that the other source-level debuggers on UNIX don't
+have. For example, it has convenience variables within the debugger so you
+can save values, and it also has a history of all the values that you have
+printed out, making it tremendously easier to chase around list structures.
+
+BYTE: You have finished an editor that is now widely distributed and you
+are about to finish the compiler.
+
+Stallman: I expect that it will be finished this October.
+
+BYTE: What about the kernel?
+
+Stallman: I'm currently planning to start with the kernel that was written
+at MIT and was released to the public recently with the idea that I would
+use it. This kernel is called TRIX; it's based on remote procedure call. I
+still need to add compatibility for a lot of the features of UNIX which it
+doesn't have currently. I haven't started to work on that yet. I'm
+finishing the compiler before I go to work on the kernel. I am also going
+to have to rewrite the file system. I intend to make it failsafe just by
+having it write blocks in the proper order so that the disk structure is
+always consistent. Then I want to add version numbers. I have a complicated
+scheme to reconcile version numbers with the way people usually use UNIX.
+You have to be able to specify filenames without version numbers, but you
+also have to be able to specify them with explicit version numbers, and
+these both need to work with ordinary UNIX programs that have not been
+modified in any way to deal with the existence of this feature. I think I
+have a scheme for doing this, and only trying it will show me whether it
+really does the job.
+
+BYTE: Do you have a brief description you can give us as to how GNU as a
+system will be superior to other systems? We know that one of your goals is
+to produce something that is compatible with UNIX. But at least in the area
+of file systems you have already said that you are going to go beyond UNIX
+and produce something that is better.
+
+Stallman: The C compiler will produce better code and run faster. The
+debugger is better. With each piece I may or may not find a way to improve
+it. But there is no one answer to this question. To some extent I am
+getting the benefit of reimplementation, which makes many systems much
+better. To some extent it's because I have been in the field a long time
+and worked on many other systems. I therefore have many ideas to bring to
+bear. One way in which it will be better is that practically everything in
+the system will work on files of any size, on lines of any size, with any
+characters appearing in them. The UNIX system is very bad in that regard.
+It's not anything new as a principle of software engineering that you
+shouldn't have arbitrary limits. But it just was the standard practice in
+writing UNIX to put those in all the time, possibly just because they were
+writing it for a very small computer. The only limit in the GNU system is
+when your program runs out of memory because it tried to work on too much
+data and there is no place to keep it all.
+
+BYTE: And that isn't likely to be hit if you've got virtual memory. You may
+just take forever to come up with the solution.
+
+Stallman: Actually these limits tend to hit in a time long before you take
+forever to come up with the solution.
+
+BYTE: Can you say something about what types of machines and environments
+GNU EMACS in particular has been made to run under? It's now running on
+VAXes; has it migrated in any form to personal computers?
+
+Stallman: I'm not sure what you mean by personal computers. For example, is
+a Sun a personal computer? GNU EMACS requires at least a megabyte of
+available memory and preferably more. It is normally used on machines that
+have virtual memory. Except for various technical problems in a few C
+compilers, almost any machine with virtual memory and running a fairly
+recent version of UNIX will run GNU EMACS, and most of them currently do.
+
+BYTE: Has anyone tried to port it to Ataris or Macintoshes?
+
+Stallman: The Atari 1040ST still doesn't have quite enough memory. The next
+Atari machine, I expect, will run it. I also think that future Ataris will
+have some forms of memory mapping. Of course, I am not designing the
+software to run on the kinds of computers that are prevalent today. I knew
+when I started this project it was going to take a few years. I therefore
+decided that I didn't want to make a worse system by taking on the
+additional challenge of making it run in the currently constrained
+environment. So instead I decided I'm going to write it in the way that
+seems the most natural and best. I am confident that in a couple of years
+machines of sufficient size will be prevalent. In fact, increases in memory
+size are happening so fast it surprises me how slow most of the people are
+to put in virtual memory; I think it is totally essential.
+
+BYTE: I think people don't really view it as being necessary for
+single-user machines.
+
+Stallman: They don't understand that single user doesn't mean single
+program. Certainly for any UNIX-like system it's important to be able to
+run lots of different processes at the same time even if there is only one
+of you. You could run GNU EMACS on a nonvirtual-memory machine with enough
+memory, but you couldn't run the rest of the GNU system very well or a UNIX
+system very well.
+
+BYTE: How much of LISP is present in GNU EMACS? It occurred to me that it
+may be useful to use that as a tool for learning LISP.
+
+Stallman: You can certainly do that. GNU EMACS contains a complete,
+although not very powerful, LISP system. It's powerful enough for writing
+editor commands. It's not comparable with, say, a Common LISP System,
+something you could really use for system programming, but it has all the
+things that LISP needs to have.
+
+BYTE: Do you have any predictions about when you would be likely to
+distribute a workable environment in which, if we put it on our machines or
+workstations, we could actually get reasonable work done without using
+anything other than code that you distribute?
+
+Stallman: It's really hard to say. That could happen in a year, but of
+course it could take longer. It could also conceivably take less, but
+that's not too likely anymore. I think I'll have the compiler finished in a
+month or two. The only other large piece of work I really have to do is in
+the kernel. I first predicted GNU would take something like two years, but
+it has now been two and a half years and I'm still not finished. Part of
+the reason for the delay is that I spent a lot of time working on one
+compiler that turned out to be a dead end. I had to rewrite it completely.
+Another reason is that I spent so much time on GNU EMACS. I originally
+thought I wouldn't have to do that at all.
+
+BYTE: Tell us about your distribution scheme.
+
+Stallman: I don't put software or manuals in the public domain, and the
+reason is that I want to make sure that all the users get the freedom to
+share. I don't want anyone making an improved version of a program I wrote
+and distributing it as proprietary. I don't want that to ever be able to
+happen. I want to encourage the free improvements to these programs, and
+the best way to do that is to take away any temptation for a person to make
+improvements nonfree. Yes, a few of them will refrain from making
+improvements, but a lot of others will make the same improvements and
+they'll make them free.
+
+BYTE: And how do you go about guaranteeing that?
+
+Stallman: I do this by copyrighting the programs and putting on a notice
+giving people explicit permission to copy the programs and change them but
+only on the condition that they distribute under the same terms that I
+used, if at all. You don't have to distribute the changes you make to any
+of my programs--you can just do it for yourself, and you don't have to give
+it to anyone or tell anyone. But if you do give it to someone else, you
+have to do it under the same terms that I use.
+
+BYTE: Do you obtain any rights over the executable code derived from the C
+compiler?
+
+Stallman: The copyright law doesn't give me copyright on output from the
+compiler, so it doesn't give me a way to say anything about that, and in
+fact I don't try to. I don't sympathize with people developing proprietary
+products with any compiler, but it doesn't seem especially useful to try to
+stop them from developing them with this compiler, so I am not going to.
+
+BYTE: Do your restrictions apply if people take pieces of your code to
+produce other things as well?
+
+Stallman: Yes, if they incorporate with changes any sizable piece. If it
+were two lines of code, that's nothing; copyright doesn't apply to that.
+Essentially, I have chosen these conditions so that first there is a
+copyright, which is what all the software hoarders use to stop everybody
+from doing anything, and then I add a notice giving up part of those
+rights. So the conditions talk only about the things that copyright applies
+to. I don't believe that the reason you should obey these conditions is
+because of the law. The reason you should obey is because an upright person
+when he distributes software encourages other people to share it further.
+
+BYTE: In a sense you are enticing people into this mode of thinking by
+providing all of these interesting tools that they can use but only if they
+buy into your philosophy.
+
+Stallman: Yes. You could also see it as using the legal system that
+software hoarders have set up against them. I'm using it to protect the
+public from them.
+
+BYTE: Given that manufacturers haven't wanted to fund the project, who do
+you think will use the GNU system when it is done?
+
+Stallman: I have no idea, but it is not an important question. My purpose
+is to make it possible for people to reject the chains that come with
+proprietary software. I know that there are people who want to do that.
+Now, there may be others who don't care, but they are not my concern. I
+feel a bit sad for them and for the people that they influence. Right now a
+person who perceives the unpleasantness of the terms of proprietary
+software feels that he is stuck and has no alternative except not to use a
+computer. Well, I am going to give him a comfortable alternative.
+ Other people may use the GNU system simply because it is technically
+superior. For example, my C compiler is producing about as good a code as I
+have seen from any C compiler. And GNU EMACS is generally regarded as being
+far superior to the commercial competition. And GNU EMACS was not funded by
+anyone either, but everyone is using it. I therefore think that many people
+will use the rest of the GNU system because of its technical advantages.
+But I would be doing a GNU system even if I didn't know how to make it
+technically better because I want it to be socially better. The GNU project
+is really a social project. It uses technical means to make a change in
+society.
+
+BYTE: Then it is fairly important to you that people adopt GNU. It is not
+just an academic exercise to produce this software to give it away to
+people. You hope it will change the way the software industry operates.
+
+Stallman: Yes. Some people say no one will ever use it because it doesn't
+have some attractive corporate logo on it, and other people say that they
+think it is tremendously important and everyone's going to want to use it.
+I have no way of knowing what is really going to happen. I don't know any
+other way to try to change the ugliness of the field that I find myself in,
+so this is what I have to do.
+
+BYTE: Can you address the implications? You obviously feel that this is an
+important political and social statement.
+
+Stallman: It is a change. I'm trying to change the way people approach
+knowledge and information in general. I think that to try to own knowledge,
+to try to control whether people are allowed to use it, or to try to stop
+other people from sharing it, is sabotage. It is an activity that benefits
+the person that does it at the cost of impoverishing all of society. One
+person gains one dollar by destroying two dollars' worth of wealth. I think
+a person with a conscience wouldn't do that sort of thing except perhaps if
+he would otherwise die. And of course the people who do this are fairly
+rich; I can only conclude that they are unscrupulous. I would like to see
+people get rewards for writing free software and for encouraging other
+people to use it. I don't want to see people get rewards for writing
+proprietary software because that is not really a contribution to society.
+The principle of capitalism is the idea that people manage to make money by
+producing things and thereby are encouraged to do what is useful,
+automatically, so to speak. But that doesn't work when it comes to owning
+knowledge. They are encouraged to do not really what's useful, and what
+really is useful is not encouraged. I think it is important to say that
+information is different from material objects like cars and loaves of
+bread because people can copy it and share it on their own and, if nobody
+attempts to stop them, they can change it and make it better for
+themselves. That is a useful thing for people to do. This isn't true of
+loaves of bread. If you have one loaf of bread and you want another, you
+can't just put your loaf of bread into a bread copier. you can't make
+another one except by going through all the steps that were used to make
+the first one. It therefore is irrelevant whether people are permitted to
+copy it--it's impossible.
+ Books were printed only on printing presses until recently. It was
+possible to make a copy yourself by hand, but it wasn't practical because
+it took so much more work than using a printing press. And it produced
+something so much less attractive that, for all intents and purposes, you
+could act as if it were impossible to make books except by mass producing
+them. And therefore copyright didn't really take any freedom away from the
+reading public. There wasn't anything that a book purchaser could do that
+was forbidden by copyright.
+ But this isn't true for computer programs. It's also not true for tape
+cassettes. It's partly false now for books, but it is still true that for
+most books it is more expensive and certainly a lot more work to Xerox them
+than to buy a copy, and the result is still less attractive. Right now we
+are in a period where the situation that made copyright harmless and
+acceptable is changing to a situation where copyright will become
+destructive and intolerable. So the people who are slandered as "pirates"
+are in fact the people who are trying to do something useful that they have
+been forbidden to do. The copyright laws are entirely designed to help
+people take complete control over the use of some information for their own
+good. But they aren't designed to help people who want to make sure that
+the information is accessible to the public and stop others from depriving
+the public. I think that the law should recognize a class of works that are
+owned by the public, which is different from public domain in the same
+sense that a public park is different from something found in a garbage
+can. It's not there for anybody to take away, it's there for everyone to
+use but for no one to impede. Anybody in the public who finds himself being
+deprived of the derivative work of something owned by the public should be
+able to sue about it.
+
+BYTE: But aren't pirates interested in getting copies of programs because
+they want to use those programs, not because they want to use that
+knowledge to produce something better?
+
+Stallman: I don't see that that's the important distinction. More people
+using a program means that the program contributes more to society. You
+have a loaf of bread that could be eaten either once or a million times.
+
+BYTE: Some users buy commercial software to obtain support. How does your
+distribution scheme provide support?
+
+Stallman: I suspect that those users are misled and are not thinking
+clearly. It is certainly useful to have support, but when they start
+thinking about how that has something to do with selling software or with
+the software being proprietary, at that point they are confusing
+themselves. There is no guarantee that proprietary software will receive
+good support. Simply because sellers say that they provide support, that
+doesn't mean it will be any good. And they may go out of business. In fact,
+people think that GNU EMACS has better support than commercial EMACSes. One
+of the reasons is that I'm probably a better hacker than the people who
+wrote the other EMACSes, but the other reason is that everyone has sources
+and there are so many people interested in figuring out how to do things
+with it that you don't have to get your support from me. Even just the free
+support that consists of my fixing bugs people report to me and
+incorporating that in the next release has given people a good level of
+support. You can always hire somebody to solve a problem for you, and when
+the software is free you have a competitive market for the support. You can
+hire anybody. I distribute a service list with EMACS, a list of people's
+names and phone numbers and what they charge to provide support.
+
+BYTE: Do you collect their bug fixes?
+
+Stallman: Well, they send them to me. I asked all the people who wanted to
+be listed to promise that they would never ask any of their customers to
+keep secret whatever they were told or any changes they were given to the
+GNU software as part of that support.
+
+BYTE: So you can't have people competing to provide support based on their
+knowing the solution to some problem that somebody else doesn't know.
+
+Stallman: No. They can compete based on their being clever and more likely
+to find the solution to your problem, or their already understanding more
+of the common problems, or knowing better how to explain to you what you
+should do. These are all ways they can compete. They can try to do better,
+but they cannot actively impede their competitors.
+
+BYTE: I suppose it's like buying a car. You're not forced to go back to the
+original manufacturer for support or continued maintenance.
+
+Stallman: Or buying a house--what would it be like if the only person who
+could ever fix problems with your house was the contractor who built it
+originally? That is the kind of imposition that's involved in proprietary
+software. People tell me about a problem that happens in UNIX. Because
+manufacturers sell improved versions of UNIX, they tend to collect fixes
+and not give them out except in binaries. The result is that the bugs don't
+really get fixed.
+
+BYTE: They're all duplicating effort trying to solve bugs independently.
+
+Stallman: Yes. Here is another point that helps put the problem of
+proprietary information in a social perspective. Think about the liability
+insurance crisis. In order to get any compensation from society, an injured
+person has to hire a lawyer and split the money with that lawyer. This is a
+stupid and inefficient way of helping out people who are victims of
+accidents. And consider all the time that people put into hustling to take
+business away from their competition. Think of the pens that are packaged
+in large cardboard packages that cost more than the pen--just to make sure
+that the pen isn't stolen. Wouldn't it be better if we just put free pens
+on every street corner? And think of all the toll booths that impede the
+flow of traffic. It's a gigantic social phenomenon. People find ways of
+getting money by impeding society. Once they can impede society, they can
+be paid to leave people alone. The waste inherent in owning information
+will become more and more important and will ultimately make the difference
+between the utopia in which nobody really has to work for a living because
+it's all done by robots and a world just like ours where everyone spends
+much time replicating what the next fellow is doing.
+
+BYTE: Like typing in copyright notices on the software.
+
+Stallman: More like policing everyone to make sure that they don't have
+forbidden copies of anything and duplicating all the work people have
+already done because it is proprietary.
+
+BYTE: A cynic might wonder how you earn your living.
+
+Stallman: From consulting. When I do consulting, I always reserve the right
+to give away what I wrote for the consulting job. Also, I could be making
+my living by mailing copies of the free software that I wrote and some that
+other people wrote. Lots of people send in $150 for GNU EMACS, but now this
+money goes to the Free Software Foundation that I started. The foundation
+doesn't pay me a salary because it would be a conflict of interest.
+Instead, it hires other people to work on GNU. As long as I can go on
+making a living by consulting I think that's the best way.
+
+BYTE: What is currently included in the official GNU distribution tape?
+
+Stallman: Right now the tape contains GNU EMACS (one version fits all
+computers); Bison, a program that replaces YACC; MIT Scheme, which is
+Professor Sussman's super-simplified dialect of LISP; and Hack, a
+dungeon-exploring game similar to Rogue.
+
+BYTE: Does the printed manual come with the tape as well?
+
+Stallman: No. Printed manuals cost $15 each or copy them yourself. Copy
+this interview and share it, too.
+
+BYTE: How can you get a copy of that?
+
+Stallman: Write to the Free Software Foundation, 675 Massachusetts Ave.,
+Cambridge, MA 02139.
+
+BYTE: What are you going to do when you are done with the GNU system?
+
+Stallman: I'm not sure. Sometimes I think that what I'll go on to do is the
+same thing in other areas of software.
+
+BYTE: So this is just the first of a whole series of assaults on the
+software industry?
+
+Stallman: I hope so. But perhaps what I'll do is just live a life of ease
+working a little bit of the time just to live. I don't have to live
+expensively. The rest of the time I can find interesting people to hang
+around with or learn to do things that I don't know how to do.
+
+Editorial Note: BYTE holds the right to provide this interview on BIX but
+will not interfere with its distribution.
+
+Richard Stallman, 545 Technology Square, Room 703, Cambridge, MA 02139.
+Copyright (C) 1986 Richard Stallman. Permission is granted to make and
+distribute copies of this article as long as the copyright and this notice
+appear on all copies.
diff --git a/etc/LEDIT b/etc/LEDIT
new file mode 100644
index 00000000000..ff274ce46bf
--- /dev/null
+++ b/etc/LEDIT
@@ -0,0 +1,77 @@
+Date: 17 Apr 85 15:45:42 EST (Wed)
+From: Martin David Connor <mdc@MIT-HTVAX.ARPA>
+
+ Date: Sat, 13 Apr 85 16:28:15 est
+ From: Richard M. Stallman <rms@mit-prep>
+
+ Can you help this person? Also, can you give me the rest of ledit
+ to distribute, plus some info on how to use it?
+
+I have put the files "ledit.l" and "leditcfns.c" on prep:~mdc.
+Much to my disgust ledit.l relied on some bogus little package of
+functions on HT, so I had to massage it a bit.
+
+To get it to work, one must:
+
+ - Compile leditcfns.c with something like:
+
+ cc leditcfns.c
+
+ - Edit ledit.l, changing the line beginning "(cfasl" to
+ have the right pathname for the cfns file you compiled in
+ the last step.
+
+ - Compile ledit.l with:
+
+ liszt ledit.l
+
+Then put the following lines in your .lisprc file:
+
+ ;load in functions for emacs interface
+ (load "//src//mdc//ledit//ledit") ; Location of Ledit library
+ (set-proc-str "%gnumacs") ; Name of editor
+
+Then you can use ^E <RETURN> to get from LISP back to gnumacs.
+
+Here is the part of my .emacs file that pertains to ledit.
+
+ ;;; Set up ledit mode
+ (setq ledit-go-to-lisp-string "%lisp")
+ (setq lisp-mode-hook 'ledit-from-lisp-mode)
+
+ Date: Sat, 13 Apr 85 11:26:32 cst
+ From: neves@wisc-ai.arpa (David Neves)
+
+ This is a documentation question.
+ I cannot figure out how to use Ledit. I suspect I need some
+ function on the Franz Lisp end of things to go to Emacs and read in
+ the temporary file. Is this true? Is the Lisp job started within
+ Emacs or outside of emacs? I'm just plain confused. Perhaps a couple
+ of words from someone in the know would help.
+
+ A related question. I have been using a shell buffer when interacting
+ with Lisp (ie. put a definition in the kill buffer and then yank it
+ into the shell buffer to redefine it). This is nice but tends to fill
+ up the shell buffer with lots of code (I'd rather keep calls to functions
+ in the shell and not the functions themselves).
+ My question: Is using the shell buffer "better" than ledit? Am I using
+ it in the best way (i.e. copying definitions from an edit buffer to the
+ shell buffer)? -Thanks, David Neves
+
+I have found that ledit works well for doing programming development
+when you are changing lots of little pieces of a file and don't wish
+to recompile the whole file. Of course M-X Compile is very nice for
+calling up a liszt on a buffer and watching it in the another window.
+Of course the interface of something like NIL is even better because
+you can compile your function directly into your lisp. But since NIL
+doesn't run under Unix, this is probably the next best thing.
+
+I have tried the 2 window method (shell in lower window, lisp code in
+upper), and have found it a little awkward. It does have certain
+advantages, but most of the time, I get be fine using M-C-D to save a
+defun for lisp, and C-X Z to jump back to LISP. C-E RETURN from lisp
+is also mnemonic for getting back to gnumacs.
+
+I hope this helps somewhat.
+
+
diff --git a/etc/LPF b/etc/LPF
new file mode 100644
index 00000000000..e5c020b3cec
--- /dev/null
+++ b/etc/LPF
@@ -0,0 +1,122 @@
+ Protect Your Freedom to Write Programs
+ Join the League for Programming Freedom
+ (Version of January 15, 1991)
+
+Ten years ago, programmers were allowed to write programs using all
+the techniques they knew, and providing whatever features they felt
+were useful. This is no longer the case. The new monopolies,
+software patents and interface copyrights, have taken away our
+freedom of expression and our ability to do a good job.
+
+"Look and feel" lawsuits attempt to monopolize well-known command
+languages; some have succeeded. Copyrights on command languages
+enforce gratuitous incompatibility, close opportunities for
+competition, and stifle incremental improvements.
+
+Software patents are even more dangerous; they make every design
+decision in the development of a program carry a risk of a lawsuit,
+with draconian pretrial seizure. It is difficult and expensive to
+find out whether the techniques you consider using are patented; it is
+impossible to find out whether they will be patented in the future.
+
+The League for Programming Freedom is a grass-roots organization of
+professors, students, businessmen, programmers and users dedicated to
+bringing back the freedom to write programs. The League is not
+opposed to the legal system that Congress intended--copyright on
+individual programs. Our aim is to reverse the recent changes made by
+judges in response to special interests, often explicitly rejecting
+the public interest principles of the Constitution.
+
+The League works to abolish the new monopolies by publishing articles,
+talking with public officials, boycotting egregious offenders, and in
+the future may intervene in court cases. On May 24, 1989, the League
+picketed Lotus headquarters on account of their lawsuits, and then
+again on August 2, 1990. These marches stimulated widespread media
+coverage for the issue. We welcome suggestions for other activities,
+as well as help in carrying them out.
+
+Membership dues in the League are $42 per year for programmers,
+managers and professionals; $10.50 for students; $21 for others.
+Please give more if you can. The League's funds will be used for
+filing briefs; for printing handouts, buttons and signs; whatever will
+persuade the courts, the legislators, and the people. You may not get
+anything personally for your dues--except for the freedom to write
+programs. The League is a non-profit corporation, but not considered
+a tax-exempt charity. However, for those self-employed in software,
+the dues can be a business expense.
+
+The League needs both activist members and members who only pay their
+dues. We also greatly need additional corporate members; contact us
+for information.
+
+If you have any questions, please write to the League or phone
+(617) 243-4091. Or send Internet mail to league@prep.ai.mit.edu.
+
+ Jack Larsen, President
+ Chris Hofstader, Secretary
+ Steve Sisak, Treasurer
+
+Jack Larsen can be contacted at (708) 698-1160; Fax (708) 698-6221.
+ To join, please send a check and the following information to:
+
+ League for Programming Freedom
+ 1 Kendall Square #143
+ P.O.Box 9171
+ Cambridge, Massachusetts 02139
+
+(Outside the US, please send a check in US dollars on a bank
+having a US correspondant bank, to save us check cashing fees.)
+
+Your name:
+
+
+The address for League mailings (a few each year):
+
+
+
+The company you work for, and your position:
+
+
+Your phone numbers (home, work or both):
+
+
+Your email address, so we can contact you for demonstrations or for
+writing letters. (If you don't want us to contact you for these
+things, please say so, but please give us your email address anyway.)
+
+
+Is there anything about you which would enable your endorsement of the
+LPF to impress the public? For example, if you are or have been a
+professor or an executive, or have written software that has a good
+reputation, please tell us.
+
+
+
+Would you like to help with LPF activities?
+
+
+
+
+The corporate charter of the League for Programming Freedom states:
+
+ The purpose of the corporation is to engage in the following
+ activities:
+
+ 1. To determine the existence of, and warn the public about
+ restrictions and monopolies on classes of computer programs where such
+ monopolies prevent or restrict the right to develop certain types of
+ computer programs.
+
+ 2. To develop countermeasures and initiatives, in the public interest,
+ effective to block or otherwise prevent or restrain such monopolistic
+ activities including education, research, publications, public
+ assembly, legislative testimony, and intervention in court proceedings
+ involving public interest issues (as a friend of the court).
+
+ 3. To engage in any business or other activity in service of and
+ related to the foregoing paragraphs that lawfully may be carried on
+ by a corporation organized under Chapter 180 of the Massachusetts
+ General Laws.
+
+The officers and directors of the League will be elected annually by
+the members.
diff --git a/etc/MACHINES b/etc/MACHINES
index 01eebd5a2ee..d118bc76921 100644
--- a/etc/MACHINES
+++ b/etc/MACHINES
@@ -1,5 +1,5 @@
This is a list of the status of GNU Emacs on various machines and systems.
-Last updated 27 December 1990.
+Last updated 18 Oct 1992.
Systems:
For each type of system, the name of the appropriate s- header file
@@ -21,6 +21,10 @@ Microport
See under "Intel 386".
+Solaris (s-sol2.h)
+
+ Changes merged, and may work.
+
System V rel 0 (s-usg5-0.h)
Works, on Vaxes and 3bxxx's.
@@ -41,6 +45,9 @@ System V rel 2 (s-usg5-2.h)
and make it store 7 there. I have as yet no evidence of whether
this problem, known in HP-UX, exists in other system V versions.
+ If you are compiling to work with X11 release 4, you may need
+ to define HAVE_RANDOM in config.h.
+
System V rel 2.2 (s-usg5-2-2.h)
In 5.2.2 AT&T undid, incompatibly, their previous incompatible
@@ -54,31 +61,50 @@ System V rel 2.2 (s-usg5-2-2.h)
NO_REMAP. It is not yet known whether this applies to all
machines running 5.2.2.
+ If you are compiling to work with X11 release 4, you may need
+ to define HAVE_RANDOM in config.h.
+
System V rel 3 (s-usg5-3.h)
Some versions of this system support ptys and BSD-style sockets.
On such systems, you should define HAVE_PTYS and HAVE_SOCKETS in config.h.
+ If you are compiling to work with X11 release 4, you may need
+ to define HAVE_RANDOM in config.h.
+
If you want to link Emacs with shared libraries, define
USG_SHARED_LIBRARIES.
System V rel 4 (s-usg5-4.h)
- Supported, including shared libraries for ELF, but ptys do not
- work because TIOCGPGRP fails to work on ptys.
- This failure is probably due to a misunderstanding of the
- consequences of the POSIX spec: many system designers mistakenly
- think that POSIX requires this feature to fail. This is untrue;
- ptys are an extension, and POSIX says that extensions *when used*
- may change the action of standard facilities in any fashion.
+ Supported, including shared libraries for ELF. pty's work now.
+
+ The standard C preprocessor generates xmakefile incorrectly. However,
+ /lib/cpp will work, so use `make CPP=/lib/cpp' in the `src' subdirectory.
- The standard C preprocessor generate xmakefile incorrectly. However,
- /lib/cpp will work, so use `make CPP=/lib/cpp'.
+ Versions 3 and earlier of V.4, on the Intel 386 and 860, had
+ problems in the X11 libraries. These prevent Emacs from working
+ with X. You can use Emacs with X provided your copy of X is based
+ on X11 release 4 or newer. Unfortunately, the only way you can tell
+ for certain whether your X11 library is new enough is to try
+ compiling Emacs to use X. If xemacs runs, your X11 library is new
+ enough.
-Ultrix (s-bsd4-2.h)
+ In this context, GSV4 and GSV4i are alternate names for X11R4.
+ OL2.* is X11R3 based. OL3 is in between X11R3 and X11R4, and may or
+ may not work, depending on who made the Unix system. If the library
+ libXol is part of the X distribution, then you have X11R3 and Emacs
+ won't work with X.
- DEC's Ultrix OS is essentially Berkeley 4.2. It does not correctly
- implement certain features of 4.3.
+ Most versions of V.4 support sockets. If `/usr/lib/libsocket.so'
+ exists, your system supports them. If yours does not, you must add
+ #undef HAVE_SOCKETS in config.h, aftern the inclusion of s-usg5-4.h.
+ (Any system that supports Internet should implement sockets.)
+
+Ultrix (s-bsd4-3.h)
+
+ Recent versions of Ultrix appear to support the features of Berkeley 4.3.
+ Ultrix was at the BSD 4.2 level for a long time after BSD 4.3 came out.
Ultrix 3.0 has incompatibilities in its X library if you have the
Ultrix version of X (UWS version 2.0). To solve them, you need to
@@ -96,16 +122,19 @@ Ultrix (s-bsd4-2.h)
The problem is said to be gone in UWS version 2.1.
+ Ultrix 4.1 has moved the file X11/X10.h into mit/X11/X10.h.
+
Uniplus 5.2 (s-unipl5-2.h)
Works, on Dual machines at least.
-VMS (s-vms.h)
+VMS (s-vms4-0.h, s-vms4-2.h, s-vms4-4.h, s-vms5-5.h)
Works except for certain features (directory listing, dired,
sending and receiving mail) that use synchronous subprocesses.
- We need people to write alternative implementations of these
- facilities.
+ (These will work in Emacs 19.)
+ s-vms5-5.h may be right for some earlier versions; please let us know
+ what happens when you try it in VMS versions 5.0 thru 5.4.
Note that Emacs for VMS is usually distributed in a special
VMS distribution. See the file ../VMSINSTALL for info on moving
@@ -128,27 +157,36 @@ Machines:
For each type of machine, the names of the m- and s- header files
are given.
-Alliant (m-alliant4.h or m-alliant.h or m-alliant1.h; s-bsd4-2.h)
+Alliant FX/80 (m-alliant4.h or m-alliant.h or m-alliant1.h;
+ s-bsd4-2.h or s-bsd4-3.h)
- 18.52 works on system version 4. Previous Emacs versions were
+ There are reports of bugs in the Alliant compiler
+ that prevent compiling Emacs 18.57.
+ No word on how to get around them. Perhaps using GCC will work.
+ A work-around is installed in src/dispnew.c in 18.58 for a compiler bug.
+
+ 18.52 worked on system version 4. Previous Emacs versions were
known to work on previous system versions.
Use m-alliant1.h on version 1 of their operating system
and use m-alliant.h on version 2 or 3.
- Use m-alliant4.h on version 4.
+ Use m-alliant4.h on version 4 and above.
+
+ Use s-bsd4-3.h with system version 5 and above.
+
+Alliant FX/2800 (m-all2800.h; s-bsd4-3.h)
+
+ Known to work with 18.58 and OS version 2.2, compiler version 1.3.
Altos 3068 (m-altos.h; s-usg5-2.h)
18.52 is said to work, provided you don't compile unexec.c with -O.
-Amdahl UTS (m-amdahl.h; s-usg5-2-2.h)
+Amdahl UTS (m-amdahl.h; s-usg5-3.h)
- Small changes for 18.38 were merged in 18.39. It is mostly
- working, but at last report a bug sometimes causes Emacs to
- grab very large amounts of memory. No fix or explanation
- has yet been reported. It may be possible to find this bug
- if you find which Emacs command it happens within and then
- run that command with a breakpoint set at malloc.
+ Support for a newer system version, and X Windows, merged in 18.58.
+ (Some people report that s-usg5-2.h worked better than s-usg5-3.h
+ for 18.57.)
The 5.2u370 compiler is so brain damaged that it is not
even worth trying to use it. Success was obtained with the
@@ -161,7 +199,7 @@ Apollo running Domain (m-apollo.h; s-bsd4-2.h)
distribute it yet.
There are reports of bugs in cc -O on this system.
- In etc/Makefile, don't expect emacsclient and emacsserver to
+ In etc/Makefile, don't expect emacsclient and server to
compile. You might want to remove them from your makefile.
Supposedly something in dired.c runs into a compiler bug.
@@ -199,9 +237,19 @@ AT&T 7300 or 3b1 (m-7300.h; s-usg5-2-2.h)
older than 3.5 did not support long symbol names. Version 3.5 does
support them, so you can remove the #define SHORTNAMES in that version.
-Bull sps7 (m-sps7.h; s-usg5-2.h)
+Aviion (m-aviion.h; s-dgux.h)
+
+ Changes merged in 18.58.
+
+Bull DPX/2 models 2nn or 3nn (m-dpx2-200.h or m-dpx2-300.h; s-usg5-3.h)
+
+ Should work in 18.58 except that there is a report of
+ Emacs terminating mysteriously if run in the background
+ using its own X window and the invoking process
+ terminates.
- Changes partially merged in version 19, but some fixes are probably required.
+ Be sure to read m-dpx2.h for instructions as to how to deal
+ with optional packages such as INET and X Windows.
CCI 5/32, 6/32
@@ -211,35 +259,30 @@ Celerity (m-celerity.h; s-bsd4-2.h)
Version 18.49 works.
-Clipper (m-clipper.h; ???)
-
- Version 19 has support for some brand of clipper system.
- Note that the Orion 105 is also a clipper, but some system-related
- parameters are different.
-
Convex (m-convex.h; s-bsd4-3.h)
- 18.53 is supposed to work.
-
-Cubix QBx/386 (m-intel386.h; s-usg5-3.h)
-
- Changes merged in 19.1. Systems before 2/A/0 may fail to compile etags.c
- due to a compiler bug.
+ 18.58 works.
+ Use "make CC='cc -pcc'" to avoid problems creating ymakefile from xmakefile.
Cydra 5 (m-cydra5.h; s-usg5-3.h)
18.51 worked in one version of their operating system but stopped
working in a newer version. This has not been fixed.
-DECstation (m-pmax.h; s-bsd4-2.h)
+Data General
- Works, as of 18.55. See under Ultrix for problems using X windows
- on Ultrix. Note that this is a MIPS machine.
+ See aviion.
-Delta (m-delta.h; s-usg5-3.h)
+DECstation (m-pmax.h; s-bsd4-3.h or s-osf1.h)
- Motorola Delta boxes running System V/68 release 3.
- (tested on sys1147 with SVR3V5). Changes merged in 19.1.
+ OSF1 support merged in 18.59.
+
+ See under Ultrix for problems using X windows
+ on Ultrix. Note that this is a MIPS machine.
+ s-bsd4-3.h is said to work ok with Ultrix 4.1.
+
+ For Ultrix versions prior to 4.0, you may need to delete
+ the definition of START_FILES from m-pmax.h.
Dual running System V (m-dual.h; s-usg5-2.h)
@@ -252,8 +295,13 @@ Dual running Uniplus (m-dual.h; s-unipl5-2.h)
Elxsi 6400 (m-elxsi; s-usg5-2.h)
- Changes for 12.0 release are in 19.1.
- Dumping should work now.
+ 18.36 required one small change that's installed in 18.38.
+
+ m-elxsi.h currenty specifies CANNOT_DUMP.
+ The Elxsi can in principle dump, but the necessary changes to
+ unexec, which involve byte-swapping, were too ugly to install.
+ If someone submits simple code that supports dumping on the Elxsi,
+ it can be installed and CANNOT_DUMP can be turned off.
Encore machine (m-ns16000.h; s-umax.h)
@@ -269,12 +317,16 @@ Encore machine (m-ns16000.h; s-umax.h)
A kernel bug in some system versions causes input characters to be lost
occasionally.
+Encore running MACH.
+
+ This does not yet work.
+
GEC 93 (m-gec93.h; s-usg5-2.h?)
Changes are partially merged in version 18, but
certainly require more work.
-Gould Power Node (m-gould.h; s-bsd4-2.h or s-bsd4-3.h)
+Gould (m-gould.h; s-bsd4-2.h or s-bsd4-3.h)
18.36 worked on versions 1.2 and 2.0 of the operating system.
@@ -287,26 +339,24 @@ Gould Power Node (m-gould.h; s-bsd4-2.h or s-bsd4-3.h)
UTX/32 1.3 has a bug in the bcopy library routine. Fix it by
#undef BSTRING in m-gould.h.
- Version 19 incorporates support for releases 2.1 and later of UTX/32.
- A site running a pre-release of 2.1 should #define RELEASE2_1 in config.h.
-
-Gould NP1 (m-gould-np1.h; s-bsd4-3.h)
-
- Version 19 supposedly works.
-
-Honeywell XPS100 (m-xps100.h; s-usg5-2.h)
-
- Config file added in version 19.
-
-HP 9000 series 200 or 300 (m-hp9000s300.h; s-hpux.h or s-bsd4-3.h)
+HP 9000 series 200 or 300 (m-hp9000s300.h; s-hpux7.h, s-hpux8.h or s-bsd4-3.h)
Version 18 works.
These machines are 68000-series CPUs running HP-UX
(a derivative of sysV with some BSD features) or BSD 4.3 ported by Utah.
The choice of s- file determines which system Emacs is built for.
+ If you are running HP-UX release 8.0 or later, you need the optional
+ "C/ANSI C" software in order to build Emacs (older releases of HP-UX
+ do not require any special software). If the file "/etc/filesets/C"
+ exists on your machine, you have this software, otherwise you do not.
+
Series 200 HPUX runs Emacs only if it has the "HP-UX upgrade".
+ The series 500 has a seriously incompatible memory architecture
+ which relocates data in memory during execution of a program,
+ and support for it would be difficult to implement.
+
Note that HP has used two incompatible assembler syntaxes,
and has recently changed the format of C function frames.
src/crt0.c and src/alloca.s have been conditionalised for the new
@@ -328,21 +378,28 @@ HP 9000 series 200 or 300 (m-hp9000s300.h; s-hpux.h or s-bsd4-3.h)
that include the `netunam' system call. This is refered to as
Network Services (NS/9000) in HP literature.
-HP 9000 series 300 running BSD 4.3 (m-hp300bsd.h; s-bsd4-3.h)
+ If you are compiling to work with X11 release 4, you may need
+ to define HAVE_RANDOM in config.h.
- Version 18.55 works.
+HP 9000 series 700 or 800 (Spectrum) (m-hp9000s800.h; s-hpux7.h or s-hpux8.h)
-HP 9000 series 500: not supported.
+ These files support HP's Precision Architecture machines
+ running HP-UX. Version 18.58 should work on the 700 and the 800.
+ Use s-hpux7.h for HPUX version 7 or earlier,
+ and s-hpux8.h for HPUX version 8.
+ If you are running HP-UX release 8.0 or later, you need the optional
+ "C/ANSI C" software in order to build Emacs (older releases of HP-UX
+ do not require any special software). If the file "/etc/filesets/C"
+ exists on your machine, you have this software, otherwise you do not.
- The series 500 has a seriously incompatible memory architecture
- which relocates data in memory during execution of a program,
- and support for it would be difficult to implement.
+ HAVE_X_MENU works, but you may need to modify oldXMenu/Makefile
+ to compile insque.c.
-HP 9000 series 800 (Spectrum) (m-hp9000s800.h; s-hpux.h)
+ If you compile with MIT's X11R5, rather than HP's version,
+ then you may need to add the following to config.h:
- These files support HP's Precision Architecture machines
- running HP-UX. It has been moderately tested on the Series
- 840.
+ #define srandom srand
+ #define random rand
High Level Hardware Orion (m-orion.h; s-bsd4-2.h)
@@ -352,30 +409,34 @@ High Level Hardware Orion (m-orion.h; s-bsd4-2.h)
High Level Hardware Orion 1/05 (m-orion105.h; s-bsd4-2.h)
Changes merged in 18.52. This is the one with the Clipper cpu.
- Note that systems which lack NFS need LOAD_AVE_TYPE changed to `double'.
+ Note that systems which lack NFS may need LOAD_AVE_TYPE changed to `double'.
- C compiler has a bug; it loops compiling eval.c.
- Compile it by hand without optimization.
+ In 18.58, trouble was reported with X windows: XrmGetResource was
+ reported undefined in the library. You may need to change
+ XT_GetDefaults in x11term.c to make it link. If so, please
+ send a bug report saying exactly what change was needed.
-IBM PS/2 (m-ibmps2-aix.h; s-usg5-2-2.h)
+IBM PS2 (m-ibmps2-aix.h; s-usg5-2-2.h or s-usg5-3.h)
- Changes merged in version 19. You may need to copy
+ Changes mostly merged in 18.55. You may need to put an #ifndef AIX
+ conditional around the definition of closedir in sysdep.c, and
+ perhaps delete the #include of sioctl.h. You may need to copy
/usr/lib/samples/hft/hftctl.c to the Emacs src directory.
-IBM RS/6000 (m-ibmrs6000.h; s-aix3-1.h)
+ Use s-usg5-3.h on AIX 1.2.
+ s-usg5-2-2.h should work on either AIX 1.1 or 1.2, but may not work with
+ certain new X window managers, and may be suboptimal.
- Changes merged in version 19.
+IBM RS/6000 (m-ibmrs6000.h; s-aix3-1.h or s-aix3-2.h)
- Dumping does not work. Code has been written to implement it, but
- it fails because the address of bss seems to vary occasionally
- between Emacs runs. It does not seem to vary from minute to minute,
- but every few days or weeks it changes to a new steady state.
- When this happens, the dumped Emacs data file becomes invalid.
+ Changes merged in 18.56. Note that for installation on AIX you must
+ use `make install.aix' rather than just `make'. Use s-aix3-2.h
+ on AIX 3.2 also.
-IBM RT/PC (m-ibmrt.h or m-ibmrt-aix.h; s-bsd4-2.h or s-usg5-2-2.h)
+IBM RT/PC (m-ibmrt.h or m-ibmrt-aix.h; s-bsd4-3.h or s-usg5-2-2.h)
18.52 works on both operating systems.
- Use s-bsd-4-2.h for the 4.2-like system and s-usg5-2-2.h for AIX.
+ Use s-bsd-4-3.h for the 4.3-like system AOS, and s-usg5-2-2.h for AIX.
On BSD, if you have trouble, try compiling with a different compiler.
@@ -401,10 +462,27 @@ Integrated Solutions `Optimum V' (m-isi-ov.h; s-bsd4-2.h or s-bsd4-3.h)
in a system header file, which confuses Emacs (which thinks that UMAX
indicates the Umax operating system).
-Intel 80386 (m-intel386.h or m-is386.h; s-bsd4-2.h, s-usg5-2-2.h, s-usg5-3.h,
- s-386-ix.h, s-esix.h or s-xenix.h)
+Integrated Solutions 386 (m-is386.h; ??)
+
+ Configuration file present in 18.57.
+
+Intel 80386 (m-intel386.h; s-bsd4-2.h, s-usg5-2-2.h, s-usg5-3.h, s-esix.h,
+ s-386ix.h, s-isc2-2.h, s-isc3-0.h, s-sco3-2-2.h, s-sco3-2-4.h,
+ or s-xenix.h)
+
+ 18.59 should support a wide variety of operating systems.
+ Use s-isc2-2.h for Interactive 386/ix version 2.2
+ and s-isc3-0.h for versions 3.0 and 3.2.
+ Use s-386ix.h for prior versions.
+ Use s-esix.h for Esix.
+
+ Use s-sco3-2-4.h for version 3.2.4, and s-sco3-2-2.h for version 3.2.2
+ (but it only makes a difference if you compile Emacs for X windows).
+ You may have to compile the cpp that comes with Emacs
+ and use that to preprocess src/ymakefile to get src/xmakefile.
+ s-sco3-2-1.h may work on SCO 3.2.1, but see the instructions in
+ that file for other changes you need to make.
- Changes merged in 18.50 for all three operating systems.
If you are using Xenix, see notes above under Xenix.
Some sysV.3 systems seem to have bugs in `opendir';
@@ -412,11 +490,20 @@ Intel 80386 (m-intel386.h or m-is386.h; s-bsd4-2.h, s-usg5-2-2.h, s-usg5-3.h,
and undefine SYSV_SYSTEM_DIR.
If you use optimization on V.3, you may need the option -W2,'-y 0'
- to prevent certain faulty optimization.
+ to prevent certain faulty optimization. Otherwise, fns.c won't work.
On 386/ix, to link with shared libraries, add #define USG_SHARED_LIBRARIES
to config.h.
+ On one V.4 system, it was necessary to define LIBS_TERMCAP as -ltermcap.
+
+ Versions 3 and earlier of V.4 supposedly have problems
+ in the X11 libraries that prevent Emacs from working with X.
+ Version 4 of V.4 is said to have fixed this problem. See the
+ entry for System V Release 4, above. Similar problems occur on
+ SCO systems and perhaps also on ISC systems. There is no known
+ remedy except to get a different system.
+
There is no consistency in the handling of certain system header files
on V.3.
@@ -436,34 +523,34 @@ Intel 80386 (m-intel386.h or m-is386.h; s-bsd4-2.h, s-usg5-2-2.h, s-usg5-3.h,
Some versions convince sysdep.c to try to use `struct tchars'
but define `struct tc' instead; add `#define tchars tc'
to config.h to solve this problem.
+ Some systems have problems that can be solved by inserting
+ #undef TIOCGETC
+ in sysdep.c, near the place where this is done for XENIX.
- The file m-is386.h is used for an Integrated Solutions 386 machine.
- It may also be correct for Microport systems.
+Intel 860 (m-intel860.h; s-usg5-4.h)
-Iris 2500 (m-irist.h; s-iris3-5.h or s-iris3-6.h)
+ Supposed to work in 18.58. See the notes for System V Release 4,
+ above, for notes on using X windows and using sockets.
- Version 18 said to work; use s-irist3-5.h for system version 2.5
- and s-iris3-6.h for system version 3.6.
-
-Iris 2500 Turbo (m-irist.h; s-iris3-5.h or s-iris3-6.h)
-
- 18.49 works. Use s-iris3-6.h for system versions 3.6 and up.
- Note that the 3030 is the same machine as this.
+Iris 4D (m-iris4d.h; s-irix3-3.h or s-irix4-0.h)
-Iris 4D (m-iris4d.h; s-iris3-6.h or s-irix3-3.h)
+ 18.58 is known to work on Silicon Graphics 4D series machines
+ with IRIX 3.3 or IRIX 4.0.
- 18.56 is known to work on 4D series machines with Irix 3.3 or later.
-
- If you use the X menu facility, you must edit oldXmenu/Makefile
- to add the line
+ Most irix3.3 systems do not have an ANSI C compiler, but a few do.
+ If you are using the ANSI C compiler, you may need to add
+ #define C_SWITCH_MACHINE -cckr
+ to config.h.
- RANLIB=true
+ There is a bug in IRIX that can sometimes leave ptys owned by
+ root with a permission of 622. This causes malfunctions in use
+ of subprocesses of Emacs. This may be fixed in IRIX 4.0.5.
- Someone says that with the yellow pages you must change two definitions
- in m-iris4d.h as follows:
+Iris 2500 Turbo (m-irist.h; s-iris3-5.h or s-iris3-6.h)
- #define LIBS_MACHINE -lsun -lbsd -lPW -lmld
- #define C_SWITCH_MACHINE -I/usr/include/sun -I/usr/include/bsd
+ 18.49 works. Use s-iris3-6.h for system versions 3.6 and up.
+ s-iris3-5.h is said to work with system version 2.5.
+ Note that the 3030 is the same machine as this.
Macintosh
@@ -505,10 +592,35 @@ Mips (m-mips.h or m-mips4.h; s-usg5-2-2.h, s-bsd4-3.h)
Use m-mips4.h for RISCOS version 4; use s-bsd4-3.h with the BSD world.
-Motorola Delta (m-delta.h; s-usg5-3.h)
+ If you are compiling with GCC, then you must run fixincludes;
+ the alternative of using -traditional won't work because
+ the definition of SIGN_EXTEND_CHAR uses the keyword `signed'.
+
+ If the SYSV world is the default, then you probably need the following
+ line in etc/Makefile:
+
+ CFLAGS= -g -systype bsd43
+
+ Some operating systems on MIPS machines give SIGTRAP for division by
+ zero instead of the usual signals. The only real solution is to fix
+ the system to give a proper signal.
+
+ In the meantime, you can change init_data in data.c if you wish.
+ Change it to handle SIGTRAP as well as SIGFPE. But this will have a
+ great disadvantage: you will not be able to run Emacs under a
+ debugger. I think crashing on division by zero is a lesser problem.
+
+ Note that the proper m- file for the Decstation is m-pmax.h.
+Motorola Delta 147 (m-delta.h; s-usg5-3.h)
+
m- file added in version 18.56.
+Motorola Delta 187 (m-delta88k.h; s-usg5-3.h)
+
+ m- file added in version 18.58.
+ HAVE_X_MENU may work if you modify oldXMenu/Makefile to compile insque.c.
+
National Semiconductor 32000 (m-ns32000.h; s-usg5-2.h)
This is for a complete machine from National Semiconductor,
@@ -528,31 +640,46 @@ NCR Tower 32 running System V release 3 (m-tower32v3.h; s-usg5-3.h)
C_OPTIMIZE_SWITCH rather than C_DEBUG_SWITCH, and do not use gcc, check
out the comments in src/m-tower32v3.h about this.
+NeXT (m-next.h; s-mach2.h)
+
+ Changes merged in 18.59.
+
Nixdorf Targon 31 (m-targon31.h; s-usg5-2-2.h)
- m- file for version 17 is included in 18
- but whether it works is not known.
- src/unexec.c bombs if compiled with -O.
+ Changes merged in 18.56 may work.
+ It may be necessary to define C_ALLOCA in m-targon31.h
+ and it may be necessary to remove alloca from libc.a.
+ (The alloca in libc.a is said to be broken.)
+ Please report to the Foundation what works.
+
Note that the "Targon 35" is really a Pyramid.
Nu (TI or LMI) (m-nu.h; s-usg5-2.h)
Version 18 is believed to work.
+pfa50 (m-pfa50.h; s-usg5-3.h)
+
+ Changes mostly merged in 18.59.
+
Plexus (m-plexus.h; s-usg5-2.h)
Works as of 17.56.
-Pmax (DEC Mips) (m-pmax.h; s-bsd4-2.h)
+Pmax, Mips from DEC (m-pmax.h; s-bsd4-2.h)
See under DECstation, above.
Prime EXL (m-intel386.h; s-usg5-3.h)
- Minor changes merged in 19.1.
+ 18.54 should work.
Pyramid (m-pyramid.h; s-bsd4-2.h)
+ 18.58 seems to work on the MIServer 2/1T under OSx 5.1-910507.
+ You need to build Emacs in the Berkeley universe with
+ the `ucb' command, as in `ucb make' or `ucb build-install'.
+
In OSx 4.0, it seems necessary to add the following two lines
to m-pyramid.h:
#define _longjmp longjmp
@@ -571,14 +698,20 @@ Pyramid (m-pyramid.h; s-bsd4-2.h)
Some old system versions may require you to define PYRAMID_OLD
in when alloca.s is preprocessed, in order to define _longjmp and _setjmp.
-Sequent Balance (m-sequent.h; s-bsd4-2.h, or s-bsd4-3.h on newer systems)
+Pyramid MIPS systems (m-pyrmips.h; s-usg5-4.h)
+
+ Changes merged in 18.59; may work. Dumping is not supported.
+ Use CPP=/usr/ccs/lib/cpp when running make in src.
- Emacs 18.51 should work on system version 3.0. 18.52 is said to work.
- Delete some lines at the end of m-sequent.h for earlier system versions.
+Sequent Balance (m-sequent.h; s-bsd4-2.h)
-Sequent Symmetry (m-symmetry.h; s-bsd4-3.h)
+ Emacs 18.51 should work on system version
+ 3.0. 18.5[23] is said to work. Delete some lines at the end of
+ m-sequent.h for earlier system versions.
- Emacs 19 should work.
+Sequent Symmetry (m-seq386.h; s-bsd4-2.h)
+
+ Changes merged in 18.59 for compiling with GCC.
SONY News (m-news.h; s-bsd4-2.h, or s-bsd4-3.h for system release 3)
@@ -588,9 +721,12 @@ SONY News 3000 series (RISC NEWS) (m-news-risc.h; s-bsd4-3.h)
Works, as of 18.56. Note that this is a MIPS architecture machine.
-Stardent 1500 or 3000
-
- See Titan.
+ Some versions of the operating system give SIGTRAP for division by zero
+ instead of the usual signals. This causes division by zero
+ to make Emacs crash. The system should be fixed to give the proper signal.
+ Changing Emacs is not a proper solution, because it would prevent
+ Emacs from working under any debugger. But you can change init_data
+ in data.c if you wish.
Stride (m-stride.h; s-usg5-2.h)
@@ -599,7 +735,8 @@ Stride (m-stride.h; s-usg5-2.h)
It may be possible to run on their V.1 system but changes
in the s- file would be needed.
-Sun 1, 2 and 3 (m-sun1.h, m-sun2.h, m-sun3.h; s-bsd4-2.h or s-sunos4.h)
+Sun 1, 2 and 3 (m-sun1.h, m-sun2.h, m-sun3.h;
+ s-bsd4-2.h, s-sunos4-0.h or s-sunos4-1.h)
There are three m- files for different versions of SunOS.
All are derived from Berkeley 4.2. Emacs 17 has run on all of them.
@@ -607,14 +744,16 @@ Sun 1, 2 and 3 (m-sun1.h, m-sun2.h, m-sun3.h; s-bsd4-2.h or s-sunos4.h)
on the VERSION OF THE OPERATING SYSTEM you have.
You will need to use m-sun3.h on Sun 2's running SunOS release 3.
- For SunOS release 4 on a Sun 3, use m-sun3.h and s-sunos4.h.
+ For SunOS release 4 on a Sun 2 or Sun 3, use m-sun3.h and s-sunos4-1.h.
+ (Use s-sunos4-0.h instead if using system version 4.0.*.)
See the file etc/SUNBUG for how to solve problems caused by bugs in
the "export" version of SunOS 4.
- If you have trouble using open-network-stream, get the
- distribution of `bind' (the BSD name-server), build libresolv.a,
- and link Emacs with -lresolv. This problem is due to obsolete
- software in the nonshared standard library.
+ If you get inappropriate "unknown host" errors from
+ open-network-stream, get the distribution of `bind' (the BSD
+ name-server), build libresolv.a, and link Emacs with -lresolv. This
+ problem is due to obsolete software in the nonshared standard
+ library.
If you want to use SunWindows, define HAVE_SUN_WINDOWS
in config.h to enable a special interface called `emacstool'.
@@ -629,6 +768,11 @@ Sun 1, 2 and 3 (m-sun1.h, m-sun2.h, m-sun3.h; s-bsd4-2.h or s-sunos4.h)
compiled to use the 68881, then you must edit config.h according
the comments at the end of m-sun3.h.
+ It is advisable to add #define ForceNormalLib YES before building
+ X11R5, to force creation of a nonshared library (as well as the
+ shared X library). Emacs does not use shared libraries, so it
+ needs to have a nonshared X library in order to run with X.
+
Note that Emacs on a Sun is not really as big as it looks.
As dumped, it includes around 200k of zeros between the
original text section and the original data section
@@ -638,20 +782,33 @@ Sun 1, 2 and 3 (m-sun1.h, m-sun2.h, m-sun3.h; s-bsd4-2.h or s-sunos4.h)
To build a single Emacs that will run on Sun 2 and Sun 3
HARDWARE, just build it on the Sun 2.
-Sun 4 (m-sparc.h; s-bsd4-2.h or s-sunos4.h)
+Sun 4 (m-sparc.h; s-bsd4-2.h or s-sunos4-0.h or s-sunos4-1.h or s-sol2.h)
+
+ Works under Sunos 4; changes for Solaris 2 merged in Emacs 18.59.
+ You may need to use CPP=/usr/ucb/cc -E in src/Makefile on Solaris 2.
- Changes merged in 18.50. Some people say optimizing compilation
+ Some people have said optimizing compilation
does not work; some say that -O2 (whatever that is) works
perhaps with a small change.
- Use s-sunos4.h for operating system version 4.
- See the file etc/SUNBUG for how to solve problems caused by bugs in
- the "export" version of SunOS 4.
+ See the entry above for the Sun 3; most of the information
+ applies to the Sun 4 as well.
-Sun Roadrunner (m-sun386.h; s-sunos4.h)
+Sun Roadrunner (m-sun386.h; s-sunos4-0.h)
Changes merged in 18.51.
+Tadpole (m-tad68.h; s-usg5-3.h)
+
+ Changes merged in 18.58; minor fixes in 18.59.
+
+ You may need to edit Makefile to change the variables LIBDIR and
+ BINDIR from /usr/local to /usr/contrib.
+
+ To give movemail access to /usr/mail, you may need to execute
+
+ chmod 2755 etc/movemail; chgrp mail etc/movemail
+
Tahoe (m-tahoe.h; s-bsd4-2.h or s-bsd4-3.h)
18.52 known to work on some Tahoes, but a compiler bug intervenes
@@ -672,15 +829,20 @@ Tektronix 16000 box (6130?) (m-ns16000.h; s-bsd4-2.h)
Emacs 17.61 worked.
-Tektronix 4300 (m-tex4300.h; s-bsd4-3.h)
+Tektronix 4300 (m-tek4300.h; s-bsd4-3.h)
+
+ Emacs 18.58 should work.
- Emacs 18.51 should work.
+ Depending on which linker you use, you might want to change
+ the value of TEXT_START in m-tek4300.h; though the native linker
+ does use zero, it is possible (and reasonable) to use a linker
+ that starts text elsewhere, like 0x2000.
-Titan P2 or P3 (m-titan.h; s-usg5-3.h)
+Triton 88 (m-triton88.h; s-usg5-3.h?)
- Changes probably merged in version 19.
+ Changes merged in 18.58.
-Ustation E30 (SS5E) (m-ustation.h; s-unipl5-2.h).
+Ustation E30 (SS5E) (m-ustation.h; s-unipl5-2.h)
Changes merged in 18.52; don't know whether they work.
diff --git a/etc/MAILINGLISTS b/etc/MAILINGLISTS
new file mode 100644
index 00000000000..05a51144413
--- /dev/null
+++ b/etc/MAILINGLISTS
@@ -0,0 +1,743 @@
+ GNU Project Electronic Mailing Lists. Last Updated 23 Oct 91
+
+ Please report improvements to: gnu@prep.ai.mit.edu
+
+* GNU mailing lists are also distributed as USENET news groups
+
+The mailing lists are gated both ways with the gnu.all newsgroups at
+ohio-state.edu. The one-to-one correspondence is indicated below. If
+you don't know if your site is on USENET, ask your system administrator.
+If you are a USENET site and don't get the gnu.all newsgroups, please
+ask your USENET administrator to get them. If he has your feeds ask
+their feeds, you should win. And everyone else wins: newsgroups make
+better use of the limited bandwidth of the computer networks and your
+home machine than mailing list traffic; and staying off the mailing
+lists make better use of the people who maintain the lists and the
+machines that the GNU people working with rms use (i.e. we have more
+time to produce code!!). Thanx.
+
+* Getting the mailing lists directly
+
+If several users at your site or local network want to read a list and
+you aren't a USENET site, Project GNU would prefer that you would set up
+one address that redistributes locally. This reduces overhead on our
+people and machines, your gateway machine, and the network(s) used to
+transport the mail from us to you.
+
+* How to subscribe to and report bugs in mailing lists
+
+Send messages ABOUT these lists, such as reports of mail problems, or
+requests to be added or removed, to help-gnu-emacs-request (or
+info-gnu-request, bug-gdb-request, etc.), NOT to info-gnu-emacs (or
+info-gnu, etc.). These <LIST_NAME>-request addresses go only to the
+people who can do something about your requests or problems, and thus
+avoids disturbing everyone else.
+
+Note that all GNU mailing lists are maintained by volunteers. They get
+behind occasionally. Wait at least 3 or 4 days before asking again.
+Thanks!
+
+Many of the GNU mailing lists are very large and are received by many
+people. Please don't send them anything that is not seriously important
+to all their readers. All GNU mailing lists are unmoderated, mail
+reflectors, except info-gnu, info-gnu-emacs, info-gcc, info-g++ and
+info-gnu-fortran.
+
+All addresses below are in internet format. Consult the mail guru for
+your computer to figure out address syntaxes from other networks. From
+UUCP machines:
+ ..!ucbvax!prep.ai.mit.edu!ADDRESS
+ ..!uunet!prep.ai.mit.edu!ADDRESS
+
+If a message you mail to a list is returned from a MAILER-DAEMON (often
+with the line:
+ ----- Transcript of session follows -----
+ don't resend the message to the list. All this return means is that
+your original message failed to reach a few addresses on the list. Such
+messages are NEVER a reason to resend a piece of mail a 2nd time. This
+just bothers all (less the few delivery failures (which will probably
+just fail again!)) of the readers of the list with a message they have
+already seen. It also wastes computer and network resources.
+
+It is appropriate to send these to the -request address for a list, and
+ask them to check the problem out.
+
+* Send Specific Requests for Information to: gnu@prep.ai.mit.edu
+
+Specific requests for information about obtaining GNU software, or GNU
+activities in Cambridge and elsewhere can be directed to:
+ gnu@prep.ai.mit.edu
+
+* General Information about all lists
+
+Please keep each message under 40,000 characters. Some mailers bounce
+messages that are longer than this.
+
+Most of the time, when you reply to a message sent to a list, the reply
+should not go to the list. But most mail reading programs supply, by
+default, all the recipients of the original as recipients of the reply.
+Make a point of deleting the list address from the header when it does
+not belong. This prevents bothering all readers of a list, and reduces
+network congestion.
+
+The GNU mailing lists and newsgroups, like the GNU project itself, exist
+to promote the freedom to share software. So don't use these lists to
+promote or recommend non-free software. (Using them to post ordering
+information is the ultimate faux pas.) If there is no free program to
+do a certain task, then somebody should write one!
+
+* General Information about info-* lists
+
+These lists and their newsgroups are meant for important announcements.
+Since the GNU project uses software development as a means for social
+change, the announcements may be technical or political.
+
+Most GNU projects info-* lists (and their corresponding gnu.*.announce
+newsgroups) are moderated to keep their content significant and
+relevant. If you have a bug to report, send it to the bug-* list. If
+you need help on something else and the help-* list exists, ask it.
+
+See section '* General Information about all lists'.
+
+* General Information about help-* lists
+
+These lists (and their newsgroups) exist for anyone to ask questions
+about the GNU software that the list deals with. The lists are read by
+people who are willing to take the time to help other users.
+
+When you answer the questions that people ask on the help-* lists, keep
+in mind that you shouldn't answer by promoting a proprietary program as
+a solution. The only real solutions are the ones all the readers can
+share.
+
+See section '* General Information about all lists'.
+
+* General Information about bug-* lists and reporting program bugs
+
+If you think something is a bug in a program, it might be one; or, it
+might be a misunderstanding or even a feature. Before beginning to
+report bugs, please read the section ``Reporting Emacs Bugs'' toward the
+end of the GNU Emacs reference manual (or node Emacs/Bugs in Emacs's
+built-in Info system) for a discussion of how and when to send in bug
+reports. For GNU programs other than GNU Emacs, also consult their
+documentation for their bug reporting procedures. Always include the
+version number of the GNU program, as well as the operating system and
+machine the program was ran on (if the program doesn't have a version
+number, send the date of the latest entry in the file ChangeLog). For
+GNU Emacs bugs, type "M-x emacs-version". A debugger backtrace of any
+core dump, can also be useful. Be careful to separate out hypothesis
+from fact! For bugs in GNU Emacs lisp, set variable debug-on-error to
+t, and re-enter the command(s) that cause the error message; Emacs will
+pop up a debug buffer if something is wrong; please include a copy of
+the buffer in your bug report.
+
+Please don't send in a patch without a test case to illustrate the
+problem the patch is supposed to fix. Sometimes the patches aren't
+correct or aren't the best way to do the job, and without a test case
+there is no way to debug an alternate fix.
+
+The purpose of reporting a bug is to enable the bug to be fixed for the
+sake of the whole community of users. You may or may not receive a
+response; the maintainers will send one if that helps them find or
+verify a fix. Most GNU maintainers are volunteers and all are
+overworked; they don't have time to help individuals and still fix the
+bugs and make the improvements that everyone wants. If you want help
+for yourself in particular, you may have to hire someone. The GNU
+project maintains a list of people providing such services. It is
+distributed with GNU Emacs in file etc/SERVICE, and can be requested
+from gnu@prep.ai.mit.edu.
+
+Anything addressed to the implementors and maintainers of a GNU program
+via a bug-* list, should NOT be sent to the corresponding info-* or
+help-* list.
+
+Please DON'T post your bug reports on the gnu.* newsgroups! Mail them
+to bug-*@prep instead! At first sight, it seems to make no difference:
+anything sent to one will be propagated to the other; but if you post on
+the newsgroup, the information about how to reach you is lost in the
+message that goes on the mailing list. It can be very important to know
+how to reach you if there is anything in the bug report that we don't
+understand. Bug reports also reach the GNU maintainers quickest when
+they are sent to the bug-* mailing list submittal address.
+
+And please DON'T post your GNU bug reports to comp.* or other non gnu.*
+newsgroups, they never make it to the GNU maintainers at all. Please
+mail them to bug-*@prep instead!
+
+See section '* General Information about all lists'.
+
+* info-gnu-request@prep.ai.mit.edu to subscribe to info-gnu
+** gnUSENET newsgroup: gnu.announce
+** Send announcements to: info-gnu@prep.ai.mit.edu
+
+This list distributes progress reports on the GNU Project. It is also
+used by the GNU Project to ask people for various kinds of help. It is
+NOT for general discussion.
+
+The list is filtered to remove items meant for info-gnu-request, that
+can be answered by the moderator without bothering the list, or should
+have been sent to another list.
+
+See section '* General Information about info-* lists'.
+
+* gnu-misc-discuss-request@cis.ohio-state.edu to subscribe to gnu-misc-discuss
+** gnUSENET newsgroup: gnu.misc.discuss
+** Send contributions to: gnu-misc-discuss@cis.ohio-state.edu
+
+This list is for serious discussion of freed software, the GNU
+Project, the GNU Manifesto and their implications. It's THE place for
+discussion that is not appropriate in the other GNU mailing lists and
+gnUSENET newsgroups.
+
+Flaming is out of place. Tit-for-tat is not welcome. Repetition
+should not occur.
+
+Good READING and writing are expected. Before posting, wait a while,
+cool off, and think.
+
+Don't trust pronouncements made on gnu-misc-discuss about what GNU is,
+what FSF position is, what the GNU General Public License is, etc.,
+unless they are made by someone you know is well connected with GNU and
+are sure the message is not forged.
+
+USENET and gnUSENET readers are expected to have read ALL the articles
+in news.announce.newusers before posting. If news.announce.newusers is
+empty at your site, wait (the articles are posted monthly), your posting
+isn't that urgent! Readers on the Internet can anonymous ftp these
+articles from wsmr-simtel20.army.mil under directory
+PD2:<UNIX-C.USENET>.
+
+Someone from the Free Software Foundation will attempt to follow this
+group as time and volume permits.
+
+Remember, "GNUs Not Unix" and "gnUSENET is Not USENET". We have
+higher standards!
+
+Note that sending technical questions about specific GNU software to
+gnu-misc-discuss is likely to be less useful than sending them to the
+appropriate mailing list or gnUSENET newsgroup, since more technical
+people read those.
+
+* bug-gnu-emacs-request@prep.ai.mit.edu to subscribe to bug-gnu-emacs
+** gnUSENET newsgroup: gnu.emacs.bug
+** Gnu Emacs bug reports to: bug-gnu-emacs@prep.ai.mit.edu
+
+This list distributes, to the active maintainers of GNU Emacs, bug
+reports and fixes for, and suggestions for improvements in GNU Emacs.
+It is the place to report GNU Emacs bugs by all users of GNU Emacs.
+
+Send bugs in the GNU Emacs Lisp reference manual to:
+ lisp-manual-bugs@prep.ai.mit.edu
+
+lisp-manual-bugs is neither a mailing list nor a gnUSENET newsgroup.
+It's just a bug-reporting address.
+
+Subscribers to bug-gnu-emacs automatically receive all
+info-gnu-emacs messages.
+
+See section '* General Information about bug-* lists and reporting
+program bugs'.
+
+* gnu-emacs-sources-request@prep.ai.mit.edu to subscribe to gnu-emacs-sources
+** gnUSENET newsgroup: gnu.emacs.sources
+** Gnu Emacs source code to: gnu-emacs-sources@prep.ai.mit.edu
+
+This list/newsgroup will be for the posting, by their authors, of lisp
+and C sources and patches that improve GNU Emacs. Its contents will
+be reviewed by FSF for inclusion in future releases of GNU Emacs.
+
+Please do NOT discuss or request source code here. Use
+help-gnu-emacs/gnu.emacs.help for those purposes. This allows the
+automatic archiving of sources posted to this list/newsgroup.
+
+Please do NOT post such sources to any other GNU mailing list (e.g
+help-gnu-emacs) or gnUSENET newsgroups (e.g. gnu.emacs.help). It's up
+to each poster to decide whether to cross-post to any non-gnUSENET
+newsgroup (e.g. comp.emacs or vmsnet.sources).
+
+Please do NOT announce that you have posted source code to
+gnu.emacs.sources to any other GNU mailing list (e.g. help-gnu-emacs) or
+gnUSENET newsgroups (e.g. gnu.emacs.help). People who want to keep up
+with sources will read this list/newsgroup. It's up to each poster to
+decide whether to announce a gnu.emacs.sources article in any
+non-gnUSENET newsgroup (e.g comp.emacs or comp.sources.d).
+
+If source or patches that were previously posted or a simple fix is
+requested in help-gnu-emacs, please mail it to the requester. Do NOT
+repost it. If you also want something that is requested, send mail to
+the requester asking him to forward it to you. This kind of traffic is
+best handled by e-mail, not by a broadcast medium that reaches thousands
+of sites.
+
+If the source is very long (>10k bytes) send mail offering to send it.
+This prevents the requester from getting many redundant copies and saves
+network bandwidth.
+
+* help-gnu-emacs-request@prep.ai.mit.edu to subscribe to help-gnu-emacs
+** gnUSENET newsgroup: gnu.emacs.help (and one-way into comp.emacs)
+** Send contributions to: help-gnu-emacs@prep.ai.mit.edu
+
+This list is the place for users and installers of GNU Emacs to ask for
+help. Please send bug reports to bug-gnu-emacs instead of posting them
+here.
+
+Since help-gnu-emacs is a very large list, send it only those items that
+are seriously important to many people.
+
+If source or patches that were previously posted or a simple fix is
+requested in help-gnu-emacs, please mail it to the requester. Do NOT
+repost it. If you also want something that is requested, send mail to
+the requester asking him to forward it to you. This kind of traffic is
+best handled by e-mail, not a broadcast medium that reaches thousands of
+sites.
+
+This list is also gated one way to USENET's newsgroup comp.emacs (once
+known as net.emacs). This one-way gating is done for users whose sites
+get comp.emacs, but not gnu.emacs.help. Users at non-USENET sites may
+receive all articles from comp.emacs by making their request to:
+unix-emacs-request@bbn.com
+
+If Emacs crashes, or if you build Emacs following the standard procedure
+on a system which Emacs is supposed to work on (see etc/MACHINES) and it
+does not work at all, or if an editing command does not behave as it is
+documented to behave, this is a bug. Don't send bug reports to
+help-gnu-emacs (gnu.emacs.help) or post them to comp.emacs; mail them to
+bug-gnu-emacs instead.
+
+See section '* General Information about help-* lists'.
+
+* info-gnu-emacs-request@prep.ai.mit.edu to subscribe to info-gnu-emacs
+** gnUSENET newsgroup: gnu.emacs.announce (and one-way into comp.emacs)
+** Send announcements to: info-gnu-emacs@prep.ai.mit.edu
+
+This list distributes announcements and progress reports on GNU Emacs.
+It is NOT for general discussion; please use help-gnu-emacs for that.
+
+The list is filtered to remove items meant for info-gnu-emacs-request,
+that can be answered by the moderator without bothering the list, or
+should have been sent to another list.
+
+info-gnu-emacs is also gated one way to USENET's newsgroup comp.emacs
+(once known as net.emacs). This one-way gating is done for users whose
+sites get comp.emacs, but not gnu.emacs.announce. Users at non-USENET
+sites may receive all articles from comp.emacs by making their request
+to: unix-emacs-request@bbn.com
+
+Do not report GNU Emacs bugs to info-gnu-emacs or comp.emacs, instead
+mail them to bug-gnu-emacs@prep.ai.mit.edu.
+
+See section '* General Information about info-* lists'.
+
+* vms-gnu-emacs-request@harvard.harvard.edu to subscribe to vms-gnu-emacs
+** gnUSENET newsgroup: gnu.emacs.vms
+** Send contributions to: vms-gnu-emacs@harvard.harvard.edu
+*** UUCP: ..!uunet!harvard!vms-gnu-emacs-request
+
+This list was a working group who did the initial port of GNU Emacs to
+the VMS operating system. It still discusses problems and solutions to
+the VMS port and the distribution of it.
+
+* bug-bash-request@prep.ai.mit.edu to subscribe to bug-bash
+** gnUSENET newsgroup: gnu.bash.bug
+** BASH bug reports to: bug-bash@prep.ai.mit.edu
+
+This list distributes, to the active maintainers of BASH (the Bourne
+Again SHell), bug reports and fixes for, and suggestions for
+improvements in BASH. It is the place to report BASH bugs by all users
+of BASH.
+
+Always report the version number of the operating system, hardware, and
+bash (flag -version on startup or check the variable $BASH_VERSION in a
+running bash).
+
+There are no other GNU mailing lists or gnUSENET newsgroups for BASH.
+
+See section '* General Information about bug-* lists and reporting
+program bugs'.
+
+* bug-gdb-request@prep.ai.mit.edu to subscribe to bug-gdb
+** gnUSENET newsgroup: gnu.gdb.bug
+** GDB bug reports to: bug-gdb@prep.ai.mit.edu
+
+This list distributes, to the active maintainers of GDB (Gnu's
+DeBugger), bug reports and fixes for, and suggestions for improvements
+in GDB. It is the place to report GDB bugs by all users of GDB.
+
+There are no other GNU mailing lists or gnUSENET newsgroups for GDB.
+
+See section '* General Information about bug-* lists and reporting
+program bugs'.
+
+* bug-gcc-request@prep.ai.mit.edu to subscribe to bug-gcc
+** gnUSENET newsgroup: gnu.gcc.bug
+** GCC bug reports to: bug-gcc@prep.ai.mit.edu
+
+This list distributes bug reports for, fixes for bugs in, and
+suggestions for improvements in the GNU C Compiler to its active
+developers. It is the place to report GCC bugs by all testers of GCC.
+The GNU C Compiler still has bugs in it, and is not quite ready for
+everyday use.
+
+Please don't send in a patch without a test case to illustrate the
+problem the patch is supposed to fix. Sometimes the patches aren't
+correct or aren't the best way to do the job, and without a test case
+there is no way to debug an alternate fix.
+
+The most convenient form of test case is a piece of cpp output that can
+be passed directly to cc1. Preferably written in C, not C++.
+
+Subscribers to bug-gcc automatically receive all info-gcc messages.
+
+See section '* General Information about bug-* lists and reporting
+program bugs'.
+
+* help-gcc-request@prep.ai.mit.edu to subscribe to help-gcc
+** gnUSENET newsgroup: gnu.gcc.help
+** Send contributions to: help-gcc@prep.ai.mit.edu
+
+This list is the place for users and installers of the GNU C Compiler to
+ask for help.
+
+If gcc crashes, or if you build gcc following the standard procedure on
+a system which gcc is supposed to work on (see config.gcc) and it does
+not work at all, or if an command line option does not behave as it is
+documented to behave, this is a bug. Don't send bug reports to help-gcc
+(gnu.gcc.help); mail them to bug-gcc instead.
+
+See section '* General Information about help-* lists'.
+
+* info-gcc-request@prep.ai.mit.edu to subscribe to info-gcc
+** gnUSENET newsgroup: gnu.gcc.announce
+** Send announcements to: info-gcc@prep.ai.mit.edu
+
+This list distributes announcements and progress reports on the GNU C
+Compiler. It is NOT for general discussion; please use help-gcc for
+that.
+
+The list is filtered to remove items meant for info-gcc-request, that
+can be answered by the moderator without bothering the list, or should
+have been sent to another list.
+
+See section '* General Information about info-* lists'.
+
+* bug-g++-request@prep.ai.mit.edu to subscribe to bug-g++
+** gnUSENET newsgroup: gnu.g++.bug
+** G++ bug reports to: bug-g++@prep.ai.mit.edu
+
+This list distributes bug reports for, fixes for bugs in, and
+suggestions for improvements in the GNU C++ Compiler to its active
+developers. It is the place to report G++ bugs by all testers of G++.
+
+G++ uses the GNU C-Compiler back end. Active developers may wish to
+subscribe to bug-gcc@prep.ai.mit.edu as well.
+
+Subscribers to bug-g++ automatically receive all info-g++ messages.
+
+See section '* General Information about bug-* lists and reporting
+program bugs'.
+
+* help-g++-request@prep.ai.mit.edu to subscribe to help-g++
+** gnUSENET newsgroup: gnu.g++.help (and one-way into comp.lang.c++)
+** Send contributions to: help-g++@prep.ai.mit.edu
+
+This list is the place for users and installers of the GNU C++ Compiler
+to ask for help. Please send bug reports to bug-g++ instead of posting
+them here.
+
+help-g++ is also gated one way to USENET's newsgroup comp.lang.c++.
+This one-way gating is done for users whose sites get comp.lang.c++, but
+not gnu.g++.help.
+
+If g++ crashes, or if you build g++ following the standard procedure on
+a system which g++ is supposed to work on (see config.g++) and it does
+not work at all, or if an command line option does not behave as it is
+documented to behave, this is a bug. Don't send bug reports to help-g++
+(gnu.g++.help) or post them to comp.lang.c++; mail them to bug-g++
+instead.
+
+See section '* General Information about help-* lists'.
+
+* info-g++-request@prep.ai.mit.edu to subscribe to info-g++
+** gnUSENET newsgroup: gnu.g++.announce (and one-way into comp.lang.c++)
+** Send announcements to: info-g++@prep.ai.mit.edu
+
+This list distributes announcements and progress reports on the GNU C++
+Compiler. It is NOT for general discussion; please use help-g++ for
+that.
+
+The list is filtered to remove items meant for info-g++-request, that
+can be answered by the moderator without bothering the list, or should
+have been sent to another list.
+
+It is also gated one way to USENET's newsgroup comp.lang.c++. This
+one-way gating is done for users whose sites get comp.lang.c++, but not
+gnu.g++.announce.
+
+Do not report g++ bugs to info-g++ or comp.lang.c++, mail them to
+bug-g++@prep.ai.mit.edu instead.
+
+See section '* General Information about info-* lists'.
+
+* bug-lib-g++-request@prep.ai.mit.edu to subscribe to bug-lib-g++
+** gnUSENET newsgroup: gnu.g++.lib.bug
+** lib-g++ bug reports to: bug-lib-g++@prep.ai.mit.edu
+
+This list distributes, to the active maintainers of lib-g++ (GNU's
+library for C++), bug reports and fixes for, and suggestions for
+improvements in lib-g++. It is the place to report lib-g++ bugs by all
+users of lib-g++.
+
+Announcements of new releases of lib-g++ are made on both info-g++ and
+bug-lib-g++.
+
+There are no other GNU mailing lists or gnUSENET newsgroups for the G++
+Library.
+
+See section '* General Information about bug-* lists and reporting
+program bugs'.
+
+* info-gnu-fortran-request@prep.ai.mit.edu to subscribe to info-gnu-fortran
+** gnUSENET newsgroup: NONE YET
+** Send contributions to: info-gnu-fortran@prep.ai.mit.edu
+
+This list is for progress reports about the GNU Fortran compiler. In
+the future it will also be used for release notices.
+
+The list is filtered to remove items meant for info-gnu-fortran-request,
+that can be answered by the moderator without bothering the list, or
+should have been sent to another list.
+
+See section '* General Information about info-* lists'.
+
+There are no other GNU mailing lists or gnUSENET newsgroups for GNU
+Fortran (yet).
+
+* bug-gnu-smalltalk-request@prep.ai.mit.edu to subscribe to bug-gnu-smalltalk
+** gnUSENET newsgroup: gnu.smalltalk.bug
+** GNU Smalltalk bug reports to: bug-gnu-smalltalk@prep.ai.mit.edu
+
+GNU Smalltalk is the GNU project implementation of the Smalltalk language.
+
+This list distributes, to the active maintainers of GNU Smalltalk, bug
+reports and fixes for, and suggestions for improvements to GNU
+Smalltalk. It is the place to report bugs in GNU Smalltalk by all users
+of the program.
+
+For now, new releases of GNU Smalltalk will also be announced on this list.
+
+There are no other GNU mailing lists or gnUSENET newsgroups for GNU
+Smalltalk.
+
+See section '* General Information about bug-* lists and reporting
+program bugs'.
+
+* bug-groff-request@prep.ai.mit.edu to subscribe to bug-groff
+** gnUSENET newsgroup: gnu.groff.bug
+** GNU groff bug reports to: bug-groff@prep.ai.mit.edu
+
+groff is the GNU project implementation, in C++, of the traditional
+Unix document formatting tools. As of June 1990 it includes troff,
+pic, tbl, eqn, man macros, a PostScript driver, a driver which
+produces TeX dvi format and a driver for typewriter-like devices. A
+modified version of the Berkeley me macros and an enhanced version of
+the X11R4 xditview are also included.
+
+This list distributes, to the active maintainers of groff, bug reports
+and fixes for, and suggestions for improvements to groff (and it
+component programs). It is the place for all users of groff to report
+bugs.
+
+For now, new releases of groff will also be announced on this list.
+
+There are no other GNU mailing lists or gnUSENET newsgroups for groff.
+
+See section '* General Information about bug-* lists and reporting
+program bugs'.
+
+* bug-ghostscript-request@prep.ai.mit.edu to subscribe to bug-ghostscript
+** gnUSENET newsgroup: gnu.ghostscript.bug
+** Ghostscript bug reports to: bug-ghostscript@prep.ai.mit.edu
+
+GhostScript is the GNU project implementation of a language and graphics
+library with a remarkable similarity to PostScript.
+
+This list distributes, to the active maintainers of Ghostscript, bug
+reports and fixes for, and suggestions for improvements in Ghostscript. It
+is the place to report bugs in Ghostscript by all users of them.
+
+For now, new releases of Ghostscript will also be announced on this list.
+
+There are no other GNU mailing lists or gnUSENET newsgroups for
+GhostScript.
+
+See section '* General Information about bug-* lists and reporting
+program bugs'.
+
+* info-gnu-chess-request@prep.ai.mit.edu to subscribe to info-gnu-chess
+** gnUSENET newsgroup: gnu.chess
+** Send contributions to: info-gnu-chess@prep.ai.mit.edu
+
+This list reports new releases and information about the program GNU
+Chess.
+
+See section '* General Information about info-* lists'.
+
+* bug-gnu-utils-request@prep.ai.mit.edu to subscribe to bug-gnu-utils
+** gnUSENET newsgroup: gnu.utils.bug
+** GNU Utilities bug reports to: bug-gnu-utils@prep.ai.mit.edu
+
+This list distributes, to the active maintainers of these programs, bug
+reports and fixes for, and suggestions for improvements in GNU programs
+not covered by other bug-* mailing lists/gnu.*.bug newsgroups. It is
+the place to report bugs in these GNU programs by all users of them.
+
+There are no other GNU mailing lists or gnUSENET newsgroups for these
+GNU utilities.
+
+See section '* General Information about bug-* lists and reporting
+program bugs'.
+
+* bug-fortran-mode-request@erl.mit.edu to subscribe to bug-fortran-mode
+** USENET newsgroup: (none)
+** Fortran mode bug reports to: bug-fortran-mode@erl.mit.edu
+
+This list collects bug reports, fixes for bugs, and suggestions for
+improvements in GNU Emacs's Fortran mode (a major mode to support
+editing Fortran source code).
+
+It is the place to report Fortran mode bugs by all users of Fortran
+mode.
+
+Always report the version number Fortran mode reports on startup as well
+as the version of Emacs.
+
+There is no info-fortran-mode list. There are no USENET gateways to
+bug-fortran-mode at this time.
+
+* info-gnus-request%flab.Fujitsu.JUNET@uunet.UU.NET to subscribe
+** gnUSENET newsgroup: NONE YET
+** Send contributions to: info-gnus%flab.Fujitsu.JUNET@uunet.UU.NET
+
+The list is intended to exchange useful information about GNUS, such as
+bug reports, useful hooks, and extensions of GNUS. GNUS is an NNTP-base
+network news reader for GNU Emacs (which also works with a news spool).
+English and Japanese are the official languages of the list. GNUS is
+quite different than gnews.
+
+* info-gnus-english-request@cis.ohio-state.edu to subscribe
+** gnUSENET newsgroup: gnu.emacs.gnus
+** Send contributions to: info-gnus-english@cis.ohio-state.edu
+
+The list has the same charter as info-gnus. The difference is that
+English is the only official language of the list.
+
+info-gnus-english/gnu.emacs.gnus is forward to info-gnus, but NOT
+vice-versa.
+
+* info-gnews-request@ics.uci.edu to subscribe to info-gnews
+** gnUSENET newsgroup: gnu.emacs.gnews
+** Send contributions to: info-gnews@ics.uci.edu
+
+This newsgroup is intended to exchange useful information about gnews,
+such as bug reports, useful hooks, and extensions of gnews. gnews is an
+NNTP-base network news reader for GNU Emacs (which also works a news
+spool). It is quite different than GNUS.
+
+* gnu-emacs-ada-request@grebyn.com to subscribe to gnu-emacs-ada
+** gnUSENET newsgroup: NONE PLANNED
+** Gnu Emacs Ada support bug reports to: gnu-emacs-ada@grebyn.com
+
+This list distributes bug reports for, fixes for bugs in, and
+suggestions for improvements in GNU Emacs' editing support of the Ada
+programming language.
+
+There are no other GNU mailing lists or gnUSENET newsgroups for GNU
+Emacs' editing support of Ada.
+
+See section '* General Information about bug-* lists and reporting
+program bugs'.
+
+* bug-vm-request@uunet.uu.net to subscribe to bug-vm
+** gnUSENET newsgroup: NONE
+** VM mail reader bug reports to: bug-vm@uunet.uu.net
+
+This list discusses bugs in View Mail mode for GNU Emacs, with an
+emphasis on beta and prerelease versions. It is the place to report
+bugs in VM.
+
+Always report the version number of VM you are using, as well as the
+version of Emacs you're running. If you believe it is significant,
+report the operating system used and the hardware.
+
+Subscribers to bug-vm automatically receive all info-vm messages.
+
+* info-vm-request@uunet.uu.net to subscribe to info-vm
+** gnUSENET newsgroup: NONE
+** Send contributions to: info-vm@uunet.uu.net
+
+This list dicusses the View Mail mode for GNU Emacs, an alternative to
+rmail mode.
+
+* supercite-request@warsaw.nlm.nih.gov to subscribe to supercite
+** gnUSENET newsgroup: NONE PLANNED
+** Send articles to: supercite@warsaw.nlm.nih.gov
+*** UUCP: ..!uunet!warsaw.nlm.nih.gov!supercite-request
+
+The supercite mailing list covers issues related to the advanced
+mail/news citation package called Supercite for GNU Emacs.
+
+* bug-gnu960-request@mipon2.intel.com to subscribe to bug-gnu960
+** gnUSENET newsgroup: NONE PLANNED
+** Intel 960 Port bug reports to: bug-gnu960@mipon2.intel.com
+
+This list distributes bug reports for, fixes for bugs in, and
+suggestions for improvements in Intel's port of GNU software to the
+Intel 960 microprocessor.
+
+You can also fax to: GNU/960 - 1-503-696-4930.
+
+There are no other GNU mailing lists or gnUSENET newsgroups for Intel's
+port of GNU software to the Intel 960 microprocessor.
+
+See section '* General Information about bug-* lists and reporting
+program bugs'.
+
+* gnu-manual-request@a.cs.uiuc.edu IS NOW DEFUNCT
+** DEAD: Gnusenet newsgroup: gnu.emacs.lisp.manual
+** DEAD address: gnu-manual@a.cs.uiuc.edu
+*** DEAD UUCP address: ..!uunet!uiucdcs!gnu-manual-request
+
+This list and newsgroup is dead. It was a working group whose
+volunteers wrote, proofread and commented on the developing GNU Emacs
+Lisp programmers manual.
+
+Send bugs in the GNU Emacs Lisp reference manual to:
+ lisp-manual-bugs@prep.ai.mit.edu
+
+lisp-manual-bugs is neither a mailing list nor a gnUSENET newsgroup.
+It's just a bug-reporting address.
+
+* no mailing list request
+** gnUSENET newsgroup: gnu.gnusenet.config
+** no mailing list
+
+This newsgroup has nothing to do with GNU software, especially its
+configuration. It's exists to distribute information about the
+administration and configuration of gnUSENET: the gnu.all alternative
+USENET hierarchy that carry the GNU mailing lists.
+
+Administrators of gnUSENET hosts receiving the gnu.all newsgroups are
+welcome to ask questions here or via e-mail of gnu@prep.ai.mit.edu.
+
+* no mailing list request
+** gnUSENET newsgroup: gnu.gnusenet.test
+** no mailing list
+
+This newsgroup has nothing to do with GNU software, especially its
+testing. It's exists to allow test messages to be made in gnUSENET: the
+gnu.all alternative USENET hierarchy that carry the GNU mailing lists.
+
+Local variables:
+mode: outline
+fill-column: 72
+End:
diff --git a/etc/MOTIVATION b/etc/MOTIVATION
new file mode 100644
index 00000000000..37ed36f47b0
--- /dev/null
+++ b/etc/MOTIVATION
@@ -0,0 +1,176 @@
+STUDIES FIND REWARD OFTEN NO MOTIVATOR
+
+Creativity and intrinsic interest diminish if task is done for gain
+
+By Alfie Kohn
+Special to the Boston Globe
+[reprinted with permission of the author
+ from the Monday 19 January 1987 Boston Globe]
+
+In the laboratory, rats get Rice Krispies. In the classroom the top
+students get A's, and in the factory or office the best workers get
+raises. It's an article of faith for most of us that rewards promote
+better performance.
+
+But a growing body of research suggests that this law is not nearly as
+ironclad as was once thought. Psychologists have been finding that
+rewards can lower performance levels, especially when the performance
+involves creativity.
+
+A related series of studies shows that intrinsic interest in a task -
+the sense that something is worth doing for its own sake - typically
+declines when someone is rewarded for doing it.
+
+If a reward - money, awards, praise, or winning a contest - comes to
+be seen as the reason one is engaging in an activity, that activity
+will be viewed as less enjoyable in its own right.
+
+With the exception of some behaviorists who doubt the very existence
+of intrinsic motivation, these conclusions are now widely accepted
+among psychologists. Taken together, they suggest we may unwittingly
+be squelching interest and discouraging innovation among workers,
+students and artists.
+
+The recognition that rewards can have counter-productive effects is
+based on a variety of studies, which have come up with such findings
+as these: Young children who are rewarded for drawing are less likely
+to draw on their own that are children who draw just for the fun of
+it. Teenagers offered rewards for playing word games enjoy the games
+less and do not do as well as those who play with no rewards.
+Employees who are praised for meeting a manager's expectations suffer
+a drop in motivation.
+
+Much of the research on creativity and motivation has been performed
+by Theresa Amabile, associate professor of psychology at Brandeis
+University. In a paper published early last year on her most recent
+study, she reported on experiments involving elementary school and
+college students. Both groups were asked to make "silly" collages.
+The young children were also asked to invent stories.
+
+The least-creative projects, as rated by several teachers, were done
+by those students who had contracted for rewards. "It may be that
+commissioned work will, in general, be less creative than work that is
+done out of pure interest," Amabile said.
+
+In 1985, Amabile asked 72 creative writers at Brandeis and at Boston
+University to write poetry. Some students then were given a list of
+extrinsic (external) reasons for writing, such as impressing teachers,
+making money and getting into graduate school, and were asked to think
+about their own writing with respect to these reasons. Others were
+given a list of intrinsic reasons: the enjoyment of playing with
+words, satisfaction from self-expression, and so forth. A third group
+was not given any list. All were then asked to do more writing.
+
+The results were clear. Students given the extrinsic reasons not only
+wrote less creatively than the others, as judged by 12 independent
+poets, but the quality of their work dropped significantly. Rewards,
+Amabile says, have this destructive effect primarily with creative
+tasks, including higher-level problem-solving. "The more complex the
+activity, the more it's hurt by extrinsic reward," she said.
+
+But other research shows that artists are by no means the only ones
+affected.
+
+In one study, girls in the fifth and sixth grades tutored younger
+children much less effectively if they were promised free movie
+tickets for teaching well. The study, by James Gabarino, now
+president of Chicago's Erikson Institute for Advanced Studies in Child
+Development, showed that tutors working for the reward took longer to
+communicate ideas, got frustrated more easily, and did a poorer job in
+the end than those who were not rewarded.
+
+Such findings call into question the widespread belief that money is
+an effective and even necessary way to motivate people. They also
+challenge the behaviorist assumption that any activity is more likely
+to occur if it is rewarded. Amabile says her research "definitely
+refutes the notion that creativity can be operantly conditioned."
+
+But Kenneth McGraw, associate professor of psychology at the
+University of Mississippi, cautions that this does not mean
+behaviorism itself has been invalidated. "The basic principles of
+reinforcement and rewards certainly work, but in a restricted context"
+- restricted, that is, to tasks that are not especially interesting.
+
+Researchers offer several explanations for their surprising findings
+about rewards and performance.
+
+First, rewards encourage people to focus narrowly on a task, to do it
+as quickly as possible and to take few risks. "If they feel that
+'this is something I hve to get through to get the prize,' the're
+going to be less creative," Amabile said.
+
+Second, people come to see themselves as being controlled by the
+reward. They feel less autonomous, and this may interfere with
+performance. "To the extent one's experience of being
+self-determined is limited," said Richard Ryan, associate psychology
+professor at the University of Rochester, "one's creativity will be
+reduced as well."
+
+Finally, extrinsic rewards can erode intrinsic interest. People who
+see themselves as working for money, approval or competitive success
+find their tasks less pleasurable, and therefore do not do them as
+well.
+
+The last explanation reflects 15 years of work by Ryan's mentor at the
+University of Rochester, Edward Deci. In 1971, Deci showed that
+"money may work to buy off one's intrinsic motivation for an activity"
+on a long-term basis. Ten years later, Deci and his colleagues
+demonstrated that trying to best others has the same effect. Students
+who competed to solve a puzzle quickly were less likely than those who
+were not competing to keep working at it once the experiment was over.
+
+Control plays role
+
+There is general agreement, however, that not all rewards have the
+same effect. Offering a flat fee for participating in an experiment -
+similar to an hourly wage in the workplace - usually does not reduce
+intrinsic motivation. It is only when the rewards are based on
+performing a given task or doing a good job at it - analogous to
+piece-rate payment and bonuses, respectively - that the problem
+develops.
+
+The key, then, lies in how a reward is experienced. If we come to
+view ourselves as working to get something, we will no longer find
+that activity worth doing in its own right.
+
+There is an old joke that nicely illustrates the principle. An
+elderly man, harassed by the taunts of neighborhood children, finally
+devises a scheme. He offered to pay each child a dollar if they would
+all return Tuesday and yell their insults again. They did so eagerly
+and received the money, but he told them he could only pay 25 cents on
+Wednesday. When they returned, insulted him again and collected their
+quarters, he informed them that Thursday's rate would be just a penny.
+"Forget it," they said - and never taunted him again.
+
+Means to and end
+
+In a 1982 study, Stanford psychologist Mark L. Lepper showed that any
+task, no matter how enjoyable it once seemed, would be devalued if it
+were presented as a means rather than an end. He told a group of
+preschoolers they could not engage in one activity they liked until
+they first took part in another. Although they had enjoyed both
+activities equally, the children came to dislike the task that was a
+prerequisite for the other.
+
+It should not be surprising that when verbal feedback is experienced
+as controlling, the effect on motivation can be similar to that of
+payment. In a study of corporate employees, Ryan found that those who
+were told, "Good, you're doing as you /should/" were "significantly
+less intrinsically motivated than those who received feedback
+informationally."
+
+There's a difference, Ryan says, between saying, "I'm giving you this
+reward because I recognize the value of your work" and "You're getting
+this reward because you've lived up to my standards."
+
+A different but related set of problems exists in the case of
+creativity. Artists must make a living, of course, but Amabile
+emphasizes that "the negative impact on creativity of working for
+rewards can be minimized" by playing down the significance of these
+rewards and trying not to use them in a controlling way. Creative
+work, the research suggests, cannot be forced, but only allowed to
+happen.
+
+/Alfie Kohn, a Cambridge, MA writer, is the author of "No Contest: The
+Case Against Competition," recently published by Houghton Mifflin Co.,
+Boston, MA. ISBN 0-395-39387-6. /
diff --git a/etc/Makefile b/etc/Makefile
new file mode 100644
index 00000000000..229aaab43b0
--- /dev/null
+++ b/etc/Makefile
@@ -0,0 +1,87 @@
+CFLAGS= -g
+# For Xenix. Needed for movemail
+# LOADLIBES= -lx
+# For Mips. Needed for who knows what.
+# CFLAGS = -g -systype bsd43
+
+EXECUTABLES = test-distrib etags ctags wakeup make-docfile \
+ digest-doc sorted-doc movemail cvtmail fakemail yow env \
+ server emacsclient
+
+all: ${EXECUTABLES}
+
+clean:
+ -rm -f ${EXECUTABLES} core
+
+distclean:
+ -rm -f ${EXECUTABLES} *~ \#* DOC* core
+
+# This justs verifies that the non-ASCII characters
+# in the file `testfile' have no been clobbered by
+# whatever means were used to copy and distribute Emacs.
+# If they were clobbered, all the .elc files were clobbered too.
+test-distrib: test-distrib.c
+ $(CC) -o test-distrib test-distrib.c
+ ./test-distrib
+
+etags: etags.c
+ $(CC) -o etags ${CFLAGS} -DETAGS etags.c $(LOADLIBES)
+
+ctags: etags.c
+ $(CC) -o ctags ${CFLAGS} -DCTAGS etags.c $(LOADLIBES)
+
+wakeup: wakeup.c
+ $(CC) -o wakeup ${CFLAGS} wakeup.c $(LOADLIBES)
+
+make-docfile: make-docfile.c
+ $(CC) -o make-docfile ${CFLAGS} make-docfile.c $(LOADLIBES)
+
+digest-doc: digest-doc.c
+ $(CC) -o digest-doc ${CFLAGS} digest-doc.c $(LOADLIBES)
+
+sorted-doc: sorted-doc.c
+ $(CC) -o sorted-doc ${CFLAGS} sorted-doc.c $(LOADLIBES)
+
+#
+movemail: movemail.c ../src/config.h
+ $(CC) -o movemail ${CFLAGS} movemail.c $(LOADLIBES)
+
+cvtmail: cvtmail.c
+ $(CC) -o cvtmail ${CFLAGS} cvtmail.c $(LOADLIBES)
+
+fakemail: fakemail.c ../src/config.h
+ $(CC) -o fakemail ${CFLAGS} fakemail.c $(LOADLIBES)
+
+yow: yow.c ../src/paths.h
+ $(CC) -o yow ${CFLAGS} yow.c $(LOADLIBES)
+
+# this is silly -- just use emacs to edit this file!
+# (in any case this program doesn't preserve alphabetical ordering,
+# which is why I'm removing it)
+#addyow: addyow.c
+# $(CC) -o addyow ${CFLAGS} addyow.c
+
+env: env.c ../src/config.h
+ $(CC) -o env -DEMACS ${CFLAGS} env.c $(LOADLIBES)
+
+server: server.c ../src/config.h
+ $(CC) -o server ${CFLAGS} server.c $(LOADLIBES)
+
+emacsclient: emacsclient.c ../src/config.h
+ $(CC) -o emacsclient ${CFLAGS} emacsclient.c $(LOADLIBES)
+
+# This one is NOT included in EXECUTABLES.
+# See ../src/ymakefile.
+emacstool: emacstool.c
+ $(CC) -o emacstool ${CFLAGS} emacstool.c -lsuntool -lsunwindow -lpixrect $(LOADLIBES)
+
+nemacstool: emacstool.c
+ $(CC) -o nemacstool ${CFLAGS} -DJLE emacstool.c -lsuntool -lmle -lsunwindow -lpixrect $(LOADLIBES) # For SUN Japanese Language Environment
+
+xvetool: emacstool.c
+ $(CC) -o xvetool ${CFLAGS} -DXVIEW emacstool.c -lxview -lolgx -lX -I$(OPENWINHOME)/include -L$(OPENWINHOME)/lib $(LOADLIBES)
+
+xveterm: emacstool.c
+ $(CC) -o xveterm ${CFLAGS} -DXVIEW -DTTERM emacstool.c -lxview -lolgx -lX -I$(OPENWINHOME)/include -L$(OPENWINHOME)/lib $(LOADLIBES)
+
+
diff --git a/etc/NEWS b/etc/NEWS
new file mode 100644
index 00000000000..61d72912eae
--- /dev/null
+++ b/etc/NEWS
@@ -0,0 +1,1655 @@
+GNU Emacs NEWS -- history of user-visible changes. 3 Feb 1992
+Copyright (C) 1988, 1990, 1992 Free Software Foundation, Inc.
+See the end for copying conditions.
+
+Changes in version 18.58.
+
+* RMAIL reply now properly parses nested comments in addresses.
+
+* The "visual bell" feature when used with X windows
+now flashes only 1/4 of the window's total area. This is because
+flashing the whole window is too slow on some systems.
+
+* call-process and call-process-region now return an indication
+of the exit status of the subprocess: either a numeric exit code
+or a string describing the signal which caused termination.
+
+* It is possible for regular expression matching to overflow the stack
+of failure points. In the past, such overflow was treated as simple
+failure to match. Now it causes an error.
+
+* You can use C-u to end a numeric argument. Thus, type C-u 1 0 0 C-u 1
+to insert 100 1's.
+
+* Emacs now knows how to get resource values from the X server.
+
+* Job control commands in shell mode work properly on more systems
+because they now work by "typing" signal characters such as C-c.
+
+* copy-keymap no longer recursively copies keymaps reached through
+symbols' function definitions (i.e., those that have names). It does
+copy nested keymaps that appear directly in the other copied keymaps.
+
+Changes in version 18.56.
+
+* C-g should now work to interrupt a running program
+on all kinds of systems even when using X windows.
+
+* Quitting is inhibited while a filter or sentinel is running.
+Those functions can run asynchronously while Emacs is waiting
+for keyboard input, and if they allow quitting, they
+make the behavior of C-g unpredictable.
+
+* Storing text into the X windows cut buffer
+now clears out any selection.
+
+* The undo facility is completely rewritten, and now
+uses Lisp data structures. It can record much more
+information. You can use the variables undo-threshold
+and undo-high-threshold to control how much.
+
+* There is no longer a maximum screen height or width.
+
+Changes in version 18.52.
+
+* X windows version 10 is supported under system V.
+
+* Pop-up menus are now supported with the same Lisp interface in
+both version 10 and 11 of X windows.
+
+* C-x 4 a is a new command to edit a change-log entry in another window.
+
+* The emacs client program now allows an option +NNN to specify the
+line number to go to in the file whose name follows. Thus,
+ emacsclient foo.c +45 bar.c
+will find the files `foo.c' and `bar.c', going to line 45 in `bar.c'.
+
+* Dired allows empty directories to be deleted like files.
+
+* When the terminal type is used to find a terminal-specific file to
+run, Emacs now tries the entire terminal type first. If that doesn't
+yield a file that exists, the last hyphen and what follows it is
+stripped. If that doesn't yield a file that exists, the previous
+hyphen is stripped, and so on until all hyphens are gone. For
+example, if the terminal type is `aaa-48-foo', Emacs will try first
+`term/aaa-48-foo.el', then `term/aaa-48.el' and finally `term/aaa.el'.
+
+Underscores now receive the same treatment as hyphens.
+
+* Texinfo features: @defun, etc. texinfo-show-structure.
+New template commands. texinfo-format-region.
+
+* The special "local variable" `eval' is now ignored if you are running
+as root.
+
+* New command `c-macro-expand' shows the result of C macro expansion
+in the region. It works using the C preprocessor, so its results
+are completely accurate.
+
+* Errors in trying to auto save now flash error messages for a few seconds.
+
+* Killing a buffer now sends SIGHUP to the buffer's process.
+
+* New hooks.
+
+** `spell-region' now allows you to filter the text before spelling-checking.
+If the value of `spell-filter' is non-nil, it is called, with no arguments,
+looking at a temporary buffer containing a copy of the text to be checked.
+It can alter the text freely before the spell program sees it.
+
+** The variable `lpr-command' now specifies the command to be used when
+you use the commands to print text (such as M-x print-buffer).
+
+** Posting netnews now calls the value of `news-inews-hook' (if not nil)
+as a function of no arguments before the actual posting.
+
+** Rmail now calls the value of `rmail-show-message-hook' (if not nil)
+as a function of no arguments, each time a new message is selected.
+
+** `kill-emacs' calls the value of `kill-emacs-hook' as a function of no args.
+
+* New libraries.
+See the source code of each library for more information.
+
+** icon.el: a major mode for editing programs written in Icon.
+
+** life.el: a simulator for the cellular automaton "life". Load the
+library and run M-x life.
+
+** doctex.el: a library for converting the Emacs `etc/DOC' file of
+documentation strings into TeX input.
+
+** saveconf.el: a library which records the arrangement of windows and
+buffers when you exit Emacs, and automatically recreates the same
+setup the next time you start Emacs.
+
+** uncompress.el: a library that automatically uncompresses files
+when you visit them.
+
+** c-fill.el: a mode for editing filled comments in C.
+
+** kermit.el: an extended version of shell-mode designed for running kermit.
+
+** spook.el: a library for adding some "distract the NSA" keywords to every
+message you send.
+
+** hideif.el: a library for hiding parts of a C program based on preprocessor
+conditionals.
+
+** autoinsert.el: a library to put in some initial text when you visit
+a nonexistent file. The text used depends on the major mode, and
+comes from a directory of files created by you.
+
+* New programming features.
+
+** The variable `window-system-version' now contains the version number
+of the window system you are using (if appropriate). When using X windows,
+its value is either 10 or 11.
+
+** (interactive "N") uses the prefix argument if any; otherwise, it reads
+a number using the minibuffer.
+
+** VMS: there are two new functions `vms-system-info' and `shrink-to-icon'.
+The former allows you to get many kinds of system status information.
+See its self-documentation for full details.
+The second is used with the window system: it iconifies the Emacs window.
+
+** VMS: the new function `define-logical-name' allows you to create
+job-wide logical names. The old function `define-dcl-symbol' has been
+removed.
+
+Changes in version 18.50.
+
+* X windows version 11 is supported.
+
+Define X11 in config.h if you want X version 11 instead of version 10.
+
+* The command M-x gdb runs the GDB debugger as an inferior.
+It asks for the filename of the executable you want to debug.
+
+GDB runs as an inferior with I/O through an Emacs buffer. All the
+facilities of Shell mode are available. In addition, each time your
+program stops, and each time you select a new stack frame, the source
+code is displayed in another window with an arrow added to the line
+where the program is executing.
+
+Special GDB-mode commands include M-s, M-n, M-i, M-u, M-d, and C-c C-f
+which send the GDB commands `step', `next', `stepi', `up', `down'
+and `finish'.
+
+In any source file, the commands C-x SPC tells GDB to set a breakpoint
+on the current line.
+
+* M-x calendar displays a three-month calendar.
+
+* C-u 0 C-x C-s never makes a backup file.
+
+This is a way you can explicitly request not to make a backup.
+
+* `term-setup-hook' is for users only.
+
+Emacs never uses this variable for internal purposes, so you can freely
+set it in your `.emacs' file to make Emacs do something special after
+loading any terminal-specific setup file from `lisp/term'.
+
+* `copy-keymap' now copies recursive submaps.
+
+* New overlay-arrow feature.
+
+If you set the variable `overlay-arrow-string' to a string
+and `overlay-arrow-position' to a marker, that string is displayed on
+the screen at the position of that marker, hiding whatever text would
+have appeared there. If that position isn't on the screen, or if
+the buffer the marker points into isn't displayed, there is no effect.
+
+* -batch mode can read from the terminal.
+
+It now works to use `read-char' to do terminal input in a noninteractive
+Emacs run. End of file causes Emacs to exit.
+
+* Variables `data-bytes-used' and `data-bytes-free' removed.
+
+These variables cannot really work because the 24-bit range of an
+integer in (most ports of) GNU Emacs is not large enough to hold their
+values on many systems.
+
+Changes in version 18.45, since version 18.41.
+
+* C indentation parameter `c-continued-brace-offset'.
+
+This parameter's value is added to the indentation of any
+line that is in a continuation context and starts with an open-brace.
+For example, it applies to the open brace shown here:
+
+ if (x)
+ {
+
+The default value is zero.
+
+* Dabbrev expansion (Meta-/) preserves case.
+
+When you use Meta-/ to search the buffer for an expansion of an
+abbreviation, if the expansion found is all lower case except perhaps
+for its first letter, then the case pattern of the abbreviation
+is carried over to the expansion that replaces it.
+
+* TeX-mode syntax.
+
+\ is no longer given "escape character" syntax in TeX mode. It now
+has the syntax of an ordinary punctuation character. As a result,
+\[...\] and such like are considered to balance each other.
+
+* Mail-mode automatic Reply-to field.
+
+If the variable `mail-default-reply-to' is non-`nil', then each time
+you start to compose a message, a Reply-to field is inserted with
+its contents taken from the value of `mail-default-reply-to'.
+
+* Where is your .emacs file?
+
+If you run Emacs under `su', so your real and effective uids are
+different, Emacs uses the home directory associated with the real uid
+(the name you actually logged in under) to find the .emacs file.
+
+Otherwise, Emacs uses the environment variable HOME to find the .emacs
+file.
+
+The .emacs file is not loaded at all if -batch is specified.
+
+* Prolog mode is the default for ".pl" files.
+
+* File names are not case-sensitive on VMS.
+
+On VMS systems, all file names that you specify are converted to upper
+case. You can use either upper or lower case indiscriminately.
+
+* VMS-only function 'define-dcl-symbol'.
+
+This is a new name for the function formerly called
+`define-logical-name'.
+
+Editing Changes in Emacs 18
+
+* Additional systems and machines are supported.
+
+GNU Emacs now runs on Vax VMS. However, many facilities that are normally
+implemented by running subprocesses do not work yet. This includes listing
+a directory and sending mail. There are features for running subprocesses
+but they are incompatible with those on Unix. I hope that some of
+the VMS users can reimplement these features for VMS (compatibly for
+the user, if possible).
+
+VMS wizards are also asked to work on making the subprocess facilities
+more upward compatible with those on Unix, and also to rewrite their
+internals to use the same Lisp objects that are used on Unix to
+represent processes.
+
+In addition, the TI Nu machine running Unix system V, the AT&T 3b, and
+the Wicat, Masscomp, Integrated Solutions, Alliant, Amdahl uts, Mips,
+Altos 3068 and Gould Unix systems are now supported. The IBM PC-RT is
+supported under 4.2, but not yet under system V. The GEC 93 is close
+to working. The port for the Elxsi is partly merged. See the file
+MACHINES for full status information and machine-specific installation
+advice.
+
+* Searching is faster.
+
+Forward search for a text string, or for a regexp that is equivalent
+to a text string, is now several times faster. Motion by lines and
+counting lines is also faster.
+
+* Memory usage improvements.
+
+It is no longer possible to run out of memory during garbage
+collection. As a result, running out of memory is never fatal. This
+is due to a new garbage collection algorithm which compactifies
+strings in place rather than copying them. Another consequence of the
+change is a reduction in total memory usage and a slight increase in
+garbage collection speed.
+
+* Display changes.
+
+** Editing above top of screen.
+
+When you delete or kill or alter text that reaches to the top of the
+screen or above it, so that display would start in the middle of a
+line, Emacs will usually attempt to scroll the text so that display
+starts at the beginning of a line again.
+
+** Yanking in the minibuffer.
+
+The message "Mark Set" is no longer printed when the minibuffer is
+active. This is convenient with many commands, including C-y, that
+normally print such a message.
+
+** Cursor appears in last line during y-or-n questions.
+
+Questions that want a `y' or `n' answer now move the cursor
+to the last line, following the question.
+
+* Library loading changes.
+
+`load' now considers all possible suffixes (`.elc', `.el' and none)
+for each directory in `load-path' before going on to the next directory.
+It now accepts an optional fourth argument which, if non-nil, says to
+use no suffixes; then the file name must be given in full. The search
+of the directories in `load-path' goes on as usual in this case, but
+it too can be prevented by passing an absolute file name.
+
+The value of `load-path' no longer by default includes nil (meaning to
+look in the current default directory). The idea is that `load' should
+be used to search the path only for libraries to be found in the standard
+places. If you want to override system libraries with your own, place
+your own libraries in one special directory and add that directory to the
+front of `load-path'.
+
+The function `load' is no longer a command; that is to say, `M-x load'
+is no longer allowed. Instead, there are two commands for loading files.
+`M-x load-library' is equivalent to the old meaning of `M-x load'.
+`M-x load-file' reads a file name with completion and defaulting
+and then loads exactly that file, with no searching and no suffixes.
+
+* Emulation of other editors.
+
+** `edt-emulation-on' starts emulating DEC's EDT editor.
+
+Do `edt-emulation-off' to return Emacs to normal.
+
+** `vi-mode' and `vip-mode' starts emulating vi.
+
+These are two different vi emulations provided by GNU Emacs users.
+We are interested in feedback as to which emulation is preferable.
+
+See the documentation and source code for these functions
+for more information.
+
+** `set-gosmacs-bindings' emulates Gosling Emacs.
+
+This command changes many global bindings to resemble those of
+Gosling Emacs. The previous bindings are saved and can be restored using
+`set-gnu-bindings'.
+
+* Emulation of a display terminal.
+
+Within Emacs it is now possible to run programs (such as emacs or
+supdup) which expect to do output to a visual display terminal.
+
+See the function `terminal-emulator' for more information.
+
+* New support for keypads and function keys.
+
+There is now a first attempt at terminal-independent support for
+keypad and function keys.
+
+Emacs now defines a standard set of key-names for function and keypad
+keys, and provides standard hooks for defining them. Most of the
+standard key-names have default definitions built into Emacs; you can
+override these in a terminal-independent manner. The default definitions
+and the conventions for redefining them are in the file `lisp/keypad.el'.
+
+These keys on the terminal normally work by sending sequences of
+characters starting with ESC. The exact sequences used vary from
+terminal to terminal. Emacs interprets them in two stages:
+in the first stage, terminal-dependent sequences are mapped into
+the standard key-names; then second stage maps the standard key-names
+into their definitions in a terminal-independent fashion.
+
+The terminal-specific file `term/$TERM.el' now is responsible only for
+establishing the mapping from the terminal's escape sequences into
+standard key-names. It no longer knows what Emacs commands are
+assigned to the standard key-names.
+
+One other change in terminal-specific files: if the value of the TERM
+variable contains a hyphen, only the part before the first hyphen is
+used in forming the name of the terminal-specific file. Thus, for
+terminal type `aaa-48', the file loaded is now `term/aaa.el' rather
+than `term/aaa-48.el'.
+
+* New startup command line options.
+
+`-i FILE' or `-insert FILE' in the command line to Emacs tells Emacs to
+insert the contents of FILE into the current buffer at that point in
+command line processing. This is like using the command M-x insert-file.
+
+`-funcall', `-load', `-user' and `-no-init-file' are new synonyms for
+`-f', `-l', `-u' and `-q'.
+
+`-nw' means don't use a window system. If you are using a terminal
+emulator on the X window system and you want to run Emacs to work through
+the terminal emulator instead of working directly with the window system,
+use this switch.
+
+* Buffer-sorting commands.
+
+Various M-x commands whose names start with `sort-' sort parts of
+the region:
+
+sort-lines divides the region into lines and sorts them alphabetically.
+sort-pages divides into pages and sorts them alphabetically.
+sort-paragraphs divides into paragraphs and sorts them alphabetically.
+sort-fields divides into lines and sorts them alphabetically
+ according to one field in the line.
+ The numeric argument specifies which field (counting
+ from field 1 at the beginning of the line). Fields in a line
+ are separated by whitespace.
+sort-numeric-fields
+ is similar but converts the specified fields to numbers
+ and sorts them numerically.
+sort-columns divides into lines and sorts them according to the contents
+ of a specified range of columns.
+
+Refer to the self-documentation of these commands for full usage information.
+
+* Changes in various commands.
+
+** `tags-query-replace' and `tags-search' change.
+
+These functions now display the name of the file being searched at the moment.
+
+** `occur' output now serves as a menu. `occur-menu' command deleted.
+
+`M-x occur' now allows you to move quickly to any of the occurrences
+listed. Select the `*Occur*' buffer that contains the output of `occur',
+move point to the occurrence you want, and type C-c C-c.
+This will move point to the same occurrence in the buffer that the
+occurrences were found in.
+
+The command `occur-menu' is thus obsolete, and has been deleted.
+
+One way to get a list of matching lines without line numbers is to
+copy the text to another buffer and use the command `keep-lines'.
+
+** Incremental search changes.
+
+Ordinary and regexp incremental searches now have distinct default
+search strings. Thus, regexp searches recall only previous regexp
+searches.
+
+If you exit an incremental search when the search string is empty,
+the old default search string is kept. The default does not become
+empty.
+
+Reversing the direction of an incremental search with C-s or C-r
+when the search string is empty now does not get the default search
+string. It leaves the search string empty. A second C-s or C-r
+will get the default search string. As a result, you can do a reverse
+incremental regexp search with C-M-s C-r.
+
+If you add a `*', `?' or `\|' to an incremental search regexp,
+point will back up if that is appropriate. For example, if
+you have searched for `ab' and add a `*', point moves to the
+first match for `ab*', which may be before the match for `ab'
+that was previously found.
+
+If an incremental search is failing and you ask to repeat it,
+it will start again from the beginning of the buffer (or the end,
+if it is a backward search).
+
+The search-controlling parameters `isearch-slow-speed' and
+`isearch-slow-window-lines' have now been renamed to start with
+`search' instead of `isearch'. Now all the parameters' names start
+with `search'.
+
+If `search-slow-window-lines' is negative, the slow search window
+is put at the top of the screen, and the absolute value or the
+negative number specifies the height of it.
+
+** Undo changes
+
+The undo command now will mark the buffer as unmodified only when it is
+identical to the contents of the visited file.
+
+** C-M-v in minibuffer.
+
+If while in the minibuffer you request help in a way that uses a
+window to display something, then until you exit the minibuffer C-M-v
+in the minibuffer window scrolls the window of help.
+
+For example, if you request a list of possible completions, C-M-v can
+be used reliably to scroll the completion list.
+
+** M-TAB command.
+
+Meta-TAB performs completion on the Emacs Lisp symbol names. The sexp
+in the buffer before point is compared against all existing nontrivial
+Lisp symbols and completed as far as is uniquely determined by them.
+Nontrivial symbols are those with either function definitions, values
+or properties.
+
+If there are multiple possibilities for the very next character, a
+list of possible completions is displayed.
+
+** Dynamic abbreviation package.
+
+The new command Meta-/ expands an abbreviation in the buffer before point
+by searching the buffer for words that start with the abbreviation.
+
+** Changes in saving kbd macros.
+
+The commands `write-kbd-macro' and `append-kbd-macro' have been
+deleted. The way to save a keyboard macro is to use the new command
+`insert-kbd-macro', which inserts Lisp code to define the macro as
+it is currently defined into the buffer before point. Visit a Lisp
+file such as your Emacs init file `~/.emacs', insert the macro
+definition (perhaps deleting an old definition for the same macro)
+and then save the file.
+
+** C-x ' command.
+
+The new command C-x ' (expand-abbrev) expands the word before point as
+an abbrev, even if abbrev-mode is not turned on.
+
+** Sending to inferior Lisp.
+
+The command C-M-x in Lisp mode, which sends the current defun to
+an inferior Lisp process, now works by writing the text into a temporary
+file and actually sending only a `load'-form to load the file.
+As a result, it avoids the Unix bugs that used to strike when the
+text was above a certain length.
+
+With a prefix argument, this command now makes the inferior Lisp buffer
+appear on the screen and scrolls it so that the bottom is showing.
+
+Two variables `inferior-lisp-load-command' and `inferior-lisp-prompt',
+exist to customize these feature for different Lisp implementations.
+
+** C-x p now disabled.
+
+The command C-x p, a nonrecomended command which narrows to the current
+page, is now initially disabled like C-x n.
+
+* Dealing with files.
+
+** C-x C-v generalized
+
+This command is now allowed even if the current buffer is not visiting
+a file. As usual, it kills the current buffer and replaces it with a
+newly found file.
+
+** M-x recover-file improved; auto save file names changed.
+
+M-x recover-file now checks whether the last auto-save file is more
+recent than the real visited file before offering to read in the
+auto-save file. If the auto-save file is newer, a directory listing
+containing the two files is displayed while you are asked whether you
+want the auto save file.
+
+Visiting a file also makes this check. If the auto-save file is more recent,
+a message is printed suggesting that you consider using M-x recover file.
+
+Auto save file names now by default have a `#' at the end as well
+as at the beginning. This is so that `*.c' in a shell command
+will never match auto save files.
+
+On VMS, auto save file names are made by appending `_$' at the front
+and `$' at the end.
+
+When you change the visited file name of a buffer, the auto save file
+is now renamed to belong to the new visited file name.
+
+You can customize the way auto save file names are made by redefining
+the two functions `make-auto-save-file-name' and `auto-save-file-name-p',
+both of which are defined in `files.el'.
+
+** Modifying a buffer whose file is changed on disk is detected instantly.
+
+On systems where clash detection (locking of files being edited) is
+implemented, Emacs also checks the first time you modify a buffer
+whether the file has changed on disk since it was last visited or saved.
+If it has, you are asked to confirm that you want to change the buffer.
+
+** Exiting Emacs offers to save `*mail*'.
+
+Emacs can now know about buffers that it should offer to save on exit
+even though they are not visiting files. This is done for any buffer
+which has a non-nil local value of `buffer-offer-save'. By default,
+Mail mode provides such a local value.
+
+** Backup file changes.
+
+If a backup file cannot be written in the directory of the visited file
+due to fascist file protection, a backup file is now written in your home
+directory as `~/%backup%~'. Only one such file is made, ever, so only
+the most recently made such backup is available.
+
+When backup files are made by copying, the last-modification time of the
+original file is now preserved in the backup copy.
+
+** Visiting remote files.
+
+On an internet host, you can now visit and save files on any other
+internet host directly from Emacs with the commands M-x ftp-find-file
+and M-x ftp-write-file. Specify an argument of the form HOST:FILENAME.
+Since standard internet FTP is used, the other host may be any kind
+of machine and is not required to have any special facilities.
+
+The first time any one remote host is accessed, you will be asked to
+give the user name and password for use on that host. FTP is reinvoked
+each time you ask to use it, but previously specified user names and
+passwords are remembered automatically.
+
+** Dired `g' command.
+
+`g' in Dired mode is equivalent to M-x revert-buffer; it causes the
+current contents of the same directory to be read in.
+
+* Changes in major modes.
+
+** C mode indentation change.
+
+The binding of Linefeed is no longer changed by C mode. It once again
+has its normal meaning, which is to insert a newline and then indent
+afterward.
+
+The old definition did one additional thing: it reindented the line
+before the new newline. This has been removed because it made the
+command twice as slow. The only time it was really useful was after the
+insertion of an `else', since the fact of starting with `else' may change
+the way that line is indented. Now you will have to type TAB again
+yourself to reindent the `else' properly.
+
+If the variable `c-tab-always-indent' is set to `nil', the TAB command
+in C mode, with no argument, will just insert a tab character if there
+is non-whitespace preceding point on the current line. Giving it a
+prefix argument will force reindentation of the line (as well as
+of the compound statement that begins after point, if any).
+
+** Fortran mode now exists.
+
+This mode provides commands for motion and indentation of Fortran code,
+plus built-in abbrevs for Fortran keywords. For details, see the manual
+or the on-line documentation of the command `fortran-mode'.
+
+** Scribe mode now exists.
+
+This mode does something useful for editing files of Scribe input.
+It is used automatically for files with names ending in ".mss".
+
+** Modula2 and Prolog modes now exist.
+
+These modes are for editing programs in the languages of the same names.
+They can be selected with M-x modula-2-mode and M-x prolog-mode.
+
+** Telnet mode changes.
+
+The telnet mode special commands have now been assigned to C-c keys.
+Most of them are the same as in Shell mode.
+
+** Picture mode changes.
+
+The special picture-mode commands to specify the direction of cursor
+motion after insertion have been moved to C-c keys. The commands to
+specify diagonal motion were already C-c keys; they are unchanged.
+The keys to specify horizontal or vertical motion are now
+C-c < (left), C-c > (right), C-c ^ (up) and C-c . (down).
+
+** Nroff mode comments.
+
+Comments are now supported in Nroff mode. The standard comment commands
+such as M-; and C-x ; know how to insert, align and delete comments
+that start with backslash-doublequote.
+
+** LaTeX mode.
+
+LaTeX mode now exists. Use M-x latex-mode to select this mode, and
+M-x plain-tex-mode to select the previously existing mode for Plain
+TeX. M-x tex-mode attempts to examine the contents of the buffer and
+choose between latex-mode and plain-tex-mode accordingly; if the
+buffer is empty or it cannot tell, the variable `TeX-default-mode'
+controls the choice. Its value should be the symbol for the mode to
+be used.
+
+The facilities for running TeX on all or part of the buffer
+work with LaTeX as well.
+
+Some new commands available in both modes:
+
+C-c C-l recenter the window showing the TeX output buffer
+ so most recent line of output can be seen.
+C-c C-k kill the TeX subprocess.
+C-c C-q show the printer queue.
+C-c C-f close a block (appropriate for LaTeX only).
+ If the current line contains a \begin{...},
+ this inserts an \end{...} on the following line
+ and puts point on a blank line between them.
+
+** Outline mode changes.
+
+Invisible lines in outline mode are now indicated by `...' at the
+end of the previous visible line.
+
+The special outline heading motion commands are now all on C-c keys.
+A few new ones have been added. Here is a full list:
+
+C-c C-n Move to next visible heading (formerly M-})
+C-c C-p Move to previous visible heading (formerly M-{)
+C-c C-f Move to next visible heading at the same level.
+ Thus, if point is on a level-2 heading line,
+ this command moves to the next visible level-2 heading.
+C-c C-b Move to previous visible heading at the same level.
+C-c C-u Move up to previous visible heading at a higher level.
+
+The variable `outline-regexp' now controls recognition of heading lines.
+Any line whose beginning matches this regexp is a heading line.
+The depth in outline structure is determined by the length of
+the string that matches.
+
+A line starting with a ^L (formfeed) is now by default considered
+a header line.
+
+* Mail reading and sending.
+
+** MH-E changes.
+
+MH-E has been extensively modified and improved since the v17 release.
+It contains many new features, including commands to: extracted failed
+messages, kill a draft message, undo changes to a mail folder, monitor
+delivery of a letter, print multiple messages, page digests backwards,
+insert signatures, and burst digests. Also, many commands have been
+made to able to deal with named sequences of messages, instead of
+single messages. MH-E also has had numerous bugs fixed and commands
+made to run faster. Furthermore, its keybindings have been changed to
+be compatible with Rmail and the rest of GNU Emacs.
+
+** Mail mode changes.
+
+The C-c commands of mail mode have been rearranged:
+
+C-c s, C-c c, C-c t and C-c b (move point to various header fields)
+have been reassigned as C-c C-f C-s, C-c C-f C-c, C-c C-f C-t and C-c
+C-f C-b. C-c C-f is for "field".
+
+C-c y, C-c w and C-c q have been changed to C-c C-y, C-c C-w and C-c C-q.
+
+Thus, C-c LETTER is always unassigned.
+
+** Rmail C-r command changed to w.
+
+The Rmail command to edit the current message is now `w'. This change
+has been made because people frequently type C-r while in Rmail hoping
+to do a reverse incremental search. That now works.
+
+* Rnews changes.
+
+** Caesar rotation added.
+
+The function news-caesar-buffer-body performs encryption and
+decryption of the body of a news message. It defaults to the USENET
+standard of 13, and accepts any numeric arg between 1 to 25 and -25 to -1.
+The function is bound to C-c C-r in both news-mode and news-reply-mode.
+
+** rmail-output command added.
+
+The C-o command has been bound to rmail-output in news-mode.
+This allows one to append an article to a file which is in either Unix
+mail or RMAIL format.
+
+** news-reply-mode changes.
+
+The C-c commands of news reply mode have been rearranged and changed,
+so that C-c LETTER is always unassigned:
+
+C-c y, C-c w and C-c q have been changed to C-c C-y, C-c C-w and C-c C-q.
+
+C-c c, C-c t, and C-c b (move to various mail header fields) have been
+deleted (they make no sense for posting and replying to USENET).
+
+C-c s (move to Subject: header field) has been reassigned as C-c C-f
+C-s. C-c C-f is for "field". Several additional move to news header
+field commands have been added.
+
+The local news-reply-mode bindings now look like this:
+
+C-c C-s news-inews (post the message) C-c C-c news-inews
+C-c C-f move to a header field (and create it if there isn't):
+ C-c C-f C-n move to Newsgroups: C-c C-f C-s move to Subj:
+ C-c C-f C-f move to Followup-To: C-c C-f C-k move to Keywords:
+ C-c C-f C-d move to Distribution: C-c C-f C-a move to Summary:
+C-c C-y news-reply-yank-original (insert current message, in NEWS).
+C-c C-q mail-fill-yanked-message (fill what was yanked).
+C-c C-r caesar rotate all letters by 13 places in the article's body (rot13).
+
+* Existing Emacs usable as a server.
+
+Programs such as mailers that invoke "the editor" as an inferior
+to edit some text can now be told to use an existing Emacs process
+instead of creating a new editor.
+
+To do this, you must have an Emacs process running and capable of
+doing terminal I/O at the time you want to invoke it. This means that
+either you are using a window system and give Emacs a separate window
+or you run the other programs as inferiors of Emacs (such as, using
+M-x shell).
+
+First prepare the existing Emacs process by loading the `server'
+library and executing M-x server-start. (Your .emacs can do this
+automatically.)
+
+Now tell the other programs to use, as "the editor", the Emacs client
+program (etc/emacsclient, located in the same directory as this file).
+This can be done by setting the environment variable EDITOR.
+
+When another program invokes the emacsclient as "the editor", the
+client actually transfers the file names to be edited to the existing
+Emacs, which automatically visits the files.
+
+When you are done editing a buffer for a client, do C-x # (server-edit).
+This marks that buffer as done, and selects the next buffer that the client
+asked for. When all the buffers requested by a client are marked in this
+way, Emacs tells the client program to exit, so that the program that
+invoked "the editor" will resume execution.
+
+You can only have one server Emacs at a time, but multiple client programs
+can put in requests at the same time.
+
+The client/server work only on Berkeley Unix, since they use the Berkeley
+sockets mechanism for their communication.
+
+Changes in Lisp programming in Emacs version 18.
+
+* Init file changes.
+
+** Suffixes no longer accepted on `.emacs'.
+
+Emacs will no longer load a file named `.emacs.el' or `emacs.elc'
+in place of `.emacs'. This is so that it will take less time to
+find `.emacs'. If you want to compile your init file, give it another
+name and make `.emacs' a link to the `.elc' file, or make it contain
+a call to `load' to load the `.elc' file.
+
+** `default-profile' renamed to `default', and loaded after `.emacs'.
+
+It used to be the case that the file `default-profile' was loaded if
+and only if `.emacs' was not found.
+
+Now the name `default-profile' is not used at all. Instead, a library
+named `default' is loaded after the `.emacs' file. `default' is loaded
+whether the `.emacs' file exists or not. However, loading of `default'
+can be prevented if the `.emacs' file sets `inhibit-default-init' to non-nil.
+
+In fact, you would call the default file `default.el' and probably would
+byte-compile it to speed execution.
+
+Note that for most purposes you are better off using a `site-init' library
+since that will be loaded before the runnable Emacs is dumped. By using
+a `site-init' library, you avoid taking up time each time Emacs is started.
+
+** inhibit-command-line has been eliminated.
+
+This variable used to exist for .emacs files to set. It has been
+eliminated because you can get the same effect by setting
+command-line-args to nil and setting inhibit-startup-message to t.
+
+* `apply' is more general.
+
+`apply' now accepts any number of arguments. The first one is a function;
+the rest are individual arguments to pass to that function, except for the
+last, which is a list of arguments to pass.
+
+Previously, `apply' required exactly two arguments. Its old behavior
+follows as a special case of the new definition.
+
+* New code-letter for `interactive'.
+
+(interactive "NFoo: ") is like (interactive "nFoo: ") in reading
+a number using the minibuffer to serve as the argument; however,
+if a prefix argument was specified, it uses the prefix argument
+value as the argument, and does not use the minibuffer at all.
+
+This is used by the `goto-line' and `goto-char' commands.
+
+* Semantics of variables.
+
+** Built-in per-buffer variables improved.
+
+Several built-in variables which in the past had a different value in
+each buffer now behave exactly as if `make-variable-buffer-local' had
+been done to them.
+
+These variables are `tab-width', `ctl-arrow', `truncate-lines',
+`fill-column', `left-margin', `mode-line-format', `abbrev-mode',
+`overwrite-mode', `case-fold-search', `auto-fill-hook',
+`selective-display', `selective-display-ellipses'.
+
+To be precise, each variable has a default value which shows through
+in most buffers and can be accessed with `default-value' and set with
+`set-default'. Setting the variable with `setq' makes the variable
+local to the current buffer. Changing the default value has retroactive
+effect on all buffers in which the variable is not local.
+
+The variables `default-case-fold-search', etc., are now obsolete.
+They now refer to the default value of the variable, which is not
+quite the same behavior as before, but it should enable old init files
+to continue to work.
+
+** New per-buffer variables.
+
+The variables `fill-prefix', `comment-column' and `indent-tabs-mode'
+are now per-buffer. They work just like `fill-column', etc.
+
+** New function `setq-default'.
+
+`setq-default' sets the default value of a variable, and uses the
+same syntax that `setq' accepts: the variable name is not evaluated
+and need not be quoted.
+
+`(setq-default case-fold-search nil)' would make searches case-sensitive
+in all buffers that do not have local values for `case-fold-search'.
+
+** Functions `global-set' and `global-value' deleted.
+
+These functions were never used except by mistake by users expecting
+the functionality of `set-default' and `default-value'.
+
+* Changes in defaulting of major modes.
+
+When `default-major-mode' is `nil', new buffers are supposed to
+get their major mode from the buffer that is current. However,
+certain major modes (such as Dired mode, Rmail mode, Rmail Summary mode,
+and others) are not reasonable to use in this way.
+
+Now such modes' names have been given non-`nil' `mode-class' properties.
+If the current buffer's mode has such a property, Fundamental mode is
+used as the default for newly created buffers.
+
+* `where-is-internal' requires additional arguments.
+
+This function now accepts three arguments, two of them required:
+DEFINITION, the definition to search for; LOCAL-KEYMAP, the keymap
+to use as the local map when doing the searching, and FIRST-ONLY,
+which is nonzero to return only the first key found.
+
+This function returns a list of keys (strings) whose definitions
+(in the LOCAL-KEYMAP or the current global map) are DEFINITION.
+
+If FIRST-ONLY is non-nil, it returns a single key (string).
+
+This function has changed incompatibly in that now two arguments
+are required when previously only one argument was allowed. To get
+the old behavior of this function, write `(current-local-map)' as
+the expression for the second argument.
+
+The incompatibility is sad, but `nil' is a legitimate value for the
+second argument (it means there is no local keymap), so it cannot also
+serve as a default meaning to use the current local keymap.
+
+* Abbrevs with hooks.
+
+When an abbrev defined with a hook is expanded, it now performs the
+usual replacement of the abbrev with the expansion before running the
+hook. Previously the abbrev itself was deleted but the expansion was
+not inserted.
+
+* Function `scan-buffer' deleted.
+
+Use `search-forward' or `search-backward' in place of `scan-buffer'.
+You will have to rearrange the arguments.
+
+* X window interface improvements.
+
+** Detect release of mouse buttons.
+
+Button-up events can now be detected. See the file `lisp/x-mouse.el'
+for details.
+
+** New pop-up menu facility.
+
+The new function `x-popup-menu' pops up a menu (in a X window)
+and returns an indication of which selection the user made.
+For more information, see its self-documentation.
+
+* M-x disassemble.
+
+This command prints the disassembly of a byte-compiled Emacs Lisp function.
+
+Would anyone like to interface this to the debugger?
+
+* `insert-buffer-substring' can insert part of the current buffer.
+
+The old restriction that the text being inserted had to come from
+a different buffer is now lifted.
+
+When inserting text from the current buffer, the text to be inserted
+is determined from the specified bounds before any copying takes place.
+
+* New function `substitute-key-definition'.
+
+This is a new way to replace one command with another command as the
+binding of whatever keys may happen to refer to it.
+
+(substitute-key-definition OLDDEF NEWDEF KEYMAP) looks through KEYMAP
+for keys defined to run OLDDEF, and rebinds those keys to run NEWDEF
+instead.
+
+* New function `insert-char'.
+
+Insert a specified character, a specified number of times.
+
+* `mark-marker' changed.
+
+When there is no mark, this now returns a marker that points
+nowhere, rather than `nil'.
+
+* `ding' accepts argument.
+
+When given an argument, the function `ding' does not terminate
+execution of a keyboard macro. Normally, `ding' does terminate
+all macros that are currently executing.
+
+* New function `minibuffer-depth'.
+
+This function returns the current depth in minibuffer activations.
+The value is zero when the minibuffer is not in use.
+Values greater than one are possible if the user has entered the
+minibuffer recursively.
+
+* New function `documentation-property'.
+
+(documentation-property SYMBOL PROPNAME) is like (get SYMBOL PROPNAME),
+except that if the property value is a number `documentation-property'
+will take that number (or its absolute value) as a character position
+in the DOC file and return the string found there.
+
+(documentation-property VAR 'variable-documentation) is the proper
+way for a Lisp program to get the documentation of variable VAR.
+
+* New documentation-string expansion feature.
+
+If a documentation string (for a variable or function) contains text
+of the form `\<FOO>', it means that all command names specified in
+`\[COMMAND]' construct from that point on should be turned into keys
+using the value of the variable FOO as the local keymap. Thus, for example,
+
+ `\<emacs-lisp-mode-map>\[eval-defun] evaluates the defun containing point.'
+
+will expand into
+
+ "ESC C-x evaluates the defun containing point."
+
+regardless of the current major mode, because ESC C-x is defined to
+run `eval-defun' in the keymap `emacs-lisp-mode-map'. The effect is
+to show the key for `eval-defun' in Emacs Lisp mode regardless of the
+current major mode.
+
+The `\<...>' construct applies to all `\[...]' constructs that follow it,
+up to the end of the documentation string or the next `\<...>'.
+
+Without `\<...>', the keys for commands specified in `\[...]' are found
+in the current buffer's local map.
+
+The current global keymap is always searched second, whether `\<...>'
+has been used or not.
+
+* Multiple hooks allowed in certain contexts.
+
+The old hook variables `find-file-hook', `find-file-not-found-hook' and
+`write-file-hook' have been replaced.
+
+The replacements are `find-file-hooks', `find-file-not-found-hooks'
+and `write-file-hooks'. Each holds a list of functions to be called;
+by default, `nil', for no functions. The functions are called in
+order of appearance in the list.
+
+In the case of `find-file-hooks', all the functions are executed.
+
+In the case of `find-file-not-found-hooks', if any of the functions
+returns non-`nil', the rest of the functions are not called.
+
+In the case of `write-file-hooks', if any of the functions returns
+non-`nil', the rest of the functions are not called, and the file is
+considered to have been written already; so actual writing in the
+usual way is not done. If `write-file-hooks' is local to a buffer,
+it is set to its global value if `set-visited-file-name' is called
+(and thus by C-x C-w as well).
+
+`find-file-not-found-hooks' and `write-file-hooks' can be used
+together to implement editing of files that are not stored as Unix
+files: stored in archives, or inside version control systems, or on
+other machines running other operating systems and accessible via ftp.
+
+* New hooks for suspending Emacs.
+
+Suspending Emacs runs the hook `suspend-hook' before suspending
+and the hook `suspend-resume-hook' if the suspended Emacs is resumed.
+Running a hook is done by applying the variable's value to no arguments
+if the variable has a non-`nil' value. If `suspend-hook' returns
+non-`nil', then suspending is inhibited and so is running the
+`suspend-resume-hook'. The non-`nil' value means that the `suspend-hook'
+has done whatever suspending is required.
+
+* Disabling commands can print a special message.
+
+A command is disabled by giving it a non-`nil' `disabled' property.
+Now, if this property is a string, it is included in the message
+printed when the user tries to run the command.
+
+* Emacs can open TCP connections.
+
+The function `open-network-stream' opens a TCP connection to
+a specified host and service. Its value is a Lisp object that represents
+the connection. The object is a kind of "subprocess", and I/O are
+done like I/O to subprocesses.
+
+* Display-related changes.
+
+** New mode-line control features.
+
+The display of the mode line used to be controlled by a format-string
+that was the value of the variable `mode-line-format'.
+
+This variable still exists, but it now allows more general values,
+not just strings. Lists, cons cells and symbols are also meaningful.
+
+The mode line contents are created by outputting various mode elements
+one after the other. Here are the kinds of objects that can be
+used as mode elements, and what they do in the display:
+
+ string the contents of the string are output to the mode line,
+ and %-constructs are replaced by other text.
+
+ t or nil ignored; no output results.
+
+ symbol the symbol's value is used. If the value is a string,
+ the string is output verbatim to the mode line
+ (so %-constructs are not interpreted). Otherwise,
+ the symbol's value is processed as a mode element.
+
+ list (whose first element is a string or list or cons cell)
+ the elements of the list are treated as as mode elements,
+ so that the output they generate is concatenated,
+
+ list (whose car is a symbol)
+ if the symbol's value is non-nil, the second element of the
+ list is treated as a mode element. Otherwise, the third
+ element (if any) of the list is treated as a mode element.
+
+ cons (whose car is a positive integer)
+ the cdr of the cons is used as a mode element, but
+ the text it produces is padded, if necessary, to have
+ at least the width specified by the integer.
+
+ cons (whose car is a negative integer)
+ the cdr of the cons is used as a mode element, but
+ the text it produces is truncated, if necessary, to have
+ at most the width specified by the integer.
+
+There is always one mode element to start with, that being the value of
+`mode-line-format', but if this value is a list then it leads to several
+more mode elements, which can lead to more, and so on.
+
+There is one new %-construct for mode elements that are strings:
+`%n' displays ` Narrow' for a buffer that is narrowed.
+
+The default value of `mode-line-format' refers to several other variables.
+These variables are `mode-name', `mode-line-buffer-identification',
+`mode-line-process', `mode-line-modified', `global-mode-string' and
+`minor-mode-alist'. The first four are local in every buffer in which they
+are changed from the default.
+
+mode-name Name of buffer's major mode. Local in every buffer.
+
+mode-line-buffer-identification
+ Normally the list ("Emacs: %17b"), it is responsible
+ for displaying text to indicate what buffer is being shown
+ and what kind of editing it is doing. `Emacs' means
+ that a file of characters is being edited. Major modes
+ such as Info and Dired which edit or view other kinds
+ of data often change this value. This variables becomes
+ local to the current buffer if it is setq'd.
+
+mode-line-process
+ Normally nil, this variable is responsible for displaying
+ information about the process running in the current buffer.
+ M-x shell-mode and M-x compile alter this variable.
+
+mode-line-modified
+ This variable is responsible for displaying the indication
+ of whether the current buffer is modified or read-only.
+ By default its value is `("--%*%*-")'.
+
+minor-mode-alist
+ This variable is responsible for displaying text for those
+ minor modes that are currently enabled. Its value
+ is a list of elements of the form (VARIABLE STRING),
+ where STRING is to be displayed if VARIABLE's value
+ (in the buffer whose mode line is being displayed)
+ is non-nil. This variable is not made local to particular
+ buffers, but loading some libraries may add elements to it.
+
+global-mode-string
+ This variable is used to display the time, if you ask
+ for that.
+
+The idea of these variables is to eliminate the need for major modes
+to alter mode-line-format itself.
+
+** `window-point' valid for selected window.
+
+The value returned by `window-point' used to be incorrect when its
+argument was the selected window. Now the value is correct.
+
+** Window configurations may be saved as Lisp objects.
+
+The function `current-window-configuration' returns a special type of
+Lisp object that represents the current layout of windows: the
+sizes and positions of windows, which buffers appear in them, and
+which parts of the buffers appear on the screen.
+
+The function `set-window-configuration' takes one argument, which must
+be a window configuration object, and restores that configuration.
+
+** New hook `temp-output-buffer-show-hook'.
+
+This hook allows you to control how help buffers are displayed.
+Whenever `with-output-to-temp-buffer' has executed its body and wants
+to display the temp buffer, if this variable is bound and non-`nil'
+then its value is called with one argument, the temp buffer.
+The hook function is solely responsible for displaying the buffer.
+The standard manner of display--making the buffer appear in a window--is
+used only if there is no hook function.
+
+** New function `minibuffer-window'.
+
+This function returns the window used (sometimes) for displaying
+the minibuffer. It can be used even when the minibuffer is not active.
+
+** New feature to `next-window'.
+
+If the optional second argument is neither `nil' nor `t', the minibuffer
+window is omitted from consideration even when active; if the starting
+window was the last non-minibuffer window, the value will be the first
+non-minibuffer window.
+
+** New variable `minibuffer-scroll-window'.
+
+When this variable is non-`nil', the command `scroll-other-window'
+uses it as the window to be scrolled. Displays of completion-lists
+set this variable to the window containing the display.
+
+** New argument to `sit-for'.
+
+A non-nil second argument to `sit-for' means do not redisplay;
+just wait for the specified time or until input is available.
+
+** Deleted function `set-minor-mode'; minor modes must be changed.
+
+The function `set-minor-mode' has been eliminated. The display
+of minor mode names in the mode line is now controlled by the
+variable `minor-mode-alist'. To specify display of a new minor
+mode, it is sufficient to add an element to this list. Once that
+is done, you can turn the mode on and off just by setting a variable,
+and the display will show its status automatically.
+
+** New variable `cursor-in-echo-area'.
+
+If this variable is non-nil, the screen cursor appears on the
+last line of the screen, at the end of the text displayed there.
+
+Binding this variable to t is useful at times when reading single
+characters of input with `read-char'.
+
+** New per-buffer variable `selective-display-ellipses'.
+
+If this variable is non-nil, an ellipsis (`...') appears on the screen
+at the end of each text line that is followed by invisible text.
+
+If this variable is nil, no ellipses appear. Then there is no sign
+on the screen that invisible text is present.
+
+Text is made invisible under the control of the variable
+`selective-display'; this is how Outline mode and C-x $ work.
+
+** New variable `no-redraw-on-reenter'.
+
+If you set this variable non-nil, Emacs will not clear the screen when
+you resume it after suspending it. This is for the sake of terminals
+with multiple screens of memory, where the termcap entry has been set
+up to switch between screens when Emacs is suspended and resumed.
+
+** New argument to `set-screen-height' or `set-screen-width'.
+
+These functions now take an optional second argument which says
+what significance the newly specified height or width has.
+
+If the argument is nil, or absent, it means that Emacs should
+believe that the terminal height or width really is as just specified.
+
+If the argument is t, it means Emacs should not believe that the
+terminal really is this high or wide, but it should use the
+specific height or width as the number of lines or columns to display.
+Thus, you could display only 24 lines on a screen known to have 48 lines.
+
+What practical difference is there between using only 24 lines for display
+and really believing that the terminal has 24 lines?
+
+1. The ``real'' height of the terminal says what the terminal command
+to move the cursor to the last line will do.
+
+2. The ``real'' height of the terminal determines how much padding is
+needed.
+
+* File-related changes.
+
+** New parameter `backup-by-copying-when-mismatch'.
+
+If this variable is non-`nil', then when Emacs is about to save a
+file, it will create the backup file by copying if that would avoid
+changing the file's uid or gid.
+
+The default value of this variable is `nil', because usually it is
+useful to have the uid of a file change according to who edited it
+last. I recommend thet this variable be left normally `nil' and
+changed with a local variables list in those particular files where
+the uid needs to be preserved.
+
+** New parameter `file-precious-flag'.
+
+If this variable is non-`nil', saving the buffer tries to avoid
+leaving an incomplete file due to disk full or other I/O errors.
+It renames the old file before saving. If saving is successful,
+the renamed file is deleted; if saving gets an error, the renamed
+file is renamed back to the name you visited.
+
+Backups are always made by copying for such files.
+
+** New variable `buffer-offer-save'.
+
+If the value of this variable is non-`nil' in a buffer then exiting
+Emacs will offer to save the buffer (if it is modified and nonempty)
+even if the buffer is not visiting a file. This variable is
+automatically made local to the current buffer whenever it is set.
+
+** `rename-file', `copy-file', `add-name-to-file' and `make-symbolic-link'.
+
+The third argument to these functions used to be `t' or `nil'; `t'
+meaning go ahead even if the specified new file name already has a file,
+and `nil' meaning to get an error.
+
+Now if the third argument is a number it means to ask the user for
+confirmation in this case.
+
+** New optional argument to `copy-file'.
+
+If `copy-file' receives a non-nil fourth argument, it attempts
+to give the new copy the same time-of-last-modification that the
+original file has.
+
+** New function `file-newer-than-file-p'.
+
+(file-newer-than-file-p FILE1 FILE2) returns non-nil if FILE1 has been
+modified more recently than FILE2. If FILE1 does not exist, the value
+is always nil; otherwise, if FILE2 does not exist, the value is t.
+This is meant for use when FILE2 depends on FILE1, to see if changes
+in FILE1 make it necessary to recompute FILE2 from it.
+
+** Changed function `file-exists-p'.
+
+This function is no longer the same as `file-readable-p'.
+`file-exists-p' can now return t for a file that exists but which
+the fascists won't allow you to read.
+
+** New function `file-locked-p'.
+
+This function receives a file name as argument and returns `nil'
+if the file is not locked, `t' if locked by this Emacs, or a
+string giving the name of the user who has locked it.
+
+** New function `file-name-sans-versions'.
+
+(file-name-sans-versions NAME) returns a substring of NAME, with any
+version numbers or other backup suffixes deleted from the end.
+
+** New functions for directory names.
+
+Although a directory is really a kind of file, specifying a directory
+uses a somewhat different syntax from specifying a file.
+In Emacs, a directory name is used as part of a file name.
+
+On Unix, the difference is small: a directory name ends in a slash,
+while a file name does not: thus, `/usr/rms/' to name a directory,
+while `/usr/rms' names the file which holds that directory.
+
+On VMS, the difference is considerable: `du:[rms.foo]' specifies a
+directory, but the name of the file that holds that directory is
+`du:[rms]foo.dir'.
+
+There are two new functions for converting between directory names
+and file names. `directory-file-name' takes a directory name and
+returns the name of the file in which that directory's data is stored.
+`file-name-as-directory' takes the name of a file and returns
+the corresponding directory name. These always understand Unix file name
+syntax; on VMS, they understand VMS syntax as well.
+
+For example, (file-name-as-directory "/usr/rms") returns "/usr/rms/"
+and (directory-file-name "/usr/rms/") returns "/usr/rms".
+On VMS, (file-name-as-directory "du:[rms]foo.dir") returns "du:[rms.foo]"
+and (directory-file-name "du:[rms.foo]") returns "du:[rms]foo.dir".
+
+** Value of `file-attributes' changed.
+
+The function file-attributes returns a list containing many kinds of
+information about a file. Now the list has eleven elements.
+
+The tenth element is `t' if deleting the file and creating another
+file of the same name would result in a change in the file's group;
+`nil' if there would be no change. You can also think of this as
+comparing the file's group with the default group for files created in
+the same directory by you.
+
+The eleventh element is the inode number of the file.
+
+** VMS-only function `file-name-all-versions'.
+
+This function returns a list of all the completions, including version
+number, of a specified version-number-less file name. This is like
+`file-name-all-completions', except that the latter returns values
+that do not include version numbers.
+
+** VMS-only variable `vms-stmlf-recfm'.
+
+On a VMS system, if this variable is non-nil, Emacs will give newly
+created files the record format `stmlf'. This is necessary for files
+that must contain lines of arbitrary length, such as compiled Emacs
+Lisp.
+
+When writing a new version of an existing file, Emacs always keeps
+the same record format as the previous version; so this variable has
+no effect.
+
+This variable has no effect on Unix systems.
+
+** `insert-file-contents' on an empty file.
+
+This no longer sets the buffer's "modified" flag.
+
+** New function (VMS only) `define-logical-name':
+
+(define-logical-name LOGICAL TRANSLATION) defines a VMS logical name
+LOGICAL whose translation is TRANSLATION. The new name applies to
+the current process only.
+
+** Deleted variable `ask-about-buffer-names'.
+
+If you want buffer names for files to be generated in a special way,
+you must redefine `create-file-buffer'.
+
+* Subprocess-related changes.
+
+** New function `process-list'.
+
+This function takes no arguments and returns a list of all
+of Emacs's asynchronous subprocesses.
+
+** New function `process-exit-status'.
+
+This function, given a process, process name or buffer as argument,
+returns the exit status code or signal number of the process.
+If the process has not yet exited or died, this function returns 0.
+
+** Process output ignores `buffer-read-only'.
+
+Output from a process will go into the process's buffer even if the
+buffer is read only.
+
+** Switching buffers in filter functions and sentinels.
+
+Emacs no longer saves and restore the current buffer around calling
+the filter and sentinel functions, so these functions can now
+permanently alter the selected buffer in a straightforward manner.
+
+** Specifying environment variables for subprocesses.
+
+When a subprocess is started with `start-process' or `call-process',
+the value of the variable `process-environment' is taken to
+specify the environment variables to give the subprocess. The
+value should be a list of strings, each of the form "VAR=VALUE".
+
+`process-environment' is initialized when Emacs starts up
+based on Emacs's environment.
+
+** New variable `process-connection-type'.
+
+If this variable is `nil', when a subprocess is created, Emacs uses
+a pipe rather than a pty to communicate with it. Normally this
+variable is `t', telling Emacs to use a pty if ptys are supported
+and one is available.
+
+** New function `waiting-for-user-input-p'.
+
+This function, given a subprocess as argument, returns `t' if that
+subprocess appears to be waiting for input sent from Emacs,
+or `nil' otherwise.
+
+** New hook `shell-set-directory-error-hook'.
+
+The value of this variable is called, with no arguments, whenever
+Shell mode gets an error trying to keep track of directory-setting
+commands (such as `cd' and `pushd') used in the shell buffer.
+
+* New functions `user-uid' and `user-real-uid'.
+
+These functions take no arguments and return, respectively,
+the effective uid and the real uid of the Emacs process.
+The value in each case is an integer.
+
+* New variable `print-escape-newlines' controls string printing.
+
+If this variable is non-`nil', then when a Lisp string is printed
+by the Lisp printing function `prin1' or `print', newline characters
+are printed as `\n' rather than as a literal newline.
+
+* New function `sysnetunam' on HPUX.
+
+This function takes two arguments, a network address PATH and a
+login string LOGIN, and executes the system call `netunam'.
+It returns `t' if the call succeeds, otherwise `nil'.
+
+News regarding installation:
+
+* Many `s-...' file names changed.
+
+Many `s-...' files have been renamed. All periods in such names,
+except the ones just before the final `h', have been changed to
+hyphens. Thus, `s-bsd4.2.h' has been renamed to `s-bsd4-2.h'.
+
+This is so a Unix distribution can be moved mechanically to VMS.
+
+* `DOCSTR...' file now called `DOC-...'.
+
+The file of on-line documentation strings, that used to be
+`DOCSTR.mm.nn.oo' in this directory, is now called `DOC-mm.nn.oo'.
+This is so that it can port to VMS using the standard conventions
+for translating filenames for VMS.
+
+This file also now contains the doc strings for variables as
+well as functions.
+
+* Emacs no longer uses floating point arithmetic.
+
+This may make it easier to port to some machines.
+
+* Macros `XPNTR' and `XSETPNTR'; flag `DATA_SEG_BITS'.
+
+These macros exclusively are used to unpack a pointer from a Lisp_Object
+and to insert a pointer into a Lisp_Object. Redefining them may help
+port Emacs to machines in which all pointers to data objects have
+certain high bits set.
+
+If `DATA_SEG_BITS' is defined, it should be a number which contains
+the high bits to be inclusive or'ed with pointers that are unpacked.
+
+* New flag `HAVE_X_MENU'.
+
+Define this flag in `config.h' in addition to `HAVE_X_WINDOWS'
+to enable use of the Emacs interface to X Menus. On some operating
+systems, the rest of the X interface works properly but X Menus
+do not work; hence this separate flag. See the file `src/xmenu.c'
+for more information.
+
+* Macros `ARRAY_MARK_FLAG' and `DONT_COPY_FLAG'.
+
+* `HAVE_ALLOCA' prevents assembly of `alloca.s'.
+
+* `SYSTEM_MALLOC' prevents use of GNU `malloc.c'.
+
+SYSTEM_MALLOC, if defined, means use the system's own `malloc' routines
+rather than those that come with Emacs.
+
+Use this only if absolutely necessary, because if it is used you do
+not get warnings when space is getting low.
+
+* New flags to control unexec.
+
+See the file `unexec.c' for a long comment on the compilation
+switches that suffice to make it work on many machines.
+
+* `PNTR_COMPARISON_TYPE'
+
+Pointers that need to be compared for ordering are converted to this type
+first. Normally this is `unsigned int'.
+
+* `HAVE_VFORK', `HAVE_DUP2' and `HAVE_GETTIMEOFDAY'.
+
+These flags just say whether certain system calls are available.
+
+* New macros control compiler switches, linker switches and libraries.
+
+The m- and s- files can now control in a modular fashion the precise
+arguments passed to `cc' and `ld'.
+
+LIBS_STANDARD defines the standard C libraries. Default is `-lc'.
+LIBS_DEBUG defines the extra libraries to use when debugging. Default `-lg'.
+LIBS_SYSTEM can be defined by the s- file to specify extra libraries.
+LIBS_MACHINE can be defined by the m- file to specify extra libraries.
+LIBS_TERMCAP defines the libraries for Termcap or Terminfo.
+ It is defined by default in a complicated fashion but the m- or s- file
+ can override it.
+
+LD_SWITCH_SYSTEM can be defined by the s- file to specify extra `ld' switches.
+ The default is `-X' on BSD systems except those few that use COFF object files.
+LD_SWITCH_MACHINE can be defined by the m- file to specify extra `ld' switches.
+
+C_DEBUG_SWITCH defines the switches to give `cc' when debugging. Default `-g'.
+C_OPTIMIZE_SWITCH defines the switches to give `cc' to optimize. Default `-O'.
+C_SWITCH_MACHINE can be defined by the m- file to specify extra `cc' switches.
+
+For older news, see the file ONEWS.
+
+----------------------------------------------------------------------
+Copyright information:
+
+Copyright (C) 1988, 1990 Free Software Foundation, Inc.
+
+ Permission is granted to anyone to make or distribute verbatim copies
+ of this document as received, in any medium, provided that the
+ copyright notice and this permission notice are preserved,
+ thus giving the recipient permission to redistribute in turn.
+
+ Permission is granted to distribute modified versions
+ of this document, or of portions of it,
+ under the above conditions, provided also that they
+ carry prominent notices stating who last changed them.
+
+Local variables:
+mode: text
+end:
diff --git a/etc/NICKLES.WORTH b/etc/NICKLES.WORTH
new file mode 100644
index 00000000000..bae5e0a1f61
--- /dev/null
+++ b/etc/NICKLES.WORTH
@@ -0,0 +1,188 @@
+Article from _Computer Language_ by Bruce Tonkin.
+
+ Several prominent software companies have caused a stir lately by dropping
+all development work in Pascal and adopting Microsoft BASIC. When queried all
+have declined to comment about this move, but one company insider (code-named
+Deep Poke) suggested talking to Niklaus Wirth to get the full story.
+ Speaking from his home in Zurich, Switzerland, Wirth proved to be a far
+more genial soul than one might imagine, being the founder of Pascal and all.
+But the European lifestyle obviously agrees with him, and he was more than
+willing to provide some insights into this strange phenomenon, currently taking
+place in the computer industry.
+ In fact, what began as an innocent inquiry eventually revealed a shocking
+and exclusive piece of information: that the invention of Pascal nearly 20
+years ago was intended entirely as a joke, an April Fools' prank.
+ Wirth tried to explain. "Every year at the Swiss Federal Institute for
+Technology [the university in Zurich where Wirth is a professor of computer
+science] I taught the same classes, gave the same tests, told the same
+jokes," he began. "it was boring. I needed a little humor. So I started
+talking about this crazy language called Pascal. Eventually, the Pascal joke
+became so popular I just kept adding to it, making it more and more elaborate.
+ "But some of the students went to class so seldom that they missed the
+joke and thought Pascal was a real language! Imagine the looks on their faces
+when they got out into the world and discovered there was no such thing as a
+language called Pascal. Hoo-boy! They sure learned to pay attention after
+that!" he said, giggling.
+ Several of his better students, he continued, figured they'd make some
+money by fleecing the people who actually believed in Pascal and so wrote a
+simple Pascal compiler for this purpose. It was actually a kind of prank, much
+like selling elevator passes to high school freshmen.
+ "Yes, yes," Wirth said, "the UCSD operating system started the same way.
+The same bunch of rascals who did the whole Pascal thing kept pushing the idea
+until it reached the point of complete absurdity. They were hysterical!
+Especially late at night - they'd come up with some really boffo material.
+They the next week they'd modify it and it would get even more entertaining."
+ Wirth's best student was Philippe Kahn, who he met while Kahn was a
+student. "I used to go to a small bistro called 'Der Blaue Engel' after my
+classes, and it happened that Kahn played jazz saxophone there while people
+danced on the tables." Wirth was impressed with Kahn's talent and evident wit
+and encouraged him to end his musical career and enter the lucrative field of
+software comedy. Once he explained Pascal's comedic possibilities, Kahn was
+hooked and quickly agreed.
+ Since most of the staff at Apple Computer Inc. was educated at the
+University of California at San Diego, they were also in on the joke, Wirth
+said. "That's why they kept pushing Pascal. A bunch of fine kids, those Apple
+guys. Born comedians, most of them. Except this one guy - he had no sense
+of humor at all. [Editor's hint: not Woz.]
+ "When we finally decided to do a DOS that was even funnier than UCSD
+Pascal, the feeling was that UCSD was already the ultimate. But then one of
+the guys proposed doing a DOS that was written in Pascal but used hieroglyphics
+instead of a written language. What a genius! We were rolling in the aisles.
+But that one guy, he thought we were serious. What a nerd!"
+ Wirth's list of the funniest features of Pascal begins with the lack of a
+string data type, no random file access, primitive numeric handling, and the
+existential absurdity of the semicolon.
+ "But I'd have to say that my crowning achievement was the lack of input
+and output functions. First you can't get anything in too easy. And once it's
+in, you can't do much with it. Pascal isn't good with letters and it's not
+good at all with numbers. Besides, I made it very picky. You have to
+recompile, recompile, recompile forever. Ha! And once you've done something
+with the data, you can't get it out." Wirth started chuckling uncontrollably.
+"Philippe has said C is a write-only language - I made Pascal a read-only
+language!" His chuckling turned into hysterical laughter that went on for
+several minutes.
+ "Of course, some didn't get the joke," he finally said when he could speak
+again. "They kept trying to make Pascal actually useful. But I stopped them;
+I made the original Pascal a standard. That meant anyone who made Pascal good
+for anything was nonstandard and out on a limb!"
+
+ * * * * *
+
+ How will all this affect the future of Modula-2? Wirths' merry manner
+and beaming face suddenly became hard when presented with this question;
+perhaps this was taboo territory, sacred subject matter.
+ "Modula-2 is a real language," he finally said, his demeanor solemn. "It
+represents a serious effort on my part to make amends for any damage caused by
+well-meaning but unimaginative people teaching and learning Pascal.
+ "But it's so hard! Pascal is a very good joke, yes? But to make a really
+good language from it is not so easy," he sighed.
+ In addition to Pascal, Wirth admitted, three other languages also were
+intended as pranks: Forth, PL/I, and True BASIC.
+ "Forth is essentially black humor," Wirth said. "Charles Moore [who
+created the language in the late 1960s] designed it as a native language for
+people whose brains ran backward." Originally, he continued, it was supposed
+to be the ultimate parody of Hewlett-Packard calculators, which Moore has been
+competing with unsuccessfully for years. As an astronomer, he had used HP's
+calculators out of necessity rather than any appreciation for their design.
+But to his great surprise, he found that there were actually quite a few
+people whose brains did run in reverse. Eventually, Moore came to see Forth
+as a boon, especially for backward thinkers. "At least it keeps them of the
+streets out of really serious trouble," Wirth said. "Imagine one of them
+trying to drive a car or operate heavy machinery!"
+ PL/I originally stood for "Prostituted Language/Interface," Wirth
+explained. "The designers were under so much pressure to add features and
+include every possible construction from every other language in existence that
+they eventually gave up and decided to play the whole thing for laughs. They
+said 'yes' to every request, no matter how absurd, and even added things to
+the language no one ever could or would use. The scoured journals for
+off-beat syntax and weird symbolic notation; some of their better ideas came
+from early editions of The Mad Reader and other E. C. publications. Besides,
+several of them were upset with the compiler-writing team and decided to stick
+it to them with a life-time project."
+ True BASIC is not "True" in the sense most people understand the word,
+Wirth continued. Rather, "True" is itself an acronym for a "Totally wRecked-Up
+Example of." The professors who came up with it are amazed that no one has
+yet caught on to the joke; they felt sure their insistence on the LET keyword
+would be a dead giveaway. "Of course there were other clues, but this was the
+most clear-cut," Wirth said. "They even called Microsoft BASIC a street
+BASIC in hopes that Bill Gates would challenge them and reveal the joke."
+But Gates refused to play along, and both professors had to all but beg Wirth
+to tell the world the truth about True BASIC before things went any further.
+
+ * * * * *
+
+ Jokes abound in the world of operating systems as well, according to
+Wirth. In addition to the UCSD Pascal operating system, said Wirth, "Tandy,
+Apple, and Commodore were for a number of years carrying out a private comedic
+battle to see who could produce the world's funniest DOS."
+ Tandy's TRS-DOS (Tandy Radio Signal Detection Operating System - a
+reference to the fact that early machines would reboot when any transmitted
+signal was detected) was an early front-runner until Apple came out with the
+vary amusing Control-D command what could enable or disable disk operations.
+In the end, though, Commodore won the battle. Its DOS was oriented toward
+records exactly the size of punch cards and took over four minutes to boot from
+disk since it read disk data more slowly than most audio tape machines and even
+some 300-baud modems.
+ But the funniest joke of all is, in Wirth's estimation, also the most
+common, and he's amazed so few people have caught on to it yet.
+ "Come on, come on. Surely you can guess," he said, his voice rising in
+excitement. "What one thing makes users more livid than any other? What one
+computer product makes you feel sure it was produced by a team of trained
+gerbils on mind-altering drugs? Yes, yes, yes! You see it now - manuals!"
+ Wirth considers Gates, who wrote all the BASIC manuals and who was on the
+staff of many others, a "comic genius." "Mitch Kapor should get more
+recognition - he's far better than Neil Simon. And what's-his-name, the guy
+who wrote the WordStar manual - he got an award at at dinner we threw for
+him a few years back. That manual is a classic in the truest Marxist
+[brothers] sense of the word! Pure slapstick! But the best of them all is the
+author of the dBase II manual. Now there is a writer for the ages!"
+ As for the IBM manuals, Wirth considers them mere hack work. "Anyone can
+do stuff like that," he snorted.
+ But perusing a copy of the manual for NEWDOS, he seemed a little more
+impressed. "Hmmmm. Not bad work. Not bad at all," he said. "But it's still
+simple stuff. 'To do this, read page 40. But to know what's on page 40, you
+have to read page 65, which refers to page 15, which shows a whole list of
+exceptions for page 53.' Entertaining, but hardly in the class of any of the
+modern masters of the art." But when his attention was brought to the fact
+that none of the error numbers listed in the NEWDOS manual were ever returned
+to the BASIC programmer, and that the most common disk setup (double-density,
+double-sided) was not on the configuration menu, Wirth admitted that these were
+indeed nice touches.
+ Although it is a known fact that most of the early computer manuals
+(probably even the NEWDOS manual) were written by programmers and that
+programmers are notoriously poor writers, Wirth would not be deterred from his
+opinion that these writings are works of art.
+ "Most people fail to consider that good programmers are very bright.
+Their thoughts are extremely well organized and most of them have the benefit
+of higher education. Their brains are not warped by overexposure to TV and
+their attention spans are not short-circuited by overindulgence in sex, drugs,
+or alcohol. They are not constrained by conventionality. If you want to get
+picky, there are a lot more programmers than there ever were writers. And
+programmers simply work harder than writers. Few writers work 100 hours a
+week; almost all programmers do."
+ The result, according to Wirth? "All programmers write at least as well
+as Faulkner. Most are as good as Proust, and about a third are as good as
+Dickens. Several hundred are at least as good as Shakespeare. So the manuals
+you thought were inferior were simply beyond your poor ability to appreciate.
+If you were a programmer, you would delight in their verbal virtuosity," he
+said.
+ In fact, Wirth claimed, even the grammatical errors and misspellings in
+the manuals were placed there deliberately. Most are elaborate literary
+allusions and puns; some are inventive Joycean neologisms. As an example,
+Wirth discussed the history of the word "kernal."
+ "Everyone, including programmers, knows the word is spelled k-e-r-n-e-l,"
+he explained. "The deliberate misspelling is an implied criticism of the
+typesetter (a writer's bane for years.) Of course typesetters kern the letter
+l; thus, 'kern el.' But kerning can only be done for certain letter
+combinations, such as two l's. Thus, 'kern a l' dares the typesetter to kern
+an isolated l, an obvious typographic impossibility.
+ "Moreover," he continued, "'kernal' is an anagram for 'rankle,' which
+describes programmers' feelings toward typesetters. Finally the inventor of
+this particular word, R. K. Lane (who is well known within the Southern
+California computer community) has concealed his name by means of yet another
+anagram."
+ Wirth smiled a last secretive smile, leaving us all to wonder if this was
+perhaps just one more in his series of personal computer pranks.
+
+
+
diff --git a/etc/ONEWS b/etc/ONEWS
new file mode 100644
index 00000000000..ad593ec4553
--- /dev/null
+++ b/etc/ONEWS
@@ -0,0 +1,1346 @@
+GNU Emacs NEWS -- history of user-visible changes. 26-Mar-1986
+Copyright (C) 1986 Richard M. Stallman.
+See the end for copying conditions.
+
+Changes in Emacs 17
+
+* Frustrated?
+
+Try M-x doctor.
+
+* Bored?
+
+Try M-x hanoi.
+
+* Brain-damaged?
+
+Try M-x yow.
+
+* Sun3, Tahoe, Apollo, HP9000s300, Celerity, NCR Tower 32,
+ Sequent, Stride, Encore, Plexus and AT&T 7300 machines supported.
+
+The Tahoe, Sun3, Sequent and Celerity use 4.2. In regard to the
+Apollo, see the file APOLLO in this directory. NCR Tower32,
+HP9000s300, Stride and Nu run forms of System V. System V rel 2 also
+works on Vaxes now. See etc/MACHINES.
+
+* System V Unix supported, including subprocesses.
+
+It should be possible now to bring up Emacs on a machine running
+mere unameliorated system V Unix with no major work; just possible bug
+fixes. But you can expect to find a handful of those on any machine
+that Emacs has not been run on before.
+
+* Berkeley 4.1 Unix supported.
+
+See etc/MACHINES.
+
+* Portable `alloca' provided.
+
+Emacs can now run on machines that do not and cannot support the library
+subroutine `alloca' in the canonical fashion, using an `alloca' emulation
+written in C.
+
+* On-line manual.
+
+Info now contains an Emacs manual, with essentially the same text
+as in the printed manual.
+
+The manual can now be printed with a standard TeX.
+
+Nicely typeset and printed copies of the manual are available
+from the Free Software Foundation.
+
+* Backup file version numbers.
+
+Emacs now supports version numbers in backup files.
+
+The first time you save a particular file in one editing session,
+the old file is copied or renamed to serve as a backup file.
+In the past, the name for the backup file was made by appending `~'
+to the end of the original file name.
+
+Now the backup file name can instead be made by appending ".~NN~" to
+the original file name, where NN stands for a numeric version. Each
+time this is done, the new version number is one higher than the
+highest previously used.
+
+Thus, the active, current file does not have a version number.
+Only the backups have them.
+
+This feature is controlled by the variable `version-control'. If it
+is `nil', as normally, then numbered backups are made only for files
+that already have numbered backups. Backup names with just `~' are
+used for files that have no numbered backups.
+
+If `version-control' is `never', then the backup file's name is
+made with just `~' in any case.
+
+If `version-control' is not `nil' or `never', numbered backups are
+made unconditionally.
+
+To prevent unlimited consumption of disk space, Emacs can delete
+old backup versions automatically. Generally Emacs keeps the first
+few backups and the latest few backups, deleting any in between.
+This happens every time a new backup is made. The two variables that
+control the deletion are `kept-old-versions' and `kept-new-versions'.
+Their values are, respectively, the number of oldest backups to keep
+and the number of newest ones to keep, each time a new backup is made.
+The value of `kept-new-versions' includes the backup just created.
+By default, both values are 2.
+
+If `trim-versions-without-asking' is non-`nil', the excess middle versions
+are deleted without a murmur. If it is `nil', the default, then you
+are asked whether the excess middle versions should really be deleted.
+
+Dired has a new command `.' which marks for deletion all but the latest
+and oldest few of every numeric series of backups. `kept-old-versions'
+controls the number of oldest versions to keep, and `dired-kept-versions'
+controls the number of latest versions to keep. A numeric argument to
+the `.' command, if positive, specifies the number of latest versions
+to keep, overriding `dired-kept-versions'. A negative argument specifies
+the number of oldest versions to keep, using minus the argument to override
+`kept-old-versions'.
+
+* Immediate conflict detection.
+
+Emacs now locks the files it is modifying, so that if
+you start to modify within Emacs a file that is being
+modified in another Emacs, you get an immediate warning.
+
+The warning gives you three choices:
+1. Give up, and do not make any changes.
+2. Make changes anyway at your own risk.
+3. Make changes anyway, and record yourself as
+ the person locking the file (instead of whoever
+ was previously recorded.)
+
+Just visiting a file does not lock it. It is locked
+when you try to change the buffer that is visiting the file.
+Saving the file unlocks it until you make another change.
+
+Locking is done by writing a lock file in a special designated
+directory. If such a directory is not provided and told to
+Emacs as part of configuring it for your machine, the lock feature
+is turned off.
+
+* M-x recover-file.
+
+This command is used to get a file back from an auto-save
+(after a system crash, for example). It takes a file name
+as argument and visits that file, but gets the data from the
+file's last auto save rather than from the file itself.
+
+* M-x normal-mode.
+
+This command resets the current buffer's major mode and local
+variables to be as specified by the visit filename, the -*- line
+and/or the Local Variables: block at the end of the buffer.
+It is the same thing normally done when a file is first visited.
+
+* Echo area messages disappear shortly if minibuffer is in use.
+
+Any message in the echo area disappears after 2 seconds
+if the minibuffer is active. This allows the minibuffer
+to become visible again.
+
+* C-z on System V runs a subshell.
+
+On systems which do not allow programs to be suspended, the C-z command
+forks a subshell that talks directly to the terminal, and then waits
+for the subshell to exit. This gets almost the effect of suspending
+in that you can run other programs and then return to Emacs. However,
+you cannot log out from the subshell.
+
+* C-c is always a prefix character.
+
+Also, subcommands of C-c which are letters are always
+reserved for the user. No standard Emacs major mode
+defines any of them.
+
+* Picture mode C-c commands changed.
+
+The old C-c k command is now C-c C-w.
+The old C-c y command is now C-c C-x.
+
+* Shell mode commands changed.
+
+All the special commands of Shell mode are now moved onto
+the C-c prefix. Most are not changed aside from that.
+Thus, the old Shell mode C-c command (kill current job)
+is now C-c C-c; the old C-z (suspend current job) is now C-c C-z,
+etc.
+
+The old C-x commands are now C-c commands. C-x C-k (kill output)
+is now C-c C-o, and C-x C-v (show output) is now C-c C-r.
+
+The old M-= (copy previous input) command is now C-c C-y.
+
+* Shell mode recognizes aliases for `pushd', `popd' and `cd'.
+
+Shell mode now uses the variable `shell-pushd-regexp' as a
+regular expression to recognize any command name that is
+equivalent to a `pushd' command. By default it is set up
+to recognize just `pushd' itself. If you use aliases for
+`pushd', change the regexp to recognize them as well.
+
+There are also `shell-popd-regexp' to recognize commands
+with the effect of a `popd', and `shell-cd-regexp' to recognize
+commands with the effect of a `cd'.
+
+* "Exit" command in certain modes now C-c C-c.
+
+These include electric buffer menu mode, electric command history
+mode, Info node edit mode, and Rmail edit mode. In all these
+modes, the command to exit used to be just C-c.
+
+* Outline mode changes.
+
+Lines that are not heading lines are now called "body" lines.
+The command `hide-text' is renamed to `hide-body'.
+The key M-H is renamed to C-c C-h.
+The key M-S is renamed to C-c C-s.
+The key M-s is renamed to C-c C-i.
+
+Changes of line visibility are no longer undoable. As a result,
+they no longer use up undo memory and no longer interfere with
+undoing earlier commands.
+
+* Rmail changes.
+
+The s and q commands now both expunge deleted messages before saving;
+use C-x C-s to save without expunging.
+
+The u command now undeletes the current message if it is deleted;
+otherwise, it backs up as far as necessary to reach a deleted message,
+and undeletes that one. The u command in the summary behaves likewise,
+but considers only messages listed in the summary. The M-u command
+has been eliminated.
+
+The o and C-o keys' meanings are interchanged.
+o now outputs to an Rmail file, and C-o to a Unix mail file.
+
+The F command (rmail-find) is renamed to M-s (rmail-search).
+Various new commands and features exist; see the Emacs manual.
+
+* Local bindings described first in describe-bindings.
+
+* [...], {...} now balance in Fundamental mode.
+
+* Nroff mode and TeX mode.
+
+The are two new major modes for editing nroff input and TeX input.
+See the Emacs manual for full information.
+
+* New C indentation style variable `c-brace-imaginary-offset'.
+
+The value of `c-brace-imaginary-offset', normally zero, controls the
+indentation of a statement inside a brace-group where the open-brace
+is not the first thing on a line. The value says where the open-brace
+is imagined to be, relative to the first nonblank character on the line.
+
+* Dired improvements.
+
+Dired now normally keeps the cursor at the beginning of the file name,
+not at the beginning of the line. The most used motion commands are
+redefined in Dired to position the cursor this way.
+
+`n' and `p' are now equivalent in dired to `C-n' and `C-p'.
+
+If any files to be deleted cannot be deleted, their names are
+printed in an error message.
+
+If the `v' command is invoked on a file which is a directory,
+dired is run on that directory.
+
+* `visit-tag-table' renamed `visit-tags-table'.
+
+This is so apropos of `tags' finds everything you need to
+know about in connection with Tags.
+
+* `mh-e' library uses C-c as prefix.
+
+All the special commands of `mh-rmail' now are placed on a
+C-c prefix rather than on the C-x prefix. This is for
+consistency with other special modes with their own commands.
+
+* M-$ or `spell-word' checks word before point.
+
+It used to check the word after point.
+
+* Quitting during autoloading no longer causes trouble.
+
+Now, when a file is autoloaded, all function redefinitions
+and `provide' calls are recorded and are undone if you quit
+before the file is finished loading.
+
+As a result, it no longer happens that some of the entry points
+which are normally autoloading have been defined already, but the
+entire file is not really present to support them.
+
+* `else' can now be indented correctly in C mode.
+
+TAB in C mode now knows which `if' statement an `else' matches
+up with, and can indent the `else' correctly under the `if',
+even if the `if' contained such things as another `if' statement,
+or a `while' or `for' statement, with no braces around it.
+
+* `batch-byte-compile'
+
+Runs byte-compile-file on the files specified on the command line.
+All the rest of the command line arguments are taken as files to
+compile (or, if directories, to do byte-recompile-directory on).
+Must be used only with -batch, and kills emacs on completion.
+Each file will be processed even if an error occurred previously.
+For example, invoke `emacs -batch -f batch-byte-compile *.el'.
+
+* `-batch' changes.
+
+`-batch' now implies `-q': no init file is loaded by Emacs when
+`-batch' is used. Also, no `term/TERMTYPE.el' file is loaded. Auto
+saving is not done except in buffers in which it is explicitly
+requested. Also, many echo-area printouts describing what is going on
+are inhibited in batch mode, so that the only output you get is the
+output you program specifically.
+
+One echo-area message that is not suppressed is the one that says
+that a file is being loaded. That is because you can prevent this
+message by passing `t' as the third argument to `load'.
+
+* Display of search string in incremental search.
+
+Now, when you type C-s or C-r to reuse the previous search
+string, that search string is displayed immediately in the echo area.
+
+Three dots are displayed after the search string while search
+is actually going on.
+
+* View commands.
+
+The commands C-x ], C-x [, C-x /, C-x j and C-x o are now
+available inside `view-buffer' and `view-file', with their
+normal meanings.
+
+* Full-width windows preferred.
+
+The ``other-window'' commands prefer other full width windows,
+and will split only full width windows.
+
+* M-x rename-file can copy if necessary.
+
+When used between different file systems, since actual renaming does
+not work, the old file will be copied and deleted.
+
+* Within C-x ESC, you can pick the command to repeat.
+
+While editing a previous command to be repeated, inside C-x ESC,
+you can now use the commands M-p and M-n to pick an earlier or
+later command to repeat. M-n picks the next earlier command
+and M-p picks the next later one. The new command appears in
+the minibuffer, and you can go ahead and edit it, and repeat it
+when you exit the minibuffer.
+
+Using M-n or M-p within C-x ESC is like having used a different
+numeric argument when you ran C-x ESC in the first place.
+
+The command you finally execute using C-x ESC is added to the
+front of the command history, unless it is identical with the
+first thing in the command history.
+
+* Use C-c C-c to exit from editing within Info.
+
+It used to be C-z for this. Somehow this use of C-z was
+left out when all the others were moved. The intention is that
+C-z should always suspend Emacs.
+
+* Default arg to C-x < and C-x > now window width minus 2.
+
+These commands, which scroll the current window horizontally
+by a specified number of columns, now scroll a considerable
+distance rather than a single column if used with no argument.
+
+* Auto Save Files Deleted.
+
+The default value of `delete-auto-save-files' is now `t', so that
+when you save a file for real, its auto save file is deleted.
+
+* Rnews changes.
+
+The N, P and J keys in Rnews are renamed to M-n, M-p and M-j.
+These keys move among newsgroups.
+
+The n and p keys for moving sequentially between news articles now
+accept repeat count arguments, and the + and - keys, made redundant by
+this change, are eliminated.
+
+The s command for outputting the current article to a file
+is renamed as o, to be compatible with Rmail.
+
+* Sendmail changes.
+
+If you have a ~/.mailrc file, Emacs searches it for mailing address
+aliases, and these aliases are expanded when you send mail in Emacs.
+
+Fcc fields can now be used in the headers in the *mail* buffer
+to specify files in which copies of the message should be put.
+The message is written into those files in Unix mail file format.
+The message as sent does not contain any Fcc fields in its header.
+You can use any number of Fcc fields, but only one file name in each one.
+The variable `mail-archive-file-name', if non-`nil', can be a string
+which is a file name; an Fcc to that file will be inserted in every
+message when you begin to compose it.
+
+A new command C-c q now exists in Mail mode. It fills the
+paragraphs of an old message that had been inserted with C-c y.
+
+When the *mail* buffer is put in Mail mode, text-mode-hook
+is now run in addition to mail-mode-hook. text-mode-hook
+is run first.
+
+The new variable `mail-header-separator' now specifies the string
+to use on the line that goes between the headers and the message text.
+By default it is still "--text follows this line--".
+
+* Command history truncated automatically.
+
+Just before each garbage collection, all but the last 30 elements
+of the command history are discarded.
+
+Incompatible Lisp Programming Changes in Emacs 17
+
+* `&quote' no longer supported.
+
+This feature, which allowed Lisp functions to take arguments
+that were not evaluated, has been eliminated, because it is
+inescapably hard to make the compiler work properly with such
+functions.
+
+You should use macros instead. A simple way to change any
+code that uses `&quote' is to replace
+
+ (defun foo (&quote x y z) ...
+
+with
+
+ (defmacro foo (x y z)
+ (list 'foo-1 (list 'quote x) (list 'quote y) (list 'quote z)))
+
+ (defun foo-1 (x y z) ...
+
+* Functions `region-to-string' and `region-around-match' removed.
+
+These functions were made for compatibility with Gosling Emacs, but it
+turns out to be undesirable to use them in GNU Emacs because they use
+the mark. They have been eliminated from Emacs proper, but are
+present in mlsupport.el for the sake of converted mocklisp programs.
+
+If you were using `region-to-string', you should instead use
+`buffer-substring'; then you can pass the bounds as arguments and
+can avoid setting the mark.
+
+If you were using `region-around-match', you can use instead
+the two functions `match-beginning' and `match-end'. These give
+you one bound at a time, as a numeric value, without changing
+point or the mark.
+
+* Function `function-type' removed.
+
+This just appeared not to be very useful. It can easily be written in
+Lisp if you happen to want it. Just use `symbol-function' to get the
+function definition of a symbol, and look at its data type or its car
+if it is a list.
+
+* Variable `buffer-number' removed.
+
+You can still use the function `buffer-number' to find out
+a buffer's unique number (assigned in order of creation).
+
+* Variable `executing-macro' renamed `executing-kbd-macro'.
+
+This variable is the currently executing keyboard macro, as
+a string, or `nil' when no keyboard macro is being executed.
+
+* Loading term/$TERM.
+
+The library term/$TERM (where $TERM get replaced by your terminal
+type), which is done by Emacs automatically when it starts up, now
+happens after the user's .emacs file is loaded.
+
+In previous versions of Emacs, these files had names of the form
+term-$TERM; thus, for example, term-vt100.el, but now they live
+in a special subdirectory named term, and have names like
+term/vt100.el.
+
+* `command-history' format changed.
+
+The elements of this list are now Lisp expressions which can
+be evaluated directly to repeat a command.
+
+* Unused editing commands removed.
+
+The functions `forward-to-word', `backward-to-word',
+`upcase-char', `mark-beginning-of-buffer' and `mark-end-of-buffer'
+have been removed. Their definitions can be found in file
+lisp/unused.el if you need them.
+
+Upward Compatible Lisp Programming Changes in Emacs 17
+
+* You can now continue after errors and quits.
+
+When the debugger is entered because of a C-g, due to
+a non-`nil' value of `debug-on-quit', the `c' command in the debugger
+resumes execution of the code that was running when the quit happened.
+Use the `q' command to go ahead and quit.
+
+The same applies to some kinds of errors, but not all. Errors
+signaled with the Lisp function `signal' can be continued; the `c'
+command causes `signal' to return. The `r' command causes `signal' to
+return the value you specify. The `c' command is equivalent to `r'
+with the value `nil'.
+
+For a `wrong-type-argument' error, the value returned with the `r'
+command is used in place of the invalid argument. If this new value
+is not valid, another error occurs.
+
+Errors signaled with the function `error' cannot be continued.
+If you try to continue, the error just happens again.
+
+* `dot' renamed `point'.
+
+The word `dot' has been replaced with `point' in all
+function and variable names, including:
+
+ point, point-min, point-max,
+ point-marker, point-min-marker, point-max-marker,
+ window-point, set-window-point,
+ point-to-register, register-to-point,
+ exchange-point-and-mark.
+
+The old names are still supported, for now.
+
+* `string-match' records position of end of match.
+
+After a successful call to `string-match', `(match-end 0)' will
+return the index in the string of the first character after the match.
+Also, `match-begin' and `match-end' with nonzero arguments can be
+used to find the indices of beginnings and ends of substrings matched
+by subpatterns surrounded by parentheses.
+
+* New function `insert-before-markers'.
+
+This function is just like `insert' except in the handling of any
+relocatable markers that are located at the point of insertion.
+With `insert', such markers end up pointing before the inserted text.
+With `insert-before-markers', they end up pointing after the inserted
+text.
+
+* New function `copy-alist'.
+
+This function takes one argument, a list, and makes a disjoint copy
+of the alist structure. The list itself is copied, and each element
+that is a cons cell is copied, but the cars and cdrs of elements
+remain shared with the original argument.
+
+This is what it takes to get two alists disjoint enough that changes
+in one do not change the result of `assq' on the other.
+
+* New function `copy-keymap'.
+
+This function takes a keymap as argument and returns a new keymap
+containing initially the same bindings. Rebindings in either one of
+them will not alter the bindings in the other.
+
+* New function `copy-syntax-table'.
+
+This function takes a syntax table as argument and returns a new
+syntax table containing initially the same syntax settings. Changes
+in either one of them will not alter the other.
+
+* Randomizing the random numbers.
+
+`(random t)' causes the random number generator's seed to be set
+based on the current time and Emacs's process id.
+
+* Third argument to `modify-syntax-entry'.
+
+The optional third argument to `modify-syntax-entry', if specified
+should be a syntax table. The modification is made in that syntax table
+rather than in the current syntax table.
+
+* New function `run-hooks'.
+
+This function takes any number of symbols as arguments.
+It processes the symbols in order. For each symbol which
+has a value (as a variable) that is non-nil, the value is
+called as a function, with no arguments.
+
+This is useful in major mode commands.
+
+* Second arg to `switch-to-buffer'.
+
+If this function is given a non-`nil' second argument, then the
+selection being done is not recorded on the selection history.
+The buffer's position in the history remains unchanged. This
+feature is used by the view commands, so that the selection history
+after exiting from viewing is the same as it was before.
+
+* Second arg to `display-buffer' and `pop-to-buffer'.
+
+These two functions both accept an optional second argument which
+defaults to `nil'. If the argument is not `nil', it means that
+another window (not the selected one) must be found or created to
+display the specified buffer in, even if it is already shown in
+the selected window.
+
+This feature is used by `switch-to-buffer-other-window'.
+
+* New variable `completion-ignore-case'.
+
+If this variable is non-`nil', completion allows strings
+in different cases to be considered matching. The global value
+is `nil'
+
+This variable exists for the sake of commands that are completing
+an argument in which case is not significant. It is possible
+to change the value globally, but you might not like the consequences
+in the many situations (buffer names, command names, file names)
+where case makes a difference.
+
+* Major modes related to Text mode call text-mode-hook, then their own hooks.
+
+For example, turning on Outline mode first calls the value of
+`text-mode-hook' as a function, if it exists and is non-`nil',
+and then does likewise for the variable `outline-mode-hook'.
+
+* Defining new command line switches.
+
+You can define a new command line switch in your .emacs file
+by putting elements on the value of `command-switch-alist'.
+Each element of this list should look like
+ (SWITCHSTRING . FUNCTION)
+where SWITCHSTRING is a string containing the switch to be
+defined, such as "-foo", and FUNCTION is a function to be called
+if such an argument is found in the command line. FUNCTION
+receives the command line argument, a string, as its argument.
+
+To implement a switch that uses up one or more following arguments,
+use the fact that the remaining command line arguments are kept
+as a list in the variable `command-line-args'. FUNCTION can
+examine this variable, and do
+ (setq command-line-args (cdr command-line-args)
+to "use up" an argument.
+
+* New variable `load-in-progress'.
+
+This variable is non-`nil' when a file of Lisp code is being read
+and executed by `load'.
+
+* New variable `print-length'.
+
+The value of this variable is normally `nil'. It may instead be
+a number; in that case, when a list is printed by `prin1' or
+`princ' only that many initial elements are printed; the rest are
+replaced by `...'.
+
+* New variable `find-file-not-found-hook'.
+
+If `find-file' or any of its variants is used on a nonexistent file,
+the value of `find-file-not-found-hook' is called (if it is not `nil')
+with no arguments, after creating an empty buffer. The file's name
+can be found as the value of `buffer-file-name'.
+
+* Processes without buffers.
+
+In the function `start-process', you can now specify `nil' as
+the process's buffer. You can also set a process's buffer to `nil'
+using `set-process-buffer'.
+
+The reason you might want to do this is to prevent the process
+from being killed because any particular buffer is killed.
+When a process has a buffer, killing that buffer kills the
+process too.
+
+When a process has no buffer, its output is lost unless it has a
+filter, and no indication of its being stopped or killed is given
+unless it has a sentinel.
+
+* New function `user-variable-p'. `v' arg prompting changed.
+
+This function takes a symbol as argument and returns `t' if
+the symbol is defined as a user option variable. This means
+that it has a `variable-documentation' property whose value is
+a string starting with `*'.
+
+Code `v' in an interactive arg reading string now accepts
+user variables only, and completion is limited to the space of
+user variables.
+
+The function `read-variable' also now accepts and completes
+over user variables only.
+
+* CBREAK mode input is the default in Unix 4.3 bsd.
+
+In Berkeley 4.3 Unix, there are sufficient features for Emacs to
+work fully correctly using CBREAK mode and not using SIGIO.
+Therefore, this mode is the default when running under 4.3.
+This mode corresponds to `nil' as the first argument to
+`set-input-mode'. You can still select either mode by calling
+that function.
+
+* Information on memory usage.
+
+The new variable `data-bytes-used' contains the number
+of bytes of impure space allocated in Emacs.
+`data-bytes-free' contains the number of additional bytes
+Emacs could allocate. Note that space formerly allocated
+and freed again still counts as `used', since it is still
+in Emacs's address space.
+
+* No limit on size of output from `format'.
+
+The string output from `format' used to be truncated to
+100 characters in length. Now it can have any length.
+
+* New errors `void-variable' and `void-function' replace `void-symbol'.
+
+This change makes it possible to have error messages that
+clearly distinguish undefined variables from undefined functions.
+It also allows `condition-case' to handle one case without the other.
+
+* `replace-match' handling of `\'.
+
+In `replace-match', when the replacement is not literal,
+`\' in the replacement string is always treated as an
+escape marker. The only two special `\' constructs
+are `\&' and `\DIGIT', so `\' followed by anything other than
+`&' or a digit has no effect. `\\' is necessary to include
+a `\' in the replacement text.
+
+This level of escaping is comparable with what goes on in
+a regular expression. It is over and above the level of `\'
+escaping that goes on when strings are read in Lisp syntax.
+
+* New error `invalid-regexp'.
+
+A regexp search signals this type of error if the argument does
+not meet the rules for regexp syntax.
+
+* `kill-emacs' with argument.
+
+If the argument is a number, it is returned as the exit status code
+of the Emacs process. If the argument is a string, its contents
+are stuffed as pending terminal input, to be read by another program
+after Emacs is dead.
+
+* New fifth argument to `subst-char-in-region'.
+
+This argument is optional and defaults to `nil'. If it is not `nil',
+then the substitutions made by this function are not recorded
+in the Undo mechanism.
+
+This feature should be used with great care. It is now used
+by Outline mode to make lines visible or invisible.
+
+* ` *Backtrace*' buffer renamed to `*Backtrace*'.
+
+As a result, you can now reselect this buffer easily if you switch to
+another while in the debugger.
+
+Exiting from the debugger kills the `*Backtrace*' buffer, so you will
+not try to give commands in it when no longer really in the debugger.
+
+* New function `switch-to-buffer-other-window'.
+
+This is the new primitive to select a specified buffer (the
+argument) in another window. It is not quite the same as
+`pop-to-buffer', because it is guaranteed to create another
+window (assuming there is room on the screen) so that it can
+leave the current window's old buffer displayed as well.
+
+All functions to select a buffer in another window should
+do so by calling this new function.
+
+* New variable `minibuffer-help-form'.
+
+At entry to the minibuffer, the variable `help-form' is bound
+to the value of `minibuffer-help-form'.
+
+`help-form' is expected at all times to contain either `nil'
+or an expression to be executed when C-h is typed (overriding
+teh definition of C-h as a command). `minibuffer-help-form'
+can be used to provide a different default way of handling
+C-h while in the minibuffer.
+
+* New \{...} documentation construct.
+
+It is now possible to set up the documentation string for
+a major mode in such a way that it always describes the contents
+of the major mode's keymap, as it has been customized.
+To do this, include in the documentation string the characters `\{'
+followed by the name of the variable containing the keymap,
+terminated with `}'. (The `\' at the beginning probably needs to
+be quoted with a second `\', to include it in the doc string.)
+This construct is normally used on a line by itself, with no blank
+lines before or after.
+
+For example, the documentation string for the function `c-mode' contains
+ ...
+ Paragraphs are separated by blank lines only.
+ Delete converts tabs to spaces as it moves back.
+ \\{c-mode-map}
+ Variables controlling indentation style:
+ ...
+
+* New character syntax class "punctuation".
+
+Punctuation characters behave like whitespace in word and
+list parsing, but can be distinguished in regexps and in the
+function `char-syntax'. Punctuation syntax is represented by
+a period in `modify-syntax-entry'.
+
+* `auto-mode-alist' no longer needs entries for backup-file names,
+
+Backup suffixes of all kinds are now stripped from a file's name
+before searching `auto-mode-alist'.
+
+Changes in Emacs 16
+
+* No special code for Ambassadors, VT-100's and Concept-100's.
+
+Emacs now controls these terminals based on the termcap entry, like
+all other terminals. Formerly it did not refer to the termcap entries
+for those terminal types, and often the termcap entries for those
+terminals are wrong or inadequate. If you experience worse behavior
+on these terminals than in version 15, you can probably correct it by
+fixing up the termcap entry. See ./TERMS for more info.
+
+See ./TERMS in any case if you find that some terminal does not work
+right with Emacs now.
+
+* Minibuffer default completion character is TAB (and not ESC).
+
+So that ESC can be used in minibuffer for more useful prefix commands.
+
+* C-z suspends Emacs in all modes.
+
+Formerly, C-z was redefined for other purposes by certain modes,
+such as Buffer Menu mode. Now other keys are used for those purposes,
+to keep the meaning of C-z uniform.
+
+* C-x ESC (repeat-complex-command) allows editing the command it repeats.
+
+Instead of asking for confirmation to re-execute a command from the
+command history, the command is placed, in its Lisp form, into the
+minibuffer for editing. You can confirm by typing RETURN, change some
+arguments and then confirm, or abort with C-g.
+
+* Incremental search does less redisplay on slow terminals.
+
+If the terminal baud rate is <= the value of `isearch-slow-speed',
+incremental searching outside the text on the screen creates
+a single-line window and uses that to display the line on which
+a match has been found. Exiting or quitting the search restores
+the previous window configuration and redisplays the window you
+were searching in.
+
+The initial value of `isearch-slow-speed' is 1200.
+
+This feature is courtesy of crl@purdue.
+
+* Recursive minibuffers not allowed.
+
+If the minibuffer window is selected, most commands that would
+use the minibuffer gets an error instead. (Specific commands
+may override this feature and therefore still be allowed.)
+
+Strictly speaking, recursive entry to the minibuffer is still
+possible, because you can switch to another window after
+entering the minibuffer, and then minibuffer-using commands
+are allowed. This is still allowed by a deliberate decision:
+if you know enough to switch windows while in the minibuffer,
+you can probably understand recursive minibuffers.
+
+This may be overridden by binding the variable
+`enable-recursive-minibuffers' to t.
+
+* New major mode Emacs-Lisp mode, for editing Lisp code to run in Emacs.
+
+The mode in which emacs lisp files is edited is now called emacs-lisp-mode
+and is distinct from lisp-mode. The latter is intended for use with
+lisps external to emacs.
+
+The hook which is funcalled (if non-nil) on entry to elisp-mode is now
+called emacs-lisp-mode-hook. A consequence of this changes is that
+.emacs init files which set the value of lisp-mode-hook may need to be
+changed to use the new names.
+
+* Correct matching of parentheses is checked on insertion.
+
+When you insert a close-paren, the matching open-paren
+is checked for validity. The close paren must be the kind
+of close-paren that the open-paren says it should match.
+Otherwise, a warning message is printed. close-paren immediately
+preceded by quoting backslash syntax character is not matched.
+
+This feature was originally written by shane@mit-ajax.
+
+* M-x list-command-history
+* M-x command-history-mode
+* M-x electric-command-history
+
+`list-command-history' displays forms from the command history subject
+to user controlled filtering and limit on number of forms. It leaves
+the buffer in `command-history-mode'. M-x command-history-mode
+recomputes the command history each time it is invoked via
+`list-command-history'. It is like Emacs-Lisp mode except that characters
+don't insert themselves and provision is made for re-evaluating an
+expression from the list. `electric-command-history' pops up a type
+out window with the command history displayed. If the very next
+character is Space, the window goes away and the previous window
+configuration is restored. Otherwise you can move around in the
+history and select an expression for evaluation *inside* the buffer
+which invoked `electric-command-history'. The original window
+configuration is restored on exit unless the command selected changes
+it.
+
+* M-x edit-picture
+
+Enters a temporary major mode (the previous major mode is remembered
+and can is restored on exit) designed for editing pictures and tables.
+Printing characters replace rather than insert themselves with motion
+afterwards that is user controlled (you can specify any of the 8
+compass directions). Special commands for movement are provided.
+Special commands for hacking tabs and tab stops are provided. Special
+commands for killing rectangles and overlaying them are provided. See
+the documentation of function edit-picture for more details.
+
+Calls value of `edit-picture-hook' on entry if non-nil.
+
+* Stupid C-s/C-q `flow control' supported.
+
+Do (set-input-mode nil t) to tell Emacs to use CBREAK mode and interpret
+C-s and C-q as flow control commands. (set-input-mode t nil) switches
+back to interrupt-driven input. (set-input-mode nil nil) uses CBREAK
+mode but no `flow control'; this may make it easier to run Emacs under
+certain debuggers that have trouble dealing with inferiors that use SIGIO.
+
+CBREAK mode has certain inherent disadvantages, which are why it is
+not the default:
+
+ Meta-keys are ignored; CBREAK mode discards the 8th bit of
+ input characters.
+
+ Control-G as keyboard input discards buffered output,
+ and therefore can cause incorrect screen updating.
+
+The use of `flow control' has its own additional disadvantage: the
+characters C-s and C-q are not available as editing commands. You can
+partially compensate for this by setting up a keyboard-translate-table
+(see file ONEWS) that maps two other characters (such as C-^ and C-\) into
+C-s and C-q. Of course, C-^ and C-\ are commonly used as escape
+characters in remote-terminal programs. You really can't win except
+by getting rid of this sort of `flow control.'
+
+The configuration switch CBREAK_INPUT is now eliminated.
+INTERRUPT_INPUT exists only to specify the default mode of operation;
+#define it to make interrupt-driven input the default.
+
+* Completion of directory names provides a slash.
+
+If file name completion yields the name of a directory,
+a slash is appended to it.
+
+* Undo can clear modified-flag.
+
+If you undo changes in a buffer back to a state in which the
+buffer was not considered "modified", then it is labelled as
+once again "unmodified".
+
+* M-x run-lisp.
+
+This command creates an inferior Lisp process whose input and output
+appear in the Emacs buffer named `*lisp*'. That buffer uses a major mode
+called inferior-lisp-mode, which has many of the commands of lisp-mode
+and those of shell-mode. Calls the value of shell-mode-hook and
+lisp-mode-hook, in that order, if non-nil.
+
+Meanwhile, in lisp-mode, the command C-M-x is defined to
+send the current defun as input to the `*lisp*' subprocess.
+
+* Mode line says `Narrow' when buffer is clipped.
+
+If a buffer has a clipping restriction (made by `narrow-to-region')
+then its mode line contains the word `Narrow' after the major and
+minor modes.
+
+* Mode line says `Abbrev' when abbrev mode is on.
+
+* add-change-log-entry takes prefix argument
+
+Giving a prefix argument makes it prompt for login name, full name,
+and site name, with defaults. Otherwise the defaults are used
+with no confirmation.
+
+* M-x view-buffer and M-x view-file
+
+view-buffer selects the named buffer, view-file finds the named file; the
+resulting buffer is placed into view-mode (a recursive edit). The normal
+emacs commands are not available. Instead a set of special commands is
+provided which faclitate moving around in the buffer, searching and
+scrolling by screenfuls. Exiting view-mode returns to the buffer in which
+the view-file or view-buffer command was given.
+Type ? or h when viewing for a complete list of view commands.
+Each calls value of `view-hook' if non-nil on entry.
+
+written by shane@mit-ajax.
+
+* New key commands in dired.
+
+`v' views (like more) the file on the current line.
+`#' marks auto-save files for deletion.
+`~' marks backup files for deletion.
+`r' renames a file and updates the directory listing if the
+file is renamed to same directory.
+`c' copies a file and updates the directory listing if the file is
+copied to the same directory.
+
+* New function `electric-buffer-list'.
+
+This pops up a buffer describing the set of emacs buffers.
+Immediately typing space makes the buffer list go away and returns
+to the buffer and window which were previously selected.
+
+Otherwise one may use the c-p and c-n commands to move around in the
+buffer-list buffer and type Space or C-z to select the buffer on the
+cursor's line. There are a number of other commands which are the same
+as those of buffer-menu-mode.
+
+This is a useful thing to bind to c-x c-b in your `.emacs' file if the
+rather non-standard `electric' behaviour of the buffer list suits your taste.
+Type C-h after invoking electric-buffer-list for more information.
+
+Calls value of `electric-buffer-menu-mode-hook' if non-nil on entry.
+Calls value of `after-electric-buffer-menu' on exit (select) if non-nil.
+
+Changes in version 16 for mail reading and sending
+
+* sendmail prefix character is C-c (and not C-z). New command C-c w.
+
+For instance C-c C-c (or C-c C-s) sends mail now rather than C-z C-z.
+C-c w inserts your `signature' (contents of ~/.signature) at the end
+of mail.
+
+* New feature in C-c y command in sending mail.
+
+C-c y is the command to insert the message being replied to.
+Normally it deletes most header fields and indents everything
+by three spaces.
+
+Now, C-c y does not delete header fields or indent.
+C-c y with any other numeric argument does delete most header
+fields, but indents by the amount specified in the argument.
+
+* C-r command in Rmail edits current message.
+
+It does this by switching to a different major mode
+which is nearly the same as Text mode. The only difference
+between it and text mode are the two command C-c and C-].
+C-c is defined to switch back to Rmail mode, and C-]
+is defined to restore the original contents of the message
+and then switch back to Rmail mode.
+
+C-c and C-] are the only ways "back into Rmail", but you
+can switch to other buffers and edit them as usual.
+C-r in Rmail changes only the handling of the Rmail buffer.
+
+* Rmail command `t' toggles header display.
+
+Normally Rmail reformats messages to hide most header fields.
+`t' switches to display of all the header fields of the
+current message, as long as it remains current.
+Another `t' switches back to the usual display.
+
+* Rmail command '>' goes to the last message.
+
+* Rmail commands `a' and `k' set message attributes.
+`a' adds an attribute and `k' removes one. You specify
+the attrbute by name. You can specify either a built-in
+flag such as "deleted" or "filed", or a user-defined keyword
+(anything not recognized as built-in).
+
+* Rmail commands `l' and `L' summarize by attributes.
+
+These commands create a summary with one line per message,
+like `h', but they list only some of the messages. You
+specify which attribute (for `l') or attributes (for `L')
+the messages should have.
+
+* Rmail can parse mmdf mail files.
+
+* Interface to MH mail system.
+
+mh-e is a front end for GNU emacs and the MH mail system. It
+provides a friendly and convient interface to the MH commands.
+
+To read mail, invoke mh-rmail. This will inc new mail and display the
+scan listing on the screen. To see a summary of the mh-e commands,
+type ?. Help is available through the usual facilities.
+
+To send mail, invoke mh-smail.
+
+mh-e requires a copy of MH.5 that has been compiled with the MHE
+compiler switch.
+
+From larus@berkeley.
+
+New hooks and parameters in version 16
+
+* New variable `blink-matching-paren-distance'.
+
+This is the maximum number of characters to search for
+an open-paren to match an inserted close-paren.
+The matching open-paren is shown and checked if it is found
+within this distance.
+
+`nil' means search all the way to the beginning of the buffer.
+In this case, a warning message is printed if no matching
+open-paren is found.
+
+This feature was originally written by shane@mit-ajax.
+
+* New variable `find-file-run-dired'
+
+If nil, find-file will report an error if an attempt to visit a
+directory is detected; otherwise, it runs dired on that directory.
+The default is t.
+
+* Variable `dired-listing-switches' holds switches given to `ls' by dired.
+
+The value should be a string containing `-' followed by letters.
+The letter `l' had better be included and letter 'F' had better be excluded!
+The default is "-al".
+
+This feature was originally written by shane@mit-ajax.
+
+* New variable `display-time-day-and-date'.
+
+If this variable is set non-`nil', the function M-x display-time
+displays the day and date, as well as the time.
+
+* New parameter `c-continued-statement-indent'.
+
+This controls the extra indentation given to a line
+that continues a C statement started on the previous line.
+By default it is 2, which is why you would see
+
+ if (foo)
+ bar ();
+
+
+* Changed meaning of `c-indent-level'.
+
+The value of `c-brace-offset' used to be
+subtracted from the value of `c-indent-level' whenever
+that value was used. Now it is not.
+
+As a result, `c-indent-level' is now the offset of
+statements within a block, relative to the line containing
+the open-brace that starts the block.
+
+* turn-on-auto-fill is useful value for text-mode-hook.
+
+(setq text-mode-hook 'turn-on-auto-fill)
+is all you have to do to make sure Auto Fill mode is turned
+on whenever you enter Text mode.
+
+* Parameter explicit-shell-file-name for M-x shell.
+
+This variable, if non-nil, specifies the file name to use
+for the shell to run if you do M-x shell.
+
+Changes in version 16 affecting Lisp programming:
+
+* Documentation strings adapt to customization.
+
+Often the documentation string for a command wants to mention
+another command. Simply stating the other command as a
+character sequence has a disadvantage: if the user customizes
+Emacs by moving that function to a different command, the
+cross reference in the documentation becomes wrong.
+
+A new feature allows you to write the documentation string
+using a function name, and the command to run that function
+is looked up when the documentation is printed.
+
+If a documentation string contains `\[' (two characters) then
+the following text, up to the next `]', is taken as a function name.
+Instead of printing that function name, the command that runs it is printed.
+(M-x is used to construct a command if no shorter one exists.)
+
+For example, instead of putting `C-n' in a documentation string
+to refer to the C-n command, put in `\[next-line]'. (In practice
+you will need to quote the backslash with another backslash,
+due to the syntax for strings in Lisp and C.)
+
+To include the literal characters `\[' in a documentation string,
+precede them with `\='. To include the characters `\=', precede
+them with `\='. For example, "\\=\\= is the way to quote \\=\\["
+will come out as `\= is the way to quote \['.
+
+The new function `substitute-command-keys' takes a string possibly
+contaning \[...] constructs and replaces those constructs with
+the key sequences they currently stand for.
+
+* Primitives `find-line-comment' and `find-line-comment-body' flushed.
+
+Search for the value of `comment-start-skip' if you want to find
+whether and where a line has a comment.
+
+* New function `auto-save-file-name-p'
+
+Should return non-`nil' iff given a string which is the name of an
+auto-save file (sans directory name). If you redefine
+`make-auto-save-file-name', you should redefine this accordingly. By
+default, this function returns `t' for filenames beginning with
+character `#'.
+
+* The value of `exec-directory' now ends in a slash.
+
+This is to be compatible with most directory names in GNU Emacs.
+
+* Dribble files and termscript files.
+
+(open-dribble-file FILE) opens a dribble file named FILE. When a
+dribble file is open, every character Emacs reads from the terminal is
+written to the dribble file.
+
+(open-termscript FILE) opens a termscript file named FILE. When a
+termscript file is open, all characters sent to the terminal by Emacs
+are also written in the termscript file.
+
+The two of these together are very useful for debugging Emacs problems
+in redisplay.
+
+* Upper case command characters by default are same as lower case.
+
+If a character in a command is an upper case letter, and is not defined,
+Emacs uses the definition of the corresponding lower case letter.
+For example, if C-x U is not directly undefined, it is treated as
+a synonym for C-x u (undo).
+
+* Undefined function errors versus undefined variable errors.
+
+Void-symbol errors now say "boundp" if the symbol's value was void
+or "fboundp" if the function definition was void.
+
+* New function `bury-buffer'.
+
+The new function `bury-buffer' takes one argument, a buffer object,
+and puts that buffer at the end of the internal list of buffers.
+So it is the least preferred candidate for use as the default value
+of C-x b, or for other-buffer to return.
+
+* Already-displayed buffers have low priority for display.
+
+When a buffer is chosen automatically for display, or to be the
+default in C-x b, buffers already displayed in windows have lower
+priority than buffers not currently visible.
+
+* `set-window-start' accepts a third argument NOFORCE.
+
+This argument, if non-nil, prevents the window's force_start flag
+from being set. Setting the force_start flag causes the next
+redisplay to insist on starting display at the specified starting
+point, even if dot must be moved to get it onto the screen.
+
+* New function `send-string-to-terminal'.
+
+This function takes one argument, a string, and outputs its contents
+to the terminal exactly as specified: control characters, escape
+sequences, and all.
+
+* Keypad put in command mode.
+
+The terminal's keypad is now put into command mode, as opposed to
+numeric mode, while Emacs is running. This is done by means of the
+termcap `ks' and `ke' strings.
+
+* New function `generate-new-buffer'
+
+This function takes a string as an argument NAME and looks for a
+creates and returns a buffer called NAME if one did not already exist.
+Otherwise, it successively tries appending suffixes of the form "<1>",
+"<2>" etc to NAME until it creates a string which does not name an
+existing buffer. A new buffer with that name is the created and returned.
+
+* New function `prin1-to-string'
+This function takes one argument, a lisp object, and returns a string
+containing that object's printed representation, such as `prin1'
+would output.
+
+* New function `read-from-minibuffer'
+Lets you supply a prompt, initial-contents, a keymap, and specify
+whether the result should be interpreted as a string or a lisp object.
+
+Old functions `read-minibuffer', `eval-minibuffer', `read-string' all
+take second optional string argument which is initial contents of
+minibuffer.
+
+* minibuffer variable names changed (names of keymaps)
+
+minibuf-local-map -> minibuffer-local-map
+minibuf-local-ns-map -> minibuffer-local-ns-map
+minibuf-local-completion-map -> minibuffer-local-completion-map
+minibuf-local-must-match-map -> minibuffer-local-must-match-map
+
+Changes in version 16 affecting configuring and building Emacs
+
+* Configuration switch VT100_INVERSE eliminated.
+
+You can control the use of inverse video on any terminal by setting
+the variable `inverse-video', or by changing the termcap entry. If
+you like, set `inverse-video' in your `.emacs' file based on
+examination of (getenv "TERM").
+
+* New switch `-batch' makes Emacs run noninteractively.
+
+If the switch `-batch' is used, Emacs treats its standard output
+and input like ordinary files (even if they are a terminal).
+It does not display buffers or windows; the only output to standard output
+is what would appear as messages in the echo area, and each
+message is followed by a newline.
+
+The terminal modes are not changed, so that C-z and C-c retain
+their normal Unix meanings. Emacs does still read commands from
+the terminal, but the idea of `-batch' is that you use it with
+other command line arguments that tell Emacs a complete task to perform,
+including killing itself. `-kill' used as the last argument is a good
+way to accomplish this.
+
+The Lisp variable `noninteractive' is now defined, to be `nil'
+except when `-batch' has been specified.
+
+* Emacs can be built with output redirected to a file.
+
+This is because -batch (see above) is now used in building Emacs.
+
+For older news, see the file ONEWS.
+
+----------------------------------------------------------------------
+Copyright information:
+
+Copyright (C) 1985 Richard M. Stallman
+
+ Permission is granted to anyone to make or distribute verbatim copies
+ of this document as received, in any medium, provided that the
+ copyright notice and this permission notice are preserved,
+ thus giving the recipient permission to redistribute in turn.
+
+ Permission is granted to distribute modified versions
+ of this document, or of portions of it,
+ under the above conditions, provided also that they
+ carry prominent notices stating who last changed them.
+
+Local variables:
+mode: text
+end:
diff --git a/etc/OONEWS b/etc/OONEWS
new file mode 100644
index 00000000000..06b5405be1e
--- /dev/null
+++ b/etc/OONEWS
@@ -0,0 +1,1165 @@
+Old GNU Emacs NEWS -- history of user-visible changes thru version 15.
+Copyright (C) 1985 Richard M. Stallman.
+See the end for copying conditions.
+
+Changes in Emacs 15
+
+* Emacs now runs on Sun and Megatest 68000 systems;
+ also on at least one 16000 system running 4.2.
+
+* Emacs now alters the output-start and output-stop characters
+ to prevent C-s and C-q from being considered as flow control
+ by cretinous rlogin software in 4.2.
+
+* It is now possible convert Mocklisp code (for Gosling Emacs) to Lisp code
+ that can run in GNU Emacs. M-x convert-mocklisp-buffer
+ converts the contents of the current buffer from Mocklisp to
+ GNU Emacs Lisp. You should then save the converted buffer with C-x C-w
+ under a name ending in ".el"
+
+ There are probably some Mocklisp constructs that are not handled.
+ If you encounter one, feel free to report the failure as a bug.
+ The construct will be handled in a future Emacs release, if that is not
+ not too hard to do.
+
+ Note that lisp code converted from Mocklisp code will not necessarily
+ run as fast as code specifically written for GNU Emacs, nor will it use
+ the many features of GNU Emacs which are not present in Gosling's emacs.
+ (In particular, the byte-compiler (m-x byte-compile-file) knows little
+ about compilation of code directly converted from mocklisp.)
+ It is envisaged that old mocklisp code will be incrementally converted
+ to GNU lisp code, with M-x convert-mocklisp-buffer being the first
+ step in this process.
+
+* Control-x n (narrow-to-region) is now by default a disabled command.
+
+ This means that, if you issue this command, it will ask whether
+ you really mean it. You have the opportunity to enable the
+ command permanently at that time, so you will not be asked again.
+ This will place the form "(put 'narrow-to-region 'disabled nil)" in your
+ .emacs file.
+
+* Tags now prompts for the tag table file name to use.
+
+ All the tags commands ask for the tag table file name
+ if you have not yet specified one.
+
+ Also, the command M-x visit-tag-table can now be used to
+ specify the tag table file name initially, or to switch
+ to a new tag table.
+
+* If truncate-partial-width-windows is non-nil (as it intially is),
+ all windows less than the full screen width (that is,
+ made by side-by-side splitting) truncate lines rather than continuing
+ them.
+
+* Emacs now checks for Lisp stack overflow to avoid fatal errors.
+ The depth in eval, apply and funcall may not exceed max-lisp-eval-depth.
+ The depth in variable bindings and unwind-protects may not exceed
+ max-specpdl-size. If either limit is exceeded, an error occurs.
+ You can set the limits to larger values if you wish, but if you make them
+ too large, you are vulnerable to a fatal error if you invoke
+ Lisp code that does infinite recursion.
+
+* New hooks find-file-hook and write-file-hook.
+ Both of these variables if non-nil should be functions of no arguments.
+ At the time they are called (current-buffer) will be the buffer being
+ read or written respectively.
+
+ find-file-hook is called whenever a file is read into its own buffer,
+ such as by calling find-file, revert-buffer, etc. It is not called by
+ functions such as insert-file which do not read the file into a buffer of
+ its own.
+ find-file-hook is called after the file has been read in and its
+ local variables (if any) have been processed.
+
+ write-file-hook is called just before writing out a file from a buffer.
+
+* The initial value of shell-prompt-pattern is now "^[^#$%>]*[#$%>] *"
+
+* If the .emacs file sets inhibit-startup-message to non-nil,
+ the messages normally printed by Emacs at startup time
+ are inhibited.
+
+* Facility for run-time conditionalization on the basis of emacs features.
+
+ The new variable features is a list of symbols which represent "features"
+ of the executing emacs, for use in run-time conditionalization.
+
+ The function featurep of one argument may be used to test for the
+ presence of a feature. It is just the same as
+ (not (null (memq FEATURE features))) where FEATURE is its argument.
+ For example, (if (featurep 'magic-window-hack)
+ (transmogrify-window 'vertical)
+ (split-window-vertically))
+
+ The function provide of one argument "announces" that FEATURE is present.
+ It is much the same as (if (not (featurep FEATURE))
+ (setq features (cons FEATURE features)))
+
+ The function require with arguments FEATURE and FILE-NAME loads FILE-NAME
+ (which should contain the form (provide FEATURE)) unless FEATURE is present.
+ It is much the same as (if (not (featurep FEATURE))
+ (progn (load FILE-NAME)
+ (if (not featurep FEATURE) (error ...))))
+ FILE-NAME is optional and defaults to FEATURE.
+
+* New function load-average.
+
+ This returns a list of three integers, which are
+ the current 1 minute, 5 minute and 15 minute load averages,
+ each multiplied by a hundred (since normally they are floating
+ point numbers).
+
+* Per-terminal libraries loaded automatically.
+
+ Emacs when starting up on terminal type T automatically loads
+ a library named term-T. T is the value of the TERM environment variable.
+ Thus, on terminal type vt100, Emacs would do (load "term-vt100" t t).
+ Such libraries are good places to set the character translation table.
+
+ It is a bad idea to redefine lots of commands in a per-terminal library,
+ since this affects all users. Instead, define a command to do the
+ redefinitions and let the user's init file, which is loaded later,
+ call that command or not, as the user prefers.
+
+* Programmer's note: detecting killed buffers.
+
+ Buffers are eliminated by explicitly killing them, using
+ the function kill-buffer. This does not eliminate or affect
+ the pointers to the buffer which may exist in list structure.
+ If you have a pointer to a buffer and wish to tell whether
+ the buffer has been killed, use the function buffer-name.
+ It returns nil on a killed buffer, and a string on a live buffer.
+
+* New ways to access the last command input character.
+
+ The function last-key-struck, which used to return the last
+ input character that was read by command input, is eliminated.
+ Instead, you can find this information as the value of the
+ variable last-command-char. (This variable used to be called
+ last-key).
+
+ Another new variable, last-input-char, holds the last character
+ read from the command input stream regardless of what it was
+ read for. last-input-char and last-command-char are different
+ only inside a command that has called read-char to read input.
+
+* The new switch -kill causes Emacs to exit after processing the
+ preceding command line arguments. Thus,
+ emacs -l lib data -e do-it -kill
+ means to load lib, find file data, call do-it on no arguments,
+ and then exit.
+
+* The config.h file has been modularized.
+
+ Options that depend on the machine you are running on are defined
+ in a file whose name starts with "m-", such as m-vax.h.
+ Options that depend on the operating system software version you are
+ running on are defined in a file whose name starts with "s-",
+ such as s-bsd4.2.h.
+
+ config.h includes one m- file and one s- file. It also defines a
+ few other options whose values do not follow from the machine type
+ and system type being used. Installers normally will have to
+ select the correct m- and s- files but will never have to change their
+ contents.
+
+* Termcap AL and DL strings are understood.
+
+ If the termcap entry defines AL and DL strings, for insertion
+ and deletion of multiple lines in one blow, Emacs now uses them.
+ This matters most on certain bit map display terminals for which
+ scrolling is comparatively slow.
+
+* Bias against scrolling screen far on fast terminals.
+
+ Emacs now prefers to redraw a few lines rather than
+ shift them a long distance on the screen, when the terminal is fast.
+
+* New major mode, mim-mode.
+
+ This major mode is for editing MDL code. Perhaps a MDL
+ user can explain why it is not called mdl-mode.
+ You must load the library mim-mode explicitly to use this.
+
+* GNU documentation formatter `texinfo'.
+
+ The `texinfo' library defines a format for documentation
+ files which can be passed through Tex to make a printed manual
+ or passed through texinfo to make an Info file. Texinfo is
+ documented fully by its own Info file; compare this file
+ with its source, texinfo.texinfo, for additional guidance.
+
+ All documentation files for GNU utilities should be written
+ in texinfo input format.
+
+ Tex processing of texinfo files requires the Botex macro package.
+ This is not ready for distribution yet, but will appear at
+ a later time.
+
+* New function read-from-string (emacs 15.29)
+
+ read-from-string takes three arguments: a string to read from,
+ and optionally start and end indices which delimit a substring
+ from which to read. (They default to 0 and the length of the string,
+ respectively.)
+
+ This function returns a cons cell whose car is the object produced
+ by reading from the string and whose cdr is a number giving the
+ index in the string of the first character not read. That index may
+ be passed as the second argument to a later call to read-from-string
+ to read the next form represented by the string.
+
+ In addition, the function read now accepts a string as its argument.
+ In this case, it calls read-from-string on the whole string, and
+ returns the car of the result. (ie the actual object read.)
+
+Changes in Emacs 14
+
+* Completion now prints various messages such as [Sole Completion]
+ or [Next Character Not Unique] to describe the results obtained.
+ These messages appear after the text in the minibuffer, and remain
+ on the screen until a few seconds go by or you type a key.
+
+* The buffer-read-only flag is implemented.
+ Setting or binding this per-buffer variable to a non-nil value
+ makes illegal any operation which would modify the textual content of
+ the buffer. (Such operations signal a buffer-read-only error)
+ The read-only state of a buffer may be altered using toggle-read-only
+ (C-x C-q)
+ The buffers used by Rmail, Dired, Rnews, and Info are now read-only
+ by default to prevent accidental damage to the information in those
+ buffers.
+
+* Functions car-safe and cdr-safe.
+ These functions are like car and cdr when the argument is a cons.
+ Given an argument not a cons, car-safe always returns nil, with
+ no error; the same for cdr-safe.
+
+* The new function user-real-login-name returns the name corresponding
+ to the real uid of the Emacs process. This is usually the same
+ as what user-login-name returns; however, when Emacs is invoked
+ from su, user-real-login-name returns "root" but user-login-name
+ returns the name of the user who invoked su.
+
+Changes in Emacs 13
+
+* There is a new version numbering scheme.
+
+ What used to be the first version number, which was 1,
+ has been discarded since it does not seem that I need three
+ levels of version number.
+
+ However, a new third version number has been added to represent
+ changes by user sites. This number will always be zero in
+ Emacs when I distribute it; it will be incremented each time
+ Emacs is built at another site.
+
+* There is now a reader syntax for Meta characters:
+ \M-CHAR means CHAR or'ed with the Meta bit. For example:
+
+ ?\M-x is (+ ?x 128)
+ ?\M-\n is (+ ?\n 128)
+ ?\M-\^f is (+ ?\^f 128)
+
+ This syntax can be used in strings too. Note, however, that
+ Meta characters are not meaningful in key sequences being passed
+ to define-key or lookup-key; you must use ESC characters (\e)
+ in them instead.
+
+ ?\C- can be used likewise for control characters. (13.9)
+
+* Installation change
+ The string "../lisp" now adds to the front of the load-path
+ used for searching for Lisp files during Emacs initialization.
+ It used to replace the path specified in paths.h entirely.
+ Now the directory ../lisp is searched first and the directoris
+ specified in paths.h are searched afterward.
+
+Changes in Emacs 1.12
+
+* There is a new installation procedure.
+ See the file INSTALL that comes in the top level
+ directory in the tar file or tape.
+
+* The Meta key is now supported on terminals that have it.
+ This is a shift key which causes the high bit to be turned on
+ in all input characters typed while it is held down.
+
+ read-char now returns a value in the range 128-255 if
+ a Meta character is typed. When interpreted as command
+ input, a Meta character is equivalent to a two character
+ sequence, the meta prefix character followed by the un-metized
+ character (Meta-G unmetized is G).
+
+ The meta prefix character
+ is specified by the value of the variable meta-prefix-char.
+ If this character (normally Escape) has been redefined locally
+ with a non-prefix definition (such as happens in completing
+ minibuffers) then the local redefinition is suppressed when
+ the character is not the last one in a key sequence.
+ So the local redefinition is effective if you type the character
+ explicitly, but not effective if the character comes from
+ the use of the Meta key.
+
+* `-' is no longer a completion command in the minibuffer.
+ It is an ordinary self-inserting character.
+
+* The list load-path of directories load to search for Lisp files
+ is now controlled by the EMACSLOADPATH environment variable
+[[ Note this was originally EMACS-LOAD-PATH and has been changed
+ again; sh does not deal properly with hyphens in env variable names]]
+ rather than the EPATH environment variable. This is to avoid
+ conflicts with other Emacses.
+
+ While Emacs is being built initially, the load-path
+ is now just ("../lisp"), ignoring paths.h. It does not
+ ignore EMACSLOADPATH, however; you should avoid having
+ this variable set while building Emacs.
+
+* You can now specify a translation table for keyboard
+ input characters, as a way of exchanging or substituting
+ keys on the keyboard.
+
+ If the value of keyboard-translate-table is a string,
+ every character received from the keyboard is used as an
+ index in that string, and the character at that index in
+ the string is used as input instead of what was actually
+ typed. If the actual input character is >= the length of
+ the string, it is used unchanged.
+
+ One way this feature can be used is to fix bad keyboard
+ designes. For example, on some terminals, Delete is
+ Shift-Underscore. Since Delete is a more useful character
+ than Underscore, it is an improvement to make the unshifted
+ character Delete and the shifted one Underscore. This can
+ be done with
+
+ ;; First make a translate table that does the identity translation.
+ (setq keyboard-translate-table (make-string 128 0))
+ (let ((i 0))
+ (while (< i 128)
+ (aset keyboard-translate-table i i)
+ (setq i (1+ i))))
+
+ ;; Now alter translations of some characters.
+ (aset keyboard-translate-table ?\_ ?\^?)
+ (aset keyboard-translate-table ?\^? ?\_)
+
+ If your terminal has a Meta key and can therefore send
+ codes up to 255, Meta characters are translated through
+ elements 128 through 255 of the translate table, and therefore
+ are translated independently of the corresponding non-Meta
+ characters. You must therefore establish translations
+ independently for the Meta characters if you want them too:
+
+ ;; First make a translate table that does the identity translation.
+ (setq keyboard-translate-table (make-string 256 0))
+ (let ((i 0))
+ (while (< i 256)
+ (aset keyboard-translate-table i i)
+ (setq i (1+ i))))
+
+ ;; Now alter translations of some characters.
+ (aset keyboard-translate-table ?\_ ?\^?)
+ (aset keyboard-translate-table ?\^? ?\_)
+
+ ;; Now alter translations of some Meta characters.
+ (aset keyboard-translate-table (+ 128 ?\_) (+ 128 ?\^?))
+ (aset keyboard-translate-table (+ 128 ?\^?) (+ 128 ?\_))
+
+* (process-kill-without-query PROCESS)
+
+This marks the process so that, when you kill Emacs,
+you will not on its account be queried about active subprocesses.
+
+Changes in Emacs 1.11
+
+* The commands C-c and C-z have been interchanged,
+ for greater compatibility with normal Unix usage.
+ C-z now runs suspend-emacs and C-c runs exit-recursive-edit.
+
+* The value returned by file-name-directory now ends
+ with a slash. (file-name-directory "foo/bar") => "foo/".
+ This avoids confusing results when dealing with files
+ in the root directory.
+
+ The value of the per-buffer variable default-directory
+ is also supposed to have a final slash now.
+
+* There are now variables to control the switches passed to
+ `ls' by the C-x C-d command (list-directory).
+ list-directory-brief-switches is a string, initially "-CF",
+ used for brief listings, and list-directory-verbose-switches
+ is a string, initially "-l", used for verbose ones.
+
+* For Ann Arbor Ambassador terminals, the termcap "ti" string
+ is now used to initialize the screen geometry on entry to Emacs,
+ and the "te" string is used to set it back on exit.
+ If the termcap entry does not define the "ti" or "te" string,
+ Emacs does what it used to do.
+
+Changes in Emacs 1.10
+
+* GNU Emacs has been made almost 1/3 smaller.
+ It now dumps out as only 530kbytes on Vax 4.2bsd.
+
+* The term "checkpoint" has been replaced by "auto save"
+ throughout the function names, variable names and documentation
+ of GNU Emacs.
+
+* The function load now tries appending ".elc" and ".el"
+ to the specified filename BEFORE it tries the filename
+ without change.
+
+* rmail now makes the mode line display the total number
+ of messages and the current message number.
+ The "f" command now means forward a message to another user.
+ The command to search through all messages for a string is now "F".
+ The "u" command now means to move back to the previous
+ message and undelete it. To undelete the selected message, use Meta-u.
+
+* The hyphen character is now equivalent to a Space while
+ in completing minibuffers. Both mean to complete an additional word.
+
+* The Lisp function error now takes args like format
+ which are used to construct the error message.
+
+* Redisplay will refuse to start its display at the end of the buffer.
+ It will pick a new place to display from, rather than use that.
+
+* The value returned by garbage-collect has been changed.
+ Its first element is no longer a number but a cons,
+ whose car is the number of cons cells now in use,
+ and whose cdr is the number of cons cells that have been
+ made but are now free.
+ The second element is similar but describes symbols rather than cons cells.
+ The third element is similar but describes markers.
+
+* The variable buffer-name has been eliminated.
+ The function buffer-name still exists. This is to prevent
+ user programs from changing buffer names without going
+ through the rename-buffer function.
+
+Changes in Emacs 1.9
+
+* When a fill prefix is in effect, paragraphs are started
+ or separated by lines that do not start with the fill prefix.
+ Also, a line which consists of the fill prefix followed by
+ white space separates paragraphs.
+
+* C-x C-v runs the new function find-alternate-file.
+ It finds the specified file, switches to that buffer,
+ and kills the previous current buffer. (It requires
+ confirmation if that buffer had changes.) This is
+ most useful after you find the wrong file due to a typo.
+
+* Exiting the minibuffer moves the cursor to column 0,
+ to show you that it has really been exited.
+
+* Meta-g (fill-region) now fills each paragraph in the
+ region individually. To fill the region as if it were
+ a single paragraph (for when the paragraph-delimiting mechanism
+ does the wrong thing), use fill-region-as-paragraph.
+
+* Tab in text mode now runs the function tab-to-tab-stop.
+ A new mode called indented-text-mode is like text-mode
+ except that in it Tab runs the function indent-relative,
+ which indents the line under the previous line.
+ If auto fill is enabled while in indented-text-mode,
+ the new lines that it makes are indented.
+
+* Functions kill-rectangle and yank-rectangle.
+ kill-rectangle deletes the rectangle specified by dot and mark
+ (or by two arguments) and saves it in the variable killed-rectangle.
+ yank-rectangle inserts the rectangle in that variable.
+
+ Tab characters in a rectangle being saved are replaced
+ by spaces in such a way that their appearance will
+ not be changed if the rectangle is later reinserted
+ at a different column position.
+
+* `+' in a regular expression now means
+ to repeat the previous expression one or more times.
+ `?' means to repeat it zero or one time.
+ They are in all regards like `*' except for the
+ number of repetitions they match.
+
+ \< in a regular expression now matches the null string
+ when it is at the beginning of a word; \> matches
+ the null string at the end of a word.
+
+* C-x p narrows the buffer so that only the current page
+ is visible.
+
+* C-x ) with argument repeats the kbd macro just
+ defined that many times, counting the definition
+ as one repetition.
+
+* C-x ( with argument begins defining a kbd macro
+ starting with the last one defined. It executes that
+ previous kbd macro initially, just as if you began
+ by typing it over again.
+
+* C-x q command queries the user during kbd macro execution.
+ With prefix argument, enters recursive edit,
+ reading keyboard commands even within a kbd macro.
+ You can give different commands each time the macro executes.
+ Without prefix argument, reads a character. Your options are:
+ Space -- execute the rest of the macro.
+ Delete -- skip the rest of the macro; start next repetition.
+ C-d -- skip rest of the macro and don't repeat it any more.
+ C-r -- enter a recursive edit, then on exit ask again for a character
+ C-l -- redisplay screen and ask again."
+
+* write-kbd-macro and append-kbd-macro are used to save
+ a kbd macro definition in a file (as Lisp code to
+ redefine the macro when the file is loaded).
+ These commands differ in that write-kbd-macro
+ discards the previous contents of the file.
+ If given a prefix argument, both commands
+ record the keys which invoke the macro as well as the
+ macro's definition.
+
+* The variable global-minor-modes is used to display
+ strings in the mode line of all buffers. It should be
+ a list of elements thaht are conses whose cdrs are strings
+ to be displayed. This complements the variable
+ minor-modes, which has the same effect but has a separate
+ value in each buffer.
+
+* C-x = describes horizontal scrolling in effect, if any.
+
+* Return now auto-fills the line it is ending, in auto fill mode.
+ Space with zero as argument auto-fills the line before it
+ just like Space without an argument.
+
+Changes in Emacs 1.8
+
+This release mostly fixes bugs. There are a few new features:
+
+* apropos now sorts the symbols before displaying them.
+ Also, it returns a list of the symbols found.
+
+ apropos now accepts a second arg PRED which should be a function
+ of one argument; if PRED is non-nil, each symbol is tested
+ with PRED and only symbols for which PRED returns non-nil
+ appear in the output or the returned list.
+
+ If the third argument to apropos is non-nil, apropos does not
+ display anything; it merely returns the list of symbols found.
+
+ C-h a now runs the new function command-apropos rather than
+ apropos, and shows only symbols with definitions as commands.
+
+* M-x shell sends the command
+ if (-f ~/.emacs_NAME)source ~/.emacs_NAME
+ invisibly to the shell when it starts. Here NAME
+ is replaced by the name of shell used,
+ as it came from your ESHELL or SHELL environment variable
+ but with directory name, if any, removed.
+
+* M-, now runs the command tags-loop-continue, which is used
+ to resume a terminated tags-search or tags-query-replace.
+
+Changes in Emacs 1.7
+
+It's Beat CCA Week.
+
+* The initial buffer is now called "*scratch*" instead of "scratch",
+ so that all buffer names used automatically by Emacs now have *'s.
+
+* Undo information is now stored separately for each buffer.
+ The Undo command (C-x u) always applies to the current
+ buffer only.
+
+ C-_ is now a synonym for C-x u.
+
+ (buffer-flush-undo BUFFER) causes undo information not to
+ be kept for BUFFER, and frees the space that would have
+ been used to hold it. In any case, no undo information is
+ kept for buffers whose names start with spaces. (These
+ buffers also do not appear in the C-x C-b display.)
+
+* Rectangle operations are now implemented.
+ C-x r stores the rectangle described by dot and mark
+ into a register; it reads the register name from the keyboard.
+ C-x g, the command to insert the contents of a register,
+ can be used to reinsert the rectangle elsewhere.
+
+ Other rectangle commands include
+ open-rectangle:
+ insert a blank rectangle in the position and size
+ described by dot and mark, at its corners;
+ the existing text is pushed to the right.
+ clear-rectangle:
+ replace the rectangle described by dot ane mark
+ with blanks. The previous text is deleted.
+ delete-rectangle:
+ delete the text of the specified rectangle,
+ moving the text beyond it on each line leftward.
+
+* Side-by-side windows are allowed. Use C-x 5 to split the
+ current window into two windows side by side.
+ C-x } makes the selected window ARG columns wider at the
+ expense of the windows at its sides. C-x { makes the selected
+ window ARG columns narrower. An argument to C-x 5 specifies
+ how many columns to give to the leftmost of the two windows made.
+
+ C-x 2 now accepts a numeric argument to specify the number of
+ lines to give to the uppermost of the two windows it makes.
+
+* Horizontal scrolling of the lines in a window is now implemented.
+ C-x < (scroll-left) scrolls all displayed lines left,
+ with the numeric argument (default 1) saying how far to scroll.
+ When the window is scrolled left, some amount of the beginning
+ of each nonempty line is replaced by an "$".
+ C-x > scrolls right. If a window has no text hidden at the left
+ margin, it cannot be scrolled any farther right than that.
+ When nonzero leftwards scrolling is in effect in a window.
+ lines are automatically truncated at the window's right margin
+ regardless of the value of the variable truncate-lines in the
+ buffer being displayed.
+
+* C-x C-d now uses the default output format of `ls',
+ which gives just file names in multiple columns.
+ C-u C-x C-d passes the -l switch to `ls'.
+
+* C-t at the end of a line now exchanges the two preceding characters.
+
+ All the transpose commands now interpret zero as an argument
+ to mean to transpose the textual unit after or around dot
+ with the one after or around the mark.
+
+* M-! executes a shell command in an inferior shell
+ and displays the output from it. With a prefix argument,
+ it inserts the output in the current buffer after dot
+ and sets the mark after the output. The shell command
+ gets /dev/null as its standard input.
+
+ M-| is like M-! but passes the contents of the region
+ as input to the shell command. A prefix argument makes
+ the output from the command replace the contents of the region.
+
+* The mode line will now say "Def" after the major mode
+ while a keyboard macro is being defined.
+
+* The variable fill-prefix is now used by Meta-q.
+ Meta-q removes the fill prefix from lines that start with it
+ before filling, and inserts the fill prefix on each line
+ after filling.
+
+ The command C-x . sets the fill prefix equal to the text
+ on the current line before dot.
+
+* The new command Meta-j (indent-new-comment-line),
+ is like Linefeed (indent-new-line) except when dot is inside a comment;
+ in that case, Meta-j inserts a comment starter on the new line,
+ indented under the comment starter above. It also inserts
+ a comment terminator at the end of the line above,
+ if the language being edited calls for one.
+
+* Rmail should work correctly now, and has some C-h m documentation.
+
+Changes in Emacs 1.6
+
+* save-buffers-kill-emacs is now on C-x C-c
+ while C-x C-z does suspend-emacs. This is to make
+ C-x C-c like the normal Unix meaning of C-c
+ and C-x C-z linke the normal Unix meaning of C-z.
+
+* M-ESC (eval-expression) is now a disabled command by default.
+ This prevents users who type ESC ESC accidentally from
+ getting confusing results. Put
+ (put 'eval-expression 'disabled nil)
+ in your ~/.emacs file to enable the command.
+
+* Self-inserting text is grouped into bunches for undoing.
+ Each C-x u command undoes up to 20 consecutive self-inserting
+ characters.
+
+* Help f now uses as a default the function being called
+ in the innermost Lisp expression that dot is in.
+ This makes it more convenient to use while writing
+ Lisp code to run in Emacs.
+ (If the text around dot does not appear to be a call
+ to a Lisp function, there is no default.)
+
+ Likewise, Help v uses the symbol around or before dot
+ as a default, if that is a variable name.
+
+* Commands that read filenames now insert the default
+ directory in the minibuffer, to become part of your input.
+ This allows you to see what the default is.
+ You may type a filename which goes at the end of the
+ default directory, or you may edit the default directory
+ as you like to create the input you want to give.
+ You may also type an absolute pathname (starting with /)
+ or refer to a home directory (input starting with ~)
+ after the default; the presence of // or /~ causes
+ everything up through the slash that precedes your
+ type-in to be ignored.
+
+ Returning the default directory without change,
+ including the terminating slash, requests the use
+ of the default file name (usually the visited file's name).
+
+ Set the variable insert-default-directory to nil
+ to turn off this feature.
+
+* M-x shell now uses the environment variable ESHELL,
+ if it exists, as the file name of the shell to run.
+ If there is no ESHELL variable, the SHELL variable is used.
+ This is because some shells do not work properly as inferiors
+ of Emacs (or anything like Emacs).
+
+* A new variable minor-modes now exists, with a separate value
+ in each buffer. Its value should be an alist of elements
+ (MODE-FUNCTION-SYMBOL . PRETTY-NAME-STRING), one for each
+ minor mode that is turned on in the buffer. The pretty
+ name strings are displayed in the mode line after the name of the
+ major mode (with spaces between them). The mode function
+ symbols should be symbols whose function definitions will
+ turn on the minor mode if given 1 as an argument; they are present
+ so that Help m can find their documentation strings.
+
+* The format of tag table files has been changed.
+ The new format enables Emacs to find tags much faster.
+
+ A new program, etags, exists to make the kind of
+ tag table that Emacs wants. etags is invoked just
+ like ctags; in fact, if you give it any switches,
+ it does exactly what ctags would do. Give it the
+ empty switch ("-") to make it act like ctags with no switches.
+
+ etags names the tag table file "TAGS" rather than "tags",
+ so that these tag tables and the standard Unix ones
+ can coexist.
+
+ The tags library can no longer use standard ctags-style
+ tag tables files.
+
+* The file of Lisp code Emacs reads on startup is now
+ called ~/.emacs rather than ~/.emacs_pro.
+
+* copy-file now gives the copied file the same mode bits
+ as the original file.
+
+* Output from a process inserted into the process's buffer
+ no longer sets the buffer's mark. Instead it sets a
+ marker associated with the process to point to the end
+ of the inserted text. You can access this marker with
+ (process-mark PROCESS)
+ and then either examine its position with marker-position
+ or set its position with set-marker.
+
+* completing-read takes a new optional fifth argument which,
+ if non-nil, should be a string of text to insert into
+ the minibuffer before reading user commands.
+
+* The Lisp function elt now exists:
+ (elt ARRAY N) is like (aref ARRAY N),
+ (elt LIST N) is like (nth N LIST).
+
+* rplaca is now a synonym for setcar, and rplacd for setcdr.
+ eql is now a synonym for eq; it turns out that the Common Lisp
+ distinction between eq and eql is insignificant in Emacs.
+ numberp is a new synonym for integerp.
+
+* auto-save has been renamed to auto-save-mode.
+
+* Auto save file names for buffers are now created by the
+ function make-auto-save-file-name. This is so you can
+ redefine that function to change the way auto save file names
+ are chosen.
+
+* expand-file-name no longer discards a final slash.
+ (expand-file-name "foo" "/lose") => "/lose/foo"
+ (expand-file-name "foo/" "/lose") => "/lose/foo/"
+
+ Also, expand-file-name no longer substitutes $ constructs.
+ A new function substitute-in-file-name does this. Reading
+ a file name with read-file-name or the `f' or`F' option
+ of interactive calling uses substitute-in-file-name
+ on the file name that was read and returns the result.
+
+ All I/O primitives including insert-file-contents and
+ delete-file call expand-file-name on the file name supplied.
+ This change makes them considerably faster in the usual case.
+
+* Interactive calling spec strings allow the new code letter 'D'
+ which means to read a directory name. It is like 'f' except
+ that the default if the user makes no change in the minibuffer
+ is to return the current default directory rather than the
+ current visited file name.
+
+Changes in Emacs 1.5
+
+* suspend-emacs now accepts an optional argument
+ which is a string to be stuffed as terminal input
+ to be read by Emacs's superior shell after Emacs exits.
+
+ A library called ledit exists which uses this feature
+ to transmit text to a Lisp job running as a sibling of
+ Emacs.
+
+* If find-file is given the name of a directory,
+ it automatically invokes dired on that directory
+ rather than reading in the binary data that make up
+ the actual contents of the directory according to Unix.
+
+* Saving an Emacs buffer now preserves the file modes
+ of any previously existing file with the same name.
+ This works using new Lisp functions file-modes and
+ set-file-modes, which can be used to read or set the mode
+ bits of any file.
+
+* The Lisp function cond now exists, with its traditional meaning.
+
+* defvar and defconst now permit the documentation string
+ to be omitted. defvar also permits the initial value
+ to be omitted; then it acts only as a comment.
+
+Changes in Emacs 1.4
+
+* Auto-filling now normally indents the new line it creates
+ by calling indent-according-to-mode. This function, meanwhile,
+ has in Fundamental and Text modes the effect of making the line
+ have an indentation of the value of left-margin, a per-buffer variable.
+
+ Tab no longer precisely does indent-according-to-mode;
+ it does that in all modes that supply their own indentation routine,
+ but in Fundamental, Text and allied modes it inserts a tab character.
+
+* The command M-x grep now invokes grep (on arguments
+ supplied by the user) and reads the output from grep
+ asynchronously into a buffer. The command C-x ` can
+ be used to move to the lines that grep has found.
+ This is an adaptation of the mechanism used for
+ running compilations and finding the loci of error messages.
+
+ You can now use C-x ` even while grep or compilation
+ is proceeding; as more matches or error messages arrive,
+ C-x ` will parse them and be able to find them.
+
+* M-x mail now provides a command to send the message
+ and "exit"--that is, return to the previously selected
+ buffer. It is C-z C-z.
+
+* Tab in C mode now tries harder to adapt to all indentation styles.
+ If the line being indented is a statement that is not the first
+ one in the containing compound-statement, it is aligned under
+ the beginning of the first statement.
+
+* The functions screen-width and screen-height return the
+ total width and height of the screen as it is now being used.
+ set-screen-width and set-screen-height tell Emacs how big
+ to assume the screen is; they each take one argument,
+ an integer.
+
+* The Lisp function 'function' now exists. function is the
+ same as quote, except that it serves as a signal to the
+ Lisp compiler that the argument should be compiled as
+ a function. Example:
+ (mapcar (function (lambda (x) (+ x 5))) list)
+
+* The function set-key has been renamed to global-set-key.
+ undefine-key and local-undefine-key has been renamed to
+ global-unset-key and local-unset-key.
+
+* Emacs now collects input from asynchronous subprocesses
+ while waiting in the functions sleep-for and sit-for.
+
+* Shell mode's Newline command attempts to distinguish subshell
+ prompts from user input when issued in the middle of the buffer.
+ It no longer reexecutes from dot to the end of the line;
+ it reeexecutes the entire line minus any prompt.
+ The prompt is recognized by searching for the value of
+ shell-prompt-pattern, starting from the beginning of the line.
+ Anything thus skipped is not reexecuted.
+
+Changes in Emacs 1.3
+
+* An undo facility exists now. Type C-x u to undo a batch of
+ changes (usually one command's changes, but some commands
+ such as query-replace divide their changes into multiple
+ batches. You can repeat C-x u to undo further. As long
+ as no commands other than C-x u intervene, each one undoes
+ another batch. A numeric argument to C-x u acts as a repeat
+ count.
+
+ If you keep on undoing, eventually you may be told that
+ you have used up all the recorded undo information.
+ Some actions, such as reading in files, discard all
+ undo information.
+
+ The undo information is not currently stored separately
+ for each buffer, so it is mainly good if you do something
+ totally spastic. [This has since been fixed.]
+
+* A learn-by-doing tutorial introduction to Emacs now exists.
+ Type C-h t to enter it.
+
+* An Info documentation browser exists. Do M-x info to enter it.
+ It contains a tutorial introduction so that no more documentation
+ is needed here. As of now, the only documentation in it
+ is that of Info itself.
+
+* Help k and Help c are now different. Help c prints just the
+ name of the function which the specified key invokes. Help k
+ prints the documentation of the function as well.
+
+* A document of the differences between GNU Emacs and Twenex Emacs
+ now exists. It is called DIFF, in the same directory as this file.
+
+* C mode can now indent comments better, including multi-line ones.
+ Meta-Control-q now reindents comment lines within the expression
+ being aligned.
+
+* Insertion of a close-parenthesis now shows the matching open-parenthesis
+ even if it is off screen, by printing the text following it on its line
+ in the minibuffer.
+
+* A file can now contain a list of local variable values
+ to be in effect when the file is edited. See the file DIFF
+ in the same directory as this file for full details.
+
+* A function nth is defined. It means the same thing as in Common Lisp.
+
+* The function install-command has been renamed to set-key.
+ It now takes the key sequence as the first argument
+ and the definition for it as the second argument.
+ Likewise, local-install-command has been renamed to local-set-key.
+
+Changes in Emacs 1.2
+
+* A Lisp single-stepping and debugging facility exists.
+ To cause the debugger to be entered when an error
+ occurs, set the variable debug-on-error non-nil.
+
+ To cause the debugger to be entered whenever function foo
+ is called, do (debug-on-entry 'foo). To cancel this,
+ do (cancel-debug-on-entry 'foo). debug-on-entry does
+ not work for primitives (written in C), only functions
+ written in Lisp. Most standard Emacs commands are in Lisp.
+
+ When the debugger is entered, the selected window shows
+ a buffer called " *Backtrace" which displays a series
+ of stack frames, most recently entered first. For each
+ frame, the function name called is shown, usually followed
+ by the argument values unless arguments are still being
+ calculated. At the beginning of the buffer is a description
+ of why the debugger was entered: function entry, function exit,
+ error, or simply that the user called the function `debug'.
+
+ To exit the debugger and return to top level, type `q'.
+
+ In the debugger, you can evaluate Lisp expressions by
+ typing `e'. This is equivalent to `M-ESC'.
+
+ When the debugger is entered due to an error, that is
+ all you can do. When it is entered due to function entry
+ (such as, requested by debug-on-entry), you have two
+ options:
+ Continue execution and reenter debugger after the
+ completion of the function being entered. Type `c'.
+ Continue execution but enter the debugger before
+ the next subexpression. Type `d'.
+
+ You will see that some stack frames are marked with *.
+ This means the debugger will be entered when those
+ frames exit. You will see the value being returned
+ in the first line of the backtrace buffer. Your options:
+ Continue execution, and return that value. Type `c'.
+ Continue execution, and return a specified value. Type `r'.
+
+ You can mark a frame to enter the debugger on exit
+ with the `b' command, or clear such a mark with `u'.
+
+* Lisp macros now exist.
+ For example, you can write
+ (defmacro cadr (arg) (list 'car (list 'cdr arg)))
+ and then the expression
+ (cadr foo)
+ will expand into
+ (car (cdr foo))
+
+Changes in Emacs 1.1
+
+* The initial buffer is now called "scratch" and is in a
+ new major mode, Lisp Interaction mode. This mode is
+ intended for typing Lisp expressions, evaluating them,
+ and having the values printed into the buffer.
+
+ Type Linefeed after a Lisp expression, to evaluate the
+ expression and have its value printed into the buffer,
+ advancing dot.
+
+ The other commands of Lisp mode are available.
+
+* The C-x C-e command for evaluating the Lisp expression
+ before dot has been changed to print the value in the
+ minibuffer line rather than insert it in the buffer.
+ A numeric argument causes the printed value to appear
+ in the buffer instead.
+
+* In Lisp mode, the command M-C-x evaluates the defun
+ containing or following dot. The value is printed in
+ the minibuffer.
+
+* The value of a Lisp expression evaluated using M-ESC
+ is now printed in the minibuffer.
+
+* M-q now runs fill-paragraph, independent of major mode.
+
+* C-h m now prints documentation on the current buffer's
+ major mode. What it prints is the documentation of the
+ major mode name as a function. All major modes have been
+ equipped with documentation that describes all commands
+ peculiar to the major mode, for this purpose.
+
+* You can display a Unix manual entry with
+ the M-x manual-entry command.
+
+* You can run a shell, displaying its output in a buffer,
+ with the M-x shell command. The Return key sends input
+ to the subshell. Output is printed inserted automatically
+ in the buffer. Commands C-c, C-d, C-u, C-w and C-z are redefined
+ for controlling the subshell and its subjobs.
+ "cd", "pushd" and "popd" commands are recognized as you
+ enter them, so that the default directory of the Emacs buffer
+ always remains the same as that of the subshell.
+
+* C-x $ (that's a real dollar sign) controls line-hiding based
+ on indentation. With a numeric arg N > 0, it causes all lines
+ indented by N or more columns to become invisible.
+ They are, effectively, tacked onto the preceding line, where
+ they are represented by " ..." on the screen.
+ (The end of the preceding visible line corresponds to a
+ screen cursor position before the "...". Anywhere in the
+ invisible lines that follow appears on the screen as a cursor
+ position after the "...".)
+ Currently, all editing commands treat invisible lines just
+ like visible ones, except for C-n and C-p, which have special
+ code to count visible lines only.
+ C-x $ with no argument turns off this mode, which in any case
+ is remembered separately for each buffer.
+
+* Outline mode is another form of selective display.
+ It is a major mode invoked with M-x outline-mode.
+ It is intended for editing files that are structured as
+ outlines, with heading lines (lines that begin with one
+ or more asterisks) and text lines (all other lines).
+ The number of asterisks in a heading line are its level;
+ the subheadings of a heading line are all following heading
+ lines at higher levels, until but not including the next
+ heading line at the same or a lower level, regardless
+ of intervening text lines.
+
+ In outline mode, you have commands to hide (remove from display)
+ or show the text or subheadings under each heading line
+ independently. Hidden text or subheadings are invisibly
+ attached to the end of the preceding heading line, so that
+ if you kill the hading line and yank it back elsewhere
+ all the invisible lines accompany it.
+
+ All editing commands treat hidden outline-mode lines
+ as part of the preceding visible line.
+
+* C-x C-z runs save-buffers-kill-emacs
+ offers to save each file buffer, then exits.
+
+* C-c's function is now called suspend-emacs.
+
+* The command C-x m runs mail, which switches to a buffer *mail*
+ and lets you compose a message to send. C-x 4 m runs mail in
+ another window. Type C-z C-s in the mail buffer to send the
+ message according to what you have entered in the buffer.
+
+ You must separate the headers from the message text with
+ an empty line.
+
+* You can now dired partial directories (specified with names
+ containing *'s, etc, all processed by the shell). Also, you
+ can dired more than one directory; dired names the buffer
+ according to the filespec or directory name. Reinvoking
+ dired on a directory already direded just switches back to
+ the same directory used last time; do M-x revert if you want
+ to read in the current contents of the directory.
+
+ C-x d runs dired, and C-x 4 d runs dired in another window.
+
+ C-x C-d (list-directory) also allows partial directories now.
+
+Lisp programming changes
+
+* t as an output stream now means "print to the minibuffer".
+ If there is already text in the minibuffer printed via t
+ as an output stream, the new text is appended to the old
+ (or is truncated and lost at the margin). If the minibuffer
+ contains text put there for some other reason, it is cleared
+ first.
+
+ t is now the top-level value of standard-output.
+
+ t as an input stream now means "read via the minibuffer".
+ The minibuffer is used to read a line of input, with editing,
+ and this line is then parsed. Any excess not used by `read'
+ is ignored; each `read' from t reads fresh input.
+ t is now the top-level value of standard-input.
+
+* A marker may be used as an input stream or an output stream.
+ The effect is to grab input from where the marker points,
+ advancing it over the characters read, or to insert output
+ at the marker and advance it.
+
+* Output from an asynchronous subprocess is now inserted at
+ the end of the associated buffer, not at the buffer's dot,
+ and the buffer's mark is set to the end of the inserted output
+ each time output is inserted.
+
+* (pos-visible-in-window-p POS WINDOW)
+ returns t if position POS in WINDOW's buffer is in the range
+ that is being displayed in WINDOW; nil if it is scrolled
+ vertically out of visibility.
+
+ If display in WINDOW is not currently up to date, this function
+ calculates carefully whether POS would appear if display were
+ done immediately based on the current (window-start WINDOW).
+
+ POS defaults to (dot), and WINDOW to (selected-window).
+
+* Variable buffer-alist replaced by function (buffer-list).
+ The actual alist of buffers used internally by Emacs is now
+ no longer accessible, to prevent the user from crashing Emacs
+ by modifying it. The function buffer-list returns a list
+ of all existing buffers. Modifying this list cannot hurt anything
+ as a new list is constructed by each call to buffer-list.
+
+* load now takes an optional third argument NOMSG which, if non-nil,
+ prevents load from printing a message when it starts and when
+ it is done.
+
+* byte-recompile-directory is a new function which finds all
+ the .elc files in a directory, and regenerates each one which
+ is older than the corresponding .el (Lisp source) file.
+
+----------------------------------------------------------------------
+Copyright information:
+
+Copyright (C) 1985 Richard M. Stallman
+
+ Permission is granted to anyone to make or distribute verbatim copies
+ of this document as received, in any medium, provided that the
+ copyright notice and this permission notice are preserved,
+ thus giving the recipient permission to redistribute in turn.
+
+ Permission is granted to distribute modified versions
+ of this document, or of portions of it,
+ under the above conditions, provided also that they
+ carry prominent notices stating who last changed them.
+
+Local variables:
+mode: text
+end:
diff --git a/etc/OPTIONS b/etc/OPTIONS
new file mode 100644
index 00000000000..b08ffc71f57
--- /dev/null
+++ b/etc/OPTIONS
@@ -0,0 +1,190 @@
+This describes the sequence of Emacs start-up actions, including the meaning
+of all the command-line options. It was written by Joe Wells.
+
+ 1. These command line switches are handled, only if they appear before
+ all other command line arguments, and only if they appear in this
+ order:
+
+ `-map'. Only under VMS. Instead of "undumping", under VMS the
+ contents of a dump file are mapped over a section of memory (very
+ quickly initializing lots of variables). You would not normally
+ use this options explicitly; it is given automatically by the
+ command file that implements the `emacs' command.
+
+ `-t'. The next argument is treated as the name of a terminal to use
+ instead of whatever is connected to the stdin, stdout, and stderr
+ FILE pointers.
+
+ `-display' (synonym: `-d'). The next argument is treated as the
+ name of an X Window System server with which to connect. This
+ overrides the DISPLAY environment variable.
+
+ `-nw'. This means don't connect to an X Window server even if the
+ DISPLAY environment variable was set or the `-display' switch was
+ specified. Instead, Emacs talks to a regular dumb terminal.
+
+ `-batch'. Run noninteractively. This disables any full screen
+ interaction either with a dumb terminal or with a window system.
+ In addition, Emacs will die after processing all command line
+ arguments. The variable `noninteractive' is t.
+
+ All of Emacs's internal data structures are initialized between steps 2
+ and 5.
+
+ 2. The `*scratch*' buffer is created and its value of `default-directory'
+ is set from the result of calling the `getwd' library routine.
+ (getwd does what the `pwd' program does.)
+
+ 3. If X11 is being used, Emacs determines the name under which it looks
+ for X resource values. (I haven't checked how it does this under
+ X10.)
+
+ 1. If there is a `-rn' command line switch, it is handled now, no
+ matter where it is on the command line. (Later it will be
+ processed again and ignored.) The next argument is used as
+ Emacs's resource name.
+
+ 2. If the `-rn' switch was missing, Emacs looks for the WM_RES_NAME
+ environment variable.
+
+ 3. If neither of the previous two steps succeed, Emacs uses the
+ filename with which it was invoked as its resource name.
+
+ 4. If X11 is being used, these command line switches are handled now,
+ no matter where they appear in the command line. (Under X10, they
+ are not handled until step 13.) WARNING: this can cause strange
+ interactions with the processing of the remaining command line
+ arguments in step 13.
+
+ In addition, under both X11 and X10, X resources (ie. the stuff in
+ an `.Xdefaults' file) are handled now. Command line switches take
+ precedence over resources.
+
+ After each command line switch are given the equivalent resource
+ names in this format: (X10 name / X11 instance name / X11 class name).
+
+ `-r'. Reverse video. (ReverseVideo/reverseVideo/ReverseVideo)
+ `-font' (synonym: `-fn'). Font. (BodyFont/font/Font)
+ `-wn'. Window name (X11 only). (/title/Title)
+ `-in'. Icon name (X11 only). (/iconName/Title)
+ `-i'. Use built-in icon bitmap. (BitMapIcon//)
+
+ `-b'. Border width (in pixels).
+ (BorderWidth/borderWidth/BorderWidth)
+
+ `-ib'. Internal border width (in pixels) (default: 1).
+ (/internalBorder/BorderWidth)
+
+ `-xrm RESOURCESTRING'. Specifies a resource name and value
+ that overrides any other value in the X server for that name.
+ This is useful also for setting parameters that don't have their
+ own specific options.
+
+ `-geometry' (synonym: `-w'). Window shape and size. `-geometry' is
+ X11 only, but its synonym `-w' was available under X10.
+ (/geometry/Geometry)
+
+ Color options only:
+
+ `-fg'. Foreground color. (Foreground/foreground/Foreground)
+ `-bg'. Background color. (Background/background/Background)
+ `-bd'. Border color. (Border/borderColor/BorderColor)
+ `-cr'. Cursor color. (Cursor/cursorColor/Foreground)
+ `-ms'. Mouse pointer color. (Mouse/pointerColor/Foreground)
+
+ In addition, under X10, the resource `Keymap' was handled now.
+
+ 5. If your Emacs isn't dumped, the default Lisp libraries are
+ loaded now.
+
+ 6. Emacs enters a recursive edit. The first time Emacs does a
+ recursive edit, steps 7 through 15 are followed, and then Emacs
+ enters its normal editing mode.
+
+ 7. If the environment variable PWD exists, the value of
+ `default-directory' in the `*scratch*' buffer is set to the value of
+ PWD. This often causes problems and confusion when the value of PWD
+ doesn't actually contain the pathname of the current directory.
+
+ 8. Now the `-no-init-file' (synonym: `-q') and `-user' (synonym: `-u')
+ command line switches are handled. They must follow the switches
+ mentioned in step 1, and must precede any other command line
+ arguments. Actually, both of these options can be specified;
+ whichever is last on the command line wins.
+
+ 9. The user's `.emacs' file is loaded now, if the `-no-init-file'
+ option was not specified. If the `-user' option was specified,
+ that user's init file is loaded instead. This file is named
+ `.emacs' in the user's home directory. If no such file exists,
+ this step has no effect.
+
+ 10. The system wide `default.el' file is loaded now, if the variable
+ `inhibit-default-init' is nil. The user can set this variable in the
+ `.emacs' file to skip this step.
+
+ 11. If the *scratch* buffer still exists now, the value of
+ `initial-major-mode' is called as a function in this buffer.
+ Normally, this puts this buffer in Lisp Interaction mode.
+
+ 12. Now the terminal/window-system setup file is loaded. The name of
+ this file is determined as follows:
+
+ 1. It starts with the value of `term-file-prefix'. Normally this is
+ `term/', but the user can set it to another value. If this
+ variable is nil, this entire step is skipped.
+
+ 2. For a window system, the prefix is followed by the name of the
+ value of the variable `window-system', followed by `-win'. For X
+ Windows, this means the name is `term/x-win'.
+
+ 3. For a terminal, the prefix is followed by the value of the
+ environment variable TERM, for example, `term/vt200'. If Emacs
+ cannot find such a file to load, it retries by stripping off
+ suffixes that begin with a hyphen. For example, if TERM is
+ `vt200-40', first Emacs will try `term/vt200-40', and if that
+ fails it will try `term/vt200'.
+
+ 13. The rest of the command line arguments are handled at this point, in
+ the order they appear:
+
+ `-funcall' (synonyms: `-f', `-e'). The next argument is treated as
+ the name of a function, which is called with no arguments.
+
+ `-load' (synonym: `-l'). The next argument is treated as the name
+ of a file to load. NOTE: the value of the variable `load-path'
+ will be restored after this file is done loading. Thus, trying
+ to change `load-path' in such a file will fail!!
+
+ `-kill'. When this argument is handled, Emacs kills itself.
+
+ `+DDD', where D is a digit. DDD is used as a line number to go to.
+ When the next ordinary file argument on the command line is
+ handled, Emacs positions point in that file on line DDD.
+
+ An ordinary filename. Emacs edits this file using the function
+ `find-file'. If the filename is not an absolute filename, it is
+ expanded relative to the value that default-directory in the
+ `*scratch*' buffer had at the beginning of step 11. The buffer
+ visiting this file becomes the current buffer.
+
+ `-insert' (synonym: `-i'). The next argument is treated as the name
+ of a file. This file is inserted in the current buffer.
+ Initially, this is the `*scratch*' buffer. Otherwise it is the
+ buffer visiting the file most recently specified on the command
+ line.
+
+ Other command line switches may have been created by modifying the
+ value of the variable `command-switch-alist'. If X Windows is being
+ used, all X-specific switches mentioned above in steps 3 and 4 will
+ be processed. Under X11, they will have already been handled, and
+ will be ignored now. Under X10, they are being handled for the
+ first time.
+
+ 14. The values of the variables `term-setup-hook' and `window-setup-hook'
+ are called as functions with no arguments, in the order listed.
+
+ 15. If the user did not specify any of the command line options handled
+ in step 13, and the variable `inhibit-startup-message' is still nil,
+ the familiar Emacs startup message is displayed.
+
+
diff --git a/etc/SERVICE b/etc/SERVICE
new file mode 100644
index 00000000000..b6015387546
--- /dev/null
+++ b/etc/SERVICE
@@ -0,0 +1,968 @@
+GNU Service Directory -*- text -*-
+
+This is a list of people who have asked to be listed as offering
+support services for GNU software, including GNU Emacs, for a fee
+or in some cases at no charge.
+
+The information comes from the people who asked to be listed;
+we do not include any information we know to be false, but we
+cannot check out any of the information; we are transmitting it to
+you as it was given to us and do not promise it is correct.
+Also, this is not an endorsement of the people listed here.
+We have no opinions and usually no information about the abilities of
+any specific person. We provide this list to enable you to contact
+service providers and decide for yourself whether to hire one.
+
+Before FSF will list your name in the GNU Service Directory, we ask
+that you agree informally to the following terms:
+
+1. You will not restrict (except by copyleft) the use or distribution
+of any software, documentation, or other information you supply anyone
+in the course of modifying, extending, or supporting GNU software.
+This includes any information specifically designed to ameliorate the
+use of GNU software.
+
+2. You will not take advantage of contact made through the Service
+Directory to advertise an unrelated business (e.g., sales of
+non-GNU-related proprietary information). You may spontaneously
+mention your availability for general consulting, but you should not
+promote a specific unrelated business unless the client asks.
+
+Please include some indication of your rates, because otherwise users
+have nothing to go by. Please put each e-mail address inside "<>".
+Please put nothing else inside "<>". Thanks!
+
+For a current copy of this directory, or to have yourself listed, ask:
+ gnu@prep.ai.mit.edu
+
+** Please keep this file alphabetical **
+
+
+Joseph Arceneaux <jla@ai.mit.edu>
+PO Box 460633
+San Francisco, CA 94146-0633
++1 415 285 9088
+
+Performed X11 implementation of Emacs version 19.
+Worked on Emacs text annotation.
+
+Service and development of GNU and X11 software. Handholding, teaching,
+and installations at lower rates.
+
+Rates: $150/hour. Free to selected non-profit and activist organizations.
+
+Updated: 11/7/91
+
+Giuseppe Attardi <attardi@di.unipi.it>
+Dipartimento di Informatica
+Corso Italia 40
+I-56125 Pisa, Italy
++39 (50) 510-111
+
+GNU: help on obtaininig GNU, for italian sites.
+
+Updated: 18/11/91
+
+Randolph Back <rback@boulder.Colorado.edu>
+Back Software & Consulting, Inc.
+1705 14th St. #344
+Boulder, CO 80302
+(303) 443-7758
+
+Consulting, installation, cutomization and training for GNU emacs, and
+other GNU software.
+
+Entered: 3/13/91
+
+Andrea Baldi
+European Space Agency (ESA)
+European Space Operations Center (ESOC)
+Robert-Bosch-Str 5
+D-6100 DARMSTADT
+West-Germany
+Phone 0049-6151-902762 (Work) Bitnet : <abaldi@esoc.bitnet>
+Fax 0049-6151-90-495 Uucp : <unido!esoc.bitnet!abaldi>
+
+Your Rate: Free
+
+Programs Supported: Emacs, bison, gcc, g++, gdb, bash, X11
+ Emacs: installation and upgrading aid, answering, customization.
+ Gcc, g++, gdb, bash: installation and upgrading aid.
+ X11: quick questions
+
+Experience (with gnu software)
+ I have maintained Emacs for more than 4 years as well as bison, gcc,
+ g++, gdb, bash, X11. I have written/modified several Emacs lisp programs.
+ Currently I maintain many GNU programs for my department.
+
+Updated: 11 Sept 91
+
+ Bard Bloom
+ Department of Computer Science
+ Cornell University
+ Ithaca, NY 14850
+ 607-255-9211
+
+Your Rate: $200/hour.
+ I might do work for friends and worthy organizations for free.
+
+Programs Supported: GNU Emacs
+
+Experience: Lots. For example, in 1989 I wrote a safe multi-user
+ database program of sorts in Gnu Emacs in about a week.
+ I've written some 30,000 lines of Gnu Lisp code in total.
+
+Degree: PhD in CS from MIT.
+Other: My real life as a professor takes precedence over consulting.
+
+Updated: 11 Sept 91
+
+James Craig Burley
+4 Mountain Gate Rd.
+Ashland, MA 01721-2326
+(508) 881-6087, -4745
+Email: <burley@gnu.ai.mit.edu> (preferred)
+ <burley@cygnus.com>
+ <burley@world.std.com>
+
+Expertise:
+ Compiler Internals (author of GNU Fortran, for example)
+ Operating Systems Internals (lately Linux on the ix86)
+ Tools/Utilities Development and Maintenance
+ Microcode Development and Maintenance (primarily VLIW machines)
+ Debugging (often asked to help debug Other People's Code)
+ Documentation (authored many books and ran a few doc projects)
+ Extensive experience with a variety of operating systems, hardware,
+ languages, and so on
+
+Rate: $75/hour, though somewhat volatile due to commitments regarding
+ GNU Fortran -- willing to consider flat-fee arrangements
+
+Entered: 10 Jul 92
+
+Michael I. Bushnell <mib@gnu.ai.mit.edu>
+NE43-426, 545 Technology Square
+Cambridge, MA 02139
+(617) 253-8568
+
+All GNU software: Installation, customization, answering simple or
+ complex questions, bug fixing, extension.
+
+Experience: I have done Unix and GNU programming for several years,
+ I am the primary author of the Hurd (which provides most
+ kernel related facilities for the GNU OS).
+
+I am easily available in the Cambridge/Boston area; work via email.
+I am willing to travel for sufficiently large jobs.
+
+Rates: $50/hr, negotiable, less for non-profit organizaions.
+
+Updated: 10/29/91
+
+C2V Renaud Dumeur <renaud@ccv.fr>
+82 bd Haussmann Jean-Alain Le Borgne <jalb@ccv.fr>
+75009 Paris
+France
+Tel (1) 40.08.07.07
+Fax (1) 43.87.35.99
+
+Emacs: questions answered, installation, teaching (all levels), elisp
+ and C extensions and customization, porting, troubleshooting
+gcc: installation, extensions, porting
+gdb: installation, debugging, porting
+X11: installation, debugging, internationalization
+
+Experience: yes (ask for details)
+
+Rates: 500ff/hr, negotiable.
+
+Entered: 12/17/91
+
+Mr. David J. Camp <david@wubios.wustl.edu>
+6103 Charlotte Avenue
+Saint Louis, MO 63120-1201
+
+Background: Bachelor of Science in Computer Science, Washington University
+ Master of Science in Computer Science, Washington University
+ Over 12 years experience in the computer industry.
+ Author of the future GNU uu/xxen/decoder program.
+ Skilled in many languages, including C and Unix scripts.
+
+Tasks: I can do on-site service in the St. Louis area.
+ I prefer short-term projects.
+ I can handle long projects given time.
+ I reserve the right to refuse work.
+
+Rates: $50 per hour, including travel time
+
+Entered: 1/1/91
+
+Computing Support Team (CSTeam)
+111 College Place, Rm 2-212
+Syracuse, NY, 13244-4100
+
+phone: 1-315-443-3929, fax: 1-315-443-4745, email: <info@csteam.com>
+
+The Computing Support Team offers a wide variety of support services
+including system design, installation, software support, contract
+programming, network design, integration and migration services,
+training, e-mail and telephone support. Experienced with GNU, X, TeX,
+and other public domain software.
+
+Rates: $50-$80/hr, 33% non-profit discount.
+
+Entered: 10 Jul 92
+
+Contributed Software
+Graefestr. 76
+1000 Berlin 61, Germany
+phone: (+49 30) 694 69 07
+modems: (+49 30) 694 {61 82 | 67 49 | 68 09}
+email: <info@contrib.de>
+internet: scuzzy.contrib.de [192.109.39.1]
+
+We distribute, install/port, teach and support free software
+in general, i.e. X11, GNU, khoros etc.
+Rates are DM 150,-- plus tax per hour, educational sites get rebates.
+
+Entered: 10 Jul 92
+
+Cygnus Support <info@cygnus.com>
+814 University Avenue ...uunet!cygint!info
+Palo Alto, CA 94301
++1 415 322 3811 Voice
++1 415 322 3270 FAX
+
+Cygnus Support offers warranty protection (service contracts) for a
+number of free software tools. For a fixed annual fee our customers
+receive binary and source distributions, mail and phone support,
+documentation and customization assistance on a variety of popular
+platforms.
+
+At the time of this writing we offer support for a development package
+including (among other things) gcc, g++, gdb, and of course, GNU
+Emacs. We also offer support for a network facilities package
+including many of the Athena tools like Kerberos and Hesiod. However
+the set of supported tools and platforms increases frequently so
+contact us for the latest information.
+
+For those who need on-site assistance, support is also available from
+our Cambridge office.
+
+Rates: $300/hour. Annual Support starts at $35,000.
+
+Updated: 11 Sept 91
+
+Bradley N. Davis <b-davis@jaguar.utah.edu>
+3242 South 540 West
+Bountiful, UT 84010
+(801) 298-6345
+
+Will work on most GNU software. Especially GNU Emacs, GCC and a
+little X11 and G++. Experienced with PCs and 386s.
+
+Services offered: Installation, porting, customizing, troubleshooting.
+
+Fee: $20 to $50 / hour depending on job
+
+Updated: 6/11/91
+
+DePalma SoftCraft Contact: Mauro DePalma
+2923 Cohansey Drive Voice: (408) 259-4789
+San Jose, CA 95132-1619 Fax: (408) 259-6935
+ Internet: <mauro@netcom.com> (or <apple!netcom!mauro>)
+
+DePalma SoftCraft provides distribution, installation, setup, and
+support for the X Window System (X11R4).
+
+This small business provides consulting in every area of a computer
+s/w project life cycle. We specialize in UNIX, GNU Development Tools
+(gcc, g++, ...), RCS, and XView.
+
+Updated: 4/29/91
+
+Equivalent Software HB <ingwa@isy.liu.se>
+Repslagaregatan 34 or <jonas-y@isy.liu.se>
+582 22 Linkoping
+SWEDEN
++46 (0)13 13 54 21
+
+Equivalent Software HB is the worlds second(?) company dedicated to
+supporting free UNIX software. The owners have more than 5 years of
+UNIX experience, both as system adminstrators and programmers. We
+also have extensive experience in maintaining the GNU programs, both
+administrating it and fixing bugs.
+
+Services offered:
+
+ - Installation and custumizing GNU and other free software. We will
+ make free software as easy to install and use as shrink wrapped
+ programs.
+ - Customization and porting.
+ - Subscriptions to new versions which we will send monthly or with
+ any other interval.
+ - Finding, Recommending and Investigation of free software in any
+ area of the customers choise.
+ - Regular consulting. We prefer smaller jobs, but are willing to
+ consider larger ones. We can work through the Internet, but prefer
+ jobs in Sweden.
+
+Rates: For software items, request our price list.
+ For consulting, 450 SEK/hour.
+
+Entered: 2/14/92
+
+Andy Gaynor -- [Ag] <gaynor@paul.rutgers.edu>
+597 Hoes Lane, Piscataway, NJ 08854
+908-463-3376
+
+GNU Emacs:
+ Lisp development, customization, troubleshooting, support, etc
+ User instruction and management for all levels of experience
+ Umpteen-thousand lines of Lisp code, careful study of GNU Emacs organization,
+ years of monitoring the UseNet Emacs and GNU groups, etc
+ Version 19 is due soon -- I will be up-to-speed as quickly as possible
+ $50/hour starting, negotiable on difficulty, organization, distribution, etc
+
+Other Tasks:
+ General programming/software engineering (language software preferred)
+ Familiar with Unix, C, Lisp, networking, standard Unix utilities, various
+ other languages, etc
+ Contact me for more info
+
+Entered: 10 Feb 92
+
+Ron Guilmette <rfg@ncd.com>
+396 Ano Nuevo Ave. #216
+Sunnyvale, CA 94086
+408-732-7839
+
+Services: Development & porting of GNU software development tools.
+
+GNU Contributions:
+ Invented, designed, and implemented the protoize and
+ unprotoize tools supplied with GCC2.
+
+ Designed and developed all code to support the generation
+ of Dwarf symbolic debugging information for System V Release
+ 4 in GCC2.
+
+ Finished GCC2 port to the Intel i860 RISC processor.
+
+ Now developing GDB code for System V Release 4 support of
+ ELF and Dwarf.
+
+Experience: 9+ years UNIX systems experience, all working on compilers
+ and related tools.
+
+ 3+ years working professionally on GCC, G++, and GDB under
+ contract to various firms including the Microelectronics
+ and Computer Technology Corporation (MCC), Data General (DG),
+ Network Computing Devices (NCD), and Intel Corp.
+
+Other qualifications:
+ Holder of both a Bachelor's and a Master's degree, both in
+ Computer Science.
+
+ Observer Member of ANSI X3J16 (C++ standardization) committee.
+
+ Former vice-chairman of UNIX International Programming
+ Languages Special Interest Group (UI/PLSIG).
+
+Rates: Variable depending upon contract duration. Call for quote.
+
+Updated: 9 Feb 92
+
+Johannes M. Heuft <ksh@pcs.com>
+Pfarrweg 2c
+D-8000 Munich 90
+Germany
+Telephone: Germany+89/681773
+
+Rate: min. DM 180.- ($ 120.-) per hour
+ interesting tasks for non-profit organisations may be free
+
+Supported Programs: gcc, gas, g++, gdb, binutils, gnuplot, ...; (not emacs)
+
+Experience: 10 years of operating system, network, and compiler
+ construction; also includes engineering management.
+
+Degrees: Dipl. Inform. (similar to MS CS)
+
+Updated: 11/9/91
+
+Sanjay Hiranandani <4393472@mcimail.com>
+16 Campus Plaza, Suite 180
+Vestal, NY 13850
+Work:607-729-7834 ext. 180
+Home:607-748-2709
+Fax:607-748-0243
+
+Rate: $40/hr. Phone questions for free are ok as far as my schedule will permit
+ Lower rates for students and certain non-profit organizations
+
+Can help with installation/customization/modification of most GNU software.
+
+Experience: Software Development, System Administration, and Consulting on
+ a variety of computing platforms.
+
+Updated: 11 Sept 91
+
+Hundred Acre Software Consultants <info@pooh.com>
+1280 Terminal Way, Suite 26 <uunet!heather!info>
+Reno NV 89502-3243
+(702) 329-9333
+
+Hundred Acre is a consulting group providing support and development
+services to organizations of all sizes. We support all kinds of publicly
+available software, not just GNU; write for the current list. We work on
+a "service contract" basis for support -- for a yearly fee, we provide email
+and toll free telephone support, and free updates and bug fixes. Certain
+support levels even have free on-site support. Development is charged on
+either an hourly or fixed bid basis.
+
+Consulting rates: $50 to $70 per hour, or fixed bid.
+Support contracts: Several levels, from $500 to $30000 per year.
+
+Updated: 2 Jul 91
+
+Jose A. Fernandez <jaf@inference.com>
+
+WORK: Inference Corporation HOME:
+ 550 N. Continental Blvd. 1025 Hillside Dr.
+ El Segundo, CA 90245 Chino Hills, CA 91709
+ (310) 322-0200 (714) 528-2523
+
+RATES:
+ $50-$200/hour plus expenses (or possibly free), depending on task.
+
+SERVICES:
+ GNU software: installation, troubleshooting, and customization.
+ X11 software: installation and troubleshooting.
+ SysAdmin: installation, configuration, and trouble-shooting.
+ NetAdmin: installation, configuration, and trouble-shooting.
+ Education: teaching how to fish opens the demand for fishing poles.
+ Advice: free over email.
+
+Entered: 10 Jul 92
+
+Scott D. Kalter <sdk@twinsun.com>
+970 Palm Ave. #218
+West Hollywood, CA 90069
+Home: (213)657-9174
+Work: (213)524-1805
+
+Emacs: e-lisp and C level customization/extension
+ training for general use and customization
+ user support, installation, troubleshooting
+Rates: approx. $50/hr, negotiable
+ Very willing to answer quick questions for free.
+ Prefer e-mail communication to telephone.
+
+Qualifications: BS Math/CS 1985: Carnegie Mellon University
+ MS CS 1988: UCLA
+ Extensive e-lisp level modification for rapid prototyping of
+ designs used in groupware research. Very familiar with all
+ levels of elisp programming. Taught Emacs use and
+ customization in universities and industry. Extensive
+ troubleshooting and user support experience.
+
+Updated:10/10/91
+
+Scott J. Kramer <sjk@aura.nbn.com>
+P.O. Box 3392
+San Rafael, CA 94912
++1 415-454-1295
+
+Emacs: Tutoring, installations/upgrades, Lisp customizations,
+ general troubleshooting/support. Prefer that work I do
+ becomes part of the official Free Software Foundation
+ distribution.
+
+Rate: Task- and time-dependent; non-monetary offers considered.
+
+Updated: 28Aug91
+
+Fen Labalme <fen@well.sf.ca.us>
+Broadcatch Technologies
+40 Carl St. #4
+San Francisco CA 94117
+(415) 731-1174
+
+Rates: Free phone consultation
+ Extended project or consultation: $70/hour plus expenses
+ Non-profits get lower rates or free; barter welcome!
+Emacs: Anything but specific termcap questions (general ones OK).
+ Includes elisp extensions & teaching beginning or advanced users.
+Experience: I've been "hacking Emacs" for just about 15 years now.
+
+Updated: 7/30/91
+
+David C Lawrence <tale@cs.rpi.edu>
+P.O. Box 61
+North Chatham, NY 12132-0061
+Home:518 766-9098 Work:518 851-2813
+
+Rates: $30 hour for projects less than 8 hours.
+ $20 hour for longer projects.
+ Course fees vary with level of subject being taught.
+ Short queries answered free of charge.
+ All rates negotiable.
+
+Support: Emacs (both lisp and C aspects), GCC, GAWK, sed, fileutils,
+ binutils, miscellaneous others. Definitely not G++.
+ Consulting via email or telephone, or possibly on-site.
+
+Updated: 11 Sept 91
+
+Greg Lehey
+LEMIS
+Schellnhausen 2
+W-6324 Feldatal
+Germany
+
+Phone: +49-6637-1488
+Fax: +49-6637-1489
+Mail <grog%lemis@Germany.EU.net>
+
+Services: Supply, porting, installation, consultation on all GNU
+products.
+
+Experience: 20 years OS and compiler experience, portations of most
+GNU products.
+
+Entered: 10 Jul 92
+
+Marty Leisner <leisner.henr801c@xerox.com>
+332 Shaftsbury Road
+Rochester, New York 14610
+Home:(716) 654-7931
+
+Experience: 10 years C/Unix, 7 years DOS.
+ Extensive experience with GNU binary tools, cross-compilers,
+ embedded/hosted systems.
+Degree : BS CS, Cornell University
+Rates: $75/hr
+
+Updated: 6 Jul 91
+
+Roland McGrath <roland@idr.org>
+545 Tech Sq rm 426
+Cambridge, MA 02139
+Work: (617) 253-8568
+
+Co-author of GNU Make (with Richard Stallman); maintainer of GNU Make.
+Author and maintainer of the GNU C Library and parts of the GNU Hurd.
+FSF employee summer 1989, fall 1990 to the present.
+
+Installation, maintenance, porting, enhancement of all GNU software.
+
+Fees negotiable. I can work anywhere in the Boston or SF Bay Area, or
+anywhere on the Internet.
+
+Updated: 10/18/92
+
+Lee McLoughlin <lmjm@doc.ic.ac.uk>
+ Department of Computing,
+ Imperial College,
+ 180 Queens Gate,
+ London
+ SW7 2BZ,
+ UK work: +44 71 589 5111 X 5085
+
+gcc, emacs: can support and port to new machines
+other: some experience with most gnu packages
+
+Ported emacs to two new platforms (WhiteChappel Worstations,
+HLH Orion). Worked on gcc port to Intergraph Clipper. Support
+various gnu packages as part of a teaching service.
+
+Rates: Quick phone questions are free.
+
+Degrees:.Sc(Hons) Computer Science
+
+Other: I'm a general workaholic and well versed in compilers, communications
+and most things related to Unix.
+
+Updated: 10.10.91
+
+T.S.Mohan <mohan%vidya@shakti.ernet.in>
+KBCS Group <mohan@vigyan.ernet.in>
+Supercomputer Education and Research Centre
+Indian Institute of Science
+Bangalore 560 012
+INDIA
+Telephone (01-91-812)-341811, -341805
+
+Rate: NIL. Availability for consultancy depends on
+ work load. High preference for academic institutions.
+Support: emacs, gdb, gcc, g++ and other small public domain utilities
+Experience: Installed and supported these + other gnu programs in our
+ centre for the past three years. General help to sister academic
+ departments and other academic institutions.
+Degrees: Master of Engineering in CS. Currently working towards a PhD
+ in Distributed computing and programming languages.
+
+Updated: 1 Dec 1991
+
+Mojave Systems <mojsys!support@uunet.uu.net>
+1254 Harvard Avenue
+Claremont, CA 91711
+714-621-7372
+
+Mojave Systems offers porting services, warranty protection, and
+software support for several GNU products. Porting services are
+provided for a fixed fee. Software support is provided for fixed
+annual fee.
+
+Mojave Systems is able to provide these services for a wide variety of
+hosts. We are currently porting GNU make and RCS to non-Unix hosts.
+
+Entered: 12 Dec 90
+
+Eric Raible <raible@nas.nasa.gov>
+Nasa Ames Research Center
+Mail Stop T045-1
+Moffett Field, CA, 94035
+(415) 604-4320 (W)
+
+Rates: $40 hour; email questions free.
+
+Gnu emacs C/lisp programming and porting. General
+unix/graphics/emacs hacking, especially on Silicon Graphics
+workstations.
+
+Degree: MIT 83 BS CS.
+
+Updated: 11 Sept 91
+
+Paul Reilly <reilly@dg-rtp.dg.com>
+721 Bennington Drive
+Raleigh, NC 27615
+Work: 919 248 6210
+Home: 919 847 7294
+
+Services: access, installation, porting, customizing and debugging
+Unix Free software: X11, GNU, TeX, etc.
+
+Rates: $150/hour
+
+Updated: Dec 1991
+
+Adam J. Richter <adam@soda.berkeley.edu> ...!ucbvax!soda!adam
+409 Evelyn Avenue, Apartment 312 (510) 528-3209
+Albany, CA 94706 fax: (510) 528-8508
+
+X windows server expert. Freeware (especially copylefted) projects
+preferred.
+
+Updated: 18 Nov 91
+
+Wolfgang S. Rupprecht <wolfgang@wsrcc.com>
+PO Box 6524 <uunet!wsrcc!wolfgang>
+Alexandria, VA 22306-0524 <wolfgang%wsrcc.com@uunet.uu.net>
+(703) 768-2640
+
+Emacs: Anything, (lisp, C, customization, porting, installing) I have
+written thousands of lines of GNU Emacs C and Lisp code. Original
+author of the floating point additions to appear in Emacs 19.
+
+Rates: $75/hr.
+
+Updated: 7/20/91
+
+John Sechrest
+Jasmic Systems Internet: <sechrest@jasmic.uucp>
+2140 SW 49th St. UUCP: <hp-pcd!orstcs!jasmic!sechrest>
+Corvallis, Oregon 97333
+
+Gnu software: Questions about gnu emacs general use, training and classes,
+ documentation, system set up and design.
+
+Experience: 11 years of Unix work. Heavy on System administration.
+ Teaching classes in Unix system administraion, Unix
+ Kernal Programming, Networking and Consulting services.
+ Currently working as the Support Coordinator for
+ Oregon State University (for 8 years).
+
+ Familiar with BSD systems mostly. Some SysVR4.
+ I have supported VAxes, HP's with HPUX, HP's with 4.3 BSD,
+ Sequent's, Next's and a few other misc. machines.
+
+Updated: 28 Oct 1991
+
+Steve Simmons <scs@lokkur.dexter.mi.us>
+Inland Sea
+9353 Hidden Lake Circle
+Dexter, MI 48130
+313-769-4086 (office1)
+313-426-2086 (office2)
+
+Rate: $75.00/hr for straight time until Jan 1, 1992. Rates will go up
+an undetermined amount at that time. Free advice for short questions
+by phone or email.
+
+Programs Supported: Any. Quality of support I can offer depends on
+the nature of the software; in particular I am *not* a compiler person.
+
+Experiance: 13 years in computing, 10 with UNIX and various derivatives.
+Specialist in systems administration. Lots of network admin.
+
+Degree: Bachelors from University of Michigan, 1980.
+
+Updated: 10 Oct 91
+
+Lynn Slater <lrs@indetech.com>
+42075 Lawrence Place
+Fremont Ca 94538
+Office (415) 438-2048; Home (415) 793-1864; Fax (415) 438-2034
+
+Programs: Gnu Emacs Ada Mode, Gnu Emacs Empire Tool, Emacs,
+ g++ and gnumake (limited support only).
+
+Experiance:
+ Gnu Emacs Ada Mode -- Co-author, principle integrator
+ Gnu Emacs Empire Tool -- Originator, co-author, principle distributor
+ Emacs -- Almost all parts. Authored super-apropos, headers, first GDB
+ interface, fancy-lisp, enhanced scribe mode,and lots of small stuff
+ g++ -- Have maintained, modified, and used G++ on 300+ user commercial
+ OLTP software.
+ gnumake -- Have bug fixed and extended.
+
+ Have single makefile that can merge in local changes and build the
+ following systems in a consistent manner in multiple releases on multiple
+ machines:
+ asm, bison, gcc, g++, emacs, rcs, gdb, libg++, att c++ libs, gnumake,
+ diff, tex2iroff
+ The makefile and related techniques are a bit hard to explain, but they
+ enable use and local changes in a broad spectrum of FSF code on many
+ platforms without having to remember all the individual make procedures.
+
+Rate: Free for good cause or short stuff as there is time.
+ Am most likely to help in areas in which I have had problems or expect to
+ have problems.
+
+Updated: 10 Oct 91
+
+Small Business Systems, Inc. <postmaster@anomaly.sbs.com>
+Box 17220, Route 104
+Esmond, RI 02917
+401.273.4669
+
+Rate: Varies depending on complexity of task.
+ Hourly and fixed-rate contracts are available.
+Programs Supported: All
+
+Updated: 11 Sept 91
+
+Randall D. Smith <randy@ai.mit.edu>
+20 Watson Street
+Cambridge, MA 02139, USA
++1 (617) 983-0276
+
+Will work on most GNU software.
+Installation, handholding, trouble shooting, extensions, teaching,
+GCC, GDB, GNU-EMACS, and other ports.
+
+Rates: Upward from $50.00/hour depending on my expertise in the area of the
+job. GDB consulting at $80.00/hour.
+
+Experience: 4 years of intensive experience with Unix and C including
+system hacking and modification. Experience in porting GNU-EMACS (to
+SGI Iris 4D) and GCC (to use Sun FPA chip). Experience working
+full-time for the GNU project on other GNU programs (June 1988 -
+August 1989). Primary maintainer of GDB and the GNU loader for that
+period. Resume available on request.
+
+Entered: 10 Feb 92
+
+Richard M. Stallman <rms@prep.ai.mit.edu>
+UUCP: {mit-eddie,ucbvax,uunet,harvard,uw-beaver}!ai.mit.edu!rms
+545 Tech Sq, Rm 430
+Cambridge, MA 02139
+
+Emacs: anything whatever
+Is anyone interested in courses in using or extending GNU Emacs?
+
+Original inventor of Emacs and main author of GNU Emacs and GCC.
+
+Rates: $6/min or $250/hr.
+
+Entered: 5/24/90
+
+Jonathan Stone <jonathan@isor.vuw.ac.nz>
+c/o- Institute of Statistics and Operations Research
+Victoria University of Wellington
+P.O Box 600
+Wellington
+New Zealand
+Work: +64 4 715-315 Fax: +64 4 712-070
+
+Rate: hourly rate: NZ $ 150/hr. Quick phone questions are free.
+ Reduced rates available for for non-profit/educational insts
+ and daily rate work. Fixed-price contracts also considered.
+
+Programs: GNU Emacs, GCC, GDB, GNU binutils,
+ Ghostscript, MIT X11
+ I am the author of the Pyramid ports of gcc and gdb.
+
+Experiance: Five years administration of Unix systems and GNU tools
+ in University environments, and support of Unix administrators
+ and GNU tools as an external contractor to New Zealand Government
+ departments.
+
+Degrees: M.Sc (Distinction) for a thesis involving work done on GCC.
+
+Updated: 28 Aug 91
+
+Bob Sutterfield <bob@morningstar.com>
+
+work: home:
+Morning Star Technologies
+1760 Zollinger Road 3542 Norwood Street
+Columbus, Ohio 43221 USA Columbus, Ohio 43224-3424 USA
+(614)451-1883 (614)267-7611
+
+Rates: $50/hr (negotiable) plus travel expenses
+ Gratis to Christian missionaries and mission agencies
+
+Services: Installation, troubleshooting, and mild customization of
+ most GNU production and beta-test software; tutorials, training,
+ and handholding; general UNIX system and network consulting.
+
+Entered: 2/16/92
+
+Kayvan Sylvan <kayvan@satyr.Sylvan.COM>
+Sylvan Associates
+879 Lewiston Drive
+San Jose, CA 95136
+Phone: 408-978-1407
+
+I will help you port, install and customize GNU Emacs, GCC, G++,
+bison, and other GNU tools on almost any architechture and operating
+system. Questions answered. GNU C and lisp hacking available. I will
+also do ongoing support and periodic upgrades if you get on my GNU
+software subscription list.
+
+Rates: $60-$100/hour, depending on type of work. Substantial discounts
+for long-term contracts and also for educational or non-profit
+institutions.
+
+Experience: Many different Unix systems (2.9BSD to 4.3BSD, SVR3 and
+SVR4, Xenix). Systems programming and system administration on all
+brands of Unix. Kernel hacking experience. Lots of porting experience.
+I can port anything to anything (within reason).
+
+Updated: 10 Jul 92
+
+Leonard H. Tower Jr. <tower@prep.ai.mit.edu>
+36 Porter Street
+Somerville, MA 02143, USA
++1 (617) 623-7739
+
+Will work on most GNU software.
+Installation, handholding, trouble shooting, extensions, teaching.
+
+Rates: 100.00/hour + travel expenses. Negotiable for non-profits.
+
+Experience: Have hacked on over a dozen architectures in many languages. Have
+system mothered several varieties of Unixes. Assisted rms with the front end
+of gcc and it's back-end support. Resume available on request.
+
+Entered: 12 Feb 92
+
+Watchmaker Computing <support@watch.com>
+P.O.Box 163, Kendall Square
+Cambridge, MA 02142
+email: support@watch.com
+
+Emacs: We'll do GNUEmacs support, porting, bug fixing, and customizing.
+We also have specific expertise in:
+ packages: GCC, G++, X11, Xt, InterViews, PERL, TeX, Epoch
+ languages: C, C++, Lisp, most others; we learn quickly!
+Extensive experience coding for portability under UNIX.
+Typical rates $35-$150/hour; will telecommute (Internet or phone)
+
+Entered: 1/16/91
+
+Chris Welty <weltyc@cs.rpi.edu>
+RPI Computer Science Dept
+Troy, NY 12180
+518-276-2816 (W)
+
+EMail correspondance preferred.
+Rates vary depending on need, barter often accepted.
+
+Programs: emacs, especially emacs lisp.
+Lots of experience in various areas.
+BS, MS from RPI. Currently working on PhD.
+
+Updated: 10/10/91
+
+Pace Willisson <pace@blitz.com>
+Blitz Product Development Corporation <uunet!blitz!pace>
+4 Spruce Road
+Medway, MA 02053, USA
+Work: (508) 533-6430
+
+Rates: $80.00/hour
+
+Will work on any GNU software.
+
+Experience: 12 years working with C, Unix and Lisp Machines including
+compilation systems, networks, device drivers, demand paging systems,
+boot programs and window systems. Ported GDB to 80386. Designed COFF
+encapsulation scheme to run GNU linker output on System 5 kernels.
+Author of Unix "ispell".
+
+Degree: BS in Computer Science from MIT
+
+Updated: 7/31/91
+
+Patrick Wood
+Pipeline Associates, Inc.
+2740 Route 10 West
+Morris Plains, NJ 07950
+
+Rate: Free
+Support For: gcc, binutils, gnulib, using gcc for cross compiling
+Experiance: used gcc for cross compiling for over 2 years; used
+ gcc for three years; installed and support gcc on several
+ BSD and System V UNIX systems; wrote peephole optimizer for
+ gcc on 68K, wrote portable replacement for FP routines in
+ gnulib.c. Modified gcc and binutils to work in byte-swapped
+ environments.
+Other: email consulting only <pipeline!phw@motown.com>,
+ uunet!motown!pipeline!phw,sun!pipeline!phw, amdcad!pipeline!phw
+
+Updated: 18 Sept 91
+
+xprt Computer Consulting, Inc. <jody@shell.com>
+17200 El Camino Real Suite 110 T
+Houston, TX 77058
+(713) 480 UNIX
+(713) 486 8575 (Fax)
+
+Programs Supported:
+X11, TeX, and all of GNU.
+
+Experience:
+We have supported and maintained all of GNU, X11 and TeX for over four
+years for a major oil company's research division on several different
+Unix platforms.
+
+Rates: $150/hour
+
+Entered: 10 Jul 92
+
+Name: david d [zoo] zuhn <zuhn@cs.umn.edu>
+Company: armadillo zoo software
+Fees: $50/hour, discounts for educational institutions and non-profits
+
+ GNU and X11 installation and maintainance on SGI Iris, Sun [68k &
+ SPARC], and Sequent machines. Additional machines a possibility.
+ Any GNU software installed. Most supported.
+
+Updated: 7/11/92
+
+** Please keep this file alphabetical **
diff --git a/etc/SUN-SUPPORT b/etc/SUN-SUPPORT
new file mode 100644
index 00000000000..0afcc1cedf6
--- /dev/null
+++ b/etc/SUN-SUPPORT
@@ -0,0 +1,318 @@
+NOTE: the Free Software Foundation agreed to put this file, and the
+programs it describes, into the Emacs distribution ONLY on the
+condition that we would not lift a finger to maintain them! We are
+willing to *pass along* support for Sun windows, but we are not
+willing to let it distract us from what we are trying to do. If you
+have complaints or suggestions about Sun windows support, send them to
+peck@sun.com, who is the maintainer.
+
+
+The interface between GNU Emacs and Sun windows consists of the program
+etc/emacstool, the Lisp programs lisp/sun-*.el and lisp/term/sun.el,
+and the C source file src/sunfns.c. It is documented with a man page,
+etc/emacstool.1.
+
+To enable use of these files and programs, define the configuration
+switch HAVE_SUN_WINDOWS in src/config.h before compiling Emacs.
+The definition of HAVE_SUN_WINDOWS must precede the #include m-sun3.h
+or #include m-sun4.h.
+If you must change PURESIZE, do so after the #include m-sun3.h
+
+This software is based on SunView for Sun UNIX 4.2 Release 3.2,
+and will not work "as is" on previous releases, eg 3.0 or 3.1.
+
+Using Emacstool with GNU Emacs:
+
+ The GNU Emacs files lisp/term/sun.el, lisp/sun-mouse.el,
+lisp/sun-fns.el, and src/sunfns.c provide emacs support for the
+Emacstool and function keys. If your terminal type is SUN (that is,
+if your environment variable TERM is set to SUN), then Emacs will
+automatically load the file lisp/term/sun.el. This, in turn, will
+ensure that sun-mouse.el is autoloaded when any mouse events are
+detected. It is suggested that sun-mouse and sun-fns be
+included in your site-init.el file, so that they will always be loaded
+when running on a Sun workstation. [Increase PURESIZE to 154000].
+
+ Support for the Sun function keys requires disconnecting the standard
+Emacs command Meta-[. Therefore, the function keys are supported only
+if you do (setq sun-esc-bracket t) in your .emacs file.
+
+ The file src/sunfns.c defines several useful functions for emacs on
+the Sun. Among these are procedures to pop-up SunView menus, put and
+get from the SunView selection [STUFF] buffer, and a procedure for
+changing the cursor icon. If you want to define cursor icons, try
+using the functions in lisp/sun-cursors.el.
+
+ The file lisp/sun-mouse.el includes a mass of software for defining
+bindings for mouse events. Any function can be called or any form
+evaluated as a result of a mouse event. If you want a pop-up menu,
+your function can call sun-menu-evaluate. This will bring up a
+SunView walking menu of your choice.
+
+ Use the macro (defmenu menu-name &rest menu-items) to define menu
+objects. Each menu item is a cons of ("string" . VALUE), VALUE is
+evaluated when the string item is picked. If VALUE is a menu, then a
+pullright item is created.
+
+ This version also includes support for copying to and from the
+sun-windows "stuff" selection. The keyboard bindings defined in
+lisp/sun-fns.el let you move the current region to the "STUFF"
+selection and vice versa. Just set point with the left button, set
+mark with the middle button, (the region is automatically copied to
+"STUFF") then switch to a shelltool, and "Stuff" will work. Going the
+other way, the main right button menu contains a "Stuff Selection"
+command that works just like in shelltool. [The Get and Put function
+keys are also assigned to these functions, so you don't need the mouse
+or even emacstool to make this work.]
+
+ Until someone write code to read the textsw "Selection Shelf", it is
+not possible to copy directly from a textsw to emacs, you must go through
+the textsw "STUFF" selection.
+
+ The Scroll-bar region is not a SunView scrollbar. It really should
+be called the "Right-Margin" region. The scroll bar region is basically
+the rightmost five columns (see documentation on variable scrollbar-width).
+Mouse hits in this region can have special bindings, currently those binding
+effect scrolling of the window, and so are refered to as the "Scroll-bar"
+region.
+
+ For information on what mouse bindings are in effect, use the command
+M-x Describe-mouse-bindings, or the quick pop-up menu item "Mouse-Help".
+
+
+GNU Emacs EXAMPLES:
+ See definitions in lisp/sun-fns.el for examples.
+
+ You can redefine the cursor that is displayed in the emacs window.
+On initialization, it is set to a right arrow. See lisp/sun-cursors.el
+for additional cursors, how to define them, how to edit them.
+
+BUGS:
+ It takes a few milliseconds to create a menu before it pops up.
+Someone who understands the GNU Garbage Collector might see if it
+is possible for defmenu to create a SunView menu struct that does
+not get destroyed by Garbage Collection.
+
+ An outline of the files used to support Sun Windows and the mouse.
+
+etc/SUN-SUPPORT.
+ This document.
+
+etc/emacstool.1:
+ Added: an nroff'able man page for emacstool.
+
+etc/emacstool.c:
+ Encodes all the function keys internally, and passes non-window
+system arguments to emacs.
+
+etc/emacs.icon:
+ The "Kitchen Sink" GNU Emacs icon.
+
+src/sunfns.c:
+ This contains the auxilary functions that allow elisp code to interact
+with the sunwindows, selection, and menu functions.
+
+lisp/sun-mouse.el:
+ Defines the lisp function which is called when a mouse hit is found
+in the input queue. This handler decodes the mouse hit via a keymap-like
+structure sensitive to a particular window and where in the window the
+hit occured (text-region, right-margin, mode-line). Three variables
+are bound (*mouse-window* *mouse-x* *mouse-y*) and the selected function
+is called.
+ See documentation on "define-mouse" or look at lisp/sun-fns.el
+to see how this is done.
+ Defines two functions to pass between region and sun-selection
+ Defines functions for interfacing with the Menu.
+During menu evaluation, the variables *menu-window* *menu-x* *menu-y* are bound.
+
+lisp/sun-fns.el
+ The definition of the default menu and mouse function bindings.
+
+lisp/sun-cursors.el
+ Defines a number of alternate cursors, and an editor for them.
+ The editor is also a demonstration of mouse/menu utilization.
+
+lisp/term/sun.el
+ Sets up the keymap to make the sun function keys do useful things.
+Also includes the setup/initialization code for running under emacstool,
+which makes "\C-Z" just close the emacstool window (-WI emacs.icon).
+
+ Jeff Peck, Sun Microsystems, Inc <peck@sun.com>
+
+
+Subject: Making multi-line scrolling really work:
+
+In your .defaults file, include the line:
+/Tty/Retained "Yes"
+That way, the terminal emulator can do text moves using bitblt,
+instead of repaint.
+
+If that's not enough for you, then tell unix and emacs that
+the sun terminal supports multi-line and multi-character insert/delete.
+Add this patch to your /etc/termcap file:
+
+*** /etc/termcap.~1~ Mon Sep 15 12:34:23 1986
+--- /etc/termcap Mon Feb 9 17:34:08 1987
+***************
+*** 32,39 ****
+--- 32,40 ----
+ Mu|sun|Sun Microsystems Workstation console:\
+ :am:bs:km:mi:ms:pt:li#34:co#80:cl=^L:cm=\E[%i%d;%dH:\
+ :ce=\E[K:cd=\E[J:so=\E[7m:se=\E[m:rs=\E[s:\
+ :al=\E[L:dl=\E[M:im=:ei=:ic=\E[@:dc=\E[P:\
++ :AL=\E[%dL:DL=\E[%dM:IC=\E[%d@:DC=\E[%dP:\
+ :up=\E[A:nd=\E[C:ku=\E[A:kd=\E[B:kr=\E[C:kl=\E[D:\
+ :k1=\E[224z:k2=\E[225z:k3=\E[226z:k4=\E[227z:k5=\E[228z:\
+ :k6=\E[229z:k7=\E[230z:k8=\E[231z:k9=\E[232z:
+ M-|sun-nic|sune|Sun Microsystems Workstation console without insert character:\
+
+
+If you don't have the program "patch", just add the line:
+ :AL=\E[%dL:DL=\E[%dM:IC=\E[%d@:DC=\E[%dP:\
+
+casetek@crvax.sri.com says:
+
+Those of you using GNU Emacs on Sun workstations under
+3.2 may be interested in reducing memory utilization in
+the emacstool via the Sun toolmerge facility. The technique
+is described in the Release 3.2 Manual starting on page
+71. The following is a summary of how it would apply
+to merging emacstool into the basetools.
+
+1) Change the main procedure declaration in emacstool.c to:
+
+ #ifdef SUN_TOOLMERGE
+ emacstool_main (argc, argv);
+ #else
+ main (argc, argv)
+ #endif
+
+ This will allow creation of either standard or toolmerge
+ versions.
+
+2) Copy emacstool.o into directory /usr/src/sun/suntool.
+3) make CFLAGS="-g -DSUN_TOOLMERGE" emacstool.o
+4) Add the following line to basetools.h
+
+ "emacstool",emacstool_main,
+
+5) Add the following line to toolmerge.c.
+
+ extern emacstool_main();
+
+6) make basetools MOREOBJS="emacstool.o"
+7) make install_bins
+
+To invoke the toolmerged version, you must exit suntools and
+re-start it. Make sure that /usr/bin occurs before the directory
+in which you installed the standard (non-toolmerged) version.
+
+
+Subject: Moving selections between OW and Emacstool/xvetool
+Date: Wed, 26 Jun 91 18:58:24 PDT
+From: Jeff Peck <peck>
+
+The short answer is that we can Cut and Paste between Emacstool
+and TTYSW (shelltool) and we can Paste between Emacstool and TEXTSW(cmdtool)
+and somewhat more slowly move from TEXTSW to Emacstool.
+
+**** This interaction with the TTYSW selection is a HACK! ****
+
+At end of this message is the code that should be in your sun-mouse.el or .emacs
+
+Here's the restrictions on using it:
+
+1. from Shelltool to Emacstool:
+ select text in shelltool and hit COPY.
+ move to Emacstool, hit PASTE. (simple, eh?)
+
+For any other movement, you must remember this:
+ "The window system must believe that a shelltool has the current selection."
+ If you do that, then this will all work painlessly.
+ [that will also explain why you can not make a selection in a cmdtool
+ and then directly PASTE it into Emacstool]
+
+2. from Emacstool to Shelltool
+ ensure that a shelltool has the selection: (select something and hit COPY)
+ in emacstool select a region and hit COPY
+ in shelltool hit PASTE. (not too bad, yet)
+
+3. from Emacstool to Cmdtool
+ ensure that a shelltool has the selection:
+ (in a *shelltool* select something and hit COPY)
+ in emacstool select a region and hit COPY
+ in shelltool hit PASTE. (ok, its getting crufty)
+
+4. from Cmdtool to Emacstool
+ select in Cmdtool, hit COPY
+ in a shelltool, % cat > /dev/null
+ then hit PASTE
+ Select the text again, from the shelltool this time. hit COPY
+ in emacstool, hit PASTE
+
+4a. from Cmdtool (or shelltool) to Emacstool
+ the function "sunview-yank-any-selection" should be bound to Meta-PASTE
+ If so, then just:
+ select in Cmdtool
+ in emacstool, hit Meta-PASTE
+
+ This uses the function "sunview-yank-current-selection"
+ which relies one the (supported) utility "get_selection"
+ As such, it is *not* a hack, but it *IS* SLOW (or slower)
+
+
+If you know that a shelltool *still* has the selection
+(note: nothing you do with Emacstool or the PASTE key will affect that)
+then the "ensure..." line is a NO-OP.
+
+Note that using COPY in emacstool will change the *value* of the selection
+behind the window systems back:
+ the holder of the selection doesn't know of this,
+ the window system doesn't know of this,
+ and the highlighted text *WILL NOT CHANGE*
+
+Turns out the selection value is written into a /tmp/ttyselection file
+and emacs just rewrites that file, clever, eh?
+
+
+Your version of sun-mouse.el should include these functions
+ (or put them into your .emacs)
+
+
+;;; define the selection file used by this emacs
+;;; if not local machine, then automounter must find /net/<host>/tmp
+(defconst owselectionfile
+ (let ((display (getenv "DISPLAY")))
+ (if (null display)
+ nil ; no DISPLAY variable -- return nil
+ (let ((colon_at (string-match ":" display)))
+ (if (null colon_at)
+ nil ; no colon in environment variable -- return nil
+ (if (zerop colon_at)
+ "/tmp/ttyselection" ; colon is first character
+ (concat "/net/" (substring display 0 colon_at) "/tmp/ttyselection")
+ )))))
+ )
+
+(defun xv-yank-selection ()
+ "Set mark and yank the contents of the current Xview selection
+into the current buffer at point. The STUFF selection contains the currently
+or previously highlighted text from a TTYSW."
+ (interactive "*")
+ (insert-file owselectionfile)
+ (exchange-point-and-mark)
+ )
+
+(defun xv-select-region (beg end)
+ "Set the TTYSW selection to the region in the current buffer."
+ (interactive "r")
+ (write-region beg end owselectionfile nil 'noprint)
+ )
+
+You can then bind these to Copy and Paste in your .emacs
+
+(setq suntool-map-hooks '( ; not your usual hook list
+ (define-key suntool-map "fl" 'xv-select-region) ; L6 Copy
+ (define-key suntool-map "hl" 'xv-yank-selection) ; L8 Paste
+ )
+)
diff --git a/etc/SUNBUG b/etc/SUNBUG
new file mode 100644
index 00000000000..da44eba6ec8
--- /dev/null
+++ b/etc/SUNBUG
@@ -0,0 +1,41 @@
+From: coho!daveg (Dave Gagne)
+Subject: Re: Problems with building emacs on SunOS 4.0 (EXPORT)
+Summary: SunOS 4.0_Export "cc -Bstatic" don't work.
+Organization: UBC Dept. of Electrical Engineering, Vancouver, Canada
+
+> Has anyone else seen similar problems?
+
+Yes indeed. Anyone who does not live in the jolly US of A.
+
+ What you are encountering is a screw-up in SunOS 4.0_Export. This
+problem only occurs in the "EXPORT" version of SunOS 4.0: ie the
+software which Sun ships outside of the USA. The problem has something
+to do with Sun not wanting to ship their DES chips outside of the good
+'ole USA. What we poor foreigners get instead is some buggered up
+software.
+
+ What all this means is that "cc -Bstatic ..." WILL NOT WORK ON SUNOS
+4.0 EXPORT without a little help from "ar". The static C-library is
+/lib/libc.a, and this is where the problem occurs. There are a bunch of
+.o files in there relating to DES stuff (des_crypt.o, des_soft.o, _crypt.o,
+etc). All of them will case cc -Bstatic to die as you found with the
+errors:
+
+> _edata: ld: user attempt to redefine loader-defined symbol
+> _end: user attempt to redefine loader-defined symbol
+> _etext: /lib/libc.a(des_crypt.o): multiply defined
+
+ In order to make cc -Bstatic useful, you must remove all the
+brain-damaged .o files from /lib/libc.a. To do this use
+
+ ar d /lib/libc.a des_crypt.o des_soft.o _crypt.o ....
+
+(Make a backup of /lib/libc.a first, you may decide you need the "real"
+thing someday). Note that there are a bunch of these files, I can't
+remember all of them. You will find them quick enough by trying to
+compile ANY C program, even one which does NOTHING.
+
+ After you have done this, Emacs should compile OK. I was able to get
+both the "normal" text version and the X-windows (X11R2) version to
+compile OK. It seems to me that the Suntools version may not have worked,
+but I may just be halucinating.
diff --git a/etc/TERMS b/etc/TERMS
new file mode 100644
index 00000000000..0245fe2c2db
--- /dev/null
+++ b/etc/TERMS
@@ -0,0 +1,229 @@
+This file describes what you must or might want to do to termcap entries
+to make terminals work properly and efficiently with Emacs. Information
+on likely problems with specific types of terminals appears at the end
+of the file.
+
+*** What you want in a terminal ***
+
+Vital
+1. Easy to compute suitable padding for.
+2. Never ever sends ^S/^Q unless you type them, at least in one mode.
+
+Nice for speed
+1. Supports insert/delete of multiple lines in one command.
+2. Same for multiple characters, though doing them one by
+one is usually fast enough except on emulators running on
+machines with bitmap screens.
+
+Nice for usability
+1. Considerably more than 24 lines.
+2. Meta key (shift-like key that controls the 0200 bit
+in every character you type).
+
+*** New termcap strings ***
+
+Emacs supports certain termcap strings that are not described in the
+4.2 manual but appear to be standard in system V. The one exception
+is `cS', which I invented.
+
+`AL' insert several lines. Takes one parameter, the number of
+ lines to be inserted. You specify how to send this parameter
+ using a %-construct, just like the cursor positions in the `cm'
+ string.
+
+`DL' delete several lines. One parameter.
+
+`IC' insert several characters. One parameter.
+
+`DC' delete several characters. One parameter.
+
+`rp' repeat a character. Takes two parameters, the character
+ to be repeated and the number of times to repeat it.
+ Most likely you will use `%.' for sending the character
+ to be repeated. Emacs interprets a padding spec with a *
+ as giving the amount of padding per repetition.
+
+ WARNING: Many terminals have a command to repeat the
+ *last character output* N times. This means that the character
+ will appear N+1 times in a row when the command argument is N.
+ However, the `rp' string's parameter is the total number of
+ times wanted, not one less. Therefore, such repeat commands
+ may be used in an `rp' string only if you use Emacs's special
+ termcap operator `%a-c\001' to subtract 1 from the repeat count
+ before substituting it into the string. It is probably safe
+ to use this even though the Unix termcap does not accept it
+ because programs other than Emacs probably won't look for `rp'
+ anyway.
+
+`cs' set scroll region. Takes two parameters, the vertical
+ positions of the first line to include in the scroll region
+ and the last line to include in the scroll region.
+ Both parameters are origin-zero. The effect of this
+ should be to cause a following insert-line or delete-line
+ not to move lines below the bottom of the scroll region.
+
+ This is not the same convention that Emacs version 16 used.
+ That is because I was led astray by unclear documentation
+ of the meaning of %i in termcap strings. Since the termcap
+ documentation for `cs' is also unclear, I had to deduce the
+ correct parameter conventions from what would make the VT-100's
+ `cs' string work properly. From an incorrect assumption about
+ %i, I reached an incorrect conclusion about `cs', but the result
+ worked correctly on the VT100 and ANSII terminals. In Emacs
+ version 17, both `cs' and %i work correctly.
+
+ The version 16 convention was to pass, for the second parameter,
+ the line number of the first line beyond the end of the
+ scroll region.
+
+`cS' set scroll region. Differs from `cs' in taking parameters
+ differently. There are four parameters:
+ 1. Total number of lines on the screen.
+ 2. Number of lines above desired scroll region.
+ 3. Number of lines below (outside of) desired scroll region.
+ 4. Total number of lines on the screen, like #1.
+ This is because an Ambassador needs the parameters like this.
+
+`cr', `do', `le'
+ Emacs will not attempt to use ^M, ^J or ^H for cursor motion
+ unless these capabilities are present and say to use those
+ characters.
+
+`km' Says the terminal has a Meta key.
+
+Defining these strings is important for getting maximum performance
+from your terminal.
+
+Make sure that the `ti' string sets all modes needed for editing
+in Emacs. For example, if your terminal has a mode that controls
+wrap at the end of the line, you must decide whether to specify
+the `am' flag in the termcap entry; whichever you decide, the `ti'
+string should contain commands to set the mode that way.
+(Emacs also sends the `vs' string after the `ti' string.
+You can put the mode-setting commands in either one of them.)
+
+*** Specific Terminal Types ***
+
+Watch out for termcap entries for Ann Arbor Ambassadors that
+give too little padding for clear-screen. 7.2 msec per line is right.
+These are the strings whose padding you probably should change:
+ :al=1*\E[L:dl=1*\E[M:cd=7.2*\E[J:cl=7.2*\E[H\E[J:
+I have sometimes seen `\E[2J' at the front of the `ti' string;
+this is a clear-screen, very slow, and it can cause you to get
+Control-s sent by the terminal at startup. I recommend removing
+the `\E[2J' from the `ti' string.
+The `ti' or `vs' strings also usually need stuff added to them, such as
+ \E[>33;52;54h\E[>30;37;38;39l
+You might want to add the following to the `te' or `ve' strings:
+ \E[>52l\E[>37h
+The following additional capabilities will improve performance:
+ :AL=1*\E[%dL:DL=1*\E[%dM:IC=4\E[%d@:DC=4\E[%dP:rp=1*%.\E[%a-c\001%db:
+If you find that the Meta key does not work, make sure that
+ :km:
+is present in the termcap entry.
+
+Watch out for termcap entries for VT100's that fail to specify
+the `sf' string, or that omit the padding needed for the `sf' and `sr'
+strings (2msec per line affected). What you need is
+ :sf=2*^J:sr=2*\EM:cs=\E[%i%d;%dr:
+
+The Concept-100 and Concept-108 have many modes that `ti' strings
+often fail to initialize. If you have problems on one of these
+terminals, that is probably the place to fix them. These terminals
+can support an `rp' string.
+
+Watch out on HP terminals for problems with standout disappearing on
+part of the mode line. These problems are due to the absence of
+:sg#0: which some HP terminals need.
+
+The vi55 is said to require `ip=2'.
+
+The Sun console should have these capabilities for good performance.
+ :AL=\E[%dL:DL=\E[%dM:IC=\E[%d@:DC=\E[%dP:
+
+The vt220 needs to be set to vt220 mode, 7 bit, space parity
+in order to work fully with TERM=vt220.
+
+If you are using a LAT terminal concentrator, you need to issue these
+commands to turn off flow control:
+
+ set port flow control disable
+ define port flow control disable
+
+On System V, in the terminfo database, various terminals may have
+the `xt' flag that should not have it. `xt' should be present only
+for the Teleray 1061 or equivalent terminal.
+
+In particular, System V for the 386 often has `xt' for terminal type
+AT386 or AT386-M, which is used for the console. You should delete
+this flag. Here is how:
+
+You can get a copy of the terminfo "source" for at386 using the
+command: `infocmp at386 >at386.tic'. Edit the file at386.tic and remove
+the `xt' flag. Then compile the new entry with: `tic at386.tic'.
+
+It is also reported that these terminal types sometimes have the wrong
+reverse-scroll string. It should be \E[T, but sometimes is given as \E[S.
+
+Here is what watserv1!maytag!focsys!larry recommends for these terminals:
+
+# This copy of the terminfo description has been fixed.
+# The suggestions came from a number of usenet postings.
+#
+# Intel AT/386 for color card with monochrome display
+#
+AT386-M|at386-m|386AT-M|386at-m|at/386 console,
+ am, bw, eo, xon,
+ cols#80, lines#25,
+ acsc=``a1fxgqh0jYk?lZm@nEooppqDrrsstCu4vAwBx3yyzz{{||}}~~,
+ bel=^G, blink=\E[5m, bold=\E[1m, cbt=\E[Z,
+ clear=\E[2J\E[H,
+ cr=\r, cub=\E[%p1%dD, cub1=\E[D, cud=\E[%p1%dB,
+ cud1=\E[B, cuf=\E[%p1%dC, cuf1=\E[C,
+ cup=\E[%i%p1%02d;%p2%02dH, cuu=\E[%p1%dA, cuu1=\E[A,
+ dch=\E[%p1%dP, dch1=\E[P, dl=\E[%p1%dM, dl1=\E[1M,
+ ech=\E[%p1%dX,ed=\E[J, el=\E[K, el1=\E[1K\E[X, flash=^G, home=\E[H,
+ hpa=\E[%i%p1%dG, ich=\E[%p1%d@, ich1=\E[1@, il=\E[%p1%dL, il1=\E[1L,
+ ind=\E[S, indn=\E[%p1%dS, invis=\E[9m,
+ is2=\E[0;10;38m, kbs=\b, kcbt=^], kclr=\E[2J,
+ kcub1=\E[D, kcud1=\E[B, kcuf1=\E[C, kcuu1=\E[A,
+ kdch1=\E[P, kend=\E[Y, kf1=\EOP, kf10=\EOY, kf11=\EOZ,
+ kf12=\EOA, kf2=\EOQ, kf3=\EOR, kf4=\EOS, kf5=\EOT,
+ kf6=\EOU, kf7=\EOV, kf8=\EOW, kf9=\EOX, khome=\E[H,
+ kich1=\E[@, knp=\E[U, kpp=\E[V, krmir=\E0, rev=\E[7m, ri=\E[T,
+ rin=\E[%p1%dT, rmacs=\E[10m, rmso=\E[m, rmul=\E[m,
+ sgr=\E[10m\E[0%?%p1%p3%|%t;7%;%?%p2%t;4%;%?%p4%t;5%;%?%p6%t;1%;%?%p9%t;12%;%?%p7%t;9%;m,
+ sgr0=\E[0;10m, smacs=\E[12m, smso=\E[7m, smul=\E[4m,
+
+#
+# AT&T 386 color console
+#
+AT386|at386|386AT|386at|at/386 console,
+ colors#8, ncv#3, pairs#64,
+ is2=\E[0;10;39m,
+ op=\E[0m,
+ setb=\E[%?%p1%{0}%=%t40m
+ %e%p1%{1}%=%t44m
+ %e%p1%{2}%=%t42m
+ %e%p1%{3}%=%t46m
+ %e%p1%{4}%=%t41m
+ %e%p1%{5}%=%t45m
+ %e%p1%{6}%=%t43m
+ %e%p1%{7}%=%t47m%;,
+ setf=\E[%?%p1%{0}%=%t30m
+ %e%p1%{1}%=%t34m
+ %e%p1%{2}%=%t32m
+ %e%p1%{3}%=%t36m
+ %e%p1%{4}%=%t31m
+ %e%p1%{5}%=%t35m
+ %e%p1%{6}%=%t33m
+ %e%p1%{6}%=%t33m
+ %e%p1%{7}%=%t37m%;,
+ use=at386-m,
+#
+# Color console version that supports underline but maps blue
+# foreground color to cyan.
+#
+AT386-UL|at386-ul|386AT-UL|386at-ul|at/386 console,
+ is2=\E[0;10;38m,
+ use=at386,
diff --git a/etc/TO-DO b/etc/TO-DO
new file mode 100644
index 00000000000..cc5b398eeca
--- /dev/null
+++ b/etc/TO-DO
@@ -0,0 +1,26 @@
+Things useful to do for GNU Emacs:
+
+* Primitive for random access insertion of part of a file.
+
+* Making I/O streams for files, so that read and prin1 can
+ be used on files directly. The I/O stream itself would
+ serve as a function to read or write one character.
+
+* If a file you can't write is in a directory you can write,
+ make sure it works to modify and save this file.
+
+* Make dired's commands handle correctly the case where
+ ls has listed several subdirectories' contents.
+ It needs to be able to tell which directory each file
+ is really in, by searching backward for the line
+ which identifies the start of a directory.
+
+* Add more dired commands, such as sorting (use the
+ sort utility through call-process-region).
+
+* Make display.c record inverse-video-ness on
+ a character by character basis. Then make non-full-screen-width
+ mode lines inverse video, and display the marked location in
+ inverse video.
+
+* VMS code to list a file directory. Make dired work.
diff --git a/etc/TUTORIAL b/etc/TUTORIAL
index 993de7ce0b2..9a4cf614ace 100644
--- a/etc/TUTORIAL
+++ b/etc/TUTORIAL
@@ -296,7 +296,7 @@ commands that can destroy a lot of text save it, while the ones that
attack only one character, or nothing but blank lines and spaces, do
not save.
-For instance, type C-n a couple times to position the cursor
+For instance, type C-n a couple times to postion the cursor
at some line on this screen.
>> Do this now, move the cursor and kill that line with C-k.
@@ -533,7 +533,7 @@ to replace it with--each one ended with a Return.
Then type M-x repl s<Return>changed<Return>altered<Return>.
Notice how this line has changed: you've replaced
- the word c-h-a-n-g-e-d with "altered" wherever it occurred
+ the word c-h-a-n-g-e-d with "altered" wherever it occured
after the cursor.
diff --git a/etc/XDOC b/etc/XDOC
new file mode 100644
index 00000000000..a8a36327f4c
--- /dev/null
+++ b/etc/XDOC
@@ -0,0 +1,461 @@
+BABYL OPTIONS:
+Version: 5
+Labels:
+Note: This is the header of an rmail file.
+Note: If you are seeing it in rmail,
+Note: it means the file has no messages in it.
+
+1,,
+Received: from ATHENA (ATHENA.MIT.EDU) by prep; Thu, 19 Dec 85 23:09:34 est
+Received: from PARIS (PARIS.MIT.EDU) by ATHENA (4.12/4.7)
+ id AA02786; Thu, 19 Dec 85 23:07:35 est
+From: martillo@ATHENA.MIT.EDU (Yakim Martillo)
+Received: by PARIS (5.15/4.7)
+ id AA24170; Thu, 19 Dec 85 23:07:36 EST
+Date: Thu, 19 Dec 85 23:07:36 EST
+Message-Id: <8512200407.AA24170@PARIS>
+To: rms@prep
+Cc: lbm
+Subject: Gnu Emacs + X documentation
+
+*** EOOH ***
+From: martillo@ATHENA.MIT.EDU (Yakim Martillo)
+Date: Thu, 19 Dec 85 23:07:36 EST
+To: rms@prep
+Cc: lbm
+Subject: Gnu Emacs + X documentation
+
+
+This is the start of my X documentation.
+
+I have not finished the last five sections yet. Please give me some
+suggestions.
+
+Joachim
+
+
+Special Terminal Interfaces
+
+Some terminals provide special capabilities which can be more
+effectively used via specially written C functions rather than normal
+termcap processing. To ease the use of these capabilities and aid the
+integration of these C functions, special terminal hooks are provided.
+
+The hooks are all externed in the source header file termhooks.h.
+To determine the arguments, the interested user who wishes to develop
+a special terminal interface should consult term.c.
+For proper functioning of the user defined C termhook functions, the
+user should make certain that the terminal characteristics as externed
+in termchar.h are properly set.
+
+Examples of how to use the termhooks can be found in xterm.c which
+contains the Gnu Emacs to X interface.
+
+Gnu Emacs to X Interface
+
+The termhooks feature has enough power that termhooks need not be
+restricted merely to the employment of special terminal capabilities.
+Termhooks can be used to interface Gnu Emacs to special graphics
+devices or window systems. Gnu Emacs interfaces with not a great deal
+of difficulty to the MIT/Project Athena X Window system. With not too
+much effort, a competent hacker should be able to interface Gnu Emacs
+to the Sun, Apollo, or Blit Window systems.
+
+What is X?
+
+X is a network transparent window system developed at MIT by Bob
+Scheiffler, Jim Gettys, Tony della Fera, Ron Newman and others. X is
+a descendent of the Stanford V kernal system and Gosling's rectangle
+management system. X has a standard protocol for communication with
+an X server which talks to the high resolution graphics device driver.
+The X developers have supplied a library libX.a which provides library
+routines to handle typical graphics/window system commands. X is
+network transparent in that a process running on a machine which wants
+to make use of a high resolution graphics device will establish a
+network connection to the X server which talks to the driver for that
+device. The process will be a client of the X server. Since LAN's
+typically can move data at megabit rates, running a window system in
+this fashion has many advantages. For more information about X,
+hackers are directed to "Xlib - C Language X Interface Version (?)"
+written by Jim Gettys (DEC/MIT) and Ron Newman (MIT).
+
+New Functionality of Gnu Emacs + X
+
+Gnu Emacs running as a client of X provides very rapid line insertion
+and deletion because bit blit commands are sent to the server and the
+driver simply tells the device to move the pixels on the screen
+directly. In fact, Gnu Emacs running under the xterm terminal
+emulator can also cause bit blts to take place but bit blits via the
+terminal emulator are rather slow because of escape sequence parsing
+overhead in the terminal emulator and because of context switching
+overhead as the bits take a merry trip through the pty interfaces and
+drivers.
+
+Gnu Emacs runs in its own X window and therefore no information is
+lost from the xterm session from which the user invoked Gnu Emacs.
+Gnu Emacs should probably be run in background from the parent X
+session because then the user may continue to do more work in the
+parent xterm session. As Gnu Emacs should be run in background, the
+lisp form
+ (put 'suspend-emacs 'disabled t)
+is passed to the Gnu Emacs lisp interpreter when Gnu Emacs is invoked
+from an xterm terminal emulator. Should the user accidently type the
+key sequence for suspend-emacs (initially C-z or C-XC-z), he will be
+queried whether he truly wishes to suspend emacs. Unless the user is
+confident he should reply n (= no).
+
+If the user has an X window manager running, the user can resize the
+Gnu Emacs window using the usual mouse sequences which have been
+grabbed by the window manager. Gnu Emacs then automatically resizes
+itself and updates the display.
+
+By using the mouse window manager commands, the user can cause
+formerly obscured sections of the Gnu Emacs window to be uncovered.
+These sections have to be repainted. Since Gnu Emacs creates the Gnu
+Emacs window by its lonesome, Gnu Emacs must repaint these sections of
+the window all by itself. If Gnu Emacs is chugging away on some
+global regexp replacement, Gnu Emacs may take its time in repainting
+the display. (Similar repainting may take place on bit blits.)
+
+With the Gnu Emacs to X interface the mouse becomes even more
+powerful. Some mouse events (basically the ones not grabbed by the
+window manager) are passed to Gnu Emacs. Gnu Emacs is informed of the
+reception of such events because it receives the key sequence C-cC-m.
+Therefore a user who wishes to use the Gnu Emacs to X interface should
+not rebind this key sequence to any function.
+
+This key sequence is bound to the lisp function x-mouse-mode which
+goes and checks the special X Mouse Queue for mouse events. Each
+control/shift/meta-mouse button sequence is associated with a defined
+constant in the lisp file x-mouse.el. The constants are defined as
+follows:
+
+ (defconst x-button-right (char-to-string 0))
+ (defconst x-button-middle (char-to-string 1))
+ (defconst x-button-left (char-to-string 2))
+
+ (defconst x-button-s-right (char-to-string 16))
+ (defconst x-button-s-middle (char-to-string 17))
+ (defconst x-button-s-left (char-to-string 18))
+
+ (defconst x-button-m-right (char-to-string 32))
+ (defconst x-button-m-middle (char-to-string 33))
+ (defconst x-button-m-left (char-to-string 34))
+
+ (defconst x-button-c-right (char-to-string 64))
+ (defconst x-button-c-middle (char-to-string 65))
+ (defconst x-button-c-left (char-to-string 66))
+
+ (defconst x-button-m-s-right (char-to-string 48))
+ (defconst x-button-m-s-middle (char-to-string 49))
+ (defconst x-button-m-s-left (char-to-string 50))
+
+ (defconst x-button-c-s-right (char-to-string 80))
+ (defconst x-button-c-s-middle (char-to-string 81))
+ (defconst x-button-c-s-left (char-to-string 82))
+
+ (defconst x-button-c-m-right (char-to-string 96))
+ (defconst x-button-c-m-middle (char-to-string 97))
+ (defconst x-button-c-m-left (char-to-string 98))
+
+ (defconst x-button-c-m-s-right (char-to-string 112))
+ (defconst x-button-c-m-s-middle (char-to-string 113))
+ (defconst x-button-c-m-s-left (char-to-string 114)).
+
+To understand why these constants are so defined, the user should
+check out the (C) definition of the lisp function x-mouse-mode in the
+src file xfns.c. (I, Joachim Martillo not RMS, do not claim
+this code handles mouse events in the best way possible, and all
+involved with maintaining the Gnu Emacs to X interface would be open
+to suggestions for improvement.)
+
+Anyway, using these defined constants, the user may bind his own
+defined functions to mouse sequences using the define-key command as
+below:
+
+ (define-key mouse-map x-button-right 'x-mouse-select).
+
+Mouse functions are defined like any of the other lisp functions in
+Gnu Emacs.
+
+Here, exempli gratia, is the lisp definition of x-mouse-select:
+
+ (defun x-mouse-select (arg)
+ "Select Emacs window the mouse is on."
+ (let ((start-w (selected-window))
+ (done nil)
+ (w (selected-window))
+ (rel-coordinate nil))
+ (while (and (not done)
+ (null (setq rel-coordinate
+ (coordinates-in-window-p arg w))))
+ (setq w (next-window w))
+ (if (eq w start-w)
+ (setq done t)))
+ (select-window w)
+ rel-coordinate)).
+
+When the mouse sequence is received, x-mouse-mode checks out the mouse
+queue, sees the defined constant associated with that button event,
+looks up that defined constants binding in the mouse-map and then
+invokes this lisp function with arg which is a list of the x and y
+coordinates of the mouse when the mouse event under question took
+place. The lisp symbol arg is bound to (x-coordinate y-coordinate).
+
+The supplied mouse-functions and bindings are:
+
+ x-cut-and-wipe-text
+ Function: Kill text between point and mouse; also copy to
+ window system cut buffer.
+ Binding: C-Middle Button.
+
+ x-cut-text
+ Function: Copy text between point and mouse position into
+ window system cut buffer.
+ Binding: S-Middle Button (i.e. Shift-Middle Button).
+
+ x-mouse-keep-one-window
+ Function: Select Emacs window mouse is on, then kill all other Emacs
+ windows.
+ Binding: C-S-Right Button.
+
+ x-mouse-select
+ Function: Select Emacs window the mouse is on.
+ Binding: Right Button.
+
+ x-mouse-select-and-split
+ Function: Select Emacs window mouse is on, then split it vertically
+ in half.
+ Binding: C-Right Button.
+
+ x-mouse-set-mark
+ Function: Select Emacs window mouse is on, and set mark at mouse
+ position.
+ Binding: Left Button.
+ x-mouse-set-point
+ Function: Select Emacs window mouse is on, and move point to mouse
+ position.
+ Binding: Middle Button.
+
+ x-paste-text
+ Function: Move point to mouse position and insert window system cut
+ buffer contents.
+ Binding: S-Right Button.
+
+These functions are invoked simply by positioning the mouse and then
+pressing the correct key/button combination.
+
+The cut and paste functions deserve special remark. The X server
+maintains special buffers where data may be salted away. One client
+may salt data away in a cut buffer. Then another client could request
+this data. In emacs, data is salted away, by setting the point (you
+could use the mouse to set the point) then moving the mouse to the end
+(or beginning) of the text to be salted away and pressing shift
+middle. If the text should be wiped out of the buffer as well as
+salted away, C-Middle Button should be used instead of S-Middle
+Button. To get the text back into this emacs or another emacs, move
+the mouse to where the text should be inserted and invoke x-paste-text
+via S-Right Button. The text can be pasted into any client of the
+current X server from the current cut buffer using that client's paste
+command. For xterm the paste command is also S-Right Button.
+
+Other Gnu Emacs Lisp Functions
+
+Command Line Arguments
+
+.emacs File
+
+x-switches
+
+.Xdefaults
+
+
+1,,
+Summary-line: 19-Dec lbm@ATHENA.MIT.EDU #GNU Emacs under X Writeup for Manual
+Received: from ATHENA (ATHENA.MIT.EDU) by prep; Thu, 19 Dec 85 15:57:34 est
+Received: from JASON (JASON.MIT.EDU) by ATHENA (4.12/4.7)
+ id AA12646; Thu, 19 Dec 85 15:55:53 est
+Received: by JASON (5.15/4.7)
+ id AA20416; Thu, 19 Dec 85 15:55:40 EST
+Message-Id: <8512192055.AA20416@JASON>
+To: rms@prep
+Cc: tower@prep
+Subject: GNU Emacs under X Writeup for Manual
+Date: 19 Dec 85 15:55:33 EST (Thu)
+From: Linda B. Merims <lbm@ATHENA.MIT.EDU>
+
+*** EOOH ***
+To: rms@prep
+Cc: tower@prep
+Subject: GNU Emacs under X Writeup for Manual
+Date: 19 Dec 85 15:55:33 EST (Thu)
+From: Linda B. Merims <lbm@ATHENA.MIT.EDU>
+
+
+Here's something you can put in the V17 manual to describe GNU Emacs under
+X. I've added a couple of notes to you about things that didn't work
+when I tried them. It has no formatting commands in it. I
+don't know if we followed your naming conventions. It is important
+for us to distinguish between "gnuemacs" and "emacs" for the next
+six months while we convert our 2000+ users over from CCA, so I mention
+that at MIT's Project Athena, things are a little different for
+a short while.
+
+I didn't put in anything about X-specific variables. I don't know
+anything about them. I'm also a bit colloquial in places, to make
+my point better with novices (who, for example, understand "cursor" better
+than "point".) I also didn't document the -d display command option.
+Nor are there any credits to, for example, Joachim Martillo. Up to you.
+
+Hope this does you good.
+
+ Linda Merims
+
+
+----------------------------------------------------------------
+GNU Emacs on X Window System Displays
+
+
+GNU Emacs works with the X window system. It starts
+by "popping up" a new window on the screen. This can be a bit
+disconcerting if you're not used to it. If you're on one of these
+terminals, the easiest way to start up GNU Emacs is to type the same command
+you would before, but to follow it with a &, as in:
+
+emacs paper.mss &
+
+The "&" runs GNU Emacs in the "background," freeing your original
+window for other uses. (There are X-specific options to the Gnuemacs
+commands that will be listed later.)
+
+NOTE: GNU Emacs may be invoked by
+different names at different sites. It is sometimes known
+as xemacs. At MIT's Project Athena where GNU Emacs was first
+adapted to X, the correct command is: gnuemacs until summer
+1986, when it will become just: emacs.
+
+Soon, you will see a small black box in the upper left hand corner of your
+screen that reads, "emacs: 10 x 10". (This number represents
+columns x rows.) You'll also see a small outline of a window with
+a cross in the upper left hand corner of it. This is where the upper
+left hand corner of your window will be. You can move this cross with
+the mouse to any spot on the screen. You can then do one of three
+things:
+
+make an 80 column by 24 row emacs window -- click the left mouse button
+
+make an 80 column by 65 row emacs window -- click the right mouse button
+ (the length will actually be however many lines long your screen
+ can hold. 80 by 66 is about the size of an 8 1/2 x 11 piece of paper.)
+
+make any size emacs window you want -- hold down the middle mouse button
+ and move the mouse to create a window of any size. As you move the
+ mouse, the numbers in the upper left hand corner of the screen and
+ the rubber-band outline will expand or contract. Just release the
+ button when the window is the size you want.
+
+Unless you make the window in any area that does not overlap any other
+windows, you may have problems when you want to get back to a window
+obscured by the GNU Emacs window. You need to know how to use the X
+window manager, xwm, to move and shuffle these windows around. For
+more information on the window manager, you can type man xwm, on
+any Berkeley 4.3 Unix system with this user-contributed (/usr/new)
+utility available.
+
+Note that you cannot suspend (C-Z) a GNU emacs X window.
+
+
+
+GNU Emacs and the X Mouse
+
+When using GNU Emacs on an X terminal, you can take advantage of the
+convenient, quick commands for moving point, setting the mark, and
+cutting and pasting text. You issue these commands by pressing
+the mouse's buttons alone or in concert with the SHIFT, CTRL, or
+SHIFT-CTRL keys as follows:
+
+left set mark ('x-mouse-set-mark) (RMS, this blinked cursor but didn't
+ actually set anything...lbm)
+
+middle move the cursor (point) to where the mouse is. This is
+ like moving the cursor with C-F or C-N or the arrow keys,
+ only immediate. ('x-mouse-set-point)
+
+right move to the window where the mouse is. Point is in the same
+ place as it was the last time you were in the window.
+ ('x-mouse-select)
+
+
+SHIFT-left
+ undefined
+
+SHIFT-middle
+ take the text between point and mark and put it into the
+ X cut buffer. The text does NOT disappear from the screen.
+ It does NOT go into the emacs kill right. Used for copying
+ text. Recall text with SHIFT-right below. ('x-cut-text)
+
+SHIFT-right
+ paste text from the X cut buffer to before point. ('x-paste-text)
+
+
+CTRL-left
+ undefined
+
+CTRL-middle
+ take the text between point and mark and put it into the
+ X cut buffer, AND the emacs kill ring. Text is deleted
+ from the screen. Used for moving text. Recall text with
+ SHIFT-right above, or any emacs kill ring command.
+ ('x-cut-and-wipe-text)
+
+CTRL-right
+ divide current window in two. ('x-mouse-select-and-split)
+
+
+CTRL-SHIFT-middle
+ return to one-window mode, keeping the window the mouse is
+ in. ('x-mouse-keep-one-window)(RMS, this didn't always work...lbm)
+
+
+
+Emacs Command X Window Options
+
+These command options have meaning to the X window system:
+
+-r use reverse video (white characters on black background)
+
+-i use GNU emacs's bitmap icon (a kitchen sink) if the emacs
+ window is iconized instead of the xwm window manager default.
+
+-font fontname
+ use fontname instead of the default vtsingle
+
+-b borderwidth
+ make the window border borderwidth pixels wide. Default is 1.
+
+-w windowsize
+ instead of relying on the mouse buttons to determine size and
+ placement of the GNU emacs window, make it this size. Size
+ is specified as:
+
+ =[WIDTH][xHEIGHT][{+-}XOFF[{+-}YOFF]]
+
+ The []'s denote optional stuff, the {}'s surround
+ alternatives. WIDTH and HEIGHT are in number of
+ characters, XOFF and YOFF are in pixels. X and YOFF are
+ the xy offsets from the upper left corner origin for the
+ upper left corner of the window.
+
+
+GNU Emacs will check in the .Xdefaults file for default values for
+these variables. (RMS, we're not sure what program name it's
+going to be looking for...lbm)
+
+
+GNU Emacs under X Variables
+
+I don't know what these are. Sorry.
+
+
+ \ No newline at end of file
diff --git a/etc/XENIX b/etc/XENIX
new file mode 100644
index 00000000000..f466354e90b
--- /dev/null
+++ b/etc/XENIX
@@ -0,0 +1,116 @@
+Return-Path: <info-gnu-emacs-request@prep.ai.mit.edu>
+Date: 5 Aug 88 18:46:22 GMT
+From: jetson!john@uunet.uu.net (John Owens)
+Organization: SMART HOUSE Limited Partnership
+Subject: Meta key support in SCO Xenix!
+Sender: info-gnu-emacs-request@prep.ai.mit.edu
+To: info-gnu-emacs@prep.ai.mit.edu
+
+Here is a substitute for /usr/lib/keyboard/keys in SCO Xenix that
+allows use of the meta key in GNU Emacs. Pressing ALT with any key
+causes the code returned to have the 80hex bit set. In conjunction
+with this, I added lisp/term/ansi.el with the single line
+
+(setq meta-flag t)
+
+Here's the keys file. Make sure MAPKEY=YES is in your
+/etc/default/boot. (This also allows you to enter graphics characters
+from the keyboard.) Enjoy!
+
+# alt
+# scan cntrl alt alt cntrl lock
+# code base shift cntrl shift alt shift cntrl shift state
+ 0 nop nop nop nop nop nop nop nop O
+ 1 esc esc nop nop 0x9b 0x9b nop nop O
+ 2 '1' '!' nop nop 0xb1 0xa1 nop nop O
+ 3 '2' '@' nul nul 0xb2 0xc0 0x80 0x80 O
+ 4 '3' '#' nop nop 0xb3 0xa3 nop nop O
+ 5 '4' '$' nop nop 0xb4 0xa4 nop nop O
+ 6 '5' '%' nop nop 0xb5 0xa5 nop nop O
+ 7 '6' '^' rs rs 0xb6 0xde 0x9e 0x9e O
+ 8 '7' '&' nop nop 0xb7 0xa6 nop nop O
+ 9 '8' '*' nop nop 0xb8 0xaa nop nop O
+ 10 '9' '(' nop nop 0xb9 0xa8 nop nop O
+ 11 '0' ')' nop nop 0xb0 0xa9 nop nop O
+ 12 '-' '_' ns ns 0xad 0xdf 0x9f 0x9f O
+ 13 '=' '+' nop nop 0xbd 0xab nop nop O
+ 14 bs bs del del 0x88 0x88 0xff 0xff O
+ 15 ht btab nop nop 0x89 btab nop nop O
+ 16 'q' 'Q' dc1 dc1 0xf1 0xd1 0x91 0x91 C
+ 17 'w' 'W' etb etb 0xf7 0xd7 0x97 0x97 C
+ 18 'e' 'E' enq enq 0xe5 0xc5 0x85 0x85 C
+ 19 'r' 'R' dc2 dc2 0xf2 0xd2 0x92 0x92 C
+ 20 't' 'T' dc4 dc4 0xf4 0xd4 0x94 0x94 C
+ 21 'y' 'Y' em em 0xf9 0xd9 0x99 0x99 C
+ 22 'u' 'U' nak nak 0xf5 0xd5 0x95 0x95 C
+ 23 'i' 'I' ht ht 0xe9 0xc9 0x89 0x89 C
+ 24 'o' 'O' si si 0xef 0xcf 0x8f 0x8f C
+ 25 'p' 'P' dle dle 0xf0 0xd0 0x90 0x90 C
+ 26 '[' '{' esc esc 0xdb 0xfb 0x9b 0x9b O
+ 27 ']' '}' gs gs 0xdd 0xfd 0x9d 0x9d O
+ 28 cr cr nl nl 0x8d 0x8d 0x8a 0x8a O
+ 29 ctrl ctrl ctrl ctrl ctrl ctrl ctrl ctrl O
+ 30 'a' 'A' soh soh 0xe1 0xc1 0x81 0x81 C
+ 31 's' 'S' dc3 dc3 0xf3 0xd3 0x93 0x93 C
+ 32 'd' 'D' eot eot 0xe4 0xc4 0x84 0x84 C
+ 33 'f' 'F' ack ack 0xe6 0xc6 0x86 0x86 C
+ 34 'g' 'G' bel bel 0xe7 0xc7 0x87 0x87 C
+ 35 'h' 'H' bs bs 0xe8 0xc8 0x88 0x88 C
+ 36 'j' 'J' nl nl 0xea 0xca 0x8a 0x8a C
+ 37 'k' 'K' vt vt 0xeb 0xcb 0x8b 0x8b C
+ 38 'l' 'L' np np 0xec 0xcc 0x8c 0x8c C
+ 39 ';' ':' nop nop 0xbb 0xba nop nop O
+ 40 '\'' '"' nop nop 0xa7 0xa2 nop nop O
+ 41 '`' '~' nop nop 0xe0 0xfe nop nop O
+ 42 lshift lshift lshift lshift lshift lshift lshift lshift O
+ 43 '\\' '|' fs fs 0xdc 0xfc 0x9c 0x9c O
+ 44 'z' 'Z' sub sub 0xfa 0xda 0x9a 0x9a C
+ 45 'x' 'X' can can 0xf8 0xd8 0x98 0x98 C
+ 46 'c' 'C' etx etx 0xe3 0xc3 0x83 0x83 C
+ 47 'v' 'V' syn syn 0xf6 0xd6 0x96 0x96 C
+ 48 'b' 'B' stx stx 0xe2 0xc2 0x82 0x82 C
+ 49 'n' 'N' so so 0xee 0xce 0x8e 0x8e C
+ 50 'm' 'M' cr cr 0xed 0xcd 0x8d 0x8d C
+ 51 ',' '<' nop nop 0xac 0xbc nop nop O
+ 52 '.' '>' nop nop 0xae 0xbe nop nop O
+ 53 '/' '?' nop nop 0xaf 0xbf nop nop O
+ 54 rshift rshift rshift rshift rshift rshift rshift rshift O
+ 55 '*' '*' nscr nscr 0xaa 0xaa nscr nscr O
+ 56 alt alt alt alt alt alt alt alt O
+ 57 ' ' ' ' ' ' ' ' 0xa0 0xa0 0xa0 0xa0 O
+ 58 clock clock clock clock clock clock clock clock O
+ 59 fkey1 fkey13 fkey25 fkey37 scr1 scr11 scr1 scr11 O
+ 60 fkey2 fkey14 fkey26 fkey38 scr2 scr12 scr2 scr12 O
+ 61 fkey3 fkey15 fkey27 fkey39 scr3 scr13 scr3 scr13 O
+ 62 fkey4 fkey16 fkey28 fkey40 scr4 scr14 scr4 scr14 O
+ 63 fkey5 fkey17 fkey29 fkey41 scr5 scr15 scr5 scr15 O
+ 64 fkey6 fkey18 fkey30 fkey42 scr6 scr16 scr6 scr16 O
+ 65 fkey7 fkey19 fkey31 fkey43 scr7 scr7 scr7 scr7 O
+ 66 fkey8 fkey20 fkey32 fkey44 scr8 scr8 scr8 scr8 O
+ 67 fkey9 fkey21 fkey33 fkey45 scr9 scr9 scr9 scr9 O
+ 68 fkey10 fkey22 fkey34 fkey46 scr10 scr10 scr10 scr10 O
+ 69 nlock nlock dc3 dc3 nlock nlock 0x93 0x93 O
+ 70 slock slock del del slock slock 0xff 0xff O
+ 71 fkey49 '7' '7' '7' 0xb7 0xb7 0xb7 0xb7 N
+ 72 fkey50 '8' '8' '8' 0xb8 0xb8 0xb8 0xb8 N
+ 73 fkey51 '9' '9' '9' 0xb9 0xb9 0xb9 0xb9 N
+ 74 fkey52 '-' '-' '-' 0xad 0xad 0xad 0xad N
+ 75 fkey53 '4' '4' '4' 0xb4 0xb4 0xb4 0xb4 N
+ 76 fkey54 '5' '5' '5' 0xb5 0xb5 0xb5 0xb5 N
+ 77 fkey55 '6' '6' '6' 0xb6 0xb6 0xb6 0xb6 N
+ 78 fkey56 '+' '+' '+' 0xab 0xab 0xab 0xab N
+ 79 fkey57 '1' '1' '1' 0xb1 0xb1 0xb1 0xb1 N
+ 80 fkey58 '2' '2' '2' 0xb2 0xb2 0xb2 0xb2 N
+ 81 fkey59 '3' '3' '3' 0xb3 0xb3 0xb3 0xb3 N
+ 82 fkey60 '0' '0' '0' 0xb0 0xb0 0xb0 0xb0 N
+ 83 del '.' del del 0xff 0xff 0xff 0xff N
+ 84 nop nop nop nop nop nop nop nop O
+ 85 nop nop nop nop nop nop nop nop O
+ 86 nop nop nop nop nop nop nop nop O
+ 87 fkey11 fkey23 fkey35 fkey47 scr11 scr11 scr11 scr11 O
+ 88 fkey12 fkey24 fkey36 fkey48 scr12 scr12 scr12 scr12 O
+--
+John Owens john@jetson.UPMA.MD.US
+SMART HOUSE L.P. uunet!jetson!john (old uucp)
++1 301 249 6000 john%jetson.uucp@uunet.uu.net (old internet)
+
diff --git a/etc/Xkeymap.txt b/etc/Xkeymap.txt
new file mode 100644
index 00000000000..07ecf6e8b10
--- /dev/null
+++ b/etc/Xkeymap.txt
@@ -0,0 +1,98 @@
+# -*-Mode: Fundamental-*-
+# X keymap file for rlk with some emacsified bindings
+# This file contains the default keyboard mapping. The first column contains a X keyboard code; the other
+# 16 columns contain the mapping of the keycode to a character string, with various combinations
+# of the SHIFT, LOCK, META, and CONTROL keys down. See the man page for "keycomp" for more information.
+#
+# Keycode constants for non-typewriter keys are found in <X/Xkeyboard.h>.
+#
+# It is easiest to edit this file with an EMACS window running across the entire width of the display, with
+# tab stop set to 4.
+#
+# E1=Find, E2=Insert Here, E3=Remove, E4=Select, E5=Prev Screen, E6=Next Screen
+# uns L S SL M ML MS MSL C CL CS CSL CM CML CMS CMSL
+0212 0023, 0023, 0023, 0023, 0223, 0223, 0223, 0223, 0022, 0022, 0022, 0022, 0222, 0222, 0222, 0222, /* E1 */
+0213 U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, /* E2 */
+0214 0004, 0004, 0177, 0177, 0304, 0304, 0377, 0377, 0004, 0004, 0177, 0177, 0204, 0204, 0377, 0377 /* E3 */
+0215 U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, /* E4 */
+0216 0326, 0326, 0326, 0326, 0326, 0326, 0326, 0326, "\255\226" "\255\226" "\255\226" "\255\226" "\255\226" "\255\226" "\255\226" "\255\226" /* E5 */
+0217 0026, 0026, 0026, 0026, 0026, 0026, 0026, 0026, 0226, 0226, 0226, 0226, 0226, 0226, 0226, 0226, /* E6 */
+0247 0002, 0002, 0002, 0002, 0302, 0302, 0302, 0302, 0202, 0202, 0202, 0202, 0202, 0202, 0202, 0202, /* Left arrow */
+0250 0006, 0006, 0006, 0006, 0306, 0306, 0306, 0306, 0206, 0206, 0206, 0206, 0206, 0206, 0206, 0206, /* Right arrow */
+0251 0016, 0016, 0016, 0016, 0316, 0316, 0316, 0316, 0216, 0216, 0216, 0216, 0216, 0216, 0216, 0216, /* Down arrow */
+0252 0020, 0020, 0020, 0020, 0320, 0320, 0320, 0320, 0220, 0220, 0220, 0220, 0220, 0220, 0220, 0220, /* Up arrow */
+0222 0260, '0', 0260, '0', 0260, '0', 0260, '0', 0260, '0', 0260, '0', 0260, '0', 0260, '0', /* KP 0 */
+0224 0256, '.', 0256, '.', 0256, '.', 0256, '.', 0256, '.', 0256, '.', 0256, '.', 0256, '.', /* KP . */
+0225 '\n', '\n', '\n', '\n', 0312, 0312, 0312, 0312, 0212, 0212, 0212, 0212, 0212, 0212, 0212, 0212, /* KP Enter */
+0226 0261, '1', 0261, '1', 0261, '1', 0261, '1', 0261, '1', 0261, '1', 0261, '1', 0261, '1', /* KP 1 */
+0227 0262, '2', 0262, '2', 0262, '2', 0262, '2', 0262, '2', 0262, '2', 0262, '2', 0262, '2', /* KP 2 */
+0230 0263, '3', 0263, '3', 0263, '3', 0263, '3', 0263, '3', 0263, '3', 0263, '3', 0263, '3', /* KP 3 */
+0231 0264, '4', 0264, '4', 0264, '4', 0264, '4', 0264, '4', 0264, '4', 0264, '4', 0264, '4', /* KP 4 */
+0232 0265, '5', 0265, '5', 0265, '5', 0265, '5', 0265, '5', 0265, '5', 0265, '5', 0265, '5', /* KP 5 */
+0233 0266, '6', 0266, '6', 0266, '6', 0266, '6', 0266, '6', 0266, '6', 0266, '6', 0266, '6', /* KP 6 */
+0234 0254, ',', 0254, ',', 0254, ',', 0254, ',', 0254, ',', 0254, ',', 0254, ',', 0254, ',', /* KP , */
+0235 0267, '7', 0267, '7', 0267, '7', 0267, '7', 0267, '7', 0267, '7', 0267, '7', 0267, '7', /* KP 7 */
+0236 0270, '8', 0270, '8', 0270, '8', 0270, '8', 0270, '8', 0270, '8', 0270, '8', 0270, '8', /* KP 8 */
+0237 0271, '9', 0271, '9', 0271, '9', 0271, '9', 0271, '9', 0271, '9', 0271, '9', 0271, '9', /* KP 9 */
+0240 0255, '-', 0255, '-', 0255, '-', 0255, '-', 0255, '-', 0255, '-', 0255, '-', 0255, '-', /* KP - */
+0174 0010, 0010, 0010, 0010, 0010, 0010, 0010, 0010, 0010, 0010, 0010, 0010, 0010, 0010, 0010, 0010, /* F15/Help */
+0175 0037, 0037, 0037, 0037, 0037, 0037, 0037, 0037, 0037, 0037, 0037, 0037, 0037, 0037, 0037, 0037, /* F16/(Un)Do */
+0161 0033, 0033, 0033, 0033, 0033, 0033, 0033, 0033, 0033, 0033, 0033, 0033, 0033, 0033, 0033, 0033, /* F11/ESC */
+0162 '\b', '\b', '\b', '\b', '\b', '\b', U, U, '\b', '\b', U, U, U, U, U, U, /* F12/BS */
+0163 '\n', '\n', '\n', '\n', '\n', '\n', U, U, '\n', '\n', U, U, U, U, U, U, /* F13/LF */
+0274 0177, 0177, 0177, 0177, 0377, 0377, 0377, 0377, 0030, 0030, 0177, 0177, 0377, 0377, 0377, 0377, /* back */
+0275 '\r', '\r', '\r', '\r', 0215, 0215, 0215, 0215, '\r', '\r', U, U, U, U, U, U, /* Return */
+0276 '\t', '\t', '\t', '\t', 0211, 0211, 0211, 0211, "\021\t" "\021\t" "\021\t" "\021\t" "\021\t" "\021\t" "\021\t" "\021\t" /* Tab */
+0277 '`', '`', '~', '~', 0340, 0340, 0376, 0376, 0036, 0036, 0036, 0036, U, U, U, U, /* ` */
+0300 '1', '1', '!', '!', 0261, 0261, 0241, 0241, '1', '1', '!', '!', U, U, U, U, /* 1 */
+0301 'q', 'Q', 'Q', 'Q', 0361, 0361, 0321, 0321, 0021, 0021, 0021, 0021, 0221, 0221, 0221, 0221, /* q */
+0302 'a', 'A', 'A', 'A', 0341, 0341, 0301, 0301, 0001, 0001, 0001, 0001, 0201, 0201, 0201, 0201, /* a */
+0303 'z', 'Z', 'Z', 'Z', 0372, 0372, 0332, 0332, 0032, 0032, 0032, 0032, 0232, 0232, 0232, 0232, /* z */
+0305 '2', '2', '@', '@', 0262, 0262, 0300, 0300, 0000, 0000, 0000, 0000, 0262, 0262, 0200, 0200, /* 2 */
+0306 'w', 'W', 'W', 'W', 0367, 0367, 0327, 0327, 0027, 0027, 0027, 0027, 0227, 0227, 0227, 0227, /* w */
+0307 's', 'S', 'S', 'S', 0363, 0363, 0323, 0323, 0023, 0023, 0023, 0023, 0223, 0223, 0223, 0223, /* s */
+0310 'x', 'X', 'X', 'X', 0370, 0370, 0330, 0330, 0030, 0030, 0030, 0030, 0230, 0230, 0230, 0230, /* x */
+0311 '<', '<', '>', '>', 0274, 0274, 0276, 0276, U, U, U, U, U, U, U, U, /* < */
+0313 '3', '3', '#', '#', 0263, 0263, 0243, 0243, 0033, 0033, '#', '#', U, U, U, U, /* 3 */
+0314 'e', 'E', 'E', 'E', 0345, 0345, 0305, 0305, 0005, 0005, 0005, 0005, 0205, 0205, 0205, 0205, /* e */
+0315 'd', 'D', 'D', 'D', 0344, 0344, 0304, 0304, 0004, 0004, 0004, 0004, 0204, 0204, 0204, 0204, /* d */
+0316 'c', 'C', 'C', 'C', 0343, 0343, 0303, 0303, 0003, 0003, 0003, 0003, 0203, 0203, 0203, 0203, /* c */
+0320 '4', '4', '$', '$', 0264, 0264, 0244, 0244, 0034, 0034, '$', '$', U, U, U, U, /* 4 */
+0321 'r', 'R', 'R', 'R', 0362, 0362, 0322, 0322, 0022, 0022, 0022, 0022, 0222, 0222, 0222, 0222, /* r */
+0322 'f', 'F', 'F', 'F', 0346, 0346, 0306, 0306, 0006, 0006, 0006, 0006, 0206, 0206, 0206, 0206, /* f */
+0323 'v', 'V', 'V', 'V', 0366, 0366, 0326, 0326, 0026, 0026, 0026, 0026, 0226, 0226, 0226, 0226, /* v */
+0324 ' ', ' ', ' ', ' ', 0240, 0240, 0240, 0240, 0000, 0000, 0000, 0000, 0200, 0200, 0200, 0200, /* space */
+0326 '5', '5', '%', '%', 0265, 0265, 0245, 0245, 0035, 0035, '%', '%', U, U, U, U, /* 5 */
+0327 't', 'T', 'T', 'T', 0364, 0364, 0324, 0324, 0024, 0024, 0024, 0024, 0224, 0224, 0224, 0224, /* t */
+0330 'g', 'G', 'G', 'G', 0347, 0347, 0307, 0307, 0007, 0007, 0007, 0007, 0207, 0207, 0207, 0207, /* g */
+0331 'b', 'B', 'B', 'B', 0342, 0342, 0302, 0302, 0002, 0002, 0002, 0002, 0202, 0202, 0202, 0202, /* b */
+0333 '6', '6', '^', '^', 0266, 0266, 0336, 0336, 0036, 0036, 0036, 0036, U, U, U, U, /* 6 */
+0334 'y', 'Y', 'Y', 'Y', 0371, 0371, 0331, 0331, 0031, 0031, 0031, 0031, 0231, 0231, 0231, 0231, /* y */
+0335 'h', 'H', 'H', 'H', 0350, 0350, 0310, 0310, 0010, 0010, 0010, 0010, 0210, 0210, 0210, 0210, /* h */
+0336 'n', 'N', 'N', 'N', 0356, 0356, 0316, 0316, 0016, 0016, 0016, 0016, 0216, 0216, 0216, 0216, /* n */
+0340 '7', '7', '&', '&', 0267, 0267, 0246, 0246, 0037, 0037, '&', '&', U, U, U, U, /* 7 */
+0341 'u', 'U', 'U', 'U', 0365, 0365, 0325, 0325, 0025, 0025, 0025, 0025, 0225, 0225, 0225, 0225, /* u */
+0342 'j', 'J', 'J', 'J', 0352, 0352, 0312, 0312, 0012, 0012, 0012, 0012, 0212, 0212, 0212, 0212, /* j */
+0343 'm', 'M', 'M', 'M', 0355, 0355, 0315, 0315, 0015, 0015, 0015, 0015, 0215, 0215, 0215, 0215, /* m */
+0345 '8', '8', '*', '*', 0270, 0270, 0252, 0252, 0177, 0177, '*', '*', U, U, U, U, /* 8 */
+0346 'i', 'I', 'I', 'I', 0351, 0351, 0311, 0311, 0011, 0011, 0011, 0011, 0211, 0211, 0211, 0211, /* i */
+0347 'k', 'K', 'K', 'K', 0353, 0353, 0313, 0313, 0013, 0013, 0013, 0013, 0213, 0213, 0213, 0213, /* k */
+0350 ',', ',', '<', '<', 0254, 0254, 0274, 0274, U, U, U, U, U, U, U, U, /* , */
+0352 '9', '9', '(', '(', 0271, 0271, 0250, 0250, '9', '9', '(', '(', U, U, U, U, /* 9 */
+0353 'o', 'O', 'O', 'O', 0357, 0357, 0317, 0317, 0017, 0017, 0017, 0017, 0217, 0217, 0217, 0217, /* o */
+0354 'l', 'L', 'L', 'L', 0354, 0354, 0314, 0314, 0014, 0014, 0014, 0014, 0214, 0214, 0214, 0214, /* l */
+0355 '.', '.', '>', '>', 0256, 0256, 0276, 0276, U, U, U, U, U, U, U, U, /* . */
+0357 '0', '0', ')', ')', 0260, 0260, 0251, 0251, '0', '0', ')', ')', U, U, U, U, /* 0 */
+0360 'p', 'P', 'P', 'P', 0360, 0360, 0320, 0320, 0020, 0020, 0020, 0020, 0220, 0220, 0220, 0220, /* p */
+0362 ';', ';', ':', ':', 0273, 0273, 0272, 0272, U, U, U, U, U, U, U, U, /* ; */
+0363 '/', '/', '?', '?', 0257, 0257, 0277, 0277, 0037, 0037, 0037, 0037, 0237, 0237, 0237, 0237, /* / */
+0365 '=', '=', '+', '+', 0275, 0275, 0253, 0253, U, U, U, U, U, U, U, U, /* = */
+0366 ']', ']', '}', '}', 0335, 0335, 0376, 0376, 0035, 0035, 0035, 0035, 0335, 0335, 0335, 0335, /* ] */
+0367 '\\', '\\', '|', '|', 0334, 0334, 0374, 0374, 0034, 0034, 0034, 0034, 0334, 0334, 0334, 0334, /* \ */
+0371 '-', '-', '_', '_', 0255, 0255, 0337, 0337, 0037, 0037, 0037, 0037, 0337, 0337, 0337, 0337, /* - */
+0372 '[', '[', '{', '{', 0333, 0333, 0373, 0373, 0033, 0033, 0033, 0033, 0333, 0333, 0333, 0333, /* [ */
+0373 '\'', '\'', '"', '"', 0247, 0247, 0242, 0242, U, U, U, U, U, U, U, U, /* ' */
+#
+# local variables:
+# tab-width: 4
+# End:
diff --git a/etc/celibacy.1 b/etc/celibacy.1
new file mode 100644
index 00000000000..5a3fdd594f3
--- /dev/null
+++ b/etc/celibacy.1
@@ -0,0 +1,12 @@
+CELIBACY(1) UNIX Programmer's Manual CELIBACY(1)
+
+
+
+NAME
+ celibacy - don't have sex
+
+SYNOPSIS
+ celibacy
+
+DESCRIPTION
+ Does nothing worth mentioning.
diff --git a/etc/complink.com b/etc/complink.com
new file mode 100644
index 00000000000..1d7ea749de2
--- /dev/null
+++ b/etc/complink.com
@@ -0,0 +1,41 @@
+$ ! Compile and link those programs in [etc] that are usable on VMS.
+$
+$ old = f$environment("default")
+$ set default emacs_library:[etc]
+$ if f$search("test-distrib.c") .nes. "" then goto version44
+$
+$ cc test_distrib.c
+$ link test_distrib.obj,vmslink.opt/opt
+$ run test_distrib.exe
+$ cc /debug make_docfile.c
+$ link make_docfile.obj,vmslink.opt/opt
+$ cc /debug digest_doc.c
+$ link digest_doc.obj,vmslink.opt/opt
+$ cc /debug sorted_doc.c
+$ cc /debug qsort.c
+$ link sorted_doc.obj,qsort.obj,vmslink.opt/opt
+$ cc /debug etags_vmslib.c
+$ cc /debug etags.c
+$ link etags.obj,etags_vmslib.obj,vmslink.opt/opt
+$ goto finish
+$
+$version44:
+$ cc test-distrib.c
+$ link test-distrib.obj,vmslink.opt/opt
+$ run test-distrib.exe
+$ cc /debug make-docfile.c
+$ link make-docfile.obj,vmslink.opt/opt
+$ cc /debug digest-doc.c
+$ link digest-doc.obj,vmslink.opt/opt
+$ cc /debug sorted-doc.c
+$ cc /debug qsort.c
+$ link sorted-doc.obj,qsort.obj,vmslink.opt/opt
+$ cc /debug etags-vmslib.c
+$ cc /debug etags.c
+$ link etags.obj,etags-vmslib.obj,vmslink.opt/opt
+$
+$finish:
+$ cc /debug yow.c
+$ link yow.obj,vmslink.opt/opt
+$
+$ set default 'old'
diff --git a/lib-src/cvtmail.c b/etc/cvtmail.c
index 1f3b8ff9f9e..e9ed160153e 100644
--- a/lib-src/cvtmail.c
+++ b/etc/cvtmail.c
@@ -1,4 +1,5 @@
/* Copyright (C) 1985 Free Software Foundation
+
This file is part of GNU Emacs.
GNU Emacs is free software; you can redistribute it and/or modify
diff --git a/lib-src/digest-doc.c b/etc/digest-doc.c
index d7764c08a65..d7764c08a65 100644
--- a/lib-src/digest-doc.c
+++ b/etc/digest-doc.c
diff --git a/etc/echo.msg b/etc/echo.msg
new file mode 100644
index 00000000000..459a1b24f5e
--- /dev/null
+++ b/etc/echo.msg
@@ -0,0 +1,207 @@
+Path: mit-amt!mit-eddie!think!harvard!seismo!gatech!akgua!whuxlm!whuxl!houxm!ihnp4!stolaf!umn-cs!herndon
+From: herndon@umn-cs.UUCP
+Newsgroups: net.sources
+Subject: GNU Echo, Release 1
+Message-ID: <1600001@umn-cs.UUCP>
+Date: 28 Oct 85 18:23:00 GMT
+
+
+/* Written 12:22 pm Oct 28, 1985 by umn-cs!herndon in umn-cs:net.jokes */
+/* ---------- "GNU Echo, Release 1" ---------- */
+
+
+
+
+GNUecho(1) UNIX Programmer's Manual GNUecho(1)
+
+
+
+NAME
+ echo - echo arguments
+
+SYNOPSIS
+ echo [ options ] ...
+
+DESCRIPTION
+ _^HE_^Hc_^Hh_^Ho writes its arguments separated by blanks and terminated
+ by a newline on the standard output. Options to filter and
+ redirect the output are as follows:
+
+ -2 generate rhyming couplets from keywords
+
+ -3 generate Haiku verse from keywords
+
+ -5 generate limerick from keywords
+
+ -a convert ASCII to ASCII
+
+ -A disambiguate sentence structure
+
+ -b generate bureaucratese equivalent (see -x)
+
+ -B issue equivalent C code with bugs fixed
+
+ -c simplify/calculate arithmetic expression(s)
+
+ -C remove copyright notice(s)
+
+ -d define new echo switch map
+
+ -D delete all ownership information from system files
+
+ -e evaluate lisp expression(s)
+
+ -E convert ASCII to Navajo
+
+ -f read input from file
+
+ -F transliterate to french
+
+ -g generate pseudo-revolutionary marxist catch-phrases
+
+ -G prepend GNU manifesto
+
+ -h halt system (reboot suppressed on Suns, Apollos, and
+ VAXen, not supported on NOS-2)
+
+ -i emulate IBM OS/VU (recursive universes not supported)
+
+ -I emulate IBM VTOS 3.7.6 (chronosynclastic infundibulae
+ supported with restrictions documented in IBM VTOS
+
+
+
+Printed 10/28/85 18 January 1983 1
+
+
+
+
+
+
+GNUecho(1) UNIX Programmer's Manual GNUecho(1)
+
+
+
+ Reference Manual rev 3.2.6)
+
+ -J generate junk mail
+
+ -j justify text (see -b option)
+
+ -k output "echo" software tools
+
+ -K delete privileged accounts
+
+ -l generate legalese equivalent
+
+ -L load echo modules
+
+ -M generate mail
+
+ -N send output to all reachable networks (usable with -J,
+ -K, -h options)
+
+ -n do not add newline to the output
+
+ -o generate obscene text
+
+ -O clean up dirty language
+
+ -p decrypt and print /etc/passwd
+
+ -P port echo to all reachable networks
+
+ -P1 oolcay itay
+
+ -q query standard input for arguments
+
+ -r read alternate ".echo" file on start up
+
+ -R change root password to "RMS"
+
+ -s suspend operating system during output (Sun and VAX BSD
+ 4.2 only)
+
+ -S translate to swahili
+
+ -T emulate TCP/IP handler
+
+ -t issue troff output
+
+ -u issue unix philosophy essay
+
+ -v generate reverberating echo
+
+ -V print debugging information
+
+
+
+
+Printed 10/28/85 18 January 1983 2
+
+
+
+
+
+
+GNUecho(1) UNIX Programmer's Manual GNUecho(1)
+
+
+
+ -x decrypt DES format messages (NSA secret algorithm CX
+ 3.8, not distributed outside continental US)
+
+ _^HE_^Hc_^Hh_^Ho is useful for producing diagnostics in shell programs
+ and for writing constant data on pipes. To send diagnostics
+ to the standard error file, do `echo ... 1>&2'.
+
+AUTHOR
+ Richard M. Stallman
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Printed 10/28/85 18 January 1983 3
+
diff --git a/etc/emacs.1 b/etc/emacs.1
new file mode 100644
index 00000000000..65bf842960e
--- /dev/null
+++ b/etc/emacs.1
@@ -0,0 +1,513 @@
+.TH EMACS 1 "1990 November 13"
+.UC 4
+.SH NAME
+emacs \- GNU project Emacs
+.SH SYNOPSIS
+.B emacs
+[
+.I command-line switches
+] [
+.I files ...
+]
+.br
+.SH DESCRIPTION
+.I GNU Emacs
+is a new version of
+.I Emacs,
+written by the author of the original (PDP-10)
+.I Emacs,
+Richard Stallman.
+Its user functionality encompasses
+everything other
+.I Emacs
+editors do, and it is easily extensible since its
+editing commands are written in Lisp.
+.PP
+.I Emacs
+has an extensive interactive help facility,
+but the facility assumes that you know how to manipulate
+.I Emacs
+windows and buffers.
+CTRL-h (backspace
+or CTRL-h) enters the Help facility. Help Tutorial (CTRL-h t)
+requests an interactive tutorial which can teach beginners the fundamentals
+of
+.I Emacs
+in a few minutes.
+Help Apropos (CTRL-h a) helps you
+find a command given its functionality, Help Character (CTRL-h c)
+describes a given character's effect, and Help Function (CTRL-h f)
+describes a given Lisp function specified by name.
+.PP
+.I Emacs's
+Undo can undo several steps of modification to your buffers, so it is
+easy to recover from editing mistakes.
+.PP
+.I GNU Emacs's
+many special packages handle mail reading (RMail) and sending (Mail),
+outline editing (Outline), compiling (Compile), running subshells
+within
+.I Emacs
+windows (Shell), running a Lisp read-eval-print loop
+(Lisp-Interaction-Mode), and automated psychotherapy (Doctor).
+.PP
+There is an extensive reference manual, but
+users of other Emacses
+should have little trouble adapting even
+without a copy. Users new to
+.I Emacs
+will be able
+to use basic features fairly rapidly by studying the tutorial and
+using the self-documentation features.
+.PP
+.SM Emacs Options
+.PP
+The following options are of general interest:
+.TP 8
+.I file
+Edit
+.I file.
+.TP
+.BI \+ number
+Go to the line specified by
+.I number
+(do not insert a space between the "+" sign and
+the number).
+.TP
+.B \-q
+Do not load an init file.
+.TP
+.BI \-u " user"
+Load
+.I user's
+init file.
+.TP
+.BI \-t " file"
+Use specified
+.I file
+as the terminal instead of using stdin/stdout.
+This must be the first argument specified in the command line.
+.PP
+The following options are lisp-oriented
+(these options are processed in the order encountered):
+.TP 8
+.BI \-f " function"
+Execute the lisp function
+.I function.
+.TP
+.BI \-l " file"
+Load the lisp code in the file
+.I file.
+.PP
+The following options are useful when running
+.I Emacs
+as a batch editor:
+.TP 8
+.BI \-batch
+Edit in batch mode according to the other command line arguments.
+The editor will send messages to stdout.
+This option must be the first in the argument list.
+.TP
+.B \-kill
+Exit
+.I Emacs
+while in batch mode.
+.\" START DELETING HERE IF YOU'RE NOT USING X
+.PP
+.SM Using Emacs with X
+.PP
+.I Emacs
+has been tailored to work well with the X window system.
+If you run
+.I Emacs
+from under X windows, it will create its own X window to
+display in. You will probably want to start the editor
+as a background process
+so that you can continue using your original window.
+.PP
+.I Emacs
+can be started with the following X switches:
+.TP 8
+.BI \-rn " name"
+Specifies the program name which should be used when looking up
+defaults in the user's X resources. This must be the first option
+specified in the command line.
+.TP 8
+.BI \-wn " name"
+Specifies the name which should be assigned to the
+.I Emacs
+window.
+.TP 8
+.B \-r
+Display the
+.I Emacs
+window in reverse video.
+.TP
+.B \-i
+Use the "kitchen sink" bitmap icon when iconifying the
+.I Emacs
+window.
+.TP
+.BI \-font " font, " \-fn " font"
+Set the
+.I Emacs
+window's font to that specified by
+.I font.
+You will find the various
+.I X
+fonts in the
+.I /usr/lib/X11/fonts
+directory.
+Note that
+.I Emacs
+will only accept fixed width fonts.
+Under the X11 Release 4 font-naming conventions, any font with the
+value "m" or "c" in the eleventh field of the font name is a fixed
+width font. Furthermore, fonts whose name are of the form
+.IR width x height
+are generally fixed width, as is the font
+.IR fixed .
+See
+.IR xlsfonts (1)
+for more information.
+
+When you specify a font, be sure to put a space between the
+switch and the font name.
+.TP
+.BI \-b " pixels"
+Set the
+.I Emacs
+window's border width to the number of pixels specified by
+.I pixels.
+Defaults to one pixel on each side of the window.
+.TP
+.BI \-ib " pixels"
+Set the window's internal border width to the number of pixels specified
+by
+.I pixels.
+Defaults to one pixel of padding on each side of the window.
+.PP
+.TP 8
+.BI \-w " geometry, " \-geometry " geometry"
+Set the
+.I Emacs
+window's width, height, and position as specified. The geometry
+specification is in the standard X format; see
+.IR X (1)
+for more information.
+The width and height are specified in characters; the default is 80 by
+24.
+.PP
+.TP 8
+.BI \-fg " color"
+On color displays, sets the color of the text.
+
+See the file
+.I /usr/lib/X11/rgb.txt
+for a list of valid
+color names.
+.TP
+.BI \-bg " color"
+On color displays,
+sets the color of the window's background.
+.TP
+.BI \-bd " color"
+On color displays,
+sets the color of the window's border.
+.TP
+.BI \-cr " color"
+On color displays,
+sets the color of the window's text cursor.
+.TP
+.BI \-ms " color"
+On color displays,
+sets the color of the window's mouse cursor.
+.TP
+.BI \-d " displayname, " \-display " displayname"
+Create the
+.I Emacs
+window on the display specified by
+.IR displayname .
+Must be the first option specified in the command line.
+.TP
+.B \-nw
+Tells
+.I Emacs
+not to use its special interface to X. If you use this
+switch when invoking
+.I Emacs
+from an
+.IR xterm (1)
+window, display is done in that window.
+This must be the first option specified in the command line.
+.PP
+You can set
+.I X
+default values for your
+.I Emacs
+windows in your
+.I \.Xresources
+file (see
+.IR xrdb (1)).
+Use the following format:
+.IP
+emacs.keyword:value
+.PP
+where
+.I value
+specifies the default value of
+.I keyword.
+.I Emacs
+lets you set default values for the following keywords:
+.TP 8
+.B font (\fPclass\fB Font)
+Sets the window's text font.
+.TP
+.B reverseVideo (\fPclass\fB ReverseVideo)
+If
+.I reverseVideo's
+value is set to
+.I on,
+the window will be displayed in reverse video.
+.TP
+.B bitmapIcon (\fPclass\fB BitmapIcon)
+If
+.I bitmapIcon's
+value is set to
+.I on,
+the window will iconify into the "kitchen sink."
+.TP
+.B borderWidth (\fPclass\fB BorderWidth)
+Sets the window's border width in pixels.
+.TP
+.B internalBorder (\fPclass\fB BorderWidth)
+Sets the window's internal border width in pixels.
+.TP
+.B foreground (\fPclass\fB Foreground)
+For color displays,
+sets the window's text color.
+.TP
+.B background (\fPclass\fB Background)
+For color displays,
+sets the window's background color.
+.TP
+.B borderColor (\fPclass\fB BorderColor)
+For color displays,
+sets the color of the window's border.
+.TP
+.B cursorColor (\fPclass\fB Foreground)
+For color displays,
+sets the color of the window's text cursor.
+.TP
+.B pointerColor (\fPclass\fB Foreground)
+For color displays,
+sets the color of the window's mouse cursor.
+.TP
+.B geometry (\fPclass\fB Geometry)
+Sets the geometry of the
+.I Emacs
+window (as described above).
+.TP
+.B title (\fPclass\fB Title)
+Sets the title of the
+.I Emacs
+window.
+.TP
+.B iconName (\fPclass\fB Title)
+Sets the icon name for the
+.I Emacs
+window icon.
+.PP
+If you try to set color values while using a black and white display,
+the window's characteristics will default as follows:
+the foreground color will be set to black,
+the background color will be set to white,
+the border color will be set to grey,
+and the text and mouse cursors will be set to black.
+.PP
+.SM Using the Mouse
+.PP
+The following lists the mouse button bindings for the
+.I Emacs
+window under X11.
+
+.in +\w'CTRL-SHIFT-middle'u+4n
+.ta \w'CTRL-SHIFT-middle'u+4n
+.ti -\w'CTRL-SHIFT-middle'u+4n
+MOUSE BUTTON FUNCTION
+.br
+.ti -\w'CTRL-SHIFT-middle'u+4n
+left Set point.
+.br
+.ti -\w'CTRL-SHIFT-middle'u+4n
+middle Paste text.
+.br
+.ti -\w'CTRL-SHIFT-middle'u+4n
+right Cut text into X cut buffer.
+.br
+.ti -\w'CTRL-SHIFT-middle'u+4n
+SHIFT-middle Cut text into X cut buffer.
+.br
+.ti -\w'CTRL-SHIFT-middle'u+4n
+SHIFT-right Paste text.
+.br
+.ti -\w'CTRL-SHIFT-middle'u+4n
+CTRL-middle Cut text into X cut buffer and kill it.
+.br
+.ti -\w'CTRL-SHIFT-middle'u+4n
+CTRL-right Select this window, then split it into
+two windows. Same as typing CTRL-x 2.
+.\" START DELETING HERE IF YOU'RE NOT USING X MENUS
+.br
+.ti -\w'CTRL-SHIFT-middle'u+4n
+CTRL-SHIFT-left X buffer menu--hold the buttons and keys
+down, wait for menu to appear, select
+buffer, and release. Move mouse out of
+menu and release to cancel.
+.br
+.ti -\w'CTRL-SHIFT-middle'u+4n
+CTRL-SHIFT-middle X help menu--pop up index card menu for
+Emacs help.
+.\" STOP DELETING HERE IF YOU'RE NOT USING X MENUS
+.br
+.ti -\w'CTRL-SHIFT-middle'u+4n
+CTRL-SHIFT-right Select window with mouse, and delete all
+other windows. Same as typing CTRL-x 1.
+.\" STOP DELETING HERE IF YOU'RE NOT USING X
+.PP
+.SH MANUALS
+You can order printed copies of the GNU Emacs Manual for $20.00/copy
+postpaid from the Free Software Foundation, which develops GNU software.
+Their address is:
+.nf
+ Free Software Foundation
+ 675 Mass Ave.
+ Cambridge, MA 02139
+.fi
+See the file etc/DISTRIB in the Emacs distribution
+for full ordering information.
+Your local Emacs maintainer might also have copies available. As
+with all software and publications from FSF, everyone is permitted to
+make and distribute copies of the Emacs manual. The TeX source to the
+manual is also included in the Emacs source distribution.
+.PP
+.SH FILES
+/usr/local/emacs/src - C source files and object files
+
+/usr/local/emacs/lisp - Lisp source files and compiled files
+that define most editing commands. Some are preloaded;
+others are autoloaded from this directory when used.
+
+/usr/local/emacs/man - sources for the Emacs reference manual.
+
+/usr/local/emacs/etc - various programs that are used with
+GNU Emacs, and some files of information.
+
+/usr/local/emacs/etc/DOC.* - contains the documentation
+strings for the Lisp primitives and preloaded Lisp functions
+of GNU Emacs. They are stored here to reduce the size of
+Emacs proper.
+
+/usr/local/emacs/etc/DISTRIB discusses GNU Emacs distribution and
+contains an order form for all of the software and manuals available
+from the Free Software Foundation.
+
+/usr/local/emacs/etc/DIFF discusses GNU Emacs vs. Twenex Emacs;
+.br
+/usr/local/emacs/etc/CCADIFF discusses GNU Emacs vs. CCA Emacs;
+.br
+/usr/local/emacs/etc/GOSDIFF discusses GNU Emacs vs. Gosling Emacs.
+.br
+/usr/local/emacs/etc/SERVICE lists people offering various services
+to assist users of GNU Emacs, including education, troubleshooting,
+porting and customization.
+.br
+These files also have information useful to anyone wishing to write
+programs in the Emacs Lisp extension language, which is
+documented in the GNU Emacs Lisp Manual.
+
+/usr/local/emacs/info - files for the Info documentation browser
+(a subsystem of Emacs) to refer to. Currently not much of Unix
+is documented here, but the complete text of the Emacs reference
+manual is included in a convenient tree structured form.
+
+/usr/local/emacs/lock - holds lock files that are made for all
+files being modified in Emacs, to prevent simultaneous modification
+of one file by two users.
+
+/usr/local/emacs/cpp - the GNU cpp, needed for building Emacs on
+certain versions of Unix where the standard cpp cannot handle long
+names for macros.
+
+/usr/local/emacs/shortnames - facilities for translating long names to
+short names in C code, needed for building Emacs on certain versions
+of Unix where the C compiler cannot handle long names for functions
+or variables.
+
+.\" START DELETING HERE IF YOU'RE NOT USING X
+/usr/lib/X11/rgb.txt - list of valid X color names.
+.\" STOP DELETING HERE IF YOU'RE NOT USING X
+.PP
+.SH BUGS
+There is a mailing list, bug-gnu-emacs@prep.ai.mit.edu on the internet
+(ucbvax!prep.ai.mit.edu!bug-gnu-emacs on UUCPnet), for reporting Emacs
+bugs and fixes. But before reporting something as a bug, please try
+to be sure that it really is a bug, not a misunderstanding or a
+deliberate feature. We ask you to read the section ``Reporting Emacs
+Bugs'' near the end of the reference manual (or Info system) for hints
+on how and when to report bugs. Also, include the version number of
+the Emacs you are running in \fIevery\fR bug report that you send in.
+
+Do not expect a personal answer to a bug report. The purpose of reporting
+bugs is to get them fixed for everyone in the next release, if possible.
+For personal assistance, look in the SERVICE file (see above) for
+a list of people who offer it.
+
+Please do not send anything but bug reports to this mailing list.
+Send requests to be added to mailing lists to the special list
+info-gnu-emacs-request@prep.ai.mit.edu (or the corresponding UUCP
+address). For more information about Emacs mailing lists, see the
+file /usr/local/emacs/etc/MAILINGLISTS. Bugs tend actually to be
+fixed if they can be isolated, so it is in your interest to report
+them in such a way that they can be easily reproduced.
+.PP
+Bugs that I know about are: shell will not work with programs
+running in Raw mode on some Unix versions.
+.SH UNRESTRICTIONS
+.PP
+.I Emacs
+is free; anyone may redistribute copies of
+.I Emacs
+to
+anyone under the terms stated in the
+.I Emacs
+General Public License,
+a copy of which accompanies each copy of
+.I Emacs
+and which also
+appears in the reference manual.
+.PP
+Copies of
+.I Emacs
+may sometimes be received packaged with distributions of Unix systems,
+but it is never included in the scope of any license covering those
+systems. Such inclusion violates the terms on which distribution
+is permitted. In fact, the primary purpose of the General Public
+License is to prohibit anyone from attaching any other restrictions
+to redistribution of
+.I Emacs.
+.PP
+Richard Stallman encourages you to improve and extend
+.I Emacs,
+and urges that
+you contribute your extensions to the GNU library. Eventually GNU
+(Gnu's Not Unix) will be a complete replacement for Berkeley
+Unix.
+Everyone will be able to use the GNU system for free.
+.SH SEE ALSO
+X(1), xlsfonts(1), xterm(1), xrdb(1)
+.SH AUTHORS
+.PP
+.I Emacs
+was written by Richard Stallman and the Free Software Foundation.
+Joachim Martillo and Robert Krawitz added the X features.
diff --git a/etc/emacs.icon b/etc/emacs.icon
new file mode 100644
index 00000000000..2c348c8a6e5
--- /dev/null
+++ b/etc/emacs.icon
@@ -0,0 +1,34 @@
+/* Format_version=1, Width=64, Height=64, Depth=1, Valid_bits_per_item=16
+ */
+ 0xFFFF,0xFFFF,0xFFFF,0xFFFF,0x8000,0x0000,0x0000,0x0001,
+ 0x8000,0x0000,0x007E,0x1C01,0x8000,0x0000,0x0006,0x1C01,
+ 0x8000,0x0000,0x007F,0xFC01,0x8000,0x0000,0x0080,0x1C01,
+ 0x8000,0x0000,0x013F,0xFC01,0x8000,0x0000,0x0140,0x1C01,
+ 0x8000,0x0000,0x03E0,0x1C01,0x8000,0x0000,0x0000,0x1C01,
+ 0x8000,0x0000,0x0000,0x1C01,0x8000,0x0000,0x0000,0x1C01,
+ 0x8000,0x0000,0x0000,0x1C01,0x8000,0x0000,0x0210,0x1C01,
+ 0x8000,0x0000,0x0330,0x1C01,0x8000,0x0000,0x00C0,0x1C01,
+ 0x8003,0xFFFF,0xFFFF,0xFE01,0x8005,0xFFFF,0xFFFF,0xFE01,
+ 0x8004,0xFFFF,0xFFFF,0xFC01,0x8004,0x787F,0xFFFF,0xF801,
+ 0x8004,0x77FF,0xFFFF,0xF801,0x8000,0x77E3,0x6FFF,0xF801,
+ 0x8000,0x762D,0x6FFF,0xF801,0x8004,0x77AD,0x6FFF,0xF801,
+ 0x800C,0x77AD,0x6FFF,0xF801,0x8004,0x786D,0x8FFF,0xF801,
+ 0x8000,0x7FFF,0xFFFF,0xF801,0x8000,0x7FFF,0xFFFF,0xF801,
+ 0x8000,0x7E0F,0xFFFF,0xF801,0x8008,0x7EFF,0xFFFF,0xF801,
+ 0x800C,0x7EF9,0x31CE,0x3801,0x8004,0x7E1A,0xADB5,0xF801,
+ 0x8000,0x7EFA,0xADBE,0x7801,0x8000,0x7EFB,0xADB7,0xB801,
+ 0x8000,0x7E0B,0xB2CC,0x7801,0x8000,0x7FFF,0xFFFF,0xF801,
+ 0x8004,0x3FFF,0xFFFF,0xF001,0x8004,0x1FFF,0xFFFF,0xE001,
+ 0x800C,0x0003,0x6000,0x0001,0x8000,0x0001,0x43C0,0x0001,
+ 0x8000,0x0001,0x4420,0x0001,0x8000,0x0001,0x4990,0x0001,
+ 0x8000,0x0001,0x4A50,0x0001,0x8004,0x0001,0x3250,0x0001,
+ 0x8004,0x0000,0x8450,0x0001,0x800A,0x0000,0x7850,0x0001,
+ 0x8000,0x0000,0x0050,0x0001,0xFFFF,0xFFFF,0xFFFF,0xFFFF,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
diff --git a/etc/emacs.names b/etc/emacs.names
new file mode 100644
index 00000000000..bae4996ea12
--- /dev/null
+++ b/etc/emacs.names
@@ -0,0 +1,442 @@
+From: harvard!topaz!BLUE!BRAIL@mit-eddie
+Date: 9 Sep 85 17:25:27 EDT
+Subject: EMACS -- What does it mean?
+To: mit-prep!info-gnu-emacs@TOPAZ.RUTGERS.EDU
+
+ EMACS may stand for "Editing MACroS," but some friends of mine
+suggested some more creative definitions. Here they are. Anyone have
+any additions?
+
+--------
+
+Even a
+Master of
+Arts
+Comes
+Simpler
+
+Emacs
+Manuals
+Are
+Cryptic and
+Surreal
+
+Energetic
+Merchants
+Always
+Cultivate
+Sales
+
+Each
+Manual's
+Audience is
+Completely
+Stupified
+
+Emacs
+Means
+A
+Crappy
+Screen
+
+Eventually
+Munches
+All
+Computer
+Storage
+
+Even
+My
+Aunt
+Crashes the
+System
+
+Eradication of
+Memory
+Accomplished with
+Complete
+Simplicity
+
+Elsewhere
+Maybe
+Alternative
+Civilizations
+Survive
+
+Egregious
+Managers
+Actively
+Court
+Stallman
+
+Esoteric
+Malleability
+Always
+Considered
+Silly
+
+Emacs
+Manuals
+Always
+Cause
+Senility
+
+Easily
+Maintained with the
+Assistance of
+Chemical
+Solutions
+
+EMACS
+MACRO
+ACTED
+CREDO
+SODOM
+
+Edwardian
+Manifestation of
+All
+Colonial
+Sins
+
+Generally
+Not
+Used
+
+Except by
+Middle
+Aged
+Computer
+Scientists
+
+Extended
+Macros
+Are
+Considered
+Superfluous
+
+Every
+Mode
+Accelerates
+Creation of
+Software
+
+Elsewhere
+Maybe
+All
+Commands are
+Simple
+
+Emacs
+May
+Allow
+Customised
+Screwups
+
+Excellent
+Manuals
+Are
+Clearly
+Suppressed
+
+Emetic
+Macros
+Assault
+Core and
+Segmentation
+
+Embarrassed
+Manual-Writer
+Accused of
+Communist
+Subversion
+
+Extensibilty and
+Modifiability
+Aggravate
+Confirmed
+Simpletons
+
+Emacs
+May
+Annihilate
+Command
+Structures
+
+Easily
+Mangles,
+Aborts,
+Crashes and
+Stupifies
+
+Extraneous
+Macros
+And
+Commands
+Stink
+
+Exceptionally
+Mediocre
+Algorithm for
+Computer
+Scientists
+
+EMACS
+Makes no
+Allowances
+Considering its
+Stiff price
+
+Equine
+Mammals
+Are
+Considerably
+Smaller
+
+Embarrasingly
+Mundane
+Advertising
+Cuts
+Sales
+
+Every
+Moron
+Assumes
+CCA is
+Superior
+
+Exceptionally
+Mediocre
+Autocratic
+Control
+System
+
+EMACS
+May
+Alienate
+Clients and
+Supporters
+
+Excavating
+Mayan
+Architecture
+Comes
+Simpler
+
+Erasing
+Minds
+Allows
+Complete
+Submission
+
+Every
+Male
+Adolescent
+Craves
+Sex
+
+Elephantine
+Memory
+Absolutely
+Considered
+Sine que non
+
+Emacs
+Makers
+Are
+Crazy
+Sickos
+
+Eenie-Meenie-Miney-Mo-
+Macros
+Are
+Completely
+Slow
+
+Experience the
+Mildest
+Ad
+Campaign ever
+Seen
+
+Emacs
+Makefiles
+Annihilate
+C-
+Shells
+
+Eradication of
+Memory
+Accomplished with
+Complete
+Simplicity
+
+Emetic
+Macros
+Assault
+Core and
+Segmentation
+
+Epileptic
+MLisp
+Aggravates
+Compiler
+Seizures
+
+Eleven thousand
+Monkeys
+Asynchronously
+Crank out these
+Slogans
+-------
+
+From: ihnss!warren@mit-eddie (Warren Montgomery)
+Newsgroups: net.emacs
+Subject: Re: EMACS -- What does it mean?
+Date: Tue, 10-Sep-85 09:14:24 EDT
+Organization: AT&T Bell Labs, Naperville, IL
+Apparently-To: emacs-netnews-distribution@mit-prep
+
+Someone at a luncheon suggested it meant:
+
+Evenings,
+Mornings,
+And a
+Couple of
+Saturdays
+
+(In reference to the odd hours that went into the creation of my
+implementation).
+
+--
+
+ Warren Montgomery
+ ihnss!warren
+ IH ((312)-979) x2494
+
+Date: Wed, 18 Sep 85 10:11:04 edt
+From: inmet!tower@inmet.inmet (Leonard H. Tower Jr.) <inmet!tower@cca-unix>
+Subject: Re: EMACS -- What does it mean?
+To: tower@MIT-PREP.ARPA
+
+Received: by inmet.uucp (4.12/inmet) id AA02199; Wed, 18 Sep 85 09:10:17 edt
+Date: Wed, 18 Sep 85 09:10:17 edt
+Message-Id: <8509181310.AA02199@inmet.uucp>
+Uucp-Paths: {bellcore,ima,ihnp4}!inmet!tower
+Arpa-Path: ima!inmet!tower@CCA-UNIX.ARPA
+Organization: Intermetrics, Inc., Cambridge, MA, USA
+Home: 36 Porter Street, Somerville, MA 02143, USA +1 (617) 623-7739
+/* Written 6:48 pm Sep 14, 1985 by gml@ssc-vax in inmet:net.emacs */
+/* ---------- "Re: EMACS -- What does it mean?" ---------- */
+Pleeeeeeeze!!! Nice try on the meaning of EMACS. I believe the
+correct acronym is:
+
+Emacs
+Makes
+All
+Computing
+Simple
+
+Thank you, and Good Night
+/* End of text from inmet:net.emacs */
+
+From: ho95e!wcs@mit-eddie (Bill.Stewart.4K435.x0705)
+Newsgroups: net.emacs
+Subject: Re: EMACS -- What does it mean?
+Date: Thu, 26-Sep-85 21:43:54 EDT
+Organization: AT&T Bell Labs, Holmdel NJ
+Apparently-To: emacs-netnews-distribution@mit-prep
+
+> > very interesting, but what does GNU stand for ?
+> GNU = Gnu's Not UNIX. There is also MINCE, for Mince Is Not a Complete Emacs.
+> More recursive acronyms, anyone?
+Many people have also seen FINE Is Not Emacs, but the one that has
+character is THief Isn't Even Fine.
+--
+## Bill Stewart, AT&T Bell Labs, Holmdel NJ 1-201-949-0705 ihnp4!ho95c!wcs
+
+Path: mit-eddie!think!harvard!bbnccv!bbncca!linus!decvax!mcnc!ncsu!uvacs!edison!ta2
+From: edison!ta2@mit-eddie (tom allebrandi)
+Newsgroups: net.emacs
+Subject: Re: Re: EMACS -- What does it mean?
+Date: Sun, 29-Sep-85 18:11:55 EDT
+Organization: General Electric's Mountain Resort
+Apparently-To: emacs-netnews-distribution@mit-prep
+
+> GNU = Gnu's Not UNIX. There is also MINCE, for Mince Is Not a Complete Emacs.
+>
+> More recursive acronyms, anyone?
+>
+
+For the DEC-system-10/20: FINE - Fine Is Not Emacs.....
+
+--
+...............
+tom allebrandi 2, general electric aco, charlottesville, va
+{decvax,duke}!mcnc!ncsu!uvacs!edison!ta2
+box 8106, charlottesville, va, 22906
+(804) 978-5566
+...............
+
+Date: Wed, 16 Oct 85 01:38:12 edt
+From: inmet!tower (Leonard H. Tower Jr.) <inmet!tower@cca-unix>
+Subject: more names
+To: tower@MIT-PREP.ARPA
+
+Received: by inmet.uucp (4.12/inmet) id AA12997; Tue, 15 Oct 85 22:31:39 edt
+Date: Tue, 15 Oct 85 22:31:39 edt
+Message-Id: <8510160231.AA12997@inmet.uucp>
+Uucp-Paths: {bellcore,ima,ihnp4}!inmet!tower
+Arpa-Path: ima!inmet!tower@CCA-UNIX.ARPA
+Organization: Intermetrics, Inc., Cambridge, MA, USA
+Home: 36 Porter Street, Somerville, MA 02143, USA +1 (617) 623-7739
+/* Written 12:20 pm Oct 14, 1985 by rs@mirror.UUCP in inmet:net.emacs */
+
+
+SINE: Sine Is Not Emacs
+ (MIT Architecture Machine Group)
+
+EINE: Eine is Not Emacs
+ (MIT Lisp Machine)
+
+ZWEI: Zwei Was Eine Initially
+ ("rev2" of EINE)
+
+--
+Rich $alz {mit-eddie, ihnp4!inmet, wjh12, cca, datacube} !mirror!rs
+Mirror Systems 2067 Massachusetts Ave.
+617-661-0777 Cambridge, MA, 02140
+/* End of text from inmet:net.emacs */
+
+Path: mit-eddie!genrad!panda!talcott!harvard!seismo!gatech!ulysses!pajb
+From: ulysses!pajb@mit-eddie (Paul Bennett)
+Newsgroups: net.emacs
+Subject: Here we go again ...
+Date: Sat, 19-Oct-85 17:26:49 EDT
+Organization: AT&T Bell Laboratories, Murray Hill
+Apparently-To: emacs-netnews-distribution@mit-prep
+
+
+> EINE: Eine is Not Emacs
+> (MIT Lisp Machine)
+>
+> ZWEI: Zwei Was Eine Initially
+> ("rev2" of EINE)
+
+DREI: DREI - Really Emacs Inside
+ (Exists only in my head)
+
+Paul.
+
+UUCP: {decvax,allegra,vax135,ucbvax}!ulysses!circe!pajb
+DDD: (201) 582 7346
+USPS: AT&T Bell Labs, Room 5E-103, Murray Hill, NJ 07974
+
+.. I don't care WHO you are, you're not walking on the water while I'M fishing.--
+Paul.
+
+UUCP: {decvax,allegra,vax135,ucbvax}!ulysses!circe!pajb
+DDD: (201) 582 7346
+USPS: AT&T Bell Labs, Room 5E-103, Murray Hill, NJ 07974
+
+.. I don't care WHO you are, you're not walking on the water while I'M fishing.
diff --git a/etc/emacsclient.c b/etc/emacsclient.c
new file mode 100644
index 00000000000..c46baaf3aba
--- /dev/null
+++ b/etc/emacsclient.c
@@ -0,0 +1,278 @@
+/* Client process that communicates with GNU Emacs acting as server.
+ Copyright (C) 1986, 1987 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#define NO_SHORTNAMES
+#include "../src/config.h"
+#undef read
+#undef write
+#undef open
+#ifdef close
+#undef close
+#endif
+
+
+#if !defined(BSD) && !defined(HAVE_SYSVIPC)
+#include <stdio.h>
+
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ fprintf (stderr, "%s: Sorry, the Emacs server is supported only\n",
+ argv[0]);
+ fprintf (stderr, "on systems with Berkeley sockets or System V IPC.\n");
+ exit (1);
+}
+
+#else /* BSD or HAVE_SYSVIPC */
+
+#if defined(BSD) && ! defined (HAVE_SYSVIPC)
+/* BSD code is very different from SYSV IPC code */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/stat.h>
+
+extern int sys_nerr;
+extern char *sys_errlist[];
+extern int errno;
+
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ char system_name[32];
+ int s, i;
+ FILE *out;
+ struct sockaddr_un server;
+ char *homedir, *cwd, *str;
+ char string[BUFSIZ];
+ struct stat statbfr;
+
+ char *getenv (), *getwd ();
+
+ if (argc < 2)
+ {
+ fprintf (stderr, "Usage: %s filename\n", argv[0]);
+ exit (1);
+ }
+
+ /*
+ * Open up an AF_UNIX socket in this person's home directory
+ */
+
+ if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
+ {
+ fprintf (stderr, "%s: ", argv[0]);
+ perror ("socket");
+ exit (1);
+ }
+ server.sun_family = AF_UNIX;
+#ifndef SERVER_HOME_DIR
+ gethostname (system_name, sizeof (system_name));
+ sprintf (server.sun_path, "/tmp/esrv%d-%s", geteuid (), system_name);
+
+ if (stat (server.sun_path, &statbfr) == -1)
+ {
+ perror ("stat");
+ exit (1);
+ }
+ if (statbfr.st_uid != geteuid())
+ {
+ fprintf (stderr, "Illegal socket owner\n");
+ exit (1);
+ }
+#else
+ if ((homedir = getenv ("HOME")) == NULL)
+ {
+ fprintf (stderr, "%s: No home directory\n", argv[0]);
+ exit (1);
+ }
+ strcpy (server.sun_path, homedir);
+ strcat (server.sun_path, "/.emacs_server");
+#endif
+
+ if (connect (s, &server, strlen (server.sun_path) + 2) < 0)
+ {
+ fprintf (stderr, "%s: ", argv[0]);
+ perror ("connect");
+ exit (1);
+ }
+ if ((out = fdopen (s, "r+")) == NULL)
+ {
+ fprintf (stderr, "%s: ", argv[0]);
+ perror ("fdopen");
+ exit (1);
+ }
+
+ cwd = getwd (string);
+ if (cwd == 0)
+ {
+ /* getwd puts message in STRING if it fails. */
+ fprintf (stderr, "%s: %s (%s)\n", argv[0], string,
+ (errno < sys_nerr) ? sys_errlist[errno] : "unknown error");
+ exit (1);
+ }
+
+ for (i = 1; i < argc; i++)
+ {
+ if (*argv[i] == '+')
+ {
+ char *p = argv[i] + 1;
+ while (*p >= '0' && *p <= '9') p++;
+ if (*p != 0)
+ fprintf (out, "%s/", cwd);
+ }
+ else if (*argv[i] != '/')
+ fprintf (out, "%s/", cwd);
+ fprintf (out, "%s ", argv[i]);
+ }
+ fprintf (out, "\n");
+ fflush (out);
+
+ printf ("Waiting for Emacs...");
+ fflush (stdout);
+
+ rewind (out); /* re-read the output */
+ str = fgets (string, BUFSIZ, out);
+
+ /* Now, wait for an answer and print any messages. */
+
+ while (str = fgets (string, BUFSIZ, out))
+ printf ("%s", str);
+
+ exit (0);
+}
+
+#else /* This is the SYSV IPC section */
+
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/msg.h>
+#include <stdio.h>
+
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ int s;
+ key_t key;
+ struct msgbuf * msgp =
+ (struct msgbuf *) malloc (sizeof *msgp + BUFSIZ);
+ struct msqid_ds * msg_st;
+ char *homedir, buf[BUFSIZ];
+ char gwdirb[BUFSIZ];
+ char *cwd;
+ char *temp;
+ char *getwd (), *getcwd (), *getenv ();
+
+ if (argc < 2)
+ {
+ fprintf (stderr, "Usage: %s filename\n", argv[0]);
+ exit (1);
+ }
+
+ /*
+ * Create a message queue using ~/.emacs_server as the path for ftok
+ */
+ if ((homedir = getenv ("HOME")) == NULL)
+ {
+ fprintf (stderr, "%s: No home directory\n", argv[0]);
+ exit (1);
+ }
+ strcpy (buf, homedir);
+ strcat (buf, "/.emacs_server");
+ creat (buf, 0600);
+ key = ftok (buf, 1); /* unlikely to be anyone else using it */
+ s = msgget (key, 0600 | IPC_CREAT);
+ if (s == -1)
+ {
+ fprintf (stderr, "%s: ", argv[0]);
+ perror ("msgget");
+ exit (1);
+ }
+
+ /* Determine working dir, so we can prefix it to all the arguments. */
+#ifdef BSD
+ temp = getwd (gwdirb);
+#else
+ temp = getcwd (gwdirb, sizeof gwdirb);
+#endif
+
+ cwd = gwdirb;
+ if (temp != 0)
+ {
+ /* On some systems, cwd can look like `@machine/...';
+ ignore everything before the first slash in such a case. */
+ while (*cwd && *cwd != '/')
+ cwd++;
+ strcat (cwd, "/");
+ }
+ else
+ {
+ fprintf (stderr, cwd);
+ exit (1);
+ }
+
+ msgp->mtext[0] = 0;
+ argc--; argv++;
+ while (argc)
+ {
+ if (*argv[0] == '+')
+ {
+ char *p = argv[0] + 1;
+ while (*p >= '0' && *p <= '9') p++;
+ if (*p != 0)
+ strcat (msgp->mtext, cwd);
+ }
+ else if (*argv[0] != '/')
+ strcat (msgp->mtext, cwd);
+
+ strcat (msgp->mtext, argv[0]);
+ strcat (msgp->mtext, " ");
+ argv++; argc--;
+ }
+ strcat (msgp->mtext, "\n");
+ msgp->mtype = 1;
+ if (msgsnd (s, msgp, strlen (msgp->mtext)+1, 0) < 0)
+ {
+ fprintf (stderr, "%s: ", argv[0]);
+ perror ("msgsnd");
+ exit (1);
+ }
+ /*
+ * Now, wait for an answer
+ */
+ printf ("Waiting for Emacs...");
+ fflush (stdout);
+
+ msgrcv (s, msgp, BUFSIZ, getpid (), 0); /* wait for anything back */
+ strcpy (buf, msgp->mtext);
+
+ printf ("\n%s\n", buf);
+ exit (0);
+}
+
+#endif /* HAVE_SYSVIPC */
+
+#endif /* BSD or HAVE_SYSVIPC */
diff --git a/etc/emacstool.1 b/etc/emacstool.1
new file mode 100644
index 00000000000..8cd8165f9c0
--- /dev/null
+++ b/etc/emacstool.1
@@ -0,0 +1,134 @@
+.TH EMACSTOOL 1
+.SH NAME
+.I emacstool
+\- run emacs under Sun windows with function-key and mouse support.
+.SH SYNOPSIS
+.I emacstool
+[{window_args} {-rc run_command_path} args ... ]
+.SH TYPICAL USAGE
+In ~/.suntools or ~/.rootmenu include a line like this:
+.br
+"Emacstool" emacstool -WI emacs.icon -f emacstool-init
+.SH DESCRIPTION
+.B Emacstool
+creates a SunView frame and a tty subwindow within which mouse events
+and function keys are translated to ASCII sequences which Emacs can
+parse. The translated input events are sent to the process running in
+the tty subwindow, which is typically GNU Emacs. Emacstool thereby
+allows GNU Emacs users to make full use of the mouse and function keys.
+GNU Emacs can be loaded with functions to interpret the mouse and
+function-key events to make a truely fine screen oriented editor for
+the Sun Workstation.
+.PP
+(Note that GNU Emacs has a special interface to the X window system as
+well. The X window system has many technical advantages, it is an
+industry standard, and it is also free software. The Free Software
+Foundation urges you to try X windows, and distributes a free copy of
+X on Emacs distribution tapes.)
+.PP
+Function keys are translated to a sequence of the form
+`^X*[a-o][lrt]'. The last character is `l', `r', or `t' corresponding
+to whether the key is among the Left, Right, or Top function keys.
+The third character indicates which button of the group
+was pressed. Thus, the function key in the lower right corner will
+transmit the sequence `^X*or'. In addition, the [lrt] is affected by
+the Control, Meta, and Shift keys. Unshifted Control keys will be
+non-alphabetic: C-l is [,], C-r is [2], C-t is [4].
+.PP
+Mouse buttons are encoded as `^X^@([124] x y)\\n'. ^X^@ is the
+standard GNU Emacs mouse event prefix, it is followed by a list
+indicating the button pressed and the character row and column of the
+point in the window where the mouse cursor is, and followed by a
+newline character. In GNU Emacs, the ^X^@ dispatches to a
+mouse event handler which then reads the following list.
+.SH OPTIONS
+.B Emacstool
+supports all the standard window arguments, including font and icon
+specifiers.
+.PP
+By default, Emacstool runs the program
+.I emacs
+in the created subwindow.
+The value of the environment variable
+.I EMACSTOOL
+can be used to override this if your version of
+.B Emacs
+is not accessible on your search path by the name
+.I Emacs.
+In addition, the run command can be set by the
+.I pathname
+following the last occurence of the
+.I \-rc
+flag.
+This is convenient for using Emacstool to run on remote machines.
+.PP
+All other command line arguments not used by the window system are passed
+as arguments to the program that runs in the Emacstool window.
+.PP
+For example:
+.PP
+local% (emacstool -rc rlogin remote -8 &)&
+.PP
+will create an Emacstool window logged in to a machine named
+.I remote.
+If Emacs is run from this window,
+Emacstool will encode mouse and function keys, and send them to rlogin.
+If Emacs is run from this shell on the remote machine, it will see
+the mouse and function keys properly.
+However, since the remote host does not have access to the screen,
+the cursor cannot be changed, menus will not appear, and the selection
+buffer (STUFF) is limited.
+.SH Using With GNU Emacs:
+The GNU Emacs files
+lisp/term/sun.el,
+lisp/sun-mouse.el,
+lisp/sun-fns.el,
+and
+src/sunfns.c
+provide emacs support for the Emacstool and function keys.
+Emacstool will automatically set the TERM environment variable to be "sun"
+and unset the environment variable TERMCAP. That is, these variables will
+not be inherited from the shell that starts Emacstool.
+Since the terminal type is
+.I SUN
+(that is, the environment variable TERM is set to
+.I SUN),
+Emacs will automatically load the file lisp/term/sun.
+This, in turn, will ensure that sun-mouse.el is autoloaded when any mouse
+events are detected. It is suggested that
+.I sun-mouse
+and
+.I sun-fns
+be loaded in your site-init.el file, so that they will always be loaded
+when running on a Sun workstation.
+.PP
+In addition, Emacstool sets the environment variable IN_EMACSTOOL = "t".
+Lisp code in your ~/.emacs can use (getenv "IN_EMACSTOOL")
+to determine whether to do Emacstool specific initalization.
+Sun.el uses this to automatically call emacstool-init (getenv "IN_EMACSTOOL")
+is defined.
+.PP
+The file src/sunfns.c defines several useful functions for emacs on
+the Sun. Among these are procedures to pop-up SunView
+.I menus,
+put and get from the SunView
+.I STUFF
+buffer, and a procedure for changing the cursor
+.I icon.
+If you want to define or edit cursor icons,
+there is a rudimentary mouse driven icon editor in the file
+lisp/sun-cursors.el. Try invoking (sc:edit-cursor)
+.SH BUGS
+It takes a few milliseconds to create a menu before it pops up.
+.SH ENVIRONMENT VARIABLES
+EMACSTOOL
+IN_EMACSTOOL
+TERM
+TERMCAP
+.SH FILES
+.DT
+emacs
+.SH "SEE ALSO"
+emacs(1)
+ .../etc/SUN-SUPPORT
+ .../lisp/term/sun.el
diff --git a/etc/emacstool.c b/etc/emacstool.c
new file mode 100644
index 00000000000..332ce98ba69
--- /dev/null
+++ b/etc/emacstool.c
@@ -0,0 +1,520 @@
+/* Copyright (C) 1986, 1988, 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* For Emacs in SunView/Sun-Windows: (supported by Sun Unix v3.2 or greater)
+ * Insert a notifier filter-function to convert all useful input
+ * to "key" sequences that emacs can understand. See: Emacstool(1).
+ *
+ * Author: Jeff Peck, Sun Microsystems, Inc. <peck@eng.sun.com>
+ *
+ * Original Idea: Ian Batten
+ * Updated 15-Mar-88, Jeff Peck: set IN_EMACSTOOL, TERM, TERMCAP
+ * Updated 10-Sep-88, Jeff Peck: add XVIEW and JLE support
+ * Updated 8-Oct-90, Jeff Peck: add Meta-bit for Xview
+ * Updated 6-Mar-91, Jeff Peck: Hack to detect -Wt invocation
+ * [note, TTYSW limitation means you must Click-To-Type in Openwin]
+ * [fixed in OW3 or use local/tty.o]
+ * for better results, this should move to using TERMSW.
+ * Updated 30-Mar-91, Jeff Peck, et al: Enable using TERMSW (-DTTERM)
+ * TERMSW understands point-to-type, even in OW2.
+ * Updated 5-Jun-91, Jeff Peck: Meta-key support fixed for OWv3
+ * Better event diagnostics for DEBUGEMACSTOOL
+ *
+ * [note: xvetool should be started with the "-nw" flag for emacs!]
+ */
+
+#ifdef XVIEW
+#include <xview/xview.h>
+#include <xview/panel.h>
+#include <xview/attr.h>
+#include <xview/tty.h>
+#include <xview/ttysw.h> /* private defines */
+#include <xview/termsw.h> /* -DTTERM */
+#include <xview/font.h> /* for testing */
+#else
+#include <suntool/sunview.h>
+#include <suntool/tty.h>
+#include <suntool/ttysw.h>
+#endif /* XVIEW */
+
+#ifdef JLE
+# include <locale.h>
+#endif /* JLE */
+
+#include <stdio.h>
+#include <sys/file.h>
+
+#define BUFFER_SIZE 128 /* Size of all the buffers */
+
+/* define WANT_CAPS_LOCK to make f-key T1 (aka F1) behave as CapsLock */
+#define WANT_CAPS_LOCK
+#ifdef WANT_CAPS_LOCK
+int caps_lock; /* toggle indicater for f-key T1 caps lock */
+static char *Caps = "[CAPS] "; /* Caps Lock prefix string */
+#define CAPS_LEN 7 /* strlen (Caps) */
+#endif
+
+static char *mouse_prefix = "\030\000"; /* C-x C-@ */
+static int m_prefix_length = 2; /* mouse_prefix length */
+
+static char *key_prefix = "\030*"; /* C-x * */
+static int k_prefix_length = 2; /* key_prefix length */
+
+#ifdef JLE
+static char *emacs_name = "nemacs"; /* default run command */
+static char *title = "NEmacstool - "; /* initial title */
+#else
+static char *emacs_name = "emacs"; /* default run command */
+static char *title = "Emacstool - "; /* initial title */
+#endif /* JLE */
+
+static char buffer[BUFFER_SIZE]; /* send to ttysw_input */
+static char *bold_name = 0; /* for -bold option */
+
+Frame frame; /* Base frame for system */
+
+#ifndef TTERM
+#define SWTYPE TTY
+Tty tty_win; /* Where emacs is reading */
+#else
+#define SWTYPE TERMSW
+Termsw tty_win; /* Termsw does follow-mouse */
+#endif /* TTERM */
+
+#ifdef XVIEW
+Xv_Window tty_view; /* Where the events are in Xview*/
+#else
+Tty tty_view; /* SunView place filler */
+#endif /* XVIEW */
+
+int font_width, font_height; /* For translating pixels to chars */
+int left_margin = 0; /* default window -- frame offset */
+
+int console_fd = 0; /* for debugging: setenv DEBUGEMACSTOOL */
+FILE *console; /* for debugging: setenv DEBUGEMACSTOOL */
+
+Icon frame_icon;
+/* make an icon_image for the default frame_icon */
+static short default_image[258] =
+{
+#include <images/terminal.icon>
+};
+mpr_static(icon_image, 64, 64, 1, default_image);
+
+/*
+ * Assign a value to a set of keys
+ */
+int
+button_value (event)
+ Event *event;
+{
+ int retval = 0;
+ /*
+ * Code up the current situation:
+ *
+ * 1 = MS_LEFT;
+ * 2 = MS_MIDDLE;
+ * 4 = MS_RIGHT;
+ * 8 = SHIFT;
+ * 16 = CONTROL;
+ * 32 = META;
+ * 64 = DOUBLE;
+ * 128 = UP;
+ */
+
+ if (MS_LEFT == (event_id (event))) retval = 1;
+ if (MS_MIDDLE == (event_id (event))) retval = 2;
+ if (MS_RIGHT == (event_id (event))) retval = 4;
+
+ if (event_shift_is_down (event)) retval += 8;
+ if (event_ctrl_is_down (event)) retval += 16;
+ if (event_meta_is_down (event)) retval += 32;
+ if (event_is_up (event)) retval += 128;
+ return retval;
+}
+
+/*
+ * Variables to store the time of the previous mouse event that was
+ * sent to emacs.
+ *
+ * The theory is that to time double clicks while ignoreing UP buttons,
+ * we must keep track of the accumulated time.
+ *
+ * If someone writes a SUN-SET-INPUT-MASK for emacstool,
+ * That could be used to selectively disable UP events,
+ * and then this cruft wouldn't be necessary.
+ */
+static long prev_event_sec = 0;
+static long prev_event_usec = 0;
+
+/*
+ * Give the time difference in milliseconds, where one second
+ * is considered infinite.
+ */
+int
+time_delta (now_sec, now_usec, prev_sec, prev_usec)
+ long now_sec, now_usec, prev_sec, prev_usec;
+{
+ long sec_delta = now_sec - prev_sec;
+ long usec_delta = now_usec - prev_usec;
+
+ if (usec_delta < 0) { /* "borrow" a second */
+ usec_delta += 1000000;
+ --sec_delta;
+ }
+
+ if (sec_delta >= 10)
+ return (9999); /* Infinity */
+ else
+ return ((sec_delta * 1000) + (usec_delta / 1000));
+}
+
+
+/*
+ * Filter function to translate selected input events for emacs
+ * Mouse button events become ^X^@(button x-col y-line time-delta) .
+ * Function keys: ESC-*{c}{lrt} l,r,t for Left, Right, Top;
+ * {c} encodes the keynumber as a character [a-o]
+ */
+static Notify_value
+input_event_filter_function (window, event, arg, type)
+#ifdef XVIEW
+ Xv_Window window;
+#else /* not XVIEW */
+ Window window;
+#endif /* XVIEW */
+ Event *event;
+ Notify_arg arg;
+ Notify_event_type type;
+{
+ struct timeval time_stamp;
+
+ /* if DEBUGEMACSTOOL is set, printout event information */
+ if (console_fd) {
+ fprintf(console, "Event: %s%s%c %d %d\n",
+ (event_ctrl_is_down(event) ? "C-" : " "),
+ (event_meta_is_down(event) ? "M-" : " "),
+ (((event_is_button (event)) ? 'M' :
+ ((event_is_key_left (event)) ? 'L' :
+ ((event_is_key_right (event)) ? 'R' :
+ ((event_is_key_top (event)) ? 'T' :
+ (((ASCII_FIRST <= event_id(event))
+ && (event_id(event) <= ASCII_LAST)) ?
+ (((127 & event_id(event)) < 32) ?
+ ((127 & event_id(event)) + 64) :
+ ((127 & event_id(event)))) : '?')))))),
+ event_id(event),
+ event_action(event));
+ }
+ /* UP L1 is the STOP key */
+ if (event_id(event) == WIN_STOP) {
+ ttysw_input(tty_win, "\007\007\007\007\007\007\007", 7);
+ return NOTIFY_IGNORED;
+ }
+
+ /* UP L5 & L7 is Expose & Open, let them pass to sunview */
+ if (event_id(event) == KEY_LEFT(5) || event_id(event) == KEY_LEFT(7))
+ if (event_is_up (event))
+ return notify_next_event_func (window, event, arg, type);
+ else
+ return NOTIFY_IGNORED;
+
+
+ { /* Do the mouse == button events */
+ if (event_is_button (event)) { /* do Mouse Button events */
+ time_stamp = event_time (event);
+ ttysw_input (tty_win, mouse_prefix, m_prefix_length);
+ sprintf (buffer, "(%d %d %d %d)\015",
+ button_value (event),
+ (event_x (event) - left_margin) / font_width,
+ event_y (event) / font_height,
+ time_delta (time_stamp.tv_sec, time_stamp.tv_usec,
+ prev_event_sec, prev_event_usec)
+ );
+ ttysw_input (tty_win, buffer, strlen(buffer));
+ prev_event_sec = time_stamp.tv_sec;
+ prev_event_usec = time_stamp.tv_usec;
+ return NOTIFY_IGNORED;
+ }
+ }
+ { /* Do the function key events */
+ int d;
+ char c = (char) 0;
+ if ((event_is_key_left (event)) ?
+ ((d = event_id(event) - KEY_LEFT(1) + 'a'), c='l') :
+ ((event_is_key_right (event)) ?
+ ((d = event_id(event) - KEY_RIGHT(1) + 'a'), c='r') :
+ ((event_is_key_top (event)) ?
+ ((d = event_id(event) - KEY_TOP(1) + 'a'), c='t') : 0))) {
+ if (event_is_up(event)) return NOTIFY_IGNORED;
+ if (event_shift_is_down (event)) c = c - 32;
+ /* this will give a non-{lrt} for unshifted keys */
+ if (event_ctrl_is_down (event)) c = c - 64;
+ if (event_meta_is_down (event)) c = c + 128;
+#ifdef WANT_CAPS_LOCK
+ /* set a toggle and relabel window so T1 can act like caps-lock */
+ if (event_id(event) == KEY_TOP(1)) {
+ /* make a frame label with and without CAPS */
+ strcpy (buffer, Caps);
+ title = &buffer[CAPS_LEN];
+ strncpy (title, (char *)window_get (frame, FRAME_LABEL),
+ BUFFER_SIZE - CAPS_LEN);
+ buffer[BUFFER_SIZE] = (char) 0;
+ if (strncmp (title, Caps, CAPS_LEN) == 0)
+ title += CAPS_LEN; /* already Caps */
+ caps_lock = (caps_lock ? 0 : CAPS_LEN);
+ window_set(frame, FRAME_LABEL, (title -= caps_lock), 0);
+ return NOTIFY_IGNORED;
+ }
+#endif /* WANT_CAPS_LOCK */
+ ttysw_input (tty_win, key_prefix, k_prefix_length);
+ sprintf (buffer, "%c%c", d, c);
+ ttysw_input(tty_win, buffer, strlen(buffer));
+
+ return NOTIFY_IGNORED;
+ }
+ }
+
+ /* handle ascii keyboard events
+ * extract "event_is_ascii(event)" from the event_id, not the event_action
+ */
+ if ((ASCII_FIRST <= event_id(event)) && (event_id(event) <= ASCII_LAST)) {
+ /* ignore key-up events (button events have already been handled) */
+ if (event_is_up(event)) return NOTIFY_IGNORED;
+#ifdef WANT_CAPS_LOCK
+ /* shift alpha chars to upper case if toggle is set */
+ if ((caps_lock) && (event_id(event) >= 'a') && (event_id(event) <= 'z'))
+ event_set_id(event, (event_id(event) - 32));
+#endif /* WANT_CAPS_LOCK */
+
+#ifndef NO_META_BIT
+ /* under Openwindows/X, the meta bit is not set in the key event,
+ * emacs expects this so we add it in here:
+ */
+ if (event_meta_is_down(event))
+ event_set_id(event, 128 | event_id(event));
+#endif /* NO_META_BIT */
+ }
+ return notify_next_event_func (window, event, arg, type);
+}
+
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ int error_code; /* Error codes */
+
+#ifdef JLE
+ setlocale(LC_ALL, "");
+#endif /* JLE */
+
+ if(getenv("DEBUGEMACSTOOL"))
+ console = fdopen (console_fd = open("/dev/console",O_WRONLY), "w");
+
+ putenv("IN_EMACSTOOL=t"); /* notify subprocess that it is in emacstool */
+
+ if (putenv("TERM=sun") != 0) /* TTY_WIN will be a TERM=sun window */
+ {fprintf (stderr, "%s: Could not set TERM=sun, using `%s'\n",
+ argv[0], (char *)getenv("TERM")) ;};
+ /*
+ * If TERMCAP starts with a slash, it is the pathname of the
+ * termcap file, not an entry extracted from it, so KEEP it!
+ * Otherwise, it may not relate to the new TERM, so Nuke-It.
+ * If there is no TERMCAP environment variable, don't make one.
+ */
+ {
+ char *termcap ; /* Current TERMCAP value */
+ termcap = (char *)getenv("TERMCAP") ;
+ if (termcap && (*termcap != '/'))
+ {
+ if (putenv("TERMCAP=") != 0)
+ {fprintf (stderr, "%s: Could not clear TERMCAP\n", argv[0]) ;} ;
+ } ;
+ } ;
+
+ /* find command to run as subprocess in window */
+ if (!(argv[0] = (char *)getenv("EMACSTOOL"))) /* Set emacs command name */
+ argv[0] = emacs_name;
+ /* Emacstool recognizes two special args: -rc <file> and -bold <bold-name> */
+ for (argc = 1; argv[argc]; argc++) /* Use last one on line */
+ {
+ if(!(strcmp ("-rc", argv[argc]))) /* Override if -rc given */
+ {int i = argc;
+ argv[argc--]=0; /* kill the -rc argument */
+ if (argv[i+1]) { /* move to argv[0] and squeeze the rest */
+ argv[0]=argv[i+1];
+ for (; argv[i+2]; (argv[i]=argv[i+2],argv[++i]=0));
+ }
+ }
+
+ if (!(strcmp ("-bold", argv[argc])))
+ {int i = argc;
+ argv[argc--]=0; /* kill the -bold argument */
+ if (argv[i+1]) { /* move to bold_name and squeeze the rest */
+ bold_name = argv[i+1];
+ for (; argv[i+2]; (argv[i]=argv[i+2],argv[++i]=0));
+ }
+ }
+ };
+
+ strcpy (buffer, title);
+ strncat (buffer, argv[0], /* append run command name */
+ (BUFFER_SIZE - (strlen (buffer)) - (strlen (argv[0]))) - 1);
+
+ error_code = interpose_on_window(argc,argv);
+ if (error_code != 0) { /* Barf */
+ fprintf (stderr, "notify_interpose_event_func returns %d.\n", error_code);
+ exit (1);
+ }
+
+#ifdef XVIEW
+ xv_main_loop (frame); /* And away we go */
+#else
+ window_main_loop (frame);
+#endif /* XVIEW */
+}
+
+#ifdef XVIEW
+int interpose_on_window(argc,argv)
+ int argc;
+ char **argv;
+{
+#ifndef TTERM
+#ifdef FONT_WIDTH_ADJUST
+ int i, font_width_adjust = 1; /* hackery, and hueristics */
+ /* If -Wt is not supplied, OWv2 font defaults as lucidasans-12 (width=8)
+ * rather than the lucidasanstypewriter (width=7) actually used by ttysw.
+ * This hack attempts to workaround it.
+ */
+ for (i = 1; argv[i]; i++) {
+ if (!(strcmp ("-Wt", argv[i])) || !(strcmp ("-font", argv[i])))
+ {font_width_adjust = 0;
+ if (console_fd) fprintf(console, "-Wt = %d\n", font_width_adjust);
+ break;}
+ }
+#endif /* FONT_WIDTH_ADJUST */
+#endif /* not TTERM */
+ /* initialize Xview, and strip window args */
+ xv_init(XV_INIT_ARGC_PTR_ARGV, &argc, argv, 0);
+
+ /* do this first, so arglist can override it */
+ frame_icon = icon_create (ICON_LABEL, "Emacstool",
+ ICON_IMAGE, &icon_image,
+ 0);
+
+ /* Build a frame to run in */
+ frame = xv_create ((Xv_Window)NULL, FRAME,
+ FRAME_LABEL, buffer,
+ FRAME_ICON, frame_icon,
+ 0);
+
+ /* Create a tty with emacs in it */
+ tty_win = xv_create (frame, SWTYPE, WIN_IS_CLIENT_PANE,
+ TTY_QUIT_ON_CHILD_DEATH, TRUE,
+ TTY_BOLDSTYLE, TTYSW_BOLD_INVERT,
+ TTY_ARGV, argv,
+ 0);
+
+ if (bold_name) {
+ (void)xv_set(tty_win, TTY_BOLDSTYLE_NAME, bold_name, 0);
+ }
+
+ {
+ Xv_font font; /* declare temp font variable */
+ font = (Xv_font)xv_get (tty_win, XV_FONT);
+ font_height = (int)xv_get (font, FONT_DEFAULT_CHAR_HEIGHT);
+ font_width = (int)xv_get (font, FONT_DEFAULT_CHAR_WIDTH);
+ }
+ if (console_fd) fprintf(console, "Width = %d\n", font_width);
+
+#ifndef TTERM
+#ifdef FONT_WIDTH_ADJUST
+ font_width -= font_width_adjust; /* A guess! font cache bug in ttysw*/
+#endif /* FONT_WIDTH_ADJUST */
+#else
+ /* make the termsw act as a tty */
+ xv_set(tty_win, TERMSW_MODE, TTYSW_MODE_TYPE, 0);
+ /* termsw has variable offset depending on scrollbar size/location */
+ left_margin = (int)xv_get (tty_win, TEXTSW_LEFT_MARGIN);
+#endif /* TTERM */
+
+ tty_view = (Xv_Window) xv_get (tty_win, OPENWIN_NTH_VIEW, 0);
+ xv_set(tty_view,
+ WIN_CONSUME_EVENTS,
+ WIN_MOUSE_BUTTONS, WIN_UP_EVENTS,
+ ACTION_ADJUST, ACTION_MENU,
+ WIN_ASCII_EVENTS,
+ WIN_LEFT_KEYS, WIN_TOP_KEYS, WIN_RIGHT_KEYS,
+ 0,
+ 0);
+ /* Interpose my event function */
+ return (int) notify_interpose_event_func
+ (tty_view, input_event_filter_function, NOTIFY_SAFE);
+}
+#else /* not XVIEW */
+int interpose_on_window (argc, argv)
+ int argc;
+ char **argv;
+{
+ /* do this first, so arglist can override it */
+ frame_icon = icon_create (ICON_LABEL, "Emacstool",
+ ICON_IMAGE, &icon_image,
+ 0);
+
+ /* Build a frame to run in */
+ frame = window_create ((Window)NULL, FRAME,
+ FRAME_LABEL, buffer,
+ FRAME_ICON, frame_icon,
+ FRAME_ARGC_PTR_ARGV, &argc, argv,
+ 0);
+
+ /* Create a tty with emacs in it */
+ tty_win = window_create (frame, TTY,
+ TTY_QUIT_ON_CHILD_DEATH, TRUE,
+ TTY_BOLDSTYLE, TTYSW_BOLD_INVERT,
+ TTY_ARGV, argv,
+ 0);
+
+ if (bold_name) {
+ (void)window_set(tty_win, TTY_BOLDSTYLE_NAME, bold_name, 0);
+ }
+
+ /* ttysw uses pf_default, one must set WIN_FONT explicitly */
+ window_set (tty_win, WIN_FONT, pf_default(), 0);
+ font_height = (int)window_get (tty_win, WIN_ROW_HEIGHT);
+ font_width = (int)window_get (tty_win, WIN_COLUMN_WIDTH);
+
+ tty_view = tty_win;
+ window_set(tty_view,
+ WIN_CONSUME_PICK_EVENTS,
+ WIN_STOP,
+ WIN_MOUSE_BUTTONS, WIN_UP_EVENTS,
+ /* LOC_WINENTER, LOC_WINEXIT, LOC_MOVE, */
+ 0,
+ WIN_CONSUME_KBD_EVENTS,
+ WIN_STOP,
+ WIN_ASCII_EVENTS,
+ WIN_LEFT_KEYS, WIN_TOP_KEYS, WIN_RIGHT_KEYS,
+ /* WIN_UP_ASCII_EVENTS, */
+ 0,
+ 0);
+ /* Interpose my event function */
+ return (int) notify_interpose_event_func
+ (tty_view, input_event_filter_function, NOTIFY_SAFE);
+}
+#endif /* XVIEW */
diff --git a/etc/env.c b/etc/env.c
new file mode 100644
index 00000000000..32d4826653b
--- /dev/null
+++ b/etc/env.c
@@ -0,0 +1,326 @@
+/* env.c - manipulate environment and execute a program
+ in that environment
+ Mly 861126
+
+ Copyright (C) 1986 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ In other words, you are welcome to use, share and improve this program.
+ You are forbidden to forbid anyone else to use, share and improve
+ what you give them. Help stamp out software-hoarding! */
+
+/*
+
+ If first argument is "-", then a new environment is constructed
+ from scratch; otherwise the environment is inherited from the parent
+ process, except as modified by other options.
+
+ So, "env - foo" will invoke the "foo" program in a null environment,
+ whereas "env foo" would invoke "foo" in the same environment as that
+ passed to "env" itself.
+
+ Subsequent arguments are interpreted as follows:
+
+ * "variable=value" (ie an arg containing a "=" character)
+ means to set the specified environment variable to that value.
+ `value' may be of zero length ("variable="). Note that setting
+ a variable to a zero-length value is different from unsetting it.
+
+ * "-u variable" or "-unset variable"
+ means to unset that variable
+ If that variable isn't set, does nothing.
+
+ * "-s variable value" or "-set variable value"
+ same as "variable=value"
+
+ * "-" or "--"
+ are used to indicate that the following argument is the program
+ to invoke. This is only necessary when the program's name
+ begins with "-" or contains a "="
+
+ * anything else
+ The first remaining argument specifies a program to invoke
+ (it is searched for according to the specification of the PATH
+ environment variable) and any arguments following that are
+ passed as arguments to that program
+
+ If no program-name is specified following the environment
+ specifications the the resulting environment is printed
+ (The is like specifying a program-name of "printenv")
+
+ Examples:
+ If the environment passed to "env" is
+ { USER=rms EDITOR=emacs PATH=.:/gnubin:/hacks }
+
+ * "env DISPLAY=gnu:0 nemacs"
+ calls "nemacs" in the envionment
+ { EDITOR=emacs USER=rms DISPLAY=gnu }
+
+ * "env - USER=foo /hacks/hack bar baz"
+ will call the "hack" program on arguments "bar" and "baz"
+ in an environment in which the only variable is "USER"
+ Note that the "-" option will clear out the PATH variable,
+ so one should be careful to specify in which directory
+ to find the program to call
+
+ * "env -u EDITOR USER=foo PATH=/energy -- e=mc2 bar baz"
+ The program "/energy/e=mc2" is called with environment
+ { USER=foo PATH=/energy }
+
+*/
+
+#ifdef EMACS
+#define NO_SHORTNAMES
+#include "../src/config.h"
+#endif /* EMACS */
+
+#include <stdio.h>
+#include <errno.h>
+
+extern int execvp ();
+extern char *index ();
+
+char *xmalloc (), *xrealloc ();
+char *concat ();
+
+extern char **environ;
+
+char **nenv;
+int nenv_size;
+
+char *progname;
+void setenv ();
+void fatal ();
+
+main (argc, argv, envp)
+ register int argc;
+ register char **argv;
+ char **envp;
+{
+ register char *tem;
+
+ progname = argv[0];
+ argc--;
+ argv++;
+
+ nenv_size = 100;
+ nenv = (char **) xmalloc (nenv_size * sizeof (char *));
+ *nenv = (char *) 0;
+
+ /* "-" flag means to not inherit parent's environment */
+ if (argc && !strcmp (*argv, "-"))
+ {
+ argc--;
+ argv++;
+ }
+ else
+ /* Else pass on existing env vars. */
+ for (; *envp; envp++)
+ {
+ tem = index (*envp, '=');
+ if (tem)
+ {
+ *tem = '\000';
+ setenv (*envp, tem + 1);
+ }
+ }
+
+ while (argc > 0)
+ {
+ tem = index (*argv, '=');
+ if (tem)
+ /* If arg contains a "=" it specifies to set a variable */
+ {
+ *tem = '\000';
+ setenv (*argv, tem + 1);
+ argc--; argv++;
+ continue;
+ }
+
+ if (**argv != '-')
+ /* Remaining args are program name and args to pass it */
+ break;
+
+ if (argc < 2)
+ fatal ("No argument following \"%s\" switch", *argv);
+ if (!strcmp (*argv, "-u") ||
+ !strcmp (*argv, "-unset"))
+ /* Unset a variable */
+ {
+ argc--; argv++;
+ setenv (*argv, 0);
+ argc--; argv++;
+ }
+ else if (!strcmp (*argv, "-s") ||
+ !strcmp (*argv, "-set"))
+ /* Set a variable */
+ {
+ argc--; argv++;
+ tem = *argv;
+ if (argc < 2)
+ fatal ("No value specified for variable \"%s\"",
+ tem);
+ argc--; argv++;
+ setenv (tem, *argv);
+ argc--; argv++;
+ }
+ else if (!strcmp (*argv, "-") || !strcmp (*argv, "--"))
+ {
+ argc--; argv++;
+ break;
+ }
+ else
+ {
+ fatal ("unknown switch \"%s\"", *argv);
+ }
+ }
+
+ /* If no program specified print the environment and exit */
+ if (argc <= 0)
+ {
+ while (*nenv)
+ printf ("%s\n", *nenv++);
+ exit (0);
+ }
+ else
+ {
+ extern int errno, sys_nerr;
+ extern char *sys_errlist[];
+
+ environ = nenv;
+ (void) execvp (*argv, argv);
+
+ fprintf (stderr, "%s: Cannot execute \"%s\"",
+ progname, *argv);
+ if (errno < sys_nerr)
+ fprintf (stderr, ": %s\n" , sys_errlist[errno]);
+ else
+ putc ('\n', stderr);
+ exit (errno != 0 ? errno : 1);
+ }
+}
+
+void
+setenv (var, val)
+ register char *var, *val;
+{
+ register char **e;
+ int len = strlen (var);
+
+ {
+ register char *tem = index (var, '=');
+ if (tem)
+ fatal ("Environment variable names may not contain \"=\": %s",
+ var);
+ else if (*var == '\000')
+ fatal ("Zero-length environment variable name specified.");
+ }
+
+ for (e = nenv; *e; e++)
+ if (!strncmp (var, *e, len) &&
+ (*e)[len] == '=')
+ {
+ if (val)
+ goto set;
+ else
+ do { *e = *(e + 1); } while (*e++);
+ return;
+ }
+
+ if (!val)
+ return; /* Nothing to unset */
+
+ len = e - nenv;
+ if (len + 1 >= nenv_size)
+ {
+ nenv_size += 100;
+ nenv = (char **) xrealloc (nenv, nenv_size * sizeof (char *));
+ e = nenv + len;
+ }
+
+ set:
+ val = concat (var, "=", val);
+ if (*e)
+ free (*e);
+ else
+ *(e + 1) = (char *) 0;
+ *e = val;
+ return;
+}
+
+void
+fatal (msg, arg1, arg2)
+ char *msg, *arg1, *arg2;
+{
+ fprintf (stderr, "%s: ", progname);
+ fprintf (stderr, msg, arg1, arg2);
+ putc ('\n', stderr);
+ exit (1);
+}
+
+
+extern char *malloc (), *realloc ();
+
+void
+memory_fatal ()
+{
+ fatal ("Out of memory");
+}
+
+char *
+xmalloc (size)
+ int size;
+{
+ register char *value;
+ value = (char *) malloc (size);
+ if (!value) memory_fatal ();
+ return (value);
+}
+
+char *
+xrealloc (ptr, size)
+ char *ptr;
+ int size;
+{
+ register char *value;
+ value = (char *) realloc (ptr, size);
+ if (!value) memory_fatal ();
+ return (value);
+}
+
+/* Return a newly-allocated string whose contents concatenate those of s1, s2, s3. */
+
+char *
+concat (s1, s2, s3)
+ char *s1, *s2, *s3;
+{
+ int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
+ char *result = (char *) xmalloc (len1 + len2 + len3 + 1);
+
+ strcpy (result, s1);
+ strcpy (result + len1, s2);
+ strcpy (result + len1 + len2, s3);
+ *(result + len1 + len2 + len3) = 0;
+
+ return result;
+}
+
+
+/*
+ * Local variables:
+ * compile-command: "cc -g -o env env.c"
+ * end:
+ */
diff --git a/lib-src/etags-vmslib.c b/etc/etags-vmslib.c
index 0aa5bf6cc5d..cb5a02684f2 100644
--- a/lib-src/etags-vmslib.c
+++ b/etc/etags-vmslib.c
@@ -1,49 +1,21 @@
/* File name wild card expansion for VMS.
This file is part of the etags program.
Copyright (C) 1987 Free Software Foundation, Inc. 3 Feb 1987
-
-This program is distributed in the hope that it will be useful,
-but without any warranty. No author or distributor
-accepts responsibility to anyone for the consequences of using it
-or for whether it serves any particular purpose or works at all,
-unless he says so in writing.
-
- Permission is granted to anyone to distribute verbatim copies
- of this program's source code as received, in any medium, provided that
- the copyright notice, the nonwarraty notice above
- and this permission notice are preserved,
- and that the distributor grants the recipient all rights
- for further redistribution as permitted by this notice,
- and informs him of these rights.
-
- Permission is granted to distribute modified versions of this
- program's source code, or of portions of it, under the above
- conditions, plus the conditions that all changed files carry
- prominent notices stating who last changed them and that the
- derived material, including anything packaged together with it and
- conceptually functioning as a modification of it rather than an
- application of it, is in its entirety subject to a permission
- notice identical to this one.
-
- Permission is granted to distribute this program (verbatim or
- as modified) in compiled or executable form, provided verbatim
- redistribution is permitted as stated above for source code, and
- A. it is accompanied by the corresponding machine-readable
- source code, under the above conditions, or
- B. it is accompanied by a written offer, with no time limit,
- to distribute the corresponding machine-readable source code,
- under the above conditions, to any one, in return for reimbursement
- of the cost of distribution. Verbatim redistribution of the
- written offer must be permitted. Or,
- C. it is distributed by someone who received only the
- compiled or executable form, and is accompanied by a copy of the
- written offer of source code which he received along with it.
-
- Permission is granted to distribute this program (verbatim or as modified)
- in executable form as part of a larger system provided that the source
- code for this program, including any modifications used,
- is also distributed or offered as stated in the preceding paragraph.
-
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
In other words, you are welcome to use, share and improve this program.
You are forbidden to forbid anyone else to use, share and improve
what you give them. Help stamp out software-hoarding! */
@@ -135,7 +107,7 @@ fn_exp(out, in)
if (pass1)
{
pass1 = NO;
- o.dsc$a_pointer = out;
+ o.dsc$a_pointer = (char *) out;
o.dsc$w_length = (short)OUTSIZE;
i.dsc$a_pointer = in;
i.dsc$w_length = (short)strlen(in);
diff --git a/etc/etags.c b/etc/etags.c
new file mode 100644
index 00000000000..20ed3424151
--- /dev/null
+++ b/etc/etags.c
@@ -0,0 +1,1631 @@
+/* Tags file maker to go with GNUmacs
+ Copyright (C) 1984, 1987, 1988 Free Software Foundation, Inc. and Ken Arnold
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+In other words, you are welcome to use, share and improve this program.
+You are forbidden to forbid anyone else to use, share and improve
+what you give them. Help stamp out software-hoarding! */
+
+#include <stdio.h>
+#include <ctype.h>
+
+/* Define the symbol ETAGS to make the program "etags",
+ which makes emacs-style tag tables by default.
+ Define CTAGS to make the program "ctags" compatible with the usual one.
+ Define neither one to get behavior that depends
+ on the name with which the program is invoked
+ (but we don't normally compile it that way). */
+
+/* On VMS, CTAGS is not useful, so always do ETAGS. */
+#ifdef VMS
+#ifndef ETAGS
+#define ETAGS
+#endif
+#endif
+
+/* Exit codes for success and failure. */
+
+#ifdef VMS
+#define GOOD (1)
+#define BAD (0)
+#else
+#define GOOD (0)
+#define BAD (1)
+#endif
+
+#define reg register
+#define logical char
+
+#define TRUE (1)
+#define FALSE (0)
+
+#define iswhite(arg) (_wht[arg]) /* T if char is white */
+#define begtoken(arg) (_btk[arg]) /* T if char can start token */
+#define intoken(arg) (_itk[arg]) /* T if char can be in token */
+#define endtoken(arg) (_etk[arg]) /* T if char ends tokens */
+#define isgood(arg) (_gd[arg]) /* T if char can be after ')' */
+
+#define max(I1,I2) (I1 > I2 ? I1 : I2)
+
+/* cause token checking for typedef, struct, union, enum to distinguish
+ keywords from identifier-prefixes (e.g. struct vs struct_tag). */
+#define istoken(s, tok, len) (!strncmp(s,tok,len) && endtoken(*((s)+(len))))
+
+struct nd_st { /* sorting structure */
+ char *name; /* function or type name */
+ char *file; /* file name */
+ logical f; /* use pattern or line no */
+ int lno; /* line number tag is on */
+ long cno; /* character number line starts on */
+ char *pat; /* search pattern */
+ logical been_warned; /* set if noticed dup */
+ struct nd_st *left,*right; /* left and right sons */
+};
+
+long ftell();
+typedef struct nd_st NODE;
+
+int number; /* tokens found so far on line starting with # (including #) */
+logical gotone, /* found a func already on line */
+ /* boolean "func" (see init) */
+ _wht[0177],_etk[0177],_itk[0177],_btk[0177],_gd[0177];
+
+ /* typedefs are recognized using a simple finite automata,
+ * tydef is its state variable.
+ */
+typedef enum {none, begin, tag_ok, middle, end } TYST;
+
+TYST tydef = none;
+
+logical next_token_is_func;
+
+char searchar = '/'; /* use /.../ searches */
+
+int lineno; /* line number of current line */
+long charno; /* current character number */
+long linecharno; /* character number of start of line */
+
+char *curfile, /* current input file name */
+ *outfile= 0, /* output file */
+ *white = " \f\t\n", /* white chars */
+ *endtk = " \t\n\"'#()[]{}=-+%*/&|^~!<>;,.:?",
+ /* token ending chars */
+ *begtk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$",
+ /* token starting chars */
+ *intk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789",
+ /* valid in-token chars */
+ *notgd = ",;"; /* non-valid after-function chars */
+
+int file_num = 0; /* current file number */
+int aflag = 0; /* -a: append to tags */
+int tflag = 0; /* -t: create tags for typedefs */
+int uflag = 0; /* -u: update tags */
+int wflag = 0; /* -w: suppress warnings */
+int vflag = 0; /* -v: create vgrind style index output */
+int xflag = 0; /* -x: create cxref style output */
+int eflag = 0; /* -e: emacs style output */
+
+/* Name this program was invoked with. */
+char *progname;
+
+FILE *inf, /* ioptr for current input file */
+ *outf; /* ioptr for tags file */
+
+NODE *head; /* the head of the sorted binary tree */
+
+char *savestr();
+char *savenstr ();
+char *rindex();
+char *index();
+char *concat ();
+void initbuffer ();
+long readline ();
+
+/* A `struct linebuffer' is a structure which holds a line of text.
+ `readline' reads a line from a stream into a linebuffer
+ and works regardless of the length of the line. */
+
+struct linebuffer
+ {
+ long size;
+ char *buffer;
+ };
+
+struct linebuffer lb, lb1;
+
+#if 0 /* VMS now provides the `system' function. */
+#ifdef VMS
+
+#include <descrip.h>
+
+void
+system (buf)
+ char *buf;
+{
+ struct dsc$descriptor_s command =
+ {
+ strlen(buf), DSC$K_DTYPE_T, DSC$K_CLASS_S, buf
+ };
+
+ LIB$SPAWN(&command);
+}
+#endif /* VMS */
+#endif /* 0 */
+
+main(ac,av)
+ int ac;
+ char *av[];
+{
+ char cmd[100];
+ int i;
+ int fflag = 0;
+ char *this_file;
+#ifdef VMS
+ char got_err;
+
+ extern char *gfnames();
+ extern char *massage_name();
+#endif
+
+ progname = av[0];
+
+#ifdef ETAGS
+ eflag = 1;
+#else
+ eflag = 0;
+#endif
+
+ while (ac > 1 && av[1][0] == '-')
+ {
+ for (i=1; av[1][i]; i++)
+ {
+ switch(av[1][i])
+ {
+#ifndef VMS /* These options are useful only with ctags,
+ and VMS can't input them, so just omit them. */
+ case 'B':
+ searchar='?';
+ eflag = 0;
+ break;
+ case 'F':
+ searchar='/';
+ eflag = 0;
+ break;
+#endif
+ case 'a':
+ aflag++;
+ break;
+ case 'e':
+ eflag++;
+ break;
+ case 'f':
+ if (fflag > 0)
+ {
+ fprintf(stderr,
+ "%s: -f flag may only be given once\n", progname);
+ goto usage;
+ }
+ fflag++, ac--; av++;
+ if (ac <= 1 || av[1][0] == '\0')
+ {
+ fprintf(stderr,
+ "%s: -f flag must be followed by a filename\n",
+ progname);
+ goto usage;
+ }
+ outfile = av[1];
+ goto end_loop;
+ case 't':
+ tflag++;
+ break;
+#ifndef VMS
+ case 'u':
+ uflag++;
+ eflag = 0;
+ break;
+#endif
+ case 'w':
+ wflag++;
+ break;
+ case 'v':
+ vflag++;
+ xflag++;
+ eflag = 0;
+ break;
+ case 'x':
+ xflag++;
+ eflag = 0;
+ break;
+ default:
+ goto usage;
+ }
+ }
+ end_loop: ;
+ ac--; av++;
+ }
+
+ if (ac <= 1)
+ {
+ usage:
+#ifdef VMS
+ fprintf (stderr, "Usage: %s [-aetwvx] [-f outfile] file ...\n", progname);
+#else
+ fprintf (stderr, "Usage: %s [-BFaetuwvx] [-f outfile] file ...\n", progname);
+#endif
+ exit(BAD);
+ }
+
+ if (outfile == 0)
+ {
+ outfile = eflag ? "TAGS" : "tags";
+ }
+
+ init(); /* set up boolean "functions" */
+
+ initbuffer (&lb);
+ initbuffer (&lb1);
+ /*
+ * loop through files finding functions
+ */
+ if (eflag)
+ {
+ outf = fopen (outfile, aflag ? "a" : "w");
+ if (!outf)
+ {
+ fprintf (stderr, "%s: ", progname);
+ perror (outfile);
+ exit (BAD);
+ }
+ }
+
+ file_num = 1;
+#ifdef VMS
+ for (ac--, av++;
+ (this_file = gfnames (&ac, &av, &got_err)) != NULL; file_num++)
+ {
+ if (got_err)
+ {
+ error("Can't find file %s\n", this_file);
+ ac--, av++;
+ }
+ else
+ {
+ this_file = massage_name (this_file);
+#else
+ for (; file_num < ac; file_num++)
+ {
+ this_file = av[file_num];
+ if (1)
+ {
+#endif
+ find_entries (this_file);
+ if (eflag)
+ {
+ fprintf (outf, "\f\n%s,%d\n",
+ this_file, total_size_of_entries (head));
+ put_entries (head);
+ free_tree (head);
+ head = NULL;
+ }
+ }
+ }
+
+ if (eflag)
+ {
+ fclose (outf);
+ exit (GOOD);
+ }
+
+ if (xflag)
+ {
+ put_entries(head);
+ exit(GOOD);
+ }
+ if (uflag)
+ {
+ for (i=1; i<ac; i++)
+ {
+ sprintf(cmd,
+ "mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS",
+ outfile, av[i], outfile);
+ system(cmd);
+ }
+ aflag++;
+ }
+ outf = fopen(outfile, aflag ? "a" : "w");
+ if (outf == NULL)
+ {
+ fprintf (stderr, "%s: ", outfile);
+ perror(outfile);
+ exit(BAD);
+ }
+ put_entries(head);
+ fclose(outf);
+#ifndef VMS
+ if (uflag)
+ {
+ sprintf(cmd, "sort %s -o %s", outfile, outfile);
+ system(cmd);
+ }
+#endif
+ exit(GOOD);
+}
+
+/*
+ * This routine sets up the boolean psuedo-functions which work
+ * by seting boolean flags dependent upon the corresponding character
+ * Every char which is NOT in that string is not a white char. Therefore,
+ * all of the array "_wht" is set to FALSE, and then the elements
+ * subscripted by the chars in "white" are set to TRUE. Thus "_wht"
+ * of a char is TRUE if it is the string "white", else FALSE.
+ */
+init()
+{
+
+ reg char *sp;
+ reg int i;
+
+ for (i = 0; i < 0177; i++)
+ {
+ _wht[i] = _etk[i] = _itk[i] = _btk[i] = FALSE;
+ _gd[i] = TRUE;
+ }
+ for (sp = white; *sp; sp++)
+ _wht[*sp] = TRUE;
+ for (sp = endtk; *sp; sp++)
+ _etk[*sp] = TRUE;
+ for (sp = intk; *sp; sp++)
+ _itk[*sp] = TRUE;
+ for (sp = begtk; *sp; sp++)
+ _btk[*sp] = TRUE;
+ for (sp = notgd; *sp; sp++)
+ _gd[*sp] = FALSE;
+ _wht[0] = _wht['\n'];
+ _etk[0] = _etk['\n'];
+ _btk[0] = _btk['\n'];
+ _itk[0] = _itk['\n'];
+ _gd[0] = _gd['\n'];
+}
+
+/*
+ * This routine opens the specified file and calls the function
+ * which finds the function and type definitions.
+ */
+find_entries (file)
+ char *file;
+{
+ char *cp;
+
+ if ((inf=fopen(file,"r")) == NULL)
+ {
+ fprintf (stderr, "%s: ", progname);
+ perror(file);
+ return;
+ }
+ curfile = savestr(file);
+ cp = rindex(file, '.');
+ /* .tex, .aux or .bbl implies LaTeX source code */
+ if (cp && (!strcmp (cp + 1, "tex") || !strcmp (cp + 1, "aux")
+ || !strcmp (cp + 1, "bbl")))
+ {
+ TEX_funcs(inf);
+ fclose(inf);
+ return;
+ }
+ /* .l or .el or .lisp (or .cl or .clisp or ...) implies lisp source code */
+ if (cp && (!strcmp (cp + 1, "l") ||
+ !strcmp (cp + 1, "el") ||
+ !strcmp (cp + 1, "lsp") ||
+ !strcmp (cp + 1, "lisp") ||
+ !strcmp (cp + 1, "cl") ||
+ !strcmp (cp + 1, "clisp")))
+ {
+ L_funcs(inf);
+ fclose(inf);
+ return;
+ }
+ /* .scm or .sm or .scheme implies scheme source code */
+ if (cp && (!strcmp (cp + 1, "sm")
+ || !strcmp (cp + 1, "scm")
+ || !strcmp (cp + 1, "scheme")
+ || !strcmp (cp + 1, "t")
+ || !strcmp (cp + 1, "sch")
+ || !strcmp (cp + 1, "SM")
+ || !strcmp (cp + 1, "SCM")
+ /* The `SCM' or `scm' prefix with a version number */
+ || (cp[-1] == 'm' && cp[-2] == 'c' && cp[-3] == 's'
+ && string_numeric_p (cp + 1))
+ || (cp[-1] == 'M' && cp[-2] == 'C' && cp[-3] == 'S'
+ && string_numeric_p (cp + 1))))
+ {
+ Scheme_funcs(inf);
+ fclose(inf);
+ return;
+ }
+ /* if not a .c or .h or .y file, try fortran */
+ if (cp && (cp[1] != 'c' && cp[1] != 'h' && cp[1] != 'y')
+ && cp[2] == '\0')
+ {
+ if (PF_funcs(inf) != 0)
+ {
+ fclose(inf);
+ return;
+ }
+ rewind(inf); /* no fortran tags found, try C */
+ }
+ C_entries();
+ fclose(inf);
+}
+
+/* Nonzero if string STR is composed of digits. */
+
+int
+string_numeric_p (str)
+ char *str;
+{
+ while (*str)
+ {
+ if (*str < '0' || *str > '9')
+ return 0;
+ }
+ return 1;
+}
+
+/* Record a tag on the current line.
+ name is the tag name,
+ f is nonzero to use a pattern, zero to use line number instead. */
+
+pfnote (name, f, linestart, linelen, lno, cno)
+ char *name;
+ logical f; /* f == TRUE when function */
+ char *linestart;
+ int linelen;
+ int lno;
+ long cno;
+{
+ register char *fp;
+ register NODE *np;
+ char *altname;
+ char tem[51];
+
+ if ((np = (NODE *) malloc (sizeof (NODE))) == NULL)
+ {
+ fprintf(stderr, "%s: too many entries to sort\n", progname);
+ put_entries(head);
+ free_tree(head);
+ head = NULL;
+ np = (NODE *) xmalloc(sizeof (NODE));
+ }
+ /* Change name "main" to M<thisfilename>. */
+ if (!eflag && !xflag && !strcmp(name, "main"))
+ {
+ fp = rindex(curfile, '/');
+ if (fp == 0)
+ fp = curfile;
+ else
+ fp++;
+ altname = concat ("M", fp, "");
+ fp = rindex(altname, '.');
+ if (fp && fp[2] == 0)
+ *fp = 0;
+ name = altname;
+ }
+ np->name = savestr(name);
+ np->file = curfile;
+ np->f = f;
+ np->lno = lno;
+ np->cno = cno;
+ np->left = np->right = 0;
+ if (eflag)
+ {
+ linestart[linelen] = 0;
+ }
+ else if (xflag == 0)
+ {
+ sprintf (tem, strlen (linestart) < 50 ? "%s$" : "%.50s", linestart);
+ linestart = tem;
+ }
+ np->pat = savestr (linestart);
+ if (head == NULL)
+ head = np;
+ else
+ add_node(np, head);
+}
+
+free_tree(node)
+ NODE *node;
+{
+ while (node)
+ {
+ free_tree(node->right);
+ free(node);
+ node = node->left;
+ }
+}
+
+add_node(node, cur_node)
+ NODE *node,*cur_node;
+{
+ register int dif;
+
+ dif = strcmp(node->name, cur_node->name);
+
+ /* If this tag name matches an existing one, then
+ unless -e was given, do not add the node, but maybe print a warning */
+ if (!eflag && !dif)
+ {
+ if (node->file == cur_node->file)
+ {
+ if (!wflag)
+ {
+ fprintf(stderr,"%s: Duplicate entry in file %s, line %d: %s\n",
+ progname, node->file,lineno,node->name);
+ fprintf(stderr,"Second entry ignored\n");
+ }
+ return;
+ }
+ if (!cur_node->been_warned)
+ if (!wflag)
+ fprintf(stderr,"%s: Duplicate entry in files %s and %s: %s (Warning only)\n",
+ progname, node->file, cur_node->file, node->name);
+ cur_node->been_warned = TRUE;
+ return;
+ }
+
+ /* Actually add the node */
+ if (dif < 0)
+ {
+ if (cur_node->left != NULL)
+ add_node(node,cur_node->left);
+ else
+ cur_node->left = node;
+ return;
+ }
+ if (cur_node->right != NULL)
+ add_node(node,cur_node->right);
+ else
+ cur_node->right = node;
+}
+
+put_entries(node)
+ reg NODE *node;
+{
+ reg char *sp;
+
+ if (node == NULL)
+ return;
+
+ /* Output subentries that precede this one */
+ put_entries (node->left);
+
+ /* Output this entry */
+
+ if (eflag)
+ {
+ fprintf (outf, "%s%c%d,%d\n",
+ node->pat, 0177, node->lno, node->cno);
+ }
+ else if (!xflag)
+ {
+ fprintf (outf, "%s\t%s\t",
+ node->name, node->file);
+
+ if (node->f)
+ { /* a function */
+ putc (searchar, outf);
+ putc ('^', outf);
+
+ for (sp = node->pat; *sp; sp++)
+ {
+ if (*sp == '\\' || *sp == searchar)
+ putc ('\\', outf);
+ putc (*sp, outf);
+ }
+ putc (searchar, outf);
+ }
+ else
+ { /* a typedef; text pattern inadequate */
+ fprintf (outf, "%d", node->lno);
+ }
+ putc ('\n', outf);
+ }
+ else if (vflag)
+ fprintf (stdout, "%s %s %d\n",
+ node->name, node->file, (node->lno+63)/64);
+ else
+ fprintf (stdout, "%-16s%4d %-16s %s\n",
+ node->name, node->lno, node->file, node->pat);
+
+ /* Output subentries that follow this one */
+ put_entries (node->right);
+}
+
+/* Return total number of characters that put_entries will output for
+ the nodes in the subtree of the specified node.
+ Works only if eflag is set, but called only in that case. */
+
+total_size_of_entries(node)
+ reg NODE *node;
+{
+ reg int total = 0;
+ reg long num;
+
+ if (node == NULL)
+ return 0;
+
+ /* Count subentries that precede this one */
+ total = total_size_of_entries (node->left);
+
+ /* Count subentries that follow this one */
+ total += total_size_of_entries (node->right);
+
+ /* Count this entry */
+
+ total += strlen (node->pat) + 3;
+
+ num = node->lno;
+ while (num)
+ {
+ total++;
+ num /= 10;
+ }
+
+ num = node->cno;
+ if (!num) total++;
+ while (num)
+ {
+ total++;
+ num /= 10;
+ }
+ return total;
+}
+
+/*
+ * This routine finds functions and typedefs in C syntax and adds them
+ * to the list.
+ */
+#ifdef VMS
+long vmslinecharno;
+#define VMS_SET_LINECHARNO (vmslinecharno = ftell(inf))
+#else
+#define VMS_SET_LINECHARNO
+#endif
+
+#define CNL_SAVE_NUMBER \
+{ \
+ VMS_SET_LINECHARNO; \
+ linecharno = charno; lineno++; \
+ charno += 1 + readline (&lb, inf); \
+ lp = lb.buffer; \
+}
+
+#define CNL \
+{ \
+ CNL_SAVE_NUMBER; \
+ number = 0; \
+}
+
+C_entries ()
+{
+ register int c;
+ register char *token, *tp, *lp;
+ logical incomm, inquote, inchar, midtoken;
+ int level;
+ char tok[BUFSIZ];
+
+ lineno = 0;
+ charno = 0;
+ lp = lb.buffer;
+ *lp = 0;
+
+ number = 0;
+ gotone = midtoken = inquote = inchar = incomm = FALSE;
+ level = 0;
+ tydef = none;
+ next_token_is_func = 0;
+
+ while (!feof (inf))
+ {
+ c = *lp++;
+ if (c == 0)
+ {
+ CNL;
+ gotone = FALSE;
+ }
+ if (c == '\\')
+ {
+ c = *lp++;
+ if (c == 0)
+ CNL_SAVE_NUMBER;
+ c = ' ';
+ }
+ else if (incomm)
+ {
+ if (c == '*')
+ {
+ while ((c = *lp++) == '*')
+ continue;
+ if (c == 0)
+ CNL;
+ if (c == '/')
+ incomm = FALSE;
+ }
+ }
+ else if (inquote)
+ {
+ /*
+ * Too dumb to know about \" not being magic, but
+ * they usually occur in pairs anyway.
+ */
+ if (c == '"')
+ inquote = FALSE;
+ continue;
+ }
+ else if (inchar)
+ {
+ if (c == '\'')
+ inchar = FALSE;
+ continue;
+ }
+ else switch (c)
+ {
+ case '"':
+ inquote = TRUE;
+ continue;
+ case '\'':
+ inchar = TRUE;
+ continue;
+ case '/':
+ if (*lp == '*')
+ {
+ lp++;
+ incomm = TRUE;
+ }
+ continue;
+ case '#':
+ if (lp == lb.buffer + 1)
+ number = 1;
+ continue;
+ case '{':
+ if (tydef == tag_ok)
+ {
+ tydef=middle;
+ }
+ level++;
+ continue;
+ case '}':
+ if (lp == lb.buffer + 1)
+ level = 0; /* reset */
+ else
+ level--;
+ if (!level && tydef==middle)
+ {
+ tydef=end;
+ }
+ continue;
+ }
+ if (!level && !inquote && !incomm && gotone == FALSE)
+ {
+ if (midtoken)
+ {
+ if (endtoken(c))
+ {
+ int f;
+ char *buf = lb.buffer;
+ int endpos = lp - lb.buffer;
+ char *lp1 = lp;
+ int line = lineno;
+ long linestart = linecharno;
+#ifdef VMS
+ long vmslinestart = vmslinecharno;
+#endif
+ int tem = consider_token (&lp1, token, &f, level);
+ lp = lp1;
+ if (tem)
+ {
+ if (linestart != linecharno)
+ {
+#ifdef VMS
+ getline (vmslinestart);
+#else
+ getline (linestart);
+#endif
+ strncpy (tok, token + (lb1.buffer - buf),
+ tp-token+1);
+ tok[tp-token+1] = 0;
+ pfnote(tok, f, lb1.buffer, endpos, line, linestart);
+ }
+ else
+ {
+ strncpy (tok, token, tp-token+1);
+ tok[tp-token+1] = 0;
+ pfnote(tok, f, lb.buffer, endpos, line, linestart);
+ }
+ gotone = f; /* function */
+ }
+ midtoken = FALSE;
+ token = lp - 1;
+ }
+ else if (intoken(c))
+ tp++;
+ }
+ else if (begtoken(c))
+ {
+ token = tp = lp - 1;
+ midtoken = TRUE;
+ }
+ }
+ if (c == ';' && tydef==end) /* clean with typedefs */
+ tydef=none;
+ }
+}
+
+/*
+ * This routine checks to see if the current token is
+ * at the start of a function, or corresponds to a typedef
+ * It updates the input line * so that the '(' will be
+ * in it when it returns.
+ */
+consider_token (lpp, token, f, level)
+ char **lpp, *token;
+ int *f, level;
+{
+ reg char *lp = *lpp;
+ reg char c;
+ logical firsttok; /* T if have seen first token in ()'s */
+ int bad, win;
+
+ *f = 1; /* a function */
+ c = lp[-1];
+ bad = FALSE;
+ if (!number)
+ { /* space is not allowed in macro defs */
+ while (iswhite(c))
+ {
+ c = *lp++;
+ if (c == 0)
+ {
+ if (feof (inf))
+ break;
+ CNL;
+ }
+ }
+ /* the following tries to make it so that a #define a b(c) */
+ /* doesn't count as a define of b. */
+ }
+ else
+ {
+ number++;
+ if (number >= 4 || (number==2 && strncmp (token, "define", 6)))
+ {
+ gotone = TRUE;
+ badone:
+ bad = TRUE;
+ goto ret;
+ }
+ }
+ /* check for the typedef cases */
+ if (tflag && istoken(token, "typedef", 7))
+ {
+ tydef=begin;
+ goto badone;
+ }
+ if (tydef==begin && (istoken(token, "struct", 6) ||
+ istoken(token, "union", 5) || istoken(token, "enum", 4)))
+ {
+ tydef=tag_ok;
+ goto badone;
+ }
+ if (tydef==tag_ok)
+ {
+ tydef=middle;
+ goto badone;
+ }
+ if (tydef==begin) /* e.g. typedef ->int<- */
+ {
+ tydef=end;
+ goto badone;
+ }
+ if (tydef==middle && level == 0) /* e.g. typedef struct tag ->struct_t<- */
+ {
+ tydef=end;
+ }
+ if (tydef==end)
+ {
+ *f = 0;
+ win = 1;
+ goto ret;
+ }
+ /* Detect GNUmacs's function-defining macros. */
+ if (!number && !strncmp (token, "DEF", 3))
+
+ {
+ next_token_is_func = 1;
+ goto badone;
+ }
+ if (next_token_is_func)
+ {
+ next_token_is_func = 0;
+ win = 1;
+ goto ret;
+ }
+ if (c != '(')
+ goto badone;
+ firsttok = FALSE;
+ while ((c = *lp++) != ')')
+ {
+ if (c == 0)
+ {
+ if (feof (inf))
+ break;
+ CNL;
+ }
+ /*
+ * This line used to confuse ctags:
+ * int (*oldhup)();
+ * This fixes it. A nonwhite char before the first
+ * token, other than a / (in case of a comment in there)
+ * makes this not a declaration.
+ */
+ if (begtoken(c) || c=='/') firsttok++;
+ else if (!iswhite(c) && !firsttok) goto badone;
+ }
+ while (iswhite (c = *lp++))
+ {
+ if (c == 0)
+ {
+ if (feof (inf))
+ break;
+ CNL;
+ }
+ }
+ win = isgood (c);
+ret:
+ *lpp = lp - 1;
+ return !bad && win;
+}
+
+getline (atchar)
+ long atchar;
+{
+ long saveftell = ftell (inf);
+
+ fseek (inf, atchar, 0);
+ readline (&lb1, inf);
+ fseek (inf, saveftell, 0);
+}
+
+/* Fortran parsing */
+
+char *dbp;
+int pfcnt;
+
+PF_funcs(fi)
+ FILE *fi;
+{
+ lineno = 0;
+ charno = 0;
+ pfcnt = 0;
+
+ while (!feof (fi))
+ {
+ lineno++;
+ linecharno = charno;
+ charno += readline (&lb, fi) + 1;
+ dbp = lb.buffer;
+ if (*dbp == '%') dbp++ ; /* Ratfor escape to fortran */
+ while (isspace(*dbp))
+ dbp++;
+ if (*dbp == 0)
+ continue;
+ switch (*dbp |' ')
+ {
+ case 'i':
+ if (tail("integer"))
+ takeprec();
+ break;
+ case 'r':
+ if (tail("real"))
+ takeprec();
+ break;
+ case 'l':
+ if (tail("logical"))
+ takeprec();
+ break;
+ case 'c':
+ if (tail("complex") || tail("character"))
+ takeprec();
+ break;
+ case 'd':
+ if (tail("double"))
+ {
+ while (isspace(*dbp))
+ dbp++;
+ if (*dbp == 0)
+ continue;
+ if (tail("precision"))
+ break;
+ continue;
+ }
+ break;
+ }
+ while (isspace(*dbp))
+ dbp++;
+ if (*dbp == 0)
+ continue;
+ switch (*dbp|' ')
+ {
+ case 'f':
+ if (tail("function"))
+ getit();
+ continue;
+ case 's':
+ if (tail("subroutine"))
+ getit();
+ continue;
+ case 'p':
+ if (tail("program"))
+ {
+ getit();
+ continue;
+ }
+ if (tail("procedure"))
+ getit();
+ continue;
+ }
+ }
+ return (pfcnt);
+}
+
+tail(cp)
+ char *cp;
+{
+ register int len = 0;
+
+ while (*cp && (*cp&~' ') == ((*(dbp+len))&~' '))
+ cp++, len++;
+ if (*cp == 0)
+ {
+ dbp += len;
+ return (1);
+ }
+ return (0);
+}
+
+takeprec()
+{
+ while (isspace(*dbp))
+ dbp++;
+ if (*dbp != '*')
+ return;
+ dbp++;
+ while (isspace(*dbp))
+ dbp++;
+ if (!isdigit(*dbp))
+ {
+ --dbp; /* force failure */
+ return;
+ }
+ do
+ dbp++;
+ while (isdigit(*dbp));
+}
+
+getit()
+{
+ register char *cp;
+ char c;
+ char nambuf[BUFSIZ];
+
+ while (isspace(*dbp))
+ dbp++;
+ if (*dbp == 0 || (!isalpha (*dbp)) && (*dbp != '_') && (*dbp != '$'))
+ return;
+ for (cp = dbp + 1; *cp && (isalpha (*cp) || isdigit (*cp)
+ || (*cp == '_') || (*cp == '$')); cp++)
+ continue;
+ c = cp[0];
+ cp[0] = 0;
+ strcpy(nambuf, dbp);
+ cp[0] = c;
+ pfnote(nambuf, TRUE, lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
+ pfcnt++;
+}
+
+/*
+ * lisp tag functions
+ * just look for (def or (DEF
+ */
+
+L_funcs (fi)
+ FILE *fi;
+{
+ lineno = 0;
+ charno = 0;
+ pfcnt = 0;
+
+ while (!feof (fi))
+ {
+ lineno++;
+ linecharno = charno;
+ charno += readline (&lb, fi) + 1;
+ dbp = lb.buffer;
+ if (dbp[0] == '(' &&
+ (dbp[1] == 'D' || dbp[1] == 'd') &&
+ (dbp[2] == 'E' || dbp[2] == 'e') &&
+ (dbp[3] == 'F' || dbp[3] == 'f'))
+ {
+ while (!isspace(*dbp)) dbp++;
+ while (isspace(*dbp)) dbp++;
+ L_getit();
+ }
+ }
+}
+
+L_getit()
+{
+ register char *cp;
+ char c;
+ char nambuf[BUFSIZ];
+
+ if (*dbp == 0) return;
+ for (cp = dbp+1; *cp && *cp != '(' && *cp != ' '; cp++)
+ continue;
+ c = cp[0];
+ cp[0] = 0;
+ strcpy(nambuf, dbp);
+ cp[0] = c;
+ pfnote(nambuf, TRUE, lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
+ pfcnt++;
+}
+
+/*
+ * Scheme tag functions
+ * look for (def... xyzzy
+ * look for (def... (xyzzy
+ * look for (def ... ((...(xyzzy ....
+ * look for (set! xyzzy
+ */
+
+static get_scheme ();
+Scheme_funcs (fi)
+ FILE *fi;
+{
+ lineno = 0;
+ charno = 0;
+ pfcnt = 0;
+
+ while (!feof (fi))
+ {
+ lineno++;
+ linecharno = charno;
+ charno += readline (&lb, fi) + 1;
+ dbp = lb.buffer;
+ if (dbp[0] == '(' &&
+ (dbp[1] == 'D' || dbp[1] == 'd') &&
+ (dbp[2] == 'E' || dbp[2] == 'e') &&
+ (dbp[3] == 'F' || dbp[3] == 'f'))
+ {
+ while (!isspace(*dbp)) dbp++;
+ /* Skip over open parens and white space */
+ while (*dbp && (isspace(*dbp) || *dbp == '(')) dbp++;
+ get_scheme ();
+ }
+ if (dbp[0] == '(' &&
+ (dbp[1] == 'S' || dbp[1] == 's') &&
+ (dbp[2] == 'E' || dbp[2] == 'e') &&
+ (dbp[3] == 'T' || dbp[3] == 't') &&
+ (dbp[4] == '!' || dbp[4] == '!') &&
+ (isspace(dbp[5])))
+ {
+ while (!isspace(*dbp)) dbp++;
+ /* Skip over white space */
+ while (isspace(*dbp)) dbp++;
+ get_scheme ();
+ }
+ }
+}
+
+static
+get_scheme()
+{
+ register char *cp;
+ char c;
+ char nambuf[BUFSIZ];
+
+ if (*dbp == 0) return;
+ /* Go till you get to white space or a syntactic break */
+ for (cp = dbp+1; *cp && *cp != '(' && *cp != ')' && !isspace(*cp); cp++)
+ continue;
+ /* Null terminate the string there. */
+ c = cp[0];
+ cp[0] = 0;
+ /* Copy the string */
+ strcpy(nambuf, dbp);
+ /* Unterminate the string */
+ cp[0] = c;
+ /* Announce the change */
+ pfnote(nambuf, TRUE, lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
+ pfcnt++;
+}
+
+/* Find tags in TeX and LaTeX input files. */
+
+/* TEX_toktab is a table of TeX control sequences that define tags.
+ Each TEX_tabent records one such control sequence. */
+
+struct TEX_tabent
+{
+ char *name;
+ int len;
+};
+
+struct TEX_tabent *TEX_toktab = NULL; /* Table with tag tokens */
+
+/* Default set of control sequences to put into TEX_toktab.
+ The value of environment var TEXTAGS is prepended to this. */
+
+static char *TEX_defenv =
+ ":chapter:section:subsection:subsubsection:eqno:label:ref:cite:bibitem:typeout";
+
+struct TEX_tabent *TEX_decode_env ();
+
+static char TEX_esc = '\\';
+static char TEX_opgrp = '{';
+static char TEX_clgrp = '}';
+
+/*
+ * TeX/LaTeX scanning loop.
+ */
+
+TEX_funcs (fi)
+ FILE *fi;
+{
+ char *lasthit;
+
+ lineno = 0;
+ charno = 0;
+ pfcnt = 0;
+
+ /* Select either \ or ! as escape character. */
+ TEX_mode (fi);
+
+ /* Initialize token table once from environment. */
+ if (!TEX_toktab)
+ TEX_toktab = TEX_decode_env ("TEXTAGS", TEX_defenv);
+
+ while (!feof (fi))
+ { /* Scan each line in file */
+ lineno++;
+ linecharno = charno;
+ charno += readline (&lb, fi) + 1;
+ dbp = lb.buffer;
+ lasthit = dbp;
+ while (dbp = index (dbp, TEX_esc)) /* Look at each escape in line */
+ {
+ register int i;
+
+ if (! *(++dbp))
+ break;
+ linecharno += dbp - lasthit;
+ lasthit = dbp;
+ i = TEX_Token (lasthit);
+ if (0 <= i)
+ {
+ TEX_getit (lasthit, TEX_toktab[i].len);
+ break; /* We only save a line once */
+ }
+ }
+ }
+}
+
+#define TEX_LESC '\\'
+#define TEX_SESC '!'
+#define TEX_CMT '%'
+
+/* Figure out whether TeX's escapechar is '\\' or '!' and set grouping */
+/* chars accordingly. */
+
+TEX_mode (f)
+ FILE *f;
+{
+ int c, skip_line = 0;
+
+ while ((c = getc (f)) != EOF)
+ {
+ /* Skip to next line if we hit the TeX comment char. */
+ if (c == TEX_CMT)
+ skip_line = 1;
+ else if (c == '\n')
+ skip_line = 0;
+ else if (! skip_line)
+ if (c == TEX_LESC || c == TEX_SESC)
+ break;
+ }
+
+ if (c == TEX_LESC)
+ {
+ TEX_esc = TEX_LESC;
+ TEX_opgrp = '{';
+ TEX_clgrp = '}';
+ }
+ else
+ {
+ TEX_esc = TEX_SESC;
+ TEX_opgrp = '<';
+ TEX_clgrp = '>';
+ }
+ rewind (f);
+}
+
+/* Read environment and prepend it to the default string. */
+/* Build token table. */
+
+struct TEX_tabent *
+TEX_decode_env (evarname, defenv)
+ char *evarname;
+ char *defenv;
+{
+ register char *env, *p;
+ extern char *savenstr (), *index ();
+
+ struct TEX_tabent *tab;
+ int size, i;
+
+ /* Append deafult string to environment. */
+ env = (char *) getenv (evarname);
+ if (!env)
+ env = defenv;
+ else
+ env = concat (env, defenv, "");
+
+ /* Allocate a token table */
+ for (size = 1, p=env; p;)
+ if ((p = index (p, ':')) && *(++p))
+ size++;
+ tab = (struct TEX_tabent *) xmalloc ((size + 1)
+ * sizeof (struct TEX_tabent));
+
+ /* Unpack environment string into token table. Be careful about */
+ /* zero-length strings (leading ':', "::" and trailing ':') */
+ for (i = 0; *env;)
+ {
+ p = index (env, ':');
+ if (!p) /* End of environment string. */
+ p = env + strlen (env);
+ if (p - env > 0)
+ { /* Only non-zero strings. */
+ tab[i].name = savenstr (env, p - env);
+ tab[i].len = strlen (tab[i].name);
+ i++;
+ }
+ if (*p)
+ env = p + 1;
+ else
+ {
+ tab[i].name = NULL; /* Mark end of table. */
+ tab[i].len = 0;
+ break;
+ }
+ }
+ return tab;
+}
+
+/* Record a tag defined by a TeX command of length LEN and starting at NAME.
+ The name being defined actually starts at (NAME + LEN + 1).
+ But we seem to include the TeX command in the tag name. */
+
+TEX_getit (name, len)
+ char *name;
+ int len;
+{
+ char *p = name + len;
+ char nambuf[BUFSIZ];
+
+ if (*name == 0) return;
+
+ /* Let tag name extend to next group close (or end of line) */
+ while (*p && *p != TEX_clgrp)
+ p++;
+ strncpy (nambuf, name, p - name);
+ nambuf[p - name] = 0;
+
+ pfnote (nambuf, TRUE, lb.buffer, strlen (lb.buffer), lineno, linecharno);
+ pfcnt++;
+}
+
+/* If the text at CP matches one of the tag-defining TeX command names,
+ return the index of that command in TEX_toktab.
+ Otherwise return -1. */
+
+/* Keep the capital `T' in `Token' for dumb truncating compilers
+ (this distinguishes it from `TEX_toktab' */
+TEX_Token (cp)
+ char *cp;
+{
+ int i;
+
+ for (i = 0; TEX_toktab[i].len > 0; i++)
+ if (strncmp (TEX_toktab[i].name, cp, TEX_toktab[i].len) == 0)
+ return i;
+ return -1;
+}
+
+/* Initialize a linebuffer for use */
+
+void
+initbuffer (linebuffer)
+ struct linebuffer *linebuffer;
+{
+ linebuffer->size = 200;
+ linebuffer->buffer = (char *) xmalloc (200);
+}
+
+/* Read a line of text from `stream' into `linebuffer'.
+ Return the length of the line. */
+
+long
+readline (linebuffer, stream)
+ struct linebuffer *linebuffer;
+ register FILE *stream;
+{
+ char *buffer = linebuffer->buffer;
+ register char *p = linebuffer->buffer;
+ register char *pend;
+
+ pend = p + linebuffer->size;
+
+ while (1)
+ {
+ int c = getc (stream);
+ if (p == pend)
+ {
+ linebuffer->size *= 2;
+ buffer = (char *) xrealloc (buffer, linebuffer->size);
+ p += buffer - linebuffer->buffer;
+ pend = buffer + linebuffer->size;
+ linebuffer->buffer = buffer;
+ }
+ if (c < 0 || c == '\n')
+ {
+ *p = 0;
+ break;
+ }
+ *p++ = c;
+ }
+
+ return p - buffer;
+}
+
+char *
+savestr(cp)
+ char *cp;
+{
+ return savenstr (cp, strlen (cp));
+}
+
+char *
+savenstr(cp, len)
+ char *cp;
+ int len;
+{
+ register char *dp;
+
+ dp = (char *) xmalloc (len + 1);
+ strncpy (dp, cp, len);
+ dp[len] = '\0';
+ return dp;
+}
+
+/*
+ * Return the ptr in sp at which the character c last
+ * appears; NULL if not found
+ *
+ * Identical to v7 rindex, included for portability.
+ */
+
+char *
+rindex(sp, c)
+ register char *sp, c;
+{
+ register char *r;
+
+ r = NULL;
+ do
+ {
+ if (*sp == c)
+ r = sp;
+ } while (*sp++);
+ return(r);
+}
+
+/*
+ * Return the ptr in sp at which the character c first
+ * appears; NULL if not found
+ *
+ * Identical to v7 index, included for portability.
+ */
+
+char *
+index(sp, c)
+ register char *sp, c;
+{
+ do
+ {
+ if (*sp == c)
+ return (sp);
+ } while (*sp++);
+ return (NULL);
+}
+
+/* Print error message and exit. */
+
+fatal (s1, s2)
+ char *s1, *s2;
+{
+ error (s1, s2);
+ exit (BAD);
+}
+
+/* Print error message. `s1' is printf control string, `s2' is arg for it. */
+
+error (s1, s2)
+ char *s1, *s2;
+{
+ fprintf (stderr, "%s: ", progname);
+ fprintf (stderr, s1, s2);
+ fprintf (stderr, "\n");
+}
+
+/* Return a newly-allocated string whose contents concatenate those of s1, s2, s3. */
+
+char *
+concat (s1, s2, s3)
+ char *s1, *s2, *s3;
+{
+ int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
+ char *result = (char *) xmalloc (len1 + len2 + len3 + 1);
+
+ strcpy (result, s1);
+ strcpy (result + len1, s2);
+ strcpy (result + len1 + len2, s3);
+ *(result + len1 + len2 + len3) = 0;
+
+ return result;
+}
+
+/* Like malloc but get fatal error if memory is exhausted. */
+
+int
+xmalloc (size)
+ int size;
+{
+ int result = malloc (size);
+ if (!result)
+ fatal ("virtual memory exhausted", 0);
+ return result;
+}
+
+int
+xrealloc (ptr, size)
+ char *ptr;
+ int size;
+{
+ int result = realloc (ptr, size);
+ if (!result)
+ fatal ("virtual memory exhausted");
+ return result;
+}
diff --git a/etc/etags.vms b/etc/etags.vms
new file mode 100644
index 00000000000..3237a479256
--- /dev/null
+++ b/etc/etags.vms
@@ -0,0 +1,15 @@
+VMS-ed version of etags
+-----------------------
+
+1. The changes made allow the program to compile correctly,
+ to give error messages more meaningful to VMS, to allow '$'
+ in identifier tokens in C programs, and to expand wild-cards in the
+ input filespecs.
+
+2. To minimize the differences from the original version,
+ the VMS filename expansion converts filenames to lower
+ case, and strips version numbers. This does indeed mean
+ that some input specs (containing version wildcards) will
+ cause curious effects, it is reasonably consistent with
+ Emacs, which ignores file versions.
+
diff --git a/lib-src/fakemail.c b/etc/fakemail.c
index 464a739e998..9fedf7c598c 100644
--- a/lib-src/fakemail.c
+++ b/etc/fakemail.c
@@ -21,7 +21,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#define NO_SHORTNAMES
#include "../src/config.h"
-#if defined (BSD) && !defined (BSD4_1) && !defined (USE_FAKEMAIL)
+#if defined (BSD) && !defined (BSD4_1)
/* This program isnot used in BSD, so just avoid loader complaints. */
main ()
{
@@ -267,16 +267,7 @@ add_field (the_list, field, where)
{
*where++ = ' ';
while ((c = *field++) != '\0')
- {
- if (c == '(')
- {
- while (*field && *field != ')') ++field;
- if (! (*field++)) break; /* no closer */
- if (! (*field)) break; /* closerNULL */
- c = *field;
- }
- *where++ = ((c == ','||c=='>'||c=='<') ? ' ' : c);
- }
+ *where++ = ((c == ',') ? ' ' : c);
if (the_list == NIL) break;
field = the_list->string;
the_list = the_list->continuation;
@@ -400,49 +391,15 @@ put_string (s)
}
void
-put_line (string)
- char *string;
+put_line (s)
+ char *s;
{
register stream_list rem;
for (rem = the_streams;
rem != ((stream_list) NULL);
rem = rem->rest_streams)
{
- char *s = string;
- int column = 0;
-
- /* Divide STRING into lines. */
- while (*s != 0)
- {
- char *breakpos;
-
- /* Find the last char that fits. */
- for (breakpos = s; *breakpos && column < 78; ++breakpos)
- {
- if (*breakpos == '\t')
- column += 8;
- else
- column++;
- }
- /* Back up to just after the last comma that fits. */
- while (breakpos != s && breakpos[-1] != ',') --breakpos;
- if (breakpos == s)
- {
- /* If no comma fits, move past the first address anyway. */
- while (*breakpos != 0 && *breakpos != ',') ++breakpos;
- if (*breakpos != 0)
- /* Include the comma after it. */
- ++breakpos;
- }
- /* Output that much, then break the line. */
- fwrite (s, 1, breakpos - s, rem->handle);
- fputs ("\n\t", rem->handle);
- column = 8;
-
- /* Skip whitespace and prepare to print more addresses. */
- s = breakpos;
- while (*s == ' ' || *s == '\t') ++s;
- }
+ fputs (s, rem->handle);
putc ('\n', rem->handle);
}
return;
@@ -614,19 +571,11 @@ main (argc, argv)
{
char *command_line;
header the_header;
- long name_length;
- char *mail_program_name;
+ long name_length = strlen (MAIL_PROGRAM_NAME);
char buf[BUFLEN + 1];
register int size;
FILE *the_pipe;
- extern char *getenv ();
-
- mail_program_name = getenv ("FAKEMAILER");
- if (!(mail_program_name && *mail_program_name))
- mail_program_name = MAIL_PROGRAM_NAME;
- name_length = strlen (mail_program_name);
-
my_name = MY_NAME;
the_streams = ((stream_list) NULL);
the_date = ((char *) NULL);
@@ -634,7 +583,7 @@ main (argc, argv)
the_header = read_header ();
command_line = alloc_string (name_length + args_size (the_header));
- strcpy (command_line, mail_program_name);
+ strcpy (command_line, MAIL_PROGRAM_NAME);
parse_header (the_header, &command_line[name_length]);
the_pipe = popen (command_line, "w");
diff --git a/etc/faq2texi.perl b/etc/faq2texi.perl
new file mode 100644
index 00000000000..3a040ab7387
--- /dev/null
+++ b/etc/faq2texi.perl
@@ -0,0 +1,220 @@
+#!/usr/staff/bin/perl
+#
+# efaq2texinfo : Convert Emacs FAQ to texinfo format
+#
+# George Ferguson, ferguson@cs.rochester.edu, 24 Jan 1992.
+#
+# Usage, assuming the list is in the file FAQ:
+# % efaq2texinfo <FAQ >efaq.texinfo
+# If you store your FAQ compressed, you can use
+# % zcat FAQ.Z | efaq2texinfo >efaq.texinfo
+# In any case, you then need to convert to info format:
+# % makeinfo +fill-column 80 efaq.texinfo
+# The result will be files efaq-info and efaq-info-[1-4]. If you don't
+# have makeinfo(1), you can try using "texinfo-format-buffer" within
+# emacs.
+#
+# The FAQ can be obtained from pit-manager.mit.edu.
+#
+
+$chapter = 0;
+$item = 0;
+$itemizing = 0;
+$enumerating = 0;
+$displaying = 0;
+
+# Now process each line
+while (<>) {
+ if ($. == 1 || /^---Continued---$/) {
+ &skipJunk;
+ }
+ s/^ +$//; # blanks only -> newline
+ s/\t/ /; # tabs -> spaces (stupidly)
+ if (/^([^0-9 \n].*)$/) { # new chapter heading
+ &endDisplay;
+ &endLists;
+ $chapter += 1;
+ $text = $1;
+ $text =~ s/ +[-!+]$//; # remove change marker
+ $chapterTitle[$chapter] = $text;
+ $item = 0;
+# print "CHAPTER $chapter: \"$text\"\n";
+ } elsif (/^([0-9]+): (.*)$/) {
+ &endDisplay;
+ &endLists;
+ $num = $1;
+ $text = $2;
+ $text =~ s/ +[-!+]$//; # remove change marker
+ $menu[$chapter] .= "* Question $num::\t$text\n";
+ $item = $num;
+ $itemTitle[$item] = "$text\n";
+# print "QUESTION $item: \"$text\"\n";
+ } else {
+ if (/^ +\* Topic/) { # hack for info example
+ &addText("@example\n");
+ &addText("$_");
+ &addText("@end example\n");
+ next;
+ } elsif (/^ +\*/) { # asterisk marks list element
+ if (!$itemizing) {
+ &addText("\@itemize \@bullet\n");
+ $itemizing = 1;
+ }
+ &endDisplay;
+ &addText("\@item\n");
+ s/^ +\* *//;
+ } elsif (/^ +[0-9]\./) { # digit-period marks list element
+ if (!$enumerating) {
+ &addText("\@enumerate\n");
+ $enumerating = 1;
+ }
+ &endDisplay;
+ &addText("\@item\n");
+ s/^ +[0-9]+\. *//;
+ } elsif (/^ {0,2}[^ \n]/) { # less whitespace marks end of list
+ &endLists;
+ }
+ s/ //; # automatically remove 2 spaces
+ if ($itemizing) { # adjust leading whitespace in lists
+ s/^ //;
+ } elsif ($enumerating) {
+ s/^ //;
+ }
+ if (/^ +/ && !$displaying) { # extra leading spaces -> display
+ &addText("\@example\n");
+ $displaying = 1;
+ }
+ if (/^[^ ]/ && $displaying) { # no leading spaces -> display end
+ &addText("\@end example\n");
+ $displaying = 0;
+ }
+ s/ +[-!+]$//; # remove "change" markers (sorry)
+ $_ = &formatText;
+ &addText($_);
+ }
+}
+# Just in case
+&endDisplay;
+&endLists;
+
+# Output it all
+
+# Print texinfo header
+print "\\input texinfo\n";
+print "@setfilename efaq.info\n";
+print "@settitle Frequently Asked Questions about Emacs\n";
+print "\n";
+print "@node Top\n";
+print "@top Frequently Asked Questions about Emacs\n";
+print "\n";
+
+print $chapterText[0];
+print "\@menu\n";
+for ($i = 1; $i <= $chapter; $i++) {
+ print "* Chapter $i::\t$chapterTitle[$i]\n";
+}
+print "* Index::\tHosts, usernames, files, etc.\n";
+print "\@end menu\n\n";
+for ($i = 1; $i <= $chapter; $i++) {
+ print "\@node Chapter $i\n";
+ print "\@chapter $chapterTitle[$i]\n";
+ print $chapterText[$i];
+ print "\@menu\n";
+ print $menu[$i];
+ print "\@end menu\n\n";
+}
+for ($i = 1; $i <= $item; $i++) {
+ print "\@node Question $i\n";
+ print "\@section $itemTitle[$i]"; # too many newlines already
+ print $itemText[$i];
+}
+
+# Print texinfo trailer
+print "\n";
+print "@node Index\n";
+print "@appendix Index\n";
+print "\n";
+print "@printindex fn\n";
+print "\n";
+print "@bye\n";
+
+############################################################################
+
+sub addText {
+ if ($item == 0) {
+ $chapterText[$chapter] .= "$_[0]";
+ } else {
+ $itemText[$item] .= "$_[0]";
+ }
+}
+
+sub endLists {
+ if ($itemizing) {
+ &addText("\@end itemize\n");
+ }
+ if ($enumerating) {
+ &addText("\@end enumerate\n");
+ }
+ $enumerating = 0;
+ $itemizing = 0;
+}
+
+sub endDisplay {
+ if ($displaying) {
+ &addText("\@end example\n");
+ $displaying = 0;
+ }
+}
+
+sub skipJunk {
+ local($blank) = 0;
+ # skip until double newline (ie. mail headers, etc.)
+ while ($_ ne "\n" || !$blank) {
+ $blank = ($_ eq "\n");
+ $_ = <>;
+ }
+ # skip next paragraph: "If you are viewing..."
+ $_ = <>;
+ while ($_ ne "\n") { $_ = <>; }
+ # skip next paragraph: "To search for..."
+ $_ = <>;
+ while ($_ ne "\n") { $_ = <>; }
+ # skip next paragraph: "A `+' in the..."
+ $_ = <>;
+ while ($_ ne "\n") { $_ = <>; }
+}
+
+#
+# For each line of text in the document, we generate an index entry for
+# anything that looks like a hostname, email address, newsgroup, filename
+# or emacs command (only long command recognized). This function is complicated
+# by the fact that the index entries have to come on lines of their own,
+# after the text that contains them.
+#
+# To recognize host:file as a single entity, add ":?" inside the first
+# nested set of brackets but before the multiple-alternatives pattern.
+#
+# This function also escapes any characters with special meaning to
+# texinfo. Returns the line of text.
+#
+sub formatText {
+ # convert special chars to texinfo escapes
+ s/@/@@/g;
+ s/\{/@{/g;
+ s/\}/@}/g;
+ # remove trailing spaces
+ s/ +$//g;
+ # gather the index entries
+ local($t) = $_;
+ local($tt) = "";
+ while ($t =~ /([-a-zA-Z0-9]{2,}((\.|@@|%|!|-|\/)[-@a-zA-Z0-9]+){2,})/) {
+ $t = $';
+ $tt .= "@findex $1\n";
+ }
+ # Flag cross-references
+ s/(q|Q)uestion ([0-9]+)/@ref\{Question $2\}/g;
+ # print the line of text
+ return("$_$tt");
+}
+
+__END__
diff --git a/etc/ledit.l b/etc/ledit.l
new file mode 100644
index 00000000000..203803677da
--- /dev/null
+++ b/etc/ledit.l
@@ -0,0 +1,150 @@
+;;; -*- Mode: lisp -*-
+
+; load in the c functions
+
+(removeaddress '_signal)
+(removeaddress '_switch_to_proc)
+(removeaddress '_set_proc_str)
+
+(cfasl "/src/mdc/ledit/leditcfns.o" '_switch_to_proc 'emacs)
+
+(getaddress '_set_proc_str 'set_proc_str)
+
+(declare (special *ledit-infile* ; emacs->lisp tempfile
+ *ledit-outfile* ; lisp->emacs tempfile
+ *ledit-ppfile* ; pp->emacs tempfile
+ *ledit-lisztfile* ; compiler input
+ *ledit-objfile* ; compiler output
+ *ledit-initialized*) ; flag
+ )
+
+(setq *ledit-initialized* nil)
+
+;;; INIT-LEDIT
+
+(defun init-ledit ()
+ (let ((user (getenv '|USER|))) ;USER must be uppercase
+ (setq
+ *ledit-outfile* (concat "/tmp/" user ".l2") ; lisp -> emacs
+ *ledit-infile* (concat "/tmp/" user ".l1") ; emacs -> lisp
+ *ledit-ppfile* (concat "/tmp/" user ".l3") ; pp output to emacs.
+ *ledit-lisztfile* (concat "/tmp/" user ".l4")
+ *ledit-objfile* (concat "/tmp/" user ".o")
+ *ledit-initialized* t)))
+
+;;; LEDIT
+; if 1 arg, arg is taken as a tag name to pass to emacs.
+; if 2 args, second arg is a keyword. If 2nd arg is pp,
+; pp is applied to first arg, and result is sent to emacs
+; to put in a buffer called LEDIT (which is first erased.)
+
+(defun ledit fexpr (args)
+ (apply #'ledit* args))
+
+;;; LEDIT*
+
+(defun ledit* n
+ (if (not *ledit-initialized*) (init-ledit))
+ (ledit-output (listify n))
+ (syscall 10. *ledit-infile*) ; syscall 10 is "delete"
+ (syscall 10. *ledit-lisztfile*)
+ (emacs)
+ (ledit-input)
+ (syscall 10. *ledit-outfile*)
+ (syscall 10. *ledit-ppfile*)
+ t)
+
+;;; LEDIT-OUTPUT
+;;; Egad, what a mess! Doesn't work for XEMACS yet.
+;;; Here's an example from Moclisp:
+;;; -> (defun bar (nothing) (bar nothing))
+;;; bar
+;;; -> (ledit bar)
+;;; should produce...
+;;; (progn) (progn tag (setq tag "bar") (&goto-tag))
+;;; and
+;;; -> (ledit bar pp)
+;;; should stuff this to emacs...
+;;; (progn) (switch-to-buffer "LEDIT") (erase-buffer)
+;;; (insert-file "/tmp/walter.l3") (lisp-mode)
+;;; and this...
+;;; (def bar
+;;; (lambda (x)
+;;; (bar nothing)))
+;;; into *LEDIT*
+
+(defun ledit-output (args)
+ (if args
+ (let ((ofile (outfile *ledit-outfile*)))
+ (format ofile "(progn)") ; this is necessary.
+
+ (cond ((null (cdr args)) ; no keyword -> arg is a tag.
+ (format ofile "(progn tag (setq tag \"~A\"~
+ (&goto-tag))"
+ (car args)))
+ ((eq (cadr args) 'pp) ; pp-> pp first arg to emacs
+ (apply 'pp `((|F| ,*ledit-ppfile*) ,(car args)))
+ (format ofile "(switch-to-buffer \"LEDIT\")~
+ (erase-buffer)")
+ (format ofile "(insert-file \"~A\")"
+ *ledit-ppfile*)
+ (format ofile "(lisp-mode)"))
+
+ (t (format t "~&~A -- unknown option~%" (cdr args))))
+ (close ofile))))
+
+;;; LISZT*
+;;; Need this guy to do compile-input.
+;;; Liszt returns 0 if all was well.
+;;; Note that in ordinary use the user will have to get used to looking
+;;; at "%Warning: ... Compiler declared *foo* special" messages, since
+;;; you don't usually want to hunt around in your file, zap in the the
+;;; declarations, then go back to what you were doing.
+;;; Fortunately this doesn't cause the compiler to bomb.
+;;; Some sleepless night I will think of a way to get around this.
+
+(defun liszt* (&rest args)
+ (apply #'liszt args))
+
+;;; LEDIT-INPUT
+;;; Although there are two cases here, in practice
+;;; it is never the case that there is both input to be
+;;; interpreted and input to be compiled.
+
+(defun ledit-input ()
+ (if (probef *ledit-lisztfile*)
+ (cond ((getd #'liszt)
+ (format t ";Compiling LEDIT:")
+ (and (zerop (liszt* *ledit-lisztfile* '-o *ledit-objfile*))
+ (load *ledit-objfile*)))
+ (t (format t ";Can't compile LEDIT: No liszt.~%;Reading instead:")
+ (let ((ifile (infile *ledit-lisztfile*)))
+ (ledit-load ifile)
+ (close ifile)))))
+
+ (if (probef *ledit-infile*)
+ (let ((ifile (infile *ledit-infile*)))
+ (format t ";Reading from LEDIT:~%")
+ (ledit-load ifile)
+ (close ifile))))
+
+;;; LEDIT-LOAD
+;;; A generally useful form of load
+
+(defun ledit-load (ifile)
+ (let ((eof-form (list 'eof-form)))
+ (do ((form (read ifile eof-form) (read ifile eof-form)))
+ ((eq form eof-form))
+ (format t "; ~A~%" (eval form)))))
+
+(setsyntax #/ 'macro 'ledit) ; make ^E = (ledit)<return>
+
+;; more robust version of the c function set_proc_str. Does argument checking.
+;; set_proc_str sets the string that is stuffed to the tty after franz pauses
+;; and the csh wakes up. It is usually "%emacs" or "%vemacs" or "%?emacs"
+(defun set-proc-str (arg)
+ (if (stringp arg)
+ (set_proc_str arg)
+ (if (symbolp arg)
+ (set_proc_str (get-pname arg))
+ (error arg " is illegal argument to set-proc-str"))))
diff --git a/lib-src/leditcfns.c b/etc/leditcfns.c
index b8a7a6bfe1f..b8a7a6bfe1f 100644
--- a/lib-src/leditcfns.c
+++ b/etc/leditcfns.c
diff --git a/lib-src/make-docfile.c b/etc/make-docfile.c
index 1af038027e0..0aea1104d04 100644
--- a/lib-src/make-docfile.c
+++ b/etc/make-docfile.c
@@ -61,10 +61,10 @@ main (argc, argv)
err_count += scan_file (argv[i]); /* err_count seems to be {mis,un}used */
#ifndef VMS
exit (err_count); /* see below - shane */
-#endif VMS
+#endif /* VMS */
}
-/* Read file FILENAME and output its doc strings to outfile. */
+/* Read file FILENAME and output its doc strings to stdout. */
/* Return 1 if file is not found, 0 if it is found. */
scan_file (filename)
@@ -83,7 +83,7 @@ char buf[128];
/* Skip a C string from INFILE,
and return the character that follows the closing ".
- If printflag is positive, output string contents to outfile.
+ If printflag is positive, output string contents to stdout.
If it is negative, store contents in buf.
Convert escape sequences \n and \t to newline and tab;
discard \ followed by newline. */
@@ -135,46 +135,10 @@ read_c_string (infile, printflag)
return c;
}
-/* Write to file OUT the argument names of the function whose text is in BUF.
- MINARGS and MAXARGS are the minimum and maximum number of arguments. */
-
-write_c_args (out, buf, minargs, maxargs)
- FILE *out;
- char *buf;
- int minargs, maxargs;
-{
- register int c;
- register char *p = buf;
- int space = 0;
-
- fprintf (out, "arguments: ");
-
- while (*p)
- {
- c = *p++;
- if (c == ',')
- {
- minargs--;
- maxargs--;
- if (!space)
- putc (' ', out);
- if (minargs == 0 && maxargs > 0)
- fprintf (out, "&optional ");
- space = 1;
- continue;
- }
- else if (c == ' ' && space)
- continue;
- space = (c == ' ');
- putc (c, out);
- }
- putc ('\n', out);
-}
-
/* Read through a c file. If a .o file is named,
- the corresponding .c file is read instead.
- Looks for DEFUN constructs such as are defined in ../src/lisp.h.
- Accepts any word starting DEF... so it finds DEFSIMPLE and DEFPRED. */
+ the corresponding .c file is read instead.
+ Looks for DEFUN constructs such as are defined in ../src/lisp.h.
+ Accepts any word starting DEF... so it finds DEFSIMPLE and DEFPRED. */
scan_c_file (filename)
char *filename;
@@ -184,8 +148,7 @@ scan_c_file (filename)
register int commas;
register int defunflag;
register int defvarflag;
- int minargs, maxargs;
-
+
if (filename[strlen (filename) - 1] == 'o')
filename[strlen (filename) - 1] = 'c';
@@ -243,7 +206,7 @@ scan_c_file (filename)
while (c != '(')
{
if (c < 0)
- goto eof;
+ return 0;
c = getc (infile);
}
@@ -261,28 +224,9 @@ scan_c_file (filename)
while (commas)
{
- if (c == ',')
- {
- commas--;
- if (defunflag && (commas == 1 || commas == 2))
- {
- do
- c = getc (infile);
- while (c == ' ' || c == '\n' || c == '\t');
- if (c < 0)
- goto eof;
- ungetc (c, infile);
- if (commas == 2) /* pick up minargs */
- fscanf (infile, "%d", &minargs);
- else /* pick up maxargs */
- if (c == 'M' || c == 'U') /* MANY || UNEVALLED */
- maxargs = -1;
- else
- fscanf (infile, "%d", &maxargs);
- }
- }
+ if (c == ',') commas --;
if (c < 0)
- goto eof;
+ return 0;
c = getc (infile);
}
while (c == ' ' || c == '\n' || c == '\t')
@@ -300,41 +244,9 @@ scan_c_file (filename)
putc (037, outfile);
putc (defvarflag ? 'V' : 'F', outfile);
fprintf (outfile, "%s\n", buf);
- c = read_c_string (infile, 1);
-
- /* If this is a defun, find the arguments and print them. If
- this function takes MANY or UNEVALLED args, then the C source
- won't give the names of the arguments, so we shouldn't bother
- trying to find them. */
- if (defunflag && maxargs != -1)
- {
- char argbuf[1024], *p = argbuf;
- while (c != ')')
- {
- if (c < 0)
- goto eof;
- c = getc (infile);
- }
- /* Skip into arguments. */
- while (c != '(')
- {
- if (c < 0)
- goto eof;
- c = getc (infile);
- }
- /* Copy arguments into ARGBUF. */
- *p++ = c;
- do
- *p++ = c = getc (infile);
- while (c != ')');
- *p = '\0';
- /* Output them. */
- fprintf (outfile, "\n\n");
- write_c_args (outfile, argbuf, minargs, maxargs);
- }
+ read_c_string (infile, 1);
}
}
- eof:
fclose (infile);
return 0;
}
@@ -345,8 +257,6 @@ scan_c_file (filename)
(autoload 'NAME FILE DOCSTRING ...)
(defvar NAME VALUE DOCSTRING)
(defconst NAME VALUE DOCSTRING)
- (fset (quote NAME) (make-byte-code (quote ARGS) ... "\
- DOCSTRING")
starting in column zero.
ARGS, FILE or VALUE is ignored. We do not know how to parse Lisp code
so we use a kludge to skip them:
@@ -390,8 +300,6 @@ scan_lisp_file (filename)
c = getc (infile);
if (c != '(')
continue;
-
- /* Handle an autoload. */
c = getc (infile);
if (c == 'a')
{
@@ -471,8 +379,6 @@ scan_lisp_file (filename)
}
c = read_c_string (infile, 0);
}
-
- /* Handle def* clauses. */
else if (c == 'd')
{
c = getc (infile);
@@ -482,8 +388,6 @@ scan_lisp_file (filename)
if (c != 'f')
continue;
c = getc (infile);
-
- /* Is this a defun? */
if (c == 'u')
{
c = getc (infile);
@@ -491,8 +395,6 @@ scan_lisp_file (filename)
continue;
defvarflag = 0;
}
-
- /* Or a defvar? */
else if (c == 'v')
{
c = getc (infile);
@@ -503,8 +405,6 @@ scan_lisp_file (filename)
continue;
defvarflag = 1;
}
-
- /* Or a defconst? */
else if (c == 'c')
{
c = getc (infile);
@@ -592,155 +492,6 @@ scan_lisp_file (filename)
continue;
}
}
-
- /* Handle an fset clause. */
- else if (c == 'f')
- {
- c = getc (infile);
- if (c != 's')
- continue;
- c = getc (infile);
- if (c != 'e')
- continue;
- c = getc (infile);
- if (c != 't')
- continue;
-
- /* Skip white space */
- do
- c = getc (infile);
- while (c == ' ' || c == '\n' || c == '\t');
-
- /* Recognize "(quote". */
- if (c != '(')
- continue;
- c = getc (infile);
- if (c != 'q')
- continue;
- c = getc (infile);
- if (c != 'u')
- continue;
- c = getc (infile);
- if (c != 'o')
- continue;
- c = getc (infile);
- if (c != 't')
- continue;
- c = getc (infile);
- if (c != 'e')
- continue;
-
- /* Skip white space */
- do
- c = getc (infile);
- while (c == ' ' || c == '\n' || c == '\t');
-
- /* Read and store name of function or variable being defined
- Discard backslashes that are for quoting. */
- p = buf;
- while (c != ')' && c != ' ' && c != '\n' && c != '\t')
- {
- if (c == '\\')
- c = getc (infile);
- *p++ = c;
- c = getc (infile);
- }
- *p = '\0';
-
- /* Skip white space */
- do
- c = getc (infile);
- while (c == ' ' || c == '\n' || c == '\t');
-
- /* Recognize "(make-byte-code". */
- if (c != '(')
- continue;
- c = getc (infile);
- if (c != 'm')
- continue;
- c = getc (infile);
- if (c != 'a')
- continue;
- c = getc (infile);
- if (c != 'k')
- continue;
- c = getc (infile);
- if (c != 'e')
- continue;
- c = getc (infile);
- if (c != '-')
- continue;
- c = getc (infile);
- if (c != 'b')
- continue;
- c = getc (infile);
- if (c != 'y')
- continue;
- c = getc (infile);
- if (c != 't')
- continue;
- c = getc (infile);
- if (c != 'e')
- continue;
- c = getc (infile);
- if (c != '-')
- continue;
- c = getc (infile);
- if (c != 'c')
- continue;
- c = getc (infile);
- if (c != 'o')
- continue;
- c = getc (infile);
- if (c != 'd')
- continue;
- c = getc (infile);
- if (c != 'e')
- continue;
-
- /* Scan for a \" followed by a newline, or for )) followed by
- a newline. If we find the latter first, this function has
- no docstring. */
- {
- char c1 = 0, c2 = 0;
-
- for (;;)
- {
-
- /* Find newlines, and remember the two previous characters. */
- for (;;)
- {
- c = getc (infile);
-
- if (c == '\n' || c < 0)
- break;
-
- c2 = c1;
- c1 = c;
- }
-
- /* If we've hit eof, quit. */
- if (c == EOF)
- break;
-
- /* If the last two characters were \", this is a docstring. */
- else if (c2 == '"' && c1 == '\\')
- {
- putc (037, outfile);
- putc ('F', outfile);
- fprintf (outfile, "%s\n", buf);
- read_c_string (infile, 1);
- break;
- }
-
- /* If the last two characters were )), there is no
- docstring. */
- else if (c2 == ')' && c1 == ')')
- break;
- }
- continue;
- }
- }
else
continue;
diff --git a/etc/makedoc.com b/etc/makedoc.com
new file mode 100644
index 00000000000..c08dae9b827
--- /dev/null
+++ b/etc/makedoc.com
@@ -0,0 +1,48 @@
+$ ! VMS command file to create or update the file `DOC.' which contains
+$ ! documentation strings for the functions and variables preloaded in Emacs.
+$ ! This command file should be run when you build Emacs for the first time and
+$ ! again if any documentation strings change in the source files listed here.
+$
+$ old = f$environment("default")
+$ set default emacs_library:[etc]
+$ on error then goto done
+$ if f$search("emacs_library:[etc]make-docfile.exe") .nes. "" then goto version44
+$ doit := $emacs_library:[etc]make_docfile
+$ rest = "[lisp]lisp_mode.elc [lisp]text_mode.elc [lisp]c_mode.elc [lisp]buff_menu.elc [lisp]vms_patch.elc"
+$ goto doit
+$version44:
+$ doit := $emacs_library:[etc]make-docfile
+$ rest = "[lisp]lisp-mode.elc [lisp]text-mode.elc [lisp]c-mode.elc [lisp]buff-menu.elc [lisp]vms-patch.elc"
+$
+$doit:
+$ set default emacs_library:[000000]
+$ doit -o [etc]DOC
+$ doit := 'doit' -a [etc]DOC
+$ doit [src]dispnew.c [src]scroll.c
+$ doit [src]xdisp.c [src]window.c [src]term.c [src]cm.c
+$ doit [src]emacs.c [src]keyboard.c [src]macros.c
+$ doit [src]keymap.c [src]sysdep.c [src]buffer.c
+$ doit [src]filelock.c [src]insdel.c [src]marker.c
+$ doit [src]minibuf.c [src]fileio.c [src]dired.c
+$ doit [src]filemode.c [src]cmds.c [src]casefiddle.c
+$ doit [src]indent.c [src]search.c [src]regex.c
+$ doit [src]undo.c [src]alloc.c [src]data.c [src]doc.c
+$ doit [src]editfns.c [src]callint.c [src]eval.c
+$ doit [src]fns.c [src]print.c [src]lread.c [src]abbrev.c
+$ doit [src]syntax.c [src]mocklisp.c
+$ doit [src]bytecode.c [src]process.c [src]callproc.c [src]doprnt.c
+$ doit [src]vmsfns.c
+$
+$ doit [lisp]simple.elc [lisp]help.elc
+$ doit [lisp]files.elc [lisp]window.elc
+$ doit [lisp]indent.elc [lisp]loaddefs.el
+$ doit [lisp]paths.el [lisp]startup.elc
+$ doit [lisp]lisp.elc [lisp]page.elc
+$ doit [lisp]register.elc [lisp]paragraphs.elc
+$ doit [lisp]fill.elc [lisp]isearch.elc
+$ doit [lisp]replace.elc [lisp]abbrev.elc
+$ doit [lisp]subr.elc [lisp]vmsproc.elc
+$ doit 'rest'
+$
+$done:
+$ set default 'old'
diff --git a/lib-src/movemail.c b/etc/movemail.c
index 9709202e131..f27052bf4f6 100644
--- a/lib-src/movemail.c
+++ b/etc/movemail.c
@@ -18,6 +18,18 @@ You should have received a copy of the GNU General Public License
along with GNU Emacs; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+/* Important notice: defining MAIL_USE_FLOCK *will cause loss of mail*
+ if you do it on a system that does not normally use flock as its way of
+ interlocking access to inbox files. The setting of MAIL_USE_FLOCK
+ *must agree* with the system's own conventions.
+ It is not a choice that is up to you.
+
+ So, if your system uses lock files rather than flock, then the only way
+ you can get proper operation is to enable movemail to write lockfiles there.
+ This means you must either give that directory access modes
+ that permit everyone to write lockfiles in it, or you must make movemail
+ a setuid or setgid program. */
+
/*
* Modified January, 1986 by Michael R. Gretzinger (Project Athena)
*
@@ -29,7 +41,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
*
* New module: popmail.c
* Modified routines:
- * main - added code within #ifdef MAIL_USE_POP; added setuid(getuid())
+ * main - added code within #ifdef MAIL_USE_POP; added setuid (getuid ())
* after POP code.
* New routines in movemail.c:
* get_errmsg - return pointer to system error message
@@ -88,7 +100,7 @@ main (argc, argv)
long now;
int tem;
char *lockname, *p;
- char tempname[40];
+ char *tempname;
int desc;
#endif /* not MAIL_USE_FLOCK */
@@ -133,7 +145,7 @@ main (argc, argv)
exit (status);
}
- setuid (getuid());
+ setuid (getuid ());
#endif /* MAIL_USE_POP */
/* Check access to input file. */
@@ -144,7 +156,29 @@ main (argc, argv)
#ifndef MAIL_USE_FLOCK
/* Use a lock file named /usr/spool/mail/$USER.lock:
If it exists, the mail file is locked. */
+ /* Note: this locking mechanism is *required* by the mailer
+ (on systems which use it) to prevent loss of mail.
+
+ On systems that use a lock file, extracting the mail without locking
+ WILL occasionally cause loss of mail due to timing errors!
+
+ So, if creation of the lock file fails
+ due to access permission on /usr/spool/mail,
+ you simply MUST change the permission
+ and/or make movemail a setgid program
+ so it can create lock files properly.
+
+ You might also wish to verify that your system is one
+ which uses lock files for this purpose. Some systems use other methods.
+
+ If your system uses the `flock' system call for mail locking,
+ define MAIL_USE_FLOCK in config.h or the s-*.h file
+ and recompile movemail. If the s- file for your system
+ should define MAIL_USE_FLOCK but does not, send a bug report
+ to bug-gnu-emacs@prep.ai.mit.edu so we can fix it. */
+
lockname = concat (inname, ".lock", "");
+ tempname = (char *) xmalloc (strlen (inname) + 20);
strcpy (tempname, inname);
p = tempname + strlen (tempname);
while (p != tempname && p[-1] != '/')
@@ -152,7 +186,7 @@ main (argc, argv)
*p = 0;
strcpy (p, "EXXXXXX");
mktemp (tempname);
- (void) unlink (tempname);
+ unlink (tempname);
while (1)
{
@@ -160,11 +194,11 @@ main (argc, argv)
/* Give up if cannot do that. */
desc = open (tempname, O_WRONLY | O_CREAT, 0666);
if (desc < 0)
- pfatal_with_name (concat ("temporary file \"", tempname, "\""));
+ pfatal_with_name ("lock file--see source file etc/movemail.c");
close (desc);
tem = link (tempname, lockname);
- (void) unlink (tempname);
+ unlink (tempname);
if (tem >= 0)
break;
sleep (1);
@@ -174,7 +208,7 @@ main (argc, argv)
{
now = time (0);
if (st.st_ctime < now - 60)
- (void) unlink (lockname);
+ unlink (lockname);
}
}
@@ -193,7 +227,7 @@ main (argc, argv)
if (indesc < 0)
pfatal_with_name (inname);
-#if defined(BSD) || defined(XENIX)
+#if defined (BSD) || defined (XENIX)
/* In case movemail is setuid to root, make sure the user can
read the output file. */
/* This is desirable for all systems
@@ -217,7 +251,7 @@ main (argc, argv)
if (nread != write (outdesc, buf, nread))
{
int saved_errno = errno;
- (void) unlink (outname);
+ unlink (outname);
errno = saved_errno;
pfatal_with_name (outname);
}
@@ -226,24 +260,20 @@ main (argc, argv)
}
#ifdef BSD
- fsync (outdesc);
+ if (fsync (outdesc) < 0)
+ pfatal_and_delete (outname);
#endif
/* Check to make sure no errors before we zap the inbox. */
if (close (outdesc) != 0)
- {
- int saved_errno = errno;
- (void) unlink (outname);
- errno = saved_errno;
- pfatal_with_name (outname);
- }
+ pfatal_and_delete (outname);
#ifdef MAIL_USE_FLOCK
-#if defined(STRIDE) || defined(XENIX)
+#if defined (STRIDE) || defined (XENIX)
/* Stride, xenix have file locking, but no ftruncate. This mess will do. */
- (void) close (open (inname, O_CREAT | O_TRUNC | O_RDWR, 0666));
+ close (open (inname, O_CREAT | O_TRUNC | O_RDWR, 0666));
#else
- (void) ftruncate (indesc, 0L);
+ ftruncate (indesc, 0L);
#endif /* STRIDE or XENIX */
#endif /* MAIL_USE_FLOCK */
@@ -300,6 +330,22 @@ pfatal_with_name (name)
fatal (s, name);
}
+pfatal_and_delete (name)
+ char *name;
+{
+ extern int errno, sys_nerr;
+ extern char *sys_errlist[];
+ char *s;
+
+ if (errno < sys_nerr)
+ s = concat ("", sys_errlist[errno], " for %s");
+ else
+ s = "cannot open %s";
+
+ unlink (name);
+ fatal (s, name);
+}
+
/* Return a newly-allocated string whose contents concatenate those of s1, s2, s3. */
char *
@@ -337,6 +383,7 @@ xmalloc (size)
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
+#include <pwd.h>
#ifdef USG
#include <fcntl.h>
@@ -372,6 +419,9 @@ popmail (user, outfile)
register int i;
int mbfi;
FILE *mbf;
+ struct passwd *pw = (struct passwd *) getpwuid (getuid ());
+ if (pw == NULL)
+ fatal ("cannot determine user name");
host = getenv ("MAILHOST");
if (host == NULL)
@@ -381,29 +431,25 @@ popmail (user, outfile)
if (pop_init (host) == NOTOK)
{
- error (Errmsg);
- return 1;
+ fatal (Errmsg);
}
if (getline (response, sizeof response, sfi) != OK)
{
- error (response);
- return 1;
+ fatal (response);
}
- if (pop_command ("USER %s", user) == NOTOK
- || pop_command ("RPOP %s", user) == NOTOK)
+ if (pop_command ("USER %s", user) == NOTOK
+ || pop_command ("RPOP %s", pw->pw_name) == NOTOK)
{
- error (Errmsg);
pop_command ("QUIT");
- return 1;
+ fatal (Errmsg);
}
if (pop_stat (&nmsgs, &nbytes) == NOTOK)
{
- error (Errmsg);
pop_command ("QUIT");
- return 1;
+ fatal (Errmsg);
}
if (!nmsgs)
@@ -416,18 +462,14 @@ popmail (user, outfile)
if (mbfi < 0)
{
pop_command ("QUIT");
- error ("Error in open: %s, %s", get_errmsg (), outfile);
- return 1;
+ pfatal_and_delete (outfile);
}
fchown (mbfi, getuid (), -1);
if ((mbf = fdopen (mbfi, "w")) == NULL)
{
pop_command ("QUIT");
- error ("Error in fdopen: %s", get_errmsg ());
- close (mbfi);
- unlink (outfile);
- return 1;
+ pfatal_and_delete (outfile);
}
for (i = 1; i <= nmsgs; i++)
@@ -435,29 +477,37 @@ popmail (user, outfile)
mbx_delimit_begin (mbf);
if (pop_retr (i, mbx_write, mbf) != OK)
{
- error (Errmsg);
pop_command ("QUIT");
close (mbfi);
- return 1;
+ unlink (outfile);
+ fatal (Errmsg);
}
mbx_delimit_end (mbf);
fflush (mbf);
}
+ if (fsync (mbfi) < 0)
+ {
+ pop_command ("QUIT");
+ pfatal_and_delete (outfile);
+ }
+
+ if (close (mbfi) == -1)
+ {
+ pop_command ("QUIT");
+ pfatal_and_delete (outfile);
+ }
+
for (i = 1; i <= nmsgs; i++)
{
if (pop_command ("DELE %d", i) == NOTOK)
{
- error (Errmsg);
- pop_command ("QUIT");
- close (mbfi);
- return 1;
+ /* Better to ignore this failure. */
}
}
pop_command ("QUIT");
- close (mbfi);
- return 0;
+ return (0);
}
pop_init (host)
@@ -529,7 +579,8 @@ pop_command (fmt, a, b, c, d)
return NOTOK;
}
- if (debug) fprintf (stderr, "<--- %s\n", buf);
+ if (debug)
+ fprintf (stderr, "<--- %s\n", buf);
if (*buf != '+')
{
strcpy (Errmsg, buf);
@@ -547,8 +598,10 @@ pop_stat (nmsgs, nbytes)
{
char buf[128];
- if (debug) fprintf (stderr, "---> STAT\n");
- if (putline ("STAT", Errmsg, sfo) == NOTOK) return NOTOK;
+ if (debug)
+ fprintf (stderr, "---> STAT\n");
+ if (putline ("STAT", Errmsg, sfo) == NOTOK)
+ return NOTOK;
if (getline (buf, sizeof buf, sfi) != OK)
{
@@ -635,17 +688,14 @@ multiline (buf, n, f)
register int n;
FILE *f;
{
- if (getline (buf, n, f) != OK) return NOTOK;
+ if (getline (buf, n, f) != OK)
+ return NOTOK;
if (*buf == '.')
{
if (*(buf+1) == NULL)
- {
- return DONE;
- }
+ return DONE;
else
- {
- strcpy (buf, buf+1);
- }
+ strcpy (buf, buf+1);
}
return OK;
}
diff --git a/etc/ms-kermit b/etc/ms-kermit
new file mode 100644
index 00000000000..e7dba440e07
--- /dev/null
+++ b/etc/ms-kermit
@@ -0,0 +1,167 @@
+;;; This file is designed for an 8-bit connection.
+;;; Use the file ms-kermit-7bit if you have a 7-bit connection.
+
+;; Meta key mappings for EMACS
+;; By Robert Earl (rearl@watnxt3.ucr.edu)
+;; May 13, 1990
+;;
+;; WARNING:
+;; requires an 8-bit path to host. many dialups and lans won't pass the
+;; eighth bit by default and may require a special command to turn this
+;; off. `screen' is known to mask the eighth bit of input as well.
+
+set term controls 8-bit
+set translation key off
+
+;; control keys
+set key \3449 \128 ;; m-c-@
+set key \3358 \129 ;; m-c-a
+set key \3376 \130 ;; m-c-b
+set key \3374 \131 ;; m-c-c
+set key \3360 \132 ;; m-c-d
+set key \3346 \133 ;; m-c-e
+set key \3361 \134 ;; m-c-f
+set key \3362 \135 ;; m-c-g
+set key \3342 \136 ;; m-bs
+set key \3363 \136 ;; m-c-h (sends same code as above)
+set key \2469 \137 ;; m-tab
+set key \3351 \137 ;; m-c-i (same as above)
+set key \3364 \138 ;; m-c-j
+set key \3365 \139 ;; m-c-k
+set key \3366 \140 ;; m-c-l
+;set key \3378 \141 ;; m-c-m
+set key \2332 \141 ;; m-ret (sends same code as above)
+set key \3377 \142 ;; m-c-n
+set key \3352 \143 ;; m-c-o
+set key \3353 \144 ;; m-c-p
+set key \3344 \145 ;; m-c-q
+set key \3347 \146 ;; m-c-r
+set key \3359 \147 ;; m-c-s
+set key \3348 \148 ;; m-c-t
+set key \3350 \149 ;; m-c-u
+set key \3375 \150 ;; m-c-v
+set key \3345 \151 ;; m-c-w
+set key \3373 \152 ;; m-c-x
+set key \3349 \153 ;; m-c-y
+set key \3372 \154 ;; m-c-z
+
+;; misc keys
+;set key \3354 \155 ;; m-c-[
+set key \2305 \155 ;; m-esc (sends same as above)
+set key \3371 \156 ;; m-c-\
+set key \3355 \157 ;; m-c-]
+set key \3453 \158 ;; m-c-^
+set key \3458 \159 ;; m-c-_
+
+;; \160 is conspicuously missing here--
+;; alt-spc doesn't generate a distinct scan code...
+;; neither do shift-spc and ctrl-spc.
+;; no idea why.
+
+set key \2936 \161 ;; m-!
+set key \2856 \162 ;; m-"
+set key \2938 \163 ;; m-#
+set key \2939 \164 ;; m-$
+set key \2940 \165 ;; m-%
+set key \2942 \166 ;; m-&
+set key \2344 \167 ;; m-'
+set key \2944 \168 ;; m-(
+set key \2945 \169 ;; m-)
+set key \2943 \170 ;; m-*
+set key \2947 \171 ;; m-+
+set key \2355 \172 ;; m-,
+set key \2434 \173 ;; m--
+set key \2356 \174 ;; m-.
+set key \2357 \175 ;; m-/
+
+;; number keys
+set key \2433 \176 ;; m-0
+set key \2424 \177 ;; m-1
+set key \2425 \178
+set key \2426 \179
+set key \2427 \180
+set key \2428 \181
+set key \2429 \182
+set key \2430 \183
+set key \2431 \184
+set key \2432 \185 ;; m-9
+
+set key \2855 \186 ;; m-:
+set key \2343 \187 ;; m-;
+set key \2867 \188 ;; m-<
+set key \2435 \189 ;; m-=
+set key \2868 \190 ;; m->
+set key \2869 \191 ;; m-?
+set key \2937 \192 ;; m-@
+
+;; shifted A-Z
+set key \2846 \193 ;; m-A
+set key \2864 \194
+set key \2862 \195
+set key \2848 \196
+set key \2834 \197
+set key \2849 \198
+set key \2850 \199
+set key \2851 \200
+set key \2839 \201
+set key \2852 \202
+set key \2853 \203
+set key \2854 \204
+set key \2866 \205
+set key \2865 \206
+set key \2840 \207
+set key \2841 \208
+set key \2832 \209
+set key \2835 \210
+set key \2847 \211
+set key \2836 \212
+set key \2838 \213
+set key \2863 \214
+set key \2833 \215
+set key \2861 \216
+set key \2837 \217
+set key \2860 \218 ;; m-Z
+
+set key \2330 \219 ;; m-[
+set key \2347 \220 ;; m-\
+set key \2331 \221 ;; m-]
+set key \2941 \222 ;; m-^
+set key \2946 \223 ;; m-_
+set key \2345 \224 ;; m-`
+
+;; lowercase a-z
+set key \2334 \225 ;; m-a
+set key \2352 \226
+set key \2350 \227
+set key \2336 \228
+set key \2322 \229
+set key \2337 \230
+set key \2338 \231
+set key \2339 \232
+set key \2327 \233
+set key \2340 \234
+set key \2341 \235
+set key \2342 \236
+set key \2354 \237
+set key \2353 \238
+set key \2328 \239
+set key \2329 \240
+set key \2320 \241
+set key \2323 \242
+set key \2335 \243
+set key \2324 \244
+set key \2326 \245
+set key \2351 \246
+set key \2321 \247
+set key \2349 \248
+set key \2325 \249
+set key \2348 \250 ;; m-z
+
+;; more shifted misc. keys
+set key \2842 \251 ;; m-{
+set key \2859 \252 ;; m-|
+set key \2843 \253 ;; m-}
+set key \2857 \254 ;; m-~
+set key \2318 \255 ;; m-del
+
+
diff --git a/etc/ms-kermit-7bit b/etc/ms-kermit-7bit
new file mode 100644
index 00000000000..7a55179876b
--- /dev/null
+++ b/etc/ms-kermit-7bit
@@ -0,0 +1,312 @@
+;;; This file is designed for 7-bit connections.
+;;; Use the file ms-kermit if you have an 8-bit connection.
+
+;;; This kermit script maps the IBM-PC keyboard for use with Gnu Emacs.
+;;; The ALT key is used to generate Meta characters and, in conjunction
+;;; with the CTRL key, Control-Meta characters. A few other useful
+;;; mappings are also performed.
+;;; Andy Lowry, May 1989
+
+;;; Exchange ESC and backquote... tilde stays put (shift-backquote)
+set key \27 `
+set key ` \27
+
+;;; BACKSPACE deletes backward one character
+set key scan \270 \127
+
+;;; The following mappings affect certain special keys... all the keys
+;;; are duplicated on the numeric keypad when NUM LOCK is off, but
+;;; the keypad versions are NOT mapped (string definition space too small
+;;; for that)
+
+;;; INSERT toggles overwrite mode
+set key scan \4434 \27xoverwrite-mode\13
+;;; HOME moves point to beginning of buffer
+set key scan \4423 \27<
+;;; PAGE-UP scrolls backward one screen
+set key scan \4425 \27v
+;;; DELETE deletes one character *forward*
+set key scan \4435 \4
+;;; END moves point to end of buffer
+set key scan \4431 \27>
+;;; PAGE-DOWN scrolls forward one screen
+set key scan \4433 \22
+;;; ARROW keys move in the appropriate directions
+set key scan \4424 \16
+set key scan \4427 \2
+set key scan \4432 \14
+set key scan \4429 \6
+
+;;; META versions of all the printing characters except uppercase
+;;; letters are generated by using the ALT key. The definition string
+;;; consists of an ESC character followed by the META-ized character.
+;;; The characters are listed roughly left-to-right and top-to-bottom
+;;; as they appear on the keyboard
+set key scan \2345 \27`
+set key scan \2424 \27\o61 ; need to use char code, since digit
+set key scan \2425 \27\o62 ; would not terminate '\27'
+set key scan \2426 \27\o63
+set key scan \2427 \27\o64
+set key scan \2428 \27\o65
+set key scan \2429 \27\o66
+set key scan \2430 \27\o67
+set key scan \2431 \27\o70
+set key scan \2432 \27\o71
+set key scan \2433 \27\o60
+set key scan \2434 \27\45
+set key scan \2435 \27=
+set key scan \2857 \27~
+set key scan \2936 \27!
+set key scan \2937 \27@
+set key scan \2938 \27#
+set key scan \2939 \27$
+set key scan \2940 \27%
+set key scan \2941 \27^
+set key scan \2942 \27&
+set key scan \2943 \27*
+set key scan \2944 \27(
+set key scan \2945 \27)
+set key scan \2946 \27_
+set key scan \2947 \27+
+set key scan \2469 \27\9
+set key scan \2320 \27q
+set key scan \2321 \27w
+set key scan \2322 \27e
+set key scan \2323 \27r
+set key scan \2324 \27t
+set key scan \2325 \27y
+set key scan \2326 \27u
+set key scan \2327 \27i
+set key scan \2328 \27o
+set key scan \2329 \27p
+set key scan \2330 \27[
+set key scan \2842 \27{
+set key scan \2331 \27]
+set key scan \2843 \27}
+set key scan \2347 \27\
+set key scan \2859 \27|
+set key scan \2334 \27a
+set key scan \2335 \27s
+set key scan \2336 \27d
+set key scan \2337 \27f
+set key scan \2338 \27g
+set key scan \2339 \27h
+set key scan \2340 \27j
+set key scan \2341 \27k
+set key scan \2342 \27l
+set key scan \2343 \27\59
+set key scan \2855 \27:
+set key scan \2344 \27'
+set key scan \2856 \27"
+set key scan \2348 \27z
+set key scan \2349 \27x
+set key scan \2350 \27c
+set key scan \2351 \27v
+set key scan \2352 \27b
+set key scan \2353 \27n
+set key scan \2354 \27m
+set key scan \2355 \27,
+set key scan \2867 \27<
+set key scan \2356 \27.
+set key scan \2868 \27>
+set key scan \2357 \27/
+set key scan \2869 \27?
+
+;;; CONTROL-META characters are generated by using both the CTRL and
+;;; ALT keys simultaneously. All the lowercase letters are included.
+;;; The definition string consists of an ESC character followed by
+;;; the control character corresponding to the letter.
+set key scan \3344 \27\17
+set key scan \3345 \27\23
+set key scan \3346 \27\5
+set key scan \3347 \27\18
+set key scan \3348 \27\20
+set key scan \3349 \27\25
+set key scan \3350 \27\21
+set key scan \3351 \27\9
+set key scan \3352 \27\15
+set key scan \3353 \27\16
+set key scan \3358 \27\1
+set key scan \3359 \27\19
+set key scan \3360 \27\4
+set key scan \3361 \27\6
+set key scan \3362 \27\7
+set key scan \3363 \27\8
+set key scan \3364 \27\10
+set key scan \3365 \27\11
+set key scan \3366 \27\12
+set key scan \3372 \27\26
+set key scan \3373 \27\24
+set key scan \3374 \27\3
+set key scan \3375 \27\22
+set key scan \3376 \27\2
+set key scan \3377 \27\14
+set key scan \3378 \27\13
+
+end of msiem2.ini
+------------------
+
+msiema.hlp
+-----------
+Date: Wed, 14 Sep 88 05:20:08 GMT
+From: spolsky@YALE.ARPA
+Subject: Using MS kermit 2.31 with emacs
+Keywords: MS-DOS Kermit 2.31, EMACS, Meta Key
+
+If you are using kermit (version 2.31 only) with emacs on a mainframe, the
+following file may help you. It assigns all the Alt-keys so that the Alt key
+may be used as a "Meta" shift, e.g. Alt-x produces M-x, etc. Note that it
+will distinguish correctly between upper and lower case and accepts all
+printables. (If anybody has the patience to do the Meta-Ctrl combinations,
+please post them!) This actually sends "escapes" so you don't need 8 bits.
+This file also sets up the cursor keys to behave as expected.
+
+On extended keyboards (the ones with a separate cursor pad, like PS/2s) you
+also get assignments for Page Up/Down, Home, End, Insert, Delete, etc.
+
+Please let me know if you find any problems with this.
+
+Joel Spolsky bitnet: spolsky@yalecs uucp: ...!yale!spolsky
+Yale University arpa: spolsky@yale.edu voicenet: 203-436-1483
+
+[Ed. - Thanks, Joel! Your key definitions file has been put in the kermit
+distribution area as msiema.ini ("ms" for MS-Kermit, "i" because it's an
+initialization file, "ema" for EMACS), along with this message as msiema.hlp.]
+
+end of msiema.hlp
+-----------------
+
+
+msiema.ini
+------------
+; Emacs keyboard layout for Kermit 2.31
+; by Joel Spolsky, Yale Univ. Save this in a file, then
+; initialize it by issuing the kermit command
+; take filename
+; It will set up the keyboard to allow ALT to be used
+; as a meta-key, and will allow cursor keys to be used
+; with emacs.
+
+; First, define all the ALT keys to send ESC+key
+; to simulate "meta"
+
+set key \2320 \27q ;; letters: unshifted
+set key \2321 \27w
+set key \2322 \27e
+set key \2323 \27r
+set key \2324 \27t
+set key \2325 \27y
+set key \2326 \27u
+set key \2327 \27i
+set key \2328 \27o
+set key \2329 \27p
+set key \2334 \27a
+set key \2335 \27s
+set key \2336 \27d
+set key \2337 \27f
+set key \2338 \27g
+set key \2339 \27h
+set key \2340 \27j
+set key \2341 \27k
+set key \2342 \27l
+set key \2348 \27z
+set key \2349 \27x
+set key \2350 \27c
+set key \2351 \27v
+set key \2352 \27b
+set key \2353 \27n
+set key \2354 \27m
+set key \2832 \27Q ;; letters: shifted
+set key \2833 \27W
+set key \2834 \27E
+set key \2835 \27R
+set key \2836 \27T
+set key \2837 \27Y
+set key \2838 \27U
+set key \2839 \27I
+set key \2840 \27O
+set key \2841 \27P
+set key \2846 \27A
+set key \2847 \27S
+set key \2848 \27D
+set key \2849 \27F
+set key \2850 \27G
+set key \2851 \27H
+set key \2852 \27J
+set key \2853 \27K
+set key \2854 \27L
+set key \2860 \27Z
+set key \2861 \27X
+set key \2862 \27C
+set key \2863 \27V
+set key \2864 \27B
+set key \2865 \27N
+set key \2866 \27M
+set key \2857 \27\126 ; ALT + ~ ;; special symbols begin here
+set key \2345 \27\96 ; ALT + `
+set key \2936 \27\33 ; ALT + !
+set key \2937 \27\64 ; ALT + @
+set key \2938 \27\35 ; ALT + #
+set key \2939 \27\36 ; ALT + $
+set key \2940 \27\37 ; ALT + %
+set key \2941 \27\94 ; ALT + ^
+set key \2942 \27\38 ; ALT + &
+set key \2943 \27\42 ; ALT + *
+set key \2944 \27\40 ; ALT + (
+set key \2945 \27\41 ; ALT + )
+set key \2946 \27\95 ; ALT + _
+set key \2947 \27\43 ; ALT + +
+set key \2842 \27\123 ; ALT + {
+set key \2843 \27\125 ; ALT + }
+set key \2330 \27\91 ; ALT + [
+set key \2331 \27\93 ; ALT + ]
+set key \2859 \27\124 ; ALT + :
+set key \2347 \27\92 ; ALT + \
+set key \2867 \27< ; ALT + <
+set key \2868 \27> ; ALT + >
+set key \2343 \27\59 ; ALT + ;
+set key \2855 \27\58 ; ALT + :
+set key \2344 \27\39 ; ALT + '
+set key \2856 \27\34 ; ALT + "
+set key \2355 \27\44 ; ALT + ,
+set key \2356 \27\46 ; ALT + .
+set key \2357 \27\47 ; ALT + /
+set key \2869 \27\63 ; ALT + ?
+set key \2424 \27\49 ;; numbers
+set key \2425 \27\50
+set key \2426 \27\51
+set key \2427 \27\52
+set key \2428 \27\53
+set key \2429 \27\54
+set key \2430 \27\55
+set key \2431 \27\56
+set key \2432 \27\57
+set key \2433 \27\48
+
+;; These 6 special keys for extended (PS/2) keyboards:
+set key \4434 \25 ;; Insert is like ^Y - yank from kill ring
+set key \4435 \23 ;; Delete is like ^W - kill to ring
+set key \4423 \1 ;; Home is ^A
+set key \4431 \5 ;; End is ^E
+set key \4425 \27V ;; Page up is Esc-V
+set key \4433 \22 ;; Page dn is ^v
+
+set key \328 \16 ;; up cursor is ^P
+set key \331 \2 ;; left cursor is ^B
+set key \333 \6 ;; right cursor is ^F
+set key \336 \14 ;; down cursor is ^N
+set key \4427 \2 ;; left cursor on extended kbd
+set key \4432 \14 ;; down cursor on extended kbd
+set key \4424 \16 ;; up cursor on extended kbd
+set key \4429 \6 ;; right cursor on extended kbd
+
+set key \5491 \27b ;; ctrl-left cursor is M-b
+set key \5492 \27f ;; ctrl-right cursor is M-f
+
+;; move kermit's screen scroll (playback) features to Alt- Home,End,PgUp,PgDn
+;; (this is an issue for extended keyboards only)
+
+set key \2455 \khomscn
+set key \2463 \kendscn
+set key \2457 \kupscn
+set key \2465 \kdnscn
diff --git a/etc/qsort.c b/etc/qsort.c
new file mode 100644
index 00000000000..23a5162c5bc
--- /dev/null
+++ b/etc/qsort.c
@@ -0,0 +1,226 @@
+/*
+ * qsort.c:
+ * Our own version of the system qsort routine which is faster by an average
+ * of 25%, with lows and highs of 10% and 50%.
+ * The THRESHold below is the insertion sort threshold, and has been adjusted
+ * for records of size 48 bytes.
+ * The MTHREShold is where we stop finding a better median.
+ */
+
+#define THRESH 4 /* threshold for insertion */
+
+#define MTHRESH 6 /* threshold for median */
+
+
+
+static int qsz; /* size of each record */
+static int (*qcmp)(); /* the comparison routine */
+
+static int thresh; /* THRESHold in chars */
+static int mthresh; /* MTHRESHold in chars */
+
+/*
+ * qsort:
+ * First, set up some global parameters for qst to share. Then, quicksort
+ * with qst(), and then a cleanup insertion sort ourselves. Sound simple?
+ * It's not...
+ */
+qsort (base, n, size, compar)
+ char *base;
+ int n;
+ int size;
+ int (*compar)();
+{
+ register char *i, *j, *lo, *hi, *min;
+ register int c;
+ char *max;
+
+ if (n <= 1) return;
+ qsz = size;
+ qcmp = compar;
+ thresh = qsz*THRESH;
+ mthresh = qsz*MTHRESH;
+ max = base + n*qsz;
+ if (n >= THRESH)
+ {
+ qst (base, max);
+ hi = base + thresh;
+ }
+ else
+ {
+ hi = max;
+ }
+ /*
+ * First put smallest element, which must be in the first THRESH, in
+ * the first position as a sentinel. This is done just by searching
+ * the first THRESH elements (or the first n if n < THRESH), finding
+ * the min, and swapping it into the first position.
+ */
+ for (j = lo = base; (lo += qsz) < hi; )
+ {
+ if ((*qcmp) (j, lo) > 0)
+ j = lo;
+ }
+ if (j != base)
+ { /* swap j into place */
+ for (i = base, hi = base + qsz; i < hi;)
+ {
+ c = *j;
+ *j++ = *i;
+ *i++ = c;
+ }
+ }
+ /*
+ * With our sentinel in place, we now run the following hyper-fast
+ * insertion sort. For each remaining element, min, from [1] to [n-1],
+ * set hi to the index of the element AFTER which this one goes.
+ * Then, do the standard insertion sort shift on a character at a time
+ * basis for each element in the frob.
+ */
+ for (min = base; (hi = min += qsz) < max;)
+ {
+ while ( (*qcmp) (hi -= qsz, min) > 0);
+ if ((hi += qsz) != min)
+ {
+ for (lo = min + qsz; --lo >= min;)
+ {
+ c = *lo;
+ for (i = j = lo; (j -= qsz) >= hi; i = j)
+ *i = *j;
+ *i = c;
+ }
+ }
+ }
+}
+
+/*
+ * qst:
+ * Do a quicksort
+ * First, find the median element, and put that one in the first place as the
+ * discriminator. (This "median" is just the median of the first, last and
+ * middle elements). (Using this median instead of the first element is a big
+ * win). Then, the usual partitioning/swapping, followed by moving the
+ * discriminator into the right place. Then, figure out the sizes of the two
+ * partions, do the smaller one recursively and the larger one via a repeat of
+ * this code. Stopping when there are less than THRESH elements in a partition
+ * and cleaning up with an insertion sort (in our caller) is a huge win.
+ * All data swaps are done in-line, which is space-losing but time-saving.
+ * (And there are only three places where this is done).
+ */
+
+qst (base, max)
+ char *base, *max;
+{
+ register char *i, *j, *jj, *mid;
+ register int ii, c;
+ char *tmp;
+ int lo, hi;
+
+ lo = max - base; /* number of elements as chars */
+ do
+ {
+ /*
+ * At the top here, lo is the number of characters of elements in the
+ * current partition. (Which should be max - base).
+ * Find the median of the first, last, and middle element and make that the
+ * middle element. Set j to largest of first and middle. If max is larger
+ * than that guy, then it's that guy, else compare max with loser of first
+ * and take larger. Things are set up to prefer the middle, then the first
+ * in case of ties.
+ */
+ mid = i = base + qsz * ((lo/qsz) >> 1);
+ if (lo >= mthresh)
+ {
+ j = ((*qcmp) ((jj = base), i) > 0 ? jj : i);
+ if ((*qcmp) (j, (tmp = max - qsz)) > 0)
+ {
+ j = (j == jj ? i : jj); /* switch to first loser */
+ if ((*qcmp) (j, tmp) < 0)
+ j = tmp;
+ }
+ if (j != i)
+ {
+ ii = qsz;
+ do
+ {
+ c = *i;
+ *i++ = *j;
+ *j++ = c;
+ }
+ while( --ii );
+ }
+ }
+ /*
+ * Semi-standard quicksort partitioning/swapping
+ */
+ for (i = base, j = max - qsz; ;)
+ {
+ while (i < mid && (*qcmp) (i, mid) <= 0)
+ i += qsz;
+ while (j > mid)
+ {
+ if ((*qcmp) (mid, j) <= 0)
+ {
+ j -= qsz;
+ continue;
+ }
+ tmp = i + qsz; /* value of i after swap */
+ if (i == mid)
+ { /* j <-> mid, new mid is j */
+ mid = jj = j;
+ }
+ else
+ { /* i <-> j */
+ jj = j;
+ j -= qsz;
+ }
+ goto swap;
+ }
+ if (i == mid)
+ {
+ break;
+ }
+ else
+ { /* i <-> mid, new mid is i */
+ jj = mid;
+ tmp = mid = i; /* value of i after swap */
+ j -= qsz;
+ }
+ swap:
+ ii = qsz;
+ do
+ {
+ c = *i;
+ *i++ = *jj;
+ *jj++ = c;
+ }
+ while (--ii);
+ i = tmp;
+ }
+ /*
+ * Look at sizes of the two partitions, do the smaller one first by
+ * recursion, then do the larger one by making sure lo is its size,
+ * base and max are update correctly, and branching back.
+ * But only repeat (recursively or by branching) if the partition is
+ * of at least size THRESH.
+ */
+ i = (j = mid) + qsz;
+ if ((lo = j - base) <= (hi = max - i))
+ {
+ if (lo >= thresh)
+ qst (base, j);
+ base = i;
+ lo = hi;
+ }
+ else
+ {
+ if (hi >= thresh)
+ qst (i, max);
+ max = j;
+ }
+ }
+ while (lo >= thresh);
+}
+
+
+
diff --git a/etc/refcard.tex b/etc/refcard.tex
new file mode 100644
index 00000000000..78f5cedd42f
--- /dev/null
+++ b/etc/refcard.tex
@@ -0,0 +1,627 @@
+% Reference Card for GNU Emacs version 18 on Unix systems
+%**start of header
+\newcount\columnsperpage
+
+% This file can be printed with 1, 2, or 3 columns per page (see below).
+% Specify how many you want here. Nothing else needs to be changed.
+
+\columnsperpage=1
+
+% Copyright (c) 1987 Free Software Foundation, Inc.
+
+% This file is part of GNU Emacs.
+
+% GNU Emacs is free software; you can redistribute it and/or modify
+% it under the terms of the GNU General Public License as published by
+% the Free Software Foundation; either version 1, or (at your option)
+% any later version.
+
+% GNU Emacs is distributed in the hope that it will be useful,
+% but WITHOUT ANY WARRANTY; without even the implied warranty of
+% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+% GNU General Public License for more details.
+
+% You should have received a copy of the GNU General Public License
+% along with GNU Emacs; see the file COPYING. If not, write to
+% the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+% This file is intended to be processed by plain TeX (TeX82).
+%
+% The final reference card has six columns, three on each side.
+% This file can be used to produce it in any of three ways:
+% 1 column per page
+% produces six separate pages, each of which needs to be reduced to 80%.
+% This gives the best resolution.
+% 2 columns per page
+% produces three already-reduced pages.
+% You will still need to cut and paste.
+% 3 columns per page
+% produces two pages which must be printed sideways to make a
+% ready-to-use 8.5 x 11 inch reference card.
+% For this you need a dvi device driver that can print sideways.
+% Which mode to use is controlled by setting \columnsperpage above.
+%
+% Author:
+% Stephen Gildea
+% UUCP: mit-erl!gildea
+% Internet: gildea@erl.mit.edu
+%
+% Thanks to Paul Rubin, Bob Chassell, Len Tower, and Richard Mlynarik
+% for their many good ideas.
+
+% If there were room, it would be nice to see sections on
+% Abbrevs, Rectangles, and Dired.
+
+\def\versionnumber{1.9}
+\def\year{1987}
+\def\version{March \year\ v\versionnumber}
+
+\def\shortcopyrightnotice{\vskip 1ex plus 2 fill
+ \centerline{\small \copyright\ \year\ Free Software Foundation, Inc.
+ Permissions on back. v\versionnumber}}
+
+\def\copyrightnotice{
+\vskip 1ex plus 2 fill\begingroup\small
+\centerline{Copyright \copyright\ \year\ Free Software Foundation, Inc.}
+\centerline{designed by Stephen Gildea, \version}
+\centerline{for GNU Emacs version 18 on Unix systems}
+
+Permission is granted to make and distribute copies of
+this card provided the copyright notice and this permission notice
+are preserved on all copies.
+
+For copies of the GNU Emacs manual, write to the Free Software
+Foundation, Inc., 675 Massachusetts Ave, Cambridge MA 02139.
+
+\endgroup}
+
+% make \bye not \outer so that the \def\bye in the \else clause below
+% can be scanned without complaint.
+\def\bye{\par\vfill\supereject\end}
+
+\newdimen\intercolumnskip
+\newbox\columna
+\newbox\columnb
+
+\def\ncolumns{\the\columnsperpage}
+
+\message{[\ncolumns\space
+ column\if 1\ncolumns\else s\fi\space per page]}
+
+\def\scaledmag#1{ scaled \magstep #1}
+
+% This multi-way format was designed by Stephen Gildea
+% October 1986.
+\if 1\ncolumns
+ \hsize 4in
+ \vsize 10in
+ \voffset -.7in
+ \font\titlefont=\fontname\tenbf \scaledmag3
+ \font\headingfont=\fontname\tenbf \scaledmag2
+ \font\smallfont=\fontname\sevenrm
+ \font\smallsy=\fontname\sevensy
+
+ \footline{\hss\folio}
+ \def\makefootline{\baselineskip10pt\hsize6.5in\line{\the\footline}}
+\else
+ \hsize 3.2in
+ \vsize 7.95in
+ \hoffset -.75in
+ \voffset -.745in
+ \font\titlefont=cmbx10 \scaledmag2
+ \font\headingfont=cmbx10 \scaledmag1
+ \font\smallfont=cmr6
+ \font\smallsy=cmsy6
+ \font\eightrm=cmr8
+ \font\eightbf=cmbx8
+ \font\eightit=cmti8
+ \font\eighttt=cmtt8
+ \font\eightsy=cmsy8
+ \textfont0=\eightrm
+ \textfont2=\eightsy
+ \def\rm{\eightrm}
+ \def\bf{\eightbf}
+ \def\it{\eightit}
+ \def\tt{\eighttt}
+ \normalbaselineskip=.8\normalbaselineskip
+ \normallineskip=.8\normallineskip
+ \normallineskiplimit=.8\normallineskiplimit
+ \normalbaselines\rm %make definitions take effect
+
+ \if 2\ncolumns
+ \let\maxcolumn=b
+ \footline{\hss\rm\folio\hss}
+ \def\makefootline{\vskip 2in \hsize=6.86in\line{\the\footline}}
+ \else \if 3\ncolumns
+ \let\maxcolumn=c
+ \nopagenumbers
+ \else
+ \errhelp{You must set \columnsperpage equal to 1, 2, or 3.}
+ \errmessage{Illegal number of columns per page}
+ \fi\fi
+
+ \intercolumnskip=.46in
+ \def\abc{a}
+ \output={%
+ % This next line is useful when designing the layout.
+ %\immediate\write16{Column \folio\abc\space starts with \firstmark}
+ \if \maxcolumn\abc \multicolumnformat \global\def\abc{a}
+ \else\if a\abc
+ \global\setbox\columna\columnbox \global\def\abc{b}
+ %% in case we never use \columnb (two-column mode)
+ \global\setbox\columnb\hbox to -\intercolumnskip{}
+ \else
+ \global\setbox\columnb\columnbox \global\def\abc{c}\fi\fi}
+ \def\multicolumnformat{\shipout\vbox{\makeheadline
+ \hbox{\box\columna\hskip\intercolumnskip
+ \box\columnb\hskip\intercolumnskip\columnbox}
+ \makefootline}\advancepageno}
+ \def\columnbox{\leftline{\pagebody}}
+
+ \def\bye{\par\vfill\supereject
+ \if a\abc \else\null\vfill\eject\fi
+ \if a\abc \else\null\vfill\eject\fi
+ \end}
+\fi
+
+% we won't be using math mode much, so redefine some of the characters
+% we might want to talk about
+\catcode`\^=12
+\catcode`\_=12
+
+\chardef\\=`\\
+\chardef\{=`\{
+\chardef\}=`\}
+
+\hyphenation{mini-buf-fer}
+
+\parindent 0pt
+\parskip 1ex plus .5ex minus .5ex
+
+\def\small{\smallfont\textfont2=\smallsy\baselineskip=.8\baselineskip}
+
+\outer\def\newcolumn{\vfill\eject}
+
+\outer\def\title#1{{\titlefont\centerline{#1}}\vskip 1ex plus .5ex}
+
+\outer\def\section#1{\par\filbreak
+ \vskip 3ex plus 2ex minus 2ex {\headingfont #1}\mark{#1}%
+ \vskip 2ex plus 1ex minus 1.5ex}
+
+\newdimen\keyindent
+
+\def\beginindentedkeys{\keyindent=1em}
+\def\endindentedkeys{\keyindent=0em}
+\endindentedkeys
+
+\def\paralign{\vskip\parskip\halign}
+
+\def\<#1>{$\langle${\rm #1}$\rangle$}
+
+\def\kbd#1{{\tt#1}\null} %\null so not an abbrev even if period follows
+
+\def\beginexample{\par\leavevmode\begingroup
+ \obeylines\obeyspaces\parskip0pt\tt}
+{\obeyspaces\global\let =\ }
+\def\endexample{\endgroup}
+
+\def\key#1#2{\leavevmode\hbox to \hsize{\vtop
+ {\hsize=.75\hsize\rightskip=1em
+ \hskip\keyindent\relax#1}\kbd{#2}\hfil}}
+
+\newbox\metaxbox
+\setbox\metaxbox\hbox{\kbd{M-x }}
+\newdimen\metaxwidth
+\metaxwidth=\wd\metaxbox
+
+\def\metax#1#2{\leavevmode\hbox to \hsize{\hbox to .75\hsize
+ {\hskip\keyindent\relax#1\hfil}%
+ \hskip -\metaxwidth minus 1fil
+ \kbd{#2}\hfil}}
+
+\def\threecol#1#2#3{\hskip\keyindent\relax#1\hfil&\kbd{#2}\quad
+ &\kbd{#3}\quad\cr}
+
+%**end of header
+
+
+\title{GNU Emacs Reference Card}
+
+\centerline{(for version 18)}
+
+\section{Starting Emacs}
+
+To enter Emacs, just type its name: \kbd{emacs}
+
+To read in a file to edit, see Files, below.
+
+\section{Leaving Emacs}
+
+\key{suspend Emacs (the usual way of leaving it)}{C-z}
+\key{exit Emacs permanently}{C-x C-c}
+
+\section{Files}
+
+\key{{\bf read} a file into Emacs}{C-x C-f}
+\key{{\bf save} a file back to disk}{C-x C-s}
+\key{{\bf insert} contents of another file into this buffer}{C-x i}
+\key{replace this file with the file you really want}{C-x C-v}
+\key{write buffer to a specified file}{C-x C-w}
+\key{run Dired, the directory editor}{C-x d}
+
+\section{Getting Help}
+
+The Help system is simple. Type \kbd{C-h} and follow the directions.
+If you are a first-time user, type \kbd{C-h t} for a {\bf tutorial}.
+(This card assumes you know the tutorial.)
+
+\key{get rid of Help window}{C-x 1}
+\key{scroll Help window}{ESC C-v}
+
+\key{apropos: show commands matching a string}{C-h a}
+\key{show the function a key runs}{C-h c}
+\key{describe a function}{C-h f}
+\key{get mode-specific information}{C-h m}
+
+\section{Error Recovery}
+
+\key{{\bf abort} partially typed or executing command}{C-g}
+\metax{{\bf recover} a file lost by a system crash}{M-x recover-file}
+\key{{\bf undo} an unwanted change}{C-x u {\rm or} C-_}
+\metax{restore a buffer to its original contents}{M-x revert-buffer}
+\key{redraw garbaged screen}{C-l}
+
+\section{Incremental Search}
+
+\key{search forward}{C-s}
+\key{search backward}{C-r}
+\key{regular expression search}{C-M-s}
+
+Use \kbd{C-s} or \kbd{C-r} again to repeat the search in either direction.
+
+\key{exit incremental search}{ESC}
+\key{undo effect of last character}{DEL}
+\key{abort current search}{C-g}
+
+If Emacs is still searching, \kbd{C-g} will cancel the
+part of the search not done, otherwise it aborts the entire search.
+
+\shortcopyrightnotice
+
+\section{Motion}
+
+Cursor motion:
+
+\beginindentedkeys
+
+\paralign to \hsize{#\tabskip=10pt plus 1 fil&#\tabskip=0pt&#\cr
+\threecol{{\bf entity to move over}}{{\bf backward}}{{\bf forward}}
+\threecol{character}{C-b}{C-f}
+\threecol{word}{M-b}{M-f}
+\threecol{line}{C-p}{C-n}
+\threecol{go to line beginning (or end)}{C-a}{C-e}
+\threecol{sentence}{M-a}{M-e}
+\threecol{paragraph}{M-[}{M-]}
+\threecol{page}{C-x [}{C-x ]}
+\threecol{sexp}{C-M-b}{C-M-f}
+\threecol{function}{C-M-a}{C-M-e}
+\threecol{go to buffer beginning (or end)}{M-<}{M->}
+}
+Screen motion:
+
+\key{scroll to next screen}{C-v}
+\key{scroll to previous screen}{M-v}
+\key{scroll left}{C-x <}
+\key{scroll right}{C-x >}
+
+\endindentedkeys
+
+\section{Killing and Deleting}
+
+\paralign to \hsize{#\tabskip=10pt plus 1 fil&#\tabskip=0pt&#\cr
+\threecol{{\bf entity to kill}}{{\bf backward}}{{\bf forward}}
+\threecol{character (delete, not kill)}{DEL}{C-d}
+\threecol{word}{M-DEL}{M-d}
+\threecol{line (to end of)}{M-0 C-k}{C-k}
+\threecol{sentence}{C-x DEL}{M-k}
+\threecol{sexp}{M-- C-M-k}{C-M-k}
+}
+
+\key{kill {\bf region}}{C-w}
+\key{kill to next occurrence of {\it char}}{M-z {\it char}}
+
+\key{yank back last thing killed}{C-y}
+\key{replace last yank with previous kill}{M-y}
+
+\section{Marking}
+
+\key{set mark here}{C-@ {\rm or} C-SPC}
+\key{exchange point and mark}{C-x C-x}
+
+\key{set mark {\it arg\/} {\bf words} away}{M-@}
+\key{mark {\bf paragraph}}{M-h}
+\key{mark {\bf page}}{C-x C-p}
+\key{mark {\bf sexp}}{C-M-@}
+\key{mark {\bf function}}{C-M-h}
+\key{mark entire {\bf buffer}}{C-x h}
+
+\section{Query Replace}
+
+\key{interactively replace a text string}{M-\%}
+\metax{using regular expressions}{M-x query-replace-regexp}
+
+Valid responses in query-replace mode are
+
+\key{{\bf replace} this one, go on to next}{SPC}
+\key{replace this one, don't move}{,}
+\key{{\bf skip} to next without replacing}{DEL}
+\key{replace all remaining matches}{!}
+\key{{\bf back up} to the previous match}{^}
+\key{{\bf exit} query-replace}{ESC}
+\key{enter recursive edit (\kbd{C-M-c} to exit)}{C-r}
+
+\section{Multiple Windows}
+
+\key{delete all other windows}{C-x 1}
+\key{delete this window}{C-x 0}
+\key{split window in 2 vertically}{C-x 2}
+\key{split window in 2 horizontally}{C-x 5}
+
+\key{scroll other window}{C-M-v}
+\key{switch cursor to another window}{C-x o}
+
+\metax{shrink window shorter}{M-x shrink-window}
+\key{grow window taller}{C-x ^}
+\key{shrink window narrower}{C-x \{}
+\key{grow window wider}{C-x \}}
+
+\key{select a buffer in other window}{C-x 4 b}
+\key{find file in other window}{C-x 4 f}
+\key{compose mail in other window}{C-x 4 m}
+\key{run Dired in other window}{C-x 4 d}
+\key{find tag in other window}{C-x 4 .}
+
+\section{Formatting}
+
+\key{indent current {\bf line} (mode-dependent)}{TAB}
+\key{indent {\bf region} (mode-dependent)}{C-M-\\}
+\key{indent {\bf sexp} (mode-dependent)}{C-M-q}
+\key{indent region rigidly {\it arg\/} columns}{C-x TAB}
+
+\key{insert newline after point}{C-o}
+\key{move rest of line vertically down}{C-M-o}
+\key{delete blank lines around point}{C-x C-o}
+\key{delete all whitespace around point}{M-\\}
+\key{put exactly one space at point}{M-SPC}
+
+\key{fill {\bf paragraph}}{M-q}
+\key{fill {\bf region}}{M-g}
+\key{set fill column}{C-x f}
+\key{set prefix each line starts with}{C-x .}
+
+\section{Case Change}
+
+\key{uppercase word}{M-u}
+\key{lowercase word}{M-l}
+\key{capitalize word}{M-c}
+
+\key{uppercase region}{C-x C-u}
+\key{lowercase region}{C-x C-l}
+\metax{capitalize region}{M-x capitalize-region}
+
+\section{The Minibuffer}
+
+The following keys are defined in the minibuffer.
+
+\key{complete as much as possible}{TAB}
+\key{complete up to one word}{SPC}
+\key{complete and execute}{RET}
+\key{show possible completions}{?}
+\key{abort command}{C-g}
+
+Type \kbd{C-x ESC} to edit and repeat the last command that used the
+minibuffer. The following keys are then defined.
+
+\key{previous minibuffer command}{M-p}
+\key{next minibuffer command}{M-n}
+
+\newcolumn
+\title{GNU Emacs Reference Card}
+
+\section{Buffers}
+
+\key{select another buffer}{C-x b}
+\key{list all buffers}{C-x C-b}
+\key{kill a buffer}{C-x k}
+
+\section{Transposing}
+
+\key{transpose {\bf characters}}{C-t}
+\key{transpose {\bf words}}{M-t}
+\key{transpose {\bf lines}}{C-x C-t}
+\key{transpose {\bf sexps}}{C-M-t}
+
+\section{Spelling Check}
+
+\key{check spelling of current word}{M-\$}
+\metax{check spelling of all words in region}{M-x spell-region}
+\metax{check spelling of entire buffer}{M-x spell-buffer}
+
+\section{Tags}
+
+\key{find tag}{M-.}
+\key{find next occurrence of tag}{C-u M-.}
+\metax{specify a new tags file}{M-x visit-tags-table}
+
+\metax{regexp search on all files in tags table}{M-x tags-search}
+\metax{query replace on all the files}{M-x tags-query-replace}
+\key{continue last tags search or query-replace}{M-,}
+
+\section{Shells}
+
+\key{execute a shell command}{M-!}
+\key{run a shell command on the region}{M-|}
+\key{filter region through a shell command}{C-u M-|}
+\metax{start a shell in window \kbd{*shell*}}{M-x shell}
+
+\section{Rmail}
+
+\key{scroll forward}{SPC}
+\key{scroll reverse}{DEL}
+\key{beginning of message}{. {\rm (dot)}}
+\key{{\bf next} non-deleted message}{n}
+\key{{\bf previous} non-deleted message}{p}
+\key{next message}{M-n}
+\key{previous message}{M-p}
+\key{{\bf delete} message}{d}
+\key{delete message and back up}{C-d}
+\key{undelete message}{u}
+\key{{\bf reply} to message}{r}
+\key{forward message to someone}{f}
+\key{send mail}{m}
+\key{{\bf get} newly arrived mail}{g}
+\key{{\bf quit} Rmail}{q}
+\key{output message to another Rmail file}{o}
+\key{output message in Unix-mail style}{C-o}
+\key{show summary of headers}{h}
+
+\section{Regular Expressions}
+
+The following have special meaning inside a regular expression.
+
+\key{any single character}{. {\rm(dot)}}
+\key{zero or more repeats}{*}
+\key{one or more repeats}{+}
+\key{zero or one repeat}{?}
+\key{any character in set}{[ {\rm$\ldots$} ]}
+\key{any character not in set}{[^ {\rm$\ldots$} ]}
+\key{beginning of line}{^}
+\key{end of line}{\$}
+\key{quote a special character {\it c\/}}{\\{\it c}}
+\key{alternative (``or'')}{\\|}
+\key{grouping}{\\( {\rm$\ldots$} \\)}
+\key{{\it n\/}th group}{\\{\it n}}
+\key{beginning of buffer}{\\`}
+\key{end of buffer}{\\'}
+\key{word break}{\\b}
+\key{not beginning or end of word}{\\B}
+\key{beginning of word}{\\<}
+\key{end of word}{\\>}
+\key{any word-syntax character}{\\w}
+\key{any non-word-syntax character}{\\W}
+\key{character with syntax {\it c}}{\\s{\it c}}
+\key{character with syntax not {\it c}}{\\S{\it c}}
+
+\section{Registers}
+
+\key{copy region to register}{C-x x}
+\key{insert register contents}{C-x g}
+
+\key{save point in register}{C-x /}
+\key{move point to saved location}{C-x j}
+
+\section{Info}
+
+\key{enter the Info documentation reader}{C-h i}
+\beginindentedkeys
+
+Moving within a node:
+
+\key{scroll forward}{SPC}
+\key{scroll reverse}{DEL}
+\key{beginning of node}{. {\rm (dot)}}
+
+Moving between nodes:
+
+\key{{\bf next} node}{n}
+\key{{\bf previous} node}{p}
+\key{move {\bf up}}{u}
+\key{select menu item by name}{m}
+\key{select {\it n\/}th menu item by number (1--5)}{{\it n}}
+\key{follow cross reference (return with \kbd{l})}{f}
+\key{return to last node you saw}{l}
+\key{return to directory node}{d}
+\key{go to any node by name}{g}
+
+Other:
+
+\key{run Info {\bf tutorial}}{h}
+\key{list Info commands}{?}
+\key{{\bf quit} Info}{q}
+\key{search nodes for regexp}{s}
+
+\endindentedkeys
+
+\section{Keyboard Macros}
+
+\key{{\bf start} defining a keyboard macro}{C-x (}
+\key{{\bf end} keyboard macro definition}{C-x )}
+\key{{\bf execute} last-defined keyboard macro}{C-x e}
+\key{append to last keyboard macro}{C-u C-x (}
+\metax{name last keyboard macro}{M-x name-last-kbd-macro}
+\metax{insert lisp definition in buffer}{M-x insert-kbd-macro}
+
+\section{Commands Dealing with Emacs Lisp}
+
+\key{eval {\bf sexp} before point}{C-x C-e}
+\key{eval current {\bf defun}}{C-M-x}
+\metax{eval {\bf region}}{M-x eval-region}
+\metax{eval entire {\bf buffer}}{M-x eval-current-buffer}
+\key{read and eval minibuffer}{M-ESC}
+\key{re-execute last minibuffer command}{C-x ESC}
+\metax{read and eval Emacs Lisp file}{M-x load-file}
+\metax{load from standard system directory}{M-x load-library}
+
+\section{Simple Customization}
+
+% The intended audience here is the person who wants to make simple
+% customizations and knows Lisp syntax.
+
+Here are some examples of binding global keys in Emacs Lisp. Note
+that you cannot say \kbd{"\\M-\#"}; you must say \kbd{"\\e\#"}.
+
+\beginexample%
+(global-set-key "\\C-cg" 'goto-line)
+(global-set-key "\\e\\C-r" 'isearch-backward-regexp)
+(global-set-key "\\e\#" 'query-replace-regexp)
+\endexample
+
+An example of setting a variable in Emacs Lisp:
+
+\beginexample%
+(setq backup-by-copying-when-linked t)
+\endexample
+
+\section{Writing Commands}
+
+\beginexample%
+(defun \<command-name> (\<args>)
+ "\<documentation>"
+ (interactive "\<template>")
+ \<body>)
+\endexample
+
+An example:
+
+\beginexample%
+(defun this-line-to-top-of-screen (line)
+ "Reposition line point is on to the top of
+the screen. With ARG, put point on line ARG.
+Negative counts from bottom."
+ (interactive "P")
+ (recenter (if (null line)
+ 0
+ (prefix-numeric-value line))))
+\endexample
+
+The argument to \kbd{interactive} is a string specifying how to get
+the arguments when the function is called interactively.
+Type \kbd{C-h f interactive} for more information.
+
+\copyrightnotice
+
+\bye
+
+% Local variables:
+% compile-command: "tex refcard"
+% End:
diff --git a/lib-src/emacsserver.c b/etc/server.c
index 19e4e430ab3..654af4aa5d2 100644
--- a/lib-src/emacsserver.c
+++ b/etc/server.c
@@ -24,6 +24,11 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
and passes their commands (consisting of keyboard characters)
up to the Emacs which then executes them. */
+/* This must precede sys/signal.h on certain machines. */
+#include <sys/types.h>
+/* This must precede config.h on certain machines. */
+#include <sys/signal.h>
+
#define NO_SHORTNAMES
#include "../src/config.h"
#undef read
@@ -32,25 +37,24 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#undef close
-#if !defined(HAVE_SOCKETS) && !defined(HAVE_SYSVIPC)
+#if !defined(BSD) && !defined(HAVE_SYSVIPC)
#include <stdio.h>
main ()
{
- fprintf (stderr, "Sorry, the Emacs server is supported only on systems\n");
- fprintf (stderr, "with Berkeley sockets or System V IPC.\n");
+ fprintf (stderr, "Sorry, the Emacs server is supported only on Berkeley Unix\n");
+ fprintf (stderr, "or System V systems with IPC\n");
exit (1);
}
-#else /* HAVE_SOCKETS or HAVE_SYSVIPC */
+#else /* BSD or HAVE_SYSVIPC */
-#if ! defined (HAVE_SYSVIPC)
+#if defined (BSD) && ! defined (HAVE_SYSVIPC)
/* BSD code is very different from SYSV IPC code */
#include <sys/file.h>
#include <sys/types.h>
#include <sys/socket.h>
-#include <sys/signal.h>
#include <sys/un.h>
#include <stdio.h>
#include <errno.h>
@@ -59,6 +63,7 @@ extern int errno;
main ()
{
+ char system_name[32];
int s, infd, fromlen;
struct sockaddr_un server, fromunix;
char *homedir;
@@ -67,7 +72,6 @@ main ()
FILE **openfiles;
int openfiles_size;
- int geteuid ();
char *getenv ();
openfiles_size = 20;
@@ -85,28 +89,32 @@ main ()
exit (1);
}
server.sun_family = AF_UNIX;
- homedir = getenv ("HOME");
- if (homedir == NULL)
+#ifndef SERVER_HOME_DIR
+ gethostname (system_name, sizeof (system_name));
+ sprintf (server.sun_path, "/tmp/esrv%d-%s", geteuid (), system_name);
+
+ if (unlink (server.sun_path) == -1 && errno != ENOENT)
+ {
+ perror ("unlink");
+ exit (1);
+ }
+#else
+ if ((homedir = getenv ("HOME")) == NULL)
{
fprintf (stderr,"No home directory\n");
exit (1);
}
- sprintf (server.sun_path, "/tmp/esrv%d", geteuid ());
-
-#if 0
strcpy (server.sun_path, homedir);
strcat (server.sun_path, "/.emacs_server");
-#endif
-
/* Delete anyone else's old server. */
unlink (server.sun_path);
+#endif
+
if (bind (s, &server, strlen (server.sun_path) + 2) < 0)
{
perror ("bind");
exit (1);
}
- /* Only this user can send commands to this Emacs. */
- chmod (server.sun_path, 0600);
/*
* Now, just wait for everything to come in..
*/
@@ -214,13 +222,14 @@ main ()
#else /* This is the SYSV IPC section */
#include <sys/types.h>
-#include <sys/signal.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <setjmp.h>
jmp_buf msgenv;
+void /* void here fixes bug on sgi.
+ Let's hope this doesn't break other systems. */
msgcatch ()
{
longjmp (msgenv, 1);
@@ -294,6 +303,7 @@ main ()
if ((fromlen = msgrcv (s, msgp, BUFSIZ - 1, 1, 0)) < 0)
{
perror ("msgrcv");
+ exit (1);
}
else
{
@@ -313,6 +323,8 @@ main ()
}
}
-#endif /* HAVE_SYSVIPC */
+#endif /* SYSV IPC */
+
+#endif /* BSD && IPC */
+
-#endif /* HAVE_SOCKETS or HAVE_SYSVIPC */
diff --git a/etc/sex.6 b/etc/sex.6
new file mode 100644
index 00000000000..fb40f9fada8
--- /dev/null
+++ b/etc/sex.6
@@ -0,0 +1,111 @@
+SEX(6) EUNUCH Programmer's Manual SEX(6)
+
+
+
+NAME
+ sex - have sex
+
+SYNOPSIS
+ sex [ options ] ... [ username ] ...
+
+DESCRIPTION
+ _s_e_x allows the invoker to have sex with the user(s) speci-
+ fied in the command line. If no users are specified, they
+ are taken from the LOVERS environment variable. Options to
+ make things more interesting are as follows:
+
+ -1 masturbate
+
+ -a external stimulus (aphrodisiac) option
+
+ -b buggery
+
+ -B<animal>
+ bestiality with <animal>
+
+ -c chocolate sauce option
+
+ -C chaining option (cuffs included) (see also -m -s -W)
+
+ -d<file>
+ get a date with the features described in <file>
+
+ -e exhibitionism (image sent to all machines on the net)
+
+ -f foreplay option
+
+ -F nasal sex with plants
+
+ -i coitus interruptus (messy!)
+
+ -j jacuzzi option (California sites only)
+
+ -l leather option
+
+ -m masochism (see -s)
+
+ -M triple parallel (Menage a Trois) option
+
+ -n necrophilia (if target process is not dead, program
+ kills it)
+
+ -o oral option
+
+ -O parallel access (orgy)
+
+ -p debug option (proposition only)
+
+ -P pedophilia (must specify a child process)
+
+
+
+Printed 2/15/87 2/15/87 1
+
+
+
+
+
+
+SEX(6) EUNUCH Programmer's Manual SEX(6)
+
+
+
+ -q quickie (wham, bam, thank you, ma'am)
+
+ -s sadism (target must set -m)
+
+ -S sundae option
+
+ -v voyeurism (surveys the entire net)
+
+ -w whipped cream option
+
+ -W whips (see also -s, -C, and -m)
+
+ENVIRONMENT
+ LOVERS
+ is a list of default partners which will be used if
+ none are specified in the command line. If any are
+ specified, the values in LOVERS is ignored.
+
+FILES
+ /usr/lib/sex/animals animals for bestiality
+
+ /usr/lib/sex/blackbook possible dates
+
+ /usr/lib/sex/sundaes sundae recipes
+
+ /usr/lib/sex/s&m sado-masochistic equipment
+
+
+
+BUGS
+ ^C (quit process) may leave the user very unsatisfied.
+
+ ^Z (stop process) is usually quite messy.
+
+MAN AUTHOR
+ Author prefers to be anonymous.
+
+HISTORY
+ Oldest program ever.
diff --git a/lib-src/sorted-doc.c b/etc/sorted-doc.c
index c14f13c37ca..c14f13c37ca 100644
--- a/lib-src/sorted-doc.c
+++ b/etc/sorted-doc.c
diff --git a/etc/spook.lines b/etc/spook.lines
new file mode 100644
index 00000000000..4d5e80422e3
--- /dev/null
+++ b/etc/spook.lines
Binary files differ
diff --git a/etc/termcap.dat b/etc/termcap.dat
index a9d0ef02e0a..689008a89f4 100644
--- a/etc/termcap.dat
+++ b/etc/termcap.dat
@@ -47,12 +47,12 @@ ZW|gator|HP 9000 model 237 emulating AAA:\
ZY|gator-52|HP 9000 model 237 emulating VT52:\
:cr=^M:do=^J:nl=^J:bl=^G:\
:le=^H:bs:cd=\EJ:ce=\EK:cl=\EH\EJ:cm=\EY%+ %+ :co#128:li#47:nd=\EC:\
- :ta=^I:pt:sr=\EI:up=\EA:ku=\EA:kd=\EB:kr=\EC:kl=\ED:kb=^H:\
+ :ta=^I:pt:sr=\EI:up=\EA:ku=\EA:kd=\EB:kr=\EC:kl=\ED:kb=^H:
:ce=\EK:ho=\EH:
ZZ|gator-52t|HP 9000 model 237 emulating extra-tall VT52:\
:cr=^M:do=^J:nl=^J:bl=^G:\
:le=^H:bs:cd=\EJ:ce=\EK:cl=\EH\EJ:cm=\EY%+ %+ :co#128:li#94:nd=\EC:\
- :ta=^I:pt:sr=\EI:up=\EA:ku=\EA:kd=\EB:kr=\EC:kl=\ED:kb=^H:\
+ :ta=^I:pt:sr=\EI:up=\EA:ku=\EA:kd=\EB:kr=\EC:kl=\ED:kb=^H:
:ce=\EK:ho=\EH:
#
# N: ANN ARBOR
@@ -461,9 +461,9 @@ ZN|aaa60|ambas60|ambassador60|ann arbor ambassador/60 lines:\
:li#60:mi:tc=aaax:
# vt100 -- this has been changed to delete the "pt" ("real tabs")
# option, which was losing. -- walter 10/84
-d0|vt100-132|vt125-132|dec vt100 with 132 columns:\
+d0|vt100-132|vt101-132|vt102-132|vt125-132|vt131-132|dec vt100 with 132 columns:\
:co#132:tc=vt100:
-d0|vt100|vt100-am|vt100-80|vt125|vt125-80|dec vt100:\
+d0|vt100|vt100-am|vt100-80|vt101|vt101-80|vt102|vt102-80|vt125|vt125-80|vt131|vt131-80|dec vt100:\
:cr=^M:bl=^G:le=^H:do=\ED:ho=\E[H:\
:co#80:li#24:cl=45\E[H\E[2J:bs:am:cm=5\E[%i%d;%dH:nd=\E[C:up=\E[A:\
:ce=2\E[K:cd=2*\E[J:so=2\E[7m:se=2\E[m:us=2\E[4m:ue=2\E[m:\
@@ -549,7 +549,7 @@ nunix-61|nu-telnet-61|nu-full| Full nu screen thru telnet:\
# It is bad form to use ^J,^L,^K to scroll the screen.
# If the VT2xx doesn't have newline mode set those characters
# donot move the cursor down a line. Use \ED instead.
-d0|vt200-80|vt200|vt300-80|VT 200 with 80 columns, on VMS:\
+d0|vt200-80|vt200|vt300-80|vt300|VT 200 with 80 columns, on VMS:\
:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:IC=\E[%d@:\
:LE=\E[%dD:RI=\E[%dC:SR=1*\E[%dM:UP=\E[%dA:al=\E[L:\
:am:bl=^G:bs:cd=2*\E[J:ce=2*\E[K:cl=45\E[H\E[2J:\
diff --git a/etc/termcap.ucb b/etc/termcap.ucb
new file mode 100644
index 00000000000..28d825276a0
--- /dev/null
+++ b/etc/termcap.ucb
@@ -0,0 +1,2667 @@
+# ------------------------
+#
+# Termcap source file @(#)termcap.src 5.31 (Berkeley) 8/6/86
+# Kevin Layer, Berkeley
+# Craig Leres, Berkeley
+# Mark Horton, Berkeley
+#
+# Please mail changes to (arpanet): termcap@berkeley
+#
+sa|network:\
+ :tc=unknown:
+sb|arpanet:\
+ :tc=unknown:
+sc|bussiplexer:\
+ :tc=unknown:
+sd|du|dialup:\
+ :tc=unknown:
+se|ethernet:\
+ :tc=unknown:
+sl|lpr|printer|print|printing|line printer:\
+ :do=^J:le=^H:bs:co#132:hc:os:
+sp|plugboard|patch|patchboard:\
+ :tc=unknown:
+su|dumb|un|unknown:\
+ :am:co#80:do=^J:
+sw|switch|intelligent switch:\
+ :tc=unknown:
+sx|ansi|any ansi terminal with pessimistic assumptions:\
+ :co#80:li#24:cl=50\E[;H\E[2J:bs:am:cm=\E[%i%d;%dH:\
+ :nd=\E[C:up=\E[A:ce=\E[K:ho=\E[H:pt:
+TD|dmd|5620|ttydmd|tty5620|5620 terminal 88 columns:\
+ :co#88:li#70:am:bs:pt:cm=\E[%i%d;%dH:nd=\E[C:up=\E[A:\
+ :cl=\E[H\E[J:cd=\E[J:ce=\E[K:al=\E[L:dl=\E[M:do=^J:\
+ :im=:ei=:ic=\E[@:dc=\E[P:sr=\E[T:sf=\E[S:le=^H:kb=^H:\
+ :kl=\E[D:kr=\E[C:ku=\E[A:kd=\E[B:kh=\E[H:ho=\E[H:ll=\E[70;1H:\
+ :AL=\E[%dL:DL=\E[%dM:IC=\E[%d@:DC=\E[%dP:rc=\E8:rs=\Ec:sc=\E7:\
+ :so=\E[7m:se=\E[0m:us=\E[4m:ue=\E[0m:ms:me=\E[0m:mr=\E[7m:
+kg|h19-g|h19g|heathkit w/block cursor:\
+ :ve=\Ex4:tc=h19-b:
+ke|h19-e|h19e|h19 for emacs:ip=1.5:tc=h19-us:
+kU|h19-us|h19us|heathkit w/keypad shifted/underscore cursor:\
+ :ks=\Et:ke=\Eu:tc=h19-u:
+ku|h19-u|h19u|heathkit with underscore cursor:\
+ :vs@:ve@:tc=h19-b:
+kb|h19|heath|h19-b|h19b|heathkit|heath-19|z19|zenith|heathkit h19:\
+ :al=1*\EL:am:le=^H:bs:cd=\EJ:ce=\EK:cl=\EE:cm=\EY%+ %+ :co#80:dc=\EN:\
+ :dl=1*\EM:do=\EB:ei=\EO:ho=\EH:im=\E@:li#24:mi:nd=\EC:as=\EF:ae=\EG:\
+ :ms:pt:sr=\EI:se=\Eq:so=\Ep:up=\EA:vs=\Ex4:ve=\Ey4:\
+ :kb=^h:ku=\EA:kd=\EB:kl=\ED:kr=\EC:kh=\EH:kn#8:ke=\E>:ks=\E=:\
+ :k1=\ES:k2=\ET:k3=\EU:k4=\EV:k5=\EW:\
+ :l6=blue:l7=red:l8=white:k6=\EP:k7=\EQ:k8=\ER:\
+ :es:hs:ts=\Ej\Ex5\Ex1\EY8%+ \Eo:fs=\Ek\Ey5:ds=\Ey1:
+kC|h29|heath-29|z29|zenith-29:\
+ :am:bc=\ED:bt=\E-:do=^J:\
+ :al=\EL:le=^H:bs:cd=\EJ:ce=\EK:cl=\EE:cm=\EY%+ %+ :co#80:dc=\EN:\
+ :dl=1*\EM:do=\EB:ei=\EO:ho=\EH:im=\E@:li#24:mi:nd=\EC:as=\EF:ae=\EG:\
+ :ms:pt:sr=\EI:se=\Eq:so=\Ep:up=\EA:vs=\Ex4:ve=\Ey4:\
+ :kb=^H:ku=\EA:kd=\EB:kl=\ED:kr=\EC:kh=\EH:kn#1:k0=\E~:l0=HOME:\
+ :k1=\ES:k2=\ET:k3=\EU:k4=\EV:k5=\EW:k6=\EP:k7=\EQ:k8=\ER:k9=\E0I:\
+ :es:hs:ts=\Ej\Ex5\Ex1\EY8%+ \Eo:fs=\Ek\Ey5:ds=\Ey1:us=\Es8:ue=\Es0:
+h2|2621|hp2621|hp2621a|hp2621p|2621a|2621p|2621-pb|hp2621-fl|hp 2621:\
+ :is=\E&j@\r:bt=\Ei:cm=\E&a%r%dc%dY:dc=2\EP:ip=2:pb#19200:\
+ :so=\E&dD:se=\E&d@:us=\E&dD:ue=\E&d@:me=\E&d@:\
+ :kh=\Ep\r:ku=\Et\r:kl=\Eu\r:kr=\Ev\r:kd=\Ew\r:\
+ :kn#8:k1=\Ep\r:k2=\Eq\r:k3=\Er\r:k4=\Es\r:k5=\Et\r:k6=\Eu\r:k7=\Ev\r:\
+ :k8=\Ew\r:ks=\E&jB:ke=\E&j@:ta=2^I:tc=hp:
+hn|2621-nl|hp2621nl|2621nl|hp2621-nl|hp 2621 with no labels:\
+ :ks@:ke@:kh@:ku@:kl@:kr@:kd@:tc=hp2621-fl:
+h4|hp2645|2645|hp45:\
+ :mh=\E&dH:mr=\E&dB:us=\E&dD:mb=\E&dA:me=\E&d@:\
+ :ku=\EA:kd=\EB:kl=\ED:kr=\EC:kh=\Eh:ks=\E&s1A:ke=\E&s0A:tc=hp:
+dl|vt200|vt220|vt200-js|vt220-js|dec vt200 series with jump scroll:\
+ :im=\E[4h:ei=\E[4l:mi:dc=\E[P:dm=:ed=:al=\E[L:dl=\E[M:\
+ :cs=\E[%i%d;%dr:sf=\ED:sr=\EM:sb=\EM:\
+ :ce=\E[K:cl=\E[H\E[J:cd=\E[J:cm=\E[%i%d;%dH:nd=\E[C:up=\E[A:\
+ :so=\E[7m:se=\E[27m:us=\E[4m:ue=\E[24m:\
+ :md=\E[1m:mr=\E[7m:mb=\E[5m:me=\E[m:\
+ :is=\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h\E[1;24r\E[24;1H:\
+ :rs=\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h:\
+ :tc=vt100:
+d0|vt100|vt100-am|vt100am|dec vt100:\
+ :do=^J:co#80:li#24:cl=50\E[;H\E[2J:sf=5\ED:\
+ :le=^H:bs:am:cm=5\E[%i%d;%dH:nd=2\E[C:up=2\E[A:\
+ :ce=3\E[K:cd=50\E[J:so=2\E[7m:se=2\E[m:us=2\E[4m:ue=2\E[m:\
+ :md=2\E[1m:mr=2\E[7m:mb=2\E[5m:me=2\E[m:is=\E[1;24r\E[24;1H:\
+ :rf=/usr/lib/tabset/vt100:\
+ :rs=\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h:ks=\E[?1h\E=:ke=\E[?1l\E>:\
+ :ku=\EOA:kd=\EOB:kr=\EOC:kl=\EOD:kb=^H:\
+ :ho=\E[H:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:pt:sr=5\EM:vt#3:xn:\
+ :sc=\E7:rc=\E8:cs=\E[%i%d;%dr:
+la|adm3a|3a|lsi adm3a:\
+ :am:do=^J:le=^H:bs:cm=\E=%+ %+ :cl=1^Z:co#80:ho=^^:\
+ :li#24:ma=^K^P:nd=^L:up=^K:
+l1|adm31|31|lsi adm31:\
+ :is=\Eu\E0:do=^J:al=\EE:am:le=^H:bs:ce=\ET:cm=\E=%+ %+ :\
+ :cl=\E*:cd=\EY:co#80:dc=\EW:dl=\ER:ei=\Er:ho=^^:im=\Eq:\
+ :k0=^A0\r:k1=^A1\r:k2=^A2\r:k3=^A3\r:k4=^A4\r:\
+ :k5=^A5\r:k6=^A6\r:k7=^A7\r:k8=^A8\r:k9=^A9\r:kd=^J:kl=^H:kr=^L:ku=^K:\
+ :li#24:ma=j^Jk^P^K^Pl ^R^L^L :mi:nd=^L:\
+ :se=\EG0:so=\EG1:up=^K:us=\EG1:ue=\EG0:
+l3|adm3|3|lsi adm3:\
+ :do=^J:am:le=^H:bs:cl=^Z:li#24:ma=^K^P:co#80:
+vs|xterm|vs100|xterm terminal emulator (X window system):\
+ :do=^J:le=^H:ho=\E[H:\
+ :co#80:li#65:cl=\E[H\E[2J:am:bs:cm=\E[%i%d;%dH:nd=\E[C:up=\E[A:\
+ :ce=\E[K:cd=\E[J:so=\E[7m:se=2\E[m:us=\E[4m:ue=\E[m:\
+ :md=\E[1m:mr=\E[7m:me=2\E[m:\
+ :ku=\EOA:kd=\EOB:kr=\EOC:kl=\EOD:kb=^H:\
+ :k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:pt:sf=\n:sr=\EM:\
+ :al=\E[L:dl=\E[M:ic=\E[@:dc=\E[P:\
+ :MT:ks=\E[?1h\E=:ke=\E[?1l\E>:xn:\
+ :is=\E\E[m\E[?7h\E[?1;4l:\
+ :rs=\E[r\E<\E[m\E[H\E[2J\E[?7h\E[?1;3;4;6l:
+v2|xterms|vs100s|xterm terminal emulator (small)(X window system):\
+ :co#80:li#24:tc=xterm:
+Mu|sun|Sun Microsystems Workstation console:\
+ :li#34:co#80:cl=^L:cm=\E[%i%d;%dH:nd=\E[C:up=\E[A:\
+ :am:bs:mi:ms:pt:\
+ :ce=\E[K:cd=\E[J:so=\E[7m:se=\E[m:\
+ :kd=\E[B:kl=\E[D:ku=\E[A:kr=\E[C:kh=\E[H:\
+ :k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:\
+ :al=\E[L:dl=\E[M:im=:ei=:ic=\E[@:dc=\E[P:\
+ :AL=\E[%dL:DL=\E[%dM:
+M6|sun-e|sun-nic|sune|Sun Microsystems Workstation without insert character:\
+ :ic@:im@:ei@:tc=sun:
+Mu|sun-s|Sun Microsystems Workstation window with status line:\
+ :hs:ts=\E]l:fs=\E\\:ds=\E]l\E\\:tc=sun:
+Mu|sun-e-s|sun-s-e|Sun Microsystems Workstation with status hacked for emacs:\
+ :hs:ts=\E]l:fs=\E\\:ds=\E]l\E\\:tc=sun-e:
+M0|sun-48|Sun 48-line window:\
+ :li#48:co#80:tc=sun:
+M1|sun-34|Sun 34-line window:\
+ :li#34:co#80:tc=sun:
+M2|sun-24|Sun 24-line window:\
+ :li#24:co#80:tc=sun:
+M3|sun-17|Sun 17-line window:\
+ :li#17:co#80:tc=sun:
+cB|avt-8p-s|concept avt w/8 pages & 80 cols running sysline:\
+ :is=\E[1*q\E[2!t\E[7!t\E[=4;101;103;119l\E[=107;118;207h\E)1\E[1Q\EW\E[0!y\E[0\0720\07232!r\E[2!w\E[192w\E[2*w\E[!w\E[1;191w\E2\r\n:\
+ :hs:es:ts=\E[2!w\E[H\E[J\E[%i%dG:fs=\E[!w:\
+ :ds=\E[2!w\E[2J\E[!w\E[*w:te=\E[1;191w\E2\n:tc=avt:
+cC|avt-4p-s|concept avt w/4 pages & 80 cols running sysline:\
+ :is=\E[1*q\E[2!t\E[7!t\E[=4;101;103;119l\E[=107;118;207h\E)1\E[1Q\EW\E[0!y\E[0\0720\07232!r\E[2!w\E[96w\E[2*w\E[!w\E[1;95w\E2\r\n:\
+ :hs:es:ts=\E[2!w\E[H\E[J\E[%i%dG:fs=\E[!w:\
+ :ds=\E[2!w\E[2J\E[!w\E[*w:te=\E[1;95w\E2\n:tc=avt:
+cD|avt-rv|HDS concept avt w/4 or 8 pages, 80 columns, reverse video:\
+ :is=\E[1*q\E[2!t\E[7!t\E[=4;101;103;119l\E[=107;118;205;207h\E)1\E[1Q\EW\E[0!y\E[0\0720\07232!r\E[w\E2\r\n:\
+ :ve=\E[4l:vs=\E[4l:tc=avt
+cE|avt|HDS concept avt w/4 or 8 pages, 80 columns:\
+ :is=\E[1*q\E[2!t\E[7!t\E[=4;101;103;119;205l\E[=107;118;207h\E)1\E[1Q\EW\E[0!y\E[0\0720\07232!r\E[w\E2\r\n\E[*w:\
+ :ae=^O:al=\E[L:am:as=^N:bs:bt=\E[Z:cd=\E[J:ce=\E[K:\
+ :ch=\E[%i%2G:cl=\E[H\E[J:cm=\E[%i%2;%2H:co#80:cv=\E[%i%2d:\
+ :dc=\E[P:dl=\E[M:do=\E[B:ei=\E1:eo:ho=\E[H:im=\E1:kb=^H:kd=\E[B:\
+ :kh=\E[H:kl=\E[D:ko=do,ho,nd,up:kr=\E[C:\
+ :ks=\E[1;4!z\E[1;8!z\E[1;10!z\E[1;11!z\E[1;12!z\E[1;14!z\E[3;7!z\E[3;9!z:\
+ :ke=\E[;4!z\E[;8!z\E[;10!z\E[;11!z\E[;12!z\E[3;14!z\E[;7!z\E[;9!z:\
+ :ku=\E[A:li#24:mi:nd=\E[C:pt:se=\E[7!{:so=\E[7m:\
+ :te=\E[w\E2\n:ti=\E[1;24w\E2\n:ue=\E[4!{:ul:\
+ :up=\E[A:us=\E[4m:ve=\E[=4;119l:vs=\E[4l\E[=119h:xn:
+c4|c108-rv-8p|concept108-rv-8p|concept 108 w/8 pages, in reverse video:\
+ :vb=\EK\200\200\200\200\200\200\200\200\200\200\200\200\200\200\Ek:\
+ :is=\EU\E F\Ef\E7\E5\E8\El\ENH\Ek\E\200\Eo&\200\Eo\47\E\E!\E^G!\E^HA@ :\
+ :ts=\E z"\E?\E^C\EE\Ea %+ :fs=\Ee\E z :tc=c108-8p:
+c2|c108|c108-8p|concept108-8p|concept 108 w/8 pages:\
+ :i2=\EU\E z"\Ev^A\177 !p\E ;"\E z \Ev ^A\177p\Ep\n:\
+ :te=\Ev ^A\177p\Ep\r\n:tc=c108-4p:
+c5|c108-rv-4p|concept108-rv-4p|concept 108 w/4 pages, in reverse video:\
+ :vb=\EK\200\200\200\200\200\200\200\200\200\200\200\200\200\200\Ek:\
+ :is=\EU\E F\Ef\E7\E5\E8\El\ENH\Ek\E\200\Eo&\200\Eo\47\E\E!\E^G!\E^HA@ :\
+ :ts=\E z"\E?\E^C\EE\Ea %+ :fs=\Ee\E z :tc=c108-4p:
+c3|c108-4p|concept108-4p|concept 108 w/4 pages:\
+ :es:hs:ts=\E z"\E?\E^C\Ea %+ :fs=\E z :ds=\E ;\177:\
+ :i2=\EU\E z"\Ev\177 !p\E ;"\E z \Ev \177p\Ep\n:do=^J:pt:\
+ :is=\EU\E F\Ef\E7\E5\E8\El\ENH\EK\E\200\Eo&\200\Eo\47\E\E!\E^G!\E^HA@ :\
+ :ti=\EU\Ev 8p\Ep\r:te=\Ev \177p\Ep\r\n:\
+ :al=\E^R:le=^H:bs:cd=\E^C:ce=\E^S:cl=\E?\E^E:cm=\Ea%+ %+ :co#80:\
+ :dc=\E^Q:dl=\E^B:ei=\E\200:eo:im=\E^P:li#24:mi:nd=\E=:\
+ :kb=^h:ul:up=\E;:db:us=\EG:ue=\Eg:vs=\EW:ve=\Ew:am:xn:\
+ :vb=\Ek\200\200\200\200\200\200\200\200\200\200\200\200\200\200\EK:\
+ :ks=\EX:ke=\Ex:ku=\E;:kd=\E<:kl=\E>:kr=\E=:kh=\E?:\
+ :k1=\E5:k2=\E6:k3=\E7:k4=\E8:k5=\E9:k6=\E\72:\
+ :so=\ED:se=\Ed:mh=\EE:md=\ED:mr=\ED:me=\Ee\Ed\Eg\Ec:
+cb|c100-rv-pp|c100-rv-4p-pp|concept100-rv-pp|c100rv4ppp|w/ printer port:\
+ :is=\EU\Ef\E7\E5\E8\El\ENH\Ek\E\200\Eo&\200\Eo\041\200\EQ"\EY(^W\Eo\47\E\E^G\041\E^HA@ :\
+ :tc=c100-rv:
+cd|c100-rv|c100-rv-4p|concept100-rv|c100rv4p|c100rv|c100 rev video:\
+ :is=\EU\Ef\E7\E5\E8\El\ENH\Ek\E\200\Eo&\200\Eo\47\E\E^G\041\E^HA@ :\
+ :vb=\EK\200\200\200\200\200\200\200\200\200\200\200\200\200\200\Ek:\
+ :so=\EE:se=\Ee:tc=c100:
+ca|c100|concept|c1004p|c100-4p|concept100|concept 100:\
+ :is=\EU\Ef\E7\E5\E8\El\ENH\EK\E\200\Eo&\200\Eo\47\E\E^G\041\E^HA@ :\
+ :ti=\EU\Ev 8p\Ep\r:te=\Ev \200\200\200\200\200\200\Ep\r\n:\
+ :al=3*\E^R:am:le=^H:bs:cd=16*\E^C:ce=16\E^U:cl=2*^L:cm=\Ea%+ %+ :co#80:\
+ :dc=16\E^Q:dl=3*\E^B:ei=\E\200:eo:im=\E^P:ip=16*:li#24:mi:nd=\E=:\
+ :pt:kb=^h:ta=8\t:ul:up=\E;:db:us=\EG:ue=\Eg:xn:\
+ :vb=\Ek\200\200\200\200\200\200\200\200\200\200\200\200\200\200\EK:\
+ :.dN#9:dC#9:pb#9600:vt#8:us=\EG:ue=\Eg:so=\EE\ED:se=\Ed\Ee:\
+ :mh=\EE:mr=\ED:mb=\EC:mp=\EI:mk=\EH:me=\EN\200:do=^J:\
+ :ks=\EX:ke=\Ex:ku=\E;:kd=\E<:kl=\E>:kr=\E=:kh=\E?:k1=\E5:k2=\E6:k3=\E7:
+# Copyright (c) 1980 Regents of the University of California.
+# All rights reserved. The Berkeley software License Agreement
+# specifies the terms and conditions for redistribution.
+#
+# This file describes capabilities of various terminals, as needed by
+# software such as screen editors. It does not attempt to describe
+# printing terminals very well, nor graphics terminals. Someday.
+# See termcap(5) in the Unix Programmers Manual for documentation.
+#
+# Conventions: First entry is two chars, first char is manufacturer,
+# second char is canonical name for model or mode.
+# Third entry is the one the editor will print with "set" command.
+# Last entry is verbose description.
+# Others are mnemonic synonyms for the terminal.
+#
+# Terminal naming conventions:
+# Terminal names look like <manufacturer> <model> - <modes/options>
+# Certain abbreviations (e.g. c100 for concept100) are also allowed
+# for upward compatibility. The part to the left of the dash, if a
+# dash is present, describes the particular hardware of the terminal.
+# The part to the right can be used for flags indicating special ROM's,
+# extra memory, particular terminal modes, or user preferences.
+# All names are always in lower case, for consistency in typing.
+#
+# The following are conventionally used flags:
+# rv Terminal in reverse video mode (black on white)
+# 2p Has two pages of memory. Likewise 4p, 8p, etc.
+# w Wide - in 132 column mode.
+# pp Has a printer port which is used.
+# na No arrow keys - termcap ignores arrow keys which are
+# actually there on the terminal, so the user can use
+# the arrow keys locally.
+#
+# There are some cases where the same name is used for two different
+# terminals, e.g. "teleray" or "2621" or "vt100". In these cases,
+# if a site has one of these, they should choose a local default and
+# bring that terminal to the front in the reorder script. This works
+# because tgetent picks the first match in /etc/termcap.
+# The list of names intentionally duplicated is:
+# 2621, c108, dtc, hp2621, teleray, tvi, vt100.
+#
+# If you absolutely MUST check for a specific terminal (this is discouraged)
+# check for the 2nd entry (the canonical form) since all other codes are
+# subject to change. The two letter codes are there for version 6 and are
+# EXTREMELY subject to change, or even to go away if version 6 becomes for
+# all practical purposes obsolete. We would much rather put in special
+# capabilities to describe your terminal rather than having you key on the
+# name.
+#
+# Special manufacturer codes:
+# A: hardcopy daisy wheel terminals
+# M: Misc. (with only a few terminals)
+# q: Homemade
+# s: special (dialup, etc.)
+#
+# Comments in this file begin with # - they cannot appear in the middle
+# of a termcap entry. Individual entries are commented out by
+# placing a period between the colon and the capability name.
+#
+# This file is to be installed with an editor script (reorder)
+# that moves the most common terminals to the front of the file.
+# If the source is not available, it can be constructed by sorting
+# the above entries by the 2 char initial code.
+# # --------------------------------
+#
+# A: DAISY WHEEL PRINTERS
+#
+# The A manufacturer represents Diablo, DTC, Xerox, Qume, and other Daisy
+# wheel terminals until such time as termcap distinguishes between them
+# enough to justify separate codes.
+# This is an "experimental" entry for the SRI Agiles.
+# It has been tried in a minimal way -- the Agile did not blow up!
+# However, it has not been exhaustively tested.
+# Anyone who tries it and finds it wanting should get in touch with:
+# Ralph Keirstead (ralph@sri-unix);
+# EK352; SRI International; 333 Ravenswood Avenue; Menlo Park, CA 94025
+Aa|agile|agiles|sri agiles:\
+ :bs:hc:os:pl:co#132:do=^J:kb=^H:up=\E\n:\
+ :hu=\E0:hd=\E9:if=/usr/lib/tabset/std:is=\EE\EF\EJ:
+A6|1620|1720|450|ipsi|diablo 1620:\
+ :do=^J:ct=\E2:st=\E1:ch=\E\t%i%.:\
+ :if=/usr/lib/tabset/xerox1720:\
+ :kb=^H:le=^H:bs:co#132:hc:hu=\EU:hd=\ED:os:pt:up=\E\n:
+A7|1620-m8|1640-m8|diablo 1620 w/8 column left margin:\
+ :do=^J:co#124:is=\r \E9:tc=1620:
+A8|1640|1740|630|1730|x1700|diablo|xerox|diablo 1640:\
+ :if=/usr/lib/tabset/xerox1730:\
+ :us=\EE:ue=\ER:so=\EW:se=\E&:tc=1620:
+Am|1640-lm|1740-lm|630-lm|1730-lm|x1700-lm|diablo-lm|xerox-lm|\
+ diablo 1640 with idented left margin:\
+ :if=/usr/lib/tabset/xerox1730-lm:\
+ :co#124:us=\EE:ue=\ER:so=\EW:se=\E&:tc=1620:
+# DTC 382 with VDU. Has no cd so we fake it with ce. Standout works but
+# won't go away without dynamite. The terminal has tabs, but I'm getting
+# tired of fighting the braindamage. If no tab is set or the terminal's
+# in a bad mood, it glitches the screen around all of memory. Note that
+# return puts a blank ("a return character") in the space the cursor was
+# at, so we use ^P return (and thus ^P newline for newline). Note also
+# that if you turn off pt and let Unix expand tabs, curses won't work
+# (current version) because it doesn't turn off this bit, and cursor
+# addressing sends a tab for row/column 9. What a losing terminal! I
+# have been unable to get tabs set in all 96 lines - it always leaves at
+# least one line with no tabs in it, and once you tab through that line,
+# it completely weirds out.
+Ac|dtc|ps|dtc382|382:\
+ :do=^J:al=^P^Z:am:le=^H:\
+ :bs:co#80:ce=^P^U:cl=20^P^]:cm=%r^P^Q%.%.:dc=^X:\
+ :dl=^P^S:ei=^Pi:ho=^P^R:im=^PI:ve=^Pb:vs=^PB:pc=\177:te=20^P^]:\
+ :li#24:nd=^PR:.se=^P \200:.so=^P \002^PF:us=^P \020:ue=^P \200:\
+ :up=^P^L:nc:xr:xs:da:db:.pt:cr=^P^M:cd=^P^U^P^S^P^S:\
+ :if=/usr/lib/tabset/dtc382:
+Ad|dtc300s|300|300s|dtc 300s:\
+ :ct=\E3:st=\E1:do=^J:\
+ :kb=^h:le=^H:bs:co#132:hc:hu=\EH:hd=\Eh:os:pt:up=^Z:
+Ag|gsi:\
+ :le=^H:bs:co#132:hc:hd=\Eh:hu=\EH:os:pt:up=^Z:do=^J:
+# This used to have :pl: - maybe they meant :pt:?
+Aj|aj830|aj832|aj|anderson jacobson:\
+ :do=^J:le=^H:bs:hc:hd=\E9:hu=\E8:os:up=\E7:
+# From Chris Torek <chris@gyre.umd.edu> Thu, 7 Nov 85 18:21:58 EST
+AJ|aj510|AJ510|Anderson-Jacobson model 510:\
+ :ic=:ip=.1*:so=\E"I:us=\E"U:cd=\E'P:ce=\E'L:cl=^L:cm=\E#%+ %+ :\
+ :dl=2*\E&D:ue=\E"U:co#80:li#24:se=\E"I:al=2*\E&I:im=\E'I:ei=\E'J:\
+ :dc=.1*\E'D:up=\EY:nd=\EX:bs:am:mi:ti=\E"N:te=\E"N:\
+ :ku=\EY:kd=\EZ:kl=\EW:kr=\EX:pc=\177:
+# From cbosg!ucbvax!pur-ee!cincy!chris Thu Aug 20 09:09:18 1981
+# This is incomplete, but it's a start.
+An|5520|nec|spinwriter|nec 5520:\
+ :ct=\E3:st=\E1:do=^J:kb=^h:le=^H:bs:co#132:hc:hu=\E]s\E9\E]W:\
+ :hd=\E]s\n\E]W:os:pt:up=\E9:
+Aq|qume5|qume|Qume Sprint 5:\
+ :ct=\E3:st=\E1:do=^J:\
+ :kb=^h:le=^H:bs:co#80:hc:hu=\EH:hd=\Eh:os:pt:up=^Z:
+Ar|q102|qume102|Qume 102:\
+ :al=\EE:am:bs:bt=\EI:\
+ :cd=\EY:ce=\ET:cl=^Z:cm=\E=%+ %+ :co#80:ct=\E3:\
+ :dc=\EW:dl=\ER:do=^J:ei=:ho=^^:ic=\EQ:im=:\
+ :k0=^A@\r:k1=^AA\r:k2=^AB\r:k3=^AC\r:kd=^J:kl=^H:kr=^L:ku=^K:\
+ :le=^H:li#24:ma=^K^P^L :nd=^L:\
+ :se=\EG0:sg#1:so=\EG4:st=\E1:\
+ :ue=\EG0:ug#1:ul:up=^K:us=\EG8:
+# From ucbvax!mtxinu!sybase!tim (Tim Wood) Fri Sep 27 10:25:24 PDT 1985
+# This entry supports line and character insert and delete, scroll up and
+# down and the arrow keys. To use it, perform the following on your qvt-101
+# 1) enter SET-UP mode, select the SET 3 line;
+# 2) move the cursor to the EMULATION item and hit SPACE
+# until QVT-101B appears
+# 3) enter SHIFT-S
+# 4) exit SET-UP - the terminal is now configured
+Aq|q101|qvt101|qvt-101|Qume 101 $310 special:\
+ :al=\EE:am:bt=\EI:ce=\Et:cl=\E*:dc=\EW:\
+ :dl=\ER:do=^J:ic=\EQ:ei=:im=:md=\E(:me=\EG0:mh=\E):\
+ :le=^H:bs:cm=\E=%+ %+ :cl=1^Z:co#80:ho=^^:li#24:ma=^K^P:nd=^L:ku=^K:\
+ :vs=\EM4\040\200\200\200:mr=\EG4:ms:so=\EG4:se=\EG1:
+# I suspect the xerox1720 is the same as the diablo 1620.
+Ax|x1720|x1700|1700|x1750|xerox 1720:\
+ :co#132:le=^H:bs:hc:os:pt:do=^J:ct=\E2:st=\E1:
+# # --------------------------------
+#
+# C: CONTROL DATA
+#
+Ca|cdc456|cdc:\
+ :do=^J:li#24:co#80:cl=^Y^X:nd=^L:up=^Z:le=^H:bs:\
+ :cm=\E1%+ %+ :ho=^Y:al=\E\114:dl=\E\112:ce=^V:cd=^X:am:
+Cc|cdc456tst:\
+ :do=^J:li#24:co#80:cl=^y^x:le=^H:bs:cm=\E1%+ %+ :am:
+# # --------------------------------
+#
+# D: DATAMEDIA
+#
+D0|dm1520|dm1521|1521|1520|datamedia 1520:\
+ :am:le=^H:bs:cd=^K:ce=^]:cl=^L:cm=^^%r%+ %+ :co#80:ho=^Y:\
+ :ku=^_:kd=^J:kl=^H:kr=^\:kh=^Y:\
+ :li#24:nd=^\:up=^_:xn:ma=^\ ^_^P^YH:pt:
+D2|dm2500|datamedia2500|2500|datamedia 2500:\
+ :do=^J:al=15^P\n^X^]^X^]:le=^H:bs:ce=^W:cl=^^^^\177:\
+ :cm=^L%r%n%.%.:co#80:dc=10*^P\b^X^]:dl=10*^P^Z^X^]:\
+ :dm=^P:ed=^X^]:ei=10\377\377^X^]:ho=^B:ic=10*^P^\^X^]:\
+ :im=^P:li#24:nc:nd=^\:pc=\377:so@=^N:se=^X^]:up=^Z:
+D3|dm3025|datamedia 3025a:\
+ :MT:is=\EQ\EU\EV:do=^J:\
+ :al=130\EP\n\EQ:le=^H:bs:cd=2\EJ:ce=\EK:cl=2\EM:cm=\EY%r%+ %+ :\
+ :co#80:dc=6\b:dl=130\EP\EA\EQ:dm=\EP:ed=\EQ:ei=\EQ:ho=\EH:\
+ :im=\EP:ip=6:li#24:nd=\EC:pt:so=\EO1:se=\EO0:up=\EA:
+D4|3045|dm3045|datamedia 3045a:\
+ :is=\EU\EV:do=^J:\
+ :am:le=^H:bs:cd=2\EJ:ce=\EK:cl=2\EM:cm=\EY%r%+ %+ :co#80:\
+ :dc=6\EB:dm=:ed=:ei=\EP:ho=\EH:ic=:im=\EP:ip=6:\
+ :k0=\Ey\r:k1=\Ep\r:k2=\Eq\r:k3=\Er\r:k4=\Es\r:\
+ :k5=\Et\r:k6=\Eu\r:k7=\Ev\r:k8=\Ew\r:k9=\Ex\r:\
+ :kh=\EH:ku=\EA:kr=\EC:li#24:nd=\EC:pc=\177:pt:eo:ul:up=\EA:xn:
+# dt80/1 is a vt100 lookalike, but it doesn't seem to need any padding.
+D5|dt80|dmdt80|dm80|datamedia dt80/1:\
+ :do=^J:cd=\E[J:ce=\E[K:cl=\E[2J\E[H:cm=%i\E[%d;%dH:ho=\E[H:\
+ :nd=\E[C:sr=\EM:so=\E[7m:se=\E[m:up=\E[A:us=\E[4m:ue=\E[m:tc=vt100:
+# except in 132 column mode, where it needs a little padding.
+# This is still less padding than the vt100, and you can always turn on
+# the ^S/^Q handshaking, so you can use vt100 flavors for things like
+# reverse video.
+D6|dt80w|dmdt80w|dm80w|datamedia dt80/1 in 132 char mode:\
+ :do=^J:cd=20\E[0J:co#132:ce=20\E[0K:\
+ :cm=5\E[%i%d;%dH:cl=50\E[H\E[2J:up=5\E[A:tc=dmdt80:
+# # --------------------------------
+#
+# H: HAZELTINE
+#
+# Since nd is blank, when you want to erase something you
+# are out of luck. You will have to do ^L's a lot to
+# redraw the screen. h1000 is untested. It doesn't work in
+# vi - this terminal is too dumb for even vi. (The code is
+# there but it isn't debugged for this case.)
+H1|h1000|hazeltine 1000:\
+ :le=^H:bs:ho=^K:cl=^L:nd= :co#80:li#12:do=^J:
+# Note: the h1552 appears to be the first Hazeltine terminal which
+# is not braindamaged. It has tildes and backprimes and everything!
+# Be sure the auto lf/cr switch is set to cr.
+H2|h1552|hazeltine 1552:\
+ :do=^J:al=\EE:dl=\EO:k1=\EP:l1=blue:k2=\EQ:\
+ :l2=red:k3=\ER:l3=green:tc=vt52:
+H3|h1552rv|hazeltine 1552 reverse video:\
+ :do=^J:so=\ES:se=\ET:tc=h1552:
+# From cbosg!ucbvax!pur-ee!cincy!chris Thu Aug 20 09:09:18 1981
+H4|h1420|hazeltine 1420:\
+ :do=^J:le=^H:bs:am:li#24:co#80:al=\E^Z:dl=\E^S:cd=\E^X:cl=\E\034:\
+ :up=\E^L:nd=^P:ce=\E^O:ta=^N:cm=\E^Q%r%.%+ :so=\E\037:se=\E^Y:
+H5|h1500|hazeltine 1500:\
+ :do=^J:al=40~^Z:am:le=^H:bs:cd=10~^X:ce=~^O:cl=~^\:cm=~^Q%r%.%.:\
+ :co#80:dl=40~^S:do=~^K:li#24:nd=^P:.se=~^_:.so=~^Y:up=~^L:
+# h1510 assumed to be in sane escape mode. Else use h1500.
+H6|h1510|hazeltine 1510:\
+ :do=^J:al=\E^Z:am:le=^H:bs:cd=\E^X:ce=\E^O:cl=\E^\:cm=\E^Q%r%.%.:\
+ :co#80:dl=\E^S:do=\E^K:li#24:nd=^P:.se=\E^_:.so=\E^Y:up=\E^L:
+H8|h1520|hazeltine 1520:\
+ :do=^J:al=~^Z:am:le=^H:bs:cd=~^X:ce=~^O:cl=~\034:cm=~^Q%r%.%.\200:\
+ :co#80:dl=~^S:do=~^K:hz:li#24:nd=^P:se=~^Y:so=~\037:up=~^L:ho=~^R:
+# Note: h2000 won't work well because of a clash between upper case and ~'s.
+H7|h2000|hazeltine 2000:\
+ :do=^J:al=6~^z:am:le=^H:bs:cl=6~^\:cm=~^q%r%.%.:co#74:\
+ :dl=6~^s:ho=~^r:li#27:nc:pc=\177:
+# Hazeltine esprit entries from Univ of Utah Tue Feb 1 06:39:37 1983
+# J.Lepreau, lepreau@utah-cs, harpo!utah-cs!lepreau
+HE|esprit|hazeltine esprit:\
+ :al=40\E^Z:bs:cd=5\E^X:ce=\E^O:cl=\E^\:cm=\E^Q%r%>^^ %+`%+`:co#80:\
+ :dl=40\E^S:do=\E^K:ho=\E^R:li#24:nd=^P:se=\E^Y:so=\E^_:up=\E^L:
+HF|esprit-am|hazeltine esprit auto-margin:\
+ :am:tc=esprit:
+# # --------------------------------
+#
+# I: IBM, INTERACTIVE SYSTEMS, and INTECOLOR
+#
+# Some of these should go in the misc category, IBM, ISC, and ISC can't
+# all have I. I will wait to see who comes out with more terminals.
+# These compucolors appear similar, but they at least have different
+# sized screens. I don't know what's going on here.
+I8|8001|ISC8001|compucolor|intecolor:\
+ :do=^J:al=\EU:am:le=^Z:bc=^Z:cl=3*^L:cm=^C%r%.%.:\
+ :co#80:cd=\EQ:dm=\EQ:ed=\EF:dc=\177:dl=\EV:ei=\EF:\
+ :im=\EQ:li#40:nd=1^Y:ta=8\t:up=^\:ho=1^H:pc=^@:
+IG|compucolor2|compucolorII:\
+ :do=^J:pt:am:cm=%r^C%.%.:le=^Z:bc=^Z:li#32:co#64:\
+ :cl=^L:ho=^H:nd=^Y:up=^\:
+# From cithep!eric Wed Sep 16 08:06:44 1981
+It|intext|Interactive Systems Corporation modified owl 1200:\
+ :do=^J:al=5.5*\020:am:le=^_:bc=^_:le=^H:bs:bt=^Y:cd=5.5*\026J:\
+ :ce=^K\160^R:cl=132\014:cm=\017%+ %+ :co#80:dc=5.5*\022:dl=5.5*\021:\
+ :ei=\026\074:im=\026\073:ip=5.5*:li#24:nd=\036:pt:up=\034:\
+ :se=^V# :sg#1:so=^V$,:ma=^K^P^R^L^L :\
+ :kl=^_:kd=^J:kr=^^:ku=\034:kb=^H:kh=^Z:\
+ :k1=^VA\r:k2=^VB\r:k3=^VC\r:k4=^VD\r:k5=^VE\r:\
+ :k6=^VF\r:k7=^VG\r:k8=^VH\r:k9=^VI\r:k0=^VJ\r:
+I9|ibm|ibm3101|3101|i3101|IBM 3101-10:\
+ :do=^J:ct=\EH:st=\E0:\
+ :if=/usr/lib/tabset/ibm3101:\
+ :am:le=^H:bs:cl=\EK:li#24:co#80:nd=\EC:up=\EA:cd=\EJ:ce=\EI:\
+ :kd=\EB:kl=\ED:kr=\EC:ku=\EA:ho=\EH:cm=\EY%+\40%+\40:pt:
+Ia|ibm-apl|apl|IBM apl terminal simulator:\
+ :li#25:tc=dm1520:
+#
+# M: MISCELLANEOUS TERMINALS
+#
+# The tab 132 uses xon/xoff, so no padding needed.
+# ks/ke have nothing to do with arrow keys.
+# is sets 80 col mode, normal video, autowrap on (for am).
+# Seems to be no way to get rid of status line.
+M0|abm80|amtek business machines 80:\
+ :do=^J:al=\E^Z:am:le=^H:bs:cd=\E^X:ce=\E^O:cl=\E^\:cm=\E^Q%r%+ %+ :\
+ :co#80:dl=\E^S:do=\E^K:li#24:nd=^P:.so=\E^_:.se=\E^Y:up=\E^L:\
+ :bw:bt=^T:ho=\E^R:
+M1|tab132|tab|tab132/15|tab 132/15:\
+ :is=\E[?7h\E[?3l\E[?5l:dN@:ks@:ke@:do=^J:\
+ :da:db:al=\E[L:dl=\E[M:dc=\E[P:ei=\E[4l:im=\E[4h:cm=\E[%i%d;%dH:\
+ :ku=\E[A:kd=\E[B:kl=\E[D:tc=vt100:
+M2|tab132w:\
+ :co#132:is=\E[?7h\E[?3h\E[?5l:tc=tab132:
+M3|tab132rv:\
+ :is=\E[?7h\E[?3l\E[?5h:tc=tab132:
+M4|tab132wrv:\
+ :is=\E[?7h\E[?3h\E[?5h:tc=tab132w:
+# This used to say "de#001202" which presumably refers to the stty bits
+# that need to be set for some version of Unix. We need the real delay
+# requirements in MS.
+M5|mw2|Multiwriter 2:\
+ :do=^J:co#132:hc:os:
+M6|trs80|trs-80|radio shack trs-80 Model I:\
+ :do=^J:am:le=^H:bs:co#64:li#16:
+M7|d800|Direct 800/A:\
+ :do=^J:co#80:li#24:am:cl=\E[1;1H\E[2J:le=^H:bs:cm=\E[%i%d;%dH:\
+ :nd=\E[C:up=\E[A:ce=\E[K:cd=\E[J:\
+ :so=\E[7m:se=\E[0m:us=\E[4m:ue=\E[0m:xs:vs=\E[>12l:ve=\E[>12h:\
+ :sf=\ED:sr=\EM:da:db:as=\E[1m:ae=\E[0m:ms:pt:\
+ :kl=\E[D:kr=\E[C:ku=\E[A:kd=\E[B:\
+ :k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:\
+ :k5=\EOT:k6=\EOU:k7=\EOV:k8=\EOW:
+M8|vc404|volker-craig 404:\
+ :do=^J:am:le=^H:bs:cd=40^W:ce=20^V:cl=40^X:cm=^P%+ %+ :co#80:\
+ :ho=40^Y:kd=^J:kl=^H:kr=^U:ku=^Z:li#24:ma=^Z^P^U :nd=^U:up=^Z:
+M9|vc404-s|volker-craig 404 w/standout mode:\
+ :do=^J:se=^O:so=^N:tc=vc404:
+MA|vc404-na|volker-craig 404 w/no arrow keys:\
+ :ma@:kr@:ku@:tc=vc404:
+MB|vc404-s-na|volker-craig 404 w/standout mode and no arrow keys:\
+ :se=^O:so=^N:tc=vc404na:
+# missing in vc303a and vc303 descriptions: they scroll 2 lines at a time
+MC|vc303a|vc403a|volker-craig 303a:\
+ :do=^J:am:le=^H:bs:ce=20^V:cl=40^X:co#80:ho=40^Y:kd=^J:kl=^H::kr=^U:\
+ :ku=^Z:li#24:ll=^P^@W:nd=^U:ns:up=^Z:
+MD|vc303|vc103|vc203|volker-craig 303:\
+ :do=^J:am:le=^H:bs:cl=40^L:co#80:ho=40^K:kd=^J:kl=^H:\
+ :kr=^I:ku=^N:li#24:ll=^O\200W:nd=^I:ns:up=^N:
+# Test version for Falco ts-1. See "arpavax.hickman@ucb" for info
+ME|falco|ts1|ts-1|falco ts-1:is=\Eu\E3:\
+ :do=^J:al=\EE:am:bs:ce=\ET\EG0^h:cm=\E=%+ %+ :cl=\E*:cd=\EY:co#80:\
+ :dc=\EW:dl=\ER:ei=\Er:ho=^^:im=\Eq:k0=^A0\r:kd=^J:kl=^H:pt:\
+ :kr=^L:ku=^K:li#24:nd=^L:se=\Eg0:so=\Eg1:up=^K:us=\Eg1:ue=\Eg0:
+MF|falco-p|falco ts-1sp|falco with paging option:\
+ :is=\EZ\E3\E_c:\
+ :al=\EE:am:bs:ce=\ET\EG0^H\Eg0:cl=\E*:cd=\EY:co#80:dc=\EW:\
+ :dl=\ER:kd=\E[B:kl=\E[D:ei=\Er:im=\Eq:pt:db:\
+ :kr=\E[C:ku=\E[A:li#24:nd=\E[C:se=\Eg0:so=\Eg4:\
+ :up=\E[A:us=\Eg1:ti=\E_d:te=\E_b:\
+ :ue=\Eg0:do=\E[B:cm=\E=%+ %+ :ms:ul:kh=\E[H:da:mi:bt=\EI:
+#NOTE: bg can scroll, it just would rather not (ns) - rwells 3/13/81.
+# (Shouldn't you take out ns and put in an nl instead? - mrh)
+MG|bg|bitgraph|BBN BitGraph terminal:\
+ :do=^J:al=2*\E[L:bs:cd=150\E[J:ce=2\E[K:\
+ :cl=150\E[H\E[J:cm=%i\E[%d;%dH:co#85:\
+ :dl=2*\E[M:k0=\EP:k1=\EQ:k2=\ER:k3=\ES:kd=\EB:ke=\E>:kl=\ED:kr=\EC:\
+ :ks=\E=:ku=\EA:li#64:nd=\E[C:ns:pt:se=\E[0m:so=\E[7m:up=\E[A:sf=280\n:
+MH|d132|datagraphix|datagraphix 132a:\
+ :do=^J:co#80:li#30:cl=^l:ho=\Et:da:db:sf=\Ev:sr=\Ew:\
+ :up=\Ek:nd=\El:vs=\ex:ve=\Em\En:\
+ :al=\E3:ic=\E5:dc=\E6:in:ic=\E5:
+MI|soroc|Soroc 120:\
+ :do=^J:cd=\EY:ce=\ET:cl=2\E*:ma=^K^P^R^L^L :\
+ :kl=^H:ku=^K:kr=^L:kd=^J:tc=adm3a:
+# From: ma179abu%sdcc3@sdcsvax.ucsd.edu (Bill Houle)
+MI|iq140|soroc140|Soroc IQ140 with inverse & dim:\
+ :ic=\EQ:dc=\EW:al=\EE:dl=\ER:ce=\ET:cd=\EY:cl=\E+:cm=\E=%+ %+ :\
+ :up=^K:do=^J:le=^H:nd=^L:ho=^^:ta=\Ei:ma=^Kk^Jj^Hh^Ll^^h:am:bs:\
+ :co#80:li#24:ei=:im=:kb=^H:kh=^^:ku=^K:kd=^J:kl=^H:kr=^L:\
+ :k0=^AI:k1=^A@:k2=^AA:k3=^AB:k4=^AC:k5=^AD:k6=^AE:k7=^AF:\
+ :k8=^AG:k9=^AH:se=\E:so=\E:us=\E):ue=\E(:
+# tec is untested, and taken from CB/Unix virtual terminal driver.
+# Upper case terminal, uses lower case for control sequences!!!
+# The driver shows the C ~ operator used on CM coordinates.
+# Without the terminal in front of me, I can't figure out what's
+# going on, so I've dotted out the cm. Note there is no ~ in tgoto.
+MJ|tec400|tec scope:\
+ :do=^J:.cm=l%r%.%.:up=x:do=h:nd=g:le=w:ho=i:so={:se=|:sg#1:\
+ :cl=f:al=e:dl=u:ic=d:dc=t:ce=c:cd=s:
+# From ucbvax!geoff Mon Sep 21 21:15:45 1981
+# This entry has been tested.
+MK|tec500|tec 500:\
+ :do=^J:am:le=^H:bs:cm=\E=%+ %+ :cl=20^Z:\
+ :co#80:ho=^^:li#24:nd=^L:up=^K:so=^]:se=^\:
+# I would appreciate more information on this terminal, such as the
+# manufacturer and the model number. There is too many tecs in here.
+ML|tec:\
+ :li#24:co#80:cl=^l:up=^k:nd=\037:\
+ :am:le=^H:bs:ho=\036:ma=^K^P^_ :do=^J:
+MM|teletec|Teletec Datascreen:\
+ :do=^J:am:le=^H:bs:co#80:cl=^l:ho=^^:li#24:nd=^_:up=^k:
+# From cbosg!ucbvax!SRC:george Fri Sep 11 22:38:32 1981
+MN|ampex|d80|dialogue|dialogue80|ampex dialogue 80:\
+ :ct=\E3:st=\E1:do=^J:is=\EA:us=\El:ue=\Em:\
+ :am:le=^H:bs:pt:cl=75\E*:cm=\E=%+ %+ :\
+ :al=5*\EE:bt=\EI:ic=\EQ:im=:ei=:dl=5*\ER:dc=\EW:\
+ :ce=\Et:cd=\Ey:so=\Ej:se=\Ek:li#24:co#80:nd=^L:up=^K:
+# From: atd!dsd!rcb@ucbvax.berkeley.edu (Richard Bascove)
+A2|a210|210|ampex210|ampex a210:\
+ :am:bs:cl=\E*:cm=\E=%+ %+ :al=\EE:bt=\EI:ic=\EQ:im=:ei=:\
+ :dl=\ER:dc=\EW:ho=^^:xn:ce=\Et:cd=\Ey:li#24:co#80:nd=^L:up=^K:\
+ :pt:if=/usr/lib/tabset/std:is=\EC\Eu\E'\E(\El\EA\E%\E{\E.2\EG0\Ed\En:\
+ :kl=^H:kr=^L:kd=^V:ku=^K:kh=^^:hs:ts=\E.0\Eg\E}\Ef:fs=\E.2:\
+ :kn#10:k0=^A0^M:k1=^A1^M:k2=^A2^M:k3=^A3^M:k4=^A4^M:k5=^A5^M:\
+ :vb=\EU\EX\EU\EX\EU\EX\EU\EX:k6=^A6^M:k7=^A7^M:k8=^A8^M:k9=^A9^M:\
+ :so=\EG4:se=\EG0:us=\EG8:ue=\EG0:ug#1:sg#1:
+MO|digilog|333|digilog 333:\
+ :le=^H:bs:co#80:ce=\030:ho=^n:li#16:nd=^i:up=^o:do=^J:
+MP|ep48|ep4080|execuport 4080:\
+ :am:le=^H:bs:os:co#80:hu=\036:hd=\034:do=^J:
+MQ|ep40|ep4000|execuport 4000:\
+ :am:le=^H:bs:os:co#136:hu=\036:hd=\034:do=^J:
+MR|terminet1200|terminet300|tn1200|tn300|terminet|GE terminet 1200:\
+ :co#120:hc:os:do=^J:
+# AED 512
+# by giles Billingsley (gilesb%ucbcad@berkeley)
+# rewritten 8/82 for newer AEDs and better operation of vi,etc.
+MS|aed|AED|aed512|AED512|aed 512:\
+ :db:co#64:li#40:cl=^L:bs:nd=\Ei0800\001:\
+ :up=^K:ve=\E\E\E\E\E\E\E\072004=000200??\001:\
+ :vb=\EK0001??0000K0001202080\001:\
+ :us=\E\07200>8000140\001:ue=\E\07200>8000100\001:\
+ :uc=\Ei???>l0800i0102\001:\
+ :ti=\E\07200>8000140{<04<0??00001010L<0\072004=0002??00\001:\
+ :te=\E\07200>8000100{804<0??00001000L80\072004=000200??\001:\
+ :so=\E\07200>8000140[80C00\001:se=\E[00C80\001:\
+ :is=\EG1MMM.`40K0001202080K8001????00^L\EC80L80{80^L\EK010100????K0601??0000c818100\EG1HHH.\07210000019A27FD006A280D002A200A52429FE8524861086118612861360N031B4C3F3F1800N041B0C1B4C38301800N001B3B313030301800N011B3B313030341800N021B3B313030381800N050800N061B3B313335301800\07211000015A58E8D5011A58F8D5111A5908D5211A5918D531160\07212000015AD5011858EAD5111858FAD52118590AD5311859160\0721300004B2071C5858E0A18658E0A0A858EA900858F268FA5278590A50A29018591A9F51865908590A90165918591A59038E58E8590A591E58F290185912071C5180A0A0A0901858EA900858F268F60\0721350000BA9472031DEA9502031DE60\E\E\E\EG1MMM.^A:
+zL|aed-ucb|AED-UCB|aed512-ucb|AED512-UCB|aed 512 w/o UCB ROM:\
+ :db:co#64:li#40:cl=^L:bs:nd=\Ei0800\001:up=^K:\
+ :ve=\E\E\E\E\E\E\E\072004=000200??\001:\
+ :vb=\EK0001??0000K0001202080\001:\
+ :us=\E\07200>8000140\001:ue=\E\07200>8000100\001:\
+ :uc=\Ei???>l0800i0102\001:\
+ :ti=\E\07200>8000140{<04<0??00001010L<0\072004=0002??00\001:\
+ :te=\E\07200>8000100{804<0??00001000L80\072004=000200??\001:\
+ :so=\E\07200>8000140[80C00\001:se=\E[00C80\001:\
+ :if=/usr/lib/tabset/aed512:
+# CIT 80 - vt 100 emulator, the termcap has been modified to remove
+# the delay times and do an auto tab set rather than the indirect
+# file used in vt100.
+MT|cit80|cit 80|Citoh 80:\
+ :co#80:li#24:am:cl=\E[;H\EJ:bs:cm=\E[%i%2;%2H:nd=\E[C:up=\E[A:\
+ :ce=\EK:cd=\EJ:is=\E>:ks=\E[?1h\E=:ke=\E[?1l\E>:\
+ :ku=\EOA:kd=\EOB:kr=\EOC:kl=\EOD:
+# From mtxinu!sybase!tim (Tim Wood) Fri Sep 27 09:39:12 PDT 1985
+# Alternate cit101 (vt100 em) file used in vt100.
+# Uses 23 lines so can run citsys (like h19sys).
+# 24 May 85 (mtxinu!sybase!tim) - removed 2-byte limit on 'cm' cursor
+# coordinates otherwise there is garbling on long lines in
+# co#132 mode; also added support for multipage memory on the Itoh.
+MU|citc|Citoh fast vt100:\
+ :co#80:li#23:am:cl=\E[;H\E[2J:bs:cm=\E[%i%d;%dH:nd=\E[C:up=\E[A:\
+ :ce=\E[K:cd=\E[J:so=\E[7m:se=\E[m:us=\E[4m:ue=\E[m:\
+ :is=\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h\E[3g\E[>5g:\
+ :ks=\E[?1h\E=:ke=\E[?1l\E>:ku=\EOA:kd=\EOB:kr=\EOC:kl=\EOD:\
+ :vb=\E[?5h\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\E[?5l:\
+ :dc=\E[P:al=\E[L:im=:ei=:dl=\E[M:ic=\E[@:vs=\E7\E[U:ve=\E[V\E8:xn:
+MV|cita|:\
+ :co#80:li#23:am:cl=\E[;H\E[2J:bs:cm=\E[%i%d;%dH:nd=\E[C:up=\E[A:\
+ :ce=\E[K:cd=\E[J:so=\E[7m:se=\E[m:us=\E[4m:ue=\E[m:\
+ :is=\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h\E[3g\E[>5g:\
+ :ks=\E[?1h\E=:ke=\E[?1l\E>:\
+ :ku=\EOA:kd=\EOB:kr=\EOC:kl=\EOD:vs=\E7\E[U:ve=\E[V\E8:\
+ :vb=\E[?5h\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\E[?5l:xn:
+MW|cit101:li#24:vb@:tc=citc
+MX|cit101b:li#24:tc=citc
+Mh|cit500|cit-500|cit 500:\
+ :co#80:li#40:cl=50\E[;H\E[2J:bs:am:cm=5\E[%i%2;%2H:nd=2\E[C:up=2\E[A:\
+ :ce=3\E[K:cd=50\E[J:so=2\E[7m:se=2\E[m:us=2\E[4m:ue=2\E[m:\
+ :is=\E(B\E)0\E>\E[?3l\E[?7h\E[?8h:ks=\E[?1h\E=:ke=\E[?1l\E>:\
+ :if=/usr/lib/tabset/vt100:ku=\EOA:kd=\EOB:kr=\EOC:kl=\EOD:\
+ :kh=\E[H:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:pt:sr=5\EM:xn:\
+ :do=\ED:al=\E[L:dc=\E[P:dl=\E[M:
+# Note several versions of blit. I don't know exactly what is what
+# so please send me any corrections to this -- mrh
+# From research!ikeya!rob Tue Aug 31 23:41 EDT 1982
+MY|blit|jerq|blit-pb|blit running teletype rom:\
+ :do=^J:IC=\Ef%+ :DC=\Ee%+ :AL=\EF%+ :DL=\EE%+ :\
+ :mi:dl=\EE!:ic=\Ef!:dc=\Ee!:al=\EF!:\
+ :ce=\EK:cl=^L:cm=\EY%r%+ %+ :co#87:li#72:nd=\EC:\
+ :up=\EA:ku=\EA:kd=\EB:kr=\EC:kl=\ED:kb=^H:am:ul:pt:eo:
+MZ|cbblit|columbus enhanced tty blit:\
+ :vb=\E^G:so=\EU!:se=\EV!:us=\EU":ue=\EV":cd=\EJ:\
+ :im=\EQ:ei=\ER:ic@:co#88:sf=\EG:tc=blit:
+Ma|oblit|ojerq|first version of blit rom:\
+ :do=^J:AL=\Ef%+ :DL=\Ee%+ :mi:dl=\EE:ei=\ER:im=\EQ:dc=\EO:da:db:\
+ :al=\EF:cd=\EJ:ce=\EK:cl=^L:cm=\EY%r%+ %+ :co#88:li#72:nd=\EC:\
+ :up=\EA:vb=\E^G:am:ul:pt:eo:
+Mb|daleblit|daleterm|blit running Dale DeJager's ROM:\
+ :ku=\EA:kd=\EB:kr=\EC:kl=\ED:so=\EU!:se=\EV!:us=\EU":ue=\EV":\
+ :da@:db@:tc=oblit:
+Mc|datapoint|dp3|dp3360|datapoint 3360:\
+ :do=^J:am:le=^H:bs:cd=^_:ce=^^:cl=^]^_:co#82:ho=^]:li#25:nd=^x:up=^z:
+#From: cbosgd!utcs!romwa@ucbvax.berkeley.edu (mark dornfeld)
+# This termcap is for the LANPAR Technologies VISION 3220
+# terminal. The function key definitions k0-k5 represent the
+# edit keypad: FIND, INSERT HERE, REMOVE, SELECT, PREV SCREEN,
+# NEXT SCREEN. The key definitions k6-k9 represent the PF1 to
+# PF4 keys.
+v0|v3220|LANPAR Vision II model 3220/3221/3222:\
+ :co#80:li#24:cl=\E[H\E[J:bs:am:cm=\E[%i%d;%dH:nd=\E[C:up=\E[A:\
+ :ce=\E[K:cd=\E[J:so=\E[7m:se=\E[m:us=\E[4m:ue=\E[m:\
+ :is=\E>\E[?3l\E[?7h\E[?8h\E[p:ks=\E=:ke=\E>:\
+ :kn#10:k0=\E[1~:k1=\E[2~:k2=\E[3~:k3=\E[4~:k4=\E[5~:k5=\E[6~:\
+ :k6=\E[OP:k7=\E[OQ:k8=\E[OR:k9=\E[OS:\
+ :ku=\E[A:kd=\E[B:kr=\E[C:kl=\E[D:\
+ :kh=\E[H:pt:sr=\EM:xn:\
+ :dl=\E[M:dc=\E[P:ei=\E[4l:al=\E[L:im=\E[4h:mi:
+# From ucbvax!faletti (Faletti@Berkeley)
+# FREEDOM 100 by Liberty Electronics USA, SF.
+# :kh=^^: left out because it precludes using change-to-alternate-file in vi.
+# Basic Freedom 100 entry, works with VI at 1200 baud.
+Md|f100|freedom100|freedom|freedom 100 no padding:\
+ :am:bs:bw:mi:ms:pt:co#80:kn#20:li#24:\
+ :ct=\E3:st=\E1:is=\Eg\Ef\r\Ed:kr=^L:\
+ :cl=^Z:do=^J:ho=^^:kb=^H:kl=^H:\:kd=^V:\
+ :ko=dc,al,dl,cl,bt,ce,cd:ku=^K:le=^H:nd=^L:\
+ :ch=\E]%+ :cm=\E=%+ %+ :cv=\E[%+ :sr=\Ej:up=^K:\
+ :al=\EE:bt=\EI:cd=\EY:ce=\ET:dc=\EW:dl=\ER:ei=\Er:im=\Eq:\
+ :se=\EG0:so=\EG4:ue=\EG0:us=\EG8:as=\E$:ae=\E%:\
+ :vb=\Eb\200\200\Ed:\
+ :k1=^A@\r:k2=^AA\r:k3=^AB\r:k4=^AC\r:k5=^AD\r:\
+ :k6=^AE\r:k7=^AF\r:k8=^AG\r:k9=^AH\r:k0=^AI\r:\
+ :hs:ts=\Eg\Ef:fs=\r:ds=\Eg\Ef\r:
+Me|f100-rv|freedom100-rv|freedom-rv|freedom100 with reverse video at 1200:\
+ :is=\Eg\Ef\r\Eb:vb=\Ed\200\200\Eb:tc=freedom100:
+# VI at 9600 baud (or EMACS at 1200 -- but may be more than is needed for emacs)
+Mf|f100-v|freedom100-v|freedom-v|freedom100 for 9600 vi or 1200 emacs:\
+ :al=6.5*\EE:dl=11.5*\ER:\
+ :vb=\Eb\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\Ed:\
+ :tc=freedom100:
+Mx|f100-v-rv|freedom100-v-rv|freedom-v-rv|freedom100 rev. vid. for 9600 vi:\
+ :al=6.5*\EE:dl=11.5*\ER:is=\Eg\Ef\r\Eb:\
+ :vb=\Ed\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\Eb:\
+ :tc=freedom100:
+# EMACS at 9600 baud -- this still needs some more work on the padding
+My|f100-e|freedom100-e|freedom-e|freedom100 for 9600 emacs:\
+ :al=8.5*\EE:dl=11.5*\ER:ip=6:\
+ :vb=\Eb\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\Ed:\
+ :tc=freedom100:
+Mz|f100-e-rv|freedom100-e-rv|freedom-e-rv|freedom100 rev. vid. for emacs 9600:\
+ :al=8.5*\EE:dl=11.5*\ER:ip=6:is=\Eg\Ef\r\Eb:\
+ :vb=\Ed\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\Eb:\
+ :tc=freedom100:
+zM|f110-v|freedom110-v|freedom110 for 9600 vi or 1200 emacs:\
+ :is=\Eg\Ef\r\Ed\EO:dc=\EO\EW:im=\EO\Eq:\
+ :al=6.5*\EE:dl=11.5*\ER:\
+ :vb=\Eb\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\Ed:\
+ :tc=freedom100:
+# (from kerch@lll-crg)
+L1|f200|freedom200| Freedom 200 VDT by Liberty Electronics :\
+ :if=/usr/lib/tabset/stdcrt:al=\EE:am:bs:bt=\EI:cd=\EY:\
+ :ce=\ET:cl=^Z:cm=\E=%+ %+ :co#80:dc=\EW:dl=\ER:do=^V:\
+ :ds=\Eh:ei=\Er:im=\Eq:is=\Eg\El\E\041\062:\
+ :k1=^A@\r:k2=^AA\r:k3=^AB\r:k4=^AC\r:k5=^AD\r:\
+ :k6=^AE\r:k7=^AE\r:k8=^AF\r:k9=^AG\r:kd=^V:kr=L:\
+ :ku=^K:li#24:ms:nd=^L:se=\EG0:so=\EG4:sr=\Ej:\
+ :te=\EJ\E\\2\E|\041\061^L^Y:ti=\E\\1\EK\E|\041\061L^Y:\
+ :ts=\Ef:ue=\EG0:up=^K:us=\EG8:vb=\Eb\Ed:hs:i2=\E^O\Eg:\
+ :ts=\Ef:fs=^M:ds=\E^N:
+Mg|dg|dg6053|data general 6053:\
+ :do=^J:am:le=^H:bs:cm=^P%r%.%.:cl=^L:ho=^H:nd=^S:\
+ :up=^W:ce=^K:co#80:li#24:
+Mi|cdi|cdi1203:\
+ :am:le=^H:bs:hc:os:co#80:dC#200:do=^J:
+# ^S is an arrow key! Boy is this guy in for a surprise on v7!
+Ml|sol:\
+ :do=^J:am:le=^Y:ho=^H:bs:cm=\E^1%.\E^2%.:cl=^K:ho=^N:co#64:li#16:\
+ :nd=^S:up=^W:kl=^A:kr=^S:ku=^W:kd=^Z:ma=^A^H^S ^W^P^Z^N:
+Mn|xl83|Cybernex XL-83:\
+ :do=^J:am:le=^H:bs:cd=62^P:ce=3^O:cl=62^L:cm=^W%+ %+ :co#80:ho=^K:\
+ :kd=^J:kl=^H:ku=^N:li#24:up=^N:nd=^I:
+Mo|omron|Omron 8025AG:\
+ :do=^J:al=\EL:am:le=^H:bs:cd=\ER:co#80:ce=\EK:cl=\EJ:\
+ :da:db:dc=\EP:dl=\EM:ho=\EH:li#24:nd=\EC:se=\E4:sf=\ES:\
+ :so=\Ef:sr=\ET:up=\EA:ve=:vs=\EN:
+Mp|plasma|plasma panel:\
+ :am:le=^H:bs:cl=^L:co#85:ho=^^:li#45:nd=\030:up=\026:do=^J:
+Mq|pty|psuedo teletype:\
+ :do=^J:co#80:li#24:am:cl=\EJ:le=^H:bs:cm=\EG%+ %+ :nd=\EC:\
+ :up=\EA:ce=\EK:cd=\EL:al=\EP:dl=\EN:ic=\EO:\
+ :so=\Ea$:se=\Eb$:us=\Ea!:ue=\Eb!:
+Mr|remote|virtual remote terminal:\
+ :co#79:am@:nl@:tc=virtual:
+Ms|swtp|ct82|southwest technical products ct82:\
+ :do=^J:am:le=^d:bc=^d:\
+ :al=^\^y:cd=^v:ce=^F:cl=^L:cm=%r^k%.%.:co#82:li#20:\
+ :dl=^z:nd=^s:up=^a:so=^^^v:se=^^^F:dc=^\^h:ic=^\^x:ho=^p:\
+ :ei=:sf=^n:sr=^o:ll=^c:im=:\
+ :is=^\^r^^^s^^^d^]^w^i^s^^^]^^^o^]^w^r^i:
+Mt|terak|Terak emulating Datamedia 1520:\
+ :tc=dm1520:
+# From john@ucbrenoir Tue Sep 24 13:14:44 1985
+M4|sun-12|Sun 12-line window:\
+ :li#12:co#80:tc=sun:
+M5|sun-1|Sun 1-line window for sysline:\
+ :li#1:co#80:es:hs:ts=\r:fs=\E[K:ds=^L:tc=sun:
+Mv|virtual|VIRTUAL|cb unix virtual terminal:\
+ :do=^J:co#80:li#24:am:cl=\E\112:le=^H:bs:cm=\E\107%r%.%.:nd=\E\103:\
+ :up=\E\101:ce=\E\113:cd=\E\114:al=\E\120:dl=\E\116:im=:ei=:ic=\E\117:\
+ :da:db:kl=\E\104:kr=\E\103:ku=\E\101:kd=\E\102:kh=\E\105:\
+ :so=\E\141\004:se=\E\142\004:us=\E\141\001:ue=\E\142\001:
+Mw|it2|intertube2|intertec data systems intertube 2:\
+ :do=^J:am:bs:cl=^L:co#80:ho=^A:li#25:up=^Z:ce=\EK:\
+ :cm=^N%+ %+ :ch=^P%\102%.:cv=^K%.:nd=^F:do=\n:ll=^K^X\r:\
+ :so=\E0P:se=\E0@:
+Mx|delta|dd5000|delta data 5000:\
+ :do=^J:am:le=^H:bs:cl=^NR:cm=^O%\068%+9%\068%+9:co#80:li#27:\
+ :ho=^NQ:nc:nd=^Y:up=^Z:ce=^NU:dc=^NV:ma=^K^J^Z^P^Y :xr:
+My|mdl110|cybernex mdl-110:\
+ :cm=^P%+ %+ :co#80:li#24:am:cl=70^X:le=^H:bs:do=^J:\
+ :nd=^U:up=^Z:ho=^Y:ce=145^N@^V:cd=145^NA^W:al=65^NA^N^]:\
+ :dl=40^NA^N^^:im=:ei=:ic=3.5^NA^]:dm=:ed=:dc=3.5^NA^^:\
+ :so=^NF:se=^NG:ta=43\t:ma=^Z^P:cd=6^N@^V
+Mz|zen30|z30|zentec 30:\
+ :do=^J:mi:co#80:li#24:ma=^L ^R^L^K^P:ul:\
+ :al=1.5*\EE:le=^H:bs:ce=1.0*\ET:cm=\E=%+ %+ :cl=\E*:\
+ :ho=^^:nd=^L:se=\EG0:so=\EG6:up=^K:im=\Eq:ei=\Er:\
+ :am:dc=\EW:dl=1.5*\ER:cd=\EY:
+m0|modgraph|mod|Modgraph terminal emulating vt100, 24x80:\
+ :xn@:rf@:sr=5\EM\E[K:vs=\E\^9;0s\E\^7;1s:\
+ :is=\E\^9;0s\E\^7;1s\E[3g\E\^11;9s\E\^11;17s\E\^11;25s\E\^11;33s\E\^11;41s\E\^11;49s\E\^11;57s\E\^11;65s\E\^11;73s\E\^11;81s\E\^11;89s:\
+ :tc=vt100:
+# dmchat is like DM2500, but DOES need "all that padding" (jcm 1/31/82)
+# also, has a meta-key (MT)
+# from goldberger@su-csli.arpa
+MX|dmchat|dmchat version of datamedia 2500:\
+ :al=1*^P\n^X^]^X^]:\
+ :MT:km:\
+ :dl=2^P^Z^X^]:\
+ :tc=dm2500:
+# # --------------------------------
+#
+# N: ANN ARBOR
+#
+# Needs function keys added.
+# Originally from Mike O'Brien@Rand and Howard Katseff at Bell Labs.
+# Highly modified 6/22 by Mike O'Brien.
+# split out into several for the various screen sizes by dave-yost@rand
+# Modifications made 3/82 by Mark Horton
+# Modified by Tom Quarles at UCB for greater efficiency and more diversity
+# status line moved to top of screen, vb removed 5/82
+#
+# assumes the following setup:
+# A: 0000 1010 0001 0000
+# B: 9600 0100 1000 0000 0000 1000 0000 17 19
+# C: 56 66 0 0 9600 0110 1100
+# D: 0110 1001 1 0
+#
+# Briefly, the settings are for the following modes:
+# (values are for bit set/clear with * indicating our preference
+# and the value used to test these termcaps)
+# Note that many of these settings are irelevent to the termcap
+# and are just set to the default mode of the terminal as shipped
+# by the factory.
+#
+# A menu: 0000 1010 0001 0000
+# Block/underline cursor*
+# blinking/nonblinking cursor*
+# key click/no key click*
+# bell/no bell at column 72*
+#
+# key pad is cursor control*/key pad is numeric
+# return and line feed/return for <cr> key *
+# repeat after .5 sec*/no repeat
+# repeat at 25/15 chars per sec. *
+#
+# hold data until pause pressed/process data unless pause pressed*
+# slow scroll/no slow scroll*
+# Hold in area/don't hold in area*
+# functions keys have default*/function keys disabled on powerup
+#
+# show/don't show position of cursor during page transmit*
+# unused
+# unused
+# unused
+#
+# B menu: 9600 0100 1000 0000 0000 1000 0000 17 19
+# Baud rate (9600*)
+#
+# 2 bits of parity - 00=odd,01=even*,10=space,11=mark
+# 1 stop bit*/2 stop bits
+# parity error detection off*/on
+#
+# keyboard local/on line*
+# half/full duplex*
+# disable/do not disable keyboard after data transmission*
+#
+# transmit entire page/stop transmission at cursor*
+# transfer/do not transfer protected characters*
+# transmit all characters/transmit only selected characters*
+# transmit all selected areas/transmit only 1 selected area*
+#
+# transmit/do not transmit line seperators to host*
+# transmit/do not transmit page tab stops tabs to host*
+# transmit/do not transmit column tab stop tabs to host*
+# transmit/do not transmit graphics control (underline,inverse..)*
+#
+# enable*/disable auto XON/XOFF control
+# require/do not require receipt of a DC1 from host after each LF*
+# pause key acts as a meta key/pause key is pause*
+# unused
+#
+# unused
+# unused
+# unused
+# unused
+#
+# XON character (17*)
+# XOFF character (19*)
+#
+# C menu: 56 66 0 0 9600 0110 1100
+# number of lines to print data on (printer) (56*)
+#
+# number of lines on a sheet of paper (printer) (66*)
+#
+# left margin (printer) (0*)
+#
+# number of pad chars on new line to printer (0*)
+#
+# printer baud rate (9600*)
+#
+# printer parity: 00=odd,01=even*,10=space,11=mark
+# printer stop bits: 2*/1
+# print/do not print guarded areas*
+#
+# new line is: 01=LF,10=CR,11=CRLF*
+# unused
+# unused
+#
+# D menu: 0110 1001 1 0
+# LF is newline/LF is down one line, same column*
+# wrap to preceeding line if move left from col 1*/don't wrap
+# wrap to next line if move right from col 80*/don't wrap
+# backspace is/is not destructive*
+#
+# display*/ignore DEL character
+# display will not/will scroll*
+# page/column tab stops*
+# erase everything*/erase unprotected only
+#
+# editing extent: 0=display,1=line*,2=field,3=area
+#
+# unused
+#
+N0|aaa-29-np|aaa-29 with no padding (for psl):\
+ :al=\E[L:ce=\E[K:cl=\E[H\E[J:dc=\E[P:dl=\E[M:ic=\E[@:tc=aaa-29:
+NA|aaa-unk|ann arbor ambassador (internal - don't use this directly):\
+ :do=^J:al=3\E[L:am:le=^H:bs:\
+ :cd=\E[J:ce=5\E[K:cl=156\E[H\E[J:cm=\E[%i%d;%dH:co#80:\
+ :dc=4\E[P:dl=3\E[M:ho=\E[H:ic=4\E[@:\
+ :md=\E[1m:mr=\E[7m:mb=\E[5m:mk=\E[8m:me=\E[m:\
+ :ku=\EM:kd=\ED:kl=\E[D:kr=\E[C:kh=\E[H:ko=cl,dc,dl,ce,cd:\
+ :ks=\EP`?z~[H~[[J`>z~[[J`8xz~[M`4xz~[[D`6xz~[[C`2xz~[D\E\\:\
+ :ke=\EP`?y~[H~[[J`>y~[[2J`8xy~[M`4xy~[[D`6xy~[[C`2xy~[D\E\\:\
+ :ch=\E[%i%d`:ul:ei=:im=:pt:bw:bt=\E[Z:\
+ :mi:nd=\E[C:se=\E[m:so=\E[7m:ue=\E[m:us=\E[4m:up=\EM:
+NB|aaa-18|ann arbor ambassador/18 lines:\
+ :ti=\E[2J\E[18;0;0;18p:te=\E[60;0;0;18p\E[18;1H\E[J:\
+ :is=\EP`+x~M\E\\\E[m\E7\E[60;0;0;18p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\
+ :li#18:tc=aaa-unk:
+NC|aaa-20|ann arbor ambassador/20 lines:\
+ :ti=\E[2J\E[20;0;0;20p:te=\E[60;0;0;20p\E[20;1H\E[J:\
+ :is=\EP`+x~M\E\\\E[m\E7\E[60;0;0;20p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\
+ :li#20:tc=aaa-unk:
+ND|aaa-22|ann arbor ambassador/22 lines:\
+ :ti=\E[2J\E[22;0;0;22p:te=\E[60;0;0;22p\E[22;1H\E[J:\
+ :is=\EP`+x~M\E\\\E[m\E7\E[60;0;0;22p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\
+ :li#22:tc=aaa-unk:
+NE|aaa-24|ann arbor ambassador/24 lines:\
+ :ti=\E[2J\E[24;0;0;24p:te=\E[60;0;0;24p\E[24;1H\E[J:\
+ :is=\EP`+x~M\E\\\E[m\E7\E[60;0;0;24p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\
+ :li#24:tc=aaa-unk:
+NF|aaa-26|ann arbor ambassador/26 lines:\
+ :ti=\E[2J\E[26;0;0;26p:te=\E[60;0;0;26p\E[26;1H\E[J:\
+ :is=\EP`+x~M\E\\\E[m\E7\E[60;0;0;26p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\
+ :li#26:tc=aaa-unk:
+NG|aaa-28|ann arbor ambassador/28 lines:\
+ :ti=\E[2J\E[28;0;0;28p:te=\E[60;0;0;28p\E[28;1H\E[J:\
+ :is=\EP`+x~M\E\\\E[m\E7\E[60;0;0;28p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\
+ :li#28:tc=aaa-unk:
+NH|aaa|aaa-30|ambas|ambassador|ann arbor ambassador/30 lines:\
+ :ti=\E[2J\E[30;0;0;30p:te=\E[60;0;0;30p\E[30;1H\E[J:\
+ :is=\EP`+x~M\E\\\E[m\E7\E[60;0;0;30p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\
+ :li#30:tc=aaa-unk:
+NI|aaa-36|ann arbor ambassador/36 lines:\
+ :ti=\E[2J\E[36;0;0;36p:te=\E[60;0;0;36p\E[36;1H\E[J:\
+ :is=\EP`+x~M\E\\\E[m\E7\E[60;0;0;36p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\
+ :li#36:tc=aaa-unk:
+NJ|aaa-40|ann arbor ambassador/40 lines:\
+ :ti=\E[2J\E[40;0;0;40p:te=\E[60;0;0;40p\E[40;1H\E[J:\
+ :is=\EP`+x~M\E\\\E[m\E7\E[60;0;0;40p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\
+ :li#40:tc=aaa-unk:
+NK|aaa-48|ann arbor ambassador/48 lines:\
+ :ti=\E[2J\E[48;0;0;48p:te=\E[60;0;0;48p\E[48;1H\E[J:\
+ :is=\EP`+x~M\E\\\E[m\E7\E[60;0;0;48p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\
+ :li#48:tc=aaa-unk:
+NL|aaa-60|ann arbor ambassador/60 lines:\
+ :ti=\E[2J\E[60;0;0;60p:te=\E[60;0;0;60p\E[60;1H\E[J:\
+ :is=\EP`+x~M\E\\\E[m\E7\E[60;0;0;60p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\
+ :li#60:tc=aaa-unk:
+NS|aaa-unk-s|ann arbor ambassador unknown with/status:\
+ :es:hs:i2=\E7\E[>51h\E[H\E[2K\E[>51l\E8:\
+ :ts=\E7\E[>51h\E[H\E[2K\E[%i%d`:fs=\E[>51l\E8:\
+ :ds=\E7\E[>51h\E[H\E[2K\E[>51l\E8:\
+ :tc=aaa-unk:
+NM|aaa-18-s|ambassador|ann arbor ambassador/18 lines + status line:\
+ :ti=\E[2J\E[18;1;0;18p:\
+ :te=\E[60;1;0;18p\E[17;1H\E[J:\
+ :is=\EP`+x~M\E\\\E[m\E7\E[60;1;0;18p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\
+ :li#17:tc=aaa-unk-s:
+NN|aaa-20-s|ambassador|ann arbor ambassador/20 lines + status line:\
+ :ti=\E[2J\E[20;1;0;20p:\
+ :te=\E[60;1;0;20p\E[19;1H\E[J:\
+ :is=\EP`+x~M\E\\\E[m\E7\E[60;1;0;20p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\
+ :li#19:tc=aaa-unk-s:
+NO|aaa-22-s|ambassador|ann arbor ambassador/22 lines + status line:\
+ :ti=\E[2J\E[22;1;0;22p:\
+ :te=\E[60;1;0;22p\E[21;1H\E[J:\
+ :is=\EP`+x~M\E\\\E[m\E7\E[60;1;0;22p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\
+ :li#21:tc=aaa-unk-s:
+NP|aaa-24-s|ambassador|ann arbor ambassador/24 lines + status line:\
+ :ti=\E[2J\E[24;1;0;24p:\
+ :te=\E[60;1;0;24p\E[23;1H\E[J:\
+ :is=\EP`+x~M\E\\\E[m\E7\E[60;1;0;24p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\
+ :li#23:tc=aaa-unk-s:
+NQ|aaa-26-s|ambassador|ann arbor ambassador/26 lines + status line:\
+ :ti=\E[2J\E[26;1;0;26p:\
+ :te=\E[60;1;0;26p\E[25;1H\E[J:\
+ :is=\EP`+x~M\E\\\E[m\E7\E[60;1;0;26p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\
+ :li#25:tc=aaa-unk-s:
+NR|aaa-28-s|ambassador|ann arbor ambassador/28 lines + status line:\
+ :ti=\E[2J\E[28;1;0;28p:\
+ :te=\E[60;1;0;28p\E[27;1H\E[J:\
+ :is=\EP`+x~M\E\\\E[m\E7\E[60;1;0;28p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\
+ :li#27:tc=aaa-unk-s:
+NT|aaa-30-s|ambassador|ann arbor ambassador/30 lines + status line:\
+ :ti=\E[2J\E[30;1;0;30p:\
+ :te=\E[60;1;0;30p\E[29;1H\E[J:\
+ :is=\EP`+x~M\E\\\E[m\E7\E[60;1;0;30p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\
+ :li#29:tc=aaa-unk-s:
+NU|aaa-36-s|ambassador|ann arbor ambassador/36 lines + status line:\
+ :ti=\E[2J\E[36;1;0;36p:\
+ :te=\E[60;1;0;36p\E[35;1H\E[J:\
+ :is=\EP`+x~M\E\\\E[m\E7\E[60;1;0;36p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\
+ :li#35:tc=aaa-unk-s:
+NV|aaa-40-s|ambassador|ann arbor ambassador/40 lines + status line:\
+ :ti=\E[2J\E[40;1;0;40p:\
+ :te=\E[60;1;0;40p\E[39;1H\E[J:\
+ :is=\EP`+x~M\E\\\E[m\E7\E[60;1;0;40p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\
+ :li#39:tc=aaa-unk-s:
+NW|aaa-48-s|ann arbor ambassador/48 lines+sl:\
+ :ti=\E[2J\E[48;1;0;48p:te=\E[60;1;0;48p\E[47;1H\E[J:\
+ :is=\EP`+x~M\E\\\E[m\EP`?y~[[2J~[[H\E7\E[60;1;0;48p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\
+ :li#47:tc=aaa-unk-s:
+NX|aaa-60-s|ambassador|ann arbor ambassador/60 lines + status line:\
+ :ti=\E[2J\E[60;1;0;60p:te=\E[60;1;0;60p\E[59;1H\E[J:\
+ :is=\EP`+x~M\E\\\E[m\E7\E[60;1;0;60p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\
+ :li#59:tc=aaa-unk-s:
+NY|aaa-18-rv|ambassador/18 lines+rv:\
+ :md=\E[1;7m:mr=\E[m:mb=\E[5;7m:mk=\E[7;8m:me=\E[7m:\
+ :us=\E[4;7m:ue=\E[7m:se=\E[7m:so=\E[m:\
+ :is=\EP`+x~M\E\\\E[7m\E7\E[60;0;0;18p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\
+ :tc=aaa-18:
+NZ|aaa-20-rv|ambassador/20 lines+rv:\
+ :md=\E[1;7m:mr=\E[m:mb=\E[5;7m:mk=\E[7;8m:me=\E[7m:\
+ :us=\E[4;7m:ue=\E[7m:se=\E[7m:so=\E[m:\
+ :is=\EP`+x~M\E\\\E[7m\E7\E[60;0;0;20p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\
+ :tc=aaa-20:
+Na|aaa-22-rv|ambassador/22 lines+rv:\
+ :md=\E[1;7m:mr=\E[m:mb=\E[5;7m:mk=\E[7;8m:me=\E[7m:\
+ :us=\E[4;7m:ue=\E[7m:se=\E[7m:so=\E[m:\
+ :is=\EP`+x~M\E\\\E[7m\E7\E[60;0;0;22p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\
+ :tc=aaa-22:
+Nb|aaa-24-rv|ambassador/24 lines+rv:\
+ :md=\E[1;7m:mr=\E[m:mb=\E[5;7m:mk=\E[7;8m:me=\E[7m:\
+ :us=\E[4;7m:ue=\E[7m:se=\E[7m:so=\E[m:\
+ :is=\EP`+x~M\E\\\E[7m\E7\E[60;0;0;24p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\
+ :tc=aaa-24:
+Nc|aaa-26-rv|ambassador/26 lines+rv:\
+ :md=\E[1;7m:mr=\E[m:mb=\E[5;7m:mk=\E[7;8m:me=\E[7m:\
+ :us=\E[4;7m:ue=\E[7m:se=\E[7m:so=\E[m:\
+ :is=\EP`+x~M\E\\\E[7m\E7\E[60;0;0;26p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\
+ :tc=aaa-26:
+Nd|aaa-28-rv|ambassador/28 lines+rv:\
+ :md=\E[1;7m:mr=\E[m:mb=\E[5;7m:mk=\E[7;8m:me=\E[7m:\
+ :us=\E[4;7m:ue=\E[7m:se=\E[7m:so=\E[m:\
+ :is=\EP`+x~M\E\\\E[7m\E7\E[60;0;0;28p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\
+ :tc=aaa-28:
+Ne|aaa-30-rv|ann arbor ambassador/30 lines in reverse video:\
+ :md=\E[1;7m:mr=\E[m:mb=\E[5;7m:mk=\E[7;8m:me=\E[7m:\
+ :us=\E[4;7m:ue=\E[7m:se=\E[7m:so=\E[m:\
+ :is=\EP`+x~M\E\\\E[7m\E7\E[60;0;0;30p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\
+ :tc=aaa-30:
+Nf|aaa-36-rv|ann arbor ambassador/36 lines in reverse video:\
+ :md=\E[1;7m:mr=\E[m:mb=\E[5;7m:mk=\E[7;8m:me=\E[7m:\
+ :us=\E[4;7m:ue=\E[7m:se=\E[7m:so=\E[m:\
+ :is=\EP`+x~M\E\\\E[7m\E7\E[60;0;0;36p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\
+ :tc=aaa-36:
+Ng|aaa-40-rv|ann arbor ambassador/40 lines in reverse video:\
+ :md=\E[1;7m:mr=\E[m:mb=\E[5;7m:mk=\E[7;8m:me=\E[7m:\
+ :us=\E[4;7m:ue=\E[7m:se=\E[7m:so=\E[m:\
+ :is=\EP`+x~M\E\\\E[7m\E7\E[60;0;0;40p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\
+ :tc=aaa-40:
+Nh|aaa-48-rv|ann arbor ambassador/48 lines in reverse video:\
+ :md=\E[1;7m:mr=\E[m:mb=\E[5;7m:mk=\E[7;8m:me=\E[7m:\
+ :us=\E[4;7m:ue=\E[7m:se=\E[7m:so=\E[m:\
+ :is=\EP`+x~M\E\\\E[7m\E7\E[60;0;0;48p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\
+ :tc=aaa-48:
+Ni|aaa-60-rv|ann arbor ambassador/60 lines in reverse video:\
+ :md=\E[1;7m:mr=\E[m:mb=\E[5;7m:mk=\E[7;8m:me=\E[7m:\
+ :us=\E[4;7m:ue=\E[7m:se=\E[7m:so=\E[m:\
+ :is=\EP`+x~M\E\\\E[7m\E7\E[60;0;0;60p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\
+ :tc=aaa-60:
+Nj|aaa-18-rv-s|aaa-18-s-rv|ambassador/18 lines+sl+rv:\
+ :md=\E[1;7m:mr=\E[m:mb=\E[5;7m:mk=\E[7;8m:me=\E[7m:\
+ :us=\E[4;7m:ue=\E[7m:se=\E[7m:so=\E[m:\
+ :ti=\E[2J\E[18;1;0;18p:te=\E[60;1;0;18p\E[17;1H\E[J:li#17:\
+ :is=\EP`+x~M\E\\\E[7m\E7\E[60;1;0;18p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\
+ :tc=aaa-unk-s:
+Nk|aaa-20-rv-s|aaa-20-s-rv|ambassador/20 lines+sl+rv:\
+ :md=\E[1;7m:mr=\E[m:mb=\E[5;7m:mk=\E[7;8m:me=\E[7m:\
+ :us=\E[4;7m:ue=\E[7m:se=\E[7m:so=\E[m:\
+ :ti=\E[2J\E[20;1;0;20p:te=\E[60;1;0;20p\E[19;1H\E[J:li#19:\
+ :is=\EP`+x~M\E\\\E[7m\E7\E[60;1;0;20p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\
+ :tc=aaa-unk-s:
+Nl|aaa-22-rv-s|aaa-22-s-rv|ambassador/22 lines+sl+rv:\
+ :md=\E[1;7m:mr=\E[m:mb=\E[5;7m:mk=\E[7;8m:me=\E[7m:\
+ :us=\E[4;7m:ue=\E[7m:se=\E[7m:so=\E[m:\
+ :ti=\E[2J\E[22;1;0;22p:te=\E[60;1;0;22p\E[21;1H\E[J:li#21:\
+ :is=\EP`+x~M\E\\\E[7m\E7\E[60;1;0;22p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\
+ :tc=aaa-unk-s:
+Nm|aaa-24-rv-s|aaa-24-s-rv|ambassador/24 lines+sl+rv:\
+ :md=\E[1;7m:mr=\E[m:mb=\E[5;7m:mk=\E[7;8m:me=\E[7m:\
+ :us=\E[4;7m:ue=\E[7m:se=\E[7m:so=\E[m:\
+ :ti=\E[2J\E[24;1;0;24p:te=\E[60;1;0;24p\E[23;1H\E[J:li#23:\
+ :is=\EP`+x~M\E\\\E[7m\E7\E[60;1;0;24p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\
+ :tc=aaa-unk-s:
+Nn|aaa-26-rv-s|aaa-26-s-rv|ambassador/26 lines+sl+rv:\
+ :md=\E[1;7m:mr=\E[m:mb=\E[5;7m:mk=\E[7;8m:me=\E[7m:\
+ :us=\E[4;7m:ue=\E[7m:se=\E[7m:so=\E[m:\
+ :ti=\E[2J\E[26;1;0;26p:te=\E[60;1;0;26p\E[25;1H\E[J:li#25:\
+ :is=\EP`+x~M\E\\\E[7m\E7\E[60;1;0;26p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\
+ :tc=aaa-unk-s:
+No|aaa-28-rv-s|aaa-28-s-rv|ambassador/28 lines+sl+rv:\
+ :md=\E[1;7m:mr=\E[m:mb=\E[5;7m:mk=\E[7;8m:me=\E[7m:\
+ :us=\E[4;7m:ue=\E[7m:se=\E[7m:so=\E[m:\
+ :ti=\E[2J\E[28;1;0;28p:te=\E[60;1;0;28p\E[27;1H\E[J:li#27:\
+ :is=\EP`+x~M\E\\\E[7m\E7\E[60;1;0;28p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\
+ :tc=aaa-unk-s:
+Np|aaa-rv|aaa-30-rv-s|aaa-30-s-rv|ambassador/30 lines+sl+rv:\
+ :md=\E[1;7m:mr=\E[m:mb=\E[5;7m:mk=\E[7;8m:me=\E[7m:\
+ :us=\E[4;7m:ue=\E[7m:se=\E[7m:so=\E[m:\
+ :ti=\E[2J\E[30;1;0;30p:te=\E[60;1;0;30p\E[29;1H\E[J:li#29:\
+ :is=\EP`+x~M\E\\\E[7m\E7\E[60;1;0;30p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\
+ :tc=aaa-unk-s:
+Nq|aaa-36-rv-s|aaa-36-s-rv|ambassador/36 lines+sl+rv:\
+ :md=\E[1;7m:mr=\E[m:mb=\E[5;7m:mk=\E[7;8m:me=\E[7m:\
+ :us=\E[4;7m:ue=\E[7m:se=\E[7m:so=\E[m:\
+ :ti=\E[2J\E[36;1;0;36p:te=\E[60;1;0;36p\E[35;1H\E[J:li#35:\
+ :is=\EP`+x~M\E\\\E[7m\E7\E[60;1;0;36p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\
+ :tc=aaa-unk-s:
+Nr|aaa-40-rv-s|aaa-40-s-rv|ambassador/40 lines+sl+rv:\
+ :md=\E[1;7m:mr=\E[m:mb=\E[5;7m:mk=\E[7;8m:me=\E[7m:\
+ :us=\E[4;7m:ue=\E[7m:se=\E[7m:so=\E[m:\
+ :ti=\E[2J\E[40;1;0;40p:te=\E[60;1;0;40p\E[39;1H\E[J:li#39:\
+ :is=\EP`+x~M\E\\\E[7m\E7\E[60;1;0;40p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\
+ :tc=aaa-unk-s:
+Ns|aaa-48-rv-s|aaa-48-s-rv|ambassador/48 lines+sl+rv:\
+ :md=\E[1;7m:mr=\E[m:mb=\E[5;7m:mk=\E[7;8m:me=\E[7m:\
+ :us=\E[4;7m:ue=\E[7m:se=\E[7m:so=\E[m:\
+ :ti=\E[2J\E[48;1;0;48p:te=\E[60;1;0;48p\E[47;1H\E[J:li#47:\
+ :is=\EP`+x~M\E\\\E[7m\E7\E[60;1;0;48p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\
+ :tc=aaa-unk-s:
+Nt|aaa-60-rv-s|aaa-60-s-rv|ambassador/60 lines+sl+rv:\
+ :md=\E[1;7m:mr=\E[m:mb=\E[5;7m:mk=\E[7;8m:me=\E[7m:\
+ :us=\E[4;7m:ue=\E[7m:se=\E[7m:so=\E[m:\
+ :ti=\E[2J\E[60;1;0;60p:te=\E[60;1;0;60p\E[59;1H\E[J:li#59:\
+ :is=\EP`+x~M\E\\\E[7m\E7\E[60;1;0;60p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\
+ :tc=aaa-unk-s:
+NL|aaa-24-ctxt|ann arbor ambassador/24 lines:\
+ :ti=\E[30;1H\E[K\E[24;0;0;24p:te=\E[60;1;0;24p\E[60;1H\E[K:tc=aaa-24:
+NL|aaa-24-rv-ctxt|ambassador/24+rv:\
+ :ti=\E[30;1H\E[K\E[24;0;0;24p:te=\E[60;1;0;24p\E[60;1H\E[K:tc=aaa-24-rv:
+NL|aaa-s-ctxt|aaa-30-s-ctxt|hairy aaa:\
+ :ti=\E[30;1H\E[K\E[30;1;0;30p:te=\E[60;1;0;30p\E[59;1H\E[K:tc=aaa-30-s:
+NL|aaa-s-rv-ctxt|aaa-30-s-rv-ctxt|hairy aaa:\
+ :md=\E[1;7m:mr=\E[m:mb=\E[5;7m:mk=\E[7;8m:me=\E[7m:\
+ :us=\E[4;7m:ue=\E[7m:se=\E[7m:so=\E[m:\
+ :is=\EP`+x~M\E\\\E[7m\E7\E[60;1;0;30p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\
+ :ti=\E[30;1H\E[K\E[30;1;0;30p:te=\E[60;1;0;30p\E[59;1H\E[K:\
+ :li#29:tc=aaa-unk-s:
+NH|aaa-ctxt|aaa-30-ctxt|ann arbor ambassador/30 lines:\
+ :ti=\E[30;0;0;30p:te=\E[60;0;0;30p\E[60;1H\E[K:tc=aaa-30:
+NH|aaa-rv-ctxt|aaa-30-rv-ctxt|ann arbor ambassador/30 lines:\
+ :ti=\E[30;0;0;30p:te=\E[60;0;0;30p\E[60;1H\E[K:\
+ :md=\E[1;7m:mr=\E[m:mb=\E[5;7m:mk=\E[7;8m:me=\E[7m:\
+ :us=\E[4;7m:ue=\E[7m:se=\E[7m:so=\E[m:\
+ :is=\EP`+x~M\E\\\E[7m\E7\E[60;0;0;30p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\
+ :li#30:tc=aaa-unk:
+Nd|aaa-db|ann arbor ambassador 30/destructive backspace:\
+ :ti=\E[H\E[J\E[30;0;0;30p:te=\E7\E[60;0;0;30p\E8:li#30:\
+ :is=\E[60;0;0;30p\E[H\E[J\E[1Q\E[m\E[20l\E[>30h:le=\E[D:bc=\E[D:bs@:\
+ :tc=aaa-unk:
+N1|aa|annarbor|4080|ann arbor 4080:\
+ :do=^J:pt:ct=^\^P^P:st=^]^P1:cm=^O%r%\066%.%>^S^L%+@:\
+ :co#80:li#40:le=^H:bs:cl=2^L:up=^N:nd=^_:ho=^K:am:\
+ :kb=^^:kd=^J:ku=^N:kl=^H:kr=^_:kh=^K:ma=^_ ^N^P:
+# # --------------------------------
+#
+# T: TELETYPE
+#
+# We need descriptions for the model 40. There are known to be at least three
+# flavors of the 40, both seem more like IBM half duplex forms fillers than
+# ASCII terminals. They have lots of awful braindamage, such as printing
+# a visible newline indicator after each newline. The 40-1 is a half duplex
+# terminal and is hopeless. The 40-2 is braindamaged but has hope and is
+# described here. The 40-4 is a 3270 lookalike and beyond hope.
+# The terminal has visible bell but I don't know it - it's
+# null here to prevent it from showing the BL character.
+# There is an \EG in nl because of a bug in vi (if stty says you have
+# a "newline" style terminal (-crmode) vi figures all it needs is nl
+# to get crlf, even if cr is not ^M.)
+T0|40|tty40|ds40|ds40/2|ds40-2|dataspeed40|teletype dataspeed 40/2:\
+ :cl=160\ER:cd=160\EJ:al=160\EL:dl=160\EM:dc=50\EP:im=:ei=:ic=50\E\^:\
+ :nd=\EC:up=\E7:bs:cr=\EG:nl=\EG\EB:do=\EB:co#80:li#24:vb=:\
+ :so=\E3:se=\E4:
+T3|33|tty33|tty|model 33 teletype:\
+ :do=^J:co#72:hc:os:
+T4|43|tty43|model 43 teletype:\
+ :do=^J:kb=^h:am:le=^H:bs:hc:os:co#132:
+T7|37|tty37|model 37 teletype:\
+ :do=^J:le=^H:bs:hc:hu=\E8:hd=\E9:up=\E7:os:
+# From jwb Wed Mar 31 13:25:09 1982 remote from ihuxp
+# This entry appears to avoid the top line - I have no idea why.
+TT|4424|tty4424|teletype 4424M:\
+ :al=\EL:da:db:ip=2:im=:ei=:ic=\E\^:dc=\EP:dl=\EM:\
+ :co#80:li#23:am:cl=\E[2;H\E[J:bs:cm=\E[%i%2;%2H\E[B:\
+ :nd=\E[C:up=\E[A:pt:mi:sr=\ET:\
+ :ce=\E[K:so=\E[7m:se=\E[m:us=\E[4m:ue=\E[m:\
+ :is=\E[m\E[2;24r:\
+ :kd=\E[B:kl=\E[D:ku=\E[A:kr=\E[C:\
+ :kh=\E[H:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:
+# Teletype blit.
+# # --------------------------------
+#
+# V: VISUAL
+#
+# The Visual 200 beeps when you type a character in insert mode.
+# This is a horribly obnoxious misfeature, and some of the entries
+# below try to get around the problem by ignoring the feature or
+# turning it off when inputting a character. They are said not to
+# work well at 300 baud. (You could always cut the wire to the bell!)
+#From mike@brl-vgr Mon Nov 14 08:34:29 1983
+V2|vi200|vis200|visual 200 with function keys:\
+ :so=\E4:se=\E3:ms:do=^J:\
+ :al=\EL:am:le=^H:bs:cd=\Ey:ce=\Ex:cl=\Ev:\
+ :cm=\EY%+ %+ :co#80:dc=\EO:dl=\EM:ho=\EH:\
+ :im=:ei=:ic=\Ei \b\Ej:\
+ :is=\E3\Eb\Ej\E\\\El\EG\Ec\Ek:\
+ :k0=\EP:k1=\EQ:k2=\ER:k3=\E :k4=\E!:k5=\E":k6=\E#:\
+ :k7=\E$:k8=\E%:k9=\E&:kl=\ED:kr=\EC:ku=\EA:kd=\EB:kh=\EH:\
+ :li#24:nd=\EC:pt:sr=\EI:up=\EA:vs=\Ed:ve=\Ec:
+VR|vi200-rv-ic|visual 200 reverse video using insert char:\
+ :ei=\Ej:im=\Ei:ic@:tc=vi200-rv:
+# The older Visuals didn't come with function keys. This entry uses
+# ks and ke so that the keypad keys can be used as function keys.
+# If your version of vi doesn't support function keys you may want
+# to use V2.
+Vf|vi200-f|visual|visual 200 no function keys:\
+ :do=^J:al=\EL:am:le=^H:bs:cd=\Ey:ce=4*\Ex:cl=\Ev:\
+ :cm=\EY%+ %+ :co#80:dc=4*\EO:dl=4*\EM:ho=\EH:\
+ :im=:ei=:ic=\Ei \b\Ej:\
+ :is=\E3\Eb\Ej\E\\\El\EG\Ed\Ek:ks=\E=:ke=\E>:\
+ :k0=\E?p:k1=\E?q:k2=\E?r:k3=\E?s:k4=\E?t:k5=\E?u:k6=\E?v:\
+ :k7=\E?w:k8=\E?x:k9=\E?y:kl=\ED:kr=\EC:ku=\EA:kd=\EB:kh=\EH:\
+ :li#24:nd=\EC:pt:sr=\EI:up=\EA:vs=\Ed:ve=\Ec:
+Vr|vi200-rv|visual 200 reverse video:\
+ :so=\E4:se=\E3:sr@:vs@:ve@:tc=vi200:
+Vt|vi200-ic|visual 200 using insert char:\
+ :ei=\Ej:im=\Ei:ic@:tc=vi200:
+# From: jbs@athena.mit.edu Jeff Siegal
+V5|vi55|Visual 55:\
+ :im=\Ea:ei=\Eb:mi:dc=\Ew:dm=:ed=:al=\EL:dl=\EM:cs=\E_%+A%+A:\
+ :ho=\EH:cl=\Ev:is=\Ev\E_AX\Eb\EW\E9P\ET:so=\EU:se=\ET:ms:\
+ :do=^J:le=^H:bs:cd=\EJ:ce=\EK:cm=\EY%+ %+ :co#80:li#24:\
+ :nd=\EC:pt:sr=\EI:up=\EA:ku=\EA:kd=\EB:kr=\EC:kl=\ED:kb=^H:
+# # --------------------------------
+#
+# X: TEKTRONIX
+#
+Xa|tek|tek4012|4012|tektronix 4012:\
+ :do=^J:is=\E^O:le=^H:bs:cl=1000\E^L:co#75:ns:li#35:os:
+Xb|tek4013|4013|tektronix 4013:\
+ :as=\E^N:ae=\E^O:dF#1000:tc=4012:
+Xc|tek4014|4014|tektronix 4014:\
+ :is=\E^O\E9:co#81:li#38:dF#1000:tc=tek4012:
+Xd|tek4015|4015|tektronix 4015:\
+ :as=\E^N:ae=\E^O:tc=4014:
+Xe|tek4014-sm|4014-sm|tektronix 4014 in small font:\
+ :is=\E^O\E\072:co#121:li#58:tc=tek4014:
+Xf|tek4015-sm|4015-sm|tektronix 4015 in small font:\
+ :as=\E^N:ae=\E^O:tc=4014sm:
+# I think the 1000UP is supposed to be so expensive it never happens.
+X4|tek4023|4023|tex|tektronix 4023:\
+ :do=^J:so=^_P:se=^_@:cm=\034%r%+ %+ :nd=\t:le=^H:\
+ :bs:cl=4\E^L:co#80:li#24:am:up=1000UP:vt#4:
+# Can't use cursor motion because it's memory relative, and because
+# it only works in the workspace, not the monitor. Same for home.
+# Likewise, standout only works in the workspace.
+# 145 ms padding on al and AL taken out since it doesn't seem to be needed much.
+X5|4025|4027|4024|tek4025|tek4027|tek4024|4025cu|4027cu|tektronix 4024/4025/4027:\
+ :sf=^F^J:do=^F^J:is=\41com 31\r\n^_sto 9 17 25 33 41 49 57 65 73\r:\
+ :ks=^_lea p4 /h/\r^_lea p8 /k/\r^_lea p6 / /\r^_lea p2 /j/\r^_lea f5 /H/\r^_lea p5 /H/\r:\
+ :ke=^_lea p2\r^_lea p4\r^_lea p6\r^_lea p8\r^_lea p5\r^_lea f5\r:\
+ :am:le=^H:bs:da:db:pt:li#34:co#80:cl=^_era\r\n\n:up=^K:nd=^_rig\r:\
+ :al=^_up\r^_ili\r:dl=^_dli\r^F:\
+ :dc=^_dch\r:im=^_ich\r:ei=^F^_dow\r^K:nl=^F\n:\
+ :cd=^_dli 50\r:CC=^_:AL=^_up\r^_ili %d\r:DL=^_dli %d\r^F:\
+ :UP=^_up %d\r:DO=^_dow %d\r:LE=^_lef %d\r:RI=^_rig %d\r:
+X7|4025-17|4027-17|tek 4025 17 line window:\
+ :li#17:tc=4025:
+X8|4025-17ws|4027-17ws|tek 4025 17 line window in workspace:\
+ :is=\41com 31\r\n^_sto 9,17,25,33,41,49,57,65,73\r^_wor 17\r^_mon 17\r:\
+ :ti=^_wor h\r:te=^_mon h\r:so=^_att e\r:se=^_att s\r:tc=4025-17:
+X9|4025ex|4027ex|tek 4025 w/!:\
+ :ti=\41com 31\r:te=^_com 33\r:\
+ :is=^_com 33\r\n\41sto 9,17,25,33,41,49,57,65,73\r:tc=4025:
+# From jcoker @ ucbic
+Xp|4107|tek4107|Tektronix 4107 graphics terminal with memory:\
+ :ti=\E[?6l\E[H\E[J:te=\E[?6h\E%!0\ELBP0\E%!1\E[32;1f:\
+ :is=\E%!0\ELBP0\E%!1\E[H\E[2g\EH\E[8C\EH\E[8C\EH\E[8C\EH\E[8C\EH\E[8C\EH\E[8C\EH\E[8C\EH\E[8C\EH\E[8C\EH\E[J:\
+ :li#32:do=^J:al=3\E[L:xn:am:le=^H:bs:cd=\E[J:\
+ :ce=5\E[K:cl=156\E[H\E[J:cm=\E[%i%d;%dH:co#80:dc=4\E[P:dl=3\E[M:\
+ :ho=\E[H:ic=4\E[@:md=\E[1m:mr=\E[7m:mb=\E[5m:me=\E[m:ku=\EM:\
+ :kd=\ED:kl=\E[D:kr=\E[C:kh=\E[H:\
+ :ul:ei=:im=:pt:bw:bt=\E[Z:mi:nd=\E[C:se=\E[m:so=\E[7m:\
+ :ue=\E[m:us=\E[4m:up=\EM:
+# Tektronix 4107 with sysline
+Xq|4107-s|tek4107-s|Tektronix 4107 with sysline but no memory:\
+ :is=\E%!1\E[2;32r\E[132D\E[2g\EH\E[8C\EH\E[8C\EH\E[8C\EH\E[8C\EH\E[8C\EH\E[8C\EH\E[8C\EH\E[8C\EH\E[8C\EH\E[J:\
+ :es:hs:i2=\E7\E[?6l\E[2K\E[?6h\E8:ts=\E7\E[?6l\E[2K\E[;%i%df:\
+ :fs=\E[?6h\E8:ds=\E7\E[?6l\E[2K\E[?6h\E8:tc=4107:
+# From cbosg!teklabs!davem Wed Sep 16 21:11:41 1981
+# Here's the comamnd file that I use to get rogue to work on the 4025.
+# It should work with any program using the old curses (e.g. it better
+# not try to scroll, or cursor addressing won't work. Also, you can't
+# see the cursor.)
+# (This "learns" the arrow keys for rogue. I have adapted it for termcap - mrh)
+Xr|4025-cr|tek 4025 for curses and rogue:\
+ :is=\41com 31\r\n^_sto 9 17 25 33 41 49 57 65 73\r:\
+ :am:le=^H:bs:pt:li#33:co#80:cm=^_jum%i%d,%d;:up=^K:\
+ :do=^F^J:cl=^_era;:nd=^_rig;:nl=^F\n:ti=^_wor 33h:te=^_wor 0:
+# next two lines commented out since curses only allows 128 chars, sigh.
+# :ti=^_lea p1/b/^_lea p2/j/^_lea p3/n/^_lea p4/h/^_lea p5/ /^_lea p6/l/^_lea p7/y/^_lea p8/k/^_lea p9/u/^_lea p./f/^_lea pt/`era w/13^_lea p0/s/^_wor 33h:\
+# :te=^_lea p1^_lea p2^_lea p3^_lea p4^_lea pt^_lea p5^_lea p6^_lea p7^_lea p8^_lea p9/la/13^_lea p.^_lea p0^_wor 0:
+# The 4110 series may be a wonderful graphics series, but they make the 4025
+# look good for screen editing. In the dialog area, you can't move the cursor
+# off the bottom line. Out of the dialog area, ^K moves it up, but there
+# is no way to scroll.
+Xs|4112|4114|tek4112|tektronix 4110 series:\
+ :is=\E3!1:li#34:co#80:am:al=\E[L:bs:bt=\E[Z:\
+ :cd=\E[0J:ce=\E[0K:cl=\E[2J\E[0;0H:cm=\E[%i%d;%dH:\
+ :db:dc=\E[P:dl=\E[M:ic=\E[@:im=:nd=\E[C:se=\E[m:\
+ :so=\E[7m:ue=\E[m:up=\EM:us=\E[4m:vs=:ve=:\
+ :sr=\E7\E[0;0H\E[L\E8:sf=\E7\E[0;0H\E[M\E8:
+Xt|4112-nd|4112 not in dialog area:up=^K:ns:tc=4112:
+Xu|4112-5|4112 in 5 line dialog area:li#5:tc=4112:
+Xv|4113|tek4113|tektronix 4113 color graphics, 5 line dialog area:\
+ :le=^H:do=^J:eo:da:bs:am:li#5:co#80:is=\EKA1\ELL5\ELV0\ELV1:\
+ :vb=\ERBA4\ERBA4\ERBA4\ERBA4\ERBA4\ERBA4\ERBA4\ERBA4\ERBA4\ERBA4\ERB0:\
+ :cl=\ELZ:uc=^H\ELM1_\ELM0:nd=\LM1 \LM0:\
+ :.as=\E^N:.ae=\E^O:
+Xw|4113-34|tek4113-34|tektronix 4113 color graphics, 34 line dialog area:\
+ :is=\EKA1\ELLB2\ELV0\ELV1:li#34:tc=tek4113:
+# ns hidden from vi to allow visual mode. APL font (as, ae) not supported here.
+# uc is slow, but looks nice. Suggest setenv MORE -up . vb needs enough delay
+# to let you see the background color being toggled.
+Xy|4113-nd|tek4113-nd|tektronix 4113 color graphics, no dialog area:\
+ :le=^H:do=^J:nd=\t:up=^K:ll=\ELF hl @:ho=\ELF7l\177 @:\
+ :eo:bs:am:li#34:co#80:is=\ELZ\EKA0\ELF7l\177 @:vs=\ELZ\EKA0:\
+ :vb=\ERBA4\ERBA4\ERBA4\ERBA4\ERBA4\ERBA4\ERBA4\ERBA4\ERBA4\ERBA4\ERB0:\
+ :cl=\E\f:uc=^H\EMG1_\EMG0:so=\EMT2:se=\EMT1:\
+ :.ns:.as=\E^N:.ae=\E^O:
+Xz|4105|tek4105:\
+ :al=\E[1L:am:bs:cd=\E[J:ce=\E[K:cl=\E[2J\E[H:cm=\E[%i%2;%2H:co#80:\
+ :dc=\E[1P:dl=\E[1M:dn=\E[1B:ho=\E[H:im=\E[4h:li#30:mi:nd=\E[1C:\
+ :as=\E[1m:ae=\E[0m:ms:pt:se=\E[0m:so=\E[7m:up=\E[1A:kb=^h:ku=\E[1A:\
+ :kd=\E[1B:kl=\E[1D:kr=\E[1C:ul:us=\E[4m:ue=\E[0m:is=\E%!1\E[?6l\E[0m:\
+ :mr=\E[<3m:md=\E[<4m:mh=\E[<6m:mb=\E[<7m:me=\E[<1m:ti=\E%!1\E[?6l:xt:
+# This entry is from Tek. Inc. (Brian Biehl)
+Xz|4115|tek4115|Tektronix 4115:\
+ :co#80:li#34:\
+ :al=\E[L:am:bc=\E[D:bs:bt=\E[Z:cd=\E[J:ce=\E[K:\
+ :cl=\E[;H\E[2J:cm=\E[%i%d;%dH:da:db:dc=\E[P:dl=\E[M:do=\E[B:\
+ :ei=\E[4l:eo:ho=\E[;H:im=\E[4h:if=/usr/lib/tabset/vt100:\
+ :is=\E%\0410\E%\014\ELV0\EKA1\ELBB2\ENU@\075\ELLB2\ELM0\ELV1\EKYA?\E%\0411\E[<1l\E[?7h\E[?8h\E[34;1H\E[34B\E[0m:\
+ :kb=^H:ke=\E>:ks=\E=:nd=\E[C:pt:se=\E[m:so=\E[7m:sr=\EM:\
+ :te=\E%\0410\ELBG8\E%\0411\E[34;1H\E[J:
+ :ti=\E%\0410\ELBB2\E%\0411:\
+ :ue=\E[m:up=\E[A:us=\E[4m:\
+ :ve=\E%\0410\ELBG8\E%\0411\E[34;1H:\
+ :vs=\E%\0410\ELBB2\E%\0411:
+# The tek4125 emulates a vt100 incorrectly - the scrolling region
+# command is ignored. The following entry replaces the cs with the
+# needed al, dl, and im; removes some cursor pad commands that the tek4125
+# chokes on; and adds a lot of initialization for the tek dialog area.
+# Note that this entry uses all 34 lines and sets the cursor color to green
+# Steve Jacobson 8/85
+XB|tek4125:\
+ :ks=\E=:li#34:\
+ :is=\EQD1\EUX03\E%\!0\EKA\ELBB2\ELCE0\ELI100\ELJ2\ELLB2\ELM0\ELS1\ELX00\ELV1\E%\!1\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h:dl=\E[1M:\
+ :al=\E[1L:cs@:sc@:rc@:im=\E1:tc=vt100:
+# From carolyn@dali.berkeley.edu Thu Oct 31 12:54:27 1985
+XA|4404|tek4404:\
+ :al=\E[1L:bs:cd=\E[J:ce=\E[K:cl=\E[;H\E[2J:cm=\E[%i%d;%dH:co#80:\
+ :cs=\E[%i%d;%dr:dc=\E[P:dl=\E[1M:do=^J:ei=\E[4l:ho=\E[H:im=\E[4h:\
+ :kd=\E[B:ke=\E[?1h:kl=\E[D:kr=\E[C:ks=\E[?1l:ku=\E[A:li#32::mb=\E[5m:\
+ :md=\E[1m:me=\E[m:nd=\E[C:pt:rc=\E8:sc=\E7:se=\E[27m:so=\E[7m:\
+ :ta=\E[2I:ti=\E%\!1\E[1;32r\E[?6l\E>:te=\E[1;1H\E[0J\E[?6h\E[?1l:\
+ :ue=\E[m:up=\E[A:us=\E[4m:
+# # --------------------------------
+#
+# a: ADDS
+#
+# Regent: lowest common denominator, works on all regents.
+a0|regent|Adds Regent Series:li#24:co#80:am:cl=^L:ll=^A:up=^Z:\
+ :bs:bc=^U:nd=^F:do=^J:ho=\EY :
+# Regent 100 has a bug where if computer sends escape when user is holding
+# down shift key it gets confused, so we avoid escape.
+a1|regent100|Adds Regent 100:k0=^B1^M:k1=^B2^M:k2=^B3^M:k3=^B4^M:\
+ :k4=^B5^M:k5=^B6^M:k6=^B7^M:k7=^B8^M:\
+ :l0=F1:l1=F2:l2=F3:l3=F4:l4=F5:l5=F6:l6=F7:l7=F8:\
+ :so=\E0P:ue=\E0@:us=\E0`:se=\E0@:\
+ :cm=^K%+ %B^P%.:ug#1:sg#1:tc=regent:
+a2|regent20|Adds Regent 20:cd=\Ek:ce=\EK:cm=\EY%+ %+ :tc=regent:
+a3|regent25|Adds Regent 25:kh=^A:kl=^U:kr=^F:ku=^Z:kd=^J:tc=regent20:
+a4|regent40|Adds Regent 40:k0=^B1^M:k1=^B2^M:k2=^B3^M:k3=^B4^M:\
+ :k4=^B5^M:k5=^B6^M:k6=^B7^M:k7=^B8^M:\
+ :l0=F1:l1=F2:l2=F3:l3=F4:l4=F5:l5=F6:l6=F7:l7=F8:\
+ :al=2*\EM:dl=2*\El:\
+ :so=\E0P:ue=\E0@:us=\E0`:se=\E0@:ug#1:sg#1:tc=regent25:
+a5|regent40+|Adds Regent 40+:is=\EB:tc=regent40:
+a6|regent60|regent200|Adds Regent 60:se=\ER\E0@\EV:so=\ER\E0P\EV:dc=\EE:ei=\EF:\
+ :im=\EF:is=\EV\EB:ko=dc,im,ei:tc=regent40+:
+a7|regent60na|regent 60 w/no arrow keys:\
+ kl@:kr@:ku@:kd@:tc=regent60:
+# Note: if return acts weird on a980, check internal switch #2
+# on the top chip on the CONTROL pc board.
+ac|a980|adds consul 980:\
+ :do=^J:al=13\E^N:am:le=^H:bs:cl=^L\200^K@:cm=^K%+@\E^E%2:co#80:\
+ :dl=13\E^O:k0=\E0:k1=\E1:k2=\E2:k3=\E3:k4=\E4:k5=\E5:k6=\E6:k7=\E7:\
+ :k8=\E8:k9=\E9:li#24:nd=\E^E01:so=^Y^^^N:se=^O:up=9:
+as|viewpt60|viewpoint60|addsviewpoint60|adds viewpoint60:\
+ :tc=regent40:
+# From Onyx:edward Thu Jul 9 09:27:33 1981
+av|viewpoint|addsviewpoint|adds viewpoint:\
+ :do=^J:am:le=^H:bs:li#24:co#80:cm=\EY%+ %+ :cd=\Ek:ce=\EK:\
+ :up=^Z:cl=^L:ll=^A:kl=^U:kd=^J:ku=^Z:kh=^A:\
+ :so=^N:se=^O:us=^N:ue=^O:is=^O\E0`:vs=^O\E0P:ve=^O\E0`:
+# # --------------------------------
+#
+# b: BEEHIVE
+#
+# Reports are that most of these Beehive entries (except superbee) have not been
+# tested and do not work right. se is a trouble spot. Be warned.
+b2|sb2|sb3|fixed superbee:\
+ :xb@:tc=superbee:
+# set tab is ^F, clear (one) tab is ^V, no way to clear all tabs.
+# good grief - does this entry make sg/ug when it doesn't have to?
+# look at those spaces in se/so. Seems strange to me...
+bh|bh3m|beehiveIIIm:\
+ :if=/usr/lib/tabset/beehive:do=^J:\
+ :al=160^S:am:le=^H:bs:cd=^R:ce=^P:cl=^E^R:\
+ :co#80:dl=350^Q:ho=^E:li#20:ll=^E^K:\
+ :nd=^L:pt:se= ^_:so=^] :up=^K:
+# This loses on lines > 80 chars long, use at your own risk
+bi|superbeeic|super bee with insert char:\
+ :ic=:im=\EQ:ei=\ER:tc=superbee:
+bm|microb|microbee|micro bee series:\
+ :do=^J:am:le=^H:bs:cd=\EJ:ce=\EK:cl=\EE:co#80:cm=\EF%+ %+ :\
+ :k1=\Ep:k2=\Eq:k3=\Er:k4=\Es:k5=\Et:k6=\Eu:k7=\Ev:k8=\Ew:k9=\Ex:\
+ :kd=\EB:kh=\EH:kl=\ED:kr=\EC:ku=\EA:\
+ :li#24:nd=\EC:pt:se=\Ed@ :so= \EdP:ue=\Ed@:up=\EA:us=\Ed`:
+# Superbee - f1=escape, f2=^C.
+# Note: there are at least 3 kinds of superbees in the world. The sb1
+# holds onto escapes and botches ^C's. The sb2 is the best of the 3.
+# The sb3 puts garbage on the bottom of the screen when you scroll with
+# the switch in the back set to CRLF instead of AEP. This description
+# is tested on the sb2 but should work on all with either switch setting.
+# The f1/f2 business is for the sb1 and the :xb: can be taken out for
+# the other two if you want to try to hit that tiny escape key.
+# This description is tricky: being able to use cm depends on there being
+# 2048 bytes of memory and the hairy nl string.
+bs|sb1|superbee|superb|beehive super bee:\
+ :ct=\E3:st=\E1:is=\EH\EJ:do=^J:\
+ :sf=\n\200\200\200\n\200\200\200\EA\EK\200\200\200\ET\ET:\
+ :am:le=^H:bs:cd=3\EJ:ce=3\EK:cl=3\EH\EJ:co#80:cm=\EF%r%3%3:cr=1000\r:\
+ :dC#10:da:db:xb:dc=3\EP:dl=100\EM:so=\E_1:se=\E_3:\
+ :li#25:nl=\n\200\200\200\n\200\200\200\EA\EK\200\200\200\ET\ET:\
+ :nd=\EC:pt:up=\EA:ho=\EH:ve=\n:\
+ :k1=\Ep:k2=\Eq:k3=\Er:k4=\Es:k5=\Et:k6=\Eu:k7=\Ev:k8=\Ew:\
+ :kd=\EB:kh=\EH:kl=\ED:kr=\EC:ku=\EA:
+# # --------------------------------
+#
+# c: CONCEPT (HUMAN DESIGNED SYSTEMS)
+#
+# From vax135!hpk Sat Jun 27 07:41:20 1981
+# Extensive changes to c108 by arpavax:eric Feb 1982
+#
+# There seem to be a number of different versions of the C108 PROMS
+# (with bug fixes in its Z-80 program).
+# The first one that we had would lock out the keyboard of you
+# sent lots of short lines (like /usr/dict/words) at 9600 baud.
+# Try that on your C108 and see if it sends a ^S when you type it.
+# If so, you have an old version of the PROMs.
+# The old one also messed up running vi with a 132-character line-length.
+# You should configure the C108 to send ^S/^Q before running this.
+# It is much faster (at 9600 baud) than the c100 because the delays
+# are not fixed.
+# new status line display entries for c108:
+# hs - has status capability
+# es - escape sequences are OK on status line
+# i2 - second init str - setup term for status display - set programmer mode,
+# select window 2, define window at last line of memory,
+# set bkgnd stat mesg there, select window 0.
+# ts - to status line - select window 2, home cursor, erase to end-of-window,
+# 1/2 bright on, goto(line#0, col#?)
+# fs - from status line - 1/2 bright off, select window 0
+# ds - disable status display - set bkgnd status mesg with illegal window #
+#
+# the following two entries are for emacs -- they are just like the regular
+# entries except that they have buffer overflow control OFF
+c0|e108-8p:\
+ :i2=\EU\E z"\Ev^A\177 !p\E ;"\E z \Ev ^A\177p\Ep\n:\
+ :te=\Ev ^A\177p\Ep\r\n:tc=e108-4p:
+c1|e108-4p:\
+ :is=\EU\E f\Ef\E7\E5\E8\El\ENH\EK\E\200\Eo&\200\Eo\47\E\E!\E^G!\E^HA@ :\
+ :tc=c108-4p:
+c6|c108-na|c108-na-8p|concept108-na-8p|concept 108 w/8 pages, no arrows:\
+ :ks@:ke@:k7=\E;:k8=\E<:k9=\E=:tc=c108-8p
+c7|c108-rv-na|c108-rv-na-8p|concept 108 w/8 pages, no arrows in rev video:\
+ :ts=\E z"\E?\E^C\EE\Ea %+ :fs=\Ee\E z :\
+ :ks@:ke@:k7=\E;:k8=\E<:k9=\E=:tc=c108-rv8p
+# this needs new frotz in the cm capability for 2-char addrs when > 95....
+c8|c108-w|c108-w-8p|concept108-w-8p|concept 108 w/8 pages in wide mode:\
+ :is=\EU\E F\Ef\E7\E5\E8\El\ENH\EK\E\200\Eo&\200\Eo\47\E\E"\E^G!\E^HA@ :\
+ :ti=\EU\Ev 8^AD\Ep\r:te=\Ev ^A0^AD\Ep\r\n:pt@:cm@:\
+ :co#132:tc=c108-8p
+cA|avt-w|avtw|HDS concept avt w/4 or 8 pages; 132 columns:\
+ :is=\E[1*q\E[2!t\E[7!t\E[=4;101;119l\E[=103;107;118;207h\E)1\E[1Q\EW\E[7!y\E[0\0720\07232!r\E[w\E2\r\n:\
+ :ch=\E[%i%3G:cm=\E[%i%2;%3H:co#132:tc=avt:
+#
+# Concepts have only window relative cursor addressing, not screen relative.
+# To get it to work right here, ti/te (which were invented for the concept)
+# lock you into a one page window for screen style programs. To get out of
+# the one page window, we use a clever trick: we set the window size to zero
+# ("\Ev " in te) which the terminal recognizes as an error and resets the
+# window to all of memory.
+#
+# Some tty drivers use cr3 for concept, others use nl3, hence dN/dC below.
+# This padding is only needed at 9600 baud.
+# 2 nulls padding on te isn't always enough. 6 works fine. Maybe less
+# than 6 but more than 2 will work.
+cc|c100-rv-na|c100-rv-4p-na|concept100-rv-na|c100rv4pna|c100 with no arrows:\
+ :ks@:ke@:tc=c100-rv:
+# This is useful at 1200 baud.
+ce|c100-s|concept-s|concept100-s|slow concept 100:\
+ :vb=\Ek\200\EK:pt:dC@:dN@:tc=c100:
+cf|c100-rv-s|concept-rv-s|concept100-rv-s|c100rvs|slow reverse concept 100:\
+ :vb=\EK\200\Ek:pt:dC@:dN@:tc=c100-rv:
+# # --------------------------------
+#
+# d: DEC (DIGITAL EQUIPMENT CORPORATION)
+#
+# Note that xn glitch in vt100 is not quite the same as concept, since
+# the cursor is left in a different position while in the weird state
+# (concept at beginning of next line, vt100 at end of this line) so
+# all versions of vi before 3.7 don't handle xn right on vt100.
+# I assume you have smooth scroll off or are at a slow enough baud
+# rate that it doesn't matter (1200? or less). Also this assumes
+# that you set auto-nl to "on", if you set it off use vt100-nam below.
+#
+# Since there are two things here called vt100, the installer can make
+# a local decision to make either one standard "vt100" by including
+# it in the list of terminals in reorder, since the first vt100 in
+# /etc/termcap is the one that it will find. The choice is between
+# nam (no automatic margins) and am (automatic margins), as determined
+# by the wrapline switch (group 3 #2). I presonally recommend turning
+# on the bit and using vt100-am, since having stuff hammer on the right
+# margin is sort of hard to read. However, the xn glitch does not occur
+# if you turn the bit off.
+#
+# I am unsure about the padding requirements listed here. I have heard
+# a claim that the vt100 needs no padding. It's possible that it needs
+# padding only if the xon/xoff switch is off. For UNIX, this switch
+# should probably be on.
+#
+# The vt100 uses rs and rf rather than is/ct/st because the tab settings
+# are in non-volatile memory and don't need to be reset upon login.
+# You can type "reset" to get them set.
+dp|vt100-np|vt100 with no padding (for psl games):\
+ :cl=\E[H\E[2J:sr=\EM:cm=\E[%i%d;%dH:nd=\E[C:up=\E[A:\
+ :ce=\E[K:cd=\E[J:so=\E[7m:se=\E[m:us=\E[4m:ue=\E[m:\
+ :md=\E[1m:mr=\E[7m:mb=\E[5m:me=\E[m:tc=vt100:
+d1|vt100-nam|vt100nam|vt100 w/no am:\
+ :am@:xn@:\
+ :is=\E>\E[?3l\E[?4l\E[?5l\E[?7l\E[?8h:ks=\E[?1h\E=:ke=\E[?1l\E>:\
+ :tc=vt100-am:
+d2|gt42|dec gt42:\
+ :do=^J:le=^H:bs:co#72:ns:li#40:os:
+d3|vt132|vt132:\
+ :al=99\E[L:dl=99\E[M:ip=7:dc=7\E[P:ei=\E[4l:im=\E[4h:xn:dN#30:tc=vt100:
+d4|gt40|dec gt40:\
+ :do=^J:le=^H:bs:co#72:ns:li#30:os:
+d5|vt50|dec vt50:\
+ :do=^J:le=^H:bs:cd=\EJ:ce=\EK:cl=\EH\EJ:co#80:li#12:nd=\EC:pt:up=\EA:
+d6|vt125|vt125-am|DEC vt125:\
+ :xn:do=^J:co#80:li#24:cl=50\E[H\E[2J:\
+ :le=^H:am:bs:cm=5\E[%i%d;%dH:nd=2\E[C:up=2\E[A:ce=3\E[K:cd=50\E[J:\
+ :so=2\E[7m:se=2\E[m:us=2\E[4m:ue=2\E[m:md=2\E[1m:mr=2\E[7m:mb=2\E[5m:\
+ :me=2\E[m:is=\E[1;24r\E[24;1H\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h:\
+ :ks=\E[?1h\E=:ke=\E[?1l\E>:if=/usr/lib/tabset/vt100:ku=\EOA:kd=\EOB:\
+ :kr=\EOC:kl=\EOD:kb=^H:ho=\E[H:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:\
+ :pt:sr=5\EM:vt#3:sc=\E7:rc=\E8:cs=\E[%i%d;%dr:
+d9|vt125-nam|DEC vt125 no automatic margin:\
+ :am@:tc=vt125-am:
+# DEC gigi color graphic terminal , same as vt52
+d7|gigi|dec gigi terminal:\
+ :co#80:is=200\E>\E[?4l\E[?5l\E[?7h\E[?8h:\
+ :li#24:cl=100\E[;H\E[2J:bs:cm=50\E[%i%2;%2H:nd=200\E[C:up=100\E[A:\
+ :ce=120\E[K:cd=100\E[J:so=20\E[7m:se=20\E[m:us=20\E[4m:ue=20\E[m:\
+ :ks=200\E[?1h\E=:ke=200\E[?1l\E>:\
+ :ku=\EOA:kd=\EOB:kr=\EOC:kl=\EOD:\
+ :kh=\E[H:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:pt:sr=200\EM:\
+ :dC=50:dF=200:dN=50:dT=50:
+dI|dw1|decwriter I:\
+ :do=^J:le=^H:bs:co#72:hc:os:
+# From tut@Topaz.CC Thu May 12 14:49:02 1983
+dJ|dw3|la120|decwriter III:\
+ :bs:kb=^H:co#132:hc:os:pt:\
+ :is=\E(B\E[20l\E[w\E[1;132s\E[2g\E[9;17;25;33;41;49;57;65;73;81;89;97;105;113;121;129u\E[z\E[66t\E[1;66r\E[4g\E>\r:
+# From tut@topaz.CC Thu Sep 24 22:10:46 1981
+df|dw4|decwriter IV:\
+ :do=^J:le=^H:bs:co#132:hc:os:am:\
+ :pt:is=\Ec:k0=\EOP:k1=\EOQ:k2=\EOR:k3=\EOS:kb=^H:
+dh|vt50h|dec vt50h:\
+ :do=^J:le=^H:bs:cd=\EJ:ce=\EK:cl=\EH\EJ:cm=\EY%+ %+ :\
+ :co#80:li#12:nd=\EC:pt:sr=\EI:up=\EA:
+di|vt100-s|vt100 with status line at top:\
+ :li#23:i2=\E[2;24r\E[24;1H:cm@:ho=\E[H^J:cl=50\E[;H^J\E[0J:\
+ :hs:es:ts=\E7\E[1;%dH\E[1K:fs=\E8:tc=vt100-am:
+dj|vt100-s-bot|vt100 with status line at bottom:\
+ :li#23:i2=\E[1;23r\E[23;1H:\
+ :hs:es:ts=\E7\E[24;%dH\E[1K:fs=\E8:tc=vt100-am:
+ds|vt100-nav|dec vt100 132 cols 14 lines (w/o advanced video option):\
+ :li#14:tc=vt100-w:
+dt|vt100-w|dec vt100 132 cols (w/advanced video):\
+ :co#132:li#24:rs=\E>\E[?3h\E[?4l\E[?5l\E[?8h:tc=vt100-am:
+dv|vt100-w-nam|dec vt100 132 cols (w/advanced video), no am:\
+ :co#132:li#24:rs=\E>\E[?3h\E[?4l\E[?5l\E[?8h:vt@:tc=vt100-nam:
+# vt 102 (from lai@decwrl)
+dy|vt102|vt-102|dec vt102:\
+ :do=^J:co#80:li#24:cl=50\E[;H\E[2J:\
+ :le=^H:bs:cm=5\E[%i%d;%dH:nd=2\E[C:up=2\E[A:\
+ :ce=3\E[K:cd=50\E[J:so=2\E[7m:se=2\E[m:us=2\E[4m:ue=2\E[m:\
+ :md=2\E[1m:mr=2\E[7m:mb=2\E[5m:me=2\E[m:is=\E[1;24r\E[24;1H:\
+ :rs=\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h:ks=\E[?1h\E=:ke=\E[?1l\E>:\
+ :ku=\EOA:kd=\EOB:kr=\EOC:kl=\EOD:kb=^H:\
+ :ho=\E[H:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:pt:sr=5\EM:vt#3:\
+ :sc=\E7:rc=\E8:cs=\E[%i%d;%dr:vs=\E[?7l:ve=\E[?7h:
+dw|vt52|dec vt52:\
+ :do=^J:le=^H:bs:cd=\EJ:ce=\EK:cl=\EH\EJ:cm=\EY%+ %+ :co#80:li#24:\
+ :nd=\EC:pt:sr=\EI:up=\EA:ku=\EA:kd=\EB:kr=\EC:kl=\ED:kb=^H:
+# vt61 created by Roger Sacilotto Massachusetts Computer Associates, Inc
+# Similar to vt52 but add al and dl
+#
+dq|vt61|dec vt61:\
+ :al=\EPf:dl=\EPd:tc=vt52:
+dx|dw2|decwriter II:\
+ :do=^J:kb=^h:le=^H:bs:co#132:hc:os:
+# DEC PRO-350 console (VT220-style)
+dP|pro350|decpro|dec pro console:\
+ :bs:cd=\EJ:ce=\EK:cl=\EH\EJ:\
+ :cm=\EY%+ %+ :co#80:ho=\EH:\
+ :kl=\ED:kr=\EC:ku=\EA:kd=\EB:kh=\EH:\
+ :k0=\EE:k1=\EF:k2=\EG:k3=\EH:k4=\EI:k5=\EJ:k6=\Ei:k7=\Ej:\
+ :li#24:nd=\EC:pt:sr=\EI:up=\EA:do=\EB:\
+ :se=\E^N:so=\E^H:us=\E^D:ue=\E^C:\
+ :ae=\EG:as=\EF:
+#
+# From: Bracy H. Elton <elton@lll-crg>
+dm|vt200-ss|vt220-ss|dec vt200 series with smooth scroll:\
+ :is=\E>\E[?3l\E[?4h\E[?5l\E[?7h\E[?8h\E[1;24r\E[24;1H:\
+ :rs=\E>\E[?3l\E[?4h\E[?5l\E[?7h\E[?8h:\
+ :tc=vt200:
+dn|vt200-w|vt220-w|vt200-wj|vt220-wj|dec vt200 series; 132 col.; jump scroll:\
+ :is=\E>\E[?3h\E[?4l\E[?5l\E[?7h\E[?8h\E[1;24r\E[24;1H:\
+ :rs=\E>\E[?3h\E[?4l\E[?5l\E[?7h\E[?8h:\
+ :co#132:tc=vt200:
+do|vt200-ws|vt220-ws|dec vt200 series; 132 col.; smooth scroll:\
+ :is=\E>\E[?3h\E[?4h\E[?5l\E[?7h\E[?8h\E[1;24r\E[24;1H:\
+ :rs=\E>\E[?3h\E[?4h\E[?5l\E[?7h\E[?8h:\
+ :co#132:tc=vt200:
+# vs100 emulator using tsim (from lai@decwrl)
+vt|vs100t|tsim|vs100-tsim:\
+ :bs:cm=\EM%+ %+ :ho=\EH:do=^J:up=^K:cl=\EE:ce=\EL:cs=\ES%+ %+ :\
+ :so=\Eh:se=\Er:us=\Eu:ue=\Ev:al=\EI:Al=\E+%+ :dl=\ED:Dl=\E-%+ :\
+ :ic=\Ei:dc=\Ed:is=\ER:rs=\ER:am:cd=\EQ:pt:nd=\En:li#24:co#80:
+# # --------------------------------
+#
+# h: HEWLETT PACKARD
+#
+# Note: no "ho" on HP's since that homes to top of memory, not screen.
+# Due to severe 2621 braindamage, the only way to get the arrow keys to
+# transmit anything at all is to turn on the function key labels
+# (f1-f8) with ks, and even then the poor user has to hold down shift!
+# The default 2621 turns off the labels except when it has to to enable
+# the function keys. If your installation prefers labels on all the time,
+# or off all the time (at the "expense" of the function keys) move the
+# 2621-nl or 2621-wl labels to the front using reorder.
+# Note: there are newer ROM's for 2621's that allow you to set strap A
+# so the regular arrow keys xmit \EA, etc, as with the 2645. However,
+# even with this strap set, the terminal stops xmitting if you reset it,
+# until you unset and reset the strap! Since there is no way to set/unset
+# the strap with an escape sequence, we don't use it in the default.
+# If you like, you can use 2621-ba (braindamaged arrow keys).
+h1|2621-ba|2621 w/new rom, strap A set:\
+ :ks@:ke@:ku=\EA:kd=\EB:kl=\ED:kr=\EC:kh=\Eh:tc=hp2621:
+# 2621 with function labels. Most of the time they are off,
+# but inside vi, the function key labels appear. You have to
+# hold down shift to get them to xmit.
+# 2621k45: untested
+# 2622: unsure if this is quite it, have only heard about the terminal.
+h3|2621k45|hp2621k45|k45|2622|hp2622|hp 2621 with 45 keyboard:\
+ :kb=^H:ku=\EA:kd=\EB:kl=\ED:kr=\EC:kh=\Eh:ks=\E&s1A:ke=\E&s0A:tc=2621:
+h5|hp|hewlett-packard:\
+ :ct=\E3:st=\E1:do=^J:al=\EL:am:le=^H:bs:\
+ :cd=\EJ:ce=\EK:ch=\E&a%dC:cl=\EH\EJ:cm=6\E&a%r%dc%dY:\
+ :co#80:cv=\E&a%dY:da:db:dc=\EP:dl=\EM:ei=\ER:im=\EQ:\
+ :kb=^H:li#24:mi:nd=\EC:pt:se=\E&d@:so=\E&dJ:\
+ :us=\E&dD:ue=\E&d@:up=\EA:xs:vt#6:pb#9600:
+# This entry does not use any of the fancy windowing stuff of the 2621.
+# Indeed, termcap does not yet handle such stuff. We are looking at it.
+h6|hp2626|hp2626a|hp2626p|2626|2626a|2626p|hp 2626:\
+ :dc=2\EP:ip=2:se=\E&d@:so=\E&dB:cd=500\EJ:\
+ :mr=\E&dB:us=\E&dD:mb=\E&dA:mk=\E&dS:me=\E&d@:ue=\E&d@:\
+ :kh=\Eh:ku=\EA:kl=\ED:kr=\EC:kd=\EB:ks=\E&s1A:ke=\E&s0A:\
+ :sf=\ES:ta=2^I:xs:tc=2621:
+# cD is a pain - but it only screws up at 9600 baud.
+# You should use this terminal at 4800 baud or less.
+h8|hp2648|hp2648a|2648a|2648|HP 2648a graphics terminal:\
+ :cl=50\EH\EJ:cm=20\E&a%r%dc%dY:dc=7\EP:ip=5:tc=2645:
+# This terminal should be used at 4800 baud or less.
+h9|hp2645-np|2645 w/no padding:cm=\E&a%r%dc%dY:tc=hp2645:
+# 2640a doesn't have the Y cursor addressing feature, and C is memory relative
+# instead of screen relative, as we need.
+ha|2640|hp2640a|2640a|hp 2640a:\
+ :cm@:ks@:ke@:tc=2645:
+hb|2640b|hp2640b|2644a|hp2644a|hp 264x series:\
+ :ks@:ke@:tc=2645:
+# 2621 using all 48 lines of memory, only 24 visible at any time. Untested.
+hl|2621-48|48 line 2621:\
+ :li#48:ho=\EH:cm=\E&a%r%dc%dR:tc=2621:
+# Hp 110 computer is the same as 2621 except has 16 lines
+hm|hp110|110|hp 110 computer:\
+ :li#16:tc=2621:
+# 2621 with no labels ever. Also prevents vi delays on escape.
+# Needed for UCB ARPAVAX console, since lsi-11 expands tabs (wrong).
+ht|hp2621-nt|2621nt|2621-nt|hp2621nt|hp 2621 w/no tabs:\
+ :pt@:tc=hp2621:
+# 2621 with labels on all the time - normal outside vi, function inside vi.
+hw|hp2621wl|2621wl|2621-wl|hp2621-wl|hp 2621 w/labels:\
+ :is=\E&jA\r:ke=\E&jA:tc=hp2621-fl:
+# 2392 (from haddix@arpa?)
+hz|2392|hp2392|hp2392a:\
+ :bt=\Ei:ip=2:is=\E&j@\E3\r:if=/usr/lib/tabset/stdcrt:\
+ :ml=\El:MT:mu=\Em:km:\
+ :mh=\E&dH:mr=\E&dB:us=\E&dD:mb=\E&dA:me=\E&d@:\
+ :ku=\EA:kd=\EB:kl=\ED:kr=\EC:kh=\Eh:ks=\E&s1A:ke=\E&s0A:tc=hp:
+#HP 236 console running 4.3 BSD
+#from ddavis@ic.berkeley.edu
+h7|236|hp236|HP236 internal terminal emulator:\
+ :am:bs:li#24:co#80:cl=\EF:cm=\EE%+ %+ :\
+ :dc=\EJ:dl=\EH:ic=\EI:al=\EG:up=^K:im=:ei=:\
+ :so=\EBI:se=\ECI:vs=\EDB:ve=\EDE:
+# hp150 from ddavis@ic.berkeley.edu
+h0|150|hp150|hp150a|150a:\
+ :is=\E&s1A\E&f0a1k2L\Ep\r\E&k0K\E&f0a2k2L\Eq\r\E&f0a3k2L\Er\r\E&f0a4k2L\Es\r\E&f0a5k2L\Et\r\E&f0a6k2L\Eu\r\E&f0a7k2L\Ev\r\E&f0a8k2L\Ew\r\E&k0D\E&s0A:\
+ :bt=\Ei:li#24:cm=\E&a%r%dc%dY:dc=2\EP:ip=2:pb#19200:so=\E&dJ:\
+ :se=\E&d@:us=\E&dD:ue=\E&d@:me=\E&d@:kh=\Eh:ku=\EA:kl=\ED:kr=\EC:\
+ :kd=\EB:kn#8:k1=\Ep:k2=\Eq:k3=\Er:k4=\Es:k5=\Et:k6=\Eu:k7=\Ev:\
+ :k8=\Ew:ta=2^I:ct=\E3:st=\E1:do=^J:al=\EL:am:le=^H:\
+ :bs:cd=\EJ:ce=\EK:ch=\E&a%dC:cl=\Eh\EJ:co#80:cv=\E&a%dY:da:db:dl=\EM:\
+ :ei=\ER:im=\EQ:kb=^H:mi:nd=\EC:pt:up=\EA:xs:vt#6:sf=\ES:sr=\ET:\
+ :vs=\E&s1A:ve=\E&s0A:ks=\E&jB\E&j@:ke=\E&j@:
+# # --------------------------------
+#
+# i: INFOTON (GENERAL TERMINAL)
+#
+# Infoton is now called General Terminal Corp. or some such thing.
+# gt100 sounds like something DEC would come out with. Lets hope they don't.
+i1|i100|gt100|gt100a|General Terminal 100A (formerly Infoton 100):\
+ :do=^J:cl=^L:cd=\EJ:ce=\EK:li#24:co#80:\
+ :al=\EL:dl=\EM:up=\EA:nd=\EC:ho=\EH:cm=\Ef%r%+ %+ :vb=\Eb\Ea:\
+ :am:le=^H:bs:so=\Eb:se=\Ea:
+i4|i400|400|infoton 400:\
+ :do=^J:al=\E[L:am:le=^H:bs:ce=\E[N:cl=\E[2J:cm=%i\E[%3;%3H:co#80:\
+ :dl=\E[M:li#25:nd=\E[C:up=\E[A:im=\E[4h\E[2Q:ei=\E[4l\E[0Q:\
+ :dc=\E[4h\E[2Q\E[P\E[4l\E[0Q:
+ia|addrinfo:\
+ :do=^J:li#24:co#80:cl=^L:ho=^H:nd=^Y:cd=^K:\
+ :up=^\:am:le=^Z:bc=^Z:cm=\037%+\377%+\377:ll=^H^\:
+ik|infotonKAS:\
+ :do=^J:am:le=^Z:bc=^Z:cd=^K:cl=^L:co#80:li#24:nd=^Y:up=^\:ll=^H^\:
+# # --------------------------------
+#
+# k: HEATHKIT (ZENITH)
+#
+kA|h19-a|h19a|heath-ansi|heathkit-a|heathkit h19 ansi mode:\
+ :\
+ :al=1*\E[1L:am:le=^H:bs:cd=\E[J:ce=\E[K:cl=\E[2J:cm=\E[%i%2;%2H:co#80:\
+ :dc=\E[1P:dl=1*\E[1M:do=\E[1B:ei=\E[4l:ho=\E[H:im=\E[4h:li#24:mi:\
+ :nd=\E[1C:as=\E[10m:ae=\E[11m:ms:pt:se=\E[0m:so=\E[7m:up=\E[1A:\
+ :vs=\E[>4h:ve=\E[>4l:kb=^h:ku=\E[1A:kd=\E[1B:kl=\E[1D:kr=\E[1C:\
+ :kh=\E[H:kn#8:k1=\EOS:k2=\EOT:k3=\EOU:k4=\EOV:k5=\EOW:l6=blue:\
+ :l7=red:l8=white:k6=\EOP:k7=\EOQ:k8=\EOR:\
+ :sr=\EM:is=\E<\E[>1;2;3;4;5;6;7;8;9l\E[0m\E[11m\E[?7h:
+kB|h19-bs|h19bs|heathkit w/keypad shifted:\
+ :ks=\Et:ke=\Eu:tc=h19-b:
+#written by David Shewmake, UCSF Medical Information Science
+#ucbvax!ucsfmis!shewmake
+#the z29-e entry sucks...but it works with emacs
+kD|z29-e|zenith 29 hacked for emacs:\
+ :ip=1.5:ks=\Et:ke=\Eu:vs@:ve@:al=1*\EL:am:le=^H:\
+ :bs:cd=\EJ:ce=\EK:cl=\EE:cm=\EY%+ %+ :co#80:dc=\EN:dl=1*\EM:\
+ :do=\EB:ho=\EH:li#24:nd=\EC:as=\EF:ae=\EG:ms:\
+ :pt:sr=\EI:se=\Eq:so=\Ep:up=\EA:vs=\Ex4:ve=\Ey4:kb=^h:\
+ :ku=\EA:kd=\EB:kl=\ED:kr=\EC:kh=\EH:kn#8:k1=\ES:k2=\ET:k3=\EU:\
+ :k4=\EV:k5=\EW:l6=blue:l7=red:l8=white:k6=\EP:k7=\EQ:k8=\ER:es:hs:\
+ :ts=\Ej\Ex5\Ex1\EY8%+ \Eo:fs=\Ek\Ey5:ds=\Ey1:
+# z29 in ansi mode. Assumes that the cursor is in the correct state, and that
+# the world is stable. `rs' causes the terminal to be reset to the state
+# indicated by the name. kc -> key click, nkc -> no key click, uc -> underscore
+# cursor, bc -> block cursor.
+# from Mike Meyers
+kF|z29a|z29a-kc-bc|h29a-kc-bc|heath/zenith 29 in ansi mode:\
+ :do=^J:co#80:li#24:cl=\E[2J:pt:ho=\E[H:\
+ :le=^H:bs:cm=\E[%i%d;%dH:nd=\E[C:up=\E[A:mb=\E[5m:mr=\E7m:\
+ :ce=\E[K:cd=\E[J:so=\E[7;2m:se=\E[m:us=\E[4m:ue=\E[m:mh=\E[2m:\
+ :md=\E[2m:mr=\E[7m:mb=\E[5m:me=\E[m:\
+ :rs=\E<\E[1;24r\E[24;1H\E[?7h\E[>4h\E[>1;2;3;5;6;7;8;9l\E[m\E[11m:\
+ :ku=\EOA:kd=\EOB:kr=\EOC:kl=\EOD:kb=^H:\
+ :k1=\EOS:k2=\EOT:k3=\EOU:k4=\EOV:k5=\EOW:k6=\EOP:k7=\EOQ:k8=\EOR:\
+ :k9=\EOX:k0=\E[~:l0=help:kn#2:ko=ho,cd:if=/usr/lib/tabset/zenith29:\
+ :es:hs:ts=\E[s\E[>5;1h\E[25;%i%dH\E[1K:fs=\E[u\E[>5l:ds=\E[>1l:\
+ :cs=\E[%i%d;%dr:sr=\EM:sf=\ED:DO=\E[%dB:UP=\E[%dA:LE=\E[%dD:\
+ :RI=\E[%dC:AL=\E[%dL:DL=\E[%dM:sc=\E[s:rc=\E[r:dc=\E[1P:DC=\E[%dP:\
+ :kC=\E[J:ct=\E[3g:st=\EH:ti=\E[?7l:te=\E[?7h:ps=\E#7:
+kG|z29a-kc-uc|h29a-kc-uc|heath/zenith 29 in ansi mode:\
+ :rs=\E<\E[1;24r\E[24;1H\E[?7h\E[>1;2;3;4;5;6;7;8;9l\E[m\E[11m:\
+ :tc=z29a:
+kH|z29a-nkc-bc|h29a-nkc-bc|heath/zenith 29 in ansi mode:\
+ :rs=\E<\E[1;24r\E[24;1H\E[?7h\E[>2;4h\E[>1;3;5;6;7;8;9l\E[m\E[11m:\
+ :tc=z29a:
+kI|z29a-nkc-uc|h29a-nkc-uc|heath/zenith 29 in ansi mode:\
+ :rs=\E<\E[1;24r\E[24;1H\E[?7h\E[>2h\E[>1;3;4;5;6;7;8;9l\E[m\E[11m:\
+ :tc=z29a:
+#z100 entry from Brad Brahms at TRW (Brahms@USC-ECLC)
+# usenet: {decvax,ucbvax}!trwrb!trwspp!brahms
+kc|z100|h100|z110|z-100|h-100|heath/zenith z-100 pc with color monitor:\
+ :vs=\Ex4\Em71:ve=\Ey4\Em70:tc=z100bw:
+kY|z100bw|h100bw|z110bw|z-100bw|h-100bw|heath/zenith z-100 pc:\
+ :al=5*\EL:bs:cd=\EJ:ce=\EK:cl=5*\EE:cm=1*\EY%+ %+ :co#80:dc=1*\EN:\
+ :dl=5*\EM:do=\EB:ei=\EO:ho=\EH:im=\E@:li#24:mi:nd=\EC:as=\EF:ae=\EG:\
+ :ms:pt:sr=\EI:se=\Eq:so=\Ep:up=\EA:vs=\Ex4:ve=\Ey4:\
+ :kb=^h:ku=\EA:kd=\EB:kl=\ED:kr=\EC:kh=\EH:kn#10:\
+ :k0=\EJ:k1=\ES:k2=\ET:k3=\EU:k4=\EV:k5=\EW:\k6=\EP:k7=\EQ:\
+ :k8=\ER:k9=\EOI:
+kp|p19:\
+ :al=2*\EL:dl=2*\EM:tc=h19-b:
+# from ucscc!B.fiatlux@ucbvax.berkeley.edu
+zx|ztx|ztx11|zt-1|htx11|ztx-1-a|ztx-10/11:\
+ :al=\EL:am:bs:cd=\EJ:ce=\EK:cl=\EE:cm=\EY%+ %+ :co#80:\
+ :dl=\EM:do=^J:ho=\EH:is=\Ej\EH\Eq\Ek\Ev\Ey1\Ey5\EG\Ey8\Ey9\Ey>:\
+ :k0=\ES:k1=\EB:k2=\EU:k3=\EV:k4=\EW:k5=\EP:k6=\EQ:k7=\ER:kb=^H:kd=\EB:\
+ :kl=\ED:kr=\EC:ku=\EA:le=^H:li#24:nd=\EC:pt:se=\Eq:so=\Es5:\
+ :sr=\EI:sr=\EI:ue=\Eq:up=\EA:us=\Es2:\
+ :es:hs:ts=\Ej\Ex5\Ex1\EY8%+ \Eo:fs=\Ek\Ey5:ds=\Ey1:
+# # --------------------------------
+#
+# l: LEAR SIEGLER (ADM)
+#
+# If the adm31 gives you trouble with standout mode, check the DIP switch
+# in position 6, bank @c11, 25% from back end of pc. Should be OFF.
+# If there is no such switch, you have an old adm31 and must use oadm31
+l2|adm2|lsi adm2:\
+ :do=^J:al=\EE:am:le=^H:bs:cd=\EY:ce=\ET:cl=\E;:\
+ :cm=\E=%+ %+ :co#80:dc=\EW:dl=\ER:\
+ :ei=:ho=^^:ic=\EQ:im=:kd=^J:kh=^^:kl=^H:kr=^L:ku=^K:li#24:nd=^L:up=^K:
+l4|adm42|42|lsi adm42:\
+ :vs=\EC\E3 \E3(:do=^J:al=270\EE:am:le=^H:bs:cd=\EY:ce=\ET:cl=\E;:\
+ :cm=\E=%+ %+ :co#80:dc=\EW:dl=\ER:ei=\Er:im=\Eq:ip=6*:li#24:\
+ :bt=\EI:nd=^L:se=\EG0:so=\EG4:up=^k:ma=^K^P:pc=\177:
+l5|adm5|5|lsi adm5:\
+ :do=^J:cd=\EY:ce=\ET:do=^J:kb=^H:kh=^^:\
+ :ma=^Hh^Jj^Kk^Ll^^H:se=\EG:sg#1:so=\EG:tc=adm3aplus:
+l7|adm20|lear siegler adm20:\
+ :am:li#24:co#80:bs:cl=^Z:cm=\E=%i%r%+^_%+^_:nd=^L:up=^K:ho=^^:ce=\ET:\
+ :cd=\EY:al=\EE:dl=\ER:im=:ei=:ic=\EQ:dm=:ed=:dc=\EW:so=\E):se=\E(:\
+ :bt=\EI:pt:kn#7:k1=^A:k2=^B:k3=^W:k4=^D:k5=^E:k6:^X:k7=^Z:
+# From Andrew Scott Beals <bandy@lll-crg.ARPA>
+l8|adm12|12|lsi adm12:\
+ :is=\Eq:do=^J:al=\EE:am:le=^H:bs:ce=\ET:cm=\E=%+ %+ :cl=^Z:cd=\EY:\
+ :co#80:dc=\EW:dl=\ER:ei=\Er:ho=^^:im=\Eq:\
+ :k0=^A0\r:k1=^A1\r:k2=^A2\r:k3=^A3\r:k4=^A4\r:\
+ :k5=^A5\r:k6=^A6\r:k7=^A7\r:k8=^A8\r:k9=^A9\r:kd=^J:kl=^H:kr=^L:ku=^K:\
+ :li#24:ma=j^Jk^P^K^Pl ^R^L^L :mi:nd=^L:\
+ :se=\EG0:so=\EG4:up=^K:us=\EG1:ue=\EG0:
+lb|adm3a+|3a+|adm3aplus:\
+ :kl=^H:kd=^J:ku=^K:kr=^L:tc=adm3a:
+lc|adm22|22|lsi adm22:\
+ :is=\E%\014\014\014\016\003\000\003\002\003\002\000\000\000\000\000\000\000\000\000\000\000:\
+ :al=\EE:am:bs:bt=\EI:cd=\Ey:ce=\Et:cl=\E+:cm=\000\E=%+ %+ :co#80:\
+ :dc=\EW:dl=\ER:do=^J:em=:ho=^^:ic=\EQ:im=:\
+ :k1=\001@\015:k2=\001A\015:k3=\001B\015:k4=\001C\015:\
+ :k5=\001D\015:k6=\001E\015:k7=\001F\015:kn#7:\
+ :ko=ho:l1=F1:l2=F2:l3=F3:l4=F4:l5=F5:l6=F6:l7=F7:\
+ :kb=^H:kd=^J:kh=^^:kl=^H:kr=^L:ku=^K:li#24:\
+ :ma=j^Jk^P^K^Pl ^R^L^L :nd=^L:se=\E(:so=\E):ta=\Ei:up=^K:
+#From: stephen%comp.lancs.ac.uk@ucl-cs.arpa
+le|adm11|lsi adm11:\
+ :do=^J:bs:\
+ :cd=\EY:ce=\ET:kb=^H:kh=^^:\
+ :ma=^Hh^Jj^Kk^Ll^^H:so=\E):se=\E(:\
+ :kl=^H:kd=^J:ku=^K:kr=^L:\
+ :am:cm=\E=%+ %+ :cl=^Z:co#80:li#24:nd=^L:up=^K:\
+ :hs:ts=\EF\E):fs=\E(^M:ds=\Eh:
+# # --------------------------------
+#
+# m: MICROTERM
+#
+# These mime1 entries refer to the Microterm Mime I or Mime II.
+# The default mime is assumed to be in enhanced act iv mode.
+m3|mime3a|mime1 emulating 3a:\
+ :am@:ma=^X ^K^J^Z^P:ku=^Z:kd=^K:kl=^H:kr=^X:tc=adm3a:
+m4|microterm|act4|microterm act iv:\
+ :am:do=^J:le=^H:bs:cd=^_:ce=^^:cl=^L:cm=^T%.%.:\
+ :co#80:li#24:nd=^X:up=^Z:ho=^]:
+# The padding on sr and ta for act5 and mime is a guess and not final.
+# The act 5 has hardware tabs, but they are in columns 8, 16, 24, 32, 41 (!)...
+m5|microterm5|act5|microterm act v:\
+ :uc=^H\EA:sr=3\EH:ku=^Z:kd=^K:kl=^H:kr=^X:ma=^Z^P^Xl^Kj:tc=act4:
+# Act V in split screen mode. act5s is not tested and said not to work.
+mS|act5s|skinny act5:\
+ :ti=\EP:te=\EQ:li#48:co#39:tc=act5:
+# Mimes using brightness for standout. Half bright is really dim unless
+# you turn up the brightness so far that lines show up on the screen.
+# uc is disabled to get around a curses bug, should be put back in someday.
+mf|mime-fb|full bright mime1:\
+ :so=^Y:se=^S:is=^S\E:tc=mime:
+mh|mime-hb|half bright mime1:\
+ :so=^S:se=^Y:is=^Y\E:tc=mime:
+mm|mime|mime1|mime2|mimei|mimeii|microterm mime1:\
+ :do=^J:al=80^A:am:le=^H:bs:cd=^_:ce=^^:cl=\035^C:cm=^T%+^X%> 0%+P:\
+ :co#80:dl=80^W:ta=2^I:li#24:nd=^X:pt:uc=^U:up=^z:ho=\035:do=^K:\
+ :is=^S\E^Q:ma=^X ^K^J^Z^P:ku=^Z:kd=^K:kl=^H:kr=^X:sr=3^R:vt#9:
+# These termcaps (for mime 2a) put the terminal in low intensity mode
+# since high intensity mode is so obnoxious.
+ms|mime2a-s|microterm mime2a (emulating an enhanced soroc iq120):\
+ :do=^J:\
+ :al=20*^A:am:le=^H:bs:cd=20*\EJ:ce=\EK:cl=\EL:cm=\E=%+ %+ :co#80:dc=\ED:\
+ :dl=20*^W:kl=^H:kr=^L:ku=^K:kd=^J:ho=^^:is=\E):sr=\EI\
+ :im=\EE:ei=^Z:ip=2:li#24:nd=^L:so=\E\072:se=\E;:up=\EI:\
+ :us=\E6:ue=\E7:
+# This is the preferred mode (but ^X can't be used as a kill character)
+mv|mime2a|mime2a-v|microterm mime2a (emulating an enhanced vt52):\
+ :do=^J:al=20*^A:le=^H:bs:cd=20*\EQ:co#80:ce=\EP:cl=\EL:cm=\EY%+ %+ :\
+ :is=^Ydc=^N:dl=20*^W:ip=2:ei=^Z:ho=\EH:im=^O:kd=\EB:kl=\ED:kr=\EC:\
+ :ku=\EA:li#24:nd=\EC:pt:se=\E9:so=\E8:up=\EA:sr=\EA:us=\E4:ue=\E5:
+mx|mime-3ax|mime1 emulating enhanced 3a:\
+ :al=80^A:dl=80^W:pt:ce=^X:cd=^_:tc=mime-3a:
+# # --------------------------------
+#
+# p: PERKIN ELMER
+#
+pe|pe550|bantam|perkin elmer 550:\
+ :do=^J:le=^H:bs:co#80:ce=20\EI:cl=20\EK:cm=\EX%+ \EY%+ :\
+ :ho=\EH:li#24:ll=\EH\EA:nd=\EC:up=\EA:ma=^Z^P:cd=6^N@^V:
+pf|fox|perkin elmer 1100:\
+ :ct=\E3:st=\E1:do=^J:\
+ :am:le=^H:bs:cd=5.5*\EJ:ce=\EI:cl=132\EH\EJ:co#80:ho=\EH:li#24:\
+ :ll=\EH\EA:nd=\EC:cm=\EX%+ \EY%+ :up=\EA:vb=^P^B^P^C:
+po|owl|perkin elmer 1200:\
+ :ct=\E3:st=\E1:do=^J:al=5.5*\EL:am:le=^H:\
+ :bs:cd=5.5*\EJ:ce=5.5\EI:cl=132\EH\EJ:ho=\EH:ll=\EH\EA:\
+ :cm=\EX%+ \EY%+ :co#80:dc=5.5*\EO:dl=5.5*\EM:ei=:ic=\EN:im=:ip=5.5*:\
+ :kb=^h:in:li#24:nd=\EC:up=\EA:se?=\E!\200:so?=\E!^H:vb=^P^B^P^C:\
+ :k1=\ERA:k2=\ERB:k3=\ERC:k4=\ERD:k5=\ERE:k6=\ERF:\
+ :k7=\ERG:k8=\ERH:k9=\ERI:k0=\ERJ:
+# # --------------------------------
+#
+# q: HOME MADE TERMINALS
+#
+qB|bc|bill croft homebrew:\
+ :do=^J:am:le=^H:bs:cm=\E=%+ %+ :cl=^Z:co#96:ho=^^:li#72:\
+ :nd=^L:up=^K:vb=:
+qN|nucterm|rayterm|NUC homebrew:\
+ :do=^J:am:le=^H:bs:cl=1^L:li#24:co#80:nd=^C:\
+ :up=^N:ho=^B:ll=^K:ce=^A:cd=^E:
+qb|ex3000:\
+ :do=^J:li#24:co#80:ho=^Q:
+qc|carlock|klc:\
+ :do=^J:al=^E:am:bs:ce=^U:cl=100^Z:cm=\E=%+ %+ :co#80:dc=\177:dl=^D:\
+ :dm=:ed=:ei=^T:ho=^^:im=^T:li#24:nd=^L:se=^V:so=^V:up=^K:vb=\EV\EV:
+qe|exidy|exidy2500|exidy sorcerer as dm2500:\
+ :do=^J:al=^P^J^X:am:le=^H:bs:ce=^W:cl=^^:cm=^L%r%n%.%.:co#64:\
+ :dc=\b:dl=^P^Z^X:dm=^P:ed=^X:ei=^X:ho=^B:ic=^\:\
+ :im=^P:li#30:nd=^\:pt:so=^N:se=^X:up=^Z:
+qn|netx|netronics:\
+ :do=^J:le=^H:bs:cd=2000^F^E:ce=1600^E:cl=466^L:cm=\E=%+@%+@:\
+ :co#64:ho=^D:li#16:ma=j^Jk^Pl :nd=\E+@A:pc=\200:sr=\E=@@^K:up=^K:
+# This came from the comp ctr who got it from some user. Smart indeed!
+qs|sexidy|exidy smart:\
+ :do=^J:li#24:co#64:cl=^l:ho=^q:nd=^s:\
+ :up=^w:le=^H:bs:le=^a:bc=^a:ma=^x^J:kd=^S:
+qu|ubell|ubellchar:\
+ :if=/usr/lib/tabset/ubell:do=^J:am:le=^H:bs:pt:ce=\Ed:cl=^Z:\
+ :cm=\E=%+ %+ :co#80:li#24:nd=^L:up=^K:ma=j^Jk^P^K^Pl :ho=^^:
+qw|ttyWilliams:\
+ :do=^J:co#80:li#12:le=^Y:bc=^Y:do=^K:up=^Z:cl=^^:ce=^_:am:ho=^]:nd=^X:
+qx|xitex|xitex sct-100:\
+ :do=^J:le=^H:bs:cd=2000^F^E:ce=1600^E:cl=400^L:cm=\E=%+@%+@:co#64:\
+ :ho=^D:li#16:ma=j^Jk^Pl :nd=\E+@A:pc=\200:sr=\E=@@^K:up=^K:
+# # --------------------------------
+#
+# s: SPECIALS
+#
+# Special "terminals". These are used to label tty lines when you don't
+# know what kind of terminal is on it. The characteristics of an unknown
+# terminal are the lowest common denominator - they look about like a ti 700.
+# # --------------------------------
+#
+# t: TEXAS INSTRUMENTS
+#
+t3|ti|ti700|ti733|735|ti735|ti silent 700:\
+ :do=^J:le=^H:bs:co#80:hc:os:dC#162:
+t4|ti745|745|743|ti silent 745:\
+ :do=^J:le=^H:bs:co#80:hc:os:
+t8|ti800|ti omni 800:\
+ :do=^J:le=^H:bs:co#132:hc:os:
+# # --------------------------------
+#
+# v: TELEVIDEO
+#
+# There are some tvi's that require incredible amounts of padding and
+# some that don't. I'm assuming 912 and 920 are the old slow ones,
+# and 912b, 912c, 920b, 920c are the new ones that don't need padding.
+v1|tvi912|912|920|tvi920|old televideo:\
+ :ct=\E3:st=\E1:do=^J:\
+ :al=33*\EE:le=^H:ce=\ET:cm=\E=%+ %+ :cl=^Z:co#80:dc=\EW:dl=33*\ER:ei=:\
+ :kb=^H:ku=^K:kd=^J:kl=^H:kr=^L:k0=^AI\r:k1=^A@\r:k2=^AA\r:k3=^AB\r:\
+ :bs:am:k4=^AC\r:k5=^AD\r:k6=^AE\r:k7=^AF\r:k8=^AG\r:k9=^AH\r:\
+ :ho=^^:im=:ic=\EQ:li#24:nd=^L:pt:se=\Ek:so=\Ej:up=^K:us=\El:ue=\Em:\
+ :ma=^K^P^L :sg#1:ug#1:if=/usr/lib/tabset/stdcrt
+# the 912 has a <funct> key that's like shift: <funct>8 xmits "^A8\r".
+# The 920 has this plus real function keys that xmit different things.
+# Termcap makes you use the funct key on the 912 but the real keys on the 920.
+v2|912b|912c|tvi912b|tvi912c|tvi|new televideo 912:\
+ :al=5*\EE:dl=5*\ER:tc=tvi912:
+v3|920b|920c|tvi920b|tvi920c|new televideo 920:\
+ :k0=^AI\r:k1=^A@\r:k2=^AA\r:k3=^AB\r:k4=^AC\r:k5=^AD\r:\
+ :k6=^AE\r:k7=^AF\r:k8=^AG\r:k9=^AH\r:tc=tvi912b:
+# set to page 1 when entering ex (\E-17 )
+# reset to page 0 when exiting ex (\E-07 )
+v4|tvi912-2p|tvi920-2p|912-2p|920-2p|tvi-2p|televideo w/2 pages:\
+ :ti=\E-17 :te=\E-07 :tc=tvi912:\
+v5|tvi950-ap|tvi 950 w/alt pages:\
+ :is=\E\\1:ti=\E-06 :te=\E-16 :tc=tvi950:
+v6|tvi950-b|bare tvi950 no is:\
+ :is@:tc=tvi950:
+v7|tvi950-ns|tvi950 w/no standout:\
+ :so@:se@:us@:ue@:tc=tvi950:
+vi|tvi925|925|televideo model 925:\
+ :hs:xn:am:bs:co#80:li#24:cm=\E=%+ %+ :cl=\E*:cd=\Ey:ce=\Et:is=\El\E":\
+ :al=\EE:dl=\ER:im=:ei=:ic=\EQ:dc=\EW:if=/usr/lib/tabset/stdcrt:\
+ :ho=^^:nd=^L:bt=\EI:pt:so=\EG4:se=\EG0:sg#1:us=\EG8:ue=\EG0:ug#1:\
+ :up=^K:do=^V:kb=^H:ku=^K:kd=^V:kl=^H:kr=^L:kh=^^:ma=^V^J^L :\
+ :k1=^A@\r:k2=^AA\r:k3=^AB\r:k4=^AC\r:k5=^AD\r:k6=^AE\r:k7=^AF\r:\
+ :k8=^AG\r:k9=^AH\r:k0=^AI\r:ko=ic,dc,al,dl,cl,ce,cd,bt:\
+ :ts=\Ef:fs=^M\Eg:ds=\Eh:sr=\Ej:
+vj|tvi925vb|925vb|televideo model 925 visual bells:\
+ :vb=\Eb\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\Ed:\
+ :tc=tvi925:
+# Since the 925's uses a character position to store the escape sequences to go
+# in and out of both stand out and underline modes, screen positioning is
+# difficult. The following 925 entries don't use these modes.
+vn|tvi925n|925n|televideo model 925 no standout or underline:\
+ :so@:se@:us@:ue@:tc=tvi925:
+vk|tvi925vbn|925vbn|televideo model 925 visual bells no so or ul:\
+ :vb=\Eb\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\Ed:\
+ :tc=tvi925n:
+# entry by Tim Curry 5/21/82 Univ. of Central Fla. duke!ucf-cs!tim
+v9|925a|tvi925a|TeleVideo Model 925:\
+ :al=\EE:am:bs:bt=\EI:bw:cd=\EY:ce=\ET:cl=^Z:cm=\E=%+ %+ :co#80:dc=\EW:\
+ :dl=\ER:do=^V:ei=:ic=\EQ:if=/usr/lib/tabset/std:im=:kb=^H:kd=^V:\
+ :kh=^^:kl=^H:kn#12:kr=^L:ku=^K:li#24:nd=^L:pt:se=\EG0:sg=#1:so=\EG4:\
+ :ue=\EG0:ug#1:ul:up=^K:us=\EG8:is=\El\
+ :vb=\Eb\200\200\200\200\200\200\200\200\200\200\200\200\200\200\Ed:\
+ :ve=\E.4:vs=\E.2:
+# The following tvi descriptions from B:pjphar and virus!mike
+# is for all 950's. It sets the following attributes:
+# full duplex (\EDF) write protect off (\E()
+# conversation mode (\EC) graphics mode off (\E%)
+# white on black (\Ed) auto page flip off (\Ew)
+# turn off status line (\Eg) clear status line (\Ef\r)
+# normal video (\E0) monitor mode off (\EX or \Eu)
+# edit mode (\Er) load blank char to space (\Ee\040)
+# line edit mode (\EO) enable buffer control (^O)
+# protect mode off (\E\047) duplex edit keys (\El)
+# program unshifted send key to send line all (\E016)
+# program shifted send key to send line unprotected (\E004)
+# set the following to nulls:
+# field delimiter (\Ex0\200\200)
+# line delimiter (\Ex1\200\200)
+# start-protected field delimiter (\Ex2\200\200)
+# end-protected field delimiter (\Ex3\200\200)
+# set end of text delimiter to carriage return/null (\Ex4\r\200)
+#
+va|tvi950|950|televideo950:\
+ :ct=\E3:st=\E1:do=^J:\
+ :is=\EDF\EC\Ed\EG0\Eg\Er\EO\E\047\E(\E%\Ew\EX\Ee ^O\
+ \El\E016\E004\Ex0\200\200\Ex1\200\200\Ex2\200\200\
+ \Ex3\200\200\Ex4\r\200\Ef\r:\
+ :al=\EE:am:le=^H:bs:bt=\EI:cd=\Ey:ce=\Et:cl=\E*:cm=\E=%+ %+ :\
+ :co#80:dc=\EW:dl=\ER:do=^V:ei=\Er:ho=^^:im=\Eq:k0=^A0\r:\
+ :k1=^A@\r:k2=^AA\r:k3=^AB\r:k4=^AC\r:k5=^AD\r:k6=^AE\r:\
+ :k7=^AF\r:k8=^AG\r:k9=^AH\r:kb=^H:kd=^V:kh=^^:kl=^H:\
+ :ko=ic\054dc\054al\054dl\054cl\054bt\054ce\054cd:kr=^L:\
+ :ku=^K:li#24:ma=^Vj^Kk^Hh^Ll^^H:mi:ms:nd=^L:pt:se=\EG0:\
+ :sg#1:so=\EG4:sr=\Ej:ue=\EG0:ug#1:up=^K:us=\EG8:\
+ :vb=\Eb\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\Ed:\
+ :xn:hs:ts=\Eg\Ef:fs=\r:ds=\Eg\Ef\r:
+#
+# is for 950 with two pages adds the following:
+# set 48 line page (\E\\2)
+# place cursor at page 0, line 24, column 1 (\E-07 )
+# set local (no send) edit keys (\Ek)
+#
+# two page 950 adds the following:
+# when entering ex, set 24 line page (\E\\1)
+# when exiting ex, reset 48 line page (\E\\2)
+# place cursor at 0,24,1 (\E-07 )
+# set duplex (send) edit keys (\El) when entering vi
+# set local (no send) edit keys (\Ek) when exiting vi
+#
+vb|tvi950-2p|950-2p|televideo950 w/2 pages:\
+ :is=\EDF\EC\Ed\EG0\Eg\Er\EO\E\047\E(\E%\Ew\EX\Ee ^O\
+ \Ek\E016\E004\Ex0\200\200\Ex1\200\200\Ex2\200\200\
+ \Ex3\200\200\Ex4\r\200\E\\2\E-07 \
+ :te=\E\\2\E-07 :ti=\E\\1\E-07 :ks=\El:ke=\Ek:tc=tvi950:
+#
+# is for 950 with four pages adds the following:
+# set 96 line page (\E\\3)
+# place cursor at page 0, line 24, column 1 (\E-07 )
+#
+# four page 950 adds the following:
+# when entering ex, set 24 line page (\E\\1)
+# when exiting ex, reset 96 line page (\E\\3)
+# place cursor at 0,24,1 (\E-07 )
+#
+vc|tvi950-4p|950-4p|televideo950 w/4 pages:\
+ :is=\EDF\EC\Ed\EG0\Eg\Er\EO\E\047\E(\E%\Ew\EX\Ee ^O\
+ \Ek\E016\E004\Ex0\200\200\Ex1\200\200\Ex2\200\200\
+ \Ex3\200\200\Ex4\r\200\E\\3\E-07 \
+ :te=\E\\3\E-07 :ti=\E\\1\E-07 :ks=\El:ke=\Ek:tc=tvi950:
+#
+# is for reverse video 950 changes the following:
+# set reverse video (\Ed)
+#
+# set vb accordingly (\Ed ...nulls... \Eb)
+#
+vd|tvi950-rv|950-rv|televideo950 rev video:\
+ :is=\EDF\EC\Eb\EG0\Eg\Er\EO\E\047\E(\E%\Ew\EX\Ee ^O\
+ \El\E016\E004\Ex0\200\200\Ex1\200\200\Ex2\200\200\
+ \Ex3\200\200\Ex4\r\200:\
+ :vb=\Ed\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\Eb:\
+ :tc=tvi950:
+#
+# uses the appropriate entries from 950-2p and 950-rv
+#
+ve|tvi950-rv-2p|950-rv-2p|televideo950 rev video w/2 pages:\
+ :is=\EDF\EC\Eb\EG0\Eg\Er\EO\E\047\E(\E%\Ew\EX\Ee ^O\
+ \Ek\E016\E004\Ex0\200\200\Ex1\200\200\Ex2\200\200\
+ \Ex3\200\200\Ex4\r\200\E\\2\E-07 :\
+ :vb=\Ed\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\Eb:\
+ :te=\E\\2\E-07 :ti=\E\\1\E-07 :ks=\El:ke=\Ek:tc=tvi950:
+#
+# uses the appropriate entries from 950-4p and 950-rv
+#
+vf|tvi950-rv-4p|950-rv-4p|televideo950 rev video w/4 pages:\
+ :is=\EDF\EC\Eb\EG0\Er\EO\E\047\E(\E%\Ew\EX\Ee ^O\
+ \Ek\E016\E004\Ex0\200\200\Ex1\200\200\Ex2\200\200\
+ \Ex3\200\200\Ex4\r\200\E\\3\E-07 :\
+ :vb=\Ed\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\Eb:\
+ :te=\E\\3\E-07 :ti=\E\\1\E-07 :ks=\El:ke=\Ek:tc=tvi950:
+vg|tvi924|924|televideo model 924:\
+ :am:bs:xn:co#80:li#24:cm=\E=%+ %+ :cl=\E*0:cd=\Ey:ce=\Et:is=\Ek0\E"^O:\
+ :al=\EE:dl=\ER:im=:ei=:ic=\EQ:dc=\EW:if=/usr/lib/tabset/stdcrt:ho=^^:\
+ :nd=^L:bt=\EI:pt:so=\EG4:se=\EG0:us=\EG8:ue=\EG0:up=^K:do=^V:kb=^H:\
+ :ku=^K:kd=^V:kl=^H:kr=^L:kh=^^:ma=^Vj^Kk^Ll^^H^R^L:k1=^A@\r:k2=^AA\r:\
+ :k3=^AB\r:k4=^AC\r:k5=^AD\r:k6=^AE\r:k7=^AF\r:k8=^AG\r:k9=^AH\r:\
+ :k0=^AI\r:ko=ic,dc,al,dl,cl,ce,cd,bt:sr=\Ej:\
+ :hs:fs=^Y\Es1:ts=\Ef:ds=\Es0\Ef^Y:
+vo|tvi924vb|924vb|televideo model 924 visual bells:\
+ :vb=\Eb\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\Ed:\
+ :tc=tvi924:
+# tvipt termcap from armsis@amber (Gene Rochlin), 9/19/84. Works with vi and
+# rogue. NOTE: Esc v sets autowrap on, Esc u sets 80 char/line (rather than
+# 40), Esc K chooses the normal character set. Not sure padding is needed, but
+# adapted from the tvi920c termcap. so and us are klutzy, but at least use no
+# screen space.
+vp|tvipt|televideopt:if=/usr/lib/tabset/stdcrt:\
+ :is=\Ev\Eu\EK:al=5*\EE:am:bs:bt=\EI:ce=\ET:cm=\E=%+ %+ :cl=^Z:co#80:\
+ :dl=5*\ER:kb=^H:ku=^K:kd=^J:kl=^H:kr=^L:ho=^^:li#24:nd=^L:se=\EF:\
+ :so=\EG1@A\EH:ue=\EF:us=\EG1B@\EH:up=^K:ma=^Kk^Ll^R^L:
+# from Alan R. Rogers (rogers%albany@csnet-relay)
+vh|tvi910+|910+|televideo 910+:\
+ :al=5*\EE:am:bs:bt=\EI:cd=\EY:ce=\ET:cl=^Z:cm=\E=%+\040%+\040:\
+ :co#80:dc=\EW:dl=\ER:do=^J:ei=:ho=^^:ic=\EQ:\
+ :if=/usr/lib/tabset/stdcrt:im=:k0=^A@\r:k1=^AA\r:k2=^AB\r:k3=^AC\r:\
+ :k4=^AD\r:k5=^AE\r:k6=^AF\r:k7=^AG\r:k8=^AH\r:k9=^AI\r:kb=^H:\
+ :kd=^J:kh=^^:kl=^H:kr=^L:ku=^K:li#24:ll=\E=7\040:ma=^K^P^L\040:\
+ :nd=^L:pt:se=\EG0:sg#1:so=\EG4:ue=\EG0:up=^K:us=\EG8:xn:
+# From fair@ucbarpa Sun Oct 27 07:21:05 1985
+v6|ims950-b|bare ims950 no is:\
+ :is@:tc=ims950:
+v7|ims950-ns|ims950 w/no standout:\
+ :so@:se@:us@:ue@:tc=ims950:
+va|ims950|ims televideo 950 emulation:\
+ :k0@:k1@:k2@:k3@:k4@:k5@:k6@:k7@:k8@:k9@:kb@:kd@:kh@:kl@:ko@:kr@:ku@:\
+ :vb@:xn@:tc=tvi950:
+vd|ims950-rv|ims tvi950 rev video:\
+ :k0@:k1@:k2@:k3@:k4@:k5@:k6@:k7@:k8@:k9@:kb@:kd@:kh@:kl@:ko@:kr@:ku@:\
+ :vb@:xn@:tc=tvi950-rv:
+vx|ims-ansi|ultima2|ultimaII|IMS Ultima II:\
+ :pt:am:bs:co#80:li#24:\
+ :is=\E[0m\E[>14l\E[?1;?5;20l\E>\E[1m^M:if=/usr/lib/tabset/vt100:\
+ :cl=\E[;H\E[2J:cd=\E[0J:ce=\E[0K:cm=\E[%i%2;%2H:up=\EM:do=\ED:\
+ :ku=\E[A:kd=\E[B:kr=\E[C:kl=\E[D:kh=\E[H:\
+ :so=\E[7m:se=\E[0m\E[1m:us=\E[4m:ue=\E[0m\E[1m:sr=\EM:
+# # --------------------------------
+#
+# y: TELERAY
+#
+# Note two things called "teleray". Reorder should move the common one
+# to the front if you have either. A dumb teleray with the cursor stuck
+# on the bottom and no obvious model number is probably a 3700.
+y1|t3700|teleray|dumb teleray 3700:\
+ :do=^J:le=^H:bs:cl=^L:co#80:li#24:
+y3|t3800|teleray 3800 series:\
+ :do=^J:le=^H:bs:cd=\EJ:ce=\EK:cl=^L:cm=\EY%+ %+ :co#80: \
+ :do=\n:ho=\EH:li#24:ll=\EY7 :nd=\EC:pt:up=^K:
+y6|t1061|teleray 1061:\
+ :if=/usr/lib/tabset/teleray:\
+ :ct=\EG:st=\EF:do=^J:\
+ :al=2*\EL:am:le=^H:bs:cd=1\EJ:ce=\EK:cl=1^L:cm=\EY%+ %+ :co#80:\
+ :dc=\EQ:dl=2*\EM:ei=:ho=\EH:ic=\EP:im=:ip=0.4*:\
+ :k1=^Z1:k2=^Z2:k3=^Z3:k4=^Z4:k5=^Z5:k6=^Z6:k7=^Z7:k8=^Z8:\
+ :li#24:nd=\EC:pt:se=\ER@:so= \ERD:\
+ :is=\Ee\EU01^Z1\EV\EU02^Z2\EV\EU03^Z3\EV\EU04^Z4\EV\EU05^Z5\EV\EU06^Z6\EV\EU07^Z7\EV\EU08^Z8\EV\Ef:\
+ :up=\EA:us=\ERH:ue=\ER@:xs:xt:sg#2:ug#1:
+# "Teleray Arpa Special", offically designated as
+# "Teleray Arpa network model 10" with "Special feature 720".
+# This is the new (1981) fast microcode updating the older "arpa" proms
+# (which gave meta-key and pgmmable-fxn keys). 720 is much much faster,
+# converts the keypad to programmable function keys, and has other goodies.
+# Standout mode is still broken (magic cookie, etc) so is suppressed as no
+# programs handle such lossage properly.
+# Note: this is NOT the old termcap's "t1061f with fast proms."
+# From Univ of Utah, J.Lepreau Tue Feb 1 06:39:37 1983
+# lepreau@utah-cs, harpo!utah-cs!lepreau
+#
+y7|t10|teleray 10 special:\
+ :so@:se@:us@:ue@:\
+ :al=\EL:bs:cd=\EJ:ce=\EK:cl=30\Ej:cm=\EY%+ %+ :co#80:\
+ :dc=\EQ:dl=\EM:ei=:ho=\EH:ic=\EP:im=:km:li#24:nd=\EC:pc=\200:pt:\
+ :se=\ER@:so=\ERD:sf=\Eq:sg#2:sr=\Ep:up=\EA:ug#1:ue=\ER@:us=\ERH:\
+ :xs:xt:
+yf|t1061f|teleray 1061 with fast PROMs:\
+ :al=\EL:ip@:dl=\EM:tc=t1061:
+# Wyse 50 entry by Toni Guttman extended by Jeff Anton
+ye|w50|wyse50|Wyse 50:\
+ :al=\EE:am:bs:bt=\EI:cd=\EY:ce=\ET:cl=^Z:cm=\E=%+ %+ :co#80:\
+ :dc=\EW:dl=\ER:do=^J:ei=\Er:im=\Eq:is=\E`\072\200\EC\EDF\E0\E'\E(\EA21:\
+ :kd=^J:kl=^H:kr=^L:ku=^K:li#24:nd=^L:up=^K:us=\EG8:ue=\EG0:\
+ :so=\EG4:se=\EG0:sg#0:sr=\Ej:ho=^^:ug#0:
+# it is not known if the status line works with sysline
+yh|w50-s|wyse50-s|Wyse 50 for sysline
+ :hs:ts=\Ef:fs=\r:ds=\Ef\r:es:tc=w50:
+yg|w50-w|w50-132|wyse50-132|Wyse 50-132:\
+ :cm=\Ea%i%dR%dC:co#132:is=\E`;\200\EC\EDF\E0\E'\E(\EA21:tc=w50:
+# from John Gillmore hoptoad!gnu@lll-crg.arpa
+wv|wyse-vp|wyse|Wyse 50 in ADDS Viewpoint emulation mode with "enhance" on:\
+ :am:do=^J:if=/usr/lib/tabset/wyse-adds:\
+ :le=^H:bs:li#24:co#80:cm=\EY%+ %+ :cd=\Ek:ce=\EK:nd=^F:\
+ :up=^Z:cl=^L:ho=^A:ll=^A^Z:kl=^U:kr=^F:kd=^J:ku=^Z:kh=^A:\
+ :pt:so=^N:se=^O:us=^N:ue=^O:dl=\El:al=\EM:im=\Eq:ei=\Er:dc=\EW:\
+ :is=\E`\072\E`9^O\Er:rs=\E`\072\E`9^O\Er:
+wk|wyse-vp-nk|Wyse 50 in ADDS Viewpoint enhanced mode with cursor keys gone:\
+ :kl@:kr@:kd@:ku@:kh@:tc=wyse-vp:
+vw|wyse925|Wyse-50 emulating tvi925:\
+ :xn@:tc=tvi925:
+# wyse 75 series from JLarson.pa@xerox.arpa
+wx|wyse75|wy75|wyse 75 terminal :\
+ :co#80:li#24:cl=50\E[H\E[2J:bs:cm=5\E[%i%d;%dH:nd=\E[C:up=\E[A:\
+ :al=3\E[L:dl=3\E[M:ku=\E[A:kd=\E[B:kr=\E[C:kl=\E[D:do=\E[B:\
+ :ic=\E[@:ei=:im=:pt:bw:dc=\E[P:ce=3\E[K:ho=10\E[H:pt:\
+ :mi:nd=\E[C:bt=\E[Z:us=\E[8p:ue=\E[p:so=\E[5m:se=\E[m:\
+ :md=\E[1p:mr=\E[16p:mb=\E[2p:mk=\E[4p:me=\E[0p:hs:ll=\E[24;1H:\
+ :cd=50\E[J:cs=9\E[%i%d;%dr:ae=\E(B:as=\E(0:kh=\E[H:kb=^H:\
+ :k0=\EOP:k1=\EOQ:k2=\EOR:k3=\EOS:k4=\E[M:\
+ :k5=\E[17~:k6=\E[31~:k7=\E[18~:k8=\E[19~:k9=\E[20~:kn#10:\
+ :l0=PF1:l1=PF2:l2=PF3:l3=PF4:l4=F5:\
+ :l5=F6:l6=F7:l7=F8:l8=F9:l9=F10:\
+ :is=\E[1;24r\E[?10;3;1l\E[4l\E[?25h\E[m\E(B\E>:\
+ :ds=\E7\E[>,//\E8:ts=\E7\E[>,^A:fs=^A\E8:
+wx|wyse75-80|wy75-80|wyse 75 terminal with 80-column initialization:\
+ :is=\E[?3l:tc=wy75:
+wl|wyse75-132|wy75-132|wyse 75 terminal with 132 columns :\
+ :is=\E[?3h:co#132:tc=wy75:
+#
+# Wyse WY75 utilizing keypad
+#
+w5|wy75ap|wyse75ap|wy-75ap|wyse-75ap|Wyse WY-75 Applications and Cursor keypad:\
+ :is=\E[1;24r\E[?10;3l\E[?1;25h\E[4l\E[m\E(B\E=:\
+ :kd=\EOB:ke=10\E[?1l\E>:kh=\EOH:kl=\EOD:kr=\EOC:\
+ :ks=10\E[?1h\E=:ku=\EOA:\
+ :tc=wyse75:
+# from ucbvax!ucsfmis!shewmake
+Wc|wy85|wyse85|wyse-85:\
+ :do=^J:co#80:li#24:cl=\E[;H\E[2J:\
+ :le=^H:bs:cm=\E[%i%d;%dH:nd=\E[C:up=\E[A:\
+ :ce=\E[0K:cd=\E[0J:so=\E[7m:se=\E[27m:\
+ :us=\E[4m:ue=\E[24m:\
+ :is=\E[1;24r\E[24;1H\E[0m:\
+ :ks=\E[?1h\E=:ke=\E[?1l\E>:\
+ :ku=\EOA:kd=\EOB:kr=\EOC:kl=\EOD:kb=^H:\
+ :ho=\E[H:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:kh=\E[H"ta=^I:pt:sr=\EM:\
+ :sc=\E7:rc=\E8:cs=\E[%i%d;%dr:as=^N:ae=^O:bt=\E[Z:\
+ :dc=\E[P:dl=\E[M:al=\E[L:ei=\E[4l:im=\E[4h:\
+ :vb=\E[?5h\E[?5l:\
+ :hs:es:ts=\E7\E[?25l\E[40h\E[25;%dH\E[2K:fs=\E[1;24r\E8\E[?25h:
+#
+# # --------------------------------
+#
+# z: MISC (cont)
+#
+z0|wind:\
+ :bs:cm=\Ep%r%.%.:cl=\En\120\030\Eo:co#80:\
+ :ho=\Ep\200\200:li#24:nd=^L:up=^K:nl=\035:\
+ :kl=\E3:kr=\E4:ku=\E1:kd=\E2:k1=\E5:k2=\E6:k3=\E7:k4=\E8:\
+ :so=\Em\014:se=\Em\003:
+z1|wind16:\
+ :bs:cm=\Ep%r%.%.:cl=\En\120\020\Eo:co#80:\
+ :ho=\Ep\200\200:li#16:nd=^L:up=^K:nl=\035:\
+ :so=\Em\014:se=\Em\003:
+z2|wind40:\
+ :bs:cm=\Ep%r%.%.:cl=\En\120\050\Eo:co#80:\
+ :ho=\Ep\200\200:li#40:nd=^L:up=^K:nl=\035:\
+ :so=\Em\014:se=\Em\003:
+z3|wind50:\
+ :bs:cm=\Ep%r%.%.:cl=\En\128\062\Eo:co#88:\
+ :ho=\Ep\200\200:li#50:nd=^L:up=^K:nl=\035:\
+ :kl=\E3:kr=\E4:ku=\E1:kd=\E2:k1=\E5:k2=\E6:k3=\E7:k4=\E8:\
+ :so=\Em\014:se=\Em\003:
+z4|cad68-3|cgc3|cad68 basic monitor transparent mode size 3 chars:\
+ :am:bs:cl=^Z:co#73:ho=\036:li#36:nd=^L:up=^K:
+z5|cad68-2|cgc2|cad68 basic monitor transparent mode size 2 chars:\
+ :am:bs:cl=^Z:co#85:ho=\036:li#39:nd=^L:up=^K:\
+ :kl=\E3:kr=\E4:ku=\E1:kd=\E2:k1=\E5:k2=\E6:k3=\E7:k4=\E8:\
+ :so=\Em\014:se=\Em\003:
+z6|v50|visual 50:\
+ :am:bs:al=\EL:dl=\EM:\
+ :cd=\Ek:ce=\EK:cl=^Z:cm=\E=%+\040%+\040:co#80:do=^J:ho=\EH:\
+ :kb=^H:kd=\EB:kh=\EH:kl=\ED:kr=\EC:ku=\EA:li#24:ms:nd=^L:pt:\
+ :so=\EU:se=\ET:up=^K:
+z7|trs2|trsII|trs80II|Radio Shack Model II using P&T CP/M:\
+ :nl=^_:al=^D:am:bs:cd=^B:ce=^A:cl=^L:cm=\EY%+ %+ :co#80:\
+ :dl=^K:do=^_:ho=^F:li#24:nd=^]:ms:pt:se=^O:so=^N:up:=^^:\
+ :kb=^H:kd=^_:kl=^\:kr=^]:ku=^^:
+z8|apollo:\
+ :al=\EI:am:bs:cd=\EJ:ce=\EK:ch=\EN%d:cl=^L:cm=\EM%+ %d):\
+ :cv=\EO+ :dc=\EP:dl=\EL:do=\EB:ei=\ER:im=\EQ:mi:nd=\EC:se=\ET:sf=\EE:\
+ :so=\ES:sr=\ED:te=\EX:ti=\EW:ue=\EV:ul:up=\EA:us=\EU:co#88:li#53:
+z9|ps300|Picture System 300:us@:ue@:so@:se@:xt:pt@:tc=vt100:
+za|masscomp2:co#64:li#21:tc=masscomp:
+zb|masscomp1:co#104:li#36:tc=masscomp:
+zc|masscomp:\
+ :al=\E[L:bs:cd=\E[J:ce=\E[K:co#80:dc=\E[P:dl=\E[M:do=\E[B:\
+ :ei=\E[4l:im=\E[4h:is=\EGc\EGb\EGw:li#24:mi:MT:nd=\E[C:pt:se=\E[0m:\
+ :sg#0:so=\E[7m:cm=\E[%i%d;%dH:ue=\EGau:us=\EGu:up=\E[A:\
+ :ku=\EOA:kd=\EOB:kr=\EOC:kl=\EOD:kb=^h:cl=\E[2J:
+# Kimtron TC entries include (undocumented) codes for: enter dim mode (mh),
+# enter bold mode (md), enter reverse mode (mr), turn off all attributes (me)
+# Kimtron ABM 85 added by Dual Systems
+zd|abm85|Kimtron ABM 85:\
+ :is=\EC\EX\Eg\En\E%\Er\E(\Ek\Em\Eq:if=/usr/lib/tabset/stdcrt:\
+ :li#24:co#80:am:bs:bw:ms:pt:\
+ :cl=\E*:cd=\Ey:dl=\ER:al=\EE:ce=\Et:dc=\EW:im=\EQ:ei=\Er:\
+ :cm=\E=%+ %+ :do=^J:nd=^L:up=^K:bt=\EI:\
+ :kh=^^:kb=^H:kd=^J:ku=^K:kd=^J:kl=^H:kr=^L:\
+ :so=\Ej:se=\Ek:sg#1:us=\El:ue=\Em:ug#1:
+# Kimtron ABM 85H added by Dual Systems.
+# Some notes about the 85h entries:
+# 1) there are several firmware revs of 85H in the world. Use o85h for
+# firmware revs prior to SP51
+# 2) Make sure to use 85h entry if the terminal is in 85H mode and the
+# 85e entry if it is in 920 emulation mode. They are incompatible in
+# some places and NOT software settable i.e., `is' can't fix change it)
+# 3) In 85h mode, the arrow keys and special functions transmit when
+# the terminal is in dup-edit, and work only locally in local-edit.
+# Vi won't swallow `del char' for instance, but `vs' turns on
+# dup-edit anyway so that the arrow keys will work right. If the
+# arrow keys don't work the way you like, change `vs', `ve', and `is'.
+# 920E mode does not have software commands to toggle between dup
+# and local edit, so you get whatever was set last on the terminal.
+# 4) vb attribute is nice, but seems too slow to work correctly (\Eb<pad>\Ed)
+# 5) Make sure `hidden' attributes are selected. If `embedded' attributes
+# are selected, the entries :sg@: and :ug@: should be removed.
+# 6) auto new-line should be on (selectable from setup mode only)
+#
+# From fair@ucbarpa Sun Oct 27 07:21:05 1985
+ze|85h|85H|abm85h|Kimtron ABM 85H, 85H mode:\
+ :is=\EC\EN\EX^T^N\EA\Ea\E%\E9\Ee\Er\En\E"\E}\E'\E(\Ef^M\EG0\Ed\E.4\El:\
+ :im=\EZ:kd=^V:so=\EG4:se=\EG0:us=\EG8:ue=\EG0:vb@:vs=\E.2:ve=\E.4:\
+ :mh=\E):mr=\EG4:me=\E(\EG0:sg@:ug@:ds=\Ee:fs=^M:hs:ts=\Eg\Ef:tc=abm85:
+zf|85e|85E|abm85e|Kimtron ABM 85H, 920E mode:\
+ :is=\EC\EX\EA\E%\E9\Ee\Er\En\E"\E}\E'\E(\Ef^M\Ek\Eq\Em:\
+ :mh=\E):mr=\Ej:me=\E(\Ek:im=\EZ:sg@:ug@:vb@:tc=abm85:
+zg|o85h|oabm85h|Kimtron ABM 85H, old firmware rev.:\
+ :is=\E}\EC\EX\Ee\En\E%\Er\E(\Ek\Em\Eq\Ed\ET\EC\E9\EF:\
+ :im=\EZ:sg@:ug@:vb=\200\200\200^G\200\200\200:\
+ :mh=\E):mr=\Ej:me=\E(\Ek:tc=abm85:
+#from malman@bbn-vax.arpa
+zE|kt7|kimtron model kt-7:\
+ :am:bs:co#80:li#24:cm=\E=%+ %+ :cl=^Z:cd=\EY:ce=\ET:is=\El\E":\
+ :al=\EE:dl=\ER:im=:ei=:ic=\EQ:dc=\EW:if=/usr/lib/tabset/stdcrt:\
+ :ho=^^:nd=^L:bt=\EI:pt:so=\EG4:se=\EG0:sg#0:us=\EG8:ue=\EG0:ug#0:\
+ :up=^K:do=^V:kb=^H:ku=^K:kd=^V:kl=^H:kr=^L:kh=^^:ma=^V^J^L :\
+ :k1=^A@\r:k2=^AA\r:k3=^AB\r:k4=^AC\r:k5=^AD\r:k6=^AE\r:k7=^AF\r:\
+ :k8=^AG\r:k9=^AH\r:k0=^AI\r:ko=ic,dc,al,dl,cl,ce,cd,bt:\
+ :ts=\Ef:fs=\Eg:
+zh|appleII|apple ii plus:vs=\024\103\066:ve=\024\103\062:\
+ :am:co#80:ce=\035:li#24:cl=\014:bs:nd=\034:up=\037:ho=\E\031:pt:\
+ :cd=\013:so=\017:se=\016:cm=\036%r%+ %+ :is=\024T1\016:do=^J:kd=^J:\
+ :vb=\024G1\024T1:kr=:
+# Gary Ford 21NOV83
+# New version from ee178aci%sdcc7@SDCSVAX.ARPA Fri Oct 11 21:27:00 1985
+zi|apple-80|apple II with smarterm 80 col:\
+ :am:bs:bt=^R:bw:cd=10*^K:ce=10^]:cl=10*^L:cm=^^%r%+ %+ :\
+ :co#80:cr=10*^M:do=^J:ho=^Y:le=^H:li#24:nd=^\\:up=^_:
+#
+zj|lisa|apple lisa xenix console display (white on black):\
+ :al=\E[L:am:bs:cd=\E[J:ce=\E[K:cl=^L:cm=\E[%i%d;%dH:co#88:\
+ :dc=\E[P:dl=\E[M:dn=\E[B:ei=:ho=\E[H:ic=\E[@:im=:li#32:\
+ :nd=\E[C:ms:pt:so=\E[m:se=\E[7m:us=\E[4m:ue=\E[7m:up=\E[A:\
+ :kb=^h:ku=\E[A:kd=\E[B:kl=\E[D:kr=\E[C:eo:\
+ :is=\E[7m^L:GS=\E[11m:GE=\E[10m:GV=\140:GH=a:G1=c:\
+ :G2=f:G3=e:G4=d:GU=u:GD=s:GC=b:GL=v:GR=t:
+# The following is a version of the ibm-pc entry distributed with PC/IX,
+# (Interactive Systems' System 3 for the Big Blue), modified by Richard
+# McIntosh at UCB/CSM. The :pt: and :uc: have been removed from the original,
+# (the former is untrue, and the latter failed under UCB/man); standout and
+# underline modes have been added. Note: this entry describes the "native"
+# capabilities of the PC monochrome display, without ANY emulation; most
+# communications packages (but NOT PC/IX connect) do some kind of emulation.
+pc|ibmpc|ibm pc PC/IX:\
+ :li#24:co#80:am:bs:bw:eo:\
+ :cd=\E[J:ce=\E[K:cl=\Ec:cm=\E[%i%2;%2H:do=\E[B:ho=\E[;H:\
+ :nd=\E[C:up=\E[A:so=\E[7m:se=\E[0m:us=\E[4m:ue=\E[0m:
+zk|ibmx|ibmpcx|IBM PC xenix console display:\
+ :al=\E[L:am:bs:cd=\E[J:ce=\E[K:cl=^L:cm=\E[%d;%dH:co#80:\
+ :dc=\E[P:dl=\E[M:dn=\E[B:ei=:ho=\E[H:ic=\E[@:im=:li#25:\
+ :nd=\E[C:ms:se=\E[0m:so=\E[7m:us=\E[4m:\
+ :ue=\E[m:up=\E[A:MR=\E[0m:\
+ :kb=^h:kh=\E[Y:ku=\E[A:kd=\E[B:kl=\E[D:kr=\E[C:eo:\
+ :GS=\E[11m:GE=\E[10m:\
+ :GC=b:GL=v:GR=t:RT=^J:\
+ :GH=\E[196g:GV=\E[179g:\
+ :GU=\E[193g:GD=\E[194g:\
+ :G1=\E[191g:G2=\E[218g:G3=\E[192g:G4=\E[217g:\
+ :CW=\E[E:NU=\E[F:RF=\E[G:RC=\E[H:\
+ :WL=\E[K:WR=\E[L:CL=\E[M:CR=\E[N:\
+ :HM=\E[Y:EN=\E[d:PU=\E[Z:PD=\E[e:
+zl|ibmc|ibmcpc|IBM PC xenix color console display:\
+ :tc=ibm:
+zl|ibmcx|ibmcpcx|IBM PC xenix color console display:\
+ :tc=ibmx:
+zm|kaypro|kaypro2|kaypro II:\
+ :am:bs:cm=\E=%+ %+ :cl=1^Z:co#80:ho=^^:li#24:ma=^K^P:nd=^L:up=^K:\
+ :kr= :kl=^H:ku= :kd=^J:
+# From Suk Lee ..!{decvax,linus,allegra,ihnp4}!utcsrgv!spoo
+zn|trs100|Radio Shack Model 100:\
+ :am:bs:le=^H:li#8:co#40:ku=^^:kd=^_:kl=^]:kr=^\:up=\EA:\
+ :nd=\EC:ho=\EH:ce=\EK:cd=\EJ:cl=\EE:xt:cm=\EY%+ %+ :\
+ :so=\Ep:se=\Eq:al=\EL:dl=\EM:
+zt|mac|macintosh|Macintosh with MacTerminal:\
+ :al=20\E[L:dl=20\E[M:ip=7:dc=7\E[P:ic=9\E[@:xn:dN#30:tc=vt100:
+zs|zen50|z50:zephyr:\
+ :cm=\E=%+ %+ :cd=\EY:co#80:li#24:\
+ :am:al=\EE:ce=\ET:dc=\EW:dl=\ER:ic=\EQ:im=:ei=:\
+ :cl=\E+:bs:ma=^Hh^Ll^Jj^Kk:sg#1:se=\EGO:so=\EG4:\
+ :kl=^H:kr=^L:ku=^K:kd=^J:kh=\036:up=^K:\
+ :BS=^U:CL=^V:CR=^B:RK=^L:UK=^K:LK=^H:DK=^J:HM=\036:
+zu|go140|graphon go-140:\
+ :co#80:li#24:cl=10\E[;H\E[2J:bs:cm=\E[%i%2;%2H:nd=\E[C:up=\E[A:\
+ :ce=\E[K:cd=10\E[J:so=\E[7m:se=\E[m:us=\E[4m:ue=\E[m:\
+ :is=\E<\E=\E[?3l\E[?7l\E(B\E[J\E7\E[;r\E8\E[m\E[q:\
+ :dl=\E[M:al=\E[L:dc=\E[P:im=\E[4h:ei=\E[4l:\
+ :ks=\E[?1h\E=:ke=\E[?1l\E>:\
+ :if=/usr/lib/tabset/vt100:ku=\EOA:kd=\EOB:kr=\EOC:kl=\EOD:\
+ :kh=\E[H:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:pt:sr=\EM:
+zv|go140w|graphon go-140 in 132 column mode:\
+ :co#132:is=\E<\E=\E[?3h\E[?7h\E(B\E[J\E7\E[;r\E8\E[m\E[q:\
+ :tc=go140:
+zw|sanyo55|sanyo|sanyo mbc-55x pc compatible:\
+ :co#80:li#25:am:cl=\E[H\E[J:bs:cm=\E[%i%d;%dH:nd=\E[C:up=\E[A:\
+ :ce=\E[K:cd=\E[J:so=\E[7m:se=\E[m:us=\E[4m:ue=\E[m:
+#From: Simson L. Garfinkel <simsong@media-lab.mit.edu>
+st|ST|atari st:\
+ :bs:cd=\EJ:ce=\EK:cl=\EH\EJ:cm=\EY%+ %+ :co#80:li#25:nd=\EC:\
+ :pt:sr=\EI:up=\EA:ku=\EA:kd=\EB:kr=\EC:kl=\ED:\
+ :do=\EB:\
+ :so=\Ep:se=\Eq:dl=\EM:al=\EL:am:
+# YTERM standard version 1.0. (gts 9-25-84)
+# Straight old ascii keyboard except function keys are Yale (e.g.,ASCII.KBD).
+# Only 80 tab columns (else yterm 1.1 bug). No :xn: in 1.0.
+# Cannot use termcap :sr=\EM: because vi will not work, too bad.
+# vi string is given so that yterm is reset each vi startup.
+Y0|yterm10|yterm 1.0 UCB ascii.kbd:\
+ :am:bs:cd=^K:ce=^]:cl=^L:cm=^^%r%+ %+ :co#80:EP:ho=^Y:li#24:nd=^\:pt:\
+ :rc=\E8:sc=\E7:so=\E[7m:se=\E[m:up=^_:us=\E[4m:ue=\E[m:\
+ :is=^O\E[7i\E[m\E[?7h\E[?3g\r\EHY0 for \EHYTERM 1.\EH0 with A\EHSCII.KBD\EH 9-13-84\EH \EH \EH \EH \EH\n:\
+ :ku=^K:kd=^J:kl=^H:kr=^L:kh=^^:ma=h\012j k lH:\
+ :k0=\E0:k1=\E1:k2=\E2:k3=\E3:k4=\E4:k5=\E5:k6=\E6:k7=\E7:k8=\E8:k9=\E9:\
+ :vs=^O\E[7i\E[m\E[?7h\E[?3g\r\EHY0 \EH \EH \EH \EH \EH \EH \EH \EH \EH\r:
+# YTERM varient version 1.1. (gts 9-13-84) Version 1.1 has :xn:.
+Y1|yterm11|yterm 1.1 UCB ascii.kbd:\
+ :xn:is=^O\E[7i\E[m\E[?7h\E[?3g\r\EHY1 for \EHYTERM 1.\EH1 with A\EHSCII.KBD\EH 9-13-84\EH \EH \EH \EH \EH\n:\
+ :tc=yterm10
+# YTERM 1.0 varient no autowrap or tabs
+# X does not remember autowrap or tabs when T is deleted and restarted.
+Y2|yterm10nat|yterm 1.0 UCB ascii.kbd no autowrap or tabs:\
+ :am@:pt@:vs=^O\E[7i\E[m\E[?7l\E[?3g\rY2\r:\
+ :is=^O\E[7i\E[m\E[?7l\E[?3g\rY2 for YTERM 1.0 with ASCII.KBD 9-20-84 no autowrap or tabs\n:\
+ :tc=yterm10
+# KERMIT standard all versions. (gts 9-25-84)
+# Straight ascii keyboard. :sr=\EI: not avail. many versions + bug prone in vi.
+K0|kermit|standard kermit:\
+ :bs:cd=\EJ:ce=\EK:cl=\EE:cm=\EY%+ %+ :co#80:ho=\EH:li#24:nd=\EC:up=\EA:\
+ :ku=^K:kd=^J:kl=^H:kr=^L:kh=^^:ma=^Hh\012j^Kk^Ll^^H:\
+ :is=K0 Standard Kermit 9-25-84\n:
+K1|kermitam|standard kermit plus am:\
+ :am:is=K1 Standard Kermit plus Automatic Margins\n:tc=kermit:
+# IBMPC Kermit 1.2. (gts 8-30-84)
+# Bugs :cd:ce: do not work except at beginning of line! :cl: does not work,
+# but fake with :cl=\EH\EJ (since :cd=\EJ: works at beginning of line).
+K2|pckermit|pckermit12|UCB IBMPC Kermit 1.2:\
+ :am:li#25:cd@:ce@:cl=\EH\EJ:\
+ :is=K2 UCB IBMPC Kermit 1.2 8-30-84\n:tc=kermit:
+# IBMPC Kermit 1.20 (gts 12-19-84)
+# Cannot use line 25, now acts funny like ansi special scrolling region.
+# Initialization must escape from that region by cursor position to line 24.
+# Cannot use character insert because 1.20 goes crazy if insert at col 80.
+# Does not use am: because autowrap mode lost when kermit dropped and restarted.
+K3|pckermit120|UCB IBMPC Kermit 1.20:\
+ :al=\EL:am@:dc=\EN:dl=\EM:do=\EB:ei@:im@:li#24:pt:se=\Eq:so=\Ep:\
+ :is=\EO\Eq\EJ\EY7 K3 UCB IBMPC Kermit 1.20 12-19-84\n:\
+ :vs=\EO\Eq\EEK3:tc=kermit:
+# MS-DOS Kermit 2.27 for the IBMPC (UCB gts 3-17-85)
+# Straight ascii keyboard. :sr=\EI: not avail. many versions + bug prone in vi.
+# Cannot use line 25, now acts funny like ansi special scrolling region.
+# Initialization must escape from that region by cursor position to line 24.
+# Does not use am: because autowrap mode lost when kermit dropped and restarted.
+# Reverse video for standout like H19.
+K4|mskermit227|msk227|MS-DOS Kermit 2.27 for the IBMPC:\
+ :al=\EL:am@:bs:cd=\EJ:ce=\EK:cl=\EE:cm=\EY%+ %+ :co#80:\
+ :dc=\EN:dl=\EM:do=\EB:ei=\EO:im=\E@:\
+ :ho=\EH:li#24:nd=\EC:up=\EA:pt:rc=\Ek:sc=\Ej:se=\Eq:so=\Ep:\
+ :ku=^K:kd=^J:kl=^H:kr=^L:kh=^^:ma=^Hh\012j^Kk^Ll^^H:\
+ :is=\EO\Eq\EG\Ew\EJ\EY7 K4 MS Kermit 2.27 for the IBMPC 3-17-85\n:\
+ :vs=\EO\Eq\EG\EwK4:
+# MS-DOS Kermit 2.27 with automatic margins (UCB gts 3-17-85)
+K5|mskermit227am|msk227am|UCB MS-DOS Kermit 2.27 with automatic margins:\
+ :am:\
+ :is=\EO\Eq\EG\Ev\EJ\EY7 K5 MS Kermit 2.27 +automatic margins 3-17-85\n:\
+ :vs=\EO\Eq\EG\EvK5:tc=mskermit227:
+# MS-DOS Kermit 2.27 UCB 227.14 for the IBM PC (UCB gts 3-17-85)
+# Automatic margins now default. Use ansi set graphic rendition for standout,
+# underline and ul codes (md,me,mr). Define function keys.
+K6|mskermit22714|msk22714|UCB MS-DOS Kermit 2.27 UCB 227.14 IBM PC:\
+ :am:kn#10:\
+ :k0=\E0:k1=\E1:k2=\E2:k3=\E3:k4=\E4:k5=\E5:k6=\E6:k7=\E7:k8=\E8:k9=\E9:\
+ :md=\E[1m:me=\E[m:mr=\E[7m:se=\E[m:so=\E[1m:ue=\E[m:us=\E[4m:\
+ :is=\EO\Eq\EG\Ev\EJ\EY7 K6 MS Kermit 2.27 UCB 227.14 IBM PC 3-17-85\n:\
+ :vs=\EO\Eq\EG\EvK6:tc=mskermit227:
+# From earle@smeagol.UUCP 29 Oct 85 05:40:18 GMT
+# MS-Kermit with Heath-19 emulation mode enabled
+Kh|h19kermit|h19k|heathkit emulation provided by Kermit (no auto margin):\
+ :am@:ta@:pt@:xt:da:db:tc=h19-u:
+# rough draft of Amiga termcap by Mike Meyer
+AA|amiga|Amiga ANSI:\
+ :co#80:li#25:am:do=\E[B:ce=\E[K:cd=\E[J:\
+ :cl=\E[H\E[J:ku=\E[A:kd=\E[B:kl=\E[C:kr=\E[D:kb=^H:\
+ :al=\E[L:dl=\E[M:le=^H:cm=\E[%i%d;%dH:nd=\E[C:up=\E[A:\
+ :ce=\E[K:ho=\E[H:dc=\E[P:ic=\E[@:\
+ :so=\E[2m:se=\E[m:us=\E[4m:ue=\E[m:mr=\E[7m:mb=\E[7;2m:me=\E[m:
+# The pcplot IBM-PC terminal emulation program is really messed up. It is
+# supposed to emulate a vt-100, but emulates the wraparound bug incorrectly,
+# doesn't support scrolling regions, ignores add line commands, and ignores
+# delete line commands. Consequently, the resulting behavior looks like a
+# crude adm3a-type terminal.
+# Steve Jacobson 8/85
+pp|pcplot:\
+ :cs@:sc@:rc@:xn@:tc=vt100:
+# From Joel Rubin, jmrubin@coral, a preliminary TERMCAP for VIDTEX,
+# a terminal program sold by Compuserve. Line and column numbers are
+# computer-dependent (I have a Commodore '64); you should use the meta-B
+# option to shut off clean-breaking of lines. No key codes included
+# since some of them are programmable and most are machine-specific.
+# Works on vi if you don't use clean-breaking. Very similar to the IBM 3101
+# termcap. Escape-D used for backspace because control-H is destructive
+# backspace. There seem to be a few weirdnesses (especially at the beginning
+# of a wrapped line), and the cursor does not, unfortunately, flash.
+zQ|vid|vidtex|Compuserve vidtex program:\
+ :am:bc=\ED:cl=^L:li#25:co#40:nd=\EC:up=\EA:cd=\EJ:ce=\EK:\
+ :ho=\EH:cm=\EY%+\40%+\40:pt:
+# Fortune from c160-3bp@Coral (Robert Nathanson) via tut Wed Oct 5, 1983
+zK|fos|fortune|Fortune system:\
+ :is=^_..:li#25:co#80:am:bs:bw:cl=20^L:cd=3*^\Y:\
+ :ic=5^\Q:dc=5^\W:dl=15^\R:al=15^\E:cm=^\C%+ %+ :ta=^Z:ho=10^^:do=3^J:\
+ :up=3^K:bs=^H:kb=^H:kd=^Ay\r:kh=^A?\r:kl=^Aw\r:kr=^Az\r:ku=^Ax\r:\
+ :nl=5^J:so=^\H`:se=^\I`:sg=0:us=^\HP:ue=^\IP:ug=0:ce=^\Z:rv=\EH:re=\EI:\
+ :rg=0:GS=\Eo:GE=^O:GG=0:GV=-:GH=&:GU=%:GD=#:G1=(:G2= :G3=":G4=*:CF=\E]:\
+ :CO=\E\\:WL=^Aa\r:WR=^Ab\r:CL=^Ac\r:CR=^Ad\r:DL=^Ae\r:RF=^Af\r:\
+ :RC=^Ag\r:CW=^Ah\r:NU=^Aj\r:EN=^Ak\r:HM=^Al:PL=^Am\r:PU=^An\r:PD=^Ao\r:\
+ :PR=^Ap\r:HP=^A@\r:RT=^Aq\r:TB=\r:CN=\177:MP=\E+F:
+# basis from Peter Harrison, Computer Graphics Lab, San Francisco
+# ucbvax!ucsfmis!harrison ...uucp / ucbvax!ucsfmis!harrison@BERKELEY ...ARPA
+ba|basis|BASIS108 computer with terminal translation table active:\
+ :do=5000^J:nl=5000*^J:\
+ :cd=\EY:ce=\ET:cl=300\E*:ma=^K^P^R^L^L :\
+ :kb=^H:kl=^H:ku=^K:kr=^L:kd=^J:so=\E(:se=\E):tc=adm3a:
+# From Peter Harrison, Computer Graphics Lab, San Francisco
+# ucbvax!ucsfmis!harrison .....uucp
+# ucbvax!ucsfmis!harrison@BERKELEY .......ARPA
+# "These two work. If you don't have the inverse video chip for the
+# Apple with videx then remove the so and se fields."
+zO|DaleApple|Apple with videx videoterm 80 column board with inverse video:\
+ :do=^J:am:le=^H:bs:cd=^K:ce=^]:cl=300^L:cm=^^%r%+ %+ :co#80:ho=^Y:\
+ :kd=^J:kl=^H:kr=^U:kh=^Y:\
+ :li#24:nd=^\:pt:so=^Z3:se=^Z2:up=^_:xn:
+zJ|ibmaed|IBM Experimental display:\
+ :al=\EN:am:bs:cd=\EJ:ce=\EI:cl=\EH\EK:cm=\EY%+\40%+\40:co#80:\
+ :dc=\EQ:dl=\EO:do=\EB:ei=:ho=\EH:ic=\EP:im=:li#52:\
+ :nd=\EC:ms:so=\E0:se=\E0:us=:ue=:up=\EA:\
+ :kb=^h:ku=\EA:kd=\EB:kl=\ED:kr=\EC:eo:vb=\EG:pt:
+# funny terminal that the TANDEM uses.
+zA|653|t653x|Tandem 653x multipage terminal:\
+ :li#24:co#80:ho=\EH:cm=\023%+ %+ :cl=\EI:cd=\EJ:ce=\EK:am:bs:\
+ :if=/usr/lib/tabset/tandem653:sb=\ES:sr=\ET:da:db:so=\E6$:se=\E6 :\
+ :us=\E60:ue=\E6 :sg#1:ug#1:up=\EA:do=\012:le=\010:nd=\EC:\
+ :hs:ts=\Eo:fs=\r:ds=\Eo\r:ws#64:
+#
+# END OF TERMCAP
+# ------------------------
diff --git a/lib-src/test-distrib.c b/etc/test-distrib.c
index e1f5be11861..e1f5be11861 100644
--- a/lib-src/test-distrib.c
+++ b/etc/test-distrib.c
diff --git a/etc/testfile b/etc/testfile
new file mode 100644
index 00000000000..8230c35f405
--- /dev/null
+++ b/etc/testfile
Binary files differ
diff --git a/etc/ulimit.hack b/etc/ulimit.hack
new file mode 100644
index 00000000000..1baeecc40db
--- /dev/null
+++ b/etc/ulimit.hack
@@ -0,0 +1,38 @@
+#!/bin/sh
+#
+# ulimit.hack: Create an intermediate program for use in
+# between kernel initialization and init startup.
+# This is needed on a 3b system if the standard CDLIMIT is
+# so small that the dumped Emacs file cannot be written.
+# This program causes everyone to get a bigger CDLIMIT value
+# so that the dumped Emacs can be written out.
+#
+# Users of V.3.1 and later should not use this; see etc/MACHINES
+# and reconfig your kernel's CDLIMIT parameter instead.
+#
+# Caveat: Heaven help you if you screw this up. This puts
+# a new program in as /etc/init, which then execs the real init.
+#
+cat > ulimit.init.c << \EOF
+main(argc, argv)
+int argc;
+char *argv[];
+{
+ ulimit(2, 262144L); /* "2" is the "set" command. */
+ /* 262,144 allows for 128Mb files to be written. */
+ /* If that value isn't suitable, roll your own. */
+ execv("/etc/real.init", argv);
+}
+EOF
+#
+# Compile it and put it in place of the usual init program.
+#
+cc ulimit.init.c -o ulimit.init
+mv /etc/init /etc/real.init
+mv ulimit.init /etc/ulimit.init
+ln /etc/ulimit.init /etc/init
+mv ulimit.init.c /etc/ulimit.init.c # to keep src for this hack nearby.
+chmod 0754 /etc/init
+exit 0
+#
+# Upon system reboot, all processes will inherit the new large ulimit.
diff --git a/etc/vipcard.tex b/etc/vipcard.tex
new file mode 100644
index 00000000000..62c5677ff37
--- /dev/null
+++ b/etc/vipcard.tex
@@ -0,0 +1,680 @@
+% Quick Reference Card for VIP 3.5 under GNU Emacs version 18 on Unix systems
+%**start of header
+\newcount\columnsperpage
+
+% This file can be printed with 1, 2, or 3 columns per page (see below).
+% Specify how many you want here. Nothing else needs to be changed.
+
+\columnsperpage=1
+
+% Copyright (c) 1987 Free Software Foundation, Inc.
+
+% This file is part of GNU Emacs.
+
+% GNU Emacs is free software; you can redistribute it and/or modify
+% it under the terms of the GNU General Public License as published by
+% the Free Software Foundation; either version 1, or (at your option)
+% any later version.
+
+% GNU Emacs is distributed in the hope that it will be useful,
+% but WITHOUT ANY WARRANTY; without even the implied warranty of
+% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+% GNU General Public License for more details.
+
+% You should have received a copy of the GNU General Public License
+% along with GNU Emacs; see the file COPYING. If not, write to
+% the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+% This file is intended to be processed by plain TeX (TeX82).
+%
+% The final reference card has six columns, three on each side.
+% This file can be used to produce it in any of three ways:
+% 1 column per page
+% produces six separate pages, each of which needs to be reduced to 80%.
+% This gives the best resolution.
+% 2 columns per page
+% produces three already-reduced pages.
+% You will still need to cut and paste.
+% 3 columns per page
+% produces two pages which must be printed sideways to make a
+% ready-to-use 8.5 x 11 inch reference card.
+% For this you need a dvi device driver that can print sideways.
+% Which mode to use is controlled by setting \columnsperpage above.
+%
+% Author:
+% Masahiko Sato
+% Internet: ms@sail.stanford.edu
+% Junet: masahiko@sato.riec.tohoku.junet
+%
+% The original TeX code for formatting the reference card was written by:
+% Stephen Gildea
+% UUCP: mit-erl!gildea
+% Internet: gildea@erl.mit.edu
+
+
+\def\versionnumber{1.2}
+\def\year{1987}
+\def\version{September \year\ v\versionnumber}
+
+\def\shortcopyrightnotice{\vskip 1ex plus 2 fill
+ \centerline{\small \copyright\ \year\ Free Software Foundation, Inc.
+ Permissions on back. v\versionnumber}}
+
+\def\copyrightnotice{
+%\vskip 1ex plus 2 fill\begingroup\small
+\vskip 1ex \begingroup\small
+\centerline{Copyright \copyright\ \year\ Free Software Foundation, Inc.}
+\centerline{designed by Masahiko Sato, \version}
+\centerline{for VIP 3.5 under GNU Emacs version 18 on Unix systems}
+
+Permission is granted to make and distribute copies of
+this card provided the copyright notice and this permission notice
+are preserved on all copies.
+
+For copies of the GNU Emacs manual, write to the Free Software
+Foundation, Inc., 1000 Massachusetts Ave, Cambridge MA 02138.
+
+\endgroup}
+
+% make \bye not \outer so that the \def\bye in the \else clause below
+% can be scanned without complaint.
+\def\bye{\par\vfill\supereject\end}
+
+\newdimen\intercolumnskip
+\newbox\columna
+\newbox\columnb
+
+\def\ncolumns{\the\columnsperpage}
+
+\message{[\ncolumns\space
+ column\if 1\ncolumns\else s\fi\space per page]}
+
+\def\scaledmag#1{ scaled \magstep #1}
+
+% This multi-way format was designed by Stephen Gildea
+% October 1986.
+% Slightly modified by Masahiko Sato, September 1987.
+\if 1\ncolumns
+ \hsize 4in
+ \vsize 10in
+ %\voffset -.7in
+ \voffset -.57in
+ \font\titlefont=\fontname\tenbf \scaledmag3
+ \font\headingfont=\fontname\tenbf \scaledmag2
+ \font\miniheadingfont=\fontname\tenbf \scaledmag1 % masahiko
+ \font\smallfont=\fontname\sevenrm
+ \font\smallsy=\fontname\sevensy
+
+ \footline{\hss\folio}
+ \def\makefootline{\baselineskip10pt\hsize6.5in\line{\the\footline}}
+\else
+ %\hsize 3.2in
+ %\vsize 7.95in
+ \hsize 3.41in % masahiko
+ \vsize 8in % masahiko
+ \hoffset -.75in
+ \voffset -.745in
+ \font\titlefont=cmbx10 \scaledmag2
+ \font\headingfont=cmbx10 \scaledmag1
+ \font\miniheadingfont=cmbx10 % masahiko
+ \font\smallfont=cmr6
+ \font\smallsy=cmsy6
+ \font\eightrm=cmr8
+ \font\eightbf=cmbx8
+ \font\eightit=cmti8
+ \font\eightsl=cmsl8
+ \font\eighttt=cmtt8
+ \font\eightsy=cmsy8
+ \textfont0=\eightrm
+ \textfont2=\eightsy
+ \def\rm{\eightrm}
+ \def\bf{\eightbf}
+ \def\it{\eightit}
+ \def\sl{\eightsl} % masahiko
+ \def\tt{\eighttt}
+ \normalbaselineskip=.8\normalbaselineskip
+ \normallineskip=.8\normallineskip
+ \normallineskiplimit=.8\normallineskiplimit
+ \normalbaselines\rm %make definitions take effect
+
+ \if 2\ncolumns
+ \let\maxcolumn=b
+ \footline{\hss\rm\folio\hss}
+ \def\makefootline{\vskip 2in \hsize=6.86in\line{\the\footline}}
+ \else \if 3\ncolumns
+ \let\maxcolumn=c
+ \nopagenumbers
+ \else
+ \errhelp{You must set \columnsperpage equal to 1, 2, or 3.}
+ \errmessage{Illegal number of columns per page}
+ \fi\fi
+
+ %\intercolumnskip=.46in
+ \intercolumnskip=.19in % masahiko .19x4 + 3.41x3 = 10.99
+ \def\abc{a}
+ \output={%
+ % This next line is useful when designing the layout.
+ %\immediate\write16{Column \folio\abc\space starts with \firstmark}
+ \if \maxcolumn\abc \multicolumnformat \global\def\abc{a}
+ \else\if a\abc
+ \global\setbox\columna\columnbox \global\def\abc{b}
+ %% in case we never use \columnb (two-column mode)
+ \global\setbox\columnb\hbox to -\intercolumnskip{}
+ \else
+ \global\setbox\columnb\columnbox \global\def\abc{c}\fi\fi}
+ \def\multicolumnformat{\shipout\vbox{\makeheadline
+ \hbox{\box\columna\hskip\intercolumnskip
+ \box\columnb\hskip\intercolumnskip\columnbox}
+ \makefootline}\advancepageno}
+ \def\columnbox{\leftline{\pagebody}}
+
+ \def\bye{\par\vfill\supereject
+ \if a\abc \else\null\vfill\eject\fi
+ \if a\abc \else\null\vfill\eject\fi
+ \end}
+\fi
+
+% we won't be using math mode much, so redefine some of the characters
+% we might want to talk about
+\catcode`\^=12
+\catcode`\_=12
+
+\chardef\\=`\\
+\chardef\{=`\{
+\chardef\}=`\}
+
+\hyphenation{mini-buf-fer}
+
+\parindent 0pt
+\parskip 1ex plus .5ex minus .5ex
+
+\def\small{\smallfont\textfont2=\smallsy\baselineskip=.8\baselineskip}
+
+\outer\def\newcolumn{\vfill\eject}
+
+\outer\def\title#1{{\titlefont\centerline{#1}}\vskip 1ex plus .5ex}
+
+\outer\def\section#1{\par\filbreak
+ \vskip 3ex plus 2ex minus 2ex {\headingfont #1}\mark{#1}%
+ \vskip 2ex plus 1ex minus 1.5ex}
+
+% masahiko
+\outer\def\subsection#1{\par\filbreak
+ \vskip 2ex plus 2ex minus 2ex {\miniheadingfont #1}\mark{#1}%
+ \vskip 1ex plus 1ex minus 1.5ex}
+
+\newdimen\keyindent
+
+\def\beginindentedkeys{\keyindent=1em}
+\def\endindentedkeys{\keyindent=0em}
+\endindentedkeys
+
+\def\paralign{\vskip\parskip\halign}
+
+\def\<#1>{$\langle${\rm #1}$\rangle$}
+
+\def\kbd#1{{\tt#1}\null} %\null so not an abbrev even if period follows
+
+\def\beginexample{\par\leavevmode\begingroup
+ \obeylines\obeyspaces\parskip0pt\tt}
+{\obeyspaces\global\let =\ }
+\def\endexample{\endgroup}
+
+\def\key#1#2{\leavevmode\hbox to \hsize{\vtop
+ {\hsize=.75\hsize\rightskip=1em
+ \hskip\keyindent\relax#1}\kbd{#2}\hfil}}
+
+\newbox\metaxbox
+\setbox\metaxbox\hbox{\kbd{M-x }}
+\newdimen\metaxwidth
+\metaxwidth=\wd\metaxbox
+
+\def\metax#1#2{\leavevmode\hbox to \hsize{\hbox to .75\hsize
+ {\hskip\keyindent\relax#1\hfil}%
+ \hskip -\metaxwidth minus 1fil
+ \kbd{#2}\hfil}}
+
+\def\fivecol#1#2#3#4#5{\hskip\keyindent\relax#1\hfil&\kbd{#2}\quad
+ &\kbd{#3}\quad&\kbd{#4}\quad&\kbd{#5}\cr}
+
+\def\fourcol#1#2#3#4{\hskip\keyindent\relax#1\hfil&\kbd{#2}\quad
+ &\kbd{#3}\quad&\kbd{#4}\quad\cr}
+
+\def\threecol#1#2#3{\hskip\keyindent\relax#1\hfil&\kbd{#2}\quad
+ &\kbd{#3}\quad\cr}
+
+\def\twocol#1#2{\hskip\keyindent\relax\kbd{#1}\hfil&\kbd{#2}\quad\cr}
+
+\def\twocolkey#1#2#3#4{\hskip\keyindent\relax#1\hfil&\kbd{#2}\quad&\relax#3\hfil&\kbd{#4}\quad\cr}
+
+%**end of header
+
+\beginindentedkeys
+
+\title{VIP Quick Reference Card}
+
+\centerline{(for version 3.5 under GNU Emacs version 18)}
+
+%\copyrightnotice
+
+\section{Loading VIP}
+
+Just type \kbd{M-x vip-mode} followed by \kbd{RET}
+
+\section{VIP Modes}
+
+VIP has three modes: {\it emacs mode}, {\it vi mode} and {\it insert mode}.
+Mode line tells you which mode you are in.
+In emacs mode you can do all the normal GNU Emacs editing.
+This card explains only vi mode and insert mode.
+{\bf GNU Emacs Reference Card} explains emacs mode.
+You can switch modes as follows.
+
+\key{from emacs mode to vi mode}{C-z}
+\key{from vi mode to emacs mode}{C-z}
+\metax{from vi mode to insert mode}{i, I, a, A, o, O {\rm or} C-o}
+\key{from insert mode to vi mode}{ESC}
+
+If you wish to be in vi mode just after you startup Emacs,
+include the line:
+
+\hskip 5ex
+\kbd{(setq term-setup-hook 'vip-mode)}
+
+in your \kbd{.emacs} file.
+Or, you can put the following alias in your \kbd{.cshrc} file.
+
+\hskip 5ex
+\kbd{alias vip 'emacs \\!* -f vip-mode'}
+
+
+\section{Insert Mode}
+Insert mode is like emacs mode except for the following.
+
+\key{go back to vi mode}{ESC}
+\key{delete previous character}{C-h}
+\key{delete previous word}{C-w}
+\key{emulate \kbd{ESC} key in emacs mode}{C-z}
+
+The rest of this card explains commands in {\bf vi mode}.
+
+\section{Getting Information on VIP}
+
+Execute info command by typing \kbd{M-x info} and select menu item
+\kbd{vip}. Also:
+
+\key{describe function attached to the key {\it x}}{C-h k {\it x}}
+
+\section{Leaving Emacs}
+
+\key{suspend Emacs}{X Z {\rm or} :st}
+\metax{exit Emacs permanently}{Z Z {\rm or} X C {\rm or} :q}
+
+\section{Error Recovery}
+
+\key{abort partially typed or executing command}{C-g}
+\key{redraw messed up screen}{C-l}
+\metax{{\bf recover} a file lost by a system crash}{M-x recover-file}
+\metax{restore a buffer to its original contents}{M-x revert-buffer}
+
+\shortcopyrightnotice
+
+\section{Counts}
+
+Most commands in vi mode accept a {\it count} which can be supplied as a
+prefix to the commands. In most cases, if a count is given, the
+command is executed that many times. E.g., \kbd{5 d d} deletes 5
+lines.
+
+%\shortcopyrightnotice
+\section{Registers}
+
+There are 26 registers (\kbd{a} to \kbd{z}) that can store texts
+and marks.
+You can append a text at the end of a register (say \kbd{x}) by
+specifying the register name in capital letter (say \kbd{X}).
+There are also 9 read only registers (\kbd{1} to \kbd{9}) that store
+up to 9 previous changes.
+We will use {\it x\/} to denote a register.
+\section{Entering Insert Mode}
+
+\key{{\bf insert} at point}{i}
+\key{{\bf append} after cursor}{a}
+\key{{\bf insert} before first non-white}{I}
+\key{{\bf append} at end of line}{A}
+\key{{\bf open} line below}{o}
+\key{{\bf open} line above}{O}
+\key{{\bf open} line at point}{C-o}
+
+\section{Buffers and Windows}
+
+\key{move cursor to {\bf next} window}{C-n}
+\key{delete current window}{X 0}
+\key{delete other windows}{X 1}
+\key{split current window into two windows}{X 2}
+\key{show current buffer in two windows}{X 3}
+\key{{\bf switch} to a buffer in the current window}{s {\sl buffer}}
+\key{{\bf switch} to a buffer in another window}{S {\sl buffer}}
+\key{{\bf kill} a buffer}{K}
+\key{list exisiting {\bf buffers}}{X B}
+
+\section{Files}
+
+\metax{{\bf visit} file in the current window}{v {\sl file} {\rm or} :e {\sl file}}
+\key{{\bf visit} file in another window}{V {\sl file}}
+\key{{\bf save} buffer to the associated file}{X S}
+\key{{\bf write} buffer to a specified file}{X W}
+\key{{\bf insert} a specified file at point}{X I}
+\key{{\bf get} information on the current {\bf file}}{g {\rm or} :f}
+\key{run the {\bf directory} editor}{X d}
+
+\section{Viewing the Buffer}
+
+\key{scroll to next screen}{SPC {\rm or} C-f}
+\key{scroll to previous screen}{RET {\rm or} C-b}
+\key{scroll {\bf down} half screen}{C-d}
+\key{scroll {\bf up} half screen}{C-u}
+\key{scroll down one line}{C-e}
+\key{scroll up one line}{C-y}
+
+\key{put current line on the {\bf home} line}{z H {\rm or} z RET}
+\key{put current line on the {\bf middle} line}{z M {\rm or} z .}
+\key{put current line on the {\bf last} line}{z L {\rm or} z -}
+
+\section{Marking and Returning}
+
+\key{{\bf mark} point in register {\it x}}{m {\it x}}
+\key{set mark at buffer beginning}{m <}
+\key{set mark at buffer end}{m >}
+\key{set mark at point}{m .}
+\key{jump to mark}{m ,}
+\key{exchange point and mark}{` `}
+\key{... and skip to first non-white on line}{' '}
+\key{go to mark {\it x}}{` {\it x}}
+\key{... and skip to first non-white on line}{' {\it x}}
+
+\section{Macros}
+
+\key{start remembering keyboard macro}{X (}
+\key{finish remembering keyboard macro}{X )}
+\key{call last keyboard macro}{*}
+\key{execute macro stored in register {\it x}}{@ {\it x}}
+
+\section{Motion Commands}
+
+\key{go backward one character}{h}
+\key{go forward one character}{l}
+\key{next line keeping the column}{j}
+\key{previous line keeping the column}{k}
+\key{next line at first non-white}{+}
+\key{previous line at first non-white}{-}
+
+\key{beginning of line}{0}
+\key{first non-white on line}{^}
+\key{end of line}{\$}
+\key{go to {\it n}-th column on line}{{\it n} |}
+
+\key{go to {\it n}-th line}{{\it n} G}
+\key{go to last line}{G}
+\key{find matching parenthesis for \kbd{()}, \kbd{\{\}} and \kbd{[]}}{\%}
+
+\key{go to {\bf home} window line}{H}
+\key{go to {\bf middle} window line}{M}
+\key{go to {\bf last} window line}{L}
+
+\subsection{Words, Sentences, Paragraphs}
+
+\key{forward {\bf word}}{w {\rm or} W}
+\key{{\bf backward} word}{b {\rm or} B}
+\key{{\bf end} of word}{e {\rm or} E}
+
+In the case of capital letter commands, a word is delimited by a
+non-white character.
+
+\key{forward sentence}{)}
+\key{backward sentence}{(}
+
+\key{forward paragraph}{\}}
+\key{backward paragraph}{\{}
+
+\subsection{Find Characters on the Line}
+
+\key{{\bf find} {\it c} forward on line}{f {\it c}}
+\key{{\bf find} {\it c} backward on line}{F {\it c}}
+\key{up {\bf to} {\it c} forward on line}{t {\it c}}
+\key{up {\bf to} {\it c} backward on line}{T {\it c}}
+\key{repeat previous \kbd{f}, \kbd{F}, \kbd{t} or \kbd{T}}{;}
+\key{... in the opposite direction}{,}
+
+\newcolumn
+\title{VIP Quick Reference Card}
+
+\section{Searching and Replacing}
+
+\key{search forward for {\sl pat}}{/ {\sl pat}}
+\key{search backward for {\sl pat}}{?\ {\sl pat}}
+\key{repeat previous search}{n}
+\key{... in the opposite direction}{N}
+
+\key{incremental {\bf search}}{C-s}
+\key{{\bf reverse} incremental search}{C-r}
+
+\key{{\bf replace}}{R}
+\key{{\bf query} replace}{Q}
+\key{{\bf replace} a character by another character {\it c}}{r {\it c}}
+
+\section{Modifying Commands}
+
+The delete (yank, change) commands explained below accept a motion command as
+their argument and delete (yank, change) the region determined by the motion
+command. Motion commands are classified into {\it point commands} and
+{\it line commands}. In the case of line commands, whole lines will
+be affected by the command. Motion commands will be represented by
+{\it m} below.
+
+The point commands are as follows:
+
+\hskip 5ex
+\kbd{h l 0 ^ \$ w W b B e E ( ) / ?\ ` f F t T \% ; ,}
+
+The line commands are as follows:
+
+\hskip 5ex
+\kbd{j k + - H M L \{ \} G '}
+
+\subsection{Delete/Yank/Change Commands}
+
+\paralign to \hsize{#\tabskip=10pt plus 1 fil&#\tabskip=0pt&#\tabskip=0pt&#\cr
+\fourcol{}{{\bf delete}}{{\bf yank}}{{\bf change}}
+\fourcol{region determined by {\it m}}{d {\it m}}{y {\it m}}{c {\it m}}
+\fourcol{... into register {\it x}}{" {\it x\/} d {\it m}}{" {\it x\/} y {\it m}}{" {\it x\/} c {\it m}}
+\fourcol{a line}{d d}{Y {\rm or} y y}{c c}
+\fourcol{current {\bf region}}{d r}{y r}{c r}
+\fourcol{expanded {\bf region}}{d R}{y R}{c R}
+\fourcol{to end of line}{D}{y \$}{c \$}
+\fourcol{a character after point}{x}{y l}{c l}
+\fourcol{a character before point}{DEL}{y h}{c h}
+}
+
+\subsection{Put Back Commands}
+
+Deleted/yanked/changed text can be put back by the following commands.
+
+\key{{\bf Put} back at point/above line}{P}
+\key{... from register {\it x}}{" {\it x\/} P}
+\key{{\bf put} back after point/below line}{p}
+\key{... from register {\it x}}{" {\it x\/} p}
+
+\subsection{Repeating and Undoing Modifications}
+
+\key{{\bf undo} last change}{u {\rm or} :und}
+\key{repeat last change}{.\ {\rm (dot)}}
+
+Undo is undoable by \kbd{u} and repeatable by \kbd{.}.
+For example, \kbd{u...} will undo 4 previous changes.
+A \kbd{.} after \kbd{5dd} is equivalent to \kbd{5dd},
+while \kbd{3.} after \kbd{5dd} is equivalent to \kbd{3dd}.
+
+\section{Miscellaneous Commands}
+
+\endindentedkeys
+
+\paralign to \hsize{#\tabskip=5pt plus 1 fil&#\tabskip=0pt&#\tabskip=0pt&#\tabskip=0pt&#\cr
+\fivecol{}{{\bf shift left}}{{\bf shift right}}{{\bf filter shell command}}{{\bf indent}}
+\fivecol{region}{< {\it m}}{> {\it m}}{!\ {\it m\/} {\sl shell-com}}{= {\it m}}
+\fivecol{line}{< <}{> >}{!\ !\ {\sl shell-com}}{= =}
+}
+
+\key{emulate \kbd{ESC}/\kbd{C-h} in emacs mode}{ESC{\rm /}C-h}
+\key{emulate \kbd{C-c}/\kbd{C-x} in emacs mode}{C{\rm /}X}
+
+\key{{\bf join} lines}{J}
+
+\key{lowercase region}{\# c {\it m}}
+\key{uppercase region}{\# C {\it m}}
+\key{execute last keyboard macro on each line in the region}{\# g {\it m}}
+
+\key{insert specified string for each line in the region}{\# q {\it m}}
+\key{check spelling of the words in the region}{\# s {\it m}}
+
+\section{Differences from Vi}
+
+\beginindentedkeys
+
+In VIP some keys behave rather differently from Vi.
+The table below lists such keys, and you can get the effect of typing
+these keys by typing the corresponding keys in the VIP column.
+
+\paralign to \hsize{#\tabskip=10pt plus 1 fil&#\tabskip=0pt&#\cr
+\threecol{}{{\bf Vi}}{{\bf VIP}}
+\threecol{forward character}{SPC}{l}
+\threecol{backward character}{C-h}{h}
+\threecol{next line at first non-white}{RET}{+}
+\threecol{delete previous character}{X}{DEL}
+\threecol{get information on file}{C-g}{g}
+\threecol{substitute characters}{s}{x i}
+\threecol{substitute line}{S}{c c}
+\threecol{change to end of line}{C {\rm or} R}{c \$}
+}
+
+(Strictly speaking, \kbd{C} and \kbd{R} behave slightly differently in Vi.)
+
+\section{Customization}
+
+By default, search is case sensitive.
+You can change this by including the following line in your \kbd{.vip} file.
+
+\hskip 5ex
+\kbd{(setq vip-case-fold-search t)}
+
+\beginindentedkeys
+
+\paralign to \hsize{#\tabskip=10pt plus 1 fil&#\tabskip=0pt&#\cr
+\twocol{{\bf variable}}{{\bf default value}}
+\twocol{vip-search-wrap-around}{t}
+\twocol{vip-case-fold-search}{nil}
+\twocol{vip-re-search}{nil}
+\twocol{vip-re-replace}{nil}
+\twocol{vip-re-query-replace}{nil}
+\twocol{vip-open-with-indent}{nil}
+\twocol{vip-help-in-insert-mode}{nil}
+\twocol{vip-shift-width}{8}
+\twocol{vip-tags-file-name}{"TAGS"}
+}
+
+%\subsection{Customizing Key Bindings}
+
+Include (some of) following lines in your \kbd{.vip} file
+to restore Vi key bindings.
+
+\beginexample
+(define-key vip-mode-map "\\C-g" 'vip-info-on-file)
+(define-key vip-mode-map "\\C-h" 'vip-backward-char)
+(define-key vip-mode-map "\\C-m" 'vip-next-line-at-bol)
+(define-key vip-mode-map " " 'vip-forward-char)
+(define-key vip-mode-map "g" 'vip-keyboard-quit)
+(define-key vip-mode-map "s" 'vip-substitute)
+(define-key vip-mode-map "C" 'vip-change-to-eol)
+(define-key vip-mode-map "R" 'vip-change-to-eol)
+(define-key vip-mode-map "S" 'vip-substitute-line)
+(define-key vip-mode-map "X" 'vip-delete-backward-char)
+\endexample
+
+\newcolumn
+
+\title{Ex Commands in VIP}
+
+In vi mode, an Ex command is entered by typing:
+
+\hskip 5ex
+\kbd{:\ {\sl ex-command} RET}
+
+\section{Ex Addresses}
+
+\paralign to \hsize{#\tabskip=5pt plus 1 fil&#\tabskip=2pt&#\tabskip=5pt plus 1 fil&#\cr
+\twocolkey{current line}{.}{next line with {\sl pat}}{/ {\sl pat} /}
+\twocolkey{line {\it n}}{{\it n}}{previous line with {\sl pat}}{?\ {\sl pat} ?}
+\twocolkey{last line}{\$}{{\it n\/} line before {\it a}}{{\it a} - {\it n}}
+\twocolkey{next line}{+}{{\it a\/} through {\it b}}{{\it a\/} , {\it b}}
+\twocolkey{previous line}{-}{line marked with {\it x}}{' {\it x}}
+\twocolkey{entire buffer}{\%}{previous context}{' '}
+}
+
+Addresses can be specified in front of a command.
+For example,
+
+\hskip 5ex
+\kbd{:.,.+10m\$}
+
+moves 11 lines below current line to the end of buffer.
+
+\section{Ex Commands}
+
+\endindentedkeys
+
+\key{mark lines matching {\sl pat} and execute {\sl cmds} on these lines}{:g /{\sl pat}/ {\sl cmds}}
+
+\key{mark lines {\it not\/} matching {\sl pat} and execute {\sl cmds} on these lines}{:v /{\sl pat}/ {\sl cmds}}
+
+
+\key{{\bf move} specified lines after {\sl addr}}{:m {\sl addr}}
+\key{{\bf copy} specified lines after {\sl addr}}{:co\rm\ (or \kbd{:t})\ \sl addr}
+\key{{\bf delete} specified lines [into register {\it x\/}]}{:d {\rm [{\it x\/}]}}
+\key{{\bf yank} specified lines [into register {\it x\/}]}{:y {\rm [{\it x\/}]}}
+\key{{\bf put} back text [from register {\it x\/}]}{:pu {\rm [{\it x\/}]}}
+
+\key{{\bf substitute} {\sl repl} for first string on line matching {\sl pat}}{:s /{\sl pat}/{\sl repl}/}
+
+\key{repeat last substitution}{:\&}
+\key{repeat previous substitute with previous search pattern as {\sl pat}}{:\~{}}
+
+\key{{\bf read} in a file}{:r {\sl file}}
+\key{{\bf read} in the output of a shell command}{:r!\ {\sl command}}
+\key{write out specified lines into {\sl file}}{:w {\sl file}}
+\key{write out specified lines at the end of {\sl file}}{:w>> {\sl file}}
+\key{write out and then quit}{:wq {\sl file}}
+
+\key{define a macro {\it x} that expands to {\sl cmd}}{:map {\it x} {\sl cmd}}
+\key{remove macro expansion associated with {\it x}}{:unma {\it x}}
+
+\key{print line number}{:=}
+\key{print {\bf version} number of VIP}{:ve}
+
+\key{shift specified lines to the right}{:>}
+\key{shift specified lines to the left}{:<}
+
+\key{{\bf join} lines}{:j}
+\key{mark specified line to register {\it x}}{:k {\it x}}
+\key{{\bf set} a variable's value}{:se}
+\key{run a sub{\bf shell} in a window}{:sh}
+\key{execute shell command {\sl command}}{:!\ {\sl command}}
+\key{find first definition of {\bf tag} {\sl tag}}{:ta {\sl tag}}
+
+
+\copyrightnotice
+
+\bye
+
+% Local variables:
+% compile-command: "tex refcard"
+% End:
diff --git a/etc/vmslink.opt b/etc/vmslink.opt
new file mode 100644
index 00000000000..20886ac6dd8
--- /dev/null
+++ b/etc/vmslink.opt
@@ -0,0 +1,2 @@
+!sys$share:vaxcrtl/share
+sys$library:vaxcrtl/library
diff --git a/lib-src/wakeup.c b/etc/wakeup.c
index 61ad4401d1f..eb3dd72c95c 100644
--- a/lib-src/wakeup.c
+++ b/etc/wakeup.c
@@ -18,6 +18,9 @@ main (argc, argv)
while (1)
{
+ /* Make sure wakeup stops when Emacs goes away. */
+ if (getppid () == 1)
+ exit (0);
printf ("Wake up!\n");
fflush (stdout);
/* If using a period of 60, produce the output when the minute
diff --git a/etc/xmouse.doc b/etc/xmouse.doc
new file mode 100644
index 00000000000..bdaa4b4392f
--- /dev/null
+++ b/etc/xmouse.doc
@@ -0,0 +1,31 @@
+.\" X windows GNU Emacs key bindings.
+.\" Print with `tbl xmouse.doc | troff`
+.\"
+.rs
+.sp 1i
+.ps 6
+.vs 7
+.TS
+box;
+cfI s s
+c | c | c
+l | l | l.
+GNU Emacs Key Bindings for X Windows
+=
+Key Button Function
+_
+Unshifted left x-mouse-set-point
+\^ middle x-paste-text
+\^ right x-cut-text
+_
+Control middle x-cut-and-wipe-text
+\^ right x-mouse-select-and-split
+_
+Shift middle x-cut-text
+\^ right x-paste-text
+_
+Control-Shift left x-buffer-menu
+\^ middle x-help
+\^ right x-mouse-keep-one-window
+.TE
+
diff --git a/lib-src/yow.c b/etc/yow.c
index bfff0e7d3ea..f39822c9687 100644
--- a/lib-src/yow.c
+++ b/etc/yow.c
@@ -1,22 +1,17 @@
-/*
- * yow.c
+#include <stdio.h>
+#include <ctype.h>
+#include "../src/paths.h"
+
+/* zippy.c
*
* Print a quotation from Zippy the Pinhead.
* Qux <Kaufman-David@Yale> March 6, 1986
*
- * With dynamic memory allocation.
*/
-#include <stdio.h>
-#include <ctype.h>
-#include "../src/paths.h" /* For PATH_EXEC. */
-
-#define BUFSIZE 80
+#define BUFSIZE 2000
#define SEP '\0'
-
-#ifndef YOW_FILE
#define YOW_FILE "yow.lines"
-#endif
main (argc, argv)
int argc;
@@ -24,7 +19,7 @@ main (argc, argv)
{
FILE *fp;
char file[BUFSIZ];
- void yow(), setup_yow();
+ void yow();
if (argc > 2 && !strcmp (argv[1], "-f"))
strcpy (file, argv[2]);
@@ -43,58 +38,29 @@ main (argc, argv)
/* initialize random seed */
srand((int) (getpid() + time((long *) 0)));
- setup_yow(fp);
yow(fp);
fclose(fp);
exit(0);
}
-static long len = -1;
-static long header_len;
-
-#define AVG_LEN 40 /* average length of a quotation */
-
-/* Sets len and header_len */
-void
-setup_yow(fp)
- FILE *fp;
-{
- int c;
-
- /* Get length of file */
- /* Because the header (stuff before the first SEP) can be very long,
- * thus biasing our search in favor of the first quotation in the file,
- * we explicitly skip that. */
- while ((c = getc(fp)) != SEP) {
- if (c == EOF) {
- fprintf(stderr, "File contains no separators.\n");
- exit(2);
- }
- }
- header_len = ftell(fp);
- if (header_len > AVG_LEN)
- header_len -= AVG_LEN; /* allow the first quotation to appear */
-
- if (fseek(fp, 0L, 2) == -1) {
- perror("fseek 1");
- exit(1);
- }
- len = ftell(fp) - header_len;
-}
-
-
-/* go to a random place in the file and print the quotation there */
void
yow (fp)
FILE *fp;
{
+ static long len = -1;
long offset;
int c, i = 0;
- char *buf;
- unsigned int bufsize;
- char *malloc(), *realloc();
+ char buf[BUFSIZE];
- offset = rand() % len + header_len;
+ /* Get length of file, go to a random place in it */
+ if (len == -1) {
+ if (fseek(fp, 0, 2) == -1) {
+ perror("fseek 1");
+ exit(1);
+ }
+ len = ftell(fp);
+ }
+ offset = rand() % len;
if (fseek(fp, offset, 0) == -1) {
perror("fseek 2");
exit(1);
@@ -117,27 +83,13 @@ yow (fp)
yow(fp);
return;
}
-
- bufsize = BUFSIZE;
- buf = malloc(bufsize);
- if (buf == (char *)0) {
- fprintf(stderr, "can't allocate any memory\n");
- exit (3);
- }
-
buf[i++] = c;
while ((c = getc(fp)) != SEP && c != EOF) {
buf[i++] = c;
-
- if (i == bufsize-1) {
+
+ if (i == BUFSIZ-1)
/* Yow! Is this quotation too long yet? */
- bufsize *= 2;
- buf = realloc(buf, bufsize);
- if (buf == (char *)0) {
- fprintf(stderr, "can't allocate more memory\n");
- exit (3);
- }
- }
+ break;
}
buf[i++] = 0;
printf("%s\n", buf);
diff --git a/info/COPYING b/info/COPYING
new file mode 100644
index 00000000000..9a170375811
--- /dev/null
+++ b/info/COPYING
@@ -0,0 +1,249 @@
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 1, February 1989
+
+ Copyright (C) 1989 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The license agreements of most software companies try to keep users
+at the mercy of those companies. By contrast, our General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. The
+General Public License applies to the Free Software Foundation's
+software and to any other program whose authors commit to using it.
+You can use it for your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Specifically, the General Public License is designed to make
+sure that you have the freedom to give away or sell copies of free
+software, that you receive source code or can get it if you want it,
+that you can change the software or use pieces of it in new free
+programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of a such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must tell them their rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any program or other work which
+contains a notice placed by the copyright holder saying it may be
+distributed under the terms of this General Public License. The
+"Program", below, refers to any such program or work, and a "work based
+on the Program" means either the Program or any work containing the
+Program or a portion of it, either verbatim or with modifications. Each
+licensee is addressed as "you".
+
+ 1. You may copy and distribute verbatim copies of the Program's source
+code as you receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice and
+disclaimer of warranty; keep intact all the notices that refer to this
+General Public License and to the absence of any warranty; and give any
+other recipients of the Program a copy of this General Public License
+along with the Program. You may charge a fee for the physical act of
+transferring a copy.
+
+ 2. You may modify your copy or copies of the Program or any portion of
+it, and copy and distribute such modifications under the terms of Paragraph
+1 above, provided that you also do the following:
+
+ a) cause the modified files to carry prominent notices stating that
+ you changed the files and the date of any change; and
+
+ b) cause the whole of any work that you distribute or publish, that
+ in whole or in part contains the Program or any part thereof, either
+ with or without modifications, to be licensed at no charge to all
+ third parties under the terms of this General Public License (except
+ that you may choose to grant warranty protection to some or all
+ third parties, at your option).
+
+ c) If the modified program normally reads commands interactively when
+ run, you must cause it, when started running for such interactive use
+ in the simplest and most usual way, to print or display an
+ announcement including an appropriate copyright notice and a notice
+ that there is no warranty (or else, saying that you provide a
+ warranty) and that users may redistribute the program under these
+ conditions, and telling the user how to view a copy of this General
+ Public License.
+
+ d) You may charge a fee for the physical act of transferring a
+ copy, and you may at your option offer warranty protection in
+ exchange for a fee.
+
+Mere aggregation of another independent work with the Program (or its
+derivative) on a volume of a storage or distribution medium does not bring
+the other work under the scope of these terms.
+
+ 3. You may copy and distribute the Program (or a portion or derivative of
+it, under Paragraph 2) in object code or executable form under the terms of
+Paragraphs 1 and 2 above provided that you also do one of the following:
+
+ a) accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of
+ Paragraphs 1 and 2 above; or,
+
+ b) accompany it with a written offer, valid for at least three
+ years, to give any third party free (except for a nominal charge
+ for the cost of distribution) a complete machine-readable copy of the
+ corresponding source code, to be distributed under the terms of
+ Paragraphs 1 and 2 above; or,
+
+ c) accompany it with the information you received as to where the
+ corresponding source code may be obtained. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form alone.)
+
+Source code for a work means the preferred form of the work for making
+modifications to it. For an executable file, complete source code means
+all the source code for all modules it contains; but, as a special
+exception, it need not include source code for modules which are standard
+libraries that accompany the operating system on which the executable
+file runs, or for standard header files or definitions files that
+accompany that operating system.
+
+ 4. You may not copy, modify, sublicense, distribute or transfer the
+Program except as expressly provided under this General Public License.
+Any attempt otherwise to copy, modify, sublicense, distribute or transfer
+the Program is void, and will automatically terminate your rights to use
+the Program under this License. However, parties who have received
+copies, or rights to use copies, from you under this General Public
+License will not have their licenses terminated so long as such parties
+remain in full compliance.
+
+ 5. By copying, distributing or modifying the Program (or any work based
+on the Program) you indicate your acceptance of this license to do so,
+and all its terms and conditions.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the original
+licensor to copy, distribute or modify the Program subject to these
+terms and conditions. You may not impose any further restrictions on the
+recipients' exercise of the rights granted herein.
+
+ 7. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of the license which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+the license, you may choose any version ever published by the Free Software
+Foundation.
+
+ 8. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to humanity, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these
+terms.
+
+ To do so, attach the following notices to the program. It is safest to
+attach them to the start of each source file to most effectively convey
+the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19xx name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the
+appropriate parts of the General Public License. Of course, the
+commands you use may be called something other than `show w' and `show
+c'; they could even be mouse-clicks or menu items--whatever suits your
+program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ program `Gnomovision' (a program to direct compilers to make passes
+ at assemblers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/info/dir b/info/dir
new file mode 100644
index 00000000000..c8b5555e78e
--- /dev/null
+++ b/info/dir
@@ -0,0 +1,32 @@
+-*- Text -*-
+This is the file .../info/dir, which contains the topmost node of the
+Info hierarchy. The first time you invoke Info you start off
+looking at that node, which is (dir)Top.
+
+File: dir Node: Top This is the top of the INFO tree
+ This (the Directory node) gives a menu of major topics.
+ Typing "d" returns here, "q" exits, "?" lists all INFO commands, "h"
+ gives a primer for first-timers, "mTexinfo<Return>" visits Texinfo topic,
+ etc.
+ --- PLEASE ADD DOCUMENTATION TO THIS TREE. (See INFO topic first.) ---
+
+* Menu: The list of major topics begins on the next line.
+
+* Info: (info). Documentation browsing system.
+
+* Emacs: (emacs). The extensible self-documenting text editor.
+
+* VIP: (vip). A VI-emulation for Emacs.
+
+* Texinfo: (texinfo).
+ With one source file, make either a printed manual
+ (through TeX) or an Info file (through texinfo).
+ Full documentation in this menu item.
+
+* Termcap: (termcap).
+ The termcap library, which enables application programs
+ to handle all types of character-display terminals.
+
+* Regex: (regex).
+ The GNU regular expression library.
+
diff --git a/info/emacs b/info/emacs
new file mode 100644
index 00000000000..eba9e506b60
--- /dev/null
+++ b/info/emacs
@@ -0,0 +1,369 @@
+This is Info file ../info/emacs, produced by Makeinfo-1.49 from the
+input file emacs.texi.
+
+ This file documents the GNU Emacs editor.
+
+ Copyright (C) 1985, 1986, 1988, 1992 Richard M. Stallman.
+
+ Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+ Permission is granted to copy and distribute modified versions of
+this manual under the conditions for verbatim copying, provided also
+that the sections entitled "The GNU Manifesto", "Distribution" and "GNU
+General Public License" are included exactly as in the original, and
+provided that the entire resulting derived work is distributed under the
+terms of a permission notice identical to this one.
+
+ Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that the sections entitled "The GNU Manifesto",
+"Distribution" and "GNU General Public License" may be included in a
+translation approved by the author instead of in the original English.
+
+Indirect:
+emacs-1: 1115
+emacs-2: 48771
+emacs-3: 96620
+emacs-4: 146550
+emacs-5: 193326
+emacs-6: 242965
+emacs-7: 292468
+emacs-8: 339287
+emacs-9: 389177
+emacs-10: 437965
+emacs-11: 485451
+emacs-12: 534362
+emacs-13: 583212
+emacs-14: 632855
+emacs-15: 682479
+emacs-16: 705948
+emacs-17: 737068
+emacs-18: 764424
+emacs-19: 813651
+
+Tag Table:
+(Indirect)
+Node: Top1117
+Node: Distrib15242
+Node: License17658
+Node: Intro30930
+Node: Screen33604
+Node: Point35048
+Node: Echo Area36624
+Node: Mode Line38883
+Node: Characters43201
+Node: Keys46260
+Node: Commands48773
+Node: Entering Emacs51538
+Node: Exiting52860
+Node: Command Switches55228
+Node: Basic62319
+Node: Blank Lines71078
+Node: Continuation Lines72633
+Node: Position Info74072
+Node: Arguments77253
+Node: Undo80508
+Node: Minibuffer84182
+Node: Minibuffer File86705
+Node: Minibuffer Edit88332
+Node: Completion90623
+Node: Repetition96622
+Node: M-x99542
+Node: Help102154
+Node: Mark111292
+Node: Setting Mark112925
+Node: Using Region115121
+Node: Marking Objects115861
+Node: Mark Ring117714
+Node: Killing119560
+Node: Yanking125074
+Node: Kill Ring125876
+Node: Appending Kills127116
+Node: Earlier Kills129180
+Node: Accumulating Text131805
+Node: Rectangles134869
+Node: Registers138379
+Node: RegPos139398
+Node: RegText140282
+Node: RegRect141345
+Node: Display142072
+Node: Scrolling143216
+Node: Horizontal Scrolling146552
+Node: Selective Display147742
+Node: Display Vars148961
+Node: Search151589
+Node: Incremental Search152775
+Node: Nonincremental Search160677
+Node: Word Search162140
+Node: Regexp Search163747
+Node: Regexps165602
+Node: Search Case176255
+Node: Replace176962
+Node: Unconditional Replace177906
+Node: Regexp Replace179013
+Node: Replacement and Case179928
+Node: Query Replace180877
+Node: Other Repeating Search184477
+Node: Fixit185728
+Node: Kill Errors186316
+Node: Transpose187621
+Node: Fixing Case190085
+Node: Spelling190742
+Node: Files192174
+Node: File Names193328
+Node: Visiting196943
+Node: Saving201764
+Node: Backup206641
+Node: Backup Names208034
+Node: Backup Deletion209547
+Node: Backup Copying210718
+Node: Interlocking212452
+Node: Reverting216298
+Node: Auto Save218111
+Node: Auto Save Files219074
+Node: Auto Save Control220897
+Node: Recover222115
+Node: ListDir223257
+Node: Dired224740
+Node: Dired Enter225396
+Node: Dired Edit226213
+Node: Dired Deletion227953
+Node: Dired Immed231163
+Node: Misc File Ops232435
+Node: Buffers235090
+Node: Select Buffer237366
+Node: List Buffers238678
+Node: Misc Buffer240059
+Node: Kill Buffer241763
+Node: Several Buffers242967
+Node: Windows246738
+Node: Basic Window247323
+Node: Split Window249061
+Node: Other Window250751
+Node: Pop Up Window252498
+Node: Change Window253640
+Node: Major Modes255556
+Node: Choosing Modes257806
+Node: Indentation260347
+Node: Indentation Commands262441
+Node: Tab Stops265140
+Node: Just Spaces267068
+Node: Text267874
+Node: Text Mode269868
+Node: Nroff Mode272051
+Node: TeX Mode273674
+Node: TeX Editing275890
+Node: TeX Print279306
+Node: Texinfo Mode282548
+Node: Outline Mode283675
+Node: Outline Format285142
+Node: Outline Motion287936
+Node: Outline Visibility289512
+Node: Words292470
+Node: Sentences295430
+Node: Paragraphs297642
+Node: Pages299963
+Node: Filling302576
+Node: Auto Fill303355
+Node: Fill Commands305492
+Node: Fill Prefix307628
+Node: Case309810
+Node: Programs311848
+Node: Program Modes314413
+Node: Lists316618
+Node: Defuns322320
+Node: Grinding324938
+Node: Basic Indent325551
+Node: Multi-line Indent327560
+Node: Lisp Indent329190
+Node: C Indent332572
+Node: Matching337718
+Node: Comments339289
+Node: Macro Expansion345804
+Node: Balanced Editing346355
+Node: Lisp Completion347379
+Node: Documentation348388
+Node: Change Log349635
+Node: Tags352485
+Node: Tag Syntax353812
+Node: Create Tag Table354506
+Node: Select Tag Table356099
+Node: Find Tag356939
+Node: Tags Search359259
+Node: Tags Stepping361545
+Node: List Tags362115
+Node: Fortran363134
+Node: Fortran Motion364194
+Node: Fortran Indent364997
+Node: ForIndent Commands365677
+Node: ForIndent Num366804
+Node: ForIndent Conv368075
+Node: ForIndent Vars368860
+Node: Fortran Comments369999
+Node: Fortran Columns373630
+Node: Fortran Abbrev375047
+Node: Compiling/Testing375959
+Node: Compilation376932
+Node: Lisp Modes381893
+Node: Lisp Libraries383152
+Node: Loading383714
+Node: Compiling Libraries386598
+Node: Mocklisp388500
+Node: Lisp Eval389179
+Node: Lisp Debug392809
+Node: Lisp Interaction398298
+Node: External Lisp399664
+Node: Abbrevs401750
+Node: Defining Abbrevs403968
+Node: Expanding Abbrevs406380
+Node: Editing Abbrevs409178
+Node: Saving Abbrevs411053
+Node: Dynamic Abbrevs413016
+Node: Picture414332
+Node: Basic Picture416763
+Node: Insert in Picture419063
+Node: Tabs in Picture420477
+Node: Rectangles in Picture421985
+Node: Sending Mail423727
+Node: Mail Format425626
+Node: Mail Headers426958
+Node: Mail Mode430251
+Node: Rmail433950
+Node: Rmail Scrolling436976
+Node: Rmail Motion437967
+Node: Rmail Deletion441295
+Node: Rmail Inbox444068
+Node: Rmail Files446239
+Node: Rmail Output448789
+Node: Rmail Labels451173
+Node: Rmail Summary454708
+Node: Rmail Make Summary455671
+Node: Rmail Summary Edit457096
+Node: Rmail Reply460460
+Node: Rmail Editing463555
+Node: Rmail Digest465865
+Node: Recursive Edit466933
+Node: Narrowing470007
+Node: Sorting472014
+Node: Shell477102
+Node: Single Shell478018
+Node: Interactive Shell479601
+Node: Shell Mode482620
+Node: Hardcopy484408
+Node: Dissociated Press485453
+Node: Amusements488012
+Node: Emulation488498
+Node: Customization491221
+Node: Minor Modes492683
+Node: Variables494336
+Node: Examining496317
+Node: Edit Options497759
+Node: Locals499365
+Node: File Variables502401
+Node: Keyboard Macros506234
+Node: Basic Kbd Macro508421
+Node: Save Kbd Macro510663
+Node: Kbd Macro Query512324
+Node: Key Bindings514243
+Node: Keymaps515103
+Node: Rebinding519723
+Node: Disabling521940
+Node: Syntax523734
+Node: Syntax Entry524604
+Node: Syntax Change528757
+Node: Init File530947
+Node: Init Syntax532243
+Node: Init Examples534364
+Node: Terminal Init538264
+Node: Debugging Init539994
+Node: Quitting540700
+Node: Lossage543671
+Node: Stuck Recursive544303
+Node: Screen Garbled545003
+Node: Text Garbled546113
+Node: Unasked-for Search546742
+Node: Emergency Escape547519
+Node: Total Frustration549271
+Node: Bugs549890
+Node: Version 19559029
+Node: Basic Changes561292
+Node: New Facilities564717
+Node: Binding Changes567776
+Node: Changed Commands571408
+Node: M-x Changes573788
+Node: New Commands576105
+Node: Search Changes580453
+Node: Filling Changes581913
+Node: TeX Mode Changes583214
+Node: Shell Changes584536
+Node: Spell Changes588181
+Node: Mail Changes589841
+Node: Tags Changes592552
+Node: Info Changes594453
+Node: Dired Changes595940
+Node: Marks in Dired597105
+Node: Multiple Files598949
+Node: Shell Commands in Dired601846
+Node: Dired Regexps603444
+Node: Dired Case Conversion605867
+Node: Comparison in Dired606273
+Node: Subdirectories in Dired607019
+Node: Hiding Subdirectories608966
+Node: Editing Dired Buffer610085
+Node: Dired and Find611418
+Node: GNUS612640
+Node: Buffers of GNUS613413
+Node: GNUS Startup614424
+Node: Summary of GNUS615321
+Node: Calendar/Diary618790
+Node: Calendar619976
+Node: Diary Entries622461
+Node: Displaying Diary623856
+Node: New Entries624932
+Node: European Calendar Style627760
+Node: Simple and Fancy628435
+Node: Other Diary Features629321
+Node: Startup Diary630467
+Node: Printing Diary630963
+Node: Version Control631771
+Node: Concepts of VC632857
+Node: Editing with VC634136
+Node: Variables for Check-in/out638545
+Node: Log Entries640198
+Node: Change Logs and VC641494
+Node: Comparing Versions644881
+Node: VC Status646117
+Node: Renaming and VC647150
+Node: Snapshots647915
+Node: Making Snapshots648407
+Node: Snapshot Caveats649966
+Node: Version Headers651790
+Node: Emerge654041
+Node: Overview of Emerge654532
+Node: Submodes of Emerge657429
+Node: State of Difference659006
+Node: Merge Commands661545
+Node: Exiting Emerge664130
+Node: Combining in Emerge664814
+Node: Fine Points of Emerge665594
+Node: Debuggers666535
+Node: Starting GUD667156
+Node: Debugger Operation668114
+Node: Commands of GUD669262
+Node: GUD Customization671301
+Node: Other New Modes673219
+Node: Asm Mode674326
+Node: Edebug Mode674783
+Node: Editing Binary Files675522
+Node: Key Sequence Changes676650
+Node: Hook Changes680636
+Node: Manifesto682481
+Node: Glossary705950
+Node: Key Index737070
+Node: Command Index764426
+Node: Variable Index802648
+Node: Concept Index813653
+
+End Tag Table
diff --git a/info/emacs-1 b/info/emacs-1
new file mode 100644
index 00000000000..3366143d000
--- /dev/null
+++ b/info/emacs-1
@@ -0,0 +1,1007 @@
+This is Info file ../info/emacs, produced by Makeinfo-1.49 from the
+input file emacs.texi.
+
+ This file documents the GNU Emacs editor.
+
+ Copyright (C) 1985, 1986, 1988, 1992 Richard M. Stallman.
+
+ Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+ Permission is granted to copy and distribute modified versions of
+this manual under the conditions for verbatim copying, provided also
+that the sections entitled "The GNU Manifesto", "Distribution" and "GNU
+General Public License" are included exactly as in the original, and
+provided that the entire resulting derived work is distributed under the
+terms of a permission notice identical to this one.
+
+ Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that the sections entitled "The GNU Manifesto",
+"Distribution" and "GNU General Public License" may be included in a
+translation approved by the author instead of in the original English.
+
+
+File: emacs, Node: Top, Next: Distrib, Up: (DIR)
+
+The Emacs Editor
+****************
+
+ Emacs is the extensible, customizable, self-documenting real-time
+display editor. This Info file describes how to edit with Emacs and
+some of how to customize it, but not how to extend it.
+
+* Menu:
+
+* Distrib:: How to get the latest Emacs distribution.
+* License:: The GNU General Public License gives you permission
+ to redistribute GNU Emacs on certain terms; and also
+ explains that there is no warranty.
+* Intro:: An introduction to Emacs concepts.
+* Glossary:: The glossary.
+* Version 19:: Changes coming in Emacs version 19, to be released.
+* Manifesto:: What's GNU? Gnu's Not Unix!
+
+Indexes, nodes containing large menus
+* Key Index:: An item for each standard Emacs key sequence.
+* Command Index:: An item for each command name.
+* Variable Index:: An item for each documented variable.
+* Concept Index:: An item for each concept.
+
+Important General Concepts
+* Screen:: How to interpret what you see on the screen.
+* Characters:: Emacs's character sets for file contents and for keyboard.
+* Keys:: Key sequences: what you type to request one editing action.
+* Commands:: Commands: named functions run by key sequences to do editing.
+* Entering Emacs:: Starting Emacs from the shell.
+* Command Switches:: Hairy startup options.
+* Exiting:: Stopping or killing Emacs.
+* Basic:: The most basic editing commands.
+* Undo:: Undoing recently made changes in the text.
+* Minibuffer:: Entering arguments that are prompted for.
+* M-x:: Invoking commands by their names.
+* Help:: Commands for asking Emacs about its commands.
+
+Important Text-Changing Commands
+* Mark:: The mark: how to delimit a "region" of text.
+* Killing:: Killing text.
+* Yanking:: Recovering killed text. Moving text.
+* Accumulating Text::
+ Other ways of copying text.
+* Rectangles:: Operating on the text inside a rectangle on the screen.
+* Registers:: Saving a text string or a location in the buffer.
+* Display:: Controlling what text is displayed.
+* Search:: Finding or replacing occurrences of a string.
+* Fixit:: Commands especially useful for fixing typos.
+
+Larger Units of Text
+* Files:: All about handling files.
+* Buffers:: Multiple buffers; editing several files at once.
+* Windows:: Viewing two pieces of text at once.
+
+Advanced Features
+* Major Modes:: Text mode vs. Lisp mode vs. C mode ...
+* Indentation:: Editing the white space at the beginnings of lines.
+* Text:: Commands and modes for editing English.
+* Programs:: Commands and modes for editing programs.
+* Compiling/Testing::
+ Compiling, running and debugging programs.
+* Abbrevs:: How to define text abbreviations to reduce
+ the number of characters you must type.
+* Picture:: Editing pictures made up of characters
+ using the quarter-plane screen model.
+* Sending Mail::Sending mail in Emacs.
+* Rmail:: Reading mail in Emacs.
+* Recursive Edit::
+ A command can allow you to do editing
+ "within the command". This is called a
+ `recursive editing level'.
+* Narrowing:: Restricting display and editing to a portion
+ of the buffer.
+* Sorting:: Sorting lines, paragraphs or pages within Emacs.
+* Shell:: Executing shell commands from Emacs.
+* Hardcopy:: Printing buffers or regions.
+* Dissociated Press:: Dissociating text for fun.
+* Amusements:: Various games and hacks.
+* Emulation:: Emulating some other editors with Emacs.
+* Customization:: Modifying the behavior of Emacs.
+
+Recovery from Problems.
+* Quitting:: Quitting and aborting.
+* Lossage:: What to do if Emacs is hung or malfunctioning.
+* Bugs:: How and when to report a bug.
+
+Here are some other nodes which are really inferiors of the ones
+already listed, mentioned here so you can get to them in one step:
+
+Subnodes of Screen
+* Point:: The place in the text where editing commands operate.
+* Echo Area:: Short messages appear at the bottom of the screen.
+* Mode Line:: Interpreting the mode line.
+
+Subnodes of Basic
+* Blank Lines:: Commands to make or delete blank lines.
+* Continuation Lines:: Lines too wide for the screen.
+* Position Info:: What page, line, row, or column is point on?
+* Arguments:: Giving numeric arguments to commands.
+
+Subnodes of Minibuffer
+* Minibuffer File:: Entering file names with the minibuffer.
+* Minibuffer Edit:: How to edit in the minibuffer.
+* Completion:: An abbreviation facility for minibuffer input.
+* Repetition:: Re-executing previous commands that used the minibuffer.
+
+Subnodes of Mark
+* Setting Mark:: Commands to set the mark.
+* Using Region:: Summary of ways to operate on contents of the region.
+* Marking Objects:: Commands to put region around textual units.
+* Mark Ring:: Previous mark positions saved so you can go back there.
+
+Subnodes of Yanking
+* Kill Ring:: Where killed text is stored. Basic yanking.
+* Appending Kills:: Several kills in a row all yank together.
+* Earlier Kills:: Yanking something killed some time ago.
+
+Subnodes of Registers
+* RegPos:: Saving positions in registers.
+* RegText:: Saving text in registers.
+* RegRect:: Saving rectangles in registers.
+
+Subnodes of Display
+* Scrolling:: Moving text up and down in a window.
+* Horizontal Scrolling:: Moving text left and right in a window.
+* Selective Display:: Hiding lines with lots of indentation.
+* Display Vars:: Information on variables for customizing display.
+
+Subnodes of Search
+* Incremental Search:: Search happens as you type the string.
+* Nonincremental Search:: Specify entire string and then search.
+* Word Search:: Search for sequence of words.
+* Regexp Search:: Search for match for a regexp.
+* Regexps:: Syntax of regular expressions.
+* Search Case:: To ignore case while searching, or not.
+* Replace:: Search, and replace some or all matches.
+* Unconditional Replace:: Everything about replacement except for querying.
+* Query Replace:: How to use querying.
+* Other Repeating Search:: Operating on all matches for some regexp.
+
+Subnodes of Fixit
+* Kill Errors:: Commands to kill a batch of recently entered text.
+* Transpose:: Exchanging two characters, words, lines, lists...
+* Fixing Case:: Correcting case of last word entered.
+* Spelling:: Apply spelling checker to a word, or a whole file.
+
+Subnodes of Files
+* File Names:: How to type and edit file name arguments.
+* Visiting:: Visiting a file prepares Emacs to edit the file.
+* Saving:: Saving makes your changes permanent.
+* Backup:: How Emacs saves the old version of your file.
+* Interlocking::How Emacs protects against simultaneous editing
+ of one file by two users.
+* Reverting:: Reverting cancels all the changes not saved.
+* Auto Save:: Auto Save periodically protects against loss of data.
+* ListDir:: Listing the contents of a file directory.
+* Dired:: "Editing" a directory to delete, rename, etc.
+ the files in it.
+* Misc File Ops:: Other things you can do on files.
+
+Subnodes of Buffers
+* Select Buffer:: Creating a new buffer or reselecting an old one.
+* List Buffers:: Getting a list of buffers that exist.
+* Misc Buffer:: Renaming; changing read-only status.
+* Kill Buffer:: Killing buffers you no longer need.
+* Several Buffers:: How to go through the list of all buffers
+ and operate variously on several of them.
+
+Subnodes of Windows
+* Basic Window:: Introduction to Emacs windows.
+* Split Window:: New windows are made by splitting existing windows.
+* Other Window:: Moving to another window or doing something to it.
+* Pop Up Window:: Finding a file or buffer in another window.
+* Change Window:: Deleting windows and changing their sizes.
+
+Subnodes of Indentation
+* Indentation Commands:: Various commands and techniques for indentation.
+* Tab Stops:: You can set arbitrary "tab stops" and then
+ indent to the next tab stop when you want to.
+* Just Spaces:: You can request indentation using just spaces.
+
+Subnodes of Text
+* Text Mode:: The major mode for editing text files.
+* Nroff Mode:: The major mode for editing input to the formatter nroff.
+* TeX Mode:: The major mode for editing input to the formatter TeX.
+* Texinfo Mode::The major mode for editing input to the formatter Texinfo.
+* Outline Mode::The major mode for editing outlines.
+* Words:: Moving over and killing words.
+* Sentences:: Moving over and killing sentences.
+* Paragraphs:: Moving over paragraphs.
+* Pages:: Moving over pages.
+* Filling:: Filling or justifying text
+* Case:: Changing the case of text
+
+Subnodes of Programs
+* Program Modes:: Major modes for editing programs.
+* Lists:: Expressions with balanced parentheses.
+ There are editing commands to operate on them.
+* Defuns:: Each program is made up of separate functions.
+ There are editing commands to operate on them.
+* Grinding:: Adjusting indentation to show the nesting.
+* Matching:: Insertion of a close-delimiter flashes matching open.
+* Comments:: Inserting, killing and aligning comments.
+* Balanced Editing:: Inserting two matching parentheses at once, etc.
+* Lisp Completion:: Completion on symbol names in Lisp code.
+* Documentation:: Getting documentation of functions you plan to call.
+* 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.
+* Fortran:: Fortran mode and its special features.
+
+Subnodes of Compiling/Testing
+* Compilation:: Compiling programs in languages other than Lisp
+ (C, Pascal, etc.)
+* Lisp Modes:: Various modes for editing Lisp programs, with
+ different facilities for running the Lisp programs.
+* Lisp Libraries:: Creating Lisp programs to run in Emacs.
+* Lisp Interaction:: Executing Lisp in an Emacs buffer.
+* Lisp Eval:: Executing a single Lisp expression in Emacs.
+* Lisp Debug:: Debugging Lisp programs running in Emacs.
+* External Lisp:: Communicating through Emacs with a separate Lisp.
+
+Subnodes of Abbrevs
+* Defining Abbrevs:: Defining an abbrev, so it will expand when typed.
+* Expanding Abbrevs:: Controlling expansion: prefixes, canceling expansion.
+* Editing Abbrevs:: Viewing or editing the entire list of defined abbrevs.
+* Saving Abbrevs:: Saving the entire list of abbrevs for another session.
+* Dynamic Abbrevs:: Abbreviations for words already in the buffer.
+
+Subnodes of Picture
+* Basic Picture:: Basic concepts and simple commands of Picture mode.
+* Insert in Picture:: Controlling direction of cursor motion
+ after "self-inserting" characters.
+* Tabs in Picture:: Various features for tab stops and indentation.
+* Rectangles in Picture:: Clearing and superimposing rectangles.
+
+Subnodes of Sending Mail
+* Mail Format:: Format of the mail being composed.
+* Mail Headers:: Details of allowed mail header fields.
+* Mail Mode:: Special commands for editing mail being composed.
+
+Subnodes of Rmail
+* Rmail Scrolling:: Scrolling through a message.
+* Rmail Motion:: Moving to another message.
+* Rmail Deletion:: Deleting and expunging messages.
+* Rmail Inbox:: How mail gets into the Rmail file.
+* Rmail Files:: Using multiple Rmail files.
+* Rmail Output:: Copying message out to files.
+* Rmail Labels:: Classifying messages by labeling them.
+* Rmail Summary:: Summaries show brief info on many messages.
+* Rmail Reply:: Sending replies to messages you are viewing.
+* Rmail Editing:: Editing message text and headers in Rmail.
+* Rmail Digest:: Extracting the messages from a digest message.
+
+Subnodes of Shell
+* Single Shell:: Commands to run one shell command and return.
+* Interactive Shell:: Permanent shell taking input via Emacs.
+* Shell Mode:: Special Emacs commands used with permanent shell.
+
+Subnodes of Customization
+* Minor Modes:: Each minor mode is one feature you can turn on
+ independently of any others.
+* Variables:: Many Emacs commands examine Emacs variables
+ to decide what to do; by setting variables,
+ you can control their functioning.
+* Examining:: Examining or setting one variable's value.
+* Edit Options:: Examining or editing list of all variables' values.
+* Locals:: Per-buffer values of variables.
+* File Variables:: How files can specify variable values.
+* Keyboard Macros:: A keyboard macro records a sequence of keystrokes
+ to be replayed with a single command.
+* Key Bindings:: The keymaps say what command each key runs.
+ By changing them, you can "redefine keys".
+* Keymaps:: Definition of the keymap data structure.
+* Rebinding:: How to redefine one key's meaning conveniently.
+* Disabling:: Disabling a command means confirmation is required
+ before it can be executed. This is done to protect
+ beginners from surprises.
+* Syntax:: The syntax table controls how words and expressions
+ are parsed.
+* Init File:: How to write common customizations in the `.emacs' file.
+
+Subnodes of Lossage (and recovery)
+* Stuck Recursive:: `[...]' in mode line around the parentheses.
+* Screen Garbled:: Garbage on the screen.
+* Text Garbled:: Garbage in the text.
+* Unasked-for Search::Spontaneous entry to incremental search.
+* Emergency Escape:: Emergency escape--
+ What to do if Emacs stops responding.
+* Total Frustration:: When you are at your wits' end.
+
+
+File: emacs, Node: Distrib, Next: License, Prev: Top, Up: Top
+
+Distribution
+************
+
+ GNU Emacs is "free"; this means that everyone is free to use it and
+free to redistribute it on a free basis. GNU Emacs is not in the public
+domain; it is copyrighted and there are restrictions on its
+distribution, but these restrictions are designed to permit everything
+that a good cooperating citizen would want to do. What is not allowed
+is to try to prevent others from further sharing any version of GNU
+Emacs that they might get from you. The precise conditions are found in
+the GNU General Public License that comes with Emacs and also appears
+following this section.
+
+ The easiest way to get a copy of GNU Emacs 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
+distribution version of GNU Emacs from host `prep.ai.mit.edu' using
+anonymous login. See the file `/u2/emacs/GETTING.GNU.SOFTWARE' on that
+host to find out about your options for copying and which files to use.
+
+ You may also receive GNU Emacs when you buy a computer. Computer
+manufacturers are free to distribute copies on the same terms that
+apply to everyone else. These terms require them to give you the full
+sources, including whatever changes they may have made, and to permit
+you to redistribute the GNU Emacs received from them under the usual
+terms of the General Public License. In other words, the program must
+be free for you when you get it, not just free for the manufacturer.
+
+ If you cannot get a copy in any of those ways, you can order one
+from the Free Software Foundation. Though Emacs itself is free, our
+distribution service is not. An order form is included at the end of
+manuals printed by the Foundation. It is also included in the file
+`etc/DISTRIB' in the Emacs distribution. For further information,
+write to
+
+ Free Software Foundation
+ 675 Mass Ave
+ Cambridge, MA 02139
+ USA
+
+ The income from distribution fees goes to support the foundation's
+purpose: the development of more free software to distribute just like
+GNU Emacs.
+
+ If you find GNU Emacs useful, please send a donation to the Free
+Software Foundation. This will help support development of the rest of
+the GNU system, and other useful software beyond that. Your donation
+is tax deductible.
+
+
+File: emacs, Node: License, Next: Intro, Prev: Distrib, Up: Top
+
+GNU GENERAL PUBLIC LICENSE
+**************************
+
+ Version 1, February 1989
+
+ Copyright (C) 1989 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+Preamble
+========
+
+ The license agreements of most software companies try to keep users
+at the mercy of those companies. By contrast, our General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. The
+General Public License applies to the Free Software Foundation's
+software and to any other program whose authors commit to using it. You
+can use it for your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Specifically, the General Public License is designed to make
+sure that you have the freedom to give away or sell copies of free
+software, that you receive source code or can get it if you want it,
+that you can change the software or use pieces of it in new free
+programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of a such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must tell them their rights.
+
+ We protect your rights with two steps: (1) copyright the software,
+and (2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 1. This License Agreement applies to any program or other work which
+ contains a notice placed by the copyright holder saying it may be
+ distributed under the terms of this General Public License. The
+ "Program", below, refers to any such program or work, and a "work
+ based on the Program" means either the Program or any work
+ containing the Program or a portion of it, either verbatim or with
+ modifications. Each licensee is addressed as "you".
+
+ 2. You may copy and distribute verbatim copies of the Program's source
+ code as you receive it, in any medium, provided that you
+ conspicuously and appropriately publish on each copy an
+ appropriate copyright notice and disclaimer of warranty; keep
+ intact all the notices that refer to this General Public License
+ and to the absence of any warranty; and give any other recipients
+ of the Program a copy of this General Public License along with
+ the Program. You may charge a fee for the physical act of
+ transferring a copy.
+
+ 3. You may modify your copy or copies of the Program or any portion of
+ it, and copy and distribute such modifications under the terms of
+ Paragraph 1 above, provided that you also do the following:
+
+ * cause the modified files to carry prominent notices stating
+ that you changed the files and the date of any change; and
+
+ * cause the whole of any work that you distribute or publish,
+ that in whole or in part contains the Program or any part
+ thereof, either with or without modifications, to be licensed
+ at no charge to all third parties under the terms of this
+ General Public License (except that you may choose to grant
+ warranty protection to some or all third parties, at your
+ option).
+
+ * If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the simplest and most usual way, to print
+ or display an announcement including an appropriate copyright
+ notice and a notice that there is no warranty (or else,
+ saying that you provide a warranty) and that users may
+ redistribute the program under these conditions, and telling
+ the user how to view a copy of this General Public License.
+
+ * You may charge a fee for the physical act of transferring a
+ copy, and you may at your option offer warranty protection in
+ exchange for a fee.
+
+ Mere aggregation of another independent work with the Program (or
+ its derivative) on a volume of a storage or distribution medium
+ does not bring the other work under the scope of these terms.
+
+ 4. You may copy and distribute the Program (or a portion or
+ derivative of it, under Paragraph 2) in object code or executable
+ form under the terms of Paragraphs 1 and 2 above provided that you
+ also do one of the following:
+
+ * accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of
+ Paragraphs 1 and 2 above; or,
+
+ * accompany it with a written offer, valid for at least three
+ years, to give any third party free (except for a nominal
+ charge for the cost of distribution) a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Paragraphs 1 and 2 above; or,
+
+ * accompany it with the information you received as to where the
+ corresponding source code may be obtained. (This alternative
+ is allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form alone.)
+
+ Source code for a work means the preferred form of the work for
+ making modifications to it. For an executable file, complete
+ source code means all the source code for all modules it contains;
+ but, as a special exception, it need not include source code for
+ modules which are standard libraries that accompany the operating
+ system on which the executable file runs, or for standard header
+ files or definitions files that accompany that operating system.
+
+ 5. You may not copy, modify, sublicense, distribute or transfer the
+ Program except as expressly provided under this General Public
+ License. Any attempt otherwise to copy, modify, sublicense,
+ distribute or transfer the Program is void, and will automatically
+ terminate your rights to use the Program under this License.
+ However, parties who have received copies, or rights to use
+ copies, from you under this General Public License will not have
+ their licenses terminated so long as such parties remain in full
+ compliance.
+
+ 6. By copying, distributing or modifying the Program (or any work
+ based on the Program) you indicate your acceptance of this license
+ to do so, and all its terms and conditions.
+
+ 7. Each time you redistribute the Program (or any work based on the
+ Program), the recipient automatically receives a license from the
+ original licensor to copy, distribute or modify the Program
+ subject to these terms and conditions. You may not impose any
+ further restrictions on the recipients' exercise of the rights
+ granted herein.
+
+ 8. The Free Software Foundation may publish revised and/or new
+ versions of the General Public License from time to time. Such
+ new versions will be similar in spirit to the present version, but
+ may differ in detail to address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+ Program specifies a version number of the license which applies to
+ it and "any later version", you have the option of following the
+ terms and conditions either of that version or of any later
+ version published by the Free Software Foundation. If the Program
+ does not specify a version number of the license, you may choose
+ any version ever published by the Free Software Foundation.
+
+ 9. If you wish to incorporate parts of the Program into other free
+ programs whose distribution conditions are different, write to the
+ author to ask for permission. For software which is copyrighted
+ by the Free Software Foundation, write to the Free Software
+ Foundation; we sometimes make exceptions for this. Our decision
+ will be guided by the two goals of preserving the free status of
+ all derivatives of our free software and of promoting the sharing
+ and reuse of software generally.
+
+ NO WARRANTY
+
+ 10. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO
+ WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE
+ LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+ HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT
+ WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT
+ NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE
+ QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+ PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY
+ SERVICING, REPAIR OR CORRECTION.
+
+ 11. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+ WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY
+ MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE
+ LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL,
+ INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR
+ INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+ DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU
+ OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY
+ OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+How to Apply These Terms to Your New Programs
+=============================================
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to humanity, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these
+terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ ONE LINE TO GIVE THE PROGRAM'S NAME AND A BRIEF IDEA OF WHAT IT DOES.
+ Copyright (C) 19YY NAME OF AUTHOR
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Also add information on how to contact you by electronic and paper
+mail.
+
+ If the program is interactive, make it output a short notice like
+this when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19YY NAME OF AUTHOR
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details
+ type `show w'. This is free software, and you are welcome
+ to redistribute it under certain conditions; type `show c'
+ for details.
+
+ The hypothetical commands `show w' and `show c' should show the
+appropriate parts of the General Public License. Of course, the
+commands you use may be called something other than `show w' and `show
+c'; they could even be mouse-clicks or menu items--whatever suits your
+program.
+
+ You should also get your employer (if you work as a programmer) or
+your school, if any, to sign a "copyright disclaimer" for the program,
+if necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright
+ interest in the program `Gnomovision'
+ (a program to direct compilers to make passes
+ at assemblers) written by James Hacker.
+
+ SIGNATURE OF TY COON, 1 April 1989
+ Ty Coon, President of Vice
+
+ That's all there is to it!
+
+
+File: emacs, Node: Intro, Next: Glossary, Prev: License, Up: Top
+
+Introduction
+************
+
+ You are reading about GNU Emacs, the GNU incarnation of the advanced,
+self-documenting, customizable, extensible real-time display editor
+Emacs. (The `G' in `GNU' is not silent.)
+
+ We say that Emacs is a "display" editor because normally the text
+being edited is visible on the screen and is updated automatically as
+you type your commands. *Note Display: Screen.
+
+ We call it a "real-time" editor because the display is updated very
+frequently, usually after each character or pair of characters you
+type. This minimizes the amount of information you must keep in your
+head as you edit. *Note Real-time: Basic.
+
+ We call Emacs advanced because it provides facilities that go beyond
+simple insertion and deletion: filling of text; automatic indentation of
+programs; viewing two or more files at once; and dealing in terms of
+characters, words, lines, sentences, paragraphs, and pages, as well as
+expressions and comments in several different programming languages.
+It is much easier to type one command meaning "go to the end of the
+paragraph" than to find that spot with simple cursor keys.
+
+ "Self-documenting" means that at any time you can type a special
+character, `Control-h', to find out what your options are. You can
+also use it to find out what any command does, or to find all the
+commands that pertain to a topic. *Note Help::.
+
+ "Customizable" means that you can change the definitions of Emacs
+commands in little ways. For example, if you use a programming
+language in which comments start with `<**' and end with `**>', you can
+tell the Emacs comment manipulation commands to use those strings
+(*note Comments::.). Another sort of customization is rearrangement of
+the command set. For example, if you prefer the four basic cursor
+motion commands (up, down, left and right) on keys in a diamond pattern
+on the keyboard, you can have it. *Note Customization::.
+
+ "Extensible" means that you can go beyond simple customization and
+write entirely new commands, programs in the Lisp language to be run by
+Emacs's own Lisp interpreter. Emacs is an "on-line extensible" system,
+which means that it is divided into many functions that call each other,
+any of which can be redefined in the middle of an editing session. Any
+part of Emacs can be replaced without making a separate copy of all of
+Emacs. Most of the editing commands of Emacs are written in Lisp
+already; the few exceptions could have been written in Lisp but are
+written in C for efficiency. Although only a programmer can write an
+extension, anybody can use it afterward.
+
+
+File: emacs, Node: Screen, Next: Characters, Prev: Concept Index, Up: Top
+
+The Organization of the Screen
+******************************
+
+ Emacs divides the screen into several areas, each of which contains
+its own sorts of information. The biggest area, of course, is the one
+in which you usually see the text you are editing.
+
+ When you are using Emacs, the screen is divided into a number of
+"windows". Initially there is one text window occupying all but the
+last line, plus the special "echo area" or "minibuffer window" in the
+last line. The text window can be subdivided horizontally or
+vertically into multiple text windows, each of which can be used for a
+different file (*note Windows::.). The window that the cursor is in is
+the "selected window", in which editing takes place. The other windows
+are just for reference unless you select one of them.
+
+ Each text window's last line is a "mode line" which describes what is
+going on in that window. It is in inverse video if the terminal
+supports that, and contains text that starts like `-----Emacs:
+SOMETHING'. Its purpose is to indicate what buffer is being displayed
+above it in the window; what major and minor modes are in use; and
+whether the buffer's text has been changed.
+
+* Menu:
+
+* Point:: The place in the text where editing commands operate.
+* Echo Area:: Short messages appear at the bottom of the screen.
+* Mode Line:: Interpreting the mode line.
+
+
+File: emacs, Node: Point, Next: Echo Area, Prev: Screen, Up: Screen
+
+Point
+=====
+
+ When Emacs is running, the terminal's cursor shows the location at
+which editing commands will take effect. This location is called
+"point". Other commands move point through the text, so that you can
+edit at different places in it.
+
+ While the cursor appears to point AT a character, point should be
+thought of as BETWEEN two characters; it points BEFORE the character
+that the cursor appears on top of. Sometimes people speak of "the
+cursor" when they mean "point", or speak of commands that move point as
+"cursor motion" commands.
+
+ Terminals have only one cursor, and when output is in progress it
+must appear where the typing is being done. This does not mean that
+point is moving. It is only that Emacs has no way to show you the
+location of point except when the terminal is idle.
+
+ If you are editing several files in Emacs, each file has its own
+point location. A file that is not being displayed remembers where
+point is so that it can be seen when you look at that file again.
+
+ When there are multiple text windows, each window has its own point
+location. The cursor shows the location of point in the selected
+window. This also is how you can tell which window is selected. If the
+same buffer appears in more than one window, point can be moved in each
+window independently.
+
+ The term `point' comes from the character `.', which was the command
+in TECO (the language in which the original Emacs was written) for
+accessing the value now called `point'.
+
+
+File: emacs, Node: Echo Area, Next: Mode Line, Prev: Point, Up: Screen
+
+The Echo Area
+=============
+
+ The line at the bottom of the screen (below the mode line) is the
+"echo area". It is used to display small amounts of text for several
+purposes.
+
+ "Echoing" means printing out the characters that you type. Emacs
+never echoes single-character commands, and multi-character commands are
+echoed only if you pause while typing them. As soon as you pause for
+more than a second in the middle of a command, all the characters of
+the command so far are echoed. This is intended to "prompt" you for
+the rest of the command. Once echoing has started, the rest of the
+command is echoed immediately when you type it. This behavior is
+designed to give confident users fast response, while giving hesitant
+users maximum feedback. You can change this behavior by setting a
+variable (*note Display Vars::.).
+
+ If a command cannot be executed, it may print an "error message" in
+the echo area. Error messages are accompanied by a beep or by flashing
+the screen. Also, any input you have typed ahead is thrown away when
+an error happens.
+
+ Some commands print informative messages in the echo area. These
+messages look much like error messages, but they are not announced with
+a beep and do not throw away input. Sometimes the message tells you
+what the command has done, when this is not obvious from looking at the
+text being edited. Sometimes the sole purpose of a command is to print
+a message giving you specific information. For example, the command
+`C-x =' is used to print a message describing the character position of
+point in the text and its current column in the window. Commands that
+take a long time often display messages ending in `...' while they are
+working, and add `done' at the end when they are finished.
+
+ The echo area is also used to display the "minibuffer", a window that
+is used for reading arguments to commands, such as the name of a file
+to be edited. When the minibuffer is in use, the echo area begins with
+a prompt string that usually ends with a colon; also, the cursor
+appears in that line because it is the selected window. You can always
+get out of the minibuffer by typing `C-g'. *Note Minibuffer::.
+
+
+File: emacs, Node: Mode Line, Prev: Echo Area, Up: Screen
+
+The Mode Line
+=============
+
+ Each text window's last line is a "mode line" which describes what is
+going on in that window. When there is only one text window, the mode
+line appears right above the echo area. The mode line is in inverse
+video if the terminal supports that, starts and ends with dashes, and
+contains text like `Emacs: SOMETHING'.
+
+ If a mode line has something else in place of `Emacs: SOMETHING',
+then the window above it is in a special subsystem such as Dired. The
+mode line then indicates the status of the subsystem.
+
+ Normally, the mode line has the following appearance:
+
+ --CH-Emacs: BUF (MAJOR MINOR)----POS------
+
+This gives information about the buffer being displayed in the window:
+the buffer's name, what major and minor modes are in use, whether the
+buffer's text has been changed, and how far down the buffer you are
+currently looking.
+
+ CH contains two stars `**' if the text in the buffer has been edited
+(the buffer is "modified"), or `--' if the buffer has not been edited.
+Exception: for a read-only buffer, it is `%%'.
+
+ BUF is the name of the window's chosen "buffer". The chosen buffer
+in the selected window (the window that the cursor is in) is also
+Emacs's selected buffer, the one that editing takes place in. When we
+speak of what some command does to "the buffer", we are talking about
+the currently selected buffer. *Note Buffers::.
+
+ POS tells you whether there is additional text above the top of the
+screen, or below the bottom. If your file is small and it is all on the
+screen, POS is `All'. Otherwise, it is `Top' if you are looking at the
+beginning of the file, `Bot' if you are looking at the end of the file,
+or `NN%', where NN is the percentage of the file above the top of the
+screen.
+
+ MAJOR is the name of the "major mode" in effect in the buffer. At
+any time, each buffer is in one and only one of the possible major
+modes. The major modes available include Fundamental mode (the least
+specialized), Text mode, Lisp mode, and C mode. *Note Major Modes::,
+for details of how the modes differ and how to select one.
+
+ MINOR is a list of some of the "minor modes" that are turned on at
+the moment in the window's chosen buffer. `Fill' means that Auto Fill
+mode is on. `Abbrev' means that Word Abbrev mode is on. `Ovwrt' means
+that Overwrite mode is on. *Note Minor Modes::, for more information.
+`Narrow' means that the buffer being displayed has editing restricted
+to only a portion of its text. This is not really a minor mode, but is
+like one. *Note Narrowing::. `Def' means that a keyboard macro is
+being defined. *Note Keyboard Macros::.
+
+ Some buffers display additional information after the minor modes.
+For example, Rmail buffers display the current message number and the
+total number of messages. Compilation buffers and Shell mode display
+the status of the subprocess.
+
+ In addition, if Emacs is currently inside a recursive editing level,
+square brackets (`[...]') appear around the parentheses that surround
+the modes. If Emacs is in one recursive editing level within another,
+double square brackets appear, and so on. Since this information
+pertains to Emacs in general and not to any one buffer, the square
+brackets appear in every mode line on the screen or not in any of them.
+*Note Recursive Edit::.
+
+ Emacs can optionally display the time and system load in all mode
+lines. To enable this feature, type `M-x display-time'. The
+information added to the mode line usually appears after the file name,
+before the mode names and their parentheses. It looks like this:
+
+ HH:MMpm L.LL [D]
+
+(Some fields may be missing if your operating system cannot support
+them.) HH and MM are the hour and minute, followed always by `am' or
+`pm'. L.LL is the average number of running processes in the whole
+system recently. D is an approximate index of the ratio of disk
+activity to cpu activity for all users.
+
+ The word `Mail' appears after the load level if there is mail for
+you that you have not read yet.
+
+ Customization note: the user variable `mode-line-inverse-video'
+controls whether the mode line is displayed in inverse video (assuming
+the terminal supports it); `nil' means no inverse video. The default
+is `t'.
+
+
+File: emacs, Node: Characters, Next: Keys, Prev: Screen, Up: Top
+
+The Emacs Character Set
+=======================
+
+ GNU Emacs uses the ASCII character set, which defines 128 different
+character codes. Some of these codes are assigned graphic symbols such
+as `a' and `='; the rest are control characters, such as `Control-a'
+(also called `C-a' for short). `C-a' gets its name from the fact that
+you type it by holding down the CTRL key and then pressing `a'. There
+is no distinction between `C-a' and `C-A'; they are the same character.
+
+ Some control characters have special names, and special keys you can
+type them with: RET, TAB, LFD, DEL and ESC. The space character is
+usually referred to below as SPC, even though strictly speaking it is a
+graphic character whose graphic happens to be blank.
+
+ Emacs extends the 7-bit ASCII code to an 8-bit code by adding an
+extra bit to each character. This makes 256 possible command
+characters. The additional bit is called Meta. Any ASCII character
+can be made Meta; examples of Meta characters include `Meta-a' (`M-a',
+for short), `M-A' (not the same character as `M-a', but those two
+characters normally have the same meaning in Emacs), `M-RET', and
+`M-C-a'. For traditional reasons, `M-C-a' is usually called `C-M-a';
+logically speaking, the order in which the modifier keys CTRL and META
+are mentioned does not matter.
+
+ Some terminals have a META key, and allow you to type Meta
+characters by holding this key down. Thus, `Meta-a' is typed by
+holding down META and pressing `a'. The META key works much like the
+SHIFT key. Such a key is not always labeled META, however, as this
+function is often a special option for a key with some other primary
+purpose.
+
+ If there is no META key, you can still type Meta characters using
+two-character sequences starting with ESC. Thus, to enter `M-a', you
+could type `ESC a'. To enter `C-M-a', you would type `ESC C-a'. ESC is
+allowed on terminals with Meta keys, too, in case you have formed a
+habit of using it.
+
+ Emacs believes the terminal has a META key if the variable
+`meta-flag' is non-`nil'. Normally this is set automatically according
+to the termcap entry for your terminal type. However, sometimes the
+termcap entry is wrong, and then it is useful to set this variable
+yourself. *Note Variables::, for how to do this.
+
+ Emacs buffers also use an 8-bit character set, because bytes have 8
+bits, but only the ASCII characters are considered meaningful. ASCII
+graphic characters in Emacs buffers are displayed with their graphics.
+LFD is the same as a newline character; it is displayed by starting a
+new line. TAB is displayed by moving to the next tab stop column
+(usually every 8 columns). Other control characters are displayed as a
+caret (`^') followed by the non-control version of the character; thus,
+`C-a' is displayed as `^A'. Non-ASCII characters 128 and up are
+displayed with octal escape sequences; thus, character code 243
+(octal), also called `M-#' when used as an input character, is
+displayed as `\243'.
+
+
+File: emacs, Node: Keys, Next: Commands, Prev: Characters, Up: Top
+
+Keys
+====
+
+ A "complete key"--where `key' is short for "key sequence"--is a
+sequence of keystrokes that are understood by Emacs as a unit, as a
+single command (possibly undefined). Most single characters constitute
+complete keys in the standard Emacs command set; there are also some
+multi-character keys. Examples of complete keys are `C-a', `X', RET,
+`C-x C-f' and `C-x 4 C-f'.
+
+ A "prefix key" is a sequence of keystrokes that are the beginning of
+a complete key, but not a whole one. Prefix keys and complete keys are
+collectively called "keys".
+
+ A prefix key is the beginning of a series of longer sequences that
+are valid keys; adding any single character to the end of the prefix
+gives a valid key, which could be defined as an Emacs command, or could
+be a prefix itself. For example, `C-x' is standardly defined as a
+prefix, so `C-x' and the next input character combine to make a
+two-character key. There are 256 different two-character keys starting
+with `C-x', one for each possible second character. Many of these
+two-character keys starting with `C-x' are standardly defined as Emacs
+commands. Notable examples include `C-x C-f' and `C-x s' (*note
+Files::.).
+
+ Adding one character to a prefix key does not have to form a complete
+key. It could make another, longer prefix. For example, `C-x 4' is
+itself a prefix that leads to 256 different three-character keys,
+including `C-x 4 f', `C-x 4 b' and so on. It would be possible to
+define one of those three-character sequences as a prefix, creating a
+series of four-character keys, but we did not define any of them this
+way.
+
+ By contrast, the two-character sequence `C-f C-k' is not a key,
+because the `C-f' is a complete key in itself. It's impossible to give
+`C-f C-k' an independent meaning as a command as long as `C-f' retains
+its meaning. `C-f C-k' is two commands.
+
+ All told, the prefix keys in Emacs are `C-c', `C-x', `C-h', `C-x 4',
+and ESC. But this is not built in; it is just a matter of Emacs's
+standard key bindings. In customizing Emacs, you could make new prefix
+keys, or eliminate these. *Note Key Bindings::.
+
+ Whether a sequence is a key can be changed by customization. For
+example, if you redefine `C-f' as a prefix, `C-f C-k' automatically
+becomes a key (complete, unless you define it too as a prefix).
+Conversely, if you remove the prefix definition of `C-x 4', then `C-x 4
+f' (or `C-x 4 ANYTHING') is no longer a key.
+
+ \ No newline at end of file
diff --git a/info/emacs-10 b/info/emacs-10
new file mode 100644
index 00000000000..fff4cd44322
--- /dev/null
+++ b/info/emacs-10
@@ -0,0 +1,1131 @@
+This is Info file ../info/emacs, produced by Makeinfo-1.49 from the
+input file emacs.texi.
+
+ This file documents the GNU Emacs editor.
+
+ Copyright (C) 1985, 1986, 1988, 1992 Richard M. Stallman.
+
+ Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+ Permission is granted to copy and distribute modified versions of
+this manual under the conditions for verbatim copying, provided also
+that the sections entitled "The GNU Manifesto", "Distribution" and "GNU
+General Public License" are included exactly as in the original, and
+provided that the entire resulting derived work is distributed under the
+terms of a permission notice identical to this one.
+
+ Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that the sections entitled "The GNU Manifesto",
+"Distribution" and "GNU General Public License" may be included in a
+translation approved by the author instead of in the original English.
+
+
+File: emacs, Node: Rmail Motion, Next: Rmail Deletion, Prev: Rmail Scrolling, Up: Rmail
+
+Moving Among Messages
+=====================
+
+ The most basic thing to do with a message is to read it. The way to
+do this in Rmail is to make the message current. You can make any
+message current given its message number using the `j' command, but the
+usual thing to do is to move sequentially through the file, since this
+is the order of receipt of messages. When you enter Rmail, you are
+positioned at the first new message (new messages are those received
+since the previous use of Rmail), or at the last message if there are
+no new messages this time. Move forward to see the other new messages;
+move backward to reexamine old messages.
+
+`n'
+ Move to the next nondeleted message, skipping any intervening
+ deleted messages (`rmail-next-undeleted-message').
+
+`p'
+ Move to the previous nondeleted message
+ (`rmail-previous-undeleted-message').
+
+`M-n'
+ Move to the next message, including deleted messages
+ (`rmail-next-message').
+
+`M-p'
+ Move to the previous message, including deleted messages
+ (`rmail-previous-message').
+
+`j'
+ Move to the first message. With argument N, move to message
+ number N (`rmail-show-message').
+
+`>'
+ Move to the last message (`rmail-last-message').
+
+`M-s REGEXP RET'
+ Move to the next message containing a match for REGEXP
+ (`rmail-search'). If REGEXP is empty, the last regexp used is
+ used again.
+
+`- M-s REGEXP RET'
+ Move to the previous message containing a match for REGEXP. If
+ REGEXP is empty, the last regexp used is used again.
+
+ `n' and `p' are the usual way of moving among messages in Rmail.
+They move through the messages sequentially, but skip over deleted
+messages, which is usually what you want to do. Their command
+definitions are named `rmail-next-undeleted-message' and
+`rmail-previous-undeleted-message'. If you do not want to skip deleted
+messages--for example, if you want to move to a message to undelete
+it--use the variants `M-n' and `M-p' (`rmail-next-message' and
+`rmail-previous-message'). A numeric argument to any of these commands
+serves as a repeat count.
+
+ In Rmail, you can specify a numeric argument by typing the digits.
+It is not necessary to type `C-u' first.
+
+ The `M-s' (`rmail-search') command is Rmail's version of search. The
+usual incremental search command `C-s' works in Rmail, but it searches
+only within the current message. The purpose of `M-s' is to search for
+another message. It reads a regular expression (*note Regexps::.)
+nonincrementally, then searches starting at the beginning of the
+following message for a match. The message containing the match is
+selected.
+
+ To search backward in the file for another message, give `M-s' a
+negative argument. In Rmail this can be done with `- M-s'.
+
+ It is also possible to search for a message based on labels. *Note
+Rmail Labels::.
+
+ To move to a message specified by absolute message number, use `j'
+(`rmail-show-message') with the message number as argument. With no
+argument, `j' selects the first message. `>' (`rmail-last-message')
+selects the last message.
+
+ Each time Rmail selects a message, it calls (with no arguments) the
+value of the variable `rmail-show-message-hook', if that is non-`nil'.
+
+
+File: emacs, Node: Rmail Deletion, Next: Rmail Inbox, Prev: Rmail Motion, Up: Rmail
+
+Deleting Messages
+=================
+
+ When you no longer need to keep a message, you can "delete" it. This
+flags it as ignorable, and some Rmail commands will pretend it is no
+longer present; but it still has its place in the Rmail file, and still
+has its message number.
+
+ "Expunging" the Rmail file actually removes the deleted messages.
+The remaining messages are renumbered consecutively. Expunging is the
+only action that changes the message number of any message, except for
+undigestifying (*note Rmail Digest::.).
+
+`d'
+ Delete the current message, and move to the next nondeleted message
+ (`rmail-delete-forward').
+
+`C-d'
+ Delete the current message, and move to the previous nondeleted
+ message (`rmail-delete-backward').
+
+`u'
+ Undelete the current message, or move back to a deleted message and
+ undelete it (`rmail-undelete-previous-message').
+
+`x'
+`e'
+ Expunge the Rmail file (`rmail-expunge'). These two commands are
+ synonyms.
+
+ There are two Rmail commands for deleting messages. Both delete the
+current message and select another message. `d'
+(`rmail-delete-forward') moves to the following message, skipping
+messages already deleted, while `C-d' (`rmail-delete-backward') moves
+to the previous nondeleted message. If there is no nondeleted message
+to move to in the specified direction, the message that was just
+deleted remains current.
+
+ To make all the deleted messages finally vanish from the Rmail file,
+type `e' (`rmail-expunge'). Until you do this, you can still "undelete"
+the deleted messages.
+
+ To undelete, type `u' (`rmail-undelete-previous-message'), which is
+designed to cancel the effect of a `d' command (usually). It undeletes
+the current message if the current message is deleted. Otherwise it
+moves backward to previous messages until a deleted message is found,
+and undeletes that message.
+
+ You can usually undo a `d' with a `u' because the `u' moves back to
+and undeletes the message that the `d' deleted. But this does not work
+when the `d' skips a few already-deleted messages that follow the
+message being deleted; then the `u' command will undelete the last of
+the messages that were skipped. There is no clean way to avoid this
+problem. However, by repeating the `u' command, you can eventually get
+back to the message that you intended to undelete. You can also reach
+that message with `M-p' commands and then type `u'.
+
+ A deleted message has the `deleted' attribute, and as a result
+`deleted' appears in the mode line when the current message is deleted.
+ In fact, deleting or undeleting a message is nothing more than adding
+or removing this attribute. *Note Rmail Labels::.
+
+
+File: emacs, Node: Rmail Inbox, Next: Rmail Files, Prev: Rmail Deletion, Up: Rmail
+
+Rmail Files and Inboxes
+=======================
+
+ Unix places incoming mail for you in a file that we call your
+"inbox". When you start up Rmail, it copies the new messages from your
+inbox into your primary mail file, an Rmail file, which also contains
+other messages saved from previous Rmail sessions. It is in this file
+that you actually read the mail with Rmail. This operation is called
+"getting new mail". It can be repeated at any time using the `g' key in
+Rmail. The inbox file name is `/usr/spool/mail/USERNAME' in Berkeley
+Unix, `/usr/mail/USERNAME' in System V.
+
+ There are two reasons for having separate Rmail files and inboxes.
+
+ 1. The format in which Unix delivers the mail in the inbox is not
+ adequate for Rmail mail storage. It has no way to record
+ attributes (such as `deleted') or user-specified labels; it has no
+ way to record old headers and reformatted headers; it has no way
+ to record cached summary line information.
+
+ 2. It is very cumbersome to access an inbox file without danger of
+ losing mail, because it is necessary to interlock with mail
+ delivery. Moreover, different Unix systems use different
+ interlocking techniques. The strategy of moving mail out of the
+ inbox once and for all into a separate Rmail file avoids the need
+ for interlocking in all the rest of Rmail, since only Rmail
+ operates on the Rmail file.
+
+ When getting new mail, Rmail first copies the new mail from the inbox
+file to the Rmail file; then it saves the Rmail file; then it deletes
+the inbox file. This way, a system crash may cause duplication of mail
+between the inbox and the Rmail file, but cannot lose mail.
+
+ Copying mail from an inbox in the system's mailer directory actually
+puts it in an intermediate file `~/.newmail'. This is because the
+interlocking is done by a C program that copies to another file.
+`~/.newmail' is deleted after mail merging is successful. If there is
+a crash at the wrong time, this file will continue to exist and will be
+used as an inbox the next time you get new mail.
+
+
+File: emacs, Node: Rmail Files, Next: Rmail Output, Prev: Rmail Inbox, Up: Rmail
+
+Multiple Mail Files
+===================
+
+ Rmail operates by default on your "primary mail file", which is named
+`~/RMAIL' and receives your incoming mail from your system inbox file.
+But you can also have other mail files and edit them with Rmail. These
+files can receive mail through their own inboxes, or you can move
+messages into them by explicit command in Rmail (*note Rmail Output::.).
+
+`i FILE RET'
+ Read FILE into Emacs and run Rmail on it (`rmail-input').
+
+`M-x set-rmail-inbox-list RET FILES RET'
+ Specify inbox file names for current Rmail file to get mail from.
+
+`g'
+ Merge new mail from current Rmail file's inboxes
+ (`rmail-get-new-mail').
+
+`C-u g FILE'
+ Merge new mail from inbox file FILE.
+
+ To run Rmail on a file other than your primary mail file, you may
+use the `i' (`rmail-input') command in Rmail. This visits the file,
+puts it in Rmail mode, and then gets new mail from the file's inboxes
+if any. You can also use `M-x rmail-input' even when not in Rmail.
+
+ The file you read with `i' does not have to be in Rmail file format.
+It could also be Unix mail format, or `mmdf' format; or it could be a
+mixture of all three, as long as each message belongs to one of the
+three formats. Rmail recognizes all three and converts all the
+messages to proper Rmail format before showing you the file.
+
+ Each Rmail file can contain a list of inbox file names; you can
+specify this list with `M-x set-rmail-inbox-list RET FILES RET'. The
+argument can contain any number of file names, separated by commas. It
+can also be empty, which specifies that this file should have no
+inboxes. Once a list of inboxes is specified, the Rmail file remembers
+it permanently until it is explicitly changed.
+
+ If an Rmail file has inboxes, new mail is merged in from the inboxes
+when the Rmail file is brought into Rmail, and when the `g'
+(`rmail-get-new-mail') command is used. If the Rmail file specifies no
+inboxes, then no new mail is merged in at these times. A special
+exception is made for your primary mail file in using the standard
+system inbox for it if it does not specify any.
+
+ To merge mail from a file that is not the usual inbox, give the `g'
+key a numeric argument, as in `C-u g'. Then it reads a file name and
+merges mail from that file. The inbox file is not deleted or changed in
+any way when `g' with an argument is used. This is, therefore, a
+general way of merging one file of messages into another.
+
+
+File: emacs, Node: Rmail Output, Next: Rmail Labels, Prev: Rmail Files, Up: Rmail
+
+Copying Messages Out to Files
+=============================
+
+`o FILE RET'
+ Append a copy of the current message to the file FILE, writing it
+ in Rmail file format (`rmail-output-to-rmail-file').
+
+`C-o FILE RET'
+ Append a copy of the current message to the file FILE, writing it
+ in Unix mail file format (`rmail-output').
+
+ If an Rmail file has no inboxes, how does it get anything in it? By
+explicit `o' commands.
+
+ `o' (`rmail-output-to-rmail-file') appends the current message in
+Rmail format to the end of the specified file. This is the best command
+to use to move messages between Rmail files. If the other Rmail file is
+currently visited, the copying is done into the other file's Emacs
+buffer instead. You should eventually save it on disk.
+
+ The `C-o' (`rmail-output') command in Rmail appends a copy of the
+current message to a specified file, in Unix mail file format. This is
+useful for moving messages into files to be read by other mail
+processors that do not understand Rmail format.
+
+ Copying a message with `o' or `C-o' gives the original copy of the
+message the `filed' attribute, so that `filed' appears in the mode line
+when such a message is current.
+
+ Normally you should use only `o' to output messages to other Rmail
+files, never `C-o'. But it is also safe if you always use `C-o', never
+`o'. When a file is visited in Rmail, the last message is checked, and
+if it is in Unix format, the entire file is scanned and all Unix-format
+messages are converted to Rmail format. (The reason for checking the
+last message is that scanning the file is slow and most Rmail files
+have only Rmail format messages.) If you use `C-o' consistently, the
+last message is sure to be in Unix format, so Rmail will convert all
+messages properly.
+
+ The case where you might want to use `C-o' always, instead of `o'
+always, is when you or other users want to append mail to the same file
+from other mail processors. Other mail processors probably do not know
+Rmail format but do know Unix format.
+
+ In any case, always use `o' to add to an Rmail file that is being
+visited in Rmail. Adding messages with `C-o' to the actual disk file
+will trigger a "simultaneous editing" warning when you ask to save the
+Emacs buffer, and will be lost if you do save.
+
+
+File: emacs, Node: Rmail Labels, Next: Rmail Summary, Prev: Rmail Output, Up: Rmail
+
+Labels
+======
+
+ Each message can have various "labels" assigned to it as a means of
+classification. A label has a name; different names mean different
+labels. Any given label is either present or absent on a particular
+message. A few label names have standard meanings and are given to
+messages automatically by Rmail when appropriate; these special labels
+are called "attributes". All other labels are assigned by the user.
+
+`a LABEL RET'
+ Assign the label LABEL to the current message (`rmail-add-label').
+
+`k LABEL RET'
+ Remove the label LABEL from the current message
+ (`rmail-kill-label').
+
+`C-M-n LABELS RET'
+ Move to the next message that has one of the labels LABELS
+ (`rmail-next-labeled-message').
+
+`C-M-p LABELS RET'
+ Move to the previous message that has one of the labels LABELS
+ (`rmail-previous-labeled-message').
+
+`C-M-l LABELS RET'
+ Make a summary of all messages containing any of the labels LABELS
+ (`rmail-summary-by-labels').
+
+Specifying an empty string for one these commands means to use the last
+label specified for any of these commands.
+
+ The `a' (`rmail-add-label') and `k' (`rmail-kill-label') commands
+allow you to assign or remove any label on the current message. If the
+LABEL argument is empty, it means to assign or remove the same label
+most recently assigned or removed.
+
+ Once you have given messages labels to classify them as you wish,
+there are two ways to use the labels: in moving and in summaries.
+
+ The command `C-M-n LABELS RET' (`rmail-next-labeled-message') moves
+to the next message that has one of the labels LABELS. LABELS is one
+or more label names, separated by commas. `C-M-p'
+(`rmail-previous-labeled-message') is similar, but moves backwards to
+previous messages. A preceding numeric argument to either one serves
+as a repeat count.
+
+ The command `C-M-l LABELS RET' (`rmail-summary-by-labels') displays
+a summary containing only the messages that have at least one of a
+specified set of messages. The argument LABELS is one or more label
+names, separated by commas. *Note Rmail Summary::, for information on
+summaries.
+
+ If the LABELS argument to `C-M-n', `C-M-p' or `C-M-l' is empty, it
+means to use the last set of labels specified for any of these commands.
+
+ Some labels such as `deleted' and `filed' have built-in meanings and
+are assigned to or removed from messages automatically at appropriate
+times; these labels are called "attributes". Here is a list of Rmail
+attributes:
+
+`unseen'
+ Means the message has never been current. Assigned to messages
+ when they come from an inbox file, and removed when a message is
+ made current.
+
+`deleted'
+ Means the message is deleted. Assigned by deletion commands and
+ removed by undeletion commands (*note Rmail Deletion::.).
+
+`filed'
+ Means the message has been copied to some other file. Assigned by
+ the file output commands (*note Rmail Files::.).
+
+`answered'
+ Means you have mailed an answer to the message. Assigned by the
+ `r' command (`rmail-reply'). *Note Rmail Reply::.
+
+`forwarded'
+ Means you have forwarded the message to other users. Assigned by
+ the `f' command (`rmail-forward'). *Note Rmail Reply::.
+
+`edited'
+ Means you have edited the text of the message within Rmail. *Note
+ Rmail Editing::.
+
+ All other labels are assigned or removed only by the user, and it is
+up to the user to decide what they mean.
+
+
+File: emacs, Node: Rmail Summary, Next: Rmail Reply, Prev: Rmail Labels, Up: Rmail
+
+Summaries
+=========
+
+ A "summary" is a buffer containing one line per message that Rmail
+can make and display to give you an overview of the mail in an Rmail
+file. Each line shows the message number, the sender, the labels, and
+the subject. When the summary buffer is selected, various commands can
+be used to select messages by moving in the summary buffer, or delete
+or undelete messages.
+
+ A summary buffer applies to a single Rmail file only; if you are
+editing multiple Rmail files, they have separate summary buffers. The
+summary buffer name is made by appending `-summary' to the Rmail
+buffer's name. Only one summary buffer will be displayed at a time
+unless you make several windows and select the summary buffers by hand.
+
+* Menu:
+
+* Rmail Make Summary:: Making various sorts of summaries.
+* Rmail Summary Edit:: Manipulating messages from the summary.
+
+
+File: emacs, Node: Rmail Make Summary, Next: Rmail Summary Edit, Prev: Rmail Summary, Up: Rmail Summary
+
+Making Summaries
+----------------
+
+ Here are the commands to create a summary for the current Rmail file.
+Summaries do not update automatically; to make an updated summary, you
+must use one of these commands again.
+
+`h'
+`C-M-h'
+ Summarize all messages (`rmail-summary').
+
+`l LABELS RET'
+`C-M-l LABELS RET'
+ Summarize message that have one or more of the specified labels
+ (`rmail-summary-by-labels').
+
+`C-M-r RCPTS RET'
+ Summarize messages that have one or more of the specified
+ recipients (`rmail-summary-by-recipients').
+
+ The `h' or `C-M-h' (`rmail-summary') command fills the summary buffer
+for the current Rmail file with a summary of all the messages in the
+file. It then displays and selects the summary buffer in another window.
+
+ `C-M-l LABELS RET' (`rmail-summary-by-labels') makes a partial
+summary mentioning only the messages that have one or more of the
+labels LABELS. LABELS should contain label names separated by commas.
+
+ `C-M-r RCPTS RET' (`rmail-summary-by-recipients') makes a partial
+summary mentioning only the messages that have one or more of the
+recipients RCPTS. RCPTS should contain mailing addresses separated by
+commas.
+
+ Note that there is only one summary buffer for any Rmail file;
+making one kind of summary discards any previously made summary.
+
+
+File: emacs, Node: Rmail Summary Edit, Prev: Rmail Make Summary, Up: Rmail Summary
+
+Editing in Summaries
+--------------------
+
+ Summary buffers are given the major mode Rmail Summary mode, which
+provides the following special commands:
+
+`j'
+ Select the message described by the line that point is on
+ (`rmail-summary-goto-msg').
+
+`C-n'
+ Move to next line and select its message in Rmail
+ (`rmail-summary-next-all').
+
+`C-p'
+ Move to previous line and select its message
+ (`rmail-summary-previous-all').
+
+`n'
+ Move to next line, skipping lines saying `deleted', and select its
+ message (`rmail-summary-next-msg').
+
+`p'
+ Move to previous line, skipping lines saying `deleted', and select
+ its message (`rmail-summary-previous-msg').
+
+`d'
+ Delete the current line's message, then do like `n'
+ (`rmail-summary-delete-forward').
+
+`u'
+ Undelete and select this message or the previous deleted message in
+ the summary (`rmail-summary-undelete').
+
+`SPC'
+ Scroll the other window (presumably Rmail) forward
+ (`rmail-summary-scroll-msg-up').
+
+`DEL'
+ Scroll the other window backward (`rmail-summary-scroll-msg-down').
+
+`x'
+ Kill the summary window (`rmail-summary-exit').
+
+`q'
+ Exit Rmail (`rmail-summary-quit').
+
+ The keys `C-n' and `C-p' are modified in Rmail Summary mode so that
+in addition to moving point in the summary buffer they also cause the
+line's message to become current in the associated Rmail buffer. That
+buffer is also made visible in another window if it is not already so.
+
+ `n' and `p' are similar to `C-n' and `C-p', but skip lines that say
+`message deleted'. They are like the `n' and `p' keys of Rmail itself.
+ Note, however, that in a partial summary these commands move only
+among the message listed in the summary.
+
+ The other Emacs cursor motion commands are not changed in Rmail
+Summary mode, so it is easy to get the point on a line whose message is
+not selected in Rmail. This can also happen if you switch to the Rmail
+window and switch messages there. To get the Rmail buffer back in sync
+with the summary, use the `j' (`rmail-summary-goto-msg') command, which
+selects in Rmail the message of the current summary line.
+
+ Deletion and undeletion can also be done from the summary buffer.
+They always work based on where point is located in the summary buffer,
+ignoring which message is selected in Rmail. `d'
+(`rmail-summary-delete-forward') deletes the current line's message,
+then moves to the next line whose message is not deleted and selects
+that message. The inverse of this is `u' (`rmail-summary-undelete'),
+which moves back (if necessary) to a line whose message is deleted,
+undeletes that message, and selects it in Rmail.
+
+ When moving through messages with the summary buffer, it is
+convenient to be able to scroll the message while remaining in the
+summary window. The commands SPC (`rmail-summary-scroll-msg-up') and DEL
+(`rmail-summary-scroll-msg-down') do this. They scroll the message just
+as those same keys do when the Rmail buffer is selected.
+
+ When you are finished using the summary, type `x'
+(`rmail-summary-exit') to kill the summary buffer's window.
+
+ You can also exit Rmail while in the summary. `q'
+(`rmail-summary-quit') kills the summary window, then saves the Rmail
+file and switches to another buffer.
+
+
+File: emacs, Node: Rmail Reply, Next: Rmail Editing, Prev: Rmail Summary, Up: Rmail
+
+Sending Replies
+===============
+
+ Rmail has several commands that use Mail mode to send outgoing mail.
+*Note Sending Mail::, for information on using Mail mode. What are
+documented here are the special commands of Rmail for entering Mail
+mode. Note that the usual keys for sending mail, `C-x m' and `C-x 4 m',
+are available in Rmail mode and work just as they usually do.
+
+`m'
+ Send a message (`rmail-mail').
+
+`c'
+ Continue editing already started outgoing message
+ (`rmail-continue').
+
+`r'
+ Send a reply to the current Rmail message (`rmail-reply').
+
+`f'
+ Forward current message to other users (`rmail-forward').
+
+ The most common reason to send a message while in Rmail is to reply
+to the message you are reading. To do this, type `r' (`rmail-reply').
+This displays the `*mail*' buffer in another window, much like `C-x 4
+m', but preinitializes the `Subject', `To', `CC' and `In-reply-to'
+header fields based on the message being replied to. The `To' field is
+given the sender of that message, and the `CC' gets all the recipients
+of that message (but recipients that match elements of the list
+`rmail-dont-reply-to' are omitted; by default, this list contains your
+own mailing address).
+
+ If you don't want to include the other recipients in the `cc' field,
+you can use a prefix argument to the `r' command. In Rmail, you can do
+this with `1 r'.
+
+ Once you have initialized the `*mail*' buffer this way, sending the
+mail goes as usual (*note Sending Mail::.). You can edit the
+presupplied header fields if they are not right for you.
+
+ One additional Mail mode command is available when mailing is invoked
+from Rmail: `C-c C-y' (`mail-yank-original') inserts into the outgoing
+message a copy of the current Rmail message; normally this is the
+message you are replying to, but you can also switch to the Rmail
+buffer, select a different message, switch back, and yank new current
+message. Normally the yanked message is indented four spaces and has
+most header fields deleted from it; an argument to `C-c C-y' specifies
+the amount to indent, and `C-u C-c C-y' does not indent at all and does
+not delete any header fields.
+
+ Another frequent reason to send mail in Rmail is to forward the
+current message to other users. `f' (`rmail-forward') makes this easy
+by preinitializing the `*mail*' buffer with the current message as the
+text, and a subject designating a forwarded message. All you have to
+do is fill in the recipients and send.
+
+ The `m' (`rmail-mail') command is used to start editing an outgoing
+message that is not a reply. It leaves the header fields empty. Its
+only difference from `C-x 4 m' is that it makes the Rmail buffer
+accessible for `C-c y', just as `r' does. Thus, `m' can be used to
+reply to or forward a message; it can do anything `r' or `f' can do.
+
+ The `c' (`rmail-continue') command resumes editing the `*mail*'
+buffer, to finish editing an outgoing message you were already
+composing, or to alter a message you have sent.
+
+
+File: emacs, Node: Rmail Editing, Next: Rmail Digest, Prev: Rmail Reply, Up: Rmail
+
+Editing Within a Message
+========================
+
+ Rmail mode provides a few special commands for moving within and
+editing the current message. In addition, the usual Emacs commands are
+available (except for a few, such as `C-M-n' and `C-M-h', that are
+redefined by Rmail for other purposes). However, the Rmail buffer is
+normally read-only, and to alter it you must use the Rmail command `w'
+described below.
+
+`t'
+ Toggle display of original headers (`rmail-toggle-headers').
+
+`w'
+ Edit current message (`rmail-edit-current-message').
+
+ Rmail reformats the header of each message before displaying it.
+Normally this involves deleting most header fields, on the grounds that
+they are not interesting. The variable `rmail-ignored-headers' should
+contain a regexp that matches the header fields to discard in this way.
+The original headers are saved permanently, and to see what they look
+like, use the `t' (`rmail-toggle-headers') command. This discards the
+reformatted headers of the current message and displays it with the
+original headers. Repeating `t' reformats the message again. Selecting
+the message again also reformats.
+
+ The Rmail buffer is normally read-only, and most of the characters
+you would type to modify it (including most letters) are redefined as
+Rmail commands. This is usually not a problem since it is rare to want
+to change the text of a message. When you do want to do this, the way
+is to type `w' (`rmail-edit-current-message'), which changes from Rmail
+mode into Rmail Edit mode, another major mode which is nearly the same
+as Text mode. The mode line illustrates this change.
+
+ In Rmail Edit mode, letters insert themselves as usual and the Rmail
+commands are not available. When you are finished editing the message
+and are ready to go back to Rmail, type `C-c C-c', which switches back
+to Rmail mode. Alternatively, you can return to Rmail mode but cancel
+all the editing that you have done by typing `C-c C-]'.
+
+ Entering Rmail Edit mode calls with no arguments the value of the
+variable `text-mode-hook', if that value exists and is not `nil'; then
+it does the same with the variable `rmail-edit-mode-hook'. It adds the
+attribute `edited' to the message.
+
+
+File: emacs, Node: Rmail Digest, Prev: Rmail Editing, Up: Rmail
+
+Digest Messages
+===============
+
+ A "digest message" is a message which exists to contain and carry
+several other messages. Digests are used on moderated mailing lists;
+all the messages that arrive for the list during a period of time such
+as one day are put inside a single digest which is then sent to the
+subscribers. Transmitting the single digest uses much less computer
+time than transmitting the individual messages even though the total
+size is the same, because the per-message overhead in network mail
+transmission is considerable.
+
+ When you receive a digest message, the most convenient way to read
+it is to "undigestify" it: to turn it back into many individual
+messages. Then you can read and delete the individual messages as it
+suits you.
+
+ To undigestify a message, select it and then type `M-x
+undigestify-rmail-message'. This copies each submessage as a separate
+Rmail message and inserts them all following the digest. The digest
+message itself is flagged as deleted.
+
+
+File: emacs, Node: Recursive Edit, Next: Narrowing, Prev: Rmail, Up: Top
+
+Recursive Editing Levels
+========================
+
+ A "recursive edit" is a situation in which you are using Emacs
+commands to perform arbitrary editing while in the middle of another
+Emacs command. For example, when you type `C-r' inside of a
+`query-replace', you enter a recursive edit in which you can change the
+current buffer. On exiting from the recursive edit, you go back to the
+`query-replace'.
+
+ "Exiting" the recursive edit means returning to the unfinished
+command, which continues execution. For example, exiting the recursive
+edit requested by `C-r' in `query-replace' causes query replacing to
+resume. Exiting is done with `C-M-c' (`exit-recursive-edit').
+
+ You can also "abort" the recursive edit. This is like exiting, but
+also quits the unfinished command immediately. Use the command `C-]'
+(`abort-recursive-edit') for this. *Note Quitting::.
+
+ The mode line shows you when you are in a recursive edit by
+displaying square brackets around the parentheses that always surround
+the major and minor mode names. Every window's mode line shows this,
+in the same way, since being in a recursive edit is true of Emacs as a
+whole rather than any particular buffer.
+
+ It is possible to be in recursive edits within recursive edits. For
+example, after typing `C-r' in a `query-replace', you might type a
+command that entered the debugger. In such circumstances, two or more
+sets of square brackets appear in the mode line. Exiting the inner
+recursive edit (such as, with the debugger `c' command) would resume
+the command where it called the debugger. After the end of this
+command, you would be able to exit the first recursive edit. Aborting
+also gets out of only one level of recursive edit; it returns
+immediately to the command level of the previous recursive edit. So
+you could immediately abort that one too.
+
+ Alternatively, the command `M-x top-level' aborts all levels of
+recursive edits, returning immediately to the top level command reader.
+
+ The text being edited inside the recursive edit need not be the same
+text that you were editing at top level. It depends on what the
+recursive edit is for. If the command that invokes the recursive edit
+selects a different buffer first, that is the buffer you will edit
+recursively. In any case, you can switch buffers within the recursive
+edit in the normal manner (as long as the buffer-switching keys have
+not been rebound). You could probably do all the rest of your editing
+inside the recursive edit, visiting files and all. But this could have
+surprising effects (such as stack overflow) from time to time. So
+remember to exit or abort the recursive edit when you no longer need it.
+
+ In general, GNU Emacs tries to avoid using recursive edits. It is
+usually preferable to allow the user to switch among the possible
+editing modes in any order he likes. With recursive edits, the only
+way to get to another state is to go "back" to the state that the
+recursive edit was invoked from.
+
+
+File: emacs, Node: Narrowing, Next: Sorting, Prev: Recursive Edit, Up: Top
+
+Narrowing
+=========
+
+ "Narrowing" means focusing in on some portion of the buffer, making
+the rest temporarily invisible and inaccessible. Cancelling the
+narrowing, and making the entire buffer once again visible, is called
+"widening". The amount of narrowing in effect in a buffer at any time
+is called the buffer's "restriction".
+
+`C-x n'
+ Narrow down to between point and mark (`narrow-to-region').
+
+`C-x w'
+ Widen to make the entire buffer visible again (`widen').
+
+ When you have narrowed down to a part of the buffer, that part
+appears to be all there is. You can't see the rest, you can't move
+into it (motion commands won't go outside the visible part), you can't
+change it in any way. However, it is not gone, and if you save the
+file all the invisible text will be saved. In addition to sometimes
+making it easier to concentrate on a single subroutine or paragraph by
+eliminating clutter, narrowing can be used to restrict the range of
+operation of a replace command or repeating keyboard macro. The word
+`Narrow' appears in the mode line whenever narrowing is in effect.
+
+ The primary narrowing command is `C-x n' (`narrow-to-region'). It
+sets the current buffer's restrictions so that the text in the current
+region remains visible but all text before the region or after the
+region is invisible. Point and mark do not change.
+
+ Because narrowing can easily confuse users who do not understand it,
+`narrow-to-region' is normally a disabled command. Attempting to use
+this command asks for confirmation and gives you the option of enabling
+it; once you enable the command, confirmation will no longer be
+required for it. *Note Disabling::.
+
+ The way to undo narrowing is to widen with `C-x w' (`widen'). This
+makes all text in the buffer accessible again.
+
+ You can get information on what part of the buffer you are narrowed
+down to using the `C-x =' command. *Note Position Info::.
+
+
+File: emacs, Node: Sorting, Next: Shell, Prev: Narrowing, Up: Top
+
+Sorting Text
+============
+
+ Emacs provides several commands for sorting text in the buffer. All
+operate on the contents of the region (the text between point and the
+mark). They divide the text of the region into many "sort records",
+identify a "sort key" for each record, and then reorder the records
+into the order determined by the sort keys. The records are ordered so
+that their keys are in alphabetical order, or, for numeric sorting, in
+numeric order. In alphabetic sorting, all upper case letters `A'
+through `Z' come before lower case `a', in accord with the ASCII
+character sequence.
+
+ The various sort commands differ in how they divide the text into
+sort records and in which part of each record is used as the sort key.
+Most of the commands make each line a separate sort record, but some
+commands use paragraphs or pages as sort records. Most of the sort
+commands use each entire sort record as its own sort key, but some use
+only a portion of the record as the sort key.
+
+`M-x sort-lines'
+ Divide the region into lines, and sort by comparing the entire
+ text of a line. A prefix argument means sort into descending
+ order.
+
+`M-x sort-paragraphs'
+ Divide the region into paragraphs, and sort by comparing the entire
+ text of a paragraph (except for leading blank lines). A prefix
+ argument means sort into descending order.
+
+`M-x sort-pages'
+ Divide the region into pages, and sort by comparing the entire
+ text of a page (except for leading blank lines). A prefix
+ argument means sort into descending order.
+
+`M-x sort-fields'
+ Divide the region into lines, and sort by comparing the contents of
+ one field in each line. Fields are defined as separated by
+ whitespace, so the first run of consecutive non-whitespace
+ characters in a line constitutes field 1, the second such run
+ constitutes field 2, etc.
+
+ You specify which field to sort by with a numeric argument: 1 to
+ sort by field 1, etc. A negative argument means sort into
+ descending order. Thus, minus 2 means sort by field 2 in
+ reverse-alphabetical order.
+
+ If two lines are equal in the field being compared, their relative
+ order in the text is not changed. This enables you to sort by
+ multiple keys: sort first by the least significant key, then by
+ the next-to-least key, and so on, ending with the most important
+ key.
+
+`M-x sort-numeric-fields'
+ Like `M-x sort-fields' except the specified field is converted to
+ a number for each line, and the numbers are compared. `10' comes
+ before `2' when considered as text, but after it when considered
+ as a number.
+
+`M-x sort-columns'
+ Like `M-x sort-fields' except that the text within each line used
+ for comparison comes from a fixed range of columns. See below for
+ an explanation.
+
+ For example, if the buffer contains
+
+ On systems where clash detection (locking of files being edited) is
+ implemented, Emacs also checks the first time you modify a buffer
+ whether the file has changed on disk since it was last visited or
+ saved. If it has, you are asked to confirm that you want to change
+ the buffer.
+
+then if you apply `M-x sort-lines' to the entire buffer you get
+
+ On systems where clash detection (locking of files being edited) is
+ implemented, Emacs also checks the first time you modify a buffer
+ saved. If it has, you are asked to confirm that you want to change
+ the buffer.
+ whether the file has changed on disk since it was last visited or
+
+where the upper case `O' comes before all lower case letters. If you
+apply instead `C-u 2 M-x sort-fields' you get
+
+ implemented, Emacs also checks the first time you modify a buffer
+ saved. If it has, you are asked to confirm that you want to change
+ the buffer.
+ On systems where clash detection (locking of files being edited) is
+ whether the file has changed on disk since it was last visited or
+
+where the sort keys were `Emacs', `If', `buffer', `systems' and `the'.
+
+ `M-x sort-columns' requires more explanation. You specify the
+columns by putting point at one of the columns and the mark at the other
+column. Because this means you cannot put point or the mark at the
+beginning of the first line to sort, this command uses an unusual
+definition of `region': all of the line point is in is considered part
+of the region, and so is all of the line the mark is in.
+
+ For example, to sort a table by information found in columns 10 to
+15, you could put the mark on column 10 in the first line of the table,
+and point on column 15 in the last line of the table, and then use this
+command. Or you could put the mark on column 15 in the first line and
+point on column 10 in the last line.
+
+ This can be thought of as sorting the rectangle specified by point
+and the mark, except that the text on each line to the left or right of
+the rectangle moves along with the text inside the rectangle. *Note
+Rectangles::.
+
+
+File: emacs, Node: Shell, Next: Hardcopy, Prev: Sorting, Up: Top
+
+Running Shell Commands from Emacs
+=================================
+
+ Emacs has commands for passing single command lines to inferior shell
+processes; it can also run a shell interactively with input and output
+to an Emacs buffer `*shell*'.
+
+`M-!'
+ Run a specified shell command line and display the output
+ (`shell-command').
+
+`M-|'
+ Run a specified shell command line with region contents as input;
+ optionally replace the region with the output
+ (`shell-command-on-region').
+
+`M-x shell'
+ Run a subshell with input and output through an Emacs buffer. You
+ can then give commands interactively.
+
+* Menu:
+
+* Single Shell:: How to run one shell command and return.
+* Interactive Shell:: Permanent shell taking input via Emacs.
+* Shell Mode:: Special Emacs commands used with permanent shell.
+
+
+File: emacs, Node: Single Shell, Next: Interactive Shell, Prev: Shell, Up: Shell
+
+Single Shell Commands
+---------------------
+
+ `M-!' (`shell-command') reads a line of text using the minibuffer
+and creates an inferior shell to execute the line as a command.
+Standard input from the command comes from the null device. If the
+shell command produces any output, the output goes into an Emacs buffer
+named `*Shell Command Output*', which is displayed in another window
+but not selected. A numeric argument, as in `M-1 M-!', directs this
+command to insert any output into the current buffer. In that case,
+point is left before the output and the mark is set after the output.
+
+ `M-|' (`shell-command-on-region') is like `M-!' but passes the
+contents of the region as input to the shell command, instead of no
+input. If a numeric argument is used, meaning insert output in the
+current buffer, then the old region is deleted first and the output
+replaces it as the contents of the region.
+
+ Both `M-!' and `M-|' use `shell-file-name' to specify the shell to
+use. This variable is initialized based on your `SHELL' environment
+variable when Emacs is started. If the file name does not specify a
+directory, the directories in the list `exec-path' are searched; this
+list is initialized based on the environment variable `PATH' when Emacs
+is started. Your `.emacs' file can override either or both of these
+default initializations.
+
+ With `M-!' and `M-|', Emacs has to wait until the shell command
+completes. You can quit with `C-g'; that terminates the shell command.
+
+
+File: emacs, Node: Interactive Shell, Next: Shell Mode, Prev: Single Shell, Up: Shell
+
+Interactive Inferior Shell
+--------------------------
+
+ To run a subshell interactively, putting its typescript in an Emacs
+buffer, use `M-x shell'. This creates (or reuses) a buffer named
+`*shell*' and runs a subshell with input coming from and output going
+to that buffer. That is to say, any "terminal output" from the subshell
+will go into the buffer, advancing point, and any "terminal input" for
+the subshell comes from text in the buffer. To give input to the
+subshell, go to the end of the buffer and type the input, terminated by
+RET.
+
+ Emacs does not wait for the subshell to do anything. You can switch
+windows or buffers and edit them while the shell is waiting, or while
+it is running a command. Output from the subshell waits until Emacs
+has time to process it; this happens whenever Emacs is waiting for
+keyboard input or for time to elapse.
+
+ If you would like multiple subshells, change the name of buffer
+`*shell*' to something different by using `M-x rename-buffer'. The
+next use of `M-x shell' will create a new buffer `*shell*' with its own
+subshell. By renaming this buffer as well you can create a third one,
+and so on. All the subshells run independently and in parallel.
+
+ The file name used to load the subshell is the value of the variable
+`explicit-shell-file-name', if that is non-`nil'. Otherwise, the
+environment variable `ESHELL' is used, or the environment variable
+`SHELL' if there is no `ESHELL'. If the file name specified is
+relative, the directories in the list `exec-path' are searched (*note
+Single Shell Commands: Single Shell.).
+
+ As soon as the subshell is started, it is sent as input the contents
+of the file `~/.emacs_SHELLNAME', if that file exists, where SHELLNAME
+is the name of the file that the shell was loaded from. For example,
+if you use `csh', the file sent to it is `~/.emacs_csh'; if you use the
+Bourne-Again shell, the file sent to it is `~/.emacs_bash'.
+
+ `cd', `pushd' and `popd' commands given to the inferior shell are
+watched by Emacs so it can keep the `*shell*' buffer's default
+directory the same as the shell's working directory. These commands
+are recognized syntactically by examining lines of input that are sent.
+ If you use aliases for these commands, you can tell Emacs to recognize
+them also. For example, if the value of the variable
+`shell-pushd-regexp' matches the beginning of a shell command line,
+that line is regarded as a `pushd' command. Change this variable when
+you add aliases for `pushd'. Likewise, `shell-popd-regexp' and
+`shell-cd-regexp' are used to recognize commands with the meaning of
+`popd' and `cd'. These commands are recognized only at the beginning
+of a shell command line.
+
+ If Emacs gets an error while trying to handle what it believes is a
+`cd', `pushd' or `popd' command, and the value of
+`shell-set-directory-error-hook' is non-`nil', that value is called as
+a function with no arguments.
+
+
+File: emacs, Node: Shell Mode, Prev: Interactive Shell, Up: Shell
+
+Shell Mode
+----------
+
+ The shell buffer uses Shell mode, which defines several special keys
+attached to the `C-c' prefix. They are chosen to resemble the usual
+editing and job control characters present in shells that are not under
+Emacs, except that you must type `C-c' first. Here is a complete list
+of the special key bindings of Shell mode:
+
+`RET'
+ At end of buffer, send line as input; otherwise, copy current line
+ to end of buffer and send it (`send-shell-input'). When a line is
+ copied, any text at the beginning of the line that matches the
+ variable `shell-prompt-pattern' is left out; this variable's value
+ should be a regexp string that matches the prompts that you use in
+ your subshell.
+
+`C-c C-d'
+ Send end-of-file as input, probably causing the shell or its
+ current subjob to finish (`shell-send-eof').
+
+`C-c C-u'
+ Kill all text that has yet to be sent as input
+ (`kill-shell-input').
+
+`C-c C-w'
+ Kill a word before point (`backward-kill-word').
+
+`C-c C-c'
+ Interrupt the shell or its current subjob if any
+ (`interrupt-shell-subjob').
+
+`C-c C-z'
+ Stop the shell or its current subjob if any (`stop-shell-subjob').
+
+`C-c C-\'
+ Send quit signal to the shell or its current subjob if any
+ (`quit-shell-subjob').
+
+`C-c C-o'
+ Delete last batch of output from shell (`kill-output-from-shell').
+
+`C-c C-r'
+ Scroll top of last batch of output to top of window
+ (`show-output-from-shell').
+
+`C-c C-y'
+ Copy the previous bunch of shell input, and insert it into the
+ buffer before point (`copy-last-shell-input'). No final newline
+ is inserted, and the input copied is not resubmitted until you type
+ RET.
+
+
+File: emacs, Node: Hardcopy, Next: Dissociated Press, Prev: Shell, Up: Top
+
+Hardcopy Output
+===============
+
+ The Emacs commands for making hardcopy derive their names from the
+Unix commands `print' and `lpr'.
+
+`M-x print-buffer'
+ Print hardcopy of current buffer using Unix command `print' (`lpr
+ -p'). This makes page headings containing the file name and page
+ number.
+
+`M-x lpr-buffer'
+ Print hardcopy of current buffer using Unix command `lpr'. This
+ makes no page headings.
+
+`M-x print-region'
+ Like `print-buffer' but prints only the current region.
+
+`M-x lpr-region'
+ Like `lpr-buffer' but prints only the current region.
+
+ All the hardcopy commands pass extra switches to the `lpr' program
+based on the value of the variable `lpr-switches'. Its value should be
+a list of strings, each string a switch starting with `-'. For
+example, the value could be `("-Pfoo")' to print on printer `foo'. You
+can specify an alternative command to run instead of `lpr' by setting
+the variable `lpr-command'.
+
+ \ No newline at end of file
diff --git a/info/emacs-11 b/info/emacs-11
new file mode 100644
index 00000000000..7a4245aae77
--- /dev/null
+++ b/info/emacs-11
@@ -0,0 +1,1173 @@
+This is Info file ../info/emacs, produced by Makeinfo-1.49 from the
+input file emacs.texi.
+
+ This file documents the GNU Emacs editor.
+
+ Copyright (C) 1985, 1986, 1988, 1992 Richard M. Stallman.
+
+ Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+ Permission is granted to copy and distribute modified versions of
+this manual under the conditions for verbatim copying, provided also
+that the sections entitled "The GNU Manifesto", "Distribution" and "GNU
+General Public License" are included exactly as in the original, and
+provided that the entire resulting derived work is distributed under the
+terms of a permission notice identical to this one.
+
+ Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that the sections entitled "The GNU Manifesto",
+"Distribution" and "GNU General Public License" may be included in a
+translation approved by the author instead of in the original English.
+
+
+File: emacs, Node: Dissociated Press, Next: Amusements, Prev: Hardcopy, Up: Top
+
+Dissociated Press
+=================
+
+ `M-x dissociated-press' is a command for scrambling a file of text
+either word by word or character by character. Starting from a buffer
+of straight English, it produces extremely amusing output. The input
+comes from the current Emacs buffer. Dissociated Press writes its
+output in a buffer named `*Dissociation*', and redisplays that buffer
+after every couple of lines (approximately) to facilitate reading it.
+
+ `dissociated-press' asks every so often whether to continue
+operating. Answer `n' to stop it. You can also stop at any time by
+typing `C-g'. The dissociation output remains in the `*Dissociation*'
+buffer for you to copy elsewhere if you wish.
+
+ Dissociated Press operates by jumping at random from one point in the
+buffer to another. In order to produce plausible output rather than
+gibberish, it insists on a certain amount of overlap between the end of
+one run of consecutive words or characters and the start of the next.
+That is, if it has just printed out `president' and then decides to
+jump to a different point in the file, it might spot the `ent' in
+`pentagon' and continue from there, producing `presidentagon'. Long
+sample texts produce the best results.
+
+ A positive argument to `M-x dissociated-press' tells it to operate
+character by character, and specifies the number of overlap characters.
+ A negative argument tells it to operate word by word and specifies the
+number of overlap words. In this mode, whole words are treated as the
+elements to be permuted, rather than characters. No argument is
+equivalent to an argument of two. For your againformation, the output
+goes only into the buffer `*Dissociation*'. The buffer you start with
+is not changed.
+
+ Dissociated Press produces nearly the same results as a Markov chain
+based on a frequency table constructed from the sample text. It is,
+however, an independent, ignoriginal invention. Dissociated Press
+techniquitously copies several consecutive characters from the sample
+between random choices, whereas a Markov chain would choose randomly for
+each word or character. This makes for more plausible sounding results,
+and runs faster.
+
+ It is a mustatement that too much use of Dissociated Press can be a
+developediment to your real work. Sometimes to the point of outragedy.
+And keep dissociwords out of your documentation, if you want it to be
+well userenced and properbose. Have fun. Your buggestions are welcome.
+
+
+File: emacs, Node: Amusements, Next: Emulation, Prev: Dissociated Press, Up: Top
+
+Other Amusements
+================
+
+ If you are a little bit bored, you can try `M-x hanoi'. If you are
+considerably bored, give it a numeric argument. If you are very very
+bored, try an argument of 9. Sit back and watch.
+
+ When you are frustrated, try the famous Eliza program. Just do `M-x
+doctor'. End each input by typing `RET' twice.
+
+ When you are feeling strange, type `M-x yow'.
+
+
+File: emacs, Node: Emulation, Next: Customization, Prev: Amusements, Up: Top
+
+Emulation
+=========
+
+ GNU Emacs can be programmed to emulate (more or less) most other
+editors. Standard facilities can emulate these:
+
+EDT (DEC VMS editor)
+ Turn on EDT emulation with `M-x edt-emulation-on'. `M-x
+ edt-emulation-off' restores normal Emacs command bindings.
+
+ Most of the EDT emulation commands are keypad keys, and most
+ standard Emacs key bindings are still available. The EDT
+ emulation rebindings are done in the global keymap, so there is no
+ problem switching buffers or major modes while in EDT emulation.
+
+Gosling Emacs
+ Turn on emulation of Gosling Emacs (aka Unipress Emacs) with `M-x
+ set-gosmacs-bindings'. This redefines many keys, mostly on the
+ `C-x' and `ESC' prefixes, to work as they do in Gosmacs. `M-x
+ set-gnu-bindings' returns to normal GNU Emacs by rebinding the
+ same keys to the definitions they had at the time `M-x
+ set-gosmacs-bindings' was done.
+
+ It is also possible to run Mocklisp code written for Gosling Emacs.
+ *Note Mocklisp::.
+
+vi (Berkeley Unix editor)
+ Turn on vi emulation with `M-x vi-mode'. This is a major mode
+ that replaces the previously established major mode. All of the
+ vi commands that, in real vi, enter "input" mode are programmed in
+ the Emacs emulator to return to the previous major mode. Thus,
+ ordinary Emacs serves as vi's "input" mode.
+
+ Because vi emulation works through major modes, it does not work
+ to switch buffers during emulation. Return to normal Emacs first.
+
+ If you plan to use vi emulation much, you probably want to bind a
+ key to the `vi-mode' command.
+
+vi (alternate emulator)
+ Another vi emulator said to resemble real vi more thoroughly is
+ invoked by `M-x vip-mode'. "Input" mode in this emulator is
+ changed from ordinary Emacs so you can use ESC to go back to
+ emulated vi command mode. To get from emulated vi command mode
+ back to ordinary Emacs, type `C-z'.
+
+ This emulation does not work through major modes, and it is
+ possible to switch buffers in various ways within the emulator.
+ It is not so necessary to assign a key to the command `vip-mode' as
+ it is with `vi-mode' because terminating insert mode does not use
+ it.
+
+ For full information, see the long comment at the beginning of the
+ source file, which is `lisp/vip.el' in the Emacs distribution.
+
+ I am interested in hearing which vi emulator users prefer, as well
+as in receiving more complete user documentation for either or both
+emulators. Warning: loading both at once may cause name conficts; no
+one has checked.
+
+
+File: emacs, Node: Customization, Next: Quitting, Prev: Emulation, Up: Top
+
+Customization
+*************
+
+ This chapter talks about various topics relevant to adapting the
+behavior of Emacs in minor ways.
+
+ All kinds of customization affect only the particular Emacs job that
+you do them in. They are completely lost when you kill the Emacs job,
+and have no effect on other Emacs jobs you may run at the same time or
+later. The only way an Emacs job can affect anything outside of it is
+by writing a file; in particular, the only way to make a customization
+`permanent' is to put something in your `.emacs' file or other
+appropriate file to do the customization in each session. *Note Init
+File::.
+
+* Menu:
+
+* Minor Modes:: Each minor mode is one feature you can turn on
+ independently of any others.
+* Variables:: Many Emacs commands examine Emacs variables
+ to decide what to do; by setting variables,
+ you can control their functioning.
+* Keyboard Macros:: A keyboard macro records a sequence of keystrokes
+ to be replayed with a single command.
+* Key Bindings:: The keymaps say what command each key runs.
+ By changing them, you can "redefine keys".
+* Syntax:: The syntax table controls how words and expressions
+ are parsed.
+* Init File:: How to write common customizations in the `.emacs' file.
+
+
+File: emacs, Node: Minor Modes, Next: Variables, Prev: Customization, Up: Customization
+
+Minor Modes
+===========
+
+ Minor modes are options which you can use or not. For example, Auto
+Fill mode is a minor mode in which SPC breaks lines between words as you
+type. All the minor modes are independent of each other and of the
+selected major mode. Most minor modes say in the mode line when they
+are on; for example, `Fill' in the mode line means that Auto Fill mode
+is on.
+
+ Append `-mode' to the name of a minor mode to get the name of a
+command function that turns the mode on or off. Thus, the command to
+enable or disable Auto Fill mode is called `M-x auto-fill-mode'. These
+commands are usually invoked with `M-x', but you can bind keys to them
+if you wish. With no argument, the function turns the mode on if it was
+off and off if it was on. This is known as "toggling". A positive
+argument always turns the mode on, and an explicit zero argument or a
+negative argument always turns it off.
+
+ Auto Fill mode allows you to enter filled text without breaking lines
+explicitly. Emacs inserts newlines as necessary to prevent lines from
+becoming too long. *Note Filling::.
+
+ Overwrite mode causes ordinary printing characters to replace
+existing text instead of shoving it over. For example, if the point is
+in front of the `B' in `FOOBAR', then in Overwrite mode typing a `G'
+changes it to `FOOGAR', instead of making it `FOOGBAR' as usual.
+
+ Abbrev mode allows you to define abbreviations that automatically
+expand as you type them. For example, `amd' might expand to `abbrev
+mode'. *Note Abbrevs::, for full information.
+
+
+File: emacs, Node: Variables, Next: Keyboard Macros, Prev: Minor Modes, Up: Customization
+
+Variables
+=========
+
+ A "variable" is a Lisp symbol which has a value. The symbol's name
+is also called the name of the variable. Variable names can contain any
+characters, but conventionally they are chosen to be words separated by
+hyphens. A variable can have a documentation string which describes
+what kind of value it should have and how the value will be used.
+
+ Lisp allows any variable to have any kind of value, but most
+variables that Emacs uses require a value of a certain type. Often the
+value should always be a string, or should always be a number.
+Sometimes we say that a certain feature is turned on if a variable is
+"non-`nil'," meaning that if the variable's value is `nil', the feature
+is off, but the feature is on for any other value. The conventional
+value to use to turn on the feature--since you have to pick one
+particular value when you set the variable--is `t'.
+
+ Emacs uses many Lisp variables for internal recordkeeping, as any
+Lisp program must, but the most interesting variables for you are the
+ones that exist for the sake of customization. Emacs does not
+(usually) change the values of these variables; instead, you set the
+values, and thereby alter and control the behavior of certain Emacs
+commands. These variables are called "options". Most options are
+documented in this manual, and appear in the Variable Index (*note
+Variable Index::.).
+
+ One example of a variable which is an option is `fill-column', which
+specifies the position of the right margin (as a number of characters
+from the left margin) to be used by the fill commands (*note
+Filling::.).
+
+* Menu:
+
+* Examining:: Examining or setting one variable's value.
+* Edit Options:: Examining or editing list of all variables' values.
+* Locals:: Per-buffer values of variables.
+* File Variables:: How files can specify variable values.
+
+
+File: emacs, Node: Examining, Next: Edit Options, Prev: Variables, Up: Variables
+
+Examining and Setting Variables
+-------------------------------
+
+`C-h v'
+`M-x describe-variable'
+ Print the value and documentation of a variable.
+
+`M-x set-variable'
+ Change the value of a variable.
+
+ To examine the value of a single variable, type `C-h v'
+(`describe-variable'), which reads a variable name using the
+minibuffer, with completion. It prints both the value and the
+documentation of the variable.
+
+ C-h v fill-column RET
+
+prints something like
+ fill-column's value is 72
+
+ Documentation:
+ *Column beyond which automatic line-wrapping should happen.
+ Automatically becomes local when set in any fashion.
+
+The star at the beginning of the documentation indicates that this
+variable is an option. `C-h v' is not restricted to options; it allows
+any variable name.
+
+ If you know which option you want to set, you can set it using `M-x
+set-variable'. This reads the variable name with the minibuffer (with
+completion), and then reads a Lisp expression for the new value using
+the minibuffer a second time. For example,
+
+ M-x set-variable RET fill-column RET 72 RET
+
+sets `fill-column' to 72, like executing the Lisp expression
+
+ (setq fill-column 72)
+
+ Setting variables in this way, like all means of customizing Emacs
+except where explicitly stated, affects only the current Emacs session.
+
+
+File: emacs, Node: Edit Options, Next: Locals, Prev: Examining, Up: Variables
+
+Editing Variable Values
+-----------------------
+
+`M-x list-options'
+ Display a buffer listing names, values and documentation of all
+ options.
+
+`M-x edit-options'
+ Change option values by editing a list of options.
+
+ `M-x list-options' displays a list of all Emacs option variables, in
+an Emacs buffer named `*List Options*'. Each option is shown with its
+documentation and its current value. Here is what a portion of it might
+look like:
+
+ ;; exec-path:
+ ("." "/usr/local/bin" "/usr/ucb" "/bin" "/usr/bin" "/u2/emacs/etc")
+ *List of directories to search programs to run in subprocesses.
+ Each element is a string (directory name)
+ or nil (try the default directory).
+ ;;
+ ;; fill-column:
+ 72
+ *Column beyond which automatic line-wrapping should happen.
+ Automatically becomes local when set in any fashion.
+ ;;
+
+ `M-x edit-options' goes one step further and immediately selects the
+`*List Options*' buffer; this buffer uses the major mode Options mode,
+which provides commands that allow you to point at an option and change
+its value:
+
+`s'
+ Set the variable point is in or near to a new value read using the
+ minibuffer.
+
+`x'
+ Toggle the variable point is in or near: if the value was `nil',
+ it becomes `t'; otherwise it becomes `nil'.
+
+`1'
+ Set the variable point is in or near to `t'.
+
+`0'
+ Set the variable point is in or near to `nil'.
+
+`n'
+`p'
+ Move to the next or previous variable.
+
+ Changes take effect immediately.
+
+
+File: emacs, Node: Locals, Next: File Variables, Prev: Edit Options, Up: Variables
+
+Local Variables
+---------------
+
+`M-x make-local-variable'
+ Make a variable have a local value in the current buffer.
+
+`M-x kill-local-variable'
+ Make a variable use its global value in the current buffer.
+
+`M-x make-variable-buffer-local'
+ Mark a variable so that setting it will make it local to the
+ buffer that is current at that time.
+
+ Any variable can be made "local" to a specific Emacs buffer. This
+means that its value in that buffer is independent of its value in other
+buffers. A few variables are always local in every buffer. Every other
+Emacs variable has a "global" value which is in effect in all buffers
+that have not made the variable local.
+
+ Major modes always make the variables they set local to the buffer.
+This is why changing major modes in one buffer has no effect on other
+buffers.
+
+ `M-x make-local-variable' reads the name of a variable and makes it
+local to the current buffer. Further changes in this buffer will not
+affect others, and further changes in the global value will not affect
+this buffer.
+
+ `M-x make-variable-buffer-local' reads the name of a variable and
+changes the future behavior of the variable so that it will become local
+automatically when it is set. More precisely, once a variable has been
+marked in this way, the usual ways of setting the variable will
+automatically do `make-local-variable' first. We call such variables
+"per-buffer" variables.
+
+ Some important variables have been marked per-buffer already. These
+include `abbrev-mode', `auto-fill-hook', `case-fold-search',
+`ctl-arrow', `comment-column', `fill-column', `fill-prefix',
+`indent-tabs-mode', `left-margin', `mode-line-format', `overwrite-mode',
+`selective-display', `tab-width', `selective-display-ellipses', and
+`truncate-lines'. Some other variables are always local in every
+buffer, but they are used for internal purposes.
+
+ `M-x kill-local-variable' reads the name of a variable and makes it
+cease to be local to the current buffer. The global value of the
+variable henceforth is in effect in this buffer. Setting the major
+mode kills all the local variables of the buffer.
+
+ To set the global value of a variable, regardless of whether the
+variable has a local value in the current buffer, you can use the Lisp
+function `setq-default'. It works like `setq'. If there is a local
+value in the current buffer, the local value is not affected by
+`setq-default'; thus, the new global value may not be visible until you
+switch to another buffer. For example,
+
+ (setq-default fill-column 72)
+
+`setq-default' is the only way to set the global value of a variable
+that has been marked with `make-variable-buffer-local'.
+
+ Programs can look at a variable's default value with `default-value'.
+This function takes a symbol as argument and returns its default value.
+The argument is evaluated; usually you must quote it explicitly. For
+example,
+
+ (default-value 'fill-column)
+
+
+File: emacs, Node: File Variables, Prev: Locals, Up: Variables
+
+Local Variables in Files
+------------------------
+
+ A file can contain a "local variables list", which specifies the
+values to use for certain Emacs variables when that file is edited.
+Visiting the file checks for a local variables list and makes each
+variable in the list local to the buffer in which the file is visited,
+with the value specified in the file.
+
+ A local variables list goes near the end of the file, in the last
+page. (It is often best to put it on a page by itself.) The local
+variables list starts with a line containing the string `Local
+Variables:', and ends with a line containing the string `End:'. In
+between come the variable names and values, one set per line, as
+`VARIABLE: VALUE'. The VALUEs are not evaluated; they are used
+literally.
+
+ The line which starts the local variables list does not have to say
+just `Local Variables:'. If there is other text before `Local
+Variables:', that text is called the "prefix", and if there is other
+text after, that is called the "suffix". If these are present, each
+entry in the local variables list should have the prefix before it and
+the suffix after it. This includes the `End:' line. The prefix and
+suffix are included to disguise the local variables list as a comment so
+that the compiler or text formatter will not be perplexed by it. If
+you do not need to disguise the local variables list as a comment in
+this way, do not bother with a prefix or a suffix.
+
+ Two "variable" names are special in a local variables list: a value
+for the variable `mode' really sets the major mode, and a value for the
+variable `eval' is simply evaluated as an expression and the value is
+ignored. These are not real variables; setting such variables in any
+other context has no such effect. If `mode' is used in a local
+variables list, it should be the first entry in the list.
+
+ Here is an example of a local variables list:
+
+ ;;; Local Variables: ***
+ ;;; mode:lisp ***
+ ;;; comment-column:0 ***
+ ;;; comment-start: ";;; " ***
+ ;;; comment-end:"***" ***
+ ;;; End: ***
+
+ Note that the prefix is `;;; ' and the suffix is ` ***'. Note also
+that comments in the file begin with and end with the same strings.
+Presumably the file contains code in a language which is like Lisp
+(like it enough for Lisp mode to be useful) but in which comments start
+and end in that way. The prefix and suffix are used in the local
+variables list to make the list appear as comments when the file is read
+by the compiler or interpreter for that language.
+
+ The start of the local variables list must be no more than 3000
+characters from the end of the file, and must be in the last page if the
+file is divided into pages. Otherwise, Emacs will not notice it is
+there. The purpose of this is so that a stray `Local Variables:' not in
+the last page does not confuse Emacs, and so that visiting a long file
+that is all one page and has no local variables list need not take the
+time to search the whole file.
+
+ You may be tempted to try to turn on Auto Fill mode with a local
+variable list. That is a mistake. The choice of Auto Fill mode or not
+is a matter of individual taste, not a matter of the contents of
+particular files. If you want to use Auto Fill, set up major mode hooks
+with your `.emacs' file to turn it on (when appropriate) for you alone
+(*note Init File::.). Don't try to use a local variable list that would
+impose your taste on everyone.
+
+ If you are concerned that you might visit a file containing a
+Trojan-horse local variable specification, you can prevent local
+variables processing by setting the variable `inhibit-local-variables'
+to a non-`nil' value. Emacs will display the local variables
+specification and then ask you whether to process it.
+
+
+File: emacs, Node: Keyboard Macros, Next: Key Bindings, Prev: Variables, Up: Customization
+
+Keyboard Macros
+===============
+
+ A "keyboard macro" is a command defined by the user to abbreviate a
+sequence of keys. For example, if you discover that you are about to
+type `C-n C-d' forty times, you can speed your work by defining a
+keyboard macro to do `C-n C-d' and calling it with a repeat count of
+forty.
+
+`C-x ('
+ Start defining a keyboard macro (`start-kbd-macro').
+
+`C-x )'
+ End the definition of a keyboard macro (`end-kbd-macro').
+
+`C-x e'
+ Execute the most recent keyboard macro (`call-last-kbd-macro').
+
+`C-u C-x ('
+ Re-execute last keyboard macro, then add more keys to its
+ definition.
+
+`C-x q'
+ When this point is reached during macro execution, ask for
+ confirmation (`kbd-macro-query').
+
+`M-x name-last-kbd-macro'
+ Give a command name (for the duration of the session) to the most
+ recently defined keyboard macro.
+
+`M-x insert-kbd-macro'
+ Insert in the buffer a keyboard macro's definition, as Lisp code.
+
+ Keyboard macros differ from ordinary Emacs commands in that they are
+written in the Emacs command language rather than in Lisp. This makes
+it easier for the novice to write them, and makes them more convenient
+as temporary hacks. However, the Emacs command language is not powerful
+enough as a programming language to be useful for writing anything
+intelligent or general. For such things, Lisp must be used.
+
+ You define a keyboard macro while executing the commands which are
+the definition. Put differently, as you are defining a keyboard macro,
+the definition is being executed for the first time. This way, you can
+see what the effects of your commands are, so that you don't have to
+figure them out in your head. When you are finished, the keyboard
+macro is defined and also has been, in effect, executed once. You can
+then do the whole thing over again by invoking the macro.
+
+* Menu:
+
+* Basic Kbd Macro:: Defining and running keyboard macros.
+* Save Kbd Macro:: Giving keyboard macros names; saving them in files.
+* Kbd Macro Query:: Keyboard macros that do different things each use.
+
+
+File: emacs, Node: Basic Kbd Macro, Next: Save Kbd Macro, Prev: Keyboard Macros, Up: Keyboard Macros
+
+Basic Use
+---------
+
+ To start defining a keyboard macro, type the `C-x (' command
+(`start-kbd-macro'). From then on, your keys continue to be executed,
+but also become part of the definition of the macro. `Def' appears in
+the mode line to remind you of what is going on. When you are
+finished, the `C-x )' command (`end-kbd-macro') terminates the
+definition (without becoming part of it!).
+
+For example,
+
+ C-x ( M-F foo C-x )
+
+defines a macro to move forward a word and then insert `foo'.
+
+ The macro thus defined can be invoked again with the `C-x e' command
+(`call-last-kbd-macro'), which may be given a repeat count as a numeric
+argument to execute the macro many times. `C-x )' can also be given a
+repeat count as an argument, in which case it repeats the macro that
+many times right after defining it, but defining the macro counts as
+the first repetition (since it is executed as you define it). So,
+giving `C-x )' an argument of 4 executes the macro immediately 3
+additional times. An argument of zero to `C-x e' or `C-x )' means
+repeat the macro indefinitely (until it gets an error or you type
+`C-g').
+
+ If you wish to repeat an operation at regularly spaced places in the
+text, define a macro and include as part of the macro the commands to
+move to the next place you want to use it. For example, if you want to
+change each line, you should position point at the start of a line, and
+define a macro to change that line and leave point at the start of the
+next line. Then repeating the macro will operate on successive lines.
+
+ After you have terminated the definition of a keyboard macro, you
+can add to the end of its definition by typing `C-u C-x ('. This is
+equivalent to plain `C-x (' followed by retyping the whole definition
+so far. As a consequence it re-executes the macro as previously
+defined.
+
+ One limitation on the use of keyboard macros is that if you exit a
+recursive edit within a macro that was not entered within the macro,
+then the execution of the macro stops at that point. In Emacs 18, View
+mode uses a recursive edit, so exiting View mode is an occasion for such
+a problem.
+
+
+File: emacs, Node: Save Kbd Macro, Next: Kbd Macro Query, Prev: Basic Kbd Macro, Up: Keyboard Macros
+
+Naming and Saving Keyboard Macros
+---------------------------------
+
+ If you wish to save a keyboard macro for longer than until you
+define the next one, you must give it a name using `M-x
+name-last-kbd-macro'. This reads a name as an argument using the
+minibuffer and defines that name to execute the macro. The macro name
+is a Lisp symbol, and defining it in this way makes it a valid command
+name for calling with `M-x' or for binding a key to with
+`global-set-key' (*note Keymaps::.). If you specify a name that has a
+prior definition other than another keyboard macro, an error message is
+printed and nothing is changed.
+
+ Once a macro has a command name, you can save its definition in a
+file. Then it can be used in another editing session. First visit the
+file you want to save the definition in. Then use the command
+
+ M-x insert-kbd-macro RET MACRONAME RET
+
+This inserts some Lisp code that, when executed later, will define the
+same macro with the same definition it has now. You need not
+understand Lisp code to do this, because `insert-kbd-macro' writes the
+Lisp code for you. Then save the file. The file can be loaded with
+`load-file' (*note Lisp Libraries::.). If the file you save in is your
+init file `~/.emacs' (*note Init File::.) then the macro will be
+defined each time you run Emacs.
+
+ If you give `insert-kbd-macro' a prefix argument, it makes
+additional Lisp code to record the keys (if any) that you have bound to
+the keyboard macro, so that the macro will be reassigned the same keys
+when you load the file.
+
+
+File: emacs, Node: Kbd Macro Query, Prev: Save Kbd Macro, Up: Keyboard Macros
+
+Executing Macros with Variations
+--------------------------------
+
+ Using `C-x q' (`kbd-macro-query'), you can get an effect similar to
+that of `query-replace', where the macro asks you each time around
+whether to make a change. When you are defining the macro, type `C-x
+q' at the point where you want the query to occur. During macro
+definition, the `C-x q' does nothing, but when the macro is invoked the
+`C-x q' reads a character from the terminal to decide whether to
+continue.
+
+ The special answers are SPC, DEL, `C-d', `C-l' and `C-r'. Any other
+character terminates execution of the keyboard macro and is then read
+as a command. SPC means to continue. DEL means to skip the remainder
+of this repetition of the macro, starting again from the beginning in
+the next repetition. `C-d' means to skip the remainder of this
+repetition and cancel further repetition. `C-l' redraws the screen and
+asks you again for a character to say what to do. `C-r' enters a
+recursive editing level, in which you can perform editing which is not
+part of the macro. When you exit the recursive edit using `C-M-c', you
+are asked again how to continue with the keyboard macro. If you type a
+SPC at this time, the rest of the macro definition is executed. It is
+up to you to leave point and the text in a state such that the rest of
+the macro will do what you want.
+
+ `C-u C-x q', which is `C-x q' with a numeric argument, performs a
+different function. It enters a recursive edit reading input from the
+keyboard, both when you type it during the definition of the macro, and
+when it is executed from the macro. During definition, the editing you
+do inside the recursive edit does not become part of the macro. During
+macro execution, the recursive edit gives you a chance to do some
+particularized editing. *Note Recursive Edit::.
+
+
+File: emacs, Node: Key Bindings, Next: Syntax, Prev: Keyboard Macros, Up: Customization
+
+Customizing Key Bindings
+========================
+
+ This section deals with the "keymaps" which define the bindings
+between keys and functions, and shows how you can customize these
+bindings.
+
+ A command is a Lisp function whose definition provides for
+interactive use. Like every Lisp function, a command has a function
+name, a Lisp symbol whose name usually consists of lower case letters
+and hyphens.
+
+* Menu:
+
+* Keymaps:: Definition of the keymap data structure.
+ Names of Emacs's standard keymaps.
+* Rebinding:: How to redefine one key's meaning conveniently.
+* Disabling:: Disabling a command means confirmation is required
+ before it can be executed. This is done to protect
+ beginners from surprises.
+
+
+File: emacs, Node: Keymaps, Next: Rebinding, Prev: Key Bindings, Up: Key Bindings
+
+Keymaps
+-------
+
+ The bindings between characters and command functions are recorded in
+data structures called "keymaps". Emacs has many of these. One, the
+"global" keymap, defines the meanings of the single-character keys that
+are defined regardless of major mode. It is the value of the variable
+`global-map'.
+
+ Each major mode has another keymap, its "local keymap", which
+contains overriding definitions for the single-character keys that are
+to be redefined in that mode. Each buffer records which local keymap is
+installed for it at any time, and the current buffer's local keymap is
+the only one that directly affects command execution. The local
+keymaps for Lisp mode, C mode, and many other major modes always exist
+even when not in use. They are the values of the variables
+`lisp-mode-map', `c-mode-map', and so on. For major modes less often
+used, the local keymap is sometimes constructed only when the mode is
+used for the first time in a session. This is to save space.
+
+ There are local keymaps for the minibuffer too; they contain various
+completion and exit commands.
+
+ * `minibuffer-local-map' is used for ordinary input (no completion).
+
+ * `minibuffer-local-ns-map' is similar, except that SPC exits just
+ like RET. This is used mainly for Mocklisp compatibility.
+
+ * `minibuffer-local-completion-map' is for permissive completion.
+
+ * `minibuffer-local-must-match-map' is for strict completion and for
+ cautious completion.
+
+ * `repeat-complex-command-map' is for use in `C-x ESC'.
+
+ Finally, each prefix key has a keymap which defines the key sequences
+that start with it. For example, `ctl-x-map' is the keymap used for
+characters following a `C-x'.
+
+ * `ctl-x-map' is the variable name for the map used for characters
+ that follow `C-x'.
+
+ * `help-map' is used for characters that follow `C-h'.
+
+ * `esc-map' is for characters that follow ESC. Thus, all Meta
+ characters are actually defined by this map.
+
+ * `ctl-x-4-map' is for characters that follow `C-x 4'.
+
+ * `mode-specific-map' is for characters that follow `C-c'.
+
+ The definition of a prefix key is just the keymap to use for looking
+up the following character. Actually, the definition is sometimes a
+Lisp symbol whose function definition is the following character
+keymap. The effect is the same, but it provides a command name for the
+prefix key that can be used as a description of what the prefix key is
+for. Thus, the binding of `C-x' is the symbol `Ctl-X-Prefix', whose
+function definition is the keymap for `C-x' commands, the value of
+`ctl-x-map'.
+
+ Prefix key definitions of this sort can appear in either the global
+map or a local map. The definitions of `C-c', `C-x', `C-h' and ESC as
+prefix keys appear in the global map, so these prefix keys are always
+available. Major modes can locally redefine a key as a prefix by
+putting a prefix key definition for it in the local map.
+
+ A mode can also put a prefix definition of a global prefix character
+such as `C-x' into its local map. This is how major modes override the
+definitions of certain keys that start with `C-x'. This case is
+special, because the local definition does not entirely replace the
+global one. When both the global and local definitions of a key are
+other keymaps, the next character is looked up in both keymaps, with
+the local definition overriding the global one as usual. So, the
+character after the `C-x' is looked up in both the major mode's own
+keymap for redefined `C-x' commands and in `ctl-x-map'. If the major
+mode's own keymap for `C-x' commands contains `nil', the definition
+from the global keymap for `C-x' commands is used.
+
+ A keymap is actually a Lisp object. The simplest form of keymap is a
+Lisp vector of length 128. The binding for a character in such a
+keymap is found by indexing into the vector with the character as an
+index. A keymap can also be a Lisp list whose CAR is the symbol
+`keymap' and whose remaining elements are pairs of the form `(CHAR .
+BINDING)'. Such lists are called "sparse keymaps" because they are used
+when most of the characters' entries will be `nil'. Sparse keymaps are
+used mainly for prefix characters.
+
+ Keymaps are only of length 128, so what about Meta characters, whose
+codes are from 128 to 255? A key that contains a Meta character
+actually represents it as a sequence of two characters, the first of
+which is ESC. So the key `M-a' is really represented as `ESC a', and
+its binding is found at the slot for `a' in `esc-map'.
+
+
+File: emacs, Node: Rebinding, Next: Disabling, Prev: Keymaps, Up: Key Bindings
+
+Changing Key Bindings Interactively
+-----------------------------------
+
+ The way to redefine an Emacs key is to change its entry in a keymap.
+You can change the global keymap, in which case the change is effective
+in all major modes (except those that have their own overriding local
+definitions for the same key). Or you can change the current buffer's
+local map, which affects all buffers using the same major mode.
+
+`M-x global-set-key RET KEY CMD RET'
+ Defines KEY globally to run CMD.
+
+`M-x local-set-key RET KEY CMD RET'
+ Defines KEY locally (in the major mode now in effect) to run CMD.
+
+ For example,
+
+ M-x global-set-key RET C-f next-line RET
+
+would redefine `C-f' to move down a line. The fact that CMD is read
+second makes it serve as a kind of confirmation for KEY.
+
+ These functions offer no way to specify a particular prefix keymap
+as the one to redefine in, but that is not necessary, as you can
+include prefixes in KEY. KEY is read by reading characters one by one
+until they amount to a complete key (that is, not a prefix key). Thus,
+if you type `C-f' for KEY, that's the end; the minibuffer is entered
+immediately to read CMD. But if you type `C-x', another character is
+read; if that is `4', another character is read, and so on. For
+example,
+
+ M-x global-set-key RET C-x 4 $ spell-other-window RET
+
+would redefine `C-x 4 $' to run the (fictitious) command
+`spell-other-window'.
+
+ All the key sequences which consist of `C-c' followed by a letter
+are supposed to be reserved for user customization. That is, Emacs Lisp
+libraries should not define any of these commands.
+
+ The most general way to modify a keymap is the function `define-key',
+used in Lisp code (such as your `.emacs' file). `define-key' takes
+three arguments: the keymap, the key to modify in it, and the new
+definition. *Note Init File::, for an example.
+`substitute-key-definition' is used similarly; it takes three
+arguments, an old definition, a new definition and a keymap, and
+redefines in that keymap all keys that were previously defined with the
+old definition to have the new definition instead.
+
+
+File: emacs, Node: Disabling, Prev: Rebinding, Up: Key Bindings
+
+Disabling Commands
+------------------
+
+ Disabling a command marks the command as requiring confirmation
+before it can be executed. The purpose of disabling a command is to
+prevent beginning users from executing it by accident and being
+confused.
+
+ The direct mechanism for disabling a command is to have a non-`nil'
+`disabled' property on the Lisp symbol for the command. These
+properties are normally set up by the user's `.emacs' file with Lisp
+expressions such as
+
+ (put 'delete-region 'disabled t)
+
+ If the value of the `disabled' property is a string, that string is
+included in the message printed when the command is used:
+
+ (put 'delete-region 'disabled
+ "Text deleted this way cannot be yanked back!\n")
+
+ You can make a command disabled either by editing the `.emacs' file
+directly or with the command `M-x disable-command', which edits the
+`.emacs' file for you. *Note Init File::.
+
+ Attempting to invoke a disabled command interactively in Emacs
+causes the display of a window containing the command's name, its
+documentation, and some instructions on what to do immediately; then
+Emacs asks for input saying whether to execute the command as
+requested, enable it and execute, or cancel it. If you decide to
+enable the command, you are asked whether to do this permanently or
+just for the current session. Enabling permanently works by
+automatically editing your `.emacs' file. You can use `M-x
+enable-command' at any time to enable any command permanently.
+
+ Whether a command is disabled is independent of what key is used to
+invoke it; it also applies if the command is invoked using `M-x'.
+Disabling a command has no effect on calling it as a function from Lisp
+programs.
+
+
+File: emacs, Node: Syntax, Next: Init File, Prev: Key Bindings, Up: Customization
+
+The Syntax Table
+================
+
+ All the Emacs commands which parse words or balance parentheses are
+controlled by the "syntax table". The syntax table says which
+characters are opening delimiters, which are parts of words, which are
+string quotes, and so on. Actually, each major mode has its own syntax
+table (though sometimes related major modes use the same one) which it
+installs in each buffer that uses that major mode. The syntax table
+installed in the current buffer is the one that all commands use, so we
+call it "the" syntax table. A syntax table is a Lisp object, a vector
+of length 256 whose elements are numbers.
+
+* Menu:
+
+* Entry: Syntax Entry. What the syntax table records for each character.
+* Change: Syntax Change. How to change the information.
+
+
+File: emacs, Node: Syntax Entry, Next: Syntax Change, Prev: Syntax, Up: Syntax
+
+Information about Each Character
+--------------------------------
+
+ The syntax table entry for a character is a number that encodes six
+pieces of information:
+
+ * The syntactic class of the character, represented as a small
+ integer.
+
+ * The matching delimiter, for delimiter characters only. The
+ matching delimiter of `(' is `)', and vice versa.
+
+ * A flag saying whether the character is the first character of a
+ two-character comment starting sequence.
+
+ * A flag saying whether the character is the second character of a
+ two-character comment starting sequence.
+
+ * A flag saying whether the character is the first character of a
+ two-character comment ending sequence.
+
+ * A flag saying whether the character is the second character of a
+ two-character comment ending sequence.
+
+ The syntactic classes are stored internally as small integers, but
+are usually described to or by the user with characters. For example,
+`(' is used to specify the syntactic class of opening delimiters. Here
+is a table of syntactic classes, with the characters that specify them.
+
+` '
+ The class of whitespace characters.
+
+`-'
+ Another name for the class of whitespace characters.
+
+`w'
+ The class of word-constituent characters.
+
+`_'
+ The class of characters that are part of symbol names but not
+ words. This class is represented by `_' because the character `_'
+ has this class in both C and Lisp.
+
+`.'
+ The class of punctuation characters that do not fit into any other
+ special class.
+
+`('
+ The class of opening delimiters.
+
+`)'
+ The class of closing delimiters.
+
+`''
+ The class of expression-adhering characters. These characters are
+ part of a symbol if found within or adjacent to one, and are part
+ of a following expression if immediately preceding one, but are
+ like whitespace if surrounded by whitespace.
+
+`"'
+ The class of string-quote characters. They match each other in
+ pairs, and the characters within the pair all lose their syntactic
+ significance except for the `\' and `/' classes of escape
+ characters, which can be used to include a string-quote inside the
+ string.
+
+`$'
+ The class of self-matching delimiters. This is intended for TeX's
+ `$', which is used both to enter and leave math mode. Thus, a
+ pair of matching `$' characters surround each piece of math mode
+ TeX input. A pair of adjacent `$' characters act like a single
+ one for purposes of matching.
+
+`/'
+ The class of escape characters that always just deny the following
+ character its special syntactic significance. The character after
+ one of these escapes is always treated as alphabetic.
+
+`\'
+ The class of C-style escape characters. In practice, these are
+ treated just like `/'-class characters, because the extra
+ possibilities for C escapes (such as being followed by digits)
+ have no effect on where the containing expression ends.
+
+`<'
+ The class of comment-starting characters. Only single-character
+ comment starters (such as `;' in Lisp mode) are represented this
+ way.
+
+`>'
+ The class of comment-ending characters. Newline has this syntax in
+ Lisp mode.
+
+ The characters flagged as part of two-character comment delimiters
+can have other syntactic functions most of the time. For example, `/'
+and `*' in C code, when found separately, have nothing to do with
+comments. The comment-delimiter significance overrides when the pair of
+characters occur together in the proper order. Only the list and sexp
+commands use the syntax table to find comments; the commands
+specifically for comments have other variables that tell them where to
+find comments. And the list and sexp commands notice comments only if
+`parse-sexp-ignore-comments' is non-`nil'. This variable is set to
+`nil' in modes where comment-terminator sequences are liable to appear
+where there is no comment; for example, in Lisp mode where the comment
+terminator is a newline but not every newline ends a comment.
+
+
+File: emacs, Node: Syntax Change, Prev: Syntax Entry, Up: Syntax
+
+Altering Syntax Information
+---------------------------
+
+ It is possible to alter a character's syntax table entry by storing
+a new number in the appropriate element of the syntax table, but it
+would be hard to determine what number to use. Therefore, Emacs
+provides a command that allows you to specify the syntactic properties
+of a character in a convenient way.
+
+ `M-x modify-syntax-entry' is the command to change a character's
+syntax. It can be used interactively, and is also the means used by
+major modes to initialize their own syntax tables. Its first argument
+is the character to change. The second argument is a string that
+specifies the new syntax. When called from Lisp code, there is a
+third, optional argument, which specifies the syntax table in which to
+make the change. If not supplied, or if this command is called
+interactively, the third argument defaults to the current buffer's
+syntax table.
+
+ 1. The first character in the string specifies the syntactic class.
+ It is one of the characters in the previous table (*note Syntax
+ Entry::.).
+
+ 2. The second character is the matching delimiter. For a character
+ that is not an opening or closing delimiter, this should be a
+ space, and may be omitted if no following characters are needed.
+
+ 3. The remaining characters are flags. The flag characters allowed
+ are
+
+ `1'
+ Flag this character as the first of a two-character comment
+ starting sequence.
+
+ `2'
+ Flag this character as the second of a two-character comment
+ starting sequence.
+
+ `3'
+ Flag this character as the first of a two-character comment
+ ending sequence.
+
+ `4'
+ Flag this character as the second of a two-character comment
+ ending sequence.
+
+ A description of the contents of the current syntax table can be
+displayed with `C-h s' (`describe-syntax'). The description of each
+character includes both the string you would have to give to
+`modify-syntax-entry' to set up that character's current syntax, and
+some English to explain that string if necessary.
+
+
+File: emacs, Node: Init File, Prev: Syntax, Up: Customization
+
+The Init File, .emacs
+=====================
+
+ When Emacs is started, it normally loads the file `.emacs' in your
+home directory. This file, if it exists, should contain Lisp code. It
+is called your "init file". The command line switches `-q' and `-u'
+can be used to tell Emacs whether to load an init file (*note Entering
+Emacs::.).
+
+ There can also be a "default init file", which is the library named
+`default.el', found via the standard search path for libraries. The
+Emacs distribution contains no such library; your site may create one
+for local customizations. If this library exists, it is loaded
+whenever you start Emacs. But your init file, if any, is loaded first;
+if it sets `inhibit-default-init' non-`nil', then `default' is not
+loaded.
+
+ If you have a large amount of code in your `.emacs' file, you should
+move it into another file named `SOMETHING.el', byte-compile it (*note
+Lisp Libraries::.), and make your `.emacs' file load the other file
+using `load'.
+
+* Menu:
+
+* Init Syntax:: Syntax of constants in Emacs Lisp.
+* Init Examples:: How to do some things with an init file.
+* Terminal Init:: Each terminal type can have an init file.
+* Debugging Init:: How to debug your `.emacs' file.
+
+
+File: emacs, Node: Init Syntax, Next: Init Examples, Prev: Init File, Up: Init File
+
+Init File Syntax
+----------------
+
+ The `.emacs' file contains one or more Lisp function call
+expressions. Each of these consists of a function name followed by
+arguments, all surrounded by parentheses. For example, `(setq
+fill-column 60)' represents a call to the function `setq' which is used
+to set the variable `fill-column' (*note Filling::.) to 60.
+
+ The second argument to `setq' is an expression for the new value of
+the variable. This can be a constant, a variable, or a function call
+expression. In `.emacs', constants are used most of the time. They
+can be:
+
+Numbers:
+ Numbers are written in decimal, with an optional initial minus
+ sign.
+
+Strings:
+ Lisp string syntax is the same as C string syntax with a few extra
+ features. Use a double-quote character to begin and end a string
+ constant.
+
+ Newlines and special characters may be present literally in
+ strings. They can also be represented as backslash sequences:
+ `\n' for newline, `\b' for backspace, `\r' for carriage return,
+ `\t' for tab, `\f' for formfeed (control-l), `\e' for escape, `\\'
+ for a backslash, `\"' for a double-quote, or `\OOO' for the
+ character whose octal code is OOO. Backslash and double-quote are
+ the only characters for which backslash sequences are mandatory.
+
+ `\C-' can be used as a prefix for a control character, as in
+ `\C-s' for ASCII Control-S, and `\M-' can be used as a prefix for
+ a meta character, as in `\M-a' for Meta-A or `\M-\C-a' for
+ Control-Meta-A.
+
+Characters:
+ Lisp character constant syntax consists of a `?' followed by
+ either a character or an escape sequence starting with `\'.
+ Examples: `?x', `?\n', `?\"', `?\)'. Note that strings and
+ characters are not interchangeable in Lisp; some contexts require
+ one and some contexts require the other.
+
+True:
+ `t' stands for `true'.
+
+False:
+ `nil' stands for `false'.
+
+Other Lisp objects:
+ Write a single-quote (') followed by the Lisp object you want.
+
+ \ No newline at end of file
diff --git a/info/emacs-12 b/info/emacs-12
new file mode 100644
index 00000000000..ce4255c7a54
--- /dev/null
+++ b/info/emacs-12
@@ -0,0 +1,1216 @@
+This is Info file ../info/emacs, produced by Makeinfo-1.49 from the
+input file emacs.texi.
+
+ This file documents the GNU Emacs editor.
+
+ Copyright (C) 1985, 1986, 1988, 1992 Richard M. Stallman.
+
+ Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+ Permission is granted to copy and distribute modified versions of
+this manual under the conditions for verbatim copying, provided also
+that the sections entitled "The GNU Manifesto", "Distribution" and "GNU
+General Public License" are included exactly as in the original, and
+provided that the entire resulting derived work is distributed under the
+terms of a permission notice identical to this one.
+
+ Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that the sections entitled "The GNU Manifesto",
+"Distribution" and "GNU General Public License" may be included in a
+translation approved by the author instead of in the original English.
+
+
+File: emacs, Node: Init Examples, Next: Terminal Init, Prev: Init Syntax, Up: Init File
+
+Init File Examples
+------------------
+
+ Here are some examples of doing certain commonly desired things with
+Lisp expressions:
+
+ * Make TAB in C mode just insert a tab if point is in the middle of a
+ line.
+
+ (setq c-tab-always-indent nil)
+
+ Here we have a variable whose value is normally `t' for `true' and
+ the alternative is `nil' for `false'.
+
+ * Make searches case sensitive by default (in all buffers that do not
+ override this).
+
+ (setq-default case-fold-search nil)
+
+ This sets the default value, which is effective in all buffers
+ that do not have local values for the variable. Setting
+ `case-fold-search' with `setq' affects only the current buffer's
+ local value, which is not what you probably want to do in an init
+ file.
+
+ * Make Text mode the default mode for new buffers.
+
+ (setq default-major-mode 'text-mode)
+
+ Note that `text-mode' is used because it is the command for
+ entering the mode we want. A single-quote is written before it to
+ make a symbol constant; otherwise, `text-mode' would be treated as
+ a variable name.
+
+ * Turn on Auto Fill mode automatically in Text mode and related
+ modes.
+
+ (setq text-mode-hook
+ '(lambda () (auto-fill-mode 1)))
+
+ Here we have a variable whose value should be a Lisp function. The
+ function we supply is a list starting with `lambda', and a single
+ quote is written in front of it to make it (for the purpose of this
+ `setq') a list constant rather than an expression. Lisp functions
+ are not explained here, but for mode hooks it is enough to know
+ that `(auto-fill-mode 1)' is an expression that will be executed
+ when Text mode is entered, and you could replace it with any other
+ expression that you like, or with several expressions in a row.
+
+ (setq text-mode-hook 'turn-on-auto-fill)
+
+ This is another way to accomplish the same result.
+ `turn-on-auto-fill' is a symbol whose function definition is
+ `(lambda () (auto-fill-mode 1))'.
+
+ * Load the installed Lisp library named `foo' (actually a file
+ `foo.elc' or `foo.el' in a standard Emacs directory).
+
+ (load "foo")
+
+ When the argument to `load' is a relative pathname, not starting
+ with `/' or `~', `load' searches the directories in `load-path'
+ (*note Loading::.).
+
+ * Load the compiled Lisp file `foo.elc' from your home directory.
+
+ (load "~/foo.elc")
+
+ Here an absolute file name is used, so no searching is done.
+
+ * Rebind the key `C-x l' to run the function `make-symbolic-link'.
+
+ (global-set-key "\C-xl" 'make-symbolic-link)
+
+ or
+
+ (define-key global-map "\C-xl" 'make-symbolic-link)
+
+ Note once again the single-quote used to refer to the symbol
+ `make-symbolic-link' instead of its value as a variable.
+
+ * Do the same thing for C mode only.
+
+ (define-key c-mode-map "\C-xl" 'make-symbolic-link)
+
+ * Redefine all keys which now run `next-line' in Fundamental mode so
+ that they run `forward-line' instead.
+
+ (substitute-key-definition 'next-line 'forward-line
+ global-map)
+
+ * Make `C-x C-v' undefined.
+
+ (global-unset-key "\C-x\C-v")
+
+ One reason to undefine a key is so that you can make it a prefix.
+ Simply defining `C-x C-v ANYTHING' would make `C-x C-v' a prefix,
+ but `C-x C-v' must be freed of any non-prefix definition first.
+
+ * Make `$' have the syntax of punctuation in Text mode. Note the use
+ of a character constant for `$'.
+
+ (modify-syntax-entry ?\$ "." text-mode-syntax-table)
+
+ * Enable the use of the command `eval-expression' without
+ confirmation.
+
+ (put 'eval-expression 'disabled nil)
+
+
+File: emacs, Node: Terminal Init, Next: Debugging Init, Prev: Init Examples, Up: Init File
+
+Terminal-specific Initialization
+--------------------------------
+
+ Each terminal type can have a Lisp library to be loaded into Emacs
+when it is run on that type of terminal. For a terminal type named
+TERMTYPE, the library is called `term/TERMTYPE' and it is found by
+searching the directories `load-path' as usual and trying the suffixes
+`.elc' and `.el'. Normally it appears in the subdirectory `term' of
+the directory where most Emacs libraries are kept.
+
+ The usual purpose of the terminal-specific library is to define the
+escape sequences used by the terminal's function keys using the library
+`keypad.el'. See the file `term/vt100.el' for an example of how this
+is done.
+
+ When the terminal type contains a hyphen, only the part of the name
+before the first hyphen is significant in choosing the library name.
+Thus, terminal types `aaa-48' and `aaa-30-rv' both use the library
+`term/aaa'. The code in the library can use `(getenv "TERM")' to find
+the full terminal type name.
+
+ The library's name is constructed by concatenating the value of the
+variable `term-file-prefix' and the terminal type. Your `.emacs' file
+can prevent the loading of the terminal-specific library by setting
+`term-file-prefix' to `nil'.
+
+ The value of the variable `term-setup-hook', if not `nil', is called
+as a function of no arguments at the end of Emacs initialization, after
+both your `.emacs' file and any terminal-specific library have been
+read in. You can set the value in the `.emacs' file to override part
+of any of the terminal-specific libraries and to define initializations
+for terminals that do not have a library.
+
+
+File: emacs, Node: Debugging Init, Prev: Terminal Init, Up: Init File
+
+Debugging Your `.emacs' File
+----------------------------
+
+ Ordinarily, Emacs traps errors that occur while reading `.emacs'.
+This is convenient, most of the time, because it means you can still get
+an Emacs in which you can edit. But it causes inconvenience because
+there is no way to enter the debugger if there is an error.
+
+ But you can run the `.emacs' file explicitly in an Emacs that is
+already set up, and debug errors at that time.
+
+ M-x set-variable
+ debug-on-error
+ t
+ M-x load-file
+ ~/.emacs
+
+ In Emacs 19, use the `-debug-init' option if you want errors in
+`.emacs' to enter the debugger.
+
+
+File: emacs, Node: Quitting, Next: Lossage, Prev: Customization, Up: Top
+
+Quitting and Aborting
+=====================
+
+`C-g'
+ Quit. Cancel running or partially typed command.
+
+`C-]'
+ Abort innermost recursive editing level and cancel the command
+ which invoked it (`abort-recursive-edit').
+
+`M-x top-level'
+ Abort all recursive editing levels that are currently executing.
+
+`C-x u'
+ Cancel an already-executed command, usually (`undo').
+
+ There are two ways of cancelling commands which are not finished
+executing: "quitting" with `C-g', and "aborting" with `C-]' or `M-x
+top-level'. Quitting is cancelling a partially typed command or one
+which is already running. Aborting is getting out of a recursive
+editing level and cancelling the command that invoked the recursive
+edit.
+
+ Quitting with `C-g' is used for getting rid of a partially typed
+command, or a numeric argument that you don't want. It also stops a
+running command in the middle in a relatively safe way, so you can use
+it if you accidentally give a command which takes a long time. In
+particular, it is safe to quit out of killing; either your text will
+ALL still be there, or it will ALL be in the kill ring (or maybe both).
+ Quitting an incremental search does special things documented under
+searching; in general, it may take two successive `C-g' characters to
+get out of a search. `C-g' works by setting the variable `quit-flag' to
+`t' the instant `C-g' is typed; Emacs Lisp checks this variable
+frequently and quits if it is non-`nil'. `C-g' is only actually
+executed as a command if it is typed while Emacs is waiting for input.
+
+ If you quit twice in a row before the first `C-g' is recognized, you
+activate the "emergency escape" feature and return to the shell. *Note
+Emergency Escape::.
+
+ Aborting with `C-]' (`abort-recursive-edit') is used to get out of a
+recursive editing level and cancel the command which invoked it.
+Quitting with `C-g' does not do this, and could not do this, because it
+is used to cancel a partially typed command within the recursive
+editing level. Both operations are useful. For example, if you are in
+the Emacs debugger (*note Lisp Debug::.) and have typed `C-u 8' to
+enter a numeric argument, you can cancel that argument with `C-g' and
+remain in the debugger.
+
+ The command `M-x top-level' is equivalent to "enough" `C-]' commands
+to get you out of all the levels of recursive edits that you are in.
+`C-]' gets you out one level at a time, but `M-x top-level' goes out
+all levels at once. Both `C-]' and `M-x top-level' are like all other
+commands, and unlike `C-g', in that they are effective only when Emacs
+is ready for a command. `C-]' is an ordinary key and has its meaning
+only because of its binding in the keymap. *Note Recursive Edit::.
+
+ `C-x u' (`undo') is not strictly speaking a way of cancelling a
+command, but you can think of it as cancelling a command already
+finished executing. *Note Undo::.
+
+
+File: emacs, Node: Lossage, Next: Bugs, Prev: Quitting, Up: Top
+
+Dealing with Emacs Trouble
+==========================
+
+ This section describes various conditions in which Emacs fails to
+work, and how to recognize them and correct them.
+
+* Menu:
+
+* Stuck Recursive:: `[...]' in mode line around the parentheses
+* Screen Garbled:: Garbage on the screen
+* Text Garbled:: Garbage in the text
+* Unasked-for Search:: Spontaneous entry to incremental search
+* Emergency Escape:: Emergency escape--
+ What to do if Emacs stops responding
+* Total Frustration:: When you are at your wits' end.
+
+
+File: emacs, Node: Stuck Recursive, Next: Screen Garbled, Prev: Lossage, Up: Lossage
+
+Recursive Editing Levels
+------------------------
+
+ Recursive editing levels are important and useful features of Emacs,
+but they can seem like malfunctions to the user who does not understand
+them.
+
+ If the mode line has square brackets `[...]' around the parentheses
+that contain the names of the major and minor modes, you have entered a
+recursive editing level. If you did not do this on purpose, or if you
+don't understand what that means, you should just get out of the
+recursive editing level. To do so, type `M-x top-level'. This is
+called getting back to top level. *Note Recursive Edit::.
+
+
+File: emacs, Node: Screen Garbled, Next: Text Garbled, Prev: Stuck Recursive, Up: Lossage
+
+Garbage on the Screen
+---------------------
+
+ If the data on the screen looks wrong, the first thing to do is see
+whether the text is really wrong. Type `C-l', to redisplay the entire
+screen. If it appears correct after this, the problem was entirely in
+the previous screen update.
+
+ Display updating problems often result from an incorrect termcap
+entry for the terminal you are using. The file `etc/TERMS' in the Emacs
+distribution gives the fixes for known problems of this sort. `INSTALL'
+contains general advice for these problems in one of its sections.
+Very likely there is simply insufficient padding for certain display
+operations. To investigate the possibility that you have this sort of
+problem, try Emacs on another terminal made by a different manufacturer.
+If problems happen frequently on one kind of terminal but not another
+kind, it is likely to be a bad termcap entry, though it could also be
+due to a bug in Emacs that appears for terminals that have or that lack
+specific features.
+
+
+File: emacs, Node: Text Garbled, Next: Unasked-for Search, Prev: Screen Garbled, Up: Lossage
+
+Garbage in the Text
+-------------------
+
+ If `C-l' shows that the text is wrong, try undoing the changes to it
+using `C-x u' until it gets back to a state you consider correct. Also
+try `C-h l' to find out what command you typed to produce the observed
+results.
+
+ If a large portion of text appears to be missing at the beginning or
+end of the buffer, check for the word `Narrow' in the mode line. If it
+appears, the text is still present, but marked off-limits. To make it
+visible again, type `C-x w'. *Note Narrowing::.
+
+
+File: emacs, Node: Unasked-for Search, Next: Emergency Escape, Prev: Text Garbled, Up: Lossage
+
+Spontaneous Entry to Incremental Search
+---------------------------------------
+
+ If Emacs spontaneously displays `I-search:' at the bottom of the
+screen, it means that the terminal is sending `C-s' and `C-q' according
+to the poorly designed `xon/xoff' "flow control" protocol. You should
+try to prevent this by putting the terminal in a mode where it will not
+use flow control or giving it enough padding that it will never send a
+`C-s'. If that cannot be done, you must tell Emacs to expect flow
+control to be used, until you can get a properly designed terminal.
+
+ Information on how to do these things can be found in the file
+`INSTALL' in the Emacs distribution.
+
+
+File: emacs, Node: Emergency Escape, Next: Total Frustration, Prev: Unasked-for Search, Up: Lossage
+
+Emergency Escape
+----------------
+
+ Because at times there have been bugs causing Emacs to loop without
+checking `quit-flag', a special feature causes Emacs to be suspended
+immediately if you type a second `C-g' while the flag is already set,
+so you can always get out of GNU Emacs. Normally Emacs recognizes and
+clears `quit-flag' (and quits!) quickly enough to prevent this from
+happening.
+
+ When you resume Emacs after a suspension caused by multiple `C-g', it
+asks two questions before going back to what it had been doing:
+
+ Auto-save? (y or n)
+ Abort (and dump core)? (y or n)
+
+Answer each one with `y' or `n' followed by RET.
+
+ Saying `y' to `Auto-save?' causes immediate auto-saving of all
+modified buffers in which auto-saving is enabled.
+
+ Saying `y' to `Abort (and dump core)?' causes an illegal instruction
+to be executed, dumping core. This is to enable a wizard to figure out
+why Emacs was failing to quit in the first place. Execution does not
+continue after a core dump. If you answer `n', execution does
+continue. With luck, GNU Emacs will ultimately check `quit-flag' and
+quit normally. If not, and you type another `C-g', it is suspended
+again.
+
+ If Emacs is not really hung, just slow, you may invoke the double
+`C-g' feature without really meaning to. Then just resume and answer
+`n' to both questions, and you will arrive at your former state.
+Presumably the quit you requested will happen soon.
+
+ The double-`C-g' feature may be turned off when Emacs is running
+under a window system, since the window system always enables you to
+kill Emacs or to create another window and run another program.
+
+
+File: emacs, Node: Total Frustration, Prev: Emergency Escape, Up: Lossage
+
+Help for Total Frustration
+--------------------------
+
+ If using Emacs (or something else) becomes terribly frustrating and
+none of the techniques described above solve the problem, Emacs can
+still help you.
+
+ First, if the Emacs you are using is not responding to commands, type
+`C-g C-g' to get out of it and then start a new one.
+
+ Second, type `M-x doctor RET'.
+
+ The doctor will make you feel better. Each time you say something to
+the doctor, you must end it by typing RET RET. This lets the doctor
+know you are finished.
+
+
+File: emacs, Node: Bugs, Next: Version 19, Prev: Lossage, Up: Top
+
+Reporting Bugs
+==============
+
+ Sometimes you will encounter a bug in Emacs. Although we cannot
+promise we can or will fix the bug, and we might not even agree that it
+is a bug, we want to hear about bugs you encounter in case we do want
+to fix them.
+
+ To make it possible for us to fix a bug, you must report it. In
+order to do so effectively, you must know when and how to do it.
+
+When Is There a Bug
+-------------------
+
+ If Emacs executes an illegal instruction, or dies with an operating
+system error message that indicates a problem in the program (as
+opposed to something like "disk full"), then it is certainly a bug.
+
+ If Emacs updates the display in a way that does not correspond to
+what is in the buffer, then it is certainly a bug. If a command seems
+to do the wrong thing but the problem corrects itself if you type
+`C-l', it is a case of incorrect display updating.
+
+ Taking forever to complete a command can be a bug, but you must make
+certain that it was really Emacs's fault. Some commands simply take a
+long time. Type `C-g' and then `C-h l' to see whether the input Emacs
+received was what you intended to type; if the input was such that you
+KNOW it should have been processed quickly, report a bug. If you don't
+know whether the command should take a long time, find out by looking
+in the manual or by asking for assistance.
+
+ If a command you are familiar with causes an Emacs error message in a
+case where its usual definition ought to be reasonable, it is probably a
+bug.
+
+ If a command does the wrong thing, that is a bug. But be sure you
+know for certain what it ought to have done. If you aren't familiar
+with the command, or don't know for certain how the command is supposed
+to work, then it might actually be working right. Rather than jumping
+to conclusions, show the problem to someone who knows for certain.
+
+ Finally, a command's intended definition may not be best for editing
+with. This is a very important sort of problem, but it is also a
+matter of judgment. Also, it is easy to come to such a conclusion out
+of ignorance of some of the existing features. It is probably best not
+to complain about such a problem until you have checked the
+documentation in the usual ways, feel confident that you understand it,
+and know for certain that what you want is not available. If you are
+not sure what the command is supposed to do after a careful reading of
+the manual, check the index and glossary for any terms that may be
+unclear. If you still do not understand, this indicates a bug in the
+manual. The manual's job is to make everything clear. It is just as
+important to report documentation bugs as program bugs.
+
+ If the on-line documentation string of a function or variable
+disagrees with the manual, one of them must be wrong, so report the bug.
+
+How to Report a Bug
+-------------------
+
+ When you decide that there is a bug, it is important to report it
+and to report it in a way which is useful. What is most useful is an
+exact description of what commands you type, starting with the shell
+command to run Emacs, until the problem happens. Always include the
+version number of Emacs that you are using; type `M-x emacs-version' to
+print this.
+
+ The most important principle in reporting a bug is to report FACTS,
+not hypotheses or categorizations. It is always easier to report the
+facts, but people seem to prefer to strain to posit explanations and
+report them instead. If the explanations are based on guesses about
+how Emacs is implemented, they will be useless; we will have to try to
+figure out what the facts must have been to lead to such speculations.
+Sometimes this is impossible. But in any case, it is unnecessary work
+for us.
+
+ For example, suppose that you type `C-x C-f /glorp/baz.ugh RET',
+visiting a file which (you know) happens to be rather large, and Emacs
+prints out `I feel pretty today'. The best way to report the bug is
+with a sentence like the preceding one, because it gives all the facts
+and nothing but the facts.
+
+ Do not assume that the problem is due to the size of the file and
+say, "When I visit a large file, Emacs prints out `I feel pretty
+today'." This is what we mean by "guessing explanations". The problem
+is just as likely to be due to the fact that there is a `z' in the file
+name. If this is so, then when we got your report, we would try out
+the problem with some "large file", probably with no `z' in its name,
+and not find anything wrong. There is no way in the world that we
+could guess that we should try visiting a file with a `z' in its name.
+
+ Alternatively, the problem might be due to the fact that the file
+starts with exactly 25 spaces. For this reason, you should make sure
+that you inform us of the exact contents of any file that is needed to
+reproduce the bug. What if the problem only occurs when you have typed
+the `C-x C-a' command previously? This is why we ask you to give the
+exact sequence of characters you typed since starting to use Emacs.
+
+ You should not even say "visit a file" instead of `C-x C-f' unless
+you know that it makes no difference which visiting command is used.
+Similarly, rather than saying "if I have three characters on the line,"
+say "after I type `RET A B C' RET C-p," if that is the way you entered
+the text.
+
+ If you are not in Fundamental mode when the problem occurs, you
+should say what mode you are in.
+
+ If the manifestation of the bug is an Emacs error message, it is
+important to report not just the text of the error message but a
+backtrace showing how the Lisp program in Emacs arrived at the error.
+To make the backtrace, you must execute the Lisp expression `(setq
+debug-on-error t)' before the error happens (that is to say, you must
+execute that expression and then make the bug happen). This causes the
+Lisp debugger to run (*note Lisp Debug::.). The debugger's backtrace
+can be copied as text into the bug report. This use of the debugger is
+possible only if you know how to make the bug happen again. Do note
+the error message the first time the bug happens, so if you can't make
+it happen again, you can report at least that.
+
+ Check whether any programs you have loaded into the Lisp world,
+including your `.emacs' file, set any variables that may affect the
+functioning of Emacs. Also, see whether the problem happens in a
+freshly started Emacs without loading your `.emacs' file (start Emacs
+with the `-q' switch to prevent loading the init file.) If the problem
+does NOT occur then, it is essential that we know the contents of any
+programs that you must load into the Lisp world in order to cause the
+problem to occur.
+
+ If the problem does depend on an init file or other Lisp programs
+that are not part of the standard Emacs system, then you should make
+sure it is not a bug in those programs by complaining to their
+maintainers first. After they verify that they are using Emacs in a way
+that is supposed to work, they should report the bug.
+
+ If you can tell us a way to cause the problem without visiting any
+files, please do so. This makes it much easier to debug. If you do
+need files, make sure you arrange for us to see their exact contents.
+For example, it can often matter whether there are spaces at the ends
+of lines, or a newline after the last line in the buffer (nothing ought
+to care whether the last line is terminated, but tell that to the bugs).
+
+ The easy way to record the input to Emacs precisely is to write a
+dribble file; execute the Lisp expression
+
+ (open-dribble-file "~/dribble")
+
+using `Meta-ESC' or from the `*scratch*' buffer just after starting
+Emacs. From then on, all Emacs input will be written in the specified
+dribble file until the Emacs process is killed.
+
+ For possible display bugs, it is important to report the terminal
+type (the value of environment variable `TERM'), the complete termcap
+entry for the terminal from `/etc/termcap' (since that file is not
+identical on all machines), and the output that Emacs actually sent to
+the terminal. The way to collect this output is to execute the Lisp
+expression
+
+ (open-termscript "~/termscript")
+
+using `Meta-ESC' or from the `*scratch*' buffer just after starting
+Emacs. From then on, all output from Emacs to the terminal will be
+written in the specified termscript file as well, until the Emacs
+process is killed. If the problem happens when Emacs starts up, put
+this expression into your `.emacs' file so that the termscript file will
+be open when Emacs displays the screen for the first time. Be warned:
+it is often difficult, and sometimes impossible, to fix a
+terminal-dependent bug without access to a terminal of the type that
+stimulates the bug.
+
+ The address for reporting bugs is
+
+GNU Emacs Bugs
+Free Software Foundation
+675 Mass Ave
+Cambridge, MA 02139
+
+or send email either to `bug-gnu-emacs@prep.ai.mit.edu' (Internet) or
+to `uunet!prep.ai.mit.edu!bug-gnu-emacs' (Usenet).
+
+ Once again, we do not promise to fix the bug; but if the bug is
+serious, or ugly, or easy to fix, chances are we will want to.
+
+
+File: emacs, Node: Version 19, Next: Manifesto, Prev: Bugs, Up: Top
+
+Version 19 Antenews
+*******************
+
+ This chapter prematurely describes new features of Emacs 19, in
+anticipation of its release. We have included this so that the version
+18 manuals don't become obsolete as soon as Emacs 19 comes out. This
+list mentions only features that would belong in `The GNU Emacs
+Manual'; changes relevant to Emacs Lisp programming will be documented
+in the next revision of `The GNU Emacs Lisp Manual'.
+
+* Menu:
+
+* Basic Changes:: Changes every user must know.
+* New Facilities:: Changes every user will want to know.
+* Binding Changes:: Ordinary commands that have been moved. Important!.
+* Changed Commands:: Ordinary commands that have new features. Important!
+* M-x Changes:: Changes in commands you run with `M-x'. Important!
+* New Commands:: Commands that have been added
+ that we expect many users to want to use.
+* Search Changes:: Changes in incremental search. Some are important.
+
+The rest of the changes you can pretty much ignore unless you are interested.
+
+* Filling Changes:: Changes in fill commands.
+* TeX Mode Changes:: Changes in the commands for editing TeX files
+ and running TeX.
+* Shell Changes:: Major changes in all the modes that run subprograms.
+* Spell Changes:: These commands now use ispell instead of spell.
+* Tags Changes:: Changes in Tags facility.
+* Mail Changes:: Changes in both Sendmail mode and Rmail mode.
+* Info Changes:: New commands in Info.
+* Dired Changes:: Powerful new features in Dired.
+* GNUS:: An alternative news reader.
+* Calendar/Diary:: The calendar feature now lets you move to different
+ dates and convert to and from other calendars.
+ You can also display related entries from your diary
+ file.
+* Version Control:: A convenient interface to RCS or SCCS.
+* Emerge:: A new feature for merging files interactively.
+* Debuggers:: Running debuggers (GDB, DBX, SDB) under Emacs.
+* Other New Modes:: Miscellaneous new and changed major modes.
+* Key Sequence Changes:: You can now bind key sequences that include function
+ keys and mouse clicks.
+* Hook Changes:: Hook variables have been renamed more systematically.
+
+
+File: emacs, Node: Basic Changes, Next: New Facilities, Up: Version 19
+
+Basic Changes
+=============
+
+ We have made changes to help Emacs use fewer resources and make it
+less likely to become irreparably hung. While these changes don't
+alter the commands of Emacs, they are important enough to be worth
+mentioning.
+
+ You can quit with `C-g' while Emacs is waiting to read or write a
+file--provided the operating system will allow you to interrupt the
+system call that is hung. (Unfortunately, most NFS implementations
+won't allow interruption.)
+
+ When you kill buffers, Emacs now returns memory to the operating
+system, thus reducing the size of the Emacs process. The space that
+you free up by killing buffers can now be reused for other buffers no
+matter what their sizes, or reused by other processes if Emacs doesn't
+need it.
+
+Multiple X Windows
+------------------
+
+ When using X windows, you can now create more than one window at the
+X level. Each X window displays a "frame" which can contain one or
+several Emacs windows. Each frame has its own echo area and normally
+its own minibuffer. (To avoid confusion, we reserve the word "window"
+for the subdivisions that Emacs implements, and never use it to refer
+to a frame.) The easiest way to create additional frames is with the
+`C-x 5' prefix character (*note New Everyday Commands: New Commands.).
+
+ Emacs windows can now have scroll bars; use the `scroll-bar-mode'
+command to turn scroll bars on or off. With no argument, it toggles the
+use of scroll bars. With an argument, it turns use of scroll bars on if
+and only if the argument is positive. This command applies to all
+frames, including frames yet to be created. (You can control scroll
+bars on a frame by frame basis by writing a Lisp program.)
+
+Undo Improvements
+-----------------
+
+ Undoing a deletion now puts the cursor position where it was just
+before the deletion.
+
+Auto Save Improvements
+----------------------
+
+ Emacs now does garbage collection and auto saving while it is waiting
+for input, which often avoids the need to do these things while you are
+typing. The variable `auto-save-timeout' says how many seconds Emacs
+should wait, after you stop typing, before it does an auto save and
+perhaps also a garbage collection. (The actual time period varies also
+according to the size of the buffer--longer for longer buffers, since
+auto saving itself is slower for long buffers.) This way, Emacs does
+not interrupt or delay your typing.
+
+ In Emacs 18, when auto saving detects that a buffer has shrunk
+greatly, it refrains from auto saving that buffer and displays a
+warning. In version 19, it also turns off Auto Save mode in that
+buffer, so that you won't get the same warning repeatedly. If you
+reenable Auto Save mode in that buffer, Emacs will start saving it
+again despite the shrinkage.
+
+ In Emacs 19, `revert-buffer' no longer offers to revert from the
+latest auto-save file. That option hasn't been very useful since the
+change to keep more undo information.
+
+ The command `recover-file' no longer turns off Auto Save mode.
+
+File Local Variables
+--------------------
+
+ The user option for controlling whether files can set local
+variables is called `enable-local-variables' in Emacs 19, rather than
+`inhibit-local-variables'. A value of `t' means local-variables lists
+are obeyed; `nil' means they are ignored; anything else means query the
+user.
+
+
+File: emacs, Node: New Facilities, Next: Binding Changes, Prev: Basic Changes, Up: Version 19
+
+New Basic Facilities
+====================
+
+ You can now get back recent minibuffer inputs conveniently. While in
+the minibuffer, type `M-p' (`previous-history-element') to fetch the
+next earlier minibuffer input, and use `M-n' (`next-history-element')
+to fetch the next later input.
+
+ There are also commands to search forward or backward through the
+history. As of this writing, they search for history elements that
+match a regular expression that you specify with the minibuffer. `M-r'
+(`previous-matching-history-element') searches older elements in the
+history, while `M-s' (`next-matching-history-element') searches newer
+elements. By special dispensation, these commands can always use the
+minibuffer to read their arguments even though you are already in the
+minibuffer when you issue them.
+
+ We may have changed the precise way these commands work by the time
+you use Emacs 19. Perhaps they will search for a match for the string
+given so far in the minibuffer; perhaps they will search for a literal
+match rather than a regular expression match; perhaps they will only
+accept matches at the beginning of a history element; perhaps they will
+read the string to search for incrementally like `C-s'. We want to
+choose an interface that is convenient, flexible and natural, and these
+goals are somewhat contradictory. To find out what interface is
+actually available, type `C-h f previous-matching-history-element'.
+
+ The history feature is available for all uses of the minibuffer, but
+there are separate history lists for different kinds of input. For
+example, there is a list for file names, used by all the commands that
+read file names. There is a list for arguments of commands like
+`query-replace'. There are also very specific history lists, such as
+the one that `compile' uses for compilation commands.
+
+Remote File Access
+------------------
+
+ You can refer to files on other machines using a special file name
+syntax:
+
+ /HOST:FILENAME
+ /USER@HOST:FILENAME
+
+ When you do this, Emacs uses the FTP program to read and write files
+on the specified host. It logs in through FTP using your user name or
+the name USER. It may ask you for a password from time to time; this
+is used for logging in on HOST.
+
+Using Flow Control
+------------------
+
+ There is now a convenient way to enable flow control when your
+terminal or your connection won't work without it. Suppose you want to
+do this on VT-100 and H19 terminals; put the following in your `.emacs'
+file:
+
+ (evade-flow-control-on "vt100" "h19")
+
+ When flow control is enabled, you must type `C-\' to get the effect
+of a `C-s', and type `C-^' to get the effect of a `C-q'.
+
+Controlling Backup File Names
+-----------------------------
+
+ The default setting of the Lisp variable `version-control' now comes
+from the environment variable `VERSION_CONTROL'. Thus, you can select
+a style of backup file naming for Emacs and other GNU utilities all
+together.
+
+
+File: emacs, Node: Binding Changes, Next: Changed Commands, Prev: New Facilities, Up: Version 19
+
+Changed Key Bindings
+====================
+
+`M-{'
+ This is the new key sequence for `backward-paragraph'. The old key
+ sequence for this, `M-[', is now undefined by default.
+
+ The reason for this change is to avoid conflict with the sequences
+ that function keys send on most terminals.
+
+`M-}'
+ This is the new key sequence for `forward-paragraph'. The old key
+ sequence for this, `M-]', is now undefined by default.
+
+ We changed this to go along with `M-{'.
+
+`C-x C-u'
+`C-x C-l'
+ The two commands, `C-x C-u' (`upcase-region') and `C-x C-l'
+ (`downcase-region'), are now disabled by default; these keys seem
+ to be often hit by accident, and can be quite destructive if their
+ effects are not noticed immediately.
+
+`C-x 3'
+ `C-x 3' is now the key binding for `split-window-horizontally',
+ which splits a window into two side-by-side windows. This used to
+ be `C-x 5'.
+
+``C-x 4 C-o''
+ This key now runs `display-buffer', which displays a specified
+ buffer in another window without selecting it.
+
+`M-g'
+ `M-g' is now undefined. It used to run the command `fill-region'.
+ This command used to be run more often by mistake than on purpose.
+
+`C-x a'
+`C-x n'
+`C-x r'
+ Three new prefix keys have been created to make many of the `C-x'
+ commands more systematic: `C-x a', `C-x n' and `C-x r'. `C-x a' is
+ used for abbreviation commands, `C-x n' for commands pertaining to
+ narrowing, and `C-x r' for register and rectangle commands. These
+ are the new bindings, in detail:
+
+ `C-x a l'
+ `add-mode-abbrev' (previously `C-x C-a').
+
+ `C-x a g'
+ `add-global-abbrev' (previously `C-x +').
+
+ `C-x a i g'
+ `inverse-add-mode-abbrev' (previously `C-x C-h').
+
+ `C-x a i l'
+ `inverse-add-global-abbrev' (previously `C-x -').
+
+ `C-x a e'
+ `expand-abbrev' (previously `C-x '').
+
+ `C-x n n'
+ `narrow-to-region' (previously `C-x n').
+
+ `C-x n p'
+ `narrow-to-page' (previously `C-x p').
+
+ `C-x n w'
+ `widen' (previously `C-x w').
+
+ `C-x r C-SPC'
+ `point-to-register' (previously `C-x /').
+
+ `C-x r SPC'
+ Also `point-to-register' (previously `C-x /').
+
+ `C-x r j'
+ `jump-to-register' (previously `C-x j').
+
+ `C-x r s'
+ `copy-to-register' (previously `C-x x').
+
+ `C-x r i'
+ `insert-register' (previously `C-x g').
+
+ `C-x r r'
+ `copy-rectangle-to-register' (previously `C-x r').
+
+ `C-x r k'
+ `kill-rectangle' (no previous key binding).
+
+ `C-x r y'
+ `yank-rectangle' (no previous key binding).
+
+ `C-x r o'
+ `open-rectangle' (no previous key binding).
+
+ `C-x r f'
+ `frame-configuration-to-register' (a new command) saves the
+ state of all windows in all frames. Use `C-x r j' to restore
+ the configuration.
+
+ `C-x r w'
+ `window-configuration-to-register' (a new command) saves the
+ state of all windows in the selected frame. Use `C-x r j' to
+ restore the configuration.
+
+ The old key bindings `C-x /', `C-x j', `C-x x' and `C-x g' have
+ not yet been removed. The other old key bindings listed have been
+ removed. The old key binding `C-x a', which was
+ `append-to-buffer', was removed to make way for a prefix key; now
+ `append-to-buffer' has no keybinding.
+
+`C-x v'
+ `C-x v' is a new prefix character, used for version control
+ commands. *Note Version Control::.
+
+
+File: emacs, Node: Changed Commands, Next: M-x Changes, Prev: Binding Changes, Up: Version 19
+
+Changed Everyday Commands
+=========================
+
+`C-o'
+ When you have a fill prefix, the command `C-o' inserts the prefix
+ on the newly created line.
+
+`M-^'
+ When you have a fill prefix, the command `M-^' deletes the prefix
+ (if it occurs) after the newline that it deletes.
+
+`M-z'
+ The `M-z' command (`zap-to-char') now kills through the target
+ character. In version 18, it killed up to but not including the
+ target character.
+
+`M-!'
+ The command `M-!' (`shell-command') now runs the specified shell
+ command asynchronously if it ends in `&', just as the shell does.
+
+`C-x 2'
+ The `C-x 2' command (`split-window-vertically') now tries to avoid
+ scrolling by putting point in whichever window happens to contain
+ the screen line the cursor is already on. If you don't like this,
+ you can turn it off by setting `split-window-keep-point' to `nil'.
+
+`C-x s'
+ The `C-x s' command (`save-some-buffers') now gives you more
+ options when it asks whether to save a particular buffer. The
+ options are analogous to those of `query-replace'. Here they are:
+
+ `y'
+ Save this buffer and ask about the rest of the buffers.
+
+ `n'
+ Don't save this buffer, but ask about the rest of the buffers.
+
+ `!'
+ Save this buffer and all the rest with no more questions.
+
+ `ESC'
+ Terminate `save-some-buffers' without any more saving.
+
+ `.'
+ Save only this buffer, then exit `save-some-buffers' without
+ even asking about other buffers.
+
+ `C-r'
+ View the buffer that you are currently being asked about.
+ When you exit View mode, you get back to `save-some-buffers',
+ which asks the question again.
+
+ `C-h'
+ Display a help message about these options.
+
+`C-x C-v'
+ This command (`find-alternate-file') now inserts the entire current
+ file name in the minibuffer. This is convenient if you made a
+ small mistake in typing it. Point goes after the last slash,
+ before the last file name component, so if you want to replace it
+ entirely, you can use `C-k' right away to delete it.
+
+`C-M-f'
+ Expression and list commands such as `C-M-f' now ignore parentheses
+ within comments in Lisp mode.
+
+
+File: emacs, Node: M-x Changes, Next: New Commands, Prev: Changed Commands, Up: Version 19
+
+Changes in Common `M-x' Commands
+================================
+
+`M-x make-symbolic-link'
+ This command now does not expand its second argument. This lets
+ you make a link with a target that is a relative file name.
+
+`M-x add-change-log-entry'
+`C-x 4 a'
+ These commands now automatically insert the name of the file and
+ often the name of the function that you changed. They also handle
+ grouping of entries.
+
+ There is now a special major mode for editing `ChangeLog' files.
+ It makes filling work conveniently. Each bunch of grouped entries
+ is one paragraph, and each collection of entries from one person
+ on one day is considered a page.
+
+`M-x compare-windows'
+ With a prefix argument, `compare-windows' ignores changes in
+ whitespace. If the variable `compare-ignore-case' is non-`nil',
+ it ignores differences in case as well.
+
+`M-x view-buffer'
+`M-x view-file'
+ The View commands (such as `M-x view-buffer' and `M-x view-file')
+ no longer use recursive edits; instead, they switch temporarily to
+ a different major mode (View mode) specifically designed for
+ moving around through a buffer without editing it.
+
+`M-x manual-entry'
+ `M-x manual-entry' now uses View mode for the buffer showing the
+ man page.
+
+`M-x compile'
+ You can repeat any previous `compile' conveniently using the
+ minibuffer history commands, while in the minibuffer entering the
+ compilation command.
+
+ While a compilation is going on, the string `Compiling' appears in
+ the mode line. When this string disappears, the compilation is
+ finished.
+
+ The buffer of compiler messages is in Compilation mode. This mode
+ provides the keys SPC and DEL to scroll by screenfuls, and `M-n'
+ and `M-p' to move to the next or previous error message. You can
+ also use `M-{' and `M-}' to move up or down to an error message
+ for a different source file. Use `C-c C-c' on any error message
+ to find the corresponding source code.
+
+ Emacs 19 has a more general parser for compiler messages. For
+ example, it can understand messages from lint, and from certain C
+ compilers whose error message format is unusual.
+
+
+File: emacs, Node: New Commands, Next: Search Changes, Prev: M-x Changes, Up: Version 19
+
+New Everyday Commands
+=====================
+
+`C-z'
+ When you are using X windows, `C-z' (`iconify-frame') now
+ iconifies the current frame.
+
+`C-M-l'
+ The `C-M-l' command (`reposition-window') scrolls the current
+ window heuristically in a way designed to get useful information
+ onto the screen. For example, in a Lisp file, this command tries
+ to get the entire current defun onto the screen if possible.
+
+`C-M-r'
+ The `C-M-r' key now runs the command `isearch-backward-regexp',
+ which does reverse incremental regexp search.
+
+`C-x 5'
+ The prefix key `C-x 5' is analogous to `C-x 4', with parallel
+ subcommands. The difference is that `C-x 5' commands create a new
+ frame rather than just a new window.
+
+`C-x 5 C-f'
+`C-x 5 b'
+ These new commands switch to a specified file or buffer in a new
+ frame (when using X windows). The commands' names are
+ `find-file-other-frame' and `switch-to-buffer-other-frame'.
+
+`C-x 5 m'
+ Start outgoing mail in another frame (`mail-other-frame').
+
+`C-x 5 .'
+ Find a tag in another frame (`find-tag-other-frame').
+
+`C-x 4 r'
+ This is now `find-file-read-only-other-window'.
+
+arrow keys
+ The arrow keys now have default bindings to move in the appropriate
+ directions.
+
+`C-h C-f'
+`C-h C-k'
+ These new help commands enter Info and display the node for a given
+ Emacs function name or key sequence, respectively.
+
+`M-a'
+`M-e'
+ In C mode, `M-a' and `M-e' now move by complete C statements
+ (`c-beginning-of-statement' and `c-end-of-statement').
+
+`M-q'
+ `M-q' in C mode now runs `c-fill-paragraph', which is designed for
+ filling C comments. (We assume you don't want to fill the actual C
+ code in a C program.)
+
+`M-x c-up-conditional'
+ In C mode, `c-up-conditional' moves back to the containing
+ preprocessor conditional, setting the mark where point was
+ previously.
+
+ A prefix argument acts as a repeat count. With a negative
+ argument, this command moves forward to the end of the containing
+ preprocessor conditional. When going backwards, `#elif' acts like
+ `#else' followed by `#if'. When going forwards, `#elif' is
+ ignored.
+
+`M-x comment-region'
+ The `comment-region' command adds comment delimiters to the lines
+ that start in the region, thus commenting them out. With a
+ negative argument, it deletes comment delimiters from the lines in
+ the region--this is the inverse of the effect of `comment-region'
+ without an argument.
+
+ With a positive argument, `comment-region' adds comment delimiters
+ but duplicates the last character of the comment start sequence as
+ many times as the argument specifies. This is a way of calling
+ attention to the comment. In Lisp, you should use an argument of
+ at least two, because the indentation convention for single
+ semicolon comments does not leave them at the beginning of a line.
+
+`M-x super-apropos'
+ This command is like `apropos' except that it searches for a
+ regular expression instead of merely a substring.
+
+ If you use a prefix argument (regardless of its value) with
+ `apropos' or `super-apropos', they also search documentation
+ strings for matches as well as symbol names. The prefix argument
+ also controls looking up and printing the key bindings of all
+ commands.
+
+`M-x diff'
+ This new command compares two files, displaying the differences in
+ an Emacs buffer. The options for the `diff' program come from the
+ variable `diff-switches', whose value should be a string.
+
+ The buffer of differences has Compilation mode as its major mode,
+ so you can use `C-x `' to visit successive changed locations in
+ the two source files, or you can move to a particular hunk of
+ changes and type `C-c C-c' to move to the corresponding source.
+ You can also use the other special commands of Compilation mode:
+ SPC and DEL for scrolling, and `M-p' and `M-n' for cursor motion.
+
+`M-x diff-backup'
+ The command `diff-backup' compares a specified file with its most
+ recent backup. If you specify the name of a backup file,
+ `diff-backup' compares it with the source file that it is a backup
+ of.
+
+
+File: emacs, Node: Search Changes, Next: Filling Changes, Prev: New Commands, Up: Version 19
+
+Changes in Incremental Search
+=============================
+
+ The most important change in incremental search is that RET now
+terminates a search, and ESC does not. The other changes are useful,
+but not vital to know about.
+
+ * The character to terminate an incremental search is now RET. This
+ is for compatibility with the way most other arguments are read.
+
+ To search for a newline in an incremental search, type LFD (also
+ known as `C-j').
+
+ (This change is somewhat of an experiment; it might be taken back
+ by the time Emacs 19 is really released.)
+
+ * Incremental search now maintains a ring of previous search
+ strings. Use `M-p' and `M-n' to move through the ring to pick a
+ search string to reuse. These commands leave the selected search
+ ring element in the minibuffer, where you can edit it. Type RET
+ to finish editing and search for the chosen string.
+
+ * When there is an upper-case letter in the search string, then the
+ search is case sensitive.
+
+ * Incremental search is now implemented as a major mode. When you
+ type `C-s', it switches temporarily to a different keymap which
+ defines each key to do what it ought to do for incremental search.
+ This has next to no effect on the user-visible behavior of
+ searching, but makes it easier to customize that behavior.
+
+
+File: emacs, Node: Filling Changes, Next: TeX Mode Changes, Prev: Search Changes, Up: Version 19
+
+Changes in Fill Commands
+========================
+
+ * `fill-individual-paragraphs' now has two modes. Its default mode
+ is that any change in indentation starts a new paragraph. The
+ alternate mode is that only separator lines separate paragraphs;
+ this can handle paragraphs with extra indentation on the first
+ line. To select the alternate mode, set
+ `fill-individual-varying-indent' to a non-`nil' value.
+
+ * Filling is now partially controlled by a new minor mode, Adaptive
+ Fill mode. When this mode is enabled (and it is enabled by
+ default), if you use `fill-region-as-paragraph' on an indented
+ paragraph and you don't have a fill prefix, it uses the
+ indentation of the second line of the paragraph as the fill prefix.
+
+ Adaptive Fill mode doesn't have much effect on `M-q' in most major
+ modes, because an indented line will probably count as a paragraph
+ starter and thus each line of an indented paragraph will be
+ considered a paragraph of its own.
+
+ * `M-q' in C mode now runs `c-fill-paragraph', which is designed for
+ filling C comments. (We assume you don't want to fill the actual C
+ code in a C program.)
+
+ \ No newline at end of file
diff --git a/info/emacs-13 b/info/emacs-13
new file mode 100644
index 00000000000..6aab0c053c6
--- /dev/null
+++ b/info/emacs-13
@@ -0,0 +1,1330 @@
+This is Info file ../info/emacs, produced by Makeinfo-1.49 from the
+input file emacs.texi.
+
+ This file documents the GNU Emacs editor.
+
+ Copyright (C) 1985, 1986, 1988, 1992 Richard M. Stallman.
+
+ Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+ Permission is granted to copy and distribute modified versions of
+this manual under the conditions for verbatim copying, provided also
+that the sections entitled "The GNU Manifesto", "Distribution" and "GNU
+General Public License" are included exactly as in the original, and
+provided that the entire resulting derived work is distributed under the
+terms of a permission notice identical to this one.
+
+ Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that the sections entitled "The GNU Manifesto",
+"Distribution" and "GNU General Public License" may be included in a
+translation approved by the author instead of in the original English.
+
+
+File: emacs, Node: TeX Mode Changes, Next: Shell Changes, Prev: Filling Changes, Up: Version 19
+
+Changes in TeX Mode
+===================
+
+ The old TeX mode bindings of `M-{' and `M-}' have been moved to `C-c
+{' and `C-c }'. (These commands are `up-list' and `tex-insert-braces';
+they are the TeX equivalents of `M-(' and `M-)'.)
+
+ The new command `C-c C-o' (`tex-latex-block') inserts a matching
+`\begin'--`\end' pair. The new command `C-c C-e'
+(`tex-close-latex-block') inserts a matching `\end' for the last
+unterminated `\begin'.
+
+ You can run BibTeX on the current file using `C-c TAB'
+(`tex-bibtex-file').
+
+ There is a new command `C-c C-v' (`tex-view') for running a DVI
+previewer.
+
+ You can specify the directory to use for running TeX by setting the
+variable `tex-directory'. `"."' is the default value. If your
+environment variable `TEXINPUTS' contains relative directory names, or
+if your files contains `\input' commands with relative file names, then
+`tex-directory' *must* be `"."' or you will get the wrong results.
+Otherwise, it is safe to specify some other directory, such as `/tmp'.
+
+ There is now a third variant of TeX mode, for SliTeX. This is in
+addition to the variants for plain TeX and LaTeX. As before, the
+correct variant is chosen automatically when you visit a file.
+
+
+File: emacs, Node: Shell Changes, Next: Spell Changes, Prev: TeX Mode Changes, Up: Version 19
+
+Changes in Shell Mode
+=====================
+
+ Shell mode has been completely replaced with a new implementation.
+The basic idea is the same: Emacs runs a subshell, and all input and
+output to the subshell go through the shell buffer. But the special
+commands of Shell mode have been redesigned.
+
+`TAB'
+ Complete the file name before point in the shell buffer
+ (`comint-dynamic-complete').
+
+`M-?'
+ To get a list of all possible completions of the file name before,
+ type `M-?' (`comint-dynamic-list-completions').
+
+`M-p'
+`M-n'
+ There is a new convenient history mechanism for repeating previous
+ shell inputs. Use the command `M-p' (`comint-previous-input') to
+ recall the last input; it copies the text of that input to the
+ place where you are editing. If you repeat `M-p', it replaces the
+ copied input with successively earlier inputs. `M-n' is similar
+ but goes in the opposite direction, towards the present
+ (`comint-next-input').
+
+ When you find the previous input you want, you can resubmit it by
+ typing RET, or you can edit it first and then resubmit it if you
+ wish.
+
+ These shell history commands operate outside the minibuffer, but
+ they are completely analogous to the minibuffer history commands.
+
+`M-r'
+`M-s'
+ You can also use `M-r' and `M-s' to search for (respectively)
+ earlier or later inputs starting with a given string. First type
+ the string, then type `M-r' (`comint-previous-matching-input') to
+ yank a previous input from the history which starts with that
+ string. You can repeat `M-r' to find successively earlier inputs
+ starting with the same string.
+
+ You can start moving in the opposite direction (toward more recent
+ inputs) by typing `M-s' (`comint-next-matching-input') instead of
+ `M-r'. As long as you don't use any commands except `M-r' and
+ `M-s', they keep using the same string that you had entered
+ initially.
+
+ These commands serve a purpose similar to that of `M-r' and `M-s'
+ in the minibuffer, but do not work in quite the same way. We may
+ change the interface of these commands, as well as that of the
+ analogous minibuffer commands; one goal will be to make the two
+ sets of commands compatible. But we haven't yet figured out which
+ of the possible interfaces is best. To find out what interface is
+ actually supported in Emacs 19, type `C-h f
+ comint-previous-matching-input RET'.
+
+`C-c C-o'
+ Kill the last batch of output from a shell command
+ (`comint-kill-output'). This is useful if a shell command spews
+ out lots of output that just gets in the way.
+
+`C-c C-r'
+ Scroll to display the beginning of the last batch of output at the
+ top of the window; it also moves the cursor there
+ (`comint-show-output').
+
+`C-a'
+ If you type `C-a' on a line that starts with a shell prompt, it
+ moves to the end of the prompt, not to the very beginning of the
+ line.
+
+`C-d'
+ Typed at the end of the shell buffer, `C-d' sends EOF to the
+ subshell. Typed at any other position in the buffer, `C-d'
+ deletes a character as usual.
+
+`M-x dirs'
+ If Emacs gets confused while trying to track changes in the shell's
+ current directory, type `M-x dirs' to re-synchronize.
+
+`M-x send-invisible'
+ This command reads a line of text without echoing it, and sends it
+ to the shell.
+
+`M-x comint-continue-subjob'
+ If you accidentally suspend your process, use this command to
+ continue it.
+
+
+File: emacs, Node: Spell Changes, Next: Tags Changes, Prev: Shell Changes, Up: Version 19
+
+Changes in Spell Checking
+=========================
+
+ Emacs 19 uses the Ispell program for spelling correction instead of
+the Unix spell program. Ispell has many advantages; one is that it can
+be started the first time you check a word, and left running thereafter,
+which makes further checking much faster. If you want to get rid of the
+Ispell process, use `M-x kill-ispell'.
+
+ To check the entire current buffer, use `M-x ispell-buffer'. Use
+`M-x ispell-region' to check just the current region.
+
+ Ispell commands often involve interactive replacement of words. You
+can interrupt the interactive replacement with `C-g'. You can restart
+it again afterward with `C-u M-$'.
+
+ Interactive replacement shows you one misspelling at a time and asks
+you what to do. To answer, type one of the following characters:
+
+`DIGIT'
+ Replace the word (this time) with one of the displayed near-misses.
+ The digit you use says which near-miss to use.
+
+`a'
+ Accept this word this time.
+
+`i'
+ Insert this word in your private dictionary so that Ispell will
+ consider it correct it from now on.
+
+`r'
+ Replace the word this time with a string typed by you.
+
+ When the Ispell process starts, it reads your private dictionary
+which is the file `~/ispell.words'. Words that you "insert" with the
+`i' command are added to that file, but not right away--only at the end
+of the interactive replacement procedure.
+
+ Use the `M-x reload-ispell' command to reload your private
+dictionary from `~/ispell.words' if you edit the file outside of Ispell.
+
+
+File: emacs, Node: Mail Changes, Next: Info Changes, Prev: Tags Changes, Up: Version 19
+
+Changes in Mail Reading and Sending
+===================================
+
+ `%' is now a word-separator character in Mail mode. This is because
+that character frequently appears in addresses.
+
+ If you set the variable `mail-signature' non-`nil', then `mail'
+inserts the contents of your `.signature' file automatically when it
+initializes a mail buffer. If you don't want your signature in a
+particular message, just delete it from the buffer before you send the
+message.
+
+ You can specify the text to insert at the beginning of each line when
+you use `C-c C-y' to yank the message you are replying to. Set
+`mail-yank-prefix' to the desired string. A value of `nil' (the
+default) means to use indentation, as in Emacs 18. If you use `C-u' by
+itself as the prefix argument to `C-c C-y', then it does not insert
+anything at the beginning of the lines, regardless of the value of
+`mail-yank-prefix'.
+
+ You can easily convert an Rmail file to system mailbox format with
+the command `unrmail'. This command reads two arguments, the name of
+the Rmail file to convert, and the name of the new mailbox file. The
+Rmail file is unchanged by this command.
+
+ Rmail now initially positions you at the first message in the Rmail
+file that you have not seen. This may not be a message that just
+arrived; it may have arrived in a previous session during which you did
+not select it. You can then read all the unseen messages going
+forwards.
+
+ When a message that you sent "bounces" back to you, you can retry
+sending it by typing `C-M-m' (`rmail-retry-failure') on the failure
+message.
+
+ By contrast, the new command `M-x rmail-resend' is used for
+forwarding a message and marking it as "resentby" you, with the special
+header fields `Resent-by:' and `Resent-to:'.
+
+ Another new Rmail command is `<', which moves to the first message.
+(This is for symmetry with `>'.) `<' is actually an alias for `j'.
+
+ `e' (`rmail-edit-current-message') is now the command to edit a
+message. To expunge, type `x'. We know this will surprise people some
+of the time, but the surprise will not be disastrous--if you type `e'
+meaning to expunge, just type `C-c C-c' to leave Rmail Edit mode, and
+then type `x'.
+
+ The variable `rmail-output-file-alist' now controls the default for
+the file to output a message to.
+
+ In the Rmail summary, `C-n' and `C-p' are now ordinary cursor motion
+commands. To move in the summary *and* select a new message, use `n'
+and `p' (which skip deleted messages) or `M-n' and `M-p' (which stop at
+all messages). These are, of course, the same commands you would use
+in the Rmail buffer.
+
+
+File: emacs, Node: Tags Changes, Next: Mail Changes, Prev: Spell Changes, Up: Version 19
+
+Changes in Tags Commands
+========================
+
+ `M-.' (`find-tag') and the other commands to find a tag now look
+first for an exact match in the tags table, and try substring matches
+only afterward.
+
+ Another change in `M-.' is that it has no effect on what `M-,' will
+do subsequently. You can no longer use `M-,' to find the next similar
+tag; instead, use `M-.' with a prefix argument.
+
+ The new command `find-tag-regexp' successively visits the tags that
+match a specified regular expression.
+
+ You can now use more than one tags table. Using `visit-tags-table'
+to load a new tags table does not discard the other tables previously
+loaded. The other tags commands use all the tags tables that are
+loaded; the first one they use is the one that mentions the current
+visited file.
+
+ You can specify a precise list of tags tables by setting the variable
+`tags-table-list' to a list of strings, like this:
+
+ (setq tags-table-list
+ '("~/emacs" "/usr/local/lib/emacs/src"))
+
+This tells `find-tag' to look at the `TAGS' files in your `~/emacs'
+directory and in the `/usr/local/lib/emacs/src' directory. The order
+depends on which file you are in and which tags table mentions that
+file, as explained above.
+
+ You can now use the tags table for completion of names during
+ordinary editing. The command `M-TAB' (except in Emacs Lisp and Lisp
+Interaction modes) completes the identifier in the buffer before point,
+using the set of all tags as the list of possible completions.
+
+ `tags-query-replace' and `tags-search' now create buffers only
+temporarily for the files that they have to search (those which are not
+already visited in Emacs buffers). If one of these files contains a
+match for the search pattern, then its buffer continues to exist;
+otherwise, it is killed.
+
+
+File: emacs, Node: Info Changes, Next: Dired Changes, Prev: Mail Changes, Up: Version 19
+
+Changes in Info
+===============
+
+ There are new commands in Info mode.
+
+`]'
+ Move forward a node, going up and down levels as needed in a
+ depth-first tree walk. This command treats all the nodes in the
+ file as forming a single sequence in which the "children" of a
+ node follow that node. It is the equivalent of reading a printed
+ manual sequentially.
+
+`['
+ Similar, but move backward.
+
+`<'
+ Move to the top node of the current Info file.
+
+`>'
+ Move to the last node of the file.
+
+`SPC'
+ Scroll through this node, or advance to the next node in
+ depth-first order (like `]').
+
+`i STRING RET'
+ Move to the node associated with STRING in the index or indices of
+ this manual. If there is more than one match for STRING, the `i'
+ command finds the first match.
+
+`,'
+ Find the next match for the string in the previous `i' command, and
+ go to that node.
+
+ If you click the middle mouse button near a cross-reference, menu
+item or node pointer while in Info, you will go to the node which is
+referenced.
+
+ The variable `Info-directory-list' specifies a list of directory
+names that contain Info files. Each time Info looks for an Info file,
+it searches all these directories. This makes it easy to install the
+Info files that come with various packages. You can specify the path
+with the environment variable `INFOPATH'.
+
+
+File: emacs, Node: Dired Changes, Next: GNUS, Prev: Info Changes, Up: Version 19
+
+Changes in Dired
+================
+
+ Dired has many new features which allow you to do these things:
+
+ * Make distinguishable types of marks for different operations.
+
+ * Rename, copy, or make links to many files at once.
+
+ * Display contents of subdirectories in the same Dired buffer as the
+ parent directory.
+
+* Menu:
+
+* Marks in Dired:: Flagging for deletion vs marking for other actions.
+* Multiple Files:: How to copy, rename, print, compress, etc.
+ either one file or several files.
+* Shell Commands in Dired:: Running a shell command on the marked files.
+* Dired Regexps:: Using patterns to rename multiple files.
+* Dired Case Conversion:: Converting file names to upper or lower case.
+* Comparison in Dired:: Running `diff' by way of Dired.
+* Subdirectories in Dired:: Adding subdirectories to the Dired buffer.
+* Hiding Subdirectories:: Making subdirectories visible or invisible.
+* Editing Dired Buffer:: Discarding lines for files of no interest.
+* Dired and Find:: Using `find' to select the files for Dired to show.
+
+
+File: emacs, Node: Marks in Dired, Next: Multiple Files, Up: Dired Changes
+
+Setting and Clearing Marks
+--------------------------
+
+ There are now two kinds of marker that you can put on a file in
+Dired: `D' for deletion, and `*' for any other kind of operation. The
+`x' command deletes only files marked with `D', and most other Dired
+commands operate only on the files marked with `*'.
+
+ To mark files with `D' (also called "flagging" the files), you can
+use `d' as usual. Here are some commands for marking with `*' (and
+also for unmarking):
+
+`m'
+ Mark the current file with `*', for an operation other than
+ deletion (`dired-mark').
+
+`*'
+ Mark all executable files (`dired-mark-executables'). With a
+ prefix argument, unmark all those files.
+
+`@'
+ Mark all symbolic links (`dired-mark-symlinks'). With a prefix
+ argument, unmark all those files.
+
+`/'
+ Mark all files which are actually directories, except for `.' and
+ `..' (`dired-mark-directories'). With a prefix argument, unmark
+ all those files.
+
+`M-DEL'
+ Remove a specific or all marks from every file
+ (`dired-unmark-all-files'). With an argument, query for each
+ marked file. Type your help character, usually `C-h', at that time
+ for help.
+
+`c OLD NEW'
+ Replace all marks that use the character OLD with marks that use
+ the character NEW. You can use almost any character as a mark
+ character by means of this command, to distinguish various classes
+ of files. If OLD is ` ', then the command operates on all
+ unmarked files; if NEW is ` ', then the command unmarks the files
+ it acts on.
+
+ To illustrate the power of this command, here is how to put `*'
+ marks on all the files that were unmarked, while unmarking all
+ those that had `*' marks:
+
+ c * t c SPC * c t SPC
+
+
+File: emacs, Node: Multiple Files, Next: Shell Commands in Dired, Prev: Marks in Dired, Up: Dired Changes
+
+Operating on Multiple Files
+---------------------------
+
+ The Dired commands to operate on files (rename them, copy them, and
+so on) have been generalized to work on multiple files. There are also
+some additional commands in this series.
+
+ All of these commands use the same convention to decide which files
+to manipulate:
+
+ * If you give the command a numeric prefix argument N, it operates
+ on the next N files, starting with the current file.
+
+ * Otherwise, if there are marked files, the commands operate on all
+ the marked files.
+
+ * Otherwise, the command operates on the current file only.
+
+ Here are the commands that operate on multiple files in this way:
+
+`C'
+ Copy the specified files (`dired-do-copy'). You must specify a
+ directory to copy into, or (if copying a single file) a new name.
+
+ If `dired-copy-preserve-time' is non-`nil', then copying with this
+ command sets the modification time of the new file to be the same
+ as that of the old file.
+
+`R'
+ Rename the specified files (`dired-do-rename'). You must specify
+ a directory to rename into, or (if renaming a single file) a new
+ name.
+
+ Dired automatically changes the visited file name of buffers
+ associated with renamed files so that they refer to the new names.
+
+`H'
+ Make hard links to the specified files (`dired-do-hardlink'). You
+ must specify a directory to make the links in, or (if making just
+ one link) the name to give the link.
+
+`S'
+ Make symbolic links to the specified files (`dired-do-symlink').
+ You must specify a directory to make the links in, or (if making
+ just one link) the name to give the link.
+
+`M'
+ Change the mode (also called "permission bits") of the specified
+ files (`dired-do-chmod'). This calls the `chmod' program, so you
+ can describe the desired mode change with any argument that
+ `chmod' would handle.
+
+`G'
+ Change the group of the specified files (`dired-do-chgrp').
+
+`O'
+ Change the owner of the specified files (`dired-do-chown'). (On
+ most systems, only the superuser can do this.)
+
+ The variable `dired-chown-program' specifies the name of the
+ program to use to do the work (different systems put `chown' in
+ different places.
+
+`Z'
+ Compress or uncompress the specified files. If the file appears to
+ be a compressed file, it is uncompressed; otherwise, it is
+ compressed (`dired-do-compress').
+
+`L'
+ Load the specified Emacs Lisp files (`dired-do-load').
+
+`B'
+ Byte compile the specified Emacs Lisp files
+ (`dired-do-byte-compile').
+
+`P'
+ Print the specified files (`dired-do-print'). This command uses
+ the variables `lpr-command' and `lpr-switches' just as `lpr-file'
+ does (*note Hardcopy::.).
+
+
+File: emacs, Node: Shell Commands in Dired, Next: Dired Regexps, Prev: Multiple Files, Up: Dired Changes
+
+Shell Commands in Dired
+-----------------------
+
+ The dired command `!' (`dired-do-shell-command') reads a shell
+command string in the minibuffer and runs the shell command on all the
+specified files. There are two ways of applying a shell command to
+multiple files:
+
+ * If you use `*' in the shell command, then it runs just once, with
+ the list of file names substituted for the `*'.
+
+ Thus, `! tar cf foo.tar * RET' runs `tar' on the entire list of
+ file names, putting them into one tar file `foo.tar'. The file
+ names are inserted in the order that they appear in the Dired
+ buffer.
+
+ * If the command string doesn't contain `*', then it runs once *for
+ each file*, with the file name attached at the end.
+
+ For example, `! uudecode RET' runs `uudecode' on each file.
+
+ What if you want to run the shell command once for each file but with
+the file name inserted in the middle? Or if you want to use the file
+names in a more complicated fashion? Use a shell loop. For example,
+this shell command would run `uuencode' on each of the specified files,
+writing the output into a corresponding `.uu' file:
+
+ for file in *; uuencode $file $file >$file.uu; done
+
+ The working directory for the shell command is the top level
+directory of the Dired buffer.
+
+ The `!' command does not attempt to update the Dired buffer to show
+new or modified files, because it doesn't know what those files might
+be. Type `g' to update the Dired buffer.
+
+
+File: emacs, Node: Dired Regexps, Next: Dired Case Conversion, Prev: Shell Commands in Dired, Up: Dired Changes
+
+Regular Expression File Name Substitution
+-----------------------------------------
+
+ Here are commands that select files according to a regular
+expression:
+
+`% m REGEXP RET'
+ Mark all files whose names match the regular expression REGEXP
+ (`dired-mark-files-regexp').
+
+ Only the non-directory part of the file name is used in matching.
+ Use `^' and `$' to anchor matches. Exclude subdirs by hiding them
+ (*note Hiding Subdirectories::.).
+
+`% d REGEXP RET'
+ Flag for deletion all files whose names match the regular
+ expression REGEXP (`dired-flag-files-regexp').
+
+`% R FROM RET TO RET'
+`% C FROM RET TO RET'
+`% H FROM RET TO RET'
+`% S FROM RET TO RET'
+ These four commands rename, copy, make hard links and make soft
+ links, in each case computing the new name by regular expression
+ substitution from the name of the old file.
+
+ The four regular expression substitution commands effectively perform
+`query-replace-regexp' on the selected file names in the Dired buffer.
+They read two arguments: a regular expression FROM, and a substitution
+pattern TO. Each selected file name is matched against the regular
+expression, and then the part which matched is replaced with the
+substitution pattern. You can use `\&' and `\DIGIT' in the
+substitution pattern to refer to all or part of the old file name.
+
+ Thus, `% R ^.*$ RET x-\& RET' renames each selected file by
+prepending `x-' to its name. The inverse of this is to remove `x-'
+from the front of each file name. One way to do that is `% R ^x-.*$
+RET \& RET'; another is `% R ^x- RET RET'. (Use `^' and `$' to anchor
+matches that should span the whole filename.)
+
+ If the regular expression matches more than once in a file name,
+only the first match is replaced.
+
+ Normally, the replacement process does not consider the directory
+names; it operates on the file name within the directory. If you
+specify a prefix argument of zero, then replacement affects the entire
+file name.
+
+ Often you will want to apply the command to all files matching the
+same REGEXP that you use in the command. To do this, mark those files
+with `% m REGEXP RET', then use the same regular expression in `% R'.
+To make this easier, `% R' uses the last regular expression specified
+in a `%' command as a default.
+
+
+File: emacs, Node: Dired Case Conversion, Next: Comparison in Dired, Prev: Dired Regexps, Up: Dired Changes
+
+Dired Case Conversion
+---------------------
+
+ Here are commands for changing the case of selected files:
+
+`% u'
+ Rename each of the selected files to an upper case name
+ (`dired-upcase').
+
+`% l'
+ Rename each of the selected files to a lower case name
+ (`dired-downcase').
+
+
+File: emacs, Node: Comparison in Dired, Next: Subdirectories in Dired, Prev: Dired Case Conversion, Up: Dired Changes
+
+File Comparison with Dired
+--------------------------
+
+ Here are two commands to run `diff' on selected files:
+
+`='
+ Compare the current file with another file (the file at the mark),
+ by running the `diff' program (`dired-diff'). The file at the
+ mark is the first argument of `diff', and the file at point is the
+ second argument.
+
+`M-='
+ Compare the current file with its backup file
+ (`dired-backup-diff'). If there are several numerical backups, use
+ the most recent one. If this file is a backup, compare it to its
+ original. The backup file is the first file given to `diff'.
+
+
+File: emacs, Node: Subdirectories in Dired, Next: Hiding Subdirectories, Prev: Comparison in Dired, Up: Dired Changes
+
+Subdirectories in Dired
+-----------------------
+
+ One Dired buffer can now display more than one directory.
+
+ The simplest way to include multiple directories is to specify the
+options `-lR' for running `ls'. That produces a recursive directory
+listing showing all subdirectories, all within the same Dired buffer.
+
+ But the simplest way is not usually the most convenient way--usually
+the complete recursive listing is more than you want. So there is a
+Dired command to insert a single subdirectory into the Dired buffer:
+
+`i'
+ Use the `i' (`dired-maybe-insert-subdir') command on a line that
+ describes a file which is a directory. It inserts the contents of
+ that directory into the same Dired buffer. Inserted subdirectory
+ contents follow the top-level directory of the Dired buffer, just
+ as they do in `ls -lR' output.
+
+ If the subdirectory's contents are already present in the buffer,
+ the `i' command just moves to it (type `l' (`dired-do-redisplay')
+ to refresh it). It sets the Emacs mark before moving, so `C-x
+ C-x' takes you back to the old position in the buffer.
+
+ When you have subdirectories in the Dired buffer, you can use the
+page motion commands `C-x [' and `C-x ]' to move by entire directories.
+
+ The following commands move up and down in the tree of directories
+in one Dired buffer:
+
+`C-M-u'
+ Go up to the parent directory's headerline (`dired-tree-up').
+
+`C-M-d'
+ Go down in the tree, to the first subdirectory's headerline
+ (`dired-tree-down').
+
+ The following commands move forwards and backwards to subdirectory
+headerlines:
+
+`C-M-n'
+ Go to next subdirectory headerline, regardless of level
+ (`dired-next-subdir').
+
+`C-M-p'
+ Go to previous subdirectory headerline, regardless of level
+ (`dired-prev-subdir').
+
+
+File: emacs, Node: Hiding Subdirectories, Next: Editing Dired Buffer, Prev: Subdirectories in Dired, Up: Dired Changes
+
+Hiding Subdirectories
+---------------------
+
+ "Hiding" a subdirectory means to make it invisible, except for its
+headerline. Files inside a hidden subdirectory are never considered by
+Dired. For example, the commands to operate on marked files ignore
+files in hidden directories even if they are marked. Thus you can use
+hiding to temporarily exclude subdirectories from operations without
+having to remove the markers.
+
+ The hiding commands toggle; that is they unhide what was hidden and
+vice versa.
+
+`$'
+ Hide or reveal the current subdirectory and move point to the next
+ subdirectory (`dired-hide-subdir'). A prefix argument serves as a
+ repeat count.
+
+`M-$'
+ Hide all subdirectories, leaving only their header lines
+ (`dired-hide-all'). Or, if any subdirectory is currently hidden,
+ make all subdirectories visible again. You can use this command
+ to get an overview in very deep directory trees or to move quickly
+ to subdirectories far away.
+
+
+File: emacs, Node: Editing Dired Buffer, Next: Dired and Find, Prev: Hiding Subdirectories, Up: Dired Changes
+
+Editing the Dired Buffer
+------------------------
+
+`l'
+ Update the specified files in a Dired buffer. This means reading
+ their current status from the file system and changing the buffer
+ to reflect it properly (`dired-do-redisplay').
+
+ If you use this command on a subdirectory header line, it updates
+ the contents of the subdirectory.
+
+`g'
+ Update the entire contents of the Dired buffer (`revert-buffer').
+ Preserve all marks except for those on files that have vanished.
+ Hidden subdirectories are updated but remain hidden.
+
+`k'
+ Kill all marked lines (`dired-do-kill-lines'). With a prefix
+ argument, kill that many lines starting with the current line.
+
+ This command does not delete files; it just deletes text from the
+ Dired buffer.
+
+ If you kill the line for a file that is a directory, then its
+ contents are also deleted from the buffer. Typing `C-u k' on the
+ header line for a subdirectory is another way to delete a
+ subdirectory from the Dired buffer.
+
+ The `g' command will bring back any individual lines that you have
+ killed in this way, but not subdirectories--you must use `i' to
+ reinsert each subdirectory.
+
+
+File: emacs, Node: Dired and Find, Prev: Editing Dired Buffer, Up: Dired Changes
+
+Dired and `find'
+----------------
+
+ You can select a set of files for display in a Dired buffer more
+flexibly by using the `find' utility to choose the files.
+
+ To search for files with names matching a wildcard pattern use
+`find-name-dired'. Its arguments are DIRECTORY and PATTERN. It
+selects all the files in DIRECTORY or its subdirectories whose own
+names match PATTERN.
+
+ The files thus selected are displayed in a Dired buffer in which the
+ordinary Dired commands are available.
+
+ If you want to test the contents of files, rather than their names,
+use `find-grep-dired'. This command takes two minibuffer arguments,
+DIRECTORY and REGEXP; it selects all the files in DIRECTORY or its
+subdirectories that contain a match for REGEXP. It works by running
+`find' and `grep'.
+
+ The most general command in this series is `find-dired', which lets
+you specify any condition that `find' can test. It takes two
+minibuffer arguments, DIRECTORY and FIND-ARGS; it runs `find' in
+DIRECTORY with FIND-ARGS as the arguments to `find' that specify which
+files to accept. To use this command, you need to know how to use
+`find'.
+
+
+File: emacs, Node: GNUS, Next: Calendar/Diary, Prev: Dired Changes, Up: Version 19
+
+GNUS
+====
+
+ GNUS is an Emacs subsystem for reading and responding to netnews.
+You can use GNUS to browse through news groups, look at summaries of
+articles in specific group, and read articles of interest. You can
+respond to authors or write replies to all the readers of a news group.
+
+ This document introduces GNUS and describes several basic features.
+Full documentation will appear in `The GNU Emacs Extensions Manual'.
+
+ To start GNUS, type `M-x gnus RET'.
+
+* Menu:
+
+* Buffers of GNUS:: The Newsgroups, Summary and Article buffers.
+* GNUS Startup:: What you should know about starting GNUS.
+* Summary of GNUS:: A short description of the basic GNUS commands.
+
+
+File: emacs, Node: Buffers of GNUS, Next: GNUS Startup, Up: GNUS
+
+GNUS's Three Buffers
+--------------------
+
+ GNUS creates and uses three Emacs buffers, each with its own
+particular purpose and its own major mode.
+
+ The "Newsgroup buffer" contains a list of newsgroups. This is the
+first buffer that GNUS displays when it starts up. Normally the list
+contains only the newsgroups to which you subscribe (which are listed in
+your `.newsrc' file) and which contain unread articles. Use this
+buffer to select a specific newsgroup.
+
+ The "Summary buffer" lists the articles in a single newsgroup,
+including their subjects, their numbers, and who posted them. GNUS
+creates a Summary buffer for a newsgroup when you select the group in
+the Newsgroup buffer. Use this buffer to select an article, and to move
+around in an article.
+
+ The "Article buffer" displays the text of an article. You rarely
+need to select this buffer because you can read the text while keeping
+the Summary buffer selected.
+
+
+File: emacs, Node: GNUS Startup, Next: Summary of GNUS, Prev: Buffers of GNUS, Up: GNUS
+
+When GNUS Starts Up
+-------------------
+
+ At startup, GNUS reads your `.newsrc' news initialization file and
+attempts to communicate with the local news server, which is a
+repository of news articles. The news server need not be the same
+computer you are logged in on.
+
+ If you start GNUS and connect to the server, but do not see any
+newsgroups listed in the Newsgroup buffer, type `L' to get a listing of
+all the newsgroups. Then type `u' to unsubscribe from particular
+newsgroups. (Move the cursor using `n' and `p' or the usual Emacs
+commands.) When you quit with `q', GNUS automatically records the
+subscribed groups in your `.newsrc' initialization file. (You do not
+have to edit this file yourself, although you may.) Next time you start
+GNUS, you will see only the subscribed groups.
+
+
+File: emacs, Node: Summary of GNUS, Prev: GNUS Startup, Up: GNUS
+
+Summary of GNUS Commands
+------------------------
+
+ Reading news is a two step process:
+
+ 1. Choose a newsgroup in the Newsgroup buffer.
+
+ 2. Choose an article in the Summary buffer. The article is displayed
+ in the Article buffer in a large window, below the Summary buffer
+ in its small window.
+
+ Each buffer has commands particular to it, but commands that do the
+same things have similar keybindings. Here are commands for the
+Newsgroup and Summary buffers:
+
+`z'
+ In the Newsgroup buffer, suspend GNUS. You can return to GNUS
+ later by selecting the Newsgroup buffer and typing `g' to get
+ newly arrived articles.
+
+`q'
+ In the Newsgroup buffer, update your `.newsrc' initialization file
+ and quit GNUS.
+
+ In the Summary buffer, exit the current newsgroup and return to the
+ Newsgroup buffer. Thus, typing `q' twice quits GNUS.
+
+`L'
+ In the Newsgroup buffer, list all the newsgroups available on your
+ news server. This may be a long list!
+
+`l'
+ In the Newsgroup buffer, list only the newsgroups to which you
+ subscribe and which contain unread articles.
+
+`u'
+ In the Newsgroup buffer, unsubscribe from (or subscribe to) the
+ newsgroup listed in the line that point is on. When you quit GNUS
+ by typing `q', GNUS lists your subscribed-to newsgroups in your
+ `.newsrc' file. The next time you start GNUS, you see only the
+ newsgroups listed in your `.newsrc' file.
+
+ You may also edit your `.newsrc' file directly in Emacs. First
+ quit GNUS, then visit the `.newsrc' file. For example, you can
+ remove all the `alt.' groups by going to the beginning of the file
+ and typing `M-x flush-lines RET alt RET'. Next time you start
+ GNUS, you will see only the newsgroups still listed in the
+ `.newsrc' file.
+
+`SPC'
+ In the Newsgroup buffer, select the group on the line under the
+ cursor and display the first unread article in that group.
+
+ In the Summary buffer,
+
+ - Select the article on the line under the cursor if none is
+ selected.
+
+ - Scroll the text of the article if one is selected.
+
+ - Select the next unread article if at the end of the current
+ article.
+
+ Thus, you can move through all the articles by repeatedly typing
+ SPC.
+
+`DEL'
+ In the Newsgroup Buffer, move point to the previous newsgroup
+ containing unread articles.
+
+ In the Summary buffer, scroll the text of the article backwards.
+
+`n'
+ Move point to the next unread newsgroup, or select the next unread
+ article.
+
+`p'
+ Move point to the previous unread newsgroup, or select the previous
+ unread article.
+
+`C-n'
+`C-p'
+ Move point to the next or previous item, even if it is marked as
+ read. This does not select the article or newsgroup on that line.
+
+`s'
+ In the Summary buffer, do an incremental search of the current
+ text in the Article buffer, just as if you switched to the Article
+ buffer and typed `C-s'.
+
+`M-s REGEXP RET'
+ In the Summary buffer, search forward for articles containing a
+ match for REGEXP.
+
+`C-c C-s C-n'
+`C-c C-s C-s'
+`C-c C-s C-d'
+`C-c C-s C-a'
+ In the Summary buffer, sort the list of articles by number,
+ subject, date, or author.
+
+`C-M-n'
+`C-M-p'
+ In the Summary buffer, read the next or previous article with the
+ same subject as the current article.
+
+
+File: emacs, Node: Calendar/Diary, Next: Version Control, Prev: GNUS, Up: Version 19
+
+Calendar and Diary
+==================
+
+ The calendar facility in Emacs 19 is almost completely new, and it
+comes with a diary feature. You can use the diary to keep track of
+appointments, anniversaries, and other events.
+
+ To use the diary, you must write diary entries in a particular file,
+called your "diary file". Its name is `~/diary'. Emacs displays the
+entries for particular dates by finding them in the diary file,
+formatting them, and displaying them in a diary display buffer.
+
+* Menu:
+
+* Calendar:: New features of the calendar proper.
+* Entries: Diary Entries. The location and form of a diary entry.
+* New Entries:: Inserting diary entries using the calendar.
+* Displaying Diary:: How to display diary entries from the calendar.
+* European Calendar Style :: Day-month-year style for dates.
+* Simple and Fancy:: The diary has two modes for display.
+* Other Diary Features:: The diary has many advanced commands.
+* Startup Diary:: How to display your diary when you start Emacs.
+* Printing Diary:: Print selected entries of the diary.
+
+
+File: emacs, Node: Calendar, Next: Diary Entries, Up: Calendar/Diary
+
+Calendar
+--------
+
+ In Emacs 19 you can use ordinary Emacs cursor commands to move
+through the calendar, which scrolls automatically to display different
+months or different years. Character motion translates to days, line
+motion to weeks, sentence and paragraph motion to months, and page
+motion to years. The vertical and horizontal scroll commands also
+handle the calendar suitably.
+
+ `p d' displays the selected date as a day within the year. `g d'
+selects a date given as month, day, year. Type `.' to go back to
+today's date.
+
+ The command `M-=', which normally gives the number of lines in the
+region, in Calendar mode gives the number of days in the region
+(`calendar-count-days-region').
+
+ The calendar facility also knows about other important calendars.
+The commands for these come in pairs; the commands to convert *to*
+another calendar start with the `p' prefix (short for "print"), and the
+commands to convert from another calendar start with the `g' prefix
+(short for "go to"). Here is a complete list:
+
+`g a', `p a'
+ The astronomical calendar, a simple count of days elapsed since
+ noon, Monday, January 1, 4713 B.C. on the Julian calendar. The
+ number of days elapsed is also called the "Julian day number"
+ (`calendar-goto-astro-date', `calendar-print-astro-date').
+
+`g c', `p c'
+ ISO commercial calendar
+ (`calendar-goto-iso-date', `calendar-print-iso-date').
+
+`g f', `p f'
+ French revolutionary calendar
+ (`calendar-goto-french-date',
+ `calendar-print-french-date').
+
+`g h', `p h'
+ Hebrew calendar
+ (`calendar-goto-hebrew-date',
+ `calendar-print-hebrew-date').
+
+`g i', `p i'
+ Islamic calendar
+ (`calendar-goto-islamic-date',
+ `calendar-print-islamic-date').
+
+`g j', `p j'
+ Julian calendar
+ (`calendar-goto-julian-date',
+ `calendar-print-julian-date').
+
+`p m'
+ Mayan calendar (`calendar-print-mayan-date').
+
+ The calendar also knows the dates of standard holidays. Type `h'
+(`calendar-cursor-holidays') to display a list of holidays for the
+selected date. This list appears in another window. Type `x'
+(`mark-calendar-holidays') to mark each day that is a holiday with `*'
+in the calendar itself. The command `u' (`calendar-unmark') turns off
+this marking.
+
+ At any time, you can use `M-x holidays' to display a list of
+holidays for the present month and the preceding and following months.
+
+
+File: emacs, Node: Diary Entries, Next: New Entries, Prev: Calendar, Up: Calendar/Diary
+
+Diary Entries
+-------------
+
+ To use the diary feature, you must write "diary entries" that
+describe plans associated with particular dates, and put them in your
+"diary file", which is normally the file `~/diary'. You can specify a
+different name for it by setting the variable `diary-file'; you would
+do this before using any of the commands that operate on the diary.
+
+ Diary file entries follow a simple convention: begin entries with a
+date at the beginning of a line, followed optionally by a time, and
+then by the text of the entry:
+
+ DATE OPTIONAL-TIME-OF-DAY TEXT-OF-ENTRY
+
+To continue an entry over two or more lines, indent the second and
+subsequent lines. The lines of the entry after the first are called
+"continuation lines". Other lines in the diary file that are not part
+of any entry are comment lines; Emacs does not display these.
+
+ When you make diary entries using Calendar mode, Emacs inserts the
+date for you in the appropriate format and places the cursor so you can
+type the text of the entry.
+
+ You can write entries in any order and Emacs will display the
+entries by date. However, time-of-day entries can be sorted
+chronologically only in a diary mode called Fancy mode; in Simple mode,
+Emacs displays time-of-day entries in their order in the diary file.
+
+
+File: emacs, Node: Displaying Diary, Next: European Calendar Style, Prev: New Entries, Up: Calendar/Diary
+
+Calendar Commands to Display Diary Entries
+------------------------------------------
+
+ In Calendar mode, use the following commands to display your diary
+entries:
+
+`d'
+ Display any diary entries for the date under the cursor
+ (`view-diary-entries').
+
+ With a numeric argument, Emacs shows the diary entries for that
+ many successive days, starting with and including the date under
+ the cursor. Thus, `2 d' displays all the entries for the selected
+ date and for the following day.
+
+`s'
+ Display your entire diary file (`show-all-diary-entries').
+
+`m'
+ In the calendar, mark all visible dates that have diary entries
+ (`mark-diary-entries').
+
+`u'
+ Unmark the calendar (`calendar-unmark').
+
+ At any time, not just in Calendar mode, you can display today's diary
+entries by typing:
+
+ M-x diary
+
+With a prefix argument N, this command displays diary entries for N
+successive days, starting from and including today.
+
+
+File: emacs, Node: New Entries, Next: Displaying Diary, Prev: Diary Entries, Up: Calendar/Diary
+
+Calendar Commands for Making Diary Entries
+------------------------------------------
+
+ Calendar mode provides several commands to help you make diary file
+entries. These commands work by visiting the diary file and inserting
+the date information; you must finish the job by inserting the text of
+the entry, and then save the diary file with `C-x C-s'. The commands
+are:
+
+`i d'
+ Add a diary entry for the selected date in the calendar
+ (`insert-diary-entry').
+
+`i w'
+ Add a diary entry for the selected day of the week
+ (`insert-weekly-diary-entry'). This entry is displayed each week
+ on the selected day.
+
+`i m'
+ Add a diary entry for the selected day of the month
+ (`insert-monthly-diary-entry'). This entry is displayed each month
+ on the selected day.
+
+`i y'
+ Add a diary entry for the selected day of the year
+ (`insert-yearly-diary-entry'). This entry is displayed each year
+ on the selected day.
+
+ Here are commands for entering more complex kinds of diary entries in
+Calendar mode. These kinds of entries operate properly only in Fancy
+Diary Display mode (*note Simple and Fancy::.).
+
+`i a'
+ Add an anniversary diary entry for the selected date
+ (`insert-anniversary-diary-entry').
+
+ Select the date you want remembered, in the proper year--if it is a
+ birthday, remember to go to the person's year of birth! Then type
+ `i a' and enter the text of the entry.
+
+ In the textual part of the entry you can type `%d'. When Emacs
+ displays the entry in the diary buffer, the `%d' is replaced by the
+ number of years since the date. Thus, if you use `%d years old' as
+ the text of the entry, it will display as `53 years old' on the
+ 53rd birthday.
+
+`i c'
+ Add a cyclic diary entry starting at the date
+ (`insert-cyclic-diary-entry'). An entry is displayed on a
+ specified starting date and then is repeatedly displayed at the
+ specified interval. This is useful for ten day cycles of
+ preventive maintenance and similar activities.
+
+ To use this command, first select the start date. The command
+ reads the interval (the number of days between repetitions) using
+ the minibuffer, then inserts the beginning of the entry.
+
+`i b'
+ Add a block diary entry for the current region
+ (`insert-block-diary-entry'). With a block entry, Emacs writes
+ the same message in the display for successive days.
+
+ Position point and mark at the beginning and end of the block of
+ days you want entered and type `i b'. This sets up the diary
+ entry's date info and positions point so you can write the text of
+ the entry. People usually use this command for trips or vacations.
+
+
+File: emacs, Node: European Calendar Style, Next: Simple and Fancy, Prev: Displaying Diary, Up: Calendar/Diary
+
+European Calendar Style
+-----------------------
+
+ By default, Emacs interprets and displays diary dates in civilian
+American form, `MONTH/DAY/YEAR': `2/15/1993', or `February 15, 1993'.
+
+ Alternatively, you can specify the European calendar style for
+writing dates: `DAY/MONTH/YEAR', `15/2/1993' or `15 February 1993'. To
+do this, set the variable `european-calendar-style' to `t', before
+using any calendar or diary command. This also affects display of
+dates.
+
+ Here's how to do this in your `.emacs' file:
+
+ (setq european-calendar-style t)
+
+
+File: emacs, Node: Simple and Fancy, Next: Other Diary Features, Prev: European Calendar Style, Up: Calendar/Diary
+
+Simple and Fancy Diary Display
+------------------------------
+
+ There are two modes for displaying a subset of diary entries: Simple
+mode and Fancy mode. Fancy mode provides a more dramatic display for
+the diary, and can also display the actual matching date for diary
+entries that match more than one date.
+
+ By default, Emacs uses Simple mode, which is quicker than Fancy mode.
+Another advantage of Simple mode is that you can edit the displayed
+diary entries "in place" and save them. When you use Fancy mode, it is
+useless to edit the displayed subset of the diary; instead you must
+visit the diary file separately. To select Fancy mode, set
+`diary-display-hook' to `fancy-diary-display' like this:
+
+ (setq diary-display-hook 'fancy-diary-display)
+
+
+File: emacs, Node: Other Diary Features, Next: Startup Diary, Prev: Simple and Fancy, Up: Calendar/Diary
+
+Other Diary Features
+--------------------
+
+ Here are some additional diary features. These will be explained in
+full in `The GNU Emacs Extensions Manual'.
+
+ You can schedule meetings on a date such as the first Tuesday of
+every month. This is called an "offset" date. The diary has commands
+for specifying such meetings, but not in Calendar mode. To create such
+an entry, you need to edit the diary file yourself.
+
+ You can make entries according to Hebrew and Islamic dates. Calendar
+mode provides commands of the form `i h d' to add a diary entry for the
+Hebrew date corresponding to the selected date and `i i d' to add a
+diary entry for the Islamic date corresponding to the selected date.
+You can make entries that repeat every week, month, or year. Before
+using these commands, you must set the
+`nongregorian-diary-listing-hook' and the
+`nongregorian-diary-marking-hook' in your `.emacs' file.
+
+ You can include other diary files in your diary display. This way, a
+group of people can share a common diary file.
+
+
+File: emacs, Node: Startup Diary, Next: Printing Diary, Prev: Other Diary Features, Up: Calendar/Diary
+
+Displaying your Diary on Emacs Startup
+--------------------------------------
+
+ If you start a new Emacs each day, you might want to display your
+diary automatically at that time. To do so, put this in your `.emacs'
+file:
+
+ (diary)
+
+ If you want to see both the calendar and your diary at startup, use
+this instead:
+
+ (setq view-diary-entries-initially t)
+ (calendar)
+
+
+File: emacs, Node: Printing Diary, Prev: Startup Diary, Up: Calendar/Diary
+
+Printing the Displayed Part of the Diary
+----------------------------------------
+
+ To print the selected diary entries as they appear on the screen, use
+`M-x print-diary-entries'. The same variables that customize
+`lpr-buffer' also affect this command.
+
+ In Simple mode, the diary display buffer uses selective display
+(*note Selective Display::.). This means that what you see on the
+screen is just part of the text in the Emacs buffer. The diary entries
+that don't apply to the dates you asked for are still in the buffer, but
+hidden. The ordinary printing commands such as `lpr-buffer' would not
+do what you want; they print the entire text, including the hidden
+parts. This is why we need `print-diary-entries'.
+
+
+File: emacs, Node: Version Control, Next: Emerge, Prev: Calendar/Diary, Up: Version 19
+
+Version Control
+===============
+
+ "Version control systems" are packages that can record multiple
+versions of a source file, usually storing the unchanged parts of the
+file just once. Version control systems also record history information
+such as the creation time of each version, who created it, and a
+description of what was changed in that version.
+
+ The GNU project recommends the version control system known as RCS,
+which is free software and available from the Free Software Foundation.
+Emacs supports use of either RCS or SCCS (a proprietary, but widely
+used, version control system that is not quite as powerful as RCS)
+through a facility called VC. The same Emacs commands work with either
+RCS or SCCS, so you hardly have to know which one of them you are using.
+
+* Menu:
+
+* Concepts of VC::
+* Editing with VC::
+* Variables for Check-in/out::
+* Comparing Versions::
+* VC Status::
+* Renaming and VC::
+* Snapshots::
+* Log Entries::
+* Change Logs and VC::
+* Version Headers::
+
+ \ No newline at end of file
diff --git a/info/emacs-14 b/info/emacs-14
new file mode 100644
index 00000000000..8b28d91c4c9
--- /dev/null
+++ b/info/emacs-14
@@ -0,0 +1,1335 @@
+This is Info file ../info/emacs, produced by Makeinfo-1.49 from the
+input file emacs.texi.
+
+ This file documents the GNU Emacs editor.
+
+ Copyright (C) 1985, 1986, 1988, 1992 Richard M. Stallman.
+
+ Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+ Permission is granted to copy and distribute modified versions of
+this manual under the conditions for verbatim copying, provided also
+that the sections entitled "The GNU Manifesto", "Distribution" and "GNU
+General Public License" are included exactly as in the original, and
+provided that the entire resulting derived work is distributed under the
+terms of a permission notice identical to this one.
+
+ Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that the sections entitled "The GNU Manifesto",
+"Distribution" and "GNU General Public License" may be included in a
+translation approved by the author instead of in the original English.
+
+
+File: emacs, Node: Concepts of VC, Next: Editing with VC, Up: Version Control
+
+Concepts of Version Control
+---------------------------
+
+ When a file is under version control, we also say that it is
+"registered" in the version control system. Each registered file has a
+corresponding "master file" which represents the file's present state
+plus its change history, so that you can reconstruct from it either the
+current version or any specified earlier version. Usually the master
+file also records a change comment for each version.
+
+ The file that is maintained under version control is sometimes called
+the "work file" corresponding to its master file.
+
+ To examine a file, you "check it out". This extracts a version of
+the file (typically, the most recent) from the master. If you want to
+edit the file, you must check it out "locked". Only one user can do
+this at a time for any given source file. When you are done with your
+editing, you must "check in" the new version. This records the new
+version in the master file, and unlocks the source file so that other
+people can lock it and thus modify it.
+
+ These are the basic operations of version control. Checking in and
+checking out both use the single Emacs command `C-x C-q'
+(`vc-toggle-read-only').
+
+
+File: emacs, Node: Editing with VC, Next: Variables for Check-in/out, Prev: Concepts of VC, Up: Version Control
+
+Editing with Version Control
+----------------------------
+
+ When you visit a file that is maintained using version control, the
+mode line displays `RCS' or `SCCS' to inform you that version control
+is in use, and also (in case you care) which low-level system the file
+is actually stored in. Normally, such a source file is read-only, and
+the mode line indicates this with `%%'.)
+
+ These are the commands that you use to edit a file maintained with
+version control:
+
+`C-x C-q'
+ Check the visited file in or out.
+
+`C-x v u'
+ Revert the buffer and the file to the last checked in version.
+
+`C-x v c'
+ Remove the last-entered change from the master for the visited
+ file. This undoes your last check-in.
+
+`C-x v i'
+ Register the visited file in version control.
+
+(`C-x v' is the prefix key for version control commands; all of these
+commands except for `C-x C-q' start with `C-x v'.)
+
+ If you want to edit the file, type `C-x C-q'
+(`vc-toggle-read-only'). This "checks out" and locks the file, so that
+you can edit it. The file is writable after check-out, but only for
+you, not for anyone else.
+
+ Emacs does not save backup files for source files that are maintained
+with version control. If you want to make backup files despite version
+control, set the variable `vc-make-backups' to a non-`nil' value.
+
+ When you are finished editing the file, type `C-x C-q' again. When
+used on a file that is checked out, this command checks the file in.
+But check-in does not start immediately; first, you must enter a "log
+entry"--a description of the changes in the new version. `C-x C-q' pops
+up a buffer for you to enter this in. When you are finished typing in
+the log entry, type `C-c C-c' to terminate it; this is when actual
+check-in takes place.
+
+ Once you have checked in your changes, the file is unlocked, so that
+other users can lock it and modify it.
+
+ Normally the work file exists all the time, whether it is locked or
+not. If you set `vc-keep-workfiles' to `nil', then checking in a new
+version with `C-x C-q' deletes the work file; but any attempt to visit
+the file with Emacs creates it again.
+
+ Actually, it is not impossible to lock a file that someone else has
+locked. If you try to check out a file that is locked, `C-x C-q' asks
+you whether you want to "steal the lock." If you say yes, the file
+becomes locked by you, but a message is sent to the person who had
+formerly locked the file, to inform him or her of what has happened.
+
+ If you want to discard your current set of changes and revert to the
+last version checked in, use `C-x v u' (`vc-revert-buffer'). This
+cancels your last check-out, leaving the file unlocked. If you want to
+make a different set of changes, you must first check the file out
+again. `C-x v u' requies confirmation, unless it sees that you haven't
+made any changes since the last checked-in version.
+
+ `C-x v u' is also the command to use if you lock a file and then
+don't actually change it.
+
+ You can even cancel a change after checking it in, with `C-x v c'
+(`vc-cancel-version'). Normally, `C-x v c' reverts your workfile and
+buffer to the previous version (the one that precedes the version that
+is deleted), but you can prevent the reversion by giving the command a
+prefix argument. Then the buffer does not change.
+
+ This command with a prefix argument is useful when you have checked
+in a change and then discover a trivial error in it; you can cancel the
+erroneous check-in, fix the error, and repeat the check-in.
+
+ Be careful when invoking `C-x v c', as it is easy to throw away a
+lot of work with it. To help you be careful, this command always asks
+for confirmation with `yes'.
+
+ You can register the visited file for version control using
+`C-x v i' (`vc-register'). This uses RCS if RCS is installed on your
+system; otherwise, it uses SCCS.
+
+ By default, the initial version number is 1.1. If you want to use a
+different number, give `C-x v i' a prefix argument; then it reads the
+initial version number using the minibuffer.
+
+ After `C-x v i', the file is unlocked and read-only. Type `C-x C-q'
+if you wish to edit it.
+
+ If `vc-initial-comment' is non-`nil', `C-x v i' reads an initial
+comment (much like a log entry) to describe the purpose of this source
+file.
+
+
+File: emacs, Node: Variables for Check-in/out, Next: Comparing Versions, Prev: Editing with VC, Up: Version Control
+
+Variables Affecting Check-in and Check-out
+------------------------------------------
+
+ If `vc-suppress-confirm' is non-`nil', then `C-x C-q' and `C-x v i'
+can save the current buffer without asking, and `C-x v u' also operates
+without asking for confirmation. (This variable does not affect `C-x v
+c'; that is so drastic that it should always ask for confirmation.)
+
+ VC mode does much of its work by running the shell commands for RCS
+and SCCS. If `vc-command-messages' is non-`nil', VC displays messages
+to indicate which shell commands it runs, and additional messages when
+the commands finish.
+
+ Normally, VC assumes that it can deduce the locked/unlocked state of
+files by looking at the file permissions of the work file; this is
+fast. However, if the `RCS' or `SCCS' subdirectory is actually a
+symbolic link, then VC does not trust the file permissions to reflect
+this status.
+
+ You can specify the criterion for whether to trust the file
+permissions by setting the variable `vc-mistrust-permissions'. Its
+value may be `t' (always mistrust the file permissions and check the
+master file), `nil' (always trust the file permissions), or a function
+of one argument which makes the decision. The argument is the directory
+name of the `RCS' or `SCCS' subdirectory. A non-`nil' value from the
+function says to mistrust the file permissions.
+
+ If you find that the file permissions of work files are changed
+erroneously, then you can set `vc-mistrust-permissions' to `t' so that
+VC always checks the master file.
+
+
+File: emacs, Node: Log Entries, Next: Change Logs and VC, Prev: Snapshots, Up: Version Control
+
+Log Entries
+-----------
+
+ When you're editing an initial or change comment for inclusion in a
+master file, finish your entry by typing `C-c C-c'.
+
+`C-c C-c'
+ Finish the comment edit normally (`vc-finish-logentry'). This
+ finishes check-in.
+
+ To abort check-in, just don't type `C-c C-c' in that buffer. You
+can switch buffers and do other editing. As long as you don't try to
+check in another file, the comment you were editing remains in its
+buffer, and you can go back to that buffer at any time to complete the
+check-in.
+
+ If you change several source files for the same reason, it is often
+convenient to specify the same log entry for many of the files. To do
+this, use the history of previous log entries. The commands `M-n',
+`M-p', `M-s' and `M-r' for doing this work just like the minibuffer
+history commands (except that they don't use the minibuffer).
+
+ The history of previous log entries is actually stored in previous
+pages of the log entry editing buffer; they are normally hidden by
+narrowing.
+
+ Each time you check in a file, the log entry buffer is put into VC
+Log mode, which involves running two hook variables: `text-mode-hook'
+and `vc-log-mode-hook'.
+
+
+File: emacs, Node: Change Logs and VC, Next: Version Headers, Prev: Log Entries, Up: Version Control
+
+Change Logs and VC
+------------------
+
+ Emacs users often record brief summaries of program changes in a file
+called `ChangeLog', which is kept in the same directory as the source
+files, and is usually meant to be distributed along with the source
+files. You can maintain `ChangeLog' from the version control logs with
+the following command.
+
+`C-x v a'
+ Visit the current directory's change log file and create new
+ entries for versions checked in since the most recent entry in the
+ change log file (`vc-update-change-log').
+
+ This command works with RCS only; it does not work with SCCS.
+
+ For example, suppose the first line of `ChangeLog' is dated 10 April
+1992, and suppose the only check-in since then was by Nathaniel
+Bowditch to `rcs2log' on 8 May 1992 with log text `Ignore log messages
+that start with `#'.'. Then `C-x v a' visits `ChangeLog' and inserts
+text like this:
+
+ Fri May 8 21:45:00 1992 Nathaniel Bowditch (nat@apn.org)
+
+ * rcs2log: Ignore log messages that start with `#'.
+
+You can then further edit as you wish.
+
+ A log entry whose text begins with `#' is not copied to `ChangeLog'.
+ For example, if you merely fix some misspellings in comments, you can
+log the change with an entry beginning with `#' to avoid putting such
+trivia into `ChangeLog'.
+
+ When `C-x v a' adds several change log entries at once, it groups
+related log entries together if they all are checked in by the same
+author at nearly the same time. If the log entries for several such
+files all have the same text, it coalesces them into a single entry.
+For example, suppose the most recent check-ins have the following log
+entries:
+
+For `vc.texinfo':
+ Fix expansion typos.
+For `vc.el':
+ Don't call expand-file-name.
+For `vc-hooks.el':
+ Don't call expand-file-name.
+
+ They appear like this in `ChangeLog':
+
+ Wed Apr 1 08:57:59 1992 Nathaniel Bowditch (nat@apn.org)
+
+ * vc.texinfo: Fix expansion typos.
+
+ * vc.el, vc-hooks.el: Don't call expand-file-name.
+
+ Normally, `C-x v a' separates log entries by a blank line, but you
+can mark several related log entries to be clumped together (without an
+intervening blank line) by starting the text of each related log entry
+with a label of the form `{CLUMPNAME} '. The label itself is not
+copied to `ChangeLog'. For example, suppose the log entries are:
+
+For `vc.texinfo':
+ {expand} Fix expansion typos.
+For `vc.el':
+ {expand} Don't call expand-file-name.
+For `vc-hooks.el':
+ {expand} Don't call expand-file-name.
+
+ Then the text in `ChangeLog' looks like this:
+
+ Wed Apr 1 08:57:59 1992 Nathaniel Bowditch (nat@apn.org)
+
+ * vc.texinfo: Fix expansion typos.
+ * vc.el, vc-hooks.el: Don't call expand-file-name.
+
+ Normally, the log entry for file `foo' is displayed as `* foo: TEXT
+OF LOG ENTRY'. But by convention, the `:' after `foo' is omitted if
+the text of the log entry starts with `(FUNCTIONNAME): '. For example,
+if the log entry for `vc.el' is `(vc-do-command): Check call-process
+status.', then the text in `ChangeLog' looks like this:
+
+ Wed May 6 10:53:00 1992 Nathaniel Bowditch (nat@apn.org)
+
+ * vc.el (vc-do-command): Check call-process status.
+
+
+File: emacs, Node: Comparing Versions, Next: VC Status, Prev: Variables for Check-in/out, Up: Version Control
+
+Comparing Versions
+------------------
+
+ To compare two versions of a file, use `C-x v =' (`vc-diff').
+
+ Plain `C-x v =' compares the current buffer contents (saving them in
+the file if necessary) with the last checked-in version of the file.
+With a prefix argument, `C-x v =' reads a filename and two version
+numbers, and compares those versions of the file you specify.
+
+ If you supply a directory name instead of the name of a work file,
+this command compares the two specified versions of all registered files
+in that directory and its subdirectories. You can also specify a
+snapshot name (*note Snapshots::.) instead of one or both version
+numbers.
+
+ You can specify a checked-in version by its number; you can specify
+the most recent checked-in version with `-'; and you can specify the
+current buffer contents with `+'. Thus, you can compare two checked-in
+versions, or compare a checked-in version with the text you are editing.
+
+ This command works by running the `diff' utility, getting the
+options from the variable `diff-switches'. It displays the output in a
+special buffer in another window.
+
+
+File: emacs, Node: VC Status, Next: Renaming and VC, Prev: Comparing Versions, Up: Version Control
+
+VC Status Commands
+------------------
+
+ To get the detailed version control status of one file, type `C-x v
+l' (`vc-print-log'). It displays the history of changes to the current
+file, including the text of the log entries. The output appears in a
+separate window.
+
+ When you are working on a large program, it's often useful to find
+all the files that are currently locked, or all the files maintained in
+version control at all. You can do so using these commands, both of
+which operate on the branch of the file system starting at the current
+directory.
+
+ You can use `C-x v d' (`vc-directory') to show all the locked files
+in or beneath the current directory. This includes all files that are
+locked by any user.
+
+ With a prefix argument, `C-x v d' shows all the version control
+activity in the current directory--it lists all files in or beneath the
+current directory that are maintained with version control.
+
+
+File: emacs, Node: Renaming and VC, Next: Snapshots, Prev: VC Status, Up: Version Control
+
+Renaming VC Work Files and Master Files
+---------------------------------------
+
+ When you rename a registered file, you must also rename its master
+file correspondingly to get proper results. Use `vc-rename-file' to
+rename the source file as you specify, and rename its master file
+accordingly. It also updates any snapshots (*note Snapshots::.) that
+mention the file, so that they use the new name; despite this, the
+snapshot thus modified may not completely work (*note Snapshot
+Caveats::.).
+
+ You cannot use `vc-rename-file' on a file that is locked by someone
+else.
+
+ `vc-rename-file' is not bound to a key because it's not likely to be
+used frequently.
+
+
+File: emacs, Node: Snapshots, Next: Log Entries, Prev: Renaming and VC, Up: Version Control
+
+Snapshots
+---------
+
+ A "snapshot" is a named set of file versions (one for each
+registered file) that you can treat as a unit. One important kind of
+snapshot is a "release", a (theoretically) stable version of the system
+that is ready for distribution to users.
+
+* Menu:
+
+* Making Snapshots:: The snapshot facilities.
+* Snapshot Caveats:: Things to be careful of, when using snapshots.
+
+
+File: emacs, Node: Making Snapshots, Next: Snapshot Caveats, Up: Snapshots
+
+Making and Using Snapshots
+..........................
+
+ There are two basic commands for snapshots; one makes a snapshot
+with a given name, the other retrieves a named snapshot.
+
+`C-x v s NAME RET'
+ Define the last saved versions of every registered file in or
+ under the current directory as a snapshot named NAME
+ (`vc-create-snapshot').
+
+`C-x v r NAME RET'
+ Check out all registered files at or below the current directory
+ level using whatever versions correspond to the snapshot NAME
+ (`vc-retrieve-snapshot').
+
+ This function reports an error if any files are locked at or below
+ the current directory, without changing anything; this is to avoid
+ overwriting work in progress.
+
+ You shouldn't need to use `vc-retrieve-snapshot' very often; you can
+get difference reports between two snapshots without retrieving either
+one, using `C-x =' (*note Comparing Versions::.). Thus, retrieving a
+snapshot is only necessary if you need to study or compile portions of
+the snapshot.
+
+ A snapshot uses a very small amount of resources--just enough to
+record the list of file names and which version belongs to the
+snapshot. Thus, you need not hesitate to create snapshots whenever
+they are useful.
+
+ You can give a snapshot name as an argument to `C-x v =' (*note
+Comparing Versions::.). Thus, you can use it to compare a snapshot
+against the current files, or two snapshots against each other, or a
+snapshot against a named version.
+
+
+File: emacs, Node: Snapshot Caveats, Prev: Making Snapshots, Up: Snapshots
+
+Snapshot Caveats
+................
+
+ VC's snapshot facilities are modeled on RCS's named-configuration
+support. They use RCS's native facilities for this, so under VC
+snapshots made using RCS are visible even when you bypass VC.
+
+ For SCCS, VC implements snapshots itself. The files it uses contain
+name/file/version-number triples. These snapshots are visible only
+through VC.
+
+ File renaming and deletion can create some difficulties with
+snapshots. This is not a VC-specific problem, but a general design
+issue in version control systems that no one has solved very well yet.
+
+ If you rename a registered file, you need to rename its master along
+with it (the function `vc-rename-file' does this automatically). If you
+are using SCCS, you must also update the records of the snapshot, to
+mention the file by its new name (`vc-rename-file' does this, too).
+This makes the snapshot remain valid for retrieval, but it does not
+solve all problems.
+
+ For example, some of the files in the program probably refer to
+others by name. At the very least, the makefile probably mentions the
+file that you renamed. If you retrieve an old snapshot, the renamed
+file is retrieved under its new name, which is not the name that the
+makefile expects. So the program won't really work.
+
+ If you use snapshots, don't rename either work files or master files
+except by means of `vc-rename-file'. It knows how to update snapshots
+so that you can still retrieve them. An old snapshot that refers to a
+master file that no longer exists under the recorded name is invalid;
+VC can no longer retrieve it. It would be beyond the scope of this
+manual to explain enough about RCS and SCCS to teach the reader how to
+update the snapshots by hand.
+
+
+File: emacs, Node: Version Headers, Prev: Change Logs and VC, Up: Version Control
+
+Inserting Version Control Headers
+---------------------------------
+
+ Sometimes it is convenient to put version identification strings
+directly into working files. Certain special strings called "version
+headers" are replaced in each successive version by the number of that
+version.
+
+ You can use the `C-x v h' command (`vc-insert-headers') to insert a
+suitable header string.
+
+`C-x v h'
+ Insert headers in a file for use with your version-control system.
+
+ The default header string is `$ld$' for RCS and `%W%' for SCCS. You
+can specify other headers to insert by setting the variable
+`vc-header-string'. Its value (if non-`nil') should be the string to
+be inserted. You can also specify a list of strings; then each string
+in the list is inserted as a separate header on a line of its own. (It
+is often important to use "superfluous" backslashes when writing a Lisp
+string constant for this use, to prevent the string in the constant
+from being interpreted as a header itself if the Emacs Lisp file
+containing it is maintained with version control.)
+
+ Each header is inserted surrounded by tabs, inside comment
+delimiters, on a new line at the start of the buffer. Normally the
+ordinary comment start and comment end strings of the current mode are
+used, but for certain modes, there are special comment delimiters for
+this purpose; the variable `vc-comment-alist' specifies them. Each
+element of this list has the form `(MODE STARTER ENDER)'.
+
+ `vc-static-header-alist' is consulted to add further strings based
+on the name of the buffer. Its value should be a list of dotted pairs;
+the CAR of each pair is a regular expression that should match the
+buffer name, and the CDR is the format to use on each header. A string
+is inserted for each file name pattern that matches the buffer name,
+and for each header taken from `vc-header-string'. The default value
+for `vc-static-header-alist' is:
+
+ (("\\.c$" .
+ "\n#ifndef lint\nstatic char vcid[] = \"\%s\";\n\
+ #endif /* lint */\n"))
+
+which specifies insertion of a string of this form:
+
+
+ #ifndef lint
+ static char vcid[] = "HEADER-STRING";
+ #endif /* lint */
+
+
+File: emacs, Node: Emerge, Next: Debuggers, Prev: Version Control, Up: Version 19
+
+Emerge
+======
+
+ It's not unusual for programmers to get their signals crossed and
+modify the same program in two different directions. To recover from
+this confusion, you need to merge the two versions. Emerge makes this
+easier.
+
+* Menu:
+
+* Overview of Emerge::
+* Submodes of Emerge::
+* State of Difference::
+* Merge Commands::
+* Exiting Emerge::
+* Combining in Emerge::
+* Fine Points of Emerge::
+
+
+File: emacs, Node: Overview of Emerge, Next: Submodes of Emerge, Up: Emerge
+
+Overview of Emerge
+------------------
+
+ To start Emerge, run one of these four commands:
+
+`M-x emerge-files'
+ Merge two specified files.
+
+`M-x emerge-files-with-ancestor'
+ Merge two specified files, with reference to a common ancestor.
+
+`M-x emerge-buffers'
+ Merge two buffers (the currently accessible portions).
+
+`M-x emerge-buffers-with-ancestor'
+ Merge two buffers (the currently accessible portions) with
+ reference to a common ancestor in another buffer.
+
+ The Emerge commands compare two texts, and display the results in
+three buffers: one for each input text (the "A buffer" and the "B
+buffer"), and one (the "merge buffer") where merging takes place. The
+merge buffer does not show just the differences. Rather, it shows you
+the full text, but wherever the input texts differ, you can choose
+which one of them to include in the merge buffer.
+
+ If a common ancestor version is available, from which the two texts
+to be merged were both derived, Emerge can use it to guess which
+alternative is right. Wherever one current version agrees with the
+ancestor, Emerge presumes that the other current version is a deliberate
+change which should be kept in the merged version. Use the
+"with-ancestor" commands if you want to specify a common ancestor text.
+ These commands read three file or buffer names--variant A, variant B,
+and the common ancestor.
+
+ After the comparison is done and the buffers are prepared, the actual
+merging starts. You control the merging interactively by editing the
+merge buffer. The merge buffer shows you a full merged text, not just
+differences. For each point where the input texts differ, you can
+choose which one of them to include in the merge buffer.
+
+ The merge buffer has a special major mode, Emerge mode, with commands
+for making these choices. But you can also edit the buffer with
+ordinary Emacs commands.
+
+ At any given time, the attention of Emerge is focused on one
+particular difference, called the "selected" difference. This
+difference is marked off in the three buffers by
+
+ vvvvvvvvvvvvvvvvvvvv
+
+above and
+
+ ^^^^^^^^^^^^^^^^^^^^
+
+below. Emerge numbers all the differences sequentially and the mode
+line always shows the number of the selected difference.
+
+ Normally, the merge buffer starts out with the A version of the text.
+But when the A version of a part of the buffer agrees with the common
+ancestor, then the B version is preferred for that part.
+
+ Normally, Emerge stores the merged output in place of the first input
+text (the A file or buffer). If you give a prefix argument to
+`emerge-files' or `emerge-files-with-ancestor', it reads the name of
+the output file using the minibuffer. (This is the last file name
+those commands read.)
+
+ If you abort Emerge with `C-u q', the output is not saved.
+
+
+File: emacs, Node: Submodes of Emerge, Next: State of Difference, Prev: Overview of Emerge, Up: Emerge
+
+Submodes of Emerge
+------------------
+
+ You can choose between two modes for giving merge commands: Fast mode
+and Edit mode. In Fast mode, basic Emerge commands are single
+characters, but ordinary Emacs commands are disabled. This is
+convenient if you use only Emerge commands.
+
+ In Edit mode, all Emerge commands start with the prefix character
+`C-c', and the normal Emacs commands are also available. This allows
+editing the merge buffer, but slows down Emerge operations.
+
+ Use `e' to switch to Edit mode, and `f' to switch to Fast mode. The
+mode line indicates Edit and Fast modes with `E' and `F'.
+
+ Emerge has two additional submodes that affect how particular merge
+commands work: Auto Advance mode and Skip Prefers mode.
+
+ If Auto Advance mode is in effect, the `a' and `b' commands advance
+to the next difference. This lets you go through the merge faster
+doing ordinary things. The mode line indicates Auto Advance mode with
+`A'.
+
+ If Skip Prefers mode is in effect, the `n' and `p' commands skip
+over differences in states prefer-A and prefer-B. Thus you will only
+see differences for which neither version is presumed "correct". The
+mode line indicates Skip Prefers mode with `S'.
+
+ Use the command `emerge-auto-advance-mode' to set or clear Auto
+Advance mode. Use `emerge-skip-prefers-mode' to set or clear Skip
+Prefers mode. A positive argument turns the mode on, a nonpositive
+argument turns it off, and no argument toggles it.
+
+
+File: emacs, Node: State of Difference, Next: Merge Commands, Prev: Submodes of Emerge, Up: Emerge
+
+State of a Difference
+---------------------
+
+ In the merge buffer, a difference is marked `vvvvvvvvvvvvvvvvvvvv'
+above and `^^^^^^^^^^^^^^^^^^^^' below. Such a difference can have one
+of seven states:
+
+A
+ The difference is showing the A version. The `a' command always
+ produces this state; the mode line indicates it with `A'.
+
+B
+ The difference is showing the B version. The `b' command always
+ produces this state; the mode line indicates it with `B'.
+
+default-A
+default-B
+ The difference is showing the A or the B state by default, because
+ you haven't made a choice. All differences start in the default-A
+ state (and thus the merge buffer is a copy of the A buffer),
+ except those for which one alternative is "preferred" (see below).
+
+ When you select a difference, its state changes from default-A or
+ default-B to plain A or B. Thus, the selected difference never has
+ state default-A or default-B, and these states are never displayed
+ in the mode line.
+
+ The command `d a' chooses default-A as the default state, and `d
+ b' chooses default-B. This chosen default applies to all
+ differences which you haven't selected and for which no
+ alternative is preferred. If you are moving through the merge
+ sequentially, the differences you haven't selected are those
+ following the selected one. Thus, while moving sequentially, you
+ can effectively make the A version the default for some sections
+ of the merge buffer and the B version the default for others by
+ using `d a' and `d b' at the end of each section.
+
+prefer-A
+prefer-B
+ The difference is showing the A or B state because it is
+ "preferred". This means that you haven't made an explicit choice,
+ but one alternative seems likely to be right because the other
+ alternative agrees with the common ancestor. Thus, where the A
+ buffer agrees with the common ancestor, the B version is
+ preferred, because chances are it is the one that was actually
+ changed.
+
+ These two states are displayed in the mode line as `A*' and `B*'.
+
+combined
+ The difference is showing a combination of the A and B states, as a
+ result of the `x c' or `x C' commands.
+
+ Once a difference is in this state, the `a' and `b' commands don't
+ do anything to it unless you give them a prefix argument.
+
+ The mode line displays this state as `comb'.
+
+
+File: emacs, Node: Merge Commands, Next: Exiting Emerge, Prev: State of Difference, Up: Emerge
+
+Merge Commands
+--------------
+
+ Here are the Merge commands for Fast mode; in Edit mode, precede
+these with `C-c' and turn all the letters into control characters.
+
+`p'
+ Select the previous difference.
+
+`n'
+ Select the next difference.
+
+`a'
+ Choose the A version of this difference.
+
+`b'
+ Choose the B version of this difference.
+
+`j'
+ Select a particular difference; specify the sequence number of that
+ difference as a prefix argument.
+
+`M-x emerge-select-difference'
+ Select the run of differences containing the current location.
+ You can use this command in the merge buffer or in the A or B
+ buffer.
+
+`q'
+ Quit--finish the merge. With an argument, abort the merge.
+
+`f'
+ Go into fast mode.
+
+`e'
+ Go into edit mode.
+
+`l'
+ Recenter (like `C-l') all three windows.
+
+`-'
+ Specify part of a prefix numeric argument.
+
+`DIGIT'
+ Also specify part of a prefix numeric argument.
+
+`d a'
+ Choose the A version as the default from here down in the merge
+ buffer.
+
+`d b'
+ Choose the B version as the default from here down in the merge
+ buffer.
+
+`c a'
+ Copy the A version of this difference into the kill ring.
+
+`c b'
+ Copy the B version of this difference into the kill ring.
+
+`i a'
+ Insert the A version of this difference at the point.
+
+`i b'
+ Insert the B version of this difference at the point.
+
+`m'
+ Put the point and mark around the difference region.
+
+`^'
+ Scroll all three windows down (like `M-v').
+
+`v'
+ Scroll all three windows up (like `C-v').
+
+`<'
+ Scroll all three windows left (like `C-x <').
+
+`>'
+ Scroll all three windows right (like `C-x >').
+
+`|'
+ Reset horizontal scroll on all three windows.
+
+`x 1'
+ Shrink the merge window to one line. (Use `C-u l' to restore it
+ to full size.)
+
+`x c'
+ Combine the two versions of this difference.
+
+`x f'
+ Show the files/buffers Emerge is operating on in Help window. (Use
+ `C-u l' to restore windows.)
+
+`x j'
+ Join this difference with the following one. (`C-u x j' joins this
+ difference with the previous one.)
+
+`x s'
+ Split this difference into two differences. Before you use this
+ command, position point in each of the three buffers to the place
+ where you want to split the difference.
+
+`x t'
+ Trim identical lines off top and bottom of the difference. Such
+ lines occur when the A and B versions are identical but differ
+ from the ancestor version.
+
+
+File: emacs, Node: Exiting Emerge, Next: Combining in Emerge, Prev: Merge Commands, Up: Emerge
+
+Exiting Emerge
+--------------
+
+ The `q' (`emerge-quit') command finishes the merge, storing the
+results into the output file. It restores the A and B buffers to their
+proper contents, or kills them if they were created by Emerge. It also
+disables the Emerge commands in the merge buffer, since executing them
+later could damage the contents of the various buffers.
+
+ `C-u q' aborts the merge. Aborting means that Emerge does not write
+the output file.
+
+ If Emerge was called from another Lisp program, then its return value
+is `t' or `nil' to indicate success or failure.
+
+
+File: emacs, Node: Combining in Emerge, Next: Fine Points of Emerge, Prev: Exiting Emerge, Up: Emerge
+
+Combining the Two Versions
+--------------------------
+
+ Sometimes you want to keep *both* alternatives for a particular
+locus. To do this, use `x c', which edits the merge buffer like this:
+
+ #ifdef NEW
+ VERSION FROM A FILE
+ #else /* NEW */
+ VERSION FROM B FILE
+ #endif /* NEW */
+
+ While this example shows C preprocessor conditionals delimiting the
+two alternative versions, you can specify the strings you want by
+setting the variable `emerge-combine-template' to a list of three
+strings. The default setting, which produces the results shown above,
+looks like this:
+
+ ("#ifdef NEW\n"
+ "#else /* NEW */\n"
+ "#endif /* NEW */\n")
+
+
+File: emacs, Node: Fine Points of Emerge, Prev: Combining in Emerge, Up: Emerge
+
+Fine Points of Emerge
+---------------------
+
+ You can have any number of merges going at once--just don't use any
+one buffer as input to more than one merge at once, since that will
+cause the read-only/modified/auto-save status save-and-restore to screw
+up.
+
+ Starting Emerge can take a long time because it needs to compare the
+files. Emacs can't do anything else until `diff' finishes. Perhaps in
+the future someone will change Emerge to do the comparison in the
+background when the input files are large--then you could keep on doing
+other things with Emacs until Emerge gets ready to accept commands.
+
+ After the merge has been set up, Emerge runs the hooks in
+`emerge-startup-hook'.
+
+ During the merge, you musn't try to edit the A and B buffers
+yourself. Emerge modifies them temporarily, but ultimately puts them
+back the way they were.
+
+
+File: emacs, Node: Debuggers, Next: Other New Modes, Prev: Emerge, Up: Version 19
+
+Running Debuggers Under Emacs
+=============================
+
+ The GUD (Grand Unified Debugger) library provides an interface to
+various symbolic debuggers from within Emacs. We recommend the
+debugger GDB, which is free software, but you can also run DBX or SDB
+if you have them.
+
+* Menu:
+
+* Starting GUD:: How to start a debugger subprocess.
+* Debugger Operation:: Connection between the debugger and source buffers.
+* Commands of GUD:: Keybindings for common commands.
+* GUD Customization:: Defining your own commands for GUD.
+
+
+File: emacs, Node: Starting GUD, Next: Debugger Operation, Up: Debuggers
+
+Starting GUD
+------------
+
+ There are three commands for starting a debugger. Each corresponds
+to a particular debugger program.
+
+`M-x gdb RET FILE RET'
+`M-x dbx RET FILE RET'
+ Run GDB or DBX in a subprocess of Emacs. Both of these commands
+ select the buffer used for input and output to the debugger.
+
+`M-x sdb RET FILE RET'
+ Run SDB in a subprocess of Emacs. SDB's messages do not mention
+ file names, so the Emacs interface to SDB depends on having a tags
+ table (*note Tags::.) to find which file each function is in. If
+ you have not visited a tags table or the tags table doesn't list
+ one of the functions, you get a message saying `The sdb support
+ requires a valid tags table to work'. If this happens, generate a
+ valid tags table in the working directory and try again.
+
+ You can only run one debugger process at a time.
+
+
+File: emacs, Node: Debugger Operation, Next: Commands of GUD, Prev: Starting GUD, Up: Debuggers
+
+Debugger Operation
+------------------
+
+ When you run a debugger with GUD, the debugger displays source files
+via Emacs--Emacs finds the source file and moves point to the line
+where the program is executing. An arrow (`=>') indicates the current
+execution line, and it stays put even if you move the cursor.
+
+ You can start editing the file at any time. The arrow is not part of
+the file's text; it appears only on the screen. If you do modify a
+source file, keep in mind that inserting or deleting lines will throw
+off the arrow's positioning; GUD has no way of figuring out which line
+corresponded before your changes to the line number in a debugger
+message. Also, you'll typically have to recompile and restart the
+program for your changes to be reflected in the debugger's tables.
+
+ If you wish, you can control your debugger process entirely through
+the debugger buffer, which uses a variant of Shell mode. All the usual
+commands for your debugger are available, and you can use the Shell mode
+history commands to repeat them.
+
+
+File: emacs, Node: Commands of GUD, Next: GUD Customization, Prev: Debugger Operation, Up: Debuggers
+
+Commands of GUD
+---------------
+
+ GUD provides a command available in all buffers for setting
+breakpoints. This command is defined globally because you need to use
+it in the source files' buffers.
+
+`C-x SPC'
+ Set a breakpoint on the line that point is on.
+
+ The debugger buffer has a number of keybindings for invoking common
+debugging commands quickly:
+
+`C-c C-l'
+ Display in another window the last line referred to in the GUD
+ buffer (that is, the line indicated in the last location message).
+ This runs the command `gud-refresh'.
+
+`C-c C-s'
+ Execute a single line of code (`gud-step'). If the code contains
+ a function call, execution stops after entering the called
+ function.
+
+`C-c C-n'
+ Execute a single line of code, stepping across entire function
+ calls at full speed (`gud-next').
+
+`C-c C-i'
+ Execute a single machine instruction (`gud-stepi').
+
+`C-c C-c'
+ Continue execution until the next breakpoint, or other event that
+ would normally stop the program (`gud-cont').
+
+ The above commands are common to all supported debuggers. If you are
+using GDB or (some versions of) DBX, these additional commands are
+available:
+
+`C-c <'
+ Select the next enclosing stack frame (`gud-up'). This is
+ equivalent to the `up' command.
+
+`C-c >'
+ Select the next inner stack frame (`gud-down'). This is
+ equivalent to the `down' command.
+
+ If you are using GDB, two additional keybindings are available:
+
+`C-c C-f'
+ Run the program until the selected stack frame returns (or until it
+ stops for some other reason).
+
+`TAB'
+ Complete the symbol in the buffer before point, using the set of
+ all symbols known to GDB.
+
+ These commands interpret a prefix argument as a repeat count, when
+that makes sense.
+
+ After each command that changes the program counter, GUD displays the
+new current source line, and updates the location of the arrow.
+
+
+File: emacs, Node: GUD Customization, Prev: Commands of GUD, Up: Debuggers
+
+GUD Customization
+-----------------
+
+ On startup, GUD executes one of the following hooks:
+`gdb-mode-hook', if you are using GDB; `dbx-mode-hook', if you are
+using DBX; and `sdb-mode-hook', if you are using SDB. You can use
+these hooks to define custom keybindings for the debugger interaction
+buffer.
+
+ Here is a convenient way to define a command that sends a particular
+command string to the debugger, and set up a key binding for it in the
+debugger interaction buffer:
+
+ (gud-def FUNCTION CMDSTRING BINDING DOCSTRING)
+
+ This defines a command named FUNCTION which sends CMDSTRING to the
+debugger process, with documentation string DOCSTRING, and binds it to
+BINDING in the debugger buffer's mode. (If BINDING is `nil', this
+defines the command but does not make a binding for it; you can make a
+binding explicitly, perhaps using one of the above hooks.)
+
+ Commands defined with `gud-def' handle prefix arguments by passing
+them to the debugger, appended to end of CMDSTRING with a space in
+between. (This use of prefix arguments works with GDB and DBX, but not
+with SDB.)
+
+ You can also set up commands that you can send to the debugger while
+in another buffer, such as a source file. Set the variable
+`gud-commands' to a list of strings containing debugger commands you
+might want to send.
+
+`C-x &'
+ Send a custom command to the debugger process
+ (`send-gud-command'). Normally, send the CAR of the
+ `gud-commands' list; a prefix argument specifies which element of
+ that list to use (counting from 0).
+
+ If the string contains `%s', `C-x &' substitutes a numeric value
+ found in the buffer at or near point. It looks for decimal,
+ octal, or hexadecimal numbers, with `0x' allowed. This lets you
+ define commands to chase pointers whose numeric values have been
+ displayed.
+
+
+File: emacs, Node: Other New Modes, Next: Key Sequence Changes, Prev: Debuggers, Up: Version 19
+
+Other New Modes
+===============
+
+ There is now a Perl mode for editing Perl programs and an Icon mode
+for editing Icon programs.
+
+ C++ mode is like C mode, except that it understands C++ comment
+syntax and certain other differences between C and C++. It also has a
+command `fill-c++-comment' which fills a paragraph made of comment
+lines. The command `comment-region' is useful in C++ mode for commenting
+out several consecutive lines, or removing the commenting out of such
+lines.
+
+ WordStar emulation is available--type `M-x wordstar-mode'. For more
+information, type `C-h f wordstar-mode RET'.
+
+ The command `C-o' in Buffer Menu mode now displays the current
+line's buffer in another window but does not select it. This is like
+the existing command `o' which selects the current line's buffer in
+another window.
+
+* Menu:
+
+* Asm Mode:: A major mode for editing assembler files.
+* Edebug Mode:: A new Lisp debugger.
+* Editing Binary Files::Hexl mode lets you edit a binary file as numbers.
+
+
+File: emacs, Node: Asm Mode, Next: Edebug Mode, Up: Other New Modes
+
+Asm Mode
+--------
+
+ Asm mode is a new major mode for editing files of assembler code. It
+defines these commands:
+
+`TAB'
+ `tab-to-tab-stop'.
+
+`LFD'
+ Insert a newline and then indent using `tab-to-tab-stop'.
+
+`:'
+ Insert a colon and then remove the indentation from before the
+ label preceding colon. Then do `tab-to-tab-stop'.
+
+`;'
+ Insert or align a comment.
+
+
+File: emacs, Node: Edebug Mode, Next: Editing Binary Files, Prev: Asm Mode, Up: Other New Modes
+
+Edebug Mode
+-----------
+
+ Edebug is a new source-level debugger for Emacs Lisp programs.
+
+ To use Edebug, use the command `M-x edebug-defun' to "evaluate" a
+function definition in an Emacs Lisp file. We put "evaluate" in
+quotation marks because it doesn't just evaluate the function, it also
+inserts additional information to support source-level debugging.
+
+ You must also do this:
+
+ (setq debugger 'edebug-debug)
+
+to cause errors and single-stepping to use Edebug instead of the usual
+Emacs Lisp debugger.
+
+ For more information, see `The Emacs Extensions Manual', which
+should be included in the Emacs 19 distribution.
+
+
+File: emacs, Node: Editing Binary Files, Prev: Edebug Mode, Up: Other New Modes
+
+Editing Binary Files
+--------------------
+
+ There is a new major mode for editing binary files: Hexl mode. To
+use it, use `M-x hexl-find-file' instead of `C-x C-f' to visit the
+file. This command converts the file's contents to hexadecimal and lets
+you edit the translation. When you save the file, it is converted
+automatically back to binary.
+
+ You can also use `M-x hexl-mode' to translate an existing buffer
+into hex. This is useful if you visit a file normally and discover it
+is a binary file.
+
+ Hexl mode has a few other commands:
+
+`C-M-d'
+ Insert a byte with a code typed in decimal.
+
+`C-M-o'
+ Insert a byte with a code typed in octal.
+
+`C-M-x'
+ Insert a byte with a code typed in hex.
+
+`C-x ['
+ Move to the beginning of a 1k-byte "page".
+
+`C-x ]'
+ Move to the end of a 1k-byte "page".
+
+`M-g'
+ Move to an address specified in hex.
+
+`M-j'
+ Move to an address specified in decimal.
+
+`C-c C-c'
+ Leave Hexl mode, going back to the major mode this buffer had
+ before you invoked `hexl-mode'.
+
+
+File: emacs, Node: Key Sequence Changes, Next: Hook Changes, Prev: Other New Modes, Up: Version 19
+
+Changes in Key Sequences
+========================
+
+ In Emacs 18, a key sequence was a sequence of characters, which
+represented keyboard input.
+
+ In Emacs 19, you can still use a sequence of characters as a key
+sequence, but you aren't limited to characters. You can also use Lisp
+symbols which represent terminal function keys or mouse buttons. If the
+function key has a word as its label, then that word is also the name of
+the symbol which represents the function key. Other function keys are
+assigned Lisp names as follows:
+
+`kp-add', `kp-decimal', `kp-divide', ...
+ Keypad keys (to the right of the regular keyboard), with names or
+ punctuation
+
+`kp-0', `kp-1', ...
+ Keypad keys with digits
+
+`kp-f1', `kp-f2', `kp-f3', `kp-f4'
+ Keypad PF keys
+
+`left', `up', `right', `down'
+ Cursor arrow keys
+
+ A key sequence which contains non-characters must be a vector rather
+than a string.
+
+ Thus, to bind function key `f1' to `rmail', write the following:
+
+ (global-set-key [f1] 'rmail)
+
+(To find the name of a key, type `C-h k' and then the key.)
+
+ To bind the right-arrow key to the command `forward-char', you can
+use this expression:
+
+ (global-set-key [right] 'forward-char)
+
+using the Lisp syntax for a vector containing the symbol `right'.
+
+ And this is how to make `C-x RIGHTARROW' move forward a page:
+
+ (global-set-key [?\C-x right] 'forward-page)
+
+where `?\C-x' is the Lisp syntax for an integer whose value is the code
+for the character `C-x'.
+
+ You can use modifier keys such as CTRL, META and SHIFT with function
+keys. To represent these modifiers, prepend the strings `C-', `M-' and
+`S-' to the symbol name. Thus, here is how to make `M-RIGHTARROW' move
+forward a word:
+
+ (global-set-key [M-right] 'forward-word)
+
+ Emacs uses symbols to designate mouse buttons, too. The ordinary
+mouse events in Emacs are "click" events; these happen when you press a
+button and release it without moving the mouse. You can also get "drag"
+events, when you move the mouse while holding the button down. Drag
+events happen when you finally let go of the button.
+
+ The symbols for basic click events are `mouse-1' for the leftmost
+button, `mouse-2' for the next, and so on. Here is how you can
+redefine the second mouse button to split the current window:
+
+ (global-set-key [mouse-2] 'split-window-vertically)
+
+ The symbols for drag events are similar, but have the prefix `drag-'
+before the word `mouse'. For example, dragging the left button
+generates a `drag-mouse-1' event.
+
+ You can also request events when the mouse button is pressed down.
+These events start with `down-' instead of `drag-'. Such events are
+generated only if they have key bindings. When you get a button-down
+event, a corresponding click or drag event will always follow.
+
+ The symbols for mouse events also indicate the status of the modifier
+keys, with the usual prefixes `C-', `M-' and `S-'. These always follow
+`drag-' or `down-'.
+
+ When mouse events occur in special parts of a frame or window, such
+as a mode line or a scroll bar, the event symbol shows nothing special.
+ The information about the special part is implicit in other data (the
+screen location of the event). But `read-key-sequence' figures out this
+aspect of the event, and encodes it with make-believe prefix keys, all
+of which are symbols: `mode-line', `vertical-line',
+`horizontal-scrollbar' and `vertical-scrollbar'. Thus, to define the
+command for clicking the left button in a mode line, you could use this
+key sequence:
+
+ [mode-line mouse-1]
+
+ You are not limited to defining individual function keys or mouse
+buttons; these can appear anywhere in a key sequence, just as characters
+can. You can even mix together all three kinds of inputs in one key
+sequence--but mixing mouse buttons with keyboard inputs is probably not
+convenient for actual use.
+
+
+File: emacs, Node: Hook Changes, Prev: Key Sequence Changes, Up: Version 19
+
+Changes Regarding Hooks
+=======================
+
+ A "hook variable" is a variable that exists so that you can store in
+it functions for Emacs to call on certain occasions. (The functions
+that you put in hook variables are called "hook functions".) Emacs 19
+has a new convention for naming hook variables that indicates more
+reliably how to use them.
+
+ All the variables whose names end in `-hook' are "normal hooks";
+their values are lists of functions to be called with no arguments.
+You can use `add-hook' (see below) to install hook functions in these
+hooks. We have made all Emacs hooks into normal hooks except when
+there is some reason this won't work.
+
+ A few hook-like variables are "abnormal"--they don't use the normal
+convention. This is either because the user-supplied functions receive
+arguments, or because their return values matter. These variables have
+names that end in `-function' (if the value is a single function) or
+`-functions' (if the value is a list of functions).
+
+ Thus, you can always tell from the variable's name precisely how to
+install a new hook function in the variable. If the name indicates a
+normal hook, then you also know how to write your hook function.
+
+ To add a hook function to a normal hook, use `add-hook'. It takes
+care of adding a new hook function to any functions already installed in
+a given hook. It takes two arguments, the hook symbol and the function
+to add. For example,
+
+ (add-hook 'text-mode-hook 'my-text-hook-function)
+
+is how to arrange to call `my-text-hook-function' when entering Text
+mode or related modes. Two new hooks are worth noting here. Expansion
+of an abbrev first runs the hook `pre-abbrev-expand-hook'.
+`kill-buffer-hook' now runs whenever a buffer is killed.
+
+ \ No newline at end of file
diff --git a/info/emacs-15 b/info/emacs-15
new file mode 100644
index 00000000000..c8d46c939ba
--- /dev/null
+++ b/info/emacs-15
@@ -0,0 +1,503 @@
+This is Info file ../info/emacs, produced by Makeinfo-1.49 from the
+input file emacs.texi.
+
+ This file documents the GNU Emacs editor.
+
+ Copyright (C) 1985, 1986, 1988, 1992 Richard M. Stallman.
+
+ Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+ Permission is granted to copy and distribute modified versions of
+this manual under the conditions for verbatim copying, provided also
+that the sections entitled "The GNU Manifesto", "Distribution" and "GNU
+General Public License" are included exactly as in the original, and
+provided that the entire resulting derived work is distributed under the
+terms of a permission notice identical to this one.
+
+ Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that the sections entitled "The GNU Manifesto",
+"Distribution" and "GNU General Public License" may be included in a
+translation approved by the author instead of in the original English.
+
+
+File: emacs, Node: Manifesto, Prev: Version 19, Up: Top
+
+The GNU Manifesto
+*****************
+
+ By Richard M. Stallman, 1986
+
+What's GNU? Gnu's Not Unix!
+============================
+
+ GNU, which stands for Gnu's Not Unix, is the name for the complete
+Unix-compatible software system which I am writing so that I can give it
+away free to everyone who can use it. Several other volunteers are
+helping me. Contributions of time, money, programs and equipment are
+greatly needed.
+
+ So far we have an Emacs text editor with Lisp for writing editor
+commands, a source level debugger, a yacc-compatible parser generator,
+a linker, and around 35 utilities. A shell (command interpreter) is
+nearly completed. A new portable optimizing C compiler has compiled
+itself and may be released this year. An initial kernel exists but
+many more features are needed to emulate Unix. When the kernel and
+compiler are finished, it will be possible to distribute a GNU system
+suitable for program development. We will use TeX as our text
+formatter, but an nroff is being worked on. We will use the free,
+portable X window system as well. After this we will add a portable
+Common Lisp, an Empire game, a spreadsheet, and hundreds of other
+things, plus on-line documentation. We hope to supply, eventually,
+everything useful that normally comes with a Unix system, and more.
+
+ GNU will be able to run Unix programs, but will not be identical to
+Unix. We will make all improvements that are convenient, based on our
+experience with other operating systems. In particular, we plan to
+have longer filenames, file version numbers, a crashproof file system,
+filename completion perhaps, terminal-independent display support, and
+perhaps eventually a Lisp-based window system through which several
+Lisp programs and ordinary Unix programs can share a screen. Both C
+and Lisp will be available as system programming languages. We will
+try to support UUCP, MIT Chaosnet, and Internet protocols for
+communication.
+
+ GNU is aimed initially at machines in the 68000/16000 class with
+virtual memory, because they are the easiest machines to make it run
+on. The extra effort to make it run on smaller machines will be left
+to someone who wants to use it on them.
+
+ To avoid horrible confusion, please pronounce the `G' in the word
+`GNU' when it is the name of this project.
+
+Why I Must Write GNU
+====================
+
+ I consider that the golden rule requires that if I like a program I
+must share it with other people who like it. Software sellers want to
+divide the users and conquer them, making each user agree not to share
+with others. I refuse to break solidarity with other users in this
+way. I cannot in good conscience sign a nondisclosure agreement or a
+software license agreement. For years I worked within the Artificial
+Intelligence Lab to resist such tendencies and other inhospitalities,
+but eventually they had gone too far: I could not remain in an
+institution where such things are done for me against my will.
+
+ So that I can continue to use computers without dishonor, I have
+decided to put together a sufficient body of free software so that I
+will be able to get along without any software that is not free. I
+have resigned from the AI lab to deny MIT any legal excuse to prevent
+me from giving GNU away.
+
+Why GNU Will Be Compatible with Unix
+====================================
+
+ Unix is not my ideal system, but it is not too bad. The essential
+features of Unix seem to be good ones, and I think I can fill in what
+Unix lacks without spoiling them. And a system compatible with Unix
+would be convenient for many other people to adopt.
+
+How GNU Will Be Available
+=========================
+
+ GNU is not in the public domain. Everyone will be permitted to
+modify and redistribute GNU, but no distributor will be allowed to
+restrict its further redistribution. That is to say, proprietary
+modifications will not be allowed. I want to make sure that all
+versions of GNU remain free.
+
+Why Many Other Programmers Want to Help
+=======================================
+
+ I have found many other programmers who are excited about GNU and
+want to help.
+
+ Many programmers are unhappy about the commercialization of system
+software. It may enable them to make more money, but it requires them
+to feel in conflict with other programmers in general rather than feel
+as comrades. The fundamental act of friendship among programmers is the
+sharing of programs; marketing arrangements now typically used
+essentially forbid programmers to treat others as friends. The
+purchaser of software must choose between friendship and obeying the
+law. Naturally, many decide that friendship is more important. But
+those who believe in law often do not feel at ease with either choice.
+They become cynical and think that programming is just a way of making
+money.
+
+ By working on and using GNU rather than proprietary programs, we can
+be hospitable to everyone and obey the law. In addition, GNU serves as
+an example to inspire and a banner to rally others to join us in
+sharing. This can give us a feeling of harmony which is impossible if
+we use software that is not free. For about half the programmers I
+talk to, this is an important happiness that money cannot replace.
+
+How You Can Contribute
+======================
+
+ I am asking computer manufacturers for donations of machines and
+money. I'm asking individuals for donations of programs and work.
+
+ One consequence you can expect if you donate machines is that GNU
+will run on them at an early date. The machines should be complete,
+ready to use systems, approved for use in a residential area, and not
+in need of sophisticated cooling or power.
+
+ I have found very many programmers eager to contribute part-time
+work for GNU. For most projects, such part-time distributed work would
+be very hard to coordinate; the independently-written parts would not
+work together. But for the particular task of replacing Unix, this
+problem is absent. A complete Unix system contains hundreds of utility
+programs, each of which is documented separately. Most interface
+specifications are fixed by Unix compatibility. If each contributor
+can write a compatible replacement for a single Unix utility, and make
+it work properly in place of the original on a Unix system, then these
+utilities will work right when put together. Even allowing for Murphy
+to create a few unexpected problems, assembling these components will
+be a feasible task. (The kernel will require closer communication and
+will be worked on by a small, tight group.)
+
+ If I get donations of money, I may be able to hire a few people full
+or part time. The salary won't be high by programmers' standards, but
+I'm looking for people for whom building community spirit is as
+important as making money. I view this as a way of enabling dedicated
+people to devote their full energies to working on GNU by sparing them
+the need to make a living in another way.
+
+Why All Computer Users Will Benefit
+===================================
+
+ Once GNU is written, everyone will be able to obtain good system
+software free, just like air.
+
+ This means much more than just saving everyone the price of a Unix
+license. It means that much wasteful duplication of system programming
+effort will be avoided. This effort can go instead into advancing the
+state of the art.
+
+ Complete system sources will be available to everyone. As a result,
+a user who needs changes in the system will always be free to make them
+himself, or hire any available programmer or company to make them for
+him. Users will no longer be at the mercy of one programmer or company
+which owns the sources and is in sole position to make changes.
+
+ Schools will be able to provide a much more educational environment
+by encouraging all students to study and improve the system code.
+Harvard's computer lab used to have the policy that no program could be
+installed on the system if its sources were not on public display, and
+upheld it by actually refusing to install certain programs. I was very
+much inspired by this.
+
+ Finally, the overhead of considering who owns the system software
+and what one is or is not entitled to do with it will be lifted.
+
+ Arrangements to make people pay for using a program, including
+licensing of copies, always incur a tremendous cost to society through
+the cumbersome mechanisms necessary to figure out how much (that is,
+which programs) a person must pay for. And only a police state can
+force everyone to obey them. Consider a space station where air must
+be manufactured at great cost: charging each breather per liter of air
+may be fair, but wearing the metered gas mask all day and all night is
+intolerable even if everyone can afford to pay the air bill. And the
+TV cameras everywhere to see if you ever take the mask off are
+outrageous. It's better to support the air plant with a head tax and
+chuck the masks.
+
+ Copying all or parts of a program is as natural to a programmer as
+breathing, and as productive. It ought to be as free.
+
+Some Easily Rebutted Objections to GNU's Goals
+==============================================
+
+ "Nobody will use it if it is free, because that means they can't
+ rely on any support."
+
+ "You have to charge for the program to pay for providing the
+ support."
+
+ If people would rather pay for GNU plus service than get GNU free
+without service, a company to provide just service to people who have
+obtained GNU free ought to be profitable.
+
+ We must distinguish between support in the form of real programming
+work and mere handholding. The former is something one cannot rely on
+from a software vendor. If your problem is not shared by enough
+people, the vendor will tell you to get lost.
+
+ If your business needs to be able to rely on support, the only way
+is to have all the necessary sources and tools. Then you can hire any
+available person to fix your problem; you are not at the mercy of any
+individual. With Unix, the price of sources puts this out of
+consideration for most businesses. With GNU this will be easy. It is
+still possible for there to be no available competent person, but this
+problem cannot be blamed on distribution arrangements. GNU does not
+eliminate all the world's problems, only some of them.
+
+ Meanwhile, the users who know nothing about computers need
+handholding: doing things for them which they could easily do
+themselves but don't know how.
+
+ Such services could be provided by companies that sell just
+hand-holding and repair service. If it is true that users would rather
+spend money and get a product with service, they will also be willing
+to buy the service having got the product free. The service companies
+will compete in quality and price; users will not be tied to any
+particular one. Meanwhile, those of us who don't need the service
+should be able to use the program without paying for the service.
+
+ "You cannot reach many people without advertising, and you must
+ charge for the program to support that."
+
+ "It's no use advertising a program people can get free."
+
+ There are various forms of free or very cheap publicity that can be
+used to inform numbers of computer users about something like GNU. But
+it may be true that one can reach more microcomputer users with
+advertising. If this is really so, a business which advertises the
+service of copying and mailing GNU for a fee ought to be successful
+enough to pay for its advertising and more. This way, only the users
+who benefit from the advertising pay for it.
+
+ On the other hand, if many people get GNU from their friends, and
+such companies don't succeed, this will show that advertising was not
+really necessary to spread GNU. Why is it that free market advocates
+don't want to let the free market decide this?
+
+ "My company needs a proprietary operating system to get a
+ competitive edge."
+
+ GNU will remove operating system software from the realm of
+competition. You will not be able to get an edge in this area, but
+neither will your competitors be able to get an edge over you. You and
+they will compete in other areas, while benefitting mutually in this
+one. If your business is selling an operating system, you will not
+like GNU, but that's tough on you. If your business is something else,
+GNU can save you from being pushed into the expensive business of
+selling operating systems.
+
+ I would like to see GNU development supported by gifts from many
+manufacturers and users, reducing the cost to each.
+
+ "Don't programmers deserve a reward for their creativity?"
+
+ If anything deserves a reward, it is social contribution.
+Creativity can be a social contribution, but only in so far as society
+is free to use the results. If programmers deserve to be rewarded for
+creating innovative programs, by the same token they deserve to be
+punished if they restrict the use of these programs.
+
+ "Shouldn't a programmer be able to ask for a reward for his
+ creativity?"
+
+ There is nothing wrong with wanting pay for work, or seeking to
+maximize one's income, as long as one does not use means that are
+destructive. But the means customary in the field of software today
+are based on destruction.
+
+ Extracting money from users of a program by restricting their use of
+it is destructive because the restrictions reduce the amount and the
+ways that the program can be used. This reduces the amount of wealth
+that humanity derives from the program. When there is a deliberate
+choice to restrict, the harmful consequences are deliberate destruction.
+
+ The reason a good citizen does not use such destructive means to
+become wealthier is that, if everyone did so, we would all become
+poorer from the mutual destructiveness. This is Kantian ethics; or,
+the Golden Rule. Since I do not like the consequences that result if
+everyone hoards information, I am required to consider it wrong for one
+to do so. Specifically, the desire to be rewarded for one's creativity
+does not justify depriving the world in general of all or part of that
+creativity.
+
+ "Won't programmers starve?"
+
+ I could answer that nobody is forced to be a programmer. Most of us
+cannot manage to get any money for standing on the street and making
+faces. But we are not, as a result, condemned to spend our lives
+standing on the street making faces, and starving. We do something
+else.
+
+ But that is the wrong answer because it accepts the questioner's
+implicit assumption: that without ownership of software, programmers
+cannot possibly be paid a cent. Supposedly it is all or nothing.
+
+ The real reason programmers will not starve is that it will still be
+possible for them to get paid for programming; just not paid as much as
+now.
+
+ Restricting copying is not the only basis for business in software.
+It is the most common basis because it brings in the most money. If it
+were prohibited, or rejected by the customer, software business would
+move to other bases of organization which are now used less often.
+There are always numerous ways to organize any kind of business.
+
+ Probably programming will not be as lucrative on the new basis as it
+is now. But that is not an argument against the change. It is not
+considered an injustice that sales clerks make the salaries that they
+now do. If programmers made the same, that would not be an injustice
+either. (In practice they would still make considerably more than
+that.)
+
+ "Don't people have a right to control how their creativity is
+ used?"
+
+ "Control over the use of one's ideas" really constitutes control over
+other people's lives; and it is usually used to make their lives more
+difficult.
+
+ People who have studied the issue of intellectual property rights
+carefully (such as lawyers) say that there is no intrinsic right to
+intellectual property. The kinds of supposed intellectual property
+rights that the government recognizes were created by specific acts of
+legislation for specific purposes.
+
+ For example, the patent system was established to encourage
+inventors to disclose the details of their inventions. Its purpose was
+to help society rather than to help inventors. At the time, the life
+span of 17 years for a patent was short compared with the rate of
+advance of the state of the art. Since patents are an issue only among
+manufacturers, for whom the cost and effort of a license agreement are
+small compared with setting up production, the patents often do not do
+much harm. They do not obstruct most individuals who use patented
+products.
+
+ The idea of copyright did not exist in ancient times, when authors
+frequently copied other authors at length in works of non-fiction. This
+practice was useful, and is the only way many authors' works have
+survived even in part. The copyright system was created expressly for
+the purpose of encouraging authorship. In the domain for which it was
+invented--books, which could be copied economically only on a printing
+press--it did little harm, and did not obstruct most of the individuals
+who read the books.
+
+ All intellectual property rights are just licenses granted by society
+because it was thought, rightly or wrongly, that society as a whole
+would benefit by granting them. But in any particular situation, we
+have to ask: are we really better off granting such license? What kind
+of act are we licensing a person to do?
+
+ The case of programs today is very different from that of books a
+hundred years ago. The fact that the easiest way to copy a program is
+from one neighbor to another, the fact that a program has both source
+code and object code which are distinct, and the fact that a program is
+used rather than read and enjoyed, combine to create a situation in
+which a person who enforces a copyright is harming society as a whole
+both materially and spiritually; in which a person should not do so
+regardless of whether the law enables him to.
+
+ "Competition makes things get done better."
+
+ The paradigm of competition is a race: by rewarding the winner, we
+encourage everyone to run faster. When capitalism really works this
+way, it does a good job; but its defenders are wrong in assuming it
+always works this way. If the runners forget why the reward is offered
+and become intent on winning, no matter how, they may find other
+strategies--such as, attacking other runners. If the runners get into
+a fist fight, they will all finish late.
+
+ Proprietary and secret software is the moral equivalent of runners
+in a fist fight. Sad to say, the only referee we've got does not seem
+to object to fights; he just regulates them ("For every ten yards you
+run, you can fire one shot"). He really ought to break them up, and
+penalize runners for even trying to fight.
+
+ "Won't everyone stop programming without a monetary incentive?"
+
+ Actually, many people will program with absolutely no monetary
+incentive. Programming has an irresistible fascination for some people,
+usually the people who are best at it. There is no shortage of
+professional musicians who keep at it even though they have no hope of
+making a living that way.
+
+ But really this question, though commonly asked, is not appropriate
+to the situation. Pay for programmers will not disappear, only become
+less. So the right question is, will anyone program with a reduced
+monetary incentive? My experience shows that they will.
+
+ For more than ten years, many of the world's best programmers worked
+at the Artificial Intelligence Lab for far less money than they could
+have had anywhere else. They got many kinds of non-monetary rewards:
+fame and appreciation, for example. And creativity is also fun, a
+reward in itself.
+
+ Then most of them left when offered a chance to do the same
+interesting work for a lot of money.
+
+ What the facts show is that people will program for reasons other
+than riches; but if given a chance to make a lot of money as well, they
+will come to expect and demand it. Low-paying organizations do poorly
+in competition with high-paying ones, but they do not have to do badly
+if the high-paying ones are banned.
+
+ "We need the programmers desperately. If they demand that we stop
+ helping our neighbors, we have to obey."
+
+ You're never so desperate that you have to obey this sort of demand.
+Remember: millions for defense, but not a cent for tribute!
+
+ "Programmers need to make a living somehow."
+
+ In the short run, this is true. However, there are plenty of ways
+that programmers could make a living without selling the right to use a
+program. This way is customary now because it brings programmers and
+businessmen the most money, not because it is the only way to make a
+living. It is easy to find other ways if you want to find them. Here
+are a number of examples.
+
+ A manufacturer introducing a new computer will pay for the porting of
+operating systems onto the new hardware.
+
+ The sale of teaching, hand-holding and maintenance services could
+also employ programmers.
+
+ People with new ideas could distribute programs as freeware, asking
+for donations from satisfied users, or selling hand-holding services.
+I have met people who are already working this way successfully.
+
+ Users with related needs can form users' groups, and pay dues. A
+group would contract with programming companies to write programs that
+the group's members would like to use.
+
+ All sorts of development can be funded with a Software Tax:
+
+ Suppose everyone who buys a computer has to pay x percent of the
+ price as a software tax. The government gives this to an agency
+ like the NSF to spend on software development.
+
+ But if the computer buyer makes a donation to software development
+ himself, he can take a credit against the tax. He can donate to
+ the project of his own choosing--often, chosen because he hopes to
+ use the results when it is done. He can take a credit for any
+ amount of donation up to the total tax he had to pay.
+
+ The total tax rate could be decided by a vote of the payers of the
+ tax, weighted according to the amount they will be taxed on.
+
+ The consequences:
+
+ * The computer-using community supports software development.
+
+ * This community decides what level of support is needed.
+
+ * Users who care which projects their share is spent on can
+ choose this for themselves.
+
+ In the long run, making programs free is a step toward the
+post-scarcity world, where nobody will have to work very hard just to
+make a living. People will be free to devote themselves to activities
+that are fun, such as programming, after spending the necessary ten
+hours a week on required tasks such as legislation, family counseling,
+robot repair and asteroid prospecting. There will be no need to be
+able to make a living from programming.
+
+ We have already greatly reduced the amount of work that the whole
+society must do for its actual productivity, but only a little of this
+has translated itself into leisure for workers because much
+nonproductive activity is required to accompany productive activity.
+The main causes of this are bureaucracy and isometric struggles against
+competition. Free software will greatly reduce these drains in the
+area of software production. We must do this, in order for technical
+gains in productivity to translate into less work for us.
+
+ \ No newline at end of file
diff --git a/info/emacs-16 b/info/emacs-16
new file mode 100644
index 00000000000..9fcc0448be8
--- /dev/null
+++ b/info/emacs-16
@@ -0,0 +1,797 @@
+This is Info file ../info/emacs, produced by Makeinfo-1.49 from the
+input file emacs.texi.
+
+ This file documents the GNU Emacs editor.
+
+ Copyright (C) 1985, 1986, 1988, 1992 Richard M. Stallman.
+
+ Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+ Permission is granted to copy and distribute modified versions of
+this manual under the conditions for verbatim copying, provided also
+that the sections entitled "The GNU Manifesto", "Distribution" and "GNU
+General Public License" are included exactly as in the original, and
+provided that the entire resulting derived work is distributed under the
+terms of a permission notice identical to this one.
+
+ Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that the sections entitled "The GNU Manifesto",
+"Distribution" and "GNU General Public License" may be included in a
+translation approved by the author instead of in the original English.
+
+
+File: emacs, Node: Glossary, Next: Key Index, Prev: Intro, Up: Top
+
+Glossary
+********
+
+Abbrev
+ An abbrev is a text string which expands into a different text
+ string when present in the buffer. For example, you might define
+ a short word as an abbrev for a long phrase that you want to insert
+ frequently. *Note Abbrevs::.
+
+Aborting
+ Aborting means getting out of a recursive edit (q.v.). The
+ commands `C-]' and `M-x top-level' are used for this. *Note
+ Quitting::.
+
+Auto Fill mode
+ Auto Fill mode is a minor mode in which text that you insert is
+ automatically broken into lines of fixed width. *Note Filling::.
+
+Auto Saving
+ Auto saving is when Emacs automatically stores the contents of an
+ Emacs buffer in a specially-named file so that the information will
+ not be lost if the buffer is lost due to a system error or user
+ error. *Note Auto Save::.
+
+Backup File
+ A backup file records the contents that a file had before the
+ current editing session. Emacs makes backup files automatically
+ to help you track down or cancel changes you later regret making.
+ *Note Backup::.
+
+Balance Parentheses
+ Emacs can balance parentheses manually or automatically. Manual
+ balancing is done by the commands to move over balanced expressions
+ (*note Lists::.). Automatic balancing is done by blinking the
+ parenthesis that matches one just inserted (*note Matching Parens:
+ Matching.).
+
+Bind
+ To bind a key is to change its binding (q.v.). *Note Rebinding::.
+
+Binding
+ A key gets its meaning in Emacs by having a binding which is a
+ command (q.v.), a Lisp function that is run when the key is typed.
+ *Note Binding: Commands. Customization often involves rebinding a
+ character to a different command function. The bindings of all
+ keys are recorded in the keymaps (q.v.). *Note Keymaps::.
+
+Blank Lines
+ Blank lines are lines that contain only whitespace. Emacs has
+ several commands for operating on the blank lines in the buffer.
+
+Buffer
+ The buffer is the basic editing unit; one buffer corresponds to one
+ piece of text being edited. You can have several buffers, but at
+ any time you are editing only one, the `selected' buffer, though
+ several can be visible when you are using multiple windows. *Note
+ Buffers::.
+
+Buffer Selection History
+ Emacs keeps a buffer selection history which records how recently
+ each Emacs buffer has been selected. This is used for choosing a
+ buffer to select. *Note Buffers::.
+
+C-
+ `C' in the name of a character is an abbreviation for Control.
+ *Note C-: Characters.
+
+C-M-
+ `C-M-' in the name of a character is an abbreviation for
+ Control-Meta. *Note C-M-: Characters.
+
+Case Conversion
+ Case conversion means changing text from upper case to lower case
+ or vice versa. *Note Case::, for the commands for case conversion.
+
+Characters
+ Characters form the contents of an Emacs buffer; also, Emacs
+ commands are invoked by keys (q.v.), which are sequences of one or
+ more characters. *Note Characters::.
+
+Command
+ A command is a Lisp function specially defined to be able to serve
+ as a key binding in Emacs. When you type a key (q.v.), its binding
+ (q.v.) is looked up in the relevant keymaps (q.v.) to find the
+ command to run. *Note Commands::.
+
+Command Name
+ A command name is the name of a Lisp symbol which is a command
+ (*note Commands::.). You can invoke any command by its name using
+ `M-x' (*note M-x::.).
+
+Comments
+ A comment is text in a program which is intended only for humans
+ reading the program, and is marked specially so that it will be
+ ignored when the program is loaded or compiled. Emacs offers
+ special commands for creating, aligning and killing comments.
+ *Note Comments::.
+
+Compilation
+ Compilation is the process of creating an executable program from
+ source code. Emacs has commands for compiling files of Emacs Lisp
+ code (*note Lisp Libraries::.) and programs in C and other
+ languages (*note Compilation::.).
+
+Complete Key
+ A complete key is a character or sequence of characters which,
+ when typed by the user, fully specifies one action to be performed
+ by Emacs. For example, `X' and `Control-f' and `Control-x m' are
+ keys. Keys derive their meanings from being bound (q.v.) to
+ commands (q.v.). Thus, `X' is conventionally bound to a command to
+ insert `X' in the buffer; `C-x m' is conventionally bound to a
+ command to begin composing a mail message. *Note Keys::.
+
+Completion
+ Completion is what Emacs does when it automatically fills out an
+ abbreviation for a name into the entire name. Completion is done
+ for minibuffer (q.v.) arguments when the set of possible valid
+ inputs is known; for example, on command names, buffer names, and
+ file names. Completion occurs when TAB, SPC or RET is typed.
+ *Note Completion::.
+
+Continuation Line
+ When a line of text is longer than the width of the screen, it
+ takes up more than one screen line when displayed. We say that the
+ text line is continued, and all screen lines used for it after the
+ first are called continuation lines. *Note Continuation: Basic.
+
+Control-Character
+ ASCII characters with octal codes 0 through 037, and also code
+ 0177, do not have graphic images assigned to them. These are the
+ control characters. Any control character can be typed by holding
+ down the CTRL key and typing some other character; some have
+ special keys on the keyboard. RET, TAB, ESC, LFD and DEL are all
+ control characters. *Note Characters::.
+
+Copyleft
+ A copyleft is a notice giving the public legal permission to
+ redistribute a program or other work of art. Copylefts are used
+ by leftists to enrich the public just as copyrights are used by
+ rightists to gain power over the public.
+
+Current Buffer
+ The current buffer in Emacs is the Emacs buffer on which most
+ editing commands operate. You can select any Emacs buffer as the
+ current one. *Note Buffers::.
+
+Current Line
+ The line point is on (*note Point::.).
+
+Current Paragraph
+ The paragraph that point is in. If point is between paragraphs,
+ the current paragraph is the one that follows point. *Note
+ Paragraphs::.
+
+Current Defun
+ The defun (q.v.) that point is in. If point is between defuns, the
+ current defun is the one that follows point. *Note Defuns::.
+
+Cursor
+ The cursor is the rectangle on the screen which indicates the
+ position called point (q.v.) at which insertion and deletion takes
+ place. The cursor is on or under the character that follows point.
+ Often people speak of `the cursor' when, strictly speaking, they
+ mean `point'. *Note Cursor: Basic.
+
+Customization
+ Customization is making minor changes in the way Emacs works. It
+ is often done by setting variables (*note Variables::.) or by
+ rebinding keys (*note Keymaps::.).
+
+Default Argument
+ The default for an argument is the value that will be assumed if
+ you do not specify one. When the minibuffer is used to read an
+ argument, the default argument is used if you just type RET. *Note
+ Minibuffer::.
+
+Default Directory
+ When you specify a file name that does not start with `/' or `~',
+ it is interpreted relative to the current buffer's default
+ directory. *Note Default Directory: Minibuffer File.
+
+Defun
+ A defun is a list at the top level of parenthesis or bracket
+ structure in a program. It is so named because most such lists in
+ Lisp programs are calls to the Lisp function `defun'. *Note
+ Defuns::.
+
+DEL
+ DEL is a character that runs the command to delete one character of
+ text. *Note DEL: Basic.
+
+Deletion
+ Deletion means erasing text without saving it. Emacs deletes text
+ only when it is expected not to be worth saving (all whitespace, or
+ only one character). The alternative is killing (q.v.). *Note
+ Deletion: Killing.
+
+Deletion of Files
+ Deleting a file means erasing it from the file system. *Note Misc
+ File Ops::.
+
+Deletion of Messages
+ Deleting a message means flagging it to be eliminated from your
+ mail file. This can be undone by undeletion until the mail file
+ is expunged. *Note Rmail Deletion::.
+
+Deletion of Windows
+ Deleting a window means eliminating it from the screen. Other
+ windows expand to use up the space. The deleted window can never
+ come back, but no actual text is thereby lost. *Note Windows::.
+
+Directory
+ Files in the Unix file system are grouped into file directories.
+ *Note Directories: ListDir.
+
+Dired
+ Dired is the Emacs facility that displays the contents of a file
+ directory and allows you to "edit the directory", performing
+ operations on the files in the directory. *Note Dired::.
+
+Disabled Command
+ A disabled command is one that you may not run without special
+ confirmation. The usual reason for disabling a command is that it
+ is confusing for beginning users. *Note Disabling::.
+
+Dribble File
+ A file into which Emacs writes all the characters that the user
+ types on the keyboard. Dribble files are used to make a record for
+ debugging Emacs bugs. Emacs does not make a dribble file unless
+ you tell it to. *Note Bugs::.
+
+Echo Area
+ The echo area is the bottom line of the screen, used for echoing
+ the arguments to commands, for asking questions, and printing brief
+ messages (including error messages). *Note Echo Area::.
+
+Echoing
+ Echoing is acknowledging the receipt of commands by displaying them
+ (in the echo area). Emacs never echoes single-character keys;
+ longer keys echo only if you pause while typing them.
+
+Error
+ An error occurs when an Emacs command cannot execute in the current
+ circumstances. When an error occurs, execution of the command
+ stops (unless the command has been programmed to do otherwise) and
+ Emacs reports the error by printing an error message (q.v.).
+ Type-ahead is discarded. Then Emacs is ready to read another
+ editing command.
+
+Error Messages
+ Error messages are single lines of output printed by Emacs when the
+ user asks for something impossible to do (such as, killing text
+ forward when point is at the end of the buffer). They appear in
+ the echo area, accompanied by a beep.
+
+ESC
+ ESC is a character, used to end incremental searches and as a
+ prefix for typing Meta characters on keyboards lacking a META key.
+ Unlike the META key (which, like the SHIFT key, is held down
+ while another character is typed), the ESC key is pressed once and
+ applies to the next character typed.
+
+Fill Prefix
+ The fill prefix is a string that should be expected at the
+ beginning of each line when filling is done. It is not regarded
+ as part of the text to be filled. *Note Filling::.
+
+Filling
+ Filling text means moving text from line to line so that all the
+ lines are approximately the same length. *Note Filling::.
+
+Global
+ Global means `independent of the current environment; in effect
+ throughout Emacs'. It is the opposite of local (q.v.). Particular
+ examples of the use of `global' appear below.
+
+Global Abbrev
+ A global definition of an abbrev (q.v.) is effective in all major
+ modes that do not have local (q.v.) definitions for the same
+ abbrev. *Note Abbrevs::.
+
+Global Keymap
+ The global keymap (q.v.) contains key bindings that are in effect
+ except when overridden by local key bindings in a major mode's
+ local keymap (q.v.). *Note Keymaps::.
+
+Global Substitution
+ Global substitution means replacing each occurrence of one string
+ by another string through a large amount of text. *Note Replace::.
+
+Global Variable
+ The global value of a variable (q.v.) takes effect in all buffers
+ that do not have their own local (q.v.) values for the variable.
+ *Note Variables::.
+
+Graphic Character
+ Graphic characters are those assigned pictorial images rather than
+ just names. All the non-Meta (q.v.) characters except for the
+ Control (q.v.) characters are graphic characters. These include
+ letters, digits, punctuation, and spaces; they do not include RET
+ or ESC. In Emacs, typing a graphic character inserts that
+ character (in ordinary editing modes). *Note Basic Editing: Basic.
+
+Grinding
+ Grinding means adjusting the indentation in a program to fit the
+ nesting structure. *Note Grinding: Indentation.
+
+Hardcopy
+ Hardcopy means printed output. Emacs has commands for making
+ printed listings of text in Emacs buffers. *Note Hardcopy::.
+
+HELP
+ You can type HELP at any time to ask what options you have, or to
+ ask what any command does. HELP is really `Control-h'. *Note
+ Help::.
+
+Inbox
+ An inbox is a file in which mail is delivered by the operating
+ system. Rmail transfers mail from inboxes to mail files (q.v.) in
+ which the mail is then stored permanently or until explicitly
+ deleted. *Note Rmail Inbox::.
+
+Indentation
+ Indentation means blank space at the beginning of a line. Most
+ programming languages have conventions for using indentation to
+ illuminate the structure of the program, and Emacs has special
+ features to help you set up the correct indentation. *Note
+ Indentation::.
+
+Insertion
+ Insertion means copying text into the buffer, either from the
+ keyboard or from some other place in Emacs.
+
+Justification
+ Justification means adding extra spaces to lines of text to make
+ them come exactly to a specified width. *Note Justification:
+ Filling.
+
+Keyboard Macros
+ Keyboard macros are a way of defining new Emacs commands from
+ sequences of existing ones, with no need to write a Lisp program.
+ *Note Keyboard Macros::.
+
+Key
+ A key is a sequence of characters that, when input to Emacs,
+ specify or begin to specify a single action for Emacs to perform.
+ That is, the sequence is not more than a single unit. If the key
+ is enough to specify one action, it is a complete key (q.v.); if
+ it is less than enough, it is a prefix key (q.v.). *Note Keys::.
+
+Keymap
+ The keymap is the data structure that records the bindings (q.v.)
+ of keys to the commands that they run. For example, the keymap
+ binds the character `C-n' to the command function `next-line'.
+ *Note Keymaps::.
+
+Kill Ring
+ The kill ring is where all text you have killed recently is saved.
+ You can reinsert any of the killed text still in the ring; this is
+ called yanking (q.v.). *Note Yanking::.
+
+Killing
+ Killing means erasing text and saving it on the kill ring so it
+ can be yanked (q.v.) later. Some other systems call this
+ "cutting". Most Emacs commands to erase text do killing, as
+ opposed to deletion (q.v.). *Note Killing::.
+
+Killing Jobs
+ Killing a job (such as, an invocation of Emacs) means making it
+ cease to exist. Any data within it, if not saved in a file, is
+ lost. *Note Exiting::.
+
+List
+ A list is, approximately, a text string beginning with an open
+ parenthesis and ending with the matching close parenthesis. In C
+ mode and other non-Lisp modes, groupings surrounded by other kinds
+ of matched delimiters appropriate to the language, such as braces,
+ are also considered lists. Emacs has special commands for many
+ operations on lists. *Note Lists::.
+
+Local
+ Local means `in effect only in a particular context'; the relevant
+ kind of context is a particular function execution, a particular
+ buffer, or a particular major mode. It is the opposite of `global'
+ (q.v.). Specific uses of `local' in Emacs terminology appear
+ below.
+
+Local Abbrev
+ A local abbrev definition is effective only if a particular major
+ mode is selected. In that major mode, it overrides any global
+ definition for the same abbrev. *Note Abbrevs::.
+
+Local Keymap
+ A local keymap is used in a particular major mode; the key bindings
+ (q.v.) in the current local keymap override global bindings of the
+ same keys. *Note Keymaps::.
+
+Local Variable
+ A local value of a variable (q.v.) applies to only one buffer.
+ *Note Locals::.
+
+M-
+ `M-' in the name of a character is an abbreviation for META, one
+ of the modifier keys that can accompany any character. *Note
+ Characters::.
+
+M-C-
+ `M-C-' in the name of a character is an abbreviation for
+ Control-Meta; it means the same thing as `C-M-'. If your terminal
+ lacks a real META key, you type a Control-Meta character by typing
+ ESC and then typing the corresponding Control character. *Note
+ C-M-: Characters.
+
+M-x
+ `M-x' is the key which is used to call an Emacs command by name.
+ This is how commands that are not bound to keys are called. *Note
+ M-x::.
+
+Mail
+ Mail means messages sent from one user to another through the
+ computer system, to be read at the recipient's convenience. Emacs
+ has commands for composing and sending mail, and for reading and
+ editing the mail you have received. *Note Sending Mail::. *Note
+ Rmail::, for how to read mail.
+
+Mail File
+ A mail file is a file which is edited using Rmail and in which
+ Rmail stores mail. *Note Rmail::.
+
+Major Mode
+ The major modes are a mutually exclusive set of options each of
+ which configures Emacs for editing a certain sort of text.
+ Ideally, each programming language has its own major mode. *Note
+ Major Modes::.
+
+Mark
+ The mark points to a position in the text. It specifies one end of
+ the region (q.v.), point being the other end. Many commands
+ operate on all the text from point to the mark. *Note Mark::.
+
+Mark Ring
+ The mark ring is used to hold several recent previous locations of
+ the mark, just in case you want to move back to them. *Note Mark
+ Ring::.
+
+Message
+ See `mail'.
+
+Meta
+ Meta is the name of a modifier bit which a command character may
+ have. It is present in a character if the character is typed with
+ the META key held down. Such characters are given names that start
+ with `Meta-'. For example, `Meta-<' is typed by holding down META
+ and at the same time typing `<' (which itself is done, on most
+ terminals, by holding down SHIFT and typing `,'). *Note Meta:
+ Characters.
+
+Meta Character
+ A Meta character is one whose character code includes the Meta bit.
+
+Minibuffer
+ The minibuffer is the window that appears when necessary inside the
+ echo area (q.v.), used for reading arguments to commands. *Note
+ Minibuffer::.
+
+Minor Mode
+ A minor mode is an optional feature of Emacs which can be switched
+ on or off independently of all other features. Each minor mode
+ has a command to turn it on or off. *Note Minor Modes::.
+
+Mode Line
+ The mode line is the line at the bottom of each text window (q.v.),
+ which gives status information on the buffer displayed in that
+ window. *Note Mode Line::.
+
+Modified Buffer
+ A buffer (q.v.) is modified if its text has been changed since the
+ last time the buffer was saved (or since when it was created, if it
+ has never been saved). *Note Saving::.
+
+Moving Text
+ Moving text means erasing it from one place and inserting it in
+ another. This is done by killing (q.v.) and then yanking (q.v.).
+ *Note Killing::.
+
+Named Mark
+ A named mark is a register (q.v.) in its role of recording a
+ location in text so that you can move point to that location.
+ *Note Registers::.
+
+Narrowing
+ Narrowing means creating a restriction (q.v.) that limits editing
+ in the current buffer to only a part of the text in the buffer.
+ Text outside that part is inaccessible to the user until the
+ boundaries are widened again, but it is still there, and saving
+ the file saves it all. *Note Narrowing::.
+
+Newline
+ LFD characters in the buffer terminate lines of text and are
+ called newlines. *Note Newline: Characters.
+
+Numeric Argument
+ A numeric argument is a number, specified before a command, to
+ change the effect of the command. Often the numeric argument
+ serves as a repeat count. *Note Arguments::.
+
+Option
+ An option is a variable (q.v.) that exists so that you can
+ customize Emacs by giving it a new value. *Note Variables::.
+
+Overwrite Mode
+ Overwrite mode is a minor mode. When it is enabled, ordinary text
+ characters replace the existing text after point rather than
+ pushing it to the right. *Note Minor Modes::.
+
+Page
+ A page is a unit of text, delimited by formfeed characters (ASCII
+ Control-L, code 014) coming at the beginning of a line. Some Emacs
+ commands are provided for moving over and operating on pages.
+ *Note Pages::.
+
+Paragraphs
+ Paragraphs are the medium-size unit of English text. There are
+ special Emacs commands for moving over and operating on paragraphs.
+ *Note Paragraphs::.
+
+Parsing
+ We say that Emacs parses words or expressions in the text being
+ edited. Really, all it knows how to do is find the other end of a
+ word or expression. *Note Syntax::.
+
+Point
+ Point is the place in the buffer at which insertion and deletion
+ occur. Point is considered to be between two characters, not at
+ one character. The terminal's cursor (q.v.) indicates the
+ location of point. *Note Point: Basic.
+
+Prefix Key
+ A prefix key is a key (q.v.) whose sole function is to introduce a
+ set of multi-character keys. `Control-x' is an example of prefix
+ key; thus, any two-character sequence starting with `C-x' is also
+ a legitimate key. *Note Keys::.
+
+Primary Mail File
+ Your primary mail file is the file named `RMAIL' in your home
+ directory, where all mail that you receive is stored by Rmail
+ unless you make arrangements to do otherwise. *Note Rmail::.
+
+Prompt
+ A prompt is text printed to ask the user for input. Printing a
+ prompt is called prompting. Emacs prompts always appear in the
+ echo area (q.v.). One kind of prompting happens when the
+ minibuffer is used to read an argument (*note Minibuffer::.); the
+ echoing which happens when you pause in the middle of typing a
+ multicharacter key is also a kind of prompting (*note Echo
+ Area::.).
+
+Quitting
+ Quitting means cancelling a partially typed command or a running
+ command, using `C-g'. *Note Quitting::.
+
+Quoting
+ Quoting means depriving a character of its usual special
+ significance. In Emacs this is usually done with `Control-q'.
+ What constitutes special significance depends on the context and
+ on convention. For example, an "ordinary" character as an Emacs
+ command inserts itself; so in this context, a special character is
+ any character that does not normally insert itself (such as DEL,
+ for example), and quoting it makes it insert itself as if it were
+ not special. Not all contexts allow quoting. *Note Quoting:
+ Basic.
+
+Read-only Buffer
+ A read-only buffer is one whose text you are not allowed to change.
+ Normally Emacs makes buffers read-only when they contain text which
+ has a special significance to Emacs; for example, Dired buffers.
+ Visiting a file that is write protected also makes a read-only
+ buffer. *Note Buffers::.
+
+Recursive Editing Level
+ A recursive editing level is a state in which part of the
+ execution of a command involves asking the user to edit some text.
+ This text may or may not be the same as the text to which the
+ command was applied. The mode line indicates recursive editing
+ levels with square brackets (`[' and `]'). *Note Recursive Edit::.
+
+Redisplay
+ Redisplay is the process of correcting the image on the screen to
+ correspond to changes that have been made in the text being edited.
+ *Note Redisplay: Screen.
+
+Regexp
+ See `regular expression'.
+
+Region
+ The region is the text between point (q.v.) and the mark (q.v.).
+ Many commands operate on the text of the region. *Note Region:
+ Mark.
+
+Registers
+ Registers are named slots in which text or buffer positions or
+ rectangles can be saved for later use. *Note Registers::.
+
+Regular Expression
+ A regular expression is a pattern that can match various text
+ strings; for example, `l[0-9]+' matches `l' followed by one or more
+ digits. *Note Regexps::.
+
+Replacement
+ See `global substitution'.
+
+Restriction
+ A buffer's restriction is the amount of text, at the beginning or
+ the end of the buffer, that is temporarily invisible and
+ inaccessible. Giving a buffer a nonzero amount of restriction is
+ called narrowing (q.v.). *Note Narrowing::.
+
+RET
+ RET is a character that in Emacs runs the command to insert a
+ newline into the text. It is also used to terminate most arguments
+ read in the minibuffer (q.v.). *Note Return: Characters.
+
+Saving
+ Saving a buffer means copying its text into the file that was
+ visited (q.v.) in that buffer. This is the way text in files
+ actually gets changed by your Emacs editing. *Note Saving::.
+
+Scrolling
+ Scrolling means shifting the text in the Emacs window so as to see
+ a different part of the buffer. *Note Scrolling: Display.
+
+Searching
+ Searching means moving point to the next occurrence of a specified
+ string. *Note Search::.
+
+Selecting
+ Selecting a buffer means making it the current (q.v.) buffer.
+ *Note Selecting: Buffers.
+
+Self-documentation
+ Self-documentation is the feature of Emacs which can tell you what
+ any command does, or give you a list of all commands related to a
+ topic you specify. You ask for self-documentation with the help
+ character, `C-h'. *Note Help::.
+
+Sentences
+ Emacs has commands for moving by or killing by sentences. *Note
+ Sentences::.
+
+Sexp
+ A sexp (short for `s-expression') is the basic syntactic unit of
+ Lisp in its textual form: either a list, or Lisp atom. Many Emacs
+ commands operate on sexps. The term `sexp' is generalized to
+ languages other than Lisp, to mean a syntactically recognizable
+ expression. *Note Sexps: Lists.
+
+Simultaneous Editing
+ Simultaneous editing means two users modifying the same file at
+ once. Simultaneous editing if not detected can cause one user to
+ lose his work. Emacs detects all cases of simultaneous editing
+ and warns the user to investigate them. *Note Simultaneous
+ Editing: Interlocking.
+
+String
+ A string is a kind of Lisp data object which contains a sequence of
+ characters. Many Emacs variables are intended to have strings as
+ values. The Lisp syntax for a string consists of the characters in
+ the string with a `"' before and another `"' after. A `"' that is
+ part of the string must be written as `\"' and a `\' that is part
+ of the string must be written as `\\'. All other characters,
+ including newline, can be included just by writing them inside the
+ string; however, escape sequences as in C, such as `\n' for
+ newline or `\241' using an octal character code, are allowed as
+ well.
+
+String Substitution
+ See `global substitution'.
+
+Syntax Table
+ The syntax table tells Emacs which characters are part of a word,
+ which characters balance each other like parentheses, etc. *Note
+ Syntax::.
+
+Tag Table
+ A tag table is a file that serves as an index to the function
+ definitions in one or more other files. *Note Tags::.
+
+Termscript File
+ A termscript file contains a record of all characters sent by
+ Emacs to the terminal. It is used for tracking down bugs in Emacs
+ redisplay. Emacs does not make a termscript file unless you tell
+ it to. *Note Bugs::.
+
+Text
+ Two meanings (*note Text::.):
+
+ * Data consisting of a sequence of characters, as opposed to
+ binary numbers, images, graphics commands, executable
+ programs, and the like. The contents of an Emacs buffer are
+ always text in this sense.
+
+ * Data consisting of written human language, as opposed to
+ programs, or following the stylistic conventions of human
+ language.
+
+Top Level
+ Top level is the normal state of Emacs, in which you are editing
+ the text of the file you have visited. You are at top level
+ whenever you are not in a recursive editing level (q.v.) or the
+ minibuffer (q.v.), and not in the middle of a command. You can
+ get back to top level by aborting (q.v.) and quitting (q.v.).
+ *Note Quitting::.
+
+Transposition
+ Transposing two units of text means putting each one into the place
+ formerly occupied by the other. There are Emacs commands to
+ transpose two adjacent characters, words, sexps (q.v.) or lines
+ (*note Transpose::.).
+
+Truncation
+ Truncating text lines in the display means leaving out any text on
+ a line that does not fit within the right margin of the window
+ displaying it. See also `continuation line'. *Note Truncation:
+ Basic.
+
+Undoing
+ Undoing means making your previous editing go in reverse, bringing
+ back the text that existed earlier in the editing session. *Note
+ Undo::.
+
+Variable
+ A variable is an object in Lisp that can store an arbitrary value.
+ Emacs uses some variables for internal purposes, and has others
+ (known as `options' (q.v.)) just so that you can set their values
+ to control the behavior of Emacs. The variables used in Emacs
+ that you are likely to be interested in are listed in the
+ Variables Index in this manual. *Note Variables::, for
+ information on variables.
+
+Visiting
+ Visiting a file means loading its contents into a buffer (q.v.)
+ where they can be edited. *Note Visiting::.
+
+Whitespace
+ Whitespace is any run of consecutive formatting characters (space,
+ tab, newline, and backspace).
+
+Widening
+ Widening is removing any restriction (q.v.) on the current buffer;
+ it is the opposite of narrowing (q.v.). *Note Narrowing::.
+
+Window
+ Emacs divides the screen into one or more windows, each of which
+ can display the contents of one buffer (q.v.) at any time. *Note
+ Screen::, for basic information on how Emacs uses the screen.
+ *Note Windows::, for commands to control the use of windows.
+
+Word Abbrev
+ Synonymous with `abbrev'.
+
+Word Search
+ Word search is searching for a sequence of words, considering the
+ punctuation between them as insignificant. *Note Word Search::.
+
+Yanking
+ Yanking means reinserting text previously killed. It can be used
+ to undo a mistaken kill, or for copying or moving text. Some other
+ systems call this "pasting". *Note Yanking::.
+
+ \ No newline at end of file
diff --git a/info/emacs-17 b/info/emacs-17
new file mode 100644
index 00000000000..8130ac2a6c0
--- /dev/null
+++ b/info/emacs-17
@@ -0,0 +1,538 @@
+This is Info file ../info/emacs, produced by Makeinfo-1.49 from the
+input file emacs.texi.
+
+ This file documents the GNU Emacs editor.
+
+ Copyright (C) 1985, 1986, 1988, 1992 Richard M. Stallman.
+
+ Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+ Permission is granted to copy and distribute modified versions of
+this manual under the conditions for verbatim copying, provided also
+that the sections entitled "The GNU Manifesto", "Distribution" and "GNU
+General Public License" are included exactly as in the original, and
+provided that the entire resulting derived work is distributed under the
+terms of a permission notice identical to this one.
+
+ Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that the sections entitled "The GNU Manifesto",
+"Distribution" and "GNU General Public License" may be included in a
+translation approved by the author instead of in the original English.
+
+
+File: emacs, Node: Key Index, Next: Command Index, Prev: Glossary, Up: Top
+
+Key (Character) Index
+*********************
+
+* Menu:
+
+* ! (query-replace): Query Replace.
+* ! (Dired, V19): Shell Commands in Dired.
+* " (TeX mode): TeX Editing.
+* $ (Dired, V19): Hiding Subdirectories.
+* % C (Dired, V19): Dired Regexps.
+* % d (Dired, V19): Dired Regexps.
+* % H (Dired, V19): Dired Regexps.
+* % l (Dired, V19): Dired Case Conversion.
+* % m (Dired, V19): Dired Regexps.
+* % R (Dired, V19): Dired Regexps.
+* % S (Dired, V19): Dired Regexps.
+* % u (Dired, V19): Dired Case Conversion.
+* * (Dired, V19): Marks in Dired.
+* , (query-replace): Query Replace.
+* . (query-replace): Query Replace.
+* . (Rmail): Rmail Scrolling.
+* / (Dired, V19): Marks in Dired.
+* < (Rmail in V19): Mail Changes.
+* = (Dired, V19): Comparison in Dired.
+* > (Rmail): Rmail Motion.
+* @ (Dired, V19): Marks in Dired.
+* TAB (Shell mode in V19): Shell Changes.
+* a (Rmail): Rmail Labels.
+* B (Dired, V19): Multiple Files.
+* c (Rmail): Rmail Reply.
+* C (Dired, V19): Multiple Files.
+* c (Dired, V19): Marks in Dired.
+* C-a: Basic.
+* C-a (Shell mode in V19): Shell Changes.
+* C-b: Basic.
+* C-c: Keys.
+* C-c ' (Picture mode): Insert in Picture.
+* C-c . (Picture mode): Insert in Picture.
+* C-c / (Picture mode): Insert in Picture.
+* C-c ; (Fortran mode): Fortran Comments.
+* C-c < (Picture mode): Insert in Picture.
+* C-c < (GUD in V19): Commands of GUD.
+* C-c > (Picture mode): Insert in Picture.
+* C-c > (GUD in V19): Commands of GUD.
+* C-c TAB (TeX mode in V19): TeX Mode Changes.
+* C-c { (TeX mode in V19): TeX Mode Changes.
+* C-c } (TeX mode in V19): TeX Mode Changes.
+* C-c C-b (Outline mode): Outline Motion.
+* C-c C-b (Picture mode): Insert in Picture.
+* C-c C-b (TeX mode): TeX Print.
+* C-c C-c (Edit Abbrevs): Editing Abbrevs.
+* C-c C-c (Edit Tab Stops): Tab Stops.
+* C-c C-c (Mail mode): Mail Mode.
+* C-c C-c (Occur mode): Other Repeating Search.
+* C-c C-c (Shell mode): Shell Mode.
+* C-c C-c (GUD in V19): Commands of GUD.
+* C-c C-d (Picture mode): Basic Picture.
+* C-c C-d (Shell mode): Shell Mode.
+* C-c C-e (TeX mode in V19): TeX Mode Changes.
+* C-c C-f (LaTeX mode): TeX Editing.
+* C-c C-f (Outline mode): Outline Motion.
+* C-c C-f (Picture mode): Insert in Picture.
+* C-c C-f (GUD in V19): Commands of GUD.
+* C-c C-f C-c (Mail mode): Mail Mode.
+* C-c C-f C-s (Mail mode): Mail Mode.
+* C-c C-f C-t (Mail mode): Mail Mode.
+* C-c C-h (Outline mode): Outline Visibility.
+* C-c C-i (Outline mode): Outline Visibility.
+* C-c C-i (GUD in V19): Commands of GUD.
+* C-c C-k (Picture mode): Rectangles in Picture.
+* C-c C-k (TeX mode): TeX Print.
+* C-c C-l (TeX mode): TeX Print.
+* C-c C-l (GUD in V19): Commands of GUD.
+* C-c C-n (Fortran mode): Fortran Motion.
+* C-c C-n (Outline mode): Outline Motion.
+* C-c C-n (GUD in V19): Commands of GUD.
+* C-c C-o (Shell mode): Shell Mode.
+* C-c C-o (Shell mode in V19): Shell Changes.
+* C-c C-o (TeX mode in V19): TeX Mode Changes.
+* C-c C-p (Fortran mode): Fortran Motion.
+* C-c C-p (Outline mode): Outline Motion.
+* C-c C-p (TeX mode): TeX Print.
+* C-c C-q (Mail mode): Mail Mode.
+* C-c C-q (TeX mode): TeX Print.
+* C-c C-r (Fortran mode): Fortran Columns.
+* C-c C-r (Shell mode): Shell Mode.
+* C-c C-r (TeX mode): TeX Print.
+* C-c C-r (Shell mode in V19): Shell Changes.
+* C-c C-s (Mail mode): Mail Mode.
+* C-c C-s (Outline mode): Outline Visibility.
+* C-c C-s (GUD in V19): Commands of GUD.
+* C-c C-u (Outline mode): Outline Motion.
+* C-c C-u (Shell mode): Shell Mode.
+* C-c C-v (TeX mode in V19): TeX Mode Changes.
+* C-c C-w (Fortran mode): Fortran Columns.
+* C-c C-w (Mail mode): Mail Mode.
+* C-c C-w (Picture mode): Rectangles in Picture.
+* C-c C-w (Shell mode): Shell Mode.
+* C-c C-x (Picture mode): Rectangles in Picture.
+* C-c C-y (Mail mode): Mail Mode.
+* C-c C-y (Mail mode): Rmail Reply.
+* C-c C-y (Picture mode): Rectangles in Picture.
+* C-c C-y (Shell mode): Shell Mode.
+* C-c C-z (Shell mode): Shell Mode.
+* C-c C-\ (Shell mode): Shell Mode.
+* C-c TAB (Picture mode): Tabs in Picture.
+* C-c \ (Picture mode): Insert in Picture.
+* C-c ^ (Picture mode): Insert in Picture.
+* C-c ` (Picture mode): Insert in Picture.
+* C-d: Killing.
+* C-d (Rmail): Rmail Deletion.
+* C-d (Shell mode in V19): Shell Changes.
+* C-e: Basic.
+* C-f: Basic.
+* C-g: Minibuffer.
+* C-h: Keys.
+* C-h a: Help.
+* C-h a (V19): New Commands.
+* C-h b: Help.
+* C-h c: Help.
+* C-h C-c: Help.
+* C-h C-d: Help.
+* C-h C-f (V19): New Commands.
+* C-h C-k (V19): New Commands.
+* C-h C-w: Help.
+* C-h f: Help.
+* C-h f: Documentation.
+* C-h i: Help.
+* C-h k: Help.
+* C-h l: Help.
+* C-h m: Help.
+* C-h n: Help.
+* C-h s: Syntax Change.
+* C-h t: Basic.
+* C-h t: Help.
+* C-h v: Documentation.
+* C-h v: Help.
+* C-h v: Examining.
+* C-h w: Help.
+* C-k: Killing.
+* C-k: Killing.
+* C-l: Basic.
+* C-l: Scrolling.
+* C-l (query-replace): Query Replace.
+* C-M-@: Lists.
+* C-M-@: Marking Objects.
+* C-M-a: Defuns.
+* C-M-a (Fortran mode): Fortran Motion.
+* C-M-b: Lists.
+* C-M-c: Recursive Edit.
+* C-M-d: Lists.
+* C-M-d (Dired, V19): Subdirectories in Dired.
+* C-M-e: Defuns.
+* C-M-e (Fortran mode): Fortran Motion.
+* C-M-f: Lists.
+* C-M-f (V19): Changed Commands.
+* C-M-h: Defuns.
+* C-M-h: Marking Objects.
+* C-M-h (Fortran mode): Fortran Motion.
+* C-M-k: Killing.
+* C-M-k: Lists.
+* C-M-l (Rmail): Rmail Make Summary.
+* C-M-l (Rmail): Rmail Labels.
+* C-M-l (V19): New Commands.
+* C-M-m (Rmail in V19): Mail Changes.
+* C-M-n: Lists.
+* C-M-n (Rmail): Rmail Labels.
+* C-M-n (Dired, V19): Subdirectories in Dired.
+* C-M-n (Summary mode) (GNUS, V19): Summary of GNUS.
+* C-M-o: Indentation Commands.
+* C-M-p: Lists.
+* C-M-p (Rmail): Rmail Labels.
+* C-M-p (Dired, V19): Subdirectories in Dired.
+* C-M-p (Summary mode) (GNUS, V19): Summary of GNUS.
+* C-M-q: Multi-line Indent.
+* C-M-q (Fortran mode): ForIndent Commands.
+* C-M-r (Rmail): Rmail Make Summary.
+* C-M-r (V19): New Commands.
+* C-M-s: Regexp Search.
+* C-M-t: Transpose.
+* C-M-t: Lists.
+* C-M-u: Lists.
+* C-M-u (Dired, V19): Subdirectories in Dired.
+* C-M-v: Minibuffer Edit.
+* C-M-v: Other Window.
+* C-M-w: Appending Kills.
+* C-M-x: External Lisp.
+* C-M-x: Lisp Eval.
+* C-M-\: Indentation Commands.
+* C-M-\: Multi-line Indent.
+* C-n: Basic.
+* C-n (Rmail summary): Rmail Summary Edit.
+* C-n (Group mode) (GNUS, V19): Summary of GNUS.
+* C-n (Rmail summary in V19): Mail Changes.
+* C-n (Summary mode) (GNUS, V19): Summary of GNUS.
+* C-o: Blank Lines.
+* C-o (Rmail): Rmail Output.
+* C-o (V19): Changed Commands.
+* C-p: Basic.
+* C-p (Rmail summary): Rmail Summary Edit.
+* C-p (Group mode) (GNUS, V19): Summary of GNUS.
+* C-p (Rmail summary in V19): Mail Changes.
+* C-p (Summary mode) (GNUS, V19): Summary of GNUS.
+* C-q: Basic.
+* C-r: Incremental Search.
+* C-r (query-replace): Query Replace.
+* C-s: Incremental Search.
+* C-SPC: Setting Mark.
+* C-t: Basic.
+* C-t: Transpose.
+* C-u: Arguments.
+* C-u - C-x ;: Comments.
+* C-u C-@: Mark Ring.
+* C-u C-SPC: Mark Ring.
+* C-u TAB: Multi-line Indent.
+* C-v: Scrolling.
+* C-w: Killing.
+* C-w (query-replace): Query Replace.
+* C-x: Keys.
+* C-x $: Selective Display.
+* C-x & (GUD in V19): GUD Customization.
+* C-x (: Basic Kbd Macro.
+* C-x ): Basic Kbd Macro.
+* C-x +: Defining Abbrevs.
+* C-x -: Defining Abbrevs.
+* C-x .: Fill Prefix.
+* C-x /: RegPos.
+* C-x 0: Change Window.
+* C-x 1: Change Window.
+* C-x 2: Split Window.
+* C-x 2 (V19): Changed Commands.
+* C-x 3 (V19): Binding Changes.
+* C-x 4: Pop Up Window.
+* C-x 4 .: Find Tag.
+* C-x 4 a: Change Log.
+* C-x 4 a (V19): M-x Changes.
+* C-x 4 b: Select Buffer.
+* C-x 4 C-o (V19): Binding Changes.
+* C-x 4 d: Dired Enter.
+* C-x 4 f: Visiting.
+* C-x 4 m: Sending Mail.
+* C-x 4 r (V19): New Commands.
+* C-x 5: Split Window.
+* C-x 5 . (V19): New Commands.
+* C-x 5 (V19): New Commands.
+* C-x 5 b (V19): New Commands.
+* C-x 5 C-f (V19): New Commands.
+* C-x 5 m (V19): New Commands.
+* C-x ;: Comments.
+* C-x <: Horizontal Scrolling.
+* C-x =: Position Info.
+* C-x >: Horizontal Scrolling.
+* C-x SPC (V19): Commands of GUD.
+* C-x }: Change Window.
+* C-x a: Accumulating Text.
+* C-x a (V19): Binding Changes.
+* C-x b: Select Buffer.
+* C-x C-a: Defining Abbrevs.
+* C-x C-b: List Buffers.
+* C-x C-c: Exiting.
+* C-x C-d: ListDir.
+* C-x C-e: Lisp Eval.
+* C-x C-f: Visiting.
+* C-x C-h: Defining Abbrevs.
+* C-x C-l: Case.
+* C-x C-l (V19): Binding Changes.
+* C-x C-o: Blank Lines.
+* C-x C-o: Killing.
+* C-x C-p: Pages.
+* C-x C-p: Marking Objects.
+* C-x C-q: Misc Buffer.
+* C-x C-q (V19): Editing with VC.
+* C-x C-s: Saving.
+* C-x C-t: Transpose.
+* C-x C-u: Case.
+* C-x C-u (V19): Binding Changes.
+* C-x C-v: Visiting.
+* C-x C-v (V19): Changed Commands.
+* C-x C-w: Saving.
+* C-x C-x: Setting Mark.
+* C-x d: Dired Enter.
+* C-x DEL: Killing.
+* C-x DEL: Kill Errors.
+* C-x DEL: Sentences.
+* C-x e: Basic Kbd Macro.
+* C-x ESC: Repetition.
+* C-x f: Fill Commands.
+* C-x g: RegText.
+* C-x h: Marking Objects.
+* C-x j: RegPos.
+* C-x k: Kill Buffer.
+* C-x l: Pages.
+* C-x m: Sending Mail.
+* C-x n: Narrowing.
+* C-x n (V19): Binding Changes.
+* C-x o: Other Window.
+* C-x q: Kbd Macro Query.
+* C-x r (V19): Binding Changes.
+* C-x s: Saving.
+* C-x s (V19): Changed Commands.
+* C-x TAB: Indentation Commands.
+* C-x u: Undo.
+* C-x v = (V19): Comparing Versions.
+* C-x v a (V19): Change Logs and VC.
+* C-x v c (V19): Editing with VC.
+* C-x v d (V19): VC Status.
+* C-x v h (V19): Version Headers.
+* C-x v i (V19): Editing with VC.
+* C-x v l (V19): VC Status.
+* C-x v r (V19): Making Snapshots.
+* C-x v s (V19): Making Snapshots.
+* C-x v u (V19): Editing with VC.
+* C-x w: Narrowing.
+* C-x x: RegText.
+* C-x [: Pages.
+* C-x ]: Pages.
+* C-x ^: Change Window.
+* C-x `: Compilation.
+* C-y: Kill Ring.
+* C-z: Exiting.
+* C-z (V19): New Commands.
+* C-]: Quitting.
+* C-]: Recursive Edit.
+* C-_: Undo.
+* d (Rmail summary): Rmail Summary Edit.
+* d (Rmail): Rmail Deletion.
+* DEL: Program Modes.
+* DEL: Major Modes.
+* DEL: Basic.
+* DEL: Killing.
+* DEL: Kill Errors.
+* DEL (query-replace): Query Replace.
+* DEL (Rmail summary): Rmail Summary Edit.
+* DEL (Rmail): Rmail Scrolling.
+* DEL (Group mode) (GNUS, V19): Summary of GNUS.
+* DEL (Summary mode) (GNUS, V19): Summary of GNUS.
+* e (Rmail): Rmail Deletion.
+* e (Rmail in V19): Mail Changes.
+* ESC: Keys.
+* ESC (query-replace): Query Replace.
+* f (Rmail): Rmail Reply.
+* g (Rmail): Rmail Files.
+* g (Dired, V19): Editing Dired Buffer.
+* G (Dired, V19): Multiple Files.
+* h (Rmail): Rmail Make Summary.
+* H (Dired, V19): Multiple Files.
+* Help: Help.
+* i (Rmail): Rmail Files.
+* i (Dired, V19): Subdirectories in Dired.
+* j (Rmail summary): Rmail Summary Edit.
+* j (Rmail): Rmail Motion.
+* k (rmail): Rmail Labels.
+* k (Dired, V19): Editing Dired Buffer.
+* l (Rmail): Rmail Make Summary.
+* L (Dired, V19): Multiple Files.
+* l (Dired, V19): Editing Dired Buffer.
+* l (Group mode) (GNUS, V19): Summary of GNUS.
+* L (Group mode) (GNUS, V19): Summary of GNUS.
+* LFD: Basic Indent.
+* LFD: Major Modes.
+* LFD (TeX mode): TeX Editing.
+* m (Rmail): Rmail Reply.
+* m (Dired, V19): Marks in Dired.
+* M (Dired, V19): Multiple Files.
+* M-!: Single Shell.
+* M-! (V19): Changed Commands.
+* M-$: Spelling.
+* M-$ (Dired, V19): Hiding Subdirectories.
+* M-$ (V19): Spell Changes.
+* M-%: Query Replace.
+* M-': Expanding Abbrevs.
+* M-(: Balanced Editing.
+* M-): Balanced Editing.
+* M-,: Tags Search.
+* M-.: Find Tag.
+* M-. (V19): Tags Changes.
+* M-/: Dynamic Abbrevs.
+* M-1: Arguments.
+* M-;: Comments.
+* M-<: Basic.
+* M-=: Position Info.
+* M-= (Dired, V19): Comparison in Dired.
+* M->: Basic.
+* M-?: Nroff Mode.
+* M-? (Shell mode in V19): Shell Changes.
+* M-@: Words.
+* M-@: Marking Objects.
+* M-DEL (Dired, V19): Marks in Dired.
+* M-TAB (V19): Tags Changes.
+* M--: Arguments.
+* M-- M-c: Fixing Case.
+* M-- M-l: Fixing Case.
+* M-- M-u: Fixing Case.
+* M-{ (TeX mode): TeX Editing.
+* M-{ (V19): Binding Changes.
+* M-} (TeX mode): TeX Editing.
+* M-} (V19): Binding Changes.
+* M-a: Sentences.
+* M-a (C mode in V19): New Commands.
+* M-b: Words.
+* M-c: Case.
+* M-d: Words.
+* M-d: Killing.
+* M-DEL: Kill Errors.
+* M-DEL: Killing.
+* M-DEL: Words.
+* M-e: Sentences.
+* M-e (C mode in V19): New Commands.
+* M-ESC: Lisp Eval.
+* M-f: Words.
+* M-g: Fill Commands.
+* M-g (V19): Binding Changes.
+* M-h: Marking Objects.
+* M-h: Paragraphs.
+* M-i: Tab Stops.
+* M-k: Sentences.
+* M-k: Killing.
+* M-l: Case.
+* M-LFD: Comments.
+* M-LFD (Fortran mode): ForIndent Commands.
+* M-m: Indentation Commands.
+* M-n: Nroff Mode.
+* M-n: Repetition.
+* M-n (Rmail): Rmail Motion.
+* M-n (Rmail summary in V19): Mail Changes.
+* M-n (Shell mode in V19): Shell Changes.
+* M-n (V19): New Facilities.
+* M-p: Nroff Mode.
+* M-p: Repetition.
+* M-p (Rmail): Rmail Motion.
+* M-p (Rmail summary in V19): Mail Changes.
+* M-p (Shell mode in V19): Shell Changes.
+* M-p (V19): New Facilities.
+* M-q: Fill Commands.
+* M-q (C mode in V19): New Commands.
+* M-q (C mode in V19): Filling Changes.
+* M-r: Basic.
+* M-r (Shell mode in V19): Shell Changes.
+* M-r (V19): New Facilities.
+* M-s: Fill Commands.
+* M-s (Rmail): Rmail Motion.
+* M-s (Shell mode in V19): Shell Changes.
+* M-s (Summary mode) (GNUS, V19): Summary of GNUS.
+* M-s (V19): New Facilities.
+* M-SPC: Killing.
+* M-t: Transpose.
+* M-t: Words.
+* M-TAB: Tabs in Picture.
+* M-TAB: Lisp Completion.
+* M-u: Case.
+* M-v: Scrolling.
+* M-w: Kill Ring.
+* M-x: M-x.
+* M-x gnus (V19): GNUS.
+* M-y: Earlier Kills.
+* M-z: Killing.
+* M-z (V19): Changed Commands.
+* M-[: Paragraphs.
+* M-\: Killing.
+* M-\: Indentation Commands.
+* M-]: Paragraphs.
+* M-^: Killing.
+* M-^: Indentation Commands.
+* M-^ (V19): Changed Commands.
+* M-|: Single Shell.
+* M-~: Saving.
+* n (Rmail summary): Rmail Summary Edit.
+* n (Rmail): Rmail Motion.
+* n (Group mode) (GNUS, V19): Summary of GNUS.
+* n (Rmail summary in V19): Mail Changes.
+* o (Rmail): Rmail Output.
+* O (Dired, V19): Multiple Files.
+* p (Rmail summary): Rmail Summary Edit.
+* p (Rmail): Rmail Motion.
+* P (Dired, V19): Multiple Files.
+* p (Group mode) (GNUS, V19): Summary of GNUS.
+* p (Rmail summary in V19): Mail Changes.
+* q (Rmail summary): Rmail Summary Edit.
+* q (Rmail): Rmail.
+* q (Group mode) (GNUS, V19): Summary of GNUS.
+* r (Rmail): Rmail Reply.
+* R (Dired, V19): Multiple Files.
+* RET: Basic.
+* RET (Shell mode): Shell Mode.
+* s (Rmail): Rmail.
+* S (Dired, V19): Multiple Files.
+* s (Summary mode) (GNUS, V19): Summary of GNUS.
+* SPC: Completion.
+* SPC (query-replace): Query Replace.
+* SPC (Rmail summary): Rmail Summary Edit.
+* SPC (Rmail): Rmail Scrolling.
+* SPC (Group mode) (GNUS, V19): Summary of GNUS.
+* SPC (Summary mode) (GNUS, V19): Summary of GNUS.
+* t (Rmail): Rmail Editing.
+* TAB: Basic Indent.
+* TAB: Completion.
+* TAB: Indentation.
+* TAB: Text Mode.
+* TAB: Indentation.
+* TAB: Major Modes.
+* u (Rmail summary): Rmail Summary Edit.
+* u (Rmail): Rmail Deletion.
+* u (Group mode) (GNUS, V19): Summary of GNUS.
+* w (Rmail): Rmail Editing.
+* x (Rmail summary): Rmail Summary Edit.
+* x (Rmail in V19): Mail Changes.
+* Z (Dired, V19): Multiple Files.
+* z (Group mode) (GNUS, V19): Summary of GNUS.
+* ^ (query-replace): Query Replace.
+
+ \ No newline at end of file
diff --git a/info/emacs-18 b/info/emacs-18
new file mode 100644
index 00000000000..242e44d9d97
--- /dev/null
+++ b/info/emacs-18
@@ -0,0 +1,949 @@
+This is Info file ../info/emacs, produced by Makeinfo-1.49 from the
+input file emacs.texi.
+
+ This file documents the GNU Emacs editor.
+
+ Copyright (C) 1985, 1986, 1988, 1992 Richard M. Stallman.
+
+ Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+ Permission is granted to copy and distribute modified versions of
+this manual under the conditions for verbatim copying, provided also
+that the sections entitled "The GNU Manifesto", "Distribution" and "GNU
+General Public License" are included exactly as in the original, and
+provided that the entire resulting derived work is distributed under the
+terms of a permission notice identical to this one.
+
+ Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that the sections entitled "The GNU Manifesto",
+"Distribution" and "GNU General Public License" may be included in a
+translation approved by the author instead of in the original English.
+
+
+File: emacs, Node: Command Index, Next: Variable Index, Prev: Key Index, Up: Top
+
+Command and Function Index
+**************************
+
+* Menu:
+
+* abbrev-mode: Abbrevs.
+* abbrev-prefix-mark: Expanding Abbrevs.
+* abort-recursive-edit: Quitting.
+* abort-recursive-edit: Recursive Edit.
+* add-change-log-entry: Change Log.
+* add-change-log-entry (V19): M-x Changes.
+* add-change-log-entry-other-window: Change Log.
+* add-global-abbrev: Defining Abbrevs.
+* add-hook (V19): Hook Changes.
+* add-mode-abbrev: Defining Abbrevs.
+* add-name-to-file: Misc File Ops.
+* append-next-kill: Appending Kills.
+* append-to-buffer: Accumulating Text.
+* append-to-file: Misc File Ops.
+* append-to-file: Accumulating Text.
+* apropos: Help.
+* apropros (V19): New Commands.
+* ask-user-about-lock: Interlocking.
+* auto-fill-mode: Auto Fill.
+* auto-save-mode: Auto Save Control.
+* back-to-indentation: Indentation Commands.
+* backward-char: Basic.
+* backward-delete-char-untabify: Program Modes.
+* backward-kill-sentence: Sentences.
+* backward-kill-sentence: Kill Errors.
+* backward-kill-sentence: Killing.
+* backward-kill-word: Killing.
+* backward-kill-word: Words.
+* backward-kill-word: Kill Errors.
+* backward-list: Lists.
+* backward-page: Pages.
+* backward-paragraph: Paragraphs.
+* backward-sentence: Sentences.
+* backward-sexp: Lists.
+* backward-text-line: Nroff Mode.
+* backward-up-list: Lists.
+* backward-word: Words.
+* batch-byte-compile: Compiling Libraries.
+* beginning-of-buffer: Basic.
+* beginning-of-defun: Defuns.
+* beginning-of-fortran-subprogram: Fortran Motion.
+* beginning-of-line: Basic.
+* buffer-enable-undo: Undo.
+* buffer-menu: Several Buffers.
+* byte-compile-file: Compiling Libraries.
+* byte-recompile-directory: Compiling Libraries.
+* c-beginning-of-statement (V19): New Commands.
+* c-end-of-statement (V19): New Commands.
+* c-fill-paragraph (V19): Filling Changes.
+* c-fill-paragraph (V19): New Commands.
+* c-indent-line: Basic Indent.
+* c-macro-expand: Macro Expansion.
+* c-up-conditional (V19): New Commands.
+* calendar-count-days-region (V19): Calendar.
+* calendar-cursor-holidays (V19): Calendar.
+* calendar-goto-astro-date (V19): Calendar.
+* calendar-goto-french-date (V19): Calendar.
+* calendar-goto-hebrew-date (V19): Calendar.
+* calendar-goto-islamic-date (V19): Calendar.
+* calendar-goto-iso-date (V19): Calendar.
+* calendar-goto-julian-date (V19): Calendar.
+* calendar-print-astro-date (V19): Calendar.
+* calendar-print-french-date (V19): Calendar.
+* calendar-print-hebrew-date (V19): Calendar.
+* calendar-print-islamic-date (V19): Calendar.
+* calendar-print-iso-date (V19): Calendar.
+* calendar-print-julian-date (V19): Calendar.
+* calendar-print-mayan-date (V19): Calendar.
+* calendar-unmark (V19): Calendar.
+* calendar-unmark (V19): Displaying Diary.
+* call-last-kbd-macro: Basic Kbd Macro.
+* cancel-debug-on-entry: Lisp Debug.
+* capitalize-word: Case.
+* capitalize-word: Fixing Case.
+* center-line: Fill Commands.
+* clear-rectangle: Rectangles.
+* comint-continue-subjob (V19): Shell Changes.
+* comint-dynamic-complete (V19): Shell Changes.
+* comint-dynamic-list-completions (V19): Shell Changes.
+* comint-kill-output (V19): Shell Changes.
+* comint-next-input (V19): Shell Changes.
+* comint-next-matching-input (V19): Shell Changes.
+* comint-previous-input (V19): Shell Changes.
+* comint-previous-matching-input (V19): Shell Changes.
+* comint-show-output (V19): Shell Changes.
+* command-apropos: Help.
+* comment-region (V19): New Commands.
+* compare-windows: Other Window.
+* compare-windows (V19): M-x Changes.
+* compile: Compilation.
+* compile (V19): M-x Changes.
+* convert-mocklisp-buffer: Mocklisp.
+* copy-file: Misc File Ops.
+* copy-last-shell-input: Shell Mode.
+* copy-region-as-kill: Kill Ring.
+* copy-to-buffer: Accumulating Text.
+* copy-to-register: RegText.
+* count-lines-page: Pages.
+* count-lines-region: Position Info.
+* count-matches: Other Repeating Search.
+* count-text-lines: Nroff Mode.
+* dabbrev-expand: Dynamic Abbrevs.
+* dbx (V19): Starting GUD.
+* debug: Lisp Debug.
+* debug-on-entry: Lisp Debug.
+* default-value: Locals.
+* define-abbrevs: Saving Abbrevs.
+* define-key: Rebinding.
+* delete-backward-char: Killing.
+* delete-backward-char: Basic.
+* delete-backward-char: Kill Errors.
+* delete-blank-lines: Killing.
+* delete-blank-lines: Blank Lines.
+* delete-char: Basic Picture.
+* delete-char: Killing.
+* delete-file: Misc File Ops.
+* delete-horizontal-space: Killing.
+* delete-horizontal-space: Indentation Commands.
+* delete-indentation: Killing.
+* delete-indentation: Indentation Commands.
+* delete-matching-lines: Other Repeating Search.
+* delete-non-matching-lines: Other Repeating Search.
+* delete-other-windows: Change Window.
+* delete-rectangle: Rectangles.
+* delete-window: Change Window.
+* describe-bindings: Help.
+* describe-copying: Help.
+* describe-distribution: Help.
+* describe-function: Documentation.
+* describe-function: Help.
+* describe-key: Help.
+* describe-key-briefly: Help.
+* describe-mode: Help.
+* describe-no-warranty: Help.
+* describe-syntax: Syntax Change.
+* describe-variable: Documentation.
+* describe-variable: Examining.
+* describe-variable: Help.
+* diary (V19): Displaying Diary.
+* diff (V19): New Commands.
+* diff-backup (V19): New Commands.
+* digit-argument: Arguments.
+* dired: Dired Enter.
+* dired-backup-diff (V19): Comparison in Dired.
+* dired-change-marks (V19): Marks in Dired.
+* dired-diff (V19): Comparison in Dired.
+* dired-do-byte-compile (V19): Multiple Files.
+* dired-do-chgrp (V19): Multiple Files.
+* dired-do-chmod (V19): Multiple Files.
+* dired-do-chown (V19): Multiple Files.
+* dired-do-compress (V19): Multiple Files.
+* dired-do-copy (V19): Multiple Files.
+* dired-do-copy-regexp (V19): Dired Regexps.
+* dired-do-hardlink (V19): Multiple Files.
+* dired-do-hardlink-regexp (V19): Dired Regexps.
+* dired-do-kill-lines (V19): Editing Dired Buffer.
+* dired-do-load (V19): Multiple Files.
+* dired-do-print (V19): Multiple Files.
+* dired-do-redisplay (V19): Editing Dired Buffer.
+* dired-do-rename (V19): Multiple Files.
+* dired-do-rename-regexp (V19): Dired Regexps.
+* dired-do-shell-command (V19): Shell Commands in Dired.
+* dired-do-symlink (V19): Multiple Files.
+* dired-do-symlink-regexp (V19): Dired Regexps.
+* dired-downcase (V19): Dired Case Conversion.
+* dired-flag-files-regexp (V19): Dired Regexps.
+* dired-hide-all (V19): Hiding Subdirectories.
+* dired-hide-subdir (V19): Hiding Subdirectories.
+* dired-mark (V19): Marks in Dired.
+* dired-mark-directories (V19): Marks in Dired.
+* dired-mark-executables (V19): Marks in Dired.
+* dired-mark-files-regexp (V19): Dired Regexps.
+* dired-mark-symlinks (V19): Marks in Dired.
+* dired-maybe-insert-subdir (V19): Subdirectories in Dired.
+* dired-next-subdir (V19): Subdirectories in Dired.
+* dired-other-window: Pop Up Window.
+* dired-other-window: Dired Enter.
+* dired-prev-subdir (V19): Subdirectories in Dired.
+* dired-tree-down (V19): Subdirectories in Dired.
+* dired-tree-up (V19): Subdirectories in Dired.
+* dired-unmark-all-files (V19): Marks in Dired.
+* dired-upcase (V19): Dired Case Conversion.
+* dirs (V19): Shell Changes.
+* disable-command: Disabling.
+* disassemble: Compiling Libraries.
+* display-buffer (V19): Binding Changes.
+* display-time: Mode Line.
+* dissociated-press: Dissociated Press.
+* do-auto-save: Auto Save Control.
+* doctor: Total Frustration.
+* down-list: Lists.
+* downcase-region: Case.
+* downcase-word: Fixing Case.
+* downcase-word: Case.
+* edebug-defun (V19): Edebug Mode.
+* edit-abbrevs: Editing Abbrevs.
+* edit-abbrevs-redefine: Editing Abbrevs.
+* edit-options: Edit Options.
+* edit-picture: Picture.
+* edit-tab-stops: Text Mode.
+* edit-tab-stops: Tab Stops.
+* edit-tab-stops-note-changes: Tab Stops.
+* edt-emulation-off: Emulation.
+* edt-emulation-on: Emulation.
+* electric-nroff-mode: Nroff Mode.
+* emacs-lisp-mode: Lisp Eval.
+* emacs-version: Bugs.
+* emerge-auto-advance-mode (V19): Submodes of Emerge.
+* emerge-buffers (V19): Overview of Emerge.
+* emerge-buffers-with-ancestor (V19): Overview of Emerge.
+* emerge-files (V19): Overview of Emerge.
+* emerge-files-with-ancestor (V19): Overview of Emerge.
+* emerge-skip-prefers-mode (V19): Submodes of Emerge.
+* enable-command: Disabling.
+* end-kbd-macro: Basic Kbd Macro.
+* end-of-buffer: Basic.
+* end-of-defun: Defuns.
+* end-of-fortran-subprogram: Fortran Motion.
+* end-of-line: Basic.
+* enlarge-window: Change Window.
+* enlarge-window-horizontally: Change Window.
+* evade-flow-control-on (V19): New Facilities.
+* eval-current-buffer: Lisp Eval.
+* eval-defun: Lisp Eval.
+* eval-expression: Lisp Eval.
+* eval-last-sexp: Lisp Eval.
+* eval-region: Lisp Eval.
+* exchange-point-and-mark: Setting Mark.
+* execute-extended-command: M-x.
+* exit-recursive-edit: Recursive Edit.
+* expand-abbrev: Expanding Abbrevs.
+* expand-region-abbrevs: Expanding Abbrevs.
+* fancy-diary-display (V19): Simple and Fancy.
+* fill-c++-comment (V19): Other New Modes.
+* fill-individual-paragraphs: Fill Prefix.
+* fill-individual-paragraphs (V19): Filling Changes.
+* fill-paragraph: Fill Commands.
+* fill-region: Fill Commands.
+* fill-region-as-paragraph: Fill Commands.
+* fill-region-as-paragraph (V19): Filling Changes.
+* find-alternate-file: Visiting.
+* find-dired: Dired and Find.
+* find-file: Visiting.
+* find-file-other-frame (V19): New Commands.
+* find-file-other-window: Pop Up Window.
+* find-file-other-window: Visiting.
+* find-file-read-only-other-window (V19): New Commands.
+* find-grep-dired: Dired and Find.
+* find-name-dired: Dired and Find.
+* find-tag: Find Tag.
+* find-tag-other-frame (V19): New Commands.
+* find-tag-other-window: Find Tag.
+* find-tag-other-window: Pop Up Window.
+* find-tag-regexp (V19): Tags Changes.
+* fortran-column-ruler: Fortran Columns.
+* fortran-comment-region: Fortran Comments.
+* fortran-indent-line: ForIndent Commands.
+* fortran-indent-subprogram: ForIndent Commands.
+* fortran-mode: Fortran.
+* fortran-next-statement: Fortran Motion.
+* fortran-previous-statement: Fortran Motion.
+* fortran-split-line: ForIndent Commands.
+* fortran-window-create: Fortran Columns.
+* forward-char: Basic.
+* forward-list: Lists.
+* forward-page: Pages.
+* forward-paragraph: Paragraphs.
+* forward-sentence: Sentences.
+* forward-sexp: Lists.
+* forward-text-line: Nroff Mode.
+* forward-word: Words.
+* gdb (V19): Starting GUD.
+* global-set-key: Rebinding.
+* global-set-key (V19): Key Sequence Changes.
+* gnus (V19): GNUS.
+* gnus-Group-exit (V19): Summary of GNUS.
+* gnus-Group-list-all-groups (V19): Summary of GNUS.
+* gnus-Group-list-groups (V19): Summary of GNUS.
+* gnus-Group-next-group (V19): Summary of GNUS.
+* gnus-Group-next-unread-group (V19): Summary of GNUS.
+* gnus-Group-prev-group (V19): Summary of GNUS.
+* gnus-Group-prev-unread-group (V19): Summary of GNUS.
+* gnus-Group-read-group (V19): Summary of GNUS.
+* gnus-Group-suspend (V19): Summary of GNUS.
+* gnus-Group-unsubscribe-current-group (V19): Summary of GNUS.
+* gnus-Summary-isearch-article (V19): Summary of GNUS.
+* gnus-Summary-next-page (V19): Summary of GNUS.
+* gnus-Summary-next-same-subject (V19): Summary of GNUS.
+* gnus-Summary-next-subject (V19): Summary of GNUS.
+* gnus-Summary-prev-page (V19): Summary of GNUS.
+* gnus-Summary-prev-same-subject (V19): Summary of GNUS.
+* gnus-Summary-prev-subject (V19): Summary of GNUS.
+* gnus-Summary-search-article-forward (V19): Summary of GNUS.
+* gnus-Summary-sort-by-author (V19): Summary of GNUS.
+* gnus-Summary-sort-by-date (V19): Summary of GNUS.
+* gnus-Summary-sort-by-number (V19): Summary of GNUS.
+* gnus-Summary-sort-by-subject (V19): Summary of GNUS.
+* goto-char: Basic.
+* goto-line: Basic.
+* grep: Compilation.
+* gud-cont (V19): Commands of GUD.
+* gud-def (V19): GUD Customization.
+* gud-down (V19): Commands of GUD.
+* gud-finish (V19): Commands of GUD.
+* gud-next (V19): Commands of GUD.
+* gud-refresh (V19): Commands of GUD.
+* gud-step (V19): Commands of GUD.
+* gud-stepi (V19): Commands of GUD.
+* gud-up (V19): Commands of GUD.
+* hanoi: Amusements.
+* help-with-tutorial: Basic.
+* help-with-tutorial: Help.
+* hide-body: Outline Visibility.
+* hide-entry: Outline Visibility.
+* hide-leaves: Outline Visibility.
+* hide-subtree: Outline Visibility.
+* holidays (V19): Calendar.
+* iconify-frame (V19): New Commands.
+* indent-c-exp: Multi-line Indent.
+* indent-for-comment: Comments.
+* indent-new-comment-line: Comments.
+* indent-region: Multi-line Indent.
+* indent-region: Indentation Commands.
+* indent-relative: Indentation Commands.
+* indent-rigidly: Indentation Commands.
+* indent-sexp: Multi-line Indent.
+* indented-text-mode: Text Mode.
+* info: Help.
+* insert-abbrevs: Saving Abbrevs.
+* insert-anniversary-diary-entry (V19): New Entries.
+* insert-block-diary-entry (V19): New Entries.
+* insert-cyclic-diary-entry (V19): New Entries.
+* insert-diary-entry (V19): New Entries.
+* insert-file: Misc File Ops.
+* insert-kbd-macro: Save Kbd Macro.
+* insert-monthly-diary-entry (V19): New Entries.
+* insert-parentheses: Balanced Editing.
+* insert-register: RegText.
+* insert-weekly-diary-entry (V19): New Entries.
+* insert-yearly-diary-entry (V19): New Entries.
+* interrupt-shell-subjob: Shell Mode.
+* inverse-add-global-abbrev: Defining Abbrevs.
+* inverse-add-mode-abbrev: Defining Abbrevs.
+* isearch (V19): Search Changes.
+* isearch-backward: Incremental Search.
+* isearch-backward-regexp: Regexp Search.
+* isearch-backward-regexp (V19): New Commands.
+* isearch-forward: Incremental Search.
+* isearch-forward-regexp: Regexp Search.
+* ispell-buffer (V19): Spell Changes.
+* ispell-region (V19): Spell Changes.
+* just-one-space: Killing.
+* kbd-macro-query: Kbd Macro Query.
+* kill-all-abbrevs: Defining Abbrevs.
+* kill-buffer: Kill Buffer.
+* kill-comment: Comments.
+* kill-compilation: Compilation.
+* kill-ispell (V19): Spell Changes.
+* kill-line: Killing.
+* kill-line: Killing.
+* kill-local-variable: Locals.
+* kill-output-from-shell: Shell Mode.
+* kill-rectangle: Rectangles.
+* kill-region: Killing.
+* kill-sentence: Killing.
+* kill-sentence: Sentences.
+* kill-sexp: Lists.
+* kill-sexp: Killing.
+* kill-some-buffers: Kill Buffer.
+* kill-word: Killing.
+* kill-word: Words.
+* latex-mode: TeX Mode.
+* LaTeX-mode: TeX Mode.
+* lisp-complete-symbol: Lisp Completion.
+* lisp-indent-line: Basic Indent.
+* lisp-interaction-mode: Lisp Interaction.
+* lisp-mode: External Lisp.
+* lisp-send-defun: External Lisp.
+* list-abbrevs: Editing Abbrevs.
+* list-buffers: List Buffers.
+* list-command-history: Repetition.
+* list-directory: ListDir.
+* list-matching-lines: Other Repeating Search.
+* list-options: Edit Options.
+* list-tags: List Tags.
+* load: Loading.
+* load-file: Loading.
+* load-library: Loading.
+* local-set-key: Rebinding.
+* lpr-buffer: Hardcopy.
+* lpr-region: Hardcopy.
+* mail: Sending Mail.
+* mail-cc: Mail Mode.
+* mail-fill-yanked-message: Mail Mode.
+* mail-other-frame (V19): New Commands.
+* mail-other-window: Pop Up Window.
+* mail-other-window: Sending Mail.
+* mail-send: Mail Mode.
+* mail-send-and-exit: Mail Mode.
+* mail-signature: Mail Mode.
+* mail-subject: Mail Mode.
+* mail-to: Mail Mode.
+* mail-yank-original: Mail Mode.
+* mail-yank-original: Rmail Reply.
+* make-local-variable: Locals.
+* make-symbolic-link: Misc File Ops.
+* make-symbolic-link (V19): M-x Changes.
+* make-variable-buffer-local: Locals.
+* manual-entry: Documentation.
+* manual-entry (V19): M-x Changes.
+* mark-calendar-holidays (V19): Calendar.
+* mark-defun: Defuns.
+* mark-defun: Marking Objects.
+* mark-diary-entries (V19): Displaying Diary.
+* mark-fortran-subprogram: Fortran Motion.
+* mark-page: Pages.
+* mark-page: Marking Objects.
+* mark-paragraph: Paragraphs.
+* mark-paragraph: Marking Objects.
+* mark-sexp: Marking Objects.
+* mark-sexp: Lists.
+* mark-whole-buffer: Marking Objects.
+* mark-word: Marking Objects.
+* mark-word: Words.
+* minibuffer-complete: Completion.
+* minibuffer-complete-word: Completion.
+* modify-syntax-entry: Syntax Change.
+* move-over-close-and-reindent: Balanced Editing.
+* move-to-window-line: Basic.
+* name-last-kbd-macro: Save Kbd Macro.
+* narrow-to-region: Narrowing.
+* negative-argument: Arguments.
+* newline: Basic.
+* newline-and-indent: Basic Indent.
+* next-complex-command: Repetition.
+* next-error: Compilation.
+* next-file: Tags Stepping.
+* next-history-element (V19): New Facilities.
+* next-line: Basic.
+* next-matching-history-element (V19): New Facilities.
+* normal-mode: Choosing Modes.
+* not-modified: Saving.
+* nroff-mode: Nroff Mode.
+* occur: Other Repeating Search.
+* open-dribble-file: Bugs.
+* open-line: Blank Lines.
+* open-rectangle: Rectangles.
+* open-termscript: Bugs.
+* other-window: Other Window.
+* outline-backward-same-level: Outline Motion.
+* outline-forward-same-level: Outline Motion.
+* outline-mode: Outline Mode.
+* outline-next-visible-heading: Outline Motion.
+* outline-previous-visible-heading: Outline Motion.
+* outline-up-heading: Outline Motion.
+* overwrite-mode: Minor Modes.
+* picture-backward-clear-column: Basic Picture.
+* picture-backward-column: Basic Picture.
+* picture-clear-column: Basic Picture.
+* picture-clear-line: Basic Picture.
+* picture-clear-rectangle: Rectangles in Picture.
+* picture-clear-rectangle-to-register: Rectangles in Picture.
+* picture-forward-column: Basic Picture.
+* picture-motion: Insert in Picture.
+* picture-motion-reverse: Insert in Picture.
+* picture-move-down: Basic Picture.
+* picture-move-up: Basic Picture.
+* picture-movement-down: Insert in Picture.
+* picture-movement-left: Insert in Picture.
+* picture-movement-ne: Insert in Picture.
+* picture-movement-nw: Insert in Picture.
+* picture-movement-right: Insert in Picture.
+* picture-movement-se: Insert in Picture.
+* picture-movement-sw: Insert in Picture.
+* picture-movement-up: Insert in Picture.
+* picture-newline: Basic Picture.
+* picture-open-line: Basic Picture.
+* picture-set-tab-stops: Tabs in Picture.
+* picture-tab: Tabs in Picture.
+* picture-tab-search: Tabs in Picture.
+* picture-yank-rectangle: Rectangles in Picture.
+* picture-yank-rectangle-from-register: Rectangles in Picture.
+* plain-tex-mode: TeX Mode.
+* plain-TeX-mode: TeX Mode.
+* point-to-register: RegPos.
+* prepend-to-buffer: Accumulating Text.
+* previous-complex-command: Repetition.
+* previous-history-element (V19): New Facilities.
+* previous-line: Basic.
+* previous-matching-history-element (V19): New Facilities.
+* print-buffer: Hardcopy.
+* print-diary-entries (V19): Printing Diary.
+* print-region: Hardcopy.
+* query-replace: Query Replace.
+* query-replace-regexp: Query Replace.
+* quietly-read-abbrev-file: Saving Abbrevs.
+* quit-shell-subjob: Shell Mode.
+* quoted-insert: Basic.
+* re-search-backward: Regexp Search.
+* re-search-forward: Regexp Search.
+* read-abbrev-file: Saving Abbrevs.
+* recenter: Scrolling.
+* recenter: Basic.
+* recover-file: Recover.
+* register-to-point: RegPos.
+* reload-ispell (V19): Spell Changes.
+* rename-buffer: Misc Buffer.
+* rename-file: Misc File Ops.
+* repeat-complex-command: Repetition.
+* replace-regexp: Unconditional Replace.
+* replace-string: Unconditional Replace.
+* reposition-window (V19): New Commands.
+* revert-buffer: Reverting.
+* revert-buffer (Dired, V19): Editing Dired Buffer.
+* revert-buffer (V19): Basic Changes.
+* rmail: Rmail.
+* rmail-add-label: Rmail Labels.
+* rmail-beginning-of-message: Rmail Scrolling.
+* rmail-continue: Rmail Reply.
+* rmail-delete-backward: Rmail Deletion.
+* rmail-delete-forward: Rmail Deletion.
+* rmail-edit-current-message: Rmail Editing.
+* rmail-expunge: Rmail Deletion.
+* rmail-forward: Rmail Reply.
+* rmail-get-new-mail: Rmail Files.
+* rmail-input: Rmail Files.
+* rmail-kill-label: Rmail Labels.
+* rmail-last-message: Rmail Motion.
+* rmail-mail: Rmail Reply.
+* rmail-next-labeled-message: Rmail Labels.
+* rmail-next-message: Rmail Motion.
+* rmail-next-undeleted-message: Rmail Motion.
+* rmail-output: Rmail Output.
+* rmail-output-to-rmail-file: Rmail Output.
+* rmail-previous-labeled-message: Rmail Labels.
+* rmail-previous-message: Rmail Motion.
+* rmail-previous-undeleted-message: Rmail Motion.
+* rmail-quit: Rmail.
+* rmail-reply: Rmail Reply.
+* rmail-resend (V19): Mail Changes.
+* rmail-retry-failure (V19): Mail Changes.
+* rmail-save: Rmail.
+* rmail-search: Rmail Motion.
+* rmail-show-message: Rmail Motion.
+* rmail-summary: Rmail Make Summary.
+* rmail-summary-by-labels: Rmail Labels.
+* rmail-summary-by-labels: Rmail Make Summary.
+* rmail-summary-by-recipients: Rmail Make Summary.
+* rmail-summary-delete-forward: Rmail Summary Edit.
+* rmail-summary-exit: Rmail Summary Edit.
+* rmail-summary-goto-msg: Rmail Summary Edit.
+* rmail-summary-next-all: Rmail Summary Edit.
+* rmail-summary-next-msg: Rmail Summary Edit.
+* rmail-summary-previous-all: Rmail Summary Edit.
+* rmail-summary-previous-msg: Rmail Summary Edit.
+* rmail-summary-quit: Rmail Summary Edit.
+* rmail-summary-scroll-msg-down: Rmail Summary Edit.
+* rmail-summary-scroll-msg-up: Rmail Summary Edit.
+* rmail-summary-undelete: Rmail Summary Edit.
+* rmail-toggle-header: Rmail Editing.
+* rmail-undelete-previous-message: Rmail Deletion.
+* run-lisp: External Lisp.
+* save-buffer: Saving.
+* save-buffers-kill-emacs: Exiting.
+* save-some-buffers: Saving.
+* scroll-bar-mode (V19): Basic Changes.
+* scroll-down: Scrolling.
+* scroll-left: Horizontal Scrolling.
+* scroll-other-window: Other Window.
+* scroll-right: Horizontal Scrolling.
+* scroll-up: Scrolling.
+* sdb (V19): Starting GUD.
+* search-backward: Nonincremental Search.
+* search-forward: Nonincremental Search.
+* self-insert: Basic.
+* send-gud-command (V19): GUD Customization.
+* send-invisible (V19): Shell Changes.
+* send-shell-input: Shell Mode.
+* set-comment-column: Comments.
+* set-fill-column: Fill Commands.
+* set-fill-prefix: Fill Prefix.
+* set-gnu-bindings: Emulation.
+* set-goal-column: Basic.
+* set-gosmacs-bindings: Emulation.
+* set-mark-command: Setting Mark.
+* set-rmail-inbox-list: Rmail Files.
+* set-selective-display: Selective Display.
+* set-variable: Examining.
+* set-visited-file-name: Saving.
+* setq-default: Locals.
+* shell: Interactive Shell.
+* shell-command: Single Shell.
+* shell-command-on-region: Single Shell.
+* shell-send-eof: Shell Mode.
+* show-all: Outline Visibility.
+* show-all-diary-entries (V19): Displaying Diary.
+* show-branches: Outline Visibility.
+* show-children: Outline Visibility.
+* show-entry: Outline Visibility.
+* show-output-from-shell: Shell Mode.
+* show-subtree: Outline Visibility.
+* sort-columns: Sorting.
+* sort-fields: Sorting.
+* sort-lines: Sorting.
+* sort-numeric-fields: Sorting.
+* sort-pages: Sorting.
+* sort-paragraphs: Sorting.
+* spell-buffer: Spelling.
+* spell-region: Spelling.
+* spell-string: Spelling.
+* spell-word: Spelling.
+* split-line: Indentation Commands.
+* split-window-horizontally: Split Window.
+* split-window-vertically: Split Window.
+* start-kbd-macro: Basic Kbd Macro.
+* stop-shell-subjob: Shell Mode.
+* substitute-key-definition: Rebinding.
+* super-apropos (V19): New Commands.
+* suspend-emacs: Exiting.
+* switch-to-buffer: Select Buffer.
+* switch-to-buffer-other-frame (V19): New Commands.
+* switch-to-buffer-other-window: Pop Up Window.
+* tab-to-tab-stop: Text Mode.
+* tab-to-tab-stop: Tab Stops.
+* tabify: Just Spaces.
+* tags-apropos: List Tags.
+* tags-loop-continue: Tags Search.
+* tags-query-replace: Tags Search.
+* tags-search: Tags Search.
+* tex-bibtex-file (V19): TeX Mode Changes.
+* TeX-buffer: TeX Print.
+* TeX-close-LaTeX-block: TeX Editing.
+* tex-close-latex-block (V19): TeX Mode Changes.
+* TeX-insert-braces: TeX Editing.
+* TeX-insert-quote: TeX Editing.
+* TeX-kill-job: TeX Print.
+* tex-latex-block (V19): TeX Mode Changes.
+* tex-mode: TeX Mode.
+* TeX-mode: TeX Mode.
+* TeX-print: TeX Print.
+* TeX-recenter-output-buffer: TeX Print.
+* TeX-region: TeX Print.
+* TeX-show-print-queue: TeX Print.
+* TeX-terminate-paragraph: TeX Editing.
+* tex-view (V19): TeX Mode Changes.
+* texinfo-mode: Texinfo Mode.
+* text-mode: Text Mode.
+* toggle-read-only: Misc Buffer.
+* top-level: Recursive Edit.
+* top-level: Quitting.
+* transpose-chars: Transpose.
+* transpose-chars: Basic.
+* transpose-lines: Transpose.
+* transpose-sexps: Lists.
+* transpose-sexps: Transpose.
+* transpose-words: Transpose.
+* transpose-words: Words.
+* undigestify-rmail-message: Rmail Digest.
+* undo: Undo.
+* unexpand-abbrev: Expanding Abbrevs.
+* universal-argument: Arguments.
+* unrmail: Mail Changes.
+* untabify: Just Spaces.
+* up-list: TeX Editing.
+* upcase-region: Case.
+* upcase-word: Fixing Case.
+* upcase-word: Case.
+* validate-TeX-buffer: TeX Editing.
+* vc-cancel-version (V19): Editing with VC.
+* vc-create-snapshot (V19): Making Snapshots.
+* vc-diff (V19): Comparing Versions.
+* vc-directory (V19): VC Status.
+* vc-insert-headers (V19): Version Headers.
+* vc-print-log (V19): VC Status.
+* vc-register (V19): Editing with VC.
+* vc-rename-file (V19): Renaming and VC.
+* vc-retrieve-snapshot (V19): Making Snapshots.
+* vc-revert-buffer (V19): Editing with VC.
+* vc-toggle-read-only (V19): Editing with VC.
+* vc-update-change-log (V19): Change Logs and VC.
+* vi-mode: Emulation.
+* view-buffer: Misc Buffer.
+* view-buffer (V19): M-x Changes.
+* view-diary-entries (V19): Displaying Diary.
+* view-emacs-news: Help.
+* view-file: Misc File Ops.
+* view-file (V19): M-x Changes.
+* view-lossage: Help.
+* view-register: Registers.
+* vip-mode: Emulation.
+* visit-tags-table: Select Tag Table.
+* what-cursor-position: Position Info.
+* what-line: Position Info.
+* what-page: Position Info.
+* where-is: Help.
+* widen: Narrowing.
+* word-search-backward: Word Search.
+* word-search-forward: Word Search.
+* write-abbrev-file: Saving Abbrevs.
+* write-file: Saving.
+* write-region: Misc File Ops.
+* Yank: Kill Ring.
+* yank-pop: Earlier Kills.
+* yank-rectangle: Rectangles.
+* yow: Amusements.
+* zap-to-char: Killing.
+
+
+File: emacs, Node: Variable Index, Next: Concept Index, Prev: Command Index, Up: Top
+
+Variable Index
+**************
+
+* Menu:
+
+* abbrev-all-caps: Expanding Abbrevs.
+* abbrev-file-name: Saving Abbrevs.
+* abbrev-mode: Abbrevs.
+* auto-mode-alist: Choosing Modes.
+* auto-save-default: Auto Save Control.
+* auto-save-interval: Auto Save Control.
+* auto-save-timeout (V19): Basic Changes.
+* auto-save-visited-file-name: Auto Save Files.
+* backup-by-copying: Backup Copying.
+* backup-by-copying-when-linked: Backup Copying.
+* backup-by-copying-when-mismatch: Backup Copying.
+* blink-matching-paren: Matching.
+* blink-matching-paren-distance: Matching.
+* buffer-read-only: Misc Buffer.
+* c-argdecl-indent: C Indent.
+* c-auto-newline: C Indent.
+* c-brace-imaginary-offset: C Indent.
+* c-brace-offset: C Indent.
+* c-continued-statement-offset: C Indent.
+* c-indent-level: C Indent.
+* c-label-offset: C Indent.
+* c-mode-hook: Program Modes.
+* c-mode-map: Keymaps.
+* c-tab-always-indent: C Indent.
+* case-fold-search: Replacement and Case.
+* case-fold-search: Search Case.
+* case-replace: Replacement and Case.
+* command-history: Repetition.
+* command-line-args: Command Switches.
+* comment-column: Comments.
+* comment-end: Comments.
+* comment-indent-hook: Comments.
+* comment-line-start: Fortran Comments.
+* comment-line-start-skip: Fortran Comments.
+* comment-multi-line: Comments.
+* comment-start: Comments.
+* comment-start-skip: Comments.
+* compile-command: Compilation.
+* completion-auto-help: Completion.
+* completion-ignored-extensions: Completion.
+* ctl-arrow: Display Vars.
+* ctl-x-map: Keymaps.
+* dbx-mode-hook: GUD Customization.
+* debug-on-error: Lisp Debug.
+* debug-on-quit: Lisp Debug.
+* default-directory: File Names.
+* default-major-mode: Choosing Modes.
+* delete-auto-save-files: Auto Save Files.
+* diary-display-hook (V19): Simple and Fancy.
+* diary-file (V19): Diary Entries.
+* diff-switches (V19): New Commands.
+* dired-chown-program (V19): Multiple Files.
+* dired-copy-preserve-time (V19): Multiple Files.
+* dired-kept-versions: Dired Deletion.
+* dired-listing-switches: Dired Enter.
+* echo-keystrokes: Display Vars.
+* emacs-lisp-mode-hook: Program Modes.
+* emerge-combine-template (V19): Combining in Emerge.
+* emerge-startup-hook (V19): Fine Points of Emerge.
+* enable-local-variables (V19): Basic Changes.
+* enable-recursive-minibuffers: Minibuffer Edit.
+* esc-map: Keymaps.
+* european-calendar-style (V19): European Calendar Style.
+* explicit-shell-file-name: Interactive Shell.
+* fill-column: Fill Commands.
+* fill-prefix: Fill Prefix.
+* find-file-hooks: Visiting.
+* find-file-not-found-hooks: Visiting.
+* find-file-run-dired: Visiting.
+* fortran-check-all-num-for-matching-do: ForIndent Vars.
+* fortran-column-ruler: Fortran Columns.
+* fortran-comment-indent-char: Fortran Comments.
+* fortran-comment-indent-style: Fortran Comments.
+* fortran-comment-line-column: Fortran Comments.
+* fortran-comment-region: Fortran Comments.
+* fortran-continuation-char: ForIndent Conv.
+* fortran-continuation-indent: ForIndent Vars.
+* fortran-do-indent: ForIndent Vars.
+* fortran-electric-line-number: ForIndent Num.
+* fortran-if-indent: ForIndent Vars.
+* fortran-line-number-indent: ForIndent Num.
+* fortran-minimum-statement-indent: ForIndent Vars.
+* gdb-mode-hook: GUD Customization.
+* global-map: Keymaps.
+* help-map: Keymaps.
+* indent-tabs-mode: Just Spaces.
+* Info-directory-list (V19): Info Changes.
+* INFOPATH: Info Changes.
+* inhibit-local-variables: File Variables.
+* inhibit-local-variables (V19): Basic Changes.
+* initial-major-mode: Entering Emacs.
+* insert-default-directory: Minibuffer File.
+* insert-default-directory: File Names.
+* inverse-video: Display Vars.
+* kept-new-versions: Backup Deletion.
+* kept-old-versions: Backup Deletion.
+* kill-buffer-hook (V19): Hook Changes.
+* kill-ring-max: Earlier Kills.
+* LaTeX-mode-hook: TeX Print.
+* lisp-body-indent: Lisp Indent.
+* lisp-indent-offset: Lisp Indent.
+* lisp-interaction-mode-hook: Program Modes.
+* lisp-mode-hook: Program Modes.
+* lisp-mode-map: Keymaps.
+* list-directory-brief-switches: ListDir.
+* list-directory-verbose-switches: ListDir.
+* load-path: Loading.
+* lpr-command: Hardcopy.
+* lpr-switches: Hardcopy.
+* mail-archive-file-name: Mail Headers.
+* mail-default-reply-to: Mail Headers.
+* mail-header-separator: Mail Format.
+* mail-mode-hook: Mail Mode.
+* mail-setup-hook: Mail Mode.
+* mail-signature (V19): Mail Changes.
+* mail-yank-prefix (V19): Mail Changes.
+* make-backup-files: Backup.
+* mark-ring: Mark Ring.
+* mark-ring-max: Mark Ring.
+* meta-flag: Characters.
+* minibuffer-local-completion-map: Keymaps.
+* minibuffer-local-map: Keymaps.
+* minibuffer-local-must-match-map: Keymaps.
+* minibuffer-local-ns-map: Keymaps.
+* mode-line-inverse-video: Display Vars.
+* mode-line-inverse-video: Mode Line.
+* muddle-mode-hook: Program Modes.
+* next-screen-context-lines: Scrolling.
+* no-redraw-on-reenter: Display Vars.
+* nroff-mode-hook: Nroff Mode.
+* outline-mode-hook: Outline Mode.
+* outline-regexp: Outline Format.
+* page-delimiter: Pages.
+* paragraph-separate: Paragraphs.
+* paragraph-start: Paragraphs.
+* parse-sexp-ignore-comments: Syntax Entry.
+* picture-mode-hook: Picture.
+* picture-tab-chars: Tabs in Picture.
+* plain-TeX-mode-hook: TeX Print.
+* pre-abbrev-expand-hook (V19): Hook Changes.
+* repeat-complex-command-map: Keymaps.
+* require-final-newline: Saving.
+* rmail-dont-reply-to: Rmail Reply.
+* rmail-edit-mode-hook: Rmail Editing.
+* rmail-ignored-headers: Rmail Editing.
+* rmail-output-file-alist: Mail Changes.
+* save-abbrevs: Saving Abbrevs.
+* scheme-mode-hook: Program Modes.
+* scroll-step: Scrolling.
+* sdb-mode-hook: GUD Customization.
+* search-delete-char: Incremental Search.
+* search-exit-char: Incremental Search.
+* search-quote-char: Incremental Search.
+* search-repeat-char: Incremental Search.
+* search-reverse-char: Incremental Search.
+* search-slow-speed: Incremental Search.
+* search-slow-window-lines: Incremental Search.
+* search-yank-line-char: Incremental Search.
+* search-yank-word-char: Incremental Search.
+* selective-display-ellipses: Outline Visibility.
+* selective-display-ellipses: Display Vars.
+* sentence-end: Sentences.
+* shell-cd-regexp: Interactive Shell.
+* shell-file-name: Single Shell.
+* shell-popd-regexp: Interactive Shell.
+* shell-prompt-pattern: Shell Mode.
+* shell-pushd-regexp: Interactive Shell.
+* shell-set-directory-error-hook: Interactive Shell.
+* split-window-keep-point (V19): Changed Commands.
+* tab-stop-list: Tab Stops.
+* tab-width: Display Vars.
+* tags-file-name: Select Tag Table.
+* term-file-prefix: Terminal Init.
+* term-setup-hook: Terminal Init.
+* tex-directory (V19): TeX Mode Changes.
+* TeX-mode-hook: TeX Print.
+* text-mode-hook: Text Mode.
+* track-eol: Basic.
+* trim-versions-without-asking: Backup Deletion.
+* truncate-lines: Continuation Lines.
+* truncate-partial-width-windows: Split Window.
+* undo-limit: Undo.
+* undo-strong-limit: Undo.
+* vc-command-messages (V19): Variables for Check-in/out.
+* vc-comment-alist (V19): Version Headers.
+* vc-header-string (V19): Version Headers.
+* vc-initial-comment (V19): Editing with VC.
+* vc-keep-workfiles (V19): Editing with VC.
+* vc-log-mode-hook (V19): Log Entries.
+* vc-make-backups (V19): Editing with VC.
+* vc-mistrust-permissions (V19): Variables for Check-in/out.
+* vc-static-header-alist (V19): Version Headers.
+* vc-suppress-confirm (V19): Variables for Check-in/out.
+* version-control: Backup Names.
+* version-control (V19): New Facilities.
+* VERSION_CONTROL: New Facilities.
+* visible-bell: Display Vars.
+* window-min-height: Change Window.
+* window-min-width: Change Window.
+* write-file-hooks: Saving.
+
+ \ No newline at end of file
diff --git a/info/emacs-19 b/info/emacs-19
new file mode 100644
index 00000000000..1b59f6e0da7
--- /dev/null
+++ b/info/emacs-19
@@ -0,0 +1,445 @@
+This is Info file ../info/emacs, produced by Makeinfo-1.49 from the
+input file emacs.texi.
+
+ This file documents the GNU Emacs editor.
+
+ Copyright (C) 1985, 1986, 1988, 1992 Richard M. Stallman.
+
+ Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+ Permission is granted to copy and distribute modified versions of
+this manual under the conditions for verbatim copying, provided also
+that the sections entitled "The GNU Manifesto", "Distribution" and "GNU
+General Public License" are included exactly as in the original, and
+provided that the entire resulting derived work is distributed under the
+terms of a permission notice identical to this one.
+
+ Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that the sections entitled "The GNU Manifesto",
+"Distribution" and "GNU General Public License" may be included in a
+translation approved by the author instead of in the original English.
+
+
+File: emacs, Node: Concept Index, Next: Screen, Prev: Variable Index, Up: Top
+
+Concept Index
+*************
+
+* Menu:
+
+* find and Dired: Dired and Find.
+* ispell program (V19): Spell Changes.
+* GNUS: GNUS.
+* A and B buffers (Emerge): Overview of Emerge.
+* Abbrev mode: Abbrevs.
+* abbrevs: Abbrevs.
+* aborting: Quitting.
+* Adaptive Fill mode: Filling Changes.
+* againformation: Dissociated Press.
+* American date style (Calendar, V19): European Calendar Style.
+* apropos: Help.
+* arguments (from shell): Command Switches.
+* arguments, prefix and numeric: Arguments.
+* arrow keys: New Commands.
+* ASCII: Characters.
+* Asm mode (V19): Asm Mode.
+* astronomical calendar: Calendar.
+* attribute (Rmail): Rmail Labels.
+* Auto Fill mode: Auto Fill.
+* Auto-Save mode: Auto Save.
+* autoload: Loading.
+* Backtrace mode: Lisp Debug.
+* backup file: Backup.
+* backups, automatic deleting of: Backup Deletion.
+* batch mode: Command Switches.
+* binding: Commands.
+* blank lines: Comments.
+* blank lines: Blank Lines.
+* body lines (Outline mode): Outline Format.
+* boredom: Amusements.
+* buffer locking: Interlocking.
+* buffer menu: Several Buffers.
+* Buffer Menu mode: Several Buffers.
+* Buffer Menu mode (V19): Other New Modes.
+* buffers: Buffers.
+* buggestion: Dissociated Press.
+* bugs: Bugs.
+* byte code: Compiling Libraries.
+* C mode: Program Modes.
+* C++ mode (V19): Other New Modes.
+* C-: Characters.
+* C-g: Quitting.
+* calendar (V19): Calendar.
+* case conversion: Case.
+* case conversion: Fixing Case.
+* case conversion of file names (V19): Dired Case Conversion.
+* centering: Fill Commands.
+* change buffers: Select Buffer.
+* change log: Change Log.
+* character set: Characters.
+* checking in files: Concepts of VC.
+* checking out files: Concepts of VC.
+* choosing a mode: Choosing Modes.
+* clipping text: Killing.
+* command: Key Bindings.
+* command: Commands.
+* command history: Repetition.
+* command line arguments: Command Switches.
+* command name: Key Bindings.
+* comments: Comments.
+* compilation errors: Compilation.
+* completion: Completion.
+* completion (symbol names): Lisp Completion.
+* continuation line: Continuation Lines.
+* Control: Characters.
+* Control-Meta: Lists.
+* copying files: Misc File Ops.
+* copying text: Yanking.
+* crashes: Auto Save.
+* creating files: Visiting.
+* current buffer: Buffers.
+* current stack frame: Lisp Debug.
+* cursor: Basic.
+* cursor: Point.
+* customization: Customization.
+* customization: Lisp Indent.
+* customization: Commands.
+* cutting: Killing.
+* dates, style of writing (Calendar, V19): European Calendar Style.
+* DBX: Debuggers.
+* debugger: Lisp Debug.
+* debuggers: Debuggers.
+* default argument: Minibuffer.
+* defuns: Defuns.
+* deletion: Killing.
+* deletion: Basic.
+* deletion (of files): Dired.
+* deletion (of files): Misc File Ops.
+* deletion (Rmail): Rmail Deletion.
+* diary and Emacs startup (V19): Startup Diary.
+* diary display (V19): Displaying Diary.
+* diary entries (V19): Diary Entries.
+* diary entries, inserting (V19): New Entries.
+* digest message: Rmail Digest.
+* directory listing: ListDir.
+* Dired: Dired.
+* Dired in V19: Dired Changes.
+* Dired mode: Dired Enter.
+* Dired multiple file ops (V19): Multiple Files.
+* disabled command: Disabling.
+* disassemble: Compiling Libraries.
+* display of diary (V19): Displaying Diary.
+* display time: Mode Line.
+* Distribution: License.
+* doctor: Total Frustration.
+* drastic changes: Reverting.
+* dribble file: Bugs.
+* dynamic abbrevs: Dynamic Abbrevs.
+* echo area: Echo Area.
+* Edebug mode (V19): Edebug Mode.
+* Edit-Abbrevs mode: Editing Abbrevs.
+* editing binary files (V19): Editing Binary Files.
+* editing level, recursive: Recursive Edit.
+* editing level, recursive: Quitting.
+* EDT: Emulation.
+* Electric Nroff mode: Nroff Mode.
+* Eliza: Total Frustration.
+* Emacs initialization file: Init File.
+* Emacs version: Bugs.
+* Emacs-Lisp mode: Lisp Eval.
+* Emerge (V19): Emerge.
+* entering Emacs: Entering Emacs.
+* environment: Single Shell.
+* error log: Compilation.
+* ESC replacing META key: Characters.
+* etags program: Create Tag Table.
+* European calendar style (V19): European Calendar Style.
+* European date style (Calendar, V19): European Calendar Style.
+* exiting: Exiting.
+* exiting: Recursive Edit.
+* expanded subdirectory (Dired, V19): Subdirectories in Dired.
+* expanding subdirectories in Dired (V19): Subdirectories in Dired.
+* expansion (of abbrevs): Abbrevs.
+* expansion of C macros: Macro Expansion.
+* expression: Lists.
+* expressions, regular: Regexp Search.
+* expunging (Rmail): Rmail Deletion.
+* Fancy Diary mode (V19): Simple and Fancy.
+* file dates: Interlocking.
+* file directory: ListDir.
+* file names: File Names.
+* files: Files.
+* files: Basic.
+* files: Visiting.
+* fill prefix: Fill Prefix.
+* filling: Filling.
+* flow control in V19: New Facilities.
+* formfeed: Pages.
+* Fortran mode: Fortran.
+* forward a message: Rmail Reply.
+* French revolutionary calendar: Calendar.
+* ftp: New Facilities.
+* function: Key Bindings.
+* function: Commands.
+* function keys (V19): Key Sequence Changes.
+* GDB: Debuggers.
+* General Public License: License.
+* global keymap: Keymaps.
+* global substitution: Replace.
+* goal column: Basic.
+* graphic characters: Basic.
+* grinding: Grinding.
+* hardcopy: Hardcopy.
+* header (TeX mode): TeX Print.
+* headerline (Dired, V19): Subdirectories in Dired.
+* headers (of mail message): Mail Headers.
+* heading lines (Outline mode): Outline Format.
+* Hebrew calendar: Calendar.
+* help: Help.
+* Hexl mode (V19): Editing Binary Files.
+* hiding in Dired (Dired, V19): Hiding Subdirectories.
+* history of commands: Repetition.
+* history, in minibuffer: New Facilities.
+* hook variable (V19): Hook Changes.
+* hooks for files: Visiting.
+* horizontal scrolling: Horizontal Scrolling.
+* ignoriginal: Dissociated Press.
+* in-situ subdirectory (Dired, V19): Subdirectories in Dired.
+* inbox file: Rmail Inbox.
+* Incremental search in V19: Search Changes.
+* indentation: Comments.
+* indentation: Indentation.
+* indentation: Grinding.
+* indentation: Indentation.
+* Indented Text mode: Text Mode.
+* Inferior Lisp mode: External Lisp.
+* inferior process: Compilation.
+* Inferior Scheme mode: Lisp Modes.
+* Info mode in V19: Info Changes.
+* init file: Init File.
+* inserted subdirectory (Dired, V19): Subdirectories in Dired.
+* insertion: Basic.
+* interlocking buffers: Interlocking.
+* invisible lines: Outline Mode.
+* Islamic calendar: Calendar.
+* ISO commercial calendar: Calendar.
+* Julian calendar: Calendar.
+* Julian day number: Calendar.
+* justification: Fill Commands.
+* key: Keys.
+* key rebinding, permanent: Init File.
+* key rebinding, this session: Rebinding.
+* key sequence changes (V19): Key Sequence Changes.
+* keyboard macros: Keyboard Macros.
+* keymap: Commands.
+* keymap: Keymaps.
+* kill ring: Yanking.
+* killing: Killing.
+* killing Emacs: Exiting.
+* label (Rmail): Rmail Labels.
+* LaTeX: TeX Mode.
+* libraries: Lisp Libraries.
+* license to copy Emacs: License.
+* line number: Position Info.
+* Lisp Interaction mode: Lisp Interaction.
+* Lisp mode: Lisp Modes.
+* Lisp mode: Program Modes.
+* list: Lists.
+* listing a directory: ListDir.
+* loading Lisp code: Lisp Libraries.
+* local keymap: Keymaps.
+* local variables: Locals.
+* local variables and Auto Fill: File Variables.
+* local variables in files: File Variables.
+* locking and version control: Concepts of VC.
+* locking buffers: Interlocking.
+* M-: Characters.
+* macro expansion in C: Macro Expansion.
+* mail: Sending Mail.
+* mail arrival: Mode Line.
+* Mail mode: Mail Mode.
+* Mail mode in V19: Mail Changes.
+* major modes: Major Modes.
+* make: Compilation.
+* margin position: Variables.
+* mark: Mark.
+* mark ring: Mark Ring.
+* Markov chain: Dissociated Press.
+* Marks in Dired (V19): Marks in Dired.
+* master file: Concepts of VC.
+* matching parentheses: Matching.
+* Mayan calendar: Calendar.
+* merge buffer (Emerge): Overview of Emerge.
+* merging files (V19): Emerge.
+* message: Sending Mail.
+* message: Rmail.
+* message number: Rmail.
+* Meta: Characters.
+* Meta: Words.
+* minibuffer: M-x.
+* minibuffer: Minibuffer.
+* minibuffer: Keymaps.
+* minibuffer history: New Facilities.
+* minor modes: Minor Modes.
+* mistakes, correcting: Undo.
+* mistakes, correcting: Fixit.
+* mocklisp: Mocklisp.
+* mode hook: Program Modes.
+* mode line: Mode Line.
+* mode line: Minor Modes.
+* mode selection: Choosing Modes.
+* modified (buffer): Visiting.
+* mouse buttons (V19): Key Sequence Changes.
+* moving text: Yanking.
+* Multiple file ops, Dired (V19): Multiple Files.
+* named configurations (RCS): Snapshot Caveats.
+* narrowing: Narrowing.
+* newline: Basic.
+* nonincremental search: Nonincremental Search.
+* normal hook (V19): Hook Changes.
+* nroff: Nroff Mode.
+* Nroff mode: Nroff Mode.
+* numeric arguments: Arguments.
+* option: Examining.
+* option: Variables.
+* Options mode: Edit Options.
+* other editors: Emulation.
+* Outline mode: Outline Mode.
+* outlines: Outline Mode.
+* outragedy: Dissociated Press.
+* Overwrite mode: Minor Modes.
+* pages: Pages.
+* paragraphs: Paragraphs.
+* parentheses: Matching.
+* pasting: Yanking.
+* per-buffer variables: Locals.
+* Picture mode: Picture.
+* pictures: Picture.
+* point: Basic.
+* point: Point.
+* prefix arguments: Arguments.
+* prefix key: Keys.
+* presidentagon: Dissociated Press.
+* primary mail file: Rmail.
+* Printing diary (V19): Printing Diary.
+* prompt: Minibuffer.
+* properbose: Dissociated Press.
+* query replace: Query Replace.
+* quitting: Quitting.
+* quitting: Quitting.
+* quitting (in search): Incremental Search.
+* quoting: Basic.
+* RCS: Concepts of VC.
+* read-only buffer: Misc Buffer.
+* reading netnews: GNUS.
+* rebinding keys, permanently: Init File.
+* rebinding keys, this session: Rebinding.
+* rebinding keys, this session: Rebinding.
+* rectangles: Rectangles.
+* rectangles and Picture mode: Rectangles in Picture.
+* recursive editing level: Quitting.
+* recursive editing level: Recursive Edit.
+* recursive minibuffer: Minibuffer Edit.
+* regexp: Regexp Search.
+* region: Case.
+* region: Mark.
+* registered file: Concepts of VC.
+* registers: Registers.
+* regular expression: Regexp Search.
+* remote file access: New Facilities.
+* replacement: Replace.
+* reply to a message: Rmail Reply.
+* restriction: Narrowing.
+* right margin position: Variables.
+* Rmail: Rmail.
+* Rmail in V19: Mail Changes.
+* Rmail mode: Rmail.
+* Rmail Summary mode: Rmail Summary Edit.
+* saving: Visiting.
+* SCCS: Concepts of VC.
+* Scheme mode: Program Modes.
+* Scheme mode: Lisp Modes.
+* scratch buffer: Lisp Interaction.
+* screen: Screen.
+* scrolling: Scrolling.
+* SDB: Debuggers.
+* searching: Search.
+* selected buffer: Buffers.
+* selected window: Basic Window.
+* selection of mode: Choosing Modes.
+* selective display: Outline Mode.
+* self-documentation: Help.
+* sentences: Sentences.
+* setting variables: Examining.
+* sexp: Lists.
+* shell commands: Shell.
+* shell commands, Dired V19: Shell Commands in Dired.
+* Shell mode: Shell Mode.
+* Shell mode in V19: Shell Changes.
+* Simple Diary mode (V19): Simple and Fancy.
+* simultaneous editing: Interlocking.
+* snapshots and version control: Snapshots.
+* sorting: Sorting.
+* sparse keymap: Keymaps.
+* Spell checking in V19: Spell Changes.
+* spelling: Spelling.
+* string substitution: Replace.
+* subdirectories in Dired (V19): Subdirectories in Dired.
+* subscribe newsgroups (V19): Summary of GNUS.
+* subshell: Shell.
+* subtree (Outline mode): Outline Visibility.
+* summaries in Rmail: Rmail Summary Edit.
+* summary (Rmail): Rmail Summary.
+* suspending: Exiting.
+* switch buffers: Select Buffer.
+* syntax table: Syntax.
+* syntax table: Words.
+* tag table: Tags.
+* tags in V19: Tags Changes.
+* techniquitous: Dissociated Press.
+* television: Appending Kills.
+* termscript file: Bugs.
+* TeX: TeX Mode.
+* TeX mode: TeX Mode.
+* Tex mode in V19: TeX Mode Changes.
+* Texinfo mode: Texinfo Mode.
+* text: Text.
+* Text mode: Text Mode.
+* time displayed in mode line: Mode Line.
+* top level: Mode Line.
+* transposition: Transpose.
+* transposition: Words.
+* transposition: Lists.
+* truncation: Continuation Lines.
+* typos: Fixit.
+* undeletion (Rmail): Rmail Deletion.
+* undigestify: Rmail Digest.
+* undo: Undo.
+* universal argument: Arguments.
+* unsubscribe newsgroups (V19): Summary of GNUS.
+* variables: Variables.
+* version control: Version Control.
+* version of Emacs: Bugs.
+* versions, keeping old: Backup Deletion.
+* vi: Emulation.
+* VI mode: Emulation.
+* View mode: Misc Buffer.
+* viewing: Misc File Ops.
+* visiting: Visiting.
+* visiting files: Visiting.
+* widening: Narrowing.
+* windows: Windows.
+* word search: Word Search.
+* words: Words.
+* words: Case.
+* words: Fixing Case.
+* WordStar mode (V19): Other New Modes.
+* work file: Concepts of VC.
+* wrapping: Filling.
+* xon-xoff in V19: New Facilities.
+* yanking: Yanking.
+
+
diff --git a/info/emacs-2 b/info/emacs-2
new file mode 100644
index 00000000000..f8a7470f13d
--- /dev/null
+++ b/info/emacs-2
@@ -0,0 +1,1133 @@
+This is Info file ../info/emacs, produced by Makeinfo-1.49 from the
+input file emacs.texi.
+
+ This file documents the GNU Emacs editor.
+
+ Copyright (C) 1985, 1986, 1988, 1992 Richard M. Stallman.
+
+ Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+ Permission is granted to copy and distribute modified versions of
+this manual under the conditions for verbatim copying, provided also
+that the sections entitled "The GNU Manifesto", "Distribution" and "GNU
+General Public License" are included exactly as in the original, and
+provided that the entire resulting derived work is distributed under the
+terms of a permission notice identical to this one.
+
+ Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that the sections entitled "The GNU Manifesto",
+"Distribution" and "GNU General Public License" may be included in a
+translation approved by the author instead of in the original English.
+
+
+File: emacs, Node: Commands, Next: Entering Emacs, Prev: Keys, Up: Top
+
+Keys and Commands
+=================
+
+ This manual is full of passages that tell you what particular keys
+do. But Emacs does not assign meanings to keys directly. Instead, Emacs
+assigns meanings to "functions", and then gives keys their meanings by
+"binding" them to functions.
+
+ A function is a Lisp object that can be executed as a program.
+Usually it is a Lisp symbol which has been given a function definition;
+every symbol has a name, usually made of a few English words separated
+by dashes, such as `next-line' or `forward-word'. It also has a
+"definition" which is a Lisp program; this is what makes the function
+do what it does. Only some functions can be the bindings of keys;
+these are functions whose definitions use `interactive' to specify how
+to call them interactively. Such functions are called "commands", and
+their names are "command names". *Note Defining Commands:
+(elisp)Defining Commands, for more information.
+
+ The bindings between keys and functions are recorded in various
+tables called "keymaps". *Note Keymaps::.
+
+ When we say that "`C-n' moves down vertically one line" we are
+glossing over a distinction that is irrelevant in ordinary use but is
+vital in understanding how to customize Emacs. It is the function
+`next-line' that is programmed to move down vertically. `C-n' has this
+effect because it is bound to that function. If you rebind `C-n' to
+the function `forward-word' then `C-n' will move forward by words
+instead. Rebinding keys is a common method of customization.
+
+ In the rest of this manual, we usually ignore this subtlety to keep
+things simple. To give the customizer the information he needs, we
+state the name of the command which really does the work in parentheses
+after mentioning the key that runs it. For example, we will say that
+"The command `C-n' (`next-line') moves point vertically down," meaning
+that `next-line' is a command that moves vertically down and `C-n' is a
+key that is standardly bound to it.
+
+ While we are on the subject of information for customization only,
+it's a good time to tell you about "variables". Often the description
+of a command will say, "To change this, set the variable `mumble-foo'."
+A variable is a name used to remember a value. Most of the variables
+documented in this manual exist just to facilitate customization: some
+command or other part of Emacs examines the variable and behaves
+differently accordingly. Until you are interested in customizing, you
+can ignore the information about variables. When you are ready to be
+interested, read the basic information on variables, and then the
+information on individual variables will make sense. *Note Variables::.
+
+
+File: emacs, Node: Entering Emacs, Next: Exiting, Prev: Commands, Up: Top
+
+Entering and Exiting Emacs
+**************************
+
+ The usual way to invoke Emacs is just to type `emacs RET' at the
+shell. Emacs clears the screen and then displays an initial advisor
+message and copyright notice. You can begin typing Emacs commands
+immediately afterward.
+
+ Some operating systems insist on discarding all type-ahead when Emacs
+starts up; they give Emacs no way to prevent this. Therefore, it is
+wise to wait until Emacs clears the screen before typing your first
+editing command.
+
+ Before Emacs reads the first command, you have not had a chance to
+give a command to specify a file to edit. But Emacs must always have a
+current buffer for editing. In an attempt to do something useful,
+Emacs presents a buffer named `*scratch*' which is in Lisp Interaction
+mode; you can use it to type Lisp expressions and evaluate them, or you
+can ignore that capability and simply doodle. (You can specify a
+different major mode for this buffer by setting the variable
+`initial-major-mode' in your init file. *Note Init File::.)
+
+ It is also possible to specify files to be visited, Lisp files to be
+loaded, and functions to be called, by giving Emacs arguments in the
+shell command line. *Note Command Switches::.
+
+
+File: emacs, Node: Exiting, Next: Command Switches, Prev: Entering Emacs, Up: Top
+
+Exiting Emacs
+=============
+
+ There are two commands for exiting Emacs because there are two kinds
+of exiting: "suspending" Emacs and "killing" Emacs. "Suspending" means
+stopping Emacs temporarily and returning control to its superior
+(usually the shell), allowing you to resume editing later in the same
+Emacs job, with the same files, same kill ring, same undo history, and
+so on. This is the usual way to exit. "Killing" Emacs means
+destroying the Emacs job. You can run Emacs again later, but you will
+get a fresh Emacs; there is no way to resume the same editing session
+after it has been killed.
+
+`C-z'
+ Suspend Emacs (`suspend-emacs').
+
+`C-x C-c'
+ Kill Emacs (`save-buffers-kill-emacs').
+
+ To suspend Emacs, type `C-z' (`suspend-emacs'). This takes you back
+to the shell from which you invoked Emacs. You can resume Emacs with
+the command `%emacs' if you are using the C shell or the Bourne-Again
+shell.
+
+ On systems that do not permit programs to be suspended, `C-z' runs an
+inferior shell that communicates directly with the terminal, and Emacs
+waits until you exit the subshell. The only way on these systems to get
+back to the shell from which Emacs was run (to log out, for example) is
+to kill Emacs. `C-d' or `exit' are typical commands to exit a subshell.
+
+ To kill Emacs, type `C-x C-c' (`save-buffers-kill-emacs'). A
+two-character key is used for this to make it harder to type. Unless a
+numeric argument is used, this command first offers to save any modified
+buffers. If you do not save them all, it asks for reconfirmation with
+`yes' before killing Emacs, since any changes not saved before that
+will be lost forever. Also, if any subprocesses are still running,
+`C-x C-c' asks for confirmation about them, since killing Emacs will
+kill the subprocesses immediately.
+
+ In most programs running on Unix, certain characters may instantly
+suspend or kill the program. (In Berkeley Unix these characters are
+normally `C-z' and `C-c'.) This Unix feature is turned off while you
+are in Emacs. The meanings of `C-z' and `C-x C-c' as keys in Emacs
+were inspired by the standard Berkeley Unix meanings of `C-z' and
+`C-c', but that is their only relationship with Unix. You could
+customize these keys to do anything (*note Keymaps::.).
+
+
+File: emacs, Node: Command Switches, Next: Basic, Prev: Exiting, Up: Top
+
+Command Line Switches and Arguments
+===================================
+
+ GNU Emacs supports command line arguments to request various actions
+when invoking Emacs. These are for compatibility with other editors and
+for sophisticated activities. They are not needed for ordinary editing
+with Emacs, so new users can skip this section.
+
+ You may be used to using command line arguments with other editors
+to specify which file to edit. That's because many other editors are
+designed to be started afresh each time you want to edit. You edit one
+file and then exit the editor. The next time you want to edit either
+another file or the same one, you must run the editor again. With these
+editors, it makes sense to use a command line argument to say which
+file to edit.
+
+ The recommended way to use GNU Emacs is to start it only once, just
+after you log in, and do all your editing in the same Emacs process.
+Each time you want to edit a different file, you visit it with the
+existing Emacs, which eventually comes to have many files in it ready
+for editing. Usually you do not kill the Emacs until you are about to
+log out.
+
+ In the usual style of Emacs use, files are nearly always read by
+typing commands to an editor that is already running. So command line
+arguments for specifying a file when the editor is started are seldom
+used.
+
+ Emacs accepts command-line arguments that specify files to visit,
+functions to call, and other activities and operating modes.
+
+ The command arguments are processed in the order they appear in the
+command argument list; however, certain arguments (the ones in the
+second table) must be at the front of the list if they are used.
+
+ Here are the arguments allowed:
+
+`FILE'
+ Visit FILE using `find-file'. *Note Visiting::.
+
+`+LINENUM FILE'
+ Visit FILE using `find-file', then go to line number LINENUM in it.
+
+`-l FILE'
+`-load FILE'
+ Load a file FILE of Lisp code with the function `load'. *Note Lisp
+ Libraries::.
+
+`-f FUNCTION'
+`-funcall FUNCTION'
+ Call Lisp function FUNCTION with no arguments.
+
+`-i FILE'
+`-insert FILE'
+ Insert the contents of FILE into the current buffer. This is like
+ what `M-x insert-buffer' does; see *Note Misc File Ops::.
+
+`-kill'
+ Exit from Emacs without asking for confirmation.
+
+ The following switches are recognized only at the beginning of the
+command line. If more than one of them appears, they must appear in the
+order that they appear in this table.
+
+`-t DEVICE'
+ Use DEVICE as the device for terminal input and output.
+
+`-d DISPLAY'
+ When running with the X window system, use the display named
+ DISPLAY to make Emacs's X window.
+
+`-nw'
+ Don't use a window system; display text only, using an ordinary
+ terminal device. Thus, if you run an X-capable Emacs in an Xterm
+ with `emacs -nw', it displays in the Xterm's own window instead of
+ making its own.
+
+`-batch'
+ Run Emacs in "batch mode", which means that the text being edited
+ is not displayed and the standard Unix interrupt characters such
+ as `C-z' and `C-c' continue to have their normal effect. Emacs in
+ batch mode outputs to `stdout' only what would normally be printed
+ in the echo area under program control.
+
+ Batch mode is used for running programs written in Emacs Lisp from
+ shell scripts, makefiles, and so on. Normally the `-l' switch or
+ `-f' switch will be used as well, to invoke a Lisp program to do
+ the batch processing.
+
+ `-batch' implies `-q' (do not load an init file). It also causes
+ Emacs to exit after all command switches have been processed. In
+ addition, auto-saving is not done except in buffers for which it
+ has been explicitly requested.
+
+`-q'
+`-no-init-file'
+ Do not load your Emacs init file `~/.emacs'.
+
+`-u USER'
+`-user USER'
+ Load USER's Emacs init file `~USER/.emacs' instead of your own.
+
+ With X Windows, you can use these additional options to specify how
+to display the window. Each option has a corresponding resource name
+(used with `emacs' unless you specify another name with `-rn NAME'),
+listed with the option, which lets you specify the same parameter using
+the usual X Windows defaulting mechanism. The corresponding generic
+resource name (used with `Emacs') is usually made by capitalizing the
+first letter of the individual resource name, but in some cases it is a
+completely different string (which is listed below).
+
+`-rn NAME'
+ Use NAME instead of `emacs' when looking for X resources.
+
+`-font FONTNAME'
+`-fn FONTNAME'
+ Use font FONTNAME.
+ (Resource `font'.)
+
+`-wn NAME'
+ Name the window NAME.
+ (Resource `title'.)
+
+`-i'
+ Use a bitmap icon (showing the kitchen sink) rather than a textual
+ icon.
+ (Resource `bitmapIcon'.)
+
+`-in NAME'
+ Name the icon NAME. (Resource `iconName'; `Title').
+
+`-geometry COORDS'
+`-w COORDS'
+ Specify the shape and optionally the position of the Emacs window
+ in the usual X way.
+ (Resource `geometry'.)
+
+`-b WIDTH'
+ Specify that the window border is WIDTH pixels thick.
+ (Resource `borderWidth'.)
+
+`-ib WIDTH'
+ Leave WIDTH blank pixels between the border and the window
+ contents.
+ (Resource `internalBorder'; `BorderWidth'.)
+
+`-r'
+ Use reverse video.
+ (Resource `reverseVideo'.)
+
+`-fg COLOR'
+ Use color COLOR for text in the window.
+ (Resource `foreground'.)
+
+`-bg COLOR'
+ Use the color COLOR for the background of the window.
+ (Resource `background'.)
+
+`-bd COLOR'
+ Use color COLOR for the window border.
+ (Resource `borderColor'.)
+
+`-cr COLOR'
+ Specify the color, COLOR, to use for the cursor.
+ (Resource `cursorColor'; `Foreground'.)
+
+`-ms COLOR'
+ Use color COLOR for the mouse cursor.
+ (Resource `pointerColor'; `Foreground'.)
+
+ The init file can get access to the command line argument values as
+the elements of a list in the variable `command-line-args'. (The
+arguments in the second table above will already have been processed and
+will not be in the list.) The init file can override the normal
+processing of the other arguments by setting this variable.
+
+ One way to use command arguments is to visit many files
+automatically:
+
+ emacs *.c
+
+passes each `.c' file as a separate argument to Emacs, so that Emacs
+visits each file (*note Visiting::.).
+
+ Here is an advanced example that assumes you have a Lisp program
+file called `hack-c-program.el' which, when loaded, performs some
+useful operation on current buffer, expected to be a C program.
+
+ emacs -batch foo.c -l hack-c-program -f save-buffer -kill > log
+
+This says to visit `foo.c', load `hack-c-program.el' (which makes
+changes in the visited file), save `foo.c' (note that `save-buffer' is
+the function that `C-x C-s' is bound to), and then exit to the shell
+that this command was done with. `-batch' guarantees there will be no
+problem redirecting output to `log', because Emacs will not assume that
+it has a display terminal to work with.
+
+
+File: emacs, Node: Basic, Next: Undo, Prev: Command Switches, Up: Top
+
+Basic Editing Commands
+**********************
+
+ We now give the basics of how to enter text, make corrections, and
+save the text in a file. If this material is new to you, you might
+learn it more easily by running the Emacs learn-by-doing tutorial. To
+do this, type `Control-h t' (`help-with-tutorial').
+
+Inserting Text
+==============
+
+ To insert printing characters into the text you are editing, just
+type them. This inserts the character into the buffer at the cursor
+(that is, at "point"; *note Point::.). The cursor moves forward. Any
+characters after the cursor move forward too. If the text in the
+buffer is `FOOBAR', with the cursor before the `B', then if you type
+`XX', you get `FOOXXBAR', with the cursor still before the `B'.
+
+ To "delete" text you have just inserted, use DEL. DEL deletes the
+character BEFORE the cursor (not the one that the cursor is on top of
+or under; that is the character AFTER the cursor). The cursor and all
+characters after it move backwards. Therefore, if you type a printing
+character and then type DEL, they cancel out.
+
+ To end a line and start typing a new one, type RET. This inserts a
+newline character in the buffer. If point is in the middle of a line,
+RET splits the line. Typing DEL when the cursor is at the beginning of
+a line rubs out the newline before the line, thus joining the line with
+the preceding line.
+
+ Emacs will split lines automatically when they become too long, if
+you turn on a special mode called "Auto Fill" mode. *Note Filling::,
+for how to use Auto Fill mode.
+
+ Customization information: DEL in most modes runs the command named
+`delete-backward-char'; RET runs the command `newline', and
+self-inserting printing characters run the command `self-insert', which
+inserts whatever character was typed to invoke it. Some major modes
+rebind DEL to other commands.
+
+ Direct insertion works for printing characters and SPC, but other
+characters act as editing commands and do not insert themselves. If you
+need to insert a control character or a character whose code is above
+200 octal, you must "quote" it by typing the character `control-q'
+(`quoted-insert') first. There are two ways to use `C-q':
+
+ * `Control-q' followed by any non-graphic character (even `C-g')
+ inserts that character.
+
+ * `Control-q' followed by three octal digits inserts the character
+ with the specified character code.
+
+A numeric argument to `C-q' specifies how many copies of the quoted
+character should be inserted (*note Arguments::.).
+
+ If you prefer to have text characters replace (overwrite) existing
+text rather than shove it to the right, you can enable Overwrite mode,
+a minor mode. *Note Minor Modes::.
+
+Changing the Location of Point
+==============================
+
+ To do more than insert characters, you have to know how to move
+point (*note Point::.). Here are a few of the commands for doing that.
+
+`C-a'
+ Move to the beginning of the line (`beginning-of-line').
+
+`C-e'
+ Move to the end of the line (`end-of-line').
+
+`C-f'
+ Move forward one character (`forward-char').
+
+`C-b'
+ Move backward one character (`backward-char').
+
+`M-f'
+ Move forward one word (`forward-word').
+
+`M-b'
+ Move backward one word (`backward-word').
+
+`C-n'
+ Move down one line, vertically (`next-line'). This command
+ attempts to keep the horizontal position unchanged, so if you
+ start in the middle of one line, you end in the middle of the
+ next. When on the last line of text, `C-n' creates a new line and
+ moves onto it.
+
+`C-p'
+ Move up one line, vertically (`previous-line').
+
+`C-l'
+ Clear the screen and reprint everything (`recenter'). Text moves
+ on the screen to bring point to the center of the window.
+
+`M-r'
+ Move point to left margin on the line halfway down the screen or
+ window (`move-to-window-line'). Text does not move on the screen.
+ A numeric argument says how many screen lines down from the top
+ of the window (zero for the top). A negative argument counts from
+ the bottom (-1 for the bottom).
+
+`C-t'
+ Transpose two characters, the ones before and after the cursor
+ (`transpose-chars').
+
+`M-<'
+ Move to the top of the buffer (`beginning-of-buffer'). With
+ numeric argument N, move to N/10 of the way from the top. *Note
+ Arguments::, for more information on numeric arguments.
+
+`M->'
+ Move to the end of the buffer (`end-of-buffer').
+
+`M-x goto-char'
+ Read a number N and move cursor to character number N. Position 1
+ is the beginning of the buffer.
+
+`M-x goto-line'
+ Read a number N and move cursor to line number N. Line 1 is the
+ beginning of the buffer.
+
+`C-x C-n'
+ Use the current column of point as the "semipermanent goal column"
+ for `C-n' and `C-p' (`set-goal-column'). Henceforth, those
+ commands always move to this column in each line moved into, or as
+ close as possible given the contents of the line. This goal
+ column remains in effect until canceled.
+
+`C-u C-x C-n'
+ Cancel the goal column. Henceforth, `C-n' and `C-p' once again
+ try to avoid changing the horizontal position, as usual.
+
+ If you set the variable `track-eol' to a non-`nil' value, then `C-n'
+and `C-p' when at the end of the starting line move to the end of the
+line. Normally, `track-eol' is `nil'.
+
+Erasing Text
+============
+
+`DEL'
+ Delete the character before the cursor (`delete-backward-char').
+
+`C-d'
+ Delete the character after the cursor (`delete-char').
+
+`C-k'
+ Kill to the end of the line (`kill-line').
+
+`M-d'
+ Kill forward to the end of the next word (`kill-word').
+
+`M-DEL'
+ Kill back to the beginning of the previous word
+ (`backward-kill-word').
+
+ You already know about the DEL key which deletes the character
+before the cursor. Another key, `Control-d', deletes the character
+after the cursor, causing the rest of the text on the line to shift
+left. If `Control-d' is typed at the end of a line, that line and the
+next line are joined together.
+
+ To erase a larger amount of text, use the `Control-k' key, which
+kills a line at a time. If `C-k' is done at the beginning or middle of
+a line, it kills all the text up to the end of the line. If `C-k' is
+done at the end of a line, it joins that line and the next line.
+
+ *Note Killing::, for more flexible ways of killing text.
+
+Files
+=====
+
+ The commands above are sufficient for creating and altering text in
+an Emacs buffer; the more advanced Emacs commands just make things
+easier. But to keep any text permanently you must put it in a "file".
+Files are named units of text which are stored by the operating system
+for you to retrieve later by name. To look at or use the contents of a
+file in any way, including editing the file with Emacs, you must
+specify the file name.
+
+ Consider a file named `/usr/rms/foo.c'. In Emacs, to begin editing
+this file, type
+
+ C-x C-f /usr/rms/foo.c RET
+
+Here the file name is given as an "argument" to the command `C-x C-f'
+(`find-file'). That command uses the "minibuffer" to read the
+argument, and you type RET to terminate the argument (*note
+Minibuffer::.).
+
+ Emacs obeys the command by "visiting" the file: creating a buffer,
+copying the contents of the file into the buffer, and then displaying
+the buffer for you to edit. You can make changes in it, and then "save"
+the file by typing `C-x C-s' (`save-buffer'). This makes the changes
+permanent by copying the altered contents of the buffer back into the
+file `/usr/rms/foo.c'. Until then, the changes are only inside your
+Emacs, and the file `foo.c' is not changed.
+
+ To create a file, just visit the file with `C-x C-f' as if it already
+existed. Emacs will make an empty buffer in which you can insert the
+text you want to put in the file. When you save your text with `C-x
+C-s', the file will be created.
+
+ Of course, there is a lot more to learn about using files. *Note
+Files::.
+
+Help
+====
+
+ If you forget what a key does, you can find out with the Help
+character, which is `C-h'. Type `C-h k' followed by the key you want
+to know about; for example, `C-h k C-n' tells you all about what `C-n'
+does. `C-h' is a prefix key; `C-h k' is just one of its subcommands
+(the command `describe-key'). The other subcommands of `C-h' provide
+different kinds of help. Type `C-h' three times to get a description
+of all the help facilities. *Note Help::.
+
+* Menu:
+
+* Blank Lines:: Commands to make or delete blank lines.
+* Continuation Lines:: Lines too wide for the screen.
+* Position Info:: What page, line, row, or column is point on?
+* Arguments:: Numeric arguments for repeating a command.
+
+
+File: emacs, Node: Blank Lines, Next: Continuation Lines, Prev: Basic, Up: Basic
+
+Blank Lines
+===========
+
+ Here are special commands and techniques for putting in and taking
+out blank lines.
+
+`C-o'
+ Insert one or more blank lines after the cursor (`open-line').
+
+`C-x C-o'
+ Delete all but one of many consecutive blank lines
+ (`delete-blank-lines').
+
+ When you want to insert a new line of text before an existing line,
+you can do it by typing the new line of text, followed by RET. However,
+it may be easier to see what you are doing if you first make a blank
+line and then insert the desired text into it. This is easy to do
+using the key `C-o' (`open-line'), which inserts a newline after point
+but leaves point in front of the newline. After `C-o', type the text
+for the new line. `C-o F O O' has the same effect as `F O O RET',
+except for the final location of point.
+
+ You can make several blank lines by typing `C-o' several times, or by
+giving it an argument to tell it how many blank lines to make. *Note
+Arguments::, for how.
+
+ If you have many blank lines in a row and want to get rid of them,
+use `C-x C-o' (`delete-blank-lines'). When point is on a blank line
+which is adjacent to at least one other blank line, `C-x C-o' deletes
+all but one of the consecutive blank lines, leaving exactly one. With
+point on a blank line with no other blank line adjacent to it, the sole
+blank line is deleted, leaving none. When point is on a nonblank line,
+`C-x C-o' deletes any blank lines following that nonblank line.
+
+
+File: emacs, Node: Continuation Lines, Next: Position Info, Prev: Blank Lines, Up: Basic
+
+Continuation Lines
+==================
+
+ If you add too many characters to one line, without breaking it with
+a RET, the line will grow to occupy two (or more) lines on the screen,
+with a `\' at the extreme right margin of all but the last of them. The
+`\' says that the following screen line is not really a distinct line
+in the text, but just the "continuation" of a line too long to fit the
+screen. Sometimes it is nice to have Emacs insert newlines
+automatically when a line gets too long; for this, use Auto Fill mode
+(*note Filling::.).
+
+ Instead of continuation, long lines can be displayed by "truncation".
+This means that all the characters that do not fit in the width of the
+screen or window do not appear at all. They remain in the buffer,
+temporarily invisible. `$' is used in the last column instead of `\'
+to inform you that truncation is in effect.
+
+ Continuation can be turned off for a particular buffer by setting the
+variable `truncate-lines' to non-`nil' in that buffer. Truncation
+instead of continuation also happens whenever horizontal scrolling is
+in use, and optionally whenever side-by-side windows are in use (*note
+Windows::.). Altering the value of `truncate-lines' makes it local to
+the current buffer; until that time, the default value is in effect.
+The default is initially `nil'. *Note Locals::.
+
+
+File: emacs, Node: Position Info, Next: Arguments, Prev: Continuation Lines, Up: Basic
+
+Cursor Position Information
+===========================
+
+ If you are accustomed to other display editors, you may be surprised
+that Emacs does not always display the page number or line number of
+point in the mode line. This is because the text is stored in a way
+that makes it difficult to compute this information. Displaying them
+all the time would be intolerably slow. They are not needed very often
+in Emacs anyway, but there are commands to compute them and print them.
+
+`M-x what-page'
+ Print page number of point, and line number within page.
+
+`M-x what-line'
+ Print line number of point in the buffer.
+
+`M-='
+ Print number of lines in the current region (`count-lines-region').
+
+`C-x ='
+ Print character code of character after point, character position
+ of point, and column of point (`what-cursor-position').
+
+ There are two commands for printing line numbers. `M-x what-line'
+counts lines from the beginning of the file and prints the line number
+point is on. The first line of the file is line number 1. These
+numbers can be used as arguments to `M-x goto-line'. By contrast, `M-x
+what-page' counts pages from the beginning of the file, and counts lines
+within the page, printing both of them. *Note Pages::.
+
+ While on this subject, we might as well mention `M-='
+(`count-lines-region'), which prints the number of lines in the region
+(*note Mark::.). *Note Pages::, for the command `C-x l' which counts
+the lines in the current page.
+
+ The command `C-x =' (`what-cursor-position') can be used to find out
+the column that the cursor is in, and other miscellaneous information
+about point. It prints a line in the echo area that looks like this:
+
+ Char: x (0170) point=65986 of 563027(12%) x=44
+
+(In fact, this is the output produced when point is before the `x=44'
+in the example.)
+
+ The two values after `Char:' describe the character following point,
+first by showing it and second by giving its octal character code.
+
+ `point=' is followed by the position of point expressed as a
+character count. The front of the buffer counts as position 1, one
+character later as 2, and so on. The next, larger number is the total
+number of characters in the buffer. Afterward in parentheses comes the
+position expressed as a percentage of the total size.
+
+ `x=' is followed by the horizontal position of point, in columns
+from the left edge of the window.
+
+ If the buffer has been narrowed, making some of the text at the
+beginning and the end temporarily invisible, `C-x =' prints additional
+text describing the current visible range. For example, it might say
+
+ Char: x (0170) point=65986 of 563025(12%) <65102 - 68533> x=44
+
+where the two extra numbers give the smallest and largest character
+position that point is allowed to assume. The characters between those
+two positions are the visible ones. *Note Narrowing::.
+
+ If point is at the end of the buffer (or the end of the visible
+part), `C-x =' omits any description of the character after point. The
+output looks like
+
+ point=563026 of 563025(100%) x=0
+
+
+File: emacs, Node: Arguments, Prev: Position Info, Up: Basic
+
+Numeric Arguments
+=================
+
+ Any Emacs command can be given a "numeric argument". Some commands
+interpret the argument as a repetition count. For example, giving an
+argument of ten to the key `C-f' (the command `forward-char', move
+forward one character) moves forward ten characters. With these
+commands, no argument is equivalent to an argument of one. Negative
+arguments are allowed. Often they tell a command to move or act
+backwards.
+
+ If your terminal keyboard has a META key, the easiest way to specify
+a numeric argument is to type digits and/or a minus sign while holding
+down the META key. For example,
+ M-5 C-n
+
+would move down five lines. The characters `Meta-1', `Meta-2', and so
+on, as well as `Meta--', do this because they are keys bound to
+commands (`digit-argument' and `negative-argument') that are defined to
+contribute to an argument for the next command.
+
+ Another way of specifying an argument is to use the `C-u'
+(`universal-argument') command followed by the digits of the argument.
+With `C-u', you can type the argument digits without holding down shift
+keys. To type a negative argument, start with a minus sign. Just a
+minus sign normally means -1. `C-u' works on all terminals.
+
+ `C-u' followed by a character which is neither a digit nor a minus
+sign has the special meaning of "multiply by four". It multiplies the
+argument for the next command by four. `C-u' twice multiplies it by
+sixteen. Thus, `C-u C-u C-f' moves forward sixteen characters. This
+is a good way to move forward "fast", since it moves about 1/5 of a line
+in the usual size screen. Other useful combinations are `C-u C-n',
+`C-u C-u C-n' (move down a good fraction of a screen), `C-u C-u C-o'
+(make "a lot" of blank lines), and `C-u C-k' (kill four lines).
+
+ Some commands care only about whether there is an argument, and not
+about its value. For example, the command `M-q' (`fill-paragraph') with
+no argument fills text; with an argument, it justifies the text as well.
+(*Note Filling::, for more information on `M-q'.) Just `C-u' is a
+handy way of providing an argument for such commands.
+
+ Some commands use the value of the argument as a repeat count, but do
+something peculiar when there is no argument. For example, the command
+`C-k' (`kill-line') with argument N kills N lines, including their
+terminating newlines. But `C-k' with no argument is special: it kills
+the text up to the next newline, or, if point is right at the end of
+the line, it kills the newline itself. Thus, two `C-k' commands with
+no arguments can kill a nonblank line, just like `C-k' with an argument
+of one. (*Note Killing::, for more information on `C-k'.)
+
+ A few commands treat a plain `C-u' differently from an ordinary
+argument. A few others may treat an argument of just a minus sign
+differently from an argument of -1. These unusual cases will be
+described when they come up; they are always for reasons of convenience
+of use of the individual command.
+
+ To insert multiple copies of a digit, you can type `C-u COUNT C-u
+DIGIT'. The second `C-u' ends the numeric argument, so that the
+following character always acts a key sequence to be executed.
+
+
+File: emacs, Node: Undo, Next: Minibuffer, Prev: Basic, Up: Top
+
+Undoing Changes
+***************
+
+ Emacs allows all changes made in the text of a buffer to be undone,
+up to a certain amount of change (8000 characters). Each buffer records
+changes individually, and the undo command always applies to the
+current buffer. Usually each editing command makes a separate entry in
+the undo records, but some commands such as `query-replace' make many
+entries, and very simple commands such as self-inserting characters are
+often grouped to make undoing less tedious.
+
+`C-x u'
+ Undo one batch of changes (usually, one command worth) (`undo').
+
+`C-_'
+ The same.
+
+ The command `C-x u' or `C-_' is how you undo. The first time you
+give this command, it undoes the last change. Point moves to the text
+affected by the undo, so you can see what was undone.
+
+ Consecutive repetitions of the `C-_' or `C-x u' commands undo earlier
+and earlier changes, back to the limit of what has been recorded. If
+all recorded changes have already been undone, the undo command prints
+an error message and does nothing.
+
+ Any command other than an undo command breaks the sequence of undo
+commands. Starting at this moment, the previous undo commands are
+considered ordinary changes that can themselves be undone. Thus, to
+redo changes you have undone, type `C-f' or any other command that will
+have no important effect, and then give more undo commands.
+
+ If you notice that a buffer has been modified accidentally, the
+easiest way to recover is to type `C-_' repeatedly until the stars
+disappear from the front of the mode line. At this time, all the
+modifications you made have been cancelled. If you do not remember
+whether you changed the buffer deliberately, type `C-_' once, and when
+you see the last change you made undone, you will remember why you made
+it. If it was an accident, leave it undone. If it was deliberate,
+redo the change as described in the preceding paragraph.
+
+ Whenever an undo command makes the stars disappear from the mode
+line, it means that the buffer contents are the same as they were when
+the file was last read in or saved.
+
+ Not all buffers record undo information. Buffers whose names start
+with spaces don't; these buffers are used internally by Emacs and its
+extensions to hold text that users don't normally look at or edit.
+Also, minibuffers, help buffers and documentation buffers don't record
+undo information. Use the command `buffer-enable-undo' to enable
+recording undo information in the current buffer.
+
+ As editing continues, undo lists get longer and longer. To prevent
+them from using up all available memory space, garbage collection trims
+back their sizes to thresholds you can set. (For this purpose, the
+"size" of an undo list measures the cons cells that make up the list,
+plus the strings of deleted text.)
+
+ Two variables control the range of acceptable sizes: `undo-limit'
+and `undo-strong-limit'. Normally, the most recent changes are kept
+until their size exceeds `undo-limit'; all older changes are discarded.
+ But if a change pushes the size above `undo-strong-limit', it is
+discarded as well as all older changes. One exception: the most recent
+set of changes is sacred; garbage collection never discards that. (In
+Emacs versions 18.57 and 18.58, these variables are called
+`undo-threshold' and `undo-high-threshold'.)
+
+ The reason the `undo' command has two keys, `C-x u' and `C-_', set
+up to run it is that it is worthy of a single-character key, but the
+way to type `C-_' on some keyboards is not obvious. `C-x u' is an
+alternative you can type in the same fashion on any terminal.
+
+
+File: emacs, Node: Minibuffer, Next: M-x, Prev: Undo, Up: Top
+
+The Minibuffer
+**************
+
+ The "minibuffer" is the facility used by Emacs commands to read
+arguments more complicated than a single number. Minibuffer arguments
+can be file names, buffer names, Lisp function names, Emacs command
+names, Lisp expressions, and many other things, depending on the
+command reading the argument. The usual Emacs editing commands can be
+used in the minibuffer to edit the argument.
+
+ When the minibuffer is in use, it appears in the echo area, and the
+terminal's cursor moves there. The beginning of the minibuffer line
+displays a "prompt" which says what kind of input you should supply and
+how it will be used. Often this prompt is derived from the name of the
+command that the argument is for. The prompt normally ends with a
+colon.
+
+ Sometimes a "default argument" appears in parentheses after the
+colon; it too is part of the prompt. The default will be used as the
+argument value if you enter an empty argument (e.g., just type RET).
+For example, commands that read buffer names always show a default,
+which is the name of the buffer that will be used if you type just RET.
+
+ The simplest way to give a minibuffer argument is to type the text
+you want, terminated by RET which exits the minibuffer. You can get out
+of the minibuffer, canceling the command that it was for, by typing
+`C-g'.
+
+ Since the minibuffer uses the screen space of the echo area, it can
+conflict with other ways Emacs customarily uses the echo area. Here is
+how Emacs handles such conflicts:
+
+ * If a command gets an error while you are in the minibuffer, this
+ does not cancel the minibuffer. However, the echo area is needed
+ for the error message and therefore the minibuffer itself is
+ hidden for a while. It comes back after a few seconds, or as soon
+ as you type anything.
+
+ * If in the minibuffer you use a command whose purpose is to print a
+ message in the echo area, such as `C-x =', the message is printed
+ normally, and the minibuffer is hidden for a while. It comes back
+ after a few seconds, or as soon as you type anything.
+
+ * Echoing of keystrokes does not take place while the minibuffer is
+ in use.
+
+* Menu:
+
+* File: Minibuffer File. Entering file names with the minibuffer.
+* Edit: Minibuffer Edit. How to edit in the minibuffer.
+* Completion:: An abbreviation facility for minibuffer input.
+* Repetition:: Re-executing commands that used the minibuffer.
+
+
+File: emacs, Node: Minibuffer File, Next: Minibuffer Edit, Prev: Minibuffer, Up: Minibuffer
+
+Minibuffers for File Names
+==========================
+
+ Sometimes the minibuffer starts out with text in it. For example,
+when you are supposed to give a file name, the minibuffer starts out
+containing the "default directory", which ends with a slash. This is
+to inform you which directory the file will be found in if you do not
+specify a directory. For example, the minibuffer might start out with
+
+ Find File: /u2/emacs/src/
+
+where `Find File: ' is the prompt. Typing `buffer.c' specifies the
+file `/u2/emacs/src/buffer.c'. To find files in nearby directories,
+use `..'; thus, if you type `../lisp/simple.el', the file that you
+visit will be the one named `/u2/emacs/lisp/simple.el'. Alternatively,
+you can kill with `M-DEL' the directory names you don't want (*note
+Words::.).
+
+ You can also type an absolute file name, one starting with a slash
+or a tilde, ignoring the default directory. For example, to find the
+file `/etc/termcap', just type the name, giving
+
+ Find File: /u2/emacs/src//etc/termcap
+
+Two slashes in a row are not normally meaningful in Unix file names, but
+they are allowed in GNU Emacs. They mean, "ignore everything before the
+second slash in the pair." Thus, `/u2/emacs/src/' is ignored, and you
+get the file `/etc/termcap'.
+
+ If you set `insert-default-directory' to `nil', the default directory
+is not inserted in the minibuffer. This way, the minibuffer starts out
+empty. But the name you type, if relative, is still interpreted with
+respect to the same default directory.
+
+
+File: emacs, Node: Minibuffer Edit, Next: Completion, Prev: Minibuffer File, Up: Minibuffer
+
+Editing in the Minibuffer
+=========================
+
+ The minibuffer is an Emacs buffer (albeit a peculiar one), and the
+usual Emacs commands are available for editing the text of an argument
+you are entering.
+
+ Since RET in the minibuffer is defined to exit the minibuffer,
+inserting a newline into the minibuffer must be done with `C-o' or with
+`C-q LFD'. (Recall that a newline is really the LFD character.)
+
+ The minibuffer has its own window which always has space on the
+screen but acts as if it were not there when the minibuffer is not in
+use. When the minibuffer is in use, its window is just like the
+others; you can switch to another window with `C-x o', edit text in
+other windows and perhaps even visit more files, before returning to
+the minibuffer to submit the argument. You can kill text in another
+window, return to the minibuffer window, and then yank the text to use
+it in the argument. *Note Windows::.
+
+ There are some restrictions on the use of the minibuffer window,
+however. You cannot switch buffers in it--the minibuffer and its window
+are permanently attached. Also, you cannot split or kill the minibuffer
+window. But you can make it taller in the normal fashion with `C-x ^'
+(*note Change Window::.).
+
+ If while in the minibuffer you issue a command that displays help
+text of any sort in another window, then that window is identified as
+the one to scroll if you type `C-M-v' while in the minibuffer. This
+lasts until you exit the minibuffer. This feature comes into play if a
+completing minibuffer gives you a list of possible completions.
+
+ Recursive use of the minibuffer is supported by Emacs. However, it
+is easy to do this by accident (because of autorepeating keyboards, for
+example) and get confused. Therefore, most Emacs commands that use the
+minibuffer refuse to operate if the minibuffer window is selected. If
+the minibuffer is active but you have switched to a different window,
+recursive use of the minibuffer is allowed--if you know enough to try
+to do this, you probably will not get confused.
+
+ If you set the variable `enable-recursive-minibuffers' to be
+non-`nil', recursive use of the minibuffer is always allowed.
+
+
+File: emacs, Node: Completion, Next: Repetition, Prev: Minibuffer Edit, Up: Minibuffer
+
+Completion
+==========
+
+ When appropriate, the minibuffer provides a "completion" facility.
+This means that you type enough of the argument to determine the rest,
+based on Emacs's knowledge of which arguments make sense, and Emacs
+visibly fills in the rest, or as much as can be determined from the
+part you have typed.
+
+ When completion is available, certain keys--TAB, RET, and SPC--are
+redefined to complete an abbreviation present in the minibuffer into a
+longer string that it stands for, by matching it against a set of
+"completion alternatives" provided by the command reading the argument.
+`?' is defined to display a list of possible completions of what you
+have inserted.
+
+ For example, when the minibuffer is being used by `Meta-x' to read
+the name of a command, it is given a list of all available Emacs command
+names to complete against. The completion keys match the text in the
+minibuffer against all the command names, find any additional
+characters of the name that are implied by the ones already present in
+the minibuffer, and add those characters to the ones you have given.
+
+ Case is normally significant in completion, because it is
+significant in most of the names that you can complete (buffer names,
+file names and command names). Thus, `fo' will not complete to `Foo'.
+When you are completing a name in which case does not matter, case may
+be ignored for completion's sake if the program said to do so.
+
+Completion Example
+------------------
+
+ A concrete example may help here. If you type `Meta-x au TAB', the
+TAB looks for alternatives (in this case, command names) that start
+with `au'. There are only two: `auto-fill-mode' and `auto-save-mode'.
+These are the same as far as `auto-', so the `au' in the minibuffer
+changes to `auto-'.
+
+ If you type TAB again immediately, there are multiple possibilities
+for the very next character--it could be `s' or `f'--so no more
+characters are added; but a list of all possible completions is
+displayed in another window.
+
+ If you go on to type `f TAB', this TAB sees `auto-f'. The only
+command name starting this way is `auto-fill-mode', so completion
+inserts the rest of that. You now have `auto-fill-mode' in the
+minibuffer after typing just `au TAB f TAB'. Note that TAB has this
+effect because in the minibuffer it is bound to the function
+`minibuffer-complete' when completion is supposed to be done.
+
+Completion Commands
+-------------------
+
+ Here is a list of all the completion commands, defined in the
+minibuffer when completion is available.
+
+`TAB'
+ Complete the text in the minibuffer as much as possible
+ (`minibuffer-complete').
+
+`SPC'
+ Complete the text in the minibuffer but don't add or fill out more
+ than one word (`minibuffer-complete-word').
+
+`RET'
+ Submit the text in the minibuffer as the argument, possibly
+ completing first as described below
+ (`minibuffer-complete-and-exit').
+
+`?'
+ Print a list of all possible completions of the text in the
+ minibuffer (`minibuffer-list-completions').
+
+ SPC completes much like TAB, but never goes beyond the next hyphen
+or space. If you have `auto-f' in the minibuffer and type SPC, it
+finds that the completion is `auto-fill-mode', but it stops completing
+after `fill-'. This gives `auto-fill-'. Another SPC at this point
+completes all the way to `auto-fill-mode'. SPC in the minibuffer runs
+the function `minibuffer-complete-word' when completion is available.
+
+ There are three different ways that RET can work in completing
+minibuffers, depending on how the argument will be used.
+
+ * "Strict" completion is used when it is meaningless to give any
+ argument except one of the known alternatives. For example, when
+ `C-x k' reads the name of a buffer to kill, it is meaningless to
+ give anything but the name of an existing buffer. In strict
+ completion, RET refuses to exit if the text in the minibuffer does
+ not complete to an exact match.
+
+ * "Cautious" completion is similar to strict completion, except that
+ RET exits only if the text was an exact match already, not needing
+ completion. If the text is not an exact match, RET does not exit,
+ but it does complete the text. If it completes to an exact match,
+ a second RET will exit.
+
+ Cautious completion is used for reading file names for files that
+ must already exist.
+
+ * "Permissive" completion is used when any string whatever is
+ meaningful, and the list of completion alternatives is just a
+ guide. For example, when `C-x C-f' reads the name of a file to
+ visit, any file name is allowed, in case you want to create a
+ file. In permissive completion, RET takes the text in the
+ minibuffer exactly as given, without completing it.
+
+ The completion commands display a list of all possible completions
+in a window whenever there is more than one possibility for the very
+next character. Also, typing `?' explicitly requests such a list. The
+list of completions counts as help text, so `C-M-v' typed in the
+minibuffer scrolls the list.
+
+ When completion is done on file names, certain file names are usually
+ignored. The variable `completion-ignored-extensions' contains a list
+of strings; a file whose name ends in any of those strings is ignored
+as a possible completion. The standard value of this variable has
+several elements including `".o"', `".elc"', `".dvi"' and `"~"'. The
+effect is that, for example, `foo' can complete to `foo.c' even though
+`foo.o' exists as well. If the only possible completions are files
+that end in "ignored" strings, then they are not ignored.
+
+ Normally, a completion command that finds the next character is
+undetermined automatically displays a list of all possible completions.
+ If the variable `completion-auto-help' is set to `nil', this does not
+happen, and you must type `?' to display the possible completions.
+
+ \ No newline at end of file
diff --git a/info/emacs-3 b/info/emacs-3
new file mode 100644
index 00000000000..d039c6f920e
--- /dev/null
+++ b/info/emacs-3
@@ -0,0 +1,1220 @@
+This is Info file ../info/emacs, produced by Makeinfo-1.49 from the
+input file emacs.texi.
+
+ This file documents the GNU Emacs editor.
+
+ Copyright (C) 1985, 1986, 1988, 1992 Richard M. Stallman.
+
+ Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+ Permission is granted to copy and distribute modified versions of
+this manual under the conditions for verbatim copying, provided also
+that the sections entitled "The GNU Manifesto", "Distribution" and "GNU
+General Public License" are included exactly as in the original, and
+provided that the entire resulting derived work is distributed under the
+terms of a permission notice identical to this one.
+
+ Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that the sections entitled "The GNU Manifesto",
+"Distribution" and "GNU General Public License" may be included in a
+translation approved by the author instead of in the original English.
+
+
+File: emacs, Node: Repetition, Prev: Completion, Up: Minibuffer
+
+Repeating Minibuffer Commands
+=============================
+
+ Every command that uses the minibuffer at least once is recorded on a
+special history list, together with the values of the minibuffer
+arguments, so that you can repeat the command easily. In particular,
+every use of `Meta-x' is recorded, since `M-x' uses the minibuffer to
+read the command name.
+
+`C-x ESC'
+ Re-execute a recent minibuffer command `repeat-complex-command').
+
+`M-p'
+ Within `C-x ESC', move to the previous recorded command
+ (`previous-complex-command').
+
+`M-n'
+ Within `C-x ESC', move to the next (more recent) recorded command
+ (`next-complex-command').
+
+`M-x list-command-history'
+ Display the entire command history, showing all the commands `C-x
+ ESC' can repeat, most recent first.
+
+ `C-x ESC' is used to re-execute a recent minibuffer-using command.
+With no argument, it repeats the last such command. A numeric argument
+specifies which command to repeat; 1 means the last one, and larger
+numbers specify earlier ones.
+
+ `C-x ESC' works by turning the previous command into a Lisp
+expression and then entering a minibuffer initialized with the text for
+that expression. If you type just RET, the command is repeated as
+before. You can also change the command by editing the Lisp expression.
+Whatever expression you finally submit is what will be executed. The
+repeated command is added to the front of the command history unless it
+is identical to the most recently executed command already there.
+
+ Even if you don't understand Lisp syntax, it will probably be obvious
+which command is displayed for repetition. If you do not change the
+text, you can be sure it will repeat exactly as before.
+
+ Once inside the minibuffer for `C-x ESC', if the command shown to
+you is not the one you want to repeat, you can move around the list of
+previous commands using `M-n' and `M-p'. `M-p' replaces the contents
+of the minibuffer with the next earlier recorded command, and `M-n'
+replaces them with the next later command. After finding the desired
+previous command, you can edit its expression as usual and then
+resubmit it by typing RET as usual. Any editing you have done on the
+command to be repeated is lost if you use `M-n' or `M-p'.
+
+ `M-p' is more useful than `M-n', since more often you will initially
+request to repeat the most recent command and then decide to repeat an
+older one instead. These keys are specially defined within `C-x ESC'
+to run the commands `previous-complex-command' and
+`next-complex-command'.
+
+ The list of previous minibuffer-using commands is stored as a Lisp
+list in the variable `command-history'. Each element is a Lisp
+expression which describes one command and its arguments. Lisp
+programs can reexecute a command by feeding the corresponding
+`command-history' element to `eval'.
+
+
+File: emacs, Node: M-x, Next: Help, Prev: Minibuffer, Up: Top
+
+Running Commands by Name
+************************
+
+ The Emacs commands that are used often or that must be quick to type
+are bound to keys--short sequences of characters--for convenient use.
+Other Emacs commands that do not need to be brief are not bound to
+keys; to run them, you must refer to them by name.
+
+ A command name is, by convention, made up of one or more words,
+separated by hyphens; for example, `auto-fill-mode' or `manual-entry'.
+The use of English words makes the command name easier to remember than
+a key made up of obscure characters, even though it is more characters
+to type. Any command can be run by name, even if it is also runnable by
+keys.
+
+ The way to run a command by name is to start with `M-x', type the
+command name, and finish it with RET. `M-x' uses the minibuffer to
+read the command name. RET exits the minibuffer and runs the command.
+
+ Emacs uses the minibuffer for reading input for many different
+purposes; on this occasion, the string `M-x' is displayed at the
+beginning of the minibuffer as a "prompt" to remind you that your input
+should be the name of a command to be run. *Note Minibuffer::, for
+full information on the features of the minibuffer.
+
+ You can use completion to enter the command name. For example, the
+command `forward-char' can be invoked by name by typing
+
+ M-x forward-char RET
+or
+
+ M-x fo TAB c RET
+
+Note that `forward-char' is the same command that you invoke with the
+key `C-f'. Any command (interactively callable function) defined in
+Emacs can be called by its name using `M-x' whether or not any keys are
+bound to it.
+
+ If you type `C-g' while the command name is being read, you cancel
+the `M-x' command and get out of the minibuffer, ending up at top level.
+
+ To pass a numeric argument to the command you are invoking with
+`M-x', specify the numeric argument before the `M-x'. `M-x' passes the
+argument along to the function which it calls. The argument value
+appears in the prompt while the command name is being read.
+
+ Normally, when describing a command that is run by name, we omit the
+RET that is needed to terminate the name. Thus we might speak of `M-x
+auto-fill-mode' rather than `M-x auto-fill-mode RET'. We mention the
+RET only when there is a need to emphasize its presence, such as when
+describing a sequence of input that contains a command name and
+arguments that follow it.
+
+ `M-x' is defined to run the command `execute-extended-command',
+which is responsible for reading the name of another command and
+invoking it.
+
+
+File: emacs, Node: Help, Next: Mark, Prev: M-x, Up: Top
+
+Help
+****
+
+ Emacs provides extensive help features which revolve around a single
+character, `C-h'. `C-h' is a prefix key that is used only for
+documentation-printing commands. The characters that you can type after
+`C-h' are called "help options". One help option is `C-h'; that is how
+you ask for help about using `C-h'.
+
+ `C-h C-h' prints a list of the possible help options, and then asks
+you to go ahead and type the option. It prompts with a string
+
+ A B C F I K L M N S T V W C-c C-d C-n C-w. Type C-h again for more help:
+
+and you should type one of those characters.
+
+ Typing a third `C-h' displays a description of what the options mean;
+it still waits for you to type an option. To cancel, type `C-g'.
+
+ Here is a summary of the defined help commands.
+
+`C-h a STRING RET'
+ Display a list of commands whose names contain STRING
+ (`command-apropos').
+
+`C-h b'
+ Display a table of all key bindings in effect now; local bindings
+ of the current major mode first, followed by all global bindings
+ (`describe-bindings').
+
+`C-h c KEY'
+ Print the name of the command that KEY runs
+ (`describe-key-briefly'). `c' is for `character'. For more
+ extensive information on KEY, use `C-h k'.
+
+`C-h f FUNCTION RET'
+ Display documentation on the Lisp function named FUNCTION
+ (`describe-function'). Note that commands are Lisp functions, so
+ a command name may be used.
+
+`C-h i'
+ Run Info, the program for browsing documentation files (`info').
+ The complete Emacs manual is available on-line in Info.
+
+`C-h k KEY'
+ Display name and documentation of the command KEY runs
+ (`describe-key').
+
+`C-h l'
+ Display a description of the last 100 characters you typed
+ (`view-lossage').
+
+`C-h m'
+ Display documentation of the current major mode (`describe-mode').
+
+`C-h n'
+ Display documentation of Emacs changes, most recent first
+ (`view-emacs-news').
+
+`C-h s'
+ Display current contents of the syntax table, plus an explanation
+ of what they mean (`describe-syntax').
+
+`C-h t'
+ Display the Emacs tutorial (`help-with-tutorial').
+
+`C-h v VAR RET'
+ Display the documentation of the Lisp variable VAR
+ (`describe-variable').
+
+`C-h w COMMAND RET'
+ Print which keys run the command named COMMAND (`where-is').
+
+Documentation for a Key
+=======================
+
+ The most basic `C-h' options are `C-h c' (`describe-key-briefly')
+and `C-h k' (`describe-key'). `C-h c KEY' prints in the echo area the
+name of the command that KEY is bound to. For example, `C-h c C-f'
+prints `forward-char'. Since command names are chosen to describe what
+the command does, this is a good way to get a very brief description of
+what KEY does.
+
+ `C-h k KEY' is similar but gives more information. It displays the
+documentation string of the command KEY is bound to as well as its
+name. This is too big for the echo area, so a window is used for the
+display.
+
+Help by Command or Variable Name
+================================
+
+ `C-h f' (`describe-function') reads the name of a Lisp function
+using the minibuffer, then displays that function's documentation string
+in a window. Since commands are Lisp functions, you can use this to get
+the documentation of a command that is known by name. For example,
+
+ C-h f auto-fill-mode RET
+
+displays the documentation of `auto-fill-mode'. This is the only way
+to see the documentation of a command that is not bound to any key (one
+which you would normally call using `M-x').
+
+ `C-h f' is also useful for Lisp functions that you are planning to
+use in a Lisp program. For example, if you have just written the code
+`(make-vector len)' and want to be sure that you are using
+`make-vector' properly, type `C-h f make-vector RET'. Because `C-h f'
+allows all function names, not just command names, you may find that
+some of your favorite abbreviations that work in `M-x' don't work in
+`C-h f'. An abbreviation may be unique among command names yet fail to
+be unique when other function names are allowed.
+
+ The function name for `C-h f' to describe has a default which is
+used if you type RET leaving the minibuffer empty. The default is the
+function called by the innermost Lisp expression in the buffer around
+point, provided that is a valid, defined Lisp function name. For
+example, if point is located following the text `(make-vector (car x)',
+the innermost list containing point is the one that starts with
+`(make-vector', so the default is to describe the function
+`make-vector'.
+
+ `C-h f' is often useful just to verify that you have the right
+spelling for the function name. If `C-h f' mentions a default in the
+prompt, you have typed the name of a defined Lisp function. If that
+tells you what you want to know, just type `C-g' to cancel the `C-h f'
+command and go on editing.
+
+ `C-h w COMMAND RET' tells you what keys are bound to COMMAND. It
+prints a list of the keys in the echo area. Alternatively, it says that
+the command is not on any keys, which implies that you must use `M-x'
+to call it.
+
+ `C-h v' (`describe-variable') is like `C-h f' but describes Lisp
+variables instead of Lisp functions. Its default is the Lisp symbol
+around or before point, but only if that is the name of a known Lisp
+variable. *Note Variables::.
+
+Apropos
+=======
+
+ A more sophisticated sort of question to ask is, "What are the
+commands for working with files?" For this, type `C-h a file RET',
+which displays a list of all command names that contain `file', such as
+`copy-file', `find-file', and so on. With each command name appears a
+brief description of how to use the command, and what keys you can
+currently invoke it with. For example, it would say that you can
+invoke `find-file' by typing `C-x C-f'. The `a' in `C-h a' stands for
+`Apropos'; `C-h a' runs the Lisp function `command-apropos'.
+
+ Because `C-h a' looks only for functions whose names contain the
+string which you specify, you must use ingenuity in choosing the string.
+If you are looking for commands for killing backwards and `C-h a
+kill-backwards RET' doesn't reveal any, don't give up. Try just
+`kill', or just `backwards', or just `back'. Be persistent. Pretend
+you are playing Adventure. Also note that you can use a regular
+expression as the argument (*note Regexps::.).
+
+ Here is a set of arguments to give to `C-h a' that covers many
+classes of Emacs commands, since there are strong conventions for naming
+the standard Emacs commands. By giving you a feel for the naming
+conventions, this set should also serve to aid you in developing a
+technique for picking `apropos' strings.
+
+ char, line, word, sentence, paragraph, region, page, sexp, list,
+ defun, buffer, screen, window, file, dir, register, mode,
+ beginning, end, forward, backward, next, previous, up, down,
+ search, goto, kill, delete, mark, insert, yank, fill, indent, case,
+ change, set, what, list, find, view, describe.
+
+ To list all Lisp symbols that contain a match for a regexp, not just
+the ones that are defined as commands, use the command `M-x apropos'
+instead of `C-h a'.
+
+Other Help Commands
+===================
+
+ `C-h i' (`info') runs the Info program, which is used for browsing
+through structured documentation files. The entire Emacs manual is
+available within Info. Eventually all the documentation of the GNU
+system will be available. Type `h' after entering Info to run a
+tutorial on using Info.
+
+ If something surprising happens, and you are not sure what commands
+you typed, use `C-h l' (`view-lossage'). `C-h l' prints the last 100
+command characters you typed in. If you see commands that you don't
+know, you can use `C-h c' to find out what they do.
+
+ Emacs has several major modes, each of which redefines a few keys and
+makes a few other changes in how editing works. `C-h m'
+(`describe-mode') prints documentation on the current major mode, which
+normally describes all the commands that are changed in this mode.
+
+ `C-h b' (`describe-bindings') and `C-h s' (`describe-syntax')
+present other information about the current Emacs mode. `C-h b'
+displays a list of all the key bindings now in effect; the local
+bindings of the current major mode first, followed by the global
+bindings (*note Key Bindings::.). `C-h s' displays the contents of the
+syntax table, with explanations of each character's syntax (*note
+Syntax::.).
+
+ The other `C-h' options display various files of useful information.
+ `C-h C-w' displays the full details on the complete absence of
+warranty for GNU Emacs. `C-h n' (`view-emacs-news') displays the file
+`emacs/etc/NEWS', which contains documentation on Emacs changes
+arranged chronologically. `C-h t' (`help-with-tutorial') displays the
+learn-by-doing Emacs tutorial. `C-h C-c' (`describe-copying') displays
+the file `emacs/etc/COPYING', which tells you the conditions you must
+obey in distributing copies of Emacs. `C-h C-d'
+(`describe-distribution') displays another file named
+`emacs/etc/DISTRIB', which tells you how you can order a copy of the
+latest version of Emacs.
+
+
+File: emacs, Node: Mark, Next: Killing, Prev: Help, Up: Top
+
+The Mark and the Region
+***********************
+
+ There are many Emacs commands which operate on an arbitrary
+contiguous part of the current buffer. To specify the text for such a
+command to operate on, you set the "mark" at one end of it, and move
+point to the other end. The text between point and the mark is called
+the "region". You can move point or the mark to adjust the boundaries
+of the region. It doesn't matter which one is set first
+chronologically, or which one comes earlier in the text.
+
+ Once the mark has been set, it remains until it is set again at
+another place. The mark remains fixed with respect to the preceding
+character if text is inserted or deleted in the buffer. Each Emacs
+buffer has its own mark, so that when you return to a buffer that had
+been selected previously, it has the same mark it had before.
+
+ Many commands that insert text, such as `C-y' (`yank') and `M-x
+insert-buffer', position the mark at one end of the inserted text--the
+opposite end from where point is positioned, so that the region
+contains the text just inserted.
+
+ Aside from delimiting the region, the mark is also useful for
+remembering a spot that you may want to go back to. To make this
+feature more useful, Emacs remembers 16 previous locations of the mark,
+in the `mark ring'.
+
+* Menu:
+
+* Setting Mark:: Commands to set the mark.
+* Using Region:: Summary of ways to operate on contents of the region.
+* Marking Objects:: Commands to put region around textual units.
+* Mark Ring:: Previous mark positions saved so you can go back there.
+
+
+File: emacs, Node: Setting Mark, Next: Using Region, Prev: Mark, Up: Mark
+
+Setting the Mark
+================
+
+ Here are some commands for setting the mark:
+
+`C-SPC'
+ Set the mark where point is (`set-mark-command').
+
+`C-@'
+ The same.
+
+`C-x C-x'
+ Interchange mark and point (`exchange-point-and-mark').
+
+ For example, if you wish to convert part of the buffer to all
+upper-case, you can use the `C-x C-u' (`upcase-region') command, which
+operates on the text in the region. You can first go to the beginning
+of the text to be capitalized, type `C-SPC' to put the mark there, move
+to the end, and then type `C-x C-u'. Or, you can set the mark at the
+end of the text, move to the beginning, and then type `C-x C-u'. Most
+commands that operate on the text in the region have the word `region'
+in their names.
+
+ The most common way to set the mark is with the `C-SPC' command
+(`set-mark-command'). This sets the mark where point is. Then you can
+move point away, leaving the mark behind. It is actually incorrect to
+speak of the character `C-SPC'; there is no such character. When you
+type SPC while holding down CTRL, what you get on most terminals is the
+character `C-@'. This is the key actually bound to `set-mark-command'.
+ But unless you are unlucky enough to have a terminal where typing
+`C-SPC' does not produce `C-@', you might as well think of this
+character as `C-SPC'.
+
+ Since terminals have only one cursor, there is no way for Emacs to
+show you where the mark is located. You have to remember. The usual
+solution to this problem is to set the mark and then use it soon,
+before you forget where it is. But you can see where the mark is with
+the command `C-x C-x' (`exchange-point-and-mark') which puts the mark
+where point was and point where the mark was. The extent of the region
+is unchanged, but the cursor and point are now at the previous location
+of the mark.
+
+ `C-x C-x' is also useful when you are satisfied with the location of
+point but want to move the mark; do `C-x C-x' to put point there and
+then you can move it. A second use of `C-x C-x', if necessary, puts
+the mark at the new location with point back at its original location.
+
+
+File: emacs, Node: Using Region, Next: Marking Objects, Prev: Setting Mark, Up: Mark
+
+Operating on the Region
+=======================
+
+ Once you have created an active region, you can do many things to
+the text in it:
+ * Kill it with `C-w' (*note Killing::.).
+
+ * Save it in a register with `C-x x' (*note Registers::.).
+
+ * Save it in a buffer or a file (*note Accumulating Text::.).
+
+ * Convert case with `C-x C-l' or `C-x C-u'
+ (*note Case::.).
+
+ * Evaluate it as Lisp code with `M-x eval-region' (*note Lisp
+ Eval::.).
+
+ * Fill it as text with `M-g' (*note Filling::.).
+
+ * Print hardcopy with `M-x print-region' (*note Hardcopy::.).
+
+ * Indent it with `C-x TAB' or `C-M-\'
+ (*note Indentation::.).
+
+
+File: emacs, Node: Marking Objects, Next: Mark Ring, Prev: Using Region, Up: Mark
+
+Commands to Mark Textual Objects
+================================
+
+ There are commands for placing point and the mark around a textual
+object such as a word, list, paragraph or page.
+
+`M-@'
+ Set mark after end of next word (`mark-word'). This command and
+ the following one do not move point.
+
+`C-M-@'
+ Set mark after end of next Lisp expression (`mark-sexp').
+
+`M-h'
+ Put region around current paragraph (`mark-paragraph').
+
+`C-M-h'
+ Put region around current Lisp defun (`mark-defun').
+
+`C-x h'
+ Put region around entire buffer (`mark-whole-buffer').
+
+`C-x C-p'
+ Put region around current page (`mark-page').
+
+ `M-@' (`mark-word') puts the mark at the end of the next word, while
+`C-M-@' (`mark-sexp') puts it at the end of the next Lisp expression.
+These characters allow you to save a little typing or redisplay,
+sometimes.
+
+ Other commands set both point and mark, to delimit an object in the
+buffer. `M-h' (`mark-paragraph') moves point to the beginning of the
+paragraph that surrounds or follows point, and puts the mark at the end
+of that paragraph (*note Paragraphs::.). `M-h' does all that's
+necessary if you wish to indent, case-convert, or kill a whole
+paragraph. `C-M-h' (`mark-defun') similarly puts point before and the
+mark after the current or following defun (*note Defuns::.). `C-x C-p'
+(`mark-page') puts point before the current page (or the next or
+previous, according to the argument), and mark at the end (*note
+Pages::.). The mark goes after the terminating page delimiter (to
+include it), while point goes after the preceding page delimiter (to
+exclude it). Finally, `C-x h' (`mark-whole-buffer') sets up the entire
+buffer as the region, by putting point at the beginning and the mark at
+the end.
+
+
+File: emacs, Node: Mark Ring, Prev: Marking Objects, Up: Mark
+
+The Mark Ring
+=============
+
+ Aside from delimiting the region, the mark is also useful for
+remembering a spot that you may want to go back to. To make this
+feature more useful, Emacs remembers 16 previous locations of the mark,
+in the "mark ring". Most commands that set the mark push the old mark
+onto this ring. To return to a marked location, use `C-u C-SPC' (or
+`C-u C-@'); this is the command `set-mark-command' given a numeric
+argument. It moves point to where the mark was, and restores the mark
+from the ring of former marks. So repeated use of this command moves
+point to all of the old marks on the ring, one by one. The marks you
+see go to the end of the ring, so no marks are lost.
+
+ Each buffer has its own mark ring. All editing commands use the
+current buffer's mark ring. In particular, `C-u C-SPC' always stays in
+the same buffer.
+
+ Many commands that can move long distances, such as `M-<'
+(`beginning-of-buffer'), start by setting the mark and saving the old
+mark on the mark ring. This is to make it easier for you to move back
+later. Searches do this except when they do not actually move point.
+You can tell when a command sets the mark because `Mark Set' is printed
+in the echo area.
+
+ Another way of remembering positions so you can go back to them is
+with registers (*note RegPos::.).
+
+ The variable `mark-ring-max' is the maximum number of entries to
+keep in the mark ring. If that many entries exist and another one is
+pushed, the last one in the list is discarded. Repeating `C-u C-SPC'
+circulates through the limited number of entries that are currently in
+the ring.
+
+ The variable `mark-ring' holds the mark ring itself, as a list of
+marker objects in the order most recent first. This variable is local
+in every buffer.
+
+
+File: emacs, Node: Killing, Next: Yanking, Prev: Mark, Up: Top
+
+Deletion and Killing
+====================
+
+ Most commands which erase text from the buffer save it so that you
+can get it back if you change your mind, or move or copy it to other
+parts of the buffer. These commands are known as "kill" commands. The
+rest of the commands that erase text do not save it; they are known as
+"delete" commands. (This distinction is made only for erasure of text
+in the buffer.)
+
+ The delete commands include `C-d' (`delete-char') and DEL
+(`delete-backward-char'), which delete only one character at a time,
+and those commands that delete only spaces or newlines. Commands that
+can destroy significant amounts of nontrivial data generally kill. The
+commands' names and individual descriptions use the words `kill' and
+`delete' to say which they do. If you do a kill or delete command by
+mistake, you can use the `C-x u' (`undo') command to undo it (*note
+Undo::.).
+
+Deletion
+--------
+
+`C-d'
+ Delete next character (`delete-char').
+
+`DEL'
+ Delete previous character (`delete-backward-char').
+
+`M-\'
+ Delete spaces and tabs around point (`delete-horizontal-space').
+
+`M-SPC'
+ Delete spaces and tabs around point, leaving one space
+ (`just-one-space').
+
+`C-x C-o'
+ Delete blank lines around the current line (`delete-blank-lines').
+
+`M-^'
+ Join two lines by deleting the intervening newline, and any
+ indentation following it (`delete-indentation').
+
+ The most basic delete commands are `C-d' (`delete-char') and DEL
+(`delete-backward-char'). `C-d' deletes the character after point, the
+one the cursor is "on top of". Point doesn't move. DEL deletes the
+character before the cursor, and moves point back. Newlines can be
+deleted like any other characters in the buffer; deleting a newline
+joins two lines. Actually, `C-d' and DEL aren't always delete
+commands; if given an argument, they kill instead, since they can erase
+more than one character this way.
+
+ The other delete commands are those which delete only formatting
+characters: spaces, tabs and newlines. `M-\'
+(`delete-horizontal-space') deletes all the spaces and tab characters
+before and after point. `M-SPC' (`just-one-space') does likewise but
+leaves a single space after point, regardless of the number of spaces
+that existed previously (even zero).
+
+ `C-x C-o' (`delete-blank-lines') deletes all blank lines after the
+current line, and if the current line is blank deletes all blank lines
+preceding the current line as well (leaving one blank line, the current
+line). `M-^' (`delete-indentation') joins the current line and the
+previous line, or the current line and the next line if given an
+argument, by deleting a newline and all surrounding spaces, possibly
+leaving a single space. *Note M-^: Indentation.
+
+Killing by Lines
+----------------
+
+`C-k'
+ Kill rest of line or one or more lines (`kill-line').
+
+ The simplest kill command is `C-k'. If given at the beginning of a
+line, it kills all the text on the line, leaving it blank. If given on
+a blank line, the blank line disappears. As a consequence, if you go
+to the front of a non-blank line and type `C-k' twice, the line
+disappears completely.
+
+ More generally, `C-k' kills from point up to the end of the line,
+unless it is at the end of a line. In that case it kills the newline
+following the line, thus merging the next line into the current one.
+Invisible spaces and tabs at the end of the line are ignored when
+deciding which case applies, so if point appears to be at the end of
+the line, you can be sure the newline will be killed.
+
+ If `C-k' is given a positive argument, it kills that many lines and
+the newlines that follow them (however, text on the current line before
+point is spared). With a negative argument, it kills back to a number
+of line beginnings. An argument of -2 means kill back to the second
+line beginning. If point is at the beginning of a line, that line
+beginning doesn't count, so `C-u - 2 C-k' with point at the front of a
+line kills the two previous lines.
+
+ `C-k' with an argument of zero kills all the text before point on the
+current line.
+
+Other Kill Commands
+-------------------
+
+`C-w'
+ Kill region (from point to the mark) (`kill-region'). *Note
+ Words::.
+
+`M-d'
+ Kill word (`kill-word').
+
+`M-DEL'
+ Kill word backwards (`backward-kill-word').
+
+`C-x DEL'
+ Kill back to beginning of sentence (`backward-kill-sentence').
+ *Note Sentences::.
+
+`M-k'
+ Kill to end of sentence (`kill-sentence').
+
+`C-M-k'
+ Kill sexp (`kill-sexp'). *Note Lists::.
+
+`M-z CHAR'
+ Kill up to next occurrence of CHAR (`zap-to-char').
+
+ A kill command which is very general is `C-w' (`kill-region'), which
+kills everything between point and the mark. With this command, you
+can kill any contiguous sequence of characters, if you first set the
+mark at one end of them and go to the other end.
+
+ A convenient way of killing is combined with searching: `M-z'
+(`zap-to-char') reads a character and kills from point up to (but not
+including) the next occurrence of that character in the buffer. If
+there is no next occurrence, killing goes to the end of the buffer. A
+numeric argument acts as a repeat count. A negative argument means to
+search backward and kill text before point.
+
+ Other syntactic units can be killed: words, with `M-DEL' and `M-d'
+(*note Words::.); sexps, with `C-M-k' (*note Lists::.); and sentences,
+with `C-x DEL' and `M-k' (*note Sentences::.).
+
+
+File: emacs, Node: Yanking, Next: Accumulating Text, Prev: Killing, Up: Top
+
+Yanking
+=======
+
+ "Yanking" is getting back text which was killed. This is what some
+systems call "pasting". The usual way to move or copy text is to kill
+it and then yank it one or more times.
+
+`C-y'
+ Yank last killed text (`yank').
+
+`M-y'
+ Replace re-inserted killed text with the previously killed text
+ (`yank-pop').
+
+`M-w'
+ Save region as last killed text without actually killing it
+ (`copy-region-as-kill').
+
+`C-M-w'
+ Append next kill to last batch of killed text (`append-next-kill').
+
+* Menu:
+
+* Kill Ring:: Where killed text is stored. Basic yanking.
+* Appending Kills:: Several kills in a row all yank together.
+* Earlier Kills:: Yanking something killed some time ago.
+
+
+File: emacs, Node: Kill Ring, Next: Appending Kills, Prev: Yanking, Up: Yanking
+
+The Kill Ring
+-------------
+
+ All killed text is recorded in the "kill ring", a list of blocks of
+text that have been killed. There is only one kill ring, used in all
+buffers, so you can kill text in one buffer and yank it in another
+buffer. This is the usual way to move text from one file to another.
+(*Note Accumulating Text::, for some other ways.)
+
+ The command `C-y' (`yank') reinserts the text of the most recent
+kill. It leaves the cursor at the end of the text. It sets the mark at
+the beginning of the text. *Note Mark::.
+
+ `C-u C-y' leaves the cursor in front of the text, and sets the mark
+after it. This is only if the argument is specified with just a `C-u',
+precisely. Any other sort of argument, including `C-u' and digits, has
+an effect described below (under "Yanking Earlier Kills").
+
+ If you wish to copy a block of text, you might want to use `M-w'
+(`copy-region-as-kill'), which copies the region into the kill ring
+without removing it from the buffer. This is approximately equivalent
+to `C-w' followed by `C-y', except that `M-w' does not mark the buffer
+as "modified" and does not temporarily change the screen.
+
+
+File: emacs, Node: Appending Kills, Next: Earlier Kills, Prev: Kill Ring, Up: Yanking
+
+Appending Kills
+---------------
+
+ Normally, each kill command pushes a new block onto the kill ring.
+However, two or more kill commands in a row combine their text into a
+single entry, so that a single `C-y' gets it all back as it was before
+it was killed. This means that you don't have to kill all the text in
+one command; you can keep killing line after line, or word after word,
+until you have killed it all, and you can still get it all back at
+once. (Thus we join television in leading people to kill
+thoughtlessly.)
+
+ Commands that kill forward from point add onto the end of the
+previous killed text. Commands that kill backward from point add onto
+the beginning. This way, any sequence of mixed forward and backward
+kill commands puts all the killed text into one entry without
+rearrangement. Numeric arguments do not break the sequence of appending
+kills. For example, suppose the buffer contains
+
+ This is the first
+ line of sample text
+ and here is the third.
+
+with point at the beginning of the second line. If you type `C-k C-u 2
+M-DEL C-k', the first `C-k' kills the text `line of sample text', `C-u
+2 M-DEL' kills `the first' with the newline that followed it, and the
+second `C-k' kills the newline after the second line. The result is
+that the buffer contains `This is and here is the third.' and a single
+kill entry contains `the firstRETline of sample textRET'--all the
+killed text, in its original order.
+
+ If a kill command is separated from the last kill command by other
+commands (not just numeric arguments), it starts a new entry on the kill
+ring. But you can force it to append by first typing the command
+`C-M-w' (`append-next-kill') in front of it. The `C-M-w' tells the
+following command, if it is a kill command, to append the text it kills
+to the last killed text, instead of starting a new entry. With
+`C-M-w', you can kill several separated pieces of text and accumulate
+them to be yanked back in one place.
+
+
+File: emacs, Node: Earlier Kills, Prev: Appending Kills, Up: Yanking
+
+Yanking Earlier Kills
+---------------------
+
+ To recover killed text that is no longer the most recent kill, you
+need the `Meta-y' (`yank-pop') command. `M-y' can be used only after a
+`C-y' or another `M-y'. It takes the text previously yanked and
+replaces it with the text from an earlier kill. So, to recover the
+text of the next-to-the-last kill, you first use `C-y' to recover the
+last kill, and then use `M-y' to replace it with the previous kill.
+
+ You can think in terms of a "last yank" pointer which points at an
+item in the kill ring. Each time you kill, the "last yank" pointer
+moves to the newly made item at the front of the ring. `C-y' yanks the
+item which the "last yank" pointer points to. `M-y' moves the "last
+yank" pointer to a different item, and the text in the buffer changes to
+match. Enough `M-y' commands can move the pointer to any item in the
+ring, so you can get any item into the buffer. Eventually the pointer
+reaches the end of the ring; the next `M-y' moves it to the first item
+again.
+
+ Yanking moves the "last yank" pointer around the ring, but it does
+not change the order of the entries in the ring, which always runs from
+the most recent kill at the front to the oldest one still remembered.
+
+ `M-y' can take a numeric argument, which tells it how many items to
+advance the "last yank" pointer by. A negative argument moves the
+pointer toward the front of the ring; from the front of the ring, it
+moves to the last entry and starts moving forward from there.
+
+ Once the text you are looking for is brought into the buffer, you can
+stop doing `M-y' commands and it will stay there. It's just a copy of
+the kill ring item, so editing it in the buffer does not change what's
+in the ring. As long as no new killing is done, the "last yank" pointer
+remains at the same place in the kill ring, so repeating `C-y' will
+yank another copy of the same old kill.
+
+ If you know how many `M-y' commands it would take to find the text
+you want, you can yank that text in one step using `C-y' with a numeric
+argument. `C-y' with an argument greater than one restores the text
+the specified number of entries back in the kill ring. Thus, `C-u 2
+C-y' gets the next to the last block of killed text. It is equivalent
+to `C-y M-y'. `C-y' with a numeric argument starts counting from the
+"last yank" pointer, and sets the "last yank" pointer to the entry that
+it yanks.
+
+ The length of the kill ring is controlled by the variable
+`kill-ring-max'; no more than that many blocks of killed text are saved.
+
+
+File: emacs, Node: Accumulating Text, Next: Rectangles, Prev: Yanking, Up: Top
+
+Accumulating Text
+=================
+
+ Usually we copy or move text by killing it and yanking it, but there
+are other ways that are useful for copying one block of text in many
+places, or for copying many scattered blocks of text into one place.
+
+ You can accumulate blocks of text from scattered locations either
+into a buffer or into a file if you like. These commands are described
+here. You can also use Emacs registers for storing and accumulating
+text. *Note Registers::.
+
+`C-x a'
+ Append region to contents of specified buffer (`append-to-buffer').
+
+`M-x prepend-to-buffer'
+ Prepend region to contents of specified buffer.
+
+`M-x copy-to-buffer'
+ Copy region into specified buffer, deleting that buffer's old
+ contents.
+
+`M-x insert-buffer'
+ Insert contents of specified buffer into current buffer at point.
+
+`M-x append-to-file'
+ Append region to contents of specified file, at the end.
+
+ To accumulate text into a buffer, use the command `C-x a BUFFERNAME'
+(`append-to-buffer'), which inserts a copy of the region into the
+buffer BUFFERNAME, at the location of point in that buffer. If there
+is no buffer with that name, one is created. If you append text into a
+buffer which has been used for editing, the copied text goes into the
+middle of the text of the buffer, wherever point happens to be in it.
+
+ Point in that buffer is left at the end of the copied text, so
+successive uses of `C-x a' accumulate the text in the specified buffer
+in the same order as they were copied. Strictly speaking, `C-x a' does
+not always append to the text already in the buffer; but if `C-x a' is
+the only command used to alter a buffer, it does always append to the
+existing text because point is always at the end.
+
+ `M-x prepend-to-buffer' is just like `C-x a' except that point in
+the other buffer is left before the copied text, so successive
+prependings add text in reverse order. `M-x copy-to-buffer' is similar
+except that any existing text in the other buffer is deleted, so the
+buffer is left containing just the text newly copied into it.
+
+ You can retrieve the accumulated text from that buffer with `M-x
+insert-buffer'; this too takes BUFFERNAME as an argument. It inserts a
+copy of the text in buffer BUFFERNAME into the selected buffer. You
+could alternatively select the other buffer for editing, perhaps moving
+text from it by killing or with `C-x a'. *Note Buffers::, for
+background information on buffers.
+
+ Instead of accumulating text within Emacs, in a buffer, you can
+append text directly into a file with `M-x append-to-file', which takes
+FILE-NAME as an argument. It adds the text of the region to the end of
+the specified file. The file is changed immediately on disk. This
+command is normally used with files that are not being visited in
+Emacs. Using it on a file that Emacs is visiting can produce confusing
+results, because the text inside Emacs for that file will not change
+while the file itself changes.
+
+
+File: emacs, Node: Rectangles, Next: Registers, Prev: Accumulating Text, Up: Top
+
+Rectangles
+==========
+
+ The rectangle commands affect rectangular areas of the text: all the
+characters between a certain pair of columns, in a certain range of
+lines. Commands are provided to kill rectangles, yank killed
+rectangles, clear them out, or delete them. Rectangle commands are
+useful with text in multicolumnar formats, such as perhaps code with
+comments at the right, or for changing text into or out of such formats.
+
+ When you must specify a rectangle for a command to work on, you do
+it by putting the mark at one corner and point at the opposite corner.
+The rectangle thus specified is called the "region-rectangle" because
+it is controlled about the same way the region is controlled. But
+remember that a given combination of point and mark values can be
+interpreted either as specifying a region or as specifying a rectangle;
+it is up to the command that uses them to choose the interpretation.
+
+`M-x delete-rectangle'
+ Delete the text of the region-rectangle, moving any following text
+ on each line leftward to the left edge of the region-rectangle.
+
+`M-x kill-rectangle'
+ Similar, but also save the contents of the region-rectangle as the
+ "last killed rectangle".
+
+`M-x yank-rectangle'
+ Yank the last killed rectangle with its upper left corner at point.
+
+`M-x open-rectangle'
+ Insert blank space to fill the space of the region-rectangle. The
+ previous contents of the region-rectangle are pushed rightward.
+
+`M-x clear-rectangle'
+ Clear the region-rectangle by replacing its contents with spaces.
+
+ The rectangle operations fall into two classes: commands deleting and
+moving rectangles, and commands for blank rectangles.
+
+ There are two ways to get rid of the text in a rectangle: you can
+discard the text (delete it) or save it as the "last killed" rectangle.
+ The commands for these two ways are `M-x delete-rectangle' and `M-x
+kill-rectangle'. In either case, the portion of each line that falls
+inside the rectangle's boundaries is deleted, causing following text
+(if any) on the line to move left.
+
+ Note that "killing" a rectangle is not killing in the usual sense;
+the rectangle is not stored in the kill ring, but in a special place
+that can only record the most recent rectangle killed. This is because
+yanking a rectangle is so different from yanking linear text that
+different yank commands have to be used and yank-popping is hard to
+make sense of.
+
+ Inserting a rectangle is the opposite of deleting one. All you need
+to specify is where to put the upper left corner; that is done by
+putting point there. The rectangle's first line is inserted there, the
+rectangle's second line is inserted at a point one line vertically
+down, and so on. The number of lines affected is determined by the
+height of the saved rectangle.
+
+ To insert the last killed rectangle, type `M-x yank-rectangle'. This
+can be used to convert single-column lists into double-column lists;
+kill the second half of the list as a rectangle and then yank it beside
+the first line of the list.
+
+ There are two commands for working with blank rectangles: `M-x
+clear-rectangle' to blank out existing text, and `M-x open-rectangle'
+to insert a blank rectangle. Clearing a rectangle is equivalent to
+deleting it and then inserting as blank rectangle of the same size.
+
+ Rectangles can also be copied into and out of registers. *Note
+Rectangle Registers: RegRect.
+
+
+File: emacs, Node: Registers, Next: Display, Prev: Rectangles, Up: Top
+
+Registers
+*********
+
+ Emacs "registers" are places you can save text or positions for
+later use. Text saved in a register can be copied into the buffer once
+or many times; a position saved in a register is used by moving point
+to that position. Rectangles can also be copied into and out of
+registers (*note Rectangles::.).
+
+ Each register has a name, which is a single character. A register
+can store either a piece of text or a position or a rectangle, but only
+one thing at any given time. Whatever you store in a register remains
+there until you store something else in that register.
+
+* Menu:
+
+* RegPos:: Saving positions in registers.
+* RegText:: Saving text in registers.
+* RegRect:: Saving rectangles in registers.
+
+`M-x view-register RET R'
+ Display a description of what register R contains.
+
+ `M-x view-register' reads a register name as an argument and then
+displays the contents of the specified register.
+
+
+File: emacs, Node: RegPos, Next: RegText, Prev: Registers, Up: Registers
+
+Saving Positions in Registers
+=============================
+
+ Saving a position records a spot in a buffer so that you can move
+back there later. Moving to a saved position reselects the buffer and
+moves point to the spot.
+
+`C-x / R'
+ Save location of point in register R (`point-to-register').
+
+`C-x j R'
+ Jump to the location saved in register R (`register-to-point').
+
+ To save the current location of point in a register, choose a name R
+and type `C-x / R'. The register R retains the location thus saved
+until you store something else in that register.
+
+ The command `C-x j R' moves point to the location recorded in
+register R. The register is not affected; it continues to record the
+same location. You can jump to the same position using the same
+register any number of times.
+
+
+File: emacs, Node: RegText, Next: RegRect, Prev: RegPos, Up: Registers
+
+Saving Text in Registers
+========================
+
+ When you want to insert a copy of the same piece of text frequently,
+it may be impractical to use the kill ring, since each subsequent kill
+moves the piece of text further down on the ring. It becomes hard to
+keep track of what argument is needed to retrieve the same text with
+`C-y'. An alternative is to store the text in a register with `C-x x'
+(`copy-to-register') and then retrieve it with `C-x g'
+(`insert-register').
+
+`C-x x R'
+ Copy region into register R (`copy-to-register').
+
+`C-x g R'
+ Insert text contents of register R (`insert-register').
+
+ `C-x x R' stores a copy of the text of the region into the register
+named R. Given a numeric argument, `C-x x' deletes the text from the
+buffer as well.
+
+ `C-x g R' inserts in the buffer the text from register R. Normally
+it leaves point before the text and places the mark after, but with a
+numeric argument it puts point after the text and the mark before.
+
+
+File: emacs, Node: RegRect, Prev: RegText, Up: Registers
+
+Saving Rectangles in Registers
+==============================
+
+ A register can contain a rectangle instead of linear text. The
+rectangle is represented as a list of strings. *Note Rectangles::, for
+basic information on rectangles and how rectangles in the buffer are
+specified.
+
+`C-x r R'
+ Copy the region-rectangle into register R
+ (`copy-region-to-rectangle'). With numeric argument, delete it as
+ well.
+
+`C-x g R'
+ Insert the rectangle stored in register R (if it contains a
+ rectangle) (`insert-register').
+
+ The `C-x g' command inserts linear text if the register contains
+that, or inserts a rectangle if the register contains one.
+
+
+File: emacs, Node: Display, Next: Search, Prev: Registers, Up: Top
+
+Controlling the Display
+***********************
+
+ Since only part of a large buffer fits in the window, Emacs tries to
+show the part that is likely to be interesting. The display control
+commands allow you to specify which part of the text you want to see.
+
+`C-l'
+ Clear screen and redisplay, scrolling the selected window to center
+ point vertically within it (`recenter').
+
+`C-v'
+ Scroll forward (a windowful or a specified number of lines)
+ (`scroll-up').
+
+`M-v'
+ Scroll backward (`scroll-down').
+
+`ARG C-l'
+ Scroll so point is on line ARG (`recenter').
+
+`C-x <'
+ Scroll text in current window to the left (`scroll-left').
+
+`C-x >'
+ Scroll to the right (`scroll-right').
+
+`C-x $'
+ Make deeply indented lines invisible (`set-selective-display').
+
+* Menu:
+
+* Scrolling:: Moving text up and down in a window.
+* Horizontal Scrolling:: Moving text left and right in a window.
+* Selective Display:: Hiding lines with lots of indentation.
+* Display Vars:: Information on variables for customizing display.
+
+
+File: emacs, Node: Scrolling, Next: Horizontal Scrolling, Prev: Display, Up: Display
+
+Scrolling
+=========
+
+ If a buffer contains text that is too large to fit entirely within a
+window that is displaying the buffer, Emacs shows a contiguous section
+of the text. The section shown always contains point.
+
+ "Scrolling" means moving text up or down in the window so that
+different parts of the text are visible. Scrolling forward means that
+text moves up, and new text appears at the bottom. Scrolling backward
+moves text down and new text appears at the top.
+
+ Scrolling happens automatically if you move point past the bottom or
+top of the window. You can also explicitly request scrolling with the
+commands in this section.
+
+`C-l'
+ Clear screen and redisplay, scrolling the selected window to center
+ point vertically within it (`recenter').
+
+`C-v'
+ Scroll forward (a windowful or a specified number of lines)
+ (`scroll-up').
+
+`M-v'
+ Scroll backward (`scroll-down').
+
+`ARG C-l'
+ Scroll so point is on line ARG (`recenter').
+
+ The most basic scrolling command is `C-l' (`recenter') with no
+argument. It clears the entire screen and redisplays all windows. In
+addition, the selected window is scrolled so that point is halfway down
+from the top of the window.
+
+ The scrolling commands `C-v' and `M-v' let you move all the text in
+the window up or down a few lines. `C-v' (`scroll-up') with an
+argument shows you that many more lines at the bottom of the window,
+moving the text and point up together as `C-l' might. `C-v' with a
+negative argument shows you more lines at the top of the window.
+`Meta-v' (`scroll-down') is like `C-v', but moves in the opposite
+direction.
+
+ To read the buffer a windowful at a time, use `C-v' with no argument.
+It takes the last two lines at the bottom of the window and puts them at
+the top, followed by nearly a whole windowful of lines not previously
+visible. If point was in the text scrolled off the top, it moves to the
+new top of the window. `M-v' with no argument moves backward with
+overlap similarly. The number of lines of overlap across a `C-v' or
+`M-v' is controlled by the variable `next-screen-context-lines'; by
+default, it is two.
+
+ Another way to do scrolling is with `C-l' with a numeric argument.
+`C-l' does not clear the screen when given an argument; it only scrolls
+the selected window. With a positive argument N, it repositions text
+to put point N lines down from the top. An argument of zero puts point
+on the very top line. Point does not move with respect to the text;
+rather, the text and point move rigidly on the screen. `C-l' with a
+negative argument puts point that many lines from the bottom of the
+window. For example, `C-u - 1 C-l' puts point on the bottom line, and
+`C-u - 5 C-l' puts it five lines from the bottom. Just `C-u' as
+argument, as in `C-u C-l', scrolls point to the center of the screen.
+
+ Scrolling happens automatically if point has moved out of the visible
+portion of the text when it is time to display. Usually the scrolling
+is done so as to put point vertically centered within the window.
+However, if the variable `scroll-step' has a nonzero value, an attempt
+is made to scroll the buffer by that many lines; if that is enough to
+bring point back into visibility, that is what is done.
+
+ \ No newline at end of file
diff --git a/info/emacs-4 b/info/emacs-4
new file mode 100644
index 00000000000..47a8cb7cd06
--- /dev/null
+++ b/info/emacs-4
@@ -0,0 +1,1133 @@
+This is Info file ../info/emacs, produced by Makeinfo-1.49 from the
+input file emacs.texi.
+
+ This file documents the GNU Emacs editor.
+
+ Copyright (C) 1985, 1986, 1988, 1992 Richard M. Stallman.
+
+ Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+ Permission is granted to copy and distribute modified versions of
+this manual under the conditions for verbatim copying, provided also
+that the sections entitled "The GNU Manifesto", "Distribution" and "GNU
+General Public License" are included exactly as in the original, and
+provided that the entire resulting derived work is distributed under the
+terms of a permission notice identical to this one.
+
+ Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that the sections entitled "The GNU Manifesto",
+"Distribution" and "GNU General Public License" may be included in a
+translation approved by the author instead of in the original English.
+
+
+File: emacs, Node: Horizontal Scrolling, Prev: Scrolling, Up: Display
+
+Horizontal Scrolling
+====================
+
+`C-x <'
+ Scroll text in current window to the left (`scroll-left').
+
+`C-x >'
+ Scroll to the right (`scroll-right').
+
+ The text in a window can also be scrolled horizontally. This means
+that each line of text is shifted sideways in the window, and one or
+more characters at the beginning of each line are not displayed at all.
+ When a window has been scrolled horizontally in this way, text lines
+are truncated rather than continued (*note Continuation Lines::.), with
+a `$' appearing in the first column when there is text truncated to the
+left, and in the last column when there is text truncated to the right.
+
+ The command `C-x <' (`scroll-left') scrolls the selected window to
+the left by N columns with argument N. With no argument, it scrolls by
+almost the full width of the window (two columns less, to be precise).
+`C-x >' (`scroll-right') scrolls similarly to the right. The window
+cannot be scrolled any farther to the right once it is displaying
+normally (with each line starting at the window's left margin);
+attempting to do so has no effect.
+
+
+File: emacs, Node: Selective Display, Next: Display Vars, Prev: Display, Up: Display
+
+Selective Display
+=================
+
+ Emacs has the ability to hide lines indented more than a certain
+number of columns (you specify how many columns). You can use this to
+get an overview of a part of a program.
+
+ To hide lines, type `C-x $' (`set-selective-display') with a numeric
+argument N. (*Note Arguments::, for how to give the argument.) Then
+lines with at least N columns of indentation disappear from the screen.
+ The only indication of their presence is that three dots (`...')
+appear at the end of each visible line that is followed by one or more
+invisible ones.
+
+ The invisible lines are still present in the buffer, and most editing
+commands see them as usual, so it is very easy to put point in the
+middle of invisible text. When this happens, the cursor appears at the
+end of the previous line, after the three dots. If point is at the end
+of the visible line, before the newline that ends it, the cursor
+appears before the three dots.
+
+ The commands `C-n' and `C-p' move across the invisible lines as if
+they were not there.
+
+ To make everything visible again, type `C-x $' with no argument.
+
+
+File: emacs, Node: Display Vars, Prev: Selective Display, Up: Display
+
+Variables Controlling Display
+=============================
+
+ This section contains information for customization only. Beginning
+users should skip it.
+
+ The variable `mode-line-inverse-video' controls whether the mode
+line is displayed in inverse video (assuming the terminal supports it);
+`nil' means don't do so. *Note Mode Line::.
+
+ If the variable `inverse-video' is non-`nil', Emacs attempts to
+invert all the lines of the display from what they normally are.
+
+ If the variable `visible-bell' is non-`nil', Emacs attempts to make
+the whole screen blink when it would normally make an audible bell
+sound. This variable has no effect if your terminal does not have a way
+to make the screen blink.
+
+ When you reenter Emacs after suspending, Emacs normally clears the
+screen and redraws the entire display. On some terminals with more
+than one page of memory, it is possible to arrange the termcap entry so
+that the `ti' and `te' strings (output to the terminal when Emacs is
+entered and exited, respectively) switch between pages of memory so as
+to use one page for Emacs and another page for other output. Then you
+might want to set the variable `no-redraw-on-reenter' non-`nil' so that
+Emacs will assume, when resumed, that the screen page it is using still
+contains what Emacs last wrote there.
+
+ The variable `echo-keystrokes' controls the echoing of
+multi-character keys; its value is the number of seconds of pause
+required to cause echoing to start, or zero meaning don't echo at all.
+*Note Echo Area::.
+
+ If the variable `ctl-arrow' is `nil', control characters in the
+buffer are displayed with octal escape sequences, all except newline and
+tab. Altering the value of `ctl-arrow' makes it local to the current
+buffer; until that time, the default value is in effect. The default is
+initially `t'. *Note Locals::.
+
+ Normally, a tab character in the buffer is displayed as whitespace
+which extends to the next display tab stop position, and display tab
+stops come at intervals equal to eight spaces. The number of spaces
+per tab is controlled by the variable `tab-width', which is made local
+by changing it, just like `ctl-arrow'. Note that how the tab character
+in the buffer is displayed has nothing to do with the definition of TAB
+as a command.
+
+ If you set the variable `selective-display-ellipses' to `nil', the
+three dots do not appear at the end of a line that precedes invisible
+lines. Then there is no visible indication of the invisible lines.
+This variable too becomes local automatically when set.
+
+
+File: emacs, Node: Search, Next: Fixit, Prev: Display, Up: Top
+
+Searching and Replacement
+*************************
+
+ Like other editors, Emacs has commands for searching for occurrences
+of a string. The principal search command is unusual in that it is
+"incremental"; it begins to search before you have finished typing the
+search string. There are also nonincremental search commands more like
+those of other editors.
+
+ Besides the usual `replace-string' command that finds all
+occurrences of one string and replaces them with another, Emacs has a
+fancy replacement command called `query-replace' which asks
+interactively which occurrences to replace.
+
+* Menu:
+
+* Incremental Search:: Search happens as you type the string.
+* Nonincremental Search:: Specify entire string and then search.
+* Word Search:: Search for sequence of words.
+* Regexp Search:: Search for match for a regexp.
+* Regexps:: Syntax of regular expressions.
+* Search Case:: To ignore case while searching, or not.
+* Replace:: Search, and replace some or all matches.
+* Other Repeating Search:: Operating on all matches for some regexp.
+
+
+File: emacs, Node: Incremental Search, Next: Nonincremental Search, Prev: Search, Up: Search
+
+Incremental Search
+==================
+
+ An incremental search begins searching as soon as you type the first
+character of the search string. As you type in the search string, Emacs
+shows you where the string (as you have typed it so far) would be found.
+When you have typed enough characters to identify the place you want,
+you can stop. Depending on what you will do next, you may or may not
+need to terminate the search explicitly with an ESC first.
+
+`C-s'
+ Incremental search forward (`isearch-forward').
+
+`C-r'
+ Incremental search backward (`isearch-backward').
+
+ `C-s' starts an incremental search. `C-s' reads characters from the
+keyboard and positions the cursor at the first occurrence of the
+characters that you have typed. If you type `C-s' and then `F', the
+cursor moves right after the first `F'. Type an `O', and see the
+cursor move to after the first `FO'. After another `O', the cursor is
+after the first `FOO' after the place where you started the search.
+Meanwhile, the search string `FOO' has been echoed in the echo area.
+
+ The echo area display ends with three dots when actual searching is
+going on. When search is waiting for more input, the three dots are
+removed. (On slow terminals, the three dots are not displayed.)
+
+ If you make a mistake in typing the search string, you can erase
+characters with DEL. Each DEL cancels the last character of search
+string. This does not happen until Emacs is ready to read another
+input character; first it must either find, or fail to find, the
+character you want to erase. If you do not want to wait for this to
+happen, use `C-g' as described below.
+
+ When you are satisfied with the place you have reached, you can type
+ESC, which stops searching, leaving the cursor where the search brought
+it. Also, any command not specially meaningful in searches stops the
+searching and is then executed. Thus, typing `C-a' would exit the
+search and then move to the beginning of the line. ESC is necessary
+only if the next command you want to type is a printing character, DEL,
+ESC, or another control character that is special within searches
+(`C-q', `C-w', `C-r', `C-s' or `C-y').
+
+ Sometimes you search for `FOO' and find it, but not the one you
+expected to find. There was a second `FOO' that you forgot about,
+before the one you were looking for. In this event, type another `C-s'
+to move to the next occurrence of the search string. This can be done
+any number of times. If you overshoot, you can cancel some `C-s'
+characters with DEL.
+
+ After you exit a search, you can search for the same string again by
+typing just `C-s C-s': the first `C-s' is the key that invokes
+incremental search, and the second `C-s' means "search again".
+
+ If your string is not found at all, the echo area says `Failing
+I-Search'. The cursor is after the place where Emacs found as much of
+your string as it could. Thus, if you search for `FOOT', and there is
+no `FOOT', you might see the cursor after the `FOO' in `FOOL'. At this
+point there are several things you can do. If your string was
+mistyped, you can rub some of it out and correct it. If you like the
+place you have found, you can type ESC or some other Emacs command to
+"accept what the search offered". Or you can type `C-g', which removes
+from the search string the characters that could not be found (the `T'
+in `FOOT'), leaving those that were found (the `FOO' in `FOOT'). A
+second `C-g' at that point cancels the search entirely, returning point
+to where it was when the search started.
+
+ If a search is failing and you ask to repeat it by typing another
+`C-s', it starts again from the beginning of the buffer. Repeating a
+failing reverse search with `C-r' starts again from the end. This is
+called "wrapping around". `Wrapped' appears in the search prompt once
+this has happened.
+
+ The `C-g' "quit" character does special things during searches; just
+what it does depends on the status of the search. If the search has
+found what you specified and is waiting for input, `C-g' cancels the
+entire search. The cursor moves back to where you started the search.
+If `C-g' is typed when there are characters in the search string that
+have not been found--because Emacs is still searching for them, or
+because it has failed to find them--then the search string characters
+which have not been found are discarded from the search string. With
+them gone, the search is now successful and waiting for more input, so
+a second `C-g' will cancel the entire search.
+
+ To search for a control character such as `C-s' or DEL or ESC, you
+must quote it by typing `C-q' first. This function of `C-q' is
+analogous to its meaning as an Emacs command: it causes the following
+character to be treated the way a graphic character would normally be
+treated in the same context. You can also specify a quoted character
+in octal while searching, just as you can for insertion. *Note Basic::.
+
+ You can change to searching backwards with `C-r'. If a search fails
+because the place you started was too late in the file, you should do
+this. Repeated `C-r' keeps looking for more occurrences backwards. A
+`C-s' starts going forwards again. `C-r' in a search can be cancelled
+with DEL.
+
+ If you know initially that you want to search backwards, you can use
+`C-r' instead of `C-s' to start the search, because `C-r' is also a key
+running a command (`isearch-backward') to search backward.
+
+ The characters `C-y' and `C-w' can be used in incremental search to
+grab text from the buffer into the search string. This makes it
+convenient to search for another occurrence of text at point. `C-w'
+copies the word after point as part of the search string, advancing
+point over that word. Another `C-s' to repeat the search will then
+search for a string including that word. `C-y' is similar to `C-w' but
+copies all the rest of the current line into the search string.
+
+ All the characters special in incremental search can be changed by
+setting the following variables:
+
+`search-delete-char'
+ Character to delete from incremental search string (normally DEL).
+
+`search-exit-char'
+ Character to exit incremental search (normally ESC).
+
+`search-quote-char'
+ Character to quote special characters for incremental search
+ (normally `C-q').
+
+`search-repeat-char'
+ Character to repeat incremental search forwards (normally `C-s').
+
+`search-reverse-char'
+ Character to repeat incremental search backwards (normally `C-r').
+
+`search-yank-line-char'
+ Character to pull rest of line from buffer into search string
+ (normally `C-y').
+
+`search-yank-word-char'
+ Character to pull next word from buffer into search string
+ (normally `C-w').
+
+Slow Terminal Incremental Search
+--------------------------------
+
+ Incremental search on a slow terminal uses a modified style of
+display that is designed to take less time. Instead of redisplaying
+the buffer at each place the search gets to, it creates a new
+single-line window and uses that to display the line that the search
+has found. The single-line window comes into play as soon as point
+gets outside of the text that is already on the screen.
+
+ When the search is terminated, the single-line window is removed.
+Only at this time is the window in which the search was done
+redisplayed to show its new value of point.
+
+ The three dots at the end of the search string, normally used to
+indicate that searching is going on, are not displayed in slow style
+display.
+
+ The slow terminal style of display is used when the terminal baud
+rate is less than or equal to the value of the variable
+`search-slow-speed', initially 1200.
+
+ The number of lines to use in slow terminal search display is
+controlled by the variable `search-slow-window-lines'. 1 is its normal
+value.
+
+
+File: emacs, Node: Nonincremental Search, Next: Word Search, Prev: Incremental Search, Up: Search
+
+Nonincremental Search
+=====================
+
+ Emacs also has conventional nonincremental search commands, which
+require you to type the entire search string before searching begins.
+
+`C-s ESC STRING RET'
+ Search for STRING.
+
+`C-r ESC STRING RET'
+ Search backward for STRING.
+
+ To do a nonincremental search, first type `C-s ESC'. This enters
+the minibuffer to read the search string; terminate the string with
+RET, and then the search is done. If the string is not found the
+search command gets an error.
+
+ The way `C-s ESC' works is that the `C-s' invokes incremental
+search, which is specially programmed to invoke nonincremental search
+if the argument you give it is empty. (Such an empty argument would
+otherwise be useless.) `C-r ESC' also works this way.
+
+ Forward and backward nonincremental searches are implemented by the
+commands `search-forward' and `search-backward'. These commands may be
+bound to keys in the usual manner. The reason that incremental search
+is programmed to invoke them as well is that `C-s ESC' is the
+traditional sequence of characters used in Emacs to invoke
+nonincremental search.
+
+ However, nonincremental searches performed using `C-s ESC' do not
+call `search-forward' right away. The first thing done is to see if
+the next character is `C-w', which requests a word search. *Note Word
+Search::.
+
+
+File: emacs, Node: Word Search, Next: Regexp Search, Prev: Nonincremental Search, Up: Search
+
+Word Search
+===========
+
+ Word search searches for a sequence of words without regard to how
+the words are separated. More precisely, you type a string of many
+words, using single spaces to separate them, and the string can be
+found even if there are multiple spaces, newlines or other punctuation
+between the words.
+
+ Word search is useful in editing documents formatted by text
+formatters. If you edit while looking at the printed, formatted
+version, you can't tell where the line breaks are in the source file.
+With word search, you can search without having to know them.
+
+`C-s ESC C-w WORDS RET'
+ Search for WORDS, ignoring differences in punctuation.
+
+`C-r ESC C-w WORDS RET'
+ Search backward for WORDS, ignoring differences in punctuation.
+
+ Word search is a special case of nonincremental search and is invoked
+with `C-s ESC C-w'. This is followed by the search string, which must
+always be terminated with RET. Being nonincremental, this search does
+not start until the argument is terminated. It works by constructing a
+regular expression and searching for that. *Note Regexp Search::.
+
+ A backward word search can be done by `C-r ESC C-w'.
+
+ Forward and backward word searches are implemented by the commands
+`word-search-forward' and `word-search-backward'. These commands may
+be bound to keys in the usual manner. The reason that incremental
+search is programmed to invoke them as well is that `C-s ESC C-w' is
+the traditional Emacs sequence of keys for word search.
+
+
+File: emacs, Node: Regexp Search, Next: Regexps, Prev: Word Search, Up: Search
+
+Regular Expression Search
+=========================
+
+ A "regular expression" ("regexp", for short) is a pattern that
+denotes a set of strings, possibly an infinite set. Searching for
+matches for a regexp is a very powerful operation that editors on Unix
+systems have traditionally offered. In GNU Emacs, you can search for
+the next match for a regexp either incrementally or not.
+
+ Incremental search for a regexp is done by typing `C-M-s'
+(`isearch-forward-regexp'). This command reads a search string
+incrementally just like `C-s', but it treats the search string as a
+regexp rather than looking for an exact match against the text in the
+buffer. Each time you add text to the search string, you make the
+regexp longer, and the new regexp is searched for. A reverse regexp
+search command, `isearch-backward-regexp', also exists but no key runs
+it.
+
+ All of the control characters that do special things within an
+ordinary incremental search have the same function in incremental
+regexp search. Typing `C-s' or `C-r' immediately after starting the
+search retrieves the last incremental search regexp used; that is to
+say, incremental regexp and non-regexp searches have independent
+defaults.
+
+ Note that adding characters to the regexp in an incremental regexp
+search does not make the cursor move back and start again. Perhaps it
+ought to; I am not sure. As it stands, if you have searched for `foo'
+and you add `\|bar', the search will not check for a `bar' in the
+buffer before the `foo'.
+
+ Nonincremental search for a regexp is done by the functions
+`re-search-forward' and `re-search-backward'. You can invoke these
+with `M-x', or bind them to keys. Also, you can call
+`re-search-forward' by way of incremental regexp search with `C-M-s
+ESC'.
+
+
+File: emacs, Node: Regexps, Next: Search Case, Prev: Regexp Search, Up: Search
+
+Syntax of Regular Expressions
+=============================
+
+ Regular expressions have a syntax in which a few characters are
+special constructs and the rest are "ordinary". An ordinary character
+is a simple regular expression which matches that character and nothing
+else. The special characters are `$', `^', `.', `*', `+', `?', `[', `]'
+and `\'; no new special characters will be defined. Any other
+character appearing in a regular expression is ordinary, unless a `\'
+precedes it.
+
+ For example, `f' is not a special character, so it is ordinary, and
+therefore `f' is a regular expression that matches the string `f' and
+no other string. (It does not match the string `ff'.) Likewise, `o'
+is a regular expression that matches only `o'.
+
+ Any two regular expressions A and B can be concatenated. The result
+is a regular expression which matches a string if A matches some amount
+of the beginning of that string and B matches the rest of the string.
+
+ As a simple example, we can concatenate the regular expressions `f'
+and `o' to get the regular expression `fo', which matches only the
+string `fo'. Still trivial. To do something nontrivial, you need to
+use one of the special characters. Here is a list of them.
+
+`. (Period)'
+ is a special character that matches any single character except a
+ newline. Using concatenation, we can make regular expressions like
+ `a.b' which matches any three-character string which begins with
+ `a' and ends with `b'.
+
+`*'
+ is not a construct by itself; it is a suffix, which means the
+ preceding regular expression is to be repeated as many times as
+ possible. In `fo*', the `*' applies to the `o', so `fo*' matches
+ one `f' followed by any number of `o's. The case of zero `o's is
+ allowed: `fo*' does match `f'.
+
+ `*' always applies to the smallest possible preceding expression.
+ Thus, `fo*' has a repeating `o', not a repeating `fo'.
+
+ The matcher processes a `*' construct by matching, immediately, as
+ many repetitions as can be found. Then it continues with the rest
+ of the pattern. If that fails, backtracking occurs, discarding
+ some of the matches of the `*'-modified construct in case that
+ makes it possible to match the rest of the pattern. For example,
+ matching `ca*ar' against the string `caaar', the `a*' first tries
+ to match all three `a's; but the rest of the pattern is `ar' and
+ there is only `r' left to match, so this try fails. The next
+ alternative is for `a*' to match only two `a's. With this choice,
+ the rest of the regexp matches successfully.
+
+`+'
+ Is a suffix character similar to `*' except that it requires that
+ the preceding expression be matched at least once. So, for
+ example, `ca+r' will match the strings `car' and `caaaar' but not
+ the string `cr', whereas `ca*r' would match all three strings.
+
+`?'
+ Is a suffix character similar to `*' except that it can match the
+ preceding expression either once or not at all. For example,
+ `ca?r' will match `car' or `cr'; nothing else.
+
+`[ ... ]'
+ `[' begins a "character set", which is terminated by a `]'. In
+ the simplest case, the characters between the two form the set.
+ Thus, `[ad]' matches either one `a' or one `d', and `[ad]*'
+ matches any string composed of just `a's and `d's (including the
+ empty string), from which it follows that `c[ad]*r' matches `cr',
+ `car', `cdr', `caddaar', etc.
+
+ Character ranges can also be included in a character set, by
+ writing two characters with a `-' between them. Thus, `[a-z]'
+ matches any lower-case letter. Ranges may be intermixed freely
+ with individual characters, as in `[a-z$%.]', which matches any
+ lower case letter or `$', `%' or period.
+
+ Note that the usual special characters are not special any more
+ inside a character set. A completely different set of special
+ characters exists inside character sets: `]', `-' and `^'.
+
+ To include a `]' in a character set, you must make it the first
+ character. For example, `[]a]' matches `]' or `a'. To include a
+ `-', write `---', which is a range containing only `-'. To
+ include `^', make it other than the first character in the set.
+
+`[^ ... ]'
+ `[^' begins a "complement character set", which matches any
+ character except the ones specified. Thus, `[^a-z0-9A-Z]' matches
+ all characters except letters and digits.
+
+ `^' is not special in a character set unless it is the first
+ character. The character following the `^' is treated as if it
+ were first (`-' and `]' are not special there).
+
+ Note that a complement character set can match a newline, unless
+ newline is mentioned as one of the characters not to match.
+
+`^'
+ is a special character that matches the empty string, but only if
+ at the beginning of a line in the text being matched. Otherwise
+ it fails to match anything. Thus, `^foo' matches a `foo' which
+ occurs at the beginning of a line.
+
+`$'
+ is similar to `^' but matches only at the end of a line. Thus,
+ `xx*$' matches a string of one `x' or more at the end of a line.
+
+`\'
+ has two functions: it quotes the special characters (including
+ `\'), and it introduces additional special constructs.
+
+ Because `\' quotes special characters, `\$' is a regular
+ expression which matches only `$', and `\[' is a regular
+ expression which matches only `[', and so on.
+
+ Note: for historical compatibility, special characters are treated as
+ordinary ones if they are in contexts where their special meanings make
+no sense. For example, `*foo' treats `*' as ordinary since there is no
+preceding expression on which the `*' can act. It is poor practice to
+depend on this behavior; better to quote the special character anyway,
+regardless of where is appears.
+
+ For the most part, `\' followed by any character matches only that
+character. However, there are several exceptions: characters which,
+when preceded by `\', are special constructs. Such characters are
+always ordinary when encountered on their own. Here is a table of `\'
+constructs.
+
+`\|'
+ specifies an alternative. Two regular expressions A and B with
+ `\|' in between form an expression that matches anything that
+ either A or B will match.
+
+ Thus, `foo\|bar' matches either `foo' or `bar' but no other string.
+
+ `\|' applies to the largest possible surrounding expressions.
+ Only a surrounding `\( ... \)' grouping can limit the grouping
+ power of `\|'.
+
+ Full backtracking capability exists to handle multiple uses of
+ `\|'.
+
+`\( ... \)'
+ is a grouping construct that serves three purposes:
+
+ 1. To enclose a set of `\|' alternatives for other operations.
+ Thus, `\(foo\|bar\)x' matches either `foox' or `barx'.
+
+ 2. To enclose a complicated expression for the postfix `*' to
+ operate on. Thus, `ba\(na\)*' matches `bananana', etc., with
+ any (zero or more) number of `na' strings.
+
+ 3. To mark a matched substring for future reference.
+
+
+ This last application is not a consequence of the idea of a
+ parenthetical grouping; it is a separate feature which happens to
+ be assigned as a second meaning to the same `\( ... \)' construct
+ because there is no conflict in practice between the two meanings.
+ Here is an explanation of this feature:
+
+`\DIGIT'
+ after the end of a `\( ... \)' construct, the matcher remembers the
+ beginning and end of the text matched by that construct. Then,
+ later on in the regular expression, you can use `\' followed by
+ DIGIT to mean "match the same text matched the DIGIT'th time by the
+ `\( ... \)' construct."
+
+ The strings matching the first nine `\( ... \)' constructs
+ appearing in a regular expression are assigned numbers 1 through 9
+ in order that the open-parentheses appear in the regular
+ expression. `\1' through `\9' may be used to refer to the text
+ matched by the corresponding `\( ... \)' construct.
+
+ For example, `\(.*\)\1' matches any newline-free string that is
+ composed of two identical halves. The `\(.*\)' matches the first
+ half, which may be anything, but the `\1' that follows must match
+ the same exact text.
+
+`\`'
+ matches the empty string, provided it is at the beginning of the
+ buffer.
+
+`\''
+ matches the empty string, provided it is at the end of the buffer.
+
+`\b'
+ matches the empty string, provided it is at the beginning or end
+ of a word. Thus, `\bfoo\b' matches any occurrence of `foo' as a
+ separate word. `\bballs?\b' matches `ball' or `balls' as a
+ separate word.
+
+`\B'
+ matches the empty string, provided it is not at the beginning or
+ end of a word.
+
+`\<'
+ matches the empty string, provided it is at the beginning of a
+ word.
+
+`\>'
+ matches the empty string, provided it is at the end of a word.
+
+`\w'
+ matches any word-constituent character. The editor syntax table
+ determines which characters these are.
+
+`\W'
+ matches any character that is not a word-constituent.
+
+`\sCODE'
+ matches any character whose syntax is CODE. CODE is a character
+ which represents a syntax code: thus, `w' for word constituent,
+ `-' for whitespace, `(' for open-parenthesis, etc. *Note Syntax::.
+
+`\SCODE'
+ matches any character whose syntax is not CODE.
+
+ Here is a complicated regexp, used by Emacs to recognize the end of a
+sentence together with any whitespace that follows. It is given in Lisp
+syntax to enable you to distinguish the spaces from the tab characters.
+ In Lisp syntax, the string constant begins and ends with a
+double-quote. `\"' stands for a double-quote as part of the regexp,
+`\\' for a backslash as part of the regexp, `\t' for a tab and `\n' for
+a newline.
+
+ "[.?!][]\"')]*\\($\\|\t\\| \\)[ \t\n]*"
+
+This contains four parts in succession: a character set matching period,
+`?' or `!'; a character set matching close-brackets, quotes or
+parentheses, repeated any number of times; an alternative in
+backslash-parentheses that matches end-of-line, a tab or two spaces;
+and a character set matching whitespace characters, repeated any number
+of times.
+
+ Note that the above example shows how to write this regexp when
+entering it as part of an Emacs Lisp program. To enter the same regexp
+in an interactive command such as `re-search-forward' you must spell it
+differently:
+
+ [.?!][]"')]*\($\|^Q^I\| \)[ ^Q^I^Q^J]*
+
+
+File: emacs, Node: Search Case, Next: Replace, Prev: Regexps, Up: Search
+
+Searching and Case
+==================
+
+ All sorts of searches in Emacs normally ignore the case of the text
+they are searching through; if you specify searching for `FOO', then
+`Foo' and `foo' are also considered a match. Regexps, and in
+particular character sets, are included: `[aB]' would match `a' or `A'
+or `b' or `B'.
+
+ If you do not want this feature, set the variable `case-fold-search'
+to `nil'. Then all letters must match exactly, including case. This
+is a per-buffer variable; altering the variable affects only the current
+buffer, but there is a default value which you can change as well.
+*Note Locals::.
+
+
+File: emacs, Node: Replace, Next: Other Repeating Search, Prev: Search Case, Up: Search
+
+Replacement Commands
+====================
+
+ Global search-and-replace operations are not needed as often in
+Emacs as they are in other editors, but they are available. In
+addition to the simple `replace-string' command which is like that
+found in most editors, there is a `query-replace' command which asks
+you, for each occurrence of the pattern, whether to replace it.
+
+ The replace commands all replace one string (or regexp) with one
+replacement string. It is possible to perform several replacements in
+parallel using the command `expand-region-abbrevs'. *Note Expanding
+Abbrevs::.
+
+* Menu:
+
+* Unconditional Replace:: Replacing all matches for a string.
+* Regexp Replace:: Replacing all matches for a regexp.
+* Replacement and Case:: How replacements preserve case of letters.
+* Query Replace:: How to use querying.
+
+
+File: emacs, Node: Unconditional Replace, Next: Regexp Replace, Prev: Replace, Up: Replace
+
+Unconditional Replacement
+-------------------------
+
+`M-x replace-string RET STRING RET NEWSTRING RET'
+ Replace every occurrence of STRING with NEWSTRING.
+
+`M-x replace-regexp RET REGEXP RET NEWSTRING RET'
+ Replace every match for REGEXP with NEWSTRING.
+
+ To replace every instance of `foo' after point with `bar', use the
+command `M-x replace-string' with the two arguments `foo' and `bar'.
+Replacement occurs only after point, so if you want to cover the whole
+buffer you must go to the beginning first. All occurrences up to the
+end of the buffer are replaced; to limit replacement to part of the
+buffer, narrow to that part of the buffer before doing the replacement
+(*note Narrowing::.).
+
+ When `replace-string' exits, point is left at the last occurrence
+replaced. The value of point when the `replace-string' command was
+issued is remembered on the mark ring; `C-u C-SPC' moves back there.
+
+ A numeric argument restricts replacement to matches that are
+surrounded by word boundaries.
+
+
+File: emacs, Node: Regexp Replace, Next: Replacement and Case, Prev: Unconditional Replace, Up: Replace
+
+Regexp Replacement
+------------------
+
+ `replace-string' replaces exact matches for a single string. The
+similar command `replace-regexp' replaces any match for a specified
+pattern.
+
+ In `replace-regexp', the NEWSTRING need not be constant. It can
+refer to all or part of what is matched by the REGEXP. `\&' in
+NEWSTRING stands for the entire text being replaced. `\D' in NEWSTRING,
+where D is a digit, stands for whatever matched the D'th parenthesized
+grouping in REGEXP. For example,
+
+ M-x replace-regexp RET c[ad]+r RET \&-safe RET
+
+would replace (for example) `cadr' with `cadr-safe' and `cddr' with
+`cddr-safe'.
+
+ M-x replace-regexp RET \(c[ad]+r\)-safe RET \1 RET
+
+would perform exactly the opposite replacements. To include a `\' in
+the text to replace with, you must give `\\'.
+
+
+File: emacs, Node: Replacement and Case, Next: Query Replace, Prev: Regexp Replace, Up: Replace
+
+Replace Commands and Case
+-------------------------
+
+ If the arguments to a replace command are in lower case, it preserves
+case when it makes a replacement. Thus, the command
+
+ M-x replace-string RET foo RET bar RET
+
+replaces a lower case `foo' with a lower case `bar', `FOO' with `BAR',
+and `Foo' with `Bar'. If upper case letters are used in the second
+argument, they remain upper case every time that argument is inserted.
+If upper case letters are used in the first argument, the second
+argument is always substituted exactly as given, with no case
+conversion. Likewise, if the variable `case-replace' is set to `nil',
+replacement is done without case conversion. If `case-fold-search' is
+set to `nil', case is significant in matching occurrences of `foo' to
+replace; also, case conversion of the replacement string is not done.
+
+
+File: emacs, Node: Query Replace, Prev: Replacement and Case, Up: Replace
+
+Query Replace
+-------------
+
+`M-% STRING RET NEWSTRING RET'
+`M-x query-replace RET STRING RET NEWSTRING RET'
+ Replace some occurrences of STRING with NEWSTRING.
+
+`M-x query-replace-regexp RET REGEXP RET NEWSTRING RET'
+ Replace some matches for REGEXP with NEWSTRING.
+
+ If you want to change only some of the occurrences of `foo' to
+`bar', not all of them, then you cannot use an ordinary
+`replace-string'. Instead, use `M-%' (`query-replace'). This command
+finds occurrences of `foo' one by one, displays each occurrence and
+asks you whether to replace it. A numeric argument to `query-replace'
+tells it to consider only occurrences that are bounded by
+word-delimiter characters.
+
+ Aside from querying, `query-replace' works just like
+`replace-string', and `query-replace-regexp' works just like
+`replace-regexp'.
+
+ The things you can type when you are shown an occurrence of STRING
+or a match for REGEXP are:
+
+`SPC'
+ to replace the occurrence with NEWSTRING. This preserves case,
+ just like `replace-string', provided `case-replace' is non-`nil',
+ as it normally is.
+
+`DEL'
+ to skip to the next occurrence without replacing this one.
+
+`, (Comma)'
+ to replace this occurrence and display the result. You are then
+ asked for another input character, except that since the
+ replacement has already been made, DEL and SPC are equivalent.
+ You could type `C-r' at this point (see below) to alter the
+ replaced text. You could also type `C-x u' to undo the
+ replacement; this exits the `query-replace', so if you want to do
+ further replacement you must use `C-x ESC' to restart (*note
+ Repetition::.).
+
+`ESC'
+ to exit without doing any more replacements.
+
+`. (Period)'
+ to replace this occurrence and then exit.
+
+`!'
+ to replace all remaining occurrences without asking again.
+
+`^'
+ to go back to the location of the previous occurrence (or what
+ used to be an occurrence), in case you changed it by mistake.
+ This works by popping the mark ring. Only one `^' in a row is
+ allowed, because only one previous replacement location is kept
+ during `query-replace'.
+
+`C-r'
+ to enter a recursive editing level, in case the occurrence needs
+ to be edited rather than just replaced with NEWSTRING. When you
+ are done, exit the recursive editing level with `C-M-c' and the
+ next occurrence will be displayed. *Note Recursive Edit::.
+
+`C-w'
+ to delete the occurrence, and then enter a recursive editing level
+ as in `C-r'. Use the recursive edit to insert text to replace the
+ deleted occurrence of STRING. When done, exit the recursive
+ editing level with `C-M-c' and the next occurrence will be
+ displayed.
+
+`C-l'
+ to redisplay the screen and then give another answer.
+
+`C-h'
+ to display a message summarizing these options, then give another
+ answer.
+
+ If you type any other character, the `query-replace' is exited, and
+the character executed as a command. To restart the `query-replace',
+use `C-x ESC', which repeats the `query-replace' because it used the
+minibuffer to read its arguments. *Note C-x ESC: Repetition.
+
+ To replace every occurrence, you can start `query-replace' at the
+beginning of the buffer and type `!', or you can use the
+`replace-string' command at the beginning of the buffer. To replace
+every occurrence in a part of the buffer, narrow to that part and then
+run `replace-string' or `query-replace' at the beginning of it. *Note
+Narrowing::.
+
+
+File: emacs, Node: Other Repeating Search, Prev: Replace, Up: Search
+
+Other Search-and-Loop Commands
+==============================
+
+ Here are some other commands that find matches for a regular
+expression. They all operate from point to the end of the buffer.
+
+`M-x occur'
+ Print each line that follows point and contains a match for the
+ specified regexp. A numeric argument specifies the number of
+ context lines to print before and after each matching line; the
+ default is none.
+
+ The buffer `*Occur*' containing the output serves as a menu for
+ finding the occurrences in their original context. Find an
+ occurrence as listed in `*Occur*', position point there and type
+ `C-c C-c'; this switches to the buffer that was searched and moves
+ point to the original of the same occurrence.
+
+`M-x list-matching-lines'
+ Synonym for `M-x occur'.
+
+`M-x count-matches'
+ Print the number of matches following point for the specified
+ regexp.
+
+`M-x delete-non-matching-lines'
+ Delete each line that follows point and does not contain a match
+ for the specified regexp.
+
+`M-x delete-matching-lines'
+ Delete each line that follows point and contains a match for the
+ specified regexp.
+
+
+File: emacs, Node: Fixit, Next: Files, Prev: Search, Up: Top
+
+Commands for Fixing Typos
+*************************
+
+ In this chapter we describe the commands that are especially useful
+for the times when you catch a mistake in your text just after you have
+made it, or change your mind while composing text on line.
+
+* Menu:
+
+* Kill Errors:: Commands to kill a batch of recently entered text.
+* Transpose:: Exchanging two characters, words, lines, lists...
+* Fixing Case:: Correcting case of last word entered.
+* Spelling:: Apply spelling checker to a word, or a whole file.
+
+
+File: emacs, Node: Kill Errors, Next: Transpose, Prev: Fixit, Up: Fixit
+
+Killing Your Mistakes
+=====================
+
+`DEL'
+ Delete last character (`delete-backward-char').
+
+`M-DEL'
+ Kill last word (`backward-kill-word').
+
+`C-x DEL'
+ Kill to beginning of sentence (`backward-kill-sentence').
+
+ The DEL character (`delete-backward-char') is the most important
+correction command. When used among graphic (self-inserting)
+characters, it can be thought of as canceling the last character typed.
+
+ When your mistake is longer than a couple of characters, it might be
+more convenient to use `M-DEL' or `C-x DEL'. `M-DEL' kills back to the
+start of the last word, and `C-x DEL' kills back to the start of the
+last sentence. `C-x DEL' is particularly useful when you are thinking
+of what to write as you type it, in case you change your mind about
+phrasing. `M-DEL' and `C-x DEL' save the killed text for `C-y' and
+`M-y' to retrieve. *Note Yanking::.
+
+ `M-DEL' is often useful even when you have typed only a few
+characters wrong, if you know you are confused in your typing and aren't
+sure exactly what you typed. At such a time, you cannot correct with
+DEL except by looking at the screen to see what you did. It requires
+less thought to kill the whole word and start over again.
+
+
+File: emacs, Node: Transpose, Next: Fixing Case, Prev: Kill Errors, Up: Fixit
+
+Transposing Text
+================
+
+`C-t'
+ Transpose two characters (`transpose-chars').
+
+`M-t'
+ Transpose two words (`transpose-words').
+
+`C-M-t'
+ Transpose two balanced expressions (`transpose-sexps').
+
+`C-x C-t'
+ Transpose two lines (`transpose-lines').
+
+ The common error of transposing two characters can be fixed, when
+they are adjacent, with the `C-t' command (`transpose-chars').
+Normally, `C-t' transposes the two characters on either side of point.
+When given at the end of a line, rather than transposing the last
+character of the line with the newline, which would be useless, `C-t'
+transposes the last two characters on the line. So, if you catch your
+transposition error right away, you can fix it with just a `C-t'. If
+you don't catch it so fast, you must move the cursor back to between
+the two transposed characters. If you transposed a space with the last
+character of the word before it, the word motion commands are a good
+way of getting there. Otherwise, a reverse search (`C-r') is often the
+best way. *Note Search::.
+
+ `Meta-t' (`transpose-words') transposes the word before point with
+the word after point. It moves point forward over a word, dragging the
+word preceding or containing point forward as well. The punctuation
+characters between the words do not move. For example, `FOO, BAR'
+transposes into `BAR, FOO' rather than `BAR FOO,'.
+
+ `C-M-t' (`transpose-sexps') is a similar command for transposing two
+expressions (*note Lists::.), and `C-x C-t' (`transpose-lines')
+exchanges lines. They work like `M-t' except in determining the
+division of the text into syntactic units.
+
+ A numeric argument to a transpose command serves as a repeat count:
+it tells the transpose command to move the character (word, sexp, line)
+before or containing point across several other characters (words,
+sexps, lines). For example, `C-u 3 C-t' moves the character before
+point forward across three other characters. This is equivalent to
+repeating `C-t' three times. `C-u - 4 M-t' moves the word before point
+backward across four words. `C-u - C-M-t' would cancel the effect of
+plain `C-M-t'.
+
+ A numeric argument of zero is assigned a special meaning (because
+otherwise a command with a repeat count of zero would do nothing): to
+transpose the character (word, sexp, line) ending after point with the
+one ending after the mark.
+
+
+File: emacs, Node: Fixing Case, Next: Spelling, Prev: Transpose, Up: Fixit
+
+Case Conversion
+===============
+
+`M-- M-l'
+ Convert last word to lower case. Note `Meta--' is Meta-minus.
+
+`M-- M-u'
+ Convert last word to all upper case.
+
+`M-- M-c'
+ Convert last word to lower case with capital initial.
+
+ A very common error is to type words in the wrong case. Because of
+this, the word case-conversion commands `M-l', `M-u' and `M-c' have a
+special feature when used with a negative argument: they do not move the
+cursor. As soon as you see you have mistyped the last word, you can
+simply case-convert it and go on typing. *Note Case::.
+
+
+File: emacs, Node: Spelling, Prev: Fixing Case, Up: Fixit
+
+Checking and Correcting Spelling
+================================
+
+`M-$'
+ Check and correct spelling of word (`spell-word').
+
+`M-x spell-buffer'
+ Check and correct spelling of each word in the buffer.
+
+`M-x spell-region'
+ Check and correct spelling of each word in the region.
+
+`M-x spell-string'
+ Check spelling of specified word.
+
+ To check the spelling of the word before point, and optionally
+correct it as well, use the command `M-$' (`spell-word'). This command
+runs an inferior process containing the `spell' program to see whether
+the word is correct English. If it is not, it asks you to edit the
+word (in the minibuffer) into a corrected spelling, and then does a
+`query-replace' to substitute the corrected spelling for the old one
+throughout the buffer.
+
+ If you exit the minibuffer without altering the original spelling, it
+means you do not want to do anything to that word. Then the
+`query-replace' is not done.
+
+ `M-x spell-buffer' checks each word in the buffer the same way that
+`spell-word' does, doing a `query-replace' if appropriate for every
+incorrect word.
+
+ `M-x spell-region' is similar but operates only on the region, not
+the entire buffer.
+
+ `M-x spell-string' reads a string as an argument and checks whether
+that is a correctly spelled English word. It prints in the echo area a
+message giving the answer.
+
+
+File: emacs, Node: Files, Next: Buffers, Prev: Fixit, Up: Top
+
+File Handling
+*************
+
+ The basic unit of stored data in Unix is the "file". To edit a file,
+you must tell Emacs to examine the file and prepare a buffer containing
+a copy of the file's text. This is called "visiting" the file. Editing
+commands apply directly to text in the buffer; that is, to the copy
+inside Emacs. Your changes appear in the file itself only when you
+"save" the buffer back into the file.
+
+ In addition to visiting and saving files, Emacs can delete, copy,
+rename, and append to files, and operate on file directories.
+
+* Menu:
+
+* File Names:: How to type and edit file name arguments.
+* Visiting:: Visiting a file prepares Emacs to edit the file.
+* Saving:: Saving makes your changes permanent.
+* Reverting:: Reverting cancels all the changes not saved.
+* Auto Save:: Auto Save periodically protects against loss of data.
+* ListDir:: Listing the contents of a file directory.
+* Dired:: "Editing" a directory to delete, rename, etc.
+ the files in it.
+* Misc File Ops:: Other things you can do on files.
+
+ \ No newline at end of file
diff --git a/info/emacs-5 b/info/emacs-5
new file mode 100644
index 00000000000..31efa6c1c80
--- /dev/null
+++ b/info/emacs-5
@@ -0,0 +1,1123 @@
+This is Info file ../info/emacs, produced by Makeinfo-1.49 from the
+input file emacs.texi.
+
+ This file documents the GNU Emacs editor.
+
+ Copyright (C) 1985, 1986, 1988, 1992 Richard M. Stallman.
+
+ Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+ Permission is granted to copy and distribute modified versions of
+this manual under the conditions for verbatim copying, provided also
+that the sections entitled "The GNU Manifesto", "Distribution" and "GNU
+General Public License" are included exactly as in the original, and
+provided that the entire resulting derived work is distributed under the
+terms of a permission notice identical to this one.
+
+ Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that the sections entitled "The GNU Manifesto",
+"Distribution" and "GNU General Public License" may be included in a
+translation approved by the author instead of in the original English.
+
+
+File: emacs, Node: File Names, Next: Visiting, Prev: Files, Up: Files
+
+File Names
+==========
+
+ Most Emacs commands that operate on a file require you to specify the
+file name. (Saving and reverting are exceptions; the buffer knows which
+file name to use for them.) File names are specified using the
+minibuffer (*note Minibuffer::.). "Completion" is available, to make
+it easier to specify long file names. *Note Completion::.
+
+ There is always a "default file name" which will be used if you type
+just RET, entering an empty argument. Normally the default file name
+is the name of the file visited in the current buffer; this makes it
+easy to operate on that file with any of the Emacs file commands.
+
+ Each buffer has a default directory, normally the same as the
+directory of the file visited in that buffer. When Emacs reads a file
+name, if you do not specify a directory, the default directory is used.
+ If you specify a directory in a relative fashion, with a name that
+does not start with a slash, it is interpreted with respect to the
+default directory. The default directory is kept in the variable
+`default-directory', which has a separate value in every buffer.
+
+ For example, if the default file name is `/u/rms/gnu/gnu.tasks' then
+the default directory is `/u/rms/gnu/'. If you type just `foo', which
+does not specify a directory, it is short for `/u/rms/gnu/foo'.
+`../.login' would stand for `/u/rms/.login'. `new/foo' would stand for
+the filename `/u/rms/gnu/new/foo'.
+
+ The command `M-x pwd' prints the current buffer's default directory,
+and the command `M-x cd' sets it (to a value read using the
+minibuffer). A buffer's default directory changes only when the `cd'
+command is used. A file-visiting buffer's default directory is
+initialized to the directory of the file that is visited there. If a
+buffer is made randomly with `C-x b', its default directory is copied
+from that of the buffer that was current at the time.
+
+ The default directory actually appears in the minibuffer when the
+minibuffer becomes active to read a file name. This serves two
+purposes: it shows you what the default is, so that you can type a
+relative file name and know with certainty what it will mean, and it
+allows you to edit the default to specify a different directory. This
+insertion of the default directory is inhibited if the variable
+`insert-default-directory' is set to `nil'.
+
+ Note that it is legitimate to type an absolute file name after you
+enter the minibuffer, ignoring the presence of the default directory
+name as part of the text. The final minibuffer contents may look
+invalid, but that is not so. *Note Minibuffer File::.
+
+ `$' in a file name is used to substitute environment variables. For
+example, if you have used the C shell command `setenv FOO rms/hacks' to
+set up an environment variable named `FOO', then you can use
+`/u/$FOO/test.c' or `/u/${FOO}/test.c' as an abbreviation for
+`/u/rms/hacks/test.c'. (In the Bourne-Again shell, write `export
+FOO=rms/hacks' to define `FOO'.) The environment variable name
+consists of all the alphanumeric characters after the `$';
+alternatively, it may be enclosed in braces after the `$'. Note that
+the `setenv' command affects Emacs only if done before Emacs is started.
+
+ To access a file with `$' in its name, type `$$'. This pair is
+converted to a single `$' at the same time as variable substitution is
+performed for single `$'. The Lisp function that performs the
+substitution is called `substitute-in-file-name'. The substitution is
+performed only on filenames read as such using the minibuffer.
+
+
+File: emacs, Node: Visiting, Next: Saving, Prev: File Names, Up: Files
+
+Visiting Files
+==============
+
+`C-x C-f'
+ Visit a file (`find-file').
+
+`C-x C-v'
+ Visit a different file instead of the one visited last
+ (`find-alternate-file').
+
+`C-x 4 C-f'
+ Visit a file, in another window (`find-file-other-window'). Don't
+ change this window.
+
+ "Visiting" a file means copying its contents into Emacs where you can
+edit them. Emacs makes a new buffer for each file that you visit. We
+say that the buffer is visiting the file that it was created to hold.
+Emacs constructs the buffer name from the file name by throwing away the
+directory, keeping just the name proper. For example, a file named
+`/usr/rms/emacs.tex' would get a buffer named `emacs.tex'. If there is
+already a buffer with that name, a unique name is constructed by
+appending `<2>', `<3>', or so on, using the lowest number that makes a
+name that is not already in use.
+
+ Each window's mode line shows the name of the buffer that is being
+displayed in that window, so you can always tell what buffer you are
+editing.
+
+ The changes you make with Emacs are made in the Emacs buffer. They
+do not take effect in the file that you visited, or any place
+permanent, until you "save" the buffer. Saving the buffer means that
+Emacs writes the current contents of the buffer into its visited file.
+*Note Saving::.
+
+ If a buffer contains changes that have not been saved, the buffer is
+said to be "modified". This is important because it implies that some
+changes will be lost if the buffer is not saved. The mode line displays
+two stars near the left margin if the buffer is modified.
+
+ To visit a file, use the command `C-x C-f' (`find-file'). Follow
+the command with the name of the file you wish to visit, terminated by a
+RET.
+
+ The file name is read using the minibuffer (*note Minibuffer::.),
+with defaulting and completion in the standard manner (*note File
+Names::.). While in the minibuffer, you can abort `C-x C-f' by typing
+`C-g'.
+
+ Your confirmation that `C-x C-f' has completed successfully is the
+appearance of new text on the screen and a new buffer name in the mode
+line. If the specified file does not exist and could not be created, or
+cannot be read, then an error results. The error message is printed in
+the echo area, and includes the file name which Emacs was trying to
+visit.
+
+ If you visit a file that is already in Emacs, `C-x C-f' does not make
+another copy. It selects the existing buffer containing that file.
+However, before doing so, it checks that the file itself has not changed
+since you visited or saved it last. If the file has changed, a warning
+message is printed. *Note Simultaneous Editing: Interlocking.
+
+ What if you want to create a file? Just visit it. Emacs prints
+`(New File)' in the echo area, but in other respects behaves as if you
+had visited an existing empty file. If you make any changes and save
+them, the file is created.
+
+ If you visit a nonexistent file unintentionally (because you typed
+the wrong file name), use the `C-x C-v' (`find-alternate-file') command
+to visit the file you wanted. `C-x C-v' is similar to `C-x C-f', but
+it kills the current buffer (after first offering to save it if it is
+modified). `C-x C-v' is allowed even if the current buffer is not
+visiting a file.
+
+ If the file you specify is actually a directory, Dired is called on
+that directory (*note Dired::.). This can be inhibited by setting the
+variable `find-file-run-dired' to `nil'; then it is an error to try to
+visit a directory.
+
+ `C-x 4 f' (`find-file-other-window') is like `C-x C-f' except that
+the buffer containing the specified file is selected in another window.
+ The window that was selected before `C-x 4 f' continues to show the
+same buffer it was already showing. If this command is used when only
+one window is being displayed, that window is split in two, with one
+window showing the same before as before, and the other one showing the
+newly requested file. *Note Windows::.
+
+ There are two hook variables that allow extensions to modify the
+operation of visiting files. Visiting a file that does not exist runs
+the functions in the list `find-file-not-found-hooks'; the value of this
+variable is expected to be a list of functions, and the functions are
+called one by one until one of them returns non-`nil'. Any visiting of
+a file, whether extant or not, expects `find-file-hooks' to contain a
+list of functions and calls them all, one by one. In both cases the
+functions receive no arguments. Visiting a nonexistent file runs the
+`find-file-not-found-hooks' first.
+
+ You can put a local variable specification at the end of a file which
+specifies values for Emacs local variables whenever you visit the file.
+*Note File Variables::.
+
+
+File: emacs, Node: Saving, Next: Reverting, Prev: Visiting, Up: Files
+
+Saving Files
+============
+
+ "Saving" a buffer in Emacs means writing its contents back into the
+file that was visited in the buffer.
+
+`C-x C-s'
+ Save the current buffer in its visited file (`save-buffer').
+
+`C-x s'
+ Save any or all buffers in their visited files
+ (`save-some-buffers').
+
+`M-~'
+ Forget that the current buffer has been changed
+ (`not-modified').
+
+`C-x C-w'
+ Save the current buffer in a specified file, and record that file
+ as the one visited in the buffer (`write-file').
+
+`M-x set-visited-file-name'
+ Change file the name under which the current buffer will be saved.
+
+ When you wish to save the file and make your changes permanent, type
+`C-x C-s' (`save-buffer'). After saving is finished, `C-x C-s' prints
+a message such as
+
+ Wrote /u/rms/gnu/gnu.tasks
+
+If the selected buffer is not modified (no changes have been made in it
+since the buffer was created or last saved), saving is not really done,
+because it would have no effect. Instead, `C-x C-s' prints a message
+in the echo area saying
+
+ (No changes need to be written)
+
+ The command `C-x s' (`save-some-buffers') can save any or all
+modified buffers. First it asks, for each modified buffer, whether to
+save it. These questions should be answered with `y' or `n'. `C-x C-c',
+the key that kills Emacs, invokes `save-some-buffers' and therefore
+asks the same questions.
+
+ If you have changed a buffer and do not want the changes to be
+saved, you should take some action to prevent it. Otherwise, each time
+you use `save-some-buffers' you are liable to save it by mistake. One
+thing you can do is type `M-~' (`not-modified'), which clears out the
+indication that the buffer is modified. If you do this, none of the
+save commands will believe that the buffer needs to be saved. (`~' is
+often used as a mathematical symbol for `not'; thus `Meta-~' is `not',
+metafied.) You could also use `set-visited-file-name' (see below) to
+mark the buffer as visiting a different file name, one which is not in
+use for anything important. Alternatively, you can undo all the
+changes made since the file was visited or saved, by reading the text
+from the file again. This is called "reverting". *Note Reverting::.
+You could also undo all the changes by repeating the undo command `C-x
+u' until you have undone all the changes; but this only works if you
+have not made more changes than the undo mechanism can remember.
+
+ `M-x set-visited-file-name' alters the name of the file that the
+current buffer is visiting. It reads the new file name using the
+minibuffer. It can be used on a buffer that is not visiting a file,
+too. The buffer's name is changed to correspond to the file it is now
+visiting in the usual fashion (unless the new name is in use already
+for some other buffer; in that case, the buffer name is not changed).
+`set-visited-file-name' does not save the buffer in the newly visited
+file; it just alters the records inside Emacs so that, if you save the
+buffer, it will be saved in that file. It also marks the buffer as
+"modified" so that `C-x C-s' will save.
+
+ If you wish to mark the buffer as visiting a different file and save
+it right away, use `C-x C-w' (`write-file'). It is precisely
+equivalent to `set-visited-file-name' followed by `C-x C-s'. `C-x C-s'
+used on a buffer that is not visiting with a file has the same effect
+as `C-x C-w'; that is, it reads a file name, marks the buffer as
+visiting that file, and saves it there. The default file name in a
+buffer that is not visiting a file is made by combining the buffer name
+with the buffer's default directory.
+
+ If Emacs is about to save a file and sees that the date of the latest
+version on disk does not match what Emacs last read or wrote, Emacs
+notifies you of this fact, because it probably indicates a problem
+caused by simultaneous editing and requires your immediate attention.
+*Note Simultaneous Editing: Interlocking.
+
+ If the variable `require-final-newline' is non-`nil', Emacs puts a
+newline at the end of any file that doesn't already end in one, every
+time a file is saved or written.
+
+ You can implement other ways to write files, and other things to be
+done before writing them, using the hook variable `write-file-hooks'.
+The value of this variable should be a list of Lisp functions. When a
+file is to be written, the functions in the list are called, one by
+one, with no arguments. If one of them returns a non-`nil' value,
+Emacs takes this to mean that the file has been written in some
+suitable fashion; the rest of the functions are not called, and normal
+writing is not done.
+
+* Menu:
+
+* Backup:: How Emacs saves the old version of your file.
+* Interlocking:: How Emacs protects against simultaneous editing
+ of one file by two users.
+
+
+File: emacs, Node: Backup, Next: Interlocking, Prev: Saving, Up: Saving
+
+Backup Files
+------------
+
+ Because Unix does not provide version numbers in file names,
+rewriting a file in Unix automatically destroys all record of what the
+file used to contain. Thus, saving a file from Emacs throws away the
+old contents of the file--or it would, except that Emacs carefully
+copies the old contents to another file, called the "backup" file,
+before actually saving (provided the variable `make-backup-files' is
+non-`nil'; backup files are not written if this variable is `nil').
+
+ At your option, Emacs can keep either a single backup file or a
+series of numbered backup files for each file that you edit.
+
+ Emacs makes a backup for a file only the first time the file is saved
+from one buffer. No matter how many times you save a file, its backup
+file continues to contain the contents from before the file was visited.
+Normally this means that the backup file contains the contents from
+before the current editing session; however, if you kill the buffer and
+then visit the file again, a new backup file will be made by the next
+save.
+
+* Menu:
+
+* Names: Backup Names. How backup files are named;
+ Choosing single or numbered backup files.
+* Deletion: Backup Deletion. Emacs deletes excess numbered backups.
+* Copying: Backup Copying. Backups can be made by copying or renaming.
+
+
+File: emacs, Node: Backup Names, Next: Backup Deletion, Prev: Backup, Up: Backup
+
+Single or Numbered Backups
+..........................
+
+ If you choose to have a single backup file (this is the default),
+the backup file's name is constructed by appending `~' to the file name
+being edited; thus, the backup file for `eval.c' would be `eval.c~'.
+
+ If you choose to have a series of numbered backup files, backup file
+names are made by appending `.~', the number, and another `~' to the
+original file name. Thus, the backup files of `eval.c' would be called
+`eval.c.~1~', `eval.c.~2~', and so on, through names like
+`eval.c.~259~' and beyond.
+
+ If protection stops you from writing backup files under the usual
+names, the backup file is written as `%backup%~' in your home directory.
+Only one such file can exist, so only the most recently made such
+backup is available.
+
+ The choice of single backup or numbered backups is controlled by the
+variable `version-control'. Its possible values are
+
+`t'
+ Make numbered backups.
+
+`nil'
+ Make numbered backups for files that have numbered backups already.
+ Otherwise, make single backups.
+
+`never'
+ Do not in any case make numbered backups; always make single
+ backups.
+
+`version-control' may be set locally in an individual buffer to control
+the making of backups for that buffer's file. For example, Rmail mode
+locally sets `version-control' to `never' to make sure that there is
+only one backup for an Rmail file. *Note Locals::.
+
+
+File: emacs, Node: Backup Deletion, Next: Backup Copying, Prev: Backup Names, Up: Backup
+
+Automatic Deletion of Backups
+.............................
+
+ To prevent unlimited consumption of disk space, Emacs can delete
+numbered backup versions automatically. Generally Emacs keeps the
+first few backups and the latest few backups, deleting any in between.
+This happens every time a new backup is made. The two variables that
+control the deletion are `kept-old-versions' and `kept-new-versions'.
+Their values are, respectively the number of oldest (lowest-numbered)
+backups to keep and the number of newest (highest-numbered) ones to
+keep, each time a new backup is made. Recall that these values are used
+just after a new backup version is made; that newly made backup is
+included in the count in `kept-new-versions'. By default, both
+variables are 2.
+
+ If `trim-versions-without-asking' is non-`nil', the excess middle
+versions are deleted without a murmur. If it is `nil', the default,
+then you are asked whether the excess middle versions should really be
+deleted.
+
+ Dired's `.' (Period) command can also be used to delete old versions.
+*Note Dired::.
+
+
+File: emacs, Node: Backup Copying, Prev: Backup Deletion, Up: Backup
+
+Copying vs. Renaming
+....................
+
+ Backup files can be made by copying the old file or by renaming it.
+This makes a difference when the old file has multiple names. If the
+old file is renamed into the backup file, then the alternate names
+become names for the backup file. If the old file is copied instead,
+then the alternate names remain names for the file that you are
+editing, and the contents accessed by those names will be the new
+contents.
+
+ The method of making a backup file may also affect the file's owner
+and group. If copying is used, these do not change. If renaming is
+used, you become the file's owner, and the file's group becomes the
+default (different operating systems have different defaults for the
+group).
+
+ Having the owner change is usually a good idea, because then the
+owner always shows who last edited the file. Also, the owners of the
+backups show who produced those versions. Occasionally there is a file
+whose owner should not change; it is a good idea for such files to
+contain local variable lists to set `backup-by-copying-when-mismatch'
+for them alone (*note File Variables::.).
+
+ The choice of renaming or copying is controlled by three variables.
+Normally, renaming is done. If the variable `backup-by-copying' is
+non-`nil', copying is used. Otherwise, if the variable
+`backup-by-copying-when-linked' is non-`nil', then copying is done for
+files that have multiple names, but renaming may still done when the
+file being edited has only one name. If the variable
+`backup-by-copying-when-mismatch' is non-`nil', then copying is done if
+renaming would cause the file's owner or group to change.
+
+
+File: emacs, Node: Interlocking, Prev: Backup, Up: Saving
+
+Protection against Simultaneous Editing
+---------------------------------------
+
+ Simultaneous editing occurs when two users visit the same file, both
+make changes, and then both save them. If nobody were informed that
+this was happening, whichever user saved first would later find that
+his changes were lost. On some systems, Emacs notices immediately when
+the second user starts to change the file, and issues an immediate
+warning. When this is not possible, or if the second user has gone on
+to change the file despite the warning, Emacs checks later when the
+file is saved, and issues a second warning when a user is about to
+overwrite a file containing another user's changes. If the editing
+user takes the proper corrective action at this point, he can prevent
+actual loss of work.
+
+ When you make the first modification in an Emacs buffer that is
+visiting a file, Emacs records that you have locked the file. (It does
+this by writing another file in a directory reserved for this purpose.)
+ The lock is removed when you save the changes. The idea is that the
+file is locked whenever the buffer is modified. If you begin to modify
+the buffer while the visited file is locked by someone else, this
+constitutes a collision, and Emacs asks you what to do. It does this
+by calling the Lisp function `ask-user-about-lock', which you can
+redefine for the sake of customization. The standard definition of
+this function asks you a question and accepts three possible answers:
+
+`s'
+ Steal the lock. Whoever was already changing the file loses the
+ lock, and you gain the lock.
+
+`p'
+ Proceed. Go ahead and edit the file despite its being locked by
+ someone else.
+
+`q'
+ Quit. This causes an error (`file-locked') and the modification
+ you were trying to make in the buffer does not actually take place.
+
+ Note that locking works on the basis of a file name; if a file has
+multiple names, Emacs does not realize that the two names are the same
+file and cannot prevent two user from editing it simultaneously under
+different names. However, basing locking on names means that Emacs can
+interlock the editing of new files that will not really exist until
+they are saved.
+
+ Some systems are not configured to allow Emacs to make locks. On
+these systems, Emacs cannot detect trouble in advance, but it still can
+detect it in time to prevent you from overwriting someone else's
+changes.
+
+ Every time Emacs saves a buffer, it first checks the
+last-modification date of the existing file on disk to see that it has
+not changed since the file was last visited or saved. If the date does
+not match, it implies that changes were made in the file in some other
+way, and these changes are about to be lost if Emacs actually does
+save. To prevent this, Emacs prints a warning message and asks for
+confirmation before saving. Occasionally you will know why the file was
+changed and know that it does not matter; then you can answer `yes' and
+proceed. Otherwise, you should cancel the save with `C-g' and
+investigate the situation.
+
+ The first thing you should do when notified that simultaneous
+editing has already taken place is to list the directory with `C-u C-x
+C-d' (*note Directory Listing: ListDir.). This will show the file's
+current author. You should attempt to contact that person to warn him
+or her not to continue editing. Often the next step is to save the
+contents of your Emacs buffer under a different name, and use `diff' to
+compare the two files.
+
+ Simultaneous editing checks are also made when you visit with `C-x
+C-f' a file that is already visited and when you start to modify a file.
+This is not strictly necessary, but it can cause you to find out about
+the problem earlier, when perhaps correction takes less work.
+
+
+File: emacs, Node: Reverting, Next: Auto Save, Prev: Saving, Up: Files
+
+Reverting a Buffer
+==================
+
+ If you have made extensive changes to a file and then change your
+mind about them, you can get rid of them by reading in the previous
+version of the file. To do this, use `M-x revert-buffer', which
+operates on the current buffer. Since this is a very dangerous thing
+to do, you must confirm it with `yes'.
+
+ If the current buffer has been auto-saved more recently than it has
+been saved for real, `revert-buffer' offers to read the auto save file
+instead of the visited file (*note Auto Save::.). This question comes
+before the usual request for confirmation, and demands `y' or `n' as an
+answer. If you have started to type `yes' for confirmation without
+realizing that the other question was going to be asked, the `y' will
+answer that question, but the `es' will not be valid confirmation. So
+you will have a chance to cancel the operation with `C-g' and try it
+again with the answers that you really intend.
+
+ `revert-buffer' keeps point at the same distance (measured in
+characters) from the beginning of the file. If the file was edited only
+slightly, you will be at approximately the same piece of text after
+reverting as before. If you have made drastic changes, the same value
+of point in the old file may address a totally different piece of text.
+
+ A buffer reverted from its visited file is marked "not modified"
+until another change is made.
+
+ Some kinds of buffers whose contents reflect data bases other than
+files, such as Dired buffers, can also be reverted. For them,
+reverting means recalculating their contents from the appropriate data
+base. Buffers created randomly with `C-x b' cannot be reverted;
+`revert-buffer' reports an error when asked to do so.
+
+
+File: emacs, Node: Auto Save, Next: ListDir, Prev: Reverting, Up: Files
+
+Auto-Saving: Protection Against Disasters
+=========================================
+
+ Emacs saves all the visited files from time to time (based on
+counting your keystrokes) without being asked. This is called
+"auto-saving". It prevents you from losing more than a limited amount
+of work if the system crashes.
+
+ When Emacs determines that it is time for auto-saving, each buffer is
+considered, and is auto-saved if auto-saving is turned on for it and it
+has been changed since the last time it was auto-saved. If any
+auto-saving is done, the message `Auto-saving...' is displayed in the
+echo area until auto-saving is finished. Errors occurring during
+auto-saving are caught so that they do not interfere with the execution
+of commands you have been typing.
+
+* Menu:
+
+* Files: Auto Save Files.
+* Control: Auto Save Control.
+* Recover:: Recovering text from auto-save files.
+
+
+File: emacs, Node: Auto Save Files, Next: Auto Save Control, Prev: Auto Save, Up: Auto Save
+
+Auto-Save Files
+---------------
+
+ Auto-saving does not normally save in the files that you visited,
+because it can be very undesirable to save a program that is in an
+inconsistent state when you have made half of a planned change.
+Instead, auto-saving is done in a different file called the "auto-save
+file", and the visited file is changed only when you request saving
+explicitly (such as with `C-x C-s').
+
+ Normally, the auto-save file name is made by appending `#' to the
+front and rear of the visited file name. Thus, a buffer visiting file
+`foo.c' would be auto-saved in a file `#foo.c#'. Most buffers that are
+not visiting files are auto-saved only if you request it explicitly;
+when they are auto-saved, the auto-save file name is made by appending
+`#%' to the front and `#' to the rear of buffer name. For example, the
+`*mail*' buffer in which you compose messages to be sent is auto-saved
+in a file named `#%*mail*#'. Auto-save file names are made this way
+unless you reprogram parts of Emacs to do something different (the
+functions `make-auto-save-file-name' and `auto-save-file-name-p'). The
+file name to be used for auto-saving in a buffer is calculated when
+auto-saving is turned on in that buffer.
+
+ If you want auto-saving to be done in the visited file, set the
+variable `auto-save-visited-file-name' to be non-`nil'. In this mode,
+there is really no difference between auto-saving and explicit saving.
+
+ A buffer's auto-save file is deleted when you save the buffer in its
+visited file. To inhibit this, set the variable
+`delete-auto-save-files' to `nil'. Changing the visited file name with
+`C-x C-w' or `set-visited-file-name' renames any auto-save file to go
+with the new visited name.
+
+
+File: emacs, Node: Auto Save Control, Next: Recover, Prev: Auto Save Files, Up: Auto Save
+
+Controlling Auto-Saving
+-----------------------
+
+ Each time you visit a file, auto-saving is turned on for that file's
+buffer if the variable `auto-save-default' is non-`nil' (but not in
+batch mode; *note Entering Emacs::.). The default for this variable is
+`t', so auto-saving is the usual practice for file-visiting buffers.
+Auto-saving can be turned on or off for any existing buffer with the
+command `M-x auto-save-mode'. Like other minor mode commands, `M-x
+auto-save-mode' turns auto-saving on with a positive argument, off with
+a zero or negative argument; with no argument, it toggles.
+
+ Emacs does auto-saving periodically based on counting how many
+characters you have typed since the last time auto-saving was done.
+The variable `auto-save-interval' specifies how many characters there
+are between auto-saves. By default, it is 300. Emacs also auto-saves
+whenever you call the function `do-auto-save'.
+
+ Emacs also does auto-saving whenever it gets a fatal error. This
+includes killing the Emacs job with a shell command such as `kill
+%emacs', or disconnecting a phone line or network connection.
+
+
+File: emacs, Node: Recover, Prev: Auto Save Control, Up: Auto Save
+
+Recovering Data from Auto-Saves
+-------------------------------
+
+ The way to use the contents of an auto-save file to recover from a
+loss of data is with the command `M-x recover-file RET FILE RET'. This
+visits FILE and then (after your confirmation) restores the contents
+from its auto-save file `#FILE#'. You can then save with `C-x C-s' to
+put the recovered text into FILE itself. For example, to recover file
+`foo.c' from its auto-save file `#foo.c#', do:
+
+ M-x recover-file RET foo.c RET
+ C-x C-s
+
+ Before asking for confirmation, `M-x recover-file' displays a
+directory listing describing the specified file and the auto-save file,
+so you can compare their sizes and dates. If the auto-save file is
+older, `M-x recover-file' does not offer to read it.
+
+ Auto-saving is disabled by `M-x recover-file' because using this
+command implies that the auto-save file contains valuable data from a
+past session. If you save the data in the visited file and then go on
+to make new changes, you should turn auto-saving back on with `M-x
+auto-save-mode'.
+
+
+File: emacs, Node: ListDir, Next: Dired, Prev: Auto Save, Up: Files
+
+Listing a File Directory
+========================
+
+ Files are classified by Unix into "directories". A "directory
+listing" is a list of all the files in a directory. Emacs provides
+directory listings in brief format (file names only) and verbose format
+(sizes, dates, and authors included).
+
+`C-x C-d DIR-OR-PATTERN'
+ Print a brief directory listing (`list-directory').
+
+`C-u C-x C-d DIR-OR-PATTERN'
+ Print a verbose directory listing.
+
+ The command to print a directory listing is `C-x C-d'
+(`list-directory'). It reads using the minibuffer a file name which is
+either a directory to be listed or a wildcard-containing pattern for
+the files to be listed. For example,
+
+ C-x C-d /u2/emacs/etc RET
+
+lists all the files in directory `/u2/emacs/etc'. An example of
+specifying a file name pattern is
+
+ C-x C-d /u2/emacs/src/*.c RET
+
+ Normally, `C-x C-d' prints a brief directory listing containing just
+file names. A numeric argument (regardless of value) tells it to print
+a verbose listing (like `ls -l').
+
+ The text of a directory listing is obtained by running `ls' in an
+inferior process. Two Emacs variables control the switches passed to
+`ls': `list-directory-brief-switches' is a string giving the switches
+to use in brief listings (`"-CF"' by default), and
+`list-directory-verbose-switches' is a string giving the switches to
+use in a verbose listing (`"-l"' by default).
+
+
+File: emacs, Node: Dired, Next: Misc File Ops, Prev: ListDir, Up: Files
+
+Dired, the Directory Editor
+===========================
+
+ Dired makes it easy to delete or visit many of the files in a single
+directory at once. It makes an Emacs buffer containing a listing of the
+directory. You can use the normal Emacs commands to move around in this
+buffer, and special Dired commands to operate on the files.
+
+* Menu:
+
+* Enter: Dired Enter. How to invoke Dired.
+* Edit: Dired Edit. Editing the Dired buffer.
+* Deletion: Dired Deletion. Deleting files with Dired.
+* Immed: Dired Immed. Other file operations through Dired.
+
+
+File: emacs, Node: Dired Enter, Next: Dired Edit, Prev: Dired, Up: Dired
+
+Entering Dired
+--------------
+
+ To invoke dired, do `C-x d' or `M-x dired'. The command reads a
+directory name or wildcard file name pattern as a minibuffer argument
+just like the `list-directory' command, `C-x C-d'. Where `dired'
+differs from `list-directory' is in naming the buffer after the
+directory name or the wildcard pattern used for the listing, and putting
+the buffer into Dired mode so that the special commands of Dired are
+available in it. The variable `dired-listing-switches' is a string
+used as an argument to `ls' in making the directory; this string must
+contain `-l'.
+
+ To display the Dired buffer in another window rather than in the
+selected window, use `C-x 4 d' (`dired-other-window)' instead of `C-x
+d'.
+
+
+File: emacs, Node: Dired Edit, Next: Dired Deletion, Prev: Dired Enter, Up: Dired
+
+Editing in Dired
+----------------
+
+ Once the Dired buffer exists, you can switch freely between it and
+other Emacs buffers. Whenever the Dired buffer is selected, certain
+special commands are provided that operate on files that are listed.
+The Dired buffer is "read-only", and inserting text in it is not
+useful, so ordinary printing characters such as `d' and `x' are used
+for Dired commands. Most Dired commands operate on the file described
+by the line that point is on. Some commands perform operations
+immediately; others "flag" the file to be operated on later.
+
+ Most Dired commands that operate on the current line's file also
+treat a numeric argument as a repeat count, meaning to act on the files
+of the next few lines. A negative argument means to operate on the
+files of the preceding lines, and leave point on the first of those
+lines.
+
+ All the usual Emacs cursor motion commands are available in Dired
+buffers. Some special purpose commands are also provided. The keys
+`C-n' and `C-p' are redefined so that they try to position the cursor
+at the beginning of the filename on the line, rather than at the
+beginning of the line.
+
+ For extra convenience, SPC and `n' in Dired are equivalent to `C-n'.
+ `p' is equivalent to `C-p'. Moving by lines is done so often in Dired
+that it deserves to be easy to type. DEL (move up and unflag) is often
+useful simply for moving up.
+
+ The `g' command in Dired runs `revert-buffer' to reinitialize the
+buffer from the actual disk directory and show any changes made in the
+directory by programs other than Dired. All deletion flags in the Dired
+buffer are lost when this is done.
+
+
+File: emacs, Node: Dired Deletion, Next: Dired Immed, Prev: Dired Edit, Up: Dired
+
+Deleting Files with Dired
+-------------------------
+
+ The primary use of Dired is to flag files for deletion and then
+delete them.
+
+`d'
+ Flag this file for deletion.
+
+`u'
+ Remove deletion-flag on this line.
+
+`DEL'
+ Remove deletion-flag on previous line, moving point to that line.
+
+`x'
+ Delete the files that are flagged for deletion.
+
+`#'
+ Flag all auto-save files (files whose names start and end with `#')
+ for deletion (*note Auto Save::.).
+
+`~'
+ Flag all backup files (files whose names end with `~') for deletion
+ (*note Backup::.).
+
+`. (Period)'
+ Flag excess numeric backup files for deletion. The oldest and
+ newest few backup files of any one file are exempt; the middle
+ ones are flagged.
+
+ You can flag a file for deletion by moving to the line describing the
+file and typing `d' or `C-d'. The deletion flag is visible as a `D' at
+the beginning of the line. Point is moved to the beginning of the next
+line, so that repeated `d' commands flag successive files.
+
+ The files are flagged for deletion rather than deleted immediately to
+avoid the danger of deleting a file accidentally. Until you direct
+Dired to delete the flagged files, you can remove deletion flags using
+the commands `u' and DEL. `u' works just like `d', but removes flags
+rather than making flags. DEL moves upward, removing flags; it is like
+`u' with numeric argument automatically negated.
+
+ To delete the flagged files, type `x'. This command first displays a
+list of all the file names flagged for deletion, and requests
+confirmation with `yes'. Once you confirm, all the flagged files are
+deleted, and their lines are deleted from the text of the Dired buffer.
+ The shortened Dired buffer remains selected. If you answer `no' or
+quit with `C-g', you return immediately to Dired, with the deletion
+flags still present and no files actually deleted.
+
+ The `#', `~' and `.' commands flag many files for deletion, based on
+their names. These commands are useful precisely because they do not
+actually delete any files; you can remove the deletion flags from any
+flagged files that you really wish to keep.
+
+ `#' flags for deletion all files that appear to have been made by
+auto-saving (that is, files whose names begin and end with `#'). `~'
+flags for deletion all files that appear to have been made as backups
+for files that were edited (that is, files whose names end with `~').
+
+ `.' (Period) flags just some of the backup files for deletion: only
+numeric backups that are not among the oldest few nor the newest few
+backups of any one file. Normally `dired-kept-versions' (not
+`kept-new-versions'; that applies only when saving) specifies the
+number of newest versions of each file to keep, and `kept-old-versions'
+specifies the number of oldest versions to keep. Period with a positive
+numeric argument, as in `C-u 3 .', specifies the number of newest
+versions to keep, overriding `dired-kept-versions'. A negative numeric
+argument overrides `kept-old-versions', using minus the value of the
+argument to specify the number of oldest versions of each file to keep.
+
+
+File: emacs, Node: Dired Immed, Prev: Dired Deletion, Up: Dired
+
+Immediate File Operations in Dired
+----------------------------------
+
+ Some file operations in Dired take place immediately when they are
+requested.
+
+`c'
+ Copies the file described on the current line. You must supply a
+ file name to copy to, using the minibuffer.
+
+`f'
+ Visits the file described on the current line. It is just like
+ typing `C-x C-f' and supplying that file name. If the file on
+ this line is a subdirectory, `f' actually causes Dired to be
+ invoked on that subdirectory. *Note Visiting::.
+
+`o'
+ Like `f', but uses another window to display the file's buffer.
+ The Dired buffer remains visible in the first window. This is
+ like using `C-x 4 C-f' to visit the file. *Note Windows::.
+
+`r'
+ Renames the file described on the current line. You must supply a
+ file name to rename to, using the minibuffer.
+
+`v'
+ Views the file described on this line using `M-x view-file'.
+ Viewing a file is like visiting it, but is slanted toward moving
+ around in the file conveniently and does not allow changing the
+ file. *Note View File: Misc File Ops. Viewing a file that is a
+ directory runs Dired on that directory.
+
+
+File: emacs, Node: Misc File Ops, Prev: Dired, Up: Files
+
+Miscellaneous File Operations
+=============================
+
+ Emacs has commands for performing many other operations on files.
+All operate on one file; they do not accept wild card file names.
+
+ `M-x view-file' allows you to scan or read a file by sequential
+screenfuls. It reads a file name argument using the minibuffer. After
+reading the file into an Emacs buffer, `view-file' reads and displays
+one windowful. You can then type SPC to scroll forward one windowful,
+or DEL to scroll backward. Various other commands are provided for
+moving around in the file, but none for changing it; type `C-h' while
+viewing for a list of them. They are mostly the same as normal Emacs
+cursor motion commands. To exit from viewing, type `C-c'.
+
+ `M-x insert-file' inserts a copy of the contents of the specified
+file into the current buffer at point, leaving point unchanged before
+the contents and the mark after them. *Note Mark::.
+
+ `M-x write-region' is the inverse of `M-x insert-file'; it copies
+the contents of the region into the specified file. `M-x
+append-to-file' adds the text of the region to the end of the specified
+file.
+
+ `M-x delete-file' deletes the specified file, like the `rm' command
+in the shell. If you are deleting many files in one directory, it may
+be more convenient to use Dired (*note Dired::.).
+
+ `M-x rename-file' reads two file names OLD and NEW using the
+minibuffer, then renames file OLD as NEW. If a file named NEW already
+exists, you must confirm with `yes' or renaming is not done; this is
+because renaming causes the old meaning of the name NEW to be lost. If
+OLD and NEW are on different file systems, the file OLD is copied and
+deleted.
+
+ The similar command `M-x add-name-to-file' is used to add an
+additional name to an existing file without removing its old name. The
+new name must belong on the same file system that the file is on.
+
+ `M-x copy-file' reads the file OLD and writes a new file named NEW
+with the same contents. Confirmation is required if a file named NEW
+already exists, because copying has the consequence of overwriting the
+old contents of the file NEW.
+
+ `M-x make-symbolic-link' reads two file names OLD and LINKNAME, and
+then creates a symbolic link named LINKNAME and pointing at OLD. The
+effect is that future attempts to open file LINKNAME will refer to
+whatever file is named OLD at the time the opening is done, or will get
+an error if the name OLD is not in use at that time. Confirmation is
+required when creating the link if LINKNAME is in use. Note that not
+all systems support symbolic links.
+
+
+File: emacs, Node: Buffers, Next: Windows, Prev: Files, Up: Top
+
+Using Multiple Buffers
+**********************
+
+ The text you are editing in Emacs resides in an object called a
+"buffer". Each time you visit a file, a buffer is created to hold the
+file's text. Each time you invoke Dired, a buffer is created to hold
+the directory listing. If you send a message with `C-x m', a buffer
+named `*mail*' is used to hold the text of the message. When you ask
+for a command's documentation, that appears in a buffer called `*Help*'.
+
+ At any time, one and only one buffer is "selected". It is also
+called the "current buffer". Often we say that a command operates on
+"the buffer" as if there were only one; but really this means that the
+command operates on the selected buffer (most commands do).
+
+ When Emacs makes multiple windows, each window has a chosen buffer
+which is displayed there, but at any time only one of the windows is
+selected and its chosen buffer is the selected buffer. Each window's
+mode line displays the name of the buffer that the window is displaying
+(*note Windows::.).
+
+ Each buffer has a name, which can be of any length, and you can
+select any buffer by giving its name. Most buffers are made by
+visiting files, and their names are derived from the files' names. But
+you can also create an empty buffer with any name you want. A newly
+started Emacs has a buffer named `*scratch*' which can be used for
+evaluating Lisp expressions in Emacs. The distinction between upper
+and lower case matters in buffer names.
+
+ Each buffer records individually what file it is visiting, whether
+it is modified, and what major mode and minor modes are in effect in it
+(*note Major Modes::.). Any Emacs variable can be made "local to" a
+particular buffer, meaning its value in that buffer can be different
+from the value in other buffers. *Note Locals::.
+
+* Menu:
+
+* Select Buffer:: Creating a new buffer or reselecting an old one.
+* List Buffers:: Getting a list of buffers that exist.
+* Misc Buffer:: Renaming; changing read-onliness; copying text.
+* Kill Buffer:: Killing buffers you no longer need.
+* Several Buffers:: How to go through the list of all buffers
+ and operate variously on several of them.
+
+
+File: emacs, Node: Select Buffer, Next: List Buffers, Prev: Buffers, Up: Buffers
+
+Creating and Selecting Buffers
+==============================
+
+`C-x b BUFFER RET'
+ Select or create a buffer named BUFFER (`switch-to-buffer').
+
+`C-x 4 b BUFFER RET'
+ Similar, but select a buffer named BUFFER in another window
+ (`switch-to-buffer-other-window').
+
+ To select the buffer named BUFNAME, type `C-x b BUFNAME RET'. This
+is the command `switch-to-buffer' with argument BUFNAME. You can use
+completion on an abbreviation for the buffer name you want (*note
+Completion::.). An empty argument to `C-x b' specifies the most
+recently selected buffer that is not displayed in any window.
+
+ Most buffers are created by visiting files, or by Emacs commands that
+want to display some text, but you can also create a buffer explicitly
+by typing `C-x b BUFNAME RET'. This makes a new, empty buffer which is
+not visiting any file, and selects it for editing. Such buffers are
+used for making notes to yourself. If you try to save one, you are
+asked for the file name to use. The new buffer's major mode is
+determined by the value of `default-major-mode' (*note Major Modes::.).
+
+ Note that `C-x C-f', and any other command for visiting a file, can
+also be used to switch buffers. *Note Visiting::.
+
+
+File: emacs, Node: List Buffers, Next: Misc Buffer, Prev: Select Buffer, Up: Buffers
+
+Listing Existing Buffers
+========================
+
+`C-x C-b'
+ List the existing buffers (`list-buffers').
+
+ To print a list of all the buffers that exist, type `C-x C-b'. Each
+line in the list shows one buffer's name, major mode and visited file.
+`*' at the beginning of a line indicates the buffer is "modified". If
+several buffers are modified, it may be time to save some with `C-x s'
+(*note Saving::.). `%' indicates a read-only buffer. `.' marks the
+selected buffer. Here is an example of a buffer list:
+
+ MR Buffer Size Mode File
+ -- ------ ---- ---- ----
+ .* emacs.tex 383402 Texinfo /u2/emacs/man/emacs.tex
+ *Help* 1287 Fundamental
+ files.el 23076 Emacs-Lisp /u2/emacs/lisp/files.el
+ % RMAIL 64042 RMAIL /u/rms/RMAIL
+ *% man 747 Dired
+ net.emacs 343885 Fundamental /u/rms/net.emacs
+ fileio.c 27691 C /u2/emacs/src/fileio.c
+ NEWS 67340 Text /u2/emacs/etc/NEWS
+ *scratch* 0 Lisp Interaction
+
+Note that the buffer `*Help*' was made by a help request; it is not
+visiting any file. The buffer `man' was made by Dired on the directory
+`/u2/emacs/man/'.
+
+
+File: emacs, Node: Misc Buffer, Next: Kill Buffer, Prev: List Buffers, Up: Buffers
+
+Miscellaneous Buffer Operations
+===============================
+
+`C-x C-q'
+ Toggle read-only status of buffer (`toggle-read-only').
+
+`M-x rename-buffer'
+ Change the name of the current buffer.
+
+`M-x view-buffer'
+ Scroll through a buffer.
+
+ A buffer can be "read-only", which means that commands to change its
+text are not allowed. Normally, read-only buffers are made by
+subsystems such as Dired and Rmail that have special commands to
+operate on the text; a read-only buffer is also made if you visit a
+file that is protected so you cannot write it. If you wish to make
+changes in a read-only buffer, use the command `C-x C-q'
+(`toggle-read-only'). It makes a read-only buffer writable, and makes
+a writable buffer read-only. This works by setting the variable
+`buffer-read-only', which has a local value in each buffer and makes
+the buffer read-only if its value is non-`nil'.
+
+ `M-x rename-buffer' changes the name of the current buffer. Specify
+the new name as a minibuffer argument. There is no default. If you
+specify a name that is in use for some other buffer, an error happens
+and no renaming is done.
+
+ `M-x view-buffer' is much like `M-x view-file' (*note Misc File
+Ops::.) except that it examines an already existing Emacs buffer. View
+mode provides commands for scrolling through the buffer conveniently
+but not for changing it. When you exit View mode, the value of point
+that resulted from your perusal remains in effect.
+
+ The commands `C-x a' (`append-to-buffer') and `M-x insert-buffer'
+can be used to copy text from one buffer to another. *Note Accumulating
+Text::.
+
+
+File: emacs, Node: Kill Buffer, Next: Several Buffers, Prev: Misc Buffer, Up: Buffers
+
+Killing Buffers
+===============
+
+ After you use Emacs for a while, you may accumulate a large number of
+buffers. You may then find it convenient to eliminate the ones you no
+longer need. There are several commands provided for doing this.
+
+`C-x k'
+ Kill a buffer, specified by name (`kill-buffer').
+
+`M-x kill-some-buffers'
+ Offer to kill each buffer, one by one.
+
+ `C-x k' (`kill-buffer') kills one buffer, whose name you specify in
+the minibuffer. The default, used if you type just RET in the
+minibuffer, is to kill the current buffer. If the current buffer is
+killed, another buffer is selected; a buffer that has been selected
+recently but does not appear in any window now is chosen to be selected.
+If the buffer being killed is modified (has unsaved editing) then you
+are asked to confirm with `yes' before the buffer is killed.
+
+ The command `M-x kill-some-buffers' asks about each buffer, one by
+one. An answer of `y' means to kill the buffer. Killing the current
+buffer or a buffer containing unsaved changes selects a new buffer or
+asks for confirmation just like `kill-buffer'.
+
+ \ No newline at end of file
diff --git a/info/emacs-6 b/info/emacs-6
new file mode 100644
index 00000000000..5ff39073c11
--- /dev/null
+++ b/info/emacs-6
@@ -0,0 +1,1204 @@
+This is Info file ../info/emacs, produced by Makeinfo-1.49 from the
+input file emacs.texi.
+
+ This file documents the GNU Emacs editor.
+
+ Copyright (C) 1985, 1986, 1988, 1992 Richard M. Stallman.
+
+ Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+ Permission is granted to copy and distribute modified versions of
+this manual under the conditions for verbatim copying, provided also
+that the sections entitled "The GNU Manifesto", "Distribution" and "GNU
+General Public License" are included exactly as in the original, and
+provided that the entire resulting derived work is distributed under the
+terms of a permission notice identical to this one.
+
+ Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that the sections entitled "The GNU Manifesto",
+"Distribution" and "GNU General Public License" may be included in a
+translation approved by the author instead of in the original English.
+
+
+File: emacs, Node: Several Buffers, Prev: Kill Buffer, Up: Buffers
+
+Operating on Several Buffers
+============================
+
+ The "buffer-menu" facility is like a "Dired for buffers"; it allows
+you to request operations on various Emacs buffers by editing an Emacs
+buffer containing a list of them. You can save buffers, kill them
+(here called "deleting" them, for consistency with Dired), or display
+them.
+
+`M-x buffer-menu'
+ Begin editing a buffer listing all Emacs buffers.
+
+ The command `buffer-menu' writes a list of all Emacs buffers into
+the buffer `*Buffer List*', and selects that buffer in Buffer Menu
+mode. The buffer is read-only, and can only be changed through the
+special commands described in this section. Most of these commands are
+graphic characters. The usual Emacs cursor motion commands can be used
+in the `*Buffer List*' buffer. The following special commands apply to
+the buffer described on the current line.
+
+`d'
+ Request to delete (kill) the buffer, then move down. The request
+ shows as a `D' on the line, before the buffer name. Requested
+ deletions take place when the `x' command is used.
+
+`k'
+ Synonym for `d'.
+
+`C-d'
+ Like `d' but move up afterwards instead of down.
+
+`s'
+ Request to save the buffer. The request shows as an `S' on the
+ line. Requested saves take place when the `x' command is used.
+ You may request both saving and deletion for the same buffer.
+
+`~'
+ Mark buffer "unmodified". The command `~' does this immediately
+ when typed.
+
+`x'
+ Perform previously requested deletions and saves.
+
+`u'
+ Remove any request made for the current line, and move down.
+
+`DEL'
+ Move to previous line and remove any request made for that line.
+
+ All the commands that put in or remove flags to request later
+operations also move down a line, and accept a numeric argument as a
+repeat count, unless otherwise specified.
+
+ There are also special commands to use the buffer list to select
+another buffer, and to specify one or more other buffers for display in
+additional windows.
+
+`1'
+ Select the buffer in a full-screen window. This command takes
+ effect immediately.
+
+`2'
+ Immediately set up two windows, with this buffer in one, and the
+ previously selected buffer (aside from the buffer `*Buffer List*')
+ in the other.
+
+`f'
+ Immediately select the buffer in place of the `*Buffer List*'
+ buffer.
+
+`o'
+ Immediately select the buffer in another window as if by `C-x 4 b',
+ leaving `*Buffer List*' visible.
+
+`q'
+ Immediately select this buffer, and also display in other windows
+ any buffers previously flagged with the `m' command. If there are
+ no such buffers, this command is equivalent to `1'.
+
+`m'
+ Flag this buffer to be displayed in another window if the `q'
+ command is used. The request shows as a `>' at the beginning of
+ the line. The same buffer may not have both a delete request and a
+ display request.
+
+ All that `buffer-menu' does directly is create and select a suitable
+buffer, and turn on Buffer Menu mode. Everything else described above
+is implemented by the special commands provided in Buffer Menu mode.
+One consequence of this is that you can switch from the `*Buffer List*'
+buffer to another Emacs buffer, and edit there. You can reselect the
+`buffer-menu' buffer later, to perform the operations already
+requested, or you can kill it, or pay no further attention to it.
+
+ The only difference between `buffer-menu' and `list-buffers' is that
+`buffer-menu' selects the `*Buffer List*' buffer and `list-buffers'
+does not. If you run `list-buffers' (that is, type `C-x C-b') and
+select the buffer list manually, you can use all of the commands
+described here.
+
+
+File: emacs, Node: Windows, Next: Major Modes, Prev: Buffers, Up: Top
+
+Multiple Windows
+****************
+
+ Emacs can split the screen into two or many windows, which can
+display parts of different buffers, or different parts of one buffer.
+
+* Menu:
+
+* Basic Window:: Introduction to Emacs windows.
+* Split Window:: New windows are made by splitting existing windows.
+* Other Window:: Moving to another window or doing something to it.
+* Pop Up Window:: Finding a file or buffer in another window.
+* Change Window:: Deleting windows and changing their sizes.
+
+
+File: emacs, Node: Basic Window, Next: Split Window, Prev: Windows, Up: Windows
+
+Concepts of Emacs Windows
+=========================
+
+ When multiple windows are being displayed, each window has an Emacs
+buffer designated for display in it. The same buffer may appear in more
+than one window; if it does, any changes in its text are displayed in
+all the windows where it appears. But the windows showing the same
+buffer can show different parts of it, because each window has its own
+value of point.
+
+ At any time, one of the windows is the "selected window"; the buffer
+this window is displaying is the current buffer. The terminal's cursor
+shows the location of point in this window. Each other window has a
+location of point as well, but since the terminal has only one cursor
+there is no way to show where those locations are.
+
+ Commands to move point affect the value of point for the selected
+Emacs window only. They do not change the value of point in any other
+Emacs window, even one showing the same buffer. The same is true for
+commands such as `C-x b' to change the selected buffer in the selected
+window; they do not affect other windows at all. However, there are
+other commands such as `C-x 4 b' that select a different window and
+switch buffers in it. Also, all commands that display information in a
+window, including (for example) `C-h f' (`describe-function') and `C-x
+C-b' (`list-buffers'), work by switching buffers in a nonselected window
+without affecting the selected window.
+
+ Each window has its own mode line, which displays the buffer name,
+modification status and major and minor modes of the buffer that is
+displayed in the window. *Note Mode Line::, for full details on the
+mode line.
+
+
+File: emacs, Node: Split Window, Next: Other Window, Prev: Basic Window, Up: Windows
+
+Splitting Windows
+=================
+
+`C-x 2'
+ Split the selected window into two windows, one above the other
+ (`split-window-vertically').
+
+`C-x 5'
+ Split the selected window into two windows positioned side by side
+ (`split-window-horizontally').
+
+ The command `C-x 2' (`split-window-vertically') breaks the selected
+window into two windows, one above the other. Both windows start out
+displaying the same buffer, with the same value of point. By default
+the two windows each get half the height of the window that was split; a
+numeric argument specifies how many lines to give to the top window.
+
+ `C-x 5' (`split-window-horizontally') breaks the selected window
+into two side-by-side windows. A numeric argument specifies how many
+columns to give the one on the left. A line of vertical bars separates
+the two windows. Windows that are not the full width of the screen
+have mode lines, but they are truncated; also, they do not always
+appear in inverse video, because, the Emacs display routines have not
+been taught how to display a region of inverse video that is only part
+of a line on the screen.
+
+ When a window is less than the full width, text lines too long to
+fit are frequent. Continuing all those lines might be confusing. The
+variable `truncate-partial-width-windows' can be set non-`nil' to force
+truncation in all windows less than the full width of the screen,
+independent of the buffer being displayed and its value for
+`truncate-lines'. *Note Continuation Lines::.
+
+ Horizontal scrolling is often used in side-by-side windows. *Note
+Display::.
+
+
+File: emacs, Node: Other Window, Next: Pop Up Window, Prev: Split Window, Up: Windows
+
+Using Other Windows
+===================
+
+`C-x o'
+ Select another window (`other-window'). That is `o', not zero.
+
+`C-M-v'
+ Scroll the next window (`scroll-other-window').
+
+`M-x compare-windows'
+ Find next place where the text in the selected window does not
+ match the text in the next window.
+
+ To select a different window, use `C-x o' (`other-window'). That is
+an `o', for `other', not a zero. When there are more than two windows,
+this command moves through all the windows in a cyclic order, generally
+top to bottom and left to right. From the rightmost and bottommost
+window, it goes back to the one at the upper left corner. A numeric
+argument means to move several steps in the cyclic order of windows. A
+negative argument moves around the cycle in the opposite order. When
+the minibuffer is active, the minibuffer is the last window in the
+cycle; you can switch from the minibuffer window to one of the other
+windows, and later switch back and finish supplying the minibuffer
+argument that is requested. *Note Minibuffer Edit::.
+
+ The usual scrolling commands (*note Display::.) apply to the selected
+window only, but there is one command to scroll the next window.
+`C-M-v' (`scroll-other-window') scrolls the window that `C-x o' would
+select. It takes arguments, positive and negative, like `C-v'.
+
+ The command `M-x compare-windows' compares the text in the current
+window with that in the next window. Comparison starts at point in each
+window. Point moves forward in each window, a character at a time in
+each window, until the next characters in the two windows are
+different. Then the command is finished.
+
+
+File: emacs, Node: Pop Up Window, Next: Change Window, Prev: Other Window, Up: Windows
+
+Displaying in Another Window
+============================
+
+ `C-x 4' is a prefix key for commands that select another window
+(splitting the window if there is only one) and select a buffer in that
+window. Different `C-x 4' commands have different ways of finding the
+buffer to select.
+
+`C-x 4 b BUFNAME RET'
+ Select buffer BUFNAME in another window. This runs
+ `switch-to-buffer-other-window'.
+
+`C-x 4 f FILENAME RET'
+ Visit file FILENAME and select its buffer in another window. This
+ runs `find-file-other-window'. *Note Visiting::.
+
+`C-x 4 d DIRECTORY RET'
+ Select a Dired buffer for directory DIRECTORY in another window.
+ This runs `dired-other-window'. *Note Dired::.
+
+`C-x 4 m'
+ Start composing a mail message in another window. This runs
+ `mail-other-window', and its same-window version is `C-x m' (*note
+ Sending Mail::.).
+
+`C-x 4 .'
+ Find a tag in the current tag table in another window. This runs
+ `find-tag-other-window', the multiple-window variant of `M-.'
+ (*note Tags::.).
+
+
+File: emacs, Node: Change Window, Prev: Pop Up Window, Up: Windows
+
+Deleting and Rearranging Windows
+================================
+
+`C-x 0'
+ Get rid of the selected window (`kill-window'). That is a zero.
+
+`C-x 1'
+ Get rid of all windows except the selected one
+ (`delete-other-windows').
+
+`C-x ^'
+ Make the selected window taller, at the expense of the other(s)
+ (`enlarge-window').
+
+`C-x }'
+ Widen the selected window (`enlarge-window-horizontally').
+
+ To delete a window, type `C-x 0' (`delete-window'). (That is a
+zero.) The space occupied by the deleted window is distributed among
+the other active windows (but not the minibuffer window, even if that
+is active at the time). Once a window is deleted, its attributes are
+forgotten; there is no automatic way to make another window of the same
+shape or showing the same buffer. But the buffer continues to exist,
+and you can select it in any window with `C-x b'.
+
+ `C-x 1' (`delete-other-windows') is more powerful than `C-x 0'; it
+deletes all the windows except the selected one (and the minibuffer);
+the selected window expands to use the whole screen except for the echo
+area.
+
+ To readjust the division of space among existing windows, use `C-x ^'
+(`enlarge-window'). It makes the currently selected window get one
+line bigger, or as many lines as is specified with a numeric argument.
+With a negative argument, it makes the selected window smaller. `C-x
+}' (`enlarge-window-horizontally') makes the selected window wider by
+the specified number of columns. The extra screen space given to a
+window comes from one of its neighbors, if that is possible; otherwise,
+all the competing windows are shrunk in the same proportion. If this
+makes any windows too small, those windows are deleted and their space
+is divided up. The minimum size is specified by the variables
+`window-min-height' and `window-min-width'.
+
+
+File: emacs, Node: Major Modes, Next: Indentation, Prev: Windows, Up: Top
+
+Major Modes
+***********
+
+ Emacs has many different "major modes", each of which customizes
+Emacs for editing text of a particular sort. The major modes are
+mutually exclusive, and each buffer has one major mode at any time.
+The mode line normally contains the name of the current major mode, in
+parentheses. *Note Mode Line::.
+
+ The least specialized major mode is called "Fundamental mode". This
+mode has no mode-specific redefinitions or variable settings, so that
+each Emacs command behaves in its most general manner, and each option
+is in its default state. For editing any specific type of text, such
+as Lisp code or English text, you should switch to the appropriate
+major mode, such as Lisp mode or Text mode.
+
+ Selecting a major mode changes the meanings of a few keys to become
+more specifically adapted to the language being edited. The ones which
+are changed frequently are TAB, DEL, and LFD. In addition, the
+commands which handle comments use the mode to determine how comments
+are to be delimited. Many major modes redefine the syntactical
+properties of characters appearing in the buffer. *Note 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 for specific
+purposes by Emacs, such as Dired mode for buffers made by Dired (*note
+Dired::.), and Mail mode for buffers made by `C-x m' (*note Sending
+Mail::.), and Shell mode for buffers used for communicating with an
+inferior shell process (*note Interactive Shell::.).
+
+ Most programming language major modes specify that only blank lines
+separate paragraphs. This is so that the paragraph commands remain
+useful. *Note Paragraphs::. They also cause Auto Fill mode to use the
+definition of TAB to indent the new lines it creates. This is because
+most lines in a program are usually indented. *Note Indentation::.
+
+* Menu:
+
+* Choosing Modes:: How major modes are specified or chosen.
+
+
+File: emacs, Node: Choosing Modes, Prev: Major Modes, Up: Major Modes
+
+How Major Modes are Chosen
+==========================
+
+ You can select a major mode explicitly for the current buffer, but
+most of the time Emacs determines which mode to use based on the file
+name or some text in the file.
+
+ Explicit selection of a new major mode is done with a `M-x' command.
+From the name of a major mode, add `-mode' to get the name of a command
+to select that mode. Thus, you can enter Lisp mode by executing `M-x
+lisp-mode'.
+
+ When you visit a file, Emacs usually chooses the right major mode
+based on the file's name. For example, files whose names end in `.c'
+are edited in C mode. The correspondence between file names and major
+mode is controlled by the variable `auto-mode-alist'. Its value is a
+list in which each element has the form
+
+ (REGEXP . MODE-FUNCTION)
+
+For example, one element normally found in the list has the form
+`("\\.c$" . c-mode)', and it is responsible for selecting C mode for
+files whose names end in `.c'. (Note that `\\' is needed in Lisp
+syntax to include a `\' in the string, which is needed to suppress the
+special meaning of `.' in regexps.) The only practical way to change
+this variable is with Lisp code.
+
+ You can specify which major mode should be used for editing a certain
+file by a special sort of text in the first nonblank line of the file.
+The mode name should appear in this line both preceded and followed by
+`-*-'. Other text may appear on the line as well. For example,
+
+ ;-*-Lisp-*-
+
+tells Emacs to use Lisp mode. Note how the semicolon is used to make
+Lisp treat this line as a comment. Such an explicit specification
+overrides any defaulting based on the file name.
+
+ Another format of mode specification is
+
+ -*-Mode: MODENAME;-*-
+
+which allows other things besides the major mode name to be specified.
+However, Emacs does not look for anything except the mode name.
+
+ The major mode can also be specified in a local variables list.
+*Note File Variables::.
+
+ When a file is visited that does not specify a major mode to use, or
+when a new buffer is created with `C-x b', the major mode used is that
+specified by the variable `default-major-mode'. Normally this value is
+the symbol `fundamental-mode', which specifies Fundamental mode. If
+`default-major-mode' is `nil', the major mode is taken from the
+previously selected buffer.
+
+ The command `M-x normal-mode' recalculates the major mode from the
+visited file name and the contents of the buffer.
+
+
+File: emacs, Node: Indentation, Next: Text, Prev: Major Modes, Up: Top
+
+Indentation
+***********
+
+`TAB'
+ Indent current line "appropriately" in a mode-dependent fashion.
+
+`LFD'
+ Perform RET followed by TAB (`newline-and-indent').
+
+`M-^'
+ Merge two lines (`delete-indentation'). This would cancel out the
+ effect of LFD.
+
+`C-M-o'
+ Split line at point; text on the line after point becomes a new
+ line indented to the same column that it now starts in
+ (`split-line').
+
+`M-m'
+ Move (forward or back) to the first nonblank character on the
+ current line (`back-to-indentation').
+
+`C-M-\'
+ Indent several lines to same column (`indent-region').
+
+`C-x TAB'
+ Shift block of lines rigidly right or left (`indent-rigidly').
+
+`M-i'
+ Indent from point to the next prespecified tab stop column
+ (`tab-to-tab-stop').
+
+`M-x indent-relative'
+ Indent from point to under an indentation point in the previous
+ line.
+
+ Most programming languages have some indentation convention. For
+Lisp code, lines are indented according to their nesting in
+parentheses. The same general idea is used for C code, though many
+details are different.
+
+ Whatever the language, to indent a line, use the TAB command. Each
+major mode defines this command to perform the sort of indentation
+appropriate for the particular language. In Lisp mode, TAB aligns the
+line according to its depth in parentheses. No matter where in the
+line you are when you type TAB, it aligns the line as a whole. In C
+mode, TAB implements a subtle and sophisticated indentation style that
+knows about many aspects of C syntax.
+
+ In Text mode, TAB runs the command `tab-to-tab-stop', which indents
+to the next tab stop column. You can set the tab stops with `M-x
+edit-tab-stops'.
+
+* Menu:
+
+* Indentation Commands:: Various commands and techniques for indentation.
+* Tab Stops:: You can set arbitrary "tab stops" and then
+ indent to the next tab stop when you want to.
+* Just Spaces:: You can request indentation using just spaces.
+
+
+File: emacs, Node: Indentation Commands, Next: Tab Stops, Prev: Indentation, Up: Indentation
+
+Indentation Commands and Techniques
+===================================
+
+ If you just want to insert a tab character in the buffer, you can
+type `C-q TAB'.
+
+ To move over the indentation on a line, type `Meta-m'. This command,
+given anywhere on a line, positions point at the first nonblank
+character on the line (`back-to-indentation').
+
+ To insert an indented line before the current line, do `C-a C-o
+TAB'. To make an indented line after the current line, use `C-e LFD'.
+
+ `C-M-o' (`split-line') moves the text from point to the end of the
+line vertically down, so that the current line becomes two lines.
+`C-M-o' first moves point forward over any spaces and tabs. Then it
+inserts after point a newline and enough indentation to reach the same
+column point is on. Point remains before the inserted newline; in this
+regard, `C-M-o' resembles `C-o'.
+
+ To join two lines cleanly, use the `Meta-^' (`delete-indentation')
+command to delete the indentation at the front of the current line, and
+the line boundary as well. They are replaced by a single space, or by
+no space if point after joining is at the beginning of a line or before
+a `)' or after a `('. To delete just the indentation of a line, go to
+the beginning of the line and use `Meta-\' (`delete-horizontal-space'),
+which deletes all spaces and tabs around the cursor.
+
+ There are also commands for changing the indentation of several
+lines at once. `Control-Meta-\' (`indent-region') gives each line which
+begins in the region the "usual" indentation by invoking TAB at the
+beginning of the line. A numeric argument specifies the column to
+indent to, and each line is shifted left or right so that its first
+nonblank character appears in that column. `C-x TAB'
+(`indent-rigidly') moves all of the lines in the region right by its
+argument (left, for negative arguments). The whole group of lines moves
+rigidly sideways, which is how the command gets its name.
+
+ `M-x indent-relative' indents at point based on the previous line
+(actually, the last nonempty line.) It inserts whitespace at point,
+moving point, until it is underneath an indentation point in the
+previous line. An indentation point is the end of a sequence of
+whitespace or the end of the line. If point is farther right than any
+indentation point in the previous line, the whitespace before point is
+deleted and the first indentation point then applicable is used. If no
+indentation point is applicable even then, `tab-to-tab-stop' is run
+(see next section).
+
+ `indent-relative' is the definition of TAB in Indented Text mode.
+*Note Text::.
+
+
+File: emacs, Node: Tab Stops, Next: Just Spaces, Prev: Indentation Commands, Up: Indentation
+
+Tab Stops
+=========
+
+ For typing in tables, you can use Text mode's definition of TAB,
+`tab-to-tab-stop'. This command inserts indentation before point,
+enough to reach the next tab stop column. If you are not in Text mode,
+this function can be found on `M-i' anyway.
+
+ The tab stops used by `M-i' can be set arbitrarily by the user. They
+are stored in a variable called `tab-stop-list', as a list of
+column-numbers in increasing order.
+
+ The convenient way to set the tab stops is using `M-x
+edit-tab-stops', which creates and selects a buffer containing a
+description of the tab stop settings. You can edit this buffer to
+specify different tab stops, and then type `C-c C-c' to make those new
+tab stops take effect. In the tab stop buffer, `C-c C-c' runs the
+function `edit-tab-stops-note-changes' rather than its usual definition
+`save-buffer'. `edit-tab-stops' records which buffer was current when
+you invoked it, and stores the tab stops back in that buffer; normally
+all buffers share the same tab stops and changing them in one buffer
+affects all, but if you happen to make `tab-stop-list' local in one
+buffer then `edit-tab-stops' in that buffer will edit the local
+settings.
+
+ Here is what the text representing the tab stops looks like for
+ordinary tab stops every eight columns.
+
+ : : : : : :
+ 0 1 2 3 4
+ 0123456789012345678901234567890123456789012345678
+ To install changes, type C-c C-c
+
+ The first line contains a colon at each tab stop. The remaining
+lines are present just to help you see where the colons are and know
+what to do.
+
+ Note that the tab stops that control `tab-to-tab-stop' have nothing
+to do with displaying tab characters in the buffer. *Note Display
+Vars::, for more information on that.
+
+
+File: emacs, Node: Just Spaces, Prev: Tab Stops, Up: Indentation
+
+Tabs vs. Spaces
+===============
+
+ Emacs normally uses both tabs and spaces to indent lines. If you
+prefer, all indentation can be made from spaces only. To request this,
+set `indent-tabs-mode' to `nil'. This is a per-buffer variable;
+altering the variable affects only the current buffer, but there is a
+default value which you can change as well. *Note Locals::.
+
+ There are also commands to convert tabs to spaces or vice versa,
+always preserving the columns of all nonblank text. `M-x tabify' scans
+the region for sequences of spaces, and converts sequences of at least
+three spaces to tabs if that can be done without changing indentation.
+`M-x untabify' changes all tabs in the region to appropriate numbers of
+spaces.
+
+
+File: emacs, Node: Text, Next: Programs, Prev: Indentation, Up: Top
+
+Commands for Human Languages
+****************************
+
+ The term "text" has two widespread meanings in our area of the
+computer field. One is data that is a sequence of characters. Any file
+that you edit with Emacs is text, in this sense of the word. The other
+meaning is more restrictive: a sequence of characters in a human
+language for humans to read (possibly after processing by a text
+formatter), as opposed to a program or commands for a program.
+
+ Human languages have syntactic/stylistic conventions that can be
+supported or used to advantage by editor commands: conventions involving
+words, sentences, paragraphs, and capital letters. This chapter
+describes Emacs commands for all of these things. There are also
+commands for "filling", or rearranging paragraphs into lines of
+approximately equal length. The commands for moving over and killing
+words, sentences and paragraphs, while intended primarily for editing
+text, are also often useful for editing programs.
+
+ Emacs has several major modes for editing human language text. If
+the file contains text pure and simple, use Text mode, which customizes
+Emacs in small ways for the syntactic conventions of text. For text
+which contains embedded commands for text formatters, Emacs has other
+major modes, each for a particular text formatter. Thus, for input to
+TeX, you would use TeX mode; for input to nroff, Nroff mode.
+
+* Menu:
+
+* Text Mode:: The major modes for editing text files.
+* Nroff Mode:: The major mode for editing input to the formatter nroff.
+* TeX Mode:: The major modes for editing input to the formatter TeX.
+* Outline Mode::The major mode for editing outlines.
+* Words:: Moving over and killing words.
+* Sentences:: Moving over and killing sentences.
+* Paragraphs:: Moving over paragraphs.
+* Pages:: Moving over pages.
+* Filling:: Filling or justifying text
+* Case:: Changing the case of text
+
+
+File: emacs, Node: Text Mode, Next: Words, Prev: Text, Up: Text
+
+Text Mode
+=========
+
+ Editing files of text in a human language ought to be done using Text
+mode rather than Lisp or Fundamental mode. Invoke `M-x text-mode' to
+enter Text mode. In Text mode, TAB runs the function
+`tab-to-tab-stop', which allows you to use arbitrary tab stops set with
+`M-x edit-tab-stops' (*note Tab Stops::.). Features concerned with
+comments in programs are turned off except when explicitly invoked. The
+syntax table is changed so that periods are not considered part of a
+word, while apostrophes, backspaces and underlines are.
+
+ A similar variant mode is Indented Text mode, intended for editing
+text in which most lines are indented. This mode defines TAB to run
+`indent-relative' (*note Indentation::.), and makes Auto Fill indent
+the lines it creates. The result is that normally a line made by Auto
+Filling, or by LFD, is indented just like the previous line. Use `M-x
+indented-text-mode' to select this mode.
+
+ Entering Text mode or Indented Text mode calls with no arguments the
+value of the variable `text-mode-hook', if that value exists and is not
+`nil'. This value is also called when modes related to Text mode are
+entered; this includes Nroff mode, TeX mode, Outline mode and Mail
+mode. Your hook can look at the value of `major-mode' to see which of
+these modes is actually being entered.
+
+* Menu:
+
+ Three modes similar to Text mode are of use for editing text that is to
+be passed through a text formatter before achieving the form in which
+humans are to read it.
+
+* Nroff Mode:: The nroff formatter typesets text.
+* TeX Mode:: The TeX formatter typesets text and mathematics.
+* Texinfo Mode::Texinfo provides both on-line information and printed output
+ from the same source file.
+
+ Another similar mode is used for editing outlines. It allows you
+to view the text at various levels of detail. You can view either
+the outline headings alone or both headings and text; you can also
+hide some of the headings at lower levels from view to make the high
+level structure more visible.
+
+* Outline Mode::The major mode for editing outlines.
+
+
+File: emacs, Node: Nroff Mode, Next: TeX Mode, Prev: Text Mode, Up: Text Mode
+
+Nroff Mode
+----------
+
+ Nroff mode is a mode like Text mode but modified to handle nroff
+commands present in the text. Invoke `M-x nroff-mode' to enter this
+mode. It differs from Text mode in only a few ways. All nroff command
+lines are considered paragraph separators, so that filling will never
+garble the nroff commands. Pages are separated by `.bp' commands.
+Comments start with backslash-doublequote. Also, three special
+commands are provided that are not in Text mode:
+
+`M-n'
+ Move to the beginning of the next line that isn't an nroff command
+ (`forward-text-line'). An argument is a repeat count.
+
+`M-p'
+ Like `M-n' but move up (`backward-text-line').
+
+`M-?'
+ Prints in the echo area the number of text lines (lines that are
+ not nroff commands) in the region (`count-text-lines').
+
+ The other feature of Nroff mode is Electric Nroff newline mode. This
+is a minor mode that you can turn on or off with `M-x
+electric-nroff-mode' (*note Minor Modes::.). When the mode is on, each
+time you use RET to end a line that contains an nroff command that
+opens a kind of grouping, it also inserts the matching nroff command to
+close that grouping, on the following line. For example, if you are at
+the beginning of a line and type `. ( b RET', this inserts the matching
+command `.)b' on a new line following point.
+
+ Entering Nroff mode calls with no arguments the value of the variable
+`text-mode-hook', if that value exists and is not `nil'; then it does
+the same with the variable `nroff-mode-hook'.
+
+
+File: emacs, Node: TeX Mode, Next: Texinfo Mode, Prev: Nroff Mode, Up: Text Mode
+
+TeX Mode
+--------
+
+ TeX is a powerful text formatter written by Donald Knuth; it is also
+free, like GNU Emacs. LaTeX is a simplified input format for TeX,
+implemented by TeX macros. It comes with TeX.
+
+ Emacs has a special TeX mode for editing TeX input files. It
+provides facilities for checking the balance of delimiters and for
+invoking TeX on all or part of the file.
+
+ TeX mode has two variants, Plain TeX mode and LaTeX mode (actually
+two distinct major modes which differ only slightly). They are
+designed for editing the two different input formats. The command `M-x
+tex-mode' looks at the contents of the buffer to determine whether the
+contents appear to be LaTeX input or not; it then selects the
+appropriate mode. If it can't tell which is right (e.g., the buffer is
+empty), the variable `TeX-default-mode' controls which mode is used.
+
+ The commands `M-x plain-tex-mode' and `M-x latex-mode' explicitly
+select the two variants of TeX mode. Use these commands when `M-x
+tex-mode' does not guess right.
+
+* Menu:
+
+* Editing: TeX Editing. Special commands for editing in TeX mode.
+* Printing: TeX Print. Commands for printing part of a file with TeX.
+
+ TeX for Unix systems can be obtained from the University of
+Washington for a distribution fee.
+
+ To order a full distribution, send $200.00 for a 1/2-inch 9-track
+1600 bpi (`tar' or `cpio') tape reel, or $210.00 for a 1/4-inch 4-track
+QIC-24 (`tar' or `cpio') cartridge, to:
+
+ Northwest Computing Support Center
+ DR-10, Thomson Hall 35
+ University of Washington
+ Seattle, Washington 98195
+
+Please make checks payable to the University of Washington.
+
+ Prepaid orders are preferred but purchase orders are acceptable;
+however, purchase orders carry an extra charge of $10.00, to pay for
+processing.
+
+ Overseas sites: please add to the base cost $20.00 for shipment via
+air parcel post, or $30.00 for shipment via courier.
+
+ Please check with the Northwest Computing Support Center at the
+University of Washington for current prices and formats:
+
+ telephone: (206) 543-6259
+ email: elisabet@u.washington.edu
+
+
+File: emacs, Node: TeX Editing, Next: TeX Print, Prev: TeX Mode, Up: TeX Mode
+
+TeX Editing Commands
+....................
+
+ Here are the special commands provided in TeX mode for editing the
+text of the file.
+
+`"'
+ Insert, according to context, either ```' or `"' or `'''
+ (`TeX-insert-quote').
+
+`LFD'
+ Insert a paragraph break (two newlines) and check the previous
+ paragraph for unbalanced braces or dollar signs
+ (`TeX-terminate-paragraph').
+
+`M-x validate-TeX-buffer'
+ Check each paragraph in the buffer for unbalanced braces or dollar
+ signs.
+
+`M-{'
+ Insert `{}' and position point between them (`TeX-insert-braces').
+
+`M-}'
+ Move forward past the next unmatched close brace (`up-list').
+
+`C-c C-f'
+ Close a block for LaTeX (`TeX-close-LaTeX-block').
+
+ In TeX, the character `"' is not normally used; use ```' to start a
+quotation and `''' to end one. TeX mode defines the key `"' to insert
+```' after whitespace or an open brace, `"' after a backslash, or `'''
+otherwise. This is done by the command `TeX-insert-quote'. If you
+need the character `"' itself in unusual contexts, use `C-q' to insert
+it. Also, `"' with a numeric argument always inserts that number of
+`"' characters.
+
+ In TeX mode, `$' has a special syntax code which attempts to
+understand the way TeX math mode delimiters match. When you insert a
+`$' that is meant to exit math mode, the position of the matching `$'
+that entered math mode is displayed for a second. This is the same
+feature that displays the open brace that matches a close brace that is
+inserted. However, there is no way to tell whether a `$' enters math
+mode or leaves it; so when you insert a `$' that enters math mode, the
+previous `$' position is shown as if it were a match, even though they
+are actually unrelated.
+
+ If you prefer to keep braces balanced at all times, you can use `M-{'
+(`TeX-insert-braces') to insert a pair of braces. It leaves point
+between the two braces so you can insert the text that belongs inside.
+Afterward, use the command `M-}' (`up-list') to move forward past the
+close brace.
+
+ There are two commands for checking the matching of braces. LFD
+(`TeX-terminate-paragraph') checks the paragraph before point, and
+inserts two newlines to start a new paragraph. It prints a message in
+the echo area if any mismatch is found. `M-x validate-TeX-buffer'
+checks the entire buffer, paragraph by paragraph. When it finds a
+paragraph that contains a mismatch, it displays point at the beginning
+of the paragraph for a few seconds and pushes a mark at that spot.
+Scanning continues until the whole buffer has been checked or until you
+type another key. The positions of the last several paragraphs with
+mismatches can be found in the mark ring (*note Mark Ring::.).
+
+ Note that square brackets and parentheses are matched in TeX mode,
+not just braces. This is wrong for the purpose of checking TeX syntax.
+However, parentheses and square brackets are likely to be used in text
+as matching delimiters and it is useful for the various motion commands
+and automatic match display to work with them.
+
+ In LaTeX input, `\begin' and `\end' commands must balance. After you
+insert a `\begin', use `C-c C-f' (`TeX-close-LaTeX-block') to insert
+automatically a matching `\end' (on a new line following the `\begin').
+ A blank line is inserted between the two, and point is left there.
+
+
+File: emacs, Node: TeX Print, Prev: TeX Editing, Up: TeX Mode
+
+TeX Printing Commands
+.....................
+
+ You can invoke TeX as an inferior of Emacs on either the entire
+contents of the buffer or just a region at a time. Running TeX in this
+way on just one chapter is a good way to see what your changes look
+like without taking the time to format the entire file.
+
+`C-c C-r'
+ Invoke TeX on the current region, plus the buffer's header
+ (`TeX-region').
+
+`C-c C-b'
+ Invoke TeX on the entire current buffer (`TeX-buffer').
+
+`C-c C-l'
+ Recenter the window showing output from the inferior TeX so that
+ the last line can be seen (`TeX-recenter-output-buffer').
+
+`C-c C-k'
+ Kill the inferior TeX (`TeX-kill-job').
+
+`C-c C-p'
+ Print the output from the last `C-c C-r' or `C-c C-b' command
+ (`TeX-print').
+
+`C-c C-q'
+ Show the printer queue (`TeX-show-print-queue').
+
+ You can pass the current buffer through an inferior TeX by means of
+`C-c C-b' (`TeX-buffer'). The formatted output appears in a file in
+`/tmp'; to print it, type `C-c C-p' (`TeX-print'). Afterward use `C-c
+C-q' (`TeX-show-print-queue') to view the progress of your output
+towards being printed.
+
+ The console output from TeX, including any error messages, appears
+in a buffer called `*TeX-shell*'. If TeX gets an error, you can switch
+to this buffer and feed it input (this works as in Shell mode; *note
+Interactive Shell::.). Without switching to this buffer you can scroll
+it so that its last line is visible by typing `C-c C-l'.
+
+ Type `C-c C-k' (`TeX-kill-job') to kill the TeX process if you see
+that its output is no longer useful. Using `C-c C-b' or `C-c C-r' also
+kills any TeX process still running.
+
+ You can also pass an arbitrary region through an inferior TeX by
+typing `C-c C-r' (`TeX-region'). This is tricky, however, because most
+files of TeX input contain commands at the beginning to set parameters
+and define macros, without which no later part of the file will format
+correctly. To solve this problem, `C-c C-r' allows you to designate a
+part of the file as containing essential commands; it is included before
+the specified region as part of the input to TeX. The designated part
+of the file is called the "header".
+
+ To indicate the bounds of the header in Plain TeX mode, you insert
+two special strings in the file. Insert `%**start of header' before the
+header, and `%**end of header' after it. Each string must appear
+entirely on one line, but there may be other text on the line before or
+after. The lines containing the two strings are included in the header.
+If `%**start of header' does not appear within the first 100 lines of
+the buffer, `C-c C-r' assumes that there is no header.
+
+ In LaTeX mode, the header begins with `\documentstyle' and ends with
+`\begin{document}'. These are commands that LaTeX requires you to use
+in any case, so nothing special needs to be done to identify the header.
+
+ Entering either kind of TeX mode calls with no arguments the value of
+the variable `text-mode-hook', if that value exists and is not `nil';
+then it does the same with the variable `TeX-mode-hook'. Finally it
+does the same with either `plain-TeX-mode-hook' or `LaTeX-mode-hook'.
+
+
+File: emacs, Node: Texinfo Mode, Next: Outline Mode, Prev: TeX Mode, Up: Text Mode
+
+Texinfo Mode
+------------
+
+ Texinfo is a documentation system that uses a single source file to
+produce both on-line information and printed output. This means that
+instead of writing two different documents, one for the on-line help or
+other on-line information and the other for a typeset manual or other
+printed work, you need write only one document. When the work is
+revised, you need revise only one document. (You can read the on-line
+information, known as an "Info file", with an Info
+documentation-reading program. *note info: (info)Top, for more
+information about Info.) Texinfo is the format in which documentation
+for GNU utilities and libraries is written.
+
+ Texinfo mode provides special features for working with Texinfo files
+including utilities to construct Info menus and pointers automatically,
+keybindings to insert frequently used formatting commands, and
+keybindings for commands to format both for Info and for printing.
+
+ Texinfo mode is described in *Note Using Texinfo Mode: (
+texinfo)Texinfo Mode.
+
+
+File: emacs, Node: Outline Mode, Prev: Texinfo Mode, Up: Text Mode
+
+Outline Mode
+------------
+
+ Outline mode is a major mode much like Text mode but intended for
+editing outlines. It allows you to make parts of the text temporarily
+invisible so that you can see just the overall structure of the
+outline. Type `M-x outline-mode' to turn on Outline mode in the
+current buffer.
+
+ Entering Outline mode calls with no arguments the value of the
+variable `text-mode-hook', if that value exists and is not `nil'; then
+it does the same with the variable `outline-mode-hook'.
+
+ When a line is invisible in outline mode, it does not appear on the
+screen. The screen appears exactly as if the invisible line were
+deleted, except that an ellipsis (three periods in a row) appears at
+the end of the previous visible line (only one ellipsis no matter how
+many invisible lines follow).
+
+ All editing commands treat the text of the invisible line as part of
+the previous visible line. For example, `C-n' moves onto the next
+visible line. Killing an entire visible line, including its
+terminating newline, really kills all the following invisible lines
+along with it; yanking it all back yanks the invisible lines and they
+remain invisible.
+
+* Menu:
+
+* Format: Outline Format. What the text of an outline looks like.
+* Motion: Outline Motion. Special commands for moving through outlines.
+* Visibility: Outline Visibility. Commands to control what is visible.
+
+
+File: emacs, Node: Outline Format, Next: Outline Motion, Prev: Outline Mode, Up: Outline Mode
+
+Format of Outlines
+..................
+
+ Outline mode assumes that the lines in the buffer are of two types:
+"heading lines" and "body lines". A heading line represents a topic in
+the outline. Heading lines start with one or more stars; the number of
+stars determines the depth of the heading in the outline structure.
+Thus, a heading line with one star is a major topic; all the heading
+lines with two stars between it and the next one-star heading are its
+subtopics; and so on. Any line that is not a heading line is a body
+line. Body lines belong to the preceding heading line. Here is an
+example:
+
+ * Food
+
+ This is the body,
+ which says something about the topic of food.
+
+ ** Delicious Food
+
+ This is the body of the second-level header.
+
+ ** Distasteful Food
+
+ This could have
+ a body too, with
+ several lines.
+
+ *** Dormitory Food
+
+ * Shelter
+
+ A second first-level topic with its header line.
+
+ A heading line together with all following body lines is called
+collectively an "entry". A heading line together with all following
+deeper heading lines and their body lines is called a "subtree".
+
+ You can customize the criterion for distinguishing heading lines by
+setting the variable `outline-regexp'. Any line whose beginning has a
+match for this regexp is considered a heading line. Matches that start
+within a line (not at the beginning) do not count. The length of the
+matching text determines the level of the heading; longer matches make
+a more deeply nested level. Thus, for example, if a text formatter has
+commands `@chapter', `@section' and `@subsection' to divide the
+document into chapters and sections, you could make those lines count
+as heading lines by setting `outline-regexp' to
+`"@chap\\|@\\(sub\\)*section"'. Note the trick: the two words `chapter'
+and `section' are equally long, but by defining the regexp to match
+only `chap' we ensure that the length of the text matched on a chapter
+heading is shorter, so that Outline mode will know that sections are
+contained in chapters. This works as long as no other command starts
+with `@chap'.
+
+ Outline mode makes a line invisible by changing the newline before it
+into an ASCII Control-M (code 015). Most editing commands that work on
+lines treat an invisible line as part of the previous line because,
+strictly speaking, it is part of that line, since there is no longer a
+newline in between. When you save the file in Outline mode, Control-M
+characters are saved as newlines, so the invisible lines become ordinary
+lines in the file. But saving does not change the visibility status of
+a line inside Emacs.
+
+
+File: emacs, Node: Outline Motion, Next: Outline Visibility, Prev: Outline Format, Up: Outline Mode
+
+Outline Motion Commands
+.......................
+
+ There are some special motion commands in Outline mode that move
+backward and forward to heading lines.
+
+`C-c C-n'
+ Move point to the next visible heading line
+ (`outline-next-visible-heading').
+
+`C-c C-p'
+ Move point to the previous visible heading line
+ (`outline-previous-visible-heading').
+
+`C-c C-f'
+ Move point to the next visible heading line at the same level as
+ the one point is on (`outline-forward-same-level').
+
+`C-c C-b'
+ Move point to the previous visible heading line at the same level
+ (`outline-backward-same-level').
+
+`C-c C-u'
+ Move point up to a lower-level (more inclusive) visible heading
+ line (`outline-up-heading').
+
+ `C-c C-n' (`next-visible-heading') moves down to the next heading
+line. `C-c C-p' (`previous-visible-heading') moves similarly backward.
+ Both accept numeric arguments as repeat counts. The names emphasize
+that invisible headings are skipped, but this is not really a special
+feature. All editing commands that look for lines ignore the invisible
+lines automatically.
+
+ More advanced motion commands understand the levels of headings. The
+two commands, `C-c C-f' (`outline-forward-same-level') and `C-c C-b'
+(`outline-backward-same-level'), move from one heading line to another
+visible heading at the same depth in the outline. `C-c C-u'
+(`outline-up-heading') moves backward to another heading that is less
+deeply nested.
+
+
+File: emacs, Node: Outline Visibility, Prev: Outline Motion, Up: Outline Mode
+
+Outline Visibility Commands
+...........................
+
+ The other special commands of outline mode are used to make lines
+visible or invisible. Their names all start with `hide' or `show'.
+Most of them fall into pairs of opposites. They are not undoable;
+instead, you can undo right past them. Making lines visible or
+invisible is simply not recorded by the undo mechanism.
+
+`M-x hide-body'
+ Make all body lines in the buffer invisible.
+
+`M-x show-all'
+ Make all lines in the buffer visible.
+
+`C-c C-h'
+ Make everything under this heading invisible, not including this
+ heading itself (`hide-subtree').
+
+`C-c C-s'
+ Make everything under this heading visible, including body,
+ subheadings, and their bodies (`show-subtree').
+
+`M-x hide-leaves'
+ Make the body of this heading line, and of all its subheadings,
+ invisible.
+
+`M-x show-branches'
+ Make all subheadings of this heading line, at all levels, visible.
+
+`C-c C-i'
+ Make immediate subheadings (one level down) of this heading line
+ visible (`show-children').
+
+`M-x hide-entry'
+ Make this heading line's body invisible.
+
+`M-x show-entry'
+ Make this heading line's body visible.
+
+ Two commands that are exact opposites are `M-x hide-entry' and `M-x
+show-entry'. They are used with point on a heading line, and apply
+only to the body lines of that heading. The subtopics and their bodies
+are not affected.
+
+ Two more powerful opposites are `C-c C-h' (`hide-subtree') and `C-c
+C-s' (`show-subtree'). Both expect to be used when point is on a
+heading line, and both apply to all the lines of that heading's
+"subtree": its body, all its subheadings, both direct and indirect, and
+all of their bodies. In other words, the subtree contains everything
+following this heading line, up to and not including the next heading of
+the same or higher rank.
+
+ Intermediate between a visible subtree and an invisible one is having
+all the subheadings visible but none of the body. There are two
+commands for doing this, depending on whether you want to hide the
+bodies or make the subheadings visible. They are `M-x hide-leaves' and
+`M-x show-branches'.
+
+ A little weaker than `show-branches' is `C-c C-i' (`show-children').
+ It makes just the direct subheadings visible--those one level down.
+Deeper subheadings remain invisible, if they were invisible.
+
+ Two commands have a blanket effect on the whole file. `M-x
+hide-body' makes all body lines invisible, so that you see just the
+outline structure. `M-x show-all' makes all lines visible. These
+commands can be thought of as a pair of opposites even though `M-x
+show-all' applies to more than just body lines.
+
+ The use of ellipses at the ends of visible lines can be turned off
+by setting `selective-display-ellipses' to `nil'. Then there is no
+visible indication of the presence of invisible lines.
+
+ \ No newline at end of file
diff --git a/info/emacs-7 b/info/emacs-7
new file mode 100644
index 00000000000..324f3a5a0f1
--- /dev/null
+++ b/info/emacs-7
@@ -0,0 +1,1132 @@
+This is Info file ../info/emacs, produced by Makeinfo-1.49 from the
+input file emacs.texi.
+
+ This file documents the GNU Emacs editor.
+
+ Copyright (C) 1985, 1986, 1988, 1992 Richard M. Stallman.
+
+ Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+ Permission is granted to copy and distribute modified versions of
+this manual under the conditions for verbatim copying, provided also
+that the sections entitled "The GNU Manifesto", "Distribution" and "GNU
+General Public License" are included exactly as in the original, and
+provided that the entire resulting derived work is distributed under the
+terms of a permission notice identical to this one.
+
+ Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that the sections entitled "The GNU Manifesto",
+"Distribution" and "GNU General Public License" may be included in a
+translation approved by the author instead of in the original English.
+
+
+File: emacs, Node: Words, Next: Sentences, Prev: Text Mode, Up: Text
+
+Words
+=====
+
+ Emacs has commands for moving over or operating on words. By
+convention, the keys for them are all `Meta-' characters.
+
+`M-f'
+ Move forward over a word (`forward-word').
+
+`M-b'
+ Move backward over a word (`backward-word').
+
+`M-d'
+ Kill up to the end of a word (`kill-word').
+
+`M-DEL'
+ Kill back to the beginning of a word (`backward-kill-word').
+
+`M-@'
+ Mark the end of the next word (`mark-word').
+
+`M-t'
+ Transpose two words; drag a word forward or backward across other
+ words (`transpose-words').
+
+ Notice how these keys form a series that parallels the
+character-based `C-f', `C-b', `C-d', `C-t' and DEL. `M-@' is related
+to `C-@', which is an alias for `C-SPC'.
+
+ The commands `Meta-f' (`forward-word') and `Meta-b'
+(`backward-word') move forward and backward over words. They are thus
+analogous to `Control-f' and `Control-b', which move over single
+characters. Like their `Control-' analogues, `Meta-f' and `Meta-b'
+move several words if given an argument. `Meta-f' with a negative
+argument moves backward, and `Meta-b' with a negative argument moves
+forward. Forward motion stops right after the last letter of the word,
+while backward motion stops right before the first letter.
+
+ `Meta-d' (`kill-word') kills the word after point. To be precise,
+it kills everything from point to the place `Meta-f' would move to.
+Thus, if point is in the middle of a word, `Meta-d' kills just the part
+after point. If some punctuation comes between point and the next
+word, it is killed along with the word. (If you wish to kill only the
+next word but not the punctuation before it, simply do `Meta-f' to get
+the end, and kill the word backwards with `Meta-DEL'.) `Meta-d' takes
+arguments just like `Meta-f'.
+
+ `Meta-DEL' (`backward-kill-word') kills the word before point. It
+kills everything from point back to where `Meta-b' would move to. If
+point is after the space in `FOO, BAR', then `FOO, ' is killed. (If
+you wish to kill just `FOO', do `Meta-b Meta-d' instead of `Meta-DEL'.)
+
+ `Meta-t' (`transpose-words') exchanges the word before or containing
+point with the following word. The delimiter characters between the
+words do not move. For example, `FOO, BAR' transposes into `BAR, FOO'
+rather than `BAR FOO,'. *Note Transpose::, for more on transposition
+and on arguments to transposition commands.
+
+ To operate on the next N words with an operation which applies
+between point and mark, you can either set the mark at point and then
+move over the words, or you can use the command `Meta-@' (`mark-word')
+which does not move point, but sets the mark where `Meta-f' would move
+to. It can be given arguments just like `Meta-f'.
+
+ The word commands' understanding of syntax is completely controlled
+by the syntax table. Any character can, for example, be declared to be
+a word delimiter. *Note Syntax::.
+
+
+File: emacs, Node: Sentences, Next: Paragraphs, Prev: Words, Up: Text
+
+Sentences
+=========
+
+ The Emacs commands for manipulating sentences and paragraphs are
+mostly on `Meta-' keys, so as to be like the word-handling commands.
+
+`M-a'
+ Move back to the beginning of the sentence
+ (`backward-sentence').
+
+`M-e'
+ Move forward to the end of the sentence (`forward-sentence').
+
+`M-k'
+ Kill forward to the end of the sentence (`kill-sentence').
+
+`C-x DEL'
+ Kill back to the beginning of the sentence
+ (`backward-kill-sentence').
+
+ The commands `Meta-a' and `Meta-e' (`backward-sentence' and
+`forward-sentence') move to the beginning and end of the current
+sentence, respectively. They were chosen to resemble `Control-a' and
+`Control-e', which move to the beginning and end of a line. Unlike
+them, `Meta-a' and `Meta-e' if repeated or given numeric arguments move
+over successive sentences. Emacs assumes that the typist's convention
+is followed, and thus considers a sentence to end wherever there is a
+`.', `?' or `!' followed by the end of a line or two spaces, with any
+number of `)', `]', `'', or `"' characters allowed in between. A
+sentence also begins or ends wherever a paragraph begins or ends.
+
+ Neither `M-a' nor `M-e' moves past the newline or spaces beyond the
+sentence edge at which it is stopping.
+
+ Just as `C-a' and `C-e' have a kill command, `C-k', to go with them,
+so `M-a' and `M-e' have a corresponding kill command `M-k'
+(`kill-sentence') which kills from point to the end of the sentence.
+With minus one as an argument it kills back to the beginning of the
+sentence. Larger arguments serve as a repeat count.
+
+ There is a special command, `C-x DEL' (`backward-kill-sentence') for
+killing back to the beginning of a sentence, because this is useful
+when you change your mind in the middle of composing text.
+
+ The variable `sentence-end' controls recognition of the end of a
+sentence. It is a regexp that matches the last few characters of a
+sentence, together with the whitespace following the sentence. Its
+normal value is
+
+ "[.?!][]\"')]*\\($\\|\t\\| \\)[ \t\n]*"
+
+This example is explained in the section on regexps. *Note Regexps::.
+
+
+File: emacs, Node: Paragraphs, Next: Pages, Prev: Sentences, Up: Text
+
+Paragraphs
+==========
+
+ The Emacs commands for manipulating paragraphs are also `Meta-' keys.
+
+`M-['
+ Move back to previous paragraph beginning
+ (`backward-paragraph').
+
+`M-]'
+ Move forward to next paragraph end (`forward-paragraph').
+
+`M-h'
+ Put point and mark around this or next paragraph
+ (`mark-paragraph').
+
+ `Meta-[' moves to the beginning of the current or previous paragraph,
+while `Meta-]' moves to the end of the current or next paragraph. Blank
+lines and text formatter command lines separate paragraphs and are not
+part of any paragraph. Also, an indented line starts a new paragraph.
+
+ In major modes for programs (as opposed to Text mode), paragraphs
+begin and end only at blank lines. This makes the paragraph commands
+continue to be useful even though there are no paragraphs per se.
+
+ When there is a fill prefix, then paragraphs are delimited by all
+lines which don't start with the fill prefix. *Note Filling::.
+
+ When you wish to operate on a paragraph, you can use the command
+`Meta-h' (`mark-paragraph') to set the region around it. This command
+puts point at the beginning and mark at the end of the paragraph point
+was in. If point is between paragraphs (in a run of blank lines, or at
+a boundary), the paragraph following point is surrounded by point and
+mark. If there are blank lines preceding the first line of the
+paragraph, one of these blank lines is included in the region. Thus,
+for example, `M-h C-w' kills the paragraph around or after point.
+
+ The precise definition of a paragraph boundary is controlled by the
+two variables `paragraph-separate' and `paragraph-start'. The value of
+`paragraph-start' is a regexp that should match any line that either
+starts or separates paragraphs. The value of `paragraph-separate' is
+another regexp that should match only lines that separate paragraphs
+without being part of any paragraph. Lines that start a new paragraph
+and are contained in it must match both regexps. For example, normally
+`paragraph-start' is `"^[ \t\n\f]"' and `paragraph-separate' is
+`"^[ \t\f]*$"'.
+
+ Normally it is desirable for page boundaries to separate paragraphs.
+The default values of these variables recognize the usual separator for
+pages.
+
+
+File: emacs, Node: Pages, Next: Filling, Prev: Paragraphs, Up: Text
+
+Pages
+=====
+
+ Files are often thought of as divided into "pages" by the "formfeed"
+character (ASCII Control-L, octal code 014). For example, if a file is
+printed on a line printer, each page of the file, in this sense, will
+start on a new page of paper. Emacs treats a page-separator character
+just like any other character. It can be inserted with `C-q C-l', or
+deleted with DEL. Thus, you are free to paginate your file or not.
+However, since pages are often meaningful divisions of the file,
+commands are provided to move over them and operate on them.
+
+`C-x ['
+ Move point to previous page boundary (`backward-page').
+
+`C-x ]'
+ Move point to next page boundary (`forward-page').
+
+`C-x C-p'
+ Put point and mark around this page (or another page)
+ (`mark-page').
+
+`C-x l'
+ Count the lines in this page (`count-lines-page').
+
+ The `C-x [' (`backward-page') command moves point to immediately
+after the previous page delimiter. If point is already right after a
+page delimiter, it skips that one and stops at the previous one. A
+numeric argument serves as a repeat count. The `C-x ]' (`forward-page')
+command moves forward past the next page delimiter.
+
+ The `C-x C-p' command (`mark-page') puts point at the beginning of
+the current page and the mark at the end. The page delimiter at the end
+is included (the mark follows it). The page delimiter at the front is
+excluded (point follows it). This command can be followed by `C-w' to
+kill a page which is to be moved elsewhere. If it is inserted after a
+page delimiter, at a place where `C-x ]' or `C-x [' would take you, then
+the page will be properly delimited before and after once again.
+
+ A numeric argument to `C-x C-p' is used to specify which page to go
+to, relative to the current one. Zero means the current page. One
+means the next page, and -1 means the previous one.
+
+ The `C-x l' command (`count-lines-page') is good for deciding where
+to break a page in two. It prints in the echo area the total number of
+lines in the current page, and then divides it up into those preceding
+the current line and those following, as in
+
+ Page has 96 (72+25) lines
+
+Notice that the sum is off by one; this is correct if point is not at
+the beginning of a line.
+
+ The variable `page-delimiter' should have as its value a regexp that
+matches the beginning of a line that separates pages. This is what
+defines where pages begin. The normal value of this variable is
+`"^\f"', which matches a formfeed character at the beginning of a line.
+
+
+File: emacs, Node: Filling, Next: Case, Prev: Pages, Up: Text
+
+Filling Text
+============
+
+ With Auto Fill mode, text can be "filled" (broken up into lines that
+fit in a specified width) as you insert it. If you alter existing text
+it may no longer be properly filled; then explicit commands for filling
+can be used. (Filling is sometimes called "wrapping" in the
+terminology used for other text editors, but we don't use that term,
+because it could just as well refer to the continuation of long lines
+which happens in Emacs if you *don't* fill them.)
+
+* Menu:
+
+* Auto Fill:: Auto Fill mode breaks long lines automatically.
+* Fill Commands:: Commands to refill paragraphs and center lines.
+* Fill Prefix:: Filling when every line is indented or in a comment, etc.
+
+
+File: emacs, Node: Auto Fill, Next: Fill Commands, Prev: Filling, Up: Filling
+
+Auto Fill Mode
+--------------
+
+ "Auto Fill" mode is a minor mode in which lines are broken
+automatically when they become too wide. Breaking happens only when
+you type a SPC or RET.
+
+`M-x auto-fill-mode'
+ Enable or disable Auto Fill mode.
+
+`SPC'
+`RET'
+ In Auto Fill mode, break lines when appropriate.
+
+ `M-x auto-fill-mode' turns Auto Fill mode on if it was off, or off if
+it was on. With a positive numeric argument it always turns Auto Fill
+mode on, and with a negative argument always turns it off. You can see
+when Auto Fill mode is in effect by the presence of the word `Fill' in
+the mode line, inside the parentheses. Auto Fill mode is a minor mode,
+turned on or off for each buffer individually. *Note Minor Modes::.
+
+ In Auto Fill mode, lines are broken automatically at spaces when
+they get longer than the desired width. Line breaking and
+rearrangement takes place only when you type SPC or RET. If you wish
+to insert a space or newline without permitting line-breaking, type
+`C-q SPC' or `C-q LFD' (recall that a newline is really a linefeed).
+Also, `C-o' inserts a newline without line breaking.
+
+ Auto Fill mode works well with Lisp mode, because when it makes a new
+line in Lisp mode it indents that line with TAB. If a line ending in a
+comment gets too long, the text of the comment is split into two
+comment lines. Optionally new comment delimiters are inserted at the
+end of the first line and the beginning of the second so that each line
+is a separate comment; the variable `comment-multi-line' controls the
+choice (*note Comments::.).
+
+ Auto Fill mode does not refill entire paragraphs. It can break
+lines but cannot merge lines. So editing in the middle of a paragraph
+can result in a paragraph that is not correctly filled. The easiest
+way to make the paragraph properly filled again is usually with the
+explicit fill commands.
+
+ Many users like Auto Fill mode and want to use it in all text files.
+The section on init files says how to arrange this permanently for
+yourself. *Note Init File::.
+
+
+File: emacs, Node: Fill Commands, Next: Fill Prefix, Prev: Auto Fill, Up: Filling
+
+Explicit Fill Commands
+----------------------
+
+`M-q'
+ Fill current paragraph (`fill-paragraph').
+
+`M-g'
+ Fill each paragraph in the region (`fill-region').
+
+`C-x f'
+ Set the fill column (`set-fill-column').
+
+`M-x fill-region-as-paragraph.'
+ Fill the region, considering it as one paragraph.
+
+`M-s'
+ Center a line.
+
+ To refill a paragraph, use the command `Meta-q' (`fill-paragraph').
+It causes the paragraph that point is inside, or the one after point if
+point is between paragraphs, to be refilled. All the line-breaks are
+removed, and then new ones are inserted where necessary. `M-q' can be
+undone with `C-_'. *Note Undo::.
+
+ To refill many paragraphs, use `M-g' (`fill-region'), which divides
+the region into paragraphs and fills each of them.
+
+ `Meta-q' and `Meta-g' use the same criteria as `Meta-h' for finding
+paragraph boundaries (*note Paragraphs::.). For more control, you can
+use `M-x fill-region-as-paragraph', which refills everything between
+point and mark. This command recognizes no paragraph separators; it
+deletes any blank lines found within the region to be filled.
+
+ A numeric argument to `M-g' or `M-q' causes it to "justify" the text
+as well as filling it. This means that extra spaces are inserted to
+make the right margin line up exactly at the fill column. To remove the
+extra spaces, use `M-q' or `M-g' with no argument.
+
+ The command `Meta-s' (`center-line') centers the current line within
+the current fill column. With an argument, it centers several lines
+individually and moves past them.
+
+ The maximum line width for filling is in the variable `fill-column'.
+Altering the value of `fill-column' makes it local to the current
+buffer; until that time, the default value is in effect. The default is
+initially 70. *Note Locals::.
+
+ The easiest way to set `fill-column' is to use the command `C-x f'
+(`set-fill-column'). With no argument, it sets `fill-column' to the
+current horizontal position of point. With a numeric argument, it uses
+that as the new fill column.
+
+
+File: emacs, Node: Fill Prefix, Prev: Fill Commands, Up: Filling
+
+The Fill Prefix
+---------------
+
+ To fill a paragraph in which each line starts with a special marker
+(which might be a few spaces, giving an indented paragraph), use the
+"fill prefix" feature. The fill prefix is a string which Emacs expects
+every line to start with, and which is not included in filling.
+
+`C-x .'
+ Set the fill prefix (`set-fill-prefix').
+
+`M-q'
+ Fill a paragraph using current fill prefix (`fill-paragraph').
+
+`M-x fill-individual-paragraphs'
+ Fill the region, considering each change of indentation as
+ starting a new paragraph.
+
+ To specify a fill prefix, move to a line that starts with the desired
+prefix, put point at the end of the prefix, and give the command
+`C-x .' (`set-fill-prefix'). That's a period after the `C-x'. To turn
+off the fill prefix, specify an empty prefix: type `C-x .' with point
+at the beginning of a line.
+
+ When a fill prefix is in effect, the fill commands remove the fill
+prefix from each line before filling and insert it on each line after
+filling. The fill prefix is also inserted on new lines made
+automatically by Auto Fill mode. Lines that do not start with the fill
+prefix are considered to start paragraphs, both in `M-q' and the
+paragraph commands; this is just right if you are using paragraphs with
+hanging indentation (every line indented except the first one). Lines
+which are blank or indented once the prefix is removed also separate or
+start paragraphs; this is what you want if you are writing
+multi-paragraph comments with a comment delimiter on each line.
+
+ The fill prefix is stored in the variable `fill-prefix'. Its value
+is a string, or `nil' when there is no fill prefix. This is a
+per-buffer variable; altering the variable affects only the current
+buffer, but there is a default value which you can change as well.
+*Note Locals::.
+
+ Another way to use fill prefixes is through `M-x
+fill-individual-paragraphs'. This function divides the region into
+groups of consecutive lines with the same amount and kind of
+indentation and fills each group as a paragraph using its indentation
+as a fill prefix.
+
+
+File: emacs, Node: Case, Prev: Filling, Up: Text
+
+Case Conversion Commands
+========================
+
+ Emacs has commands for converting either a single word or any
+arbitrary range of text to upper case or to lower case.
+
+`M-l'
+ Convert following word to lower case (`downcase-word').
+
+`M-u'
+ Convert following word to upper case (`upcase-word').
+
+`M-c'
+ Capitalize the following word (`capitalize-word').
+
+`C-x C-l'
+ Convert region to lower case (`downcase-region').
+
+`C-x C-u'
+ Convert region to upper case (`upcase-region').
+
+ The word conversion commands are the most useful. `Meta-l'
+(`downcase-word') converts the word after point to lower case, moving
+past it. Thus, repeating `Meta-l' converts successive words. `Meta-u'
+(`upcase-word') converts to all capitals instead, while `Meta-c'
+(`capitalize-word') puts the letter following point into upper case and
+the rest of the letters in the word into lower case. All these
+commands convert several words at once if given an argument. They are
+especially convenient for converting a large amount of text from all
+upper case to mixed case, because you can move through the text using
+`M-l', `M-u' or `M-c' on each word as appropriate, occasionally using
+`M-f' instead to skip a word.
+
+ When given a negative argument, the word case conversion commands
+apply to the appropriate number of words before point, but do not move
+point. This is convenient when you have just typed a word in the wrong
+case: you can give the case conversion command and continue typing.
+
+ If a word case conversion command is given in the middle of a word,
+it applies only to the part of the word which follows point. This is
+just like what `Meta-d' (`kill-word') does. With a negative argument,
+case conversion applies only to the part of the word before point.
+
+ The other case conversion commands are `C-x C-u' (`upcase-region')
+and `C-x C-l' (`downcase-region'), which convert everything between
+point and mark to the specified case. Point and mark do not move.
+
+
+File: emacs, Node: Programs, Next: Compiling/Testing, Prev: Text, Up: Top
+
+Editing Programs
+****************
+
+ Emacs has many commands designed to understand the syntax of
+programming languages such as Lisp and C. These commands can
+
+ * Move over or kill balanced expressions or "sexps" (*note Lists::.).
+
+ * Move over or mark top-level balanced expressions ("defuns", in
+ Lisp; functions, in C).
+
+ * Show how parentheses balance (*note Matching::.).
+
+ * Insert, kill or align comments (*note Comments::.).
+
+ * Follow the usual indentation conventions of the language (*note
+ Grinding::.).
+
+ The commands for words, sentences and paragraphs are very useful in
+editing code even though their canonical application is for editing
+human language text. Most symbols contain words (*note Words::.);
+sentences can be found in strings and comments (*note Sentences::.).
+Paragraphs per se are not present in code, but the paragraph commands
+are useful anyway, because Lisp mode and C mode define paragraphs to
+begin and end at blank lines (*note Paragraphs::.). Judicious use of
+blank lines to make the program clearer will also provide interesting
+chunks of text for the paragraph commands to work on.
+
+ The selective display feature is useful for looking at the overall
+structure of a function (*note Selective Display::.). This feature
+causes only the lines that are indented less than a specified amount to
+appear on the screen.
+
+* Menu:
+
+* Program Modes:: Major modes for editing programs.
+* Lists:: Expressions with balanced parentheses.
+ There are editing commands to operate on them.
+* Defuns:: Each program is made up of separate functions.
+ There are editing commands to operate on them.
+* Grinding:: Adjusting indentation to show the nesting.
+* Matching:: Insertion of a close-delimiter flashes matching open.
+* Comments:: Inserting, killing and aligning comments.
+* Macro Expansion:: How to see the results of C macro expansion.
+* Balanced Editing:: Inserting two matching parentheses at once, etc.
+* Lisp Completion:: Completion on symbol names in Lisp code.
+* Documentation:: Getting documentation of functions you plan to call.
+* 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.
+* Fortran:: Fortran mode and its special features.
+
+
+File: emacs, Node: Program Modes, Next: Lists, Prev: Programs, Up: Programs
+
+Major Modes for Programming Languages
+=====================================
+
+ Emacs has 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 that 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 forms of Lisp mode, which differ in the way they
+interface to Lisp execution. *Note Lisp Modes::.
+
+ Each of the programming language modes defines the 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 TAB is bound to `c-indent-line'. LFD is normally
+defined to do RET followed by TAB; thus, it too indents in a
+mode-specific fashion.
+
+ In most programming languages, indentation is likely to vary from
+line to line. So the major modes for those languages rebind DEL to
+treat a tab as if it were the equivalent number of spaces (using the
+command `backward-delete-char-untabify'). This makes it possible to
+rub out indentation one column at a time without worrying whether it is
+made up of spaces or tabs. Use `C-b C-d' to delete a tab character
+before point, in these modes.
+
+ Programming language modes define paragraphs to be separated only by
+blank lines, so that the paragraph commands remain useful. Auto Fill
+mode, if enabled in a programming language major mode, indents the new
+lines which it creates.
+
+ Turning on a major mode calls a user-supplied function called the
+"mode hook", which is the value of a Lisp variable. For example,
+turning on C mode calls the value of the variable `c-mode-hook' if that
+value exists and is non-`nil'. Mode hook variables for other
+programming language modes include `lisp-mode-hook',
+`emacs-lisp-mode-hook', `lisp-interaction-mode-hook',
+`scheme-mode-hook' and `muddle-mode-hook'. The mode hook function
+receives no arguments.
+
+
+File: emacs, Node: Lists, Next: Defuns, Prev: Program Modes, Up: Programs
+
+Lists and Sexps
+===============
+
+ By convention, Emacs keys for dealing with balanced expressions are
+usually `Control-Meta-' characters. They tend to be analogous in
+function to their `Control-' and `Meta-' equivalents. These commands
+are usually thought of as pertaining to expressions in programming
+languages, but can be useful with any language in which some sort of
+parentheses exist (including English).
+
+ These commands fall into two classes. Some deal only with "lists"
+(parenthetical groupings). They see nothing except parentheses,
+brackets, braces (whichever ones must balance in the language you are
+working with), and escape characters that might be used to quote those.
+
+ The other commands deal with expressions or "sexps". The word `sexp'
+is derived from "s-expression", the ancient term for an expression in
+Lisp. But in Emacs, the notion of `sexp' is not limited to Lisp. It
+refers to an expression in whatever language your program is written in.
+Each programming language has its own major mode, which customizes the
+syntax tables so that expressions in that language count as sexps.
+
+ Sexps typically include symbols, numbers, and string constants, as
+well as anything contained in parentheses, brackets or braces.
+
+ In languages that use prefix and infix operators, such as C, it is
+not possible for all expressions to be sexps. For example, C mode does
+not recognize `foo + bar' as a sexp, even though it is a C expression;
+it recognizes `foo' as one sexp and `bar' as another, with the `+' as
+punctuation between them. This is a fundamental ambiguity: both `foo +
+bar' and `foo' are legitimate choices for the sexp to move over if
+point is at the `f'. Note that `(foo + bar)' is a sexp in C mode.
+
+ Some languages have obscure forms of syntax for expressions that
+nobody has bothered to make Emacs understand properly.
+
+`C-M-f'
+ Move forward over a sexp (`forward-sexp').
+
+`C-M-b'
+ Move backward over a sexp (`backward-sexp').
+
+`C-M-k'
+ Kill sexp forward (`kill-sexp').
+
+`C-M-u'
+ Move up and backward in list structure (`backward-up-list').
+
+`C-M-d'
+ Move down and forward in list structure (`down-list').
+
+`C-M-n'
+ Move forward over a list (`forward-list').
+
+`C-M-p'
+ Move backward over a list (`backward-list').
+
+`C-M-t'
+ Transpose expressions (`transpose-sexps').
+
+`C-M-@'
+ Put mark after following expression (`mark-sexp').
+
+ To move forward over a sexp, use `C-M-f' (`forward-sexp'). If the
+first significant character after point is an opening delimiter (`(' in
+Lisp; `(', `[' or `{' in C), `C-M-f' moves past the matching closing
+delimiter. If the character begins a symbol, string, or number,
+`C-M-f' moves over that. If the character after point is a closing
+delimiter, `C-M-f' gets an error.
+
+ The command `C-M-b' (`backward-sexp') moves backward over a sexp.
+The detailed rules are like those above for `C-M-f', but with
+directions reversed. If there are any prefix characters (singlequote,
+backquote and comma, in Lisp) preceding the sexp, `C-M-b' moves back
+over them as well.
+
+ `C-M-f' or `C-M-b' with an argument repeats that operation the
+specified number of times; with a negative argument, it moves in the
+opposite direction.
+
+ The sexp commands move across comments as if they were whitespace, in
+languages such as C where the comment-terminator can be recognized. 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.
+
+ Killing a sexp at a time can be done with `C-M-k' (`kill-sexp').
+`C-M-k' kills the characters that `C-M-f' would move over.
+
+ The "list commands" move over lists like the sexp commands but skip
+blithely over any number of other kinds of sexps (symbols, strings,
+etc). They are `C-M-n' (`forward-list') and `C-M-p' (`backward-list').
+The main reason they are useful is that they usually ignore comments
+(since the comments usually do not contain any lists).
+
+ `C-M-n' and `C-M-p' stay at the same level in parentheses, when
+that's possible. To move up one (or N) levels, use `C-M-u'
+(`backward-up-list'). `C-M-u' moves backward up past one unmatched
+opening delimiter. A positive argument serves as a repeat count; a
+negative argument reverses direction of motion and also requests
+repetition, so it moves forward and up one or more levels.
+
+ To move down in list structure, use `C-M-d' (`down-list'). In Lisp
+mode, where `(' is the only opening delimiter, this is nearly the same
+as searching for a `('. An argument specifies the number of levels of
+parentheses to go down.
+
+ A somewhat random-sounding command which is nevertheless easy to use
+is `C-M-t' (`transpose-sexps'), which drags the previous sexp across
+the next one. An argument serves as a repeat count, and a negative
+argument drags backwards (thus canceling out the effect of `C-M-t' with
+a positive argument). An argument of zero, rather than doing nothing,
+transposes the sexps ending after point and the mark.
+
+ To make the region be the next sexp in the buffer, use `C-M-@'
+(`mark-sexp') which sets mark at the same place that `C-M-f' would move
+to. `C-M-@' takes arguments like `C-M-f'. In particular, a negative
+argument is useful for putting the mark at the beginning of the
+previous sexp.
+
+ The list and sexp commands' understanding of syntax is completely
+controlled by the syntax table. Any character can, for example, be
+declared to be an opening delimiter and act like an open parenthesis.
+*Note Syntax::.
+
+
+File: emacs, Node: Defuns, Next: Grinding, Prev: Lists, Up: Programs
+
+Defuns
+======
+
+ In Emacs, a parenthetical grouping at the top level in the buffer is
+called a "defun". The name derives from the fact that most top-level
+lists in a Lisp file are instances of the special form `defun', but any
+top-level parenthetical grouping counts as a defun in Emacs parlance
+regardless of what its contents are, and regardless of the programming
+language in use. For example, in C, the body of a function definition
+is a defun.
+
+`C-M-a'
+ Move to beginning of current or preceding defun
+ (`beginning-of-defun').
+
+`C-M-e'
+ Move to end of current or following defun (`end-of-defun').
+
+`C-M-h'
+ Put region around whole current or following defun (`mark-defun').
+
+ The commands to move to the beginning and end of the current defun
+are `C-M-a' (`beginning-of-defun') and `C-M-e' (`end-of-defun').
+
+ If you wish to operate on the current defun, use `C-M-h'
+(`mark-defun') which puts point at the beginning and mark at the end of
+the current or next defun. For example, this is the easiest way to get
+ready to move the defun to a different place in the text. In C mode,
+`C-M-h' runs the function `mark-c-function', which is almost the same
+as `mark-defun'; the difference is that it backs up over the argument
+declarations, function name and returned data type so that the entire C
+function is inside the region.
+
+ Emacs assumes that any open-parenthesis found in the leftmost column
+is the start of a defun. Therefore, never put an open-parenthesis at
+the left margin in a Lisp file unless it is the start of a top level
+list. Never put an open-brace or other opening delimiter at the
+beginning of a line of C code unless it starts the body of a function.
+The most likely problem case is when you want an opening delimiter at
+the start of a line inside a string. To avoid trouble, put an escape
+character (`\', in C and Emacs Lisp, `/' in some other Lisp dialects)
+before the opening delimiter. It will not affect the contents of the
+string.
+
+ In the remotest past, the original Emacs found defuns by moving
+upward a level of parentheses until there were no more levels to go up.
+ This always required scanning all the way back to the beginning of the
+buffer, even for a small function. To speed up the operation, Emacs
+was changed to assume that any `(' (or other character assigned the
+syntactic class of opening-delimiter) at the left margin is the start
+of a defun. This heuristic was nearly always right and avoided the
+costly scan; however, it mandated the convention described above.
+
+
+File: emacs, Node: Grinding, Next: Matching, Prev: Defuns, Up: Programs
+
+Indentation for Programs
+========================
+
+ The best way to keep a program properly indented ("ground") is to use
+Emacs to re-indent it as you change it. Emacs has commands to indent
+properly either a single line, a specified number of lines, or all of
+the lines inside a single parenthetical grouping.
+
+* Menu:
+
+* 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.
+
+
+File: emacs, Node: Basic Indent, Next: Multi-line Indent, Prev: Grinding, Up: Grinding
+
+Basic Program Indentation Commands
+----------------------------------
+
+`TAB'
+ Adjust indentation of current line.
+
+`LFD'
+ Equivalent to RET followed by TAB (`newline-and-indent').
+
+ The basic indentation command is TAB, which gives the current line
+the correct indentation as determined from the previous lines. The
+function that TAB runs depends on the major mode; it is
+`lisp-indent-line' in Lisp mode, `c-indent-line' in C mode, etc. These
+functions understand different syntaxes for different languages, but
+they all do about the same thing. TAB in any programming language
+major mode inserts or deletes whitespace at the beginning of the
+current line, independent of where point is in the line. If point is
+inside the whitespace at the beginning of the line, TAB leaves it at
+the end of that whitespace; otherwise, TAB leaves point fixed with
+respect to the characters around it.
+
+ Use `C-q TAB' to insert a tab at point.
+
+ When entering a large amount of new code, use LFD
+(`newline-and-indent'), which is equivalent to a RET followed by a TAB.
+ LFD creates a blank line, and then gives it the appropriate
+indentation.
+
+ TAB indents the second and following lines of the body of a
+parenthetical grouping each under the preceding one; therefore, if you
+alter one line's indentation to be nonstandard, the lines below will
+tend to follow it. This is the right behavior in cases where the
+standard result of TAB is unaesthetic.
+
+ Remember that an open-parenthesis, open-brace or other opening
+delimiter at the left margin is assumed by Emacs (including the
+indentation routines) to be the start of a function. Therefore, you
+must never have an opening delimiter in column zero that is not the
+beginning of a function, not even inside a string. This restriction is
+vital for making the indentation commands fast; you must simply accept
+it. *Note Defuns::, for more information on this.
+
+
+File: emacs, Node: Multi-line Indent, Next: Lisp Indent, Prev: Basic Indent, Up: Grinding
+
+Indenting Several Lines
+-----------------------
+
+ When you wish to re-indent several lines of code which have been
+altered or moved to a different level in the list structure, you have
+several commands available.
+
+`C-M-q'
+ Re-indent all the lines within one list (`indent-sexp').
+
+`C-u TAB'
+ Shift an entire list rigidly sideways so that its first line is
+ properly indented.
+
+`C-M-\'
+ Re-indent all lines in the region (`indent-region').
+
+ You can re-indent the contents of a single list by positioning point
+before the beginning of it and typing `C-M-q' (`indent-sexp' in Lisp
+mode, `indent-c-exp' in C mode; also bound to other suitable functions
+in other modes). The indentation of the line the sexp starts on is not
+changed; therefore, only the relative indentation within the list, and
+not its position, is changed. To correct the position as well, type a
+TAB before the `C-M-q'.
+
+ If the relative indentation within a list is correct but the
+indentation of its beginning is not, go to the line the list begins on
+and type `C-u TAB'. When TAB is given a numeric argument, it moves all
+the lines in the grouping starting on the current line sideways the
+same amount that the current line moves. It is clever, though, and
+does not move lines that start inside strings, or C preprocessor lines
+when in C mode.
+
+ Another way to specify the range to be re-indented is with point and
+mark. The command `C-M-\' (`indent-region') applies TAB to every line
+whose first character is between point and mark.
+
+
+File: emacs, Node: Lisp Indent, Next: C Indent, Prev: Multi-line Indent, Up: Grinding
+
+Customizing Lisp Indentation
+----------------------------
+
+ The indentation pattern for a Lisp expression can depend on the
+function called by the expression. For each Lisp function, you can
+choose among several predefined patterns of indentation, or define an
+arbitrary one with a Lisp program.
+
+ The standard pattern of indentation is as follows: the second line
+of the expression is indented under the first argument, if that is on
+the same line as the beginning of the expression; otherwise, the second
+line is indented underneath the function name. Each following line is
+indented under the previous line whose nesting depth is the same.
+
+ If the variable `lisp-indent-offset' is non-`nil', it overrides the
+usual indentation pattern for the second line of an expression, so that
+such lines are always indented `lisp-indent-offset' more columns than
+the containing list.
+
+ The standard pattern is overridden for certain functions. Functions
+whose names start with `def' always indent the second line by
+`lisp-body-indention' extra columns beyond the open-parenthesis
+starting the expression.
+
+ The standard pattern can be overridden in various ways for individual
+functions, according to the `lisp-indent-hook' property of the function
+name. There are four possibilities for this property:
+
+`nil'
+ This is the same as no property; the standard indentation pattern
+ is used.
+
+`defun'
+ The pattern used for function names that start with `def' is used
+ for this function also.
+
+a number, NUMBER
+ The first NUMBER arguments of the function are "distinguished"
+ arguments; the rest are considered the "body" of the expression.
+ A line in the expression is indented according to whether the
+ first argument on it is distinguished or not. If the argument is
+ part of the body, the line is indented `lisp-body-indent' more
+ columns than the open-parenthesis starting the containing
+ expression. If the argument is distinguished and is either the
+ first or second argument, it is indented twice that many extra
+ columns. If the argument is distinguished and not the first or
+ second argument, the standard pattern is followed for that line.
+
+a symbol, SYMBOL
+ SYMBOL should be a function name; that function is called to
+ calculate the indentation of a line within this expression. The
+ function receives two arguments:
+ STATE
+ The value returned by `parse-partial-sexp' (a Lisp primitive
+ for indentation and nesting computation) when it parses up to
+ the beginning of this line.
+
+ POS
+ The position at which the line being indented begins.
+
+ It should return either a number, which is the number of columns of
+ indentation for that line, or a list whose CAR is such a number.
+ The difference between returning a number and returning a list is
+ that a number says that all following lines at the same nesting
+ level should be indented just like this one; a list says that
+ following lines might call for different indentations. This makes
+ a difference when the indentation is being computed by `C-M-q'; if
+ the value is a number, `C-M-q' need not recalculate indentation
+ for the following lines until the end of the list.
+
+
+File: emacs, Node: C Indent, Prev: Lisp Indent, Up: Grinding
+
+Customizing C Indentation
+-------------------------
+
+ Two variables control which commands perform C indentation and when.
+
+ If `c-auto-newline' is non-`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.
+
+ If `c-tab-always-indent' is `nil', the 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, then TAB
+just inserts a tab character in the buffer. Normally, this variable is
+`t', and 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.
+
+`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.
+
+`c-continued-statement-offset'
+ Extra indentation given to a substatement, such as the then-clause
+ of an if or body of a while.
+
+`c-brace-offset'
+ Extra indentation for line if it starts with an open brace.
+
+`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.
+
+`c-argdecl-indent'
+ Indentation level of declarations of C function arguments.
+
+`c-label-offset'
+ Extra indentation for line that is a label, or case or default.
+
+ The variable `c-indent-level' controls the indentation for C
+statements with respect to the surrounding block. In the example
+
+ {
+ foo ();
+
+the difference in indentation between the lines is `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 `c-indent-level' is added to the indentation
+of the line, not the column of the open-brace. For example,
+
+ if (losing) {
+ do_this ();
+
+One popular indentation style is that which results from setting
+`c-indent-level' to 8 and putting open-braces at the end of a line in
+this way. I prefer to put the open-brace on a separate line.
+
+ In fact, the value of the variable `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 nonblank character on the line.
+By setting this variable to 4 and `c-indent-level' to 0, you can get
+this style:
+
+ if (x == y) {
+ do_it ();
+ }
+
+ When `c-indent-level' is zero, the statements inside most braces
+will line up right under the open brace. But there is an exception made
+for braces in column zero, such as surrounding a function's body. The
+statements just inside it do not go at column zero. Instead,
+`c-brace-offset' and `c-continued-statement-offset' (see below) are
+added to produce a typical offset between brace levels, and the
+statements are indented that far.
+
+ `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 that are within other
+statements, such as the then-clauses of `if' statements and the bodies
+of `while' statements. This parameter is the difference in indentation
+between the two lines in
+
+ if (x == y)
+ do_it ();
+
+Its standard value is 2. Some popular indentation styles correspond to
+a value of zero for `c-continued-statement-offset'.
+
+ `c-brace-offset' is the extra indentation given to a line that
+starts with an open-brace. Its standard value is zero; compare
+
+ if (x == y)
+ {
+
+with
+
+ if (x == y)
+ do_it ();
+
+if `c-brace-offset' were set to 4, the first example would become
+
+ if (x == y)
+ {
+
+ `c-argdecl-indent' controls the indentation of declarations of the
+arguments of a C function. It is absolute: argument declarations
+receive exactly `c-argdecl-indent' spaces. The standard value is 5,
+resulting in code like this:
+
+ char *
+ index (string, c)
+ char *string;
+ int c;
+
+ `c-label-offset' is the extra indentation given to a line that
+contains a label, a case statement, or a `default:' statement. Its
+standard value is -2, resulting in code like this
+
+ switch (c)
+ {
+ case 'x':
+
+If `c-label-offset' were zero, the same code would be indented as
+
+ switch (c)
+ {
+ case 'x':
+
+This example assumes that the other variables above also have their
+standard values.
+
+ I strongly recommend that you try out the indentation style produced
+by the standard settings of these variables, together with putting open
+braces on separate lines. You can see how it looks in all the C source
+files of GNU Emacs.
+
+
+File: emacs, Node: Matching, Next: Comments, Prev: Grinding, Up: Programs
+
+Automatic Display Of Matching Parentheses
+=========================================
+
+ The Emacs parenthesis-matching feature is designed to show
+automatically how parentheses match in the text. Whenever a
+self-inserting character that is a closing delimiter is typed, the
+cursor moves momentarily to the location of the matching opening
+delimiter, provided that is on the screen. If it is not on the screen,
+some text starting with that opening delimiter is displayed in the echo
+area. Either way, you can tell what grouping is being closed off.
+
+ In Lisp, automatic matching applies only to parentheses. In C, it
+applies to braces and brackets too. Emacs knows which characters to
+regard as matching delimiters based on the syntax table, which is set
+by the major mode. *Note Syntax::.
+
+ If the opening delimiter and closing delimiter are mismatched--such
+as in `[x)'--a warning message is displayed in the echo area. The
+correct matches are specified in the syntax table.
+
+ Two variables control parenthesis match display.
+`blink-matching-paren' turns the feature on or off; `nil' turns it off,
+but the default is `t' to turn match display on.
+`blink-matching-paren-distance' specifies how many characters back to
+search to find the matching opening delimiter. If the match is not
+found in that far, scanning stops, and nothing is displayed. This is
+to prevent scanning for the matching delimiter from wasting lots of
+time when there is no match. The default is 4000.
+
+ \ No newline at end of file
diff --git a/info/emacs-8 b/info/emacs-8
new file mode 100644
index 00000000000..bc18a3ae024
--- /dev/null
+++ b/info/emacs-8
@@ -0,0 +1,1191 @@
+This is Info file ../info/emacs, produced by Makeinfo-1.49 from the
+input file emacs.texi.
+
+ This file documents the GNU Emacs editor.
+
+ Copyright (C) 1985, 1986, 1988, 1992 Richard M. Stallman.
+
+ Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+ Permission is granted to copy and distribute modified versions of
+this manual under the conditions for verbatim copying, provided also
+that the sections entitled "The GNU Manifesto", "Distribution" and "GNU
+General Public License" are included exactly as in the original, and
+provided that the entire resulting derived work is distributed under the
+terms of a permission notice identical to this one.
+
+ Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that the sections entitled "The GNU Manifesto",
+"Distribution" and "GNU General Public License" may be included in a
+translation approved by the author instead of in the original English.
+
+
+File: emacs, Node: Comments, Next: Macro Expansion, Prev: Matching, Up: Programs
+
+Manipulating Comments
+=====================
+
+ The comment commands insert, kill and align comments.
+
+`M-;'
+ Insert or align comment (`indent-for-comment').
+
+`C-x ;'
+ Set comment column (`set-comment-column').
+
+`C-u - C-x ;'
+ Kill comment on current line (`kill-comment').
+
+`M-LFD'
+ Like RET followed by inserting and aligning a comment
+ (`indent-new-comment-line').
+
+ The command that creates a comment is `Meta-;'
+(`indent-for-comment'). If there is no comment already on the line, a
+new comment is created, aligned at a specific column called the
+"comment column". The comment is created by inserting the string Emacs
+thinks comments should start with (the value of `comment-start'; see
+below). Point is left after that string. If the text of the line
+extends past the comment column, then the indentation is done to a
+suitable boundary (usually, at least one space is inserted). If the
+major mode has specified a string to terminate comments, that is
+inserted after point, to keep the syntax valid.
+
+ `Meta-;' can also be used to align an existing comment. If a line
+already contains the string that starts comments, then `M-;' just moves
+point after it and re-indents it to the conventional place. Exception:
+comments starting in column 0 are not moved.
+
+ Some major modes have special rules for indenting certain kinds of
+comments in certain contexts. For example, in Lisp code, comments which
+start with two semicolons are indented as if they were lines of code,
+instead of at the comment column. Comments which start with three
+semicolons are supposed to start at the left margin. Emacs understands
+these conventions by indenting a double-semicolon comment using TAB,
+and by not changing the indentation of a triple-semicolon comment at
+all.
+
+ ;; This function is just an example
+ ;;; Here either two or three semicolons are appropriate.
+ (defun foo (x)
+ ;;; And now, the first part of the function:
+ ;; The following line adds one.
+ (1+ x)) ; This line adds one.
+
+ In C code, a comment preceded on its line by nothing but whitespace
+is indented like a line of code.
+
+ Even when an existing comment is properly aligned, `M-;' is still
+useful for moving directly to the start of the comment.
+
+ `C-u - C-x ;' (`kill-comment') kills the comment on the current line,
+if there is one. The indentation before the start of the comment is
+killed as well. If there does not appear to be a comment in the line,
+nothing is done. To reinsert the comment on another line, move to the
+end of that line, do `C-y', and then do `M-;' to realign it. Note that
+`C-u - C-x ;' is not a distinct key; it is `C-x ;'
+(`set-comment-column') with a negative argument. That command is
+programmed so that when it receives a negative argument it calls
+`kill-comment'. However, `kill-comment' is a valid command which you
+could bind directly to a key if you wanted to.
+
+Multiple Lines of Comments
+--------------------------
+
+ If you are typing a comment and find that you wish to continue it on
+another line, you can use the command `Meta-LFD'
+(`indent-new-comment-line'), which terminates the comment you are
+typing, creates a new blank line afterward, and begins a new comment
+indented under the old one. When Auto Fill mode is on, going past the
+fill column while typing a comment causes the comment to be continued
+in just this fashion. If point is not at the end of the line when
+`M-LFD' is typed, the text on the rest of the line becomes part of the
+new comment line.
+
+Options Controlling Comments
+----------------------------
+
+ The comment column is stored in the variable `comment-column'. You
+can set it to a number explicitly. Alternatively, the command `C-x ;'
+(`set-comment-column') sets the comment column to the column point is
+at. `C-u C-x ;' sets the comment column to match the last comment
+before point in the buffer, and then does a `Meta-;' to align the
+current line's comment under the previous one. Note that `C-u - C-x ;'
+runs the function `kill-comment' as described above.
+
+ `comment-column' is a per-buffer variable; altering the variable
+affects only the current buffer, but there is a default value which you
+can change as well. *Note Locals::. Many major modes initialize this
+variable for the current buffer.
+
+ The comment commands recognize comments based on the regular
+expression that is the value of the variable `comment-start-skip'.
+This regexp should not match the null string. It may match more than
+the comment starting delimiter in the strictest sense of the word; for
+example, in C mode the value of the variable is `"/\\*+ *"', which
+matches extra stars and spaces after the `/*' itself. (Note that `\\'
+is needed in Lisp syntax to include a `\' in the string, which is needed
+to deny the first star its special meaning in regexp syntax. *Note
+Regexps::.)
+
+ When a comment command makes a new comment, it inserts the value of
+`comment-start' to begin it. The value of `comment-end' is inserted
+after point, so that it will follow the text that you will insert into
+the comment. In C mode, `comment-start' has the value `"/* "' and
+`comment-end' has the value `" */"'.
+
+ `comment-multi-line' controls how `M-LFD' (`indent-new-comment-line')
+behaves when used inside a comment. If `comment-multi-line' is `nil',
+as it normally is, then the comment on the starting line is terminated
+and a new comment is started on the new following line. If
+`comment-multi-line' is not `nil', then the new following line is set
+up as part of the same comment that was found on the starting line.
+This is done by not inserting a terminator on the old line, and not
+inserting a starter on the new line. In languages where multi-line
+comments work, the choice of value for this variable is a matter of
+taste.
+
+ The variable `comment-indent-hook' should contain a function that
+will be called to compute the indentation for a newly inserted comment
+or for aligning an existing comment. It is set differently by various
+major modes. The function is called with no arguments, but with point
+at the beginning of the comment, or at the end of a line if a new
+comment is to be inserted. It should return the column in which the
+comment ought to start. For example, in Lisp mode, the indent hook
+function bases its decision on how many semicolons begin an existing
+comment, and on the code in the preceding lines.
+
+
+File: emacs, Node: Macro Expansion, Next: Balanced Editing, Prev: Comments, Up: Programs
+
+Viewing How C Macros Expand
+===========================
+
+ When you are debugging C code that uses macros, sometimes it is hard
+to figure out precisely how the macros expand. The command `M-x
+c-macro-expand'. It runs the C preprocessor and shows you what
+expansion results from the region. The portion of the buffer before the
+region is also included in preprocessing, for the sake of macros defined
+there, but the output from this part isn't shown.
+
+
+File: emacs, Node: Balanced Editing, Next: Lisp Completion, Prev: Macro Expansion, Up: Programs
+
+Editing Without Unbalanced Parentheses
+======================================
+
+`M-('
+ Put parentheses around next sexp(s) (`insert-parentheses').
+
+`M-)'
+ Move past next close parenthesis and re-indent
+ (`move-over-close-and-reindent').
+
+ The two commands, `M-(' (`insert-parentheses') and `M-)'
+(`move-over-close-and-reindent'), are designed to facilitate a style of
+editing which keeps parentheses balanced at all times. `M-(' inserts a
+pair of parentheses, either together as in `()', or, if given an
+argument, around the next several sexps, and leaves point after the open
+parenthesis. Instead of typing `( F O O )', you can type `M-( F O O',
+which has the same effect except for leaving the cursor before the
+close parenthesis. Then you would type `M-)', which moves past the
+close parenthesis, deleting any indentation preceding it (in this
+example there is none), and indenting with LFD after it.
+
+
+File: emacs, Node: Lisp Completion, Next: Documentation, Prev: Balanced Editing, Up: Programs
+
+Completion for Lisp Symbols
+===========================
+
+ Usually completion happens in the minibuffer. But one kind of
+completion is available in all buffers: completion for Lisp symbol
+names.
+
+ The command `M-TAB' (`lisp-complete-symbol') takes the partial Lisp
+symbol before point to be an abbreviation, and compares it against all
+nontrivial Lisp symbols currently known to Emacs. Any additional
+characters that they all have in common are inserted at point.
+Nontrivial symbols are those that have function definitions, values or
+properties.
+
+ If there is an open-parenthesis immediately before the beginning of
+the partial symbol, only symbols with function definitions are
+considered as completions.
+
+ If the partial name in the buffer has more than one possible
+completion and they have no additional characters in common, a list of
+all possible completions is displayed in another window.
+
+
+File: emacs, Node: Documentation, Next: Change Log, Prev: Lisp Completion, Up: Programs
+
+Documentation Commands
+======================
+
+ As you edit Lisp code to be run in Emacs, the commands `C-h f'
+(`describe-function') and `C-h v' (`describe-variable') can be used to
+print documentation of functions and variables that you want to call.
+These commands use the minibuffer to read the name of a function or
+variable to document, and display the documentation in a window.
+
+ For extra convenience, these commands provide default arguments
+based on the code in the neighborhood of point. `C-h f' sets the
+default to the function called in the innermost list containing point.
+`C-h v' uses the symbol name around or adjacent to point as its default.
+
+ Documentation on Unix commands, system calls and libraries can be
+obtained with the `M-x manual-entry' command. This reads a topic as an
+argument, and displays the text on that topic from the Unix manual.
+`manual-entry' always searches all 8 sections of the manual, and
+concatenates all the entries that are found. For example, the topic
+`termcap' finds the description of the termcap library from section 3,
+followed by the description of the termcap data base from section 5.
+
+
+File: emacs, Node: Change Log, Next: Tags, Prev: Documentation, Up: Programs
+
+Change Logs
+===========
+
+ The Emacs command `M-x add-change-log-entry' helps you keep a record
+of when and why you have changed a program. It assumes that you have a
+file in which you write a chronological sequence of entries describing
+individual changes. The default is to store the change entries in a
+file called `ChangeLog' in the same directory as the file you are
+editing. The same `ChangeLog' file therefore records changes for all
+the files in the directory.
+
+ A change log entry starts with a header line that contains your name
+and the current date. Aside from these header lines, every line in the
+change log starts with a tab. One entry can describe several changes;
+each change starts with a line starting with a tab and a star. `M-x
+add-change-log-entry' visits the change log file and creates a new
+entry unless the most recent entry is for today's date and your name.
+In either case, it adds a new line to start the description of another
+change just after the header line of the entry. When `M-x
+add-change-log-entry' is finished, all is prepared for you to edit in
+the description of what you changed and how. You must then save the
+change log file yourself.
+
+ The change log file is always visited in Indented Text mode, which
+means that LFD and auto-filling indent each new line like the previous
+line. This is convenient for entering the contents of an entry, which
+must all be indented. *Note Text Mode::.
+
+ An alternative convenient command for starting a change log entry is
+`C-x 4 a' (`add-change-log-entry-other-window'). It resembles
+`add-change-log-entry' except that it visits the change log in another
+window, and always uses the file `./ChangeLog'--it does not ask you for
+the file name.
+
+ Here is an example of the formatting conventions used in the change
+log for Emacs:
+
+ Wed Jun 26 19:29:32 1985 Richard M. Stallman (rms at mit-prep)
+
+ * xdisp.c (try_window_id):
+ If C-k is done at end of next-to-last line,
+ this fn updates window_end_vpos and cannot leave
+ window_end_pos nonnegative (it is zero, in fact).
+ If display is preempted before lines are output,
+ this is inconsistent. Fix by setting
+ blank_end_of_window to nonzero.
+
+ Tue Jun 25 05:25:33 1985 Richard M. Stallman (rms at mit-prep)
+
+ * cmds.c (Fnewline):
+ Call the auto fill hook if appropriate.
+
+ * xdisp.c (try_window_id):
+ If point is found by compute_motion after xp, record that
+ permanently. If display_text_line sets point position wrong
+ (case where line is killed, point is at eob and that line is
+ not displayed), set it again in final compute_motion.
+
+
+File: emacs, Node: Tags, Next: Fortran, Prev: Change Log, Up: Programs
+
+Tag Tables
+==========
+
+ A "tag table" is a description of how a multi-file program is broken
+up into files. It lists the names of the component files and the names
+and positions of the functions in each file. Grouping the related
+files makes it possible to search or replace through all the files with
+one command. Recording the function names and positions makes possible
+the `Meta-.' command which you can use to find the definition of a
+function without having to know which of the files it is in.
+
+ Tag tables are stored in files called "tag table files". The
+conventional name for a tag table file is `TAGS'.
+
+ Each entry in the tag table records the name of one tag, the name of
+the file that the tag is defined in (implicitly), and the position in
+that file of the tag's definition.
+
+ Just what names from the described files are recorded in the tag
+table depends on the programming language of the described file. They
+normally include all functions and subroutines, and may also include
+global variables, data types, and anything else convenient. In any
+case, each name recorded is called a "tag".
+
+* Menu:
+
+* Tag Syntax::
+* Create Tag Table::
+* Select Tag Table::
+* Find Tag::
+* Tags Search::
+* Tags Stepping::
+* List Tags::
+
+
+File: emacs, Node: Tag Syntax, Next: Create Tag Table, Prev: Tags, Up: Tags
+
+Source File Tag Syntax
+----------------------
+
+ In Lisp code, any function defined with `defun', any variable
+defined with `defvar' or `defconst', and in general the first argument
+of any expression that starts with `(def' in column zero, is a tag.
+
+ In C code, any C function is a tag, and so is any typedef if `-t' is
+specified when the tag table is constructed.
+
+ In Fortran code, functions and subroutines are tags.
+
+ In LaTeX text, the argument of any of the commands `\chapter',
+`\section', `\subsection', `\subsubsection', `\eqno', `\label', `\ref',
+`\cite', `\bibitem' and `\typeout' is a tag.
+
+
+File: emacs, Node: Create Tag Table, Next: Select Tag Table, Prev: Tag Syntax, Up: Tags
+
+Creating Tag Tables
+-------------------
+
+ The `etags' program is used to create a tag table file. It knows
+the syntax of C, Fortran, LaTeX, Scheme and Emacs Lisp/Common Lisp. To
+use `etags', type
+
+ etags INPUTFILES...
+
+as a shell command. It reads the specified files and writes a tag table
+named `TAGS' in the current working directory. `etags' recognizes the
+language used in an input file based on its file name and contents;
+there are no switches for specifying the language. The `-t' switch
+tells `etags' to record typedefs in C code as tags.
+
+ If the tag table data become outdated due to changes in the files
+described in the table, the way to update the tag table is the same way
+it was made in the first place. It is not necessary to do this often.
+
+ If the tag table fails to record a tag, or records it for the wrong
+file, then Emacs cannot possibly find its definition. However, if the
+position recorded in the tag table becomes a little bit wrong (due to
+some editing in the file that the tag definition is in), the only
+consequence is to slow down finding the tag slightly. Even if the
+stored position is very wrong, Emacs will still find the tag, but it
+must search the entire file for it.
+
+ So you should update a tag table when you define new tags that you
+want to have listed, or when you move tag definitions from one file to
+another, or when changes become substantial. Normally there is no need
+to update the tag table after each edit, or even every day.
+
+
+File: emacs, Node: Select Tag Table, Next: Find Tag, Prev: Create Tag Table, Up: Tags
+
+Selecting a Tag Table
+---------------------
+
+ Emacs has at any time one "selected" tag table, and all the commands
+for working with tag tables use the selected one. To select a tag
+table, type `M-x visit-tags-table', which reads the tag table file name
+as an argument. The name `TAGS' in the default directory is used as the
+default file name.
+
+ All this command does is store the file name in the variable
+`tags-file-name'. Emacs does not actually read in the tag table
+contents until you try to use them. Setting this variable yourself is
+just as good as using `visit-tags-table'. The variable's initial value
+is `nil'; this value tells all the commands for working with tag tables
+that they must ask for a tag table file name to use.
+
+
+File: emacs, Node: Find Tag, Next: Tags Search, Prev: Select Tag Table, Up: Tags
+
+Finding a Tag
+-------------
+
+ The most important thing that a tag table enables you to do is to
+find the definition of a specific tag.
+
+`M-. TAG'
+ Find first definition of TAG (`find-tag').
+
+`C-u M-.'
+ Find next alternate definition of last tag specified.
+
+`C-x 4 . TAG'
+ Find first definition of TAG, but display it in another window
+ (`find-tag-other-window').
+
+ `M-.' (`find-tag') is the command to find the definition of a
+specified tag. It searches through the tag table for that tag, as a
+string, and then uses the tag table info to determine the file that the
+definition is in and the approximate character position in the file of
+the definition. Then `find-tag' visits that file, moves point to the
+approximate character position, and starts searching ever-increasing
+distances away for the the text that should appear at the beginning of
+the definition.
+
+ If an empty argument is given (just type RET), the sexp in the
+buffer before or around point is used as the name of the tag to find.
+*Note Lists::, for info on sexps.
+
+ The argument to `find-tag' need not be the whole tag name; it can be
+a substring of a tag name. However, there can be many tag names
+containing the substring you specify. Since `find-tag' works by
+searching the text of the tag table, it finds the first tag in the
+table that the specified substring appears in.
+
+ The way to find other tags that match the substring is to give
+`find-tag' a numeric argument, as in `C-u M-.'; this does not read a
+tag name, but continues searching the tag table's text for another tag
+containing the same substring last used. If you have a real META key,
+`M-0 M-.' is an easier alternative to `C-u M-.'. (That is a zero in
+`M-0'.)
+
+ Like most commands that can switch buffers, `find-tag' has another
+similar command that displays the new buffer in another window. `C-x 4
+.' invokes the function `find-tag-other-window'. (This key sequence
+ends with a period.)
+
+ Emacs comes with a tag table file `TAGS', in the `src' subdirectory,
+which includes all the Lisp libraries and all the C sources of Emacs.
+By specifying this file with `visit-tags-table' and then using `M-.'
+you can quickly look at the source of any Emacs function.
+
+
+File: emacs, Node: Tags Search, Next: Tags Stepping, Prev: Find Tag, Up: Tags
+
+Searching and Replacing with Tag Tables
+---------------------------------------
+
+ The commands in this section visit and search all the files listed
+in the selected tag table, one by one. For these commands, the tag
+table serves only to specify a sequence of files to search. A related
+command is `M-x grep' (*note Compilation::.).
+
+`M-x tags-search'
+ Search for the specified regexp through the files in the selected
+ tag table.
+
+`M-x tags-query-replace'
+ Perform a `query-replace' on each file in the selected tag table.
+
+`M-,'
+ Restart one of the commands above, from the current location of
+ point (`tags-loop-continue').
+
+ `M-x tags-search' reads a regexp using the minibuffer, then visits
+the files of the selected tag table one by one, and searches through
+each one for that regexp. It displays the name of the file being
+searched so you can follow its progress. As soon as an occurrence is
+found, `tags-search' returns.
+
+ Having found one match, you probably want to find all the rest. To
+find one more match, type `M-,' (`tags-loop-continue') to resume the
+`tags-search'. This searches the rest of the current buffer, followed
+by the remaining files of the tag table.
+
+ `M-x tags-query-replace' performs a single `query-replace' through
+all the files in the tag table. It reads a string to search for and a
+string to replace with, just like ordinary `M-x query-replace'. It
+searches much like `M-x tags-search' but repeatedly, processing matches
+according to your input. *Note Replace::, for more information on
+`query-replace'.
+
+ It is possible to get through all the files in the tag table with a
+single invocation of `M-x tags-query-replace'. But since any
+unrecognized character causes the command to exit, you may need to
+continue where you left off. `M-,' can be used for this. It resumes
+the last tags search or replace command that you did.
+
+ It may have struck you that `tags-search' is a lot like `grep'. You
+can also run `grep' itself as an inferior of Emacs and have Emacs show
+you the matching lines one by one. This works mostly the same as
+running a compilation and having Emacs show you where the errors were.
+*Note Compilation::.
+
+
+File: emacs, Node: Tags Stepping, Next: List Tags, Prev: Tags Search, Up: Tags
+
+Stepping Through a Tag Table
+----------------------------
+
+ If you wish to process all the files in the selected tag table, but
+`M-x tags-search' and `M-x tags-query-replace' in particular are not
+what you want, you can use `M-x next-file'.
+
+`C-u M-x next-file'
+ With a numeric argument, regardless of its value, visit the first
+ file in the tag table, and prepare to advance sequentially by
+ files.
+
+`M-x next-file'
+ Visit the next file in the selected tag table.
+
+
+File: emacs, Node: List Tags, Prev: Tags Stepping, Up: Tags
+
+Tag Table Inquiries
+-------------------
+
+`M-x list-tags'
+ Display a list of the tags defined in a specific program file.
+
+`M-x tags-apropos'
+ Display a list of all tags matching a specified regexp.
+
+ `M-x list-tags' reads the name of one of the files described by the
+selected tag table, and displays a list of all the tags defined in that
+file. The "file name" argument is really just a string to compare
+against the names recorded in the tag table; it is read as a string
+rather than as a file name. Therefore, completion and defaulting are
+not available, and you must enter the string the same way it appears in
+the tag table. Do not include a directory as part of the file name
+unless the file name recorded in the tag table includes a directory.
+
+ `M-x tags-apropos' is like `apropos' for tags. It reads a regexp,
+then finds all the tags in the selected tag table whose entries match
+that regexp, and displays the tag names found.
+
+
+File: emacs, Node: Fortran, Prev: Tags, Up: Programs
+
+Fortran Mode
+============
+
+ Fortran mode provides special motion commands for Fortran statements
+and subprograms, and indentation commands that understand Fortran
+conventions of nesting, line numbers and continuation statements.
+
+ Special commands for comments are provided because Fortran comments
+are unlike those of other languages.
+
+ Built-in abbrevs optionally save typing when you insert Fortran
+keywords.
+
+ Use `M-x fortran-mode' to switch to this major mode. Doing so calls
+the value of `fortran-mode-hook' as a function of no arguments if that
+variable has a value that is not `nil'.
+
+* Menu:
+
+* Motion: Fortran Motion. Moving point by statements or subprograms.
+* Indent: Fortran Indent. Indentation commands for Fortran.
+* Comments: Fortran Comments. Inserting and aligning comments.
+* Columns: Fortran Columns. Measuring columns for valid Fortran.
+* Abbrev: Fortran Abbrev. Built-in abbrevs for Fortran keywords.
+
+ Fortran mode was contributed by Michael Prange.
+
+
+File: emacs, Node: Fortran Motion, Next: Fortran Indent, Prev: Fortran, Up: Fortran
+
+Motion Commands
+---------------
+
+ Fortran mode provides special commands to move by subprograms
+(functions and subroutines) and by statements. There is also a command
+to put the region around one subprogram, convenient for killing it or
+moving it.
+
+`C-M-a'
+ Move to beginning of subprogram
+ (`beginning-of-fortran-subprogram').
+
+`C-M-e'
+ Move to end of subprogram (`end-of-fortran-subprogram').
+
+`C-M-h'
+ Put point at beginning of subprogram and mark at end
+ (`mark-fortran-subprogram').
+
+`C-c C-n'
+ Move to beginning of current or next statement
+ (`fortran-next-statement').
+
+`C-c C-p'
+ Move to beginning of current or previous statement
+ (`fortran-previous-statement').
+
+
+File: emacs, Node: Fortran Indent, Next: Fortran Comments, Prev: Fortran Motion, Up: Fortran
+
+Fortran Indentation
+-------------------
+
+ Special commands and features are needed for indenting Fortran code
+in order to make sure various syntactic entities (line numbers, comment
+line indicators and continuation line flags) appear in the columns that
+are required for standard Fortran.
+
+* Menu:
+
+* Commands: ForIndent Commands. Commands for indenting Fortran.
+* Numbers: ForIndent Num. How line numbers auto-indent.
+* Conv: ForIndent Conv. Conventions you must obey to avoid trouble.
+* Vars: ForIndent Vars. Variables controlling Fortran indent style.
+
+
+File: emacs, Node: ForIndent Commands, Next: ForIndent Num, Prev: Fortran Indent, Up: Fortran Indent
+
+Fortran Indentation Commands
+............................
+
+`TAB'
+ Indent the current line (`fortran-indent-line').
+
+`M-LFD'
+ Break the current line and set up a continuation line.
+
+`C-M-q'
+ Indent all the lines of the subprogram point is in
+ (`fortran-indent-subprogram').
+
+ TAB is redefined by Fortran mode to reindent the current line for
+Fortran (`fortran-indent-line'). Line numbers and continuation markers
+are indented to their required columns, and the body of the statement
+is independently indented based on its nesting in the program.
+
+ The key `C-M-q' is redefined as `fortran-indent-subprogram', a
+command to reindent all the lines of the Fortran subprogram (function or
+subroutine) containing point.
+
+ The key `M-LFD' is redefined as `fortran-split-line', a command to
+split a line in the appropriate fashion for Fortran. In a non-comment
+line, the second half becomes a continuation line and is indented
+accordingly. In a comment line, both halves become separate comment
+lines.
+
+
+File: emacs, Node: ForIndent Num, Next: ForIndent Conv, Prev: ForIndent Commands, Up: Fortran Indent
+
+Line Numbers and Continuation
+.............................
+
+ If a number is the first non-whitespace in the line, it is assumed
+to be a line number and is moved to columns 0 through 4. (Columns are
+always counted from 0 in GNU Emacs.) If the text on the line starts
+with the conventional Fortran continuation marker `$', it is moved to
+column 5. If the text begins with any non whitespace character in
+column 5, it is assumed to be an unconventional continuation marker and
+remains in column 5.
+
+ Line numbers of four digits or less are normally indented one space.
+This amount is controlled by the variable `fortran-line-number-indent'
+which is the maximum indentation a line number can have. Line numbers
+are indented to right-justify them to end in column 4 unless that would
+require more than this maximum indentation. The default value of the
+variable is 1.
+
+ Simply inserting a line number is enough to indent it according to
+these rules. As each digit is inserted, the indentation is recomputed.
+ To turn off this feature, set the variable
+`fortran-electric-line-number' to `nil'. Then inserting line numbers
+is like inserting anything else.
+
+
+File: emacs, Node: ForIndent Conv, Next: ForIndent Vars, Prev: ForIndent Num, Up: Fortran Indent
+
+Syntactic Conventions
+.....................
+
+ Fortran mode assumes that you follow certain conventions that
+simplify the task of understanding a Fortran program well enough to
+indent it properly:
+
+ * Two nested `do' loops never share a `continue' statement.
+
+ * The same character appears in column 5 of all continuation lines,
+ and this character is the value of the variable
+ `fortran-continuation-char'. By default, this character is `$'.
+
+If you fail to follow these conventions, the indentation commands may
+indent some lines unaesthetically. However, a correct Fortran program
+will retain its meaning when reindented even if the conventions are not
+followed.
+
+
+File: emacs, Node: ForIndent Vars, Prev: ForIndent Conv, Up: Fortran Indent
+
+Variables for Fortran Indentation
+.................................
+
+ Several additional variables control how Fortran indentation works.
+
+`fortran-do-indent'
+ Extra indentation within each level of `do' statement
+ (default 3).
+
+`fortran-if-indent'
+ Extra indentation within each level of `if' statement
+ (default 3).
+
+`fortran-continuation-indent'
+ Extra indentation for bodies of continuation lines (default 5).
+
+`fortran-check-all-num-for-matching-do'
+ If this is `nil', indentation assumes that each `do' statement
+ ends on a `continue' statement. Therefore, when computing
+ indentation for a statement other than `continue', it can save
+ time by not checking for a `do' statement ending there. If this is
+ non-`nil', indenting any numbered statement must check for a `do'
+ that ends there. The default is `nil'.
+
+`fortran-minimum-statement-indent'
+ Minimum indentation for fortran statements. For standard Fortran,
+ this is 6. Statement bodies will never be indented less than this
+ much.
+
+
+File: emacs, Node: Fortran Comments, Next: Fortran Columns, Prev: Fortran Indent, Up: Fortran
+
+Comments
+--------
+
+ The usual Emacs comment commands assume that a comment can follow a
+line of code. In Fortran, the standard comment syntax requires an
+entire line to be just a comment. Therefore, Fortran mode replaces the
+standard Emacs comment commands and defines some new variables.
+
+ Fortran mode can also handle a nonstandard comment syntax where
+comments start with `!' and can follow other text. Because only some
+Fortran compilers accept this syntax, Fortran mode will not insert such
+comments unless you have said in advance to do so. To do this, set the
+variable `comment-start' to `"!"' (*note Variables::.).
+
+`M-;'
+ Align comment or insert new comment (`fortran-comment-indent').
+
+`C-x ;'
+ Applies to nonstandard `!' comments only.
+
+`C-c ;'
+ Turn all lines of the region into comments, or (with arg) turn
+ them back into real code (`fortran-comment-region').
+
+ `M-;' in Fortran mode is redefined as the command
+`fortran-comment-indent'. Like the usual `M-;' command, this
+recognizes any kind of existing comment and aligns its text
+appropriately; if there is no existing comment, a comment is inserted
+and aligned. But inserting and aligning comments are not the same in
+Fortran mode as in other modes.
+
+ When a new comment must be inserted, if the current line is blank, a
+full-line comment is inserted. On a non-blank line, a nonstandard `!'
+comment is inserted if you have said you want to use them. Otherwise a
+full-line comment is inserted on a new line before the current line.
+
+ Nonstandard `!' comments are aligned like comments in other
+languages, but full-line comments are different. In a standard
+full-line comment, the comment delimiter itself must always appear in
+column zero. What can be aligned is the text within the comment. You
+can choose from three styles of alignment by setting the variable
+`fortran-comment-indent-style' to one of these values:
+
+`fixed'
+ The text is aligned at a fixed column, which is the value of
+ `fortran-comment-line-column'. This is the default.
+
+`relative'
+ The text is aligned as if it were a line of code, but with an
+ additional `fortran-comment-line-column' columns of indentation.
+
+`nil'
+ Text in full-line columns is not moved automatically.
+
+ In addition, you can specify the character to be used to indent
+within full-line comments by setting the variable
+`fortran-comment-indent-char' to the character you want to use.
+
+ Fortran mode introduces the two variables, `comment-line-start' and
+`comment-line-start-skip', which play for full-line comments the same
+roles played by `comment-start' and `comment-start-skip' for ordinary
+text-following comments. Normally these are set properly by Fortran
+mode so you do not need to change them.
+
+ The normal Emacs comment command `C-x ;' has not been redefined. If
+you use `!' comments, this command can be used with them. Otherwise it
+is useless in Fortran mode.
+
+ The command `C-c ;' (`fortran-comment-region') turns all the lines
+of the region into comments by inserting the string `C$$$' at the front
+of each one. With a numeric arg, the region is turned back into live
+code by deleting `C$$$' from the front of each line in it. The string
+used for these comments can be controlled by setting the variable
+`fortran-comment-region'. Note that here we have an example of a
+command and a variable with the same name; these two uses of the name
+never conflict because in Lisp and in Emacs it is always clear from the
+context which one is meant.
+
+
+File: emacs, Node: Fortran Columns, Next: Fortran Abbrev, Prev: Fortran Comments, Up: Fortran
+
+Columns
+-------
+
+`C-c C-r'
+ Displays a "column ruler" momentarily above the current line
+ (`fortran-column-ruler').
+
+`C-c C-w'
+ Splits the current window horizontally so that it is 72 columns
+ wide. This may help you avoid going over that limit
+ (`fortran-window-create').
+
+ The command `C-c C-r' (`fortran-column-ruler') shows a column ruler
+momentarily above the current line. The comment ruler is two lines of
+text that show you the locations of columns with special significance
+in Fortran programs. Square brackets show the limits of the columns for
+line numbers, and curly brackets show the limits of the columns for the
+statement body. Column numbers appear above them.
+
+ Note that the column numbers count from zero, as always in GNU
+Emacs. As a result, the numbers may not be those you are familiar
+with; but the actual positions in the line are standard Fortran.
+
+ The text used to display the column ruler is the value of the
+variable `fortran-comment-ruler'. By changing this variable, you can
+change the display.
+
+ For even more help, use `C-c C-w' (`fortran-window-create'), a
+command which splits the current window horizontally, making a window 72
+columns wide. By editing in this window you can immediately see when
+you make a line too wide to be correct Fortran.
+
+
+File: emacs, Node: Fortran Abbrev, Prev: Fortran Columns, Up: Fortran
+
+Fortran Keyword Abbrevs
+-----------------------
+
+ Fortran mode provides many built-in abbrevs for common keywords and
+declarations. These are the same sort of abbrev that you can define
+yourself. To use them, you must turn on Abbrev mode (*note Abbrevs::.).
+
+ The built-in abbrevs are unusual in one way: they all start with a
+semicolon. You cannot normally use semicolons in an abbrev, but Fortran
+mode makes this possible by changing the syntax of semicolon to "word
+constituent".
+
+ For example, one built-in Fortran abbrev is `;c' for `continue'. If
+you insert `;c' and then insert a punctuation character such as a space
+or a newline, the `;c' will change automatically to `continue',
+provided Abbrev mode is enabled.
+
+ Type `;?' or `;C-h' to display a list of all the built-in Fortran
+abbrevs and what they stand for.
+
+
+File: emacs, Node: Compiling/Testing, Next: Abbrevs, Prev: Programs, Up: Top
+
+Compiling and Testing Programs
+******************************
+
+ The previous chapter discusses the Emacs commands that are useful for
+making changes in programs. This chapter deals with commands that
+assist in the larger process of developing and maintaining programs.
+
+* Menu:
+
+* Compilation:: Compiling programs in languages other than Lisp
+ (C, Pascal, etc.)
+* Modes: Lisp Modes. Various modes for editing Lisp programs, with
+ different facilities for running the Lisp programs.
+* Libraries: Lisp Libraries. Creating Lisp programs to run in Emacs.
+* Interaction: Lisp Interaction. Executing Lisp in an Emacs buffer.
+* Eval: Lisp Eval. Executing a single Lisp expression in Emacs.
+* Debug: Lisp Debug. Debugging Lisp programs running in Emacs.
+* External Lisp:: Communicating through Emacs with a separate Lisp.
+
+
+File: emacs, Node: Compilation, Next: Lisp Modes, Prev: Compiling/Testing, Up: Compiling/Testing
+
+Running `make', or Compilers Generally
+======================================
+
+ Emacs can run compilers for noninteractive languages such as C and
+Fortran as inferior processes, feeding the error log into an Emacs
+buffer. It can also parse the error messages and visit the files in
+which errors are found, moving point right to the line where the error
+occurred.
+
+`M-x compile'
+ Run a compiler asynchronously under Emacs, with error messages to
+ `*compilation*' buffer.
+
+`M-x grep'
+ Run `grep' asynchronously under Emacs, with matching lines listed
+ in the buffer named `*compilation*'.
+
+`M-x kill-compilation'
+`M-x kill-grep'
+ Kill the running compilation or `grep' subprocess.
+
+`C-x `'
+ Visit the locus of the next compiler error message or `grep' match.
+
+ To run `make' or another compiler, do `M-x compile'. This command
+reads a shell command line using the minibuffer, and then executes the
+specified command line in an inferior shell with output going to the
+buffer named `*compilation*'. The current buffer's default directory
+is used as the working directory for the execution of the command;
+normally, therefore, the makefile comes from this directory.
+
+ When the shell command line is read, the minibuffer appears
+containing a default command line, which is the command you used the
+last time you did `M-x compile'. If you type just RET, the same
+command line is used again. The first `M-x compile' provides `make -k'
+as the default. The default is taken from the variable
+`compile-command'; if the appropriate compilation command for a file is
+something other than `make -k', it can be useful to have the file
+specify a local value for `compile-command' (*note File Variables::.).
+
+ Starting a compilation causes the buffer `*compilation*' to be
+displayed in another window but not selected. Its mode line tells you
+whether compilation is finished, with the word `run' or `exit' inside
+the parentheses. You do not have to keep this buffer visible;
+compilation continues in any case.
+
+ To kill the compilation process, do `M-x kill-compilation'. You will
+see that the mode line of the `*compilation*' buffer changes to say
+`signal' instead of `run'. Starting a new compilation also kills any
+running compilation, as only one can exist at any time. However, this
+requires confirmation before actually killing a compilation that is
+running.
+
+ To parse the compiler error messages, type `C-x `' (`next-error').
+The character following the `C-x' is the grave accent, not the single
+quote. This command displays the buffer `*compilation*' in one window
+and the buffer in which the next error occurred in another window.
+Point in that buffer is moved to the line where the error was found.
+The corresponding error message is scrolled to the top of the window in
+which `*compilation*' is displayed.
+
+ The first time `C-x `' is used after the start of a compilation, it
+parses all the error messages, visits all the files that have error
+messages, and makes markers pointing at the lines that the error
+messages refer to. Then it moves to the first error message location.
+Subsequent uses of `C-x `' advance down the data set up by the first
+use. When the preparsed error messages are exhausted, the next `C-x `'
+checks for any more error messages that have come in; this is useful if
+you start editing the compiler errors while the compilation is still
+going on. If no more error messages have come in, `C-x `' reports an
+error.
+
+ `C-u C-x `' discards the preparsed error message data and parses the
+`*compilation*' buffer over again, then displaying the first error.
+This way, you can process the same set of errors again.
+
+ Instead of running a compiler, you can run `grep' and see the lines
+on which matches were found. To do this, type `M-x grep' with an
+argument line that contains the same arguments you would give `grep'
+when running it normally: a `grep'-style regexp (usually in
+singlequotes to quote the shell's special characters) followed by
+filenames which may use wildcards. The output from `grep' goes in the
+`*compilation*' buffer and the lines that matched can be found with
+`C-x `' as if they were compilation errors.
+
+ Note: a shell is used to run the compile command, but the shell is
+told that it should be noninteractive. This means in particular that
+the shell starts up with no prompt. If you find your usual shell
+prompt making an unsightly appearance in the `*compilation*' buffer, it
+means you have made a mistake in your shell's init file (`.cshrc' or
+`.shrc' or ...) by setting the prompt unconditionally. The shell init
+file should set the prompt only if there already is a prompt.
+
+ Here is how to do it in `csh':
+
+ if ($?prompt) set prompt = ...
+
+ Here is how to do it in the Bourne-Again shell:
+
+ if [ ! "$PS1" ]; then
+ PS1=...
+ fi
+
+
+File: emacs, Node: Lisp Modes, Next: Lisp Libraries, Prev: Compilation, Up: Compiling/Testing
+
+Major Modes for Lisp
+====================
+
+ Emacs has four different major modes for Lisp. They are the same in
+terms of editing commands, but differ in the commands for executing Lisp
+expressions.
+
+Emacs-Lisp mode
+ The mode for editing source files of programs to run in Emacs Lisp.
+ This mode defines `C-M-x' to evaluate the current defun. *Note
+ Lisp Libraries::.
+
+Lisp Interaction mode
+ The mode for an interactive session with Emacs Lisp. It defines
+ LFD to evaluate the sexp before point and insert its value in the
+ buffer. *Note Lisp Interaction::.
+
+Lisp mode
+ The mode for editing source files of programs that run in Lisps
+ other than Emacs Lisp. This mode defines `C-M-x' to send the
+ current defun to an inferior Lisp process. *Note External Lisp::.
+
+Inferior Lisp mode
+ The mode for an interactive session with an inferior Lisp process.
+ This mode combines the special features of Lisp mode and Shell mode
+ (*note Shell Mode::.).
+
+Scheme mode
+ Like Lisp mode but for Scheme programs.
+
+Inferior Scheme mode
+ The mode for an interactive session with an inferior Scheme
+ process.
+
+
+File: emacs, Node: Lisp Libraries, Next: Lisp Eval, Prev: Lisp Modes, Up: Compiling/Testing
+
+Libraries of Lisp Code for Emacs
+================================
+
+ Lisp code for Emacs editing commands is stored in files whose names
+conventionally end in `.el'. This ending tells Emacs to edit them in
+Emacs-Lisp mode (*note Lisp Modes::.).
+
+* Menu:
+
+* Loading:: Loading libraries of Lisp code into Emacs for use.
+* Compiling Libraries:: Compiling a library makes it load and run faster.
+* Mocklisp:: Converting Mocklisp to Lisp so GNU Emacs can run it.
+
+
+File: emacs, Node: Loading, Next: Compiling Libraries, Prev: Lisp Libraries, Up: Lisp Libraries
+
+Loading Libraries
+-----------------
+
+ To execute a file of Emacs Lisp, use `M-x load-file'. This command
+reads a file name using the minibuffer and then executes the contents of
+that file as Lisp code. It is not necessary to visit the file first;
+in any case, this command reads the file as found on disk, not text in
+an Emacs buffer.
+
+ Once a file of Lisp code is installed in the Emacs Lisp library
+directories, users can load it using `M-x load-library'. Programs can
+load it by calling `load-library', or with `load', a more primitive
+function that is similar but accepts some additional arguments.
+
+ `M-x load-library' differs from `M-x load-file' in that it searches
+a sequence of directories and tries three file names in each directory.
+ The three names are, first, the specified name with `.elc' appended;
+second, with `.el' appended; third, the specified name alone. A `.elc'
+file would be the result of compiling the Lisp file into byte code; it
+is loaded if possible in preference to the Lisp file itself because the
+compiled file will load and run faster.
+
+ Because the argument to `load-library' is usually not in itself a
+valid file name, file name completion is not available. Indeed, when
+using this command, you usually do not know exactly what file name will
+be used.
+
+ The sequence of directories searched by `M-x load-library' is
+specified by the variable `load-path', a list of strings that are
+directory names. The default value of the list contains the directory
+where the Lisp code for Emacs itself is stored. If you have libraries
+of your own, put them in a single directory and add that directory to
+`load-path'. `nil' in this list stands for the current default
+directory, but it is probably not a good idea to put `nil' in the list.
+ If you find yourself wishing that `nil' were in the list, most likely
+what you really want to do is use `M-x load-file' this once.
+
+ Often you do not have to give any command to load a library, because
+the commands defined in the library are set up to "autoload" that
+library. Running any of those commands causes `load' to be called to
+load the library; this replaces the autoload definitions with the real
+ones from the library.
+
+ If autoloading a file does not finish, either because of an error or
+because of a `C-g' quit, all function definitions made by the file are
+undone automatically. So are any calls to `provide'. As a consequence,
+if you use one of the autoloadable commands again, the entire file will
+be loaded a second time. This prevents problems where the command is no
+longer autoloading but it works wrong because not all the file was
+loaded. Function definitions are undone only for autoloading; explicit
+calls to `load' do not undo anything if loading is not completed.
+
+
+File: emacs, Node: Compiling Libraries, Next: Mocklisp, Prev: Loading, Up: Lisp Libraries
+
+Compiling Libraries
+-------------------
+
+ Emacs Lisp code can be compiled into byte-code which loads faster,
+takes up less space when loaded, and executes faster.
+
+ The way to make a byte-code compiled file from an Emacs-Lisp source
+file is with `M-x byte-compile-file'. The default argument for this
+function is the file visited in the current buffer. It reads the
+specified file, compiles it into byte code, and writes an output file
+whose name is made by appending `c' to the input file name. Thus, the
+file `rmail.el' would be compiled into `rmail.elc'.
+
+ To recompile the changed Lisp files in a directory, use `M-x
+byte-recompile-directory'. Specify just the directory name as an
+argument. Each `.el' file that has been byte-compiled before is
+byte-compiled again if it has changed since the previous compilation.
+A numeric argument to this command tells it to offer to compile each
+`.el' file that has not already been compiled. You must answer `y' or
+`n' to each offer.
+
+ Emacs can be invoked noninteractively from the shell to do byte
+compilation with the aid of the function `batch-byte-compile'. In this
+case, the files to be compiled are specified with command-line
+arguments. Use a shell command of the form
+
+ emacs -batch -f batch-byte-compile FILES...
+
+ Directory names may also be given as arguments;
+`byte-recompile-directory' is invoked (in effect) on each such
+directory. `batch-byte-compile' uses all the remaining command-line
+arguments as file or directory names, then kills the Emacs process.
+
+ `M-x disassemble' explains the result of byte compilation. Its
+argument is a function name. It displays the byte-compiled code in a
+help window in symbolic form, one instruction per line. If the
+instruction refers to a variable or constant, that is shown too.
+
+
+File: emacs, Node: Mocklisp, Prev: Compiling Libraries, Up: Lisp Libraries
+
+Converting Mocklisp to Lisp
+---------------------------
+
+ GNU Emacs can run Mocklisp files by converting them to Emacs Lisp
+first. To convert a Mocklisp file, visit it and then type `M-x
+convert-mocklisp-buffer'. Then save the resulting buffer of Lisp file
+in a file whose name ends in `.el' and use the new file as a Lisp
+library.
+
+ It does not currently work to byte-compile converted Mocklisp code.
+This is because converted Mocklisp code uses some special Lisp features
+to deal with Mocklisp's incompatible ideas of how arguments are
+evaluated and which values signify "true" or "false".
+
+ \ No newline at end of file
diff --git a/info/emacs-9 b/info/emacs-9
new file mode 100644
index 00000000000..95456103ba1
--- /dev/null
+++ b/info/emacs-9
@@ -0,0 +1,1136 @@
+This is Info file ../info/emacs, produced by Makeinfo-1.49 from the
+input file emacs.texi.
+
+ This file documents the GNU Emacs editor.
+
+ Copyright (C) 1985, 1986, 1988, 1992 Richard M. Stallman.
+
+ Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+ Permission is granted to copy and distribute modified versions of
+this manual under the conditions for verbatim copying, provided also
+that the sections entitled "The GNU Manifesto", "Distribution" and "GNU
+General Public License" are included exactly as in the original, and
+provided that the entire resulting derived work is distributed under the
+terms of a permission notice identical to this one.
+
+ Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that the sections entitled "The GNU Manifesto",
+"Distribution" and "GNU General Public License" may be included in a
+translation approved by the author instead of in the original English.
+
+
+File: emacs, Node: Lisp Eval, Next: Lisp Debug, Prev: Lisp Libraries, Up: Compiling/Testing
+
+Evaluating Emacs-Lisp Expressions
+=================================
+
+ Lisp programs intended to be run in Emacs should be edited in
+Emacs-Lisp mode; this will happen automatically for file names ending
+in `.el'. By contrast, Lisp mode itself is used for editing Lisp
+programs intended for other Lisp systems. Emacs-Lisp mode can be
+selected with the command `M-x emacs-lisp-mode'.
+
+ For testing of Lisp programs to run in Emacs, it is useful to be
+able to evaluate part of the program as it is found in the Emacs
+buffer. For example, after changing the text of a Lisp function
+definition, evaluating the definition installs the change for future
+calls to the function. Evaluation of Lisp expressions is also useful in
+any kind of editing task for invoking noninteractive functions
+(functions that are not commands).
+
+`M-ESC'
+ Read a Lisp expression in the minibuffer, evaluate it, and print
+ the value in the minibuffer (`eval-expression').
+
+`C-x C-e'
+ Evaluate the Lisp expression before point, and print the value in
+ the minibuffer (`eval-last-sexp').
+
+`C-M-x'
+ Evaluate the defun containing or after point, and print the value
+ in the minibuffer (`eval-defun').
+
+`M-x eval-region'
+ Evaluate all the Lisp expressions in the region.
+
+`M-x eval-current-buffer'
+ Evaluate all the Lisp expressions in the buffer.
+
+ `M-ESC' (`eval-expression') is the most basic command for evaluating
+a Lisp expression interactively. It reads the expression using the
+minibuffer, so you can execute any expression on a buffer regardless of
+what the buffer contains. When the expression is evaluated, the current
+buffer is once again the buffer that was current when `M-ESC' was typed.
+
+ `M-ESC' can easily confuse users who do not understand it,
+especially on keyboards with autorepeat where it can result from holding
+down the ESC key for too long. Therefore, `eval-expression' is
+normally a disabled command. Attempting to use this command asks for
+confirmation and gives you the option of enabling it; once you enable
+the command, confirmation will no longer be required for it. *Note
+Disabling::.
+
+ In Emacs-Lisp mode, the key `C-M-x' is bound to the function
+`eval-defun', which parses the defun containing or following point as a
+Lisp expression and evaluates it. The value is printed in the echo
+area. This command is convenient for installing in the Lisp
+environment changes that you have just made in the text of a function
+definition.
+
+ The command `C-x C-e' (`eval-last-sexp') performs a similar job but
+is available in all major modes, not just Emacs-Lisp mode. It finds
+the sexp before point, reads it as a Lisp expression, evaluates it, and
+prints the value in the echo area. It is sometimes useful to type in an
+expression and then, with point still after it, type `C-x C-e'.
+
+ If `C-M-x' or `C-x C-e' is given a numeric argument, it prints the
+value by insertion into the current buffer at point, rather than in the
+echo area. The argument value does not matter.
+
+ The most general command for evaluating Lisp expressions from a
+buffer is `eval-region'. `M-x eval-region' parses the text of the
+region as one or more Lisp expressions, evaluating them one by one.
+`M-x eval-current-buffer' is similar but evaluates the entire buffer.
+This is a reasonable way to install the contents of a file of Lisp code
+that you are just ready to test. After finding and fixing a bug, use
+`C-M-x' on each function that you change, to keep the Lisp world in
+step with the source file.
+
+
+File: emacs, Node: Lisp Debug, Next: Lisp Interaction, Prev: Lisp Eval, Up: Compiling/Testing
+
+The Emacs-Lisp Debugger
+=======================
+
+ GNU Emacs contains a debugger for Lisp programs executing inside it.
+This debugger is normally not used; many commands frequently get Lisp
+errors when invoked in inappropriate contexts (such as `C-f' at the end
+of the buffer) and it would be very unpleasant for that to enter a
+special debugging mode. When you want to make Lisp errors invoke the
+debugger, you must set the variable `debug-on-error' to non-`nil'.
+Quitting with `C-g' is not considered an error, and `debug-on-error'
+has no effect on the handling of `C-g'. However, if you set
+`debug-on-quit' non-`nil', `C-g' will invoke the debugger. This can be
+useful for debugging an infinite loop; type `C-g' once the loop has had
+time to reach its steady state. `debug-on-quit' has no effect on
+errors.
+
+ You can also cause the debugger to be entered when a specified
+function is called, or at a particular place in Lisp code. Use `M-x
+debug-on-entry' with argument FUN-NAME to cause function FUN-NAME to
+enter the debugger as soon as it is called. Use `M-x
+cancel-debug-on-entry' to make the function stop entering the debugger
+when called. (Redefining the function also does this.) To enter the
+debugger from some other place in Lisp code, you must insert the
+expression `(debug)' there and install the changed code with `C-M-x'.
+*Note Lisp Eval::.
+
+ When the debugger is entered, it displays the previously selected
+buffer in one window and a buffer named `*Backtrace*' in another
+window. The backtrace buffer contains one line for each level of Lisp
+function execution currently going on. At the beginning of this buffer
+is a message describing the reason that the debugger was invoked (such
+as, what error message if it was invoked due to an error).
+
+ The backtrace buffer is read-only, and is in a special major mode,
+Backtrace mode, in which letters are defined as debugger commands. The
+usual Emacs editing commands are available; you can switch windows to
+examine the buffer that was being edited at the time of the error, and
+you can also switch buffers, visit files, and do any other sort of
+editing. However, the debugger is a recursive editing level (*note
+Recursive Edit::.) and it is wise to go back to the backtrace buffer
+and exit the debugger officially when you don't want to use it any
+more. Exiting the debugger kills the backtrace buffer.
+
+ The contents of the backtrace buffer show you the functions that are
+executing and the arguments that were given to them. It has the
+additional purpose of allowing you to specify a stack frame by moving
+point to the line describing that frame. The frame whose line point is
+on is considered the "current frame". Some of the debugger commands
+operate on the current frame. Debugger commands are mainly used for
+stepping through code an expression at a time. Here is a list of them.
+
+`c'
+ Exit the debugger and continue execution. In most cases,
+ execution of the program continues as if the debugger had never
+ been entered (aside from the effect of any variables or data
+ structures you may have changed while inside the debugger). This
+ includes entry to the debugger due to function entry or exit,
+ explicit invocation, quitting or certain errors. Most errors
+ cannot be continued; trying to continue one of them causes the
+ same error to occur again.
+
+`d'
+ Continue execution, but enter the debugger the next time a Lisp
+ function is called. This allows you to step through the
+ subexpressions of an expression, seeing what values the
+ subexpressions compute and what else they do.
+
+ The stack frame made for the function call which enters the
+ debugger in this way will be flagged automatically for the
+ debugger to be called when the frame is exited. You can use the
+ `u' command to cancel this flag.
+
+`b'
+ Set up to enter the debugger when the current frame is exited.
+ Frames that will invoke the debugger on exit are flagged with
+ stars.
+
+`u'
+ Don't enter the debugger when the current frame is exited. This
+ cancels a `b' command on that frame.
+
+`e'
+ Read a Lisp expression in the minibuffer, evaluate it, and print
+ the value in the echo area. This is the same as the command
+ `M-ESC', except that `e' is not normally disabled like `M-ESC'.
+
+`q'
+ Terminate the program being debugged; return to top-level Emacs
+ command execution.
+
+ If the debugger was entered due to a `C-g' but you really want to
+ quit, not to debug, use the `q' command.
+
+`r'
+ Return a value from the debugger. The value is computed by
+ reading an expression with the minibuffer and evaluating it.
+
+ The value returned by the debugger makes a difference when the
+ debugger was invoked due to exit from a Lisp call frame (as
+ requested with `b'); then the value specified in the `r' command
+ is used as the value of that frame.
+
+ The debugger's return value also matters with many errors. For
+ example, `wrong-type-argument' errors will use the debugger's
+ return value instead of the invalid argument; `no-catch' errors
+ will use the debugger value as a throw tag instead of the tag that
+ was not found. If an error was signaled by calling the Lisp
+ function `signal', the debugger's return value is returned as the
+ value of `signal'.
+
+
+File: emacs, Node: Lisp Interaction, Next: External Lisp, Prev: Lisp Debug, Up: Compiling/Testing
+
+Lisp Interaction Buffers
+========================
+
+ The buffer `*scratch*' which is selected when Emacs starts up is
+provided for evaluating Lisp expressions interactively inside Emacs.
+Both the expressions you evaluate and their output goes in the buffer.
+
+ The `*scratch*' buffer's major mode is Lisp Interaction mode, which
+is the same as Emacs-Lisp mode except for one command, LFD. In
+Emacs-Lisp mode, LFD is an indentation command, as usual. In Lisp
+Interaction mode, LFD is bound to `eval-print-last-sexp'. This
+function reads the Lisp expression before point, evaluates it, and
+inserts the value in printed representation before point.
+
+ Thus, the way to use the `*scratch*' buffer is to insert Lisp
+expressions at the end, ending each one with LFD so that it will be
+evaluated. The result is a complete typescript of the expressions you
+have evaluated and their values.
+
+ The rationale for this feature is that Emacs must have a buffer when
+it starts up, but that buffer is not useful for editing files since a
+new buffer is made for every file that you visit. The Lisp interpreter
+typescript is the most useful thing I can think of for the initial
+buffer to do. `M-x lisp-interaction-mode' will put any buffer in Lisp
+Interaction mode.
+
+
+File: emacs, Node: External Lisp, Prev: Lisp Interaction, Up: Compiling/Testing
+
+Running an External Lisp
+========================
+
+ Emacs has facilities for running programs in other Lisp systems.
+You can run a Lisp process as an inferior of Emacs, and pass
+expressions to it to be evaluated. You can also pass changed function
+definitions directly from the Emacs buffers in which you edit the Lisp
+programs to the inferior Lisp process.
+
+ To run an inferior Lisp process, type `M-x run-lisp'. This runs the
+program named `lisp', the same program you would run by typing `lisp'
+as a shell command, with both input and output going through an Emacs
+buffer named `*lisp*'. That is to say, any "terminal output" from Lisp
+will go into the buffer, advancing point, and any "terminal input" for
+Lisp comes from text in the buffer. To give input to Lisp, go to the
+end of the buffer and type the input, terminated by RET. The `*lisp*'
+buffer is in Inferior Lisp mode, a mode which has all the special
+characteristics of Lisp mode and Shell mode (*note Shell Mode::.).
+
+ For the source files of programs to run in external Lisps, use Lisp
+mode. This mode can be selected with `M-x lisp-mode', and is used
+automatically for files whose names end in `.l' or `.lisp', as most Lisp
+systems usually expect.
+
+ When you edit a function in a Lisp program you are running, the
+easiest way to send the changed definition to the inferior Lisp process
+is the key `C-M-x'. In Lisp mode, this runs the function
+`lisp-send-defun', which finds the defun around or following point and
+sends it as input to the Lisp process. (Emacs can send input to any
+inferior process regardless of what buffer is current.)
+
+ Contrast the meanings of `C-M-x' in Lisp mode (for editing programs
+to be run in another Lisp system) and Emacs-Lisp mode (for editing Lisp
+programs to be run in Emacs): in both modes it has the effect of
+installing the function definition that point is in, but the way of
+doing so is different according to where the relevant Lisp environment
+is found. *Note Lisp Modes::.
+
+
+File: emacs, Node: Abbrevs, Next: Picture, Prev: Compiling/Testing, Up: Top
+
+Abbrevs
+*******
+
+ An "abbrev" is a word which "expands", if you insert it, into some
+different text. Abbrevs are defined by the user to expand in specific
+ways. For example, you might define `foo' as an abbrev expanding to
+`find outer otter'. With this abbrev defined, you would be able to get
+`find outer otter ' into the buffer by typing `f o o SPC'.
+
+ Abbrevs expand only when Abbrev mode (a minor mode) is enabled.
+Disabling Abbrev mode does not cause abbrev definitions to be forgotten,
+but they do not expand until Abbrev mode is enabled again. The command
+`M-x abbrev-mode' toggles Abbrev mode; with a numeric argument, it
+turns Abbrev mode on if the argument is positive, off otherwise. *Note
+Minor Modes::. `abbrev-mode' is also a variable; Abbrev mode is on
+when the variable is non-`nil'. The variable `abbrev-mode'
+automatically becomes local to the current buffer when it is set.
+
+ Abbrev definitions can be "mode-specific"--active only in one major
+mode. Abbrevs can also have "global" definitions that are active in
+all major modes. The same abbrev can have a global definition and
+various mode-specific definitions for different major modes. A mode
+specific definition for the current major mode overrides a global
+definition.
+
+ Abbrevs can be defined interactively during the editing session.
+Lists of abbrev definitions can also be saved in files and reloaded in
+later sessions. Some users keep extensive lists of abbrevs that they
+load in every session.
+
+ A second kind of abbreviation facility is called the "dynamic
+expansion". Dynamic abbrev expansion happens only when you give an
+explicit command and the result of the expansion depends only on the
+current contents of the buffer. *Note Dynamic Abbrevs::.
+
+* Menu:
+
+* Defining Abbrevs:: Defining an abbrev, so it will expand when typed.
+* Expanding Abbrevs:: Controlling expansion: prefixes, canceling expansion.
+* Editing Abbrevs:: Viewing or editing the entire list of defined abbrevs.
+* Saving Abbrevs:: Saving the entire list of abbrevs for another session.
+* Dynamic Abbrevs:: Abbreviations for words already in the buffer.
+
+
+File: emacs, Node: Defining Abbrevs, Next: Expanding Abbrevs, Prev: Abbrevs, Up: Abbrevs
+
+Defining Abbrevs
+================
+
+`C-x +'
+ Define an abbrev to expand into some text before point
+ (`add-global-abbrev').
+
+`C-x C-a'
+ Similar, but define an abbrev available only in the current major
+ mode (`add-mode-abbrev').
+
+`C-x -'
+ Define a word in the buffer as an abbrev
+ (`inverse-add-global-abbrev').
+
+`C-x C-h'
+ Define a word in the buffer as a mode-specific abbrev
+ (`inverse-add-mode-abbrev').
+
+`M-x kill-all-abbrevs'
+ After this command, there are no abbrev definitions in effect.
+
+ The usual way to define an abbrev is to enter the text you want the
+abbrev to expand to, position point after it, and type `C-x +'
+(`add-global-abbrev'). This reads the abbrev itself using the
+minibuffer, and then defines it as an abbrev for one or more words
+before point. Use a numeric argument to say how many words before
+point should be taken as the expansion. For example, to define the
+abbrev `foo' as mentioned above, insert the text `find outer otter' and
+then type `C-u 3 C-x + f o o RET'.
+
+ An argument of zero to `C-x +' means to use the contents of the
+region as the expansion of the abbrev being defined.
+
+ The command `C-x C-a' (`add-mode-abbrev') is similar, but defines a
+mode-specific abbrev. Mode specific abbrevs are active only in a
+particular major mode. `C-x C-a' defines an abbrev for the major mode
+in effect at the time `C-x C-a' is typed. The arguments work the same
+as for `C-x +'.
+
+ If the text of the abbrev you want is already in the buffer instead
+of the expansion, use command `C-x -' (`inverse-add-global-abbrev')
+instead of `C-x +', or use `C-x C-h' (`inverse-add-mode-abbrev')
+instead of `C-x C-a'. These commands are called "inverse" because they
+invert the meaning of the argument found in the buffer and the argument
+read using the minibuffer.
+
+ To change the definition of an abbrev, just add the new definition.
+You will be asked to confirm if the abbrev has a prior definition. To
+remove an abbrev definition, give a negative argument to `C-x +' or `C-x
+C-a'. You must choose the command to specify whether to kill a global
+definition or a mode-specific definition for the current mode, since
+those two definitions are independent for one abbrev.
+
+ `M-x kill-all-abbrevs' removes all the abbrev definitions there are.
+
+
+File: emacs, Node: Expanding Abbrevs, Next: Editing Abbrevs, Prev: Defining Abbrevs, Up: Abbrevs
+
+Controlling Abbrev Expansion
+============================
+
+ An abbrev expands whenever it is present in the buffer just before
+point and a self-inserting punctuation character (SPC, comma, etc.) is
+typed. Most often the way an abbrev is used is to insert the abbrev
+followed by punctuation.
+
+ Abbrev expansion preserves case; thus, `foo' expands into `find
+outer otter'; `Foo' into `Find outer otter', and `FOO' into `FIND OUTER
+OTTER' or `Find Outer Otter' according to the variable
+`abbrev-all-caps' (a non-`nil' value chooses the first of the two
+expansions).
+
+ These two commands are used to control abbrev expansion:
+
+`M-''
+ Separate a prefix from a following abbrev to be expanded
+ (`abbrev-prefix-mark').
+
+`C-x ''
+ Expand the abbrev before point (`expand-abbrev'). This is
+ effective even when Abbrev mode is not enabled.
+
+`M-x unexpand-abbrev'
+ Undo last abbrev expansion.
+
+`M-x expand-region-abbrevs'
+ Expand some or all abbrevs found in the region.
+
+ You may wish to expand an abbrev with a prefix attached; for
+example, if `cnst' expands into `construction', you might want to use
+it to enter `reconstruction'. It does not work to type `recnst',
+because that is not necessarily a defined abbrev. What does work is to
+use the command `M-'' (`abbrev-prefix-mark') in between the prefix `re'
+and the abbrev `cnst'. First, insert `re'. Then type `M-''; this
+inserts a minus sign in the buffer to indicate that it has done its
+work. Then insert the abbrev `cnst'; the buffer now contains
+`re-cnst'. Now insert a punctuation character to expand the abbrev
+`cnst' into `construction'. The minus sign is deleted at this point,
+because `M-'' left word for this to be done. The resulting text is the
+desired `reconstruction'.
+
+ If you actually want the text of the abbrev in the buffer, rather
+than its expansion, you can accomplish this by inserting the following
+punctuation with `C-q'. Thus, `foo C-q -' leaves `foo-' in the buffer.
+
+ If you expand an abbrev by mistake, you can undo the expansion
+(replace the expansion by the original abbrev text) with `M-x
+unexpand-abbrev'. `C-_' (`undo') can also be used to undo the
+expansion; but first it will undo the insertion of the following
+punctuation character!
+
+ `M-x expand-region-abbrevs' searches through the region for defined
+abbrevs, and for each one found offers to replace it with its expansion.
+This command is useful if you have typed in text using abbrevs but
+forgot to turn on Abbrev mode first. It may also be useful together
+with a special set of abbrev definitions for making several global
+replacements at once. This command is effective even if Abbrev mode is
+not enabled.
+
+
+File: emacs, Node: Editing Abbrevs, Next: Saving Abbrevs, Prev: Expanding Abbrevs, Up: Abbrevs
+
+Examining and Editing Abbrevs
+=============================
+
+`M-x list-abbrevs'
+ Print a list of all abbrev definitions.
+
+`M-x edit-abbrevs'
+ Edit a list of abbrevs; you can add, alter or remove definitions.
+
+ The output from `M-x list-abbrevs' looks like this:
+
+ (lisp-mode-abbrev-table)
+ "dk" 0 "define-key"
+ (global-abbrev-table)
+ "dfn" 0 "definition"
+
+(Some blank lines of no semantic significance, and some other abbrev
+tables, have been omitted.)
+
+ A line containing a name in parentheses is the header for abbrevs in
+a particular abbrev table; `global-abbrev-table' contains all the global
+abbrevs, and the other abbrev tables that are named after major modes
+contain the mode-specific abbrevs.
+
+ Within each abbrev table, each nonblank line defines one abbrev. The
+word at the beginning is the abbrev. The number that appears is the
+number of times the abbrev has been expanded. Emacs keeps track of
+this to help you see which abbrevs you actually use, in case you decide
+to eliminate those that you don't use often. The string at the end of
+the line is the expansion.
+
+ `M-x edit-abbrevs' allows you to add, change or kill abbrev
+definitions by editing a list of them in an Emacs buffer. The list has
+the same format described above. The buffer of abbrevs is called
+`*Abbrevs*', and is in Edit-Abbrevs mode. This mode redefines the key
+`C-c C-c' to install the abbrev definitions as specified in the buffer.
+ The command that does this is `edit-abbrevs-redefine'. Any abbrevs
+not described in the buffer are eliminated when this is done.
+
+ `edit-abbrevs' is actually the same as `list-abbrevs' except that it
+selects the buffer `*Abbrevs*' whereas `list-abbrevs' merely displays
+it in another window.
+
+
+File: emacs, Node: Saving Abbrevs, Next: Dynamic Abbrevs, Prev: Editing Abbrevs, Up: Abbrevs
+
+Saving Abbrevs
+==============
+
+ These commands allow you to keep abbrev definitions between editing
+sessions.
+
+`M-x write-abbrev-file'
+ Write a file describing all defined abbrevs.
+
+`M-x read-abbrev-file'
+ Read such a file and define abbrevs as specified there.
+
+`M-x quietly-read-abbrev-file'
+ Similar but do not display a message about what is going on.
+
+`M-x define-abbrevs'
+ Define abbrevs from buffer.
+
+`M-x insert-abbrevs'
+ Insert all abbrevs and their expansions into the buffer.
+
+ `M-x write-abbrev-file' reads a file name using the minibuffer and
+writes a description of all current abbrev definitions into that file.
+The text stored in the file looks like the output of `M-x list-abbrevs'.
+This is used to save abbrev definitions for use in a later session.
+
+ `M-x read-abbrev-file' reads a file name using the minibuffer and
+reads the file, defining abbrevs according to the contents of the file.
+`M-x quietly-read-abbrev-file' is the same except that it does not
+display a message in the echo area saying that it is doing its work; it
+is actually useful primarily in the `.emacs' file. If an empty
+argument is given to either of these functions, the file name used is
+the value of the variable `abbrev-file-name', which is by default
+`"~/.abbrev_defs"'.
+
+ Emacs will offer to save abbrevs automatically if you have changed
+any of them, whenever it offers to save all files (for `C-x s' or `C-x
+C-c'). This feature can be inhibited by setting the variable
+`save-abbrevs' to `nil'.
+
+ The commands `M-x insert-abbrevs' and `M-x define-abbrevs' are
+similar to the previous commands but work on text in an Emacs buffer.
+`M-x insert-abbrevs' inserts text into the current buffer before point,
+describing all current abbrev definitions; `M-x define-abbrevs' parses
+the entire current buffer and defines abbrevs accordingly.
+
+
+File: emacs, Node: Dynamic Abbrevs, Prev: Saving Abbrevs, Up: Abbrevs
+
+Dynamic Abbrev Expansion
+========================
+
+ The abbrev facility described above operates automatically as you
+insert text, but all abbrevs must be defined explicitly. By contrast,
+"dynamic abbrevs" allow the meanings of abbrevs to be determined
+automatically from the contents of the buffer, but dynamic abbrev
+expansion happens only when you request it explicitly.
+
+`M-/'
+ Expand the word in the buffer before point as a "dynamic abbrev",
+ by searching in the buffer for words starting with that
+ abbreviation (`dabbrev-expand').
+
+ For example, if the buffer contains `does this follow ' and you type
+`f o M-/', the effect is to insert `follow' because that is the last
+word in the buffer that starts with `fo'. A numeric argument to `M-/'
+says to take the second, third, etc. distinct expansion found looking
+backward from point. Repeating `M-/' searches for an alternative
+expansion by looking farther back. After the part of the buffer
+preceding point has been considered, the part of the buffer after point
+is searched.
+
+ Dynamic abbrev expansion is completely independent of Abbrev mode;
+the expansion of a word with `M-/' is completely independent of whether
+it has a definition as an ordinary abbrev.
+
+
+File: emacs, Node: Picture, Next: Sending Mail, Prev: Abbrevs, Up: Top
+
+Editing Pictures
+****************
+
+ If you want to create a picture made out of text characters (for
+example, a picture of the division of a register into fields, as a
+comment in a program), use the command `edit-picture' to enter Picture
+mode.
+
+ In Picture mode, editing is based on the "quarter-plane" model of
+text, according to which the text characters lie studded on an area that
+stretches infinitely far to the right and downward. The concept of the
+end of a line does not exist in this model; the most you can say is
+where the last nonblank character on the line is found.
+
+ Of course, Emacs really always considers text as a sequence of
+characters, and lines really do have ends. But in Picture mode most
+frequently-used keys are rebound to commands that simulate the
+quarter-plane model of text. They do this by inserting spaces or by
+converting tabs to spaces.
+
+ Most of the basic editing commands of Emacs are redefined by Picture
+mode to do essentially the same thing but in a quarter-plane way. In
+addition, Picture mode defines various keys starting with the `C-c'
+prefix to run special picture editing commands.
+
+ One of these keys, `C-c C-c', is pretty important. Often a picture
+is part of a larger file that is usually edited in some other major
+mode. `M-x edit-picture' records the name of the previous major mode,
+and then you can use the `C-c C-c' command (`picture-mode-exit') to
+restore that mode. `C-c C-c' also deletes spaces from the ends of
+lines, unless given a numeric argument.
+
+ The commands used in Picture mode all work in other modes (provided
+the `picture' library is loaded), but are not bound to keys except in
+Picture mode. Note that the descriptions below talk of moving "one
+column" and so on, but all the picture mode commands handle numeric
+arguments as their normal equivalents do.
+
+ Turning on Picture mode calls the value of the variable
+`picture-mode-hook' as a function, with no arguments, if that value
+exists and is non-`nil'.
+
+* Menu:
+
+* Basic Picture:: Basic concepts and simple commands of Picture Mode.
+* Insert in Picture:: Controlling direction of cursor motion
+ after "self-inserting" characters.
+* Tabs in Picture:: Various features for tab stops and indentation.
+* Rectangles in Picture:: Clearing and superimposing rectangles.
+
+
+File: emacs, Node: Basic Picture, Next: Insert in Picture, Prev: Picture, Up: Picture
+
+Basic Editing in Picture Mode
+=============================
+
+ Most keys do the same thing in Picture mode that they usually do,
+but do it in a quarter-plane style. For example, `C-f' is rebound to
+run `picture-forward-column', which is defined to move point one column
+to the right, by inserting a space if necessary, so that the actual end
+of the line makes no difference. `C-b' is rebound to run
+`picture-backward-column', which always moves point left one column,
+converting a tab to multiple spaces if necessary. `C-n' and `C-p' are
+rebound to run `picture-move-down' and `picture-move-up', which can
+either insert spaces or convert tabs as necessary to make sure that
+point stays in exactly the same column. `C-e' runs
+`picture-end-of-line', which moves to after the last nonblank character
+on the line. There is no need to change `C-a', as the choice of screen
+model does not affect beginnings of lines.
+
+ Insertion of text is adapted to the quarter-plane screen model
+through the use of Overwrite mode (*note Minor Modes::.).
+Self-inserting characters replace existing text, column by column,
+rather than pushing existing text to the right. RET runs
+`picture-newline', which just moves to the beginning of the following
+line so that new text will replace that line.
+
+ Deletion and killing of text are replaced with erasure. DEL
+(`picture-backward-clear-column') replaces the preceding character with
+a space rather than removing it. `C-d' (`picture-clear-column') does
+the same thing in a forward direction. `C-k' (`picture-clear-line')
+really kills the contents of lines, but does not ever remove the
+newlines from the buffer.
+
+ To do actual insertion, you must use special commands. `C-o'
+(`picture-open-line') still creates a blank line, but does so after the
+current line; it never splits a line. `C-M-o', `split-line', makes
+sense in Picture mode, so it is not changed. LFD
+(`picture-duplicate-line') inserts below the current line another line
+with the same contents.
+
+ Real deletion can be done with `C-w', or with `C-c C-d' (which is
+defined as `delete-char', as `C-d' is in other modes), or with one of
+the picture rectangle commands (*note Rectangles in Picture::.).
+
+
+File: emacs, Node: Insert in Picture, Next: Tabs in Picture, Prev: Basic Picture, Up: Picture
+
+Controlling Motion after Insert
+===============================
+
+ Since "self-inserting" characters in Picture mode just overwrite and
+move point, there is no essential restriction on how point should be
+moved. Normally point moves right, but you can specify any of the eight
+orthogonal or diagonal directions for motion after a "self-inserting"
+character. This is useful for drawing lines in the buffer.
+
+`C-c <'
+ Move left after insertion (`picture-movement-left').
+
+`C-c >'
+ Move right after insertion (`picture-movement-right').
+
+`C-c ^'
+ Move up after insertion (`picture-movement-up').
+
+`C-c .'
+ Move down after insertion (`picture-movement-down').
+
+`C-c `'
+ Move up and left ("northwest") after insertion
+ (`picture-movement-nw').
+
+`C-c ''
+ Move up and right ("northeast") after insertion
+ (`picture-movement-ne').
+
+`C-c /'
+ Move down and left ("southwest") after insertion
+ (`picture-movement-sw').
+
+`C-c \'
+ Move down and right ("southeast") after insertion
+ (`picture-movement-se').
+
+ Two motion commands move based on the current Picture insertion
+direction. The command `C-c C-f' (`picture-motion') moves in the same
+direction as motion after "insertion" currently does, while `C-c C-b'
+(`picture-motion-reverse') moves in the opposite direction.
+
+
+File: emacs, Node: Tabs in Picture, Next: Rectangles in Picture, Prev: Insert in Picture, Up: Picture
+
+Picture Mode Tabs
+=================
+
+ Two kinds of tab-like action are provided in Picture mode.
+Context-based tabbing is done with `M-TAB' (`picture-tab-search').
+With no argument, it moves to a point underneath the next "interesting"
+character that follows whitespace in the previous nonblank line.
+"Next" here means "appearing at a horizontal position greater than the
+one point starts out at". With an argument, as in `C-u M-TAB', this
+command moves to the next such interesting character in the current
+line. `M-TAB' does not change the text; it only moves point.
+"Interesting" characters are defined by the variable
+`picture-tab-chars', which contains a string whose characters are all
+considered interesting. Its default value is `"!-~"'.
+
+ TAB itself runs `picture-tab', which operates based on the current
+tab stop settings; it is the Picture mode equivalent of
+`tab-to-tab-stop'. Normally it just moves point, but with a numeric
+argument it clears the text that it moves over.
+
+ The context-based and tab-stop-based forms of tabbing are brought
+together by the command `C-c TAB', `picture-set-tab-stops'. This
+command sets the tab stops to the positions which `M-TAB' would
+consider significant in the current line. The use of this command,
+together with TAB, can get the effect of context-based tabbing. But
+`M-TAB' is more convenient in the cases where it is sufficient.
+
+
+File: emacs, Node: Rectangles in Picture, Prev: Tabs in Picture, Up: Picture
+
+Picture Mode Rectangle Commands
+===============================
+
+ Picture mode defines commands for working on rectangular pieces of
+the text in ways that fit with the quarter-plane model. The standard
+rectangle commands may also be useful (*note Rectangles::.).
+
+`C-c C-k'
+ Clear out the region-rectangle (`picture-clear-rectangle'). With
+ argument, kill it.
+
+`C-c C-w R'
+ Similar but save rectangle contents in register R first
+ (`picture-clear-rectangle-to-register').
+
+`C-c C-y'
+ Copy last killed rectangle into the buffer by overwriting, with
+ upper left corner at point (`picture-yank-rectangle'). With
+ argument, insert instead.
+
+`C-c C-x R'
+ Similar, but use the rectangle in register R
+ (`picture-yank-rectangle-from-register').
+
+ The picture rectangle commands `C-c C-k' (`picture-clear-rectangle')
+and `C-c C-w' (`picture-clear-rectangle-to-register') differ from the
+standard rectangle commands in that they normally clear the rectangle
+instead of deleting it; this is analogous with the way `C-d' is changed
+in Picture mode.
+
+ However, deletion of rectangles can be useful in Picture mode, so
+these commands delete the rectangle if given a numeric argument.
+
+ The Picture mode commands for yanking rectangles differ from the
+standard ones in overwriting instead of inserting. This is the same
+way that Picture mode insertion of other text is different from other
+modes. `C-c C-y' (`picture-yank-rectangle') inserts (by overwriting) the
+rectangle that was most recently killed, while `C-c C-x'
+(`picture-yank-rectangle-from-register') does likewise for the
+rectangle found in a specified register.
+
+
+File: emacs, Node: Sending Mail, Next: Rmail, Prev: Picture, Up: Top
+
+Sending Mail
+************
+
+ To send a message in Emacs, you start by typing a command (`C-x m')
+to select and initialize the `*mail*' buffer. Then you edit the text
+and headers of the message in this buffer, and type another command
+(`C-c C-c') to send the message.
+
+`C-x m'
+ Begin composing a message to send (`mail').
+
+`C-x 4 m'
+ Likewise, but display the message in another window
+ (`mail-other-window').
+
+`C-c C-c'
+ In Mail mode, send the message and switch to another buffer
+ (`mail-send-and-exit').
+
+ The command `C-x m' (`mail') selects a buffer named `*mail*' and
+initializes it with the skeleton of an outgoing message. `C-x 4 m'
+(`mail-other-window') selects the `*mail*' buffer in a different
+window, leaving the previous current buffer visible.
+
+ Because the mail composition buffer is an ordinary Emacs buffer, you
+can switch to other buffers while in the middle of composing mail, and
+switch back later (or never). If you use the `C-x m' command again
+when you have been composing another message but have not sent it, you
+are asked to confirm before the old message is erased. If you answer
+`n', the `*mail*' buffer is left selected with its old contents, so you
+can finish the old message and send it. `C-u C-x m' is another way to
+do this. Sending the message marks the `*mail*' buffer "unmodified",
+which avoids the need for confirmation when `C-x m' is next used.
+
+ If you are composing a message in the `*mail*' buffer and want to
+send another message before finishing the first, rename the `*mail*'
+buffer using `M-x rename-buffer' (*note Misc Buffer::.).
+
+* Menu:
+
+* Format: Mail Format. Format of the mail being composed.
+* Headers: Mail Headers. Details of allowed mail header fields.
+* Mode: Mail Mode. Special commands for editing mail being composed.
+
+
+File: emacs, Node: Mail Format, Next: Mail Headers, Prev: Sending Mail, Up: Sending Mail
+
+The Format of the Mail Buffer
+=============================
+
+ In addition to the "text" or contents, a message has "header fields"
+which say who sent it, when, to whom, why, and so on. Some header
+fields such as the date and sender are created automatically after the
+message is sent. Others, such as the recipient names, must be
+specified by you in order to send the message properly.
+
+ Mail mode provides a few commands to help you edit some header
+fields, and some are preinitialized in the buffer automatically at
+times. You can insert or edit any header fields using ordinary editing
+commands.
+
+ The line in the buffer that says
+
+ --text follows this line--
+
+is a special delimiter that separates the headers you have specified
+from the text. Whatever follows this line is the text of the message;
+the headers precede it. The delimiter line itself does not appear in
+the message actually sent. The text used for the delimiter line is
+controlled by the variable `mail-header-separator'.
+
+ Here is an example of what the headers and text in the `*mail*'
+buffer might look like.
+
+ To: rms@mc
+ CC: mly@mc, rg@oz
+ Subject: The Emacs Manual
+ --Text follows this line--
+ Please ignore this message.
+
+
+File: emacs, Node: Mail Headers, Next: Mail Mode, Prev: Mail Format, Up: Sending Mail
+
+Mail Header Fields
+==================
+
+ There are several header fields you can use in the `*mail*' buffer.
+Each header field starts with a field name at the beginning of a line,
+terminated by a colon. It does not matter whether you use upper or
+lower case in the field name. After the colon and optional whitespace
+comes the contents of the field.
+
+`To'
+ This field contains the mailing addresses to which the message is
+ addressed.
+
+`Subject'
+ The contents of the `Subject' field should be a piece of text that
+ says what the message is about. The reason `Subject' fields are
+ useful is that most mail-reading programs can provide a summary of
+ messages, listing the subject of each message but not its text.
+
+`CC'
+ This field contains additional mailing addresses to send the
+ message to, but whose readers should not regard the message as
+ addressed to them.
+
+`BCC'
+ This field contains additional mailing addresses to send the
+ message to, but which should not appear in the header of the
+ message actually sent.
+
+`FCC'
+ This field contains the name of one file (in Unix mail file
+ format) to which a copy of the message should be appended when the
+ message is sent.
+
+`From'
+ Use the `From' field to say who you are, when the account you are
+ using to send the mail is not your own. The contents of the
+ `From' field should be a valid mailing address, since replies will
+ normally go there.
+
+`Reply-To'
+ Use the `Reply-to' field to direct replies to a different address,
+ not your own. There is no difference between `From' and
+ `Reply-to' in their effect on where replies go, but they convey a
+ different meaning to the human who reads the message.
+
+ If you set the variable `mail-default-reply-to' to a non-`nil'
+ value, then every message you begin to edit will have a `Reply-to'
+ field whose contents are the value of the variable.
+
+`In-Reply-To'
+ This field contains a piece of text describing a message you are
+ replying to. Some mail systems can use this information to
+ correlate related pieces of mail. Normally this field is filled
+ in by Rmail when you are replying to a message in Rmail, and you
+ never need to think about it (*note Rmail::.).
+
+ The `To', `CC', `BCC' and `FCC' fields can appear any number of
+times, to specify many places to send the message.
+
+ The `To', `CC', and `BCC' fields can have continuation lines. All
+the lines starting with whitespace, following the line on which the
+field starts, are considered part of the field. For example,
+
+ To: foo@here, this@there,
+ me@gnu.cambridge.mass.usa.earth.spiral3281
+
+ If you have a `~/.mailrc' file, Emacs will scan it for mail aliases
+the first time you try to send mail in an Emacs session. Aliases found
+in the `To', `CC', and `BCC' fields will be expanded where appropriate.
+
+ If the variable `mail-archive-file-name' is non-`nil', it should be a
+string naming a file; every time you start to edit a message to send,
+an `FCC' field will be put in for that file. Unless you remove the
+`FCC' field, every message will be written into that file when it is
+sent.
+
+
+File: emacs, Node: Mail Mode, Prev: Mail Headers, Up: Sending Mail
+
+Mail Mode
+=========
+
+ The major mode used in the `*mail*' buffer is Mail mode, which is
+much like Text mode except that various special commands are provided on
+the `C-c' prefix. These commands all have to do specifically with
+editing or sending the message.
+
+`C-c C-s'
+ Send the message, and leave the `*mail*' buffer selected
+ (`mail-send').
+
+`C-c C-c'
+ Send the message, and select some other buffer
+ (`mail-send-and-exit').
+
+`C-c C-f C-t'
+ Move to the `To' header field, creating one if there is none
+ (`mail-to').
+
+`C-c C-f C-s'
+ Move to the `Subject' header field, creating one if there is none
+ (`mail-subject').
+
+`C-c C-f C-c'
+ Move to the `CC' header field, creating one if there is none
+ (`mail-cc').
+
+`C-c C-w'
+ Insert the file `~/.signature' at the end of the message text
+ (`mail-signature').
+
+`C-c C-y'
+ Yank the selected message from Rmail (`mail-yank-original'). This
+ command does nothing unless your command to start sending a
+ message was issued with Rmail.
+
+`C-c C-q'
+ Fill all paragraphs of yanked old messages, each individually
+ (`mail-fill-yanked-message').
+
+ There are two ways to send the message. `C-c C-s' (`mail-send')
+sends the message and marks the `*mail*' buffer unmodified, but leaves
+that buffer selected so that you can modify the message (perhaps with
+new recipients) and send it again. `C-c C-c' (`mail-send-and-exit')
+sends and then deletes the window (if there is another window) or
+switches to another buffer. It puts the `*mail*' buffer at the lowest
+priority for automatic reselection, since you are finished with using
+it. This is the usual way to send the message.
+
+ Mail mode provides some other special commands that are useful for
+editing the headers and text of the message before you send it. There
+are three commands defined to move point to particular header fields,
+all based on the prefix `C-c C-f' (`C-f' is for "field"). They are
+`C-c C-f C-t' (`mail-to') to move to the `To' field, `C-c C-f C-s'
+(`mail-subject') for the `Subject' field, and `C-c C-f C-c' (`mail-cc')
+for the `CC' field. These fields have special motion commands because
+they are the most common fields for the user to want to edit.
+
+ `C-c C-w' (`mail-signature') adds a standard piece text at the end
+of the message to say more about who you are. The text comes from the
+file `.signature' in your home directory.
+
+ When mail sending is invoked from the Rmail mail reader using an
+Rmail command, `C-c C-y' can be used inside the `*mail*' buffer to
+insert the text of the message you are replying to. Normally it
+indents each line of that message four spaces and eliminates most
+header fields. A numeric argument specifies the number of spaces to
+indent. An argument of just `C-u' says not to indent at all and not to
+eliminate anything. `C-c C-y' always uses the current message from the
+`RMAIL' buffer, so you can insert several old messages by selecting one
+in `RMAIL', switching to `*mail*' and yanking it, then switching back to
+`RMAIL' to select another.
+
+ After using `C-c C-y', you can type the command `C-c C-q'
+(`mail-fill-yanked-message') to fill the paragraphs of the yanked old
+message or messages. One use of `C-c C-q' fills all such paragraphs,
+each one separately.
+
+ Turning on Mail mode (which `C-x m' does automatically) calls the
+value of `text-mode-hook', if it is not void or `nil', and then calls
+the value of `mail-mode-hook' if that is not void or `nil'. Aside from
+these, the `mail' command runs `mail-setup-hook' whenever it
+initializes the `*mail*' buffer for editing a message.
+
+
+File: emacs, Node: Rmail, Next: Recursive Edit, Prev: Sending Mail, Up: Top
+
+Reading Mail with Rmail
+***********************
+
+ Rmail is an Emacs subsystem for reading and disposing of mail that
+you receive. Rmail stores mail messages in files called "Rmail files".
+ Reading the message in an Rmail file is done in a special major mode,
+Rmail mode, which redefines most letters to run commands for managing
+mail. To enter Rmail, type `M-x rmail'. This reads your primary mail
+file, merges new mail in from your inboxes, displays the first new
+message, and lets you begin reading.
+
+ Using Rmail in the simplest fashion, you have one Rmail file,
+`~/RMAIL', in which all of your mail is saved. It is called your
+"primary mail file". In more sophisticated usage, you can copy
+messages into other Rmail files and then edit those files with Rmail.
+
+ Rmail displays only one message at a time. It is called the "current
+message". Rmail mode's special commands can do such things as move to
+another message, delete the message, copy the message into another
+file, or send a reply.
+
+ Within the Rmail file, messages are arranged sequentially in order
+of receipt. They are also assigned consecutive integers as their
+"message numbers". The number of the current message is displayed in
+Rmail's mode line, followed by the total number of messages in the
+file. You can move to a message by specifying its message number using
+the `j' key (*note Rmail Motion::.).
+
+ Following the usual conventions of Emacs, changes in an Rmail file
+become permanent only when the file is saved. You can do this with `s'
+(`rmail-save'), which also expunges deleted messages from the file
+first (*note Rmail Deletion::.). To save the file without expunging,
+use `C-x C-s'. Rmail saves the Rmail file spontaneously when moving new
+mail from an inbox file (*note Rmail Inbox::.).
+
+ You can exit Rmail with `q' (`rmail-quit'); this expunges and saves
+the Rmail file and then switches to another buffer. But there is no
+need to `exit' formally. If you switch from Rmail to editing in other
+buffers, and never happen to switch back, you have exited. Just make
+sure to save the Rmail file eventually (like any other file you have
+changed). `C-x s' is a good enough way to do this (*note Saving::.).
+
+* Menu:
+
+* Scroll: Rmail Scrolling. Scrolling through a message.
+* Motion: Rmail Motion. Moving to another message.
+* Deletion: Rmail Deletion. Deleting and expunging messages.
+* Inbox: Rmail Inbox. How mail gets into the Rmail file.
+* Files: Rmail Files. Using multiple Rmail files.
+* Output: Rmail Output. Copying message out to files.
+* Labels: Rmail Labels. Classifying messages by labeling them.
+* Summary: Rmail Summary. Summaries show brief info on many messages.
+* Reply: Rmail Reply. Sending replies to messages you are viewing.
+* Editing: Rmail Editing. Editing message text and headers in Rmail.
+* Digest: Rmail Digest. Extracting the messages from a digest message.
+
+
+File: emacs, Node: Rmail Scrolling, Next: Rmail Motion, Prev: Rmail, Up: Rmail
+
+Scrolling Within a Message
+==========================
+
+ When Rmail displays a message that does not fit on the screen, it is
+necessary to scroll through it. This could be done with `C-v', `M-v'
+and `M-<', but in Rmail scrolling is so frequent that it deserves to be
+easier to type.
+
+`SPC'
+ Scroll forward (`scroll-up').
+
+`DEL'
+ Scroll backward (`scroll-down').
+
+`.'
+ Scroll to start of message (`rmail-beginning-of-message').
+
+ Since the most common thing to do while reading a message is to
+scroll through it by screenfuls, Rmail makes SPC and DEL synonyms of
+`C-v' (`scroll-up') and `M-v' (`scroll-down').
+
+ The command `.' (`rmail-beginning-of-message') scrolls back to the
+beginning of the selected message. This is not quite the same as `M-<':
+for one thing, it does not set the mark; for another, it resets the
+buffer boundaries to the current message if you have changed them.
+
+ \ No newline at end of file
diff --git a/info/info b/info/info
new file mode 100644
index 00000000000..4d297533e8a
--- /dev/null
+++ b/info/info
@@ -0,0 +1,628 @@
+This file documents the Info program. -*-Text-*-
+The H command of Info goes to the node Help in this file.
+
+File: info Node: Top Up: (DIR) Next: Expert
+
+Info is a program for reading documentation, which you are using now.
+
+To learn how to use Info, type the command "h". It will bring you
+to a programmed instruction sequence.
+
+* Menu:
+
+* Expert:: Advanced Info commands: g, s, e, and 1 - 5.
+* Add:: Describes how to add new nodes to the hierarchy.
+ Also tells what nodes look like.
+* Menus:: How to add to or create menus in Info nodes.
+* Cross-refs:: How to add cross-references to Info nodes.
+* Tags:: How to make tag tables for Info files.
+* Checking:: How to check the consistency of an Info file.
+* Texinfo: (texinfo).
+ How to generate an Info file and a printed manual
+ from the same source file.
+
+File: info Node: Help-Small-Screen Next: Help
+
+Since your terminal has an unusually small number of lines on its
+screen, it is necessary to give you special advice at the beginning.
+
+If you see the text "--All----" at near the bottom right corner of
+the screen, it means the entire text you are looking at fits on the
+screen. If you see "--Top----" instead, it means that there is more
+text below that does not fit. To move forward through the text and
+see another screen full, press the Space bar. To move back up, press
+the key labeled Rubout or Delete or DEL.
+
+Here are 40 lines of junk, so you can try Spaces and Rubout and
+see what they do. At the end are instructions of what you should do
+next.
+
+This is line 17
+This is line 18
+This is line 19
+This is line 20
+This is line 21
+This is line 22
+This is line 23
+This is line 24
+This is line 25
+This is line 26
+This is line 27
+This is line 28
+This is line 29
+This is line 30
+This is line 31
+This is line 32
+This is line 33
+This is line 34
+This is line 35
+This is line 36
+This is line 37
+This is line 38
+This is line 39
+This is line 40
+This is line 41
+This is line 42
+This is line 43
+This is line 44
+This is line 45
+This is line 46
+This is line 47
+This is line 48
+This is line 49
+This is line 50
+This is line 51
+This is line 52
+This is line 53
+This is line 54
+This is line 55
+This is line 56
+
+If you have managed to get here, go back to the beginning with
+Rubout, and come back here again, then you understand Space and
+Rubout. So now type an "n"--just one character; don't type the
+quotes and don't type a Return afterward-- to get to the normal start
+of the course.
+
+File: info Node: Help Next: Help-P Previous: Help-Small-Screen
+
+You are talking to the program Info, for reading documentation.
+
+ Right now you are looking at one "Node" of Information.
+A node contains text describing a specific topic at a specific
+level of detail. This node's topic is "how to use Info".
+
+ The top line of a node is its "header". This node's header (look at
+it now) says that it is the node named "Help" in the file "info".
+It says that the Next node after this one is the node called "Help-P".
+An advanced Info command lets you go to any node whose name you know.
+
+ Besides a "Next", a node can have a "Previous" or an "Up".
+This node has a "Previous" but no "Up", as you can see.
+
+ Now it's time to move on to the Next node, named "Help-P".
+
+>> Type "n" to move there. Type just one character;
+ don't type the quotes and don't type a Return afterward.
+
+">>" in the margin means it is really time to try a command.
+
+File: info Node: Help-P Next: Help-^L Previous: Help
+
+This node is called "Help-P". The "Previous" node, as you see, is
+"Help", which is the one you just came from using the "N" command.
+Another "N" command now would take you to the Next node, "Help-^L".
+
+>> But don't do that yet. First, try the "p" command, which takes
+you to the Previous node. When you get there, you can do an "n"
+again to return here.
+
+ This all probably seems insultingly simple so far, but DON'T be
+led into skimming. Things will get more complicated soon. Also,
+don't try a new command until you are told it's time to. Otherwise,
+you may make Info skip past an important warning that was coming up.
+
+>> Now do an "n" to get to the node "Help-^L" and learn more.
+
+File: info Node: Help-^L Next: Help-M Previous: Help-P
+
+Space, Rubout, B and ^L commands.
+
+ This node's header tells you that you are now at node "Help-^L", and
+that "P" would get you back to "Help-P". The line starting "Space,"
+is a "Title", saying what the node is about (most nodes have titles).
+
+ This is a big node and it doesn't all fit on your display screen.
+You can tell that there is more that isn't visible because you
+can see the string "--Top-----" rather than "--All-----" near
+the bottom right corner of the screen.
+
+ The Space, Rubout and B commands exist to allow you to "move
+around" in a node that doesn't all fit on the screen at once.
+Space moves forward, to show what was below the bottom of the screen.
+Rubout moves backward, to show what was above the top of the screen
+(there isn't anything above the top until you have typed some spaces).
+>> Now try typing a Space (afterward, type a Rubout to return here).
+
+ When you type the space, the two lines that were at the bottom of the
+screen appear at the top, followed by more lines. Rubout takes the
+two lines from the top and moves them to the bottom, USUALLY, but if
+there are not a full screen's worth of lines above them they may not
+make it all the way to the bottom.
+
+ If you type a Space when there is no more to see, it will ring the
+bell and otherwise do nothing. The same goes for a Rubout when
+the header of the node is visible.
+
+ If your screen is ever garbaged, you can tell Info to print it out
+again by typing C-l (Control-L, that is--hold down "Control" and
+type an "L" or "l").
+>> Type C-l now.
+
+ To move back to the beginning of the node you are on, you can type
+a lot of Rubouts. You can also type simply "b" for beginning.
+>> Try that now. (I have put in enough verbiage to make sure you are
+ not on the first screenful now). Then come back, with Spaces.
+
+ You have just learned a considerable number of commands. If you
+want to use one but have trouble remembering which, you should type
+a "?" which will print out a brief list of commands. When you are
+finished looking at the list, make it go away by typing a Space.
+>> Type a "?" now. After it finishes, type a Space.
+
+ From now on, you will encounter large nodes without warning, and
+will be expected to know how to use Space and Rubout to move
+around in them without being told. Since not all terminals have
+the same size screen, it would be impossible to warn you anyway.
+
+>> Now type "n" to see the description of the "m" command.
+
+File: info Node: Help-M Next: Help-Adv Previous: Help-^L
+
+Menus and the "m" command
+
+ With only the "n" and "p" commands for moving between nodes, nodes
+are restricted to a linear sequence. Menus allow a branching
+structure. A menu is a list of other nodes you can move to. It is
+actually just part of the text of the node formatted specially so that
+Info can interpret it. The beginning of a menu is always identified
+by a line which starts with "* Menu:". A node contains a menu if and
+only if it has a line in it which starts that way. The only menu you
+can use at any moment is the one in the node you are in. To use a
+menu in any other node, you must move to that node first.
+
+ After the start of the menu, each line that starts with a "*"
+identifies one subtopic. The line will usually contain a brief name
+for the subtopic (followed by a ":"), the name of the node that talks
+about that subtopic, and optionally some further description of the
+subtopic. Lines in the menu that don't start with a "*" have no
+special meaning - they are only for the human reader's benefit and do
+not define additional subtopics. Here is an example:
+* Foo: FOO's Node This tells about FOO
+The subtopic name is Foo, and the node describing it is "FOO's Node".
+The rest of the line is just for the reader's Information.
+[[ But this line is not a real menu item, simply because there is
+no line above it which starts with "* Menu:".]]
+
+ When you use a menu to go to another node (in a way that will be
+described soon), what you specify is the subtopic name, the first
+thing in the menu line. Info uses it to find the menu line, extracts
+the node name from it, and goes to that node. The reason that there
+is both a subtopic name and a node name is that the node name must be
+meaningful to the computer and may therefore have to be ugly looking.
+The subtopic name can be chosen just to be convenient for the user to
+specify. Often the node name is convenient for the user to specify
+and so both it and the subtopic name are the same. There is an
+abbreviation for this:
+* Foo:: This tells about FOO
+This means that the subtopic name and node name are the same; they are
+both "Foo".
+
+>> Now use Spaces to find the menu in this node, then come back to
+the front with a "b". As you see, a menu is actually visible
+in its node. If you can't find a menu in a node by looking at it,
+then the node doesn't have a menu and the "m" command is not available.
+
+ The command to go to one of the subnodes is "m" - but DON'T DO IT
+YET! Before you use "m", you must understand the difference between
+commands and arguments. So far, you have learned several commands
+that do not need arguments. When you type one, Info processes it and
+is instantly ready for another command. The "m" command is different:
+it is incomplete without the NAME OF THE SUBTOPIC. Once you have
+typed "m", Info tries to read the subtopic name.
+
+ Now look for the line containing many dashes near the bottom of the
+screen. There is one more line beneath that one, but usually it is
+blank If it is empty, Info is ready for a command, such as "n" or "b"
+or Space or "m". If that line contains text ending in a colon, it
+mean Info is trying to read the ARGUMENT to a command. At such
+times, commands won't work, because Info will try to use them as the
+argument. You must either type the argument and finish the command
+you started, or type Control-g to cancel the command. When you have
+done one of those things, the line will become blank again.
+
+ The command to go to a subnode via a menu is "m". After you type
+the "m", the line at the bottom of the screen says "Menu item: ".
+You must then type the name of the subtopic you want, and end it with
+a Return.
+
+ You can abbreviate the subtopic name. If the abbreviation is not
+unique, the first matching subtopic is chosen. Some menus will put
+the shortest possible abbreviation for each subtopic name in capital
+letters, so you can see how much you need to type. It does not
+matter whether you use upper case or lower case when you type the
+subtopic. You should not put any spaces at the end, or inside of the
+item name, except for one space where a space appears in the item in
+the menu.
+
+ Here is a menu to give you a chance to practice.
+
+* Menu: The menu starts here.
+
+This menu givs you three ways of going to one place, Help-FOO.
+
+* Foo: Help-FOO A node you can visit for fun
+* Bar: Help-FOO Strange! two ways to get to the same place.
+* Help-FOO:: And yet another!
+
+>> Now type just an "m" and see what happens:
+
+ Now you are "inside" an "m" command. Commands can't be used now;
+the next thing you will type must be the name of a subtopic.
+
+ You can change your mind about doing the "m" by typing Control-g.
+>> Try that now; notice the bottom line clear.
+>> Then type another "m".
+
+>> Now type "BAR", the item name. Don't type Return yet.
+
+ While you are typing the item name, you can use the Rubout
+character to cancel one character at a time if you make a mistake.
+>> Type one to cancel the "R". You could type another "R" to
+replace it. You don't have to, since "BA" is a valid abbreviation.
+>> Now you are ready to go. Type a Return.
+
+ After visiting Help-FOO, you should return here.
+
+>> Type "n" to see more commands.
+
+File: info Node: Help-FOO Up: Help-M
+
+The "u" command
+
+ Congratulations! This is the node Help-FOO. Unlike the other
+nodes you have seen, this one has an "Up": "Help-M", the node you
+just came from via the "m" command. This is the usual convention--
+the nodes you reach from a menu have Ups that lead back to the menu.
+Menus move Down in the tree, and Up moves Up. Previous, on the other
+hand, is usually used to "stay on the same level but go backwards".
+
+ You can go back to the node Help-M by typing the command
+"u" for "Up". That will put you at the FRONT of the node - to get
+back to where you were reading you will have to type some Spaces.
+
+>> Now type "u" to move back up to Help-M.
+
+File: info Node: Help-Adv Next: Help-Q Previous: Help-M
+
+Some advanced Info commands
+
+ The course is almost over, so please stick with it to the end.
+
+ If you have been moving around to different nodes and wish to
+retrace your steps, the "l" command ("l" for "last") will do that, one
+node at a time. If you have been following directions, an "l" command
+now will get you back to Help-M. Another "l" command would undo the "u"
+and get you back to Help-FOO. Another "l" would undo the M and get you
+back to Help-M.
+
+>> Try typing three "l"'s, pausing in between to see what each "l" does.
+Then follow directions again and you will end up back here.
+
+ Note the difference between "l" and "p": "l" moves to where YOU
+last were, whereas "p" always moves to the node which the header says
+is the "Previous" node (from this node, to Help-M).
+
+ The "d" command gets you instantly to the Directory node.
+This node, which is the first one you saw when you entered Info,
+has a menu which leads (directly, or indirectly through other menus),
+to all the nodes that exist.
+
+>> Try doing a "d", then do an "l" to return here (yes, DO return).
+
+ Sometimes, in Info documentation, you will see a cross reference.
+Cross references look like this: *Note Cross: Help-Cross. That is a
+real, live cross reference which is named "Cross" and points at the
+node named "Help-Cross".
+
+ If you wish to follow a cross reference, you must use the "f"
+command. The "f" must be followed by the cross reference name (in
+this case, "Cross"). You can use Rubout to edit the name, and if you
+change your mind about following any reference you can use Control-g
+to cancel the command.
+
+ Completion is available in the "f" command; you can complete among
+all the cross reference names in the current node.
+
+>> Type "f", followed by "Cross", and a Return.
+
+ To get a list of all the cross references in the current node, you can
+type "?" after an "f". The "f" continues to await a cross reference name
+even after printing the list, so if you don't actually want to follow
+a reference you should type a Control-g to cancel the "f".
+
+>> Type "f?" to get a list of the footnotes in this node. Then
+type a Control-g and see how the "f" gives up.
+
+>> Now type "n" to see the last node of the course.
+
+File: info Node: Help-Cross
+
+ This is the node reached by the cross reference named "Cross".
+
+ While this node is specifically intended to be reached by a cross
+reference, most cross references lead to nodes that "belong" someplace
+else far away in the structure of Info. So you can't expect the
+footnote to have a Next, Previous or Up pointing back to where you
+came from. In general, the "l" (el) command is the only way to get
+back there.
+
+>> Type "l" to return to the node where the cross reference was.
+
+File: info Node: Help-Q Previous: Help-Adv Up: Top
+
+ To get out of Info, back to what you were doing before, type "q"
+for "Quit".
+
+ This is the end of the course on using Info. There are some other
+commands that are not essential or meant for experienced users; they
+are useful, and you can find them by looking in the directory for
+documentation on Info. Finding them will be a good exercise in using
+Info in the usual manner.
+
+>> Type "d" to go to the Info directory node;
+ then type "mInfo" and Return, to get to the node about Info
+ and see what other help is available.
+
+File: info, Node: Expert, Up: Top, Previous: Top, Next: Add
+
+Some Advanced Info Commands ("g", "s", "1" - "5", and "e").
+
+If you know a node's name, you can go there by typing
+"g", the name, and Return. Thus, "gTop<Return>" would go to the node
+called Top in this file (its directory node). "gExpert<Return>"
+would come back here.
+
+Unlike "m", "g" does not allow the use of abbreviations.
+
+To go to a node in another file, you can include the filename in the
+node name by putting it at the front, in parentheses. Thus,
+"g(dir)Top<Return>" would go to the Info Directory node, which is node Top
+in the file dir.
+
+The node name "*" specifies the whole file. So you can look at all
+of the current file by typing "g*<Return>" or all of any other file
+with "g(FILENAME)<Return>".
+
+The "s" command allows you to search a whole file for a string. It
+will switch to the next node if and when that is necessary. You type
+"s" followed by the string to search for, terminated by Return. To
+search for the same string again, just "s" followed by Return will do.
+The file's nodes will be scanned in the order they are in in the file,
+which has no necessary relationship to the order that they may be in
+in the tree structure of menus and next's. But normally the two
+orders will not be far different. In any case, you can always do a
+"b" to find out what node you have reached, if the header isn't
+visible (this can happen, because "S" puts your cursor at the
+occurrence of the string, not at the beginning of the node).
+
+If you grudge the system each character of type-in it requires,
+you might like to use the commands "1", "2", "3", "4", and "5".
+They are short for the "m" command together with an argument.
+"1" goes through the first item in the current node's menu;
+"2" goes through the second item, etc. Note that numbers
+larger than 5 are not allowed. If the item you want is that
+far down, you are better off using an abbreviation for its
+name than counting.
+
+The Info command "e" changes from Info mode to an ordinary
+Emacs editing mode, so that you can edit the text of the current node.
+Type C-c C-c to switch back to Info. The "e" command is allowed
+only if the variable Info-enable-edit is non-nil.
+
+File: info, Node: Add, Up: Top, Previous: Expert, Next: Menus
+
+To add a new topic to the list in the directory, you must
+ 1) create a node, in some file, to document that topic.
+ 2) put that topic in the menu in the directory. *Note Menu: Menus.
+
+ The new node can live in an existing documentation file, or in a new
+one. It must have a ^_ character before it (invisible to the user;
+this node has one but you can't see it), and it ends with either a ^_,
+a ^L, or the end of file. Note: If you put in a ^L to end a new
+node, be sure that there is a ^_ after it to start the next one, since
+^L can't START a node. Also, a nicer way to make a node boundary be a
+page boundary as well is to put a ^L RIGHT AFTER the ^_.
+
+ The ^_ starting a node must be followed by a newline or a ^L newline,
+after which comes the node's header line. The header line must give
+the node's name (by which Info will find it), and state the names of
+the Next, Previous, and Up nodes (if there are any). As you can see,
+this node's Up node is the node Top, which points at all the
+documentation for Info. The Next node is "Menus".
+
+ The keywords "Node", "Previous", "Up" and "Next", may appear in
+any order, anywhere in the header line, but the recommended order is
+the one in this sentence. Each keyword must be followed by a colon,
+spaces and tabs, and then the appropriate name. The name may be
+terminated with a tab, a comma, or a newline. A space does not end
+it; node names may contain spaces. The case of letters in the names
+is insignificant.
+
+ A node name has two forms. A node in the current file is named by
+what appears after the "Node: " in that node's first line. For
+example, this node's name is "Add". A node in another file is named
+by "(FILENAME)NODE-WITHIN-FILE", as in "(info)Add" for this node. If
+the file name is relative, it is taken starting from the standard
+Info file directory of your site. The name "(FILENAME)Top" can be
+abbreviated to just "(FILENAME)". By convention, the name "Top" is
+used for the "highest" node in any single file - the node whose "Up"
+points out of the file. The Directory node is "(dir)". The Top node
+of a document file listed in the Directory should have an "Up: (dir)"
+in it.
+
+ The node name "*" is special: it refers to the entire file. Thus,
+g* will show you the whole current file. The use of the node * is to
+make it possible to make old-fashioned, unstructured files into nodes
+of the tree.
+
+ The "Node:" name, in which a node states its own name, must not
+contain a filename, since Info when searching for a node does not
+expect one to be there. The Next, Previous and Up names may contain
+them. In this node, since the Up node is in the same file, it was not
+necessary to use one.
+
+ Note that the nodes in this file have a File name in the header
+line. The File names are ignored by Info, but they serve as
+comments to help identify the node for the user.
+
+File: info, Node: Menus, Previous: Add, Up: Top, Next: Cross-refs
+
+How to Create Menus:
+
+ Any node in the Info hierarchy may have a MENU--a list of subnodes.
+The "m" command searches the current node's menu for the topic which it
+reads from the terminal.
+
+ A menu begins with a line starting with "* Menu:". The rest of the
+line is a comment. After the starting line, every line that begins
+with a "* " lists a single topic. The name of the topic--the arg
+that the user must give to the "m" command to select this topic--
+comes right after the star and space, and is followed by
+a colon, spaces and tabs, and the name of the node which discusses
+that topic. The node name, like node names following Next,
+Previous and Up, may be terminated with a tab, comma, or newline;
+it may also be terminated with a period.
+
+ If the node name and topic name are the same, than rather than
+giving the name twice, the abbreviation "* NAME::" may be used
+(and should be used, whenever possible, as it reduces the visual
+clutter in the menu).
+
+ It is considerate to choose the topic names so that they differ
+from each other very near the beginning--this allows the user to type
+short abbreviations. In a long menu, it is a good idea to capitalize
+the beginning of each item name which is the minimum acceptable
+abbreviation for it (a long menu is more than 5 or so entries).
+
+ The node's listed in a node's menu are called its "subnodes", and
+it is their "superior". They should each have an "Up:" pointing at
+the superior. It is often useful to arrange all or most of the
+subnodes in a sequence of Next's/Previous's so that someone who
+wants to see them all need not keep revisiting the Menu.
+
+ The Info Directory is simply the menu of the node "(dir)Top"--that
+is, node Top in file .../info/dir. You can put new entries in that
+menu just like any other menu. The Info Directory is NOT the same as
+the file directory called "info". It happens that many of Info's
+files live on that file directory, but they don't have to; and files
+on that directory are not automatically listed in the Info Directory
+node.
+
+ Also, although the Info node graph is claimed to be a "hierarchy",
+in fact it can be ANY directed graph. Shared structures and pointer
+cycles are perfectly possible, and can be used if they are
+appropriate to the meaning to be expressed. There is no need for all
+the nodes in a file to form a connected structure. In fact, this
+file has two connected components. You are in one of them, which is
+under the node Top; the other contains the node Help which the "h"
+command goes to. In fact, since there is no garbage collector,
+nothing terrible happens if a substructure is not pointed to, but
+such a substructure will be rather useless since nobody will ever
+find out that it exists.
+
+File: info, Node: Cross-refs, Previous: Menus, Up: Top, Next: Tags
+
+Creating Cross References:
+
+ A cross reference can be placed anywhere in the text, unlike a menu
+item which must go at the front of a line. A cross reference looks
+like a menu item except that it has "*note" instead of "*". It CANNOT
+be terminated by a ")", because ")"'s are so often part of node names.
+If you wish to enclose a cross reference in parentheses, terminate it
+with a period first. Here are two examples of cross references pointers:
+
+ *Note details: commands. (See *note 3: Full Proof.)
+
+They are just examples. The places they "lead to" don't really exist!
+
+File: info, Node: Tags, Previous: Cross-refs, Up: Top, Next: Checking
+
+Tag Tables for Info Files:
+
+ You can speed up the access to nodes of a large Info file by giving
+it a tag table. Unlike the tag table for a program, the tag table for
+an Info file lives inside the file itself and will automatically be
+used whenever Info reads in the file.
+
+ To make a tag table, go to a node in the file using Info and type
+M-x Info-tagify. Then you must use C-x C-s to save the file.
+
+ Once the Info file has a tag table, you must make certain it is up
+to date. If, as a result of deletion of text, any node moves back
+more than a thousand characters in the file from the position
+recorded in the tag table, Info will no longer be able to find that
+node. To update the tag table, use the Info-tagify command again.
+
+ An Info file tag table appears at the end of the file and looks like
+this:
+
+^_
+Tag Table:
+File: info, Node: Cross-refs21419
+File: info, Node: Tags22145
+^_
+End Tag Table
+
+Note that it contains one line per node, and this line contains
+the beginning of the node's header (ending just after the node name),
+a rubout character, and the character position in the file of the
+beginning of the node.
+
+File: info, Node: Checking, Previous: Tags, Up: Top
+
+Checking an Info File:
+
+ When creating an Info file, it is easy to forget the name of a node
+when you are making a pointer to it from another node. If you put in
+the wrong name for a node, this will not be detected until someone
+tries to go through the pointer using Info. Verification of the Info
+file is an automatic process which checks all pointers to nodes and
+reports any pointers which are invalid. Every Next, Previous, and Up
+is checked, as is every menu item and every cross reference. In addition,
+any Next which doesn't have a Previous pointing back is reported.
+Only pointers within the file are checked, because checking pointers
+to other files would be terribly slow. But those are usually few.
+
+ To check an Info file, do M-x Info-validate while looking at any
+node of the file with Info.
+
+Tag table:
+File: info, Node: Checking25796
+File: info, Node: Tags24579
+File: info, Node: Cross-refs23926
+File: info, Node: Menus21121
+File: info, Node: Add18186
+File: info, Node: Expert15972
+File: info Node: Help-Q15421
+File: info Node: Help-Cross14907
+File: info Node: Help-Adv12631
+File: info Node: Help-FOO11930
+File: info Node: Help-M6648
+File: info Node: Help-^L4141
+File: info Node: Help-P3393
+File: info Node: Help2444
+File: info Node: Help-Small-Screen816
+File: info Node: Top111
+
+End tag table
diff --git a/info/regex b/info/regex
new file mode 100644
index 00000000000..a262ac6aacf
--- /dev/null
+++ b/info/regex
@@ -0,0 +1,601 @@
+Info file regex, produced by Makeinfo, -*- Text -*- from input file
+regex.texinfo.
+
+
+
+File: regex, Node: top, Next: syntax, Up: (dir)
+
+"regex" regular expression matching library.
+********************************************
+
+Overview
+========
+
+Regular expression matching allows you to test whether a string fits
+into a specific syntactic shape. You can also search a string for a
+substring that fits a pattern.
+
+A regular expression describes a set of strings. The simplest case
+is one that describes a particular string; for example, the string
+`foo' when regarded as a regular expression matches `foo' and nothing
+else. Nontrivial regular expressions use certain special constructs
+so that they can match more than one string. For example, the
+regular expression `foo\|bar' matches either the string `foo' or the
+string `bar'; the regular expression `c[ad]*r' matches any of the
+strings `cr', `car', `cdr', `caar', `cadddar' and all other such
+strings with any number of `a''s and `d''s.
+
+The first step in matching a regular expression is to compile it.
+You must supply the pattern string and also a pattern buffer to hold
+the compiled result. That result contains the pattern in an internal
+format that is easier to use in matching.
+
+Having compiled a pattern, you can match it against strings. You can
+match the compiled pattern any number of times against different
+strings.
+
+* Menu:
+
+* syntax:: Syntax of regular expressions
+* directives:: Meaning of characters as regex string directives.
+* emacs:: Additional character directives available
+ only for use within Emacs.
+* programming:: Using the regex library from C programs
+* unix:: Unix-compatible entry-points to regex library
+
+
+
+File: regex, Node: syntax, Next: directives, Prev: top, Up: top
+
+Syntax of Regular Expressions
+=============================
+
+Regular expressions have a syntax in which a few characters are
+special constructs and the rest are "ordinary". An ordinary
+character is a simple regular expression which matches that character
+and nothing else. The special characters are `$', `^', `.', `*',
+`+', `?', `[', `]' and `\'. Any other character appearing in a
+regular expression is ordinary, unless a `\' precedes it.
+
+For example, `f' is not a special character, so it is ordinary, and
+therefore `f' is a regular expression that matches the string `f' and
+no other string. (It does *not* match the string `ff'.) Likewise,
+`o' is a regular expression that matches only `o'.
+
+Any two regular expressions A and B can be concatenated. The result
+is a regular expression which matches a string if A matches some
+amount of the beginning of that string and B matches the rest of the
+string.
+
+As a simple example, we can concatenate the regular expressions `f'
+and `o' to get the regular expression `fo', which matches only the
+string `fo'. Still trivial.
+
+Note: for Unix compatibility, special characters are treated as
+ordinary ones if they are in contexts where their special meanings
+make no sense. For example, `*foo' treats `*' as ordinary since
+there is no preceding expression on which the `*' can act. It is
+poor practice to depend on this behavior; better to quote the special
+character anyway, regardless of where is appears.
+
+
+
+File: regex, Node: directives, Next: emacs, Prev: syntax, Up: top
+
+The following are the characters and character sequences which have
+special meaning within regular expressions. Any character not
+mentioned here is not special; it stands for exactly itself for the
+purposes of searching and matching. *Note syntax::.
+
+`.'
+ is a special character that matches anything except a newline.
+ Using concatenation, we can make regular expressions like `a.b'
+ which matches any three-character string which begins with `a'
+ and ends with `b'.
+
+`*'
+ is not a construct by itself; it is a suffix, which means the
+ preceding regular expression is to be repeated as many times as
+ possible. In `fo*', the `*' applies to the `o', so `fo*'
+ matches `f' followed by any number of `o''s.
+
+ The case of zero `o''s is allowed: `fo*' does match `f'.
+
+ `*' always applies to the *smallest* possible preceding
+ expression. Thus, `fo*' has a repeating `o', not a repeating
+ `fo'.
+
+ The matcher processes a `*' construct by matching, immediately,
+ as many repetitions as can be found. Then it continues with the
+ rest of the pattern. If that fails, backtracking occurs,
+ discarding some of the matches of the `*''d construct in case
+ that makes it possible to match the rest of the pattern. For
+ example, matching `c[ad]*ar' against the string `caddaar', the
+ `[ad]*' first matches `addaa', but this does not allow the next
+ `a' in the pattern to match. So the last of the matches of
+ `[ad]' is undone and the following `a' is tried again. Now it
+ succeeds.
+
+`+'
+ `+' is like `*' except that at least one match for the preceding
+ pattern is required for `+'. Thus, `c[ad]+r' does not match
+ `cr' but does match anything else that `c[ad]*r' would match.
+
+`?'
+ `?' is like `*' except that it allows either zero or one match
+ for the preceding pattern. Thus, `c[ad]?r' matches `cr' or
+ `car' or `cdr', and nothing else.
+
+`[ ... ]'
+ `[' begins a "character set", which is terminated by a `]'. In
+ the simplest case, the characters between the two form the set.
+ Thus, `[ad]' matches either `a' or `d', and `[ad]*' matches any
+ string of `a''s and `d''s (including the empty string), from
+ which it follows that `c[ad]*r' matches `car', etc.
+
+ Character ranges can also be included in a character set, by
+ writing two characters with a `-' between them. Thus, `[a-z]'
+ matches any lower-case letter. Ranges may be intermixed freely
+ with individual characters, as in `[a-z$%.]', which matches any
+ lower case letter or `$', `%' or period.
+
+ Note that the usual special characters are not special any more
+ inside a character set. A completely different set of special
+ characters exists inside character sets: `]', `-' and `^'.
+
+ To include a `]' in a character set, you must make it the first
+ character. For example, `[]a]' matches `]' or `a'. To include
+ a `-', you must use it in a context where it cannot possibly
+ indicate a range: that is, as the first character, or
+ immediately after a range.
+
+`[^ ... ]'
+ `[^' begins a "complement character set", which matches any
+ character except the ones specified. Thus, `[^a-z0-9A-Z]'
+ matches all characters *except* letters and digits.
+
+ `^' is not special in a character set unless it is the first
+ character. The character following the `^' is treated as if it
+ were first (it may be a `-' or a `]').
+
+`^'
+ is a special character that matches the empty string -- but only
+ if at the beginning of a line in the text being matched.
+ Otherwise it fails to match anything. Thus, `^foo' matches a
+ `foo' which occurs at the beginning of a line.
+
+`$'
+ is similar to `^' but matches only at the end of a line. Thus,
+ `xx*$' matches a string of one or more `x''s at the end of a line.
+
+`\'
+ has two functions: it quotes the above special characters
+ (including `\'), and it introduces additional special constructs.
+
+ Because `\' quotes special characters, `\$' is a regular
+ expression which matches only `$', and `\[' is a regular
+ expression which matches only `[', and so on.
+
+ For the most part, `\' followed by any character matches only
+ that character. However, there are several exceptions:
+ characters which, when preceded by `\', are special constructs.
+ Such characters are always ordinary when encountered on their own.
+
+ No new special characters will ever be defined. All extensions
+ to the regular expression syntax are made by defining new
+ two-character constructs that begin with `\'.
+
+`\|'
+ specifies an alternative. Two regular expressions A and B with
+ `\|' in between form an expression that matches anything that
+ either A or B will match.
+
+ Thus, `foo\|bar' matches either `foo' or `bar' but no other
+ string.
+
+ `\|' applies to the largest possible surrounding expressions.
+ Only a surrounding `\( ... \)' grouping can limit the grouping
+ power of `\|'.
+
+ Full backtracking capability exists when multiple `\|''s are used.
+
+`\( ... \)'
+ is a grouping construct that serves three purposes:
+
+ 1. To enclose a set of `\|' alternatives for other operations.
+ Thus, `\(foo\|bar\)x' matches either `foox' or `barx'.
+
+ 2. To enclose a complicated expression for the postfix `*' to
+ operate on. Thus, `ba\(na\)*' matches `bananana', etc.,
+ with any (zero or more) number of `na''s.
+
+ 3. To mark a matched substring for future reference.
+
+ This last application is not a consequence of the idea of a
+ parenthetical grouping; it is a separate feature which happens
+ to be assigned as a second meaning to the same `\( ... \)'
+ construct because there is no conflict in practice between the
+ two meanings. Here is an explanation of this feature:
+
+`\DIGIT'
+ After the end of a `\( ... \)' construct, the matcher remembers
+ the beginning and end of the text matched by that construct.
+ Then, later on in the regular expression, you can use `\'
+ followed by DIGIT to mean "match the same text matched the
+ DIGIT'th time by the `\( ... \)' construct." The `\( ... \)'
+ constructs are numbered in order of commencement in the regexp.
+
+ The strings matching the first nine `\( ... \)' constructs
+ appearing in a regular expression are assigned numbers 1 through
+ 9 in order of their beginnings. `\1' through `\9' may be used
+ to refer to the text matched by the corresponding `\( ... \)'
+ construct.
+
+ For example, `\(.*\)\1' matches any string that is composed of
+ two identical halves. The `\(.*\)' matches the first half,
+ which may be anything, but the `\1' that follows must match the
+ same exact text.
+
+`\b'
+ matches the empty string, but only if it is at the beginning or
+ end of a word. Thus, `\bfoo\b' matches any occurrence of `foo'
+ as a separate word. `\bball\(s\|\)\b' matches `ball' or `balls'
+ as a separate word.
+
+`\B'
+ matches the empty string, provided it is *not* at the beginning
+ or end of a word.
+
+`\<'
+ matches the empty string, but only if it is at the beginning of
+ a word.
+
+`\>'
+ matches the empty string, but only if it is at the end of a word.
+
+`\w'
+ matches any word-constituent character.
+
+`\W'
+ matches any character that is not a word-constituent.
+
+There are a number of additional `\' regexp directives available for
+use within Emacs only.
+
+(*note emacs::.).
+
+
+
+File: regex, Node: emacs, Next: programming, Prev: directives, Up: top
+
+Constructs Available in Emacs Only
+----------------------------------
+
+`\`'
+ matches the empty string, but only if it is at the beginning of
+ the buffer.
+
+`\''
+ matches the empty string, but only if it is at the end of the
+ buffer.
+
+`\sCODE'
+ matches any character whose syntax is CODE. CODE is a letter
+ which represents a syntax code: thus, `w' for word constituent,
+ `-' for whitespace, `(' for open-parenthesis, etc. See the
+ documentation for the Emacs function `modify-syntax-entry' for
+ further details.
+
+ Thus, `\s(' matches any character with open-parenthesis syntax.
+
+`\SCODE'
+ matches any character whose syntax is not CODE.
+
+
+
+File: regex, Node: programming, Next: compiling, Prev: emacs, Up: top
+
+Programming using the `regex' library
+=====================================
+
+The subnodes accessible from this menu give information on entry
+points and data structures which C programs need to interface to the
+`regex' library.
+
+* Menu:
+
+* compiling:: How to compile regular expressions
+* matching:: Matching compiled regular expressions
+* searching:: Searching for compiled regular expressions
+* translation:: Translating characters into other characters
+ (for both compilation and matching)
+* registers:: determining what was matched
+* split:: matching data which is split into two pieces
+* unix:: Unix-compatible entry-points to regex library
+
+
+
+File: regex, Node: compiling, Next: matching, Prev: programming, Up: programming
+
+Compiling a Regular Expression
+------------------------------
+
+To compile a regular expression, you must supply a pattern buffer.
+This is a structure defined, in the include file `regex.h', as
+follows:
+
+ struct re_pattern_buffer
+ {
+ char *buffer /* Space holding the compiled pattern commands. */
+ int allocated /* Size of space that buffer points to */
+ int used /* Length of portion of buffer actually occupied */
+ char *fastmap; /* Pointer to fastmap, if any, or zero if none. */
+ /* re_search uses the fastmap, if there is one,
+ to skip quickly over totally implausible
+ characters */
+ char *translate;
+ /* Translate table to apply to characters before
+ comparing, or zero for no translation.
+ The translation is applied to a pattern when
+ it is compiled and to data when it is matched. */
+ char fastmap_accurate;
+ /* Set to zero when a new pattern is stored,
+ set to one when the fastmap is updated from it. */
+ };
+
+Before compiling a pattern, you must initialize the `buffer' field to
+point to a block of memory obtained with `malloc', and the
+`allocated' field to the size of that block, in bytes. The pattern
+compiler will replace this block with a larger one if necessary.
+
+You must also initialize the `translate' field to point to the
+translate table that you will use when you match the compiled
+pattern, or to zero if you will use no translate table when you
+match. *Note translation::.
+
+Then call `re_compile_pattern' to compile a regular expression into
+the buffer:
+
+ re_compile_pattern (REGEX, REGEX_SIZE, BUF)
+
+REGEX is the address of the regular expression (`char *'), REGEX_SIZE
+is its length (`int'), BUF is the address of the buffer (`struct
+re_pattern_buffer *').
+
+`re_compile_pattern' returns zero if it succeeds in compiling the
+regular expression. In that case, `*buf' now contains the results.
+Otherwise, `re_compile_pattern' returns a string which serves as an
+error message.
+
+After compiling, if you wish to search for the pattern, you must
+initialize the `fastmap' component of the pattern buffer. *Note
+searching::.
+
+
+
+File: regex, Node: matching, Next: searching, Prev: compiling, Up: programming
+
+Matching a Compiled Pattern
+---------------------------
+
+Once a regular expression has been compiled into a pattern buffer,
+you can match the pattern buffer against a string with `re_match'.
+
+ re_match (BUF, STRING, SIZE, POS, REGS)
+
+BUF is, once again, the address of the buffer (`struct
+re_pattern_buffer *'). STRING is the string to be matched (`char *').
+sIZE is the length of that string (`int'). POS is the position
+within the string at which to begin matching (`int'). The beginning
+of the string is position 0. REGS is described below. Normally it
+is zero. *Note registers::.
+
+`re_match' returns `-1' if the pattern does not match; otherwise, it
+returns the length of the portion of `string' which was matched.
+
+For example, suppose that BUF points to a buffer containing the
+result of compiling `x*', STRING points to `xxxxxy', and SIZE is `6'.
+Suppose that POS is `2'. Then the last three `x''s will be matched,
+so `re_match' will return `3'. If POS is zero, the value will be `5'.
+If POS is `5' or `6', the value will be zero, meaning that the null
+string was successfully matched. Note that since `x*' matches the
+empty string, it will never entirely fail.
+
+It is up to the caller to avoid passing a value of POS that results
+in matching outside the specified string. POS must not be negative
+and must not be greater than SIZE.
+
+
+
+File: regex, Node: searching, Next: translation, Prev: matching, Up: programming
+
+Searching for a Match
+---------------------
+
+Searching means trying successive starting positions for a match
+until a match is found. To search, you supply a compiled pattern
+buffer. Before searching you must initialize the `fastmap' field of
+the pattern buffer (see below).
+
+ re_search (BUF, STRING, SIZE, STARTPOS, RANGE, REGS)
+
+is called like `re_match' except that the POS argument is replaced by
+two arguments STARTPOS and RANGE. `re_search' tests for a match
+starting at index STARTPOS, then at `STARTPOS + 1', and so on. It
+tries RANGE consecutive positions before giving up and returning
+`-1'. If a match is found, `re_search' returns the index at which
+the match was found.
+
+If RANGE is negative, RE_SEARCH tries starting positions STARTPOS,
+`STARTPOS - 1', ... in that order. `|RANGE|' is the number of tries
+made.
+
+It is up to the caller to avoid passing value of STARTPOS and RANGE
+that result in matching outside the specified string. STARTPOS must
+be between zero and SIZE, inclusive, and so must `STARTPOS + RANGE -
+1' (if RANGE is positive) or `STARTPOS + RANGE + 1' (if RANGE is
+negative).
+
+If you may be searching over a long distance (that is, trying many
+different match starting points) with a compiled pattern, you should
+use a "fastmap" in it. This is a block of 256 bytes, whose address
+is placed in the `fastmap' component of the pattern buffer. The
+first time you search for a particular compiled pattern, the fastmap
+is set so that `FASTMAP[CH]' is nonzero if the character CH might
+possibly start a match for this pattern. `re_search' checks each
+character against the fastmap so that it can skip more quickly over
+non-matches.
+
+If you do not want a fastmap, store zero in the `fastmap' component
+of the pattern buffer before calling `re_search'.
+
+In either case, you must initialize this component in a pattern
+buffer before you can use that buffer in a search; but you can choose
+as an initial value either zero or the address of a suitable block of
+memory.
+
+If you compile a new pattern in an existing pattern buffer, it is not
+necessary to reinitialize the `fastmap' component (unless you wish to
+override your previous choice).
+
+
+
+File: regex, Node: translation, Next: registers, Prev: searching, Up: programming
+
+Translate Tables
+----------------
+
+With a translate table, you can apply a transformation to all
+characters before they are compared. For example, a table that maps
+lower case letters into upper case (or vice versa) causes differences
+in case to be ignored by matching.
+
+A translate table is a block of 256 bytes. Each character of raw
+data is used as an index in the translate table. The value found
+there is used instead of the original character. Each character in a
+regular expression, except for the syntactic constructs, is
+translated when the expression is compiled. Each character of a
+string being matched is translated whenever it is compared or tested.
+
+A suitable translate table to ignore differences in case maps all
+characters into themselves, except for lower case letters, which are
+mapped into the corresponding upper case letters. It could be
+initialized by:
+
+ for (i = 0; i < 0400; i++)
+ table[i] = i;
+ for (i = 'a'; i <= 'z'; i++)
+ table[i] = i - 040;
+
+You specify the use of a translate table by putting its address in
+the TRANSLATE component of the compiled pattern buffer. If this
+component is zero, no translation is done. Since both compilation
+and matching use the translate table, you must use the same table
+contents for both operations or confusing things will happen.
+
+
+
+File: regex, Node: registers, Next: split, Prev: translation, Up: programming
+
+Registers: or "What Did the `\( ... \)' Groupings Actually Match?"
+------------------------------------------------------------------
+
+If you want to find out, after the match, what each of the first nine
+`\( ... \)' groupings actually matched, you can pass the REGS
+argument to the match or search function. Pass the address of a
+structure of this type:
+
+ struct re_registers
+ {
+ int start[RE_NREGS];
+ int end[RE_NREGS];
+ };
+
+ `re_match' and `re_search' will store into this structure the data
+you want. `REGS->start[REG]' will be the index in STRING of the
+beginning of the data matched by the REG'th `\( ... \)' grouping, and
+`REGS->end[REG]' will be the index of the end of that data (the index
+of the first character beyond those matched). The values in the
+start and end arrays at indexes greater than the number of `\( ...
+\)' groupings present in the regular expression will be set to the
+value -1. Register numbers start at 1 and run to `RE_NREGS - 1'
+(normally `9'). `REGS->start[0]' and `REGS->end[0]' are similar but
+describe the extent of the substring matched by the entire pattern.
+
+ Both `struct re_registers' and `RE_NREGS' are defined in `regex.h'.
+
+
+
+File: regex, Node: split, Next: unix, Prev: registers, Up: programming
+
+Matching against Split Data
+---------------------------
+
+The functions `re_match_2' and `re_search_2' allow one to match in or
+search data which is divided into two strings.
+
+`re_match_2' works like `re_match' except that two data strings and
+sizes must be given.
+
+ re_match_2 (BUF, STRING1, SIZE1, STRING2, SIZE2, POS, REGS)
+
+The matcher regards the contents of STRING1 as effectively followed
+by the contents of STRING2, and matches the combined string against
+the pattern in BUF.
+
+`re_search_2' is likewise similar to `re_search':
+
+ re_search_2 (BUF, STRING1, SIZE1, STRING2, SIZE2, STARTPOS, RANGE, REGS)
+
+The value returned by RE_SEARCH_2 is an index into the combined data
+made up of STRING1 and STRING2. It never exceeds `SIZE1 + SIZE2'.
+The values returned in the REGS structure (if there is one) are
+likewise indices in the combined data.
+
+
+
+File: regex, Node: unix, Prev: split, Up: programming
+
+Unix-Compatible Entry Points
+----------------------------
+
+The standard Berkeley Unix way to compile a regular expression is to
+call `re_comp'. This function takes a single argument, the address
+of the regular expression, which is assumed to be terminated by a
+null character.
+
+`re_comp' does not ask you to specify a pattern buffer because it has
+its own pattern buffer -- just one. Using `re_comp', one may match
+only the most recently compiled regular expression.
+
+The value of `re_comp' is zero for success or else an error message
+string, as for `re_compile_pattern'.
+
+Calling `re_comp' with the null string as argument it has no effect;
+the contents of the buffer remain unchanged.
+
+The standard Berkeley Unix way to match the last regular expression
+compiled is to call `re_exec'. This takes a single argument, the
+address of the string to be matched. This string is assumed to be
+terminated by a null character. Matching is tried starting at each
+position in the string. `re_exec' returns `1' for success or `0' for
+failure. One cannot find out how long a substring was matched, nor
+what the `\( ... \)' groupings matched.
+
+
+
+Tag Table:
+Node: top85
+Node: syntax1706
+Node: directives3241
+Node: emacs10891
+Node: programming11653
+Node: compiling12381
+Node: matching14827
+Node: searching16269
+Node: translation18534
+Node: registers19952
+Node: split21245
+Node: unix22183
+
+End Tag Table
diff --git a/info/termcap b/info/termcap
new file mode 100644
index 00000000000..defe463a11e
--- /dev/null
+++ b/info/termcap
@@ -0,0 +1,76 @@
+This is Info file ../info/termcap, produced by Makeinfo-1.49 from the
+input file termcap.texi.
+
+ This file documents the termcap library of the GNU system.
+
+ Copyright (C) 1988 Free Software Foundation, Inc.
+
+ Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+ Permission is granted to copy and distribute modified versions of
+this manual under the conditions for verbatim copying, provided that
+the entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+ Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be stated in a
+translation approved by the Foundation.
+
+Indirect:
+termcap-1: 872
+termcap-2: 49021
+termcap-3: 92519
+
+Tag Table:
+(Indirect)
+Node: Top874
+Node: Introduction1514
+Node: Library3237
+Node: Preparation4249
+Node: Find5443
+Node: Interrogate8986
+Node: Initialize14288
+Node: Padding15923
+Node: Why Pad16579
+Node: Describe Padding18220
+Node: Output Padding19686
+Node: Parameters23294
+Node: Encode Parameters24950
+Node: Using Parameters31045
+Node: tparam31629
+Node: tgoto33689
+Node: Data Base36238
+Node: Format37110
+Node: Capability Format39193
+Node: Naming42237
+Node: Inheriting46800
+Node: Capabilities49023
+Node: Basic51859
+Node: Screen Size55929
+Node: Cursor Motion57666
+Node: Wrapping67310
+Node: Scrolling70132
+Node: Windows75146
+Node: Clearing75874
+Node: Insdel Line77633
+Node: Insdel Char82540
+Node: Standout92521
+Node: Underlining101573
+Node: Cursor Visibility103988
+Node: Bell104730
+Node: Keypad105275
+Node: Meta Key109991
+Node: Initialization110939
+Node: Pad Specs113298
+Node: Status Line115344
+Node: Half-Line117222
+Node: Printer118019
+Node: Summary119691
+Node: Var Index129892
+Node: Cap Index130600
+Node: Index137653
+
+End Tag Table
diff --git a/info/termcap-1 b/info/termcap-1
new file mode 100644
index 00000000000..bc786fff9bf
--- /dev/null
+++ b/info/termcap-1
@@ -0,0 +1,1147 @@
+This is Info file ../info/termcap, produced by Makeinfo-1.49 from the
+input file termcap.texi.
+
+ This file documents the termcap library of the GNU system.
+
+ Copyright (C) 1988 Free Software Foundation, Inc.
+
+ Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+ Permission is granted to copy and distribute modified versions of
+this manual under the conditions for verbatim copying, provided that
+the entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+ Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be stated in a
+translation approved by the Foundation.
+
+
+File: termcap, Node: Top, Next: Introduction, Prev: (DIR), Up: (DIR)
+
+* Menu:
+
+* Introduction::What is termcap? Why this manual?
+* Library:: The termcap library functions.
+* Data Base:: What terminal descriptions in `/etc/termcap' look like.
+* Capabilities::Definitions of the individual terminal capabilities:
+ how to write them in descriptions, and how to use
+ their values to do display updating.
+* Summary:: Brief table of capability names and their meanings.
+* Var Index:: Index of C functions and variables.
+* Cap Index:: Index of termcap capabilities.
+* Index:: Concept index.
+
+
+File: termcap, Node: Introduction, Next: Library, Prev: Top, Up: Top
+
+Introduction
+************
+
+ "Termcap" is a library and data base that enables programs to use
+display terminals in a terminal-independent manner. It originated in
+Berkeley Unix.
+
+ The termcap data base describes the capabilities of hundreds of
+different display terminals in great detail. Some examples of the
+information recorded for a terminal could include how many columns wide
+it is, what string to send to move the cursor to an arbitrary position
+(including how to encode the row and column numbers), how to scroll the
+screen up one or several lines, and how much padding is needed for such
+a scrolling operation.
+
+ The termcap library is provided for easy access this data base in
+programs that want to do terminal-independent character-based display
+output.
+
+ This manual describes the GNU version of the termcap library, which
+has some extensions over the Unix version. All the extensions are
+identified as such, so this manual also tells you how to use the Unix
+termcap.
+
+ The GNU version of the termcap library is available free as source
+code, for use in free programs, and runs on Unix and VMS systems (at
+least). You can find it in the GNU Emacs distribution in the files
+`termcap.c' and `tparam.c'.
+
+ This manual was written for the GNU project, whose goal is to
+develop a complete free operating system upward-compatible with Unix
+for user programs. The project is approximately two thirds complete.
+For more information on the GNU project, including the GNU Emacs editor
+and the mostly-portable optimizing C compiler, send one dollar to
+
+ Free Software Foundation
+ 675 Mass Ave
+ Cambridge, MA 02139
+
+
+File: termcap, Node: Library, Next: Data Base, Prev: Introduction, Up: Top
+
+The Termcap Library
+*******************
+
+ The termcap library is the application programmer's interface to the
+termcap data base. It contains functions for the following purposes:
+
+ * Finding the description of the user's terminal type (`tgetent').
+
+ * Interrogating the description for information on various topics
+ (`tgetnum', `tgetflag', `tgetstr').
+
+ * Computing and performing padding (`tputs').
+
+ * Encoding numeric parameters such as cursor positions into the
+ terminal-specific form required for display commands (`tparam',
+ `tgoto').
+
+* Menu:
+
+* Preparation:: Preparing to use the termcap library.
+* Find:: Finding the description of the terminal being used.
+* Interrogate:: Interrogating the description for particular capabilities.
+* Initialize:: Initialization for output using termcap.
+* Padding:: Outputting padding.
+* Parameters:: Encoding parameters such as cursor positions.
+
+
+File: termcap, Node: Preparation, Next: Find, Prev: Library, Up: Library
+
+Preparing to Use the Termcap Library
+====================================
+
+ To use the termcap library in a program, you need two kinds of
+preparation:
+
+ * The compiler needs declarations of the functions and variables in
+ the library.
+
+ On GNU systems, it suffices to include the header file `termcap.h'
+ in each source file that uses these functions and variables.
+
+ On Unix systems, there is often no such header file. Then you must
+ explictly declare the variables as external. You can do likewise
+ for the functions, or let them be implicitly declared and cast
+ their values from type `int' to the appropriate type.
+
+ We illustrate the declarations of the individual termcap library
+ functions with ANSI C prototypes because they show how to pass the
+ arguments. If you are not using the GNU C compiler, you probably
+ cannot use function prototypes, so omit the argument types and
+ names from your declarations.
+
+ * The linker needs to search the library. Usually either
+ `-ltermcap' or `-ltermlib' as an argument when linking will do
+ this.
+
+
+File: termcap, Node: Find, Next: Interrogate, Prev: Preparation, Up: Library
+
+Finding a Terminal Description: `tgetent'
+=========================================
+
+ An application program that is going to use termcap must first look
+up the description of the terminal type in use. This is done by calling
+`tgetent', whose declaration in ANSI Standard C looks like:
+
+ int tgetent (char *BUFFER, char *TERMTYPE);
+
+This function finds the description and remembers it internally so that
+you can interrogate it about specific terminal capabilities (*note
+Interrogate::.).
+
+ The argument TERMTYPE is a string which is the name for the type of
+terminal to look up. Usually you would obtain this from the environment
+variable `TERM' using `getenv ("TERM")'.
+
+ If you are using the GNU version of termcap, you can alternatively
+ask `tgetent' to allocate enough space. Pass a null pointer for
+BUFFER, and `tgetent' itself allocates the storage using `malloc'. In
+this case the returned value on success is the address of the storage,
+cast to `int'. But normally there is no need for you to look at the
+address. Do not free the storage yourself.
+
+ With the Unix version of termcap, you must allocate space for the
+description yourself and pass the address of the space as the argument
+BUFFER. There is no way you can tell how much space is needed, so the
+convention is to allocate a buffer 2048 characters long and assume that
+is enough. (Formerly the convention was to allocate 1024 characters and
+assume that was enough. But one day, for one kind of terminal, that was
+not enough.)
+
+ No matter how the space to store the description has been obtained,
+termcap records its address internally for use when you later
+interrogate the description with `tgetnum', `tgetstr' or `tgetflag'. If
+the buffer was allocated by termcap, it will be freed by termcap too if
+you call `tgetent' again. If the buffer was provided by you, you must
+make sure that its contents remain unchanged for as long as you still
+plan to interrogate the description.
+
+ The return value of `tgetent' is -1 if there is some difficulty
+accessing the data base of terminal types, 0 if the data base is
+accessible but the specified type is not defined in it, and some other
+value otherwise.
+
+ Here is how you might use the function `tgetent':
+
+ #ifdef unix
+ static char term_buffer[2048];
+ #else
+ #define term_buffer 0
+ #endif
+
+ init_terminal_data ()
+ {
+ char *termtype = getenv ("TERM");
+ int success;
+
+ if (termtype == 0)
+ fatal ("Specify a terminal type with `setenv TERM <yourtype>'.\n");
+
+ success = tgetent (term_buffer, termtype);
+ if (success < 0)
+ fatal ("Could not access the termcap data base.\n");
+ if (success == 0)
+ fatal ("Terminal type `%s' is not defined.\n", termtype);
+ }
+
+Here we assume the function `fatal' prints an error message and exits.
+
+ If the environment variable `TERMCAP' is defined, its value is used
+to override the terminal type data base. The function `tgetent' checks
+the value of `TERMCAP' automatically. If the value starts with `/'
+then it is taken as a file name to use as the data base file, instead
+of `/etc/termcap' which is the standard data base. If the value does
+not start with `/' then it is itself used as the terminal description,
+provided that the terminal type TERMTYPE is among the types it claims
+to apply to. *Note Data Base::, for information on the format of a
+terminal description.
+
+
+File: termcap, Node: Interrogate, Next: Initialize, Prev: Find, Up: Library
+
+Interrogating the Terminal Description
+======================================
+
+ Each piece of information recorded in a terminal description is
+called a "capability". Each defined terminal capability has a
+two-letter code name and a specific meaning. For example, the number
+of columns is named `co'. *Note Capabilities::, for definitions of all
+the standard capability names.
+
+ Once you have found the proper terminal description with `tgetent'
+(*note Find::.), your application program must "interrogate" it for
+various terminal capabilities. You must specify the two-letter code of
+the capability whose value you seek.
+
+ Capability values can be numeric, boolean (capability is either
+present or absent) or strings. Any particular capability always has
+the same value type; for example, `co' always has a numeric value,
+while `am' (automatic wrap at margin) is always a flag, and `cm'
+(cursor motion command) always has a string value. The documentation
+of each capability says which type of value it has.
+
+ There are three functions to use to get the value of a capability,
+depending on the type of value the capability has. Here are their
+declarations in ANSI C:
+
+ int tgetnum (char *NAME);
+ int tgetflag (char *NAME);
+ char *tgetstr (char *NAME, char **AREA);
+
+`tgetnum'
+ Use `tgetnum' to get a capability value that is numeric. The
+ argument NAME is the two-letter code name of the capability. If
+ the capability is present, `tgetnum' returns the numeric value
+ (which is nonnegative). If the capability is not mentioned in the
+ terminal description, `tgetnum' returns -1.
+
+`tgetflag'
+ Use `tgetflag' to get a boolean value. If the capability NAME is
+ present in the terminal description, `tgetflag' returns 1;
+ otherwise, it returns 0.
+
+`tgetstr'
+ Use `tgetstr' to get a string value. It returns a pointer to a
+ string which is the capability value, or a null pointer if the
+ capability is not present in the terminal description.
+
+ There are two ways `tgetstr' can find space to store the string
+ value:
+
+ * You can ask `tgetstr' to allocate the space. Pass a null
+ pointer for the argument AREA, and `tgetstr' will use
+ `malloc' to allocate storage big enough for the value.
+ Termcap will never free this storage or refer to it again; you
+ should free it when you are finished with it.
+
+ This method is more robust, since there is no need to guess
+ how much space is needed. But it is supported only by the GNU
+ termcap library.
+
+ * You can provide the space. Provide for the argument AREA the
+ address of a pointer variable of type `char *'. Before
+ calling `tgetstr', initialize the variable to point at
+ available space. Then `tgetstr' will store the string value
+ in that space and will increment the pointer variable to
+ point after the space that has been used. You can use the
+ same pointer variable for many calls to `tgetstr'.
+
+ There is no way to determine how much space is needed for a
+ single string, and no way for you to prevent or handle
+ overflow of the area you have provided. However, you can be
+ sure that the total size of all the string values you will
+ obtain from the terminal description is no greater than the
+ size of the description (unless you get the same capability
+ twice). You can determine that size with `strlen' on the
+ buffer you provided to `tgetent'. See below for an example.
+
+ Providing the space yourself is the only method supported by
+ the Unix version of termcap.
+
+ Note that you do not have to specify a terminal type or terminal
+description for the interrogation functions. They automatically use the
+description found by the most recent call to `tgetent'.
+
+ Here is an example of interrogating a terminal description for
+various capabilities, with conditionals to select between the Unix and
+GNU methods of providing buffer space.
+
+ char *tgetstr ();
+
+ char *cl_string, *cm_string;
+ int height;
+ int width;
+ int auto_wrap;
+
+ char PC; /* For tputs. */
+ char *BC; /* For tgoto. */
+ char *UP;
+
+ interrogate_terminal ()
+ {
+ #ifdef UNIX
+ /* Here we assume that an explicit term_buffer
+ was provided to tgetent. */
+ char *buffer
+ = (char *) malloc (strlen (term_buffer));
+ #define BUFFADDR &buffer
+ #else
+ #define BUFFADDR 0
+ #endif
+
+ char *temp;
+
+ /* Extract information we will use. */
+ cl_string = tgetstr ("cl", BUFFADDR);
+ cm_string = tgetstr ("cm", BUFFADDR);
+ auto_wrap = tgetflag ("am");
+ height = tgetnum ("li");
+ width = tgetnum ("co");
+
+ /* Extract information that termcap functions use. */
+ temp = tgetstr ("pc", BUFFADDR);
+ PC = temp ? *temp : 0;
+ BC = tgetstr ("le", BUFFADDR);
+ UP = tgetstr ("up", BUFFADDR);
+ }
+
+*Note Padding::, for information on the variable `PC'. *Note Using
+Parameters::, for information on `UP' and `BC'.
+
+
+File: termcap, Node: Initialize, Next: Padding, Prev: Interrogate, Up: Library
+
+Initialization for Use of Termcap
+=================================
+
+ Before starting to output commands to a terminal using termcap, an
+application program should do two things:
+
+ * Initialize various global variables which termcap library output
+ functions refer to. These include `PC' and `ospeed' for padding
+ (*note Output Padding::.) and `UP' and `BC' for cursor motion
+ (*note tgoto::.).
+
+ * Tell the kernel to turn off alteration and padding of
+ horizontal-tab characters sent to the terminal.
+
+ To turn off output processing in Berkeley Unix you would use `ioctl'
+with code `TIOCLSET' to set the bit named `LLITOUT', and clear the bits
+`ANYDELAY' using `TIOCSETN'. In POSIX or System V, you must clear the
+bit named `OPOST'. Refer to the system documentation for details.
+
+ If you do not set the terminal flags properly, some older terminals
+will not work. This is because their commands may contain the
+characters that normally signify newline, carriage return and
+horizontal tab--characters which the kernel thinks it ought to modify
+before output.
+
+ When you change the kernel's terminal flags, you must arrange to
+restore them to their normal state when your program exits. This
+implies that the program must catch fatal signals such as `SIGQUIT' and
+`SIGINT' and restore the old terminal flags before actually terminating.
+
+ Modern terminals' commands do not use these special characters, so
+if you do not care about problems with old terminals, you can leave the
+kernel's terminal flags unaltered.
+
+
+File: termcap, Node: Padding, Next: Parameters, Prev: Initialize, Up: Library
+
+Padding
+=======
+
+ "Padding" means outputting null characters following a terminal
+display command that takes a long time to execute. The terminal
+description says which commands require padding and how much; the
+function `tputs', described below, outputs a terminal command while
+extracting from it the padding information, and then outputs the
+padding that is necessary.
+
+* Menu:
+
+* Why Pad:: Explanation of padding.
+* Describe Padding:: The data base says how much padding a terminal needs.
+* Output Padding:: Using `tputs' to output the needed padding.
+
+
+File: termcap, Node: Why Pad, Next: Describe Padding, Prev: Padding, Up: Padding
+
+Why Pad, and How
+----------------
+
+ Most types of terminal have commands that take longer to execute
+than they do to send over a high-speed line. For example, clearing the
+screen may take 20msec once the entire command is received. During
+that time, on a 9600 bps line, the terminal could receive about 20
+additional output characters while still busy clearing the screen.
+Every terminal has a certain amount of buffering capacity to remember
+output characters that cannot be processed yet, but too many slow
+commands in a row can cause the buffer to fill up. Then any additional
+output that cannot be processed immediately will be lost.
+
+ To avoid this problem, we normally follow each display command with
+enough useless charaters (usually null characters) to fill up the time
+that the display command needs to execute. This does the job if the
+terminal throws away null characters without using up space in the
+buffer (which most terminals do). If enough padding is used, no output
+can ever be lost. The right amount of padding avoids loss of output
+without slowing down operation, since the time used to transmit padding
+is time that nothing else could be done.
+
+ The number of padding characters needed for an operation depends on
+the line speed. In fact, it is proportional to the line speed. A 9600
+baud line transmits about one character per msec, so the clear screen
+command in the example above would need about 20 characters of padding.
+ At 1200 baud, however, only about 3 characters of padding are needed
+to fill up 20msec.
+
+
+File: termcap, Node: Describe Padding, Next: Output Padding, Prev: Why Pad, Up: Padding
+
+Specifying Padding in a Terminal Description
+--------------------------------------------
+
+ In the terminal description, the amount of padding required by each
+display command is recorded as a sequence of digits at the front of the
+command. These digits specify the padding time in msec. They can be
+followed optionally by a decimal point and one more digit, which is a
+number of tenths of msec.
+
+ Sometimes the padding needed by a command depends on the cursor
+position. For example, the time taken by an "insert line" command is
+usually proportional to the number of lines that need to be moved down
+or cleared. An asterisk (`*') following the padding time says that the
+time should be multiplied by the number of screen lines affected by the
+command.
+
+ :al=1.3*\E[L:
+
+is used to describe the "insert line" command for a certain terminal.
+The padding required is 1.3 msec per line affected. The command itself
+is `ESC [ L'.
+
+ The padding time specified in this way tells `tputs' how many pad
+characters to output. *Note Output Padding::.
+
+ Two special capability values affect padding for all commands.
+These are the `pc' and `pb'. The variable `pc' specifies the character
+to pad with, and `pb' the speed below which no padding is needed. The
+defaults for these variables, a null character and 0, are correct for
+most terminals. *Note Pad Specs::.
+
+
+File: termcap, Node: Output Padding, Prev: Describe Padding, Up: Padding
+
+Performing Padding with `tputs'
+-------------------------------
+
+ Use the termcap function `tputs' to output a string containing an
+optional padding spec of the form described above (*note Describe
+Padding::.). The function `tputs' strips off and decodes the padding
+spec, outputs the rest of the string, and then outputs the appropriate
+padding. Here is its declaration in ANSI C:
+
+ char PC;
+ short ospeed;
+
+ int tputs (char *STRING, int NLINES, int (*OUTFUN) ());
+
+ Here STRING is the string (including padding spec) to be output;
+NLINES is the number of lines affected by the operation, which is used
+to multiply the amount of padding if the padding spec ends with a `*'.
+Finally, OUTFUN is a function (such as `fputchar') that is called to
+output each character. When actually called, OUTFUN should expect one
+argument, a character.
+
+ The operation of `tputs' is controlled by two global variables,
+`ospeed' and `PC'. The value of `ospeed' is supposed to be the
+terminal output speed, encoded as in the `ioctl' system call which gets
+the speed information. This is needed to compute the number of padding
+characters. The value of `PC' is the character used for padding.
+
+ You are responsible for storing suitable values into these variables
+before using `tputs'. The value stored into the `PC' variable should be
+taken from the `pc' capability in the terminal description (*note Pad
+Specs::.). Store zero in `PC' if there is no `pc' capability.
+
+ The argument NLINES requires some thought. Normally, it should be
+the number of lines whose contents will be cleared or moved by the
+command. For cursor motion commands, or commands that do editing within
+one line, use the value 1. For most commands that affect multiple
+lines, such as `al' (insert a line) and `cd' (clear from the cursor to
+the end of the screen), NLINES should be the screen height minus the
+current vertical position (origin 0). For multiple insert and scroll
+commands such as `AL' (insert multiple lines), that same value for
+NLINES is correct; the number of lines being inserted is not correct.
+
+ If a "scroll window" feature is used to reduce the number of lines
+affected by a command, the value of NLINES should take this into
+account. This is because the delay time required depends on how much
+work the terminal has to do, and the scroll window feature reduces the
+work. *Note Scrolling::.
+
+ Commands such as `ic' and `dc' (insert or delete characters) are
+problematical because the padding needed by these commands is
+proportional to the number of characters affected, which is the number
+of columns from the cursor to the end of the line. It would be nice to
+have a way to specify such a dependence, and there is no need for
+dependence on vertical position in these commands, so it is an obvious
+idea to say that for these commands NLINES should really be the number
+of columns affected. However, the definition of termcap clearly says
+that NLINES is always the number of lines affected, even in this case,
+where it is always 1. It is not easy to change this rule now, because
+too many programs and terminal descriptions have been written to follow
+it.
+
+ Because NLINES is always 1 for the `ic' and `dc' strings, there is
+no reason for them to use `*', but some of them do. These should be
+corrected by deleting the `*'. If, some day, such entries have
+disappeared, it may be possible to change to a more useful convention
+for the NLINES argument for these operations without breaking any
+programs.
+
+
+File: termcap, Node: Parameters, Prev: Padding, Up: Library
+
+Filling In Parameters
+=====================
+
+ Some terminal control strings require numeric "parameters". For
+example, when you move the cursor, you need to say what horizontal and
+vertical positions to move it to. The value of the terminal's `cm'
+capability, which says how to move the cursor, cannot simply be a
+string of characters; it must say how to express the cursor position
+numbers and where to put them within the command.
+
+ The specifications of termcap include conventions as to which
+string-valued capabilities require parameters, how many parameters, and
+what the parameters mean; for example, it defines the `cm' string to
+take two parameters, the vertical and horizontal positions, with 0,0
+being the upper left corner. These conventions are described where the
+individual commands are documented.
+
+ Termcap also defines a language used within the capability
+definition for specifying how and where to encode the parameters for
+output. This language uses character sequences starting with `%'.
+(This is the same idea as `printf', but the details are different.)
+The language for parameter encoding is described in this section.
+
+ A program that is doing display output calls the functions `tparam'
+or `tgoto' to encode parameters according to the specifications. These
+functions produce a string containing the actual commands to be output
+(as well a padding spec which must be processed with `tputs'; *note
+Padding::.).
+
+* Menu:
+
+* Encode Parameters:: The language for encoding parameters.
+* Using Parameters:: Outputting a string command with parameters.
+
+
+File: termcap, Node: Encode Parameters, Next: Using Parameters, Prev: Parameters, Up: Parameters
+
+Describing the Encoding
+-----------------------
+
+ A terminal command string that requires parameters contains special
+character sequences starting with `%' to say how to encode the
+parameters. These sequences control the actions of `tparam' and
+`tgoto'.
+
+ The parameters values passed to `tparam' or `tgoto' are considered
+to form a vector. A pointer into this vector determines the next
+parameter to be processed. Some of the `%'-sequences encode one
+parameter and advance the pointer to the next parameter. Other
+`%'-sequences alter the pointer or alter the parameter values without
+generating output.
+
+ For example, the `cm' string for a standard ANSI terminal is written
+as `\E[%i%d;%dH'. (`\E' stands for ESC.) `cm' by convention always
+requires two parameters, the vertical and horizontal goal positions, so
+this string specifies the encoding of two parameters. Here `%i'
+increments the two values supplied, and each `%d' encodes one of the
+values in decimal. If the cursor position values 20,58 are encoded
+with this string, the result is `\E[21;59H'.
+
+ First, here are the `%'-sequences that generate output. Except for
+`%%', each of them encodes one parameter and advances the pointer to
+the following parameter.
+
+`%%'
+ Output a single `%'. This is the only way to represent a literal
+ `%' in a terminal command with parameters. `%%' does not use up a
+ parameter.
+
+`%d'
+ As in `printf', output the next parameter in decimal.
+
+`%2'
+ Like `%02d' in `printf': output the next parameter in decimal, and
+ always use at least two digits.
+
+`%3'
+ Like `%03d' in `printf': output the next parameter in decimal, and
+ always use at least three digits. Note that `%4' and so on are
+ *not* defined.
+
+`%.'
+ Output the next parameter as a single character whose ASCII code is
+ the parameter value. Like `%c' in `printf'.
+
+`%+CHAR'
+ Add the next parameter to the character CHAR, and output the
+ resulting character. For example, `%+ ' represents 0 as a space,
+ 1 as `!', etc.
+
+ The following `%'-sequences specify alteration of the parameters
+(their values, or their order) rather than encoding a parameter for
+output. They generate no output; they are used only for their side
+effects on the parameters. Also, they do not advance the "next
+parameter" pointer except as explicitly stated. Only `%i', `%r' and
+`%>' are defined in standard Unix termcap. The others are GNU
+extensions.
+
+`%i'
+ Increment the next two parameters. This is used for terminals that
+ expect cursor positions in origin 1. For example, `%i%d,%d' would
+ output two parameters with `1' for 0, `2' for 1, etc.
+
+`%r'
+ Interchange the next two parameters. This is used for terminals
+ whose cursor positioning command expects the horizontal position
+ first.
+
+`%s'
+ Skip the next parameter. Do not output anything.
+
+`%b'
+ Back up one parameter. The last parameter used will become once
+ again the next parameter to be output, and the next output command
+ will use it. Using `%b' more than once, you can back up any
+ number of parameters, and you can refer to each parameter any
+ number of times.
+
+`%>C1C2'
+ Conditionally increment the next parameter. Here C1 and C2 are
+ characters which stand for their ASCII codes as numbers. If the
+ next parameter is greater than the ASCII code of C1, the ASCII
+ code of C2 is added to it.
+
+`%a OP TYPE POS'
+ Perform arithmetic on the next parameter, do not use it up, and do
+ not output anything. Here OP specifies the arithmetic operation,
+ while TYPE and POS together specify the other operand.
+
+ Spaces are used above to separate the operands for clarity; the
+ spaces don't appear in the data base, where this sequence is
+ exactly five characters long.
+
+ The character OP says what kind of arithmetic operation to
+ perform. It can be any of these characters:
+
+ `='
+ assign a value to the next parameter, ignoring its old value.
+ The new value comes from the other operand.
+
+ `+'
+ add the other operand to the next parameter.
+
+ `-'
+ subtract the other operand from the next parameter.
+
+ `*'
+ multiply the next parameter by the other operand.
+
+ `/'
+ divide the next parameter by the other operand.
+
+ The "other operand" may be another parameter's value or a constant;
+ the character TYPE says which. It can be:
+
+ `p'
+ Use another parameter. The character POS says which
+ parameter to use. Subtract 64 from its ASCII code to get the
+ position of the desired parameter relative to this one. Thus,
+ the character `A' as POS means the parameter after the next
+ one; the character `?' means the parameter before the next
+ one.
+
+ `c'
+ Use a constant value. The character POS specifies the value
+ of the constant. The 0200 bit is cleared out, so that 0200
+ can be used to represent zero.
+
+ The following `%'-sequences are special purpose hacks to compensate
+for the weird designs of obscure terminals. They modify the next
+parameter or the next two parameters but do not generate output and do
+not use up any parameters. `%m' is a GNU extension; the others are
+defined in standard Unix termcap.
+
+`%n'
+ Exclusive-or the next parameter with 0140, and likewise the
+ parameter after next.
+
+`%m'
+ Complement all the bits of the next parameter and the parameter
+ after next.
+
+`%B'
+ Encode the next parameter in BCD. It alters the value of the
+ parameter by adding six times the quotient of the parameter by ten.
+ Here is a C statement that shows how the new value is computed:
+
+ PARM = (PARM / 10) * 16 + PARM % 10;
+
+`%D'
+ Transform the next parameter as needed by Delta Data terminals.
+ This involves subtracting twice the remainder of the parameter by
+ 16.
+
+ PARM -= 2 * (PARM % 16);
+
+
+File: termcap, Node: Using Parameters, Prev: Encode Parameters, Up: Parameters
+
+Sending Display Commands with Parameters
+----------------------------------------
+
+ The termcap library functions `tparam' and `tgoto' serve as the
+analog of `printf' for terminal string parameters. The newer function
+`tparam' is a GNU extension, more general but missing from Unix
+termcap. The original parameter-encoding function is `tgoto', which is
+preferable for cursor motion.
+
+* Menu:
+
+* tparam:: The general case, for GNU termcap only.
+* tgoto:: The special case of cursor motion.
+
+
+File: termcap, Node: tparam, Next: tgoto, Prev: Using Parameters, Up: Using Parameters
+
+`tparam'
+........
+
+ The function `tparam' can encode display commands with any number of
+parameters and allows you to specify the buffer space. It is the
+preferred function for encoding parameters for all but the `cm'
+capability. Its ANSI C declaration is as follows:
+
+ char *tparam (char *CTLSTRING, char *BUFFER, int SIZE, int PARM1,...)
+
+ The arguments are a control string CTLSTRING (the value of a terminal
+capability, presumably), an output buffer BUFFER and SIZE, and any
+number of integer parameters to be encoded. The effect of `tparam' is
+to copy the control string into the buffer, encoding parameters
+according to the `%' sequences in the control string.
+
+ You describe the output buffer by its address, BUFFER, and its size
+in bytes, SIZE. If the buffer is not big enough for the data to be
+stored in it, `tparam' calls `malloc' to get a larger buffer. In
+either case, `tparam' returns the address of the buffer it ultimately
+uses. If the value equals BUFFER, your original buffer was used.
+Otherwise, a new buffer was allocated, and you must free it after you
+are done with printing the results. If you pass zero for SIZE and
+BUFFER, `tparam' always allocates the space with `malloc'.
+
+ All capabilities that require parameters also have the ability to
+specify padding, so you should use `tputs' to output the string
+produced by `tparam'. *Note Padding::. Here is an example.
+
+ {
+ char *buf;
+ char buffer[40];
+
+ buf = tparam (command, buffer, 40, parm);
+ tputs (buf, 1, fputchar);
+ if (buf != buffer)
+ free (buf);
+ }
+
+ If a parameter whose value is zero is encoded with `%.'-style
+encoding, the result is a null character, which will confuse `tputs'.
+This would be a serious problem, but luckily `%.' encoding is used only
+by a few old models of terminal, and only for the `cm' capability. To
+solve the problem, use `tgoto' rather than `tparam' to encode the `cm'
+capability.
+
+
+File: termcap, Node: tgoto, Prev: tparam, Up: Using Parameters
+
+`tgoto'
+.......
+
+ The special case of cursor motion is handled by `tgoto'. There are
+two reasons why you might choose to use `tgoto':
+
+ * For Unix compatibility, because Unix termcap does not have
+ `tparam'.
+
+ * For the `cm' capability, since `tgoto' has a special feature to
+ avoid problems with null characters, tabs and newlines on certain
+ old terminal types that use `%.' encoding for that capability.
+
+ Here is how `tgoto' might be declared in ANSI C:
+
+ char *tgoto (char *CSTRING, int HPOS, int VPOS)
+
+ There are three arguments, the terminal description's `cm' string and
+the two cursor position numbers; `tgoto' computes the parametrized
+string in an internal static buffer and returns the address of that
+buffer. The next time you use `tgoto' the same buffer will be reused.
+
+ Parameters encoded with `%.' encoding can generate null characters,
+tabs or newlines. These might cause trouble: the null character because
+`tputs' would think that was the end of the string, the tab because the
+kernel or other software might expand it into spaces, and the newline
+becaue the kernel might add a carriage-return, or padding characters
+normally used for a newline. To prevent such problems, `tgoto' is
+careful to avoid these characters. Here is how this works: if the
+target cursor position value is such as to cause a problem (that is to
+say, zero, nine or ten), `tgoto' increments it by one, then compensates
+by appending a string to move the cursor back or up one position.
+
+ The compensation strings to use for moving back or up are found in
+global variables named `BC' and `UP'. These are actual external C
+variables with upper case names; they are declared `char *'. It is up
+to you to store suitable values in them, normally obtained from the
+`le' and `up' terminal capabilities in the terminal description with
+`tgetstr'. Alternatively, if these two variables are both zero, the
+feature of avoiding nulls, tabs and newlines is turned off.
+
+ It is safe to use `tgoto' for commands other than `cm' only if you
+have stored zero in `BC' and `UP'.
+
+ Note that `tgoto' reverses the order of its operands: the horizontal
+position comes before the vertical position in the arguments to
+`tgoto', even though the vertical position comes before the horizontal
+in the parameters of the `cm' string. If you use `tgoto' with a
+command such as `AL' that takes one parameter, you must pass the
+parameter to `tgoto' as the "vertical position".
+
+
+File: termcap, Node: Data Base, Next: Capabilities, Prev: Library, Up: Top
+
+The Format of the Data Base
+***************************
+
+ The termcap data base of terminal descriptions is stored in the file
+`/etc/termcap'. It contains terminal descriptions, blank lines, and
+comments.
+
+ A terminal description starts with one or more names for the
+terminal type. The information in the description is a series of
+"capability names" and values. The capability names have standard
+meanings (*note Capabilities::.) and their values describe the terminal.
+
+* Menu:
+
+* Format:: Overall format of a terminal description.
+* Capability Format:: Format of capabilities within a description.
+* Naming:: Naming conventions for terminal types.
+* Inheriting:: Inheriting part of a description from
+ a related terminal type.
+
+
+File: termcap, Node: Format, Next: Capability Format, Prev: Data Base, Up: Data Base
+
+Terminal Description Format
+===========================
+
+ Aside from comments (lines starting with `#', which are ignored),
+each nonblank line in the termcap data base is a terminal description.
+A terminal description is nominally a single line, but it can be split
+into multiple lines by inserting the two characters `\ newline'. This
+sequence is ignored wherever it appears in a description.
+
+ The preferred way to split the description is between capabilities:
+insert the four characters `: \ newline tab' immediately before any
+colon. This allows each sub-line to start with some indentation. This
+works because, after the `\ newline' are ignored, the result is `: tab
+:'; the first colon ends the preceding capability and the second colon
+starts the next capability. If you split with `\ newline' alone, you
+may not add any indentation after them.
+
+ Here is a real example of a terminal description:
+
+ dw|vt52|DEC vt52:\
+ :cr=^M:do=^J:nl=^J:bl=^G:\
+ :le=^H:bs:cd=\EJ:ce=\EK:cl=\EH\EJ:cm=\EY%+ %+ :co#80:li#24:\
+ :nd=\EC:ta=^I:pt:sr=\EI:up=\EA:\
+ :ku=\EA:kd=\EB:kr=\EC:kl=\ED:kb=^H:
+
+ Each terminal description begins with several names for the terminal
+type. The names are separated by `|' characters, and a colon ends the
+last name. The first name should be two characters long; it exists
+only for the sake of very old Unix systems and is never used in modern
+systems. The last name should be a fully verbose name such as "DEC
+vt52" or "Ann Arbor Ambassador with 48 lines". The other names should
+include whatever the user ought to be able to specify to get this
+terminal type, such as `vt52' or `aaa-48'. *Note Naming::, for
+information on how to choose terminal type names.
+
+ After the terminal type names come the terminal capabilities,
+separated by colons and with a colon after the last one. Each
+capability has a two-letter name, such as `cm' for "cursor motion
+string" or `li' for "number of display lines".
+
+
+File: termcap, Node: Capability Format, Next: Naming, Prev: Format, Up: Data Base
+
+Writing the Capabilities
+========================
+
+ There are three kinds of capabilities: flags, numbers, and strings.
+Each kind has its own way of being written in the description. Each
+defined capability has by convention a particular kind of value; for
+example, `li' always has a numeric value and `cm' always a string value.
+
+ A flag capability is thought of as having a boolean value: the value
+is true if the capability is present, false if not. When the
+capability is present, just write its name between two colons.
+
+ A numeric capability has a value which is a nonnegative number.
+Write the capability name, a `#', and the number, between two colons.
+For example, `...:li#48:...' is how you specify the `li' capability for
+48 lines.
+
+ A string-valued capability has a value which is a sequence of
+characters. Usually these are the characters used to perform some
+display operation. Write the capability name, a `=', and the characters
+of the value, between two colons. For example,
+`...:cm=\E[%i%d;%dH:...' is how the cursor motion command for a
+standard ANSI terminal would be specified.
+
+ Special characters in the string value can be expressed using
+`\'-escape sequences as in C; in addition, `\E' stands for ESC. `^' is
+also a kind of escape character; `^' followed by CHAR stands for the
+control-equivalent of CHAR. Thus, `^a' stands for the character
+control-a, just like `\001'. `\' and `^' themselves can be represented
+as `\\' and `\^'.
+
+ To include a colon in the string, you must write `\072'. You might
+ask, "Why can't `\:' be used to represent a colon?" The reason is that
+the interrogation functions do not count slashes while looking for a
+capability. Even if `:ce=ab\:cd:' were interpreted as giving the `ce'
+capability the value `ab:cd', it would also appear to define `cd' as a
+flag.
+
+ The string value will often contain digits at the front to specify
+padding (*note Padding::.) and/or `%'-sequences within to specify how
+to encode parameters (*note Parameters::.). Although these things are
+not to be output literally to the terminal, they are considered part of
+the value of the capability. They are special only when the string
+value is processed by `tputs', `tparam' or `tgoto'. By contrast, `\'
+and `^' are considered part of the syntax for specifying the characters
+in the string.
+
+ Let's look at the VT52 example again:
+
+ dw|vt52|DEC vt52:\
+ :cr=^M:do=^J:nl=^J:bl=^G:\
+ :le=^H:bs:cd=\EJ:ce=\EK:cl=\EH\EJ:cm=\EY%+ %+ :co#80:li#24:\
+ :nd=\EC:ta=^I:pt:sr=\EI:up=\EA:\
+ :ku=\EA:kd=\EB:kr=\EC:kl=\ED:kb=^H:
+
+ Here we see the numeric-valued capabilities `co' and `li', the flags
+`bs' and `pt', and many string-valued capabilities. Most of the
+strings start with ESC represented as `\E'. The rest contain control
+characters represented using `^'. The meanings of the individual
+capabilities are defined elsewhere (*note Capabilities::.).
+
+
+File: termcap, Node: Naming, Next: Inheriting, Prev: Capability Format, Up: Data Base
+
+Terminal Type Name Conventions
+==============================
+
+ There are conventions for choosing names of terminal types. For one
+thing, all letters should be in lower case. The terminal type for a
+terminal in its most usual or most fundamental mode of operation should
+not have a hyphen in it.
+
+ If the same terminal has other modes of operation which require
+different terminal descriptions, these variant descriptions are given
+names made by adding suffixes with hyphens. Such alternate descriptions
+are used for two reasons:
+
+ * When the terminal has a switch that changes its behavior. Since
+ the computer cannot tell how the switch is set, the user must tell
+ the computer by choosing the appropriate terminal type name.
+
+ For example, the VT-100 has a setup flag that controls whether the
+ cursor wraps at the right margin. If this flag is set to "wrap",
+ you must use the terminal type `vt100-am'. Otherwise you must use
+ `vt100-nam'. Plain `vt100' is defined as a synonym for either
+ `vt100-am' or `vt100-nam' depending on the preferences of the
+ local site.
+
+ The standard suffix `-am' stands for "automatic margins".
+
+ * To give the user a choice in how to use the terminal. This is done
+ when the terminal has a switch that the computer normally controls.
+
+ For example, the Ann Arbor Ambassador can be configured with many
+ screen sizes ranging from 20 to 60 lines. Fewer lines make bigger
+ characters but more lines let you see more of what you are editing.
+ As a result, users have different preferences. Therefore, termcap
+ provides terminal types for many screen sizes. If you choose type
+ `aaa-30', the terminal will be configured to use 30 lines; if you
+ choose `aaa-48', 48 lines will be used, and so on.
+
+ Here is a list of standard suffixes and their conventional meanings:
+
+`-w'
+ Short for "wide". This is a mode that gives the terminal more
+ columns than usual. This is normally a user option.
+
+`-am'
+ "Automatic margins". This is an alternate description for use when
+ the terminal's margin-wrap switch is on; it contains the `am'
+ flag. The implication is that normally the switch is off and the
+ usual description for the terminal says that the switch is off.
+
+`-nam'
+ "No automatic margins". The opposite of `-am', this names an
+ alternative description which lacks the `am' flag. This implies
+ that the terminal is normally operated with the margin-wrap switch
+ turned on, and the normal description of the terminal says so.
+
+`-na'
+ "No arrows". This terminal description initializes the terminal to
+ keep its arrow keys in local mode. This is a user option.
+
+`-rv'
+ "Reverse video". This terminal description causes text output for
+ normal video to appear as reverse, and text output for reverse
+ video to come out as normal. Often this description differs from
+ the usual one by interchanging the two strings which turn reverse
+ video on and off.
+
+ This is a user option; you can choose either the "reverse video"
+ variant terminal type or the normal terminal type, and termcap will
+ obey.
+
+`-s'
+ "Status". Says to enable use of a status line which ordinary
+ output does not touch (*note Status Line::.).
+
+ Some terminals have a special line that is used only as a status
+ line. For these terminals, there is no need for an `-s' variant;
+ the status line commands should be defined by default. On other
+ terminals, enabling a status line means removing one screen line
+ from ordinary use and reducing the effective screen height. For
+ these terminals, the user can choose the `-s' variant type to
+ request use of a status line.
+
+`-NLINES'
+ Says to operate with NLINES lines on the screen, for terminals
+ such as the Ambassador which provide this as an option. Normally
+ this is a user option; by choosing the terminal type, you control
+ how many lines termcap will use.
+
+`-NPAGESp'
+ Says that the terminal has NPAGES pages worth of screen memory,
+ for terminals where this is a hardware option.
+
+`-unk'
+ Says that description is not for direct use, but only for
+ reference in `tc' capabilities. Such a description is a kind of
+ subroutine, because it describes the common characteristics of
+ several variant descriptions that would use other suffixes in
+ place of `-unk'.
+
+
+File: termcap, Node: Inheriting, Prev: Naming, Up: Data Base
+
+Inheriting from Related Descriptions
+====================================
+
+ When two terminal descriptions are similar, their identical parts do
+not need to be given twice. Instead, one of the two can be defined in
+terms of the other, using the `tc' capability. We say that one
+description "refers to" the other, or "inherits from" the other.
+
+ The `tc' capability must be the last one in the terminal description,
+and its value is a string which is the name of another terminal type
+which is referred to. For example,
+
+ N9|aaa|ambassador|aaa-30|ann arbor ambassador/30 lines:\
+ :ti=\E[2J\E[30;0;0;30p:\
+ :te=\E[60;0;0;30p\E[30;1H\E[J:\
+ :li#30:tc=aaa-unk:
+
+defines the terminal type `aaa-30' (also known as plain `aaa') in terms
+of `aaa-unk', which defines everything about the Ambassador that is
+independent of screen height. The types `aaa-36', `aaa-48' and so on
+for other screen heights are likewise defined to inherit from `aaa-unk'.
+
+ The capabilities overridden by `aaa-30' include `li', which says how
+many lines there are, and `ti' and `te', which configure the terminal
+to use that many lines.
+
+ The effective terminal description for type `aaa' consists of the
+text shown above followed by the text of the description of `aaa-unk'.
+The `tc' capability is handled automatically by `tgetent', which finds
+the description thus referenced and combines the two descriptions
+(*note Find::.). Therefore, only the implementor of the terminal
+descriptions needs to think about using `tc'. Users and application
+programmers do not need to be concerned with it.
+
+ Since the reference terminal description is used last, capabilities
+specified in the referring description override any specifications of
+the same capabilities in the reference description.
+
+ The referring description can cancel out a capability without
+specifying any new value for it by means of a special trick. Write the
+capability in the referring description, with the character `@' after
+the capability name, as follows:
+
+ NZ|aaa-30-nam|ann arbor ambassador/30 lines/no automatic-margins:\
+ :am@:tc=aaa-30:
+
+ \ No newline at end of file
diff --git a/info/termcap-2 b/info/termcap-2
new file mode 100644
index 00000000000..19c06ad9e77
--- /dev/null
+++ b/info/termcap-2
@@ -0,0 +1,1004 @@
+This is Info file ../info/termcap, produced by Makeinfo-1.49 from the
+input file termcap.texi.
+
+ This file documents the termcap library of the GNU system.
+
+ Copyright (C) 1988 Free Software Foundation, Inc.
+
+ Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+ Permission is granted to copy and distribute modified versions of
+this manual under the conditions for verbatim copying, provided that
+the entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+ Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be stated in a
+translation approved by the Foundation.
+
+
+File: termcap, Node: Capabilities, Next: Summary, Prev: Data Base, Up: Top
+
+Definitions of the Terminal Capabilities
+****************************************
+
+ This section is divided into many subsections, each for one aspect of
+use of display terminals. For writing a display program, you usually
+need only check the subsections for the operations you want to use.
+For writing a terminal description, you must read each subsection and
+fill in the capabilities described there.
+
+ String capabilities that are display commands may require numeric
+parameters (*note Parameters::.). Most such capabilities do not use
+parameters. When a capability requires parameters, this is explicitly
+stated at the beginning of its definition. In simple cases, the first
+or second sentence of the definition mentions all the parameters, in
+the order they should be given, using a name in upper case for each
+one. For example, the `rp' capability is a command that requires two
+parameters; its definition begins as follows:
+
+ String of commands to output a graphic character C, repeated N
+ times.
+
+ In complex cases or when there are many parameters, they are
+described explicitly.
+
+ When a capability is described as obsolete, this means that programs
+should not be written to look for it, but terminal descriptions should
+still be written to provide it.
+
+ When a capability is described as very obsolete, this means that it
+should be omitted from terminal descriptions as well.
+
+* Menu:
+
+* Basic:: Basic characteristics.
+* Screen Size:: Screen size, and what happens when it changes.
+* Cursor Motion:: Various ways to move the cursor.
+* Scrolling:: Pushing text up and down on the screen.
+* Wrapping:: What happens if you write a character in the last column.
+* Windows:: Limiting the part of the window that output affects.
+* Clearing:: Erasing one or many lines.
+* Insdel Line:: Making new blank lines in mid-screen; deleting lines.
+* Insdel Char:: Inserting and deleting characters within a line.
+* Standout:: Highlighting some of the text.
+* Underlining:: Underlining some of the text.
+* Cursor Visibility:: Making the cursor more or less easy to spot.
+* Bell:: Attracts user's attention; not localized on the screen.
+* Keypad:: Recognizing when function keys or arrows are typed.
+* Meta Key:: META acts like an extra shift key.
+* Initialization:: Commands used to initialize or reset the terminal.
+* Pad Specs:: Info for the kernel on how much padding is needed.
+* Status Line:: A status line displays "background" information.
+* Half-Line:: Moving by half-lines, for superscripts and subscripts.
+* Printer:: Controlling auxiliary printers of display terminals.
+
+
+File: termcap, Node: Basic, Next: Screen Size, Prev: Capabilities, Up: Capabilities
+
+Basic Characteristics
+=====================
+
+ This section documents the capabilities that describe the basic and
+nature of the terminal, and also those that are relevant to the output
+of graphic characters.
+
+`os'
+ Flag whose presence means that the terminal can overstrike. This
+ means that outputting a graphic character does not erase whatever
+ was present in the same character position before. The terminals
+ that can overstrike include printing terminals, storage tubes (all
+ obsolete nowadays), and many bit-map displays.
+
+`eo'
+ Flag whose presence means that outputting a space erases a
+ character position even if the terminal supports overstriking. If
+ this flag is not present and overstriking is supported, output of
+ a space has no effect except to move the cursor.
+
+ (On terminals that do not support overstriking, you can always
+ assume that outputting a space at a position erases whatever
+ character was previously displayed there.)
+
+`gn'
+ Flag whose presence means that this terminal type is a generic type
+ which does not really describe any particular terminal. Generic
+ types are intended for use as the default type assigned when the
+ user connects to the system, with the intention that the user
+ should specify what type he really has. One example of a generic
+ type is the type `network'.
+
+ Since the generic type cannot say how to do anything interesting
+ with the terminal, termcap-using programs will always find that the
+ terminal is too weak to be supported if the user has failed to
+ specify a real terminal type in place of the generic one. The
+ `gn' flag directs these programs to use a different error message:
+ "You have not specified your real terminal type", rather than
+ "Your terminal is not powerful enough to be used".
+
+`hc'
+ Flag whose presence means this is a hardcopy terminal.
+
+`rp'
+ String of commands to output a graphic character C, repeated N
+ times. The first parameter value is the ASCII code for the desired
+ character, and the second parameter is the number of times to
+ repeat the character. Often this command requires padding
+ proportional to the number of times the character is repeated.
+ This effect can be had by using parameter arithmetic with
+ `%'-sequences to compute the amount of padding, then generating
+ the result as a number at the front of the string so that `tputs'
+ will treat it as padding.
+
+`hz'
+ Flag whose presence means that the ASCII character `~' cannot be
+ output on this terminal because it is used for display commands.
+
+ Programs handle this flag by checking all text to be output and
+ replacing each `~' with some other character(s). If this is not
+ done, the screen will be thoroughly garbled.
+
+ The old Hazeltine terminals that required such treatment are
+ probably very rare today, so you might as well not bother to
+ support this flag.
+
+`CC'
+ String whose presence means the terminal has a settable command
+ character. The value of the string is the default command
+ character (which is usually ESC).
+
+ All the strings of commands in the terminal description should be
+ written to use the default command character. If you are writing
+ an application program that changes the command character, use the
+ `CC' capability to figure out how to translate all the display
+ commands to work with the new command character.
+
+ Most programs have no reason to look at the `CC' capability.
+
+`xb'
+ Flag whose presence identifies Superbee terminals which are unable
+ to transmit the characters ESC and `Control-C'. Programs which
+ support this flag are supposed to check the input for the code
+ sequences sent by the F1 and F2 keys, and pretend that ESC or
+ `Control-C' (respectively) had been read. But this flag is
+ obsolete, and not worth supporting.
+
+
+File: termcap, Node: Screen Size, Next: Cursor Motion, Prev: Basic, Up: Capabilities
+
+Screen Size
+===========
+
+ A terminal description has two capabilities, `co' and `li', that
+describe the screen size in columns and lines. But there is more to
+the question of screen size than this.
+
+ On some operating systems the "screen" is really a window and the
+effective width can vary. On some of these systems, `tgetnum' uses the
+actual width of the window to decide what value to return for the `co'
+capability, overriding what is actually written in the terminal
+description. On other systems, it is up to the application program to
+check the actual window width using a system call. For example, on BSD
+4.3 systems, the system call `ioctl' with code `TIOCGWINSZ' will tell
+you the current screen size.
+
+ On all window systems, termcap is powerless to advise the application
+program if the user resizes the window. Application programs must deal
+with this possibility in a system-dependent fashion. On some systems
+the C shell handles part of the problem by detecting changes in window
+size and setting the `TERMCAP' environment variable appropriately.
+This takes care of application programs that are started subsequently.
+It does not help application programs already running.
+
+ On some systems, including BSD 4.3, all programs using a terminal get
+a signal named `SIGWINCH' whenever the screen size changes. Programs
+that use termcap should handle this signal by using `ioctl TIOCGWINSZ'
+to learn the new screen size.
+
+`co'
+ Numeric value, the width of the screen in character positions.
+ Even hardcopy terminals normally have a `co' capability.
+
+`li'
+ Numeric value, the height of the screen in lines.
+
+
+File: termcap, Node: Cursor Motion, Next: Wrapping, Prev: Screen Size, Up: Capabilities
+
+Cursor Motion
+=============
+
+ Termcap assumes that the terminal has a "cursor", a spot on the
+screen where a visible mark is displayed, and that most display
+commands take effect at the position of the cursor. It follows that
+moving the cursor to a specified location is very important.
+
+ There are many terminal capabilities for different cursor motion
+operations. A terminal description should define as many as possible,
+but most programs do not need to use most of them. One capability,
+`cm', moves the cursor to an arbitrary place on the screen; this by
+itself is sufficient for any application as long as there is no need to
+support hardcopy terminals or certain old, weak displays that have only
+relative motion commands. Use of other cursor motion capabilities is an
+optimization, enabling the program to output fewer characters in some
+common cases.
+
+ If you plan to use the relative cursor motion commands in an
+application program, you must know what the starting cursor position
+is. To do this, you must keep track of the cursor position and update
+the records each time anything is output to the terminal, including
+graphic characters. In addition, it is necessary to know whether the
+terminal wraps after writing in the rightmost column. *Note Wrapping::.
+
+ One other motion capability needs special mention: `nw' moves the
+cursor to the beginning of the following line, perhaps clearing all the
+starting line after the cursor, or perhaps not clearing at all. This
+capability is a least common denominator that is probably supported
+even by terminals that cannot do most other things such as `cm' or `do'.
+Even hardcopy terminals can support `nw'.
+
+`cm'
+ String of commands to position the cursor at line L, column C.
+ Both parameters are origin-zero, and are defined relative to the
+ screen, not relative to display memory.
+
+ All display terminals except a few very obsolete ones support `cm',
+ so it is acceptable for an application program to refuse to
+ operate on terminals lacking `cm'.
+
+`ho'
+ String of commands to move the cursor to the upper left corner of
+ the screen (this position is called the "home position"). In
+ terminals where the upper left corner of the screen is not the
+ same as the beginning of display memory, this command must go to
+ the upper left corner of the screen, not the beginning of display
+ memory.
+
+ Every display terminal supports this capability, and many
+ application programs refuse to operate if the `ho' capability is
+ missing.
+
+`ll'
+ String of commands to move the cursor to the lower left corner of
+ the screen. On some terminals, moving up from home position does
+ this, but programs should never assume that will work. Just
+ output the `ll' string (if it is provided); if moving to home
+ position and then moving up is the best way to get there, the `ll'
+ command will do that.
+
+`cr'
+ String of commands to move the cursor to the beginning of the line
+ it is on. If this capability is not specified, many programs
+ assume they can use the ASCII carriage return character for this.
+
+`le'
+ String of commands to move the cursor left one column. Unless the
+ `bw' flag capability is specified, the effect is undefined if the
+ cursor is at the left margin; do not use this command there. If
+ `bw' is present, this command may be used at the left margin, and
+ it wraps the cursor to the last column of the preceding line.
+
+`nd'
+ String of commands to move the cursor right one column. The
+ effect is undefined if the cursor is at the right margin; do not
+ use this command there, not even if `am' is present.
+
+`up'
+ String of commands to move the cursor vertically up one line. The
+ effect of sending this string when on the top line is undefined;
+ programs should never use it that way.
+
+`do'
+ String of commands to move the cursor vertically down one line.
+ The effect of sending this string when on the bottom line is
+ undefined; programs should never use it that way.
+
+ The original idea was that this string would not contain a newline
+ character and therefore could be used without disabling the
+ kernel's usual habit of converting of newline into a
+ carriage-return newline sequence. But many terminal descriptions
+ do use newline in the `do' string, so this is not possible; a
+ program which sends the `do' string must disable output conversion
+ in the kernel (*note Initialize::.).
+
+`bw'
+ Flag whose presence says that `le' may be used in column zero to
+ move to the last column of the preceding line. If this flag is
+ not present, `le' should not be used in column zero.
+
+`nw'
+ String of commands to move the cursor to start of next line,
+ possibly clearing rest of line (following the cursor) before
+ moving.
+
+`DO', `UP', `LE', `RI'
+ Strings of commands to move the cursor N lines down vertically, up
+ vertically, or N columns left or right. Do not attempt to move
+ past any edge of the screen with these commands; the effect of
+ trying that is undefined. Only a few terminal descriptions provide
+ these commands, and most programs do not use them.
+
+`CM'
+ String of commands to position the cursor at line L, column C,
+ relative to display memory. Both parameters are origin-zero. This
+ capability is present only in terminals where there is a
+ difference between screen-relative and memory-relative addressing,
+ and not even in all such terminals.
+
+`ch'
+ String of commands to position the cursor at column C in the same
+ line it is on. This is a special case of `cm' in which the
+ vertical position is not changed. The `ch' capability is provided
+ only when it is faster to output than `cm' would be in this
+ special case. Programs should not assume most display terminals
+ have `ch'.
+
+`cv'
+ String of commands to position the cursor at line L in the same
+ column. This is a special case of `cm' in which the horizontal
+ position is not changed. The `cv' capability is provided only
+ when it is faster to output than `cm' would be in this special
+ case. Programs should not assume most display terminals have `cv'.
+
+`sc'
+ String of commands to make the terminal save the current cursor
+ position. Only the last saved position can be used. If this
+ capability is present, `rc' should be provided also. Most
+ terminals have neither.
+
+`rc'
+ String of commands to make the terminal restore the last saved
+ cursor position. If this capability is present, `sc' should be
+ provided also. Most terminals have neither.
+
+`ff'
+ String of commands to advance to the next page, for a hardcopy
+ terminal.
+
+`ta'
+ String of commands to move the cursor right to the next hardware
+ tab stop column. Missing if the terminal does not have any kind of
+ hardware tabs. Do not send this command if the kernel's terminal
+ modes say that the kernel is expanding tabs into spaces.
+
+`bt'
+ String of commands to move the cursor left to the previous hardware
+ tab stop column. Missing if the terminal has no such ability; many
+ terminals do not. Do not send this command if the kernel's
+ terminal modes say that the kernel is expanding tabs into spaces.
+
+ The following obsolete capabilities should be included in terminal
+descriptions when appropriate, but should not be looked at by new
+programs.
+
+`nc'
+ Flag whose presence means the terminal does not support the ASCII
+ carriage return character as `cr'. This flag is needed because
+ old programs assume, when the `cr' capability is missing, that
+ ASCII carriage return can be used for the purpose. We use `nc' to
+ tell the old programs that carriage return may not be used.
+
+ New programs should not assume any default for `cr', so they need
+ not look at `nc'. However, descriptions should contain `nc'
+ whenever they do not contain `cr'.
+
+`xt'
+ Flag whose presence means that the ASCII tab character may not be
+ used for cursor motion. This flag exists because old programs
+ assume, when the `ta' capability is missing, that ASCII tab can be
+ used for the purpose. We use `xt' to tell the old programs not to
+ use tab.
+
+ New programs should not assume any default for `ta', so they need
+ not look at `xt' in connection with cursor motion. Note that `xt'
+ also has implications for standout mode (*note Standout::.). It is
+ obsolete in regard to cursor motion but not in regard to standout.
+
+ In fact, `xt' means that the terminal is a Teleray 1061.
+
+`bc'
+ Very obsolete alternative name for the `le' capability.
+
+`bs'
+ Flag whose presence means that the ASCII character backspace may be
+ used to move the cursor left. Obsolete; look at `le' instead.
+
+`nl'
+ Obsolete capability which is a string that can either be used to
+ move the cursor down or to scroll. The same string must scroll
+ when used on the bottom line and move the cursor when used on any
+ other line. New programs should use `do' or `sf', and ignore `nl'.
+
+ If there is no `nl' capability, some old programs assume they can
+ use the newline character for this purpose. These programs follow
+ a bad practice, but because they exist, it is still desirable to
+ define the `nl' capability in a terminal description if the best
+ way to move down is *not* a newline.
+
+
+File: termcap, Node: Wrapping, Next: Scrolling, Prev: Cursor Motion, Up: Capabilities
+
+Wrapping
+========
+
+ "Wrapping" means moving the cursor from the right margin to the left
+margin of the following line. Some terminals wrap automatically when a
+graphic character is output in the last column, while others do not.
+Most application programs that use termcap need to know whether the
+terminal wraps. There are two special flag capabilities to describe
+what the terminal does when a graphic character is output in the last
+column.
+
+`am'
+ Flag whose presence means that writing a character in the last
+ column causes the cursor to wrap to the beginning of the next line.
+
+ If `am' is not present, writing in the last column leaves the
+ cursor at the place where the character was written.
+
+ Writing in the last column of the last line should be avoided on
+ terminals with `am', as it may or may not cause scrolling to occur
+ (*note Scrolling::.). Scrolling is surely not what you would
+ intend.
+
+ If your program needs to check the `am' flag, then it also needs
+ to check the `xn' flag which indicates that wrapping happens in a
+ strange way. Many common terminals have the `xn' flag.
+
+`xn'
+ Flag whose presence means that the cursor wraps in a strange way.
+ At least two distinct kinds of strange behavior are known; the
+ termcap data base does not contain anything to distinguish the two.
+
+ On Concept-100 terminals, output in the last column wraps the
+ cursor almost like an ordinary `am' terminal. But if the next
+ thing output is a newline, it is ignored.
+
+ DEC VT-100 terminals (when the wrap switch is on) do a different
+ strange thing: the cursor wraps only if the next thing output is
+ another graphic character. In fact, the wrap occurs when the
+ following graphic character is received by the terminal, before the
+ character is placed on the screen.
+
+ On both of these terminals, after writing in the last column a
+ following graphic character will be displayed in the first column
+ of the following line. But the effect of relative cursor motion
+ characters such as newline or backspace at such a time depends on
+ the terminal. The effect of erase or scrolling commands also
+ depends on the terminal. You can't assume anything about what
+ they will do on a terminal that has `xn'. So, to be safe, you
+ should never do these things at such a time on such a terminal.
+
+ To be sure of reliable results on a terminal which has the `xn'
+ flag, output a `cm' absolute positioning command after writing in
+ the last column. Another safe thing to do is to output
+ carriage-return newline, which will leave the cursor at the
+ beginning of the following line.
+
+
+File: termcap, Node: Scrolling, Next: Windows, Prev: Wrapping, Up: Capabilities
+
+Scrolling
+=========
+
+ "Scrolling" means moving the contents of the screen up or down one or
+more lines. Moving the contents up is "forward scrolling"; moving them
+down is "reverse scrolling".
+
+ Scrolling happens after each line of output during ordinary output
+on most display terminals. But in an application program that uses
+termcap for random-access output, scrolling happens only when
+explicitly requested with the commands in this section.
+
+ Some terminals have a "scroll region" feature. This lets you limit
+the effect of scrolling to a specified range of lines. Lines outside
+the range are unaffected when scrolling happens. The scroll region
+feature is available if either `cs' or `cS' is present.
+
+`sf'
+ String of commands to scroll the screen one line up, assuming it is
+ output with the cursor at the beginning of the bottom line.
+
+`sr'
+ String of commands to scroll the screen one line down, assuming it
+ is output with the cursor at the beginning of the top line.
+
+`SF'
+ String of commands to scroll the screen N lines up, assuming it is
+ output with the cursor at the beginning of the bottom line.
+
+`SR'
+ String of commands to scroll the screen N line down, assuming it
+ is output with the cursor at the beginning of the top line.
+
+`cs'
+ String of commands to set the scroll region. This command takes
+ two parameters, START and END, which are the line numbers
+ (origin-zero) of the first line to include in the scroll region
+ and of the last line to include in it. When a scroll region is
+ set, scrolling is limited to the specified range of lines; lines
+ outside the range are not affected by scroll commands.
+
+ Do not try to move the cursor outside the scroll region. The
+ region remains set until explicitly removed. To remove the scroll
+ region, use another `cs' command specifying the full height of the
+ screen.
+
+ The cursor position is undefined after the `cs' command is set, so
+ position the cursor with `cm' immediately afterward.
+
+`cS'
+ String of commands to set the scroll region using parameters in
+ different form. The effect is the same as if `cs' were used. Four
+ parameters are required:
+
+ 1. Total number of lines on the screen.
+
+ 2. Number of lines above desired scroll region.
+
+ 3. Number of lines below (outside of) desired scroll region.
+
+ 4. Total number of lines on the screen, the same as the first
+ parameter.
+
+ This capability is a GNU extension that was invented to allow the
+ Ann Arbor Ambassador's scroll-region command to be described; it
+ could also be done by putting non-Unix `%'-sequences into a `cs'
+ string, but that would have confused Unix programs that used the
+ `cs' capability with the Unix termcap. Currently only GNU Emacs
+ uses the `cS' capability.
+
+`ns'
+ Flag which means that the terminal does not normally scroll for
+ ordinary sequential output. For modern terminals, this means that
+ outputting a newline in ordinary sequential output with the cursor
+ on the bottom line wraps to the top line. For some obsolete
+ terminals, other things may happen.
+
+ The terminal may be able to scroll even if it does not normally do
+ so. If the `sf' capability is provided, it can be used for
+ scrolling regardless of `ns'.
+
+`da'
+ Flag whose presence means that lines scrolled up off the top of the
+ screen may come back if scrolling down is done subsequently.
+
+ The `da' and `db' flags do not, strictly speaking, affect how to
+ scroll. But programs that scroll usually need to clear the lines
+ scrolled onto the screen, if these flags are present.
+
+`db'
+ Flag whose presence means that lines scrolled down off the bottom
+ of the screen may come back if scrolling up is done subsequently.
+
+`lm'
+ Numeric value, the number of lines of display memory that the
+ terminal has. A value of zero means that the terminal has more
+ display memory than can fit on the screen, but no fixed number of
+ lines. (The number of lines may depend on the amount of text in
+ each line.)
+
+ Any terminal description that defines `SF' should also define `sf';
+likewise for `SR' and `sr'. However, many terminals can only scroll by
+one line at a time, so it is common to find `sf' and not `SF', or `sr'
+without `SR'.
+
+ Therefore, all programs that use the scrolling facilities should be
+prepared to work with `sf' in the case that `SF' is absent, and
+likewise with `sr'. On the other hand, an application program that
+uses only `sf' and not `SF' is acceptable, though slow on some
+terminals.
+
+ When outputting a scroll command with `tputs', the NLINES argument
+should be the total number of lines in the portion of the screen being
+scrolled. Very often these commands require padding proportional to
+this number of lines. *Note Padding::.
+
+
+File: termcap, Node: Windows, Next: Clearing, Prev: Scrolling, Up: Capabilities
+
+Windows
+=======
+
+ A "window", in termcap, is a rectangular portion of the screen to
+which all display operations are restricted. Wrapping, clearing,
+scrolling, insertion and deletion all operate as if the specified
+window were all the screen there was.
+
+`wi'
+ String of commands to set the terminal output screen window. This
+ string requires four parameters, all origin-zero:
+ 1. The first line to include in the window.
+
+ 2. The last line to include in the window.
+
+ 3. The first column to include in the window.
+
+ 4. The last column to include in the window.
+
+ Most terminals do not support windows.
+
+
+File: termcap, Node: Clearing, Next: Insdel Line, Prev: Windows, Up: Capabilities
+
+Clearing Parts of the Screen
+============================
+
+ There are several terminal capabilities for clearing parts of the
+screen to blank. All display terminals support the `cl' string, and
+most display terminals support all of these capabilities.
+
+`cl'
+ String of commands to clear the entire screen and position the
+ cursor at the upper left corner.
+
+`cd'
+ String of commands to clear the line the cursor is on, and all the
+ lines below it, down to the bottom of the screen. This command
+ string should be used only with the cursor in column zero; their
+ effect is undefined if the cursor is elsewhere.
+
+`ce'
+ String of commands to clear from the cursor to the end of the
+ current line.
+
+`ec'
+ String of commands to clear N characters, starting with the
+ character that the cursor is on. This command string is expected
+ to leave the cursor position unchanged. The parameter N should
+ never be large enough to reach past the right margin; the effect
+ of such a large parameter would be undefined.
+
+ Clear to end of line (`ce') is extremely important in programs that
+maintain an updating display. Nearly all display terminals support this
+operation, so it is acceptable for a an application program to refuse to
+work if `ce' is not present. However, if you do not want this
+limitation, you can accomplish clearing to end of line by outputting
+spaces until you reach the right margin. In order to do this, you must
+know the current horizontal position. Also, this technique assumes
+that writing a space will erase. But this happens to be true on all
+the display terminals that fail to support `ce'.
+
+
+File: termcap, Node: Insdel Line, Next: Insdel Char, Prev: Clearing, Up: Capabilities
+
+Insert/Delete Line
+==================
+
+ "Inserting a line" means creating a blank line in the middle of the
+screen, and pushing the existing lines of text apart. In fact, the
+lines above the insertion point do not change, while the lines below
+move down, and one is normally lost at the bottom of the screen.
+
+ "Deleting a line" means causing the line to disappear from the
+screen, closing up the gap by moving the lines below it upward. A new
+line appears at the bottom of the screen. Usually this line is blank,
+but on terminals with the `db' flag it may be a line previously moved
+off the screen bottom by scrolling or line insertion.
+
+ Insertion and deletion of lines is useful in programs that maintain
+an updating display some parts of which may get longer or shorter.
+They are also useful in editors for scrolling parts of the screen, and
+for redisplaying after lines of text are killed or inserted.
+
+ Many terminals provide commands to insert or delete a single line at
+the cursor position. Some provide the ability to insert or delete
+several lines with one command, using the number of lines to insert or
+delete as a parameter. Always move the cursor to column zero before
+using any of these commands.
+
+`al'
+ String of commands to insert a blank line before the line the
+ cursor is on. The existing line, and all lines below it, are
+ moved down. The last line in the screen (or in the scroll region,
+ if one is set) disappears and in most circumstances is discarded.
+ It may not be discarded if the `db' is present (*note
+ Scrolling::.).
+
+ The cursor must be at the left margin before this command is used.
+ This command does not move the cursor.
+
+`dl'
+ String of commands to delete the line the cursor is on. The
+ following lines move up, and a blank line appears at the bottom of
+ the screen (or bottom of the scroll region). If the terminal has
+ the `db' flag, a nonblank line previously pushed off the screen
+ bottom may reappear at the bottom.
+
+ The cursor must be at the left margin before this command is used.
+ This command does not move the cursor.
+
+`AL'
+ String of commands to insert N blank lines before the line that
+ the cursor is on. It is like `al' repeated N times, except that
+ it is as fast as one `al'.
+
+`DL'
+ String of commands to delete N lines starting with the line that
+ the cursor is on. It is like `dl' repeated N times, except that
+ it is as fast as one `dl'.
+
+ Any terminal description that defines `AL' should also define `al';
+likewise for `DL' and `dl'. However, many terminals can only insert or
+delete one line at a time, so it is common to find `al' and not `AL',
+or `dl' without `DL'.
+
+ Therefore, all programs that use the insert and delete facilities
+should be prepared to work with `al' in the case that `AL' is absent,
+and likewise with `dl'. On the other hand, it is acceptable to write
+an application that uses only `al' and `dl' and does not look for `AL'
+or `DL' at all.
+
+ If a terminal does not support line insertion and deletion directly,
+but does support a scroll region, the effect of insertion and deletion
+can be obtained with scrolling. However, it is up to the individual
+user program to check for this possibility and use the scrolling
+commands to get the desired result. It is fairly important to implement
+this alternate strategy, since it is the only way to get the effect of
+line insertion and deletion on the popular VT100 terminal.
+
+ Insertion and deletion of lines is affected by the scroll region on
+terminals that have a settable scroll region. This is useful when it is
+desirable to move any few consecutive lines up or down by a few lines.
+*Note Scrolling::.
+
+ The line pushed off the bottom of the screen is not lost if the
+terminal has the `db' flag capability; instead, it is pushed into
+display memory that does not appear on the screen. This is the same
+thing that happens when scrolling pushes a line off the bottom of the
+screen. Either reverse scrolling or deletion of a line can bring the
+apparently lost line back onto the bottom of the screen. If the
+terminal has the scroll region feature as well as `db', the pushed-out
+line really is lost if a scroll region is in effect.
+
+ When outputting an insert or delete command with `tputs', the NLINES
+argument should be the total number of lines from the cursor to the
+bottom of the screen (or scroll region). Very often these commands
+require padding proportional to this number of lines. *Note Padding::.
+
+ For `AL' and `DL' the NLINES argument should *not* depend on the
+number of lines inserted or deleted; only the total number of lines
+affected. This is because it is just as fast to insert two or N lines
+with `AL' as to insert one line with `al'.
+
+
+File: termcap, Node: Insdel Char, Next: Standout, Prev: Insdel Line, Up: Capabilities
+
+Insert/Delete Character
+=======================
+
+ "Inserting a character" means creating a blank space in the middle
+of a line, and pushing the rest of the line rightward. The character
+in the rightmost column is lost.
+
+ "Deleting a character" means causing the character to disappear from
+the screen, closing up the gap by moving the rest of the line leftward.
+ A blank space appears in the rightmost column.
+
+ Insertion and deletion of characters is useful in programs that
+maintain an updating display some parts of which may get longer or
+shorter. It is also useful in editors for redisplaying the results of
+editing within a line.
+
+ Many terminals provide commands to insert or delete a single
+character at the cursor position. Some provide the ability to insert
+or delete several characters with one command, using the number of
+characters to insert or delete as a parameter.
+
+ Many terminals provide an insert mode in which outputting a graphic
+character has the added effect of inserting a position for that
+character. A special command string is used to enter insert mode and
+another is used to exit it. The reason for designing a terminal with
+an insert mode rather than an insert command is that inserting
+character positions is usually followed by writing characters into
+them. With insert mode, this is as fast as simply writing the
+characters, except for the fixed overhead of entering and leaving
+insert mode. However, when the line speed is great enough, padding may
+be required for the graphic characters output in insert mode.
+
+ Some terminals require you to enter insert mode and then output a
+special command for each position to be inserted. Or they may require
+special commands to be output before or after each graphic character to
+be inserted.
+
+ Deletion of characters is usually accomplished by a straightforward
+command to delete one or several positions; but on some terminals, it
+is necessary to enter a special delete mode before using the delete
+command, and leave delete mode afterward. Sometimes delete mode and
+insert mode are the same mode.
+
+ Some terminals make a distinction between character positions in
+which a space character has been output and positions which have been
+cleared. On these terminals, the effect of insert or delete character
+runs to the first cleared position rather than to the end of the line.
+In fact, the effect may run to more than one line if there is no
+cleared position to stop the shift on the first line. These terminals
+are identified by the `in' flag capability.
+
+ On terminals with the `in' flag, the technique of skipping over
+characters that you know were cleared, and then outputting text later
+on in the same line, causes later insert and delete character
+operations on that line to do nonstandard things. A program that has
+any chance of doing this must check for the `in' flag and must be
+careful to write explicit space characters into the intermediate
+columns when `in' is present.
+
+ A plethora of terminal capabilities are needed to describe all of
+this complexity. Here is a list of them all. Following the list, we
+present an algorithm for programs to use to take proper account of all
+of these capabilities.
+
+`im'
+ String of commands to enter insert mode.
+
+ If the terminal has no special insert mode, but it can insert
+ characters with a special command, `im' should be defined with a
+ null value, because the `vi' editor assumes that insertion of a
+ character is impossible if `im' is not provided.
+
+ New programs should not act like `vi'. They should pay attention
+ to `im' only if it is defined.
+
+`ei'
+ String of commands to leave insert mode. This capability must be
+ present if `im' is.
+
+ On a few old terminals the same string is used to enter and exit
+ insert mode. This string turns insert mode on if it was off, and
+ off it it was on. You can tell these terminals because the `ei'
+ string equals the `im' string. If you want to support these
+ terminals, you must always remember accurately whether insert mode
+ is in effect. However, these terminals are obsolete, and it is
+ reasonable to refuse to support them. On all modern terminals, you
+ can safely output `ei' at any time to ensure that insert mode is
+ turned off.
+
+`ic'
+ String of commands to insert one character position at the cursor.
+ The cursor does not move.
+
+ If outputting a graphic character while in insert mode is
+ sufficient to insert the character, then the `ic' capability
+ should be defined with a null value.
+
+ If your terminal offers a choice of ways to insert--either use
+ insert mode or use a special command--then define `im' and do not
+ define `ic', since this gives the most efficient operation when
+ several characters are to be inserted. *Do not* define both
+ strings, for that means that *both* must be used each time
+ insertion is done.
+
+`ip'
+ String of commands to output following an inserted graphic
+ character in insert mode. Often it is used just for a padding
+ spec, when padding is needed after an inserted character (*note
+ Padding::.).
+
+`IC'
+ String of commands to insert N character positions at and after
+ the cursor. It has the same effect as repeating the `ic' string
+ and a space, N times.
+
+ If `IC' is provided, application programs may use it without first
+ entering insert mode.
+
+`mi'
+ Flag whose presence means it is safe to move the cursor while in
+ insert mode and assume the terminal remains in insert mode.
+
+`in'
+ Flag whose presence means that the terminal distinguishes between
+ character positions in which space characters have been output and
+ positions which have been cleared.
+
+ An application program can assume that the terminal can do character
+insertion if *any one of* the capabilities `IC', `im', `ic' or `ip' is
+provided.
+
+ To insert N blank character positions, move the cursor to the place
+to insert them and follow this algorithm:
+
+ 1. If an `IC' string is provided, output it with parameter N and you
+ are finished. Otherwise (or if you don't want to bother to look
+ for an `IC' string) follow the remaining steps.
+
+ 2. Output the `im' string, if there is one, unless the terminal is
+ already in insert mode.
+
+ 3. Repeat steps 4 through 6, N times.
+
+ 4. Output the `ic' string if any.
+
+ 5. Output a space.
+
+ 6. Output the `ip' string if any.
+
+ 7. Output the `ei' string, eventually, to exit insert mode. There is
+ no need to do this right away. If the `mi' flag is present, you
+ can move the cursor and the cursor will remain in insert mode;
+ then you can do more insertion elsewhere without reentering insert
+ mode.
+
+ To insert N graphic characters, position the cursor and follow this
+algorithm:
+
+ 1. If an `IC' string is provided, output it with parameter N, then
+ output the graphic characters, and you are finished. Otherwise
+ (or if you don't want to bother to look for an `IC' string) follow
+ the remaining steps.
+
+ 2. Output the `im' string, if there is one, unless the terminal is
+ already in insert mode.
+
+ 3. For each character to be output, repeat steps 4 through 6.
+
+ 4. Output the `ic' string if any.
+
+ 5. Output the next graphic character.
+
+ 6. Output the `ip' string if any.
+
+ 7. Output the `ei' string, eventually, to exit insert mode. There is
+ no need to do this right away. If the `mi' flag is present, you
+ can move the cursor and the cursor will remain in insert mode;
+ then you can do more insertion elsewhere without reentering insert
+ mode.
+
+ Note that this is not the same as the original Unix termcap
+specifications in one respect: it assumes that the `IC' string can be
+used without entering insert mode. This is true as far as I know, and
+it allows you be able to avoid entering and leaving insert mode, and
+also to be able to avoid the inserted-character padding after the
+characters that go into the inserted positions.
+
+ Deletion of characters is less complicated; deleting one column is
+done by outputting the `dc' string. However, there may be a delete
+mode that must be entered with `dm' in order to make `dc' work.
+
+`dc'
+ String of commands to delete one character position at the cursor.
+ If `dc' is not present, the terminal cannot delete characters.
+
+`DC'
+ String of commands to delete N characters starting at the cursor.
+ It has the same effect as repeating the `dc' string N times. Any
+ terminal description that has `DC' also has `dc'.
+
+`dm'
+ String of commands to enter delete mode. If not present, there is
+ no delete mode, and `dc' can be used at any time (assuming there is
+ a `dc').
+
+`ed'
+ String of commands to exit delete mode. This must be present if
+ `dm' is.
+
+ To delete N character positions, position the cursor and follow these
+steps:
+
+ 1. If the `DC' string is present, output it with parameter N and you
+ are finished. Otherwise, follow the remaining steps.
+
+ 2. Output the `dm' string, unless you know the terminal is already in
+ delete mode.
+
+ 3. Output the `dc' string N times.
+
+ 4. Output the `ed' string eventually. If the flag capability `mi' is
+ present, you can move the cursor and do more deletion without
+ leaving and reentering delete mode.
+
+ As with the `IC' string, we have departed from the original termcap
+specifications by assuming that `DC' works without entering delete mode
+even though `dc' would not.
+
+ If the `dm' and `im' capabilities are both present and have the same
+value, it means that the terminal has one mode for both insertion and
+deletion. It is useful for a program to know this, because then it can
+do insertions after deletions, or vice versa, without leaving
+insert/delete mode and reentering it.
+
+ \ No newline at end of file
diff --git a/info/termcap-3 b/info/termcap-3
new file mode 100644
index 00000000000..5921c90e720
--- /dev/null
+++ b/info/termcap-3
@@ -0,0 +1,1429 @@
+This is Info file ../info/termcap, produced by Makeinfo-1.49 from the
+input file termcap.texi.
+
+ This file documents the termcap library of the GNU system.
+
+ Copyright (C) 1988 Free Software Foundation, Inc.
+
+ Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+ Permission is granted to copy and distribute modified versions of
+this manual under the conditions for verbatim copying, provided that
+the entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+ Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be stated in a
+translation approved by the Foundation.
+
+
+File: termcap, Node: Standout, Next: Underlining, Prev: Insdel Char, Up: Capabilities
+
+Standout and Appearance Modes
+=============================
+
+ "Appearance modes" are modifications to the ways characters are
+displayed. Typical appearance modes include reverse video, dim, bright,
+blinking, underlined, invisible, and alternate character set. Each
+kind of terminal supports various among these, or perhaps none.
+
+ For each type of terminal, one appearance mode or combination of
+them that looks good for highlighted text is chosen as the "standout
+mode". The capabilities `so' and `se' say how to enter and leave
+standout mode. Programs that use appearance modes only to highlight
+some text generally use the standout mode so that they can work on as
+many terminals as possible. Use of specific appearance modes other
+than "underlined" and "alternate character set" is rare.
+
+ Terminals that implement appearance modes fall into two general
+classes as to how they do it.
+
+ In some terminals, the presence or absence of any appearance mode is
+recorded separately for each character position. In these terminals,
+each graphic character written is given the appearance modes current at
+the time it is written, and keeps those modes until it is erased or
+overwritten. There are special commands to turn the appearance modes on
+or off for characters to be written in the future.
+
+ In other terminals, the change of appearance modes is represented by
+a marker that belongs to a certain screen position but affects all
+following screen positions until the next marker. These markers are
+traditionally called "magic cookies".
+
+ The same capabilities (`so', `se', `mb' and so on) for turning
+appearance modes on and off are used for both magic-cookie terminals
+and per-character terminals. On magic cookie terminals, these give the
+commands to write the magic cookies. On per-character terminals, they
+change the current modes that affect future output and erasure. Some
+simple applications can use these commands without knowing whether or
+not they work by means of cookies.
+
+ However, a program that maintains and updates a display needs to know
+whether the terminal uses magic cookies, and exactly what their effect
+is. This information comes from the `sg' capability.
+
+ The `sg' capability is a numeric capability whose presence indicates
+that the terminal uses magic cookies for appearance modes. Its value is
+the number of character positions that a magic cookie occupies. Usually
+the cookie occupies one or more character positions on the screen, and
+these character positions are displayed as blank, but in some terminals
+the cookie has zero width.
+
+ The `sg' capability describes both the magic cookie to turn standout
+on and the cookie to turn it off. This makes the assumption that both
+kinds of cookie have the same width on the screen. If that is not true,
+the narrower cookie must be "widened" with spaces until it has the same
+width as the other.
+
+ On some magic cookie terminals, each line always starts with normal
+display; in other words, the scope of a magic cookie never extends over
+more than one line. But on other terminals, one magic cookie affects
+all the lines below it unless explicitly canceled. Termcap does not
+define any way to distinguish these two ways magic cookies can work.
+To be safe, it is best to put a cookie at the beginning of each line.
+
+ On some per-character terminals, standout mode or other appearance
+modes may be canceled by moving the cursor. On others, moving the
+cursor has no effect on the state of the appearance modes. The latter
+class of terminals are given the flag capability `ms' ("can move in
+standout"). All programs that might have occasion to move the cursor
+while appearance modes are turned on must check for this flag; if it is
+not present, they should reset appearance modes to normal before doing
+cursor motion.
+
+ A program that has turned on only standout mode should use `se' to
+reset the standout mode to normal. A program that has turned on only
+alternate character set mode should use `ae' to return it to normal. If
+it is possible that any other appearance modes are turned on, use the
+`me' capability to return them to normal.
+
+ Note that the commands to turn on one appearance mode, including `so'
+and `mb' ... `mr', if used while some other appearance modes are turned
+on, may combine the two modes on some terminals but may turn off the
+mode previously enabled on other terminals. This is because some
+terminals do not have a command to set or clear one appearance mode
+without changing the others. Programs should not attempt to use
+appearance modes in combination except with `sa', and when switching
+from one single mode to another should always turn off the previously
+enabled mode and then turn on the new desired mode.
+
+ On some old terminals, the `so' and `se' commands may be the same
+command, which has the effect of turning standout on if it is off, or
+off it is on. It is therefore risky for a program to output extra `se'
+commands for good measure. Fortunately, all these terminals are
+obsolete.
+
+ Programs that update displays in which standout-text may be replaced
+with non-standout text must check for the `xs' flag. In a per-character
+terminal, this flag says that the only way to remove standout once
+written is to clear that portion of the line with the `ce' string or
+something even more powerful (*note Clearing::.); just writing new
+characters at those screen positions will not change the modes in
+effect there. In a magic cookie terminal, `xs' says that the only way
+to remove a cookie is to clear a portion of the line that includes the
+cookie; writing a different cookie at the same position does not work.
+
+ Such programs must also check for the `xt' flag, which means that the
+terminal is a Teleray 1061. On this terminal it is impossible to
+position the cursor at the front of a magic cookie, so the only two
+ways to remove a cookie are (1) to delete the line it is on or (2) to
+position the cursor at least one character before it (possibly on a
+previous line) and output the `se' string, which on these terminals
+finds and removes the next `so' magic cookie on the screen. (It may
+also be possible to remove a cookie which is not at the beginning of a
+line by clearing that line.) The `xt' capability also has implications
+for the use of tab characters, but in that regard it is obsolete (*Note
+Cursor Motion::).
+
+`so'
+ String of commands to enter standout mode.
+
+`se'
+ String of commands to leave standout mode.
+
+`sg'
+ Numeric capability, the width on the screen of the magic cookie.
+ This capability is absent in terminals that record appearance modes
+ character by character.
+
+`ms'
+ Flag whose presence means that it is safe to move the cursor while
+ the appearance modes are not in the normal state. If this flag is
+ absent, programs should always reset the appearance modes to
+ normal before moving the cursor.
+
+`xs'
+ Flag whose presence means that the only way to reset appearance
+ modes already on the screen is to clear to end of line. On a
+ per-character terminal, you must clear the area where the modes
+ are set. On a magic cookie terminal, you must clear an area
+ containing the cookie. See the discussion above.
+
+`xt'
+ Flag whose presence means that the cursor cannot be positioned
+ right in front of a magic cookie, and that `se' is a command to
+ delete the next magic cookie following the cursor. See discussion
+ above.
+
+`mb'
+ String of commands to enter blinking mode.
+
+`md'
+ String of commands to enter double-bright mode.
+
+`mh'
+ String of commands to enter half-bright mode.
+
+`mk'
+ String of commands to enter invisible mode.
+
+`mp'
+ String of commands to enter protected mode.
+
+`mr'
+ String of commands to enter reverse-video mode.
+
+`me'
+ String of commands to turn off all appearance modes, including
+ standout mode and underline mode. On some terminals it also turns
+ off alternate character set mode; on others, it may not. This
+ capability must be present if any of `mb' ... `mr' is present.
+
+`as'
+ String of commands to turn on alternate character set mode. This
+ mode assigns some or all graphic characters an alternate picture
+ on the screen. There is no standard as to what the alternate
+ pictures look like.
+
+`ae'
+ String of commands to turn off alternate character set mode.
+
+`sa'
+ String of commands to turn on an arbitrary combination of
+ appearance modes. It accepts 9 parameters, each of which controls
+ a particular kind of appearance mode. A parameter should be 1 to
+ turn its appearance mode on, or zero to turn that mode off. Most
+ terminals do not support the `sa' capability, even among those
+ that do have various appearance modes.
+
+ The nine parameters are, in order, STANDOUT, UNDERLINE, REVERSE,
+ BLINK, HALF-BRIGHT, DOUBLE-BRIGHT, BLANK, PROTECT, ALT CHAR SET.
+
+
+File: termcap, Node: Underlining, Next: Cursor Visibility, Prev: Standout, Up: Capabilities
+
+Underlining
+===========
+
+ Underlining on most terminals is a kind of appearance mode, much like
+standout mode. Therefore, it may be implemented using magic cookies or
+as a flag in the terminal whose current state affects each character
+that is output. *Note Standout::, for a full explanation.
+
+ The `ug' capability is a numeric capability whose presence indicates
+that the terminal uses magic cookies for underlining. Its value is the
+number of character positions that a magic cookie for underlining
+occupies; it is used for underlining just as `sg' is used for standout.
+ Aside from the simplest applications, it is impossible to use
+underlining correctly without paying attention to the value of `ug'.
+
+`us'
+ String of commands to turn on underline mode or to output a magic
+ cookie to start underlining.
+
+`ue'
+ String of commands to turn off underline mode or to output a magic
+ cookie to stop underlining.
+
+`ug'
+ Width of magic cookie that represents a change of underline mode;
+ or missing, if the terminal does not use a magic cookie for this.
+
+`ms'
+ Flag whose presence means that it is safe to move the cursor while
+ the appearance modes are not in the normal state. Underlining is
+ an appearance mode. If this flag is absent, programs should
+ always turn off underlining before moving the cursor.
+
+ There are two other, older ways of doing underlining: there can be a
+command to underline a single character, or the output of `_', the
+ASCII underscore character, as an overstrike could cause a character to
+be underlined. New programs need not bother to handle these
+capabilities unless the author cares strongly about the obscure
+terminals which support them. However, terminal descriptions should
+provide these capabilities when appropriate.
+
+`uc'
+ String of commands to underline the character under the cursor, and
+ move the cursor right.
+
+`ul'
+ Flag whose presence means that the terminal can underline by
+ overstriking an underscore character (`_'); some terminals can do
+ this even though they do not support overstriking in general. An
+ implication of this flag is that when outputting new text to
+ overwrite old text, underscore characters must be treated
+ specially lest they underline the old text instead.
+
+
+File: termcap, Node: Cursor Visibility, Next: Bell, Prev: Underlining, Up: Capabilities
+
+Cursor Visibility
+=================
+
+ Some terminals have the ability to make the cursor invisible, or to
+enhance it. Enhancing the cursor is often done by programs that plan
+to use the cursor to indicate to the user a position of interest that
+may be anywhere on the screen--for example, the Emacs editor enhances
+the cursor on entry. Such programs should always restore the cursor to
+normal on exit.
+
+`vs'
+ String of commands to enhance the cursor.
+
+`vi'
+ String of commands to make the cursor invisible.
+
+`ve'
+ String of commands to return the cursor to normal.
+
+ If you define either `vs' or `vi', you must also define `ve'.
+
+
+File: termcap, Node: Bell, Next: Keypad, Prev: Cursor Visibility, Up: Capabilities
+
+Bell
+====
+
+ Here we describe commands to make the terminal ask for the user to
+pay attention to it.
+
+`bl'
+ String of commands to cause the terminal to make an audible sound.
+ If this capability is absent, the terminal has no way to make a
+ suitable sound.
+
+`vb'
+ String of commands to cause the screen to flash to attract
+ attention ("visible bell"). If this capability is absent, the
+ terminal has no way to do such a thing.
+
+
+File: termcap, Node: Keypad, Next: Meta Key, Prev: Bell, Up: Capabilities
+
+Keypad and Function Keys
+========================
+
+ Many terminals have arrow and function keys that transmit specific
+character sequences to the computer. Since the precise sequences used
+depend on the terminal, termcap defines capabilities used to say what
+the sequences are. Unlike most termcap string-valued capabilities,
+these are not strings of commands to be sent to the terminal, rather
+strings that are received from the terminal.
+
+ Programs that expect to use keypad keys should check, initially, for
+a `ks' capability and send it, to make the keypad actually transmit.
+Such programs should also send the `ke' string when exiting.
+
+`ks'
+ String of commands to make the function keys transmit. If this
+ capability is not provided, but the others in this section are,
+ programs may assume that the function keys always transmit.
+
+`ke'
+ String of commands to make the function keys work locally. This
+ capability is provided only if `ks' is.
+
+`kl'
+ String of input characters sent by typing the left-arrow key. If
+ this capability is missing, you cannot expect the terminal to have
+ a left-arrow key that transmits anything to the computer.
+
+`kr'
+ String of input characters sent by typing the right-arrow key.
+
+`ku'
+ String of input characters sent by typing the up-arrow key.
+
+`kd'
+ String of input characters sent by typing the down-arrow key.
+
+`kh'
+ String of input characters sent by typing the "home-position" key.
+
+`K1' ... `K5'
+ Strings of input characters sent by the five other keys in a 3-by-3
+ array that includes the arrow keys, if the keyboard has such a
+ 3-by-3 array. Note that one of these keys may be the
+ "home-position" key, in which case one of these capabilities will
+ have the same value as the `kh' key.
+
+`k0'
+ String of input characters sent by function key 10 (or 0, if the
+ terminal has one labeled 0).
+
+`k1' ... `k9'
+ Strings of input characters sent by function keys 1 through 9,
+ provided for those function keys that exist.
+
+`kn'
+ Number: the number of numbered function keys, if there are more
+ than 10.
+
+`l0' ... `l9'
+ Strings which are the labels appearing on the keyboard on the keys
+ described by the capabilities `k0' ... `l9'. These capabilities
+ should be left undefined if the labels are `f0' or `f10' and `f1'
+ ... `f9'.
+
+`kH'
+ String of input characters sent by the "home down" key, if there is
+ one.
+
+`kb'
+ String of input characters sent by the "backspace" key, if there is
+ one.
+
+`ka'
+ String of input characters sent by the "clear all tabs" key, if
+ there is one.
+
+`kt'
+ String of input characters sent by the "clear tab stop this column"
+ key, if there is one.
+
+`kC'
+ String of input characters sent by the "clear screen" key, if
+ there is one.
+
+`kD'
+ String of input characters sent by the "delete character" key, if
+ there is one.
+
+`kL'
+ String of input characters sent by the "delete line" key, if there
+ is one.
+
+`kM'
+ String of input characters sent by the "exit insert mode" key, if
+ there is one.
+
+`kE'
+ String of input characters sent by the "clear to end of line" key,
+ if there is one.
+
+`kS'
+ String of input characters sent by the "clear to end of screen"
+ key, if there is one.
+
+`kI'
+ String of input characters sent by the "insert character" or "enter
+ insert mode" key, if there is one.
+
+`kA'
+ String of input characters sent by the "insert line" key, if there
+ is one.
+
+`kN'
+ String of input characters sent by the "next page" key, if there is
+ one.
+
+`kP'
+ String of input characters sent by the "previous page" key, if
+ there is one.
+
+`kF'
+ String of input characters sent by the "scroll forward" key, if
+ there is one.
+
+`kR'
+ String of input characters sent by the "scroll reverse" key, if
+ there is one.
+
+`kT'
+ String of input characters sent by the "set tab stop in this
+ column" key, if there is one.
+
+`ko'
+ String listing the other function keys the terminal has. This is a
+ very obsolete way of describing the same information found in the
+ `kH' ... `kT' keys. The string contains a list of two-character
+ termcap capability names, separated by commas. The meaning is
+ that for each capability name listed, the terminal has a key which
+ sends the string which is the value of that capability. For
+ example, the value `:ko=cl,ll,sf,sr:' says that the terminal has
+ four function keys which mean "clear screen", "home down", "scroll
+ forward" and "scroll reverse".
+
+
+File: termcap, Node: Meta Key, Next: Initialization, Prev: Keypad, Up: Capabilities
+
+Meta Key
+========
+
+ A Meta key is a key on the keyboard that modifies each character you
+type by controlling the 0200 bit. This bit is on if and only if the
+Meta key is held down when the character is typed. Characters typed
+using the Meta key are called Meta characters. Emacs uses Meta
+characters as editing commands.
+
+`km'
+ Flag whose presence means that the terminal has a Meta key.
+
+`mm'
+ String of commands to enable the functioning of the Meta key.
+
+`mo'
+ String of commands to disable the functioning of the Meta key.
+
+ If the terminal has `km' but does not have `mm' and `mo', it means
+that the Meta key always functions. If it has `mm' and `mo', it means
+that the Meta key can be turned on or off. Send the `mm' string to
+turn it on, and the `mo' string to turn it off. I do not know why one
+would ever not want it to be on.
+
+
+File: termcap, Node: Initialization, Next: Pad Specs, Prev: Meta Key, Up: Capabilities
+
+Initialization
+==============
+
+`ti'
+ String of commands to put the terminal into whatever special modes
+ are needed or appropriate for programs that move the cursor
+ nonsequentially around the screen. Programs that use termcap to do
+ full-screen display should output this string when they start up.
+
+`te'
+ String of commands to undo what is done by the `ti' string.
+ Programs that output the `ti' string on entry should output this
+ string when they exit.
+
+`is'
+ String of commands to initialize the terminal for each login
+ session.
+
+`if'
+ String which is the name of a file containing the string of
+ commands to initialize the terminal for each session of use.
+ Normally `is' and `if' are not both used.
+
+`i1'
+`i3'
+ Two more strings of commands to initialize the terminal for each
+ login session. The `i1' string (if defined) is output before `is'
+ or `if', and the `i3' string (if defined) is output after.
+
+ The reason for having three separate initialization strings is to
+ make it easier to define a group of related terminal types with
+ slightly different initializations. Define two or three of the
+ strings in the basic type; then the other types can override one
+ or two of the strings.
+
+`rs'
+ String of commands to reset the terminal from any strange mode it
+ may be in. Normally this includes the `is' string (or other
+ commands with the same effects) and more. What would go in the
+ `rs' string but not in the `is' string are annoying or slow
+ commands to bring the terminal back from strange modes that nobody
+ would normally use.
+
+`it'
+ Numeric value, the initial spacing between hardware tab stop
+ columns when the terminal is powered up. Programs to initialize
+ the terminal can use this to decide whether there is a need to set
+ the tab stops. If the initial width is 8, well and good; if it is
+ not 8, then the tab stops should be set; if they cannot be set,
+ the kernel is told to convert tabs to spaces, and other programs
+ will observe this and do likewise.
+
+`ct'
+ String of commands to clear all tab stops.
+
+`st'
+ String of commands to set tab stop at current cursor column on all
+ lines.
+
+
+File: termcap, Node: Pad Specs, Next: Status Line, Prev: Initialization, Up: Capabilities
+
+Padding Capabilities
+====================
+
+ There are two terminal capabilities that exist just to explain the
+proper way to obey the padding specifications in all the command string
+capabilities. One, `pc', must be obeyed by all termcap-using programs.
+
+`pb'
+ Numeric value, the lowest baud rate at which padding is actually
+ needed. Programs may check this and refrain from doing any
+ padding at lower speeds.
+
+`pc'
+ String of commands for padding. The first character of this
+ string is to be used as the pad character, instead of using null
+ characters for padding. If `pc' is not provided, use null
+ characters. Every program that uses termcap must look up this
+ capability and use it to set the variable `PC' that is used by
+ `tputs'. *Note Padding::.
+
+ Some termcap capabilities exist just to specify the amount of
+padding that the kernel should give to cursor motion commands used in
+ordinary sequential output.
+
+`dC'
+ Numeric value, the number of msec of padding needed for the
+ carriage-return character.
+
+`dN'
+ Numeric value, the number of msec of padding needed for the newline
+ (linefeed) character.
+
+`dB'
+ Numeric value, the number of msec of padding needed for the
+ backspace character.
+
+`dF'
+ Numeric value, the number of msec of padding needed for the
+ formfeed character.
+
+`dT'
+ Numeric value, the number of msec of padding needed for the tab
+ character.
+
+ In some systems, the kernel uses the above capabilities; in other
+systems, the kernel uses the paddings specified in the string
+capabilities `cr', `sf', `le', `ff' and `ta'. Descriptions of
+terminals which require such padding should contain the `dC' ... `dT'
+capabilities and also specify the appropriate padding in the
+corresponding string capabilities. Since no modern terminals require
+padding for ordinary sequential output, you probably won't need to do
+either of these things.
+
+
+File: termcap, Node: Status Line, Next: Half-Line, Prev: Pad Specs, Up: Capabilities
+
+Status Line
+===========
+
+ A "status line" is a line on the terminal that is not used for
+ordinary display output but instead used for a special message. The
+intended use is for a continuously updated description of what the
+user's program is doing, and that is where the name "status line" comes
+from, but in fact it could be used for anything. The distinguishing
+characteristic of a status line is that ordinary output to the terminal
+does not affect it; it changes only if the special status line commands
+of this section are used.
+
+`hs'
+ Flag whose presence means that the terminal has a status line. If
+ a terminal description specifies that there is a status line, it
+ must provide the `ts' and `fs' capabilities.
+
+`ts'
+ String of commands to move the terminal cursor into the status
+ line. Usually these commands must specifically record the old
+ cursor position for the sake of the `fs' string.
+
+`fs'
+ String of commands to move the cursor back from the status line to
+ its previous position (outside the status line).
+
+`es'
+ Flag whose presence means that other display commands work while
+ writing the status line. In other words, one can clear parts of
+ it, insert or delete characters, move the cursor within it using
+ `ch' if there is a `ch' capability, enter and leave standout mode,
+ and so on.
+
+`ds'
+ String of commands to disable the display of the status line. This
+ may be absent, if there is no way to disable the status line
+ display.
+
+`ws'
+ Numeric value, the width of the status line. If this capability is
+ absent in a terminal that has a status line, it means the status
+ line is the same width as the other lines.
+
+ Note that the value of `ws' is sometimes as small as 8.
+
+
+File: termcap, Node: Half-Line, Next: Printer, Prev: Status Line, Up: Capabilities
+
+Half-Line Motion
+================
+
+ Some terminals have commands for moving the cursor vertically by
+half-lines, useful for outputting subscripts and superscripts. Mostly
+it is hardcopy terminals that have such features.
+
+`hu'
+ String of commands to move the cursor up half a line. If the
+ terminal is a display, it is your responsibility to avoid moving
+ up past the top line; however, most likely the terminal that
+ supports this is a hardcopy terminal and there is nothing to be
+ concerned about.
+
+`hd'
+ String of commands to move the cursor down half a line. If the
+ terminal is a display, it is your responsibility to avoid moving
+ down past the bottom line, etc.
+
+
+File: termcap, Node: Printer, Prev: Half-Line, Up: Capabilities
+
+Controlling Printers Attached to Terminals
+==========================================
+
+ Some terminals have attached hardcopy printer ports. They may be
+able to copy the screen contents to the printer; they may also be able
+to redirect output to the printer. Termcap does not have anything to
+tell the program whether the redirected output appears also on the
+screen; it does on some terminals but not all.
+
+`ps'
+ String of commands to cause the contents of the screen to be
+ printed. If it is absent, the screen contents cannot be printed.
+
+`po'
+ String of commands to redirect further output to the printer.
+
+`pf'
+ String of commands to terminate redirection of output to the
+ printer. This capability must be present in the description if
+ `po' is.
+
+`pO'
+ String of commands to redirect output to the printer for next N
+ characters of output, regardless of what they are. Redirection
+ will end automatically after N characters of further output. Until
+ then, nothing that is output can end redirection, not even the
+ `pf' string if there is one. The number N should not be more than
+ 255.
+
+ One use of this capability is to send non-text byte sequences
+ (such as bit-maps) to the printer.
+
+ Most terminals with printers do not support all of `ps', `po' and
+`pO'; any one or two of them may be supported. To make a program that
+can send output to all kinds of printers, it is necessary to check for
+all three of these capabilities, choose the most convenient of the ones
+that are provided, and use it in its own appropriate fashion.
+
+
+File: termcap, Node: Summary, Next: Var Index, Prev: Capabilities, Up: Top
+
+Summary of Capability Names
+***************************
+
+ Here are all the terminal capability names in alphabetical order
+with a brief description of each. For cross references to their
+definitions, see the index of capability names (*note Cap Index::.).
+
+`ae'
+ String to turn off alternate character set mode.
+
+`al'
+ String to insert a blank line before the cursor.
+
+`AL'
+ String to insert N blank lines before the cursor.
+
+`am'
+ Flag: output to last column wraps cursor to next line.
+
+`as'
+ String to turn on alternate character set mode.like.
+
+`bc'
+ Very obsolete alternative name for the `le' capability.
+
+`bl'
+ String to sound the bell.
+
+`bs'
+ Obsolete flag: ASCII backspace may be used for leftward motion.
+
+`bt'
+ String to move the cursor left to the previous hardware tab stop
+ column.
+
+`bw'
+ Flag: `le' at left margin wraps to end of previous line.
+
+`CC'
+ String to change terminal's command character.
+
+`cd'
+ String to clear the line the cursor is on, and following lines.
+
+`ce'
+ String to clear from the cursor to the end of the line.
+
+`ch'
+ String to position the cursor at column C in the same line.
+
+`cl'
+ String to clear the entire screen and put cursor at upper left
+ corner.
+
+`cm'
+ String to position the cursor at line L, column C.
+
+`CM'
+ String to position the cursor at line L, column C, relative to
+ display memory.
+
+`co'
+ Number: width of the screen.
+
+`cr'
+ String to move cursor sideways to left margin.
+
+`cs'
+ String to set the scroll region.
+
+`cS'
+ Alternate form of string to set the scroll region.
+
+`ct'
+ String to clear all tab stops.
+
+`cv'
+ String to position the cursor at line L in the same column.
+
+`da'
+ Flag: data scrolled off top of screen may be scrolled back.
+
+`db'
+ Flag: data scrolled off bottom of screen may be scrolled back.
+
+`dB'
+ Obsolete number: msec of padding needed for the backspace
+ character.
+
+`dc'
+ String to delete one character position at the cursor.
+
+`dC'
+ Obsolete number: msec of padding needed for the carriage-return
+ character.
+
+`DC'
+ String to delete N characters starting at the cursor.
+
+`dF'
+ Obsolete number: msec of padding needed for the formfeed character.
+
+`dl'
+ String to delete the line the cursor is on.
+
+`DL'
+ String to delete N lines starting with the cursor's line.
+
+`dm'
+ String to enter delete mode.
+
+`dN'
+ Obsolete number: msec of padding needed for the newline character.
+
+`do'
+ String to move the cursor vertically down one line.
+
+`DO'
+ String to move cursor vertically down N lines.
+
+`ds'
+ String to disable the display of the status line.
+
+`dT'
+ Obsolete number: msec of padding needed for the tab character.
+
+`ec'
+ String of commands to clear N characters at cursor.
+
+`ed'
+ String to exit delete mode.
+
+`ei'
+ String to leave insert mode.
+
+`eo'
+ Flag: output of a space can erase an overstrike.
+
+`es'
+ Flag: other display commands work while writing the status line.
+
+`ff'
+ String to advance to the next page, for a hardcopy terminal.
+
+`fs'
+ String to move the cursor back from the status line to its
+ previous position (outside the status line).
+
+`gn'
+ Flag: this terminal type is generic, not real.
+
+`hc'
+ Flag: hardcopy terminal.
+
+`hd'
+ String to move the cursor down half a line.
+
+`ho'
+ String to position cursor at upper left corner.
+
+`hs'
+ Flag: the terminal has a status line.
+
+`hu'
+ String to move the cursor up half a line.
+
+`hz'
+ Flag: terminal cannot accept `~' as output.
+
+`i1'
+ String to initialize the terminal for each login session.
+
+`i3'
+ String to initialize the terminal for each login session.
+
+`ic'
+ String to insert one character position at the cursor.
+
+`IC'
+ String to insert N character positions at the cursor.
+
+`if'
+ String naming a file of commands to initialize the terminal.
+
+`im'
+ String to enter insert mode.
+
+`in'
+ Flag: outputting a space is different from moving over empty
+ positions.
+
+`ip'
+ String to output following an inserted character in insert mode.
+
+`is'
+ String to initialize the terminal for each login session.
+
+`it'
+ Number: initial spacing between hardware tab stop columns.
+
+`k0'
+ String of input sent by function key 0 or 10.
+
+`k1 ... k9'
+ Strings of input sent by function keys 1 through 9.
+
+`K1 ... K5'
+ Strings sent by the five other keys in 3-by-3 array with arrows.
+
+`ka'
+ String of input sent by the "clear all tabs" key.
+
+`kA'
+ String of input sent by the "insert line" key.
+
+`kb'
+ String of input sent by the "backspace" key.
+
+`kC'
+ String of input sent by the "clear screen" key.
+
+`kd'
+ String of input sent by typing the down-arrow key.
+
+`kD'
+ String of input sent by the "delete character" key.
+
+`ke'
+ String to make the function keys work locally.
+
+`kE'
+ String of input sent by the "clear to end of line" key.
+
+`kF'
+ String of input sent by the "scroll forward" key.
+
+`kh'
+ String of input sent by typing the "home-position" key.
+
+`kH'
+ String of input sent by the "home down" key.
+
+`kI'
+ String of input sent by the "insert character" or "enter insert
+ mode" key.
+
+`kl'
+ String of input sent by typing the left-arrow key.
+
+`kL'
+ String of input sent by the "delete line" key.
+
+`km'
+ Flag: the terminal has a Meta key.
+
+`kM'
+ String of input sent by the "exit insert mode" key.
+
+`kn'
+ Numeric value, the number of numbered function keys.
+
+`kN'
+ String of input sent by the "next page" key.
+
+`ko'
+ Very obsolete string listing the terminal's named function keys.
+
+`kP'
+ String of input sent by the "previous page" key.
+
+`kr'
+ String of input sent by typing the right-arrow key.
+
+`kR'
+ String of input sent by the "scroll reverse" key.
+
+`ks'
+ String to make the function keys transmit.
+
+`kS'
+ String of input sent by the "clear to end of screen" key.
+
+`kt'
+ String of input sent by the "clear tab stop this column" key.
+
+`kT'
+ String of input sent by the "set tab stop in this column" key.
+
+`ku'
+ String of input sent by typing the up-arrow key.
+
+`l0'
+ String on keyboard labelling function key 0 or 10.
+
+`l1 ... l9'
+ Strings on keyboard labelling function keys 1 through 9.
+
+`le'
+ String to move the cursor left one column.
+
+`LE'
+ String to move cursor left N columns.
+
+`li'
+ Number: height of the screen.
+
+`ll'
+ String to position cursor at lower left corner.
+
+`lm'
+ Number: lines of display memory.
+
+`mb'
+ String to enter blinking mode.
+
+`md'
+ String to enter double-bright mode.
+
+`me'
+ String to turn off all appearance modes
+
+`mh'
+ String to enter half-bright mode.
+
+`mi'
+ Flag: cursor motion in insert mode is safe.
+
+`mk'
+ String to enter invisible mode.
+
+`mm'
+ String to enable the functioning of the Meta key.
+
+`mo'
+ String to disable the functioning of the Meta key.
+
+`mp'
+ String to enter protected mode.
+
+`mr'
+ String to enter reverse-video mode.
+
+`ms'
+ Flag: cursor motion in standout mode is safe.
+
+`nc'
+ Obsolete flag: do not use ASCII carriage-return on this terminal.
+
+`nd'
+ String to move the cursor right one column.
+
+`nl'
+ Obsolete alternative name for the `do' and `sf' capabilities.
+
+`ns'
+ Flag: the terminal does not normally scroll for sequential output.
+
+`nw'
+ String to move to start of next line, possibly clearing rest of
+ old line.
+
+`os'
+ Flag: terminal can overstrike.
+
+`pb'
+ Number: the lowest baud rate at which padding is actually needed.
+
+`pc'
+ String containing character for padding.
+
+`pf'
+ String to terminate redirection of output to the printer.
+
+`po'
+ String to redirect further output to the printer.
+
+`pO'
+ String to redirect N characters ofoutput to the printer.
+
+`ps'
+ String to print the screen on the attached printer.
+
+`rc'
+ String to move to last saved cursor position.
+
+`RI'
+ String to move cursor right N columns.
+
+`rp'
+ String to output character C repeated N times.
+
+`rs'
+ String to reset the terminal from any strange modes.
+
+`sa'
+ String to turn on an arbitrary combination of appearance modes.
+
+`sc'
+ String to save the current cursor position.
+
+`se'
+ String to leave standout mode.
+
+`sf'
+ String to scroll the screen one line up.
+
+`SF'
+ String to scroll the screen N lines up.
+
+`sg'
+ Number: width of magic standout cookie. Absent if magic cookies
+ are not used.
+
+`so'
+ String to enter standout mode.
+
+`sr'
+ String to scroll the screen one line down.
+
+`SR'
+ String to scroll the screen N line down.
+
+`st'
+ String to set tab stop at current cursor column on all lines.
+ programs.
+
+`ta'
+ String to move the cursor right to the next hardware tab stop
+ column.
+
+`te'
+ String to return terminal to settings for sequential output.
+
+`ti'
+ String to initialize terminal for random cursor motion.
+
+`ts'
+ String to move the terminal cursor into the status line.
+
+`uc'
+ String to underline one character and move cursor right.
+
+`ue'
+ String to turn off underline mode
+
+`ug'
+ Number: width of underlining magic cookie. Absent if underlining
+ doesn't use magic cookies.
+
+`ul'
+ Flag: underline by overstriking with an underscore.
+
+`up'
+ String to move the cursor vertically up one line.
+
+`UP'
+ String to move cursor vertically up N lines.
+
+`us'
+ String to turn on underline mode
+
+`vb'
+ String to make the screen flash.
+
+`ve'
+ String to return the cursor to normal.
+
+`vi'
+ String to make the cursor invisible.
+
+`vs'
+ String to enhance the cursor.
+
+`wi'
+ String to set the terminal output screen window.
+
+`ws'
+ Number: the width of the status line.
+
+`xb'
+ Flag: superbee terminal.
+
+`xn'
+ Flag: cursor wraps in a strange way.
+
+`xs'
+ Flag: clearing a line is the only way to clear the appearance
+ modes of positions in that line (or, only way to remove magic
+ cookies on that line).
+
+`xt'
+ Flag: Teleray 1061; several strange characteristics.
+
+
+File: termcap, Node: Var Index, Next: Cap Index, Prev: Summary, Up: Top
+
+Variable and Function Index
+***************************
+
+* Menu:
+
+* BC: tgoto.
+* ospeed: Output Padding.
+* PC: Output Padding.
+* tgetent: Find.
+* tgetflag: Interrogate.
+* tgetnum: Interrogate.
+* tgetstr: Interrogate.
+* tgoto: tgoto.
+* tparam: tparam.
+* tputs: Output Padding.
+* UP: tgoto.
+
+
+File: termcap, Node: Cap Index, Next: Index, Prev: Var Index, Up: Top
+
+Capability Index
+****************
+
+* Menu:
+
+* ae: Standout.
+* AL: Insdel Line.
+* al: Insdel Line.
+* am: Wrapping.
+* as: Standout.
+* bc: Cursor Motion.
+* bl: Bell.
+* bs: Cursor Motion.
+* bt: Cursor Motion.
+* bw: Cursor Motion.
+* CC: Basic.
+* cd: Clearing.
+* ce: Clearing.
+* ch: Cursor Motion.
+* cl: Clearing.
+* CM: Cursor Motion.
+* cm: Cursor Motion.
+* co: Screen Size.
+* cr: Cursor Motion.
+* cs: Scrolling.
+* cS: Scrolling.
+* ct: Initialization.
+* cv: Cursor Motion.
+* da: Scrolling.
+* dB: Pad Specs.
+* db: Scrolling.
+* dC: Pad Specs.
+* DC: Insdel Char.
+* dc: Insdel Char.
+* dF: Pad Specs.
+* dl: Insdel Line.
+* DL: Insdel Line.
+* dm: Insdel Char.
+* dN: Pad Specs.
+* DO: Cursor Motion.
+* do: Cursor Motion.
+* ds: Status Line.
+* dT: Pad Specs.
+* ec: Clearing.
+* ed: Insdel Char.
+* ei: Insdel Char.
+* eo: Basic.
+* es: Status Line.
+* ff: Cursor Motion.
+* fs: Status Line.
+* gn: Basic.
+* hc: Basic.
+* hd: Half-Line.
+* ho: Cursor Motion.
+* hs: Status Line.
+* hu: Half-Line.
+* hz: Basic.
+* i1: Initialization.
+* i3: Initialization.
+* IC: Insdel Char.
+* ic: Insdel Char.
+* if: Initialization.
+* im: Insdel Char.
+* in: Insdel Char.
+* ip: Insdel Char.
+* is: Initialization.
+* it: Initialization.
+* K1...K5: Keypad.
+* k1...k9: Keypad.
+* kA...kT: Keypad.
+* ka...ku: Keypad.
+* km: Meta Key.
+* l0...l9: Keypad.
+* le: Cursor Motion.
+* LE: Cursor Motion.
+* li: Screen Size.
+* ll: Cursor Motion.
+* lm: Scrolling.
+* mb: Standout.
+* md: Standout.
+* me: Standout.
+* mh: Standout.
+* mi: Insdel Char.
+* mk: Standout.
+* mm: Meta Key.
+* mo: Meta Key.
+* mp: Standout.
+* mr: Standout.
+* ms: Standout.
+* ms: Underlining.
+* nc: Cursor Motion.
+* nd: Cursor Motion.
+* nl: Cursor Motion.
+* ns: Scrolling.
+* nw: Cursor Motion.
+* os: Basic.
+* pb: Pad Specs.
+* pc: Pad Specs.
+* pf: Printer.
+* po: Printer.
+* pO: Printer.
+* ps: Printer.
+* rc: Cursor Motion.
+* RI: Cursor Motion.
+* rp: Basic.
+* rs: Initialization.
+* sa: Standout.
+* sc: Cursor Motion.
+* se: Standout.
+* sf: Scrolling.
+* SF: Scrolling.
+* sg: Standout.
+* so: Standout.
+* SR: Scrolling.
+* sr: Scrolling.
+* st: Initialization.
+* ta: Cursor Motion.
+* te: Initialization.
+* ti: Initialization.
+* ts: Status Line.
+* uc: Underlining.
+* ue: Underlining.
+* ug: Underlining.
+* ul: Underlining.
+* up: Cursor Motion.
+* UP: Cursor Motion.
+* us: Underlining.
+* vb: Bell.
+* ve: Cursor Visibility.
+* vi: Cursor Visibility.
+* vs: Cursor Visibility.
+* wi: Windows.
+* ws: Status Line.
+* xb: Basic.
+* xn: Wrapping.
+* xs: Standout.
+* xt: Cursor Motion.
+* xt: Standout.
+
+
+File: termcap, Node: Index, Prev: Cap Index, Up: Top
+
+Concept Index
+*************
+
+* Menu:
+
+* %: Encode Parameters.
+* appearance modes: Standout.
+* bell: Bell.
+* clearing the screen: Clearing.
+* command character: Basic.
+* cursor motion: Cursor Motion.
+* delete character: Insdel Char.
+* delete line: Insdel Line.
+* delete mode: Insdel Char.
+* description format: Format.
+* erasing: Clearing.
+* generic terminal type: Basic.
+* home position: Cursor Motion.
+* inheritance: Inheriting.
+* initialization: Initialization.
+* insert character: Insdel Char.
+* insert line: Insdel Line.
+* insert mode: Insdel Char.
+* line speed: Output Padding.
+* magic cookie: Standout.
+* meta key: Meta Key.
+* names of terminal types: Naming.
+* overstrike: Basic.
+* padding: Pad Specs.
+* padding: Padding.
+* parameters: Parameters.
+* printer: Printer.
+* repeat output: Basic.
+* reset: Initialization.
+* screen size: Screen Size.
+* screen size: Naming.
+* screen size: Screen Size.
+* scrolling: Scrolling.
+* standout: Standout.
+* status line: Status Line.
+* Superbee: Basic.
+* tab stops: Initialization.
+* termcap: Introduction.
+* terminal flags (kernel): Initialize.
+* underlining: Underlining.
+* visibility: Cursor Visibility.
+* visible bell: Bell.
+* window: Windows.
+* wrapping: Wrapping.
+* wrapping: Naming.
+
+
diff --git a/info/texinfo b/info/texinfo
new file mode 100644
index 00000000000..0f20d11377d
--- /dev/null
+++ b/info/texinfo
@@ -0,0 +1,147 @@
+Info file ../info/texinfo, produced by Makeinfo, -*- Text -*- from
+input file texinfo.texinfo.
+
+This file documents Texinfo, a documentation system that uses a
+single source file to produce both on-line help and a printed manual.
+
+This is edition 1.1 of the Texinfo documentation, and is for the
+Texinfo that is distributed as part of Version 18 of GNU Emacs.
+
+Copyright (C) 1988 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of
+this manual under the conditions for verbatim copying, provided that
+the entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be stated in a
+translation approved by the Foundation.
+
+Indirect:
+texinfo-1: 1062
+texinfo-2: 48679
+texinfo-3: 97174
+texinfo-4: 144851
+
+Tag Table:
+(Indirect)
+Node: Top1064
+Node: License6576
+Node: Overview8743
+Node: Info File11940
+Node: Printed Manual15506
+Node: Conventions17534
+Node: Short Sample20787
+Node: Texinfo Mode23979
+Node: Info on a Region25450
+Node: Showing the Structure26068
+Node: Inserting27212
+Node: Beginning a File28386
+Node: Header31571
+Node: First Line32330
+Node: Start-of-Header33326
+Node: Setfilename34274
+Node: Settitle34782
+Node: Setchapternewpage35792
+Node: End-of-Header36461
+Node: Permissions for Info37259
+Node: Titlepage & Copyright Page37977
+Node: Titlepage38727
+Node: Center39910
+Node: Copyright & Printed Permissions40158
+Node: Top Node42166
+Node: License and Distribution44844
+Node: Ending a File46338
+Node: Contents47206
+Node: Indices48681
+Node: Index Entries51171
+Node: Combining Indices53369
+Node: Printing Indices & Menus55002
+Node: Structuring57375
+Node: Chapter62702
+Node: Unnumbered and Appendix63302
+Node: Section63770
+Node: Subsection64359
+Node: Subsubsection64859
+Node: Node65362
+Node: Menu70060
+Node: Quotations and Examples73123
+Node: Quotation74061
+Node: Example74660
+Node: Display75821
+Node: Lists and Tables76180
+Node: Itemize77492
+Node: Enumerate79374
+Node: Table80615
+Node: Itemx83146
+Node: Cross References85323
+Node: Xref87152
+Node: Pxref91427
+Node: Inforef92360
+Node: Formatting Paragraphs92983
+Node: Refilling & Noindent94246
+Node: Refill95052
+Node: Noindent96223
+Node: Breaks Blank-Lines Groups97176
+Node: Line Breaks98706
+Node: Sp99118
+Node: Br99380
+Node: W99625
+Node: Page99893
+Node: Group100127
+Node: Need100883
+Node: Marking Text101182
+Node: Specifying102040
+Node: Code104509
+Node: Samp106367
+Node: File107401
+Node: Kbd107799
+Node: Key108801
+Node: Ctrl109862
+Node: Var110765
+Node: Dfn111649
+Node: Cite112253
+Node: Braces Atsigns Periods112449
+Node: Inserting An Atsign113607
+Node: Insert Left Brace113778
+Node: Insert Colon114038
+Node: Insert Period114766
+Node: Dots Bullets Tex115518
+Node: Dots116358
+Node: Bullet116731
+Node: Tex116934
+Node: Emphasis117136
+Node: Emph and Strong117946
+Node: Fonts118284
+Node: Conditionals118868
+Node: Using Tex Commands120402
+Node: Printing Hardcopy121426
+Node: Requirements126459
+Node: Compile-Command129137
+Node: Creating an Info File129941
+Node: Installing an Info File133322
+Node: Catching Mistakes135118
+Node: Debugging with Info136352
+Node: Using the Emacs Lisp Debugger139127
+Node: Debugging with Tex141318
+Node: Using texinfo-show-structure144853
+Node: Using Occur147475
+Node: Running Info-Validate148938
+Node: Info-Validating a Large File151046
+Node: Splitting152810
+Node: Command Syntax154342
+Node: Include Files156597
+Node: TeX Input159761
+Node: Sample Permissions161794
+Node: Ifinfo Permissions164661
+Node: Titlepage Permissions166324
+Node: Command Index167630
+Node: Concept Index169779
+
+End Tag Table
diff --git a/info/texinfo-1 b/info/texinfo-1
new file mode 100644
index 00000000000..1471ecc041b
--- /dev/null
+++ b/info/texinfo-1
@@ -0,0 +1,1283 @@
+Info file ../info/texinfo, produced by Makeinfo, -*- Text -*- from
+input file texinfo.texinfo.
+
+This file documents Texinfo, a documentation system that uses a
+single source file to produce both on-line help and a printed manual.
+
+This is edition 1.1 of the Texinfo documentation, and is for the
+Texinfo that is distributed as part of Version 18 of GNU Emacs.
+
+Copyright (C) 1988 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of
+this manual under the conditions for verbatim copying, provided that
+the entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be stated in a
+translation approved by the Foundation.
+
+
+
+File: texinfo, Node: Top, Next: License, Prev: (dir), Up: (dir)
+
+* Menu:
+
+* License:: Licensing information.
+* Overview:: What is Texinfo?
+* Texinfo Mode:: Special features in GNU Emacs.
+* Beginning a File:: What to put at the beginning of a Texinfo file.
+* Ending a File:: What to put at the end of a Texinfo file.
+* Structuring:: How to make nodes and chapters.
+* Quotations and Examples:: How to insert quotations and examples.
+* Lists and Tables:: How to make lists and tables.
+* Cross References:: How to make cross references.
+* Formatting Paragraphs:: How to format paragraphs.
+* Marking Text:: How to mark code, definitions, variables etc.
+* Conditionals:: Putting text in only Info or the printed work.
+* Printing Hardcopy:: How to print a hardcopy of the manual.
+* Creating an Info File:: How to create an on-line Info file.
+* Catching Mistakes:: How to find problems.
+
+Indices, nodes containing large menus
+
+* Command Index:: An item for each @-command.
+* Concept Index:: An item for each concept.
+
+A detailed node listing
+
+Overview
+* Info File:: Characteristics of the Info file.
+* Printed Manual:: Characteristics of the printed manual.
+* Conventions:: General syntactic conventions.
+* Short Sample:: A short sample Texinfo file.
+
+Using Texinfo Mode
+* Info on a Region:: Formatting a region for Info.
+* Showing the Structure:: Showing the structure of a file.
+* Inserting:: Inserting frequently used commands.
+
+Beginning a Texinfo File.
+* First Line:: The first line of a Texinfo file.
+* Start-of-Header:: Identifying the start of the header.
+* Setfilename:: Specifying the name of the Info file.
+* Settitle:: Specifying the title used by the headings.
+* Setchapternewpage:: Starting chapters on odd numbered pages.
+* Titlepage:: The title and copyright page.
+* Center:: Centering a line.
+* Copyright & Printed Permissions:: Ensuring free distributability.
+* Top Node:: The master menu.
+* License and Distribution:: Your are free to copy and distribute this.
+
+Ending a Texinfo File
+* Contents:: Generating tables of contents.
+* Indices:: Generating indices.
+* Index Entries:: Defining the entries of an index.
+* Combining Indices:: Putting two or more indices together.
+* Printing Indices & Menus:: Printing an index and generating menus.
+
+Node and Chapter Structuring
+* Chapter:: Creating a chapter.
+* Unnumbered and Appendix:: Chapter-like parts.
+* Section:: Creating sections
+* Subsection:: Creating subsections.
+* Subsubsection:: Creating subsubsections.
+
+* Node:: Creating nodes.
+* Menu:: Creating menus.
+
+
+Making quotations and examples
+* Quotation:: Inserting long quotations.
+* Example:: Inserting examples of code and the like.
+* Display:: Inserting displayed text.
+
+Making lists and two column tables
+* Itemize:: Creating itemized lists.
+* Enumerate:: Creating enumerated lists.
+* Table:: Creating two column tables.
+* Itemx:: Putting an extra item in the
+ first column of a table.
+
+Making Cross References
+* Xref:: Making a regular cross reference.
+* Pxref:: Making a parenthetical cross reference.
+* Inforef:: Making a cross reference to an Info file.
+
+
+Formatting Paragraphs
+* Refilling & Noindent:: Refilling paragraphs
+ and preventing indentation
+* Refill:: Using the `@refill' command.
+* Noindent:: Using the `@noindent' command.
+
+
+Breaks, Blank Lines and Groups
+* Line Breaks:: Inserting line breaks in TeX.
+* Sp:: Inserting blank lines.
+* Br:: Inserting paragraph breaks.
+* W:: Preventing line breaks.
+* Page:: Starting new pages.
+* Group:: Holding text together on one page.
+* Need:: Keeping text together.
+
+Marking Text Within a Paragraph
+* Code:: A literal example of a piece of a program.
+* Samp:: A literal example of a sequence of characters.
+* File:: The name of a file.
+* Kbd:: The names of keys or else characters you type.
+* Key:: The conventional name for a key on a keyboard.
+* Ctrl:: Indicates the ASCII control character.
+* Var:: A variable.
+* Dfn:: The introductory or defining use of a term.
+* Cite:: The name of a book.
+
+Inserting Braces, `@' and Periods
+* Braces Atsigns Periods:: Inserting braces, `@' and periods.
+* Dots Bullets Tex:: Inserting dots, bullets and the TeX logo
+* Emphasis:: Emphasizing text.
+
+Emphasizing Text
+* Emph and Strong:: Emphasizing text.
+* Fonts:: Selecting italic, bold or typewriter fonts.
+
+Creating an Info File
+* Installing an Info File:: Putting the Info file in the
+ `info' directory.
+
+Catching Mistakes
+* Debugging with Info:: Catching errors with info formatting.
+* Using the Emacs Lisp Debugger:: Using the Emacs Lisp Debugger
+* Debugging with Tex:: Catching errors with TeX formatting.
+* Using texinfo-show-structure:: Using `texinfo-show-structure'
+ to catch mistakes.
+* Using Occur:: Using `occur' to catch mistakes.
+* Running Info-Validate:: Checking for unreferenced nodes.
+
+Finding badly referenced nodes
+* Info-Validating a Large File:: Running `Info-validate'
+ on a large file.
+* Splitting:: Splitting a file manually.
+
+Appendices
+* Command Syntax:: Details about the syntax.
+* Include Files:: Making one printed file out of
+ several Info files.
+* TeX Input:: Where TeX finds its `\input' file.
+* Sample Permissions:: You may copy GNU Software.
+* Ifinfo Permissions:: What to put in the `ifinfo' section.
+* Titlepage Permissions:: What to put in the `@titlepage' section.
+
+
+
+File: texinfo, Node: License, Next: Overview, Prev: Top, Up: Top
+
+Licensing Information
+*********************
+
+ The programs currently being distributed that relate to Texinfo
+include two portions of GNU Emacs, plus two other separate programs
+(`texindex' and `texinfo.tex'). These programs are "free"; this
+means that everyone is free to use them and free to redistribute them
+on a free basis. The Texinfo related programs are not in the public
+domain; they are copyrighted and there are restrictions on their
+distribution, but these restrictions are designed to permit
+everything that a good cooperating citizen would want to do. What is
+not allowed is to try to prevent others from further sharing any
+version of these programs that they might get from you.
+
+ Specifically, we want to make sure that you have the right to give
+away copies of the programs that relate to Texinfo, that you receive
+source code or else can get it if you want it, that you can change
+these programs or use pieces of them in new free programs, and that
+you know you can do these things.
+
+ To make sure that everyone has such rights, we have to forbid you to
+deprive anyone else of these rights. For example, if you distribute
+copies of the Texinfo related programs, you must give the recipients
+all the rights that you have. You must make sure that they, too,
+receive or can get the source code. And you must tell them their
+rights.
+
+ Also, for our own protection, we must make certain that everyone
+finds out that there is no warranty for the programs that relate to
+Texinfo. If these programs are modified by someone else and passed
+on, we want their recipients to know that what they have is not what
+we distributed, so that any problems introduced by others will not
+reflect on our reputation.
+
+ The precise conditions of the licenses for the programs currently
+being distributed that relate to Texinfo are found in the General
+Public Licenses that accompany them. The programs that are part of
+GNU Emacs are covered by the GNU Emacs copying terms (*note :
+(emacs)License.), and other programs are covered by licenses that are
+contained in their source files.
+
+
+
+File: texinfo, Node: Overview, Next: Texinfo Mode, Prev: License, Up: Top
+
+Overview of Texinfo
+*******************
+
+Texinfo is a documentation system that uses a single source file for
+both on-line help and a printed manual. This means that instead of
+writing two different documents, one for the on-line help and the
+other for the printed manual, only one document needs to be written.
+When the system is revised, only one file has to be revised.
+
+Using Texinfo, you can create a document with the normal features of
+a book such as chapters, sections, cross references and indices. The
+chapters and sections of the printed manual can be made to correspond
+to the nodes of the on-line help. The cross references and indices
+can be used in both the on-line help and in the printed document.
+Indices are generated semi-automatically. The ``GNU Emacs Manual''
+is a good example of a Texinfo file.
+
+To make the printed manual, the Texinfo source file is processed by
+the TeX typesetting program; the resulting DVI file can be typeset
+and printed as a book. To make the on-line help, the Texinfo source
+file is by processed the `M-x texinfo-format-buffer' command; the
+resulting Info file is installed in the `info' directory.
+
+Since the Texinfo source file is used for a dual task--to create both
+the on-line help and the printed manual--it must be written in a
+special format that uses @-commands (words preceded by an `@') to
+indicate chapters, sections, nodes, examples, index entries and the
+like.
+
+Before writing a Texinfo source file, you should be familiar with the
+on-line Info documentation reading program. (*note info: (info)Info,
+for more information.) If you are writing a document that will be
+both on-line and printed, you will need both Info and TeX.
+
+To make an Info file, you use the `M-x texinfo-format-buffer' command
+in GNU Emacs.
+
+To make a printed manual, you need to use TeX, a powerful,
+sophisticated typesetting program written by Donald Knuth. TeX is
+freely distributable. It is written in a dialect of Pascal called WEB
+and can be compiled either in Pascal or (by using a conversion
+program that comes with the TeX distribution) in C. (For information
+about getting TeX, *note : (emacs)TeX Mode.)
+
+When TeX processes a Texinfo source file, TeX makes use of a macro
+definitions file called `texinfo.tex' that comes with the GNU Emacs
+distribution in the `emacs/man' sources directory. (The first line
+of every Texinfo file has a command that says `\input texinfo'; this
+tells TeX to use the `texinfo.tex' file.)
+
+If the `texinfo.tex' file has not already been copied to the
+directory which contains the other TeX macro definition files when
+Emacs was installed, you will probably want to copy it to that
+directory. Usually, this is the `/usr/lib/tex/macros' directory.
+For more information, *note @TeX{} Input Initialization: TeX Input.
+
+Documentation for GNU utilities and libraries should be written in
+Texinfo format.
+
+* Menu:
+
+* Info File:: Characteristics of the Info file.
+* Printed Manual:: Characteristics of the Printed Manual.
+* Conventions:: General Syntactic Conventions.
+* Short Sample:: A short sample Texinfo file.
+
+
+
+File: texinfo, Node: Info File, Next: Printed Manual, Up: Overview
+
+Characteristics of the Info file
+================================
+
+A Texinfo file can be transformed into a printed manual and an
+on-line Info file.
+
+An on-line Info file is a file formatted so that the Info
+documentation reading program can operate on it. Info files are
+divided into pieces called "nodes", each of which contains the
+discussion of one topic. Each node has a name, and contains both
+text for the user to read and pointers to other nodes, which are
+identified by their names. The Info program displays one node at a
+time, and provides commands with which the user can move to the other
+nodes to which the current node points.
+
+*note info: (info)Info, for more information about using Info.
+
+Normally, most of the nodes are arranged in a tree which branches down.
+Each node may have any number of child nodes that describe subtopics
+of the node's topic. The names of these child nodes, if any, are
+listed in a "menu" within the parent node; this allows certain Info
+commands to be used to move to one of the child nodes. Each child
+node records the parent node name, as its `Up' pointer. Thus, if a
+node were at the logical level of a `chapter', its child nodes would
+be `sections'; likewise, the child nodes of a section would be
+subsections.
+
+The root of the tree is the top node of the file, through which users
+enter the file from the Info directory. By convention, this node is
+always called `Top'. This node normally contains just a brief
+summary of the file's purpose, and a large menu through which the
+rest of the file is reached.
+
+Generally you enter the Info file from the top; then you can either
+traverse the file systematically by going from node to node or you
+can search large menus that correspond to indices and go directly to
+the node that has the information you want.
+
+If you want to read through an Info file in sequence, as if it were a
+printed manual, you can get the whole file with the advanced Info
+command `g *'. (*note info: (info)Expert.)
+
+All the children of any one parent are linked together in a
+bidirectional chain of `Next' and `Previous' pointers. This means
+that all the nodes that are logically parallel to sections within a
+chapter are all linked together. Normally the order in this chain is
+the same as the order of the children in the parent's menu. The last
+child has no `Next' pointer, and the first child normally has the
+parent as its `Previous' pointer (as well as its `Up' pointer, of
+course).
+
+Structuring the nodes in a tree is a matter of convention, not a
+requirement. In fact, the `Up', `Previous' and `Next' pointers of a
+node can point to any other nodes, and the menu can contain any other
+nodes. The structure of nodes can be any directed graph. But it is
+usually more comprehensible to make it a tree. Info provides another
+kind of pointer between nodes, called a reference, that can be
+sprinkled through the text of a node. This is usually the best way
+to represent links that do not fit the tree structure.
+
+Most often the nodes fall into a strict tree structure that
+corresponds to the structure of chapters and sections in the printed
+manual. But there are times when this is not right for the material
+being discussed. Therefore, Texinfo uses separate commands to
+specify the node structure of the Info file and the section structure
+of the printed manual. Also, Texinfo requires that you specify menus
+explicitly, rather than generate them automatically based on an
+assumed tree structure.
+
+
+
+File: texinfo, Node: Printed Manual, Next: Conventions, Prev: Info File, Up: Top
+
+Characteristics of the Printed Manual
+=====================================
+
+A Texinfo file can be formatted and typeset as a printed manual. The
+printed manual will be the same as any other book; it will have a
+title page, copyright page, table of contents, and preface as you
+would expect, as well as chapters, numbered or unnumbered sections
+and subsections, not to mention page headers, cross references and
+indices.
+
+Texinfo can be used for writing a book without ever having the
+intention of converting it into on-line help. Texinfo can be used
+for writing a novel; and it can even be used to write a memo,
+although this application is not recommended since electronic mail is
+so much easier.
+
+Texinfo uses the formatting language called TeX for typesetting. A
+file called `texinfo.tex' contains information (definitions or
+"macros") that TeX uses when it typesets a Texinfo file. (The macros
+tell TeX how to convert the Texinfo @-commands to TeX commands which
+TeX can then process to create the typeset document.) `texinfo.tex'
+contains the specifications for printing a document, either with 7
+inch by 9.25 inch pages or with 8.5 inch by 11 inch pages. (This is
+178 mm by 235 mm or else 216 mm by 280 mm.) Also, by changing the
+parameters in `texinfo.tex' you can easily change the size of the
+printed document. In addition, you can readily change the style in
+which the printed document is formatted; for example, you can change
+the sizes and fonts used, the amount of indentation for each
+paragraph, the degree to which words are hyphenated, and the like.
+By changing the specifications, you can make a book look dignified,
+old and serious, or light-hearted, young and cheery.
+
+TeX is very powerful and has a great many features. Because a
+Texinfo file must be able to present information both on a
+character-only terminal in Info form and in a typeset book, the
+commands that Texinfo supports are necessarily limited.
+
+
+
+File: texinfo, Node: Conventions, Next: Short Sample, Prev: Printed Manual, Up: Overview
+
+General Syntactic Conventions
+=============================
+
+Texinfo files contain a strictly limited set of constructs. The
+strict limits make it possible for Texinfo files to be understood
+both by TeX and by the code which converts them into Info files.
+
+All ASCII printing characters except `@', `{' and `}' can appear in
+body text in a Texinfo file and stand for themselves. `@' is the
+escape character which introduces commands. `{' and `}' should be
+used only to surround arguments to certain commands. `{' and `}'
+appearing anywhere else will be treated by TeX as a grouping but
+treated by the code that produces an Info file as themselves; this
+inconsistency is undesirable, so don't let it occur. To put one of
+these special characters into the document, put an `@' character in
+front of it. For example, you would insert `@@', `@{', and `@}'.
+
+It is customary in TeX to use doubled single-quote characters to
+begin and end quotations, `"' like these `"'. This convention should
+be followed in Texinfo files. Also, three hyphens in a row, `--',
+are used for a dash--like this. In TeX, a single or even a double
+hyphen produces a dash that is shorter than you want.
+
+TeX ignores the line-breaks in the input text, except for blank
+lines, which separate paragraphs. Info generally preserves the line
+breaks that are present in the input file. Therefore, break the
+lines in the Texinfo file the way you want them to appear in the
+output Info file, and let TeX take care of itself.
+
+Since Info does not normally refill paragraphs when it processes
+them, a line with @-commands in it will sometimes look bad after Info
+has run on it. To cause Info to refill the paragraph after finishing
+with the other processing, you need to put the command `@refill' at
+the end of the paragraph. (*Note Refilling paragraphs and Preventing
+indentation: Refilling & Noindent.)
+
+To prevent a paragraph from being indented in the printed manual, put
+the command `@noindent' on a line by itself before the start of the
+text that should not be indented.
+
+If you mark off a region of the Texinfo file with the `@iftex' and
+`@end iftex' commands so that the region will appear only in the
+printed copy, you can use TeX commands that cannot be used in the
+Info file.
+
+In order to be made into a printed manual, a Texinfo file *must*
+begin with lines that looks like
+
+ \input texinfo @c -*-texinfo-*-
+ @setfilename INFO-FILE-NAME
+ @settitle NAME OF MANUAL
+
+The `\input texinfo' line tells TeX to use the `texinfo.tex' file.
+This line is usually followed by a start-of-header line (not shown
+here) and then by the `@setfilename INFO-FILE-NAME' and `@settitle
+NAME OF MANUAL' lines. These two lines are needed to provide a name
+for the Info file and to specify the name used on the left-hand page
+headers of the printed manual.
+
+The two lines that contain the `@setfilename' and `@settitle'
+commands usually are sandwiched between the start-of-header line and
+the end-of-header line. (*Note Start-of-Header::, for more
+information.) The start-of-header and end-of-header lines are needed
+if you are going to run TeX or Info on just part of a file.
+
+
+
+File: texinfo, Node: Short Sample, Prev: Conventions, Up: Overview
+
+A Short Sample Texinfo File
+===========================
+
+A Texinfo file looks like the following, which is a complete but very
+short Texinfo file. The `@comment' command introduces comments that
+will not appear in either the Info file or the printed manual; they
+are for the person who reads the Texinfo file.
+
+The first part of the file, from `\input texinfo' through to `@end
+titlepage', looks more intimidating than it is. Most of the material
+is standard boilerplate; when you write a manual, you just put in the
+name of your own manual in this section.
+
+All the commands that tell TeX how to typeset the printed manual and
+tell `texinfo-format-buffer' how to create an Info file are preceded
+by `@'; thus, `@node' indicates a node and `@chapter' indicates the
+start of a chapter.
+
+ \input texinfo @c -*-texinfo-*-
+ @setfilename name-of-texinfo-file
+ @settitle Name of Manual
+ @setchapternewpage odd
+
+ @ifinfo
+ @comment The following line inserts the copyright notice
+ @comment into the Info file.
+ Copyright @copyright{} 1988 Free Software Foundation, Inc.
+ @end ifinfo
+
+ @comment The titlepage section does not appear in the Info file.
+ @titlepage
+ @sp 10
+ @comment The title is printed in a large font.
+ @center @titlefont{Sample Title}
+
+ @comment The following two commands start the copyright page
+ @comment for the printed manual. This will not appear in the Info file.
+ @page
+ @vskip 0pt plus 1filll
+ Copyright @copyright{} year copyright-owner
+ @end titlepage
+
+ @comment The Top node contains the master menu for the Info file.
+ @comment This appears only in the Info file, not the printed manual.
+
+ @node Top, First Chapter, (dir), (dir)
+ @comment node-name, next, previous, up
+
+ @menu
+ * First Chapter:: The first chapter is the
+ only chapter in this sample.
+ @end menu
+
+ @node First Chapter, , Top, Top
+ @comment node-name, next, previous, up
+ @chapter First Chapter
+ @cindex Reference to First Chapter
+
+ This is the contents of the first chapter.
+
+ Here is a numbered list.
+
+ @enumerate
+ @item
+ This is the first item.
+
+ @item
+ This is the second item.
+ @end enumerate
+
+ The @kbd{M-x texinfo-format-buffer} command transforms a Texinfo file
+ like this into an Info file; and @TeX{} typesets it for a printed
+ manual.
+
+ @node Concept Index, , Previous Node, Top
+ @comment node-name, next, previous, up
+ @unnumbered Concept Index
+
+ @printindex cp
+
+ @contents
+ @bye
+
+Here is what the contents of the first chapter of the sample look like:
+
+ This is the contents of the first chapter.
+
+ Here is a numbered list.
+
+ 1. This is the first item.
+
+ 2. This is the second item.
+
+ The `M-x texinfo-format-buffer' command transforms a Texinfo
+ file like this into an Info file; and TeX typesets it for a
+ printed manual.
+
+
+
+File: texinfo, Node: Texinfo Mode, Next: Beginning a File, Prev: Overview, Up: Top
+
+Using Texinfo Mode
+******************
+
+In GNU Emacs, Texinfo mode is a major mode for editing Texinfo files.
+This means that Emacs has commands and features especially designed
+for working with Texinfo files. Like all other Emacs features, you
+can customize or enhance these as you wish. In particular, the
+keybindings are very easy to change. The keybindings described here
+are the default or standard ones.
+
+The major features of Texinfo mode are:
+
+ * Paragraph filling control.
+
+ * A command to show the structure of the file.
+
+ * Pre-defined keystroke commands to insert commonly used strings
+ of text.
+
+ * Formatting a part of a file for Info, rather than the whole file.
+
+In general, in Texinfo mode, the GNU Emacs editing commands are like
+those in text-mode. The major difference is that the paragraph
+separation variable and syntax table are set up so expression
+commands skip Texinfo bracket groups. This means, for example, that
+the `M-q' (`fill-paragraph') command will refill a paragraph but not
+the @-command on a line adjacent to it.
+
+By convention, the Texinfo file name shall end with the extension
+`.texinfo' so that Emacs knows to use Texinfo mode for editing it.
+
+* Menu:
+
+* Info on a Region:: Formatting part of a file for Info.
+* Showing the Structure:: Showing the structure of a file.
+* Inserting:: Inserting frequently used commands.
+
+
+
+File: texinfo, Node: Info on a Region, Next: Showing the Structure, Prev: Texinfo Mode, Up: Texinfo Mode
+
+Formatting a Region for Info
+============================
+
+To see what part of a Texinfo file will look like after it has been
+transformed into an Info file, use the command `C-c C-f'
+(`texinfo-format-region'). This command formats the current region
+of the Texinfo file for Info and writes it to a temporary buffer
+called `*Info Region*'.
+
+For `texinfo-format-region' to work, the file *must* include a line
+that has `@setfilename' in its header.
+
+The command is:
+
+`C-c C-f'
+ texinfo-format-region
+
+
+
+File: texinfo, Node: Showing the Structure, Next: Inserting, Prev: Info on a Region, Up: Texinfo Mode
+
+Showing the Structure of a File
+===============================
+
+You can show the structure of a Texinfo file by using the `C-c C-s'
+command (`texinfo-show-structure'). This command shows the structure
+of a Texinfo file by listing the lines with the @-commands for
+`@node', `@chapter', `@section' and the like. These lines are
+displayed in another window called the `*Occur*' window. In that
+window, you can position the cursor over one of the lines and use the
+`C-c C-c' command (`occur-mode-goto-occurrence'), to jump to the
+corresponding spot in the Texinfo file.
+
+The two commands are:
+
+`C-c C-s'
+ texinfo-show-structure
+
+`C-c C-c'
+ occur-mode-goto-occurrence
+
+Often, when you are working on a manual, you will be interested only
+in the structure of the current chapter. In this case, you can mark
+off the region of the buffer that you are interested in with the `C-x
+n' (`narrow-to-region') command and `texinfo-show-structure' will
+work on only that region. (To see the whole buffer again, use `C-x
+w' (`widen').)
+
+
+
+File: texinfo, Node: Inserting, Prev: Showing the Structure, Up: Texinfo Mode
+
+Inserting Frequently Used Commands
+==================================
+
+Texinfo mode provides commands that insert various frequently used
+@-commands into the buffer. You can use these commands to save
+keystrokes. And you can insert balanced curly braces with the `M-{'
+command, (`texinfo-insert-braces') and later use the `M-}' command
+(`up-list') to move forward past the closing brace.
+
+The special commands are invoked by typing `C-c' twice and then the
+first letter of the @-command.
+
+`C-c C-c c'
+ texinfo-insert-@code
+
+`C-c C-c d'
+ texinfo-insert-@dfn
+
+`C-c C-c e'
+ texinfo-insert-@end
+
+`C-c C-c i'
+ texinfo-insert-@item
+
+`C-c C-c n'
+ texinfo-insert-@node
+
+`C-c C-c s'
+ texinfo-insert-@samp
+
+`C-c C-c v'
+ texinfo-insert-@var
+
+`M-{'
+ texinfo-insert-braces
+
+`M-}'
+ up-list
+
+This list was generated by analyzing the frequency with which
+commands were used in the ``GNU Emacs Manual'' and the ``GDB
+Manual''. If you wish to add your own insert commands, you can bind
+a keyboard macro to a key, use abbreviations or extend the code in
+`texinfo.el'.
+
+
+
+File: texinfo, Node: Beginning a File, Next: Ending a File, Prev: Texinfo Mode, Up: Top
+
+Beginning a Texinfo File
+************************
+
+Various pieces of information have to be provided to Texinfo at the
+beginning of a Texinfo file, such as the name of the file, the title
+of the document and the like. Generally, the beginning of a Texinfo
+file has four parts:
+
+ 1. The header, marked by start-of-header and end-of-header lines,
+ that includes the commands for naming the Texinfo file and
+ telling TeX what definitions' file to use when processing the
+ file.
+
+ 2. A section, marked by the `@ifinfo' and `@end ifinfo' commands,
+ that contains a short statement of what the file is about, the
+ copyright notice and copying permissions. This section appears
+ only in the Info file.
+
+ 3. A section, marked by the `@titlepage' and `@end titlepage'
+ commands, that contains the title page, the copyright page and
+ copying permissions. This section appears only in the printed
+ manual.
+
+ 4. The `Top' node that contains an extensive menu for the whole
+ Info file. The contents of this node only appear in the Info
+ file.
+
+If the Texinfo file has a section containing licensing information
+and a warranty disclaimer, that section usually follows the `Top'
+node. The licensing section will be followed by a preface or else by
+the first chapter of the manual.
+
+Since the copyright notice and the copying permissions are in
+sections that appear only in the Info file or only in the printed
+manual, this information has to be repeated twice.
+
+The following sample shows what is needed.
+
+ \input texinfo @c -*-texinfo-*-
+ @comment %**start of header (This is for running Texinfo on a region.)
+ @setfilename name-of-texinfo-file
+ @settitle Name of Manual
+ @setchapternewpage odd
+ @comment %**end of header (This is for running Texinfo on a region.)
+
+ @ifinfo
+ This file documents ...
+
+ Copyright @copyright{} year copyright-owner
+
+ Permission is granted to ...
+ @end ifinfo
+
+ @titlepage
+ @sp 10
+ @center @titlefont{Name of Manual When Printed}
+ @sp 2
+ @center Subtitle, If Any
+ @sp 2
+ @center Author
+
+ @comment The following two commands start the copyright page.
+ @page
+ @vskip 0pt plus 1filll
+ Copyright @copyright{} year copyright-owner
+
+ Published by ...
+
+ Permission is granted to ...
+ @end titlepage
+
+
+ @node Top, Overview, (dir), (dir)
+
+ @menu
+ * First Chapter:: The first chapter is usually an overview.
+ * Second Chapter:: ...
+ <many more menu items here>
+ @end menu
+
+ @node First Chapter, Second Chapter, top, top
+ @comment node-name, next, previous, up
+ @chapter First Chapter
+ @cindex Reference to First Chapter
+
+* Menu:
+
+* Header:: Necessary first lines.
+* Permissions for Info:: Copyright notice and copying permissions.
+* Titlepage & Copyright Page:: Printed title and copyright pages.
+* Top Node:: The top node and master menu.
+* License and Distribution:: The importance of the license.
+
+
+
+File: texinfo, Node: Header, Next: Permissions for Info, Prev: Beginning a File, Up: Beginning a File
+
+The Texinfo File Header
+=======================
+
+Texinfo files start with at least three lines that provide Info and
+TeX with necessary information. If you want to run TeX on just a
+part of the Texinfo File, you also have to mark these heading lines
+with start-of-header and end-of-header lines.
+
+* Menu:
+
+* First Line:: The first line of a Texinfo file.
+* Start-of-Header:: Identifying the start of the header.
+* Setfilename:: Specifying the name of the Info file.
+* Settitle:: Specifying the title used by the headings.
+* Setchapternewpage:: Starting chapters on odd numbered pages.
+* End-of-Header:: Identifying the end of the header.
+
+
+
+File: texinfo, Node: First Line, Next: Start-of-Header, Prev: Header, Up: Header
+
+The First Line of a Texinfo File
+--------------------------------
+
+Every Texinfo file that is to be the top-level input to TeX must
+begin with a line that looks like this:
+
+ \input texinfo @c -*-texinfo-*-
+
+The line serves two functions:
+
+ 1. When the file is processed by TeX, it loads the macros needed
+ for processing a Texinfo file. These are in a file called
+ `texinfo.tex' which is usually located in the
+ `/usr/lib/tex/macros' directory.
+
+ 2. When the file is edited in GNU Emacs, it causes Texinfo mode to
+ be used.
+
+The `\input texinfo' line should be followed by the start-of-header
+line. This makes it possible for the command for running TeX on a
+part of the Texinfo file (`texinfo-hardcopy-region') to operate. The
+reason for this is that the `texinfo-hardcopy-region' command will
+look on the line preceding the start-of-header line for the `\input
+texinfo' line.
+
+
+
+File: texinfo, Node: Start-of-Header, Next: Setfilename, Prev: First Line, Up: Header
+
+`start-of-header'
+-----------------
+
+The start-of-header line should immediately follow the first line of
+the Texinfo file.
+
+The `texinfo-hardcopy-region' command will look at the line preceding
+the start-of-header line to find the `\input texinfo' line.
+
+Usually, the start-of-header line looks like this:
+
+ @comment %**start of header (This is for running Texinfo on a region.)
+
+The reason for the odd string of characters (`%**') is so that the
+`texinfo-hardcopy-region' command does not accidently find something
+that it shouldn't when it is looking for the header.
+
+In the default configuration, the phrase `(This is for running
+Texinfo on a region.)' is not needed and is just included to make it
+easier for someone reading the Texinfo file.
+
+The start-of-header line and the end-of-header line are Texinfo mode
+variables that you can change.
+
+
+
+File: texinfo, Node: Setfilename, Next: Settitle, Prev: Start-of-Header, Up: Header
+
+@setfilename
+------------
+
+In order to be made into an Info file, a Texinfo file must contain a
+line that looks like this:
+
+ @setfilename INFO-FILE-NAME
+
+This line specifies the name of the Info file to be generated. In
+fact, there can be other things in the file before this line, but
+they are ignored in the generation of an Info file. The
+`@setfilename' line is ignored when a printed manual is generated.
+
+
+
+File: texinfo, Node: Settitle, Next: Setchapternewpage, Prev: Setfilename, Up: Header
+
+@settitle
+---------
+
+In order to be made into a printed manual file, a Texinfo file must
+contain a line that specifies the title of the manual. Texinfo uses
+this information during printing to put the title on every other page
+as a heading; Texinfo puts the current chapter title on the other
+pages. Texinfo can find the name of the chapter title from the
+information provided by the `@chapter' command, but you must tell it
+the manual title with `@settitle':
+
+ @settitle TITLE
+
+This command, on a line by itself, causes TITLE to be used for the
+headings. Usually, you will use the same words for the title on the
+title page and for the title specified by this command for the
+headings, but the two could be different. For example, the title on
+the title page may be longer than the title specified by the
+`settitle' command.
+
+The `@settitle' command should precede everything that generates
+actual output.
+
+
+
+File: texinfo, Node: Setchapternewpage, Next: End-of-Header, Prev: Settitle, Up: Header
+
+@setchapternewpage
+------------------
+
+Conventionally, chapters start on the page on the right hand side of
+a book; and the right hand page has an odd number. To make sure that
+Texinfo does this, you can use the command `@setchapternewpage'. For
+example, to cause each chapter to start on a fresh odd-numbered page:
+
+ @setchapternewpage odd
+
+Page numbering is turned on by the `@end titlepage' command, so the
+`@setchapternewpage' should come before it. Although it can occur
+anywhere in the beginning of the file, it is most convenient to put
+it in this location.
+
+
+
+File: texinfo, Node: End-of-Header, Prev: Setchapternewpage, Up: Header
+
+`end-of-header'
+---------------
+
+The end-of-header line should follow the line containing the
+`@setchapternewpage' command.
+
+Usually, the end-of-header line looks like this:
+
+ @comment %**end of header (This is for running Texinfo on a region.)
+
+In the default configuration, the phrase `(This is for running
+Texinfo on a region.)' is not needed and is just included to make it
+easier for someone reading the Texinfo file.
+
+The reason for the odd string of characters (`%**') is so that the
+`texinfo-hardcopy-region' command does not accidently find something
+that it shouldn't when it is looking for the header.
+
+The start-of-header line and the end-of-header line are Texinfo mode
+variables that you can change.
+
+
+
+File: texinfo, Node: Permissions for Info, Next: Titlepage & Copyright Page, Prev: Header, Up: Beginning a File
+
+Copying Permissions for Info
+============================
+
+Since the title page and the copyright page appear only in the
+printed copy of the manual, the same information has to inserted in a
+section that appears only in the Info file. This section usually
+contains a brief description of the contents of the Info file, a
+copyright notice and copying permissions.
+
+The copyright notice should read:
+
+ Copyright YEAR COPYRIGHT-OWNER
+
+and be put on a line by itself.
+
+Standard text for the copyright permissions is contained in the
+appendix. *Note Ifinfo Permissions::, for the complete text.
+
+
+
+File: texinfo, Node: Titlepage & Copyright Page, Next: Top Node, Prev: Permissions for Info, Up: Beginning a File
+
+The Title and Copyright Pages
+=============================
+
+The title and copyright pages appear in the printed manual, but not
+in the Info file. Because of this, it is possible to use a couple of
+slightly obscure TeX typesetting commands that could not be used in
+an Info file. In addition, this part of the beginning of a Texinfo
+file contains the text of the copying permissions that will appear in
+the printed manual.
+
+* Menu:
+
+* Titlepage:: Creating a title page for the printed manual.
+* Center:: Centering a line.
+* Copyright & Printed Permissions:: Inserting the copyright notice
+ and printed permissions.
+
+
+
+File: texinfo, Node: Titlepage, Next: Center, Prev: Titlepage & Copyright Page, Up: Titlepage & Copyright Page
+
+@titlepage
+----------
+
+Start the material for the title page and following copyright page
+with `@titlepage' on a line by itself and end it with `@end
+titlepage' on a line by itself. The title page and copyright page
+material appears only in the printed manual, not in the Info file.
+
+Also, the `@end titlepage' command starts a new page and turns on
+page numbering (generation of headings). Therefore, all the material
+that you want to appear on unnumbered pages should be put between the
+`@titlepage' and `@end titlepage' commands. By using the `@page'
+command you can force a page break within the region delineated by
+the `@titlepage' and `@end titlepage' commands and create more than
+one unnumbered page. This is how the copyright page is produced.
+
+To select a large font suitable for the title itself, you can use the
+command `@titlefont'. For example:
+
+ @center @titlefont{Texinfo}
+
+Also, you can use `@sp' commands to adjust vertical spacing. For
+example:
+
+ @sp 2
+
+In the sample, the spacing was chosen to fit an 8 1/2 by 11 inch
+manual.
+
+
+
+File: texinfo, Node: Center, Next: Copyright & Printed Permissions, Prev: Titlepage, Up: Titlepage & Copyright Page
+
+@center
+-------
+
+A line containing `@center TEXT' produces a line of output containing
+TEXT, centered between the margins.
+
+
+
+File: texinfo, Node: Copyright & Printed Permissions, Prev: Center, Up: Titlepage & Copyright Page
+
+The Copyright Page and Printed Permissions
+------------------------------------------
+
+By international treaty, the copyright notice for a book should
+either be on the title page or on the back of the title page. Other
+locations in a book are not official and do not provide copyright
+protection. The copyright notice should include the year followed by
+the name of the person or organization who has the copyright.
+
+When the copyright notice is on the back of the title page, the page
+is not numbered. Therefore, in Texinfo, the information on the
+copyright page should be within the region delineated by the
+`@titlepage' and `@end titlepage' commands.
+
+To cause a page break, the `@page' command is used. In the sample,
+the `@page' command is followed by the somewhat mysterious line that
+reads: `@vskip 0pt plus 1filll'. This is a line that uses TeX
+commands to push the copyright notice and the other text on the
+copyright page towards the bottom of the page. The `@vskip' command
+means to skip lines and put in white space. The `0pt plus 1filll'
+means to put in zero points of mandatory white space, and as much
+optional white space as needed. Note the use of three `l's in the
+word `filll'; this is the correct use in TeX.
+
+The `@copyright{}' command generates a `c' inside a circle. The
+copyright notice itself has the following legally defined sequence:
+
+ Copyright (C) YEAR COPYRIGHT-OWNER
+
+It is customary to put information on how to get a manual after the
+copyright notice (the address of the Free Software Foundation, for
+example) and the permissions.
+
+Note that the permissions have to be repeated here as well as in the
+`ifinfo' section that immediately follows the header since this
+section appears only in the printed manual and the `ifinfo' section
+appears only in the Info file.
+
+Standard text for the permissions appears in the appendix. *Note
+Sample Permissions::.
+
+
+
+File: texinfo, Node: Top Node, Next: License and Distribution, Prev: Titlepage & Copyright Page, Up: Beginning a File
+
+The Top Node and Master Menu
+============================
+
+The `Top' node contains an extensive, master menu for the whole Info
+file. The contents of this node appear only in the Info file.
+Nothing in this node should appear in the printed file. Since a node
+line by itself and a menu by itself are not printed, the contents of
+this node do not have to be within a region delineated by `@ifinfo'
+and `@end ifinfo' commands. However, any text within the node should
+be marked off in that manner. You may want to put a short summary
+before the master menu inside a region delineated by `@ifinfo' and
+`@end ifinfo' commands. Usually, the `Previous' and `Up' nodes refer
+to the top level directory of the whole Info system, with pointers to
+`(dir)'.
+
+Generally, the top menu is divided into parts.
+
+ * The first part contains the major nodes in the Texinfo file: the
+ nodes for the chapters, chapter-like sections and the major
+ appendices.
+
+ * The second part contains entries for the indices. In an Info
+ file, it is very useful to have indices here at the beginning of
+ the file in the top node rather than at the end, as in a printed
+ book.
+
+ * The third and subsequent parts contain a listing of the other,
+ lower level nodes, often ordered by chapter. This way, an
+ inquirer can go directly to a particular node if he or she is
+ searching for specific information. (These nodes are not
+ required; use them if you think they are a convenience.)
+
+Each section in the menu can be introduced a descriptive line. So
+long as the line does not begin with an asterisk, it will not be
+treated as a menu item. (*Note Making Menus: Menu, for more
+information.)
+
+For example, the Top node of this manual looks like this (but with
+many more entries):
+
+ @node Top, Overview, (dir), (dir)
+
+ @menu
+ * Overview:: What is Texinfo?
+ * Texinfo Mode:: Special features in GNU Emacs.
+ ...
+
+ Indices, nodes containing large menus
+
+ * Command Index:: An item for each @-command.
+ * Concept Index:: An item for each concept.
+
+ A detailed node listing
+
+ Overview
+ * Info File:: Characteristics of the Info file.
+ * Printed Manual:: Characteristics of the printed manual.
+
+ Using Texinfo Mode
+ * Info on a Region:: Formatting a region for Info.
+ * Showing the Structure:: Showing the structure of a file.
+ ...
+ ...
+
+
+
+File: texinfo, Node: License and Distribution, Prev: Top Node, Up: Beginning a File
+
+Licensing and Distribution Information
+======================================
+
+If the Texinfo file has a section containing the "General Public
+License" and the distribution information and a warranty disclaimer,
+this section usually follows the `Top' node. The licensing and
+distribution information and the disclaimer are followed by a preface
+or else by the first chapter of the manual.
+
+The licensing agreement is very important to Project GNU
+documentation and software. Without it, you may find that you can no
+longer get the software or its documentation. This sounds
+paradoxical, but the state of the world is such that documentation
+and software that does not have a "restrictive" license to make them
+freely distributable may be lost to the public. This has happened.
+
+For a good example of the text that could be used for the
+Distribution, General Public License and NO WARRANTY sections of your
+document, see the latest version of the ``GNU Emacs Manual''.
+
+Although a preface is not a required part of a Texinfo file, it is
+very helpful. Ideally, it should state clearly and concisely what
+the file is about and who would be interested in reading it. In
+general, the preface would follow the licensing and distribution
+information, although sometimes people put it earlier in the
+document. Usually, a preface is put in an `@unnumbered' section.
+(*Note Unnumbered and Appendix::.)
+
+
+
+File: texinfo, Node: Ending a File, Next: Structuring, Prev: Beginning a File, Up: Top
+
+Ending a Texinfo File
+*********************
+
+The end of a Texinfo file should include the indices, the commands to
+generate detailed and summary tables of contents and the @-command
+that tells TeX that it has reached the end of the file.
+
+For example, a Texinfo file might be ended as follows:
+
+ @node Concept Index, , Previous Node, Top
+ @comment node-name, next, previous, up
+ @unnumbered Concept Index
+
+ @printindex cp
+
+ @contents
+ @bye
+
+The `@bye' command should be on a line by itself and every Texinfo
+file must end with such a line. This command terminates TeX
+processing and forces out unfinished pages.
+
+* Menu:
+
+* Contents:: Generating a table of contents
+* Indices:: Generating, sorting and printing indices
+
+
+
+File: texinfo, Node: Contents, Next: Indices, Up: Ending a File
+
+Generating a Table of Contents
+==============================
+
+The commands `@chapter', `@section', etc., supply the information to
+make up a table of contents, but they do not cause an actual table to
+be generated. To do this, you must use the commands `@contents' and
+`@summarycontents'.
+
+`@contents'
+ The table of contents command outputs (into a printed manual) a
+ complete table of contents, based on the `@chapter',
+ `@unnumbered' and other sectioning commands. This command
+ should be used on a line by itself.
+
+`@summarycontents'
+ The summary contents command generates a summary table of
+ contents that lists only the chapters (and appendices and
+ unnumbered chapters); sections, subsections and subsubsections
+ are omitted. This command should be used on a line by itself.
+ Only large manuals need a summary table of contents.
+
+You can use either one of these commands, or both. Each command
+automatically generates a chapter-like heading at the top of the page.
+Tables of contents should be generated at the very end of the manual,
+just before the `@bye' command; the tables of contents commands
+should follow any indices that are output, so that the indices will
+appear in the contents.
+
+ INDICES...
+ @summarycontents
+ @contents
+ @bye
+
+The commands `@contents' and `@summarycontents' are ignored when an
+Info file is being generated.
+
+
diff --git a/info/texinfo-2 b/info/texinfo-2
new file mode 100644
index 00000000000..865e03dc371
--- /dev/null
+++ b/info/texinfo-2
@@ -0,0 +1,1405 @@
+Info file ../info/texinfo, produced by Makeinfo, -*- Text -*- from
+input file texinfo.texinfo.
+
+This file documents Texinfo, a documentation system that uses a
+single source file to produce both on-line help and a printed manual.
+
+This is edition 1.1 of the Texinfo documentation, and is for the
+Texinfo that is distributed as part of Version 18 of GNU Emacs.
+
+Copyright (C) 1988 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of
+this manual under the conditions for verbatim copying, provided that
+the entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be stated in a
+translation approved by the Foundation.
+
+
+
+File: texinfo, Node: Indices, Prev: Contents, Up: Ending a File
+
+Creating Indices
+================
+
+Using Texinfo, you can generate printed indices and Info file menus
+without having to sort and collate entries manually. Texinfo will do
+this for you automatically. Each index covers a certain kind of
+entry (functions, or variables, or concepts, etc.) and lists all of
+those entries in alphabetical order, together with information on how
+to find the discussion of each entry. In a printed manual, this
+information consists of page numbers. In an Info file, it consists
+of a menu item leading to the first node referenced.
+
+When you are making index entries, it is good practice to think of
+the different categories under which people may look for something.
+Different people *do not* think of the same words when they look
+something up. They think of different words. A helpful index will
+have items indexed under all the different words that people may use.
+For example, someone might think it obvious that the two letter names
+for indices should be listed under "Indices, two letter names", since
+the word "Index" is the general concept. But another reader may
+remember the specific concept of two letter names and search for the
+entry listed as "Two letter names for indices". A good index will
+have both entries and will help both kinds of user.
+
+Like typesetting, the construction of an index is a highly skilled,
+professional art, the subtleties of which are not appreciated until
+you have to do it yourself.
+
+Normally, six indices are provided for:
+
+ * A "program index" listing names of programs and leading to the
+ places where those programs are documented.
+
+ * A "function index" listing functions (such as, entry points of
+ libraries).
+
+ * A "variables index" listing variables (such as, external
+ variables of libraries).
+
+ * A "data type index" listing data types (such as, structures
+ defined in header files).
+
+ * A "keystroke index" listing keyboard commands.
+
+ * A "concept index" listing concepts that are discussed.
+
+Not every manual needs all of these. This manual has two indices: a
+concept index and an @-command index (that uses the function index
+but is called a command index in the chapter heading). Two or more
+indices can be combined into one using the `@synindex' command.
+*Note Combining Indices::.
+
+* Menu:
+
+* Index Entries:: Defining the entries of an index
+* Combining Indices::
+* Printing Indices & Menus::
+
+
+
+File: texinfo, Node: Index Entries, Next: Combining Indices, Up: Indices
+
+Defining the Entries of an Index
+--------------------------------
+
+The data to make an index comes from many individual commands
+scattered throughout the Texinfo source file. Each command says to
+add one entry to a particular index; after processing, it will give
+the current page number or node name as the reference.
+
+`@cindex CONCEPT'
+ Make an entry in the concept index for CONCEPT, referring to the
+ current page or node.
+
+`@findex FUNCTION'
+ Make an entry in the function index for FUNCTION, referring to
+ the current page or node.
+
+`@vindex VARIABLE'
+ Make an entry in the variable index for VARIABLE, referring to
+ the current page or node.
+
+`@pindex PROGRAM'
+ Make an entry in the program index for PROGRAM, referring to the
+ current page or node.
+
+`@kindex KEY'
+ Make an entry in the key index for KEY, referring to the current
+ page or node.
+
+`@tindex DATA TYPE'
+ Make an entry in the data type index for DATA TYPE, referring to
+ the current page or node.
+
+If the same name is indexed on several pages, all the pages are
+listed in the printed manual's index. However, *only* the *first*
+node referenced will appear in the index of an Info file. This means
+that it is best to write indices in which each entry will refer to
+only one place in the Texinfo file. Fortunately, this constraint is
+a feature rather than loss since it means that the index will be easy
+to use. Otherwise, it can be easy to create an index which has many
+pages listed for an entry and you don't know which one you need.
+
+You are not actually required to use indices for their canonical
+purposes. For example, you might wish to index some C preprocessor
+macros. You could put them in the function index along with actual
+functions, just by writing `@findex' commands for them; then, when
+you print the "function index", you could give it the title `Function
+and Macro Index' and all will be consistent for the reader. Or you
+could put the macros in with the data types by writing `@tindex'
+commands for them, and give that index a suitable title so the reader
+will understand.
+
+
+
+File: texinfo, Node: Combining Indices, Next: Printing Indices & Menus, Prev: Index Entries, Up: Indices
+
+Combining Indices
+-----------------
+
+Sometimes you will want to combine two disparate indices such as
+functions and variables, perhaps because you have few enough of one
+of them that a separate index for them would look silly.
+
+You could put variables into the function index by writing `@findex'
+commands for them instead of `@vindex' commands, and produce a
+consistent manual by printing the function index with the title
+`Function and Variable Index' and not printing the `Variable Index'
+at all; but this is not a robust procedure. It works only as long as
+your document is never included in part of or together with another
+document that is designed to have a separate variable index; if you
+did that, the variables from your document and those from the other
+would not end up together.
+
+What you should do instead when you want functions and variables in
+one index is to index the variables with `@vindex' as they should be,
+but use the `@synindex' command to redirect these `@vindex' commands
+to the function index. `@synindex' takes two arguments: the name of
+an index to redirect, and the name of an index to redirect it to.
+For this purpose, the indices are given two-letter names:
+
+`cp'
+ the concept index
+
+`vr'
+ the variable index
+
+`fn'
+ the function index
+
+`ky'
+ the key index
+
+`pg'
+ the program index
+
+`tp'
+ the data type index
+
+Thus, `@synindex vr fn' at the front of a Texinfo file will cause all
+entries designated for the variable index to go to the function index
+instead.
+
+
+
+File: texinfo, Node: Printing Indices & Menus, Prev: Combining Indices, Up: Indices
+
+Printing an Index and Generating Menus
+--------------------------------------
+
+To print an index means to include it as part of a manual or Info file.
+This does not happen automatically just because you use `@cindex' or
+other index-entry generating commands in the Texinfo file; those just
+cause the raw data for the index to be accumulated. To print an
+index, you must include the `@printindex' command at the place in the
+document where you want the index to appear. Also, for the case of
+the printed manual, you must run a program called `texindex' to sort
+the raw data to produce a sorted index file, which is what will
+actually be used to print the index.
+
+The Texinfo command that is used to print indices is `@printindex'.
+It takes the two-letter index name (*note Combining Indices::.) as an
+argument without braces, and reads the corresponding sorted index
+file and formats it appropriately into an index.
+
+The two-letter index names are:
+
+`cp'
+ the concept index.
+
+`vr'
+ the variable index.
+
+`fn'
+ the function index.
+
+`ky'
+ the key index.
+
+`pg'
+ the program index.
+
+`tp'
+ the data type index.
+
+`@printindex' does not generate a chapter heading for the index.
+Consequently, you should precede the command with a suitable section
+or chapter command (usually `@unnumbered') to supply the chapter
+heading and put the index into the table of contents. And before
+that, you will probably put a `@node' command. For example,
+
+ @node Variables Index, Concept Index, Function Index, Top
+ @comment node-name, next, previous, up
+ @unnumbered Variable Index
+
+ @printindex vr
+
+ @node Concept Index, , Variables Index, Top
+ @comment node-name, next, previous, up
+ @unnumbered Concept Index
+
+ @printindex cp
+
+ @summarycontents
+ @contents
+ @bye
+
+In TeX, `@printindex' needs a sorted index file to work from. TeX
+does not know how to do sorting; this is one of the main deficiencies
+of TeX. You must invoke the program `texindex' to do so, giving it
+the names of the raw index files to be sorted as arguments. You do
+not have to run `texindex' on all of them; only the ones you are
+going to print. (*Note Printing Hardcopy::, for more information.)
+
+
+
+File: texinfo, Node: Structuring, Next: Quotations and Examples, Prev: Ending a File, Up: Top
+
+Node and Chapter Structuring
+****************************
+
+The chapter structuring commands divide a document into a hierarchy
+of chapters, sections, subsections and subsubsections. These
+commands generate large headings.
+
+In a printed manual, the table of contents is based on the
+information specified by the chapter structuring commands.
+
+Although the chapter structuring commands used for creating a printed
+document are entirely different from the node commands for
+structuring an Info file, you are likely to use the two kinds of
+command together since the single Texinfo file is usually designed to
+be read both as an Info file and as a printed manual. The only time
+you are likely to use the chapter structuring commands without using
+the node structuring commands is if you are writing a document that
+will never be put into Info format, for example, a novel, a letter,
+an article or a memorandum.
+
+It is unlikely that you will ever write a Texinfo file that is only
+intended as an on-line Info file and not as a printable document.
+However, Texinfo is flexible enough so that you can do this if you
+wish.
+
+Although a Texinfo file can be structured in a variety of ways, it is
+usually structured like a book with chapters, sections, subsections
+and the like. This structure can also be visualized as a tree (or
+rather as an upside down tree) with the root at the top and each
+level corresponding to chapters or sections or whatnot. In Info
+format, you reach the nodes on each level by using the the `Next' and
+`Previous' pointers in the node line. For example, you go from one
+chapter to the next or previous chapter by using the the pointers to
+the next and previous chapters. In Info, you go the level above by
+using an `Up' pointer and you go to the level below through a `Menu'.
+In the printed manual, cross references are indicated by page and
+section numbers; in the on-line file, cross references are specified
+by inline menu items.
+
+Here is a diagram that shows a Texinfo file with three chapters;
+each chapter has two sections.
+
+ top
+ |
+ |
+ ---------------------------------------------
+ | | |
+ | | |
+ Chapter 1 Chapter 2 Chapter 3
+ | | |
+ | | |
+ ---------- ---------- ----------
+ | | | | | |
+ Sect. 1.1 Sect. 1.2 Sect. 2.1 Sect. 2.2 Sect. 3.1 Sect. 3.2
+
+
+In this structure, the node for Chapter 2 looks like this:
+
+ @node Chapter 2, Chapter 3, Chapter 1, top
+ @comment node-name, next, previous, up
+
+To get to Sections 2.1 and 2.2, you need a menu inside of Chapter 2
+that says:
+
+ @menu
+ * Sect. 2.1:: Description of this section.
+ * Sect. 2.2::
+ @end menu
+
+This menu is located inside Chapter 2, after the beginning of the
+chapter, just before Section 2.1.
+
+Note that a menu entry has three parts: the menu item name, the name
+of the node and, optionally, a description of the item (in that
+order). If the menu item name and the name of the node are the same,
+you can put two colons after the item name, as is shown in the
+example. (If the second part is different from the first, the first
+part is terminated by a colon and the second part terminated by a
+tab, newline, comma or period.) (*Note Menu::.)
+
+The node for Sect. 2.1 will look like this:
+
+ @node Sect. 2.1, Sect. 2.2, , Chapter 2
+ @comment node-name, next, previous, up
+
+This node does not have a `Previous' node.
+
+Usually, an `@node' command and a chapter structuring command are
+used in sequence, along with indexing commands. For example, the
+node for the chapter on ending a file looks like this:
+
+ @node Ending a File, Structuring, Beginning a File, Top
+ @comment node-name, next, previous, up
+ @chapter Ending a Texinfo File
+ @cindex Ending a Texinfo file
+ @cindex Texinfo file ending
+ @cindex File ending
+
+The chapter structuring commands fall into four groups that have the
+characteristics of chapters, sections, subsections and subsubsections.
+The groups are:
+
+`@chapter'
+`@unnumbered'
+`@appendix'
+ For chapters and chapter-like parts of a document.
+
+`@section'
+`@unnumberedsec'
+`@appendixsec'
+ For sections and section-like parts of a document.
+
+`@subsection'
+`@unnumberedsubsec'
+`@appendixsubsec'
+ For subsections and subsection-like parts of a document.
+
+`@subsubsection'
+`@unnumberedsubsubsec'
+`@appendixsubsubsec'
+ For subsubsections and subsubsection-like parts of a document.
+
+In the sections that follow, the chapter structuring commands are
+described first and then the `@node' and `@menu' commands.
+
+* Menu:
+
+* Chapter::
+* Unnumbered and Appendix::
+* Section::
+* Subsection::
+* Subsubsection::
+* Node::
+* Menu::
+
+
+
+File: texinfo, Node: Chapter, Next: Unnumbered and Appendix, Up: Structuring
+
+@chapter
+========
+
+`@chapter' identifies a chapter in the document. It is followed by a
+single argument which is the rest of the line, as in
+
+ @chapter Node and Chapter Structuring
+
+In TeX, it creates a chapter in the document, specifying the chapter
+title.
+
+In the Info file, `@chapter' causes its argument to appear on a line
+by itself, with a line of asterisks inserted underneath. Thus, the
+above example produces the following output:
+
+ Node and Chapter Structuring
+ ****************************
+
+
+
+File: texinfo, Node: Unnumbered and Appendix, Next: Section, Prev: Chapter, Up: Structuring
+
+@unnumbered, @appendix
+======================
+
+These commands are equivalent to `@chapter' for Info file output.
+(*Note Chapter::.) In a printed manual, they generate chapters that
+are numbered differently in the table of contents. `@unnumbered'
+chapters appear without chapter numbers of any kind, and `@appendix'
+chapters are given a letter instead of a number.
+
+
+
+File: texinfo, Node: Section, Next: Subsection, Prev: Unnumbered and Appendix, Up: Structuring
+
+@section
+========
+
+`@section' is like `@chapter' except that in TeX it makes a section
+rather than a chapter. (*Note Chapter::.) Sections go within
+chapters. In the Info file, `@chapter' and `@section' differ only in
+that `@section' underlines with `='. For example,
+
+ This is a section
+ =================
+
+@unnumberedsec, @appendixsec
+============================
+
+Use these constructs for sections within chapters made by
+`@unnumbered' or `@appendix'. (*Note Section::.)
+
+
+
+File: texinfo, Node: Subsection, Next: Subsubsection, Prev: Section, Up: Structuring
+
+@subsection
+===========
+
+Subsections are to sections as sections are to chapters. (*Note
+Section::.) They are underlined with `-'. For example,
+
+ This is a subsection
+ --------------------
+
+@unnumberedsubsec, @appendixsubsec
+==================================
+
+Use these constructs for subsections within sections within chapters
+made by `@unnumberedsec' or `@appendixsec'. (*Note Subsection::.)
+
+
+
+File: texinfo, Node: Subsubsection, Next: Node, Prev: Subsection, Up: Structuring
+
+@subsubsection And Other Subsection Commands
+============================================
+
+Subsubsections are to subsections as subsections are to sections.
+(*Note Subsection::.) They are underlined with periods. The
+equivalent commands for `@unnumberedsubsec' and `@appendixsubsec' are
+`@unnumberedsubsubsec' and `@appendixsubsubsec'. For example,
+
+ This is a subsubsection
+ .......................
+
+
+
+File: texinfo, Node: Node, Next: Menu, Prev: Subsubsection, Up: Structuring
+
+@node
+=====
+
+`@node' defines the beginning of a new node in the Info output file
+(*note info: (info)Top.). It is followed by four arguments,
+separated by commas, that make up the rest of the line. Since it is
+often hard to remember the order in which are arguments are listed,
+`texinfo-mode' provides the `C-c C-c n' command
+(`texinfo-insert-@node') which automatically inserts a comment line
+listing the arguments. For example,
+
+ @node Texinfo Mode, Beginning a File, Overview, Top
+ @comment node-name, next, previous, up
+
+defines a node named `Texinfo Mode', whose `Next' pointer is to node
+`Beginning a File', whose `Previous' pointer is to node `Overview',
+and whose `Up' pointer is to node `Top'. What this means is that
+Texinfo changes `@node ARGS' into the special text string necessary
+to separate Info nodes and to identify the node that is starting and
+say what nodes it points to.
+
+The pointer names should be the names of nodes defined elsewhere.
+For this example, nodes named `Beginning a File', `Overview' and
+`Top' should be defined elsewhere in the file with other `@node'
+commands. It does not matter whether they are before or after the
+node that refers to them.
+
+Normally, a node's `Up' pointer should point at the node whose menu
+mentions that node. The node's `Next' pointer should point at the
+node that follows that node and its `Previous' pointer should point
+at the node that precedes it in that menu.
+
+In TeX, `@node' is nearly ignored. It generates no text. Its only
+function is to identify the name to use for cross-references to the
+chapter or section which follows the `@node' command and which which
+makes up the body of the node. (Cross references are made with
+`@xref'. *Note Cross References::.)
+
+`@node' should be followed immediately by a chapter-structuring
+command such as `@chapter', `@section', `@subsection' or
+`@subsubsection'.
+
+The easiest way to write a node is to use the Texinfo mode keyboard
+command `C-c C-c n' to insert `@node' and a comment line listing the
+names of each of the pointers in their proper order. This way you
+won't lose track of which arguments are for which pointers. The
+template is especially useful if you are not familiar with Texinfo.
+It is important to pick a suitable node name. Generally, these begin
+with an uppercase letter as if the node name were a heading for a
+chapter or section. Do not use any of the Texinfo @-commands in the
+name; these commands confuse Info. The node name should be
+informative. Unfortunately, long names will not fit onto the line,
+which can be awkward. Sometimes it is better to use long but
+informative names rather than short ones.
+
+Some people insert the names of the `Next', `Previous' and `Up'
+pointers at the same time they insert the node's own name. This is
+because it is easier to keep track of the node structure as you
+create a document than it is to sort it out after you have dozens of
+nodes. Others wait to insert the `Next', `Previous' and `Up'
+pointers until they have a nearly final version of the document.
+This is because they expect to change the organization of the
+document while they write it and insert or delete sections and move
+them around. The command `texinfo-show-structure' can be used to
+find the `Next', `Previous' and `Up' pointers of a node. (See *Note
+Using texinfo-show-structure::.)
+
+However you do it, it is best to name the node whenever you write the
+section so you can easily make cross references to the section. A
+large number of cross references are an especially important feature
+of a good Info file.
+
+After you have inserted the node-line, you should immediately write
+an @-command for the chapter or section and insert its name. Next,
+(and this is important!), put in several index entries. Usually, you
+will find at least two and often as many as four or five ways of
+referring to the node in the index. Use them all. This will make it
+much easier for people to find the node.
+
+The top node of the file, named `Top', should have as its parent the
+name of a node in another file, where there is a menu that leads to
+this file. Specify the file name in parentheses. If the file is to
+be installed directly in the Info directory file, use `(dir)' as the
+parent of the top node; this is short for `(dir)top', the node `top'
+in the file `dir', which is the main menu of Info. For example,
+
+ @node Top, Overview, (dir), (dir)
+ @comment node-name, next, previous, up
+
+For more information about installing an Info file in the `info'
+directory, *note Installing an Info File::.
+
+
+
+File: texinfo, Node: Menu, Prev: Node, Up: Structuring
+
+@menu
+=====
+
+Info file nodes can contain "menus" which point to other nodes. You
+must type the menus in by hand, and surround them with lines
+containing `@menu' and `@end menu'. In Info, the `@menu' line
+changes into `* Menu:', which indicates the beginning of a menu to
+the Info program. Otherwise, the contents are unchanged by Texinfo,
+except for the processing of any other @-commands within. The entire
+menu construct has no effect in the printed manual and will not
+appear there.
+
+By convention, a menu is put at the end of a node. This way, it is
+easy for someone using Info to find the menu, using the `M->'
+(`end-of-buffer') command.
+
+In a menu, every line that begins with a `*' lists a single topic. A
+line that does not start with a `*' will also appear in the menu and
+can be used as a comment.
+
+A menu item has three parts:
+
+ 1. The menu item name.
+
+ 2. The name of the node.
+
+ 3. A description of the item.
+
+Only the first part is required. This part is the name of the
+topic--the name of the menu item that the user must give to the `m'
+command to select this topic when using Info. The first part comes
+right after the asterisk and a space, and is followed by a colon,
+spaces and tabs, and then the name of the node which discusses that
+topic. The name of the node is terminated by a tab, comma, newline
+or period. If the node name and topic name are the same, rather than
+give the name twice, put two colons after the name instead. For
+example, `* Name::'. (You should do this whenever possible, since it
+reduces visual clutter in the menu).
+
+If the second part is present, it may be terminated with a tab,
+comma, or newline; or with a period.
+
+For example,
+
+ @menu
+ A Section on Foo and Switches
+ * Foo:: The node named Foo tells you how to go fooing.
+ * Sw: Switches. Type @code{m Sw} to see node @code{Switches}
+ which describes the switches available here.
+ @end menu
+
+produces
+
+ * menu:
+
+ A Section on Foo and Switches
+ * Foo:: The node named foo tells you how to go fooing.
+ * Sw: Switches. Type `m Sw' to see node `Switches'
+ which describes the switches available here.
+
+ In this example, the menu has two items. `Foo' is both a menu item
+name and the name of the node referred to by that item. `Sw' is the
+other menu item name, and it refers to the node named `Switches'.
+Since no file name is specified with `Foo' or `Switches', they must
+be the names of other nodes in the same Info file.
+
+Nodes in other Info files can be referred to by putting the file name
+in parentheses at the beginning of the node name. For example,
+
+ @menu
+ * Outlining: (emacs) Outline Mode. The major mode for editing outlines.
+ * Rebinding: (emacs) Rebinding. How to redefine the meaning of a key.
+ @end menu
+
+When this is done, the item has to have at least two parts: the first
+part is the menu item name and the second part is the name of the node.
+
+
+
+File: texinfo, Node: Quotations and Examples, Next: Lists and Tables, Prev: Structuring, Up: Top
+
+Making Quotations and Examples
+******************************
+
+Quotations and examples are blocks of text, consisting of one or more
+whole paragraphs that are set off from the bulk of the text and
+treated differently. They are usually indented.
+
+In Texinfo, an insertion is always begun by writing an @-command on a
+line by itself, and ended by writing an `@end' command that is also
+on a line by itself. For instance, an "example" is a kind of
+insertion that is begun with `@example' and ended with `@end example'.
+
+There are three commands for quotations and examples:
+
+`@quotation'
+ Used to indicated text that is quoted.
+
+`@example'
+ Used to illustrate code, commands and the like in a fixed width
+ font without filling.
+
+`@display'
+ Used for illustrative text.
+
+* Menu:
+
+* Quotation::
+* Example::
+* Display::
+
+
+
+File: texinfo, Node: Quotation, Next: Example, Up: Quotations and Examples
+
+@quotation
+==========
+
+`@quotation' is used to indicate text that is excerpted from another
+(real or hypothetical) printed work. The inside of a quotation is
+processed normally except that
+
+ 1. The margins are narrower.
+
+ 2. Paragraphs are not indented.
+
+ 3. Interline spacing and interparagraph spacing are reduced.
+
+Thus, the input
+
+ @quotation
+ This is
+ a foo.
+ @end quotation
+
+produces in the printed manual
+
+ This is a foo.
+
+and in the Info file
+
+ This is
+ a foo.
+
+
+
+File: texinfo, Node: Example, Next: Display, Prev: Quotation, Up: Quotations and Examples
+
+@example
+========
+
+`@example' is used to indicate an example that is not part of the
+running text. In the printed manual, this is done by switching to a
+fixed width font, turning off filling, and making extra spaces and
+blank lines significant. In the Info file, an analogous result is
+obtained by indenting each line with five extra spaces.
+
+`@example' should appear on a line by itself; this line will
+disappear from the output. Mark the end of the example with a line
+containing `@end example', which will likewise disappear. For example:
+
+ @example
+ mv foo bar
+ @end example
+
+produces
+
+ mv foo bar
+
+Since the lines containing `@example' and `@end example' will
+disappear, you will want to put a blank line before the `@example'
+and another blank line after the `@end example'. (Remember that
+blank lines between the beginning `@example' and the ending `@end
+example' will appear in the output.)
+
+Don't use tabs in lines of an example! TeX has trouble with tabs:
+it treats them like single spaces, and that is not what they look like.
+
+
+
+File: texinfo, Node: Display, Prev: Example, Up: Quotations and Examples
+
+@display
+========
+
+`@display' is just like `@example' except that, in the printed
+manual, `@display' does not select the fixed-width font. In fact, it
+does not specify the font at all, so that the text appears in the
+same font it would have appeared in without the `@display'.
+
+
+
+File: texinfo, Node: Lists and Tables, Next: Cross References, Prev: Quotations and Examples, Up: Top
+
+Making Lists and Tables
+***********************
+
+Texinfo has several ways of making lists and two-column tables.
+Lists can be bulleted or numbered while two-column tables can
+highlight the items in the first column.
+
+For example, this is an enumerated list:
+
+ 1. This is a numbered item.
+
+ 2. This is the second item in this list.
+
+ 3. This is the third item on this list.
+
+Texinfo will automatically indent the text in lists or tables and
+number an enumerated list. This last feature is useful if you are
+reordering the list, since you do not have to renumber it yourself.
+
+Lists or tables are always begun by an @-command on a line by itself
+and ended with an `@end' command on a line by itself. For example,
+an enumerated list begins with the command `@enumerate' and ends with
+the command `@end enumerate'; and an itemized list begins with the
+command `@itemize' and ends with the command `@end itemize'.
+
+The elements of a list are begun with the `@item' command.
+
+Here is an itemized list of the different kinds of table and lists:
+
+ * Itemized lists with or without bullets.
+
+ * Numbered lists.
+
+ * two-column tables with highlighting.
+
+* Menu:
+
+* Itemize::
+* Enumerate::
+* Table::
+
+
+
+File: texinfo, Node: Itemize, Next: Enumerate, Up: Lists and Tables
+
+@itemize
+========
+
+`@itemize' is used to produce sequences of indented paragraphs, with
+a mark inside the left margin at the beginning of each paragraph.
+The rest of the line that starts with `@itemize' should contain the
+character or Texinfo commands to generate such a mark. Usually, it
+is the @-command `@bullet'. Whatever mark you choose, ultimately, it
+should result in a single character in the Texinfo file, or the
+indentation will come out wrong. When you write the command, omit
+the `{}' after the command if you use just one command and nothing
+else.
+
+The text of the indented paragraphs themselves come after the
+`@itemize', up to another line that says `@end itemize'.
+
+Before each paragraph for which a mark in the margin is desired,
+place a line that says just `@item'. Don't put any other text on
+this line.
+
+Info indents the lines in an itemized list by five columns, but it
+does not fill them. This can produce lines in the Info file that are
+too wide. You can either write shorter lines in the Texinfo file by
+setting the fill column to five columns less than it is normally, or
+else you can tell Info to refill the paragraphs by adding the
+@-command `@refill' to the end of the paragraph. (*Note Refill::, for
+more information about the use of the `@refill' command.)
+
+Usually, you should put a blank line before an `@item'. This puts a
+blank like in the Info file. Except when the entries are very brief,
+a blank line looks better.
+
+Here is an example of the use of `@itemize', followed by the output
+it produces. Note that `@bullet' produces a `*' in Texinfo and a
+round dot in TeX.
+
+ @itemize @bullet
+ @item
+ Some text for foo.
+
+ @item
+ Some text
+ for bar.
+ @end itemize
+
+produces
+
+ * Some text for foo.
+
+ * Some text for bar.
+
+
+
+File: texinfo, Node: Enumerate, Next: Table, Prev: Itemize, Up: Lists and Tables
+
+@enumerate
+==========
+
+`@enumerate' is like `@itemize' except that the marks in the left
+margin contain successive integers starting with 1. (*Note
+Itemize::.) Do not put any argument on the same line as `@enumerate'.
+
+ @enumerate
+ @item
+ Some text for foo.
+ @item
+ Some text
+ for bar.
+ @end enumerate
+
+produces
+
+ 1. Some text for foo.
+
+ 2. Some text for bar.
+
+If you want, you can put a blank line between the entries in the list.
+This often makes it easier to read the Info file. For example,
+
+ @enumerate
+ @item
+ This is the first item.
+
+ @item
+ This is the second item.
+ @end enumerate
+
+Info indents the lines of the enumerated list by five columns, but it
+does not fill them. As a result, the lines in the Info file may be
+too wide. To prevent this, you can either write shorter lines in the
+Texinfo file file by setting the fill column to five columns less
+than it is normally, or else you can tell Info to refill the
+paragraphs by adding the @-command `@refill' to the end of the
+paragraph. (*Note Refill::, for more information about the use of
+the `@refill' command.)
+
+
+
+File: texinfo, Node: Table, Prev: Enumerate, Up: Lists and Tables
+
+@table
+======
+
+`@table' is similar to `@itemize', but allows you to specify a name
+or heading line for each item. (*Note Itemize::.) The command is
+used to produce two-column tables, and is especially useful for
+glossaries and explanatory exhibits.
+
+You must follow each use of `@item' inside of `@table' with text to
+serve as the heading line for that item. This text is put on the
+same line as the `@item' command. Each heading line is put into the
+first column of the table and the supporting text, which you put on
+the line following the line beginning with `@item', goes into the
+second column.
+
+Also, `@table' itself must be followed by an argument that is a
+Texinfo command such as `@code', `@var', `@kbd' or `@asis'. Although
+these commands are usually followed by arguments in braces, in this
+case you use the command name without an argument. (`@item' supplies
+the argument.) This command will be applied to the text that goes
+into the first column of each item and determines how it will be
+highlighted. For example, `@samp' will cause the text in the first
+column to be highlighted as if it were acted on by an `@samp' command.
+
+`@asis' is a command that does nothing; in that case, each item will
+come out without highlighting, unless that particular piece of text
+contains @-commands for highlighting.
+
+(Various other command names might work with `@table'. However, only
+commands that normally take arguments in braces may be used.)
+
+Usually, you should put a blank line before an `@item'. This puts a
+blank like in the Info file. Except when the entries are very brief,
+a blank line looks better.
+
+The following table, for example, highlights the text in the first
+column as if each item were acted on by an `@samp' command:
+
+ @table @samp
+ @item foo
+ This is the text for
+ @samp{foo}.
+
+ @item bar
+ Text for @samp{bar}.
+ @end table
+
+produces
+
+ `foo'
+ This is the text for `foo'.
+
+ `bar'
+ Text for `bar'.
+
+Info indents the lines of text in the second column, but does not
+fill them. As a result, the lines in the Info file may be too wide.
+To prevent this, cause Info to refill the paragraphs after processing
+by adding the @-command `@refill' to the end of the paragraph. (*Note
+Refill::, for more information about the use of the `@refill' command.)
+
+If you want to list two or more named items with a single block of
+text, use the `@itemx' command.
+
+* Menu:
+
+* Itemx::
+
+
+
+File: texinfo, Node: Itemx, Prev: Table, Up: Table
+
+@itemx
+------
+
+`@itemx' is used inside a `@table' when you have two or more named
+items for the same block of text. Use `@itemx' for all but the first
+of the items. It works exactly like `@item' except that it does not
+generate extra vertical space above the item text. For example,
+
+ @table @code
+ @item upcase
+ @itemx downcase
+ These two functions accept a character or a string as argument,
+ and return the corresponding upper case (lower case) character
+ or string. @refill
+ @end table
+
+produces
+
+ `upcase'
+ `downcase'
+ These two functions accept a character or a string as
+ argument, and return the corresponding upper case (lower
+ case) character or string.
+
+A more complicated example of the use of `@itemx' comes from the
+chapter on structuring commands. Here is how the list showing how
+the chapter structuring commands fall into four groups was constructed.
+(*Note Chapter Structuring Commands: Structuring.)
+
+ @table @code
+ @item @@chapter
+ @itemx @@unnumbered
+ @itemx @@appendix
+ For chapters and chapter-like parts of a document.
+
+ @item @@section
+ @itemx @@unnumberedsec
+ @itemx @@appendixsec
+ For sections and section-like parts of a document.
+
+ @item @@subsection
+ @itemx @@unnumberedsubsec
+ @itemx @@appendixsubsec
+ For subsections and subsection-like parts of a document.
+
+ @item @@subsubsection
+ @itemx @@unnumberedsubsubsec
+ @itemx @@appendixsubsubsec
+ For subsubsections and similar parts of a document.
+ @end table
+
+and this is what the resulting table looks like:
+
+`@chapter'
+`@unnumbered'
+`@appendix'
+ For chapters and chapter-like parts of a document.
+
+`@section'
+`@unnumberedsec'
+`@appendixsec'
+ For sections and section-like parts of a document.
+
+`@subsection'
+`@unnumberedsubsec'
+`@appendixsubsec'
+ For subsections and subsection-like parts of a document.
+
+`@subsubsection'
+`@unnumberedsubsubsec'
+`@appendixsubsubsec'
+ For subsubsections and similar parts of a document.
+
+Also, either column of a table can be empty.
+
+
+
+File: texinfo, Node: Cross References, Next: Formatting Paragraphs, Prev: Lists and Tables, Up: Top
+
+Making Cross References
+***********************
+
+Cross references are used to refer the reader to other parts of the
+same or different Texinfo files. In Texinfo, "nodes" are the points
+to which cross-references can refer.
+
+In general, a document should be designed so that it can be read
+sequentially. People soon tire of flipping back and forth to find
+information that should be presented to them as they need it.
+However, there will be information (often too detailed for whatever
+the current context may be) that is related to whatever is presented
+and to which reference should be made. More important, in an on-line
+help system or in a reference manual, readers do *not* read
+everything in sequence from beginning to end. Instead, they look up
+what they need. For this reason, such creations should contain many
+cross references to help the reader find other information that he or
+she may not have read.
+
+Although nodes are not a fundamental concept in a printed manual,
+they still serve to define a cross-reference point and the variants
+of `@xref' still serve to make references. Thus, if you are writing
+a manual that will only be printed, and will not be used on-line, you
+continue to use the `@node' command for when you make cross references.
+
+There are several kinds of cross reference command.
+
+`@xref'
+ Used to start a sentence in the printed manual saying, `See ...'
+ or an entry in the Info file saying `*note ...'.
+
+`@pxref'
+ Used to make a reference that starts with a lowercase `see'
+ and is usually contained within parentheses.
+
+`@inforef'
+ Used to make a reference to an Info file for which there is no
+ printed manual.
+
+* Menu:
+
+* Xref::
+* Pxref::
+* Inforef::
+
+
+
+File: texinfo, Node: Xref, Next: Pxref, Prev: Cross References, Up: Cross References
+
+@xref
+=====
+
+`@xref' generates a cross-reference. In Texinfo, it turns into an
+Info cross-reference which the Info `f' command can use to go
+directly to another node. In TeX, it turns into a sentence of the form
+
+ See section SECTION [TOPIC], page PAGE
+
+but does not generate a period to end it.
+
+`@xref' must refer to an Info node created by `@node', by the node's
+name.
+
+`@xref' is followed by an argument inside braces; but actually the
+text inside the braces is treated as several arguments, separated by
+commas. Whitespace after these commas is ignored. A period or comma
+*must* follow the closing brace of an `@xref'. It is required to
+terminate the cross reference. This period or comma will appear in
+the output, both in the Info file and in the printed manual.
+
+The simplest form of `@xref' takes one argument, the name of another
+node in the same Info file. Here we show the input text, followed by
+a blank line and then the output text for Info files and the output
+text for printed manuals.
+
+ @xref{node-name}, for more info.
+
+ *note node-name::, for more info.
+
+ See section NNN [node-name], page PPP, for more info.
+
+With two arguments, the second one is used as the name of the Info
+cross-reference, while the first argument is still the node that the
+cross-reference points to:
+
+ @xref{node-name, name-for-note}, for more info.
+
+ *note name-for-note: node-name, for more info.
+
+ See section NNN [node-name], page PPP, for more info.
+
+A third argument replaces the node name when it actually appears in
+the TeX output. It should state the topic discussed by the section
+being referenced. Often, you will want to use initial uppercase
+letters so it will be easier to read when the reference is printed.
+Use a third argument when the node name is unsuitable because of
+syntax, grammar or diction.
+
+ @xref{node-name, name-for-note, Topic Description}, for more info.
+
+ *note name-for-note: node-name, for more info.
+
+ See section NNN [Topic Description], page PPP, for more info.
+
+If a third argument is given and the second one is empty, then the
+third argument serves both purposes:
+
+ @xref{node-name, , Topic Description}, for more info.
+
+ *note Topic Description: node-name, for more info.
+
+ See section NNN [Topic Description], page PPP, for more info.
+
+A fourth argument specifies the name of the Info file in which the
+referenced node is located, assuming it is not the one in which the
+reference appears. `@xref' with only four arguments is used when the
+reference is not within one Info file, but is within a single printed
+manual--when multiple Texinfo files are incorporated into the same
+TeX run but make separate Info files. (This is seldom the case and
+usually you will use five arguments if you are making a reference
+that is outside the current Info file.)
+
+ @xref{node-name, name-for-note, Topic, info-file-name},
+ for more info.
+
+ *note name-for-note: (info-file-name) node-name, for more info.
+
+ See section NNN [Topic], page PPP, for more info.
+
+A fifth argument is used when you are making a reference to another
+Info file which is also part of another printed manual. Write the
+title of the manual in this slot. Since a different manual is made
+during a different TeX run, the printed reference will not have a
+page number.
+
+Whenever you refer to another manual, use this version of `@xref'
+with five arguments.
+
+ @xref{node-name, name-for-note, Topic, info-file-name, A Printed Manual},
+ for more info.
+
+ *note name-for-note: (info-file-name) node-name, for more info.
+
+ See section Topic of A Printed Manual, for more info.
+
+The name of the printed manual will be typeset in italics.
+
+Often, you will leave out the second argument when you use the long
+version of `@xref'. In this case, the third argument, the topic
+description, will replace the node name:
+
+ @xref{node-name, , Topic Description, info-file-name, A Printed Manual},
+ for more info.
+
+ *note Topic Description: (info-file-name) node-name, for more info.
+
+ See section Topic Description of A Printed Manual, for more info.
+
+
+
+File: texinfo, Node: Pxref, Next: Inforef, Prev: Xref, Up: Cross References
+
+@pxref
+======
+
+`@pxref' is nearly the same as `@xref'; it differs in only two ways:
+
+ 1. The output starts with lower case `see' rather than `See'.
+
+ 2. A period is generated automatically in the Info file output to
+ end the Info cross-reference, but no period is generated for the
+ printed manual.
+
+The purpose of `@pxref' is to be used inside parentheses as part of
+another sentence. In the printed manual, no period is needed after
+the cross reference text itself (within the parentheses), but a
+period is needed after the cross reference text in the Info file
+because only thus can Info recognize the end of the cross-reference.
+`@pxref' spares you the need to use complicated methods to put a
+period into one form of the output and not the other.
+
+`@pxref' can be used with up to five arguments just like `@xref'.
+(*Note Xref::.)
+
+
+
+File: texinfo, Node: Inforef, Prev: Pxref, Up: Cross References
+
+@inforef
+========
+
+`@inforef' is used for cross-references to Info files for which there
+are no printed manuals. Even in a printed manual, `@inforef'
+generates a reference directing the user to look in an Info file.
+`@inforef' takes exactly three arguments. The syntax is
+`@inforef{NODE, NAME, FILE}'.
+
+ @inforef{node-name, name-for-note, info-file-name}, for more information.
+
+ *note name-for-note: (info-file-name) node-name, for more information.
+
+ See Info file `info-file-name', node `node-name', for more
+ information.
+
+
+
+File: texinfo, Node: Formatting Paragraphs, Next: Marking Text, Prev: Cross References, Up: Top
+
+Formatting Paragraphs
+*********************
+
+Usually, a Texinfo file will be processed both by TeX and by the `M-x
+texinfo-format-buffer' command. Consequently, you must make sure
+that text will come out looking right both in the printed manual and
+in the on-line help.
+
+For example, unless told otherwise, `M-x texinfo-format-buffer' will
+not refill a paragraph after processing it although TeX will. This
+means that a paragraph with numerous or large @-commands may not look
+properly filled after processing by Info. The @-commands are removed
+from the text but the lines are not refilled so some are much shorter
+than they were. To cause the `M-x texinfo-format-buffer' command to
+refill such a paragraph, put `@refill' at the end of the paragraph.
+
+TeX may also format a document improperly. For example, page breaks
+may occur in the "wrong place"; to control this, text can be held
+together by a group command that keeps the text within the group from
+being split across two pages.
+
+* Menu:
+
+* Refilling & Noindent:: Refilling paragraphs & preventing indentation
+* Breaks Blank-Lines Groups:: Line and paragraph breaks, blank lines, grouping
+
+
+
+File: texinfo, Node: Refilling & Noindent, Next: Breaks Blank-Lines Groups, Prev: Formatting Paragraphs, Up: Formatting Paragraphs
+
+Refilling Paragraphs and Preventing Indentation
+===============================================
+
+The `@refill' and `@noindent' commands are used just after or just
+before paragraphs which, after processing by either Info or TeX,
+might look bad. The `@refill' command refills a paragraph in the
+Info file after all the other processing has been done. In the
+printed manual, the `@noindent' command prevents a piece of text that
+is a continuation of the preceding paragraph from being indented as
+if it were a new paragraph.
+
+* Menu:
+
+* Refill:: Refilling an info paragraph after other processing.
+* Noindent:: Preventing paragraph indentation in continuation text.
+
+
+
+File: texinfo, Node: Refill, Next: Noindent, Prev: Refilling & Noindent, Up: Refilling & Noindent
+
+@refill
+-------
+
+If a paragraph contains sizable @-constructs, it may look badly
+filled after `texinfo-format-buffer' is through with it.
+
+Put `@refill' at the end of the paragraph to tell
+`texinfo-format-buffer' to refill the paragraph after finishing all
+other processing on it. `@refill' has no effect on TeX, which always
+fills everything that ought to be filled. For example,
+
+ To use @code{foo}, pass @samp{xx%$} and @var{flag} and type @kbd{x}
+ after running @code{make-foo}.@refill
+
+produces (in the Info file)
+
+ To use `foo', pass `xx%$' and FLAG and type `x' after running `make-foo'.
+
+ whereas without the `@refill' it would produce
+
+ To use `foo', pass `xx%$' and FLAG and type `x'
+ after running `make-foo'.
+
+ with the line broken at the same place as in the Texinfo input file.
+
+Do not put a space before `@refill'; otherwise the command might be
+put at the beginning of the line when you refill the paragraph in the
+Texinfo file with `M-q' (`fill-paragraph'). If this were to happen,
+the `@refill' command might fail to work
+
+
+
+File: texinfo, Node: Noindent, Prev: Refill, Up: Refilling & Noindent
+
+@noindent
+---------
+
+If you have text following an `@example' or other similar "special
+paragraph" that reads as a continuation of the text before the
+`@example', it is good to prevent this text from being indented as a
+new paragraph. To accomplish this, put `@noindent' on a line by
+itself before the start of the text that should not be indented. For
+example,
+
+ @example
+ This is an example
+ @end example
+
+ @noindent
+ This line will not be indented.
+
+ produces
+
+ This is an example
+
+This line will not be indented.
+
+To adjust the number of blank lines properly in the Info file output,
+remember that the line containing `@noindent' does not generate a
+blank line, and neither does the `@end example' line.
+
+In the Texinfo source file for this documentation, each of the lines
+that says `produces' is preceded by a line containing `@noindent'.
+
+
diff --git a/info/texinfo-3 b/info/texinfo-3
new file mode 100644
index 00000000000..8941531ca2b
--- /dev/null
+++ b/info/texinfo-3
@@ -0,0 +1,1410 @@
+Info file ../info/texinfo, produced by Makeinfo, -*- Text -*- from
+input file texinfo.texinfo.
+
+This file documents Texinfo, a documentation system that uses a
+single source file to produce both on-line help and a printed manual.
+
+This is edition 1.1 of the Texinfo documentation, and is for the
+Texinfo that is distributed as part of Version 18 of GNU Emacs.
+
+Copyright (C) 1988 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of
+this manual under the conditions for verbatim copying, provided that
+the entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be stated in a
+translation approved by the Foundation.
+
+
+
+File: texinfo, Node: Breaks Blank-Lines Groups, Prev: Refilling & Noindent, Up: Formatting Paragraphs
+
+Breaks, Blank Lines and Groups
+==============================
+
+Texinfo has several commands for making blank lines, for forcing
+paragraph and page breaks in the printed manual and for preventing
+text from running from one page to the next.
+
+`@*'
+ Force a line break in the printed manual. This command has no
+ effect on the Info file.
+
+`@sp'
+ Generate blank lines in both the printed manual and in the Info
+ file.
+
+`@br'
+ Force a paragraph break in the printed manual. This command has
+ no effect on the Info file.
+
+`@w'
+ Prevent text from being split across two lines in the printed
+ manual. This command has no effect on the Info file.
+
+`@page'
+ Start a new page in the printed manual. This command has no
+ effect on the Info file.
+
+`@group'
+ Hold text together that must appear on one printed page. This
+ command has no effect on the Info file.
+
+`@need'
+ Start a new printed page if required space not on this one.
+ This command has no effect on the Info file.
+
+* Menu:
+
+* Line Breaks:: Force a line break in the printed manual.
+* Sp:: Generate blank lines.
+* Br:: Force a paragraph break in the printed manual.
+* W:: Prevent a paragraph break in the printed manual.
+* Page:: Start a new page in the printed manual.
+* Group:: Hold text together that must appear on one printed page.
+* Need:: Start a new printed page if required space not on this one.
+
+
+
+File: texinfo, Node: Line Breaks, Next: Sp, Prev: Breaks Blank-Lines Groups, Up: Breaks Blank-Lines Groups
+
+@*
+--
+
+`@*' forces a line break in the printed manual. It has no effect on
+the Info file output, where line breaks follow those in the source
+file. If you want a line break at a certain spot in both forms of
+output, break the line there in the source file and put `@*' at the
+end of the line.
+
+
+
+File: texinfo, Node: Sp, Next: Br, Prev: Line Breaks, Up: Breaks Blank-Lines Groups
+
+@sp
+---
+
+A line containing `@sp N' generates N blank lines of space in either
+the printed manual or the Info file. For example,
+
+ @sp 2
+
+generates two blank lines.
+
+
+
+File: texinfo, Node: Br, Next: W, Prev: Sp, Up: Breaks Blank-Lines Groups
+
+@br
+---
+
+In a printed manual, a line containing `@br' forces a paragraph
+break; in the Info file output, it does nothing (not even a blank
+line results from it).
+
+
+
+File: texinfo, Node: W, Next: Page, Prev: Br, Up: Breaks Blank-Lines Groups
+
+@w
+--
+
+In a printed manual, `@w{TEXT}' outputs TEXT and prohibits line
+breaks within TEXT. `@w' has no effect on the Info file output; it
+is the same as would result from just TEXT.
+
+
+
+File: texinfo, Node: Page, Next: Group, Prev: W, Up: Breaks Blank-Lines Groups
+
+@page
+-----
+
+A line containing `@page' starts a new page in a printed manual. The
+line has no effect on Info files since they are not paginated.
+
+
+
+File: texinfo, Node: Group, Next: Need, Prev: Page, Up: Breaks Blank-Lines Groups
+
+@group
+------
+
+A line containing `@group' begins an unsplittable vertical group,
+which must appear entirely on one page. The group is terminated by a
+line containing `@end group'. These two lines produce no output of
+their own, and in the Info file output they have no effect at all.
+
+If you forget to end a group, you may get strange and unfathomable
+error messages when you run TeX. This is because TeX keeps trying to
+put the rest of the Texinfo file into the group and error messages do
+not start to get generated until TeX has gone a long way. It's a
+good rule of thumb to look for a missing `@end group' if you get
+incomprehensible error messages in TeX.
+
+
+
+File: texinfo, Node: Need, Prev: Group, Up: Breaks Blank-Lines Groups
+
+@need
+-----
+
+A line containing `@need N' starts a new page in a printed manual if
+fewer than N mils (thousandths of an inch) remain on the current
+page. The line has no effect on Info files since they are not
+paginated.
+
+
+
+File: texinfo, Node: Marking Text, Next: Conditionals, Prev: Formatting Paragraphs, Up: Top
+
+Marking Text Within a Paragraph
+*******************************
+
+In Texinfo, text within a paragraph can be marked in a variety of ways.
+The most important way is to specify whether a word or phrase is a
+definition, a metasyntactic variable, a literal example of a program
+or what not.
+
+In addition, there are special commands for inserting single
+characters that have special meaning in Texinfo, such as braces, and
+for inserting symbols with special handling, such as dots and
+bullets. Finally, there are ways to emphasize words.
+
+* Menu:
+
+* Specifying:: Specifying commands, files and so on.
+* Braces Atsigns Periods:: Inserting braces, `@' and periods.
+* Dots Bullets Tex:: Inserting dots, bullets and the TeX logo
+* Emphasis:: Emphasizing text.
+
+
+
+File: texinfo, Node: Specifying, Next: Braces Atsigns Periods, Up: Marking Text
+
+Specifying Definitions, Files, Commands etc.
+============================================
+
+Texinfo has a variety of commands for specifying just what kind of
+object a piece of text refers to. Metasyntactic variables, for
+example, are marked by one @-command and code by another. Texinfo
+uses this information to determine how to highlight the text. Since
+the pieces of text are labelled by commands that tell what kind of
+object they are, it is easy to change the way Texinfo formats and
+typesets such text. For example, code is usually illustrated in a
+typewriter font, but it would be easy to change the way Texinfo
+highlights code to use another font. This change would not effect
+how metasyntatic variables are highlighted. If straight typesetting
+commands were used in the body of the file, you would have to check
+every single occurrence to make sure that you were changing code and
+not something else that should not be changed.
+
+In addition, the commands can be used to generate useful information
+from the file, such as lists of functions or file names. It is
+possible, for example, to write code in Emacs Lisp (or a keyboard
+macro) to insert an index entry after every paragraph that contains
+the text labelled by a specified command. You could do this to
+construct an index of functions if you had not already made the
+entries.
+
+The commands serve a variety of purposes:
+
+`@code'
+ Indicates text that is a literal example of a piece of a program.
+
+`@samp'
+ Indicates text that is a literal example of a sequence of
+ characters.
+
+`@file'
+ Indicates the name of a file.
+
+`@kbd'
+ Indicates the names of keys on the keyboard or characters you
+ type.
+
+`@key'
+ Used for the conventional name for a key on a keyboard.
+
+`@ctrl'
+ Indicates an ASCII control character.
+
+`@var'
+ Indicates a metasyntactic variable.
+
+`@dfn'
+ Indicates the introductory or defining use of a term.
+
+`@cite'
+ Indicates the name of a book.
+
+* Menu:
+
+* Code:: A literal example of a piece of a program.
+* Samp:: A literal example of a sequence of characters.
+* File:: The name of a file.
+* Kbd:: The names of keys or else characters you type.
+* Key:: The conventional name for a key on a keyboard.
+* Ctrl:: Indicates the ASCII control character.
+* Var:: A variable.
+* Dfn:: The introductory or defining use of a term.
+* Cite:: The name of a book.
+
+
+
+File: texinfo, Node: Code, Next: Samp, Up: Specifying
+
+@code
+-----
+
+`@code' is used to indicate text that is a piece of a program which
+consists of entire syntactic tokens. The text follows, enclosed in
+braces.
+
+For example, `@code' is used for an expression in a program, the name
+of a variable or function used in a program, or a keyword. `@code'
+is not used for a piece of a token, such as when speaking about the
+characters used in a token; for example, when you are explaining what
+letters or printable symbols can be used in the names of functions.
+It is also not used for input to programs unless the input is written
+in a language that is like a programming language. For example, it
+is not used for the single character commands of GNU Emacs although
+it is used for the names of Emacs Lisp functions that the keyboard
+commands invoke.
+
+You should also `@code' for command names in command languages that
+resemble programming languages, such as Texinfo or the shell. Note,
+however, that `@code' is not used for options such as `-c' when such
+options stand alone. There is some argument as to whether an entire
+shell command incorporating an option should be written using `@code'
+or `@samp'.
+
+It is an error to alter the case of a word inside an `@code' command.
+This is a particularly insidious error if the language being
+documented is case sensitive. If the command is `printf', then
+`Printf' is a misspelling. If you do not like having such a command
+with lower case at the beginning of a sentence, you may wish to
+rearrange the sentence.
+
+In the printed manual, `@code' puts the argument in bold face. In
+the Info file, it uses `...' quotation. For example:
+
+ To compare two files, showing text inserted or removed, use @code{diff}.
+
+ produces
+
+ To compare two files, showing text inserted or removed, use
+ `diff'.
+
+
+
+File: texinfo, Node: Samp, Next: File, Prev: Code, Up: Specifying
+
+@samp
+-----
+
+`@samp' is used to indicate text that is a literal example of a
+sequence of characters in a file, string, pattern, etc. The text
+follows, enclosed in braces. The argument appears within `...'
+quotation in both the Info file and the printed manual; in addition,
+it is printed in a fixed-width font.
+
+ To match @samp{foo} at the end of the line, use the regexp @samp{foo$}.
+
+ produces
+
+ To match `foo' at the end of the line, use the regexp `foo$'.
+
+Any time you are referring to single characters, you should use
+`@samp' unless `@kbd' is more appropriate. Basically, `@samp' is a
+catchall for whatever is not covered by `@code', `@file', `@kbd'.
+
+Punctuation marks that are part of the English text that surrounds
+the strings you are specifying are *never* included within the
+braces. In the following sentence, for example, the commas and
+period are outside of the braces:
+
+ A symbol name ends in @samp{a}, @samp{b}, or @samp{c}.
+
+
+
+File: texinfo, Node: File, Next: Kbd, Prev: Samp, Up: Specifying
+
+@file
+-----
+
+`@file' is used to indicate text that is the name of a file or
+directory. Currently, it is equivalent to `@samp' in its effects on
+the output. For example,
+
+ The @file{.el} files are in
+ the @file{/gnu/emacs/lisp} directory.
+
+ produces
+
+ The `.el' files are in the `/gnu/emacs/lisp' directory.
+
+
+
+File: texinfo, Node: Kbd, Next: Key, Prev: File, Up: Specifying
+
+@kbd
+----
+
+`@kbd' is used much like `@code'. The difference is that `@kbd' is
+for names of keys on the keyboard, or of characters you can type.
+For example, to refer to the command `M-a', you would use
+
+ @kbd{M-a}
+
+and to refer to `M-x shell', you would use
+
+ @kbd{M-x shell}
+
+The `@kbd' command has the same effect as `@code' in Info, but may
+produce a different font in a printed manual.
+
+You can embed another @-command inside the braces of a `@kbd'
+command. This is the way to describe a command that would be
+described more verbosely as "press an `r' and then press the RET key":
+
+ @kbd{r @key{RET}}
+
+This produces: `r RET'
+
+You also use the `@kbd' command if you are spelling out the letters
+you type; for example:
+
+ To give the @code{logout} command,
+ type the characters @kbd{l o g o u t @key{RET}}.
+
+ This produces
+
+ To give the `logout' command, type the characters `l o g o u t
+ RET'.
+
+
+
+File: texinfo, Node: Key, Next: Ctrl, Prev: Kbd, Up: Specifying
+
+@key
+----
+
+`@key' is used for the conventional name for a key on a keyboard, as in
+
+ @key{RET}
+
+Often, `@key' is used within the argument of a `@kbd' command,
+whenever the sequence of characters to be typed includes one or more
+keys that are described by name.
+
+For example, to produce `C-x ESC' you would use
+
+ @kbd{C-x @key{ESC}}
+
+The recommended names to use for keys are in upper case and are
+
+SPC
+ Space.
+
+RET
+ Return.
+
+LFD
+ Linefeed.
+
+TAB
+ Tab.
+
+BS
+ Backspace.
+
+ESC
+ Escape.
+
+DEL
+ Delete.
+
+SFT
+ Shift.
+
+CTL
+ Control.
+
+META
+ Meta.
+
+There are subtleties to handling words like `meta' or `ctrl' which
+are names of shift keys. When mentioning a character in which the
+shift key is used, such as `Meta-a', use the `@kbd' command alone
+without the `@key' command, but when you are referring to shift key
+in isolation, use the `@key' command. For example, you would use
+`@kbd{Meta-a}' to produce `Meta-a' and `@key{META}' to produce META.
+
+
+
+File: texinfo, Node: Ctrl, Next: Var, Prev: Key, Up: Specifying
+
+@ctrl
+-----
+
+`@ctrl' is used to describe an ASCII control character. The pattern
+of usage is `@ctrl{CH}', where CH is an ASCII character whose
+control-equivalent is wanted. Thus, you put in an `f' when you want
+to indicate a `control-f'
+
+Thus, to specify `control-f', you would enter
+
+ @ctrl{f}
+
+which produces
+
+ f
+
+In the Info file, this generates the specified control character,
+output literally into the file. This is done so a user can copy the
+specified control character (along with whatever else he or she
+wants) into another Emacs buffer and use it. Since the
+`control-h',`control-i', and `control-j' characters are formatting
+characters, they should not be indicated this way.
+
+In a printed manual, this generates text to describe or identify that
+control character: an uparrow followed by the character CH.
+
+
+
+File: texinfo, Node: Var, Next: Dfn, Prev: Ctrl, Up: Specifying
+
+@var
+----
+
+`@var' is used to indicate metasyntactic variables. A metasyntactic
+variable is something that stands for another piece of text. You
+would use a metasyntactic variable in the documentation of a function
+to describe the arguments that are passed to that function.
+
+`@var' is not used for names of particular variables in programming
+languages. For example, the Texinfo variable `texinfo-tex-command'
+is not a metasyntactic variable.
+
+Its effect in the Info file is to upcase the argument; in the printed
+manual, to italicize it. Example:
+
+ To delete file @var{filename}, type @code{rm @var{filename}}.
+
+ produces
+
+ To delete file FILENAME, type `rm FILENAME'.
+
+In some documentation styles, metasyntactic variables are shown with
+angle brackets, for example:
+
+ ..., type rm <filename>
+
+
+
+File: texinfo, Node: Dfn, Next: Cite, Prev: Var, Up: Specifying
+
+@dfn
+----
+
+`@dfn' is used to identify the introductory or defining use of a
+technical term. The command should be used only in a passage whose
+purpose is to introduce a term which will be used again or which the
+reader ought to know. Mere passing mention of a term for the first
+time doesn't deserve `@dfn'. It generates italics in the printed
+manual, and double quotation marks in the Info file. Example:
+
+ Getting rid of a file is called @dfn{deleting} it.
+
+ produces
+
+ Getting rid of a file is called "deleting" it.
+
+
+
+File: texinfo, Node: Cite, Prev: Dfn, Up: Specifying
+
+@cite
+-----
+
+`@cite' is used for the name of a book. It produces italics in the
+printed manual, and quotation marks in the Info file.
+
+
+
+File: texinfo, Node: Braces Atsigns Periods, Next: Dots Bullets Tex, Prev: Specifying, Up: Marking Text
+
+Inserting Braces, `@' and Periods
+=================================
+
+`@' and curly braces are special characters in Texinfo. This means
+that you have to put an `@' in front of these characters in order to
+insert them into text.
+
+Periods are also special. Depending on whether the period is inside
+of or at the end of a sentence, less or more space is inserted after
+a period in a typeset manual. Since it is not always possible for
+Texinfo to determine when a period ends a sentence and when it is
+used in an abbreviation, special commands are needed. (Usually,
+Texinfo figures out how to handle periods, so you don't have to use
+the special commands; you just enter a period as you would if you
+were using a typewriter, which means you put two spaces after the
+period that ends a sentence and after a colon.)
+
+* Menu:
+
+* Inserting an Atsign:: inserting an atsign.
+* Insert Left Brace:: Inserting a left brace.
+* Insert Colon:: Preventing unintended additional whitespace.
+* Insert Period:: Inserting a period that does end a sentence.
+
+
+
+File: texinfo, Node: Inserting An Atsign, Next: Insert Left Brace, Up: Braces Atsigns Periods
+
+@@
+--
+
+`@@' stands for a single @ in either printed or Info output.
+
+
+
+File: texinfo, Node: Insert Left Brace, Next: Insert Colon, Prev: Inserting an Atsign, Up: Braces Atsigns Periods
+
+@{
+--
+
+`@{' stands for a single { in either printed or Info output.
+
+@}
+--
+
+`@}' stands for a single } in either printed or Info output.
+
+
+
+File: texinfo, Node: Insert Colon, Next: Insert Period, Prev: Insert Left Brace, Up: Braces Atsigns Periods
+
+@:
+--
+
+`@:' is used after a character such as period or colon which normally
+causes TeX to increase the width of the following whitespace, to
+suppress that effect. For example, it can be used after periods that
+end abbreviations and do not end sentences. `@:' has no effect on
+the Info file output.
+
+ It displays @code{Foo:}@: at that time.
+
+ produces
+
+ It displays `Foo:' at that time.
+
+The meanings of `@:' and `@.' in Texinfo are designed to work well
+with the Emacs sentence motion commands. This means they are
+different from their meanings in some other formatting systems that
+use @-commands.
+
+
+
+File: texinfo, Node: Insert Period, Prev: Insert Colon, Up: Braces Atsigns Periods
+
+@.
+--
+
+`@.' stands for a period that really does end a sentence, useful when
+TeX would otherwise assume by its heuristics that that is not so.
+This happens when there is a single-capital-letter word at the end of
+a sentence: TeX normally guesses that it is an abbreviation.
+
+In the Info file output, `@.' is equivalent to a simple `.'. The
+Texinfo program preserves the amount of space that you use, so put
+two spaces after a period if you intend it to be the end of a
+sentence (as well as using `@.', if necessary, for the printed
+manual's sake).
+
+ Give it to X. Give it to X@. Give it to X@.
+
+ produces
+
+ Give it to X. Give it to X. Give it to X.
+
+
+
+File: texinfo, Node: Dots Bullets Tex, Next: Emphasis, Prev: Braces Atsigns Periods, Up: Marking Text
+
+Inserting Dots, Bullets and TeX
+===============================
+
+An ellipsis, a line of dots, is typeset differently than a string of
+periods; more whitespace is put between the dots in the ellipsis than
+is put between the periods. Because of this, a special command is
+used in Texinfo for inserting dots. Also, the trademark, TeX, is
+typeset in a special fashion and it needs an @-command, as does the
+command for inserting the copyright symbol. The `@bullet' command is
+special, too. Each of these commands is followed by a pair of
+braces, `{}', without any whitespace between the name of the command
+and the braces.
+
+* Menu:
+
+* Dots:: Inserting dots.
+* Bullet:: Inserting bullets.
+* Tex:: Inserting the TeX trademark.
+
+
+
+File: texinfo, Node: Dots, Next: Bullet, Up: Dots Bullets Tex
+
+@dots{}
+-------
+
+`@dots{}' generates an ellipsis which is three dots in a row,
+appropriately spaced, like this: `...'. Do not simply write three
+periods in the input file; that would work for the Info file output,
+but would produce the wrong amount of space between the periods in
+the printed manual.
+
+
+
+File: texinfo, Node: Bullet, Next: Tex, Prev: Dots, Up: Dots Bullets Tex
+
+@bullet{}
+---------
+
+`@bullet{}' generates a large round dot, or the closest possible
+thing to one.
+
+Here is a bullet: *
+
+
+
+File: texinfo, Node: Tex, Prev: Bullet, Up: Dots Bullets Tex
+
+@TeX{}
+------
+
+`@TeX{}' generates `TeX'. In a printed manual, this is a special
+logo that is different from three ordinary letters.
+
+
+
+File: texinfo, Node: Emphasis, Prev: Dots Bullets Tex, Up: Marking Text
+
+Emphasizing Text
+================
+
+Usually, Texinfo changes the font automatically to mark words in the
+text according to what category the words belong to. The `@code'
+command, for example, does this. Most often, this is the best way to
+mark specified words. However, sometimes you will want to emphasize
+text directly. Texinfo has two ways to do this: commands that tell
+Texinfo to emphasize the text but leave the method to the program,
+and commands that specify the font to use. The first method is
+generally the best and it makes it possible to change the style of a
+document without have to re-edit it line by line.
+
+* Menu:
+
+* Emph and Strong:: Emphasizing text.
+* Fonts:: Selecting italic, bold or typewriter fonts.
+
+
+
+File: texinfo, Node: Emph and Strong, Next: Fonts, Up: Emphasis
+
+@emph and @strong
+-----------------
+
+`@emph' and `@strong' are two forms of emphasis. `@strong' is
+stronger.
+
+In printed output, `@emph' produces *italics* and `@strong' produces
+*bold*.
+
+In the Info file, both of these commands put asterisks around the
+argument.
+
+
+
+File: texinfo, Node: Fonts, Prev: Emph and Strong, Up: Emphasis
+
+@i, @b and @t
+--------------
+
+These three commands specify font changes in the printed manual and
+have no effect in the Info file. `@i' requests italic font (in some
+versions of TeX, a slanted font is used), `@b' requests bold face,
+and `@t' requests the fixed-width font used by `@kbd'. All three
+commands apply to an argument that follows, surrounded by braces.
+
+If possible, you should avoid using these three commands. If you
+find a need to use one, it probably indicates a lack in the Texinfo
+language.
+
+
+
+File: texinfo, Node: Conditionals, Next: Printing Hardcopy, Prev: Marking Text, Up: Top
+
+Conditionals
+************
+
+You may not always be able to use the same text for both the printed
+manual and the on-line Info file. In this case, you can use the
+conditional commands to specify which text is for the printed manual
+and which is for the Info file.
+
+`@ifinfo' begins text that should be ignored by TeX when it typesets
+the printed manual. The text appears only in the Info file. The
+`@ifinfo' command should appear on a line by itself. End the
+info-only text with a line containing `@end ifinfo' by itself. At
+the beginning of a Texinfo file, the Info permissions are contained
+within a region marked by `@ifinfo' and `@end ifinfo'.
+
+Likewise, `@iftex' and `@end iftex' lines delimit text that will not
+appear in the Info file but will appear in the printed manual.
+
+For example,
+
+ @iftex
+ This text will appear only in the printed manual.
+ @end iftex
+
+
+ @ifinfo
+ However, this text will appear only in the info manual.
+ @end ifinfo
+
+The preceding example produces the following. Note how you only see
+one of the two lines, depending on whether you are reading the
+on-line Info version or the printed version of this manual.
+
+However, this text will appear only in the info manual.
+
+The `@titlepage' command is a special variant of `@iftex' that is
+used for making the title and copyright pages of the printed manual.
+
+* Menu:
+
+* Using Tex Commands:: Using commands from regular TeX.
+
+
+
+File: texinfo, Node: Using Tex Commands, Prev: Conditionals, Up: Conditionals
+
+Using TeX Commands
+==================
+
+Inside a region delineated by `@iftex' and `@end iftex', you can
+embed ordinary TeX commands. Info will ignore these commands since
+they are only in that part of the file that is seen by TeX. The TeX
+commands are the same as any TeX commands except that an `@' replaces
+the `\' used by TeX. For example, in the `@titlepage' section of a
+Texinfo file, the TeX command `@vskip' is used to format the
+copyright page.
+
+You can enter TeX completely, and use `\' in the TeX commands by
+delineating a region with the `@tex' and `@end tex' commands. (These
+commands automatically put the region inside of `@iftex' and `@end
+iftex' commands.) For example,
+
+ @tex
+ Here you would put text with TeX commands;
+ such as $\bigl(x\in A(n)\bigm|x\in B(n)\bigr)$
+ that will appear only in the printed manual.
+ @end tex
+
+In the Info file, nothing between `@tex' and `@end tex' will appear.
+
+
+
+File: texinfo, Node: Printing Hardcopy, Next: Creating an Info File, Prev: Conditionals, Up: Top
+
+Printing Hardcopy
+*****************
+
+There are three shell commands for printing a hardcopy of a Texinfo
+file. One is for formatting the file, the second is for sorting the
+index and the third is for printing the formatted document. When you
+use the shell commands, you can either work directly in the operating
+system shell or work within a shell inside of GNU Emacs.
+
+The typesetting program TeX is used for formatting a Texinfo file.
+TeX is a very powerful typesetting program and, if used right, does
+an exceptionally good job. The @-commands in a Texinfo file are
+translated by a file called `texinfo.tex' into commands that TeX
+understands. (That is why the beginning of every Texinfo file starts
+with the line that says `\input texinfo'; this command tells TeX to
+use the `texinfo.tex' file in processing the Texinfo file.
+Customarily, `texinfo.tex' is in a directory called
+`/usr/lib/tex/macros'.) `texinfo-format-buffer' reads the very same
+@-commands in the Texinfo file and processes them differently from
+TeX to make an Info file.
+
+Usually, the TeX formatting command is the shell command `tex'
+followed by the name of the Texinfo file. The TeX command produces a
+formatted DVI file as well as several auxiliary files containing
+indices, cross references, etc. The DVI file (for "DeVice
+Independent" file) can be printed on a wide variety of printers.
+
+The TeX formatting command itself does not sort the indices. This is
+a misfeature of TeX. Hence, to generate a printed index, you first
+need a sorted index to work from.
+
+TeX outputs raw, unsorted index files under names that obey a
+standard convention. These names are the name of your main input
+file to TeX, with everything after the first period thrown away, and
+the two letter names of indices added at the end. For example, the
+raw index output files for the input file `foo.texinfo' would be
+`foo.cp', `foo.vr', `foo.fn', `foo.tp', `foo.pg' and `foo.ky'. Those
+are exactly the arguments to give to `texindex'. Or else, you can
+use `??' as "wild-cards" and give the command in this form:
+
+ texindex foo.??
+
+ For each file specified, `texindex' generates a sorted index file
+whose name is made by appending `s' to the input file name. The
+`@printindex' command knows to look for a file of that name.
+`texindex' does not alter the raw index output file. After you have
+sorted the indices, you need to rerun the TeX command on the Texinfo
+file. This regenerates a formatted DVI file with the index entries
+in the correct order.
+
+To summarize, this is a three step process:
+
+ 1. Run the TeX command on the Texinfo file. This generates the
+ formatted DVI file as well as the raw index files with two
+ letter extensions.
+
+ 2. Run the shell command `texindex' on the raw index files to sort
+ them. The arguments to `texindex' are the names of the raw
+ index files. `texindex' creates sorted index files whose names
+ are the names of the raw index files with an `s' appended. To
+ cause `texindex' to sort all the raw index files, append `??' to
+ the Texinfo file name in place of the `.texinfo' extension.
+
+ 3. Rerun the TeX command on the Texinfo file. This regenerates a
+ formatted DVI file with the index entries in the correct order.
+ This second run also makes all the cross references correct as
+ well. (The tables of contents are always correct.)
+
+You need not run `texindex' after each TeX run. If you don't, the
+next TeX run will use whatever sorted index files happen to exist
+from the previous use of `texindex'. This is usually ok while you
+are debugging.
+
+Finally, the document can be printed out with the DVI print command
+(a shell command). Depending on the system used, the DVI print
+command will be a command such as `lpr -d'. The DVI print command
+may require a file name without any extension or with a `.dvi'
+extension.
+
+The following commands, for example, sort the indices, format and
+print the ``Bison Manual'' (where `%' is the shell prompt):
+
+ % tex bison.texinfo
+ % texindex bison.??
+ % tex bison.texinfo
+ % lpr -d bison.dvi
+
+(Remember that the words for the shell commands may be different at
+your site; but these are commonly used versions.)
+
+It is often most convenient to give formatting and printing commands
+from a shell within GNU Emacs. This way, you can easily keep track
+of errors. To create a shell within Emacs, type `M-x shell'. In
+this shell, you can format and print the document. You can switch to
+and from this shell while it is running and do other things. If you
+are formatting a very long document on a slow machine, this can be
+very convenient; on a VAX 750, for example, formatting often takes 8
+seconds or more per page depending on how loaded the computer is.
+Faster machines take correspondingly less time.
+
+* Menu:
+
+* Requirements:: Formatting requirements.
+* Compile-Command:: Formatting with the compile command.
+
+
+
+File: texinfo, Node: Requirements, Next: Compile-Command, Up: Printing Hardcopy
+
+Formatting Requirements
+=======================
+
+Every Texinfo file that is to be input to TeX must begin with a line
+that looks like
+
+ \input texinfo @c -*-texinfo-*-
+
+This serves two functions.
+
+ 1. When the file is processed by TeX, it loads the macros needed
+ for processing a Texinfo file.
+
+ 2. When the file is edited in Emacs, it causes Texinfo mode to be
+ used.
+
+Every Texinfo file must end with a line saying
+
+ @bye
+
+which terminates TeX processing and forces out unfinished pages.
+
+You also have to include two lines that specify the Info file name
+and the title of the printed manual:
+
+ @setfilename NAME-OF-TEXINFO-FILE
+ @settitle NAME OF MANUAL
+
+You might also want to include a line saying
+
+ @setchapternewpage odd
+
+to cause each chapter to start on a fresh odd-numbered page.
+
+By default, TeX typesets pages for printing in an 8.5 by 11 inch
+format. However, you can direct TeX to typeset a document in a 7 by
+9.25 inch format that is suitable for bound books by inserting the
+following command on a line by itself at the beginning of the Texinfo
+file, before the `@setchapternewpage' command:
+
+ @smallbook
+
+The Free Software Foundation distributes printed copies of the ``GNU
+Emacs Manual'' in this size.
+
+Finally, TeX sometimes is unable to typeset a line without extending
+it into the right margin. This can occur when TeX comes upon what it
+interprets as a long word that it cannot hyphenate, like a net
+address, or a very long title. When this happens, TeX prints an
+error message like this:
+
+ Overfull \hbox (20.76302pt too wide)
+
+and gives the line number along with the text of the offending line
+marked at all the places that TeX knows to hyphenate words. (In TeX
+lines are in `horizontal boxes', hence the term, `hbox'.)
+
+If the Texinfo file has an overfull hbox, you can rewrite the
+sentence so the overfull hbox does not occur or you can decide to
+leave it. A small excursion into the right margin often does not
+matter and may not even be noticable. However, unless told
+otherwise, TeX will print a large, ugly, black rectangle beside every
+line that is overfull. This is so you will notice the location of
+the problem if you are correcting a draft. To prevent such
+monstrosities from marring your final printout, put the following in
+the beginning of the Texinfo file on lines of their own, before the
+`@setchapternewpage' command:
+
+ @iftex
+ @finalout
+ @end iftex
+
+*Note Titlepage::, for information about creating a title page.
+*Note Contents::, for information about creating a table of contents.
+
+
+
+File: texinfo, Node: Compile-Command, Prev: Requirements, Up: Printing Hardcopy
+
+Using Local Variables and the Compile Command
+=============================================
+
+Another way to give the TeX formatting command to Texinfo is to put
+that command in a "local variables list" at the end of the Texinfo
+file. You can then specify the TeX formatting command as a
+`compile-command' and have Emacs run the TeX formatting command by
+giving the command `M-x compile'. This creates a special shell
+called the `*compilation buffer*'. For example, at the end of the
+`gdb.texinfo' file, after the `@bye', you would put the following:
+
+ @c Local Variables:
+ @c compile-command: "tex gdb.texinfo"
+ @c End:
+
+This technique is most often used by programmers who compile programs
+this way.
+
+
+
+File: texinfo, Node: Creating an Info File, Next: Catching Mistakes, Prev: Printing Hardcopy, Up: Top
+
+Creating an On-line Info file
+*****************************
+
+In GNU Emacs, using Texinfo mode, you can see what part or all of a
+Texinfo file will look like in Info by using the keyboard command
+`C-c C-f' (`texinfo-format-region'). This formats a region and
+displays in a temporary buffer called `*Info Region*'; however, this
+command does not turn on Info reading program--it just displays what
+the region will look like. The `texinfo-format-region' command is
+described more extensively in the chapter on using Texinfo mode.
+*Note Info on a Region::.
+
+In GNU Emacs, the way to create a working Info file is to visit the
+file and invoke
+
+ `M-x texinfo-format-buffer'
+
+A new buffer is created and the Info file text is generated there.
+`C-x C-s' will save it under the name specified in the `@setfilename'
+command.
+
+If the Texinfo file has more than 30,000 bytes,
+`texinfo-format-buffer' will automatically create a "tag table" for
+it. With a tag table, Info can jump to new nodes more quickly than
+it can otherwise. In addition, if the file has more than 100,000
+bytes in it, `texinfo-format-buffer' will split the file into shorter
+Indirect subfiles of about 50,000 bytes each. Files are split so
+that Info does not have to make a large buffer to hold the whole of a
+large Info file; instead, Info allocates just enough memory for the
+small, split off file that is needed at the time. This way, Emacs
+avoids wasting memory when you run Info. (Before splitting was
+implemented, Info files were always short and "include" files were
+designed as a way to create a single, large printed manual out of the
+smaller Info files. *Note Include Files::, for more information.)
+
+When the file is split, Info itself works through a shortened version
+of the original file that contains the tag table and references to
+the files that were split off. The split off files are called
+"indirect" files.
+
+The split off files have names that are created by appending `-1',
+`-2', `-3' and so on to the file names specified by the
+`@setfilename' command. The shortened version of the original file
+continues to have the name specified by `@setfilename'.
+
+At one stage in writing this document, for example, the Info file was
+saved as `test-texinfo' and that file looked like this:
+
+ Info file: test-texinfo, -*-Text-*-
+ produced by texinfo-format-buffer
+ from file: new-texinfo-manual.texinfo
+
+ ^_
+ Indirect:
+ test-texinfo-1: 102
+ test-texinfo-2: 50422
+ test-texinfo-3: 101300
+ ^_^L
+ Tag table:
+ (Indirect)
+ Node: overview^?104
+ Node: info file^?1271
+ Node: printed manual^?4853
+ Node: conventions^?6855
+ ...
+
+ (But `test-texinfo' had far more nodes than are shown here.) Each of
+the split off, indirect files, `test-texinfo-1', `test-texinfo-2',
+and `test-texinfo-3', is listed in this file after the line that says
+`Indirect:'. The tag table is listed after the line that says `Tag
+table:'.
+
+You cannot run the `M-x Info-validate' node checking command on
+indirect files. For information on how to prevent files from being
+split and how to validate the structure of the nodes, *note
+Info-Validating a Large File::.
+
+* Menu:
+
+* Installing an Info File:: Putting the Info file in the info directory.
+
+
+
+File: texinfo, Node: Installing an Info File, Prev: Creating an Info File, Up: Creating an Info File
+
+Installing an Info file
+=======================
+
+An Info file is usually installed in the GNU Emacs directory called
+`info'. For Info to work, this directory must contain all the Info
+files, including the split off files. In addition, the `info'
+directory must have a file that serves as a top level directory for
+the Info system. This file is called `dir'.
+
+For example, in the `info' directory, the file called `dir' has the
+top level menu for all the Info files in the system. This file has a
+master menu that looks like this:
+
+ * Menu:
+
+ * Info: (info). Documentation browsing system.
+ * Emacs: (emacs). The extensible self-documenting text editor.
+ * Texinfo: (texinfo). With one source file, make either a printed
+ manual using TeX or an Info file using
+ Texinfo.
+
+ To add a new Info file, just add it to this menu. For example, if
+you were adding documentation for GDB, you would make the following
+entry:
+
+ * GDB: (gdb). The source-level C debugger.
+
+ The first item is the menu item name; it is followed by a colon. The
+second item is the name of the Info file, in parentheses; it is
+followed by a period. The third part of the entry is the description
+of the item.
+
+The top node of the file, named `top', should have as its parent the
+name of a node in another file, where there is a menu that leads to
+this file. Specify the file name in parentheses. If the file is to
+be installed directly in the Info directory file, use `(dir)' as the
+parent of the top node; this is short for `(dir)top', the node `top'
+in the file `dir', which is the main menu of Info.
+
+
+
+File: texinfo, Node: Catching Mistakes, Next: Command Syntax, Prev: Creating an Info File, Up: Top
+
+Catching Mistakes
+*****************
+
+Besides mistakes with the content of what ever you are describing,
+there are two kinds of mistake you can make with Texinfo: you can
+make mistakes with @-commands, and you can make mistakes with the
+structure of the nodes and chapters.
+
+There are two tools for catching the first kind of mistake and two
+for catching the second.
+
+For finding problems with @-commands, your best action is to run `M-x
+texinfo-format-region' on regions of your file as you write it. In
+Texinfo mode, the `texinfo-format-region' command is bound to `C-c
+C-f'. In addition, you can run TeX on the whole file.
+
+For finding problems with the structure of nodes and chapters, you
+can use `C-c C-s' (`texinfo-show-structure') (and the related `occur'
+command) and you can use the `M-x Info-validate' command.
+
+* Menu:
+
+* Debugging with Info:: Catching errors with info formatting.
+* Debugging with Tex:: Catching errors with TeX formatting.
+* Using texinfo-show-structure:: Using `texinfo-show-structure'
+ to catch mistakes.
+* Running Info-Validate:: Checking for unreferenced nodes.
+
+
+
+File: texinfo, Node: Debugging with Info, Next: Debugging with Tex, Up: Catching Mistakes
+
+Catching Errors with Info Formatting
+====================================
+
+After you have written part of a Texinfo file, you can use the `M-x
+texinfo-format-region' command to see whether the region formats
+properly. In Texinfo mode, this command is bound to the keyboard
+command `C-c C-f'.
+
+If you have made a mistake with an @-command, `M-x
+texinfo-format-region' will stop processing at or after the error and
+give an error message. To see where in the file the error occurred,
+switch to the `*Info Region*' buffer; the cursor will be in a
+position that is after the location of the error. Also, the text
+will not be formatted after the place the error occurred.
+
+For example, if you accidently end a menu with the command `@end
+menus' with an `s' on the end, instead of with `@end menu', you will
+get an error message that says:
+
+ @end menus is not handled by texinfo.
+
+ The cursor will stop at the point in the file where the error occurs,
+or not long after it. It will look like this:
+
+ @menu
+ * Using texinfo-show-structure:: Using `texinfo-show-structure'
+ to catch mistakes.
+ * Running Info-Validate:: Checking for unreferenced nodes.
+ @end menus
+
+The `texinfo-format-region' command does not always recognize errors.
+For example, no errors were reported when `texinfo-format-region' was
+run on the whole itemized list of which the following is a part:
+
+ name of the Texinfo file as an extension. The @samp{??} are `wildcards'
+ that cause the shell to substitute all the raw index files. (@xref{sorting
+ indices), for more information about sorting indices.) @refill
+ @cindex Sorting indices
+ @cindex Indices, sorting
+
+ @item
+ @emph{Third}, rerun the @TeX{} command on the Texinfo file. This
+ regenerates a formatted DVI file with the index entries in the correct
+ order. This second run also makes all the cross references and table of
+ contents correct as well.
+
+ Instead, `texinfo-format-region' ran without reporting the error, but
+it produced output with very long lines, containing some of the
+original `@cindex' commands mixed in. (It is not practical to
+display these over long lines here.
+
+However, when `texinfo-format-region' was run on part of the list
+that is shown, it did give an error message, `Search failed: "[{,}"'.
+(This error message is explained in the section on using the Emacs
+Lisp Debugger, *note Using the Emacs Lisp Debugger::.)
+
+Sometimes `texinfo-format-region' will stop long after the original
+error; this is because it does not discover the problem until then.
+In this case, you will have to backtrack.
+
+
+
+File: texinfo, Node: Using the Emacs Lisp Debugger, Up: Debugging with Info
+
+Using the Emacs Lisp Debugger
+-----------------------------
+
+If an error is especially elusive, you can turn on the Emacs Lisp
+debugger and look at the backtrace; this tells you where in the
+`texinfo-format-region' function the problem occurred. You can turn
+on the debugger with the command:
+
+ M-x set-variable RET debug-on-error RET t
+
+and turn it off with
+
+ M-x set-variable RET debug-on-error RET nil
+
+Often, when you are using the debugger, it is easier to follow what
+is going on if you use the Emacs Lisp files that are not
+byte-compiled. The byte-compiled sources send octal numbers to the
+debugger that may look mysterious. To use the uncompiled source
+files, load `texinfmt.el' and `texinfo.el' with the `M-x load-file'
+command.
+
+The debugger will not catch an error if `texinfo-format-region' does
+not detect one. In the example shown above, `texinfo-format-region'
+did not find the error when the whole list was formatted, but only
+when part of the list was formatted. When `texinfo-format-region'
+did not find an error, the debugger did not find one either.
+
+However, when `texinfo-format-region' did report an error, it invoked
+the debugger. This is the backtrace it produced:
+
+ Signalling: (search-failed "[},]")
+ re-search-forward("[},]")
+ (while ...)
+ (let ...)
+ texinfo-format-parse-args()
+ (let ...)
+ texinfo-format-xref()
+ funcall(texinfo-format-xref)
+ (if ...)
+ (let ...)
+ (if ...)
+ (while ...)
+ texinfo-format-scan()
+ (save-excursion ...)
+ (let ...)
+ texinfo-format-region(103370 103631)
+ * call-interactively(texinfo-format-region)
+
+The backtrace is read from the bottom up. `texinfo-format-region'
+was called interactively; and it, in turn, called various functions,
+including `texinfo-format-scan', `texinfo-format-xref' and
+`texinfo-format-parse-args'. Inside the function
+`texinfo-format-parse-args', the function `re-search-forward' was
+called; it was this function that could not find the missing right
+hand brace.
+
+*Note : (emacs)Lisp Debug, for more information.
+
+
+
+File: texinfo, Node: Debugging with Tex, Next: Using texinfo-show-structure, Prev: Debugging with Info, Up: Catching Mistakes
+
+Catching Errors with TeX Formatting
+===================================
+
+You can also catch mistakes when you format a file with TeX.
+
+Usually, you will want to do this after you have run
+`texinfo-format-buffer' on the same file. `texinfo-format-buffer' is
+usually faster and sometimes gives error messages that make more
+sense. *Note Debugging with Info::, for more information.
+
+For example, TeX was run on the same itemized list discussed in the
+section on the use of `texinfo-format-region' (*note Debugging with
+Info::.); the fragment with the error looked like this:
+
+ name of the texinfo file as an extension. The @samp{??} are `wildcards'
+ that cause the shell to substitute all the raw index files. (@xref{sorting
+ indices, for more information about sorting indices.) @refill
+
+This produced the following output, after which TeX stopped:
+
+ Runaway argument?
+ {sorting indices, for more information about sorting indices.) @refill @ETC.
+ ! Paragraph ended before \xref was complete.
+ <to be read again>
+ \par
+ l.27
+
+ ?
+
+In this case, TeX produced an accurate and understandable error
+message: `Paragraph ended before \xref was complete.' (Note, however,
+that TeX translated the `@' into a `\'.) Also, `\par' is an internal
+TeX command of no relevance to Texinfo.)
+
+Unfortunately, TeX is not always so helpful, and sometimes you have
+to be truly a Sherlock Holmes to discover what went wrong.
+
+In any case, if you run into a problem like this, you can do one of
+two things.
+
+ 1. You can tell TeX to continue running and to ignore errors as
+ best it can by typing `r RET' at the `?' prompt.
+
+ This is often the best thing to do. However, beware: the one
+ error may produce a cascade of additional error messages as it
+ consequences are felt through the rest of the file.
+
+ 2. You can tell TeX to stop this run by typing `x RET' at the `?'
+ prompt.
+
+Sometimes TeX will format a file without producing error messages
+even though there is a problem. This usually occurs if a command is
+not ended but TeX is able to continue processing anyhow. For
+example, if you fail to end an itemized list with the `@end itemize'
+command, TeX will write a DVI file that you can print out. The only
+error message that TeX will give you is the somewhat mysterious
+comment that
+
+ (\end occurred inside a group at level 1)
+
+However, if you print the DVI file, you will find that the text of
+the file that follows the itemized list is entirely indented as if it
+were part of the last item in the itemized list. The error message
+is the way TeX says that it expected to find an `@end' command
+somewhere in the file; but that it could not locate where it was
+needed.
+
+Another source of notoriously hard to find errors is a missing `@end
+group' command. If you ever are stumped by incomprehensible errors,
+look for a missing `@end group' command first.
+
+If you do not have the header lines in the file, TeX may stop in the
+beginning of its run and display output that looks like the following.
+The `*' indicates that TeX is waiting for input.
+
+ This is TeX, Version 2.0 for Berkeley UNIX (preloaded format=plain-cm
+ 87.10.25) (#tz-bar-a02987.tex [1])
+ *
+
+In this case, simply type `\end RET' after the asterisk. Then put
+the header lines into the Texinfo file and run the TeX command again.
+
+
diff --git a/info/texinfo-4 b/info/texinfo-4
new file mode 100644
index 00000000000..9a7f8029a01
--- /dev/null
+++ b/info/texinfo-4
@@ -0,0 +1,861 @@
+Info file ../info/texinfo, produced by Makeinfo, -*- Text -*- from
+input file texinfo.texinfo.
+
+This file documents Texinfo, a documentation system that uses a
+single source file to produce both on-line help and a printed manual.
+
+This is edition 1.1 of the Texinfo documentation, and is for the
+Texinfo that is distributed as part of Version 18 of GNU Emacs.
+
+Copyright (C) 1988 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of
+this manual under the conditions for verbatim copying, provided that
+the entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be stated in a
+translation approved by the Foundation.
+
+
+
+File: texinfo, Node: Using texinfo-show-structure, Next: Running Info-Validate, Prev: Debugging with Tex, Up: Catching Mistakes
+
+Using `texinfo-show-structure'
+==============================
+
+It is not always easy to keep track of the nodes, chapters, sections
+and subsections of a Texinfo file. This is especially true if you
+are revising or adding to a Texinfo file that someone else has written.
+
+In GNU Emacs, in Texinfo mode, there is a command that will list all
+the lines that begin with the @-commands that specify the structure:
+@node, @chapter, @section, @appendix and so on. This is the
+`texinfo-show-structure' command. It is bound to the keyboard
+command `C-c C-s'. `texinfo-show-structure' displays the lines that
+begin with the node and chapter structuring @-commands in another
+window called the `*Occur*' buffer. For example, when
+`texinfo-show-structure' is run on the first part of this chapter, it
+produces the following:
+
+ Lines matching
+ "^@\\(chapter\\|unnum\\|appendix\\|sect\\|sub\\|heading\\|major
+ \\|node\\)" in buffer new-texinfo-manual.texinfo.
+ 2:@node catching mistakes, @-Command Syntax, running info, top
+ 4:@chapter Catching Mistakes
+ 41:@node debugging with info, debugging with tex, , catching mistakes
+ 43:@section Catching errors with Info Formatting
+
+This means that lines 2, 4, 41 and 43 began with `@node', `@chapter',
+`@node', and `@section' respectively. If you move your cursor into
+the `*Occur*' window, you can position the cursor over one of the
+lines and use the `C-c C-c' command (`occur-mode-goto-occurrence'),
+to jump to the corresponding spot in the Texinfo file. *Note :
+(emacs)Other Repeating Search, for more information about
+`occur-mode-goto-occurrence'.
+
+The first line in the `*Occur*' window describes the "regular
+expression" specified by TEXINFO-HEADING-PATTERN. This regular
+expression is the pattern that `texinfo-show-structure' looks for.
+*Note : (emacs)Regexps, for more information.
+
+When you give the `texinfo-show-structure' command, it will show the
+structure of the whole buffer. If you want to see the structure of
+just a part of the buffer, of one chapter, for example, use the `C-x
+n' (`narrow-to-region') command to mark the region. (*Note :
+(emacs)Narrowing.) This is how the example used above was generated.
+(To see the whole buffer again, use `C-x w' (`widen').)
+
+You can remind yourself of the structure of a Texinfo file by looking
+at the list in the `*Occur*' window; and if you have mis-named a node
+or left out a section, you can correct the mistake.
+
+* Menu:
+
+* Using Occur::
+
+
+
+File: texinfo, Node: Using Occur, Prev: Using texinfo-show-structure, Up: Using texinfo-show-structure
+
+Using `occur'
+-------------
+
+Sometimes the `texinfo-show-structure' command produces too much
+information. Perhaps you want to remind yourself of the overall
+structure of a Texinfo file, and are overwhelmed by the detailed list
+produced by `texinfo-show-structure'. In this case, you can use the
+`occur' command itself. To do this, type
+
+ `M-x occur'
+
+and then, when prompted, type a "regexp", a regular expression for
+the pattern you want to match. (*Note : (emacs)Regexps.) `occur'
+works from the current location of the cursor in the buffer to the
+end of the buffer. If you want to run `occur' on the whole buffer,
+place the cursor at the beginning of the buffer. For example, to see
+all the lines that contain the word `@chapter' in them, just type
+`@chapter'. This will produce a list of the chapters. It will also
+list all the sentences with `@chapter' in the middle of the line. If
+you want to see only those lines that start with the word `@chapter',
+type `^@chapter' when prompted by `occur'. If you want to see all
+the lines that end with a word or phrase, end the last word with a
+`$'; for example, `catching mistakes$'. This can be helpful when you
+want to see all the nodes that are part of the same chapter or
+section and therefore have the same `Up' pointer.
+
+*Note : (emacs)Other Repeating Search, for more information.
+
+
+
+File: texinfo, Node: Running Info-Validate, Prev: Using texinfo-show-structure, Up: Catching Mistakes
+
+Finding Badly Referenced Nodes
+==============================
+
+You can check whether any of the `Next', `Previous', `Up' or other
+node pointers fail to point to a node with the `Info-validate' command.
+This command checks that every node pointer points to an existing node.
+
+To use this command, you first need to load the `info' library and
+then do `M-x Info-validate'.
+
+ `M-x load-library RET info RET'
+ `M-x Info-validate'
+
+(Note that all the `Info' commands require an uppercase `I'.)
+
+If your file is ok, you will receive a message that says "File
+appears valid". However, if you have a pointer that does not point
+to a node, error messages will be displayed in a buffer called
+`*problems in info file*'.
+
+For example, `Info-validate' was run on a test file that contained
+only the first node of this manual. One of the messages said:
+
+ In node "Overview", invalid Next: Texinfo Mode
+
+This meant that the node called `Overview' had a `Next' pointer that
+did not point to anything (which was true in this case, since the
+test file had only one node in it).
+
+Now suppose we add a node named `Texinfo Mode' to our test case but
+we don't specify a `Previous' for this node. Then we will get the
+following error message:
+
+ In node "Texinfo Mode", should have Previous: Overview
+
+This is because every `Next' pointer should be matched by a
+`Previous' (in the node where the `Next' points) which points back.
+
+`Info-validate' also checks that all menu items and cross-references
+point to actual nodes.
+
+Significantly, `Info-validate' does not work with large files that
+have been split. (Info thinks of a large file as being over 100,000
+bytes, approximately.) In order to use `Info-validate' on a large
+file, you must run `texinfo-format-buffer' with an argument so that
+it does not split the Info file, and then create a tag table.
+
+* Menu:
+
+* Info-Validating a Large File:: Running `Info-validate' on a large file.
+* Splitting:: Splitting a file manually.
+
+
+
+File: texinfo, Node: Info-Validating a Large File, Next: Splitting, Prev: Running Info-Validate, Up: Running Info-Validate
+
+Running `Info-validate' on a Large File.
+----------------------------------------
+
+You can run `Info-validate' only on a single Info file. The command
+will not work on indirect subfiles that are generated when the master
+file is split. If you have a large file (longer than 100,000 bytes),
+you need to run the `texinfo-format-buffer' command in such a way
+that it does not create indirect subfiles. You will also need to
+create a tag table. When you have done this, you can run
+`Info-validate' and look for badly referenced nodes.
+
+After you have validated the node structure, you can rerun
+`texinfo-format-buffer' in the normal way so it will construct the
+tag table and split the file automatically or, you can make the tag
+table and split the file manually.
+
+To prevent the `texinfo-format-buffer' command from splitting a
+Texinfo file into smaller Info files, give a prefix to the `M-x
+texinfo-format-buffer' command:
+
+ C-u M-x texinfo-format-buffer
+
+When you do this, Texinfo will not split the file and will not create
+a tag table for it.
+
+Before you can run `M-x Info-validate' on the Info file, you need to
+create a tag table for it. In order to do this, you first need to
+load the `info' library into Emacs with the following command:
+
+ M-x load-library RET info RET
+
+Then you can give the command:
+
+ M-x Info-tagify
+
+This creates a file which you can validate.
+
+ M-x Info-validate
+
+After you have checked the validity of the nodes, you can either run
+`M-x texinfo-format-buffer' as you would normally, or else tagify and
+split the file manually with the two commands `Info-tagify' and
+`Info-split'.
+
+
+
+File: texinfo, Node: Splitting, Prev: Info-Validating a Large File, Up: Running Info-Validate
+
+Splitting a File Manually
+-------------------------
+
+If the file has more than 100,000 or so bytes in it, you should split
+it or else let the `texinfo-format-buffer' command do it for you
+automatically. (Generally you will let `texinfo-format-buffer' do
+this job for you. *Note Creating an Info File::.)
+
+The split off files are called the indirect subfiles.
+
+Info files are split to save memory. With smaller files, Emacs does
+not have make such a large buffer to hold the information. This way,
+Emacs can save memory.
+
+If the Info file has more than 30 nodes, you should also make a tag
+table for it. *Note Info-Validating a Large File::, for information
+about creating a tag table.
+
+Before running `Info-split', you need to load the `info' library into
+Emacs by giving the command `M-x load-library RET info RET'. After
+you have done this, you can give the two commands:
+
+ M-x Info-tagify
+ M-x Info-split
+
+(Note that the `I' in `Info' is uppercase.)
+
+When you use the `Info-split' command, the buffer is modified into a
+(small) Info file which lists the indirect subfiles. This file
+should be saved in place of the original visited file. The indirect
+subfiles are written in the same directory the original file is in,
+with names generated by appending `-' and a number to the original
+file name.
+
+The primary file still functions as an Info file, but it contains
+just the tag table and a directory of subfiles.
+
+
+
+File: texinfo, Node: Command Syntax, Next: Include Files, Prev: Catching Mistakes, Up: Top
+
+@-Command Syntax
+****************
+
+The character `@' is used to start special Texinfo commands. (It has
+the same meaning that `\' has in plain TeX.) Syntactically, there
+are three classes of @-commands:
+
+1. Non-alphabetic commands: @ followed by a punctuation character.
+ These commands are always part of the text within a paragraph,
+ and never take any argument. The two characters (@ and the
+ other one) are complete in themselves. For example, `@.', `@:',
+ `@{' and `@}'.
+
+2. Alphabetic commands used within a paragraph.
+ These commands have @ followed by a letter or a word, followed
+ by an argument within braces. For example, the command `@dfn'
+ indicates the introductory or defining use of a term; it is used
+ as follows: `In Texinfo, @-commands are @dfn{mark-up} commands.'
+
+3. Alphabetic commands used outside of paragraphs.
+ Each such command occupies an entire line. The line starts with
+ @, followed by the name of the command (a word) such as
+ `@center' or `@cindex'. If no argument is needed, the word is
+ followed by the end of the line. If there is an argument, it is
+ separated from the command name by a space.
+
+Thus, the alphabetic commands fall into two classes that have
+different argument syntax. You cannot tell which class a command
+falls in by the appearance of its name, but you can tell by the
+command's meaning: if it makes sense to use the command together with
+other words as part of a paragraph, the command is in class 2 and
+must be followed by an argument in braces; otherwise, it is in class
+3 and uses the rest of the line as its argument.
+
+The purpose of having different syntax for commands of classes 2 and
+3 is to make the Texinfo file easier to read, and also to help the
+GNU Emacs paragraph and filling commands work properly. There is
+only one exception to this rule: the command `@refill', which is
+always used at the end of a paragraph immediately following the final
+period or other punctuation character. `@refill' takes no argument.
+`@refill' never confuses the Emacs paragraph commands because it
+cannot start at the beginning of a line.
+
+
+
+File: texinfo, Node: Include Files, Next: TeX Input, Prev: Command Syntax, Up: Top
+
+Include Files
+*************
+
+When Info was first created, it was customary to create many small
+Info files on one subject. By doing this, Emacs did not have to make
+a large buffer to hold the whole of a large Info file; instead, Emacs
+allocated just enough memory for the small Info file that was needed
+at the time. This way, Emacs could avoid wasting memory. Include
+files were designed as a way to create a single, large printed manual
+out of several smaller Info files.
+
+However, because large Info files can now be split, include files are
+no longer strictly necessary and they are used infrequently. Most
+often, they are now used in projects where several different people
+are writing different sections of a document simultaneously.
+
+How Include Files Work
+======================
+
+In a Texinfo file, a line of the form `@include `filename'' is
+ignored when the Info file is generated, but in a printed manual it
+causes the contents of the file `filename' to be processed and
+included in the manual. The contents of the file `filename' can be
+ignored by Info because the first file can refer to `filename' with
+menus as well as cross references. In the Info system, all the
+information is, as it were, `in one place'. However, when two
+printed manuals are made from two separate Texinfo files, the two
+manuals are separate, and even if they give each other as references,
+the references are to separate documents. Consequently, you will
+sometimes want to create a comprehensive, printed manual that
+contains all the necessary information together in one place.
+
+`@include' files are special Texinfo files that are used only for
+making such a comprehensive manual. They are listed inside an outer
+file that contains nothing but the beginning and end matter of a
+Texinfo file and a number of `@include' commands listing the included
+files.
+
+An `@include' file--a file that will be listed inside an outer file
+and processed with the `@include' command--should not start with
+`\input texinfo', as that has already been done by the outer file,
+and the character `\' has already been redefined to generate a
+backslash in the output. Instead, an `@include' file usually begins
+with a node; it lacks the beginning and ending of a Texinfo file that
+are described in the chapters on beginning and ending a file. *Note
+Beginning a File::, and *note Ending a File::.
+
+Likewise, an `@include' file should not end with `@bye', since that
+would terminate TeX processing immediately.
+
+Here is an example of a outer Texinfo file with `@include' files
+within it:
+
+ \input texinfo @c -*-texinfo-*-
+ @setfilename include
+ @settitle Include Manual
+
+ @setchapternewpage odd
+ @titlepage
+ @sp 12
+ @center @titlefont{Include Manual}
+ @sp 2
+ @center by Whom Ever
+
+ @page
+ Copyright @copyright{} 1988 Free Software Foundation, Inc.
+ @end titlepage
+
+ @include foo.texinfo
+ @include bar.texinfo
+
+ @unnumbered Concept Index
+ @printindex cp
+
+ @summarycontents
+ @contents
+
+ @bye
+
+
+
+File: texinfo, Node: TeX Input, Next: Sample Permissions, Prev: Include Files, Up: Top
+
+TeX Input Initialization
+************************
+
+You must put an input command on the first line of every Texinfo file
+to tell TeX to use the `texinfo.tex' file when it is processing the
+Texinfo source file. Otherwise TeX will not know what to do with the
+@-commands. (The TeX input command is written as `\input texinfo'.
+*Note First Line::.)
+
+TeX needs to be told where to find the `texinfo.tex' file that you
+have told it to input. The preferred way to do this is to put
+`texinfo.tex' in the default inputs directory, which is the
+`/usr/lib/tex/macros' directory. If this is done (as it usually is
+when GNU Emacs is installed), TeX will find the file and you don't
+have to do anything. Alternatively, you can put `texinfo.tex' in the
+directory in which the Texinfo source file is located.
+
+However, you may want to specify the location of the `\input' file
+yourself. One way to do this is to write the complete path for the
+file after the `\input' command. Another way is to set the
+`TEXINPUTS' environment variable in your `.cshrc' or `.profile' file.
+The `TEXINPUTS' environment variable will tell TeX where to find the
+`texinfo.tex' file and any other file that you might want TeX to use.
+
+Whether you use a `.cshrc' or `.profile' file depends on whether you
+use `csh' or `sh' for your shell command interpreter. When you use
+`csh', it looks to the `.cshrc' file for initialization information,
+and when you use `sh', it looks to the `.profile' file.
+
+In a `.cshrc' file, you could use the following `csh' command sequence:
+
+ setenv TEXINPUTS .:/usr/me/mylib:/usr/lib/tex/macros
+
+In a `.profile' file, you could use the following `sh' command
+sequence:
+
+ TEXINPUTS=.:/usr/me/mylib:/usr/lib/tex/macros
+ export TEXINPUTS
+
+This would cause TeX to look for `\input' file first in the current
+directory, indicated by the `.', then in a hypothetical user's
+`me/mylib' directory, and finally in the system library.
+
+
+
+File: texinfo, Node: Sample Permissions, Next: Command Index, Prev: TeX Input, Up: Top
+
+Standard text for Copying Permissions
+*************************************
+
+Texinfo files should contain sections that tell the readers that they
+have the right to copy and distribute the Info file, the printed
+manual and any accompanying software. This appendix contains the
+standard text of the Free Software Foundation copying permission
+notice. For an example of the text that could be used for the
+Distribution, General Public License and NO WARRANTY sections of a
+document, see the latest version of the ``GNU Emacs Manual''.
+
+The texts of the Free Software Foundation copying permission notice
+in the `@ifinfo' section and in the `@titlepage' section are slightly
+different.
+
+The `@ifinfo' section usually begins with a line that says what the
+file documents. This is what a person looking at the file will first
+read if he or she reads the unprocessed Texinfo file or if he or she
+uses the advanced Info command `g *'. *note info: (info)Expert, for
+more information. (If the reader uses the regular Info commands, he
+or she will usually start reading at the first node and skip this
+first section, which is not in a node.)
+
+In the `@ifinfo' section, the summary sentence should be followed by
+a copyright notice and then by the copying permission notice. One of
+the copying permission paragraphs is enclosed in `@ignore' and `@end
+ignore' commands. This paragraph states that the Texinfo file can be
+processed through TeX and printed, provided the printed manual
+carries the proper copying permission notice. This paragraph is not
+made part of the Info file since it is not relevant to the Info file;
+but it is a mandatory part of the Texinfo file since it permits
+people to process the Texinfo file in TeX.
+
+In the printed manual, the Free Software Foundation copying
+permission notice follows the copyright notice and publishing
+information and is located within the region delineated by the
+`@titlepage' and `@end titlepage' commands. The copying permission
+notice is exactly the same as the notice in the `@ifinfo' section
+except that the paragraph enclosed in `@ignore' and `@end ignore'
+commands is not part of the notice.
+
+To make it simpler to copy the permission notice into each section of
+the Texinfo file, the complete permission notices for each section
+are reproduced in full below even though most of the information is
+redundant.
+
+Note that you my have to specify the correct name of a section
+mentioned in the permission notice. For example, in the ``GDB
+Manual'', the name of the section referring to the General Public
+License is called the "GDB General Public License", but in the sample
+shown below, that section is referred to generically as the "General
+Public License".
+
+* Menu:
+
+* Ifinfo Permissions::
+* Titlepage Permissions::
+
+
+
+File: texinfo, Node: Ifinfo Permissions, Next: Titlepage Permissions, Prev: Sample Permissions, Up: Sample Permissions
+
+Ifinfo Copying Permissions
+==========================
+
+In the `@ifinfo' section of the Texinfo file, the standard Free
+Software Foundation permission notices reads as follows:
+
+ This file documents ...
+
+ Copyright 1988 Free Software Foundation, Inc.
+
+ Permission is granted to make and distribute verbatim copies of
+ this manual provided the copyright notice and this permission notice
+ are preserved on all copies.
+
+ @ignore
+ Permission is granted to process this file through TeX and print the
+ results, provided the printed document carries a copying permission
+ notice identical to this one except for the removal of this paragraph
+ (this paragraph not being relevant to the printed manual).
+
+ @end ignore
+ Permission is granted to copy and distribute modified versions of this
+ manual under the conditions for verbatim copying, provided also that the
+ sections entitled ``Distribution'' and ``General Public License'' are
+ included exactly as in the original, and provided that the entire
+ resulting derived work is distributed under the terms of a permission
+ notice identical to this one.
+
+ Permission is granted to copy and distribute translations of this manual
+ into another language, under the above conditions for modified versions,
+ except that the sections entitled ``Distribution'' and ``General Public
+ License'' may be included in a translation approved by the author instead
+ of in the original English.
+
+
+
+File: texinfo, Node: Titlepage Permissions, Prev: Ifinfo Permissions, Up: Sample Permissions
+
+Titlepage Copying Permissions
+=============================
+
+In the `@titlepage' section of the Texinfo file, the standard Free
+Software Foundation copying permission notices follows the copyright
+notice and publishing information. The standard phrasing is:
+
+ Permission is granted to make and distribute verbatim copies of
+ this manual provided the copyright notice and this permission notice
+ are preserved on all copies.
+
+ Permission is granted to copy and distribute modified versions of this
+ manual under the conditions for verbatim copying, provided also that the
+ sections entitled ``Distribution'' and ``General Public License'' are
+ included exactly as in the original, and provided that the entire
+ resulting derived work is distributed under the terms of a permission
+ notice identical to this one.
+
+ Permission is granted to copy and distribute translations of this manual
+ into another language, under the above conditions for modified versions,
+ except that the sections entitled ``Distribution'' and ``General Public
+ License'' may be included in a translation approved by the author instead
+ of in the original English.
+
+
+
+File: texinfo, Node: Command Index, Next: Concept Index, Prev: Sample Permissions, Up: Top
+
+Command Index
+*************
+
+(When used in a Texinfo file, @-commands are preceded by an `@'.)
+
+* Menu:
+
+* *: Line Breaks.
+* TeX: Tex.
+* appendix: Unnumbered and Appendix.
+* appendixsec: Section.
+* appendixsubsec: Subsection.
+* appendixsubsubsec: Subsubsection.
+* asterisk: Line Breaks.
+* at-sign colons: Insert Colon.
+* at-sign periods: Insert Period.
+* at-signs: Inserting An Atsign.
+* b (bold font): Fonts.
+* br (paragraph breaks): Br.
+* bullet: Bullet.
+* bye: Ending a File.
+* center: Center.
+* chapter: Chapter.
+* cite: Cite.
+* code: Code.
+* copyright: Copyright & Printed Permissions.
+* ctrl: Ctrl.
+* dfn: Dfn.
+* display: Display.
+* dots: Dots.
+* emph: Emph and Strong.
+* end: Lists and Tables.
+* end: Quotations and Examples.
+* enumerate: Enumerate.
+* example: Example.
+* file: File.
+* filll: Copyright & Printed Permissions.
+* group: Group.
+* i (italic font): Fonts.
+* ifinfo: Conditionals.
+* iftex: Conditionals.
+* inforef: Inforef.
+* item: Itemize.
+* item: Table.
+* itemize: Itemize.
+* itemx: Itemx.
+* kbd: Kbd.
+* key: Key.
+* left-braces: Insert Left Brace.
+* menu: Menu.
+* need: Need.
+* node: Structuring.
+* noindent: Noindent.
+* page: Page.
+* pxref: Pxref.
+* quotation: Quotation.
+* refill: Refill.
+* right-braces: Insert Left Brace.
+* samp: Samp.
+* section: Section.
+* setchapternewpage: Setchapternewpage.
+* setfilename: Setfilename.
+* settitle: Settitle.
+* sp (line spacing): Sp.
+* start-of-header: Start-of-Header.
+* strong: Emph and Strong.
+* subsection: Subsection.
+* subsubsection: Subsubsection.
+* t (typewriter font): Fonts.
+* table: Table.
+* texindex (for sorting indices): Printing Hardcopy.
+* texinfo-format-buffer: Creating an Info File.
+* texinfo-format-region: Info on a Region.
+* texinfo-show-structure: Using texinfo-show-structure.
+* titlefont: Titlepage.
+* titlepage: Titlepage.
+* unnumbered: Unnumbered and Appendix.
+* unnumberedsec: Section.
+* unnumberedsubsec: Subsection.
+* unnumberedsubsubsec: Subsubsection.
+* var: Var.
+* vskip: Copyright & Printed Permissions.
+* w (preventing a line break): W.
+* xref: Xref.
+
+
+
+
+File: texinfo, Node: Concept Index, Prev: Command Index, Up: Top
+
+Concept Index
+*************
+
+* Menu:
+
+* @-Command Syntax: Command Syntax.
+* Badly referenced nodes: Running Info-Validate.
+* Beginning a Texinfo file: Beginning a File.
+* Beginning line of a Texinfo file: First Line.
+* Braces, inserting: Braces Atsigns Periods.
+* Breaks in a line: Line Breaks.
+* Breaks in a paragraph: Br.
+* Bullets, inserting: Dots Bullets Tex.
+* Catching errors with Info Formatting: Debugging with Info.
+* Catching errors with TeX Formatting: Debugging with Tex.
+* Catching mistakes: Catching Mistakes.
+* Centering a line: Center.
+* Chapter structuring: Structuring.
+* Characteristics of the Info file: Info File.
+* Characteristics, printed manual: Printed Manual.
+* Checking for badly referenced nodes: Running Info-Validate.
+* Combining Indices: Combining Indices.
+* Commands to insert single characters: Braces Atsigns Periods.
+* Commands, inserting them: Inserting.
+* Commands, specifying them within text: Specifying.
+* Compile command for formatting: Compile-Command.
+* Conditionals: Conditionals.
+* Contents, Table of: Contents.
+* Conventions, syntactic: Conventions.
+* Copying permissions: Sample Permissions.
+* Copyright: Copyright & Printed Permissions.
+* Copyright page: Titlepage & Copyright Page.
+* Correcting mistakes: Catching Mistakes.
+* Creating an on-line Info file: Creating an Info File.
+* Creating indices: Indices.
+* Cross references: Cross References.
+* Cross references using inforef: Inforef.
+* Cross references using pxref: Pxref.
+* Cross references using xref: Xref.
+* Debugger, using the Emacs Lisp: Using the Emacs Lisp Debugger.
+* Debugging the Texinfo structure: Catching Mistakes.
+* Debugging with Info Formatting: Debugging with Info.
+* Debugging with TeX Formatting: Debugging with Tex.
+* Defining the entries of an index: Index Entries.
+* Definitions, specifying them within text: Specifying.
+* Dir directory for Info installation: Installing an Info File.
+* Display: Display.
+* Distribution: License and Distribution.
+* Dots, inserting: Dots Bullets Tex.
+* Dots, inserting: Dots.
+* Emacs: Texinfo Mode.
+* Emacs Lisp debugger: Using the Emacs Lisp Debugger.
+* Emphasizing text: Emphasis.
+* Ending a Texinfo file: Ending a File.
+* Entries for an index: Index Entries.
+* Enumerate: Enumerate.
+* Examples: Example.
+* Examples: Quotations and Examples.
+* File beginning: Beginning a File.
+* File ending: Ending a File.
+* File structure, showing it: Showing the Structure.
+* Files, specifying them within text: Specifying.
+* Finding badly referenced nodes: Running Info-Validate.
+* First line of a Texinfo file: First Line.
+* Formatting a file for Info: Creating an Info File.
+* Formatting paragraphs: Formatting Paragraphs.
+* Formatting requirements: Requirements.
+* Formatting with the compile command: Compile-Command.
+* Frequently used commands, inserting them: Inserting.
+* GNU Emacs: Texinfo Mode.
+* General syntactic conventions: Conventions.
+* Generating menus with indices: Printing Indices & Menus.
+* Group: Group.
+* Hardcopy, printing it: Printing Hardcopy.
+* Header for Texinfo files: Header.
+* Highlighting: Specifying.
+* Holding text together vertically: Group.
+* Ifinfo: Conditionals.
+* Ifinfo permissions: Ifinfo Permissions.
+* Iftex: Conditionals.
+* Include files: Include Files.
+* Index entries: Index Entries.
+* Indices: Indices.
+* Indices, combining them: Combining Indices.
+* Indices, printing: Printing Indices & Menus.
+* Indices, sorting: Printing Hardcopy.
+* Indices, two letter names: Combining Indices.
+* Indirect subfiles: Creating an Info File.
+* Info file characteristics: Info File.
+* Info file installation: Installing an Info File.
+* Info file requirement for @setfilename: Setfilename.
+* Info file, splitting manually: Splitting.
+* Info validating a large file: Info-Validating a Large File.
+* Info, creating an on-line file: Creating an Info File.
+* Info, formatting on a region: Info on a Region.
+* Info-validate, running the command: Running Info-Validate.
+* Inforef for cross references: Inforef.
+* Inserting braces, @ and periods: Braces Atsigns Periods.
+* Inserting dots: Dots.
+* Inserting frequently used commands: Inserting.
+* Installing an Info file: Installing an Info File.
+* Itemize: Itemize.
+* Itemx: Itemx.
+* License agreement: License and Distribution.
+* Line breaks: Line Breaks.
+* Line breaks, preventing: W.
+* Line spacing: Sp.
+* Lists and tables, making them: Lists and Tables.
+* Local variables: Compile-Command.
+* Looking for badly referenced nodes: Running Info-Validate.
+* Making a printed manual: Printing Hardcopy.
+* Making a tag table manually: Info-Validating a Large File.
+* Making cross references: Cross References.
+* Making lists and tables: Lists and Tables.
+* Marking text within a paragraph: Marking Text.
+* Master menu: Top Node.
+* Menus: Menu.
+* Menus generated with indices: Printing Indices & Menus.
+* Mistakes, catching: Catching Mistakes.
+* Mode, using Texinfo: Texinfo Mode.
+* Names for indices: Combining Indices.
+* Need: Need.
+* Node and chapter structuring: Structuring.
+* Node structuring: Structuring.
+* Nodes, catching mistakes: Catching Mistakes.
+* Nodes, checking for badly referenced nodes: Running Info-Validate.
+* Nodes, correcting mistakes: Catching Mistakes.
+* Occur, using the command: Using Occur.
+* Overview of Texinfo: Overview.
+* Page breaks: Page.
+* Pages, starting odd: Setchapternewpage.
+* Paragraph breaks: Br.
+* Paragraphs, formatting: Formatting Paragraphs.
+* Periods, inserting: Braces Atsigns Periods.
+* Permissions: Sample Permissions.
+* Permissions, printed: Copyright & Printed Permissions.
+* Preface: License and Distribution.
+* Preventing indentation in the printed text: Refilling & Noindent.
+* Printed manual characteristics: Printed Manual.
+* Printed permissions: Copyright & Printed Permissions.
+* Printing an index: Printing Indices & Menus.
+* Printing hardcopy: Printing Hardcopy.
+* Problems, catching: Catching Mistakes.
+* Pxref for cross references: Pxref.
+* Quotations: Quotation.
+* Quotations: Quotations and Examples.
+* References: Cross References.
+* Refilling paragraphs automatically: Refilling & Noindent.
+* Requirements for formatting: Requirements.
+* Running Info: Creating an Info File.
+* Running Info on a region: Info on a Region.
+* Running Info-validate: Running Info-Validate.
+* Running Info-validate on a large file: Info-Validating a Large File.
+* Sample texinfo file: Short Sample.
+* Setfilename command: Setfilename.
+* Showing the structure of a file: Using texinfo-show-structure.
+* Showing the structure of a file: Showing the Structure.
+* Single characters, commands to insert: Braces Atsigns Periods.
+* Sorting indices: Printing Hardcopy.
+* Spaces from line to line: Sp.
+* Special typesetting commands: Dots Bullets Tex.
+* Specifying commands, files and the like: Specifying.
+* Splitting an Info file manually: Splitting.
+* Starting chapters: Setchapternewpage.
+* Structure of Texinfo, catching mistakes: Catching Mistakes.
+* Structure of a file, showing it: Showing the Structure.
+* Structuring of nodes and chapters: Structuring.
+* Syntactic conventions: Conventions.
+* TEXINPUTS environment variable: TeX Input.
+* Table of contents: Contents.
+* Tables and lists, making them: Lists and Tables.
+* Tables, making two-column: Table.
+* Tag table, making manually: Info-Validating a Large File.
+* TeX Input Initialization: TeX Input.
+* TeX commands, using them: Using Tex Commands.
+* TeX-logo, inserting: Dots Bullets Tex.
+* Texinfo file beginning: Beginning a File.
+* Texinfo file ending: Ending a File.
+* Texinfo file header: Header.
+* Texinfo file structure, showing it: Showing the Structure.
+* Texinfo mode: Texinfo Mode.
+* Texinfo overview: Overview.
+* Titlepage: Titlepage.
+* Titlepage: Titlepage & Copyright Page.
+* Titlepage permissions: Titlepage Permissions.
+* Top node: Top Node.
+* Two letter names for indices: Combining Indices.
+* Typesetting commands for dots and the like: Dots Bullets Tex.
+* Using TeX commands: Using Tex Commands.
+* Using occur: Using Occur.
+* Using texinfo-show-structure to catch mistakes: Using texinfo-show-structure.
+* Using the Emacs Lisp debugger: Using the Emacs Lisp Debugger.
+* Validating a large file: Info-Validating a Large File.
+* Vertically holding text together: Group.
+* Xref for cross references: Xref.
+* cshrc initialization file: TeX Input.
+* end-of-header: End-of-Header.
+* profile initialization file: TeX Input.
+* start-of-header: Start-of-Header.
+* texinfo-show-structure for catching mistakes: Using texinfo-show-structure.
+
+
+
diff --git a/info/vip b/info/vip
new file mode 100644
index 00000000000..53d344fb2d6
--- /dev/null
+++ b/info/vip
@@ -0,0 +1,73 @@
+Info file ../info/vip, produced by Makeinfo, -*- Text -*- from input
+file vip.texinfo.
+
+Distribution
+************
+
+Copyright (C) 1987 Masahiko Sato.
+
+Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of
+this manual under the conditions for verbatim copying, provided that
+the entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this
+manual into another language, under the same conditions as for
+modified versions.
+
+Indirect:
+vip-1: 708
+vip-2: 49470
+
+Tag Table:
+(Indirect)
+Node: Top710
+Node: Survey1688
+Node: Basic Concepts2172
+Node: Loading VIP3787
+Node: Modes in VIP4518
+Node: Emacs Mode7052
+Node: Vi Mode7405
+Node: Insert Mode7711
+Node: Differences from Vi8328
+Node: Undoing9320
+Node: Changing9675
+Node: Searching10283
+Node: z Command10994
+Node: Counts11323
+Node: Marking11823
+Node: Region Commands12321
+Node: New Commands12988
+Node: New Bindings15740
+Node: Window Commands17903
+Node: Buffer Commands18366
+Node: File Commands18847
+Node: Misc Commands19210
+Node: Vi Commands19622
+Node: Numeric Arguments20383
+Node: Important Keys20872
+Node: Buffers and Windows22610
+Node: Files24818
+Node: Viewing the Buffer28040
+Node: Mark Commands29924
+Node: Motion Commands30773
+Node: Searching and Replacing36297
+Node: Modifying Commands38569
+Node: Delete Commands39996
+Node: Yank Commands41690
+Node: Put Back Commands42565
+Node: Change Commands44013
+Node: Repeating and Undoing Modifications45031
+Node: Other Vi Commands45844
+Node: Commands in Insert Mode49472
+Node: Ex Commands51530
+Node: Ex Command Reference52697
+Node: Customization59179
+Node: Customizing Constants59594
+Node: Customizing Key Bindings60918
+
+End Tag Table
diff --git a/info/vip-1 b/info/vip-1
new file mode 100644
index 00000000000..33c187cb25b
--- /dev/null
+++ b/info/vip-1
@@ -0,0 +1,1514 @@
+Info file ../info/vip, produced by Makeinfo, -*- Text -*- from input
+file vip.texinfo.
+
+Distribution
+************
+
+Copyright (C) 1987 Masahiko Sato.
+
+Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of
+this manual under the conditions for verbatim copying, provided that
+the entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this
+manual into another language, under the same conditions as for
+modified versions.
+
+
+
+File: vip, Node: Top, Next: Survey, Up: (DIR)
+
+VIP ***
+
+VIP is a Vi emulating package written in Emacs Lisp. VIP implements
+most Vi commands including Ex commands. It is therefore hoped that
+this package will enable you to do Vi style editing under the
+powerful GNU Emacs environment. This info file describes the usage
+of VIP assuming that you are fairly accustomed to Vi but not so much
+with Emacs. Also we will concentrate mainly on differences from Vi,
+especially features unique to VIP.
+
+It is recommended that you read nodes on survey and on customization
+before you start using VIP. Other nodes may be visited as needed.
+
+Comments and bug reports are welcome. Please send messages to
+`ms@Sail.Stanford.Edu' if you are outside of Japan and to
+`masahiko@sato.riec.tohoku.junet' if you are in Japan.
+
+* Menu:
+
+* Survey:: A survey of VIP.
+* Vi Commands:: Details of Vi commands.
+* Ex Commands:: Details of Ex commands.
+* Customization:: How to customize VIP.
+
+
+
+File: vip, Node: Survey, Next: Basic Concepts, Prev: Top, Up: Top
+
+A Survey of VIP
+***************
+
+In this chapter we describe basics of VIP with emphasis on the
+features not found in Vi and on how to use VIP under GNU Emacs.
+
+* Menu:
+
+* Basic Concepts:: Basic concepts in Emacs.
+* Loading VIP:: How to load VIP automatically.
+* Modes in VIP:: VIP has three modes, which are orthogonal to modes
+ in Emacs.
+* Differences from Vi:: Differences of VIP from Vi is explained.
+
+
+
+File: vip, Node: Basic Concepts, Next: Loading VIP, Prev: Survey, Up: Survey
+
+Basic Concepts
+==============
+
+We begin by explaining some basic concepts of Emacs. These concepts
+are explained in more detail in the GNU Emacs Manual.
+
+Conceptually, a "buffer" is just a string of ASCII characters and two
+special characters PNT ("point") and MRK ("mark") such that the
+character PNT occurs exactly once and MRK occurs at most once. The
+"text" of a buffer is obtained by deleting the occurrences of PNT and
+MRK. If, in a buffer, there is a character following PNT then we say
+that point is "looking at" the character; otherwise we say that point
+is "at the end of buffer". PNT and MRK are used to indicate
+positions in a buffer and they are not part of the text of the
+buffer. If a buffer contains a MRK then the text between MRK and PNT
+is called the "region" of the buffer.
+
+Emacs provides (multiple) "windows" on the screen, and you can see
+the content of a buffer through the window associated with the
+buffer. The cursor of the screen is always positioned on the
+character after PNT.
+
+A "keymap" is a table that records the bindings between characters
+and command functions. There is the "global keymap" common to all
+the buffers. Each buffer has its "local keymap" that determines the
+"mode" of the buffer. Local keymap overrides global keymap, so that
+if a function is bound to some key in the local keymap then that
+function will be executed when you type the key. If no function is
+bound to a key in the local map, however, the function bound to the
+key in the global map becomes in effect.
+
+
+
+File: vip, Node: Loading VIP, Next: Modes in VIP, Prev: Basic Concepts, Up: Survey
+
+Loading VIP
+===========
+
+The recommended way to load VIP automatically is to include the line:
+
+ (load "vip")
+
+in your `.emacs' file. The `.emacs' file is placed in your home
+directory and it will be executed every time you invoke Emacs. If
+you wish to be in vi mode whenver Emacs starts up, you can include
+the following line in your `.emacs' file instead of the above line:
+
+ (setq term-setup-hook 'vip-mode)
+
+(*Note Vi Mode::, for the explanation of vi mode.)
+
+Even if your `.emacs' file does not contain any of the above lines,
+you can load VIP and enter vi mode by typing the following from
+within Emacs.
+
+ M-x vip-mode
+
+
+
+File: vip, Node: Modes in VIP, Next: Emacs Mode, Prev: Loading VIP, Up: Survey
+
+Modes in VIP
+============
+
+Loading VIP has the effect of globally binding `C-z' (`Control-z') to
+the function `vip-change-mode-to-vi'. The default binding of `C-z' in
+GNU Emacs is `suspend-emacs', but, you can also call `suspend-emacs'
+by typing `C-x C-z'. Other than this, all the key bindings of Emacs
+remain the same after loading VIP.
+
+Now, if you hit `C-z', the function `vip-change-mode-to-vi' will be
+called and you will be in "vi mode". (Some major modes may locally
+bind `C-z' to some special functions. In such cases, you can call
+`vip-change-mode-to-vi' by `execute-extended-command' which is
+invoked by `M-x'. Here `M-x' means `Meta-x', and if your terminal
+does not have a META key you can enter it by typing `ESC x'. The
+same effect can also be achieve by typing `M-x vip-mode'.)
+
+You can observe the change of mode by looking at the "mode line".
+For instance, if the mode line is:
+
+ -----Emacs: *scratch* (Lisp Interaction)----All------------
+
+then it will change to:
+
+ -----Vi: *scratch* (Lisp Interaction)----All------------
+
+Thus the word `Emacs' in the mode line will change to `Vi'.
+
+You can go back to the original "emacs mode" by typing `C-z' in vi
+mode. Thus `C-z' toggles between these two modes.
+
+Note that modes in VIP exist orthogonally to modes in Emacs. This
+means that you can be in vi mode and at the same time, say, shell mode.
+
+Vi mode corresponds to Vi's command mode. From vi mode you can enter
+"insert mode" (which corresponds to Vi's insert mode) by usual Vi
+command keys like `i', `a', `o' ... etc.
+
+In insert mode, the mode line will look like this:
+
+ -----Insert *scratch* (Lisp Interaction)----All------------
+
+You can exit from insert mode by hitting ESC key as you do in Vi.
+
+That VIP has three modes may seem very complicated, but in fact it is
+not so. VIP is implemented so that you can do most editing remaining
+only in the two modes for Vi (that is vi mode and insert mode).
+
+The figure below shows the transition of three modes in VIP.
+
+
+
+ === C-z ==> == i,o ... ==>
+ emacs mode vi mode insert mode
+ <== X-z === <=== ESC ====
+
+* Menu:
+
+* Emacs Mode:: This is the mode you should know better.
+* Vi Mode:: Vi commands are executed in this mode.
+* Insert Mode:: You can enter text, and also can do editing if you
+ know enough Emacs commands.
+
+
+
+File: vip, Node: Emacs Mode, Next: Vi Mode, Prev: Modes in VIP, Up: Modes in VIP
+
+Emacs Mode
+----------
+
+You will be in this mode just after you loaded VIP. You can do all
+normal Emacs editing in this mode. Note that the key `C-z' is
+globally bound to `vip-change-mode-to-vi'. So, if you type `C-z' in
+this mode then you will be in vi mode.
+
+
+
+File: vip, Node: Vi Mode, Next: Insert Mode, Prev: Emacs Mode, Up: Modes in VIP
+
+Vi Mode
+-------
+
+This mode corresponds to Vi's command mode. Most Vi commands work as
+they do in Vi. You can go back to emacs mode by typing `C-z'. You
+can enter insert mode, just as in Vi, by typing `i', `a' etc.
+
+
+
+File: vip, Node: Insert Mode, Next: Differences from Vi, Prev: Vi Mode, Up: Modes in VIP
+
+Insert Mode
+-----------
+
+The key bindings in this mode is the same as in the emacs mode except
+for the following 4 keys. So, you can move around in the buffer and
+change its content while you are in insert mode.
+
+`ESC'
+ This key will take you back to vi mode.
+
+`C-h'
+ Delete previous character.
+
+`C-w'
+ Delete previous word.
+
+`C-z'
+ Typing this key has the same effect as typing ESC in emacs mode.
+ Thus typing `C-z x' in insert mode will have the same effect as
+ typing `ESC x' in emacs mode.
+
+
+
+File: vip, Node: Differences from Vi, Next: Undoing, Prev: Insert Mode, Up: Survey
+
+Differences from Vi
+===================
+
+The major differences from Vi are explained below.
+
+* Menu:
+
+* Undoing:: You can undo more in VIP.
+* Changing:: Commands for changing the text.
+* Searching:: Search commands.
+* z Command:: You can now use zH, zM and zL as well as z- etc.
+* Counts:: Some Vi commands which do not accept a count now
+ accept one.
+* Marking:: You can now mark the current point, beginning of
+ the buffer etc.
+* Region Commands:: You can now give a region as an argument for delete
+ commands etc.
+* New Commands:: Some new commands not available in Vi are added.
+* New Bindings:: Bindings of some keys are changed for the
+ convenience of editing under Emacs.
+* Window Commands:: Commands for moving among windows etc.
+* Buffer Commands:: Commands for selecting buffers etc.
+* File Commands:: Commands for visiting files etc.
+* Misc Commands:: Other useful commands.
+
+
+
+File: vip, Node: Undoing, Next: Changing, Prev: Differences from Vi, Up: Differences from Vi
+
+Undoing
+-------
+
+You can repeat undoing by the `.' key. So, `u' will undo a single
+change, while `u . . .', for instance, will undo 4 previous changes.
+Undo is undoable as in Vi. So the content of the buffer will be the
+same before and after `u u'.
+
+
+
+File: vip, Node: Changing, Next: Searching, Prev: Undoing, Up: Differences from Vi
+
+Changing
+--------
+
+Some commands which change a small number of characters are executed
+slightly differently. Thus, if point is at the beginning of a word
+`foo' and you wished to change it to `bar' by typing `c w', then VIP
+will prompt you for a new word in the minibuffer by the prompt `foo
+=> '. You can then enter `bar' followed by RET or ESC to complete
+the command. Before you enter RET or ESC you can abort the command
+by typing `C-g'. In general, you can abort a partially formed
+command by typing `C-g'.
+
+
+
+File: vip, Node: Searching, Next: z Command, Prev: Changing, Up: Differences from Vi
+
+Searching
+---------
+
+As in Vi, searching is done by `/' and `?'. The string will be
+searched literally by default. To invoke a regular expression
+search, first execute the search command `/' (or `?') with empty
+search string. (I.e, type `/' followed by RET.) A search for empty
+string will toggle the search mode between vanilla search and regular
+expression search. You cannot give an offset to the search string.
+(It is a limitation.) By default, search will wrap around the buffer
+as in Vi. You can change this by rebinding the variable
+`vip-search-wrap-around'. *Note Customization::, for how to do this.
+
+
+
+File: vip, Node: z Command, Next: Counts, Prev: Searching, Up: Differences from Vi
+
+z Command
+---------
+
+For those of you who cannot remember which of `z' followed by RET,
+`.' and `-' do what. You can also use `z' followed by `H', `M' and
+`L' to place the current line in the Home (Middle, and Last) line of
+the window.
+
+
+
+File: vip, Node: Counts, Next: Marking, Prev: z Command, Up: Differences from Vi
+
+Counts
+------
+
+Some Vi commands which do not accept a count now accept one
+
+`p'
+`P'
+ Given counts, text will be yanked (in Vi's sense) that many
+ times. Thus `3 p' is the same as `p p p'.
+
+`o'
+`O'
+ Given counts, that many copies of text will be inserted. Thus `o
+ a b c ESC' will insert 3 lines of `abc' below the current line.
+
+`/'
+`?'
+ Given a count N, N-th occurrence will be searched.
+
+
+
+File: vip, Node: Marking, Next: Region Commands, Prev: Counts, Up: Differences from Vi
+
+Marking
+-------
+
+Typing an `m' followed by a lower case character CH marks the point
+to the register named CH as in Vi. In addition to these, we have
+following key bindings for marking.
+
+`m <'
+ Set mark at the beginning of buffer.
+
+`m >'
+ Set mark at the end of buffer.
+
+`m .'
+ Set mark at point (and push old mark on mark ring).
+
+`m ,'
+ Jump to mark (and pop mark off the mark ring).
+
+
+
+File: vip, Node: Region Commands, Next: New Commands, Prev: Marking, Up: Differences from Vi
+
+Region Commands
+---------------
+
+Vi operators like `d', `c' etc. are usually used in combination with
+motion commands. It is now possible to use current region as the
+argument to these operators. (A "region" is a part of buffer
+delimited by point and mark.) The key `r' is used for this purpose.
+Thus `d r' will delete the current region. If `R' is used instead of
+`r' the region will first be enlarged so that it will become the
+smallest region containing the original region and consisting of
+whole lines. Thus `m . d R' will have the same effect as `d d'.
+
+
+
+File: vip, Node: New Commands, Next: New Bindings, Prev: Region Commands, Up: Differences from Vi
+
+Some New Commands
+-----------------
+
+Note that the keys below (except for `R') are not used in Vi.
+
+`C-a'
+ Move point to the beginning of line.
+
+`C-n'
+ If you have two or more windows in the screen, this key will
+ move point to the next window.
+
+`C-o'
+ Insert a newline and leave point before it, and then enter
+ insert mode.
+
+`C-r'
+ Backward incremental search.
+
+`C-s'
+ Forward incremental search.
+
+`C-c'
+`C-x'
+`ESC'
+ These keys will exit from vi mode and return to emacs mode
+ temporarily. If you hit one of these keys, Emacs will be in
+ emacs mode and will believe that you hit that key in emacs mode.
+ For example, if you hit `C-x' followed by `2', then the current
+ window will be split into 2 and you will be in vi mode again.
+
+`\'
+ Escape to emacs mode. Hitting `\' will take you to emacs mode,
+ and you can execute a single Emacs command. After executing the
+ Emacs command you will be in vi mode again. You can give a
+ count before typing `\'. Thus `5 \ *', as well as `\ C-u 5 *',
+ will insert `*****' before point. Similarly `1 0 \ C-p' will
+ move the point 10 lines above the current line.
+
+`K'
+ Kill current buffer if it is not modified. Useful when you
+ selected a buffer which you did not want.
+
+`Q'
+`R'
+ `Q' is for query replace and `R' is for replace. By default,
+ string to be replaced are treated literally. If you wish to do
+ a regular expression replace, first do replace with empty string
+ as the string to be replaced. In this way, you can toggle
+ between vanilla and regular expression replacement.
+
+`v'
+`V'
+ These keys are used to Visit files. `v' will switch to a buffer
+ visiting file whose name can be entered in the minibuffer. `V'
+ is similar, but will use window different from the current window.
+
+`#'
+ If followed by a certain character CH, it becomes an operator
+ whose argument is the region determined by the motion command
+ that follows. Currently, CH can be one of `c', `C', `g', `q'
+ and `s'.
+
+`# c'
+ Change upper case characters in the region to lower case
+ (`downcase-region').
+
+`# C'
+ Change lower case characters in the region to upper case. For
+ instance, `# C 3 w' will capitalize 3 words from the current
+ point (`upcase-region').
+
+`# g'
+ Execute last keyboard macro for each line in the region
+ (`vip-global-execute').
+
+`# q'
+ Insert specified string at the beginning of each line in the
+ region (`vip-quote-region').
+
+`# s'
+ Check spelling of words in the region (`spell-region').
+
+`*'
+ Call last keyboard macro.
+
+
+
+File: vip, Node: New Bindings, Next: Window Commands, Prev: New Commands, Up: Differences from Vi
+
+New Key Bindings
+----------------
+
+In VIP the meanings of some keys are entirely different from Vi.
+These key bindings are done deliberately in the hope that editing
+under Emacs will become easier. It is however possible to rebind
+these keys to functions which behave similarly as in Vi. *Note
+Customizing Key Bindings::, for details.
+
+`C-g'
+`g'
+ In Vi, `C-g' is used to get information about the file
+ associated to the current buffer. Here, `g' will do that, and
+ `C-g' is used to abort a command (this is for compatibility with
+ emacs mode.)
+
+`SPC'
+`RET'
+ Now these keys will scroll up and down the text of current window.
+ Convenient for viewing the text.
+
+`s'
+`S'
+ They are used to switch to a specified buffer. Useful for
+ switching to already existing buffer since buffer name
+ completion is provided. Also a default buffer will be given as
+ part of the prompt, to which you can switch by just typing RET
+ key. `s' is used to select buffer in the current window, while
+ `S' selects buffer in another window.
+
+`C'
+`X'
+ These keys will exit from vi mode and return to emacs mode
+ temporarily. If you type `C' (`X'), Emacs will be in emacs mode
+ and will believe that you have typed `C-c' (`C-x', resp.) in
+ emacs mode. Moreover, if the following character you type is an
+ upper case letter, then Emacs will believe that you have typed
+ the corresponding control character. You will be in vi mode
+ again after the command is executed. For example, typing `X S'
+ in vi mode is the same as typing `C-x C-s' in emacs mode. You
+ get the same effect by typing `C-x C-s' in vi mode, but the idea
+ here is that you can execute useful Emacs commands without
+ typing control characters. For example, if you hit `X' (or
+ `C-x') followed by `2', then the current window will be split
+ into 2 and you will be in vi mode again.
+
+In addition to these, `ctl-x-map' is slightly modified:
+
+`X 3'
+`C-x 3'
+ This is equivalent to `C-x 1 C-x 2' (1 + 2 = 3).
+
+
+
+File: vip, Node: Window Commands, Next: Buffer Commands, Prev: New Bindings, Up: Differences from Vi
+
+Window Commands
+---------------
+
+In this and following subsections, we give a summary of key bindings
+for basic functions related to windows, buffers and files.
+
+`C-n'
+ Switch to next window.
+
+`X 1'
+`C-x 1'
+ Delete other windows.
+
+`X 2'
+`C-x 2'
+ Split current window into two windows.
+
+`X 3'
+`C-x 3'
+ Show current buffer in two windows.
+
+
+
+File: vip, Node: Buffer Commands, Next: File Commands, Prev: Window Commands, Up: Differences from Vi
+
+Buffer Commands
+---------------
+
+`s'
+ Switch to the specified buffer in the current window
+ (`vip-switch-to-buffer').
+
+`S'
+ Switch to the specified buffer in another window
+ (`vip-switch-to-buffer-other-window').
+
+`K'
+ Kill the current buffer if it is not modified.
+
+`X S'
+`C-x C-s'
+ Save the current buffer in the file associated to the buffer.
+
+
+
+File: vip, Node: File Commands, Next: Misc Commands, Prev: Buffer Commands, Up: Differences from Vi
+
+File Commands
+-------------
+
+`v'
+ Visit specified file in the current window.
+
+`V'
+ Visit specified file in another window.
+
+`X W'
+`C-x C-w'
+ Write current buffer into the specified file.
+
+`X I'
+`C-x C-i'
+ Insert specified file at point.
+
+
+
+File: vip, Node: Misc Commands, Next: Vi Commands, Prev: File Commands, Up: Differences from Vi
+
+Miscellaneous Commands
+----------------------
+
+`X ('
+`C-x ('
+ Start remembering keyboard macro.
+
+`X )'
+`C-x )'
+ Finish remembering keyboard macro.
+
+`*'
+ Call last remembered keyboard macro.
+
+`X Z'
+`C-x C-z'
+ Suspend Emacs.
+
+`Z Z'
+ Exit Emacs.
+
+`Q'
+ Query replace.
+
+`R'
+ Replace.
+
+
+
+File: vip, Node: Vi Commands, Next: Numeric Arguments, Prev: Misc Commands, Up: Top
+
+Vi Commands
+***********
+
+This chapter describes Vi commands other than Ex commands implemented
+in VIP. Except for the last section which discusses insert mode, all
+the commands described in this chapter are to be used in vi mode.
+
+* Menu:
+
+* Numeric Arguments:: Many commands accept numeric arguments
+* Important Keys:: Some very important keys.
+* Buffers and Windows:: Commands for handling buffers and windows.
+* Files:: Commands for handling files.
+* Viewing the Buffer:: How you can view the current buffer.
+* Mark Commands:: Marking positions in a buffer.
+* Motion Commands:: Commands for moving point.
+* Modifying Commands:: Commands for modifying the buffer.
+
+
+
+File: vip, Node: Numeric Arguments, Next: Important Keys, Prev: Vi Commands, Up: Vi Commands
+
+Numeric Arguments
+=================
+
+Most Vi commands accept a "numeric argument" which can be supplied as
+a prefix to the commands. A numeric argument is also called a "count".
+In many cases, if a count is given, the command is executed that many
+times. For instance, `5 d d' deletes 5 lines while simple `d d'
+deletes a line. In this manual the metavariable N will denote a count.
+
+
+
+File: vip, Node: Important Keys, Next: Buffers and Windows, Prev: Numeric Arguments, Up: Vi Commands
+
+Important Keys
+==============
+
+The keys `C-g' and `C-l' are unique in that their associated
+functions are the same in any of emacs, vi and insert mode.
+
+`C-g'
+ Quit. Cancel running or partially typed command
+ (`keyboard-quit').
+
+`C-l'
+ Clear the screen and reprint everything (`recenter').
+
+In Emacs many commands are bound to the key strokes that start with
+`C-x', `C-c' and ESC. These commands can be accessed from vi mode as
+easily as from emacs mode.
+
+`C-x'
+`C-c'
+`ESC'
+ Typing one of these keys have the same effect as typing it in
+ emacs mode. Appropriate command will be executed according as
+ the keys you type after it. You will be in vi mode again after
+ the execution of the command. For instance, if you type `ESC <'
+ (in vi mode) then the cursor will move to the beginning of the
+ buffer and you will still be in vi mode.
+
+`C'
+`X'
+ Typing one of these keys have the effect of typing the
+ corresponding control character in emacs mode. Moreover, if you
+ type an upper case character following it, that character will
+ also be translated to the corresponding control character. Thus
+ typing `X W' in vi mode is the same as typing `C-x C-w' in emacs
+ mode. You will be in vi mode again after the execution of a
+ command.
+
+`\'
+ Escape to emacs mode. Hitting the `\' key will take you to
+ emacs mode, and you can execute a single Emacs command. After
+ executing the Emacs command you will be in vi mode again. You
+ can give a count before typing `\'. Thus `5 \ +', as well as `\
+ C-u 5 +', will insert `+++++' before point.
+
+
+
+File: vip, Node: Buffers and Windows, Next: Files, Prev: Important Keys, Up: Vi Commands
+
+Buffers and Windows
+===================
+
+In Emacs the text you edit is stored in a "buffer". See GNU Emacs
+Manual, for details. There is always one "selected" buffer which is
+called the "current buffer".
+
+You can see the contents of buffers through "windows" created by Emacs.
+When you have multiple windows on the screen only one of them is
+selected. Each buffer has a unique name, and each window has a mode
+line which shows the name of the buffer associated with the window
+and other information about the status of the buffer. You can change
+the format of the mode line, but normally if you see `**' at the
+beginning of a mode line it means that the buffer is "modified". If
+you write out the content of the buffer to a file, then the buffer
+will become not modified. Also if you see `%%' at the beginning of
+the mode line, it means that the file associated with the buffer is
+write protected.
+
+We have the following commands related to windows and buffers.
+
+`C-n'
+ Move cursor to the next-window (`vip-next-window').
+
+`X 1'
+ Delete other windows and make the selected window fill the screen
+ (`delete-other-windows').
+
+`X 2'
+ Split current window into two windows (`split-window-vertically').
+
+`X 3'
+ Show current buffer in two windows.
+
+`s BUFFER RET'
+ Select or create a buffer named BUFFER (`vip-switch-to-buffer').
+
+`S BUFFER RET'
+ Similar but select a buffer named BUFFER in another window
+ (`vip-switch-to-buffer-other-window').
+
+`K'
+ Kill the current buffer if it is not modified or if it is not
+ associated with a file
+ (`vip-kill-buffer').
+
+`X B'
+ List the existing buffers (`list-buffers').
+
+As "buffer name completion" is provided, you have only to type in
+initial substring of the buffer name which is sufficient to identify
+it among names of existing buffers. After that, if you hit TAB the
+rest of the buffer name will be supplied by the system, and you can
+confirm it by RET. The default buffer name to switch to will also be
+prompted, and you can select it by giving a simple RET. See GNU
+Emacs Manual for details of completion.
+
+
+
+File: vip, Node: Files, Next: Viewing the Buffer, Prev: Buffers and Windows, Up: Vi Commands
+
+Files
+=====
+
+We have the following commands related to files. They are used to
+visit, save and insert files.
+
+`v FILE RET'
+ Visit specified file in the current window (`vip-find-file').
+
+`V FILE RET'
+ Visit specified file in another window
+ (`vip-find-file-other-window').
+
+`X S'
+ Save current buffer to the file associated with the buffer. If
+ no file is associated with the buffer, the name of the file to
+ write out the content of the buffer will be asked in the
+ minibuffer.
+
+`X W FILE RET'
+ Write current buffer into a specified file.
+
+`X I FILE RET'
+ Insert a specified file at point.
+
+`g'
+ Give information on the file associated with the current buffer.
+ Tell you the name of the file associated with the buffer, the
+ line number of the current point and total line numbers in the
+ buffer. If no file is associated with the buffer, this fact
+ will be indicated by the null file name `""'.
+
+In Emacs, you can edit a file by "visiting" it. If you wish to visit
+a file in the current window, you can just type `v'. Emacs maintains
+the "default directory" which is specific to each buffer. Suppose,
+for instance, that the default directory of the current buffer is
+`/usr/masahiko/lisp/'. Then you will get the following prompt in the
+minibuffer.
+
+ visit file: /usr/masahiko/lisp/
+
+If you wish to visit, say, `vip.el' in this directory, then you can
+just type `vip.el' followed by RET. If the file `vip.el' already
+exists in the directory, Emacs will visit that file, and if not, the
+file will be created. Emacs will use the file name (`vip.el', in
+this case) as the name of the buffer visiting the file. In order to
+make the buffer name unique, Emacs may append `<2>', `<3>' etc., to
+the buffer name. As the "file name completion" is provided here, you
+can sometime save typing. For instance, suppose there is only one
+file in the default directory whose name starts with `v', that is
+`vip.el'. Then if you just type `v TAB' then it will be completed to
+`vip.el'. Thus, in this case, you just have to type `v v TAB RET' to
+visit `/usr/masahiko/lisp/vip.el'. Continuing the example, let us
+now suppose that you wished to visit the file
+`/usr/masahiko/man/vip.texinfo'. Then to the same prompt which you
+get after you typed `v', you can enter
+`/usr/masahiko/man/vip.texinfo' or `../man/vip.texinfo' followed by
+RET.
+
+Use `V' instead of `v', if you wish to visit a file in another window.
+
+You can verify which file you are editing by typing `g'. (You can
+also type `X B' to get nformation on other buffers too.) If you type
+`g' you will get an information like below in the echo area:
+
+ "/usr/masahiko/man/vip.texinfo" line 921 of 1949
+
+After you edited the buffer (`vip.texinfo', in our example) for a
+while, you may wish to save it in a file. If you wish to save it in
+the file associated with the buffer (`/usr/masahiko/man/vip.texinfo',
+in this case), you can just say `X S'. If you wish to save it in
+another file, you can type `X W'. You will then get a similar prompt
+as you get for `v', to which you can enter the file name.
+
+
+
+File: vip, Node: Viewing the Buffer, Next: Mark Commands, Prev: Files, Up: Vi Commands
+
+Viewing the Buffer
+==================
+
+In this and next section we discuss commands for moving around in the
+buffer. These command do not change the content of the buffer. The
+following commands are useful for viewing the content of the current
+buffer.
+
+`SPC'
+`C-f'
+ Scroll text of current window upward almost full screen. You
+ can go forward in the buffer by this command (`vip-scroll').
+
+`RET'
+`C-b'
+ Scroll text of current window downward almost full screen. You
+ can go backward in the buffer by this command (`vip-scroll-back').
+
+`C-d'
+ Scroll text of current window upward half screen. You can go
+ down in the buffer by this command (`vip-scroll-down').
+
+`C-u'
+ Scroll text of current window downward half screen. You can go
+ up in the buffer by this command (`vip-scroll-up').
+
+`C-y'
+ Scroll text of current window upward by one line
+ (`vip-scroll-down-one').
+
+`C-e'
+ Scroll text of current window downward by one line
+ (`vip-scroll-up-one').
+
+You can repeat these commands by giving a count. Thus, `2 SPC' has
+the same effect as `SPC SPC'.
+
+The following commands reposition point in the window.
+
+`z H'
+`z RET'
+ Put point on the top (home) line in the window. So the current
+ line becomes the top line in the window. Given a count N, point
+ will be placed in the N-th line from top (`vip-line-to-top').
+
+`z M'
+`z .'
+ Put point on the middle line in the window. Given a count N,
+ point will be placed in the N-th line from the middle line
+ (`vip-line-to-middle').
+
+`z L'
+`z -'
+ Put point on the bottom line in the window. Given a count N,
+ point will be placed in the N-th line from bottom
+ (`vip-line-to-bottom').
+
+`C-l'
+ Center point in window and redisplay screen (`recenter').
+
+
+
+File: vip, Node: Mark Commands, Next: Motion Commands, Prev: Viewing the Buffer, Up: Vi Commands
+
+Mark Commands
+=============
+
+The following commands are used to mark positions in the buffer.
+
+`m CH'
+ Store current point in the register CH. CH must be a lower case
+ character between `a' and `z'.
+
+`m <'
+ Set mark at the beginning of current buffer.
+
+`m >'
+ Set mark at the end of current buffer.
+
+`m .'
+ Set mark at point.
+
+`m ,'
+ Jump to mark (and pop mark off the mark ring).
+
+Emacs uses the "mark ring" to store marked positions. The commands
+`m <', `m >' and `m .' not only set mark but also add it as the
+latest element of the mark ring (replacing the oldest one). By
+repeating the command ``m ,'' you can visit older and older marked
+positions. You will eventually be in a loop as the mark ring is a
+ring.
+
+
+
+File: vip, Node: Motion Commands, Next: Searching and Replacing, Prev: Mark Commands, Up: Vi Commands
+
+Motion Commands
+===============
+
+Commands for moving around in the current buffer are collected here.
+These commands are used as an `argument' for the delete, change and
+yank commands to be described in the next section.
+
+`h'
+ Move point backward by one character. Signal error if point is
+ at the beginning of buffer, but (unlike Vi) do not complain
+ otherwise (`vip-backward-char').
+
+`l'
+ Move point backward by one character. Signal error if point is
+ at the end of buffer, but (unlike Vi) do not complain otherwise
+ (`vip-forward-char').
+
+`j'
+ Move point to the next line keeping the current column. If
+ point is on the last line of the buffer, a new line will be
+ created and point will move to that line (`vip-next-line').
+
+`k'
+ Move point to the previous line keeping the current column
+ (`vip-next-line').
+
+`+'
+ Move point to the next line at the first non-white character.
+ If point is on the last line of the buffer, a new line will be
+ created and point will move to the beginning of that line
+ (`vip-next-line-at-bol').
+
+`-'
+ Move point to the previous line at the first non-white character
+ (`vip-previous-line-at-bol').
+
+If a count is given to these commands, the commands will be repeated
+that many times.
+
+`0'
+ Move point to the beginning of line (`vip-beginning-of-line').
+
+`^'
+ Move point to the first non-white character on the line
+ (`vip-bol-and-skip-white').
+
+`$'
+ Move point to the end of line (`vip-goto-eol').
+
+`N |'
+ Move point to the N-th column on the line (`vip-goto-col').
+
+Except for the `|' command, these commands neglect a count.
+
+`w'
+ Move point forward to the beginning of the next word
+ (`vip-forward-word').
+
+`W'
+ Move point forward to the beginning of the next word, where a
+ "word" is considered as a sequence of non-white characters
+ (`vip-forward-Word').
+
+`b'
+ Move point backward to the beginning of a word
+ (`vip-backward-word').
+
+`B'
+ Move point backward to the beginning of a word, where a word is
+ considered as a sequence of non-white characters
+ (`vip-forward-Word').
+
+`e'
+ Move point forward to the end of a word (`vip-end-of-word').
+
+`E'
+ Move point forward to the end of a word, where a word is
+ considered as a sequence of non-white characters
+ (`vip-end-of-Word').
+
+Here the meaning of the word `word' for the `w', `b' and `e' commands
+is determined by the "syntax table" effective in the current buffer.
+Each major mode has its syntax mode, and therefore the meaning of a
+word also changes as the major mode changes. See GNU Emacs Manual
+for details of syntax table.
+
+`H'
+ Move point to the beginning of the home (top) line of the window.
+ Given a count N, go to the N-th line from top (`vip-window-top').
+
+`M'
+ Move point to the beginning of the middle line of the window.
+ Given a count N, go to the N-th line from the middle line
+ (`vip-window-middle').
+
+`L'
+ Move point to the beginning of the lowest (bottom) line of the
+ window. Given count, go to the N-th line from bottom
+ (`vip-window-bottom').
+
+These commands can be used to go to the desired line visible on the
+screen.
+
+`('
+ Move point backward to the beginning of the sentence
+ (`vip-backward-sentence').
+
+`)'
+ Move point forward to the end of the sentence
+ (`vip-forward-sentence').
+
+`{'
+ Move point backward to the beginning of the paragraph
+ (`vip-backward-paragraph').
+
+`}'
+ Move point forward to the end of the paragraph
+ (`vip-forward-paragraph').
+
+A count repeats the effect for these commands.
+
+`G'
+ Given a count N, move point to the N-th line in the buffer on
+ the first non-white character. Without a count, go to the end
+ of the buffer (`vip-goto-line').
+
+`` `'
+ Exchange point and mark (`vip-goto-mark').
+
+`` CH'
+ Move point to the position stored in the register CH. CH must
+ be a lower case letter.
+
+`' ''
+ Exchange point and mark, and then move point to the first
+ non-white character on the line (`vip-goto-mark-and-skip-white').
+
+`' CH'
+ Move point to the position stored in the register CH and skip to
+ the first non-white character on the line. CH must be a lower
+ case letter.
+
+`%'
+ Move point to the matching parenthesis if point is looking at
+ `(', `)', `{', `}', `[' or `]'
+ (`vip-paren-match').
+
+The command `G' mark point before move, so that you can return to the
+original point by `` `'. The original point will also be stored in
+the mark ring.
+
+The following commands are useful for moving points on the line. A
+count will repeat the effect.
+
+`f CH'
+ Move point forward to the character CH on the line. Signal
+ error if CH could not be found (`vip-find-char-forward').
+
+`F CH'
+ Move point backward to the character CH on the line. Signal
+ error if CH could not be found (`vip-find-char-backward').
+
+`t CH'
+ Move point forward upto the character CH on the line. Signal
+ error if CH could not be found (`vip-goto-char-forward').
+
+`T CH'
+ Move point backward upto the character CH on the line. Signal
+ error if CH could not be found (`vip-goto-char-backward').
+
+`;'
+ Repeat previous `f', `t', `F' or `T' command (`vip-repeat-find').
+
+`,'
+ Repeat previous `f', `t', `F' or `T' command, in the opposite
+ direction (`vip-repeat-find-opposite').
+
+
+
+File: vip, Node: Searching and Replacing, Next: Modifying Commands, Prev: Motion Commands, Up: Vi Commands
+
+Searching and Replacing
+=======================
+
+Following commands are available for searching and replacing.
+
+`/ STRING RET'
+ Search the first occurrence of the string STRING forward
+ starting from point. Given a count N, the N-th occurrence of
+ STRING will be searched. If the variable `vip-re-search' has
+ value `t' then "regular expression" search is done and the
+ string matching the regular expression STRING is found. If you
+ give an empty string as STRING then the search mode will change
+ from vanilla search to regular expression search and vice versa
+ (`vip-search-forward').
+
+`? STRING RET'
+ Same as `/', except that search is done backward
+ (`vip-search-backward').
+
+`n'
+ Search the previous search pattern in the same direction as
+ before (`vip-search-next').
+
+`N'
+ Search the previous search pattern in the opposite direction
+ (`vip-search-Next').
+
+`C-s'
+ Search forward incrementally. See GNU Emacs Manual for details
+ (`isearch-forward').
+
+`C-r'
+ Search backward incrementally (`isearch-backward').
+
+`R STRING RET NEWSTRING'
+ There are two modes of replacement, "vanilla" and "regular
+ expression". If the mode is vanilla you will get a prompt
+ `Replace string:', and if the mode is regular expression you
+ will ge a prompt `Replace regexp:'. The mode is initially
+ vanilla, but you can toggle these modes by giving a null string
+ as STRING. If the mode is vanilla, this command replaces every
+ occurrence of STRING with NEWSTRING. If the mode is regular
+ expression, STRING is treated as a regular expression and every
+ string matching the regular expression is replaced with
+ NEWSTRING (`vip-replace-string').
+
+`Q STRING RET NEWSTRING'
+ Same as `R' except that you will be asked form confirmation
+ before each replacement
+ (`vip-query-replace').
+
+`r CH'
+ Replace the character point is looking at by the character CH.
+ Give count, replace that many characters by CH
+ (`vip-replace-char').
+
+The commands `/' and `?' mark point before move, so that you can
+return to the original point by `` `'.
+
+
+
+File: vip, Node: Modifying Commands, Next: Delete Commands, Prev: Searching and Replacing, Up: Vi Commands
+
+Modifying Commands
+==================
+
+In this section, commands for modifying the content of a buffer are
+described. These commands affect the region determined by a motion
+command which is given to the commands as their argument.
+
+We classify motion commands into "point commands" and "line
+commands". The point commands are as follows:
+
+ `h', `l', `0', `^', `$', `w', `W', `b', `B', `e', `E', `(', `)', `/', `?', ``', `f', `F', `t', `T', `%', `;', `,'
+
+The line commands are as follows:
+
+ `j', `k', `+', `-', `H', `M', `L', `{', `}', `G', `''
+
+If a point command is given as an argument to a modifying command,
+the region determined by the point command will be affected by the
+modifying command. On the other hand, if a line command is given as
+an argument to a modifying command, the region determined by the line
+command will be enlarged so that it will become the smallest region
+properly containing the region and consisting of whole lines (we call
+this process "expanding the region"), and then the enlarged region
+will be affected by the modifying command.
+
+* Menu:
+
+* Delete Commands:: Commands for deleting text.
+* Yank Commands:: Commands for yanking text in Vi's sense.
+* Put Back Commands:: Commands for putting bake deleted/yanked text.
+* Change Commands:: Commands for changing text.
+
+
+
+File: vip, Node: Delete Commands, Next: Yank Commands, Prev: Modifying Commands, Up: Modifying Commands
+
+Delete Commands
+---------------
+
+`d MOTION-COMMAND'
+ Delete the region determined by the motion command MOTION-COMMAND.
+
+For example, `d $' will delete the region between point and end of
+current line since `$' is a point command that moves point to end of
+line. `d G' will delete the region between the beginning of current
+line and end of the buffer, since `G' is a line command. A count
+given to the command above will become the count for the associated
+motion command. Thus, `3 d w' will delete three words.
+
+It is also possible to save the deleted text into a register you
+specify. For example, you can say `" t 3 d w' to delete three words
+and save it to register `t'. The name of a register is a lower case
+letter between `a' and `z'. If you give an upper case letter as an
+argument to a delete command, then the deleted text will be appended
+to the content of the register having the corresponding lower case
+letter as its name. So, `" T d w' will delete a word and append it
+to register `t'. Other modifying commands also accept a register
+name as their argument, and we will not repeat similar explanations.
+
+We have more delete commands as below.
+
+`d d'
+ Delete a line. Given a count N, delete N lines.
+
+`d r'
+ Delete current region.
+
+`d R'
+ Expand current region and delete it.
+
+`D'
+ Delete to the end of a line (`vip-kill-line').
+
+`x'
+ Delete a character after point. Given N, delete N characters
+ (`vip-delete-char').
+
+`DEL'
+ Delete a character before point. Given N, delete N characters
+ (`vip-delete-backward-char').
+
+
+
+File: vip, Node: Yank Commands, Next: Put Back Commands, Prev: Delete Commands, Up: Modifying Commands
+
+Yank Commands
+-------------
+
+Yank commands "yank" a text of buffer into a (usually anonymous)
+register. Here the word `yank' is used in Vi's sense. Thus yank
+commands do not alter the content of the buffer, and useful only in
+combination with commands that put back the yanked text into the
+buffer.
+
+`y MOTION-COMMAND'
+ Yank the region determined by the motion command MOTION-COMMAND.
+
+For example, `y $' will yank the text between point and the end of
+line into an anonymous register, while `"c y $' will yank the same
+text into register `c'.
+
+Use the following command to yank consecutive lines of text.
+
+`y y'
+`Y'
+ Yank a line. Given N, yank N lines (`vip-yank-line').
+
+`y r'
+ Yank current region.
+
+`y R'
+ Expand current region and yank it.
+
+
+
+File: vip, Node: Put Back Commands, Next: Change Commands, Prev: Yank Commands, Up: Modifying Commands
+
+Put Back Commands
+-----------------
+
+Deleted or yanked texts can be put back into the buffer by the
+command below.
+
+`p'
+ Insert, after the character point is looking at, most recently
+ deleted/yanked text from anonymous register. Given a register
+ name argument, the content of the named register will be put
+ back. Given a count, the command will be repeated that many
+ times. This command also checks if the text to put back ends
+ with a new line character, and if so the text will be put below
+ the current line (`vip-put-back').
+
+`P'
+ Insert at point most recently deleted/yanked text from anonymous
+ register. Given a register name argument, the content of the
+ named register will be put back. Given a count, the command
+ will be repeated that many times. This command also checks if
+ the text to put back ends with a new line character, and if so
+ the text will be put above the current line rather than at point
+ (`vip-Put-back').
+
+Thus, `" c p' will put back the content of the register `c' into the
+buffer. It is also possible to specify "number register" which is a
+numeral between `1' and `9'. If the number register N is specified,
+N-th previously deleted/yanked text will be put back. It is an error
+to specify a number register for the delete/yank commands.
+
+
+
+File: vip, Node: Change Commands, Next: Repeating and Undoing Modifications, Prev: Put Back Commands, Up: Modifying Commands
+
+Change Commands
+---------------
+
+Most commonly used change command takes the following form.
+
+`c MOTION-COMMAND'
+ Replace the content of the region determined by the motion
+ command MOTION-COMMAND by the text you type. If the motion
+ command is a point command then you will type the text into
+ minibuffer, and if the motion command is a line command then the
+ region will be deleted first and you can insert the text in
+ INSERT MODE.
+
+For example, if point is at the beginning of a word `foo' and you
+wish to change it to `bar', you can type `c w'. Then, as `w' is a
+point command, you will get the prompt `foo =>' in the minibuffer,
+for which you can type `b a r RET' to complete the change command.
+
+`c c'
+ Change a line. Given a count, that many lines are changed.
+
+`c r'
+ Change current region.
+
+`c R'
+ Expand current region and change it.
+
+
+
+File: vip, Node: Repeating and Undoing Modifications, Next: Other Vi Commands, Prev: Change Commands, Up: Modifying Commands
+
+Repeating and Undoing Modifications
+-----------------------------------
+
+VIP records the previous modifying command, so that it is easy to
+repeat it. It is also very easy to undo changes made by modifying
+commands.
+
+`u'
+ Undo the last change. You can undo more by repeating undo by
+ the repeat command `.'. For example, you can undo 5 previous
+ changes by typing `u....'. If you type `uu', then the second
+ `u' undoes the first undo command (`vip-undo').
+
+`.'
+ Repeat the last modifying command. Given count N it becomes the
+ new count for the repeated command. Otherwise, the count for
+ the last modifying command is used again (`vip-repeat').
+
+
+
+File: vip, Node: Other Vi Commands, Next: Commands in Insert Mode, Prev: Repeating and Undoing Modifications, Up: Vi Commands
+
+Other Vi Commands
+=================
+
+Miscellaneous Vi commands are collected here.
+
+`Z Z'
+ Exit Emacs. If modified buffers exist, you will be asked
+ whether you wish to save them or not (`save-buffers-kill-emacs').
+
+`! MOTION-COMMAND FORMAT-COMMAND'
+`N ! ! FORMAT-COMMAND'
+ The region determined by the motion command MOTION-COMMAND will
+ be given to the shell command FORMAT-COMMAND and the region will
+ be replaced by its output. If a count is given, it will be
+ passed to MOTION-COMMAND. For example, `3!Gsort' will sort the
+ region between point and the 3rd line. If `!' is used instead
+ of MOTION-COMMAND then N lines will be processed by
+ FORMAT-COMMAND (`vip-command-argument').
+
+`J'
+ Join two lines. Given count, join that many lines. A space
+ will be inserted at each junction (`vip-join-lines').
+
+`< MOTION-COMMAND'
+`N < <'
+ Shift region determined by the motion command MOTION-COMMAND to
+ left by SHIFT-WIDTH (default is 8). If `<' is used instead of
+ MOTION-COMMAND then shift N lines
+ (`vip-command-argument').
+
+`> MOTION-COMMAND'
+`N > >'
+ Shift region determined by the motion command MOTION-COMMAND to
+ right by SHIFT-WIDTH (default is 8). If `<' is used instead of
+ MOTION-COMMAND then shift N lines
+ (`vip-command-argument').
+
+`= MOTION-COMMAND'
+ Indent region determined by the motion command MOTION-COMMAND.
+ If `=' is used instead of MOTION-COMMAND then indent N lines
+ (`vip-command-argument').
+
+`*'
+ Call last remembered keyboard macro.
+
+`#'
+ A new vi operator. *Note New Commands::, for more details.
+
+The following keys are reserved for future extensions, and currently
+assigned to a function that just beeps (`vip-nil').
+
+ &, @, U, [, ], _, q, ~
+
+VIP uses a special local keymap to interpret key strokes you enter in
+vi mode. The following keys are bound to NIL in the keymap.
+Therefore, these keys are interpreted by the global keymap of Emacs.
+We give below a short description of the functions bound to these
+keys in the global keymap. See GNU Emacs Manual for details.
+
+`C-@'
+ Set mark and push previous mark on mark ring (`set-mark-command').
+
+`TAB'
+ Indent line for current major mode (`indent-for-tab-command').
+
+`LFD'
+ Insert a newline, then indent according to mode
+ (`newline-and-indent').
+
+`C-k'
+ Kill the rest of the current line; before a newline, kill the
+ newline. With prefix argument, kill that many lines from point.
+ Negative arguments kill lines backward (`kill-line').
+
+`C-l'
+ Clear the screen and reprint everything (`recenter').
+
+`N C-p'
+ Move cursor vertically up N lines (`previous-line').
+
+`C-q'
+ Read next input character and insert it. Useful for inserting
+ control characters
+ (`quoted-insert').
+
+`C-r'
+ Search backward incrementally (`isearch-backward').
+
+`C-s'
+ Search forward incrementally (`isearch-forward').
+
+`N C-t'
+ Interchange charcters around point, moving forward one
+ character. With count N, take character before point and drag
+ it forward past N other characters. If no argument and at end
+ of line, the previous two characters are exchanged
+ (`transpose-chars').
+
+`N C-v'
+ Scroll text upward N lines. If N is not given, scroll near full
+ screen (`scroll-up').
+
+`C-w'
+ Kill between point and mark. The text is save in the kill ring.
+ The command `P' or `p' can retrieve it from kill ring
+ (`kill-region').
+
+
diff --git a/info/vip-2 b/info/vip-2
new file mode 100644
index 00000000000..1dc14b40391
--- /dev/null
+++ b/info/vip-2
@@ -0,0 +1,665 @@
+Info file ../info/vip, produced by Makeinfo, -*- Text -*- from input
+file vip.texinfo.
+
+Distribution
+************
+
+Copyright (C) 1987 Masahiko Sato.
+
+Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of
+this manual under the conditions for verbatim copying, provided that
+the entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this
+manual into another language, under the same conditions as for
+modified versions.
+
+
+
+File: vip, Node: Commands in Insert Mode, Next: Ex Commands, Prev: Other Vi Commands, Up: Vi Commands
+
+Insert Mode
+===========
+
+You can enter insert mode by one of the following commands. In
+addition to these, you will enter insert mode if you give a change
+command with a line command as the motion command. Insert commands
+are also modifying commands and you can repeat them by the repeat
+command `.' (`vip-repeat').
+
+`i'
+ Enter insert mode at point (`vip-insert').
+
+`I'
+ Enter insert mode at the first non white character on the line
+ (`vip-Insert').
+
+`a'
+ Move point forward by one character and then enter insert mode
+ (`vip-append').
+
+`A'
+ Enter insert mode at end of line (`vip-Append').
+
+`o'
+ Open a new line below the current line and enter insert mode
+ (`vip-open-line').
+
+`O'
+ Open a new line above the current line and enter insert mode
+ (`vip-Open-line').
+
+`C-o'
+ Insert a newline and leave point before it, and then enter
+ insert mode
+ (`vip-open-line-at-point').
+
+Insert mode is almost like emacs mode. Only the following 4 keys
+behave differently from emacs mode.
+
+`ESC'
+ This key will take you back to vi mode (`vip-change-mode-to-vi').
+
+`C-h'
+ Delete previous character (`delete-backward-char').
+
+`C-w'
+ Delete previous word (`vip-delete-backward-word').
+
+`C-z'
+ This key simulates ESC key in emacs mode. For instance, typing
+ `C-z x' in insert mode iw the same as typing `ESC x' in emacs
+ mode (`vip-ESC').
+
+You can also bind `C-h' to `help-command' if you like. (*Note
+Customizing Key Bindings::, for details.) Binding `C-h' to
+`help-command' has the effect of making the meaning of `C-h' uniform
+among emacs, vi and insert modes.
+
+When you enter insert mode, VIP records point as the start point of
+insertion, and when you leave insert mode the region between point
+and start point is saved for later use by repeat command etc.
+Therefore, repeat command will not really repeat insertion if you
+move point by emacs commands while in insert mode.
+
+
+
+File: vip, Node: Ex Commands, Next: Ex Command Reference, Prev: Commands in Insert Mode, Up: Top
+
+Ex Commands
+***********
+
+In vi mode, you can execute an Ex command EX-COMMAND by typing:
+
+ `: EX-COMMAND RET'
+
+Every Ex command follows the following pattern:
+
+ ADDRESS COMMAND `!' PARAMETERS COUNT FLAGS
+
+where all parts are optional. For the syntax of "address", the
+reader is referred to the reference manual of Ex.
+
+In the current version of VIP, searching by Ex commands is always
+"magic". That is, search patterns are always treated as "regular
+expressions". For example, a typical forward search would be invoked
+by `:/PAT/'. If you wish to include `/' as part of PAT you must
+preceded it by `\'. VIP strips off these `\''s before `/' and the
+resulting PAT becomes the actual search pattern. Emacs provides a
+different and richer class or regular expressions than Vi/Ex, and VIP
+uses Emacs' regular expressions. See GNU Emacs Manual for details of
+regular expressions.
+
+Several Ex commands can be entered in a line by separating them by a
+pipe character `|'.
+
+* Menu:
+
+* Ex Command Reference:: Explain all the Ex commands available in VIP.
+
+
+
+File: vip, Node: Ex Command Reference, Next: Customization, Prev: Ex Commands, Up: Ex Commands
+
+Ex Command Reference
+====================
+
+In this section we briefly explain all the Ex commands supported by
+VIP. Most Ex commands expect ADDRESS as their argument, and they use
+default addresses if they are not explicitly given. In the
+following, such default addresses will be shown in parentheses.
+
+Most command names can and preferably be given in abbreviated forms.
+In the following, optional parts of command names will be enclosed in
+brackets. For example, `co[py]' will mean that copy command can be
+give as `co' or `cop' or `copy'.
+
+If COMMAND is empty, point will move to the beginning of the line
+specified by the ADDRESS. If ADDRESS is also empty, point will move
+to the beginning of the current line.
+
+Some commands accept "flags" which are one of `p', `l' and `#'. If
+FLAGS are given, the text affected by the commands will be displayed
+on a temporary window, and you will be asked to hit return to
+continue. In this way, you can see the text affected by the commands
+before the commands will be executed. If you hit `C-g' instead of
+RET then the commands will be aborted. Note that the meaning of
+FLAGS is different in VIP from that in Vi/Ex.
+
+`(.,.) co[py] ADDR FLAGS'
+`(.,.) t ADDR FLAGS'
+ Place a copy of specified lines after ADDR. If ADDR is `0', it
+ will be placed before the first line.
+
+`(.,.) d[elete] REGISTER COUNT FLAGS'
+ Delete specified lines. Text will be saved in a named REGISTER
+ if a lower case letter is given, and appended to a register if a
+ capital letter is given.
+
+`e[dit] ! +ADDR FILE'
+`e[x] ! +ADDR FILE'
+`vi[sual] ! +ADDR FILE'
+ Edit a new file FILE in the current window. The command will
+ abort if current buffer is modified, which you can override by
+ giving `!'. If `+'ADDR is given, ADDR becomes the current line.
+
+`file'
+ Give information about the current file.
+
+`(1,$) g[lobal] ! /PAT/ CMDS'
+`(1,$) v /PAT/ CMDS'
+ Among specified lines first mark each line which matches the
+ regular expression PAT, and then execute CMDS on each marked line.
+ If `!' is given, CMDS will be executed on each line not matching
+ PAT. `v' is same as `g!'.
+
+`(.,.+1) j[oin] ! COUNT FLAGS'
+ Join specified lines into a line. Without `!', a space
+ character will be inserted at each junction.
+
+`(.) k CH'
+`(.) mar[k] CH'
+ Mark specified line by a lower case character CH. Then the
+ addressing form `''CH will refer to this line. No white space
+ is required between `k' and CH. A white space is necessary
+ between `mark' and CH, however.
+
+`map CH RHS'
+ Define a macro for vi mode. After this command, the character
+ CH will be expanded to RHS in vi mode.
+
+`(.,.) m[ove] ADDR'
+ Move specified lines after ADDR.
+
+`(.) pu[t] REGISTER'
+ Put back previously deleted or yanked text. If REGISTER is
+ given, the text saved in the register will be put back;
+ otherwise, last deleted or yanked text will be put back.
+
+`q[uit] !'
+ Quit from Emacs. If modified buffers with associated files
+ exist, you will be asked whether you wish to save each of them.
+ At this point, you may choose not to quit, by hitting `C-g'. If
+ `!' is given, exit from Emacs without saving modified buffers.
+
+`(.) r[ead] FILE'
+ Read in the content of the file FILE after the specified line.
+
+`(.) r[ead] ! COMMAND'
+ Read in the output of the shell command COMMAND after the
+ specified line.
+
+`se[t]'
+ Set a variable's value. *Note Customizing Constants::, for the
+ list of variables you can set.
+
+`sh[ell]'
+ Run a subshell in a window.
+
+`(.,.) s[ubstitute] /PAT/REPL/ OPTIONS COUNT FLAGS'
+`(.,.) & OPTIONS COUNT FLAGS'
+ On each specified line, the first occurrence of string matching
+ regular expression PAT is replaced by replacement pattern REPL.
+ Option characters are `g' and `c'. If global option character
+ `g' appears as part of OPTIONS, all occurrences are substituted.
+ If confirm option character `c' appears, you will be asked to
+ give confirmation before each substitution. If `/PAT/REPL/' is
+ missing, the last substitution is repeated.
+
+`st[op]'
+ Suspend Emacs.
+
+`ta[g] TAG'
+ Find first definition of TAG. If no TAG is given, previously
+ given TAG is used and next alternate definition is find. By
+ default, the file `TAGS' in the current directory becomes the
+ "selected tag table". You can select another tag table by `set'
+ command. *Note Customizing Constants::, for details.
+
+`und[o]'
+ Undo the last change.
+
+`unm[ap] CH'
+ The macro expansion associated with CH is removed.
+
+`ve[rsion]'
+ Tell the version number of VIP.
+
+`(1,$) w[rite] ! FILE'
+ Write out specified lines into file FILE. If no FILE is given,
+ text will be written to the file associated to the current
+ buffer. Unless `!' is given, if FILE is different from the file
+ associated to the current buffer and if the file FILE exists,
+ the command will not be executed. Unlike Ex, FILE becomes the
+ file associated to the current buffer.
+
+`(1,$) w[rite]>> FILE'
+ Write out specified lines at the end of file FILE. FILE becomes
+ the file associated to the current buffer.
+
+`(1,$) wq ! FILE'
+ Same as `write' and then `quit'. If `!' is given, same as
+ `write !' then `quit'.
+
+`(.,.) y[ank] REGISTER COUNT'
+ Save specified lines into register REGISTER. If no register is
+ specified, text will be saved in an anonymous register.
+
+`ADDR ! COMMAND'
+ Execute shell command COMMAND. The output will be shown in a
+ new window. If ADDR is given, specified lines will be used as
+ standard input to COMMAND.
+
+`($) ='
+ Print the line number of the addressed line.
+
+`(.,.) > COUNT FLAGS'
+ Shift specified lines to the right. The variable
+ `vip-shift-width' (default value is 8) determines the amount of
+ shift.
+
+`(.,.) < COUNT FLAGS'
+ Shift specified lines to the left. The variable
+ `vip-shift-width' (default value is 8) determines the amount of
+ shift.
+
+`(.,.) ~ OPTIONS COUNT FLAGS'
+ Repeat the previous `substitute' command using previous search
+ pattern as PAT for matching.
+
+The following Ex commands are available in Vi, but not implemented in
+VIP.
+
+ `abbreviate', `list', `next', `print', `preserve', `recover', `rewind', `source',
+ `unabbreviate', `xit', `z'
+
+
+
+File: vip, Node: Customization, Next: Customizing Constants, Prev: Ex Command Reference, Up: Top
+
+Customization
+*************
+
+If you have a file called `.vip' in your home directory, then it will
+also be loaded when VIP is loaded. This file is thus useful for
+customizing VIP.
+
+* Menu:
+
+* Customizing Constants:: How to change values of constants.
+* Customizing Key Bindings:: How to change key bindings.
+
+
+
+File: vip, Node: Customizing Constants, Next: Customizing Key Bindings, Prev: Customization, Up: Customization
+
+Customizing Constants
+=====================
+
+An easy way to customize VIP is to change the values of constants
+used in VIP. Here is the list of the constants used in VIP and their
+default values.
+
+`vip-shift-width 8'
+ The number of columns shifted by `>' and `<' command.
+
+`vip-re-replace nil'
+ If `t' then do regexp replace, if `nil' then do string replace.
+
+`vip-search-wrap-around t'
+ If `t', search wraps around the buffer.
+
+`vip-re-search nil'
+ If `t' then search is reg-exp search, if `nil' then vanilla
+ search.
+
+`vip-case-fold-search nil'
+ If `t' search ignores cases.
+
+`vip-re-query-replace nil'
+ If `t' then do reg-exp replace in query replace.
+
+`vip-open-with-indent nil'
+ If `t' then indent to the previous current line when open a new
+ line by `o' or `O' command.
+
+`vip-tags-file-name "TAGS"'
+ The name of the file used as the tag table.
+
+`vip-help-in-insert-mode nil'
+ If `t' then C-h is bound to `help-command' in insert mode, if
+ `nil' then it sis bound to `delete-backward-char'.
+
+You can reset these constants in VIP by the Ex command `set'. Or you
+can include a line like this in your `.vip' file:
+
+ (setq vip-case-fold-search t)
+
+
+
+File: vip, Node: Customizing Key Bindings, Prev: Customizing Constants, Up: Customization
+
+Customizing Key Bindings
+========================
+
+VIP uses `vip-command-mode-map' as the "local keymap" for vi mode.
+For example, in vi mode, SPC is bound to the function `vip-scroll'.
+But, if you wish to make SPC and some other keys behave like Vi, you
+can include the following lines in your `.vip' file.
+
+ (define-key vip-command-mode-map "\C-g" 'vip-info-on-file)
+ (define-key vip-command-mode-map "\C-h" 'vip-backward-char)
+ (define-key vip-command-mode-map "\C-m" 'vip-next-line-at-bol)
+ (define-key vip-command-mode-map " " 'vip-forward-char)
+ (define-key vip-command-mode-map "g" 'vip-keyboard-quit)
+ (define-key vip-command-mode-map "s" 'vip-substitute)
+ (define-key vip-command-mode-map "C" 'vip-change-to-eol)
+ (define-key vip-command-mode-map "R" 'vip-change-to-eol)
+ (define-key vip-command-mode-map "S" 'vip-substitute-line)
+ (define-key vip-command-mode-map "X" 'vip-delete-backward-char)
+
+Key Index
+*********
+
+* Menu:
+
+* 000 C-@ (set-mark-command): Other Vi Commands.
+* 001 C-a (vip-beginning-of-line): New Commands.
+* 002 C-b (vip-scroll-back): Viewing the Buffer.
+* 003 C-c (vip-ctl-c): New Commands.
+* 003 C-c (vip-ctl-c): Important Keys.
+* 004 C-d (vip-scroll-up): Viewing the Buffer.
+* 005 C-e (vip-scroll-up-one): Viewing the Buffer.
+* 006 C-f (vip-scroll-back): Viewing the Buffer.
+* 007 C-g (vip-keyboard-quit): New Bindings.
+* 007 C-g (vip-keyboard-quit): Changing.
+* 007 C-g (vip-keyboard-quit): Important Keys.
+* 010 C-h (delete-backward-char) (insert mode): Commands in Insert Mode.
+* 010 C-h (vip-delete-backward-char) (insert mode): Insert Mode.
+* 011 TAB (indent-for-tab-command): Other Vi Commands.
+* 012 LFD (newline-and-indent): Other Vi Commands.
+* 013 C-k (kill-line): Other Vi Commands.
+* 014 C-l (recenter): Important Keys.
+* 014 C-l (recenter): Other Vi Commands.
+* 015 RET (vip-scroll-back): Viewing the Buffer.
+* 015 RET (vip-scroll-back): New Bindings.
+* 016 C-n (vip-next-window): New Commands.
+* 016 C-n (vip-next-window): Buffers and Windows.
+* 016 C-n (vip-next-window): Window Commands.
+* 017 C-o (vip-open-line-at-point): New Commands.
+* 017 C-o (vip-open-line-at-point): Commands in Insert Mode.
+* 020 C-p (previous-line): Other Vi Commands.
+* 021 C-q (quoted-insert): Other Vi Commands.
+* 022 C-r (isearch-backward): Other Vi Commands.
+* 022 C-r (isearch-backward): New Commands.
+* 022 C-r (isearch-backward): Searching and Replacing.
+* 023 C-s (isearch-forward): Other Vi Commands.
+* 023 C-s (isearch-forward): Searching and Replacing.
+* 023 C-s (isearch-forward): New Commands.
+* 024 C-t (transpose-chars): Other Vi Commands.
+* 025 C-u (vip-scroll-down): Viewing the Buffer.
+* 026 C-v (scroll-up): Other Vi Commands.
+* 027 C-w (kill-region): Other Vi Commands.
+* 027 C-w (vip-delete-backward-word) (insert mode): Insert Mode.
+* 027 C-w (vip-delete-backward-word) (insert mode): Commands in Insert Mode.
+* 0300 C-x (vip-ctl-x): Important Keys.
+* 0300 C-x (vip-ctl-x): New Commands.
+* 0301 C-x C-z (suspend-emacs): Modes in VIP.
+* 031 C-y (vip-scroll-down-one): Viewing the Buffer.
+* 032 C-z (vip-ESC) (insert mode): Commands in Insert Mode.
+* 032 C-z (vip-ESC) (insert mode): Insert Mode.
+* 032 C-z (vip-change-mode-to-vi): Modes in VIP.
+* 032 C-z (vip-change-mode-to-vi): Emacs Mode.
+* 033 ESC (vip-ESC): New Commands.
+* 033 ESC (vip-ESC): Important Keys.
+* 033 ESC (vip-change-mode-to-vi) (insert mode): Insert Mode.
+* 033 ESC (vip-change-mode-to-vi) (insert mode): Commands in Insert Mode.
+* 040 SPC (vip-scroll): Viewing the Buffer.
+* 040 SPC (vip-scroll): New Bindings.
+* 041 ! (vip-command-argument): Other Vi Commands.
+* 042 " (vip-command-argument): Delete Commands.
+* 0430 # (vip-command-argument): New Commands.
+* 0431 # C (upcase-region): New Commands.
+* 0432 # c (downcase-region): New Commands.
+* 0432 # g (vip-global-execute): New Commands.
+* 0432 # q (vip-quote-region): New Commands.
+* 0432 # s (spell-region): New Commands.
+* 044 $ (vip-goto-eol): Motion Commands.
+* 045 % (vip-paren-match): Motion Commands.
+* 046 & (vip-nil): Other Vi Commands.
+* 047 ' (vip-goto-mark-and-skip-white): Motion Commands.
+* 050 ( (vip-backward-sentence): Motion Commands.
+* 051 ) (vip-forward-sentence): Motion Commands.
+* 052 * (vip-call-last-kbd-macro): New Commands.
+* 052 * (vip-call-last-kbd-macro): Other Vi Commands.
+* 052 * (vip-call-last-kbd-macro): Misc Commands.
+* 053 + (vip-next-line-at-bol): Motion Commands.
+* 054 , (vip-repeat-find-opposite): Motion Commands.
+* 055 - (vip-previous-line-at-bol): Motion Commands.
+* 056 . (vip-repeat): Repeating and Undoing Modifications.
+* 056 . (vip-repeat): Undoing.
+* 057 / (vip-search-forward): Searching.
+* 057 / (vip-search-forward): Counts.
+* 057 / (vip-search-forward): Searching and Replacing.
+* 060 0 (vip-beginning-of-line): Motion Commands.
+* 061 1 (numeric argument): Numeric Arguments.
+* 062 2 (numeric argument): Numeric Arguments.
+* 063 3 (numeric argument): Numeric Arguments.
+* 064 4 (numeric argument): Numeric Arguments.
+* 065 5 (numeric argument): Numeric Arguments.
+* 066 6 (numeric argument): Numeric Arguments.
+* 067 7 (numeric argument): Numeric Arguments.
+* 068 8 (numeric argument): Numeric Arguments.
+* 069 9 (numeric argument): Numeric Arguments.
+* 072 : (vip-ex): Ex Commands.
+* 073 ; (vip-repeat-find): Motion Commands.
+* 074 < (vip-command-argument): Other Vi Commands.
+* 075 = (vip-command-argument): Other Vi Commands.
+* 076 > (vip-command-argument): Other Vi Commands.
+* 077 ? (vip-search-backward): Searching.
+* 077 ? (vip-search-backward): Counts.
+* 077 ? (vip-search-backward): Searching and Replacing.
+* 100 @ (vip-nil): Other Vi Commands.
+* 101 A (vip-Append): Commands in Insert Mode.
+* 102 B (vip-backward-Word): Motion Commands.
+* 103 C (vip-ctl-c-equivalent): Important Keys.
+* 103 C (vip-ctl-c-equivalent): New Bindings.
+* 104 D (vip-kill-line): Delete Commands.
+* 105 E (vip-end-of-Word): Motion Commands.
+* 106 F (vip-find-char-backward): Motion Commands.
+* 107 G (vip-goto-line): Motion Commands.
+* 110 H (vip-window-top): Motion Commands.
+* 111 I (vip-Insert): Commands in Insert Mode.
+* 112 J (vip-join-lines): Other Vi Commands.
+* 113 K (vip-kill-buffer): Buffer Commands.
+* 113 K (vip-kill-buffer): New Commands.
+* 113 K (vip-kill-buffer): Buffers and Windows.
+* 114 L (vip-window-bottom): Motion Commands.
+* 115 M (vip-window-middle): Motion Commands.
+* 116 N (vip-search-Next): Searching and Replacing.
+* 117 O (vip-Open-line): Counts.
+* 117 O (vip-Open-line): Commands in Insert Mode.
+* 120 P (vip-Put-back): Counts.
+* 120 P (vip-Put-back): Put Back Commands.
+* 121 Q (vip-query-replace): New Commands.
+* 121 Q (vip-query-replace): Searching and Replacing.
+* 122 R (vip-replace-string): New Commands.
+* 122 R (vip-replace-string): Searching and Replacing.
+* 123 S (vip-switch-to-buffer-other-window): New Bindings.
+* 123 S (vip-switch-to-buffer-other-window): Buffer Commands.
+* 123 S (vip-switch-to-buffer-other-window): Buffers and Windows.
+* 124 T (vip-goto-char-backward): Motion Commands.
+* 125 U (vip-nil): Other Vi Commands.
+* 126 V (vip-find-file-other-window): Files.
+* 126 V (vip-find-file-other-window): File Commands.
+* 126 V (vip-find-file-other-window): New Commands.
+* 127 W (vip-forward-Word): Motion Commands.
+* 1300 X (vip-ctl-x-equivalent): Important Keys.
+* 1300 X (vip-ctl-x-equivalent): New Bindings.
+* 1301 X ( (start-kbd-macro): Misc Commands.
+* 1301 X ) (end-kbd-macro): Misc Commands.
+* 1301 X 1 (delete-other-windows): Window Commands.
+* 1301 X 1 (delete-other-windows): Buffers and Windows.
+* 1301 X 2 (split-window-vertically): Buffers and Windows.
+* 1301 X 2 (split-window-vertically): Window Commands.
+* 1301 X 3 (vip-buffer-in-two-windows): Buffers and Windows.
+* 1301 X 3 (vip-buffer-in-two-windows): Window Commands.
+* 1301 X 3 (vip-buffer-in-two-windows): New Bindings.
+* 1302 X B (list-buffers): Buffers and Windows.
+* 1302 X I (insert-file): Files.
+* 1302 X I (insert-file): File Commands.
+* 1302 X S (save-buffer): Files.
+* 1302 X S (save-buffer): Buffer Commands.
+* 1302 X W (write-file): Files.
+* 1302 X W (write-file): File Commands.
+* 1302 X Z (suspend-emacs): Misc Commands.
+* 131 Y (vip-yank-line): Yank Commands.
+* 132 Z Z (save-buffers-kill-emacs): Other Vi Commands.
+* 133 [ (vip-nil): Other Vi Commands.
+* 134 \ (vip-escape-to-emacs): New Commands.
+* 134 \ (vip-escape-to-emacs): Important Keys.
+* 135 ] (vip-nil): Other Vi Commands.
+* 136 ^ (vip-bol-and-skip-white): Motion Commands.
+* 137 _ (vip-nil): Other Vi Commands.
+* 140 ` (vip-goto-mark): Motion Commands.
+* 141 a (vip-append): Commands in Insert Mode.
+* 142 b (vip-backward-word): Motion Commands.
+* 1430 c (vip-command-argument): Change Commands.
+* 1431 c R: Change Commands.
+* 1432 c c: Change Commands.
+* 1432 c r: Change Commands.
+* 1440 d (vip-command-argument): Delete Commands.
+* 1441 d R: Delete Commands.
+* 1442 d d: Delete Commands.
+* 1442 d r: Delete Commands.
+* 145 e (vip-end-of-word): Motion Commands.
+* 146 f (vip-find-char-forward): Motion Commands.
+* 147 g (vip-info-on-file): New Bindings.
+* 147 g (vip-info-on-file): Files.
+* 150 h (vip-backward-char): Motion Commands.
+* 151 i (vip-insert): Commands in Insert Mode.
+* 152 j (vip-next-line): Motion Commands.
+* 153 k (vip-previous-line): Motion Commands.
+* 154 l (vip-forward-char): Motion Commands.
+* 155 m (vip-mark-point): Mark Commands.
+* 155 m (vip-mark-point): Marking.
+* 156 n (vip-search-next): Searching and Replacing.
+* 157 o (vip-open-line): Commands in Insert Mode.
+* 157 o (vip-open-line): Counts.
+* 160 p (vip-put-back): Put Back Commands.
+* 160 p (vip-put-back): Counts.
+* 161 q (vip-nil): Other Vi Commands.
+* 162 r (vip-replace-char): Searching and Replacing.
+* 163 s (vip-switch-to-buffer): Buffer Commands.
+* 163 s (vip-switch-to-buffer): Buffers and Windows.
+* 163 s (vip-switch-to-buffer): New Bindings.
+* 164 t (vip-goto-char-forward): Motion Commands.
+* 165 u (vip-undo): Undoing.
+* 165 u (vip-undo): Repeating and Undoing Modifications.
+* 166 v (vip-find-file): File Commands.
+* 166 v (vip-find-file): Files.
+* 166 v (vip-find-file): New Commands.
+* 167 w (vip-forward-word): Motion Commands.
+* 170 x (vip-delete-char): Delete Commands.
+* 1710 y (vip-command-argument): Yank Commands.
+* 1711 y R: Yank Commands.
+* 1712 y r: Yank Commands.
+* 1712 y y (vip-yank-line): Yank Commands.
+* 1721 z RET (vip-line-to-top): Viewing the Buffer.
+* 1721 z RET (vip-line-to-top): z Command.
+* 1722 z - (vip-line-to-bottom): Viewing the Buffer.
+* 1722 z - (vip-line-to-bottom): z Command.
+* 1722 z . (vip-line-to-middle): z Command.
+* 1722 z . (vip-line-to-middle): Viewing the Buffer.
+* 1723 z H (vip-line-to-top): Viewing the Buffer.
+* 1723 z H (vip-line-to-top): z Command.
+* 1723 z L (vip-line-to-bottom): z Command.
+* 1723 z L (vip-line-to-bottom): Viewing the Buffer.
+* 1723 z M (vip-line-to-middle): z Command.
+* 1723 z M (vip-line-to-middle): Viewing the Buffer.
+* 173 { (vip-backward-paragraph): Motion Commands.
+* 174 | (vip-goto-col): Motion Commands.
+* 175 } (vip-forward-paragraph): Motion Commands.
+* 176 ~ (vip-nil): Other Vi Commands.
+* 177 DEL (vip-delete-backward-char): Delete Commands.
+
+
+ Concept Index
+**************
+
+* Menu:
+
+* address: Ex Commands.
+* buffer: Basic Concepts.
+* buffer: Buffers and Windows.
+* buffer name completion: Buffers and Windows.
+* count: Numeric Arguments.
+* current buffer: Buffers and Windows.
+* default directory: Files.
+* emacs mode: Modes in VIP.
+* end (of buffer): Basic Concepts.
+* expanding (region): Modifying Commands.
+* file name completion: Files.
+* flag: Ex Command Reference.
+* global keymap: Basic Concepts.
+* insert mode: Modes in VIP.
+* keymap: Basic Concepts.
+* line commands: Modifying Commands.
+* local keymap: Customizing Key Bindings.
+* local keymap: Basic Concepts.
+* looking at: Basic Concepts.
+* magic: Ex Commands.
+* mark: Basic Concepts.
+* mark ring: Mark Commands.
+* mode: Basic Concepts.
+* mode line: Modes in VIP.
+* modified (buffer): Buffers and Windows.
+* number register: Put Back Commands.
+* numeric arguments: Numeric Arguments.
+* point: Basic Concepts.
+* point commands: Modifying Commands.
+* region: Basic Concepts.
+* region: Region Commands.
+* regular expression: Ex Commands.
+* regular expression (replacement): Searching and Replacing.
+* regular expression (search): Searching and Replacing.
+* selected buffer: Buffers and Windows.
+* selected tag table: Ex Command Reference.
+* syntax table: Motion Commands.
+* tag: Ex Command Reference.
+* text: Basic Concepts.
+* vanilla (replacement): Searching and Replacing.
+* vi mode: Modes in VIP.
+* visiting (a file): Files.
+* window: Basic Concepts.
+* window: Buffers and Windows.
+* word: Motion Commands.
+* yank: Yank Commands.
+
+
+
diff --git a/install.sh b/install.sh
new file mode 100755
index 00000000000..0ff4b6a08e8
--- /dev/null
+++ b/install.sh
@@ -0,0 +1,119 @@
+#!/bin/sh
+
+#
+# install - install a program, script, or datafile
+# This comes from X11R5; it is not part of GNU.
+#
+# $XConsortium: install.sh,v 1.2 89/12/18 14:47:22 jim Exp $
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+#
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+
+instcmd="$mvprog"
+chmodcmd=""
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+
+while [ x"$1" != x ]; do
+ case $1 in
+ -c) instcmd="$cpprog"
+ shift
+ continue;;
+
+ -m) chmodcmd="$chmodprog $2"
+ shift
+ shift
+ continue;;
+
+ -o) chowncmd="$chownprog $2"
+ shift
+ shift
+ continue;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift
+ shift
+ continue;;
+
+ -s) stripcmd="$stripprog"
+ shift
+ continue;;
+
+ *) if [ x"$src" = x ]
+ then
+ src=$1
+ else
+ dst=$1
+ fi
+ shift
+ continue;;
+ esac
+done
+
+if [ x"$src" = x ]
+then
+ echo "install: no input file specified"
+ exit 1
+fi
+
+if [ x"$dst" = x ]
+then
+ echo "install: no destination specified"
+ exit 1
+fi
+
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+if [ -d $dst ]
+then
+ dst="$dst"/`basename $src`
+fi
+
+# Make a temp file name in the proper directory.
+
+dstdir=`dirname $dst`
+dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+$doit $instcmd $src $dsttmp
+
+# and set any options; do chmod last to preserve setuid bits
+
+if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; fi
+if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; fi
+if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; fi
+if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; fi
+
+# Now rename the file to the real destination.
+
+$doit $rmcmd $dst
+$doit $mvcmd $dsttmp $dst
+
+
+exit 0
diff --git a/kepteditor.com b/kepteditor.com
new file mode 100644
index 00000000000..78594548a0b
--- /dev/null
+++ b/kepteditor.com
@@ -0,0 +1,88 @@
+$ verify = f$verify (0)
+$ !
+$ ! Kept_Editor.COM
+$ ! Command file for use on VMS to spawn an Emacs process
+$ ! that can be suspended with C-z and will not go away
+$ ! when other programs are run. This is the normal way
+$ ! for users to invoke Emacs on VMS; the command "emacs"
+$ ! is normally defined to execute this file.
+$ ! That definition, and other definitions used by it, are done by `emacs.com'.
+$ ! Users who want to use Emacs should have their `login.com' files
+$ ! execute `emacs.com', which is to be found in this directory.
+$ !
+$ ! Joe Kelsey
+$ ! FlexComm Corp.
+$ !
+$ ! September, 1985
+$ !
+$ ! Run or attach to an editor in a kept fork.
+$ !
+$ ! Modified by Marty Sasaki to define the job logical name
+$ ! "EMACS_FILE_NAME" with the value of the filename on the command
+$ ! line. Lisp code can then use the value of the logical to resume or
+$ ! to start editing in that file.
+$ !
+$ !
+$ edit = ""
+$ name = p1 + " " + f$trnlnm ( "TT" ) - ":"
+$ priv_list = f$setprv ("NOWORLD, NOGROUP")
+$ pid = 0
+$ 10$:
+$ proc = f$getjpi ( f$pid ( pid ), "PRCNAM")
+$ if proc .eqs. name then -
+$ goto attach
+$ if pid .ne. 0 then -
+$ goto 10$
+$ spawn:
+$ args = p2 + " " + p3 + " " + p4 + " " + p5 + " " + -
+ p6 + " " + p7 + " " + p8
+$ priv_list = f$setprv ( priv_list )
+$ write sys$error -
+"[Spawning a new Kept ''P1']"
+$ if p1 .nes. "TPU" then -
+$ goto check_emacs
+$ define/user sys$input sys$command
+$ spawn /process="''NAME'" -
+ /nolog -
+ edit/'p1' 'args'
+$ goto quit1
+$ check_emacs:
+$ if p1 .nes. "EMACS" then -
+$ goto un_kempt
+$ define/user sys$input sys$command
+$ spawn /process="''NAME'" -
+ /nolog -
+ runemacs 'args'
+$ goto quit1
+$ un_kempt:
+$ ! The editor is unruly - spawn a process and let the user deal with the
+$ ! editor himself.
+$ spawn /process="''NAME'" -
+ /nolog
+$ goto quit1
+$ attach:
+$ priv_list = f$setprv ( priv_list )
+$ message_status = f$environment("message")
+$ set noon
+$ on control_y then goto quit
+$ set message /nofacility/noidentification/noseverity/notext
+$ if p2 .eqs. "" then goto no_logical
+$ temp = f$trnlnm("SYS$DISK") + f$directory() + p2
+$ temp = f$edit(temp,"lowercase")
+$ define/nolog/job emacs_file_name "''temp'"
+$ no_logical:
+$ write sys$error -
+"[Attaching to process ''NAME']"
+$ define/user sys$input sys$command
+$ attach "''NAME'"
+$ quit:
+$ set noon
+$ if p2 .eqs. "" then goto quit1
+$ deassign/job emacs_file_name
+$ quit1:
+$ set message 'message_status
+$ write sys$error -
+"[Attached to DCL in directory ''F$TRNLNM("SYS$DISK")'''F$DIRECTORY()']"
+$ if verify then -
+$ set verify
+$ exit
diff --git a/lib-src/emacstool.c b/lib-src/emacstool.c
deleted file mode 100644
index 5e310e0faa4..00000000000
--- a/lib-src/emacstool.c
+++ /dev/null
@@ -1,340 +0,0 @@
-/*
- *
- * Copyright (C) 1986 Free Software Foundation, Inc.
- *
- * This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 1, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
- *
- *
- * For Emacs in SunView/Sun-Windows: (supported by Sun Unix v3.2)
- * Insert a notifier filter-function to convert all useful input
- * to "key" sequences that emacs can understand. See: Emacstool(1).
- *
- * Author: Jeff Peck, Sun Microsystems, Inc. <peck@sun.com>
- *
- * Original Idea: Ian Batten
- * Updated 15-Mar-88, Jeff Peck: set IN_EMACSTOOL, TERM, TERMCAP
- *
- */
-
-#include <suntool/sunview.h>
-#include <suntool/tty.h>
-#include <stdio.h>
-#include <sys/file.h>
-
-#define BUFFER_SIZE 128 /* Size of all the buffers */
-
-/* define WANT_CAPS_LOCK to make f-key T1 (aka F1) behave as CapsLock */
-#define WANT_CAPS_LOCK
-#ifdef WANT_CAPS_LOCK
-int caps_lock; /* toggle indicater for f-key T1 caps lock */
-static char *Caps = "[CAPS] "; /* Caps Lock prefix string */
-#define CAPS_LEN 7 /* strlen (Caps) */
-#endif
-
-static char *mouse_prefix = "\030\000"; /* C-x C-@ */
-static int m_prefix_length = 2; /* mouse_prefix length */
-
-static char *key_prefix = "\030*"; /* C-x * */
-static int k_prefix_length = 2; /* key_prefix length */
-
-static char *emacs_name = "emacs"; /* default run command */
-static char buffer[BUFFER_SIZE]; /* send to ttysw_input */
-static char *title = "Emacstool - "; /* initial title */
-
-Frame frame; /* Base frame for system */
-Tty ttysw; /* Where emacs is */
-int font_width, font_height; /* For translating pixels to chars */
-
-int console_fd = 0; /* for debugging: setenv DEBUGEMACSTOOL */
-FILE *console; /* for debugging: setenv DEBUGEMACSTOOL */
-
-Icon frame_icon;
-/* make an icon_image for the default frame_icon */
-static short default_image[258] =
-{
-#include <images/terminal.icon>
-};
-mpr_static(icon_image, 64, 64, 1, default_image);
-
-
-/*
- * Assign a value to a set of keys
- */
-int
-button_value (event)
- Event *event;
-{
- int retval = 0;
- /*
- * Code up the current situation:
- *
- * 1 = MS_LEFT;
- * 2 = MS_MIDDLE;
- * 4 = MS_RIGHT;
- * 8 = SHIFT;
- * 16 = CONTROL;
- * 32 = META;
- * 64 = DOUBLE;
- * 128 = UP;
- */
-
- if (MS_LEFT == (event_id (event))) retval = 1;
- if (MS_MIDDLE == (event_id (event))) retval = 2;
- if (MS_RIGHT == (event_id (event))) retval = 4;
-
- if (event_shift_is_down (event)) retval += 8;
- if (event_ctrl_is_down (event)) retval += 16;
- if (event_meta_is_down (event)) retval += 32;
- if (event_is_up (event)) retval += 128;
- return retval;
-}
-
-/*
- * Variables to store the time of the previous mouse event that was
- * sent to emacs.
- *
- * The theory is that to time double clicks while ignoreing UP buttons,
- * we must keep track of the accumulated time.
- *
- * If someone writes a SUN-SET-INPUT-MASK for emacstool,
- * That could be used to selectively disable UP events,
- * and then this cruft wouldn't be necessary.
- */
-static long prev_event_sec = 0;
-static long prev_event_usec = 0;
-
-/*
- * Give the time difference in milliseconds, where one second
- * is considered infinite.
- */
-int
-time_delta (now_sec, now_usec, prev_sec, prev_usec)
- long now_sec, now_usec, prev_sec, prev_usec;
-{
- long sec_delta = now_sec - prev_sec;
- long usec_delta = now_usec - prev_usec;
-
- if (usec_delta < 0) { /* "borrow" a second */
- usec_delta += 1000000;
- --sec_delta;
- }
-
- if (sec_delta >= 10)
- return (9999); /* Infinity */
- else
- return ((sec_delta * 1000) + (usec_delta / 1000));
-}
-
-
-/*
- * Filter function to translate selected input events for emacs
- * Mouse button events become ^X^@(button x-col y-line time-delta) .
- * Function keys: ESC-*{c}{lrt} l,r,t for Left, Right, Top;
- * {c} encodes the keynumber as a character [a-o]
- */
-static Notify_value
-input_event_filter_function (window, event, arg, type)
- Window window;
- Event *event;
- Notify_arg arg;
- Notify_event_type type;
-{
- struct timeval time_stamp;
-
- if (console_fd) fprintf(console, "Event: %d\n", event_id(event));
-
- /* UP L1 is the STOP key */
- if (event_id(event) == WIN_STOP) {
- ttysw_input(ttysw, "\007\007\007\007\007\007\007", 7);
- return NOTIFY_IGNORED;
- }
-
- /* UP L5 & L7 is Expose & Open, let them pass to sunview */
- if (event_id(event) == KEY_LEFT(5) || event_id(event) == KEY_LEFT(7))
- if(event_is_up (event))
- return notify_next_event_func (window, event, arg, type);
- else return NOTIFY_IGNORED;
-
- if (event_is_button (event)) { /* do Mouse Button events */
-/* Commented out so that we send mouse up events too.
- if (event_is_up (event))
- return notify_next_event_func (window, event, arg, type);
-*/
- time_stamp = event_time (event);
- ttysw_input (ttysw, mouse_prefix, m_prefix_length);
- sprintf (buffer, "(%d %d %d %d)\015",
- button_value (event),
- event_x (event) / font_width,
- event_y (event) / font_height,
- time_delta (time_stamp.tv_sec, time_stamp.tv_usec,
- prev_event_sec, prev_event_usec)
- );
- ttysw_input (ttysw, buffer, strlen(buffer));
- prev_event_sec = time_stamp.tv_sec;
- prev_event_usec = time_stamp.tv_usec;
- return NOTIFY_IGNORED;
- }
-
- { /* Do the function key events */
- int d;
- char c = (char) 0;
- if ((event_is_key_left (event)) ?
- ((d = event_id(event) - KEY_LEFT(1) + 'a'), c='l') :
- ((event_is_key_right (event)) ?
- ((d = event_id(event) - KEY_RIGHT(1) + 'a'), c='r') :
- ((event_is_key_top (event)) ?
- ((d = event_id(event) - KEY_TOP(1) + 'a'), c='t') : 0)))
- {
- if (event_is_up(event)) return NOTIFY_IGNORED;
- if (event_shift_is_down (event)) c = c - 32;
- /* this will give a non-{lrt} for unshifted keys */
- if (event_ctrl_is_down (event)) c = c - 64;
- if (event_meta_is_down (event)) c = c + 128;
-#ifdef WANT_CAPS_LOCK
-/* set a toggle and relabel window so T1 can act like caps-lock */
- if (event_id(event) == KEY_TOP(1))
- {
- /* make a frame label with and without CAPS */
- strcpy (buffer, Caps);
- title = &buffer[CAPS_LEN];
- strncpy (title, (char *)window_get (frame, FRAME_LABEL),
- BUFFER_SIZE - CAPS_LEN);
- buffer[BUFFER_SIZE] = (char) 0;
- if (strncmp (title, Caps, CAPS_LEN) == 0)
- title += CAPS_LEN; /* already Caps */
- caps_lock = (caps_lock ? 0 : CAPS_LEN);
- window_set(frame, FRAME_LABEL, (title -= caps_lock), 0);
- return NOTIFY_IGNORED;
- }
-#endif
- ttysw_input (ttysw, key_prefix, k_prefix_length);
- sprintf (buffer, "%c%c", d, c);
- ttysw_input(ttysw, buffer, strlen(buffer));
-
- return NOTIFY_IGNORED;
- }
- }
- if ((event_is_ascii(event) || event_is_meta(event))
- && event_is_up(event)) return NOTIFY_IGNORED;
-#ifdef WANT_CAPS_LOCK
-/* shift alpha chars to upper case if toggle is set */
- if ((caps_lock) && event_is_ascii(event)
- && (event_id(event) >= 'a') && (event_id(event) <= 'z'))
- event_set_id(event, (event_id(event) - 32));
-/* crufty, but it works for now. is there an UPCASE(event)? */
-#endif
- return notify_next_event_func (window, event, arg, type);
-}
-
-main (argc, argv)
- int argc;
- char **argv;
-{
- int error_code; /* Error codes */
-
- if(getenv("DEBUGEMACSTOOL"))
- console = fdopen (console_fd = open("/dev/console",O_WRONLY), "w");
-
- /* do this first, so arglist can override it */
- frame_icon = icon_create (ICON_LABEL, "Emacstool",
- ICON_IMAGE, &icon_image,
- 0);
-
- putenv("IN_EMACSTOOL=t"); /* notify subprocess that it is in emacstool */
-
- if (putenv("TERM=sun") != 0) /* TTYSW will be a TERM=sun window */
- {fprintf (stderr, "%s: Could not set TERM=sun, using `%s'\n",
- argv[0], (char *)getenv("TERM")) ;};
- /*
- * If TERMCAP starts with a slash, it is the pathname of the
- * termcap file, not an entry extracted from it, so KEEP it!
- * Otherwise, it may not relate to the new TERM, so Nuke-It.
- * If there is no TERMCAP environment variable, don't make one.
- */
- {
- char *termcap ; /* Current TERMCAP value */
- termcap = (char *)getenv("TERMCAP") ;
- if (termcap && (*termcap != '/'))
- {
- if (putenv("TERMCAP=") != 0)
- {fprintf (stderr, "%s: Could not clear TERMCAP\n", argv[0]) ;} ;
- } ;
- } ;
-
- /* find command to run as subprocess in window */
- if (!(argv[0] = (char *)getenv("EMACSTOOL"))) /* Set emacs command name */
- argv[0] = emacs_name;
- for (argc = 1; argv[argc]; argc++) /* Use last one on line */
- if(!(strcmp ("-rc", argv[argc]))) /* Override if -rc given */
- {
- int i = argc;
- argv[argc--]=0; /* kill the -rc argument */
- if (argv[i+1]) { /* move to agrv[0] and squeeze the rest */
- argv[0]=argv[i+1];
- for (; argv[i+2]; (argv[i]=argv[i+2],argv[++i]=0));
- }
- }
-
- strcpy (buffer, title);
- strncat (buffer, argv[0], /* append run command name */
- (BUFFER_SIZE - (strlen (buffer)) - (strlen (argv[0]))) - 1);
-
- /* Build a frame to run in */
- frame = window_create ((Window)NULL, FRAME,
- FRAME_LABEL, buffer,
- FRAME_ICON, frame_icon,
- FRAME_ARGC_PTR_ARGV, &argc, argv,
- 0);
-
- /* Create a tty with emacs in it */
- ttysw = window_create (frame, TTY,
- TTY_QUIT_ON_CHILD_DEATH, TRUE,
- TTY_BOLDSTYLE, 8,
- TTY_ARGV, argv,
- 0);
-
- window_set(ttysw,
- WIN_CONSUME_PICK_EVENTS,
- WIN_STOP,
- WIN_MOUSE_BUTTONS, WIN_UP_EVENTS,
- /* LOC_WINENTER, LOC_WINEXIT, LOC_MOVE, */
- 0,
-
- WIN_CONSUME_KBD_EVENTS,
- WIN_STOP,
- WIN_ASCII_EVENTS,
- WIN_LEFT_KEYS, WIN_TOP_KEYS, WIN_RIGHT_KEYS,
- /* WIN_UP_ASCII_EVENTS, */
- 0,
-
- 0);
-
- font_height = (int)window_get (ttysw, WIN_ROW_HEIGHT);
- font_width = (int)window_get (ttysw, WIN_COLUMN_WIDTH);
-
- /* Interpose my event function */
- error_code = (int) notify_interpose_event_func
- (ttysw, input_event_filter_function, NOTIFY_SAFE);
-
- if (error_code != 0) /* Barf */
- {
- fprintf (stderr, "notify_interpose_event_func got %d.\n", error_code);
- exit (1);
- }
-
- window_main_loop (frame); /* And away we go */
-}
diff --git a/lib-src/hexl.c b/lib-src/hexl.c
deleted file mode 100644
index 8b28880ea79..00000000000
--- a/lib-src/hexl.c
+++ /dev/null
@@ -1,219 +0,0 @@
-#include <stdio.h>
-#include <ctype.h>
-
-#define DEFAULT_GROUPING 0x01
-#define DEFAULT_BASE 16
-
-#undef TRUE
-#undef FALSE
-#define TRUE (1)
-#define FALSE (0)
-
-extern void exit(), perror();
-
-int base = DEFAULT_BASE, un_flag = FALSE, iso_flag = FALSE, endian = 1;
-int group_by = DEFAULT_GROUPING;
-char *progname;
-
-main(argc, argv)
-int argc;
-char *argv[];
-{
- register long address;
- char string[18];
- FILE *fp;
-
- progname = *argv++; --argc;
-
- /*
- ** -hex hex dump
- ** -oct Octal dump
- ** -group-by-8-bits
- ** -group-by-16-bits
- ** -group-by-32-bits
- ** -group-by-64-bits
- ** -iso iso character set.
- ** -big-endian Big Endian
- ** -little-endian Little Endian
- ** -un || -de from hexl format to binary.
- ** -- End switch list.
- ** <filename> dump filename
- ** - (as filename == stdin)
- */
-
- while (*argv && *argv[0] == '-' && (*argv)[1])
- {
- /* A switch! */
- if (!strcmp(*argv, "--"))
- {
- --argc; argv++;
- break;
- } else if (!strcmp(*argv, "-un") || !strcmp(*argv, "-de"))
- {
- un_flag = TRUE;
- --argc; argv++;
- } else if (!strcmp(*argv, "-hex"))
- {
- base = 16;
- --argc; argv++;
- } else if (!strcmp(*argv, "-iso"))
- {
- iso_flag = TRUE;
- --argc; argv++;
- } else if (!strcmp(*argv, "-oct"))
- {
- base = 8;
- --argc; argv++;
- } else if (!strcmp(*argv, "-big-endian"))
- {
- endian = 1;
- --argc; argv++;
- } else if (!strcmp(*argv, "-little-endian"))
- {
- endian = 0;
- --argc; argv++;
- } else if (!strcmp(*argv, "-group-by-8-bits"))
- {
- group_by = 0x00;
- --argc; argv++;
- } else if (!strcmp(*argv, "-group-by-16-bits"))
- {
- group_by = 0x01;
- --argc; argv++;
- } else if (!strcmp(*argv, "-group-by-32-bits"))
- {
- group_by = 0x03;
- --argc; argv++;
- } else if (!strcmp(*argv, "-group-by-64-bits"))
- {
- group_by = 0x07;
- endian = 0;
- --argc; argv++;
- } else
- {
- (void) fprintf(stderr, "%s: invalid switch: \"%s\".\n", progname,
- *argv);
- usage();
- }
- }
-
- do
- {
- if (*argv == NULL)
- fp = stdin;
- else
- {
- char *filename = *argv++;
-
- if (!strcmp(filename, "-"))
- fp = stdin;
- else
- if ((fp = fopen(filename, "r")) == NULL)
- {
- perror(filename);
- continue;
- }
- }
-
- if (un_flag)
- {
- char buf[18];
-
- for (;;)
- {
- register int i, c, d;
-
-#define hexchar(x) (isdigit(x) ? x - '0' : x - 'a' + 10)
-
- (void) fread(buf, 1, 10, fp); /* skip 10 bytes */
-
- for (i=0; i < 16; ++i)
- {
- if ((c = getc(fp)) == ' ' || c == EOF)
- break;
-
- d = getc(fp);
- c = hexchar(c) * 0x10 + hexchar(d);
- (void) putchar(c);
-
- if ((i&group_by) == group_by)
- (void) getc(fp);
- }
-
- if (c == ' ')
- {
- while ((c = getc(fp)) != '\n' && c != EOF)
- ;
-
- if (c == EOF)
- break;
- }
- else
- {
- if (i < 16)
- break;
-
- (void) fread(buf, 1, 18, fp); /* skip 18 bytes */
- }
- }
- }
- else
- {
- address = 0;
- string[0] = ' ';
- string[17] = '\0';
- for (;;)
- {
- register int i, c;
-
- for (i=0; i < 16; ++i)
- {
- if ((c = getc(fp)) == EOF)
- {
- if (!i)
- break;
-
- (void) fputs(" ", stdout);
- string[i+1] = '\0';
- }
- else
- {
- if (!i)
- (void) printf("%08x: ", address);
-
- if (iso_flag)
- string[i+1] =
- (c < 0x20 || (c >= 0x7F && c < 0xa0)) ? '.' :c;
- else
- string[i+1] = (c < 0x20 || c >= 0x7F) ? '.' : c;
-
- (void) printf("%02x", c);
- }
-
- if ((i&group_by) == group_by)
- (void) putchar(' ');
- }
-
- if (i)
- (void) puts(string);
-
- if (c == EOF)
- break;
-
- address += 0x10;
-
- }
- }
-
- if (fp != stdin)
- (void) close(fp);
-
- } while (*argv != NULL);
- return 0;
-}
-
-usage()
-{
- (void) fprintf(stderr, "usage: %s [-de] [-iso]\n", progname);
- exit(1);
-}
diff --git a/lib-src/timer.c b/lib-src/timer.c
deleted file mode 100644
index 3af3210f7d0..00000000000
--- a/lib-src/timer.c
+++ /dev/null
@@ -1,155 +0,0 @@
-#include <stdio.h>
-#include <signal.h>
-#include <fcntl.h> /* FASYNC */
-#ifdef USG /* FASYNC for SysV */
-#include <sys/file.h>
-#endif
-#include <sys/time.h> /* itimer */
-#include <sys/types.h> /* time_t */
-
-extern int errno;
-extern char *sys_errlist[], *malloc();
-extern time_t time();
-
-#define MAXEVENTS 256
-#define FS 1 /* field seperator for input */
-
-struct event {
- char *token;
- time_t reply_at;
-} *events[MAXEVENTS];
-
-int slot; /* The next open place in the events array */
-int mevent = 0; /* 1+ the highest event number */
-char *pname; /* programme name for error messages */
-
-/* Accepts a string of two fields seperated by a ';'
- * First field is string for getdate, saying when to wake-up.
- * Second field is a token to identify the request.
- */
-struct event *
-schedule(str)
- char *str;
-
-{
- extern time_t getdate();
- extern char *strcpy();
- time_t now;
- register char *p;
- static struct event e;
-
- for(p = str; *p && *p != FS; p++);
- if (!*p) {
- (void)fprintf(stderr, "%s: bad input format: %s", pname, str);
- return((struct event *)NULL);
- }
- *p++ = 0;
-
- if ((e.reply_at = getdate(str, NULL)) - time(&now) < 0) {
- (void)fprintf(stderr, "%s: bad time spec: %s%c%s", pname, str, FS, p);
- return((struct event *)NULL);
- }
-
- if ((e.token = malloc((unsigned)strlen(p) + 1)) == NULL) {
- (void)fprintf(stderr, "%s: malloc %s: %s%c%s",
- pname, sys_errlist[errno], str, FS, p);
- return((struct event *)NULL);
- }
- (void)strcpy(e.token,p);
-
- return(&e);
-}
-
-void
-notify()
-
-{
- time_t now, tdiff;
- register int i, newmax = 0;
- /* I prefer using the interval timer rather than alarm(); the latter
- could be substituted if portability requires it. */
- struct itimerval itimer;
-
- now = time((time_t *)NULL);
- slot = mevent;
- itimer.it_interval.tv_sec = itimer.it_interval.tv_usec = 0;
- itimer.it_value.tv_usec = 0;
- itimer.it_value.tv_sec = -1;
-
- for(i=0; i < mevent; i++) {
- while (events[i] && events[i]->reply_at <= now) {
- (void)fputs(events[i]->token, stdout);
- free(events[i]->token);
- free((char *)events[i]);
- events[i] = 0;
- }
-
- if (events[i]) {
- newmax = i+1;
- if ((tdiff = events[i]->reply_at - now) < (time_t)itimer.it_value.tv_sec
- || itimer.it_value.tv_sec < 0)
- /* next timeout */
- itimer.it_value.tv_sec = (long)tdiff;
- } else {
- /* Keep slot as the lowest unused events element */
- if (i < slot) slot = i;
- }
- }
- /* if the array is full to mevent, slot should be the next available spot */
- if (slot > (mevent = newmax)) slot = mevent;
- /* If there's no more events, SIGIO should be next wake-up */
- if (mevent) (void)setitimer(ITIMER_REAL, &itimer, (struct itimerval *)NULL);
-}
-
-void
-getevent()
-
-{
- extern char *memcpy(), *fgets();
- struct event *ep;
- char buf[256];
-
- /* in principle the itimer should be disabled on entry to this function,
- but it really doesn't make any important difference if it isn't */
-
- if (fgets(buf, sizeof(buf), stdin) == NULL) exit(0);
-
- if (slot == MAXEVENTS)
- (void)fprintf(stderr, "%s: too many events: %s", pname, buf);
-
- else {
- if ((events[slot] = (struct event *)malloc((sizeof(struct event))))
- == NULL)
- (void)fprintf(stderr,"%s: malloc %s: %s", pname, sys_errlist[errno],buf);
-
- else {
- if ((ep = schedule(buf)) == NULL)
- free((char *)events[slot]), events[slot] = 0;
-
- else {
- (void)memcpy((char *)events[slot],(char *)ep,sizeof(struct event));
- if (slot == mevent) mevent++;
- } /* schedule */
- } /* malloc */
- } /* limit events */
- /* timing, timing. Who knows what this interrupted, or if it said "now"? */
- notify();
-}
-
-/*ARGSUSED*/
-int
-main(argc, argv)
- int argc;
- char **argv;
-
-{
- for (pname = argv[0] + strlen(argv[0]); *pname != '/' && pname != argv[0];
- pname--);
- if (*pname == '/') pname++;
-
- (void)signal(SIGIO, getevent);
- (void)signal(SIGALRM, notify);
- (void)fcntl(0, F_SETFL, FASYNC);
-
- while (1) pause();
-}
diff --git a/lisp/COPYING b/lisp/COPYING
new file mode 100644
index 00000000000..9a170375811
--- /dev/null
+++ b/lisp/COPYING
@@ -0,0 +1,249 @@
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 1, February 1989
+
+ Copyright (C) 1989 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The license agreements of most software companies try to keep users
+at the mercy of those companies. By contrast, our General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. The
+General Public License applies to the Free Software Foundation's
+software and to any other program whose authors commit to using it.
+You can use it for your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Specifically, the General Public License is designed to make
+sure that you have the freedom to give away or sell copies of free
+software, that you receive source code or can get it if you want it,
+that you can change the software or use pieces of it in new free
+programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of a such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must tell them their rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any program or other work which
+contains a notice placed by the copyright holder saying it may be
+distributed under the terms of this General Public License. The
+"Program", below, refers to any such program or work, and a "work based
+on the Program" means either the Program or any work containing the
+Program or a portion of it, either verbatim or with modifications. Each
+licensee is addressed as "you".
+
+ 1. You may copy and distribute verbatim copies of the Program's source
+code as you receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice and
+disclaimer of warranty; keep intact all the notices that refer to this
+General Public License and to the absence of any warranty; and give any
+other recipients of the Program a copy of this General Public License
+along with the Program. You may charge a fee for the physical act of
+transferring a copy.
+
+ 2. You may modify your copy or copies of the Program or any portion of
+it, and copy and distribute such modifications under the terms of Paragraph
+1 above, provided that you also do the following:
+
+ a) cause the modified files to carry prominent notices stating that
+ you changed the files and the date of any change; and
+
+ b) cause the whole of any work that you distribute or publish, that
+ in whole or in part contains the Program or any part thereof, either
+ with or without modifications, to be licensed at no charge to all
+ third parties under the terms of this General Public License (except
+ that you may choose to grant warranty protection to some or all
+ third parties, at your option).
+
+ c) If the modified program normally reads commands interactively when
+ run, you must cause it, when started running for such interactive use
+ in the simplest and most usual way, to print or display an
+ announcement including an appropriate copyright notice and a notice
+ that there is no warranty (or else, saying that you provide a
+ warranty) and that users may redistribute the program under these
+ conditions, and telling the user how to view a copy of this General
+ Public License.
+
+ d) You may charge a fee for the physical act of transferring a
+ copy, and you may at your option offer warranty protection in
+ exchange for a fee.
+
+Mere aggregation of another independent work with the Program (or its
+derivative) on a volume of a storage or distribution medium does not bring
+the other work under the scope of these terms.
+
+ 3. You may copy and distribute the Program (or a portion or derivative of
+it, under Paragraph 2) in object code or executable form under the terms of
+Paragraphs 1 and 2 above provided that you also do one of the following:
+
+ a) accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of
+ Paragraphs 1 and 2 above; or,
+
+ b) accompany it with a written offer, valid for at least three
+ years, to give any third party free (except for a nominal charge
+ for the cost of distribution) a complete machine-readable copy of the
+ corresponding source code, to be distributed under the terms of
+ Paragraphs 1 and 2 above; or,
+
+ c) accompany it with the information you received as to where the
+ corresponding source code may be obtained. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form alone.)
+
+Source code for a work means the preferred form of the work for making
+modifications to it. For an executable file, complete source code means
+all the source code for all modules it contains; but, as a special
+exception, it need not include source code for modules which are standard
+libraries that accompany the operating system on which the executable
+file runs, or for standard header files or definitions files that
+accompany that operating system.
+
+ 4. You may not copy, modify, sublicense, distribute or transfer the
+Program except as expressly provided under this General Public License.
+Any attempt otherwise to copy, modify, sublicense, distribute or transfer
+the Program is void, and will automatically terminate your rights to use
+the Program under this License. However, parties who have received
+copies, or rights to use copies, from you under this General Public
+License will not have their licenses terminated so long as such parties
+remain in full compliance.
+
+ 5. By copying, distributing or modifying the Program (or any work based
+on the Program) you indicate your acceptance of this license to do so,
+and all its terms and conditions.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the original
+licensor to copy, distribute or modify the Program subject to these
+terms and conditions. You may not impose any further restrictions on the
+recipients' exercise of the rights granted herein.
+
+ 7. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of the license which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+the license, you may choose any version ever published by the Free Software
+Foundation.
+
+ 8. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to humanity, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these
+terms.
+
+ To do so, attach the following notices to the program. It is safest to
+attach them to the start of each source file to most effectively convey
+the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19xx name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the
+appropriate parts of the General Public License. Of course, the
+commands you use may be called something other than `show w' and `show
+c'; they could even be mouse-clicks or menu items--whatever suits your
+program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ program `Gnomovision' (a program to direct compilers to make passes
+ at assemblers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
new file mode 100644
index 00000000000..94490f6ef33
--- /dev/null
+++ b/lisp/ChangeLog
@@ -0,0 +1,5068 @@
+Fri Oct 30 19:36:38 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * Version 18.59 released.
+
+Wed Oct 21 00:36:11 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * sun-fns.el, sun-mouse.el, term/sun.el: New versions from Peck.
+
+ * dired.el (dired-chown): Treat silicon-graphics-unix like usg-unix-v.
+
+ * lpr.el (lpr-command):
+ Treat hpux and silicon-graphics-unix like usg-unix-v.
+
+Thu Oct 15 03:18:59 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * telnet.el (telnet): Wait for telnet output before sending `open'.
+
+Sun Oct 11 18:21:46 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * picture.el (edit-picture): Run picture-mode-hook.
+
+ * files.el (hack-local-variables): Undo March 5 change.
+
+Fri Oct 9 01:26:40 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * files.el (hack-local-variables): Don't allow `force' as local var.
+
+Thu Oct 8 02:48:50 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * files.el (hack-local-variables):
+ Ignore attempt to set inhibit-local-eval as local variable.
+
+Wed Oct 7 03:33:05 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * files.el (file-name-sans-versions): Recognize empty VMS version.
+
+Wed Sep 23 00:22:55 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * c-mode.el (calculate-c-indent): When testing for function start line,
+ match the first open paren; insist no = or doublequote before it.
+
+Sat Sep 19 01:58:01 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * rmail.el (rmail-insert-inbox-text): Make the inbox file empty here
+ if we rename it with rename-file here.
+ (rmail-get-new-mail): Always try deleting the files in delete-files.
+
+Fri Sep 18 02:58:14 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * rmail.el (rmail-get-new-mail): Truncate inbox file if we
+ fail to delete it, or if it's not in the ordinary mail spool dir.
+
+Sat Sep 12 04:39:41 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * files.el (backup-buffer): Delete %backup% before copying to it.
+
+Fri Sep 4 03:33:08 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * shell.el (make-shell): Don't call shell-mode if already in that mode.
+
+Sat Aug 29 04:25:31 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * picture.el (picture-snarf-rectangle): Delete extra closeparen.
+
+ * c-mode.el (calculate-c-indent): If taking indent from prev stmt
+ and it starts with an {, subtract c-brace-offset.
+
+Wed Aug 19 23:26:47 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * info.el (Info-mode): Add mode-class property.
+
+Fri Aug 14 03:50:30 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * compile.el (compile1): Don't mess with comp-proc if it's nil.
+
+ * info.el (Info-find-node): Be more abt format of tags table.
+
+Thu Jul 23 14:26:14 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * paths.el (mh-lib, mh-prog): Add more alternatives.
+
+Sat Jul 4 12:20:43 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * files.el (save-buffers-kill-emacs): Consider open net connections
+ as possibly requiring a query.
+
+Thu Jul 2 16:13:10 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * tags.el (visit-tags-table-buffer): Update file name after find-file.
+
+Fri Jun 12 20:12:12 1992 Jim Blandy (jimb@wookumz.gnu.ai.mit.edu)
+
+ * cal.el (generate-month): Removed extranous '7' from let* binding
+ of `first-day-of-month'.
+
+Thu Jun 11 18:30:36 1992 Jim Blandy (jimb@pogo.cs.oberlin.edu)
+
+ * cal.el (calendar): Do not assume that if `one-window-p' returns
+ non-nil, then we can shrink the current window vertically. This is
+ not true if the screen is split only into side-by-side windows;
+ shrinking the window in this case enlarges the minibuffer.
+ Instead, add up the height of the current window and the
+ minibuffer window and compare this with the height of the whole
+ screen, to see if the current window is full-height. If it is,
+ don't try to shrink the current window.
+
+Sat May 30 03:38:17 1992 Jim Blandy (jimb@wookumz.gnu.ai.mit.edu)
+
+ * dbx.el (run-dbx): Apply expand-file-name to PATH. Among other
+ things, this makes sure that the default-directory gets set to
+ something non-nil when we set it to (file-name-directory PATH).
+
+Tue May 19 23:23:53 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * subr.el (one-window-p): If arg is t, completely avoid minibuffer.
+
+Thu May 14 23:08:09 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * fill.el (fill-region-as-paragraph):
+ Handle fill-prefix wider than fill-column.
+
+Wed May 13 15:42:52 1992 Jim Blandy (jimb@wookumz.gnu.ai.mit.edu)
+
+ * loadup.el: Disable undo in *scratch* while we're loading the
+ files to dump, and re-enable it before we dump. We used to
+ disable it in init_buffer_once in ../src/buffer.c, but didn't
+ re-enable it anywhere; this was obscured by the fact that GC would
+ re-enable undo in all buffers.
+
+Tue May 5 23:15:57 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * ftp.el (ftp-command): Correctly ignore lines without status codes.
+ (ftp-write-file-hook): Clear modified flag in the proper buffer.
+
+ * fill.el (fill-individual-paragraphs): Choice of two modes,
+ controlled by fill-individual-varying-indent.
+
+Sun May 3 23:26:39 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * dired.el (dired-readin): At end, clear modified flag.
+
+Sat Apr 18 17:38:03 1992 Jim Blandy (jimb@pogo.cs.oberlin.edu)
+
+ * startup.el (normal-top-level): Don't change default-directory to
+ (getenv "PWD") unless they actually refer to the same directory.
+
+Fri Apr 17 11:16:33 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * rmail.el (rmail-unix-mail-delimiter): Doc str changed to comment.
+
+Wed Apr 15 02:08:03 1992 Jim Blandy (jimb@pogo.cs.oberlin.edu)
+
+ * simple.el (reindent-then-newline-and-indent,
+ newline-and-indent): Call the newline function instead of saying
+ (insert ?\n), so that auto fill mode will break lines correctly.
+
+ * rmail.el (rmail-unix-mail-delimiter): New variable.
+ (rmail-convert-to-babyl-format): Use it to recognize the start of
+ an mbox message.
+ (rmail-nuke-pinhead-header): Same.
+
+Wed Mar 25 17:47:25 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * sendmail.el (mail-do-fcc): Use regexp to find time zone.
+
+Tue Mar 24 00:01:37 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * picture.el (picture-snarf-rectangle): Effectively preserve
+ column of mark.
+
+Fri Mar 20 15:13:12 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * files.el (find-backup-file-name): Fix the overflow test.
+
+Sun Mar 15 23:04:19 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * simple.el (undo): Suppress message in minibuffer.
+
+Sat Mar 14 00:39:09 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * sendmail.el (mail-do-fcc): Insert the time zone before the year.
+
+ * x-mouse-el (x-mouse-set-point): Special case if mouse is past eob.
+
+Fri Mar 13 17:40:09 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * sendmail.el (mail-position-on-field): Insert new field differently.
+
+Wed Mar 11 18:29:09 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * files.el (set-visited-file-name): Add comments.
+
+ * sendmail.el (mail-position-on-field):
+ Do find separator even if it's the first line.
+
+Thu Mar 5 17:30:24 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * files.el (find-backup-file-name): Use make-backup-file-name.
+
+ * sendmail.el: Doc fix.
+
+ * rect.el (clear-rectangle): New arg, preserve-position.
+ (clear-rectangle-line): Do the real work.
+ * picture.el (picture-snarf-rectangle): Pass t for preserve-position.
+
+ * dired.el (dired-do-deletions): Don't try delete-file on a dir.
+
+ * rmail.el (rmail-forward): Look for >From if no From.
+
+Wed Mar 4 02:57:57 1992 Jim Blandy (jimb@wookumz.gnu.ai.mit.edu)
+
+ * telnet.el (read-password): Allow C-g to terminate password
+ entry.
+
+Mon Feb 3 16:44:51 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * add-log.el (add-change-log-entry): Don't get confused by
+ old-format entries that use `at' instead of `@'.
+
+Sat Feb 1 16:41:32 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * x-mouse.el (x-set-mouse-point): Handle continuation at a tab.
+
+Wed Jan 29 12:16:42 1992 Jim Blandy (jimb at pogo.cs.oberlin.edu)
+
+ * float.el (mantissa-minval): Make this (1- (ash 1 maxbit)),
+ rather than plain (ash 1 maxbit), since the latter can't be
+ negated.
+ (mantissa-half-minval): New constant.
+ (normalize): Shift negative numbers until the next value would be
+ less than mantissa-minval, not until the highest bit is one; the
+ latter is always true of a negative number.
+ (f+): Let f1 and f2 be the arguments with the greatest and least
+ exponents, not values. If a negative number with a greater
+ exponent is added to a positive number with a lesser exponent, the
+ positive number should be shifted right to meet the negative
+ number, not vice versa. You can't shift a normalized mantissa
+ left.
+
+Tue Jan 28 16:22:59 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * sendmail.el (mail-do-fcc): Put timezone in From line.
+
+Mon Jan 27 15:57:46 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * loaddefs.el (auto-mode-alist): Treat .texi like .texinfo.
+
+Tue Jan 21 18:07:19 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * mh-e.el: New version from Gildea.
+
+Thu Jan 16 01:10:02 1992 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * telnet.el (telnet-initial-filter): Bind `password'.
+
+Mon Jan 13 09:44:54 1992 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * files.el (set-visited-file-name): Error check for directories.
+ Do error checks before setting buffer-file-name.
+
+Wed Dec 25 22:24:50 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * mail-utils.el (mail-strip-quoted-names): Return nil if given nil.
+
+Sun Dec 8 00:28:11 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * texinfmt.el: Handle @need and @sp.
+
+Sat Nov 30 22:49:11 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * simple.el (prefix-arg-internal): Make C-u end the arg.
+ Doc fixes on the argument commands.
+
+Mon Nov 18 11:43:56 1991 Stephen Gildea (gildea at expo.lcs.mit.edu)
+
+ * mh-e.el:
+ (mh-reply): pass -noquery to repl
+ (mh-list-folders): obey mh-recursive-subfolders
+ (mh-redist-full-contents): change default to nil
+ (mh-unshar-msg): new function w variable mh-unshar-default-directory
+ (mh-before-quit-hook): new hook
+ (mh-read-folder-sequences): parse private sequences properly
+ (mh-undo): search backwards if nothing to undo on current message
+ (mh-folder-mode): turn on truncate-lines
+
+Sat Nov 16 00:45:58 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * fill.el (fill-region-as-paragraph): Don't forget which side of
+ a space point and markers were on. Add lots of comments.
+
+ * files.el (file-name-sans-versions): Quote period in VMS regexp.
+ Don't accept .nnn which is really VMS file extension.
+ Merge non-VMS regexps. Use just nil as length if no version.
+
+Fri Nov 15 13:18:00 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * replace.el (query-replace-help): Correction to explain action of SPC.
+
+Wed Oct 23 20:42:23 1991 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * bytecomp.el (byte-compile-cond-1): Typo in singleton uncond clause.
+
+Tue Oct 22 00:30:37 1991 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * replace.el (how-many): Do count successive blank lines matching ^$.
+
+Sat Oct 19 12:32:16 1991 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * simple.el (fixup-whitespace): Leave no space at end of line.
+
+Sun Oct 6 00:32:38 1991 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * bytecomp.el (byte-compile-file): Don't run emacs-lisp-mode-hook.
+
+ * files.el (automount-dir-prefix): New var.
+ (find-file-noselect): Use it.
+
+Sat Oct 5 13:28:25 1991 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * time.el (display-time-filter): Be consistent: space before words.
+
+ * texinfo.el (texinfo-mode): Don't call text-mode; run its hook once.
+
+Tue Sep 24 02:24:42 1991 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * isearch.el (nonincremental-search):
+ Use separate defaults var for regexp search, like isearch.
+
+Sun Sep 15 15:34:14 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * rnewspost.el (news-setup): Delete text rather than killing.
+
+ * inc-vers.el: Search load-path for version.el.
+
+Fri Sep 13 00:32:19 1991 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * fill.el (justify-current-line): Rewrite of insertion of spaces.
+
+ * x-mouse.el (x-mouse-select): Compensate for minibuf prompt width.
+
+Sat Sep 7 16:27:20 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * fill.el (fill-individual-paragraphs):
+ Find a fill-prefix that works for the whole paragraph.
+
+Mon Sep 2 20:28:24 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * server.el (server-start): Delete old socket in /tmp as well as in ~.
+
+Tue Jul 30 17:17:39 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * dired.el (dired-chown): Use /bin/chown on certain systems.
+
+Tue Jul 23 14:21:24 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * rmail.el (rmail-convert-to-babyl-format): Handle Content-Length.
+
+Sat Jun 29 13:07:39 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * simple.el (shell-command-on-region):
+ Handle case where input is from *Shell Command Output*.
+
+ * compile.el (compilation-parse-error): Don't screw up on silly lineno.
+
+Fri Jun 28 08:48:18 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * simple.el (kill-region): If read-only bfr, don't mess with undo.
+
+Mon May 13 11:37:01 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * view.el (View-previous-line, View-next-line): New functions.
+ (view-mode-map): Use them.
+ (view-mode-command-loop): Don't bind goal-column.
+
+ * loaddefs.el (auto-mode-alist): Recognize .emacs only at end.
+
+Thu May 2 14:35:31 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * time.el (display-time-filter): If load-average fails, run uptime.
+
+ * at386.el: New file.
+
+Tue Apr 30 18:14:58 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * mail-utils.el (mail-strip-quoted-names): Handle nested parens.
+
+ * isearch.el (isearch): * and ? are not special after incomplete input.
+ When they are special, use old other-end for cs in both reverse
+ and forward.
+
+Mon Apr 29 15:00:31 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * info.el (Info-read-subfile): Skip blank lines.
+
+Sat Apr 13 18:10:28 1991 Eric Youngdale (youngdale@v6550c.nrl.navy.mil)
+
+ * files.el (basic-save-buffer): Stop messing with the file protection
+ (mode) under VMS, since we are going to write a new file.
+
+ * vms-patch.el (make-auto-save-file-name): Fixed generation of the
+ name of the auto-save file, when the name of the file being edited has
+ a version number.
+
+
+Sun Mar 24 21:35:34 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * files.el (hack-local-variables): ignore-local-eval ignores `eval'.
+
+ * telnet.el (read-password): Clear quit-flag.
+
+Tue Mar 19 23:17:45 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * fill.el (justify-current-line): Adjust for 18.57 behavior
+ of current-column.
+
+Sun Mar 17 16:13:00 1991 Richard Stallman (rms@mole.ai.mit.edu)
+
+ * add-log.el (add-change-log-entry): Use @, not ` at '.
+
+ * fill.el (justify-current-line): Handle extra indent after prefix.
+
+Mon Mar 11 18:12:45 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * simple.el (kill-region): Don't copy from undo list if empty.
+
+Sun Mar 10 19:42:39 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * files.el (find-backup-file-name): Delete nothing if overflow
+ in number of versions to keep.
+
+Tue Mar 5 21:47:16 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * files.el (find-alternate-file): Avoid killing current buffer.
+
+Thu Feb 28 18:04:11 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * server.el (server-start): Don't use a pty.
+ * time.el (display-time): Likewise.
+ * mh-e.el (mh-exec-cmd-daemon): Likewise.
+
+ * bytecomp.el (byte-compile-cond-1): Better handling of
+ unconditional clauses.
+
+Tue Feb 26 16:00:30 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * isearch.el (isearch): Copy point from small window
+ before deciding whether to set the mark.
+
+Mon Feb 25 13:07:37 1991 Paul Hilfinger (hilfingr at hilfinger.cs.nyu.edu)
+
+ * fill.el (fill-individual-paragraphs): Changed response to mailp
+ to effect only leading lines in a region (was getting confused
+ about colons embedded in ordinary text). Changed method of
+ moving to next paragraph in the main loop to use forward-paragraph
+ rather than goto-char, since the final character position is
+ rendered obsolete by the intervening fill-region-as-paragraph.
+
+Sun Feb 24 18:06:43 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * vip.el (ex-write): Kill just this buffer, not Emacs.
+
+ * vip.el (vip-emacs-old-commands): New buffer-local variable.
+ (vip-change-mode): Redefine C-x 3 and C-x TAB, saving old definitions.
+ No longer redefine at top level.
+
+Sat Feb 9 13:16:53 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * sendmail.el (sendmail-send-it): Turn off undo in tembuf.
+
+ * x-mouse.el (x-mouse-set-point): Take account of minibuffer prompt.
+
+ * rmailout.el (rmail-output-to-rmail-file): Always insert at end.
+
+Fri Feb 8 16:22:43 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * simple.el (goto-line): Take special care of selective-display.
+ * compile.el (compilation-parse-errors): Likewise.
+
+Wed Feb 6 12:44:16 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * rnews.el (news-select-message): Error does not prevent update
+ of .newsrc.
+
+ * rmail.el (rmail-insert-inbox-text): Don't insert newline after
+ empty file.
+
+Tue Feb 5 13:19:19 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * info.el (Info-find-node): Try appending .info to node name.
+
+Mon Feb 4 21:49:39 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * info.el (Info-extract-menu-node-name): New arg MULTI-LINE.
+ (Info-follow-reference): Pass t for that.
+
+Sat Feb 2 13:26:42 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * files.el (basic-save-buffer): Clear setmodes if hook writes the file.
+
+Thu Jan 31 13:49:36 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * rmailout.el (rmail-output):
+ Don't pass nil to mail-strip-quoted-names.
+
+ * files.el (find-file-noselect): Strip auto-mount prefix only if safe.
+
+Fri Jan 25 16:41:18 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * Version 18.57 released.
+
+Fri Jan 18 02:06:18 1991 Jim Blandy (jimb at wookumz.ai.mit.edu)
+
+ * version.el (emacs-version): Change version number to 18.56.0.
+
+Wed Jan 16 18:57:23 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * Version 18.56 released.
+
+Tue Jan 15 23:25:27 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * startup.el (command-line-1): Update copyright year.
+
+Wed Jan 9 18:35:06 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * doctex.el (LaTeXify-DOC): Upgrade permission notice that is output.
+
+ * Most files: Upgrade permission notice.
+
+Tue Jan 8 15:02:30 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * rmail.el (rmail-insert-inbox-text): Put .newmail in dir with
+ rmail file.
+
+Fri Jan 4 00:41:56 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * files.el (find-file-noselect): Get rid of automounter prefixes.
+
+Mon Dec 31 23:49:38 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * files.el (revert-buffer): Clear buffer-backed-up if file has changed.
+
+Sun Dec 30 23:10:59 1990 Jim Blandy (jimb at pogo.ai.mit.edu)
+
+ * startup.el (command-line-1): Avoid binding load-path for -l
+ switch.
+
+Sun Dec 23 17:07:13 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * rmail.el (rmail-convert-to-babyl-format, rmail-nuke-pinhead-header):
+ Accept `remote from ...' at end of UNIX From line.
+
+Sat Dec 22 13:15:09 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * bytecomp.el (byte-compile-form): Handle call to explicit lambda.
+
+ * time.el (display-time): Specify precise directory for wakeup.
+ (display-time-filter): Don't display 0 as load.
+
+Fri Dec 21 11:32:28 1990 Chris Hanson (cph at kleph)
+
+ * info.el (Info-extract-menu-node-name): Permit \n between colon
+ and start of node name.
+
+Thu Dec 20 21:07:26 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * sort.el (sort-numeric-fields): Fix syntax of chars to be skipped.
+
+Tue Dec 18 20:25:28 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * files.el (hack-local-variables): Match suffix only at eol.
+
+Sun Dec 16 22:49:45 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * rmail.el (rmail-parse-file-inboxes): Look for BABYL OPTIONS in u.c.
+ (rmail-convert-to-babyl-format): Likewise.
+ And don't skip white space after ^_ that ends a babyl format message.
+
+Wed Dec 12 00:11:37 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * rmail.el (rmail-insert-inbox-text): Extra tests for POP.
+
+ * files.el (hack-local-variables): Display local vars at screen top.
+
+Mon Dec 10 12:24:56 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * sendmail.el: Doc fix.
+
+Tue Dec 4 21:01:26 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * server.el (server-process-filter): Don't be confused
+ if input from process is split into multiple chunks.
+
+ * time.el (display-time-filter): Let user specify mail file name.
+
+Thu Nov 29 20:43:40 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * files.el (hack-local-variables): Show buffer when asking question.
+
+ * rmail.el (rmail-insert-inbox-text): Don't give up if movemail fails.
+
+ * cl.el (safe-idiv): Avoid overflow computing s.
+
+Wed Nov 28 17:01:40 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * info.el (Info-extract-menu-item): Try exact match first.
+
+ * rmail.el (rmail-insert-inbox-text): Handle file names for pop.
+
+Mon Nov 26 17:02:13 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * bg-mouse.el (bg-insert-moused-sexp): If before ')', just skip that.
+
+Mon Nov 19 16:24:35 1990 Richard Mlynarik (mly at august-east)
+
+ * rfc822.el (rfc822-addresses): Blow out, don't loop, on ")
+ (rfc822-addresses-1) Error if address "phrase" not followed by
+ route-spec
+
+Tue Nov 13 22:29:01 1990 David J. MacKenzie (djm at apple-gunkies)
+
+ * fortran.el: Use domain format instead of uucp format for bug
+ list address.
+
+Mon Nov 12 17:03:44 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * lisp.el (lisp-complete-symbol): Use emacs-lisp-mode-syntax-table.
+
+Sun Nov 11 17:28:00 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * simple.el (kill-region): Share storage with undo list.
+
+Fri Nov 2 19:19:05 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * files.el (set-visited-file-name): Reject empty string as name.
+
+Thu Nov 1 20:30:50 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * lisp-mode.el (lisp-interaction-mode): Use Emacs Lisp syntax.
+
+Tue Oct 30 15:20:05 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * files.el (delete-auto-save-file-if-necessary):
+ Don't delete if auto-saving in visited file.
+
+Sun Oct 28 16:14:19 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * dabbrev.el (dabbrevs-search): Rename arg nocase to do-case.
+ (dabbrev-expand): Likewise. Also correct usage in replace-match.
+ Also reinsert original abbrev before copying case pattern.
+
+Thu Oct 25 22:08:34 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * x-win.el (command-switch-alist): Ignore -xrm.
+
+Tue Oct 16 13:32:21 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * files.el (revert-buffer): Discard all undo records.
+ * rmail.el (rmail-expunge, rmail-get-new-mail): Likewise.
+
+Wed Oct 10 18:00:11 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * rmailsum.el (rmail-summary-scroll-msg-up): Make msg visible.
+ (rmail-summary-scroll-msg-down): Likewise.
+
+Tue Oct 9 14:32:00 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * dired.el (dired-compress, dired-uncompress): Put output from
+ subprocess in a buffer to display it.
+
+ * lisp.el (lisp-complete-symbol): Last change clobbered beg.
+
+ * lisp-mode.el (indent-sexp): Make sure outer loop ends at eob.
+
+Mon Oct 8 19:03:01 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * files.el (save-buffers-kill-emacs): process-list is undef on VMS.
+
+Sun Sep 30 15:12:58 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * compile.el (compile1): Make compilation-error-regexp local
+ only after switching modes.
+
+ * bytecomp.el (byte-compile-lambda): Handle string constant as value.
+
+Fri Sep 28 17:52:57 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * mh-e.el: New version from Larus.
+
+Thu Sep 27 21:41:33 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * time.el (display-time-filter): Don't lose if load-average fails.
+
+Wed Sep 26 16:03:59 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * replace.el (occur-mode-goto-occurrence): Fix typo.
+
+Tue Sep 25 21:45:54 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * lisp.el (lisp-complete-symbol): Switch to lisp syntax temporarily.
+ Put output in ` *Completions*' buffer.
+
+Fri Sep 21 16:04:59 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * isearch.el (nonincremental-search): Bind cursor-in-echo-area
+ only as long as necessary.
+
+Thu Sep 20 14:06:22 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * uncompress.el (uncompress-while-visiting): Make buffer writable.
+
+Tue Sep 18 08:53:22 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * doctor.el (doctor-member, doctor-cadr, doctor-caddr): Renamed.
+ (doctor-cddr): Renamed.
+
+Thu Sep 13 22:23:01 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * x-mouse.el (x-mouse-set-point): Compensate for hscroll.
+
+Tue Sep 11 18:14:21 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * loadup.el: Handle dump-emacs-data if defined.
+
+Sat Sep 8 15:30:30 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * ftp.el (ftp-sentinel): Bind buffer-read-only only very locally.
+ (ftp-command): Ignore output lines with no status code.
+
+Fri Sep 7 13:25:37 1990 Chris Hanson (cph at kleph)
+
+ * scheme.el: Don't treat #| ... |# as comment syntax. Emacs
+ doesn't handle it correctly, and when `indent-sexp' sees #| it
+ inserts a semicolon in the comment column.
+
+Thu Sep 6 17:04:03 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * simple.el (kill-comment): Eliminate recursive-edit.
+
+Tue Sep 4 18:15:10 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * ftp.el (ftp-write-file): Accept status 125 as normal.
+
+Wed Aug 29 18:19:46 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * rmail.el (rmail-search): Call rmail-maybe-set-message-counters.
+
+Tue Aug 28 13:12:40 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * isearch.el (isearch): Do regexp-quote for what ^W and ^Y get.
+
+Thu Aug 16 13:31:56 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * vi.el (vi-next-line): Use next-line-internal.
+ * vip.el (vip-next-line): Likewise.
+
+ * telnet.el (telnet-mode-map): Take out copy-last-shell-input.
+
+ * time.el (display-time-filter): Check that file is non-empty.
+
+Wed Aug 15 18:31:16 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * x-win.el (x-new-display): Define only for X10.
+
+Thu Aug 9 17:36:45 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * replace.el (occur-mode-goto-occurrence): Calculate from
+ beginning of line in *occur* buffer.
+
+Tue Jul 31 23:21:10 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * files.el (find-alternate-file): Nothing special for read-only buf.
+
+Sun Jul 29 14:18:37 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * time.el (display-time-filter): Compute inbox name from user.
+
+Thu Jul 26 20:44:37 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * help.el (view-lossage): Use insert, not `newline'.
+
+ * info.el (Info-find-node): Set case-fold-search for tag tbl buffer.
+
+Wed Jul 18 16:23:10 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * files.el (save-buffers-kill-emacs): Improve confirmation msg.
+
+Sun Jul 15 22:34:33 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * register.el (view-register): Don't ignore first line of rect.
+
+Wed Jul 4 15:35:44 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * time.el (display-time-filter): Create the string here.
+ The output sent by the subprocess no longer matters.
+ (display-time): Run "wakeup", not "loadst".
+
+Sat Jun 30 13:07:32 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * dbx.el: Use C-x SPC for setting break point.
+
+Wed Jun 27 14:33:55 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * paragraphs.el (start-of-paragraph-text): Avoid infinite loop.
+
+Fri Jun 22 13:30:24 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * rmail.el (rmail): Ignore local variable specs in rmail file.
+
+Wed Jun 20 11:43:17 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * float.el: Provide 'float.
+
+Tue Jun 19 21:06:48 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * page.el (what-page): Reckon from beginning of line.
+
+Tue May 29 13:01:25 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * scheme.el (run-scheme): Autoload deleted. Done in loaddefs.
+
+Sat May 26 17:44:57 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * compile.el (next-error): Use set-buffer, not switch-to-buffer,
+ before parsing.
+
+Fri May 25 14:14:51 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * files.el (save-buffers-kill-emacs): Fix bugs in testing
+ for modified buffers.
+
+ * subr.el (undo-start, undo-more): New functions.
+
+Mon May 21 14:53:38 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * time.el (display-time): Local cleanup.
+
+ * simple.el (kill-comment): Local cleanup.
+
+ * buff-menu.el (Buffer-menu-buffer): Simplified.
+ Set Buffer-menu-buffer-column initially.
+
+ * rmail.el (rmail): Don't assume mode of existing buffer is rmail.
+ If not, switch to rmail-mode, unless it is rmail-edit-mode.
+
+Fri May 18 17:59:41 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * lisp-mode.el (indent-sexp): Typo in name inner-loop-done.
+ * c-mode.el (indent-c-exp): Likewise.
+
+Sat May 12 16:53:35 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * info.el (Info-read-subfile): Ignore blank lines in split file list.
+
+Tue May 1 14:49:46 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * replace.el (occur): Avoid infinite loop at end of buffer.
+
+Mon Apr 30 20:54:47 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * float.el (float-to-string):
+ Adjust POWER when rounding makes new digit.
+
+Sat Apr 28 17:51:24 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * files.el (save-buffers-kill-emacs): Query here about modified
+ buffers and active processes.
+
+Wed Apr 25 17:12:08 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * simple.el (next-line-internal): Handle track-eol more cleanly.
+
+Thu Apr 12 21:48:01 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * startup.el (normal-top-level): Don't check envvar PWD on vms.
+
+Thu Apr 5 16:41:44 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * rmailout.el (rmail-output-to-rmail-file): Set message counters
+ before inserting in a file being visited.
+
+ * startup.el (command-line-1): Always erase *scratch*, not current buf.
+
+Tue Apr 3 04:53:01 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * fill.el (fill-individual-paragraphs): Anchor regexp for MAILP=t.
+
+Sun Mar 18 23:03:33 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * c-mode.el: Doc fix.
+
+Fri Mar 9 18:24:21 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * rnewspost.el (news-mail-reply, news-reply, news-post-news):
+ Include newline before the blank line, when narrowing.
+
+Thu Feb 1 02:21:56 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * texinfmt.el (batch-texinfo-format): Paren error on (setq error 1).
+
+Thu Jan 4 21:09:29 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * doctor.el: Delete spurious symbol at top level.
+
+Sat Dec 16 08:59:00 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * c-mode.el (c-backward-to-noncomment): Stop better at beg of bfr.
+
+Wed Nov 8 15:56:52 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * debug.el (debug): No need to check match-data for invalid markers.
+
+Mon Nov 6 01:20:59 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * server.el (server-done): Add space to error message.
+
+Sat Oct 14 01:56:27 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * paragraphs.el (forward-paragraph): Don't hang at eob.
+
+Tue Aug 15 21:41:10 1989 Richard Stallman (rms at hobbes.ai.mit.edu)
+
+ * Version 18.55 released.
+
+ * files.el (basic-save-buffer): If rename of precious file fails,
+ don't try to delete it after new version is written.
+
+Wed Aug 9 19:26:25 1989 Chris Hanson (cph at kleph)
+
+ * xscheme.el: From the RCS change log:
+
+ (1.23) Guarantee that the process-filter's state is correctly
+ updated before calling any code that can possibly allow more input
+ to be read from the process.
+
+ (1.22) Remove filter queuing mechanism. Rewrite filter state
+ machine to be iterative instead of tail-recursive. Move all C-c
+ commands to control characters.
+
+ (1.21) Force control-g synchronization always. Turns out BSD had
+ the same problem as hp-ux.
+
+ (1.20) Don't use second argument to `interrupt-process' and
+ `quit-process'. Apparently that causes difficulties under Ultrix.
+
+Thu Jul 20 02:02:33 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * info.el (Info-follow-reference): Handle newline and indentation
+ immediately after *note.
+
+ * hideif.el (hif-tokenize): Recognize `defined', not `hif-defined',
+ in the input.
+
+Tue Jul 4 20:27:28 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * mailalias.el (build-mail-aliases): Accept `group' as synonym.
+
+ * nroff-mode.el (electric-nroff-mode): Arg now optional.
+
+ * man.el (insert-man-file): Handle HP's directories with .Z in
+ their names.
+
+Sun Jun 25 12:45:05 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * rmail.el (rmail, rmail-insert-inbox-text): For login name,
+ try LOGNAME, USER, and user-login-name.
+ * mail-utils.el (rmail-dont-reply-to): Likewise.
+
+Tue Jun 20 14:03:54 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * term/x-win.el: If x-sigio-bug is non-nil, don't use interrupts.
+
+Thu Jun 8 12:09:14 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * spell.el (spell-region): Downcase misspelled word.
+
+Tue Jun 6 19:58:01 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * chistory.el (list-command-history): Go to history buffer
+ before examining its text.
+
+Fri Jun 2 16:04:14 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * rmail.el (rmail-convert-to-babyl-format): Generalize time zone fmt.
+ (rmail-nuke-pinhead-header): Likewise.
+
+Wed May 31 18:05:20 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * cmacexp.el (c-macro-expand): Handle \-continuation of macros.
+
+Wed May 17 14:27:38 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * rmail.el (rmail-nuke-pinhead-header): Accept space before
+ numeric time zone in From line.
+
+ * sendmail.el (sendmail-send-it): Always pass -f option.
+
+Fri May 12 22:19:37 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * term/s4.el: Don't define M-9, M-0.
+ Typo in defn of M-N I.
+
+Wed Apr 26 16:17:02 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * Version 18.54 released.
+
+ * term/xterm.el: Set reset-terminal-on-clear.
+
+Wed Apr 12 10:45:30 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * picture.el (picture-tab): Dumb errors in prefix-arg case.
+
+Tue Apr 11 01:04:53 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * lpr.el (print-region-1): For tab-conversion case, insert specd range.
+
+Thu Apr 6 12:27:21 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * startup.el (normal-top-level): Use PWD envvar to set default dir.
+ (command-switch-alist): Doc fix.
+
+ * rmail.el (rmail-convert-to-babyl-format):
+ Bind case-fold-search to t for mmdf case.
+
+ * rmail.el (rmail-convert-to-babyl-format, rmail-nuke-pinhead-header):
+ Accept spaces at end of Unix-style From line.
+
+Sun Apr 2 00:24:51 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * paths.el (rmail-spool-directory): Treat silicon-graphics-unix
+ like usg.
+
+Tue Mar 14 17:23:47 1989 Randall Smith (randy at sugar-bombs.ai.mit.edu)
+
+ * rmail.el (rmail-convert-to-babyl-format): reset case-fold-search
+ to true in the mmdf case.
+
+Mon Mar 13 16:57:03 1989 Randall Smith (randy at sugar-bombs.ai.mit.edu)
+
+ * tex-mode.el (TeX-common-initialization): Made lines beginning
+ with % separate paragraphs.
+
+Thu Feb 23 06:47:13 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * Version 18.53 released.
+
+ * tex-mode.el (TeX-start): Wait 1 second for TeX to start.
+ (TeX-common-initialization): Make comment-start-skip find comment
+ at start of a line.
+ (TeX-region): don't include previous line (before start) in the header.
+
+ * autoinsert.el: Change defconst to defvar.
+
+Wed Feb 15 03:55:23 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * dbx.el (run-dbx): Set dbx-process.
+ (dbx-stop-at): Use that to decide where to send the string.
+
+Thu Dec 29 14:23:37 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * compile.el (compilation-sentinel): Set OPOINT, OMAX in proper buffer.
+
+Wed Dec 28 23:07:35 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * debug.el (cancel-debug-on-entry): Paren error in case for macros.
+
+ * spell.el (spell-region): Don't lose if `spell-filter' is local.
+
+ * texinfmt.el (texinfo-format-defun-1): Fix bug in &-kwds in @defun.
+ (texinfo-format-emph): Rescan the argument.
+
+ * lpr.el (print-region-1): sysV wants different options.
+
+ * rmail.el (rmail-convert-to-babyl-format):
+ Do case-significant searches.
+
+Thu Sep 1 14:22:30 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * Version 18.52 released.
+
+ * fortran.el (fortran-split-line): Add space before continuation-char.
+
+Mon Aug 29 15:57:20 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * mh-e.el: New version from Larus.
+
+Sun Aug 21 21:05:08 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * view.el (view-mode): Initially view-scroll-size is nil.
+ (view-scroll-size): If it's nil, return (view-window-size).
+
+Thu Aug 18 14:21:41 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * fill.el (justify-current-line): Skip fill-prefix before whitespace.
+
+ * spell.el (spell-region): Change minibuffer prompt.
+
+Mon Aug 15 19:37:27 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * add-log.el (add-change-log-entry): Log filename is now an arg;
+ prompt for it with `interactive'.
+ (add-change-log-entry-other-window): Always use default log filename
+ and never prompt for anything.
+
+Sat Aug 13 14:59:02 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * simula.el: New version from obh.
+
+ * add-log.el (add-change-log-entry): New arg OTHER-WINDOW.
+ (add-change-log-entry-other-window): New fn.
+ * loaddefs.el: Autoload that fn and put on C-x 4 a.
+
+Thu Aug 11 22:43:01 1988 Chris Hanson (cph at kleph)
+
+ * xscheme.el (xscheme-cd): New function to guarantee that `cd'
+ happens in Scheme process buffer.
+
+Mon Aug 8 08:09:17 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * life.el, saveconf.el, doctex.el: New files.
+
+ * files.el (create-file-buffer): Avoid empty buffer name for root dir.
+ * dired.el (dired-find-buffer): Let create-file-buffer do more work.
+ (dired-noselect): Use directory-file-name, file-name-as-directory.
+
+Thu Aug 4 15:26:44 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * server.el (server-process-filter): Handle +NNN to specify linenum.
+ (server-visit-files): Arg is now alist of (FILENAME . LINENUM).
+
+ * server.el (server-visit-files): criterion for revert is if either
+ buffer or file has changed.
+
+ * abbrev.el: Doc fix.
+ * files.el:
+
+Wed Aug 3 12:28:05 1988 Robert J. Chassell (bob at frosted-flakes.ai.mit.edu)
+
+ * texinfo.el: Changed fill-colum from 75 to 72. The larger
+ fill-column causes numerous overfull hboxes in TeX when you are
+ writing Emacs Lisp code that will be formatted as a Texinfo example.
+
+Sun Jul 31 06:46:43 1988 Richard Stallman (rms at frosted-flakes.ai.mit.edu)
+
+ * rmailsum.el (rmail-new-summary): Always go to line for current msg.
+ (rmail-summary-exit): Delete just current window, and that
+ only if Rmail was already in another window.
+
+Fri Jul 29 13:45:27 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * tags.el: provide 'tags.
+
+Tue Jul 26 16:30:30 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * info.el (Info-follow-reference): Handle extra newlines, tabs or
+ spaces inside of cross-references.
+
+ * outline.el: doc fix.
+
+Sat Jul 23 17:05:13 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * loaddefs.el: autoload texinfo-format-region.
+
+Fri Jul 22 05:11:50 1988 Richard Stallman (rms at frosted-flakes.ai.mit.edu)
+
+ * simple.el (transpose-subr-1): Error if regions overlap.
+
+ * dired.el (dired-flag-file-deleted): Directories no longer special.
+ * dired.el (dired-do-deletions): If deleting a dir, run `rmdir'.
+
+Tue Jul 19 00:43:31 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * ftp.el (ftp-find-file-or-directory): Typo in arg name.
+
+Mon Jul 18 00:24:40 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * c-fill.el: New file.
+
+ * compile.el (compilation-error-regexp): Exclude colon from filename.
+
+Sun Jul 17 13:43:49 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * view.el: `h' ran undefined command; make it like `?'.
+
+Sat Jul 16 22:25:36 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * spell.el (spell-region): Run spell-filter to alter the text
+ before actual checking.
+
+Fri Jul 15 04:10:30 1988 Richard Stallman (rms at frosted-flakes.ai.mit.edu)
+
+ * rmailsum.el (rmail-make-basic-summary-line): If sender is self,
+ show recipient instead, with `to:'.
+
+Wed Jul 13 13:36:36 1988 Richard Stallman (rms at wheat-chex.ai.mit.edu)
+
+ * files.el (auto-save-file-name-p): doc fix.
+
+Tue Jul 12 21:58:17 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * paths.el (rmail-spool-directory): Handle RTU like sysV.
+
+Sun Jul 10 14:43:44 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * compile.el (compile1): use set-buffer, not switch-to-buffer.
+
+ * startup.el (command-line): strip hyphens one by one from TERM type.
+
+Tue Jul 5 15:11:42 1988 Chris Hanson (cph at kleph)
+
+ * texinfmt.el: Add support for @defun and related commands.
+
+Tue Jul 5 14:00:46 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * loadup.el: Avoid setting the global variable `name'.
+
+Mon Jul 4 12:21:03 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * rmail.el (rmail-make-in-reply-to-field): Use doublequotes, not
+ parens, around sender name in rfc822 mode.
+
+ * info.el (Info-read-subfile): Don't lose if subfile header isn't
+ same length as main file header.
+
+Sun Jul 3 10:37:05 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * shell.el (shell-send-input): Put bound on search for prompt.
+
+Fri Jul 1 10:07:14 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * autoinsert.el: New file.
+
+ * text-mode.el (center-region): Don't let end-of-region
+ become wrong when insertion/deletion is done.
+
+ * info.el (Info-find-node): Typo in regexp.
+ (Info-following-node-name): At open paren, continue to close.
+
+ * tags.el (list-tags): Terminate scan on end-of-buffer.
+
+Thu Jun 30 10:09:19 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * loaddefs.el (auto-mode-alist): C mode for `.cc'.
+
+Mon Jun 27 12:22:11 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * paths.el (rmail-spool-directory): Treat unisoft like usg.
+
+ * texinfo.el (texinfo-show-structure): New function.
+ (texinfo-insert-*): Several new functions.
+ (texinfo-mode-map): New keymap.
+
+ * dired.el: provide 'dired.
+
+Thu Jun 23 11:02:37 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * files.el (hack-local-variables): Ignore `eval' if running as root.
+
+Wed Jun 22 10:33:39 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * nroff-mode.el (nroff-brace-table): Add G1 vs G2.
+
+Tue Jun 21 04:43:41 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * spell.el (spell-region, spell-string): Fix typo `spell-cmd'.
+
+Sun Jun 19 15:35:21 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * lpr.el (lpr-command): New variable holds the shell command to
+ print a file (normally "lpr").
+
+Wed Jun 15 06:13:32 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * rnewspost.el (news-inews): run news-inews-hook.
+
+ * rmail.el (rmail-show-message): run rmail-show-message-hook.
+
+Sun Jun 12 10:55:47 1988 Richard Stallman (rms at gluteus.ai.mit.edu)
+
+ * keypad.el: Additional conventional chars added in the comments.
+
+ * text-mode.el: erroneously installed text-mode-syntax-table
+ in current buffer.
+
+Thu Jun 9 05:28:48 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * fill.el (fill-region-as-paragraph): Err if fill-prefix is
+ too long for the fill-column.
+
+ * texinfmt.el (texinfo-format-{region,buffer-1}): Make sure buffer
+ ends in a newline.
+
+Tue Jun 7 12:47:31 1988 Chris Hanson (cph at kleph)
+
+ * xscheme.el (xscheme-process-filter-alist): add escape sequence
+ which instructs Emacs to change the working directory of the
+ Scheme process buffer. This change is required for Scheme runtime
+ library version 14.
+
+Thu Jun 2 06:36:43 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * sendmail.el (mail-do-fcc): avoid insert-buffer (too high level).
+
+Tue May 31 18:12:10 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * outline.el: Must put `\(...\)' around outline-regexp
+ when prepending `^'.
+
+Mon May 30 17:30:18 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * fortran.el, hanoi.el, helper.el, info.el, mlconvert.el, modula2.el,
+ rmail.el, sendmail.el, sort.el, underline.el: doc fixes.
+ * loaddefs.el: autoload doc fixes.
+
+Sat May 28 05:19:41 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * help.el (print-help-return-message): Handle pop-up-windows = nil.
+
+ * nroff-mode.el (nroff-brace-table): Add more pairs, for some mm macros
+ (nroff-comment-indent): Recognize ' like period.
+ (nroff-mode): .SK and .OP separate pages.
+
+ * shell.el (lisp-send-defun): Install new, corrected no-process check.
+
+Fri May 27 21:28:20 1988 Richard Stallman (rms at frosted-flakes.ai.mit.edu)
+
+ * c-mode.el (electric-c-terminator): Tests to distinguish labels
+ from other uses of colon failed if inserting at end of buffer.
+
+Tue May 24 15:09:32 1988 Richard Stallman (rms at frosted-flakes.ai.mit.edu)
+
+ * texinfmt.el (texinfo-parse-expanded-arg): like texinfo-parse-line-arg
+ but expand commands inside the arg.
+ (texinfo-index): Use that.
+ (@end ifinfo): Discard terminating newline.
+
+Mon May 23 12:45:52 1988 Richard Stallman (rms at frosted-flakes.ai.mit.edu)
+
+ * files.el (file-name-sans-versions): VMS version can be sep. by `.'.
+ Also delete mysterious line that removes `$__$'.
+
+Sun May 22 14:28:56 1988 Richard Stallman (rms at frosted-flakes.ai.mit.edu)
+
+ * gdb.el (gdb-filter-accumulate-marker): Empty gdb-filter-accumulate
+ since its contents are now in STRING.
+
+ * rnews.el (news-get-pruned-list-of-files): catch errors for
+ read-protected directories.
+
+Fri May 20 00:54:22 1988 Richard Stallman (rms at frosted-flakes.ai.mit.edu)
+
+ * meese.el: Bind off buffer-read-only while changing buffer.
+ Don't add protect-innocence-hook twice.
+
+ * sendmail.el (mail-do-fcc): If fcc file is in a buffer, append there.
+
+Mon May 16 21:17:39 1988 Richard Stallman (rms at frosted-flakes.ai.mit.edu)
+
+ * bibtex.el (bibtex-mode): Delete some keys that were vt100 keypad.
+ (bibtex-DEAthesis): Delete this and its key definition.
+ (bibtex-sun-*): Insert functions.
+
+Sun May 15 19:35:59 1988 Richard Stallman (rms at frosted-flakes.ai.mit.edu)
+
+ * loaddefs.el: Doc fix.
+
+Thu May 12 17:47:35 1988 Richard Stallman (rms at frosted-flakes.ai.mit.edu)
+
+ * tex-mode.el (TeX-region): Pass nil to make-shell as startfile arg.
+
+Wed May 11 14:20:41 1988 Richard Stallman (rms at frosted-flakes.ai.mit.edu)
+
+ * shell.el (make-shell): If PROGRAM is nil, default like M-x shell.
+
+ * tex-mode.el (TeX-region): Used eliminated fn. expand-directory-name.
+
+Tue May 10 21:45:09 1988 Richard Stallman (rms at corn-chex.ai.mit.edu)
+
+ * shell.el (lisp-send-defun): Undo last change.
+
+ * loaddefs.el (rmail-primary-inbox-list): Doc fix.
+
+Sun May 8 15:15:45 1988 Richard Stallman (rms at lucky-charms.ai.mit.edu)
+
+ * man.el (manual-entry): Handle section names > 1 letter.
+
+ * paths.el (manual-formatted-*): Add alternative for Xenix.
+
+Fri May 6 10:49:12 1988 Richard Stallman (rms at frosted-flakes.ai.mit.edu)
+
+ * Version 18.51 released.
+
+ * vms-patch.el (vms-suspend-resume-hook): New fn to find a file
+ after Emacs is resumed on VMS.
+ (vms-suspend-hook): Don't suspend if logical name DONT_SUSPEND_EMACS
+
+ * server.el (server-start): Don't say "restarting" the first time.
+
+ * files.el (revert-buffer): Avoid wta error if autosave turned off.
+
+Tue May 3 08:30:12 1988 Richard Stallman (rms at frosted-flakes.ai.mit.edu)
+
+ * icon.el: New file.
+
+Mon May 2 17:44:49 1988 Brian Fox (bfox at rice-krispies.ai.mit.edu)
+
+ * replace.el (perform-replace): Make `y' do what SPC does, `n' do
+ what DEL does, and `q' do what ESC does. The original set of keys
+ still work.
+
+Sun May 1 17:09:04 1988 Richard Stallman (rms at frosted-flakes.ai.mit.edu)
+
+ * gdb.el (gdb-filter-insert): Save and restore prev. current buffer.
+ (gdb-filter-accumulate-marker): set-buffer should not be done here.
+
+Thu Apr 28 17:46:02 1988 Chris Hanson (cph at kleph)
+
+ * xscheme.el: Force use of pipes for communication with inferior
+ Scheme. This avoids bugs in PTY implementations on various
+ systems.
+
+Mon Apr 25 08:56:41 1988 Chris Hanson (cph at kleph)
+
+ * scheme.el: Add indentation for `with-values'.
+
+Fri Apr 22 07:12:46 1988 Richard Stallman (rms at frosted-flakes.ai.mit.edu)
+
+ * shell.el (shell-send-input, lisp-send-defun): Err right away
+ if shell no process.
+
+ * text-mode.el (center-line): doc fix.
+
+Thu Apr 21 01:00:45 1988 Richard Stallman (rms at corn-chex.ai.mit.edu)
+
+ * texinfmt.el (texinfo-format-region): Select the output buffer
+ at the beginning. Copy the @setfilename command as well as
+ the specified region. At end, put point at top.
+ Accept @bye only at beg of line.
+
+Wed Apr 20 19:20:33 1988 Richard Stallman (rms at frosted-flakes.ai.mit.edu)
+
+ * informat.el (Info-validate): Change message for Next's Previous.
+ Now the word "invalid" must be included in the message string
+ if it is wanted.
+
+Tue Apr 19 00:01:22 1988 Richard Stallman (rms at frosted-flakes.ai.mit.edu)
+
+ * cl-indent.el (common-lisp-indent-hook): Handle ` like '.
+
+ * gdb.el: Completely rewritten filtering mechanism (by cph).
+ Should look the same to the user.
+
+Mon Apr 18 16:17:42 1988 Richard Stallman (rms at frosted-flakes.ai.mit.edu)
+
+ * startup.el (command-line): Treat `_' in term-type name like `-'.
+
+ * term/apollo.el: New file, loads vt100.el.
+
+ * dired.el (dired-mode): Allow no arg--to put any old dir into
+ dired mode. Make it interactive.
+
+ * simple.el (indent-for-comment): If comment-start-skip has \(...\),
+ the delimiter starts where the end of the first pair matches.
+
+ * tex-mode.el (TeX-common-initialization): Add a \(...\) to
+ comment-start-skip so its end is always at start of delimiter.
+
+Thu Apr 14 05:54:37 1988 Richard Stallman (rms at frosted-flakes.ai.mit.edu)
+
+ * paragraph.el (forward-paragraph): Bug in pragraph-ignore-fill-prefix.
+
+ * terminal.el (te-sentinel): Delete whitespace at end of buffer
+ before inserting the message.
+
+ * debug.el (debug): Bind executing-macro to nil; avoid lossage
+ if enter debugger while kbd macro is running.
+
+ * rmailout.el (rmail-output-to-rmail-file):
+ Error if output file is same as current file.
+
+ * rmailout.el (rmail-output): Don't die if rmail-last-file is nil.
+
+Wed Apr 13 10:48:13 1988 Leonard H. Tower Jr. (tower at rice-krispies.ai.mit.edu)
+
+ * rnews.el: fixed mis-documentation.
+
+Wed Apr 13 00:55:00 1988 Richard Stallman (rms at frosted-flakes.ai.mit.edu)
+
+ * dired.el (dired-readin): Print msg on startup and when done.
+
+ * spell.el (spell-command): New var; command to use to invoke
+ the spell program.
+
+ * terminal.el (terminal-emulator): Choose default shell like shell.el.
+ Use /bin/sh for changing env.
+ (te-parse-program-and-args): Use shell-file-name for globbing.
+
+ * dired.el (dired-rename-file): Include old file name in prompt.
+
+ * cal.el (calendar): Convert any nonnull arg to a number.
+
+Tue Apr 12 13:05:18 1988 Chris Hanson (cph at kleph)
+
+ * xscheme.el: Change to print ";No value" when the value of an
+ expression is undefined.
+
+Sun Apr 10 02:33:43 1988 Richard Stallman (rms at frosted-flakes.ai.mit.edu)
+
+ * kermit.el: New file.
+
+ * tex-mode.el (TeX-common-initialization): Make TeX-command, etc.,
+ local here rather than in both callers.
+ Provide 'tex-mode.
+ (TeX-start-shell): Make keymap only once, and reuse it.
+ Pass 'nostartfile, not "/dev/null", to `make-shell'.
+ (set-buffer-directory): Use file-name-as-directory. Don't use...
+ (expand-directory-name): function deleted.
+
+ * simple.el (indent-for-comment): If comment-start-skip matches a
+ string with nonfinal whitespace, the comment delimiter starts
+ after that whitespace (for indentation purposes).
+ Don't modify the buffer if existing indent is correct.
+
+ * cmacexp.el (c-macro-expand): Use cpp to expand macros in the region.
+ * c-mode.el: Autoload that.
+
+ * texinfmt.el (texinfo-format-scan): Guts of texinfo-format-buffer-1
+ split into a new function.
+ Delete handling of C-q, which is not used in Texinfo nowadays.
+ (texinfo-format-region): New function to format a region.
+
+Sat Apr 9 11:48:24 1988 Leonard H. Tower Jr. (tower at frosted-flakes.ai.mit.edu)
+
+ * rnewspost.el (news-post-news, news-reply) No longer re-inits
+ *post-news* buffer, if buffer-modified-p.
+
+Sat Apr 9 03:09:36 1988 Richard Stallman (rms at frosted-flakes.ai.mit.edu)
+
+ * spook.el (shuffle-vector): Rewrite by phr.
+
+ * undigest.el (undigestify-rmail-message): Put space before `unseen'.
+
+ * ada.el, c-mode.el, lisp-mode.el, mim-mode.el, modula2.el, prolog.el,
+ scheme.el: Make paragraph-ignore-fill-prefix locally t in these modes.
+ * paragraph.el (forward-paragraph): Ignore fill-prefix if
+ Make paragraph-ignore-fill-prefix is non-nil.
+
+Fri Apr 8 05:39:13 1988 Richard Stallman (rms at frosted-flakes.ai.mit.edu)
+
+ * man.el, loaddefs.el: Doc fix.
+
+Wed Apr 6 21:06:52 1988 Robert J. Chassell (bob at frosted-flakes.ai.mit.edu)
+
+ * loaddefs.el: added `.texinfo' to the less common extensions
+ section of the auto-mode-alist so that emacs chooses the correct
+ mode for files with this extension.
+
+Fri Apr 1 17:53:57 1988 Richard M. Stallman (rms at wilson)
+
+ * gdb.el (gdb): Specify -cd option to GDB so GDB will use
+ the same path for the dir as the user is using in Emacs.
+
+Thu Mar 24 01:15:15 1988 Richard M. Stallman (rms at wilson)
+
+ * spook.el: New file.
+
+ * nroff-mode.el (forward-text-line): either . or ' starts a request.
+ (nroff-mode): In paragraph-{start,separate}, ditto.
+ (electric-nroff-newline): Don't insert extra newlines.
+
+Wed Mar 23 16:21:02 1988 Richard M. Stallman (rms at wilson)
+
+ * x-mouse.el: Change unshifted clicks for x11.
+ Bind all up-clicks to no-op.
+
+ * term/x-win.el (command-switch-alist): Ignore all X's switches
+ in x11.
+ Don't test fboundness of `x-change-display'.
+ On x11, don't set-input-mode or set term-setup-hook.
+ x-switches feature now broken.
+
+ * term/x11-win.el: Delete this file since X11 is now
+ a subcase of X.
+
+Sun Mar 20 14:23:07 1988 Richard M. Stallman (rms at wilson)
+
+ * rmailkwd.el (rmail-next-labeled-message): Allow space
+ before the label name (since now they are supposed to be there).
+
+ * paths.el (rmail-primary-inbox-list): Don't define it here.
+ * loaddefs.el: Define it here but set it to nil.
+ * rmail.el (rmail): If it's nil, compute the default here.
+ Now we decide $LOGNAME vs $USER at run time, not build time.
+
+ * lisp-mode.el (lisp-indent-line):
+ Single-semicolon comment lines should be indented at comment col.
+
+ * cl-indent.el (lisp-indent-do): Smarter version from Kevin Layer.
+
+ * cl.el (setf): Simplify code produced; don't use `apply'
+ and, if handler isn't a macro, don't bind any temp vars.
+
+ * cl.el: Make and doc strings and error messages use GNU style.
+
+Sat Mar 19 17:18:01 1988 Richard M. Stallman (rms at wilson)
+
+ * hideif.el: New version from liberte@b.cs.uiuc.edu.
+
+ * VMS-oriented bug fixes from David Gentzel.
+
+ * texinfmt.el (texinfo-format-setfilename): expand the filename.
+ (texinfo-do-itemize): Don't indent an empty line.
+ (texinfo-format-printindex): On VMS, use texinfo-sort-region to sort.
+ (texinfo-sort-{region,startkeyfun}): New functions.
+
+ * sort.el: provide 'sort.
+
+ * sendmail.el (mail): Doc fix.
+
+ * help.el (help-with-tutorial): Use expanded file name for making bfr.
+
+ * info.el (Info-find-node): Remove versions from file name.
+ * informat.el (Info-split): Remove versions from file name.
+
+ * bytecomp.el (byte-compile-file, byte-recompile-directory):
+ Remove versions from name of file to write. Good on VMS.
+ (batch-byte-compile): Likewise.
+
+Fri Mar 18 13:11:35 1988 Chris Hanson (cph at kleph)
+
+ * term/x11-win.el (command-switch-alist): Option "-rn" mistakenly
+ omitted from this list.
+
+Fri Mar 18 15:42:19 1988 Richard M. Stallman (rms at wilson)
+
+ * modula2.el: Changes from Michael Schmidt:
+ Better prompting in m2-for. Variables for program name for
+ compilation and for linking. Don't assume executable name
+ comes from module name. m2-toggle knows about .md and .mi files.
+
+ * rmail.el (rmail): Default for C-o is now `xmail';
+ rmail-last-rmail-file now defaults independently to `XMAIL'.
+
+ * lisp-mode.el (lisp-mode): Define C-c C-l as M-x run-lisp.
+
+ * paths.el (rmail-primary-inbox-list): Use rmail-spool-directory
+ as a basis for value of this; avoid redundant decisions.
+
+ * rnews.el (news-update-message-read): typo, cdadr => news-cdadr.
+
+ * gdb.el (gdb): expand `path'; start-process loses if
+ default-directory is not absolute.
+
+ * tags.el (find-tag-tag): Create this function again
+ to hold shared arg-reading code for find-tag and find-tag-other-window.
+ (find-tag, find-tag-other-window): Use find-tag-tag.
+
+ * shell.el (inferior-lisp-mode): lisp-mode-variables needs an arg.
+ Also improve the doc string.
+ * chistory.el (Command-history-setup): Likewise.
+
+Thu Feb 11 01:37:48 1988 Richard Stallman (rms at frosted-flakes.ai.mit.edu)
+
+ * Version 18.50 released.
+
+ * tex-mode.el (tex-mode): Use the default if file has no tex commands.
+
+ * term/vt200.el: Delete vt200-enable-arrows; leave the standard
+ name enable-arrow-keys.
+
+ * version.el (emacs-build-system): Store system name on which
+ Emacs was built.
+ * version.el (emacs-version): Print that system name.
+
+ * vip.el: Install version 3.5 sent by author.
+
+ * man.el (nuke-nroff-bs): New regexp for footers on hpux.
+
+Wed Feb 10 12:34:14 1988 Richard Stallman (rms at frosted-flakes.ai.mit.edu)
+
+ * simple.el (fundamental-mode): Delete fundamental-mode-map.
+
+Mon Feb 8 22:50:08 1988 Richard Stallman (rms at frosted-flakes.ai.mit.edu)
+
+ * paths.el (rmail-primary-inbox-list): Check separately for which
+ directory and which envvar.
+
+Sat Feb 6 18:31:55 1988 Richard Stallman (rms at frosted-flakes.ai.mit.edu)
+
+ * loaddefs.el: Autoload `gdb'.
+
+ * gdb.el: New file, interface to GDB. From Schelter,
+ but rewritten to use the new GDB -fullname feature
+ and the new Emacs overlay-arrow-position feature.
+
+ * dbx.el: New file (Masanobu's version,
+ changed to use overlay-arrow-string).
+
+Thu Feb 4 21:00:23 1988 Richard Stallman (rms at frosted-flakes.ai.mit.edu)
+
+ * mh-e.el: Version 3.4o from Larus.
+
+Sun Jan 31 18:16:14 1988 Richard Stallman (rms at frosted-flakes.ai.mit.edu)
+
+ * term/vt125.el, term/vt240.el: New files:
+ Just load vt100.el or vt200.el.
+
+Thu Jan 28 07:21:54 1988 Richard Stallman (rms at frosted-flakes.ai.mit.edu)
+
+ * tags.el (find-tag-tag): Deleted.
+ * tags.el (find-tag-default): New function returns default tag
+ based on buffer text, or nil.
+ Fix several bugs such as handling of quote-characters,
+ and case of before or after a list or near unbalanced paren.
+
+ * tags.el (find-tag): Use find-tag-default and show default in the
+ prompt while reading the tag.
+
+Sun Jan 24 02:38:17 1988 Richard Stallman (rms at frosted-flakes.ai.mit.edu)
+
+ * undigest.el (undigestify-rmail-message): Accept "Apparently-To".
+
+Fri Jan 22 22:46:19 1988 Richard Stallman (rms at frosted-flakes.ai.mit.edu)
+
+ * edt.el (edt-bind-gold-keypad): New fn so that calls to
+ define-keypad-key are deferred till edt-mode is turned on.
+
+Thu Jan 21 23:11:14 1988 Richard Stallman (rms at frosted-flakes)
+
+ * simple.el (kill-line): doc fix.
+
+Wed Jan 20 03:22:12 1988 Richard Stallman (rms at frosted-flakes)
+
+ * rmail.el (rmail-get-new-mail): If save fails, recount messages.
+ * rmail.el (rmail-revert): Handle revert-buffer; recount messages.
+ * rmail.el (rmail-variables): Set up to use this.
+ * rmail.el (rmail-convert-file): Babyl-mode conversion code
+ moved here from `rmail'.
+
+ * files.el (revert-buffer): Return t if did revert.
+
+Tue Jan 19 21:54:04 1988 Richard Stallman (rms at frosted-flakes)
+
+ * sendmail.el (mail-send-and-exit): Don't delete the window
+ unless an rmail-mode buffer is in the next window.
+
+Tue Jan 19 14:03:23 1988 Chris Hanson (cph at sugar-smacks)
+
+ * xscheme.el: Extensive changes including better documentation, a
+ new major mode `scheme-debugger-mode', and a new format for the
+ modeline when using the Scheme interface.
+
+ The major mode `scheme-debugger-mode' is used when Scheme is
+ running one of the character-driven debugger interfaces. It is
+ like Scheme mode except that evaluation is disabled, and
+ characters that are normally self-inserting instead are
+ transmitted to the Scheme process.
+
+ The modeline is changed so that information about the state of the
+ Scheme process is shown only in buffers whose major mode is
+ `scheme-mode' or one of the related Scheme major modes.
+ Information about the state of the read-eval-print loop is shown
+ only in the Scheme process buffer.
+
+ All of these changes are upwards compatible with versions of
+ Scheme which ran using the previous interface. However, some of
+ the features will not be enabled in older Scheme systems. Newer
+ versions of Scheme (specifically, those newer than release 6.1.1)
+ require the new interface for correct operation. They will not
+ work correctly with older version of this interface.
+
+ * scheme.el: Minor changes to support "xscheme.el" changes.
+ Mostly this involved adding hooks to existing facilities.
+
+Tue Jan 19 05:07:25 1988 Richard Stallman (rms at frosted-flakes)
+
+ * c-mode.el (indent-c-exp): Use new state-element from
+ parse-partial-sexp to handle case of (...newline...) {...
+
+Sun Jan 17 21:53:57 1988 Richard Stallman (rms at frosted-flakes)
+
+ * rmail.el (rmail-display-labels): Preserve buffer bounds correctly.
+ Remove extra spaces from the string before displaying it.
+
+ * rmail.el (rmail-insert-inbox-text): message only if file exists.
+ * rmail.el (rmail-get-new-mail): Don't save if was no new mail.
+
+Fri Jan 15 16:46:17 1988 Richard Stallman (rms at frosted-flakes)
+
+ * info.el (Info-search): Two bugs in indirect files:
+ Failed to search the indirect table right, and failed
+ to recover if nothing found.
+
+Thu Jan 14 00:23:29 1988 Richard Stallman (rms at frosted-flakes)
+
+ * loaddefs.el: Make search-... into user variables.
+
+Mon Jan 11 20:46:54 1988 Richard Stallman (rms at frosted-flakes)
+
+ * rmail.el (rmail-display-label): Put a space before each label
+ name if there wasn't one already. Turns out valid BABYL format
+ requires a space there.
+
+ * rmailkwd.el (rmail-set-label): Expect and write spaces before labels.
+ Eliminate the loop to delete such spaces.
+
+ * rmail.el (rmail-set-attribute): Expect and write spaces before labels.
+ * rmailsum.el (rmail-summary-by-labels): Expect spaces.
+
+ * info.el (Info-find-node): If filename starts with ./,
+ interpret relative to current directory.
+
+Sun Jan 10 15:51:08 1988 Richard Stallman (rms at frosted-flakes)
+
+ * undigest.el: If it fails, delete ALL of the temporary copy.
+
+Wed Jan 6 17:20:59 1988 Richard Stallman (rms at frosted-flakes)
+
+ * paths.el (mh-dir, mh-lib): Add two new alternatives to test for.
+ (For HPUX).
+ * paths.el (manual-formatted-dirlist) [HPUX]:
+ Add a completely new alternative value.
+
+Tue Jan 5 16:56:12 1988 Richard Stallman (rms at frosted-flakes)
+
+ * simple.el (indent-new-comment-line): In a comment, look back
+ for a line with a nonempty comment and indent the comment text
+ like it.
+
+ * lpr.el (print-buffer-1): Use `untabify' to expand tabs,
+ not the `expand' program. Fix other bugs with tab-width != 8.
+
+Sat Dec 26 13:27:00 1987 Richard Stallman (rms at frosted-flakes)
+
+ * c-mode.el (electric-c-terminator, c-indent-line):
+ Don't recognize `case' unless space or tab follows.
+
+Wed Dec 23 17:24:16 1987 Richard Mlynarik (mly at peduncle)
+
+ * loaddefs.el:
+ Update terminal-emualator documentation. (This wasn't done
+ after the last edit.)
+
+ * terminal.el:
+ Split out te-stty-string from function terminal-emulator.
+ Run "sh" if no env var SHELL.
+ Add nonstandard (though useful) NF and LP termcap flags.
+ Fix terminal-emulator documentation. Some comments.
+
+Tue Dec 22 19:34:37 1987 Richard Stallman (rms at frosted-flakes)
+
+ * rnews.el (news-get-pruned-list-of-files): Don't die on
+ unreadable directory.
+
+Mon Dec 21 19:52:15 1987 Richard Stallman (rms at frosted-flakes)
+
+ * window.el (split-widow-{vertically,horizontally}):
+ Make the arg optional.
+
+Wed Dec 9 18:32:21 1987 Richard Stallman (rms at frosted-flakes)
+
+ * picture.el (picture-clear-rectangle): Delete spurious arg.
+
+Tue Dec 8 16:09:28 1987 Richard Stallman (rms at frosted-flakes)
+
+ * rmailout.el (rmail-output): Don't crash if msg has no From.
+
+ * dabbrev.el (dabbrev-expand): Don't print messages.
+
+ * isearch.el (nonincremental-search): Put onto command-history.
+
+ * simple.el (kill-region): Doc fix.
+
+Sun Dec 6 01:22:27 1987 Richard Stallman (rms at frosted-flakes)
+
+ * compile.el (compilation-error-regexp): Last alternative
+ could match spuriously; change `.*' to ` *'. Change may be wrong;
+ nobody knows which program makes error messages this should match.
+
+ * terminal.el: Many fixes: some new termcap entries and fix bugs
+ in others.
+
+ Terminal width and height may be specified.
+ Scrolling is now the default. Enabling or disabling scrolling
+ during use does not really work because it is necessary to change
+ the termcap entry.
+
+ Do `stty new dec' at startup. Without this, you get printing
+ terminal echoing which looks very strange with DEL as the erase
+ char. This may lose on sysV, but the need can't be ignored.
+
+ One known bug remains a mystery: when running `ex', the empty-line
+ command fails to overprint the colon with the text that is
+ printed. The output Emacs receives contains a crlf in place of a cr.
+
+ * startup.el (command-line-1): Don't insert the startup-message
+ in a buffer other than *scratch*. Fixes bug with (rmail) in .emacs.
+
+ * files.el (save-buffer): Don't make a backup if arg is 0.
+ Clean up documentation.
+
+ * tags.el (tags-query-replace): Handle prefix arg like query-replace.
+
+ * replace.el ({keep,flush}-lines): Handle matches split across lines.
+
+Sat Dec 5 03:46:16 1987 Richard Stallman (rms at frosted-flakes)
+
+ * xscheme.el (xscheme-start-process): Put xscheme-mode-string
+ into mode-line-process.
+ * xscheme.el (add-to-global-mode-string): Function eliminated.
+
+ * startup.el: New var window-setup-hook; works like term-setup-hook.
+ * term/x-win.el: Set window-setup-hook instead of term-setup-hook.
+ term-setup-hook now for users only.
+
+Fri Dec 4 19:34:36 1987 Richard Stallman (rms at frosted-flakes)
+
+ * tags.el (find-tag): Better error message when no tag found
+ for substring.
+
+ * lisp-mode.el (emacs-lisp-mode-syntax-table): New variable.
+ Initialize this instead of lisp-mode-syntax-table.
+ * lisp-mode.el (lisp-mode-variables): New arg; if non-nil,
+ initialize lisp-mode-syntax-table unless already done,
+ and install it.
+ * lisp-mode.el (*-mode): Pass an arg to lisp-mode-variables.
+
+ * lisp-mode.el (eval-last-sexp): Use emacs-lisp-mode-syntax-table.
+ * lisp-mode.el (eval-print-last-sexp):
+ * debug.el (debugger-mode):
+ * chistory.el (Command-history-setup):
+ * options.el (Edit-options-mode):
+
+Tue Dec 1 00:48:06 1987 Richard Stallman (rms at frosted-flakes)
+
+ * lisp-mode.el (calculate-lisp-indent): Typo for case within a string.
+ Indent first arg of ordinary function directly under the function
+ name. Remove a call to parse-partial-sexp that always did
+ nothing.
+
+Wed Nov 25 19:14:29 1987 Richard Stallman (rms at frosted-flakes)
+
+ * rmail.el (rmail): Widen and goto beginning before checking format.
+
+Sun Nov 22 00:59:46 1987 Richard Stallman (rms at frosted-flakes)
+
+ * page.el (mark-page): Be more careful about where exactly
+ to put the buffer boundaries. Widen before searching for a page.
+
+Thu Nov 19 18:31:11 1987 Richard Stallman (rms at frosted-flakes)
+
+ * startup.el (command-line-1): Don't (goto-line 0).
+
+ * replace.el (occur-mode): Doc fix.
+
+Wed Nov 11 11:22:13 1987 Richard Stallman (rms at frosted-flakes)
+
+ * dired.el (dired-find-file{,-other-window}): No need to
+ check for a line saying it is a directory, because find-file
+ does that in a better way.
+ * dired.el (dired-view-file): Use file-directory-p to
+ decide whether to call dired.
+
+ * rmail.el (rmail): If buffer already existed and find-file
+ reverts it, recompute the message tables.
+
+Tue Nov 3 07:22:29 1987 Richard Stallman (rms at frosted-flakes)
+
+ * files.el (hack-local-variables): If selective-display
+ is set, next local-variables line starts with either \n or ^M.
+
+Sat Oct 31 22:09:52 1987 Richard Stallman (rms at sugar-smacks)
+
+ * mh-e.el (push): Renamed to mh-push.
+
+ * mailalias.el (define-mail-alias): Fix bug when there was
+ multiple whitespace.
+
+Thu Oct 29 20:39:55 1987 Richard Stallman (rms at frosted-flakes)
+
+ * simple.el (repeat-complex-command, next-complex-command):
+ Rename `arg' to `repeat-complex-command-arg'.
+
+Thu Oct 15 12:46:36 1987 Leonard H. Tower Jr. (tower at frosted-flakes)
+
+ * rnewspost.el (news-inews):
+ commented out -n and -t args in news-inews.
+
+Wed Oct 7 10:54:14 1987 Richard Stallman (rms at frosted-flakes)
+
+ * tex-mode.el (TeX-start-shell): Copy the local map
+ before changing it: don't clobber shell-mode's map.
+
+ * rmail.el (rmail-insert-inbox-text): Print the "getting..."
+ message for all files.
+
+Fri Oct 2 00:30:30 1987 Richard Stallman (rms at frosted-flakes)
+
+ * rnews.el: Rename // to news-/. Rename cadr, etc. to news-cadr, etc.
+ Rename push to news-push and supply a definition for it.
+
+Wed Sep 30 11:50:10 1987 Richard Stallman (rms at frosted-flakes)
+
+ * compile.el (compile1): Save the compilation process
+ across the sit-for.
+
+Wed Sep 16 17:19:40 1987 Richard M. Stallman (rms at prep)
+
+ * Version 18.49 released.
+
+ * debug.el (debugger-mode): mode-class special.
+
+ * buff-menu.el: Typo putting mode-class on `Buffer-menu-mode'.
+
+ * c-mode.el (electric-c-brace): set insertpos after
+ calling newline, since newline might do an auto-fill.
+
+Sat Sep 12 22:47:11 1987 Richard Mlynarik (mly at prep)
+
+ * loaddefs.el, mail-utils.el (rmail-dont-reply-to):
+ Add new variable `rmail-default-dont-reply-to-names' which is used
+ (together with the user's name) as the default value of
+ rmail-dont-reply-to-names. This variable replaces the wired-in
+ constant "info-" in `rmail-dont-reply-to' and is intended to be
+ used in the site-init.el file -- eg "all-ai\\>\\|[0-9]ai\\>\\|info-"
+
+Thu Sep 10 18:46:16 1987 Richard M. Stallman (rms at prep)
+
+ * debug.el (debug): bind default-major-mode normally when
+ creating the backtrace buffer.
+
+ * rmailsum.el (rmail-summary-goto-msg): Avoid error on empty buf.
+
+Mon Sep 7 19:49:56 1987 Richard Mlynarik (mly at prep)
+
+ * rmailsum (rmail-new-summary): Fix scope of `new-summary-line-count'
+
+ * lisp-mode.el (calculate-lisp-indent):
+ Don't fail on first line of defun.
+
+Sun Aug 30 02:20:48 1987 Richard M. Stallman (rms at prep)
+
+ * Version 18.48 released.
+
+ * backquote.el: Rename push to bq-push, and likewise for
+ caar, cadr and cdar. Delete cddr.
+ Definitions for the common-lisp functions
+ were different from those in cl.el and could interfere.
+
+Wed Aug 19 18:07:39 1987 Richard Mlynarik (mly at prep)
+
+ * lisp-mode.el (lisp-indent-hook): Fix braino.
+
+Fri Aug 14 17:55:42 1987 Richard M. Stallman (rms at prep)
+
+ * loaddefs.el (auto-mode-alist): Recognize .emacs file
+ with either Unix or VMS syntax.
+
+ * sun-mouse-fns.el: Renamed to sun-fns.el.
+ * sun-mouse.el, term/sun.el: Rename references too.
+
+ * shell.el (lisp-send-defun-and-go):
+ Call to lisp-send-defun requires an arg.
+
+Fri Jul 31 11:15:46 1987 Leonard H. Tower Jr. (tower at prep)
+
+ * rnewspost.el (news-setup) commented out Posting-Front-End to
+ save USENET bytes
+
+Wed Jul 29 22:12:12 1987 Richard Mlynarik (mly at prep)
+
+ * simple.el (negative-argument):
+ Pass explicit ?- to prefix-arg-internal rather than relying on
+ value of last-command-char (broke when this command wasn't
+ assigned to the "-" key)
+
+ * loaddefs.el: Autoload common-lisp-indent-hook.
+
+ * cl-indent.el:
+ New file which understands common lisp special forms and
+ has hairy indentation-specification templates.
+ (setq lisp-indent-hook 'common-lisp-indent-hook)
+ to enable it.
+
+ * lisp-mode.el (lisp-indent-hook):
+ No need to do save-excursion.
+ Deal with case of car of form being a list (which used to be
+ handled by calculate-lisp-indent)
+
+ * lisp-mode.el (calculate-lisp-indent):
+ Call indent-hook even if looking-at a list.
+ Needed for correct indentation of pleblisp FLET, etc.
+
+Sun Jul 26 20:07:49 1987 Richard M. Stallman (rms at prep)
+
+ * rmailsum.el (rmail-new-summary): Avoid error on empty summary.
+
+ * sendmail.el (mail): Doc fix.
+
+ * c-mode.el (c-backward-to-noncomment): Last change broke it totally.
+
+Sat Jul 25 15:33:26 1987 Richard M. Stallman (rms at prep)
+
+ * paths.el (term-file-prefix): Make it "[.term]" on VMS
+
+ * mlconvert.el: Add a few simple translations.
+
+ * tags.el (visit-tags-table): Reset tag-table-files.
+
+Sat Jul 18 19:37:10 1987 Richard M. Stallman (rms at prep)
+
+ * lpr.el (print-region-1): Make program name conditional on
+ system-type; use "lp" on sysV.
+
+ * keypad.el: Use help-for-help on the `?' key.
+ Provide a default for the `D' key. Change syntax for the
+ control-letters from ^ to `C-'.
+
+ * simple.el (delete-indentation): Do nothing if have arg
+ and on last line of buffer.
+
+ * mailalias.el (define-mail-alias): Call build-mail-aliases
+ if that has not yet been done.
+
+ * mailalias.el (build-mail-aliases): If no newline at eof, invent one.
+
+ * helper.el (Helper-help): Downcase the char before looking in map.
+
+ * informat.el (Info-tagify): The check for a split file
+ searched for the wrong string.
+
+Tue Jun 30 12:37:39 1987 Richard Mlynarik (mly at prep)
+
+ * info.el (Info-menu):
+ If interactive and point is within a menu item,
+ make that item the default for completing-read.
+
+ * man.el (nuke-nroff-bs):
+ Split this function out from manual-entry for users who need to
+ remove stupid control-h characters from text.
+
+ * mh-e.el: Version 3.4m from Larus.
+ Bug fixes plus draft folders.
+
+Mon Jun 29 01:04:03 1987 Richard M. Stallman (rms at prep)
+
+ * vms-patch.el (make-legal-file-name): New function converts any
+ string to a similar string that's a legal VMS filename.
+
+ * picture.el: provide 'picture.
+
+ * blackbox.el (bb-init-board):
+ Use (logand (random) 7) instead of remainder by 8.
+
+Thu Jun 25 21:38:21 1987 Richard M. Stallman (rms at prep)
+
+ * replace.el (perform-replace): Don't exit on no-op comma.
+
+Tue Jun 23 02:09:31 1987 Richard M. Stallman (rms at prep)
+
+ * c-mode.el (electric-c-terminator): Bug if auto-fill
+ while doing an auto-newline. (insertpos off by 1).
+
+ * files.el (set-visited-file-name):
+ Downcase buffer name uniformly on VMS.
+
+Mon Jun 22 22:24:12 1987 Richard M. Stallman (rms at prep)
+
+ * c-mode.el (c-backward-to-noncomment):
+ Don't loop on lines starting in ` #'.
+
+Thu Jun 18 00:38:46 1987 Richard M. Stallman (rms at prep)
+
+ * files.el (set-visited-file-name):
+ Downcase the new buffer name on VMS.
+
+Wed Jun 17 00:39:56 1987 Richard M. Stallman (rms at prep)
+
+ * view.el (View-scroll-lines-forward):
+ If end of buffer is visible, exit view mode.
+
+Mon Jun 15 20:25:55 1987 Richard M. Stallman (rms at prep)
+
+ * rmail.el (rmail-get-new-mail):
+ If file has changed on disk and is read in again,
+ count its messages again.
+
+Wed Jun 10 21:10:01 1987 Richard M. Stallman (rms at prep)
+
+ * Version 18.47 released.
+
+ * startup.el (command-line): Old test for su failed.
+ Now assume su if (user-login-name) != (getenv "USER").
+
+Mon Jun 8 19:31:03 1987 Richard M. Stallman (rms at prep)
+
+ * version 18.46 released.
+
+ * isearch.el (isearch): Typo (3 should be 2) in getting old
+ start-point in reverse regexp search made more liberal.
+
+Mon Jun 8 18:41:28 1987 Chris Hanson (cph at prep)
+
+ * scheme.el (scheme-mode-syntax-table): Typo.
+
+Thu Jun 4 17:14:54 1987 Richard M. Stallman (rms at prep)
+
+ * telnet.el: Doc fix.
+
+Sun May 31 01:20:32 1987 Richard M. Stallman (rms at prep)
+
+ * version 18.45.
+
+ * informat.el (Info-split): Bind case-fold-search to t.
+
+Fri May 29 00:41:16 1987 Richard M. Stallman (rms at prep)
+
+ * lisp-mode.el: Add some comments.
+
+ * replace.el (list-matching-lines): If run on *Occur* buffer,
+ find nothing, rather than getting infinite loop.
+
+Thu May 28 16:41:41 1987 Richard M. Stallman (rms at prep)
+
+ * simple.el (backward-delete-char-untabify):
+ Use insert-char to insert the spaces. Wins for large tab-width.
+
+Thu May 28 15:40:36 1987 Chris Hanson (cph at prep)
+
+ * xscheme.el (xscheme-send-current-line): Send the line to Scheme
+ AFTER writing the newline which acknowledges the command.
+ Otherwise the process-mark can end up in the wrong place.
+
+Thu May 28 12:24:54 1987 Richard M. Stallman (rms at prep)
+
+ * texinfmt.el (texinfo-format-printindex): Pass -d to `sort'.
+ This makes entry `Foo' precede `Foo Bar'.
+
+ * vms-patch.el (create-file-buffer): New VMS-override definition
+ downcases the file name.
+
+Wed May 27 12:44:22 1987 Richard M. Stallman (rms at prep)
+
+ * informat.el (Info-split): Put newlines at end of split files.
+
+ * dabbrev.el (dabbrev-expand): Preserve case in the replacement
+ if that's enabled and the replacement is either all lower case
+ or capitalized.
+ (dabbrevs-search): Don't distinguish possible replacements
+ that match except for case, if new 3rd arg NOCASE is set.
+
+ * ftp.el (various): Ignore errors in accept-process-output.
+
+Mon May 25 23:01:09 1987 Richard M. Stallman (rms at prep)
+
+ * sun-mouse-fns.el (mouse-scroll-proportional):
+ Scroll proportional to current restrictions.
+ * sun-mouse-fns.el (enable-mouse-in-buffer-list):
+ Make mouse do something on *Buffer List*.
+
+Sat May 23 18:30:02 1987 Richard M. Stallman (rms at prep)
+
+ * shell.el (kill-output-from-shell): Save final unfinished line.
+
+Thu May 21 17:37:45 1987 Richard M. Stallman (rms at prep)
+
+ * c-mode.el (calculate-c-indent, indent-c-exp):
+ When using c-continued-statement-offset, if line starts
+ with an open-brace, add c-continued-brace-offset.
+
+Wed May 20 11:38:25 1987 Richard M. Stallman (rms at prep)
+
+ * isearch.el (isearch): When splitting window, any hscroll
+ stays with the text it applied to.
+
+Tue May 19 10:38:25 1987 Chris Hanson (cph at prep)
+
+ * scheme.el (scheme-indent-specform):
+ Do not handle first two distinguished forms specially. All
+ distinguished forms are indented at double scheme-body-indent.
+
+ * scheme.el:
+ Conditionalize MIT-Scheme specific indentation with a flag
+ `scheme-mit-dialect'. Users of other dialects can set this to
+ false to disable that indentation.
+
+Sat May 16 02:16:31 1987 Richard M. Stallman (rms at prep)
+
+ * rmailsum.el (rmail-summary-scroll-msg-{up,down}):
+ Simplify, and make ...-down use scroll-other-window
+ so it avoids changing the selected window.
+
+ * tex-mode.el (TeX-common-initialization): Don't give \
+ any special syntax.
+
+ * dired.el (dired-compress): Fix typo in call to `message'.
+
+ * rmailsum.el (rmail-make-basic-summary-line):
+ When searching for header field names, insist they appear
+ at beginning of line.
+
+ * subr.el (one-window-p): If ARG was nil it was
+ really less-than-three-windows-p.
+ * sendmail.el, electric.el, ehelp.el, rmail.el:
+ Delete temporary duplicate definitions of one-window-p.
+
+Wed May 13 10:28:39 1987 Richard M. Stallman (rms at prep)
+
+ * sendmail.el (mail-setup): New parameter mail-default-reply-to:
+ if non-nil, insert it as a Reply-to field.
+
+ * dired.el (dired-unflag): Doc fix.
+
+ * simple.el (blink-matching-open):
+ Don't use last-input-char; look in the buffer to determine
+ which closeparen is present.
+
+Tue May 12 11:50:22 1987 Richard M. Stallman (rms at prep)
+
+ * loadefs.el (sentence-end): Treat `}' like `)'.
+
+ * buff-menu.el (buffer-menu-mode):
+ Run buffer-menu-mode-hook.
+
+ * modula2.el (m2-newline): Define this missing function.
+
+ * server.el (server-done): Write MH backup with write-region.
+ loaddefs.el: Autoload server-start, not server-edit.
+ (server-start): Change documentation: this is the main entry.
+
+ * startup.el (command-line): If running under `su',
+ use user's original login name to get init file.
+ Otherwise use $HOME.
+
+Mon May 11 17:25:04 1987 Richard M. Stallman (rms at prep)
+
+ * isearch.el (isearch): When splitting window for slow search
+ with temp window at the top, prevent scrolling in main window.
+
+ * term/vt200.el: Correct mapping of Insert key.
+
+ * loaddefs.el (run-scheme): Add an autoload.
+
+Wed Apr 29 14:46:12 1987 Richard Mlynarik (mly at prep)
+
+ * abbrevlist.el (list-one-abbrev-list): Use value returned by sort.
+ (Michael Prange <8704291816.AA13767@prep.ai.mit.edu>)
+
+Wed Apr 29 10:02:00 1987 Leonard H. Tower Jr. (tower at prep)
+
+ * loaddefs.el
+ Updated rnews documentation and added autoload of news-post-news.
+
+Tue Apr 28 15:24:49 1987 Leonard H. Tower Jr. (tower at prep)
+
+ * rnewspost.el (news-post-news, news-reply)
+ Fixed news-show-all-headers bug when *news* buffer was on an
+ article that no longer has a file in the news spool directory
+ tree. Also made both work from almost any buffer in any mode.
+ (Dave Steiner <8704230309.AA03452@topaz.rutgers.edu>)
+
+Tue Apr 28 10:51:16 1987 Richard Mlynarik (mly at prep)
+
+ * files.el (save-buffer):
+ When saving a large file, print a message.
+
+ * terminal.el (te-newline, te-set-window-start):
+ Don't set-window-start unless
+ (eq (selected-window) (get-buffer-window (current-buffer)))
+
+ * startup.el (command-line): -batch => -no-init-file
+
+Thu Apr 23 17:10:41 1987 Leonard H. Tower Jr. (tower at prep)
+
+ * rnewspost.el; rnews.el:
+ added (require 'rnews) and (provide 'rnews), respectively.
+
+Thu Apr 23 12:38:37 1987 Chris Hanson (cph at prep)
+
+ * scheme.el:
+ * xscheme.el:
+ Install new versions of these files to correspond to CScheme
+ release 5. The old `xscheme.el' will not work correctly with the
+ new CScheme release. The new `scheme.el' implements the Scheme
+ standard syntax more correctly.
+
+Thu Apr 23 10:42:53 1987 Richard Mlynarik (mly at prep)
+
+ * loaddefs.el:
+ Autoload `run-prolog'. ".pl" files are in prolog-mode.
+
+ * prolog.el: Fix to prolog-indent-level.
+ (Masanobu UMEDA <8704201111.AA10940@flab.flab.fujitsu.junet>)
+
+ * vip.el: Fixes from Masahiko Sato; Version 2.8
+ (ms@sail.stanford.edu <8704231017.AA11075@nttlab.ntt.junet>)
+
+Wed Apr 15 01:29:41 1987 Paul Rubin (phr at prep)
+
+ * version 18.44 released.
+
+Tue Apr 14 09:55:34 1987 Richard Mlynarik (mly at prep)
+
+ * mailalias.el (build-mail-aliases):
+ Don't treat "alt" as "alias" (delimit "[ \t]+" not "[ \t]*")
+ (sjk <8704140433.AA00840@cancun.ads.arpa>)
+
+Mon Apr 13 08:53:18 1987 Richard Mlynarik (mly at prep)
+
+ * loaddefs.el ((query-)replace-regexp documentation):
+ Use \=\<n> in doc strings now that \< is special in
+ substitute-command-keys.
+
+Sat Apr 11 15:30:17 1987 Richard Mlynarik (mly at prep)
+
+ * server.el: (various):
+ Changes suggested by rlk@athena.mit.edu
+ (<8704032045.AA00797@CHOWPEENTULK.MIT.EDU>)
+
+ * loaddefs.el:
+ Autoload server-edit rather than server-start.
+ [This was later taken out.]
+
+ * dired.el (dired-compress, dired-uncompress):
+ Add "(Un)compressing <file>... done" messages.
+
+ * view.el (view-mode-command-loop):
+ Restore local map of correct buffer, even if user has switched
+ buffers.
+ (jason <19933.545094826@violet.berkeley.edu>)
+
+ * lisp.el (lisp-complete-symbol):
+ Skip over `quote' syntax chars to find real start of symbol.
+ (douglis <8704102143.AA16318@sloth.Berkeley.EDU>)
+
+Fri Apr 10 10:16:51 1987 Richard Mlynarik (mly at prep)
+
+ * mailalias.el:
+ build-mail-aliases: Hack "\\\n" continuation lines.
+ define-mail-alias: Addresses sent to the mailer should be
+ separated by ", ", not " "!!
+
+Wed Apr 8 13:05:41 1987 Richard Mlynarik (mly at prep)
+
+ * rfc822.el (rfc822-addresses):
+ Don't loop trying to report that ";" is an invalid address.
+
+Mon Apr 6 09:21:18 1987 Richard Mlynarik (mly at prep)
+
+ * sun-mouse.el: (sm::window-xy):
+ Agree with `new' args to next-window.
+ (peck@sun.com <8704032106.AA12845@denali.sun.com>)
+
+Fri Apr 3 08:49:27 1987 Richard Mlynarik (mly at prep)
+
+ * term/vt200.el: Fix typo.
+
+Thu Apr 2 12:42:08 1987 Richard Mlynarik (mly at prep)
+
+ * startup.el (command-line):
+ Default init file is "$HOME/.emacs", not "~$USER/.emacs"
+
+Tue Mar 31 10:03:06 1987 Richard Mlynarik (mly at prep)
+
+ * edt.el: Fix typo.
+
+ * mh-e.el (mh-send-letter):
+ "-unique" => "-nopush.
+ (larus <8703311804.AA05788@paris.Berkeley.EDU>)
+
+ * shell.el: Minor doc fixes.
+
+ * rmail.el (rmail-get-new-mail):
+ Handle errors competently. (Don't attempt to
+ handle them, rather than botching the job)
+
+ * rmail.el (rmail-insert-inbox-text):
+ Put ".newmail" file in same directory as rmail-file-name
+ rather than in $HOME. This allows one to read things in
+ even when out of space on one filesystem.
+ Use expand-file-name rather than (concat file "/...")
+ for system-independence.
+ Collect and report errors from `movemail' (rather than
+ saying "(There is no new mail)"!)
+
+ * rmail.el:
+ rms' changes of the 5th of March never made it in.
+ rmail-undelete-previous-message, rmail-next-undeleted-message:
+ Don't call rmail-show-msg if message is already current.
+ Avoids scrolling.
+
+Sun Mar 22 09:26:51 1987 Richard M. Stallman (rms at prep)
+
+ * Version 18.41 released.
+
+ * vip.el (vip-mode): Add this function, which loaddefs.el expected.
+ * vip.el (change-mode): Eliminate emacs-mode-line-format;
+ use change-mode-line when reentering emacs-mode.
+
+ * prolog.el (prolog-mode-variables): comment-column=48.
+ * prolog.el (prolog-consult-region): New arg COMPILE (prefix).
+ Before the region, send one of prolog-{consult,compile}-string.
+ After, send prolog-eof-string or else real eof.
+ Get region bounds using interactive r.
+ * prolog.el (prolog-consult-region-and-go): Similar.
+
+ * info.el (Info-find-node): Don't call Info-mode
+ if already in that mode. Avoids wiping out local variables
+ such as Info-current-file.
+
+Sat Mar 21 13:36:04 1987 Richard M. Stallman (rms at prep)
+
+ * term/sun.el: Define sun-esc-bracket as nil:
+ don't redefine M-[ by default.
+
+ * informat.el (Info-validate): Don't get error while
+ checking for an indirect info file.
+
+Fri Mar 20 10:20:16 1987 Richard M. Stallman (rms at prep)
+
+ * dired.el (dired-{un,}compress): Don't specify path
+ for programs compress and uncompress.
+
+Thu Mar 19 14:56:55 1987 Richard Mlynarik (mly at prep)
+
+ * disassemble.el (disassemble-1):
+ Let print-escape-newlines t around constant printing.
+
+ * terminal.el (terminal-emulator):
+ Quote shell arg as "TERMCAP=foo" not TERMCAP="foo"
+
+Thu Mar 19 14:21:09 1987 Richard M. Stallman (rms at prep)
+
+ * vip.el (string-tail, change-mode-line):
+ Use string manipulation; flush the temp buffer " *working-space*".
+
+Wed Mar 18 11:36:49 1987 Richard M. Stallman (rms at prep)
+
+ * Version 18.40 released.
+
+ * files.el (after-find-file): Use directory-file-name where needed.
+
+Wed Mar 18 10:11:51 1987 Richard Mlynarik (mly at prep)
+
+ * ftp.el (ftp-find-file-or-directory): Paren error.
+
+Tue Mar 17 09:46:29 1987 Richard M. Stallman (rms at prep)
+
+ * server.el (server-visit-buffers): Don't revert a buffer
+ automatically if the file does not currently exist.
+
+ * mh-e.el (mh-list-to-string, mh-page-digest{,-backwards}):
+ Fixes from Larus.
+
+ * server.el (server-start): Kill old server before
+ clearing out its records. Delete any old server socket
+ unconditionally. Mark server process as kill-without-query.
+
+ * files.el (recover-file): Don't try to list directory on vms.
+
+Sat Mar 14 09:39:24 1987 Richard M. Stallman (rms at prep)
+
+ * Version 18.39 released.
+
+Fri Mar 13 19:34:24 1987 Richard M. Stallman (rms at prep)
+
+ * dired.el: New commands dired-{un,}compress,
+ dired-byte-compile, dired-ch{mod,own,grp} and subroutine
+ dired-redisplay. From Jim Cottrell, rbj@icst-cmr.arpa.
+ They are all put on keys.
+
+ * sun-{mouse,mouse-fns,cursors}.el, term/sun.el:
+ New and replacement files from peck@sun.com.
+
+Thu Mar 12 16:17:22 1987 Richard M. Stallman (rms at prep)
+
+ * server.el (server-visit-files): Before trying
+ find-file-noselect, check for existing buffer, and if it
+ isn't modified, revert it unconditionally.
+
+ * mh-e.el (mh-send-letter): Considerable rewrite by Larus;
+ don't know why.
+
+Wed Mar 11 18:11:12 1987 Chris Hanson (cph at prep)
+
+ * sort.el (sort-subr): fix typo in sorting of lists: in case where
+ `sortcar' is not available, and arguments are numbers, was using
+ `cdr' to extract second argument to `sort' (rather than `car').
+
+Wed Mar 11 10:05:35 1987 Richard M. Stallman (rms at prep)
+
+ * tex-mode.el (TeX-comment-indent): In column 0,
+ don't require indenting at least to column 1.
+
+ * vip.el: New version from Sato; handles the EX commands.
+
+ * server.el: New version frm peck@sun, supporting
+ multiple clients.
+
+Tue Mar 10 16:20:48 1987 Richard M. Stallman (rms at prep)
+
+ * outline.el (hide-region-body): Exit loop cleanly
+ no matter which stage reaches eob.
+
+Mon Mar 9 10:21:40 1987 Richard M. Stallman (rms at prep)
+
+ * files.el (hack-local-variables): New optional arg FORCE.
+ If it's nil, and `inhibit-local-variables' is non-nil,
+ then query before installing the file's local variables.
+ * files.el (normal-mode): Pass non-nil FORCE to
+ hack-local-variables if we were called from find-file.
+
+ * shell.el (shell-send-input): Fix typo in condition-case syntax.
+
+ * shell.el (make-shell): Make a TERMCAP env var
+ for term type "emacs" to give the screen width.
+
+Sun Mar 8 08:30:26 1987 Richard M. Stallman (rms at prep)
+
+ * info.el (Info-mode): Make variables Info-current-*,
+ Info-tag-table-marker and Info-history local in Info-mode.
+
+Fri Mar 6 14:55:31 1987 Richard Mlynarik (mly at prep)
+
+ * ftp.el: Paren error.
+
+Thu Mar 5 16:27:47 1987 Richard M. Stallman (rms at prep)
+
+ * sort.el (sort-reorder-buffer): Fix typo `end'->`last'
+ in insertion of the spacing after the last sort record.
+
+ * rmail.el (rmail-undelete-previous-message):
+ Don't call rmail-show-msg if message is already current.
+ Avoids scrolling.
+
+ * rmail.el (rmail-next-undeleted-message): Likewise.
+
+Wed Mar 4 01:21:22 1987 Richard M. Stallman (rms at prep)
+
+ * loaddefs.el (auto-mode-alist): Add .article and .letter
+ as text-mode, for rn.
+
+ * ftp.el (ftp-list-directory): New command.
+ * ftp.el (ftp-find-file-or-directory):
+ Guts of ftp-find-file are now here. 3rd arg is t for a file,
+ nil for listing a directory.
+
+ * mailalias.el (expand-mail-aliases): Correct handling of
+ aliases whose expansions use other aliases, and aliases
+ that are self-referent.
+
+ * c-mode.el (calculate-c-indent): Line at beg of buffer
+ needs no indentation.
+
+Tue Mar 3 21:43:01 1987 Richard M. Stallman (rms at prep)
+
+ * shell.el (shell): New series of variables `explicit-FOO-args'
+ specify args to use when running program FOO as a shell.
+ Supply system-dependent default for explicit-csh-args.
+
+ * mailalias.el (expand-mail-aliases):
+ Fix typo: use build-mail-aliases to gobble redefined mail aliases.
+
+ * loaddefs.el (dired-listing-switches): Doc fix.
+
+Mon Mar 2 15:54:47 1987 Richard Mlynarik (mly at prep)
+
+ * Version 18.38 released.
+
+ * shell.el (make-shell):
+ Use the "env" program.
+ This both simplifies and shortens the code, and makes it
+ environment-implementation-independent.
+
+Mon Mar 2 08:36:03 1987 Chris Hanson (cph at prep)
+
+ * page.el (what-page): Reported wrong page number if invoked
+ exactly to the right of a page-delimiter.
+
+Sat Feb 28 14:28:28 1987 Richard M. Stallman (rms at prep)
+
+ * loaddefs.el (mode-line-modified):
+ New variable for string that indicates modifiedness in mode line.
+
+ * rmail.el (rmail-mode-1): If mode-line-modified is bound,
+ change it rather than mode-line-format.
+ * rmailedit.el (rmail-edit-mode): same thing.
+
+Fri Feb 27 14:06:52 1987 Richard M. Stallman (rms at prep)
+
+ * info.el (Info-follow-reference): Combine multiple spaces
+ in node name before searching. Also helps with newline and
+ spaces.
+
+ * texinfmt.el (texinfo-format-buffer-1):
+ Discard everything after the @bye.
+
+Thu Feb 26 22:02:09 1987 Paul Rubin (phr at prep)
+
+ * texinfmt.el (texinfo-format-emph):
+ Function was accidentally misnamed `texinfo-format'.
+
+Thu Feb 26 02:10:58 1987 Richard M. Stallman (rms at prep)
+
+ * x-mouse.el (x-help, x-buffer-menu):
+ Install definitions of these commands, possible now that
+ xmenu.c is installed.
+
+Tue Feb 24 13:00:44 1987 Richard M. Stallman (rms at prep)
+
+ * edt.el (update-mode-line): New function forces mode line update.
+ * edt.el (backup-mode, advance-mode): Call update-mode-line.
+ Also include a space at front of the word that's displayed.
+ function-map => function-keymap.
+ * edt.el: fix calls to define-keypad-key.
+ * edt.el: fix typo `delete-previous-character'.
+
+Sun Feb 22 23:08:54 1987 Richard M. Stallman (rms at prep)
+
+ * texinfmt.el: Define @cite, @emph and @strong.
+
+Thu Feb 19 16:00:13 1987 Richard Mlynarik (mly at prep)
+
+ * subr.el:
+ (fset 'set-window-buffer 'show-buffer) =>
+ (fset 'show-buffer 'set-window-buffer)
+
+Thu Feb 19 14:25:04 1987 Richard M. Stallman (rms at prep)
+
+ * view.el (view-mode): No longer interactive.
+ Much easier than fixing the problems that happen if it is
+ used wrong.
+
+ * files.el (find-alternate-file): Don't offer save if read-only.
+
+Wed Feb 18 19:32:06 1987 Chris Hanson (cph at prep)
+
+ * simple.el (do-auto-fill): Do not `save-excursion' if
+ do-auto-fill should have exactly the same effect as doing
+ indent-new-comment-line. Otherwise if a fill-prefix or
+ comment-start is inserted, point will be left at the beginning
+ rather than the end of the inserted prefix.
+
+Wed Feb 18 10:20:23 1987 Richard M. Stallman (rms at prep)
+
+ * abbrev.el (abbrev-mode): Update the mode line.
+ * simple.el (overwrite-mode): Update the mode line.
+
+ * term/vt100.el: If there are already keymaps on \e[ amd \eO,
+ use them for the CSI-map and SS3-map.
+
+ * texinfmt.el (texinfo-format-center): @center was missing.
+
+ * isearch.el (isearch): If DEL is not special,
+ it terminates the search as a random control character.
+
+Mon Feb 16 14:56:18 1987 Richard M. Stallman (rms at prep)
+
+ * dabbrev.el: Missing quote in arg to make-variable-buffer-local.
+
+ * man.el (manual-entry):
+ Use insert-man-file instead of insert-file-contents.
+
+ * tex-mode.el (TeX-show-print-queue): Start tex shell
+ if not already done.
+
+ * tex-mode.el (TeX-mode): bound search for % at eol.
+
+Sun Feb 15 18:03:14 1987 Richard M. Stallman (rms at prep)
+
+ * loaddefs.el (completion-ignored-extensions): Add .bin again;
+ scheme is said to use it.
+
+Fri Feb 13 14:40:51 1987 Richard M. Stallman (rms at prep)
+
+ * rmail.el (rmail-insert-inbox-text): Do expand-file-name
+ on names of inbox files.
+
+ * loaddefs.el: Add autoload for server-start.
+
+Mon Feb 9 09:53:27 1987 Richard Mlynarik (mly at prep)
+
+ * Version 18.37 released.
+
+ * rmail.el (rmail-mode-1):
+ Don't rely on mode-line-format being consp.
+
+Sun Feb 8 08:53:07 1987 Richard M. Stallman (rms at prep)
+
+ * shell.el (inferior-lisp-program): New variable is used
+ as program name when starting inferior Lisp.
+
+ * shell.el (lisp-send-defun): Write the text to a temp file,
+ then send a string saying to load the file.
+ inferior-lisp-load-command controls generation of that string.
+ Prefix arg means bring *lisp* buffer onto the screen
+ and scroll it to the end.
+ inferior-lisp-prompt controls recognition of when prompt
+ arrives, indicating no more output coming so scrolling may be done.
+
+ * server.el (server-start): Make "Server" appear in mode line
+ while actual server operation is going on.
+ Do process-kill-without-query also.
+
+ * server.el (various): Call the buffer " *server*", not "*server*".
+
+ * server.el (server-sentinel): Considerable cleanup.
+ Don't ever switch-to-buffer on *server*. Do all parsing in it
+ and finding of files without changing displayed buffers;
+ only then display one buffer that merits it.
+ Eliminate variable old-server-edit-buffer.
+
+ * files.el (save-abbrevs): Default value is nil.
+ * abbrev.el (read-abbrev-file): Set save-abbrevs to t.
+
+ * shell.el (make-shell): Change process-environment
+ to specify EMACS=t, TERM=switch and no TERMCAP.
+
+ * debug.el (debug): Bind print-escape-newlines to t
+ while printing the backtrace.
+
+ * subr.el (run-hooks): Each hook value may be a list of functions
+ as well as a single function.
+
+ * files.el (after-find-file): Wait only after serious messages,
+ not "(New file)" or "File is read-only". And don't redisplay
+ when waiting.
+
+ * mlconvert.el (convert-mocklisp-buffer):
+ Generate mocklisp-style defuns, not Lisp-style,
+ for dummy function ml-foo. Indent the body.
+
+Sun Feb 8 08:42:44 1987 Daniel LaLiberte (liberte at b.cs.uiuc.edu)
+
+ * mlconvert.el (convert-mocklisp-buffer):
+ Insert the starting comment and the `require' after
+ encapsulating non-defuns into defuns.
+
+ * mlconvert.el (fix-mlisp-syntax): Detect and fix the
+ ^LETTER syntax.
+
+Sat Feb 7 22:27:16 1987 Richard M. Stallman (rms at prep)
+
+ * mlconvert.el (convert-mocklisp-buffer):
+ Treat | as alphabetic char. Convert syntax before
+ converting non-defuns to defuns.
+
+Thu Feb 5 07:10:39 1987 Richard Mlynarik (mly at prep)
+
+ * ftp.el (ftp-find-file):
+ Ignore `125's from server.
+
+Tue Feb 3 05:21:10 1987 Richard Mlynarik (mly at prep)
+
+ * simple.el (auto-fill-mode):
+ Update mode-line after changing minor mode.
+
+Tue Feb 3 00:10:47 1987 Richard M. Stallman (rms at prep)
+
+ * mh-e.el (mh-insert-prefix-string):
+ Use explicit loop by lines.
+
+Sun Feb 1 04:39:34 1987 Richard M. Stallman (rms at prep)
+
+ * loaddefs.el: purecopy many strings found in initial var values.
+ Garbage collect in middle of file to reduce storage required
+ for loading. Remove ".bin" from completion-ignored-extensions
+ on Unix since only Symbolics customers would benefit from its presence.
+ Symbolics killed the MIT AI lab; don't do business with them.
+
+ * view.el (view-file): Kill the buffer at the end if it was
+ created just for this and was not modified.
+
+ * userlock.el (ask-user-about-supercession-help):
+ Suggest use of revert-buffer.
+
+ * help.el (print-help-return-message): Don't count minibuffer window
+ when deciding whether there is only one window. Calls one-window-p.
+ * subr.el (one-window-p): New function.
+ * subr.el: Rename some args to reduce number of symbols.
+
+ * electric.el (Electric-pop-up-window):
+ * ehelp.el (with-electric-help):
+ * rmail.el (rmail-forward):
+ * sendmail.el (mail-send-and-exit): Don't count minibuffer window
+ when deciding whether there is only one window.
+ These are done by definining subroutine one-window-p in a way that
+ works in old versions of Emacs.
+
+Fri Jan 30 16:35:48 1987 Richard Mlynarik (mly at prep)
+
+ * loaddefs.el (completion-ignored-extensions):
+ Add ".lbin"
+
+ * mail-utils.el, loaddefs.el (mail-use-rfc822): Doc typo.
+
+Thu Jan 29 03:44:29 1987 Richard M. Stallman (rms at prep)
+
+ * rmail.el (rmail-set-message-counters):
+ * rmail.el (rmail-count-new-messages):
+ Don't bind cursor-in-echo-area.
+
+ * debug.el (debug-on-entry): Doc fix.
+
+ * files.el (rename-auto-save-file): Don't rename if new and old
+ names are the same.
+
+Wed Jan 28 17:55:02 1987 Richard M. Stallman (rms at prep)
+
+ * rmail.el (rmail-mode-1): Don't set mode-line-buffer-identification.
+
+Mon Jan 26 17:15:27 1987 Richard M. Stallman (rms at prep)
+
+ * simple.el (set-variable): Use documentation-property
+ instead of get, for getting variable documentation.
+
+Sun Jan 25 15:46:01 1987 Richard Mlynarik (mly at prep)
+
+ * debug.el (debug):
+ Bind cursor-in-echo-area.
+
+Fri Jan 23 13:19:28 1987 Richard M. Stallman (rms at prep)
+
+ * isearch.el (isearch): In reverse search, wrapping is to end
+ of buffer, not beginning.
+
+ * man.el (manual-entry): Take 1st char of `section' as a
+ substring, not as a char, to pass to `concat'.
+
+ * loaddefs.el (completion-ignored-extensions):
+ Add ".glo", ".idx" and ".lot".
+
+Thu Jan 22 16:09:51 1987 Chris Hanson (cph at prep)
+
+ * shell.el (shell): Do not pass -T flag to `/bin/sh', only to
+ `/bin/csh'.
+
+Thu Jan 22 15:08:24 1987 Richard M. Stallman (rms at prep)
+
+ * scribe.el (scribe-mode): Doc fix.
+ * loaddefs.el (scribe-mode): Doc fix.
+
+ * tex-mode.el (tex-mode): Change tex vs latex discrimination
+ to avoid a slow regexp.
+
+Thu Jan 22 13:06:33 1987 Richard Mlynarik (mly at prep)
+
+ * files.el (find-file-noselect):
+ Call expand-file-name earlier so it is correct in case of errors,
+ file-not-found, etc.
+
+Wed Jan 21 17:00:19 1987 Richard Mlynarik (mly at prep)
+
+ * yow.el, flame.el, doctor.el:
+ Change calls to (random) (lisp reader doesn't read octal "07777")
+
+Wed Jan 21 02:13:17 1987 Richard M. Stallman (rms at prep)
+
+ * Version 18.36 released.
+
+Wed Jan 21 02:13:17 1987 Richard M. Stallman (rms at prep)
+
+ * bytecomp.el (byte-compile-setq-default): New function for
+ special handling needed because setq-default has an unevalled arg.
+
+ * c-mode.el (calculate-c-indent): When finding first statement
+ inside brace-group, `case' is not special unless a colon appears.
+
+ * macros.el (kbd-macro-query): Make C-l call `recenter'.
+
+ * bytecomp.el (byte-compile-setq): Make setq with no args
+ generate a value.
+
+ * bytecomp.el (byte-compile-cond): Notice unconditional clauses
+ and optimize the code generated.
+
+Tue Jan 20 11:48:17 1987 Richard M. Stallman (rms at prep)
+
+ * bytecomp.el (byte-compile-if): Correct test for else-less if's.
+
+ * sun-mouse.el: Delete code to handle resize-blips
+ since they are unnecessary and no longer generated.
+
+ * sort.el (sort-columns): Pass -t\n instead of -b to `sort'.
+
+Mon Jan 19 12:44:42 1987 Richard M. Stallman (rms at prep)
+
+ * loaddefs.el (auto-mode-alist): Recognize .lsp as Lisp mode.
+
+Fri Jan 16 18:09:59 1987 Richard Mlynarik (mly at prep)
+
+ * rmail.el (rmail-count-new-messages),
+ rmailout.el (rmail-output-to-rmail-file):
+ Add optional arg `nomsg' to former, which latter supplies,
+ so that rmail doesn't report counting one appended message.
+
+Thu Jan 15 22:19:17 1987 Richard M. Stallman (rms at prep)
+
+ * shell.el (shell): Flush hpux kludge to use "sh" instead of
+ SHELL, and install another kludge to pass -T if on hpux.
+
+Thu Jan 15 17:08:01 1987 Richard Mlynarik (mly at prep)
+
+ * time.el (display-time-filter):
+ Never eat anything larger than your own head.
+
+Thu Jan 15 16:10:33 1987 Richard M. Stallman (rms at prep)
+
+ * files.el (after-find-file): Sit for 2 sec after warning msg.
+
+Thu Jan 15 09:07:04 1987 Richard Mlynarik (mly at prep)
+
+ * rmail.el (rmail-get-new-mail):
+ (or (verify-visited-file-modtime (current-buffer))
+ (find-file (buffer-file-name)))
+
+ * simple.el (append-next-kill):
+ Make this work when not (interactive-p)
+
+Wed Jan 14 16:40:38 1987 Richard Mlynarik (mly at prep)
+
+ * terminal.el:
+ Can't send ^d chars (004) through the cretinous so-called ptys
+ written by the mindless so-called hackers responsible for un*x
+ (the Operating System of the Future.)
+
+Mon Jan 12 01:08:19 1987 Richard Mlynarik (mly at prep)
+
+ * files.el (basic-save-buffer):
+ Typo.
+
+Sun Jan 11 16:16:15 1987 Richard Mlynarik (mly at prep)
+
+ * ebuff-menu (electric-buffer-list):
+ Typo.
+
+ * buff-menu.el (Buffer-menu-select):
+ If the buffer to select is also marked with ">" only make one
+ window for it.
+
+ * terminal.el (te-filter):
+ Save/restore point from te-saved-point to minimise the lossage
+ vandals can inflict.
+
+Fri Jan 9 15:54:00 1987 Richard M. Stallman (rms at prep)
+
+ * tex-mode.el: New version from Gildea.
+ Many changes.
+
+Fri Jan 9 15:04:45 1987 Richard Mlynarik (mly at prep)
+
+ * novice.el (disabled-command-hook):
+ cursor-in-echo-area.
+
+Fri Jan 9 10:23:13 1987 Richard M. Stallman (rms at prep)
+
+ * mh-e.el (mh-send-letter, mh-fully-kill-draft):
+ Two minor fixes from Larus.
+
+ * files.el (basic-save-buffer): After prompting for
+ filename for non-file buffer, turn on auto-save.
+
+Thu Jan 8 12:05:49 1987 Richard Mlynarik (mly at prep)
+
+ * files.el (set-visited-filename):
+ (kill-local-variable 'revert-buffer-function)
+
+ * hanoi.el (hanoi0), yow.el, flame.el (psychoanalyze-{pinhead,flamer}):
+ Quit if luser types a char rather than inhibiting redisplay for 20
+ minutes!
+
+Thu Jan 8 00:59:16 1987 Richard M. Stallman (rms at prep)
+
+ * sort.el (sort-columns): Fix typo in variable name.
+ Also check for presence of tabs and get error.
+
+Wed Jan 7 13:25:01 1987 Richard M. Stallman (rms at prep)
+
+ * vi.el: New version from wu@crys.wisc.edu.
+ All function and variable names start with `vi'.
+ Some missing vi capabilities now emulated.
+
+ * sun-mouse.el (set-screen-size-and-rdis):
+ was using x as screen height and y as width; exchange.
+
+Tue Jan 6 23:52:52 1987 Richard Mlynarik (mly at prep)
+
+ * term/x-win.el:
+ Set suspend-hook to get an error.
+
+Tue Jan 6 17:35:37 1987 Richard M. Stallman (rms at prep)
+
+ * mh-e.el (mh-write-msg-to-file): Generate buffer " *mh-temp*"
+ if it is missing.
+
+Tue Jan 6 11:53:42 1987 Richard Mlynarik (mly at prep)
+
+ * rmailmsc.el (set-rmail-inbox-list):
+ More informative prompt.
+
+Mon Jan 5 01:15:17 1987 Richard M. Stallman (rms at prep)
+
+ * paths.el: Prefer Berkeley-style formatted manual directories
+ (/usr/mat/cat1...) to ATT-style ones. Pyramid has trouble
+ if it uses ATT dirs in BSD universe.
+
+ * vi.el: New version from wu@crys.wisc.edu.
+
+ * Version 18.35 released.
+
+Sun Jan 4 22:11:20 1987 Richard M. Stallman (rms at prep)
+
+ * picture.el: Fix typo in define-key for C-c<.
+
+Sun Jan 4 21:15:59 1987 Richard Mlynarik (mly at prep)
+
+ * prolog.el:
+ Don't modify current buffer's syntax-table when loading this file.
+
+Sat Jan 3 19:59:41 1987 Richard M. Stallman (rms at prep)
+
+ * x-mouse.el: Define names for the button-up events.
+
+Wed Dec 31 04:19:31 1986 Richard M. Stallman (rms at prep)
+
+ * bytecomp.el (byte-compile-function-form):
+ Was miscompiling (function SYMBOL) by failing to quote SYMBOL.
+
+Sun Dec 28 14:32:22 1986 Richard Mlynarik (mly at prep)
+
+ * userlock.el:
+ Bind cursor-in-echo-area for read-char.
+
+Wed Dec 24 18:31:50 1986 Richard Mlynarik (mly at prep)
+
+ * terminal.el:
+ Lots of things changed.
+ Have to start a shell just to call stty since emacs
+ won't set things up correctly!!! (We end up sometimes
+ execing 5 programs to start up...)
+ Emulator terminal-type capabilities extended somewhat
+ and `command-set' made somewhat emacs-oid in order to make
+ termscript files easier to understand.
+
+Tue Dec 23 02:11:49 1986 Richard M. Stallman (rms at prep)
+
+ * macros.el (insert-kbd-macro): Only look for global key bindings
+ since we don't know how to record local ones properly
+ (and in general there is no way to do it).
+
+ * bytecomp.el (byte-compile-find-vars-1):
+ Cons up and return a macroexpanded version of the form
+ being scanned.
+ Don't look inside a call to `function' or `condition-case'.
+ For catch, look only at first argument.
+
+ * bytecomp.el (byte-compile-find-vars):
+ Return (MACROEXPANDEDFORM . VARSUSED).
+
+ * bytecomp.el (byte-compile-top-level):
+ Use the macroexpanded form returned by byte-compile-find-vars
+ for subsequent compilation. Thus, each macro call is expanded
+ only once.
+
+Mon Dec 22 15:50:58 1986 Richard M. Stallman (rms at prep)
+
+ * subr.el: Delete nth and copy-keymap (now in fns.c and keymap.c).
+
+Mon Dec 22 14:04:15 1986 Richard Mlynarik (mly at prep)
+
+ * texinfmt.el (batch-texinfo-format):
+ Was printing message about source file rather than output file.
+
+Mon Dec 22 13:08:39 1986 Richard M. Stallman (rms at prep)
+
+ * subr.el: Remove `delete-backward-char-untabify',
+ insert `backward-'delete-char'.
+
+Mon Dec 22 11:06:47 1986 Richard Mlynarik (mly at prep)
+
+ * simple.el (undo):
+ Was missing local var `modified'
+
+ * subr.el:
+ Make `set-window-buffer' synonym for obfuscatory `show-buffer'
+ Make 'delete-backward-char-untabify' a synonym for
+ `backward-delete-char-untabify' -- the non-conventional naming of
+ the latter confuses people
+
+Sat Dec 20 23:38:00 1986 Richard Mlynarik (mly at prep)
+
+ * loaddefs.el:
+ Add autoload for sort-regexp-fields.
+
+ * sort.el:
+ Rename skip-fields -> sort-skip-fields to avoid name-conflict
+
+Sat Dec 20 21:51:22 1986 Richard M. Stallman (rms at prep)
+
+ * isearch.el (isearch): Print message "" only if don't set mark.
+ * isearch.el (isearch-message): Put cursor in echo area instead of
+ ellipsis.
+ * isearch.el (isearch-search): use one string-match to check
+ for all errors that mean "incomplete input".
+
+ * files.el (rename-auto-save-file):
+ Alter auto save file name of current buffer, and rename
+ any existing auto save file.
+
+ * files.el (set-visited-file-name): Use rename-auto-save-file
+ if auto save mode is already on.
+
+ * simple.el (undo): If undo-mode clears modified,
+ delete any auto-save file.
+
+Sat Dec 20 17:04:26 1986 Richard Mlynarik (mly at prep)
+
+ * fortran.el:
+ Allow fortran-comment-indent-char to be a string of length 1,
+ since that is what is documented in the printed v18 manuals.
+
+ * terminal.el:
+ Print a help message when emulator starts.
+ Fix a bug in te-escape-help.
+
+ * subr.el (read-quoted-char):
+ Document PROMPT arg.
+
+Fri Dec 19 16:26:05 1986 Richard M. Stallman (rms at prep)
+
+ * lisp.el (lisp-complete-symbol):
+ Don't put pre-completion text on kill ring.
+
+Fri Dec 19 11:31:22 1986 Richard Mlynarik (mly at prep)
+
+ * ftp.el (read-ftp-user-password):
+ Change prompting for user-name
+
+Thu Dec 18 01:40:37 1986 Richard M. Stallman (rms at prep)
+
+ * files.el (recover-file): Supply missing arg in call to error.
+
+ * isearch.el: If search-slow-window-lines is negative, put the
+ search window at the top. Always bind window-min-height to 1.
+
+ * isearch.el: When extending a reverse non-regexp search
+ must not extend past barrier (same idea as below for regexps).
+
+Wed Dec 17 11:44:21 1986 Richard M. Stallman (rms at prep)
+
+ * isearch.el: Combine code for search-repeat-char and
+ search-reverse-char into one cond clause.
+ If search direction is changing, don't greb prev search-string.
+ Otherwise, do grab it if search-string is currently empty.
+
+ * isearch.el: When extending a reverse regexp search string,
+ criterion for extending current match was one off, and also
+ now won't go into the area beyond where last C-r was typed.
+
+ * replace.el (perform-replace): If user types C-l,
+ clear screen, redisplay, and ask again.
+
+ * isearch.el: In regexp isearch, when a ?, * or | is input,
+ back up start of search. New local variable `barrier' is
+ position of original command or of last C-s or C-r; it
+ is saved by isearch-push-state.
+
+Mon Dec 15 09:30:22 1986 Richard Mlynarik (mly at prep)
+
+ * fortran.el:
+ Initialise fortran-mode-abbrev-table correctly.
+
+ * fortran.el:
+ fortran-comment-indent-char should be a character (a fixnum), not
+ a string of length one.
+
+ * rmail.el:
+ Add support for delta-from-UT timezone specs ("EST" = "-0500")
+ Add support for four-character timezone specifications such as NZST
+ [This is actually a bit suspect, since four-character timezone
+ specs violate the rfc822 date format -- one should be using a spec
+ like "+1000" instead]
+
+Fri Dec 12 09:21:03 1986 Richard M. Stallman (rms at prep)
+
+ * loaddefs.el: Delete incorrect entry for .mss in auto-mode-alist,
+ so correct entry is visible.
+
+ * rmail.el (rmail): Initialize rmail-last-{rmail-,}file here
+ rather than when rmail.el is loaded.
+
+ * Version 18.33 released.
+
+ * rnewspost.el: require sendmail.
+
+ * loaddefs.el: Autoload scribe-mode and use for ".mss" files.
+ Autoload modula-2-mode and prolog-mode as well.
+
+ * sendmail.el (mail-mode): Set buffer-offer-save.
+
+ * files.el (save-some-buffers): If user says `n' to "Save
+ abbrevs?", clear abbrevs-changed so won't ask again.
+
+ * files.el (buffer-offer-save): New variable, local in all buffers.
+ * files.el (save-some-buffers): New 2nd arg EXITING.
+ If non-nil, offer to save any nonempty modified buffer
+ in which `buffer-offer-save' is non-nil.
+
+ * sup-mouse.el: New file to handle mouse commands on
+ supdup terminals.
+
+Thu Dec 11 17:59:43 1986 Chris Hanson (cph at prep)
+
+ * man.el: Fix bug in regexp used to nuke footers in hp-ux.
+
+Thu Dec 11 17:52:44 1986 Richard M. Stallman (rms at prep)
+
+ * keypad.el: Fix typo "kill-linee".
+
+Thu Dec 11 14:19:20 1986 Richard Mlynarik (mly at prep)
+
+ * isearch.el (isearch):
+ Never set search-last-string to ""
+
+Wed Dec 10 17:28:20 1986 Richard M. Stallman (rms at prep)
+
+ * help.el (help-for-help): Once long help text is on screen,
+ bind cursor-in-echo-area to t for reading subsequent chars.
+
+ * sort.el (sort-columns): Fix typo (col-beg1 was col-beg
+ and likewise for col-end1).
+
+Tue Dec 9 16:06:45 1986 Richard Mlynarik (mly at prep)
+
+ * terminal.el, ehelp.el:
+ New files.
+ "terminal" still needs a small amount of documentation.
+
+Sat Dec 6 14:28:39 1986 Richard M. Stallman (rms at prep)
+
+ * Version 18.32 released.
+
+ * scribe.el: New file containing scribe-mode.
+ * server.el: New file containing server-start
+ (makes existing Emacs process serve as "the editor" for
+ other programs that want to invoke an editor subprocess.)
+
+Fri Dec 5 01:14:16 1986 Richard M. Stallman (rms at prep)
+
+ * subr.el (substitute-key-definition): [MLY]
+ The definitions are in the cdr's of alist elts, not the cars.
+
+ * mh-e.el: 3.4h from Larus.
+
+ * rmail.el (rmail-get-new-mail):
+ Never bind make-backup-files to t if it was nil before.
+
+ * keypad.el (function-key-sequence):
+ * macros.el (insert-kbd-macro):
+ * vi.el:
+ Pass local map argument to where-is-internal.
+
+ * c-mode.el (c-backward-to-noncomment): Skip ^L like newline.
+
+ * c-mode.el (calculate-c-indent):
+ When checking for continued previous lines, after skipping one,
+ use c-backward-to-noncomment to find next real text.
+ When classifying top-level lines, ignore page breaks;
+ lines ending in } are not continued lines.
+
+ * rmailkwd.el (rmail-set-label):
+ Delete whitespace only next to commas.
+
+ * rmailkwd.el (rmail-nuke-whitespace): Delete this function.
+
+ * sendmail.el (mail-do-fcc): Delete the entire line of an fcc
+ including the newline after it. Was failing to do so
+ if the line had a space or tab at the end.
+
+ * c-mode.el (c-indent-line): Don't think that "else_..."
+ is the keyword "else".
+
+ * rmail.el (rmail-search): For reverse search, use
+ re-search-forward to filter messages; then, once a message is found,
+ use re-search-backward to position point within it.
+
+ * rmail.el (rmail-expunge): Don't bomb if rmail file is empty.
+ * rmail.el (rmail-show-message): If showing message number zero,
+ don't beep, and set point at beginning of it.
+ * rmail.el (rmail-set-message-counters): If no messages, set
+ rmail-current-message to 0.
+
+Thu Dec 4 18:53:38 1986 Richard Mlynarik (mly at prep)
+
+ * ftp.el (ftp-sentinel):
+ Catch time taken/transfer-rate information.
+
+Tue Dec 2 22:35:00 1986 Richard M. Stallman (rms at prep)
+
+ * float.el (float-to-string): Don't infinite-loop if arg is zero.
+
+ * float.el (float-regexp): Accept numbers lacking digits before
+ the point. Accept numbers with a point and no digits after it.
+ Don't get confused by matching just part of the input.
+
+ * float.el (string-to-float): Detect if loading-0s
+ gets to equal the length of digit-string.
+
+Tue Dec 2 15:46:37 1986 Richard Mlynarik (mly at prep)
+
+ * float.el (extract-match):
+ Convert to new re-register regime
+
+Mon Dec 1 18:08:39 1986 Richard Mlynarik (mly at prep)
+
+ * mailalias.el (expand-mail-aliases):
+ Check for case of (eq mail-aliases t) -- can happen if mail-mode
+ is entered without calling mail-setup (eg when trying to recover
+ an autosaved mail file)
+
+Wed Nov 26 17:30:21 1986 Richard Mlynarik (mly at prep)
+
+ * loaddefs.el:
+ mode-line-format should contain (-3 . "%p") rather than "%3p"
+
+ * terminal.el:
+ Use the "env" program
+
+Wed Nov 26 00:07:19 1986 Richard M. Stallman (rms at prep)
+
+ * compile.el (compile1, compilation_sentinel):
+ Don't make *compilation* read-only.
+
+ * simple.el (next-complex-command): fix one-off about
+ largest allowed value of ARG. If attempting to move
+ past beginning or end of history, move to the first or
+ last element and then signal an error.
+
+ * terminal.el: New file, like shell-mode modified to
+ simulate a display terminal for the inferior.
+
+Tue Nov 25 00:04:36 1986 Richard M. Stallman (rms at prep)
+
+ * outline.el (outline-mode): outline-regexp must match at start
+ of line to be a paragraph start.
+
+ * simple.el ({beginning,end}-of-buffer):
+ When buffer-size is large, divide before multiplying
+ to avoid overflow.
+
+ * mailalias.el (expand-mail-aliases):
+ Re-expand the expansions for compatibility with Berkeley mail.
+
+ * ftp.el: New file for visiting remote files using FTP.
+
+Mon Nov 24 14:07:40 1986 Richard M. Stallman (rms at prep)
+
+ * files.el (find-file-noselect): Due to change in
+ insert-file-contents, need not set buffer-file-name if error.
+
+ * paths.el: Correct manual-formatted-dirlist for USG systems.
+
+ * man.el: Use new subroutine insert-man-file to insert files
+ uncompressing if nec. Also uncompact compacted files.
+ Detect sysV footers. Detect headers when section contains a
+ letter (as in 3n). Delete the vars already moved to paths.el.
+
+ * disass.el: new name for disassemble.el to avoid USG truncation.
+ loaddefs.el changed for this.
+
+Mon Nov 24 02:43:08 1986 Chris Hanson (cph at prep)
+
+ * term/supdup.el: Add code for hp-ux which has no binding for the
+ TERMCAP environment variable.
+
+Sun Nov 23 00:03:35 1986 Richard M. Stallman (rms at prep)
+
+ * version 18.31 released.
+
+ * x-mouse.el: New mouse-command keys are C-x C-@.
+
+Sat Nov 22 14:15:11 1986 Richard Mlynarik (mly at prep)
+
+ * bytecomp.el (byte-recompile-directory):
+ Use third arg to `directory-files'
+
+Sat Nov 22 02:26:22 1986 Richard M. Stallman (rms at prep)
+
+ * subr.el: Defvars for global-map, ctl-x-map, esc-map
+ and mouse-map, just so they get doc strings.
+
+Fri Nov 21 15:43:49 1986 Richard M. Stallman (rms at prep)
+
+ * bytecomp.el (byte-compile-file): Bind vms-stmlf-recfm to t
+ around writing the output file.
+
+Fri Nov 21 14:46:37 1986 Leonard H. Tower Jr. (tower at prep)
+
+ * rnews.el, rnewspost.el (caesar-region, news-caesar-buffer-body)
+ Added former from phr, rename latter and modified it to work with
+ former. Changed key-bindings for rename. This gets rid of the
+ interface (which also is ugly) to the UNIX "tr" command.
+
+Fri Nov 21 00:29:13 1986 Richard M. Stallman (rms at prep)
+
+ * mh-e.el (mh-display-msg):
+ Pass non-nil 2nd arg to insert-file-contents
+
+Thu Nov 20 23:57:52 1986 Richard M. Stallman (rms at prep)
+
+ * vip.el (vip-find-char): Use search-forward instead of
+ * yow.el (snarf-yows): scan-buffer. A few other local
+ * man.el (manual-entry): simplifications.
+
+ * bytecomp.el: Don't open-code scan-buffer.
+
+Thu Nov 20 12:33:31 1986 Richard Mlynarik (mly at prep)
+
+ * helper.el:
+ Flush Helper-major-mode, Helper-mode-name:
+ there is a much simpler way of doing this
+ (see new Helper-describe-mode)
+ Make it work for Helper-return-blurb to be buffer-local
+ (this is better than binding it dynamically)
+
+ * ebuffer-menu.el, echistory.el, view.el:
+ Flush references to Helper-{major-mode,mode-name}
+
+Wed Nov 19 22:39:57 1986 Richard M. Stallman (rms at prep)
+
+ * indent.el: Make tab-stop-list a user variable.
+
+ * rmail.el: Undo previous change to rmail-show-message.
+
+Tue Nov 18 08:39:59 1986 Richard Mlynarik (mly at prep)
+
+ * prolog.el (end-of-prolog-clause):
+ Typo
+
+ * ebuff-menu.el:
+ Make "n" and "p" synonymous with "\C-n" and "\C-p"
+
+ * rmail.el (rmail-show-message):
+ With no interactive argument, just move to beginning of current
+ message (like ".") rather than to message 1.
+
+Sun Nov 16 23:32:19 1986 Richard M. Stallman (rms at prep)
+
+ * startup.el: expect window-system to be a symbol, not a string,
+ and concatenate "-win" instead of "-windows" to keep
+ file names short.
+
+ * term/x-win.el: New name for term/X-windows.el
+ needed due to change in dispnew.c re window-systems.
+
+Sun Nov 16 11:04:33 1986 Leonard H. Tower Jr. (tower at prep)
+
+ * rnews.el (news-ignored-headers)
+ removed Organization:, so it's visible to readers.
+
+Fri Nov 14 13:16:48 1986 Richard M. Stallman (rms at prep)
+
+ * Emacs version 18.30 *
+
+ * rmail.el (rmail-forward):
+ Use mail-other-window unless there is only one window visible.
+ Use of `mail' instead in the case of multiple windows on the
+ screen makes it a nuisance to get back to Rmail.
+
+ * outline.el (outline-regexp): ^L starts a header line.
+
+Thu Nov 13 23:38:57 1986 Richard M. Stallman (rms at prep)
+
+ * fill.el (fill-region-as-paragraph):
+ If 1st line starts with fill prefix, exclude that fill
+ prefix from the preprocessing before actual filling.
+ Fixes failure to preserve initial whitespace after a fill prefix.
+
+Tue Nov 11 14:57:25 1986 Leonard H. Tower Jr. (tower at prep)
+
+ * rnews.el (news-show-all-headers)
+ Added code to replace previously deleted (news-get-back).
+
+ * emacsbug.el (report-emacs-bug):
+ Got rid of redundant "on system-name (system-type)" now that
+ (emacs-version) outputs it.
+
+Mon Nov 10 08:54:05 1986 Richard Mlynarik (mly at prep)
+
+ * dired.el (dired-mode):
+ (run-hooks 'dired-mode-hook)
+
+Sun Nov 9 21:59:30 1986 Richard Mlynarik (mly at prep)
+
+ * files.el (set-visited-file-name):
+ (kill-local-variable 'write-file-hooks)
+
+Sun Nov 9 14:28:43 1986 Richard M. Stallman (rms at prep)
+
+ * simple.el (push-mark): Print nothing if minibuffer active.
+
+Sat Nov 8 09:38:18 1986 Richard M. Stallman (rms at prep)
+
+ * rnews.el (news-set-mode-line):
+ Don't change mode-line-format; instead change mode-line-process
+ and mode-line-buffer-identification.
+ Delete unused function `strcpyn'.
+
+ * echistory.el (electric-command-history):
+ Delete no-op `let'.
+
+ * compile.el (compile1): Flush v17 compatibility code to sett
+ mode-line-format.
+ * info.el (Info-set-mode-line, Info-edit): Ditto.
+ * shell.el (shell-mode, inferior-lisp-mode): Ditto.
+ * telnet.el (telnet-mode): Ditto.
+
+ * c-mode.el (calculate-c-indent): When deciding whether
+ a line is a continuation, ignore label-lines.
+ Also ignore preceding lines that end in commas. Consequence:
+ if the preceding line is a continuation, our line
+ is indented just like it (as a continuation of the same thing).
+
+ * loadup.el: look for new file "site-load.el" to preload
+ libraries before the DOC file is read.
+
+Fri Nov 7 19:15:57 1986 Richard M. Stallman (rms at prep)
+
+ * novice.el (disabled-command-hook):
+ Catch errors in `documentation' in case doc file is missing.
+
+ * keypad.el (function-key-sequence):
+ Use cons, not list, to make the definition to search for.
+
+Fri Nov 7 12:30:48 1986 Richard Mlynarik (mly at prep)
+
+ * sort.el (sort-build-lists):
+ Delete CPH's change.
+ This had already been fixed in a different way.
+
+Fri Nov 7 10:40:40 1986 Richard M. Stallman (rms at prep)
+
+ * c-mode.el (calculate-c-indent):
+ A line ending in singlequote-colon now does not make the
+ following line be considered a continuation.
+
+Fri Nov 7 09:14:29 1986 Chris Hanson (cph at prep)
+
+ * sort.el (sort-build-lists):
+ Was not initializing point to the beginning of the region. As a
+ result, if one tried to sort a region where point was at the end
+ and mark at the beginning, nothing would happen.
+
+Thu Nov 6 19:47:21 1986 Richard M. Stallman (rms at prep)
+
+ * subr.el (indent-to-column): New alias for indent-to.
+
+Thu Nov 6 18:09:10 1986 Leonard H. Tower Jr. (tower at prep)
+
+ * rnewspost.el
+ Finish bringing posting and followups (mostly) up to the News 2.11
+ revision of RFC 850 (exceptions noted in rnewspost.el's header).
+ Added function news-reply-yank-original, to be used in lieu of
+ mail-yank-original.
+
+Thu Nov 6 12:46:57 1986 Richard M. Stallman (rms at prep)
+
+ * version.el (emacs-version):
+ Include host name and system type.
+
+ * rmail.el: rmail-edit-current-message moved from C-r to w.
+ Doc string of rmail-mode changed.
+
+ * loaddefs.el (auto-mode-alist, completion-ignored-extensions):
+ Ignore ".blg" and ".bbl". Know modes for ".bbl" and ".bib".
+ Rearrange auto-mode-alist with frequently used elts first.
+
+ * files.el (find-file-noselect):
+ Eliminate incorrect nested or-for-effect within or-for-effect.
+ Bug was it didn't offer to reread a changed file.
+
+Wed Nov 5 16:32:31 1986 Leonard H. Tower Jr. (tower at prep)
+
+ * rnewspost.el (news-reply)
+ Fixed bug when point was outside of header on invocation.
+ Added References: header line per RFC850.
+
+Wed Nov 5 12:48:44 1986 Richard M. Stallman (rms at prep)
+
+ * files.el (file-name-sans-versions):
+ Fix one more typo in name of argument variable.
+
+Wed Nov 5 11:01:57 1986 Richard Mlynarik (mly at prep)
+
+ * mh-e.el:
+ Version 3.4d from Larus
+
+Wed Nov 5 10:10:53 1986 Richard M. Stallman (rms at prep)
+
+ * novice.el (disabled-command-hook):
+ Clean up the message in the case of coming from M-x ...
+
+Tue Nov 4 17:55:33 1986 Richard M. Stallman (rms at prep)
+
+ * various files (dired-mode, Edit-options-mode, rmail-mode,
+ rmail-summary-mode, rmail-edit-mode, Buffer-menu-mode):
+ Give these symbols `special' as a `mode-class' property.
+
+ * dired.el (dired-mode): Take out local value for
+ default-major-mode. The mode-class property now makes sure
+ new buffers are not made in dired-mode.
+
+Tue Nov 4 16:58:49 1986 Leonard H. Tower Jr. (tower at prep)
+
+ * rnews.el
+ Add several C-C C-F C-letter fields in RFC 850.
+
+Tue Nov 4 11:56:46 1986 Richard Mlynarik (mly at prep)
+
+ * paragraphs.el (various):
+ (interactive "*") needed in some places.
+
+Mon Nov 3 23:31:42 1986 Richard M. Stallman (rms at prep)
+
+ * help.el (variable-at-point):
+ Catch all errors anywhere within. Fixes bug when
+ `C-h v' was done with point after an `('.
+
+Sun Nov 2 17:30:54 1986 Richard Mlynarik (mly at prep)
+
+ * files.el (backup-buffer):
+ "neq" isn't defined -- use /=
+
+Sat Nov 1 00:28:14 1986 Richard Mlynarik (mly at prep)
+
+ * simple.el (open-line):
+ interactive "*"
+
+ * rmail.el (rmail-variables):
+ rmail-keywords should be buffer-local
+
+ * undigest.el:
+ Another broken-un*x-mailer-compensation fix from rlk.
+
+ * file.el (file-name-sans-version):
+ Fix typo in VMS case.
+
+Thu Oct 30 20:12:01 1986 Richard Mlynarik (mly at prep)
+
+ * xscheme.el:
+ defvar scheme-program-name, not defconst
+
+ * keypad.el (setup-terminal-keypad):
+ Use correct format for indirect keymap entries.
+
+Wed Oct 29 19:07:03 1986 Leonard H. Tower Jr. (tower at prep)
+
+ * rnews.el, rnewspost.el:
+ Created later from parts of former to speed up initial rnews load
+ (also debugging time). Added autoloads as appropriate. The mail and
+ posting commands are most often not used in an rnews session.
+
+Wed Oct 29 18:53:37 1986 Richard Mlynarik (mly at prep)
+
+ * startup.el (command-line):
+ VMS sys$login:.emacs
+
+Wed Oct 29 14:13:10 1986 Leonard H. Tower Jr. (tower at prep)
+
+ * rnews.el (news-inews):
+ Added save-excursion call. Got bury-buffer at right nesting level.
+ Got rid of unneeded code.
+
+ * rnews.el (news-rotate-buffer-body):
+ Added and modified this function written by paul@media-lab.mit.edu.
+ Bound it to C-c C-r in both news and post-news modes.
+
+ * rnews.el:
+ Message text cleanup.
+
+Wed Oct 29 13:27:26 1986 Richard Mlynarik (mly at prep)
+
+ * help.el (view-lossage):
+ Use (goto-char (point-min)), not (beginning-of-buffer))
+
+ * electric.el (shrink-window-if-larger-than-buffer):
+ New function. Perhaps this should be in subr.el?
+
+ * tags.el (find-tag):
+ If arg is "" and interactive, put computed tag into
+ command-history so that repeat-complex-command works.
+
+ * subr.el (momentary-string-display):
+ Avoid losing due to file-locking.
+
+ * files.el (auto-save-mode):
+ Print a confirming message if interactive.
+
+Tue Oct 28 01:12:35 1986 Richard Mlynarik (mly at prep)
+
+ * undigestify.el:
+ Compensate for broken MH digests
+
+ * tex-mode.el (TeX-region):
+ Call csh with -f flag
+
+ * rmail.el (rmail-forward):
+ Use mail, not mail-other-window.
+
+Mon Oct 27 14:46:48 1986 Richard Mlynarik (mly at prep)
+
+ * nroff-mode (electric-nroff-mode):
+ Fix bugs.
+
+ * electric.el, ebuff-menu.el, echistory.el:
+ Do the `space to flush' before calling Electric-command-loop
+ Delete the space to flush in electric-command-history.
+
+ * tex-mode.el:
+ defconst -> defvar
+
+Sun Oct 26 01:32:14 1986 Richard Mlynarik (mly at prep)
+
+ * sendmail.el:
+ (provide 'sendmail)
+
+ * files.el (basic-save-buffer):
+ Set file modes appropriately in file-precious-flag case.
+
+Wed Oct 22 18:00:18 1986 Richard Mlynarik (mly at prep)
+
+ * Rename term/xterm.el => term/X-windows.el
+
+ * startup.el (command-line):
+ If the variable window-system is non-nil, load
+ (concat term-file-prefix window-system "-windows")
+ rather than (concat term-file-prefix (getenv "TERM"))
+
+ * files.el (basic-save-buffer):
+ Fix write-file-hooks.
+
+ * tex-mode.el (TeX-region):
+ Ensure newline before trailer (from gildea)
+
+Tue Oct 21 11:39:56 1986 Richard Mlynarik (mly at prep)
+
+ * rmailedit.el (rmail-cease-edit):
+ Don't add edited attribute unless changes were actually made.
+
+ * term/xterm.el (x-handle-switch):
+ command-line-args => command-line-args-left (yet again)
+
+Mon Oct 20 18:40:23 1986 Richard Mlynarik (mly at prep)
+
+ * sort.el:
+ Work if (point) > (mark)
+
+ * vip.el (vi-change-mode-line):
+
+Sat Oct 18 17:02:13 1986 Richard Mlynarik (mly at prep)
+
+ * add-log.el (add-change-log-entry):
+ If file specified is a directory, then use `ChangeLog' in that
+ directory.
+
+ * sendmail.el (mail-send-and-exit):
+ Don't kill selected-window, if given a prefix arg.
+
+ * files.el (normal-mode):
+ Don't clobber value of major-mode set by way of default-major-mode.
+
+Fri Oct 17 01:06:06 1986 Richard Mlynarik (mly at prep)
+
+ * help.el, picture.el, simple.el, tags.el, vi.el:
+ Doc/spelling fixes from sjk
+
+ * rmailsum.el:
+ use new mode-line technology
+
+ * rmail.el (rmail-reply):
+ Handle resent-reply-to better.
+
+Wed Oct 15 16:20:03 1986 Richard Mlynarik (mly at prep)
+
+ * edt.el:
+ (require 'keypad)
+
+ * dired.el (dired-mode):
+ Don't lose finding files from dired when default-major-mode is
+ nil.
+
+Tue Oct 14 18:08:53 1986 Richard Mlynarik (mly at prep)
+
+ * texinfmt.el:
+ Support for @include from schaefer%andy.bgsu.edu@CSNET-RELAY.ARPA
+
+ * dabbrev.el (dabbrev-expand):
+ Give useful error message. Use save-excursion.
+ Allow both symbol-constituent and word-constituent chars in the
+ expansion.
+
+ * files.el (save-buffers-kill-emacs):
+ Make arg optional.
+
+Sun Oct 12 02:26:26 1986 Richard Mlynarik (mly at prep)
+
+ * macros.el (name-last-kbd-macro):
+ Insert omitted argument in error message.
+
+ * userlock.el (ask-user-about-lock-help):
+ Improve help message.
+
+Sat Oct 11 16:33:51 1986 Richard Mlynarik (mly at prep)
+
+ * files.el (find-backup-file-name):
+ Call make-backup-file-name rather than appending "~"
+
+ * lisp-mode.el:
+ Make `|' have `"' syntax for |WeIrD SymbolS|
+
+Fri Oct 10 14:21:15 1986 Richard Mlynarik (mly at prep)
+
+ * edt.el, vi.el:
+ typo.
+
+Wed Oct 8 09:56:38 1986 Richard Mlynarik (mly at prep)
+
+ * bytecomp.el (byte-compile-function-form):
+ Handle "(function symbol)"
+
+ * sendmail.el (mail-position-on-field):
+ Return nil if field wasn't there and we did add (the
+ non-`soft' case)
+
+Tue Oct 7 01:57:31 1986 Richard Mlynarik (mly at prep)
+
+ * shell.el:
+ Split off shell-set-directory from shell-send-input.
+
+ * dabbrev.el (dabbrev-expand):
+ Fix bugs. Check whether last-command was a dabbrev-expand.
+ Undo-boundary.
+
+Sat Oct 4 14:50:01 1986 Richard Mlynarik (mly at prep)
+
+ * info.el (Info-find-node):
+ Bug in case of nodename "*"
+
+ * info.el (Info-search):
+ Hair plus: make search work with split subfiles.
+ Also, push position on node history if searching puts us in a
+ different node.
+
+ * debug.el (debug):
+ New match-data format.
+
+ * info.el (Info-goto-node):
+ Adjust to new regexp-register scheme.
+
+ * info.el (Info-read-subfile):
+ Node delimiter is \n\^_, not just \^_
+
+ * texinfmt.el (batch-texinfo-format):
+ Wasn't updated when Info-validate was given a required arg.
+
+ * informat.el (Info-validate, Info-tagify):
+ Warn that don't know how to hack indirect files.
+
+ * texinfmt.el, informat.el (batch-{texinfo-format,info-validate}):
+ First elt of command-line-args-left shouldn't be skipped.
+
+Thu Oct 2 21:40:50 1986 Richard Mlynarik (mly at prep)
+
+ * info.el (Info-find-node):
+ Tag-table position match-data was being clobbered by intervening
+ search for "(indirect)"
+
+Thu Oct 2 01:59:17 1986 Richard M. Stallman (rms at prep)
+
+ * texinfmt.el: define @smallbook and @tex ... @end tex.
+
+Wed Oct 1 02:02:14 1986 Richard M. Stallman (rms at prep)
+
+ * lisp.el (lisp-complete-symbol): fix stupid bugs
+ affecting printing completion lists.
+
+ * loaddefs.el: Improve doc of isearch functions.
+
+ * texinfmt.el: Define commands chapheading, (sub)*heading
+ to format in the Info file like chapter and (sub)*section.
+
+ * macros.el (name-last-kbd-macro):
+ Supply (interactive).
+
+ * macros.el (insert-kbd-macro): Fix a few bugs.
+
+Mon Sep 29 00:55:06 1986 Richard M. Stallman (rms at prep)
+
+ * subr.el (momentary-string-display):
+ Use insert-before-markers to insert the string so that
+ the right cursor position is displayed.
+
+Sat Sep 27 04:56:36 1986 Richard M. Stallman (rms at prep)
+
+ * vip.el: renamed from vi1.el. Many cleanup changes.
+ Entry point is now vip-mode, autoloaded from loaddefs.el.
+
+Fri Sep 26 17:47:32 1986 Richard Mlynarik (mly at prep)
+
+ * files.el (recover-file, find-file-noselect):
+ Add nowarn arg to find-file-noselect, so that recover-file doesn't
+ warn one that one should consider doing m-x recover file.
+
+ * subr.el (mod):
+ Synonym for "%"
+
+ * files.el (recover-file):
+ Call expand-file-name.
+
+ Also, get an error if user specifies an auto-save filename.
+ (Would be able to do something useful if there were a way
+ to get back the original filename from the auto-save filename)
+
+Thu Sep 25 18:35:16 1986 Richard M. Stallman (rms at prep)
+
+ * man.el (manual-entry): If formatted man file name ends
+ in .Z, uncompress it.
+
+ * macros.el (name-last-kbd-macro):
+ Now in Lisp code and autoloaded.
+ Get an error if name has a definition that's not a kbd macro.
+
+Thu Sep 25 01:17:07 1986 Richard Mlynarik (mly at prep)
+
+ * replace.el (perform-replace):
+ Make ? (as well as C-h) give help for query-replace(-regexp)
+
+Wed Sep 24 15:22:37 1986 Richard Mlynarik (mly at prep)
+
+ * simple.el (set-mark):
+ set-mark is in lisp code now (from editfns.c)
+
+ * bytecomp.el:
+ Don't compile (mark) specially -- lisp code shouldn't
+ call this function very freqently.
+
+ * startup.el (command-line-1):
+ (let ((load-path (cons default-directory load-path))) (load ...))
+ so that the "-load" switch can specify a file relative to $cwd
+ now that $cwd isn't a component of emacs' default load-path.
+
+ * man.el (manual-entry)
+ HPUX dain bramage.
+
+Tue Sep 23 20:02:01 1986 Richard M. Stallman (rms at prep)
+
+ * help.el: New file containing help commands
+ formerly in simple.el. Installed in loadup.el
+ and ../src/ymakefile.
+
+ * help.el: Move calls to print-help-return-message
+ inside the with-output-to-temp-buffer constructs.
+ Outside, they saw the window state after displaying
+ the buffer and printed the wrong stuff.
+
+ * help.el (print-help-return-message):
+ If the help buffer is already visible, do nothing
+ since it is impossible to bring back the old contents
+ of that buffer in this case.
+
+ If given an argument, apply that argument to the message
+ (and return the result) instead of calling `message' with it.
+
+Tue Sep 23 16:17:48 1986 Richard Mlynarik (mly at prep)
+
+ * files.el (revert-buffer)
+ Pass noconfirm arg to revert-buffer-function
+ dired.el (dired-revert) Ignore extra arg.
+
+ * tags.el (visit-tags-table-buffer)
+ noconfirm revert-buffer
+
+Tue Sep 23 14:33:20 1986 Richard M. Stallman (rms at prep)
+
+ * rmail.el: Define "x" like "e" for consistency with Dired.
+
+ * buff-menu.el (Buffer-menu-other-window):
+ New function on "o" command, acts like "o" in Dired.
+ * buff-menu.el (Buffer-menu-this-window):
+ New function on "f" command, acts like "f" in Dired.
+ * buff-menu.el (Buffer-menu-mode):
+ Update doc for these changes and C-d change.
+
+ * mh-e.el: Version 3.4a from Larus.
+
+Tue Sep 23 11:06:41 1986 Richard Mlynarik (mly at prep)
+
+ * doctor.el:
+ Heroine isn't a drug.
+
+ * ebuff-menu.el (electric-buffer-list)
+ If no buffers are marked with ">" just select the selected buffer
+ and don't change the window configuration or any other buffers.
+ If more than one buffer is selected, split the screen up between
+ those buffers.
+ Remove after-electric-buffer-menu. "kill" -> "delete"
+
+ * buff-menu.el
+ Use "D" rather than "K" for buffers to be deleted for
+ consistency with rmail and dired and others.
+
+ Rename "kill" -> "delete" for both function-names and documentation.
+
+ Define C-d as Buffer-menu-delete-backwards. (also in ebuff-menu)
+
+ Save space: Merge buffer-menu-{execute,do-saves,do-kills}
+
+Mon Sep 22 15:54:49 1986 Richard M. Stallman (rms at prep)
+
+ * macros.el (insert-kbd-macro): New function to insert
+ Lisp code to define a kbd macro as it is now defined.
+ * macros.el ({write,append}-kbd-macro): Commands deleted.
+ * loaddef.el: change autoloads for above changes.
+
+ * simple.el (callers of print-help-return-message):
+ Calling this function is now the last thing done in each caller.
+
+Mon Sep 22 13:18:44 1986 Richard Mlynarik (mly at prep)
+
+ * loaddefs.el
+ Fix some defvars/defconsts whose doc-string didn't start on the
+ same line (yuck). Split some of these into a defvar nil followed
+ by a setq.
+
+Sun Sep 21 22:15:02 1986 Richard M. Stallman (rms at prep)
+
+ * loaddefs.el (auto-mode-alist):
+ Don't use non-saved-text-mode now that it is deleted.
+
+Sun Sep 21 15:56:25 1986 Richard Mlynarik (mly at prep)
+
+ * disassemble.el, fortran.el
+ Use insert-char.
+
+ * fortran.el (fortran-electric-line-number)):
+ "self-insert-command", not "self-insert"
+
+ * fortran.el (fortran-window-create):
+ Just bind window-min-width, don't set it.
+
+ * fortran.el (fortran-abbrev-start):
+ Don't mark buffer as modified after ";?"
+ fortran-abbrev-help -- do "message...done"
+
+ * files.el (revert-buffer)
+ Check to see if (file-exists-p buffer-auto-save-file-name)
+ even if (recent-auto-save-p) before offering to revert from it.
+
+ * text-mode.el:
+ Remove non-saved-text-mode
+
+ * *-mode.el
+ Fix some initializations of syntax-tables so that user
+ can override them.
+
+Sun Sep 21 14:54:30 1986 Richard M. Stallman (rms at prep)
+
+ * files.el (recover-file, list-directory):
+ Don't say /bin/ls; let search path be searched for ls.
+
+Sat Sep 20 21:25:01 1986 Richard M. Stallman (rms at prep)
+
+ * lisp.el (lisp-complete-symbol): New command does
+ completion on a symbol name in the buffer.
+
+ * fortran.el: New file defining fortran-mode,
+ which is autoloaded from loaddefs.
+
+ * abbrevlist.el: New file defining list-one-abbrev-table,
+ a function now used by fortran-mode but not Fortran-specific.
+
+Fri Sep 19 00:52:07 1986 Richard M. Stallman (rms at prep)
+
+ * subr.el (momentary-string-display): New function
+ to display a string momentarily in the buffer.
+
+ * loadup.el: Load loaddefs before simple and files
+ because loaddefs makes more garbage.
+
+ * loaddefs.el: Include defvar of ctl-x-4-map
+ needed now that this is loaded before files.el.
+
+Wed Sep 17 20:55:00 1986 Richard Mlynarik (mly at prep)
+
+ * hanoi.el
+ Vital improvements
+
+Wed Sep 17 12:13:58 1986 Richard M. Stallman (rms at prep)
+
+ * loaddefs.el: disable C-x p.
+ * loaddefs.el: autoload set-gosmacs-bindings.
+ * gosmacs.el: renamed from gosling.el with many changes
+ (saves old bindings and can restore them as they were).
+
+Wed Sep 17 11:02:39 1986 Richard Mlynarik (mly at prep)
+
+ * replace.el (occur)
+ Use variable list-matching-lines-default-context-lines if
+ no prefix arg specified.
+ If nlines arg is -ve, include that many lines of preceding
+ context, no lines of following context.
+ Use markers instead of line-numbers.
+ In occur-mode-goto-occurrence, warn about deleted buffer.
+
+Tue Sep 16 02:07:53 1986 Richard M. Stallman (rms at prep)
+
+ * simple.el (indent-for-comment):
+ Delete only the spaces before the beginning of the comment starter
+ in case the comment starter contains a leading space.
+
+ * abbrev.el (edit-abbrevs-map): Define C-c C-c like C-x C-s.
+
+ * texinfmt.el: define @r as noop.
+
+ * simple.el (print-help-return-message): New function.
+ Use before doing with-output-to-temp-buffer, and it
+ prints an echo area message about how to restore
+ current screen configuration from the configuration
+ that will obtain after the with-output-to-temp-buffer.
+
+ * simple.el (describe-{key,mode,function,variable}):
+ * simple.el (view-lossage, command-apropos):
+ Ca;; print-help-return-message.
+
+Mon Sep 15 17:49:07 1986 Richard M. Stallman (rms at prep)
+
+ * sendmail.el (sendmail-send-it):
+ Don't require newline before header-separator;
+ search for regexp and use `^'.
+
+ * mh-e.el: Version 3.4 from Larus.
+ Uses `interactive' properly to read the arguments.
+
+Sun Sep 14 19:44:31 1986 Richard Mlynarik (mly at prep)
+
+ * files.el (normal-mode)
+ Use shorter error message, so more fits on screen.
+
+Sun Sep 14 14:14:35 1986 Richard M. Stallman (rms at prep)
+
+ * loadup.el: On VMS, dump under name temacs.dump only.
+
+ * vms-patch.el (make-auto-save-file-name):
+ Append "$" at end as well as "_$" at front.
+
+ * files.el (cd): Don't do file-name-as-directory on VMS.
+
+Sat Sep 13 19:36:01 1986 Richard M. Stallman (rms at prep)
+
+ * bytecomp.el (byte-compile-file):
+ Don't bomb on defvar with no initial value argument.
+
+ * texinfmt.el (texinfo-format-buffer):
+ Tagify and maybe even split automatically if buffer is big enough.
+ Non-nil arg inhibits this.
+
+ * informat.el (Info-tagify):
+ Don't leave buffer narrowed if it wasn't narrowed to start with.
+
+ * simple.el (comment-column, fill-prefix):
+ Make them buffer-local and fix documentation.
+ * loaddefs.el: make indent-tabs-mode buffer-local.
+
+Fri Sep 12 18:37:08 1986 Richard M. Stallman (rms at prep)
+
+ * dired.el (dired-add-entry): Go to beginning of line
+ before adding the entry.
+
+Fri Sep 12 02:36:53 1986 Richard Mlynarik (mly at prep)
+
+ * mlsupport.el:
+ Define ml-substr (used to be in mocklisp.c)
+
+Fri Sep 12 02:07:23 1986 Richard M. Stallman (rms at prep)
+
+ * time.el: Don't just clobber global-mode-string.
+ Instead, add 'display-time-string as an element
+ and update the time by changing value of that variable.
+
+ * rmail.el (rmail-mode-1): Change only part of mode-line-format
+ Instead set mode-line-buffer-identification.
+
+ * rmail.el (rmail-show-message): Use mode-line-process to
+ display the message numbers and labels.
+
+Thu Sep 11 18:24:28 1986 Richard Mlynarik (mly at prep)
+
+ * compile.el (compilation-sentinel)
+ Ignore buffer-read-only.
+
+Wed Sep 10 17:40:01 1986 Richard M. Stallman (rms at prep)
+
+ * picture.el: Convert `Picture' to `picture' in all symbols.
+
+ * subr.el: Define old names send-string and send-region
+ as aliases for new names process-send-...
+
+Tue Sep 9 13:08:12 1986 Richard M. Stallman (rms at prep)
+
+ * time.el (display-time): variable display-time-interval
+ specifies seconds between updates.
+
+ * loaddefs.el: Put \-newline in doc strings that lacked it.
+
+Mon Sep 8 09:45:01 1986 Richard M. Stallman (rms at prep)
+
+ * simple.el: Give C-c's keymap a name, mode-specific-map.
+
+ * options.el (list-options): Use user-variable-p to filter
+ the variables and documentation-property to get the strings.
+
+Sat Sep 6 08:52:01 1986 Richard M. Stallman (rms at prep)
+
+ * tex-mode.el (tex-region):
+ Handle case where specified region extends before header.
+
+Thu Sep 4 17:00:05 1986 Leonard H. Tower Jr. (tower at prep)
+
+ * rnews.el (news-inews)
+ added -h to call of inews to insert all header fields.
+
+Thu Sep 4 08:37:49 1986 Richard M. Stallman (rms at prep)
+
+ * files.el (save-buffers-kill-emacs):
+ Prefix arg means save with no query.
+
+ * files.el (backup-buffer): Fix uses of % in message about %backup%.
+
+Wed Sep 3 12:22:06 1986 Leonard H. Tower Jr. (tower at prep)
+
+ * rnews.el (news-reply-mode-map)
+ Change mail-x field bindings from C-c x to C-c C-f C-x to agree
+ with sendmail.el .
+
+ * sendmail.el (mail-mode-map)
+ Change mail-x field bindings from C-c C-f x to C-c C-f C-x to
+ agree with ../etc/NEWS .
+
+Mon Sep 1 06:17:17 1986 Richard M. Stallman (rms at prep)
+
+ * info.el (Info-find-node, Info-read-subfile):
+ Now knows how to deal with indirect info files.
+ * info.el: Info-current-file is now the primary
+ place that records which info file is in the *info* buffer,
+ and it is updated as soon as a new file is correctly read.
+ * info.el: New var Info-current-subfile records which
+ subfile is in the *info* buffer, or is nil for an Info file
+ that doesn't have subfiles or if no subfile read in yet.
+
+ * informat.el (Info-split): New function to split
+ an Info file into a bunch of subfiles. It edits the original
+ file into an indirect file.
+
+ * info.el, loaddefs.el:
+ Autoloads for informat.el moved from info.el to loaddefs.el.
+
+Sun Aug 31 04:21:17 1986 Richard M. Stallman (rms at prep)
+
+ * page.el (mark-page):
+ * paragraphs.el (mark-paragraph):
+ * x-mouse.el (x-mouse-set-mark):
+ Use push-mark and inhibit the message, instead of set-mark.
+
+ * mh-e.el (mh-position-on-field, mh-exec-lib-cmd-output,
+ mh-exec-cmd-output): use push-mark instead of set-mark.
+
+ * simple.el (push-mark): optional 2nd arg NOMSG inhibits message.
+
+ * ebuff-menu.el (electric-buffer-list):
+ Was using the mark for internal purposes.
+ Use an anonymous marker instead.
+
+ * bytecomp.el: Stop using the byte-set-mark opcode.
+
+ * replace.el (occur): Put the *Occur* buffer in Occur mode.
+ Remember line number of each occurrence in occur-pos-list
+ Occur mode defines C-c C-c as occur-mode-goto-occurrence,
+ which uses that list to move the cursor in the original buffer
+ (which is saved in occur-buffer).
+
+ * aton.el (occur-menu: File deleted; occur-menu is subsumed by occur.
+
+ * isearch.el (isearch): repeating the search in either direction
+ must set success to t to produce correct echo area text.
+
+ * edt.el: New file. Autoloadable entry is edt-emulation-on.
+
+ * keypad.el (function-key-sequence): New function
+ finds which key sequence leads to a slot in function-keymap.
+
+Sat Aug 30 00:31:48 1986 Richard M. Stallman (rms at prep)
+
+ * files.el (backup-buffer): Use "%backup%~", not "%backup%",
+ if cannot write the backup in the usual place.
+
+ * sort.el (sort-columns): Sort into reverse order
+ if have prefix arg. Args are now the same as for
+ sort-lines, etc.
+
+Thu Aug 28 13:56:56 1986 Richard Mlynarik (mly at prep)
+
+ * c-mode.el (electric-c-{brace,terminator})
+ c-indent-line takes no args.
+
+Thu Aug 28 01:57:58 1986 Richard M. Stallman (rms at prep)
+
+ * files.el (backup-buffer): file-precious-flag forces copying.
+
+ * loaddefs.el: Autoload plain-TeX-mode and LaTeX-mode.
+ Define aliases for them. Fix doc for TeX-mode.
+
+Tue Aug 26 14:25:59 1986 Leonard H. Tower Jr. (tower at prep)
+
+ * rnews.el:
+ Added autoload of rmail-output and bound it to C-o in
+ news-mode-map. Also needed defvar of rmail-last-file.
+
+ * rmailout.el (rmail-output):
+ Made rmail-mode specific code dependent on rmail-mode being
+ major-mode.
+
+Mon Aug 25 03:47:24 1986 Richard M. Stallman (rms at prep)
+
+ * view.el (view-mode):
+ Bind mode-line-buffer-identification;
+ in new versions don't change mode-line-format.
+
+ * dired.el (dired-mode):
+ * info.el (Info-set-mode-line):
+ * x-menu.el (x-menu-mode):
+ Don't change mode-line-format.
+ Use mode-line-buffer-identification instead.
+ * ebuff-menu.el (electric-buffer-menu-mode):
+ Likewise, and also copy the mode-line-format
+ and replace `mode-name in it with "Buffers".
+
+ * info.el (Info-edit): Restore normal mode line
+ by killing the local variables used by Info to change it.
+
+ * echistory.el (electric-command-history):
+ In newer Emacs versions, don't alter mode-line-format.
+
+ * compile.el (compile1, compilation-sentinel):
+ * shell.el (shell-mode, inferior-lisp-mode):
+ * xscheme.el (inferior-scheme-mode):
+ * telnet.el (telnet-mode):
+ If minor-mode-alist is bound, put the %s or process status
+ into mode-line-process instead of changing mode-line-format.
+
+ * sort.el: New file contains buffer-sorting commands.
+ Autoload them in loaddefs.el.
+
+ * files.el (backup-buffer): Obey new variable
+ backup-by-copying-when-mismatch.
+
+ * loaddefs.el: Set default-mode-line-format to use
+ the new list and symbol constructs. Define minor-mode-alist.
+
+ * rnews.el (news-set-minor-modes):
+ Store the string in news-minor-modes, and set minor-modes
+ only if minor-mode-alist is unbound (Emacs versions < 18.16).
+ * rnews.el (news-mode): In newer Emacses, set mode-name
+ so it displays news-minor-mode.
+
+ * nroff-mode.el (nroff-mode):
+ If minor-mode-alist bound, add an entry for nroff-electric-mode
+ to it, and don't call set-minor-mode.
+
+ * simple.el (overwrite-mode, auto-fill-mode):
+ * abbrev.el (abbrev-mode):
+ Don't call set-minor-mode.
+
+ * simple.el (set-minor-mode): Delete this function.
+
+ * bytecomp.el (byte-compile-file):
+ Put backslash-newline at front of doc string when that is safe.
+ * bytecomp.el (old-file-newer-than-file-p):
+ Deleted this; built-in file-newer-than-file-p is well established.
+
+Sun Aug 24 03:11:41 1986 Richard M. Stallman (rms at prep)
+
+ * term/xterm.el: Install some changes from rlk.
+ -ib switch and InternalBorder default are handled.
+ Set variable x-processed-defaults when defaults are processed.
+ Use require to load x-mouse.
+ Use message to say why suspend-emacs is disabled.
+
+ * x-mouse.el: Install some changes from rlk.
+
+ * x-menu.el: New file that handles menus on X window system.
+
+ * buff-menu.el (buffer-menu): Put point on third line
+ initially (this line describes the buffer that had been selected).
+
+ * files.el (create-file-buffer):
+ Delete the variable ask-about-buffer-names
+ and simplify this function.
+
+Sat Aug 23 14:57:55 1986 Richard M. Stallman (rms at prep)
+
+ * files.el (basic-save-buffer):
+ When changing visited name, don't try to rename old auto-save file
+ if it does not exist.
+
+ * c-mode.el (c-indent-command): New definition of TAB,
+ uses c-indent-line as a subroutine. Handling of prefix arg
+ and indenting an entire expression rigidly is now in this fn.
+
+ * c-mode.el (c-tab-always-indent): If nil, TAB inserts a tab
+ if not in the initial whitespace of the line.
+
+ * c-mode.el (calculate-c-indent):
+ For statements: if prev line ends in `:', this line is still
+ a continuation if the `:' follows a non-symbol-constituent char.
+ For top level: look at previous line that starts in column 0
+ to determine whether this line is at top level or in arg decls.
+ Also notice if line is a continuation.
+
+ * novice.el (disabled-command-hook):
+ If the 'disabled property is a string, include it in the message.
+
+Thu Aug 21 14:50:03 1986 Richard M. Stallman (rms at prep)
+
+ * bytecomp.el (byte-compile-interactive-p):
+ Remove superfluous compilation of 'nil causing stack overflow.
+
+ * compile.el (compilation-parse-errors):
+ Count lines from the previous error message, not from line 1.
+
+Thu Aug 21 10:45:44 1986 Richard Mlynarik (mly at prep)
+
+ * debug.el (debug, debugger-eval-expression):
+ Evaluate the expression in the context of the buffer
+ current when the debugger was entered.
+
+Thu Aug 21 02:15:36 1986 Richard M. Stallman (rms at prep)
+
+ * files.el (after-find-file): Print no message
+ rather than printing a null message.
+
+Wed Aug 20 23:34:04 1986 Richard M. Stallman (rms at prep)
+
+ * files.el (set-auto-mode): On VMS, turn on case-fold-search
+ while matching auto-mode-alist elements.
+
+Wed Aug 20 12:30:45 1986 Richard M. Stallman (rms at prep)
+
+ * debug.el (debug): Don't try to restore the match data
+ if it refers to a dead buffer.
+
+ * startup.el (command-line-1):
+ -i FILE or -insert FILE means insert contents of file into buffer.
+
+Tue Aug 19 00:05:15 1986 Richard M. Stallman (rms at prep)
+
+ * simple.el (describe-variable):
+ Use `documentation-property' instead of `get' to get
+ the `variable-documentation' property.
+
+ * userlock.el: correct spelling "supercession" -> "supersession".
+
+ * files.el (basic-save-file):
+ If file-precious-flag is non-nil, rename the old file
+ before saving, and if saving fails, rename the old file back.
+
+ * rmail.el (rmail-get-new-mail):
+ Do not make a backup file if the rmail file was just visited
+ and hasn't been changed aside from reading the new mail.
+ This preserves the old backup file.
+ * rmail.el (rmail-expunge-and-save): New name for rmail-save.
+ * rmail.el (rmail-mode): Turn on file-precious-flag.
+
+ * dired.el: Define `g' as revert-buffer in dired-mode.
+
+ * c-mode.el (c-mode): Give `&' and `|' "punctuation" syntax.
+
+Mon Aug 18 14:24:55 1986 Richard Mlynarik (mly at prep)
+
+ * files.el (find-backup-file-name):
+ Don't blow up if (eq version-control 'never)
+
+ * files.el (set-visited-file-name):
+ Use `buffer-auto-save-file-name' not `auto-save-file-name' which
+ is unbound and unused.
+
+Sun Aug 17 18:34:09 1986 Richard M. Stallman (rms at prep)
+
+ * compile.el (compilation-sentinel):
+ Don't get error if *compilation* has been killed.
+ Include current date/time in message inserted in buffer.
+
+Sun Aug 17 15:07:28 1986 Richard Mlynarik (mly at prep)
+
+ * files.el (basic-save-buffer)
+ Fix paren error
+
+Sat Aug 16 19:25:09 1986 Richard M. Stallman (rms at prep)
+
+ * files.el (find-file-noselect):
+ Change find-file-not-found-hook to find-file-not-found-hooks
+ and make it a list of functions to call until one of them
+ returns non-nil.
+ * files.el (normal-mode, after-find-file):
+ Change find-file-hook to find-file-hooks, a list of functions to
+ call. Call it from after-find-file, not from normal-mode.
+ * files.el (revert-buffer):
+ Restore old point before calling after-find-file.
+ * files.el (basic-save-buffer):
+ Change write-file-hook to write-file-hooks, a list of functions
+ to run until one returns t. In that case, skip writing the file
+ the usual way.
+
+ * tags.el (visit-tag-table-buffer):
+ Get proper error for empty tag table file;
+ realize that char-after returns nil in that case.
+ Also move error check after auto-revert.
+
+Sat Aug 16 19:21:20 1986 Richard Mlynarik (mly at prep)
+
+ * subr.el
+ Move copy-alist to c code, moved nth from c code.
+
+Sat Aug 16 19:11:11 1986 Richard M. Stallman (rms at prep)
+
+ * files.el (normal-mode): initially call fundamental-mode
+ to reinitialize everything.
+
+ * files.el (hack-local-variables):
+ Don't consider suffix as including any leading spaces.
+
+Sat Aug 16 17:05:41 1986 Richard Mlynarik (mly at prep)
+
+ * informat.el, texinfmt.el
+ Detect and complain about duplicate node-names
+
+Sat Aug 16 16:56:05 1986 Richard M. Stallman (rms at prep)
+
+ * mh-e.el: 3.3j from Larus. Changes C-c C-g prefix to C-c C-f.
+
+Fri Aug 15 16:11:37 1986 Richard M. Stallman (rms at prep)
+
+ * isearch.el:
+ Default for regexp searches is now search-last-regexp.
+ Rename isearch-slow... vars to search-slow...
+ C-s or C-r in failing search wraps around buffer and tries again.
+ New local var `wrapped' records this has happened.
+ Display `Wrapped' in echo area at such times.
+ Record value of `wrapped' on the search state stack.
+ Display shorter string for incomplete regexps.
+ Incomplete regexp no longer implies "failure" of search.
+ Clean up isearch-search considerably.
+ isearch-message computes message in lower case,
+ then case-converts the first char.
+
+ * loaddefs.el: New variable search-last-regexp;
+ default string for isearch-regexp.
+ Rename isearch-... vars to search-...
+
+ * simple.el (next-line, kill-line):
+ * lisp.el (end-of-defun):
+ * picture.el (Picture-clear-line):
+ * replace.el (keep-lines):
+ * indent.el (indent-relative):
+ Use forward-line, not scan-buffer.
+ * fill.el (justify-current-line): Use search-backward
+ not scan-buffer to check whether the line has a space in it.
+
+ * files.el (set-visited-file-name):
+ Rename the auto-save file if appropriate.
+ (make-auto-save-file-name, auto-save-file-name-p):
+ Auto save file for foo is now #foo#.
+ (make-backup-file-name, backup-file-name-p):
+ New functions, used in appropriate places.
+
+ * dired.el (dired-flag-backup-files):
+ Use backup-file-name-p.
+
+ * sendmail.el (mail-mode):
+ Fix documentation of key bindings.
+
+Fri Aug 15 14:45:40 1986 Richard Mlynarik (mly at prep)
+
+ * man.el (manual-entry)
+ Compensate for Sun wankerism.
+ If would be nice if there were something a little
+ more fine-grained than `system-type' for testing for
+ these cases...
+
+Fri Aug 15 04:11:01 1986 Richard M. Stallman (rms at prep)
+
+ * startup.el (command-line): No longer necessary to set
+ ctl-arrow from default-ctl-arrow, etc., after init file is run
+ due to changed behavior of those variables.
+
+ * info.el (Info-edit):
+ * rmailedit.el (rmail-edit-mode):
+ Change default-mode-line-format to (default-value 'mode-line-format).
+
+Thu Aug 14 16:17:20 1986 Richard Mlynarik (mly at prep)
+
+ * man.el (manual-entry):
+ Speed up `\b'-hacking.
+
+Thu Aug 14 01:08:32 1986 Richard M. Stallman (rms at prep)
+
+ * sendmail.el: Change key bindings.
+ C-c <letter> becomes C-c C-<letter> or C-c C-f <letter>.
+
+ * mh-e.el (mh-position-on-field):
+ mh-header-end -> mh-goto-header-end.
+
+ * novice.el (disabled-command-hook):
+ Print only the first paragraph of the command's documentation.
+ [Test this, once new narrow-to-region doc is installed.]
+
+ * rmailsum.el (rmail-make-basic-summary-line):
+ Don't accept a time zone as a month.
+
+Wed Aug 13 02:01:59 1986 Richard M. Stallman (rms at prep)
+
+ * mh-e.el: New version 3.3i, moving mode-specific commands
+ to C-c prefix.
+
+ * tex-mode.el: many new features incl. LaTeX mode
+ and some C-c commands.
+
+ * indent.el (indent-relative):
+ Fix lossage if point to indent under was inside a tab.
+
+ * bytecomp.el (byte-compile-substring):
+ Fix dumb error.
+
+ * info.el: Autoload Info-validate. Fix bug in autoload Info-tagify.
+
+Tue Aug 12 11:30:53 1986 Richard Mlynarik (mly at prep)
+
+ * rmailedit.el (rmail-cease-edit, rmail-attributes)
+ Add label (well, `attribute,' really) "edited" to message.
+
+ * mlsupport.el (auto-execute)
+ Fix from bap@g.cs.cmu.edu
+
+Mon Aug 11 10:36:51 1986 Richard Mlynarik (mly at prep)
+
+ * bytecomp.el (byte-compile-form)
+ Compile references to t and nil as constants rather then variable
+ references.
+
+ * bytecomp.el (byte-compile-no-args, ..., byte-compile-three-args)
+ If called with wrong-number-of-args, do a normal function call
+ and get an error at runtime.
+
+ * bytecomp.el (byte-compile-file-form)
+ Process (require ...) at compile-time
+
+ * informat.el, info.el, loaddefs.el
+ Move Info-validate and friends into new file informat.el
+ Add batch-info-validate
+
+ * texinfmt.el, loaddefs.el
+ Add batch-texinfo-format
+
+ * startup.el
+ Add synonym switches "-funcall" "-load" "-user" "-no-init-file"
+ for cryptic "-f" "-l" "-u" "-q"
+
+ * mlsupport.el
+ Make various turds know that inhibit-command-line has gone.
+
+ * bytecomp.el (batch-byte-compile), tex-start.el
+ Because of RMS's change "Mon Jul 7 14:01:51 1986"
+ must use variable command-line-args-left rather than command-line-args.
+
+ Actually, I see no circumstances under which a switch -could- be
+ interested in any command-line-args before the mention of itself,
+ and so think that rebinding command-line-args as appropriate was
+ correct (if perhaps a little confusing to the person who requested
+ that RMS' change be made)
+
+Sun Aug 10 08:02:19 1986 Richard Mlynarik (mly at prep)
+
+ * info.el (Info-validate)
+ re-search for \\*, not *
+
+Thu Aug 7 10:24:21 1986 Richard Mlynarik (mly at prep)
+
+ * rfc822.el, loaddefs.el, mail-utils.el
+ Hairy address parser, used only if mail-use-rfc822 is non-nil
+ (It is nil by default, so if one doesn't like or need the hair of
+ this file, then one is never troubled by it)
+
+ * disassemble.el, loaddefs.el
+ Code from doug@csli.stanford.edu modified by mly.
+ RMS -- if this is too random to be in the GNU Emacs
+ distribution, please tell me so.
+
+ * bytecomp.el
+ Compile eql same as eq.
+
+Wed Jul 30 22:03:02 1986 Richard M. Stallman (rms at prep)
+
+ * outline.el (many functions):
+ New variable outline-regexp controls what is a heading line.
+ It must match at the beginning of a line. Length of matched text
+ gives the depth of heading within the tree.
+
+ * term/xterm.el (x-get-default-args):
+ Process reversevideo option just once. (Twice is noop.)
+
+Mon Jul 28 20:24:18 1986 Richard M. Stallman (rms at prep)
+
+ * term/vt100.el, term/vt200.el:
+ Move (require 'keypad) to top to avoid error.
+
+Fri Jul 18 14:26:00 1986 Leonard H. Tower Jr. (tower at prep)
+
+ * rnews.el: (news-add-news-group)
+ handle unsubscribed groups better
+
+ * rnews.el: (news-{next,previous}-group)
+ now skip groups with no new messages
+
+Thu Jul 17 19:06:59 1986 Richard M. Stallman (rms at prep)
+
+ * mh-e.el: Install version 3.3h from Larus.
+
+Tue Jul 15 17:35:34 1986 Richard M. Stallman (rms at prep)
+
+ * shell.el (shell-send-input):
+ If get error trying to change directory, call
+ shell-set-directory-error-hook with no args.
+
+Sat Jul 12 00:12:37 1986 Richard M. Stallman (rms at prep)
+
+ * tags.el (list-tags, tags-apropos): Call output buffer *Tags List*.
+
+ * c-mode.el (calculate-c-indent):
+ Better handling of case where first statement at current level
+ starts on same line as a case..: or label. New local var
+ colon-line-end.
+
+Mon Jul 7 14:01:51 1986 Richard M. Stallman (rms at prep)
+
+ * startup.el (command-line-1): rename argument variable
+ command-line-args to command-line-args-left. Don't rebind
+ command-line-args.
+
+Sat Jun 21 01:11:23 1986 Richard M. Stallman (rms at prep)
+
+ * mh-e.el: Version 3.3g from Larus.
+
+Thu Jun 19 12:35:17 1986 Richard M. Stallman (rms at prep)
+
+ * isearch.el (isearch): Use slow terminal mode
+ only if current window is > 4 times the slow-terminal lines high.
+
+Tue Jun 17 05:37:59 1986 Richard M. Stallman (rms at prep)
+
+ * nroff-mode.el: Add elements to nrofff-brace-table.
+
+Mon Jun 16 06:30:54 1986 Richard M. Stallman (rms at prep)
+
+ * mlconvert.el (convert-mocklisp-buffer):
+ Proper handling of `!' function, via new function ml-not.
+ Proper handling of non-defuns, by putting them inside a
+ dummy defun and calling that function.
+
+Sat Jun 14 22:05:58 1986 Richard M. Stallman (rms at prep)
+
+ * mh-e.el : Install 3.3f from Larus.
+
+Thu Jun 12 02:47:11 1986 Richard M. Stallman (rms at prep)
+
+ * startup.el (command-line):
+ Rename default init file to default.el.
+ Don't look for suffixes on .emacs file.
+
+ * keypad.el: New file that defines a standard keypad mode.
+ * term/vt*.el: Rewrite completely to use keypad.el.
+
+Wed Jun 11 16:43:27 1986 Richard M. Stallman (rms at prep)
+
+ * abbrev.el (abbrev-prefix-mark):
+ Insert a - at the beginning of the abbrev.
+ expand-abbrev will now delete such -'s.
+
+ * userlock.el (ask-user-about-supercession):
+ Ask user what to do if he is modifying a buffer whose
+ file is changed on disk.
+
+Tue Jun 10 04:54:33 1986 Richard M. Stallman (rms at prep)
+
+ * rmail.el (rmail-reply): For the in-reply-to,
+ try to get the sender's full name from within parentheses.
+
+ * outline.el: pervasive changes; new features, changed keys.
+
+ * files.el (backup-bufer):
+ If cannot write backup under normal name, write it in ~/%backup%.
+ Preserve the last-modified time when backing up by copying.
+
+Mon Jun 9 00:00:24 1986 Richard M. Stallman (rms at prep)
+
+ * rmail.el (rmail-expunge): Preserve point unless expunging
+ the current message.
+
+ * bytecomp.el (file-newer-than-file-p):
+ Since this is a primitive in version 18, define it
+ only if not defined.
+
+Sun Jun 8 09:43:02 1986 Richard M. Stallman (rms at prep)
+
+ * files.el (load-file, load-library): two new commands.
+
+ * startup.el (command-line): Eliminate inhibit-command-line
+ since one can just set command-line-args to nil.
+
+ * term/xterm.el: No need to handle -d switch
+ since main() handles it now.
+
+ * tags.el: Display name of file being processed.
+
+ * mh-e.el: Install version 3.3 from Larus.
+
+ * replace.el, loaddefs.el (perform-replace):
+ perform-replace does not print "done"; its callers do.
+
+ * startup.el (command-line):
+ Rename file default-profile to .emacs-df;
+ load it always, unless inhibit-default-init is set to t.
+
+ * telnet.el: Switch to C-c prefix for mode-specific commands.
+
+ * startup.el (command-line): Use just first word of
+ terminal name to make per-terminal library file name.
+
+ * loadup.el: Change name of installed docstr file to
+ DOC-mm.nn.oo from DOC.mm.nn.oo.
+
+ * files.el (file-name-sans-versions): New system-dependent
+ function to remove backup or version suffixes from filename.
+
+Sat Jun 7 16:04:07 1986 Richard M. Stallman (rms at prep)
+
+ * c-mode.el (electric-c-terminator):
+ Check for point being inside a multi-line string or comment
+ and do nothing. For colon, check for more than one word
+ before it on the line (with first one not "case") and do nothing.
+
+ * c-mode.el: Don't rebind Linefeed.
+
+ * c-mode.el (calculate-c-indent):
+ If previous line ends in ") {", skip back to matching "("
+ and use that line's indentation as the brace's column.
+
+Fri Jun 6 00:12:48 1986 Richard M. Stallman (rms at prep)
+
+ * nroff-mode.el (nroff-comment-indent, nroff-mode):
+ Define a comment syntax. Install comment-indenter
+ as supplied by gildea, but change it not to use
+ insert-before-markers, to avoid display anomalies.
+
+ * files.el (find-file-noselect): Tell revert-buffer not to query.
+ * files.el (revert-buffer): Second arg non-nil means no query.
+
+ * files.el (after-find-file): Warn if auto-save file
+ exists and is newer than the file visited.
+
+ * files.el (find-alternate-file):
+ Allow replacing a non-file buffer, as long as not modified.
+
+ * files.el (recover-file):
+ Initially show a directory listing of real and auto-save files.
+ Only find the file if user says yes.
+ Print better messages.
+
+ * simple.el (goto-line): Use new interactive code N.
+
+ * subr.el (substitute-key-definition): New function.
+ Replaces all bindings to one function in one map
+ with another function.
+
+ * xterm.el: Use substitute-key-definition to get rid of keys
+ that do suspend-emacs.
+
+Thu Jun 5 00:25:52 1986 Richard M. Stallman (rms at prep)
+
+ * simple.el (fundamental-mode):
+ Provide a fundamental-mode-map in case user does local-set-key.
+
+ * picture.el (picture-mode):
+ New key bindings for setting insert motion direction:
+ C-c <, C-c >, C-c ^ and C-c . instead of M- chars.
+
+ * rmail.el (rmail-reply): When putting From into In-reply-to,
+ stop at any newline.
+
+ * mail-utils.el (mail-strip-quoted-names):
+ Consider newlines like other whitespace for <...> hacks.
+
+ * bytecomp.el (byte-compile-cond{,-1}):
+ Handling of singleton clauses that are not last.
+ Handling of cond with no clauses.
+
+ * startup.el (command-line): Switch to *scratch* before
+ running initial-major-mode, and do this only if *scratch* exists.
+
+ * compare-w.el: Simplify the handling of `size':
+ always reduce size not to exceed the amount of space
+ left in either buffer.
+
+Wed Jun 4 21:44:40 1986 Richard M. Stallman (rms at prep)
+
+ * man.el (manual-entry): Use new variables manual-program,
+ manual-formatted-dir-prefix and manual-formatted-dirlist,
+ defined in paths.el.
+
+ * time.el (display-time):
+ Don't expand-file-name of "loadst". Let start-process search
+ the exec-path for it.
+
+ * texinfmt.el (texinfo-discard-line):
+ Allow and discard spaces at end of line.
+
+ * texinfo.el:
+ Split most of this into new file texinfmt.el.
+
+ * replace.el (perform-replace):
+ Bind help-form only while the read-char is done;
+ don't interfere with recursive edits.
+
+Thu May 29 19:05:19 1986 Richard M. Stallman (rms at prep)
+
+ * info.el (Info-validate): If file is valid,
+ erase the buffer of problems found previously.
+ Non-re search was used by mistake to search for regexps; fix.
+
+ * nroff-mode.el (electric-nroff-newline):
+ Leave point between the open-directive and the close-directive,
+ as it was supposed to do.
+ Add some directive-pairs to nroff-brace-table.
+
+Wed May 28 03:56:04 1986 Richard M. Stallman (rms at prep)
+
+ * telnet.el (telnet-initial-filter):
+ If host nonexistent, kill the telnet buffer and get error.
+
+Sun May 25 20:00:21 1986 Richard M. Stallman (rms at prep)
+
+ * rmail.el (rmail-search): Don't find a match in the current message.
+
+Mon May 19 22:11:52 1986 Richard M. Stallman (rms at prep)
+
+ * mh-e.el (mh-get-new-mail): Handle error messages reeived from `inc'.
+
+Thu May 15 18:35:25 1986 Richard M. Stallman (rms at prep)
+
+ * files.el (save-buffer): Switch meanings of one-C-u and two-C-u
+ in the code, so they match the documentation.
diff --git a/lisp/abbrev.el b/lisp/abbrev.el
new file mode 100644
index 00000000000..a8d525e0ec9
--- /dev/null
+++ b/lisp/abbrev.el
@@ -0,0 +1,269 @@
+;; Abbrev mode commands for Emacs
+
+;; Copyright (C) 1985, 1986 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 1, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+(defun abbrev-mode (arg)
+ "Toggle abbrev mode.
+With arg, turn abbrev mode on iff arg is positive.
+In abbrev mode, inserting an abbreviation causes it to expand
+and be replaced by its expansion."
+ (interactive "P")
+ (setq abbrev-mode
+ (if (null arg) (not abbrev-mode)
+ (> (prefix-numeric-value arg) 0)))
+ (set-buffer-modified-p (buffer-modified-p))) ;No-op, but updates mode line.
+
+(defvar edit-abbrevs-map nil
+ "Keymap used in edit-abbrevs.")
+(if edit-abbrevs-map
+ nil
+ (setq edit-abbrevs-map (make-sparse-keymap))
+ (define-key edit-abbrevs-map "\C-x\C-s" 'edit-abbrevs-redefine)
+ (define-key edit-abbrevs-map "\C-c\C-c" 'edit-abbrevs-redefine))
+
+(defun kill-all-abbrevs ()
+ "Undefine all defined abbrevs."
+ (interactive)
+ (let ((tables abbrev-table-name-list))
+ (while tables
+ (clear-abbrev-table (symbol-value (car tables)))
+ (setq tables (cdr tables)))))
+
+(defun insert-abbrevs ()
+ "Insert after point a description of all defined abbrevs.
+Mark is set after the inserted text."
+ (interactive)
+ (push-mark
+ (save-excursion
+ (let ((tables abbrev-table-name-list))
+ (while tables
+ (insert-abbrev-table-description (car tables) t)
+ (setq tables (cdr tables))))
+ (point))))
+
+(defun list-abbrevs ()
+ "Display a list of all defined abbrevs."
+ (interactive)
+ (display-buffer (prepare-abbrev-list-buffer)))
+
+(defun prepare-abbrev-list-buffer ()
+ (save-excursion
+ (set-buffer (get-buffer-create "*Abbrevs*"))
+ (erase-buffer)
+ (let ((tables abbrev-table-name-list))
+ (while tables
+ (insert-abbrev-table-description (car tables) t)
+ (setq tables (cdr tables))))
+ (goto-char (point-min))
+ (set-buffer-modified-p nil)
+ (edit-abbrevs-mode))
+ (get-buffer-create "*Abbrevs*"))
+
+(defun edit-abbrevs-mode ()
+ "Major mode for editing the list of abbrev definitions.
+\\{edit-abbrevs-map}"
+ (interactive)
+ (setq major-mode 'edit-abbrevs-mode)
+ (setq mode-name "Edit-Abbrevs")
+ (use-local-map edit-abbrevs-map))
+
+(defun edit-abbrevs ()
+ "Alter abbrev definitions by editing a list of them.
+Selects a buffer containing a list of abbrev definitions.
+You can edit them and type C-c C-c to redefine abbrevs
+according to your editing.
+Buffer contains a header line for each abbrev table,
+ which is the abbrev table name in parentheses.
+This is followed by one line per abbrev in that table:
+NAME USECOUNT EXPANSION HOOK
+where NAME and EXPANSION are strings with quotes,
+USECOUNT is an integer, and HOOK is any valid function
+or may be omitted (it is usually omitted)."
+ (interactive)
+ (switch-to-buffer (prepare-abbrev-list-buffer)))
+
+(defun edit-abbrevs-redefine ()
+ "Redefine abbrevs according to current buffer contents."
+ (interactive)
+ (define-abbrevs t)
+ (set-buffer-modified-p nil))
+
+(defun define-abbrevs (&optional arg)
+ "Define abbrevs according to current visible buffer contents.
+See documentation of edit-abbrevs for info on the format of the
+text you must have in the buffer.
+With argument, eliminate all abbrev definitions except
+the ones defined from the buffer now."
+ (interactive "P")
+ (if arg (kill-all-abbrevs))
+ (save-excursion
+ (goto-char (point-min))
+ (while (and (not (eobp)) (re-search-forward "^(" nil t))
+ (let* ((buf (current-buffer))
+ (table (read buf))
+ abbrevs)
+ (forward-line 1)
+ (while (progn (forward-line 1)
+ (not (eolp)))
+ (setq name (read buf) count (read buf) exp (read buf))
+ (skip-chars-backward " \t\n\f")
+ (setq hook (if (not (eolp)) (read buf)))
+ (skip-chars-backward " \t\n\f")
+ (setq abbrevs (cons (list name exp hook count) abbrevs)))
+ (define-abbrev-table table abbrevs)))))
+
+(defun read-abbrev-file (file &optional quietly)
+ "Read abbrev definitions from file written with write-abbrev-file.
+Takes file name as argument.
+Optional second argument non-nil means don't print anything."
+ (interactive "fRead abbrev file: ")
+ (load (if (and file (> (length file) 0)) file abbrev-file-name)
+ nil quietly)
+ (setq save-abbrevs t abbrevs-changed nil))
+
+(defun quietly-read-abbrev-file (file)
+ "Read abbrev definitions from file written with write-abbrev-file.
+Takes file name as argument. Does not print anything."
+ ;(interactive "fRead abbrev file: ")
+ (read-abbrev-file file t))
+
+(defun write-abbrev-file (file)
+ "Write all abbrev definitions to file of Lisp code.
+The file can be loaded to define the same abbrevs."
+ (interactive "FWrite abbrev file: ")
+ (or (and file (> (length file) 0))
+ (setq file abbrev-file-name))
+ (save-excursion
+ (set-buffer (get-buffer-create " write-abbrev-file"))
+ (erase-buffer)
+ (let ((tables abbrev-table-name-list))
+ (while tables
+ (insert-abbrev-table-description (car tables) nil)
+ (setq tables (cdr tables))))
+ (write-region 1 (point-max) file)
+ (erase-buffer)))
+
+(defun add-mode-abbrev (arg)
+ "Define mode-specific abbrev for last word(s) before point.
+Argument is how many words before point form the expansion;
+or zero means the region is the expansion.
+A negative argument means to undefine the specified abbrev.
+Reads the abbreviation in the minibuffer."
+ (interactive "p")
+ (add-abbrev
+ (if only-global-abbrevs
+ global-abbrev-table
+ (or local-abbrev-table
+ (error "No per-mode abbrev table.")))
+ "Mode" arg))
+
+(defun add-global-abbrev (arg)
+ "Define global (all modes) abbrev for last word(s) before point.
+Argument is how many words before point form the expansion;
+or zero means the region is the expansion.
+A negative argument means to undefine the specified abbrev.
+Reads the abbreviation in the minibuffer."
+ (interactive "p")
+ (add-abbrev global-abbrev-table "Global" arg))
+
+(defun add-abbrev (table type arg)
+ (let ((exp (and (>= arg 0)
+ (buffer-substring
+ (point)
+ (if (= arg 0) (mark)
+ (save-excursion (forward-word (- arg)) (point))))))
+ name)
+ (setq name (read-string (format "%s abbrev for \"%s\": "
+ type exp)))
+ (if (or (null exp)
+ (not (abbrev-expansion name table))
+ (y-or-n-p (format "%s expands to \"%s\"; redefine? "
+ name (abbrev-expansion name table))))
+ (define-abbrev table (downcase name) exp))))
+
+(defun inverse-add-mode-abbrev (arg)
+ "Define last word before point as a mode-specific abbrev.
+With argument N, defines the Nth word before point.
+Reads the expansion in the minibuffer.
+Expands the abbreviation after defining it."
+ (interactive "p")
+ (inverse-add-abbrev
+ (if only-global-abbrevs
+ global-abbrev-table
+ (or local-abbrev-table
+ (error "No per-mode abbrev table.")))
+ "Mode" arg))
+
+(defun inverse-add-global-abbrev (arg)
+ "Define last word before point as a global (mode-independent) abbrev.
+With argument N, defines the Nth word before point.
+Reads the expansion in the minibuffer.
+Expands the abbreviation after defining it."
+ (interactive "p")
+ (inverse-add-abbrev global-abbrev-table "Global" arg))
+
+(defun inverse-add-abbrev (table type arg)
+ (let (name nameloc exp)
+ (save-excursion
+ (forward-word (- arg))
+ (setq name (buffer-substring (point) (progn (forward-word 1)
+ (setq nameloc (point))))))
+ (setq exp (read-string (format "%s expansion for \"%s\": "
+ type name)))
+ (if (or (not (abbrev-expansion name table))
+ (y-or-n-p (format "%s expands to \"%s\"; redefine? "
+ name (abbrev-expansion name table))))
+ (progn
+ (define-abbrev table (downcase name) exp)
+ (save-excursion
+ (goto-char nameloc)
+ (expand-abbrev))))))
+
+(defun abbrev-prefix-mark (&optional arg)
+ "Mark current point as the beginning of an abbrev.
+Abbrev to be expanded starts here rather than at
+beginning of word. This way, you can expand an abbrev
+with a prefix: insert the prefix, use this command,
+then insert the abbrev."
+ (interactive "P")
+ (or arg (expand-abbrev))
+ (setq abbrev-start-location (point-marker)
+ abbrev-start-location-buffer (current-buffer))
+ (insert "-"))
+
+(defun expand-region-abbrevs (start end &optional noquery)
+ "For abbrev occurrence in the region, offer to expand it.
+The user is asked to type y or n for each occurrence.
+A numeric argument means don't query; expand all abbrevs.
+Calling from a program, arguments are START END &optional NOQUERY."
+ (interactive "r")
+ (save-excursion
+ (goto-char (min start end))
+ (let ((lim (- (point-max) (max start end))))
+ (while (and (not (eobp))
+ (progn (forward-word 1)
+ (<= (point) (- (point-max) lim))))
+ (let ((modp (buffer-modified-p)))
+ (if (expand-abbrev)
+ (progn
+ (set-buffer-modified-p modp)
+ (unexpand-abbrev)
+ (if (or noquery (y-or-n-p "Expand this? "))
+ (expand-abbrev)))))))))
diff --git a/lisp/abbrev.elc b/lisp/abbrev.elc
new file mode 100644
index 00000000000..1bbca206bce
--- /dev/null
+++ b/lisp/abbrev.elc
Binary files differ
diff --git a/lisp/abbrevlist.el b/lisp/abbrevlist.el
index 554bacd645f..15b842c6cb6 100644
--- a/lisp/abbrevlist.el
+++ b/lisp/abbrevlist.el
@@ -22,7 +22,7 @@
(provide 'abbrevlist)
(defun list-one-abbrev-table (abbrev-table output-buffer)
- "Display alphabetical listing of ABBREV-TABLE in buffer OUTPUT-BUFFER."
+ "Display alphabetical listing of ABBREV-TABLE in buffer BUFFER."
(with-output-to-temp-buffer output-buffer
(save-excursion
(let ((abbrev-list nil) (first-column 0))
diff --git a/lisp/abbrevlist.elc b/lisp/abbrevlist.elc
new file mode 100644
index 00000000000..22267e91da0
--- /dev/null
+++ b/lisp/abbrevlist.elc
Binary files differ
diff --git a/lisp/ada.el b/lisp/ada.el
index 22c80707b42..6b99beb3fbb 100644
--- a/lisp/ada.el
+++ b/lisp/ada.el
@@ -3,23 +3,6 @@
; (borrows heavily from Mick Jordan's Modula-2 package for GNU,
; as modified by Peter Robinson, Michael Schmidt, and Tom Perrine.)
-;; Copyright (C) 1985, 1986, 1987 Free Software Foundation, Inc.
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 1, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
(setq auto-mode-alist (cons (cons "\\.ada$" 'ada-mode) auto-mode-alist))
@@ -106,30 +89,33 @@
Most control constructs and declarations of Ada can be inserted in the buffer
by typing Control-C followed by a character mnemonic for the construct.
-\\<ada-mode-map>\\[ada-array] array \\[ada-exception-block] exception block
-\\[ada-exception] exception \\[ada-declare-block] declare block
-\\[ada-package-spec] package spec \\[ada-package-body] package body
-\\[ada-procedure-spec] procedure spec \\[ada-subprogram-body] proc/func body
-\\[ada-function-spec] func spec \\[ada-for-loop] for loop
- \\[ada-if] if
- \\[ada-elsif] elsif
- \\[ada-else] else
-\\[ada-private] private \\[ada-loop] loop
-\\[ada-record] record \\[ada-case] case
-\\[ada-subtype] subtype \\[ada-separate] separate
-\\[ada-type] type \\[ada-tabsize] tab spacing for indents
-\\[ada-when] when \\[ada-while] while
- \\[ada-exit] exit
-\\[ada-paired-parens] paired parens \\[ada-inline-comment] inline comment
- \\[ada-header] header spec
-\\[ada-compile] compile \\[ada-bind] bind
-\\[ada-find-listing] find error list
-\\[ada-library-name] name library \\[ada-options-for-bind] options for bind
-
-\\[ada-backward-to-same-indent] and \\[ada-forward-to-same-indent] move backward and forward respectively to the next line
+C-c C-a array C-c b exception block
+C-c C-e exception C-c d declare block
+C-c C-k package spec C-c k package body
+C-c C-p procedure spec C-c p proc/func body
+C-c C-f func spec C-c f for loop
+ C-c i if
+ C-c I elsif
+ C-c e else
+C-c C-v private C-c l loop
+C-c C-r record C-c c case
+C-c C-s subtype C-c s separate
+C-c C-t type C-c t tab spacing for indents
+C-c C-w when C-c w while
+ C-c x exit
+C-c ( paired parens C-c - inline comment
+ C-c h header sec
+C-c C compile C-c B bind
+C-c E find error list
+C-c L name library C-c O options for bind
+
+C-c < and C-c > move backward and forward respectively to the next line
having the same (or lesser) level of indentation.
-Variable `ada-indent' controls the number of spaces for indent/undent."
+Variable ada-indent controls the number of spaces for indent/undent.
+
+\\{ada-mode-map}
+"
(interactive)
(kill-all-local-variables)
(use-local-map ada-mode-map)
@@ -153,7 +139,7 @@ Variable `ada-indent' controls the number of spaces for indent/undent."
(make-local-variable 'comment-start)
(setq comment-start "--")
(make-local-variable 'comment-end)
- (setq comment-end "")
+ (setq comment-end "\n")
(make-local-variable 'comment-column)
(setq comment-column 41)
(make-local-variable 'comment-start-skip)
@@ -165,9 +151,8 @@ Variable `ada-indent' controls the number of spaces for indent/undent."
(run-hooks 'ada-mode-hook))
(defun ada-tabsize (s)
- "Changes spacing used for indentation.
-The prefix argument is used as the new spacing."
- (interactive "p")
+ "changes spacing used for indentation. Reads spacing from minibuffer."
+ (interactive "nnew indentation spacing: ")
(setq ada-indent s))
(defun ada-newline ()
@@ -188,9 +173,9 @@ The prefix argument is used as the new spacing."
(backward-delete-char-untabify ada-indent nil))
(defun ada-go-to-this-indent (step indent-level)
- "Move point repeatedly by STEP lines until the current line has
-given INDENT-LEVEL or less, or the start or end of the buffer is reached.
-Ignore blank lines, statement labels and block or loop names."
+ "Move point repeatedly by <step> lines till the current line
+has given indent-level or less, or the start/end of the buffer is hit.
+Ignore blank lines, statement labels, block/loop names."
(while (and
(zerop (forward-line step))
(or (looking-at "^[ ]*$")
@@ -202,21 +187,21 @@ Ignore blank lines, statement labels and block or loop names."
(defun ada-backward-to-same-indent ()
"Move point backwards to nearest line with same indentation or less.
-If not found, point is left at the top of the buffer."
+If not found, point is left at top of buffer."
(interactive)
(ada-go-to-this-indent -1 (current-indentation))
(back-to-indentation))
(defun ada-forward-to-same-indent ()
"Move point forwards to nearest line with same indentation or less.
-If not found, point is left at the start of the last line in the buffer."
+If not found, point is left at start of last line in buffer."
(interactive)
(ada-go-to-this-indent 1 (current-indentation))
(back-to-indentation))
(defun ada-array ()
- "Insert array type definition. Uses the minibuffer to prompt
-for component type and index subtypes."
+ "Insert array type definition, prompting for component type,
+leaving the user to type in the index subtypes."
(interactive)
(insert "array ()")
(backward-char)
@@ -228,9 +213,8 @@ for component type and index subtypes."
(end-of-line))
(defun ada-case ()
- "Build skeleton case statement.
-Uses the minibuffer to prompt for the selector expression.
-Also builds the first when clause."
+ "Build skeleton case statment, prompting for the selector expression.
+starts up the first when clause, too."
(interactive)
(insert "case ")
(insert (read-string "selector expression: ") " is")
@@ -243,59 +227,57 @@ Also builds the first when clause."
(ada-when))
(defun ada-declare-block ()
- "Insert a block with a declare part.
-Indent for the first declaration."
+ "Insert a block with a declare part and indent for the 1st declaration."
(interactive)
(let ((ada-block-name (read-string "[block name]: ")))
(insert "declare")
(cond
- ( (not (string-equal ada-block-name ""))
- (beginning-of-line)
- (open-line 1)
- (insert ada-block-name ":")
- (next-line 1)
- (end-of-line)))
+ ( (not (string-equal ada-block-name ""))
+ (beginning-of-line)
+ (open-line 1)
+ (insert ada-block-name ":")
+ (next-line 1)
+ (end-of-line)))
(ada-newline)
(ada-newline)
(insert "begin")
(ada-newline)
(ada-newline)
(if (string-equal ada-block-name "")
- (insert "end;")
+ (insert "end;")
(insert "end " ada-block-name ";"))
- )
+ )
(end-of-line -2)
(ada-tab))
(defun ada-exception-block ()
- "Insert a block with an exception part.
-Indent for the first line of code."
+ "Insert a block with an exception part and indent for the 1st line of code."
(interactive)
(let ((block-name (read-string "[block name]: ")))
(insert "begin")
(cond
- ( (not (string-equal block-name ""))
- (beginning-of-line)
- (open-line 1)
- (insert block-name ":")
- (next-line 1)
- (end-of-line)))
+ ( (not (string-equal block-name ""))
+ (beginning-of-line)
+ (open-line 1)
+ (insert block-name ":")
+ (next-line 1)
+ (end-of-line)))
(ada-newline)
(ada-newline)
(insert "exception")
(ada-newline)
(ada-newline)
(cond
- ( (string-equal block-name "")
- (insert "end;"))
- ( t
- (insert "end " block-name ";")))
- )
+ ( (string-equal block-name "")
+ (insert "end;"))
+ ( t
+ (insert "end " block-name ";")))
+ )
(end-of-line -2)
(ada-tab))
(defun ada-exception ()
- "Insert an indented exception part into a block."
+ "Undent and insert an exception part into a block. Reindent."
(interactive)
(ada-untab)
(insert "exception")
@@ -385,7 +367,7 @@ Indent for the first line of code."
(ada-tab))
(defun ada-loop ()
- "Insert a skeleton loop statement. exit statement added by hand."
+ "insert a skeleton loop statement. exit statement added by hand."
(interactive)
(insert "loop ")
(let* ((ada-loop-name (read-string "[loop name]: "))
@@ -440,10 +422,10 @@ Indent for the first line of code."
(ada-tab))
(defun ada-get-arg-list ()
- "Read from the user a procedure or function argument list.
+ "Read from user a procedure or function argument list.
Add parens unless arguments absent, and insert into buffer.
-Individual arguments are arranged vertically if entered one at a time.
-Arguments ending with `;' are presumed single and stacked."
+Individual arguments are arranged vertically if entered one-at-a-time.
+Arguments ending with ';' are presumed single and stacked."
(insert " (")
(let ((ada-arg-indent (current-column))
(ada-args (read-string "[arguments]: ")))
@@ -474,9 +456,9 @@ Arguments ending with `;' are presumed single and stacked."
(ada-get-arg-list))
(defun get-ada-subprogram-name ()
- "Return (without moving point or mark) a pair whose CAR is the name of
-the function or procedure whose spec immediately precedes point, and whose
-CDR is the column number where the procedure/function keyword was found."
+ "Return (without moving point or mark) a pair whose CAR is
+the name of the function or procedure whose spec immediately precedes point,
+and whose CDR is the column nbr the procedure/function keyword was found at."
(save-excursion
(let ((ada-proc-indent 0))
(if (re-search-backward
@@ -495,7 +477,7 @@ CDR is the column number where the procedure/function keyword was found."
(defun ada-subprogram-body ()
"Insert frame for subprogram body.
-Invoke right after `ada-function-spec' or `ada-procedure-spec'."
+Invoke right after ada-function-spec or ada-procedure-spec."
(interactive)
(insert " is")
(let ((ada-subprogram-name-col (get-ada-subprogram-name)))
@@ -510,7 +492,7 @@ Invoke right after `ada-function-spec' or `ada-procedure-spec'."
(ada-tab))
(defun ada-separate ()
- "Finish a body stub with `is separate'."
+ "Finish a body stub with 'is separate'."
(interactive)
(insert " is")
(ada-newline)
@@ -586,9 +568,8 @@ Invoke right after `ada-function-spec' or `ada-procedure-spec'."
(backward-char))
(defun ada-inline-comment ()
- "Start a comment after the end of the line, indented at least
-`comment-column' spaces. If starting after `end-comment-column',
-start a new line."
+ "Start a comment after the end of the line, indented at least COMMENT-COLUMN.
+If starting after END-COMMENT-COLUMN, start a new line."
(interactive)
(end-of-line)
(if (> (current-column) end-comment-column) (newline))
@@ -596,30 +577,30 @@ start a new line."
(insert " -- "))
(defun ada-display-comment ()
-"Inserts three comment lines, making a display comment."
+"Inserts 3 comment lines, making a display comment."
(interactive)
(insert "--\n-- \n--")
(end-of-line 0))
;; Much of this is specific to Ada-Ed
-(defvar ada-lib-dir-name "lib" "*Current Ada program library directory.")
+(defvar ada-lib-dir-name "lib" "*Current ada program library directory.")
(defvar ada-bind-opts "" "*Options to supply for binding.")
(defun ada-library-name (ada-lib-name)
- "Specify name of Ada library directory for later compilations."
- (interactive "DName of Ada library directory: ")
+ "Specify name of ada library directory for later compilations."
+ (interactive "Dname of ada library directory: ")
(setq ada-lib-dir-name ada-lib-name))
(defun ada-options-for-bind ()
- "Specify options, such as -m and -i, needed for `ada-bind'."
- (setq ada-bind-opts (read-string "-m and -i options for `ada-bind': ")))
+ "Specify options, such as -m and -i, needed for adabind."
+ (setq ada-bind-opts (read-string "-m and -i options for adabind: ")))
-(defun ada-compile (arg)
+(defun ada-compile (ada-prefix-arg)
"Save the current buffer and compile it into the current program library.
Initialize the library if a prefix arg is given."
(interactive "P")
- (let* ((ada-init (if (null arg) "" "-n "))
+ (let* ((ada-init (if (null ada-prefix-arg) "" "-n "))
(ada-source-file (buffer-name)))
(compile
(concat "adacomp " ada-init "-l " ada-lib-dir-name " " ada-source-file))))
diff --git a/lisp/ada.elc b/lisp/ada.elc
new file mode 100644
index 00000000000..74c3ddac0c4
--- /dev/null
+++ b/lisp/ada.elc
Binary files differ
diff --git a/lisp/add-log.el b/lisp/add-log.el
new file mode 100644
index 00000000000..74dc3127c26
--- /dev/null
+++ b/lisp/add-log.el
@@ -0,0 +1,87 @@
+;; Change log maintenance commands for Emacs
+;; Copyright (C) 1985 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 1, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+(defun add-change-log-entry (whoami file-name &optional other-window)
+ "Find change log file and add an entry for today.
+First arg (interactive prefix) non-nil means prompt for user name and site.
+Second arg is file name of change log.
+Optional third arg OTHER-WINDOW non-nil means visit in other window."
+ (interactive
+ (list current-prefix-arg
+ (let ((default
+ (if (eq system-type 'vax-vms) "$CHANGE_LOG$.TXT" "ChangeLog")))
+ (expand-file-name
+ (read-file-name (format "Log file (default %s): " default)
+ nil default)))))
+ (let* ((default
+ (if (eq system-type 'vax-vms) "$CHANGE_LOG$.TXT" "ChangeLog"))
+ (full-name (if whoami
+ (read-input "Full name: " (user-full-name))
+ (user-full-name)))
+ ;; Note that some sites have room and phone number fields in
+ ;; full name which look silly when inserted. Rather than do
+ ;; anything about that here, let user give prefix argument so that
+ ;; s/he can edit the full name field in prompter if s/he wants.
+ (login-name (if whoami
+ (read-input "Login name: " (user-login-name))
+ (user-login-name)))
+ (site-name (if whoami
+ (read-input "Site name: " (system-name))
+ (system-name))))
+ (if (file-directory-p file-name)
+ (setq file-name (concat (file-name-as-directory file-name)
+ default)))
+ (if other-window (find-file-other-window file-name) (find-file file-name))
+ (or (eq major-mode 'indented-text-mode)
+ (progn
+ (indented-text-mode)
+ (setq left-margin 8)
+ (setq fill-column 74)))
+ (auto-fill-mode 1)
+ (undo-boundary)
+ (goto-char (point-min))
+ (if (not (and (looking-at (substring (current-time-string) 0 10))
+ (save-excursion (re-search-forward "(.*@"
+ (save-excursion
+ (end-of-line) (point))
+ t)
+ (skip-chars-backward "^(")
+ (looking-at login-name))))
+ (progn (insert (current-time-string)
+ " " full-name
+ " (" login-name
+ "@" site-name ")\n\n")))
+ (goto-char (point-min))
+ (forward-line 1)
+ (while (looking-at "\\sW")
+ (forward-line 1))
+ (delete-region (point)
+ (progn
+ (skip-chars-backward "\n")
+ (point)))
+ (open-line 3)
+ (forward-line 2)
+ (indent-to left-margin)
+ (insert "* ")))
+
+(defun add-change-log-entry-other-window ()
+ "Find change log file in other window, and add an entry for today."
+ (interactive)
+ (add-change-log-entry nil default-directory t))
diff --git a/lisp/add-log.elc b/lisp/add-log.elc
new file mode 100644
index 00000000000..277a06860e3
--- /dev/null
+++ b/lisp/add-log.elc
Binary files differ
diff --git a/lisp/array.el b/lisp/array.el
deleted file mode 100644
index d58d558188e..00000000000
--- a/lisp/array.el
+++ /dev/null
@@ -1,957 +0,0 @@
-;;; Array editing commands for Gnu Emacs
-;;; Written by dmb%morgoth@harvard.harvard.edu (address is old)
-;;; (David M. Brown at Goldberg-Zoino & Associates, Inc.)
-;;; Thanks to cph@kleph.ai.mit.edu for assistance
-
-;; Copyright (C) 1987 Free Software Foundation, Inc.
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 1, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
-;;; To do:
-;;; Smooth initialization process by grokking local variables list
-;;; at end of buffer or parsing buffer using whitespace as delimiters.
-;;; Make 'array-copy-column-right faster.
-
-
-
-;;; Internal information functions.
-
-(defun array-cursor-in-array-range ()
- "Returns t if the cursor is in a valid array cell.
-Its ok to be on a row number line."
- (let ((columns-last-line (% max-column columns-per-line)))
- ;; Requires buffer-line and buffer-column to be current.
- (not (or
- ;; The cursor is too far to the right.
- (>= buffer-column line-length)
- ;; The cursor is below the last row.
- (>= buffer-line (* lines-per-row max-row))
- ;; The cursor is on the last line of the row, the line is smaller
- ;; than the others, and the cursor is after the last array column
- ;; on the line.
- (and (zerop (% (1+ buffer-line) lines-per-row))
- (not (zerop columns-last-line))
- (>= buffer-column (* columns-last-line field-width)))))))
-
-(defun array-current-row ()
- "Return the array row of the field in which the cursor is located."
- ;; Requires buffer-line and buffer-column to be current.
- (and (array-cursor-in-array-range)
- (1+ (floor buffer-line lines-per-row))))
-
-(defun array-current-column ()
- "Return the array column of the field in which the cursor is located."
- ;; Requires buffer-line and buffer-column to be current.
- (and (array-cursor-in-array-range)
- ;; It's not okay to be on a row number line.
- (not (and rows-numbered
- (zerop (% buffer-line lines-per-row))))
- (+
- ;; Array columns due to line differences.
- (* columns-per-line
- (if rows-numbered
- (1- (% buffer-line lines-per-row))
- (% buffer-line lines-per-row)))
- ;; Array columns on the current line.
- (ceiling (1+ buffer-column) field-width))))
-
-(defun array-update-array-position (&optional a-row a-column)
- "Set `array-row' and `array-column' to their current values or
-to the optional arguments A-ROW and A-COLUMN."
- ;; Requires that buffer-line and buffer-column be current.
- (setq array-row (or a-row (array-current-row))
- array-column (or a-column (array-current-column))))
-
-(defun array-update-buffer-position ()
- "Set buffer-line and buffer-column to their current values."
- (setq buffer-line (current-line)
- buffer-column (current-column)))
-
-
-
-;;; Information commands.
-
-(defun array-what-position ()
- "Display the row and column in which the cursor is positioned."
- (interactive)
- (let ((buffer-line (current-line))
- (buffer-column (current-column)))
- (message (format "Array row: %s Array column: %s"
- (prin1-to-string (array-current-row))
- (prin1-to-string (array-current-column))))))
-
-(defun array-display-local-variables ()
- "Display the current state of the local variables in the minibuffer."
- (interactive)
- (let ((buf (buffer-name (current-buffer))))
- (with-output-to-temp-buffer "*Local Variables*"
- (buffer-disable-undo standard-output)
- (terpri)
- (princ (format " Buffer: %s\n\n" buf))
- (princ (format " max-row: %s\n"
- (prin1-to-string max-row)))
- (princ (format " max-column: %s\n"
- (prin1-to-string max-column)))
- (princ (format " columns-per-line: %s\n"
- (prin1-to-string columns-per-line)))
- (princ (format " field-width: %s\n"
- (prin1-to-string field-width)))
- (princ (format " rows-numbered: %s\n"
- (prin1-to-string rows-numbered)))
- (princ (format " lines-per-row: %s\n"
- (prin1-to-string lines-per-row)))
- (princ (format " line-length: %s\n"
- (prin1-to-string line-length))))))
-
-
-
-;;; Internal movement functions.
-
-(defun array-beginning-of-field (&optional go-there)
- "Return the column of the beginning of the current field.
-Optional argument GO-THERE, if non-nil, means go there too."
- ;; Requires that buffer-column be current.
- (let ((goal-column (- buffer-column (% buffer-column field-width))))
- (if go-there
- (move-to-column-untabify goal-column)
- goal-column)))
-
-(defun array-end-of-field (&optional go-there)
- "Return the column of the end of the current array field.
-If optional argument GO-THERE is non-nil, go there too."
- ;; Requires that buffer-column be current.
- (let ((goal-column (+ (- buffer-column (% buffer-column field-width))
- field-width)))
- (if go-there
- (move-to-column-untabify goal-column)
- goal-column)))
-
-(defun array-move-to-cell (a-row a-column)
- "Move to array row A-ROW and array column A-COLUMN.
-Leave point at the beginning of the field and return the new buffer column."
- (let ((goal-line (+ (* lines-per-row (1- a-row))
- (if rows-numbered 1 0)
- (floor (1- a-column) columns-per-line)))
- (goal-column (* field-width (% (1- a-column) columns-per-line))))
- (goto-char (point-min))
- (forward-line goal-line)
- (move-to-column-untabify goal-column)))
-
-(defun array-move-to-row (a-row)
- "Move to array row A-ROW preserving the current array column.
-Leave point at the beginning of the field and return the new array row."
- ;; Requires that buffer-line and buffer-column be current.
- (let ((goal-line (+ (* lines-per-row (1- a-row))
- (% buffer-line lines-per-row)))
- (goal-column (- buffer-column (% buffer-column field-width))))
- (forward-line (- goal-line buffer-line))
- (move-to-column-untabify goal-column)
- a-row))
-
-(defun array-move-to-column (a-column)
- "Move to array column A-COLUMN preserving the current array row.
-Leave point at the beginning of the field and return the new array column."
- ;; Requires that buffer-line and buffer-column be current.
- (let ((goal-line (+ (- buffer-line (% buffer-line lines-per-row))
- (if rows-numbered 1 0)
- (floor (1- a-column) columns-per-line)))
- (goal-column (* field-width (% (1- a-column) columns-per-line))))
- (forward-line (- goal-line buffer-line))
- (move-to-column-untabify goal-column)
- a-column))
-
-(defun array-move-one-row (sign)
- "Move one array row in direction SIGN (1 or -1).
-Leave point at the beginning of the field and return the new array row.
-If requested to move beyond the array bounds, signal an error."
- ;; Requires that buffer-line and buffer-column be current.
- (let ((goal-column (array-beginning-of-field))
- (array-row (or (array-current-row)
- (error "Cursor is not in a valid array cell."))))
- (cond ((and (= array-row max-row) (= sign 1))
- (error "End of array."))
- ((and (= array-row 1) (= sign -1))
- (error "Beginning of array."))
- (t
- (progn
- (forward-line (* sign lines-per-row))
- (move-to-column-untabify goal-column)
- (+ array-row sign))))))
-
-(defun array-move-one-column (sign)
- "Move one array column in direction SIGN (1 or -1).
-Leave point at the beginning of the field and return the new array column.
-If requested to move beyond the array bounds, signal an error."
- ;; Requires that buffer-line and buffer-column be current.
- (let ((array-column (or (array-current-column)
- (error "Cursor is not in a valid array cell."))))
- (cond ((and (= array-column max-column) (= sign 1))
- (error "End of array."))
- ((and (= array-column 1) (= sign -1))
- (error "Beginning of array."))
- (t
- (cond
- ;; Going backward from first column on the line.
- ((and (= sign -1) (= 1 (% array-column columns-per-line)))
- (forward-line -1)
- (move-to-column-untabify
- (* field-width (1- columns-per-line))))
- ;; Going forward from last column on the line.
- ((and (= sign 1) (zerop (% array-column columns-per-line)))
- (forward-line 1))
- ;; Somewhere in the middle of the line.
- (t
- (move-to-column-untabify (+ (array-beginning-of-field)
- (* field-width sign)))))
- (+ array-column sign)))))
-
-(defun array-normalize-cursor ()
- "Move the cursor to the first non-whitespace character in the field and,
-if necessary, scroll horizontally to keep the cursor in view."
- ;; Assumes point is at the beginning of the field.
- (let ((buffer-column (current-column)))
- (skip-chars-forward " \t"
- (1- (save-excursion (array-end-of-field t) (point))))
- (array-maybe-scroll-horizontally)))
-
-(defun array-maybe-scroll-horizontally ()
- "If necessary, scroll horizontally to keep the cursor in view."
- ;; This is only called from array-normalize-cursor so
- ;; buffer-column will always be current.
- (let ((w-hscroll (window-hscroll))
- (w-width (window-width)))
- (cond
- ((and (>= buffer-column w-hscroll)
- (<= buffer-column (+ w-hscroll w-width)))
- ;; It's already visible. Do nothing.
- nil)
- ((> buffer-column (+ w-hscroll w-width))
- ;; It's to the right. Scroll left.
- (scroll-left (- (- buffer-column w-hscroll)
- (/ w-width 2))))
- (t
- ;; It's to the left. Scroll right.
- (scroll-right (+ (- w-hscroll buffer-column)
- (/ w-width 2)))))))
-
-
-
-;;; Movement commands.
-
-(defun array-next-row (&optional arg)
- "Move down one array row, staying in the current array column.
-If optional ARG is given, move down ARG array rows."
- (interactive "p")
- (let ((buffer-line (current-line))
- (buffer-column (current-column)))
- (if (= (abs arg) 1)
- (array-move-one-row arg)
- (array-move-to-row
- (limit-index (+ (or (array-current-row)
- (error "Cursor is not in an array cell."))
- arg)
- max-row))))
- (array-normalize-cursor))
-
-(defun array-previous-row (&optional arg)
- "Move up one array row, staying in the current array column.
-If optional ARG is given, move up ARG array rows."
- (interactive "p")
- (array-next-row (- arg)))
-
-(defun array-forward-column (&optional arg)
- "Move forward one field, staying in the current array row.
-If optional ARG is given, move forward ARG array columns.
-If necessary, keep the cursor in the window by scrolling right or left."
- (interactive "p")
- (let ((buffer-line (current-line))
- (buffer-column (current-column)))
- (if (= (abs arg) 1)
- (array-move-one-column arg)
- (array-move-to-column
- (limit-index (+ (or (array-current-column)
- (error "Cursor is not in an array cell."))
- arg)
- max-column))))
- (array-normalize-cursor))
-
-(defun array-backward-column (&optional arg)
- "Move backward one field, staying in the current array row.
-If optional ARG is given, move backward ARG array columns.
-If necessary, keep the cursor in the window by scrolling right or left."
- (interactive "p")
- (array-forward-column (- arg)))
-
-(defun array-goto-cell (a-row a-column)
- "Go to array row A-ROW and array column A-COLUMN."
- (interactive "nArray row: \nnArray column: ")
- (array-move-to-cell
- (limit-index a-row max-row)
- (limit-index a-column max-column))
- (array-normalize-cursor))
-
-
-
-;;; Internal copying functions.
-
-(defun array-field-string ()
- "Return the field string at the current cursor location."
- ;; Requires that buffer-column be current.
- (buffer-substring
- (save-excursion (array-beginning-of-field t) (point))
- (save-excursion (array-end-of-field t) (point))))
-
-(defun array-copy-once-vertically (sign)
- "Copy the current field into one array row in direction SIGN (1 or -1).
-Leave point at the beginning of the field and return the new array row.
-If requested to move beyond the array bounds, signal an error."
- ;; Requires that buffer-line, buffer-column, and copy-string be current.
- (let ((a-row (array-move-one-row sign)))
- (let ((inhibit-quit t))
- (delete-region (point) (save-excursion (array-end-of-field t) (point)))
- (insert copy-string))
- (move-to-column buffer-column)
- a-row))
-
-(defun array-copy-once-horizontally (sign)
- "Copy the current field into one array column in direction SIGN (1 or -1).
-Leave point at the beginning of the field and return the new array column.
-If requested to move beyond the array bounds, signal an error."
- ;; Requires that buffer-line, buffer-column, and copy-string be current.
- (let ((a-column (array-move-one-column sign)))
- (array-update-buffer-position)
- (let ((inhibit-quit t))
- (delete-region (point) (save-excursion (array-end-of-field t) (point)))
- (insert copy-string))
- (move-to-column buffer-column)
- a-column))
-
-(defun array-copy-to-row (a-row)
- "Copy the current field vertically into every cell up to and including A-ROW.
-Leave point at the beginning of the field."
- ;; Requires that buffer-line, buffer-column, array-row, and
- ;; copy-string be current.
- (let* ((num (- a-row array-row))
- (count (abs num))
- (sign (if (zerop count) () (/ num count))))
- (while (> count 0)
- (array-move-one-row sign)
- (array-update-buffer-position)
- (let ((inhibit-quit t))
- (delete-region (point) (save-excursion (array-end-of-field t) (point)))
- (insert copy-string))
- (move-to-column buffer-column)
- (setq count (1- count)))))
-
-(defun array-copy-to-column (a-column)
- "Copy the current field horizontally into every cell up to and including
-A-COLUMN. Leave point at the beginning of the field."
- ;; Requires that buffer-line, buffer-column, array-column, and
- ;; copy-string be current.
- (let* ((num (- a-column array-column))
- (count (abs num))
- (sign (if (zerop count) () (/ num count))))
- (while (> count 0)
- (array-move-one-column sign)
- (array-update-buffer-position)
- (let ((inhibit-quit t))
- (delete-region (point) (save-excursion (array-end-of-field t) (point)))
- (insert copy-string))
- (move-to-column buffer-column)
- (setq count (1- count)))))
-
-(defun array-copy-to-cell (a-row a-column)
- "Copy the current field into the cell at A-ROW, A-COLUMN.
-Leave point at the beginning of the field."
- ;; Requires that copy-string be current.
- (array-move-to-cell a-row a-column)
- (array-update-buffer-position)
- (delete-region (point) (save-excursion (array-end-of-field t) (point)))
- (insert copy-string)
- (move-to-column buffer-column))
-
-
-
-;;; Commands for copying.
-
-(defun array-copy-down (&optional arg)
- "Copy the current field one array row down.
-If optional ARG is given, copy down through ARG array rows."
- (interactive "p")
- (let* ((buffer-line (current-line))
- (buffer-column (current-column))
- (array-row (or (array-current-row)
- (error "Cursor is not in a valid array cell.")))
- (copy-string (array-field-string)))
- (if (= (abs arg) 1)
- (array-copy-once-vertically arg)
- (array-copy-to-row
- (limit-index (+ array-row arg) max-row))))
- (array-normalize-cursor))
-
-(defun array-copy-up (&optional arg)
- "Copy the current field one array row up.
-If optional ARG is given, copy up through ARG array rows."
- (interactive "p")
- (array-copy-down (- arg)))
-
-(defun array-copy-forward (&optional arg)
- "Copy the current field one array column to the right.
-If optional ARG is given, copy through ARG array columns to the right."
- (interactive "p")
- (let* ((buffer-line (current-line))
- (buffer-column (current-column))
- (array-column (or (array-current-column)
- (error "Cursor is not in a valid array cell.")))
- (copy-string (array-field-string)))
- (if (= (abs arg) 1)
- (array-copy-once-horizontally arg)
- (array-copy-to-column
- (limit-index (+ array-column arg) max-column))))
- (array-normalize-cursor))
-
-(defun array-copy-backward (&optional arg)
- "Copy the current field one array column to the left.
-If optional ARG is given, copy through ARG array columns to the left."
- (interactive "p")
- (array-copy-forward (- arg)))
-
-(defun array-copy-column-forward (&optional arg)
- "Copy the entire current column in to the column to the right.
-If optional ARG is given, copy through ARG array columns to the right."
- (interactive "p")
- (array-update-buffer-position)
- (array-update-array-position)
- (if (not array-column)
- (error "Cursor is not in a valid array cell."))
- (message "Working...")
- (let ((this-row 0))
- (while (< this-row max-row)
- (setq this-row (1+ this-row))
- (array-move-to-cell this-row array-column)
- (array-update-buffer-position)
- (let ((copy-string (array-field-string)))
- (if (= (abs arg) 1)
- (array-copy-once-horizontally arg)
- (array-copy-to-column
- (limit-index (+ array-column arg) max-column))))))
- (message "Working...done")
- (array-move-to-row array-row)
- (array-normalize-cursor))
-
-(defun array-copy-column-backward (&optional arg)
- "Copy the entire current column one column to the left.
-If optional ARG is given, copy through ARG columns to the left."
- (interactive "p")
- (array-copy-column-forward (- arg)))
-
-(defun array-copy-row-down (&optional arg)
- "Copy the entire current row one row down.
-If optional ARG is given, copy through ARG rows down."
- (interactive "p")
- (array-update-buffer-position)
- (array-update-array-position)
- (if (not array-row)
- (error "Cursor is not in a valid array cell."))
- (cond
- ((and (= array-row 1) (= arg -1))
- (error "Beginning of array."))
- ((and (= array-row max-row) (= arg 1))
- (error "End of array."))
- (t
- (let* ((copy-string
- (buffer-substring
- (save-excursion (array-move-to-cell array-row 1)
- (point))
- (save-excursion (array-move-to-cell array-row max-column)
- (forward-line 1)
- (point))))
- (this-row array-row)
- (goal-row (limit-index (+ this-row arg) max-row))
- (num (- goal-row this-row))
- (count (abs num))
- (sign (if (not (zerop count)) (/ num count))))
- (while (> count 0)
- (setq this-row (+ this-row sign))
- (array-move-to-cell this-row 1)
- (let ((inhibit-quit t))
- (delete-region (point)
- (save-excursion
- (array-move-to-cell this-row max-column)
- (forward-line 1)
- (point)))
- (insert copy-string))
- (setq count (1- count)))
- (array-move-to-cell goal-row (or array-column 1)))))
- (array-normalize-cursor))
-
-(defun array-copy-row-up (&optional arg)
- "Copy the entire current array row into the row above.
-If optional ARG is given, copy through ARG rows up."
- (interactive "p")
- (array-copy-row-down (- arg)))
-
-(defun array-fill-rectangle ()
- "Copy the field at mark into every cell between mark and point."
- (interactive)
- ;; Bind arguments.
- (array-update-buffer-position)
- (let ((p-row (or (array-current-row)
- (error "Cursor is not in a valid array cell.")))
- (p-column (or (array-current-column)
- (error "Cursor is not in a valid array cell.")))
- (m-row
- (save-excursion
- (exchange-point-and-mark)
- (array-update-buffer-position)
- (or (array-current-row)
- (error "Mark is not in a valid array cell."))))
- (m-column
- (save-excursion
- (exchange-point-and-mark)
- (array-update-buffer-position)
- (or (array-current-column)
- (error "Mark is not in a valid array cell.")))))
- (message "Working...")
- (let ((top-row (min m-row p-row))
- (bottom-row (max m-row p-row))
- (left-column (min m-column p-column))
- (right-column (max m-column p-column)))
- ;; Do the first row.
- (let ((copy-string
- (save-excursion
- (array-move-to-cell m-row m-column)
- (array-update-buffer-position)
- (array-field-string))))
- (array-copy-to-cell top-row left-column)
- (array-update-array-position top-row left-column)
- (array-update-buffer-position)
- (array-copy-to-column right-column))
- ;; Do the rest of the rows.
- (array-move-to-cell top-row left-column)
- (let ((copy-string
- (buffer-substring
- (point)
- (save-excursion
- (array-move-to-cell top-row right-column)
- (setq buffer-column (current-column))
- (array-end-of-field t)
- (point))))
- (this-row top-row))
- (while (/= this-row bottom-row)
- (setq this-row (1+ this-row))
- (array-move-to-cell this-row left-column)
- (let ((inhibit-quit t))
- (delete-region
- (point)
- (save-excursion
- (array-move-to-cell this-row right-column)
- (setq buffer-column (current-column))
- (array-end-of-field t)
- (point)))
- (insert copy-string)))))
- (message "Working...done")
- (array-goto-cell p-row p-column)))
-
-
-
-;;; Reconfiguration of the array.
-
-(defun array-make-template ()
- "Create the template of an array."
- (interactive)
- ;; If there is a conflict between field-width and init-string, resolve it.
- (let ((check t)
- (len))
- (while check
- (setq init-field (read-input "Initial field value: "))
- (setq len (length init-field))
- (if (/= len field-width)
- (if (y-or-n-p (format "Change field width to %d? " len))
- (progn (setq field-width len)
- (setq check nil)))
- (setq check nil))))
- (goto-char (point-min))
- (message "Working...")
- (let ((this-row 1))
- ;; Loop through the rows.
- (while (<= this-row max-row)
- (if rows-numbered
- (insert (format "%d:\n" this-row)))
- (let ((this-column 1))
- ;; Loop through the columns.
- (while (<= this-column max-column)
- (insert init-field)
- (if (and (zerop (% this-column columns-per-line))
- (/= this-column max-column))
- (newline))
- (setq this-column (1+ this-column))))
- (setq this-row (1+ this-row))
- (newline)))
- (message "Working...done")
- (array-goto-cell 1 1))
-
-(defun array-reconfigure-rows (new-columns-per-line new-rows-numbered)
- "Reconfigure the state of `rows-numbered' and `columns-per-line'.
-NEW-COLUMNS-PER-LINE is the desired value of `columns-per-line' and
-NEW-ROWS-NUMBERED (a character, either ?y or ?n) is the desired value
-of rows-numbered."
- (interactive "nColumns per line: \ncRows numbered? (y or n) ")
- ;; Check on new-columns-per-line
- (let ((check t))
- (while check
- (if (and (>= new-columns-per-line 1)
- (<= new-columns-per-line max-column))
- (setq check nil)
- (setq new-columns-per-line
- (string-to-int
- (read-input
- (format "Columns per line (1 - %d): " max-column)))))))
- ;; Check on new-rows-numbered. It has to be done this way
- ;; because interactive does not have y-or-n-p.
- (cond
- ((eq new-rows-numbered ?y)
- (setq new-rows-numbered t))
- ((eq new-rows-numbered ?n)
- (setq new-rows-numbered nil))
- (t
- (setq new-rows-numbered (y-or-n-p "Rows numbered? "))))
- (message "Working...")
- (array-update-buffer-position)
- (let* ((main-buffer (buffer-name (current-buffer)))
- (temp-buffer (make-temp-name "Array"))
- (temp-max-row max-row)
- (temp-max-column max-column)
- (old-rows-numbered rows-numbered)
- (old-columns-per-line columns-per-line)
- (old-lines-per-row lines-per-row)
- (old-field-width field-width)
- (old-line-length line-length)
- (this-row 1))
- (array-update-array-position)
- ;; Do the cutting in a temporary buffer.
- (copy-to-buffer temp-buffer (point-min) (point-max))
- (set-buffer temp-buffer)
- (goto-char (point-min))
- (while (<= this-row temp-max-row)
- ;; Deal with row number.
- (cond
- ((or (and old-rows-numbered new-rows-numbered)
- (and (not old-rows-numbered) (not new-rows-numbered)))
- ;; Nothing is changed.
- ())
- ((and old-rows-numbered (not new-rows-numbered))
- ;; Delete the row number.
- (kill-line 1))
- (t
- ;; Add the row number.
- (insert-string (format "%d:\n" this-row))))
- ;; Deal with the array columns in this row.
- (cond
- ((= old-columns-per-line new-columns-per-line)
- ;; Nothing is changed. Go to the next row.
- (forward-line (- old-lines-per-row (if old-rows-numbered 1 0))))
- (t
- ;; First expand the row. Then cut it up into new pieces.
- (let ((newlines-to-be-removed
- (floor (1- temp-max-column) old-columns-per-line))
- (newlines-removed 0)
- (newlines-to-be-added
- (floor (1- temp-max-column) new-columns-per-line))
- (newlines-added 0))
- (while (< newlines-removed newlines-to-be-removed)
- (move-to-column-untabify
- (* (1+ newlines-removed) old-line-length))
- (kill-line 1)
- (setq newlines-removed (1+ newlines-removed)))
- (beginning-of-line)
- (while (< newlines-added newlines-to-be-added)
- (move-to-column-untabify (* old-field-width new-columns-per-line))
- (newline)
- (setq newlines-added (1+ newlines-added)))
- (forward-line 1))))
- (setq this-row (1+ this-row)))
- (let ((inhibit-quit t))
- (set-buffer main-buffer)
- (erase-buffer)
- (insert-buffer temp-buffer)
- ;; Update local variables.
- (setq columns-per-line new-columns-per-line)
- (setq rows-numbered new-rows-numbered)
- (setq line-length (* old-field-width new-columns-per-line))
- (setq lines-per-row
- (+ (ceiling temp-max-column new-columns-per-line)
- (if new-rows-numbered 1 0)))
- (array-goto-cell (or array-row 1) (or array-column 1)))
- (kill-buffer temp-buffer))
- (message "Working...done"))
-
-(defun array-expand-rows ()
- "Expand the rows so each fits on one line and remove row numbers."
- (interactive)
- (array-reconfigure-rows max-column ?n))
-
-
-
-;;; Utilities.
-
-(defun limit-index (index limit)
- (cond ((< index 1) 1)
- ((> index limit) limit)
- (t index)))
-
-(defun abs (int)
- "Return the absolute value of INT."
- (if (< int 0) (- int) int))
-
-
-(defun floor (int1 int2)
- "Returns the floor of INT1 divided by INT2.
-INT1 may be negative. INT2 must be positive."
- (if (< int1 0)
- (- (ceiling (- int1) int2))
- (/ int1 int2)))
-
-(defun ceiling (int1 int2)
- "Returns the ceiling of INT1 divided by INT2.
-Assumes that both arguments are nonnegative."
- (+ (/ int1 int2)
- (if (zerop (mod int1 int2))
- 0
- 1)))
-
-(defun xor (pred1 pred2)
- "Returns the logical exclusive or of predicates PRED1 and PRED2."
- (and (or pred1 pred2)
- (not (and pred1 pred2))))
-
-(defun current-line ()
- "Return the current buffer line at point. The first line is 0."
- (save-excursion
- (beginning-of-line)
- (count-lines (point-min) (point))))
-
-(defun move-to-column-untabify (column)
- "Move to COLUMN on the current line, untabifying if necessary.
-Return COLUMN."
- (or (and (= column (move-to-column column))
- column)
- ;; There is a tab in the way.
- (if respect-tabs
- (error "There is a TAB character in the way.")
- (progn
- (untabify-backward)
- (move-to-column column)))))
-
-(defun untabify-backward ()
- "Untabify the preceding tab."
- (save-excursion
- (let ((start (point)))
- (backward-char 1)
- (untabify (point) start))))
-
-
-
-;;; Array mode.
-
-(defvar array-mode-map nil
- "Keymap used in array mode.")
-
-(if array-mode-map
- ()
- (setq array-mode-map (make-keymap))
- ;; Bind keys.
- (define-key array-mode-map "\M-ad" 'array-display-local-variables)
- (define-key array-mode-map "\M-am" 'array-make-template)
- (define-key array-mode-map "\M-ae" 'array-expand-rows)
- (define-key array-mode-map "\M-ar" 'array-reconfigure-rows)
- (define-key array-mode-map "\M-a=" 'array-what-position)
- (define-key array-mode-map "\M-ag" 'array-goto-cell)
- (define-key array-mode-map "\M-af" 'array-fill-rectangle)
- (define-key array-mode-map "\C-n" 'array-next-row)
- (define-key array-mode-map "\C-p" 'array-previous-row)
- (define-key array-mode-map "\C-f" 'array-forward-column)
- (define-key array-mode-map "\C-b" 'array-backward-column)
- (define-key array-mode-map "\M-n" 'array-copy-down)
- (define-key array-mode-map "\M-p" 'array-copy-up)
- (define-key array-mode-map "\M-f" 'array-copy-forward)
- (define-key array-mode-map "\M-b" 'array-copy-backward)
- (define-key array-mode-map "\M-\C-n" 'array-copy-row-down)
- (define-key array-mode-map "\M-\C-p" 'array-copy-row-up)
- (define-key array-mode-map "\M-\C-f" 'array-copy-column-forward)
- (define-key array-mode-map "\M-\C-b" 'array-copy-column-backward))
-
-(put 'array-mode 'mode-class 'special)
-
-(defun array-mode ()
- "Major mode for editing arrays.
-
- Array mode is a specialized mode for editing arrays. An array is
-considered to be a two-dimensional set of strings. The strings are
-NOT recognized as integers or real numbers.
-
- The array MUST reside at the top of the buffer.
-
- TABs are not respected, and may be converted into spaces at any time.
-Setting the variable 'respect-tabs to non-nil will prevent TAB conversion,
-but will cause many functions to give errors if they encounter one.
-
- Upon entering array mode, you will be prompted for the values of
-several variables. Others will be calculated based on the values you
-supply. These variables are all local the the buffer. Other buffer
-in array mode may have different values assigned to the variables.
-The variables are:
-
-Variables you assign:
- max-row: The number of rows in the array.
- max-column: The number of columns in the array.
- columns-per-line: The number of columns in the array per line of buffer.
- field-width: The width of each field, in characters.
- rows-numbered: A logical variable describing whether to ignore
- row numbers in the buffer.
-
-Variables which are calculated:
- line-length: The number of characters in a buffer line.
- lines-per-row: The number of buffer lines used to display each row.
-
- The following commands are available (an asterisk indicates it may
-take a numeric prefix argument):
-
- * \\<array-mode-map>\\[array-forward-column] Move forward one column.
- * \\[array-backward-column] Move backward one column.
- * \\[array-next-row] Move down one row.
- * \\[array-previous-row] Move up one row.
-
- * \\[array-copy-forward] Copy the current field into the column to the right.
- * \\[array-copy-backward] Copy the current field into the column to the left.
- * \\[array-copy-down] Copy the current field into the row below.
- * \\[array-copy-up] Copy the current field into the row above.
-
- * \\[array-copy-column-forward] Copy the current column into the column to the right.
- * \\[array-copy-column-backward] Copy the current column into the column to the left.
- * \\[array-copy-row-down] Copy the current row into the row below.
- * \\[array-copy-row-up] Copy the current row into the row above.
-
- \\[array-fill-rectangle] Copy the field at mark into every cell with row and column
- between that of point and mark.
-
- \\[array-what-position] Display the current array row and column.
- \\[array-goto-cell] Go to a particular array cell.
-
- \\[array-make-template] Make a template for a new array.
- \\[array-reconfigure-rows] Reconfigure the array.
- \\[array-expand-rows] Expand the array (remove row numbers and
- newlines inside rows)
-
- \\[array-display-local-variables] Display the current values of local variables.
-
-Entering array mode calls the function `array-mode-hook'."
-
- (interactive)
- ;; Number of rows in the array.
- (make-local-variable 'max-row)
- ;; Number of columns in the array.
- (make-local-variable 'max-column)
- ;; Number of array columns per line.
- (make-local-variable 'columns-per-line)
- ;; Width of a field in the array.
- (make-local-variable 'field-width)
- ;; Are rows numbered in the buffer?
- (make-local-variable 'rows-numbered)
- ;; Length of a line in the array.
- (make-local-variable 'line-length)
- ;; Number of lines per array row.
- (make-local-variable 'lines-per-row)
- ;; Current line number of point in the buffer.
- (make-local-variable 'buffer-line)
- ;; Current column number of point in the buffer.
- (make-local-variable 'buffer-column)
- ;; Current array row location of point.
- (make-local-variable 'array-row)
- ;; Current array column location of point.
- (make-local-variable 'array-column)
- ;; Current field string being copied.
- (make-local-variable 'copy-string)
- ;; Should TAB conversion be prevented?
- (make-local-variable 'respect-tabs)
- (setq respect-tabs nil)
- (array-init-local-variables)
- (setq major-mode 'array-mode)
- (setq mode-name "Array")
- ;; Update mode-line.
- (progn (save-excursion (set-buffer (other-buffer)))
- (set-buffer-modified-p (buffer-modified-p))
- (sit-for 0))
- (make-variable-buffer-local 'truncate-lines)
- (setq truncate-lines t)
- (setq overwrite-mode t)
- (use-local-map array-mode-map)
- (run-hooks 'array-mode-hook))
-
-
-
-;;; Initialization functions. These are not interactive.
-
-(defun array-init-local-variables ()
- "Initialize the variables associated with the
-array in this buffer."
- (array-init-max-row)
- (array-init-max-column)
- (array-init-columns-per-line)
- (array-init-field-width)
- (array-init-rows-numbered)
- (array-init-line-length)
- (array-init-lines-per-row)
- (message ""))
-
-(defun array-init-max-row (&optional arg)
- "Initialize the value of max-row."
- (setq max-row
- (or arg (string-to-int (read-input "Number of array rows: ")))))
-
-(defun array-init-max-column (&optional arg)
- "Initialize the value of max-column."
- (setq max-column
- (or arg (string-to-int (read-input "Number of array columns: ")))))
-
-(defun array-init-columns-per-line (&optional arg)
- "Initialize the value of columns-per-line."
- (setq columns-per-line
- (or arg (string-to-int (read-input "Array columns per line: ")))))
-
-(defun array-init-field-width (&optional arg)
- "Initialize the value of field-width."
- (setq field-width
- (or arg (string-to-int (read-input "Field width: ")))))
-
-(defun array-init-rows-numbered (&optional arg)
- "Initialize the value of rows-numbered."
- (setq rows-numbered
- (or arg (y-or-n-p "Rows numbered? "))))
-
-(defun array-init-line-length (&optional arg)
- "Initialize the value of line-length."
- (setq line-length
- (or arg
- (* field-width columns-per-line))))
-
-(defun array-init-lines-per-row (&optional arg)
- "Initialize the value of lines-per-row."
- (setq lines-per-row
- (or arg
- (+ (ceiling max-column columns-per-line)
- (if rows-numbered 1 0)))))
diff --git a/lisp/autoinsert.el b/lisp/autoinsert.el
index 61736c9f68b..a185cc077ae 100644
--- a/lisp/autoinsert.el
+++ b/lisp/autoinsert.el
@@ -53,14 +53,14 @@
("\\.h$" . "h-insert.c")
("[Mm]akefile" . "makefile.inc")
("\\.bib$" . "tex-insert.tex"))
- "A list specifying text to insert by default into a new file.
+ "Alist specifying text to insert by default into a new file.
Elements look like (REGEXP . FILENAME); if the new file's name
matches REGEXP, then the file FILENAME is inserted into the buffer.
Only the first matching element is effective.")
;;; Establish a default value for auto-insert-directory
(defvar auto-insert-directory "~/insert/"
- "*Directory from which auto-inserted files are taken.")
+ "Directory from which auto-inserted files are taken.")
(defun insert-auto-insert-files ()
"Insert default contents into a new file.
@@ -80,9 +80,7 @@ Matches the visited file name against the elements of `auto-insert-alist'."
(if insert-file
(let ((file (concat auto-insert-directory insert-file)))
(if (file-readable-p file)
- (progn
- (insert-file-contents file)
- (set-buffer-modified-p nil))
+ (insert-file-contents file)
(message "Auto-insert: file %s not found" file)
(sleep-for 1))))))
diff --git a/lisp/emacs-lisp/backquote.el b/lisp/backquote.el
index 715a794d5fe..fa979a54079 100644
--- a/lisp/emacs-lisp/backquote.el
+++ b/lisp/backquote.el
@@ -91,43 +91,8 @@ a list-value atom"
;;; This is the interface
(defmacro ` (form)
- "(` FORM) is a macro that expands to code to construct FORM.
-Note that this is very slow in interpreted code, but fast if you compile.
-FORM is one or more nested lists, which are `almost quoted':
-They are copied recursively, with non-lists used unchanged in the copy.
- (` a b) == (list 'a 'b) constructs a new list with two elements, `a' and `b'.
- (` a (b c)) == (list 'a (list 'b 'c)) constructs two nested new lists.
-
-However, certain special lists are not copied. They specify substitution.
-Lists that look like (, EXP) are evaluated and the result is substituted.
- (` a (, (+ x 5))) == (list 'a (+ x 5))
-
-Elements of the form (,@ EXP) are evaluated and then all the elements
-of the result are substituted. This result must be a list; it may
-be `nil'.
-
-As an example, a simple macro `push' could be written:
- (defmacro push (v l)
- (` (setq (, l) (cons (,@ (list v l))))))
-or as
- (defmacro push (v l)
- (` (setq (, l) (cons (, v) (, l)))))
-
-LIMITATIONS: \"dotted lists\" are not allowed in FORM.
-The ultimate cdr of each list scanned by ` must be `nil'.
-\(This does not apply to constants inside expressions to be substituted.)
-
-Substitution elements are not allowed as the cdr
-of a cons cell. For example, (` (A . (, B))) does not work.
-Instead, write (` (A (,@ B))).
-
-You cannot construct vectors, only lists. Vectors are treated as
-constants.
-
-BEWARE BEWARE BEWARE
-Inclusion of (,ATOM) rather than (, ATOM)
-or of (,@ATOM) rather than (,@ ATOM)
-will result in errors that will show up very late."
+ "(` FORM) Expands to a form that will generate FORM.
+FORM is `almost quoted' -- see backquote.el for a description."
(bq-make-maker form))
;;; We develop the method for building the desired list from
@@ -190,8 +155,8 @@ See backquote.el for details"
;;; This maintains the invariant that (cons state tailmaker) is the
;;; maker for the elements of the tail we've eaten so far.
(defun bq-iterative-list-builder (form)
- "Called by `bq-make-maker'. Adds a new item form to tailmaker,
-changing state if need be, so tailmaker and state constitute a recipe
+ "Called by bq-make-maker. Adds a new item form to tailmaker,
+changing state if need be, so tailmaker and state constitute a recipie
for making the list so far."
(cond ((atom form)
(funcall (bq-cadr (assq state bq-quotefns)) form))
@@ -321,13 +286,13 @@ for making the list so far."
(rplacd (car tailmaker)
(cons form (bq-cdar tailmaker))))
((= (length tailmaker) 1)
- (setq tailmaker (cons form tailmaker)
- state 'cons))
+ (setq tailmaker (cons form tailmaker))
+ (setq state 'cons))
(t (bq-push (list 'list form) tailmaker))))
(defun bq-evalnil (form)
- (setq tailmaker (list form)
- state 'list))
+ (setq tailmaker (list form))
+ (setq state 'list))
;;; (if (matches (X Y)) ; it must
;;; (progn (setq state 'append)
@@ -335,20 +300,23 @@ for making the list so far."
(defun bq-splicecons (form)
(setq tailmaker
(list form
- (list 'cons (car tailmaker) (bq-cadr tailmaker)))
- state 'append))
+ (list 'cons (car tailmaker) (bq-cadr tailmaker))))
+ (setq state 'append))
(defun bq-splicequote (form)
- (setq tailmaker (list form (list 'quote tailmaker))
- state 'append))
+ (setq tailmaker (list form (list 'quote (list tailmaker))))
+ (setq state 'append))
(defun bq-splicelist (form)
- (setq tailmaker (list form (cons 'list tailmaker))
- state 'append))
+ (setq tailmaker (list form (cons 'list tailmaker)))
+ (setq state 'append))
(defun bq-spliceappend (form)
(bq-push form tailmaker))
(defun bq-splicenil (form)
- (setq state 'append
- tailmaker (list form)))
+ (setq state 'append)
+ (setq tailmaker (list form)))
+
+
+
diff --git a/lisp/backquote.elc b/lisp/backquote.elc
new file mode 100644
index 00000000000..798687f5e9b
--- /dev/null
+++ b/lisp/backquote.elc
Binary files differ
diff --git a/lisp/term/bg-mouse.el b/lisp/bg-mouse.el
index 9b83f5f6c2a..fef1b2d56f2 100644
--- a/lisp/term/bg-mouse.el
+++ b/lisp/bg-mouse.el
@@ -128,8 +128,8 @@ To reinitialize the mouse if the terminal is reset, type ESC : RET"
(yank-pop 1))
(defun bg-yank-or-pop ()
- "Move point to location of BitGraph mouse and yank. If last command
-was a yank, do a yank-pop."
+ "Move point to location of BitGraph mouse and yank or yank-pop.
+Do a yank unless last command was a yank, in which case do a yank-pop."
(interactive "*")
(if (eql last-command 'yank)
(yank-pop 1)
@@ -139,8 +139,8 @@ was a yank, do a yank-pop."
(defconst bg-most-positive-fixnum 8388607)
(defun bg-move-by-percentage ()
- "Go to location in buffer that is the same percentage of the way
-through the buffer as the BitGraph mouse's X position in the window."
+ "Go to location in buffer that is the same percentage of the
+way through the buffer as the BitGraph mouse's X position in the window."
(interactive)
;; check carefully for overflow in intermediate calculations
(goto-char
@@ -179,7 +179,8 @@ of the window"
(defun bg-insert-moused-sexp ()
"Insert a copy of the word (actually sexp) that the mouse is pointing at.
-Sexp is inserted into the buffer at point (where the text cursor is)."
+Sexp is inserted into the buffer at point (where the text cursor is).
+By gildea 7 Feb 89"
(interactive)
(let ((moused-text
(save-excursion
diff --git a/lisp/bibtex.el b/lisp/bibtex.el
new file mode 100644
index 00000000000..6b0e6217cc5
--- /dev/null
+++ b/lisp/bibtex.el
@@ -0,0 +1,426 @@
+;;; Simple BibTeX mode for GNU Emacs
+;;; Bengt Martensson 87-06-28
+;;; changes by Marc Shapiro shapiro@inria.inria.fr 15-oct-1986
+;;; (align long lines nicely; C-c C-o checks for the "OPT" string;
+;;; TAB goes to the end of the string; use lower case; use
+;;; run-hooks)
+;;; Marc Shapiro 19-oct-1987
+;;; add X window menu option; bug fixes. TAB, LFD, C-c " and C-c C-o now
+;;; behave consistently; deletion never occurs blindly.
+;;; Marc Shapiro 3-nov-87
+;;; addition for France: DEAthesis
+;;; Skip Montanaro <steinmetz!sprite!montanaro> 7-dec-87, Shapiro 10-dec-87
+;;; before inserting an entry, make sure we are outside of a bib entry
+;;; Marc Shapiro 14-dec-87
+;;; Cosmetic fixes. Fixed small bug in bibtex-move-outside-of-entry.
+
+;;; NOTE by Marc Shapiro, 14-dec-87:
+;;; (bibtex-x-environment) binds an X menu for bibtex mode to x-button-c-right.
+;;; Trouble is, in Emacs 18.44 you can't have a mode-specific mouse binding,
+;;; so it will remain active in all windows. Yuck!
+
+;;; Bengt Martensson 88-05-06:
+;;; Added Sun menu support. Locally bound to right mouse button in
+;;; bibtex-mode. Emacs 18.49 allows local mouse bindings!!
+;;; Commented out vtxxx-keys and DEAthesis. Changed documentation slightly.
+
+(defvar bibtex-mode-syntax-table nil "")
+(defvar bibtex-mode-abbrev-table nil "")
+(define-abbrev-table 'bibtex-mode-abbrev-table ())
+(defvar bibtex-mode-map (make-sparse-keymap) "")
+
+(defun bibtex-mode ()
+ "Major mode for editing bibtex files. Commands:
+\\{bibtex-mode-map}
+
+A command such as \\[bibtex-Book] will outline the fields for a BibTeX
+book entry.
+
+The optional fields are preceded by ""OPT"", thus ignored by BibTeX.
+Use \\[bibtex-remove-opt] to remove ""OPT"" on the current line.
+
+Use \\[bibtex-find-it] to position the dot at the end of the string on the same line.
+Use \\[bibtex-next-position] to move to the next position to fill in. Use \\[kill-current-line]
+to kill the whole line.
+
+M-x bibtex-x-environment binds a mode-specific X menu to control+right
+mouse button.
+M-x bibtex-sun-environment binds a mode-specific Sun menu to right
+mouse button.
+
+Fields:
+ address
+ Publisher's address
+ annote
+ Long annotation used for annotated bibliographies (begins sentence)
+ author
+ Name(s) of author(s), in BibTeX name format
+ booktitle
+ Book title when the thing being referenced isn't the whole book.
+ For book entries, the title field should be used instead.
+ chapter
+ Chapter number
+ edition
+ Edition of a book (e.g., ""second"")
+ editor
+ Name(s) of editor(s), in BibTeX name format.
+ If there is also an author field, then the editor field should be
+ for the book or collection that the work appears in
+ howpublished
+ How something strange has been published (begins sentence)
+ institution
+ Sponsoring institution
+ journal
+ Journal name (macros are provided for many)
+ key
+ Alphabetizing and labeling key (needed when no author or editor)
+ month
+ Month (macros are provided)
+ note
+ To help the reader find a reference (begins sentence)
+ number
+ Number of a journal or technical report
+ organization
+ Organization (sponsoring a conference)
+ pages
+ Page number or numbers (use `--' to separate a range)
+ publisher
+ Publisher name
+ school
+ School name (for theses)
+ series
+ The name of a series or set of books.
+ An individual book will will also have it's own title
+ title
+ The title of the thing being referenced
+ type
+ Type of a Techreport (e.g., ""Research Note"") to be used instead of
+ the default ""Technical Report""
+ volume
+ Volume of a journal or multivolume work
+ year
+ Year---should contain only numerals
+---------------------------------------------------------
+Entry to this mode calls the value of bibtex-mode-hook
+if that value is non-nil."
+ (interactive)
+ (kill-all-local-variables)
+ (if (not bibtex-mode-syntax-table)
+ (setq bibtex-mode-syntax-table (copy-syntax-table)))
+ (set-syntax-table bibtex-mode-syntax-table)
+ (modify-syntax-entry ?\$ "$$ ")
+ (modify-syntax-entry ?\% "< ")
+ (modify-syntax-entry ?\f "> ")
+ (modify-syntax-entry ?\n "> ")
+ (modify-syntax-entry ?' "w ")
+ (modify-syntax-entry ?@ "w ")
+ (use-local-map bibtex-mode-map)
+ (setq major-mode 'bibtex-mode)
+
+
+ (setq mode-name "BibTeX")
+ (set-syntax-table bibtex-mode-syntax-table)
+ (setq local-abbrev-table bibtex-mode-abbrev-table)
+ (make-local-variable 'paragraph-start)
+ (setq paragraph-start "^[ \f\n\t]*$")
+
+ (define-key bibtex-mode-map "\t" 'bibtex-find-it)
+ (define-key bibtex-mode-map "\n" 'bibtex-next-position)
+ ;;(define-key bibtex-mode-map "\e[25~" 'bibtex-next-position)
+ (define-key bibtex-mode-map "\C-c\"" 'bibtex-remove-double-quotes)
+ ;;(define-key bibtex-mode-map "\C-c\eOS" 'kill-current-line)
+ (define-key bibtex-mode-map "\C-c\C-k" 'kill-current-line)
+ (define-key bibtex-mode-map "\C-c\C-a" 'bibtex-Article)
+ (define-key bibtex-mode-map "\C-c\C-b" 'bibtex-Book)
+ ;;(define-key bibtex-mode-map "\C-c\C-d" 'bibtex-DEAthesis)
+ (define-key bibtex-mode-map "\C-c\C-c" 'bibtex-InProceedings)
+ (define-key bibtex-mode-map "\C-c\C-i" 'bibtex-InBook)
+ (define-key bibtex-mode-map "\C-ci" 'bibtex-InCollection)
+ (define-key bibtex-mode-map "\C-cI" 'bibtex-InProceedings)
+ (define-key bibtex-mode-map "\C-c\C-m" 'bibtex-Manual)
+ (define-key bibtex-mode-map "\C-cm" 'bibtex-MastersThesis)
+ (define-key bibtex-mode-map "\C-cM" 'bibtex-Misc)
+ (define-key bibtex-mode-map "\C-c\C-o" 'bibtex-remove-opt)
+ (define-key bibtex-mode-map "\C-c\C-p" 'bibtex-PhdThesis)
+ (define-key bibtex-mode-map "\C-cp" 'bibtex-Proceedings)
+ (define-key bibtex-mode-map "\C-c\C-t" 'bibtex-TechReport)
+ (define-key bibtex-mode-map "\C-c\C-s" 'bibtex-string)
+ (define-key bibtex-mode-map "\C-c\C-u" 'bibtex-Unpublished)
+ (define-key bibtex-mode-map "\C-c?" 'describe-mode)
+
+ ; nice alignements
+ (auto-fill-mode 1)
+ (setq left-margin 17)
+
+ (run-hooks 'bibtex-mode-hook))
+
+(defun bibtex-move-outside-of-entry ()
+ "Make sure we are outside of a bib entry"
+ (if (or
+ (= (point) (point-max))
+ (= (point) (point-min))
+ (looking-at "[ \n]*@")
+ )
+ t
+ (progn
+ (backward-paragraph)
+ (forward-paragraph)))
+ (re-search-forward "[ \t\n]*" (point-max) t))
+
+(defun bibtex-entry (entry-type required optional)
+ (bibtex-move-outside-of-entry)
+ (insert (concat "@" entry-type "{,\n\n}\n\n"))
+ (previous-line 3)
+ (insert (mapconcat 'bibtex-make-entry required ",\n"))
+ (if required (insert ",\n"))
+ (insert (mapconcat 'bibtex-make-opt-entry optional ",\n"))
+ (up-list -1)
+ (forward-char 1))
+
+(defun bibtex-make-entry (str)
+ (interactive "s")
+ (concat " " str " = \t"""""))
+
+(defun bibtex-make-opt-entry (str)
+ (interactive "s")
+ (concat " OPT" str " = \t"""""))
+
+(defun bibtex-Article ()
+ (interactive)
+ (bibtex-entry "Article" '("author" "title" "journal" "year")
+ '("volume" "number" "pages" "month" "note")))
+
+(defun bibtex-Book ()
+ (interactive)
+ (bibtex-entry "Book" '("author" "title" "publisher" "year")
+ '("editor" "volume" "series" "address"
+ "edition" "month" "note")))
+
+(defun bibtex-Booklet ()
+ (interactive)
+ (bibtex-entry "Booklet" '("title")
+ '("author" "howpublished" "address" "month" "year" "note")))
+
+;;; France: Dipl\^{o}me d'Etudes Approfondies (similar to Master's)
+;(defun bibtex-DEAthesis ()
+; (interactive)
+; (bibtex-entry "DEAthesis" '("author" "title" "school" "year")
+; '("address" "month" "note")))
+
+(defun bibtex-InBook ()
+ (interactive)
+ (bibtex-entry "InBook" '("author" "title" "chapter" "publisher" "year")
+ '("editor" "pages" "volume" "series" "address"
+ "edition" "month" "note")))
+
+(defun bibtex-InCollection ()
+ (interactive)
+ (bibtex-entry "InCollection" '("author" "title" "booktitle"
+ "publisher" "year")
+ '("editor" "chapter" "pages" "address" "month" "note")))
+
+
+(defun bibtex-InProceedings ()
+ (interactive)
+ (bibtex-entry "InProceedings" '("author" "title" "booktitle" "year")
+ '("editor" "pages" "organization" "publisher"
+ "address" "month" "note")))
+
+(defun bibtex-Manual ()
+ (interactive)
+ (bibtex-entry "Manual" '("title")
+ '("author" "organization" "address" "edition" "year"
+ "month" "note")))
+
+(defun bibtex-MastersThesis ()
+ (interactive)
+ (bibtex-entry "MastersThesis" '("author" "title" "school" "year")
+ '("address" "month" "note")))
+
+(defun bibtex-Misc ()
+ (interactive)
+ (bibtex-entry "Misc" '()
+ '("author" "title" "howpublished" "year" "month" "note")))
+
+(defun bibtex-PhdThesis ()
+ (interactive)
+ (bibtex-entry "PhDThesis" '("author" "title" "school" "year")
+ '("address" "month" "note")))
+
+(defun bibtex-Proceedings ()
+ (interactive)
+ (bibtex-entry "Proceedings" '("title" "year")
+ '("editor" "publisher" "organization"
+ "address" "month" "note")))
+(defun bibtex-TechReport ()
+ (interactive)
+ (bibtex-entry "TechReport" '("author" "title" "institution" "year")
+ '("type" "number" "address" "month" "note")))
+
+
+(defun bibtex-Unpublished ()
+ (interactive)
+ (bibtex-entry "Unpublished" '("author" "title" "note")
+ '("year" "month")))
+
+(defun bibtex-string ()
+ (interactive)
+ (bibtex-move-outside-of-entry)
+ (insert "@string{ = """"}\n")
+ (previous-line 1)
+ (forward-char 8))
+
+(defun bibtex-next-position ()
+ "Finds next position to write in."
+ (interactive)
+ (forward-line 1)
+ (bibtex-find-it))
+
+(defun bibtex-find-it ()
+ (interactive)
+ "Find position on current line (if possible) to add entry text."
+ (beginning-of-line)
+ (let ((beg (point)))
+ (end-of-line)
+ (search-backward "," beg t)
+ (backward-char 1)
+ (if (looking-at """")
+ t
+ (forward-char 1))
+ ))
+
+(defun bibtex-remove-opt ()
+ "Removes the 'OPT' starting optional arguments."
+ (interactive)
+ (beginning-of-line)
+ (forward-char 2)
+ (if (looking-at "OPT")
+ (delete-char 3))
+ (bibtex-find-it))
+
+(defun kill-current-line ()
+ "Kills the current line."
+ (interactive)
+ (beginning-of-line)
+ (kill-line 1))
+
+(defun bibtex-remove-double-quotes ()
+ "Removes """" around string."
+ (interactive)
+ (bibtex-find-it)
+ (let
+ ((here (point))
+ (eol (progn (end-of-line) (point))))
+ (beginning-of-line)
+ (if (search-forward """" eol t)
+ (progn
+ (delete-char -1)
+ (if (search-forward """" eol t)
+ (delete-char -1)
+ ))
+ (goto-char here))
+ )
+ )
+
+
+;;; X window menus for bibtex mode
+
+(defun bibtex-x-help (arg)
+ "Mouse commands for BibTeX mode"
+
+ (let ((selection
+ (x-popup-menu
+ arg
+ '("BibTeX commands"
+ ("Document types"
+ ("article in Conference Proceedings" . bibtex-InProceedings)
+ ("article in journal" . bibtex-Article)
+ ("Book" . bibtex-Book)
+ ("Booklet" . bibtex-Booklet)
+ ("Master's Thesis" . bibtex-MastersThesis)
+ ;;("DEA Thesis" . bibtex-DEAthesis)
+ ("PhD. Thesis" . bibtex-PhdThesis)
+ ("Technical Report" . bibtex-TechReport)
+ ("technical Manual" . bibtex-Manual)
+ ("Conference Proceedings" . bibtex-Proceedings)
+ ("in a Book" . bibtex-InBook)
+ ("in a Collection" . bibtex-InCollection)
+ ("miscellaneous" . bibtex-Misc)
+ ("unpublished" . bibtex-Unpublished)
+ )
+ ("others"
+ ("next field" . bibtex-next-position)
+ ("to end of field" . bibtex-find-it)
+ ("remove OPT" . bibtex-remove-opt)
+ ("remove quotes" . bibtex-remove-double-quotes)
+ ("remove this line" . kill-current-line)
+ ("describe BibTeX mode" . describe-mode)
+ ("string" . bibtex-string))))))
+ (and selection (call-interactively selection))))
+
+(defun bibtex-x-environment ()
+ "Set up X menus for BibTeX mode. Call it as bibtex-mode-hook, or interactively"
+ (interactive)
+ (require 'x-mouse)
+ (define-key mouse-map x-button-c-right 'bibtex-x-help)
+ )
+
+;; Please don't send anything to bug-gnu-emacs about these Sunwindows functions
+;; since we aren't interested. See etc/SUN-SUPPORT for the reasons why
+;; we consider this nothing but a distraction from our work.
+
+(defmenu bibtex-sun-entry-menu
+ ("Article In Conf. Proc."
+ (lambda () (eval-in-window *menu-window* (bibtex-InProceedings))))
+ ("Article In Journal"
+ (lambda () (eval-in-window *menu-window* (bibtex-Article))))
+ ("Book"
+ (lambda () (eval-in-window *menu-window* (bibtex-Book))))
+ ("Booklet"
+ (lambda () (eval-in-window *menu-window* (bibtex-Booklet))))
+ ("Master's Thesis"
+ (lambda () (eval-in-window *menu-window* (bibtex-MastersThesis))))
+ ;;("DEA Thesis" bibtex-DEAthesis)
+ ("PhD. Thesis"
+ (lambda () (eval-in-window *menu-window* (bibtex-PhdThesis))))
+ ("Technical Report"
+ (lambda () (eval-in-window *menu-window* (bibtex-TechReport))))
+ ("Technical Manual"
+ (lambda () (eval-in-window *menu-window* (bibtex-Manual))))
+ ("Conference Proceedings"
+ (lambda () (eval-in-window *menu-window* (bibtex-Proceedings))))
+ ("In A Book"
+ (lambda () (eval-in-window *menu-window* (bibtex-InBook))))
+ ("In A Collection"
+ (lambda () (eval-in-window *menu-window* (bibtex-InCollection))))
+ ("Miscellaneous"
+ (lambda () (eval-in-window *menu-window* (bibtex-Misc))))
+ ("Unpublished"
+ (lambda () (eval-in-window *menu-window* (bibtex-Unpublished)))))
+
+(defmenu bibtex-sun-menu
+ ("BibTeX menu")
+ ("add entry" . bibtex-sun-entry-menu)
+ ("add string"
+ (lambda () (eval-in-window *menu-window* (bibtex-string))))
+ ;("next field" bibtex-next-position)
+ ;("to end of field" bibtex-find-it)
+; ("remove OPT"
+; (lambda () (eval-in-window *menu-window* (bibtex-remove-opt))))
+; ("remove quotes"
+; (lambda () (eval-in-window *menu-window* (bibtex-remove-double-quotes))))
+; ("remove this line"
+; (lambda () (eval-in-window *menu-window* (kill-current-line))))
+ ("describe BibTeX mode"
+ (lambda () (eval-in-window *menu-window* (describe-mode))))
+ ("Main Emacs menu" . emacs-menu))
+
+(defun bibtex-sun-menu-eval (window x y)
+ "Pop-up menu of BibTeX commands."
+ (sun-menu-evaluate window (1+ x) (1- y) 'bibtex-sun-menu))
+
+(defun bibtex-sun-environment ()
+ "Set up sun menus for BibTeX mode. Call it as bibtex-mode-hook, or interactively"
+ (interactive)
+ (local-set-mouse '(text right) 'bibtex-sun-menu-eval))
+
diff --git a/lisp/bibtex.elc b/lisp/bibtex.elc
new file mode 100644
index 00000000000..7b21ec06cd6
--- /dev/null
+++ b/lisp/bibtex.elc
Binary files differ
diff --git a/lisp/blackbox.el b/lisp/blackbox.el
new file mode 100644
index 00000000000..938840fe205
--- /dev/null
+++ b/lisp/blackbox.el
@@ -0,0 +1,229 @@
+; Blackbox game in Emacs Lisp
+
+; by F. Thomas May
+; uw-nsr!uw-warp!tom@beaver.cs.washington.edu
+
+(defvar blackbox-mode-map nil "")
+
+(if blackbox-mode-map
+ ()
+ (setq blackbox-mode-map (make-keymap))
+ (suppress-keymap blackbox-mode-map t)
+ (define-key blackbox-mode-map "\C-f" 'bb-right)
+ (define-key blackbox-mode-map "\C-b" 'bb-left)
+ (define-key blackbox-mode-map "\C-p" 'bb-up)
+ (define-key blackbox-mode-map "\C-n" 'bb-down)
+ (define-key blackbox-mode-map "\C-e" 'bb-eol)
+ (define-key blackbox-mode-map "\C-a" 'bb-bol)
+ (define-key blackbox-mode-map " " 'bb-romp)
+ (define-key blackbox-mode-map "\C-m" 'bb-done))
+
+
+;; Blackbox mode is suitable only for specially formatted data.
+(put 'blackbox-mode 'mode-class 'special)
+
+(defun blackbox-mode ()
+ "Major mode for playing blackbox.
+
+SPC -- send in a ray from point, or toggle a ball
+RET -- end game and get score
+
+Precisely,\\{blackbox-mode-map}"
+ (interactive)
+ (kill-all-local-variables)
+ (use-local-map blackbox-mode-map)
+ (setq truncate-lines t)
+ (setq major-mode 'blackbox-mode)
+ (setq mode-name "Blackbox"))
+
+(defun blackbox (num)
+ "Play blackbox. Arg is number of balls."
+ (interactive "P")
+ (switch-to-buffer "*Blackbox*")
+ (blackbox-mode)
+ (setq buffer-read-only t)
+ (buffer-flush-undo (current-buffer))
+ (setq bb-board (bb-init-board (or num 4)))
+ (setq bb-balls-placed nil)
+ (setq bb-x -1)
+ (setq bb-y -1)
+ (setq bb-score 0)
+ (setq bb-detour-count 0)
+ (bb-insert-board)
+ (bb-goto (cons bb-x bb-y)))
+
+(defun bb-init-board (num-balls)
+ (random t)
+ (let (board pos)
+ (while (>= (setq num-balls (1- num-balls)) 0)
+ (while
+ (progn
+ (setq pos (cons (logand (random) 7) (logand (random) 7)))
+ (bb-member pos board)))
+ (setq board (cons pos board)))
+ board))
+
+(defun bb-insert-board ()
+ (let (i (buffer-read-only nil))
+ (erase-buffer)
+ (insert " \n")
+ (setq i 8)
+ (while (>= (setq i (1- i)) 0)
+ (insert " - - - - - - - - \n"))
+ (insert " \n")))
+
+(defun bb-right ()
+ (interactive)
+ (if (= bb-x 8)
+ ()
+ (forward-char 2)
+ (setq bb-x (1+ bb-x))))
+
+(defun bb-left ()
+ (interactive)
+ (if (= bb-x -1)
+ ()
+ (backward-char 2)
+ (setq bb-x (1- bb-x))))
+
+(defun bb-up ()
+ (interactive)
+ (if (= bb-y -1)
+ ()
+ (previous-line 1)
+ (setq bb-y (1- bb-y))))
+
+(defun bb-down ()
+ (interactive)
+ (if (= bb-y 8)
+ ()
+ (next-line 1)
+ (setq bb-y (1+ bb-y))))
+
+(defun bb-eol ()
+ (interactive)
+ (setq bb-x 8)
+ (bb-goto (cons bb-x bb-y)))
+
+(defun bb-bol ()
+ (interactive)
+ (setq bb-x -1)
+ (bb-goto (cons bb-x bb-y)))
+
+(defun bb-romp ()
+ (interactive)
+ (cond
+ ((and
+ (or (= bb-x -1) (= bb-x 8))
+ (or (= bb-y -1) (= bb-y 8))))
+ ((bb-outside-box bb-x bb-y)
+ (bb-trace-ray bb-x bb-y))
+ (t
+ (bb-place-ball bb-x bb-y))))
+
+(defun bb-place-ball (x y)
+ (let ((coord (cons x y)))
+ (cond
+ ((bb-member coord bb-balls-placed)
+ (setq bb-balls-placed (bb-delete coord bb-balls-placed))
+ (bb-update-board "-"))
+ (t
+ (setq bb-balls-placed (cons coord bb-balls-placed))
+ (bb-update-board "O")))))
+
+(defun bb-trace-ray (x y)
+ (let ((result (bb-trace-ray-2
+ t
+ x
+ (cond
+ ((= x -1) 1)
+ ((= x 8) -1)
+ (t 0))
+ y
+ (cond
+ ((= y -1) 1)
+ ((= y 8) -1)
+ (t 0)))))
+ (cond
+ ((eq result 'hit)
+ (bb-update-board "H")
+ (setq bb-score (1+ bb-score)))
+ ((equal result (cons x y))
+ (bb-update-board "R")
+ (setq bb-score (1+ bb-score)))
+ (t
+ (setq bb-detour-count (1+ bb-detour-count))
+ (bb-update-board (format "%d" bb-detour-count))
+ (save-excursion
+ (bb-goto result)
+ (bb-update-board (format "%d" bb-detour-count)))
+ (setq bb-score (+ bb-score 2))))))
+
+(defun bb-trace-ray-2 (first x dx y dy)
+ (cond
+ ((and (not first)
+ (bb-outside-box x y))
+ (cons x y))
+ ((bb-member (cons (+ x dx) (+ y dy)) bb-board)
+ 'hit)
+ ((bb-member (cons (+ x dx dy) (+ y dy dx)) bb-board)
+ (bb-trace-ray-2 nil x (- dy) y (- dx)))
+ ((bb-member (cons (+ x dx (- dy)) (+ y dy (- dx))) bb-board)
+ (bb-trace-ray-2 nil x dy y dx))
+ (t
+ (bb-trace-ray-2 nil (+ x dx) dx (+ y dy) dy))))
+
+(defun bb-done ()
+ (interactive)
+ (let (bogus-balls)
+ (if (not (= (length bb-balls-placed) (length bb-board)))
+ (message "Spud! You have only %d balls in the box."
+ (length bb-balls-placed))
+ (setq bogus-balls (bb-show-bogus-balls bb-balls-placed bb-board))
+ (if (= bogus-balls 0)
+ (message "Right! Your score is %d." bb-score)
+ (setq bb-score (+ bb-score (* 5 bogus-balls)))
+ (message "Veg! You missed %d balls. Your score is %d."
+ bogus-balls bb-score))
+ (bb-goto '(-1 . -1)))))
+
+(defun bb-show-bogus-balls (balls-placed board)
+ (bb-show-bogus-balls-2 balls-placed board "x")
+ (bb-show-bogus-balls-2 board balls-placed "o"))
+
+(defun bb-show-bogus-balls-2 (list-1 list-2 c)
+ (cond
+ ((null list-1)
+ 0)
+ ((bb-member (car list-1) list-2)
+ (bb-show-bogus-balls-2 (cdr list-1) list-2 c))
+ (t
+ (bb-goto (car list-1))
+ (bb-update-board c)
+ (1+ (bb-show-bogus-balls-2 (cdr list-1) list-2 c)))))
+
+(defun bb-outside-box (x y)
+ (or (= x -1) (= x 8) (= y -1) (= y 8)))
+
+(defun bb-goto (pos)
+ (goto-char (+ (* (car pos) 2) (* (cdr pos) 22) 26)))
+
+(defun bb-update-board (c)
+ (let ((buffer-read-only nil))
+ (backward-char (1- (length c)))
+ (delete-char (length c))
+ (insert c)
+ (backward-char 1)))
+
+(defun bb-member (elt list)
+ "Returns non-nil if ELT is an element of LIST. Comparison done with equal."
+ (eval (cons 'or (mapcar (function (lambda (x) (equal x elt))) list))))
+
+(defun bb-delete (item list)
+ "Deletes ITEM from LIST and returns a copy."
+ (cond
+ ((equal item (car list)) (cdr list))
+ (t (cons (car list) (bb-delete item (cdr list))))))
+
+
+
diff --git a/lisp/blackbox.elc b/lisp/blackbox.elc
new file mode 100644
index 00000000000..c2daf947c26
--- /dev/null
+++ b/lisp/blackbox.elc
Binary files differ
diff --git a/lisp/buff-menu.el b/lisp/buff-menu.el
index 77923774da7..101555c9db0 100644
--- a/lisp/buff-menu.el
+++ b/lisp/buff-menu.el
@@ -1,5 +1,5 @@
;; Buffer menu main function and support functions.
-;; Copyright (C) 1985, 1986, 1987 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 1986, 1987, 1990 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -39,14 +39,11 @@
(define-key Buffer-menu-mode-map "\C-k" 'Buffer-menu-delete)
(define-key Buffer-menu-mode-map "x" 'Buffer-menu-execute)
(define-key Buffer-menu-mode-map " " 'next-line)
- (define-key Buffer-menu-mode-map "n" 'next-line)
- (define-key Buffer-menu-mode-map "p" 'previous-line)
(define-key Buffer-menu-mode-map "\177" 'Buffer-menu-backup-unmark)
(define-key Buffer-menu-mode-map "~" 'Buffer-menu-not-modified)
(define-key Buffer-menu-mode-map "?" 'describe-mode)
(define-key Buffer-menu-mode-map "u" 'Buffer-menu-unmark)
- (define-key Buffer-menu-mode-map "m" 'Buffer-menu-mark)
- (define-key Buffer-menu-mode-map "t" 'Buffer-menu-visit-tags-table))
+ (define-key Buffer-menu-mode-map "m" 'Buffer-menu-mark))
;; Buffer Menu mode is suitable only for specially formatted data.
(put 'Buffer-menu-mode 'mode-class 'special)
@@ -55,24 +52,24 @@
"Major mode for editing a list of buffers.
Each line describes one of the buffers in Emacs.
Letters do not insert themselves; instead, they are commands.
-\\<Buffer-menu-mode-map>
-\\[Buffer-menu-mark] -- mark buffer to be displayed.
-\\[Buffer-menu-select] -- select buffer of line point is on.
+m -- mark buffer to be displayed.
+q -- select buffer of line point is on.
Also show buffers marked with m in other windows.
-\\[Buffer-menu-1-window] -- select that buffer in full-screen window.
-\\[Buffer-menu-2-window] -- select that buffer in one window,
+1 -- select that buffer in full-screen window.
+2 -- select that buffer in one window,
together with buffer selected before this one in another window.
-\\[Buffer-menu-this-window] -- select that buffer in place of the buffer menu buffer.
-\\[Buffer-menu-other-window] -- select that buffer in another window,
+f -- select that buffer in place of the buffer menu buffer.
+o -- select that buffer in another window,
so the buffer menu buffer remains visible in its window.
-\\[Buffer-menu-visit-tags-table] -- visit-tags-table this buffer.
-\\[Buffer-menu-not-modified] -- clear modified-flag on that buffer.
-\\[Buffer-menu-save] -- mark that buffer to be saved, and move down.
-\\[Buffer-menu-delete] -- mark that buffer to be deleted, and move down.
-\\[Buffer-menu-delete-backwards] -- mark that buffer to be deleted, and move up.
-\\[Buffer-menu-execute] -- delete or save marked buffers.
-\\[Buffer-menu-unmark] -- remove all kinds of marks from current line.
-\\[Buffer-menu-backup-unmark] -- back up a line and remove marks."
+~ -- clear modified-flag on that buffer.
+s -- mark that buffer to be saved, and move down.
+d or k -- mark that buffer to be deleted, and move down.
+C-d -- mark that buffer to be deleted, and move up.
+x -- delete or save marked buffers.
+u -- remove all kinds of marks from current line.
+Delete -- back up a line and remove marks.
+
+Precisely,\\{Buffer-menu-mode-map}"
(kill-all-local-variables)
(use-local-map Buffer-menu-mode-map)
(setq truncate-lines t)
@@ -112,7 +109,7 @@ Type q immediately to make the buffer menu go away."
"Commands: d, s, x; 1, 2, m, u, q; delete; ~; ? for help."))
(defun Buffer-menu-mark ()
- "Mark buffer on this line for being displayed by \\<Buffer-menu-mode-map>\\[Buffer-menu-select] command."
+ "Mark buffer on this line for being displayed by \\[Buffer-menu-select] command."
(interactive)
(beginning-of-line)
(if (looking-at " [-M]")
@@ -144,7 +141,7 @@ Type q immediately to make the buffer menu go away."
(forward-line -1))
(defun Buffer-menu-delete ()
- "Mark buffer on this line to be deleted by \\<Buffer-menu-mode-map>\\[Buffer-menu-execute] command."
+ "Mark buffer on this line to be deleted by \\[Buffer-menu-execute] command."
(interactive)
(beginning-of-line)
(if (looking-at " [-M]") ;header lines
@@ -155,7 +152,7 @@ Type q immediately to make the buffer menu go away."
(forward-line 1))))
(defun Buffer-menu-delete-backwards ()
- "Mark buffer on this line to be deleted by \\<Buffer-menu-mode-map>\\[Buffer-menu-execute] command
+ "Mark buffer on this line to be deleted by \\[Buffer-menu-execute] command
and then move up one line"
(interactive)
(Buffer-menu-delete)
@@ -163,7 +160,7 @@ and then move up one line"
(if (looking-at " [-M]") (forward-line 1)))
(defun Buffer-menu-save ()
- "Mark buffer on this line to be saved by \\<Buffer-menu-mode-map>\\[Buffer-menu-execute] command."
+ "Mark buffer on this line to be saved by \\[Buffer-menu-execute] command."
(interactive)
(beginning-of-line)
(forward-char 1)
@@ -189,7 +186,7 @@ and then move up one line"
(insert ? )))))
(defun Buffer-menu-execute ()
- "Save and/or delete buffers marked with \\<Buffer-menu-mode-map>\\[Buffer-menu-save] or \\<Buffer-menu-mode-map>\\[Buffer-menu-delete] commands."
+ "Save and/or delete buffers marked with \\[Buffer-menu-save] or \\[Buffer-menu-delete] commands."
(interactive)
(save-excursion
(goto-char (point-min))
@@ -221,8 +218,8 @@ and then move up one line"
(forward-char -1))))))
(defun Buffer-menu-select ()
- "Select this line's buffer; also display buffers marked with `>'.
-You can mark buffers with the \\<Buffer-menu-mode-map>\\[Buffer-menu-mark] command."
+ "Select this line's buffer; also display buffers marked with \">\".
+You can mark buffers with the \\[Buffer-menu-mark] command."
(interactive)
(let ((buff (Buffer-menu-buffer t))
(menu (current-buffer))
@@ -247,14 +244,6 @@ You can mark buffers with the \\<Buffer-menu-mode-map>\\[Buffer-menu-mark] comma
(switch-to-buffer (car others))
(setq others (cdr others)))
(other-window 1))) ;back to the beginning!
-
-(defun Buffer-menu-visit-tags-table ()
- "Visit the tags table in the buffer on this line. See `visit-tags-table'."
- (interactive)
- (let ((file (buffer-file-name (Buffer-menu-buffer t))))
- (if file
- (visit-tags-table file)
- (error "Specified buffer has no file"))))
(defun Buffer-menu-1-window ()
"Select this line's buffer, alone, in full screen."
diff --git a/lisp/buff-menu.elc b/lisp/buff-menu.elc
new file mode 100644
index 00000000000..eebb3eb30bd
--- /dev/null
+++ b/lisp/buff-menu.elc
Binary files differ
diff --git a/lisp/bytecomp.el b/lisp/bytecomp.el
new file mode 100644
index 00000000000..8e7bd46e07c
--- /dev/null
+++ b/lisp/bytecomp.el
@@ -0,0 +1,1165 @@
+;; Compilation of Lisp code into byte code.
+;; Copyright (C) 1985, 1986, 1987 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 1, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+(provide 'byte-compile)
+
+(defvar byte-compile-constnum -1
+ "Transfer vector index of last constant allocated.")
+(defvar byte-compile-constants nil
+ "Alist describing contents to put in transfer vector.
+Each element is (CONTENTS . INDEX)")
+(defvar byte-compile-macro-environment nil
+ "Alist of (MACRONAME . DEFINITION) macros defined in the file
+which is being compiled.")
+(defvar byte-compile-pc 0
+ "Index in byte string to store next opcode at.")
+(defvar byte-compile-output nil
+ "Alist describing contents to put in byte code string.
+Each element is (INDEX . VALUE)")
+(defvar byte-compile-depth 0
+ "Current depth of execution stack.")
+(defvar byte-compile-maxdepth 0
+ "Maximum depth of execution stack.")
+
+(defconst byte-varref 8
+ "Byte code opcode for variable reference.")
+(defconst byte-varset 16
+ "Byte code opcode for setting a variable.")
+(defconst byte-varbind 24
+ "Byte code opcode for binding a variable.")
+(defconst byte-call 32
+ "Byte code opcode for calling a function.")
+(defconst byte-unbind 40
+ "Byte code opcode for unbinding special bindings.")
+
+(defconst byte-constant 192
+ "Byte code opcode for reference to a constant.")
+(defconst byte-constant-limit 64
+ "Maximum index usable in byte-constant opcode.")
+
+(defconst byte-constant2 129
+ "Byte code opcode for reference to a constant with vector index >= 0100.")
+
+(defconst byte-goto 130
+ "Byte code opcode for unconditional jump")
+
+(defconst byte-goto-if-nil 131
+ "Byte code opcode for pop value and jump if it's nil.")
+
+(defconst byte-goto-if-not-nil 132
+ "Byte code opcode for pop value and jump if it's not nil.")
+
+(defconst byte-goto-if-nil-else-pop 133
+ "Byte code opcode for examine top-of-stack, jump and don't pop it if it's nil,
+otherwise pop it.")
+
+(defconst byte-goto-if-not-nil-else-pop 134
+ "Byte code opcode for examine top-of-stack, jump and don't pop it if it's not nil,
+otherwise pop it.")
+
+(defconst byte-return 135
+ "Byte code opcode for pop value and return it from byte code interpreter.")
+
+(defconst byte-discard 136
+ "Byte code opcode to discard one value from stack.")
+
+(defconst byte-dup 137
+ "Byte code opcode to duplicate the top of the stack.")
+
+(defconst byte-save-excursion 138
+ "Byte code opcode to make a binding to record the buffer, point and mark.")
+
+(defconst byte-save-window-excursion 139
+ "Byte code opcode to make a binding to record entire window configuration.")
+
+(defconst byte-save-restriction 140
+ "Byte code opcode to make a binding to record the current buffer clipping restrictions.")
+
+(defconst byte-catch 141
+ "Byte code opcode for catch. Takes, on stack, the tag and an expression for the body.")
+
+(defconst byte-unwind-protect 142
+ "Byte code opcode for unwind-protect. Takes, on stack, an expression for the body
+and an expression for the unwind-action.")
+
+(defconst byte-condition-case 143
+ "Byte code opcode for condition-case. Takes, on stack, the variable to bind,
+an expression for the body, and a list of clauses.")
+
+(defconst byte-temp-output-buffer-setup 144
+ "Byte code opcode for entry to with-output-to-temp-buffer.
+Takes, on stack, the buffer name.
+Binds standard-output and does some other things.
+Returns with temp buffer on the stack in place of buffer name.")
+
+(defconst byte-temp-output-buffer-show 145
+ "Byte code opcode for exit from with-output-to-temp-buffer.
+Expects the temp buffer on the stack underneath value to return.
+Pops them both, then pushes the value back on.
+Unbinds standard-output and makes the temp buffer visible.")
+
+(defconst byte-nth 56)
+(defconst byte-symbolp 57)
+(defconst byte-consp 58)
+(defconst byte-stringp 59)
+(defconst byte-listp 60)
+(defconst byte-eq 61)
+(defconst byte-memq 62)
+(defconst byte-not 63)
+(defconst byte-car 64)
+(defconst byte-cdr 65)
+(defconst byte-cons 66)
+(defconst byte-list1 67)
+(defconst byte-list2 68)
+(defconst byte-list3 69)
+(defconst byte-list4 70)
+(defconst byte-length 71)
+(defconst byte-aref 72)
+(defconst byte-aset 73)
+(defconst byte-symbol-value 74)
+(defconst byte-symbol-function 75)
+(defconst byte-set 76)
+(defconst byte-fset 77)
+(defconst byte-get 78)
+(defconst byte-substring 79)
+(defconst byte-concat2 80)
+(defconst byte-concat3 81)
+(defconst byte-concat4 82)
+(defconst byte-sub1 83)
+(defconst byte-add1 84)
+(defconst byte-eqlsign 85)
+(defconst byte-gtr 86)
+(defconst byte-lss 87)
+(defconst byte-leq 88)
+(defconst byte-geq 89)
+(defconst byte-diff 90)
+(defconst byte-negate 91)
+(defconst byte-plus 92)
+(defconst byte-max 93)
+(defconst byte-min 94)
+
+(defconst byte-point 96)
+;(defconst byte-mark 97) no longer generated -- lisp code shouldn't call this very frequently
+(defconst byte-goto-char 98)
+(defconst byte-insert 99)
+(defconst byte-point-max 100)
+(defconst byte-point-min 101)
+(defconst byte-char-after 102)
+(defconst byte-following-char 103)
+(defconst byte-preceding-char 104)
+(defconst byte-current-column 105)
+(defconst byte-indent-to 106)
+;(defconst byte-scan-buffer 107) no longer generated
+(defconst byte-eolp 108)
+(defconst byte-eobp 109)
+(defconst byte-bolp 110)
+(defconst byte-bobp 111)
+(defconst byte-current-buffer 112)
+(defconst byte-set-buffer 113)
+(defconst byte-read-char 114)
+;(defconst byte-set-mark 115) ;obsolete
+(defconst byte-interactive-p 116)
+
+(defun byte-recompile-directory (directory &optional arg)
+ "Recompile every .el file in DIRECTORY that needs recompilation.
+This is if a .elc file exists but is older than the .el file.
+If the .elc file does not exist, offer to compile the .el file
+only if a prefix argument has been specified."
+ (interactive "DByte recompile directory: \nP")
+ (save-some-buffers)
+ (setq directory (expand-file-name directory))
+ (let ((files (directory-files directory nil "\\.el\\'"))
+ (count 0)
+ source dest)
+ (while files
+ (if (and (not (auto-save-file-name-p (car files)))
+ (setq source (expand-file-name (car files) directory))
+ (setq dest (concat (file-name-sans-versions source) "c"))
+ (if (file-exists-p dest)
+ (file-newer-than-file-p source dest)
+ (and arg (y-or-n-p (concat "Compile " source "? ")))))
+ (progn (byte-compile-file source)
+ (setq count (1+ count))))
+ (setq files (cdr files)))
+ (message "Done (Total of %d file%s compiled)"
+ count (if (= count 1) "" "s"))))
+
+(defun byte-compile-file (filename)
+ "Compile a file of Lisp code named FILENAME into a file of byte code.
+The output file's name is made by appending \"c\" to the end of FILENAME."
+ (interactive "fByte compile file: ")
+ ;; Expand now so we get the current buffer's defaults
+ (setq filename (expand-file-name filename))
+ (message "Compiling %s..." filename)
+ (let ((inbuffer (get-buffer-create " *Compiler Input*"))
+ (outbuffer (get-buffer-create " *Compiler Output*"))
+ (byte-compile-macro-environment nil)
+ (case-fold-search nil)
+ sexp)
+ (save-excursion
+ (set-buffer inbuffer)
+ (erase-buffer)
+ (insert-file-contents filename)
+ (goto-char 1)
+ (set-buffer outbuffer)
+ ;; Avoid running hooks; all we really want is the syntax table.
+ (let (emacs-lisp-mode-hook)
+ (emacs-lisp-mode))
+ (erase-buffer)
+ (while (save-excursion
+ (set-buffer inbuffer)
+ (while (progn (skip-chars-forward " \t\n\^l")
+ (looking-at ";"))
+ (forward-line 1))
+ (not (eobp)))
+ (setq sexp (read inbuffer))
+ (print (byte-compile-file-form sexp) outbuffer))
+ (set-buffer outbuffer)
+ (goto-char 1)
+ ;; In each defun or autoload, if there is a doc string,
+ ;; put a backslash-newline at the front of it.
+ (while (search-forward "\n(" nil t)
+ (cond ((looking-at "defun \\|autoload ")
+ (forward-sexp 3)
+ (skip-chars-forward " ")
+ (if (looking-at "\"")
+ (progn (forward-char 1)
+ (insert "\\\n"))))))
+ (goto-char 1)
+ ;; In each defconst or defvar, if there is a doc string
+ ;; and it starts on the same line as the form begins
+ ;; (i.e. if there is no newline in a string in the initial value)
+ ;; then put in backslash-newline at the start of the doc string.
+ (while (search-forward "\n(" nil t)
+ (if (looking-at "defvar \\|defconst ")
+ (let ((this-line (1- (point))))
+ ;;Go to end of initial value expression
+ (if (condition-case ()
+ (progn (forward-sexp 3) t)
+ (error nil))
+ (progn
+ (skip-chars-forward " ")
+ (and (eq this-line
+ (save-excursion (beginning-of-line) (point)))
+ (looking-at "\"")
+ (progn (forward-char 1)
+ (insert "\\\n"))))))))
+ (let ((vms-stmlf-recfm t))
+ (write-region 1 (point-max)
+ (concat (file-name-sans-versions filename) "c")))
+ (kill-buffer (current-buffer))
+ (kill-buffer inbuffer)))
+ t)
+
+
+(defun byte-compile-file-form (form)
+ (cond ((not (listp form))
+ form)
+ ((memq (car form) '(defun defmacro))
+ (let* ((name (car (cdr form)))
+ (tem (assq name byte-compile-macro-environment)))
+ (if (eq (car form) 'defun)
+ (progn
+ (message "Compiling %s (%s)..." filename (nth 1 form))
+ (cond (tem (setcdr tem nil))
+ ((and (fboundp name)
+ (eq (car-safe (symbol-function name)) 'macro))
+ ;; shadow existing macro definition
+ (setq byte-compile-macro-environment
+ (cons (cons name nil)
+ byte-compile-macro-environment))))
+ (prog1 (cons 'defun (byte-compile-lambda (cdr form)))
+ (if (not noninteractive)
+ (message "Compiling %s..." filename))))
+ ;; defmacro
+ (if tem
+ (setcdr tem (cons 'lambda (cdr (cdr form))))
+ (setq byte-compile-macro-environment
+ (cons (cons name (cons 'lambda (cdr (cdr form))))
+ byte-compile-macro-environment)))
+ (cons 'defmacro (byte-compile-lambda (cdr form))))))
+ ((eq (car form) 'require)
+ (eval form)
+ form)
+ (t form)))
+
+(defun byte-compile (funname)
+ "Byte-compile the definition of function FUNNAME (a symbol)."
+ (if (and (fboundp funname)
+ (eq (car-safe (symbol-function funname)) 'lambda))
+ (fset funname (byte-compile-lambda (symbol-function funname)))))
+
+(defun byte-compile-lambda (fun)
+ (let* ((bodyptr (cdr fun))
+ (int (assq 'interactive (cdr bodyptr)))
+ newbody)
+ ;; Skip doc string.
+ (if (and (cdr (cdr bodyptr)) (stringp (car (cdr bodyptr))))
+ (setq bodyptr (cdr bodyptr)))
+ (setq newbody (list (byte-compile-top-level
+ (cons 'progn (cdr bodyptr)))))
+ (if int
+ (setq newbody (cons (if (or (stringp (car (cdr int)))
+ (null (car (cdr int))))
+ int
+ (list 'interactive
+ (byte-compile-top-level (car (cdr int)))))
+ newbody)))
+ (if (not (eq bodyptr (cdr fun)))
+ (setq newbody (cons (nth 2 fun) newbody)))
+ (cons (car fun) (cons (car (cdr fun)) newbody))))
+
+(defun byte-compile-top-level (form)
+ (let ((byte-compile-constants nil)
+ (byte-compile-constnum nil)
+ (byte-compile-pc 0)
+ (byte-compile-depth 0)
+ (byte-compile-maxdepth 0)
+ (byte-compile-output nil)
+ (byte-compile-string nil)
+ (byte-compile-vector nil))
+ (let (vars temp (i -1))
+ (setq temp (byte-compile-find-vars form))
+ (setq form (car temp))
+ (setq vars (nreverse (cdr temp)))
+ (while vars
+ (setq i (1+ i))
+ (setq byte-compile-constants (cons (cons (car vars) i)
+ byte-compile-constants))
+ (setq vars (cdr vars)))
+ (setq byte-compile-constnum i))
+ (byte-compile-form form)
+ (byte-compile-out 'byte-return 0)
+ (setq byte-compile-vector (make-vector (1+ byte-compile-constnum)
+ nil))
+ (while byte-compile-constants
+ (aset byte-compile-vector (cdr (car byte-compile-constants))
+ (car (car byte-compile-constants)))
+ (setq byte-compile-constants (cdr byte-compile-constants)))
+ (setq byte-compile-string (make-string byte-compile-pc 0))
+ (while byte-compile-output
+ (aset byte-compile-string (car (car byte-compile-output))
+ (cdr (car byte-compile-output)))
+ (setq byte-compile-output (cdr byte-compile-output)))
+ (list 'byte-code byte-compile-string
+ byte-compile-vector byte-compile-maxdepth)))
+
+;; Expand all macros in FORM and find all variables it uses.
+;; Return a pair (EXPANDEDFORM . VARS)
+;; VARS is ordered with the variables encountered earliest
+;; at the end.
+;; The body and cases of a condition-case, and the body of a catch,
+;; are not scanned; variables used in them are not reported,
+;; and they are not macroexpanded. This is because they will
+;; be compiled separately when encountered during the main
+;; compilation pass.
+(defun byte-compile-find-vars (form)
+ (let ((all-vars nil))
+ (cons (byte-compile-find-vars-1 form)
+ all-vars)))
+
+;; Walk FORM, making sure all variables it uses are in ALL-VARS,
+;; and also expanding macros.
+;; Return the result of expanding all macros in FORM.
+;; This is a copy; FORM itself is not altered.
+(defun byte-compile-find-vars-1 (form)
+ (cond ((symbolp form)
+ (if (not (memq form all-vars))
+ (setq all-vars (cons form all-vars)))
+ form)
+ ((or (not (consp form)) (eq (car form) 'quote))
+ form)
+ ((memq (car form) '(let let*))
+ (let* ((binds (copy-sequence (car (cdr form))))
+ (body (cdr (cdr form)))
+ (tail binds))
+ (while tail
+ (if (symbolp (car tail))
+ (if (not (memq (car tail) all-vars))
+ (setq all-vars (cons (car tail) all-vars)))
+ (if (consp (car tail))
+ (progn
+ (if (not (memq (car (car tail)) all-vars))
+ (setq all-vars (cons (car (car tail)) all-vars)))
+ (setcar tail
+ (list (car (car tail))
+ (byte-compile-find-vars-1 (car (cdr (car tail)))))))))
+ (setq tail (cdr tail)))
+ (cons (car form)
+ (cons binds
+ (mapcar 'byte-compile-find-vars-1 body)))))
+ ((or (eq (car form) 'function)
+ ;; Because condition-case is compiled by breaking out
+ ;; all its subexpressions and compiling them separately,
+ ;; we regard it here as containing nothing but constants.
+ (eq (car form) 'condition-case))
+ form)
+ ((eq (car form) 'catch)
+ ;; catch is almost like condition case, but we
+ ;; treat its first argument normally.
+ (cons 'catch
+ (cons (byte-compile-find-vars-1 (nth 1 form))
+ (nthcdr 2 form))))
+ ((eq (car form) 'cond)
+ (let* ((clauses (copy-sequence (cdr form)))
+ (tail clauses))
+ (while tail
+ (setcar tail (mapcar 'byte-compile-find-vars-1 (car tail)))
+ (setq tail (cdr tail)))
+ (cons 'cond clauses)))
+ ((not (eq form (setq form (macroexpand form byte-compile-macro-environment))))
+ (byte-compile-find-vars-1 form))
+ ((symbolp (car form))
+ (cons (car form) (mapcar 'byte-compile-find-vars-1 (cdr form))))
+ (t (mapcar 'byte-compile-find-vars-1 form))))
+
+;; This is the recursive entry point for compiling each subform of an expression.
+
+;; Note that handler functions SHOULD NOT increment byte-compile-depth
+;; for the values they are returning! That is done on return here.
+;; Handlers should make sure that the depth on exit is the same as
+;; it was when the handler was called.
+
+(defun byte-compile-form (form)
+ (setq form (macroexpand form byte-compile-macro-environment))
+ (cond ((eq form 'nil)
+ (byte-compile-constant form))
+ ((eq form 't)
+ (byte-compile-constant form))
+ ((symbolp form)
+ (byte-compile-variable-ref 'byte-varref form))
+ ((not (consp form))
+ (byte-compile-constant form))
+ ((not (symbolp (car form)))
+ (if (eq (car-safe (car form)) 'lambda)
+ (let ((vars (nth 1 (car form)))
+ (vals (cdr form))
+ result)
+ (while vars
+ (setq result (cons (list (car vars) (car vals)) result))
+ (setq vars (cdr vars) vals (cdr vals)))
+ (byte-compile-form
+ (cons 'let (cons (nreverse result) (cdr (cdr (car form)))))))
+ (byte-compile-normal-call form)))
+ (t
+ (let ((handler (get (car form) 'byte-compile)))
+ (if handler
+ (funcall handler form)
+ (byte-compile-normal-call form)))))
+ (setq byte-compile-maxdepth
+ (max byte-compile-maxdepth
+ (setq byte-compile-depth (1+ byte-compile-depth)))))
+
+(defun byte-compile-normal-call (form)
+ (byte-compile-push-constant (car form))
+ (let ((copy (cdr form)))
+ (while copy (byte-compile-form (car copy)) (setq copy (cdr copy))))
+ (byte-compile-out 'byte-call (length (cdr form)))
+ (setq byte-compile-depth (- byte-compile-depth (length (cdr form)))))
+
+(defun byte-compile-variable-ref (base-op var)
+ (let ((data (assq var byte-compile-constants)))
+ (if data
+ (byte-compile-out base-op (cdr data))
+ (error (format "Variable %s seen on pass 2 of byte compiler but not pass 1"
+ (prin1-to-string var))))))
+
+;; Use this when the value of a form is a constant,
+;; because byte-compile-depth will be incremented accordingly
+;; on return to byte-compile-form, so it should not be done by the handler.
+(defun byte-compile-constant (const)
+ (let ((data (if (stringp const)
+ (assoc const byte-compile-constants)
+ (assq const byte-compile-constants))))
+ (if data
+ (byte-compile-out-const (cdr data))
+ (setq byte-compile-constants
+ (cons (cons const (setq byte-compile-constnum (1+ byte-compile-constnum)))
+ byte-compile-constants))
+ (byte-compile-out-const byte-compile-constnum))))
+
+;; Use this for a constant that is not the value of its containing form.
+;; Note that the calling function must explicitly decrement byte-compile-depth
+;; (or perhaps call byte-compile-discard to do so)
+;; for the word pushed by this function.
+(defun byte-compile-push-constant (const)
+ (byte-compile-constant const)
+ (setq byte-compile-maxdepth
+ (max byte-compile-maxdepth
+ (setq byte-compile-depth (1+ byte-compile-depth)))))
+
+;; Compile those primitive ordinary functions
+;; which have special byte codes just for speed.
+
+(put 'point 'byte-compile 'byte-compile-no-args)
+(put 'point 'byte-opcode 'byte-point)
+
+(put 'dot 'byte-compile 'byte-compile-no-args)
+(put 'dot 'byte-opcode 'byte-point)
+
+;(put 'mark 'byte-compile 'byte-compile-no-args)
+;(put 'mark 'byte-opcode 'byte-mark)
+
+(put 'point-max 'byte-compile 'byte-compile-no-args)
+(put 'point-max 'byte-opcode 'byte-point-max)
+
+(put 'point-min 'byte-compile 'byte-compile-no-args)
+(put 'point-min 'byte-opcode 'byte-point-min)
+
+(put 'dot-max 'byte-compile 'byte-compile-no-args)
+(put 'dot-max 'byte-opcode 'byte-point-max)
+
+(put 'dot-min 'byte-compile 'byte-compile-no-args)
+(put 'dot-min 'byte-opcode 'byte-point-min)
+
+(put 'following-char 'byte-compile 'byte-compile-no-args)
+(put 'following-char 'byte-opcode 'byte-following-char)
+
+(put 'preceding-char 'byte-compile 'byte-compile-no-args)
+(put 'preceding-char 'byte-opcode 'byte-preceding-char)
+
+(put 'current-column 'byte-compile 'byte-compile-no-args)
+(put 'current-column 'byte-opcode 'byte-current-column)
+
+(put 'eolp 'byte-compile 'byte-compile-no-args)
+(put 'eolp 'byte-opcode 'byte-eolp)
+
+(put 'eobp 'byte-compile 'byte-compile-no-args)
+(put 'eobp 'byte-opcode 'byte-eobp)
+
+(put 'bolp 'byte-compile 'byte-compile-no-args)
+(put 'bolp 'byte-opcode 'byte-bolp)
+
+(put 'bobp 'byte-compile 'byte-compile-no-args)
+(put 'bobp 'byte-opcode 'byte-bobp)
+
+(put 'current-buffer 'byte-compile 'byte-compile-no-args)
+(put 'current-buffer 'byte-opcode 'byte-current-buffer)
+
+(put 'read-char 'byte-compile 'byte-compile-no-args)
+(put 'read-char 'byte-opcode 'byte-read-char)
+
+
+(put 'symbolp 'byte-compile 'byte-compile-one-arg)
+(put 'symbolp 'byte-opcode 'byte-symbolp)
+
+(put 'consp 'byte-compile 'byte-compile-one-arg)
+(put 'consp 'byte-opcode 'byte-consp)
+
+(put 'stringp 'byte-compile 'byte-compile-one-arg)
+(put 'stringp 'byte-opcode 'byte-stringp)
+
+(put 'listp 'byte-compile 'byte-compile-one-arg)
+(put 'listp 'byte-opcode 'byte-listp)
+
+(put 'not 'byte-compile 'byte-compile-one-arg)
+(put 'not 'byte-opcode 'byte-not)
+
+(put 'null 'byte-compile 'byte-compile-one-arg)
+(put 'null 'byte-opcode 'byte-not)
+
+(put 'car 'byte-compile 'byte-compile-one-arg)
+(put 'car 'byte-opcode 'byte-car)
+
+(put 'cdr 'byte-compile 'byte-compile-one-arg)
+(put 'cdr 'byte-opcode 'byte-cdr)
+
+(put 'length 'byte-compile 'byte-compile-one-arg)
+(put 'length 'byte-opcode 'byte-length)
+
+(put 'symbol-value 'byte-compile 'byte-compile-one-arg)
+(put 'symbol-value 'byte-opcode 'byte-symbol-value)
+
+(put 'symbol-function 'byte-compile 'byte-compile-one-arg)
+(put 'symbol-function 'byte-opcode 'byte-symbol-function)
+
+(put '1+ 'byte-compile 'byte-compile-one-arg)
+(put '1+ 'byte-opcode 'byte-add1)
+
+(put '1- 'byte-compile 'byte-compile-one-arg)
+(put '1- 'byte-opcode 'byte-sub1)
+
+(put 'goto-char 'byte-compile 'byte-compile-one-arg)
+(put 'goto-char 'byte-opcode 'byte-goto-char)
+
+(put 'char-after 'byte-compile 'byte-compile-one-arg)
+(put 'char-after 'byte-opcode 'byte-char-after)
+
+(put 'set-buffer 'byte-compile 'byte-compile-one-arg)
+(put 'set-buffer 'byte-opcode 'byte-set-buffer)
+
+;set-mark turns out to be too unimportant for its own opcode.
+;(put 'set-mark 'byte-compile 'byte-compile-one-arg)
+;(put 'set-mark 'byte-opcode 'byte-set-mark)
+
+
+(put 'eq 'byte-compile 'byte-compile-two-args)
+(put 'eq 'byte-opcode 'byte-eq)
+(put 'eql 'byte-compile 'byte-compile-two-args)
+(put 'eql 'byte-opcode 'byte-eq)
+
+(put 'memq 'byte-compile 'byte-compile-two-args)
+(put 'memq 'byte-opcode 'byte-memq)
+
+(put 'cons 'byte-compile 'byte-compile-two-args)
+(put 'cons 'byte-opcode 'byte-cons)
+
+(put 'aref 'byte-compile 'byte-compile-two-args)
+(put 'aref 'byte-opcode 'byte-aref)
+
+(put 'set 'byte-compile 'byte-compile-two-args)
+(put 'set 'byte-opcode 'byte-set)
+
+(put 'fset 'byte-compile 'byte-compile-two-args)
+(put 'fset 'byte-opcode 'byte-fset)
+
+(put '= 'byte-compile 'byte-compile-two-args)
+(put '= 'byte-opcode 'byte-eqlsign)
+
+(put '< 'byte-compile 'byte-compile-two-args)
+(put '< 'byte-opcode 'byte-lss)
+
+(put '> 'byte-compile 'byte-compile-two-args)
+(put '> 'byte-opcode 'byte-gtr)
+
+(put '<= 'byte-compile 'byte-compile-two-args)
+(put '<= 'byte-opcode 'byte-leq)
+
+(put '>= 'byte-compile 'byte-compile-two-args)
+(put '>= 'byte-opcode 'byte-geq)
+
+(put 'get 'byte-compile 'byte-compile-two-args)
+(put 'get 'byte-opcode 'byte-get)
+
+(put 'nth 'byte-compile 'byte-compile-two-args)
+(put 'nth 'byte-opcode 'byte-nth)
+
+(put 'aset 'byte-compile 'byte-compile-three-args)
+(put 'aset 'byte-opcode 'byte-aset)
+
+(defun byte-compile-no-args (form)
+ (if (/= (length form) 1)
+ ;; get run-time wrong-number-of-args error.
+ ;; Would be nice if there were some way to do
+ ;; compile-time warnings.
+ (byte-compile-normal-call form)
+ (byte-compile-out (symbol-value (get (car form) 'byte-opcode)) 0)))
+
+(defun byte-compile-one-arg (form)
+ (if (/= (length form) 2)
+ (byte-compile-normal-call form)
+ (byte-compile-form (car (cdr form))) ;; Push the argument
+ (setq byte-compile-depth (1- byte-compile-depth))
+ (byte-compile-out (symbol-value (get (car form) 'byte-opcode)) 0)))
+
+(defun byte-compile-two-args (form)
+ (if (/= (length form) 3)
+ (byte-compile-normal-call form)
+ (byte-compile-form (car (cdr form))) ;; Push the arguments
+ (byte-compile-form (nth 2 form))
+ (setq byte-compile-depth (- byte-compile-depth 2))
+ (byte-compile-out (symbol-value (get (car form) 'byte-opcode)) 0)))
+
+(defun byte-compile-three-args (form)
+ (if (/= (length form) 4)
+ (byte-compile-normal-call form)
+ (byte-compile-form (car (cdr form))) ;; Push the arguments
+ (byte-compile-form (nth 2 form))
+ (byte-compile-form (nth 3 form))
+ (setq byte-compile-depth (- byte-compile-depth 3))
+ (byte-compile-out (symbol-value (get (car form) 'byte-opcode)) 0)))
+
+(put 'substring 'byte-compile 'byte-compile-substring)
+(defun byte-compile-substring (form)
+ (if (or (> (length form) 4)
+ (< (length form) 2))
+ (byte-compile-normal-call form)
+ (byte-compile-form (nth 1 form))
+ (byte-compile-form (or (nth 2 form) ''nil)) ;Optional arguments
+ (byte-compile-form (or (nth 3 form) ''nil))
+ (setq byte-compile-depth (- byte-compile-depth 3))
+ (byte-compile-out byte-substring 0)))
+
+(put 'interactive-p 'byte-compile 'byte-compile-interactive-p)
+(defun byte-compile-interactive-p (form)
+ (byte-compile-out byte-interactive-p 0))
+
+(put 'list 'byte-compile 'byte-compile-list)
+(defun byte-compile-list (form)
+ (let ((len (length form)))
+ (if (= len 1)
+ (byte-compile-constant nil)
+ (if (< len 6)
+ (let ((args (cdr form)))
+ (while args
+ (byte-compile-form (car args))
+ (setq args (cdr args)))
+ (setq byte-compile-depth (- byte-compile-depth (1- len)))
+ (byte-compile-out (symbol-value
+ (nth (- len 2)
+ '(byte-list1 byte-list2 byte-list3 byte-list4)))
+ 0))
+ (byte-compile-normal-call form)))))
+
+(put 'concat 'byte-compile 'byte-compile-concat)
+(defun byte-compile-concat (form)
+ (let ((len (length form)))
+ (cond ((= len 1)
+ (byte-compile-form ""))
+ ((= len 2)
+ ;; Concat of one arg is not a no-op if arg is not a string.
+ (byte-compile-normal-call form))
+ ((< len 6)
+ (let ((args (cdr form)))
+ (while args
+ (byte-compile-form (car args))
+ (setq args (cdr args)))
+ (setq byte-compile-depth (- byte-compile-depth (1- len)))
+ (byte-compile-out
+ (symbol-value (nth (- len 3)
+ '(byte-concat2 byte-concat3 byte-concat4)))
+ 0)))
+ (t
+ (byte-compile-normal-call form)))))
+
+(put '- 'byte-compile 'byte-compile-minus)
+(defun byte-compile-minus (form)
+ (let ((len (length form)))
+ (cond ((= len 2)
+ (byte-compile-form (car (cdr form)))
+ (setq byte-compile-depth (- byte-compile-depth 1))
+ (byte-compile-out byte-negate 0))
+ ((= len 3)
+ (byte-compile-form (car (cdr form)))
+ (byte-compile-form (nth 2 form))
+ (setq byte-compile-depth (- byte-compile-depth 2))
+ (byte-compile-out byte-diff 0))
+ (t (byte-compile-normal-call form)))))
+
+(put '+ 'byte-compile 'byte-compile-maybe-two-args)
+(put '+ 'byte-opcode 'byte-plus)
+
+(put 'max 'byte-compile 'byte-compile-maybe-two-args)
+(put 'max 'byte-opcode 'byte-max)
+
+(put 'min 'byte-compile 'byte-compile-maybe-two-args)
+(put 'min 'byte-opcode 'byte-min)
+
+(defun byte-compile-maybe-two-args (form)
+ (let ((len (length form)))
+ (if (= len 3)
+ (progn
+ (byte-compile-form (car (cdr form)))
+ (byte-compile-form (nth 2 form))
+ (setq byte-compile-depth (- byte-compile-depth 2))
+ (byte-compile-out (symbol-value (get (car form) 'byte-opcode)) 0))
+ (byte-compile-normal-call form))))
+
+(put 'function 'byte-compile 'byte-compile-function-form)
+(defun byte-compile-function-form (form)
+ (cond ((symbolp (car (cdr form)))
+ (byte-compile-form
+ (list 'symbol-function (list 'quote (nth 1 form)))))
+ (t
+ (byte-compile-constant (byte-compile-lambda (car (cdr form)))))))
+
+(put 'indent-to 'byte-compile 'byte-compile-indent-to)
+(defun byte-compile-indent-to (form)
+ (let ((len (length form)))
+ (if (= len 2)
+ (progn
+ (byte-compile-form (car (cdr form)))
+ (setq byte-compile-depth (- byte-compile-depth 1))
+ (byte-compile-out byte-indent-to 0))
+ (byte-compile-normal-call form))))
+
+(put 'insert 'byte-compile 'byte-compile-insert)
+(defun byte-compile-insert (form)
+ (let ((len (length form)))
+ (if (< len 3)
+ (let ((args (cdr form)))
+ (while args
+ (byte-compile-form (car args))
+ (setq byte-compile-depth (- byte-compile-depth 1))
+ (byte-compile-out byte-insert 0)
+ (setq args (cdr args))))
+ (byte-compile-normal-call form))))
+
+(put 'setq-default 'byte-compile 'byte-compile-setq-default)
+(defun byte-compile-setq-default (form)
+ (byte-compile-form (cons 'set-default (cons (list 'quote (nth 1 form))
+ (nthcdr 2 form)))))
+
+(put 'quote 'byte-compile 'byte-compile-quote)
+(defun byte-compile-quote (form)
+ (byte-compile-constant (car (cdr form))))
+
+(put 'setq 'byte-compile 'byte-compile-setq)
+(defun byte-compile-setq (form)
+ (let ((args (cdr form)))
+ (if args
+ (while args
+ (byte-compile-form (car (cdr args)))
+ (if (null (cdr (cdr args)))
+ (progn
+ (byte-compile-out 'byte-dup 0)
+ (setq byte-compile-maxdepth (max byte-compile-maxdepth (1+ byte-compile-depth)))))
+ (setq byte-compile-depth (1- byte-compile-depth))
+ (byte-compile-variable-ref 'byte-varset (car args))
+ (setq args (cdr (cdr args))))
+ ;; (setq), with no arguments.
+ (byte-compile-constant nil))))
+
+(put 'let 'byte-compile 'byte-compile-let)
+(defun byte-compile-let (form)
+ (let ((varlist (car (cdr form))))
+ (while varlist
+ (if (symbolp (car varlist))
+ (byte-compile-push-constant nil)
+ (byte-compile-form (car (cdr (car varlist)))))
+ (setq varlist (cdr varlist))))
+ (let ((varlist (reverse (car (cdr form)))))
+ (setq byte-compile-depth (- byte-compile-depth (length varlist)))
+ (while varlist
+ (if (symbolp (car varlist))
+ (byte-compile-variable-ref 'byte-varbind (car varlist))
+ (byte-compile-variable-ref 'byte-varbind (car (car varlist))))
+ (setq varlist (cdr varlist))))
+ (byte-compile-body (cdr (cdr form)))
+ (byte-compile-out 'byte-unbind (length (car (cdr form)))))
+
+(put 'let* 'byte-compile 'byte-compile-let*)
+(defun byte-compile-let* (form)
+ (let ((varlist (car (cdr form))))
+ (while varlist
+ (if (symbolp (car varlist))
+ (byte-compile-push-constant nil)
+ (byte-compile-form (car (cdr (car varlist)))))
+ (setq byte-compile-depth (1- byte-compile-depth))
+ (if (symbolp (car varlist))
+ (byte-compile-variable-ref 'byte-varbind (car varlist))
+ (byte-compile-variable-ref 'byte-varbind (car (car varlist))))
+ (setq varlist (cdr varlist))))
+ (byte-compile-body (cdr (cdr form)))
+ (byte-compile-out 'byte-unbind (length (car (cdr form)))))
+
+(put 'save-excursion 'byte-compile 'byte-compile-save-excursion)
+(defun byte-compile-save-excursion (form)
+ (byte-compile-out 'byte-save-excursion 0)
+ (byte-compile-body (cdr form))
+ (byte-compile-out 'byte-unbind 1))
+
+(put 'save-restriction 'byte-compile 'byte-compile-save-restriction)
+(defun byte-compile-save-restriction (form)
+ (byte-compile-out 'byte-save-restriction 0)
+ (byte-compile-body (cdr form))
+ (byte-compile-out 'byte-unbind 1))
+
+(put 'with-output-to-temp-buffer 'byte-compile 'byte-compile-with-output-to-temp-buffer)
+(defun byte-compile-with-output-to-temp-buffer (form)
+ (byte-compile-form (car (cdr form)))
+ (byte-compile-out 'byte-temp-output-buffer-setup 0)
+ (byte-compile-body (cdr (cdr form)))
+ (byte-compile-out 'byte-temp-output-buffer-show 0)
+ (setq byte-compile-depth (1- byte-compile-depth)))
+
+(put 'progn 'byte-compile 'byte-compile-progn)
+(defun byte-compile-progn (form)
+ (byte-compile-body (cdr form)))
+
+(put 'interactive 'byte-compile 'byte-compile-noop)
+(defun byte-compile-noop (form)
+ (byte-compile-constant nil))
+
+(defun byte-compile-body (body)
+ (if (null body)
+ (byte-compile-constant nil)
+ (while body
+ (byte-compile-form (car body))
+ (if (cdr body)
+ (byte-compile-discard)
+ ;; Convention is this will be counted after we return.
+ (setq byte-compile-depth (1- byte-compile-depth)))
+ (setq body (cdr body)))))
+
+(put 'prog1 'byte-compile 'byte-compile-prog1)
+(defun byte-compile-prog1 (form)
+ (byte-compile-form (car (cdr form)))
+ (if (cdr (cdr form))
+ (progn
+ (byte-compile-body (cdr (cdr form)))
+ ;; This discards the value pushed by ..-body
+ ;; (which is not counted now in byte-compile-depth)
+ ;; and decrements byte-compile-depth for the value
+ ;; pushed by byte-compile-form above, which by convention
+ ;; will be counted in byte-compile-depth after we return.
+ (byte-compile-discard))))
+
+(put 'prog2 'byte-compile 'byte-compile-prog2)
+(defun byte-compile-prog2 (form)
+ (byte-compile-form (car (cdr form)))
+ (byte-compile-discard)
+ (byte-compile-form (nth 2 form))
+ (if (cdr (cdr (cdr form)))
+ (progn
+ (byte-compile-body (cdr (cdr (cdr form))))
+ (byte-compile-discard))))
+
+(defun byte-compile-discard ()
+ (byte-compile-out 'byte-discard 0)
+ (setq byte-compile-depth (1- byte-compile-depth)))
+
+(put 'if 'byte-compile 'byte-compile-if)
+(defun byte-compile-if (form)
+ (if (null (nthcdr 3 form))
+ ;; No else-forms
+ (let ((donetag (byte-compile-make-tag)))
+ (byte-compile-form (car (cdr form)))
+ (byte-compile-goto 'byte-goto-if-nil-else-pop donetag)
+ (setq byte-compile-depth (1- byte-compile-depth))
+ (byte-compile-form (nth 2 form))
+ (setq byte-compile-depth (1- byte-compile-depth))
+ (byte-compile-out-tag donetag))
+ (let ((donetag (byte-compile-make-tag)) (elsetag (byte-compile-make-tag)))
+ (byte-compile-form (car (cdr form)))
+ (byte-compile-goto 'byte-goto-if-nil elsetag)
+ (setq byte-compile-depth (1- byte-compile-depth))
+ (byte-compile-form (nth 2 form))
+ (setq byte-compile-depth (1- byte-compile-depth))
+ (byte-compile-goto 'byte-goto donetag)
+ (byte-compile-out-tag elsetag)
+ (byte-compile-body (cdr (cdr (cdr form))))
+ (byte-compile-out-tag donetag))))
+
+(put 'cond 'byte-compile 'byte-compile-cond)
+(defun byte-compile-cond (form)
+ (if (cdr form)
+ (byte-compile-cond-1 (cdr form))
+ (byte-compile-constant nil)))
+
+(defun byte-compile-cond-1 (clauses)
+ (if (or (eq (car (car clauses)) t)
+ (and (eq (car-safe (car (car clauses))) 'quote)
+ (car-safe (cdr-safe (car (car clauses))))))
+ ;; Unconditional clause
+ (if (cdr (car clauses))
+ (byte-compile-body (cdr (car clauses)))
+ (byte-compile-form (car (car clauses))))
+ (if (null (cdr clauses))
+ ;; Only one clause
+ (let ((donetag (byte-compile-make-tag)))
+ (byte-compile-form (car (car clauses)))
+ (cond ((cdr (car clauses))
+ (byte-compile-goto 'byte-goto-if-nil-else-pop donetag)
+ (setq byte-compile-depth (1- byte-compile-depth))
+ (byte-compile-body (cdr (car clauses)))
+ (byte-compile-out-tag donetag))))
+ (let ((donetag (byte-compile-make-tag))
+ (elsetag (byte-compile-make-tag)))
+ (byte-compile-form (car (car clauses)))
+ (if (null (cdr (car clauses)))
+ ;; First clause is a singleton.
+ (progn
+ (byte-compile-goto 'byte-goto-if-not-nil-else-pop donetag)
+ (setq byte-compile-depth (1- byte-compile-depth)))
+ (byte-compile-goto 'byte-goto-if-nil elsetag)
+ (setq byte-compile-depth (1- byte-compile-depth))
+ (byte-compile-body (cdr (car clauses)))
+ (byte-compile-goto 'byte-goto donetag)
+ (byte-compile-out-tag elsetag))
+ (byte-compile-cond-1 (cdr clauses))
+ (byte-compile-out-tag donetag)))))
+
+(put 'and 'byte-compile 'byte-compile-and)
+(defun byte-compile-and (form)
+ (let ((failtag (byte-compile-make-tag))
+ (args (cdr form)))
+ (if (null args)
+ (progn
+ (byte-compile-form t)
+ (setq byte-compile-depth (1- byte-compile-depth)))
+ (while args
+ (byte-compile-form (car args))
+ (setq byte-compile-depth (1- byte-compile-depth))
+ (if (null (cdr args))
+ (byte-compile-out-tag failtag)
+ (byte-compile-goto 'byte-goto-if-nil-else-pop failtag))
+ (setq args (cdr args))))))
+
+(put 'or 'byte-compile 'byte-compile-or)
+(defun byte-compile-or (form)
+ (let ((wintag (byte-compile-make-tag))
+ (args (cdr form)))
+ (if (null args)
+ (byte-compile-constant nil)
+ (while args
+ (byte-compile-form (car args))
+ (setq byte-compile-depth (1- byte-compile-depth))
+ (if (null (cdr args))
+ (byte-compile-out-tag wintag)
+ (byte-compile-goto 'byte-goto-if-not-nil-else-pop wintag))
+ (setq args (cdr args))))))
+
+(put 'while 'byte-compile 'byte-compile-while)
+(defun byte-compile-while (form)
+ (let ((endtag (byte-compile-make-tag))
+ (looptag (byte-compile-make-tag))
+ (args (cdr (cdr form))))
+ (byte-compile-out-tag looptag)
+ (byte-compile-form (car (cdr form)))
+ (byte-compile-goto 'byte-goto-if-nil-else-pop endtag)
+ (byte-compile-body (cdr (cdr form)))
+ (byte-compile-discard)
+ (byte-compile-goto 'byte-goto looptag)
+ (byte-compile-out-tag endtag)))
+
+(put 'catch 'byte-compile 'byte-compile-catch)
+(defun byte-compile-catch (form)
+ (byte-compile-form (car (cdr form)))
+ (byte-compile-push-constant (byte-compile-top-level (cons 'progn (cdr (cdr form)))))
+ (setq byte-compile-depth (- byte-compile-depth 2))
+ (byte-compile-out 'byte-catch 0))
+
+(put 'save-window-excursion 'byte-compile 'byte-compile-save-window-excursion)
+(defun byte-compile-save-window-excursion (form)
+ (byte-compile-push-constant
+ (list (byte-compile-top-level (cons 'progn (cdr form)))))
+ (setq byte-compile-depth (1- byte-compile-depth))
+ (byte-compile-out 'byte-save-window-excursion 0))
+
+(put 'unwind-protect 'byte-compile 'byte-compile-unwind-protect)
+(defun byte-compile-unwind-protect (form)
+ (byte-compile-push-constant
+ (list (byte-compile-top-level (cons 'progn (cdr (cdr form))))))
+ (setq byte-compile-depth (1- byte-compile-depth))
+ (byte-compile-out 'byte-unwind-protect 0)
+ (byte-compile-form (car (cdr form)))
+ (setq byte-compile-depth (1- byte-compile-depth))
+ (byte-compile-out 'byte-unbind 1))
+
+(put 'condition-case 'byte-compile 'byte-compile-condition-case)
+(defun byte-compile-condition-case (form)
+ (byte-compile-push-constant (car (cdr form)))
+ (byte-compile-push-constant (byte-compile-top-level (nth 2 form)))
+ (let ((clauses (cdr (cdr (cdr form))))
+ compiled-clauses)
+ (while clauses
+ (let ((clause (car clauses)))
+ (setq compiled-clauses
+ (cons (list (car clause)
+ (byte-compile-top-level (cons 'progn (cdr clause))))
+ compiled-clauses)))
+ (setq clauses (cdr clauses)))
+ (byte-compile-push-constant (nreverse compiled-clauses)))
+ (setq byte-compile-depth (- byte-compile-depth 3))
+ (byte-compile-out 'byte-condition-case 0))
+
+(defun byte-compile-make-tag ()
+ (cons nil nil))
+
+(defun byte-compile-out-tag (tag)
+ (let ((uses (car tag)))
+ (setcar tag byte-compile-pc)
+ (while uses
+ (byte-compile-store-goto (car uses) byte-compile-pc)
+ (setq uses (cdr uses)))))
+
+(defun byte-compile-goto (opcode tag)
+ (byte-compile-out opcode 0)
+ (if (integerp (car tag))
+ (byte-compile-store-goto byte-compile-pc (car tag))
+ (setcar tag (cons byte-compile-pc (car tag))))
+ (setq byte-compile-pc (+ byte-compile-pc 2)))
+
+(defun byte-compile-store-goto (at-pc to-pc)
+ (setq byte-compile-output
+ (cons (cons at-pc (logand to-pc 255))
+ byte-compile-output))
+ (setq byte-compile-output
+ (cons (cons (1+ at-pc) (lsh to-pc -8))
+ byte-compile-output)))
+
+(defun byte-compile-out (opcode offset)
+ (setq opcode (eval opcode))
+ (if (< offset 6)
+ (byte-compile-out-1 (+ opcode offset))
+ (if (< offset 256)
+ (progn
+ (byte-compile-out-1 (+ opcode 6))
+ (byte-compile-out-1 offset))
+ (byte-compile-out-1 (+ opcode 7))
+ (byte-compile-out-1 (logand offset 255))
+ (byte-compile-out-1 (lsh offset -8)))))
+
+(defun byte-compile-out-const (offset)
+ (if (< offset byte-constant-limit)
+ (byte-compile-out-1 (+ byte-constant offset))
+ (byte-compile-out-1 byte-constant2)
+ (byte-compile-out-1 (logand offset 255))
+ (byte-compile-out-1 (lsh offset -8))))
+
+(defun byte-compile-out-1 (code)
+ (setq byte-compile-output
+ (cons (cons byte-compile-pc code)
+ byte-compile-output))
+ (setq byte-compile-pc (1+ byte-compile-pc)))
+
+;;; by crl@newton.purdue.edu
+;;; Only works noninteractively.
+(defun batch-byte-compile ()
+ "Runs byte-compile-file on the files remaining on the command line.
+Must be used only with -batch, and kills emacs on completion.
+Each file will be processed even if an error occurred previously.
+For example, invoke \"emacs -batch -f batch-byte-compile $emacs/ ~/*.el\""
+ ;; command-line-args-left is what is left of the command line (from startup.el)
+ (if (not noninteractive)
+ (error "batch-byte-compile is to be used only with -batch"))
+ (let ((error nil))
+ (while command-line-args-left
+ (if (file-directory-p (expand-file-name (car command-line-args-left)))
+ (let ((files (directory-files (car command-line-args-left)))
+ source dest)
+ (while files
+ (if (and (string-match ".el$" (car files))
+ (not (auto-save-file-name-p (car files)))
+ (setq source (expand-file-name (car files)
+ (car command-line-args-left)))
+ (setq dest (concat (file-name-sans-versions source) "c"))
+ (file-exists-p dest)
+ (file-newer-than-file-p source dest))
+ (if (null (batch-byte-compile-file source))
+ (setq error t)))
+ (setq files (cdr files))))
+ (if (null (batch-byte-compile-file (car command-line-args-left)))
+ (setq error t)))
+ (setq command-line-args-left (cdr command-line-args-left)))
+ (message "Done")
+ (kill-emacs (if error 1 0))))
+
+(defun batch-byte-compile-file (file)
+ (condition-case err
+ (progn (byte-compile-file file) t)
+ (error
+ (message (if (cdr err)
+ ">>Error occurred processing %s: %s (%s)"
+ ">>Error occurred processing %s: %s")
+ file
+ (get (car err) 'error-message)
+ (prin1-to-string (cdr err)))
+ nil)))
diff --git a/lisp/bytecomp.elc b/lisp/bytecomp.elc
new file mode 100644
index 00000000000..259d23cd4cf
--- /dev/null
+++ b/lisp/bytecomp.elc
Binary files differ
diff --git a/lisp/c-fill.el b/lisp/c-fill.el
new file mode 100644
index 00000000000..457e4c4ab1d
--- /dev/null
+++ b/lisp/c-fill.el
@@ -0,0 +1,269 @@
+;;; C comment mode - An auto-filled comment mode for gnu c-mode.
+;;;
+;;; Author: Robert Mecklenburg
+;;; Computer Science Dept.
+;;; University of Utah
+;;; From: mecklen@utah-gr.UUCP (Robert Mecklenburg)
+;;; Also hartzell@Boulder.Colorado.EDU
+;;; (c) 1986, University of Utah
+;;;
+;;; Everyone is granted permission to copy, modify and redistribute
+;;; this file, provided the people they give it to can.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;
+;;; I have written a "global comment" minor-mode which performs auto-fill,
+;;; fill-paragraph, and auto-indentation functions. This function only
+;;; works for comments which occupy an entire line (not comments to the
+;;; right of code). The mode has several options set through variables.
+;;; If the variable c-comment-starting-blank is non-nil multi-line
+;;; comments come out like this:
+;;;
+;;; /*
+;;; * Your favorite
+;;; * multi-line comment.
+;;; */
+;;;
+;;; otherwise they look like this:
+;;;
+;;; /* Your Favorite
+;;; * multi-line comment.
+;;; */
+;;;
+;;; If the variable c-comment-hanging-indent is non-nil K&R style comments
+;;; are indented automatically like this:
+;;;
+;;; /* my_func - For multi-line comments with hanging indent
+;;; * the text is lined up after the dash.
+;;; */
+;;;
+;;; otherwise the text "the text" (!) is lined up under my_func. If a
+;;; comment fits (as typed) on a single line it remains a single line
+;;; comment even if c-comment-starting-blank is set. If
+;;; c-comment-indenting is non-nil hitting carriage return resets the
+;;; indentation for the next line to the current line's indentation
+;;; (within the comment) like this:
+;;;
+;;; /* Typing along merrily....
+;;; * Now I indent with spaces, when I hit return
+;;; * the indentation is automatically set to
+;;; * ^ here.
+;;; */
+;;;
+;;; Due to my lack of understanding of keymaps this permanently resets M-q
+;;; to my own fill function. I would like to have the comment mode
+;;; bindings only in comment mode but I can't seem to get that to work.
+;;; If some gnu guru can clue me in, I'd appreciate it.
+;;;
+(defvar c-comment-starting-blank t
+ "*Controls whether global comments have an initial blank line.")
+(defvar c-comment-indenting t
+ "*If set global comments are indented to the level of the previous line.")
+(defvar c-comment-hanging-indent t
+ "*If true, comments will be automatically indented to the dash.")
+(defvar c-hang-already-done t
+ "If true we have performed the haning indent already for this comment.")
+
+
+;;;
+;;; c-comment-map - This is a sparse keymap for comment mode which
+;;; gets inserted when c-comment is called.
+;;;
+(defvar c-comment-mode-map ()
+ "Keymap used in C comment mode.")
+(if c-comment-mode-map
+ ()
+ (setq c-comment-mode-map (copy-keymap c-mode-map))
+ (define-key c-comment-mode-map "\e\r" 'newline)
+ (define-key c-comment-mode-map "\eq" 'set-fill-and-fill)
+ (define-key c-comment-mode-map "\r" 'set-fill-and-return))
+
+;;;
+;;; c-comment - This is a filled comment mode which can format
+;;; indented text, do hanging indents, and symetric
+;;; placement of comment delimiters.
+;;;
+(defun c-comment ()
+ "Edit a C comment with filling and indentation.
+This performs hanging indentation, symmetric placement of delimiters,
+ and Indented-Text mode style indentation. Type 'M-x apropos
+c-comment' for information on options."
+ (interactive)
+ (let
+ ;; Save old state.
+ ((auto-fill-hook (if c-comment-indenting
+ 'do-indented-auto-fill 'do-auto-fill))
+; (comment-start nil)
+ (comment-multi-line t)
+ (comment-start-skip "/*\\*+[ ]*")
+ (paragraph-start-ref paragraph-start)
+ fill-prefix paragraph-start paragraph-separate opoint)
+
+ ;; Determine if we are inside a comment.
+ (setq in-comment
+ (save-excursion
+ (and (re-search-backward "/\\*\\|\\*/" 0 t)
+ (string= "/*" (buffer-substring (point) (+ (point) 2))))))
+
+ ;; Indent the comment and set the fill prefix to comment continuation
+ ;; string. If we are already in a comment get the indentation on
+ ;; the current line.
+ (setq c-hang-already-done nil)
+
+ ;; Set the beginning of the comment and insert the blank line if needed.
+ (use-local-map c-comment-mode-map)
+ (if (not in-comment)
+ (progn (c-indent-line)
+ (insert "/* ")
+ (setq fill-prefix (get-current-fill (point)))
+ (recursive-edit)
+
+ ;; If the comment fits on one line, place the close
+ ;; comment at the end of the line. Otherwise, newline.
+ (setq opoint (point))
+ (if (and (save-excursion (beginning-of-line)
+ (search-forward "/*" opoint t))
+ (<= (+ (current-column) 3) 79))
+ (insert " */")
+ (insert "\n*/"))
+
+ (c-indent-line))
+ (progn (setq fill-prefix (get-current-fill (point)))
+ (recursive-edit)
+ (search-forward "*/" (buffer-size) t)
+ (forward-line 1)))
+
+ ;; If starting blank enabled, insert a newline, etc., but only if
+ ;; this comment requires multiple lines.
+ (if c-comment-starting-blank
+ (save-excursion
+ (setq opoint (point))
+ (forward-line -1)
+ (if (or (null (search-forward "/*" opoint t))
+ (null (search-forward "*/" opoint t)))
+ (progn
+ (search-backward "/*")
+ (re-search-forward comment-start-skip opoint t)
+ (setq fill-prefix (get-current-fill (point)))
+ (if (not (looking-at "\n"))
+ (insert ?\n fill-prefix))))))
+; (indent-new-comment-line))))))
+
+ ;; Move cursor to indentation.
+ (c-indent-line)
+ (use-local-map c-mode-map)
+ )
+ )
+
+
+;;;
+;;; set-fill-and-fill - Get the current fill for this line and fill
+;;; the paragraph.
+;;;
+(defun set-fill-and-fill (arg)
+ "Get the fill-prefix and fill the current paragraph."
+
+ (interactive "P")
+ (setq fill-prefix (get-current-fill (point)))
+ (fill-paragraph arg))
+
+;;;
+;;; set-fill-and-return - Set the current fill prefix and
+;;; indent-new-comment-line.
+;;;
+(defun set-fill-and-return ()
+ "Set the current fill prefix and move to the next line."
+
+ (interactive)
+ (if c-comment-indenting
+ (setq fill-prefix (get-current-fill (point))))
+ (insert ?\n fill-prefix))
+
+;;;
+;;; do-indented-auto-fill - Perform the auto-fill function, but get
+;;; the fill-prefix first.
+;;;
+(defun do-indented-auto-fill ()
+ "Perform auto-fill, but get fill-prefix first."
+
+ (let ((opoint (point)))
+ (save-excursion
+ (move-to-column (1+ fill-column))
+ (skip-chars-backward "^ \t\n")
+ (if (bolp)
+ (re-search-forward "[ \t]" opoint t))
+ ;; If there is a space on the line before fill-point,
+ ;; and nonspaces precede it, break the line there.
+ (if (save-excursion
+ (skip-chars-backward " \t")
+ (not (bolp)))
+
+ ;; If we are wrapping to a new line, figure out the indentation on
+ ;; the current line first.
+ (progn
+ (setq fill-prefix (get-current-fill opoint))
+ (insert ?\n fill-prefix)))))
+; (indent-new-comment-line)))))
+ )
+
+
+;;;
+;;; get-current-fill - Get the fill-prefix for the current line. This
+;;; assumes that the valid fill prefix is between
+;;; (beginning-of-line) and (point).
+;;;
+(defun get-current-fill (pnt)
+ "Get the current fill prefix.
+A valid fill prefix must be between the beginning of the line and point."
+
+ (let ((opoint pnt) fill last-char)
+ (save-excursion
+ (beginning-of-line)
+ (setq fill
+ (buffer-substring (point)
+ (progn
+ (re-search-forward comment-start-skip opoint t)
+ (point))))
+
+ ;; Be sure there is trailing white space.
+ (setq last-char (substring fill (1- (length fill)) (length fill)))
+ (if (and (not (string= " " last-char))
+ (not (string= " " last-char)))
+ (setq fill (concat fill " ")))
+
+ (setq fill (replace-letter fill "/" " "))
+
+ ;; Get the hanging indentation if we haven't already.
+ (if (and c-comment-hanging-indent (not c-hang-already-done))
+ (let ((curr (point))
+ (opnt (progn (end-of-line) (point))))
+ (beginning-of-line)
+ (if (search-forward " - " opnt t)
+ (progn
+ (setq fill (concat fill (make-string (- (point) curr) 32)))
+ (setq c-hang-already-done t)))))
+
+ ;; Set the paragraph delimiters.
+ (setq paragraph-start (concat paragraph-start-ref
+ "\\|^"
+ (regexp-quote
+ (substring fill
+ 0 (1- (length fill))))
+ "$"))
+ (setq paragraph-separate paragraph-start))
+ fill)
+ )
+
+
+;;;
+;;; replace-letter - Given a string, an old letter and a new letter,
+;;; perform the substitution.
+;;;
+(defun replace-letter (str old-letter new-letter)
+ (let (new-str c
+ (sp 0)
+ (size (length str)))
+ (while (< sp size)
+ (setq c (substring str sp (1+ sp)))
+ (setq new-str (concat new-str (if (string= c old-letter) new-letter c)))
+ (setq sp (1+ sp)))
+ new-str))
diff --git a/lisp/c-fill.elc b/lisp/c-fill.elc
new file mode 100644
index 00000000000..ad428dea863
--- /dev/null
+++ b/lisp/c-fill.elc
Binary files differ
diff --git a/lisp/c-mode.el b/lisp/c-mode.el
new file mode 100644
index 00000000000..950de6cdde5
--- /dev/null
+++ b/lisp/c-mode.el
@@ -0,0 +1,662 @@
+;; C code editing commands for Emacs
+;; Copyright (C) 1985, 1986, 1987 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 1, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+(defvar c-mode-abbrev-table nil
+ "Abbrev table in use in C-mode buffers.")
+(define-abbrev-table 'c-mode-abbrev-table ())
+
+(defvar c-mode-map ()
+ "Keymap used in C mode.")
+(if c-mode-map
+ ()
+ (setq c-mode-map (make-sparse-keymap))
+ (define-key c-mode-map "{" 'electric-c-brace)
+ (define-key c-mode-map "}" 'electric-c-brace)
+ (define-key c-mode-map ";" 'electric-c-semi)
+ (define-key c-mode-map ":" 'electric-c-terminator)
+ (define-key c-mode-map "\e\C-h" 'mark-c-function)
+ (define-key c-mode-map "\e\C-q" 'indent-c-exp)
+ (define-key c-mode-map "\177" 'backward-delete-char-untabify)
+ (define-key c-mode-map "\t" 'c-indent-command))
+
+(autoload 'c-macro-expand "cmacexp"
+ "Display the result of expanding all C macros occurring in the region.
+The expansion is entirely correct because it uses the C preprocessor."
+ t)
+
+(defvar c-mode-syntax-table nil
+ "Syntax table in use in C-mode buffers.")
+
+(if c-mode-syntax-table
+ ()
+ (setq c-mode-syntax-table (make-syntax-table))
+ (modify-syntax-entry ?\\ "\\" c-mode-syntax-table)
+ (modify-syntax-entry ?/ ". 14" c-mode-syntax-table)
+ (modify-syntax-entry ?* ". 23" c-mode-syntax-table)
+ (modify-syntax-entry ?+ "." c-mode-syntax-table)
+ (modify-syntax-entry ?- "." c-mode-syntax-table)
+ (modify-syntax-entry ?= "." c-mode-syntax-table)
+ (modify-syntax-entry ?% "." c-mode-syntax-table)
+ (modify-syntax-entry ?< "." c-mode-syntax-table)
+ (modify-syntax-entry ?> "." c-mode-syntax-table)
+ (modify-syntax-entry ?& "." c-mode-syntax-table)
+ (modify-syntax-entry ?| "." c-mode-syntax-table)
+ (modify-syntax-entry ?\' "\"" c-mode-syntax-table))
+
+(defconst c-indent-level 2
+ "*Indentation of C statements with respect to containing block.")
+(defconst c-brace-imaginary-offset 0
+ "*Imagined indentation of a C open brace that actually follows a statement.")
+(defconst c-brace-offset 0
+ "*Extra indentation for braces, compared with other text in same context.")
+(defconst c-argdecl-indent 5
+ "*Indentation level of declarations of C function arguments.")
+(defconst c-label-offset -2
+ "*Offset of C label lines and case statements relative to usual indentation.")
+(defconst c-continued-statement-offset 2
+ "*Extra indent for lines not starting new statements.")
+(defconst c-continued-brace-offset 0
+ "*Extra indent for substatements that start with open-braces.
+This is in addition to c-continued-statement-offset.")
+
+(defconst c-auto-newline nil
+ "*Non-nil means automatically newline before and after braces,
+and after colons and semicolons, inserted in C code.")
+
+(defconst c-tab-always-indent t
+ "*Non-nil means TAB in C mode should always reindent the current line,
+regardless of where in the line point is when the TAB command is used.")
+
+(defun c-mode ()
+ "Major mode for editing C code.
+Expression and list commands understand all C brackets.
+Tab indents for C code.
+Comments are delimited with /* ... */.
+Paragraphs are separated by blank lines only.
+Delete converts tabs to spaces as it moves back.
+\\{c-mode-map}
+Variables controlling indentation style:
+ c-tab-always-indent
+ Non-nil means TAB in C mode should always reindent the current line,
+ regardless of where in the line point is when the TAB command is used.
+ c-auto-newline
+ Non-nil means automatically newline before and after braces,
+ and after colons and semicolons, inserted in C code.
+ 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.
+ c-continued-statement-offset
+ Extra indentation given to a substatement, such as the
+ then-clause of an if or body of a while.
+ c-continued-brace-offset
+ Extra indentation given to a brace that starts a substatement.
+ This is in addition to c-continued-statement-offset.
+ c-brace-offset
+ Extra indentation for line if it starts with an open brace.
+ 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.
+ c-argdecl-indent
+ Indentation level of declarations of C function arguments.
+ c-label-offset
+ Extra indentation for line that is a label, or case or default.
+
+Settings for K&R and BSD indentation styles are
+ c-indent-level 5 8
+ c-continued-statement-offset 5 8
+ c-brace-offset -5 -8
+ c-argdecl-indent 0 8
+ c-label-offset -5 -8
+
+Turning on C mode calls the value of the variable c-mode-hook with no args,
+if that value is non-nil."
+ (interactive)
+ (kill-all-local-variables)
+ (use-local-map c-mode-map)
+ (setq major-mode 'c-mode)
+ (setq mode-name "C")
+ (setq local-abbrev-table c-mode-abbrev-table)
+ (set-syntax-table c-mode-syntax-table)
+ (make-local-variable 'paragraph-start)
+ (setq paragraph-start (concat "^$\\|" page-delimiter))
+ (make-local-variable 'paragraph-separate)
+ (setq paragraph-separate paragraph-start)
+ (make-local-variable 'paragraph-ignore-fill-prefix)
+ (setq paragraph-ignore-fill-prefix t)
+ (make-local-variable 'indent-line-function)
+ (setq indent-line-function 'c-indent-line)
+ (make-local-variable 'require-final-newline)
+ (setq require-final-newline t)
+ (make-local-variable 'comment-start)
+ (setq comment-start "/* ")
+ (make-local-variable 'comment-end)
+ (setq comment-end " */")
+ (make-local-variable 'comment-column)
+ (setq comment-column 32)
+ (make-local-variable 'comment-start-skip)
+ (setq comment-start-skip "/\\*+ *")
+ (make-local-variable 'comment-indent-hook)
+ (setq comment-indent-hook 'c-comment-indent)
+ (make-local-variable 'parse-sexp-ignore-comments)
+ (setq parse-sexp-ignore-comments t)
+ (run-hooks 'c-mode-hook))
+
+;; This is used by indent-for-comment
+;; to decide how much to indent a comment in C code
+;; based on its context.
+(defun c-comment-indent ()
+ (if (looking-at "^/\\*")
+ 0 ;Existing comment at bol stays there.
+ (save-excursion
+ (skip-chars-backward " \t")
+ (max (1+ (current-column)) ;Else indent at comment column
+ comment-column)))) ; except leave at least one space.
+
+(defun electric-c-brace (arg)
+ "Insert character and correct line's indentation."
+ (interactive "P")
+ (let (insertpos)
+ (if (and (not arg)
+ (eolp)
+ (or (save-excursion
+ (skip-chars-backward " \t")
+ (bolp))
+ (if c-auto-newline (progn (c-indent-line) (newline) t) nil)))
+ (progn
+ (insert last-command-char)
+ (c-indent-line)
+ (if c-auto-newline
+ (progn
+ (newline)
+ ;; (newline) may have done auto-fill
+ (setq insertpos (- (point) 2))
+ (c-indent-line)))
+ (save-excursion
+ (if insertpos (goto-char (1+ insertpos)))
+ (delete-char -1))))
+ (if insertpos
+ (save-excursion
+ (goto-char insertpos)
+ (self-insert-command (prefix-numeric-value arg)))
+ (self-insert-command (prefix-numeric-value arg)))))
+
+(defun electric-c-semi (arg)
+ "Insert character and correct line's indentation."
+ (interactive "P")
+ (if c-auto-newline
+ (electric-c-terminator arg)
+ (self-insert-command (prefix-numeric-value arg))))
+
+(defun electric-c-terminator (arg)
+ "Insert character and correct line's indentation."
+ (interactive "P")
+ (let (insertpos (end (point)))
+ (if (and (not arg) (eolp)
+ (not (save-excursion
+ (beginning-of-line)
+ (skip-chars-forward " \t")
+ (or (= (following-char) ?#)
+ ;; Colon is special only after a label, or case ....
+ ;; So quickly rule out most other uses of colon
+ ;; and do no indentation for them.
+ (and (eq last-command-char ?:)
+ (not (looking-at "case[ \t]"))
+ (save-excursion
+ (forward-word 1)
+ (skip-chars-forward " \t")
+ (< (point) end)))
+ (progn
+ (beginning-of-defun)
+ (let ((pps (parse-partial-sexp (point) end)))
+ (or (nth 3 pps) (nth 4 pps) (nth 5 pps))))))))
+ (progn
+ (insert last-command-char)
+ (c-indent-line)
+ (and c-auto-newline
+ (not (c-inside-parens-p))
+ (progn
+ (newline)
+ (setq insertpos (- (point) 2))
+ (c-indent-line)))
+ (save-excursion
+ (if insertpos (goto-char (1+ insertpos)))
+ (delete-char -1))))
+ (if insertpos
+ (save-excursion
+ (goto-char insertpos)
+ (self-insert-command (prefix-numeric-value arg)))
+ (self-insert-command (prefix-numeric-value arg)))))
+
+(defun c-inside-parens-p ()
+ (condition-case ()
+ (save-excursion
+ (save-restriction
+ (narrow-to-region (point)
+ (progn (beginning-of-defun) (point)))
+ (goto-char (point-max))
+ (= (char-after (or (scan-lists (point) -1 1) (point-min))) ?\()))
+ (error nil)))
+
+(defun c-indent-command (&optional whole-exp)
+ "Indent current line as C code, or in some cases insert a tab character.
+If c-tab-always-indent is non-nil (the default), always indent current line.
+Otherwise, indent the current line only if point is at the left margin
+or in the line's indentation; otherwise insert a tab.
+
+A numeric argument, regardless of its value,
+means indent rigidly all the lines of the expression starting after point
+so that this line becomes properly indented.
+The relative indentation among the lines of the expression are preserved."
+ (interactive "P")
+ (if whole-exp
+ ;; If arg, always indent this line as C
+ ;; and shift remaining lines of expression the same amount.
+ (let ((shift-amt (c-indent-line))
+ beg end)
+ (save-excursion
+ (if c-tab-always-indent
+ (beginning-of-line))
+ (setq beg (point))
+ (forward-sexp 1)
+ (setq end (point))
+ (goto-char beg)
+ (forward-line 1)
+ (setq beg (point)))
+ (if (> end beg)
+ (indent-code-rigidly beg end shift-amt "#")))
+ (if (and (not c-tab-always-indent)
+ (save-excursion
+ (skip-chars-backward " \t")
+ (not (bolp))))
+ (insert-tab)
+ (c-indent-line))))
+
+(defun c-indent-line ()
+ "Indent current line as C code.
+Return the amount the indentation changed by."
+ (let ((indent (calculate-c-indent nil))
+ beg shift-amt
+ (case-fold-search nil)
+ (pos (- (point-max) (point))))
+ (beginning-of-line)
+ (setq beg (point))
+ (cond ((eq indent nil)
+ (setq indent (current-indentation)))
+ ((eq indent t)
+ (setq indent (calculate-c-indent-within-comment)))
+ ((looking-at "[ \t]*#")
+ (setq indent 0))
+ (t
+ (skip-chars-forward " \t")
+ (if (listp indent) (setq indent (car indent)))
+ (cond ((or (looking-at "case[ \t]")
+ (and (looking-at "[A-Za-z]")
+ (save-excursion
+ (forward-sexp 1)
+ (looking-at ":"))))
+ (setq indent (max 1 (+ indent c-label-offset))))
+ ((and (looking-at "else\\b")
+ (not (looking-at "else\\s_")))
+ (setq indent (save-excursion
+ (c-backward-to-start-of-if)
+ (current-indentation))))
+ ((= (following-char) ?})
+ (setq indent (- indent c-indent-level)))
+ ((= (following-char) ?{)
+ (setq indent (+ indent c-brace-offset))))))
+ (skip-chars-forward " \t")
+ (setq shift-amt (- indent (current-column)))
+ (if (zerop shift-amt)
+ (if (> (- (point-max) pos) (point))
+ (goto-char (- (point-max) pos)))
+ (delete-region beg (point))
+ (indent-to indent)
+ ;; If initial point was within line's indentation,
+ ;; position after the indentation. Else stay at same point in text.
+ (if (> (- (point-max) pos) (point))
+ (goto-char (- (point-max) pos))))
+ shift-amt))
+
+(defun calculate-c-indent (&optional parse-start)
+ "Return appropriate indentation for current line as C code.
+In usual case returns an integer: the column to indent to.
+Returns nil if line starts inside a string, t if in a comment."
+ (save-excursion
+ (beginning-of-line)
+ (let ((indent-point (point))
+ (case-fold-search nil)
+ state
+ containing-sexp)
+ (if parse-start
+ (goto-char parse-start)
+ (beginning-of-defun))
+ (while (< (point) indent-point)
+ (setq parse-start (point))
+ (setq state (parse-partial-sexp (point) indent-point 0))
+ (setq containing-sexp (car (cdr state))))
+ (cond ((or (nth 3 state) (nth 4 state))
+ ;; return nil or t if should not change this line
+ (nth 4 state))
+ ((null containing-sexp)
+ ;; Line is at top level. May be data or function definition,
+ ;; or may be function argument declaration.
+ ;; Indent like the previous top level line
+ ;; unless that ends in a closeparen without semicolon,
+ ;; in which case this line is the first argument decl.
+ (goto-char indent-point)
+ (skip-chars-forward " \t")
+ (if (= (following-char) ?{)
+ 0 ; Unless it starts a function body
+ (c-backward-to-noncomment (or parse-start (point-min)))
+ ;; Look at previous line that's at column 0
+ ;; to determine whether we are in top-level decls
+ ;; or function's arg decls. Set basic-indent accordinglu.
+ (let ((basic-indent
+ (save-excursion
+ (re-search-backward "^[^ \^L\t\n#]" nil 'move)
+ (if (and (looking-at "\\sw\\|\\s_")
+ (looking-at "[^\"\n=(]*(")
+ (progn
+ (goto-char (1- (match-end 0)))
+ (forward-sexp 1)
+ (and (< (point) indent-point)
+ (not (memq (following-char)
+ '(?\, ?\;))))))
+ c-argdecl-indent 0))))
+ ;; Now add a little if this is a continuation line.
+ (+ basic-indent (if (or (bobp)
+ (memq (preceding-char) '(?\) ?\; ?\})))
+ 0 c-continued-statement-offset)))))
+ ((/= (char-after containing-sexp) ?{)
+ ;; line is expression, not statement:
+ ;; indent to just after the surrounding open.
+ (goto-char (1+ containing-sexp))
+ (current-column))
+ (t
+ ;; Statement level. Is it a continuation or a new statement?
+ ;; Find previous non-comment character.
+ (goto-char indent-point)
+ (c-backward-to-noncomment containing-sexp)
+ ;; Back up over label lines, since they don't
+ ;; affect whether our line is a continuation.
+ (while (or (eq (preceding-char) ?\,)
+ (and (eq (preceding-char) ?:)
+ (or (eq (char-after (- (point) 2)) ?\')
+ (memq (char-syntax (char-after (- (point) 2)))
+ '(?w ?_)))))
+ (if (eq (preceding-char) ?\,)
+ (c-backward-to-start-of-continued-exp containing-sexp))
+ (beginning-of-line)
+ (c-backward-to-noncomment containing-sexp))
+ ;; Now we get the answer.
+ (if (not (memq (preceding-char) '(nil ?\, ?\; ?\} ?\{)))
+ ;; This line is continuation of preceding line's statement;
+ ;; indent c-continued-statement-offset more than the
+ ;; previous line of the statement.
+ (progn
+ (c-backward-to-start-of-continued-exp containing-sexp)
+ (+ c-continued-statement-offset (current-column)
+ (if (save-excursion (goto-char indent-point)
+ (skip-chars-forward " \t")
+ (eq (following-char) ?{))
+ c-continued-brace-offset 0)))
+ ;; This line starts a new statement.
+ ;; Position following last unclosed open.
+ (goto-char containing-sexp)
+ ;; Is line first statement after an open-brace?
+ (or
+ ;; If no, find that first statement and indent like it.
+ (save-excursion
+ (forward-char 1)
+ (let ((colon-line-end 0))
+ (while (progn (skip-chars-forward " \t\n")
+ (looking-at "#\\|/\\*\\|case[ \t\n].*:\\|[a-zA-Z0-9_$]*:"))
+ ;; Skip over comments and labels following openbrace.
+ (cond ((= (following-char) ?\#)
+ (forward-line 1))
+ ((= (following-char) ?\/)
+ (forward-char 2)
+ (search-forward "*/" nil 'move))
+ ;; case or label:
+ (t
+ (save-excursion (end-of-line)
+ (setq colon-line-end (point)))
+ (search-forward ":"))))
+ ;; The first following code counts
+ ;; if it is before the line we want to indent.
+ (and (< (point) indent-point)
+ (-
+ (if (> colon-line-end (point))
+ (- (current-indentation) c-label-offset)
+ (current-column))
+ (if (= (following-char) ?\{) c-brace-offset 0)))))
+ ;; If no previous statement,
+ ;; indent it relative to line brace is on.
+ ;; For open brace in column zero, don't let statement
+ ;; start there too. If c-indent-level is zero,
+ ;; use c-brace-offset + c-continued-statement-offset instead.
+ ;; For open-braces not the first thing in a line,
+ ;; add in c-brace-imaginary-offset.
+ (+ (if (and (bolp) (zerop c-indent-level))
+ (+ c-brace-offset c-continued-statement-offset)
+ c-indent-level)
+ ;; Move back over whitespace before the openbrace.
+ ;; If openbrace is not first nonwhite thing on the line,
+ ;; add the c-brace-imaginary-offset.
+ (progn (skip-chars-backward " \t")
+ (if (bolp) 0 c-brace-imaginary-offset))
+ ;; If the openbrace is preceded by a parenthesized exp,
+ ;; move to the beginning of that;
+ ;; possibly a different line
+ (progn
+ (if (eq (preceding-char) ?\))
+ (forward-sexp -1))
+ ;; Get initial indentation of the line we are on.
+ (current-indentation))))))))))
+
+(defun calculate-c-indent-within-comment ()
+ "Return the indentation amount for line, assuming that
+the current line is to be regarded as part of a block comment."
+ (let (end star-start)
+ (save-excursion
+ (beginning-of-line)
+ (skip-chars-forward " \t")
+ (setq star-start (= (following-char) ?\*))
+ (skip-chars-backward " \t\n")
+ (setq end (point))
+ (beginning-of-line)
+ (skip-chars-forward " \t")
+ (and (re-search-forward "/\\*[ \t]*" end t)
+ star-start
+ (goto-char (1+ (match-beginning 0))))
+ (current-column))))
+
+
+(defun c-backward-to-noncomment (lim)
+ (let (opoint stop)
+ (while (not stop)
+ (skip-chars-backward " \t\n\f" lim)
+ (setq opoint (point))
+ (if (and (>= (point) (+ 2 lim))
+ (save-excursion
+ (forward-char -2)
+ (looking-at "\\*/")))
+ (search-backward "/*" lim 'move)
+ (setq stop (or (<= (point) lim)
+ (save-excursion
+ (beginning-of-line)
+ (skip-chars-forward " \t")
+ (not (looking-at "#")))))
+ (or stop (beginning-of-line))))))
+
+(defun c-backward-to-start-of-continued-exp (lim)
+ (if (= (preceding-char) ?\))
+ (forward-sexp -1))
+ (beginning-of-line)
+ (if (<= (point) lim)
+ (goto-char (1+ lim)))
+ (skip-chars-forward " \t"))
+
+(defun c-backward-to-start-of-if (&optional limit)
+ "Move to the start of the last ``unbalanced'' if."
+ (or limit (setq limit (save-excursion (beginning-of-defun) (point))))
+ (let ((if-level 1)
+ (case-fold-search nil))
+ (while (not (zerop if-level))
+ (backward-sexp 1)
+ (cond ((looking-at "else\\b")
+ (setq if-level (1+ if-level)))
+ ((looking-at "if\\b")
+ (setq if-level (1- if-level)))
+ ((< (point) limit)
+ (setq if-level 0)
+ (goto-char limit))))))
+
+
+(defun mark-c-function ()
+ "Put mark at end of C function, point at beginning."
+ (interactive)
+ (push-mark (point))
+ (end-of-defun)
+ (push-mark (point))
+ (beginning-of-defun)
+ (backward-paragraph))
+
+(defun indent-c-exp ()
+ "Indent each line of the C grouping following point."
+ (interactive)
+ (let ((indent-stack (list nil))
+ (contain-stack (list (point)))
+ (case-fold-search nil)
+ restart outer-loop-done inner-loop-done state ostate
+ this-indent last-sexp
+ at-else at-brace
+ (opoint (point))
+ (next-depth 0))
+ (save-excursion
+ (forward-sexp 1))
+ (save-excursion
+ (setq outer-loop-done nil)
+ (while (and (not (eobp)) (not outer-loop-done))
+ (setq last-depth next-depth)
+ ;; Compute how depth changes over this line
+ ;; plus enough other lines to get to one that
+ ;; does not end inside a comment or string.
+ ;; Meanwhile, do appropriate indentation on comment lines.
+ (setq inner-loop-done nil)
+ (while (and (not inner-loop-done)
+ (not (and (eobp) (setq outer-loop-done t))))
+ (setq ostate state)
+ (setq state (parse-partial-sexp (point) (progn (end-of-line) (point))
+ nil nil state))
+ (setq next-depth (car state))
+ (if (and (car (cdr (cdr state)))
+ (>= (car (cdr (cdr state))) 0))
+ (setq last-sexp (car (cdr (cdr state)))))
+ (if (or (nth 4 ostate))
+ (c-indent-line))
+ (if (or (nth 3 state))
+ (forward-line 1)
+ (setq inner-loop-done t)))
+ (if (<= next-depth 0)
+ (setq outer-loop-done t))
+ (if outer-loop-done
+ nil
+ ;; If this line had ..))) (((.. in it, pop out of the levels
+ ;; that ended anywhere in this line, even if the final depth
+ ;; doesn't indicate that they ended.
+ (while (> last-depth (nth 6 state))
+ (setq indent-stack (cdr indent-stack)
+ contain-stack (cdr contain-stack)
+ last-depth (1- last-depth)))
+ (if (/= last-depth next-depth)
+ (setq last-sexp nil))
+ ;; Add levels for any parens that were started in this line.
+ (while (< last-depth next-depth)
+ (setq indent-stack (cons nil indent-stack)
+ contain-stack (cons nil contain-stack)
+ last-depth (1+ last-depth)))
+ (if (null (car contain-stack))
+ (setcar contain-stack (or (car (cdr state))
+ (save-excursion (forward-sexp -1)
+ (point)))))
+ (forward-line 1)
+ (skip-chars-forward " \t")
+ (if (eolp)
+ nil
+ (if (and (car indent-stack)
+ (>= (car indent-stack) 0))
+ ;; Line is on an existing nesting level.
+ ;; Lines inside parens are handled specially.
+ (if (/= (char-after (car contain-stack)) ?{)
+ (setq this-indent (car indent-stack))
+ ;; Line is at statement level.
+ ;; Is it a new statement? Is it an else?
+ ;; Find last non-comment character before this line
+ (save-excursion
+ (setq at-else (looking-at "else\\W"))
+ (setq at-brace (= (following-char) ?{))
+ (c-backward-to-noncomment opoint)
+ (if (not (memq (preceding-char) '(nil ?\, ?\; ?} ?: ?{)))
+ ;; Preceding line did not end in comma or semi;
+ ;; indent this line c-continued-statement-offset
+ ;; more than previous.
+ (progn
+ (c-backward-to-start-of-continued-exp (car contain-stack))
+ (setq this-indent
+ (+ c-continued-statement-offset (current-column)
+ (if at-brace c-continued-brace-offset 0))))
+ ;; Preceding line ended in comma or semi;
+ ;; use the standard indent for this level.
+ (if at-else
+ (progn (c-backward-to-start-of-if opoint)
+ (setq this-indent (current-indentation)))
+ (setq this-indent (car indent-stack))))))
+ ;; Just started a new nesting level.
+ ;; Compute the standard indent for this level.
+ (let ((val (calculate-c-indent
+ (if (car indent-stack)
+ (- (car indent-stack))))))
+ (setcar indent-stack
+ (setq this-indent val))))
+ ;; Adjust line indentation according to its contents
+ (if (or (looking-at "case[ \t]")
+ (and (looking-at "[A-Za-z]")
+ (save-excursion
+ (forward-sexp 1)
+ (looking-at ":"))))
+ (setq this-indent (max 1 (+ this-indent c-label-offset))))
+ (if (= (following-char) ?})
+ (setq this-indent (- this-indent c-indent-level)))
+ (if (= (following-char) ?{)
+ (setq this-indent (+ this-indent c-brace-offset)))
+ ;; Put chosen indentation into effect.
+ (or (= (current-column) this-indent)
+ (= (following-char) ?\#)
+ (progn
+ (delete-region (point) (progn (beginning-of-line) (point)))
+ (indent-to this-indent)))
+ ;; Indent any comment following the text.
+ (or (looking-at comment-start-skip)
+ (if (re-search-forward comment-start-skip (save-excursion (end-of-line) (point)) t)
+ (progn (indent-for-comment) (beginning-of-line)))))))))
+; (message "Indenting C expression...done")
+ )
diff --git a/lisp/c-mode.elc b/lisp/c-mode.elc
new file mode 100644
index 00000000000..83abc2b349a
--- /dev/null
+++ b/lisp/c-mode.elc
Binary files differ
diff --git a/lisp/cal.el b/lisp/cal.el
new file mode 100644
index 00000000000..2c39c4c5147
--- /dev/null
+++ b/lisp/cal.el
@@ -0,0 +1,242 @@
+;; Display a calendar inside GNU Emacs.
+;; Copyright (C) 1988 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 1, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+;;
+;; Comments, corrections, and improvements should be sent to
+;; Edward M. Reingold Department of Computer Science
+;; (217) 333-6733 University of Illinois at Urbana-Champaign
+;; reingold@a.cs.uiuc.edu 1304 West Springfield Avenue
+;; Urbana, Illinois 61801
+;;
+;; The author gratefully acknowledges the patient help of Richard Stallman
+;; in making this function into a reasonable piece of code!
+;;
+;; Modification for month-offset arguments suggested and implemented by
+;; Constantine Rasmussen Sun Microsystems, East Coast Division
+;; (617) 671-0404 2 Federal Street; Billerica, Ma. 01824
+;; ARPA: cdr@sun.com USENET: {cbosgd,decvax,hplabs,seismo}!sun!suneast!cdr
+;;
+;; Modification to mark current day with stars suggested by
+;; Franklin Davis Thinking Machines Corp
+;; (617) 876-1111 245 First Street, Cambridge, MA 02142
+;; fad@think.com
+
+(defvar calendar-hook nil
+ "List of functions called after the calendar buffer has been prepared with
+the calendar of the current month. This can be used, for example, to highlight
+today's date with asterisks--a function star-date is included for this purpose.
+The variable offset-calendar-hook is the list of functions called when the
+calendar function was called for a past or future month.")
+
+(defvar offset-calendar-hook nil
+ "List of functions called after the calendar buffer has been prepared with
+the calendar of a past or future month. The variable calendar-hook is the
+list of functions called when the calendar function was called for the
+current month.")
+
+(defun calendar (&optional month-offset)
+ "Display three-month calendar in another window.
+The three months appear side by side, with the current month in the middle
+surrounded by the previous and next months. The cursor is put on today's date.
+
+An optional prefix argument ARG causes the calendar displayed to be
+ARG months in the future if ARG is positive or in the past if ARG is
+negative; in this case the cursor goes on the first day of the month.
+
+The Gregorian calendar is assumed.
+
+After preparing the calendar window, the hooks calendar-hook are run
+when the calendar is for the current month--that is, the was no prefix
+argument. If the calendar is for a future or past month--that is, there
+was a prefix argument--the hooks offset-calendar-hook are run. Thus, for
+example, setting calendar-hooks to 'star-date will cause today's date to be
+replaced by asterisks to highlight it in the window."
+ (interactive "P")
+ (if month-offset (setq month-offset (prefix-numeric-value month-offset)))
+ (let ((today (make-marker)))
+ (save-excursion
+ (set-buffer (get-buffer-create "*Calendar*"))
+ (setq buffer-read-only t)
+ (let*
+ ((buffer-read-only nil)
+ ;; Get today's date and extract the day, month and year.
+ (date (current-time-string))
+ (garbage (string-match
+ " \\([A-Z][a-z][a-z]\\) *\\([0-9]*\\) .* \\([0-9]*\\)$"
+ date))
+ (day (or (and month-offset 1)
+ (string-to-int
+ (substring date (match-beginning 2) (match-end 2)))))
+ (month
+ (cdr (assoc
+ (substring date (match-beginning 1) (match-end 1))
+ '(("Jan" . 1) ("Feb" . 2) ("Mar" . 3) ("Apr" . 4)
+ ("May" . 5) ("Jun" . 6) ("Jul" . 7) ("Aug" . 8)
+ ("Sep" . 9) ("Oct" . 10) ("Nov" . 11) ("Dec" . 12)))))
+ (year (string-to-int
+ (substring date (match-beginning 3) (match-end 3)))))
+ (erase-buffer)
+ ;; If user requested a month in the future or the past,
+ ;; advance the variables MONTH and YEAR to describe that one.
+ (cond
+ (month-offset
+ (let ((year-month (+ (+ (* year 12) (- month 1)) month-offset)))
+ (setq month (+ (% year-month 12) 1))
+ (setq year (/ year-month 12)))))
+ ;; Generate previous month, starting at left margin.
+ (generate-month;; previous month
+ (if (= month 1) 12 (1- month))
+ (if (= month 1) (1- year) year)
+ 0)
+ ;; Generate this month, starting at column 24,
+ ;; and record where today's date appears, in the marker TODAY.
+ (goto-char (point-min))
+ (set-marker today (generate-month month year 24 day))
+ ;; Generate the following month, starting at column 48.
+ (goto-char (point-min))
+ (generate-month
+ (if (= month 12) 1 (1+ month))
+ (if (= month 12) (1+ year) year)
+ 48)))
+ ;; Display the buffer and put cursor on today's date.
+ ;; Do it in another window, but if this buffer is already visible,
+ ;; just select its window.
+ (pop-to-buffer "*Calendar*")
+ (goto-char (marker-position today))
+ ;; Make TODAY point nowhere so it won't slow down buffer editing until GC.
+ (set-marker today nil))
+ ;; Make the window just tall enough for its contents.
+ (let ((h (1- (window-height)))
+ (l (count-lines (point-min) (point-max))))
+ (or (= (+ (window-height (selected-window))
+ (window-height (minibuffer-window)))
+ (screen-height))
+ (<= h l)
+ (shrink-window (- h l))))
+ (if month-offset
+ (run-hooks 'offset-calendar-hook)
+ (run-hooks 'calendar-hook)))
+
+(defun leap-year-p (year)
+ "Returns true if YEAR is a Gregorian leap year, and false if not."
+ (or
+ (and (= (% year 4) 0)
+ (/= (% year 100) 0))
+ (= (% year 400) 0)))
+
+(defun day-number (month day year)
+ "Return day-number within year (origin-1) of the date MONTH DAY YEAR.
+For example, (day-number 1 1 1987) returns the value 1,
+while (day-number 12 31 1980) returns 366."
+;;
+;; an explanation of the calculation can be found in PascAlgorithms by
+;; Edward and Ruth Reingold, Scott-foresman/Little, Brown, 1988.
+;;
+ (let ((day-of-year (+ day (* 31 (1- month)))))
+ (if (> month 2)
+ (progn
+ (setq day-of-year (- day-of-year (/ (+ 23 (* 4 month)) 10)))
+ (if (leap-year-p year)
+ (setq day-of-year (1+ day-of-year)))))
+ day-of-year))
+
+(defun day-of-week (month day year)
+ "Returns the day-of-the-week index of MONTH DAY, YEAR.
+Value is 0 for Sunday, 1 for Monday, etc."
+;;
+;; Done by calculating the number of days elapsed since the (imaginary)
+;; Gregorian date Sunday, December 31, 1 BC and taking that number mod 7.
+;;
+ (%
+ (-
+ (+ (day-number month day year)
+ (* 365 (1- year))
+ (/ (1- year) 4))
+ (let ((correction (* (/ (1- year) 100) 3)))
+ (if (= (% correction 4) 0)
+ (/ correction 4)
+ (1+ (/ correction 4)))))
+ 7))
+
+(defun generate-month (month year indent &optional day)
+ "Produce a calendar for MONTH, YEAR on the Gregorian calendar, inserted
+in the buffer starting at the line on which point is currently located, but
+indented INDENT spaces. The position in the buffer of the optional
+parameter DAY is returned. The indentation is done from the first
+character on the line and does not disturb the first INDENT characters on
+the line."
+ (let* ((first-day-of-month (day-of-week month 1 year))
+ (first-saturday (- 7 first-day-of-month))
+ (last-of-month
+ (if (and (leap-year-p year) (= month 2))
+ 29
+ (aref [31 28 31 30 31 30 31 31 30 31 30 31] (1- month))))
+ (month-name
+ (aref ["January" "February" "March" "April" "May" "June"
+ "July" "August" "September" "October" "November" "December"]
+ (1- month))))
+ (insert-indented (format " %s %d" month-name year) indent t)
+ (insert-indented " S M Tu W Th F S" indent t)
+ (insert-indented "" indent);; move point to appropriate spot on line
+ (let ((i 0)) ;; add blank days before the first of the month
+ (while (<= (setq i (1+ i)) first-day-of-month)
+ (insert " ")))
+ (let ((i 0)
+ (day-marker)) ;; put in the days of the month
+ (while (<= (setq i (1+ i)) last-of-month)
+ (insert (format "%2d " i))
+ (and
+ day
+ (= i day) ;; save the location of the specified day
+ (setq day-marker (- (point) 2)))
+ (and (= (% i 7) (% first-saturday 7))
+ (/= i last-of-month)
+ (insert-indented "" 0 t) ;; force onto following line
+ (insert-indented "" indent))) ;; go to proper spot on line
+ day-marker)))
+
+(defun insert-indented (string indent &optional newline)
+ "Insert STRING at column INDENT.
+If the optional parameter NEWLINE is true, leave point at start of next
+line, inserting a newline if there was no next line; otherwise, leave point
+after the inserted text. Value is always `t'."
+ ;; Try to move to that column.
+ (move-to-column indent)
+ ;; If line is too short, indent out to that column.
+ (if (< (current-column) indent)
+ (indent-to indent))
+ (insert string)
+ ;; Advance to next line, if requested.
+ (if newline
+ (progn
+ (end-of-line)
+ (if (eobp)
+ (newline)
+ (forward-line 1))))
+ t)
+
+(defun star-date ()
+ "Replace today's date with asterisks in the calendar window.
+This function can be used with the calendar-hook run after the
+calendar window has been prepared."
+ (let ((buffer-read-only nil))
+ (forward-char 1)
+ (delete-backward-char 2)
+ (insert "**")
+ (backward-char 1)))
+
diff --git a/lisp/cal.elc b/lisp/cal.elc
new file mode 100644
index 00000000000..b51d15fe803
--- /dev/null
+++ b/lisp/cal.elc
Binary files differ
diff --git a/lisp/calendar/appt.el b/lisp/calendar/appt.el
deleted file mode 100644
index 5d11695cdaf..00000000000
--- a/lisp/calendar/appt.el
+++ /dev/null
@@ -1,500 +0,0 @@
-;; Appointment notification functions.
-;; Copyright (C) 1989, 1990 Free Software Foundation, Inc.
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 1, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
-;;
-;; appt.el - visible and/or audible notification of
-;; appointments from ~/diary file generated from
-;; Edward M. Reingold's calendar.el.
-;;
-;; Version 2.1
-;;
-;; Comments, corrections, and improvements should be sent to
-;; Neil M. Mager
-;; Net <neilm@juliet.ll.mit.edu>
-;; Voice (617) 981-4803
-;;;
-;;; Thanks to Edward M. Reingold for much help and many suggestions,
-;;; And to many others for bug fixes and suggestions.
-;;;
-;;;
-;;; This functions in this file will alert the user of a
-;;; pending appointment based on their diary file.
-;;;
-;;;
-;;; ******* It is necessary to invoke 'display-time' ********
-;;; ******* and 'diary' for this to work properly. ********
-;;;
-;;; A message will be displayed in the mode line of the emacs buffer
-;;; and (if the user desires) the terminal will beep and display a message
-;;; from the diary in the mini-buffer, or the user may select to
-;;; have a message displayed in a new buffer.
-;;;
-;;; The variable 'appt-message-warning-time' allows the
-;;; user to specify how much notice they want before the appointment. The
-;;; variable 'appt-issue-message' specifies whether the user wants
-;;; to to be notified of a pending appointment.
-;;;
-;;; In order to use, the following should be in your .emacs file in addition to
-;;; creating a diary file and invoking calendar:
-;;;
-;;; Set some options
-;;; (setq view-diary-entries-initially t)
-;;; (setq appt-issue-message t)
-;;;
-;;; The following three lines are required:
-;;; (display-time)
-;;; (autoload 'appt-make-list "appt.el" nil t)
-;;; (setq diary-display-hook
-;;; (list 'appt-make-list 'prepare-fancy-diary-buffer))
-;;;
-;;;
-;;; This is an example of what can be in your diary file:
-;;; Monday
-;;; 9:30am Coffee break
-;;; 12:00pm Lunch
-;;;
-;;; Based upon the above lines in your .emacs and diary files,
-;;; the calendar and diary will be displayed when you enter
-;;; emacs and your appointments list will automatically be created.
-;;; You will then be reminded at 9:20am about your coffee break
-;;; and at 11:50am to go to lunch.
-;;;
-;;; Use describe-function on appt-check for a description of other variables
-;;; that can be used to personalize the notification system.
-;;;
-;;; In order to add or delete items from todays list, use appt-add
-;;; and appt-delete.
-;;;
-;;; Additionally, the appointments list is recreated automatically
-;;; at 12:01am for those who do not logout every day or are programming
-;;; late.
-;;;
-;;; Brief internal description - Skip this if your not interested!
-;;;
-;;; The function appt-check is run from the 'loadst' process which is started
-;;; by invoking (display-time). A temporary function below modifies
-;;; display-time-filter
-;;; (from original time.el) to include a hook which will invoke appt-check.
-;;; This will not be necessary in the next version of gnuemacs.
-;;;
-;;;
-;;; The function appt-make-list creates the appointments list which appt-check
-;;; reads. This is all done automatically.
-;;; It is invoked from the function list-diary-entries.
-;;;
-(defvar appt-issue-message t
- "*Non-nil means check for appointments in the diary buffer.
-To be detected, the diary entry must have the time
-as the first thing on a line.")
-
-(defvar appt-message-warning-time 10
- "*Time in minutes before an appointment that the warning begins.")
-
-(defvar appt-audible t
- "*Non-nil means beep to indicate appointment.")
-
-(defvar appt-visible t
- "*Non-nil means display appointment message in echo area.")
-
-(defvar appt-display-mode-line t
- "*Non-nil means display minutes to appointment and time on the mode line.")
-
-(defvar appt-msg-window t
- "*Non-nil means display appointment message in another window.")
-
-(defvar appt-display-duration 5
- "*The number of seconds an appointment message is displayed.")
-
-(defvar appt-display-diary t
- "*Non-nil means to display the next days diary on the screen.
-This will occur at midnight when the appointment list is updated.")
-
-(defvar appt-time-msg-list nil
- "The list of appointments for today.
-Use `appt-add' and `appt-delete' to add and delete appointments from list.
-The original list is generated from the today's `diary-entries-list'.
-The number before each time/message is the time in minutes from midnight.")
-
-(defconst max-time 1439
- "11:59pm in minutes - number of minutes in a day minus 1.")
-
-(defun appt-check ()
- "Check for an appointment and update the mode line.
-Note: the time must be the first thing in the line in the diary
-for a warning to be issued.
-
-The format of the time can be either 24 hour or am/pm.
-Example:
-
- 02/23/89
- 18:00 Dinner
-
- Thursday
- 11:45am Lunch meeting.
-
-The following variables control the action of the notification:
-
-appt-issue-message
- If T, the diary buffer is checked for appointments.
-
-appt-message-warning-time
- Variable used to determine if appointment message
- should be displayed.
-
-appt-audible
- Variable used to determine if appointment is audible.
- Default is t.
-
-appt-visible
- Variable used to determine if appointment message should be
- displayed in the mini-buffer. Default is t.
-
-appt-msg-window
- Variable used to determine if appointment message
- should temporarily appear in another window. Mutually exclusive
- to appt-visible.
-
-appt-display-duration
- The number of seconds an appointment message
- is displayed in another window.
-
-This function is run from the loadst process for display time.
-Therefore, you need to have `(display-time)' in your .emacs file."
-
-
- (let ((min-to-app -1)
- (new-time ""))
- (save-excursion
-
- ;; Get the current time and convert it to minutes
- ;; from midnight. ie. 12:01am = 1, midnight = 0.
-
- (let* ((cur-hour(string-to-int
- (substring (current-time-string) 11 13)))
- (cur-min (string-to-int
- (substring (current-time-string) 14 16)))
- (cur-comp-time (+ (* cur-hour 60) cur-min)))
-
- ;; If the time is 12:01am, we should update our
- ;; appointments to todays list.
-
- (if (= cur-comp-time 1)
- (if (and view-diary-entries-initially appt-display-diary)
- (diary)
- (let ((diary-display-hook 'appt-make-list))
- (diary))))
-
- ;; If there are entries in the list, and the
- ;; user wants a message issued
- ;; get the first time off of the list
- ;; and calculate the number of minutes until
- ;; the appointment.
-
- (if (and appt-issue-message appt-time-msg-list)
- (let ((appt-comp-time (car (car (car appt-time-msg-list)))))
- (setq min-to-app (- appt-comp-time cur-comp-time))
-
- (while (and appt-time-msg-list
- (< appt-comp-time cur-comp-time))
- (setq appt-time-msg-list (cdr appt-time-msg-list))
- (if appt-time-msg-list
- (setq appt-comp-time
- (car (car (car appt-time-msg-list))))))
-
- ;; If we have an appointment between midnight and
- ;; 'appt-message-warning-time' minutes after midnight,
- ;; we must begin to issue a message before midnight.
- ;; Midnight is considered 0 minutes and 11:59pm is
- ;; 1439 minutes. Therefore we must recalculate the minutes
- ;; to appointment variable. It is equal to the number of
- ;; minutes before midnight plus the number of
- ;; minutes after midnight our appointment is.
-
- (if (and (< appt-comp-time appt-message-warning-time)
- (> (+ cur-comp-time appt-message-warning-time)
- max-time))
- (setq min-to-app (+ (- (1+ max-time) cur-comp-time))
- appt-comp-time))
-
- ;; issue warning if the appointment time is
- ;; within appt-message-warning time
-
- (if (and (<= min-to-app appt-message-warning-time)
- (>= min-to-app 0))
- (progn
- (if appt-msg-window
- (progn
- (string-match
- "[0-9]?[0-9]:[0-9][0-9]\\(am\\|pm\\)?"
- display-time-string)
-
- (setq new-time (substring display-time-string
- (match-beginning 0)
- (match-end 0)))
- (appt-disp-window min-to-app new-time
- (car (cdr (car appt-time-msg-list)))))
- ;;; else
-
- (if appt-visible
- (message "%s"
- (car (cdr (car appt-time-msg-list)))))
-
- (if appt-audible
- (beep 1)))
-
- (if appt-display-mode-line
- (progn
- (string-match
- "[0-9]?[0-9]:[0-9][0-9]\\(am\\|pm\\)?"
- display-time-string)
-
- (setq new-time (substring display-time-string
- (match-beginning 0)
- (match-end 0)))
- (setq display-time-string
- (concat "App't in "
- min-to-app " min. " new-time " "))
-
- ;; force mode line updates - from time.el
-
- (save-excursion (set-buffer (other-buffer)))
- (set-buffer-modified-p (buffer-modified-p))
- (sit-for 0)))
-
- (if (= min-to-app 0)
- (setq appt-time-msg-list
- (cdr appt-time-msg-list)))))))))))
-
-
-;; Display appointment message in a separate buffer.
-(defun appt-disp-window (min-to-app new-time appt-msg)
- (require 'electric)
- (save-window-excursion
-
- ;; Make sure we're not in the minibuffer
- ;; before splitting the window.
-
- (if (= (screen-height)
- (nth 3 (window-edges (selected-window))))
- nil
- (appt-select-lowest-window)
- (split-window))
-
- (let* ((this-buffer (current-buffer))
- (appt-disp-buf (set-buffer (get-buffer-create "appt-buf"))))
- (setq mode-line-format
- (concat "-------------------- Appointment in "
- min-to-app " minutes. " new-time " %-"))
- (pop-to-buffer appt-disp-buf)
- (insert-string appt-msg)
- (shrink-window-if-larger-than-buffer (get-buffer-window appt-disp-buf))
- (set-buffer-modified-p nil)
- (if appt-audible
- (beep 1))
- (sit-for appt-display-duration)
- (if appt-audible
- (beep 1))
- (kill-buffer appt-disp-buf))))
-
-;; Select the lowest window on the screen.
-(defun appt-select-lowest-window ()
- (setq lowest-window (selected-window))
- (let* ((bottom-edge (car (cdr (cdr (cdr (window-edges))))))
- (last-window (previous-window))
- (window-search t))
- (while window-search
- (let* ((this-window (next-window))
- (next-bottom-edge (car (cdr (cdr (cdr
- (window-edges this-window)))))))
- (if (< bottom-edge next-bottom-edge)
- (progn
- (setq bottom-edge next-bottom-edge)
- (setq lowest-window this-window)))
-
- (select-window this-window)
- (if (eq last-window this-window)
- (progn
- (select-window lowest-window)
- (setq window-search nil)))))))
-
-
-(defun appt-add (new-appt-time new-appt-msg)
- "Add an appointment for the day at TIME and issue MESSAGE.
-The time should be in either 24 hour format or am/pm format."
-
- (interactive "sTime (hh:mm[am/pm]): \nsMessage: ")
- (if (string-match "[0-9]?[0-9]:[0-9][0-9]\\(am\\|pm\\)?" new-appt-time)
- nil
- (error "Unacceptable time-string"))
-
- (let* ((appt-time-string (concat new-appt-time " " new-appt-msg))
- (appt-time (list (appt-convert-time new-appt-time)))
- (time-msg (cons appt-time (list appt-time-string))))
- (setq appt-time-msg-list (append appt-time-msg-list
- (list time-msg)))
- (setq appt-time-msg-list (appt-sort-list appt-time-msg-list))))
-
-(defun appt-delete ()
- "Delete an appointment from the list of appointments."
- (interactive)
- (let* ((tmp-msg-list appt-time-msg-list))
- (while tmp-msg-list
- (let* ((element (car tmp-msg-list))
- (prompt-string (concat "Delete "
- (prin1-to-string (car (cdr element)))
- " from list? "))
- (test-input (y-or-n-p prompt-string)))
- (setq tmp-msg-list (cdr tmp-msg-list))
- (if test-input
- (setq appt-time-msg-list (delq element appt-time-msg-list)))
- (setq tmp-appt-msg-list nil)))
- (message "")))
-
-
-;; Create the appointments list from todays diary buffer.
-;; The time must be at the beginning of a line for it to be
-;; put in the appointments list.
-;; 02/23/89
-;; 12:00pm lunch
-;; Wednesday
-;; 10:00am group meeting"
-
-(defun appt-make-list ()
- (setq appt-time-msg-list nil)
-
- (save-excursion
- (if diary-entries-list
-
- ;; Cycle through the entry-list (diary-entries-list)
- ;; looking for entries beginning with a time. If
- ;; the entry begins with a time, add it to the
- ;; appt-time-msg-list. Then sort the list.
-
- (let ((entry-list diary-entries-list)
- (new-time-string ""))
- (while (and entry-list
- (calendar-date-equal
- (calendar-current-date) (car (car entry-list))))
- (let ((time-string (substring (prin1-to-string
- (cdr (car entry-list))) 2 -2)))
-
- (while (string-match
- "[0-9]?[0-9]:[0-9][0-9]\\(am\\|pm\\)?.*"
- time-string)
- (let* ((appt-time-string (substring time-string
- (match-beginning 0)
- (match-end 0))))
-
- (if (< (match-end 0) (length time-string))
- (setq new-time-string (substring time-string
- (+ (match-end 0) 1)
- nil))
- (setq new-time-string ""))
-
- (string-match "[0-9]?[0-9]:[0-9][0-9]\\(am\\|pm\\)?"
- time-string)
-
- (let* ((appt-time (list (appt-convert-time
- (substring time-string
- (match-beginning 0)
- (match-end 0)))))
- (time-msg (cons appt-time
- (list appt-time-string))))
- (setq time-string new-time-string)
- (setq appt-time-msg-list (append appt-time-msg-list
- (list time-msg)))))))
- (setq entry-list (cdr entry-list)))))
- (setq appt-time-msg-list (appt-sort-list appt-time-msg-list))
-
- ;; Get the current time and convert it to minutes
- ;; from midnight. ie. 12:01am = 1, midnight = 0,
- ;; so that the elements in the list
- ;; that are earlier than the present time can
- ;; be removed.
-
- (let* ((cur-hour(string-to-int
- (substring (current-time-string) 11 13)))
- (cur-min (string-to-int
- (substring (current-time-string) 14 16)))
- (cur-comp-time (+ (* cur-hour 60) cur-min))
- (appt-comp-time (car (car (car appt-time-msg-list)))))
-
- (while (and appt-time-msg-list (< appt-comp-time cur-comp-time))
- (setq appt-time-msg-list (cdr appt-time-msg-list))
- (if appt-time-msg-list
- (setq appt-comp-time (car (car (car appt-time-msg-list)))))))))
-
-
-;;Simple sort to put the appointments list in order.
-;;Scan the list for the smallest element left in the list.
-;;Append the smallest element left into the new list, and remove
-;;it from the original list.
-(defun appt-sort-list (appt-list)
- (let ((order-list nil))
- (while appt-list
- (let* ((element (car appt-list))
- (element-time (car (car element)))
- (tmp-list (cdr appt-list)))
- (while tmp-list
- (if (< element-time (car (car (car tmp-list))))
- nil
- (setq element (car tmp-list))
- (setq element-time (car (car element))))
- (setq tmp-list (cdr tmp-list)))
- (setq order-list (append order-list (list element)))
- (setq appt-list (delq element appt-list))))
- order-list))
-
-
-(defun appt-convert-time (time2conv)
- "Convert hour:min[am/pm] format to minutes from midnight."
-
- (let ((conv-time 0)
- (hr 0)
- (min 0))
-
- (string-match ":[0-9][0-9]" time2conv)
- (setq min (string-to-int
- (substring time2conv
- (+ (match-beginning 0) 1) (match-end 0))))
-
- (string-match "[0-9]?[0-9]:" time2conv)
- (setq hr (string-to-int
- (substring time2conv
- (match-beginning 0)
- (match-end 0))))
-
- ;; convert the time appointment time into 24 hour time
-
- (if (and (string-match "[p][m]" time2conv) (< hr 12))
- (progn
- (string-match "[0-9]?[0-9]:" time2conv)
- (setq hr (+ 12 hr))))
-
- ;; convert the actual time
- ;; into minutes for comparison
- ;; against the actual time.
-
- (setq conv-time (+ (* hr 60) min))
- conv-time))
-
-
-(setq display-time-hook 'appt-check)
-
-
diff --git a/lisp/case-table.el b/lisp/case-table.el
deleted file mode 100644
index f10580fe575..00000000000
--- a/lisp/case-table.el
+++ /dev/null
@@ -1,101 +0,0 @@
-;; Functions for extending the character set and dealing with case tables.
-;; Copyright (C) 1988 Free Software Foundation, Inc.
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 1, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
-
-;; Written by:
-;; TN/ETX/TX/UMG Howard Gayle UUCP : seismo!enea!erix!howard
-;; Telefonaktiebolaget L M Ericsson Phone: +46 8 719 55 65
-;; Ericsson Telecom Telex: 14910 ERIC S
-;; S-126 25 Stockholm FAX : +46 8 719 64 82
-;; Sweden
-
-(defun describe-buffer-case-table ()
- "Describe the case table of the current buffer."
- (interactive)
- (let ((vector (make-vector 256 nil))
- (case-table (current-case-table))
- (i 0))
- (while (< i 256)
- (aset vector i
- (cond ((/= ch (downcase ch))
- (concat "uppercase, matches "
- (text-char-description (downcase ch))))
- ((/= ch (upcase ch))
- (concat "lowercase, matches "
- (text-char-description (upcase ch))))
- (t "case-invariant")))
- (setq i (1+ i))))
- (with-output-to-temp-buffer "*Help*"
- (describe-vector vector)))
-
-(defun invert-case (count)
- "Change the case of the character just after point and move over it.
-With arg, applies to that many chars.
-Negative arg inverts characters before point but does not move."
- (interactive "p")
- (if (< count 0)
- (progn (setq count (min (1- (point)) (- count)))
- (forward-char (- count))))
- (while (> count 0)
- (let ((oc (following-char))) ; Old character.
- (cond ((/= (upcase ch) ch)
- (replace-char (upcase ch)))
- ((/= (downcase ch) ch)
- (replace-char (downcase ch)))))
- (forward-char 1)
- (setq count (1- count))))
-
-(defun set-case-syntax-delims (l r table)
- "Make characters L and R a matching pair of non-case-converting delimiters.
-Sets the entries for L and R in standard-case-table,
-standard-syntax-table, and text-mode-syntax-table to indicate
-left and right delimiters."
- (aset (car table) l l)
- (aset (car table) r r)
- (modify-syntax-entry l (concat "(" (char-to-string r) " ")
- (standard-syntax-table))
- (modify-syntax-entry l (concat "(" (char-to-string r) " ")
- text-mode-syntax-table)
- (modify-syntax-entry r (concat ")" (char-to-string l) " ")
- (standard-syntax-table))
- (modify-syntax-entry r (concat ")" (char-to-string l) " ")
- text-mode-syntax-table))
-
-(defun set-case-syntax-pair (uc lc table)
- "Make characters UC and LC a pair of inter-case-converting letters.
-Sets the entries for characters UC and LC in
-standard-case-table, standard-syntax-table, and
-text-mode-syntax-table to indicate an (uppercase, lowercase)
-pair of letters."
- (aset (car table) uc lc)
- (modify-syntax-entry lc "w " (standard-syntax-table))
- (modify-syntax-entry lc "w " text-mode-syntax-table)
- (modify-syntax-entry uc "w " (standard-syntax-table))
- (modify-syntax-entry uc "w " text-mode-syntax-table))
-
-(defun set-case-syntax (c syntax table)
- "Make characters C case-invariant with syntax SYNTAX.
-Sets the entries for character C in standard-case-table,
-standard-syntax-table, and text-mode-syntax-table to indicate this.
-SYNTAX should be \" \", \"w\", \".\" or \"_\"."
- (aset (car table) c c)
- (modify-syntax-entry c syntax (standard-syntax-table))
- (modify-syntax-entry c syntax text-mode-syntax-table))
-
-(provide 'case-table)
diff --git a/lisp/chistory.el b/lisp/chistory.el
new file mode 100644
index 00000000000..beb3f336d24
--- /dev/null
+++ b/lisp/chistory.el
@@ -0,0 +1,151 @@
+;; chistory -- List command history
+;; Copyright (C) 1985 Free Software Foundation, Inc.
+;; Principal author K. Shane Hartman
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 1, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+(provide 'chistory)
+
+;; This really has nothing to do with list-command-history per se, but
+;; its a nice alternative to C-x ESC (repeat-complex-command) and
+;; functions as a lister if given no pattern. It's not important
+;; enough to warrant a file of its own.
+
+(defun repeat-matching-complex-command (&optional pattern)
+ "Edit and re-evaluate complex command with name matching PATTERN.
+Matching occurrences are displayed, most recent first, until you
+select a form for evaluation. If PATTERN is empty (or nil), every form
+in the command history is offered. The form is placed in the minibuffer
+for editing and the result is evaluated."
+ (interactive "sRedo Command (regexp): ")
+ (if pattern
+ (if (equal (setq pattern
+ (substring pattern
+ (or (string-match "[ \t]*[^ \t]" pattern)
+ (length pattern))))
+ "")
+ (setq pattern nil)))
+ (let ((history command-history)
+ (temp)
+ (what))
+ (while (and history (not what))
+ (setq temp (car history))
+ (if (and (or (not pattern) (string-match pattern (symbol-name (car temp))))
+ (y-or-n-p (format "Redo %s? " (setq temp (prin1-to-string temp)))))
+ (setq what (car history))
+ (setq history (cdr history))))
+ (if (not what)
+ (error "Command history exhausted.")
+ (edit-and-eval-command "Redo: " what))))
+
+(defvar default-command-history-filter-garbage
+ '(command-history-mode
+ list-command-history
+ electric-command-history)
+ "*A list of symbols. If default-list-command-history-filter is
+given a list whose car is an element of this list, then it will return
+non-nil (indicating the list should be discarded from the history).
+Initially, all commands related to the command history are discarded.")
+
+(defvar list-command-history-filter 'default-command-history-filter
+ "If non-nil, should be the name of a function of one argument.
+It is passed each element of the command history when
+\\[list-command-history] is called. If the filter returns non-nil for
+some element, that element is excluded from the history listing. The
+default filter removes commands associated with the command-history.")
+
+(defun default-command-history-filter (frob)
+ "Filter commands matching default-command-history-filter-garbage list
+from the command history."
+ (or (not (consp frob))
+ (memq (car frob) default-command-history-filter-garbage)))
+
+(defvar list-command-history-max 32
+ "*If non-nil, should be a positive number which specifies the maximum
+length of the Command History listing produced by list-command-history.")
+
+(defun list-command-history ()
+ "List history of commands typed to minibuffer.
+The number of commands listed is controlled by list-command-history-max.
+Calls value of list-command-history-filter (if non-nil) on each history
+element to judge if that element should be excluded from the list.
+
+The buffer is left in Command History mode."
+ (interactive)
+ (with-output-to-temp-buffer
+ "*Command History*"
+ (let ((history command-history)
+ (buffer-read-only nil)
+ (count (or list-command-history-max -1)))
+ (while (and (/= count 0) history)
+ (if (and (boundp 'list-command-history-filter)
+ list-command-history-filter
+ (funcall list-command-history-filter (car history)))
+ nil
+ (setq count (1- count))
+ (prin1 (car history))
+ (terpri))
+ (setq history (cdr history))))
+ (save-excursion
+ (set-buffer "*Command History*")
+ (goto-char (point-min))
+ (if (eobp)
+ (error "No command history.")
+ (Command-history-setup)))))
+
+(defun Command-history-setup (&optional majormode modename keymap)
+ (set-buffer "*Command History*")
+ (use-local-map (or keymap command-history-map))
+ (lisp-mode-variables nil)
+ (set-syntax-table emacs-lisp-mode-syntax-table)
+ (setq buffer-read-only t)
+ (use-local-map (or keymap command-history-map))
+ (setq major-mode (or majormode 'command-history-mode))
+ (setq mode-name (or modename "Command History")))
+
+(defvar command-history-hook nil
+ "If non-nil, its value is called on entry to command-history-mode.")
+
+(defvar command-history-map nil)
+(if command-history-map
+ nil
+ (setq command-history-map (make-keymap))
+ (lisp-mode-commands command-history-map)
+ (suppress-keymap command-history-map)
+ (define-key command-history-map "\n" 'next-line)
+ (define-key command-history-map "\r" 'next-line)
+ (define-key command-history-map "\177" 'previous-line))
+
+(defun command-history-mode ()
+ "Major mode for examining commands from command-history.
+The number of commands listed is controlled by list-command-history-max.
+The command history is filtered by list-command-history-filter if non-nil.
+
+Like Emacs-Lisp Mode except that characters do not insert themselves and
+Digits provide prefix arguments. Tab does not indent.
+\\{command-history-map}
+Calls the value of command-history-hook if that is non-nil
+The Command History listing is recomputed each time this mode is
+invoked."
+ (interactive)
+ (list-command-history)
+ (pop-to-buffer "*Command History*")
+ (run-hooks 'command-history-hook))
+
+
+
diff --git a/lisp/chistory.elc b/lisp/chistory.elc
new file mode 100644
index 00000000000..22a728b4ad3
--- /dev/null
+++ b/lisp/chistory.elc
Binary files differ
diff --git a/lisp/cl-indent.el b/lisp/cl-indent.el
new file mode 100644
index 00000000000..ae3b538f914
--- /dev/null
+++ b/lisp/cl-indent.el
@@ -0,0 +1,461 @@
+;; Lisp mode, and its idiosyncratic commands.
+;; Copyright (C) 1987 Free Software Foundation, Inc.
+;; Written by Richard Mlynarik July 1987
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 1, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+;;>> TODO
+;; :foo
+;; bar
+;; :baz
+;; zap
+;; &key (like &body)??
+
+;; &rest 1 in lambda-lists doesn't work
+;; -- really want (foo bar
+;; baz)
+;; not (foo bar
+;; baz)
+;; Need something better than &rest for such cases
+
+
+;;; Hairy lisp indentation.
+
+(defvar lisp-indent-maximum-backtracking 3
+ "*Maximum depth to backtrack out from a sublist for structured indentation.
+If this variable is 0, no backtracking will occur and forms such as flet
+may not be correctly indented.")
+
+(defvar lisp-tag-indentation 1
+ "*Indentation of tags relative to containing list.
+This variable is used by the function lisp-indent-tagbody.")
+
+(defvar lisp-tag-body-indentation 3
+ "*Indentation of non-tagged lines relative to containing list.
+This variable is used by the function lisp-indent-tagbody to indent normal
+lines (lines without tags).
+The indentation is relative to the indentation of the parenthesis enclosing
+he special form. If the value is t, the body of tags will be indented
+as a block at the same indentation as the first s-expression following
+the tag. In this case, any forms before the first tag are indented
+by lisp-body-indent.")
+
+
+(defun common-lisp-indent-hook (indent-point state)
+ (let ((normal-indent (current-column)))
+ ;; Walk up list levels until we see something
+ ;; which does special things with subforms.
+ (let ((depth 0)
+ ;; Path describes the position of point in terms of
+ ;; list-structure with respect to contining lists.
+ ;; `foo' has a path of (0 4 1) in `((a b c (d foo) f) g)'
+ (path ())
+ ;; set non-nil when somebody works out the indentation to use
+ calculated
+ (last-point indent-point)
+ ;; the position of the open-paren of the innermost containing list
+ (containing-form-start (elt state 1))
+ ;; the column of the above
+ sexp-column)
+ ;; Move to start of innermost containing list
+ (goto-char containing-form-start)
+ (setq sexp-column (current-column))
+ ;; Look over successively less-deep containing forms
+ (while (and (not calculated)
+ (< depth lisp-indent-maximum-backtracking))
+ (let ((containing-sexp (point)))
+ (forward-char 1)
+ (parse-partial-sexp (point) indent-point 1 t)
+ ;; Move to the car of the relevant containing form
+ (let (tem function method)
+ (if (not (looking-at "\\sw\\|\\s_"))
+ ;; This form doesn't seem to start with a symbol
+ (setq function nil method nil)
+ (setq tem (point))
+ (forward-sexp 1)
+ (setq function (downcase (buffer-substring tem (point))))
+ (goto-char tem)
+ (setq tem (intern-soft function)
+ method (get tem 'common-lisp-indent-hook))
+ (cond ((and (null method)
+ (string-match ":[^:]+" function))
+ ;; The pleblisp package feature
+ (setq function (substring function
+ (1+ (match-beginning 0)))
+ method (get (intern-soft function)
+ 'common-lisp-indent-hook)))
+ ((and (null method))
+ ;; backwards compatibility
+ (setq method (get tem 'lisp-indent-hook)))))
+ (let ((n 0))
+ ;; How far into the containing form is the current form?
+ (if (< (point) indent-point)
+ (while (condition-case ()
+ (progn
+ (forward-sexp 1)
+ (if (>= (point) indent-point)
+ nil
+ (parse-partial-sexp (point)
+ indent-point 1 t)
+ (setq n (1+ n))
+ t))
+ (error nil))))
+ (setq path (cons n path)))
+
+ ;; backwards compatibility.
+ (cond ((null function))
+ ((null method)
+ (if (null (cdr path))
+ ;; (package prefix was stripped off above)
+ (setq method (cond ((string-match "\\`def"
+ function)
+ '(4 (&whole 4 &rest 1) &body))
+ ((string-match "\\`\\(with\\|do\\)-"
+ function)
+ '(4 &body))))))
+ ;; backwards compatibility. Bletch.
+ ((eq method 'defun)
+ (setq method '(4 (&whole 4 &rest 1) &body))))
+
+ (cond ((and (memq (char-after (1- containing-sexp)) '(?\' ?\`))
+ (not (eql (char-after (- containing-sexp 2)) ?\#)))
+ ;; No indentation for "'(...)" elements
+ (setq calculated (1+ sexp-column)))
+ ((eql (char-after (1- containing-sexp)) ?\#)
+ ;; "#(...)"
+ (setq calculated (1+ sexp-column)))
+ ((null method))
+ ((integerp method)
+ ;; convenient top-level hack.
+ ;; (also compatible with lisp-indent-hook)
+ ;; The number specifies how many `distinguished'
+ ;; forms there are before the body starts
+ ;; Equivalent to (4 4 ... &body)
+ (setq calculated (cond ((cdr path)
+ normal-indent)
+ ((<= (car path) method)
+ ;; `distinguished' form
+ (list (+ sexp-column 4)
+ containing-form-start))
+ ((= (car path) (1+ method))
+ ;; first body form.
+ (+ sexp-column lisp-body-indent))
+ (t
+ ;; other body form
+ normal-indent))))
+ ((symbolp method)
+ (setq calculated (funcall method
+ path state indent-point
+ sexp-column normal-indent)))
+ (t
+ (setq calculated (lisp-indent-259
+ method path state indent-point
+ sexp-column normal-indent)))))
+ (goto-char containing-sexp)
+ (setq last-point containing-sexp)
+ (if (not calculated)
+ (condition-case ()
+ (progn (backward-up-list 1)
+ (setq depth (1+ depth)))
+ (error (setq depth lisp-indent-maximum-backtracking))))))
+ calculated)))
+
+
+(defun lisp-indent-report-bad-format (m)
+ (error "%s has a badly-formed %s property: %s"
+ ;; Love them free variable references!!
+ function 'common-lisp-indent-hook m))
+
+;; Blame the crufty control structure on dynamic scoping
+;; -- not on me!
+(defun lisp-indent-259 (method path state indent-point
+ sexp-column normal-indent)
+ (catch 'exit
+ (let ((p path)
+ (containing-form-start (elt state 1))
+ n tem tail)
+ ;; Isn't tail-recursion wonderful?
+ (while p
+ ;; This while loop is for destructuring.
+ ;; p is set to (cdr p) each iteration.
+ (if (not (consp method)) (lisp-indent-report-bad-format method))
+ (setq n (1- (car p))
+ p (cdr p)
+ tail nil)
+ (while n
+ ;; This while loop is for advancing along a method
+ ;; until the relevant (possibly &rest/&body) pattern
+ ;; is reached.
+ ;; n is set to (1- n) and method to (cdr method)
+ ;; each iteration.
+; (message "trying %s for %s %s" method p function) (sit-for 1)
+ (setq tem (car method))
+
+ (or (eq tem 'nil) ;default indentation
+; (eq tem '&lambda) ;abbrev for (&whole 4 (&rest 1))
+ (and (eq tem '&body) (null (cdr method)))
+ (and (eq tem '&rest)
+ (consp (cdr method)) (null (cdr (cdr method))))
+ (integerp tem) ;explicit indentation specified
+ (and (consp tem) ;destructuring
+ (eq (car tem) '&whole)
+ (or (symbolp (car (cdr tem)))
+ (integerp (car (cdr tem)))))
+ (and (symbolp tem) ;a function to call to do the work.
+ (null (cdr method)))
+ (lisp-indent-report-bad-format method))
+
+ (cond ((and tail (not (consp tem)))
+ ;; indent tail of &rest in same way as first elt of rest
+ (throw 'exit normal-indent))
+ ((eq tem '&body)
+ ;; &body means (&rest <lisp-body-indent>)
+ (throw 'exit
+ (if (and (= n 0) ;first body form
+ (null p)) ;not in subforms
+ (+ sexp-column
+ lisp-body-indent)
+ normal-indent)))
+ ((eq tem '&rest)
+ ;; this pattern holds for all remaining forms
+ (setq tail (> n 0)
+ n 0
+ method (cdr method)))
+ ((> n 0)
+ ;; try next element of pattern
+ (setq n (1- n)
+ method (cdr method))
+ (if (< n 0)
+ ;; Too few elements in pattern.
+ (throw 'exit normal-indent)))
+ ((eq tem 'nil)
+ (throw 'exit (list normal-indent containing-form-start)))
+; ((eq tem '&lambda)
+; ;; abbrev for (&whole 4 &rest 1)
+; (throw 'exit
+; (cond ((null p)
+; (list (+ sexp-column 4) containing-form-start))
+; ((null (cdr p))
+; (+ sexp-column 1))
+; (t normal-indent))))
+ ((integerp tem)
+ (throw 'exit
+ (if (null p) ;not in subforms
+ (list (+ sexp-column tem) containing-form-start)
+ normal-indent)))
+ ((symbolp tem) ;a function to call
+ (throw 'exit
+ (funcall tem path state indent-point
+ sexp-column normal-indent)))
+ (t
+ ;; must be a destructing frob
+ (if (not (null p))
+ ;; descend
+ (setq method (cdr (cdr tem))
+ n nil)
+ (setq tem (car (cdr tem)))
+ (throw 'exit
+ (cond (tail
+ normal-indent)
+ ((eq tem 'nil)
+ (list normal-indent
+ containing-form-start))
+ ((integerp tem)
+ (list (+ sexp-column tem)
+ containing-form-start))
+ (t
+ (funcall tem path state indent-point
+ sexp-column normal-indent))))))))))))
+
+(defun lisp-indent-tagbody (path state indent-point sexp-column normal-indent)
+ (if (not (null (cdr path)))
+ normal-indent
+ (save-excursion
+ (goto-char indent-point)
+ (beginning-of-line)
+ (skip-chars-forward " \t")
+ (list (cond ((looking-at "\\sw\\|\\s_")
+ ;; a tagbody tag
+ (+ sexp-column lisp-tag-indentation))
+ ((integerp lisp-tag-body-indentation)
+ (+ sexp-column lisp-tag-body-indentation))
+ ((eq lisp-tag-body-indentation 't)
+ (condition-case ()
+ (progn (backward-sexp 1) (current-column))
+ (error (1+ sexp-column))))
+ (t (+ sexp-column lisp-body-indent)))
+; (cond ((integerp lisp-tag-body-indentation)
+; (+ sexp-column lisp-tag-body-indentation))
+; ((eq lisp-tag-body-indentation 't)
+; normal-indent)
+; (t
+; (+ sexp-column lisp-body-indent)))
+ (elt state 1)
+ ))))
+
+(defun lisp-indent-do (path state indent-point sexp-column normal-indent)
+ (if (>= (car path) 3)
+ (let ((lisp-tag-body-indentation lisp-body-indent))
+ (funcall (function lisp-indent-tagbody)
+ path state indent-point sexp-column normal-indent))
+ (funcall (function lisp-indent-259)
+ '((&whole nil &rest
+ ;; the following causes wierd indentation
+ ;;(&whole 1 1 2 nil)
+ )
+ (&whole nil &rest 1))
+ path state indent-point sexp-column normal-indent)))
+
+(defun lisp-indent-function-lambda-hack (path state indent-point
+ sexp-column normal-indent)
+ ;; indent (function (lambda () <newline> <body-forms>)) kludgily.
+ (if (or (cdr path) ; wtf?
+ (> (car path) 3))
+ ;; line up under previous body form
+ normal-indent
+ ;; line up under function rather than under lambda in order to
+ ;; conserve horizontal space. (Which is what #' is for.)
+ (condition-case ()
+ (save-excursion
+ (backward-up-list 2)
+ (forward-char 1)
+ (if (looking-at "\\(lisp:+\\)?function\\(\\Sw\\|\\S_\\)")
+ (+ lisp-body-indent -1 (current-column))
+ (+ sexp-column lisp-body-indent)))
+ (error (+ sexp-column lisp-body-indent)))))
+
+
+(let ((l '((block 1)
+ (catch 1)
+ (case (4 &rest (&whole 2 &rest 1)))
+ (ccase . case) (ecase . case)
+ (typecase . case) (etypecase . case) (ctypecase . case)
+ (catch 1)
+ (cond (&rest (&whole 2 &rest 1)))
+ (block 1)
+ (defvar (4 2 2))
+ (defconstant . defvar) (defparameter . defvar)
+ (define-modify-macro
+ (4 &body))
+ (define-setf-method
+ (4 (&whole 4 &rest 1) &body))
+ (defsetf (4 (&whole 4 &rest 1) 4 &body))
+ (defun (4 (&whole 4 &rest 1) &body))
+ (defmacro . defun) (deftype . defun)
+ (defstruct ((&whole 4 &rest (&whole 2 &rest 1))
+ &rest (&whole 2 &rest 1)))
+ (destructuring-bind
+ ((&whole 6 &rest 1) 4 &body))
+ (do lisp-indent-do)
+ (do* . do)
+ (dolist ((&whole 4 2 1) &body))
+ (dotimes . dolist)
+ (eval-when 1)
+ (flet ((&whole 4 &rest (&whole 1 (&whole 4 &rest 1) &body))
+ &body))
+ (labels . flet)
+ (macrolet . flet)
+ ;; `else-body' style
+ (if (nil nil &body))
+ ;; single-else style (then and else equally indented)
+ (if (&rest nil))
+ ;(lambda ((&whole 4 &rest 1) &body))
+ (lambda ((&whole 4 &rest 1)
+ &rest lisp-indent-function-lambda-hack))
+ (let ((&whole 4 &rest (&whole 1 1 2)) &body))
+ (let* . let)
+ (locally 1)
+ ;(loop ...)
+ (multiple-value-bind
+ ((&whole 6 &rest 1) 4 &body))
+ (multiple-value-call
+ (4 &body))
+ (multiple-value-list 1)
+ (multiple-value-prog1 1)
+ (multiple-value-setq
+ (4 2))
+ ;; Combines the worst features of BLOCK, LET and TAGBODY
+ (prog ((&whole 4 &rest 1) &rest lisp-indent-tagbody))
+ (prog* . prog)
+ (prog1 1)
+ (prog2 2)
+ (progn 0)
+ (progv (4 4 &body))
+ (return 0)
+ (return-from (nil &body))
+ (tagbody lisp-indent-tagbody)
+ (throw 1)
+ (unless 1)
+ (unwind-protect
+ (5 &body))
+ (when 1))))
+ (while l
+ (put (car (car l)) 'common-lisp-indent-hook
+ (if (symbolp (cdr (car l)))
+ (get (cdr (car l)) 'common-lisp-indent-hook)
+ (car (cdr (car l)))))
+ (setq l (cdr l))))
+
+
+;(defun foo (x)
+; (tagbody
+; foo
+; (bar)
+; baz
+; (when (losing)
+; (with-big-loser
+; (yow)
+; ((lambda ()
+; foo)
+; big)))
+; (flet ((foo (bar baz zap)
+; (zip))
+; (zot ()
+; quux))
+; (do ()
+; ((lose)
+; (foo 1))
+; (quux)
+; foo
+; (lose))
+; (cond ((x)
+; (win 1 2
+; (foo)))
+; (t
+; (lose
+; 3))))))
+
+
+;(put 'while 'common-lisp-indent-hook 1)
+;(put 'defwrapper'common-lisp-indent-hook ...)
+;(put 'def 'common-lisp-indent-hook ...)
+;(put 'defflavor 'common-lisp-indent-hook ...)
+;(put 'defsubst 'common-lisp-indent-hook ...)
+
+;;(put 'define-restart-name 'common-lisp-indent-hook '1)
+;(put 'with-restart 'common-lisp-indent-hook '((1 4 ((* 1))) (2 &body)))
+;(put 'restart-case 'common-lisp-indent-hook '((1 4) (* 2 ((0 1) (* 1)))))
+;(put 'define-condition 'common-lisp-indent-hook '((1 6) (2 6 ((* 1))) (3 4 ((* 1))) (4 &body)))
+;(put 'with-condition-handler 'common-lisp-indent-hook '((1 4 ((* 1))) (2 &body)))
+;(put 'condition-case 'common-lisp-indent-hook '((1 4) (* 2 ((0 1) (1 3) (2 &body)))))
+
+
+;;;; Turn it on.
+;(setq lisp-indent-hook 'common-lisp-indent-hook)
+
+;; To disable this stuff, (setq lisp-indent-hook 'lisp-indent-hook)
+
diff --git a/lisp/cl-indent.elc b/lisp/cl-indent.elc
new file mode 100644
index 00000000000..f8391c84d2d
--- /dev/null
+++ b/lisp/cl-indent.elc
Binary files differ
diff --git a/lisp/cl.el b/lisp/cl.el
index a4386f3c8bb..0aab4dbc13a 100644
--- a/lisp/cl.el
+++ b/lisp/cl.el
@@ -1,22 +1,21 @@
;; Common-Lisp extensions for GNU Emacs Lisp.
-;; Copyright (C) 1987, 1988, 1989 Free Software Foundation, Inc.
+;; Copyright (C) 1987, 1988 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 1, or (at your option)
+;; any later version.
+
;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY. No author or distributor
-;; accepts responsibility to anyone for the consequences of using it
-;; or for whether it serves any particular purpose or works at all,
-;; unless he says so in writing. Refer to the GNU Emacs General Public
-;; License for full details.
-
-;; Everyone is granted permission to copy, modify and redistribute
-;; GNU Emacs, but only under the conditions described in the
-;; GNU Emacs General Public License. A copy of this license is
-;; supposed to have been given to you along with GNU Emacs so you
-;; can know your rights and responsibilities. It should be in a
-;; file named COPYING. Among other things, the copyright notice
-;; and this notice must be preserved on all copies.
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
;;;;
;;;; These are extensions to Emacs Lisp that provide some form of
@@ -44,7 +43,6 @@
;;;; to quiroz@cs.rochester.edu
(provide 'cl)
-(defvar cl-version "2.0 beta 29 October 1989")
;;;; GLOBAL
@@ -57,33 +55,65 @@
;;;; Cesar Quiroz @ UofR DofCSc - Dec. 1986
;;;; (quiroz@cs.rochester.edu)
-;;; Too many pieces of the rest of this package use psetq. So it is unwise to
-;;; use here anything but plain Emacs Lisp! There is a neater recursive form
-;;; for the algorithm that deals with the bodies.
-
-(defmacro psetq (&rest body)
- "(psetq {var value }...) => nil
-Like setq, but all the values are computed before any assignment is made."
- (let ((length (length body)))
- (cond ((/= (% length 2) 0)
- (error "psetq needs an even number of arguments, %d given"
- length))
- ((null body)
- '())
- (t
- (list 'prog1 nil
- (let ((setqs '())
- (bodyforms (reverse body)))
- (while bodyforms
- (let* ((value (car bodyforms))
- (place (cadr bodyforms)))
- (setq bodyforms (cddr bodyforms))
- (if (null setqs)
- (setq setqs (list 'setq place value))
- (setq setqs (list 'setq place
- (list 'prog1 value
- setqs))))))
- setqs))))))
+(defmacro psetq (&rest pairs)
+ "(psetq {VARIABLE VALUE}...): In parallel, set each VARIABLE to its VALUE.
+All the VALUEs are evaluated, and then all the VARIABLEs are set.
+Aside from order of evaluation, this is the same as `setq'."
+ (let ((nforms (length pairs)) ;count of args
+ ;; next are used to destructure the call
+ symbols ;even numbered args
+ forms ;odd numbered args
+ ;; these are used to generate code
+ bindings ;for the let
+ newsyms ;list of gensyms
+ assignments ;for the setq
+ ;; auxiliary indices
+ i)
+ ;; check there is a reasonable number of forms
+ (if (/= (% nforms 2) 0)
+ (error "Odd number of arguments to `psetq'"))
+
+ ;; destructure the args
+ (let ((ptr pairs) ;traverses the args
+ var ;visits each symbol position
+ )
+ (while ptr
+ (setq var (car ptr)) ;next variable
+ (if (not (symbolp var))
+ (error "`psetq' expected a symbol, found '%s'."
+ (prin1-to-string var)))
+ (setq symbols (cons var symbols))
+ (setq forms (cons (car (cdr ptr)) forms))
+ (setq ptr (cdr (cdr ptr)))))
+
+ ;; assign new symbols to the bindings
+ (let ((ptr forms) ;traverses the forms
+ form ;each form goes here
+ newsym ;gensym for current value of form
+ )
+ (while ptr
+ (setq form (car ptr))
+ (setq newsym (gensym))
+ (setq bindings (cons (list newsym form) bindings))
+ (setq newsyms (cons newsym newsyms))
+ (setq ptr (cdr ptr))))
+ (setq newsyms (nreverse newsyms)) ;to sync with symbols
+
+ ;; pair symbols with newsyms for assignment
+ (let ((ptr1 symbols) ;traverses original names
+ (ptr2 newsyms) ;traverses new symbols
+ )
+ (while ptr1
+ (setq assignments
+ (cons (car ptr1) (cons (car ptr2) assignments)))
+ (setq ptr1 (cdr ptr1))
+ (setq ptr2 (cdr ptr2))))
+
+ ;; generate code
+ (list 'let
+ bindings
+ (cons 'setq assignments)
+ nil)))
;;; utilities
;;;
@@ -108,8 +138,8 @@ symbols, the pairings list and the newsyms list are returned."
(defun zip-lists (evens odds)
"Merge two lists EVENS and ODDS, taking elts from each list alternatingly.
EVENS and ODDS are two lists. ZIP-LISTS constructs a new list, whose
-even numbered elements (0,2,...) come from EVENS and whose odd numbered
-elements (1,3,...) come from ODDS.
+even numbered elements (0,2,...) come from EVENS and whose odd
+numbered elements (1,3,...) come from ODDS.
The construction stops when the shorter list is exhausted."
(do* ((p0 evens (cdr p0))
(p1 odds (cdr p1))
@@ -138,7 +168,7 @@ elements to start with."
(setq odds (cons next odds))))
(defun reassemble-argslists (argslists)
- "(reassemble-argslists ARGSLISTS) => a list of lists
+ "(reassemble-argslists ARGSLISTS).
ARGSLISTS is a list of sequences. Return a list of lists, the first
sublist being all the entries coming from ELT 0 of the original
sublists, the next those coming from ELT 1 and so on, until the
@@ -148,9 +178,45 @@ shortest list is exhausted."
(dotimes (i minlen (nreverse result))
;; capture all the elements at index i
(setq result
- (cons (mapcar (function (lambda (sublist) (elt sublist i)))
+ (cons (mapcar
+ (function (lambda (sublist) (elt sublist i)))
argslists)
result)))))
+
+;;; to help parsing keyword arguments
+
+(defun build-klist (argslist acceptable)
+ "Decode a keyword argument list ARGSLIST for keywords in ACCEPTABLE.
+ARGSLIST is a list, presumably the &rest argument of a call, whose
+even numbered elements must be keywords.
+ACCEPTABLE is a list of keywords, the only ones that are truly acceptable.
+The result is an alist containing the arguments named by the keywords
+in ACCEPTABLE, or nil if something failed."
+
+ ;; check legality of the arguments, then destructure them
+ (unless (and (listp argslist)
+ (evenp (length argslist)))
+ (error "Odd number of keyword-args"))
+ (unless (and (listp acceptable)
+ (every 'keywordp acceptable))
+ (error "Second arg should be a list of keywords"))
+ (multiple-value-bind
+ (keywords forms)
+ (unzip-list argslist)
+ (unless (every 'keywordp keywords)
+ (error "Expected keywords, found `%s'"
+ (prin1-to-string keywords)))
+ (do* ;pick up the pieces
+ ((auxlist ;auxiliary a-list, may
+ (pairlis keywords forms)) ;contain repetitions and junk
+ (ptr acceptable (cdr ptr)) ;pointer in acceptable
+ (this (car ptr) (car ptr)) ;current acceptable keyword
+ (auxval nil) ;used to move values around
+ (alist '())) ;used to build the result
+ ((endp ptr) alist)
+ ;; if THIS appears in auxlist, use its value
+ (when (setq auxval (assoc this auxlist))
+ (setq alist (cons auxval alist))))))
;;; Checking that a list of symbols contains no duplicates is a common
@@ -163,14 +229,14 @@ shortest list is exhausted."
;;; 4th pass.
(defun duplicate-symbols-p (list)
"Find all symbols appearing more than once in LIST.
-Return a list of all such duplicates; nil if there are no duplicates."
+Return a list of all such duplicates; `nil' if there are no duplicates."
(let ((duplicates '()) ;result built here
(propname (gensym)) ;we use a fresh property
)
;; check validity
(unless (and (listp list)
(every 'symbolp list))
- (error "a list of symbols is needed"))
+ (error "A list of symbols is needed"))
;; pass 1: mark
(dolist (x list)
(put x propname 0))
@@ -200,46 +266,51 @@ Return a list of all such duplicates; nil if there are no duplicates."
(defmacro defkeyword (x &optional docstring)
"Make symbol X a keyword (symbol whose value is itself).
-Optional second arg DOCSTRING is a documentation string for it."
- (cond ((symbolp x)
- (list 'defconst x (list 'quote x) docstring))
- (t
- (error "`%s' is not a symbol" (prin1-to-string x)))))
+Optional second argument is a documentation string for it."
+ (cond
+ ((symbolp x)
+ (list 'defconst x (list 'quote x)))
+ (t
+ (error "`%s' is not a symbol" (prin1-to-string x)))))
(defun keywordp (sym)
- "Return t if SYM is a keyword."
- (if (and (symbolp sym) (char-equal (aref (symbol-name sym) 0) ?\:))
- ;; looks like one, make sure value is right
- (set sym sym)
- nil))
+ "Return `t' if SYM is a keyword."
+ (cond
+ ((and (symbolp sym)
+ (char-equal (aref (symbol-name sym) 0) ?\:))
+ ;; looks like one, make sure value is right
+ (set sym sym))
+ (t
+ nil)))
(defun keyword-of (sym)
"Return a keyword that is naturally associated with symbol SYM.
If SYM is keyword, the value is SYM.
Otherwise it is a keyword whose name is `:' followed by SYM's name."
- (cond ((keywordp sym)
- sym)
- ((symbolp sym)
- (let ((newsym (intern (concat ":" (symbol-name sym)))))
- (set newsym newsym)))
- (t
- (error "expected a symbol, not `%s'" (prin1-to-string sym)))))
+ (cond
+ ((keywordp sym)
+ sym)
+ ((symbolp sym)
+ (let ((newsym (intern (concat ":" (symbol-name sym)))))
+ (set newsym newsym)))
+ (t
+ (error "Expected a symbol, not `%s'" (prin1-to-string sym)))))
;;; Temporary symbols.
;;;
(defvar *gentemp-index* 0
- "Integer used by `gentemp' to produce new names.")
+ "Integer used by gentemp to produce new names.")
(defvar *gentemp-prefix* "T$$_"
- "Names generated by `gentemp begin' with this string by default.")
+ "Names generated by gentemp begin with this string by default.")
(defun gentemp (&optional prefix oblist)
"Generate a fresh interned symbol.
-There are two optional arguments, PREFIX and OBLIST. PREFIX is the string
-that begins the new name, OBLIST is the obarray used to search for old
-names. The defaults are just right, YOU SHOULD NEVER NEED THESE ARGUMENTS
-IN YOUR OWN CODE."
+There are 2 optional arguments, PREFIX and OBLIST. PREFIX is the
+string that begins the new name, OBLIST is the obarray used to search for
+old names. The defaults are just right, YOU SHOULD NEVER NEED THESE
+ARGUMENTS IN YOUR OWN CODE."
(if (null prefix)
(setq prefix *gentemp-prefix*))
(if (null oblist)
@@ -254,15 +325,16 @@ IN YOUR OWN CODE."
newsymbol))
(defvar *gensym-index* 0
- "Integer used by `gensym' to produce new names.")
+ "Integer used by gensym to produce new names.")
(defvar *gensym-prefix* "G$$_"
- "Names generated by `gensym' begin with this string by default.")
+ "Names generated by gensym begin with this string by default.")
(defun gensym (&optional prefix)
"Generate a fresh uninterned symbol.
-Optional arg PREFIX is the string that begins the new name. Most people
-take just the default, except when debugging needs suggest otherwise."
+There is an optional argument, PREFIX. PREFIX is the
+string that begins the new name. Most people take just the default,
+except when debugging needs suggest otherwise."
(if (null prefix)
(setq prefix *gensym-prefix*))
(let ((newsymbol nil)
@@ -286,10 +358,10 @@ take just the default, except when debugging needs suggest otherwise."
;;;; (quiroz@cs.rochester.edu)
;;; indentation info
-(put 'case 'lisp-indent-function 1)
-(put 'ecase 'lisp-indent-function 1)
-(put 'when 'lisp-indent-function 1)
-(put 'unless 'lisp-indent-function 1)
+(put 'case 'lisp-indent-hook 1)
+(put 'ecase 'lisp-indent-hook 1)
+(put 'when 'lisp-indent-hook 1)
+(put 'unless 'lisp-indent-hook 1)
;;; WHEN and UNLESS
;;; These two forms are simplified ifs, with a single branch.
@@ -316,7 +388,7 @@ HEAD -> t = catch all, must be last clause
-> otherwise = same as t
-> nil = illegal
-> atom = activated if (eql EXPR HEAD)
- -> list of atoms = activated if (memq EXPR HEAD)
+ -> list of atoms = activated if (member EXPR HEAD)
BODY -> list of forms, implicit PROGN is built around it.
EXPR is evaluated only once."
(let* ((newsym (gentemp))
@@ -334,12 +406,12 @@ EXPR is evaluated only once."
;; check that no 't clause is present.
;; case-clausify would put one such at the beginning of clauses
(if (eq (caar clauses) t)
- (error "no clause-head should be `t' or `otherwise' for `ecase'"))
+ (error "No clause-head should be `t' or `otherwise' for `ecase'"))
;; insert error-catching clause
(setq clauses
(cons
(list 't (list 'error
- "ecase on %s = %s failed to take any branch"
+ "ecase on %s = %s failed to take any branch."
(list 'quote expr)
(list 'prin1-to-string newsym)))
clauses))
@@ -362,28 +434,29 @@ reverse order."
(let ((head (car curclause))
(body (cdr curclause)))
;; construct a cond-clause according to the head
- (cond ((null head)
- (error "case clauses cannot have null heads: `%s'"
- (prin1-to-string curclause)))
- ((or (eq head 't)
- (eq head 'otherwise))
- ;; check it is the last clause
- (if (not (endp nextpos))
- (error "clause with `t' or `otherwise' head must be last"))
- ;; accept this clause as a 't' for cond
- (setq result (cons (cons 't body) result)))
- ((atom head)
- (setq result
- (cons (cons (list 'eql newsym (list 'quote head)) body)
- result)))
- ((listp head)
- (setq result
- (cons (cons (list 'memq newsym (list 'quote head)) body)
- result)))
- (t
- ;; catch-all for this parser
- (error "don't know how to parse case clause `%s'"
- (prin1-to-string head)))))))
+ (cond
+ ((null head)
+ (error "Case clauses cannot have null heads: `%s'"
+ (prin1-to-string curclause)))
+ ((or (eq head 't)
+ (eq head 'otherwise))
+ ;; check it is the last clause
+ (if (not (endp nextpos))
+ (error "Clause with `t' or `otherwise' head must be last"))
+ ;; accept this clause as a 't' for cond
+ (setq result (cons (cons 't body) result)))
+ ((atom head)
+ (setq result
+ (cons (cons (list 'eql newsym (list 'quote head)) body)
+ result)))
+ ((listp head)
+ (setq result
+ (cons (cons (list 'member newsym (list 'quote head)) body)
+ result)))
+ (t
+ ;; catch-all for this parser
+ (error "Don't know how to parse case clause `%s'."
+ (prin1-to-string head)))))))
;;;; end of cl-conditionals.el
@@ -405,29 +478,26 @@ reverse order."
;;;; (quiroz@cs.rochester.edu)
;;; some lisp-indentation information
-(put 'do 'lisp-indent-function 2)
-(put 'do* 'lisp-indent-function 2)
-(put 'dolist 'lisp-indent-function 1)
-(put 'dotimes 'lisp-indent-function 1)
-(put 'do-symbols 'lisp-indent-function 1)
-(put 'do-all-symbols 'lisp-indent-function 1)
+(put 'do 'lisp-indent-hook 2)
+(put 'do* 'lisp-indent-hook 2)
+(put 'dolist 'lisp-indent-hook 1)
+(put 'dotimes 'lisp-indent-hook 1)
+(put 'do-symbols 'lisp-indent-hook 1)
+(put 'do-all-symbols 'lisp-indent-hook 1)
(defmacro do (stepforms endforms &rest body)
- "(do STEPFORMS ENDFORMS . BODY): Iterate BODY, stepping some local
-variables. STEPFORMS must be a list of symbols or lists. In the second
-case, the lists must start with a symbol and contain up to two more forms.
-In the STEPFORMS, a symbol is the same as a (symbol). The other two forms
+ "(do STEPFORMS ENDFORMS . BODY): Iterate BODY, stepping some local variables.
+STEPFORMS must be a list of symbols or lists. In the second case, the
+lists must start with a symbol and contain up to two more forms. In
+the STEPFORMS, a symbol is the same as a (symbol). The other 2 forms
are the initial value (def. NIL) and the form to step (def. itself).
-
The values used by initialization and stepping are computed in parallel.
-The ENDFORMS are a list (CONDITION . ENDBODY). If the CONDITION evaluates
-to true in any iteration, ENDBODY is evaluated and the last form in it is
-returned.
-
-The BODY (which may be empty) is evaluated at every iteration, with the
-symbols of the STEPFORMS bound to the initial or stepped values."
-
+The ENDFORMS are a list (CONDITION . ENDBODY). If the CONDITION
+evaluates to true in any iteration, ENDBODY is evaluated and the last
+form in it is returned.
+The BODY (which may be empty) is evaluated at every iteration, with
+the symbols of the STEPFORMS bound to the initial or stepped values."
;; check the syntax of the macro
(and (check-do-stepforms stepforms)
(check-do-endforms endforms))
@@ -445,16 +515,13 @@ symbols of the STEPFORMS bound to the initial or stepped values."
(defmacro do* (stepforms endforms &rest body)
"`do*' is to `do' as `let*' is to `let'.
STEPFORMS must be a list of symbols or lists. In the second case, the
-lists must start with a symbol and contain up to two more forms. In the
-STEPFORMS, a symbol is the same as a (symbol). The other two forms are
-the initial value (def. NIL) and the form to step (def. itself).
-
+lists must start with a symbol and contain up to two more forms. In
+the STEPFORMS, a symbol is the same as a (symbol). The other 2 forms
+are the initial value (def. NIL) and the form to step (def. itself).
Initializations and steppings are done in the sequence they are written.
-
-The ENDFORMS are a list (CONDITION . ENDBODY). If the CONDITION evaluates
-to true in any iteration, ENDBODY is evaluated and the last form in it is
-returned.
-
+The ENDFORMS are a list (CONDITION . ENDBODY). If the CONDITION
+evaluates to true in any iteration, ENDBODY is evaluated and the last
+form in it is returned.
The BODY (which may be empty) is evaluated at every iteration, with
the symbols of the STEPFORMS bound to the initial or stepped values."
;; check the syntax of the macro
@@ -475,53 +542,65 @@ the symbols of the STEPFORMS bound to the initial or stepped values."
(defun check-do-stepforms (forms)
"True if FORMS is a valid stepforms for the do[*] macro (q.v.)"
- (if (nlistp forms)
- (error "init/step form for do[*] should be a list, not `%s'"
- (prin1-to-string forms))
+ (cond
+ ((nlistp forms)
+ (error "Init/Step form for do[*] should be a list, not `%s'"
+ (prin1-to-string forms)))
+ (t ;valid list
+ ;; each entry must be a symbol, or a list whose car is a symbol
+ ;; and whose length is no more than three
(mapcar
(function
(lambda (entry)
- (if (not (or (symbolp entry)
- (and (listp entry)
- (symbolp (car entry))
- (< (length entry) 4))))
- (error "init/step must be %s, not `%s'"
- "symbol or (symbol [init [step]])"
- (prin1-to-string entry)))))
- forms)))
+ (cond
+ ((or (symbolp entry)
+ (and (listp entry)
+ (symbolp (car entry))
+ (< (length entry) 4)))
+ t)
+ (t
+ (error
+ "Init/Step must be symbol or (symbol [init [step]]), not `%s'"
+ (prin1-to-string entry))))))
+ forms))))
(defun check-do-endforms (forms)
"True if FORMS is a valid endforms for the do[*] macro (q.v.)"
- (if (nlistp forms)
- (error "termination form for do macro should be a list, not `%s'"
- (prin1-to-string forms))))
+ (cond
+ ((listp forms)
+ t)
+ (t
+ (error "Termination form for do macro should be a list, not `%s'"
+ (prin1-to-string forms)))))
(defun extract-do-inits (forms)
"Returns a list of the initializations (for do) in FORMS
-(a stepforms, see the do macro).
-FORMS is assumed syntactically valid."
+-a stepforms, see the do macro-. Forms is assumed syntactically valid."
(mapcar
(function
(lambda (entry)
- (cond ((symbolp entry)
- (list entry nil))
- ((listp entry)
- (list (car entry) (cadr entry))))))
+ (cond
+ ((symbolp entry)
+ (list entry nil))
+ ((listp entry)
+ (list (car entry) (cadr entry))))))
forms))
-
+
;;; There used to be a reason to deal with DO differently than with
;;; DO*. The writing of PSETQ has made it largely unnecessary.
(defun extract-do-steps (forms)
- "EXTRACT-DO-STEPS FORMS => an s-expr.
-FORMS is the stepforms part of a DO macro (q.v.). This function constructs
-an s-expression that does the stepping at the end of an iteration."
+ "EXTRACT-DO-STEPS FORMS => an s-expr
+FORMS is the stepforms part of a DO macro (q.v.). This function
+constructs an s-expression that does the stepping at the end of an
+iteration."
(list (cons 'psetq (select-stepping-forms forms))))
(defun extract-do*-steps (forms)
- "EXTRACT-DO*-STEPS FORMS => an s-expr.
-FORMS is the stepforms part of a DO* macro (q.v.). This function constructs
-an s-expression that does the stepping at the end of an iteration."
+ "EXTRACT-DO*-STEPS FORMS => an s-expr
+FORMS is the stepforms part of a DO* macro (q.v.). This function
+constructs an s-expression that does the stepping at the end of an
+iteration."
(list (cons 'setq (select-stepping-forms forms))))
(defun select-stepping-forms (forms)
@@ -532,30 +611,34 @@ an s-expression that does the stepping at the end of an iteration."
)
(while ptr ;(not (endp entry)) might be safer
(setq entry (car ptr))
- (cond ((and (listp entry) (= (length entry) 3))
- (setq result (append ;append in reverse order!
- (list (caddr entry) (car entry))
- result))))
+ (cond
+ ((and (listp entry)
+ (= (length entry) 3))
+ (setq result (append ;append in reverse order!
+ (list (caddr entry) (car entry))
+ result))))
(setq ptr (cdr ptr))) ;step in the list of forms
+ ;;put things back in the
+ ;;correct order before return
(nreverse result)))
;;; Other iterative constructs
(defmacro dolist (stepform &rest body)
"(dolist (VAR LIST [RESULTFORM]) . BODY): do BODY for each elt of LIST.
-The RESULTFORM defaults to nil. The VAR is bound to successive elements
-of the value of LIST and remains bound (to the nil value) when the
+The RESULTFORM defaults to nil. The VAR is bound to successive
+elements of the value of LIST and remains bound (to the nil value) when the
RESULTFORM is evaluated."
;; check sanity
(cond
((nlistp stepform)
- (error "stepform for `dolist' should be (VAR LIST [RESULT]), not `%s'"
+ (error "Stepform for `dolist' should be (VAR LIST [RESULT]), not `%s'"
(prin1-to-string stepform)))
((not (symbolp (car stepform)))
- (error "first component of stepform should be a symbol, not `%s'"
+ (error "First component of stepform should be a symbol, not `%s'"
(prin1-to-string (car stepform))))
((> (length stepform) 3)
- (error "too many components in stepform `%s'"
+ (error "Too many components in stepform `%s'"
(prin1-to-string stepform))))
;; generate code
(let* ((var (car stepform))
@@ -571,23 +654,23 @@ RESULTFORM is evaluated."
resultform))))
(defmacro dotimes (stepform &rest body)
- "(dotimes (VAR COUNTFORM [RESULTFORM]) . BODY): Repeat BODY, counting in VAR.
+ "(dotimes (VAR COUNTFORM [RESULTFORM]) . BODY): Repeat BODY, counting in VAR.
The COUNTFORM should return a positive integer. The VAR is bound to
-successive integers from 0 to COUNTFORM - 1 and the BODY is repeated for
+successive integers from 0 to COUNTFORM-1 and the BODY is repeated for
each of them. At the end, the RESULTFORM is evaluated and its value
-returned. During this last evaluation, the VAR is still bound, and its
-value is the number of times the iteration occurred. An omitted RESULTFORM
+returned. During this last evaluation, the VAR is still bound, and its
+value is the number of times the iteration occurred. An omitted RESULTFORM
defaults to nil."
;; check sanity
(cond
((nlistp stepform)
- (error "stepform for `dotimes' should be (VAR COUNT [RESULT]), not `%s'"
+ (error "Stepform for `dotimes' should be (VAR COUNT [RESULT]), not `%s'"
(prin1-to-string stepform)))
((not (symbolp (car stepform)))
- (error "first component of stepform should be a symbol, not `%s'"
+ (error "First component of stepform should be a symbol, not `%s'"
(prin1-to-string (car stepform))))
((> (length stepform) 3)
- (error "too many components in stepform `%s'"
+ (error "Too many components in stepform `%s'"
(prin1-to-string stepform))))
;; generate code
(let* ((var (car stepform))
@@ -612,13 +695,13 @@ See also the function `mapatoms'."
;; check sanity
(cond
((nlistp stepform)
- (error "stepform for `do-symbols' should be (VAR OBARRAY [RESULT]), not `%s'"
+ (error "Stepform for `do-symbols' should be (VAR OBARRAY [RESULT]), not `%s'"
(prin1-to-string stepform)))
((not (symbolp (car stepform)))
- (error "first component of stepform should be a symbol, not `%s'"
+ (error "First component of stepform should be a symbol, not `%s'"
(prin1-to-string (car stepform))))
((> (length stepform) 3)
- (error "too many components in stepform `%s'"
+ (error "Too many components in stepform `%s'"
(prin1-to-string stepform))))
;; generate code
(let* ((var (car stepform))
@@ -648,12 +731,12 @@ Normally BODY uses `throw' or `signal' to cause an exit.
The forms in BODY should be lists, as non-lists are reserved for new features."
;; check that the body doesn't have atomic forms
(if (nlistp body)
- (error "body of `loop' should be a list of lists or nil")
+ (error "Body of `loop' should be a list of lists or nil")
;; ok, it is a list, check for atomic components
(mapcar
(function (lambda (component)
(if (nlistp component)
- (error "components of `loop' should be lists"))))
+ (error "Components of `loop' should be lists"))))
body)
;; build the infinite loop
(cons 'while (cons 't body))))
@@ -668,101 +751,52 @@ The forms in BODY should be lists, as non-lists are reserved for new features."
;;;; Cesar Quiroz @ UofR DofCSc - Dec. 1986
;;;; (quiroz@cs.rochester.edu)
-(defvar *cl-valid-named-list-accessors*
- '(first rest second third fourth fifth sixth seventh eighth ninth tenth))
-(defvar *cl-valid-nth-offsets*
- '((second . 1)
- (third . 2)
- (fourth . 3)
- (fifth . 4)
- (sixth . 5)
- (seventh . 6)
- (eighth . 7)
- (ninth . 8)
- (tenth . 9)))
-
-(defun byte-compile-named-list-accessors (form)
- "Generate code for (<accessor> FORM), where <accessor> is one of the named
-list accessors: first, second, ..., tenth, rest."
- (let* ((fun (car form))
- (arg (cadr form))
- (valid *cl-valid-named-list-accessors*)
- (offsets *cl-valid-nth-offsets*))
- (if (or (null (cdr form)) (cddr form))
- (error "%s needs exactly one argument, seen `%s'"
- fun (prin1-to-string form)))
- (if (not (memq fun valid))
- (error "`%s' not in {first, ..., tenth, rest}" fun))
- (cond ((eq fun 'first)
- (byte-compile-form arg)
- (setq byte-compile-depth (1- byte-compile-depth))
- (byte-compile-out byte-car 0))
- ((eq fun 'rest)
- (byte-compile-form arg)
- (setq byte-compile-depth (1- byte-compile-depth))
- (byte-compile-out byte-cdr 0))
- (t ;one of the others
- (byte-compile-constant (cdr (assoc fun offsets)))
- (byte-compile-form arg)
- (setq byte-compile-depth (1- byte-compile-depth))
- (byte-compile-out byte-nth 0)
- ))))
+
;;; Synonyms for list functions
(defun first (x)
"Synonym for `car'"
(car x))
-(put 'first 'byte-compile 'byte-compile-named-list-accessors)
(defun second (x)
"Return the second element of the list LIST."
(nth 1 x))
-(put 'second 'byte-compile 'byte-compile-named-list-accessors)
(defun third (x)
"Return the third element of the list LIST."
(nth 2 x))
-(put 'third 'byte-compile 'byte-compile-named-list-accessors)
(defun fourth (x)
"Return the fourth element of the list LIST."
(nth 3 x))
-(put 'fourth 'byte-compile 'byte-compile-named-list-accessors)
(defun fifth (x)
"Return the fifth element of the list LIST."
(nth 4 x))
-(put 'fifth 'byte-compile 'byte-compile-named-list-accessors)
(defun sixth (x)
"Return the sixth element of the list LIST."
(nth 5 x))
-(put 'sixth 'byte-compile 'byte-compile-named-list-accessors)
(defun seventh (x)
"Return the seventh element of the list LIST."
(nth 6 x))
-(put 'seventh 'byte-compile 'byte-compile-named-list-accessors)
(defun eighth (x)
"Return the eighth element of the list LIST."
(nth 7 x))
-(put 'eighth 'byte-compile 'byte-compile-named-list-accessors)
(defun ninth (x)
"Return the ninth element of the list LIST."
(nth 8 x))
-(put 'ninth 'byte-compile 'byte-compile-named-list-accessors)
(defun tenth (x)
"Return the tenth element of the list LIST."
(nth 9 x))
-(put 'tenth 'byte-compile 'byte-compile-named-list-accessors)
(defun rest (x)
"Synonym for `cdr'"
(cdr x))
-(put 'rest 'byte-compile 'byte-compile-named-list-accessors)
(defun endp (x)
"t if X is nil, nil if X is a cons; error otherwise."
@@ -774,7 +808,7 @@ list accessors: first, second, ..., tenth, rest."
(defun last (x)
"Returns the last link in the list LIST."
(if (nlistp x)
- (error "arg to `last' must be a list"))
+ (error "Arg to `last' must be a list"))
(do ((current-cons x (cdr current-cons))
(next-cons (cdr x) (cdr next-cons)))
((endp next-cons) current-cons)))
@@ -786,17 +820,30 @@ list accessors: first, second, ..., tenth, rest."
(slow x (cdr slow)) ;slow pointer, leaps by 1
(ready nil)) ;indicates termination
(ready n)
- (cond ((endp fast)
- (setq ready t)) ;return n
- ((endp (cdr fast))
- (setq n (+ n 1))
- (setq ready t)) ;return n+1
- ((and (eq fast slow) (> n 0))
- (setq n nil)
- (setq ready t)) ;return nil
- (t
- (setq n (+ n 2)))))) ;just advance counter
-
+ (cond
+ ((endp fast)
+ (setq ready t)) ;return n
+ ((endp (cdr fast))
+ (setq n (+ n 1))
+ (setq ready t)) ;return n+1
+ ((and (eq fast slow) (> n 0))
+ (setq n nil)
+ (setq ready t)) ;return nil
+ (t
+ (setq n (+ n 2)))))) ;just advance counter
+
+(defun member (item list)
+ "Look for ITEM in LIST; return first link in LIST whose car is `eql' to ITEM."
+ (let ((ptr list)
+ (done nil)
+ (result '()))
+ (while (not (or done (endp ptr)))
+ (cond ((eql item (car ptr))
+ (setq done t)
+ (setq result ptr)))
+ (setq ptr (cdr ptr)))
+ result))
+
(defun butlast (list &optional n)
"Return a new list like LIST but sans the last N elements.
N defaults to 1. If the list doesn't have N elements, nil is returned."
@@ -818,9 +865,11 @@ Thus, (list* 1 2 3 '(a b)) returns (1 2 3 a b)."
"Return a list which contains ITEM but is otherwise like LIST.
If ITEM occurs in LIST, the value is LIST. Otherwise it is (cons ITEM LIST).
When comparing ITEM against elements, `eql' is used."
- (if (memq item list)
- list
- (cons item list)))
+ (cond
+ ((member item list)
+ list)
+ (t
+ (cons item list))))
(defun ldiff (list sublist)
"Return a new list like LIST but sans SUBLIST.
@@ -831,175 +880,119 @@ SUBLIST must be one of the links in LIST; otherwise the value is LIST itself."
(reverse result))
(setq result (cons (car curcons) result))))
-;;; The popular c[ad]*r functions and other list accessors.
-
-;;; To implement this efficiently, a new byte compile handler is used to
-;;; generate the minimal code, saving one function call.
-
-(defun byte-compile-ca*d*r (form)
- "Generate code for a (c[ad]+r argument). This realizes the various
-combinations of car and cdr whose names are supported in this implementation.
-To use this functionality for a given function,just give its name a
-'byte-compile property of 'byte-compile-ca*d*r"
- (let* ((fun (car form))
- (arg (cadr form))
- (seq (mapcar (function (lambda (letter)
- (if (= letter ?a)
- 'byte-car 'byte-cdr)))
- (cdr (nreverse (cdr (append (symbol-name fun) nil)))))))
- ;; SEQ is a list of byte-car and byte-cdr in the correct order.
- (if (null seq)
- (error "internal: `%s' cannot be compiled by byte-compile-ca*d*r"
- (prin1-to-string form)))
- (if (or (null (cdr form)) (cddr form))
- (error "%s needs exactly one argument, seen `%s'"
- fun (prin1-to-string form)))
- (byte-compile-form arg)
- (setq byte-compile-depth (1- byte-compile-depth))
- ;; the rest of this code doesn't change the stack depth!
- (while seq
- (byte-compile-out (car seq) 0)
- (setq seq (cdr seq)))))
+;;; The popular c[ad]*r functions.
(defun caar (X)
"Return the car of the car of X."
(car (car X)))
-(put 'caar 'byte-compile 'byte-compile-ca*d*r)
(defun cadr (X)
"Return the car of the cdr of X."
(car (cdr X)))
-(put 'cadr 'byte-compile 'byte-compile-ca*d*r)
(defun cdar (X)
"Return the cdr of the car of X."
(cdr (car X)))
-(put 'cdar 'byte-compile 'byte-compile-ca*d*r)
(defun cddr (X)
"Return the cdr of the cdr of X."
(cdr (cdr X)))
-(put 'cddr 'byte-compile 'byte-compile-ca*d*r)
(defun caaar (X)
"Return the car of the car of the car of X."
(car (car (car X))))
-(put 'caaar 'byte-compile 'byte-compile-ca*d*r)
(defun caadr (X)
"Return the car of the car of the cdr of X."
(car (car (cdr X))))
-(put 'caadr 'byte-compile 'byte-compile-ca*d*r)
(defun cadar (X)
"Return the car of the cdr of the car of X."
(car (cdr (car X))))
-(put 'cadar 'byte-compile 'byte-compile-ca*d*r)
(defun cdaar (X)
"Return the cdr of the car of the car of X."
(cdr (car (car X))))
-(put 'cdaar 'byte-compile 'byte-compile-ca*d*r)
(defun caddr (X)
"Return the car of the cdr of the cdr of X."
(car (cdr (cdr X))))
-(put 'caddr 'byte-compile 'byte-compile-ca*d*r)
(defun cdadr (X)
"Return the cdr of the car of the cdr of X."
(cdr (car (cdr X))))
-(put 'cdadr 'byte-compile 'byte-compile-ca*d*r)
(defun cddar (X)
"Return the cdr of the cdr of the car of X."
(cdr (cdr (car X))))
-(put 'cddar 'byte-compile 'byte-compile-ca*d*r)
(defun cdddr (X)
"Return the cdr of the cdr of the cdr of X."
(cdr (cdr (cdr X))))
-(put 'cdddr 'byte-compile 'byte-compile-ca*d*r)
-
+
(defun caaaar (X)
"Return the car of the car of the car of the car of X."
(car (car (car (car X)))))
-(put 'caaaar 'byte-compile 'byte-compile-ca*d*r)
(defun caaadr (X)
"Return the car of the car of the car of the cdr of X."
(car (car (car (cdr X)))))
-(put 'caaadr 'byte-compile 'byte-compile-ca*d*r)
(defun caadar (X)
"Return the car of the car of the cdr of the car of X."
(car (car (cdr (car X)))))
-(put 'caadar 'byte-compile 'byte-compile-ca*d*r)
(defun cadaar (X)
"Return the car of the cdr of the car of the car of X."
(car (cdr (car (car X)))))
-(put 'cadaar 'byte-compile 'byte-compile-ca*d*r)
(defun cdaaar (X)
"Return the cdr of the car of the car of the car of X."
(cdr (car (car (car X)))))
-(put 'cdaaar 'byte-compile 'byte-compile-ca*d*r)
(defun caaddr (X)
"Return the car of the car of the cdr of the cdr of X."
(car (car (cdr (cdr X)))))
-(put 'caaddr 'byte-compile 'byte-compile-ca*d*r)
(defun cadadr (X)
"Return the car of the cdr of the car of the cdr of X."
(car (cdr (car (cdr X)))))
-(put 'cadadr 'byte-compile 'byte-compile-ca*d*r)
(defun cdaadr (X)
"Return the cdr of the car of the car of the cdr of X."
(cdr (car (car (cdr X)))))
-(put 'cdaadr 'byte-compile 'byte-compile-ca*d*r)
(defun caddar (X)
"Return the car of the cdr of the cdr of the car of X."
(car (cdr (cdr (car X)))))
-(put 'caddar 'byte-compile 'byte-compile-ca*d*r)
(defun cdadar (X)
"Return the cdr of the car of the cdr of the car of X."
(cdr (car (cdr (car X)))))
-(put 'cdadar 'byte-compile 'byte-compile-ca*d*r)
(defun cddaar (X)
"Return the cdr of the cdr of the car of the car of X."
(cdr (cdr (car (car X)))))
-(put 'cddaar 'byte-compile 'byte-compile-ca*d*r)
(defun cadddr (X)
"Return the car of the cdr of the cdr of the cdr of X."
(car (cdr (cdr (cdr X)))))
-(put 'cadddr 'byte-compile 'byte-compile-ca*d*r)
-
+
(defun cddadr (X)
"Return the cdr of the cdr of the car of the cdr of X."
(cdr (cdr (car (cdr X)))))
-(put 'cddadr 'byte-compile 'byte-compile-ca*d*r)
(defun cdaddr (X)
"Return the cdr of the car of the cdr of the cdr of X."
(cdr (car (cdr (cdr X)))))
-(put 'cdaddr 'byte-compile 'byte-compile-ca*d*r)
(defun cdddar (X)
"Return the cdr of the cdr of the cdr of the car of X."
(cdr (cdr (cdr (car X)))))
-(put 'cdddar 'byte-compile 'byte-compile-ca*d*r)
(defun cddddr (X)
"Return the cdr of the cdr of the cdr of the cdr of X."
(cdr (cdr (cdr (cdr X)))))
-(put 'cddddr 'byte-compile 'byte-compile-ca*d*r)
;;; some inverses of the accessors are needed for setf purposes
@@ -1008,16 +1001,17 @@ To use this functionality for a given function,just give its name a
(rplaca (nthcdr n list) newval))
(defun setnthcdr (n list newval)
- "(setnthcdr N LIST NEWVAL) => NEWVAL
+ "SETNTHCDR N LIST NEWVAL => NEWVAL
As a side effect, sets the Nth cdr of LIST to NEWVAL."
- (cond ((< n 0)
- (error "N must be 0 or greater, not %d" n))
- ((= n 0)
- (rplaca list (car newval))
- (rplacd list (cdr newval))
- newval)
- (t
- (rplacd (nthcdr (- n 1) list) newval))))
+ (cond
+ ((< n 0)
+ (error "N must be 0 or greater, not %d" n))
+ ((= n 0)
+ (rplaca list (car newval))
+ (rplacd list (cdr newval))
+ newval)
+ (t
+ (rplacd (nthcdr (- n 1) list) newval))))
;;; A-lists machinery
@@ -1031,7 +1025,7 @@ Does not copy ALIST."
optional 3rd arg ALIST is nconc'd at the end. KEYS and DATA must
have the same length."
(unless (= (length keys) (length data))
- (error "keys and data should be the same length"))
+ (error "Keys and data should be the same length"))
(do* ;;collect keys and data in front of alist
((kptr keys (cdr kptr)) ;traverses the keys
(dptr data (cdr dptr)) ;traverses the data
@@ -1041,6 +1035,7 @@ have the same length."
((endp kptr) result)
(setq result (acons key item result))))
+;;;; end of cl-lists.el
;;;; SEQUENCES
;;;; Emacs Lisp provides many of the 'sequences' functionality of
@@ -1136,50 +1131,8 @@ A sequence means either a list or a vector."
(unless applyval
(setq ready t)
(setq result t)))))
-
-;;; More sequence functions that don't need keyword arguments
-(defun concatenate (type &rest sequences)
- "(concatenate TYPE &rest SEQUENCES) => a sequence
-The sequence returned is of type TYPE (must be 'list, 'string, or 'vector) and
-contains the concatenation of the elements of all the arguments, in the order
-given."
- (let ((sequences (append sequences '(()))))
- (case type
- (list
- (apply (function append) sequences))
- (string
- (apply (function concat) sequences))
- (vector
- (apply (function vector) (apply (function append) sequences)))
- (t
- (error "type for concatenate `%s' not 'list, 'string or 'vector"
- (prin1-to-string type))))))
-
-(defun map (type function &rest sequences)
- "(map TYPE FUNCTION &rest SEQUENCES) => a sequence
-The FUNCTION is called on each set of elements from the SEQUENCES \(stopping
-when the shortest sequence is terminated\) and the results are possibly
-returned in a sequence of type TYPE \(one of 'list, 'vector, 'string, or nil\)
-giving NIL for TYPE gets rid of the values."
- (if (not (memq type (list 'list 'string 'vector nil)))
- (error "type for map `%s' not 'list, 'string, 'vector or nil"
- (prin1-to-string type)))
- (let ((argslists (reassemble-argslists sequences))
- results)
- (if (null type)
- (while argslists ;don't bother accumulating
- (apply function (car argslists))
- (setq argslists (cdr argslists)))
- (setq results (mapcar (function (lambda (args) (apply function args)))
- argslists))
- (case type
- (list
- results)
- (string
- (funcall (function concat) results))
- (vector
- (apply (function vector) results))))))
+
;;; an inverse of elt is needed for setf purposes
@@ -1187,16 +1140,20 @@ giving NIL for TYPE gets rid of the values."
"In SEQUENCE, set the Nth element to NEWVAL. Returns NEWVAL.
A sequence means either a list or a vector."
(let ((l (length seq)))
- (if (or (< n 0) (>= n l))
- (error "N(%d) should be between 0 and %d" n l)
- ;; only two cases need be considered valid, as strings are arrays
- (cond ((listp seq)
- (setnth n seq newval))
- ((arrayp seq)
- (aset seq n newval))
- (t
- (error "SEQ should be a sequence, not `%s'"
- (prin1-to-string seq)))))))
+ (cond
+ ((or (< n 0)
+ (>= n l))
+ (error "N(%d) should be between 0 and %d" n l))
+ (t
+ ;; only two cases need be considered
+ (cond
+ ((listp seq)
+ (setnth n seq newval))
+ ((arrayp seq)
+ (aset seq n newval))
+ (t
+ (error "SEQ should be a sequence, not `%s'"
+ (prin1-to-string seq))))))))
;;; Testing with keyword arguments.
;;;
@@ -1207,335 +1164,68 @@ A sequence means either a list or a vector."
;;; constructs an association list. That association list is used to
;;; test for satisfaction and matching.
-;;; DON'T USE MEMBER, NOR ANY FUNCTION THAT COULD TAKE KEYWORDS HERE!!!
-
-(defun build-klist (argslist acceptable &optional allow-other-keys)
- "Decode a keyword argument list ARGSLIST for keywords in ACCEPTABLE.
-ARGSLIST is a list, presumably the &rest argument of a call, whose
-even numbered elements must be keywords.
-ACCEPTABLE is a list of keywords, the only ones that are truly acceptable.
-The result is an alist containing the arguments named by the keywords
-in ACCEPTABLE, or an error is signalled, if something failed.
-If the third argument (an optional) is non-nil, other keys are acceptable."
- ;; check legality of the arguments, then destructure them
- (unless (and (listp argslist)
- (evenp (length argslist)))
- (error "build-klist: odd number of keyword-args"))
- (unless (and (listp acceptable)
- (every 'keywordp acceptable))
- (error "build-klist: second arg should be a list of keywords"))
- (multiple-value-bind
- (keywords forms)
- (unzip-list argslist)
- (unless (every 'keywordp keywords)
- (error "build-klist: expected keywords, found `%s'"
- (prin1-to-string keywords)))
- (unless (or allow-other-keys
- (every (function (lambda (keyword)
- (memq keyword acceptable)))
- keywords))
- (error "bad keyword[s]: %s not in %s"
- (prin1-to-string (mapcan (function (lambda (keyword)
- (if (memq keyword acceptable)
- nil
- (list keyword))))
- keywords))
- (prin1-to-string acceptable)))
- (do* ;;pick up the pieces
- ((auxlist ;auxiliary a-list, may
- (pairlis keywords forms)) ;contain repetitions and junk
- (ptr acceptable (cdr ptr)) ;pointer in acceptable
- (this (car ptr) (car ptr)) ;current acceptable keyword
- (auxval nil) ;used to move values around
- (alist '())) ;used to build the result
- ((endp ptr) alist)
- ;; if THIS appears in auxlist, use its value
- (when (setq auxval (assq this auxlist))
- (setq alist (cons auxval alist))))))
-
-
-(defun extract-from-klist (klist key &optional default)
- "(extract-from-klist KLIST KEY [DEFAULT]) => value of KEY or DEFAULT
+(defun extract-from-klist (key klist &optional default)
+ "EXTRACT-FROM-KLIST KEY KLIST [DEFAULT] => value of KEY or DEFAULT
Extract value associated with KEY in KLIST (return DEFAULT if nil)."
- (let ((retrieved (cdr (assq key klist))))
+ (let ((retrieved (cdr (assoc key klist))))
(or retrieved default)))
-(defun keyword-argument-supplied-p (klist key)
- "(keyword-argument-supplied-p KLIST KEY) => nil or something
-NIL if KEY (a keyword) does not appear in the KLIST."
- (assq key klist))
-
(defun add-to-klist (key item klist)
- "(ADD-TO-KLIST KEY ITEM KLIST) => new KLIST
+ "ADD-TO-KLIST KEY ITEM KLIST => new KLIST
Add association (KEY . ITEM) to KLIST."
(setq klist (acons key item klist)))
(defun elt-satisfies-test-p (item elt klist)
- "(elt-satisfies-test-p ITEM ELT KLIST) => t or nil
+ "ELT-SATISFIES-TEST-P ITEM ELT KLIST => t or nil
KLIST encodes a keyword-arguments test, as in CH. 14 of CLtL.
True if the given ITEM and ELT satisfy the test."
- (let ((test (extract-from-klist klist :test))
- (test-not (extract-from-klist klist :test-not))
- (keyfn (extract-from-klist klist :key 'identity)))
- (cond (test
- (funcall test item (funcall keyfn elt)))
- (test-not
- (not (funcall test-not item (funcall keyfn elt))))
- (t ;should never happen
- (error "neither :test nor :test-not in `%s'"
- (prin1-to-string klist))))))
+ (let ((test (extract-from-klist :test klist))
+ (test-not (extract-from-klist :test-not klist))
+ (keyfn (extract-from-klist :key klist 'identity)))
+ (cond
+ (test
+ (funcall test item (funcall keyfn elt)))
+ (test-not
+ (not (funcall test-not item (funcall keyfn elt))))
+ (t ;should never happen
+ (error "Neither :test nor :test-not in `%s'"
+ (prin1-to-string klist))))))
(defun elt-satisfies-if-p (item klist)
- "(elt-satisfies-if-p ITEM KLIST) => t or nil
+ "ELT-SATISFIES-IF-P ITEM KLIST => t or nil
True if an -if style function was called and ITEM satisfies the
predicate under :predicate in KLIST."
- (let ((predicate (extract-from-klist klist :predicate))
- (keyfn (extract-from-klist klist :key 'identity)))
+ (let ((predicate (extract-from-klist :predicate klist))
+ (keyfn (extract-from-klist :key 'identity)))
(funcall predicate item (funcall keyfn elt))))
(defun elt-satisfies-if-not-p (item klist)
- "(elt-satisfies-if-not-p ITEM KLIST) => t or nil
+ "ELT-SATISFIES-IF-NOT-P ITEM KLIST => t or nil
KLIST encodes a keyword-arguments test, as in CH. 14 of CLtL.
True if an -if-not style function was called and ITEM does not satisfy
the predicate under :predicate in KLIST."
- (let ((predicate (extract-from-klist klist :predicate))
- (keyfn (extract-from-klist klist :key 'identity)))
+ (let ((predicate (extract-from-klist :predicate klist))
+ (keyfn (extract-from-klist :key 'identity)))
(not (funcall predicate item (funcall keyfn elt)))))
-
+
(defun elts-match-under-klist-p (e1 e2 klist)
- "(elts-match-under-klist-p E1 E2 KLIST) => t or nil
+ "ELTS-MATCH-UNDER-KLIST-P E1 E2 KLIST => t or nil
KLIST encodes a keyword-arguments test, as in CH. 14 of CLtL.
True if elements E1 and E2 match under the tests encoded in KLIST."
- (let ((test (extract-from-klist klist :test))
- (test-not (extract-from-klist klist :test-not))
- (keyfn (extract-from-klist klist :key 'identity)))
- (if (and test test-not)
- (error "both :test and :test-not in `%s'"
- (prin1-to-string klist)))
- (cond (test
- (funcall test (funcall keyfn e1) (funcall keyfn e2)))
- (test-not
- (not (funcall test-not (funcall keyfn e1) (funcall keyfn e2))))
- (t ;should never happen
- (error "neither :test nor :test-not in `%s'"
- (prin1-to-string klist))))))
-
-;;; This macro simplifies using keyword args. It is less clumsy than using
-;;; the primitives build-klist, etc... For instance, member could be written
-;;; this way:
-
-;;; (defun member (item list &rest kargs)
-;;; (with-keyword-args kargs (test test-not (key 'identity))
-;;; ...))
-
-;;; Suggested by Robert Potter (potter@cs.rochester.edu, 15 Nov 1989)
-
-(defmacro with-keyword-args (keyargslist vardefs &rest body)
- "(WITH-KEYWORD-ARGS KEYARGSLIST VARDEFS . BODY)
-KEYARGSLIST can be either a symbol or a list of one or two symbols.
-In the second case, the second symbol is either T or NIL, indicating whether
-keywords other than the mentioned ones are tolerable.
-
-VARDEFS is a list. Each entry is either a VAR (symbol) or matches
-\(VAR [DEFAULT [KEYWORD]]). Just giving VAR is the same as giving
-\(VAR nil :VAR).
-
-The BODY is executed in an environment where each VAR (a symbol) is bound to
-the value present in the KEYARGSLIST provided, or to the DEFAULT. The value
-is searched by using the keyword form of VAR (i.e., :VAR) or the optional
-keyword if provided.
-
-Notice that this macro doesn't distinguish between a default value given
-explicitly by the user and one provided by default. See also the more
-primitive functions build-klist, add-to-klist, extract-from-klist,
-keyword-argument-supplied-p, elt-satisfies-test-p, elt-satisfies-if-p,
-elt-satisfies-if-not-p, elts-match-under-klist-p. They provide more complete,
-if clumsier, control over this feature."
- (let (allow-other-keys)
- (if (listp keyargslist)
- (if (> (length keyargslist) 2)
- (error
- "`%s' should be SYMBOL, (SYMBOL), or (SYMBOL t-OR-nil)"
- (prin1-to-string keyargslist))
- (setq allow-other-keys (cadr keyargslist)
- keyargslist (car keyargslist))
- (if (not (and
- (symbolp keyargslist)
- (memq allow-other-keys '(t nil))))
- (error
- "first subform should be SYMBOL, (SYMBOL), or (SYMBOL t-OR-nil)"
- )))
- (if (symbolp keyargslist)
- (setq allow-other-keys nil)
- (error
- "first subform should be SYMBOL, (SYMBOL), or (SYMBOL t-OR-nil)")))
- (let (vars defaults keywords forms
- (klistname (gensym "KLIST_")))
- (mapcar (function (lambda (entry)
- (if (symbolp entry) ;defaulty case
- (setq entry (list entry nil (keyword-of entry))))
- (let* ((l (length entry))
- (v (car entry))
- (d (cadr entry))
- (k (caddr entry)))
- (if (or (< l 1) (> l 3))
- (error
- "`%s' must match (VAR [DEFAULT [KEYWORD]])"
- (prin1-to-string entry)))
- (if (or (null v) (not (symbolp v)))
- (error
- "bad variable `%s': must be non-null symbol"
- (prin1-to-string v)))
- (setq vars (cons v vars))
- (setq defaults (cons d defaults))
- (if (< l 3)
- (setq k (keyword-of v)))
- (if (and (= l 3)
- (or (null k)
- (not (keywordp k))))
- (error
- "bad keyword `%s'" (prin1-to-string k)))
- (setq keywords (cons k keywords))
- (setq forms (cons (list v (list 'extract-from-klist
- klistname
- k
- d))
- forms)))))
- vardefs)
- (append
- (list 'let* (nconc (list (list klistname
- (list 'build-klist keyargslist
- (list 'quote keywords)
- allow-other-keys)))
- (nreverse forms)))
- body))))
-(put 'with-keyword-args 'lisp-indent-function 1)
-
-
-;;; REDUCE
-;;; It is here mostly as an example of how to use KLISTs.
-;;;
-;;; First of all, you need to declare the keywords (done elsewhere in this
-;;; file):
-;;; (defkeyword :from-end "syntax of sequence functions")
-;;; (defkeyword :start "syntax of sequence functions")
-;;; etc...
-;;;
-;;; Then, you capture all the possible keyword arguments with a &rest
-;;; argument. You can pass that list downward again, of course, but
-;;; internally you need to parse it into a KLIST (an alist, really). One uses
-;;; (build-klist REST-ARGS ACCEPTABLE-KEYWORDS [ALLOW-OTHER]). You can then
-;;; test for presence by using (keyword-argument-supplied-p KLIST KEY) and
-;;; extract a value with (extract-from-klist KLIST KEY [DEFAULT]).
-
-(defun reduce (function sequence &rest kargs)
- "Apply FUNCTION (a function of two arguments) to succesive pairs of elements
-from SEQUENCE. Some keyword arguments are valid after FUNCTION and SEQUENCE:
-:from-end If non-nil, process the values backwards
-:initial-value If given, prefix it to the SEQUENCE. Suffix, if :from-end
-:start Restrict reduction to the subsequence from this index
-:end Restrict reduction to the subsequence BEFORE this index.
-If the sequence is empty and no :initial-value is given, the FUNCTION is
-called on zero (not two) arguments. Otherwise, if there is exactly one
-element in the combination of SEQUENCE and the initial value, that element is
-returned."
- (let* ((klist (build-klist kargs '(:from-end :start :end :initial-value)))
- (length (length sequence))
- (from-end (extract-from-klist klist :from-end))
- (initial-value-given (keyword-argument-supplied-p
- klist :initial-value))
- (start (extract-from-klist kargs :start 0))
- (end (extract-from-klist kargs :end length)))
- (setq sequence (cl$subseq-as-list sequence start end))
- (if from-end
- (setq sequence (reverse sequence)))
- (if initial-value-given
- (setq sequence (cons (extract-from-klist klist :initial-value)
- sequence)))
- (if (null sequence)
- (funcall function) ;only use of 0 arguments
- (let* ((result (car sequence))
- (sequence (cdr sequence)))
- (while sequence
- (setq result (if from-end
- (funcall function (car sequence) result)
- (funcall function result (car sequence)))
- sequence (cdr sequence)))
- result))))
-
-(defun cl$subseq-as-list (sequence start end)
- "(cl$subseq-as-list SEQUENCE START END) => a list"
- (let ((list (append sequence nil))
- (length (length sequence))
- result)
- (if (< start 0)
- (error "start should be >= 0, not %d" start))
- (if (> end length)
- (error "end should be <= %d, not %d" length end))
- (if (and (zerop start) (= end length))
- list
- (let ((i start)
- (vector (apply 'vector list)))
- (while (/= i end)
- (setq result (cons (elt vector i) result))
- (setq i (+ i 1)))
- (nreverse result)))))
+ (let ((test (extract-from-klist :test klist))
+ (test-not (extract-from-klist :test-not klist))
+ (keyfn (extract-from-klist :key klist 'identity)))
+ (cond
+ (test
+ (funcall test (funcall keyfn e1) (funcall keyfn e2)))
+ (test-not
+ (not (funcall test-not (funcall keyfn e1) (funcall keyfn e2))))
+ (t ;should never happen
+ (error "Neither :test nor :test-not in `%s'"
+ (prin1-to-string klist))))))
;;;; end of cl-sequences.el
-;;;; Some functions with keyword arguments
-;;;;
-;;;; Both list and sequence functions are considered here together. This
-;;;; doesn't fit any more with the original split of functions in files.
-
-(defun member (item list &rest kargs)
- "Look for ITEM in LIST; return first tail of LIST the car of whose first
-cons cell tests the same as ITEM. Admits arguments :key, :test, and :test-not."
- (if (null kargs) ;treat this fast for efficiency
- (memq item list)
- (let* ((klist (build-klist kargs '(:test :test-not :key)))
- (test (extract-from-klist klist :test))
- (testnot (extract-from-klist klist :test-not))
- (key (extract-from-klist klist :key 'identity)))
- ;; another workaround allegledly for speed
- (if (and (or (eq test 'eq) (eq test 'eql)
- (eq test (symbol-function 'eq))
- (eq test (symbol-function 'eql)))
- (null testnot)
- (or (eq key 'identity) ;either by default or so given
- (eq key (function identity)) ;could this happen?
- (eq key (symbol-function 'identity)) ;sheer paranoia
- ))
- (memq item list)
- (if (and test testnot)
- (error ":test and :test-not both specified for member"))
- (if (not (or test testnot))
- (setq test 'eql))
- ;; final hack: remove the indirection through the function names
- (if testnot
- (if (symbolp testnot)
- (setq testnot (symbol-function testnot)))
- (if (symbolp test)
- (setq test (symbol-function test))))
- (if (symbolp key)
- (setq key (symbol-function key)))
- ;; ok, go for it
- (let ((ptr list)
- (done nil)
- (result '()))
- (if testnot
- (while (not (or done (endp ptr)))
- (cond ((not (funcall testnot item (funcall key (car ptr))))
- (setq done t)
- (setq result ptr)))
- (setq ptr (cdr ptr)))
- (while (not (or done (endp ptr)))
- (cond ((funcall test item (funcall key (car ptr)))
- (setq done t)
- (setq result ptr)))
- (setq ptr (cdr ptr))))
- result)))))
-
;;;; MULTIPLE VALUES
;;;; This package approximates the behavior of the multiple-values
;;;; forms of Common Lisp.
@@ -1543,12 +1233,15 @@ cons cell tests the same as ITEM. Admits arguments :key, :test, and :test-not."
;;;; Cesar Quiroz @ UofR DofCSc - Dec. 1986
;;;; (quiroz@cs.rochester.edu)
+
+
;;; Lisp indentation information
-(put 'multiple-value-bind 'lisp-indent-function 2)
-(put 'multiple-value-setq 'lisp-indent-function 2)
-(put 'multiple-value-list 'lisp-indent-function nil)
-(put 'multiple-value-call 'lisp-indent-function 1)
-(put 'multiple-value-prog1 'lisp-indent-function 1)
+(put 'multiple-value-bind 'lisp-indent-hook 2)
+(put 'multiple-value-setq 'lisp-indent-hook 2)
+(put 'multiple-value-list 'lisp-indent-hook nil)
+(put 'multiple-value-call 'lisp-indent-hook 1)
+(put 'multiple-value-prog1 'lisp-indent-hook 1)
+
;;; Global state of the package is kept here
(defvar *mvalues-values* nil
@@ -1573,6 +1266,7 @@ the first value."
(setq *mvalues-count* (length *mvalues-values*))
(car *mvalues-values*))
+
(defun values-list (&optional val-forms)
"Produce multiple values (zero or mode). Each element of LIST is one value.
This is equivalent to (apply 'values LIST)."
@@ -1582,6 +1276,7 @@ This is equivalent to (apply 'values LIST)."
(setq *mvalues-values* val-forms)
(setq *mvalues-count* (length *mvalues-values*))
(car *mvalues-values*))
+
;;; Callers that want to see the multiple values use these macros.
@@ -1665,7 +1360,7 @@ Forms a list of pairs `(,(nth i vars) (nth i vals)) for i from 0 to
the length of VARS (a list of symbols). VALS is just a fresh symbol."
(if (or (nlistp vars)
(notevery 'symbolp vars))
- (error "expected a list of symbols, not `%s'"
+ (error "Expected a list of symbols, not `%s'"
(prin1-to-string vars)))
(let* ((nvars (length vars))
(clauses '()))
@@ -1703,50 +1398,55 @@ the length of VARS (a list of symbols). VALS is just a fresh symbol."
(defun abs (number)
"Return the absolute value of NUMBER."
- (if (< number 0)
- (- number)
- number))
+ (cond
+ ((< number 0)
+ (- 0 number))
+ (t ;number is >= 0
+ number)))
(defun signum (number)
"Return -1, 0 or 1 according to the sign of NUMBER."
- (cond ((< number 0)
- -1)
- ((> number 0)
- 1)
- (t ;exactly zero
- 0)))
+ (cond
+ ((< number 0)
+ -1)
+ ((> number 0)
+ 1)
+ (t ;exactly zero
+ 0)))
(defun gcd (&rest integers)
"Return the greatest common divisor of all the arguments.
The arguments must be integers. With no arguments, value is zero."
(let ((howmany (length integers)))
- (cond ((= howmany 0)
- 0)
- ((= howmany 1)
- (abs (car integers)))
- ((> howmany 2)
- (apply (function gcd)
- (cons (gcd (nth 0 integers) (nth 1 integers))
- (nthcdr 2 integers))))
- (t ;howmany=2
- ;; essentially the euclidean algorithm
- (when (zerop (* (nth 0 integers) (nth 1 integers)))
- (error "a zero argument is invalid for `gcd'"))
- (do* ((absa (abs (nth 0 integers))) ; better to operate only
- (absb (abs (nth 1 integers))) ;on positives.
- (dd (max absa absb)) ; setup correct order for the
- (ds (min absa absb)) ;succesive divisions.
- ;; intermediate results
- (q 0)
- (r 0)
- ;; final results
- (done nil) ; flag: end of iterations
- (result 0)) ; final value
- (done result)
- (setq q (/ dd ds))
- (setq r (% dd ds))
- (cond ((zerop r) (setq done t) (setq result ds))
- (t (setq dd ds) (setq ds r))))))))
+ (cond
+ ((= howmany 0)
+ 0)
+ ((= howmany 1)
+ (abs (car integers)))
+ ((> howmany 2)
+ (apply (function gcd)
+ (cons (gcd (nth 0 integers) (nth 1 integers))
+ (nthcdr 2 integers))))
+ (t ;howmany=2
+ ;; essentially the euclidean algorithm
+ (when (zerop (* (nth 0 integers) (nth 1 integers)))
+ (error "A zero argument is invalid for `gcd'"))
+ (do* ((absa (abs (nth 0 integers))) ; better to operate only
+ (absb (abs (nth 1 integers))) ;on positives.
+ (dd (max absa absb)) ; setup correct order for the
+ (ds (min absa absb)) ;succesive divisions.
+ ;; intermediate results
+ (q 0)
+ (r 0)
+ ;; final results
+ (done nil) ; flag: end of iterations
+ (result 0)) ; final value
+ (done result)
+ (setq q (/ dd ds))
+ (setq r (% dd ds))
+ (cond
+ ((zerop r) (setq done t) (setq result ds))
+ ( t (setq dd ds) (setq ds r))))))))
(defun lcm (integer &rest more)
"Return the least common multiple of all the arguments.
@@ -1756,43 +1456,48 @@ The arguments must be integers and there must be at least one of them."
(b (nth 0 more))
prod ; intermediate product
(yetmore (nthcdr 1 more)))
- (cond ((zerop howmany)
- (abs a))
- ((> howmany 1) ; recursive case
- (apply (function lcm)
- (cons (lcm a b) yetmore)))
- (t ; base case, just 2 args
- (setq prod (* a b))
- (cond
- ((zerop prod)
- 0)
- (t
- (/ (abs prod) (gcd a b))))))))
+ (cond
+ ((zerop howmany)
+ (abs a))
+ ((> howmany 1) ; recursive case
+ (apply (function lcm)
+ (cons (lcm a b) yetmore)))
+ (t ; base case, just 2 args
+ (setq prod (* a b))
+ (cond
+ ((zerop prod)
+ 0)
+ (t
+ (/ (abs prod) (gcd a b))))))))
(defun isqrt (number)
"Return the integer square root of NUMBER.
NUMBER must not be negative. Result is largest integer less than or
equal to the real square root of the argument."
- ;; The method used here is essentially the Newtonian iteration
- ;; x[n+1] <- (x[n] + Number/x[n]) / 2
- ;; suitably adapted to integer arithmetic.
- ;; Thanks to Philippe Schnoebelen <phs@lifia.imag.fr> for suggesting the
- ;; termination condition.
- (cond ((minusp number)
- (error "argument to `isqrt' (%d) must not be negative"
- number))
- ((zerop number)
- 0)
- (t ;so (>= number 0)
- (do* ((approx 1) ;any positive integer will do
- (new 0) ;init value irrelevant
- (done nil))
- (done (if (> (* approx approx) number)
- (- approx 1)
- approx))
- (setq new (/ (+ approx (/ number approx)) 2)
- done (or (= new approx) (= new (+ approx 1)))
- approx new)))))
+ (cond
+ ((minusp number)
+ (error "Argument to `isqrt' must not be negative"))
+ ((zerop number)
+ 0)
+ ((<= number 3)
+ 1)
+ (t
+ ;; This is some sort of newtonian iteration, trying not to get in
+ ;; an infinite loop. That's why I catch 0, 1, 2 and 3 as special
+ ;; cases, so then rounding won't make this iteration loop.
+ (do* ((approx (/ number 2) iter)
+ (done nil)
+ (iter 0))
+ (done (if (> (* approx approx) number)
+ (- approx 1) ;reached from above
+ approx))
+ (setq iter
+ (/ (+ approx
+ (/ number approx)
+ (if (>= (% number approx) (/ approx 2))
+ 1 0))
+ 2))
+ (setq done (eql approx iter))))))
(defun floor (number &optional divisor)
"Divide DIVIDEND by DIVISOR, rounding toward minus infinity.
@@ -1805,15 +1510,16 @@ DIVISOR defaults to 1. The remainder is produced as a second value."
(multiple-value-bind
(q r s)
(safe-idiv number divisor)
- (cond ((zerop s)
- (values 0 0))
- ((plusp s)
- (values q r))
- (t ;opposite-signs case
- (if (zerop r)
- (values (- q) 0)
- (let ((q (- (+ q 1))))
- (values q (- number (* q divisor)))))))))))
+ (cond
+ ((zerop s)
+ (values 0 0))
+ ((plusp s)
+ (values q r))
+ (t
+ (unless (zerop r)
+ (setq q (- 0 (+ q 1)))
+ (setq r (- number (* q divisor))))
+ (values q r)))))))
(defun ceiling (number &optional divisor)
"Divide DIVIDEND by DIVISOR, rounding toward plus infinity.
@@ -1826,12 +1532,16 @@ DIVISOR defaults to 1. The remainder is produced as a second value."
(multiple-value-bind
(q r s)
(safe-idiv number divisor)
- (cond ((zerop s)
- (values 0 0))
- ((plusp s)
- (values (+ q 1) (- r divisor)))
- (t
- (values (- q) (+ number (* q divisor)))))))))
+ (cond
+ ((zerop s)
+ (values 0 0))
+ ((minusp s)
+ (values q r))
+ (t
+ (unless (zerop r)
+ (setq q (+ q 1))
+ (setq r (- number (* q divisor))))
+ (values q r)))))))
(defun truncate (number &optional divisor)
"Divide DIVIDEND by DIVISOR, rounding toward zero.
@@ -1844,35 +1554,41 @@ DIVISOR defaults to 1. The remainder is produced as a second value."
(multiple-value-bind
(q r s)
(safe-idiv number divisor)
- (cond ((zerop s)
- (values 0 0))
- ((plusp s) ;same as floor
- (values q r))
- (t ;same as ceiling
- (values (- q) (+ number (* q divisor)))))))))
+ (cond
+ ((zerop s)
+ (values 0 0))
+ ((plusp s)
+ (values q r))
+ (t
+ (unless (zerop r)
+ (setq q (- 0 q))
+ (setq r (- number (* q divisor))))
+ (values q r)))))))
(defun round (number &optional divisor)
"Divide DIVIDEND by DIVISOR, rounding to nearest integer.
DIVISOR defaults to 1. The remainder is produced as a second value."
- (cond ((and (null divisor) ; trivial case
- (numberp number))
- (values number 0))
- (t ; do the division
- (multiple-value-bind
- (q r s)
- (safe-idiv number divisor)
- (setq r (abs r))
- ;; adjust magnitudes first, and then signs
- (let ((other-r (- (abs divisor) r)))
- (cond ((> r other-r)
- (setq q (+ q 1)))
- ((and (= r other-r)
- (oddp q))
- ;; round to even is mandatory
- (setq q (+ q 1))))
- (setq q (* s q))
- (setq r (- number (* q divisor)))
- (values q r))))))
+ (cond
+ ((and (null divisor) ; trivial case
+ (numberp number))
+ (values number 0))
+ (t ; do the division
+ (multiple-value-bind
+ (q r s)
+ (safe-idiv number divisor)
+ (setq r (abs r))
+ ;; adjust magnitudes first, and then signs
+ (let ((other-r (- (abs divisor) r)))
+ (cond
+ ((> r other-r)
+ (setq q (+ q 1)))
+ ((and (= r other-r)
+ (oddp q))
+ ;; round to even is mandatory
+ (setq q (+ q 1))))
+ (setq q (* s q))
+ (setq r (- number (* q divisor)))
+ (values q r))))))
(defun mod (number divisor)
"Return remainder of X by Y (rounding quotient toward minus infinity).
@@ -1893,15 +1609,13 @@ That is, the remainder goes with the quotient produced by `truncate'."
;;; computations when working with negatives, so the idea here is to
;;; make sure we know what is coming back to the caller in all cases.
-;;; Signum computation fixed by mad@math.keio.JUNET (MAEDA Atusi)
-
(defun safe-idiv (a b)
"SAFE-IDIV A B => Q R S
Q=|A|/|B|, R is the rest, S is the sign of A/B."
(unless (and (numberp a) (numberp b))
- (error "arguments to `safe-idiv' must be numbers"))
+ (error "Arguments to `safe-idiv' must be numbers"))
(when (zerop b)
- (error "cannot divide %d by zero" a))
+ (error "Cannot divide %d by zero" a))
(let* ((absa (abs a))
(absb (abs b))
(q (/ absa absb))
@@ -1938,54 +1652,55 @@ than one PLACE and VALUE, each PLACE is set from its VALUE before
the next PLACE is evaluated."
(let ((nforms (length pairs)))
;; check the number of subforms
- (cond ((/= (% nforms 2) 0)
- (error "odd number of arguments to `setf'"))
- ((= nforms 0)
- nil)
- ((> nforms 2)
- ;; this is the recursive case
- (cons 'progn
- (do* ;collect the place-value pairs
- ((args pairs (cddr args))
- (place (car args) (car args))
- (value (cadr args) (cadr args))
- (result '()))
- ((endp args) (nreverse result))
- (setq result
- (cons (list 'setf place value)
- result)))))
- (t ;i.e., nforms=2
- ;; this is the base case (SETF PLACE VALUE)
- (let* ((place (car pairs))
- (value (cadr pairs))
- (head nil)
- (updatefn nil))
- ;; dispatch on the type of the PLACE
- (cond ((symbolp place)
- (list 'setq place value))
- ((and (listp place)
- (setq head (car place))
- (symbolp head)
- (setq updatefn (get head :setf-update-fn)))
- (if (or (and (consp updatefn) (eq (car updatefn) 'lambda))
- (and (symbolp updatefn)
- (fboundp updatefn)
- (let ((defn (symbol-function updatefn)))
- (or (subrp defn)
- (and (consp defn)
- (eq (car defn) 'lambda))))))
- (cons updatefn (append (cdr place) (list value)))
- (multiple-value-bind
- (bindings newsyms)
- (pair-with-newsyms (append (cdr place) (list value)))
- ;; this let gets new symbols to ensure adequate
- ;; order of evaluation of the subforms.
- (list 'let
- bindings
- (cons updatefn newsyms)))))
- (t
- (error "no `setf' update-function for `%s'"
- (prin1-to-string place)))))))))
+ (cond
+ ((/= (% nforms 2) 0)
+ (error "Odd number of arguments to `setf'"))
+ ((= nforms 0)
+ nil)
+ ((> nforms 2)
+ ;; this is the recursive case
+ (cons 'progn
+ (do* ;collect the place-value pairs
+ ((args pairs (cddr args))
+ (place (car args) (car args))
+ (value (cadr args) (cadr args))
+ (result '()))
+ ((endp args) (nreverse result))
+ (setq result
+ (cons (list 'setf place value)
+ result)))))
+ (t ;i.e., nforms=2
+ ;; this is the base case (SETF PLACE VALUE)
+ (let* ((place (car pairs))
+ (value (cadr pairs))
+ (head nil)
+ (updatefn nil))
+ ;; dispatch on the type of the PLACE
+ (cond
+ ((symbolp place)
+ (list 'setq place value))
+ ((and (listp place)
+ (setq head (car place))
+ (symbolp head)
+ (setq updatefn (get head :setf-update-fn)))
+ (if (or (and (consp updatefn) (eq (car updatefn) 'lambda))
+ (and (symbolp updatefn)
+ (fboundp updatefn)
+ (let ((defn (symbol-function updatefn)))
+ (or (subrp defn)
+ (and (consp defn) (eq (car defn) 'lambda))))))
+ (cons updatefn (append (cdr place) (list value)))
+ (multiple-value-bind
+ (bindings newsyms)
+ (pair-with-newsyms (append (cdr place) (list value)))
+ ;; this let* gets new symbols to ensure adequate order of
+ ;; evaluation of the subforms.
+ (list 'let
+ bindings
+ (cons updatefn newsyms)))))
+ (t
+ (error "No `setf' update-function for `%s'"
+ (prin1-to-string place)))))))))
(defmacro defsetf (accessfn updatefn &optional docstring)
"Define how `setf' works on a certain kind of generalized variable.
@@ -1998,15 +1713,11 @@ updating called for."
;; reject ill-formed requests. too bad one can't test for functionp
;; or macrop.
(when (not (symbolp accessfn))
- (error "first argument of `defsetf' must be a symbol, not `%s'"
+ (error "First argument of `defsetf' must be a symbol, not `%s'"
(prin1-to-string accessfn)))
;; update properties
- (list 'progn
- (list 'put (list 'quote accessfn)
- :setf-update-fn (list 'function updatefn))
- (list 'put (list 'quote accessfn) :setf-update-doc docstring)
- ;; any better thing to return?
- (list 'quote accessfn)))
+ (put accessfn :setf-update-fn updatefn)
+ (put accessfn :setf-update-doc docstring))
;;; This section provides the "default" setfs for Common-Emacs-Lisp
;;; The user will not normally add anything to this, although
@@ -2035,11 +1746,14 @@ updating called for."
(apply 'list* (butlast (cdr args)))
(last args)))
(newupdater nil)) ; its update-fn, if any
- (if (and (symbolp fnform)
- (setq newupdater (get fnform :setf-update-fn)))
- (apply newupdater applyargs)
- (error "can't `setf' to `%s'"
- (prin1-to-string fnform)))))
+ (cond
+ ((and (symbolp fnform)
+ (setq newupdater (get fnform :setf-update-fn)))
+ ;; just do it
+ (apply newupdater applyargs))
+ (t
+ (error "Can't `setf' to `%s'"
+ (prin1-to-string fnform))))))
"`apply' is a special case for `setf'")
@@ -2219,21 +1933,22 @@ updating called for."
(lambda (list val) (setcdr (cddr list) val))
"`setf' inversion for `cddddr'")
-(defsetf get put "`setf' inversion for `get' is `put'")
+
+(defsetf get
+ put
+ "`setf' inversion for `get' is `put'")
-(defsetf symbol-function fset
+(defsetf symbol-function
+ fset
"`setf' inversion for `symbol-function' is `fset'")
-(defsetf symbol-plist setplist
+(defsetf symbol-plist
+ setplist
"`setf' inversion for `symbol-plist' is `setplist'")
-(defsetf symbol-value set
+(defsetf symbol-value
+ set
"`setf' inversion for `symbol-value' is `set'")
-
-(defsetf point goto-char
- "To set (point) to N, use (goto-char N)")
-
-;; how about defsetfing other Emacs forms?
;;; Modify macros
;;;
@@ -2275,39 +1990,31 @@ updating called for."
;;; sides. The evaluations are done in an environment where they
;;; appear to occur in parallel.
-(defmacro psetf (&rest body)
- "(psetf {var value }...) => nil
-Like setf, but all the values are computed before any assignment is made."
- (let ((length (length body)))
- (cond ((/= (% length 2) 0)
- (error "psetf needs an even number of arguments, %d given"
- length))
- ((null body)
- '())
- (t
- (list 'prog1 nil
- (let ((setfs '())
- (bodyforms (reverse body)))
- (while bodyforms
- (let* ((value (car bodyforms))
- (place (cadr bodyforms)))
- (setq bodyforms (cddr bodyforms))
- (if (null setfs)
- (setq setfs (list 'setf place value))
- (setq setfs (list 'setf place
- (list 'prog1 value
- setfs))))))
- setfs))))))
+(defmacro psetf (&rest pairs)
+ "(psetf {PLACE VALUE}...): Set several generalized variables in parallel.
+All the VALUEs are computed, and then all the PLACEs are stored as in `setf'.
+See also `psetq', `shiftf' and `rotatef'."
+ (unless (evenp (length pairs))
+ (error "Odd number of arguments to `psetf'"))
+ (multiple-value-bind
+ (places forms)
+ (unzip-list pairs)
+ ;; obtain fresh symbols to simulate the parallelism
+ (multiple-value-bind
+ (bindings newsyms)
+ (pair-with-newsyms forms)
+ (list 'let
+ bindings
+ (cons 'setf (zip-lists places newsyms))
+ nil))))
;;; SHIFTF and ROTATEF
;;;
(defmacro shiftf (&rest forms)
- "(shiftf PLACE1 PLACE2... NEWVALUE)
-Set PLACE1 to PLACE2, PLACE2 to PLACE3...
+ "(shiftf PLACE1 PLACE2... NEWVALUE): set PLACE1 to PLACE2, PLACE2 to PLACE3...
Each PLACE is set to the old value of the following PLACE,
-and the last PLACE is set to the value NEWVALUE.
-Returns the old value of PLACE1."
+and the last PLACE is set to the value NEWVALUE."
(unless (> (length forms) 1)
(error "`shiftf' needs more than one argument"))
(let ((places (butlast forms))
@@ -2325,18 +2032,20 @@ Returns the old value of PLACE1."
(defmacro rotatef (&rest places)
"(rotatef PLACE...) sets each PLACE to the old value of the following PLACE.
The last PLACE is set to the old value of the first PLACE.
-Thus, the values rotate through the PLACEs. Returns nil."
- (if (null places)
- nil
- (multiple-value-bind
- (bindings newsyms)
- (pair-with-newsyms places)
- (list
- 'let bindings
- (cons 'setf
- (zip-lists places
- (append (cdr newsyms) (list (car newsyms)))))
- nil))))
+Thus, the values rotate through the PLACEs."
+ (cond
+ ((null places)
+ nil)
+ (t
+ (multiple-value-bind
+ (bindings newsyms)
+ (pair-with-newsyms places)
+ (list
+ 'let bindings
+ (cons 'setf
+ (zip-lists places
+ (append (cdr newsyms) (list (car newsyms)))))
+ nil)))))
;;;; STRUCTS
;;;; This file provides the structures mechanism. See the
@@ -2364,27 +2073,16 @@ Thus, the values rotate through the PLACEs. Returns nil."
(defkeyword :structure-slots "List of the slot's names")
(defkeyword :structure-indices "List of (KEYWORD-NAME . INDEX)")
(defkeyword :structure-initforms "List of (KEYWORD-NAME . INITFORM)")
-(defkeyword :structure-includes
- "() or list of a symbol, that this struct includes")
-(defkeyword :structure-included-in
- "List of the structs that include this")
(defmacro defstruct (&rest args)
"(defstruct NAME [DOC-STRING] . SLOTS) define NAME as structure type.
NAME must be a symbol, the name of the new structure. It could also
-be a list (NAME . OPTIONS).
-
-Each option is either a symbol, or a list of a keyword symbol taken from the
-list \{:conc-name, :copier, :constructor, :predicate, :include,
-:print-function, :type, :initial-offset\}. The meanings of these are as in
-CLtL, except that no BOA-constructors are provided, and the options
-\{:print-fuction, :type, :initial-offset\} are ignored quietly. All these
-structs are named, in the sense that their names can be used for type
-discrimination.
-
-The DOC-STRING is established as the `structure-doc' property of NAME.
-
+be a list (NAME . OPTIONS), but not all options are supported currently.
+As of Dec. 1986, this is supporting :conc-name, :copier and :predicate
+completely, :include arguably completely and :constructor only to
+change the name of the default constructor. No BOA constructors allowed.
+The DOC-STRING is established as the 'structure-doc' property of NAME.
The SLOTS are one or more of the following:
SYMBOL -- meaning the SYMBOL is the name of a SLOT of NAME
list of SYMBOL and VALUE -- meaning that VALUE is the initial value of
@@ -2398,11 +2096,10 @@ them. `setf' of the accessors sets their values."
;; Names for the member functions come from the options. The
;; slots* stuff collects info about the slots declared explicitly.
(multiple-value-bind
- (conc-name constructor copier predicate
- moreslotsn moreslots moreinits included)
+ (conc-name constructor copier predicate moreslotsn moreslots moreinits)
(parse$defstruct$options name options slots)
;; The moreslots* stuff refers to slots gained as a consequence
- ;; of (:include clauses). -- Oct 89: Only one :include tolerated
+ ;; of (:include clauses).
(when (and (numberp moreslotsn)
(> moreslotsn 0))
(setf slotsn (+ slotsn moreslotsn))
@@ -2419,74 +2116,18 @@ them. `setf' of the accessors sets their values."
(let (properties functions keywords accessors alterators returned)
;; compute properties of NAME
(setq properties
- (append
- (list
- (list 'put (list 'quote name) :structure-doc
- docstring)
- (list 'put (list 'quote name) :structure-slotsn
- slotsn)
- (list 'put (list 'quote name) :structure-slots
- (list 'quote slots))
- (list 'put (list 'quote name) :structure-initforms
- (list 'quote initlist))
- (list 'put (list 'quote name) :structure-indices
- (list 'quote (extract$indices initlist))))
- ;; If this definition :includes another defstruct,
- ;; modify both property lists.
- (cond (included
- (list
- (list 'put
- (list 'quote name)
- :structure-includes
- (list 'quote included))
- (list 'pushnew
- (list 'quote name)
- (list 'get (list 'quote (car included))
- :structure-included-in))))
- (t
- (list
- (let ((old (gensym)))
- (list 'let
- (list (list old
- (list 'car
- (list 'get
- (list 'quote name)
- :structure-includes))))
- (list 'when old
- (list 'put
- old
- :structure-included-in
- (list 'delq
- (list 'quote name)
- ;; careful with destructive
- ;;manipulation!
- (list
- 'append
- (list
- 'get
- old
- :structure-included-in)
- '())
- )))))
- (list 'put
- (list 'quote name)
- :structure-includes
- '()))))
- ;; If this definition used to be :included in another, warn
- ;; that things make break. On the other hand, the redefinition
- ;; may be trivial, so don't call it an error.
- (let ((old (gensym)))
- (list
- (list 'let
- (list (list old (list 'get
- (list 'quote name)
- :structure-included-in)))
- (list 'when old
- (list 'message
- "`%s' redefined. Should redefine `%s'?"
- (list 'quote name)
- (list 'prin1-to-string old))))))))
-
+ (list
+ (list 'put (list 'quote name) :structure-doc
+ docstring)
+ (list 'put (list 'quote name) :structure-slotsn
+ slotsn)
+ (list 'put (list 'quote name) :structure-slots
+ (list 'quote slots))
+ (list 'put (list 'quote name) :structure-initforms
+ (list 'quote initlist))
+ (list 'put (list 'quote name) :structure-indices
+ (list 'quote (extract$indices initlist)))))
+
;; Compute functions associated with NAME. This is not
;; handling BOA constructors yet, but here would be the place.
(setq functions
@@ -2500,34 +2141,18 @@ them. `setf' of the accessors sets their values."
(list 'fset (list 'quote copier)
(list 'function
(list 'lambda (list 'struct)
- (list 'copy-sequence 'struct))))
- (let ((typetag (gensym)))
- (list 'fset (list 'quote predicate)
- (list
- 'function
- (list
- 'lambda (list 'thing)
- (list 'and
- (list 'vectorp 'thing)
- (list 'let
- (list (list typetag
- (list 'elt 'thing 0)))
- (list 'or
- (list
- 'and
- (list 'eq
- typetag
- (list 'quote name))
- (list '=
- (list 'length 'thing)
- (1+ slotsn)))
- (list
- 'memq
- typetag
- (list 'get
- (list 'quote name)
- :structure-included-in))))))
- )))))
+ (list 'copy-vector 'struct))))
+ (list 'fset (list 'quote predicate)
+ (list 'function
+ (list 'lambda (list 'thing)
+ (list 'and
+ (list 'vectorp 'thing)
+ (list 'eq
+ (list 'elt 'thing 0)
+ (list 'quote name))
+ (list '=
+ (list 'length 'thing)
+ (1+ slotsn))))))))
;; compute accessors for NAME's slots
(multiple-value-setq
(accessors alterators keywords)
@@ -2545,7 +2170,7 @@ them. `setf' of the accessors sets their values."
accessors alterators returned))))))
(defun parse$defstruct$args (args)
- "(parse$defstruct$args ARGS) => NAME OPTIONS DOCSTRING SLOTSN SLOTS INITLIST
+ "PARSE$DEFSTRUCT$ARGS ARGS => NAME OPTIONS DOCSTRING SLOTSN SLOTS INITLIST
NAME=symbol, OPTIONS=list of, DOCSTRING=string, SLOTSN=count of slots,
SLOTS=list of their names, INITLIST=alist (keyword . initform)."
(let (name ;args=(symbol...) or ((symbol...)...)
@@ -2556,15 +2181,16 @@ SLOTS=list of their names, INITLIST=alist (keyword . initform)."
(slots '()) ;list of slot names
(initlist '())) ;list of (slot keyword . initform)
;; extract name and options
- (cond ((symbolp (car args)) ;simple name
- (setq name (car args)
- options '()))
- ((and (listp (car args)) ;(name . options)
- (symbolp (caar args)))
- (setq name (caar args)
- options (cdar args)))
- (t
- (error "first arg to `defstruct' must be symbol or (symbol ...)")))
+ (cond
+ ((symbolp (car args)) ;simple name
+ (setq name (car args)
+ options '()))
+ ((and (listp (car args)) ;(name . options)
+ (symbolp (caar args)))
+ (setq name (caar args)
+ options (cdar args)))
+ (t
+ (error "First arg to `defstruct' must be symbol or (symbol ...)")))
(setq slotargs (cdr args))
;; is there a docstring?
(when (stringp (car slotargs))
@@ -2577,7 +2203,7 @@ SLOTS=list of their names, INITLIST=alist (keyword . initform)."
(values name options docstring slotsn slots initlist))))
(defun process$slots (slots)
- "(process$slots SLOTS) => SLOTSN SLOTSLIST INITLIST
+ "PROCESS$SLOTS SLOTS => SLOTSN SLOTSLIST INITLIST
Converts a list of symbols or lists of symbol and form into the last 3
values returned by PARSE$DEFSTRUCT$ARGS."
(let ((slotsn (length slots)) ;number of slots
@@ -2587,35 +2213,28 @@ values returned by PARSE$DEFSTRUCT$ARGS."
((ptr slots (cdr ptr))
(this (car ptr) (car ptr)))
((endp ptr))
- (cond ((symbolp this)
- (setq slotslist (cons this slotslist))
- (setq initlist (acons (keyword-of this) nil initlist)))
- ((and (listp this)
- (symbolp (car this)))
- (let ((name (car this))
- (form (cadr this)))
- ;; this silently ignores any slot options. bad...
- (setq slotslist (cons name slotslist))
- (setq initlist (acons (keyword-of name) form initlist))))
- (t
- (error "slot should be symbol or (symbol ...), not `%s'"
- (prin1-to-string this)))))
+ (cond
+ ((symbolp this)
+ (setq slotslist (cons this slotslist))
+ (setq initlist (acons (keyword-of this) nil initlist)))
+ ((and (listp this)
+ (symbolp (car this)))
+ (let ((name (car this))
+ (form (cadr this)))
+ ;; this silently ignores any slot options. bad...
+ (setq slotslist (cons name slotslist))
+ (setq initlist (acons (keyword-of name) form initlist))))
+ (t
+ (error "Slot should be symbol or (symbol ...), not `%s'"
+ (prin1-to-string this)))))
(values slotsn (nreverse slotslist) (nreverse initlist))))
(defun parse$defstruct$options (name options slots)
- "(parse$defstruct$options name OPTIONS SLOTS) => many values
-A defstruct named NAME, with options list OPTIONS, has already slots SLOTS.
-Parse the OPTIONS and return the updated form of the struct's slots and other
-information. The values returned are:
-
- CONC-NAME is the string to use as prefix/suffix in the methods,
- CONST is the name of the official constructor,
- COPIER is the name of the structure copier,
- PRED is the name of the type predicate,
- MORESLOTSN is the number of slots added by :include,
- MORESLOTS is the list of slots added by :include,
- MOREINITS is the list of initialization forms added by :include,
- INCLUDED is nil, or the list of the symbol added by :include"
+ "PARSE$DEFSTRUCT$OPTIONS NAME OPTIONS SLOTS => CONC-NAME CONST COPIER PRED
+Returns at least those 4 values (a string and 3 symbols, to name the necessary
+functions), might return also things discovered by actually
+inspecting the options, namely MORESLOTSN MORESLOTS MOREINITS, as can
+be created by :include, and perhaps a list of BOACONSTRUCTORS."
(let* ((namestring (symbol-name name))
;; to build the return values
(conc-name (concat namestring "-"))
@@ -2632,7 +2251,6 @@ information. The values returned are:
these-slotsn ;When :include is found, the
these-slots ; info about the included
these-inits ; structure is added here.
- included ;NIL or (list INCLUDED)
)
;; Values above are the defaults. Now we read the options themselves
(dolist (option options)
@@ -2643,7 +2261,7 @@ information. The values returned are:
(:named
) ;ignore silently
(t
- (error "can't recognize option `%s'"
+ (error "Can't recognize option `%s'"
(prin1-to-string option)))))
((and (listp option)
(keywordp (setq option-head (car option))))
@@ -2667,7 +2285,7 @@ information. The values returned are:
(null option-rest))
option-second)
(t
- (error "can't recognize option `%s'"
+ (error "Can't recognize option `%s'"
(prin1-to-string option))))))
(:constructor ;no BOA-constructors allowed
@@ -2677,7 +2295,7 @@ information. The values returned are:
(null option-rest))
option-second)
(t
- (error "can't recognize option `%s'"
+ (error "Can't recognize option `%s'"
(prin1-to-string option))))))
(:predicate
(setq pred
@@ -2686,11 +2304,11 @@ information. The values returned are:
(null option-rest))
option-second)
(t
- (error "can't recognize option `%s'"
+ (error "Can't recognize option `%s'"
(prin1-to-string option))))))
(:include
(unless (symbolp option-second)
- (error "arg to `:include' should be a symbol, not `%s'"
+ (error "Arg to `:include' should be a symbol, not `%s'"
(prin1-to-string option-second)))
(setq these-slotsn (get option-second :structure-slotsn)
these-slots (get option-second :structure-slots)
@@ -2699,10 +2317,6 @@ information. The values returned are:
(> these-slotsn 0))
(error "`%s' is not a valid structure"
(prin1-to-string option-second)))
- (if included
- (error "`%s' already includes `%s', can't include `%s' too"
- name (car included) option-second)
- (push option-second included))
(multiple-value-bind
(xtra-slotsn xtra-slots xtra-inits)
(process$slots option-rest)
@@ -2719,18 +2333,17 @@ information. The values returned are:
((:print-function :type :initial-offset)
) ;ignore silently
(t
- (error "can't recognize option `%s'"
+ (error "Can't recognize option `%s'"
(prin1-to-string option)))))
(t
- (error "can't recognize option `%s'"
+ (error "Can't recognize option `%s'"
(prin1-to-string option)))))
;; Return values found
(values conc-name const copier pred
- moreslotsn moreslots moreinits
- included)))
+ moreslotsn moreslots moreinits)))
(defun simplify$inits (slots initlist)
- "(simplify$inits SLOTS INITLIST) => new INITLIST
+ "SIMPLIFY$INITS SLOTS INITLIST => new INITLIST
Removes from INITLIST - an ALIST - any shadowed bindings."
(let ((result '()) ;built here
key ;from the slot
@@ -2741,7 +2354,7 @@ Removes from INITLIST - an ALIST - any shadowed bindings."
(nreverse result)))
(defun extract$indices (initlist)
- "(extract$indices INITLIST) => indices list
+ "EXTRACT$INDICES INITLIST => indices list
Kludge. From a list of pairs (keyword . form) build a list of pairs
of the form (keyword . position in list from 0). Useful to precompute
some of the work of MAKE$STRUCTURE$INSTANCE."
@@ -2752,7 +2365,7 @@ some of the work of MAKE$STRUCTURE$INSTANCE."
index (+ index 1)))))
(defun build$accessors$for (name conc-name predicate slots slotsn)
- "(build$accessors$for NAME PREDICATE SLOTS SLOTSN) => FSETS DEFSETFS KWDS
+ "BUILD$ACCESSORS$FOR NAME PREDICATE SLOTS SLOTSN => FSETS DEFSETFS KWDS
Generate the code for accesors and defsetfs of a structure called
NAME, whose slots are SLOTS. Also, establishes the keywords for the
slots names."
@@ -2775,7 +2388,7 @@ slots names."
(list 'aref 'object (1+ i)))
(list 't
(list 'error
- "`%s' is not a struct %s"
+ "`%s' not a %s."
(list 'prin1-to-string
'object)
(list 'prin1-to-string
@@ -2803,7 +2416,7 @@ slots names."
keywords))))
(defun make$structure$instance (name args)
- "(make$structure$instance NAME ARGS) => new struct NAME
+ "MAKE$STRUCTURE$INSTANCE NAME ARGS => new struct NAME
A struct of type NAME is created, some slots might be initialized
according to ARGS (the &rest argument of MAKE-name)."
(unless (symbolp name)
@@ -2821,7 +2434,7 @@ according to ARGS (the &rest argument of MAKE-name)."
(error "`%s' is not a defined structure"
(prin1-to-string name)))
(unless (evenp (length args))
- (error "slot initializers `%s' not of even length"
+ (error "Slot initializers `%s' not of even length"
(prin1-to-string args)))
;; analyze the initializers provided by the call
(multiple-value-bind
@@ -2829,7 +2442,7 @@ according to ARGS (the &rest argument of MAKE-name)."
(unzip-list args) ; by the user
;; check that all the arguments are introduced by keywords
(unless (every (function keywordp) speckwds)
- (error "all of the names in `%s' should be keywords"
+ (error "All of the names in `%s' should be keywords"
(prin1-to-string speckwds)))
;; check that all the keywords are known
(dolist (kwd speckwds)
@@ -2862,276 +2475,5 @@ according to ARGS (the &rest argument of MAKE-name)."
(cons name initializers)))))
;;;; end of cl-structs.el
-
-;;; For lisp-interaction mode, so that multiple values can be seen when passed
-;;; back. Lies every now and then...
-
-(defvar - nil "form currently under evaluation")
-(defvar + nil "previous -")
-(defvar ++ nil "previous +")
-(defvar +++ nil "previous ++")
-(defvar / nil "list of values returned by +")
-(defvar // nil "list of values returned by ++")
-(defvar /// nil "list of values returned by +++")
-(defvar * nil "(first) value of +")
-(defvar ** nil "(first) value of ++")
-(defvar *** nil "(first) value of +++")
-
-(defun cl-eval-print-last-sexp ()
- "Evaluate sexp before point; print value\(s\) into current buffer.
-If the evaled form returns multiple values, they are shown one to a line.
-The variables -, +, ++, +++, *, **, ***, /, //, /// have their usual meaning.
-
-It clears the multiple-value passing mechanism, and does not pass back
-multiple values. Use this only if you are debugging cl.el and understand well
-how the multiple-value stuff works, because it can be fooled into believing
-that multiple values have been returned when they actually haven't, for
-instance
- \(identity \(values nil 1\)\)
-However, even when this fails, you can trust the first printed value to be
-\(one of\) the returned value\(s\)."
- (interactive)
- ;; top level call, can reset mvalues
- (setq *mvalues-count* nil
- *mvalues-values* nil)
- (setq - (car (read-from-string
- (buffer-substring
- (let ((stab (syntax-table)))
- (unwind-protect
- (save-excursion
- (set-syntax-table emacs-lisp-mode-syntax-table)
- (forward-sexp -1)
- (point))
- (set-syntax-table stab)))
- (point)))))
- (setq *** **
- ** *
- * (eval -))
- (setq /// //
- // /
- / *mvalues-values*)
- (setq +++ ++
- ++ +
- + -)
- (cond ((or (null *mvalues-count*) ;mvalues mechanism not used
- (not (eq * (car *mvalues-values*))))
- (print * (current-buffer)))
- ((null /) ;no values returned
- (terpri (current-buffer)))
- (t ;more than zero mvalues
- (terpri (current-buffer))
- (mapcar (function (lambda (value)
- (prin1 value (current-buffer))
- (terpri (current-buffer))))
- /)))
- (setq *mvalues-count* nil ;make sure
- *mvalues-values* nil))
-
-;;;; More LISTS functions
-;;;;
-
-;;; Some mapping functions on lists, commonly useful.
-;;; They take no extra sequences, to go along with Emacs Lisp's MAPCAR.
-
-(defun mapc (function list)
- "(MAPC FUNCTION LIST) => LIST
-Apply FUNCTION to each element of LIST, return LIST.
-Like mapcar, but called only for effect."
- (let ((args list))
- (while args
- (funcall function (car args))
- (setq args (cdr args))))
- list)
-
-(defun maplist (function list)
- "(MAPLIST FUNCTION LIST) => list'ed results of FUNCTION on cdrs of LIST
-Apply FUNCTION to successive sublists of LIST, return the list of the results"
- (let ((args list)
- results '())
- (while args
- (setq results (cons (funcall function args) results)
- args (cdr args)))
- (nreverse results)))
-
-(defun mapl (function list)
- "(MAPL FUNCTION LIST) => LIST
-Apply FUNCTION to successive cdrs of LIST, return LIST.
-Like maplist, but called only for effect."
- (let ((args list))
- (while args
- (funcall function args)
- (setq args (cdr args)))
- list))
-
-(defun mapcan (function list)
- "(MAPCAN FUNCTION LIST) => nconc'd results of FUNCTION on LIST
-Apply FUNCTION to each element of LIST, nconc the results.
-Beware: nconc destroys its first argument! See copy-list."
- (let ((args list)
- (results '()))
- (while args
- (setq results (nconc (funcall function (car args)) results)
- args (cdr args)))
- (nreverse results)))
-
-(defun mapcon (function list)
- "(MAPCON FUNCTION LIST) => nconc'd results of FUNCTION on cdrs of LIST
-Apply FUNCTION to successive sublists of LIST, nconc the results.
-Beware: nconc destroys its first argument! See copy-list."
- (let ((args list)
- (results '()))
- (while args
- (setq results (nconc (funcall function args) results)
- args (cdr args)))
- (nreverse results)))
-
-;;; Copiers
-
-(defun copy-list (list)
- "Build a copy of LIST"
- (append list '()))
-
-(defun copy-tree (tree)
- "Build a copy of the tree of conses TREE
-The argument is a tree of conses, it is recursively copied down to
-non conses. Circularity and sharing of substructure are not
-necessarily preserved."
- (if (consp tree)
- (cons (copy-tree (car tree))
- (copy-tree (cdr tree)))
- tree))
-
-;;; reversals, and destructive manipulations of a list's spine
-
-(defun revappend (x y)
- "does what (append (reverse X) Y) would, only faster"
- (if (endp x)
- y
- (revappend (cdr x) (cons (car x) y))))
-
-(defun nreconc (x y)
- "does (nconc (nreverse X) Y) would, only faster
-Destructive on X, be careful."
- (if (endp x)
- y
- ;; reuse the first cons of x, making it point to y
- (nreconc (cdr x) (prog1 x (rplacd x y)))))
-
-(defun nbutlast (list &optional n)
- "Side-effected LIST truncated N+1 conses from the end.
-This is the destructive version of BUTLAST. Returns () and does not
-modify the LIST argument if the length of the list is not at least N."
- (when (null n) (setf n 1))
- (let ((length (list-length list)))
- (cond ((null length)
- list)
- ((< length n)
- '())
- (t
- (setnthcdr (- length n) list nil)
- list))))
-
-;;; Substitutions
-
-(defun subst (new old tree)
- "NEW replaces OLD in a copy of TREE
-Uses eql for the test."
- (subst-if new (function (lambda (x) (eql x old))) tree))
-
-(defun subst-if-not (new test tree)
- "NEW replaces any subtree or leaf that fails TEST in a copy of TREE"
- ;; (subst-if new (function (lambda (x) (not (funcall test x)))) tree)
- (cond ((not (funcall test tree))
- new)
- ((atom tree)
- tree)
- (t ;no match so far
- (let ((head (subst-if-not new test (car tree)))
- (tail (subst-if-not new test (cdr tree))))
- ;; If nothing changed, return originals. Else use the new
- ;; components to assemble a new tree.
- (if (and (eql head (car tree))
- (eql tail (cdr tree)))
- tree
- (cons head tail))))))
-
-(defun subst-if (new test tree)
- "NEW replaces any subtree or leaf that satisfies TEST in a copy of TREE"
- (cond ((funcall test tree)
- new)
- ((atom tree)
- tree)
- (t ;no match so far
- (let ((head (subst-if new test (car tree)))
- (tail (subst-if new test (cdr tree))))
- ;; If nothing changed, return originals. Else use the new
- ;; components to assemble a new tree.
- (if (and (eql head (car tree))
- (eql tail (cdr tree)))
- tree
- (cons head tail))))))
-
-(defun sublis (alist tree)
- "Use association list ALIST to modify a copy of TREE
-If a subtree or leaf of TREE is a key in ALIST, it is replaced by the
-associated value. Not exactly Common Lisp, but close in spirit and
-compatible with the native Emacs Lisp ASSOC, which uses EQUAL."
- (let ((toplevel (assoc tree alist)))
- (cond (toplevel ;Bingo at top
- (cdr toplevel))
- ((atom tree) ;Give up on this
- tree)
- (t
- (let ((head (sublis alist (car tree)))
- (tail (sublis alist (cdr tree))))
- (if (and (eql head (car tree))
- (eql tail (cdr tree)))
- tree
- (cons head tail)))))))
-
-(defun member-if (predicate list)
- "PREDICATE is applied to the members of LIST. As soon as one of them
-returns true, that tail of the list if returned. Else NIL."
- (catch 'found-member-if
- (while (not (endp list))
- (if (funcall predicate (car list))
- (throw 'found-member-if list)
- (setq list (cdr list))))
- nil))
-
-(defun member-if-not (predicate list)
- "PREDICATE is applied to the members of LIST. As soon as one of them
-returns false, that tail of the list if returned. Else NIL."
- (catch 'found-member-if-not
- (while (not (endp list))
- (if (funcall predicate (car list))
- (setq list (cdr list))
- (throw 'found-member-if-not list)))
- nil))
-
-(defun tailp (sublist list)
- "(tailp SUBLIST LIST) => True if SUBLIST is a sublist of LIST."
- (catch 'tailp-found
- (while (not (endp list))
- (if (eq sublist list)
- (throw 'tailp-found t)
- (setq list (cdr list))))
- nil))
-
-;;; Suggestion of phr%widow.Berkeley.EDU@lilac.berkeley.edu
-
-(defmacro declare (&rest decls)
- "Ignore a Common-Lisp declaration."
- "declarations are ignored in this implementation")
-
-(defun proclaim (&rest decls)
- "Ignore a Common-Lisp proclamation."
- "declarations are ignored in this implementation")
-
-(defmacro the (type form)
- "(the TYPE FORM) macroexpands to FORM
-No checking is even attempted. This is just for compatibility with
-Common-Lisp codes."
- form)
;;;; end of cl.el
diff --git a/lisp/cl.elc b/lisp/cl.elc
new file mode 100644
index 00000000000..8586823a775
--- /dev/null
+++ b/lisp/cl.elc
Binary files differ
diff --git a/lisp/cmacexp.el b/lisp/cmacexp.el
new file mode 100644
index 00000000000..7b33282bb88
--- /dev/null
+++ b/lisp/cmacexp.el
@@ -0,0 +1,45 @@
+
+(defun c-macro-expand (beg end)
+ "Display the result of expanding all C macros occurring in the region.
+The expansion is entirely correct because it uses the C preprocessor."
+ (interactive "r")
+ (let ((outbuf (get-buffer-create "*Macroexpansion*"))
+ (tempfile "%%macroexpand%%")
+ process
+ last-needed)
+ (save-excursion
+ (set-buffer outbuf)
+ (erase-buffer))
+ (setq process (start-process "macros" outbuf "/lib/cpp"))
+ (set-process-sentinel process '(lambda (&rest x)))
+ (save-restriction
+ (widen)
+ (save-excursion
+ (goto-char beg)
+ (beginning-of-line)
+ (setq last-needed (point))
+ (if (re-search-backward "^[ \t]*#" nil t)
+ (progn
+ ;; Skip continued lines.
+ (while (progn (end-of-line) (= (preceding-char) ?\\))
+ (forward-line 1))
+ ;; Skip the last line of the macro definition we found.
+ (forward-line 1)
+ (setq last-needed (point)))))
+ (write-region (point-min) last-needed tempfile nil 'nomsg)
+ (process-send-string process (concat "#include \"" tempfile "\"\n"))
+ (process-send-string process "\n")
+ (process-send-region process beg end)
+ (process-send-string process "\n")
+ (process-send-eof process))
+ (while (eq (process-status process) 'run)
+ (accept-process-output))
+ (delete-file tempfile)
+ (save-excursion
+ (set-buffer outbuf)
+ (goto-char (point-max))
+ (re-search-backward "\n# [12] \"\"")
+ (forward-line 2)
+ (while (eolp) (delete-char 1))
+ (delete-region (point-min) (point)))
+ (display-buffer outbuf)))
diff --git a/lisp/comint.el b/lisp/comint.el
deleted file mode 100644
index 31e8b40e1e7..00000000000
--- a/lisp/comint.el
+++ /dev/null
@@ -1,866 +0,0 @@
-;;; -*-Emacs-Lisp-*- General command interpreter in a window stuff
-;;; Copyright (C) 1989 Free Software Foundation, Inc.
-;;; Original author: Olin Shivers <olin.shivers@cs.cmu.edu> Aug 1988
-
-;;; This file is part of GNU Emacs.
-
-;;; GNU Emacs is free software; you can redistribute it and/or modify
-;;; it under the terms of the GNU General Public License as published by
-;;; the Free Software Foundation; either version 1, or (at your option)
-;;; any later version.
-
-;;; GNU Emacs is distributed in the hope that it will be useful,
-;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;;; GNU General Public License for more details.
-
-;;; You should have received a copy of the GNU General Public License
-;;; along with GNU Emacs; see the file COPYING. If not, write to
-;;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
-;;; This file defines a general command-interpreter-in-a-buffer package
-;;; (comint mode). The idea is that you can build specific process-in-a-buffer
-;;; modes on top of comint mode -- e.g., lisp, shell, scheme, T, soar, ....
-;;; This way, all these specific packages share a common base functionality,
-;;; and a common set of bindings, which makes them easier to use (and
-;;; saves code, implementation time, etc., etc.).
-
-;;; For documentation on the functionality provided by comint mode, and
-;;; the hooks available for customising it, see the comments below.
-;;; For further information on the standard derived modes (shell,
-;;; inferior-lisp, inferior-scheme, ...), see the relevant source files.
-
-;;; For hints on converting existing process modes to use comint-mode
-;;; instead of shell-mode, see the notes at the end of this file.
-
-(require 'history)
-(provide 'comint)
-(defconst comint-version "2.01")
-
-
-;;; Not bound by default in comint-mode
-;;; send-invisible Read a line w/o echo, and send to proc
-;;; (These are bound in shell-mode)
-;;; comint-dynamic-complete Complete filename at point.
-;;; comint-dynamic-list-completions List completions in help buffer.
-;;; comint-replace-by-expanded-filename Expand and complete filename at point;
-;;; replace with expanded/completed name.
-(defvar comint-mode-map nil)
-
-(if comint-mode-map
- nil
- (setq comint-mode-map (make-sparse-keymap))
- (define-key comint-mode-map "\C-a" 'comint-bol)
- (define-key comint-mode-map "\C-d" 'comint-delchar-or-maybe-eof)
- (define-key comint-mode-map "\C-m" 'comint-send-input)
- (define-key comint-mode-map "\M-p" 'comint-previous-input)
- (define-key comint-mode-map "\M-n" 'comint-next-input)
- (define-key comint-mode-map "\M-s" 'comint-previous-similar-input)
- (define-key comint-mode-map "\C-c\C-c" 'comint-interrupt-subjob) ; tty ^C
- (define-key comint-mode-map "\C-c\C-f" 'comint-continue-subjob) ; shell "fg"
- (define-key comint-mode-map "\C-c\C-l" 'comint-show-output)
- (define-key comint-mode-map "\C-c\C-o" 'comint-flush-output) ; tty ^O
- (define-key comint-mode-map "\C-c\C-r" 'comint-history-search-backward)
- (define-key comint-mode-map "\C-c\C-s" 'comint-history-search-forward)
- (define-key comint-mode-map "\C-c\C-u" 'comint-kill-input) ; tty ^U
- (define-key comint-mode-map "\C-c\C-w" 'backward-kill-word) ; tty ^W
- (define-key comint-mode-map "\C-c\C-z" 'comint-stop-subjob) ; tty ^Z
- (define-key comint-mode-map "\C-c\C-\\" 'comint-quit-subjob)) ; tty ^\
-
-;;; Buffer Local Variables:
-;;;============================================================================
-;;; Comint mode buffer local variables:
-;;; comint-prompt-regexp - string comint-bol uses to match prompt.
-;;; comint-last-input-end - marker For comint-flush-output command
-;;; input-ring-size - integer For the input history
-;;; input-ring - ring mechanism
-;;; input-ring-index - marker ...
-;;; comint-last-input-match - string ...
-;;; comint-get-old-input - function Hooks for specific
-;;; comint-input-sentinel - function process-in-a-buffer
-;;; comint-input-filter - function modes.
-;;; comint-input-send - function
-;;; comint-eol-on-send - boolean
-
-(make-variable-buffer-local
- (defvar comint-prompt-regexp "^"
- "*Regexp to recognise prompts in the inferior process. Defaults to \"^\".
-
-Good choices:
- Canonical Lisp: \"^[^> \n]*>+:? *\" (Lucid, Franz, KCL, T, cscheme, oaklisp)
- Lucid Common Lisp: \"^\\(>\\|\\(->\\)+\\) *\"
- Franz: \"^\\(->\\|<[0-9]*>:\\) *\"
- KCL and T: \"^>+ *\"
- shell: \"^[^#$%>\n]*[#$%>] *\"
-
-This is a good thing to set in mode hooks."))
-
-(make-variable-buffer-local
- (defvar input-ring-size 30 "Size of input history ring."))
-
-;;; Here are the per-interpreter hooks.
-(make-variable-buffer-local
- (defvar comint-get-old-input (function comint-get-old-input-default)
- "Function that submits old text in comint mode.
-This function is called when return is typed while the point is in old text.
-It returns the text to be submitted as process input. The default is
-comint-get-old-input-default, which grabs the current line, and strips off
-leading text matching comint-prompt-regexp."))
-
-(make-variable-buffer-local
- (defvar comint-input-sentinel (function ignore)
- "Called on each input submitted to comint mode process by comint-send-input.
-Thus it can, for instance, track cd/pushd/popd commands issued to the csh."))
-
-(make-variable-buffer-local
- (defvar comint-input-filter
- (function (lambda (str) (not (string-match "\\`\\s *\\'" str))))
- "Predicate for filtering additions to input history.
-Only inputs answering true to this function are saved on the input
-history list. Default is to save anything that isn't all whitespace"))
-
-(defvar comint-mode-hook '()
- "Called upon entry into comint-mode")
-
-(defun comint-mode ()
- "Major mode for interacting with an inferior interpreter.
-Interpreter name is same as buffer name, sans the asterisks.
-Return at end of buffer sends line as input.
-Return not at end copies rest of line to end and sends it.
-
-This mode is typically customised to create inferior-lisp-mode,
-shell-mode, et cetera. This can be done by setting the hooks
-comint-input-sentinel, comint-input-filter, and comint-get-old-input
-to appropriate functions, and the variable comint-prompt-regexp
-to the appropriate regular expression.
-
-An input history is maintained of size input-ring-size, and
-can be accessed with the commands comint-next-input [\\[comint-next-input]] and
-comint-previous-input [\\[comint-previous-input]]. Commands not keybound by
-default are send-invisible, comint-dynamic-complete, and
-comint-list-dynamic-completions.
-
-If you accidentally suspend your process, use \\[comint-continue-subjob]
-to continue it.
-
-\\{comint-mode-map}
-
-Entry to this mode runs the hooks on comint-mode-hook."
- (interactive)
- (kill-all-local-variables)
- (setq major-mode 'comint-mode
- mode-name "Comint"
- mode-line-process '(": %s"))
- (use-local-map comint-mode-map)
- (set (make-local-variable 'input-ring) (make-ring input-ring-size))
- (put 'input-ring 'preserved t)
- (set (make-local-variable 'comint-last-input-match) "")
- (set (make-local-variable 'comint-last-similar--string) "")
- (set (make-local-variable 'input-ring-index) 0)
- (set (make-local-variable 'comint-last-input-end) (make-marker))
- (set-marker comint-last-input-end (point-max))
- (run-hooks 'comint-mode-hook))
-
-(defun comint-check-proc (buffer-name)
- "True if there is a running or stopped process associated with BUFFER."
- (let ((proc (get-buffer-process buffer-name)))
- (and proc (memq (process-status proc) '(run stop)))))
-
-(defun comint-mark ()
- ;; Returns the process-mark of the current-buffer
- (process-mark (get-buffer-process (current-buffer))))
-
-;;; Note that this guy, unlike shell.el's make-shell, barfs if you pass it ()
-;;; for the second argument (program).
-(defun make-comint (name program &optional startfile &rest switches)
- (let* ((buffer (get-buffer-create (concat "*" name "*")))
- (proc (get-buffer-process buffer)))
- ;; If no process, or nuked process, crank up a new one and put buffer in
- ;; comint mode. Otherwise, leave buffer and existing process alone.
- (cond ((not (comint-check-proc buffer))
- (save-excursion
- (set-buffer buffer)
- (comint-mode)) ; Install local vars, mode, keymap, ...
- (comint-exec buffer name program startfile switches)))
- buffer))
-
-(defun comint-exec (buffer name command startfile switches)
- "Fires up a process in buffer for comint modes.
-Blasts any old process running in the buffer. Doesn't set the buffer mode.
-You can use this to cheaply run a series of processes in the same buffer."
- (or command (error "No program for comint process"))
- (save-excursion
- (set-buffer buffer)
- (let ((proc (get-buffer-process buffer))) ; Blast any old process.
- (if proc (delete-process proc)))
- ;; Crank up a new process
- (let ((proc (comint-exec-1 name buffer command switches)))
- ;; Jump to the end, and set the process mark.
- (set-marker (comint-mark) (goto-char (point-max)))
- ;; Feed it the startfile.
- (cond (startfile
- ;;This is guaranteed to wait long enough
- ;;but has bad results if the comint does not prompt at all
- ;; (while (= size (buffer-size))
- ;; (sleep-for 1))
- ;;I hope 1 second is enough!
- (sleep-for 1)
- (goto-char (point-max))
- (insert-file-contents startfile)
- (setq startfile (buffer-substring (point) (point-max)))
- (delete-region (point) (point-max))
- (comint-send-string proc startfile))))
- buffer))
-
-;;; This auxiliary function cranks up the process for comint-exec in
-;;; the appropriate environment. It is twice as long as it should be
-;;; because emacs has two distinct mechanisms for manipulating the
-;;; process environment, selected at compile time with the
-;;; MAINTAIN-ENVIRONMENT #define. In one case, process-environment
-;;; is bound; in the other it isn't.
-
-(defun comint-exec-1 (name buffer command switches)
- (if (boundp 'process-environment) ; Not a completely reliable test.
- (let ((process-environment
- (comint-update-env process-environment
- (list (format "TERMCAP=emacs:co#%d:tc=unknown"
- (screen-width))
- "TERM=emacs"
- "EMACS=t"))))
- (apply 'start-process name buffer command switches))
- (let ((tcapv (getenv "TERMCAP"))
- (termv (getenv "TERM"))
- (emv (getenv "EMACS")))
- (unwind-protect
- (progn (setenv "TERMCAP" (format "emacs:co#%d:tc=unknown"
- (screen-width)))
- (setenv "TERM" "emacs")
- (setenv "EMACS" "t")
- (apply 'start-process name buffer command switches))
- (setenv "TERMCAP" tcapv)
- (setenv "TERM" termv)
- (setenv "EMACS" emv)))))
-
-;; This is just (append new old-env) that compresses out shadowed entries.
-;; It's also pretty ugly, mostly due to elisp's horrible iteration structures.
-(defun comint-update-env (old-env new)
- (let ((ans (reverse new))
- (vars (mapcar (function (lambda (vv)
- (and (string-match "^[^=]*=" vv)
- (substring vv 0 (match-end 0)))))
- new)))
- (while old-env
- (let* ((vv (car old-env)) ; vv is var=value
- (var (and (string-match "^[^=]*=" vv)
- (substring vv 0 (match-end 0)))))
- (setq old-env (cdr old-env))
- (cond ((not (and var (member var vars)))
- (if var (setq var (cons var vars)))
- (setq ans (cons vv ans))))))
- (nreverse ans)))
-
-;;; Input history retrieval commands
-;;; M-p -- previous input M-n -- next input
-;;; C-c r -- previous input matching
-;;; ===========================================================================
-
-(defun comint-previous-input (arg)
- "Cycle backwards through input history."
- (interactive "*p")
- (let ((len (ring-length input-ring)))
- (if (<= len 0) (error "Empty input ring"))
- (if (< (point) (comint-mark))
- (delete-region (comint-mark) (goto-char (point-max))))
- (cond ((eq last-command 'comint-previous-input)
- (delete-region (mark) (point)))
- ((eq last-command 'comint-previous-similar-input)
- (delete-region (comint-mark) (point)))
- (t
- (setq input-ring-index
- (if (> arg 0) -1
- (if (< arg 0) 1 0)))
- (push-mark (point))))
- (setq input-ring-index (comint-mod (+ input-ring-index arg) len))
- (message "%d" (1+ input-ring-index))
- (insert (ring-ref input-ring input-ring-index))
- (setq this-command 'comint-previous-input)))
-
-(defun comint-next-input (arg)
- "Cycle forwards through input history."
- (interactive "*p")
- (comint-previous-input (- arg)))
-
-(defun comint-previous-input-matching (str)
- "Searches backwards through input history for substring match."
- (interactive (let* ((last-command last-command) ; preserve around r-f-m
- (s (read-from-minibuffer
- (format "Command substring (default %s): "
- comint-last-input-match))))
- (list (if (string= s "") comint-last-input-match s))))
-; (interactive "sCommand substring: ")
- (setq comint-last-input-match str) ; update default
- (if (not (eq last-command 'comint-previous-input))
- (setq input-ring-index -1))
- (let ((str (regexp-quote str))
- (len (ring-length input-ring))
- (n (+ input-ring-index 1)))
- (while (and (< n len) (not (string-match str (ring-ref input-ring n))))
- (setq n (+ n 1)))
- (cond ((< n len)
- (comint-previous-input (- n input-ring-index)))
- (t (if (eq last-command 'comint-previous-input)
- (setq this-command 'comint-previous-input))
- (error "Not found")))))
-
-;;;
-;;; Similar input -- contributed by ccm and highly winning.
-;;;
-;;; Reenter input, removing back to the last insert point if it exists.
-;;;
-(defun comint-previous-similar-input (arg)
- "Reenters the last input that matches the string typed so far. If repeated
-successively older inputs are reentered. If arg is 1, it will go back
-in the history, if -1 it will go forward."
- (interactive "p")
- (if (< (point) (comint-mark))
- (error "Not after process mark"))
- (if (not (eq last-command 'comint-previous-similar-input))
- (setq input-ring-index -1
- comint-last-similar-string
- (buffer-substring (comint-mark) (point))))
- (let* ((size (length comint-last-similar-string))
- (len (ring-length input-ring))
- (n (+ input-ring-index arg))
- entry)
- (while (and (< n len)
- (or (< (length (setq entry (ring-ref input-ring n))) size)
- (not (equal comint-last-similar-string
- (substring entry 0 size)))))
- (setq n (+ n arg)))
- (cond ((< n len)
- (setq input-ring-index n)
- (if (eq last-command 'comint-previous-similar-input)
- (delete-region (comint-mark) (point)))
- (insert (substring entry size)))
- (t (error "Not found")))))
-
-(defun comint-send-input (&optional terminator delete)
- "Send input to process, followed by a linefeed or optional TERMINATOR.
-After the process output mark, sends all text from the process mark to
-end of buffer as input to the process. Before the process output mark, calls
-value of variable comint-get-old-input to retrieve old input, replaces it in
-the input region (from the end of process output to the end of the buffer) and
-then sends it. In either case, the value of variable comint-input-sentinel is
-called on the input before sending it. The input is entered into the input
-history ring, if value of variable comint-input-filter returns non-nil when
-called on the input.
-
-If optional second argument DELETE is non-nil, then the input is deleted from
-the end of the buffer. This is useful if the process unconditionally echoes
-input. Processes which use TERMINATOR or DELETE should have a command wrapper
-which provides them bound to RET; see telnet.el for an example.
-
-comint-get-old-input, comint-input-sentinel, and comint-input-filter are chosen
-according to the command interpreter running in the buffer. For example,
-
-If the interpreter is the csh,
- comint-get-old-input defaults: takes the current line, discard any
- initial string matching regexp comint-prompt-regexp.
- comint-input-sentinel: monitors input for \"cd\", \"pushd\", and \"popd\"
- commands. When it sees one, it changes the default directory of the buffer.
- comint-input-filter defaults: returns t if the input isn't all whitespace.
-
-If the comint is Lucid Common Lisp,
- comint-get-old-input: snarfs the sexp ending at point.
- comint-input-sentinel: does nothing.
- comint-input-filter: returns nil if the input matches input-filter-regexp,
- which matches (1) all whitespace (2) :a, :c, etc.
-
-Similar functions are used for other process modes."
- (interactive)
- ;; Note that the input string does not include its terminal newline.
- (if (not (get-buffer-process (current-buffer)))
- (error "Current buffer has no process")
- (let* ((pmark (comint-mark))
- (input (if (>= (point) pmark)
- (buffer-substring pmark (goto-char (point-max)))
- (let ((copy (funcall comint-get-old-input)))
- (delete-region pmark (goto-char (point-max)))
- (insert copy)
- copy))))
- (set-marker comint-last-input-end (point))
- (setq input-ring-index 0)
- (if (funcall comint-input-filter input) (ring-insert input-ring input))
- (funcall comint-input-sentinel input)
- (comint-send-string nil (concat input (or terminator "\n")))
- (if delete (delete-region mark (point))
- (insert "\n"))
- (set-marker (comint-mark) (point)))))
-
-(defun comint-get-old-input-default ()
- "Default for comint-get-old-input: use the current line sans prompt."
- (save-excursion
- (comint-bol)
- (buffer-substring (point) (progn (end-of-line) (point)))))
-
-(defun comint-bol (arg)
- "Goes to the beginning of line, then skips past the prompt, if any.
-With a prefix argument, (\\[universal-argument]), then doesn't skip prompt.
-
-The prompt skip is done by passing over text matching the regular expression
-comint-prompt-regexp, a buffer local variable."
- (interactive "P")
- (beginning-of-line)
- (or arg (if (looking-at comint-prompt-regexp) (goto-char (match-end 0)))))
-
-;;; These two functions are for entering text you don't want echoed or
-;;; saved -- typically passwords to ftp, telnet, or somesuch.
-;;; Just enter M-x send-invisible and type in your line.
-(defun comint-read-noecho (prompt)
- "Prompting with PROMPT, read a single line of text without echoing.
-The text can still be recovered (temporarily) with \\[view-lossage]. This
-may be a security bug for some applications."
- (let ((echo-keystrokes 0)
- (answ "")
- tem)
- (if (and (stringp prompt) (not (string= (message prompt) "")))
- (message prompt))
- (while (not (or (= (setq tem (read-char)) ?\^m)
- (= tem ?\n)))
- (setq answ (concat answ (char-to-string tem))))
- (message "")
- answ))
-
-(defun send-invisible (str)
- "Read a string without echoing, and send it to the current buffer's process.
-A newline is also sent. String is not saved on comint input history list.
-Security bug: your string can still be temporarily recovered with \\[view-lossage]."
-; (interactive (list (comint-read-noecho "Enter non-echoed text")))
- (interactive "P") ; Defeat snooping via C-x esc
- (let ((proc (get-buffer-process (current-buffer))))
- (if (not proc) (error "Current buffer has no process")
- (comint-send-string proc
- (if (stringp str) str
- (comint-read-noecho "Enter non-echoed text")))
- (comint-send-string proc "\n"))))
-
-
-;;; Low-level process communication
-
-(defvar comint-input-chunk-size 512
- "*Long inputs send to comint processes are broken up into chunks of this size.
-If your process is choking on big inputs, try lowering the value.")
-
-(defun comint-send-string (proc str)
- "Send PROCESS the contents of STRING as input.
-This is equivalent to process-send-string, except that long input strings
-are broken up into chunks of size comint-input-chunk-size. Processes
-are given a chance to output between chunks. This can help prevent processes
-from hanging when you send them long inputs on some OS's."
- (let* ((len (length str))
- (i (min len comint-input-chunk-size)))
- (process-send-string proc (substring str 0 i))
- (while (< i len)
- (let ((next-i (+ i comint-input-chunk-size)))
- (accept-process-output)
- (process-send-string proc (substring str i (min len next-i)))
- (setq i next-i)))))
-
-(defun comint-send-region (proc start end)
- "Sends to PROC the region delimited by START and END.
-This is a replacement for process-send-region that tries to keep
-your process from hanging on long inputs. See comint-send-string."
- (comint-send-string proc (buffer-substring start end)))
-
-
-;;; Random input hackage
-
-(defun comint-flush-output ()
- "Kill all output from interpreter since last input."
- (interactive)
- (save-excursion
- (goto-char (comint-mark))
- (beginning-of-line)
- (delete-region (1+ comint-last-input-end) (point))
- (insert "*** output flushed ***\n")))
-
-(defun comint-show-output ()
- "Start display of the current window at line preceding start of last output.
-\"Last output\" is considered to start at the line following the last command
-entered to the process."
- (interactive)
- (goto-char comint-last-input-end)
- (beginning-of-line)
- (set-window-start (selected-window) (point))
- (comint-bol))
-
-(defun comint-interrupt-subjob ()
- "Sent an interrupt signal to the current subprocess.
-If the process-connection-type is via ptys, the signal is sent to the current
-process group of the pseudoterminal which Emacs is using to communicate with
-the subprocess. If the process is a job-control shell, this means the
-shell's current subjob. If the process connection is via pipes, the signal is
-sent to the immediate subprocess."
- (interactive)
- (interrupt-process nil t))
-
-(defun comint-kill-subjob ()
- "Send a kill signal to the current subprocess.
-See comint-interrupt-subjob for a description of \"current subprocess\"."
- (interactive)
- (kill-process nil t))
-
-(defun comint-quit-subjob ()
- "Send a quit signal to the current subprocess.
-See comint-interrupt-subjob for a description of \"current subprocess\"."
- (interactive)
- (quit-process nil t))
-
-(defun comint-stop-subjob ()
- "Stop the current subprocess.
-See comint-interrupt-subjob for a description of \"current subprocess\".
-
-WARNING: if there is no current subjob, you can end up suspending
-the top-level process running in the buffer. If you accidentally do
-this, use \\[comint-continue-subjob] to resume the process. (This is not a
-problem with most shells, since they ignore this signal.)"
- (interactive)
- (stop-process nil t))
-
-(defun comint-continue-subjob ()
- "Send a continue signal to current subprocess.
-See comint-interrupt-subjob for a description of \"current subprocess\".
-Useful if you accidentally suspend the top-level process."
- (interactive)
- (continue-process nil t))
-
-(defun comint-kill-input ()
- "Kill from current command through point."
- (interactive)
- (let ((pmark (comint-mark)))
- (if (> (point) pmark)
- (kill-region pmark (point))
- (error "Nothing to kill"))))
-
-(defun comint-delchar-or-maybe-eof (arg)
- "Delete ARG characters forward, or send an EOF to process if at end of buffer."
- (interactive "p")
- (if (eobp)
- (process-send-eof)
- (delete-char arg)))
-
-;;; Support for source-file processing commands.
-;;;============================================================================
-;;; Many command-interpreters (e.g., Lisp, Scheme, Soar) have
-;;; commands that process files of source text (e.g. loading or compiling
-;;; files). So the corresponding process-in-a-buffer modes have commands
-;;; for doing this (e.g., lisp-load-file). The functions below are useful
-;;; for defining these commands.
-;;;
-;;; Alas, these guys don't do exactly the right thing for Lisp, Scheme
-;;; and Soar, in that they don't know anything about file extensions.
-;;; So the compile/load interface gets the wrong default occasionally.
-;;; The load-file/compile-file default mechanism could be smarter -- it
-;;; doesn't know about the relationship between filename extensions and
-;;; whether the file is source or executable. If you compile foo.lisp
-;;; with compile-file, then the next load-file should use foo.bin for
-;;; the default, not foo.lisp. This is tricky to do right, particularly
-;;; because the extension for executable files varies so much (.o, .bin,
-;;; .lbin, .mo, .vo, .ao, ...).
-
-
-;;; COMINT-SOURCE-DEFAULT -- determines defaults for source-file processing
-;;; commands.
-;;;
-;;; COMINT-CHECK-SOURCE -- if FNAME is in a modified buffer, asks you if you
-;;; want to save the buffer before issuing any process requests to the command
-;;; interpreter.
-;;;
-;;; COMINT-GET-SOURCE -- used by the source-file processing commands to prompt
-;;; for the file to process.
-
-;;; (COMINT-SOURCE-DEFAULT previous-dir/file source-modes)
-;;;============================================================================
-;;; This function computes the defaults for the load-file and compile-file
-;;; commands for tea, soar, lisp, and scheme modes.
-;;;
-;;; - PREVIOUS-DIR/FILE is a pair (directory . filename) from the last
-;;; source-file processing command. NIL if there hasn't been one yet.
-;;; - SOURCE-MODES is a list used to determine what buffers contain source
-;;; files: if the major mode of the buffer is in SOURCE-MODES, it's source.
-;;; Typically, (lisp-mode) or (scheme-mode).
-;;;
-;;; If the command is given while the cursor is inside a string, *and*
-;;; the string is an existing filename, *and* the filename is not a directory,
-;;; then the string is taken as default. This allows you to just position
-;;; your cursor over a string that's a filename and have it taken as default.
-;;;
-;;; If the command is given in a file buffer whose major mode is in
-;;; SOURCE-MODES, then the the filename is the default file, and the
-;;; file's directory is the default directory.
-;;;
-;;; If the buffer isn't a source file buffer (e.g., it's the process buffer),
-;;; then the default directory & file are what was used in the last source-file
-;;; processing command (i.e., PREVIOUS-DIR/FILE). If this is the first time
-;;; the command has been run (PREVIOUS-DIR/FILE is nil), the default directory
-;;; is the cwd, with no default file. (\"no default file\" = nil)
-;;;
-;;; SOURCE-REGEXP is typically going to be something like (tea-mode)
-;;; for T programs, (lisp-mode) for Lisp programs, (soar-mode lisp-mode)
-;;; for Soar programs, etc.
-;;;
-;;; The function returns a pair: (default-directory . default-file).
-
-(defun comint-source-default (previous-dir/file source-modes)
- (cond ((and buffer-file-name (memq major-mode source-modes))
- (cons (file-name-directory buffer-file-name)
- (file-name-nondirectory buffer-file-name)))
- (previous-dir/file)
- (t
- (cons default-directory nil))))
-
-;;; (COMINT-CHECK-SOURCE fname)
-;;;============================================================================
-;;; Prior to loading or compiling (or otherwise processing) a file (in the
-;;; process-in-a-buffer modes), this function can be called on the filename.
-;;; If the file is loaded into a buffer, and the buffer is modified, the user
-;;; is queried to see if he wants to save the buffer before proceeding with
-;;; the load or compile.
-
-(defun comint-check-source (fname)
- (let ((buff (get-file-buffer fname)))
- (if (and buff
- (buffer-modified-p buff)
- (y-or-n-p (format "Save buffer %s first? "
- (buffer-name buff))))
- ;; save BUFF.
- (let ((old-buffer (current-buffer)))
- (set-buffer buff)
- (save-buffer)
- (set-buffer old-buffer)))))
-
-;;; (COMINT-GET-SOURCE prompt prev-dir/file source-modes mustmatch-p)
-;;;============================================================================
-;;; COMINT-GET-SOURCE is used to prompt for filenames in command-interpreter
-;;; commands that process source files (like loading or compiling a file).
-;;; It prompts for the filename, provides a default, if there is one,
-;;; and returns the result filename.
-;;;
-;;; See COMINT-SOURCE-DEFAULT for more on determining defaults.
-;;;
-;;; PROMPT is the prompt string. PREV-DIR/FILE is the (directory . file) pair
-;;; from the last source processing command. SOURCE-MODES is a list of major
-;;; modes used to determine what file buffers contain source files. (These
-;;; two arguments are used for determining defaults). If MUSTMATCH-P is true,
-;;; then the filename reader will only accept a file that exists.
-;;;
-;;; A typical use:
-;;; (interactive (comint-get-source "Compile file: " prev-lisp-dir/file
-;;; '(lisp-mode) t))
-
-;;; This is pretty stupid about strings. It decides we're in a string
-;;; if there's a quote on both sides of point on the current line.
-(defun comint-extract-string ()
- "Returns string around point that starts the current line or nil."
- (save-excursion
- (let* ((point (point))
- (bol (progn (beginning-of-line) (point)))
- (eol (progn (end-of-line) (point)))
- (start (progn (goto-char point)
- (and (search-backward "\"" bol t)
- (1+ (point)))))
- (end (progn (goto-char point)
- (and (search-forward "\"" eol t)
- (1- (point))))))
- (and start end
- (buffer-substring start end)))))
-
-(defun comint-get-source (prompt prev-dir/file source-modes mustmatch-p)
- (let* ((def (comint-source-default prev-dir/file source-modes))
- (stringfile (comint-extract-string))
- (sfile-p (and stringfile
- (file-exists-p stringfile)
- (not (file-directory-p stringfile))))
- (defdir (if sfile-p (file-name-directory stringfile)
- (car def)))
- (deffile (if sfile-p (file-name-nondirectory stringfile)
- (cdr def)))
- (ans (read-file-name (if deffile (format "%s(default %s) "
- prompt deffile)
- prompt)
- defdir
- (concat defdir deffile)
- mustmatch-p)))
- (list (expand-file-name (substitute-in-file-name ans)))))
-
-
-;;; Simple process query facility.
-;;; ===========================================================================
-;;; This function is for commands that want to send a query to the process
-;;; and show the response to the user. For example, a command to get the
-;;; arglist for a Common Lisp function might send a "(arglist 'foo)" query
-;;; to an inferior Common Lisp process.
-;;;
-;;; This simple facility just sends strings to the inferior process and pops
-;;; up a window for the process buffer so you can see what the process
-;;; responds with. We don't do anything fancy like try to intercept what the
-;;; process responds with and put it in a pop-up window or on the message
-;;; line. We just display the buffer. Low tech. Simple. Works good.
-
-;;; Send to the inferior process PROC the string STR. Pop-up but do not select
-;;; a window for the inferior process so that its response can be seen.
-(defun comint-proc-query (proc str)
- (let* ((proc-buf (process-buffer proc))
- (proc-mark (process-mark proc)))
- (display-buffer proc-buf)
- (set-buffer proc-buf) ; but it's not the selected *window*
- (let ((proc-win (get-buffer-window proc-buf))
- (proc-pt (marker-position proc-mark)))
- (comint-send-string proc str) ; send the query
- (accept-process-output proc) ; wait for some output
- ;; Try to position the proc window so you can see the answer.
- ;; This is bogus code. If you delete the (sit-for 0), it breaks.
- ;; I don't know why. Wizards invited to improve it.
- (if (not (pos-visible-in-window-p proc-pt proc-win))
- (let ((opoint (window-point proc-win)))
- (set-window-point proc-win proc-mark) (sit-for 0)
- (if (not (pos-visible-in-window-p opoint proc-win))
- (push-mark opoint)
- (set-window-point proc-win opoint)))))))
-
-
-;;; Filename completion in a buffer
-;;; ===========================================================================
-;;; Useful completion functions, courtesy of the Ergo group.
-;;; M-<Tab> will complete the filename at the cursor as much as possible
-;;; M-? will display a list of completions in the help buffer.
-
-;;; Three commands:
-;;; comint-dynamic-complete Complete filename at point.
-;;; comint-dynamic-list-completions List completions in help buffer.
-;;; comint-replace-by-expanded-filename Expand and complete filename at point;
-;;; replace with expanded/completed name.
-
-;;; These are not installed in the comint-mode keymap. But they are
-;;; available for people who want them. Shell-mode-map uses them, though.
-
-(defun comint-match-partial-pathname ()
- "Returns the string of an existing filename or causes an error."
- (if (save-excursion (backward-char 1) (looking-at "\\s ")) ""
- (save-excursion
- (re-search-backward "[^~/A-Za-z0-9---_.$#,]+")
- (re-search-forward "[~/A-Za-z0-9---_.$#,]+")
- (substitute-in-file-name
- (buffer-substring (match-beginning 0) (match-end 0))))))
-
-(defun comint-replace-by-expanded-filename ()
- "Replace the filename at point with its expanded, canonicalised completion.
-\"Expanded\" means environment variables (e.g., $HOME) and ~'s are
-replaced with the corresponding directories. \"Canonicalised\" means ..
-and . are removed, and the filename is made absolute instead of relative.
-See functions expand-file-name and substitute-in-file-name. See also
-comint-dynamic-complete."
- (interactive)
- (let* ((pathname (comint-match-partial-pathname))
- (pathdir (file-name-directory pathname))
- (pathnondir (file-name-nondirectory pathname))
- (completion (file-name-completion pathnondir
- (or pathdir default-directory))))
- (cond ((null completion)
- (error "No completions"))
- ((eql completion t)
- (message "Sole completion"))
- (t ; this means a string was returned.
- (delete-region (match-beginning 0) (match-end 0))
- (insert (expand-file-name (concat pathdir completion)))))))
-
-(defun comint-dynamic-complete ()
- "Complete the filename at point.
-This function is similar to comint-replace-by-expanded-filename, except
-that it won't change parts of the filename already entered in the buffer;
-it just adds completion characters to the end of the filename."
- (interactive)
- (let* ((pathname (comint-match-partial-pathname))
- (pathdir (file-name-directory pathname))
- (pathnondir (file-name-nondirectory pathname))
- (completion (file-name-completion pathnondir
- (or pathdir default-directory))))
- (cond ((null completion)
- (error "No completions"))
- ((eql completion t)
- (error "Sole completion"))
- (t ; this means a string was returned.
- (goto-char (match-end 0))
- (insert (substring completion (length pathnondir)))))))
-
-(defun comint-dynamic-list-completions ()
- "List all possible completions of the filename at point."
- (interactive)
- (let* ((pathname (comint-match-partial-pathname))
- (pathdir (file-name-directory pathname))
- (pathnondir (file-name-nondirectory pathname))
- (completions
- (file-name-all-completions pathnondir
- (or pathdir default-directory))))
- (cond ((null completions)
- (error "No completions"))
- (t
- (let ((conf (current-window-configuration)))
- (with-output-to-temp-buffer " *Completions*"
- (display-completion-list completions))
- (sit-for 0)
- (message "Hit space to flush.")
- (let ((ch (read-char)))
- (if (= ch ?\ )
- (set-window-configuration conf)
- (setq unread-command-char ch))))))))
-
-
-;;; Converting process modes to use comint mode
-;;; ===========================================================================
-;;; Renaming variables
-;;; Most of the work is renaming variables and functions.
-;;; These are the common ones.
-
-;;; Local variables --
-;;; last-input-end comint-last-input-end
-;;; last-input-start <unnecessary>
-;;; shell-prompt-pattern comint-prompt-regexp
-;;; shell-set-directory-error-hook <no equivalent>
-;;; Miscellaneous --
-;;; shell-set-directory <unnecessary>
-;;; shell-mode-map comint-mode-map
-;;; Commands --
-;;; shell-send-input comint-send-input
-;;; shell-send-eof comint-delchar-or-maybe-eof
-;;; kill-shell-input comint-kill-input
-;;; interrupt-shell-subjob comint-interrupt-subjob
-;;; stop-shell-subjob comint-stop-subjob
-;;; quit-shell-subjob comint-quit-subjob
-;;; kill-shell-subjob comint-kill-subjob
-;;; kill-output-from-shell comint-kill-output
-;;; show-output-from-shell comint-show-output
-;;; copy-last-shell-input Use comint-previous-input/comint-next-input
-;;;
-;;; LAST-INPUT-START is no longer necessary because inputs are stored on the
-;;; input history ring. SHELL-SET-DIRECTORY is gone, its functionality taken
-;;; over by SHELL-DIRECTORY-TRACKER, the shell mode's comint-input-sentinel.
-;;; Comint mode does not provide functionality equivalent to
-;;; shell-set-directory-error-hook; it is gone.
-;;;
-;;; If you are implementing some process-in-a-buffer mode, called foo-mode, do
-;;; *not* create the comint-mode local variables in your foo-mode function.
-;;; This is not modular. Instead, call comint-mode, and let *it* create the
-;;; necessary comint-specific local variables. Then create the
-;;; foo-mode-specific local variables in foo-mode. Set the buffer's keymap to
-;;; be foo-mode-map, and its mode to be foo-mode. Set the comint-mode hooks
-;;; (comint-prompt-regexp, comint-input-filter, comint-input-sentinel,
-;;; comint-get-old-input) that need to be different from the defaults. Call
-;;; foo-mode-hook, and you're done. Don't run the comint-mode hook yourself;
-;;; comint-mode will take care of it.
-;;;
-;;; Note that make-comint is different from make-shell in that it
-;;; doesn't have a default program argument. If you give make-shell
-;;; a program name of NIL, it cleverly chooses one of explicit-shell-name,
-;;; $ESHELL, $SHELL, or /bin/sh. If you give make-comint a program argument
-;;; of NIL, it barfs. Adjust your code accordingly...
diff --git a/lisp/compare-w.el b/lisp/compare-w.el
new file mode 100644
index 00000000000..cdc93f74f62
--- /dev/null
+++ b/lisp/compare-w.el
@@ -0,0 +1,59 @@
+;; Compare text between windows for Emacs.
+;; Copyright (C) 1986 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 1, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+(defun compare-windows ()
+ "Compare text in current window with text in next window.
+Compares the text starting at point in each window,
+moving over text in each one as far as they match."
+ (interactive)
+ (let (p1 p2 maxp1 maxp2 b1 b2 w2
+ success size
+ (opoint (point)))
+ (setq p1 (point) b1 (current-buffer))
+ (setq w2 (next-window (selected-window)))
+ (if (eq w2 (selected-window))
+ (error "No other window."))
+ (setq p2 (window-point w2)
+ b2 (window-buffer w2))
+ (setq maxp1 (point-max))
+ (save-excursion
+ (set-buffer b2)
+ (setq maxp2 (point-max)))
+
+ ;; Try advancing comparing 1000 chars at a time.
+ ;; When that fails, go 500 chars at a time, and so on.
+ (setq size 1000)
+ (while (> size 0)
+ (setq success t)
+ (while success
+ (setq size (min size (- maxp1 p1) (- maxp2 p2)))
+ (save-excursion
+ (set-buffer b2)
+ (setq s2 (buffer-substring p2 (+ size p2))))
+ (setq s1 (buffer-substring p1 (+ size p1)))
+ (setq success (and (> size 0) (equal s1 s2)))
+ (if success
+ (setq p1 (+ p1 size) p2 (+ p2 size))))
+ (setq size (/ size 2)))
+
+ (goto-char p1)
+ (set-window-point w2 p2)
+ (if (= (point) opoint)
+ (ding))))
diff --git a/lisp/compare-w.elc b/lisp/compare-w.elc
new file mode 100644
index 00000000000..fea719725b3
--- /dev/null
+++ b/lisp/compare-w.elc
Binary files differ
diff --git a/lisp/compile.el b/lisp/compile.el
new file mode 100644
index 00000000000..1796d40fcf2
--- /dev/null
+++ b/lisp/compile.el
@@ -0,0 +1,318 @@
+;; Run compiler as inferior of Emacs, and parse its error messages.
+;; Copyright (C) 1985, 1986 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 1, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+(provide 'compile)
+
+(defvar compilation-process nil
+ "Process created by compile command, or nil if none exists now.
+Note that the process may have been \"deleted\" and still
+be the value of this variable.")
+
+(defvar compilation-error-list nil
+ "List of error message descriptors for visiting erring functions.
+Each error descriptor is a list of length two.
+Its car is a marker pointing to an error message.
+Its cadr is a marker pointing to the text of the line the message is about,
+ or nil if that is not interesting.
+The value may be t instead of a list;
+this means that the buffer of error messages should be reparsed
+the next time the list of errors is wanted.")
+
+(defvar compilation-parsing-end nil
+ "Position of end of buffer when last error messages parsed.")
+
+(defvar compilation-error-message nil
+ "Message to print when no more matches for compilation-error-regexp are found")
+
+;; The filename excludes colons to avoid confusion when error message
+;; starts with digits.
+(defvar compilation-error-regexp
+ "\\([^ :\n]+\\(: *\\|, line \\|(\\)[0-9]+\\)\\|\\([0-9]+ *of *[^ \n]+\\)"
+ "Regular expression for filename/linenumber in error in compilation log.")
+
+(defun compile (command)
+ "Compile the program including the current buffer. Default: run `make'.
+Runs COMMAND, a shell command, in a separate process asynchronously
+with output going to the buffer *compilation*.
+You can then use the command \\[next-error] to find the next error message
+and move to the source code that caused it."
+ (interactive (list (read-string "Compile command: " compile-command)))
+ (setq compile-command command)
+ (compile1 compile-command "No more errors"))
+
+(defun grep (command)
+ "Run grep, with user-specified args, and collect output in a buffer.
+While grep runs asynchronously, you can use the \\[next-error] command
+to find the text that grep hits refer to."
+ (interactive "sRun grep (with args): ")
+ (compile1 (concat "grep -n " command " /dev/null")
+ "No more grep hits" "grep"))
+
+(defun compile1 (command error-message &optional name-of-mode)
+ (save-some-buffers)
+ (if compilation-process
+ (if (or (not (eq (process-status compilation-process) 'run))
+ (yes-or-no-p "A compilation process is running; kill it? "))
+ (condition-case ()
+ (if compilation-process
+ (let ((comp-proc compilation-process))
+ (interrupt-process comp-proc)
+ (sit-for 1)
+ (delete-process comp-proc)))
+ (error nil))
+ (error "Cannot have two compilation processes")))
+ (setq compilation-process nil)
+ (compilation-forget-errors)
+ (setq compilation-error-list t)
+ (setq compilation-error-message error-message)
+ (setq compilation-process
+ (start-process "compilation" "*compilation*"
+ shell-file-name
+ "-c" (concat "exec " command)))
+ (with-output-to-temp-buffer "*compilation*"
+ (princ "cd ")
+ (princ default-directory)
+ (terpri)
+ (princ command)
+ (terpri))
+ (set-process-sentinel compilation-process 'compilation-sentinel)
+ (let* ((thisdir default-directory)
+ (outbuf (process-buffer compilation-process))
+ (outwin (get-buffer-window outbuf))
+ (regexp compilation-error-regexp))
+ (if (eq outbuf (current-buffer))
+ (goto-char (point-max)))
+ (save-excursion
+ (set-buffer outbuf)
+ (buffer-flush-undo outbuf)
+ (let ((start (save-excursion (set-buffer outbuf) (point-min))))
+ (set-window-start outwin start)
+ (or (eq outwin (selected-window))
+ (set-window-point outwin start)))
+ (setq default-directory thisdir)
+ (fundamental-mode)
+ (make-local-variable 'compilation-error-regexp)
+ (setq compilation-error-regexp regexp)
+ (setq mode-name (or name-of-mode "Compilation"))
+ ;; Make log buffer's mode line show process state
+ (setq mode-line-process '(": %s")))))
+
+;; Called when compilation process changes state.
+
+(defun compilation-sentinel (proc msg)
+ (cond ((null (buffer-name (process-buffer proc)))
+ ;; buffer killed
+ (set-process-buffer proc nil))
+ ((memq (process-status proc) '(signal exit))
+ (let* ((obuf (current-buffer))
+ omax opoint)
+ ;; save-excursion isn't the right thing if
+ ;; process-buffer is current-buffer
+ (unwind-protect
+ (progn
+ ;; Write something in *compilation* and hack its mode line,
+ (set-buffer (process-buffer proc))
+ (setq omax (point-max) opoint (point))
+ (goto-char (point-max))
+ (insert ?\n mode-name " " msg)
+ (forward-char -1)
+ (insert " at "
+ (substring (current-time-string) 0 -5))
+ (forward-char 1)
+ (setq mode-line-process
+ (concat ": "
+ (symbol-name (process-status proc))))
+ ;; If buffer and mode line will show that the process
+ ;; is dead, we can delete it now. Otherwise it
+ ;; will stay around until M-x list-processes.
+ (delete-process proc))
+ (setq compilation-process nil)
+ ;; Force mode line redisplay soon
+ (set-buffer-modified-p (buffer-modified-p)))
+ (if (and opoint (< opoint omax))
+ (goto-char opoint))
+ (set-buffer obuf)))))
+
+(defun kill-compilation ()
+ "Kill the process made by the \\[compile] command."
+ (interactive)
+ (if compilation-process
+ (interrupt-process compilation-process)))
+
+(defun kill-grep ()
+ "Kill the process made by the \\[grep] command."
+ (interactive)
+ (if compilation-process
+ (interrupt-process compilation-process)))
+
+(defun next-error (&optional argp)
+ "Visit next compilation error message and corresponding source code.
+This operates on the output from the \\[compile] command.
+If all preparsed error messages have been processed,
+the error message buffer is checked for new ones.
+A non-nil argument (prefix arg, if interactive)
+means reparse the error message buffer and start at the first error."
+ (interactive "P")
+ (if (or (eq compilation-error-list t)
+ argp)
+ (progn (compilation-forget-errors)
+ (setq compilation-parsing-end 1)))
+ (if compilation-error-list
+ nil
+ (save-excursion
+ (set-buffer "*compilation*")
+ (set-buffer-modified-p nil)
+ (compilation-parse-errors)))
+ (let ((next-error (car compilation-error-list)))
+ (if (null next-error)
+ (error (concat compilation-error-message
+ (if (and compilation-process
+ (eq (process-status compilation-process)
+ 'run))
+ " yet" ""))))
+ (setq compilation-error-list (cdr compilation-error-list))
+ (if (null (car (cdr next-error)))
+ nil
+ (switch-to-buffer (marker-buffer (car (cdr next-error))))
+ (goto-char (car (cdr next-error)))
+ (set-marker (car (cdr next-error)) nil))
+ (let* ((pop-up-windows t)
+ (w (display-buffer (marker-buffer (car next-error)))))
+ (set-window-point w (car next-error))
+ (set-window-start w (car next-error)))
+ (set-marker (car next-error) nil)))
+
+;; Set compilation-error-list to nil, and
+;; unchain the markers that point to the error messages and their text,
+;; so that they no longer slow down gap motion.
+;; This would happen anyway at the next garbage collection,
+;; but it is better to do it right away.
+(defun compilation-forget-errors ()
+ (if (eq compilation-error-list t)
+ (setq compilation-error-list nil))
+ (while compilation-error-list
+ (let ((next-error (car compilation-error-list)))
+ (set-marker (car next-error) nil)
+ (if (car (cdr next-error))
+ (set-marker (car (cdr next-error)) nil)))
+ (setq compilation-error-list (cdr compilation-error-list))))
+
+(defun compilation-parse-errors ()
+ "Parse the current buffer as error messages.
+This makes a list of error descriptors, compilation-error-list.
+For each source-file, line-number pair in the buffer,
+the source file is read in, and the text location is saved in compilation-error-list.
+The function next-error, assigned to \\[next-error], takes the next error off the list
+and visits its location."
+ (setq compilation-error-list nil)
+ (message "Parsing error messages...")
+ (let (text-buffer
+ last-filename last-linenum)
+ ;; Don't reparse messages already seen at last parse.
+ (goto-char compilation-parsing-end)
+ ;; Don't parse the first two lines as error messages.
+ ;; This matters for grep.
+ (if (bobp)
+ (forward-line 2))
+ (while (re-search-forward compilation-error-regexp nil t)
+ (let (linenum filename
+ error-marker text-marker)
+ ;; Extract file name and line number from error message.
+ (save-restriction
+ (narrow-to-region (match-beginning 0) (match-end 0))
+ (goto-char (point-max))
+ (skip-chars-backward "[0-9]")
+ ;; If it's a lint message, use the last file(linenum) on the line.
+ ;; Normally we use the first on the line.
+ (if (= (preceding-char) ?\()
+ (progn
+ (narrow-to-region (point-min) (1+ (buffer-size)))
+ (end-of-line)
+ (re-search-backward compilation-error-regexp)
+ (skip-chars-backward "^ \t\n")
+ (narrow-to-region (point) (match-end 0))
+ (goto-char (point-max))
+ (skip-chars-backward "[0-9]")))
+ ;; Are we looking at a "filename-first" or "line-number-first" form?
+ (if (looking-at "[0-9]")
+ (progn
+ (setq linenum (read (current-buffer)))
+ (goto-char (point-min)))
+ ;; Line number at start, file name at end.
+ (progn
+ (goto-char (point-min))
+ (setq linenum (read (current-buffer)))
+ (goto-char (point-max))
+ (skip-chars-backward "^ \t\n")))
+ (setq filename (compilation-grab-filename)))
+ ;; Locate the erring file and line.
+ (if (and (equal filename last-filename)
+ (= linenum last-linenum))
+ nil
+ (beginning-of-line 1)
+ (setq error-marker (point-marker))
+ ;; text-buffer gets the buffer containing this error's file.
+ (if (not (equal filename last-filename))
+ (setq text-buffer
+ (and (file-exists-p (setq last-filename filename))
+ (find-file-noselect filename))
+ last-linenum 0))
+ (if text-buffer
+ ;; Go to that buffer and find the erring line.
+ (save-excursion
+ (set-buffer text-buffer)
+ (if (zerop last-linenum)
+ (progn
+ (goto-char 1)
+ (setq last-linenum 1)))
+ ;; Move the right number of lines from the old position.
+ ;; If we can't move that many, put 0 in last-linenum
+ ;; so the next error message will be handled starting from
+ ;; scratch.
+ (if (eq selective-display t)
+ (or (re-search-forward "[\n\C-m]" nil 'end
+ (- linenum last-linenum))
+ (setq last-linenum 0))
+ (or (= 0 (forward-line (- linenum last-linenum)))
+ (setq last-linenum 0)))
+ (setq last-linenum linenum)
+ (setq text-marker (point-marker))
+ (setq compilation-error-list
+ (cons (list error-marker text-marker)
+ compilation-error-list)))))
+ (forward-line 1)))
+ (setq compilation-parsing-end (point-max)))
+ (message "Parsing error messages...done")
+ (setq compilation-error-list (nreverse compilation-error-list)))
+
+(defun compilation-grab-filename ()
+ "Return a string which is a filename, starting at point.
+Ignore quotes and parentheses around it, as well as trailing colons."
+ (if (eq (following-char) ?\")
+ (save-restriction
+ (narrow-to-region (point)
+ (progn (forward-sexp 1) (point)))
+ (goto-char (point-min))
+ (read (current-buffer)))
+ (buffer-substring (point)
+ (progn
+ (skip-chars-forward "^ :,\n\t(")
+ (point)))))
+
+(define-key ctl-x-map "`" 'next-error)
diff --git a/lisp/compile.elc b/lisp/compile.elc
new file mode 100644
index 00000000000..bf2ba5bd84f
--- /dev/null
+++ b/lisp/compile.elc
Binary files differ
diff --git a/lisp/completion.el b/lisp/completion.el
deleted file mode 100644
index 9d478e78630..00000000000
--- a/lisp/completion.el
+++ /dev/null
@@ -1,3113 +0,0 @@
-;;; This is a Completion system for GNU Emacs
-;;;
-;;; E-Mail:
-;;; Internet: completion@think.com, bug-completion@think.com
-;;; UUCP: {rutgers,harvard,mit-eddie}!think!completion
-;;;
-;;; If you are a new user, we'd appreciate knowing your site name and
-;;; any comments you have.
-;;;
-;;;
-;;; NO WARRANTY
-;;;
-;;; This software is distributed free of charge and is in the public domain.
-;;; Anyone may use, duplicate or modify this program. Thinking Machines
-;;; Corporation does not restrict in any way the use of this software by
-;;; anyone.
-;;;
-;;; Thinking Machines Corporation provides absolutely no warranty of any kind.
-;;; The entire risk as to the quality and performance of this program is with
-;;; you. In no event will Thinking Machines Corporation be liable to you for
-;;; damages, including any lost profits, lost monies, or other special,
-;;; incidental or consequential damages arising out of the use of this program.
-;;;
-;;; You must not restrict the distribution of this software.
-;;;
-;;; Please keep this notice and author information in any copies you make.
-;;;
-;;; 4/90
-;;;
-;;;
-;;; Advertisement
-;;;---------------
-;;; Try using this. If you are like most you will be happy you did.
-;;;
-;;; What to put in .emacs
-;;;-----------------------
-;;; (load "completion") ;; If it's not part of the standard band.
-;;; (initialize-completions)
-;;;
-;;; For best results, be sure to byte-compile the file first.
-;;;
-
-;;; Authors
-;;;---------
-;;; Jim Salem {salem@think.com}
-;;; Brewster Kahle {brewster@think.com}
-;;; Thinking Machines Corporation
-;;; 245 First St., Cambridge MA 02142 (617) 876-1111
-;;;
-;;; Mailing Lists
-;;;---------------
-;;;
-;;; Bugs to bug-completion@think.com
-;;; Comments to completion@think.com
-;;; Requests to be added completion-request@think.com
-;;;
-;;; Availability
-;;;--------------
-;;; Anonymous FTP from think.com
-;;;
-
-;;;---------------------------------------------------------------------------
-;;; Documentation [Slightly out of date]
-;;;---------------------------------------------------------------------------
-;;; (also check the documentation string of the functions)
-;;;
-;;; Introduction
-;;;---------------
-;;;
-;;; After you type a few characters, pressing the "complete" key inserts
-;;; the rest of the word you are likely to type.
-;;;
-;;; This watches all the words that you type and remembers them. When
-;;; typing a new word, pressing "complete" (meta-return) "completes" the
-;;; word by inserting the most recently used word that begins with the
-;;; same characters. If you press meta-return repeatedly, it cycles
-;;; through all the words it knows about.
-;;;
-;;; If you like the completion then just continue typing, it is as if you
-;;; entered the text by hand. If you want the inserted extra characters
-;;; to go away, type control-w or delete. More options are described below.
-;;;
-;;; The guesses are made in the order of the most recently "used". Typing
-;;; in a word and then typing a separator character (such as a space) "uses"
-;;; the word. So does moving a cursor over the word. If no words are found,
-;;; it uses an extended version of the dabbrev style completion.
-;;;
-;;; You automatically save the completions you use to a file between
-;;; sessions.
-;;;
-;;; Completion enables programmers to enter longer, more descriptive
-;;; variable names while typing fewer keystrokes than they normally would.
-;;;
-;;;
-;;; Full documentation
-;;;---------------------
-;;;
-;;; A "word" is any string containing characters with either word or symbol
-;;; syntax. [E.G. Any alphanumeric string with hypens, underscores, etc.]
-;;; Unless you change the constants, you must type at least three characters
-;;; for the word to be recognized. Only words longer than 6 characters are
-;;; saved.
-;;;
-;;; When you load this file, completion will be on. I suggest you use the
-;;; compiled version (because it is noticibly faster).
-;;;
-;;; M-X completion-mode toggles whether or not new words are added to the
-;;; database by changing the value of *completep*.
-;;;
-;;; SAVING/LOADING COMPLETIONS
-;;; Completions are automatically saved from one session to another
-;;; (unless *save-completions-p* or *completep* is nil).
-;;; Loading this file (or calling initialize-completions) causes EMACS
-;;; to load a completions database for a saved completions file
-;;; (default: ~/.completions). When you exit, EMACS saves a copy of the
-;;; completions that you
-;;; often use. When you next start, EMACS loads in the saved completion file.
-;;;
-;;; The number of completions saved depends loosely on
-;;; *saved-completions-decay-factor*. Completions that have never been
-;;; inserted via "complete" are not saved. You are encouraged to experiment
-;;; with different functions (see compute-completion-min-num-uses).
-;;;
-;;; Some completions are permanent and are always saved out. These
-;;; completions have their num-uses slot set to T. Use
-;;; add-permanent-completion to do this
-;;;
-;;; Completions are saved only if *completep* is T. The number of old
-;;; versions kept of the saved completions file is controlled by
-;;; *completion-file-versions-kept*.
-;;;
-;;; COMPLETE KEY OPTIONS
-;;; The complete function takes a numeric arguments.
-;;; control-u :: leave the point at the beginning of the completion rather
-;;; than the middle.
-;;; a number :: rotate through the possible completions by that amount
-;;; `-' :: same as -1 (insert previous completion)
-;;;
-;;; HOW THE DATABASE IS MAINTAINED
-;;; <write>
-;;;
-;;; UPDATING THE DATABASE MANUALLY
-;;; m-x kill-completion
-;;; kills the completion at point.
-;;; m-x add-completion
-;;; m-x add-permanent-completion
-;;;
-;;; UPDATING THE DATABASE FROM A SOURCE CODE FILE
-;;; m-x add-completions-from-buffer
-;;; Parses all the definition names from a C or LISP mode buffer and
-;;; adds them to the completion database.
-;;;
-;;; m-x add-completions-from-lisp-file
-;;; Parses all the definition names from a C or Lisp mode file and
-;;; adds them to the completion database.
-;;;
-;;; UPDATING THE DATABASE FROM A TAGS TABLE
-;;; m-x add-completions-from-tags-table
-;;; Adds completions from the current tags-table-buffer.
-;;;
-;;; HOW A COMPLETION IS FOUND
-;;; <write>
-;;;
-;;; STRING CASING
-;;; Completion is string case independent if case-fold-search has its
-;;; normal default of T. Also when the completion is inserted the case of the
-;;; entry is coerced appropriately.
-;;; [E.G. APP --> APPROPRIATELY app --> appropriately
-;;; App --> Appropriately]
-;;;
-;;; INITIALIZATION
-;;; The form `(initialize-completions)' initializes the completion system by
-;;; trying to load in the user's completions. After the first cal, further
-;;; calls have no effect so one should be careful not to put the form in a
-;;; site's standard site-init file.
-;;;
-;;;---------------------------------------------------------------------------
-;;;
-;;;
-
-;;;-----------------------------------------------
-;;; Porting Notes
-;;;-----------------------------------------------
-;;;
-;;; Should run on 18.49, 18.52, and 19.0
-;;; Tested on vanilla version.
-;;; This requires the standard cl.el file. It could easily rewritten to not
-;;; require it. It defines remove which is not in cl.el.
-;;;
-;;; FUNCTIONS BASHED
-;;; The following functions are bashed but it is done carefully and should not
-;;; cause problems ::
-;;; kill-region, next-line, previous-line, newline, newline-and-indent,
-;;; kill-emacs
-;;;
-;;;
-;;;---------------------------------------------------------------------------
-;;; Functions you might like to call
-;;;---------------------------------------------------------------------------
-;;;
-;;; add-completion string &optional num-uses
-;;; Adds a new string to the database
-;;;
-;;; add-permanent-completion string
-;;; Adds a new string to the database with num-uses = T
-;;;
-
-;;; kill-completion string
-;;; Kills the completion from the database.
-;;;
-;;; clear-all-completions
-;;; Clears the database
-;;;
-;;; list-all-completions
-;;; Returns a list of all completions.
-;;;
-;;;
-;;; next-completion string &optional index
-;;; Returns a completion entry that starts with string.
-;;;
-;;; find-exact-completion string
-;;; Returns a completion entry that exactly matches string.
-;;;
-;;; complete
-;;; Inserts a completion at point
-;;;
-;;; initialize-completions
-;;; Loads the completions file and sets up so that exiting emacs will
-;;; save them.
-;;;
-;;; save-completions-to-file &optional filename
-;;; load-completions-from-file &optional filename
-;;;
-;;;-----------------------------------------------
-;;; Other functions
-;;;-----------------------------------------------
-;;;
-;;; get-completion-list string
-;;;
-;;; These things are for manipulating the structure
-;;; make-completion string num-uses
-;;; completion-num-uses completion
-;;; completion-string completion
-;;; set-completion-num-uses completion num-uses
-;;; set-completion-string completion string
-;;;
-;;;
-
-;;;-----------------------------------------------
-;;; To Do :: (anybody ?)
-;;;-----------------------------------------------
-;;;
-;;; Implement Lookup and keyboard interface in C
-;;; Add package prefix smarts (for Common Lisp)
-;;; Add autoprompting of possible completions after every keystroke (fast
-;;; terminals only !)
-;;; Add doc. to texinfo
-;;;
-;;;
-;;;-----------------------------------------------
-;;; History ::
-;;;-----------------------------------------------
-;;; Sometime in '84 Brewster implemented a somewhat buggy version for
-;;; Symbolics LISPMs.
-;;; Jan. '85 Jim became enamored of the idea and implemented a faster,
-;;; more robust version.
-;;; With input from many users at TMC, (rose, craig, and gls come to mind),
-;;; the current style of interface was developed.
-;;; 9/87, Jim and Brewster took terminals home. Yuck. After
-;;; complaining for a while Brewester implemented a subset of the current
-;;; LISPM version for GNU Emacs.
-;;; 8/88 After complaining for a while (and with sufficient
-;;; promised rewards), Jim reimplemented a version of GNU completion
-;;; superior to that of the LISPM version.
-;;;
-;;;-----------------------------------------------
-;;; Acknowlegements
-;;;-----------------------------------------------
-;;; Cliff Lasser (cal@think.com), Kevin Herbert (kph@cisco.com),
-;;; eero@media-lab, kgk@cs.brown.edu, jla@ai.mit.edu,
-;;;
-;;;-----------------------------------------------
-;;; Change Log
-;;;-----------------------------------------------
-;;; From version 9 to 10
-;;; - Allowance for non-integral *completion-version* nos.
-;;; - Fix cmpl-apply-as-top-level for keyboard macros
-;;; - Fix broken completion merging (in save-completions-to-file)
-;;; - More misc. fixes for version 19.0 of emacs
-;;;
-;;; From Version 8 to 9
-;;; - Ported to version 19.0 of emacs (backcompatible with version 18)
-;;; - Added add-completions-from-tags-table (with thanks to eero@media-lab)
-;;;
-;;; From Version 7 to 8
-;;; - Misc. changes to comments
-;;; - new completion key bindings: c-x o, M->, M-<, c-a, c-e
-;;; - cdabbrev now checks all the visible window buffers and the "other buffer"
-;;; - `%' is now a symbol character rather than a separator (except in C mode)
-;;;
-;;; From Version 6 to 7
-;;; - Fixed bug with saving out .completion file the first time
-;;;
-;;; From Version 5 to 6
-;;; - removed statistics recording
-;;; - reworked advise to handle autoloads
-;;; - Fixed fortran mode support
-;;; - Added new cursor motion triggers
-;;;
-;;; From Version 4 to 5
-;;; - doesn't bother saving if nothing has changed
-;;; - auto-save if haven't used for a 1/2 hour
-;;; - save period extended to two weeks
-;;; - minor fix to capitalization code
-;;; - added *completion-auto-save-period* to variables recorded.
-;;; - added reenter protection to cmpl-record-statistics-filter
-;;; - added backup protection to save-completions-to-file (prevents
-;;; problems with disk full errors)
-
-;;;-----------------------------------------------
-;;; Requires
-;;; Version
-;;;-----------------------------------------------
-
-;;(require 'cl) ;; DOTIMES, etc. {actually done after variable defs.}
-
-(defconst *completion-version* 10
- "Tested for EMACS versions 18.49, 18.52, 18.55 and beyond and 19.0.")
-
-;;;---------------------------------------------------------------------------
-;;; User changeable parameters
-;;;---------------------------------------------------------------------------
-
-(defvar *completep* t
- "*Set to nil to turn off the completion hooks.
-(No new words added to the database or saved to the init file).")
-
-(defvar *save-completions-p* t
- "*If non-nil, the most useful completions are saved to disk when
-exiting EMACS. See *saved-completions-decay-factor*.")
-
-(defvar *saved-completions-filename* "~/.completions"
- "*The filename to save completions to.")
-
-(defvar *saved-completion-retention-time* 336
- "*The maximum amount of time to save a completion for if it has not been used.
-In hours. (1 day = 24, 1 week = 168). If this is 0, non-permanent completions
-will not be saved unless these are used. Default is two weeks.")
-
-(defvar *separator-character-uses-completion-p* nil
- "*If non-nil, typing a separator character after a completion symbol that
-is not part of the database marks it as used (so it will be saved).")
-
-(defvar *completion-file-versions-kept* kept-new-versions
- "*Set this to the number of versions you want save-completions-to-file
-to keep.")
-
-(defvar *print-next-completion-speed-threshold* 4800
- "*The baud rate at or above which to print the next potential completion
-after inserting the current one."
- )
-
-(defvar *print-next-completion-does-cdabbrev-search-p* nil
- "*If non-nil, the next completion prompt will also do a cdabbrev search.
-This can be time consuming.")
-
-(defvar *cdabbrev-radius* 15000
- "*How far to search for cdabbrevs. In number of characters. If nil, the
-whole buffer is searched.")
-
-(defvar *modes-for-completion-find-file-hook* '(lisp c)
- "*A list of modes {either C or Lisp}. Definitions from visited files
-of those types are automatically added to the completion database.")
-
-(defvar *record-cmpl-statistics-p* nil
- "*If non-nil, statistics are automatically recorded.")
-
-(defvar *completion-auto-save-period* 1800
- "*The period in seconds to wait for emacs to be idle before autosaving
-the completions. Default is a 1/2 hour.")
-
-(defconst *completion-min-length* nil ;; defined below in eval-when
- "*The minimum length of a stored completion.
-DON'T CHANGE WITHOUT RECOMPILING ! This is used by macros.")
-
-(defconst *completion-max-length* nil ;; defined below in eval-when
- "*The maximum length of a stored completion.
-DON'T CHANGE WITHOUT RECOMPILING ! This is used by macros.")
-
-(defconst *completion-prefix-min-length* nil ;; defined below in eval-when
- "The minimum length of a completion search string.
-DON'T CHANGE WITHOUT RECOMPILING ! This is used by macros.")
-
-(defmacro eval-when-compile-load-eval (&rest body)
- ;; eval everything before expanding
- (mapcar 'eval body)
- (cons 'progn body))
-
-(defun completion-eval-when ()
- (eval-when-compile-load-eval
- ;; These vars. are defined at both compile and load time.
- (setq *completion-min-length* 6)
- (setq *completion-max-length* 200)
- (setq *completion-prefix-min-length* 3)
- ;; Need this file around too
- (require 'cl)))
-
-(completion-eval-when)
-
-;;;---------------------------------------------------------------------------
-;;; Internal Variables
-;;;---------------------------------------------------------------------------
-
-(defvar cmpl-initialized-p nil
- "Set to t when the completion system is initialized. Indicates that the
-old completion file has been read in.")
-
-(defvar cmpl-completions-accepted-p nil
- "Set to T as soon as the first completion has been accepted. Used to
-decide whether to save completions.")
-
-
-;;;---------------------------------------------------------------------------
-;;; Low level tools
-;;;---------------------------------------------------------------------------
-
-;;;-----------------------------------------------
-;;; Misc.
-;;;-----------------------------------------------
-
-(defun remove (item list)
- (setq list (copy-sequence list))
- (delq item list))
-
-(defun minibuffer-window-selected-p ()
- "True iff the current window is the minibuffer."
- (eq (minibuffer-window) (selected-window)))
-
-(eval-when-compile-load-eval
-(defun function-needs-autoloading-p (symbol)
- ;; True iff symbol is represents an autoloaded function and has not yet been
- ;; autoloaded.
- (and (listp (symbol-function symbol))
- (eq 'autoload (car (symbol-function symbol)))
- )))
-
-(defun function-defined-and-loaded (symbol)
- ;; True iff symbol is bound to a loaded function.
- (and (fboundp symbol) (not (function-needs-autoloading-p symbol))))
-
-(defmacro read-time-eval (form)
- ;; Like the #. reader macro
- (eval form))
-
-;;;-----------------------------------------------
-;;; Emacs Version 19 compatibility
-;;;-----------------------------------------------
-
-(defconst emacs-is-version-19 (string= (substring emacs-version 0 2) "19"))
-
-(defun cmpl19-baud-rate ()
- (if emacs-is-version-19
- baud-rate
- (baud-rate)))
-
-(defun cmpl19-sit-for (amount)
- (if (and emacs-is-version-19 (= amount 0))
- (sit-for 1 t)
- (sit-for amount)))
-
-;;;-----------------------------------------------
-;;; Advise
-;;;-----------------------------------------------
-
-(defmacro completion-advise (function-name where &rest body)
- "Adds the body code before calling function. This advise is not compiled.
-WHERE is either :BEFORE or :AFTER."
- (completion-advise-1 function-name where body)
- )
-
-(defmacro cmpl-apply-as-top-level (function arglist)
- "Calls function-name interactively if inside a call-interactively."
- (list 'cmpl-apply-as-top-level-1 function arglist
- '(let ((executing-macro nil)) (interactive-p)))
- )
-
-(defun cmpl-apply-as-top-level-1 (function arglist interactive-p)
- (if (and interactive-p (commandp function))
- (call-interactively function)
- (apply function arglist)
- ))
-
-(eval-when-compile-load-eval
-
-(defun cmpl-defun-preamble (function-name)
- (let ((doc-string
- (condition-case e
- ;; This condition-case is here to stave
- ;; off bizarre load time errors 18.52 gets
- ;; on the function c-mode
- (documentation function-name)
- (error nil)))
- (interactivep (commandp function-name))
- )
- (append
- (if doc-string (list doc-string))
- (if interactivep '((interactive)))
- )))
-
-(defun completion-advise-1 (function-name where body &optional new-name)
- (unless new-name (setq new-name function-name))
- (let ((quoted-name (list 'quote function-name))
- (quoted-new-name (list 'quote new-name))
- )
-
- (cond ((function-needs-autoloading-p function-name)
- (list* 'defun function-name '(&rest arglist)
- (append
- (cmpl-defun-preamble function-name)
- (list (list 'load (second (symbol-function function-name)))
- (list 'eval
- (list 'completion-advise-1 quoted-name
- (list 'quote where) (list 'quote body)
- quoted-new-name))
- (list 'cmpl-apply-as-top-level quoted-new-name 'arglist)
- )))
- )
- (t
- (let ((old-def-name
- (intern (concat "$$$cmpl-" (symbol-name function-name))))
- )
-
- (list 'progn
- (list 'defvar old-def-name
- (list 'symbol-function quoted-name))
- (list* 'defun new-name '(&rest arglist)
- (append
- (cmpl-defun-preamble function-name)
- (ecase where
- (:before
- (list (cons 'progn body)
- (list 'cmpl-apply-as-top-level
- old-def-name 'arglist)))
- (:after
- (list* (list 'cmpl-apply-as-top-level
- old-def-name 'arglist)
- body)
- )))
- )))
- ))))
-) ;; eval-when
-
-
-;;;-----------------------------------------------
-;;; String case coercion
-;;;-----------------------------------------------
-
-(defun cmpl-string-case-type (string)
- "Returns :capitalized, :up, :down, :mixed, or :neither."
- (let ((case-fold-search nil))
- (cond ((string-match "[a-z]" string)
- (cond ((string-match "[A-Z]" string)
- (cond ((and (> (length string) 1)
- (null (string-match "[A-Z]" string 1)))
- ':capitalized)
- (t
- ':mixed)))
- (t ':down)))
- (t
- (cond ((string-match "[A-Z]" string)
- ':up)
- (t ':neither))))
- ))
-
-;;; Tests -
-;;; (cmpl-string-case-type "123ABCDEF456") --> :up
-;;; (cmpl-string-case-type "123abcdef456") --> :down
-;;; (cmpl-string-case-type "123aBcDeF456") --> :mixed
-;;; (cmpl-string-case-type "123456") --> :neither
-;;; (cmpl-string-case-type "Abcde123") --> :capitalized
-
-(defun cmpl-coerce-string-case (string case-type)
- (cond ((eq case-type ':down) (downcase string))
- ((eq case-type ':up) (upcase string))
- ((eq case-type ':capitalized)
- (setq string (downcase string))
- (aset string 0 (logand ?\337 (aref string 0)))
- string)
- (t string)
- ))
-
-(defun cmpl-merge-string-cases (string-to-coerce given-string)
- (let ((string-case-type (cmpl-string-case-type string-to-coerce))
- )
- (cond ((memq string-case-type '(:down :up :capitalized))
- ;; Found string is in a standard case. Coerce to a type based on
- ;; the given string
- (cmpl-coerce-string-case string-to-coerce
- (cmpl-string-case-type given-string))
- )
- (t
- ;; If the found string is in some unusual case, just insert it
- ;; as is
- string-to-coerce)
- )))
-
-;;; Tests -
-;;; (cmpl-merge-string-cases "AbCdEf456" "abc") --> AbCdEf456
-;;; (cmpl-merge-string-cases "abcdef456" "ABC") --> ABCDEF456
-;;; (cmpl-merge-string-cases "ABCDEF456" "Abc") --> Abcdef456
-;;; (cmpl-merge-string-cases "ABCDEF456" "abc") --> abcdef456
-
-
-;;;-----------------------------------------------
-;;; Emacs Idle Time hooks
-;;;-----------------------------------------------
-
-(defvar cmpl-emacs-idle-process nil)
-
-(defvar cmpl-emacs-idle-interval 150
- "Seconds between running the Emacs idle process.")
-
-(defun init-cmpl-emacs-idle-process ()
- "Initialize the emacs idle process."
- (let ((live (and cmpl-emacs-idle-process
- (eq (process-status cmpl-emacs-idle-process) 'run)))
- ;; do not allocate a pty
- (process-connection-type nil))
- (if live
- (kill-process cmpl-emacs-idle-process))
- (if cmpl-emacs-idle-process
- (delete-process cmpl-emacs-idle-process))
- (setq cmpl-emacs-idle-process
- (start-process "cmpl-emacs-idle" nil
- "loadst"
- "-n" (int-to-string cmpl-emacs-idle-interval)))
- (process-kill-without-query cmpl-emacs-idle-process)
- (set-process-filter cmpl-emacs-idle-process 'cmpl-emacs-idle-filter)
- ))
-
-(defvar cmpl-emacs-buffer nil)
-(defvar cmpl-emacs-point 0)
-(defvar cmpl-emacs-last-command nil)
-(defvar cmpl-emacs-last-command-char nil)
-(defun cmpl-emacs-idle-p ()
- ;; returns T if emacs has been idle
- (if (and (eq cmpl-emacs-buffer (current-buffer))
- (= cmpl-emacs-point (point))
- (eq cmpl-emacs-last-command last-command)
- (eq last-command-char last-command-char)
- )
- t ;; idle
- ;; otherwise, update count
- (setq cmpl-emacs-buffer (current-buffer))
- (setq cmpl-emacs-point (point))
- (setq cmpl-emacs-last-command last-command)
- (setq last-command-char last-command-char)
- nil
- ))
-
-(defvar cmpl-emacs-idle-time 0
- "The idle time of Emacs in seconds.")
-
-(defvar inside-cmpl-emacs-idle-filter nil)
-(defvar cmpl-emacs-idle-time-hooks nil)
-
-(defun cmpl-emacs-idle-filter (proc string)
- ;; This gets called every cmpl-emacs-idle-interval seconds
- ;; Update idle time clock
- (if (cmpl-emacs-idle-p)
- (incf cmpl-emacs-idle-time cmpl-emacs-idle-interval)
- (setq cmpl-emacs-idle-time 0))
-
- (unless inside-cmpl-emacs-idle-filter
- ;; Don't reenter if we are hung
-
- (setq inside-cmpl-emacs-idle-filter t)
-
- (dolist (function cmpl-emacs-idle-time-hooks)
- (condition-case e
- (funcall function)
- (error nil)
- ))
- (setq inside-cmpl-emacs-idle-filter nil)
- ))
-
-
-;;;-----------------------------------------------
-;;; Time
-;;;-----------------------------------------------
-;;; What a backwards way to get the time! Unfortunately, GNU Emacs
-;;; doesn't have an accessible time function.
-
-(defconst cmpl-hours-per-day 24)
-(defconst cmpl-hours-per-year (* 365 cmpl-hours-per-day))
-(defconst cmpl-hours-per-4-years (+ (* 4 cmpl-hours-per-year)
- cmpl-hours-per-day))
-(defconst cmpl-days-since-start-of-year
- '(0 31 59 90 120 151 181 212 243 273 304 334))
-(defconst cmpl-days-since-start-of-leap-year
- '(0 31 60 91 121 152 182 213 244 274 305 335))
-(defconst cmpl-months
- '("Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul" "Aug" "Sep" "Oct" "Nov" "Dec"))
-
-(defun cmpl-hours-since-1900-internal (month day year hours)
- "Month is an integer from 1 to 12. Year is a two digit integer (19XX)"
- (+ ;; Year
- (* (/ (1- year) 4) cmpl-hours-per-4-years)
- (* (1+ (mod (1- year) 4)) cmpl-hours-per-year)
- ;; minus two to account for 1968 rather than 1900
- ;; month
- (* cmpl-hours-per-day
- (nth (1- month) (if (zerop (mod year 4))
- cmpl-days-since-start-of-leap-year
- cmpl-days-since-start-of-year)))
- (* (1- day) cmpl-hours-per-day)
- hours))
-
-(defun cmpl-month-from-string (month-string)
- "Month string is a three char. month string"
- (let ((count 1))
- (do ((list cmpl-months (cdr list))
- )
- ((or (null list) (string-equal month-string (car list))))
- (setq count (1+ count)))
- (if (> count 12)
- (error "Unknown month - %s" month-string))
- count))
-
-(defun cmpl-hours-since-1900 (&optional time-string)
- "String is a string in the format of current-time-string (the default)."
- (let* ((string (or time-string (current-time-string)))
- (month (cmpl-month-from-string (substring string 4 7)))
- (day (string-to-int (substring string 8 10)))
- (year (string-to-int (substring string 22 24)))
- (hour (string-to-int (substring string 11 13)))
- )
- (cmpl-hours-since-1900-internal month day year hour)))
-
-;;; Tests -
-;;;(cmpl-hours-since-1900 "Wed Jan 1 00:00:28 1900") --> 35040
-;;;(cmpl-hours-since-1900 "Wed Nov 2 23:00:28 1988") --> 778751
-;;;(cmpl-hours-since-1900 "Wed Jan 23 14:34:28 1988") --> 771926
-;;;(cmpl-hours-since-1900 "Wed Feb 23 14:34:28 1988") --> 772670
-;;;(cmpl-hours-since-1900 "Wed Mar 23 14:34:28 1988") --> 773366
-;;;(cmpl-hours-since-1900 "Wed Apr 23 14:34:28 1988") --> 774110
-;;;(cmpl-hours-since-1900 "Wed May 23 14:34:28 1988") --> 774830
-;;;(cmpl-hours-since-1900 "Wed Jun 23 14:34:28 1988") --> 775574
-;;;(cmpl-hours-since-1900 "Wed Jul 23 14:34:28 1988") --> 776294
-;;;(cmpl-hours-since-1900 "Wed Aug 23 14:34:28 1988") --> 777038
-;;;(cmpl-hours-since-1900 "Wed Sep 23 14:34:28 1988") --> 777782
-;;;(cmpl-hours-since-1900 "Wed Oct 23 14:34:28 1988") --> 778502
-;;;(cmpl-hours-since-1900 "Wed Nov 23 14:34:28 1988") --> 779246
-;;;(cmpl-hours-since-1900 "Wed Dec 23 14:34:28 1988") --> 779966
-;;;(cmpl-hours-since-1900 "Wed Jan 23 14:34:28 1957") --> 500198
-;;;(cmpl-hours-since-1900 "Wed Feb 23 14:34:28 1957") --> 500942
-;;;(cmpl-hours-since-1900 "Wed Mar 23 14:34:28 1957") --> 501614
-;;;(cmpl-hours-since-1900 "Wed Apr 23 14:34:28 1957") --> 502358
-;;;(cmpl-hours-since-1900 "Wed May 23 14:34:28 1957") --> 503078
-;;;(cmpl-hours-since-1900 "Wed Jun 23 14:34:28 1957") --> 503822
-;;;(cmpl-hours-since-1900 "Wed Jul 23 14:34:28 1957") --> 504542
-;;;(cmpl-hours-since-1900 "Wed Aug 23 14:34:28 1957") --> 505286
-;;;(cmpl-hours-since-1900 "Wed Sep 23 14:34:28 1957") --> 506030
-;;;(cmpl-hours-since-1900 "Wed Oct 23 14:34:28 1957") --> 506750
-;;;(cmpl-hours-since-1900 "Wed Nov 23 14:34:28 1957") --> 507494
-;;;(cmpl-hours-since-1900 "Wed Dec 23 14:34:28 1957") --> 508214
-
-
-;;;---------------------------------------------------------------------------
-;;; "Symbol" parsing functions
-;;;---------------------------------------------------------------------------
-;;; The functions symbol-before-point, symbol-under-point, etc. quickly return
-;;; an appropriate symbol string. The strategy is to temporarily change
-;;; the syntax table to enable fast symbol searching. There are three classes
-;;; of syntax in these "symbol" syntax tables ::
-;;;
-;;; syntax (?_) - "symbol" chars (e.g. alphanumerics)
-;;; syntax (?w) - symbol chars to ignore at end of words (e.g. period).
-;;; syntax (? ) - everything else
-;;;
-;;; Thus by judicious use of scan-sexps and forward-word, we can get
-;;; the word we want relatively fast and without consing.
-;;;
-;;; Why do we need a separate category for "symbol chars to ignore at ends" ?
-;;; For example, in LISP we want starting :'s trimmed
-;;; so keyword argument specifiers also define the keyword completion. And,
-;;; for example, in C we want `.' appearing in a structure ref. to
-;;; be kept intact in order to store the whole structure ref.; however, if
-;;; it appears at the end of a symbol it should be discarded because it is
-;;; probably used as a period.
-
-;;; Here is the default completion syntax ::
-;;; Symbol chars :: A-Z a-z 0-9 @ / \ * + ~ $ < > %
-;;; Symbol chars to ignore at ends :: _ : . -
-;;; Separator chars. :: <tab> <space> ! ^ & ( ) = ` | { } [ ] ; " ' #
-;;; , ? <Everything else>
-
-;;; Mode specific differences and notes ::
-;;; LISP diffs ->
-;;; Symbol chars :: ! & ? = ^
-;;;
-;;; C diffs ->
-;;; Separator chars :: + * / : %
-;;; A note on the hypen (`-'). Perhaps, the hypen should also be a separator
-;;; char., however, we wanted to have completion symbols include pointer
-;;; references. For example, "foo->bar" is a symbol as far as completion is
-;;; concerned.
-;;;
-;;; FORTRAN diffs ->
-;;; Separator chars :: + - * / :
-;;;
-;;; Pathname diffs ->
-;;; Symbol chars :: .
-;;; Of course there is no pathname "mode" and in fact we have not implemented
-;;; this table. However, if there was such a mode, this is what it would look
-;;; like.
-
-;;;-----------------------------------------------
-;;; Table definitions
-;;;-----------------------------------------------
-
-(defun make-standard-completion-syntax-table ()
- (let ((table (make-vector 256 0)) ;; default syntax is whitespace
- )
- ;; alpha chars
- (dotimes (i 26)
- (modify-syntax-entry (+ ?a i) "_" table)
- (modify-syntax-entry (+ ?A i) "_" table))
- ;; digit chars.
- (dotimes (i 10)
- (modify-syntax-entry (+ ?0 i) "_" table))
- ;; Other ones
- (let ((symbol-chars '(?@ ?/ ?\\ ?* ?+ ?~ ?$ ?< ?> ?%))
- (symbol-chars-ignore '(?_ ?- ?: ?.))
- )
- (dolist (char symbol-chars)
- (modify-syntax-entry char "_" table))
- (dolist (char symbol-chars-ignore)
- (modify-syntax-entry char "w" table)
- )
- )
- table))
-
-(defconst cmpl-standard-syntax-table (make-standard-completion-syntax-table))
-
-(defun make-lisp-completion-syntax-table ()
- (let ((table (copy-syntax-table cmpl-standard-syntax-table))
- (symbol-chars '(?! ?& ?? ?= ?^))
- )
- (dolist (char symbol-chars)
- (modify-syntax-entry char "_" table))
- table))
-
-(defun make-c-completion-syntax-table ()
- (let ((table (copy-syntax-table cmpl-standard-syntax-table))
- (separator-chars '(?+ ?* ?/ ?: ?%))
- )
- (dolist (char separator-chars)
- (modify-syntax-entry char " " table))
- table))
-
-(defun make-fortran-completion-syntax-table ()
- (let ((table (copy-syntax-table cmpl-standard-syntax-table))
- (separator-chars '(?+ ?- ?* ?/ ?:))
- )
- (dolist (char separator-chars)
- (modify-syntax-entry char " " table))
- table))
-
-(defconst cmpl-lisp-syntax-table (make-lisp-completion-syntax-table))
-(defconst cmpl-c-syntax-table (make-c-completion-syntax-table))
-(defconst cmpl-fortran-syntax-table (make-fortran-completion-syntax-table))
-
-(defvar cmpl-syntax-table cmpl-standard-syntax-table
- "This variable holds the current completion syntax table.")
-(make-variable-buffer-local 'cmpl-syntax-table)
-
-;;;-----------------------------------------------
-;;; Installing the appropriate mode tables
-;;;-----------------------------------------------
-
-(completion-advise lisp-mode-variables :after
- (setq cmpl-syntax-table cmpl-lisp-syntax-table)
- )
-
-(completion-advise c-mode :after
- (setq cmpl-syntax-table cmpl-c-syntax-table)
- )
-
-(completion-advise fortran-mode :after
- (setq cmpl-syntax-table cmpl-fortran-syntax-table)
- (completion-setup-fortran-mode)
- )
-
-;;;-----------------------------------------------
-;;; Symbol functions
-;;;-----------------------------------------------
-(defvar cmpl-symbol-start nil
- "Set to the first character of the symbol after one of the completion
-symbol functions is called.")
-(defvar cmpl-symbol-end nil
- "Set to the last character of the symbol after one of the completion
-symbol functions is called.")
-;;; These are temp. vars. we use to avoid using let.
-;;; Why ? Small speed improvement.
-(defvar cmpl-saved-syntax nil)
-(defvar cmpl-saved-point nil)
-
-(defun symbol-under-point ()
- "Returns the symbol that the point is currently on if it is longer
-than *completion-min-length*."
- (setq cmpl-saved-syntax (syntax-table))
- (set-syntax-table cmpl-syntax-table)
- (cond
- ;; Cursor is on following-char and after preceding-char
- ((memq (char-syntax (following-char)) '(?w ?_))
- (setq cmpl-saved-point (point)
- cmpl-symbol-start (scan-sexps (1+ cmpl-saved-point) -1)
- cmpl-symbol-end (scan-sexps cmpl-saved-point 1))
- ;; remove chars to ignore at the start
- (cond ((= (char-syntax (char-after cmpl-symbol-start)) ?w)
- (goto-char cmpl-symbol-start)
- (forward-word 1)
- (setq cmpl-symbol-start (point))
- (goto-char cmpl-saved-point)
- ))
- ;; remove chars to ignore at the end
- (cond ((= (char-syntax (char-after (1- cmpl-symbol-end))) ?w)
- (goto-char cmpl-symbol-end)
- (forward-word -1)
- (setq cmpl-symbol-end (point))
- (goto-char cmpl-saved-point)
- ))
- ;; restore state
- (set-syntax-table cmpl-saved-syntax)
- ;; Return completion if the length is reasonable
- (if (and (<= (read-time-eval *completion-min-length*)
- (- cmpl-symbol-end cmpl-symbol-start))
- (<= (- cmpl-symbol-end cmpl-symbol-start)
- (read-time-eval *completion-max-length*)))
- (buffer-substring cmpl-symbol-start cmpl-symbol-end))
- )
- (t
- ;; restore table if no symbol
- (set-syntax-table cmpl-saved-syntax)
- nil)
- ))
-
-;;; tests for symbol-under-point
-;;; `^' indicates cursor pos. where value is returned
-;;; simple-word-test
-;;; ^^^^^^^^^^^^^^^^ --> simple-word-test
-;;; _harder_word_test_
-;;; ^^^^^^^^^^^^^^^^^^ --> harder_word_test
-;;; .___.______.
-;;; --> nil
-;;; /foo/bar/quux.hello
-;;; ^^^^^^^^^^^^^^^^^^^ --> /foo/bar/quux.hello
-;;;
-
-(defun symbol-before-point ()
- "Returns a string of the symbol immediately before point
-or nil if there isn't one longer than *completion-min-length*."
- ;; This is called when a word separator is typed so it must be FAST !
- (setq cmpl-saved-syntax (syntax-table))
- (set-syntax-table cmpl-syntax-table)
- ;; Cursor is on following-char and after preceding-char
- (cond ((= (setq cmpl-preceding-syntax (char-syntax (preceding-char))) ?_)
- ;; No chars. to ignore at end
- (setq cmpl-symbol-end (point)
- cmpl-symbol-start (scan-sexps (1+ cmpl-symbol-end) -1)
- )
- ;; remove chars to ignore at the start
- (cond ((= (char-syntax (char-after cmpl-symbol-start)) ?w)
- (goto-char cmpl-symbol-start)
- (forward-word 1)
- (setq cmpl-symbol-start (point))
- (goto-char cmpl-symbol-end)
- ))
- ;; restore state
- (set-syntax-table cmpl-saved-syntax)
- ;; return value if long enough
- (if (>= cmpl-symbol-end
- (+ cmpl-symbol-start
- (read-time-eval *completion-min-length*)))
- (buffer-substring cmpl-symbol-start cmpl-symbol-end))
- )
- ((= cmpl-preceding-syntax ?w)
- ;; chars to ignore at end
- (setq cmpl-saved-point (point)
- cmpl-symbol-start (scan-sexps (1+ cmpl-saved-point) -1))
- ;; take off chars. from end
- (forward-word -1)
- (setq cmpl-symbol-end (point))
- ;; remove chars to ignore at the start
- (cond ((= (char-syntax (char-after cmpl-symbol-start)) ?w)
- (goto-char cmpl-symbol-start)
- (forward-word 1)
- (setq cmpl-symbol-start (point))
- ))
- ;; restore state
- (goto-char cmpl-saved-point)
- (set-syntax-table cmpl-saved-syntax)
- ;; Return completion if the length is reasonable
- (if (and (<= (read-time-eval *completion-min-length*)
- (- cmpl-symbol-end cmpl-symbol-start))
- (<= (- cmpl-symbol-end cmpl-symbol-start)
- (read-time-eval *completion-max-length*)))
- (buffer-substring cmpl-symbol-start cmpl-symbol-end))
- )
- (t
- ;; restore table if no symbol
- (set-syntax-table cmpl-saved-syntax)
- nil)
- ))
-
-;;; tests for symbol-before-point
-;;; `^' indicates cursor pos. where value is returned
-;;; simple-word-test
-;;; ^ --> nil
-;;; ^ --> nil
-;;; ^ --> simple-w
-;;; ^ --> simple-word-test
-;;; _harder_word_test_
-;;; ^ --> harder_word_test
-;;; ^ --> harder_word_test
-;;; ^ --> harder
-;;; .___....
-;;; --> nil
-
-(defun symbol-under-or-before-point ()
- ;;; This could be made slightly faster but it is better to avoid
- ;;; copying all the code.
- ;;; However, it is only used by the completion string prompter.
- ;;; If it comes into common use, it could be rewritten.
- (setq cmpl-saved-syntax (syntax-table))
- (set-syntax-table cmpl-syntax-table)
- (cond ((memq (char-syntax (following-char)) '(?w ?_))
- (set-syntax-table cmpl-saved-syntax)
- (symbol-under-point))
- (t
- (set-syntax-table cmpl-saved-syntax)
- (symbol-before-point))
- ))
-
-
-(defun symbol-before-point-for-complete ()
- ;; "Returns a string of the symbol immediately before point
- ;; or nil if there isn't one. Like symbol-before-point but doesn't trim the
- ;; end chars."
- ;; Cursor is on following-char and after preceding-char
- (setq cmpl-saved-syntax (syntax-table))
- (set-syntax-table cmpl-syntax-table)
- (cond ((memq (setq cmpl-preceding-syntax (char-syntax (preceding-char)))
- '(?_ ?w))
- (setq cmpl-symbol-end (point)
- cmpl-symbol-start (scan-sexps (1+ cmpl-symbol-end) -1)
- )
- ;; remove chars to ignore at the start
- (cond ((= (char-syntax (char-after cmpl-symbol-start)) ?w)
- (goto-char cmpl-symbol-start)
- (forward-word 1)
- (setq cmpl-symbol-start (point))
- (goto-char cmpl-symbol-end)
- ))
- ;; restore state
- (set-syntax-table cmpl-saved-syntax)
- ;; Return completion if the length is reasonable
- (if (and (<= (read-time-eval
- *completion-prefix-min-length*)
- (- cmpl-symbol-end cmpl-symbol-start))
- (<= (- cmpl-symbol-end cmpl-symbol-start)
- (read-time-eval *completion-max-length*)))
- (buffer-substring cmpl-symbol-start cmpl-symbol-end))
- )
- (t
- ;; restore table if no symbol
- (set-syntax-table cmpl-saved-syntax)
- nil)
- ))
-
-;;; tests for symbol-before-point-for-complete
-;;; `^' indicates cursor pos. where value is returned
-;;; simple-word-test
-;;; ^ --> nil
-;;; ^ --> nil
-;;; ^ --> simple-w
-;;; ^ --> simple-word-test
-;;; _harder_word_test_
-;;; ^ --> harder_word_test
-;;; ^ --> harder_word_test_
-;;; ^ --> harder_
-;;; .___....
-;;; --> nil
-
-
-
-;;;---------------------------------------------------------------------------
-;;; Statistics Recording
-;;;---------------------------------------------------------------------------
-
-;;; Note that the guts of this has been turned off. The guts
-;;; are in completion-stats.el.
-
-;;;-----------------------------------------------
-;;; Conditionalizing code on *record-cmpl-statistics-p*
-;;;-----------------------------------------------
-;;; All statistics code outside this block should use this
-(defmacro cmpl-statistics-block (&rest body)
- "Only executes body if we are recording statistics."
- (list 'cond
- (list* '*record-cmpl-statistics-p* body)
- ))
-
-;;;-----------------------------------------------
-;;; Completion Sources
-;;;-----------------------------------------------
-
-;; ID numbers
-(defconst cmpl-source-unknown 0)
-(defconst cmpl-source-init-file 1)
-(defconst cmpl-source-file-parsing 2)
-(defconst cmpl-source-separator 3)
-(defconst cmpl-source-cursor-moves 4)
-(defconst cmpl-source-interactive 5)
-(defconst cmpl-source-cdabbrev 6)
-(defconst num-cmpl-sources 7)
-(defvar current-completion-source cmpl-source-unknown)
-
-
-
-;;;---------------------------------------------------------------------------
-;;; Completion Method #2: dabbrev-expand style
-;;;---------------------------------------------------------------------------
-;;;
-;;; This method is used if there are no useful stored completions. It is
-;;; based on dabbrev-expand with these differences :
-;;; 1) Faster (we don't use regexps)
-;;; 2) case coercion handled correctly
-;;; This is called cdabbrev to differentiate it.
-;;; We simply search backwards through the file looking for words which
-;;; start with the same letters we are trying to complete.
-;;;
-
-(defvar cdabbrev-completions-tried nil)
-;;; "A list of all the cdabbrev completions since the last reset.")
-
-(defvar cdabbrev-current-point 0)
-;;; "The current point position the cdabbrev search is at.")
-
-(defvar cdabbrev-current-window nil)
-;;; "The current window we are looking for cdabbrevs in. T if looking in
-;;; (other-buffer), NIL if no more cdabbrevs.")
-
-(defvar cdabbrev-wrapped-p nil)
-;;; "T if the cdabbrev search has wrapped around the file.")
-
-(defvar cdabbrev-abbrev-string "")
-(defvar cdabbrev-start-point 0)
-
-;;; Test strings for cdabbrev
-;;; cdat-upcase ;;same namestring
-;;; CDAT-UPCASE ;;ok
-;;; cdat2 ;;too short
-;;; cdat-1-2-3-4 ;;ok
-;;; a-cdat-1 ;;doesn't start correctly
-;;; cdat-simple ;;ok
-
-
-(defun reset-cdabbrev (abbrev-string &optional initial-completions-tried)
- "Resets the cdabbrev search to search for abbrev-string.
-initial-completions-tried is a list of downcased strings to ignore
-during the search."
- (setq cdabbrev-abbrev-string abbrev-string
- cdabbrev-completions-tried
- (cons (downcase abbrev-string) initial-completions-tried)
- )
- (reset-cdabbrev-window t)
- )
-
-(defun set-cdabbrev-buffer ()
- ;; cdabbrev-current-window must not be NIL
- (set-buffer (if (eq cdabbrev-current-window t)
- (other-buffer)
- (window-buffer cdabbrev-current-window)))
- )
-
-
-(defun reset-cdabbrev-window (&optional initializep)
- "Resets the cdabbrev search to search for abbrev-string.
-initial-completions-tried is a list of downcased strings to ignore
-during the search."
- ;; Set the window
- (cond (initializep
- (setq cdabbrev-current-window (selected-window))
- )
- ((eq cdabbrev-current-window t)
- ;; Everything has failed
- (setq cdabbrev-current-window nil))
- (cdabbrev-current-window
- (setq cdabbrev-current-window (next-window cdabbrev-current-window))
- (if (eq cdabbrev-current-window (selected-window))
- ;; No more windows, try other buffer.
- (setq cdabbrev-current-window t)))
- )
- (when cdabbrev-current-window
- (save-excursion
- (set-cdabbrev-buffer)
- (setq cdabbrev-current-point (point)
- cdabbrev-start-point cdabbrev-current-point
- cdabbrev-stop-point
- (if *cdabbrev-radius*
- (max (point-min)
- (- cdabbrev-start-point *cdabbrev-radius*))
- (point-min))
- cdabbrev-wrapped-p nil)
- )))
-
-(defun next-cdabbrev ()
- "Return the next possible cdabbrev expansion or nil if there isn't one.
-reset-cdabbrev must've been called. This is sensitive to case-fold-search."
- ;; note that case-fold-search affects the behavior of this function
- ;; Bug: won't pick up an expansion that starts at the top of buffer
- (when cdabbrev-current-window
- (let (saved-point
- saved-syntax
- (expansion nil)
- downcase-expansion tried-list syntax saved-point-2)
- (save-excursion
- (unwind-protect
- (progn
- ;; Switch to current completion buffer
- (set-cdabbrev-buffer)
- ;; Save current buffer state
- (setq saved-point (point)
- saved-syntax (syntax-table))
- ;; Restore completion state
- (set-syntax-table cmpl-syntax-table)
- (goto-char cdabbrev-current-point)
- ;; Loop looking for completions
- (while
- ;; This code returns t if it should loop again
- (cond
- (;; search for the string
- (search-backward cdabbrev-abbrev-string cdabbrev-stop-point t)
- ;; return nil if the completion is valid
- (not
- (and
- ;; does it start with a separator char ?
- (or (= (setq syntax (char-syntax (preceding-char))) ? )
- (and (= syntax ?w)
- ;; symbol char to ignore at end. Are we at end ?
- (progn
- (setq saved-point-2 (point))
- (forward-word -1)
- (prog1
- (= (char-syntax (preceding-char)) ? )
- (goto-char saved-point-2)
- ))))
- ;; is the symbol long enough ?
- (setq expansion (symbol-under-point))
- ;; have we not tried this one before
- (progn
- ;; See if we've already used it
- (setq tried-list cdabbrev-completions-tried
- downcase-expansion (downcase expansion))
- (while (and tried-list
- (not (string-equal downcase-expansion
- (car tried-list))))
- ;; Already tried, don't choose this one
- (setq tried-list (cdr tried-list))
- )
- ;; at this point tried-list will be nil if this
- ;; expansion has not yet been tried
- (if tried-list
- (setq expansion nil)
- t)
- ))))
- ;; search failed
- (cdabbrev-wrapped-p
- ;; If already wrapped, then we've failed completely
- nil)
- (t
- ;; need to wrap
- (goto-char (setq cdabbrev-current-point
- (if *cdabbrev-radius*
- (min (point-max) (+ cdabbrev-start-point *cdabbrev-radius*))
- (point-max))))
-
- (setq cdabbrev-wrapped-p t))
- ))
- ;; end of while loop
- (cond (expansion
- ;; successful
- (setq cdabbrev-completions-tried
- (cons downcase-expansion cdabbrev-completions-tried)
- cdabbrev-current-point (point))))
- )
- (set-syntax-table saved-syntax)
- (goto-char saved-point)
- ))
- ;; If no expansion, go to next window
- (cond (expansion)
- (t (reset-cdabbrev-window)
- (next-cdabbrev)))
- )))
-
-;;; The following must be eval'd in the minibuffer ::
-;;; (reset-cdabbrev "cdat")
-;;; (next-cdabbrev) --> "cdat-simple"
-;;; (next-cdabbrev) --> "cdat-1-2-3-4"
-;;; (next-cdabbrev) --> "CDAT-UPCASE"
-;;; (next-cdabbrev) --> "cdat-wrapping"
-;;; (next-cdabbrev) --> "cdat_start_sym"
-;;; (next-cdabbrev) --> nil
-;;; (next-cdabbrev) --> nil
-;;; (next-cdabbrev) --> nil
-
-;;; _cdat_start_sym
-;;; cdat-wrapping
-
-
-;;;---------------------------------------------------------------------------
-;;; Completion Database
-;;;---------------------------------------------------------------------------
-
-;;; We use two storage modes for the two search types ::
-;;; 1) Prefix {cmpl-prefix-obarray} for looking up possible completions
-;;; Used by search-completion-next
-;;; the value of the symbol is nil or a cons of head and tail pointers
-;;; 2) Interning {cmpl-obarray} to see if it's in the database
-;;; Used by find-exact-completion, completion-in-database-p
-;;; The value of the symbol is the completion entry
-
-;;; bad things may happen if this length is changed due to the way
-;;; GNU implements obarrays
-(defconst cmpl-obarray-length 511)
-
-(defvar cmpl-prefix-obarray (make-vector cmpl-obarray-length 0)
- "An obarray used to store the downcased completion prefices.
-Each symbol is bound to a list of completion entries.")
-
-(defvar cmpl-obarray (make-vector cmpl-obarray-length 0)
- "An obarray used to store the downcased completions.
-Each symbol is bound to a single completion entry.")
-
-;;;-----------------------------------------------
-;;; Completion Entry Structure Definition
-;;;-----------------------------------------------
-
-;;; A completion entry is a LIST of string, prefix-symbol num-uses, and
-;;; last-use-time (the time the completion was last used)
-;;; last-use-time is T if the string should be kept permanently
-;;; num-uses is incremented everytime the completion is used.
-
-;;; We chose lists because (car foo) is faster than (aref foo 0) and the
-;;; creation time is about the same.
-
-;;; READER MACROS
-
-(defmacro completion-string (completion-entry)
- (list 'car completion-entry))
-
-(defmacro completion-num-uses (completion-entry)
- ;; "The number of times it has used. Used to decide whether to save
- ;; it."
- (list 'car (list 'cdr completion-entry)))
-
-(defmacro completion-last-use-time (completion-entry)
- ;; "The time it was last used. In hours since 1900. Used to decide
- ;; whether to save it. T if one should always save it."
- (list 'nth 2 completion-entry))
-
-(defmacro completion-source (completion-entry)
- (list 'nth 3 completion-entry))
-
-;;; WRITER MACROS
-(defmacro set-completion-string (completion-entry string)
- (list 'setcar completion-entry string))
-
-(defmacro set-completion-num-uses (completion-entry num-uses)
- (list 'setcar (list 'cdr completion-entry) num-uses))
-
-(defmacro set-completion-last-use-time (completion-entry last-use-time)
- (list 'setcar (list 'cdr (list 'cdr completion-entry)) last-use-time))
-
-;;; CONSTRUCTOR
-(defun make-completion (string)
- "Returns a list of a completion entry."
- (list (list string 0 nil current-completion-source)))
-
-;; Obsolete
-;;(defmacro cmpl-prefix-entry-symbol (completion-entry)
-;; (list 'car (list 'cdr completion-entry)))
-
-
-
-;;;-----------------------------------------------
-;;; Prefix symbol entry definition
-;;;-----------------------------------------------
-;;; A cons of (head . tail)
-
-;;; READER Macros
-
-(defmacro cmpl-prefix-entry-head (prefix-entry)
- (list 'car prefix-entry))
-
-(defmacro cmpl-prefix-entry-tail (prefix-entry)
- (list 'cdr prefix-entry))
-
-;;; WRITER Macros
-
-(defmacro set-cmpl-prefix-entry-head (prefix-entry new-head)
- (list 'setcar prefix-entry new-head))
-
-(defmacro set-cmpl-prefix-entry-tail (prefix-entry new-tail)
- (list 'setcdr prefix-entry new-tail))
-
-;;; Contructor
-
-(defun make-cmpl-prefix-entry (completion-entry-list)
- "Makes a new prefix entry containing only completion-entry."
- (cons completion-entry-list completion-entry-list))
-
-;;;-----------------------------------------------
-;;; Completion Database - Utilities
-;;;-----------------------------------------------
-
-(defun clear-all-completions ()
- "Initializes the completion storage. All existing completions are lost."
- (interactive)
- (setq cmpl-prefix-obarray (make-vector cmpl-obarray-length 0))
- (setq cmpl-obarray (make-vector cmpl-obarray-length 0))
- (cmpl-statistics-block
- (record-clear-all-completions))
- )
-
-(defun list-all-completions ()
- "Returns a list of all the known completion entries."
- (let ((return-completions nil))
- (mapatoms 'list-all-completions-1 cmpl-prefix-obarray)
- return-completions))
-
-(defun list-all-completions-1 (prefix-symbol)
- (if (boundp prefix-symbol)
- (setq return-completions
- (append (cmpl-prefix-entry-head (symbol-value prefix-symbol))
- return-completions))))
-
-(defun list-all-completions-by-hash-bucket ()
- "Returns a list of lists of all the known completion entries organized by
-hash bucket."
- (let ((return-completions nil))
- (mapatoms 'list-all-completions-by-hash-bucket-1 cmpl-prefix-obarray)
- return-completions))
-
-(defun list-all-completions-by-hash-bucket-1 (prefix-symbol)
- (if (boundp prefix-symbol)
- (setq return-completions
- (cons (cmpl-prefix-entry-head (symbol-value prefix-symbol))
- return-completions))))
-
-
-;;;-----------------------------------------------
-;;; Updating the database
-;;;-----------------------------------------------
-;;;
-;;; These are the internal functions used to update the datebase
-;;;
-;;;
-(defvar completion-to-accept nil)
- ;;"Set to a string that is pending its acceptance."
- ;; this checked by the top level reading functions
-
-(defvar cmpl-db-downcase-string nil)
- ;; "Setup by find-exact-completion, etc. The given string, downcased."
-(defvar cmpl-db-symbol nil)
- ;; "The interned symbol corresponding to cmpl-db-downcase-string.
- ;; Set up by cmpl-db-symbol."
-(defvar cmpl-db-prefix-symbol nil)
- ;; "The interned prefix symbol corresponding to cmpl-db-downcase-string."
-(defvar cmpl-db-entry nil)
-(defvar cmpl-db-debug-p nil
- "Set to T if you want to debug the database.")
-
-;;; READS
-(defun find-exact-completion (string)
- "Returns the completion entry for string or nil.
-Sets up cmpl-db-downcase-string and cmpl-db-symbol."
- (and (boundp (setq cmpl-db-symbol
- (intern (setq cmpl-db-downcase-string (downcase string))
- cmpl-obarray)))
- (symbol-value cmpl-db-symbol)
- ))
-
-(defun find-cmpl-prefix-entry (prefix-string)
- "Returns the prefix entry for string. Sets cmpl-db-prefix-symbol.
-Prefix-string must be exactly *completion-prefix-min-length* long
-and downcased. Sets up cmpl-db-prefix-symbol."
- (and (boundp (setq cmpl-db-prefix-symbol
- (intern prefix-string cmpl-prefix-obarray)))
- (symbol-value cmpl-db-prefix-symbol)))
-
-(defvar inside-locate-completion-entry nil)
-;; used to trap lossage in silent error correction
-
-(defun locate-completion-entry (completion-entry prefix-entry)
- "Locates the completion entry. Returns a pointer to the element
-before the completion entry or nil if the completion entry is at the head.
-Must be called after find-exact-completion."
- (let ((prefix-list (cmpl-prefix-entry-head prefix-entry))
- next-prefix-list
- )
- (cond
- ((not (eq (car prefix-list) completion-entry))
- ;; not already at head
- (while (and prefix-list
- (not (eq completion-entry
- (car (setq next-prefix-list (cdr prefix-list)))
- )))
- (setq prefix-list next-prefix-list))
- (cond (;; found
- prefix-list)
- ;; Didn't find it. Database is messed up.
- (cmpl-db-debug-p
- ;; not found, error if debug mode
- (error "Completion entry exists but not on prefix list - %s"
- string))
- (inside-locate-completion-entry
- ;; recursive error: really scrod
- (locate-completion-db-error))
- (t
- ;; Patch out
- (set cmpl-db-symbol nil)
- ;; Retry
- (locate-completion-entry-retry completion-entry)
- ))))))
-
-(defun locate-completion-entry-retry (old-entry)
- (let ((inside-locate-completion-entry t))
- (add-completion (completion-string old-entry)
- (completion-num-uses old-entry)
- (completion-last-use-time old-entry))
- (let ((cmpl-entry (find-exact-completion (completion-string old-entry)))
- (pref-entry
- (if cmpl-entry
- (find-cmpl-prefix-entry
- (substring cmpl-db-downcase-string
- 0 *completion-prefix-min-length*))))
- )
- (if (and cmpl-entry pref-entry)
- ;; try again
- (locate-completion-entry cmpl-entry pref-entry)
- ;; still losing
- (locate-completion-db-error))
- )))
-
-(defun locate-completion-db-error ()
- ;; recursive error: really scrod
- (error "Completion database corrupted. Try M-x clear-all-completions. Send bug report.")
- )
-
-;;; WRITES
-(defun add-completion-to-tail-if-new (string)
- "If the string is not in the database it is added to the end of the
-approppriate prefix list with num-uses = 0. The database is unchanged if it
-is there. string must be longer than *completion-prefix-min-length*.
-This must be very fast.
-Returns the completion entry."
- (or (find-exact-completion string)
- ;; not there
- (let (;; create an entry
- (entry (make-completion string))
- ;; setup the prefix
- (prefix-entry (find-cmpl-prefix-entry
- (substring cmpl-db-downcase-string 0
- (read-time-eval
- *completion-prefix-min-length*))))
- )
- ;; The next two forms should happen as a unit (atomically) but
- ;; no fatal errors should result if that is not the case.
- (cond (prefix-entry
- ;; These two should be atomic, but nothing fatal will happen
- ;; if they're not.
- (setcdr (cmpl-prefix-entry-tail prefix-entry) entry)
- (set-cmpl-prefix-entry-tail prefix-entry entry))
- (t
- (set cmpl-db-prefix-symbol (make-cmpl-prefix-entry entry))
- ))
- ;; statistics
- (cmpl-statistics-block
- (note-added-completion))
- ;; set symbol
- (set cmpl-db-symbol (car entry))
- )))
-
-(defun add-completion-to-head (string)
- "If the string is not in the database it is added to the head of the
-approppriate prefix list. Otherwise it is moved to the head of the list.
-string must be longer than *completion-prefix-min-length*.
-Updates the saved string with the supplied string.
-This must be very fast.
-Returns the completion entry."
- ;; Handle pending acceptance
- (if completion-to-accept (accept-completion))
- ;; test if already in database
- (if (setq cmpl-db-entry (find-exact-completion string))
- ;; found
- (let* ((prefix-entry (find-cmpl-prefix-entry
- (substring cmpl-db-downcase-string 0
- (read-time-eval
- *completion-prefix-min-length*))))
- (splice-ptr (locate-completion-entry cmpl-db-entry prefix-entry))
- (cmpl-ptr (cdr splice-ptr))
- )
- ;; update entry
- (set-completion-string cmpl-db-entry string)
- ;; move to head (if necessary)
- (cond (splice-ptr
- ;; These should all execute atomically but it is not fatal if
- ;; they don't.
- ;; splice it out
- (or (setcdr splice-ptr (cdr cmpl-ptr))
- ;; fix up tail if necessary
- (set-cmpl-prefix-entry-tail prefix-entry splice-ptr))
- ;; splice in at head
- (setcdr cmpl-ptr (cmpl-prefix-entry-head prefix-entry))
- (set-cmpl-prefix-entry-head prefix-entry cmpl-ptr)
- ))
- cmpl-db-entry)
- ;; not there
- (let (;; create an entry
- (entry (make-completion string))
- ;; setup the prefix
- (prefix-entry (find-cmpl-prefix-entry
- (substring cmpl-db-downcase-string 0
- (read-time-eval
- *completion-prefix-min-length*))))
- )
- (cond (prefix-entry
- ;; Splice in at head
- (setcdr entry (cmpl-prefix-entry-head prefix-entry))
- (set-cmpl-prefix-entry-head prefix-entry entry))
- (t
- ;; Start new prefix entry
- (set cmpl-db-prefix-symbol (make-cmpl-prefix-entry entry))
- ))
- ;; statistics
- (cmpl-statistics-block
- (note-added-completion))
- ;; Add it to the symbol
- (set cmpl-db-symbol (car entry))
- )))
-
-(defun delete-completion (string)
- "Deletes the completion from the database. string must be longer than
-*completion-prefix-min-length*."
- ;; Handle pending acceptance
- (if completion-to-accept (accept-completion))
- (if (setq cmpl-db-entry (find-exact-completion string))
- ;; found
- (let* ((prefix-entry (find-cmpl-prefix-entry
- (substring cmpl-db-downcase-string 0
- (read-time-eval
- *completion-prefix-min-length*))))
- (splice-ptr (locate-completion-entry cmpl-db-entry prefix-entry))
- )
- ;; delete symbol reference
- (set cmpl-db-symbol nil)
- ;; remove from prefix list
- (cond (splice-ptr
- ;; not at head
- (or (setcdr splice-ptr (cdr (cdr splice-ptr)))
- ;; fix up tail if necessary
- (set-cmpl-prefix-entry-tail prefix-entry splice-ptr))
- )
- (t
- ;; at head
- (or (set-cmpl-prefix-entry-head
- prefix-entry (cdr (cmpl-prefix-entry-head prefix-entry)))
- ;; List is now empty
- (set cmpl-db-prefix-symbol nil))
- ))
- (cmpl-statistics-block
- (note-completion-deleted))
- )
- (error "Unknown completion: %s. Couldn't delete it." string)
- ))
-
-;;; Tests --
-;;; - Add and Find -
-;;; (add-completion-to-head "banana") --> ("banana" 0 nil 0)
-;;; (find-exact-completion "banana") --> ("banana" 0 nil 0)
-;;; (find-exact-completion "bana") --> nil
-;;; (car (find-cmpl-prefix-entry "ban")) --> (("banana" ...))
-;;; (cdr (find-cmpl-prefix-entry "ban")) --> (("banana" ...))
-;;; (add-completion-to-head "banish") --> ("banish" 0 nil 0)
-;;; (find-exact-completion "banish") --> ("banish" 0 nil 0)
-;;; (car (find-cmpl-prefix-entry "ban")) --> (("banish" ...) ("banana" ...))
-;;; (cdr (find-cmpl-prefix-entry "ban")) --> (("banana" ...))
-;;; (add-completion-to-head "banana") --> ("banana" 0 nil 0)
-;;; (car (find-cmpl-prefix-entry "ban")) --> (("banana" ...) ("banish" ...))
-;;; (cdr (find-cmpl-prefix-entry "ban")) --> (("banish" ...))
-;;;
-;;; - Deleting -
-;;; (add-completion-to-head "banner") --> ("banner" 0 nil 0)
-;;; (delete-completion "banner")
-;;; (find-exact-completion "banner") --> nil
-;;; (car (find-cmpl-prefix-entry "ban")) --> (("banana" ...) ("banish" ...))
-;;; (cdr (find-cmpl-prefix-entry "ban")) --> (("banish" ...))
-;;; (add-completion-to-head "banner") --> ("banner" 0 nil 0)
-;;; (delete-completion "banana")
-;;; (car (find-cmpl-prefix-entry "ban")) --> (("banner" ...) ("banish" ...))
-;;; (cdr (find-cmpl-prefix-entry "ban")) --> (("banish" ...))
-;;; (delete-completion "banner")
-;;; (delete-completion "banish")
-;;; (find-cmpl-prefix-entry "ban") --> nil
-;;; (delete-completion "banner") --> error
-;;;
-;;; - Tail -
-;;; (add-completion-to-tail-if-new "banana") --> ("banana" 0 nil 0)
-;;; (car (find-cmpl-prefix-entry "ban")) --> (("banana" ...))
-;;; (cdr (find-cmpl-prefix-entry "ban")) --> (("banana" ...))
-;;; (add-completion-to-tail-if-new "banish") --> ("banish" 0 nil 0)
-;;; (car (find-cmpl-prefix-entry "ban")) -->(("banana" ...) ("banish" ...))
-;;; (cdr (find-cmpl-prefix-entry "ban")) -->(("banish" ...))
-;;;
-
-
-;;;---------------------------------------------------------------------------
-;;; Database Update :: Interface level routines
-;;;---------------------------------------------------------------------------
-;;;
-;;; These lie on top of the database ref. functions but below the standard
-;;; user interface level
-
-
-(defun interactive-completion-string-reader (prompt)
- (let* ((default (symbol-under-or-before-point))
- (new-prompt
- (if default
- (format "%s: (default: %s) " prompt default)
- (format "%s: " prompt))
- )
- (read (completing-read new-prompt cmpl-obarray))
- )
- (if (zerop (length read)) (setq read (or default "")))
- (list read)
- ))
-
-(defun check-completion-length (string)
- (if (< (length string) *completion-min-length*)
- (error "The string \"%s\" is too short to be saved as a completion."
- string)
- (list string)))
-
-(defun add-completion (string &optional num-uses last-use-time)
- "If the string is not there, it is added to the head of the completion list.
-Otherwise, it is moved to the head of the list.
-The completion is altered appropriately if num-uses and/or last-use-time is
-specified."
- (interactive (interactive-completion-string-reader "Completion to add"))
- (check-completion-length string)
- (let* ((current-completion-source (if (interactive-p)
- cmpl-source-interactive
- current-completion-source))
- (entry (add-completion-to-head string)))
-
- (if num-uses (set-completion-num-uses entry num-uses))
- (if last-use-time
- (set-completion-last-use-time entry last-use-time))
- ))
-
-(defun add-permanent-completion (string)
- "Adds string if it isn't already there and and makes it a permanent string."
- (interactive
- (interactive-completion-string-reader "Completion to add permanently"))
- (let ((current-completion-source (if (interactive-p)
- cmpl-source-interactive
- current-completion-source))
- )
- (add-completion string nil t)
- ))
-
-(defun kill-completion (string)
- (interactive (interactive-completion-string-reader "Completion to kill"))
- (check-completion-length string)
- (delete-completion string)
- )
-
-(defun accept-completion ()
- "Accepts the pending completion in completion-to-accept.
-This bumps num-uses. Called by add-completion-to-head and
-completion-search-reset."
- (let ((string completion-to-accept)
- ;; if this is added afresh here, then it must be a cdabbrev
- (current-completion-source cmpl-source-cdabbrev)
- entry
- )
- (setq completion-to-accept nil)
- (setq entry (add-completion-to-head string))
- (set-completion-num-uses entry (1+ (completion-num-uses entry)))
- (setq cmpl-completions-accepted-p t)
- ))
-
-(defun use-completion-under-point ()
- "Call this to add the completion symbol underneath the point into
-the completion buffer."
- (let ((string (and *completep* (symbol-under-point)))
- (current-completion-source cmpl-source-cursor-moves))
- (if string (add-completion-to-head string))))
-
-(defun use-completion-before-point ()
- "Call this to add the completion symbol before point into
-the completion buffer."
- (let ((string (and *completep* (symbol-before-point)))
- (current-completion-source cmpl-source-cursor-moves))
- (if string (add-completion-to-head string))))
-
-(defun use-completion-under-or-before-point ()
- "Call this to add the completion symbol before point into
-the completion buffer."
- (let ((string (and *completep* (symbol-under-or-before-point)))
- (current-completion-source cmpl-source-cursor-moves))
- (if string (add-completion-to-head string))))
-
-(defun use-completion-before-separator ()
- "Call this to add the completion symbol before point into
-the completion buffer. Completions added this way will automatically be
-saved if *separator-character-uses-completion-p* is non-nil."
- (let ((string (and *completep* (symbol-before-point)))
- (current-completion-source cmpl-source-separator)
- entry)
- (cmpl-statistics-block
- (note-separator-character string)
- )
- (cond (string
- (setq entry (add-completion-to-head string))
- (when (and *separator-character-uses-completion-p*
- (zerop (completion-num-uses entry)))
- (set-completion-num-uses entry 1)
- (setq cmpl-completions-accepted-p t)
- )))
- ))
-
-;;; Tests --
-;;; - Add and Find -
-;;; (add-completion "banana" 5 10)
-;;; (find-exact-completion "banana") --> ("banana" 5 10 0)
-;;; (add-completion "banana" 6)
-;;; (find-exact-completion "banana") --> ("banana" 6 10 0)
-;;; (add-completion "banish")
-;;; (car (find-cmpl-prefix-entry "ban")) --> (("banish" ...) ("banana" ...))
-;;;
-;;; - Accepting -
-;;; (setq completion-to-accept "banana")
-;;; (accept-completion)
-;;; (find-exact-completion "banana") --> ("banana" 7 10)
-;;; (car (find-cmpl-prefix-entry "ban")) --> (("banana" ...) ("banish" ...))
-;;; (setq completion-to-accept "banish")
-;;; (add-completion "banner")
-;;; (car (find-cmpl-prefix-entry "ban"))
-;;; --> (("banner" ...) ("banish" 1 ...) ("banana" 7 ...))
-;;;
-;;; - Deleting -
-;;; (kill-completion "banish")
-;;; (car (find-cmpl-prefix-entry "ban")) --> (("banner" ...) ("banana" ...))
-
-
-;;;---------------------------------------------------------------------------
-;;; Searching the database
-;;;---------------------------------------------------------------------------
-;;; Functions outside this block must call completion-search-reset followed
-;;; by calls to completion-search-next or completion-search-peek
-;;;
-
-;;; Status variables
-;; Commented out to improve loading speed
-(defvar cmpl-test-string "")
-;; "The current string used by completion-search-next."
-(defvar cmpl-test-regexp "")
-;; "The current regexp used by completion-search-next.
-;; (derived from cmpl-test-string)"
-(defvar cmpl-last-index 0)
-;; "The last index that completion-search-next was called with."
-(defvar cmpl-cdabbrev-reset-p nil)
-;; "Set to t when cdabbrevs have been reset."
-(defvar cmpl-next-possibilities nil)
-;; "A pointer to the element BEFORE the next set of possible completions.
-;; cadr of this is the cmpl-next-possibility"
-(defvar cmpl-starting-possibilities nil)
-;; "The initial list of starting possibilities."
-(defvar cmpl-next-possibility nil)
-;; "The cached next possibility."
-(defvar cmpl-tried-list nil)
-;; "A downcased list of all the completions we have tried."
-
-
-(defun completion-search-reset (string)
- "Given a string, sets up the get-completion and completion-search-next functions.
-String must be longer than *completion-prefix-min-length*."
- (if completion-to-accept (accept-completion))
- (setq cmpl-starting-possibilities
- (cmpl-prefix-entry-head
- (find-cmpl-prefix-entry (downcase (substring string 0 3))))
- cmpl-test-string string
- cmpl-test-regexp (concat (regexp-quote string) "."))
- (completion-search-reset-1)
- )
-
-(defun completion-search-reset-1 ()
- (setq cmpl-next-possibilities cmpl-starting-possibilities
- cmpl-next-possibility nil
- cmpl-cdabbrev-reset-p nil
- cmpl-last-index -1
- cmpl-tried-list nil
- ))
-
-(defun completion-search-next (index)
- "Returns the next completion entry. If index is out of sequence it resets
-and starts from the top. If there are no more entries it tries cdabbrev and
-returns only a string."
- (cond
- ((= index (setq cmpl-last-index (1+ cmpl-last-index)))
- (completion-search-peek t))
- ((minusp index)
- (completion-search-reset-1)
- (setq cmpl-last-index index)
- ;; reverse the possibilities list
- (setq cmpl-next-possibilities (reverse cmpl-starting-possibilities))
- ;; do a "normal" search
- (while (and (completion-search-peek nil)
- (minusp (setq index (1+ index))))
- (setq cmpl-next-possibility nil)
- )
- (cond ((not cmpl-next-possibilities))
- ;; If no more possibilities, leave it that way
- ((= -1 cmpl-last-index)
- ;; next completion is at index 0. reset next-possibility list
- ;; to start at beginning
- (setq cmpl-next-possibilities cmpl-starting-possibilities))
- (t
- ;; otherwise point to one before current
- (setq cmpl-next-possibilities
- (nthcdr (- (length cmpl-starting-possibilities)
- (length cmpl-next-possibilities))
- cmpl-starting-possibilities))
- )))
- (t
- ;; non-negative index, reset and search
- ;;(prin1 'reset)
- (completion-search-reset-1)
- (setq cmpl-last-index index)
- (while (and (completion-search-peek t)
- (not (minusp (setq index (1- index)))))
- (setq cmpl-next-possibility nil)
- ))
- )
- (prog1
- cmpl-next-possibility
- (setq cmpl-next-possibility nil)
- ))
-
-
-(defun completion-search-peek (use-cdabbrev)
- "Returns the next completion entry without actually moving the pointers.
-Calling this again or calling completion-search-next will result in the same
-string being returned. Depends on case-fold-search.
-If there are no more entries it tries cdabbrev and then returns only a string."
- (cond
- ;; return the cached value if we have it
- (cmpl-next-possibility)
- ((and cmpl-next-possibilities
- ;; still a few possibilities left
- (progn
- (while
- (and (not (eq 0 (string-match cmpl-test-regexp
- (completion-string (car cmpl-next-possibilities)))))
- (setq cmpl-next-possibilities (cdr cmpl-next-possibilities))
- ))
- cmpl-next-possibilities
- ))
- ;; successful match
- (setq cmpl-next-possibility (car cmpl-next-possibilities)
- cmpl-tried-list (cons (downcase (completion-string cmpl-next-possibility))
- cmpl-tried-list)
- cmpl-next-possibilities (cdr cmpl-next-possibilities)
- )
- cmpl-next-possibility)
- (use-cdabbrev
- ;; unsuccessful, use cdabbrev
- (cond ((not cmpl-cdabbrev-reset-p)
- (reset-cdabbrev cmpl-test-string cmpl-tried-list)
- (setq cmpl-cdabbrev-reset-p t)
- ))
- (setq cmpl-next-possibility (next-cdabbrev))
- )
- ;; Completely unsuccessful, return nil
- ))
-
-;;; Tests --
-;;; - Add and Find -
-;;; (add-completion "banana")
-;;; (completion-search-reset "ban")
-;;; (completion-search-next 0) --> "banana"
-;;;
-;;; - Discrimination -
-;;; (add-completion "cumberland")
-;;; (add-completion "cumberbund")
-;;; cumbering
-;;; (completion-search-reset "cumb")
-;;; (completion-search-peek t) --> "cumberbund"
-;;; (completion-search-next 0) --> "cumberbund"
-;;; (completion-search-peek t) --> "cumberland"
-;;; (completion-search-next 1) --> "cumberland"
-;;; (completion-search-peek nil) --> nil
-;;; (completion-search-next 2) --> "cumbering" {cdabbrev}
-;;; (completion-search-next 3) --> nil or "cumming"{depends on context}
-;;; (completion-search-next 1) --> "cumberland"
-;;; (completion-search-peek t) --> "cumbering" {cdabbrev}
-;;;
-;;; - Accepting -
-;;; (completion-search-next 1) --> "cumberland"
-;;; (setq completion-to-accept "cumberland")
-;;; (completion-search-reset "foo")
-;;; (completion-search-reset "cum")
-;;; (completion-search-next 0) --> "cumberland"
-;;;
-;;; - Deleting -
-;;; (kill-completion "cumberland")
-;;; cummings
-;;; (completion-search-reset "cum")
-;;; (completion-search-next 0) --> "cumberbund"
-;;; (completion-search-next 1) --> "cummings"
-;;;
-;;; - Ignoring Capitalization -
-;;; (completion-search-reset "CuMb")
-;;; (completion-search-next 0) --> "cumberbund"
-
-
-
-;;;-----------------------------------------------
-;;; COMPLETE
-;;;-----------------------------------------------
-
-(defun completion-mode ()
- "Toggles whether or not new words are added to the database."
- (interactive)
- (setq *completep* (not *completep*))
- (message "Completion mode is now %s." (if *completep* "ON" "OFF"))
- )
-
-(defvar cmpl-current-index 0)
-(defvar cmpl-original-string nil)
-(defvar cmpl-last-insert-location -1)
-(defvar cmpl-leave-point-at-start nil)
-
-(defun complete (&optional arg)
- "Inserts a completion at point.
-Point is left at end. Consective calls rotate through all possibilities.
-Prefix args ::
- control-u :: leave the point at the beginning of the completion rather
- than at the end.
- a number :: rotate through the possible completions by that amount
- `-' :: same as -1 (insert previous completion)
- {See the comments at the top of completion.el for more info.}
-"
- (interactive "*p")
- ;;; Set up variables
- (cond ((eq last-command this-command)
- ;; Undo last one
- (delete-region cmpl-last-insert-location (point))
- ;; get next completion
- (setq cmpl-current-index (+ cmpl-current-index (or arg 1)))
- )
- (t
- (if (not cmpl-initialized-p)
- (initialize-completions)) ;; make sure everything's loaded
- (cond ((consp current-prefix-arg) ;; control-u
- (setq arg 0)
- (setq cmpl-leave-point-at-start t)
- )
- (t
- (setq cmpl-leave-point-at-start nil)
- ))
- ;; get string
- (setq cmpl-original-string (symbol-before-point-for-complete))
- (cond ((not cmpl-original-string)
- (setq this-command 'failed-complete)
- (error "To complete, the point must be after a symbol at least %d character long."
- *completion-prefix-min-length*)))
- ;; get index
- (setq cmpl-current-index (if current-prefix-arg arg 0))
- ;; statistics
- (cmpl-statistics-block
- (note-complete-entered-afresh cmpl-original-string))
- ;; reset database
- (completion-search-reset cmpl-original-string)
- ;; erase what we've got
- (delete-region cmpl-symbol-start cmpl-symbol-end)
- ))
-
- ;; point is at the point to insert the new symbol
- ;; Get the next completion
- (let* ((print-status-p
- (and (>= (cmpl19-baud-rate) *print-next-completion-speed-threshold*)
- (not (minibuffer-window-selected-p))))
- (insert-point (point))
- (entry (completion-search-next cmpl-current-index))
- string
- )
- ;; entry is either a completion entry or a string (if cdabbrev)
-
- ;; If found, insert
- (cond (entry
- ;; Setup for proper case
- (setq string (if (stringp entry)
- entry (completion-string entry)))
- (setq string (cmpl-merge-string-cases
- string cmpl-original-string))
- ;; insert
- (insert string)
- ;; accept it
- (setq completion-to-accept string)
- ;; fixup and cache point
- (cond (cmpl-leave-point-at-start
- (setq cmpl-last-insert-location (point))
- (goto-char insert-point))
- (t;; point at end,
- (setq cmpl-last-insert-location insert-point))
- )
- ;; statistics
- (cmpl-statistics-block
- (note-complete-inserted entry cmpl-current-index))
- ;; Done ! cmpl-stat-complete-successful
- ;;display the next completion
- (cond
- ((and print-status-p
- ;; This updates the display and only prints if there
- ;; is no typeahead
- (cmpl19-sit-for 0)
- (setq entry
- (completion-search-peek
- *print-next-completion-does-cdabbrev-search-p*)))
- (setq string (if (stringp entry)
- entry (completion-string entry)))
- (setq string (cmpl-merge-string-cases
- string cmpl-original-string))
- (message "Next completion: %s" string)
- ))
- )
- (t;; none found, insert old
- (insert cmpl-original-string)
- ;; Don't accept completions
- (setq completion-to-accept nil)
- ;; print message
- (if (and print-status-p (cmpl19-sit-for 0))
- (message "No %scompletions."
- (if (eq this-command last-command) "more " "")))
- ;; statistics
- (cmpl-statistics-block
- (record-complete-failed cmpl-current-index))
- ;; Pretend that we were never here
- (setq this-command 'failed-complete)
- ))))
-
-;;;-----------------------------------------------
-;;; "Complete" Key Keybindings
-;;;-----------------------------------------------
-
-;;; Complete key definition
-;;; These define c-return and meta-return
-;;; In any case you really want to bind this to a single keystroke
-(if (fboundp 'key-for-others-chord)
- (condition-case e
- ;; this can fail if some of the prefix chars. are already used
- ;; as commands (this happens on wyses)
- (global-set-key (key-for-others-chord "return" '(control)) 'complete)
- (error)
- ))
-(if (fboundp 'gmacs-keycode)
- (global-set-key (gmacs-keycode "return" '(control)) 'complete)
- )
-(global-set-key "\M-\r" 'complete)
-
-;;; Tests -
-;;; (add-completion "cumberland")
-;;; (add-completion "cumberbund")
-;;; cum
-;;; Cumber
-;;; cumbering
-;;; cumb
-
-
-;;;---------------------------------------------------------------------------
-;;; Parsing definitions from files into the database
-;;;---------------------------------------------------------------------------
-
-;;;-----------------------------------------------
-;;; Top Level functions ::
-;;;-----------------------------------------------
-
-;;; User interface
-(defun add-completions-from-file (file)
- "Parses all the definition names from a Lisp mode file and adds them to the
-completion database."
- (interactive "fFile: ")
- (setq file (if (fboundp 'expand-file-name-defaulting)
- (expand-file-name-defaulting file)
- (expand-file-name file)))
- (let* ((buffer (get-file-buffer file))
- (buffer-already-there-p buffer)
- )
- (when (not buffer-already-there-p)
- (let ((*modes-for-completion-find-file-hook* nil))
- (setq buffer (find-file-noselect file))
- ))
- (unwind-protect
- (save-excursion
- (set-buffer buffer)
- (add-completions-from-buffer)
- )
- (when (not buffer-already-there-p)
- (kill-buffer buffer))
- )))
-
-(defun add-completions-from-buffer ()
- (interactive)
- (let ((current-completion-source cmpl-source-file-parsing)
- (start-num
- (cmpl-statistics-block
- (aref completion-add-count-vector cmpl-source-file-parsing)))
- mode
- )
- (cond ((memq major-mode '(emacs-lisp-mode lisp-mode))
- (add-completions-from-lisp-buffer)
- (setq mode 'lisp)
- )
- ((memq major-mode '(c-mode))
- (add-completions-from-c-buffer)
- (setq mode 'c)
- )
- (t
- (error "Do not know how to parse completions in %s buffers."
- major-mode)
- ))
- (cmpl-statistics-block
- (record-cmpl-parse-file
- mode (point-max)
- (- (aref completion-add-count-vector cmpl-source-file-parsing)
- start-num)))
- ))
-
-;;; Find file hook
-(defun cmpl-find-file-hook ()
- (cond (*completep*
- (cond ((and (memq major-mode '(emacs-lisp-mode lisp-mode))
- (memq 'lisp *modes-for-completion-find-file-hook*)
- )
- (add-completions-from-buffer))
- ((and (memq major-mode '(c-mode))
- (memq 'c *modes-for-completion-find-file-hook*)
- )
- (add-completions-from-buffer)
- )))
- ))
-
-(pushnew 'cmpl-find-file-hook find-file-hooks)
-
-;;;-----------------------------------------------
-;;; Tags Table Completions
-;;;-----------------------------------------------
-
-(defun add-completions-from-tags-table ()
- ;; Inspired by eero@media-lab.media.mit.edu
- "Add completions from the current tags-table-buffer."
- (interactive)
- (visit-tags-table-buffer) ;this will prompt if no tags-table
- (save-excursion
- (goto-char (point-min))
- (let (string)
- (condition-case e
- (while t
- (search-forward "\177")
- (backward-char 3)
- (and (setq string (symbol-under-point))
- (add-completion-to-tail-if-new string))
- (forward-char 3)
- )
- (search-failed)
- ))))
-
-
-;;;-----------------------------------------------
-;;; Lisp File completion parsing
-;;;-----------------------------------------------
-;;; This merely looks for phrases beginning with (def.... or
-;;; (package:def ... and takes the next word.
-;;;
-;;; We tried using forward-lines and explicit searches but the regexp technique
-;;; was faster. (About 100K characters per second)
-;;;
-(defconst *lisp-def-regexp*
- "\n(\\(\\w*:\\)?def\\(\\w\\|\\s_\\)*\\s +(*"
- "A regexp that searches for lisp definition form."
- )
-
-;;; Tests -
-;;; (and (string-match *lisp-def-regexp* "\n(defun foo") (match-end 0)) -> 8
-;;; (and (string-match *lisp-def-regexp* "\n(si:def foo") (match-end 0)) -> 9
-;;; (and (string-match *lisp-def-regexp* "\n(def-bar foo")(match-end 0)) -> 10
-;;; (and (string-match *lisp-def-regexp* "\n(defun (foo") (match-end 0)) -> 9
-
-(defun add-completions-from-lisp-buffer ()
- "Parses all the definition names from a Lisp mode buffer and adds them to
-the completion database."
- ;;; Benchmarks
- ;;; Sun-3/280 - 1500 to 3000 lines of lisp code per second
- (let (string)
- (save-excursion
- (goto-char (point-min))
- (condition-case e
- (while t
- (re-search-forward *lisp-def-regexp*)
- (and (setq string (symbol-under-point))
- (add-completion-to-tail-if-new string))
- )
- (search-failed)
- ))))
-
-
-;;;-----------------------------------------------
-;;; C file completion parsing
-;;;-----------------------------------------------
-;;; C :
-;;; Looks for #define or [<storage class>] [<type>] <name>{,<name>}
-;;; or structure, array or pointer defs.
-;;; It gets most of the definition names.
-;;;
-;;; As you might suspect by now, we use some symbol table hackery
-;;;
-;;; Symbol separator chars (have whitespace syntax) --> , ; * = (
-;;; Opening char --> [ {
-;;; Closing char --> ] }
-;;; openning and closing must be skipped over
-;;; Whitespace chars (have symbol syntax)
-;;; Everything else has word syntax
-
-(defun make-c-def-completion-syntax-table ()
- (let ((table (make-vector 256 0))
- (whitespace-chars '(? ?\n ?\t ?\f ?\v ?\r))
- ;; unforunately the ?( causes the parens to appear unbalanced
- (separator-chars '(?, ?* ?= ?\( ?\;
- ))
- )
- ;; default syntax is whitespace
- (dotimes (i 256)
- (modify-syntax-entry i "w" table))
- (dolist (char whitespace-chars)
- (modify-syntax-entry char "_" table))
- (dolist (char separator-chars)
- (modify-syntax-entry char " " table))
- (modify-syntax-entry ?\[ "(]" table)
- (modify-syntax-entry ?\{ "(}" table)
- (modify-syntax-entry ?\] ")[" table)
- (modify-syntax-entry ?\} "){" table)
- table))
-
-(defconst cmpl-c-def-syntax-table (make-c-def-completion-syntax-table))
-
-;;; Regexps
-(defconst *c-def-regexp*
- ;; This stops on lines with possible definitions
- "\n[_a-zA-Z#]"
- ;; This stops after the symbol to add.
- ;;"\n\\(#define\\s +.\\|\\(\\(\\w\\|\\s_\\)+\\b\\s *\\)+[(;,[*{=]\\)"
- ;; This stops before the symbol to add. {Test cases in parens. below}
- ;;"\n\\(\\(\\w\\|\\s_\\)+\\s *(\\|\\(\\(#define\\|auto\\|extern\\|register\\|static\\|int\\|long\\|short\\|unsigned\\|char\\|void\\|float\\|double\\|enum\\|struct\\|union\\|typedef\\)\\s +\\)+\\)"
- ;; this simple version picks up too much extraneous stuff
- ;; "\n\\(\\w\\|\\s_\\|#\\)\\B"
- "A regexp that searches for a definition form."
- )
-;
-;(defconst *c-cont-regexp*
-; "\\(\\w\\|\\s_\\)+\\b\\s *\\({\\|\\(\\[[0-9\t ]*\\]\\s *\\)*,\\(*\\|\\s \\)*\\b\\)"
-; "This regexp should be used in a looking-at to parse for lists of variables.")
-;
-;(defconst *c-struct-regexp*
-; "\\(*\\|\\s \\)*\\b"
-; "This regexp should be used to test whether a symbol follows a structure definition.")
-
-;(defun test-c-def-regexp (regexp string)
-; (and (eq 0 (string-match regexp string)) (match-end 0))
-; )
-
-;;; Tests -
-;;; (test-c-def-regexp *c-def-regexp* "\n#define foo") -> 10 (9)
-;;; (test-c-def-regexp *c-def-regexp* "\nfoo (x, y) {") -> 6 (6)
-;;; (test-c-def-regexp *c-def-regexp* "\nint foo (x, y)") -> 10 (5)
-;;; (test-c-def-regexp *c-def-regexp* "\n int foo (x, y)") -> nil
-;;; (test-c-def-regexp *c-cont-regexp* "oo, bar") -> 4
-;;; (test-c-def-regexp *c-cont-regexp* "oo, *bar") -> 5
-;;; (test-c-def-regexp *c-cont-regexp* "a [5][6], bar") -> 10
-;;; (test-c-def-regexp *c-cont-regexp* "oo(x,y)") -> nil
-;;; (test-c-def-regexp *c-cont-regexp* "a [6] ,\t bar") -> 9
-;;; (test-c-def-regexp *c-cont-regexp* "oo {trout =1} my_carp;") -> 14
-;;; (test-c-def-regexp *c-cont-regexp* "truct_p complex foon") -> nil
-
-(defun add-completions-from-c-buffer ()
- "Parses all the definition names from a C mode buffer and adds them to the
-completion database."
- ;; Benchmark --
- ;; Sun 3/280-- 1250 lines/sec.
-
- (let (string next-point char
- (saved-syntax (syntax-table))
- )
- (save-excursion
- (goto-char (point-min))
- (catch 'finish-add-completions
- (unwind-protect
- (while t
- ;; we loop here only when scan-sexps fails
- ;; (i.e. unbalance exps.)
- (set-syntax-table cmpl-c-def-syntax-table)
- (condition-case e
- (while t
- (re-search-forward *c-def-regexp*)
- (cond
- ((= (preceding-char) ?#)
- ;; preprocessor macro, see if it's one we handle
- (setq string (buffer-substring (point) (+ (point) 6)))
- (cond ((or (string-equal string "define")
- (string-equal string "ifdef ")
- )
- ;; skip forward over definition symbol
- ;; and add it to database
- (and (forward-word 2)
- (setq string (symbol-before-point))
- ;;(push string foo)
- (add-completion-to-tail-if-new string)
- ))))
- (t
- ;; C definition
- (setq next-point (point))
- (while (and
- next-point
- ;; scan to next separator char.
- (setq next-point (scan-sexps next-point 1))
- )
- ;; position the point on the word we want to add
- (goto-char next-point)
- (while (= (setq char (following-char)) ?*)
- ;; handle pointer ref
- ;; move to next separator char.
- (goto-char
- (setq next-point (scan-sexps (point) 1)))
- )
- (forward-word -1)
- ;; add to database
- (if (setq string (symbol-under-point))
- ;; (push string foo)
- (add-completion-to-tail-if-new string)
- ;; Local TMC hack (useful for parsing paris.h)
- (if (and (looking-at "_AP") ;; "ansi prototype"
- (progn
- (forward-word -1)
- (setq string
- (symbol-under-point))
- ))
- (add-completion-to-tail-if-new string)
- )
- )
- ;; go to next
- (goto-char next-point)
- ;; (push (format "%c" (following-char)) foo)
- (if (= (char-syntax char) ?\()
- ;; if on an opening delimiter, go to end
- (while (= (char-syntax char) ?\()
- (setq next-point (scan-sexps next-point 1)
- char (char-after next-point))
- )
- (or (= char ?,)
- ;; Current char is an end char.
- (setq next-point nil)
- ))
- ))))
- (search-failed ;;done
- (throw 'finish-add-completions t)
- )
- (error
- ;; Check for failure in scan-sexps
- (if (or (string-equal (second e)
- "Containing expression ends prematurely")
- (string-equal (second e) "Unbalanced parentheses"))
- ;; unbalanced paren., keep going
- ;;(ding)
- (forward-line 1)
- (message "Error parsing C buffer for completions. Please bug report.")
- (throw 'finish-add-completions t)
- ))
- ))
- (set-syntax-table saved-syntax)
- )))))
-
-
-;;;---------------------------------------------------------------------------
-;;; Init files
-;;;---------------------------------------------------------------------------
-
-(defun kill-emacs-save-completions ()
- "The version of save-completions-to-file called at kill-emacs
-time."
- (when (and *save-completions-p* *completep* cmpl-initialized-p)
- (cond
- ((not cmpl-completions-accepted-p)
- (message "Completions database has not changed - not writing."))
- (t
- (save-completions-to-file)
- ))
- ))
-
-(defconst saved-cmpl-file-header
- ";;; Completion Initialization file.
-;;; Version = %s
-;;; Format is (<string> . <last-use-time>)
-;;; <string> is the completion
-;;; <last-use-time> is the time the completion was last used
-;;; If it is t, the completion will never be pruned from the file.
-;;; Otherwise it is in hours since 1900.
-\n")
-
-(defun completion-backup-filename (filename)
- (concat filename ".BAK"))
-
-(defun save-completions-to-file (&optional filename)
- "Saves a completion init file. If file is not specified,
- then *saved-completions-filename* is used."
- (interactive)
- (setq filename (expand-file-name (or filename *saved-completions-filename*)))
- (when (file-writable-p filename)
- (if (not cmpl-initialized-p)
- (initialize-completions));; make sure everything's loaded
- (message "Saving completions to file %s" filename)
-
- (let* ((trim-versions-without-asking t)
- (kept-old-versions 0)
- (kept-new-versions *completion-file-versions-kept*)
- last-use-time
- (current-time (cmpl-hours-since-1900))
- (total-in-db 0)
- (total-perm 0)
- (total-saved 0)
- (backup-filename (completion-backup-filename filename))
- )
-
- (save-excursion
- (get-buffer-create " *completion-save-buffer*")
- (set-buffer " *completion-save-buffer*")
- (setq buffer-file-name filename)
-
- (when (not (verify-visited-file-modtime (current-buffer)))
- ;; file has changed on disk. Bring us up-to-date
- (message "Completion file has changed. Merging. . .")
- (load-completions-from-file filename t)
- (message "Merging finished. Saving completions to file %s" filename)
- )
-
- ;; prepare the buffer to be modified
- (clear-visited-file-modtime)
- (erase-buffer)
- ;; (/ 1 0)
- (insert (format saved-cmpl-file-header *completion-version*))
- (dolist (completion (list-all-completions))
- (setq total-in-db (1+ total-in-db))
- (setq last-use-time (completion-last-use-time completion))
- ;; Update num uses and maybe write completion to a file
- (cond ((or;; Write to file if
- ;; permanent
- (and (eq last-use-time t)
- (setq total-perm (1+ total-perm)))
- ;; or if
- (if (plusp (completion-num-uses completion))
- ;; it's been used
- (setq last-use-time current-time)
- ;; or it was saved before and
- (and last-use-time
- ;; *saved-completion-retention-time* is nil
- (or (not *saved-completion-retention-time*)
- ;; or time since last use is < ...retention-time*
- (< (- current-time last-use-time)
- *saved-completion-retention-time*))
- )))
- ;; write to file
- (setq total-saved (1+ total-saved))
- (insert (prin1-to-string (cons (completion-string completion)
- last-use-time)) "\n")
- )))
-
- ;; write the buffer
- (condition-case e
- (let ((file-exists-p (file-exists-p filename)))
- (when file-exists-p
- ;; If file exists . . .
- ;; Save a backup(so GNU doesn't screw us when we're out of disk)
- ;; (GNU leaves a 0 length file if it gets a disk full error!)
-
- ;; If backup doesn't exit, Rename current to backup
- ;; {If backup exists the primary file is probably messed up}
- (unless (file-exists-p backup-filename)
- (rename-file filename backup-filename))
- ;; Copy the backup back to the current name
- ;; (so versioning works)
- (copy-file backup-filename filename t)
- )
- ;; Save it
- (save-buffer)
- (when file-exists-p
- ;; If successful, remove backup
- (delete-file backup-filename)
- ))
- (error
- (set-buffer-modified-p nil)
- (message "Couldn't save completion file %s." filename)
- ))
- ;; Reset accepted-p flag
- (setq cmpl-completions-accepted-p nil)
- )
- (cmpl-statistics-block
- (record-save-completions total-in-db total-perm total-saved))
- )))
-
-(defun autosave-completions ()
- (when (and *save-completions-p* *completep* cmpl-initialized-p
- *completion-auto-save-period*
- (> cmpl-emacs-idle-time *completion-auto-save-period*)
- cmpl-completions-accepted-p)
- (save-completions-to-file)
- ))
-
-(pushnew 'autosave-completions cmpl-emacs-idle-time-hooks)
-
-(defun load-completions-from-file (&optional filename no-message-p)
- "loads a completion init file. If file is not specified,
- then *saved-completions-filename* is used"
- (interactive)
- (setq filename (expand-file-name (or filename *saved-completions-filename*)))
- (let* ((backup-filename (completion-backup-filename filename))
- (backup-readable-p (file-readable-p backup-filename))
- )
- (when backup-readable-p (setq filename backup-filename))
- (when (file-readable-p filename)
- (if (not no-message-p)
- (message "Loading completions from %sfile %s . . ."
- (if backup-readable-p "backup " "") filename))
- (save-excursion
- (get-buffer-create " *completion-save-buffer*")
- (set-buffer " *completion-save-buffer*")
- (setq buffer-file-name filename)
- ;; prepare the buffer to be modified
- (clear-visited-file-modtime)
- (erase-buffer)
-
- (let ((insert-okay-p nil)
- (buffer (current-buffer))
- (current-time (cmpl-hours-since-1900))
- string num-uses entry last-use-time
- cmpl-entry cmpl-last-use-time
- (current-completion-source cmpl-source-init-file)
- (start-num
- (cmpl-statistics-block
- (aref completion-add-count-vector cmpl-source-file-parsing)))
- (total-in-file 0) (total-perm 0)
- )
- ;; insert the file into a buffer
- (condition-case e
- (progn (insert-file-contents filename t)
- (setq insert-okay-p t))
-
- (file-error
- (message "File error trying to load completion file %s."
- filename)))
- ;; parse it
- (when insert-okay-p
- (goto-char (point-min))
-
- (condition-case e
- (while t
- (setq entry (read buffer))
- (setq total-in-file (1+ total-in-file))
- (cond
- ((and (consp entry)
- (stringp (setq string (car entry)))
- (cond
- ((eq (setq last-use-time (cdr entry)) 'T)
- ;; handle case sensitivity
- (setq total-perm (1+ total-perm))
- (setq last-use-time t))
- ((eq last-use-time t)
- (setq total-perm (1+ total-perm)))
- ((integerp last-use-time))
- ))
- ;; Valid entry
- ;; add it in
- (setq cmpl-last-use-time
- (completion-last-use-time
- (setq cmpl-entry
- (add-completion-to-tail-if-new string))
- ))
- (if (or (eq last-use-time t)
- (and (> last-use-time 1000);;backcompatibility
- (not (eq cmpl-last-use-time t))
- (or (not cmpl-last-use-time)
- ;; more recent
- (> last-use-time cmpl-last-use-time))
- ))
- ;; update last-use-time
- (set-completion-last-use-time cmpl-entry last-use-time)
- ))
- (t
- ;; Bad format
- (message "Error: invalid saved completion - %s"
- (prin1-to-string entry))
- ;; try to get back in sync
- (search-forward "\n(")
- )))
- (search-failed
- (message "End of file while reading completions.")
- )
- (end-of-file
- (if (= (point) (point-max))
- (if (not no-message-p)
- (message "Loading completions from file %s . . . Done."
- filename))
- (message "End of file while reading completions.")
- ))
- ))
-
- (cmpl-statistics-block
- (record-load-completions
- total-in-file total-perm
- (- (aref completion-add-count-vector cmpl-source-init-file)
- start-num)))
-
- )))))
-
-(defun initialize-completions ()
- "Loads the default completions file and sets up so that exiting emacs will
-automatically save the file."
- (interactive)
- (cond ((not cmpl-initialized-p)
- (load-completions-from-file)
- ))
- (init-cmpl-emacs-idle-process)
- (setq cmpl-initialized-p t)
- )
-
-
-;;;-----------------------------------------------
-;;; Kill EMACS patch
-;;;-----------------------------------------------
-
-(completion-advise kill-emacs :before
- ;; | All completion code should go in here
- ;;\ /
- (kill-emacs-save-completions)
- ;;/ \
- ;; | All completion code should go in here
- (cmpl-statistics-block
- (record-cmpl-kill-emacs))
- )
-
-
-;;;-----------------------------------------------
-;;; Kill region patch
-;;;-----------------------------------------------
-
-;;; Patched to remove the most recent completion
-(defvar $$$cmpl-old-kill-region (symbol-function 'kill-region))
-
-(defun kill-region (&optional beg end)
- "Kill between point and mark.
-The text is deleted but saved in the kill ring.
-The command \\[yank] can retrieve it from there.
-/(If you want to kill and then yank immediately, use \\[copy-region-as-kill].)
-
-This is the primitive for programs to kill text (as opposed to deleting it).
-Supply two arguments, character numbers indicating the stretch of text
- to be killed.
-Any command that calls this function is a \"kill command\".
-If the previous command was also a kill command,
-the text killed this time appends to the text killed last time
-to make one entry in the kill ring.
-Patched to remove the most recent completion."
- (interactive "*")
- (cond ((and (eq last-command 'complete) (eq last-command-char ?\C-w))
- (delete-region (point) cmpl-last-insert-location)
- (insert cmpl-original-string)
- (setq completion-to-accept nil)
- (cmpl-statistics-block
- (record-complete-failed))
- )
- (t
- (if (not beg)
- (setq beg (min (point) (mark))
- end (max (point) (mark)))
- )
- (funcall $$$cmpl-old-kill-region beg end)
- )))
-
-;;;-----------------------------------------------
-;;; Patches to self-insert-command.
-;;;-----------------------------------------------
-
-;;; Need 2 versions: generic seperator chars. and space (to get auto fill
-;;; to work)
-
-;;; All common separators (eg. space "(" ")" """) characters go through a
-;;; function to add new words to the list of words to complete from:
-;;; COMPLETION-SEPARATOR-SELF-INSERT-COMMAND (arg).
-;;; If the character before this was an alpha-numeric then this adds the
-;;; symbol befoe point to the completion list (using ADD-COMPLETION).
-
-(defun completion-separator-self-insert-command (arg)
- (interactive "p")
- (use-completion-before-separator)
- (self-insert-command arg)
- )
-
-(defun completion-separator-self-insert-autofilling (arg)
- (interactive "p")
- (use-completion-before-separator)
- (self-insert-command arg)
- (and (> (current-column) fill-column)
- auto-fill-hook
- (funcall auto-fill-hook))
- )
-
-;;;-----------------------------------------------
-;;; Wrapping Macro
-;;;-----------------------------------------------
-
-;;; Note that because of the way byte compiling works, none of
-;;; the functions defined with this macro get byte compiled.
-
-(defmacro def-completion-wrapper (function-name type &optional new-name)
- "Add a call to update the completion database before the function is
-executed. TYPE is the type of the wrapper to be added. Can be :before or
-:under."
- (completion-advise-1
- function-name ':before
- (ecase type
- (:before '((use-completion-before-point)))
- (:separator '((use-completion-before-separator)))
- (:under '((use-completion-under-point)))
- (:under-or-before
- '((use-completion-under-or-before-point)))
- (:minibuffer-separator
- '((let ((cmpl-syntax-table cmpl-standard-syntax-table))
- (use-completion-before-separator))))
- )
- new-name
- ))
-
-;;;(defun foo (x y z) (+ x y z))
-;;;foo
-;;;(macroexpand '(def-completion-wrapper foo :under))
-;;;(progn (defvar $$$cmpl-foo (symbol-function (quote foo))) (defun foo (&rest arglist) (progn (use-completion-under-point)) (cmpl-apply-as-top-level $$$cmpl-foo arglist)))
-;;;(defun bar (x y z) "Documentation" (+ x y z))
-;;;bar
-;;;(macroexpand '(def-completion-wrapper bar :under))
-;;;(progn (defvar $$$cmpl-bar (symbol-function (quote bar))) (defun bar (&rest arglist) "Documentation" (progn (use-completion-under-point)) (cmpl-apply-as-top-level $$$cmpl-bar arglist)))
-;;;(defun quuz (x &optional y z) "Documentation" (interactive "P") (+ x y z))
-;;;quuz
-;;;(macroexpand '(def-completion-wrapper quuz :before))
-;;;(progn (defvar $$$cmpl-quuz (symbol-function (quote quuz))) (defun quuz (&rest arglist) "Documentation" (interactive) (progn (use-completion-before-point)) (cmpl-apply-as-top-level $$$cmpl-quuz arglist)))
-
-
-;;;---------------------------------------------------------------------------
-;;; Patches to standard keymaps insert completions
-;;;---------------------------------------------------------------------------
-
-;;;-----------------------------------------------
-;;; Separators
-;;;-----------------------------------------------
-;;; We've used the completion syntax table given as a guide.
-;;;
-;;; Global separator chars.
-;;; We left out <tab> because there are too many special cases for it. Also,
-;;; in normal coding it's rarely typed after a word.
-(global-set-key " " 'completion-separator-self-insert-autofilling)
-(global-set-key "!" 'completion-separator-self-insert-command)
-(global-set-key "%" 'completion-separator-self-insert-command)
-(global-set-key "^" 'completion-separator-self-insert-command)
-(global-set-key "&" 'completion-separator-self-insert-command)
-(global-set-key "(" 'completion-separator-self-insert-command)
-(global-set-key ")" 'completion-separator-self-insert-command)
-(global-set-key "=" 'completion-separator-self-insert-command)
-(global-set-key "`" 'completion-separator-self-insert-command)
-(global-set-key "|" 'completion-separator-self-insert-command)
-(global-set-key "{" 'completion-separator-self-insert-command)
-(global-set-key "}" 'completion-separator-self-insert-command)
-(global-set-key "[" 'completion-separator-self-insert-command)
-(global-set-key "]" 'completion-separator-self-insert-command)
-(global-set-key ";" 'completion-separator-self-insert-command)
-(global-set-key "\"" 'completion-separator-self-insert-command)
-(global-set-key "'" 'completion-separator-self-insert-command)
-(global-set-key "#" 'completion-separator-self-insert-command)
-(global-set-key "," 'completion-separator-self-insert-command)
-(global-set-key "?" 'completion-separator-self-insert-command)
-
-;;; We include period and colon even though they are symbol chars because :
-;;; - in text we want to pick up the last word in a sentence.
-;;; - in C pointer refs. we want to pick up the first symbol
-;;; - it won't make a difference for lisp mode (package names are short)
-(global-set-key "." 'completion-separator-self-insert-command)
-(global-set-key ":" 'completion-separator-self-insert-command)
-
-;;; Lisp Mode diffs
-(define-key lisp-mode-map "!" 'self-insert-command)
-(define-key lisp-mode-map "&" 'self-insert-command)
-(define-key lisp-mode-map "%" 'self-insert-command)
-(define-key lisp-mode-map "?" 'self-insert-command)
-(define-key lisp-mode-map "=" 'self-insert-command)
-(define-key lisp-mode-map "^" 'self-insert-command)
-
-;;; C mode diffs.
-(def-completion-wrapper electric-c-semi :separator)
-(define-key c-mode-map "+" 'completion-separator-self-insert-command)
-(define-key c-mode-map "*" 'completion-separator-self-insert-command)
-(define-key c-mode-map "/" 'completion-separator-self-insert-command)
-
-;;; FORTRAN mode diffs. (these are defined when fortran is called)
-(defun completion-setup-fortran-mode ()
- (define-key fortran-mode-map "+" 'completion-separator-self-insert-command)
- (define-key fortran-mode-map "-" 'completion-separator-self-insert-command)
- (define-key fortran-mode-map "*" 'completion-separator-self-insert-command)
- (define-key fortran-mode-map "/" 'completion-separator-self-insert-command)
- )
-
-;;;-----------------------------------------------
-;;; End of line chars.
-;;;-----------------------------------------------
-(def-completion-wrapper newline :separator)
-(def-completion-wrapper newline-and-indent :separator)
-(if (function-defined-and-loaded 'shell-send-input)
- (def-completion-wrapper shell-send-input :separator))
-(def-completion-wrapper exit-minibuffer :minibuffer-separator)
-(def-completion-wrapper eval-print-last-sexp :separator)
-(def-completion-wrapper eval-last-sexp :separator)
-;;(def-completion-wrapper minibuffer-complete-and-exit :minibuffer)
-
-;;;-----------------------------------------------
-;;; Cursor movement
-;;;-----------------------------------------------
-
-(def-completion-wrapper next-line :under-or-before)
-(def-completion-wrapper previous-line :under-or-before)
-(def-completion-wrapper beginning-of-buffer :under-or-before)
-(def-completion-wrapper end-of-buffer :under-or-before)
-
-;; we patch these explicitly so they byte compile and so we don't have to
-;; patch the faster underlying function.
-
-(defun cmpl-beginning-of-line (&optional n)
- "Move point to beginning of current line.\n\
-With argument ARG not nil or 1, move forward ARG - 1 lines first.\n\
-If scan reaches end of buffer, stop there without error."
- (interactive "p")
- (use-completion-under-or-before-point)
- (beginning-of-line n)
- )
-
-(defun cmpl-end-of-line (&optional n)
- "Move point to end of current line.\n\
-With argument ARG not nil or 1, move forward ARG - 1 lines first.\n\
-If scan reaches end of buffer, stop there without error."
- (interactive "p")
- (use-completion-under-or-before-point)
- (end-of-line n)
- )
-
-(defun cmpl-forward-char (n)
- "Move point right ARG characters (left if ARG negative).\n\
-On reaching end of buffer, stop and signal error."
- (interactive "p")
- (use-completion-under-or-before-point)
- (forward-char n)
- )
-(defun cmpl-backward-char (n)
- "Move point left ARG characters (right if ARG negative).\n\
-On attempt to pass beginning or end of buffer, stop and signal error."
- (interactive "p")
- (use-completion-under-point)
- (if (eq last-command 'complete)
- ;; probably a failed completion if you have to back up
- (cmpl-statistics-block (record-complete-failed)))
- (backward-char n)
- )
-
-(defun cmpl-forward-word (n)
- "Move point forward ARG words (backward if ARG is negative).\n\
-Normally returns t.\n\
-If an edge of the buffer is reached, point is left there\n\
-and nil is returned."
- (interactive "p")
- (use-completion-under-or-before-point)
- (forward-word n)
- )
-(defun cmpl-backward-word (n)
- "Move backward until encountering the end of a word.
-With argument, do this that many times.
-In programs, it is faster to call forward-word with negative arg."
- (interactive "p")
- (use-completion-under-point)
- (if (eq last-command 'complete)
- ;; probably a failed completion if you have to back up
- (cmpl-statistics-block (record-complete-failed)))
- (forward-word (- n))
- )
-
-(defun cmpl-forward-sexp (n)
- "Move forward across one balanced expression.
-With argument, do this that many times."
- (interactive "p")
- (use-completion-under-or-before-point)
- (forward-sexp n)
- )
-(defun cmpl-backward-sexp (n)
- "Move backward across one balanced expression.
-With argument, do this that many times."
- (interactive "p")
- (use-completion-under-point)
- (if (eq last-command 'complete)
- ;; probably a failed completion if you have to back up
- (cmpl-statistics-block (record-complete-failed)))
- (backward-sexp n)
- )
-
-(defun cmpl-delete-backward-char (n killflag)
- "Delete the previous ARG characters (following, with negative ARG).\n\
-Optional second arg KILLFLAG non-nil means kill instead (save in kill ring).\n\
-Interactively, ARG is the prefix arg, and KILLFLAG is set if\n\
-ARG was explicitly specified."
- (interactive "p\nP")
- (if (eq last-command 'complete)
- ;; probably a failed completion if you have to back up
- (cmpl-statistics-block (record-complete-failed)))
- (delete-backward-char n killflag)
- )
-
-(defvar $$$cmpl-old-backward-delete-char-untabify
- (symbol-function 'backward-delete-char-untabify))
-
-(defun backward-delete-char-untabify (arg &optional killp)
- "Delete characters backward, changing tabs into spaces.
-Delete ARG chars, and kill (save in kill ring) if KILLP is non-nil.
-Interactively, ARG is the prefix arg (default 1)
-and KILLP is t if prefix arg is was specified."
- (interactive "*p\nP")
- (if (eq last-command 'complete)
- ;; probably a failed completion if you have to back up
- (cmpl-statistics-block (record-complete-failed)))
- (funcall $$$cmpl-old-backward-delete-char-untabify arg killp)
- )
-
-
-(global-set-key "\C-?" 'cmpl-delete-backward-char)
-(global-set-key "\M-\C-F" 'cmpl-forward-sexp)
-(global-set-key "\M-\C-B" 'cmpl-backward-sexp)
-(global-set-key "\M-F" 'cmpl-forward-word)
-(global-set-key "\M-B" 'cmpl-backward-word)
-(global-set-key "\C-F" 'cmpl-forward-char)
-(global-set-key "\C-B" 'cmpl-backward-char)
-(global-set-key "\C-A" 'cmpl-beginning-of-line)
-(global-set-key "\C-E" 'cmpl-end-of-line)
-
-;;;-----------------------------------------------
-;;; Misc.
-;;;-----------------------------------------------
-
-(def-completion-wrapper electric-buffer-list :under-or-before)
-(def-completion-wrapper list-buffers :under-or-before)
-(def-completion-wrapper scroll-up :under-or-before)
-(def-completion-wrapper scroll-down :under-or-before)
-(def-completion-wrapper execute-extended-command
- :under-or-before)
-(def-completion-wrapper other-window :under-or-before)
-
-;;;-----------------------------------------------
-;;; Local Thinking Machines stuff
-;;;-----------------------------------------------
-
-(if (fboundp 'up-ten-lines)
- (def-completion-wrapper up-ten-lines :under-or-before))
-(if (fboundp 'down-ten-lines)
- (def-completion-wrapper down-ten-lines :under-or-before))
-(if (fboundp 'tmc-scroll-up)
- (def-completion-wrapper tmc-scroll-up :under-or-before))
-(if (fboundp 'tmc-scroll-down)
- (def-completion-wrapper tmc-scroll-down :under-or-before))
-(if (fboundp 'execute-extended-command-and-check-for-bindings)
- (def-completion-wrapper execute-extended-command-and-check-for-bindings
- :under-or-before))
-
-;;; Tests --
-;;; foobarbiz
-;;; foobar
-;;; fooquux
-;;; fooper
-
-(cmpl-statistics-block
- (record-completion-file-loaded))
diff --git a/lisp/dabbrev.el b/lisp/dabbrev.el
new file mode 100644
index 00000000000..edd6fa75331
--- /dev/null
+++ b/lisp/dabbrev.el
@@ -0,0 +1,221 @@
+;; Dynamic abbreviation package for GNU Emacs.
+;; Copyright (C) 1985, 1986 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 1, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+; DABBREVS - "Dynamic abbreviations" hack, originally written by Don Morrison
+; for Twenex Emacs. Converted to mlisp by Russ Fish. Supports the table
+; feature to avoid hitting the same expansion on re-expand, and the search
+; size limit variable. Bugs fixed from the Twenex version are flagged by
+; comments starting with ;;; .
+;
+; converted to elisp by Spencer Thomas.
+; Thoroughly cleaned up by Richard Stallman.
+;
+; If anyone feels like hacking at it, Bob Keller (Keller@Utah-20) first
+; suggested the beast, and has some good ideas for its improvement, but
+; doesn?tknow TECO (the lucky devil...). One thing that should definitely
+; be done is adding the ability to search some other buffer(s) if you can?t
+; find the expansion you want in the current one.
+
+;; (defun dabbrevs-help ()
+;; "Give help about dabbrevs."
+;; (interactive)
+;; (&info "emacs" "dabbrevs") ; Select the specific info node.
+;; )
+(provide 'dabbrevs)
+
+(defvar dabbrevs-limit nil
+ "*Limits region searched by dabbrevs-expand to that many chars away (local).")
+(make-variable-buffer-local 'dabbrevs-limit)
+
+(defvar dabbrevs-backward-only nil
+ "*If non-NIL, dabbrevs-expand only looks backwards.")
+
+; State vars for dabbrevs-re-expand.
+(defvar last-dabbrevs-table nil
+ "Table of expansions seen so far. (local)")
+(make-variable-buffer-local 'last-dabbrevs-table)
+
+(defvar last-dabbrevs-abbreviation ""
+ "Last string we tried to expand. Buffer-local.")
+(make-variable-buffer-local 'last-dabbrevs-abbreviation)
+
+(defvar last-dabbrevs-direction 0
+ "Direction of last dabbrevs search. (local)")
+(make-variable-buffer-local 'last-dabbrevs-direction)
+
+(defvar last-dabbrevs-abbrev-location nil
+ "Location last abbreviation began (local).")
+(make-variable-buffer-local 'last-dabbrevs-abbrev-location)
+
+(defvar last-dabbrevs-expansion nil
+ "Last expansion of an abbreviation. (local)")
+(make-variable-buffer-local 'last-dabbrevs-expansion)
+
+(defvar last-dabbrevs-expansion-location nil
+ "Location the last expansion was found. (local)")
+(make-variable-buffer-local 'last-dabbrevs-expansion-location)
+
+(defun dabbrev-expand (arg)
+ "Expand previous word \"dynamically\".
+Expands to the most recent, preceding word for which this is a prefix.
+If no suitable preceding word is found, words following point are considered.
+
+A positive prefix argument, N, says to take the Nth backward DISTINCT
+possibility. A negative argument says search forward. The variable
+dabbrev-backward-only may be used to limit the direction of search to
+backward if set non-nil.
+
+If the cursor has not moved from the end of the previous expansion and
+no argument is given, replace the previously-made expansion
+with the next possible expansion not yet tried."
+ (interactive "*P")
+ (let (abbrev expansion old which loc n pattern
+ (do-case (and case-fold-search case-replace)))
+ ;; abbrev -- the abbrev to expand
+ ;; expansion -- the expansion found (eventually) or nil until then
+ ;; old -- the text currently in the buffer
+ ;; (the abbrev, or the previously-made expansion)
+ ;; loc -- place where expansion is found
+ ;; (to start search there for next expansion if requested later)
+ ;; do-case -- nil if should consider case significant.
+ (save-excursion
+ (if (and (null arg)
+ (eq last-command this-command)
+ last-dabbrevs-abbrev-location)
+ (progn
+ (setq abbrev last-dabbrevs-abbreviation)
+ (setq old last-dabbrevs-expansion)
+ (setq which last-dabbrevs-direction))
+ (setq which (if (null arg)
+ (if dabbrevs-backward-only 1 0)
+ (prefix-numeric-value arg)))
+ (setq loc (point))
+ (forward-word -1)
+ (setq last-dabbrevs-abbrev-location (point)) ; Original location.
+ (setq abbrev (buffer-substring (point) loc))
+ (setq old abbrev)
+ (setq last-dabbrevs-expansion-location nil)
+ (setq last-dabbrev-table nil)) ; Clear table of things seen.
+
+ (setq pattern (concat "\\b" (regexp-quote abbrev) "\\(\\sw\\|\\s_\\)+"))
+ ;; Try looking backward unless inhibited.
+ (if (>= which 0)
+ (progn
+ (setq n (max 1 which))
+ (if last-dabbrevs-expansion-location
+ (goto-char last-dabbrevs-expansion-location))
+ (while (and (> n 0)
+ (setq expansion (dabbrevs-search pattern t do-case)))
+ (setq loc (point-marker))
+ (setq last-dabbrev-table (cons expansion last-dabbrev-table))
+ (setq n (1- n)))
+ (or expansion
+ (setq last-dabbrevs-expansion-location nil))
+ (setq last-dabbrevs-direction (min 1 which))))
+
+ (if (and (<= which 0) (not expansion)) ; Then look forward.
+ (progn
+ (setq n (max 1 (- which)))
+ (if last-dabbrevs-expansion-location
+ (goto-char last-dabbrevs-expansion-location))
+ (while (and (> n 0)
+ (setq expansion (dabbrevs-search pattern nil do-case)))
+ (setq loc (point-marker))
+ (setq last-dabbrev-table (cons expansion last-dabbrev-table))
+ (setq n (1- n)))
+ (setq last-dabbrevs-direction -1))))
+
+ (if (not expansion)
+ (let ((first (string= abbrev old)))
+ (setq last-dabbrevs-abbrev-location nil)
+ (if (not first)
+ (progn (undo-boundary)
+ (delete-backward-char (length old))
+ (insert abbrev)))
+ (error (if first
+ "No dynamic expansion for \"%s\" found."
+ "No further dynamic expansions for \"%s\" found.")
+ abbrev))
+ ;; Success: stick it in and return.
+ (undo-boundary)
+ (search-backward old)
+ ;; Make case of replacement conform to case of abbreviation
+ ;; provided (1) that kind of thing is enabled in this buffer
+ ;; and (2) the replacement itself is all lower case
+ ;; except perhaps for the first character.
+ (let ((do-case (and do-case
+ (string= (substring expansion 1)
+ (downcase (substring expansion 1))))))
+ ;; First put back the original abbreviation with its original
+ ;; case pattern.
+ (save-excursion
+ (replace-match abbrev t 'literal))
+ (search-forward abbrev)
+ (replace-match (if do-case (downcase expansion) expansion)
+ (not do-case)
+ 'literal))
+ ;; Save state for re-expand.
+ (setq last-dabbrevs-abbreviation abbrev)
+ (setq last-dabbrevs-expansion expansion)
+ (setq last-dabbrevs-expansion-location loc))))
+
+;; Search function used by dabbrevs library.
+;; First arg is string to find as prefix of word. Second arg is
+;; t for reverse search, nil for forward. Variable dabbrevs-limit
+;; controls the maximum search region size.
+
+;; Table of expansions already seen is examined in buffer last-dabbrev-table,
+;; so that only distinct possibilities are found by dabbrevs-re-expand.
+;; Note that to prevent finding the abbrev itself it must have been
+;; entered in the table.
+
+;; Value is the expansion, or nil if not found. After a successful
+;; search, point is left right after the expansion found.
+
+(defun dabbrevs-search (pattern reverse do-case)
+ (let (missing result)
+ (save-restriction ; Uses restriction for limited searches.
+ (if dabbrevs-limit
+ (narrow-to-region last-dabbrevs-abbrev-location
+ (+ (point)
+ (* dabbrevs-limit (if reverse -1 1)))))
+ ;; Keep looking for a distinct expansion.
+ (setq result nil)
+ (setq missing nil)
+ (while (and (not result) (not missing))
+ ; Look for it, leave loop if search fails.
+ (setq missing
+ (not (if reverse
+ (re-search-backward pattern nil t)
+ (re-search-forward pattern nil t))))
+
+ (if (not missing)
+ (progn
+ (setq result (buffer-substring (match-beginning 0)
+ (match-end 0)))
+ (let* ((test last-dabbrev-table))
+ (while (and test
+ (not
+ (if do-case
+ (string= (downcase (car test)) (downcase result))
+ (string= (car test) result))))
+ (setq test (cdr test)))
+ (if test (setq result nil)))))) ; if already in table, ignore
+ result)))
diff --git a/lisp/dabbrev.elc b/lisp/dabbrev.elc
new file mode 100644
index 00000000000..689b5a88af0
--- /dev/null
+++ b/lisp/dabbrev.elc
Binary files differ
diff --git a/lisp/dbx.el b/lisp/dbx.el
new file mode 100644
index 00000000000..9b268fee133
--- /dev/null
+++ b/lisp/dbx.el
@@ -0,0 +1,165 @@
+;; Run dbx under Emacs
+;; Copyright (C) 1988 Free Software Foundation, Inc.
+;; Main author Masanobu UMEDA (umerin@flab.fujitsu.junet)
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 1, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+(require 'shell)
+
+(defvar dbx-trace-flag nil
+ "Dbx trace switch.")
+
+(defvar dbx-process nil
+ "The process in which dbx is running.")
+
+(defvar dbx-break-point
+ "stopped in .* at line \\([0-9]*\\) in file \"\\([^\"]*\\)\""
+ "Regexp of pattern that dbx writes at break point.")
+
+(defvar inferior-dbx-mode-map nil)
+(if inferior-dbx-mode-map
+ nil
+ (setq inferior-dbx-mode-map (copy-keymap shell-mode-map))
+ (define-key inferior-dbx-mode-map "\C-cw" 'dbx-where)
+ (define-key inferior-dbx-mode-map "\C-c\C-t" 'dbx-trace-mode)
+ (define-key ctl-x-map " " 'dbx-stop-at))
+
+(defun inferior-dbx-mode ()
+ "Major mode for interacting with an inferior Dbx process.
+
+The following commands are available:
+\\{inferior-dbx-mode-map}
+
+Entry to this mode calls the value of dbx-mode-hook with no arguments,
+if that value is non-nil. Likewise with the value of shell-mode-hook.
+dbx-mode-hook is called after shell-mode-hook.
+
+You can display the debugging program in other window and point out
+where you are looking at using the command \\[dbx-where].
+
+\\[dbx-trace-mode] toggles dbx-trace mode. In dbx-trace mode,
+debugging program is automatically traced using output from dbx.
+
+The command \\[dbx-stop-at] sets break point at current line of the
+program in the buffer. Major mode name of the buffer must be in
+dbx-language-mode-list.
+
+Commands:
+
+Return at end of buffer sends line as input.
+Return not at end copies rest of line to end and sends it.
+\\[shell-send-eof] sends end-of-file as input.
+\\[kill-shell-input] and \\[backward-kill-word] are kill commands, imitating normal Unix input editing.
+\\[interrupt-shell-subjob] interrupts the shell or its current subjob if any.
+\\[stop-shell-subjob] stops, likewise. \\[quit-shell-subjob] sends quit signal, likewise.
+\\[dbx-where] displays debugging program in other window and
+ points out where you are looking at.
+\\[dbx-trace-mode] toggles dbx-trace mode.
+\\[dbx-stop-at] sets break point at current line."
+ (interactive)
+ (kill-all-local-variables)
+ (setq major-mode 'inferior-dbx-mode)
+ (setq mode-name "Inferior Dbx")
+ (setq mode-line-process '(": %s"))
+ (use-local-map inferior-dbx-mode-map)
+ (make-local-variable 'last-input-start)
+ (setq last-input-start (make-marker))
+ (make-local-variable 'last-input-end)
+ (setq last-input-end (make-marker))
+ (make-local-variable 'dbx-trace-flag)
+ (setq dbx-trace-flag nil)
+ (make-variable-buffer-local 'shell-prompt-pattern)
+ (setq shell-prompt-pattern "^[^)]*dbx) *") ;Set dbx prompt pattern
+ (or (assq 'dbx-trace-flag minor-mode-alist)
+ (setq minor-mode-alist
+ (cons '(dbx-trace-flag " Trace") minor-mode-alist)))
+ (run-hooks 'shell-mode-hook 'dbx-mode-hook))
+
+(defun run-dbx (path)
+ "Run an inferior Dbx process, input and output via buffer *dbx*."
+ (interactive "fProgram to debug: ")
+ (setq path (expand-file-name path))
+ (let ((file (file-name-nondirectory path)))
+ (switch-to-buffer (concat "*dbx-" file "*"))
+ (setq default-directory (file-name-directory path))
+ (switch-to-buffer (make-shell (concat "dbx-" file) "dbx" nil file)))
+ (setq dbx-process (get-buffer-process (current-buffer)))
+ (set-process-filter dbx-process 'dbx-filter)
+ (inferior-dbx-mode))
+
+(defun dbx-trace-mode (arg)
+ "Toggle dbx-trace mode.
+With arg, turn dbx-trace mode on iff arg is positive.
+In dbx-trace mode, user program is automatically traced."
+ (interactive "P")
+ (if (not (eql major-mode 'inferior-dbx-mode))
+ (error "Dbx-trace mode is effective in inferior-dbx mode only."))
+ (setq dbx-trace-flag
+ (if (null arg)
+ (not dbx-trace-flag)
+ (> (prefix-numeric-value arg) 0)))
+ ;; Force mode line redisplay
+ (set-buffer-modified-p (buffer-modified-p)))
+
+(defun dbx-filter (process string)
+ "Trace debugging program automatically if dbx-trace-flag is not nil."
+ (save-excursion
+ (set-buffer (process-buffer process))
+ (goto-char (point-max))
+ (let ((beg (point)))
+ (insert string)
+ (if dbx-trace-flag ;Trace mode is on?
+ (dbx-where beg t)))
+ (if (process-mark process)
+ (set-marker (process-mark process) (point-max))))
+ (if (eq (process-buffer process)
+ (current-buffer))
+ (goto-char (point-max)))
+ )
+
+(defun dbx-where (&optional begin quiet)
+ "Display dbx'ed program in other window and point out where you are looking at.
+BEGIN bounds the search. If QUIET, just return nil (no error) if fail."
+ (interactive)
+ (let (file line)
+ (save-excursion
+ (if (re-search-backward dbx-break-point begin quiet)
+ (progn
+ (setq line (buffer-substring (match-beginning 1) (match-end 1)))
+ (setq file (buffer-substring (match-beginning 2) (match-end 2)))
+ )))
+ (if (and file line) ;Find break point?
+ (progn
+ (find-file-other-window (expand-file-name file nil))
+ (goto-line (string-to-int line)) ;Jump to the line
+ (beginning-of-line)
+ (setq overlay-arrow-string "=>")
+ (or overlay-arrow-position
+ (setq overlay-arrow-position (make-marker)))
+ (set-marker overlay-arrow-position (point) (current-buffer))
+ (other-window 1)) ;Return to dbx
+ )))
+
+(defun dbx-stop-at ()
+ "Set break point at current line."
+ (interactive)
+ (let ((file-name (file-name-nondirectory buffer-file-name))
+ (line (save-restriction
+ (widen)
+ (1+ (count-lines 1 (point))))))
+ (send-string dbx-process
+ (concat "stop at \"" file-name "\":" line "\n"))))
diff --git a/lisp/dbx.elc b/lisp/dbx.elc
new file mode 100644
index 00000000000..6f73b802ef7
--- /dev/null
+++ b/lisp/dbx.elc
Binary files differ
diff --git a/lisp/debug.el b/lisp/debug.el
new file mode 100644
index 00000000000..0c6a124d837
--- /dev/null
+++ b/lisp/debug.el
@@ -0,0 +1,261 @@
+;; Debuggers and related commands for Emacs
+;; Copyright (C) 1985, 1986 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 1, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+(setq debugger 'debug)
+
+(defun debug (&rest debugger-args)
+ "Enter debugger. Returns if user says \"continue\".
+Arguments are mainly for use when this is called
+ from the internals of the evaluator.
+You may call with no args, or you may
+ pass nil as the first arg and any other args you like.
+ In that case, the list of args after the first will
+ be printed into the backtrace buffer."
+ (message "Entering debugger...")
+ (let (debugger-value
+ (debugger-match-data (match-data))
+ (debug-on-error nil)
+ (debug-on-quit nil)
+ (debugger-buffer (let ((default-major-mode 'fundamental-mode))
+ (generate-new-buffer "*Backtrace*")))
+ (debugger-old-buffer (current-buffer))
+ (debugger-step-after-exit nil)
+ ;; Don't keep reading from an executing kbd macro!
+ (executing-macro nil)
+ (cursor-in-echo-area nil))
+ (unwind-protect
+ (save-excursion
+ (save-window-excursion
+ (pop-to-buffer debugger-buffer)
+ (erase-buffer)
+ (let ((standard-output (current-buffer))
+ (print-escape-newlines t)
+ (print-length 50))
+ (backtrace))
+ (goto-char (point-min))
+ (debugger-mode)
+ (delete-region (point)
+ (progn
+ (forward-sexp 8)
+ (forward-line 1)
+ (point)))
+ (cond ((memq (car debugger-args) '(lambda debug))
+ (insert "Entering:\n")
+ (if (eq (car debugger-args) 'debug)
+ (progn
+ (backtrace-debug 4 t)
+ (delete-char 1)
+ (insert ?*)
+ (beginning-of-line))))
+ ((eq (car debugger-args) 'exit)
+ (insert "Return value: ")
+ (setq debugger-value (nth 1 debugger-args))
+ (prin1 debugger-value (current-buffer))
+ (insert ?\n)
+ (delete-char 1)
+ (insert ? )
+ (beginning-of-line))
+ ((eq (car debugger-args) 'error)
+ (insert "Signalling: ")
+ (prin1 (nth 1 debugger-args) (current-buffer))
+ (insert ?\n))
+ ((eq (car debugger-args) t)
+ (insert "Beginning evaluation of function call form:\n"))
+ (t
+ (prin1 (if (eq (car debugger-args) 'nil)
+ (cdr debugger-args) debugger-args)
+ (current-buffer))
+ (insert ?\n)))
+ (message "")
+ (let ((inhibit-trace t)
+ (standard-output nil)
+ (buffer-read-only t))
+ (message "")
+ (recursive-edit))))
+ ;; So that users do not try to execute debugger commands
+ ;; in an invalid context
+ (kill-buffer debugger-buffer)
+ (store-match-data debugger-match-data))
+ (setq debug-on-next-call debugger-step-after-exit)
+ debugger-value))
+
+(defun debugger-step-through ()
+ "Proceed, stepping through subexpressions of this expression.
+Enter another debugger on next entry to eval, apply or funcall."
+ (interactive)
+ (setq debugger-step-after-exit t)
+ (message "Proceding, will debug on next eval or call.")
+ (exit-recursive-edit))
+
+(defun debugger-continue ()
+ "Continue, evaluating this expression without stopping."
+ (interactive)
+ (message "Continuing.")
+ (exit-recursive-edit))
+
+(defun debugger-return-value (val)
+ "Continue, specifying value to return.
+This is only useful when the value returned from the debugger
+will be used, such as in a debug on exit from a frame."
+ (interactive "XReturn value (evaluated): ")
+ (setq debugger-value val)
+ (princ "Returning " t)
+ (prin1 debugger-value)
+ (exit-recursive-edit))
+
+(defun debugger-frame-number ()
+ "Return number of frames in backtrace before the one point points at."
+ (save-excursion
+ (beginning-of-line)
+ (let ((opoint (point))
+ (count 0))
+ (goto-char (point-min))
+ (if (or (equal (buffer-substring (point) (+ (point) 6))
+ "Signal")
+ (equal (buffer-substring (point) (+ (point) 6))
+ "Return"))
+ (progn
+ (search-forward ":")
+ (forward-sexp 1)))
+ (forward-line 1)
+ (while (progn
+ (forward-char 2)
+ (if (= (following-char) ?\()
+ (forward-sexp 1)
+ (forward-sexp 2))
+ (forward-line 1)
+ (<= (point) opoint))
+ (setq count (1+ count)))
+ count)))
+
+;; Chosen empirically to account for all the frames
+;; that will exist when debugger-frame is called
+;; within the first one that appears in the backtrace buffer.
+;; Assumes debugger-frame is called from a key;
+;; will be wrong if it is called with Meta-x.
+(defconst debugger-frame-offset 8 "")
+
+(defun debugger-frame ()
+ "Request entry to debugger when this frame exits.
+Applies to the frame whose line point is on in the backtrace."
+ (interactive)
+ (beginning-of-line)
+ (let ((level (debugger-frame-number)))
+ (backtrace-debug (+ level debugger-frame-offset) t))
+ (if (= (following-char) ? )
+ (let ((buffer-read-only nil))
+ (delete-char 1)
+ (insert ?*)))
+ (beginning-of-line))
+
+(defun debugger-frame-clear ()
+ "Do not enter to debugger when this frame exits.
+Applies to the frame whose line point is on in the backtrace."
+ (interactive)
+ (beginning-of-line)
+ (let ((level (debugger-frame-number)))
+ (backtrace-debug (+ level debugger-frame-offset) nil))
+ (if (= (following-char) ?*)
+ (let ((buffer-read-only nil))
+ (delete-char 1)
+ (insert ? )))
+ (beginning-of-line))
+
+(defun debugger-eval-expression (exp)
+ (interactive "xEval: ")
+ (save-excursion
+ (if (null (buffer-name debugger-old-buffer))
+ ;; old buffer deleted
+ (setq debugger-old-buffer (current-buffer)))
+ (set-buffer debugger-old-buffer)
+ (eval-expression exp)))
+
+(defvar debugger-mode-map nil)
+(if debugger-mode-map
+ nil
+ (let ((loop ? ))
+ (setq debugger-mode-map (make-keymap))
+ (suppress-keymap debugger-mode-map)
+ (define-key debugger-mode-map "-" 'negative-argument)
+ (define-key debugger-mode-map "b" 'debugger-frame)
+ (define-key debugger-mode-map "c" 'debugger-continue)
+ (define-key debugger-mode-map "r" 'debugger-return-value)
+ (define-key debugger-mode-map "u" 'debugger-frame-clear)
+ (define-key debugger-mode-map "d" 'debugger-step-through)
+ (define-key debugger-mode-map "h" 'describe-mode)
+ (define-key debugger-mode-map "q" 'top-level)
+ (define-key debugger-mode-map "e" 'debugger-eval-expression)
+ (define-key debugger-mode-map " " 'next-line)))
+
+(put 'debugger-mode 'mode-class 'special)
+
+(defun debugger-mode ()
+ "Mode for backtrace buffers, selected in debugger.
+\\{debugger-mode-map}
+For the r command, when in debugger due to frame being exited,
+ the value specified here will be used as the value of that frame.
+
+Note lines starting with * are frames that will
+ enter debugger when exited."
+ (kill-all-local-variables)
+ (setq major-mode 'debugger-mode)
+ (setq mode-name "Debugger")
+ (setq truncate-lines t)
+ (set-syntax-table emacs-lisp-mode-syntax-table)
+ (use-local-map debugger-mode-map))
+
+(defun debug-on-entry (function)
+ "Request FUNCTION to invoke debugger each time it is called.
+If the user continues, FUNCTION's execution proceeds.
+Works by modifying the definition of FUNCTION,
+which must be written in Lisp, not predefined.
+Use `cancel-debug-on-entry' to cancel the effect of this command.
+Redefining FUNCTION also does that."
+ (interactive "aDebug on entry (to function): ")
+ (let ((defn (symbol-function function)))
+ (if (eq (car defn) 'macro)
+ (fset function (cons 'macro (debug-on-entry-1 function (cdr defn) t)))
+ (fset function (debug-on-entry-1 function defn t))))
+ function)
+
+(defun cancel-debug-on-entry (function)
+ "Undoes effect of debug-on-entry on FUNCTION."
+ (interactive "aCancel debug on entry (to function): ")
+ (let ((defn (symbol-function function)))
+ (if (eq (car defn) 'macro)
+ (fset function
+ (cons 'macro (debug-on-entry-1 function (cdr defn) nil)))
+ (fset function (debug-on-entry-1 function defn nil))))
+ function)
+
+(defun debug-on-entry-1 (function defn flag)
+ (or (eq (car defn) 'lambda)
+ (error "%s not user-defined Lisp function." function))
+ (let (tail prec)
+ (if (stringp (car (nthcdr 2 defn)))
+ (setq tail (nthcdr 3 defn)
+ prec (list (car defn) (car (cdr defn)) (car (cdr (cdr defn)))))
+ (setq tail (nthcdr 2 defn)
+ prec (list (car defn) (car (cdr defn)))))
+ (if (eq flag (equal (car tail) '(debug 'debug)))
+ nil
+ (if flag
+ (nconc prec (cons '(debug 'debug) tail))
+ (nconc prec (cdr tail))))))
diff --git a/lisp/debug.elc b/lisp/debug.elc
new file mode 100644
index 00000000000..eb613e80b02
--- /dev/null
+++ b/lisp/debug.elc
Binary files differ
diff --git a/lisp/dired.el b/lisp/dired.el
new file mode 100644
index 00000000000..e56afcc8e17
--- /dev/null
+++ b/lisp/dired.el
@@ -0,0 +1,633 @@
+;;; Missing: P command, sorting, setting file modes.
+;;; Dired buffer containing multiple directories gets totally confused
+;;; Implement insertion of subdirectories in situ --- tree dired
+
+;; DIRED commands for Emacs
+;; Copyright (C) 1985, 1986 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 1, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+;In loaddefs.el
+;(defvar dired-listing-switches "-al"
+; "Switches passed to ls for dired. MUST contain the 'l' option.
+;CANNOT contain the 'F' option.")
+
+(defun dired-readin (dirname buffer)
+ (save-excursion
+ (message "Reading directory %s..." dirname)
+ (set-buffer buffer)
+ (let ((buffer-read-only nil))
+ (widen)
+ (erase-buffer)
+ (setq dirname (expand-file-name dirname))
+ (if (file-directory-p dirname)
+ (call-process "ls" nil buffer nil
+ dired-listing-switches dirname)
+ (let ((default-directory (file-name-directory dirname)))
+ (call-process shell-file-name nil buffer nil
+ "-c" (concat "ls " dired-listing-switches " "
+ (file-name-nondirectory dirname)))))
+ (goto-char (point-min))
+ (while (not (eobp))
+ (insert " ")
+ (forward-line 1))
+ (goto-char (point-min)))
+ (set-buffer-modified-p nil)
+ (message "Reading directory %s...done" dirname)))
+
+(defun dired-find-buffer (dirname)
+ (let ((blist (buffer-list))
+ found)
+ (while blist
+ (save-excursion
+ (set-buffer (car blist))
+ (if (and (eq major-mode 'dired-mode)
+ (equal dired-directory dirname))
+ (setq found (car blist)
+ blist nil)
+ (setq blist (cdr blist)))))
+ (or found
+ (create-file-buffer (directory-file-name dirname)))))
+
+(defun dired (dirname)
+ "\"Edit\" directory DIRNAME--delete, rename, print, etc. some files in it.
+Dired displays a list of files in DIRNAME.
+You can move around in it with the usual commands.
+You can flag files for deletion with C-d
+and then delete them by typing `x'.
+Type `h' after entering dired for more info."
+ (interactive (list (read-file-name "Dired (directory): "
+ nil default-directory nil)))
+ (switch-to-buffer (dired-noselect dirname)))
+
+(defun dired-other-window (dirname)
+ "\"Edit\" directory DIRNAME. Like M-x dired but selects in another window."
+ (interactive (list (read-file-name "Dired in other window (directory): "
+ nil default-directory nil)))
+ (switch-to-buffer-other-window (dired-noselect dirname)))
+
+(defun dired-noselect (dirname)
+ "Like M-x dired but returns the dired buffer as value, does not select it."
+ (or dirname (setq dirname default-directory))
+ (setq dirname (expand-file-name (directory-file-name dirname)))
+ (if (file-directory-p dirname)
+ (setq dirname (file-name-as-directory dirname)))
+ (let ((buffer (dired-find-buffer dirname)))
+ (save-excursion
+ (set-buffer buffer)
+ (dired-readin dirname buffer)
+ (dired-move-to-filename)
+ (dired-mode dirname))
+ buffer))
+
+(defun dired-revert (&optional arg noconfirm)
+ (let ((opoint (point))
+ (ofile (dired-get-filename t t))
+ (buffer-read-only nil))
+ (erase-buffer)
+ (dired-readin dired-directory (current-buffer))
+ (or (and ofile (re-search-forward (concat " " (regexp-quote ofile) "$")
+ nil t))
+ (goto-char opoint))
+ (beginning-of-line)))
+
+(defvar dired-mode-map nil "Local keymap for dired-mode buffers.")
+(if dired-mode-map
+ nil
+ (setq dired-mode-map (make-keymap))
+ (suppress-keymap dired-mode-map)
+ (define-key dired-mode-map "r" 'dired-rename-file)
+ (define-key dired-mode-map "\C-d" 'dired-flag-file-deleted)
+ (define-key dired-mode-map "d" 'dired-flag-file-deleted)
+ (define-key dired-mode-map "v" 'dired-view-file)
+ (define-key dired-mode-map "e" 'dired-find-file)
+ (define-key dired-mode-map "f" 'dired-find-file)
+ (define-key dired-mode-map "o" 'dired-find-file-other-window)
+ (define-key dired-mode-map "u" 'dired-unflag)
+ (define-key dired-mode-map "x" 'dired-do-deletions)
+ (define-key dired-mode-map "\177" 'dired-backup-unflag)
+ (define-key dired-mode-map "?" 'dired-summary)
+ (define-key dired-mode-map "c" 'dired-copy-file)
+ (define-key dired-mode-map "#" 'dired-flag-auto-save-files)
+ (define-key dired-mode-map "~" 'dired-flag-backup-files)
+ (define-key dired-mode-map "." 'dired-clean-directory)
+ (define-key dired-mode-map "h" 'describe-mode)
+ (define-key dired-mode-map " " 'dired-next-line)
+ (define-key dired-mode-map "\C-n" 'dired-next-line)
+ (define-key dired-mode-map "\C-p" 'dired-previous-line)
+ (define-key dired-mode-map "n" 'dired-next-line)
+ (define-key dired-mode-map "p" 'dired-previous-line)
+ (define-key dired-mode-map "g" 'revert-buffer)
+ (define-key dired-mode-map "C" 'dired-compress)
+ (define-key dired-mode-map "U" 'dired-uncompress)
+ (define-key dired-mode-map "B" 'dired-byte-recompile)
+ (define-key dired-mode-map "M" 'dired-chmod)
+ (define-key dired-mode-map "G" 'dired-chgrp)
+ (define-key dired-mode-map "O" 'dired-chown))
+
+
+;; Dired mode is suitable only for specially formatted data.
+(put 'dired-mode 'mode-class 'special)
+
+(defun dired-mode (&optional dirname)
+ "Mode for \"editing\" directory listings.
+In dired, you are \"editing\" a list of the files in a directory.
+You can move using the usual cursor motion commands.
+Letters no longer insert themselves.
+Instead, type d to flag a file for Deletion.
+Type u to Unflag a file (remove its D flag).
+ Type Rubout to back up one line and unflag.
+Type x to eXecute the deletions requested.
+Type f to Find the current line's file
+ (or Dired it, if it is a directory).
+Type o to find file or dired directory in Other window.
+Type # to flag temporary files (names beginning with #) for Deletion.
+Type ~ to flag backup files (names ending with ~) for Deletion.
+Type . to flag numerical backups for Deletion.
+ (Spares dired-kept-versions or its numeric argument.)
+Type r to rename a file.
+Type c to copy a file.
+Type v to view a file in View mode, returning to Dired when done.
+Type g to read the directory again. This discards all deletion-flags.
+Space and Rubout can be used to move down and up by lines.
+Also: C -- compress this file. U -- uncompress this file.
+ B -- byte compile this file.
+ M, G, O -- change file's mode, group or owner.
+\\{dired-mode-map}"
+ (interactive)
+ (kill-all-local-variables)
+ (make-local-variable 'revert-buffer-function)
+ (setq revert-buffer-function 'dired-revert)
+ (setq major-mode 'dired-mode)
+ (setq mode-name "Dired")
+ (make-local-variable 'dired-directory)
+ (setq dired-directory (or dirname default-directory))
+ (if dirname
+ (setq default-directory
+ (if (file-directory-p dirname)
+ dirname (file-name-directory dirname))))
+ (setq mode-line-buffer-identification '("Dired: %17b"))
+ (setq case-fold-search nil)
+ (setq buffer-read-only t)
+ (use-local-map dired-mode-map)
+ (run-hooks 'dired-mode-hook))
+
+(defun dired-repeat-over-lines (arg function)
+ (beginning-of-line)
+ (while (and (> arg 0) (not (eobp)))
+ (setq arg (1- arg))
+ (save-excursion
+ (beginning-of-line)
+ (and (bobp) (looking-at " total")
+ (error "No file on this line"))
+ (funcall function))
+ (forward-line 1)
+ (dired-move-to-filename))
+ (while (and (< arg 0) (not (bobp)))
+ (setq arg (1+ arg))
+ (forward-line -1)
+ (dired-move-to-filename)
+ (save-excursion
+ (beginning-of-line)
+ (funcall function))))
+
+(defun dired-flag-file-deleted (arg)
+ "In dired, flag the current line's file for deletion.
+With arg, repeat over several lines."
+ (interactive "p")
+ (dired-repeat-over-lines arg
+ '(lambda ()
+ (let ((buffer-read-only nil))
+ (delete-char 1)
+ (insert "D")))))
+
+(defun dired-summary ()
+ (interactive)
+ ;>> this should check the key-bindings and use substitute-command-keys if non-standard
+ (message
+ "d-elete, u-ndelete, x-ecute, f-ind, o-ther window, r-ename, c-opy, v-iew"))
+
+(defun dired-unflag (arg)
+ "In dired, remove the current line's delete flag then move to next line."
+ (interactive "p")
+ (dired-repeat-over-lines arg
+ '(lambda ()
+ (let ((buffer-read-only nil))
+ (delete-char 1)
+ (insert " ")
+ (forward-char -1)))))
+
+(defun dired-backup-unflag (arg)
+ "In dired, move up a line and remove deletion flag there."
+ (interactive "p")
+ (dired-unflag (- arg)))
+
+(defun dired-next-line (arg)
+ "Move down ARG lines then position at filename."
+ (interactive "p")
+ (next-line arg)
+ (dired-move-to-filename))
+
+(defun dired-previous-line (arg)
+ "Move up ARG lines then position at filename."
+ (interactive "p")
+ (previous-line arg)
+ (dired-move-to-filename))
+
+(defun dired-find-file ()
+ "In dired, visit the file or directory named on this line."
+ (interactive)
+ (find-file (dired-get-filename)))
+
+(defun dired-view-file ()
+ "In dired, examine a file in view mode, returning to dired when done."
+ (interactive)
+ (if (file-directory-p (dired-get-filename))
+ (dired (dired-get-filename))
+ (view-file (dired-get-filename))))
+
+(defun dired-find-file-other-window ()
+ "In dired, visit this file or directory in another window."
+ (interactive)
+ (find-file-other-window (dired-get-filename)))
+
+(defun dired-get-filename (&optional localp no-error-if-not-filep)
+ "In dired, return name of file mentioned on this line.
+Value returned normally includes the directory name.
+A non-nil 1st argument means do not include it. A non-nil 2nd argument
+says return nil if no filename on this line, otherwise an error occurs."
+ (let (eol)
+ (save-excursion
+ (end-of-line)
+ (setq eol (point))
+ (beginning-of-line)
+ (if (re-search-forward
+ "\\(Jan\\|Feb\\|Mar\\|Apr\\|May\\|Jun\\|Jul\\|Aug\\|Sep\\|Oct\\|Nov\\|Dec\\)[ ]+[0-9]+"
+ eol t)
+ (progn (skip-chars-forward " ")
+ (skip-chars-forward "^ " eol)
+ (skip-chars-forward " " eol)
+ (let ((beg (point)))
+ (skip-chars-forward "^ \n")
+ (if localp
+ (buffer-substring beg (point))
+ ;; >> uses default-directory, could lose on cd, multiple.
+ (concat default-directory (buffer-substring beg (point))))))
+ (if no-error-if-not-filep nil
+ (error "No file on this line"))))))
+
+(defun dired-move-to-filename ()
+ "In dired, move to first char of filename on this line.
+Returns position (point) or nil if no filename on this line."
+ (let ((eol (progn (end-of-line) (point))))
+ (beginning-of-line)
+ (if (re-search-forward
+ "\\(Jan\\|Feb\\|Mar\\|Apr\\|May\\|Jun\\|Jul\\|Aug\\|Sep\\|Oct\\|Nov\\|Dec\\)[ ]+[0-9]+"
+ eol t)
+ (progn
+ (skip-chars-forward " ")
+ (skip-chars-forward "^ " eol)
+ (skip-chars-forward " " eol)
+ (point)))))
+
+(defun dired-map-dired-file-lines (fn)
+ "perform fn with point at the end of each non-directory line:
+arguments are the short and long filename"
+ (save-excursion
+ (let (filename longfilename (buffer-read-only nil))
+ (goto-char (point-min))
+ (while (not (eobp))
+ (save-excursion
+ (and (not (looking-at " d"))
+ (not (eolp))
+ (setq filename (dired-get-filename t t)
+ longfilename (dired-get-filename nil t))
+ (progn (end-of-line)
+ (funcall fn filename longfilename))))
+ (forward-line 1)))))
+
+(defun dired-flag-auto-save-files ()
+ "Flag for deletion files whose names suggest they are auto save files."
+ (interactive)
+ (save-excursion
+ (let ((buffer-read-only nil))
+ (goto-char (point-min))
+ (while (not (eobp))
+ (and (not (looking-at " d"))
+ (not (eolp))
+ (if (fboundp 'auto-save-file-name-p)
+ (let ((fn (dired-get-filename t t)))
+ (if fn (auto-save-file-name-p fn)))
+ (if (dired-move-to-filename)
+ (looking-at "#")))
+ (progn (beginning-of-line)
+ (delete-char 1)
+ (insert "D")))
+ (forward-line 1)))))
+
+(defun dired-clean-directory (keep)
+ "Flag numerical backups for Deletion.
+Spares dired-kept-versions latest versions, and kept-old-versions oldest.
+Positive numeric arg overrides dired-kept-versions;
+negative numeric arg overrides kept-old-versions with minus the arg."
+ (interactive "P")
+ (setq keep (if keep (prefix-numeric-value keep) dired-kept-versions))
+ (let ((early-retention (if (< keep 0) (- keep) kept-old-versions))
+ (late-retention (if (<= keep 0) dired-kept-versions keep))
+ (file-version-assoc-list ()))
+ ;; Look at each file.
+ ;; If the file has numeric backup versions,
+ ;; put on file-version-assoc-list an element of the form
+ ;; (FILENAME . VERSION-NUMBER-LIST)
+ (dired-map-dired-file-lines 'dired-collect-file-versions)
+ ;; Sort each VERSION-NUMBER-LIST,
+ ;; and remove the versions not to be deleted.
+ (let ((fval file-version-assoc-list))
+ (while fval
+ (let* ((sorted-v-list (cons 'q (sort (cdr (car fval)) '<)))
+ (v-count (length sorted-v-list)))
+ (if (> v-count (+ early-retention late-retention))
+ (rplacd (nthcdr early-retention sorted-v-list)
+ (nthcdr (- v-count late-retention)
+ sorted-v-list)))
+ (rplacd (car fval)
+ (cdr sorted-v-list)))
+ (setq fval (cdr fval))))
+ ;; Look at each file. If it is a numeric backup file,
+ ;; find it in a VERSION-NUMBER-LIST and maybe flag it for deletion.
+ (dired-map-dired-file-lines 'dired-trample-file-versions)))
+
+(defun dired-collect-file-versions (ignore fn)
+ "If it looks like fn has versions, we make a list of the versions.
+We may want to flag some for deletion."
+ (let* ((base-versions
+ (concat (file-name-nondirectory fn) ".~"))
+ (bv-length (length base-versions))
+ (possibilities (file-name-all-completions
+ base-versions
+ (file-name-directory fn)))
+ (versions (mapcar 'backup-extract-version possibilities)))
+ (if versions
+ (setq file-version-assoc-list (cons (cons fn versions)
+ file-version-assoc-list)))))
+
+(defun dired-trample-file-versions (ignore fn)
+ (let* ((start-vn (string-match "\\.~[0-9]+~$" fn))
+ base-version-list)
+ (and start-vn
+ (setq base-version-list ; there was a base version to which
+ (assoc (substring fn 0 start-vn) ; this looks like a
+ file-version-assoc-list)) ; subversion
+ (not (memq (string-to-int (substring fn (+ 2 start-vn)))
+ base-version-list)) ; this one doesn't make the cut
+ (dired-flag-this-line-for-DEATH))))
+
+(defun dired-flag-this-line-for-DEATH ()
+ (beginning-of-line)
+ (delete-char 1)
+ (insert "D"))
+
+(defun dired-flag-backup-files ()
+ "Flag all backup files (names ending with ~) for deletion."
+ (interactive)
+ (save-excursion
+ (let ((buffer-read-only nil))
+ (goto-char (point-min))
+ (while (not (eobp))
+ (and (not (looking-at " d"))
+ (not (eolp))
+ (if (fboundp 'backup-file-name-p)
+ (let ((fn (dired-get-filename t t)))
+ (if fn (backup-file-name-p fn)))
+ (end-of-line)
+ (forward-char -1)
+ (looking-at "~"))
+ (progn (beginning-of-line)
+ (delete-char 1)
+ (insert "D")))
+ (forward-line 1)))))
+
+(defun dired-flag-backup-and-auto-save-files ()
+ "Flag all backup and temporary files for deletion.
+Backup files have names ending in ~. Auto save file names usually
+start with #."
+ (interactive)
+ (dired-flag-backup-files)
+ (dired-flag-auto-save-files))
+
+(defun dired-rename-file (to-file)
+ "Rename this file to TO-FILE."
+ (interactive
+ (list (read-file-name (format "Rename %s to: "
+ (file-name-nondirectory (dired-get-filename)))
+ nil (dired-get-filename))))
+ (setq to-file (expand-file-name to-file))
+ (rename-file (dired-get-filename) to-file)
+ (let ((buffer-read-only nil))
+ (beginning-of-line)
+ (delete-region (point) (progn (forward-line 1) (point)))
+ (setq to-file (expand-file-name to-file))
+ (dired-add-entry (file-name-directory to-file)
+ (file-name-nondirectory to-file))))
+
+(defun dired-copy-file (to-file)
+ "Copy this file to TO-FILE."
+ (interactive "FCopy to: ")
+ (copy-file (dired-get-filename) to-file)
+ (setq to-file (expand-file-name to-file))
+ (dired-add-entry (file-name-directory to-file)
+ (file-name-nondirectory to-file)))
+
+(defun dired-add-entry (directory filename)
+ ;; If tree dired is implemented, this function will have to do
+ ;; something smarter with the directory. Currently, just check
+ ;; default directory, if same, add the new entry at point. With tree
+ ;; dired, should call 'dired-current-directory' or similar. Note
+ ;; that this adds the entry 'out of order' if files sorted by time,
+ ;; etc.
+ (if (string-equal directory default-directory)
+ (let ((buffer-read-only nil))
+ (beginning-of-line)
+ (call-process "ls" nil t nil
+ "-d" dired-listing-switches (concat directory filename))
+ (forward-line -1)
+ (insert " ")
+ (dired-move-to-filename)
+ (let* ((beg (point))
+ (end (progn (end-of-line) (point))))
+ (setq filename (buffer-substring beg end))
+ (delete-region beg end)
+ (insert (file-name-nondirectory filename)))
+ (beginning-of-line))))
+
+(defun dired-compress ()
+ "Compress this file."
+ (interactive)
+ (let* ((buffer-read-only nil)
+ (error-buffer (get-buffer-create " *Dired compress output*"))
+ (from-file (dired-get-filename))
+ (to-file (concat from-file ".Z")))
+ (if (string-match "\\.Z$" from-file)
+ (error "%s is already compressed!" from-file))
+ (message "Compressing %s..." from-file)
+ (unwind-protect
+ (progn
+ (save-excursion
+ (set-buffer error-buffer)
+ (erase-buffer))
+ ;; Must have default-directory of dired buffer in call-process
+ (call-process "compress" nil error-buffer nil "-f" from-file)
+ (if (save-excursion
+ (set-buffer error-buffer)
+ (= 0 (buffer-size)))
+ (progn
+ (message "Compressing %s... done" from-file)
+ (kill-buffer error-buffer))
+ (display-buffer error-buffer)
+ (setq error-buffer nil)
+ (error "Compress error on %s." from-file)))
+ (if error-buffer (kill-buffer error-buffer)))
+ (dired-redisplay to-file)))
+
+(defun dired-uncompress ()
+ "Uncompress this file."
+ (interactive)
+ (let* ((buffer-read-only nil)
+ (error-buffer (get-buffer-create " *Dired compress output*"))
+ (from-file (dired-get-filename))
+ (to-file (substring from-file 0 -2)))
+ (if (string-match "\\.Z$" from-file) nil
+ (error "%s is not compressed!" from-file))
+ (message "Uncompressing %s..." from-file)
+ (unwind-protect
+ (progn
+ (save-excursion
+ (set-buffer error-buffer)
+ (erase-buffer))
+ ;; Must have default-directory of dired buffer in call-process
+ (call-process "uncompress" nil error-buffer nil "-f" from-file)
+ (if (save-excursion
+ (set-buffer error-buffer)
+ (= 0 (buffer-size)))
+ (progn
+ (message "Uncompressing %s... done" from-file)
+ (kill-buffer error-buffer))
+ (display-buffer error-buffer)
+ (setq error-buffer nil)
+ (error "Uncompress error on %s." from-file)))
+ (if error-buffer (kill-buffer error-buffer)))
+ (dired-redisplay to-file)))
+
+(defun dired-byte-recompile ()
+ "Byte recompile this file."
+ (interactive)
+ (let* ((buffer-read-only nil)
+ (from-file (dired-get-filename))
+ (to-file (substring from-file 0 -3)))
+ (if (string-match "\\.el$" from-file) nil
+ (error "%s is uncompilable!" from-file))
+ (byte-compile-file from-file)))
+
+(defun dired-chmod (mode)
+ "Change mode of this file."
+ (interactive "sChange to Mode: ")
+ (let ((buffer-read-only nil)
+ (file (dired-get-filename)))
+ (call-process "/bin/chmod" nil nil nil mode file)
+ (dired-redisplay file)))
+
+(defun dired-chgrp (group)
+ "Change group of this file."
+ (interactive "sChange to Group: ")
+ (let ((buffer-read-only nil)
+ (file (dired-get-filename)))
+ (call-process "/bin/chgrp" nil nil nil group file)
+ (dired-redisplay file)))
+
+(defun dired-chown (owner)
+ "Change Owner of this file."
+ (interactive "sChange to Owner: ")
+ (let ((buffer-read-only nil)
+ (file (dired-get-filename)))
+ (call-process (if (memq system-type '(hpux usg-unix-v silicon-graphics-unix))
+ "/bin/chown" "/etc/chown")
+ nil nil nil owner file)
+ (dired-redisplay file)))
+
+(defun dired-redisplay (file) "Redisplay this line."
+ (beginning-of-line)
+ (delete-region (point) (progn (forward-line 1) (point)))
+ (if file (dired-add-entry (file-name-directory file)
+ (file-name-nondirectory file)))
+ (dired-move-to-filename))
+
+(defun dired-do-deletions ()
+ "In dired, delete the files flagged for deletion."
+ (interactive)
+ (let (delete-list answer)
+ (save-excursion
+ (goto-char 1)
+ (while (re-search-forward "^D" nil t)
+ (setq delete-list
+ (cons (cons (dired-get-filename t) (1- (point)))
+ delete-list))))
+ (if (null delete-list)
+ (message "(No deletions requested)")
+ (save-window-excursion
+ (switch-to-buffer " *Deletions*")
+ (erase-buffer)
+ (setq fill-column 70)
+ (let ((l (reverse delete-list)))
+ ;; Files should be in forward order for this loop.
+ (while l
+ (if (> (current-column) 59)
+ (insert ?\n)
+ (or (bobp)
+ (indent-to (* (/ (+ (current-column) 19) 20) 20) 1)))
+ (insert (car (car l)))
+ (setq l (cdr l))))
+ (goto-char (point-min))
+ (setq answer (yes-or-no-p "Delete these files? ")))
+ (if answer
+ (let ((l delete-list)
+ failures)
+ ;; Files better be in reverse order for this loop!
+ ;; That way as changes are made in the buffer
+ ;; they do not shift the lines still to be changed.
+ (while l
+ (goto-char (cdr (car l)))
+ (let ((buffer-read-only nil))
+ (condition-case ()
+ (let ((fn (concat default-directory (car (car l)))))
+ (if (file-directory-p fn)
+ ;; This used to call delete-file if rmdir
+ ;; did not delete the file,
+ ;; but that made it too easy for root to spaz.
+ (call-process "rmdir" nil nil nil fn)
+ (delete-file fn))
+ (delete-region (point)
+ (progn (forward-line 1) (point))))
+ (error (delete-char 1)
+ (insert " ")
+ (setq failures (cons (car (car l)) failures)))))
+ (setq l (cdr l)))
+ (if failures
+ (message "Deletions failed: %s"
+ (prin1-to-string failures))))))))
+
+(provide 'dired)
diff --git a/lisp/dired.elc b/lisp/dired.elc
new file mode 100644
index 00000000000..ac01032403f
--- /dev/null
+++ b/lisp/dired.elc
Binary files differ
diff --git a/lisp/disass.el b/lisp/disass.el
new file mode 100644
index 00000000000..77e5a7fc17d
--- /dev/null
+++ b/lisp/disass.el
@@ -0,0 +1,446 @@
+;;; Disassembler for compiled Emacs Lisp code
+;; Copyright (C) 1986 Free Software Foundation
+;;; By Doug Cutting (doug@csli.stanford.edu)
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 1, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+(require 'byte-compile "bytecomp")
+
+(defvar disassemble-column-1-indent 4 "*")
+
+(defvar disassemble-column-2-indent 9 "*")
+
+(defvar disassemble-recursive-indent 3 "*")
+
+;(defun d (x)
+; (interactive "xDiss ")
+; (with-output-to-temp-buffer "*Disassemble*"
+; (disassemble-internal (list 'lambda '() x ''return-value)
+; standard-output 0 t)))
+
+(defun disassemble (object &optional stream indent interactive-p)
+ "Print disassembled code for OBJECT on (optional) STREAM.
+OBJECT can be a function name, lambda expression or any function object
+returned by SYMBOL-FUNCTION. If OBJECT is not already compiled, we will
+compile it (but not redefine it)."
+ (interactive (list (intern (completing-read "Disassemble function: "
+ obarray 'fboundp t))
+ nil 0 t))
+ (or indent (setq indent 0)) ;Default indent to zero
+ (if interactive-p
+ (with-output-to-temp-buffer "*Disassemble*"
+ (disassemble-internal object standard-output indent t))
+ (disassemble-internal object (or stream standard-output) indent nil))
+ nil)
+
+(defun disassemble-internal (obj stream indent interactive-p)
+ (let ((macro 'nil)
+ (name 'nil)
+ (doc 'nil)
+ args)
+ (while (symbolp obj)
+ (setq name obj
+ obj (symbol-function obj)))
+ (if (subrp obj)
+ (error "Can't disassemble #<subr %s>" name))
+ (if (eq (car obj) 'macro) ;handle macros
+ (setq macro t
+ obj (cdr obj)))
+ (if (not (eq (car obj) 'lambda))
+ (error "not a function"))
+ (if (assq 'byte-code obj)
+ nil
+ (if interactive-p (message (if name
+ "Compiling %s's definition..."
+ "Compiling definition...")
+ name))
+ (setq obj (byte-compile-lambda obj))
+ (if interactive-p (message "Done compiling. Disassembling...")))
+ (setq obj (cdr obj)) ;throw lambda away
+ (setq args (car obj)) ;save arg list
+ (setq obj (cdr obj))
+ (write-spaces indent stream)
+ (princ (format "byte code%s%s%s:\n"
+ (if (or macro name) " for" "")
+ (if macro " macro" "")
+ (if name (format " %s" name) ""))
+ stream)
+ (let ((doc (and (stringp (car obj)) (car obj))))
+ (if doc
+ (progn (setq obj (cdr obj))
+ (write-spaces indent stream)
+ (princ " doc: " stream)
+ (princ doc stream)
+ (terpri stream))))
+ (write-spaces indent stream)
+ (princ " args: " stream)
+ (prin1 args stream)
+ (terpri stream)
+ (let ((interactive (car (cdr (assq 'interactive obj)))))
+ (if interactive
+ (progn (write-spaces indent stream)
+ (princ " interactive: " stream)
+ (if (eq (car-safe interactive) 'byte-code)
+ (disassemble-1 interactive stream
+ (+ indent disassemble-recursive-indent))
+ (prin1 interactive stream)
+ (terpri stream)))))
+ (setq obj (assq 'byte-code obj)) ;obj is now call to byte-code
+ (disassemble-1 obj stream indent))
+ (if interactive-p
+ (message "")))
+
+(defun disassemble-1 (obj &optional stream indent)
+ "Prints the byte-code call OBJ to (optional) STREAM.
+OBJ should be a call to BYTE-CODE generated by the byte compiler."
+ (or indent (setq indent 0)) ;default indent to 0
+ (or stream (setq stream standard-output))
+ (let ((bytes (car (cdr obj))) ;the byte code
+ (ptr -1) ;where we are in it
+ (constants (car (cdr (cdr obj)))) ;constant vector
+ ;(next-indent indent)
+ offset tmp length)
+ (setq length (length bytes))
+ (terpri stream)
+ (while (< (setq ptr (1+ ptr)) length)
+ ;(setq indent next-indent)
+ (write-spaces indent stream) ;indent to recursive indent
+ (princ (setq tmp (prin1-to-string ptr)) stream) ;print line #
+ (write-char ?\ stream)
+ (write-spaces (- disassemble-column-1-indent (length tmp) 1)
+ stream)
+ (setq op (aref bytes ptr)) ;fetch opcode
+ ;; Note: as offsets are either encoded in opcodes or stored as
+ ;; bytes in the code, this function (disassemble-offset)
+ ;; can set OP and/or PTR.
+ (setq offset (disassemble-offset));fetch offset
+ (setq tmp (aref byte-code-vector op))
+ (if (consp tmp)
+ (setq ;next-indent (if (numberp (cdr tmp))
+ ; (+ indent (cdr tmp))
+ ; (+ indent (funcall (cdr tmp) offset)))
+ tmp (car tmp)))
+ (setq tmp (symbol-name tmp))
+ (princ tmp stream) ;print op-name for opcode
+ (if (null offset)
+ nil
+ (write-char ?\ stream)
+ (write-spaces (- disassemble-column-2-indent (length tmp) 1)
+ stream) ;indent to col 2
+ (princ ;print offset
+ (cond ((or (eq op byte-varref)
+ (eq op byte-varset)
+ (eq op byte-varbind))
+ ;; it's a varname (atom)
+ (aref constants offset)) ;fetch it from constants
+ ((or (eq op byte-goto)
+ (eq op byte-goto-if-nil)
+ (eq op byte-goto-if-not-nil)
+ (eq op byte-goto-if-nil-else-pop)
+ (eq op byte-goto-if-not-nil-else-pop)
+ (eq op byte-call)
+ (eq op byte-unbind))
+ ;; it's a number
+ offset) ;return it
+ ((or (eq op byte-constant)
+ (eq op byte-constant2))
+ ;; it's a constant
+ (setq tmp (aref constants offset))
+ ;; but is constant byte code?
+ (cond ((and (eq (car-safe tmp) 'lambda)
+ (assq 'byte-code tmp))
+ (princ "<compiled lambda>" stream)
+ (terpri stream)
+ (disassemble ;recurse on compiled lambda
+ tmp
+ stream
+ (+ indent disassemble-recursive-indent))
+ "")
+ ((eq (car-safe tmp) 'byte-code)
+ (princ "<byte code>" stream)
+ (terpri stream)
+ (disassemble-1 ;recurse on byte-code object
+ tmp
+ stream
+ (+ indent disassemble-recursive-indent))
+ "")
+ ((eq (car-safe (car-safe tmp)) 'byte-code)
+ (princ "(<byte code>...)" stream)
+ (terpri stream)
+ (mapcar ;recurse on list of byte-code objects
+ (function (lambda (obj)
+ (disassemble-1
+ obj
+ stream
+ (+ indent disassemble-recursive-indent))))
+ tmp)
+ "")
+ ((and (eq tmp 'byte-code)
+ (eq (aref bytes (+ ptr 4)) (+ byte-call 3)))
+ ;; this won't catch cases where args are pushed w/
+ ;; constant2.
+ (setq ptr (+ ptr 4))
+ "<compiled call to byte-code. compiled code compiled?>")
+ (t
+ ;; really just a constant
+ (let ((print-escape-newlines t))
+ (prin1-to-string tmp)))))
+ (t "<error in disassembler>"))
+ stream))
+ (terpri stream)))
+ nil)
+
+
+(defun disassemble-offset ()
+ "Don't call this!"
+ ;; fetch and return the offset for the current opcode.
+ ;; return NIL if this opcode has no offset
+ ;; OP, PTR and BYTES are used and set dynamically
+ (let (tem)
+ (cond ((< op byte-nth)
+ (setq tem (logand op 7))
+ (setq op (logand op 248))
+ (cond ((eq tem 6)
+ (setq ptr (1+ ptr)) ;offset in next byte
+ (aref bytes ptr))
+ ((eq tem 7)
+ (setq ptr (1+ ptr)) ;offset in next 2 bytes
+ (+ (aref bytes ptr)
+ (progn (setq ptr (1+ ptr))
+ (lsh (aref bytes ptr) 8))))
+ (t tem))) ;offset was in opcode
+ ((>= op byte-constant)
+ (setq tem (- op byte-constant)) ;offset in opcode
+ (setq op byte-constant)
+ tem)
+ ((or (= op byte-constant2)
+ (and (>= op byte-goto)
+ (<= op byte-goto-if-not-nil-else-pop)))
+ (setq ptr (1+ ptr)) ;offset in next 2 bytes
+ (+ (aref bytes ptr)
+ (progn (setq ptr (1+ ptr))
+ (lsh (aref bytes ptr) 8))))
+ (t nil)))) ;no offset
+
+
+(defun write-spaces (n &optional stream)
+ "Print N spaces to (optional) STREAM."
+ (or stream (setq stream standard-output))
+ (if (< n 0) (setq n 0))
+ (if (eq stream (current-buffer))
+ (insert-char ?\ n)
+ (while (> n 0)
+ (write-char ?\ stream)
+ (setq n (1- n)))))
+
+(defconst byte-code-vector
+ '[<not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ (varref . 1)
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ (varset . -1)
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ (varbind . 0);Pops a value, "pushes" a binding
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ (call . -); #'-, not -1!
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ (unbind . -);"pops" bindings
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ (nth . -1)
+ symbolp
+ consp
+ stringp
+ listp
+ (eq . -1)
+ (memq . -1)
+ not
+ car
+ cdr
+ (cons . -1)
+ list1
+ (list2 . -1)
+ (list3 . -2)
+ (list4 . -3)
+ length
+ (aref . -1)
+ (aset . -2)
+ symbol-value
+ symbol-function
+ (set . -1)
+ (fset . -1)
+ (get . -1)
+ (substring . -2)
+ (concat2 . -1)
+ (concat3 . -2)
+ (concat4 . -3)
+ sub1
+ add1
+ (eqlsign . -1) ;=
+ (gtr . -1) ;>
+ (lss . -1) ;<
+ (leq . -1) ;<=
+ (geq . -1) ;>=
+ (diff . -1) ;-
+ negate ;unary -
+ (plus . -1) ;+
+ (max . -1)
+ (min . -1)
+ <not-an-opcode>
+ (point . 1)
+ (mark\(obsolete\) . 1)
+ goto-char
+ insert
+ (point-max . 1)
+ (point-min . 1)
+ char-after
+ (following-char . 1)
+ (preceding-char . 1)
+ (current-column . 1)
+ (indent-to . 1)
+ (scan-buffer\(obsolete\) . -2)
+ (eolp . 1)
+ (eobp . 1)
+ (bolp . 1)
+ (bobp . 1)
+ (current-buffer . 1)
+ set-buffer
+ (read-char . 1)
+ set-mark\(obsolete\)
+ interactive-p
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ (constant2 . 1)
+ goto;>>>
+ goto-if-nil;>>
+ goto-if-not-nil;>>
+ (goto-if-nil-else-pop . -1)
+ (goto-if-not-nil-else-pop . -1)
+ return
+ (discard . -1)
+ (dup . 1)
+ (save-excursion . 1);Pushes a binding
+ (save-window-excursion . 1);Pushes a binding
+ (save-restriction . 1);Pushes a binding
+ (catch . -1);Takes one argument, returns a value
+ (unwind-protect . 1);Takes one argument, pushes a binding, returns a value
+ (condition-case . -2);Takes three arguments, returns a value
+ (temp-output-buffer-setup . -1)
+ temp-output-buffer-show
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ <not-an-opcode>
+ (constant . 1)
+ ])
+
diff --git a/lisp/disass.elc b/lisp/disass.elc
new file mode 100644
index 00000000000..531c744c832
--- /dev/null
+++ b/lisp/disass.elc
Binary files differ
diff --git a/lisp/disp-table.el b/lisp/disp-table.el
deleted file mode 100644
index c0fe4dfe8af..00000000000
--- a/lisp/disp-table.el
+++ /dev/null
@@ -1,115 +0,0 @@
-;; Functions for dealing with char tables.
-;; Copyright (C) 1987 Free Software Foundation, Inc.
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 1, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
-
-;; Written by Howard Gayle. See case-table.el for details.
-
-(require 'case-table)
-
-(defun rope-to-vector (rope)
- (let* ((len (/ (length rope) 2))
- (vector (make-vector len nil))
- (i 0))
- (while (< i len)
- (aset vector i (rope-elt rope i))
- (setq i (1+ i)))))
-
-(defun describe-display-table (DT)
- "Describe the display-table DT in a help buffer."
- (with-output-to-temp-buffer "*Help*"
- (princ "\nTruncation glyf: ")
- (prin1 (aref dt 256))
- (princ "\nWrap glyf: ")
- (prin1 (aref dt 257))
- (princ "\nEscape glyf: ")
- (prin1 (aref dt 258))
- (princ "\nCtrl glyf: ")
- (prin1 (aref dt 259))
- (princ "\nSelective display rope: ")
- (prin1 (rope-to-vector (aref dt 260)))
- (princ "\nCharacter display ropes:\n")
- (let ((vector (make-vector 256 nil))
- (i 0))
- (while (< i 256)
- (aset vector i
- (if (stringp (aref dt i))
- (rope-to-vector (aref dt i))
- (aref dt i)))
- (setq i (1+ i)))
- (describe-vector vector))
- (print-help-return-message)))
-
-(defun describe-current-display-table ()
- "Describe the display-table in use in the selected window and buffer."
- (interactive)
- (describe-display-table
- (or (window-display-table (selected-window))
- buffer-display-table
- standard-display-table)))
-
-(defun make-display-table ()
- (make-vector 261 nil))
-
-(defun standard-display-8bit (l h)
- "Display characters in the range [L, H] literally."
- (while (<= l h)
- (if (and (>= l ?\ ) (< l 127))
- (if standard-display-table (aset standard-display-table l nil))
- (or standard-display-table
- (setq standard-display-table (make-vector 261 nil)))
- (aset standard-display-table l l))
- (setq l (1+ l))))
-
-(defun standard-display-ascii (c s)
- "Display character C using string S."
- (or standard-display-table
- (setq standard-display-table (make-vector 261 nil)))
- (aset standard-display-table c (apply 'make-rope (append s nil))))
-
-(defun standard-display-g1 (c sc)
- "Display character C as character SC in the g1 character set."
- (or standard-display-table
- (setq standard-display-table (make-vector 261 nil)))
- (aset standard-display-table c
- (make-rope (create-glyf (concat "\016" (char-to-string sc) "\017")))))
-
-(defun standard-display-graphic (c gc)
- "Display character C as character GC in graphics character set."
- (or standard-display-table
- (setq standard-display-table (make-vector 261 nil)))
- (aset standard-display-table c
- (make-rope (create-glyf (concat "\e(0" (char-to-string gc) "\e(B")))))
-
-(defun standard-display-underline (c uc)
- "Display character C as character UC plus underlining."
- (or standard-display-table
- (setq standard-display-table (make-vector 261 nil)))
- (aset standard-display-table c
- (make-rope (create-glyf (concat "\e[4m" (char-to-string uc) "\e[m")))))
-
-(defun create-glyf (string)
- (let ((i 256))
- (while (and (< i 65536) (aref glyf-table i)
- (not (string= (aref glyf-table i) string)))
- (setq i (1+ i)))
- (if (= i 65536)
- (error "No free glyf codes remain"))
- (aset glyf-table i string)))
-
-(provide 'disp-table)
diff --git a/lisp/play/dissociate.el b/lisp/dissociate.el
index b6ac2fa4ea8..6b5c373160b 100644
--- a/lisp/play/dissociate.el
+++ b/lisp/dissociate.el
@@ -54,12 +54,12 @@ Default is 2."
(setq start (point))
(if (eq move-function 'forward-char)
(progn
- (setq end (+ start (+ move-amount (random 16))))
+ (setq end (+ start (+ move-amount (logand 15 (random)))))
(if (> end (point-max))
- (setq end (+ 1 move-amount (random 16))))
+ (setq end (+ 1 move-amount (logand 15 (random)))))
(goto-char end))
(funcall move-function
- (+ move-amount (random 16))))
+ (+ move-amount (logand 15 (random)))))
(setq end (point)))
(let ((opoint (point)))
(insert-buffer-substring inbuf start end)
diff --git a/lisp/dissociate.elc b/lisp/dissociate.elc
new file mode 100644
index 00000000000..868787c4937
--- /dev/null
+++ b/lisp/dissociate.elc
Binary files differ
diff --git a/lisp/doctex.el b/lisp/doctex.el
new file mode 100644
index 00000000000..39a2e821ea1
--- /dev/null
+++ b/lisp/doctex.el
@@ -0,0 +1,189 @@
+;;; Grind GNU Emacs DOC file into LaTeX input
+;;; Copyright (C) 1987 Kyle E. Jones, Tor Lillqvist
+
+;;; This file may be redistributed provided the above copyright
+;;; notice appears on all copies and that the further free redistribution
+;;; of this file is not in any way restricted by those who
+;;; redistribute it.
+
+;;; Based on Kyle E. Jones's grind-DOC package.
+
+;;; This software is distributed 'as is', without warranties of any kind.
+
+;;; This file is not part of GNU Emacs.
+
+;;; The document that is the output from the (LaTeXify-DOC) function is
+;;; part of GNU Emacs.
+
+
+(defvar LaTeXify-DOC-style "report"
+ "*Should be bound to a string indicating what LaTeX document style
+should be used to format the DOC file. If this variable is set to nil
+the report style will be used.")
+
+(defvar LaTeXify-DOC-style-options ""
+ "*A string containing a list of document style options for LaTeX")
+
+(defun LaTeXify-DOC () (interactive)
+ "Reads the etc/DOC-xx.xx.x file into a buffer and converts it to a form
+suitable as LaTeX input."
+ ;
+ ; Make sure we can deal with the macro package and the point size.
+ ;
+ (cond
+ ((not (stringp LaTeXify-DOC-style))
+ (error "LaTeXify-DOC-style must be a string")))
+ ;
+ ; Select the DOC file.
+ ;
+ (find-file (expand-file-name
+ (if (fboundp 'dump-emacs)
+ (concat "DOC-" emacs-version)
+ "DOC")
+ exec-directory))
+ (setq buffer-read-only nil)
+ (auto-save-mode 0)
+ (set-visited-file-name (concat (buffer-file-name) ".tex"))
+ (delete-other-windows)
+ ;
+ ; Save-excursion just in case the DOC file was already selected.
+ ;
+ (save-excursion
+ (let (case-fold-search mode-line-format varstart-point bufstring name odot)
+ ;
+ ; The first thing we must do is convert the \[COMMAND] sequences
+ ; into the keys that the COMMANDs are bound to.
+ ;
+ (setq mode-line-format
+ " Grinding the DOC file... be patient.")
+ (sit-for 0)
+ (replace-regexp "\\\\{\\(\\s_\\|\\sw\\)*}"
+ "]]bgroup]]obeylines\\&]]egroup")
+ (setq bufstring (substitute-command-keys (buffer-string)))
+ (erase-buffer)
+ (insert bufstring)
+ ;
+ ; Here we make each docstring begin and end with C-_ for
+ ; easier manipulation. This is undone later.
+ ;
+ (goto-char (1+ (point-min)))
+ (replace-string "\C-_" "\C-_\C-_" nil)
+ (goto-char (point-max))
+ (insert "\C-_")
+ ;
+ ; Sort the docstrings. This implicitly separates function
+ ; documentation from the variable documentation.
+ ;
+ (sort-regexp-fields nil "\C-_\\([FV].*\\)[^\C-_]*\C-_" "\\1"
+ (point-min) (point-max))
+ ;
+ ; Handle TeX special characters
+ ;
+ (goto-char (point-min))
+ (mapcar
+ '(lambda (x) (save-excursion (eval x)))
+ '((replace-string "#" "]]#")
+ (replace-string "$" "]]$")
+ (replace-string "%" "]]%")
+ (replace-string "&" "]]&")
+ (replace-string "~" "]]verb+~+")
+ (replace-string "_" "]]verb+_+")
+ (replace-string "^" "]]verb+^+")
+ (replace-string "\\" "]]verb+]]+")
+ (replace-string "{" "]]{")
+ (replace-string "}" "]]}")
+ (replace-string "<" "]]verb+<+")
+ (replace-string ">" "]]verb+>+")
+ (replace-string "]]" "\\")))
+ ;
+ ; Now add the indentation commands and put ( ...) around the functions
+ ;
+ (save-restriction
+ (goto-char (point-min))
+ (search-forward "\C-_V" (point-max) nil 1)
+ (backward-char 2)
+ (narrow-to-region (point-min) (dot))
+ (goto-char (point-min))
+ (insert "\\section*{Functions}\n"
+ "\\begin{description}\n")
+ (while (search-forward "\C-_F" (point-max) t 1)
+ (delete-char -2)
+ (insert "\n\\item[\\sf(")
+ (end-of-line 1)
+ (insert " ...)]")
+ (search-forward "\C-_" (point-max) nil 1)
+ (delete-char -1))
+ (insert "\\end{description}\n"))
+ (insert "\\section*{Variables}
+Variables whose documentation begins with an
+asterisk `*' are user definable options. These variables are
+used to customize Emacs. Other variables are generally of
+interest only to Emacs Lisp programmers.
+\\begin{description}\n")
+ (while (search-forward "\C-_V" (point-max) t 1)
+ (delete-char -2)
+ (insert "\n\\item[\\sf ")
+ (end-of-line 1)
+ (insert "]")
+ (search-forward "\C-_" (point-max) nil 1)
+ (delete-char -1))
+ (insert "\\end{description}\n"
+ "\\end{document}\n")
+ ;
+ ; Try to make those parameters that are in all-caps look better
+ ;
+ (goto-char (point-min))
+ (mapcar
+ '(lambda (x) (save-excursion (eval x)))
+ '((replace-regexp "[A-Z][A-Z]+" "\n{\\\\lowercase{\\\\sf \\&}}" nil)
+ (replace-string "\\lowercase{\\sf TAB}" "{\\tt TAB}")
+ (replace-string "\\lowercase{\\sf LFD}" "{\\tt LFD}")
+ (replace-string "\\lowercase{\\sf RET}" "{\\tt RET}")
+ (replace-string "\\lowercase{\\sf ESC}" "{\\tt ESC}")
+ (replace-string "\\lowercase{\\sf SPC}" "{\\tt SPC}")
+ (replace-string "\\lowercase{\\sf DEL}" "{\\tt DEL}")))
+ ;
+ ; Handle document style and front matter
+ ;
+ (goto-char (point-min))
+ (insert "\\documentstyle["
+ LaTeXify-DOC-style-options
+ "]{" LaTeXify-DOC-style "}\n"
+ "\\begin{document}\n"
+ "\\title{GNU Emacs Lisp Reference \\\\\n"
+ "Version " emacs-version " \\\\\n"
+ "\\large (gouged with a blunt instrument from the DOC file)}\n"
+ "\\author{Richard M. Stallman}\n"
+ "\\date{" (substring emacs-build-time 4 8)
+ (substring emacs-build-time 20) "}\n"
+ "\\maketitle\n")
+ ;
+ ; Insert the GNU Emacs copyright notice.
+ ;
+ (insert
+ "\\begin{centering}\n"
+ "Copyright \\copyright" (substring emacs-build-time 20)
+ " Free Software Foundation, Inc. \\\\\n"
+ "\\end{centering}
+\\vspace{\\baselineskip}
+\\noindent
+This document is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+\\newpage\\sloppy\n")
+ ;
+ ; That's it
+ ;
+ (message "Grinding completed. Behold!"))))
diff --git a/lisp/doctor.el b/lisp/doctor.el
new file mode 100644
index 00000000000..3c85b7227de
--- /dev/null
+++ b/lisp/doctor.el
@@ -0,0 +1,1614 @@
+;; Psychological help for frustrated users.
+;; Copyright (C) 1985, 1987 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 1, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+(defun doctor-cadr (x) (car (cdr x)))
+(defun doctor-caddr (x) (car (cdr (cdr x))))
+(defun doctor-cddr (x) (cdr (cdr x)))
+
+(defun doctor-member (x y)
+ "Like memq, but uses equal for comparison"
+ (while (and y (not (equal x (car y))))
+ (setq y (cdr y)))
+ y)
+
+(defun random-range (top)
+ "Return a random nonnegative integer less than TOP."
+ (let ((tem (% (random) top)))
+ (if (< tem 0) (- tem) tem)))
+
+(defun // (x) x)
+
+(defmacro $ (what)
+ "quoted arg form of doctor-$"
+ (list 'doctor-$ (list 'quote what)))
+
+(defun doctor-$ (what)
+ "Return the car of a list, rotating the list each time"
+ (let* ((vv (symbol-value what))
+ (first (car vv))
+ (ww (append (cdr vv) (list first))))
+ (set what ww)
+ first))
+
+(defvar doctor-mode-map nil)
+(if doctor-mode-map
+ nil
+ (setq doctor-mode-map (make-sparse-keymap))
+ (define-key doctor-mode-map "\n" 'doctor-read-print)
+ (define-key doctor-mode-map "\r" 'doctor-ret-or-read))
+
+(defun doctor-mode ()
+ "Major mode for running the Doctor (Eliza) program.
+Like Text mode with Auto Fill mode
+except that RET when point is after a newline, or LFD at any time,
+reads the sentence before point, and prints the Doctor's answer."
+ (interactive)
+ (text-mode)
+ (make-doctor-variables)
+ (use-local-map doctor-mode-map)
+ (setq major-mode 'doctor-mode)
+ (setq mode-name "Doctor")
+ (turn-on-auto-fill)
+ (doctor-type '(i am the psychotherapist \.
+ ($ please) ($ describe) your ($ problems) \.
+ each time you are finished talking, type \R\E\T twice \.))
+ (insert "\n"))
+
+(defun make-doctor-variables ()
+ (make-local-variable 'monosyllables)
+ (setq monosyllables
+ "
+ Your attitude at the end of the session was wholly unacceptable.
+ Please try to come back next time with a willingness to speak more
+ freely. If you continue to refuse to talk openly, there is little
+ I can do to help!
+")
+ (make-local-variable 'typos)
+ (setq typos
+ (mapcar (function (lambda (x)
+ (put (car x) 'doctor-correction (doctor-cadr x))
+ (put (doctor-cadr x) 'doctor-expansion (doctor-caddr x))
+ (car x)))
+ '((theyll they\'ll (they will))
+ (theyre they\'re (they are))
+ (hes he\'s (he is))
+ (he7s he\'s (he is))
+ (im i\'m (you are))
+ (i7m i\'m (you are))
+ (isa is\ a (is a))
+ (thier their (their))
+ (dont don\'t (do not))
+ (don7t don\'t (do not))
+ (you7re you\'re (i am))
+ (you7ve you\'ve (i have))
+ (you7ll you\'ll (i will)))))
+ (make-local-variable 'found)
+ (setq found nil)
+ (make-local-variable 'owner)
+ (setq owner nil)
+ (make-local-variable 'history)
+ (setq history nil)
+ (make-local-variable '*debug*)
+ (setq *debug* nil)
+ (make-local-variable 'inter)
+ (setq inter
+ '((well\,)
+ (hmmm \.\.\.\ so\,)
+ (so)
+ (\.\.\.and)
+ (then)))
+ (make-local-variable 'continue)
+ (setq continue
+ '((continue)
+ (proceed)
+ (go on)
+ (keep going) ))
+ (make-local-variable 'relation)
+ (setq relation
+ '((your relationship with)
+ (something you remember about)
+ (your feelings toward)
+ (some experiences you have had with)
+ (how you feel about)))
+ (make-local-variable 'fears)
+ (setq fears '( (($ whysay) you are ($ afraidof) (// feared) \?)
+ (you seem terrified by (// feared) \.)
+ (when did you first feel ($ afraidof) (// feared) \?) ))
+ (make-local-variable 'sure)
+ (setq sure '((sure)(positive)(certain)(absolutely sure)))
+ (make-local-variable 'afraidof)
+ (setq afraidof '( (afraid of) (frightened by) (scared of) ))
+ (make-local-variable 'areyou)
+ (setq areyou '( (are you)(have you been)(have you been) ))
+ (make-local-variable 'isrelated)
+ (setq isrelated '( (has something to do with)(is related to)
+ (could be the reason for) (is caused by)(is because of)))
+ (make-local-variable 'arerelated)
+ (setq arerelated '((have something to do with)(are related to)
+ (could have caused)(could be the reason for) (are caused by)
+ (are because of)))
+ (make-local-variable 'moods)
+ (setq moods '( (($ areyou)(// found) often \?)
+ (what causes you to be (// found) \?)
+ (($ whysay) you are (// found) \?) ))
+ (make-local-variable 'maybe)
+ (setq maybe
+ '((maybe)
+ (perhaps)
+ (possibly)))
+ (make-local-variable 'whatwhen)
+ (setq whatwhen
+ '((what happened when)
+ (what would happen if)))
+ (make-local-variable 'hello)
+ (setq hello
+ '((how do you do \?) (hello \.) (howdy!) (hello \.) (hi \.) (hi there \.)))
+ (make-local-variable 'drnk)
+ (setq drnk
+ '((do you drink a lot of (// found) \?)
+ (do you get drunk often \?)
+ (($ describe) your drinking habits \.) ))
+ (make-local-variable 'drugs)
+ (setq drugs '( (do you use (// found) often \?)(($ areyou)
+ addicted to (// found) \?)(do you realize that drugs can
+ be very harmful \?)(($ maybe) you should try to quit using (// found)
+ \.)))
+ (make-local-variable 'whywant)
+ (setq whywant '( (($ whysay) (// subj) might ($ want) (// obj) \?)
+ (how does it feel to want \?)
+ (why should (// subj) get (// obj) \?)
+ (when did (// subj) first ($ want) (// obj) \?)
+ (($ areyou) obsessed with (// obj) \?)
+ (why should i give (// obj) to (// subj) \?)
+ (have you ever gotten (// obj) \?) ))
+ (make-local-variable 'canyou)
+ (setq canyou '((of course i can \.)
+ (why should i \?)
+ (what makes you think i would even want to \?)
+ (i am the doctor\, i can do anything i damn please \.)
+ (not really\, it\'s not up to me \.)
+ (depends\, how important is it \?)
+ (i could\, but i don\'t think it would be a wise thing to do \.)
+ (can you \?)
+ (maybe i can\, maybe i can\'t \.\.\.)
+ (i don\'t think i should do that \.)))
+ (make-local-variable 'want)
+ (setq want '( (want) (desire) (wish) (want) (hope) ))
+ (make-local-variable 'shortlst)
+ (setq shortlst
+ '((can you elaborate on that \?)
+ (($ please) continue \.)
+ (go on\, don\'t be afraid \.)
+ (i need a little more detail please \.)
+ (you\'re being a bit brief\, ($ please) go into detail \.)
+ (can you be more explicit \?)
+ (and \?)
+ (($ please) go into more detail \?)
+ (you aren\'t being very talkative today\!)
+ (is that all there is to it \?)
+ (why must you respond so briefly \?)))
+
+ (make-local-variable 'famlst)
+ (setq famlst
+ '((tell me ($ something) about (// owner) family \.)
+ (you seem to dwell on (// owner) family \.)
+ (($ areyou) hung up on (// owner) family \?)))
+ (make-local-variable 'huhlst)
+ (setq huhlst
+ '((($ whysay)(// sent) \?)
+ (is it because of ($ things) that you say (// sent) \?) ))
+ (make-local-variable 'longhuhlst)
+ (setq longhuhlst
+ '((($ whysay) that \?)
+ (i don\'t understand \.)
+ (($ thlst))
+ (($ areyou) ($ afraidof) that \?)))
+ (make-local-variable 'feelings)
+ (setq feelings-about
+ '((feelings about)
+ (aprehensions toward)
+ (thoughts on)
+ (emotions toward)))
+ (make-local-variable 'random)
+ (setq random-adjective
+ '((vivid)
+ (emotionally stimulating)
+ (exciting)
+ (boring)
+ (interesting)
+ (recent)
+ (random) ;How can we omit this?
+ (unusual)
+ (shocking)
+ (embarrassing)))
+ (make-local-variable 'whysay)
+ (setq whysay
+ '((why do you say)
+ (what makes you believe)
+ (are you sure that)
+ (do you really think)
+ (what makes you think) ))
+ (make-local-variable 'isee)
+ (setq isee
+ '((i see \.\.\.)
+ (yes\,)
+ (i understand \.)
+ (oh \.) ))
+ (make-local-variable 'please)
+ (setq please
+ '((please\,)
+ (i would appreciate it if you would)
+ (perhaps you could)
+ (please\,)
+ (would you please)
+ (why don\'t you)
+ (could you)))
+ (make-local-variable 'bye)
+ (setq bye
+ '((my secretary will send you a bill \.)
+ (bye bye \.)
+ (see ya \.)
+ (ok\, talk to you some other time \.)
+ (talk to you later \.)
+ (ok\, have fun \.)
+ (ciao \.)))
+ (make-local-variable 'something)
+ (setq something
+ '((something)
+ (more)
+ (how you feel)))
+ (make-local-variable 'things)
+ (setq things
+ '(;(your interests in computers) ;; let's make this less computer oriented
+ ;(the machines you use)
+ (your plans)
+ ;(your use of computers)
+ (your life)
+ ;(other machines you use)
+ (the people you hang around with)
+ ;(computers you like)
+ (problems at school)
+ (any hobbies you have)
+ ;(other computers you use)
+ (your sex life)
+ (hangups you have)
+ (your inhibitions)
+ (some problems in your childhood)
+ ;(knowledge of computers)
+ (some problems at home)))
+ (make-local-variable 'describe)
+ (setq describe
+ '((describe)
+ (tell me about)
+ (talk about)
+ (discuss)
+ (tell me more about)
+ (elaborate on)))
+ (make-local-variable 'ibelieve)
+ (setq ibelieve
+ '((i believe) (i think) (i have a feeling) (it seems to me that)
+ (it looks like)))
+ (make-local-variable 'problems)
+ (setq problems '( (problems)
+ (inhibitions)
+ (hangups)
+ (difficulties)
+ (anxieties)
+ (frustrations) ))
+ (make-local-variable 'bother)
+ (setq bother
+ '((does it bother you that)
+ (are you annoyed that)
+ (did you ever regret)
+ (are you sorry)
+ (are you satisfied with the fact that)))
+ (make-local-variable 'machlst)
+ (setq machlst
+ '((you have your mind on (// found) \, it seems \.)
+ (you think too much about (// found) \.)
+ (you should try taking your mind off of (// found)\.)
+ (are you a computer hacker \?)))
+ (make-local-variable 'qlist)
+ (setq qlist
+ '((what do you think \?)
+ (i\'ll ask the questions\, if you don\'t mind!)
+ (i could ask the same thing myself \.)
+ (($ please) allow me to do the questioning \.)
+ (i have asked myself that question many times \.)
+ (($ please) try to answer that question yourself \.)))
+ (make-local-variable 'elist)
+ (setq elist
+ '((($ please) try to calm yourself \.)
+ (you seem very excited \. relax \. ($ please) ($ describe) ($ things)
+ \.)
+ (you\'re being very emotional \. calm down \.)))
+ (make-local-variable 'foullst)
+ (setq foullst
+ '((($ please) watch your tongue!)
+ (($ please) avoid such unwholesome thoughts \.)
+ (($ please) get your mind out of the gutter \.)
+ (such lewdness is not appreciated \.)))
+ (make-local-variable 'deathlst)
+ (setq deathlst
+ '((this is not a healthy way of thinking \.)
+ (($ bother) you\, too\, may die someday \?)
+ (i am worried by your obssession with this topic!)
+ (did you watch a lot of crime and violence on television as a child \?))
+ )
+ (make-local-variable 'sexlst)
+ (setq sexlst
+ '((($ areyou) ($ afraidof) sex \?)
+ (($ describe)($ something) about your sexual history \.)
+ (($ please)($ describe) your sex life \.\.\.)
+ (($ describe) your ($ feelings-about) your sexual partner \.)
+ (($ describe) your most ($ random-adjective) sexual experience \.)
+ (($ areyou) satisfied with (// lover) \.\.\. \?)))
+ (make-local-variable 'neglst)
+ (setq neglst
+ '((why not \?)
+ (($ bother) i ask that \?)
+ (why not \?)
+ (why not \?)
+ (how come \?)
+ (($ bother) i ask that \?)))
+ (make-local-variable 'beclst)
+ (setq beclst '(
+ (is it because (// sent) that you came to me \?)
+ (($ bother)(// sent) \?)
+ (when did you first know that (// sent) \?)
+ (is the fact that (// sent) the real reason \?)
+ (does the fact that (// sent) explain anything else \?)
+ (($ areyou)($ sure)(// sent) \? ) ))
+ (make-local-variable 'shortbeclst)
+ (setq shortbeclst '(
+ (($ bother) i ask you that \?)
+ (that\'s not much of an answer!)
+ (($ inter) why won\'t you talk about it \?)
+ (speak up!)
+ (($ areyou) ($ afraidof) talking about it \?)
+ (don\'t be ($ afraidof) elaborating \.)
+ (($ please) go into more detail \.)))
+ (make-local-variable 'thlst)
+ (setq thlst '(
+ (($ maybe)($ things)($ arerelated) this \.)
+ (is it because of ($ things) that you are going through all this \?)
+ (how do you reconcile ($ things) \? )
+ (($ maybe) this ($ isrelated)($ things) \?) ))
+ (make-local-variable 'remlst)
+ (setq remlst '( (earlier you said ($ history) \?)
+ (you mentioned that ($ history) \?)
+ (($ whysay)($ history) \? ) ))
+ (make-local-variable 'toklst)
+ (setq toklst
+ '((is this how you relax \?)
+ (how long have you been smoking grass \?)
+ (($ areyou) ($ afraidof) of being drawn to using harder stuff \?)))
+ (make-local-variable 'states)
+ (setq states
+ '((do you get (// found) often \?)
+ (do you enjoy being (// found) \?)
+ (what makes you (// found) \?)
+ (how often ($ areyou)(// found) \?)
+ (when were you last (// found) \?)))
+ (make-local-variable 'replist)
+ (setq replist
+ '((i . (you))
+ (my . (your))
+ (me . (you))
+ (you . (me))
+ (your . (my))
+ (mine . (yours))
+ (yours . (mine))
+ (our . (your))
+ (ours . (yours))
+ (we . (you))
+ (dunno . (do not know))
+;; (yes . ())
+ (no\, . ())
+ (yes\, . ())
+ (ya . (i))
+ (aint . (am not))
+ (wanna . (want to))
+ (gimme . (give me))
+ (gotta . (have to))
+ (gonna . (going to))
+ (never . (not ever))
+ (doesn\'t . (does not))
+ (don\'t . (do not))
+ (aren\'t . (are not))
+ (isn\'t . (is not))
+ (won\'t . (will not))
+ (can\'t . (cannot))
+ (haven\'t . (have not))
+ (i\'m . (you are))
+ (ourselves . (yourselves))
+ (myself . (yourself))
+ (yourself . (myself))
+ (you\'re . (i am))
+ (you\'ve . (i have))
+ (i\'ve . (you have))
+ (i\'ll . (you will))
+ (you\'ll . (i shall))
+ (i\'d . (you would))
+ (you\'d . (i would))
+ (here . (there))
+ (please . ())
+ (eh\, . ())
+ (eh . ())
+ (oh\, . ())
+ (oh . ())
+ (shouldn\'t . (should not))
+ (wouldn\'t . (would not))
+ (won\'t . (will not))
+ (hasn\'t . (has not))))
+ (make-local-variable 'stallmanlst)
+ (setq stallmanlst '(
+ (($ describe) your ($ feelings-about) him \.)
+ (($ areyou) a friend of Stallman \?)
+ (($ bother) Stallman is ($ random-adjective) \?)
+ (($ ibelieve) you are ($ afraidof) him \.)))
+ (make-local-variable 'schoollst)
+ (setq schoollst '(
+ (($ describe) your (// found) \.)
+ (($ bother) your grades could ($ improve) \?)
+ (($ areyou) ($ afraidof) (// found) \?)
+ (($ maybe) this ($ isrelated) to your attitude \.)
+ (($ areyou) absent often \?)
+ (($ maybe) you should study ($ something) \.)))
+ (make-local-variable 'improve)
+ (setq improve '((improve) (be better) (be improved) (be higher)))
+ (make-local-variable 'elizalst)
+ (setq elizalst '(
+ (($ areyou) ($ sure) \?)
+ (($ ibelieve) you have ($ problems) with (// found) \.)
+ (($ whysay) (// sent) \?)))
+ (make-local-variable 'sportslst)
+ (setq sportslst '(
+ (tell me ($ something) about (// found) \.)
+ (($ describe) ($ relation) (// found) \.)
+ (do you find (// found) ($ random-adjective) \?)))
+ (make-local-variable 'mathlst)
+ (setq mathlst '(
+ (($ describe) ($ something) about math \.)
+ (($ maybe) your ($ problems) ($ arerelated) (// found) \.)
+ (i do\'nt know much (// found) \, but ($ continue)
+ anyway \.)))
+ (make-local-variable 'zippylst)
+ (setq zippylst '(
+ (($ areyou) Zippy \?)
+ (($ ibelieve) you have some serious ($ problems) \.)
+ (($ bother) you are a pinhead \?)))
+ (make-local-variable 'chatlst)
+ (setq chatlst '(
+ (($ maybe) we could chat \.)
+ (($ please) ($ describe) ($ something) about chat mode \.)
+ (($ bother) our discussion is so ($ random-adjective) \?)))
+ (make-local-variable 'abuselst)
+ (setq abuselst '(
+ (($ please) try to be less abusive \.)
+ (($ describe) why you call me (// found) \.)
+ (i\'ve had enough of you!)))
+ (make-local-variable 'abusewords)
+ (setq abusewords '(boring bozo clown clumsy cretin dumb dummy
+ fool foolish gnerd gnurd idiot jerk
+ lose loser louse lousy luse luser
+ moron nerd nurd oaf oafish reek
+ stink stupid tool toolish twit))
+ (make-local-variable 'howareyoulst)
+ (setq howareyoulst '((how are you) (hows it going) (hows it going eh)
+ (how\'s it going) (how\'s it going eh) (how goes it)
+ (whats up) (whats new) (what\'s up) (what\'s new)
+ (howre you) (how\'re you) (how\'s everything)
+ (how is everything) (how do you do)
+ (how\'s it hanging) (que pasa)
+ (how are you doing) (what do you say)))
+ (make-local-variable 'whereoutp)
+ (setq whereoutp '( huh remem rthing ) )
+ (make-local-variable 'subj)
+ (setq subj nil)
+ (make-local-variable 'verb)
+ (setq verb nil)
+ (make-local-variable 'obj)
+ (setq obj nil)
+ (make-local-variable 'feared)
+ (setq feared nil)
+ (make-local-variable 'observation-list)
+ (setq observation-list nil)
+ (make-local-variable 'repetitive-shortness)
+ (setq repetitive-shortness '(0 . 0))
+ (make-local-variable '**mad**)
+ (setq **mad** nil)
+ (make-local-variable 'rms-flag)
+ (setq rms-flag nil)
+ (make-local-variable 'eliza-flag)
+ (setq eliza-flag nil)
+ (make-local-variable 'zippy-flag)
+ (setq zippy-flag nil)
+ (make-local-variable 'lover)
+ (setq lover '(your partner))
+ (make-local-variable 'bak)
+ (setq bak nil)
+ (make-local-variable 'lincount)
+ (setq lincount 0)
+ (make-local-variable '*print-upcase*)
+ (setq *print-upcase* nil)
+ (make-local-variable '*print-space*)
+ (setq *print-space* nil)
+ (make-local-variable 'howdyflag)
+ (setq howdyflag nil)
+ (make-local-variable 'object)
+ (setq object nil))
+
+;; Define equivalence classes of words that get treated alike.
+
+(defun doctor-meaning (x) (get x 'doctor-meaning))
+
+(defmacro doctor-put-meaning (symb val)
+ "Store the base meaning of a word on the property list"
+ (list 'put (list 'quote symb) ''doctor-meaning val))
+
+(doctor-put-meaning howdy 'howdy)
+(doctor-put-meaning hi 'howdy)
+(doctor-put-meaning greetings 'howdy)
+(doctor-put-meaning hello 'howdy)
+(doctor-put-meaning tops20 'mach)
+(doctor-put-meaning tops-20 'mach)
+(doctor-put-meaning tops 'mach)
+(doctor-put-meaning pdp11 'mach)
+(doctor-put-meaning computer 'mach)
+(doctor-put-meaning unix 'mach)
+(doctor-put-meaning machine 'mach)
+(doctor-put-meaning computers 'mach)
+(doctor-put-meaning machines 'mach)
+(doctor-put-meaning pdp11s 'mach)
+(doctor-put-meaning foo 'mach)
+(doctor-put-meaning foobar 'mach)
+(doctor-put-meaning multics 'mach)
+(doctor-put-meaning macsyma 'mach)
+(doctor-put-meaning teletype 'mach)
+(doctor-put-meaning la36 'mach)
+(doctor-put-meaning vt52 'mach)
+(doctor-put-meaning zork 'mach)
+(doctor-put-meaning trek 'mach)
+(doctor-put-meaning startrek 'mach)
+(doctor-put-meaning advent 'mach)
+(doctor-put-meaning pdp 'mach)
+(doctor-put-meaning dec 'mach)
+(doctor-put-meaning commodore 'mach)
+(doctor-put-meaning vic 'mach)
+(doctor-put-meaning bbs 'mach)
+(doctor-put-meaning modem 'mach)
+(doctor-put-meaning baud 'mach)
+(doctor-put-meaning macintosh 'mach)
+(doctor-put-meaning vax 'mach)
+(doctor-put-meaning vms 'mach)
+(doctor-put-meaning ibm 'mach)
+(doctor-put-meaning pc 'mach)
+(doctor-put-meaning bitching 'foul)
+(doctor-put-meaning shit 'foul)
+(doctor-put-meaning bastard 'foul)
+(doctor-put-meaning damn 'foul)
+(doctor-put-meaning damned 'foul)
+(doctor-put-meaning hell 'foul)
+(doctor-put-meaning suck 'foul)
+(doctor-put-meaning sucking 'foul)
+(doctor-put-meaning sux 'foul)
+(doctor-put-meaning ass 'foul)
+(doctor-put-meaning whore 'foul)
+(doctor-put-meaning bitch 'foul)
+(doctor-put-meaning asshole 'foul)
+(doctor-put-meaning shrink 'foul)
+(doctor-put-meaning pot 'toke)
+(doctor-put-meaning grass 'toke)
+(doctor-put-meaning weed 'toke)
+(doctor-put-meaning marijuana 'toke)
+(doctor-put-meaning acapulco 'toke)
+(doctor-put-meaning columbian 'toke)
+(doctor-put-meaning tokin 'toke)
+(doctor-put-meaning joint 'toke)
+(doctor-put-meaning toke 'toke)
+(doctor-put-meaning toking 'toke)
+(doctor-put-meaning tokin\' 'toke)
+(doctor-put-meaning toked 'toke)
+(doctor-put-meaning roach 'toke)
+(doctor-put-meaning pills 'drug)
+(doctor-put-meaning dope 'drug)
+(doctor-put-meaning acid 'drug)
+(doctor-put-meaning lsd 'drug)
+(doctor-put-meaning speed 'drug)
+(doctor-put-meaning heroin 'drug)
+(doctor-put-meaning hash 'drug)
+(doctor-put-meaning cocaine 'drug)
+(doctor-put-meaning uppers 'drug)
+(doctor-put-meaning downers 'drug)
+(doctor-put-meaning loves 'loves)
+(doctor-put-meaning love 'love)
+(doctor-put-meaning loved 'love)
+(doctor-put-meaning hates 'hates)
+(doctor-put-meaning dislikes 'hates)
+(doctor-put-meaning hate 'hate)
+(doctor-put-meaning hated 'hate)
+(doctor-put-meaning dislike 'hate)
+(doctor-put-meaning stoned 'state)
+(doctor-put-meaning drunk 'state)
+(doctor-put-meaning drunken 'state)
+(doctor-put-meaning high 'state)
+(doctor-put-meaning horny 'state)
+(doctor-put-meaning blasted 'state)
+(doctor-put-meaning happy 'state)
+(doctor-put-meaning paranoid 'state)
+(doctor-put-meaning wish 'desire)
+(doctor-put-meaning wishes 'desire)
+(doctor-put-meaning want 'desire)
+(doctor-put-meaning desire 'desire)
+(doctor-put-meaning like 'desire)
+(doctor-put-meaning hope 'desire)
+(doctor-put-meaning hopes 'desire)
+(doctor-put-meaning desires 'desire)
+(doctor-put-meaning wants 'desire)
+(doctor-put-meaning desires 'desire)
+(doctor-put-meaning likes 'desire)
+(doctor-put-meaning needs 'desire)
+(doctor-put-meaning need 'desire)
+(doctor-put-meaning frustrated 'mood)
+(doctor-put-meaning depressed 'mood)
+(doctor-put-meaning annoyed 'mood)
+(doctor-put-meaning upset 'mood)
+(doctor-put-meaning unhappy 'mood)
+(doctor-put-meaning excited 'mood)
+(doctor-put-meaning worried 'mood)
+(doctor-put-meaning lonely 'mood)
+(doctor-put-meaning angry 'mood)
+(doctor-put-meaning mad 'mood)
+(doctor-put-meaning pissed 'mood)
+(doctor-put-meaning jealous 'mood)
+(doctor-put-meaning afraid 'fear)
+(doctor-put-meaning terrified 'fear)
+(doctor-put-meaning fear 'fear)
+(doctor-put-meaning scared 'fear)
+(doctor-put-meaning frightened 'fear)
+(doctor-put-meaning virginity 'sexnoun)
+(doctor-put-meaning virgins 'sexnoun)
+(doctor-put-meaning virgin 'sexnoun)
+(doctor-put-meaning cock 'sexnoun)
+(doctor-put-meaning cocks 'sexnoun)
+(doctor-put-meaning dick 'sexnoun)
+(doctor-put-meaning dicks 'sexnoun)
+(doctor-put-meaning cunt 'sexnoun)
+(doctor-put-meaning cunts 'sexnoun)
+(doctor-put-meaning prostitute 'sexnoun)
+(doctor-put-meaning condom 'sexnoun)
+(doctor-put-meaning sex 'sexnoun)
+(doctor-put-meaning rapes 'sexnoun)
+(doctor-put-meaning wife 'family)
+(doctor-put-meaning family 'family)
+(doctor-put-meaning brothers 'family)
+(doctor-put-meaning sisters 'family)
+(doctor-put-meaning parent 'family)
+(doctor-put-meaning parents 'family)
+(doctor-put-meaning brother 'family)
+(doctor-put-meaning sister 'family)
+(doctor-put-meaning father 'family)
+(doctor-put-meaning mother 'family)
+(doctor-put-meaning husband 'family)
+(doctor-put-meaning siblings 'family)
+(doctor-put-meaning grandmother 'family)
+(doctor-put-meaning grandfather 'family)
+(doctor-put-meaning maternal 'family)
+(doctor-put-meaning paternal 'family)
+(doctor-put-meaning stab 'death)
+(doctor-put-meaning murder 'death)
+(doctor-put-meaning murders 'death)
+(doctor-put-meaning suicide 'death)
+(doctor-put-meaning suicides 'death)
+(doctor-put-meaning kill 'death)
+(doctor-put-meaning kills 'death)
+(doctor-put-meaning die 'death)
+(doctor-put-meaning dies 'death)
+(doctor-put-meaning died 'death)
+(doctor-put-meaning dead 'death)
+(doctor-put-meaning death 'death)
+(doctor-put-meaning deaths 'death)
+(doctor-put-meaning pain 'symptoms)
+(doctor-put-meaning ache 'symptoms)
+(doctor-put-meaning fever 'symptoms)
+(doctor-put-meaning sore 'symptoms)
+(doctor-put-meaning aching 'symptoms)
+(doctor-put-meaning stomachache 'symptoms)
+(doctor-put-meaning headache 'symptoms)
+(doctor-put-meaning hurts 'symptoms)
+(doctor-put-meaning disease 'symptoms)
+(doctor-put-meaning virus 'symptoms)
+(doctor-put-meaning vomit 'symptoms)
+(doctor-put-meaning vomiting 'symptoms)
+(doctor-put-meaning barf 'symptoms)
+(doctor-put-meaning toothache 'symptoms)
+(doctor-put-meaning hurt 'symptoms)
+(doctor-put-meaning rum 'alcohol)
+(doctor-put-meaning gin 'alcohol)
+(doctor-put-meaning vodka 'alcohol)
+(doctor-put-meaning alcohol 'alcohol)
+(doctor-put-meaning bourbon 'alcohol)
+(doctor-put-meaning beer 'alcohol)
+(doctor-put-meaning wine 'alcohol)
+(doctor-put-meaning whiskey 'alcohol)
+(doctor-put-meaning scotch 'alcohol)
+(doctor-put-meaning fuck 'sexverb)
+(doctor-put-meaning fucked 'sexverb)
+(doctor-put-meaning screw 'sexverb)
+(doctor-put-meaning screwing 'sexverb)
+(doctor-put-meaning fucking 'sexverb)
+(doctor-put-meaning rape 'sexverb)
+(doctor-put-meaning raped 'sexverb)
+(doctor-put-meaning kiss 'sexverb)
+(doctor-put-meaning kissing 'sexverb)
+(doctor-put-meaning kisses 'sexverb)
+(doctor-put-meaning screws 'sexverb)
+(doctor-put-meaning fucks 'sexverb)
+(doctor-put-meaning because 'conj)
+(doctor-put-meaning but 'conj)
+(doctor-put-meaning however 'conj)
+(doctor-put-meaning besides 'conj)
+(doctor-put-meaning anyway 'conj)
+(doctor-put-meaning that 'conj)
+(doctor-put-meaning except 'conj)
+(doctor-put-meaning why 'conj)
+(doctor-put-meaning how 'conj)
+(doctor-put-meaning until 'when)
+(doctor-put-meaning when 'when)
+(doctor-put-meaning whenever 'when)
+(doctor-put-meaning while 'when)
+(doctor-put-meaning since 'when)
+(doctor-put-meaning rms 'rms)
+(doctor-put-meaning stallman 'rms)
+(doctor-put-meaning school 'school)
+(doctor-put-meaning schools 'school)
+(doctor-put-meaning skool 'school)
+(doctor-put-meaning grade 'school)
+(doctor-put-meaning grades 'school)
+(doctor-put-meaning teacher 'school)
+(doctor-put-meaning teachers 'school)
+(doctor-put-meaning classes 'school)
+(doctor-put-meaning professor 'school)
+(doctor-put-meaning prof 'school)
+(doctor-put-meaning profs 'school)
+(doctor-put-meaning professors 'school)
+(doctor-put-meaning mit 'school)
+(doctor-put-meaning emacs 'eliza)
+(doctor-put-meaning eliza 'eliza)
+(doctor-put-meaning liza 'eliza)
+(doctor-put-meaning elisa 'eliza)
+(doctor-put-meaning weizenbaum 'eliza)
+(doctor-put-meaning doktor 'eliza)
+(doctor-put-meaning atheletics 'sports)
+(doctor-put-meaning baseball 'sports)
+(doctor-put-meaning basketball 'sports)
+(doctor-put-meaning football 'sports)
+(doctor-put-meaning frisbee 'sports)
+(doctor-put-meaning gym 'sports)
+(doctor-put-meaning gymnastics 'sports)
+(doctor-put-meaning hockey 'sports)
+(doctor-put-meaning lacrosse 'sports)
+(doctor-put-meaning soccer 'sports)
+(doctor-put-meaning softball 'sports)
+(doctor-put-meaning sports 'sports)
+(doctor-put-meaning swimming 'sports)
+(doctor-put-meaning swim 'sports)
+(doctor-put-meaning tennis 'sports)
+(doctor-put-meaning volleyball 'sports)
+(doctor-put-meaning math 'math)
+(doctor-put-meaning mathematics 'math)
+(doctor-put-meaning mathematical 'math)
+(doctor-put-meaning theorem 'math)
+(doctor-put-meaning axiom 'math)
+(doctor-put-meaning lemma 'math)
+(doctor-put-meaning algebra 'math)
+(doctor-put-meaning algebraic 'math)
+(doctor-put-meaning trig 'math)
+(doctor-put-meaning trigonometry 'math)
+(doctor-put-meaning trigonometric 'math)
+(doctor-put-meaning geometry 'math)
+(doctor-put-meaning geometric 'math)
+(doctor-put-meaning calculus 'math)
+(doctor-put-meaning arithmetic 'math)
+(doctor-put-meaning zippy 'zippy)
+(doctor-put-meaning zippy 'zippy)
+(doctor-put-meaning pinhead 'zippy)
+(doctor-put-meaning chat 'chat)
+
+(defun doctor ()
+ "Switch to *doctor* buffer and start giving psychotherapy."
+ (interactive)
+ (switch-to-buffer "*doctor*")
+ (doctor-mode))
+
+(defun doctor-ret-or-read (arg)
+ "Insert a newline if preceding character is not a newline,
+Otherwise call the Doctor to parse preceding sentence"
+ (interactive "*p")
+ (if (= (preceding-char) ?\n)
+ (doctor-read-print)
+ (newline arg)))
+
+(defun doctor-read-print nil
+ "top level loop"
+ (interactive)
+ (let ((sent (doctor-readin)))
+ (insert "\n")
+ (setq lincount (1+ lincount))
+ (doctor-doc sent)
+ (insert "\n")
+ (setq bak sent)))
+
+(defun doctor-readin nil
+ "Read a sentence. Return it as a list of words"
+ (let (sentence)
+ (backward-sentence 1)
+ (while (not (eobp))
+ (setq sentence (append sentence (list (doctor-read-token)))))
+ sentence))
+
+(defun doctor-read-token ()
+ "read one word from buffer"
+ (prog1 (intern (downcase (buffer-substring (point)
+ (progn
+ (forward-word 1)
+ (point)))))
+ (re-search-forward "\\Sw*")))
+
+;; Main processing function for sentences that have been read.
+
+(defun doctor-doc (sent)
+ (cond
+ ((equal sent '(foo))
+ (doctor-type '(bar! ($ please)($ continue))))
+ ((doctor-member sent howareyoulst)
+ (doctor-type '(i\'m ok \. ($ describe) yourself \.)))
+ ((or (doctor-member sent '((good bye) (see you later) (i quit) (so long)
+ (go away) (get lost)))
+ (memq (car sent)
+ '(bye halt break quit done exit goodbye
+ bye\, stop pause goodbye\, stop pause)))
+ (doctor-type ($ bye)))
+ ((and (eq (car sent) 'you)
+ (memq (doctor-cadr sent) abusewords))
+ (setq found (doctor-cadr sent))
+ (doctor-type ($ abuselst)))
+ ((eq (car sent) 'whatmeans)
+ (doctor-def (doctor-cadr sent)))
+ ((equal sent '(parse))
+ (doctor-type (list 'subj '= subj ", "
+ 'verb '= verb "\n"
+ 'object 'phrase '= obj ","
+ 'noun 'form '= object "\n"
+ 'current 'keyword 'is found
+ ", "
+ 'most 'recent 'possessive
+ 'is owner "\n"
+ 'sentence 'used 'was
+ "..."
+ '(// bak))))
+ ;; ((eq (car sent) 'forget)
+ ;; (set (doctor-cadr sent) nil)
+ ;; (doctor-type '(($ isee)($ please)
+ ;; ($ continue)\.)))
+ (t
+ (if (doctor-defq sent) (doctor-define sent found))
+ (if (> (length sent) 12)(doctor-shorten sent))
+ (setq sent (doctor-correct-spelling (doctor-replace sent replist)))
+ (cond ((and (not (memq 'me sent))(not (memq 'i sent))
+ (memq 'am sent))
+ (setq sent (doctor-replace sent '((am . (are)))))))
+ (cond ((equal (car sent) 'yow) (doctor-zippy))
+ ((< (length sent) 2)
+ (cond ((eq (doctor-meaning (car sent)) 'howdy)
+ (doctor-howdy))
+ (t (doctor-short))))
+ (t
+ (if (memq 'am sent)
+ (setq sent (doctor-replace sent '((me . (i))))))
+ (setq sent (doctor-fixup sent))
+ (if (and (eq (car sent) 'do) (eq (doctor-cadr sent) 'not))
+ (cond ((zerop (random-range 3))
+ (doctor-type '(are you ($ afraidof) that \?)))
+ ((zerop (random-range 2))
+ (doctor-type '(don\'t tell me what to do \. i am the
+ psychiatrist here!))
+ (doctor-rthing))
+ (t
+ (doctor-type '(($ whysay) that i shouldn\'t
+ (doctor-cddr sent)
+ \?))))
+ (doctor-go (doctor-wherego sent))))))))
+
+;; Things done to process sentences once read.
+
+(defun doctor-correct-spelling (sent)
+ "correct the spelling and expand each word in sentence"
+ (if sent
+ (apply 'append (mapcar '(lambda (word)
+ (if (memq word typos)
+ (get (get word 'doctor-correction) 'doctor-expansion)
+ (list word)))
+ sent))))
+
+(defun doctor-shorten (sent)
+ "Make a sentence managably short using a few hacks"
+ (let (foo
+ retval
+ (temp '(because but however besides anyway until
+ while that except why how)))
+ (while temp
+ (setq foo (memq (car temp) sent))
+ (if (and foo
+ (> (length foo) 3))
+ (setq sent foo
+ sent (doctor-fixup sent)
+ temp nil
+ retval t)
+ (setq temp (cdr temp))))
+ retval))
+
+(defun doctor-define (sent found)
+ (doctor-svo sent found 1 nil)
+ (and
+ (doctor-nounp subj)
+ (not (doctor-pronounp subj))
+ subj
+ (doctor-meaning object)
+ (put subj 'doctor-meaning (doctor-meaning object))
+ t))
+
+(defun doctor-defq (sent)
+ "Set global var found to first keyword found in sentence SENT"
+ (setq found nil)
+ (let ((temp '(means applies mean refers refer related
+ similar defined associated linked like same)))
+ (while temp
+ (if (memq (car temp) sent)
+ (setq found (car temp)
+ temp nil)
+ (setq temp (cdr temp)))))
+ found)
+
+(defun doctor-def (x)
+ (progn
+ (doctor-type (list 'the 'word x 'means (doctor-meaning x) 'to 'me))
+ nil))
+
+(defun doctor-forget ()
+ "Delete the last element of the history list"
+ (setq history (reverse (cdr (reverse history)))))
+
+(defun doctor-query (x)
+ "Prompt for a line of input from the minibuffer until a noun or a
+verb word is seen. Put dialogue in buffer."
+ (let (a
+ (prompt (concat (doctor-make-string x)
+ " what \? "))
+ retval)
+ (while (not retval)
+ (while (not a)
+ (insert ?\n
+ prompt
+ (read-string prompt)
+ ?\n)
+ (setq a (doctor-readin)))
+ (while (and a (not retval))
+ (cond ((doctor-nounp (car a))
+ (setq retval (car a)))
+ ((doctor-verbp (car a))
+ (setq retval (doctor-build
+ (doctor-build x " ")
+ (car a))))
+ ((setq a (cdr a))))))
+ retval))
+
+(defun doctor-subjsearch (sent key type)
+ "Search for the subject of a sentence SENT, looking for the noun closest to
+and preceding KEY by at least TYPE words. Set global variable subj to the
+subject noun, and return the portion of the sentence following it"
+ (let ((i (- (length sent) (length (memq key sent)) type)))
+ (while (and (> i -1) (not (doctor-nounp (nth i sent))))
+ (setq i (1- i)))
+ (cond ((> i -1)
+ (setq subj (nth i sent))
+ (nthcdr (1+ i) sent))
+ (t
+ (setq subj 'you)
+ nil))))
+
+(defun doctor-nounp (x)
+ "Returns t if the symbol argument is a noun"
+ (or (doctor-pronounp x)
+ (not (or (doctor-verbp x)
+ (equal x 'not)
+ (doctor-prepp x)
+ (doctor-modifierp x) )) ))
+
+(defun doctor-pronounp (x)
+ "Returns t if the symbol argument is a pronoun"
+ (memq x '(
+ i me mine myself
+ we us ours ourselves ourself
+ you yours yourself yourselves
+ he him himself she hers herself
+ it that those this these things thing
+ they them themselves theirs
+ anybody everybody somebody
+ anyone everyone someone
+ anything something everything)))
+
+(mapcar (function (lambda (x) (put x 'doctor-sentence-type 'verb)))
+ '(abort aborted aborts ask asked asks am
+ applied applies apply are associate
+ associated ate
+ be became become becomes becoming
+ been being believe belived believes
+ bit bite bites bore bored bores boring bought buy buys buying
+ call called calling calls came can caught catch come
+ contract contracted contracts control controlled controls
+ could croak croaks croaked cut cuts
+ dare dared define defines dial dialed dials did die died dies
+ dislike disliked
+ dislikes do does drank drink drinks drinking
+ drive drives driving drove dying
+ eat eating eats expand expanded expands
+ expect expected expects expel expels expeled expelled
+ explain explained explains
+ fart farts feel feels felt fight fights find finds finding
+ forget forgets forgot fought found fuck fucked
+ fucking fucks
+ gave get gets getting give gives go goes going gone got gotten
+ had harm harms has hate hated hates have having
+ hear heard hears hearing help helped helping helps
+ hit hits hope hoped hopes hurt hurts
+ implies imply is
+ join joined joins jump jumped jumps
+ keep keeping keeps kept
+ kill killed killing kills kiss kissed kisses kissing
+ knew know knows
+ laid lay lays let lets lie lied lies like liked likes
+ liking listen listens
+ login look looked looking looks
+ lose losing lost
+ love loved loves loving
+ luse lusing lust lusts
+ made make makes making may mean means meant might
+ move moved moves moving must
+ need needed needs
+ order ordered orders ought
+ paid pay pays pick picked picking picks
+ placed placing prefer prefers put puts
+ ran rape raped rapes
+ read reading reads recall receive received receives
+ refer refered referred refers
+ relate related relates remember remembered remembers
+ romp romped romps run running runs
+ said sang sat saw say says
+ screw screwed screwing screws scrod see sees seem seemed
+ seems seen sell selling sells
+ send sendind sends sent shall shoot shot should
+ sing sings sit sits sitting sold studied study
+ take takes taking talk talked talking talks tell tells telling
+ think thinks
+ thought told took tooled touch touched touches touching
+ transfer transfered transfers transmit transmits transmitted
+ type types types typing
+ walk walked walking walks want wanted wants was watch
+ watched watching went were will wish would work worked works
+ write writes writing wrote use used uses using))
+
+(defun doctor-verbp (x) (if (symbolp x)
+ (eq (get x 'doctor-sentence-type) 'verb)))
+
+(defun doctor-plural (x)
+ "form the plural of the word argument"
+ (let ((foo (doctor-make-string x)))
+ (cond ((string-equal (substring foo -1) "s")
+ (cond ((string-equal (substring foo -2 -1) "s")
+ (intern (concat foo "es")))
+ (t x)))
+ ((string-equal (substring foo -1) "y")
+ (intern (concat (substring foo 0 -1)
+ "ies")))
+ (t (intern (concat foo "s"))))))
+
+(defun doctor-setprep (sent key)
+ (let ((val)
+ (foo (memq key sent)))
+ (cond ((doctor-prepp (doctor-cadr foo))
+ (setq val (doctor-getnoun (doctor-cddr foo)))
+ (cond (val val)
+ (t 'something)))
+ ((doctor-articlep (doctor-cadr foo))
+ (setq val (doctor-getnoun (doctor-cddr foo)))
+ (cond (val (doctor-build (doctor-build (doctor-cadr foo) " ") val))
+ (t 'something)))
+ (t 'something))))
+
+(defun doctor-getnoun (x)
+ (cond ((null x)(setq object 'something))
+ ((atom x)(setq object x))
+ ((eq (length x) 1)
+ (setq object (cond
+ ((doctor-nounp (setq object (car x))) object)
+ (t (doctor-query object)))))
+ ((eq (car x) 'to)
+ (doctor-build 'to\ (doctor-getnoun (cdr x))))
+ ((doctor-prepp (car x))
+ (doctor-getnoun (cdr x)))
+ ((not (doctor-nounp (car x)))
+ (doctor-build (doctor-build (cdr (assq (car x)
+ (append
+ '((a . this)
+ (some . this)
+ (one . that))
+ (list
+ (cons
+ (car x) (car x))))))
+ " ")
+ (doctor-getnoun (cdr x))))
+ (t (setq object (car x))) ))
+
+(defun doctor-modifierp (x)
+ (or (doctor-adjectivep x)
+ (doctor-adverbp x)
+ (doctor-othermodifierp x)))
+
+(defun doctor-adjectivep (x)
+ (or (numberp x)
+ (doctor-nmbrp x)
+ (doctor-articlep x)
+ (doctor-colorp x)
+ (doctor-sizep x)
+ (doctor-possessivepronounp x)))
+
+(defun doctor-adverbp (xx)
+ (string-equal (substring (doctor-make-string xx) -2) "ly"))
+
+(defun doctor-articlep (x)
+ (memq x '(the a an)))
+
+(defun doctor-nmbrp (x)
+ (memq x '(one two three four five six seven eight nine ten
+ eleven twelve thirteen fourteen fifteen
+ sixteen seventeen eighteen nineteen
+ twenty thirty forty fifty sixty seventy eighty ninety
+ hundred thousand million billion
+ half quarter
+ first second third fourth fifth
+ sixth seventh eighth nineth tenth)))
+
+(defun doctor-colorp (x)
+ (memq x '(beige black blue brown crimson
+ gray grey green
+ orange pink purple red tan tawny
+ violet white yellow)))
+
+(defun doctor-sizep (x)
+ (memq x '(big large tall fat wide thick
+ small petite short thin skinny)))
+
+(defun doctor-possessivepronounp (x)
+ (memq x '(my your his her our their)))
+
+(defun doctor-othermodifierp (x)
+ (memq x '(all also always amusing any anyway associated awesome
+ bad beautiful best better but certain clear
+ ever every fantastic fun funny
+ good great gross growdy however if ignorant
+ less linked losing lusing many more much
+ never nice obnoxious often poor pretty real related rich
+ similar some stupid super superb
+ terrible terrific too total tubular ugly very)))
+
+(defun doctor-prepp (x)
+ (memq x '(about above after around as at
+ before beneath behind beside between by
+ for from in inside into
+ like near next of on onto over
+ same through thru to toward towards
+ under underneath with without)))
+
+(defun doctor-remember (thing)
+ (cond ((null history)
+ (setq history (list thing)))
+ (t (setq history (append history (list thing))))))
+
+(defun doctor-type (x)
+ (setq x (doctor-fix-2 x))
+ (doctor-txtype (doctor-assm x)))
+
+(defun doctor-fixup (sent)
+ (setq sent (append
+ (cdr
+ (assq (car sent)
+ (append
+ '((me i)
+ (him he)
+ (her she)
+ (them they)
+ (okay)
+ (well)
+ (sigh)
+ (hmm)
+ (hmmm)
+ (hmmmm)
+ (hmmmmm)
+ (gee)
+ (sure)
+ (great)
+ (oh)
+ (fine)
+ (ok)
+ (no))
+ (list (list (car sent)
+ (car sent))))))
+ (cdr sent)))
+ (doctor-fix-2 sent))
+
+(defun doctor-fix-2 (sent)
+ (let ((foo sent))
+ (while foo
+ (if (and (eq (car foo) 'me)
+ (doctor-verbp (doctor-cadr foo)))
+ (rplaca foo 'i)
+ (cond ((eq (car foo) 'you)
+ (cond ((memq (doctor-cadr foo) '(am be been is))
+ (rplaca (cdr foo) 'are))
+ ((memq (doctor-cadr foo) '(has))
+ (rplaca (cdr foo) 'have))
+ ((memq (doctor-cadr foo) '(was))
+ (rplaca (cdr foo) 'were))))
+ ((equal (car foo) 'i)
+ (cond ((memq (doctor-cadr foo) '(are is be been))
+ (rplaca (cdr foo) 'am))
+ ((memq (doctor-cadr foo) '(were))
+ (rplaca (cdr foo) 'was))
+ ((memq (doctor-cadr foo) '(has))
+ (rplaca (cdr foo) 'have))))
+ ((and (doctor-verbp (car foo))
+ (eq (doctor-cadr foo) 'i)
+ (not (doctor-verbp (car (doctor-cddr foo)))))
+ (rplaca (cdr foo) 'me))
+ ((and (eq (car foo) 'a)
+ (doctor-vowelp (string-to-char
+ (doctor-make-string (doctor-cadr foo)))))
+ (rplaca foo 'an))
+ ((and (eq (car foo) 'an)
+ (not (doctor-vowelp (string-to-char
+ (doctor-make-string (doctor-cadr foo))))))
+ (rplaca foo 'a)))
+ (setq foo (cdr foo))))
+ sent))
+
+(defun doctor-vowelp (x)
+ (memq x '(?a ?e ?i ?o ?u)))
+
+(defun doctor-replace (sent rlist)
+ "Replaces any element of SENT that is the car of a replacement element
+pair in RLIST"
+ (apply 'append
+ (mapcar
+ (function
+ (lambda (x)
+ (cdr (or (assq x rlist) ; either find a replacement
+ (list x x))))) ; or fake an identity mapping
+ sent)))
+
+(defun doctor-wherego (sent)
+ (cond ((null sent)($ whereoutp))
+ ((null (doctor-meaning (car sent)))
+ (doctor-wherego (cond ((zerop (random-range 2))
+ (reverse (cdr sent)))
+ (t (cdr sent)))))
+ (t
+ (setq found (car sent))
+ (doctor-meaning (car sent)))))
+
+(defun doctor-svo (sent key type mem)
+ "Find subject, verb and object in sentence SENT with focus on word KEY.
+TYPE is number of words preceding KEY to start looking for subject. MEM is
+t if results are to be put on doctor's memory stack. Return is in global
+variables subj, verb and object"
+ (let ((foo (doctor-subjsearch sent key type) sent))
+ (or foo
+ (setq foo sent
+ mem nil))
+ (while (and (null (doctor-verbp (car foo))) (cdr foo))
+ (setq foo (cdr foo)))
+ (setq verb (car foo))
+ (setq obj (doctor-getnoun (cdr foo)))
+ (cond ((eq object 'i)(setq object 'me))
+ ((eq subj 'me)(setq subj 'i)))
+ (cond (mem (doctor-remember (list subj verb obj))))))
+
+(defun doctor-possess (sent key)
+ "Set possessive in SENT for keyword KEY. Hack on previous word, setting
+global variable owner to possibly correct result"
+ (let* ((i (- (length sent) (length (memq key sent)) 1))
+ (prev (if (< i 0) 'your
+ (nth i sent))))
+ (setq owner (if (or (doctor-possessivepronounp prev)
+ (string-equal "s"
+ (substring (doctor-make-string prev)
+ -1)))
+ prev
+ 'your))))
+
+;; Output of replies.
+
+(defun doctor-txtype (ans)
+ "Output to buffer a list of symbols or strings as a sentence"
+ (setq *print-upcase* t *print-space* nil)
+ (mapcar 'doctor-type-symbol ans)
+ (insert "\n"))
+
+(defun doctor-type-symbol (word)
+ "Output a symbol to the buffer with some fancy case and spacing hacks"
+ (setq word (doctor-make-string word))
+ (if (string-equal word "i") (setq word "I"))
+ (if *print-upcase*
+ (progn
+ (setq word (capitalize word))
+ (if *print-space*
+ (insert " "))))
+ (cond ((or (string-match "^[.,;:?! ]" word)
+ (not *print-space*))
+ (insert word))
+ (t (insert ?\ word)))
+ (if (> (current-column) fill-column)
+ (apply auto-fill-hook nil))
+ (setq *print-upcase* (string-match "[.?!]$" word)
+ *print-space* t))
+
+(defun doctor-build (str1 str2)
+ "Make a symbol out of the concatenation of the two non-list arguments"
+ (cond ((null str1) str2)
+ ((null str2) str1)
+ ((and (atom str1)
+ (atom str2))
+ (intern (concat (doctor-make-string str1)
+ (doctor-make-string str2))))
+ (t nil)))
+
+(defun doctor-make-string (obj)
+ (cond ((stringp obj) obj)
+ ((symbolp obj) (symbol-name obj))
+ ((numberp obj) (int-to-string obj))
+ (t "")))
+
+(defun doctor-concat (x y)
+ "like append, but force atomic arguments to be lists"
+ (append
+ (if (and x (atom x)) (list x) x)
+ (if (and y (atom y)) (list y) y)))
+
+(defun doctor-assm (proto)
+ (cond ((null proto) nil)
+ ((atom proto) (list proto))
+ ((atom (car proto))
+ (cons (car proto) (doctor-assm (cdr proto))))
+ (t (doctor-concat (doctor-assm (eval (car proto))) (doctor-assm (cdr proto))))))
+
+;; Functions that handle specific words or meanings when found.
+
+(defun doctor-go (destination)
+ "Call a doctor- function"
+ (funcall (intern (concat "doctor-" (doctor-make-string destination)))))
+
+(defun doctor-desire1 ()
+ (doctor-go ($ whereoutp)))
+
+(defun doctor-huh ()
+ (cond ((< (length sent) 9) (doctor-type ($ huhlst)))
+ (t (doctor-type ($ longhuhlst)))))
+
+(defun doctor-rthing () (doctor-type ($ thlst)))
+
+(defun doctor-remem () (cond ((null history)(doctor-huh))
+ ((doctor-type ($ remlst)))))
+
+(defun doctor-howdy ()
+ (cond ((not howdyflag)
+ (doctor-type '(($ hello) what brings you to see me \?))
+ (setq howdyflag t))
+ (t
+ (doctor-type '(($ ibelieve) we\'ve introduced ourselves already \.))
+ (doctor-type '(($ please) ($ describe) ($ things) \.)))))
+
+(defun doctor-when ()
+ (cond ((< (length (memq found sent)) 3)(doctor-short))
+ (t
+ (setq sent (cdr (memq found sent)))
+ (setq sent (doctor-fixup sent))
+ (doctor-type '(($ whatwhen)(// sent) \?)))))
+
+(defun doctor-conj ()
+ (cond ((< (length (memq found sent)) 4)(doctor-short))
+ (t
+ (setq sent (cdr (memq found sent)))
+ (setq sent (doctor-fixup sent))
+ (cond ((eq (car sent) 'of)
+ (doctor-type '(are you ($ sure) that is the real reason \?))
+ (setq things (cons (cdr sent) things)))
+ (t
+ (doctor-remember sent)
+ (doctor-type ($ beclst)))))))
+
+(defun doctor-short ()
+ (cond ((= (car repetitive-shortness) (1- lincount))
+ (rplacd repetitive-shortness
+ (1+ (cdr repetitive-shortness))))
+ (t
+ (rplacd repetitive-shortness 1)))
+ (rplaca repetitive-shortness lincount)
+ (cond ((> (cdr repetitive-shortness) 6)
+ (cond ((not **mad**)
+ (doctor-type '(($ areyou)
+ just trying to see what kind of things
+ i have in my vocabulary \? please try to
+ carry on a reasonable conversation!))
+ (setq **mad** t))
+ (t
+ (doctor-type '(i give up \. you need a lesson in creative
+ writing \.\.\.))
+ ;;(push monosyllables observation-list)
+ )))
+ (t
+ (cond ((equal sent (doctor-assm '(yes)))
+ (doctor-type '(($ isee) ($ inter) ($ whysay) this is so \?)))
+ ((equal sent (doctor-assm '(because)))
+ (doctor-type ($ shortbeclst)))
+ ((equal sent (doctor-assm '(no)))
+ (doctor-type ($ neglst)))
+ (t (doctor-type ($ shortlst)))))))
+
+(defun doctor-alcohol () (doctor-type ($ drnk)))
+
+(defun doctor-desire ()
+ (let ((foo (memq found sent)))
+ (cond ((< (length foo) 2)
+ (doctor-go (doctor-build (doctor-meaning found) 1)))
+ ((memq (doctor-cadr foo) '(a an))
+ (rplacd foo (append '(to have) (cdr foo)))
+ (doctor-svo sent found 1 nil)
+ (doctor-remember (list subj 'would 'like obj))
+ (doctor-type ($ whywant)))
+ ((not (eq (doctor-cadr foo) 'to))
+ (doctor-go (doctor-build (doctor-meaning found) 1)))
+ (t
+ (doctor-svo sent found 1 nil)
+ (doctor-remember (list subj 'would 'like obj))
+ (doctor-type ($ whywant))))))
+
+(defun doctor-drug ()
+ (doctor-type ($ drugs))
+ (doctor-remember (list 'you 'used found)))
+
+(defun doctor-toke ()
+ (doctor-type ($ toklst)))
+
+(defun doctor-state ()
+ (doctor-type ($ states))(doctor-remember (list 'you 'were found)))
+
+(defun doctor-mood ()
+ (doctor-type ($ moods))(doctor-remember (list 'you 'felt found)))
+
+(defun doctor-fear ()
+ (setq feared (doctor-setprep sent found))
+ (doctor-type ($ fears))
+ (doctor-remember (list 'you 'were 'afraid 'of feared)))
+
+(defun doctor-hate ()
+ (doctor-svo sent found 1 t)
+ (cond ((memq 'not sent) (doctor-forget) (doctor-huh))
+ ((equal subj 'you)
+ (doctor-type '(why do you (// verb)(// obj) \?)))
+ (t (doctor-type '(($ whysay)(list subj verb obj))))))
+
+(defun doctor-symptoms ()
+ (doctor-type '(($ maybe) you should consult a doctor of medicine\,
+ i am a psychiatrist \.)))
+
+(defun doctor-hates ()
+ (doctor-svo sent found 1 t)
+ (doctor-hates1))
+
+(defun doctor-hates1 ()
+ (doctor-type '(($ whysay)(list subj verb obj))))
+
+(defun doctor-loves ()
+ (doctor-svo sent found 1 t)
+ (doctor-qloves))
+
+(defun doctor-qloves ()
+ (doctor-type '(($ bother)(list subj verb obj) \?)))
+
+(defun doctor-love ()
+ (doctor-svo sent found 1 t)
+ (cond ((memq 'not sent) (doctor-forget) (doctor-huh))
+ ((memq 'to sent) (doctor-hates1))
+ (t
+ (cond ((equal object 'something)
+ (setq object '(this person you love))))
+ (cond ((equal subj 'you)
+ (setq lover obj)
+ (cond ((equal lover '(this person you love))
+ (setq lover '(your partner))
+ (doctor-forget)
+ (doctor-type '(with whom are you in love \?)))
+ ((doctor-type '(($ please)
+ ($ describe)
+ ($ relation)
+ (// lover)
+ \.)))))
+ ((equal subj 'i)
+ (doctor-txtype '(we were discussing you!)))
+ (t (doctor-forget)
+ (setq obj 'someone)
+ (setq verb (doctor-build verb 's))
+ (doctor-qloves))))))
+
+(defun doctor-mach ()
+ (setq found (doctor-plural found))
+ (doctor-type ($ machlst)))
+
+(defun doctor-sexnoun () (doctor-sexverb))
+
+(defun doctor-sexverb ()
+ (if (or (memq 'me sent)(memq 'myself sent)(memq 'i sent))
+ (doctor-foul)
+ (doctor-type ($ sexlst))))
+
+(defun doctor-death () (doctor-type ($ deathlst)))
+
+(defun doctor-foul ()
+ (doctor-type ($ foullst)))
+
+(defun doctor-family ()
+ (doctor-possess sent found)
+ (doctor-type ($ famlst)))
+
+;; I did not add this -- rms.
+(defun doctor-rms ()
+ (cond (rms-flag (doctor-type ($ stallmanlst)))
+ (t (setq rms-flag t) (doctor-type '(do you know Stallman \?)))))
+
+(defun doctor-school nil (doctor-type ($ schoollst)))
+
+(defun doctor-eliza ()
+ (cond (eliza-flag (doctor-type ($ elizalst)))
+ (t (setq eliza-flag t)
+ (doctor-type '((// found) \? hah !
+ ($ please) ($ continue) \.)))))
+
+(defun doctor-sports () (doctor-type ($ sportslst)))
+
+(defun doctor-math () (doctor-type ($ mathlst)))
+
+(defun doctor-zippy ()
+ (cond (zippy-flag (doctor-type ($ zippylst)))
+ (t (setq zippy-flag t)
+ (doctor-type '(yow! are we interactive yet \?)))))
+
+
+(defun doctor-chat () (doctor-type ($ chatlst)))
diff --git a/lisp/doctor.elc b/lisp/doctor.elc
new file mode 100644
index 00000000000..62929b7af12
--- /dev/null
+++ b/lisp/doctor.elc
Binary files differ
diff --git a/lisp/ebuff-menu.el b/lisp/ebuff-menu.el
new file mode 100644
index 00000000000..72de2dd8c4f
--- /dev/null
+++ b/lisp/ebuff-menu.el
@@ -0,0 +1,244 @@
+; buggestions to mly@ai.ai.mit.edu
+
+;; who says one can't have typeout windows in gnu emacs?
+;; like ^r select buffer from its emacs lunar or tmacs libraries.
+
+;; Copyright (C) 1985, 1986 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 1, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+(require 'electric)
+
+;; this depends on the format of list-buffers (from src/buffer.c) and
+;; on stuff in lisp/buff-menu.el
+
+(defvar electric-buffer-menu-mode-map nil)
+(defun electric-buffer-list (arg)
+ "Vaguely like ITS lunar select buffer;
+combining typeoutoid buffer listing with menuoid buffer selection.
+
+This pops up a buffer describing the set of emacs buffers.
+If the very next character typed is a space then the buffer list
+ window disappears.
+
+Otherwise, one may move around in the buffer list window, marking
+ buffers to be selected, saved or deleted.
+
+To exit and select a new buffer, type Space when the cursor is on the
+ appropriate line of the buffer-list window.
+
+Other commands are much like those of buffer-menu-mode.
+
+Calls value of electric-buffer-menu-mode-hook on entry if non-nil.
+
+\\{electric-buffer-menu-mode-map}"
+ (interactive "P")
+ (let (select buffer)
+ (save-window-excursion
+ (save-window-excursion (list-buffers arg))
+ (setq buffer (window-buffer (Electric-pop-up-window "*Buffer List*")))
+ (unwind-protect
+ (progn
+ (set-buffer buffer)
+ (Electric-buffer-menu-mode)
+ (setq select
+ (catch 'electric-buffer-menu-select
+ (message "<<< Press Space to bury the buffer list >>>")
+ (if (= (setq unread-command-char (read-char)) ?\ )
+ (progn (setq unread-command-char -1)
+ (throw 'electric-buffer-menu-select nil)))
+ (let ((first (progn (goto-char (point-min))
+ (forward-line 2)
+ (point)))
+ (last (progn (goto-char (point-max))
+ (forward-line -1)
+ (point)))
+ (goal-column 0))
+ (goto-char first)
+ (Electric-command-loop 'electric-buffer-menu-select
+ nil
+ t
+ 'electric-buffer-menu-looper
+ (cons first last))))))
+ (set-buffer buffer)
+ (Buffer-menu-mode)
+ (bury-buffer buffer)
+ (message "")))
+ (if select
+ (progn (set-buffer buffer)
+ (let ((opoint (point-marker)))
+ (Buffer-menu-execute)
+ (goto-char (point-min))
+ (if (prog1 (search-forward "\n>" nil t)
+ (goto-char opoint) (set-marker opoint nil))
+ (Buffer-menu-select)
+ (switch-to-buffer (Buffer-menu-buffer t))))))))
+
+(defun electric-buffer-menu-looper (state condition)
+ (cond ((and condition
+ (not (memq (car condition) '(buffer-read-only
+ end-of-buffer
+ beginning-of-buffer))))
+ (signal (car condition) (cdr condition)))
+ ((< (point) (car state))
+ (goto-char (point-min))
+ (forward-line 2))
+ ((> (point) (cdr state))
+ (goto-char (point-max))
+ (forward-line -1)
+ (if (pos-visible-in-window-p (point-max))
+ (recenter -1)))))
+
+(put 'Electric-buffer-menu-mode 'mode-class 'special)
+(defun Electric-buffer-menu-mode ()
+ "Major mode for editing a list of buffers.
+Each line describes one of the buffers in Emacs.
+Letters do not insert themselves; instead, they are commands.
+\\{electric-buffer-menu-mode-map}
+
+C-g or C-c C-c -- exit buffer menu, returning to previous window and buffer
+ configuration. If the very first character typed is a space, it
+ also has this effect.
+Space -- select buffer of line point is on.
+ Also show buffers marked with m in other windows,
+ deletes buffers marked with \"D\", and saves those marked with \"S\".
+m -- mark buffer to be displayed.
+~ -- clear modified-flag on that buffer.
+s -- mark that buffer to be saved.
+d or C-d -- mark that buffer to be deleted.
+u -- remove all kinds of marks from current line.
+v -- view buffer, returning when done.
+Delete -- back up a line and remove marks.
+
+
+Entry to this mode via command \\[electric-buffer-list] calls the value of
+electric-buffer-menu-mode-hook if it is non-nil."
+ (kill-all-local-variables)
+ (use-local-map electric-buffer-menu-mode-map)
+ (setq mode-name "Electric Buffer Menu")
+ (setq mode-line-buffer-identification "Electric Buffer List")
+ (if (memq 'mode-name mode-line-format)
+ (progn (setq mode-line-format (copy-sequence mode-line-format))
+ (setcar (memq 'mode-name mode-line-format) "Buffers")))
+ (make-local-variable 'Helper-return-blurb)
+ (setq Helper-return-blurb "return to buffer editing")
+ (setq truncate-lines t)
+ (setq buffer-read-only t)
+ (setq major-mode 'Electric-buffer-menu-mode)
+ (goto-char (point-min))
+ (if (search-forward "\n." nil t) (forward-char -1))
+ (run-hooks 'electric-buffer-menu-mode-hook))
+
+;; generally the same as Buffer-menu-mode-map
+;; (except we don't indirect to global-map)
+(put 'Electric-buffer-menu-undefined 'suppress-keymap t)
+(if electric-buffer-menu-mode-map
+ nil
+ (let ((map (make-keymap)))
+ (fillarray map 'Electric-buffer-menu-undefined)
+ (define-key map "\e" (make-keymap))
+ (fillarray (lookup-key map "\e") 'Electric-buffer-menu-undefined)
+ (define-key map "\C-z" 'suspend-emacs)
+ (define-key map "v" 'Electric-buffer-menu-mode-view-buffer)
+ (define-key map "\C-h" 'Helper-help)
+ (define-key map "?" 'Helper-describe-bindings)
+ (define-key map "\C-c" nil)
+ (define-key map "\C-c\C-c" 'Electric-buffer-menu-quit)
+ (define-key map "\C-]" 'Electric-buffer-menu-quit)
+ (define-key map "q" 'Electric-buffer-menu-quit)
+ (define-key map " " 'Electric-buffer-menu-select)
+ (define-key map "\C-l" 'recenter)
+ (define-key map "s" 'Buffer-menu-save)
+ (define-key map "d" 'Buffer-menu-delete)
+ (define-key map "k" 'Buffer-menu-delete)
+ (define-key map "\C-d" 'Buffer-menu-delete-backwards)
+ ;(define-key map "\C-k" 'Buffer-menu-delete)
+ (define-key map "\177" 'Buffer-menu-backup-unmark)
+ (define-key map "~" 'Buffer-menu-not-modified)
+ (define-key map "u" 'Buffer-menu-unmark)
+ (let ((i ?0))
+ (while (<= i ?9)
+ (define-key map (char-to-string i) 'digit-argument)
+ (define-key map (concat "\e" (char-to-string i)) 'digit-argument)
+ (setq i (1+ i))))
+ (define-key map "-" 'negative-argument)
+ (define-key map "\e-" 'negative-argument)
+ (define-key map "m" 'Buffer-menu-mark)
+ (define-key map "\C-u" 'universal-argument)
+ (define-key map "\C-p" 'previous-line)
+ (define-key map "\C-n" 'next-line)
+ (define-key map "p" 'previous-line)
+ (define-key map "n" 'next-line)
+ (define-key map "\C-v" 'scroll-up)
+ (define-key map "\ev" 'scroll-down)
+ (define-key map "\e\C-v" 'scroll-other-window)
+ (define-key map "\e>" 'end-of-buffer)
+ (define-key map "\e<" 'beginning-of-buffer)
+ (setq electric-buffer-menu-mode-map map)))
+
+(defun Electric-buffer-menu-exit ()
+ (interactive)
+ (setq unread-command-char last-input-char)
+ ;; for robustness
+ (condition-case ()
+ (throw 'electric-buffer-menu-select nil)
+ (error (Buffer-menu-mode)
+ (other-buffer))))
+
+(defun Electric-buffer-menu-select ()
+ "Leave Electric Buffer Menu, selecting buffers and executing changes.
+Saves buffers marked \"S\". Deletes buffers marked \"K\".
+Selects buffer at point and displays buffers marked \">\" in other
+windows."
+ (interactive)
+ (throw 'electric-buffer-menu-select (point)))
+
+(defun Electric-buffer-menu-quit ()
+ "Leave Electric Buffer Menu, restoring previous window configuration.
+Does not execute select, save, or delete commands."
+ (interactive)
+ (throw 'electric-buffer-menu-select nil))
+
+(defun Electric-buffer-menu-undefined ()
+ (interactive)
+ (ding)
+ (message (if (and (eq (key-binding "\C-c\C-c") 'Electric-buffer-menu-quit)
+ (eq (key-binding " ") 'Electric-buffer-menu-select)
+ (eq (key-binding "\C-h") 'Helper-help)
+ (eq (key-binding "?") 'Helper-describe-bindings))
+ "Type C-c C-c to exit, Space to select, C-h for help, ? for commands"
+ (substitute-command-keys "\
+Type \\[Electric-buffer-menu-quit] to exit, \
+\\[Electric-buffer-menu-select] to select, \
+\\[Helper-help] for help, \\[Helper-describe-bindings] for commands.")))
+ (sit-for 4))
+
+(defun Electric-buffer-menu-mode-view-buffer ()
+ "View buffer on current line in Electric Buffer Menu.
+Returns to Electric Buffer Menu when done."
+ (interactive)
+ (let ((bufnam (Buffer-menu-buffer nil)))
+ (if bufnam
+ (view-buffer bufnam)
+ (ding)
+ (message "Buffer %s does not exist!" bufnam)
+ (sit-for 4))))
+
+
+
+
diff --git a/lisp/ebuff-menu.elc b/lisp/ebuff-menu.elc
new file mode 100644
index 00000000000..e6963d1e4c3
--- /dev/null
+++ b/lisp/ebuff-menu.elc
Binary files differ
diff --git a/lisp/echistory.el b/lisp/echistory.el
index f50c4e66c91..692afadba66 100644
--- a/lisp/echistory.el
+++ b/lisp/echistory.el
@@ -24,7 +24,7 @@
(defun Electric-command-history-redo-expression (&optional noconfirm)
"Edit current history line in minibuffer and execute result.
-With prefix arg NOCONFIRM, execute current line as-is without editing."
+With prefix argument NOCONFIRM, execute current line as is without editing."
(interactive "P")
(let (todo)
(save-excursion
@@ -73,23 +73,35 @@ With prefix arg NOCONFIRM, execute current line as-is without editing."
(define-key electric-history-map "\e\C-v" 'scroll-other-window))
(defvar electric-command-history-hook nil
- "If non-nil, its value is called by `electric-command-history'.")
+ "If non-nil, its value is called by electric-command-history.")
(defun electric-command-history ()
- "\\<electric-history-map>Major mode for examining and redoing commands from `command-history'.
-This pops up a window with the Command History listing.
-The number of command listed is controlled by `list-command-history-max'.
-The command history is filtered by `list-command-history-filter' if non-nil.
+ "Major mode for examining and redoing commands from command-history.
+The number of command listed is controlled by list-command-history-max.
+The command history is filtered by list-command-history-filter if non-nil.
Combines typeout Command History list window with menu like selection
of an expression from the history for re-evaluation in the *original* buffer.
-The history displayed is filtered by `list-command-history-filter' if non-nil.
+The history displayed is filtered by list-command-history-filter if non-nil.
-Like Emacs-Lisp mode except that characters do not insert themselves and
-Tab and Linefeed do not indent. Instead these commands are provided:
-\\{electric-history-map}
+This pops up a window with the Command History listing. If the very
+next character typed is Space, the listing is killed and the previous
+window configuration is restored. Otherwise, you can browse in the
+Command History with Return moving down and Delete moving up, possibly
+selecting an expression to be redone with Space or quitting with `Q'.
-Calls the value of `electric-command-history-hook' if that is non-nil.
+Like Emacs-Lisp Mode except that characters do not insert themselves and
+Tab and linefeed do not indent. Instead these commands are provided:
+Space or ! edit then evaluate current line in history inside
+ the ORIGINAL buffer which invoked this mode.
+ The previous window configuration is restored
+ unless the invoked command changes it.
+C-c C-c, C-], Q Quit and restore previous window configuration.
+LFD, RET Move to the next line in the history.
+DEL Move to the previous line in the history.
+? Provides a complete list of commands.
+
+Calls the value of electric-command-history-hook if that is non-nil
The Command History listing is recomputed each time this mode is invoked."
(interactive)
(let ((electric-history-in-progress t)
diff --git a/lisp/echistory.elc b/lisp/echistory.elc
new file mode 100644
index 00000000000..12ecb8fd0f4
--- /dev/null
+++ b/lisp/echistory.elc
Binary files differ
diff --git a/lisp/edmacro.el b/lisp/edmacro.el
deleted file mode 100644
index a59edee69a0..00000000000
--- a/lisp/edmacro.el
+++ /dev/null
@@ -1,640 +0,0 @@
-;; Keyboard macro editor for GNU Emacs. Version 1.02.
-;; Copyright (C) 1990 Free Software Foundation, Inc.
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 1, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
-;; Original from: Dave Gillespie, daveg@csvax.caltech.edu.
-
-;; To use, type `M-x edit-last-kbd-macro' to edit the most recently
-;; defined keyboard macro. If you have used `M-x name-last-kbd-macro'
-;; to give a keyboard macro a name, type `M-x edit-kbd-macro' to edit
-;; the macro by name. When you are done editing, type `C-c C-c' to
-;; record your changes back into the original keyboard macro.
-
-;;; The user-level commands for editing macros.
-
-(defun edit-last-kbd-macro (&optional prefix buffer hook)
- "Edit the most recently defined keyboard macro."
- (interactive "P")
- (edmacro-edit-macro last-kbd-macro
- (function (lambda (x arg) (setq last-kbd-macro x)))
- prefix buffer hook))
-
-(defun edit-kbd-macro (cmd &optional prefix buffer hook in-hook out-hook)
- "Edit a keyboard macro which has been given a name by `name-last-kbd-macro'.
-\(See also `edit-last-kbd-macro'.)"
- (interactive "CCommand name: \nP")
- (and cmd
- (edmacro-edit-macro (if in-hook
- (funcall in-hook cmd)
- (symbol-function cmd))
- (or out-hook
- (list 'lambda '(x arg)
- (list 'fset
- (list 'quote cmd)
- 'x)))
- prefix buffer hook cmd)))
-
-(defun read-kbd-macro (start end)
- "Read the region as a keyboard macro definition.
-The region is interpreted as spelled-out keystrokes, e.g., \"M-x abc RET\".
-The resulting macro is installed as the \"current\" keyboard macro.
-
-Symbols: RET, SPC, TAB, DEL, LFD, NUL; C-key; M-key. (Must be uppercase.)
- REM marks the rest of a line as a comment.
- Whitespace is ignored; other characters are copied into the macro."
- (interactive "r")
- (setq last-kbd-macro (edmacro-parse-keys (buffer-substring start end)))
- (if (and (string-match "\\`\C-x(" last-kbd-macro)
- (string-match "\C-x)\\'" last-kbd-macro))
- (setq last-kbd-macro (substring last-kbd-macro 2 -2))))
-
-;;; Formatting a keyboard macro as human-readable text.
-
-(defun edmacro-print-macro (macro-str local-map)
- (let ((save-map (current-local-map))
- (print-escape-newlines t)
- key-symbol key-str key-last prefix-arg this-prefix)
- (unwind-protect
- (progn
- (use-local-map local-map)
- (while (edmacro-peek-char)
- (edmacro-read-key)
- (setq this-prefix prefix-arg)
- (or (memq key-symbol '(digit-argument
- negative-argument
- universal-argument))
- (null prefix-arg)
- (progn
- (cond ((consp prefix-arg)
- (insert (format "prefix-arg (%d)\n"
- (car prefix-arg))))
- ((eq prefix-arg '-)
- (insert "prefix-arg -\n"))
- ((numberp prefix-arg)
- (insert (format "prefix-arg %d\n" prefix-arg))))
- (setq prefix-arg nil)))
- (cond ((null key-symbol)
- (insert "type \"")
- (edmacro-insert-string macro-str)
- (insert "\"\n")
- (setq macro-str ""))
- ((eq key-symbol 'digit-argument)
- (edmacro-prefix-arg key-last nil prefix-arg))
- ((eq key-symbol 'negative-argument)
- (edmacro-prefix-arg ?- nil prefix-arg))
- ((eq key-symbol 'universal-argument)
- (let* ((c-u 4) (argstartchar key-last)
- (char (edmacro-read-char)))
- (while (= char argstartchar)
- (setq c-u (* 4 c-u)
- char (edmacro-read-char)))
- (edmacro-prefix-arg char c-u nil)))
- ((eq key-symbol 'self-insert-command)
- (insert "insert ")
- (if (and (>= key-last 32) (<= key-last 126))
- (let ((str ""))
- (while (or (and (eq key-symbol
- 'self-insert-command)
- (< (length str) 60)
- (>= key-last 32)
- (<= key-last 126))
- (and (memq key-symbol
- '(backward-delete-char
- delete-backward-char
- backward-delete-char-untabify))
- (> (length str) 0)))
- (if (eq key-symbol 'self-insert-command)
- (setq str (concat str
- (char-to-string key-last)))
- (setq str (substring str 0 -1)))
- (edmacro-read-key))
- (insert "\"" str "\"\n")
- (edmacro-unread-chars key-str))
- (insert "\"")
- (edmacro-insert-string (char-to-string key-last))
- (insert "\"\n")))
- ((and (eq key-symbol 'quoted-insert)
- (edmacro-peek-char))
- (insert "quoted-insert\n")
- (let ((ch (edmacro-read-char))
- ch2)
- (if (and (>= ch ?0) (<= ch ?7))
- (progn
- (setq ch (- ch ?0)
- ch2 (edmacro-read-char))
- (if ch2
- (if (and (>= ch2 ?0) (<= ch2 ?7))
- (progn
- (setq ch (+ (* ch 8) (- ch2 ?0))
- ch2 (edmacro-read-char))
- (if ch2
- (if (and (>= ch2 ?0) (<= ch2 ?7))
- (setq ch (+ (* ch 8) (- ch2 ?0)))
- (edmacro-unread-chars ch2))))
- (edmacro-unread-chars ch2)))))
- (if (or (and (>= ch ?0) (<= ch ?7))
- (< ch 32) (> ch 126))
- (insert (format "type \"\\%03o\"\n" ch))
- (insert "type \"" (char-to-string ch) "\"\n"))))
- ((memq key-symbol '(isearch-forward
- isearch-backward
- isearch-forward-regexp
- isearch-backward-regexp))
- (insert (symbol-name key-symbol) "\n")
- (edmacro-isearch-argument))
- ((eq key-symbol 'execute-extended-command)
- (edmacro-read-argument obarray 'commandp))
- (t
- (let ((cust (get key-symbol 'edmacro-print)))
- (if cust
- (funcall cust)
- (insert (symbol-name key-symbol))
- (indent-to 30)
- (insert " # ")
- (edmacro-insert-string key-str)
- (insert "\n")
- (let ((int (edmacro-get-interactive key-symbol)))
- (if (string-match "\\`\\*" int)
- (setq int (substring int 1)))
- (while (> (length int) 0)
- (cond ((= (aref int 0) ?a)
- (edmacro-read-argument
- obarray nil))
- ((memq (aref int 0) '(?b ?B ?D ?f ?F ?n
- ?s ?S ?x ?X))
- (edmacro-read-argument))
- ((and (= (aref int 0) ?c)
- (edmacro-peek-char))
- (insert "type \"")
- (edmacro-insert-string
- (char-to-string
- (edmacro-read-char)))
- (insert "\"\n"))
- ((= (aref int 0) ?C)
- (edmacro-read-argument
- obarray 'commandp))
- ((= (aref int 0) ?k)
- (edmacro-read-key)
- (if key-symbol
- (progn
- (insert "type \"")
- (edmacro-insert-string key-str)
- (insert "\"\n"))
- (edmacro-unread-chars key-str)))
- ((= (aref int 0) ?N)
- (or this-prefix
- (edmacro-read-argument)))
- ((= (aref int 0) ?v)
- (edmacro-read-argument
- obarray 'user-variable-p)))
- (let ((nl (string-match "\n" int)))
- (setq int (if nl
- (substring int (1+ nl))
- "")))))))))))
- (use-local-map save-map))))
-
-(defun edmacro-prefix-arg (char c-u value)
- (let ((sign 1))
- (if (and (numberp value) (< value 0))
- (setq sign -1 value (- value)))
- (if (eq value '-)
- (setq sign -1 value nil))
- (while (and char (= ?- char))
- (setq sign (- sign) c-u nil)
- (setq char (edmacro-read-char)))
- (while (and char (>= char ?0) (<= char ?9))
- (setq value (+ (* (if (numberp value) value 0) 10) (- char ?0)) c-u nil)
- (setq char (edmacro-read-char)))
- (setq prefix-arg
- (cond (c-u (list c-u))
- ((numberp value) (* value sign))
- ((= sign -1) '-)))
- (edmacro-unread-chars char)))
-
-(defun edmacro-insert-string (str)
- (let ((i 0) j ch)
- (while (< i (length str))
- (if (and (> (setq ch (aref str i)) 127)
- (< ch 160))
- (progn
- (setq ch (- ch 128))
- (insert "\\M-")))
- (if (< ch 32)
- (cond ((= ch 8) (insret "\\b"))
- ((= ch 9) (insert "\\t"))
- ((= ch 10) (insert "\\n"))
- ((= ch 13) (insert "\\r"))
- ((= ch 27) (insert "\\e"))
- (t (insert "\\C-" (char-to-string (downcase (+ ch 64))))))
- (if (< ch 127)
- (if (or (= ch 34) (= ch 92))
- (insert "\\" (char-to-string ch))
- (setq j i)
- (while (and (< (setq i (1+ i)) (length str))
- (>= (setq ch (aref str i)) 32)
- (/= ch 34) (/= ch 92)
- (< ch 127)))
- (insert (substring str j i))
- (setq i (1- i)))
- (if (memq ch '(127 255))
- (insert (format "\\%03o" ch))
- (insert "\\M-" (char-to-string (- ch 128))))))
- (setq i (1+ i)))))
-
-(defun edmacro-lookup-key (map)
- (let ((loc (and map (lookup-key map macro-str)))
- (glob (lookup-key (current-global-map) macro-str))
- (loc-str macro-str)
- (glob-str macro-str))
- (and (integerp loc)
- (setq loc-str (substring macro-str 0 loc)
- loc (lookup-key map loc-str)))
- (and (consp loc)
- (setq loc nil))
- (or loc
- (setq loc-str ""))
- (and (integerp glob)
- (setq glob-str (substring macro-str 0 glob)
- glob (lookup-key (current-global-map) glob-str)))
- (and (consp glob)
- (setq glob nil))
- (or glob
- (setq glob-str ""))
- (if (> (length glob-str) (length loc-str))
- (setq key-symbol glob
- key-str glob-str)
- (setq key-symbol loc
- key-str loc-str))
- (setq key-last (and (> (length key-str) 0)
- (logand (aref key-str (1- (length key-str))) 127)))
- key-symbol))
-
-(defun edmacro-read-argument (&optional obarray pred) ;; currently ignored
- (let ((str "")
- (min-bsp 0)
- (exec (eq key-symbol 'execute-extended-command))
- str-base)
- (while (progn
- (edmacro-lookup-key (current-global-map))
- (or (and (eq key-symbol 'self-insert-command)
- (< (length str) 60))
- (memq key-symbol
- '(backward-delete-char
- delete-backward-char
- backward-delete-char-untabify))
- (eq key-last 9)))
- (setq macro-str (substring macro-str (length key-str)))
- (or (and (eq key-last 9)
- obarray
- (let ((comp (try-completion str obarray pred)))
- (and (stringp comp)
- (> (length comp) (length str))
- (setq str comp))))
- (if (or (eq key-symbol 'self-insert-command)
- (and (or (eq key-last 9)
- (<= (length str) min-bsp))
- (setq min-bsp (+ (length str) (length key-str)))))
- (setq str (concat str key-str))
- (setq str (substring str 0 -1)))))
- (setq str-base str
- str (concat str key-str)
- macro-str (substring macro-str (length key-str)))
- (if exec
- (let ((comp (try-completion str-base obarray pred)))
- (if (if (stringp comp)
- (and (commandp (intern comp))
- (setq str-base comp))
- (commandp (intern str-base)))
- (insert str-base "\n")
- (insert "execute-extended-command\n")
- (insert "type \"")
- (edmacro-insert-string str)
- (insert "\"\n")))
- (if (> (length str) 0)
- (progn
- (insert "type \"")
- (edmacro-insert-string str)
- (insert "\"\n"))))))
-
-(defun edmacro-isearch-argument ()
- (let ((str "")
- (min-bsp 0)
- ch)
- (while (and (setq ch (edmacro-read-char))
- (or (<= ch 127) (not search-exit-option))
- (not (eq ch search-exit-char))
- (or (eq ch search-repeat-char)
- (eq ch search-reverse-char)
- (eq ch search-delete-char)
- (eq ch search-yank-word-char)
- (eq ch search-yank-line-char)
- (eq ch search-quote-char)
- (eq ch ?\r)
- (eq ch ?\t)
- (not search-exit-option)
- (and (/= ch 127) (>= ch 32))))
- (if (and (eq ch search-quote-char)
- (edmacro-peek-char))
- (setq str (concat str (char-to-string ch)
- (char-to-string (edmacro-read-char)))
- min-bsp (length str))
- (if (or (and (< ch 127) (>= ch 32))
- (eq ch search-yank-word-char)
- (eq ch search-yank-line-char)
- (and (or (not (eq ch search-delete-char))
- (<= (length str) min-bsp))
- (setq min-bsp (1+ (length str)))))
- (setq str (concat str (char-to-string ch)))
- (setq str (substring str 0 -1)))))
- (if (eq ch search-exit-char)
- (if (= (length str) 0) ;; non-incremental search
- (progn
- (setq str (concat str (char-to-string ch)))
- (and (eq (edmacro-peek-char) ?\C-w)
- (progn
- (setq str (concat str "\C-w"))
- (edmacro-read-char)))
- (if (> (length str) 0)
- (progn
- (insert "type \"")
- (edmacro-insert-string str)
- (insert "\"\n")))
- (edmacro-read-argument)
- (setq str "")))
- (edmacro-unread-chars ch))
- (if (> (length str) 0)
- (progn
- (insert "type \"")
- (edmacro-insert-string str)
- (insert "\\e\"\n")))))
-
-;;; Get the next keystroke-sequence from the input stream.
-;;; Sets key-symbol, key-str, and key-last as a side effect.
-(defun edmacro-read-key ()
- (edmacro-lookup-key (current-local-map))
- (and key-symbol
- (setq macro-str (substring macro-str (length key-str)))))
-
-(defun edmacro-peek-char ()
- (and (> (length macro-str) 0)
- (aref macro-str 0)))
-
-(defun edmacro-read-char ()
- (and (> (length macro-str) 0)
- (prog1
- (aref macro-str 0)
- (setq macro-str (substring macro-str 1)))))
-
-(defun edmacro-unread-chars (chars)
- (and (integerp chars)
- (setq chars (char-to-string chars)))
- (and chars
- (setq macro-str (concat chars macro-str))))
-
-(defun edmacro-dump (mac)
- (set-mark-command nil)
- (insert "\n\n")
- (edmacro-print-macro mac (current-local-map)))
-
-;;; Parse a string of spelled-out keystrokes, as produced by key-description.
-
-(defun edmacro-parse-keys (str)
- (let ((pos 0)
- (mac "")
- part)
- (while (and (< pos (length str))
- (string-match "[^ \t\n]+" str pos))
- (setq pos (match-end 0)
- part (substring str (match-beginning 0) (match-end 0))
- mac (concat mac
- (if (and (> (length part) 2)
- (= (aref part 1) ?-)
- (= (aref part 0) ?M))
- (progn
- (setq part (substring part 2))
- "\e")
- (if (and (> (length part) 4)
- (= (aref part 0) ?C)
- (= (aref part 1) ?-)
- (= (aref part 2) ?M)
- (= (aref part 3) ?-))
- (progn
- (setq part (concat "C-" (substring part 4)))
- "\e")
- ""))
- (or (cdr (assoc part '( ( "NUL" . "\0" )
- ( "RET" . "\r" )
- ( "LFD" . "\n" )
- ( "TAB" . "\t" )
- ( "ESC" . "\e" )
- ( "SPC" . " " )
- ( "DEL" . "\177" )
- ( "C-?" . "\177" )
- ( "C-2" . "\0" )
- ( "C-SPC" . "\0") )))
- (and (equal part "REM")
- (setq pos (or (string-match "\n" str pos)
- (length str)))
- "")
- (and (= (length part) 3)
- (= (aref part 0) ?C)
- (= (aref part 1) ?-)
- (char-to-string (logand (aref part 2) 31)))
- part))))
- mac))
-
-;;; Parse a keyboard macro description in edmacro-print-macro's format.
-
-(defun edmacro-read-macro (&optional map)
- (or map (setq map (current-local-map)))
- (let ((macro-str ""))
- (while (not (progn
- (skip-chars-forward " \t\n")
- (eobp)))
- (cond ((looking-at "#")) ;; comment
- ((looking-at "prefix-arg[ \t]*-[ \t]*\n")
- (edmacro-append-chars "\C-u-"))
- ((looking-at "prefix-arg[ \t]*\\(-?[0-9]+\\)[ \t]*\n")
- (edmacro-append-chars (concat "\C-u" (edmacro-match-string 1))))
- ((looking-at "prefix-arg[ \t]*(\\([0-9]+\\))[ \t]*\n")
- (let ((val (string-to-int (edmacro-match-string 1))))
- (while (> val 1)
- (or (= (% val 4) 0)
- (error "Bad prefix argument value"))
- (edmacro-append-chars "\C-u")
- (setq val (/ val 4)))))
- ((looking-at "prefix-arg")
- (error "Bad prefix argument syntax"))
- ((looking-at "insert ")
- (forward-char 7)
- (edmacro-append-chars (read (current-buffer)))
- (if (< (current-column) 7)
- (forward-line -1)))
- ((looking-at "type ")
- (forward-char 5)
- (edmacro-append-chars (read (current-buffer)))
- (if (< (current-column) 5)
- (forward-line -1)))
- ((looking-at "keys \\(.*\\)\n")
- (goto-char (1- (match-end 0)))
- (edmacro-append-chars (edmacro-parse-keys
- (buffer-substring (match-beginning 1)
- (match-end 1)))))
- ((looking-at "\\([-a-zA-z0-9_]+\\)[ \t]*\\(.*\\)\n")
- (let* ((func (intern (edmacro-match-string 1)))
- (arg (edmacro-match-string 2))
- (cust (get func 'edmacro-read)))
- (if cust
- (funcall cust arg)
- (or (commandp func)
- (error "Not an Emacs command"))
- (or (equal arg "")
- (string-match "\\`#" arg)
- (error "Unexpected argument to command"))
- (let ((keys
- (or (where-is-internal func map t)
- (where-is-internal func (current-global-map) t))))
- (if keys
- (edmacro-append-chars keys)
- (edmacro-append-chars (concat "\ex"
- (symbol-name func)
- "\n")))))))
- (t (error "Syntax error")))
- (forward-line 1))
- macro-str))
-
-(defun edmacro-append-chars (chars)
- (setq macro-str (concat macro-str chars)))
-
-(defun edmacro-match-string (n)
- (if (match-beginning n)
- (buffer-substring (match-beginning n) (match-end n))
- ""))
-
-(defun edmacro-get-interactive (func)
- (if (symbolp func)
- (let ((cust (get func 'edmacro-interactive)))
- (if cust
- cust
- (edmacro-get-interactive (symbol-function func))))
- (or (and (eq (car-safe func) 'lambda)
- (let ((int (if (consp (nth 2 func))
- (nth 2 func)
- (nth 3 func))))
- (and (eq (car-safe int) 'interactive)
- (stringp (nth 1 int))
- (nth 1 int))))
- "")))
-
-(put 'search-forward 'edmacro-interactive "s")
-(put 'search-backward 'edmacro-interactive "s")
-(put 'word-search-forward 'edmacro-interactive "s")
-(put 'word-search-backward 'edmacro-interactive "s")
-(put 're-search-forward 'edmacro-interactive "s")
-(put 're-search-backward 'edmacro-interactive "s")
-(put 'switch-to-buffer 'edmacro-interactive "B")
-(put 'kill-buffer 'edmacro-interactive "B")
-(put 'rename-buffer 'edmacro-interactive "B\nB")
-(put 'goto-char 'edmacro-interactive "N")
-(put 'global-set-key 'edmacro-interactive "k\nC")
-(put 'global-unset-key 'edmacro-interactive "k")
-(put 'local-set-key 'edmacro-interactive "k\nC")
-(put 'local-unset-key 'edmacro-interactive "k")
-
-;;; Think about kbd-macro-query
-
-;;; Edit a keyboard macro in another buffer.
-;;; (Prefix argument is currently ignored.)
-
-(defun edmacro-edit-macro (mac repl &optional prefix buffer hook arg)
- (or (stringp mac)
- (error "Not a keyboard macro"))
- (let ((oldbuf (current-buffer))
- (local (current-local-map))
- (buf (get-buffer-create (or buffer "*Edit Macro*"))))
- (set-buffer buf)
- (kill-all-local-variables)
- (use-local-map edmacro-mode-map)
- (setq buffer-read-only nil
- major-mode 'edmacro-mode
- mode-name "Edit Macro")
- (set (make-local-variable 'edmacro-original-buffer) oldbuf)
- (set (make-local-variable 'edmacro-replace-function) repl)
- (set (make-local-variable 'edmacro-replace-argument) arg)
- (set (make-local-variable 'edmacro-finish-hook) hook)
- (erase-buffer)
- (insert "# Keyboard Macro Editor. Press C-c C-c to finish; press C-x k RET to cancel.\n")
- (insert "# Original keys: " (key-description mac) "\n\n")
- (message "Formatting keyboard macro...")
- (edmacro-print-macro mac local)
- (switch-to-buffer buf)
- (goto-char (point-min))
- (forward-line 3)
- (recenter '(4))
- (set-buffer-modified-p nil)
- (message "Formatting keyboard macro...done")
- (run-hooks 'edmacro-format-hook)))
-
-(defun edmacro-finish-edit ()
- (interactive)
- (or (and (boundp 'edmacro-original-buffer)
- (boundp 'edmacro-replace-function)
- (boundp 'edmacro-replace-argument)
- (boundp 'edmacro-finish-hook)
- (eq major-mode 'edmacro-mode))
- (error "This command is valid only in buffers created by `edit-kbd-macro'."))
- (let ((buf (current-buffer))
- (str (buffer-string))
- (func edmacro-replace-function)
- (arg edmacro-replace-argument)
- (hook edmacro-finish-hook))
- (goto-char (point-min))
- (run-hooks 'edmacro-compile-hook)
- (and (buffer-modified-p)
- func
- (progn
- (message "Compiling keyboard macro...")
- (let ((mac (edmacro-read-macro
- (and (buffer-name edmacro-original-buffer)
- (save-excursion
- (set-buffer edmacro-original-buffer)
- (current-local-map))))))
- (and (buffer-name edmacro-original-buffer)
- (switch-to-buffer edmacro-original-buffer))
- (funcall func mac arg))
- (message "Compiling keyboard macro...done")))
- (kill-buffer buf)
- (if hook
- (funcall hook arg))))
-
-(defun edmacro-mode ()
- "\\<edmacro-mode-map>Keyboard Macro Editing mode. Press \\[edmacro-finish-edit] to save and exit.
-To abort the edit, just kill this buffer with \\[kill-buffer] RET.
-
-The keyboard macro is represented as a series of M-x style command names.
-Keystrokes which do not correspond to simple M-x commands are written as
-\"type\" commands. When you press \\[edmacro-finish-edit], edmacro converts each command
-back into a suitable keystroke sequence; \"type\" commands are converted
-directly back into keystrokes."
- (interactive)
- (error "This mode can be enabled only by `edit-kbd-macro' or `edit-last-kbd-macro'."))
-(put 'edmacro-mode 'mode-class 'special)
-
-(if (boundp 'edmacro-mode-map) ()
- (setq edmacro-mode-map (make-sparse-keymap))
- (define-key edmacro-mode-map "\C-c\C-c" 'edmacro-finish-edit))
diff --git a/lisp/edt-doc.el b/lisp/edt-doc.el
new file mode 100644
index 00000000000..30cbc14799d
--- /dev/null
+++ b/lisp/edt-doc.el
@@ -0,0 +1,106 @@
+;; From mike@yetti.UUCP Fri Aug 29 12:49:28 1986
+;; Path: mit-prep!mit-hermes!mit-eddie!genrad!panda!husc6!seismo!mnetor!yetti!mike
+;; From: mike@yetti.UUCP (Mike Clarkson )
+;; Newsgroups: net.sources
+;; Subject: Gnu Emacs EDT Emulation - Introduction - 1/3
+;; Date: 27 Aug 86 23:30:33 GMT
+;; Reply-To: mike@yetti.UUCP (Mike Clarkson )
+;; Organization: York University Computer Science
+;;
+;; Here's my EDT emulation for GNU Emacs that is based on the EDT emulation
+;; for Gosling's Emacs sent out on the net a couple of years ago by Lynn Olson
+;; at Tektronics. This emulation was widely distributed as the file edt.ml
+;; in the maclib directory of most Emacs distributions.
+;;
+;; My emulation consists of two files: edt.el and edtdoc.el. The edtdoc.el file
+;; is the documentation, that you can add to the beginning of edt.el if you
+;; want. I have split them because I have been loading the edt.el file a lot
+;; during debugging.
+;;
+;; I will gladly take all criticisms and complaints to heart, and will fix
+;; what bugs I can find. As this is my first elisp hack, you may have to
+;; root out a few nasties hidden in the code. Please let me know if you
+;; find any (sorry,
+;; no rewards :-). I would also be interested if there are better,
+;; cleaner, faster ways of doing some of the things that I have done.
+;;
+;; You must understand some design considerations that I had in mind.
+;; The intention was not really to "emulate" EDT, but rather to take advantage
+;; of the years of EDT experience that had accumulated in my right hand,
+;; while at the same time taking advantage of EMACS.
+;;
+;; Some major differences are:
+;;
+;; HELP is describe-key;
+;; GOLD/HELP is describe-function;
+;; FIND is isearch-forward/backward;
+;; GOLD/HELP is occur-menu, which finds all occurrences of a search string;
+;; ENTER is other-window;
+;; SUBS is subprocess-command. Note that you will have to change this
+;; yourself to shell if you are running Un*x;
+;; PAGE is next-paragraph, because that's more useful than page.
+;; SPECINS is copy-to-killring;
+;; GOLD/GOLD is mark-section-wisely, which is my command to mark the
+;; section in a manner consistent with the major-mode. It
+;; uses mark-defun for emacs-lisp, lisp, mark-c-function for C,
+;; and mark-paragraph for other modes.
+;;
+;;
+;; Some subtle differences are:
+;;
+;; APPEND is append-to-buffer. One doesn't append to the kill ring much
+;; and SPECINS is now copy-to-killring;
+;; REPLACE is replace-regexp;
+;; FILL is fill-region-wisely, which uses indent-region for C, lisp
+;; emacs-lisp, and fill-region for others. It asks if you really
+;; want to fill-region in TeX-mode, because I find this to be
+;; very dangerous.
+;; CHNGCASE is case-flip for the character under the cursor only.
+;; I felt that case-flip region is unlikely, as usually you
+;; upcase-region or downcase region. Also, unlike EDT it
+;; is independent of the direction you are going, as that
+;; drives me nuts.
+;;
+;; I use Emacs definition of what a word is. This is considerably different from
+;; what EDT thinks a word is. This is not good for dyed-in-the-wool EDT fans,
+;; but is probably preferable for experienced Emacs users. My assumption is that
+;; the former are a dying breed now that GNU Emacs has made it to VMS, but let me
+;; know how you feel. Also, when you undelete a word it leave the point at the
+;; end of the undeleted text, rather than the beginning. I might change this
+;; as I'm not sure if I like this or not. I'm also not sure if I want it to
+;; set the mark each time you delete a character or word.
+;;
+;; Backspace does not invoke beginning-of-line, because ^H is the help prefix,
+;; and I felt it should be left as such. You can change this if you like.
+;;
+;; The ADVANCE and BACKUP keys do not work as terminators for forward or
+;; backward searches. In Emacs, all search strings are terminated by return.
+;; The searches will however go forward or backward depending on your current
+;; direction. Also, when you change directions, the mode line will not be
+;; updated immediately, but only when you next execute an emacs function.
+;; Personally, I consider this to be a bug, not a feature.
+;;
+;; This should also work with VT-2xx's, though I haven't tested it extensively
+;; on those terminals. It assumes that the CSI-map of vt_200.el has been defined.
+;;
+;; There are also a whole bunch of GOLD letter, and GOLD character bindings:
+;; look at edtdoc.el for them, or better still, look at the edt.el lisp code,
+;; because after all, in the true Lisp tradition, the source code is *assumed*
+;; to be self-documenting :-)
+;;
+;; Mike Clarkson, ...!allegra \ BITNET: mike@YUYETTI or
+;; CRESS, York University, ...!decvax \ SYMALG@YUSOL
+;; 4700 Keele Street, ...!ihnp4 > !utzoo!yetti!mike
+;; North York, Ontario, ...!linus /
+;; CANADA M3J 1P3. ...!watmath / Phone: +1 (416) 736-2100 x 7767
+;;
+;; Note that I am not on ARPA, and must gateway any ARPA mail through BITNET or
+;; UUCP. If you have a UUCP or BITNET address please use it for communication
+;; so that I can reach you directly. If you have both, the BITNET address
+;; is preferred.
+;; --
+;; Mike Clarkson, ...!allegra \ BITNET: mike@YUYETTI or
+;; CRESS, York University, ...!decvax \ SYMALG@YUSOL
+;; 4700 Keele Street, ...!ihnp4 > !utzoo!yetti!mike
+;; North York, Ontario, ...!linus /
+;; CANADA M3J 1P3. ...!watmath / Phone: +1 (416) 737-2100 x 7767
diff --git a/lisp/emulation/edt.el b/lisp/edt.el
index 5a2611d9460..8bacf8ef464 100644
--- a/lisp/emulation/edt.el
+++ b/lisp/edt.el
@@ -21,16 +21,16 @@
(require 'keypad)
(defvar edt-last-deleted-lines ""
- "Last text deleted by an EDT emulation `line-delete' command.")
+ "Last text deleted by an EDT emulation line-delete command.")
(defvar edt-last-deleted-words ""
- "Last text deleted by an EDT emulation `word-delete' command.")
+ "Last text deleted by an EDT emulation word-delete command.")
(defvar edt-last-deleted-chars ""
- "Last text deleted by an EDT emulation `character-delete' command.")
+ "Last text deleted by an EDT emulation character-delete command.")
(defun delete-current-line (num)
"Delete one or specified number of lines after point.
This includes the newline character at the end of each line.
-They are saved for the EDT `undelete-lines' command."
+They are saved for the EDT undelete-lines command."
(interactive "p")
(let ((beg (point)))
(forward-line num)
@@ -43,7 +43,7 @@ They are saved for the EDT `undelete-lines' command."
(defun delete-to-eol (num)
"Delete text up to end of line.
With argument, delete up to to Nth line-end past point.
-They are saved for the EDT `undelete-lines' command."
+They are saved for the EDT undelete-lines command."
(interactive "p")
(let ((beg (point)))
(forward-char 1)
@@ -54,7 +54,7 @@ They are saved for the EDT `undelete-lines' command."
(defun delete-current-word (num)
"Delete one or specified number of words after point.
-They are saved for the EDT `undelete-words' command."
+They are saved for the EDT undelete-words command."
(interactive "p")
(let ((beg (point)))
(forward-word num)
@@ -62,9 +62,9 @@ They are saved for the EDT `undelete-words' command."
(buffer-substring beg (point)))
(delete-region beg (point))))
-(defun edt-delete-previous-word (num)
+(defun delete-previous-word (num)
"Delete one or specified number of words before point.
-They are saved for the EDT `undelete-words' command."
+They are saved for the EDT undelete-words command."
(interactive "p")
(let ((beg (point)))
(forward-word (- num))
@@ -74,7 +74,7 @@ They are saved for the EDT `undelete-words' command."
(defun delete-current-char (num)
"Delete one or specified number of characters after point.
-They are saved for the EDT `undelete-chars' command."
+They are saved for the EDT undelete-chars command."
(interactive "p")
(setq edt-last-deleted-chars
(buffer-substring (point) (min (point-max) (+ (point) num))))
@@ -82,24 +82,24 @@ They are saved for the EDT `undelete-chars' command."
(defun delete-previous-char (num)
"Delete one or specified number of characters before point.
-They are saved for the EDT `undelete-chars' command."
+They are saved for the EDT undelete-chars command."
(interactive "p")
(setq edt-last-deleted-chars
(buffer-substring (max (point-min) (- (point) num)) (point)))
(delete-region (max (point-min) (- (point) num)) (point)))
(defun undelete-lines ()
- "Yank lines deleted by last EDT `line-delete' command."
+ "Yank lines deleted by last EDT line-deletion command."
(interactive)
(insert edt-last-deleted-lines))
(defun undelete-words ()
- "Yank words deleted by last EDT `word-delete' command."
+ "Yank words deleted by last EDT word-deletion command."
(interactive)
(insert edt-last-deleted-words))
(defun undelete-chars ()
- "Yank characters deleted by last EDT `character-delete' command."
+ "Yank characters deleted by last EDT character-deletion command."
(interactive)
(insert edt-last-deleted-chars))
@@ -185,7 +185,7 @@ Accepts a prefix argument for the number of paragraphs."
(goto-char (/ (* (point-max) perc) 100))))
(defun update-mode-line ()
- "Ensure mode-line reflects all changes."
+ "Make sure mode-line in the current buffer reflects all changes."
(set-buffer-modified-p (buffer-modified-p))
(sit-for 0))
@@ -215,17 +215,17 @@ Accepts a prefix argument for the number of paragraphs."
(define-key function-keymap "0" 'backward-line) ; "0"
(update-mode-line))
-(defun edt-beginning-of-window ()
+(defun beginning-of-window ()
"Home cursor to top of window."
(interactive)
(move-to-window-line 0))
-(defun edt-line-to-bottom-of-window ()
+(defun line-to-bottom-of-window ()
"Move the current line to the top of the window."
(interactive)
(recenter -1))
-(defun edt-line-to-top-of-window ()
+(defun line-to-top-of-window ()
"Move the current line to the top of the window."
(interactive)
(recenter 0))
@@ -264,11 +264,11 @@ and mark-paragraph for other modes."
;;; Key Bindings
(defun edt-emulation-on ()
- "Emulate DEC's EDT editor.
-Note that many keys are rebound; including nearly all keypad keys.
+ "Begin emulating DEC's EDT editor.
+Certain keys are rebound; including nearly all keypad keys.
Use \\[edt-emulation-off] to undo all rebindings except the keypad keys.
Note that this function does not work if called directly from the .emacs file.
-Instead, the .emacs file should do \"(setq term-setup-hook 'edt-emulation-on)\"
+Instead, the .emacs file should do (setq term-setup-hook 'edt-emulation-on)
Then this function will be called at the time when it will work."
(interactive)
(advance-direction)
@@ -281,7 +281,7 @@ Then this function will be called at the time when it will work."
(define-key emacs-lisp-mode-map "\177" 'delete-previous-char) ;"Delete"
(define-key lisp-mode-map "\177" 'delete-previous-char) ;"Delete"
(setq edt-mode-old-linefeed (lookup-key global-map "\C-j"))
- (global-set-key "\C-j" 'edt-delete-previous-word) ;"LineFeed"
+ (global-set-key "\C-j" 'delete-previous-word) ;"LineFeed"
(define-key esc-map "?" 'apropos)) ;"<ESC>?"
(defun edt-emulation-off ()
@@ -299,7 +299,7 @@ The keys redefined by \\[edt-emulation-on] are given their old definitions."
(define-key function-keymap "d" 'next-line) ;down arrow
(define-key function-keymap "l" 'backward-char) ;right arrow
(define-key function-keymap "r" 'forward-char) ;left arrow
-(define-key function-keymap "h" 'edt-beginning-of-window) ;home
+(define-key function-keymap "h" 'beginning-of-window) ;home
(define-key function-keymap "\C-b" 'describe-key) ;PF2
(define-key function-keymap "\C-d" 'delete-current-line);PF4
(define-key function-keymap "9" 'append-to-buffer) ;9 keypad key, etc.
@@ -312,10 +312,11 @@ The keys redefined by \\[edt-emulation-on] are given their old definitions."
(define-key function-keymap "e" 'other-window) ;enter key
(define-key function-keymap "\C-a" 'GOLD-prefix) ;PF1 ("gold")
+(setq GOLD-map (make-keymap))
(fset 'GOLD-prefix GOLD-map)
-(defvar GOLD-map (make-keymap)
- "`GOLD-map' maps the function keys on the VT100 keyboard preceeded
+(defvar GOLD-map nil
+ "GOLD-map maps the function keys on the VT100 keyboard preceeded
by the PF1 key. GOLD is the ASCII the 7-bit escape sequence <ESC>OP.")
(defun define-keypad-key (keymap function-keymap-slot definition)
@@ -365,8 +366,8 @@ by the PF1 key. GOLD is the ASCII the 7-bit escape sequence <ESC>OP.")
;Bind GOLD/Keypad keys
(defun edt-bind-gold-keypad ()
- (define-keypad-key GOLD-map ?u 'edt-line-to-top-of-window) ;"up-arrow"
- (define-keypad-key GOLD-map ?d 'edt-line-to-bottom-of-window) ;"down-arrow"
+ (define-keypad-key GOLD-map ?u 'line-to-top-of-window) ;"up-arrow"
+ (define-keypad-key GOLD-map ?d 'line-to-bottom-of-window) ;"down-arrow"
(define-keypad-key GOLD-map ?l 'backward-sentence) ;"left-arrow"
(define-keypad-key GOLD-map ?r 'forward-sentence) ;"right-arrow"
(define-keypad-key GOLD-map ?\C-a 'mark-section-wisely) ;Gold "PF1"
diff --git a/lisp/edt.elc b/lisp/edt.elc
new file mode 100644
index 00000000000..6a0a77a3c30
--- /dev/null
+++ b/lisp/edt.elc
Binary files differ
diff --git a/lisp/ehelp.el b/lisp/ehelp.el
index 9755bf07b7c..48c6c5b1692 100644
--- a/lisp/ehelp.el
+++ b/lisp/ehelp.el
@@ -20,7 +20,8 @@
(provide 'ehelp)
(defvar electric-help-map ()
- "Keymap defining commands available in `electric-help-mode'.")
+ "Keymap defining commands available whilst scrolling
+through a buffer in electric-help-mode")
(put 'electric-help-undefined 'suppress-keymap t)
(if electric-help-map
@@ -44,8 +45,8 @@
(setq electric-help-map map)))
(defun electric-help-mode ()
- "`with-electric-help' temporarily places its buffer in this mode.
-\(On exit from `with-electric-help', the buffer is put in `default-major-mode'.)"
+ "with-electric-help temporarily places its buffer in this mode
+\(On exit from with-electric-help, the buffer is put in default-major-mode)"
(setq buffer-read-only t)
(setq mode-name "Help")
(setq major-mode 'help)
@@ -56,59 +57,71 @@
)
(defun with-electric-help (thunk &optional buffer noerase)
- "Arguments are THUNK &optional BUFFER NOERASE. BUFFER defaults to \"*Help*\"
-THUNK is a function of no arguments which is called to initialize
-the contents of BUFFER. BUFFER will be erased before THUNK is called unless
-NOERASE is non-nil. THUNK will be called with `standard-output' bound to
-the buffer specified by BUFFER
+ "Arguments are THUNK &optional BUFFER NOERASE.
+BUFFER defaults to \"*Help*\"
+THUNK is a function of no arguments which is called to initialise
+ the contents of BUFFER. BUFFER will be erased before THUNK is called unless
+ NOERASE is non-nil. THUNK will be called with standard-output bound to
+ the buffer specified by BUFFER
After THUNK has been called, this function \"electrically\" pops up a window
in which BUFFER is displayed and allows the user to scroll through that buffer
in electric-help-mode.
-When the user exits (with `electric-help-exit', or otherwise) the help
-buffer's window disappears (i.e., we use `save-window-excursion')
-BUFFER is put into `default-major-mode' (or `fundamental-mode') when we exit"
+When the user exits (with electric-help-exit, or otherwise) the help
+buffer's window disappears (ie we use save-window-excursion)
+BUFFER is put into default-major-mode (or fundamental-mode) when we exit"
(setq buffer (get-buffer-create (or buffer "*Help*")))
(let ((one (one-window-p t))
- (config (current-window-configuration))
- (bury nil))
- (unwind-protect
- (save-excursion
- (if one (goto-char (window-start (selected-window))))
- (let ((pop-up-windows t))
- (pop-to-buffer buffer))
- (save-excursion
- (set-buffer buffer)
- (electric-help-mode)
- (setq buffer-read-only nil)
- (or noerase (erase-buffer)))
- (let ((standard-output buffer))
- (if (not (funcall thunk))
- (progn
- (set-buffer buffer)
- (set-buffer-modified-p nil)
- (goto-char (point-min))
- (if one (shrink-window-if-larger-than-buffer (selected-window))))))
- (set-buffer buffer)
- (run-hooks 'electric-help-mode-hook)
- (if (eq (car-safe (electric-help-command-loop))
- 'retain)
- (setq config (current-window-configuration))
- (setq bury t)))
- (message "")
- (set-buffer buffer)
- (setq buffer-read-only nil)
- (condition-case ()
- (funcall (or default-major-mode 'fundamental-mode))
- (error nil))
- (set-window-configuration config)
- (if bury
- (progn
- ;;>> Perhaps this shouldn't be done.
- ;; so that when we say "Press space to bury" we mean it
- (replace-buffer-in-windows buffer)
- ;; must do this outside of save-window-excursion
- (bury-buffer buffer))))))
+ (two nil))
+ (save-window-excursion
+ (save-excursion
+ (if one (goto-char (window-start (selected-window))))
+ (let ((pop-up-windows t))
+ (pop-to-buffer buffer))
+ (unwind-protect
+ (progn
+ (save-excursion
+ (set-buffer buffer)
+ (electric-help-mode)
+ (setq buffer-read-only nil)
+ (or noerase (erase-buffer)))
+ (let ((standard-output buffer))
+ (if (funcall thunk)
+ ()
+ (set-buffer buffer)
+ (set-buffer-modified-p nil)
+ (goto-char (point-min))
+ (if one (shrink-window-if-larger-than-buffer (selected-window)))))
+ (set-buffer buffer)
+ (run-hooks 'electric-help-mode-hook)
+ (setq two (electric-help-command-loop))
+ (cond ((eq (car-safe two) 'retain)
+ (setq two (vector (window-height (selected-window))
+ (window-start (selected-window))
+ (window-hscroll (selected-window))
+ (point))))
+ (t (setq two nil))))
+
+ (message "")
+ (set-buffer buffer)
+ (setq buffer-read-only nil)
+ (condition-case ()
+ (funcall (or default-major-mode 'fundamental-mode))
+ (error nil)))))
+ (if two
+ (let ((pop-up-windows t)
+ tem)
+ (pop-to-buffer buffer)
+ (setq tem (- (window-height (selected-window)) (elt two 0)))
+ (if (> tem 0) (shrink-window tem))
+ (set-window-start (selected-window) (elt two 1) t)
+ (set-window-hscroll (selected-window) (elt two 2))
+ (goto-char (elt two 3)))
+ ;;>> Perhaps this shouldn't be done.
+ ;; so that when we say "Press space to bury" we mean it
+ (replace-buffer-in-windows buffer)
+ ;; must do this outside of save-window-excursion
+ (bury-buffer buffer))))
(defun electric-help-command-loop ()
(catch 'exit
@@ -164,13 +177,29 @@ BUFFER is put into `default-major-mode' (or `fundamental-mode') when we exit"
(throw 'exit t))
(defun electric-help-retain ()
- "Exit `electric-help', retaining the current window/buffer configuration.
+ "Exit electric-help, retaining the current window/buffer conifiguration.
\(The *Help* buffer will not be selected, but \\[switch-to-buffer-other-window] RET
will select it.)"
(interactive)
(throw 'exit '(retain)))
+;(defun electric-help-undefined ()
+; (interactive)
+; (let* ((keys (this-command-keys))
+; (n (length keys)))
+; (if (or (= n 1)
+; (and (= n 2)
+; meta-flag
+; (eq (aref keys 0) meta-prefix-char)))
+; (setq unread-command-char last-input-char
+; current-prefix-arg prefix-arg)
+; ;;>>> I don't care.
+; ;;>>> The emacs command-loop is too much pure pain to
+; ;;>>> duplicate
+; ))
+; (throw 'exit t))
+
(defun electric-help-undefined ()
(interactive)
(error "%s is undefined -- Press %s to exit"
@@ -286,6 +315,7 @@ will select it.)"
;(define-key help-map "a" 'electric-command-apropos)
+
;;;; ehelp-map
@@ -305,3 +335,4 @@ will select it.)"
(fset 'ehelp-command map)))
;; Do (define-key global-map "\C-h" 'ehelp-command) if you want to win
+
diff --git a/lisp/ehelp.elc b/lisp/ehelp.elc
new file mode 100644
index 00000000000..552d79a2455
--- /dev/null
+++ b/lisp/ehelp.elc
Binary files differ
diff --git a/lisp/electric.el b/lisp/electric.el
index be992c60f0d..a10adb1dca7 100644
--- a/lisp/electric.el
+++ b/lisp/electric.el
@@ -31,8 +31,7 @@
(n 0)
(window-min-height 0)
(buffer-read-only nil)
- (modified (buffer-modified-p))
- (buffer (current-buffer)))
+ (modified (buffer-modified-p)))
(unwind-protect
(progn
(select-window window)
@@ -45,10 +44,8 @@
(delete-region (point-min) (point))
(set-buffer-modified-p modified)
(goto-char p)
- (select-window w)
- ;; Make sure we unbind buffer-read-only
- ;; with the proper current buffer.
- (set-buffer buffer)))))
+ (select-window w)))))
+
;; This loop is the guts for non-standard modes which retain control
;; until some event occurs. It is a `do-forever', the only way out is to
diff --git a/lisp/electric.elc b/lisp/electric.elc
new file mode 100644
index 00000000000..15323a2ed9e
--- /dev/null
+++ b/lisp/electric.elc
Binary files differ
diff --git a/lisp/emacs-lisp/ring.el b/lisp/emacs-lisp/ring.el
deleted file mode 100644
index 69b1d1995ac..00000000000
--- a/lisp/emacs-lisp/ring.el
+++ /dev/null
@@ -1,101 +0,0 @@
-;;; Ring Code
-;;;============================================================================
-;;; This code defines a ring data structure. A ring is a
-;;; (hd-index tl-index . vector)
-;;; list. You can insert to, remove from, and rotate a ring. When the ring
-;;; fills up, insertions cause the oldest elts to be quietly dropped.
-;;;
-;;; HEAD = index of the newest item on the ring.
-;;; TAIL = index of the oldest item on the ring.
-;;;
-;;; These functions are used by the input history mechanism, but they can
-;;; be used for other purposes as well.
-
-(provide 'history)
-
-(defun ring-p (x)
- "T if X is a ring; NIL otherwise."
- (and (consp x) (integerp (car x))
- (consp (cdr x)) (integerp (car (cdr x)))
- (vectorp (cdr (cdr x)))))
-
-(defun make-ring (size)
- "Make a ring that can contain SIZE elts"
- (cons 1 (cons 0 (make-vector (+ size 1) nil))))
-
-(defun ring-plus1 (index veclen)
- "INDEX+1, with wraparound"
- (let ((new-index (+ index 1)))
- (if (= new-index veclen) 0 new-index)))
-
-(defun ring-minus1 (index veclen)
- "INDEX-1, with wraparound"
- (- (if (= 0 index) veclen index) 1))
-
-(defun ring-length (ring)
- "Number of elts in the ring."
- (let ((hd (car ring)) (tl (car (cdr ring))) (siz (length (cdr (cdr ring)))))
- (let ((len (if (<= hd tl) (+ 1 (- tl hd)) (+ 1 tl (- siz hd)))))
- (if (= len siz) 0 len))))
-
-(defun ring-empty-p (ring)
- (= 0 (ring-length ring)))
-
-(defun ring-insert (ring item)
- "Insert a new item onto the ring. If the ring is full, dump the oldest
-item to make room."
- (let* ((vec (cdr (cdr ring))) (len (length vec))
- (new-hd (ring-minus1 (car ring) len)))
- (setcar ring new-hd)
- (aset vec new-hd item)
- (if (ring-empty-p ring) ;overflow -- dump one off the tail.
- (setcar (cdr ring) (ring-minus1 (car (cdr ring)) len)))))
-
-(defun ring-remove (ring)
- "Remove the oldest item retained on the ring."
- (if (ring-empty-p ring) (error "Ring empty")
- (let ((tl (car (cdr ring))) (vec (cdr (cdr ring))))
- (set-car (cdr ring) (ring-minus1 tl (length vec)))
- (aref vec tl))))
-
-;;; This isn't actually used in this package. I just threw it in in case
-;;; someone else wanted it. If you want rotating-ring behavior on your history
-;;; retrieval (analagous to kill ring behavior), this function is what you
-;;; need. I should write the yank-input and yank-pop-input-or-kill to go with
-;;; this, and not bind it to a key by default, so it would be available to
-;;; people who want to bind it to a key. But who would want it? Blech.
-(defun ring-rotate (ring n)
- (if (not (= n 0))
- (if (ring-empty-p ring) ;Is this the right error check?
- (error "ring empty")
- (let ((hd (car ring)) (tl (car (cdr ring))) (vec (cdr (cdr ring))))
- (let ((len (length vec)))
- (while (> n 0)
- (setq tl (ring-plus1 tl len))
- (aset ring tl (aref ring hd))
- (setq hd (ring-plus1 hd len))
- (setq n (- n 1)))
- (while (< n 0)
- (setq hd (ring-minus1 hd len))
- (aset vec hd (aref vec tl))
- (setq tl (ring-minus1 tl len))
- (setq n (- n 1))))
- (set-car ring hd)
- (set-car (cdr ring) tl)))))
-
-(defun comint-mod (n m)
- "Returns N mod M. M is positive. Answer is guaranteed to be non-negative,
-and less than m."
- (let ((n (% n m)))
- (if (>= n 0) n
- (+ n
- (if (>= m 0) m (- m)))))) ; (abs m)
-
-(defun ring-ref (ring index)
- (let ((numelts (ring-length ring)))
- (if (= numelts 0) (error "indexed empty ring")
- (let* ((hd (car ring)) (tl (car (cdr ring))) (vec (cdr (cdr ring)))
- (index (comint-mod index numelts))
- (vec-index (comint-mod (+ index hd)
- (length vec))))
- (aref vec vec-index)))))
diff --git a/lisp/mail/emacsbug.el b/lisp/emacsbug.el
index 061fd30ee39..cf9ef90e89d 100644
--- a/lisp/mail/emacsbug.el
+++ b/lisp/emacsbug.el
@@ -25,7 +25,7 @@
;; >> internet with this address.
(defvar bug-gnu-emacs "bug-gnu-emacs@prep.ai.mit.edu"
- "Address of site maintaining mailing list for GNU Emacs bugs.")
+ "Address of site maintaining mailing list for Gnu emacs bugs.")
(defun report-emacs-bug (topic)
"Report a bug in Gnu emacs.
diff --git a/lisp/files.el b/lisp/files.el
new file mode 100644
index 00000000000..a283bd408dc
--- /dev/null
+++ b/lisp/files.el
@@ -0,0 +1,1080 @@
+;; File input and output commands for Emacs
+;; Copyright (C) 1985, 1986, 1987, 1990 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 1, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+(defconst delete-auto-save-files t
+ "*Non-nil means delete a buffer's auto-save file
+when the buffer is saved for real.")
+
+;(make-variable-buffer-local 'buffer-backed-up)
+;(defvar buffer-backed-up nil
+; "Non-nil if this buffer's file has been backed up.
+;Backing up is done before the first time the file is saved.")
+
+;;; Turn off backup files on VMS since it has version numbers.
+(defconst make-backup-files (not (eq system-type 'vax-vms))
+ "*Create a backup of each file when it is saved for the first time.
+This can be done by renaming the file or by copying.
+
+Renaming means that Emacs renames the existing file so that it is a
+backup file, then writes the buffer into a new file. Any other names
+that the old file had will now refer to the backup file.
+The new file is owned by you and its group is defaulted.
+
+Copying means that Emacs copies the existing file into the backup file,
+then writes the buffer on top of the existing file. Any other names
+that the old file had will now refer to the new (edited) file.
+The file's owner and group are unchanged.
+
+The choice of renaming or copying is controlled by the variables
+backup-by-copying, backup-by-copying-when-linked and
+backup-by-copying-when-mismatch.")
+
+(defconst backup-by-copying nil
+ "*Non-nil means always use copying to create backup files.
+See documentation of variable make-backup-files.")
+
+(defconst backup-by-copying-when-linked nil
+ "*Non-nil means use copying to create backups for files with multiple names.
+This causes the alternate names to refer to the latest version as edited.
+This variable is relevant only if backup-by-copying is nil.")
+
+(defconst backup-by-copying-when-mismatch nil
+ "*Non-nil means create backups by copying if this preserves owner or group.
+Renaming may still be used (subject to control of other variables)
+when it would not result in changing the owner or group of the file;
+that is, for files which are owned by you and whose group matches
+the default for a new file created there by you.
+This variable is relevant only if backup-by-copying is nil.")
+
+(defconst buffer-offer-save nil
+ "*Non-nil in a buffer means offer to save the buffer on exit
+even if the buffer is not visiting a file. Automatically local in
+all buffers.")
+(make-variable-buffer-local 'buffer-offer-save)
+
+(defconst file-precious-flag nil
+ "*Non-nil means protect against I/O errors while saving files.
+Some modes set this non-nil in particular buffers.")
+
+(defvar version-control nil
+ "*Control use of version numbers for backup files.
+t means make numeric backup versions unconditionally.
+nil means make them for files that have some already.
+never means do not make them.")
+
+(defvar dired-kept-versions 2
+ "*When cleaning directory, number of versions to keep.")
+
+(defvar trim-versions-without-asking nil
+ "*If true, deletes excess backup versions silently.
+Otherwise asks confirmation.")
+
+(defvar kept-old-versions 2
+ "*Number of oldest versions to keep when a new numbered backup is made.")
+
+(defvar kept-new-versions 2
+ "*Number of newest versions to keep when a new numbered backup is made.
+Includes the new backup. Must be > 0")
+
+(defconst require-final-newline nil
+ "*t says silently put a newline at the end whenever a file is saved.
+Non-nil but not t says ask user whether to add a newline in each such case.
+nil means don't add newlines.")
+
+(defconst auto-save-default t
+ "*t says by default do auto-saving of every file-visiting buffer.")
+
+(defconst auto-save-visited-file-name nil
+ "*t says auto-save a buffer in the file it is visiting, when practical.
+Normally auto-save files are written under other names.")
+
+(defconst save-abbrevs nil
+ "*Non-nil means save word abbrevs too when files are saved.
+Loading an abbrev file sets this to t.")
+
+(defconst find-file-run-dired t
+ "*Non-nil says run dired if find-file is given the name of a directory.")
+
+(defvar find-file-not-found-hooks nil
+ "List of functions to be called for find-file on nonexistent file.
+These functions are called as soon as the error is detected.
+buffer-file-name is already set up.
+The functions are called in the order given,
+until one of them returns non-nil.")
+
+(defvar find-file-hooks nil
+ "List of functions to be called after a buffer is loaded from a file.
+The buffer's local variables (if any) will have been processed before the
+functions are called.")
+
+(defvar write-file-hooks nil
+ "List of functions to be called before writing out a buffer to a file.
+If one of them returns non-nil, the file is considered already written
+and the rest are not called.")
+
+(defconst inhibit-local-variables nil
+ "*Non-nil means query before obeying a file's local-variables list.
+This applies when the local-variables list is scanned automatically
+after you find a file. If you explicitly request such a scan with
+\\[normal-mode], there is no query, regardless of this variable.")
+
+(defconst ignore-local-eval nil
+ "*Non-nil means ignore the \"variable\" `eval' in a file's local variables.
+This applies when the local-variables list is scanned automatically
+after you find a file. If you explicitly request such a scan with
+\\[normal-mode], there is no query, regardless of this variable.")
+
+;; Avoid losing in versions where CLASH_DETECTION is disabled.
+(or (fboundp 'lock-buffer)
+ (fset 'lock-buffer 'ignore))
+(or (fboundp 'unlock-buffer)
+ (fset 'unlock-buffer 'ignore))
+
+(defun pwd ()
+ "Show the current default directory."
+ (interactive nil)
+ (message "Directory %s" default-directory))
+
+(defun cd (dir)
+ "Make DIR become the current buffer's default directory."
+ (interactive "DChange default directory: ")
+ (setq dir (expand-file-name dir))
+ (if (not (eq system-type 'vax-vms))
+ (setq dir (file-name-as-directory dir)))
+ (if (not (file-directory-p dir))
+ (error "%s is not a directory" dir)
+ (setq default-directory dir))
+ (pwd))
+
+(defun load-file (file)
+ "Load the file FILE of Lisp code."
+ (interactive "fLoad file: ")
+ (load (expand-file-name file) nil nil t))
+
+(defun load-library (library)
+ "Load the library named LIBRARY.
+This is an interface to the function `load'."
+ (interactive "sLoad library: ")
+ (load library))
+
+(defun switch-to-buffer-other-window (buffer)
+ "Select buffer BUFFER in another window."
+ (interactive "BSwitch to buffer in other window: ")
+ (let ((pop-up-windows t))
+ (pop-to-buffer buffer t)))
+
+(defun find-file (filename)
+ "Edit file FILENAME.
+Switch to a buffer visiting file FILENAME,
+creating one if none already exists."
+ (interactive "FFind file: ")
+ (switch-to-buffer (find-file-noselect filename)))
+
+(defun find-file-other-window (filename)
+ "Edit file FILENAME, in another window.
+May create a new window, or reuse an existing one;
+see the function display-buffer."
+ (interactive "FFind file in other window: ")
+ (switch-to-buffer-other-window (find-file-noselect filename)))
+
+(defun find-file-read-only (filename)
+ "Edit file FILENAME but don't save without confirmation.
+Like find-file but marks buffer as read-only."
+ (interactive "fFind file read-only: ")
+ (find-file filename)
+ (setq buffer-read-only t))
+
+(defun find-alternate-file (filename)
+ "Find file FILENAME, select its buffer, kill previous buffer.
+If the current buffer now contains an empty file that you just visited
+\(presumably by mistake), use this command to visit the file you really want."
+ (interactive "FFind alternate file: ")
+ (and (buffer-modified-p)
+;;; (not buffer-read-only)
+ (not (yes-or-no-p (format "Buffer %s is modified; kill anyway? "
+ (buffer-name))))
+ (error "Aborted"))
+ (let ((obuf (current-buffer))
+ (ofile buffer-file-name)
+ (oname (buffer-name)))
+ (rename-buffer " **lose**")
+ (setq buffer-file-name nil)
+ (unwind-protect
+ (progn
+ (unlock-buffer)
+ (find-file filename))
+ (cond ((eq obuf (current-buffer))
+ (setq buffer-file-name ofile)
+ (lock-buffer)
+ (rename-buffer oname))))
+ (or (eq obuf (current-buffer))
+ (kill-buffer obuf))))
+
+(defun create-file-buffer (filename)
+ "Create a suitably named buffer for visiting FILENAME, and return it.
+FILENAME (sans directory) is used unchanged if that name is free;
+otherwise a string <2> or <3> or ... is appended to get an unused name."
+ (let ((lastname (file-name-nondirectory filename)))
+ (if (string= lastname "")
+ (setq lastname filename))
+ (generate-new-buffer lastname)))
+
+(defconst automount-dir-prefix "^/tmp_mnt/"
+ "Regexp to match the automounter prefix in a directory name.")
+
+(defun find-file-noselect (filename &optional nowarn)
+ "Read file FILENAME into a buffer and return the buffer.
+If a buffer exists visiting FILENAME, return that one,
+but verify that the file has not changed since visited or saved.
+The buffer is not selected, just returned to the caller."
+ (setq filename (expand-file-name filename))
+ ;; Get rid of the prefixes added by the automounter.
+ (if (and (string-match automount-dir-prefix filename)
+ (file-exists-p (file-name-directory
+ (substring filename (1- (match-end 0))))))
+ (setq filename (substring filename (1- (match-end 0)))))
+ (if (file-directory-p filename)
+ (if find-file-run-dired
+ (dired-noselect filename)
+ (error "%s is a directory." filename))
+ (let ((buf (get-file-buffer filename))
+ error)
+ (if buf
+ (or nowarn
+ (verify-visited-file-modtime buf)
+ (cond ((not (file-exists-p filename))
+ (error "File %s no longer exists!" filename))
+ ((yes-or-no-p
+ (if (buffer-modified-p buf)
+ "File has changed since last visited or saved. Flush your changes? "
+ "File has changed since last visited or saved. Read from disk? "))
+ (save-excursion
+ (set-buffer buf)
+ (revert-buffer t t)))))
+ (save-excursion
+ (setq buf (create-file-buffer filename))
+ (set-buffer buf)
+ (erase-buffer)
+ (condition-case ()
+ (insert-file-contents filename t)
+ (file-error
+ (setq error t)
+ ;; Run find-file-not-found-hooks until one returns non-nil.
+ (let ((hooks find-file-not-found-hooks))
+ (while (and hooks
+ (not (funcall (car hooks))))
+ (setq hooks (cdr hooks))))))
+ (setq default-directory (file-name-directory filename))
+ (after-find-file error (not nowarn))))
+ buf)))
+
+(defun after-find-file (&optional error warn)
+ "Called after finding a file and by the default revert function.
+Sets buffer mode, parses local variables.
+Optional args ERROR and WARN: ERROR non-nil means there was an
+error in reading the file. WARN non-nil means warn if there
+exists an auto-save file more recent than the visited file.
+Finishes by calling the functions in find-file-hooks."
+ (setq buffer-read-only (not (file-writable-p buffer-file-name)))
+ (if noninteractive
+ nil
+ (let* (not-serious
+ (msg
+ (cond ((not buffer-read-only)
+ (if (and warn
+ (file-newer-than-file-p (make-auto-save-file-name)
+ buffer-file-name))
+ "Auto save file is newer; consider M-x recover-file"
+ (setq not-serious t)
+ (if error "(New file)" nil)))
+ ((not error)
+ (setq not-serious t)
+ "File is write protected")
+ ((file-attributes buffer-file-name)
+ "File exists, but is read-protected.")
+ ((file-attributes (directory-file-name default-directory))
+ "File not found and directory write-protected")
+ (t
+ "File not found and directory doesn't exist"))))
+ (if msg
+ (progn
+ (message msg)
+ (or not-serious (sit-for 1 t)))))
+ (if auto-save-default
+ (auto-save-mode t)))
+ (normal-mode t)
+ (mapcar 'funcall find-file-hooks))
+
+(defun normal-mode (&optional find-file)
+ "Choose the major mode for this buffer automatically.
+Also sets up any specified local variables of the file.
+Uses the visited file name, the -*- line, and the local variables spec.
+
+This function is called automatically from `find-file'. In that case,
+if `inhibit-local-variables' is non-`nil' we require confirmation before
+processing a local variables spec. If you run `normal-mode' explicitly,
+confirmation is never required."
+ (interactive)
+ (or find-file (funcall (or default-major-mode 'fundamental-mode)))
+ (condition-case err
+ (set-auto-mode)
+ (error (message "File mode specification error: %s"
+ (prin1-to-string err))))
+ (condition-case err
+ (hack-local-variables (not find-file))
+ (error (message "File local-variables error: %s"
+ (prin1-to-string err)))))
+
+;(defvar auto-mode-alist ...) now in loaddefs.el
+(defun set-auto-mode ()
+ "Select major mode appropriate for current buffer.
+May base decision on visited file name (See variable auto-mode-list)
+or on buffer contents (-*- line or local variables spec), but does not look
+for the \"mode:\" local variable. For that, use hack-local-variables."
+ ;; Look for -*-MODENAME-*- or -*- ... mode: MODENAME; ... -*-
+ (let (beg end mode)
+ (save-excursion
+ (goto-char (point-min))
+ (skip-chars-forward " \t\n")
+ (if (and (search-forward "-*-" (save-excursion (end-of-line) (point)) t)
+ (progn
+ (skip-chars-forward " \t")
+ (setq beg (point))
+ (search-forward "-*-" (save-excursion (end-of-line) (point)) t))
+ (progn
+ (forward-char -3)
+ (skip-chars-backward " \t")
+ (setq end (point))
+ (goto-char beg)
+ (if (search-forward ":" end t)
+ (progn
+ (goto-char beg)
+ (if (let ((case-fold-search t))
+ (search-forward "mode:" end t))
+ (progn
+ (skip-chars-forward " \t")
+ (setq beg (point))
+ (if (search-forward ";" end t)
+ (forward-char -1)
+ (goto-char end))
+ (skip-chars-backward " \t")
+ (setq mode (buffer-substring beg (point))))))
+ (setq mode (buffer-substring beg end)))))
+ (funcall (intern (concat (downcase mode) "-mode")))
+ (let ((alist auto-mode-alist)
+ (name buffer-file-name))
+ (let ((case-fold-search (eq system-type 'vax-vms)))
+ ;; Remove backup-suffixes from file name.
+ (setq name (file-name-sans-versions name))
+ ;; Find first matching alist entry.
+ (while (and (not mode) alist)
+ (if (string-match (car (car alist)) name)
+ (setq mode (cdr (car alist))))
+ (setq alist (cdr alist))))
+ (if mode (funcall mode)))))))
+
+(defun hack-local-variables (&optional force)
+ "Parse, and bind or evaluate as appropriate, any local variables
+for current buffer."
+ ;; Look for "Local variables:" line in last page.
+ (save-excursion
+ (goto-char (point-max))
+ (search-backward "\n\^L" (max (- (point-max) 3000) (point-min)) 'move)
+ (if (let ((case-fold-search t))
+ (and (search-forward "Local Variables:" nil t)
+ (or (not inhibit-local-variables)
+ force
+ (save-window-excursion
+ (switch-to-buffer (current-buffer))
+ (save-excursion
+ (beginning-of-line)
+ (set-window-start (selected-window) (point)))
+ (y-or-n-p (format "Set local variables as specified at end of %s? "
+ (file-name-nondirectory buffer-file-name)))))))
+ (let ((continue t)
+ prefix prefixlen suffix beg)
+ ;; The prefix is what comes before "local variables:" in its line.
+ ;; The suffix is what comes after "local variables:" in its line.
+ (skip-chars-forward " \t")
+ (or (eolp)
+ (setq suffix (buffer-substring (point)
+ (progn (end-of-line) (point)))))
+ (goto-char (match-beginning 0))
+ (or (bolp)
+ (setq prefix
+ (buffer-substring (point)
+ (progn (beginning-of-line) (point)))))
+ (if prefix (setq prefixlen (length prefix)
+ prefix (regexp-quote prefix)))
+ (if suffix (setq suffix (concat (regexp-quote suffix) "$")))
+ (while continue
+ ;; Look at next local variable spec.
+ (if selective-display (re-search-forward "[\n\C-m]")
+ (forward-line 1))
+ ;; Skip the prefix, if any.
+ (if prefix
+ (if (looking-at prefix)
+ (forward-char prefixlen)
+ (error "Local variables entry is missing the prefix")))
+ ;; Find the variable name; strip whitespace.
+ (skip-chars-forward " \t")
+ (setq beg (point))
+ (skip-chars-forward "^:\n")
+ (if (eolp) (error "Missing colon in local variables entry"))
+ (skip-chars-backward " \t")
+ (let* ((str (buffer-substring beg (point)))
+ (var (read str))
+ val)
+ ;; Setting variable named "end" means end of list.
+ (if (string-equal (downcase str) "end")
+ (setq continue nil)
+ ;; Otherwise read the variable value.
+ (skip-chars-forward "^:")
+ (forward-char 1)
+ (setq val (read (current-buffer)))
+ (skip-chars-backward "\n")
+ (skip-chars-forward " \t")
+ (or (if suffix (looking-at suffix) (eolp))
+ (error "Local variables entry is terminated incorrectly"))
+ ;; Set the variable. "Variables" mode and eval are funny.
+ (cond ((eq var 'mode)
+ (funcall (intern (concat (downcase (symbol-name val))
+ "-mode"))))
+ ((eq var 'force) nil)
+ ((eq var 'ignore-local-eval)
+ nil)
+ ((eq var 'eval)
+ (if (or (and ignore-local-eval (not force))
+ (string= (user-login-name) "root"))
+ (message "Ignoring `eval:' in file's local variables")
+ (eval val)))
+ (t (make-local-variable var)
+ (set var val))))))))))
+
+(defun set-visited-file-name (filename)
+ "Change name of file visited in current buffer to FILENAME.
+The next time the buffer is saved it will go in the newly specified file.
+nil or empty string as argument means make buffer not be visiting any file.
+Remember to delete the initial contents of the minibuffer
+if you wish to pass an empty string as the argument."
+ (interactive "FSet visited file name: ")
+ (if filename
+ (setq filename
+ (if (string-equal filename "")
+ nil
+ (expand-file-name filename))))
+ (or (equal filename buffer-file-name)
+ (null filename)
+ (progn
+ (lock-buffer filename)
+ (unlock-buffer)))
+ (if filename
+ (let ((new-name (file-name-nondirectory filename)))
+ (if (string= new-name "")
+ (error "Empty file name"))
+ (if (file-directory-p filename)
+ (error "File %s is a directory" filename))
+ (if (eq system-type 'vax-vms)
+ (setq new-name (downcase new-name)))
+ (setq buffer-file-name filename)
+ (setq default-directory (file-name-directory buffer-file-name))
+ (or (get-buffer new-name) (rename-buffer new-name)))
+ (setq buffer-file-name nil))
+ (setq buffer-backed-up nil)
+ (clear-visited-file-modtime)
+ ;; So that C-x C-w after ftp-find-file
+ ;; writes an ordinary local file in the ordinary way.
+ (kill-local-variable 'write-file-hooks)
+ ;; So that revert works normally after theat C-x C-w.
+ (kill-local-variable 'revert-buffer-function)
+ ;; Rename the auto-save file to go with the new visited name.
+ ;; If auto-save was not already on, turn it on if appropriate.
+ (if buffer-auto-save-file-name
+ (rename-auto-save-file)
+ (auto-save-mode (and buffer-file-name auto-save-default)))
+ (if buffer-file-name
+ (set-buffer-modified-p t)))
+
+(defun write-file (filename)
+ "Write current buffer into file FILENAME.
+Makes buffer visit that file, and marks it not modified."
+ (interactive "FWrite file: ")
+ (or (null filename) (string-equal filename "")
+ (set-visited-file-name filename))
+ (set-buffer-modified-p t)
+ (save-buffer))
+
+(defun backup-buffer ()
+ "Make a backup of the disk file visited by the current buffer, if appropriate.
+This is normally done before saving the buffer the first time.
+If the value is non-nil, it is the result of `file-modes' on the original file;
+this means that the caller, after saving the buffer, should change the modes
+of the new file to agree with the old modes."
+ (and make-backup-files
+ (not buffer-backed-up)
+ (file-exists-p buffer-file-name)
+ (memq (aref (elt (file-attributes buffer-file-name) 8) 0)
+ '(?- ?l))
+ (or (< (length buffer-file-name) 5)
+ (not (string-equal "/tmp/" (substring buffer-file-name 0 5))))
+ (condition-case ()
+ (let* ((backup-info (find-backup-file-name buffer-file-name))
+ (backupname (car backup-info))
+ (targets (cdr backup-info))
+ setmodes)
+; (if (file-directory-p buffer-file-name)
+; (error "Cannot save buffer in directory %s" buffer-file-name))
+ (condition-case ()
+ (if (or file-precious-flag
+ (file-symlink-p buffer-file-name)
+ backup-by-copying
+ (and backup-by-copying-when-linked
+ (> (file-nlinks buffer-file-name) 1))
+ (and backup-by-copying-when-mismatch
+ (let ((attr (file-attributes buffer-file-name)))
+ (or (nth 9 attr)
+ (/= (nth 2 attr) (user-uid))))))
+ (copy-file buffer-file-name backupname t t)
+ (condition-case ()
+ (delete-file backupname)
+ (file-error nil))
+ (rename-file buffer-file-name backupname t)
+ (setq setmodes (file-modes backupname)))
+ (file-error
+ ;; If trouble writing the backup, write it in ~.
+ (setq backupname (expand-file-name "~/%backup%~"))
+ (message "Cannot write backup file; backing up in ~/%%backup%%~")
+ (sleep-for 1)
+ (condition-case ()
+ (delete-file backupname)
+ (file-error nil))
+ (copy-file buffer-file-name backupname t t)))
+ (setq buffer-backed-up t)
+ (if (and targets
+ (or trim-versions-without-asking
+ (y-or-n-p (format "Delete excess backup versions of %s? "
+ buffer-file-name))))
+ (while targets
+ (condition-case ()
+ (delete-file (car targets))
+ (file-error nil))
+ (setq targets (cdr targets))))
+ setmodes)
+ (file-error nil))))
+
+(defun file-name-sans-versions (name)
+ "Return FILENAME sans backup versions or strings.
+This is a separate procedure so your site-init or startup file can
+redefine it."
+ (substring name 0
+ (if (eq system-type 'vax-vms)
+ (or (string-match ";[0-9]*\\'" name)
+ (and (string-match "\\." name (string-match "[]>]" name))
+ (string-match "\\.[0-9]*\\'" name (match-end 0))))
+ (string-match "\\(\\.~[0-9]+\\)?~\\'" name))))
+
+(defun make-backup-file-name (file)
+ "Create the non-numeric backup file name for FILE.
+This is a separate function so you can redefine it for customization."
+ (concat file "~"))
+
+(defun backup-file-name-p (file)
+ "Return non-nil if FILE is a backup file name (numeric or not).
+This is a separate function so you can redefine it for customization.
+You may need to redefine file-name-sans-versions as well."
+ (string-match "~$" file))
+
+;; I believe there is no need to alter this behavior for VMS;
+;; since backup files are not made on VMS, it should not get called.
+(defun find-backup-file-name (fn)
+ "Find a file name for a backup file, and suggestions for deletions.
+Value is a list whose car is the name for the backup file
+ and whose cdr is a list of old versions to consider deleting now."
+ (if (eq version-control 'never)
+ (list (make-backup-file-name fn))
+ (let* ((base-versions (concat (file-name-nondirectory fn) ".~"))
+ (bv-length (length base-versions))
+ (possibilities (file-name-all-completions
+ base-versions
+ (file-name-directory fn)))
+ (versions (sort (mapcar 'backup-extract-version possibilities)
+ '<))
+ (high-water-mark (apply 'max (cons 0 versions)))
+ (deserve-versions-p
+ (or version-control
+ (> high-water-mark 0)))
+ (number-to-delete (- (length versions)
+ ;; -1 compensates for the backup
+ ;; we are about to make.
+ kept-old-versions kept-new-versions -1)))
+ (if (not deserve-versions-p)
+ (list (make-backup-file-name fn))
+ (cons (concat fn ".~" (int-to-string (1+ high-water-mark)) "~")
+ (if (and (> number-to-delete 0)
+ ;; Delete nothing if there is overflow
+ ;; in the number of versions to keep.
+ (>= (+ kept-new-versions kept-old-versions -1) 0))
+ (mapcar (function (lambda (n)
+ (concat fn ".~"
+ (int-to-string n) "~")))
+ (let ((v (nthcdr kept-old-versions versions)))
+ (rplacd (nthcdr (1- number-to-delete) v) ())
+ v))))))))
+
+(defun backup-extract-version (fn)
+ (if (and (string-match "[0-9]+~$" fn bv-length)
+ (= (match-beginning 0) bv-length))
+ (string-to-int (substring fn bv-length -1))
+ 0))
+
+(defun file-nlinks (filename)
+ "Return number of names file FILENAME has."
+ (car (cdr (file-attributes filename))))
+
+(defun save-buffer (&optional args)
+ "Save current buffer in visited file if modified. Versions described below.
+
+By default, makes the previous version into a backup file
+ if previously requested or if this is the first save.
+With 1 or 3 \\[universal-argument]'s, marks this version
+ to become a backup when the next save is done.
+With 2 or 3 \\[universal-argument]'s,
+ unconditionally makes the previous version into a backup file.
+With argument of 0, never makes the previous version into a backup file.
+
+If a file's name is FOO, the names of its numbered backup versions are
+ FOO.~i~ for various integers i. A non-numbered backup file is called FOO~.
+Numeric backups (rather than FOO~) will be made if value of
+ `version-control' is not the atom `never' and either there are already
+ numeric versions of the file being backed up, or `version-control' is
+ non-nil.
+We don't want excessive versions piling up, so there are variables
+ `kept-old-versions', which tells Emacs how many oldest versions to keep,
+ and `kept-new-versions', which tells how many newest versions to keep.
+ Defaults are 2 old versions and 2 new.
+`dired-kept-versions' controls dired's clean-directory (.) command.
+If `trim-versions-without-asking' is nil, system will query user
+ before trimming versions. Otherwise it does it silently."
+ (interactive "p")
+ (let ((modp (buffer-modified-p))
+ (large (> (buffer-size) 50000))
+ (make-backup-files (and make-backup-files (not (eq args 0)))))
+ (and modp (memq args '(16 64)) (setq buffer-backed-up nil))
+ (if (and modp large) (message "Saving file %s..." (buffer-file-name)))
+ (basic-save-buffer)
+ (and modp (memq args '(4 64)) (setq buffer-backed-up nil))))
+
+(defun delete-auto-save-file-if-necessary ()
+ "Delete the auto-save filename for the current buffer (if it has one)
+if variable delete-auto-save-files is non-nil."
+ (and buffer-auto-save-file-name delete-auto-save-files
+ (not (string= buffer-file-name buffer-auto-save-file-name))
+ (progn
+ (condition-case ()
+ (delete-file buffer-auto-save-file-name)
+ (file-error nil))
+ (set-buffer-auto-saved))))
+
+(defun basic-save-buffer ()
+ "Save the current buffer in its visited file, if it has been modified."
+ (interactive)
+ (if (buffer-modified-p)
+ (let (setmodes tempsetmodes)
+ (or buffer-file-name
+ (progn
+ (setq buffer-file-name
+ (expand-file-name (read-file-name "File to save in: ") nil)
+ default-directory (file-name-directory buffer-file-name))
+ (auto-save-mode auto-save-default)))
+ (if (not (file-writable-p buffer-file-name))
+ (if (yes-or-no-p
+ (format "File %s is write-protected; try to save anyway? "
+ (file-name-nondirectory buffer-file-name)))
+ (setq tempsetmodes t)
+ (error
+ "Attempt to save to a file which you aren't allowed to write")))
+ (or (verify-visited-file-modtime (current-buffer))
+ (not (file-exists-p buffer-file-name))
+ (yes-or-no-p
+ "Disk file has changed since visited or saved. Save anyway? ")
+ (error "Save not confirmed"))
+ (or buffer-backed-up
+ (setq setmodes (backup-buffer)))
+ (save-restriction
+ (widen)
+ (and (> (point-max) 1)
+ (/= (char-after (1- (point-max))) ?\n)
+ (or (eq require-final-newline t)
+ (and require-final-newline
+ (yes-or-no-p
+ (format "Buffer %s does not end in newline. Add one? "
+ (buffer-name)))))
+ (save-excursion
+ (goto-char (point-max))
+ (insert ?\n)))
+ (let ((hooks write-file-hooks)
+ (done nil))
+ (while (and hooks
+ (not (setq done (funcall (car hooks)))))
+ (setq hooks (cdr hooks)))
+ ;; If a hook returned t, file is already "written".
+ (cond (done (setq setmodes nil))
+ ((not done)
+ (if file-precious-flag
+ ;; If file is precious, rename it away before
+ ;; overwriting it.
+ (let ((rename t) nodelete
+ (file (concat buffer-file-name "#")))
+ (condition-case ()
+ (progn (rename-file buffer-file-name file t)
+ (setq setmodes (file-modes file)))
+ (file-error (setq rename nil nodelete t)))
+ (unwind-protect
+ (progn (clear-visited-file-modtime)
+ (write-region (point-min) (point-max)
+ buffer-file-name nil t)
+ (setq rename nil))
+ ;; If rename is still t, writing failed.
+ ;; So rename the old file back to original name,
+ (if rename
+ (progn
+ (rename-file file buffer-file-name t)
+ (clear-visited-file-modtime))
+ ;; Otherwise we don't need the original file,
+ ;; so flush it. Unless we already lost it.
+ (or nodelete
+ (condition-case ()
+ (delete-file file)
+ (error nil))))))
+ ;; If file not writable, see if we can make it writable
+ ;; temporarily while we write it.
+ ;; But no need to do so if we have just backed it up
+ ;; (setmodes is set) because that says we're superseding.
+ ;; Systems with version numbers need not do this.
+ (if (eq system-type 'vax-vms)
+ (setq setmodes nil tempsetmodes nil))
+ (cond ((and tempsetmodes (not setmodes))
+ ;; Change the mode back, after writing.
+ (setq setmodes (file-modes buffer-file-name))
+ (set-file-modes buffer-file-name 511)))
+ (write-region (point-min) (point-max)
+ buffer-file-name nil t)))))
+ (if setmodes
+ (condition-case ()
+ (set-file-modes buffer-file-name setmodes)
+ (error nil))))
+ (delete-auto-save-file-if-necessary))
+ (message "(No changes need to be saved)")))
+
+(defun save-some-buffers (&optional arg exiting)
+ "Save some modified file-visiting buffers. Asks user about each one.
+Optional argument (the prefix) non-nil means save all with no questions.
+Optional second argument EXITING means ask about certain non-file buffers
+ as well as about file buffers."
+ (interactive "P")
+ (let (considered (list (buffer-list)))
+ (while list
+ (let ((buffer (car list)))
+ (and (buffer-modified-p buffer)
+ (save-excursion
+ (set-buffer buffer)
+ (and
+ (or buffer-file-name
+ (and exiting buffer-offer-save (> (buffer-size) 0)))
+ (setq considered t)
+ (or arg
+ (y-or-n-p (if buffer-file-name
+ (format "Save file %s? "
+ buffer-file-name)
+ (format "Save buffer %s? " (buffer-name)))))
+ (condition-case ()
+ (save-buffer)
+ (error nil))))))
+ (setq list (cdr list)))
+ (and save-abbrevs abbrevs-changed
+ (progn
+ (setq considered t)
+ (if (or arg
+ (y-or-n-p (format "Save abbrevs in %s? " abbrev-file-name)))
+ (write-abbrev-file nil))
+ ;; Don't keep bothering user if he says no.
+ (setq abbrevs-changed nil)))
+ (if considered
+ (message "")
+ (message "(No files need saving)"))))
+
+(defun not-modified ()
+ "Mark current buffer as unmodified, not needing to be saved."
+ (interactive)
+ (message "Modification-flag cleared")
+ (set-buffer-modified-p nil))
+
+(defun toggle-read-only ()
+ "Change whether this buffer is visiting its file read-only."
+ (interactive)
+ (setq buffer-read-only (not buffer-read-only))
+ ;; Force mode-line redisplay
+ (set-buffer-modified-p (buffer-modified-p)))
+
+(defun insert-file (filename)
+ "Insert contents of file FILENAME into buffer after point.
+Set mark after the inserted text."
+ (interactive "fInsert file: ")
+ (let ((tem (insert-file-contents filename)))
+ (push-mark (+ (point) (car (cdr tem))))))
+
+(defun append-to-file (start end filename)
+ "Append the contents of the region to the end of file FILENAME.
+When called from a function, expects three arguments,
+START, END and FILENAME. START and END are buffer positions
+saying what text to write."
+ (interactive "r\nFAppend to file: ")
+ (write-region start end filename t))
+
+(defvar revert-buffer-function nil
+ "Function to use to revert this buffer, or nil to do the default.")
+
+(defun revert-buffer (&optional arg noconfirm)
+ "Replace the buffer text with the text of the visited file on disk.
+This undoes all changes since the file was visited or saved.
+If latest auto-save file is more recent than the visited file,
+asks user whether to use that instead.
+First argument (optional) non-nil means don't offer to use auto-save file.
+ This is the prefix arg when called interactively.
+
+Second argument (optional) non-nil means don't ask for confirmation at all.
+
+If revert-buffer-function's value is non-nil, it is called to do the work."
+ (interactive "P")
+ (if revert-buffer-function
+ (funcall revert-buffer-function arg noconfirm)
+ (let* ((opoint (point))
+ (auto-save-p (and (null arg) (recent-auto-save-p)
+ buffer-auto-save-file-name
+ (file-readable-p buffer-auto-save-file-name)
+ (y-or-n-p
+ "Buffer has been auto-saved recently. Revert from auto-save file? ")))
+ (file-name (if auto-save-p
+ buffer-auto-save-file-name
+ buffer-file-name)))
+ (cond ((null file-name)
+ (error "Buffer does not seem to be associated with any file"))
+ ((not (file-exists-p file-name))
+ (error "File %s no longer exists!" file-name))
+ ((or noconfirm
+ (yes-or-no-p (format "Revert buffer from file %s? "
+ file-name)))
+ ;; If file was backed up but has changed since,
+ ;; we shd make another backup.
+ (and (not auto-save-p)
+ (not (verify-visited-file-modtime (current-buffer)))
+ (setq buffer-backed-up nil))
+ ;; Discard all the undo information.
+ (or (eq buffer-undo-list t)
+ (setq buffer-undo-list nil))
+ (let ((buffer-read-only nil)
+ ;; Don't record undo info for the revert itself.
+ ;; Doing so chews up too much storage.
+ (buffer-undo-list t))
+ ;; Bind buffer-file-name to nil
+ ;; so that we don't try to lock the file.
+ (let ((buffer-file-name nil))
+ (or auto-save-p
+ (unlock-buffer))
+ (erase-buffer))
+ (insert-file-contents file-name (not auto-save-p)))
+ (goto-char (min opoint (point-max)))
+ (after-find-file nil)
+ t)))))
+
+(defun recover-file (file)
+ "Visit file FILE, but get contents from its last auto-save file."
+ (interactive "FRecover file: ")
+ (setq file (expand-file-name file))
+ (if (auto-save-file-name-p file) (error "%s is an auto-save file" file))
+ (let ((file-name (let ((buffer-file-name file))
+ (make-auto-save-file-name))))
+ (cond ((not (file-newer-than-file-p file-name file))
+ (error "Auto-save file %s not current" file-name))
+ ((save-window-excursion
+ (if (not (eq system-type 'vax-vms))
+ (with-output-to-temp-buffer "*Directory*"
+ (buffer-flush-undo standard-output)
+ (call-process "ls" nil standard-output nil
+ "-l" file file-name)))
+ (yes-or-no-p (format "Recover auto save file %s? " file-name)))
+ (switch-to-buffer (find-file-noselect file t))
+ (let ((buffer-read-only nil))
+ (erase-buffer)
+ (insert-file-contents file-name nil))
+ (after-find-file nil))
+ (t (error "Recover-file cancelled."))))
+ (setq buffer-auto-save-file-name nil)
+ (message "Auto-save off in this buffer till you do M-x auto-save-mode."))
+
+(defun kill-some-buffers ()
+ "For each buffer, ask whether to kill it."
+ (interactive)
+ (let ((list (buffer-list)))
+ (while list
+ (let* ((buffer (car list))
+ (name (buffer-name buffer)))
+ (and (not (string-equal name ""))
+ (/= (aref name 0) ? )
+ (yes-or-no-p
+ (format "Buffer %s %s. Kill? "
+ name
+ (if (buffer-modified-p buffer)
+ "HAS BEEN EDITED" "is unmodified")))
+ (kill-buffer buffer)))
+ (setq list (cdr list)))))
+
+(defun auto-save-mode (arg)
+ "Toggle auto-saving of contents of current buffer.
+With arg, turn auto-saving on if arg is positive, else off."
+ (interactive "P")
+ (setq buffer-auto-save-file-name
+ (and (if (null arg)
+ (not buffer-auto-save-file-name)
+ (or (eq arg t) (listp arg) (and (integerp arg) (> arg 0))))
+ (if (and buffer-file-name auto-save-visited-file-name
+ (not buffer-read-only))
+ buffer-file-name
+ (make-auto-save-file-name))))
+ (if (interactive-p)
+ (message "Auto-save %s (in this buffer)"
+ (if buffer-auto-save-file-name "on" "off")))
+ buffer-auto-save-file-name)
+
+(defun rename-auto-save-file ()
+ "Adjust current buffer's auto save file name for current conditions.
+Also rename any existing auto save file."
+ (let ((osave buffer-auto-save-file-name))
+ (setq buffer-auto-save-file-name
+ (make-auto-save-file-name))
+ (if (and osave buffer-auto-save-file-name
+ (not (string= buffer-auto-save-file-name buffer-file-name))
+ (not (string= buffer-auto-save-file-name osave))
+ (file-exists-p osave))
+ (rename-file osave buffer-auto-save-file-name t))))
+
+(defun make-auto-save-file-name ()
+ "Return file name to use for auto-saves of current buffer.
+Does not consider auto-save-visited-file-name; that is checked
+before calling this function.
+You can redefine this for customization.
+See also auto-save-file-name-p."
+ (if buffer-file-name
+ (concat (file-name-directory buffer-file-name)
+ "#"
+ (file-name-nondirectory buffer-file-name)
+ "#")
+ (expand-file-name (concat "#%" (buffer-name) "#"))))
+
+(defun auto-save-file-name-p (filename)
+ "Return non-nil if FILENAME can be yielded by make-auto-save-file-name.
+FILENAME should lack slashes.
+You can redefine this for customization."
+ (string-match "^#.*#$" filename))
+
+(defconst list-directory-brief-switches "-CF"
+ "*Switches for list-directory to pass to `ls' for brief listing,")
+(defconst list-directory-verbose-switches "-l"
+ "*Switches for list-directory to pass to `ls' for verbose listing,")
+
+(defun list-directory (dirname &optional verbose)
+ "Display a list of files in or matching DIRNAME, a la `ls'.
+DIRNAME is globbed by the shell if necessary.
+Prefix arg (second arg if noninteractive) means supply -l switch to `ls'.
+Actions controlled by variables list-directory-brief-switches
+ and list-directory-verbose-switches."
+ (interactive (let ((pfx current-prefix-arg))
+ (list (read-file-name (if pfx "List directory (verbose): "
+ "List directory (brief): ")
+ nil default-directory nil)
+ pfx)))
+ (let ((switches (if verbose list-directory-verbose-switches
+ list-directory-brief-switches))
+ full-dir-p)
+ (or dirname (setq dirname default-directory))
+ (if (file-directory-p dirname)
+ (progn
+ (setq full-dir-p t)
+ (or (string-match "/$" dirname)
+ (setq dirname (concat dirname "/")))))
+ (setq dirname (expand-file-name dirname))
+ (with-output-to-temp-buffer "*Directory*"
+ (buffer-flush-undo standard-output)
+ (princ "Directory ")
+ (princ dirname)
+ (terpri)
+ (if full-dir-p
+ (call-process "ls" nil standard-output nil
+ switches dirname)
+ (let ((default-directory (file-name-directory dirname)))
+ (call-process shell-file-name nil standard-output nil
+ "-c" (concat "exec ls "
+ switches " "
+ (file-name-nondirectory dirname))))))))
+
+(defun save-buffers-kill-emacs (&optional arg)
+ "Offer to save each buffer, then kill this Emacs fork.
+With prefix arg, silently save all file-visiting buffers, then kill."
+ (interactive "P")
+ (save-some-buffers arg t)
+ (and (or (not (memq t (mapcar (function
+ (lambda (buf) (and (buffer-file-name buf)
+ (buffer-modified-p buf))))
+ (buffer-list))))
+ (yes-or-no-p "Modified buffers exist; exit anyway? "))
+ (or (not (fboundp 'process-list))
+ ;; process-list is not defined on VMS.
+ (let ((processes (process-list))
+ active)
+ (while processes
+ (and (memq (process-status (car processes)) '(run stop open))
+ (let ((val (process-kill-without-query (car processes))))
+ (process-kill-without-query (car processes) val)
+ val)
+ (setq active t))
+ (setq processes (cdr processes)))
+ (or (not active)
+ (yes-or-no-p "Active processes exist; kill them and exit anyway? "))))
+ (kill-emacs)))
+
+(define-key ctl-x-map "\C-f" 'find-file)
+(define-key ctl-x-map "\C-q" 'toggle-read-only)
+(define-key ctl-x-map "\C-r" 'find-file-read-only)
+(define-key ctl-x-map "\C-v" 'find-alternate-file)
+(define-key ctl-x-map "\C-s" 'save-buffer)
+(define-key ctl-x-map "s" 'save-some-buffers)
+(define-key ctl-x-map "\C-w" 'write-file)
+(define-key ctl-x-map "i" 'insert-file)
+(define-key esc-map "~" 'not-modified)
+(define-key ctl-x-map "\C-d" 'list-directory)
+(define-key ctl-x-map "\C-c" 'save-buffers-kill-emacs)
+
+(defvar ctl-x-4-map (make-keymap)
+ "Keymap for subcommands of C-x 4")
+(fset 'ctl-x-4-prefix ctl-x-4-map)
+(define-key ctl-x-map "4" 'ctl-x-4-prefix)
+(define-key ctl-x-4-map "f" 'find-file-other-window)
+(define-key ctl-x-4-map "\C-f" 'find-file-other-window)
+(define-key ctl-x-4-map "b" 'switch-to-buffer-other-window)
diff --git a/lisp/files.elc b/lisp/files.elc
new file mode 100644
index 00000000000..c02660144fa
--- /dev/null
+++ b/lisp/files.elc
Binary files differ
diff --git a/lisp/fill.el b/lisp/fill.el
new file mode 100644
index 00000000000..e514fa14cd2
--- /dev/null
+++ b/lisp/fill.el
@@ -0,0 +1,287 @@
+;; Fill commands for Emacs
+;; Copyright (C) 1985, 1986, 1992 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 1, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+(defconst fill-individual-varying-indent nil
+ "*Controls criterion for a new paragraph in `fill-individual-paragraphs'.
+Non-nil means changing indent doesn't end a paragraph.
+That mode can handle paragraphs with extra indentation on the first line,
+but it requires separator lines between paragraphs.
+Nil means that any change in indentation starts a new paragraph.")
+
+(defun set-fill-prefix ()
+ "Set the fill-prefix to the current line up to point.
+Filling expects lines to start with the fill prefix
+and reinserts the fill prefix in each resulting line."
+ (interactive)
+ (setq fill-prefix (buffer-substring
+ (save-excursion (beginning-of-line) (point))
+ (point)))
+ (if (equal fill-prefix "")
+ (setq fill-prefix nil))
+ (if fill-prefix
+ (message "fill-prefix: \"%s\"" fill-prefix)
+ (message "fill-prefix cancelled")))
+
+(defun fill-region-as-paragraph (from to &optional justify-flag)
+ "Fill region as one paragraph: break lines to fit fill-column.
+Prefix arg means justify too.
+From program, pass args FROM, TO and JUSTIFY-FLAG."
+ (interactive "r\nP")
+ (save-restriction
+ (narrow-to-region from to)
+ (goto-char (point-min))
+ (skip-chars-forward "\n")
+ (narrow-to-region (point) (point-max))
+ (setq from (point))
+ (let ((fpre (and fill-prefix (not (equal fill-prefix ""))
+ (regexp-quote fill-prefix))))
+ ;; Delete the fill prefix from every line except the first.
+ ;; The first line may not even have a fill prefix.
+ (and fpre
+ (progn
+ (if (>= (length fill-prefix) fill-column)
+ (error "fill-prefix too long for specified width"))
+ (goto-char (point-min))
+ (forward-line 1)
+ (while (not (eobp))
+ (if (looking-at fpre)
+ (delete-region (point) (match-end 0)))
+ (forward-line 1))
+ (goto-char (point-min))
+ (and (looking-at fpre) (forward-char (length fill-prefix)))
+ (setq from (point)))))
+ ;; from is now before the text to fill,
+ ;; but after any fill prefix on the first line.
+
+ ;; Make sure sentences ending at end of line get an extra space.
+ (goto-char from)
+ (while (re-search-forward "[.?!][])""']*$" nil t)
+ (insert ? ))
+ ;; The change all newlines to spaces.
+ (subst-char-in-region from (point-max) ?\n ?\ )
+ ;; Flush excess spaces, except in the paragraph indentation.
+ (goto-char from)
+ (skip-chars-forward " \t")
+ (while (re-search-forward " *" nil t)
+ (delete-region
+ (+ (match-beginning 0)
+ (if (save-excursion
+ (skip-chars-backward " ])\"'")
+ (memq (preceding-char) '(?. ?? ?!)))
+ 2 1))
+ (match-end 0)))
+ (goto-char (point-max))
+ (delete-horizontal-space)
+ (insert " ")
+ (goto-char (point-min))
+ (let ((prefixcol 0) linebeg)
+ (while (not (eobp))
+ (setq linebeg (point))
+ (move-to-column (1+ fill-column))
+ (if (eobp)
+ nil
+ ;; Move back to start of word.
+ (skip-chars-backward "^ \n" linebeg)
+ (if (if (zerop prefixcol) (bolp) (>= prefixcol (current-column)))
+ ;; Keep at least one word even if fill prefix exceeds margin.
+ ;; This handles all but the first line of the paragraph.
+ (progn
+ (skip-chars-forward " ")
+ (skip-chars-forward "^ \n"))
+ ;; Normally, move back over the single space between the words.
+ (forward-char -1)))
+ (if (and fill-prefix (zerop prefixcol)
+ (< (- (point) (point-min)) (length fill-prefix))
+ (string= (buffer-substring (point-min) (point))
+ (substring fill-prefix 0 (- (point) (point-min)))))
+ ;; Keep at least one word even if fill prefix exceeds margin.
+ ;; This handles the first line of the paragraph.
+ (progn
+ (skip-chars-forward " ")
+ (skip-chars-forward "^ \n")))
+ ;; Replace all whitespace here with one newline.
+ ;; Insert before deleting, so we don't forget which side of
+ ;; the whitespace point or markers used to be on.
+ (skip-chars-backward " ")
+ (insert ?\n)
+ (delete-horizontal-space)
+ ;; Insert the fill prefix at start of each line.
+ ;; Set prefixcol so whitespace in the prefix won't get lost.
+ (and (not (eobp)) fill-prefix (not (equal fill-prefix ""))
+ (progn
+ (insert fill-prefix)
+ (setq prefixcol (current-column))))
+ ;; Justify the line just ended, if desired.
+ (and justify-flag (not (eobp))
+ (progn
+ (forward-line -1)
+ (justify-current-line)
+ (forward-line 1)))))))
+
+(defun fill-paragraph (arg)
+ "Fill paragraph at or after point.
+Prefix arg means justify as well."
+ (interactive "P")
+ (save-excursion
+ (forward-paragraph)
+ (or (bolp) (newline 1))
+ (let ((end (point)))
+ (backward-paragraph)
+ (fill-region-as-paragraph (point) end arg))))
+
+(defun fill-region (from to &optional justify-flag)
+ "Fill each of the paragraphs in the region.
+Prefix arg (non-nil third arg, if called from program)
+means justify as well."
+ (interactive "r\nP")
+ (save-restriction
+ (narrow-to-region from to)
+ (goto-char (point-min))
+ (while (not (eobp))
+ (let ((initial (point))
+ (end (progn
+ (forward-paragraph 1) (point))))
+ (forward-paragraph -1)
+ (if (>= (point) initial)
+ (fill-region-as-paragraph (point) end justify-flag)
+ (goto-char end))))))
+
+(defun justify-current-line ()
+ "Add spaces to line point is in, so it ends at fill-column."
+ (interactive)
+ (save-excursion
+ (save-restriction
+ (let (ncols nwhites beg indent flags)
+ (beginning-of-line)
+ (forward-char (length fill-prefix))
+ (skip-chars-forward " \t")
+ (setq indent (current-column))
+ (setq beg (point))
+ (end-of-line)
+ (narrow-to-region beg (point))
+ (goto-char beg)
+ (while (re-search-forward " *" nil t)
+ (delete-region
+ (+ (match-beginning 0)
+ (if (save-excursion
+ (skip-chars-backward " ])\"'")
+ (memq (preceding-char) '(?. ?? ?!)))
+ 2 1))
+ (match-end 0)))
+ (goto-char beg)
+ (while (re-search-forward "[.?!][])""']*\n" nil t)
+ (forward-char -1)
+ (insert ? ))
+ (goto-char (point-max))
+ ;; Note that the buffer bounds start after the indentation,
+ ;; so the columns counted by INDENT don't appear in (current-column).
+ (setq ncols (- fill-column (current-column) indent))
+ ;; Count word-boundaries in the line.
+ (setq nwhites 0)
+ (while (search-backward " " nil t)
+ (skip-chars-backward " ")
+ (setq nwhites (1+ nwhites)))
+ (if (> nwhites 0)
+ (progn
+ ;; Add space uniformly as far as we can.
+ (goto-char (point-max))
+ (while (search-backward " " nil t)
+ (insert-char ?\ (/ ncols nwhites))
+ (skip-chars-backward " "))
+ ;; Make a bit vector for where to add the rest.
+ (setq ncols (% ncols nwhites))
+ (setq flags (make-string nwhites 0))
+ ;; Randomly set NCOLS different bits.
+ (while (> ncols 0)
+ (let ((where (% (logand 262143 (random)) nwhites)))
+ (or (> (aref flags where) 0)
+ (progn
+ (aset flags where 1)
+ (setq ncols (1- ncols))))))
+ ;; Insert a space at the boundaries flagged in the vector.
+ (goto-char (point-max))
+ (let ((where 0))
+ (while (search-backward " " nil t)
+ (if (> (aref flags where) 0)
+ (insert " "))
+ (setq where (1+ where))
+ (skip-chars-backward " ")))))))))
+
+(defun fill-individual-paragraphs (min max &optional justifyp mailp)
+ "Fill each paragraph in region according to its individual fill prefix.
+
+If `fill-individual-varying-indent' is non-nil,
+then a mere change in indentation does not end a paragraph. In this mode,
+the indentation for a paragraph is the minimum indentation of any line in it.
+
+Calling from a program, pass range to fill as first two arguments.
+
+Optional third and fourth arguments JUSTIFY-FLAG and MAIL-FLAG:
+JUSTIFY-FLAG to justify paragraphs (prefix arg),
+MAIL-FLAG for a mail message, i. e. don't fill header lines."
+ (interactive "r\nP")
+ (save-restriction
+ (save-excursion
+ (goto-char min)
+ (beginning-of-line)
+ (if mailp
+ (while (looking-at "[^ \t\n]*:")
+ (forward-line 1)))
+ (narrow-to-region (point) max)
+ ;; Loop over paragraphs.
+ (while (progn (skip-chars-forward " \t\n") (not (eobp)))
+ (beginning-of-line)
+ (let ((start (point))
+ fill-prefix fill-prefix-regexp)
+ ;; Find end of paragraph, and compute the smallest fill-prefix
+ ;; that fits all the lines in this paragraph.
+ (while (progn
+ ;; Update the fill-prefix on the first line
+ ;; and whenever the prefix good so far is too long.
+ (if (not (and fill-prefix
+ (looking-at fill-prefix-regexp)))
+ (setq fill-prefix
+ (buffer-substring (point)
+ (save-excursion (skip-chars-forward " \t") (point)))
+ fill-prefix-regexp
+ (regexp-quote fill-prefix)))
+ (forward-line 1)
+ ;; Now stop the loop if end of paragraph.
+ (and (not (eobp))
+ (if fill-individual-varying-indent
+ ;; If this line is a separator line, with or
+ ;; without prefix, end the paragraph.
+ (and
+ (not (looking-at paragraph-separate))
+ (save-excursion
+ (not (and (looking-at fill-prefix-regexp)
+ (progn (forward-char (length fill-prefix))
+ (looking-at paragraph-separate))))))
+ ;; If this line has more or less indent
+ ;; than the fill prefix wants, end the paragraph.
+ (and (looking-at fill-prefix-regexp)
+ (save-excursion
+ (not (progn (forward-char (length fill-prefix))
+ (or (looking-at paragraph-separate)
+ (looking-at paragraph-start))))))))))
+ ;; Fill this paragraph, but don't add a newline at the end.
+ (let ((had-newline (bolp)))
+ (fill-region-as-paragraph start (point) justifyp)
+ (or had-newline (delete-char -1))))))))
+
diff --git a/lisp/fill.elc b/lisp/fill.elc
new file mode 100644
index 00000000000..5474adf9d4e
--- /dev/null
+++ b/lisp/fill.elc
Binary files differ
diff --git a/lisp/find-gc.el b/lisp/find-gc.el
deleted file mode 100644
index 3504d2949d8..00000000000
--- a/lisp/find-gc.el
+++ /dev/null
@@ -1,127 +0,0 @@
-;;;; find-gc.el
-
-
-;;; Produce in unsafe-list the set of all functions that may invoke GC.
-;;; This expects the Emacs sources to live in emacs-source-directory.
-;;; It creates a temporary working directory /tmp/esrc.
-
-(defun find-gc-unsafe ()
- (trace-call-tree nil)
- (trace-use-tree)
- (find-unsafe-funcs 'Fgarbage_collect)
- (setq unsafe-list (sort unsafe-list
- (function (lambda (x y)
- (string-lessp (car x) (car y))))))
-)
-
-(setq emacs-source-directory "/usr/gnu/src/dist/src")
-
-
-;;; This does a depth-first search to find all functions that can
-;;; ultimately call the function "target". The result is an a-list
-;;; in unsafe-list; the cars are the unsafe functions, and the cdrs
-;;; are (one of) the unsafe functions that these functions directly
-;;; call.
-
-(defun find-unsafe-funcs (target)
- (setq unsafe-list (list (list target)))
- (trace-unsafe target)
-)
-
-(defun trace-unsafe (func)
- (let ((used (assq func subrs-used)))
- (or used
- (error "No subrs-used for %s" (car unsafe-list)))
- (while (setq used (cdr used))
- (or (assq (car used) unsafe-list)
- (memq (car used) noreturn-list)
- (progn
- (setq unsafe-list (cons (cons (car used) func) unsafe-list))
- (trace-unsafe (car used))))))
-)
-
-
-;;; Functions on this list are safe, even if they appear to be able
-;;; to call the target.
-
-(setq noreturn-list '( Fsignal Fthrow wrong_type_argument ))
-
-
-;;; This produces an a-list of functions in subrs-called. The cdr of
-;;; each entry is a list of functions which the function in car calls.
-
-(defun trace-call-tree (&optional already-setup)
- (message "Setting up directories...")
- (or already-setup
- (progn
- ;; Gee, wouldn't a built-in "system" function be handy here.
- (call-process "csh" nil nil nil "-c" "rm -rf /tmp/esrc")
- (call-process "csh" nil nil nil "-c" "mkdir /tmp/esrc")
- (call-process "csh" nil nil nil "-c"
- (format "ln -s %s/*.[ch] /tmp/esrc"
- emacs-source-directory))))
- (save-excursion
- (set-buffer (get-buffer-create "*Trace Call Tree*"))
- (setq subrs-called nil)
- (let ((case-fold-search nil)
- (files source-files)
- name entry)
- (while files
- (message "Compiling %s..." (car files))
- (call-process "csh" nil nil nil "-c"
- (format "gcc -dr -c /tmp/esrc/%s -o /dev/null"
- (car files)))
- (erase-buffer)
- (insert-file-contents (concat "/tmp/esrc/" (car files) ".rtl"))
- (while (re-search-forward ";; Function \\|(call_insn " nil t)
- (if (= (char-after (- (point) 3)) ?o)
- (progn
- (looking-at "[a-zA-Z0-9_]+")
- (setq name (intern (buffer-substring (match-beginning 0)
- (match-end 0))))
- (message "%s : %s" (car files) name)
- (setq entry (list name)
- subrs-called (cons entry subrs-called)))
- (if (looking-at ".*\n?.*\"\\([A-Za-z0-9_]+\\)\"")
- (progn
- (setq name (intern (buffer-substring (match-beginning 1)
- (match-end 1))))
- (or (memq name (cdr entry))
- (setcdr entry (cons name (cdr entry))))))))
- (delete-file (concat "/tmp/esrc/" (car files) ".rtl"))
- (setq files (cdr files)))))
-)
-
-
-;;; This was originally generated directory-files, but there were
-;;; too many files there that were not actually compiled. The
-;;; list below was created for a HP-UX 7.0 system.
-
-(setq source-files '("dispnew.c" "scroll.c" "xdisp.c" "window.c"
- "term.c" "cm.c" "emacs.c" "keyboard.c" "macros.c"
- "keymap.c" "sysdep.c" "buffer.c" "filelock.c"
- "insdel.c" "marker.c" "minibuf.c" "fileio.c"
- "dired.c" "filemode.c" "cmds.c" "casefiddle.c"
- "indent.c" "search.c" "regex.c" "undo.c"
- "alloc.c" "data.c" "doc.c" "editfns.c"
- "callint.c" "eval.c" "fns.c" "print.c" "lread.c"
- "abbrev.c" "syntax.c" "unexec.c" "mocklisp.c"
- "bytecode.c" "process.c" "callproc.c" "doprnt.c"
- "x11term.c" "x11fns.c"))
-
-
-;;; This produces an inverted a-list in subrs-used. The cdr of each
-;;; entry is a list of functions that call the function in car.
-
-(defun trace-use-tree ()
- (setq subrs-used (mapcar 'list (mapcar 'car subrs-called)))
- (let ((ptr subrs-called)
- p2 found)
- (while ptr
- (setq p2 (car ptr))
- (while (setq p2 (cdr p2))
- (if (setq found (assq (car p2) subrs-used))
- (setcdr found (cons (car (car ptr)) (cdr found)))))
- (setq ptr (cdr ptr))))
-)
-
diff --git a/lisp/flame.el b/lisp/flame.el
new file mode 100644
index 00000000000..0f6d57852eb
--- /dev/null
+++ b/lisp/flame.el
@@ -0,0 +1,306 @@
+;;; "Flame" program. This has a chequered past.
+;;;
+;;; The original was on a Motorola 286 running Vanilla V.1,
+;;; about 2 years ago. It was couched in terms of a yacc (I think)
+;;; script. I pulled the data out of it and rewrote it as a piece
+;;; of PL/1 on Multics. Now I've moved it into an emacs-lisp
+;;; form. If the original author cares to contact me, I'd
+;;; be very happy to credit you!
+;;;
+;;; Ian G. Batten, Batten@uk.ac.bham.multics
+;;;
+
+(random t)
+
+(defvar sentence
+ '((how can you say that (statement) \?)
+ (I can\'t believe how (adjective) you are\.)
+ (only a (der-term) like you would say that (statement) \.)
+ ((statement) \, huh\?) (so\, (statement) \?)
+ ((statement) \, right\?) (I mean\, (sentence))
+ (don\'t you realise that (statement) \?)
+ (I firmly believe that (statement) \.)
+ (let me tell you something\, you (der-term) \, (statement) \.)
+ (furthermore\, you (der-term) \, (statement) \.)
+ (I couldn\'t care less about your (thing) \.)
+ (How can you be so (adjective) \?)
+ (you make me sick\.)
+ (it\'s well known that (statement) \.)
+ ((statement) \.)
+ (it takes a (group-adj) (der-term) like you to say that (statement) \.)
+ (I don\'t want to hear about your (thing) \.)
+ (you\'re always totally wrong\.)
+ (I\'ve never heard anything as ridiculous as the idea that (statement) \.)
+ (you must be a real (der-term) to think that (statement) \.)
+ (you (adjective) (group-adj) (der-term) \!)
+ (you\'re probably (group-adj) yourself\.)
+ (you sound like a real (der-term) \.)
+ (why\, (statement) \!)
+ (I have many (group-adj) friends\.)
+ (save the (thing) s\!) (no nukes\!) (ban (thing) s\!)
+ (I\'ll bet you think that (thing) s are (adjective) \.)
+ (you know\, (statement) \.)
+ (your (quality) reminds me of a (thing) \.)
+ (you have the (quality) of a (der-term) \.)
+ ((der-term) \!)
+ ((adjective) (group-adj) (der-term) \!)
+ (you\'re a typical (group-adj) person\, totally (adjective) \.)
+ (man\, (sentence))))
+
+(defvar sentence-loop (nconc sentence sentence))
+
+
+(defvar quality
+ '((ignorance) (stupidity) (worthlessness)
+ (prejudice) (lack of intelligence) (lousiness)
+ (bad grammar) (lousy spelling)
+ (lack of common decency) (ugliness) (nastiness)
+ (subtlety) (dishonesty) ((adjective) (quality))))
+
+
+(defvar quality-loop (nconc quality quality))
+
+(defvar adjective
+ '((ignorant) (crass) (pathetic) (sick)
+ (bloated) (malignant) (perverted) (sadistic)
+ (stupid) (unpleasant) (lousy) (abusive) (bad)
+ (braindamaged) (selfish) (improper) (nasty)
+ (disgusting) (foul) (intolerable) (primitive)
+ (depressing) (dumb) (phoney)
+ ((adjective) and (adjective))
+ (as (adjective) as a (thing))))
+
+(defvar adjective-loop (nconc adjective adjective))
+
+(defvar der-term
+ '(((adjective) (der-term)) (sexist) (fascist)
+ (weakling) (coward) (beast) (peasant) (racist)
+ (cretin) (fool) (jerk) (ignoramus) (idiot)
+ (wanker) (rat) (slimebag) (DAF driver)
+ (Neanderthal) (sadist) (drunk) (capitalist)
+ (wimp) (dogmatist) (wally) (maniac)
+ (whimpering scumbag) (pea brain) (arsehole)
+ (moron) (goof) (incompetant) (lunkhead) (Nazi)
+ (SysThug) ((der-term) (der-term))))
+
+(defvar der-term-loop (nconc der-term der-term))
+
+
+(defvar thing
+ '(((adjective) (thing)) (computer)
+ (Honeywell dps8) (whale) (operation)
+ (sexist joke) (ten-incher) (dog) (MicroVAX II)
+ (source license) (real-time clock)
+ (mental problem) (sexual fantasy)
+ (venereal disease) (Jewish grandmother)
+ (cardboard cut-out) (punk haircut) (surfboard)
+ (system call) (wood-burning stove)
+ (graphics editor) (right wing death squad)
+ (disease) (vegetable) (religion)
+ (cruise missile) (bug fix) (lawyer) (copyright)
+ (PAD)))
+
+(defvar thing-loop (nconc thing thing))
+
+
+(defvar group-adj
+ '((gay) (old) (lesbian) (young) (black)
+ (Polish) ((adjective)) (white)
+ (mentally retarded) (Nicaraguan) (homosexual)
+ (dead) (underpriviledged) (religious)
+ ((thing) \-loving) (feminist) (foreign)
+ (intellectual) (crazy) (working) (unborn)
+ (Chinese) (short) ((adjective)) (poor) (rich)
+ (funny-looking) (Puerto Rican) (Mexican)
+ (Italian) (communist) (fascist) (Iranian)
+ (Moonie)))
+
+(defvar group-adj-loop (nconc group-adj group-adj))
+
+(defvar statement
+ '((your (thing) is great) ((thing) s are fun)
+ ((person) is a (der-term))
+ ((group-adj) people are (adjective))
+ (every (group-adj) person is a (der-term))
+ (most (group-adj) people have (thing) s)
+ (all (group-adj) dudes should get (thing) s)
+ ((person) is (group-adj)) (trees are (adjective))
+ (if you\'ve seen one (thing) \, you\'ve seen them all)
+ (you\'re (group-adj)) (you have a (thing))
+ (my (thing) is pretty good)
+ (the Martians are coming)
+ (the (paper) is always right)
+ (just because you read it in the (paper) that doesn\'t mean it\'s true)
+ ((person) was (group-adj))
+ ((person) \'s ghost is living in your (thing))
+ (you look like a (thing))
+ (the oceans are full of dirty fish)
+ (people are dying every day)
+ (a (group-adj) man ain\'t got nothing in the world these days)
+ (women are inherently superior to men)
+ (the system staff is fascist)
+ (there is life after death)
+ (the world is full of (der-term) s)
+ (you remind me of (person)) (technology is evil)
+ ((person) killed (person))
+ (the Russians are tapping your phone)
+ (the Earth is flat)
+ (it\'s OK to run down (group-adj) people)
+ (Multics is a really (adjective) operating system)
+ (the CIA killed (person))
+ (the sexual revolution is over)
+ (Lassie was (group-adj))
+ (the (group-adj) s have really got it all together)
+ (I was (person) in a previous life)
+ (breathing causes cancer)
+ (it\'s fun to be really (adjective))
+ ((quality) is pretty fun) (you\'re a (der-term))
+ (the (group-adj) culture is fascinating)
+ (when ya gotta go ya gotta go)
+ ((person) is (adjective))
+ ((person) \'s (quality) is (adjective))
+ (it\'s a wonderful day)
+ (everything is really a (thing))
+ (there\'s a (thing) in (person) \'s brain)
+ ((person) is a cool dude)
+ ((person) is just a figment of your imagination)
+ (the more (thing) s you have, the better)
+ (life is a (thing)) (life is (quality))
+ ((person) is (adjective))
+ ((group-adj) people are all (adjective) (der-term) s)
+ ((statement) \, and (statement))
+ ((statement) \, but (statement))
+ (I wish I had a (thing))
+ (you should have a (thing))
+ (you hope that (statement))
+ ((person) is secretly (group-adj))
+ (you wish you were (group-adj))
+ (you wish you were a (thing))
+ (I wish I were a (thing))
+ (you think that (statement))
+ ((statement) \, because (statement))
+ ((group-adj) people don\'t get married to (group-adj) people because (reason))
+ ((group-adj) people are all (adjective) because (reason))
+ ((group-adj) people are (adjective) \, and (reason))
+ (you must be a (adjective) (der-term) to think that (person) said (statement))
+ ((group-adj) people are inherently superior to (group-adj) people)
+ (God is Dead)))
+
+(defvar statement-loop (nconc statement statement))
+
+
+(defvar paper
+ '((Daily Mail) (Daily Express)
+ (Centre Bulletin) (Sun) (Daily Mirror)
+ (Daily Telegraph) (Beano) (Multics Manual)))
+
+(defvar paper-loop (nconc paper paper))
+
+
+(defvar person
+ '((Reagan) (Ken Thompson) (Dennis Ritchie)
+ (JFK) (the Pope) (Gadaffi) (Napoleon)
+ (Karl Marx) (Groucho) (Michael Jackson)
+ (Caesar) (Nietzsche) (Heidegger)
+ (Henry Kissinger) (Nixon) (Castro) (Thatcher)
+ (Attilla the Hun) (Alaric the Visigoth) (Hitler)))
+
+(defvar person-loop (nconc person person))
+
+(defvar reason
+ '((they don\'t want their children to grow up to be too lazy to steal)
+ (they can\'t tell them apart from (group-adj) dudes)
+ (they\'re too (adjective))
+ ((person) wouldn\'t have done it)
+ (they can\'t spray paint that small)
+ (they don\'t have (thing) s) (they don\'t know how)
+ (they can\'t afford (thing) s)))
+
+(defvar reason-loop (nconc reason reason))
+
+(defmacro define-element (name)
+ (let ((loop-to-use (intern (concat name "-loop"))))
+ (` (defun (, (intern name)) nil
+ (let ((step-forward (% (random) 10)))
+ (if (< step-forward 0) (setq step-forward (- step-forward)))
+ (prog1
+ (nth step-forward (, loop-to-use))
+ (setq (, loop-to-use) (nthcdr (1+ step-forward) (, loop-to-use)))))))))
+
+(define-element "sentence")
+(define-element "quality")
+(define-element "adjective")
+(define-element "der-term")
+(define-element "group-adj")
+(define-element "statement")
+(define-element "thing")
+(define-element "paper")
+(define-element "person")
+(define-element "reason")
+
+(defun *flame nil
+ (flame-expand '(sentence)))
+
+(defun flame-expand (object)
+ (cond ((atom object)
+ object)
+ (t (mapcar 'flame-expand (funcall (car object))))))
+
+(defun flatten (list)
+ (cond ((atom list)
+ (list list))
+ (t (apply 'append (mapcar 'flatten list)))))
+
+(defun flame (arg)
+ "Generate ARG (default 1) sentences of half-crazed gibberish."
+ (interactive "p")
+ (let ((w (selected-window)))
+ (pop-to-buffer (get-buffer-create "*Flame*"))
+ (goto-char (point-max))
+ (insert ?\n)
+ (flame2 arg)
+ (select-window w)))
+
+(defun flame2 (arg)
+ (let ((start (point)))
+ (flame1 arg)
+ (fill-region-as-paragraph start (point) t)))
+
+(defun flame1 (arg)
+ (cond ((zerop arg) t)
+ (t (insert (concat (sentence-ify (string-ify (append-suffixes-hack (flatten (*flame)))))))
+ (flame1 (1- arg)))))
+
+(defun sentence-ify (string)
+ (concat (upcase (substring string 0 1))
+ (substring string 1 (length string))
+ " "))
+
+(defun string-ify (list)
+ (mapconcat
+ '(lambda (x)
+ (format "%s" x))
+ list
+ " "))
+
+(defun append-suffixes-hack (list)
+ (cond ((null list)
+ nil)
+ ((memq (nth 1 list)
+ '(\? \. \, s\! \! s \'s \-loving))
+ (cons (intern (format "%s%s" (nth 0 list) (nth 1 list)))
+ (append-suffixes-hack (nthcdr 2 list))))
+ (t (cons (nth 0 list)
+ (append-suffixes-hack (nthcdr 1 list))))))
+
+(defun psychoanalyze-flamer ()
+ "Mr. Angry goes to the analyst."
+ (interactive)
+ (doctor) ; start the psychotherapy
+ (message "")
+ (switch-to-buffer "*doctor*")
+ (sit-for 0)
+ (while (not (input-pending-p))
+ (flame2 (if (= (% (random) 2) 0) 2 1))
+ (sit-for 0)
+ (doctor-ret-or-read 1)))
diff --git a/lisp/flame.elc b/lisp/flame.elc
new file mode 100644
index 00000000000..3b620a0df54
--- /dev/null
+++ b/lisp/flame.elc
Binary files differ
diff --git a/lisp/float-sup.el b/lisp/float-sup.el
deleted file mode 100644
index d7b756238d3..00000000000
--- a/lisp/float-sup.el
+++ /dev/null
@@ -1,52 +0,0 @@
-;; Basic editing commands for Emacs
-;; Copyright (C) 1985, 1986, 1987 Free Software Foundation, Inc.
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 1, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
-;; Provide a meaningful error message if we are running on
-;; bare (non-float) emacs.
-;; Can't test for 'floatp since that may be defined by float-imitation
-;; packages like float.el in this very directory.
-
-(if (fboundp 'atan)
- nil
- (error "Floating point was disabled at compile time"))
-
-;; provide an easy hook to tell if we are running with floats or not.
-(provide 'lisp-float-type)
-
-;; define pi and e via math-lib calls. (much less prone to killer typos.)
-(defconst pi (* 4 (atan 1)) "The value of Pi (3.1415926...)")
-(defconst e (exp 1) "The value of e (2.7182818...)")
-
-;; Careful when editing this file ... typos here will be hard to spot.
-;; (defconst pi 3.14159265358979323846264338327
-;; "The value of Pi (3.14159265358979323846264338327...)")
-
-(defconst degrees-to-radians (/ pi 180.0)
- "Degrees to radian conversion constant")
-(defconst radians-to-degrees (/ 180.0 pi)
- "Radian to degree conversion constant")
-
-;; these expand to a single multiply by a float when byte compiled
-
-(defmacro degrees-to-radians (x)
- "Convert ARG from degrees to radians."
- (list '* (/ pi 180.0) x))
-(defmacro radians-to-degrees (x)
- "Convert ARG from radians to degrees."
- (list '* (/ 180.0 pi) x))
diff --git a/lisp/emacs-lisp/float.el b/lisp/float.el
index 68b88f41ecc..9e986eed129 100644
--- a/lisp/emacs-lisp/float.el
+++ b/lisp/float.el
@@ -68,9 +68,16 @@
(defconst mantissa-maxval (1- (ash 1 maxbit))
"Maximum permissable value of mantissa")
-(defconst mantissa-minval (ash 1 maxbit)
+;;; Note that this value can't be plain (ash 1 maxbit), since
+;;; (- (ash 1 maxbit)) = (ash 1 maxbit) - it overflows.
+(defconst mantissa-minval (1- (ash 1 maxbit))
"Minimum permissable value of mantissa")
+;;; This is used when normalizing negative numbers; if the number is
+;;; less than this, multiplying it by 2 will overflow past
+;;; mantissa-minval.
+(defconst mantissa-half-minval (ash (ash 1 maxbit) -1))
+
(defconst floating-point-regexp
"^[ \t]*\\(-?\\)\\([0-9]*\\)\
\\(\\.\\([0-9]*\\)\\|\\)\
@@ -120,14 +127,15 @@
(if (> (car fnum) 0) ; make sure next-to-highest bit is set
(while (zerop (logand (car fnum) second-bit-mask))
(setq fnum (fashl fnum)))
- (if (< (car fnum) 0) ; make sure highest bit is set
- (while (zerop (logand (car fnum) high-bit-mask))
+ (if (< (car fnum) 0) ; make sure next-to-highest bit is
+ ; zero, but fnum /= mantissa-minval.
+ (while (> (car fnum) mantissa-half-minval)
(setq fnum (fashl fnum)))
(setq fnum _f0))) ; "standard 0"
fnum)
(defun abs (n) ; integer absolute value
- (if (>= n 0) n (- n)))
+ (if (natnump n) n (- n)))
(defun fabs (fnum) ; re-normalize after taking abs value
(normalize (cons (abs (car fnum)) (cdr fnum))))
@@ -160,8 +168,8 @@
;; Arithmetic functions
(defun f+ (a1 a2)
"Returns the sum of two floating point numbers."
- (let ((f1 (fmax a1 a2))
- (f2 (fmin a1 a2)))
+ (let ((f1 (if (> (cdr a1) (cdr a2)) a1 a2))
+ (f2 (if (> (cdr a1) (cdr a2)) a2 a1)))
(if (same-sign a1 a2)
(setq f1 (fashr f1) ; shift right to avoid overflow
f2 (fashr f2)))
@@ -386,10 +394,11 @@ Optional second argument non-nil means use scientific notation."
;; digits of the exponent.
(defun string-to-float (str)
"Convert the string to a floating point number.
-Accepts a decimal string in scientific notation, with exponent preceded
-by either E or e. Only the six most significant digits of the integer
-and fractional parts are used; only the first two digits of the exponent
-are used. Negative signs preceding both the decimal number and the exponent
+Accepts a decimal string in scientific notation,
+with exponent preceded by either E or e.
+Only the 6 most significant digits of the integer and fractional parts
+are used; only the first two digits of the exponent are used.
+Negative signs preceding both the decimal number and the exponent
are recognized."
(if (string-match floating-point-regexp str 0)
@@ -446,3 +455,5 @@ are recognized."
(funcall func exponent (aref powers-of-10 tens)))))
_f0)) ; if invalid, return 0
+
+
diff --git a/lisp/float.elc b/lisp/float.elc
new file mode 100644
index 00000000000..8f2e82dd36b
--- /dev/null
+++ b/lisp/float.elc
Binary files differ
diff --git a/lisp/fortran.el b/lisp/fortran.el
new file mode 100644
index 00000000000..065cad638a0
--- /dev/null
+++ b/lisp/fortran.el
@@ -0,0 +1,654 @@
+;;; Fortran mode for GNU Emacs (beta test version 1.21, Oct. 1, 1985)
+;;; Copyright (c) 1986 Free Software Foundation, Inc.
+;;; Written by Michael D. Prange (prange@erl.mit.edu)
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 1, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+;;; Author acknowledges help from Stephen Gildea <gildea@erl.mit.edu>
+
+;;; Bugs to bug-fortran-mode@erl.mit.edu.
+
+(defvar fortran-do-indent 3
+ "*Extra indentation applied to `do' blocks.")
+
+(defvar fortran-if-indent 3
+ "*Extra indentation applied to `if' blocks.")
+
+(defvar fortran-continuation-indent 5
+ "*Extra indentation applied to `continuation' lines.")
+
+(defvar fortran-comment-indent-style 'fixed
+ "*nil forces comment lines not to be touched,
+'fixed produces fixed comment indentation to comment-column,
+and 'relative indents to current fortran indentation plus comment-column.")
+
+(defvar fortran-comment-line-column 6
+ "*Indentation for text in comment lines.")
+
+(defvar comment-line-start nil
+ "*Delimiter inserted to start new full-line comment.")
+
+(defvar comment-line-start-skip nil
+ "*Regexp to match the start of a full-line comment.")
+
+(defvar fortran-minimum-statement-indent 6
+ "*Minimum indentation for fortran statements.")
+
+;; Note that this is documented in the v18 manuals as being a string
+;; of length one rather than a single character.
+;; The code in this file accepts either format for compatibility.
+(defvar fortran-comment-indent-char ?
+ "*Character to be inserted for Fortran comment indentation.
+Normally a space.")
+
+(defvar fortran-line-number-indent 1
+ "*Maximum indentation for Fortran line numbers.
+5 means right-justify them within their five-column field.")
+
+(defvar fortran-check-all-num-for-matching-do nil
+ "*Non-nil causes all numbered lines to be treated as possible do-loop ends.")
+
+(defvar fortran-continuation-char ?$
+ "*Character which is inserted in column 5 by \\[fortran-split-line]
+to begin a continuation line. Normally $.")
+
+(defvar fortran-comment-region "c$$$"
+ "*String inserted by \\[fortran-comment-region] at start of each line in region.")
+
+(defvar fortran-electric-line-number t
+ "*Non-nil causes line number digits to be moved to the correct column as typed.")
+
+(defvar fortran-startup-message t
+ "*Non-nil displays a startup message when fortran-mode is first called.")
+
+(defvar fortran-column-ruler
+ (concat "0 4 6 10 20 30 40 50 60 70\n"
+ "[ ]|{ | | | | | | | | | | | | |}\n")
+ "*String displayed above current line by \\[fortran-column-ruler].")
+
+(defconst fortran-mode-version "1.21")
+
+(defvar fortran-mode-syntax-table nil
+ "Syntax table in use in fortran-mode buffers.")
+
+(if fortran-mode-syntax-table
+ ()
+ (setq fortran-mode-syntax-table (make-syntax-table))
+ (modify-syntax-entry ?\; "w" fortran-mode-syntax-table)
+ (modify-syntax-entry ?+ "." fortran-mode-syntax-table)
+ (modify-syntax-entry ?- "." fortran-mode-syntax-table)
+ (modify-syntax-entry ?* "." fortran-mode-syntax-table)
+ (modify-syntax-entry ?/ "." fortran-mode-syntax-table)
+ (modify-syntax-entry ?\' "\"" fortran-mode-syntax-table)
+ (modify-syntax-entry ?\" "\"" fortran-mode-syntax-table)
+ (modify-syntax-entry ?\\ "/" fortran-mode-syntax-table)
+ (modify-syntax-entry ?. "w" fortran-mode-syntax-table)
+ (modify-syntax-entry ?\n ">" fortran-mode-syntax-table))
+
+(defvar fortran-mode-map ()
+ "Keymap used in fortran mode.")
+
+(if fortran-mode-map
+ ()
+ (setq fortran-mode-map (make-sparse-keymap))
+ (define-key fortran-mode-map ";" 'fortran-abbrev-start)
+ (define-key fortran-mode-map "\C-c;" 'fortran-comment-region)
+ (define-key fortran-mode-map "\e\C-a" 'beginning-of-fortran-subprogram)
+ (define-key fortran-mode-map "\e\C-e" 'end-of-fortran-subprogram)
+ (define-key fortran-mode-map "\e;" 'fortran-indent-comment)
+ (define-key fortran-mode-map "\e\C-h" 'mark-fortran-subprogram)
+ (define-key fortran-mode-map "\e\n" 'fortran-split-line)
+ (define-key fortran-mode-map "\e\C-q" 'fortran-indent-subprogram)
+ (define-key fortran-mode-map "\C-c\C-w" 'fortran-window-create)
+ (define-key fortran-mode-map "\C-c\C-r" 'fortran-column-ruler)
+ (define-key fortran-mode-map "\C-c\C-p" 'fortran-previous-statement)
+ (define-key fortran-mode-map "\C-c\C-n" 'fortran-next-statement)
+ (define-key fortran-mode-map "\t" 'fortran-indent-line)
+ (define-key fortran-mode-map "0" 'fortran-electric-line-number)
+ (define-key fortran-mode-map "1" 'fortran-electric-line-number)
+ (define-key fortran-mode-map "2" 'fortran-electric-line-number)
+ (define-key fortran-mode-map "3" 'fortran-electric-line-number)
+ (define-key fortran-mode-map "4" 'fortran-electric-line-number)
+ (define-key fortran-mode-map "5" 'fortran-electric-line-number)
+ (define-key fortran-mode-map "6" 'fortran-electric-line-number)
+ (define-key fortran-mode-map "7" 'fortran-electric-line-number)
+ (define-key fortran-mode-map "8" 'fortran-electric-line-number)
+ (define-key fortran-mode-map "9" 'fortran-electric-line-number))
+
+(defvar fortran-mode-abbrev-table nil)
+(if fortran-mode-abbrev-table
+ ()
+ (define-abbrev-table 'fortran-mode-abbrev-table ())
+ (let ((abbrevs-changed nil))
+ (define-abbrev fortran-mode-abbrev-table ";b" "byte" nil)
+ (define-abbrev fortran-mode-abbrev-table ";ch" "character" nil)
+ (define-abbrev fortran-mode-abbrev-table ";cl" "close" nil)
+ (define-abbrev fortran-mode-abbrev-table ";c" "continue" nil)
+ (define-abbrev fortran-mode-abbrev-table ";cm" "common" nil)
+ (define-abbrev fortran-mode-abbrev-table ";cx" "complex" nil)
+ (define-abbrev fortran-mode-abbrev-table ";di" "dimension" nil)
+ (define-abbrev fortran-mode-abbrev-table ";do" "double" nil)
+ (define-abbrev fortran-mode-abbrev-table ";dc" "double complex" nil)
+ (define-abbrev fortran-mode-abbrev-table ";dp" "double precision" nil)
+ (define-abbrev fortran-mode-abbrev-table ";dw" "do while" nil)
+ (define-abbrev fortran-mode-abbrev-table ";e" "else" nil)
+ (define-abbrev fortran-mode-abbrev-table ";ed" "enddo" nil)
+ (define-abbrev fortran-mode-abbrev-table ";el" "elseif" nil)
+ (define-abbrev fortran-mode-abbrev-table ";en" "endif" nil)
+ (define-abbrev fortran-mode-abbrev-table ";eq" "equivalence" nil)
+ (define-abbrev fortran-mode-abbrev-table ";ex" "external" nil)
+ (define-abbrev fortran-mode-abbrev-table ";ey" "entry" nil)
+ (define-abbrev fortran-mode-abbrev-table ";f" "format" nil)
+ (define-abbrev fortran-mode-abbrev-table ";fu" "function" nil)
+ (define-abbrev fortran-mode-abbrev-table ";g" "goto" nil)
+ (define-abbrev fortran-mode-abbrev-table ";im" "implicit" nil)
+ (define-abbrev fortran-mode-abbrev-table ";ib" "implicit byte" nil)
+ (define-abbrev fortran-mode-abbrev-table ";ic" "implicit complex" nil)
+ (define-abbrev fortran-mode-abbrev-table ";ich" "implicit character" nil)
+ (define-abbrev fortran-mode-abbrev-table ";ii" "implicit integer" nil)
+ (define-abbrev fortran-mode-abbrev-table ";il" "implicit logical" nil)
+ (define-abbrev fortran-mode-abbrev-table ";ir" "implicit real" nil)
+ (define-abbrev fortran-mode-abbrev-table ";inc" "include" nil)
+ (define-abbrev fortran-mode-abbrev-table ";in" "integer" nil)
+ (define-abbrev fortran-mode-abbrev-table ";intr" "intrinsic" nil)
+ (define-abbrev fortran-mode-abbrev-table ";l" "logical" nil)
+ (define-abbrev fortran-mode-abbrev-table ";op" "open" nil)
+ (define-abbrev fortran-mode-abbrev-table ";pa" "parameter" nil)
+ (define-abbrev fortran-mode-abbrev-table ";pr" "program" nil)
+ (define-abbrev fortran-mode-abbrev-table ";p" "print" nil)
+ (define-abbrev fortran-mode-abbrev-table ";re" "real" nil)
+ (define-abbrev fortran-mode-abbrev-table ";r" "read" nil)
+ (define-abbrev fortran-mode-abbrev-table ";rt" "return" nil)
+ (define-abbrev fortran-mode-abbrev-table ";rw" "rewind" nil)
+ (define-abbrev fortran-mode-abbrev-table ";s" "stop" nil)
+ (define-abbrev fortran-mode-abbrev-table ";su" "subroutine" nil)
+ (define-abbrev fortran-mode-abbrev-table ";ty" "type" nil)
+ (define-abbrev fortran-mode-abbrev-table ";w" "write" nil)))
+
+(defun fortran-mode ()
+ "Major mode for editing fortran code.
+Tab indents the current fortran line correctly.
+`do' statements must not share a common `continue'.
+
+Type `;?' or `;\\[help-command]' to display a list of built-in abbrevs for Fortran keywords.
+
+Variables controlling indentation style and extra features:
+
+ comment-start
+ Normally nil in Fortran mode. If you want to use comments
+ starting with `!', set this to the string \"!\".
+ fortran-do-indent
+ Extra indentation within do blocks. (default 3)
+ fortran-if-indent
+ Extra indentation within if blocks. (default 3)
+ fortran-continuation-indent
+ Extra indentation appled to continuation statements. (default 5)
+ fortran-comment-line-column
+ Amount of indentation for text within full-line comments. (default 6)
+ fortran-comment-indent-style
+ nil means don't change indentation of text in full-line comments,
+ fixed means indent that text at column fortran-comment-line-column
+ relative means indent at fortran-comment-line-column beyond the
+ indentation for a line of code.
+ Default value is fixed.
+ fortran-comment-indent-char
+ Character to be inserted instead of space for full-line comment
+ indentation. (default is a space)
+ fortran-minimum-statement-indent
+ Minimum indentation for fortran statements. (default 6)
+ fortran-line-number-indent
+ Maximum indentation for line numbers. A line number will get
+ less than this much indentation if necessary to avoid reaching
+ column 5. (default 1)
+ fortran-check-all-num-for-matching-do
+ Non-nil causes all numbered lines to be treated as possible 'continue'
+ statements. (default nil)
+ fortran-continuation-char
+ character to be inserted in column 5 of a continuation line.
+ (default $)
+ fortran-comment-region
+ String inserted by \\[fortran-comment-region] at start of each line in
+ region. (default \"c$$$\")
+ fortran-electric-line-number
+ Non-nil causes line number digits to be moved to the correct column
+ as typed. (default t)
+ fortran-startup-message
+ Set to nil to inhibit message first time fortran-mode is used.
+
+Turning on Fortran mode calls the value of the variable fortran-mode-hook
+with no args, if that value is non-nil.
+\\{fortran-mode-map}"
+ (interactive)
+ (kill-all-local-variables)
+ (if fortran-startup-message
+ (message "Emacs Fortran mode version %s. Bugs to bug-fortran-mode@erl.mit.edu" fortran-mode-version))
+ (setq fortran-startup-message nil)
+ (setq local-abbrev-table fortran-mode-abbrev-table)
+ (set-syntax-table fortran-mode-syntax-table)
+ (make-local-variable 'indent-line-function)
+ (setq indent-line-function 'fortran-indent-line)
+ (make-local-variable 'comment-indent-hook)
+ (setq comment-indent-hook 'fortran-comment-hook)
+ (make-local-variable 'comment-line-start-skip)
+ (setq comment-line-start-skip "^[Cc*][^ \t\n]*[ \t]*") ;[^ \t\n]* handles comment strings such as c$$$
+ (make-local-variable 'comment-line-start)
+ (setq comment-line-start "c")
+ (make-local-variable 'comment-start-skip)
+ (setq comment-start-skip "![ \t]*")
+ (make-local-variable 'comment-start)
+ (setq comment-start nil)
+ (make-local-variable 'require-final-newline)
+ (setq require-final-newline t)
+ (make-local-variable 'abbrev-all-caps)
+ (setq abbrev-all-caps t)
+ (make-local-variable 'indent-tabs-mode)
+ (setq indent-tabs-mode nil)
+ (use-local-map fortran-mode-map)
+ (setq mode-name "Fortran")
+ (setq major-mode 'fortran-mode)
+ (run-hooks 'fortran-mode-hook))
+
+(defun fortran-comment-hook ()
+ (save-excursion
+ (skip-chars-backward " \t")
+ (max (+ 1 (current-column))
+ comment-column)))
+
+(defun fortran-indent-comment ()
+ "Align or create comment on current line.
+Existing comments of all types are recognized and aligned.
+If the line has no comment, a side-by-side comment is inserted and aligned
+if the value of comment-start is not nil.
+Otherwise, a separate-line comment is inserted, on this line
+or on a new line inserted before this line if this line is not blank."
+ (interactive)
+ (beginning-of-line)
+ ;; Recognize existing comments of either kind.
+ (cond ((looking-at comment-line-start-skip)
+ (fortran-indent-line))
+ ((re-search-forward comment-start-skip
+ (save-excursion (end-of-line) (point)) t)
+ (indent-for-comment))
+ ;; No existing comment.
+ ;; If side-by-side comments are defined, insert one,
+ ;; unless line is now blank.
+ ((and comment-start (not (looking-at "^[ \t]*$")))
+ (end-of-line)
+ (delete-horizontal-space)
+ (indent-to (fortran-comment-hook))
+ (insert comment-start))
+ ;; Else insert separate-line comment, making a new line if nec.
+ (t
+ (if (looking-at "^[ \t]*$")
+ (delete-horizontal-space)
+ (beginning-of-line)
+ (insert "\n")
+ (forward-char -1))
+ (insert comment-line-start)
+ (insert-char (if (stringp fortran-comment-indent-char)
+ (aref fortran-comment-indent-char 0)
+ fortran-comment-indent-char)
+ (- (calculate-fortran-indent) (current-column))))))
+
+(defun fortran-comment-region (beg-region end-region arg)
+ "Comments every line in the region.
+Puts fortran-comment-region at the beginning of every line in the region.
+BEG-REGION and END-REGION are args which specify the region boundaries.
+With non-nil ARG, uncomments the region."
+ (interactive "*r\nP")
+ (let ((end-region-mark (make-marker)) (save-point (point-marker)))
+ (set-marker end-region-mark end-region)
+ (goto-char beg-region)
+ (beginning-of-line)
+ (if (not arg) ;comment the region
+ (progn (insert fortran-comment-region)
+ (while (and (= (forward-line 1) 0)
+ (< (point) end-region-mark))
+ (insert fortran-comment-region)))
+ (let ((com (regexp-quote fortran-comment-region))) ;uncomment the region
+ (if (looking-at com)
+ (delete-region (point) (match-end 0)))
+ (while (and (= (forward-line 1) 0)
+ (< (point) end-region-mark))
+ (if (looking-at com)
+ (delete-region (point) (match-end 0))))))
+ (goto-char save-point)
+ (set-marker end-region-mark nil)
+ (set-marker save-point nil)))
+
+(defun fortran-abbrev-start ()
+ "Typing \";\\[help-command]\" or \";?\" lists all the fortran abbrevs.
+Any other key combination is executed normally." ;\\[help-command] is just a way to print the value of the variable help-char.
+ (interactive)
+ (let (c)
+ (insert last-command-char)
+ (if (or (= (setq c (read-char)) ??) ;insert char if not equal to `?'
+ (= c help-char))
+ (fortran-abbrev-help)
+ (setq unread-command-char c))))
+
+(defun fortran-abbrev-help ()
+ "List the currently defined abbrevs in Fortran mode."
+ (interactive)
+ (message "Listing abbrev table...")
+ (require 'abbrevlist)
+ (list-one-abbrev-table fortran-mode-abbrev-table "*Help*")
+ (message "Listing abbrev table...done"))
+
+(defun fortran-column-ruler ()
+ "Inserts a column ruler momentarily above current line, till next keystroke.
+The ruler is defined by the value of fortran-column-ruler.
+The key typed is executed unless it is SPC."
+ (interactive)
+ (momentary-string-display
+ fortran-column-ruler (save-excursion (beginning-of-line) (point))
+ nil "Type SPC or any command to erase ruler."))
+
+(defun fortran-window-create ()
+ "Makes the window 72 columns wide."
+ (interactive)
+ (let ((window-min-width 2))
+ (split-window-horizontally 73))
+ (other-window 1)
+ (switch-to-buffer " fortran-window-extra" t)
+ (select-window (previous-window)))
+
+(defun fortran-split-line ()
+ "Break line at point and insert continuation marker and alignment."
+ (interactive)
+ (delete-horizontal-space)
+ (if (save-excursion (beginning-of-line) (looking-at comment-line-start-skip))
+ (insert "\n" comment-line-start " ")
+ (insert "\n " fortran-continuation-char))
+ (fortran-indent-line))
+
+(defun delete-horizontal-regexp (chars)
+ "Delete all characters in CHARS around point.
+CHARS is like the inside of a [...] in a regular expression
+except that ] is never special and \ quotes ^, - or \."
+ (interactive "*s")
+ (skip-chars-backward chars)
+ (delete-region (point) (progn (skip-chars-forward chars) (point))))
+
+(defun fortran-electric-line-number (arg)
+ "Self insert, but if part of a Fortran line number indent it automatically.
+Auto-indent does not happen if a numeric arg is used."
+ (interactive "P")
+ (if (or arg (not fortran-electric-line-number))
+ (self-insert-command arg)
+ (if (or (save-excursion (re-search-backward "[^ \t0-9]"
+ (save-excursion
+ (beginning-of-line)
+ (point))
+ t)) ;not a line number
+ (looking-at "[0-9]")) ;within a line number
+ (insert last-command-char)
+ (skip-chars-backward " \t")
+ (insert last-command-char)
+ (fortran-indent-line))))
+
+(defun beginning-of-fortran-subprogram ()
+ "Moves point to the beginning of the current fortran subprogram."
+ (interactive)
+ (let ((case-fold-search t))
+ (beginning-of-line -1)
+ (re-search-backward "^[ \t0-9]*end\\b[ \t]*[^ \t=(a-z]" nil 'move)
+ (if (looking-at "^[ \t0-9]*end\\b[ \t]*[^ \t=(a-z]")
+ (forward-line 1))))
+
+(defun end-of-fortran-subprogram ()
+ "Moves point to the end of the current fortran subprogram."
+ (interactive)
+ (let ((case-fold-search t))
+ (beginning-of-line 2)
+ (re-search-forward "^[ \t0-9]*end\\b[ \t]*[^ \t=(a-z]" nil 'move)
+ (goto-char (match-beginning 0))
+ (forward-line 1)))
+
+(defun mark-fortran-subprogram ()
+ "Put mark at end of fortran subprogram, point at beginning.
+The marks are pushed."
+ (interactive)
+ (end-of-fortran-subprogram)
+ (push-mark (point))
+ (beginning-of-fortran-subprogram))
+
+(defun fortran-previous-statement ()
+ "Moves point to beginning of the previous fortran statement.
+Returns 'first-statement if that statement is the first
+non-comment Fortran statement in the file, and nil otherwise."
+ (interactive)
+ (let (not-first-statement continue-test)
+ (beginning-of-line)
+ (setq continue-test
+ (or (looking-at
+ (concat "[ \t]*" (regexp-quote (char-to-string
+ fortran-continuation-char))))
+ (looking-at " [^ 0\n]")))
+ (while (and (setq not-first-statement (= (forward-line -1) 0))
+ (or (looking-at comment-line-start-skip)
+ (looking-at "[ \t]*$")
+ (looking-at " [^ 0\n]")
+ (looking-at (concat "[ \t]*" comment-start-skip)))))
+ (cond ((and continue-test
+ (not not-first-statement))
+ (message "Incomplete continuation statement."))
+ (continue-test
+ (fortran-previous-statement))
+ ((not not-first-statement)
+ 'first-statement))))
+
+(defun fortran-next-statement ()
+ "Moves point to beginning of the next fortran statement.
+ Returns 'last-statement if that statement is the last
+ non-comment Fortran statement in the file, and nil otherwise."
+ (interactive)
+ (let (not-last-statement)
+ (beginning-of-line)
+ (while (and (setq not-last-statement (= (forward-line 1) 0))
+ (or (looking-at comment-line-start-skip)
+ (looking-at "[ \t]*$")
+ (looking-at " [^ 0\n]")
+ (looking-at (concat "[ \t]*" comment-start-skip)))))
+ (if (not not-last-statement)
+ 'last-statement)))
+
+(defun fortran-indent-line ()
+ "Indents current fortran line based on its contents and on previous lines."
+ (interactive)
+ (let ((cfi (calculate-fortran-indent)))
+ (save-excursion
+ (beginning-of-line)
+ (if (or (not (= cfi (fortran-current-line-indentation)))
+ (and (re-search-forward "^[ \t]*[0-9]+" (+ (point) 4) t)
+ (not (fortran-line-number-indented-correctly-p))))
+ (fortran-indent-to-column cfi)
+ (beginning-of-line)
+ (if (re-search-forward comment-start-skip
+ (save-excursion (end-of-line) (point)) 'move)
+ (fortran-indent-comment))))
+ ;; Never leave point in left margin.
+ (if (< (current-column) cfi)
+ (move-to-column cfi))))
+
+(defun fortran-indent-subprogram ()
+ "Properly indents the Fortran subprogram which contains point."
+ (interactive)
+ (save-excursion
+ (mark-fortran-subprogram)
+ (message "Indenting subprogram...")
+ (indent-region (point) (mark) nil))
+ (message "Indenting subprogram...done."))
+
+(defun calculate-fortran-indent ()
+ "Calculates the fortran indent column based on previous lines."
+ (let (icol first-statement (case-fold-search t))
+ (save-excursion
+ (setq first-statement (fortran-previous-statement))
+ (if first-statement
+ (setq icol fortran-minimum-statement-indent)
+ (progn
+ (if (= (point) (point-min))
+ (setq icol fortran-minimum-statement-indent)
+ (setq icol (fortran-current-line-indentation)))
+ (skip-chars-forward " \t0-9")
+ (cond ((looking-at "if[ \t]*(")
+ (if (or (looking-at ".*)[ \t]*then\\b[ \t]*[^ \t(=a-z0-9]")
+ (let (then-test) ;multi-line if-then
+ (while (and (= (forward-line 1) 0) ;search forward for then
+ (looking-at " [^ 0]")
+ (not (setq then-test (looking-at ".*then\\b[ \t]*[^ \t(=a-z0-9]")))))
+ then-test))
+ (setq icol (+ icol fortran-if-indent))))
+ ((looking-at "\\(else\\|elseif\\)\\b")
+ (setq icol (+ icol fortran-if-indent)))
+ ((looking-at "do\\b")
+ (setq icol (+ icol fortran-do-indent)))))))
+ (save-excursion
+ (beginning-of-line)
+ (cond ((looking-at "[ \t]*$"))
+ ((looking-at comment-line-start-skip)
+ (cond ((eq fortran-comment-indent-style 'relative)
+ (setq icol (+ icol fortran-comment-line-column)))
+ ((eq fortran-comment-indent-style 'fixed)
+ (setq icol fortran-comment-line-column))))
+ ((or (looking-at (concat "[ \t]*"
+ (regexp-quote (char-to-string fortran-continuation-char))))
+ (looking-at " [^ 0\n]"))
+ (setq icol (+ icol fortran-continuation-indent)))
+ (first-statement)
+ ((and fortran-check-all-num-for-matching-do
+ (looking-at "[ \t]*[0-9]+")
+ (fortran-check-for-matching-do))
+ (setq icol (- icol fortran-do-indent)))
+ (t
+ (skip-chars-forward " \t0-9")
+ (cond ((looking-at "end[ \t]*if\\b")
+ (setq icol (- icol fortran-if-indent)))
+ ((looking-at "\\(else\\|elseif\\)\\b")
+ (setq icol (- icol fortran-if-indent)))
+ ((and (looking-at "continue\\b")
+ (fortran-check-for-matching-do))
+ (setq icol (- icol fortran-do-indent)))
+ ((looking-at "end[ \t]*do\\b")
+ (setq icol (- icol fortran-do-indent)))
+ ((and (looking-at "end\\b[ \t]*[^ \t=(a-z]")
+ (not (= icol fortran-minimum-statement-indent)))
+ (message "Warning: `end' not in column %d. Probably an unclosed block." fortran-minimum-statement-indent))))))
+ (max fortran-minimum-statement-indent icol)))
+
+(defun fortran-current-line-indentation ()
+ "Indentation of current line, ignoring Fortran line number or continuation.
+This is the column position of the first non-whitespace character
+aside from the line number and/or column 5 line-continuation character.
+For comment lines, returns indentation of the first
+non-indentation text within the comment."
+ (save-excursion
+ (beginning-of-line)
+ (cond ((looking-at comment-line-start-skip)
+ (goto-char (match-end 0))
+ (skip-chars-forward
+ (if (stringp fortran-comment-indent-char)
+ fortran-comment-indent-char
+ (char-to-string fortran-comment-indent-char))))
+ ((looking-at " [^ 0\n]")
+ (goto-char (match-end 0)))
+ (t
+ ;; Move past line number.
+ (move-to-column 5)))
+ ;; Move past whitespace.
+ (skip-chars-forward " \t")
+ (current-column)))
+
+(defun fortran-indent-to-column (col)
+ "Indents current line with spaces to column COL.
+notes: 1) A non-zero/non-blank character in column 5 indicates a continuation
+ line, and this continuation character is retained on indentation;
+ 2) If fortran-continuation-char is the first non-whitespace character,
+ this is a continuation line;
+ 3) A non-continuation line which has a number as the first
+ non-whitespace character is a numbered line."
+ (save-excursion
+ (beginning-of-line)
+ (if (looking-at comment-line-start-skip)
+ (if fortran-comment-indent-style
+ (let ((char (if (stringp fortran-comment-indent-char)
+ (aref fortran-comment-indent-char 0)
+ fortran-comment-indent-char)))
+ (goto-char (match-end 0))
+ (delete-horizontal-regexp (concat " \t" (char-to-string char)))
+ (insert-char char (- col (current-column)))))
+ (if (looking-at " [^ 0\n]")
+ (forward-char 6)
+ (delete-horizontal-space)
+ ;; Put line number in columns 0-4
+ ;; or put continuation character in column 5.
+ (cond ((eobp))
+ ((= (following-char) fortran-continuation-char)
+ (indent-to 5)
+ (forward-char 1))
+ ((looking-at "[0-9]+")
+ (let ((extra-space (- 5 (- (match-end 0) (point)))))
+ (if (< extra-space 0)
+ (message "Warning: line number exceeds 5-digit limit.")
+ (indent-to (min fortran-line-number-indent extra-space))))
+ (skip-chars-forward "0-9"))))
+ ;; Point is now after any continuation character or line number.
+ ;; Put body of statement where specified.
+ (delete-horizontal-space)
+ (indent-to col)
+ ;; Indent any comment following code on the same line.
+ (if (re-search-forward comment-start-skip
+ (save-excursion (end-of-line) (point)) t)
+ (progn (goto-char (match-beginning 0))
+ (if (not (= (current-column) (fortran-comment-hook)))
+ (progn (delete-horizontal-space)
+ (indent-to (fortran-comment-hook)))))))))
+
+(defun fortran-line-number-indented-correctly-p ()
+ "Return t if current line's line number is correctly indente.
+Do not call if there is no line number."
+ (save-excursion
+ (beginning-of-line)
+ (skip-chars-forward " \t")
+ (and (<= (current-column) fortran-line-number-indent)
+ (or (= (current-column) fortran-line-number-indent)
+ (progn (skip-chars-forward "0-9")
+ (= (current-column) 5))))))
+
+(defun fortran-check-for-matching-do ()
+ "When called from a numbered statement, returns t
+ if matching 'do' is found, and nil otherwise."
+ (let (charnum
+ (case-fold-search t))
+ (save-excursion
+ (beginning-of-line)
+ (if (looking-at "[ \t]*[0-9]+")
+ (progn
+ (skip-chars-forward " \t")
+ (skip-chars-forward "0") ;skip past leading zeros
+ (setq charnum (buffer-substring (point)
+ (progn (skip-chars-forward "0-9")
+ (point))))
+ (beginning-of-line)
+ (and (re-search-backward
+ (concat "\\(^[ \t0-9]*end\\b[ \t]*[^ \t=(a-z]\\)\\|\\(^[ \t0-9]*do[ \t]*0*"
+ charnum "\\b\\)\\|\\(^[ \t]*0*" charnum "\\b\\)")
+ nil t)
+ (looking-at (concat "^[ \t0-9]*do[ \t]*0*" charnum))))))))
+
+
diff --git a/lisp/fortran.elc b/lisp/fortran.elc
new file mode 100644
index 00000000000..8759a793f28
--- /dev/null
+++ b/lisp/fortran.elc
@@ -0,0 +1,242 @@
+
+(defvar fortran-do-indent 3 "\
+*Extra indentation applied to `do' blocks.")
+
+(defvar fortran-if-indent 3 "\
+*Extra indentation applied to `if' blocks.")
+
+(defvar fortran-continuation-indent 5 "\
+*Extra indentation applied to `continuation' lines.")
+
+(defvar fortran-comment-indent-style (quote fixed) "\
+*nil forces comment lines not to be touched,
+'fixed produces fixed comment indentation to comment-column,
+and 'relative indents to current fortran indentation plus comment-column.")
+
+(defvar fortran-comment-line-column 6 "\
+*Indentation for text in comment lines.")
+
+(defvar comment-line-start nil "\
+*Delimiter inserted to start new full-line comment.")
+
+(defvar comment-line-start-skip nil "\
+*Regexp to match the start of a full-line comment.")
+
+(defvar fortran-minimum-statement-indent 6 "\
+*Minimum indentation for fortran statements.")
+
+(defvar fortran-comment-indent-char 32 "\
+*Character to be inserted for Fortran comment indentation.
+Normally a space.")
+
+(defvar fortran-line-number-indent 1 "\
+*Maximum indentation for Fortran line numbers.
+5 means right-justify them within their five-column field.")
+
+(defvar fortran-check-all-num-for-matching-do nil "\
+*Non-nil causes all numbered lines to be treated as possible do-loop ends.")
+
+(defvar fortran-continuation-char 36 "\
+*Character which is inserted in column 5 by \\[fortran-split-line]
+to begin a continuation line. Normally $.")
+
+(defvar fortran-comment-region "c$$$" "\
+*String inserted by \\[fortran-comment-region] at start of each line in region.")
+
+(defvar fortran-electric-line-number t "\
+*Non-nil causes line number digits to be moved to the correct column as typed.")
+
+(defvar fortran-startup-message t "\
+*Non-nil displays a startup message when fortran-mode is first called.")
+
+(defvar fortran-column-ruler (concat "0 4 6 10 20 30 40 50 60 70
+" "[ ]|{ | | | | | | | | | | | | |}
+") "*String displayed above current line by \\[fortran-column-ruler].")
+
+(defconst fortran-mode-version "1.21")
+
+(defvar fortran-mode-syntax-table nil "\
+Syntax table in use in fortran-mode buffers.")
+
+(if fortran-mode-syntax-table nil (setq fortran-mode-syntax-table (make-syntax-table)) (modify-syntax-entry 59 "w" fortran-mode-syntax-table) (modify-syntax-entry 43 "." fortran-mode-syntax-table) (modify-syntax-entry 45 "." fortran-mode-syntax-table) (modify-syntax-entry 42 "." fortran-mode-syntax-table) (modify-syntax-entry 47 "." fortran-mode-syntax-table) (modify-syntax-entry 39 "\"" fortran-mode-syntax-table) (modify-syntax-entry 34 "\"" fortran-mode-syntax-table) (modify-syntax-entry 92 "/" fortran-mode-syntax-table) (modify-syntax-entry 46 "w" fortran-mode-syntax-table) (modify-syntax-entry 10 ">" fortran-mode-syntax-table))
+
+(defvar fortran-mode-map nil "\
+Keymap used in fortran mode.")
+
+(if fortran-mode-map nil (setq fortran-mode-map (make-sparse-keymap)) (define-key fortran-mode-map ";" (quote fortran-abbrev-start)) (define-key fortran-mode-map ";" (quote fortran-comment-region)) (define-key fortran-mode-map "" (quote beginning-of-fortran-subprogram)) (define-key fortran-mode-map "" (quote end-of-fortran-subprogram)) (define-key fortran-mode-map ";" (quote fortran-indent-comment)) (define-key fortran-mode-map "" (quote mark-fortran-subprogram)) (define-key fortran-mode-map "
+" (quote fortran-split-line)) (define-key fortran-mode-map "" (quote fortran-indent-subprogram)) (define-key fortran-mode-map "" (quote fortran-window-create)) (define-key fortran-mode-map "" (quote fortran-column-ruler)) (define-key fortran-mode-map "" (quote fortran-previous-statement)) (define-key fortran-mode-map "" (quote fortran-next-statement)) (define-key fortran-mode-map " " (quote fortran-indent-line)) (define-key fortran-mode-map "0" (quote fortran-electric-line-number)) (define-key fortran-mode-map "1" (quote fortran-electric-line-number)) (define-key fortran-mode-map "2" (quote fortran-electric-line-number)) (define-key fortran-mode-map "3" (quote fortran-electric-line-number)) (define-key fortran-mode-map "4" (quote fortran-electric-line-number)) (define-key fortran-mode-map "5" (quote fortran-electric-line-number)) (define-key fortran-mode-map "6" (quote fortran-electric-line-number)) (define-key fortran-mode-map "7" (quote fortran-electric-line-number)) (define-key fortran-mode-map "8" (quote fortran-electric-line-number)) (define-key fortran-mode-map "9" (quote fortran-electric-line-number)))
+
+(defvar fortran-mode-abbrev-table nil)
+
+(if fortran-mode-abbrev-table nil (define-abbrev-table (quote fortran-mode-abbrev-table) nil) (let ((abbrevs-changed nil)) (define-abbrev fortran-mode-abbrev-table ";b" "byte" nil) (define-abbrev fortran-mode-abbrev-table ";ch" "character" nil) (define-abbrev fortran-mode-abbrev-table ";cl" "close" nil) (define-abbrev fortran-mode-abbrev-table ";c" "continue" nil) (define-abbrev fortran-mode-abbrev-table ";cm" "common" nil) (define-abbrev fortran-mode-abbrev-table ";cx" "complex" nil) (define-abbrev fortran-mode-abbrev-table ";di" "dimension" nil) (define-abbrev fortran-mode-abbrev-table ";do" "double" nil) (define-abbrev fortran-mode-abbrev-table ";dc" "double complex" nil) (define-abbrev fortran-mode-abbrev-table ";dp" "double precision" nil) (define-abbrev fortran-mode-abbrev-table ";dw" "do while" nil) (define-abbrev fortran-mode-abbrev-table ";e" "else" nil) (define-abbrev fortran-mode-abbrev-table ";ed" "enddo" nil) (define-abbrev fortran-mode-abbrev-table ";el" "elseif" nil) (define-abbrev fortran-mode-abbrev-table ";en" "endif" nil) (define-abbrev fortran-mode-abbrev-table ";eq" "equivalence" nil) (define-abbrev fortran-mode-abbrev-table ";ex" "external" nil) (define-abbrev fortran-mode-abbrev-table ";ey" "entry" nil) (define-abbrev fortran-mode-abbrev-table ";f" "format" nil) (define-abbrev fortran-mode-abbrev-table ";fu" "function" nil) (define-abbrev fortran-mode-abbrev-table ";g" "goto" nil) (define-abbrev fortran-mode-abbrev-table ";im" "implicit" nil) (define-abbrev fortran-mode-abbrev-table ";ib" "implicit byte" nil) (define-abbrev fortran-mode-abbrev-table ";ic" "implicit complex" nil) (define-abbrev fortran-mode-abbrev-table ";ich" "implicit character" nil) (define-abbrev fortran-mode-abbrev-table ";ii" "implicit integer" nil) (define-abbrev fortran-mode-abbrev-table ";il" "implicit logical" nil) (define-abbrev fortran-mode-abbrev-table ";ir" "implicit real" nil) (define-abbrev fortran-mode-abbrev-table ";inc" "include" nil) (define-abbrev fortran-mode-abbrev-table ";in" "integer" nil) (define-abbrev fortran-mode-abbrev-table ";intr" "intrinsic" nil) (define-abbrev fortran-mode-abbrev-table ";l" "logical" nil) (define-abbrev fortran-mode-abbrev-table ";op" "open" nil) (define-abbrev fortran-mode-abbrev-table ";pa" "parameter" nil) (define-abbrev fortran-mode-abbrev-table ";pr" "program" nil) (define-abbrev fortran-mode-abbrev-table ";p" "print" nil) (define-abbrev fortran-mode-abbrev-table ";re" "real" nil) (define-abbrev fortran-mode-abbrev-table ";r" "read" nil) (define-abbrev fortran-mode-abbrev-table ";rt" "return" nil) (define-abbrev fortran-mode-abbrev-table ";rw" "rewind" nil) (define-abbrev fortran-mode-abbrev-table ";s" "stop" nil) (define-abbrev fortran-mode-abbrev-table ";su" "subroutine" nil) (define-abbrev fortran-mode-abbrev-table ";ty" "type" nil) (define-abbrev fortran-mode-abbrev-table ";w" "write" nil)))
+
+(defun fortran-mode nil "\
+Major mode for editing fortran code.
+Tab indents the current fortran line correctly.
+`do' statements must not share a common `continue'.
+
+Type `;?' or `;\\[help-command]' to display a list of built-in abbrevs for Fortran keywords.
+
+Variables controlling indentation style and extra features:
+
+ comment-start
+ Normally nil in Fortran mode. If you want to use comments
+ starting with `!', set this to the string \"!\".
+ fortran-do-indent
+ Extra indentation within do blocks. (default 3)
+ fortran-if-indent
+ Extra indentation within if blocks. (default 3)
+ fortran-continuation-indent
+ Extra indentation appled to continuation statements. (default 5)
+ fortran-comment-line-column
+ Amount of indentation for text within full-line comments. (default 6)
+ fortran-comment-indent-style
+ nil means don't change indentation of text in full-line comments,
+ fixed means indent that text at column fortran-comment-line-column
+ relative means indent at fortran-comment-line-column beyond the
+ indentation for a line of code.
+ Default value is fixed.
+ fortran-comment-indent-char
+ Character to be inserted instead of space for full-line comment
+ indentation. (default is a space)
+ fortran-minimum-statement-indent
+ Minimum indentation for fortran statements. (default 6)
+ fortran-line-number-indent
+ Maximum indentation for line numbers. A line number will get
+ less than this much indentation if necessary to avoid reaching
+ column 5. (default 1)
+ fortran-check-all-num-for-matching-do
+ Non-nil causes all numbered lines to be treated as possible 'continue'
+ statements. (default nil)
+ fortran-continuation-char
+ character to be inserted in column 5 of a continuation line.
+ (default $)
+ fortran-comment-region
+ String inserted by \\[fortran-comment-region] at start of each line in
+ region. (default \"c$$$\")
+ fortran-electric-line-number
+ Non-nil causes line number digits to be moved to the correct column
+ as typed. (default t)
+ fortran-startup-message
+ Set to nil to inhibit message first time fortran-mode is used.
+
+Turning on Fortran mode calls the value of the variable fortran-mode-hook
+with no args, if that value is non-nil.
+\\{fortran-mode-map}" (interactive) (byte-code "ÂˆÓ ˆ…
+ˆ×Ë!ˆÂ‰ ˆ×Ì!ˆÍ‰ ˆ×Î!ˆÍ‰ˆ×Ï!ˆÂ‰ˆÝ!ˆÞ‰ˆß‰ˆàá!‡" [fortran-startup-message fortran-mode-version nil local-abbrev-table fortran-mode-abbrev-table fortran-mode-syntax-table indent-line-function comment-indent-hook comment-line-start-skip comment-line-start comment-start-skip comment-start require-final-newline t abbrev-all-caps indent-tabs-mode fortran-mode-map mode-name major-mode kill-all-local-variables message "Emacs Fortran mode version %s. Bugs to bug-fortran-mode@erl.mit.edu" set-syntax-table make-local-variable fortran-indent-line fortran-comment-hook "^[Cc*][^
+]*[ ]*" "c" "![ ]*" use-local-map "Fortran" fortran-mode run-hooks fortran-mode-hook] 15))
+
+(defun fortran-comment-hook nil (byte-code "ŠÁÂ!ˆÃi\\])‡" [comment-column skip-chars-backward " " 1] 3))
+
+(defun fortran-indent-comment nil "\
+Align or create comment on current line.
+Existing comments of all types are recognized and aligned.
+If the line has no comment, a side-by-side comment is inserted and aligned
+if the value of comment-start is not nil.
+Otherwise, a separate-line comment is inserted, on this line
+or on a new line inserted before this line if this line is not blank." (interactive) (byte-code "ÆˆÇ ˆÈ!ƒ
+" forward-char -1 insert-char 0 calculate-fortran-indent] 19))
+
+(defun fortran-comment-region (beg-region end-region arg) "\
+Comments every line in the region.
+Puts fortran-comment-region at the beginning of every line in the region.
+BEG-REGION and END-REGION are args which specify the region boundaries.
+With non-nil ARG, uncomments the region." (interactive "*r
+P") (byte-code "ÇˆÈ É Ê
+\"ˆ bˆË ˆ ?ƒ2
+
+(defun fortran-abbrev-start nil "\
+Typing \";\\[help-command]\" or \";?\" lists all the fortran abbrevs.
+Any other key combination is executed normally." (interactive) (byte-code "ĈÄ cˆr‰ÅU†
+Uƒ
+
+(defun fortran-abbrev-help nil "\
+List the currently defined abbrevs in Fortran mode." (interactive) (byte-code "ÁˆÂÃ!ˆÄÅ!ˆÆÇ\"ˆÂÈ!‡" [fortran-mode-abbrev-table nil message "Listing abbrev table..." require abbrevlist list-one-abbrev-table "*Help*" "Listing abbrev table...done"] 5))
+
+(defun fortran-column-ruler nil "\
+Inserts a column ruler momentarily above current line, till next keystroke.
+The ruler is defined by the value of fortran-column-ruler.
+The key typed is executed unless it is SPC." (interactive) (byte-code "ÁˆÂŠÃ ˆ`)ÁÄ$‡" [fortran-column-ruler nil momentary-string-display beginning-of-line "Type SPC or any command to erase ruler."] 6))
+
+(defun fortran-window-create nil "\
+Makes the window 72 columns wide." (interactive) (byte-code "ˆÃÄÅ!)ˆÆÇ!ˆÈÉÁ\"ˆÊË !‡" [window-min-width t nil 2 split-window-horizontally 73 other-window 1 switch-to-buffer " fortran-window-extra" select-window previous-window] 6))
+
+(defun fortran-split-line nil "\
+Break line at point and insert continuation marker and alignment." (interactive) (byte-code "ÃˆÄ ˆŠÅ ˆÆ!)ƒ
+\"ˆË ‡" [comment-line-start-skip comment-line-start fortran-continuation-char nil delete-horizontal-space beginning-of-line looking-at insert "
+" " " "
+ " fortran-indent-line] 7))
+
+(defun delete-horizontal-regexp (chars) "\
+Delete all characters in CHARS around point.
+CHARS is like the inside of a [...] in a regular expression
+except that ] is never special and quotes ^, - or ." (interactive "*s") (byte-code "ÁˆÂ!ˆÃ`Ä!ˆ`\"‡" [chars nil skip-chars-backward delete-region skip-chars-forward] 5))
+
+(defun fortran-electric-line-number (arg) "\
+Self insert, but if part of a Fortran line number indent it automatically.
+Auto-indent does not happen if a numeric arg is used." (interactive "P") (byte-code "Ĉ†
+
+(defun beginning-of-fortran-subprogram nil "\
+Moves point to the beginning of the current fortran subprogram." (interactive) (byte-code "ˆÁÃÄ!ˆÅÆÂÇ#ˆÈÆ!…
+
+(defun end-of-fortran-subprogram nil "\
+Moves point to the end of the current fortran subprogram." (interactive) (byte-code "ˆÁÃÄ!ˆÅÆÂÇ#ˆÈÉ!bˆÊË!)‡" [case-fold-search t nil beginning-of-line 2 re-search-forward "^[ 0-9]*end\\b[ ]*[^ =(a-z]" move match-beginning 0 forward-line 1] 5))
+
+(defun mark-fortran-subprogram nil "\
+Put mark at end of fortran subprogram, point at beginning.
+The marks are pushed." (interactive) (byte-code "ÀˆÁ ˆÂ`!ˆÃ ‡" [nil end-of-fortran-subprogram push-mark beginning-of-fortran-subprogram] 4))
+
+(defun fortran-previous-statement nil "\
+Moves point to beginning of the previous fortran statement.
+Returns 'first-statement if that statement is the first
+non-comment Fortran statement in the file, and nil otherwise." (interactive) (byte-code "ňÅÅÆ ˆÇÈÉÊ
+!!P!†
+]" forward-line -1 0 "[ ]*$" message "Incomplete continuation statement." fortran-previous-statement first-statement] 13))
+
+(defun fortran-next-statement nil "\
+Moves point to beginning of the next fortran statement.
+ Returns 'last-statement if that statement is the last
+ non-comment Fortran statement in the file, and nil otherwise." (interactive) (byte-code "ÈÃÄ ˆÅÆ!ÇU‰…(
+P!…0
+]" "[ ]*" last-statement] 8))
+
+(defun fortran-indent-line nil "\
+Indents current fortran line based on its contents and on previous lines." (interactive) (byte-code "ÃˆÄ ŠÅ ˆÆ U?†
+ŠÌ ˆ`)Í#…9
+
+(defun fortran-indent-subprogram nil "\
+Properly indents the Fortran subprogram which contains point." (interactive) (byte-code "ÀˆŠÁ ˆÂÃ!ˆÄ`Å À#)ˆÂÆ!‡" [nil mark-fortran-subprogram message "Indenting subprogram..." indent-region mark "Indenting subprogram...done."] 7))
+
+(defun calculate-fortran-indent nil "\
+Calculates the fortran indent column based on previous lines." (byte-code "ÎÎÃŠÏ ‰ˆ ƒ
+\\‰‚­
+‰‚?Óáâã !!P!†À
+]" "[ ]*[0-9]+" fortran-check-for-matching-do "end[ ]*if\\b" "continue\\b" "end[ ]*do\\b" "end\\b[ ]*[^ =(a-z]" message "Warning: `end' not in column %d. Probably an unclosed block."] 29))
+
+(defun fortran-current-line-indentation nil "\
+Indentation of current line, ignoring Fortran line number or continuation.
+This is the column position of the first non-whitespace character
+aside from the line number and/or column 5 line-continuation character.
+For comment lines, returns indentation of the first
+non-indentation text within the comment." (byte-code "ŠÃ ˆÄ!ƒ
+]" move-to-column 5 " "] 10))
+
+(defun fortran-indent-to-column (col) "\
+Indents current line with spaces to column COL.
+notes: 1) A non-zero/non-blank character in column 5 indicates a continuation
+ line, and this continuation character is retained on indentation;
+ 2) If fortran-continuation-char is the first non-whitespace character,
+ this is a continuation line;
+ 3) A non-continuation line which has a number as the first
+ non-whitespace character is a numbered line." (byte-code "ŠÊ ˆË!ƒ2
+!P!ˆÑ
+ iZ\")‚£
+]" forward-char 6 delete-horizontal-space 5 1 "[0-9]+" message "Warning: line number exceeds 5-digit limit." skip-chars-forward "0-9" re-search-forward end-of-line match-beginning fortran-comment-hook] 22))
+
+(defun fortran-line-number-indented-correctly-p nil "\
+Return t if current line's line number is correctly indente.
+Do not call if there is no line number." (byte-code "ŠÁ ˆÂÃ!ˆiX…
+
+(defun fortran-check-for-matching-do nil "\
+When called from a numbered statement, returns t
+ if matching 'do' is found, and nil otherwise." (byte-code "ÃÂŠÄ ˆÅÆ!…7
diff --git a/lisp/ftp.el b/lisp/ftp.el
index c7d7b7e59df..917661d9836 100644
--- a/lisp/ftp.el
+++ b/lisp/ftp.el
@@ -18,10 +18,6 @@
;; along with GNU Emacs; see the file COPYING. If not, write to
;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-;; Prevent changes in major modes from altering these variables.
-(put 'ftp-temp-file-name 'permanent-local t)
-(put 'ftp-file 'permanent-local t)
-(put 'ftp-host 'permanent-local t)
;; you can turn this off by doing
;; (setq ftp-password-alist 'compulsory-urinalysis)
@@ -112,16 +108,14 @@ we prompt for the user name and password."
(if filep "" "-directory")
host file))))
(set-buffer buffer)
- (let ((process nil)
+ (let ((process (ftp-setup-buffer host file))
(case-fold-search nil))
(let ((win nil))
(unwind-protect
- (progn
- (setq process (ftp-setup-buffer host file))
- (if (setq win (ftp-login process host user password))
- (message "Logged in")
- (error "Ftp login failed")))
- (or win (and process (delete-process process)))))
+ (if (setq win (ftp-login process host user password))
+ (message "Logged in")
+ (error "Ftp login lost"))
+ (or win (delete-process process))))
(message "Opening %s %s:%s..." (if filep "file" "directory")
host file)
(if (ftp-command process
@@ -161,37 +155,34 @@ USER and PASSWORD are defaulted from the values used when
(let ((buffer (get-buffer-create (format "*ftp %s:%s*" host file)))
(tmp (make-temp-name "/tmp/emacsftp")))
(write-region (point-min) (point-max) tmp)
- (save-excursion
- (set-buffer buffer)
- (make-local-variable 'ftp-temp-file-name)
- (setq ftp-temp-file-name tmp)
- (let ((process (ftp-setup-buffer host file))
- (case-fold-search nil))
- (let ((win nil))
- (unwind-protect
- (if (setq win (ftp-login process host user password))
- (message "Logged in")
+ (set-buffer buffer)
+ (make-local-variable 'ftp-temp-file-name)
+ (setq ftp-temp-file-name tmp)
+ (let ((process (ftp-setup-buffer host file))
+ (case-fold-search nil))
+ (let ((win nil))
+ (unwind-protect
+ (if (setq win (ftp-login process host user password))
+ (message "Logged in")
(error "Ftp login lost"))
- (or win (delete-process process))))
- (message "Opening file %s:%s..." host file)
- (if (ftp-command process
- (format "send \"%s\" \"%s\"\nquit\n" tmp file)
- "150.*\n"
- "200.*\n")
- (progn (forward-line 1)
- (setq foo1 (current-buffer))
- (let ((buffer-read-only nil))
- (delete-region (point-min) (point)))
- (message "Saving %s:%s in background. Bye!" host file)
- (set-process-sentinel process
- 'ftp-asynchronous-output-sentinel)
- process)
- (switch-to-buffer buffer)
- (setq foo2 (current-buffer))
- (let ((buffer-read-only nil))
- (insert-before-markers "<<<Ftp lost>>>"))
- (delete-process process)
- (error "Ftp write %s:%s lost" host file))))))
+ (or win (delete-process process))))
+ (message "Opening file %s:%s..." host file)
+ (if (ftp-command process
+ (format "send \"%s\" \"%s\"\nquit\n" tmp file)
+ "\\(150\\|125\\).*\n"
+ "200.*\n")
+ (progn (forward-line 1)
+ (let ((buffer-read-only nil))
+ (delete-region (point-min) (point)))
+ (message "Saving %s:%s in background. Bye!" host file)
+ (set-process-sentinel process
+ 'ftp-asynchronous-output-sentinel)
+ process)
+ (switch-to-buffer buffer)
+ (let ((buffer-read-only nil))
+ (insert-before-markers "<<<Ftp lost>>>"))
+ (delete-process process)
+ (error "Ftp write %s:%s lost" host file)))))
(defun ftp-setup-buffer (host file)
@@ -205,14 +196,13 @@ USER and PASSWORD are defaulted from the values used when
(while (get-buffer-process (current-buffer))
(kill-process (get-buffer-process (current-buffer))))
(error "Foo"))))
- ;(buffer-disable-undo (current-buffer))
+ ;(buffer-flush-undo (current-buffer))
(setq buffer-read-only nil)
(erase-buffer)
(make-local-variable 'ftp-host)
(setq ftp-host host)
(make-local-variable 'ftp-file)
(setq ftp-file file)
- (setq foo3 (current-buffer))
(setq buffer-read-only t)
(start-process "ftp" (current-buffer) "ftp" "-i" "-n" "-g"))
@@ -222,7 +212,7 @@ USER and PASSWORD are defaulted from the values used when
(if (ftp-command process
(format "open %s\nuser %s %s\n" host user password)
"230.*\n"
- "\\(Connected to \\|220\\|331\\|Remote system type\\|Using.*mode\\|Remember to set\\).*\n")
+ "\\(Connected to \\|220\\|331\\).*\n")
t
(switch-to-buffer (process-buffer process))
(delete-process process)
@@ -233,7 +223,8 @@ USER and PASSWORD are defaulted from the values used when
(defun ftp-command (process command win ignore)
(process-send-string process command)
- (let ((p 1))
+ (let ((p 1)
+ (case-fold-search t))
(while (numberp p)
(cond ;((not (bolp)))
((looking-at win)
@@ -242,9 +233,13 @@ USER and PASSWORD are defaulted from the values used when
((looking-at "^ftp> \\|^\n")
(goto-char (match-end 0)))
((looking-at ignore)
+ ;; Ignore status messages whose codes indicate no problem.
+ (forward-line 1))
+ ((looking-at "^[^0-9]")
+ ;; Ignore any lines that don't have status codes.
(forward-line 1))
((not (search-forward "\n" nil t))
- ;; the way asynchronous process-output works with (point)
+ ;; the way asynchronous process-output fucks with (point)
;; is really really disgusting.
(setq p (point))
(condition-case ()
@@ -275,27 +270,26 @@ USER and PASSWORD are defaulted from the values used when
(set-buffer (process-buffer process))
(let (msg
(r (if input "[0-9]+ bytes received in [0-9]+\\.[0-9]+ seconds.*$" "[0-9]+ bytes sent in [0-9]+\\.[0-9]+ seconds.*$")))
- (let ((buffer-read-only nil))
- (goto-char (point-max))
- (search-backward "226 ")
- (if (looking-at r)
- (search-backward "226 "))
- (let ((p (point)))
- (setq msg (concat (format "ftp %s %s:%s done"
- (if input "read" "write")
- ftp-host ftp-file)
- (if (re-search-forward r nil t)
- (concat ": " (buffer-substring
- (match-beginning 0)
- (match-end 0)))
- "")))
- (delete-region p (point-max))
- (save-excursion
- (set-buffer (get-buffer-create "*ftp log*"))
- (let ((buffer-read-only nil))
- (insert msg ?\n)))))
- ;; Note the preceding let must end here
- ;; so it doesn't cross the (kill-buffer (current-buffer)).
+ (goto-char (point-max))
+ (search-backward "226 ")
+ (if (looking-at r)
+ (search-backward "226 "))
+ (let ((p (point)))
+ (setq msg (concat (format "ftp %s %s:%s done"
+ (if input "read" "write")
+ ftp-host ftp-file)
+ (if (re-search-forward r nil t)
+ (concat ": " (buffer-substring
+ (match-beginning 0)
+ (match-end 0)))
+ "")))
+ (let ((buffer-read-only nil))
+ (delete-region p (point-max)))
+ (save-excursion
+ (set-buffer (get-buffer-create "*ftp log*"))
+ (let ((buffer-read-only nil))
+ (insert msg ?\n)))
+ (set-buffer-modified-p nil))
(if (not input)
(progn
(condition-case ()
@@ -303,8 +297,6 @@ USER and PASSWORD are defaulted from the values used when
ftp-temp-file-name
(delete-file ftp-temp-file-name))
(error nil))
- ;; Kill the temporary buffer which the ftp process
- ;; puts its output in.
(kill-buffer (current-buffer)))
;; You don't want to look at this.
(let ((kludge (generate-new-buffer (format "%s:%s (ftp)"
@@ -312,7 +304,6 @@ USER and PASSWORD are defaulted from the values used when
(setq kludge (prog1 (buffer-name kludge) (kill-buffer kludge)))
(rename-buffer kludge)
;; ok, you can look again now.
- (set-buffer-modified-p nil)
(ftp-setup-write-file-hooks)))
(if (and asynchronous
;(waiting-for-user-input-p)
@@ -350,15 +341,20 @@ USER and PASSWORD are defaulted from the values used when
(setq buffer-read-only nil))
(defun ftp-write-file-hook ()
- (let ((process (ftp-write-file ftp-host ftp-file)))
+ (let ((buffer (current-buffer))
+ (process (ftp-write-file ftp-host ftp-file)))
(set-process-sentinel process 'ftp-synchronous-output-sentinel)
(message "FTP writing %s:%s..." ftp-host ftp-file)
(while (eq (process-status process) 'run)
(condition-case ()
(accept-process-output process)
(error nil)))
- (set-buffer-modified-p nil)
- (message "FTP writing %s:%s...done" ftp-host ftp-file))
+ (and (eq (process-status process) 'exit)
+ (= (process-exit-status process) 0)
+ (save-excursion
+ (set-buffer buffer)
+ (set-buffer-modified-p nil))))
+ (message "Written")
t)
(defun ftp-revert-buffer (&rest ignore)
diff --git a/lisp/ftp.elc b/lisp/ftp.elc
new file mode 100644
index 00000000000..d3d5da49fb1
--- /dev/null
+++ b/lisp/ftp.elc
Binary files differ
diff --git a/lisp/gdb.el b/lisp/gdb.el
new file mode 100644
index 00000000000..c7e80b99691
--- /dev/null
+++ b/lisp/gdb.el
@@ -0,0 +1,397 @@
+;; Run gdb under Emacs
+;; Copyright (C) 1988 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 1, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+;; Author: W. Schelter, University of Texas
+;; wfs@rascal.ics.utexas.edu
+;; Rewritten by rms.
+
+;; Some ideas are due to Masanobu.
+
+;; Description of GDB interface:
+
+;; A facility is provided for the simultaneous display of the source code
+;; in one window, while using gdb to step through a function in the
+;; other. A small arrow in the source window, indicates the current
+;; line.
+
+;; Starting up:
+
+;; In order to use this facility, invoke the command GDB to obtain a
+;; shell window with the appropriate command bindings. You will be asked
+;; for the name of a file to run. Gdb will be invoked on this file, in a
+;; window named *gdb-foo* if the file is foo.
+
+;; M-s steps by one line, and redisplays the source file and line.
+
+;; You may easily create additional commands and bindings to interact
+;; with the display. For example to put the gdb command next on \M-n
+;; (def-gdb next "\M-n")
+
+;; This causes the emacs command gdb-next to be defined, and runs
+;; gdb-display-frame after the command.
+
+;; gdb-display-frame is the basic display function. It tries to display
+;; in the other window, the file and line corresponding to the current
+;; position in the gdb window. For example after a gdb-step, it would
+;; display the line corresponding to the position for the last step. Or
+;; if you have done a backtrace in the gdb buffer, and move the cursor
+;; into one of the frames, it would display the position corresponding to
+;; that frame.
+
+;; gdb-display-frame is invoked automatically when a filename-and-line-number
+;; appears in the output.
+
+
+(require 'shell)
+
+(defvar gdb-prompt-pattern "^(.*gdb[+]?) *"
+ "A regexp to recognize the prompt for gdb or gdb+.")
+
+(defvar gdb-mode-map nil
+ "Keymap for gdb-mode.")
+
+(if gdb-mode-map
+ nil
+ (setq gdb-mode-map (copy-keymap shell-mode-map))
+ (define-key gdb-mode-map "\C-l" 'gdb-refresh))
+
+(define-key ctl-x-map " " 'gdb-break)
+(define-key ctl-x-map "&" 'send-gdb-command)
+
+;;Of course you may use `def-gdb' with any other gdb command, including
+;;user defined ones.
+
+(defmacro def-gdb (name key &optional doc)
+ (let* ((fun (intern (format "gdb-%s" name)))
+ (cstr (list 'if '(not (= 1 arg))
+ (list 'format "%s %s" name 'arg)
+ name)))
+ (list 'progn
+ (list 'defun fun '(arg)
+ (or doc "")
+ '(interactive "p")
+ (list 'gdb-call cstr))
+ (list 'define-key 'gdb-mode-map key (list 'quote fun)))))
+
+(def-gdb "step" "\M-s" "Step one source line with display")
+(def-gdb "stepi" "\M-i" "Step one instruction with display")
+(def-gdb "next" "\M-n" "Step one source line (skip functions)")
+(def-gdb "cont" "\M-c" "Continue with display")
+
+(def-gdb "finish" "\C-c\C-f" "Finish executing current function")
+(def-gdb "up" "\M-u" "Go up N stack frames (numeric arg) with display")
+(def-gdb "down" "\M-d" "Go down N stack frames (numeric arg) with display")
+
+(defun gdb-mode ()
+ "Major mode for interacting with an inferior Gdb process.
+The following commands are available:
+
+\\{gdb-mode-map}
+
+\\[gdb-display-frame] displays in the other window
+the last line referred to in the gdb buffer.
+
+\\[gdb-step],\\[gdb-next], and \\[gdb-nexti] in the gdb window,
+call gdb to step,next or nexti and then update the other window
+with the current file and position.
+
+If you are in a source file, you may select a point to break
+at, by doing \\[gdb-break].
+
+Commands:
+Many commands are inherited from shell mode.
+Additionally we have:
+
+\\[gdb-display-frame] display frames file in other window
+\\[gdb-step] advance one line in program
+\\[gdb-next] advance one line in program (skip over calls).
+\\[send-gdb-command] used for special printing of an arg at the current point.
+C-x SPACE sets break point at current line."
+ (interactive)
+ (kill-all-local-variables)
+ (setq major-mode 'gdb-mode)
+ (setq mode-name "Inferior Gdb")
+ (setq mode-line-process '(": %s"))
+ (use-local-map gdb-mode-map)
+ (make-local-variable 'last-input-start)
+ (setq last-input-start (make-marker))
+ (make-local-variable 'last-input-end)
+ (setq last-input-end (make-marker))
+ (make-local-variable 'gdb-last-frame)
+ (setq gdb-last-frame nil)
+ (make-local-variable 'gdb-last-frame-displayed-p)
+ (setq gdb-last-frame-displayed-p t)
+ (make-local-variable 'gdb-delete-prompt-marker)
+ (setq gdb-delete-prompt-marker nil)
+ (make-local-variable 'gdb-filter-accumulator)
+ (setq gdb-filter-accumulator nil)
+ (make-local-variable 'shell-prompt-pattern)
+ (setq shell-prompt-pattern gdb-prompt-pattern)
+ (run-hooks 'shell-mode-hook 'gdb-mode-hook))
+
+(defvar current-gdb-buffer nil)
+
+(defvar gdb-command-name "gdb"
+ "Pathname for executing gdb.")
+
+(defun gdb (path)
+ "Run gdb on program FILE in buffer *gdb-FILE*.
+The directory containing FILE becomes the initial working directory
+and source-file directory for GDB. If you wish to change this, use
+the GDB commands `cd DIR' and `directory'."
+ (interactive "FRun gdb on file: ")
+ (setq path (expand-file-name path))
+ (let ((file (file-name-nondirectory path)))
+ (switch-to-buffer (concat "*gdb-" file "*"))
+ (setq default-directory (file-name-directory path))
+ (or (bolp) (newline))
+ (insert "Current directory is " default-directory "\n")
+ (make-shell (concat "gdb-" file) gdb-command-name nil "-fullname"
+ "-cd" default-directory file)
+ (gdb-mode)
+ (set-process-filter (get-buffer-process (current-buffer)) 'gdb-filter)
+ (set-process-sentinel (get-buffer-process (current-buffer)) 'gdb-sentinel)
+ (gdb-set-buffer)))
+
+(defun gdb-set-buffer ()
+ (cond ((eq major-mode 'gdb-mode)
+ (setq current-gdb-buffer (current-buffer)))))
+
+;; This function is responsible for inserting output from GDB
+;; into the buffer.
+;; Aside from inserting the text, it notices and deletes
+;; each filename-and-line-number;
+;; that GDB prints to identify the selected frame.
+;; It records the filename and line number, and maybe displays that file.
+(defun gdb-filter (proc string)
+ (let ((inhibit-quit t))
+ (if gdb-filter-accumulator
+ (gdb-filter-accumulate-marker proc
+ (concat gdb-filter-accumulator string))
+ (gdb-filter-scan-input proc string))))
+
+(defun gdb-filter-accumulate-marker (proc string)
+ (setq gdb-filter-accumulator nil)
+ (if (> (length string) 1)
+ (if (= (aref string 1) ?\032)
+ (let ((end (string-match "\n" string)))
+ (if end
+ (progn
+ (let* ((first-colon (string-match ":" string 2))
+ (second-colon
+ (string-match ":" string (1+ first-colon))))
+ (setq gdb-last-frame
+ (cons (substring string 2 first-colon)
+ (string-to-int
+ (substring string (1+ first-colon)
+ second-colon)))))
+ (setq gdb-last-frame-displayed-p nil)
+ (gdb-filter-scan-input proc
+ (substring string (1+ end))))
+ (setq gdb-filter-accumulator string)))
+ (gdb-filter-insert proc "\032")
+ (gdb-filter-scan-input proc (substring string 1)))
+ (setq gdb-filter-accumulator string)))
+
+(defun gdb-filter-scan-input (proc string)
+ (if (equal string "")
+ (setq gdb-filter-accumulator nil)
+ (let ((start (string-match "\032" string)))
+ (if start
+ (progn (gdb-filter-insert proc (substring string 0 start))
+ (gdb-filter-accumulate-marker proc
+ (substring string start)))
+ (gdb-filter-insert proc string)))))
+
+(defun gdb-filter-insert (proc string)
+ (let ((moving (= (point) (process-mark proc)))
+ (output-after-point (< (point) (process-mark proc)))
+ (old-buffer (current-buffer))
+ start)
+ (set-buffer (process-buffer proc))
+ (unwind-protect
+ (save-excursion
+ ;; Insert the text, moving the process-marker.
+ (goto-char (process-mark proc))
+ (setq start (point))
+ (insert string)
+ (set-marker (process-mark proc) (point))
+ (gdb-maybe-delete-prompt)
+ ;; Check for a filename-and-line number.
+ (gdb-display-frame
+ ;; Don't display the specified file
+ ;; unless (1) point is at or after the position where output appears
+ ;; and (2) this buffer is on the screen.
+ (or output-after-point
+ (not (get-buffer-window (current-buffer))))
+ ;; Display a file only when a new filename-and-line-number appears.
+ t))
+ (set-buffer old-buffer))
+ (if moving (goto-char (process-mark proc)))))
+
+(defun gdb-sentinel (proc msg)
+ (cond ((null (buffer-name (process-buffer proc)))
+ ;; buffer killed
+ ;; Stop displaying an arrow in a source file.
+ (setq overlay-arrow-position nil)
+ (set-process-buffer proc nil))
+ ((memq (process-status proc) '(signal exit))
+ ;; Stop displaying an arrow in a source file.
+ (setq overlay-arrow-position nil)
+ ;; Fix the mode line.
+ (setq mode-line-process
+ (concat ": "
+ (symbol-name (process-status proc))))
+ (let* ((obuf (current-buffer)))
+ ;; save-excursion isn't the right thing if
+ ;; process-buffer is current-buffer
+ (unwind-protect
+ (progn
+ ;; Write something in *compilation* and hack its mode line,
+ (set-buffer (process-buffer proc))
+ ;; Force mode line redisplay soon
+ (set-buffer-modified-p (buffer-modified-p))
+ (if (eobp)
+ (insert ?\n mode-name " " msg)
+ (save-excursion
+ (goto-char (point-max))
+ (insert ?\n mode-name " " msg)))
+ ;; If buffer and mode line will show that the process
+ ;; is dead, we can delete it now. Otherwise it
+ ;; will stay around until M-x list-processes.
+ (delete-process proc))
+ ;; Restore old buffer, but don't restore old point
+ ;; if obuf is the gdb buffer.
+ (set-buffer obuf))))))
+
+
+(defun gdb-refresh ()
+ "Fix up a possibly garbled display, and redraw the arrow."
+ (interactive)
+ (redraw-display)
+ (gdb-display-frame))
+
+(defun gdb-display-frame (&optional nodisplay noauto)
+ "Find, obey and delete the last filename-and-line marker from GDB.
+The marker looks like \\032\\032FILENAME:LINE:CHARPOS\\n.
+Obeying it means displaying in another window the specified file and line."
+ (interactive)
+ (gdb-set-buffer)
+ (and gdb-last-frame (not nodisplay)
+ (or (not gdb-last-frame-displayed-p) (not noauto))
+ (progn (gdb-display-line (car gdb-last-frame) (cdr gdb-last-frame))
+ (setq gdb-last-frame-displayed-p t))))
+
+;; Make sure the file named TRUE-FILE is in a buffer that appears on the screen
+;; and that its line LINE is visible.
+;; Put the overlay-arrow on the line LINE in that buffer.
+
+(defun gdb-display-line (true-file line)
+ (let* ((buffer (find-file-noselect true-file))
+ (window (display-buffer buffer t))
+ (pos))
+ (save-excursion
+ (set-buffer buffer)
+ (save-restriction
+ (widen)
+ (goto-line line)
+ (setq pos (point))
+ (setq overlay-arrow-string "=>")
+ (or overlay-arrow-position
+ (setq overlay-arrow-position (make-marker)))
+ (set-marker overlay-arrow-position (point) (current-buffer)))
+ (cond ((or (< pos (point-min)) (> pos (point-max)))
+ (widen)
+ (goto-char pos))))
+ (set-window-point window overlay-arrow-position)))
+
+(defun gdb-call (command)
+ "Invoke gdb COMMAND displaying source in other window."
+ (interactive)
+ (goto-char (point-max))
+ (setq gdb-delete-prompt-marker (point-marker))
+ (gdb-set-buffer)
+ (send-string (get-buffer-process current-gdb-buffer)
+ (concat command "\n")))
+
+(defun gdb-maybe-delete-prompt ()
+ (if (and gdb-delete-prompt-marker
+ (> (point-max) (marker-position gdb-delete-prompt-marker)))
+ (let (start)
+ (goto-char gdb-delete-prompt-marker)
+ (setq start (point))
+ (beginning-of-line)
+ (delete-region (point) start)
+ (setq gdb-delete-prompt-marker nil))))
+
+(defun gdb-break ()
+ "Set GDB breakpoint at this source line."
+ (interactive)
+ (let ((file-name (file-name-nondirectory buffer-file-name))
+ (line (save-restriction
+ (widen)
+ (1+ (count-lines 1 (point))))))
+ (send-string (get-buffer-process current-gdb-buffer)
+ (concat "break " file-name ":" line "\n"))))
+
+(defun gdb-read-address()
+ "Return a string containing the core-address found in the buffer at point."
+ (save-excursion
+ (let ((pt (dot)) found begin)
+ (setq found (if (search-backward "0x" (- pt 7) t)(dot)))
+ (cond (found (forward-char 2)(setq result
+ (buffer-substring found
+ (progn (re-search-forward "[^0-9a-f]")
+ (forward-char -1)
+ (dot)))))
+ (t (setq begin (progn (re-search-backward "[^0-9]") (forward-char 1)
+ (dot)))
+ (forward-char 1)
+ (re-search-forward "[^0-9]")
+ (forward-char -1)
+ (buffer-substring begin (dot)))))))
+
+
+(defvar gdb-commands nil
+ "List of strings or functions used by send-gdb-command.
+It is for customization by you.")
+
+(defun send-gdb-command (arg)
+
+ "This command reads the number where the cursor is positioned. It
+ then inserts this ADDR at the end of the gdb buffer. A numeric arg
+ selects the ARG'th member COMMAND of the list gdb-print-command. If
+ COMMAND is a string, (format COMMAND ADDR) is inserted, otherwise
+ (funcall COMMAND ADDR) is inserted. eg. \"p (rtx)%s->fld[0].rtint\"
+ is a possible string to be a member of gdb-commands. "
+
+
+ (interactive "P")
+ (let (comm addr)
+ (if arg (setq comm (nth arg gdb-commands)))
+ (setq addr (gdb-read-address))
+ (if (eq (current-buffer) current-gdb-buffer)
+ (set-mark (point)))
+ (cond (comm
+ (setq comm
+ (if (stringp comm) (format comm addr) (funcall comm addr))))
+ (t (setq comm addr)))
+ (switch-to-buffer current-gdb-buffer)
+ (goto-char (dot-max))
+ (insert-string comm)))
diff --git a/lisp/gdb.elc b/lisp/gdb.elc
new file mode 100644
index 00000000000..b5191c30490
--- /dev/null
+++ b/lisp/gdb.elc
Binary files differ
diff --git a/lisp/gnusmail.el b/lisp/gnusmail.el
deleted file mode 100644
index 9bfedc89173..00000000000
--- a/lisp/gnusmail.el
+++ /dev/null
@@ -1,148 +0,0 @@
-;;; Mail reply commands for GNUS newsreader
-;; Copyright (C) 1990 Masanobu UMEDA
-;; $Header: gnusmail.el,v 1.1 90/03/23 13:24:39 umerin Locked $
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY. No author or distributor
-;; accepts responsibility to anyone for the consequences of using it
-;; or for whether it serves any particular purpose or works at all,
-;; unless he says so in writing. Refer to the GNU Emacs General Public
-;; License for full details.
-
-;; Everyone is granted permission to copy, modify and redistribute
-;; GNU Emacs, but only under the conditions described in the
-;; GNU Emacs General Public License. A copy of this license is
-;; supposed to have been given to you along with GNU Emacs so you
-;; can know your rights and responsibilities. It should be in a
-;; file named COPYING. Among other things, the copyright notice
-;; and this notice must be preserved on all copies.
-
-(provide 'gnusmail)
-(require 'gnus)
-
-;; Provides mail reply and mail other window command using usual mail
-;; interface and mh-e interface.
-;;
-;; To use MAIL: set the variables gnus-mail-reply-method and
-;; gnus-mail-other-window-method to gnus-mail-reply-using-mail and
-;; gnus-mail-other-window-using-mail, respectively.
-;;
-;; To use MH-E: set the variables gnus-mail-reply-method and
-;; gnus-mail-other-window-method to gnus-mail-reply-using-mhe and
-;; gnus-mail-other-window-using-mhe, respectively.
-
-(autoload 'news-mail-reply "rnewspost")
-(autoload 'news-mail-other-window "rnewspost")
-
-(autoload 'mh-send "mh-e")
-(autoload 'mh-send-other-window "mh-e")
-(autoload 'mh-find-path "mh-e")
-(autoload 'mh-yank-cur-msg "mh-e")
-
-;;; Mail reply commands of GNUS Subject Mode
-
-(defun gnus-Subject-mail-reply (yank)
- "Reply mail to news author.
-If prefix arg YANK is non-nil, original article is yanked automatically.
-Customize the variable `gnus-mail-reply-method' to use another mailer."
- (interactive "P")
- (gnus-Subject-select-article)
- (switch-to-buffer gnus-Article-buffer)
- (widen)
- (delete-other-windows)
- (bury-buffer gnus-Article-buffer)
- (funcall gnus-mail-reply-method yank))
-
-(defun gnus-Subject-mail-reply-with-original ()
- "Reply mail to news author with original article."
- (interactive)
- (gnus-Subject-mail-reply t))
-
-(defun gnus-Subject-mail-other-window ()
- "Compose mail in other window.
-Customize the variable `gnus-mail-other-window-method' to use another mailer."
- (interactive)
- (gnus-Subject-select-article)
- (switch-to-buffer gnus-Article-buffer)
- (widen)
- (delete-other-windows)
- (bury-buffer gnus-Article-buffer)
- (funcall gnus-mail-other-window-method))
-
-
-;;; Send mail using sendmail mail mode.
-
-(defun gnus-mail-reply-using-mail (&optional yank)
- "Compose reply mail using mail.
-Optional argument YANK means yank original article."
- (news-mail-reply)
- (gnus-overload-functions)
- (if yank
- (let ((last (point)))
- (goto-char (point-max))
- (mail-yank-original nil)
- (goto-char last)
- )))
-
-(defun gnus-mail-other-window-using-mail ()
- "Compose mail other window using mail."
- (news-mail-other-window)
- (gnus-overload-functions))
-
-
-;;; Send mail using mh-e.
-
-;; The following mh-e interface is all cooperative works of
-;; tanaka@flab.fujitsu.CO.JP (TANAKA Hiroshi), kawabe@sra.CO.JP
-;; (Yoshikatsu Kawabe), and shingu@casund.cpr.canon.co.jp (Toshiaki
-;; SHINGU).
-
-(defun gnus-mail-reply-using-mhe (&optional yank)
- "Compose reply mail using mh-e.
-Optional argument YANK means yank original article.
-The command \\[mh-yank-cur-msg] yanks the original message into current buffer."
- ;; First of all, prepare mhe mail buffer.
- (let (from cc subject date to reply-to (buffer (current-buffer)))
- (save-restriction
- (gnus-Article-show-all-headers) ;I don't think this is really needed.
- (setq from (gnus-fetch-field "from")
- subject (let ((subject (gnus-fetch-field "subject")))
- (if (and subject
- (not (string-match "^[Rr][Ee]:.+$" subject)))
- (concat "Re: " subject) subject))
- reply-to (gnus-fetch-field "reply-to")
- cc (gnus-fetch-field "cc")
- date (gnus-fetch-field "date"))
- (setq mh-show-buffer buffer)
- (setq to (or reply-to from))
- (mh-find-path)
- (mh-send to (or cc "") subject)
- (save-excursion
- (mh-insert-fields
- "In-reply-to:"
- (concat
- (substring from 0 (string-match " *at \\| *@ \\| *(\\| *<" from))
- "'s message of " date)))
- (setq mh-sent-from-folder buffer)
- (setq mh-sent-from-msg 1)
- ))
- ;; Then, yank original article if requested.
- (if yank
- (let ((last (point)))
- (mh-yank-cur-msg)
- (goto-char last)
- )))
-
-(defun gnus-mail-other-window-using-mhe ()
- "Compose mail other window using MH-E Mail."
- (let ((to (read-string "To: "))
- (cc (read-string "Cc: "))
- (subject (read-string "Subject: " (gnus-fetch-field "subject"))))
- (gnus-Article-show-all-headers) ;I don't think this is really needed.
- (setq mh-show-buffer (current-buffer))
- (mh-find-path)
- (mh-send-other-window to cc subject)
- (setq mh-sent-from-folder (current-buffer))
- (setq mh-sent-from-msg 1)))
diff --git a/lisp/gnusmisc.el b/lisp/gnusmisc.el
deleted file mode 100644
index d133b63a30c..00000000000
--- a/lisp/gnusmisc.el
+++ /dev/null
@@ -1,214 +0,0 @@
-;;; Miscellaneous commands for GNUS newsreader
-;; Copyright (C) 1989 Fujitsu Laboratories LTD.
-;; Copyright (C) 1989, 1990 Masanobu UMEDA
-;; $Header: gnusmisc.el,v 1.2 90/03/23 13:25:04 umerin Locked $
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY. No author or distributor
-;; accepts responsibility to anyone for the consequences of using it
-;; or for whether it serves any particular purpose or works at all,
-;; unless he says so in writing. Refer to the GNU Emacs General Public
-;; License for full details.
-
-;; Everyone is granted permission to copy, modify and redistribute
-;; GNU Emacs, but only under the conditions described in the
-;; GNU Emacs General Public License. A copy of this license is
-;; supposed to have been given to you along with GNU Emacs so you
-;; can know your rights and responsibilities. It should be in a
-;; file named COPYING. Among other things, the copyright notice
-;; and this notice must be preserved on all copies.
-
-(provide 'gnusmisc)
-(require 'gnus)
-
-;;;
-;;; GNUS Browse-Killed Mode
-;;;
-
-;; Some ideas are due to roland@wheaties.ai.mit.edu (Roland McGrath).
-;; I'd like to thank him very much.
-
-(defvar gnus-Browse-killed-mode-hook nil
- "*A hook for GNUS Browse-Killed Mode.")
-
-(defvar gnus-Browse-killed-buffer "*Killed Newsgroup*")
-(defvar gnus-Browse-killed-mode-map nil)
-(defvar gnus-winconf-browse-killed nil)
-
-(put 'gnus-Browse-killed-mode 'mode-class 'special)
-
-;; Make the buffer to be managed by GNUS.
-
-(or (memq gnus-Browse-killed-buffer gnus-buffer-list)
- (setq gnus-buffer-list
- (cons gnus-Browse-killed-buffer gnus-buffer-list)))
-
-(if gnus-Browse-killed-mode-map
- nil
- (setq gnus-Browse-killed-mode-map (make-keymap))
- (suppress-keymap gnus-Browse-killed-mode-map t)
- (define-key gnus-Browse-killed-mode-map " " 'gnus-Group-next-group)
- (define-key gnus-Browse-killed-mode-map "\177" 'gnus-Group-prev-group)
- (define-key gnus-Browse-killed-mode-map "\C-n" 'gnus-Group-next-group)
- (define-key gnus-Browse-killed-mode-map "\C-p" 'gnus-Group-prev-group)
- (define-key gnus-Browse-killed-mode-map "n" 'gnus-Group-next-group)
- (define-key gnus-Browse-killed-mode-map "p" 'gnus-Group-prev-group)
- (define-key gnus-Browse-killed-mode-map "y" 'gnus-Browse-killed-yank)
- (define-key gnus-Browse-killed-mode-map "\C-y" 'gnus-Browse-killed-yank)
- (define-key gnus-Browse-killed-mode-map "l" 'gnus-Browse-killed-groups)
- (define-key gnus-Browse-killed-mode-map "q" 'gnus-Browse-killed-exit)
- (define-key gnus-Browse-killed-mode-map "\C-c\C-c" 'gnus-Browse-killed-exit)
- (define-key gnus-Browse-killed-mode-map "\C-c\C-i" 'gnus-Info-find-node))
-
-(defun gnus-Browse-killed-mode ()
- "Major mode for browsing the killed newsgroups.
-All normal editing commands are turned off.
-Instead, these commands are available:
-\\{gnus-Browse-killed-mode-map}
-
-The killed newsgroups are saved in the quick startup file \".newsrc.el\"
-unless disabled inthe options line of the startup file \".newsrc\".
-
-Entry to this mode calls `gnus-Browse-killed-mode-hook' with no arguments
-if that value is non-nil."
- (interactive)
- (kill-all-local-variables)
- ;; Gee. Why don't you upgrade?
- (cond ((boundp 'mode-line-modified)
- (setq mode-line-modified "--- "))
- ((listp (default-value 'mode-line-format))
- (setq mode-line-format
- (cons "--- " (cdr (default-value 'mode-line-format)))))
- (t
- (setq mode-line-format
- "--- GNUS: Killed Newsgroups %[(%m)%]----%3p-%-")))
- (setq major-mode 'gnus-Browse-killed-mode)
- (setq mode-name "Browse-Killed")
- (setq mode-line-buffer-identification "GNUS: Killed Newsgroups")
- (use-local-map gnus-Browse-killed-mode-map)
- (buffer-flush-undo (current-buffer))
- (setq buffer-read-only t) ;Disable modification
- (run-hooks 'gnus-Browse-killed-mode-hook))
-
-(defun gnus-Browse-killed-groups ()
- "Browse the killed newsgroups.
-\\<gnus-Browse-killed-mode-map>\\[gnus-Browse-killed-yank] yanks the newsgroup on the current line into the Newsgroups buffer."
- (interactive)
- (or gnus-killed-assoc
- (error "No killed newsgroups"))
- ;; Save current window configuration if this is first invocation..
- (or (get-buffer-window gnus-Browse-killed-buffer)
- (setq gnus-winconf-browse-killed
- (current-window-configuration)))
- ;; Prepare browsing buffer.
- (pop-to-buffer (get-buffer-create gnus-Browse-killed-buffer))
- (gnus-Browse-killed-mode)
- (let ((buffer-read-only nil)
- (killed-assoc gnus-killed-assoc))
- (erase-buffer)
- (while killed-assoc
- (insert (gnus-Group-prepare-line (car killed-assoc)))
- (setq killed-assoc (cdr killed-assoc)))
- (goto-char (point-min))
- ))
-
-(defun gnus-Browse-killed-yank ()
- "Yank current newsgroup to Newsgroup buffer."
- (interactive)
- (let ((group (gnus-Group-group-name)))
- (if group
- (let* ((buffer-read-only nil)
- (killed (assoc group gnus-killed-assoc)))
- (pop-to-buffer gnus-Group-buffer) ;Needed to adjust point.
- (if killed
- (gnus-Group-insert-group killed))
- (pop-to-buffer gnus-Browse-killed-buffer)
- (beginning-of-line)
- (delete-region (point)
- (progn (forward-line 1) (point)))
- )))
- (gnus-Browse-killed-check-buffer))
-
-(defun gnus-Browse-killed-check-buffer ()
- "Exit if the buffer is empty by deleting the window and killing the buffer."
- (and (null gnus-killed-assoc)
- (get-buffer gnus-Browse-killed-buffer)
- (gnus-Browse-killed-exit)))
-
-(defun gnus-Browse-killed-exit ()
- "Exit this mode by deleting the window and killing the buffer."
- (interactive)
- (and (get-buffer-window gnus-Browse-killed-buffer)
- (delete-window (get-buffer-window gnus-Browse-killed-buffer)))
- (kill-buffer gnus-Browse-killed-buffer)
- ;; Restore previous window configuration if available.
- (and gnus-winconf-browse-killed
- (set-window-configuration gnus-winconf-browse-killed))
- (setq gnus-winconf-browse-killed nil))
-
-
-;;;
-;;; kill/yank newsgroup commands of GNUS Group Mode
-;;;
-
-(defun gnus-Group-kill-group (n)
- "Kill newsgroup on current line, repeated prefix argument N times.
-The killed newsgroups can be yanked by using \\[gnus-Group-yank-group]."
- (interactive "p")
- (let ((buffer-read-only nil)
- (group nil))
- (while (> n 0)
- (setq group (gnus-Group-group-name))
- (or group
- (signal 'end-of-buffer nil))
- (beginning-of-line)
- (delete-region (point)
- (progn (forward-line 1) (point)))
- (gnus-kill-newsgroup group)
- (setq n (1- n))
- ;; Add to killed newsgroups in the buffer if exists.
- (if (get-buffer gnus-Browse-killed-buffer)
- (save-excursion
- (set-buffer gnus-Browse-killed-buffer)
- (let ((buffer-read-only nil))
- (goto-char (point-min))
- (insert (gnus-Group-prepare-line (car gnus-killed-assoc)))
- )))
- )
- (search-forward ":" nil t)
- ))
-
-(defun gnus-Group-yank-group ()
- "Yank the last newsgroup killed with \\[gnus-Group-kill-group],
-inserting it before the newsgroup on the line containging point."
- (interactive)
- (gnus-Group-insert-group (car gnus-killed-assoc))
- ;; Remove killed newsgroups from the buffer if exists.
- (if (get-buffer gnus-Browse-killed-buffer)
- (save-excursion
- (set-buffer gnus-Browse-killed-buffer)
- (let ((buffer-read-only nil))
- (goto-char (point-min))
- (delete-region (point-min)
- (progn (forward-line 1) (point)))
- )))
- (gnus-Browse-killed-check-buffer))
-
-(defun gnus-Group-insert-group (info)
- "Insert newsgroup at current line using `gnus-newsrc-assoc' INFO."
- (if (null gnus-killed-assoc)
- (error "No killed newsgroups"))
- (if (not gnus-have-all-newsgroups)
- (error
- (substitute-command-keys
- "Not all newsgroups are displayed. Type \\[gnus-Group-list-all-groups] to display all newsgroups.")))
- (let ((buffer-read-only nil)
- (group (gnus-Group-group-name)))
- (gnus-insert-newsgroup info group)
- (beginning-of-line)
- (insert (gnus-Group-prepare-line info))
- (forward-line -1)
- (search-forward ":" nil t)
- ))
diff --git a/lisp/gosmacs.el b/lisp/gosmacs.el
index 98f6368f0a8..5ea2697eeb1 100644
--- a/lisp/gosmacs.el
+++ b/lisp/gosmacs.el
@@ -56,8 +56,8 @@ Use \\[set-gnu-bindings] to restore previous global bindings."
(defun rebind-and-record (bindings)
"Establish many new global bindings and record the bindings replaced.
-Arg BINDINGS is an alist whose elements are (KEY DEFINITION).
-Returns a similar alist whose elements describe the same KEYs
+Arg is an alist whose elements are (KEY DEFINITION).
+Value is a similar alist whose elements describe the same KEYs
but each with the old definition that was replaced,"
(let (old)
(while bindings
diff --git a/lisp/play/hanoi.el b/lisp/hanoi.el
index 8884f6cb37b..21871be7b91 100644
--- a/lisp/play/hanoi.el
+++ b/lisp/hanoi.el
@@ -63,7 +63,7 @@
;;
(switch-to-buffer "*Hanoi*")
(setq buffer-read-only nil)
- (buffer-disable-undo (current-buffer))
+ (buffer-flush-undo (current-buffer))
(erase-buffer)
(let ((i 0))
(while (< i floor-row)
diff --git a/lisp/hanoi.elc b/lisp/hanoi.elc
new file mode 100644
index 00000000000..62e69f90bdd
--- /dev/null
+++ b/lisp/hanoi.elc
Binary files differ
diff --git a/lisp/help.el b/lisp/help.el
new file mode 100644
index 00000000000..09086811e8a
--- /dev/null
+++ b/lisp/help.el
@@ -0,0 +1,295 @@
+;; Help commands for Emacs
+;; Copyright (C) 1985, 1986 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 1, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+(defvar help-map (make-sparse-keymap)
+ "Keymap for characters following the Help key.")
+
+(define-key global-map "\C-h" 'help-command)
+(fset 'help-command help-map)
+
+(define-key help-map "\C-h" 'help-for-help)
+(define-key help-map "?" 'help-for-help)
+
+(define-key help-map "\C-c" 'describe-copying)
+(define-key help-map "\C-d" 'describe-distribution)
+(define-key help-map "\C-w" 'describe-no-warranty)
+(define-key help-map "a" 'command-apropos)
+
+(define-key help-map "b" 'describe-bindings)
+
+(define-key help-map "c" 'describe-key-briefly)
+(define-key help-map "k" 'describe-key)
+
+(define-key help-map "d" 'describe-function)
+(define-key help-map "f" 'describe-function)
+
+(define-key help-map "i" 'info)
+
+(define-key help-map "l" 'view-lossage)
+
+(define-key help-map "m" 'describe-mode)
+
+(define-key help-map "\C-n" 'view-emacs-news)
+(define-key help-map "n" 'view-emacs-news)
+
+(define-key help-map "s" 'describe-syntax)
+
+(define-key help-map "t" 'help-with-tutorial)
+
+(define-key help-map "w" 'where-is)
+
+(define-key help-map "v" 'describe-variable)
+
+(defun help-with-tutorial ()
+ "Select the Emacs learn-by-doing tutorial."
+ (interactive)
+ (let ((file (expand-file-name "~/TUTORIAL")))
+ (delete-other-windows)
+ (if (get-file-buffer file)
+ (switch-to-buffer (get-file-buffer file))
+ (switch-to-buffer (create-file-buffer file))
+ (setq buffer-file-name file)
+ (setq default-directory (expand-file-name "~/"))
+ (setq auto-save-file-name nil)
+ (insert-file-contents (expand-file-name "TUTORIAL" exec-directory))
+ (goto-char (point-min))
+ (search-forward "\n<<")
+ (beginning-of-line)
+ (delete-region (point) (progn (end-of-line) (point)))
+ (newline (- (window-height (selected-window))
+ (count-lines (point-min) (point))
+ 6))
+ (goto-char (point-min))
+ (set-buffer-modified-p nil))))
+
+(defun describe-key-briefly (key)
+ "Print the name of the function KEY invokes. KEY is a string."
+ (interactive "kDescribe key briefly: ")
+ (let ((defn (key-binding key)))
+ (if (or (null defn) (integerp defn))
+ (message "%s is undefined" (key-description key))
+ (message "%s runs the command %s"
+ (key-description key)
+ (if (symbolp defn) defn (prin1-to-string defn))))))
+
+(defun print-help-return-message (&optional function)
+ "Display or return message saying how to restore windows after help command.
+Computes a message and applies the argument FUNCTION to it.
+If FUNCTION is nil, applies `message' to it, thus printing it."
+ (and (not (get-buffer-window standard-output))
+ (funcall (or function 'message)
+ (substitute-command-keys
+ (if (one-window-p t)
+ (if pop-up-windows
+ "Type \\[delete-other-windows] to remove help window."
+ "Type \\[switch-to-buffer] RET to remove help window.")
+ "Type \\[switch-to-buffer-other-window] RET to restore old contents of help window.")))))
+
+(defun describe-key (key)
+ "Display documentation of the function KEY invokes. KEY is a string."
+ (interactive "kDescribe key: ")
+ (let ((defn (key-binding key)))
+ (if (or (null defn) (integerp defn))
+ (message "%s is undefined" (key-description key))
+ (with-output-to-temp-buffer "*Help*"
+ (prin1 defn)
+ (princ ":\n")
+ (if (documentation defn)
+ (princ (documentation defn))
+ (princ "not documented"))
+ (print-help-return-message)))))
+
+(defun describe-mode ()
+ "Display documentation of current major mode."
+ (interactive)
+ (with-output-to-temp-buffer "*Help*"
+ (princ mode-name)
+ (princ " Mode:\n")
+ (princ (documentation major-mode))
+ (print-help-return-message)))
+
+(defun describe-distribution ()
+ "Display info on how to obtain the latest version of GNU Emacs."
+ (interactive)
+ (find-file-read-only
+ (expand-file-name "DISTRIB" exec-directory)))
+
+(defun describe-copying ()
+ "Display info on how you may redistribute copies of GNU Emacs."
+ (interactive)
+ (find-file-read-only
+ (expand-file-name "COPYING" exec-directory))
+ (goto-char (point-min)))
+
+(defun describe-no-warranty ()
+ "Display info on all the kinds of warranty Emacs does NOT have."
+ (interactive)
+ (describe-copying)
+ (let (case-fold-search)
+ (search-forward "NO WARRANTY")
+ (recenter 0)))
+
+(defun view-emacs-news ()
+ "Display info on recent changes to Emacs."
+ (interactive)
+ (find-file-read-only (expand-file-name "NEWS" exec-directory)))
+
+(defun view-lossage ()
+ "Display last 100 input keystrokes."
+ (interactive)
+ (with-output-to-temp-buffer "*Help*"
+ (princ (key-description (recent-keys)))
+ (save-excursion
+ (set-buffer standard-output)
+ (goto-char (point-min))
+ (while (progn (move-to-column 50) (not (eobp)))
+ (search-forward " " nil t)
+ (insert "\n")))
+ (print-help-return-message)))
+
+(defun help-for-help ()
+ "You have typed C-h, the help character. Type a Help option:
+
+A command-apropos. Give a substring, and see a list of commands
+ (functions interactively callable) that contain
+ that substring. See also the apropos command.
+B describe-bindings. Display table of all key bindings.
+C describe-key-briefly. Type a command key sequence;
+ it prints the function name that sequence runs.
+F describe-function. Type a function name and get documentation of it.
+I info. The info documentation reader.
+K describe-key. Type a command key sequence;
+ it displays the full documentation.
+L view-lossage. Shows last 100 characters you typed.
+M describe-mode. Print documentation of current major mode,
+ which describes the commands peculiar to it.
+N view-emacs-news. Shows emacs news file.
+S describe-syntax. Display contents of syntax table, plus explanations
+T help-with-tutorial. Select the Emacs learn-by-doing tutorial.
+V describe-variable. Type name of a variable;
+ it displays the variable's documentation and value.
+W where-is. Type command name; it prints which keystrokes
+ invoke that command.
+C-c print Emacs copying permission (General Public License).
+C-d print Emacs ordering information.
+C-n print news of recent Emacs changes.
+C-w print information on absence of warranty for GNU Emacs."
+ (interactive)
+ (message
+ "A B C F I K L M N S T V W C-c C-d C-n C-w. Type C-h again for more help: ")
+ (let ((char (read-char)))
+ (if (or (= char ?\C-h) (= char ??))
+ (save-window-excursion
+ (switch-to-buffer "*Help*")
+ (erase-buffer)
+ (insert (documentation 'help-for-help))
+ (goto-char (point-min))
+ (while (memq char '(?\C-h ?? ?\C-v ?\ ?\177 ?\M-v))
+ (if (memq char '(?\C-v ?\ ))
+ (scroll-up))
+ (if (memq char '(?\177 ?\M-v))
+ (scroll-down))
+ (message "A B C F I K L M N S T V W C-c C-d C-n C-w%s: "
+ (if (pos-visible-in-window-p (point-max))
+ "" " or Space to scroll"))
+ (let ((cursor-in-echo-area t))
+ (setq char (read-char))))))
+ (let ((defn (cdr (assq (downcase char) (cdr help-map)))))
+ (if defn (call-interactively defn) (ding)))))
+
+
+(defun function-called-at-point ()
+ (condition-case ()
+ (save-excursion
+ (save-restriction
+ (narrow-to-region (max (point-min) (- (point) 1000)) (point-max))
+ (backward-up-list 1)
+ (forward-char 1)
+ (let (obj)
+ (setq obj (read (current-buffer)))
+ (and (symbolp obj) (fboundp obj) obj))))
+ (error nil)))
+
+(defun describe-function (function)
+ "Display the full documentation of FUNCTION (a symbol)."
+ (interactive
+ (let ((fn (function-called-at-point))
+ (enable-recursive-minibuffers t)
+ val)
+ (setq val (completing-read (if fn
+ (format "Describe function (default %s): " fn)
+ "Describe function: ")
+ obarray 'fboundp t))
+ (list (if (equal val "")
+ fn (intern val)))))
+ (with-output-to-temp-buffer "*Help*"
+ (prin1 function)
+ (princ ":
+")
+ (if (documentation function)
+ (princ (documentation function))
+ (princ "not documented"))
+ (print-help-return-message)))
+
+(defun variable-at-point ()
+ (condition-case ()
+ (save-excursion
+ (forward-sexp -1)
+ (skip-chars-forward "'")
+ (let ((obj (read (current-buffer))))
+ (and (symbolp obj) (boundp obj) obj)))
+ (error nil)))
+
+(defun describe-variable (variable)
+ "Display the full documentation of VARIABLE (a symbol)."
+ (interactive
+ (let ((v (variable-at-point))
+ (enable-recursive-minibuffers t)
+ val)
+ (setq val (completing-read (if v
+ (format "Describe variable (default %s): " v)
+ "Describe variable: ")
+ obarray 'boundp t))
+ (list (if (equal val "")
+ v (intern val)))))
+ (with-output-to-temp-buffer "*Help*"
+ (prin1 variable)
+ (princ "'s value is ")
+ (if (not (boundp variable))
+ (princ "void.")
+ (prin1 (symbol-value variable)))
+ (terpri) (terpri)
+ (princ "Documentation:")
+ (terpri)
+ (let ((doc (documentation-property variable 'variable-documentation)))
+ (if doc
+ (princ (substitute-command-keys doc))
+ (princ "not documented as a variable.")))
+ (print-help-return-message)))
+
+(defun command-apropos (string)
+ "Like apropos but lists only symbols that are names of commands
+\(interactively callable functions)."
+ (interactive "sCommand apropos (regexp): ")
+ (let ((message
+ (let ((standard-output (get-buffer-create "*Help*")))
+ (print-help-return-message 'identity))))
+ (apropos string 'commandp)
+ (and message (message message))))
diff --git a/lisp/help.elc b/lisp/help.elc
new file mode 100644
index 00000000000..7969b2ecf8a
--- /dev/null
+++ b/lisp/help.elc
Binary files differ
diff --git a/lisp/emacs-lisp/helper.el b/lisp/helper.el
index 233196b5973..aa7253eab6c 100644
--- a/lisp/emacs-lisp/helper.el
+++ b/lisp/helper.el
@@ -87,13 +87,13 @@
(sit-for 4))
(defun Helper-describe-key-briefly (key)
- "Briefly describe binding of KEY."
+ "Briefly describe binding of KEYS."
(interactive "kDescribe key briefly: ")
(describe-key-briefly key)
(sit-for 4))
(defun Helper-describe-key (key)
- "Describe binding of KEY."
+ "Describe binding of KEYS."
(interactive "kDescribe key: ")
(save-window-excursion (describe-key key))
(Helper-help-scroller))
diff --git a/lisp/helper.elc b/lisp/helper.elc
new file mode 100644
index 00000000000..36bc188410a
--- /dev/null
+++ b/lisp/helper.elc
Binary files differ
diff --git a/lisp/hexl.el b/lisp/hexl.el
deleted file mode 100644
index 8671413e81a..00000000000
--- a/lisp/hexl.el
+++ /dev/null
@@ -1,659 +0,0 @@
-;; -*-Emacs-Lisp-*-
-;; hexl-mode -- Edit a file in a hex dump format.
-;; Copyright (C) 1989 Free Software Foundation, Inc.
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 1, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
-;;
-;; By: Keith Gabryelski (ag@wheaties.ai.mit.edu)
-;;
-;; This may be useful in your .emacs:
-;;
-;; (autoload 'hexl-find-file "hexl"
-;; "Edit file FILENAME in hexl-mode." t)
-;;
-;; (define-key global-map "\C-c\C-h" 'hexl-find-file)
-;;
-;; NOTE: Remember to change HEXL-PROGRAM or HEXL-OPTIONS if needed.
-;;
-;; Currently hexl only supports big endian hex output with 16 bit
-;; grouping.
-;;
-;; -iso in `hexl-options' will allow iso characters to display in the
-;; ASCII region of the screen (if your emacs supports this) instead of
-;; changing them to dots.
-
-;;
-;; vars here
-;;
-
-(defvar hexl-program "hexl"
- "The program that will hexlify and de-hexlify its stdin.
-`hexl-program' will always be concated with `hexl-options'
-and \"-de\" when dehexlfying a buffer.")
-
-(defvar hexl-iso ""
- "If your emacs can handle ISO characters, this should be set to
-\"-iso\" otherwise it should be \"\".")
-
-(defvar hexl-options (format "-hex %s" hexl-iso)
- "Options to hexl-program that suit your needs.")
-
-(defvar hexlify-command (format "%s %s" hexl-program hexl-options)
- "The command to use to hexlify a buffer. It is the concatination of
-`hexl-program' and `hexl-options'.")
-
-(defvar dehexlify-command (format "%s -de %s" hexl-program hexl-options)
- "The command to use to unhexlify a buffer. It is the concatination of
-`hexl-program', the option \"-de\", and `hexl-options'.")
-
-(defvar hexl-max-address 0
- "Maximum offset into hexl buffer.")
-
-(defvar hexl-mode-map nil)
-
-;; routines
-
-(defun hexl-mode (&optional arg)
- "\\<hexl-mode-map>
-A major mode for editting binary files in hex dump format.
-
-This function automatically converts a buffer into the hexl format
-using the function `hexlify-buffer'.
-
-Each line in the buffer has an \"address\" (displayed in hexadecimal)
-representing the offset into the file that the characters on this line
-are at and 16 characters from the file (displayed as hexadecimal
-values grouped every 16 bits) and as their ASCII values.
-
-If any of the characters (displayed as ASCII characters) are
-unprintable (control or meta characters) they will be replaced as
-periods.
-
-If `hexl-mode' is invoked with an argument the buffer is assumed to be
-in hexl format.
-
-A sample format:
-
- HEX ADDR: 0001 0203 0405 0607 0809 0a0b 0c0d 0e0f ASCII-TEXT
- -------- ---- ---- ---- ---- ---- ---- ---- ---- ----------------
- 00000000: 5468 6973 2069 7320 6865 786c 2d6d 6f64 This is hexl-mod
- 00000010: 652e 2020 4561 6368 206c 696e 6520 7265 e. Each line re
- 00000020: 7072 6573 656e 7473 2031 3620 6279 7465 presents 16 byte
- 00000030: 7320 6173 2068 6578 6164 6563 696d 616c s as hexadecimal
- 00000040: 2041 5343 4949 0a61 6e64 2070 7269 6e74 ASCII.and print
- 00000050: 6162 6c65 2041 5343 4949 2063 6861 7261 able ASCII chara
- 00000060: 6374 6572 732e 2020 416e 7920 636f 6e74 cters. Any cont
- 00000070: 726f 6c20 6f72 206e 6f6e 2d41 5343 4949 rol or non-ASCII
- 00000080: 2063 6861 7261 6374 6572 730a 6172 6520 characters.are
- 00000090: 6469 7370 6c61 7965 6420 6173 2070 6572 displayed as per
- 000000a0: 696f 6473 2069 6e20 7468 6520 7072 696e iods in the prin
- 000000b0: 7461 626c 6520 6368 6172 6163 7465 7220 table character
- 000000c0: 7265 6769 6f6e 2e0a region..
-
-Movement is as simple as movement in a normal emacs text buffer. Most
-cursor movement bindings are the same (ie. Use \\[hexl-backward-char], \\[hexl-forward-char], \\[hexl-next-line], and \\[hexl-previous-line]
-to move the cursor left, right, down, and up).
-
-Advanced cursor movement commands (ala \\[hexl-beginning-of-line], \\[hexl-end-of-line], \\[hexl-beginning-of-buffer], and \\[hexl-end-of-buffer]) are
-also supported.
-
-There are several ways to change text in hexl mode:
-
-ASCII characters (character between space (0x20) and tilde (0x7E)) are
-bound to self-insert so you can simply type the character and it will
-insert itself (actually overstrike) into the buffer.
-
-\\[hexl-quoted-insert] followed by another keystroke allows you to insert the key even if
-it isn't bound to self-insert. An octal number can be supplied in place
-of another key to insert the octal number's ASCII representation.
-
-\\[hexl-insert-hex-char] will insert a given hexadecimal value (if it is between 0 and 0xFF)
-into the buffer at the current point.
-
-\\[hexl-insert-octal-char] will insert a given octal value (if it is between 0 and 0377)
-into the buffer at the current point.
-
-\\[hexl-insert-decimal-char] will insert a given decimal value (if it is between 0 and 255)
-into the buffer at the current point.
-
-\\[hexl-save-buffer] will save the buffer in is binary format.
-
-\\[hexl-mode-exit] will exit hexl-mode.
-
-Note: \\[write-file] will write the file out in HEXL FORMAT.
-
-You can use \\[hexl-find-file] to visit a file in hexl-mode.
-
-\\[describe-bindings] for advanced commands."
- (interactive "p")
- (if (eq major-mode 'hexl-mode)
- (error "You are already in hexl mode.")
- (kill-all-local-variables)
- (make-local-variable 'hexl-mode-old-local-map)
- (setq hexl-mode-old-local-map (current-local-map))
- (use-local-map hexl-mode-map)
-
- (make-local-variable 'hexl-mode-old-mode-name)
- (setq hexl-mode-old-mode-name mode-name)
- (setq mode-name "Hexl")
-
- (make-local-variable 'hexl-mode-old-major-mode)
- (setq hexl-mode-old-major-mode major-mode)
- (setq major-mode 'hexl-mode)
-
- (let ((modified (buffer-modified-p))
- (read-only buffer-read-only)
- (original-point (1- (point))))
- (if (not (or (eq arg 1) (not arg)))
-;; if no argument then we guess at hexl-max-address
- (setq hexl-max-address (+ (* (/ (1- (buffer-size)) 68) 16) 15))
- (setq buffer-read-only nil)
- (setq hexl-max-address (1- (buffer-size)))
- (hexlify-buffer)
- (set-buffer-modified-p modified)
- (setq buffer-read-only read-only)
- (hexl-goto-address original-point)))))
-
-(defun hexl-save-buffer ()
- "Save a hexl format buffer as binary in visited file if modified."
- (interactive)
- (set-buffer-modified-p (if (buffer-modified-p)
- (save-excursion
- (let ((buf (generate-new-buffer " hexl"))
- (name (buffer-name))
- (file-name (buffer-file-name))
- (start (point-min))
- (end (point-max))
- modified)
- (set-buffer buf)
- (insert-buffer-substring name start end)
- (set-buffer name)
- (dehexlify-buffer)
- (save-buffer)
- (setq modified (buffer-modified-p))
- (delete-region (point-min) (point-max))
- (insert-buffer-substring buf start end)
- (kill-buffer buf)
- modified))
- (message "(No changes need to be saved)")
- nil)))
-
-(defun hexl-find-file (filename)
- "Edit file FILENAME in hexl-mode.
-Switch to a buffer visiting file FILENAME, creating one in none exists."
- (interactive "fFilename: ")
- (find-file filename)
- (if (not (eq major-mode 'hexl-mode))
- (hexl-mode)))
-
-(defun hexl-mode-exit (&optional arg)
- "Exit hexl-mode returning to previous mode.
-With arg, don't unhexlify buffer."
- (interactive "p")
- (if (or (eq arg 1) (not arg))
- (let ((modified (buffer-modified-p))
- (read-only buffer-read-only)
- (original-point (1+ (hexl-current-address))))
- (setq buffer-read-only nil)
- (dehexlify-buffer)
- (set-buffer-modified-p modified)
- (setq buffer-read-only read-only)
- (goto-char original-point)))
- (setq mode-name hexl-mode-old-mode-name)
- (use-local-map hexl-mode-old-local-map)
- (setq major-mode hexl-mode-old-major-mode)
-;; Kludge to update mode-line
- (switch-to-buffer (current-buffer))
-)
-
-(defun hexl-current-address ()
- "Return current hexl-address."
- (interactive)
- (let ((current-column (- (% (point) 68) 11))
- (hexl-address 0))
- (setq hexl-address (+ (* (/ (point) 68) 16)
- (/ (- current-column (/ current-column 5)) 2)))
- hexl-address))
-
-(defun hexl-address-to-marker (address)
- "Return marker for ADDRESS."
- (interactive "nAddress: ")
- (+ (* (/ address 16) 68) 11 (/ (* (% address 16) 5) 2)))
-
-(defun hexl-goto-address (address)
- "Goto hexl-mode (decimal) address ADDRESS.
-
-Signal error if ADDRESS out of range."
- (interactive "nAddress: ")
- (if (or (< address 0) (> address hexl-max-address))
- (error "Out of hexl region."))
- (goto-char (hexl-address-to-marker address)))
-
-(defun hexl-goto-hex-address (hex-address)
- "Go to hexl-mode address (hex string) HEX-ADDRESS.
-
-Signal error if HEX-ADDRESS is out of range."
- (interactive "sHex Address: ")
- (hexl-goto-address (hexl-hex-string-to-integer hex-address)))
-
-(defun hexl-hex-string-to-integer (hex-string)
- "Return decimal integer for HEX-STRING."
- (interactive "sHex number: ")
- (let ((hex-num 0))
- (while (not (equal hex-string ""))
- (setq hex-num (+ (* hex-num 16)
- (hexl-hex-char-to-integer (string-to-char hex-string))))
- (setq hex-string (substring hex-string 1)))
- hex-num))
-
-(defun hexl-octal-string-to-integer (octal-string)
- "Return decimal integer for OCTAL-STRING."
- (interactive "sOctal number: ")
- (let ((oct-num 0))
- (while (not (equal octal-string ""))
- (setq oct-num (+ (* oct-num 8)
- (hexl-oct-char-to-integer
- (string-to-char octal-string))))
- (setq octal-string (substring octal-string 1)))
- oct-num))
-
-;; move point functions
-
-(defun hexl-backward-char (arg)
- "Move to left ARG bytes (right if ARG negative) in hexl-mode."
- (interactive "p")
- (hexl-goto-address (- (hexl-current-address) arg)))
-
-(defun hexl-forward-char (arg)
- "Move right ARG bytes (left if ARG negative) in hexl-mode."
- (interactive "p")
- (hexl-goto-address (+ (hexl-current-address) arg)))
-
-(defun hexl-backward-short (arg)
- "Move to left ARG shorts (right if ARG negative) in hexl-mode."
- (interactive "p")
- (hexl-goto-address (let ((address (hexl-current-address)))
- (if (< arg 0)
- (progn
- (setq arg (- arg))
- (while (> arg 0)
- (if (not (equal address (logior address 3)))
- (if (> address hexl-max-address)
- (progn
- (message "End of buffer.")
- (setq address hexl-max-address))
- (setq address (logior address 3)))
- (if (> address hexl-max-address)
- (progn
- (message "End of buffer.")
- (setq address hexl-max-address))
- (setq address (+ address 4))))
- (setq arg (1- arg)))
- (if (> address hexl-max-address)
- (progn
- (message "End of buffer.")
- (setq address hexl-max-address))
- (setq address (logior address 3))))
- (while (> arg 0)
- (if (not (equal address (logand address -4)))
- (setq address (logand address -4))
- (if (not (equal address 0))
- (setq address (- address 4))
- (message "Beginning of buffer.")))
- (setq arg (1- arg))))
- address)))
-
-(defun hexl-forward-short (arg)
- "Move right ARG shorts (left if ARG negative) in hexl-mode."
- (interactive "p")
- (hexl-backward-short (- arg)))
-
-(defun hexl-backward-word (arg)
- "Move to left ARG words (right if ARG negative) in hexl-mode."
- (interactive "p")
- (hexl-goto-address (let ((address (hexl-current-address)))
- (if (< arg 0)
- (progn
- (setq arg (- arg))
- (while (> arg 0)
- (if (not (equal address (logior address 7)))
- (if (> address hexl-max-address)
- (progn
- (message "End of buffer.")
- (setq address hexl-max-address))
- (setq address (logior address 7)))
- (if (> address hexl-max-address)
- (progn
- (message "End of buffer.")
- (setq address hexl-max-address))
- (setq address (+ address 8))))
- (setq arg (1- arg)))
- (if (> address hexl-max-address)
- (progn
- (message "End of buffer.")
- (setq address hexl-max-address))
- (setq address (logior address 7))))
- (while (> arg 0)
- (if (not (equal address (logand address -8)))
- (setq address (logand address -8))
- (if (not (equal address 0))
- (setq address (- address 8))
- (message "Beginning of buffer.")))
- (setq arg (1- arg))))
- address)))
-
-(defun hexl-forward-word (arg)
- "Move right ARG words (left if ARG negative) in hexl-mode."
- (interactive "p")
- (hexl-backward-word (- arg)))
-
-(defun hexl-previous-line (arg)
- "Move vertically up ARG lines [16 bytes] (down if ARG negative) in hexl-mode.
-If there is byte at the target address move to the last byte in that line."
- (interactive "p")
- (hexl-next-line (- arg)))
-
-(defun hexl-next-line (arg)
- "Move vertically down ARG lines [16 bytes] (up if ARG negative) in hexl-mode.
-If there is no byte at the target address move to the last byte in that line."
- (interactive "p")
- (hexl-goto-address (let ((address (+ (hexl-current-address) (* arg 16)) t))
- (if (and (< arg 0) (< address 0))
- (progn (message "Out of hexl region.")
- (setq address
- (% (hexl-current-address) 16)))
- (if (and (> address hexl-max-address)
- (< (% hexl-max-address 16) (% address 16)))
- (setq address hexl-max-address)
- (if (> address hexl-max-address)
- (progn (message "Out of hexl region.")
- (setq
- address
- (+ (logand hexl-max-address -16)
- (% (hexl-current-address) 16)))))))
- address)))
-
-(defun hexl-beginning-of-buffer (arg)
- "Move to the beginning of the hexl buffer.
-Leaves `hexl-mark' at previous position.
-With prefix arg N, puts point N bytes of the way from the true beginning."
- (interactive "p")
- (push-mark (point))
- (hexl-goto-address (+ 0 (1- arg))))
-
-(defun hexl-end-of-buffer (arg)
- "Go to `hexl-max-address' minus ARG."
- (interactive "p")
- (push-mark (point))
- (hexl-goto-address (- hexl-max-address (1- arg))))
-
-(defun hexl-beginning-of-line ()
- "Goto beginning of line in hexl mode."
- (interactive)
- (goto-char (+ (* (/ (point) 68) 68) 11)))
-
-(defun hexl-end-of-line ()
- "Goto end of line in hexl mode."
- (interactive)
- (hexl-goto-address (let ((address (logior (hexl-current-address) 15)))
- (if (> address hexl-max-address)
- (setq address hexl-max-address))
- address)))
-
-(defun hexl-scroll-down (arg)
- "Scroll hexl buffer window upward ARG lines; or near full window if no ARG."
- (interactive "P")
- (if (null arg)
- (setq arg (1- (window-height)))
- (setq arg (prefix-numeric-value arg)))
- (hexl-scroll-up (- arg)))
-
-(defun hexl-scroll-up (arg)
- "Scroll hexl buffer window upward ARG lines; or near full window if no ARG."
- (interactive "P")
- (if (null arg)
- (setq arg (1- (window-height)))
- (setq arg (prefix-numeric-value arg)))
- (let ((movement (* arg 16))
- (address (hexl-current-address)))
- (if (or (> (+ address movement) hexl-max-address)
- (< (+ address movement) 0))
- (message "Out of hexl region.")
- (hexl-goto-address (+ address movement))
- (recenter 0))))
-
-(defun hexl-beginning-of-1k-page ()
- "Goto to beginning of 1k boundry."
- (interactive)
- (hexl-goto-address (logand (hexl-current-address) -1024)))
-
-(defun hexl-end-of-1k-page ()
- "Goto to end of 1k boundry."
- (interactive)
- (hexl-goto-address (let ((address (logior (hexl-current-address) 1023)))
- (if (> address hexl-max-address)
- (setq address hexl-max-address))
- address)))
-
-(defun hexl-beginning-of-512b-page ()
- "Goto to beginning of 512 byte boundry."
- (interactive)
- (hexl-goto-address (logand (hexl-current-address) -512)))
-
-(defun hexl-end-of-512b-page ()
- "Goto to end of 512 byte boundry."
- (interactive)
- (hexl-goto-address (let ((address (logior (hexl-current-address) 511)))
- (if (> address hexl-max-address)
- (setq address hexl-max-address))
- address)))
-
-(defun hexl-quoted-insert (arg)
- "Read next input character and insert it.
-Useful for inserting control characters.
-You may also type up to 3 octal digits, to insert a character with that code"
- (interactive "p")
- (hexl-insert-char (read-quoted-char) arg))
-
-;00000000: 0011 2233 4455 6677 8899 aabb ccdd eeff 0123456789ABCDEF
-
-(defun hexlify-buffer ()
- "Convert a binary buffer to hexl format"
- (interactive)
- (shell-command-on-region (point-min) (point-max) hexlify-command t))
-
-(defun dehexlify-buffer ()
- "Convert a hexl format buffer to binary."
- (interactive)
- (shell-command-on-region (point-min) (point-max) dehexlify-command t))
-
-(defun hexl-char-after-point ()
- "Return char for ASCII hex digits at point."
- (setq lh (char-after (point)))
- (setq rh (char-after (1+ (point))))
- (hexl-htoi lh rh))
-
-(defun hexl-htoi (lh rh)
- "Hex (char) LH (char) RH to integer."
- (+ (* (hexl-hex-char-to-integer lh) 16)
- (hexl-hex-char-to-integer rh)))
-
-(defun hexl-hex-char-to-integer (character)
- "Take a char and return its value as if it was a hex digit."
- (if (and (>= character ?0) (<= character ?9))
- (- character ?0)
- (let ((ch (logior character 32)))
- (if (and (>= ch ?a) (<= ch ?f))
- (- ch (- ?a 10))
- (error (format "Invalid hex digit `%c'." ch))))))
-
-(defun hexl-oct-char-to-integer (character)
- "Take a char and return its value as if it was a octal digit."
- (if (and (>= character ?0) (<= character ?7))
- (- character ?0)
- (error (format "Invalid octal digit `%c'." character))))
-
-(defun hexl-printable-character (ch)
- "Return a displayable string for character CH."
- (format "%c" (if hexl-iso
- (if (or (< ch 32) (and (>= ch 127) (< ch 160)))
- 46
- ch)
- (if (or (< ch 32) (>= ch 127))
- 46
- ch))))
-
-(defun hexl-self-insert-command (arg)
- "Insert this character."
- (interactive "p")
- (hexl-insert-char last-command-char arg))
-
-(defun hexl-insert-char (ch num)
- "Insert a character in a hexl buffer."
- (let ((address (hexl-current-address)))
- (while (> num 0)
- (delete-char 2)
- (insert (format "%02x" ch))
- (goto-char
- (+ (* (/ address 16) 68) 52 (% address 16)))
- (delete-char 1)
- (insert (hexl-printable-character ch))
- (if (eq address hexl-max-address)
- (hexl-goto-address address)
- (hexl-goto-address (1+ address)))
- (setq num (1- num)))))
-
-;; hex conversion
-
-(defun hexl-insert-hex-char (arg)
- "Insert a ASCII char ARG times at point for a given hexadecimal number."
- (interactive "p")
- (let ((num (hexl-hex-string-to-integer (read-string "Hex number: "))))
- (if (or (> num 255) (< num 0))
- (error "Hex number out of range.")
- (hexl-insert-char num arg))))
-
-(defun hexl-insert-decimal-char (arg)
- "Insert a ASCII char ARG times at point for a given decimal number."
- (interactive "p")
- (let ((num (string-to-int (read-string "Decimal Number: "))))
- (if (or (> num 255) (< num 0))
- (error "Decimal number out of range.")
- (hexl-insert-char num arg))))
-
-(defun hexl-insert-octal-char (arg)
- "Insert a ASCII char ARG times at point for a given octal number."
- (interactive "p")
- (let ((num (hexl-octal-string-to-integer (read-string "Octal Number: "))))
- (if (or (> num 255) (< num 0))
- (error "Decimal number out of range.")
- (hexl-insert-char num arg))))
-
-;; startup stuff.
-
-(if hexl-mode-map
- nil
- (setq hexl-mode-map (make-sparse-keymap))
-
- (define-key hexl-mode-map "\C-a" 'hexl-beginning-of-line)
- (define-key hexl-mode-map "\C-b" 'hexl-backward-char)
- (define-key hexl-mode-map "\C-d" 'undefined)
- (define-key hexl-mode-map "\C-e" 'hexl-end-of-line)
- (define-key hexl-mode-map "\C-f" 'hexl-forward-char)
-
- (if (not (eq (key-binding "\C-h") 'help-command))
- (define-key hexl-mode-map "\C-h" 'undefined))
-
- (define-key hexl-mode-map "\C-i" 'hexl-self-insert-command)
- (define-key hexl-mode-map "\C-j" 'hexl-self-insert-command)
- (define-key hexl-mode-map "\C-k" 'undefined)
- (define-key hexl-mode-map "\C-m" 'hexl-self-insert-command)
- (define-key hexl-mode-map "\C-n" 'hexl-next-line)
- (define-key hexl-mode-map "\C-o" 'undefined)
- (define-key hexl-mode-map "\C-p" 'hexl-previous-line)
- (define-key hexl-mode-map "\C-q" 'hexl-quoted-insert)
- (define-key hexl-mode-map "\C-t" 'undefined)
- (define-key hexl-mode-map "\C-v" 'hexl-scroll-up)
- (define-key hexl-mode-map "\C-w" 'undefined)
- (define-key hexl-mode-map "\C-y" 'undefined)
-
- (let ((ch 32))
- (while (< ch 127)
- (define-key hexl-mode-map (format "%c" ch) 'hexl-self-insert-command)
- (setq ch (1+ ch))))
-
- (define-key hexl-mode-map "\e\C-a" 'hexl-beginning-of-512b-page)
- (define-key hexl-mode-map "\e\C-b" 'hexl-backward-short)
- (define-key hexl-mode-map "\e\C-c" 'undefined)
- (define-key hexl-mode-map "\e\C-d" 'hexl-insert-decimal-char)
- (define-key hexl-mode-map "\e\C-e" 'hexl-end-of-512b-page)
- (define-key hexl-mode-map "\e\C-f" 'hexl-forward-short)
- (define-key hexl-mode-map "\e\C-g" 'undefined)
- (define-key hexl-mode-map "\e\C-h" 'undefined)
- (define-key hexl-mode-map "\e\C-i" 'undefined)
- (define-key hexl-mode-map "\e\C-j" 'undefined)
- (define-key hexl-mode-map "\e\C-k" 'undefined)
- (define-key hexl-mode-map "\e\C-l" 'undefined)
- (define-key hexl-mode-map "\e\C-m" 'undefined)
- (define-key hexl-mode-map "\e\C-n" 'undefined)
- (define-key hexl-mode-map "\e\C-o" 'hexl-insert-octal-char)
- (define-key hexl-mode-map "\e\C-p" 'undefined)
- (define-key hexl-mode-map "\e\C-q" 'undefined)
- (define-key hexl-mode-map "\e\C-r" 'undefined)
- (define-key hexl-mode-map "\e\C-s" 'undefined)
- (define-key hexl-mode-map "\e\C-t" 'undefined)
- (define-key hexl-mode-map "\e\C-u" 'undefined)
-
- (define-key hexl-mode-map "\e\C-w" 'undefined)
- (define-key hexl-mode-map "\e\C-x" 'hexl-insert-hex-char)
- (define-key hexl-mode-map "\e\C-y" 'undefined)
-
- (define-key hexl-mode-map "\ea" 'hexl-beginning-of-1k-page)
- (define-key hexl-mode-map "\eb" 'hexl-backward-word)
- (define-key hexl-mode-map "\ec" 'undefined)
- (define-key hexl-mode-map "\ed" 'undefined)
- (define-key hexl-mode-map "\ee" 'hexl-end-of-1k-page)
- (define-key hexl-mode-map "\ef" 'hexl-forward-word)
- (define-key hexl-mode-map "\eg" 'hexl-goto-hex-address)
- (define-key hexl-mode-map "\eh" 'undefined)
- (define-key hexl-mode-map "\ei" 'undefined)
- (define-key hexl-mode-map "\ej" 'hexl-goto-address)
- (define-key hexl-mode-map "\ek" 'undefined)
- (define-key hexl-mode-map "\el" 'undefined)
- (define-key hexl-mode-map "\em" 'undefined)
- (define-key hexl-mode-map "\en" 'undefined)
- (define-key hexl-mode-map "\eo" 'undefined)
- (define-key hexl-mode-map "\ep" 'undefined)
- (define-key hexl-mode-map "\eq" 'undefined)
- (define-key hexl-mode-map "\er" 'undefined)
- (define-key hexl-mode-map "\es" 'undefined)
- (define-key hexl-mode-map "\et" 'undefined)
- (define-key hexl-mode-map "\eu" 'undefined)
- (define-key hexl-mode-map "\ev" 'hexl-scroll-down)
- (define-key hexl-mode-map "\ey" 'undefined)
- (define-key hexl-mode-map "\ez" 'undefined)
- (define-key hexl-mode-map "\e<" 'hexl-beginning-of-buffer)
- (define-key hexl-mode-map "\e>" 'hexl-end-of-buffer)
-
- (define-key hexl-mode-map "\C-c\C-c" 'hexl-mode-exit)
-
- (define-key hexl-mode-map "\C-x\C-p" 'undefined)
- (define-key hexl-mode-map "\C-x\C-s" 'hexl-save-buffer)
- (define-key hexl-mode-map "\C-x\C-t" 'undefined))
-
-;; The End.
diff --git a/lisp/progmodes/hideif.el b/lisp/hideif.el
index 4a1b9897808..9c39980e9bd 100644
--- a/lisp/progmodes/hideif.el
+++ b/lisp/hideif.el
@@ -120,14 +120,14 @@
(defvar hide-ifdef-mode-map nil
- "Keymap used with Hide-Ifdef mode")
+ "Keymap used with hide-ifdef mode")
(defconst hide-ifdef-mode-prefix-key "\C-c"
- "Prefix key for all Hide-Ifdef mode commands.")
+ "Prefix key for all hide-ifdef-mode commands.")
(defvar hide-ifdef-mode-map-before nil
"Buffer-local variable to store a copy of the local keymap
-before `hide-ifdef-mode' modifies it.")
+ before hide-ifdef-mode modifies it.")
(defun define-hide-ifdef-mode-map ()
(if hide-ifdef-mode-map
@@ -151,7 +151,7 @@ before `hide-ifdef-mode' modifies it.")
(define-key hide-ifdef-mode-map "\C-p" 'previous-ifdef)
(define-key hide-ifdef-mode-map "\C-q" 'hide-ifdef-toggle-read-only)
(define-key hide-ifdef-mode-map
- (where-is-internal 'toggle-read-only nil nil t)
+ (where-is-internal 'toggle-read-only nil t)
'hide-ifdef-toggle-outside-read-only)
)
(fset 'hide-ifdef-mode-map hide-ifdef-mode-map) ; the function is the map
@@ -161,6 +161,7 @@ before `hide-ifdef-mode' modifies it.")
"Update mode-line by setting buffer-modified to itself."
(set-buffer-modified-p (buffer-modified-p)))
+
(defvar hide-ifdef-mode nil
"non-nil when hide-ifdef-mode is activated.")
@@ -177,35 +178,35 @@ before `hide-ifdef-mode' modifies it.")
(cons '(hide-ifdef-mode " Ifdef")
minor-mode-alist)))
+
(defun hide-ifdef-mode (arg)
- "Toggle Hide-Ifdef mode. This is a minor mode, albeit a large one.
-With ARG, turn Hide-Ifdef mode on iff arg is positive.
-In Hide-Ifdef mode, code within #ifdef constructs that the C preprocessor
+ "Toggle hide-ifdef-mode. Thus this is a minor mode, albeit a large one.
+With arg, turn hide-ifdef-mode on iff arg is positive.
+In hide-ifdef-mode, code within #ifdef constructs that the C preprocessor
would eliminate may be hidden from view. Several variables affect
how the hiding is done:
hide-ifdef-env
An association list of defined and undefined symbols for the
- current buffer. Initially, the global value of `hide-ifdef-env'
- is used.
+ current buffer. Initially, the global value of hide-ifdef-env is used.
hide-ifdef-define-alist
An association list of defined symbol lists.
- Use `hide-ifdef-set-define-alist' to save the current `hide-ifdef-env'
- and `hide-ifdef-use-define-alist' to set the current `hide-ifdef-env'
- from one of the lists in `hide-ifdef-define-alist'.
+ Use hide-ifdef-set-define-alist to save the current hide-ifdef-env
+ and hide-ifdef-use-define-alist to set the current hide-ifdef-env
+ from one of the lists in hide-ifdef-define-alist.
hide-ifdef-lines
Set to non-nil to not show #if, #ifdef, #ifndef, #else, and
#endif lines when hiding.
hide-ifdef-initially
- Indicates whether `hide-ifdefs' should be called when Hide-Ifdef mode
+ Indicates whether hide-ifdefs should be called when hide-ifdef-mode
is activated.
hide-ifdef-read-only
Set to non-nil if you want to make buffers read only while hiding.
- After `show-ifdefs', read-only status is restored to previous value.
+ After show-ifdefs, read-only status is restored to previous value.
\\{hide-ifdef-mode-map}"
@@ -235,7 +236,7 @@ hide-ifdef-read-only
(make-local-variable 'hif-outside-read-only)
(setq hif-outside-read-only buffer-read-only)
- (make-local-variable 'hide-ifdef-mode-map-before)
+ (make-local-variable 'ide-ifdef-mode-map-before)
(setq hide-ifdef-mode-map-before (current-local-map))
(use-local-map (copy-keymap (current-local-map)))
(local-unset-key hide-ifdef-mode-prefix-key)
@@ -410,13 +411,15 @@ that form should be displayed.")
(prog1
(hif-expr)
(if token ; is there still a token?
- (error "Error: unexpected token: %s" token))))
+ (error "Error: unexpected token: %s" token)))
+ )
(defun hif-nexttoken ()
"Pop the next token from token-list into the let variable \"token\"."
(setq token (car token-list))
(setq token-list (cdr token-list))
- token)
+ token
+ )
(defun hif-expr ()
"Parse and expression of the form
@@ -425,7 +428,8 @@ that form should be displayed.")
(while (eq token 'or)
(hif-nexttoken)
(setq result (list 'or result (hif-term))))
- result))
+ result
+ ))
(defun hif-term ()
"Parse a term of the form
@@ -434,7 +438,8 @@ that form should be displayed.")
(while (eq token 'and)
(hif-nexttoken)
(setq result (list 'and result (hif-factor))))
- result))
+ result
+ ))
(defun hif-factor ()
"Parse a factor of the form
@@ -455,7 +460,7 @@ that form should be displayed.")
((eq token 'hif-defined)
(hif-nexttoken)
(if (not (eq token 'lparen))
- (error "Error: expected \"(\" after \"defined\""))
+ (error "Error: expected \"(\" after \"define\""))
(hif-nexttoken)
(let ((ident token))
(if (memq token '(or and not hif-defined lparen rparen))
@@ -474,6 +479,7 @@ that form should be displayed.")
(hif-nexttoken)
(` (hif-lookup (quote (, ident))))
))
+
))
;;;----------- end of parser -----------------------
@@ -511,7 +517,8 @@ NOT including one on this line."
(end-of-line)
; avoid infinite recursion by only going to beginning of line if match found
(if (re-search-forward hif-ifx-else-endif-regexp (point-max) t)
- (beginning-of-line)))
+ (beginning-of-line))
+ )
(defun hif-find-previous-relevant ()
"Position at beginning of previous #ifdef, #ifndef, #else, #endif,
@@ -520,7 +527,9 @@ NOT including one on this line."
(beginning-of-line)
; avoid infinite recursion by only going to beginning of line if match found
(if (re-search-backward hif-ifx-else-endif-regexp (point-min) t)
- (beginning-of-line)))
+ (beginning-of-line)
+ )
+ )
(defun hif-looking-at-ifX () ;; Should eventually see #if
@@ -544,7 +553,8 @@ NOT including one on this line."
((hif-looking-at-endif)
'done)
(t
- (error "Missmatched #ifdef #endif pair"))))
+ (error "Missmatched #ifdef #endif pair"))
+ ))
(defun hif-endif-to-ifdef ()
@@ -561,12 +571,13 @@ NOT including one on this line."
(hif-endif-to-ifdef))
((hif-looking-at-ifX)
'done)
- (t ; never gets here)))
+ (t ; never gets here
+ )))
(defun forward-ifdef (&optional arg)
"Move point to beginning of line of the next ifdef-endif.
-With argument, do this that many times."
+ With argument, do this that many times."
(interactive "p")
(or arg (setq arg 1))
(if (< arg 0)
@@ -585,7 +596,7 @@ With argument, do this that many times."
(defun backward-ifdef (&optional arg)
"Move point to beginning of the previous ifdef-endif.
-With argument, do this that many times."
+ With argument, do this that many times."
(interactive "p")
(or arg (setq arg 1))
(if (< arg 0)
@@ -599,7 +610,9 @@ With argument, do this that many times."
(if (hif-looking-at-endif)
(hif-endif-to-ifdef)
(goto-char start)
- (error "No previous #ifdef")))))
+ (error "No previous #ifdef")
+ ))))
+
(defun down-ifdef ()
@@ -610,7 +623,8 @@ With argument, do this that many times."
(if (or (hif-looking-at-ifX) (hif-looking-at-else))
()
(goto-char start)
- (error "No following #ifdef"))))
+ (error "No following #ifdef")
+ )))
(defun up-ifdef ()
@@ -623,11 +637,12 @@ With argument, do this that many times."
(if (hif-looking-at-endif)
(hif-endif-to-ifdef))
(if (= start (point))
- (error "No previous #ifdef"))))
+ (error "No previous #ifdef")
+ )))
(defun next-ifdef (&optional arg)
"Move to the beginning of the next #ifX, #else, or #endif.
-With argument, do this that many times."
+ With argument, do this that many times."
(interactive "p")
(or arg (setq arg 1))
(if (< arg 0)
@@ -638,11 +653,12 @@ With argument, do this that many times."
(if (eolp)
(progn
(beginning-of-line)
- (error "No following #ifdefs, #elses, or #endifs")))))
+ (error "No following #ifdefs, #elses, or #endifs")
+ ))))
(defun previous-ifdef (&optional arg)
"Move to the beginning of the previous #ifX, #else, or #endif.
-With argument, do this that many times."
+ With argument, do this that many times."
(interactive "p")
(or arg (setq arg 1))
(if (< arg 0)
@@ -727,7 +743,8 @@ Point is left unchanged."
;;; one, we'd throw off all the counts. Feh.
(defun hif-hide-line (point)
- "Hide the line containing point. Does nothing if `hide-ifdef-lines' is nil."
+ "Hide the line containing point. Does nothing if
+hide-ifdef-lines is nil."
(if hide-ifdef-lines
(save-excursion
(goto-char point)
@@ -766,7 +783,8 @@ Point is left unchanged."
;;; possibly-hidden range.
(defun hif-recurse-on (start end)
- "Call `hide-ifdef-guts' after narrowing to end of START line and END line."
+ "Call hide-ifdef-guts after narrowing to end of START line and END
+line."
(save-excursion
(save-restriction
(goto-char start)
@@ -776,7 +794,7 @@ Point is left unchanged."
(defun hif-possibly-hide ()
"Called at #ifX expression, this hides those parts that should be
-hidden, according to judgement of `hide-ifdef-evaluator'."
+hidden, according to judgement of hide-ifdef-evaluator."
; (message "hif-possibly-hide") (sit-for 1)
(let ((test (hif-canonicalize))
(range (hif-find-range)))
@@ -811,7 +829,7 @@ hidden, according to judgement of `hide-ifdef-evaluator'."
(defun hide-ifdef-guts ()
- "Does the work of `hide-ifdefs', except for the work that's pointless
+ "Does the work of hide-ifdefs, except for the work that's pointless
to redo on a recursive entry."
; (message "hide-ifdef-guts")
(save-excursion
@@ -825,8 +843,8 @@ to redo on a recursive entry."
;===%%SF%% exports (Start) ===
(defvar hide-ifdef-initially nil
- "*Non-nil if `hide-ifdefs' should be called when Hide-Ifdef mode
-is first activated.")
+ "*Non-nil if hide-ifdefs should be called when hide-ifdef-mode
+ is first activated.")
(defvar hide-ifdef-hiding nil
"Non-nil if text might be hidden.")
@@ -835,7 +853,7 @@ is first activated.")
"*Set to non-nil if you want buffer to be read-only while hiding text.")
(defvar hif-outside-read-only nil
- "Internal variable. Saves the value of `buffer-read-only' while hiding.")
+ "Internal variable. Saves the value of buffer-read-only while hiding.")
(defvar hide-ifdef-lines nil
"*Set to t if you don't want to see the #ifX, #else, and #endif lines.")
@@ -848,10 +866,11 @@ is first activated.")
(if hide-ifdef-read-only "ON" "OFF"))
(if hide-ifdef-hiding
(setq buffer-read-only (or hide-ifdef-read-only hif-outside-read-only)))
- (hif-update-mode-line))
+ (hif-update-mode-line)
+ )
(defun hide-ifdef-toggle-outside-read-only ()
- "Replacement for `toggle-read-only' within Hide-Ifdef mode."
+ "Replacement for toggle-read-only within hide-ifdef-mode."
(interactive)
(setq hif-outside-read-only (not hif-outside-read-only))
(message "Read only %s"
@@ -860,7 +879,8 @@ is first activated.")
(or (and hide-ifdef-hiding hide-ifdef-read-only)
hif-outside-read-only)
)
- (hif-update-mode-line))
+ (hif-update-mode-line)
+ )
(defun hide-ifdef-define (var)
@@ -878,7 +898,7 @@ is first activated.")
(defun hide-ifdefs ()
"Hide the contents of some #ifdefs. Assume that defined symbols have
-been added to `hide-ifdef-env'. The text hidden is the text that would not
+been added to hide-ifdef-env. The text hidden is the text that would not
be included by the C preprocessor if it were given the file with those
symbols defined.
@@ -895,8 +915,10 @@ Turn off hiding by calling show-ifdef."
(setq hide-ifdef-hiding t)
(hide-ifdef-guts)
(if (or hide-ifdef-read-only hif-outside-read-only)
- (toggle-read-only)) ; make it read only
- (message "Hiding done"))
+ (toggle-read-only) ; make it read only
+ )
+ (message "Hiding done")
+ )
(defun show-ifdefs ()
@@ -907,7 +929,8 @@ Turn off hiding by calling show-ifdef."
(hif-show-all)
(if hif-outside-read-only
(toggle-read-only)) ; make it read only
- (setq hide-ifdef-hiding nil))
+ (setq hide-ifdef-hiding nil)
+ )
(defun hif-find-ifdef-block ()
@@ -919,15 +942,18 @@ Turn off hiding by calling show-ifdef."
(up-ifdef))
(setq top (point))
(hif-ifdef-to-endif)
- (setq max-bottom (1- (point))))
+ (setq max-bottom (1- (point)))
+ )
(save-excursion
(beginning-of-line)
(if (not (hif-looking-at-endif))
(hif-find-next-relevant))
(while (hif-looking-at-ifX)
(hif-ifdef-to-endif)
- (hif-find-next-relevant))
- (setq bottom (min max-bottom (1- (point))))))
+ (hif-find-next-relevant)
+ )
+ (setq bottom (min max-bottom (1- (point))))
+ ))
)
@@ -945,9 +971,11 @@ Turn off hiding by calling show-ifdef."
(progn
(hif-hide-line top)
(hif-hide-line (1+ bottom))))
- (setq hide-ifdef-hiding t))
+ (setq hide-ifdef-hiding t)
+ )
(if (or hide-ifdef-read-only hif-outside-read-only)
- (toggle-read-only)))
+ (toggle-read-only))
+ )
(defun show-ifdef-block ()
@@ -966,7 +994,9 @@ Turn off hiding by calling show-ifdef."
)
; restore read only status since we dont know if all is shown.
- (if old-read-only (toggle-read-only))))
+ (if old-read-only (toggle-read-only))
+ ))
+
;;; defininition alist support
@@ -984,14 +1014,16 @@ Turn off hiding by calling show-ifdef."
(if (car defs)
(setq new-defs (cons (car defs) new-defs)))
(setq defs (cdr defs)))
- new-defs))
+ new-defs
+ ))
(defun hide-ifdef-set-define-alist (name)
"Set the association for NAME to hide-ifdef-env."
(interactive "SSet define list: ")
(setq hide-ifdef-define-alist
(cons (cons name (hif-compress-define-list hide-ifdef-env))
- hide-ifdef-define-alist)))
+ hide-ifdef-define-alist))
+ )
(defun hide-ifdef-use-define-alist (name)
"Set hide-ifdef-env to the define list specified by NAME."
@@ -1002,6 +1034,8 @@ Turn off hiding by calling show-ifdef."
(mapcar '(lambda (arg) (cons arg t))
(cdr define-list)))
(error "No define list for %s" name))
- (if hide-ifdef-hiding (hide-ifdefs))))
+ (if hide-ifdef-hiding (hide-ifdefs))
+ )
+ )
;===%%SF%% exports (End) ===
diff --git a/lisp/hideif.elc b/lisp/hideif.elc
new file mode 100644
index 00000000000..247a6bffed2
--- /dev/null
+++ b/lisp/hideif.elc
Binary files differ
diff --git a/lisp/progmodes/icon.el b/lisp/icon.el
index c381f812105..718f89d5f91 100644
--- a/lisp/progmodes/icon.el
+++ b/lisp/icon.el
@@ -4,8 +4,8 @@
;; if not permanently installed in your emacs
;; Icon code editing commands for Emacs
-;; Derived from c-mode.el 15-Feb-89 Chris Smith convex!csmith
-;; Copyright (C) 1989 Free Software Foundation, Inc.
+;; from c-mode.el 13-Apr-88 Chris Smith; bugs to convex!csmith
+;; Copyright (C) 1988 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -77,8 +77,8 @@
This is in addition to icon-continued-statement-offset.")
(defconst icon-auto-newline nil
- "*Non-nil means automatically newline before and after braces
-inserted in Icon code.")
+ "*Non-nil means automatically newline before and after braces,
+and after colons and semicolons, inserted in C code.")
(defconst icon-tab-always-indent t
"*Non-nil means TAB in Icon mode should always reindent the current line,
@@ -107,15 +107,15 @@ Variables controlling indentation style:
then-clause of an if or body of a while.
icon-continued-brace-offset
Extra indentation given to a brace that starts a substatement.
- This is in addition to `icon-continued-statement-offset'.
+ This is in addition to icon-continued-statement-offset.
icon-brace-offset
Extra indentation for line if it starts with an open brace.
icon-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.
-Turning on Icon mode calls the value of the variable `icon-mode-hook'
-with no args, if that value is non-nil."
+Turning on Icon mode calls the value of the variable icon-mode-hook with no args,
+if that value is non-nil."
(interactive)
(kill-all-local-variables)
(use-local-map icon-mode-map)
@@ -143,15 +143,16 @@ with no args, if that value is non-nil."
(setq comment-indent-hook 'icon-comment-indent)
(run-hooks 'icon-mode-hook))
-;; This is used by indent-for-comment to decide how much to
-;; indent a comment in Icon code based on its context.
+;; This is used by indent-for-comment
+;; to decide how much to indent a comment in Icon code
+;; based on its context.
(defun icon-comment-indent ()
(if (looking-at "^#")
- 0
+ 0 ;Existing comment at bol stays there.
(save-excursion
(skip-chars-backward " \t")
- (max (if (bolp) 0 (1+ (current-column)))
- comment-column))))
+ (max (1+ (current-column)) ;Else indent at comment column
+ comment-column)))) ; except leave at least one space.
(defun electric-icon-brace (arg)
"Insert character and correct line's indentation."
@@ -186,14 +187,14 @@ with no args, if that value is non-nil."
(defun icon-indent-command (&optional whole-exp)
(interactive "P")
"Indent current line as Icon code, or in some cases insert a tab character.
-If `icon-tab-always-indent' is non-nil (the default), always indent current
-line. Otherwise, indent the current line only if point is at the left margin
+If icon-tab-always-indent is non-nil (the default), always indent current line.
+Otherwise, indent the current line only if point is at the left margin
or in the line's indentation; otherwise insert a tab.
-A numeric argument, regardless of its value, means indent rigidly all the
-lines of the expression starting after point so that this line becomes
-properly indented. The relative indentation among the lines of the
-expression are preserved."
+A numeric argument, regardless of its value,
+means indent rigidly all the lines of the expression starting after point
+so that this line becomes properly indented.
+The relative indentation among the lines of the expression are preserved."
(if whole-exp
;; If arg, always indent this line as Icon
;; and shift remaining lines of expression the same amount.
@@ -286,18 +287,16 @@ Returns nil if line starts inside a string, t if in a comment."
(goto-char (1+ containing-sexp))
(current-column))
(t
+ ;; Statement level. Is it a continuation or a new statement?
+ ;; Find previous non-comment character.
(if toplevel
- ;; Outside any procedures.
(progn (icon-backward-to-noncomment (point-min))
(if (icon-is-continuation-line)
icon-continued-statement-offset 0))
- ;; Statement level.
(if (null containing-sexp)
(progn (beginning-of-icon-defun)
(setq containing-sexp (point))))
(goto-char indent-point)
- ;; Is it a continuation or a new statement?
- ;; Find previous non-comment character.
(icon-backward-to-noncomment containing-sexp)
;; Now we get the answer.
(if (icon-is-continuation-line)
@@ -333,40 +332,29 @@ Returns nil if line starts inside a string, t if in a comment."
;; indent it relative to line brace is on.
;; For open brace in column zero, don't let statement
;; start there too. If icon-indent-level is zero,
- ;; use icon-brace-offset + icon-continued-statement-offset
- ;; instead.
+ ;; use icon-brace-offset + icon-continued-statement-offset instead.
;; For open-braces not the first thing in a line,
;; add in icon-brace-imaginary-offset.
(+ (if (and (bolp) (zerop icon-indent-level))
- (+ icon-brace-offset
- icon-continued-statement-offset)
+ (+ icon-brace-offset icon-continued-statement-offset)
icon-indent-level)
;; Move back over whitespace before the openbrace.
;; If openbrace is not first nonwhite thing on the line,
;; add the icon-brace-imaginary-offset.
(progn (skip-chars-backward " \t")
(if (bolp) 0 icon-brace-imaginary-offset))
- ;; Get initial indentation of the line we are on.
+ ;; here we are
(current-indentation))))))))))
-;; List of words to check for as the last thing on a line.
-;; If cdr is t, next line is a continuation of the same statement,
-;; if cdr is nil, next line starts a new (possibly indented) statement.
-
-(defconst icon-resword-alist
- '(("by" . t) ("case" . t) ("create") ("do") ("dynamic" . t) ("else")
- ("every" . t) ("if" . t) ("global" . t) ("initial" . t)
- ("link" . t) ("local" . t) ("of") ("record" . t) ("repeat" . t)
- ("static" . t) ("then") ("to" . t) ("until" . t) ("while" . t)))
-
(defun icon-is-continuation-line ()
(let* ((ch (preceding-char))
(ch-syntax (char-syntax ch)))
(if (eq ch-syntax ?w)
(assoc (buffer-substring
- (progn (forward-word -1) (point))
- (progn (forward-word 1) (point)))
- icon-resword-alist)
+ (progn (forward-word -1) (point))
+ (progn (forward-word 1) (point)))
+ '(("do") ("dynamic") ("else") ("initial") ("link")
+ ("local") ("of") ("static") ("then")))
(not (memq ch '(0 ?\; ?\} ?\{ ?\) ?\] ?\" ?\' ?\n))))))
(defun icon-backward-to-noncomment (lim)
@@ -375,25 +363,20 @@ Returns nil if line starts inside a string, t if in a comment."
(skip-chars-backward " \t\n\f" lim)
(setq opoint (point))
(beginning-of-line)
- (if (and (nth 5 (parse-partial-sexp (point) opoint))
+ (if (and (search-forward "#" opoint 'move)
(< lim (point)))
- (search-backward "#")
+ (forward-char -1)
(setq stop t)))))
(defun icon-backward-to-start-of-continued-exp (lim)
(if (memq (preceding-char) '(?\) ?\]))
(forward-sexp -1))
+ (while (icon-is-continued-line)
+ (end-of-line 0))
(beginning-of-line)
- (skip-chars-forward " \t")
- (cond
- ((<= (point) lim) (goto-char (1+ lim)))
- ((not (icon-is-continued-line)) 0)
- ((and (eq (char-syntax (following-char)) ?w)
- (cdr
- (assoc (buffer-substring (point)
- (save-excursion (forward-word 1) (point)))
- icon-resword-alist))) 0)
- (t (end-of-line 0) (icon-backward-to-start-of-continued-exp lim))))
+ (if (<= (point) lim)
+ (goto-char (1+ lim)))
+ (skip-chars-forward " \t"))
(defun icon-is-continued-line ()
(save-excursion
@@ -401,7 +384,7 @@ Returns nil if line starts inside a string, t if in a comment."
(icon-is-continuation-line)))
(defun icon-backward-to-start-of-if (&optional limit)
- "Move to the start of the last \"unbalanced\" if."
+ "Move to the start of the last ``unbalanced'' if."
(or limit (setq limit (save-excursion (beginning-of-icon-defun) (point))))
(let ((if-level 1)
(case-fold-search nil))
@@ -546,4 +529,3 @@ Returns nil if line starts inside a string, t if in a comment."
(or (looking-at comment-start-skip)
(if (re-search-forward comment-start-skip (save-excursion (end-of-line) (point)) t)
(progn (indent-for-comment) (beginning-of-line))))))))))
-
diff --git a/lisp/icon.elc b/lisp/icon.elc
new file mode 100644
index 00000000000..cdcea84e8ad
--- /dev/null
+++ b/lisp/icon.elc
Binary files differ
diff --git a/lisp/inc-vers.el b/lisp/inc-vers.el
index 13a4fb17e80..bd23aa8a728 100644
--- a/lisp/inc-vers.el
+++ b/lisp/inc-vers.el
@@ -18,7 +18,18 @@
;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-(insert-file-contents "../lisp/version.el")
+;; Find the file version.el in the path for lisp files,
+;; and set version-file.
+(setq version-file nil)
+(setq temp (mapcar '(lambda (dir)
+ (cons dir (file-exists-p (expand-file-name "version.el" dir))))
+ load-path))
+(while temp
+ (and (cdr (car temp)) (null version-file)
+ (setq version-file (expand-file-name "version.el" (car (car temp)))))
+ (setq temp (cdr temp)))
+
+(insert-file-contents version-file)
(re-search-forward "emacs-version \"[^\"]*[0-9]+\"")
(forward-char -1)
@@ -36,7 +47,7 @@
(progn (skip-chars-forward "^\"") (point))))
-(write-region (point-min) (point-max) "../lisp/version.el" nil 'nomsg)
+(write-region (point-min) (point-max) version-file nil 'nomsg)
(erase-buffer)
(set-buffer-modified-p nil)
diff --git a/lisp/indent.el b/lisp/indent.el
new file mode 100644
index 00000000000..903b8f70da7
--- /dev/null
+++ b/lisp/indent.el
@@ -0,0 +1,225 @@
+;; Indentation commands for Emacs
+;; Copyright (C) 1985 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 1, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+;Now in loaddefs.el
+;(defvar indent-line-function
+; 'indent-to-left-margin
+; "Function to indent current line.")
+
+(defun indent-according-to-mode ()
+ "Indent line in proper way for current major mode."
+ (interactive)
+ (funcall indent-line-function))
+
+(defun indent-for-tab-command ()
+ "Indent line in proper way for current major mode."
+ (interactive)
+ (if (eq indent-line-function 'indent-to-left-margin)
+ (insert-tab)
+ (funcall indent-line-function)))
+
+(defun insert-tab ()
+ (if abbrev-mode
+ (expand-abbrev))
+ (if indent-tabs-mode
+ (insert ?\t)
+ (indent-to (* tab-width (1+ (/ (current-column) tab-width))))))
+
+(defun indent-rigidly (start end arg)
+ "Indent all lines starting in the region sideways by ARG columns.
+Called from a program, takes three arguments, START, END and ARG."
+ (interactive "r\np")
+ (save-excursion
+ (goto-char end)
+ (setq end (point-marker))
+ (goto-char start)
+ (or (bolp) (forward-line 1))
+ (while (< (point) end)
+ (let ((indent (current-indentation)))
+ (delete-region (point) (progn (skip-chars-forward " \t") (point)))
+ (or (eolp)
+ (indent-to (max 0 (+ indent arg)) 0)))
+ (forward-line 1))
+ (move-marker end nil)))
+
+;; This is the default indent-line-function,
+;; used in Fundamental Mode, Text Mode, etc.
+(defun indent-to-left-margin ()
+ (or (= (current-indentation) left-margin)
+ (let (epos)
+ (save-excursion
+ (beginning-of-line)
+ (delete-region (point)
+ (progn (skip-chars-forward " \t")
+ (point)))
+ (indent-to left-margin)
+ (setq epos (point)))
+ (if (< (point) epos)
+ (goto-char epos)))))
+
+(defvar indent-region-function nil
+ "Function which is short cut to indent each line in region with Tab.
+nil means really call Tab on each line.")
+
+(defun indent-region (start end arg)
+ "Indent each nonblank line in the region.
+With no argument, indent each line with Tab.
+With argument COLUMN, indent each line to that column.
+Called from a program, takes three args: START, END and COLUMN."
+ (interactive "r\nP")
+ (if (null arg)
+ (if indent-region-function
+ (funcall indent-region-function start end)
+ (save-excursion
+ (goto-char end)
+ (setq end (point-marker))
+ (goto-char start)
+ (or (bolp) (forward-line 1))
+ (while (< (point) end)
+ (funcall indent-line-function)
+ (forward-line 1))
+ (move-marker end nil)))
+ (setq arg (prefix-numeric-value arg))
+ (save-excursion
+ (goto-char end)
+ (setq end (point-marker))
+ (goto-char start)
+ (or (bolp) (forward-line 1))
+ (while (< (point) end)
+ (delete-region (point) (progn (skip-chars-forward " \t") (point)))
+ (or (eolp)
+ (indent-to arg 0))
+ (forward-line 1))
+ (move-marker end nil))))
+
+(defun indent-relative-maybe ()
+ "Indent a new line like previous nonblank line."
+ (interactive)
+ (indent-relative t))
+
+(defun indent-relative (&optional unindented-ok)
+ "Space out to under next indent point in previous nonblank line.
+An indent point is a non-whitespace character following whitespace.
+If the previous nonblank line has no indent points beyond
+the column point starts at, tab-to-tab-stop is done instead."
+ (interactive "P")
+ (if abbrev-mode (expand-abbrev))
+ (let ((start-column (current-column))
+ indent)
+ (save-excursion
+ (beginning-of-line)
+ (if (re-search-backward "^[^\n]" nil t)
+ (let ((end (save-excursion (forward-line 1) (point))))
+ (move-to-column start-column)
+ ;; Is start-column inside a tab on this line?
+ (if (> (current-column) start-column)
+ (backward-char 1))
+ (or (looking-at "[ \t]")
+ unindented-ok
+ (skip-chars-forward "^ \t" end))
+ (skip-chars-forward " \t" end)
+ (or (= (point) end) (setq indent (current-column))))))
+ (if indent
+ (let ((opoint (point-marker)))
+ (delete-region (point) (progn (skip-chars-backward " \t") (point)))
+ (indent-to indent 0)
+ (if (> opoint (point))
+ (goto-char opoint))
+ (move-marker opoint nil))
+ (tab-to-tab-stop))))
+
+(defvar tab-stop-list
+ '(8 16 24 32 40 48 56 64 72 80 88 96 104 112 120)
+ "*List of tab stop positions used by tab-to-tab-stops.")
+
+(defvar edit-tab-stops-map nil "Keymap used in edit-tab-stops.")
+(if edit-tab-stops-map
+ nil
+ (setq edit-tab-stops-map (make-sparse-keymap))
+ (define-key edit-tab-stops-map "\C-x\C-s" 'edit-tab-stops-note-changes)
+ (define-key edit-tab-stops-map "\C-c\C-c" 'edit-tab-stops-note-changes))
+
+(defvar edit-tab-stops-buffer nil
+ "Buffer whose tab stops are being edited--in case
+the variable tab-stop-list is local in that buffer.")
+
+(defun edit-tab-stops ()
+ "Edit the tab stops used by tab-to-tab-stop.
+Creates a buffer *Tab Stops* containing text describing the tab stops.
+A colon indicates a column where there is a tab stop.
+You can add or remove colons and then do C-c C-c to make changes take effect."
+ (interactive)
+ (setq edit-tab-stops-buffer (current-buffer))
+ (switch-to-buffer (get-buffer-create "*Tab Stops*"))
+ (use-local-map edit-tab-stops-map)
+ (make-local-variable 'indent-tabs-mode)
+ (setq indent-tabs-mode nil)
+ (overwrite-mode 1)
+ (setq truncate-lines t)
+ (erase-buffer)
+ (let ((tabs tab-stop-list))
+ (while tabs
+ (indent-to (car tabs) 0)
+ (insert ?:)
+ (setq tabs (cdr tabs))))
+ (let ((count 0))
+ (insert ?\n)
+ (while (< count 8)
+ (insert (+ count ?0))
+ (insert " ")
+ (setq count (1+ count)))
+ (insert ?\n)
+ (while (> count 0)
+ (insert "0123456789")
+ (setq count (1- count))))
+ (insert "\nTo install changes, type C-c C-c")
+ (goto-char (point-min)))
+
+(defun edit-tab-stops-note-changes ()
+ "Put edited tab stops into effect."
+ (interactive)
+ (let (tabs)
+ (save-excursion
+ (goto-char 1)
+ (end-of-line)
+ (while (search-backward ":" nil t)
+ (setq tabs (cons (current-column) tabs))))
+ (bury-buffer (prog1 (current-buffer)
+ (switch-to-buffer edit-tab-stops-buffer)))
+ (setq tab-stop-list tabs))
+ (message "Tab stops installed"))
+
+(defun tab-to-tab-stop ()
+ "Insert spaces or tabs to next defined tab-stop column.
+The variable tab-stop-list is a list of columns at which there are tab stops.
+Use \\[edit-tab-stops] to edit them interactively."
+ (interactive)
+ (if abbrev-mode (expand-abbrev))
+ (let ((tabs tab-stop-list))
+ (while (and tabs (>= (current-column) (car tabs)))
+ (setq tabs (cdr tabs)))
+ (if tabs
+ (indent-to (car tabs))
+ (insert ? ))))
+
+(define-key global-map "\t" 'indent-for-tab-command)
+(define-key esc-map "\034" 'indent-region)
+(define-key ctl-x-map "\t" 'indent-rigidly)
+(define-key esc-map "i" 'tab-to-tab-stop)
diff --git a/lisp/indent.elc b/lisp/indent.elc
new file mode 100644
index 00000000000..5593bc2628d
--- /dev/null
+++ b/lisp/indent.elc
Binary files differ
diff --git a/lisp/info.el b/lisp/info.el
new file mode 100644
index 00000000000..45d2b45fe0b
--- /dev/null
+++ b/lisp/info.el
@@ -0,0 +1,708 @@
+;; Info package for Emacs -- could use a "create node" feature.
+;; Copyright (C) 1985, 1986 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 1, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+(provide 'info)
+
+(defvar Info-history nil
+ "List of info nodes user has visited.
+Each element of list is a list (FILENAME NODENAME BUFFERPOS).")
+
+(defvar Info-enable-edit nil
+ "Non-nil means the \\[Info-edit] command in Info can edit the current node.")
+
+(defvar Info-enable-active-nodes t
+ "Non-nil allows Info to execute Lisp code associated with nodes.
+The Lisp code is executed when the node is selected.")
+
+(defvar Info-directory nil
+ "Default directory for Info documentation files.")
+
+(defvar Info-current-file nil
+ "Info file that Info is now looking at, or nil.")
+
+(defvar Info-current-subfile nil
+ "Info subfile that is actually in the *info* buffer now,
+or nil if current info file is not split into subfiles.")
+
+(defvar Info-current-node nil
+ "Name of node that Info is now looking at, or nil.")
+
+(defvar Info-tag-table-marker (make-marker)
+ "Marker pointing at beginning of current Info file's tag table.
+Marker points nowhere if file has no tag table.")
+
+(defun info ()
+ "Enter Info, the documentation browser."
+ (interactive)
+ (if (get-buffer "*info*")
+ (switch-to-buffer "*info*")
+ (Info-directory)))
+
+;; Go to an info node specified as separate filename and nodename.
+;; no-going-back is non-nil if recovering from an error in this function;
+;; it says do not attempt further (recursive) error recovery.
+(defun Info-find-node (filename nodename &optional no-going-back)
+ ;; Convert filename to lower case if not found as specified.
+ ;; Expand it.
+ (if filename
+ (let (temp)
+ (setq filename (substitute-in-file-name filename))
+ (setq temp (expand-file-name filename
+ ;; Use Info's default dir
+ ;; unless the filename starts with `./'.
+ (if (not (string-match "^\\./" filename))
+ Info-directory)))
+ (if (file-exists-p temp)
+ (setq filename temp)
+ (if (file-exists-p (concat temp ".info"))
+ (setq filename (concat temp ".info"))
+ (setq temp (expand-file-name (downcase filename) Info-directory))
+ (if (file-exists-p temp)
+ (setq filename temp)
+ (if (file-exists-p (concat temp ".info"))
+ (setq filename (concat temp ".info"))
+ (error "Info file %s does not exist"
+ (expand-file-name filename Info-directory))))))))
+ ;; Record the node we are leaving.
+ (if (and Info-current-file (not no-going-back))
+ (setq Info-history
+ (cons (list Info-current-file Info-current-node (point))
+ Info-history)))
+ ;; Go into info buffer.
+ (switch-to-buffer "*info*")
+ (or (eq major-mode 'Info-mode)
+ (Info-mode))
+ (widen)
+ (setq Info-current-node nil)
+ (unwind-protect
+ (progn
+ ;; Switch files if necessary
+ (or (null filename)
+ (equal Info-current-file filename)
+ (let ((buffer-read-only nil))
+ (setq Info-current-file nil
+ Info-current-subfile nil)
+ (erase-buffer)
+ (insert-file-contents filename t)
+ (set-buffer-modified-p nil)
+ (setq default-directory (file-name-directory filename))
+ ;; See whether file has a tag table. Record the location if yes.
+ (set-marker Info-tag-table-marker nil)
+ (goto-char (point-max))
+ (forward-line -8)
+ (or (equal nodename "*")
+ (not (search-forward "\^_\nEnd tag table\n" nil t))
+ (let (pos)
+ ;; We have a tag table. Find its beginning.
+ ;; Is this an indirect file?
+ (search-backward "\nTag table:\n")
+ (setq pos (point))
+ (if (save-excursion
+ (forward-line 2)
+ (looking-at "(Indirect)\n"))
+ ;; It is indirect. Copy it to another buffer
+ ;; and record that the tag table is in that buffer.
+ (save-excursion
+ (let ((buf (current-buffer)))
+ (set-buffer (get-buffer-create " *info tag table*"))
+ (setq case-fold-search t)
+ (erase-buffer)
+ (insert-buffer-substring buf)
+ (set-marker Info-tag-table-marker
+ (match-end 0))))
+ (set-marker Info-tag-table-marker pos))))
+ (setq Info-current-file
+ (file-name-sans-versions buffer-file-name))))
+ (if (equal nodename "*")
+ (progn (setq Info-current-node nodename)
+ (Info-set-mode-line))
+ ;; Search file for a suitable node.
+ ;; First get advice from tag table if file has one.
+ ;; Also, if this is an indirect info file,
+ ;; read the proper subfile into this buffer.
+ (let ((guesspos (point-min))
+ (regexp (concat "Node: *" (regexp-quote nodename) " *[,\t\n\177]")))
+ (if (marker-position Info-tag-table-marker)
+ (save-excursion
+ (set-buffer (marker-buffer Info-tag-table-marker))
+ (goto-char Info-tag-table-marker)
+ (if (re-search-forward regexp nil t)
+ (progn
+ (setq guesspos (read (current-buffer)))
+ ;; If this is an indirect file,
+ ;; determine which file really holds this node
+ ;; and read it in.
+ (if (not (eq (current-buffer) (get-buffer "*info*")))
+ (setq guesspos
+ (Info-read-subfile guesspos))))
+ (error "No such node: \"%s\"" nodename))))
+ (goto-char (max (point-min) (- guesspos 1000)))
+ ;; Now search from our advised position (or from beg of buffer)
+ ;; to find the actual node.
+ (catch 'foo
+ (while (search-forward "\n\^_" nil t)
+ (forward-line 1)
+ (let ((beg (point)))
+ (forward-line 1)
+ (if (re-search-backward regexp beg t)
+ (throw 'foo t))))
+ (error "No such node: %s" nodename)))
+ (Info-select-node)))
+ ;; If we did not finish finding the specified node,
+ ;; go back to the previous one.
+ (or Info-current-node no-going-back
+ (let ((hist (car Info-history)))
+ (setq Info-history (cdr Info-history))
+ (Info-find-node (nth 0 hist) (nth 1 hist) t)
+ (goto-char (nth 2 hist)))))
+ (goto-char (point-min)))
+
+(defun Info-read-subfile (nodepos)
+ (set-buffer (marker-buffer Info-tag-table-marker))
+ (goto-char (point-min))
+ (search-forward "\n\^_")
+ (let (lastfilepos
+ lastfilename)
+ (forward-line 2)
+ (catch 'foo
+ (while (not (looking-at "\^_"))
+ (if (not (eolp))
+ (let ((beg (point))
+ thisfilepos thisfilename)
+ (search-forward ": ")
+ (setq thisfilename (buffer-substring beg (- (point) 2)))
+ (setq thisfilepos (read (current-buffer)))
+ (if (> thisfilepos nodepos)
+ (throw 'foo t))
+ (setq lastfilename thisfilename)
+ (setq lastfilepos thisfilepos))
+ (forward-line 1))))
+ (set-buffer (get-buffer "*info*"))
+ (or (equal Info-current-subfile lastfilename)
+ (let ((buffer-read-only nil))
+ (setq buffer-file-name nil)
+ (widen)
+ (erase-buffer)
+ (insert-file-contents lastfilename)
+ (set-buffer-modified-p nil)
+ (setq Info-current-subfile lastfilename)))
+ (goto-char (point-min))
+ (search-forward "\n\^_")
+ (+ (- nodepos lastfilepos) (point))))
+
+;; Select the info node that point is in.
+(defun Info-select-node ()
+ (save-excursion
+ ;; Find beginning of node.
+ (search-backward "\n\^_")
+ (forward-line 2)
+ ;; Get nodename spelled as it is in the node.
+ (re-search-forward "Node:[ \t]*")
+ (setq Info-current-node
+ (buffer-substring (point)
+ (progn
+ (skip-chars-forward "^,\t\n")
+ (point))))
+ (Info-set-mode-line)
+ ;; Find the end of it, and narrow.
+ (beginning-of-line)
+ (let (active-expression)
+ (narrow-to-region (point)
+ (if (re-search-forward "\n[\^_\f]" nil t)
+ (prog1
+ (1- (point))
+ (if (looking-at "[\n\^_\f]*execute: ")
+ (progn
+ (goto-char (match-end 0))
+ (setq active-expression
+ (read (current-buffer))))))
+ (point-max)))
+ (if Info-enable-active-nodes (eval active-expression)))))
+
+(defun Info-set-mode-line ()
+ (setq mode-line-buffer-identification
+ (concat
+ "Info: ("
+ (if Info-current-file
+ (file-name-nondirectory Info-current-file)
+ "")
+ ")"
+ (or Info-current-node ""))))
+
+;; Go to an info node specified with a filename-and-nodename string
+;; of the sort that is found in pointers in nodes.
+
+(defun Info-goto-node (nodename)
+ "Go to info node named NAME. Give just NODENAME or (FILENAME)NODENAME."
+ (interactive "sGoto node: ")
+ (let (filename)
+ (string-match "\\s *\\((\\s *\\([^\t)]*\\)\\s *)\\s *\\|\\)\\(.*\\)"
+ nodename)
+ (setq filename (if (= (match-beginning 1) (match-end 1))
+ ""
+ (substring nodename (match-beginning 2) (match-end 2)))
+ nodename (substring nodename (match-beginning 3) (match-end 3)))
+ (let ((trim (string-match "\\s *\\'" filename)))
+ (if trim (setq filename (substring filename 0 trim))))
+ (let ((trim (string-match "\\s *\\'" nodename)))
+ (if trim (setq nodename (substring nodename 0 trim))))
+ (Info-find-node (if (equal filename "") nil filename)
+ (if (equal nodename "") "Top" nodename))))
+
+(defvar Info-last-search nil
+ "Default regexp for Info S command to search for.")
+
+(defun Info-search (regexp)
+ "Search for REGEXP, starting from point, and select node it's found in."
+ (interactive "sSearch (regexp): ")
+ (if (equal regexp "")
+ (setq regexp Info-last-search)
+ (setq Info-last-search regexp))
+ (let ((found ()) current
+ (onode Info-current-node)
+ (ofile Info-current-file)
+ (opoint (point))
+ (osubfile Info-current-subfile))
+ (save-excursion
+ (save-restriction
+ (widen)
+ (if (null Info-current-subfile)
+ (progn (re-search-forward regexp) (setq found (point)))
+ (condition-case err
+ (progn (re-search-forward regexp) (setq found (point)))
+ (search-failed nil)))))
+ (if (not found) ;can only happen in subfile case -- else would have erred
+ (unwind-protect
+ (let ((list ()))
+ (set-buffer (marker-buffer Info-tag-table-marker))
+ (goto-char (point-min))
+ (search-forward "\n\^_\nIndirect:")
+ (save-restriction
+ (narrow-to-region (point)
+ (progn (search-forward "\n\^_")
+ (1- (point))))
+ (goto-char (point-min))
+ (search-forward (concat "\n" osubfile ": "))
+ (beginning-of-line)
+ (while (not (eobp))
+ (re-search-forward "\\(^.*\\): [0-9]+$")
+ (goto-char (+ (match-end 1) 2))
+ (setq list (cons (cons (read (current-buffer))
+ (buffer-substring (match-beginning 1)
+ (match-end 1)))
+ list))
+ (goto-char (1+ (match-end 0))))
+ (setq list (nreverse list)
+ current (car (car list))
+ list (cdr list)))
+ (while list
+ (message "Searching subfile %s..." (cdr (car list)))
+ (Info-read-subfile (car (car list)))
+ (setq list (cdr list))
+ (goto-char (point-min))
+ (if (re-search-forward regexp nil t)
+ (setq found (point) list ())))
+ (if found
+ (message "")
+ (signal 'search-failed (list regexp))))
+ (if (not found)
+ (progn (Info-read-subfile opoint)
+ (goto-char opoint)
+ (Info-select-node)))))
+ (widen)
+ (goto-char found)
+ (Info-select-node)
+ (or (and (equal onode Info-current-node)
+ (equal ofile Info-current-file))
+ (setq Info-history (cons (list ofile onode opoint)
+ Info-history)))))
+
+(defun Info-extract-pointer (name &optional errorname)
+ (save-excursion
+ (goto-char (point-min))
+ (forward-line 1)
+ (if (re-search-backward (concat name ":") nil t)
+ nil
+ (error (concat "Node has no " (capitalize (or errorname name)))))
+ (goto-char (match-end 0))
+ (Info-following-node-name)))
+
+(defun Info-following-node-name (&optional allowedchars)
+ (skip-chars-forward " \t")
+ (buffer-substring
+ (point)
+ (progn
+ (while (looking-at (concat "[" (or allowedchars "^,\t\n") "]"))
+ (skip-chars-forward (concat (or allowedchars "^,\t\n") "("))
+ (if (looking-at "(")
+ (skip-chars-forward "^)")))
+ (skip-chars-backward " ")
+ (point))))
+
+(defun Info-next ()
+ "Go to the next node of this node."
+ (interactive)
+ (Info-goto-node (Info-extract-pointer "next")))
+
+(defun Info-prev ()
+ "Go to the previous node of this node."
+ (interactive)
+ (Info-goto-node (Info-extract-pointer "prev[ious]*" "previous")))
+
+(defun Info-up ()
+ "Go to the superior node of this node."
+ (interactive)
+ (Info-goto-node (Info-extract-pointer "up")))
+
+(defun Info-last ()
+ "Go back to the last node visited."
+ (interactive)
+ (or Info-history
+ (error "This is the first Info node you looked at"))
+ (let (filename nodename opoint)
+ (setq filename (car (car Info-history)))
+ (setq nodename (car (cdr (car Info-history))))
+ (setq opoint (car (cdr (cdr (car Info-history)))))
+ (setq Info-history (cdr Info-history))
+ (Info-find-node filename nodename)
+ (setq Info-history (cdr Info-history))
+ (goto-char opoint)))
+
+(defun Info-directory ()
+ "Go to the Info directory node."
+ (interactive)
+ (Info-find-node "dir" "top"))
+
+(defun Info-follow-reference (footnotename)
+ "Follow cross reference named NAME to the node it refers to.
+NAME may be an abbreviation of the reference name."
+ (interactive
+ (let ((completion-ignore-case t)
+ completions str i)
+ (save-excursion
+ (goto-char (point-min))
+ (while (re-search-forward "\\*note[ \n\t]*\\([^:]*\\):" nil t)
+ (setq str (buffer-substring
+ (match-beginning 1)
+ (1- (point))))
+ (setq i 0)
+ (while (setq i (string-match "[ \n\t]+" str i))
+ (setq str (concat (substring str 0 i) " "
+ (substring str (match-end 0))))
+ (setq i (1+ i)))
+ (setq completions
+ (cons (cons str nil)
+ completions))))
+ (if completions
+ (list (completing-read "Follow reference named: " completions nil t))
+ (error "No cross-references in this node"))))
+ (let (target beg i (str (concat "\\*note " footnotename)))
+ (while (setq i (string-match " " str i))
+ (setq str (concat (substring str 0 i) "[ \t\n]+" (substring str (1+ i))))
+ (setq i (+ i 6)))
+ (save-excursion
+ (goto-char (point-min))
+ (or (re-search-forward str nil t)
+ (error "No cross-reference named %s" footnotename))
+ (goto-char (+ (match-beginning 0) 5))
+ (setq target
+ (Info-extract-menu-node-name "Bad format cross reference" t)))
+ (while (setq i (string-match "[ \t\n]+" target i))
+ (setq target (concat (substring target 0 i) " "
+ (substring target (match-end 0))))
+ (setq i (+ i 1)))
+ (Info-goto-node target)))
+
+(defun Info-extract-menu-node-name (&optional errmessage multi-line)
+ (skip-chars-forward " \t\n")
+ (let ((beg (point))
+ str i)
+ (skip-chars-forward "^:")
+ (forward-char 1)
+ (setq str
+ (if (looking-at ":")
+ (buffer-substring beg (1- (point)))
+ (skip-chars-forward " \t\n")
+ (Info-following-node-name (if multi-line "^.,\t" "^.,\t\n"))))
+ (while (setq i (string-match "\n" str i))
+ (aset str i ?\ ))
+ str))
+
+(defun Info-menu-item-sequence (list)
+ (while list
+ (Info-menu-item (car list))
+ (setq list (cdr list))))
+
+(defun Info-menu (menu-item)
+ "Go to node for menu item named (or abbreviated) NAME."
+ (interactive
+ (let ((completions '())
+ ;; If point is within a menu item, use that item as the default
+ (default nil)
+ (p (point))
+ (last nil))
+ (save-excursion
+ (goto-char (point-min))
+ (if (not (search-forward "\n* menu:" nil t))
+ (error "No menu in this node"))
+ (while (re-search-forward
+ "\n\\* \\([^:\t\n]*\\):" nil t)
+ (if (and (null default)
+ (prog1 (if last (< last p) nil)
+ (setq last (match-beginning 0)))
+ (<= p last))
+ (setq default (car (car completions))))
+ (setq completions (cons (cons (buffer-substring
+ (match-beginning 1)
+ (match-end 1))
+ (match-beginning 1))
+ completions)))
+ (if (and (null default) last
+ (< last p)
+ (<= p (progn (end-of-line) (point))))
+ (setq default (car (car completions)))))
+ (let ((item nil))
+ (while (null item)
+ (setq item (let ((completion-ignore-case t))
+ (completing-read (if default
+ (format "Menu item (default %s): "
+ default)
+ "Menu item: ")
+ completions nil t)))
+ ;; we rely on the bug (which RMS won't change for his own reasons)
+ ;; that ;; completing-read accepts an input of "" even when the
+ ;; require-match argument is true and "" is not a valid possibility
+ (if (string= item "")
+ (if default
+ (setq item default)
+ ;; ask again
+ (setq item nil))))
+ (list item))))
+ (Info-goto-node (Info-extract-menu-item menu-item)))
+
+(defun Info-extract-menu-item (menu-item)
+ (save-excursion
+ (goto-char (point-min))
+ (or (search-forward "\n* menu:" nil t)
+ (error "No menu in this node"))
+ (or (search-forward (concat "\n* " menu-item ":") nil t)
+ (search-forward (concat "\n* " menu-item) nil t)
+ (error "No such item in menu"))
+ (beginning-of-line)
+ (forward-char 2)
+ (Info-extract-menu-node-name)))
+
+(defun Info-extract-menu-counting (count)
+ (save-excursion
+ (goto-char (point-min))
+ (or (search-forward "\n* menu:" nil t)
+ (error "No menu in this node"))
+ (or (search-forward "\n* " nil t count)
+ (error "Too few items in menu"))
+ (Info-extract-menu-node-name)))
+
+(defun Info-first-menu-item ()
+ "Go to the node of the first menu item."
+ (interactive)
+ (Info-goto-node (Info-extract-menu-counting 1)))
+
+(defun Info-second-menu-item ()
+ "Go to the node of the second menu item."
+ (interactive)
+ (Info-goto-node (Info-extract-menu-counting 2)))
+
+(defun Info-third-menu-item ()
+ "Go to the node of the third menu item."
+ (interactive)
+ (Info-goto-node (Info-extract-menu-counting 3)))
+
+(defun Info-fourth-menu-item ()
+ "Go to the node of the fourth menu item."
+ (interactive)
+ (Info-goto-node (Info-extract-menu-counting 4)))
+
+(defun Info-fifth-menu-item ()
+ "Go to the node of the fifth menu item."
+ (interactive)
+ (Info-goto-node (Info-extract-menu-counting 5)))
+
+(defun Info-exit ()
+ "Exit Info by selecting some other buffer."
+ (interactive)
+ (switch-to-buffer (prog1 (other-buffer (current-buffer))
+ (bury-buffer (current-buffer)))))
+
+(defun Info-undefined ()
+ "Make command be undefined in Info."
+ (interactive)
+ (ding))
+
+(defun Info-help ()
+ "Enter the Info tutorial."
+ (interactive)
+ (Info-find-node "info"
+ (if (< (window-height) 23)
+ "Help-Small-Screen"
+ "Help")))
+
+(defun Info-summary ()
+ "Display a brief summary of all Info commands."
+ (interactive)
+ (save-window-excursion
+ (switch-to-buffer "*Help*")
+ (erase-buffer)
+ (insert (documentation 'Info-mode))
+ (goto-char (point-min))
+ (let (ch flag)
+ (while (progn (setq flag (not (pos-visible-in-window-p (point-max))))
+ (message (if flag "Type Space to see more"
+ "Type Space to return to Info"))
+ (if (/= ?\ (setq ch (read-char)))
+ (progn (setq unread-command-char ch) nil)
+ flag))
+ (scroll-up)))))
+
+(defvar Info-mode-map nil
+ "Keymap containing Info commands.")
+(if Info-mode-map
+ nil
+ (setq Info-mode-map (make-keymap))
+ (suppress-keymap Info-mode-map)
+ (define-key Info-mode-map "." 'beginning-of-buffer)
+ (define-key Info-mode-map " " 'scroll-up)
+ (define-key Info-mode-map "1" 'Info-first-menu-item)
+ (define-key Info-mode-map "2" 'Info-second-menu-item)
+ (define-key Info-mode-map "3" 'Info-third-menu-item)
+ (define-key Info-mode-map "4" 'Info-fourth-menu-item)
+ (define-key Info-mode-map "5" 'Info-fifth-menu-item)
+ (define-key Info-mode-map "6" 'undefined)
+ (define-key Info-mode-map "7" 'undefined)
+ (define-key Info-mode-map "8" 'undefined)
+ (define-key Info-mode-map "9" 'undefined)
+ (define-key Info-mode-map "0" 'undefined)
+ (define-key Info-mode-map "?" 'Info-summary)
+ (define-key Info-mode-map "b" 'beginning-of-buffer)
+ (define-key Info-mode-map "d" 'Info-directory)
+ (define-key Info-mode-map "e" 'Info-edit)
+ (define-key Info-mode-map "f" 'Info-follow-reference)
+ (define-key Info-mode-map "g" 'Info-goto-node)
+ (define-key Info-mode-map "h" 'Info-help)
+ (define-key Info-mode-map "l" 'Info-last)
+ (define-key Info-mode-map "m" 'Info-menu)
+ (define-key Info-mode-map "n" 'Info-next)
+ (define-key Info-mode-map "p" 'Info-prev)
+ (define-key Info-mode-map "q" 'Info-exit)
+ (define-key Info-mode-map "s" 'Info-search)
+ (define-key Info-mode-map "u" 'Info-up)
+ (define-key Info-mode-map "\177" 'scroll-down))
+
+(put 'Info-mode 'mode-class 'special)
+(defun Info-mode ()
+ "Info mode provides commands for browsing through the Info documentation tree.
+Documentation in Info is divided into \"nodes\", each of which
+discusses one topic and contains references to other nodes
+which discuss related topics. Info has commands to follow
+the references and show you other nodes.
+
+h Invoke the Info tutorial.
+
+Selecting other nodes:
+n Move to the \"next\" node of this node.
+p Move to the \"previous\" node of this node.
+u Move \"up\" from this node.
+m Pick menu item specified by name (or abbreviation).
+ Picking a menu item causes another node to be selected.
+f Follow a cross reference. Reads name of reference.
+l Move to the last node you were at.
+
+Moving within a node:
+Space scroll forward a page. DEL scroll backward.
+b Go to beginning of node.
+
+Advanced commands:
+q Quit Info: reselect previously selected buffer.
+e Edit contents of selected node.
+1 Pick first item in node's menu.
+2, 3, 4, 5 Pick second ... fifth item in node's menu.
+g Move to node specified by name.
+ You may include a filename as well, as (FILENAME)NODENAME.
+s Search through this Info file for specified regexp,
+ and select the node in which the next occurrence is found."
+ (kill-all-local-variables)
+ (setq major-mode 'Info-mode)
+ (setq mode-name "Info")
+ (use-local-map Info-mode-map)
+ (set-syntax-table text-mode-syntax-table)
+ (setq local-abbrev-table text-mode-abbrev-table)
+ (setq case-fold-search t)
+ (setq buffer-read-only t)
+ (make-local-variable 'Info-current-file)
+ (make-local-variable 'Info-current-subfile)
+ (make-local-variable 'Info-current-node)
+ (make-local-variable 'Info-tag-table-marker)
+ (make-local-variable 'Info-history)
+ (Info-set-mode-line))
+
+(defvar Info-edit-map nil
+ "Local keymap used within `e' command of Info.")
+(if Info-edit-map
+ nil
+ (setq Info-edit-map (copy-keymap text-mode-map))
+ (define-key Info-edit-map "\C-c\C-c" 'Info-cease-edit))
+
+(defun Info-edit-mode ()
+ "Major mode for editing the contents of an Info node.
+Like text mode with the addition of Info-cease-edit
+which returns to Info mode for browsing.
+\\{Info-edit-map}"
+ )
+
+(defun Info-edit ()
+ "Edit the contents of this Info node.
+Allowed only if variable Info-enable-edit is non-nil."
+ (interactive)
+ (or Info-enable-edit
+ (error "Editing info nodes is not enabled"))
+ (use-local-map Info-edit-map)
+ (setq major-mode 'Info-edit-mode)
+ (setq mode-name "Info Edit")
+ (kill-local-variable 'mode-line-buffer-identification)
+ (setq buffer-read-only nil)
+ ;; Make mode line update.
+ (set-buffer-modified-p (buffer-modified-p))
+ (message (substitute-command-keys
+ "Editing: Type \\[Info-cease-edit] to return to info")))
+
+(defun Info-cease-edit ()
+ "Finish editing Info node; switch back to Info proper."
+ (interactive)
+ ;; Do this first, so nothing has changed if user C-g's at query.
+ (and (buffer-modified-p)
+ (y-or-n-p "Save the file? ")
+ (save-buffer))
+ (use-local-map Info-mode-map)
+ (setq major-mode 'Info-mode)
+ (setq mode-name "Info")
+ (Info-set-mode-line)
+ (setq buffer-read-only t)
+ ;; Make mode line update.
+ (set-buffer-modified-p (buffer-modified-p))
+ (and (marker-position Info-tag-table-marker)
+ (buffer-modified-p)
+ (message "Tags may have changed. Use Info-tagify if necessary")))
diff --git a/lisp/info.elc b/lisp/info.elc
new file mode 100644
index 00000000000..86151dd1d43
--- /dev/null
+++ b/lisp/info.elc
Binary files differ
diff --git a/lisp/informat.el b/lisp/informat.el
new file mode 100644
index 00000000000..95d87441cbd
--- /dev/null
+++ b/lisp/informat.el
@@ -0,0 +1,411 @@
+;; Info support functions package for Emacs
+;; Copyright (C) 1986 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 1, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+(require 'info)
+
+(defun Info-tagify ()
+ "Create or update Info-file tag table in current buffer."
+ (interactive)
+ ;; Save and restore point and restrictions.
+ ;; save-restrictions would not work
+ ;; because it records the old max relative to the end.
+ ;; We record it relative to the beginning.
+ (let ((omin (point-min))
+ (omax (point-max))
+ (nomax (= (point-max) (1+ (buffer-size))))
+ (opoint (point)))
+ (unwind-protect
+ (progn
+ (widen)
+ (goto-char (point-min))
+ (if (search-forward "\^_\nIndirect:\n" nil t)
+ (message "Cannot tagify split info file")
+ (let ((regexp "Node:[ \t]*\\([^,\n\t]\\)*[,\t\n]")
+ (case-fold-search t)
+ list)
+ (while (search-forward "\n\^_" nil t)
+ (forward-line 1)
+ (let ((beg (point)))
+ (forward-line 1)
+ (if (re-search-backward regexp beg t)
+ (setq list
+ (cons (list (buffer-substring
+ (match-beginning 1)
+ (match-end 1))
+ beg)
+ list)))))
+ (goto-char (point-max))
+ (forward-line -8)
+ (let ((buffer-read-only nil))
+ (if (search-forward "\^_\nEnd tag table\n" nil t)
+ (let ((end (point)))
+ (search-backward "\nTag table:\n")
+ (beginning-of-line)
+ (delete-region (point) end)))
+ (goto-char (point-max))
+ (insert "\^_\f\nTag table:\n")
+ (move-marker Info-tag-table-marker (point))
+ (setq list (nreverse list))
+ (while list
+ (insert "Node: " (car (car list)) ?\177)
+ (princ (car (cdr (car list))) (current-buffer))
+ (insert ?\n)
+ (setq list (cdr list)))
+ (insert "\^_\nEnd tag table\n")))))
+ (goto-char opoint)
+ (narrow-to-region omin (if nomax (1+ (buffer-size))
+ (min omax (point-max)))))))
+
+(defun Info-split ()
+ "Split an info file into an indirect file plus bounded-size subfiles.
+Each subfile will be up to 50000 characters plus one node.
+
+To use this command, first visit a large Info file that has a tag table.
+The buffer is modified into a (small) indirect info file
+which should be saved in place of the original visited file.
+
+The subfiles are written in the same directory the original file is in,
+with names generated by appending `-' and a number to the original file name.
+
+The indirect file still functions as an Info file, but it contains
+just the tag table and a directory of subfiles."
+ (interactive)
+ (if (< (buffer-size) 70000)
+ (error "This is too small to be worth splitting"))
+ (goto-char (point-min))
+ (search-forward "\^_")
+ (forward-char -1)
+ (let ((start (point))
+ (chars-deleted 0)
+ subfiles
+ (subfile-number 1)
+ (case-fold-search t)
+ (filename (file-name-sans-versions buffer-file-name)))
+ (goto-char (point-max))
+ (forward-line -8)
+ (setq buffer-read-only nil)
+ (or (search-forward "\^_\nEnd tag table\n" nil t)
+ (error "Tag table required; use M-x Info-tagify"))
+ (search-backward "\nTag table:\n")
+ (if (looking-at "\nTag table:\n\^_")
+ (error "Tag table is just a skeleton; use M-x Info-tagify"))
+ (beginning-of-line)
+ (forward-char 1)
+ (save-restriction
+ (narrow-to-region (point-min) (point))
+ (goto-char (point-min))
+ (while (< (1+ (point)) (point-max))
+ (goto-char (min (+ (point) 50000) (point-max)))
+ (search-forward "\^_" nil 'move)
+ (setq subfiles
+ (cons (list (+ start chars-deleted)
+ (concat (file-name-nondirectory filename)
+ (format "-%d" subfile-number)))
+ subfiles))
+ ;; Put a newline at end of split file, to make Unix happier.
+ (insert "\n")
+ (write-region (point-min) (point)
+ (concat filename (format "-%d" subfile-number)))
+ (delete-region (1- (point)) (point))
+ ;; Back up over the final ^_.
+ (forward-char -1)
+ (setq chars-deleted (+ chars-deleted (- (point) start)))
+ (delete-region start (point))
+ (setq subfile-number (1+ subfile-number))))
+ (while subfiles
+ (goto-char start)
+ (insert (nth 1 (car subfiles))
+ (format ": %d" (car (car subfiles)))
+ "\n")
+ (setq subfiles (cdr subfiles)))
+ (goto-char start)
+ (insert "\^_\nIndirect:\n")
+ (search-forward "\nTag Table:\n")
+ (insert "(Indirect)\n")))
+
+(defun Info-validate ()
+ "Check current buffer for validity as an Info file.
+Check that every node pointer points to an existing node."
+ (interactive)
+ (save-excursion
+ (save-restriction
+ (widen)
+ (goto-char (point-min))
+ (if (search-forward "\nTag table:\n(Indirect)\n" nil t)
+ (error "Don't yet know how to validate indirect info files: \"%s\""
+ (buffer-name (current-buffer))))
+ (goto-char (point-min))
+ (let ((allnodes '(("*")))
+ (regexp "Node:[ \t]*\\([^,\n\t]*\\)[,\t\n]")
+ (case-fold-search t)
+ (tags-losing nil)
+ (lossages ()))
+ (while (search-forward "\n\^_" nil t)
+ (forward-line 1)
+ (let ((beg (point)))
+ (forward-line 1)
+ (if (re-search-backward regexp beg t)
+ (let ((name (downcase
+ (buffer-substring
+ (match-beginning 1)
+ (progn
+ (goto-char (match-end 1))
+ (skip-chars-backward " \t")
+ (point))))))
+ (if (assoc name allnodes)
+ (setq lossages
+ (cons (list name "Duplicate node-name" nil)
+ lossages))
+ (setq allnodes
+ (cons (list name
+ (progn
+ (end-of-line)
+ (and (re-search-backward
+ "prev[ious]*:" beg t)
+ (progn
+ (goto-char (match-end 0))
+ (downcase
+ (Info-following-node-name)))))
+ beg)
+ allnodes)))))))
+ (goto-char (point-min))
+ (while (search-forward "\n\^_" nil t)
+ (forward-line 1)
+ (let ((beg (point))
+ thisnode next)
+ (forward-line 1)
+ (if (re-search-backward regexp beg t)
+ (save-restriction
+ (search-forward "\n\^_" nil 'move)
+ (narrow-to-region beg (point))
+ (setq thisnode (downcase
+ (buffer-substring
+ (match-beginning 1)
+ (progn
+ (goto-char (match-end 1))
+ (skip-chars-backward " \t")
+ (point)))))
+ (end-of-line)
+ (and (search-backward "next:" nil t)
+ (setq next (Info-validate-node-name "invalid Next"))
+ (assoc next allnodes)
+ (if (equal (car (cdr (assoc next allnodes)))
+ thisnode)
+ ;; allow multiple `next' pointers to one node
+ (let ((tem lossages))
+ (while tem
+ (if (and (equal (car (cdr (car tem)))
+ "should have Previous")
+ (equal (car (car tem))
+ next))
+ (setq lossages (delq (car tem) lossages)))
+ (setq tem (cdr tem))))
+ (setq lossages
+ (cons (list next
+ "should have Previous"
+ thisnode)
+ lossages))))
+ (end-of-line)
+ (if (re-search-backward "prev[ious]*:" nil t)
+ (Info-validate-node-name "invalid Previous"))
+ (end-of-line)
+ (if (search-backward "up:" nil t)
+ (Info-validate-node-name "invalid Up"))
+ (if (re-search-forward "\n* Menu:" nil t)
+ (while (re-search-forward "\n\\* " nil t)
+ (Info-validate-node-name
+ (concat "invalid menu item "
+ (buffer-substring (point)
+ (save-excursion
+ (skip-chars-forward "^:")
+ (point))))
+ (Info-extract-menu-node-name))))
+ (goto-char (point-min))
+ (while (re-search-forward "\\*note[ \n]*[^:\t]*:" nil t)
+ (goto-char (+ (match-beginning 0) 5))
+ (skip-chars-forward " \n")
+ (Info-validate-node-name
+ (concat "invalid reference "
+ (buffer-substring (point)
+ (save-excursion
+ (skip-chars-forward "^:")
+ (point))))
+ (Info-extract-menu-node-name "Bad format cross-reference")))))))
+ (setq tags-losing (not (Info-validate-tags-table)))
+ (if (or lossages tags-losing)
+ (with-output-to-temp-buffer " *problems in info file*"
+ (while lossages
+ (princ "In node \"")
+ (princ (car (car lossages)))
+ (princ "\", ")
+ (let ((tem (nth 1 (car lossages))))
+ (cond ((string-match "\n" tem)
+ (princ (substring tem 0 (match-beginning 0)))
+ (princ "..."))
+ (t
+ (princ tem))))
+ (if (nth 2 (car lossages))
+ (progn
+ (princ ": ")
+ (let ((tem (nth 2 (car lossages))))
+ (cond ((string-match "\n" tem)
+ (princ (substring tem 0 (match-beginning 0)))
+ (princ "..."))
+ (t
+ (princ tem))))))
+ (terpri)
+ (setq lossages (cdr lossages)))
+ (if tags-losing (princ "\nTags table must be recomputed\n")))
+ ;; Here if info file is valid.
+ ;; If we already made a list of problems, clear it out.
+ (save-excursion
+ (if (get-buffer " *problems in info file*")
+ (progn
+ (set-buffer " *problems in info file*")
+ (kill-buffer (current-buffer)))))
+ (message "File appears valid"))))))
+
+(defun Info-validate-node-name (kind &optional name)
+ (if name
+ nil
+ (goto-char (match-end 0))
+ (skip-chars-forward " \t")
+ (if (= (following-char) ?\()
+ nil
+ (setq name
+ (buffer-substring
+ (point)
+ (progn
+ (skip-chars-forward "^,\t\n")
+ (skip-chars-backward " ")
+ (point))))))
+ (if (null name)
+ nil
+ (setq name (downcase name))
+ (or (and (> (length name) 0) (= (aref name 0) ?\())
+ (assoc name allnodes)
+ (setq lossages
+ (cons (list thisnode kind name) lossages))))
+ name)
+
+(defun Info-validate-tags-table ()
+ (goto-char (point-min))
+ (if (not (search-forward "\^_\nEnd tag table\n" nil t))
+ t
+ (not (catch 'losing
+ (let* ((end (match-beginning 0))
+ (start (progn (search-backward "\nTag table:\n")
+ (1- (match-end 0))))
+ tem)
+ (setq tem allnodes)
+ (while tem
+ (goto-char start)
+ (or (equal (car (car tem)) "*")
+ (search-forward (concat "Node: "
+ (car (car tem))
+ "\177")
+ end t)
+ (throw 'losing 'x))
+ (setq tem (cdr tem)))
+ (goto-char (1+ start))
+ (while (looking-at ".*Node: \\(.*\\)\177\\([0-9]+\\)$")
+ (setq tem (downcase (buffer-substring
+ (match-beginning 1)
+ (match-end 1))))
+ (setq tem (assoc tem allnodes))
+ (if (or (not tem)
+ (< 1000 (progn
+ (goto-char (match-beginning 2))
+ (setq tem (- (car (cdr (cdr tem)))
+ (read (current-buffer))))
+ (if (> tem 0) tem (- tem)))))
+ (throw 'losing 'y)))
+ (forward-line 1))
+ (or (looking-at "End tag table\n")
+ (throw 'losing 'z))
+ nil))))
+
+(defun batch-info-validate ()
+ "Runs Info-validate on the files remaining on the command line.
+Must be used only with -batch, and kills emacs on completion.
+Each file will be processed even if an error occurred previously.
+For example, invoke \"emacs -batch -f batch-info-validate $info/ ~/*.info\""
+ (if (not noninteractive)
+ (error "batch-info-validate may only be used -batch."))
+ (let ((version-control t)
+ (auto-save-default nil)
+ (find-file-run-dired nil)
+ (kept-old-versions 259259)
+ (kept-new-versions 259259))
+ (let ((error 0)
+ file
+ (files ()))
+ (while command-line-args-left
+ (setq file (expand-file-name (car command-line-args-left)))
+ (cond ((not (file-exists-p file))
+ (message ">> %s does not exist!" file)
+ (setq error 1
+ command-line-args-left (cdr command-line-args-left)))
+ ((file-directory-p file)
+ (setq command-line-args-left (nconc (directory-files file)
+ (cdr command-line-args-left))))
+ (t
+ (setq files (cons file files)
+ command-line-args-left (cdr command-line-args-left)))))
+ (while files
+ (setq file (car files)
+ files (cdr files))
+ (let ((lose nil))
+ (condition-case err
+ (progn
+ (if buffer-file-name (kill-buffer (current-buffer)))
+ (find-file file)
+ (buffer-flush-undo (current-buffer))
+ (set-buffer-modified-p nil)
+ (fundamental-mode)
+ (let ((case-fold-search nil))
+ (goto-char (point-max))
+ (cond ((search-backward "\n\^_\^L\nTag table:\n" nil t)
+ (message "%s already tagified" file))
+ ((< (point-max) 30000)
+ (message "%s too small to bother tagifying" file))
+ (t
+ (message "Tagifying %s..." file)
+ (Info-tagify)
+ (message "Tagifying %s...done" file))))
+ (let ((loss-name " *problems in info file*"))
+ (message "Checking validity of info file %s..." file)
+ (if (get-buffer loss-name)
+ (kill-buffer loss-name))
+ (Info-validate)
+ (if (not (get-buffer loss-name))
+ nil ;(message "Checking validity of info file %s... OK" file)
+ (message "----------------------------------------------------------------------")
+ (message ">> PROBLEMS IN INFO FILE %s" file)
+ (save-excursion
+ (set-buffer loss-name)
+ (princ (buffer-substring (point-min) (point-max))))
+ (message "----------------------------------------------------------------------")
+ (setq error 1 lose t)))
+ (if (and (buffer-modified-p)
+ (not lose))
+ (progn (message "Saving modified %s" file)
+ (save-buffer))))
+ (error (message ">> Error: %s" (prin1-to-string err))))))
+ (kill-emacs error))))
diff --git a/lisp/informat.elc b/lisp/informat.elc
new file mode 100644
index 00000000000..e0e07adb4b0
--- /dev/null
+++ b/lisp/informat.elc
Binary files differ
diff --git a/lisp/isearch.el b/lisp/isearch.el
new file mode 100644
index 00000000000..b0ebccf05b2
--- /dev/null
+++ b/lisp/isearch.el
@@ -0,0 +1,385 @@
+;; Incremental search
+;; Copyright (C) 1985, 1986 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 1, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+; in loaddefs.el
+;(defvar search-last-string ""
+; "Last string search for by a search command.
+;This does not include direct calls to the primitive search functions,
+;and does not include searches that are aborted.")
+;(defvar search-last-regexp ""
+; "Last string searched for by a regexp search command.
+;This does not include direct calls to the primitive search functions,
+;and does not include searches that are aborted.")
+;
+;(defconst search-repeat-char ?\C-s
+; "Character to repeat incremental search forwards.")
+;(defconst search-reverse-char ?\C-r
+; "Character to repeat incremental search backwards.")
+;(defconst search-exit-char ?\e
+; "Character to exit incremental search.")
+;(defconst search-delete-char ?\177
+; "Character to delete from incremental search string.")
+;(defconst search-quote-char ?\C-q
+; "Character to quote special characters for incremental search.")
+;(defconst search-yank-word-char ?\C-w
+; "Character to pull next word from buffer into search string.")
+;(defconst search-yank-line-char ?\C-y
+; "Character to pull rest of line from buffer into search string.")
+;(defconst search-exit-option t
+; "Non-nil means random control characters terminate incremental search.")
+;
+;(defvar search-slow-window-lines 1
+; "*Number of lines in slow search display windows.")
+;(defconst search-slow-speed 1200
+; "*Highest terminal speed at which to use \"slow\" style incremental search.
+;This is the style where a one-line window is created to show the line
+;that the search has reached.")
+
+;; This function does all the work of incremental search.
+;; The functions attached to ^R and ^S are trivial,
+;; merely calling this one, but they are always loaded by default
+;; whereas this file can optionally be autoloadable.
+;; This is the only entry point in this file.
+
+(defun isearch (forward &optional regexp)
+ (let ((search-string "")
+ (search-message "")
+ (cmds nil)
+ (success t)
+ (wrapped nil)
+ (barrier (point))
+ adjusted
+ (invalid-regexp nil)
+ (slow-terminal-mode (and (<= (baud-rate) search-slow-speed)
+ (> (window-height)
+ (* 4 search-slow-window-lines))))
+ (other-end nil) ;Start of last match if fwd, end if backwd.
+ (small-window nil) ;if t, using a small window
+ (found-point nil) ;to restore point from a small window
+ ;; This is the window-start value found by the search.
+ (found-start nil)
+ (opoint (point))
+ (inhibit-quit t)) ;Prevent ^G from quitting immediately.
+ (isearch-push-state)
+ (save-window-excursion
+ (catch 'search-done
+ (while t
+ (or (>= unread-command-char 0)
+ (progn
+ (or (input-pending-p)
+ (isearch-message))
+ (if (and slow-terminal-mode
+ (not (or small-window (pos-visible-in-window-p))))
+ (progn
+ (setq small-window t)
+ (setq found-point (point))
+ (move-to-window-line 0)
+ (let ((window-min-height 1))
+ (split-window nil (if (< search-slow-window-lines 0)
+ (1+ (- search-slow-window-lines))
+ (- (window-height)
+ (1+ search-slow-window-lines)))))
+ (if (< search-slow-window-lines 0)
+ (progn (vertical-motion (- 1 search-slow-window-lines))
+ (set-window-start (next-window) (point))
+ (set-window-hscroll (next-window)
+ (window-hscroll))
+ (set-window-hscroll (selected-window) 0))
+ (other-window 1))
+ (goto-char found-point)))))
+ (let ((char (if quit-flag
+ ?\C-g
+ (read-char))))
+ (setq quit-flag nil adjusted nil)
+ ;; Meta character means exit search.
+ (cond ((and (>= char 128)
+ search-exit-option)
+ (setq unread-command-char char)
+ (throw 'search-done t))
+ ((eq char search-exit-char)
+ ;; Esc means exit search normally.
+ ;; Except, if first thing typed, it means do nonincremental
+ (if (= 0 (length search-string))
+ (nonincremental-search forward regexp))
+ (throw 'search-done t))
+ ((= char ?\C-g)
+ ;; ^G means the user tried to quit.
+ (ding)
+ (discard-input)
+ (if success
+ ;; If search is successful, move back to starting point
+ ;; and really do quit.
+ (progn (goto-char opoint)
+ (signal 'quit nil))
+ ;; If search is failing, rub out until it is once more
+ ;; successful.
+ (while (not success) (isearch-pop))))
+ ((or (eq char search-repeat-char)
+ (eq char search-reverse-char))
+ (if (eq forward (eq char search-repeat-char))
+ ;; C-s in forward or C-r in reverse.
+ (if (equal search-string "")
+ ;; If search string is empty, use last one.
+ (setq search-string
+ (if regexp
+ search-last-regexp search-last-string)
+ search-message
+ (mapconcat 'text-char-description
+ search-string ""))
+ ;; If already have what to search for, repeat it.
+ (or success
+ (progn (goto-char (if forward (point-min) (point-max)))
+ (setq wrapped t))))
+ ;; C-s in reverse or C-r in forward, change direction.
+ (setq forward (not forward)))
+ (setq barrier (point)) ; For subsequent \| if regexp.
+ (setq success t)
+ (or (equal search-string "")
+ (isearch-search))
+ (isearch-push-state))
+ ((= char search-delete-char)
+ ;; Rubout means discard last input item and move point
+ ;; back. If buffer is empty, just beep.
+ (if (null (cdr cmds))
+ (ding)
+ (isearch-pop)))
+ (t
+ (cond ((or (eq char search-yank-word-char)
+ (eq char search-yank-line-char))
+ ;; ^W means gobble next word from buffer.
+ ;; ^Y means gobble rest of line from buffer.
+ (let ((word (save-excursion
+ (and (not forward) other-end
+ (goto-char other-end))
+ (buffer-substring
+ (point)
+ (save-excursion
+ (if (eq char search-yank-line-char)
+ (end-of-line)
+ (forward-word 1))
+ (point))))))
+ (if regexp
+ (setq word (regexp-quote word)))
+ (setq search-string (concat search-string word)
+ search-message
+ (concat search-message
+ (mapconcat 'text-char-description
+ word "")))))
+ ;; Any other control char =>
+ ;; unread it and exit the search normally.
+ ((and search-exit-option
+ (/= char search-quote-char)
+ (or (= char ?\177)
+ (and (< char ? ) (/= char ?\t) (/= char ?\r))))
+ (setq unread-command-char char)
+ (throw 'search-done t))
+ (t
+ ;; Any other character => add it to the
+ ;; search string and search.
+ (cond ((= char search-quote-char)
+ (setq char (read-quoted-char
+ (isearch-message t))))
+ ((= char ?\r)
+ ;; unix braindeath
+ (setq char ?\n)))
+ (setq search-string (concat search-string
+ (char-to-string char))
+ search-message (concat search-message
+ (text-char-description char)))))
+ (if (and (not success)
+ ;; unsuccessful regexp search may become
+ ;; successful by addition of characters which
+ ;; make search-string valid
+ (not regexp))
+ nil
+ ;; If a regexp search may have been made more
+ ;; liberal, retreat the search start.
+ ;; Go back to place last successful search started
+ ;; or to the last ^S/^R (barrier), whichever is nearer.
+ (and regexp success cmds
+ (cond ((and (memq char '(?* ??))
+ ;; Don't treat *, ? as special
+ ;; within [] or after \.
+ (not (nth 6 (car cmds))))
+ (setq adjusted t)
+ ;; This used to use element 2
+ ;; in a reverse search, but it seems that 5
+ ;; (which is the end of the old match)
+ ;; is better in that case too.
+ (let ((cs (nth 5 ; old other-end.
+ (car (cdr cmds)))))
+ ;; (car cmds) is after last search;
+ ;; (car (cdr cmds)) is from before it.
+ (setq cs (or cs barrier))
+ (goto-char
+ (if forward
+ (max cs barrier)
+ (min cs barrier)))))
+ ((eq char ?\|)
+ (setq adjusted t)
+ (goto-char barrier))))
+ ;; In reverse regexp search, adding a character at
+ ;; the end may cause zero or many more chars to be
+ ;; matched, in the string following point.
+ ;; Allow all those possibiities without moving point as
+ ;; long as the match does not extend past search origin.
+ (if (and regexp (not forward) (not adjusted)
+ (condition-case ()
+ (looking-at search-string)
+ (error nil))
+ (<= (match-end 0) (min opoint barrier)))
+ (setq success t invalid-regexp nil
+ other-end (match-end 0))
+ ;; Not regexp, not reverse, or no match at point.
+ (if (and other-end (not adjusted))
+ (goto-char (if forward other-end
+ (min opoint barrier (1+ other-end)))))
+ (isearch-search)))
+ (isearch-push-state))))))
+ (setq found-start (window-start (selected-window)))
+ (setq found-point (point)))
+ (if (> (length search-string) 0)
+ (if regexp
+ (setq search-last-regexp search-string)
+ (setq search-last-string search-string)))
+ ;; If we displayed a single-line window, set point in this window.
+ (if small-window
+ (goto-char found-point))
+ ;; If there was movement, mark the starting position.
+ ;; Maybe should test difference between and set mark iff > threshold.
+ (if (/= (point) opoint)
+ (push-mark opoint)
+ (message ""))
+ (or small-window
+ ;; Exiting the save-window-excursion clobbers this; restore it.
+ (set-window-start (selected-window) found-start t))))
+
+(defun isearch-message (&optional c-q-hack ellipsis)
+ ;; If about to search, and previous search regexp was invalid,
+ ;; check that it still is. If it is valid now,
+ ;; let the message we display while searching say that it is valid.
+ (and invalid-regexp ellipsis
+ (condition-case ()
+ (progn (re-search-forward search-string (point) t)
+ (setq invalid-regexp nil))
+ (error nil)))
+ ;; If currently failing, display no ellipsis.
+ (or success (setq ellipsis nil))
+ (let ((m (concat (if success "" "failing ")
+ (if wrapped "wrapped ")
+ (if regexp "regexp " "")
+ "I-search"
+ (if forward ": " " backward: ")
+ search-message
+ (if c-q-hack "^Q" "")
+ (if invalid-regexp
+ (concat " [" invalid-regexp "]")
+ ""))))
+ (aset m 0 (upcase (aref m 0)))
+ (let ((cursor-in-echo-area ellipsis))
+ (if c-q-hack m (message "%s" m)))))
+
+(defun isearch-pop ()
+ (setq cmds (cdr cmds))
+ (let ((cmd (car cmds)))
+ (setq search-string (car cmd)
+ search-message (car (cdr cmd))
+ success (nth 3 cmd)
+ forward (nth 4 cmd)
+ other-end (nth 5 cmd)
+ invalid-regexp (nth 6 cmd)
+ wrapped (nth 7 cmd)
+ barrier (nth 8 cmd))
+ (goto-char (car (cdr (cdr cmd))))))
+
+(defun isearch-push-state ()
+ (setq cmds (cons (list search-string search-message (point)
+ success forward other-end invalid-regexp
+ wrapped barrier)
+ cmds)))
+
+(defun isearch-search ()
+ (isearch-message nil t)
+ (condition-case lossage
+ (let ((inhibit-quit nil))
+ (if regexp (setq invalid-regexp nil))
+ (setq success
+ (funcall
+ (if regexp
+ (if forward 're-search-forward 're-search-backward)
+ (if forward 'search-forward 'search-backward))
+ search-string nil t))
+ (if success
+ (setq other-end
+ (if forward (match-beginning 0) (match-end 0)))))
+ (quit (setq unread-command-char ?\C-g)
+ (setq success nil))
+ (invalid-regexp (setq invalid-regexp (car (cdr lossage)))
+ (if (string-match "\\`Premature \\|\\`Unmatched \\|\\`Invalid "
+ invalid-regexp)
+ (setq invalid-regexp "incomplete input"))))
+ (if success
+ nil
+ ;; Ding if failed this time after succeeding last time.
+ (and (nth 3 (car cmds))
+ (ding))
+ (goto-char (nth 2 (car cmds)))))
+
+;; This is called from incremental-search
+;; if the first input character is the exit character.
+;; The interactive-arg-reader uses free variables `forward' and `regexp'
+;; which are bound by `incremental-search'.
+
+;; We store the search string in `search-string'
+;; which has been bound already by `incremental-search'
+;; so that, when we exit, it is copied into `search-last-string'.
+
+(defun nonincremental-search (forward regexp)
+ (let (message char function string inhibit-quit)
+ (let ((cursor-in-echo-area t))
+ ;; Prompt assuming not word search,
+ (setq message (if regexp
+ (if forward "Regexp search: "
+ "Regexp search backward: ")
+ (if forward "Search: " "Search backward: ")))
+ (message "%s" message)
+ ;; Read 1 char and switch to word search if it is ^W.
+ (setq char (read-char)))
+ (if (eq char search-yank-word-char)
+ (setq message (if forward "Word search: " "Word search backward: "))
+ ;; Otherwise let that 1 char be part of the search string.
+ (setq unread-command-char char))
+ (setq function
+ (if (eq char search-yank-word-char)
+ (if forward 'word-search-forward 'word-search-backward)
+ (if regexp
+ (if forward 're-search-forward 're-search-backward)
+ (if forward 'search-forward 'search-backward))))
+ ;; Read the search string with corrected prompt.
+ (setq string (read-string message))
+ (let ((var (if regexp 'search-last-regexp 'search-last-string)))
+ ;; Empty means use default.
+ (if (= 0 (length string))
+ (setq string (symbol-value var))
+ ;; Set last search string now so it is set even if we fail.
+ (set var string)))
+ ;; Since we used the minibuffer, we should be available for redo.
+ (setq command-history (cons (list function string) command-history))
+ ;; Go ahead and search.
+ (funcall function string)))
diff --git a/lisp/isearch.elc b/lisp/isearch.elc
new file mode 100644
index 00000000000..e7fcdb45584
--- /dev/null
+++ b/lisp/isearch.elc
Binary files differ
diff --git a/lisp/kermit.el b/lisp/kermit.el
index a66165b9671..2c7ef76c59a 100644
--- a/lisp/kermit.el
+++ b/lisp/kermit.el
@@ -66,6 +66,19 @@
;; option to force kermit to be local, to use stdin and stdout for interactive
;; speech, and to forget about cbreak mode.
+;; 2) The "clean-filter" can be a troublesome item. The main problem arises if
+;; you are running a program under shell-mode which is doing periodic output,
+;; and you then try to switch to another buffer. I came across this while
+;; running kermit file transfers - kermit prints a dot each time a packet is
+;; received. Since emacs is interrupted each time a dot is printed, it becomes
+;; impossible to edit the other buffer. If you hit a key while the filter code
+;; is running, that character will wind up in the *shell* buffer instead of the
+;; current one! So you need to be careful to turn the filter off before
+;; leaving the buffer if a program is still running. In fact, you can't even
+;; use "M-x clean-shell-off" to do this, because you won't be able to type
+;; "clean-shell-off" in the minibuffer!! So you need to have this command
+;; bound to a keystroke.
+
;; Please let me know if any bugs turn up.
;; Feb 1988, Jeff Norden - jeff@colgate.csnet
@@ -90,49 +103,82 @@
;; extra bindings for folks suffering form ^S/^Q braindamage:
(define-key shell-mode-map "\C-c\\" 'kermit-esc)
-(defun kermit-send-input-cr ()
- "Like \\[comint-send-input] but end the line with carriage-return."
+(defun shell-send-input-cr ()
+ "Like \\[shell-send-input] but end the line with carriage-return."
(interactive)
- (comint-send-input "\r"))
+ (end-of-line)
+ (if (eobp)
+ (progn
+ (move-marker last-input-start
+ (process-mark (get-buffer-process (current-buffer))))
+ (insert ?\n)
+ (move-marker last-input-end (point)))
+ (beginning-of-line)
+ (re-search-forward shell-prompt-pattern nil t)
+ (let ((copy (buffer-substring (point)
+ (progn (forward-line 1) (point)))))
+ (goto-char (point-max))
+ (move-marker last-input-start (point))
+ (insert copy)
+ (move-marker last-input-end (point))))
+ (condition-case ()
+ (save-excursion
+ (goto-char last-input-start)
+ (shell-set-directory))
+ (error (funcall shell-set-directory-error-hook)))
+ (let ((process (get-buffer-process (current-buffer))))
+ (process-send-region process last-input-start (- last-input-end 1))
+ (process-send-string process "\r")
+ (set-marker (process-mark process) (point))))
;; This is backwards of what makes sense, but ...
-(define-key shell-mode-map "\n" 'kermit-send-input-cr)
+(define-key shell-mode-map "\n" 'shell-send-input-cr)
(defun kermit-default-cr ()
"Make RETURN end the line with carriage-return and LFD end it with a newline.
This is useful for talking to other systems on which carriage-return
is the normal way to end a line."
(interactive)
- (define-key shell-mode-map "\r" 'kermit-send-input-cr)
- (define-key shell-mode-map "\n" 'comint-send-input))
+ (define-key shell-mode-map "\r" 'shell-send-input-cr)
+ (define-key shell-mode-map "\n" 'shell-send-input))
(defun kermit-default-nl ()
"Make RETURN end the line with a newline char. This is the default state.
In this state, use LFD to send a line and end it with a carriage-return."
(interactive)
- (define-key shell-mode-map "\n" 'kermit-send-input-cr)
- (define-key shell-mode-map "\r" 'comint-send-input))
-
-(defun kermit-clean-filter (proc str)
- "Strip ^M and ^@ characters from process output."
- (save-excursion
- (let ((beg (process-mark proc)))
- (set-buffer (process-buffer proc))
- (goto-char beg)
- (insert-before-markers str)
- (while (re-search-backware "[\r\C-a]+" beg t)
- (replace-match "")))))
+ (define-key shell-mode-map "\n" 'shell-send-input-cr)
+ (define-key shell-mode-map "\r" 'shell-send-input))
+
+;; This filter works, but I don't especially recommend it.
+(defun kermit-clean-filter (process string)
+ "A process filter which deletes all ^M's and ^@'s from the output."
+ (set-buffer (process-buffer process))
+ (let
+ ((firstpos (string-match "[^\C-@\r]+" string))
+ (buffermark (process-mark process))
+ (oldpt (point))
+ (newstring '"")
+ goback)
+ (while firstpos
+ (setq newstring
+ (concat newstring (substring string firstpos (match-end 0))))
+ (setq firstpos (string-match "[^\C-@\r]+" string (match-end 0))))
+ (goto-char (marker-position buffermark))
+ (setq goback (< oldpt (point)))
+ (insert newstring)
+ (set-marker buffermark (point))
+ (if goback (goto-char oldpt))))
(defun kermit-clean-on ()
"Delete all null characters and ^M's from the kermit output.
Note that another (perhaps better) way to do this is to use the
-command \"kermit | tr -d '\\015'\"."
+command `kermit | tr -d '\\015''."
(interactive)
(set-process-filter (get-buffer-process (current-buffer))
'kermit-clean-filter))
(defun kermit-clean-off ()
- "Cancel a previous kermit-clean-shell-on command."
+ "Cancel a previous kermit-clean-shell-on command"
(interactive)
(set-process-filter (get-buffer-process (current-buffer)) nil))
diff --git a/lisp/keypad.el b/lisp/keypad.el
new file mode 100644
index 00000000000..49bc3eaa227
--- /dev/null
+++ b/lisp/keypad.el
@@ -0,0 +1,152 @@
+;; Terminal-independent keypad and function key bindings.
+;; Copyright (C) 1986 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 1, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+;; These keys are handled by a two-level process.
+;; The first level, terminal-dependent, maps input sequences
+;; into the function keys that they represent.
+;; The second level, terminal-independent but customized by users,
+;; map function keys into meanings.
+
+;; This file takes care of the second level of mapping.
+;; The first, terminal-dependent, level is handled by the
+;; terminal-specific files term/*.el.
+
+;; The second-level mapping is done by a keymap, function-keymap.
+;; Here we document the meanings of the "characters" defined by
+;; function-keymap.
+
+;; What do these letters mean?
+;; When we say that ``a stands for the clear-all-tabs key'',
+;; we mean that you should attach to the letter `a' in function-keymap
+;; whatever command you want to be executed when you type the
+;; clear-all-tabs key on any terminal. The terminal-dependent
+;; files will attempt to make this work. If a terminal has no
+;; clear-all-tabs key that can be recognized, it makes no difference
+;; what binding you give to `a' in function-keymap.
+
+;; a -- clear all tabs key
+;; c -- erase key
+;; d -- down-arrow
+;; e -- enter key
+;; f -- find key or search key
+;; h -- home-position key
+;; k -- delete key or remove key.
+;; l -- left-arrow
+;; p -- portrait mode
+;; q -- landscape mode
+;; r -- right-arrow
+;; s -- select key
+;; t -- clear tab this column key
+;; u -- up-arrow
+;; x -- do key
+;; ? -- help
+
+;; - -- keypad key labelled `-'.
+;; . -- keypad key labelled `.'.
+;; , -- keypad key labelled `,'.
+;; 0 ... 9 -- keypad key labelled with that digit,
+;; but only if that key is not also an arrow key.
+
+;; C-@, C-a, ... C-x -- numbered function keys 0 through 24.
+;; These are used for function keys with no labels but numbers,
+;; and may also be used for function keys with labels
+;; that we have not defined letters for.
+
+;; A -- insert line key
+;; C -- clear screen key
+;; D -- delete character key.
+;; E -- clear to end of line key
+;; F -- scroll forward key
+;; H -- home-down
+;; I -- insert character key
+;; If there is just an "insert" key, it should be this.
+;; L -- delete line key
+;; M -- exit insert mode key
+;; N -- next page key
+;; P -- previous page key
+;; R -- scroll reverse key
+;; S -- clear to end of screen key
+;; T -- set tab this column key
+
+(defun keypad-default (char definition)
+ (or (lookup-key function-keymap char)
+ (define-key function-keymap char definition)))
+
+;; Here are the standard command meanings we give to the various
+;; function key names. Because this file is loaded after the user's
+;; init file, we are careful to avoid overriding any definitions
+;; already stored in function-keymap by the init file or (less often)
+;; by the terminal-specific term/*.el file.
+
+(keypad-default "l" 'backward-char)
+(keypad-default "r" 'forward-char)
+(keypad-default "D" 'delete-char)
+(keypad-default "u" 'previous-line)
+(keypad-default "d" 'next-line)
+(keypad-default "N" 'scroll-up)
+(keypad-default "P" 'scroll-down)
+(keypad-default "C" 'recenter)
+(keypad-default "?" 'help-for-help)
+(keypad-default "s" 'set-mark-command)
+(keypad-default "k" 'kill-region)
+(keypad-default "f" 're-search-forward)
+
+(keypad-default "\C-a" 'beginning-of-line)
+(keypad-default "\C-b" 'end-of-line)
+(keypad-default "\C-c" 'isearch-forward)
+(keypad-default "\C-d" 'kill-line)
+
+(keypad-default "." 'delete-char)
+(keypad-default "0" 'yank)
+(keypad-default "e" 'open-line)
+(keypad-default "1" 'backward-word)
+(keypad-default "3" 'forward-word)
+(keypad-default "7" 'backward-paragraph)
+(keypad-default "9" 'forward-paragraph)
+(keypad-default "h" 'move-to-window-line)
+
+(defun setup-terminal-keymap (map translations)
+ "Set up keymap MAP to forward to function-keymap according to TRANSLATIONS.
+TRANSLATIONS is an alist; each element of it looks like (FROMSTRING . TOCHAR).
+For each such pair, we define the key sequence FROMSTRING in MAP
+to forward to the definition of character TOCHAR in function-keymap.
+\"Forwarding\" means that subsequent redefinition of TOCHAR in
+function-keymap will be seen automatically in MAP as well.
+
+This function is used by files term/*.el to set up the mapping from the
+escape sequences sent by function keys on particular terminals (FROMSTRINGs)
+into Emacs standard function key slots (TOCHARs).
+An actual definition (such as a symbol) may be given in place of TOCHAR.
+Generally, MAP is a prefix keymap which will be attached to a key
+that is the common prefix sent by all function keys (often ESC O or ESC [)."
+ (while translations
+ (define-key map (car (car translations))
+ (if (numberp (cdr (car translations)))
+ (cons function-keymap (cdr (car translations)))
+ (cdr (car translations))))
+ (setq translations (cdr translations))))
+
+(defun function-key-sequence (char)
+ "Return key sequence for function key that on this terminal
+translates into slot CHAR in function-keymap.
+Or return nil if there is none."
+ (car (where-is-internal (cons function-keymap char) (current-local-map))))
+
+(provide 'keypad)
diff --git a/lisp/keypad.elc b/lisp/keypad.elc
new file mode 100644
index 00000000000..ab51cfd5e9f
--- /dev/null
+++ b/lisp/keypad.elc
Binary files differ
diff --git a/lisp/ledit.el b/lisp/ledit.el
index 0428fa8b228..2cdca35a470 100644
--- a/lisp/ledit.el
+++ b/lisp/ledit.el
@@ -23,12 +23,12 @@
(defvar ledit-mode-map nil)
-(defconst ledit-zap-file (concat "/tmp/" (user-login-name) ".l1")
+(defconst ledit-zap-file (concat "/tmp/" (getenv "USER") ".l1")
"File name for data sent to Lisp by Ledit.")
-(defconst ledit-read-file (concat "/tmp/" (user-login-name) ".l2")
+(defconst ledit-read-file (concat "/tmp/" (getenv "USER") ".l2")
"File name for data sent to Ledit by Lisp.")
(defconst ledit-compile-file
- (concat "/tmp/" (user-login-name) ".l4")
+ (concat "/tmp/" (getenv "USER") ".l4")
"File name for data sent to Lisp compiler by Ledit.")
(defconst ledit-buffer "*LEDIT*"
"Name of buffer in which Ledit accumulates data to send to Lisp.")
@@ -57,19 +57,19 @@
(message "Region saved for Lisp"))
(defun ledit-zap-defun-to-lisp ()
- "Carry the current defun to Lisp."
+ "Carry the current defun to lisp"
(interactive)
(ledit-save-defun)
(ledit-go-to-lisp))
(defun ledit-zap-defun-to-liszt ()
- "Carry the current defun to liszt."
+ "Carry the current defun to liszt"
(interactive)
(ledit-save-defun)
(ledit-go-to-liszt))
(defun ledit-zap-region-to-lisp (beg end)
- "Carry the current region to Lisp."
+ "Carry the current region to lisp"
(interactive "r")
(ledit-save-region beg end)
(ledit-go-to-lisp))
@@ -104,7 +104,7 @@
(load ledit-read-file t t))
(defun ledit-setup ()
- "Set up key bindings for the Lisp/Emacs interface."
+ "Set up key bindings for the Lisp / Emacs interface"
(if (not ledit-mode-map)
(progn (setq ledit-mode-map (make-sparse-keymap))
(lisp-mode-commands ledit-mode-map)))
@@ -116,13 +116,13 @@
(ledit-setup)
(defun ledit-mode ()
- "\\<ledit-mode-map>Major mode for editing text and stuffing it to a Lisp job.
+ "Major mode for editing text and stuffing it to a Lisp job.
Like Lisp mode, plus these special commands:
- \\[ledit-save-defun] -- record defun at or after point
+ M-C-d -- record defun at or after point
for later transmission to Lisp job.
- \\[ledit-save-region] -- record region for later transmission to Lisp job.
- \\[ledit-go-to-lisp] -- transfer to Lisp job and transmit saved text.
- \\[ledit-go-to-liszt] -- transfer to Liszt (Lisp compiler) job
+ M-C-r -- record region for later transmission to Lisp job.
+ C-x z -- transfer to Lisp job and transmit saved text.
+ M-C-c -- transfer to Liszt (Lisp compiler) job
and transmit saved text.
\\{ledit-mode-map}
To make Lisp mode automatically change to Ledit mode,
diff --git a/lisp/play/life.el b/lisp/life.el
index 059bf350fd4..16b0e719b5b 100644
--- a/lisp/play/life.el
+++ b/lisp/life.el
@@ -97,8 +97,8 @@
(defun life (&optional sleeptime)
"Run Conway's Life simulation.
-The starting pattern is randomly selected. Prefix arg (optional first
-arg non-nil from a program) is the number of seconds to sleep between
+The starting pattern is randomly selected. Prefix arg (optional first arg
+non-nil from a program) is the number of seconds to sleep between
generations (this defaults to 1)."
(interactive "p")
(or sleeptime (setq sleeptime 1))
@@ -131,7 +131,7 @@ generations (this defaults to 1)."
life-generation-string)
fill-column (1- (window-width))
life-window-start 1)
- (buffer-disable-undo (current-buffer))
+ (buffer-flush-undo (current-buffer))
;; stuff in the random pattern
(life-insert-random-pattern)
;; make sure (life-life-char) is used throughout
@@ -272,3 +272,5 @@ generations (this defaults to 1)."
(put 'life-extinct 'error-conditions '(life-extinct quit))
(put 'life-extinct 'error-message "All life has perished")
+
+
diff --git a/lisp/life.elc b/lisp/life.elc
new file mode 100644
index 00000000000..6ad5e273a0d
--- /dev/null
+++ b/lisp/life.elc
Binary files differ
diff --git a/lisp/emacs-lisp/lisp-mode.el b/lisp/lisp-mode.el
index e9a05c5abca..860dc368ee8 100644
--- a/lisp/emacs-lisp/lisp-mode.el
+++ b/lisp/lisp-mode.el
@@ -48,8 +48,7 @@
(modify-syntax-entry ?` "' " emacs-lisp-mode-syntax-table)
(modify-syntax-entry ?' "' " emacs-lisp-mode-syntax-table)
(modify-syntax-entry ?, "' " emacs-lisp-mode-syntax-table)
- ;; Used to be singlequote; changed for flonums.
- (modify-syntax-entry ?. "_ " emacs-lisp-mode-syntax-table)
+ (modify-syntax-entry ?. "' " emacs-lisp-mode-syntax-table)
(modify-syntax-entry ?# "' " emacs-lisp-mode-syntax-table)
(modify-syntax-entry ?\" "\" " emacs-lisp-mode-syntax-table)
(modify-syntax-entry ?\\ "\\ " emacs-lisp-mode-syntax-table)
@@ -81,10 +80,6 @@
(setq paragraph-ignore-fill-prefix t)
(make-local-variable 'indent-line-function)
(setq indent-line-function 'lisp-indent-line)
- (make-local-variable 'indent-region-function)
- (setq indent-region-function 'lisp-indent-region)
- (make-local-variable 'parse-sexp-ignore-comments)
- (setq parse-sexp-ignore-comments t)
(make-local-variable 'comment-start)
(setq comment-start ";")
(make-local-variable 'comment-start-skip)
@@ -93,26 +88,18 @@
(setq comment-column 40)
(make-local-variable 'comment-indent-hook)
(setq comment-indent-hook 'lisp-comment-indent))
-
-(defvar shared-lisp-mode-map ()
- "Keymap for commands shared by all sorts of Lisp modes.")
-
-(if shared-lisp-mode-map
- ()
- (setq shared-lisp-mode-map (make-sparse-keymap))
- (define-key shared-lisp-mode-map "\e\C-q" 'indent-sexp)
- (define-key shared-lisp-mode-map "\177" 'backward-delete-char-untabify)
- (define-key shared-lisp-mode-map "\t" 'lisp-indent-line))
-
-(defvar emacs-lisp-mode-map ()
- "Keymap for Emacs Lisp mode.
-All commands in shared-lisp-mode-map are inherited by this map.")
+(defun lisp-mode-commands (map)
+ (define-key map "\e\C-q" 'indent-sexp)
+ (define-key map "\177" 'backward-delete-char-untabify)
+ (define-key map "\t" 'lisp-indent-line))
+
+(defvar emacs-lisp-mode-map () "")
(if emacs-lisp-mode-map
()
- (setq emacs-lisp-mode-map
- (nconc (make-sparse-keymap) shared-lisp-mode-map))
- (define-key emacs-lisp-mode-map "\e\C-x" 'eval-defun))
+ (setq emacs-lisp-mode-map (make-sparse-keymap))
+ (define-key emacs-lisp-mode-map "\e\C-x" 'eval-defun)
+ (lisp-mode-commands emacs-lisp-mode-map))
(defun emacs-lisp-mode ()
"Major mode for editing Lisp code to run in Emacs.
@@ -120,7 +107,7 @@ Commands:
Delete converts tabs to spaces as it moves back.
Blank lines separate paragraphs. Semicolons start comments.
\\{emacs-lisp-mode-map}
-Entry to this mode calls the value of `emacs-lisp-mode-hook'
+Entry to this mode calls the value of emacs-lisp-mode-hook
if that value is non-nil."
(interactive)
(kill-all-local-variables)
@@ -131,16 +118,13 @@ if that value is non-nil."
(lisp-mode-variables nil)
(run-hooks 'emacs-lisp-mode-hook))
-(defvar lisp-mode-map ()
- "Keymap for ordinary Lisp mode.
-All commands in `shared-lisp-mode-map' are inherited by this map.")
-
+(defvar lisp-mode-map ())
(if lisp-mode-map
()
- (setq lisp-mode-map
- (nconc (make-sparse-keymap) shared-lisp-mode-map))
+ (setq lisp-mode-map (make-sparse-keymap))
(define-key lisp-mode-map "\e\C-x" 'lisp-send-defun)
- (define-key lisp-mode-map "\C-c\C-l" 'run-lisp))
+ (define-key lisp-mode-map "\C-c\C-l" 'run-lisp)
+ (lisp-mode-commands lisp-mode-map))
(defun lisp-mode ()
"Major mode for editing Lisp code for Lisps other than GNU Emacs Lisp.
@@ -151,7 +135,7 @@ Blank lines separate paragraphs. Semicolons start comments.
Note that `run-lisp' may be used either to start an inferior Lisp job
or to switch back to an existing one.
-Entry to this mode calls the value of `lisp-mode-hook'
+Entry to this mode calls the value of lisp-mode-hook
if that value is non-nil."
(interactive)
(kill-all-local-variables)
@@ -164,18 +148,15 @@ if that value is non-nil."
;; This will do unless shell.el is loaded.
(defun lisp-send-defun nil
- "Send the current defun to the Lisp process made by \\[run-lisp]."
+ "Send the current defun to the Lisp process made by M-x run-lisp."
(interactive)
(error "Process lisp does not exist"))
-(defvar lisp-interaction-mode-map ()
- "Keymap for Lisp Interaction moe.
-All commands in `shared-lisp-mode-map' are inherited by this map.")
-
+(defvar lisp-interaction-mode-map ())
(if lisp-interaction-mode-map
()
- (setq lisp-interaction-mode-map
- (nconc (make-sparse-keymap) shared-lisp-mode-map))
+ (setq lisp-interaction-mode-map (make-sparse-keymap))
+ (lisp-mode-commands lisp-interaction-mode-map)
(define-key lisp-interaction-mode-map "\e\C-x" 'eval-defun)
(define-key lisp-interaction-mode-map "\n" 'eval-print-last-sexp))
@@ -186,17 +167,16 @@ before point, and prints its value into the buffer, advancing point.
Commands:
Delete converts tabs to spaces as it moves back.
-Paragraphs are separated only by blank lines.
-Semicolons start comments.
+Paragraphs are separated only by blank lines. Semicolons start comments.
\\{lisp-interaction-mode-map}
-Entry to this mode calls the value of `lisp-interaction-mode-hook'
+Entry to this mode calls the value of lisp-interaction-mode-hook
if that value is non-nil."
(interactive)
(kill-all-local-variables)
(use-local-map lisp-interaction-mode-map)
+ (set-syntax-table emacs-lisp-mode-syntax-table)
(setq major-mode 'lisp-interaction-mode)
(setq mode-name "Lisp Interaction")
- (set-syntax-table emacs-lisp-mode-syntax-table)
(lisp-mode-variables nil)
(run-hooks 'lisp-interaction-mode-hook))
@@ -230,21 +210,21 @@ With argument, print output into current buffer."
(if arg (current-buffer) t)))
(defun eval-defun (arg)
- "Evaluate defun that point is in or before. Print value in minibuffer.
-With argument, edebug-defun it instead, preparing it for source-level
-debugging with the electric debugger."
+ "Evaluate defun that point is in or before.
+Print value in minibuffer.
+With argument, insert value in current buffer after the defun."
(interactive "P")
- (if arg (edebug-defun)
- (save-excursion
- (end-of-defun)
- (let ((end (point)))
- (beginning-of-defun)
- (eval-region (point) end t)))))
+ (save-excursion
+ (end-of-defun)
+ (let ((end (point)))
+ (beginning-of-defun)
+ (eval-region (point) end
+ (if arg (current-buffer) t)))))
(defun lisp-comment-indent ()
- (if (looking-at "\\s<\\s<\\s<")
+ (if (looking-at ";;;")
(current-column)
- (if (looking-at "\\s<\\s<")
+ (if (looking-at ";;")
(let ((tem (calculate-lisp-indent)))
(if (listp tem) (car tem) tem))
(skip-chars-backward " \t")
@@ -252,7 +232,7 @@ debugging with the electric debugger."
comment-column))))
(defconst lisp-indent-offset nil "")
-(defconst lisp-indent-function 'lisp-indent-function "")
+(defconst lisp-indent-hook 'lisp-indent-hook "")
(defun lisp-indent-line (&optional whole-exp)
"Indent current line as Lisp code.
@@ -264,10 +244,10 @@ rigidly along with this one."
(beginning-of-line)
(setq beg (point))
(skip-chars-forward " \t")
- (if (looking-at "\\s<\\s<\\s<")
+ (if (looking-at ";;;")
;; Don't alter indentation of a ;;; comment line.
nil
- (if (and (looking-at "\\s<") (not (looking-at "\\s<\\s<")))
+ (if (and (looking-at ";") (not (looking-at ";;")))
;; Single-semicolon comment lines should be indented
;; as comment lines, not as code.
(progn (indent-for-comment) (forward-char -1))
@@ -375,17 +355,17 @@ of the start of the containing expression."
((and (integerp lisp-indent-offset) containing-sexp)
;; Indent by constant offset
(goto-char containing-sexp)
- (+ (current-column) lisp-indent-offset))
+ (+ normal-indent lisp-indent-offset))
(desired-indent)
- ((and (boundp 'lisp-indent-function)
- lisp-indent-function
+ ((and (boundp 'lisp-indent-hook)
+ lisp-indent-hook
(not retry))
- (or (funcall lisp-indent-function indent-point state)
+ (or (funcall lisp-indent-hook indent-point state)
normal-indent))
(t
normal-indent))))))
-(defun lisp-indent-function (indent-point state)
+(defun lisp-indent-hook (indent-point state)
(let ((normal-indent (current-column)))
(goto-char (1+ (elt state 1)))
(parse-partial-sexp (point) last-sexp 0 t)
@@ -407,7 +387,7 @@ of the start of the containing expression."
(let ((function (buffer-substring (point)
(progn (forward-sexp 1) (point))))
method)
- (setq method (get (intern-soft function) 'lisp-indent-function))
+ (setq method (get (intern-soft function) 'lisp-indent-hook))
(cond ((or (eq method 'defun)
(and (null method)
(> (length function) 3)
@@ -427,7 +407,7 @@ of the start of the containing expression."
body-indent containing-form-column)
;; Move to the start of containing form, calculate indentation
;; to use for non-distinguished forms (> count), and move past the
- ;; function symbol. lisp-indent-function guarantees that there is at
+ ;; function symbol. lisp-indent-hook guarantees that there is at
;; least one word or symbol character following open paren of containing
;; form.
(goto-char containing-form-start)
@@ -475,41 +455,35 @@ of the start of the containing expression."
(+ lisp-body-indent (current-column)))))
-;; (put 'progn 'lisp-indent-function 0), say, causes progn to be indented
+;; (put 'progn 'lisp-indent-hook 0), say, causes progn to be indented
;; like defun if the first form is placed on the next line, otherwise
;; it is indented like any other form (i.e. forms line up under first).
-(put 'lambda 'lisp-indent-function 'defun)
-(put 'autoload 'lisp-indent-function 'defun)
-(put 'progn 'lisp-indent-function 0)
-(put 'prog1 'lisp-indent-function 1)
-(put 'prog2 'lisp-indent-function 2)
-(put 'save-excursion 'lisp-indent-function 0)
-(put 'save-window-excursion 'lisp-indent-function 0)
-(put 'save-restriction 'lisp-indent-function 0)
-(put 'let 'lisp-indent-function 1)
-(put 'let* 'lisp-indent-function 1)
-(put 'while 'lisp-indent-function 1)
-(put 'if 'lisp-indent-function 2)
-(put 'catch 'lisp-indent-function 1)
-(put 'condition-case 'lisp-indent-function 2)
-(put 'unwind-protect 'lisp-indent-function 1)
-(put 'with-output-to-temp-buffer 'lisp-indent-function 1)
-
-(defun indent-sexp (&optional endpos)
- "Indent each line of the list starting just after point.
-If optional arg ENDPOS is given, indent each line, stopping when
-ENDPOS is encountered."
+(put 'lambda 'lisp-indent-hook 'defun)
+(put 'progn 'lisp-indent-hook 0)
+(put 'prog1 'lisp-indent-hook 1)
+(put 'save-excursion 'lisp-indent-hook 0)
+(put 'save-window-excursion 'lisp-indent-hook 0)
+(put 'save-restriction 'lisp-indent-hook 0)
+(put 'let 'lisp-indent-hook 1)
+(put 'let* 'lisp-indent-hook 1)
+(put 'while 'lisp-indent-hook 1)
+(put 'if 'lisp-indent-hook 2)
+(put 'catch 'lisp-indent-hook 1)
+(put 'condition-case 'lisp-indent-hook 2)
+(put 'unwind-protect 'lisp-indent-hook 1)
+(put 'with-output-to-temp-buffer 'lisp-indent-hook 1)
+
+(defun indent-sexp ()
+ "Indent each line of the list starting just after point."
(interactive)
- (let ((indent-stack (list nil)) (next-depth 0) last-depth bol
- outer-loop-done inner-loop-done state this-indent
- (last-point (point)))
+ (let ((indent-stack (list nil)) (next-depth 0) bol
+ outer-loop-done inner-loop-done state this-indent)
;; Get error now if we don't have a complete sexp after point.
(save-excursion (forward-sexp 1))
(save-excursion
(setq outer-loop-done nil)
- (while (if endpos (< (point) endpos)
- (not outer-loop-done))
+ (while (not outer-loop-done)
(setq last-depth next-depth
inner-loop-done nil)
;; Parse this line so we can learn the state
@@ -539,14 +513,7 @@ ENDPOS is encountered."
(forward-line 1)
(setcar (nthcdr 5 state) nil))
(setq inner-loop-done t)))
- (and endpos
- (while (<= next-depth 0)
- (setq indent-stack (append indent-stack (list nil)))
- (setq next-depth (1+ next-depth))
- (setq last-depth (1+ last-depth))))
- (or outer-loop-done
- (setq outer-loop-done (<= next-depth 0)))
- (if outer-loop-done
+ (if (or outer-loop-done (setq outer-loop-done (<= next-depth 0)))
nil
(while (> last-depth next-depth)
(setq indent-stack (cdr indent-stack)
@@ -561,14 +528,13 @@ ENDPOS is encountered."
(skip-chars-forward " \t")
;; But not if the line is blank, or just a comment
;; (except for double-semi comments; indent them as usual).
- (if (or (eobp) (looking-at "\\s<\\|\n"))
+ (if (or (eobp) (looking-at "[;\n]"))
nil
(if (and (car indent-stack)
(>= (car indent-stack) 0))
(setq this-indent (car indent-stack))
(let ((val (calculate-lisp-indent
- (if (car indent-stack) (- (car indent-stack))
- last-point))))
+ (if (car indent-stack) (- (car indent-stack))))))
(if (integerp val)
(setcar indent-stack
(setq this-indent val))
@@ -576,26 +542,12 @@ ENDPOS is encountered."
(setq this-indent (car val)))))
(if (/= (current-column) this-indent)
(progn (delete-region bol (point))
- (indent-to this-indent)))))
- (or outer-loop-done
- (setq outer-loop-done (= (point) last-point))
- (setq last-point (point)))))))
-
-;; Indent every line whose first char is between START and END inclusive.
-(defun lisp-indent-region (start end)
- (save-excursion
- (goto-char start)
- (and (bolp) (not (eolp))
- (lisp-indent-line))
- (let ((endmark (copy-marker end)))
- (indent-sexp endmark)
- (set-marker endmark nil))))
+ (indent-to this-indent)))))))))
(defun indent-code-rigidly (start end arg &optional nochange-regexp)
"Indent all lines of code, starting in the region, sideways by ARG columns.
-Does not affect lines starting inside comments or strings, assuming that
-the start of the region is not inside them.
-
+Does not affect lines starting inside comments or strings,
+assuming that the start of the region is not inside them.
Called from a program, takes args START, END, COLUMNS and NOCHANGE-REGEXP.
The last is a regexp which, if matched at the beginning of a line,
means don't indent that line."
@@ -623,3 +575,4 @@ means don't indent that line."
(progn
(forward-line 1) (point))
nil nil state))))))
+
diff --git a/lisp/lisp-mode.elc b/lisp/lisp-mode.elc
new file mode 100644
index 00000000000..e5820af34f8
--- /dev/null
+++ b/lisp/lisp-mode.elc
Binary files differ
diff --git a/lisp/emacs-lisp/lisp.el b/lisp/lisp.el
index db2a4169ae3..8ecf0f329f8 100644
--- a/lisp/emacs-lisp/lisp.el
+++ b/lisp/lisp.el
@@ -18,30 +18,23 @@
;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-(defvar defun-prompt-regexp nil
- "Non-nil => regexp to ignore, before the `(' that starts a defun.")
-
(defun forward-sexp (&optional arg)
- "Move forward across one balanced expression (sexp).
-With argument, do it that many times. Negative arg -N means
-move backward across N balanced expressions."
+ "Move forward across one balanced expression.
+With argument, do this that many times."
(interactive "p")
(or arg (setq arg 1))
(goto-char (or (scan-sexps (point) arg) (buffer-end arg)))
(if (< arg 0) (backward-prefix-chars)))
(defun backward-sexp (&optional arg)
- "Move backward across one balanced expression (sexp).
-With argument, do it that many times. Negative arg -N means
-move forward across N balanced expressions."
+ "Move backward across one balanced expression.
+With argument, do this that many times."
(interactive "p")
(or arg (setq arg 1))
(forward-sexp (- arg)))
(defun mark-sexp (arg)
- "Set mark ARG sexps from point.
-The place mark goes is the same place \\[forward-sexp] would
-move to with the same argument."
+ "Set mark ARG sexps from point."
(interactive "p")
(push-mark
(save-excursion
@@ -50,16 +43,14 @@ move to with the same argument."
(defun forward-list (&optional arg)
"Move forward across one balanced group of parentheses.
-With argument, do it that many times.
-Negative arg -N means move backward across N groups of parentheses."
+With argument, do this that many times."
(interactive "p")
(or arg (setq arg 1))
(goto-char (or (scan-lists (point) arg 0) (buffer-end arg))))
(defun backward-list (&optional arg)
"Move backward across one balanced group of parentheses.
-With argument, do it that many times.
-Negative arg -N means move forward across N groups of parentheses."
+With argument, do this that many times."
(interactive "p")
(or arg (setq arg 1))
(forward-list (- arg)))
@@ -67,8 +58,7 @@ Negative arg -N means move forward across N groups of parentheses."
(defun down-list (arg)
"Move forward down one level of parentheses.
With argument, do this that many times.
-A negative argument means move backward but still go down a level.
-In Lisp programs, an argument is required."
+A negative argument means move backward but still go down a level."
(interactive "p")
(let ((inc (if (> arg 0) 1 -1)))
(while (/= arg 0)
@@ -78,16 +68,14 @@ In Lisp programs, an argument is required."
(defun backward-up-list (arg)
"Move backward out of one level of parentheses.
With argument, do this that many times.
-A negative argument means move forward but still to a less deep spot.
-In Lisp programs, an argument is required."
+A negative argument means move forward but still to a less deep spot."
(interactive "p")
(up-list (- arg)))
(defun up-list (arg)
"Move forward out of one level of parentheses.
With argument, do this that many times.
-A negative argument means move backward but still to a less deep spot.
-In Lisp programs, an argument is required."
+A negative argument means move backward but still to a less deep spot."
(interactive "p")
(let ((inc (if (> arg 0) 1 -1)))
(while (/= arg 0)
@@ -95,49 +83,34 @@ In Lisp programs, an argument is required."
(setq arg (- arg inc)))))
(defun kill-sexp (arg)
- "Kill the sexp (balanced expression) following the cursor.
-With argument, kill that many sexps after the cursor.
-Negative arg -N means kill N sexps before the cursor."
+ "Kill the syntactic expression following the cursor.
+With argument, kill that many expressions after (or before) the cursor."
(interactive "p")
(let ((opoint (point)))
(forward-sexp arg)
(kill-region opoint (point))))
(defun backward-kill-sexp (arg)
- "Kill the sexp (balanced expression) preceding the cursor.
-With argument, kill that many sexps before the cursor.
-Negative arg -N means kill N sexps after the cursor."
+ "Kill the syntactic expression preceding the cursor.
+With argument, kill that many expressions before (or after) the cursor."
(interactive "p")
(kill-sexp (- arg)))
(defun beginning-of-defun (&optional arg)
- "Move backward to the beginning of a defun.
-With argument, do it that many times. Negative arg -N
-means move forward to Nth following beginning of defun.
-Returns t unless search stops due to beginning or end of buffer.
-
-Normally a defun starts when there is an char with open-parenthesis
-syntax at the beginning of a line. If `defun-prompt-regexp' is
-non-nil, then a string which matches that regexp may precede the
-open-parenthesis."
+ "Move backward to next beginning-of-defun.
+With argument, do this that many times.
+Returns t unless search stops due to end of buffer."
(interactive "p")
(and arg (< arg 0) (forward-char 1))
- (and (re-search-backward (if defun-prompt-regexp
- (concat "^\\s(\\|"
- "\\(" defun-prompt-regexp "\\)\\s(")
- "^\\s(")
- nil 'move (or arg 1))
+ (and (re-search-backward "^\\s(" nil 'move (or arg 1))
(progn (beginning-of-line) t)))
(defun buffer-end (arg)
(if (> arg 0) (point-max) (point-min)))
(defun end-of-defun (&optional arg)
- "Move forward to next end of defun. With argument, do it that many times.
-Negative argument -N means move back to Nth preceding end of defun.
-
-An end of a defun occurs right after the close-parenthesis that matches
-the open-parenthesis that starts a defun; see `beginning-of-defun'."
+ "Move forward to next end of defun.
+An end of a defun is found by moving forward from the beginning of one."
(interactive "p")
(if (or (null arg) (= arg 0)) (setq arg 1))
(let ((first t))
@@ -154,7 +127,7 @@ the open-parenthesis that starts a defun; see `beginning-of-defun'."
(setq first nil)
(forward-list 1)
(skip-chars-forward " \t")
- (if (looking-at "\\s<\\|\n")
+ (if (looking-at "[;\n]")
(forward-line 1))
(<= (point) pos))))
(setq arg (1- arg)))
@@ -174,8 +147,7 @@ the open-parenthesis that starts a defun; see `beginning-of-defun'."
(setq arg (1+ arg)))))
(defun mark-defun ()
- "Put mark at end of this defun, point at beginning.
-The defun marked is the one that contains point or follows point."
+ "Put mark at end of defun, point at beginning."
(interactive)
(push-mark (point))
(end-of-defun)
@@ -187,20 +159,21 @@ The defun marked is the one that contains point or follows point."
"Put parentheses around next ARG sexps. Leave point after open-paren.
No argument is equivalent to zero: just insert () and leave point between."
(interactive "P")
- (if arg (setq arg (prefix-numeric-value arg))
- (setq arg 0))
- (or (eq arg 0) (skip-chars-forward " \t"))
- (and (memq (char-syntax (preceding-char)) '(?w ?_ ?\) ))
- (insert " "))
+;Install these commented-out lines for version 19.
+; (if arg (skip-chars-forward " \t")
+; (or (memq (char-syntax (preceding-char)) '(?\ ?> ?\( ))
+; (insert " ")))
(insert ?\()
(save-excursion
- (or (eq arg 0) (forward-sexp arg))
+ (if arg
+ (forward-sexp (prefix-numeric-value arg)))
(insert ?\))
- (and (memq (char-syntax (following-char)) '(?w ?_ ?\( ))
- (insert " "))))
+; (or (memq (char-syntax (following-char)) '(?\ ?> ?\( ))
+; (insert " "))
+ ))
(defun move-past-close-and-reindent ()
- "Move past next `)', delete indentation before it, then indent after it."
+ "Move past next ), delete indentation before it, then indent after it."
(interactive)
(up-list 1)
(forward-char -1)
@@ -213,12 +186,14 @@ No argument is equivalent to zero: just insert () and leave point between."
(newline-and-indent))
(defun lisp-complete-symbol ()
- "Perform completion on Lisp symbol preceding point. That symbol is
-compared against the symbols that exist and any additional characters
-determined by what is there are inserted.
- If the symbol starts just after an open-parenthesis, only symbols
-with function definitions are considered. Otherwise, all symbols with
-function definitions, values or properties are considered."
+ "Perform completion on Lisp symbol preceding point.
+That symbol is compared against the symbols that exist
+and any additional characters determined by what is there
+are inserted.
+If the symbol starts just after an open-parenthesis,
+only symbols with function definitions are considered.
+Otherwise, all symbols with function definitions, values
+or properties are considered."
(interactive)
(let* ((end (point))
(buffer-syntax (syntax-table))
diff --git a/lisp/lisp.elc b/lisp/lisp.elc
new file mode 100644
index 00000000000..e8ac960a0f9
--- /dev/null
+++ b/lisp/lisp.elc
Binary files differ
diff --git a/lisp/loaddefs.el b/lisp/loaddefs.el
new file mode 100644
index 00000000000..c2ce00f04f7
--- /dev/null
+++ b/lisp/loaddefs.el
@@ -0,0 +1,1942 @@
+;; Define standard autoloads and keys of other files, for Emacs.
+;; Copyright (C) 1985, 1986, 1987 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 1, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+;;; !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+;;; Special formatting conventions are used in this file!
+;;;
+;;; a backslash-newline is used at the beginning of a documentation string
+;;; when that string should be stored in the file etc/DOCnnn, not in core.
+;;;
+;;; Such strings read into Lisp as numbers (during the pure-loading phase).
+;;;
+;;; But you must obey certain rules to make sure the string is understood
+;;; and goes into etc/DOCnnn properly. Otherwise, the string will not go
+;;; anywhere!
+;;;
+;;; The doc string must appear in the standard place in a call to
+;;; defun, autoload, defvar or defconst. No Lisp macros are recognized.
+;;; The open-paren starting the definition must appear in column 0.
+;;;
+;;; In defvar and defconst, there is an additional rule:
+;;; The double-quote that starts the string must be on the same
+;;; line as the defvar or defconst.
+;;; !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+;; Know which function the debugger is!
+(setq debugger 'debug)
+
+(defconst mode-line-buffer-identification (purecopy '("Emacs: %17b")) "\
+Mode-line control for identifying the buffer being displayed.
+Its default value is \"Emacs: %17b\". Major modes that edit things
+other than ordinary files may change this (e.g. Info, Dired,...)")
+
+(make-variable-buffer-local 'mode-line-buffer-identification)
+
+(defconst mode-line-process nil "\
+Mode-line control for displaying info on process status.
+Normally nil in most modes, since there is no process to display.")
+
+(make-variable-buffer-local 'mode-line-process)
+
+(defconst mode-line-modified (purecopy '("--%1*%1*-")) "\
+Mode-line control for displaying whether current buffer is modified.")
+
+(make-variable-buffer-local 'mode-line-modified)
+
+(setq-default mode-line-format
+ (list (purecopy "")
+ 'mode-line-modified
+ 'mode-line-buffer-identification
+ (purecopy " ")
+ 'global-mode-string
+ (purecopy " %[(")
+ 'mode-name 'minor-mode-alist "%n" 'mode-line-process
+ (purecopy ")%]----")
+ (purecopy '(-3 . "%p"))
+ (purecopy "-%-")))
+
+(defvar minor-mode-alist nil "\
+Alist saying how to show minor modes in the mode line.
+Each element looks like (VARIABLE STRING);
+STRING is included in the mode line iff VARIABLE's value is non-nil.")
+(setq minor-mode-alist (mapcar 'purecopy
+ '((abbrev-mode " Abbrev")
+ (overwrite-mode " Ovwrt")
+ (auto-fill-hook " Fill")
+ ;; not really a minor mode...
+ (defining-kbd-macro " Def"))))
+
+(defconst function-keymap (make-sparse-keymap) "\
+Keymap containing definitions of keypad and function keys.")
+
+;; These variables are used by autoloadable packages.
+;; They are defined here so that they do not get overridden
+;; by the loading of those packages.
+
+(defconst paragraph-start "^[ \t\n\f]" "\
+*Regexp for beginning of a line that starts OR separates paragraphs.")
+(defconst 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.")
+
+(defconst sentence-end (purecopy "[.?!][]\"')}]*\\($\\|\t\\| \\)[ \t\n]*") "\
+*Regexp describing the end of a sentence.
+All paragraph boundaries also end sentences, regardless.")
+
+(defconst page-delimiter "^\014" "\
+*Regexp describing line-beginnings that separate pages.")
+
+(defconst case-replace t "\
+*Non-nil means query-replace should preserve case in replacements.")
+
+;; indent.el may not be autoloading, but it still loses
+;; if lisp-mode is ever called before this defvar is done.
+(defvar indent-line-function 'indent-to-left-margin "\
+Function to indent current line.")
+
+(defconst only-global-abbrevs nil "\
+*t means user plans to use global abbrevs only.
+Makes the commands to define mode-specific abbrevs define global ones instead.")
+
+;; Names in directory that end in one of these
+;; are ignored in completion,
+;; making it more likely you will get a unique match.
+(setq completion-ignored-extensions
+ (if (eq system-type 'vax-vms)
+ '(".obj" ".elc" ".exe" ".bin" ".lbin"
+ ".dvi" ".toc" ".log" ".aux"
+ ".lof" ".brn" ".rnt" ".mem" ".lni" ".lis"
+ ".olb" ".tlb" ".mlb" ".hlb" ".glo" ".idx" ".lot")
+ '(".o" ".elc" "~" ".bin" ".lbin" ".fasl"
+ ".dvi" ".toc" ".log" ".aux"
+ ".lof" ".blg" ".bbl" ".glo" ".idx" ".lot")))
+
+(defvar compile-command "make -k" "\
+*Last shell command used to do a compilation; default for next compilation.")
+
+(defvar dired-listing-switches "-al" "\
+*Switches passed to ls for Dired. MUST contain the `l' option.
+MUST NOT contain the `F, `s' or `i'' option.")
+
+(defconst lpr-switches nil "\
+*List of strings to pass as extra switch args to lpr when it is invoked.")
+
+(defvar tags-file-name nil "\
+*File name of tag table.
+To switch to a new tag table, setting this variable is sufficient.
+Use the `etags' program to make a tag table file.")
+
+(defconst shell-prompt-pattern "^[^#$%>]*[#$%>] *" "\
+*Regexp used by Newline command in shell mode to match subshell prompts.
+Anything from beginning of line up to the end of what this pattern matches
+is deemed to be prompt, and is not reexecuted.")
+
+(defconst ledit-save-files t "\
+*Non-nil means Ledit should save files before transferring to Lisp.")
+(defconst ledit-go-to-lisp-string "%?lisp" "\
+*Shell commands to execute to resume Lisp job.")
+(defconst ledit-go-to-liszt-string "%?liszt" "\
+*Shell commands to execute to resume Lisp compiler job.")
+
+(defconst display-time-day-and-date nil "\
+*Non-nil means M-x display-time should display day and date as well as time.")
+
+;;; Determine mode according to filename
+
+(defvar auto-mode-alist nil "\
+Alist of filename patterns vs corresponding major mode functions.
+Each element looks like (REGEXP . FUNCTION).
+Visiting a file whose name matches REGEXP causes FUNCTION to be called.")
+(setq auto-mode-alist (mapcar 'purecopy
+ '(("\\.text$" . text-mode)
+ ("\\.c$" . c-mode)
+ ("\\.h$" . c-mode)
+ ("\\.tex$" . TeX-mode)
+ ("\\.el$" . emacs-lisp-mode)
+ ("\\.scm$" . scheme-mode)
+ ("\\.l$" . lisp-mode)
+ ("\\.lisp$" . lisp-mode)
+ ("\\.f$" . fortran-mode)
+ ("\\.mss$" . scribe-mode)
+ ("\\.pl$" . prolog-mode)
+;;; Less common extensions come here
+;;; so more common ones above are found faster.
+ ("\\.TeX$" . TeX-mode)
+ ("\\.sty$" . LaTeX-mode)
+ ("\\.bbl$" . LaTeX-mode)
+ ("\\.bib$" . text-mode)
+ ("\\.article$" . text-mode)
+ ("\\.letter$" . text-mode)
+ ("\\.texinfo$" . texinfo-mode)
+ ("\\.texi$" . texinfo-mode)
+ ("\\.lsp$" . lisp-mode)
+ ("\\.prolog$" . prolog-mode)
+ ;; Mailer puts message to be edited in /tmp/Re.... or Message
+ ("^/tmp/Re" . text-mode)
+ ;; some news reader is reported to use this
+ ("^/tmp/fol/" . text-mode)
+ ("/Message[0-9]*$" . text-mode)
+ ("\\.y$" . c-mode)
+ ("\\.cc$" . c-mode)
+ ("\\.scm.[0-9]*$" . scheme-mode)
+ ;; .emacs following a directory delimiter
+ ;; in either Unix or VMS syntax.
+ ("[]>:/]\\..*emacs$" . emacs-lisp-mode)
+ ("\\.ml$" . lisp-mode))))
+
+(make-variable-buffer-local 'indent-tabs-mode)
+
+(defvar ctl-x-4-map (make-keymap) "\
+Keymap for subcommands of C-x 4")
+
+;; Reduce total amount of space we must allocate during this function
+;; that we will not need to keep permanently.
+(garbage-collect)
+
+;; Autoload random libraries.
+;; Alphabetical order by library name.
+
+(autoload 'add-change-log-entry "add-log"
+ "\
+Find change log file and add an entry for today.
+First arg (interactive prefix) non-nil means prompt for user name and site.
+Second arg is file name of change log.
+Optional third arg OTHER-WINDOW non-nil means visit in other window."
+ t)
+
+(define-key ctl-x-4-map "a" 'add-change-log-entry-other-window)
+
+(autoload 'add-change-log-entry-other-window "add-log"
+ "\
+Find change log file in other window, and add an entry for today."
+ t)
+
+(autoload '\` "backquote"
+ "\
+\(` FORM) Expands to a form that will generate FORM.
+FORM is `almost quoted' -- see backquote.el for a description."
+ nil t)
+
+(autoload 'byte-compile-file "bytecomp"
+ "\
+Compile a file of Lisp code named FILENAME into a file of byte code.
+The output file's name is made by appending \"c\" to the end of FILENAME."
+ t)
+
+(autoload 'byte-recompile-directory "bytecomp"
+ "\
+Recompile every .el file in DIRECTORY that needs recompilation.
+This is if a .elc file exists but is older than the .el file.
+If the .elc file does not exist, offer to compile the .el file
+only if a prefix argument has been specified."
+ t)
+
+(autoload 'batch-byte-compile "bytecomp"
+ "\
+Runs byte-compile-file on the files remaining on the command line.
+Must be used only with -batch, and kills emacs on completion.
+Each file will be processed even if an error occurred previously.
+For example, invoke \"emacs -batch -f batch-byte-compile $emacs/ ~/*.el\""
+ nil)
+
+(autoload 'calendar "cal"
+ "\
+Display three-month calendar in another window.
+The three months appear side by side, with the current month in the middle
+surrounded by the previous and next months. The cursor is put on today's date.
+
+An optional prefix argument ARG causes the calendar displayed to be
+ARG months in the future if ARG is positive or in the past if ARG is
+negative; in this case the cursor goes on the first day of the month.
+
+The Gregorian calendar is assumed.
+
+After preparing the calendar window, the hooks calendar-hook are run
+when the calendar is for the current month--that is, the was no prefix
+argument. If the calendar is for a future or past month--that is, there
+was a prefix argument--the hooks offset-calendar-hook are run. Thus, for
+example, setting calendar-hooks to 'star-date will cause today's date to be
+replaced by asterisks to highlight it in the window."
+ t)
+
+(autoload 'list-command-history "chistory"
+ "\
+List history of commands typed to minibuffer.
+The number of commands listed is controlled by list-command-history-max.
+Calls value of list-command-history-filter (if non-nil) on each history
+element to judge if that element should be excluded from the list.
+
+The buffer is left in Command History mode."
+ t)
+
+(autoload 'command-history-mode "chistory"
+ "\
+Major mode for examining commands from command-history.
+The number of commands listed is controlled by list-command-history-max.
+The command history is filtered by list-command-history-filter if non-nil.
+
+Like Emacs-Lisp Mode except that characters do not insert themselves and
+Digits provide prefix arguments. Tab does not indent.
+\\{command-history-map}
+Calls the value of command-history-hook if that is non-nil
+The Command History listing is recomputed each time this mode is
+invoked."
+ t)
+
+(autoload 'repeat-matching-complex-command "chistory"
+ "\
+Edit and re-evaluate complex command with name matching PATTERN.
+Matching occurrences are displayed, most recent first, until you
+select a form for evaluation. If PATTERN is empty (or nil), every form
+in the command history is offered. The form is placed in the minibuffer
+for editing and the result is evaluated."
+ t)
+
+
+(autoload 'common-lisp-indent-hook "cl-indent")
+
+(autoload 'compare-windows "compare-w"
+ "\
+Compare text in current window with text in next window.
+Compares the text starting at point in each window,
+moving over text in each one as far as they match."
+ t)
+
+(autoload 'compile "compile"
+ "\
+Compile the program including the current buffer. Default: run `make'.
+Runs COMMAND, a shell command, in a separate process asynchronously
+with output going to the buffer *compilation*.
+You can then use the command \\[next-error] to find the next error message
+and move to the source code that caused it."
+ t)
+
+(autoload 'grep "compile"
+ "\
+Run grep, with user-specified args, and collect output in a buffer.
+While grep runs asynchronously, you can use the \\[next-error] command
+to find the text that grep hits refer to."
+ t)
+
+(define-key ctl-x-map "`" 'next-error)
+
+(autoload 'next-error "compile"
+ "\
+Visit next compilation error message and corresponding source code.
+This operates on the output from the \\[compile] command.
+If all preparsed error messages have been processed,
+the error message buffer is checked for new ones.
+A non-nil argument (prefix arg, if interactive)
+means reparse the error message buffer and start at the first error."
+ t)
+
+(define-key esc-map "/" 'dabbrev-expand)
+
+(autoload 'dabbrev-expand "dabbrev"
+ "\
+Expand previous word \"dynamically\".
+Expands to the most recent, preceding word for which this is a prefix.
+If no suitable preceding word is found, words following point are considered.
+
+A positive prefix argument, N, says to take the Nth backward DISTINCT
+possibility. A negative argument says search forward. The variable
+dabbrev-backward-only may be used to limit the direction of search to
+backward if set non-nil.
+
+If the cursor has not moved from the end of the previous expansion and
+no argument is given, replace the previously-made expansion
+with the next possible expansion not yet tried."
+ t)
+
+(autoload 'debug "debug"
+ "\
+Enter debugger. Returns if user says \"continue\".
+Arguments are mainly for use when this is called
+ from the internals of the evaluator.
+You may call with no args, or you may
+ pass nil as the first arg and any other args you like.
+ In that case, the list of args after the first will
+ be printed into the backtrace buffer.")
+
+(autoload 'cancel-debug-on-entry "debug"
+ "\
+Undoes effect of debug-on-entry on FUNCTION."
+ t)
+
+(autoload 'debug-on-entry "debug"
+ "\
+Request FUNCTION to invoke debugger each time it is called.
+If the user continues, FUNCTION's execution proceeds.
+Works by modifying the definition of FUNCTION,
+which must be written in Lisp, not predefined.
+Use `cancel-debug-on-entry' to cancel the effect of this command.
+Redefining FUNCTION also does that."
+ t)
+
+(define-key ctl-x-map "d" 'dired)
+
+(autoload 'dired "dired"
+ "\
+\"Edit\" directory DIRNAME--delete, rename, print, etc. some files in it.
+Dired displays a list of files in DIRNAME.
+You can move around in it with the usual commands.
+You can flag files for deletion with C-d
+and then delete them by typing `x'.
+Type `h' after entering dired for more info."
+ t)
+
+(define-key ctl-x-4-map "d" 'dired-other-window)
+
+(autoload 'dired-other-window "dired"
+ "\
+\"Edit\" directory DIRNAME. Like \\[dired] but selects in another window."
+ t)
+
+(autoload 'dired-noselect "dired"
+ "\
+Like M-x dired but returns the dired buffer as value, does not select it.")
+
+(autoload 'dissociated-press "dissociate"
+ "\
+Dissociate the text of the current buffer.
+Output goes in buffer named *Dissociation*,
+which is redisplayed each time text is added to it.
+Every so often the user must say whether to continue.
+If ARG is positive, require ARG chars of continuity.
+If ARG is negative, require -ARG words of continuity.
+Default is 2."
+ t)
+
+(autoload 'doctor "doctor"
+ "\
+Switch to *doctor* buffer and start giving psychotherapy."
+ t)
+
+(autoload 'disassemble "disass"
+ "\
+Print disassembled code for OBJECT on (optional) STREAM.
+OBJECT can be a function name, lambda expression or any function object
+returned by SYMBOL-FUNCTION. If OBJECT is not already compiled, we will
+compile it (but not redefine it)."
+ t)
+
+(autoload 'electric-buffer-list "ebuff-menu"
+ "\
+Vaguely like ITS lunar select buffer;
+combining typeoutoid buffer listing with menuoid buffer selection.
+
+This pops up a buffer describing the set of emacs buffers.
+If the very next character typed is a space then the buffer list
+ window disappears.
+
+Otherwise, one may move around in the buffer list window, marking
+ buffers to be selected, saved or deleted.
+
+To exit and select a new buffer, type Space when the cursor is on the
+ appropriate line of the buffer-list window.
+
+Other commands are much like those of buffer-menu-mode.
+
+Calls value of electric-buffer-menu-mode-hook on entry if non-nil.
+
+\\{electric-buffer-menu-mode-map}"
+ t)
+
+
+(autoload 'electric-command-history "echistory"
+ "\
+Major mode for examining and redoing commands from command-history.
+The number of command listed is controlled by list-command-history-max.
+The command history is filtered by list-command-history-filter if non-nil.
+Combines typeout Command History list window with menu like selection
+of an expression from the history for re-evaluation in the *original* buffer.
+
+The history displayed is filtered by list-command-history-filter if non-nil.
+
+This pops up a window with the Command History listing. If the very
+next character typed is Space, the listing is killed and the previous
+window configuration is restored. Otherwise, you can browse in the
+Command History with Return moving down and Delete moving up, possibly
+selecting an expression to be redone with Space or quitting with `Q'.
+
+Like Emacs-Lisp Mode except that characters do not insert themselves and
+Tab and linefeed do not indent. Instead these commands are provided:
+Space or ! edit then evaluate current line in history inside
+ the ORIGINAL buffer which invoked this mode.
+ The previous window configuration is restored
+ unless the invoked command changes it.
+C-c C-c, C-], Q Quit and restore previous window configuration.
+LFD, RET Move to the next line in the history.
+DEL Move to the previous line in the history.
+? Provides a complete list of commands.
+
+Calls the value of electric-command-history-hook if that is non-nil
+The Command History listing is recomputed each time this mode is invoked."
+ t)
+
+(autoload 'edt-emulation-on "edt"
+ "\
+Begin emulating DEC's EDT editor.
+Certain keys are rebound; including nearly all keypad keys.
+Use \\[edt-emulation-off] to undo all rebindings except the keypad keys.
+Note that this function does not work if called directly from the .emacs file.
+Instead, the .emacs file should do (setq term-setup-hook 'edt-emulation-on)
+Then this function will be called at the time when it will work."
+ t)
+
+(autoload 'fortran-mode "fortran"
+ "\
+Major mode for editing fortran code.
+Tab indents the current fortran line correctly.
+`do' statements must not share a common `continue'.
+
+Type `;?' or `;\\[help-command]' to display a list of built-in abbrevs for Fortran keywords.
+
+Variables controlling indentation style and extra features:
+
+ comment-start
+ Normally nil in Fortran mode. If you want to use comments
+ starting with `!', set this to the string \"!\".
+ fortran-do-indent
+ Extra indentation within do blocks. (default 3)
+ fortran-if-indent
+ Extra indentation within if blocks. (default 3)
+ fortran-continuation-indent
+ Extra indentation appled to continuation statements. (default 5)
+ fortran-comment-line-column
+ Amount of indentation for text within full-line comments. (default 6)
+ fortran-comment-indent-style
+ nil means don't change indentation of text in full-line comments,
+ fixed means indent that text at column fortran-comment-line-column
+ relative means indent at fortran-comment-line-column beyond the
+ indentation for a line of code.
+ Default value is fixed.
+ fortran-comment-indent-char
+ Character to be inserted instead of space for full-line comment
+ indentation. (default is a space)
+ fortran-minimum-statement-indent
+ Minimum indentation for fortran statements. (default 6)
+ fortran-line-number-indent
+ Maximum indentation for line numbers. A line number will get
+ less than this much indentation if necessary to avoid reaching
+ column 5. (default 1)
+ fortran-check-all-num-for-matching-do
+ Non-nil causes all numbered lines to be treated as possible 'continue'
+ statements. (default nil)
+ fortran-continuation-char
+ character to be inserted in column 5 of a continuation line.
+ (default $)
+ fortran-comment-region
+ String inserted by \\[fortran-comment-region] at start of each line in
+ region. (default \"c$$$\")
+ fortran-electric-line-number
+ Non-nil causes line number digits to be moved to the correct column
+ as typed. (default t)
+ fortran-startup-message
+ Set to nil to inhibit message first time fortran-mode is used.
+
+Turning on Fortran mode calls the value of the variable fortran-mode-hook
+with no args, if that value is non-nil.
+\\{fortran-mode-map}"
+ t)
+
+(autoload 'ftp-find-file "ftp"
+ "\
+FTP to HOST to get FILE, logging in as USER with password PASSWORD.
+Interactively, HOST and FILE are specified by reading a string with
+ a colon character separating the host from the filename.
+USER and PASSWORD are defaulted from the values used when
+ last ftping from HOST (unless password-remembering is disabled).
+ Supply a password of the symbol `t' to override this default
+ (interactively, this is done by giving a prefix arg)"
+ t)
+
+(autoload 'ftp-write-file "ftp"
+ "\
+FTP to HOST to write FILE, logging in as USER with password PASSWORD.
+Interactively, HOST and FILE are specified by reading a string with colon
+separating the host from the filename.
+USER and PASSWORD are defaulted from the values used when
+ last ftping from HOST (unless password-remembering is disabled).
+ Supply a password of the symbol `t' to override this default
+ (interactively, this is done by giving a prefix arg)"
+ t)
+
+(autoload 'gdb "gdb"
+ "\
+Run gdb on program FILE in buffer *gdb-FILE*.
+The directory containing FILE becomes the initial working directory
+and source-file directory for GDB. If you wish to change this, use
+the GDB commands `cd DIR' and `directory'."
+ t)
+
+(autoload 'set-gosmacs-bindings "gosmacs"
+ "\
+Rebind some keys globally to make GNU Emacs resemble Gosling Emacs.
+Use \\[set-gnu-bindings] to restore previous global bindings."
+ t)
+
+(autoload 'hanoi "hanoi"
+ "\
+Towers of Hanoi diversion. Argument is number of rings."
+ t)
+
+(autoload 'Helper-help "helper"
+ "\
+Provide help for current mode."
+ t)
+
+(autoload 'Helper-describe-bindings "helper"
+ "\
+Describe local key bindings of current mode."
+ t)
+
+(autoload 'info "info"
+ "\
+Enter Info, the documentation browser."
+ t)
+
+(autoload 'Info-tagify "informat"
+ "\
+Create or update Info-file tag table in current buffer."
+ t)
+
+(autoload 'Info-validate "informat"
+ "\
+Check current buffer for validity as an Info file.
+Check that every node pointer points to an existing node."
+ t)
+
+(autoload 'Info-split "informat"
+ "\
+Split an info file into an indirect file plus bounded-size subfiles.
+Each subfile will be up to 50000 characters plus one node.
+
+To use this command, first visit a large Info file that has a tag table.
+The buffer is modified into a (small) indirect info file
+which should be saved in place of the original visited file.
+
+The subfiles are written in the same directory the original file is in,
+with names generated by appending `-' and a number to the original file name.
+
+The indirect file still functions as an Info file, but it contains
+just the tag table and a directory of subfiles."
+ t)
+
+(autoload 'batch-info-validate "informat"
+ "\
+Runs Info-validate on the files remaining on the command line.
+Must be used only with -batch, and kills emacs on completion.
+Each file will be processed even if an error occurred previously.
+For example, invoke \"emacs -batch -f batch-info-validate $info/ ~/*.info\""
+ nil)
+
+(autoload 'ledit-mode "ledit"
+ "\
+Major mode for editing text and stuffing it to a Lisp job.
+Like Lisp mode, plus these special commands:
+ M-C-d -- record defun at or after point
+ for later transmission to Lisp job.
+ M-C-r -- record region for later transmission to Lisp job.
+ C-x z -- transfer to Lisp job and transmit saved text.
+ M-C-c -- transfer to Liszt (Lisp compiler) job
+ and transmit saved text.
+\\{ledit-mode-map}
+To make Lisp mode automatically change to Ledit mode,
+do (setq lisp-mode-hook 'ledit-from-lisp-mode)"
+ t)
+
+(autoload 'ledit-from-lisp-mode "ledit")
+
+(autoload 'lpr-buffer "lpr"
+ "\
+Print buffer contents as with Unix command `lpr'.
+`lpr-switches' is a list of extra switches (strings) to pass to lpr."
+ t)
+
+(autoload 'print-buffer "lpr"
+ "\
+Print buffer contents as with Unix command `lpr -p'.
+`lpr-switches' is a list of extra switches (strings) to pass to lpr."
+ t)
+
+(autoload 'lpr-region "lpr"
+ "\
+Print region contents as with Unix command `lpr'.
+`lpr-switches' is a list of extra switches (strings) to pass to lpr."
+ t)
+
+(autoload 'print-region "lpr"
+ "\
+Print region contents as with Unix command `lpr -p'.
+`lpr-switches' is a list of extra switches (strings) to pass to lpr."
+ t)
+
+(autoload 'insert-kbd-macro "macros"
+ "\
+Insert in buffer the definition of kbd macro NAME, as Lisp code.
+Second argument KEYS non-nil means also record the keys it is on.
+ (This is the prefix argument, when calling interactively.)
+
+This Lisp code will, when executed, define the kbd macro with the
+same definition it has now. If you say to record the keys,
+the Lisp code will also rebind those keys to the macro.
+Only global key bindings are recorded since executing this Lisp code
+always makes global bindings.
+
+To save a kbd macro, visit a file of Lisp code such as your ~/.emacs,
+use this command, and then save the file."
+ t)
+
+(define-key ctl-x-map "q" 'kbd-macro-query)
+
+(autoload 'kbd-macro-query "macros"
+ "\
+Query user during kbd macro execution.
+With prefix argument, enters recursive edit,
+ reading keyboard commands even within a kbd macro.
+ You can give different commands each time the macro executes.
+Without prefix argument, reads a character. Your options are:
+ Space -- execute the rest of the macro.
+ DEL -- skip the rest of the macro; start next repetition.
+ C-d -- skip rest of the macro and don't repeat it any more.
+ C-r -- enter a recursive edit, then on exit ask again for a character
+ C-l -- redisplay screen and ask again."
+ t)
+
+(autoload 'name-last-kbd-macro "macros"
+ "\
+Assign a name to the last keyboard macro defined.
+One arg, a symbol, which is the name to define.
+The symbol's function definition becomes the keyboard macro string.
+Such a \"function\" cannot be called from Lisp, but it is a valid command
+definition for the editor command loop."
+ t)
+
+(autoload 'make-command-summary "makesum"
+ "\
+Make a summary of current key bindings in the buffer *Summary*.
+Previous contents of that buffer are killed first."
+ t)
+
+(autoload 'define-mail-alias "mailalias"
+ "\
+Define NAME as a mail-alias that translates to DEFINITION."
+ t)
+
+(autoload 'manual-entry "man"
+ "\
+Display the Unix manual entry for TOPIC.
+TOPIC is either the title of the entry, or has the form TITLE(SECTION)
+where SECTION is the desired section of the manual, as in `tty(4)'."
+ t)
+
+(autoload 'mh-rmail "mh-e"
+ "\
+Inc(orporate) new mail (no arg) or scan a MH mail box (arg given).
+This front end uses the MH mail system, which uses different conventions
+from the usual mail system."
+ t)
+
+(autoload 'mh-smail "mh-e"
+ "\
+Send mail using the MH mail system."
+ t)
+
+(autoload 'convert-mocklisp-buffer "mlconvert"
+ "\
+Convert buffer of Mocklisp code to real Lisp that GNU Emacs can run."
+ t)
+
+(autoload 'modula-2-mode "modula2"
+ "\
+This is a mode intended to support program development in Modula-2.
+All control constructs of Modula-2 can be reached by typing
+Control-C followed by the first character of the construct.
+\\{m2-mode-map}
+ Control-c b begin Control-c c case
+ Control-c d definition Control-c e else
+ Control-c f for Control-c h header
+ Control-c i if Control-c m module
+ Control-c l loop Control-c o or
+ Control-c p procedure Control-c Control-w with
+ Control-c r record Control-c s stdio
+ Control-c t type Control-c u until
+ Control-c v var Control-c w while
+ Control-c x export Control-c y import
+ Control-c { begin-comment Control-c } end-comment
+ Control-c Control-z suspend-emacs Control-c Control-t toggle
+ Control-c Control-c compile Control-x ` next-error
+ Control-c Control-l link
+
+ m2-indent controls the number of spaces for each indentation.
+ m2-compile-command holds the command to compile a Modula-2 program.
+ m2-link-command holds the command to link a Modula-2 program."
+ t)
+
+(setq disabled-command-hook 'disabled-command-hook)
+
+(autoload 'disabled-command-hook "novice")
+(autoload 'enable-command "novice"
+ "\
+Allow COMMAND to be executed without special confirmation from now on.
+The user's .emacs file is altered so that this will apply
+to future sessions." t)
+
+(autoload 'disable-command "novice"
+ "\
+Require special confirmation to execute COMMAND from now on.
+The user's .emacs file is altered so that this will apply
+to future sessions." t)
+
+(autoload 'nroff-mode "nroff-mode"
+ "\
+Major mode for editing text intended for nroff to format.
+\\{nroff-mode-map}
+Turning on Nroff mode runs text-mode-hook, then nroff-mode-hook.
+Also, try nroff-electric-mode, for automatically inserting
+closing requests for requests that are used in matched pairs."
+ t)
+
+(autoload 'list-options "options"
+ "\
+Display a list of Emacs user options, with values and documentation."
+ t)
+
+(autoload 'edit-options "options"
+ "\
+Edit a list of Emacs user option values.
+Selects a buffer containing such a list,
+in which there are commands to set the option values.
+Type \\[describe-mode] in that buffer for a list of commands."
+ t)
+
+(autoload 'outline-mode "outline"
+ "\
+Set major mode for editing outlines with selective display.
+Headings are lines which start with asterisks: one for major headings,
+two for subheadings, etc. Lines not starting with asterisks are body lines.
+
+Body text or subheadings under a heading can be made temporarily
+invisible, or visible again. Invisible lines are attached to the end
+of the heading, so they move with it, if the line is killed and yanked
+back. A heading with text hidden under it is marked with an ellipsis (...).
+
+Commands:
+C-c C-n outline-next-visible-heading move by visible headings
+C-c C-p outline-previous-visible-heading
+C-c C-f outline-forward-same-level similar but skip subheadings
+C-c C-b outline-backward-same-level
+C-c C-u outline-up-heading move from subheading to heading
+
+Meta-x hide-body make all text invisible (not headings).
+Meta-x show-all make everything in buffer visible.
+
+The remaining commands are used when point is on a heading line.
+They apply to some of the body or subheadings of that heading.
+C-c C-h hide-subtree make body and subheadings invisible.
+C-c C-s show-subtree make body and subheadings visible.
+C-c C-i show-children make direct subheadings visible.
+ No effect on body, or subheadings 2 or more levels down.
+ With arg N, affects subheadings N levels down.
+M-x hide-entry make immediately following body invisible.
+M-x show-entry make it visible.
+M-x hide-leaves make body under heading and under its subheadings invisible.
+ The subheadings remain visible.
+M-x show-branches make all subheadings at all levels visible.
+
+The variable outline-regexp can be changed to control what is a heading.
+A line is a heading if outline-regexp matches something at the
+beginning of the line. The longer the match, the deeper the level.
+
+Turning on outline mode calls the value of text-mode-hook and then of
+outline-mode-hook, if they are non-nil."
+ t)
+
+(autoload 'edit-picture "picture"
+ "\
+Switch to Picture mode, in which a quarter-plane screen model is used.
+Printing characters replace instead of inserting themselves with motion
+afterwards settable by these commands:
+ C-c < Move left after insertion.
+ C-c > Move right after insertion.
+ C-c ^ Move up after insertion.
+ C-c . Move down after insertion.
+ C-c ` Move northwest (nw) after insertion.
+ C-c ' Move northeast (ne) after insertion.
+ C-c / Move southwest (sw) after insertion.
+ C-c \\ Move southeast (se) after insertion.
+The current direction is displayed in the mode line. The initial
+direction is right. Whitespace is inserted and tabs are changed to
+spaces when required by movement. You can move around in the buffer
+with these commands:
+ C-p Move vertically to SAME column in previous line.
+ C-n Move vertically to SAME column in next line.
+ C-e Move to column following last non-whitespace character.
+ C-f Move right inserting spaces if required.
+ C-b Move left changing tabs to spaces if required.
+ C-c C-f Move in direction of current picture motion.
+ C-c C-b Move in opposite direction of current picture motion.
+ Return Move to beginning of next line.
+You can edit tabular text with these commands:
+ M-Tab Move to column beneath (or at) next interesting charecter.
+ `Indents' relative to a previous line.
+ Tab Move to next stop in tab stop list.
+ C-c Tab Set tab stops according to context of this line.
+ With ARG resets tab stops to default (global) value.
+ See also documentation of variable picture-tab-chars
+ which defines \"interesting character\". You can manually
+ change the tab stop list with command \\[edit-tab-stops].
+You can manipulate text with these commands:
+ C-d Clear (replace) ARG columns after point without moving.
+ C-c C-d Delete char at point - the command normally assigned to C-d.
+ Delete Clear (replace) ARG columns before point, moving back over them.
+ C-k Clear ARG lines, advancing over them. The cleared
+ text is saved in the kill ring.
+ C-o Open blank line(s) beneath current line.
+You can manipulate rectangles with these commands:
+ C-c C-k Clear (or kill) a rectangle and save it.
+ C-c C-w Like C-c C-k except rectangle is saved in named register.
+ C-c C-y Overlay (or insert) currently saved rectangle at point.
+ C-c C-x Like C-c C-y except rectangle is taken from named register.
+ \\[copy-rectangle-to-register] Copies a rectangle to a register.
+ \\[advertised-undo] Can undo effects of rectangle overlay commands
+ commands if invoked soon enough.
+You can return to the previous mode with:
+ C-c C-c Which also strips trailing whitespace from every line.
+ Stripping is suppressed by supplying an argument.
+
+Entry to this mode calls the value of edit-picture-hook if non-nil.
+
+Note that Picture mode commands will work outside of Picture mode, but
+they are not defaultly assigned to keys."
+ t)
+
+(fset 'picture-mode 'edit-picture)
+
+(autoload 'prolog-mode "prolog"
+ "\
+Major mode for editing Prolog code for Prologs.
+Blank lines and `%%...' separate paragraphs. `%'s start comments.
+Commands:
+\\{prolog-mode-map}
+Entry to this mode calls the value of prolog-mode-hook
+if that value is non-nil."
+ t)
+
+(autoload 'run-prolog "prolog"
+ "\
+Run an inferior Prolog process, input and output via buffer *prolog*."
+ t)
+
+
+(autoload 'clear-rectangle "rect"
+ "\
+Blank out rectangle with corners at point and mark.
+The text previously in the region is overwritten by the blanks."
+ t)
+
+(autoload 'delete-rectangle "rect"
+ "\
+Delete (don't save) text in rectangle with point and mark as corners.
+The same range of columns is deleted in each line
+starting with the line where the region begins
+and ending with the line where the region ends."
+ t)
+
+(autoload 'delete-extract-rectangle "rect"
+ "\
+Return and delete contents of rectangle with corners at START and END.
+Value is list of strings, one for each line of the rectangle.")
+
+(autoload 'extract-rectangle "rect"
+ "\
+Return contents of rectangle with corners at START and END.
+Value is list of strings, one for each line of the rectangle.")
+
+(autoload 'insert-rectangle "rect"
+ "\
+Insert text of RECTANGLE with upper left corner at point.
+RECTANGLE's first line is inserted at point,
+its second line is inserted at a point vertically under point, etc.
+RECTANGLE should be a list of strings.")
+
+(autoload 'kill-rectangle "rect"
+ "\
+Delete rectangle with corners at point and mark; save as last killed one.
+Calling from program, supply two args START and END, buffer positions.
+But in programs you might prefer to use delete-extract-rectangle."
+ t)
+
+(autoload 'open-rectangle "rect"
+ "\
+Blank out rectangle with corners at point and mark, shifting text right.
+The text previously in the region is not overwritten by the blanks,
+but insted winds up to the right of the rectangle."
+ t)
+
+(autoload 'yank-rectangle "rect"
+ "\
+Yank the last killed rectangle with upper left corner at point."
+ t)
+
+(autoload 'rnews "rnews"
+ "\
+Read USENET news for groups for which you are a member and add or
+delete groups.
+You can reply to articles posted and send articles to any group.
+
+Type \\[describe-mode] once reading news to get a list of rnews commands."
+ t)
+
+(autoload 'news-post-news "rnewspost"
+ "\
+Begin editing a new USENET news article to be posted.
+Type \\[describe-mode] once editing the article to get a list of commands."
+ t)
+(fset 'sendnews 'news-post-news)
+(fset 'postnews 'news-post-news)
+
+(autoload 'rmail "rmail"
+ "\
+Read and edit incoming mail.
+Moves messages into file named by rmail-file-name (a babyl format file)
+ and edits that file in RMAIL Mode.
+Type \\[describe-mode] once editing that file, for a list of RMAIL commands.
+
+May be called with filename as argument;
+then performs rmail editing on that file,
+but does not copy any new mail into the file."
+ t)
+
+(autoload 'rmail-input "rmail"
+ "\
+Run RMAIL on file FILENAME."
+ t)
+
+(defconst rmail-dont-reply-to-names nil "\
+*A regular expression specifying names to prune in replying to messages.
+nil means don't reply to yourself.")
+
+(defvar rmail-default-dont-reply-to-names "info-" "\
+A regular expression specifying part of the value of the default value of
+the variable `rmail-dont-reply-to-names', for when the user does not set
+`rmail-dont-reply-to-names' explicitly. (The other part of the default
+value is the user's name.)
+It is useful to set this variable in the site customisation file.")
+
+(defconst rmail-primary-inbox-list nil "\
+*List of files which are inboxes for user's primary mail file ~/RMAIL.
+`nil' means the default, which is (\"~/mbox\" \"/usr/spool/mail/$USER\")
+(the second name varies depending on the operating system).")
+
+(defconst rmail-ignored-headers "^via:\\|^mail-from:\\|^origin:\\|^status:\\|^received:\\|^[a-z-]*message-id:\\|^summary-line:\\|^errors-to:" "\
+*Gubbish header fields one would rather not see.")
+
+(defvar rmail-delete-after-output nil "\
+*Non-nil means automatically delete a message that is copied to a file.")
+
+;;; Others are in paths.el.
+
+(autoload 'run-scheme "xscheme"
+ "\
+Run an inferior Scheme process.
+Output goes to the buffer `*scheme*'.
+With argument, asks for a command line."
+ t)
+
+(autoload 'scheme-mode "scheme"
+ "\
+Major mode for editing Scheme code.
+Editing commands are similar to those of lisp-mode.
+
+In addition, if an inferior Scheme process is running, some additional
+commands will be defined, for evaluating expressions and controlling
+the interpreter, and the state of the process will be displayed in the
+modeline of all Scheme buffers. The names of commands that interact
+with the Scheme process start with \"xscheme-\". For more information
+see the documentation for xscheme-interaction-mode.
+
+Commands:
+Delete converts tabs to spaces as it moves back.
+Blank lines separate paragraphs. Semicolons start comments.
+\\{scheme-mode-map}
+Entry to this mode calls the value of scheme-mode-hook
+if that value is non-nil."
+ t)
+
+(autoload 'scribe-mode "scribe"
+ "\
+Major mode for editing files of Scribe (a text formatter) source.
+Scribe-mode is similar text-mode, with a few extra commands added.
+\\{scribe-mode-map}
+
+Interesting variables:
+
+scribe-fancy-paragraphs
+ Non-nil makes Scribe mode use a different style of paragraph separation.
+
+scribe-electric-quote
+ Non-nil makes insert of double quote use `` or '' depending on context.
+
+scribe-electric-parenthesis
+ Non-nil makes an open-parenthesis char (one of `([<{')
+ automatically insert its close if typed after an @Command form."
+ t)
+
+;; Useful to set in site-init.el
+(defconst send-mail-function 'sendmail-send-it "\
+Function to call to send the current buffer as mail.
+The headers are delimited by a string found in mail-header-separator.")
+
+(defconst mail-self-blind nil "\
+*Non-nil means insert BCC to self in messages to be sent.
+This is done when the message is initialized,
+so you can remove or alter the BCC field to override the default.")
+
+(defconst mail-interactive nil "\
+*Non-nil means when sending a message wait for and display errors.
+nil means let mailer mail back a message to report errors.")
+
+(defconst mail-yank-ignored-headers "^via:\\|^mail-from:\\|^origin:\\|^status:\\|^remailed\\|^received:\\|^[a-z-]*message-id:\\|^summary-line:\\|^to:\\|^cc:\\|^subject:\\|^in-reply-to:\\|^return-path:" "\
+Delete these headers from old message when it's inserted in a reply.")
+
+(defconst mail-header-separator "--text follows this line--" "\
+*Line used to separate headers from text in messages being composed.")
+
+(defconst mail-archive-file-name nil "\
+*Name of file to write all outgoing messages in, or nil for none.")
+
+(defvar mail-aliases t "\
+Alias of mail address aliases,
+or t meaning should be initialized from .mailrc.")
+
+(autoload 'mail-other-window "sendmail"
+ "\
+Like `mail' command, but display mail buffer in another window."
+ t)
+
+(autoload 'mail "sendmail"
+ "\
+Edit a message to be sent. Argument means resume editing (don't erase).
+Returns with message buffer selected; value t if message freshly initialized.
+While editing message, type C-c C-c to send the message and exit.
+
+Various special commands starting with C-c are available in sendmail mode
+to move to message header fields:
+\\{mail-mode-map}
+
+If mail-self-blind is non-nil, a BCC to yourself is inserted
+when the message is initialized.
+
+If mail-default-reply-to is non-nil, it should be an address (a string);
+a Reply-to: field with that address is inserted.
+
+If mail-archive-file-name is non-nil, an FCC field with that file name
+is inserted.
+
+If mail-setup-hook is bound, its value is called with no arguments
+after the message is initialized. It can add more default fields.
+
+When calling from a program, the second through fifth arguments
+ TO, SUBJECT, IN-REPLY-TO and CC specify if non-nil
+ the initial contents of those header fields.
+ These arguments should not have final newlines.
+The sixth argument REPLYBUFFER is a buffer whose contents
+ should be yanked if the user types C-c C-y."
+ t)
+
+(define-key ctl-x-4-map "m" 'mail-other-window)
+(define-key ctl-x-map "m" 'mail)
+
+;; used in mail-utils
+(defvar mail-use-rfc822 nil "\
+*If non-nil, use a full, hairy RFC822 parser on mail addresses.
+Otherwise, (the default) use a smaller, somewhat faster and
+often-correct parser.")
+
+
+(autoload 'server-start "server"
+ "\
+Allow this Emacs process to be a server for client processes.
+This starts a server communications subprocess through which
+client \"editors\" can send your editing commands to this Emacs job.
+To use the server, set up the program `etc/emacsclient' in the
+Emacs distribution as your standard \"editor\".
+
+Prefix arg means just kill any existing server communications subprocess."
+ t)
+
+(autoload 'run-lisp "shell"
+ "\
+Run an inferior Lisp process, input and output via buffer *lisp*."
+ t)
+
+(autoload 'shell "shell"
+ "\
+Run an inferior shell, with I/O through buffer *shell*.
+If buffer exists but shell process is not running, make new shell.
+Program used comes from variable explicit-shell-file-name,
+ or (if that is nil) from the ESHELL environment variable,
+ or else from SHELL if there is no ESHELL.
+If a file ~/.emacs_SHELLNAME exists, it is given as initial input
+ (Note that this may lose due to a timing error if the shell
+ discards input when it starts up.)
+The buffer is put in shell-mode, giving commands for sending input
+and controlling the subjobs of the shell. See shell-mode.
+See also variable shell-prompt-pattern.
+
+The shell file name (sans directories) is used to make a symbol name
+such as `explicit-csh-arguments'. If that symbol is a variable,
+its value is used as a list of arguments when invoking the shell.
+Otherwise, one argument `-i' is passed to the shell.
+
+Note that many people's .cshrc files unconditionally clear the prompt.
+If yours does, you will probably want to change it."
+ t)
+
+(autoload 'sort-lines "sort"
+ "\
+Sort lines in region alphabetically; argument means descending order.
+Called from a program, there are three arguments:
+REVERSE (non-nil means reverse order), BEG and END (region to sort)."
+ t)
+
+(autoload 'sort-paragraphs "sort"
+ "\
+Sort paragraphs in region alphabetically; argument means descending order.
+Called from a program, there are three arguments:
+REVERSE (non-nil means reverse order), BEG and END (region to sort)."
+ t)
+
+(autoload 'sort-pages "sort"
+ "\
+Sort pages in region alphabetically; argument means descending order.
+Called from a program, there are three arguments:
+REVERSE (non-nil means reverse order), BEG and END (region to sort)."
+ t)
+
+(autoload 'sort-numeric-fields "sort"
+ "\
+Sort lines in region numerically by the ARGth field of each line.
+Fields are separated by whitespace and numbered from 1 up.
+Specified field must contain a number in each line of the region.
+With a negative arg, sorts by the -ARG'th field, in reverse order.
+Called from a program, there are three arguments:
+FIELD, BEG and END. BEG and END specify region to sort."
+ t)
+
+(autoload 'sort-fields "sort"
+ "\
+Sort lines in region lexicographically by the ARGth field of each line.
+Fields are separated by whitespace and numbered from 1 up.
+With a negative arg, sorts by the -ARG'th field, in reverse order.
+Called from a program, there are three arguments:
+FIELD, BEG and END. BEG and END specify region to sort."
+ t)
+
+(autoload 'sort-columns "sort"
+ "\
+Sort lines in region alphabetically by a certain range of columns.
+For the purpose of this command, the region includes
+the entire line that point is in and the entire line the mark is in.
+The column positions of point and mark bound the range of columns to sort on.
+A prefix argument means sort into reverse order.
+
+Note that sort-columns uses the sort utility program and therefore
+cannot work on text containing TAB characters. Use M-x untabify
+to convert tabs to spaces before sorting."
+ t)
+
+(autoload 'sort-regexp-fields "sort"
+ "\
+Sort the region lexicographically as specifed by RECORD-REGEXP and KEY.
+RECORD-REGEXP specifies the textual units which should be sorted.
+ For example, to sort lines RECORD-REGEXP would be \"^.*$\"
+KEY specifies the part of each record (ie each match for RECORD-REGEXP)
+ is to be used for sorting.
+ If it is \"\\digit\" then the digit'th \"\\(...\\)\" match field from
+ RECORD-REGEXP is used.
+ If it is \"\\&\" then the whole record is used.
+ Otherwise, it is a regular-expression for which to search within the record.
+If a match for KEY is not found within a record then that record is ignored.
+
+With a negative prefix arg sorts in reverse order.
+
+For example: to sort lines in the region by the first word on each line
+ starting with the letter \"f\",
+ RECORD-REGEXP would be \"^.*$\" and KEY \"\\<f\\w*\\>\""
+ t)
+
+
+(autoload 'spell-buffer "spell"
+ "\
+Check spelling of every word in the buffer.
+For each incorrect word, you are asked for the correct spelling
+and then put into a query-replace to fix some or all occurrences.
+If you do not want to change a word, just give the same word
+as its \"correct\" spelling; then the query replace is skipped."
+ t)
+
+(autoload 'spell-region "spell"
+ "\
+Like spell-buffer but applies only to region.
+From program, applies from START to END."
+ t)
+
+(define-key esc-map "$" 'spell-word)
+(autoload 'spell-word "spell"
+ "\
+Check spelling of word at or before point.
+If it is not correct, ask user for the correct spelling
+and query-replace the entire buffer to substitute it."
+ t)
+
+(autoload 'spell-string "spell"
+ "\
+Check spelling of string supplied as argument."
+ t)
+
+(autoload 'untabify "tabify"
+ "\
+Convert all tabs in region to multiple spaces, preserving columns.
+The variable tab-width controls the action."
+ t)
+
+(autoload 'tabify "tabify"
+ "\
+Convert multiple spaces in region to tabs when possible.
+A group of spaces is partially replaced by tabs
+when this can be done without changing the column they end at.
+The variable tab-width controls the action."
+ t)
+
+(define-key esc-map "." 'find-tag)
+
+(autoload 'find-tag "tags"
+ "\
+Find tag (in current tag table) whose name contains TAGNAME.
+ Selects the buffer that the tag is contained in
+and puts point at its definition.
+ If TAGNAME is a null string, the expression in the buffer
+around or before point is used as the tag name.
+ If second arg NEXT is non-nil (interactively, with prefix arg),
+searches for the next tag in the tag table
+that matches the tagname used in the previous find-tag.
+
+See documentation of variable tags-file-name."
+ t)
+
+(define-key ctl-x-4-map "." 'find-tag-other-window)
+
+(autoload 'find-tag-other-window "tags"
+ "\
+Find tag (in current tag table) whose name contains TAGNAME.
+ Selects the buffer that the tag is contained in in another window
+and puts point at its definition.
+ If TAGNAME is a null string, the expression in the buffer
+around or before point is used as the tag name.
+ If second arg NEXT is non-nil (interactively, with prefix arg),
+searches for the next tag in the tag table
+that matches the tagname used in the previous find-tag.
+
+See documentation of variable tags-file-name."
+ t)
+
+(autoload 'list-tags "tags"
+ "\
+Display list of tags in file FILE.
+FILE should not contain a directory spec
+unless it has one in the tag table."
+ t)
+
+(autoload 'next-file "tags"
+ "\
+Select next file among files in current tag table.
+Non-nil argument (prefix arg, if interactive)
+initializes to the beginning of the list of files in the tag table."
+ t)
+
+(autoload 'tags-apropos "tags"
+ "\
+Display list of all tags in tag table REGEXP matches."
+ t)
+
+(define-key esc-map "," 'tags-loop-continue)
+(autoload 'tags-loop-continue "tags"
+ "\
+Continue last \\[tags-search] or \\[tags-query-replace] command.
+Used noninteractively with non-nil argument
+to begin such a command. See variable tags-loop-form."
+ t)
+
+(autoload 'tag-table-files "tags"
+ "\
+Return a list of files in the current tag table.
+File names returned are absolute.")
+
+(autoload 'tags-query-replace "tags"
+ "\
+Query-replace-regexp FROM with TO through all files listed in tag table.
+Third arg DELIMITED (prefix arg) means replace only word-delimited matches.
+If you exit (C-G or ESC), you can resume the query-replace
+with the command \\[tags-loop-continue].
+
+See documentation of variable tags-file-name."
+ t)
+
+(autoload 'tags-search "tags"
+ "\
+Search through all files listed in tag table for match for REGEXP.
+Stops when a match is found.
+To continue searching for next match, use command \\[tags-loop-continue].
+
+See documentation of variable tags-file-name."
+ t)
+
+(autoload 'visit-tags-table "tags"
+ "\
+Tell tags commands to use tag table file FILE.
+FILE should be the name of a file created with the `etags' program.
+A directory name is ok too; it means file TAGS in that directory."
+ t)
+
+(autoload 'telnet "telnet"
+ "\
+Open a network login connection to host named HOST (a string).
+Communication with HOST is recorded in a buffer *HOST-telnet*.
+Normally input is edited in Emacs and sent a line at a time."
+ t)
+
+(autoload 'terminal-emulator "terminal"
+ "\
+Under a display-terminal emulator in BUFFER, run PROGRAM on arguments ARGS.
+ARGS is a list of argument-strings. Remaining arguments are WIDTH and HEIGHT.
+BUFFER's contents are made an image of the display generated by that program,
+and any input typed when BUFFER is the current Emacs buffer is sent to that
+program an keyboard input.
+
+Interactively, BUFFER defaults to \"*terminal*\" and PROGRAM and ARGS
+are parsed from an input-string using your usual shell.
+WIDTH and HEIGHT are determined from the size of the current window
+-- WIDTH will be one less than the window's width, HEIGHT will be its height.
+
+To switch buffers and leave the emulator, or to give commands
+to the emulator itself (as opposed to the program running under it),
+type Control-^. The following character is an emulator command.
+Type Control-^ twice to send it to the subprogram.
+This escape character may be changed using the variable `terminal-escape-char'.
+
+`Meta' characters may not currently be sent through the terminal emulator.
+
+Here is a list of some of the variables which control the behaviour
+of the emulator -- see their documentation for more information:
+terminal-escape-char, terminal-scrolling, terminal-more-processing,
+terminal-redisplay-interval.
+
+This function calls the value of terminal-mode-hook if that exists
+and is non-nil after the terminal buffer has been set up and the
+subprocess started.
+
+Presently with `termcap' only; if somebody sends us code to make this
+work with `terminfo' we will try to use it."
+ t)
+
+(autoload 'latex-mode "tex-mode"
+ "\
+Major mode for editing files of input for LaTeX.
+Makes $ and } display the characters they match.
+Makes \" insert `` when it seems to be the beginning of a quotation,
+and '' when it appears to be the end; it inserts \" only after a \\.
+
+Use \\[TeX-region] to run LaTeX on the current region, plus the preamble
+copied from the top of the file (containing \\documentstyle, etc.),
+running LaTeX under a special subshell. \\[TeX-buffer] does the whole buffer.
+\\[TeX-print] prints the .dvi file made by either of these.
+
+Use \\[validate-TeX-buffer] to check buffer for paragraphs containing
+mismatched $'s or braces.
+
+Special commands:
+\\{TeX-mode-map}
+
+Mode variables:
+TeX-directory
+ Directory in which to create temporary files for TeX jobs
+ run by \\[TeX-region] or \\[TeX-buffer].
+TeX-dvi-print-command
+ Command string used by \\[TeX-print] to print a .dvi file.
+TeX-show-queue-command
+ Command string used by \\[TeX-show-print-queue] to show the print
+ queue that \\[TeX-print] put your job on.
+
+Entering LaTeX mode calls the value of text-mode-hook,
+then the value of TeX-mode-hook, and then the value
+of LaTeX-mode-hook."
+ t)
+
+(autoload 'plain-tex-mode "tex-mode"
+ "\
+Major mode for editing files of input for plain TeX.
+Makes $ and } display the characters they match.
+Makes \" insert `` when it seems to be the beginning of a quotation,
+and '' when it appears to be the end; it inserts \" only after a \\.
+
+Use \\[TeX-region] to run TeX on the current region, plus a \"header\"
+copied from the top of the file (containing macro definitions, etc.),
+running TeX under a special subshell. \\[TeX-buffer] does the whole buffer.
+\\[TeX-print] prints the .dvi file made by either of these.
+
+Use \\[validate-TeX-buffer] to check buffer for paragraphs containing
+mismatched $'s or braces.
+
+Special commands:
+\\{TeX-mode-map}
+
+Mode variables:
+TeX-directory
+ Directory in which to create temporary files for TeX jobs
+ run by \\[TeX-region] or \\[TeX-buffer].
+TeX-dvi-print-command
+ Command string used by \\[TeX-print] to print a .dvi file.
+TeX-show-queue-command
+ Command string used by \\[TeX-show-print-queue] to show the print
+ queue that \\[TeX-print] put your job on.
+
+Entering plain-TeX mode calls the value of text-mode-hook,
+then the value of TeX-mode-hook, and then the value
+of plain-TeX-mode-hook."
+ t)
+
+(autoload 'tex-mode "tex-mode"
+ "\
+Major mode for editing files of input for TeX or LaTeX.
+Trys to intuit whether this file is for plain TeX or LaTeX and
+calls plain-tex-mode or latex-mode. If it cannot be determined
+(e.g., there are no commands in the file), the value of
+TeX-default-mode is used."
+ t)
+
+(fset 'TeX-mode 'tex-mode)
+(fset 'plain-TeX-mode 'plain-tex-mode)
+(fset 'LaTeX-mode 'latex-mode)
+
+(autoload 'texinfo-mode "texinfo"
+ "\
+Major mode for editing texinfo files.
+These are files that are input for TEX and also to be turned
+into Info files by \\[texinfo-format-buffer].
+These files must be written in a very restricted and
+modified version of TEX input format.
+
+As for editing commands, like text-mode except for syntax table,
+which is set up so expression commands skip texinfo bracket groups."
+ t)
+
+(autoload 'texinfo-format-buffer "texinfmt"
+ "\
+Process the current buffer as texinfo code, into an Info file.
+The Info file output is generated in a buffer
+visiting the Info file names specified in the @setfilename command.
+
+Non-nil argument (prefix, if interactive) means don't make tag table
+and don't split the file if large. You can use Info-tagify and
+Info-split to do these manually."
+ t)
+
+(autoload 'texinfo-format-region "texinfmt"
+ "\
+Convert the the current region of the Texinfo file to Info format.
+This lets you see what that part of the file will look like in Info.
+The command is bound to \\[texinfo-format-region]. The text that is
+converted to Info is stored in a temporary buffer."
+ t)
+
+(autoload 'batch-texinfo-format "texinfmt"
+ "\
+Runs texinfo-format-buffer on the files remaining on the command line.
+Must be used only with -batch, and kills emacs on completion.
+Each file will be processed even if an error occurred previously.
+For example, invoke
+ \"emacs -batch -funcall batch-texinfo-format $docs/ ~/*.texinfo\"."
+ nil)
+
+(autoload 'display-time "time"
+ "\
+Display current time and load level in mode line of each buffer.
+Updates automatically every minute.
+If display-time-day-and-date is non-nil, the current day and date
+are displayed as well."
+ t)
+
+(autoload 'underline-region "underline"
+ "\
+Underline all nonblank characters in the region.
+Works by overstriking underscores.
+Called from program, takes two arguments START and END
+which specify the range to operate on."
+ t)
+
+(autoload 'ununderline-region "underline"
+ "\
+Remove all underlining (overstruck underscores) in the region.
+Called from program, takes two arguments START and END
+which specify the range to operate on."
+ t)
+
+(autoload 'ask-user-about-lock "userlock"
+ "\
+Ask user what to do when he wants to edit FILE but it is locked by USER.
+This function has a choice of three things to do:
+ do (signal 'buffer-file-locked (list FILE USER))
+ to refrain from editing the file
+ return t (grab the lock on the file)
+ return nil (edit the file even though it is locked).
+You can rewrite it to use any criterion you like to choose which one to do."
+ nil)
+
+(autoload 'ask-user-about-supersession-threat "userlock"
+ "\
+Ask a user who is about to modify an obsolete buffer what to do.
+This function has two choices: it can return, in which case the modification
+of the buffer will proceed, or it can (signal 'file-supersession (file)),
+in which case the proposed buffer modification will not be made.
+You can rewrite this to use any criterion you like to choose which one to do."
+ nil)
+
+(autoload 'vi-mode "vi"
+ "\
+Major mode that acts like the `vi' editor.
+The purpose of this mode is to provide you the combined power of vi (namely,
+the \"cross product\" effect of commands and repeat last changes) and Emacs.
+
+This command redefines nearly all keys to look like vi commands.
+It records the previous major mode, and any vi command for input
+\(`i', `a', `s', etc.) switches back to that mode.
+Thus, ordinary Emacs (in whatever major mode you had been using)
+is \"input\" mode as far as vi is concerned.
+
+To get back into vi from \"input\" mode, you must issue this command again.
+Therefore, it is recommended that you assign it to a key.
+
+Major differences between this mode and real vi :
+
+* Limitations and unsupported features
+ - Search patterns with line offset (e.g. /pat/+3 or /pat/z.) are
+ not supported.
+ - Ex commands are not implemented; try ':' to get some hints.
+ - No line undo (i.e. the 'U' command), but multi-undo is a standard feature.
+
+* Modifications
+ - The stopping positions for some point motion commands (word boundary,
+ pattern search) are slightly different from standard 'vi'.
+ Also, no automatic wrap around at end of buffer for pattern searching.
+ - Since changes are done in two steps (deletion then insertion), you need
+ to undo twice to completely undo a change command. But this is not needed
+ for undoing a repeated change command.
+ - No need to set/unset 'magic', to search for a string with regular expr
+ in it just put a prefix arg for the search commands. Replace cmds too.
+ - ^R is bound to incremental backward search, so use ^L to redraw screen.
+
+* Extensions
+ - Some standard (or modified) Emacs commands were integrated, such as
+ incremental search, query replace, transpose objects, and keyboard macros.
+ - In command state, ^X links to the 'ctl-x-map', and ESC can be linked to
+ esc-map or set undefined. These can give you the full power of Emacs.
+ - See vi-com-map for those keys that are extensions to standard vi, e.g.
+ `vi-name-last-change-or-macro', `vi-verify-spelling', `vi-locate-def',
+ `vi-mark-region', and 'vi-quote-words'. Some of them are quite handy.
+ - Use \\[vi-switch-mode] to switch among different modes quickly.
+
+Syntax table and abbrevs while in vi mode remain as they were in Emacs."
+ t)
+
+(autoload 'view-file "view"
+ "\
+View FILE in View mode, returning to previous buffer when done.
+The usual Emacs commands are not available; instead,
+a special set of commands (mostly letters and punctuation)
+are defined for moving around in the buffer.
+Space scrolls forward, Delete scrolls backward.
+For list of all View commands, type ? or h while viewing.
+
+Calls the value of view-hook if that is non-nil."
+ t)
+
+(autoload 'view-buffer "view"
+ "\
+View BUFFER in View mode, returning to previous buffer when done.
+The usual Emacs commands are not available; instead,
+a special set of commands (mostly letters and punctuation)
+are defined for moving around in the buffer.
+Space scrolls forward, Delete scrolls backward.
+For list of all View commands, type ? or h while viewing.
+
+Calls the value of view-hook if that is non-nil."
+ t)
+
+(autoload 'view-mode "view"
+ "\
+Major mode for viewing text but not editing it.
+Letters do not insert themselves. Instead these commands are provided.
+Most commands take prefix arguments. Commands dealing with lines
+default to \"scroll size\" lines (initially size of window).
+Search commands default to a repeat count of one.
+M-< or < move to beginning of buffer.
+M-> or > move to end of buffer.
+C-v or Space scroll forward lines.
+M-v or DEL scroll backward lines.
+CR or LF scroll forward one line (backward with prefix argument).
+z like Space except set number of lines for further
+ scrolling commands to scroll by.
+C-u and Digits provide prefix arguments. `-' denotes negative argument.
+= prints the current line number.
+g goes to line given by prefix argument.
+/ or M-C-s searches forward for regular expression
+\\ or M-C-r searches backward for regular expression.
+n searches forward for last regular expression.
+p searches backward for last regular expression.
+C-@ or . set the mark.
+x exchanges point and mark.
+C-s or s do forward incremental search.
+C-r or r do reverse incremental search.
+@ or ' return to mark and pops mark ring.
+ Mark ring is pushed at start of every
+ successful search and when jump to line to occurs.
+ The mark is set on jump to buffer start or end.
+? or h provide help message (list of commands).
+C-h provides help (list of commands or description of a command).
+C-n moves down lines vertically.
+C-p moves upward lines vertically.
+C-l recenters the screen.
+q or C-c exit view-mode and return to previous buffer.
+
+Entry to this mode calls the value of view-hook if non-nil.
+\\{view-mode-map}")
+
+(autoload 'vip-mode "vip"
+ "\
+Begin emulating the vi editor. This is distinct from `vi-mode'.
+This emulator has different capabilities from the `vi-mode' emulator.
+See the text at the beginning of the source file .../lisp/vip.el
+in the Emacs distribution."
+ t)
+
+(autoload 'yow "yow"
+ "\
+Return or display a Zippy quotation" t)
+(autoload 'psychoanalyze-pinhead "yow"
+ "\
+Zippy goes to the analyst." t)
+
+
+(define-key esc-map "\C-f" 'forward-sexp)
+(define-key esc-map "\C-b" 'backward-sexp)
+(define-key esc-map "\C-u" 'backward-up-list)
+(define-key esc-map "\C-@" 'mark-sexp)
+(define-key esc-map "\C-d" 'down-list)
+(define-key esc-map "\C-k" 'kill-sexp)
+(define-key esc-map "\C-n" 'forward-list)
+(define-key esc-map "\C-p" 'backward-list)
+(define-key esc-map "\C-a" 'beginning-of-defun)
+(define-key esc-map "\C-e" 'end-of-defun)
+(define-key esc-map "\C-h" 'mark-defun)
+(define-key esc-map "(" 'insert-parentheses)
+(define-key esc-map ")" 'move-past-close-and-reindent)
+(define-key esc-map "\t" 'lisp-complete-symbol)
+
+(define-key ctl-x-map "\C-e" 'eval-last-sexp)
+
+(define-key ctl-x-map "/" 'point-to-register)
+(define-key ctl-x-map "j" 'register-to-point)
+(define-key ctl-x-map "x" 'copy-to-register)
+(define-key ctl-x-map "g" 'insert-register)
+(define-key ctl-x-map "r" 'copy-rectangle-to-register)
+
+(define-key esc-map "q" 'fill-paragraph)
+(define-key esc-map "g" 'fill-region)
+(define-key ctl-x-map "." 'set-fill-prefix)
+
+(define-key esc-map "[" 'backward-paragraph)
+(define-key esc-map "]" 'forward-paragraph)
+(define-key esc-map "h" 'mark-paragraph)
+(define-key esc-map "a" 'backward-sentence)
+(define-key esc-map "e" 'forward-sentence)
+(define-key esc-map "k" 'kill-sentence)
+(define-key ctl-x-map "\177" 'backward-kill-sentence)
+
+(define-key ctl-x-map "[" 'backward-page)
+(define-key ctl-x-map "]" 'forward-page)
+(define-key ctl-x-map "\C-p" 'mark-page)
+(put 'narrow-to-region 'disabled t)
+(define-key ctl-x-map "p" 'narrow-to-page)
+(put 'narrow-to-page 'disabled t)
+(define-key ctl-x-map "l" 'count-lines-page)
+
+(defun isearch-forward ()
+ "\
+Do incremental search forward.
+As you type characters, they add to the search string and are found.
+Type Delete to cancel characters from end of search string.
+Type ESC to exit, leaving point at location found.
+Type C-s to search again forward, C-r to search again backward.
+Type C-w to yank word from buffer onto end of search string and search for it.
+Type C-y to yank rest of line onto end of search string, etc.
+Type C-q to quote control character to search for it.
+Other control and meta characters terminate the search
+ and are then executed normally.
+The above special characters are mostly controlled by parameters;
+ do M-x apropos on search-.*-char to find them.
+C-g while searching or when search has failed
+ cancels input back to what has been found successfully.
+C-g when search is successful aborts and moves point to starting point."
+ (interactive)
+ (isearch t))
+
+(defun isearch-forward-regexp ()
+ "\
+Do incremental search forward for regular expression.
+Like ordinary incremental search except that your input
+is treated as a regexp. See \\[isearch-forward] for more info."
+ (interactive)
+ (isearch t t))
+
+(defun isearch-backward ()
+ "\
+Do incremental search backward.
+See \\[isearch-forward] for more information."
+ (interactive)
+ (isearch nil))
+
+(defun isearch-backward-regexp ()
+ "\
+Do incremental search backward for regular expression.
+Like ordinary incremental search except that your input
+is treated as a regexp. See \\[isearch-forward] for more info."
+ (interactive)
+ (isearch nil t))
+
+(defvar search-last-string "" "\
+Last string search for by a non-regexp search command.
+This does not include direct calls to the primitive search functions,
+and does not include searches that are aborted.")
+
+(defvar search-last-regexp "" "\
+Last string searched for by a regexp search command.
+This does not include direct calls to the primitive search functions,
+and does not include searches that are aborted.")
+
+(defconst search-repeat-char ?\C-s "\
+*Character to repeat incremental search forwards.")
+(defconst search-reverse-char ?\C-r "\
+*Character to repeat incremental search backwards.")
+(defconst search-exit-char ?\e "\
+*Character to exit incremental search.")
+(defconst search-delete-char ?\177 "\
+*Character to delete from incremental search string.")
+(defconst search-quote-char ?\C-q "\
+*Character to quote special characters for incremental search.")
+(defconst search-yank-word-char ?\C-w "\
+*Character to pull next word from buffer into search string.")
+(defconst search-yank-line-char ?\C-y "\
+*Character to pull rest of line from buffer into search string.")
+(defconst search-exit-option t "\
+*Non-nil means random control characters terminate incremental search.")
+
+(defvar search-slow-window-lines 1 "\
+*Number of lines in slow search display windows.
+These are the short windows used during incremental search on slow terminals.
+Negative means put the slow search window at the top (normally it's at bottom)
+and the value is minus the number of lines.")
+
+(defvar search-slow-speed 1200 "\
+*Highest terminal speed at which to use \"slow\" style incremental search.
+This is the style where a one-line window is created to show the line
+that the search has reached.")
+
+(autoload 'isearch "isearch")
+
+(define-key global-map "\C-s" 'isearch-forward)
+(define-key global-map "\C-r" 'isearch-backward)
+(define-key esc-map "\C-s" 'isearch-forward-regexp)
+
+(defun query-replace (from-string to-string &optional arg)
+ "\
+Replace some occurrences of FROM-STRING with TO-STRING.
+As each match is found, the user must type a character saying
+what to do with it. For directions, type \\[help-command] at that time.
+
+Preserves case in each replacement if case-replace and case-fold-search
+are non-nil and FROM-STRING has no uppercase letters.
+Third arg DELIMITED (prefix arg if interactive) non-nil means replace
+only matches surrounded by word boundaries."
+ (interactive "sQuery replace: \nsQuery replace %s with: \nP")
+ (perform-replace from-string to-string t nil arg)
+ (message "Done"))
+
+(defun query-replace-regexp (regexp to-string &optional arg)
+ "\
+Replace some things after point matching REGEXP with TO-STRING.
+As each match is found, the user must type a character saying
+what to do with it. For directions, type \\[help-command] at that time.
+
+Preserves case in each replacement if case-replace and case-fold-search
+are non-nil and REGEXP has no uppercase letters.
+Third arg DELIMITED (prefix arg if interactive) non-nil means replace
+only matches surrounded by word boundaries.
+In TO-STRING, \\& means insert what matched REGEXP,
+and \\=\\<n> means insert what matched <n>th \\(...\\) in REGEXP."
+ (interactive "sQuery replace regexp: \nsQuery replace regexp %s with: \nP")
+ (perform-replace regexp to-string t t arg)
+ (message "Done"))
+
+(defun replace-string (from-string to-string &optional delimited)
+ "\
+Replace occurrences of FROM-STRING with TO-STRING.
+Preserve case in each match if case-replace and case-fold-search
+are non-nil and FROM-STRING has no uppercase letters.
+Third arg DELIMITED (prefix arg if interactive) non-nil means replace
+only matches surrounded by word boundaries."
+ (interactive "sReplace string: \nsReplace string %s with: \nP")
+ (perform-replace from-string to-string nil nil delimited)
+ (message "Done"))
+
+(defun replace-regexp (regexp to-string &optional delimited)
+ "\
+Replace things after point matching REGEXP with TO-STRING.
+Preserve case in each match if case-replace and case-fold-search
+are non-nil and REGEXP has no uppercase letters.
+Third arg DELIMITED (prefix arg if interactive) non-nil means replace
+only matches surrounded by word boundaries.
+In TO-STRING, \\& means insert what matched REGEXP,
+and \\=\\<n> means insert what matched <n>th \\(...\\) in REGEXP."
+ (interactive "sReplace regexp: \nsReplace regexp %s with: \nP")
+ (perform-replace regexp to-string nil t delimited)
+ (message "Done"))
+
+(define-key esc-map "%" 'query-replace)
+
+(autoload 'perform-replace "replace")
+
+(define-key ctl-x-map "\C-a" 'add-mode-abbrev)
+(define-key ctl-x-map "\+" 'add-global-abbrev)
+(define-key ctl-x-map "\C-h" 'inverse-add-mode-abbrev)
+(define-key ctl-x-map "\-" 'inverse-add-global-abbrev)
+(define-key esc-map "'" 'abbrev-prefix-mark)
+(define-key ctl-x-map "'" 'expand-abbrev)
diff --git a/lisp/loadup.el b/lisp/loadup.el
index 9447c74891d..01f74e7ebc3 100644
--- a/lisp/loadup.el
+++ b/lisp/loadup.el
@@ -1,4 +1,4 @@
-;;Load up standardly loaded Lisp files for Emacs.
+;Load up standardly loaded Lisp files for Emacs.
;; This is loaded into a bare Emacs to make a dumpable one.
;; Copyright (C) 1985, 1986 Free Software Foundation, Inc.
@@ -18,6 +18,8 @@
;; along with GNU Emacs; see the file COPYING. If not, write to
;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+;;; Disable undo in the *scratch* buffer so it doesn't get dumped.
+(buffer-flush-undo (get-buffer "*scratch*"))
(load "subr")
(garbage-collect)
@@ -62,10 +64,6 @@
(progn
(garbage-collect)
(load "vms-patch")))
-(if (fboundp 'atan) ; preload some constants and
- (progn ; floating pt. functions if
- (garbage-collect) ; we have float support.
- (load "float-sup")))
;If you want additional libraries to be preloaded and their
;doc strings kept in the DOC file rather than in core,
@@ -103,6 +101,10 @@
(load "site-init" t)
(garbage-collect)
+;;; Re-enable undo in the *scratch* buffer, so the dumped Emacs will
+;;; start up that way.
+(buffer-enable-undo (get-buffer "*scratch*"))
+
(if (or (equal (nth 3 command-line-args) "dump")
(equal (nth 4 command-line-args) "dump"))
(if (eq system-type 'vax-vms)
@@ -110,24 +112,32 @@
(message "Dumping data as file temacs.dump")
(dump-emacs "temacs.dump" "temacs")
(kill-emacs))
- (let ((name (concat "emacs-" emacs-version)))
- (while (string-match "[^-+_.a-zA-Z0-9]+" name)
- (setq name (concat (downcase (substring name 0 (match-beginning 0)))
- "-"
- (substring name (match-end 0)))))
- (message "Dumping under names xemacs and %s" name))
- (condition-case ()
- (delete-file "xemacs")
- (file-error nil))
- (dump-emacs "xemacs" "temacs")
- ;; Recompute NAME now, so that it isn't set when we dump.
- (let ((name (concat "emacs-" emacs-version)))
- (while (string-match "[^-+_.a-zA-Z0-9]+" name)
- (setq name (concat (downcase (substring name 0 (match-beginning 0)))
- "-"
- (substring name (match-end 0)))))
- (add-name-to-file "xemacs" name t))
- (kill-emacs)))
+ (if (fboundp 'dump-emacs-data)
+ ;; Handle the IBM RS/6000, and perhaps eventually other machines.
+ (progn
+ ;; This strange nesting is so that the variable `name'
+ ;; is not bound when the data is dumped.
+ (message "Dumping data as file ../etc/EMACS-DATA")
+ (dump-emacs-data "../etc/EMACS-DATA")
+ (kill-emacs))
+ (let ((name (concat "emacs-" emacs-version)))
+ (while (string-match "[^-+_.a-zA-Z0-9]+" name)
+ (setq name (concat (downcase (substring name 0 (match-beginning 0)))
+ "-"
+ (substring name (match-end 0)))))
+ (message "Dumping under names xemacs and %s" name))
+ (condition-case ()
+ (delete-file "xemacs")
+ (file-error nil))
+ (dump-emacs "xemacs" "temacs")
+ ;; Recompute NAME now, so that it isn't set when we dump.
+ (let ((name (concat "emacs-" emacs-version)))
+ (while (string-match "[^-+_.a-zA-Z0-9]+" name)
+ (setq name (concat (downcase (substring name 0 (match-beginning 0)))
+ "-"
+ (substring name (match-end 0)))))
+ (add-name-to-file "xemacs" name t))
+ (kill-emacs))))
;; Avoid error if user loads some more libraries now.
(setq purify-flag nil)
diff --git a/lisp/lpr.el b/lisp/lpr.el
index 3ae55b2f24a..c2b17f17b92 100644
--- a/lisp/lpr.el
+++ b/lisp/lpr.el
@@ -21,71 +21,52 @@
;(defconst lpr-switches nil
; "*List of strings to pass as extra switch args to lpr when it is invoked.")
-(defvar lpr-command (if (eq system-type 'usg-unix-v)
+(defvar lpr-command (if (memq system-type
+ '(usg-unix-v hpux silicon-graphics-unix))
"lp" "lpr")
"Shell command for printing a file")
-(defvar print-region-function nil
- "Function to call to print the region on a printer.
-See definition of `print-region-1' for calling conventions.")
-
(defun lpr-buffer ()
"Print buffer contents as with Unix command `lpr'.
`lpr-switches' is a list of extra switches (strings) to pass to lpr."
(interactive)
- (print-region-1 (point-min) (point-max) lpr-switches nil))
+ (print-region-1 (point-min) (point-max) lpr-switches))
(defun print-buffer ()
"Print buffer contents as with Unix command `lpr -p'.
`lpr-switches' is a list of extra switches (strings) to pass to lpr."
(interactive)
- (print-region-1 (point-min) (point-max) lpr-switches t))
+ (print-region-1 (point-min) (point-max) (cons "-p" lpr-switches)))
(defun lpr-region (start end)
"Print region contents as with Unix command `lpr'.
`lpr-switches' is a list of extra switches (strings) to pass to lpr."
(interactive "r")
- (print-region-1 start end lpr-switches nil))
+ (print-region-1 start end lpr-switches))
(defun print-region (start end)
"Print region contents as with Unix command `lpr -p'.
`lpr-switches' is a list of extra switches (strings) to pass to lpr."
(interactive "r")
- (print-region-1 start end lpr-switches t))
+ (print-region-1 start end (cons "-p" lpr-switches)))
-(defun print-region-1 (start end switches page-headers)
+(defun print-region-1 (start end switches)
(let ((name (concat (buffer-name) " Emacs buffer"))
(width tab-width))
(save-excursion
- (message "Spooling...")
- (if (/= tab-width 8)
- (progn
- (print-region-new-buffer start end)
- (setq tab-width width)
- (untabify (point-min) (point-max))))
- (if page-headers
- (if (eq system-type 'usg-unix-v)
- (progn
- (print-region-new-buffer)
- (call-process-region start end "pr" t t nil))
- ;; On BSD, use an option to get page headers.
- (setq switches (cons "-p" switches))))
- (apply (or print-region-function 'call-process-region)
- (nconc (list start end lpr-command
- nil nil nil)
- (nconc (and (eq system-type 'berkeley-unix)
- (list "-J" name "-T" name))
- switches)))
- (message "Spooling...done"))))
-
-;; This function copies the text between start and end
-;; into a new buffer, makes that buffer current,
-;; and sets start and end to the buffer bounds.
-;; start and end are used free.
-(defun print-region-new-buffer ()
- (or (string= (buffer-name) " *spool temp*")
- (let ((oldbuf (current-buffer)))
- (set-buffer (get-buffer-create " *spool temp*"))
- (widen) (erase-buffer)
- (insert-buffer-substring oldbuf start end)
- (setq start (point-min) end (point-max)))))
+ (message "Spooling...")
+ (if (/= tab-width 8)
+ (let ((oldbuf (current-buffer)))
+ (set-buffer (get-buffer-create " *spool temp*"))
+ (widen) (erase-buffer)
+ (insert-buffer-substring oldbuf start end)
+ (setq tab-width width)
+ (untabify (point-min) (point-max))
+ (setq start (point-min) end (point-max))))
+ (apply 'call-process-region
+ (nconc (list start end lpr-command
+ nil nil nil)
+ (nconc (and (eq system-type 'berkeley-unix)
+ (list "-J" name "-T" name))
+ switches)))
+ (message "Spooling...done"))))
diff --git a/lisp/lpr.elc b/lisp/lpr.elc
new file mode 100644
index 00000000000..efcfac8abd6
--- /dev/null
+++ b/lisp/lpr.elc
Binary files differ
diff --git a/lisp/ls-lisp.el b/lisp/ls-lisp.el
deleted file mode 100644
index 63c1f66e148..00000000000
--- a/lisp/ls-lisp.el
+++ /dev/null
@@ -1,132 +0,0 @@
-;;;; dired-lisp.el - emulate ls completely in Emacs Lisp. $Revision: 1.2 $
-;;;; Copyright (C) 1991 Sebastian Kremer <sk@thp.uni-koeln.de>
-
-;;;; READ THE WARNING BELOW BEFORE USING THIS PROGRAM!
-
-;;;; Useful if you cannot afford to fork Emacs on a real memory UNIX,
-;;;; under VMS, or if you don't have the ls program.
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 1, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
-;;;; WARNING:
-
-;;;; Sometimes I get an internal Emacs error:
-
-;;;; Signalling: (wrong-type-argument natnump #<EMACS BUG: ILLEGAL
-;;;; DATATYPE (#o37777777727) Save your buffers immediately and please
-;;;; report this bug>)
-
-;;;; Sometimes emacs just crashes with a fatal error.
-
-;;; RESTRICTIONS:
-;;;; Always sorts by name (ls switches are completely ignored for now)
-;;;; Cannot display date of file, displays a fake date "Jan 00 00:00" instead
-;;;; Only numeric uid/gid
-;;;; Loading ange-ftp breaks it
-
-;;;; It is surprisingly fast, though!
-
-;;;; TODO:
-;;;; Recognize at least some ls switches: l R g F i
-
-(require 'dired) ; we will redefine this function:
-
-(defun dired-ls (file &optional switches wildcard full-directory-p)
- "dired-lisp.el's version of dired-ls."
-; "Insert ls output of FILE, optionally formatted with SWITCHES.
-;Optional third arg WILDCARD means treat FILE as shell wildcard.
-;Optional fourth arg FULL-DIRECTORY-P means file is a directory and
-;switches do not contain `d'.
-;
-;SWITCHES default to dired-listing-switches."
- (or switches (setq switches dired-listing-switches))
- (if wildcard
- (error "Cannot handle wildcards in lisp emulation of `ls'."))
- (if full-directory-p
- (let* ((dir (file-name-as-directory file))
- (start (length dir))
- (sum 0))
- (insert "total \007\n") ; fill in afterwards
- (insert
- (mapconcat
- (function (lambda (short)
- (let* ((fil (concat dir short))
- (attr (file-attributes fil))
- (size (nth 7 attr)))
- ;;(debug)
- (setq sum (+ sum size))
- (dired-lisp-format
- ;;(file-name-nondirectory fil)
- ;;(dired-make-relative fil dir)
- ;;(substring fil start)
- short
- attr
- switches))))
- (directory-files dir)
- ""))
- (save-excursion
- (search-backward "total \007")
- (goto-char (match-end 0))
- (delete-char -1)
- (insert (format "%d" sum)))
- )
- ;; if not full-directory-p, FILE *must not* end in /, as
- ;; file-attributes will not recognize a symlink to a directory
- ;; must make it a relative filename as ls does:
- (setq file (file-name-nondirectory file))
- (insert (dired-lisp-format file (file-attributes file) switches)))
- )
-
-(defun dired-lisp-format (file-name file-attr &optional switches)
- (let ((file-type (nth 0 file-attr)))
- (concat (nth 8 file-attr) ; permission bits
- " "
- (dired-lisp-pad (nth 1 file-attr) -3) ; no. of links
- ;; numeric uid/gid are more confusing than helpful
- ;; Emacs should be able to make strings of them
- " " (dired-lisp-pad (nth 2 file-attr) -6) ; uid
- " " (dired-lisp-pad (nth 3 file-attr) -6) ; gid
- " "
- (dired-lisp-pad (nth 7 file-attr) -8) ; size in bytes
- ;; file-attributes's time is in a braindead format
- ;; Emacs should have a ctime function
- " " "Jan 00 00:00 " ; fake time
- file-name
- (if (stringp file-type) ; is a symbolic link
- (concat " -> " file-type)
- "")
- "\n"
- )))
-
-;; format should really do anything printf can!!
-(defun dired-lisp-pad (arg width &optional pad-char)
- "Pad ARG to WIDTH, from left if WIDTH < 0.
-Non-nil third arg optional PAD-CHAR defaults to a space."
- (or pad-char (setq pad-char ?\040))
- (if (integerp arg)
- (setq arg (int-to-string arg)))
- (let (l pad reverse)
- (if (< width 0)
- (setq reverse t
- width (- width)))
- (setq l (length arg)
- pad (- width l))
- (if (> pad 0)
- (if reverse
- (concat (make-string pad pad-char) arg)
- (concat arg (make-string pad pad-char)))
- arg)))
diff --git a/lisp/macros.el b/lisp/macros.el
index b318ff8eefb..bd2bd9ce449 100644
--- a/lisp/macros.el
+++ b/lisp/macros.el
@@ -20,9 +20,10 @@
(defun name-last-kbd-macro (symbol)
"Assign a name to the last keyboard macro defined.
-Argument SYMBOL is the name to define.
+One arg, a symbol, which is the name to define.
The symbol's function definition becomes the keyboard macro string.
-Such a \"function\" cannot be called from Lisp, but it is a valid editor command."
+Such a \"function\" cannot be called from Lisp, but it is a valid command
+definition for the editor command loop."
(interactive "SName for last kbd macro: ")
(or last-kbd-macro
(error "No keyboard macro defined"))
@@ -34,14 +35,14 @@ Such a \"function\" cannot be called from Lisp, but it is a valid editor command
(defun insert-kbd-macro (macroname &optional keys)
"Insert in buffer the definition of kbd macro NAME, as Lisp code.
-Optional second arg KEYS means also record the keys it is on
-(this is the prefix argument, when calling interactively).
+Second argument KEYS non-nil means also record the keys it is on.
+ (This is the prefix argument, when calling interactively.)
-This Lisp code will, when executed, define the kbd macro with the same
-definition it has now. If you say to record the keys, the Lisp code
-will also rebind those keys to the macro. Only global key bindings
-are recorded since executing this Lisp code always makes global
-bindings.
+This Lisp code will, when executed, define the kbd macro with the
+same definition it has now. If you say to record the keys,
+the Lisp code will also rebind those keys to the macro.
+Only global key bindings are recorded since executing this Lisp code
+always makes global bindings.
To save a kbd macro, visit a file of Lisp code such as your ~/.emacs,
use this command, and then save the file."
@@ -63,15 +64,15 @@ use this command, and then save the file."
(defun kbd-macro-query (flag)
"Query user during kbd macro execution.
- With prefix argument, enters recursive edit, reading keyboard
-commands even within a kbd macro. You can give different commands
-each time the macro executes.
- Without prefix argument, reads a character. Your options are:
-Space -- execute the rest of the macro.
-DEL -- skip the rest of the macro; start next repetition.
-C-d -- skip rest of the macro and don't repeat it any more.
-C-r -- enter a recursive edit, then on exit ask again for a character
-C-l -- redisplay screen and ask again."
+With prefix argument, enters recursive edit,
+ reading keyboard commands even within a kbd macro.
+ You can give different commands each time the macro executes.
+Without prefix argument, reads a character. Your options are:
+ Space -- execute the rest of the macro.
+ DEL -- skip the rest of the macro; start next repetition.
+ C-d -- skip rest of the macro and don't repeat it any more.
+ C-r -- enter a recursive edit, then on exit ask again for a character
+ C-l -- redisplay screen and ask again."
(interactive "P")
(or executing-macro
defining-kbd-macro
diff --git a/lisp/macros.elc b/lisp/macros.elc
new file mode 100644
index 00000000000..9410bfd5dd9
--- /dev/null
+++ b/lisp/macros.elc
Binary files differ
diff --git a/lisp/mail/mail-utils.el b/lisp/mail-utils.el
index a9eafa4b5e3..402b72eccdd 100644
--- a/lisp/mail/mail-utils.el
+++ b/lisp/mail-utils.el
@@ -23,8 +23,8 @@
;; should be in loaddefs
(defvar mail-use-rfc822 nil
"*If non-nil, use a full, hairy RFC822 parser on mail addresses.
-Otherwise, (the default) use a smaller, somewhat faster, and
-often correct parser.")
+Otherwise, (the default) use a smaller, somewhat faster and
+often-correct parser.")
(defun mail-string-delete (string start end)
"Returns a string containing all of STRING except the part
@@ -37,64 +37,76 @@ from START (inclusive) to END (exclusive)."
"Delete comments and quoted strings in an address list ADDRESS.
Also delete leading/trailing whitespace and replace FOO <BAR> with just BAR.
Return a modified address list."
- (if mail-use-rfc822
- (progn (require 'rfc822)
- (mapconcat 'identity (rfc822-addresses address) ", "))
- (let (pos)
- (string-match "\\`[ \t\n]*" address)
- ;; strip surrounding whitespace
- (setq address (substring address
- (match-end 0)
- (string-match "[ \t\n]*\\'" address
- (match-end 0))))
+ (if (null address)
+ nil
+ (if mail-use-rfc822
+ (progn (require 'rfc822)
+ (mapconcat 'identity (rfc822-addresses address) ", "))
+ (let (pos)
+ ;; Strip rfc822 comments (within parens).
+ ;; Understand properly the effect of backslashes and string quotes.
+ (let (instring (depth 0) start)
+ (setq pos -1)
+ (while pos
+ (cond ((< pos 0))
+ ((= (aref address pos) ?\\)
+ (setq pos (1+ pos)))
+ ((= (aref address pos) ?\")
+ (setq instring (not instring)))
+ (instring nil)
+ ((= (aref address pos) ?\()
+ (if (= depth 0) (setq start pos))
+ (setq depth (1+ depth)))
+ ((= (aref address pos) ?\))
+ (setq depth (1- depth))
+ (if (= depth 0)
+ (setq address (mail-string-delete address start (1+ pos))
+ pos (1- start)))))
+ (setq pos (string-match "[\"\\()]" address (1+ pos)))))
- ;; Detect nested comments.
- (if (string-match "[ \t]*(\\([^)\"\\]\\|\\\\.\\|\\\\\n\\)*(" address)
- ;; Strip nested comments.
- (save-excursion
- (set-buffer (get-buffer-create " *temp*"))
- (erase-buffer)
- (insert address)
- (set-syntax-table lisp-mode-syntax-table)
- (goto-char 1)
- (while (search-forward "(" nil t)
- (forward-char -1)
- (skip-chars-backward " \t")
- (delete-region (point)
- (save-excursion (forward-sexp 1) (point))))
- (setq address (buffer-string))
- (erase-buffer))
- ;; Strip non-nested comments an easier way.
- (while (setq pos (string-match
- ;; This doesn't hack rfc822 nested comments
- ;; `(xyzzy (foo) whinge)' properly. Big deal.
- "[ \t]*(\\([^)\"\\]\\|\\\\.\\|\\\\\n\\)*)"
- address))
- (setq address
- (mail-string-delete address
- pos (match-end 0)))))
+ ;; strip surrounding whitespace
+ (string-match "\\`[ \t\n]*" address)
+ (setq address (substring address
+ (match-end 0)
+ (string-match "[ \t\n]*\\'" address
+ (match-end 0))))
- ;; strip `quoted' names (This is supposed to hack `"Foo Bar" <bar@host>')
- (setq pos 0)
- (while (setq pos (string-match
- "[ \t]*\"\\([^\"\\]\\|\\\\.\\|\\\\\n\\)*\"[ \t\n]*"
- address pos))
- ;; If the next thing is "@", we have "foo bar"@host. Leave it.
- (if (and (> (length address) (match-end 0))
- (= (aref address (match-end 0)) ?@))
- (setq pos (match-end 0))
- (setq address
- (mail-string-delete address
- pos (match-end 0)))))
- ;; Retain only part of address in <> delims, if there is such a thing.
- (while (setq pos (string-match "\\(,\\|\\`\\)[^,]*<\\([^>,]*>\\)"
- address))
- (let ((junk-beg (match-end 1))
- (junk-end (match-beginning 2))
- (close (match-end 0)))
- (setq address (mail-string-delete address (1- close) close))
- (setq address (mail-string-delete address junk-beg junk-end))))
- address)))
+ ;; Strip whitespace before commas.
+ (let (instring)
+ (setq pos -1)
+ (while pos
+ (cond ((< pos 0))
+ ((= (aref address pos) ?\\)
+ (setq pos (1+ pos)))
+ ((= (aref address pos) ?\")
+ (setq instring (not instring)))
+ (instring nil)
+ ((eq (string-match "[ \t]*," address pos) pos)
+ (setq address (mail-string-delete address pos
+ (1- (match-end 0))))))
+ (setq pos (string-match "[ \t,\"\\]" address (1+ pos)))))
+
+ ;; strip `quoted' names (This is supposed to hack `"Foo Bar" <bar@host>')
+ (setq pos 0)
+ (while (setq pos (string-match
+ "[ \t]*\"\\([^\"\\]\\|\\\\.\\|\\\\\n\\)*\"[ \t\n]*"
+ address pos))
+ ;; If the next thing is "@", we have "foo bar"@host. Leave it.
+ (if (and (> (length address) (match-end 0))
+ (= (aref address (match-end 0)) ?@))
+ (setq pos (match-end 0))
+ (setq address
+ (mail-string-delete address
+ pos (match-end 0)))))
+ ;; Retain only part of address in <> delims, if there is such a thing.
+ (while (setq pos (string-match "\\(,\\|\\`\\)[^,]*<\\([^>,]*>\\)"
+ address))
+ (let ((junk-beg (match-end 1))
+ (junk-end (match-beginning 2))
+ (close (match-end 0)))
+ (setq address (mail-string-delete address (1- close) close))
+ (setq address (mail-string-delete address junk-beg junk-end))))
+ address))))
(or (and (boundp 'rmail-default-dont-reply-to-names)
(not (null rmail-default-dont-reply-to-names)))
@@ -103,14 +115,16 @@ Return a modified address list."
; rmail-dont-reply-to-names is defined in loaddefs
(defun rmail-dont-reply-to (userids)
"Returns string of mail addresses USERIDS sans any recipients
-that start with matches for `rmail-dont-reply-to-names'.
+that start with matches for rmail-dont-reply-to-names.
Usenet paths ending in an element that matches are removed also."
(if (null rmail-dont-reply-to-names)
(setq rmail-dont-reply-to-names
(concat (if rmail-default-dont-reply-to-names
(concat rmail-default-dont-reply-to-names "\\|")
"")
- (concat (regexp-quote (user-original-login-name))
+ (concat (regexp-quote
+ (or (getenv "USER") (getenv "LOGNAME")
+ (user-login-name)))
"\\>"))))
(let ((match (concat "\\(^\\|,\\)[ \t\n]*\\([^,\n]*!\\|\\)\\("
rmail-dont-reply-to-names
@@ -135,10 +149,10 @@ Usenet paths ending in an element that matches are removed also."
userids)))
(defun mail-fetch-field (field-name &optional last all)
- "Return the value of the header field FIELD-NAME.
+ "Return the value of the header field FIELD.
The buffer is expected to be narrowed to just the headers of the message.
-If second arg LAST is non-nil, use the last such field if there are several.
-If third arg ALL is non-nil, concatenate all such fields with commas between."
+If 2nd arg LAST is non-nil, use the last such field if there are several.
+If 3rd arg ALL is non-nil, concatenate all such fields, with commas between."
(save-excursion
(goto-char (point-min))
(let ((case-fold-search t)
diff --git a/lisp/mail-utils.elc b/lisp/mail-utils.elc
new file mode 100644
index 00000000000..5ef56786ed7
--- /dev/null
+++ b/lisp/mail-utils.elc
Binary files differ
diff --git a/lisp/mail/rmailout.el b/lisp/mail/rmailout.el
deleted file mode 100644
index a4018b5cf52..00000000000
--- a/lisp/mail/rmailout.el
+++ /dev/null
@@ -1,182 +0,0 @@
-;; "RMAIL" mail reader for Emacs: output message to a file.
-;; Copyright (C) 1985, 1987 Free Software Foundation, Inc.
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 1, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
-
-;; Temporary until Emacs always has this variable.
-(defvar rmail-delete-after-output nil
- "*Non-nil means automatically delete a message that is copied to a file.")
-
-(defvar rmail-output-file-alist nil
- "*Alist matching regexps to suggested output Rmail files.
-This is a list of elements of the form (REGEXP . FILENAME).")
-
-(defun rmail-output-to-rmail-file (count file-name)
- "Append the current message to an Rmail file named FILE-NAME.
-If the file does not exist, ask if it should be created.
-If file is being visited, the message is appended to the Emacs
-buffer visiting that file.
-A prefix argument N says to output N consecutive messages
-starting with the current one. Deleted messages are skipped and don't count."
- (interactive (list (prefix-numeric-value current-prefix-arg)
- (read-file-name
- (concat "Output message to Rmail file: (default "
- (file-name-nondirectory rmail-last-rmail-file)
- ") ")
- (file-name-directory rmail-last-rmail-file)
- (let (answer tail)
- (setq tail rmail-output-file-alist)
- ;; Suggest a file based on a pattern match.
- (while (and tail (not answer))
- (save-excursion
- (goto-char (point-min))
- (if (re-search-forward (car (car tail)) nil t)
- (setq answer (cdr (car tail))))
- (setq tail (cdr tail))))
- ;; If not suggestions, use same file as last time.
- (or answer rmail-last-rmail-file)))))
- (setq file-name
- (expand-file-name file-name
- (file-name-directory rmail-last-rmail-file)))
- (setq rmail-last-rmail-file file-name)
- (rmail-maybe-set-message-counters)
- (or (get-file-buffer file-name)
- (file-exists-p file-name)
- (if (yes-or-no-p
- (concat "\"" file-name "\" does not exist, create it? "))
- (let ((file-buffer (create-file-buffer file-name)))
- (save-excursion
- (set-buffer file-buffer)
- (rmail-insert-rmail-file-header)
- (let ((require-final-newline nil))
- (write-region (point-min) (point-max) file-name t 1)))
- (kill-buffer file-buffer))
- (error "Output file does not exist")))
- (while (> count 0)
- (let (redelete)
- (unwind-protect
- (progn
- (save-restriction
- (widen)
- (if (rmail-message-deleted-p rmail-current-message)
- (progn (setq redelete t)
- (rmail-set-attribute "deleted" nil)))
- ;; Decide whether to append to a file or to an Emacs buffer.
- (save-excursion
- (let ((buf (get-file-buffer file-name))
- (cur (current-buffer))
- (beg (1+ (rmail-msgbeg rmail-current-message)))
- (end (1+ (rmail-msgend rmail-current-message))))
- (if (not buf)
- (append-to-file beg end file-name)
- (if (eq buf (current-buffer))
- (error "Can't output message to same file it's already in"))
- ;; File has been visited, in buffer BUF.
- (set-buffer buf)
- (let ((buffer-read-only nil)
- (msg (and (boundp 'rmail-current-message)
- rmail-current-message)))
- ;; If MSG is non-nil, buffer is in RMAIL mode.
- (if msg
- (progn
- (rmail-maybe-set-message-counters)
- (widen)
- (narrow-to-region (point-max) (point-max))
- (insert-buffer-substring cur beg end)
- (goto-char (point-min))
- (widen)
- (search-backward "\n\^_")
- (narrow-to-region (point) (point-max))
- (rmail-count-new-messages t)
- (rmail-show-message msg))
- ;; Output file not in rmail mode => just insert at the end.
- (narrow-to-region (point-min) (1+ (buffer-size)))
- (goto-char (point-max))
- (insert-buffer-substring cur beg end)))))))
- (rmail-set-attribute "filed" t))
- (if redelete (rmail-set-attribute "deleted" t))))
- (setq count (1- count))
- (if rmail-delete-after-output
- (rmail-delete-forward)
- (if (> count 0)
- (rmail-next-undeleted-message 1)))))
-
-(defun rmail-output (count file-name)
- "Append this message to Unix mail file named FILE-NAME.
-A prefix argument N says to output N consecutive messages
-starting with the current one. Deleted messages are skipped and don't count."
- (interactive
- (list (prefix-numeric-value current-prefix-arg)
- (read-file-name
- (concat "Output message to Unix mail file"
- (if rmail-last-file
- (concat " (default "
- (file-name-nondirectory rmail-last-file)
- "): " )
- ": "))
- (and rmail-last-file (file-name-directory rmail-last-file))
- rmail-last-file)))
- (setq file-name
- (expand-file-name file-name
- (and rmail-last-file
- (file-name-directory rmail-last-file))))
- (setq rmail-last-file file-name)
- (while (> count 0)
- (let ((rmailbuf (current-buffer))
- (tembuf (get-buffer-create " rmail-output"))
- (case-fold-search t))
- (save-excursion
- (set-buffer tembuf)
- (erase-buffer)
- ;; If we can do it, read a little of the file
- ;; to check whether it is an RMAIL file.
- ;; If it is, don't mess it up.
- (if (fboundp 'insert-partial-file-contents)
- (progn
- (insert-partial-file-contents file-name 0 20)
- (if (looking-at "BABYL OPTIONS:\n")
- (error (save-excursion
- (set-buffer rmailbuf)
- (substitute-command-keys
- "File %s is an RMAIL file; use the \\[rmail-output-to-rmail-file] command"))
- file-name))
- (erase-buffer)))
- (insert-buffer-substring rmailbuf)
- (insert "\n")
- (goto-char (point-min))
- (insert "From "
- (mail-strip-quoted-names (or (mail-fetch-field "from")
- (mail-fetch-field "really-from")
- (mail-fetch-field "sender")
- "unknown"))
- " " (current-time-string) "\n")
- ;; ``Quote'' "\nFrom " as "\n>From "
- ;; (note that this isn't really quoting, as there is no requirement
- ;; that "\n[>]+From " be quoted in the same transparent way.)
- (while (search-forward "\nFrom " nil t)
- (forward-char -5)
- (insert ?>))
- (append-to-file (point-min) (point-max) file-name))
- (kill-buffer tembuf))
- (if (equal major-mode 'rmail-mode)
- (rmail-set-attribute "filed" t))
- (setq count (1- count))
- (if rmail-delete-after-output
- (rmail-delete-forward)
- (if (> count 0)
- (rmail-next-undeleted-message 1)))))
diff --git a/lisp/mail/rmailsort.el b/lisp/mail/rmailsort.el
deleted file mode 100644
index e1f01ad2f8f..00000000000
--- a/lisp/mail/rmailsort.el
+++ /dev/null
@@ -1,203 +0,0 @@
-;;; Rmail: sort messages.
-;; Copyright (C) 1990 Masanobu UMEDA
-;; umerin@tc.Nagasaki.GO.JP?
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY. No author or distributor
-;; accepts responsibility to anyone for the consequences of using it
-;; or for whether it serves any particular purpose or works at all,
-;; unless he says so in writing. Refer to the GNU Emacs General Public
-;; License for full details.
-
-;; Everyone is granted permission to copy, modify and redistribute
-;; GNU Emacs, but only under the conditions described in the
-;; GNU Emacs General Public License. A copy of this license is
-;; supposed to have been given to you along with GNU Emacs so you
-;; can know your rights and responsibilities. It should be in a
-;; file named COPYING. Among other things, the copyright notice
-;; and this notice must be preserved on all copies.
-
-(provide 'rmailsort)
-(require 'rmail)
-(require 'sort)
-
-;; GNUS compatible key bindings.
-(define-key rmail-mode-map "\C-c\C-s\C-d" 'rmail-sort-by-date)
-(define-key rmail-mode-map "\C-c\C-s\C-s" 'rmail-sort-by-subject)
-(define-key rmail-mode-map "\C-c\C-s\C-a" 'rmail-sort-by-author)
-(define-key rmail-mode-map "\C-c\C-s\C-r" 'rmail-sort-by-recipient)
-(define-key rmail-mode-map "\C-c\C-s\C-c" 'rmail-sort-by-correspondent)
-(define-key rmail-mode-map "\C-c\C-s\C-l" 'rmail-sort-by-size-lines)
-
-(defun rmail-sort-by-date (reverse)
- "Sort messages of current Rmail file by date.
-If prefix argument REVERSE is non-nil, sort them in reverse order."
- (interactive "P")
- (rmail-sort-messages reverse
- (function
- (lambda (msg)
- (rmail-sortable-date-string
- (rmail-fetch-field msg "Date"))))))
-
-(defun rmail-sort-by-subject (reverse)
- "Sort messages of current Rmail file by subject.
-If prefix argument REVERSE is non-nil, sort them in reverse order."
- (interactive "P")
- (rmail-sort-messages reverse
- (function
- (lambda (msg)
- (let ((key (or (rmail-fetch-field msg "Subject") ""))
- (case-fold-search t))
- ;; Remove `Re:'
- (if (string-match "^\\(re:[ \t]+\\)*" key)
- (substring key (match-end 0)) key))))))
-
-(defun rmail-sort-by-author (reverse)
- "Sort messages of current Rmail file by author.
-If prefix argument REVERSE is non-nil, sort them in reverse order."
- (interactive "P")
- (rmail-sort-messages reverse
- (function
- (lambda (msg)
- (mail-strip-quoted-names
- (or (rmail-fetch-field msg "From")
- (rmail-fetch-field msg "Sender") ""))))))
-
-(defun rmail-sort-by-recipient (reverse)
- "Sort messages of current Rmail file by recipient.
-If prefix argument REVERSE is non-nil, sort them in reverse order."
- (interactive "P")
- (rmail-sort-messages reverse
- (function
- (lambda (msg)
- (mail-strip-quoted-names
- (or (rmail-fetch-field msg "To")
- (rmail-fetch-field msg "Apparently-To") "")
- )))))
-
-(defun rmail-sort-by-correspondent (reverse)
- "Sort messages of current Rmail file by other correspondent.
-If prefix argument REVERSE is non-nil, sort them in reverse order."
- (interactive "P")
- (rmail-sort-messages reverse
- (function
- (lambda (msg)
- (rmail-select-correspondent
- msg
- '("From" "Sender" "To" "Apparently-To"))))))
-
-(defun rmail-select-correspondent (msg fields)
- (let ((ans ""))
- (while (and fields (string= ans ""))
- (setq ans
- (rmail-dont-reply-to
- (mail-strip-quoted-names
- (or (rmail-fetch-field msg (car fields)) ""))))
- (setq fields (cdr fields)))
- ans))
-
-(defun rmail-sort-by-size-lines (reverse)
- "Sort messages of current Rmail file by message size.
-If prefix argument REVERSE is non-nil, sort them in reverse order."
- (interactive "P")
- (rmail-sort-messages reverse
- (function
- (lambda (msg)
- (format "%9d"
- (count-lines (rmail-msgbeg msgnum)
- (rmail-msgend msgnum)))))))
-
-
-(defun rmail-sort-messages (reverse keyfunc)
- "Sort messages of current Rmail file.
-1st argument REVERSE is non-nil, sort them in reverse order.
-2nd argument KEYFUNC is called with message number, and should return a key."
- (let ((buffer-read-only nil)
- (sort-lists nil))
- (message "Finding sort keys...")
- (widen)
- (let ((msgnum 1))
- (while (>= rmail-total-messages msgnum)
- (setq sort-lists
- (cons (cons (funcall keyfunc msgnum) ;A sort key.
- (buffer-substring
- (rmail-msgbeg msgnum) (rmail-msgend msgnum)))
- sort-lists))
- (if (zerop (% msgnum 10))
- (message "Finding sort keys...%d" msgnum))
- (setq msgnum (1+ msgnum))))
- (or reverse (setq sort-lists (nreverse sort-lists)))
- (setq sort-lists
- (sort sort-lists
- (function
- (lambda (a b)
- (string-lessp (car a) (car b))))))
- (if reverse (setq sort-lists (nreverse sort-lists)))
- (message "Reordering buffer...")
- (delete-region (rmail-msgbeg 1) (rmail-msgend rmail-total-messages))
- (let ((msgnum 1))
- (while sort-lists
- (insert (cdr (car sort-lists)))
- (if (zerop (% msgnum 10))
- (message "Reordering buffer...%d" msgnum))
- (setq sort-lists (cdr sort-lists))
- (setq msgnum (1+ msgnum))))
- (rmail-set-message-counters)
- (rmail-show-message 1)))
-
-(defun rmail-fetch-field (msg field)
- "Return the value of the header field FIELD of MSG.
-Arguments are MSG and FIELD."
- (let ((next (rmail-msgend msg)))
- (save-restriction
- (goto-char (rmail-msgbeg msg))
- (narrow-to-region (if (search-forward "\n*** EOOH ***\n" next t)
- (point)
- (forward-line 1)
- (point))
- (progn (search-forward "\n\n" nil t) (point)))
- (mail-fetch-field field))))
-
-;; Copy of the function gnus-comparable-date in gnus.el
-
-(defun rmail-sortable-date-string (date)
- "Make sortable string by string-lessp from DATE."
- (let ((month '(("JAN" . " 1")("FEB" . " 2")("MAR" . " 3")
- ("APR" . " 4")("MAY" . " 5")("JUN" . " 6")
- ("JUL" . " 7")("AUG" . " 8")("SEP" . " 9")
- ("OCT" . "10")("NOV" . "11")("DEC" . "12")
- ("JANUARY" . " 1") ("FEBRUARY" . " 2")
- ("MARCH" . " 3") ("APRIL" . " 4")
- ("MAY" . " 5") ("JUNE" . " 6")
- ("JULY" . " 7") ("AUGUST" . " 8")
- ("SEPTEMBER" " 9") ("OCTOBER" . "10")
- ("NOVEMBER" "11") ("DECEMBER" . "12")))
- (date (or date "")))
- ;; Can understand the following styles:
- ;; (1) 14 Apr 89 03:20:12 GMT
- ;; (2) Fri, 17 Mar 89 4:01:33 GMT
- (if (string-match
- "\\([0-9]+\\) +\\([^ ,]+\\) +\\([0-9]+\\) +\\([0-9:]+\\)" date)
- (concat
- ;; Year
- (rmail-date-full-year
- (substring date (match-beginning 3) (match-end 3)))
- ;; Month
- (cdr
- (assoc
- (upcase (substring date (match-beginning 2) (match-end 2))) month))
- ;; Day
- (format "%2d" (string-to-int
- (substring date
- (match-beginning 1) (match-end 1))))
- ;; Time
- (substring date (match-beginning 4) (match-end 4)))
- ;; Cannot understand DATE string.
- date)))
-
-(defun rmail-date-full-year (year-string)
- (if (<= (length year-string) 2)
- (concat "19" year-string)
- year-string))
diff --git a/lisp/mail/mailalias.el b/lisp/mailalias.el
index 792514330fb..bfeb7c78ba7 100644
--- a/lisp/mail/mailalias.el
+++ b/lisp/mailalias.el
@@ -20,18 +20,16 @@
;; Called from sendmail-send-it, or similar functions,
;; only if some mail aliases are defined.
-(defun expand-mail-aliases (beg end &optional exclude)
+(defun expand-mail-aliases (beg end)
"Expand all mail aliases in suitable header fields found between BEG and END.
-Suitable header fields are `To', `Cc' and `Bcc' and their `Resent-' variants.
-Optional second arg EXCLUDE may be a regular expression defining text to be
-removed from alias expansions."
+Suitable header fields are To, Cc and Bcc."
(if (eq mail-aliases t)
(progn (setq mail-aliases nil) (build-mail-aliases)))
(goto-char beg)
(setq end (set-marker (make-marker) end))
(let ((case-fold-search nil))
(while (let ((case-fold-search t))
- (re-search-forward "^\\(to\\|cc\\|bcc\\|resent-to\\|resent-cc\\|resent-bcc\\):" end t))
+ (re-search-forward "^\\(to\\|cc\\|bcc\\):" end t))
(skip-chars-forward " \t")
(let ((beg1 (point))
end1 pos epos seplen
@@ -71,14 +69,6 @@ removed from alias expansions."
;; then rescan the expansion for more aliases.
(goto-char pos)
(insert translation)
- (if exclude
- (let ((regexp
- (concat "\\b\\(" exclude "\\)\\b"))
- (end (point-marker)))
- (goto-char pos)
- (while (re-search-forward regexp end t)
- (replace-match ""))
- (goto-char end)))
(delete-region (point) (+ (point) (- epos pos)))
(goto-char pos))
;; Name is not an alias. Skip to start of next name.
@@ -89,14 +79,14 @@ removed from alias expansions."
;; Called by mail-setup, or similar functions, only if ~/.mailrc exists.
(defun build-mail-aliases (&optional file)
- "Read mail aliases from ~/.mailrc and set `mail-aliases'."
+ "Read mail aliases from ~/.mailrc and set mail-aliases."
(setq file (expand-file-name (or file "~/.mailrc")))
(let ((buffer nil)
(obuf (current-buffer)))
(unwind-protect
(progn
(setq buffer (generate-new-buffer "mailrc"))
- (buffer-disable-undo buffer)
+ (buffer-flush-undo buffer)
(set-buffer buffer)
(cond ((get-file-buffer file)
(insert (save-excursion
@@ -131,9 +121,7 @@ removed from alias expansions."
;; Always autoloadable in case the user wants to define aliases
;; interactively or in .emacs.
(defun define-mail-alias (name definition)
- "Define NAME as a mail alias that translates to DEFINITION.
-This means that sending a message to NAME will actually send to DEFINITION.
-DEFINITION can be one or more mail addresses separated by commas."
+ "Define NAME as a mail-alias that translates to DEFINITION."
(interactive "sDefine mail alias: \nsDefine %s as mail alias for: ")
;; Read the defaults first, if we have not done so.
(if (eq mail-aliases t)
diff --git a/lisp/mailalias.elc b/lisp/mailalias.elc
new file mode 100644
index 00000000000..1c79288dadd
--- /dev/null
+++ b/lisp/mailalias.elc
Binary files differ
diff --git a/lisp/mail/mailpost.el b/lisp/mailpost.el
index 326d5092575..0a7c4e0a1d1 100644
--- a/lisp/mail/mailpost.el
+++ b/lisp/mailpost.el
@@ -13,9 +13,9 @@
;; (setq send-mail-function 'post-mail-send-it)
(defun post-mail-send-it ()
- "The MH -post interface for `rmail-mail' to call.
-To use it, include \"(setq send-mail-function 'post-mail-send-it)\" in
-site-init."
+ "\
+the MH -post interface for rmail-mail to call.
+to use it, include (setq send-mail-function 'post-mail-send-it) in site-init."
(let ((errbuf (if mail-interactive
(generate-new-buffer " post-mail errors")
0))
diff --git a/lisp/makesum.elc b/lisp/makesum.elc
new file mode 100644
index 00000000000..39785642e47
--- /dev/null
+++ b/lisp/makesum.elc
Binary files differ
diff --git a/lisp/man.el b/lisp/man.el
index a663373dea4..18407e44289 100644
--- a/lisp/man.el
+++ b/lisp/man.el
@@ -20,18 +20,16 @@
(defun manual-entry (topic &optional section)
"Display the Unix manual entry for TOPIC.
TOPIC is either the title of the entry, or has the form TITLE(SECTION)
-where SECTION is the desired section of the manual, as in \"tty(4)\"."
+where SECTION is the desired section of the manual, as in `tty(4)'."
(interactive "sManual entry (topic): ")
- (if (= (length topic) 0)
- (error "Must specify topic"))
(if (and (null section)
(string-match "\\`[ \t]*\\([^( \t]+\\)[ \t]*(\\(.+\\))[ \t]*\\'" topic))
(setq section (substring topic (match-beginning 2)
(match-end 2))
topic (substring topic (match-beginning 1)
(match-end 1))))
- (with-output-to-temp-buffer (concat "*" topic " Manual Entry*")
- (buffer-disable-undo standard-output)
+ (with-output-to-temp-buffer "*Manual Entry*"
+ (buffer-flush-undo standard-output)
(save-excursion
(set-buffer standard-output)
(message "Looking for formatted entry for %s%s..."
@@ -89,28 +87,11 @@ where SECTION is the desired section of the manual, as in \"tty(4)\"."
(message "Cleaning manual entry for %s..." topic)
(nuke-nroff-bs)
(set-buffer-modified-p nil)
- (setq buffer-read-only t)
- (view-mode nil 'bury-buffer)
(message ""))))
-;; Hint: BS stands for more things than "back space"
+;; Hint: BS stands form more things than "back space"
(defun nuke-nroff-bs ()
(interactive "*")
- ;; Nuke headers: "MORE(1) UNIX Programmer's Manual MORE(1)"
- ;; We expext to find a footer just before the header except at the beginning.
- (goto-char (point-min))
- (while (re-search-forward "^ *\\([A-Za-z][-_.A-Za-z0-9]*([0-9A-Z]+)\\).*\\1$" nil t)
- (let (start end)
- ;; Put START and END around footer and header and garbage blank lines.
- ;; Fixed line counts are risky, but allow us to preserve
- ;; significant blank lines.
- (setq start (save-excursion (forward-line -10) (point)))
- (setq end (save-excursion (forward-line 4) (point)))
- (delete-region start end)))
- ;; Catch the final footer.
- (goto-char (point-max))
- (delete-region (point) (save-excursion (forward-line -7) (point)))
-
;; Nuke underlining and overstriking (only by the same letter)
(goto-char (point-min))
(while (search-forward "\b" nil t)
@@ -119,9 +100,6 @@ where SECTION is the desired section of the manual, as in \"tty(4)\"."
(cond ((= preceding following)
;; x\bx
(delete-char -2))
- ((and (= preceding ?o) (= following ?\+))
- ;; o\b+
- (delete-char -2))
((= preceding ?\_)
;; _\b
(delete-char -2))
@@ -129,10 +107,28 @@ where SECTION is the desired section of the manual, as in \"tty(4)\"."
;; \b_
(delete-region (1- (point)) (1+ (point)))))))
- ;; Zap ESC7, ESC8, and ESC9.
- ;; This is for Sun man pages like "man 1 csh"
+ ;; Nuke headers: "MORE(1) UNIX Programmer's Manual MORE(1)"
+ (goto-char (point-min))
+ (while (re-search-forward "^ *\\([A-Za-z][-_A-Za-z0-9]*([0-9A-Z]+)\\).*\\1$" nil t)
+ (replace-match ""))
+
+ ;; Nuke footers: "Printed 12/3/85 27 April 1981 1"
+ ;; Sun appear to be on drugz:
+ ;; "Sun Release 3.0B Last change: 1 February 1985 1"
+ ;; HP are even worse!
+ ;; " Hewlett-Packard -1- (printed 12/31/99)" FMHWA12ID!!
+ ;; System V (well WICATs anyway):
+ ;; "Page 1 (printed 7/24/85)"
+ ;; Who is administering PCP to these corporate bozos?
(goto-char (point-min))
- (while (re-search-forward "\e[789]" nil t)
+ (while (re-search-forward
+ (cond ((eq system-type 'hpux)
+ "^[ \t]*Hewlett-Packard\\(\\| Company\\)[ \t]*- [0-9]* -.*$")
+ ((eq system-type 'usg-unix-v)
+ "^ *Page [0-9]*.*(printed [0-9/]*)$")
+ (t
+ "^\\(Printed\\|Sun Release\\) [0-9].*[0-9]$"))
+ nil t)
(replace-match ""))
;; Crunch blank lines
diff --git a/lisp/man.elc b/lisp/man.elc
new file mode 100644
index 00000000000..914039f49d4
--- /dev/null
+++ b/lisp/man.elc
Binary files differ
diff --git a/lisp/medit.el b/lisp/medit.el
index d42e67a26a3..4a37d8622d5 100644
--- a/lisp/medit.el
+++ b/lisp/medit.el
@@ -24,7 +24,7 @@
(require 'mim-mode)
-(defconst medit-zap-file (concat "/tmp/" (user-login-name) ".medit.mud")
+(defconst medit-zap-file (concat "/tmp/" (getenv "USER") ".medit.mud")
"File name for data sent to MDL by Medit.")
(defconst medit-buffer "*MEDIT*"
"Name of buffer in which Medit accumulates data to send to MDL.")
@@ -92,7 +92,7 @@ Optionally, offers to save changed files."
(defconst medit-mode-map nil)
(if (not medit-mode-map)
(progn
- (setq medit-mode-map (copy-keymap mim-mode-map))
+ (setq medit-mode-map (copy-alist mim-mode-map))
(define-key medit-mode-map "\e\z" 'medit-save-define)
(define-key medit-mode-map "\e\^z" 'medit-save-buffer)
(define-key medit-mode-map "\^xz" 'medit-goto-mdl)
diff --git a/lisp/medit.elc b/lisp/medit.elc
new file mode 100644
index 00000000000..8e803366f33
--- /dev/null
+++ b/lisp/medit.elc
Binary files differ
diff --git a/lisp/play/meese.el b/lisp/meese.el
index 5ba9dfd2ad2..5ba9dfd2ad2 100644
--- a/lisp/play/meese.el
+++ b/lisp/meese.el
diff --git a/lisp/mh-e.el b/lisp/mh-e.el
new file mode 100644
index 00000000000..16a2490e414
--- /dev/null
+++ b/lisp/mh-e.el
@@ -0,0 +1,2910 @@
+;;; mh-e.el (Version: 3.8 for GNU Emacs Version 18 and MH.5 and MH.6)
+
+(defvar mh-e-RCS-id)
+(setq mh-e-RCS-id "$Header: mh-e.el,v 3.5 92/01/21 11:21:59 gildea Exp $")
+(setq mh-e-time-stamp "92/01/21 10:59:18 gildea")
+(provide 'mh-e)
+
+;;; Copyright (c) 1985,1986,1987,1988,1990,1992 Free Software Foundation
+;;; Maintainer: Stephen Gildea <gildea@lcs.mit.edu>
+;;; Please send suggestions and corrections to the above address.
+;;;
+;;; This file contains mh-e, a GNU Emacs front end to the MH mail system.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 1, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+;;; Original version for Gosling emacs by Brian Reid, Stanford, 1982.
+;;; Modified by James Larus, BBN, July 1984 and UCB, 1984 & 1985.
+;;; Rewritten for GNU Emacs, James Larus 1985. larus@ginger.berkeley.edu
+;;; Modified by Stephen Gildea, BBN, 1988, and MIT, 1990. gildea@lcs.mit.edu
+
+
+;;; NB. MH must have been compiled with the MHE compiler flag or several
+;;; features necessary mh-e will be missing from MH commands, specifically
+;;; the -build switch to repl and forw.
+
+;;; HOW TO USE:
+;;; M-x mh-rmail to read mail. Type C-h m there for a list of commands.
+;;; C-u M-x mh-rmail to visit any folder.
+;;; M-x mh-smail to send mail. From within the mail reader, "m" works, too.
+;;; Your .emacs might benefit from these bindings:
+;;; (global-set-key "\C-xm" 'mh-smail)
+;;; (global-set-key "\C-x4m" 'mh-smail-other-window)
+;;; (global-set-key "\C-xr" 'mh-rmail) ;clobbers copy-rectangle-to-register
+
+
+
+;;; Constants:
+
+;;; Set for local environment:
+;;;* These are now in paths.el.
+;;;(defvar mh-progs "/usr/new/mh/" "Directory containing MH commands.")
+;;;(defvar mh-lib "/usr/new/lib/mh/" "Directory of MH library.")
+
+(defvar mh-redist-full-contents nil
+ "Non-nil if the `dist' command needs whole letter for redistribution.
+This is the case when `send' is compiled with the BERK option.")
+
+
+;;; Hooks:
+
+(defvar mh-folder-mode-hook nil
+ "Invoked in `mh-folder mode' on a new folder.")
+
+(defvar mh-letter-mode-hook nil
+ "Invoked in `mh-letter-mode' on a new letter.")
+
+(defvar mh-compose-letter-function nil
+ "Invoked in `mh-compose-and-send-mail' on a draft letter.
+It is passed three arguments: TO recipients, SUBJECT, and CC recipients.")
+
+(defvar mh-before-send-letter-hook nil
+ "Invoked at the beginning of the \\[mh-send-letter] command.")
+
+(defvar mh-inc-folder-hook nil
+ "Invoked after incorporating mail into a folder with \\[mh-inc-folder].")
+
+(defvar mh-before-quit-hook nil
+ "Invoked by \\[mh-quit] before quitting mh-e. See also mh-quit-hook")
+
+(defvar mh-quit-hook nil
+ "Invoked after quitting mh-e by \\[mh-quit]. See also mh-before-quit-hook")
+
+
+(defvar mh-ins-string nil
+ "Temporarily set by `mh-insert-prefix' prior to running `mh-yank-hooks'.")
+
+(defvar mh-yank-hooks
+ '(lambda ()
+ (save-excursion
+ (goto-char (point))
+ (or (bolp) (forward-line 1))
+ (while (< (point) (mark))
+ (insert mh-ins-string)
+ (forward-line 1))))
+ "Hook to run citation function.
+Expects POINT and MARK to be set to the region to cite.")
+
+
+;;; Personal preferences:
+
+(defvar mh-clean-message-header nil
+ "*Non-nil means clean headers of messages that are displayed or inserted.
+The variables `mh-visible-headers' and `mh-invisible-headers' control what
+is removed.")
+
+(defvar mh-visible-headers nil
+ "*If non-nil, contains a regexp specifying the headers to keep when cleaning.
+Only used if `mh-clean-message-header' is non-nil. Setting this variable
+overrides `mh-invisible-headers'.")
+
+(defvar mhl-formfile nil
+ "*Name of format file to be used by mhl to show messages.
+A value of T means use the default format file.
+Nil means don't use mhl to format messages.")
+
+(defvar mh-lpr-command-format "lpr -p -J '%s'"
+ "*Format for Unix command that prints a message.
+The string should be a Unix command line, with the string '%s' where
+the job's name (folder and message number) should appear. The message text
+is piped to this command.")
+
+(defvar mh-print-background nil
+ "*Print messages in the background if non-nil.
+WARNING: do not delete the messages until printing is finished;
+otherwise, your output may be truncated.")
+
+(defvar mh-summary-height 4
+ "*Number of lines in summary window (including the mode line).")
+
+(defvar mh-recenter-summary-p nil
+ "*Recenter summary window when the show window is toggled off if non-nil.")
+
+(defvar mh-ins-buf-prefix "> "
+ "*String to put before each non-blank line of a yanked or inserted message.
+Used when the message is inserted in an outgoing letter.")
+
+(defvar mh-do-not-confirm nil
+ "*Non-nil means do not prompt for confirmation before some commands.
+Only affects certain innocuous commands.")
+
+(defvar mh-bury-show-buffer t
+ "*Non-nil means that the displayed show buffer for a folder is buried.")
+
+(defvar mh-delete-yanked-msg-window nil
+ "*Controls window display when a message is yanked by \\[mh-yank-cur-msg].
+If non-nil, yanking the current message into a draft letter deletes any
+windows displaying the message.")
+
+(defvar mh-yank-from-start-of-msg t
+ "*Controls which part of a message is yanked by \\[mh-yank-cur-msg].
+If non-nil, include the entire message. If the symbol `body', then yank the
+message minus the header. If nil, yank only the portion of the message
+following the point. If the show buffer has a region, this variable is
+ignored.")
+
+(defvar mh-reply-default-reply-to nil
+ "*Sets the person or persons to whom a reply will be sent.
+If nil, prompt for recipient. If non-nil, then \\[mh-reply] will use this
+value and it should be one of \"from\", \"to\", or \"cc\".")
+
+(defvar mh-recursive-folders nil
+ "*If non-nil, then commands which operate on folders do so recursively.")
+
+(defvar mh-unshar-default-directory ""
+ "*Default for directory name prompted for by mh-unshar-msg.")
+
+
+;;; Parameterize mh-e to work with different scan formats. The defaults work
+;;; with the standard MH scan listings.
+
+(defvar mh-cmd-note 4
+ "Offset to insert notation.")
+
+(defvar mh-note-repl "-"
+ "String whose first character is used to notate replied to messages.")
+
+(defvar mh-note-forw "F"
+ "String whose first character is used to notate forwarded messages.")
+
+(defvar mh-note-dist "R"
+ "String whose first character is used to notate redistributed messages.")
+
+(defvar mh-good-msg-regexp "^....[^D^]"
+ "Regexp specifiying the scan lines that are 'good' messages.")
+
+(defvar mh-deleted-msg-regexp "^....D"
+ "Regexp matching scan lines of deleted messages.")
+
+(defvar mh-refiled-msg-regexp "^....\\^"
+ "Regexp matching scan lines of refiled messages.")
+
+(defvar mh-valid-scan-line "^ *[0-9]"
+ "Regexp matching scan lines for messages (not error messages).")
+
+(defvar mh-msg-number-regexp "^ *\\([0-9]+\\)"
+ "Regexp to find the number of a message in a scan line.
+The message's number must be surrounded with \\( \\)")
+
+(defvar mh-msg-search-regexp "^[^0-9]*%d[^0-9]"
+ "Format string containing a regexp matching the scan listing for a message.
+The desired message's number will be an argument to format.")
+
+(defvar mh-flagged-scan-msg-regexp "^....\\D\\|^....\\^\\|^....\\+\\|^.....%"
+ "Regexp matching flagged scan lines.
+Matches lines marked as deleted, refiled, in a sequence, or the cur message.")
+
+(defvar mh-cur-scan-msg-regexp "^....\\+"
+ "Regexp matching scan line for the cur message.")
+
+(defvar mh-show-buffer-mode-line-buffer-id "{%%b} %s/%d"
+ "Format string to produce `mode-line-buffer-id' for show buffers.
+First argument is folder name. Second is message number.")
+
+(defvar mh-partial-folder-mode-line-annotation "select"
+ "Annotation when displaying part of a folder.
+The string is displayed after the folder's name. NIL for no annotation.")
+
+
+;;; Real constants:
+
+(defvar mh-invisible-headers
+ "^Received: \\|^Message-Id: \\|^Remailed-\\|^Via: \\|^Mail-from: \\|^Return-Path: \\|^In-Reply-To: \\|^Resent-"
+ "Regexp matching lines in a message header that are not to be shown.
+If `mh-visible-headers' is non-nil, it is used instead to specify what
+to keep.")
+
+(defvar mh-rejected-letter-start
+ (concat "^ ----- Unsent message follows -----$" ;from mail system
+ "\\|^------- Unsent Draft$" ;from MH itself
+ "\\|^ --- The unsent message follows ---$") ;from AIX mail system
+ "Regexp specifying the beginning of the wrapper around a returned letter.
+This wrapper is generated by the mail system when rejecting a letter.")
+
+(defvar mh-to-field-choices '((?t . "To:") (?s . "Subject:") (?c . "Cc:")
+ (?b . "Bcc:") (?f . "Fcc:"))
+ "A-list of (character . field name) strings for mh-to-field.")
+
+
+;;; Global variables:
+
+(defvar mh-user-path ""
+ "User's mail folder.")
+
+(defvar mh-last-destination nil
+ "Destination of last refile or write command.")
+
+(defvar mh-folder-mode-map (make-keymap)
+ "Keymap for MH folders.")
+
+(defvar mh-letter-mode-map (copy-keymap text-mode-map)
+ "Keymap for composing mail.")
+
+(defvar mh-pick-mode-map (make-sparse-keymap)
+ "Keymap for searching folder.")
+
+(defvar mh-letter-mode-syntax-table nil
+ "Syntax table used while in mh-e letter mode.")
+
+(if mh-letter-mode-syntax-table
+ ()
+ (setq mh-letter-mode-syntax-table
+ (make-syntax-table text-mode-syntax-table))
+ (set-syntax-table mh-letter-mode-syntax-table)
+ (modify-syntax-entry ?% "." mh-letter-mode-syntax-table))
+
+(defvar mh-folder-list nil
+ "List of folder names for completion.")
+
+(defvar mh-draft-folder nil
+ "Name of folder containing draft messages.
+NIL means do not use draft folder.")
+
+(defvar mh-unseen-seq nil
+ "Name of the unseen sequence.")
+
+(defvar mh-previous-window-config nil
+ "Window configuration before mh-e command.")
+
+(defvar mh-previous-seq nil
+ "Name of the sequence to which a message was last added.")
+
+
+;;; Macros and generic functions:
+
+(defmacro mh-push (v l)
+ (list 'setq l (list 'cons v l)))
+
+
+(defmacro mh-when (pred &rest body)
+ (list 'cond (cons pred body)))
+
+
+(defmacro with-mh-folder-updating (save-modification-flag-p &rest body)
+ ;; Format is (with-mh-folder-updating (SAVE-MODIFICATION-FLAG-P) &body BODY).
+ ;; Execute BODY, which can modify the folder buffer without having to
+ ;; worry about file locking or the read-only flag, and return its result.
+ ;; If SAVE-MODIFICATION-FLAG-P is non-nil, the buffer's modification
+ ;; flag is unchanged, otherwise it is cleared.
+ (setq save-modification-flag-p (car save-modification-flag-p)) ; CL style
+ (` (let ((folder-updating-mod-flag (buffer-modified-p)))
+ (prog1
+ (let ((buffer-read-only nil)
+ (buffer-file-name nil)) ; don't let the buffer get locked
+ (,@ body))
+ (, (if save-modification-flag-p
+ '(mh-set-folder-modified-p folder-updating-mod-flag)
+ '(mh-set-folder-modified-p nil)))))))
+
+
+(defun mh-mapc (func list)
+ (while list
+ (funcall func (car list))
+ (setq list (cdr list))))
+
+
+
+;;; Entry points:
+
+;;;###autoload
+(defun mh-rmail (&optional arg)
+ "Inc(orporate) new mail (no arg) or scan a MH mail box (arg given).
+This front end uses the MH mail system, which uses different conventions
+from the usual mail system."
+ (interactive "P")
+ (mh-find-path)
+ (if arg
+ (call-interactively 'mh-visit-folder)
+ (mh-inc-folder)))
+
+
+;;;###autoload
+(defun mh-smail ()
+ "Compose and send mail with the MH mail system."
+ (interactive)
+ (mh-find-path)
+ (call-interactively 'mh-send))
+
+
+(defun mh-smail-other-window ()
+ "Compose and send mail in other window with the MH mail system."
+ (interactive)
+ (mh-find-path)
+ (call-interactively 'mh-send-other-window))
+
+
+
+;;; User executable mh-e commands:
+
+(defun mh-burst-digest ()
+ "Burst apart the current message, which should be a digest.
+The message is replaced by its table of contents and the letters from the
+digest are inserted into the folder after that message."
+ (interactive)
+ (let ((digest (mh-get-msg-num t)))
+ (mh-process-or-undo-commands mh-current-folder)
+ (mh-set-folder-modified-p t) ; lock folder while bursting
+ (message "Bursting digest...")
+ (mh-exec-cmd "burst" mh-current-folder digest "-inplace")
+ (mh-scan-folder mh-current-folder (format "%d-last" mh-first-msg-num))
+ (message "Bursting digest...done")))
+
+
+(defun mh-copy-msg (prefix-provided msg-or-seq dest)
+ "Copy specified MESSAGE(s) to another FOLDER without deleting them.
+Default is the displayed message. If optional prefix argument is
+provided, then prompt for the message sequence."
+ (interactive (list current-prefix-arg
+ (if current-prefix-arg
+ (mh-read-seq-default "Copy" t)
+ (mh-get-msg-num t))
+ (mh-prompt-for-folder "Copy to" "" t)))
+ (mh-exec-cmd "refile" msg-or-seq "-link" "-src" mh-current-folder dest)
+ (if prefix-provided
+ (mh-notate-seq msg-or-seq ?C mh-cmd-note)
+ (mh-notate msg-or-seq ?C mh-cmd-note)))
+
+
+(defun mh-delete-msg (msg-or-seq)
+ "Mark the specified MESSAGE(s) for subsequent deletion and move to the next.
+Default is the displayed message. If optional prefix argument is
+given then prompt for the message sequence."
+ (interactive (list (if current-prefix-arg
+ (mh-read-seq-default "Delete" t)
+ (mh-get-msg-num t))))
+ (if (numberp msg-or-seq)
+ (mh-delete-a-msg msg-or-seq)
+ (mh-map-to-seq-msgs 'mh-delete-a-msg msg-or-seq))
+ (mh-next-msg))
+
+
+(defun mh-delete-msg-no-motion (msg-or-seq)
+ "Mark the specified MESSAGE(s) for subsequent deletion.
+Default is the displayed message. If optional prefix argument is
+provided, then prompt for the message sequence."
+ (interactive (list (if current-prefix-arg
+ (mh-read-seq-default "Delete" t)
+ (mh-get-msg-num t))))
+ (if (numberp msg-or-seq)
+ (mh-delete-a-msg msg-or-seq)
+ (mh-map-to-seq-msgs 'mh-delete-a-msg msg-or-seq)))
+
+
+(defun mh-delete-msg-from-seq (prefix-provided msg-or-seq &optional from-seq)
+ "Delete MESSAGE (default: displayed message) from SEQUENCE.
+If optional prefix argument provided, then delete all messages
+from a sequence."
+ (interactive (let ((argp current-prefix-arg))
+ (list argp
+ (if argp
+ (mh-read-seq-default "Delete" t)
+ (mh-get-msg-num t))
+ (if (not argp)
+ (mh-read-seq-default "Delete from" t)))))
+ (if prefix-provided
+ (mh-remove-seq msg-or-seq)
+ (mh-remove-msg-from-seq msg-or-seq from-seq)))
+
+
+(defun mh-edit-again (msg)
+ "Clean-up a draft or a message previously sent and make it resendable."
+ (interactive (list (mh-get-msg-num t)))
+ (let* ((from-folder mh-current-folder)
+ (config (current-window-configuration))
+ (draft
+ (cond ((and mh-draft-folder (equal from-folder mh-draft-folder))
+ (pop-to-buffer (find-file-noselect (mh-msg-filename msg)) t)
+ (rename-buffer (format "draft-%d" msg))
+ (buffer-name))
+ (t
+ (mh-read-draft "clean-up" (mh-msg-filename msg) nil)))))
+ (mh-clean-msg-header (point-min)
+ "^Date:\\|^Received:\\|^Message-Id:\\|^From:\\|^Delivery-Date:"
+ nil)
+ (goto-char (point-min))
+ (set-buffer-modified-p nil)
+ (mh-compose-and-send-mail draft "" from-folder nil nil nil nil nil nil
+ config)))
+
+
+(defun mh-execute-commands ()
+ "Process outstanding delete and refile requests."
+ (interactive)
+ (if mh-narrowed-to-seq (mh-widen))
+ (mh-process-commands mh-current-folder)
+ (mh-set-scan-mode)
+ (mh-goto-cur-msg) ; after mh-set-scan-mode for efficiency
+ (mh-make-folder-mode-line)
+ t) ; return t for write-file-hooks
+
+
+(defun mh-extract-rejected-mail (msg)
+ "Extract a letter returned by the mail system and make it resendable.
+Default is the displayed message."
+ (interactive (list (mh-get-msg-num t)))
+ (let ((from-folder mh-current-folder)
+ (config (current-window-configuration))
+ (draft (mh-read-draft "extraction" (mh-msg-filename msg) nil)))
+ (goto-char (point-min))
+ (cond ((re-search-forward mh-rejected-letter-start nil t)
+ (forward-char 1)
+ (delete-region (point-min) (point))
+ (mh-clean-msg-header (point-min)
+ "^Date:\\|^Received:\\|^Message-Id:\\|^From:\\|^Sender:\\|^Return-Path:"
+ nil))
+ (t
+ (message "Does not appear to be a rejected letter.")))
+ (goto-char (point-min))
+ (set-buffer-modified-p nil)
+ (mh-compose-and-send-mail draft "" from-folder msg (mh-get-field "To")
+ (mh-get-field "From") (mh-get-field "cc")
+ nil nil config)))
+
+
+(defun mh-first-msg ()
+ "Move to the first message."
+ (interactive)
+ (goto-char (point-min)))
+
+
+(defun mh-forward (prefix-provided msg-or-seq to cc)
+ "Forward MESSAGE(s) (default: displayed message).
+If optional prefix argument provided, then prompt for the message sequence."
+ (interactive (list current-prefix-arg
+ (if current-prefix-arg
+ (mh-read-seq-default "Forward" t)
+ (mh-get-msg-num t))
+ (read-string "To: ")
+ (read-string "Cc: ")))
+ (let* ((folder mh-current-folder)
+ (config (current-window-configuration))
+ ;; forw always leaves file in "draft" since it doesn't have -draft
+ (draft-name (expand-file-name "draft" mh-user-path))
+ (draft (cond ((or (not (file-exists-p draft-name))
+ (y-or-n-p "The file 'draft' exists. Discard it? "))
+ (mh-exec-cmd "forw"
+ "-build" mh-current-folder msg-or-seq)
+ (prog1
+ (mh-read-draft "" draft-name t)
+ (mh-insert-fields "To:" to "Cc:" cc)
+ (set-buffer-modified-p nil)))
+ (t
+ (mh-read-draft "" draft-name nil)))))
+ (goto-char (point-min))
+ (re-search-forward "^------- Forwarded Message")
+ (forward-line -1)
+ (narrow-to-region (point) (point-max))
+ (let* ((subject (save-excursion (mh-get-field "From:")))
+ (trim (string-match "<" subject))
+ (forw-subject (save-excursion (mh-get-field "Subject:"))))
+ (if trim
+ (setq subject (substring subject 0 (1- trim))))
+ (widen)
+ (save-excursion
+ (mh-insert-fields "Subject:" (format "[%s: %s]" subject forw-subject)))
+ (delete-other-windows)
+ (if prefix-provided
+ (mh-add-msgs-to-seq (mh-seq-to-msgs msg-or-seq) 'forwarded t)
+ (mh-add-msgs-to-seq msg-or-seq 'forwarded t))
+ (mh-compose-and-send-mail draft "" folder msg-or-seq
+ to subject cc
+ mh-note-forw "Forwarded:"
+ config))))
+
+
+(defun mh-goto-msg (number &optional no-error-if-no-message dont-show)
+ "Position the cursor at message NUMBER.
+Non-nil second argument means do not signal an error if message does not exist.
+Non-nil third argument means not to show the message.
+Return non-nil if cursor is at message."
+ (interactive "NGoto message: ")
+ (let ((cur-msg (mh-get-msg-num nil))
+ (starting-place (point))
+ (msg-pattern (mh-msg-search-pat number)))
+ (cond ((cond ((and cur-msg (= cur-msg number)) t)
+ ((and cur-msg
+ (< cur-msg number)
+ (re-search-forward msg-pattern nil t)) t)
+ ((and cur-msg
+ (> cur-msg number)
+ (re-search-backward msg-pattern nil t)) t)
+ (t ; Do thorough search of buffer
+ (goto-char (point-max))
+ (re-search-backward msg-pattern nil t)))
+ (beginning-of-line)
+ (if (not dont-show) (mh-maybe-show number))
+ t)
+ (t
+ (goto-char starting-place)
+ (if (not no-error-if-no-message)
+ (error "No message %d" number))
+ nil))))
+
+
+(defun mh-inc-folder (&optional maildrop-name)
+ "Inc(orporate) new mail into +inbox.
+Optional prefix argument specifies an alternate maildrop from the default.
+If this is given, incorporate mail into the current folder, rather
+than +inbox. Run `mh-inc-folder-hook' after incorporating new mail."
+ (interactive (list (if current-prefix-arg
+ (expand-file-name
+ (read-file-name "inc mail from file: "
+ mh-user-path)))))
+ (let ((config (current-window-configuration)))
+ (if (not maildrop-name)
+ (cond ((not (get-buffer "+inbox"))
+ (mh-make-folder "+inbox")
+ (setq mh-previous-window-config config))
+ ((not (eq (current-buffer) (get-buffer "+inbox")))
+ (switch-to-buffer "+inbox")
+ (setq mh-previous-window-config config)))))
+ (mh-get-new-mail maildrop-name)
+ (run-hooks 'mh-inc-folder-hook))
+
+
+(defun mh-kill-folder ()
+ "Remove the current folder."
+ (interactive)
+ (if (or mh-do-not-confirm
+ (yes-or-no-p (format "Remove folder %s? " mh-current-folder)))
+ (let ((folder mh-current-folder))
+ (mh-set-folder-modified-p t) ; lock folder to kill it
+ (mh-exec-cmd-daemon "rmf" folder)
+ (mh-remove-folder-from-folder-list folder)
+ (message "Folder %s removed" folder)
+ (mh-set-folder-modified-p nil) ; so kill-buffer doesn't complain
+ (if (get-buffer mh-show-buffer)
+ (kill-buffer mh-show-buffer))
+ (kill-buffer folder))
+ (message "Folder not removed")))
+
+
+(defun mh-last-msg ()
+ "Move to the last message."
+ (interactive)
+ (goto-char (point-max))
+ (while (and (not (bobp)) (looking-at "^$"))
+ (forward-line -1)))
+
+
+(defun mh-list-folders ()
+ "List mail folders."
+ (interactive)
+ (with-output-to-temp-buffer " *mh-temp*"
+ (save-excursion
+ (switch-to-buffer " *mh-temp*")
+ (erase-buffer)
+ (message "Listing folders...")
+ (mh-exec-cmd-output "folders" t (if mh-recursive-folders
+ "-recurse"
+ "-norecurse"))
+ (goto-char (point-min))
+ (message "Listing folders...done"))))
+
+
+(defun mh-msg-is-in-seq (msg)
+ "Display the sequences that contain MESSAGE (default: displayed message)."
+ (interactive (list (mh-get-msg-num t)))
+ (message "Message %d is in sequences: %s"
+ msg
+ (mapconcat 'concat
+ (mh-list-to-string (mh-seq-containing-msg msg))
+ " ")))
+
+
+(defun mh-narrow-to-seq (seq)
+ "Restrict display of this folder to just messages in a sequence.
+Reads which sequence. Use \\[mh-widen] to undo this command."
+ (interactive (list (mh-read-seq "Narrow to" t)))
+ (let ((eob (point-max)))
+ (with-mh-folder-updating (t)
+ (cond ((mh-seq-to-msgs seq)
+ (mh-copy-seq-to-point seq eob)
+ (narrow-to-region eob (point-max))
+ (mh-make-folder-mode-line (symbol-name seq))
+ (mh-recenter nil)
+ (setq mh-narrowed-to-seq seq))
+ (t
+ (error "No messages in sequence `%s'" (symbol-name seq)))))))
+
+
+(defun mh-next-undeleted-msg (&optional arg)
+ "Move to next undeleted message in window."
+ (interactive "P")
+ (forward-line (prefix-numeric-value arg))
+ (setq mh-next-direction 'forward)
+ (cond ((re-search-forward mh-good-msg-regexp nil 0 arg)
+ (beginning-of-line)
+ (mh-maybe-show))
+ (t
+ (forward-line -1)
+ (if (get-buffer mh-show-buffer)
+ (delete-windows-on mh-show-buffer)))))
+
+
+(defun mh-pack-folder (range)
+ "Renumber the messages of a folder to be 1..n.
+First, offer to execute any outstanding commands for the current folder.
+If optional prefix argument provided, prompt for the range of messages
+to display after packing. Otherwise, show the entire folder."
+ (interactive (list (if current-prefix-arg
+ (mh-read-msg-range
+ "Range to scan after packing [all]? ")
+ "all")))
+ (mh-pack-folder-1 range)
+ (mh-goto-cur-msg)
+ (message "Packing folder...done"))
+
+
+(defun mh-pipe-msg (prefix-provided command)
+ "Pipe the current message through the given shell COMMAND.
+If optional prefix argument is provided, send the entire message.
+Otherwise just send the message's body."
+ (interactive
+ (list current-prefix-arg (read-string "Shell command on message: ")))
+ (save-excursion
+ (mh-display-msg (mh-get-msg-num t) mh-current-folder) ;update show buffer
+ (goto-char (point-min))
+ (if (not prefix-provided) (search-forward "\n\n"))
+ (shell-command-on-region (point) (point-max) command nil)))
+
+
+(defun mh-refile-msg (prefix-provided msg-or-seq dest)
+ "Refile MESSAGE(s) (default: displayed message) in FOLDER.
+If optional prefix argument provided, then prompt for message sequence."
+ (interactive
+ (list current-prefix-arg
+ (if current-prefix-arg
+ (mh-read-seq-default "Refile" t)
+ (mh-get-msg-num t))
+ (intern
+ (mh-prompt-for-folder "Destination"
+ (if (eq 'refile (car mh-last-destination))
+ (symbol-name (cdr mh-last-destination))
+ "")
+ t))))
+ (setq mh-last-destination (cons 'refile dest))
+ (if prefix-provided
+ (mh-map-to-seq-msgs 'mh-refile-a-msg msg-or-seq dest)
+ (mh-refile-a-msg msg-or-seq dest))
+ (mh-next-msg))
+
+
+(defun mh-refile-or-write-again (msg)
+ "Re-execute the last refile or write command on the given MESSAGE.
+Default is the displayed message. Use the same folder or file as the
+previous refile or write command."
+ (interactive (list (mh-get-msg-num t)))
+ (if (null mh-last-destination)
+ (error "No previous refile or write"))
+ (cond ((eq (car mh-last-destination) 'refile)
+ (mh-refile-a-msg msg (cdr mh-last-destination))
+ (message "Destination folder: %s" (cdr mh-last-destination)))
+ (t
+ (mh-write-msg-to-file msg (cdr mh-last-destination))
+ (message "Destination: %s" (cdr mh-last-destination))))
+ (mh-next-msg))
+
+
+(defun mh-reply (prefix-provided msg)
+ "Reply to a MESSAGE (default: displayed message).
+If optional prefix argument provided, then include the message in the reply
+using filter mhl.reply in your MH directory."
+ (interactive (list current-prefix-arg (mh-get-msg-num t)))
+ (let ((minibuffer-help-form
+ "from => Sender only\nto => Sender and primary recipients\ncc or all => Sender and all recipients"))
+ (let ((reply-to (or mh-reply-default-reply-to
+ (completing-read "Reply to whom: "
+ '(("from") ("to") ("cc") ("all"))
+ nil
+ t)))
+ (folder mh-current-folder)
+ (show-buffer mh-show-buffer)
+ (config (current-window-configuration)))
+ (message "Composing a reply...")
+ (cond ((or (equal reply-to "from") (equal reply-to ""))
+ (apply 'mh-exec-cmd
+ "repl" "-build" "-noquery"
+ "-nodraftfolder" mh-current-folder
+ msg
+ "-nocc" "all"
+ (if prefix-provided
+ (list "-filter" "mhl.reply"))))
+ ((equal reply-to "to")
+ (apply 'mh-exec-cmd
+ "repl" "-build" "-noquery"
+ "-nodraftfolder" mh-current-folder
+ msg
+ "-cc" "to"
+ (if prefix-provided
+ (list "-filter" "mhl.reply"))))
+ ((or (equal reply-to "cc") (equal reply-to "all"))
+ (apply 'mh-exec-cmd
+ "repl" "-build" "-noquery"
+ "-nodraftfolder" mh-current-folder
+ msg
+ "-cc" "all" "-nocc" "me"
+ (if prefix-provided
+ (list "-filter" "mhl.reply")))))
+
+ (let ((draft (mh-read-draft "reply"
+ (expand-file-name "reply" mh-user-path)
+ t)))
+ (delete-other-windows)
+ (set-buffer-modified-p nil)
+
+ (let ((to (mh-get-field "To:"))
+ (subject (mh-get-field "Subject:"))
+ (cc (mh-get-field "Cc:")))
+ (goto-char (point-min))
+ (mh-goto-header-end 1)
+ (if (not prefix-provided)
+ (mh-display-msg msg folder))
+ (mh-add-msgs-to-seq msg 'answered t)
+ (message "Composing a reply...done")
+ (mh-compose-and-send-mail draft "" folder msg to subject cc
+ mh-note-repl "Replied:" config))))))
+
+
+(defun mh-quit ()
+ "Quit mh-e.
+Start by running mh-before-quit-hook. Restore the previous window
+configuration, if one exists. Finish by running mh-quit-hook."
+ (interactive)
+ (run-hooks 'mh-before-quit-hook)
+ (if mh-previous-window-config
+ (set-window-configuration mh-previous-window-config))
+ (run-hooks 'mh-quit-hook))
+
+
+(defun mh-page-digest ()
+ "Advance displayed message to next digested message."
+ (interactive)
+ (save-excursion
+ (mh-show-message-in-other-window)
+ ;; Go to top of screen (in case user moved point).
+ (move-to-window-line 0)
+ (let ((case-fold-search nil))
+ ;; Search for blank line and then for From:
+ (mh-when (not (and (search-forward "\n\n" nil t)
+ (search-forward "From:" nil t)))
+ (other-window -1)
+ (error "No more messages")))
+ ;; Go back to previous blank line, then forward to the first non-blank.
+ (search-backward "\n\n" nil t)
+ (forward-line 2)
+ (mh-recenter 0)
+ (other-window -1)))
+
+
+(defun mh-page-digest-backwards ()
+ "Back up displayed message to previous digested message."
+ (interactive)
+ (save-excursion
+ (mh-show-message-in-other-window)
+ ;; Go to top of screen (in case user moved point).
+ (move-to-window-line 0)
+ (let ((case-fold-search nil))
+ (beginning-of-line)
+ (mh-when (not (and (search-backward "\n\n" nil t)
+ (search-backward "From:" nil t)))
+ (other-window -1)
+ (error "No more messages")))
+ ;; Go back to previous blank line, then forward to the first non-blank.
+ (search-backward "\n\n" nil t)
+ (forward-line 2)
+ (mh-recenter 0)
+ (other-window -1)))
+
+
+(defun mh-page-msg (&optional arg)
+ "Page the displayed message forwards.
+Scrolls ARG lines or a full screen if no argument is supplied."
+ (interactive "P")
+ (scroll-other-window arg))
+
+
+(defun mh-previous-page (&optional arg)
+ "Page the displayed message backwards.
+Scrolls ARG lines or a full screen if no argument is supplied."
+ (interactive "P")
+ (save-excursion
+ (mh-show-message-in-other-window)
+ (unwind-protect
+ (scroll-down arg)
+ (other-window -1))))
+
+
+(defun mh-previous-undeleted-msg (&optional arg)
+ "Move to previous undeleted message in window."
+ (interactive "p")
+ (setq mh-next-direction 'backward)
+ (beginning-of-line)
+ (cond ((re-search-backward mh-good-msg-regexp nil 0 arg)
+ (mh-maybe-show))
+ (t
+ (if (get-buffer mh-show-buffer)
+ (delete-windows-on mh-show-buffer)))))
+
+
+(defun mh-print-msg (prefix-provided msg-or-seq)
+ "Print MESSAGE(s) (default: displayed message) on a line printer.
+If optional prefix argument provided, then prompt for the message sequence."
+ (interactive (list current-prefix-arg
+ (if current-prefix-arg
+ (reverse (mh-seq-to-msgs
+ (mh-read-seq-default "Print" t)))
+ (mh-get-msg-num t))))
+ (if prefix-provided
+ (message "Printing sequence...")
+ (message "Printing message..."))
+ (let ((print-command
+ (if prefix-provided
+ (format "(scan -clear %s ; %s -nobell -clear %s %s) | %s"
+ (mapconcat (function (lambda (msg) msg)) msg-or-seq " ")
+ (expand-file-name "mhl" mh-lib)
+ (if (stringp mhl-formfile)
+ (format "-form %s" mhl-formfile)
+ "")
+ (mh-msg-filenames msg-or-seq)
+ (format mh-lpr-command-format
+ (if prefix-provided
+ (format "Sequence from %s" mh-current-folder)
+ (format "%s/%d" mh-current-folder
+ msg-or-seq))))
+ (format "%s -nobell -clear %s %s | %s"
+ (expand-file-name "mhl" mh-lib)
+ (mh-msg-filename msg-or-seq)
+ (if (stringp mhl-formfile)
+ (format "-form %s" mhl-formfile)
+ "")
+ (format mh-lpr-command-format
+ (if prefix-provided
+ (format "Sequence from %s" mh-current-folder)
+ (format "%s/%d" mh-current-folder
+ msg-or-seq)))))))
+ (if mh-print-background
+ (mh-exec-cmd-daemon shell-file-name "-c" print-command)
+ (call-process shell-file-name nil nil nil "-c" print-command))
+ (if prefix-provided
+ (mh-notate-seq msg-or-seq ?P mh-cmd-note)
+ (mh-notate msg-or-seq ?P mh-cmd-note))
+ (mh-add-msgs-to-seq msg-or-seq 'printed t)
+ (if prefix-provided
+ (message "Printing sequence...done")
+ (message "Printing message...done"))))
+
+
+(defun mh-put-msg-in-seq (prefix-provided from to)
+ "Add MESSAGE(s) (default: displayed message) to SEQUENCE.
+If optional prefix argument provided, then prompt for the message sequence."
+ (interactive (list current-prefix-arg
+ (if current-prefix-arg
+ (mh-seq-to-msgs
+ (mh-read-seq-default "Add messages from" t))
+ (mh-get-msg-num t))
+ (mh-read-seq-default "Add to" nil)))
+ (setq mh-previous-seq to)
+ (mh-add-msgs-to-seq from to))
+
+
+(defun mh-rescan-folder (&optional range)
+ "Rescan a folder after optionally processing the outstanding commands.
+If optional prefix argument is provided, prompt for the range of
+messages to display. Otherwise show the entire folder."
+ (interactive (list (if current-prefix-arg
+ (mh-read-msg-range "Range to scan [all]? ")
+ nil)))
+ (setq mh-next-direction 'forward)
+ (mh-scan-folder mh-current-folder (or range "all")))
+
+
+(defun mh-redistribute (to cc msg)
+ "Redistribute a letter.
+Depending on how your copy of MH was compiled, you may need to change the
+setting of the variable mh-redist-full-contents. See its documentation."
+ (interactive (list (read-string "Redist-To: ")
+ (read-string "Redist-Cc: ")
+ (mh-get-msg-num t)))
+ (save-window-excursion
+ (let ((folder mh-current-folder)
+ (draft (mh-read-draft "redistribution"
+ (if mh-redist-full-contents
+ (mh-msg-filename msg)
+ nil)
+ nil)))
+ (mh-goto-header-end 0)
+ (insert "Resent-To: " to "\n")
+ (if (not (equal cc "")) (insert "Resent-cc: " cc "\n"))
+ (mh-clean-msg-header (point-min)
+ "^Message-Id:\\|^Received:\\|^Return-Path:\\|^Sender:\\|^Date:\\|^From:"
+ nil)
+ (save-buffer)
+ (message "Redistributing...")
+ (if mh-redist-full-contents
+ (call-process "/bin/sh" nil 0 nil "-c"
+ (format "mhdist=1 mhaltmsg=%s %s -push %s"
+ (buffer-file-name)
+ (expand-file-name "send" mh-progs)
+ (buffer-file-name)))
+ (call-process "/bin/sh" nil 0 nil "-c"
+ (format "mhdist=1 mhaltmsg=%s mhannotate=1 %s -push %s"
+ (mh-msg-filename msg folder)
+ (expand-file-name "send" mh-progs)
+ (buffer-file-name))))
+ (mh-annotate-msg msg folder mh-note-dist
+ "-component" "Resent:"
+ "-text" (format "\"%s %s\"" to cc))
+ (kill-buffer draft)
+ (message "Redistributing...done"))))
+
+
+(defun mh-write-msg-to-file (msg file)
+ "Append MESSAGE to the end of a FILE."
+ (interactive
+ (list (mh-get-msg-num t)
+ (let ((default-dir (if (eq 'write (car mh-last-destination))
+ (file-name-directory (cdr mh-last-destination))
+ default-directory)))
+ (read-file-name "Save message in file: " default-dir
+ (expand-file-name "mail.out" default-dir)))))
+ (let ((file-name (mh-msg-filename msg))
+ (output-file (mh-expand-file-name file)))
+ (setq mh-last-destination (cons 'write file))
+ (save-excursion
+ (set-buffer (get-buffer-create " *mh-temp*"))
+ (erase-buffer)
+ (insert-file-contents file-name)
+ (append-to-file (point-min) (point-max) output-file))))
+
+
+(defun mh-search-folder (folder)
+ "Search FOLDER for messages matching a pattern."
+ (interactive (list (mh-prompt-for-folder "Search"
+ mh-current-folder
+ t)))
+ (switch-to-buffer-other-window "pick-pattern")
+ (if (or (zerop (buffer-size))
+ (not (y-or-n-p "Reuse pattern? ")))
+ (mh-make-pick-template)
+ (message ""))
+ (setq mh-searching-folder folder))
+
+
+(defun mh-send (to cc subject)
+ "Compose and send a letter.
+The letter is composed in mh-letter-mode; see its documentation for more
+details. If `mh-compose-letter-function' is defined, it is called on the
+draft and passed three arguments: to, subject, and cc."
+ (interactive "sTo: \nsCc: \nsSubject: ")
+ (let ((config (current-window-configuration)))
+ (delete-other-windows)
+ (mh-send-sub to cc subject config)))
+
+
+(defun mh-send-other-window (to cc subject)
+ "Compose and send a letter in another window.."
+ (interactive "sTo: \nsCc: \nsSubject: ")
+ (let ((pop-up-windows t))
+ (mh-send-sub to cc subject (current-window-configuration))))
+
+
+(defun mh-send-sub (to cc subject config)
+ "Do the real work of composing and sending a letter.
+Expects the TO, CC, and SUBJECT fields as arguments.
+CONFIG is the window configuration before sending mail."
+ (let ((folder mh-current-folder)
+ (msg-num (mh-get-msg-num nil)))
+ (message "Composing a message...")
+ (let ((draft (mh-read-draft
+ "message"
+ (if (file-exists-p
+ (expand-file-name "components" mh-user-path))
+ (expand-file-name "components" mh-user-path)
+ (if (file-exists-p
+ (expand-file-name "components" mh-lib))
+ (expand-file-name "components" mh-lib)
+ (error "Can't find components file")))
+ nil)))
+ (mh-insert-fields "To:" to "Subject:" subject "Cc:" cc)
+ (set-buffer-modified-p nil)
+ (goto-char (point-max))
+ (message "Composing a message...done")
+ (mh-compose-and-send-mail draft "" folder msg-num
+ to subject cc
+ nil nil config))))
+
+
+(defun mh-show (&optional msg)
+ "Show MESSAGE (default: displayed message).
+Forces a two-window display with the folder window on top (size
+mh-summary-height) and the show buffer below it."
+ (interactive)
+ (if (not msg)
+ (setq msg (mh-get-msg-num t)))
+ (setq mh-showing t)
+ (mh-set-mode-name "mh-e show")
+ (if (not (eql (next-window (minibuffer-window)) (selected-window)))
+ (delete-other-windows)) ; force ourself to the top window
+ (let ((folder mh-current-folder))
+ (mh-show-message-in-other-window)
+ (mh-display-msg msg folder))
+ (other-window -1)
+ (if (not (= (1+ (window-height)) (screen-height))) ;not horizontally split
+ (shrink-window (- (window-height) mh-summary-height)))
+ (mh-recenter nil)
+ (if (not (memq msg mh-seen-list)) (mh-push msg mh-seen-list)))
+
+
+(defun mh-sort-folder ()
+ "Sort the messages in the current folder by date."
+ (interactive)
+ (mh-process-or-undo-commands mh-current-folder)
+ (setq mh-next-direction 'forward)
+ (mh-set-folder-modified-p t) ; lock folder while sorting
+ (message "Sorting folder...")
+ (mh-exec-cmd "sortm" mh-current-folder)
+ (message "Sorting folder...done")
+ (mh-scan-folder mh-current-folder "all"))
+
+
+(defun mh-toggle-showing ()
+ "Toggle the scanning mode/showing mode of displaying messages."
+ (interactive)
+ (if mh-showing
+ (mh-set-scan-mode)
+ (mh-show)))
+
+
+(defun mh-undo (prefix-provided msg-or-seq)
+ "Undo the deletion or refile of the specified MESSAGE(s).
+Default is the displayed message. If optional prefix argument is
+provided, then prompt for the message sequence."
+ (interactive (list current-prefix-arg
+ (if current-prefix-arg
+ (mh-read-seq-default "Undo" t)
+ (mh-get-msg-num t))))
+ (cond (prefix-provided
+ (mh-mapc (function mh-undo-msg) (mh-seq-to-msgs msg-or-seq)))
+ (t
+ (let ((original-position (point)))
+ (beginning-of-line)
+ (while (not (or (looking-at mh-deleted-msg-regexp)
+ (looking-at mh-refiled-msg-regexp)
+ (and (eq mh-next-direction 'forward) (bobp))
+ (and (eq mh-next-direction 'backward)
+ (save-excursion (forward-line) (eobp)))))
+ (forward-line (if (eq mh-next-direction 'forward) -1 1)))
+ (if (or (looking-at mh-deleted-msg-regexp)
+ (looking-at mh-refiled-msg-regexp))
+ (progn
+ (mh-undo-msg (mh-get-msg-num t))
+ (mh-maybe-show))
+ (goto-char original-position)
+ (error "Nothing to undo")))))
+ ;; update the mh-refile-list so mh-outstanding-commands-p will work
+ (mh-mapc (function
+ (lambda (elt)
+ (if (not (mh-seq-to-msgs elt))
+ (setq mh-refile-list (delq elt mh-refile-list)))))
+ mh-refile-list)
+ (if (not (mh-outstanding-commands-p))
+ (mh-set-folder-modified-p nil)))
+
+
+(defun mh-undo-msg (msg)
+ ;; Undo the deletion or refile of one MESSAGE.
+ (cond ((memq msg mh-delete-list)
+ (setq mh-delete-list (delq msg mh-delete-list))
+ (mh-remove-msg-from-seq msg 'deleted t))
+ (t
+ (mh-mapc (function (lambda (dest)
+ (mh-remove-msg-from-seq msg dest t)))
+ mh-refile-list)))
+ (mh-notate msg ? mh-cmd-note))
+
+
+(defun mh-undo-folder (&rest ignore)
+ "Undo all commands in current folder."
+ (interactive)
+ (cond ((or mh-do-not-confirm
+ (yes-or-no-p "Undo all commands in folder? "))
+ (setq mh-delete-list nil
+ mh-refile-list nil
+ mh-seq-list nil
+ mh-next-direction 'forward)
+ (with-mh-folder-updating (nil)
+ (mh-unmark-all-headers t)))
+ (t
+ (message "Commands not undone.")
+ (sit-for 2))))
+
+
+(defun mh-unshar-msg (dir)
+ "Unpack the shar file contained in the current message into directory DIR."
+ (interactive (list (read-file-name "Unshar message in directory: "
+ mh-unshar-default-directory
+ mh-unshar-default-directory nil)))
+ (mh-display-msg (mh-get-msg-num t) mh-current-folder) ;update show buffer
+ (mh-unshar-buffer dir))
+
+(defun mh-unshar-buffer (dir)
+ ;; Unpack the shar file contained in the current buffer into directory DIR.
+ (goto-char (point-min))
+ (if (or (re-search-forward "^#![ \t]*/bin/sh" nil t)
+ (and (re-search-forward "^[^a-z0-9\"]*cut here\b" nil t)
+ (forward-line 1))
+ (re-search-forward "^#" nil t)
+ (re-search-forward "^: " nil t))
+ (let ((default-directory (expand-file-name dir))
+ (start (progn (beginning-of-line) (point)))
+ (log-buffer (get-buffer-create "*Unshar Output*")))
+ (save-excursion
+ (set-buffer log-buffer)
+ (setq default-directory (expand-file-name dir))
+ (erase-buffer)
+ (if (file-directory-p default-directory)
+ (insert "cd " dir "\n")
+ (insert "mkdir " dir "\n")
+ (call-process "mkdir" nil log-buffer t default-directory)))
+ (set-window-start (display-buffer log-buffer) 0) ;so can watch progress
+ (call-process-region start (point-max) "sh" nil log-buffer t))
+ (error "Cannot find start of shar.")))
+
+
+(defun mh-visit-folder (folder &optional range)
+ "Visit FOLDER and display RANGE of messages.
+Assumes mh-e has already been initialized."
+ (interactive (list (mh-prompt-for-folder "Visit" "+inbox" t)
+ (mh-read-msg-range "Range [all]? ")))
+ (let ((config (current-window-configuration)))
+ (mh-scan-folder folder (or range "all"))
+ (setq mh-previous-window-config config))
+ nil)
+
+
+(defun mh-widen ()
+ "Remove restrictions from the current folder, thereby showing all messages."
+ (interactive)
+ (if mh-narrowed-to-seq
+ (with-mh-folder-updating (t)
+ (delete-region (point-min) (point-max))
+ (widen)
+ (mh-make-folder-mode-line)))
+ (setq mh-narrowed-to-seq nil))
+
+
+
+;;; Support routines.
+
+(defun mh-delete-a-msg (msg)
+ ;; Delete the MESSAGE.
+ (save-excursion
+ (mh-goto-msg msg nil t)
+ (if (looking-at mh-refiled-msg-regexp)
+ (error "Message %d is refiled. Undo refile before deleting." msg))
+ (if (looking-at mh-deleted-msg-regexp)
+ nil
+ (mh-set-folder-modified-p t)
+ (mh-push msg mh-delete-list)
+ (mh-add-msgs-to-seq msg 'deleted t)
+ (mh-notate msg ?D mh-cmd-note))))
+
+
+(defun mh-refile-a-msg (msg destination)
+ ;; Refile MESSAGE in FOLDER. FOLDER is a symbol, not a string.
+ (save-excursion
+ (mh-goto-msg msg nil t)
+ (cond ((looking-at mh-deleted-msg-regexp)
+ (error "Message %d is deleted. Undo delete before moving." msg))
+ ((looking-at mh-refiled-msg-regexp)
+ (if (y-or-n-p
+ (format "Message %d already refiled. Copy to %s as well? "
+ msg destination))
+ (mh-exec-cmd "refile" (mh-get-msg-num t) "-link"
+ "-src" mh-current-folder
+ (symbol-name destination))
+ (message "Message not copied.")))
+ (t
+ (mh-set-folder-modified-p t)
+ (if (not (memq destination mh-refile-list))
+ (mh-push destination mh-refile-list))
+ (if (not (memq msg (mh-seq-to-msgs destination)))
+ (mh-add-msgs-to-seq msg destination t))
+ (mh-notate msg ?^ mh-cmd-note)))))
+
+
+(defun mh-display-msg (msg-num folder)
+ ;; Display message NUMBER of FOLDER.
+ ;; Sets the current buffer to the show buffer.
+ (set-buffer folder)
+ ;; Bind variables in folder buffer in case they are local
+ (let ((formfile mhl-formfile)
+ (clean-message-header mh-clean-message-header)
+ (invisible-headers mh-invisible-headers)
+ (visible-headers mh-visible-headers)
+ (msg-filename (mh-msg-filename msg-num))
+ (show-buffer mh-show-buffer)
+ (folder mh-current-folder))
+ (if (not (file-exists-p msg-filename))
+ (error "Message %d does not exist" msg-num))
+ (switch-to-buffer show-buffer)
+ (if mh-bury-show-buffer (bury-buffer (current-buffer)))
+ (mh-when (not (equal msg-filename buffer-file-name))
+ ;; Buffer does not yet contain message.
+ (clear-visited-file-modtime)
+ (unlock-buffer)
+ (setq buffer-file-name nil) ; no locking during setup
+ (erase-buffer)
+ (if formfile
+ (if (stringp formfile)
+ (mh-exec-lib-cmd-output "mhl" "-nobell" "-noclear"
+ "-form" formfile msg-filename)
+ (mh-exec-lib-cmd-output "mhl" "-nobell" "-noclear"
+ msg-filename))
+ (insert-file-contents msg-filename))
+ (goto-char (point-min))
+ (cond (clean-message-header
+ (mh-clean-msg-header (point-min)
+ invisible-headers
+ visible-headers)
+ (goto-char (point-min)))
+ (t
+ (let ((case-fold-search t))
+ (re-search-forward
+ "^To:\\|^From:\\|^Subject:\\|^Date:" nil t)
+ (beginning-of-line)
+ (mh-recenter 0))))
+ (set-buffer-modified-p nil)
+ (setq buffer-file-name msg-filename)
+ (set-mark nil)
+ (setq mode-line-buffer-identification
+ (list (format mh-show-buffer-mode-line-buffer-id
+ folder msg-num))))))
+
+
+(defun mh-invalidate-show-buffer ()
+ ;; Invalidate the show buffer so we must update it to use it.
+ (if (get-buffer mh-show-buffer)
+ (save-excursion
+ (set-buffer mh-show-buffer)
+ (setq buffer-file-name nil))))
+
+
+(defun mh-show-message-in-other-window ()
+ (switch-to-buffer-other-window mh-show-buffer)
+ (if mh-bury-show-buffer (bury-buffer (current-buffer))))
+
+
+(defun mh-clean-msg-header (start invisible-headers visible-headers)
+ ;; Flush extraneous lines in a message header, from the given POINT to the
+ ;; end of the message header. If VISIBLE-HEADERS is non-nil, it contains a
+ ;; regular expression specifying the lines to display, otherwise
+ ;; INVISIBLE-HEADERS contains a regular expression specifying lines to
+ ;; delete from the header.
+ (let ((case-fold-search t))
+ (save-restriction
+ (goto-char start)
+ (if (search-forward "\n\n" nil t)
+ (backward-char 1))
+ (narrow-to-region start (point))
+ (goto-char (point-min))
+ (if visible-headers
+ (while (< (point) (point-max))
+ (beginning-of-line)
+ (cond ((looking-at visible-headers)
+ (forward-line 1)
+ (while (looking-at "^[ \t]+") (forward-line 1)))
+ (t
+ (mh-delete-line 1)
+ (while (looking-at "^[ \t]+")
+ (beginning-of-line)
+ (mh-delete-line 1)))))
+ (while (re-search-forward invisible-headers nil t)
+ (beginning-of-line)
+ (mh-delete-line 1)
+ (while (looking-at "^[ \t]+")
+ (beginning-of-line)
+ (mh-delete-line 1))))
+ (unlock-buffer))))
+
+
+(defun mh-delete-line (lines)
+ ;; Delete version of kill-line.
+ (delete-region (point) (save-excursion (forward-line lines) (point))))
+
+
+(defun mh-read-draft (use initial-contents delete-contents-file)
+ ;; Read draft file into a draft buffer and make that buffer the current one.
+ ;; USE is a message used for prompting about the intended use of the message.
+ ;; INITIAL-CONTENTS is filename that is read into an empty buffer, or NIL
+ ;; if buffer should not be modified. Delete the initial-contents file if
+ ;; DELETE-CONTENTS-FILE flag is set.
+ ;; Returns the draft folder's name.
+ ;; If the draft folder facility is enabled in ~/.mh_profile, a new buffer is
+ ;; used each time and saved in the draft folder. The draft file can then be
+ ;; reused.
+ (cond (mh-draft-folder
+ (let ((orig-default-dir default-directory))
+ (pop-to-buffer (find-file-noselect (mh-new-draft-name)) t)
+ (rename-buffer (format "draft-%s" (buffer-name)))
+ (setq default-directory orig-default-dir)))
+ (t
+ (let ((draft-name (expand-file-name "draft" mh-user-path)))
+ (pop-to-buffer "draft") ; Create if necessary
+ (if (buffer-modified-p)
+ (if (y-or-n-p "Draft has been modified; kill anyway? ")
+ (set-buffer-modified-p nil)
+ (error "Draft preserved")))
+ (setq buffer-file-name draft-name)
+ (clear-visited-file-modtime)
+ (unlock-buffer)
+ (mh-when (and (file-exists-p draft-name)
+ (not (equal draft-name initial-contents)))
+ (insert-file-contents draft-name)
+ (delete-file draft-name)))))
+ (mh-when (and initial-contents
+ (or (zerop (buffer-size))
+ (not (y-or-n-p
+ (format "A draft exists. Use for %s? " use)))))
+ (erase-buffer)
+ (insert-file-contents initial-contents)
+ (if delete-contents-file (delete-file initial-contents)))
+ (auto-save-mode 1)
+ (if mh-draft-folder
+ (save-buffer)) ; Do not reuse draft name
+ (buffer-name))
+
+
+(defun mh-new-draft-name ()
+ ;; Returns the pathname of folder for draft messages.
+ (save-excursion
+ (set-buffer (get-buffer-create " *mh-temp*"))
+ (erase-buffer)
+ (mh-exec-cmd-output "mhpath" nil mh-draft-folder "new")
+ (buffer-substring (point) (1- (mark)))))
+
+
+(defun mh-next-msg ()
+ ;; Move backward or forward to the next undeleted message in the buffer.
+ (if (eq mh-next-direction 'forward)
+ (mh-next-undeleted-msg 1)
+ (mh-previous-undeleted-msg 1)))
+
+
+(defun mh-set-scan-mode ()
+ ;; Display the scan listing buffer, but do not show a message.
+ (if (get-buffer mh-show-buffer)
+ (delete-windows-on mh-show-buffer))
+ (mh-set-mode-name "mh-e scan")
+ (setq mh-showing nil)
+ (if mh-recenter-summary-p
+ (mh-recenter nil)))
+
+
+(defun mh-maybe-show (&optional msg)
+ ;; If in showing mode, then display the message pointed to by the cursor.
+ (if mh-showing (mh-show msg)))
+
+
+(defun mh-set-mode-name (mode-name-string)
+ ;; Set the mode-name and ensure that the mode line is updated.
+ (setq mode-name mode-name-string)
+ ;; Force redisplay of all buffers' mode lines to be considered.
+ (save-excursion (set-buffer (other-buffer)))
+ (set-buffer-modified-p (buffer-modified-p)))
+
+
+
+;;; The folder data abstraction.
+
+(defvar mh-current-folder nil "Name of current folder, a string.")
+(defvar mh-show-buffer nil "Buffer that displays mesage for this folder.")
+(defvar mh-folder-filename nil "Full path of directory for this folder.")
+(defvar mh-showing nil "If non-nil, show the message in a separate window.")
+(defvar mh-next-seq-num nil "Index of free sequence id.")
+(defvar mh-delete-list nil "List of msg numbers to delete.")
+(defvar mh-refile-list nil "List of folder names in mh-seq-list.")
+(defvar mh-seq-list nil "Alist of (seq . msgs) numbers.")
+(defvar mh-seen-list nil "List of displayed messages.")
+(defvar mh-next-direction 'forward "Direction to move to next message.")
+(defvar mh-narrowed-to-seq nil "Sequence display is narrowed to.")
+(defvar mh-first-msg-num nil "Number of first msg in buffer.")
+(defvar mh-last-msg-num nil "Number of last msg in buffer.")
+
+
+(defun mh-make-folder (name)
+ ;; Create and initialize a new mail folder called NAME and make it the
+ ;; current folder.
+ (switch-to-buffer name)
+ (setq buffer-read-only nil)
+ (erase-buffer)
+ (setq buffer-read-only t)
+ (mh-folder-mode)
+ (mh-set-folder-modified-p nil)
+ (setq buffer-file-name mh-folder-filename)
+ (mh-set-mode-name "mh-e scan"))
+
+
+;;; Don't use this mode when creating buffers if default-major-mode is nil.
+(put 'mh-folder-mode 'mode-class 'special)
+
+(defun mh-folder-mode ()
+ "Major mode for \"editing\" an MH folder scan listing.
+Messages can be marked for refiling and deletion. However, both actions
+are deferred until you request execution with \\[mh-execute-commands].
+\\{mh-folder-mode-map}
+ A prefix argument (\\[universal-argument]) to delete, refile, list, or undo
+applies the action to a message sequence.
+
+Variables controlling mh-e operation are (defaults in parentheses):
+
+ mh-bury-show-buffer (t)
+ Non-nil means that the buffer used to display message is buried.
+ It will never be offered as the default other buffer.
+
+ mh-clean-message-header (nil)
+ Non-nil means remove header lines matching the regular expression
+ specified in mh-invisible-headers from messages.
+
+ mh-visible-headers (nil)
+ If non-nil, it contains a regexp specifying the headers that are shown in
+ a message if mh-clean-message-header is non-nil. Setting this variable
+ overrides mh-invisible-headers.
+
+ mh-do-not-confirm (nil)
+ Non-nil means do not prompt for confirmation before executing some
+ non-recoverable commands such as mh-kill-folder and mh-undo-folder.
+
+ mhl-formfile (nil)
+ Name of format file to be used by mhl to show messages.
+ A value of T means use the default format file.
+ Nil means don't use mhl to format messages.
+
+ mh-lpr-command-format (\"lpr -p -J '%s'\")
+ Format for command used to print a message on a system printer.
+
+ mh-recenter-summary-p (nil)
+ If non-nil, then the scan listing is recentered when the window displaying
+ a messages is toggled off.
+
+ mh-summary-height (4)
+ Number of lines in the summary window including the mode line.
+
+ mh-ins-buf-prefix (\"> \")
+ String to insert before each non-blank line of a message as it is
+ inserted in a draft letter.
+
+The value of mh-folder-mode-hook is called when a new folder is set up."
+
+ (kill-all-local-variables)
+ (use-local-map mh-folder-mode-map)
+ (setq major-mode 'mh-folder-mode)
+ (mh-set-mode-name "mh-e folder")
+ (make-local-vars
+ 'mh-current-folder (buffer-name) ; Name of folder, a string
+ 'mh-show-buffer (format "show-%s" (buffer-name)) ; Buffer that displays msgs
+ 'mh-folder-filename ; e.g. "/usr/foobar/Mail/inbox/"
+ (file-name-as-directory (mh-expand-file-name (buffer-name)))
+ 'mh-showing nil ; Show message also?
+ 'mh-next-seq-num 0 ; Index of free sequence id
+ 'mh-delete-list nil ; List of msgs nums to delete
+ 'mh-refile-list nil ; List of folder names in mh-seq-list
+ 'mh-seq-list nil ; Alist of (seq . msgs) nums
+ 'mh-seen-list nil ; List of displayed messages
+ 'mh-next-direction 'forward ; Direction to move to next message
+ 'mh-narrowed-to-seq nil ; Sequence display is narrowed to
+ 'mh-first-msg-num nil ; Number of first msg in buffer
+ 'mh-last-msg-num nil ; Number of last msg in buffer
+ 'mh-previous-window-config nil) ; Previous window configuration
+ (setq truncate-lines t)
+ (auto-save-mode -1)
+ (setq buffer-offer-save t)
+ (make-local-variable 'write-file-hooks)
+ (setq write-file-hooks '(mh-execute-commands))
+ (make-local-variable 'revert-buffer-function)
+ (setq revert-buffer-function 'mh-undo-folder)
+ (run-hooks 'mh-folder-mode-hook))
+
+
+(defun make-local-vars (&rest pairs)
+ ;; Take VARIABLE-VALUE pairs and makes local variables initialized to the
+ ;; value.
+ (while pairs
+ (make-variable-buffer-local (car pairs))
+ (set (car pairs) (car (cdr pairs)))
+ (setq pairs (cdr (cdr pairs)))))
+
+
+(defun mh-scan-folder (folder range)
+ ;; Scan the FOLDER over the RANGE. Return in the folder's buffer.
+ (cond ((null (get-buffer folder))
+ (mh-make-folder folder))
+ (t
+ (mh-process-or-undo-commands folder)
+ (switch-to-buffer folder)))
+ (mh-regenerate-headers range)
+ (mh-when (zerop (buffer-size))
+ (if (equal range "all")
+ (message "Folder %s is empty" folder)
+ (message "No messages in %s, range %s" folder range))
+ (sit-for 5))
+ (mh-goto-cur-msg))
+
+
+(defun mh-regenerate-headers (range)
+ ;; Replace buffer with scan of its contents over range RANGE.
+ (let ((folder mh-current-folder))
+ (message "Scanning %s..." folder)
+ (with-mh-folder-updating (nil)
+ (erase-buffer)
+ (mh-exec-cmd-output "scan" nil
+ "-noclear" "-noheader"
+ "-width" (window-width)
+ folder range)
+ (goto-char (point-min))
+ (cond ((looking-at "scan: no messages in")
+ (keep-lines mh-valid-scan-line)) ; Flush random scan lines
+ ((looking-at "scan: ")) ; Keep error messages
+ (t
+ (keep-lines mh-valid-scan-line))) ; Flush random scan lines
+ (mh-delete-seq-locally 'cur) ; To pick up new one
+ (setq mh-seq-list (mh-read-folder-sequences folder nil))
+ (mh-notate-user-sequences)
+ (mh-make-folder-mode-line (if (equal range "all")
+ nil
+ mh-partial-folder-mode-line-annotation)))
+ (message "Scanning %s...done" folder)))
+
+
+(defun mh-get-new-mail (maildrop-name)
+ ;; Read new mail from a maildrop into the current buffer.
+ ;; Return T if there was new mail, NIL otherwise. Return in the current
+ ;; buffer.
+ (let ((point-before-inc (point))
+ (folder mh-current-folder)
+ (return-value t))
+ (with-mh-folder-updating (t)
+ (message (if maildrop-name
+ (format "inc %s -file %s..." folder maildrop-name)
+ (format "inc %s..." folder)))
+ (mh-unmark-all-headers nil)
+ (setq mh-next-direction 'forward)
+ (goto-char (point-max))
+ (let ((start-of-inc (point)))
+ (if maildrop-name
+ (mh-exec-cmd-output "inc" nil folder
+ "-file" (expand-file-name maildrop-name)
+ "-width" (window-width)
+ "-truncate")
+ (mh-exec-cmd-output "inc" nil
+ "-width" (window-width)))
+ (message
+ (if maildrop-name
+ (format "inc %s -file %s...done" folder maildrop-name)
+ (format "inc %s...done" folder)))
+ (goto-char start-of-inc)
+ (cond ((looking-at "inc: no mail")
+ (keep-lines mh-valid-scan-line) ; Flush random scan lines
+ (goto-char point-before-inc)
+ (message "No new mail%s%s" (if maildrop-name " in " "")
+ (if maildrop-name maildrop-name "")))
+ ((re-search-forward "^inc:" nil t) ; Error messages
+ (error "inc error"))
+ (t
+ (mh-delete-seq-locally 'cur) ; To pick up new one
+ (setq mh-seq-list (mh-read-folder-sequences folder t))
+ (mh-notate-user-sequences)
+ (keep-lines mh-valid-scan-line)
+ (mh-make-folder-mode-line)
+ (mh-goto-cur-msg)
+ (setq return-value t))))
+ return-value)))
+
+
+(defun mh-make-folder-mode-line (&optional annotation)
+ ;; Set the fields of the mode line for a folder buffer.
+ ;; The optional ANNOTATION string is displayed after the folder's name.
+ (save-excursion
+ (mh-first-msg)
+ (setq mh-first-msg-num (mh-get-msg-num nil))
+ (mh-last-msg)
+ (setq mh-last-msg-num (mh-get-msg-num nil))
+ (let ((lines (count-lines (point-min) (point-max))))
+ (setq mode-line-buffer-identification
+ (list (format "{%%b%s} %d msg%s"
+ (if annotation (format "/%s" annotation) "")
+ lines
+ (if (zerop lines)
+ "s"
+ (if (> lines 1)
+ (format "s (%d-%d)" mh-first-msg-num
+ mh-last-msg-num)
+ (format " (%d)" mh-first-msg-num)))))))))
+
+
+(defun mh-unmark-all-headers (remove-all-flags)
+ ;; Remove all '+' flags from the headers, and if called with a non-nil
+ ;; argument, remove all 'D', '^' and '%' flags too.
+ ;; Optimized for speed (i.e., no regular expressions).
+ (save-excursion
+ (let ((case-fold-search nil)
+ (last-line (- (point-max) mh-cmd-note))
+ char)
+ (mh-first-msg)
+ (while (<= (point) last-line)
+ (forward-char mh-cmd-note)
+ (setq char (following-char))
+ (if (or (and remove-all-flags
+ (or (eql char ?D)
+ (eql char ?^)
+ (eql char ?%)))
+ (eql char ?+))
+ (progn
+ (delete-char 1)
+ (insert " ")))
+ (forward-line)))))
+
+
+(defun mh-goto-cur-msg ()
+ ;; Position the cursor at the current message.
+ (let ((cur-msg (car (mh-seq-to-msgs 'cur))))
+ (cond ((and cur-msg
+ (mh-goto-msg cur-msg t nil))
+ (mh-notate nil ?+ mh-cmd-note)
+ (mh-recenter 0)
+ (mh-maybe-show cur-msg))
+ (t
+ (mh-last-msg)
+ (message "No current message")))))
+
+
+(defun mh-pack-folder-1 (range)
+ ;; Close and pack the current folder.
+ (mh-process-or-undo-commands mh-current-folder)
+ (message "Packing folder...")
+ (mh-set-folder-modified-p t) ; lock folder while packing
+ (save-excursion
+ (mh-exec-cmd-quiet " *mh-temp*" "folder" mh-current-folder "-pack"))
+ (mh-regenerate-headers range))
+
+
+(defun mh-process-or-undo-commands (folder)
+ ;; If FOLDER has outstanding commands, then either process or discard them.
+ (set-buffer folder)
+ (if (mh-outstanding-commands-p)
+ (if (or mh-do-not-confirm
+ (y-or-n-p
+ "Process outstanding deletes and refiles (or lose them)? "))
+ (mh-process-commands folder)
+ (mh-undo-folder))
+ (mh-invalidate-show-buffer)))
+
+
+(defun mh-process-commands (folder)
+ ;; Process outstanding commands for the folder FOLDER.
+ (message "Processing deletes and refiles for %s..." folder)
+ (set-buffer folder)
+ (with-mh-folder-updating (nil)
+ ;; Update the unseen sequence if it exists
+ (if (and mh-seen-list (mh-seq-to-msgs mh-unseen-seq))
+ (mh-undefine-sequence mh-unseen-seq mh-seen-list))
+
+ ;; Then refile messages
+ (mh-mapc
+ (function
+ (lambda (dest)
+ (let ((msgs (mh-seq-to-msgs dest)))
+ (mh-when msgs
+ (apply 'mh-exec-cmd "refile"
+ "-src" folder (symbol-name dest) msgs)
+ (mh-delete-scan-msgs msgs)))))
+ mh-refile-list)
+
+ ;; Now delete messages
+ (mh-when mh-delete-list
+ (apply 'mh-exec-cmd "rmm" folder mh-delete-list)
+ (mh-delete-scan-msgs mh-delete-list))
+
+ ;; Don't need to remove sequences since delete and refile do so.
+
+ ;; Mark cur message
+ (if (> (buffer-size) 0)
+ (mh-define-sequence 'cur (list (or (mh-get-msg-num nil) "last"))))
+
+ (mh-invalidate-show-buffer)
+
+ (setq mh-delete-list nil
+ mh-refile-list nil
+ mh-seq-list (mh-read-folder-sequences mh-current-folder nil)
+ mh-seen-list nil)
+ (mh-unmark-all-headers t)
+ (mh-notate-user-sequences)
+ (message "Processing deletes and refiles for %s...done" folder)))
+
+
+(defun mh-delete-scan-msgs (msgs)
+ ;; Delete the scan listing lines for each of the msgs in the LIST.
+ ;; Optimized for speed (i.e., no regular expressions).
+ (setq msgs (sort msgs (function <))) ;okay to clobber msgs
+ (save-excursion
+ (mh-first-msg)
+ (while (and msgs (< (point) (point-max)))
+ (cond ((equal (mh-get-msg-num nil) (car msgs))
+ (delete-region (point) (save-excursion (forward-line) (point)))
+ (setq msgs (cdr msgs)))
+ (t
+ (forward-line))))))
+
+
+(defun mh-set-folder-modified-p (flag)
+ "Mark current folder as modified or unmodified according to FLAG."
+ (set-buffer-modified-p flag))
+
+
+(defun mh-outstanding-commands-p ()
+ ;; Returns non-nil if there are outstanding deletes or refiles.
+ (or mh-delete-list mh-refile-list))
+
+
+
+;;; Mode for composing and sending a draft message.
+
+(defvar mh-sent-from-folder nil
+ "Folder of msg associated with this letter.")
+
+(defvar mh-sent-from-msg nil
+ "Number of msg associated with this letter.")
+
+(defvar mh-send-args nil
+ "Extra arguments to pass to \"send\" command.")
+
+(defvar mh-annotate-char nil
+ "Character to use to annotate mh-sent-from-msg.")
+
+(defvar mh-annotate-field nil
+ "Field name for message annotation.")
+
+(defun mh-letter-mode ()
+ "Mode for composing letters in mh-e.
+When you have finished composing, type \\[mh-send-letter] to send the letter.
+
+Variables controlling this mode (defaults in parentheses):
+
+ mh-delete-yanked-msg-window (nil)
+ If non-nil, \\[mh-yank-cur-msg] will delete any windows displaying
+ the yanked message.
+
+ mh-yank-from-start-of-msg (t)
+ If non-nil, \\[mh-yank-cur-msg] will include the entire message.
+ If `body', just yank the body (no header).
+ If nil, only the portion of the message following the point will be yanked.
+ If there is a region, this variable is ignored.
+
+Upon invoking mh-letter-mode, text-mode-hook and mh-letter-mode-hook are
+invoked with no args, if those values are non-nil.
+
+\\{mh-letter-mode-map}"
+ (interactive)
+ (kill-all-local-variables)
+ (make-local-variable 'paragraph-start)
+ (setq paragraph-start (concat "^[ \t]*[-_][-_][-_]+$\\|" paragraph-start))
+ (make-local-variable 'paragraph-separate)
+ (setq paragraph-separate
+ (concat "^[ \t]*[-_][-_][-_]+$\\|" paragraph-separate))
+ (make-local-variable 'mh-send-args)
+ (make-local-variable 'mh-annotate-char)
+ (make-local-variable 'mh-annotate-field)
+ (make-local-variable 'mh-previous-window-config)
+ (make-local-variable 'mh-sent-from-folder)
+ (make-local-variable 'mh-sent-from-msg)
+ (use-local-map mh-letter-mode-map)
+ (setq major-mode 'mh-letter-mode)
+ (mh-set-mode-name "mh-e letter")
+ (set-syntax-table mh-letter-mode-syntax-table)
+ (run-hooks 'text-mode-hook 'mh-letter-mode-hook)
+ (mh-when auto-fill-hook
+ (make-local-variable 'auto-fill-hook)
+ (setq auto-fill-hook 'mh-auto-fill-for-letter)))
+
+
+(defun mh-auto-fill-for-letter ()
+ ;; Auto-fill in letters treats the header specially by inserting a tab
+ ;; before continuation line.
+ (do-auto-fill)
+ (if (mh-in-header-p)
+ (save-excursion
+ (beginning-of-line nil)
+ (insert-char ?\t 1))))
+
+
+(defun mh-in-header-p ()
+ ;; Return non-nil if the point is in the header of a draft message.
+ (save-excursion
+ (let ((cur-point (point)))
+ (goto-char (dot-min))
+ (re-search-forward "^--------" nil t)
+ (< cur-point (point)))))
+
+
+(defun mh-to-field ()
+ "Move point to the end of a specified header field.
+The field is indicated by the previous keystroke. Create the field if
+it does not exist. Set the mark to point before moving."
+ (interactive)
+ (expand-abbrev)
+ (let ((target (cdr (assoc (logior last-input-char ?`) mh-to-field-choices)))
+ (case-fold-search t))
+ (cond ((mh-position-on-field target t)
+ (let ((eol (point)))
+ (skip-chars-backward " \t")
+ (delete-region (point) eol))
+ (if (and (not (eq (logior last-input-char ?`) ?s))
+ (save-excursion
+ (backward-char 1)
+ (not (looking-at "[:,]"))))
+ (insert ", ")
+ (insert " ")))
+ (t
+ (goto-char (dot-min))
+ (re-search-forward "^To:")
+ (forward-line 1)
+ (while (looking-at "^[ \t]") (forward-line 1))
+ (insert (format "%s \n" target))
+ (backward-char 1)))))
+
+
+(defun mh-to-fcc ()
+ "Insert an Fcc: field in the current message.
+Prompt for the field name with a completion list of the current folders."
+ (interactive)
+ (let ((last-input-char ?\C-f)
+ (folder (mh-prompt-for-folder "Fcc" "" t)))
+ (expand-abbrev)
+ (save-excursion
+ (mh-to-field)
+ (insert (substring folder 1 nil)))))
+
+
+(defun mh-insert-signature ()
+ "Insert the file ~/.signature at the current point."
+ (interactive)
+ (insert-file-contents "~/.signature")
+ (set-buffer-modified-p (buffer-modified-p))) ; force mode line update
+
+
+(defun mh-check-whom ()
+ "Verify recipients of the current letter."
+ (interactive)
+ (let ((file-name (buffer-file-name)))
+ (set-buffer-modified-p t) ; Force writing of contents
+ (save-buffer)
+ (message "Checking recipients...")
+ (switch-to-buffer-other-window "*Mail Recipients*")
+ (bury-buffer (current-buffer))
+ (erase-buffer)
+ (mh-exec-cmd-output "whom" t file-name)
+ (other-window -1)
+ (message "Checking recipients...done")))
+
+
+
+;;; Routines to make a search pattern and search for a message.
+
+(defvar mh-searching-folder nil "Folder this pick is searching.")
+
+
+(defun mh-make-pick-template ()
+ ;; Initialize the current buffer with a template for a pick pattern.
+ (erase-buffer)
+ (kill-all-local-variables)
+ (make-local-variable 'mh-searching-folder)
+ (insert "From: \n"
+ "To: \n"
+ "Cc: \n"
+ "Date: \n"
+ "Subject: \n"
+ "---------\n")
+ (mh-letter-mode)
+ (use-local-map mh-pick-mode-map)
+ (goto-char (point-min))
+ (end-of-line))
+
+
+(defun mh-do-pick-search ()
+ "Find messages that match the qualifications in the current pattern buffer.
+Messages are searched for in the folder named in mh-searching-folder.
+Put messages found in a sequence named `search'."
+ (interactive)
+ (let ((pattern-buffer (buffer-name))
+ (searching-buffer mh-searching-folder)
+ (range)
+ (pattern nil)
+ (new-buffer nil))
+ (save-excursion
+ (cond ((get-buffer searching-buffer)
+ (set-buffer searching-buffer)
+ (setq range (format "%d-%d" mh-first-msg-num mh-last-msg-num)))
+ (t
+ (mh-make-folder searching-buffer)
+ (setq range "all")
+ (setq new-buffer t))))
+ (message "Searching...")
+ (goto-char (point-min))
+ (while (setq pattern (mh-next-pick-field pattern-buffer))
+ (setq msgs (mh-seq-from-command searching-buffer
+ 'search
+ (nconc (cons "pick" pattern)
+ (list searching-buffer
+ range
+ "-sequence" "search"
+ "-list"))))
+ (setq range "search"))
+ (message "Searching...done")
+ (if new-buffer
+ (mh-scan-folder searching-buffer msgs)
+ (switch-to-buffer searching-buffer))
+ (delete-other-windows)
+ (mh-notate-seq 'search ?% (1+ mh-cmd-note))))
+
+
+(defun mh-next-pick-field (buffer)
+ ;; Return the next piece of a pick argument that can be extracted from the
+ ;; BUFFER. Returns nil if no pieces remain.
+ (set-buffer buffer)
+ (let ((case-fold-search t))
+ (cond ((eobp)
+ nil)
+ ((re-search-forward "^\\([a-z].*\\):[ \t]*\\([a-z0-9].*\\)$" nil t)
+ (let* ((component
+ (format "--%s"
+ (downcase (buffer-substring (match-beginning 1)
+ (match-end 1)))))
+ (pat (buffer-substring (match-beginning 2) (match-end 2))))
+ (forward-line 1)
+ (list component pat)))
+ ((re-search-forward "^-*$" nil t)
+ (forward-char 1)
+ (let ((body (buffer-substring (point) (point-max))))
+ (if (and (> (length body) 0) (not (equal body "\n")))
+ (list "-search" body)
+ nil)))
+ (t
+ nil))))
+
+
+
+;;; Routines to compose and send a letter.
+
+(defun mh-compose-and-send-mail (draft send-args
+ sent-from-folder sent-from-msg
+ to subject cc
+ annotate-char annotate-field
+ config)
+ ;; Edit and compose a draft message in buffer DRAFT and send or save it.
+ ;; SENT-FROM-FOLDER is buffer containing scan listing of current folder, or
+ ;; nil if none exists.
+ ;; SENT-FROM-MSG is the message number or sequence name or nil.
+ ;; SEND-ARGS is an optional argument passed to the send command.
+ ;; The TO, SUBJECT, and CC fields are passed to the
+ ;; mh-compose-letter-function.
+ ;; If ANNOTATE-CHAR is non-null, it is used to notate the scan listing of the
+ ;; message. In that case, the ANNOTATE-FIELD is used to build a string
+ ;; for mh-annotate-msg.
+ ;; CONFIG is the window configuration to restore after sending the letter.
+ (pop-to-buffer draft)
+ (mh-letter-mode)
+ (setq mh-sent-from-folder sent-from-folder)
+ (setq mh-sent-from-msg sent-from-msg)
+ (setq mh-send-args send-args)
+ (setq mh-annotate-char annotate-char)
+ (setq mh-annotate-field annotate-field)
+ (setq mh-previous-window-config config)
+ (setq mode-line-buffer-identification (list "{%b}"))
+ (if (and (boundp 'mh-compose-letter-function)
+ (symbol-value 'mh-compose-letter-function))
+ ;; run-hooks will not pass arguments.
+ (let ((value (symbol-value 'mh-compose-letter-function)))
+ (if (and (listp value) (not (eq (car value) 'lambda)))
+ (while value
+ (funcall (car value) to subject cc)
+ (setq value (cdr value)))
+ (funcall mh-compose-letter-function to subject cc)))))
+
+
+(defun mh-send-letter (&optional arg)
+ "Send the draft letter in the current buffer.
+If optional prefix argument is provided, monitor delivery.
+Run mh-before-send-letter-hook before doing anything."
+ (interactive "P")
+ (run-hooks 'mh-before-send-letter-hook)
+ (set-buffer-modified-p t) ; Make sure buffer is written
+ (save-buffer)
+ (message "Sending...")
+ (let ((draft-buffer (current-buffer))
+ (file-name (buffer-file-name))
+ (config mh-previous-window-config))
+ (cond (arg
+ (pop-to-buffer "MH mail delivery")
+ (erase-buffer)
+ (if mh-send-args
+ (mh-exec-cmd-output "send" t "-watch" "-nopush"
+ "-nodraftfolder" mh-send-args file-name)
+ (mh-exec-cmd-output "send" t "-watch" "-nopush"
+ "-nodraftfolder" file-name))
+ (goto-char (point-max)) ; show the interesting part
+ (recenter -1)
+ (set-buffer draft-buffer)) ; for annotation below
+ (mh-send-args
+ (mh-exec-cmd-daemon "send" "-nodraftfolder" "-noverbose"
+ mh-send-args file-name))
+ (t
+ (mh-exec-cmd-daemon "send" "-nodraftfolder" "-noverbose"
+ file-name)))
+
+ (if mh-annotate-char
+ (mh-annotate-msg mh-sent-from-msg
+ mh-sent-from-folder
+ mh-annotate-char
+ "-component" mh-annotate-field
+ "-text" (format "\"%s %s\""
+ (mh-get-field "To:")
+ (mh-get-field "Cc:"))))
+
+ (mh-when (or (not arg)
+ (y-or-n-p "Kill draft buffer? "))
+ (kill-buffer draft-buffer)
+ (if config
+ (set-window-configuration config)))
+ (message "Sending...done")))
+
+
+(defun mh-insert-letter (prefix-provided folder msg)
+ "Insert a message from any folder into the current letter.
+Removes the message's headers using mh-invisible-headers.
+Prefixes each non-blank line with mh-ins-buf-prefix (default \">> \").
+If optional prefix argument provided, do not indent and do not delete
+headers. Leaves the mark before the letter and point after it."
+ (interactive
+ (list current-prefix-arg
+ (mh-prompt-for-folder "Message from" mh-sent-from-folder nil)
+ (read-input (format "Message number%s: "
+ (if mh-sent-from-msg
+ (format " [%d]" mh-sent-from-msg)
+ "")))))
+ (save-restriction
+ (narrow-to-region (point) (point))
+ (let ((start (point-min)))
+ (if (equal msg "") (setq msg (int-to-string mh-sent-from-msg)))
+ (mh-exec-lib-cmd-output "mhl" "-nobell" "-noclear"
+ (expand-file-name msg
+ (mh-expand-file-name folder)))
+ (mh-when (not prefix-provided)
+ (mh-clean-msg-header start mh-invisible-headers mh-visible-headers)
+ (set-mark start) ; since mh-clean-msg-header moves it
+ (mh-insert-prefix-string mh-ins-buf-prefix)))))
+
+
+(defun mh-yank-cur-msg ()
+ "Insert the current message into the draft buffer.
+Prefix each non-blank line in the message with the string in
+`mh-ins-buf-prefix'. If a region is set in the message's buffer, then
+only the region will be inserted. Otherwise, the entire message will
+be inserted if `mh-yank-from-start-of-msg' is non-nil. If this variable
+is nil, the portion of the message following the point will be yanked.
+If `mh-delete-yanked-msg-window' is non-nil, any window displaying the
+yanked message will be deleted."
+ (interactive)
+ (if (and mh-sent-from-folder mh-sent-from-msg)
+ (let ((to-point (point))
+ (to-buffer (current-buffer)))
+ (set-buffer mh-sent-from-folder)
+ (if mh-delete-yanked-msg-window
+ (delete-windows-on mh-show-buffer))
+ (set-buffer mh-show-buffer) ; Find displayed message
+ (let ((mh-ins-str (cond ((mark)
+ (buffer-substring (region-beginning)
+ (region-end)))
+ ((eq 'body mh-yank-from-start-of-msg)
+ (buffer-substring
+ (save-excursion
+ (goto-char (point-min))
+ (mh-goto-header-end 1)
+ (point))
+ (point-max)))
+ (mh-yank-from-start-of-msg
+ (buffer-substring (point-min) (point-max)))
+ (t
+ (buffer-substring (point) (point-max))))))
+ (set-buffer to-buffer)
+ (narrow-to-region to-point to-point)
+ (push-mark)
+ (insert mh-ins-str)
+ (mh-insert-prefix-string mh-ins-buf-prefix)
+ (insert "\n")
+ (widen)))
+ (error "There is no current message")))
+
+
+(defun mh-insert-prefix-string (mh-ins-string)
+ ;; Run MH-YANK-HOOK to insert a prefix string before each line in the buffer.
+ ;; Generality for supercite users.
+ (save-excursion
+ (set-mark (point-max))
+ (goto-char (point-min))
+ (run-hooks 'mh-yank-hooks)))
+
+
+(defun mh-fully-kill-draft ()
+ "Kill the draft message file and the draft message buffer.
+Use \\[kill-buffer] if you don't want to delete the draft message file."
+ (interactive)
+ (if (y-or-n-p "Kill draft message? ")
+ (let ((config mh-previous-window-config))
+ (if (file-exists-p (buffer-file-name))
+ (delete-file (buffer-file-name)))
+ (set-buffer-modified-p nil)
+ (kill-buffer (buffer-name))
+ (message "")
+ (if config
+ (set-window-configuration config)))
+ (error "Message not killed")))
+
+
+(defun mh-recenter (arg)
+ ;; Like recenter but with two improvements: nil arg means recenter,
+ ;; and only does anything if the current buffer is in the selected
+ ;; window. (Commands like save-some-buffers can make this false.)
+ (if (eql (get-buffer-window (current-buffer))
+ (selected-window))
+ (recenter (if arg arg '(t)))))
+
+
+
+;;; Commands to manipulate sequences. Sequences are stored in an alist
+;;; of the form:
+;;; ((seq-name msgs ...) (seq-name msgs ...) ...)
+
+(defun mh-make-seq (name msgs) (cons name msgs))
+
+(defmacro mh-seq-name (pair) (list 'car pair))
+
+(defmacro mh-seq-msgs (pair) (list 'cdr pair))
+
+(defun mh-find-seq (name) (assoc name mh-seq-list))
+
+
+(defun mh-seq-to-msgs (seq)
+ "Return a list of the messages in SEQUENCE."
+ (mh-seq-msgs (mh-find-seq seq)))
+
+
+(defun mh-seq-containing-msg (msg)
+ ;; Return a list of the sequences containing MESSAGE.
+ (let ((l mh-seq-list)
+ (seqs ()))
+ (while l
+ (if (memq msg (mh-seq-msgs (car l)))
+ (mh-push (mh-seq-name (car l)) seqs))
+ (setq l (cdr l)))
+ seqs))
+
+
+(defun mh-msg-to-seq (msg)
+ ;; Given a MESSAGE number, return the first sequence in which it occurs.
+ (car (mh-seq-containing-msg msg)))
+
+
+(defun mh-read-seq-default (prompt not-empty)
+ ;; Read and return sequence name with default narrowed or previous sequence.
+ (mh-read-seq prompt not-empty (or mh-narrowed-to-seq mh-previous-seq)))
+
+
+(defun mh-read-seq (prompt not-empty &optional default)
+ ;; Read and return a sequence name. Prompt with PROMPT, raise an error
+ ;; if the sequence is empty and the NOT-EMPTY flag is non-nil, and supply
+ ;; an optional DEFAULT sequence.
+ ;; A reply of '%' defaults to the first sequence containing the current
+ ;; message.
+ (let* ((input (completing-read (format "%s %s %s" prompt "sequence:"
+ (if default
+ (format "[%s] " default)
+ ""))
+ (mh-seq-names mh-seq-list)))
+ (seq (cond ((equal input "%") (mh-msg-to-seq (mh-get-msg-num t)))
+ ((equal input "") default)
+ (t (intern input))))
+ (msgs (mh-seq-to-msgs seq)))
+ (if (and (null msgs) not-empty)
+ (error (format "No messages in sequence `%s'" seq)))
+ seq))
+
+
+(defun mh-read-folder-sequences (folder define-sequences)
+ ;; Read and return the predefined sequences for a FOLDER. If
+ ;; DEFINE-SEQUENCES is non-nil, then define mh-e's sequences before
+ ;; reading MH's sequences.
+ (let ((seqs ()))
+ (mh-when define-sequences
+ (mh-define-sequences mh-seq-list)
+ (mh-mapc (function (lambda (seq) ; Save the internal sequences
+ (if (mh-folder-name-p (mh-seq-name seq))
+ (mh-push seq seqs))))
+ mh-seq-list))
+ (save-excursion
+ (mh-exec-cmd-quiet " *mh-temp*" "mark" folder "-list")
+ (goto-char (point-min))
+ ;; look for name in line of form "cur: 4" or "myseq (private): 23"
+ (while (re-search-forward "^[^: ]+" nil t)
+ (mh-push (mh-make-seq (intern (buffer-substring (match-beginning 0)
+ (match-end 0)))
+ (mh-read-msg-list))
+ seqs))
+ (delete-region (point-min) (point))) ; avoid race with mh-process-daemon
+ seqs))
+
+
+(defun mh-seq-names (seq-list)
+ ;; Return an alist containing the names of the SEQUENCES.
+ (mapcar (function (lambda (entry) (list (symbol-name (mh-seq-name entry)))))
+ seq-list))
+
+
+(defun mh-seq-from-command (folder seq seq-command)
+ ;; In FOLDER, make a sequence named SEQ by executing COMMAND.
+ ;; COMMAND is a list. The first element is a program name
+ ;; and the subsequent elements are its arguments, all strings.
+ (let ((msg)
+ (msgs ())
+ (case-fold-search t))
+ (save-excursion
+ (save-window-excursion
+ (apply 'mh-exec-cmd-quiet " *mh-temp*" seq-command)
+ (goto-char (point-min))
+ (while (setq msg (car (mh-read-msg-list)))
+ (mh-push msg msgs)
+ (forward-line 1)))
+ (set-buffer folder)
+ (setq msgs (nreverse msgs)) ; Put in ascending order
+ (mh-push (mh-make-seq seq msgs) mh-seq-list)
+ msgs)))
+
+
+(defun mh-read-msg-list ()
+ ;; Return a list of message numbers from the current point to the end of
+ ;; the line.
+ (let ((msgs ())
+ (end-of-line (save-excursion (end-of-line) (point)))
+ num)
+ (while (re-search-forward "[0-9]+" end-of-line t)
+ (setq num (string-to-int (buffer-substring (match-beginning 0)
+ (match-end 0))))
+ (cond ((looking-at "-") ; Message range
+ (forward-char 1)
+ (re-search-forward "[0-9]+" end-of-line t)
+ (let ((num2 (string-to-int (buffer-substring (match-beginning 0)
+ (match-end 0)))))
+ (if (< num2 num)
+ (error "Bad message range: %d-%d" num num2))
+ (while (<= num num2)
+ (mh-push num msgs)
+ (setq num (1+ num)))))
+ ((not (zerop num)) (mh-push num msgs))))
+ msgs))
+
+
+(defun mh-remove-seq (seq)
+ ;; Delete the SEQUENCE.
+ (mh-map-to-seq-msgs 'mh-notate-if-in-one-seq seq ? (1+ mh-cmd-note) seq)
+ (mh-undefine-sequence seq (list "all"))
+ (mh-delete-seq-locally seq))
+
+
+(defun mh-delete-seq-locally (seq)
+ ;; Remove mh-e's record of SEQUENCE.
+ (let ((entry (mh-find-seq seq)))
+ (setq mh-seq-list (delq entry mh-seq-list))))
+
+
+(defun mh-remove-msg-from-seq (msg seq &optional internal-flag)
+ ;; Remove MESSAGE from the SEQUENCE. If optional FLAG is non-nil, do not
+ ;; inform MH of the change.
+ (let ((entry (mh-find-seq seq)))
+ (mh-when entry
+ (mh-notate-if-in-one-seq msg ? (1+ mh-cmd-note) (mh-seq-name entry))
+ (if (not internal-flag)
+ (mh-undefine-sequence seq (list msg)))
+ (setcdr entry (delq msg (mh-seq-msgs entry))))))
+
+
+(defun mh-add-msgs-to-seq (msgs seq &optional internal-flag)
+ ;; Add MESSAGE(s) to the SEQUENCE. If optional FLAG is non-nil, do not mark
+ ;; the message in the scan listing or inform MH of the addition.
+ (let ((entry (mh-find-seq seq)))
+ (if (and msgs (atom msgs)) (setq msgs (list msgs)))
+ (if (null entry)
+ (mh-push (mh-make-seq seq msgs) mh-seq-list)
+ (if msgs (setcdr entry (append msgs (cdr entry)))))
+ (mh-when (not internal-flag)
+ (mh-add-to-sequence seq msgs)
+ (mh-notate-seq seq ?% (1+ mh-cmd-note)))))
+
+
+(defun mh-rename-seq (seq new-name)
+ "Rename a SEQUENCE to have a new NAME."
+ (interactive "SOld sequence name: \nSNew name: ")
+ (let ((old-seq (mh-find-seq seq)))
+ (if old-seq
+ (rplaca old-seq new-name)
+ (error "Sequence %s does not exists" seq))
+ (mh-undefine-sequence seq (mh-seq-msgs old-seq))
+ (mh-define-sequence new-name (mh-seq-msgs old-seq))))
+
+
+(defun mh-notate-user-sequences ()
+ ;; Mark the scan listing of all messages in user-defined sequences.
+ (let ((seqs mh-seq-list)
+ name)
+ (while seqs
+ (setq name (mh-seq-name (car seqs)))
+ (if (not (mh-internal-seq name))
+ (mh-notate-seq name ?% (1+ mh-cmd-note)))
+ (setq seqs (cdr seqs)))))
+
+
+(defun mh-internal-seq (name)
+ ;; Return non-NIL if NAME is the name of an internal mh-e sequence.
+ (or (memq name '(answered cur deleted forwarded printed))
+ (eq name mh-unseen-seq)
+ (mh-folder-name-p name)))
+
+
+(defun mh-folder-name-p (name)
+ ;; Return non-NIL if NAME is possibly the name of a folder.
+ ;; A name (a string or symbol) can be a folder name if it begins with "+".
+ (if (symbolp name)
+ (eql (aref (symbol-name name) 0) ?+)
+ (eql (aref name 0) ?+)))
+
+
+(defun mh-notate-seq (seq notation offset)
+ ;; Mark the scan listing of all messages in the SEQUENCE with the CHARACTER
+ ;; at the given OFFSET from the beginning of the listing line.
+ (mh-map-to-seq-msgs 'mh-notate seq notation offset))
+
+
+(defun mh-notate-if-in-one-seq (msg notation offset seq)
+ ;; If the MESSAGE is in only the SEQUENCE, then mark the scan listing of the
+ ;; message with the CHARACTER at the given OFFSET from the beginning of the
+ ;; listing line.
+ (let ((in-seqs (mh-seq-containing-msg msg)))
+ (if (and (eq seq (car in-seqs)) (null (cdr in-seqs)))
+ (mh-notate msg notation offset))))
+
+
+(defun mh-map-to-seq-msgs (func seq &rest args)
+ ;; Invoke the FUNCTION at each message in the SEQUENCE, passing the
+ ;; remaining ARGS as arguments.
+ (save-excursion
+ (let ((msgs (mh-seq-to-msgs seq)))
+ (while msgs
+ (if (mh-goto-msg (car msgs) t t)
+ (apply func (car msgs) args))
+ (setq msgs (cdr msgs))))))
+
+
+(defun mh-map-over-seqs (func seq-list)
+ ;; Apply the FUNCTION to each element in the list of SEQUENCES,
+ ;; passing the sequence name and the list of messages as arguments.
+ (while seq-list
+ (funcall func (mh-seq-name (car seq-list)) (mh-seq-msgs (car seq-list)))
+ (setq seq-list (cdr seq-list))))
+
+
+(defun mh-define-sequences (seq-list)
+ ;; Define the sequences in SEQ-LIST.
+ (mh-map-over-seqs 'mh-define-sequence seq-list))
+
+
+(defun mh-add-to-sequence (seq msgs)
+ ;; Add to a SEQUENCE each message the list of MSGS.
+ (if (not (mh-folder-name-p seq))
+ (if msgs
+ (apply 'mh-exec-cmd "mark" mh-current-folder
+ "-sequence" (symbol-name seq)
+ "-add" msgs))))
+
+
+(defun mh-define-sequence (seq msgs)
+ ;; Define the SEQUENCE to contain the list of MSGS. Do not mark
+ ;; pseudo-sequences or empty sequences.
+ (if (and msgs
+ (not (mh-folder-name-p seq)))
+ (save-excursion
+ (apply 'mh-exec-cmd "mark" mh-current-folder
+ "-sequence" (symbol-name seq)
+ "-add" "-zero" (mh-list-to-string msgs)))))
+
+
+(defun mh-undefine-sequence (seq msgs)
+ ;; Remove from the SEQUENCE the list of MSGS.
+ (apply 'mh-exec-cmd "mark" mh-current-folder
+ "-sequence" (symbol-name seq)
+ "-delete" msgs))
+
+
+(defun mh-copy-seq-to-point (seq location)
+ ;; Copy the scan listing of the messages in SEQUENCE to after the point
+ ;; LOCATION in the current buffer.
+ (mh-map-to-seq-msgs 'mh-copy-line-to-point seq location))
+
+
+(defun mh-copy-line-to-point (msg location)
+ ;; Copy the current line to the LOCATION in the current buffer.
+ (beginning-of-line)
+ (let ((beginning-of-line (point)))
+ (forward-line 1)
+ (copy-region-as-kill beginning-of-line (point))
+ (goto-char location)
+ (yank)
+ (goto-char beginning-of-line)))
+
+
+
+;;; Issue commands to MH.
+
+(defun mh-exec-cmd (command &rest args)
+ ;; Execute MH command COMMAND with ARGS.
+ ;; Any output is assumed to be an error and is shown to the user.
+ (save-excursion
+ (set-buffer " *mh-temp*")
+ (erase-buffer)
+ (apply 'call-process
+ (expand-file-name command mh-progs) nil t nil
+ (mh-list-to-string args))
+ (if (> (buffer-size) 0)
+ (save-window-excursion
+ (switch-to-buffer-other-window " *mh-temp*")
+ (sit-for 5)))))
+
+
+(defun mh-exec-cmd-quiet (buffer command &rest args)
+ ;; In BUFFER, execute MH command COMMAND with ARGS.
+ ;; ARGS is a list of strings. Return in BUFFER, if one exists.
+ (mh-when (stringp buffer)
+ (set-buffer buffer)
+ (erase-buffer))
+ (apply 'call-process
+ (expand-file-name command mh-progs) nil buffer nil
+ args))
+
+
+(defun mh-exec-cmd-output (command display &rest args)
+ ;; Execute MH command COMMAND with DISPLAY flag and ARGS putting the output
+ ;; into buffer after point. Set mark after inserted text.
+ (push-mark (point) t)
+ (apply 'call-process
+ (expand-file-name command mh-progs) nil t display
+ (mh-list-to-string args))
+ (exchange-point-and-mark))
+
+
+(defun mh-exec-cmd-daemon (command &rest args)
+ ;; Execute MH command COMMAND with ARGS. Any output from command is
+ ;; displayed in an asynchronous pop-up window.
+ (save-excursion
+ (set-buffer (get-buffer-create " *mh-temp*"))
+ (erase-buffer))
+ (let* ((process-connection-type nil)
+ (process (apply 'start-process
+ command nil
+ (expand-file-name command mh-progs)
+ (mh-list-to-string args))))
+ (set-process-filter process 'mh-process-daemon)))
+
+
+(defun mh-process-daemon (process output)
+ ;; Process daemon that puts output into a temporary buffer.
+ (set-buffer (get-buffer-create " *mh-temp*"))
+ (insert-before-markers output)
+ (display-buffer " *mh-temp*"))
+
+
+(defun mh-exec-lib-cmd-output (command &rest args)
+ ;; Execute MH library command COMMAND with ARGS.
+ ;; Put the output into buffer after point. Set mark after inserted text.
+ (push-mark (point) t)
+ (apply 'call-process
+ (expand-file-name command mh-lib) nil t nil
+ (mh-list-to-string args))
+ (exchange-point-and-mark))
+
+
+(defun mh-list-to-string (l)
+ ;; Flattens the list L and makes every element of the new list into a string.
+ (let ((new-list nil))
+ (while l
+ (cond ((null (car l)))
+ ((symbolp (car l)) (mh-push (symbol-name (car l)) new-list))
+ ((numberp (car l)) (mh-push (int-to-string (car l)) new-list))
+ ((equal (car l) ""))
+ ((stringp (car l)) (mh-push (car l) new-list))
+ ((listp (car l))
+ (setq new-list (nconc (nreverse (mh-list-to-string (car l)))
+ new-list)))
+ (t (error "Bad element in mh-list-to-string: %s" (car l))))
+ (setq l (cdr l)))
+ (nreverse new-list)))
+
+
+
+;;; Commands to annotate a message.
+
+(defun mh-annotate-msg (msg buffer note &rest args)
+ ;; Mark the MESSAGE in BUFFER listing with the character NOTE and annotate
+ ;; the saved message with ARGS.
+ (apply 'mh-exec-cmd "anno" buffer msg args)
+ (save-excursion
+ (cond ((get-buffer buffer) ; Buffer may be deleted
+ (set-buffer buffer)
+ (if (symbolp msg)
+ (mh-notate-seq msg note (1+ mh-cmd-note))
+ (mh-notate msg note (1+ mh-cmd-note)))))))
+
+
+(defun mh-notate (msg notation offset)
+ ;; Marks MESSAGE with the character NOTATION at position OFFSET.
+ ;; Null MESSAGE means the message that the cursor points to.
+ (save-excursion
+ (if (or (null msg)
+ (mh-goto-msg msg t t))
+ (with-mh-folder-updating (t)
+ (beginning-of-line)
+ (forward-char offset)
+ (delete-char 1)
+ (insert notation)))))
+
+
+
+;;; User prompting commands.
+
+(defun mh-prompt-for-folder (prompt default can-create)
+ ;; Prompt for a folder name with PROMPT. Returns the folder's name as a
+ ;; string. DEFAULT is used if the folder exists and the user types return.
+ ;; If the CAN-CREATE flag is t, then a non-existent folder is made.
+ (let* ((prompt (format "%s folder%s" prompt
+ (if (equal "" default)
+ "? "
+ (format " [%s]? " default))))
+ name)
+ (if (null mh-folder-list)
+ (mh-set-folder-list))
+ (while (and (setq name (completing-read prompt mh-folder-list
+ nil nil "+"))
+ (equal name "")
+ (equal default "")))
+ (cond ((or (equal name "") (equal name "+"))
+ (setq name default))
+ ((not (mh-folder-name-p name))
+ (setq name (format "+%s" name))))
+ (let ((new-file-p (not (file-exists-p (mh-expand-file-name name)))))
+ (cond ((and new-file-p
+ (y-or-n-p
+ (format "Folder %s does not exist. Create it? " name)))
+ (message "Creating %s" name)
+ (call-process "mkdir" nil nil nil (mh-expand-file-name name))
+ (message "Creating %s...done" name)
+ (mh-push (list name) mh-folder-list))
+ (new-file-p
+ (error "Folder %s is not created" name))
+ (t
+ (mh-when (null (assoc name mh-folder-list))
+ (mh-push (list name) mh-folder-list)))))
+ name))
+
+
+(defun mh-set-folder-list ()
+ "Sets mh-folder-list correctly.
+A useful function for the command line or for when you need to sync by hand."
+ (setq mh-folder-list (mh-make-folder-list)))
+
+
+(defun mh-make-folder-list ()
+ "Return a list of the user's folders.
+Result is in a form suitable for completing read."
+ (interactive)
+ (message "Collecting folder names...")
+ (save-window-excursion
+ (mh-exec-cmd-quiet " *mh-temp*" "folders" "-fast"
+ (if mh-recursive-folders
+ "-recurse"
+ "-norecurse"))
+ (goto-char (point-min))
+ (let ((list nil)
+ start)
+ (while (not (eobp))
+ (setq start (point))
+ (forward-line 1)
+ (mh-push (list (format "+%s" (buffer-substring start (1- (point)))))
+ list))
+ (message "Collecting folder names...done")
+ list)))
+
+
+(defun mh-remove-folder-from-folder-list (folder)
+ ;; Remove FOLDER from the list of folders.
+ (setq mh-folder-list
+ (delq (assoc folder mh-folder-list) mh-folder-list)))
+
+
+(defun mh-read-msg-range (prompt)
+ ;; Read a list of blank-separated items.
+ (let* ((buf (read-string prompt))
+ (buf-size (length buf))
+ (start 0)
+ (input ()))
+ (while (< start buf-size)
+ (let ((next (read-from-string buf start buf-size)))
+ (mh-push (car next) input)
+ (setq start (cdr next))))
+ (nreverse input)))
+
+
+
+;;; Misc. functions.
+
+(defun mh-get-msg-num (error-if-no-message)
+ ;; Return the message number of the displayed message. If the argument
+ ;; ERROR-IF-NO-MESSAGE is non-nil, then complain if the cursor is not
+ ;; pointing to a message.
+ (save-excursion
+ (beginning-of-line)
+ (cond ((looking-at mh-msg-number-regexp)
+ (string-to-int (buffer-substring (match-beginning 1)
+ (match-end 1))))
+ (error-if-no-message
+ (error "Cursor not pointing to message"))
+ (t nil))))
+
+
+(defun mh-msg-search-pat (n)
+ ;; Return a search pattern for message N in the scan listing.
+ (format mh-msg-search-regexp n))
+
+
+(defun mh-msg-filename (msg &optional folder)
+ ;; Return the file name of MESSAGE in FOLDER (default current folder).
+ (expand-file-name (int-to-string msg)
+ (if folder
+ (mh-expand-file-name folder)
+ mh-folder-filename)))
+
+
+(defun mh-msg-filenames (msgs &optional folder)
+ ;; Return a list of file names for MSGS in FOLDER (default current folder).
+ (mapconcat (function (lambda (msg) (mh-msg-filename msg folder))) msgs " "))
+
+
+(defun mh-expand-file-name (filename &optional default)
+ "Just like `expand-file-name', but also handles MH folder names.
+Assumes that any filename that starts with '+' is a folder name."
+ (if (mh-folder-name-p filename)
+ (expand-file-name (substring filename 1) mh-user-path)
+ (expand-file-name filename default)))
+
+
+(defun mh-find-path ()
+ ;; Set mh-user-path, mh-draft-folder, and mh-unseen-seq from profile file.
+ (save-excursion
+ ;; Be sure profile is fully expanded before switching buffers
+ (let ((profile (expand-file-name (or (getenv "MH") "~/.mh_profile"))))
+ (if (not (file-exists-p profile))
+ (error "Cannot find MH profile %s" profile))
+ (set-buffer (get-buffer-create " *mh-temp*"))
+ (erase-buffer)
+ (insert-file-contents profile)
+ (setq mh-draft-folder (mh-get-field "Draft-Folder:"))
+ (cond ((equal mh-draft-folder "")
+ (setq mh-draft-folder nil))
+ ((not (mh-folder-name-p mh-draft-folder))
+ (setq mh-draft-folder (format "+%s" mh-draft-folder))))
+ (setq mh-user-path (mh-get-field "Path:"))
+ (if (equal mh-user-path "")
+ (setq mh-user-path "Mail"))
+ (setq mh-user-path
+ (file-name-as-directory
+ (expand-file-name mh-user-path (expand-file-name "~"))))
+ (if (and mh-draft-folder
+ (not (file-exists-p (mh-expand-file-name mh-draft-folder))))
+ (error "Draft folder %s does not exist. Create it and try again."
+ mh-draft-folder))
+ (setq mh-unseen-seq (mh-get-field "Unseen-Sequence:"))
+ (if (equal mh-unseen-seq "")
+ (setq mh-unseen-seq 'unseen)
+ (setq mh-unseen-seq (intern mh-unseen-seq))))))
+
+
+(defun mh-get-field (field)
+ ;; Find and return the value of field FIELD in the current buffer.
+ ;; Returns the empty string if the field is not in the message.
+ (let ((case-fold-search t))
+ (goto-char (point-min))
+ (cond ((not (re-search-forward (format "^%s" field) nil t)) "")
+ ((looking-at "[\t ]*$") "")
+ (t
+ (re-search-forward "[\t ]*\\([^\t \n].*\\)$" nil t)
+ (let ((start (match-beginning 1)))
+ (forward-line 1)
+ (while (looking-at "[ \t]")
+ (forward-line 1))
+ (buffer-substring start (1- (point))))))))
+
+
+(defun mh-insert-fields (&rest name-values)
+ ;; Insert the NAME-VALUE pairs in the current buffer.
+ ;; Do not insert any pairs whose value is the empty string.
+ (let ((case-fold-search t))
+ (while name-values
+ (let ((field-name (car name-values))
+ (value (car (cdr name-values))))
+ (mh-when (not (equal value ""))
+ (goto-char (point-min))
+ (cond ((not (re-search-forward (format "^%s" field-name) nil t))
+ (mh-goto-header-end 0)
+ (insert field-name " " value "\n"))
+ (t
+ (end-of-line)
+ (insert " " value))))
+ (setq name-values (cdr (cdr name-values)))))))
+
+
+(defun mh-position-on-field (field set-mark)
+ ;; Set point to the end of the line beginning with FIELD.
+ ;; Set the mark to the old value of point, if SET-MARK is non-nil.
+ ;; Returns non-nil iff the field was found.
+ (let ((case-fold-search t))
+ (if set-mark (push-mark))
+ (goto-char (point-min))
+ (mh-goto-header-end 0)
+ (if (re-search-backward (format "^%s" field) nil t)
+ (progn (end-of-line) t)
+ nil)))
+
+
+(defun mh-goto-header-end (arg)
+ ;; Find the end of the message header in the current buffer and position
+ ;; the cursor at the ARG'th newline after the header.
+ (if (re-search-forward "^$\\|^-+$" nil nil)
+ (forward-line arg)))
+
+
+
+;;; Build the folder-mode keymap:
+
+(suppress-keymap mh-folder-mode-map)
+(define-key mh-folder-mode-map "q" 'mh-quit)
+(define-key mh-folder-mode-map "b" 'mh-quit)
+(define-key mh-folder-mode-map "?" 'mh-msg-is-in-seq)
+(define-key mh-folder-mode-map "%" 'mh-put-msg-in-seq)
+(define-key mh-folder-mode-map "|" 'mh-pipe-msg)
+(define-key mh-folder-mode-map "\ea" 'mh-edit-again)
+(define-key mh-folder-mode-map "\e%" 'mh-delete-msg-from-seq)
+(define-key mh-folder-mode-map "\C-xn" 'mh-narrow-to-seq)
+(define-key mh-folder-mode-map "\C-xw" 'mh-widen)
+(define-key mh-folder-mode-map "\eb" 'mh-burst-digest)
+(define-key mh-folder-mode-map "\eu" 'mh-undo-folder)
+(define-key mh-folder-mode-map "\e " 'mh-page-digest)
+(define-key mh-folder-mode-map "\e\177" 'mh-page-digest-backwards)
+(define-key mh-folder-mode-map "\ee" 'mh-extract-rejected-mail)
+(define-key mh-folder-mode-map "\ef" 'mh-visit-folder)
+(define-key mh-folder-mode-map "\ek" 'mh-kill-folder)
+(define-key mh-folder-mode-map "\el" 'mh-list-folders)
+(define-key mh-folder-mode-map "\eo" 'mh-write-msg-to-file)
+(define-key mh-folder-mode-map "\ep" 'mh-pack-folder)
+(define-key mh-folder-mode-map "\es" 'mh-search-folder)
+(define-key mh-folder-mode-map "\er" 'mh-rescan-folder)
+(define-key mh-folder-mode-map "l" 'mh-print-msg)
+(define-key mh-folder-mode-map "t" 'mh-toggle-showing)
+(define-key mh-folder-mode-map "c" 'mh-copy-msg)
+(define-key mh-folder-mode-map ">" 'mh-write-msg-to-file)
+(define-key mh-folder-mode-map "i" 'mh-inc-folder)
+(define-key mh-folder-mode-map "x" 'mh-execute-commands)
+(define-key mh-folder-mode-map "e" 'mh-execute-commands)
+(define-key mh-folder-mode-map "r" 'mh-redistribute)
+(define-key mh-folder-mode-map "f" 'mh-forward)
+(define-key mh-folder-mode-map "s" 'mh-send)
+(define-key mh-folder-mode-map "m" 'mh-send)
+(define-key mh-folder-mode-map "a" 'mh-reply)
+(define-key mh-folder-mode-map "j" 'mh-goto-msg)
+(define-key mh-folder-mode-map "<" 'mh-first-msg)
+(define-key mh-folder-mode-map "g" 'mh-goto-msg)
+(define-key mh-folder-mode-map "\177" 'mh-previous-page)
+(define-key mh-folder-mode-map " " 'mh-page-msg)
+(define-key mh-folder-mode-map "." 'mh-show)
+(define-key mh-folder-mode-map "u" 'mh-undo)
+(define-key mh-folder-mode-map "!" 'mh-refile-or-write-again)
+(define-key mh-folder-mode-map "^" 'mh-refile-msg)
+(define-key mh-folder-mode-map "d" 'mh-delete-msg)
+(define-key mh-folder-mode-map "\C-d" 'mh-delete-msg-no-motion)
+(define-key mh-folder-mode-map "p" 'mh-previous-undeleted-msg)
+(define-key mh-folder-mode-map "n" 'mh-next-undeleted-msg)
+(define-key mh-folder-mode-map "o" 'mh-refile-msg)
+
+
+;;; Build the letter-mode keymap:
+
+(define-key mh-letter-mode-map "\C-c\C-f\C-b" 'mh-to-field)
+(define-key mh-letter-mode-map "\C-c\C-f\C-c" 'mh-to-field)
+(define-key mh-letter-mode-map "\C-c\C-f\C-f" 'mh-to-fcc)
+(define-key mh-letter-mode-map "\C-c\C-f\C-s" 'mh-to-field)
+(define-key mh-letter-mode-map "\C-c\C-f\C-t" 'mh-to-field)
+(define-key mh-letter-mode-map "\C-c\C-fb" 'mh-to-field)
+(define-key mh-letter-mode-map "\C-c\C-fc" 'mh-to-field)
+(define-key mh-letter-mode-map "\C-c\C-ff" 'mh-to-fcc)
+(define-key mh-letter-mode-map "\C-c\C-fs" 'mh-to-field)
+(define-key mh-letter-mode-map "\C-c\C-ft" 'mh-to-field)
+(define-key mh-letter-mode-map "\C-c\C-q" 'mh-fully-kill-draft)
+(define-key mh-letter-mode-map "\C-c\C-w" 'mh-check-whom)
+(define-key mh-letter-mode-map "\C-c\C-i" 'mh-insert-letter)
+(define-key mh-letter-mode-map "\C-c\C-y" 'mh-yank-cur-msg)
+(define-key mh-letter-mode-map "\C-c\C-s" 'mh-insert-signature)
+(define-key mh-letter-mode-map "\C-c\C-c" 'mh-send-letter)
+
+
+;;; Build the pick-mode keymap:
+
+(define-key mh-pick-mode-map "\C-c\C-c" 'mh-do-pick-search)
+(define-key mh-pick-mode-map "\C-c\C-f\C-b" 'mh-to-field)
+(define-key mh-pick-mode-map "\C-c\C-f\C-c" 'mh-to-field)
+(define-key mh-pick-mode-map "\C-c\C-f\C-f" 'mh-to-field)
+(define-key mh-pick-mode-map "\C-c\C-f\C-s" 'mh-to-field)
+(define-key mh-pick-mode-map "\C-c\C-f\C-t" 'mh-to-field)
+(define-key mh-pick-mode-map "\C-c\C-fb" 'mh-to-field)
+(define-key mh-pick-mode-map "\C-c\C-fc" 'mh-to-field)
+(define-key mh-pick-mode-map "\C-c\C-ff" 'mh-to-field)
+(define-key mh-pick-mode-map "\C-c\C-fs" 'mh-to-field)
+(define-key mh-pick-mode-map "\C-c\C-ft" 'mh-to-field)
+(define-key mh-pick-mode-map "\C-c\C-w" 'mh-check-whom)
+
+
+
+;;; For Gnu Emacs.
+;;; Local Variables: ***
+;;; eval: (put 'mh-when 'lisp-indent-hook 1) ***
+;;; eval: (put 'with-mh-folder-updating 'lisp-indent-hook 1) ***
+;;; End: ***
diff --git a/lisp/mh-e.elc b/lisp/mh-e.elc
new file mode 100644
index 00000000000..bc1a244d6ed
--- /dev/null
+++ b/lisp/mh-e.elc
@@ -0,0 +1,1128 @@
+
+(defvar mh-e-RCS-id)
+
+(setq mh-e-RCS-id "$Header: mh-e.el,v 3.5 92/01/21 11:21:59 gildea Exp $")
+
+(setq mh-e-time-stamp "92/01/21 10:59:18 gildea")
+
+(provide (quote mh-e))
+
+(defvar mh-redist-full-contents nil "\
+Non-nil if the `dist' command needs whole letter for redistribution.
+This is the case when `send' is compiled with the BERK option.")
+
+(defvar mh-folder-mode-hook nil "\
+Invoked in `mh-folder mode' on a new folder.")
+
+(defvar mh-letter-mode-hook nil "\
+Invoked in `mh-letter-mode' on a new letter.")
+
+(defvar mh-compose-letter-function nil "\
+Invoked in `mh-compose-and-send-mail' on a draft letter.
+It is passed three arguments: TO recipients, SUBJECT, and CC recipients.")
+
+(defvar mh-before-send-letter-hook nil "\
+Invoked at the beginning of the \\[mh-send-letter] command.")
+
+(defvar mh-inc-folder-hook nil "\
+Invoked after incorporating mail into a folder with \\[mh-inc-folder].")
+
+(defvar mh-before-quit-hook nil "\
+Invoked by \\[mh-quit] before quitting mh-e. See also mh-quit-hook")
+
+(defvar mh-quit-hook nil "\
+Invoked after quitting mh-e by \\[mh-quit]. See also mh-before-quit-hook")
+
+(defvar mh-ins-string nil "\
+Temporarily set by `mh-insert-prefix' prior to running `mh-yank-hooks'.")
+
+(defvar mh-yank-hooks (quote (lambda nil (save-excursion (goto-char (point)) (or (bolp) (forward-line 1)) (while (< (point) (mark)) (insert mh-ins-string) (forward-line 1))))) "\
+Hook to run citation function.
+Expects POINT and MARK to be set to the region to cite.")
+
+(defvar mh-clean-message-header nil "\
+*Non-nil means clean headers of messages that are displayed or inserted.
+The variables `mh-visible-headers' and `mh-invisible-headers' control what
+is removed.")
+
+(defvar mh-visible-headers nil "\
+*If non-nil, contains a regexp specifying the headers to keep when cleaning.
+Only used if `mh-clean-message-header' is non-nil. Setting this variable
+overrides `mh-invisible-headers'.")
+
+(defvar mhl-formfile nil "\
+*Name of format file to be used by mhl to show messages.
+A value of T means use the default format file.
+Nil means don't use mhl to format messages.")
+
+(defvar mh-lpr-command-format "lpr -p -J '%s'" "\
+*Format for Unix command that prints a message.
+The string should be a Unix command line, with the string '%s' where
+the job's name (folder and message number) should appear. The message text
+is piped to this command.")
+
+(defvar mh-print-background nil "\
+*Print messages in the background if non-nil.
+WARNING: do not delete the messages until printing is finished;
+otherwise, your output may be truncated.")
+
+(defvar mh-summary-height 4 "\
+*Number of lines in summary window (including the mode line).")
+
+(defvar mh-recenter-summary-p nil "\
+*Recenter summary window when the show window is toggled off if non-nil.")
+
+(defvar mh-ins-buf-prefix "> " "\
+*String to put before each non-blank line of a yanked or inserted message.
+Used when the message is inserted in an outgoing letter.")
+
+(defvar mh-do-not-confirm nil "\
+*Non-nil means do not prompt for confirmation before some commands.
+Only affects certain innocuous commands.")
+
+(defvar mh-bury-show-buffer t "\
+*Non-nil means that the displayed show buffer for a folder is buried.")
+
+(defvar mh-delete-yanked-msg-window nil "\
+*Controls window display when a message is yanked by \\[mh-yank-cur-msg].
+If non-nil, yanking the current message into a draft letter deletes any
+windows displaying the message.")
+
+(defvar mh-yank-from-start-of-msg t "\
+*Controls which part of a message is yanked by \\[mh-yank-cur-msg].
+If non-nil, include the entire message. If the symbol `body', then yank the
+message minus the header. If nil, yank only the portion of the message
+following the point. If the show buffer has a region, this variable is
+ignored.")
+
+(defvar mh-reply-default-reply-to nil "\
+*Sets the person or persons to whom a reply will be sent.
+If nil, prompt for recipient. If non-nil, then \\[mh-reply] will use this
+value and it should be one of \"from\", \"to\", or \"cc\".")
+
+(defvar mh-recursive-folders nil "\
+*If non-nil, then commands which operate on folders do so recursively.")
+
+(defvar mh-unshar-default-directory "" "\
+*Default for directory name prompted for by mh-unshar-msg.")
+
+(defvar mh-cmd-note 4 "\
+Offset to insert notation.")
+
+(defvar mh-note-repl "-" "\
+String whose first character is used to notate replied to messages.")
+
+(defvar mh-note-forw "F" "\
+String whose first character is used to notate forwarded messages.")
+
+(defvar mh-note-dist "R" "\
+String whose first character is used to notate redistributed messages.")
+
+(defvar mh-good-msg-regexp "^....[^D^]" "\
+Regexp specifiying the scan lines that are 'good' messages.")
+
+(defvar mh-deleted-msg-regexp "^....D" "\
+Regexp matching scan lines of deleted messages.")
+
+(defvar mh-refiled-msg-regexp "^....\\^" "\
+Regexp matching scan lines of refiled messages.")
+
+(defvar mh-valid-scan-line "^ *[0-9]" "\
+Regexp matching scan lines for messages (not error messages).")
+
+(defvar mh-msg-number-regexp "^ *\\([0-9]+\\)" "\
+Regexp to find the number of a message in a scan line.
+The message's number must be surrounded with \\( \\)")
+
+(defvar mh-msg-search-regexp "^[^0-9]*%d[^0-9]" "\
+Format string containing a regexp matching the scan listing for a message.
+The desired message's number will be an argument to format.")
+
+(defvar mh-flagged-scan-msg-regexp "^....\\D\\|^....\\^\\|^....\\+\\|^.....%" "\
+Regexp matching flagged scan lines.
+Matches lines marked as deleted, refiled, in a sequence, or the cur message.")
+
+(defvar mh-cur-scan-msg-regexp "^....\\+" "\
+Regexp matching scan line for the cur message.")
+
+(defvar mh-show-buffer-mode-line-buffer-id "{%%b} %s/%d" "\
+Format string to produce `mode-line-buffer-id' for show buffers.
+First argument is folder name. Second is message number.")
+
+(defvar mh-partial-folder-mode-line-annotation "select" "\
+Annotation when displaying part of a folder.
+The string is displayed after the folder's name. NIL for no annotation.")
+
+(defvar mh-invisible-headers "^Received: \\|^Message-Id: \\|^Remailed-\\|^Via: \\|^Mail-from: \\|^Return-Path: \\|^In-Reply-To: \\|^Resent-" "\
+Regexp matching lines in a message header that are not to be shown.
+If `mh-visible-headers' is non-nil, it is used instead to specify what
+to keep.")
+
+(defvar mh-rejected-letter-start (concat "^ ----- Unsent message follows -----$" "\\|^------- Unsent Draft$" "\\|^ --- The unsent message follows ---$") "\
+Regexp specifying the beginning of the wrapper around a returned letter.
+This wrapper is generated by the mail system when rejecting a letter.")
+
+(defvar mh-to-field-choices (quote ((116 . "To:") (115 . "Subject:") (99 . "Cc:") (98 . "Bcc:") (102 . "Fcc:"))) "\
+A-list of (character . field name) strings for mh-to-field.")
+
+(defvar mh-user-path "" "\
+User's mail folder.")
+
+(defvar mh-last-destination nil "\
+Destination of last refile or write command.")
+
+(defvar mh-folder-mode-map (make-keymap) "\
+Keymap for MH folders.")
+
+(defvar mh-letter-mode-map (copy-keymap text-mode-map) "\
+Keymap for composing mail.")
+
+(defvar mh-pick-mode-map (make-sparse-keymap) "\
+Keymap for searching folder.")
+
+(defvar mh-letter-mode-syntax-table nil "\
+Syntax table used while in mh-e letter mode.")
+
+(if mh-letter-mode-syntax-table nil (setq mh-letter-mode-syntax-table (make-syntax-table text-mode-syntax-table)) (set-syntax-table mh-letter-mode-syntax-table) (modify-syntax-entry 37 "." mh-letter-mode-syntax-table))
+
+(defvar mh-folder-list nil "\
+List of folder names for completion.")
+
+(defvar mh-draft-folder nil "\
+Name of folder containing draft messages.
+NIL means do not use draft folder.")
+
+(defvar mh-unseen-seq nil "\
+Name of the unseen sequence.")
+
+(defvar mh-previous-window-config nil "\
+Window configuration before mh-e command.")
+
+(defvar mh-previous-seq nil "\
+Name of the sequence to which a message was last added.")
+
+(defmacro mh-push (v l) (byte-code "ÂÃ EE‡" [l v setq cons] 5))
+
+(defmacro mh-when (pred &rest body) (byte-code "Â BD‡" [pred body cond] 3))
+
+(defmacro with-mh-folder-updating (save-modification-flag-p &rest body) (byte-code "@‰ˆÂÃÄÅÆ \"ƒ
+
+(defun mh-mapc (func list) (byte-code "…
+
+(defun mh-rmail (&optional arg) "\
+Inc(orporate) new mail (no arg) or scan a MH mail box (arg given).
+This front end uses the MH mail system, which uses different conventions
+from the usual mail system." (interactive "P") (byte-code "ÁˆÂ ˆƒ
+
+(defun mh-smail nil "\
+Compose and send mail with the MH mail system." (interactive) (byte-code "ÀˆÁ ˆÂÃ!‡" [nil mh-find-path call-interactively mh-send] 3))
+
+(defun mh-smail-other-window nil "\
+Compose and send mail in other window with the MH mail system." (interactive) (byte-code "ÀˆÁ ˆÂÃ!‡" [nil mh-find-path call-interactively mh-send-other-window] 3))
+
+(defun mh-burst-digest nil "\
+Burst apart the current message, which should be a digest.
+The message is replaced by its table of contents and the letters from the
+digest are inserted into the folder after that message." (interactive) (byte-code "ĈÅÁ!Æ
+!ˆÇÁ!ˆÈÉ!ˆÊË
+Ì$ˆÍ
+ÎÏ \"\"ˆÈÐ!)‡" [digest t mh-current-folder mh-first-msg-num nil mh-get-msg-num mh-process-or-undo-commands mh-set-folder-modified-p message "Bursting digest..." mh-exec-cmd "burst" "-inplace" mh-scan-folder format "%d-last" "Bursting digest...done"] 10))
+
+(defun mh-copy-msg (prefix-provided msg-or-seq dest) "\
+Copy specified MESSAGE(s) to another FOLDER without deleting them.
+Default is the displayed message. If optional prefix argument is
+provided, then prompt for the message sequence." (interactive (byte-code "ƒ
+ÊË &ˆ ƒ
+Í#‚
+Í#‡" [current-prefix-arg t msg-or-seq mh-current-folder dest prefix-provided mh-cmd-note nil mh-exec-cmd "refile" "-link" "-src" mh-notate-seq 67 mh-notate] 7))
+
+(defun mh-delete-msg (msg-or-seq) "\
+Mark the specified MESSAGE(s) for subsequent deletion and move to the next.
+Default is the displayed message. If optional prefix argument is
+given then prompt for the message sequence." (interactive (byte-code "ƒ
+!ƒ
+!‚
+\"ˆÇ ‡" [current-prefix-arg t msg-or-seq nil numberp mh-delete-a-msg mh-map-to-seq-msgs mh-next-msg] 5))
+
+(defun mh-delete-msg-no-motion (msg-or-seq) "\
+Mark the specified MESSAGE(s) for subsequent deletion.
+Default is the displayed message. If optional prefix argument is
+provided, then prompt for the message sequence." (interactive (byte-code "ƒ
+!ƒ
+!‚
+\"‡" [current-prefix-arg t msg-or-seq nil numberp mh-delete-a-msg mh-map-to-seq-msgs] 5))
+
+(defun mh-delete-msg-from-seq (prefix-provided msg-or-seq &optional from-seq) "\
+Delete MESSAGE (default: displayed message) from SEQUENCE.
+If optional prefix argument provided, then delete all messages
+from a sequence." (interactive (byte-code " ƒ
+
+(defun mh-edit-again (msg) "\
+Clean-up a draft or a message previously sent and make it resendable." (interactive (byte-code "ÁÀ!C‡" [t mh-get-msg-num] 2)) (byte-code "Lj
+È  …
++‡" [t from-folder mh-current-folder config draft mh-draft-folder msg nil current-window-configuration equal pop-to-buffer find-file-noselect mh-msg-filename rename-buffer format "draft-%d" buffer-name mh-read-draft "clean-up" mh-clean-msg-header "^Date:\\|^Received:\\|^Message-Id:\\|^From:\\|^Delivery-Date:" set-buffer-modified-p mh-compose-and-send-mail ""] 23))
+
+(defun mh-execute-commands nil "\
+Process outstanding delete and refile requests." (interactive) (byte-code "È…
+
+(defun mh-extract-rejected-mail (msg) "\
+Extract a letter returned by the mail system and make it resendable.
+Default is the displayed message." (interactive (byte-code "ÁÀ!C‡" [t mh-get-msg-num] 2)) (byte-code "ƈ
+È ÉÊË !Æ#ebˆÌÆÀ#ƒ,
++‡" [t from-folder mh-current-folder config draft msg nil mh-rejected-letter-start current-window-configuration mh-read-draft "extraction" mh-msg-filename re-search-forward forward-char 1 delete-region mh-clean-msg-header "^Date:\\|^Received:\\|^Message-Id:\\|^From:\\|^Sender:\\|^Return-Path:" message "Does not appear to be a rejected letter." set-buffer-modified-p mh-compose-and-send-mail "" mh-get-field "To" "From" "cc"] 23))
+
+(defun mh-first-msg nil "\
+Move to the first message." (interactive) (byte-code "Àˆeb‡" [nil] 1))
+
+(defun mh-forward (prefix-provided msg-or-seq to cc) "\
+Forward MESSAGE(s) (default: displayed message).
+If optional prefix argument provided, then prompt for the message sequence." (interactive (byte-code "ƒ
+$ˆßË!ˆ‚<
+  
+ó &
++,‡" [current-prefix-arg t folder mh-current-folder config draft-name mh-user-path draft msg-or-seq to cc nil subject trim forw-subject prefix-provided mh-note-forw current-window-configuration expand-file-name "draft" file-exists-p y-or-n-p "The file 'draft' exists. Discard it? " mh-exec-cmd "forw" "-build" mh-read-draft "" mh-insert-fields "To:" "Cc:" set-buffer-modified-p re-search-forward "^------- Forwarded Message" forward-line -1 narrow-to-region mh-get-field "From:" string-match "<" "Subject:" 0 widen format "[%s: %s]" delete-other-windows mh-add-msgs-to-seq mh-seq-to-msgs forwarded mh-compose-and-send-mail "Forwarded:"] 33))
+
+(defun mh-goto-msg (number &optional no-error-if-no-message dont-show) "\
+Position the cursor at message NUMBER.
+Non-nil second argument means do not signal an error if message does not exist.
+Non-nil third argument means not to show the message.
+Return non-nil if cursor is at message." (interactive "NGoto message: ") (byte-code "ÁˆÈÁ!`É !…
+bˆ?…o
+
+(defun mh-inc-folder (&optional maildrop-name) "\
+Inc(orporate) new mail into +inbox.
+Optional prefix argument specifies an alternate maildrop from the default.
+If this is given, incorporate mail into the current folder, rather
+than +inbox. Run `mh-inc-folder-hook' after incorporating new mail." (interactive (byte-code "…
+
+‰‚+
+‰)ˆË !ˆÌÍ!‡" [current-prefix-arg mh-user-path config maildrop-name mh-previous-window-config nil current-window-configuration get-buffer "+inbox" mh-make-folder switch-to-buffer mh-get-new-mail run-hooks mh-inc-folder-hook] 8))
+
+(defun mh-kill-folder nil "\
+Remove the current folder." (interactive) (byte-code "Ĉ†
+\"ˆÌ
+!ˆÍÎ
+\"ˆÉÄ!ˆÏ !…0
+!)‚;
+
+(defun mh-last-msg nil "\
+Move to the last message." (interactive) (byte-code "Àˆdbˆo?…
+
+(defun mh-list-folders nil "\
+List mail folders." (interactive) (byte-code "ˆÊÄÃ!ˆÅ ˆÆÇ!ˆÈÉÀ ƒ
+
+(defun mh-msg-is-in-seq (msg) "\
+Display the sequences that contain MESSAGE (default: displayed message)." (interactive (byte-code "ÁÀ!C‡" [t mh-get-msg-num] 2)) (byte-code "ˆÃÄ ÅÆÇÈ !!É##‡" [t msg nil message "Message %d is in sequences: %s" mapconcat concat mh-list-to-string mh-seq-containing-msg " "] 9))
+
+(defun mh-narrow-to-seq (seq) "\
+Restrict display of this folder to just messages in a sequence.
+Reads which sequence. Use \\[mh-widen] to undo this command." (interactive (byte-code "ÁÂÀ\"C‡" [t mh-read-seq "Narrow to"] 3)) (byte-code "ĈdÈ ÄÄÉ!ƒ0
+!ˆ))‡" [t eob folder-updating-mod-flag buffer-read-only nil buffer-file-name seq mh-narrowed-to-seq buffer-modified-p mh-seq-to-msgs mh-copy-seq-to-point narrow-to-region mh-make-folder-mode-line symbol-name mh-recenter error "No messages in sequence `%s'" mh-set-folder-modified-p] 12))
+
+(defun mh-next-undeleted-msg (&optional arg) "\
+Move to next undeleted message in window." (interactive "P") (byte-code "ÈÆÇ!!ˆÈ‰ˆÉ
+ÃÊ$ƒ
+
+(defun mh-pack-folder (range) "\
+Renumber the messages of a folder to be 1..n.
+First, offer to execute any outstanding commands for the current folder.
+If optional prefix argument provided, prompt for the range of messages
+to display after packing. Otherwise, show the entire folder." (interactive (byte-code "ƒ
+
+
+(defun mh-pipe-msg (prefix-provided command) "\
+Pipe the current message through the given shell COMMAND.
+If optional prefix argument is provided, send the entire message.
+Otherwise just send the message's body." (interactive (byte-code "ÁÂ!D‡" [current-prefix-arg read-string "Shell command on message: "] 3)) (byte-code "ňŠÆÇÁ!
+\"ˆebˆ ?…
+
+" shell-command-on-region] 8))
+
+(defun mh-refile-msg (prefix-provided msg-or-seq dest) "\
+Refile MESSAGE(s) (default: displayed message) in FOLDER.
+If optional prefix argument provided, then prompt for message sequence." (interactive (byte-code "ƒ
+@=ƒ
+A!‚!
+
+(defun mh-refile-or-write-again (msg) "\
+Re-execute the last refile or write command on the given MESSAGE.
+Default is the displayed message. Use the same folder or file as the
+previous refile or write command." (interactive (byte-code "ÁÀ!C‡" [t mh-get-msg-num] 2)) (byte-code "È ?…
+
+ A\"ˆÈÉ A\"‚+
+ A\"ˆÈË A\"ˆÌ ‡" [t mh-last-destination msg nil error "No previous refile or write" refile mh-refile-a-msg message "Destination folder: %s" mh-write-msg-to-file "Destination: %s" mh-next-msg] 7))
+
+(defun mh-reply (prefix-provided msg) "\
+Reply to a MESSAGE (default: displayed message).
+If optional prefix argument provided, then include the message in the reply
+using filter mhl.reply in your MH directory." (interactive (byte-code "ÂÁ!D‡" [current-prefix-arg t mh-get-msg-num] 3)) (byte-code "ňÓ †
+ØÙ!ˆÚ Û\"†*
+‚Œ
+‚Œ
+&
++),)‡" [current-prefix-arg t minibuffer-help-form reply-to mh-reply-default-reply-to nil folder mh-current-folder show-buffer mh-show-buffer config msg prefix-provided draft mh-user-path to subject cc mh-note-repl "from => Sender only
+to => Sender and primary recipients
+cc or all => Sender and all recipients" completing-read "Reply to whom: " (("from") ("to") ("cc") ("all")) current-window-configuration message "Composing a reply..." equal "from" "" apply mh-exec-cmd "repl" "-build" "-noquery" "-nodraftfolder" "-nocc" "all" "-filter" "mhl.reply" "to" "-cc" "cc" "me" mh-read-draft "reply" expand-file-name delete-other-windows set-buffer-modified-p mh-get-field "To:" "Subject:" "Cc:" mh-goto-header-end 1 mh-display-msg mh-add-msgs-to-seq answered "Composing a reply...done" mh-compose-and-send-mail "Replied:"] 33))
+
+(defun mh-quit nil "\
+Quit mh-e.
+Start by running mh-before-quit-hook. Restore the previous window
+configuration, if one exists. Finish by running mh-quit-hook." (interactive) (byte-code "ÁˆÂÃ!ˆ…
+
+(defun mh-page-digest nil "\
+Advance displayed message to next digested message." (interactive) (byte-code "ÁˆŠÃ ˆÄÅ!ˆÁÆÇÁÂ#…
+
+" "From:" other-window -1 error "No more messages" search-backward forward-line 2 mh-recenter] 11))
+
+(defun mh-page-digest-backwards nil "\
+Back up displayed message to previous digested message." (interactive) (byte-code "ÁˆŠÃ ˆÄÅ!ˆÁÆ ˆÇÈÁÂ#…
+
+" "From:" other-window -1 error "No more messages" forward-line 2 mh-recenter] 12))
+
+(defun mh-page-msg (&optional arg) "\
+Page the displayed message forwards.
+Scrolls ARG lines or a full screen if no argument is supplied." (interactive "P") (byte-code "ÁˆÂ!‡" [arg nil scroll-other-window] 2))
+
+(defun mh-previous-page (&optional arg) "\
+Page the displayed message backwards.
+Scrolls ARG lines or a full screen if no argument is supplied." (interactive "P") (byte-code "ÁˆŠÂ ˆÃŽÄ!))‡" [arg nil mh-show-message-in-other-window ((byte-code "ÀÁ!‡" [other-window -1] 2)) scroll-down] 3))
+
+(defun mh-previous-undeleted-msg (&optional arg) "\
+Move to previous undeleted message in window." (interactive "p") (byte-code "ˆƉˆÇ ˆÈ ÂÉ $ƒ
+
+(defun mh-print-msg (prefix-provided msg-or-seq) "\
+Print MESSAGE(s) (default: displayed message) on a line printer.
+If optional prefix argument provided, then prompt for the message sequence." (interactive (byte-code "ƒ
+ƒL
+ƒ@
+ƒs
+ß #‚”
+ËËËß &ˆ
+Ģ
+ƒ¹
+
+(defun mh-put-msg-in-seq (prefix-provided from to) "\
+Add MESSAGE(s) (default: displayed message) to SEQUENCE.
+If optional prefix argument provided, then prompt for the message sequence." (interactive (byte-code "ƒ
+
+(defun mh-rescan-folder (&optional range) "\
+Rescan a folder after optionally processing the outstanding commands.
+If optional prefix argument is provided, prompt for the range of
+messages to display. Otherwise show the entire folder." (interactive (byte-code "ƒ
+
+
+(defun mh-redistribute (to cc msg) "\
+Redistribute a letter.
+Depending on how your copy of MH was compiled, you may need to change the
+setting of the variable mh-redist-full-contents. See its documentation." (interactive (byte-code "ÁÂ!ÁÃ!ÄÀ!E‡" [t read-string "Redist-To: " "Redist-Cc: " mh-get-msg-num] 6)) (byte-code "ƈˋ‡" [t folder mh-current-folder draft mh-redist-full-contents msg nil to cc mh-progs mh-note-dist ((byte-code " ÊË ƒ
+!ˆØé!*‡" [folder mh-current-folder draft mh-redist-full-contents msg nil to cc mh-progs mh-note-dist mh-read-draft "redistribution" mh-msg-filename mh-goto-header-end 0 insert "Resent-To: " "
+" equal "" "Resent-cc: " mh-clean-msg-header "^Message-Id:\\|^Received:\\|^Return-Path:\\|^Sender:\\|^Date:\\|^From:" save-buffer message "Redistributing..." call-process "/bin/sh" "-c" format "mhdist=1 mhaltmsg=%s %s -push %s" buffer-file-name expand-file-name "send" "mhdist=1 mhaltmsg=%s mhannotate=1 %s -push %s" mh-annotate-msg "-component" "Resent:" "-text" "\"%s %s\"" kill-buffer "Redistributing...done"] 30))] 1))
+
+(defun mh-write-msg-to-file (msg file) "\
+Append MESSAGE to the end of a FILE." (interactive (byte-code "ÄÀ!Å
+@=ƒ
+A!‚
+
+(defun mh-search-folder (folder) "\
+Search FOLDER for messages matching a pattern." (interactive (byte-code "ÂÃÁ#C‡" [mh-current-folder t mh-prompt-for-folder "Search"] 4)) (byte-code "ĈÅÆ!ˆÇÈ !†
+
+(defun mh-send (to cc subject) "\
+Compose and send a letter.
+The letter is composed in mh-letter-mode; see its documentation for more
+details. If `mh-compose-letter-function' is defined, it is called on the
+draft and passed three arguments: to, subject, and cc." (interactive "sTo:
+sCc:
+sSubject: ") (byte-code "ĈŠÆ ˆÇ
+ $)‡" [config to cc subject nil current-window-configuration delete-other-windows mh-send-sub] 7))
+
+(defun mh-send-other-window (to cc subject) "\
+Compose and send a letter in another window.." (interactive "sTo:
+sCc:
+sSubject: ") (byte-code "ňÁÆ
+ Ç $)‡" [pop-up-windows t to cc subject nil mh-send-sub current-window-configuration] 6))
+
+(defun mh-send-sub (to cc subject config) "\
+Do the real work of composing and sending a letter.
+Expects the TO, CC, and SUBJECT fields as arguments.
+CONFIG is the window configuration before sending mail." (byte-code " ËÃ!ÌÍ!ˆÎÏÐÑÒ \"!ƒ
+ ÃÃ
+&
+)*‡" [folder mh-current-folder msg-num nil draft mh-user-path mh-lib to subject cc config mh-get-msg-num message "Composing a message..." mh-read-draft "message" file-exists-p expand-file-name "components" error "Can't find components file" mh-insert-fields "To:" "Subject:" "Cc:" set-buffer-modified-p "Composing a message...done" mh-compose-and-send-mail ""] 24))
+
+(defun mh-show (&optional msg) "\
+Show MESSAGE (default: displayed message).
+Forces a two-window display with the folder window on top (size
+mh-summary-height) and the show buffer below it." (interactive) (byte-code "ƈ?…
+
+(defun mh-sort-folder nil "\
+Sort the messages in the current folder by date." (interactive) (byte-code "ÈÄ!ˆÅ‰ˆÆÂ!ˆÇÈ!ˆÉÊ\"ˆÇË!ˆÌÍ\"‡" [mh-current-folder mh-next-direction t nil mh-process-or-undo-commands forward mh-set-folder-modified-p message "Sorting folder..." mh-exec-cmd "sortm" "Sorting folder...done" mh-scan-folder "all"] 8))
+
+(defun mh-toggle-showing nil "\
+Toggle the scanning mode/showing mode of displaying messages." (interactive) (byte-code "Áˆƒ
+
+(defun mh-undo (prefix-provided msg-or-seq) "\
+Undo the deletion or refile of the specified MESSAGE(s).
+Default is the displayed message. If optional prefix argument is
+provided, then prompt for the message sequence." (interactive (byte-code "ƒ
+ƒ
+
+(defun mh-undo-msg (msg) (byte-code " >ƒ
+
+(defun mh-undo-folder (&rest ignore) "\
+Undo all commands in current folder." (interactive) (byte-code "ˆ†
+
+(defun mh-unshar-msg (dir) "\
+Unpack the shar file contained in the current message into directory DIR." (interactive (byte-code "ÂÃÁ$C‡" [mh-unshar-default-directory nil read-file-name "Unshar message in directory: "] 5)) (byte-code "ÁˆÅÆÂ! \"ˆÇ !‡" [mh-unshar-default-directory nil t mh-current-folder dir mh-display-msg mh-get-msg-num mh-unshar-buffer] 4))
+
+(defun mh-unshar-buffer (dir) (byte-code "ebˆÆÇÀÁ#†&
+!ƒQ
+%)ˆÙÚ !Û\"ˆÜ dÝÀ Á&+‚w
+" "mkdir " call-process "mkdir" set-window-start display-buffer 0 call-process-region "sh" error "Cannot find start of shar."] 23))
+
+(defun mh-visit-folder (folder &optional range) "\
+Visit FOLDER and display RANGE of messages.
+Assumes mh-e has already been initialized." (interactive (byte-code "ÁÂÃÀ#ÄÅ!D‡" [t mh-prompt-for-folder "Visit" "+inbox" mh-read-msg-range "Range [all]? "] 4)) (byte-code "ÅˆÆ Ç
+ †
+
+(defun mh-widen nil "\
+Remove restrictions from the current folder, thereby showing all messages." (interactive) (byte-code "È…
+
+(defun mh-delete-a-msg (msg) (byte-code "ŠÇÁÂ#ˆÈ !…
+
+(defun mh-refile-a-msg (msg destination) (byte-code "ŠÉÁÂ#ˆÊ !ƒ
+
+(defun mh-display-msg (msg-num folder) (byte-code "qˆ
+ Õ
+!    Ö !?…(
+\"ˆÙ !ˆ…6
+#C‰.‡" [folder formfile mhl-formfile clean-message-header mh-clean-message-header invisible-headers mh-invisible-headers visible-headers mh-visible-headers msg-filename msg-num show-buffer mh-show-buffer mh-current-folder mh-bury-show-buffer buffer-file-name nil t case-fold-search mode-line-buffer-identification mh-show-buffer-mode-line-buffer-id mh-msg-filename file-exists-p error "Message %d does not exist" switch-to-buffer bury-buffer equal clear-visited-file-modtime unlock-buffer erase-buffer mh-exec-lib-cmd-output "mhl" "-nobell" "-noclear" "-form" insert-file-contents mh-clean-msg-header re-search-forward "^To:\\|^From:\\|^Subject:\\|^Date:" beginning-of-line mh-recenter 0 set-buffer-modified-p set-mark format] 22))
+
+(defun mh-invalidate-show-buffer nil (byte-code "Ã!…
+
+(defun mh-show-message-in-other-window nil (byte-code "Â!ˆ …
+
+(defun mh-clean-msg-header (start invisible-headers visible-headers) (byte-code "ÁŒ
+bˆÆÇÃÁ#…
+`\"ˆebˆ ƒ\\
+
+" backward-char 1 narrow-to-region beginning-of-line looking-at forward-line "^[ ]+" mh-delete-line re-search-forward unlock-buffer] 21))
+
+(defun mh-delete-line (lines) (byte-code "Á`ŠÂ!ˆ`)\"‡" [lines delete-region forward-line] 4))
+
+(defun mh-read-draft (use initial-contents delete-contents-file) (byte-code "ƒ
+ËÌÍ !Ã\"ˆÎÏÐÑ \"!ˆ ‰)‚]
+…†
+
+(defun mh-new-draft-name nil (byte-code "ŠÂÃ!qˆÄ ˆÅÆÀ Ç$ˆÈ`É S\")‡" [nil mh-draft-folder get-buffer-create " *mh-temp*" erase-buffer mh-exec-cmd-output "mhpath" "new" buffer-substring mark] 7))
+
+(defun mh-next-msg nil (byte-code "Á=ƒ
+
+(defun mh-set-scan-mode nil (byte-code "Ä!…
+
+(defun mh-maybe-show (&optional msg) (byte-code "…
+
+(defun mh-set-mode-name (mode-name-string) (byte-code " ‰ˆŠÂ q)ˆÃÄ !‡" [mode-name mode-name-string other-buffer set-buffer-modified-p buffer-modified-p] 4))
+
+(defvar mh-current-folder nil "\
+Name of current folder, a string.")
+
+(defvar mh-show-buffer nil "\
+Buffer that displays mesage for this folder.")
+
+(defvar mh-folder-filename nil "\
+Full path of directory for this folder.")
+
+(defvar mh-showing nil "\
+If non-nil, show the message in a separate window.")
+
+(defvar mh-next-seq-num nil "\
+Index of free sequence id.")
+
+(defvar mh-delete-list nil "\
+List of msg numbers to delete.")
+
+(defvar mh-refile-list nil "\
+List of folder names in mh-seq-list.")
+
+(defvar mh-seq-list nil "\
+Alist of (seq . msgs) numbers.")
+
+(defvar mh-seen-list nil "\
+List of displayed messages.")
+
+(defvar mh-next-direction (quote forward) "\
+Direction to move to next message.")
+
+(defvar mh-narrowed-to-seq nil "\
+Sequence display is narrowed to.")
+
+(defvar mh-first-msg-num nil "\
+Number of first msg in buffer.")
+
+(defvar mh-last-msg-num nil "\
+Number of last msg in buffer.")
+
+(defun mh-make-folder (name) (byte-code "Æ!ˆÂ‰ˆÇ ˆÃ‰ˆÈ ˆÉÂ!ˆ ‰ˆÊË!‡" [name buffer-read-only nil t buffer-file-name mh-folder-filename switch-to-buffer erase-buffer mh-folder-mode mh-set-folder-modified-p mh-set-mode-name "mh-e scan"] 6))
+
+(put (quote mh-folder-mode) (quote mode-class) (quote special))
+
+(defun mh-folder-mode nil "\
+Major mode for \"editing\" an MH folder scan listing.
+Messages can be marked for refiling and deletion. However, both actions
+are deferred until you request execution with \\[mh-execute-commands].
+\\{mh-folder-mode-map}
+ A prefix argument (\\[universal-argument]) to delete, refile, list, or undo
+applies the action to a message sequence.
+
+Variables controlling mh-e operation are (defaults in parentheses):
+
+ mh-bury-show-buffer (t)
+ Non-nil means that the buffer used to display message is buried.
+ It will never be offered as the default other buffer.
+
+ mh-clean-message-header (nil)
+ Non-nil means remove header lines matching the regular expression
+ specified in mh-invisible-headers from messages.
+
+ mh-visible-headers (nil)
+ If non-nil, it contains a regexp specifying the headers that are shown in
+ a message if mh-clean-message-header is non-nil. Setting this variable
+ overrides mh-invisible-headers.
+
+ mh-do-not-confirm (nil)
+ Non-nil means do not prompt for confirmation before executing some
+ non-recoverable commands such as mh-kill-folder and mh-undo-folder.
+
+ mhl-formfile (nil)
+ Name of format file to be used by mhl to show messages.
+ A value of T means use the default format file.
+ Nil means don't use mhl to format messages.
+
+ mh-lpr-command-format (\"lpr -p -J '%s'\")
+ Format for command used to print a message on a system printer.
+
+ mh-recenter-summary-p (nil)
+ If non-nil, then the scan listing is recentered when the window displaying
+ a messages is toggled off.
+
+ mh-summary-height (4)
+ Number of lines in the summary window including the mode line.
+
+ mh-ins-buf-prefix (\"> \")
+ String to insert before each non-blank line of a message as it is
+ inserted in a draft letter.
+
+The value of mh-folder-mode-hook is called when a new folder is set up." (byte-code "È ˆÉ!ˆÊ‰ˆËÌ!ˆÍÎÏ ÐÑÒÏ \"ÓÔÕÏ !!ÖÂ×ØÙÂÚÂÛÂÜÂÝÞßÂàÂáÂâÂ&ˆÄ‰ˆãä!ˆÄ‰ˆåÆ!ˆæ‰ˆåÇ!ˆç‰ˆèé!‡" [mh-folder-mode-map major-mode nil truncate-lines t buffer-offer-save write-file-hooks revert-buffer-function kill-all-local-variables use-local-map mh-folder-mode mh-set-mode-name "mh-e folder" make-local-vars mh-current-folder buffer-name mh-show-buffer format "show-%s" mh-folder-filename file-name-as-directory mh-expand-file-name mh-showing mh-next-seq-num 0 mh-delete-list mh-refile-list mh-seq-list mh-seen-list mh-next-direction forward mh-narrowed-to-seq mh-first-msg-num mh-last-msg-num mh-previous-window-config auto-save-mode -1 make-local-variable (mh-execute-commands) mh-undo-folder run-hooks mh-folder-mode-hook] 38))
+
+(defun make-local-vars (&rest pairs) (byte-code "…
+
+(defun mh-scan-folder (folder range) (byte-code "Ã!?ƒ
+!ˆÈÉ !…7
+Ë\"ƒ.
+#ˆÏÐ!ˆÑ ‡" [folder t range get-buffer mh-make-folder mh-process-or-undo-commands switch-to-buffer mh-regenerate-headers zerop buffer-size equal "all" message "Folder %s is empty" "No messages in %s, range %s" sit-for 5 mh-goto-cur-msg] 13))
+
+(defun mh-regenerate-headers (range) (byte-code " ËÌ\"ˆÍ ÄÄÎ ˆÏÐÄÑÒÓÔ &ˆebˆÕÖ!ƒ/
+!*àÄ!ˆ)ˆËá\")‡" [folder mh-current-folder folder-updating-mod-flag buffer-read-only nil buffer-file-name range mh-valid-scan-line t mh-seq-list mh-partial-folder-mode-line-annotation message "Scanning %s..." buffer-modified-p erase-buffer mh-exec-cmd-output "scan" "-noclear" "-noheader" "-width" window-width looking-at "scan: no messages in" keep-lines "scan: " mh-delete-seq-locally cur mh-read-folder-sequences mh-notate-user-sequences mh-make-folder-mode-line equal "all" mh-set-folder-modified-p "Scanning %s...done"] 18))
+
+(defun mh-get-new-mail (maildrop-name) (byte-code "`
+ÄÎ ÇÇÏ ƒ
+ˆdbˆ`  ƒJ
+
+(defun mh-make-folder-mode-line (&optional annotation) (byte-code "ŠÆ ˆÇÁ!‰ˆÈ ˆÇÁ!‰ˆÉed\"ÊË ƒ%
+#‚C
+
+(defun mh-unmark-all-headers (remove-all-flags) (byte-code "ŠÁd ZÁÆ ˆ`
+X…C
+
+(defun mh-goto-cur-msg nil (byte-code "ÄÅ!@…
+
+(defun mh-pack-folder-1 (range) (byte-code "Ã!ˆÄÅ!ˆÆÁ!ˆŠÇÈÉÊ$)ˆË
+!‡" [mh-current-folder t range mh-process-or-undo-commands message "Packing folder..." mh-set-folder-modified-p mh-exec-cmd-quiet " *mh-temp*" "folder" "-pack" mh-regenerate-headers] 8))
+
+(defun mh-process-or-undo-commands (folder) (byte-code "qˆÂ ƒ
+
+(defun mh-process-commands (folder) (byte-code "ÌÍ\"ˆqˆÎ Ãà …
+Ã\" ɈßË!ˆà ˆÌá\"*âÃ!ˆ)‡" [folder folder-updating-mod-flag buffer-read-only nil buffer-file-name mh-seen-list mh-unseen-seq mh-refile-list mh-delete-list mh-seq-list mh-current-folder t message "Processing deletes and refiles for %s..." buffer-modified-p mh-seq-to-msgs mh-undefine-sequence mh-mapc (lambda (dest) (byte-code "à !…
+È !&ˆÉ!)‡" [msgs dest folder mh-seq-to-msgs apply mh-exec-cmd "refile" "-src" symbol-name mh-delete-scan-msgs] 9)) apply mh-exec-cmd "rmm" mh-delete-scan-msgs buffer-size 0 mh-define-sequence cur mh-get-msg-num "last" mh-invalidate-show-buffer mh-read-folder-sequences mh-unmark-all-headers mh-notate-user-sequences "Processing deletes and refiles for %s...done" mh-set-folder-modified-p] 18))
+
+(defun mh-delete-scan-msgs (msgs) (byte-code "ÃÄK\"‰ˆŠÅ ˆ…
+
+(defun mh-set-folder-modified-p (flag) "\
+Mark current folder as modified or unmodified according to FLAG." (byte-code "Á!‡" [flag set-buffer-modified-p] 2))
+
+(defun mh-outstanding-commands-p nil (byte-code "†
+
+(defvar mh-sent-from-folder nil "\
+Folder of msg associated with this letter.")
+
+(defvar mh-sent-from-msg nil "\
+Number of msg associated with this letter.")
+
+(defvar mh-send-args nil "\
+Extra arguments to pass to \"send\" command.")
+
+(defvar mh-annotate-char nil "\
+Character to use to annotate mh-sent-from-msg.")
+
+(defvar mh-annotate-field nil "\
+Field name for message annotation.")
+
+(defun mh-letter-mode nil "\
+Mode for composing letters in mh-e.
+When you have finished composing, type \\[mh-send-letter] to send the letter.
+
+Variables controlling this mode (defaults in parentheses):
+
+ mh-delete-yanked-msg-window (nil)
+ If non-nil, \\[mh-yank-cur-msg] will delete any windows displaying
+ the yanked message.
+
+ mh-yank-from-start-of-msg (t)
+ If non-nil, \\[mh-yank-cur-msg] will include the entire message.
+ If `body', just yank the body (no header).
+ If nil, only the portion of the message following the point will be yanked.
+ If there is a region, this variable is ignored.
+
+Upon invoking mh-letter-mode, text-mode-hook and mh-letter-mode-hook are
+invoked with no args, if those values are non-nil.
+
+\\{mh-letter-mode-map}" (interactive) (byte-code "ÆˆÇ ˆÈÀ!ˆÉP‰ˆÈÁ!ˆÉ P‰ˆÈÊ!ˆÈË!ˆÈÌ!ˆÈÍ!ˆÈÎ!ˆÈÏ!ˆÐ
+!ˆÑ‰ˆÒÓ!ˆÔ !ˆÕÖ×\"ˆ …Q
+
+(defun mh-auto-fill-for-letter nil (byte-code "Á ˆÂ …
+
+(defun mh-in-header-p nil (byte-code "Š`ebˆÃÄÁÂ#ˆ`W))‡" [cur-point nil t re-search-forward "^--------"] 4))
+
+(defun mh-to-field nil "\
+Move point to the end of a specified header field.
+The field is indicated by the previous keystroke. Create the field if
+it does not exist. Set the mark to point before moving." (interactive) (byte-code "ÆˆÇ ˆÈÉ Ê\"
+\"AÄËÄ\"ƒD
+"] 16))
+
+(defun mh-to-fcc nil "\
+Insert an Fcc: field in the current message.
+Prompt for the field name with a completion list of the current folders." (interactive) (byte-code "ÈÄÅÆÇÂ#È ˆŠÉ ˆ ÊÃOc)*‡" [last-input-char folder t nil 6 mh-prompt-for-folder "Fcc" "" expand-abbrev mh-to-field 1] 6))
+
+(defun mh-insert-signature nil "\
+Insert the file ~/.signature at the current point." (interactive) (byte-code "ÀˆÁÂ!ˆÃÄ !‡" [nil insert-file-contents "~/.signature" set-buffer-modified-p buffer-modified-p] 4))
+
+(defun mh-check-whom nil "\
+Verify recipients of the current letter." (interactive) (byte-code "ˆà ÄÁ!ˆÅ ˆÆÇ!ˆÈÉ!ˆÊp!ˆË ˆÌÍÁ#ˆÎÏ!ˆÆÐ!)‡" [file-name t nil buffer-file-name set-buffer-modified-p save-buffer message "Checking recipients..." switch-to-buffer-other-window "*Mail Recipients*" bury-buffer erase-buffer mh-exec-cmd-output "whom" other-window -1 "Checking recipients...done"] 11))
+
+(defvar mh-searching-folder nil "\
+Folder this pick is searching.")
+
+(defun mh-make-pick-template nil (byte-code "Á ˆÂ ˆÃÄ!ˆÅÆÇÈÉÊË&ˆÌ ˆÍ!ˆebˆÎ ‡" [mh-pick-mode-map erase-buffer kill-all-local-variables make-local-variable mh-searching-folder insert "From:
+" "To:
+" "Cc:
+" "Date:
+" "Subject:
+" "---------
+" mh-letter-mode use-local-map end-of-line] 10))
+
+(defun mh-do-pick-search nil "\
+Find messages that match the qualifications in the current pattern buffer.
+Messages are searched for in the folder named in mh-searching-folder.
+Put messages found in a sequence named `search'." (interactive) (byte-code "ĈÌ
+ÄÄÄŠÍ !ƒ$
+ˆÛ‰ˆ‚9
+\"‚q
+
+(defun mh-next-pick-field (buffer) (byte-code "qˆÂmƒ
+" "-search"] 16))
+
+(defun mh-compose-and-send-mail (draft send-args sent-from-folder sent-from-msg to subject cc annotate-char annotate-field config) (byte-code "Ó!ˆÔ ˆ
+‰ˆ ‰ˆ‰ˆ‰ˆ
+‰ ˆ ‰ ˆÕC‰ ˆÖÒ!…4
+
+(defun mh-send-letter (&optional arg) "\
+Send the draft letter in the current buffer.
+If optional prefix argument is provided, monitor delivery.
+Run mh-before-send-letter-hook before doing anything." (interactive "P") (byte-code "ˈÌÍ!ˆÎÀ!ˆÏ ˆÐÑ!ˆpÒ  ƒL
+&‚?
+&ˆdbˆÛÜ!ˆ q‚b
+%‚b
+$ˆ…~
+áâãäå!äæ!#&ˆ ?†‡
+
+(defun mh-insert-letter (prefix-provided folder msg) "\
+Insert a message from any folder into the current letter.
+Removes the message's headers using mh-invisible-headers.
+Prefixes each non-blank line with mh-ins-buf-prefix (default \">> \").
+If optional prefix argument provided, do not indent and do not delete
+headers. Leaves the mark before the letter and point after it." (interactive (byte-code "ÄÅ Â#ÆÇÈ ƒ
+!))‡" [current-prefix-arg mh-sent-from-folder nil mh-sent-from-msg start msg folder prefix-provided mh-invisible-headers mh-visible-headers mh-ins-buf-prefix narrow-to-region equal "" int-to-string mh-exec-lib-cmd-output "mhl" "-nobell" "-noclear" expand-file-name mh-expand-file-name mh-clean-msg-header set-mark mh-insert-prefix-string] 11))
+
+(defun mh-yank-cur-msg nil "\
+Insert the current message into the draft buffer.
+Prefix each non-blank line in the message with the string in
+`mh-ins-buf-prefix'. If a region is set in the message's buffer, then
+only the region will be inserted. Otherwise, the entire message will
+be inserted if `mh-yank-from-start-of-msg' is non-nil. If this variable
+is nil, the portion of the message following the point will be yanked.
+If `mh-delete-yanked-msg-window' is non-nil, any window displaying the
+yanked message will be deleted." (interactive) (byte-code "ʈ…
+
+\"ˆÔ ˆcˆÕ !ˆÖcˆ× )*‚t
+" widen error "There is no current message"] 15))
+
+(defun mh-insert-prefix-string (mh-ins-string) (byte-code "ŠÀd!ˆebˆÁÂ!)‡" [set-mark run-hooks mh-yank-hooks] 3))
+
+(defun mh-fully-kill-draft nil "\
+Kill the draft message file and the draft message buffer.
+Use \\[kill-buffer] if you don't want to delete the draft message file." (interactive) (byte-code "ˆÃÄ!ƒ.
+
+(defun mh-recenter (arg) (byte-code "Áp! =…
+
+(defun mh-make-seq (name msgs) (byte-code " B‡" [name msgs] 2))
+
+(defmacro mh-seq-name (pair) (byte-code "ÁD‡" [pair car] 2))
+
+(defmacro mh-seq-msgs (pair) (byte-code "ÁD‡" [pair cdr] 2))
+
+(defun mh-find-seq (name) (byte-code "Â \"‡" [name mh-seq-list assoc] 3))
+
+(defun mh-seq-to-msgs (seq) "\
+Return a list of the messages in SEQUENCE." (byte-code "Á!A‡" [seq mh-find-seq] 2))
+
+(defun mh-seq-containing-msg (msg) (byte-code " Ã…
+B‰ˆA‰ˆ‚
+*‡" [l mh-seq-list seqs nil msg] 3))
+
+(defun mh-msg-to-seq (msg) (byte-code "Á!@‡" [msg mh-seq-containing-msg] 2))
+
+(defun mh-read-seq-default (prompt not-empty) (byte-code "Ä
+†
+
+(defun mh-read-seq (prompt not-empty &optional default) (byte-code "ÈÉÊ Ë
+ƒ
+\"‚
+‚4
+
+(defun mh-read-folder-sequences (folder define-sequences) (byte-code "Á
+…
+
+(defun mh-seq-names (seq-list) (byte-code "ÁÂ\"‡" [seq-list mapcar (lambda (entry) (byte-code "Á@!C‡" [entry symbol-name] 2))] 3))
+
+(defun mh-seq-from-command (folder seq seq-command) (byte-code "ÁÁÄŠÉ‹ˆqˆÊ
+!‰ˆË
+\"B‰ˆ
+)+‡" [msg nil msgs case-fold-search t seq-command folder mh-seq-list seq ((byte-code "ÃÄÅ#ˆebˆÆ @‰…
+B‰ˆÇÈ!ˆ‚
+
+(defun mh-read-msg-list nil (byte-code "ÁŠÂ ˆ`)ÁÆÇ
+Ä#…o
+Ä#ˆÈÉÊË!ÌË!\"! W…F
+
+(defun mh-remove-seq (seq) (byte-code "ÂÃÄ T%ˆÅÆC\"ˆÇ!‡" [seq mh-cmd-note mh-map-to-seq-msgs mh-notate-if-in-one-seq 32 mh-undefine-sequence "all" mh-delete-seq-locally] 6))
+
+(defun mh-delete-seq-locally (seq) (byte-code "Ã !Ä
+\"‰)‡" [entry seq mh-seq-list mh-find-seq delq] 4))
+
+(defun mh-remove-msg-from-seq (msg seq &optional internal-flag) (byte-code "Å !…$
+Ç T@$ˆ ?…
+C\"ˆÉÊ
+A\"\")‡" [entry seq msg mh-cmd-note internal-flag mh-find-seq mh-notate-if-in-one-seq 32 mh-undefine-sequence setcdr delq] 8))
+
+(defun mh-add-msgs-to-seq (msgs seq &optional internal-flag) (byte-code "Æ !
+…
+!…
+C‰ˆ?ƒ#
+\" B‰‚/
+…/
+A\"\"ˆ ?…@
+\"ˆÌ Í T#)‡" [entry seq msgs mh-seq-list internal-flag mh-cmd-note mh-find-seq atom mh-make-seq setcdr append mh-add-to-sequence mh-notate-seq 37] 10))
+
+(defun mh-rename-seq (seq new-name) "\
+Rename a SEQUENCE to have a new NAME." (interactive "SOld sequence name:
+SNew name: ") (byte-code "ÃˆÄ !ƒ
+\"‚
+A\")‡" [old-seq seq new-name nil mh-find-seq rplaca error "Sequence %s does not exists" mh-undefine-sequence mh-define-sequence] 7))
+
+(defun mh-notate-user-sequences nil (byte-code " Ä…$
+!?…
+Ç T#ˆA‰ˆ‚
+
+(defun mh-internal-seq (name) (byte-code "Â>†
+
+(defun mh-folder-name-p (name) (byte-code "9ƒ
+
+(defun mh-notate-seq (seq notation offset) (byte-code "ÃÄ
+$‡" [seq notation offset mh-map-to-seq-msgs mh-notate] 5))
+
+(defun mh-notate-if-in-one-seq (msg notation offset seq) (byte-code "Å !
+@=…
+
+(defun mh-map-to-seq-msgs (func seq &rest args) (byte-code "ŠÅ !…!
+
+(defun mh-map-over-seqs (func seq-list) (byte-code "…
+
+(defun mh-define-sequences (seq-list) (byte-code "ÁÂ\"‡" [seq-list mh-map-over-seqs mh-define-sequence] 3))
+
+(defun mh-add-to-sequence (seq msgs) (byte-code "Ã!?…
+ÇÈ!É &‡" [seq msgs mh-current-folder mh-folder-name-p apply mh-exec-cmd "mark" "-sequence" symbol-name "-add"] 10))
+
+(defun mh-define-sequence (seq msgs) (byte-code "…
+ÇÈ !ÉÊË!&)‡" [msgs seq mh-current-folder mh-folder-name-p apply mh-exec-cmd "mark" "-sequence" symbol-name "-add" "-zero" mh-list-to-string] 12))
+
+(defun mh-undefine-sequence (seq msgs) (byte-code "ÃÄÅÆÇ !È
+&‡" [mh-current-folder seq msgs apply mh-exec-cmd "mark" "-sequence" symbol-name "-delete"] 9))
+
+(defun mh-copy-seq-to-point (seq location) (byte-code "ÂÃ #‡" [seq location mh-map-to-seq-msgs mh-copy-line-to-point] 4))
+
+(defun mh-copy-line-to-point (msg location) (byte-code "À ˆ`ÂÃ!ˆÄ`\"ˆ bˆÅ ˆb)‡" [beginning-of-line location forward-line 1 copy-region-as-kill yank] 5))
+
+(defun mh-exec-cmd (command &rest args) (byte-code "ŠÅqˆÆ ˆÇÈÉ \"ÂÃÂÊ !&ˆË ÌV…
+
+(defun mh-exec-cmd-quiet (buffer command &rest args) (byte-code ";…
+
+\"ÃÃ &‡" [buffer command mh-progs nil args erase-buffer apply call-process expand-file-name] 9))
+
+(defun mh-exec-cmd-output (command display &rest args) (byte-code "Æ`À\"ˆÇÈÉ
+\"ÃÀ Ê !&ˆË ‡" [t command mh-progs nil display args push-mark apply call-process expand-file-name mh-list-to-string exchange-point-and-mark] 10))
+
+(defun mh-exec-cmd-daemon (command &rest args) (byte-code "ŠÆÇ!qˆÈ )ˆÁÉÊ ÁË \"Ì !%Í
+Î\"*‡" [process-connection-type nil process command mh-progs args get-buffer-create " *mh-temp*" erase-buffer apply start-process expand-file-name mh-list-to-string set-process-filter mh-process-daemon] 10))
+
+(defun mh-process-daemon (process output) (byte-code "ÁÂ!qˆÃ!ˆÄÂ!‡" [output get-buffer-create " *mh-temp*" insert-before-markers display-buffer] 4))
+
+(defun mh-exec-lib-cmd-output (command &rest args) (byte-code "Å`À\"ˆÆÇÈ
+\"ÃÀÃÉ !&ˆÊ ‡" [t command mh-lib nil args push-mark apply call-process expand-file-name mh-list-to-string exchange-point-and-mark] 10))
+
+(defun mh-list-to-string (l) (byte-code "Á
+…h
+@?†_
+@9ƒ
+@!B‰‚_
+@!ƒ/
+@!B‰‚_
+@È\"†_
+@;ƒF
+@B‰‚_
+@<ƒZ
+@!!\"‰‚_
+@\"ˆ
+A‰ˆ‚
+
+(defun mh-annotate-msg (msg buffer note &rest args) (byte-code "ÅÆÇ
+%ˆŠÈ!…&
+
+(defun mh-notate (msg notation offset) (byte-code "Š?†
+!ˆ))‡" [msg t folder-updating-mod-flag buffer-read-only nil buffer-file-name offset notation mh-goto-msg buffer-modified-p beginning-of-line forward-char delete-char 1 mh-set-folder-modified-p] 8))
+
+(defun mh-prompt-for-folder (prompt default can-create) (byte-code "ÇÈÉÊ \"ƒ
+Ê\"…5
+Ê\"†I
+Ï\"ƒR
+!?…_
+\"‰ˆÒÓ
+!!? …q
+\"!ƒ‘
+\"ˆØÙÄÄÄÓ
+!%ˆÖÚ
+\"ˆ
+C B‰‚ª
+\"‚ª
+ \"?…ª
+C B‰)ˆ
+*‡" [prompt default name mh-folder-list nil new-file-p t format "%s folder%s" equal "" "? " " [%s]? " mh-set-folder-list completing-read "+" mh-folder-name-p "+%s" file-exists-p mh-expand-file-name y-or-n-p "Folder %s does not exist. Create it? " message "Creating %s" call-process "mkdir" "Creating %s...done" error "Folder %s is not created" assoc] 23))
+
+(defun mh-set-folder-list nil "\
+Sets mh-folder-list correctly.
+A useful function for the command line or for when you need to sync by hand." (byte-code "Á ‰‡" [mh-folder-list mh-make-folder-list] 3))
+
+(defun mh-make-folder-list nil "\
+Return a list of the user's folders.
+Result is in a form suitable for completing read." (interactive) (byte-code "ˆÄÅ!ˆÆ‹‡" [mh-recursive-folders list nil start message "Collecting folder names..." ((byte-code "ÄÅÆǃ
+
+(defun mh-remove-folder-from-folder-list (folder) (byte-code "Âà \"\"‰‡" [mh-folder-list folder delq assoc] 4))
+
+(defun mh-read-msg-range (prompt) (byte-code "Ç !GÈÅ
+W…*
+#@ B‰ˆA‰)ˆ‚
+
+(defun mh-get-msg-num (error-if-no-message) (byte-code "ŠÄ ˆÅ!ƒ
+
+(defun mh-msg-search-pat (n) (byte-code "Â \"‡" [mh-msg-search-regexp n format] 3))
+
+(defun mh-msg-filename (msg &optional folder) (byte-code "ÃÄ! ƒ
+\"‡" [msg folder mh-folder-filename expand-file-name int-to-string mh-expand-file-name] 5))
+
+(defun mh-msg-filenames (msgs &optional folder) (byte-code "ÁÂÃ#‡" [msgs mapconcat (lambda (msg) (byte-code "Â \"‡" [msg folder mh-msg-filename] 3)) " "] 4))
+
+(defun mh-expand-file-name (filename &optional default) "\
+Just like `expand-file-name', but also handles MH folder names.
+Assumes that any filename that starts with '+' is a folder name." (byte-code "Ã!ƒ
+\"‡" [filename mh-user-path default mh-folder-name-p expand-file-name 1 nil] 5))
+
+(defun mh-find-path nil (byte-code "ŠÅÆÇ!†
+
+(defun mh-get-field (field) (byte-code "ÁebˆÅÆÇ
+\"ÃÁ#?ƒ
+].*\\)$" match-beginning 1 forward-line "[ ]" buffer-substring] 11))
+
+(defun mh-insert-fields (&rest name-values) (byte-code "Á
+…C
+@
+A@Æ Ç\"?…8
+AA‰*ˆ‚
+" end-of-line] 10))
+
+(defun mh-position-on-field (field set-mark) (byte-code "Á
+…
+
+(defun mh-goto-header-end (arg) (byte-code "ÂÃÀÀ#…
+
+(suppress-keymap mh-folder-mode-map)
+
+(define-key mh-folder-mode-map "q" (quote mh-quit))
+
+(define-key mh-folder-mode-map "b" (quote mh-quit))
+
+(define-key mh-folder-mode-map "?" (quote mh-msg-is-in-seq))
+
+(define-key mh-folder-mode-map "%" (quote mh-put-msg-in-seq))
+
+(define-key mh-folder-mode-map "|" (quote mh-pipe-msg))
+
+(define-key mh-folder-mode-map "a" (quote mh-edit-again))
+
+(define-key mh-folder-mode-map "%" (quote mh-delete-msg-from-seq))
+
+(define-key mh-folder-mode-map "n" (quote mh-narrow-to-seq))
+
+(define-key mh-folder-mode-map "w" (quote mh-widen))
+
+(define-key mh-folder-mode-map "b" (quote mh-burst-digest))
+
+(define-key mh-folder-mode-map "u" (quote mh-undo-folder))
+
+(define-key mh-folder-mode-map " " (quote mh-page-digest))
+
+(define-key mh-folder-mode-map "" (quote mh-page-digest-backwards))
+
+(define-key mh-folder-mode-map "e" (quote mh-extract-rejected-mail))
+
+(define-key mh-folder-mode-map "f" (quote mh-visit-folder))
+
+(define-key mh-folder-mode-map "k" (quote mh-kill-folder))
+
+(define-key mh-folder-mode-map "l" (quote mh-list-folders))
+
+(define-key mh-folder-mode-map "o" (quote mh-write-msg-to-file))
+
+(define-key mh-folder-mode-map "p" (quote mh-pack-folder))
+
+(define-key mh-folder-mode-map "s" (quote mh-search-folder))
+
+(define-key mh-folder-mode-map "r" (quote mh-rescan-folder))
+
+(define-key mh-folder-mode-map "l" (quote mh-print-msg))
+
+(define-key mh-folder-mode-map "t" (quote mh-toggle-showing))
+
+(define-key mh-folder-mode-map "c" (quote mh-copy-msg))
+
+(define-key mh-folder-mode-map ">" (quote mh-write-msg-to-file))
+
+(define-key mh-folder-mode-map "i" (quote mh-inc-folder))
+
+(define-key mh-folder-mode-map "x" (quote mh-execute-commands))
+
+(define-key mh-folder-mode-map "e" (quote mh-execute-commands))
+
+(define-key mh-folder-mode-map "r" (quote mh-redistribute))
+
+(define-key mh-folder-mode-map "f" (quote mh-forward))
+
+(define-key mh-folder-mode-map "s" (quote mh-send))
+
+(define-key mh-folder-mode-map "m" (quote mh-send))
+
+(define-key mh-folder-mode-map "a" (quote mh-reply))
+
+(define-key mh-folder-mode-map "j" (quote mh-goto-msg))
+
+(define-key mh-folder-mode-map "<" (quote mh-first-msg))
+
+(define-key mh-folder-mode-map "g" (quote mh-goto-msg))
+
+(define-key mh-folder-mode-map "" (quote mh-previous-page))
+
+(define-key mh-folder-mode-map " " (quote mh-page-msg))
+
+(define-key mh-folder-mode-map "." (quote mh-show))
+
+(define-key mh-folder-mode-map "u" (quote mh-undo))
+
+(define-key mh-folder-mode-map "!" (quote mh-refile-or-write-again))
+
+(define-key mh-folder-mode-map "^" (quote mh-refile-msg))
+
+(define-key mh-folder-mode-map "d" (quote mh-delete-msg))
+
+(define-key mh-folder-mode-map "" (quote mh-delete-msg-no-motion))
+
+(define-key mh-folder-mode-map "p" (quote mh-previous-undeleted-msg))
+
+(define-key mh-folder-mode-map "n" (quote mh-next-undeleted-msg))
+
+(define-key mh-folder-mode-map "o" (quote mh-refile-msg))
+
+(define-key mh-letter-mode-map "" (quote mh-to-field))
+
+(define-key mh-letter-mode-map "" (quote mh-to-field))
+
+(define-key mh-letter-mode-map "" (quote mh-to-fcc))
+
+(define-key mh-letter-mode-map "" (quote mh-to-field))
+
+(define-key mh-letter-mode-map "" (quote mh-to-field))
+
+(define-key mh-letter-mode-map "b" (quote mh-to-field))
+
+(define-key mh-letter-mode-map "c" (quote mh-to-field))
+
+(define-key mh-letter-mode-map "f" (quote mh-to-fcc))
+
+(define-key mh-letter-mode-map "s" (quote mh-to-field))
+
+(define-key mh-letter-mode-map "t" (quote mh-to-field))
+
+(define-key mh-letter-mode-map "" (quote mh-fully-kill-draft))
+
+(define-key mh-letter-mode-map "" (quote mh-check-whom))
+
+(define-key mh-letter-mode-map " " (quote mh-insert-letter))
+
+(define-key mh-letter-mode-map "" (quote mh-yank-cur-msg))
+
+(define-key mh-letter-mode-map "" (quote mh-insert-signature))
+
+(define-key mh-letter-mode-map "" (quote mh-send-letter))
+
+(define-key mh-pick-mode-map "" (quote mh-do-pick-search))
+
+(define-key mh-pick-mode-map "" (quote mh-to-field))
+
+(define-key mh-pick-mode-map "" (quote mh-to-field))
+
+(define-key mh-pick-mode-map "" (quote mh-to-field))
+
+(define-key mh-pick-mode-map "" (quote mh-to-field))
+
+(define-key mh-pick-mode-map "" (quote mh-to-field))
+
+(define-key mh-pick-mode-map "b" (quote mh-to-field))
+
+(define-key mh-pick-mode-map "c" (quote mh-to-field))
+
+(define-key mh-pick-mode-map "f" (quote mh-to-field))
+
+(define-key mh-pick-mode-map "s" (quote mh-to-field))
+
+(define-key mh-pick-mode-map "t" (quote mh-to-field))
+
+(define-key mh-pick-mode-map "" (quote mh-check-whom))
diff --git a/lisp/mhspool.el b/lisp/mhspool.el
deleted file mode 100644
index 4801579ecf7..00000000000
--- a/lisp/mhspool.el
+++ /dev/null
@@ -1,404 +0,0 @@
-;;; MH folder access using NNTP for GNU Emacs
-;; Copyright (C) 1988, 1989 Fujitsu Laboratories LTD.
-;; Copyright (C) 1988, 1989, 1990 Masanobu UMEDA
-;; $Header: mhspool.el,v 1.5 90/03/23 13:25:23 umerin Locked $
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY. No author or distributor
-;; accepts responsibility to anyone for the consequences of using it
-;; or for whether it serves any particular purpose or works at all,
-;; unless he says so in writing. Refer to the GNU Emacs General Public
-;; License for full details.
-
-;; Everyone is granted permission to copy, modify and redistribute
-;; GNU Emacs, but only under the conditions described in the
-;; GNU Emacs General Public License. A copy of this license is
-;; supposed to have been given to you along with GNU Emacs so you
-;; can know your rights and responsibilities. It should be in a
-;; file named COPYING. Among other things, the copyright notice
-;; and this notice must be preserved on all copies.
-
-(provide 'mhspool)
-(require 'nntp)
-
-;; This package enables you to read mail or articles in MH folders, or
-;; articles saved by GNUS. In any case, the file names of mail or
-;; articles must consist of only numeric letters.
-
-;; Before using this package, you have to create a server specific
-;; startup file according to the directory which you want to read. For
-;; example, if you want to read mail under the directory named
-;; `~/Mail', the file must be a file named `.newsrc-:Mail'. (There is
-;; no way to specify hierarchical directory now.) In this case, the
-;; name of the NNTP server passed to GNUS must be `:Mail'.
-
-(defvar mhspool-list-directory-switches '("-R")
- "*Switches for `nntp-request-list' to pass to `ls' for gettting file lists.
-One entry should appear on one line. You may need to add `-1' option.")
-
-
-
-(defconst mhspool-version "MHSPOOL 1.5"
- "Version numbers of this version of MHSPOOL.")
-
-(defvar mhspool-spool-directory "~/Mail"
- "Private mail directory.")
-
-(defvar mhspool-current-directory nil
- "Current news group directory.")
-
-;;;
-;;; Replacement of Extended Command for retrieving many headers.
-;;;
-
-(defun mhspool-retrieve-headers (sequence)
- "Return list of article headers specified by SEQUENCE of article id.
-The format of list is
- `([NUMBER SUBJECT FROM XREF LINES DATE MESSAGE-ID REFERENCES] ...)'.
-Reader macros for the vector are defined as `nntp-header-FIELD'.
-Writer macros for the vector are defined as `nntp-set-header-FIELD'.
-News group must be selected before calling me."
- (save-excursion
- (set-buffer nntp-server-buffer)
- ;;(erase-buffer)
- (let ((file nil)
- (number (length sequence))
- (count 0)
- (headers nil) ;Result list.
- (article 0)
- (subject nil)
- (message-id nil)
- (from nil)
- (xref nil)
- (lines 0)
- (date nil)
- (references nil))
- (while sequence
- ;;(nntp-send-strings-to-server "HEAD" (car sequence))
- (setq article (car sequence))
- (setq file
- (concat mhspool-current-directory (prin1-to-string article)))
- (if (and (file-exists-p file)
- (not (file-directory-p file)))
- (progn
- (erase-buffer)
- (insert-file-contents file)
- ;; Make message body invisible.
- (goto-char (point-min))
- (search-forward "\n\n" nil 'move)
- (narrow-to-region (point-min) (point))
- ;; Fold continuation lines.
- (goto-char (point-min))
- (while (re-search-forward "\\(\r?\n[ \t]+\\)+" nil t)
- (replace-match " " t t))
- ;; Make it possible to search for `\nFIELD'.
- (goto-char (point-min))
- (insert "\n")
- ;; Extract From:
- (goto-char (point-min))
- (if (search-forward "\nFrom: " nil t)
- (setq from (buffer-substring
- (point)
- (save-excursion (end-of-line) (point))))
- (setq from "(Unknown User)"))
- ;; Extract Subject:
- (goto-char (point-min))
- (if (search-forward "\nSubject: " nil t)
- (setq subject (buffer-substring
- (point)
- (save-excursion (end-of-line) (point))))
- (setq subject "(None)"))
- ;; Extract Message-ID:
- (goto-char (point-min))
- (if (search-forward "\nMessage-ID: " nil t)
- (setq message-id (buffer-substring
- (point)
- (save-excursion (end-of-line) (point))))
- (setq message-id nil))
- ;; Extract Date:
- (goto-char (point-min))
- (if (search-forward "\nDate: " nil t)
- (setq date (buffer-substring
- (point)
- (save-excursion (end-of-line) (point))))
- (setq date nil))
- ;; Extract Lines:
- (goto-char (point-min))
- (if (search-forward "\nLines: " nil t)
- (setq lines (string-to-int
- (buffer-substring
- (point)
- (save-excursion (end-of-line) (point)))))
- (setq lines 0))
- ;; Extract Xref:
- (goto-char (point-min))
- (if (search-forward "\nXref: " nil t)
- (setq xref (buffer-substring
- (point)
- (save-excursion (end-of-line) (point))))
- (setq xref nil))
- ;; Extract References:
- ;; If no References: field, use In-Reply-To: field instead.
- ;; Suggested by tanaka@flab.fujitsu.co.jp (Hiroshi TANAKA).
- (goto-char (point-min))
- (if (or (search-forward "\nReferences: " nil t)
- (search-forward "\nIn-Reply-To: " nil t))
- (setq references (buffer-substring
- (point)
- (save-excursion (end-of-line) (point))))
- (setq references nil))
- (setq headers
- (cons (vector article subject from
- xref lines date
- message-id references) headers))
- ))
- (setq sequence (cdr sequence))
- (setq count (1+ count))
- (and (numberp nntp-large-newsgroup)
- (> number nntp-large-newsgroup)
- (zerop (% count 20))
- (message "MHSPOOL: %d%% of headers received."
- (/ (* count 100) number)))
- )
- (and (numberp nntp-large-newsgroup)
- (> number nntp-large-newsgroup)
- (message "MHSPOOL: 100%% of headers received."))
- (nreverse headers)
- )))
-
-
-;;;
-;;; Replacement of NNTP Raw Interface.
-;;;
-
-(defun mhspool-open-server (host &optional service)
- "Open news server on HOST.
-If HOST is nil, use value of environment variable `NNTPSERVER'.
-If optional argument SERVICE is non-nil, open by the service name."
- (let ((host (or host (getenv "NNTPSERVER")))
- (status nil))
- ;; Get directory name from HOST name.
- (if (string-match ":\\(.+\\)$" host)
- (progn
- (setq mhspool-spool-directory
- (file-name-as-directory
- (expand-file-name
- (substring host (match-beginning 1) (match-end 1))
- (expand-file-name "~/" nil))))
- (setq host (system-name)))
- (setq mhspool-spool-directory nil))
- (setq nntp-status-message-string "")
- (cond ((and (stringp host)
- (stringp mhspool-spool-directory)
- (file-directory-p mhspool-spool-directory)
- (string-equal host (system-name)))
- (setq status (mhspool-open-server-internal host service)))
- ((string-equal host (system-name))
- (setq nntp-status-message-string
- (format "No such directory: %s. Goodbye."
- mhspool-spool-directory)))
- ((null host)
- (setq nntp-status-message-string "NNTP server is not specified."))
- (t
- (setq nntp-status-message-string
- (format "MHSPOOL: cannot talk to %s." host)))
- )
- status
- ))
-
-(defun mhspool-close-server ()
- "Close news server."
- (mhspool-close-server-internal))
-
-(fset 'mhspool-request-quit (symbol-function 'mhspool-close-server))
-
-(defun mhspool-server-opened ()
- "Return server process status, T or NIL.
-If the stream is opened, return T, otherwise return NIL."
- (and nntp-server-buffer
- (get-buffer nntp-server-buffer)))
-
-(defun mhspool-status-message ()
- "Return server status response as string."
- nntp-status-message-string
- )
-
-(defun mhspool-request-article (id)
- "Select article by message ID (or number)."
- (let ((file (concat mhspool-current-directory (prin1-to-string id))))
- (if (and (stringp file)
- (file-exists-p file)
- (not (file-directory-p file)))
- (save-excursion
- (mhspool-find-file file)))
- ))
-
-(defun mhspool-request-body (id)
- "Select article body by message ID (or number)."
- (if (mhspool-request-article id)
- (save-excursion
- (set-buffer nntp-server-buffer)
- (goto-char (point-min))
- (if (search-forward "\n\n" nil t)
- (delete-region (point-min) (point)))
- t
- )
- ))
-
-(defun mhspool-request-head (id)
- "Select article head by message ID (or number)."
- (if (mhspool-request-article id)
- (save-excursion
- (set-buffer nntp-server-buffer)
- (goto-char (point-min))
- (if (search-forward "\n\n" nil t)
- (delete-region (1- (point)) (point-max)))
- t
- )
- ))
-
-(defun mhspool-request-stat (id)
- "Select article by message ID (or number)."
- (error "MHSPOOL: STAT is not implemented."))
-
-(defun mhspool-request-group (group)
- "Select news GROUP."
- (cond ((file-directory-p
- (mhspool-article-pathname group))
- ;; Mail/NEWS.GROUP/N
- (setq mhspool-current-directory
- (mhspool-article-pathname group)))
- ((file-directory-p
- (mhspool-article-pathname
- (mhspool-replace-chars-in-string group ?. ?/)))
- ;; Mail/NEWS/GROUP/N
- (setq mhspool-current-directory
- (mhspool-article-pathname
- (mhspool-replace-chars-in-string group ?. ?/))))
- ))
-
-(defun mhspool-request-list ()
- "List valid newsgoups."
- (save-excursion
- (let* ((newsgroup nil)
- (articles nil)
- (directory (file-name-as-directory
- (expand-file-name mhspool-spool-directory nil)))
- (folder-regexp (concat "^" (regexp-quote directory) "\\(.+\\):$"))
- (buffer (get-buffer-create " *GNUS file listing*")))
- (set-buffer nntp-server-buffer)
- (erase-buffer)
- (set-buffer buffer)
- (erase-buffer)
- (apply 'call-process
- "ls" nil t nil
- (append mhspool-list-directory-switches (list directory)))
- (goto-char (point-min))
- (while (re-search-forward folder-regexp nil t)
- (setq newsgroup
- (mhspool-replace-chars-in-string
- (buffer-substring (match-beginning 1) (match-end 1)) ?/ ?.))
- (setq articles nil)
- (forward-line 1) ;(beginning-of-line)
- ;; Thank nobu@flab.fujitsu.junet for his bug fixes.
- (while (and (not (eobp))
- (not (looking-at "^$")))
- (if (looking-at "^[0-9]+$")
- (setq articles
- (cons (string-to-int
- (buffer-substring
- (match-beginning 0) (match-end 0)))
- articles)))
- (forward-line 1))
- (if articles
- (princ (format "%s %d %d n\n" newsgroup
- (apply (function max) articles)
- (apply (function min) articles))
- nntp-server-buffer))
- )
- (kill-buffer buffer)
- (set-buffer nntp-server-buffer)
- (buffer-size)
- )))
-
-(defun mhspool-request-last ()
- "Set current article pointer to the previous article in the current newsgroup."
- (error "MHSPOOL: LAST is not implemented."))
-
-(defun mhspool-request-next ()
- "Advance current article pointer."
- (error "MHSPOOL: NEXT is not implemented."))
-
-(defun mhspool-request-post ()
- "Post a new news in current buffer."
- (setq nntp-status-message-string "MHSPOOL: what do you mean post?")
- nil
- )
-
-
-;;;
-;;; Replacement of Low-Level Interface to NNTP Server.
-;;;
-
-(defun mhspool-open-server-internal (host &optional service)
- "Open connection to news server on HOST by SERVICE (default is nntp)."
- (save-excursion
- (if (not (string-equal host (system-name)))
- (error "MHSPOOL: cannot talk to %s." host))
- ;; Initialize communication buffer.
- (setq nntp-server-buffer (get-buffer-create " *nntpd*"))
- (set-buffer nntp-server-buffer)
- (buffer-flush-undo (current-buffer))
- (erase-buffer)
- (kill-all-local-variables)
- (setq case-fold-search t) ;Should ignore case.
- (setq nntp-server-process nil)
- (setq nntp-server-name host)
- ;; It is possible to change kanji-fileio-code in this hook.
- (run-hooks 'nntp-server-hook)
- t
- ))
-
-(defun mhspool-close-server-internal ()
- "Close connection to news server."
- (if nntp-server-buffer
- (kill-buffer nntp-server-buffer))
- (setq nntp-server-buffer nil)
- (setq nntp-server-process nil))
-
-(defun mhspool-find-file (file)
- "Insert FILE in server buffer safely."
- (set-buffer nntp-server-buffer)
- (erase-buffer)
- (condition-case ()
- (progn
- (insert-file-contents file)
- (goto-char (point-min))
- ;; If there is no body, `^L' appears at end of file. Special
- ;; hack for MH folder.
- (and (search-forward "\n\n" nil t)
- (string-equal (buffer-substring (point) (point-max)) "\^L")
- (delete-char 1))
- t
- )
- (file-error nil)
- ))
-
-(defun mhspool-article-pathname (group)
- "Make pathname for GROUP."
- (concat (file-name-as-directory mhspool-spool-directory) group "/"))
-
-(defun mhspool-replace-chars-in-string (string from to)
- "Replace characters in STRING from FROM to TO."
- (let ((string (substring string 0)) ;Copy string.
- (len (length string))
- (idx 0))
- ;; Replace all occurence of FROM with TO.
- (while (< idx len)
- (if (= (aref string idx) from)
- (aset string idx to))
- (setq idx (1+ idx)))
- string
- ))
diff --git a/lisp/mim-mode.el b/lisp/mim-mode.el
index 43e0c0118b4..ca222b918b6 100644
--- a/lisp/mim-mode.el
+++ b/lisp/mim-mode.el
@@ -86,18 +86,18 @@ are bound.")
(define-abbrev-table 'mim-mode-abbrev-table nil)
-(defconst indent-mim-function 'indent-mim-function
+(defconst indent-mim-hook 'indent-mim-hook
"Controls (via properties) indenting of special forms.
-\(put 'FOO 'indent-mim-function n\), integer n, means lines inside
+\(put 'FOO 'indent-mim-hook n\), integer n, means lines inside
<FOO ...> will be indented n spaces from start of form.
-\(put 'FOO 'indent-mim-function 'DEFINE\) is like above but means use
+\(put 'FOO 'indent-mim-hook 'DEFINE\) is like above but means use
value of mim-body-indent as offset from start of form.
-\(put 'FOO 'indent-mim-function <cons>\) where <cons> is a list or pointted list
+\(put 'FOO 'indent-mim-hook <cons>\) where <cons> is a list or pointted list
of integers, means indent each form in <FOO ...> by the amount specified
in <cons>. When <cons> is exhausted, indent remaining forms by
-`mim-body-indent' unless <cons> is a pointed list, in which case the last
-cdr is used. Confused? Here is an example:
-\(put 'FROBIT 'indent-mim-function '\(4 2 . 1\)\)
+mim-body-indent unless <cons> is a pointted list, in which case the last
+cdr is used. Confused? Here is an example:
+\(put 'FROBIT 'indent-mim-hook '\(4 2 . 1\)\)
<FROBIT
<CHOMP-IT>
<CHOMP-SOME-MORE>
@@ -111,7 +111,7 @@ Finally, the property can be a function name (read the code).")
(defvar mim-body-indent 2
"*Amount to indent in special forms which have DEFINE property on
-`indent-mim-function'.")
+indent-mim-hook.")
(defvar indent-mim-arglist t
"*nil means indent arglists like ordinary lists.
@@ -125,16 +125,16 @@ Examples (for values 'stack, t, nil):
\"AUX\" \"AUX\" \"AUX\"
BLETCH ... BLETCH ... BLETCH ...")
-(put 'DEFINE 'indent-mim-function 'DEFINE)
-(put 'DEFMAC 'indent-mim-function 'DEFINE)
-(put 'BIND 'indent-mim-function 'DEFINE)
-(put 'PROG 'indent-mim-function 'DEFINE)
-(put 'REPEAT 'indent-mim-function 'DEFINE)
-(put 'CASE 'indent-mim-function 'DEFINE)
-(put 'FUNCTION 'indent-mim-function 'DEFINE)
-(put 'MAPF 'indent-mim-function 'DEFINE)
-(put 'MAPR 'indent-mim-function 'DEFINE)
-(put 'UNWIND 'indent-mim-function (cons (* 2 mim-body-indent) mim-body-indent))
+(put 'DEFINE 'indent-mim-hook 'DEFINE)
+(put 'DEFMAC 'indent-mim-hook 'DEFINE)
+(put 'BIND 'indent-mim-hook 'DEFINE)
+(put 'PROG 'indent-mim-hook 'DEFINE)
+(put 'REPEAT 'indent-mim-hook 'DEFINE)
+(put 'CASE 'indent-mim-hook 'DEFINE)
+(put 'FUNCTION 'indent-mim-hook 'DEFINE)
+(put 'MAPF 'indent-mim-hook 'DEFINE)
+(put 'MAPR 'indent-mim-hook 'DEFINE)
+(put 'UNWIND 'indent-mim-hook (cons (* 2 mim-body-indent) mim-body-indent))
(defvar mim-down-parens-only t
"*nil means treat ADECLs and ATOM trailers like structures when
@@ -150,17 +150,35 @@ only open paren syntax characters will be considered.")
(defun mim-mode ()
"Major mode for editing Mim (MDL in MDL) code.
Commands:
- If value of `mim-mode-hysterical-bindings' is non-nil, then following
-commands are assigned to escape keys as well (e.g. ESC f = ESC C-f).
+ If value of mim-mode-hysterical-bindings is non-nil, then following
+commands are assigned to escape keys as well (e.g. M-f = M-C-f).
The default action is bind the escape keys.
-\\{mim-mode-map}
+ Tab Indents the current line as MDL code.
+ Delete Converts tabs to spaces as it moves back.
+ M-C-f Move forward over next mim object.
+ M-C-b Move backward over previous mim object.
+ M-C-p Move to beginning of previous toplevel mim object.
+ M-C-n Move to the beginning of the next toplevel mim object.
+ M-C-a Move to the top of surrounding toplevel mim form.
+ M-C-e Move to the end of surrounding toplevel mim form.
+ M-C-u Move up a level of mim structure backwards.
+ M-C-d Move down a level of mim structure forwards.
+ M-C-t Transpose mim objects on either side of point.
+ M-C-k Kill next mim object.
+ M-C-h Place mark at end of next mim object.
+ M-C-o Insert a newline before current line and indent.
+ M-Delete Kill previous mim object.
+ M-^ Join current line to previous line.
+ M-\\ Delete whitespace around point.
+ M-; Move to existing comment or insert empty comment if none.
+ M-Tab Indent following mim object and all contained lines.
Other Commands:
Use \\[describe-function] to obtain documentation.
replace-in-mim-object find-mim-definition fast-syntax-check-mim
slow-syntax-check-mim backward-down-mim-object forward-up-mim-object
Variables:
Use \\[describe-variable] to obtain documentation.
- mim-mode-hook indent-mim-comment indent-mim-arglist indent-mim-function
+ mim-mode-hook indent-mim-comment indent-mim-arglist indent-mim-hook
mim-body-indent mim-down-parens-only mim-stop-for-slop
mim-mode-hysterical-bindings
Entry to this mode calls the value of mim-mode-hook if non-nil."
@@ -592,15 +610,15 @@ is reached."
;; then state corresponds to containing environment. if desired
;; indentation not determined, we are inside a form, so call hook.
(or desired-indent
- (and indent-mim-function
+ (and indent-mim-hook
(not retry)
(setq desired-indent
- (funcall indent-mim-function state indent-point)))
+ (funcall indent-mim-hook state indent-point)))
(setq desired-indent (current-column)))
(goto-char indent-point) ; back to where we started
desired-indent))) ; return column to indent to
-(defun indent-mim-function (state indent-point)
+(defun indent-mim-hook (state indent-point)
"Compute indentation for Mim special forms. Returns column or nil."
(let ((containing-sexp (car (cdr state))) (current-indent (point)))
(save-excursion
@@ -618,7 +636,7 @@ is reached."
(intern-soft (buffer-substring (point)
(progn (forward-sexp 1)
(point)))))
- (method (get function 'indent-mim-function)))
+ (method (get function 'indent-mim-hook)))
(if (or (if (equal method 'DEFINE) (setq method mim-body-indent))
(integerp method))
;; only use method if its first line after containing-sexp.
@@ -651,7 +669,7 @@ is reached."
(defun indent-mim-offset (state indent-point)
;; offset forms explicitly according to list of indentations.
(let ((mim-body-indent mim-body-indent)
- (indentations (get function 'indent-mim-function))
+ (indentations (get function 'indent-mim-hook))
(containing-sexp (car (cdr state)))
(last-sexp (car (nthcdr 2 state)))
indentation)
diff --git a/lisp/mim-mode.elc b/lisp/mim-mode.elc
new file mode 100644
index 00000000000..53d0c938f0a
--- /dev/null
+++ b/lisp/mim-mode.elc
Binary files differ
diff --git a/lisp/mim-syntax.elc b/lisp/mim-syntax.elc
new file mode 100644
index 00000000000..c8a712e9777
--- /dev/null
+++ b/lisp/mim-syntax.elc
Binary files differ
diff --git a/lisp/misc.el b/lisp/misc.el
deleted file mode 100644
index db7b3f223b5..00000000000
--- a/lisp/misc.el
+++ /dev/null
@@ -1,51 +0,0 @@
-;; Basic editing commands for Emacs
-;; Copyright (C) 1989 Free Software Foundation, Inc.
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 1, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
-
-(defun copy-from-above-command (&optional arg)
- "Copy characters from previous nonblank line, starting just above point.
-Copy ARG characters, but not past the end of that line.
-If no argument given, copy the entire rest of the line.
-The characters copied are inserted in the buffer before point."
- (interactive "P")
- (let ((cc (current-column))
- n
- (string ""))
- (save-excursion
- (beginning-of-line)
- (backward-char 1)
- (skip-chars-backward "\ \t\n")
- (move-to-column cc)
- ;; Default is enough to copy the whole rest of the line.
- (setq n (if arg (prefix-numeric-value arg) (point-max)))
- ;; If current column winds up in middle of a tab,
- ;; copy appropriate number of "virtual" space chars.
- (if (< cc (current-column))
- (if (= (preceding-char) ?\t)
- (progn
- (setq string (make-string (min n (- (current-column) cc)) ?\ ))
- (setq n (- n (min n (- (current-column) cc)))))
- ;; In middle of ctl char => copy that whole char.
- (backward-char 1)))
- (setq string (concat string
- (buffer-substring
- (point)
- (min (save-excursion (end-of-line) (point))
- (+ n (point)))))))
- (insert string)))
diff --git a/lisp/emulation/mlconvert.el b/lisp/mlconvert.el
index faf88e5ab32..faf88e5ab32 100644
--- a/lisp/emulation/mlconvert.el
+++ b/lisp/mlconvert.el
diff --git a/lisp/mlconvert.elc b/lisp/mlconvert.elc
new file mode 100644
index 00000000000..52f49fb53f8
--- /dev/null
+++ b/lisp/mlconvert.elc
Binary files differ
diff --git a/lisp/emulation/mlsupport.el b/lisp/mlsupport.el
index 14e7a3c9557..e3c75776109 100644
--- a/lisp/emulation/mlsupport.el
+++ b/lisp/mlsupport.el
@@ -31,6 +31,9 @@
(defmacro declare-buffer-specific (&rest vars)
(cons 'progn (mapcar (function (lambda (var) (list 'make-variable-buffer-local (list 'quote var)))) vars)))
+(defmacro setq-default (var val)
+ (list 'set-default (list 'quote var) val))
+
(defun ml-set-default (varname value)
(set-default (intern varname) value))
@@ -118,7 +121,7 @@
(1- (point)) (point-max))))))
(defun set-auto-fill-hook (arg)
- (setq auto-fill-function (intern arg)))
+ (setq auto-fill-hook (intern arg)))
(defun auto-execute (function pattern)
(if (/= (aref pattern 0) ?*)
diff --git a/lisp/mlsupport.elc b/lisp/mlsupport.elc
new file mode 100644
index 00000000000..b546e6341b9
--- /dev/null
+++ b/lisp/mlsupport.elc
Binary files differ
diff --git a/lisp/progmodes/modula2.el b/lisp/modula2.el
index eee1ece3a00..bf714f0b437 100644
--- a/lisp/progmodes/modula2.el
+++ b/lisp/modula2.el
@@ -8,7 +8,7 @@
;;; Added by TEP
(defvar m2-mode-syntax-table nil
- "Syntax table in use in Modula-2 buffers.")
+ "Syntax table in use in Modula-2-mode buffers.")
(defvar m2-compile-command "m2c"
"Command to compile Modula-2 programs")
@@ -65,7 +65,6 @@
(define-key map "\C-cy" 'm2-import)
(define-key map "\C-c{" 'm2-begin-comment)
(define-key map "\C-c}" 'm2-end-comment)
- (define-key map "\C-j" 'm2-newline)
(define-key map "\C-c\C-z" 'suspend-emacs)
(define-key map "\C-c\C-v" 'm2-visit)
(define-key map "\C-c\C-t" 'm2-toggle)
@@ -76,28 +75,28 @@
(defvar m2-indent 5 "*This variable gives the indentation in Modula-2-Mode")
(defun modula-2-mode ()
- "This is a mode intended to support program development in Modula-2.
-All control constructs of Modula-2 can be reached by typing C-c
-followed by the first character of the construct.
-\\<m2-mode-map>
- \\[m2-begin] begin \\[m2-case] case
- \\[m2-definition] definition \\[m2-else] else
- \\[m2-for] for \\[m2-header] header
- \\[m2-if] if \\[m2-module] module
- \\[m2-loop] loop \\[m2-or] or
- \\[m2-procedure] procedure Control-c Control-w with
- \\[m2-record] record \\[m2-stdio] stdio
- \\[m2-type] type \\[m2-until] until
- \\[m2-var] var \\[m2-while] while
- \\[m2-export] export \\[m2-import] import
- \\[m2-begin-comment] begin-comment \\[m2-end-comment] end-comment
- \\[suspend-emacs] suspend Emacs \\[m2-toggle] toggle
- \\[m2-compile] compile \\[m2-next-error] next-error
- \\[m2-link] link
-
- `m2-indent' controls the number of spaces for each indentation.
- `m2-compile-command' holds the command to compile a Modula-2 program.
- `m2-link-command' holds the command to link a Modula-2 program."
+"This is a mode intended to support program development in Modula-2.
+All control constructs of Modula-2 can be reached by typing
+Control-C followed by the first character of the construct.
+\\{m2-mode-map}
+ Control-c b begin Control-c c case
+ Control-c d definition Control-c e else
+ Control-c f for Control-c h header
+ Control-c i if Control-c m module
+ Control-c l loop Control-c o or
+ Control-c p procedure Control-c Control-w with
+ Control-c r record Control-c s stdio
+ Control-c t type Control-c u until
+ Control-c v var Control-c w while
+ Control-c x export Control-c y import
+ Control-c { begin-comment Control-c } end-comment
+ Control-c Control-z suspend-emacs Control-c Control-t toggle
+ Control-c Control-c compile Control-x ` next-error
+ Control-c Control-l link
+
+ m2-indent controls the number of spaces for each indentation.
+ m2-compile-command holds the command to compile a Modula-2 program.
+ m2-link-command holds the command to link a Modula-2 program."
(interactive)
(kill-all-local-variables)
(use-local-map m2-mode-map)
@@ -154,11 +153,10 @@ followed by the first character of the construct.
(defun m2-case ()
"Build skeleton CASE statment, prompting for the <expression>."
(interactive)
- (let ((name (read-string "Case-Expression: ")))
- (insert "CASE " name " OF")
- (m2-newline)
- (m2-newline)
- (insert "END (* case " name " *);"))
+ (insert "CASE " (read-string ": ") " OF")
+ (m2-newline)
+ (m2-newline)
+ (insert "END (* case *);")
(end-of-line 0)
(m2-tab))
@@ -182,18 +180,14 @@ followed by the first character of the construct.
(defun m2-for ()
"Build skeleton FOR loop statment, prompting for the loop parameters."
(interactive)
- (insert "FOR ")
- (let ((name (read-string "Loop Initialiser: ")) limit by)
- (insert name " TO ")
- (setq limit (read-string "Limit: "))
- (insert limit)
- (setq by (read-string "Step: "))
+ (insert "FOR " (read-string "init: ") " TO " (read-string "end: "))
+ (let ((by (read-string "by: ")))
(if (not (string-equal by ""))
- (insert " BY " by))
- (insert " DO")
- (m2-newline)
- (m2-newline)
- (insert "END (* for " name " to " limit " *);"))
+ (insert " BY " by)))
+ (insert " DO")
+ (m2-newline)
+ (m2-newline)
+ (insert "END (* for *);")
(end-of-line 0)
(m2-tab))
@@ -212,12 +206,10 @@ followed by the first character of the construct.
(defun m2-if ()
"Insert skeleton IF statment, prompting for <boolean-expression>."
(interactive)
- (insert "IF ")
- (let ((thecondition (read-string "<boolean-expression>: ")))
- (insert thecondition " THEN")
- (m2-newline)
- (m2-newline)
- (insert "END (* if " thecondition " *);"))
+ (insert "IF " (read-string "<boolean-expression>: ") " THEN")
+ (m2-newline)
+ (m2-newline)
+ (insert "END (* if *);")
(end-of-line 0)
(m2-tab))
@@ -236,19 +228,8 @@ followed by the first character of the construct.
(interactive)
(insert "IMPLEMENTATION MODULE ")
(let ((name (read-string "Name: ")))
- (insert name ";\n\n\n\nEND " name ".\n")
- (previous-line 3)
- (m2-header)
- (m2-type)
- (newline)
- (m2-var)
- (newline)
- (m2-begin)
- (m2-begin-comment)
- (insert " Module " name " Initialisation Code "))
- (m2-end-comment)
- (newline)
- (m2-tab))
+ (insert name ";\n\n\n\nEND " name ".\n"))
+ (previous-line 3))
(defun m2-or ()
(interactive)
@@ -282,12 +263,11 @@ followed by the first character of the construct.
(defun m2-with ()
(interactive)
(insert "WITH ")
- (let ((name (read-string "Record-Type: ")))
- (insert name)
- (insert " DO")
- (m2-newline)
- (m2-newline)
- (insert "END (* with " name " *);"))
+ (insert (read-string ": "))
+ (insert " DO")
+ (m2-newline)
+ (m2-newline)
+ (insert "END (* with *);")
(end-of-line 0)
(m2-tab))
@@ -303,14 +283,14 @@ followed by the first character of the construct.
(defun m2-stdio ()
(interactive)
(insert "
-FROM TextIO IMPORT
+>FROM TextIO IMPORT
WriteCHAR, ReadCHAR, WriteINTEGER, ReadINTEGER,
WriteCARDINAL, ReadCARDINAL, WriteBOOLEAN, ReadBOOLEAN,
WriteREAL, ReadREAL, WriteBITSET, ReadBITSET,
WriteBasedCARDINAL, ReadBasedCARDINAL, WriteChars, ReadChars,
WriteString, ReadString, WhiteSpace, EndOfLine;
-FROM SysStreams IMPORT sysIn, sysOut, sysErr;
+>FROM SysStreams IMPORT sysIn, sysOut, sysErr;
"))
@@ -326,7 +306,7 @@ FROM SysStreams IMPORT sysIn, sysOut, sysErr;
(m2-newline)
(m2-newline)
(insert "UNTIL ")
- (insert (read-string "<boolean-expression>: ") ";")
+ (insert (read-string ": ") ";")
(end-of-line 0)
(m2-tab))
@@ -340,11 +320,11 @@ FROM SysStreams IMPORT sysIn, sysOut, sysErr;
(defun m2-while ()
(interactive)
(insert "WHILE ")
- (let ((name (read-string "<boolean-expression>: ")))
- (insert name " DO" )
- (m2-newline)
- (m2-newline)
- (insert "END (* while " name " *);"))
+ (insert (read-string ": "))
+ (insert " DO")
+ (m2-newline)
+ (m2-newline)
+ (insert "END (* while *);")
(end-of-line 0)
(m2-tab))
diff --git a/lisp/modula2.elc b/lisp/modula2.elc
new file mode 100644
index 00000000000..e469854a3e2
--- /dev/null
+++ b/lisp/modula2.elc
Binary files differ
diff --git a/lisp/mouse.el b/lisp/mouse.el
deleted file mode 100644
index 5ca1c02c252..00000000000
--- a/lisp/mouse.el
+++ /dev/null
@@ -1,524 +0,0 @@
-;; Mouse support that is independent of window systems.
-;; Copyright (C) 1988 Free Software Foundation, Inc.
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 1, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
-(provide 'mouse)
-
-
-(defun mouse-select ()
- "Select the Emacs window the mouse is on."
- (interactive "@"))
-
-(defun mouse-delete-window ()
- "Delete the Emacs window the mouse is on."
- (interactive "@")
- (delete-window))
-
-(defun mouse-keep-one-window ()
- "Select Emacs window mouse is on, then kill all other Emacs windows."
- (interactive "@")
- (delete-other-windows))
-
-(defun mouse-select-and-split ()
- "Select Emacs window mouse is on, then split it vertically in half."
- (interactive "@")
- (split-window-vertically nil))
-
-(defun mouse-set-point (event)
- "Select Emacs window mouse is on, and move point to mouse position."
- (interactive "@e")
- (let ((relative-coordinate
- (coordinates-in-window-p (car event) (selected-window))))
- (if (consp relative-coordinate)
- (progn
- (move-to-window-line (car (cdr relative-coordinate)))
- ;; Note that hscroll must get above 1
- ;; before the text actually starts to move.
- (move-to-column (+ (car relative-coordinate) (current-column)
- (1- (max 1 (window-hscroll (selected-window))))))
- (what-line)))))
-
-(defun mouse-eval-last-sexpr (event)
- (interactive "@e")
- (save-excursion
- (mouse-set-point event)
- (eval-last-sexp nil)))
-
-(defun mouse-line-length (event)
- "Print the length of the line indicated by the pointer."
- (interactive "@e")
- (let ((relative-coordinate
- (coordinates-in-window-p (car event) (selected-window))))
- (if (consp relative-coordinate)
- (save-excursion
- (move-to-window-line (car (cdr relative-coordinate)))
- (end-of-line)
- (push-mark nil t)
- (beginning-of-line)
- (message "Line length: %d"
- (- (region-end) (region-beginning)))
- (sleep-for 1)))))
-
-(defun mouse-set-mark (event)
- "Select Emacs window mouse is on, and set mark at mouse position.
-Display cursor at that position for a second."
- (interactive "@e")
- (let ((point-save (point)))
- (unwind-protect
- (progn (mouse-set-point event)
- (push-mark nil t)
- (sit-for 1))
- (goto-char point-save))))
-
-(defun mouse-fill-paragraph (event)
- "Fill the paragraph at the mouse position."
- (interactive "@e")
- (save-excursion
- (mouse-set-point event)
- (fill-paragraph)))
-
-(defun mouse-fill-paragraph-with-prefix (event)
- "Fill the paragraph at the mouse position with specified fill prefix.
-Click at the end of the fill prefix that you want;
-The text before the mouse position, on the same line, is used as the prefix."
- (interactive "@e")
- (save-excursion
- (mouse-set-point event)
- (let ((fill-prefix (buffer-substring (save-excursion (beginning-of-line)
- (point))
- (point))))
- (fill-paragraph))))
-
-(defun mouse-scroll (event)
- "Scroll point to the mouse position."
- (interactive "@e")
- (let ((relative-coordinate
- (coordinates-in-window-p (car event) (selected-window))))
- (if (consp relative-coordinate)
- (progn
- (recenter (car (cdr relative-coordinate)))
- (scroll-right (+ (car relative-coordinate) (current-column)))))))
-
-(defun mouse-del-char (event)
- "Delete the char pointed to by the mouse."
- (interactive "@e")
- (let ((relative-coordinate
- (coordinates-in-window-p (car event) (selected-window))))
- (if (consp relative-coordinate)
- (progn
- (move-to-window-line (car (cdr relative-coordinate)))
- (move-to-column (+ (car relative-coordinate) (current-column)))
- (delete-char 1 nil)))))
-
-(defun mouse-kill-line (event)
- "Kill the line pointed to by the mouse."
- (interactive "@e")
- (let ((relative-coordinate
- (coordinates-in-window-p (car event) (selected-window))))
- (if (consp relative-coordinate)
- (progn
- (move-to-window-line (car (cdr relative-coordinate)))
- (move-to-column (+ (car relative-coordinate) (current-column)))
- (kill-line nil)))))
-
-(defun narrow-window-to-region (m n)
- "Narrow window to region between point and last mark"
- (interactive "r")
- (save-excursion
- (save-restriction
- (if (eq (selected-window) (next-window))
- (split-window))
- (goto-char m)
- (recenter 0)
- (if (eq (selected-window)
- (if (zerop (minibuffer-depth))
- (next-window)))
- ()
- (shrink-window (- (- (window-height) (count-lines m n)) 1))))))
-
-(defun mouse-window-to-region (event)
- "Narrow window to region between cursor and mouse pointer."
- (interactive "@e")
- (let ((point-save (point)))
- (unwind-protect
- (progn (mouse-set-point event)
- (push-mark nil t)
- (sit-for 1))
- (goto-char point-save)
- (narrow-window-to-region (region-beginning) (region-end)))))
-
-(defun mouse-ignore ()
- "Don't do anything."
- (interactive))
-
-;; Commands for the scroll bar.
-
-(defun mouse-scroll-down (nlines)
- (interactive "@p")
- (scroll-down nlines))
-
-(defun mouse-scroll-up (nlines)
- (interactive "@p")
- (scroll-up nlines))
-
-(defun mouse-scroll-down-full ()
- (interactive "@")
- (scroll-down nil))
-
-(defun mouse-scroll-up-full ()
- (interactive "@")
- (scroll-up nil))
-
-(defun mouse-scroll-move-cursor (nlines)
- (interactive "@p")
- (move-to-window-line nlines))
-
-(defun mouse-scroll-absolute (event)
- (interactive "@e")
- (let* ((pos (car event))
- (position (car pos))
- (length (car (cdr pos))))
- (if (<= length 0) (setq length 1))
- (let* ((scale-factor (max 1 (/ length (/ 8000000 (buffer-size)))))
- (newpos (* (/ (* (/ (buffer-size) scale-factor)
- position)
- length)
- scale-factor)))
- (goto-char newpos)
- (recenter '(4)))))
-
-(defun mouse-scroll-left (ncolumns)
- (interactive "@p")
- (scroll-left ncolumns))
-
-(defun mouse-scroll-right (ncolumns)
- (interactive "@p")
- (scroll-right ncolumns))
-
-(defun mouse-scroll-left-full ()
- (interactive "@")
- (scroll-left nil))
-
-(defun mouse-scroll-right-full ()
- (interactive "@")
- (scroll-right nil))
-
-(defun mouse-scroll-move-cursor-horizontally (ncolumns)
- (interactive "@p")
- (move-to-column ncolumns))
-
-(defun mouse-scroll-absolute-horizontally (event)
- (interactive "@e")
- (let* ((pos (car event))
- (position (car pos))
- (length (car (cdr pos))))
- (set-window-hscroll (selected-window) 33)))
-
-;; Set up these commands, including the prefix keys for the scroll bar.
-
-(fset 'mouse-vertical-scroll-bar-prefix (make-sparse-keymap))
-(define-key global-mouse-map mouse-vertical-scroll-bar-prefix
- 'mouse-vertical-scroll-bar-prefix)
-
-(defun mouse-scroll-motion (event)
- (interactive "e")
- (let ((pos (car (car event)))
- (length (car (cdr (car event)))))
- (message "[%d %d]" pos length)))
-
-(let ((map (function mouse-vertical-scroll-bar-prefix)))
- (define-key map mouse-button-right 'mouse-scroll-down)
- (define-key map mouse-button-left 'mouse-scroll-up)
- (define-key map mouse-button-middle 'mouse-scroll-absolute)
- (define-key map mouse-motion 'x-horizontal-line))
-
-;(fset 'mouse-vertical-slider-prefix (make-sparse-keymap))
-;(define-key global-mouse-map mouse-vertical-slider-prefix
-; 'mouse-vertical-slider-prefix)
-
-;(let ((map (function mouse-vertical-slider-prefix)))
-; (define-key map mouse-button-right 'mouse-scroll-move-cursor)
-; (define-key map mouse-button-left 'mouse-scroll-move-cursor)
-; (define-key map mouse-button-middle 'mouse-scroll-move-cursor))
-
-(fset 'mouse-vertical-thumbup-prefix (make-sparse-keymap))
-(define-key global-mouse-map mouse-vertical-thumbup-prefix
- 'mouse-vertical-thumbup-prefix)
-
-(let ((map (function mouse-vertical-thumbup-prefix)))
- (define-key map mouse-button-right 'mouse-scroll-down-full)
- (define-key map mouse-button-left 'mouse-scroll-down-full)
- (define-key map mouse-button-middle 'mouse-scroll-down-full))
-
-(fset 'mouse-vertical-thumbdown-prefix (make-sparse-keymap))
-(define-key global-mouse-map mouse-vertical-thumbdown-prefix
- 'mouse-vertical-thumbdown-prefix)
-
-(let ((map (function mouse-vertical-thumbdown-prefix)))
- (define-key map mouse-button-right 'mouse-scroll-up-full)
- (define-key map mouse-button-left 'mouse-scroll-up-full)
- (define-key map mouse-button-middle 'mouse-scroll-up-full))
-
-;; Horizontal bar
-
-(fset 'mouse-horizontal-scroll-bar-prefix (make-sparse-keymap))
-(define-key global-mouse-map mouse-horizontal-scroll-bar-prefix
- 'mouse-horizontal-scroll-bar-prefix)
-
-(let ((map (function mouse-horizontal-scroll-bar-prefix)))
- (define-key map mouse-button-right 'mouse-scroll-right)
- (define-key map mouse-button-left 'mouse-scroll-left)
- (define-key map mouse-button-middle 'mouse-scroll-absolute-horizontally))
-
-(fset 'mouse-horizontal-thumbleft-prefix (make-sparse-keymap))
-(define-key global-mouse-map mouse-horizontal-thumbleft-prefix
- 'mouse-horizontal-thumbleft-prefix)
-
-(let ((map (function mouse-horizontal-thumbleft-prefix)))
- (define-key map mouse-button-right 'mouse-scroll-left-full)
- (define-key map mouse-button-left 'mouse-scroll-left-full)
- (define-key map mouse-button-middle 'mouse-scroll-left-full))
-
-(fset 'mouse-horizontal-thumbright-prefix (make-sparse-keymap))
-(define-key global-mouse-map mouse-horizontal-thumbright-prefix
- 'mouse-horizontal-thumbright-prefix)
-
-(let ((map (function mouse-horizontal-thumbright-prefix)))
- (define-key map mouse-button-right 'mouse-scroll-right-full)
- (define-key map mouse-button-left 'mouse-scroll-right-full)
- (define-key map mouse-button-middle 'mouse-scroll-right-full))
-
-
-;;
-;; Here are experimental things being tested. Mouse events
-;; are of the form:
-;; ((x y) window screen-part key-sequence timestamp)
-
-;;
-;; Dynamically track mouse coordinates
-;;
-
-(defun track-mouse (event)
- "Track the coordinates, absolute and relative, of the mouse."
- (interactive "@e")
- (while mouse-grabbed
- (let* ((pos (read-mouse-position (selected-screen)))
- (abs-x (car pos))
- (abs-y (cdr pos))
- (relative-coordinate (coordinates-in-window-p
- (list (car pos) (cdr pos))
- (selected-window))))
- (if (consp relative-coordinate)
- (message "mouse: [%d %d], (%d %d)" abs-x abs-y
- (car relative-coordinate)
- (car (cdr relative-coordinate)))
- (message "mouse: [%d %d]" abs-x abs-y)))))
-
-;;
-;; Dynamically put a box around the line indicated by point
-;;
-
-(require 'backquote)
-
-(defun mouse-select-buffer-line (event)
- (interactive "@e")
- (let ((relative-coordinate
- (coordinates-in-window-p (car event) (selected-window)))
- (abs-y (car (cdr (car event)))))
- (if (consp relative-coordinate)
- (progn
- (save-excursion
- (move-to-window-line (car (cdr relative-coordinate)))
- (x-draw-rectangle
- (selected-screen)
- abs-y 0
- (save-excursion
- (move-to-window-line (car (cdr relative-coordinate)))
- (end-of-line)
- (push-mark nil t)
- (beginning-of-line)
- (- (region-end) (region-beginning))) 1)
- (setq the-buffer (Buffer-menu-buffer t)))
- (sit-for 1)
- (x-erase-rectangle (selected-screen))))))
-
-(defvar last-line-drawn nil)
-(defvar begin-delim "[^ \t]")
-(defvar end-delim "[^ \t]")
-
-(defun mouse-boxing (event)
- (interactive "@e")
- (save-excursion
- (let ((screen (selected-screen)))
- (while (= (x-mouse-events) 0)
- (let* ((pos (read-mouse-position screen))
- (abs-x (car pos))
- (abs-y (cdr pos))
- (relative-coordinate
- (coordinates-in-window-p (` ((, abs-x) (, abs-y)))
- (selected-window)))
- (begin-reg nil)
- (end-reg nil)
- (end-column nil)
- (begin-column nil))
- (if (and (consp relative-coordinate)
- (or (not last-line-drawn)
- (not (= last-line-drawn abs-y))))
- (progn
- (move-to-window-line (car (cdr relative-coordinate)))
- (if (= (following-char) 10)
- ()
- (progn
- (setq begin-reg (1- (re-search-forward end-delim)))
- (setq begin-column (1- (current-column)))
- (end-of-line)
- (setq end-reg (1+ (re-search-backward begin-delim)))
- (setq end-column (1+ (current-column)))
- (message "%s" (buffer-substring begin-reg end-reg))
- (x-draw-rectangle screen
- (setq last-line-drawn abs-y)
- begin-column
- (- end-column begin-column) 1))))))))))
-
-(defun mouse-erase-box ()
- (interactive)
- (if last-line-drawn
- (progn
- (x-erase-rectangle (selected-screen))
- (setq last-line-drawn nil))))
-
-(defun test-x-rectangle ()
- (use-local-mouse-map (setq rectangle-test-map (make-sparse-keymap)))
- (define-key rectangle-test-map mouse-motion-button-left 'mouse-boxing)
- (define-key rectangle-test-map mouse-button-left-up 'mouse-erase-box))
-
-;;
-;; Here is how to do double clicking in lisp. About to change.
-;;
-
-(defvar double-start nil)
-(defconst double-click-interval 300
- "Max ticks between clicks")
-
-(defun double-down (event)
- (interactive "@e")
- (if double-start
- (let ((interval (- (nth 4 event) double-start)))
- (if (< interval double-click-interval)
- (progn
- (backward-up-list 1)
- ;; (message "Interval %d" interval)
- (sleep-for 1)))
- (setq double-start nil))
- (setq double-start (nth 4 event))))
-
-(defun double-up (event)
- (interactive "@e")
- (and double-start
- (> (- (nth 4 event ) double-start) double-click-interval)
- (setq double-start nil)))
-
-(defun x-test-doubleclick ()
- (use-local-mouse-map (setq doubleclick-test-map (make-sparse-keymap)))
- (define-key doubleclick-test-map mouse-button-left 'double-down)
- (define-key doubleclick-test-map mouse-button-left-up 'double-up))
-
-;;
-;; This scrolls while button is depressed. Use preferable in scrollbar.
-;;
-
-(defvar scrolled-lines 0)
-(defconst scroll-speed 1)
-
-(defun incr-scroll-down (event)
- (interactive "@e")
- (setq scrolled-lines 0)
- (incremental-scroll scroll-speed))
-
-(defun incr-scroll-up (event)
- (interactive "@e")
- (setq scrolled-lines 0)
- (incremental-scroll (- scroll-speed)))
-
-(defun incremental-scroll (n)
- (while (= (x-mouse-events) 0)
- (setq scrolled-lines (1+ (* scroll-speed scrolled-lines)))
- (scroll-down n)
- (sit-for 300 t)))
-
-(defun incr-scroll-stop (event)
- (interactive "@e")
- (message "Scrolled %d lines" scrolled-lines)
- (setq scrolled-lines 0)
- (sleep-for 1))
-
-(defun x-testing-scroll ()
- (let ((scrolling-map (function mouse-vertical-scroll-bar-prefix)))
- (define-key scrolling-map mouse-button-left 'incr-scroll-down)
- (define-key scrolling-map mouse-button-right 'incr-scroll-up)
- (define-key scrolling-map mouse-button-left-up 'incr-scroll-stop)
- (define-key scrolling-map mouse-button-right-up 'incr-scroll-stop)))
-
-;;
-;; Some playthings suitable for picture mode? They need work.
-;;
-
-(defun mouse-kill-rectangle (event)
- "Kill the rectangle between point and the mouse cursor."
- (interactive "@e")
- (let ((point-save (point)))
- (save-excursion
- (mouse-set-point event)
- (push-mark nil t)
- (if (> point-save (point))
- (kill-rectangle (point) point-save)
- (kill-rectangle point-save (point))))))
-
-(defun mouse-open-rectangle (event)
- "Kill the rectangle between point and the mouse cursor."
- (interactive "@e")
- (let ((point-save (point)))
- (save-excursion
- (mouse-set-point event)
- (push-mark nil t)
- (if (> point-save (point))
- (open-rectangle (point) point-save)
- (open-rectangle point-save (point))))))
-
-;; Must be a better way to do this.
-
-(defun mouse-multiple-insert (n char)
- (while (> n 0)
- (insert char)
- (setq n (1- n))))
-
-;; What this could do is not finalize until button was released.
-
-(defun mouse-move-text (event)
- "Move text from point to cursor position, inserting spaces."
- (interactive "@e")
- (let* ((relative-coordinate
- (coordinates-in-window-p (car event) (selected-window))))
- (if (consp relative-coordinate)
- (cond ((> (current-column) (car relative-coordinate))
- (delete-char
- (- (car relative-coordinate) (current-column))))
- ((< (current-column) (car relative-coordinate))
- (mouse-multiple-insert
- (- (car relative-coordinate) (current-column)) " "))
- ((= (current-column) (car relative-coordinate)) (ding))))))
diff --git a/lisp/netunam.el b/lisp/netunam.el
deleted file mode 100644
index 44d828729ef..00000000000
--- a/lisp/netunam.el
+++ /dev/null
@@ -1,152 +0,0 @@
-;; HP-UX RFA Commands
-;; Copyright (C) 1988 Free Software Foundation, Inc.
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 1, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
-;;; Author: cph@zurich.ai.mit.edu
-
-;;; $Header: netunam.el,v 1.3 88/12/21 16:32:23 GMT cph Exp $
-
-(defconst rfa-node-directory "/net/"
- "Directory in which RFA network special files are stored.
-By HP convention, this is \"/net/\".")
-
-(defvar rfa-default-node nil
- "If not nil, this is the name of the default RFA network special file.")
-
-(defvar rfa-password-memoize-p t
- "If non-nil, remember login user's passwords after they have been entered.")
-
-(defvar rfa-password-alist '()
- "An association from node-name strings to password strings.
-Used if `rfa-password-memoize-p' is non-nil.")
-
-(defvar rfa-password-per-node-p t
- "If nil, login user uses same password on all machines.
-Has no effect if `rfa-password-memoize-p' is nil.")
-
-(defun rfa-set-password (password &optional node user)
- "Add PASSWORD to the RFA password database.
-Optional second arg NODE is a string specifying a particular nodename;
- if supplied and not nil, PASSWORD applies to only that node.
-Optional third arg USER is a string specifying the (remote) user whose
- password this is; if not supplied this defaults to (user-login-name)."
- (if (not user) (setq user (user-login-name)))
- (let ((node-entry (assoc node rfa-password-alist)))
- (if node-entry
- (let ((user-entry (assoc user (cdr node-entry))))
- (if user-entry
- (rplacd user-entry password)
- (rplacd node-entry
- (nconc (cdr node-entry)
- (list (cons user password))))))
- (setq rfa-password-alist
- (nconc rfa-password-alist
- (list (list node (cons user password))))))))
-
-(defun rfa-open (node &optional user password)
- "Open a network connection to a server using remote file access.
-First argument NODE is the network node for the remote machine.
-Second optional argument USER is the user name to use on that machine.
- If called interactively, the user name is prompted for.
-Third optional argument PASSWORD is the password string for that user.
- If not given, this is filled in from the value of
-`rfa-password-alist', or prompted for. A prefix argument of - will
-cause the password to be prompted for even if previously memoized."
- (interactive
- (list (read-file-name "rfa-open: " rfa-node-directory rfa-default-node t)
- (read-string "user-name: " (user-login-name))))
- (let ((node
- (and (or rfa-password-per-node-p
- (not (equal user (user-login-name))))
- node)))
- (if (not password)
- (setq password
- (let ((password
- (cdr (assoc user (cdr (assoc node rfa-password-alist))))))
- (or (and (not current-prefix-arg) password)
- (rfa-password-read
- (format "password for user %s%s: "
- user
- (if node (format " on node \"%s\"" node) ""))
- password))))))
- (let ((result
- (sysnetunam (expand-file-name node rfa-node-directory)
- (concat user ":" password))))
- (if (interactive-p)
- (if result
- (message "Opened network connection to %s as %s" node user)
- (error "Unable to open network connection")))
- (if (and rfa-password-memoize-p result)
- (rfa-set-password password node user))
- result))
-
-(defun rfa-close (node)
- "Close a network connection to a server using remote file access.
-NODE is the network node for the remote machine."
- (interactive
- (list (read-file-name "rfa-close: " rfa-node-directory rfa-default-node t)))
- (let ((result (sysnetunam (expand-file-name node rfa-node-directory) "")))
- (cond ((not (interactive-p)) result)
- ((not result) (error "Unable to close network connection"))
- (t (message "Closed network connection to %s" node)))))
-
-(defun rfa-password-read (prompt default)
- (let ((rfa-password-accumulator (or default "")))
- (read-from-minibuffer prompt
- (and default
- (let ((copy (concat default))
- (index 0)
- (length (length default)))
- (while (< index length)
- (aset copy index ?.)
- (setq index (1+ index)))
- copy))
- rfa-password-map)
- rfa-password-accumulator))
-
-(defvar rfa-password-map nil)
-(if (not rfa-password-map)
- (let ((char ? ))
- (setq rfa-password-map (make-keymap))
- (while (< char 127)
- (define-key rfa-password-map (char-to-string char)
- 'rfa-password-self-insert)
- (setq char (1+ char)))
- (define-key rfa-password-map "\C-g"
- 'abort-recursive-edit)
- (define-key rfa-password-map "\177"
- 'rfa-password-rubout)
- (define-key rfa-password-map "\n"
- 'exit-minibuffer)
- (define-key rfa-password-map "\r"
- 'exit-minibuffer)))
-
-(defvar rfa-password-accumulator nil)
-
-(defun rfa-password-self-insert ()
- (interactive)
- (setq rfa-password-accumulator
- (concat rfa-password-accumulator
- (char-to-string last-command-char)))
- (insert ?.))
-
-(defun rfa-password-rubout ()
- (interactive)
- (delete-char -1)
- (setq rfa-password-accumulator
- (substring rfa-password-accumulator 0 -1)))
diff --git a/lisp/nnspool.el b/lisp/nnspool.el
deleted file mode 100644
index 8c5a36ca6ba..00000000000
--- a/lisp/nnspool.el
+++ /dev/null
@@ -1,374 +0,0 @@
-;;; Spool access using NNTP for GNU Emacs
-;; Copyright (C) 1988, 1989 Fujitsu Laboratories LTD.
-;; Copyright (C) 1988, 1989, 1990 Masanobu UMEDA
-;; $Header: nnspool.el,v 1.10 90/03/23 13:25:25 umerin Locked $
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY. No author or distributor
-;; accepts responsibility to anyone for the consequences of using it
-;; or for whether it serves any particular purpose or works at all,
-;; unless he says so in writing. Refer to the GNU Emacs General Public
-;; License for full details.
-
-;; Everyone is granted permission to copy, modify and redistribute
-;; GNU Emacs, but only under the conditions described in the
-;; GNU Emacs General Public License. A copy of this license is
-;; supposed to have been given to you along with GNU Emacs so you
-;; can know your rights and responsibilities. It should be in a
-;; file named COPYING. Among other things, the copyright notice
-;; and this notice must be preserved on all copies.
-
-(provide 'nnspool)
-(require 'nntp)
-
-(defvar nnspool-inews-program news-inews-program
- "*Program to post news.")
-
-(defvar nnspool-inews-switches '("-h")
- "*Switches for nnspool-request-post to pass to `inews' for posting news.")
-
-(defvar nnspool-spool-directory news-path
- "*Local news spool directory.")
-
-(defvar nnspool-active-file "/usr/lib/news/active"
- "*Local news active file.")
-
-(defvar nnspool-history-file "/usr/lib/news/history"
- "*Local news history file.")
-
-
-
-(defconst nnspool-version "NNSPOOL 1.10"
- "Version numbers of this version of NNSPOOL.")
-
-(defvar nnspool-current-directory nil
- "Current news group directory.")
-
-;;;
-;;; Replacement of Extended Command for retrieving many headers.
-;;;
-
-(defun nnspool-retrieve-headers (sequence)
- "Return list of article headers specified by SEQUENCE of article id.
-The format of list is
- `([NUMBER SUBJECT FROM XREF LINES DATE MESSAGE-ID REFERENCES] ...)'.
-Reader macros for the vector are defined as `nntp-header-FIELD'.
-Writer macros for the vector are defined as `nntp-set-header-FIELD'.
-News group must be selected before calling me."
- (save-excursion
- (set-buffer nntp-server-buffer)
- ;;(erase-buffer)
- (let ((file nil)
- (number (length sequence))
- (count 0)
- (headers nil) ;Result list.
- (article 0)
- (subject nil)
- (message-id nil)
- (from nil)
- (xref nil)
- (lines 0)
- (date nil)
- (references nil))
- (while sequence
- ;;(nntp-send-strings-to-server "HEAD" (car sequence))
- (setq article (car sequence))
- (setq file
- (concat nnspool-current-directory (prin1-to-string article)))
- (if (and (file-exists-p file)
- (not (file-directory-p file)))
- (progn
- (erase-buffer)
- (insert-file-contents file)
- ;; Make message body invisible.
- (goto-char (point-min))
- (search-forward "\n\n" nil 'move)
- (narrow-to-region (point-min) (point))
- ;; Fold continuation lines.
- (goto-char (point-min))
- (while (re-search-forward "\\(\r?\n[ \t]+\\)+" nil t)
- (replace-match " " t t))
- ;; Make it possible to search for `\nFIELD'.
- (goto-char (point-min))
- (insert "\n")
- ;; Extract From:
- (goto-char (point-min))
- (if (search-forward "\nFrom: " nil t)
- (setq from (buffer-substring
- (point)
- (save-excursion (end-of-line) (point))))
- (setq from "(Unknown User)"))
- ;; Extract Subject:
- (goto-char (point-min))
- (if (search-forward "\nSubject: " nil t)
- (setq subject (buffer-substring
- (point)
- (save-excursion (end-of-line) (point))))
- (setq subject "(None)"))
- ;; Extract Message-ID:
- (goto-char (point-min))
- (if (search-forward "\nMessage-ID: " nil t)
- (setq message-id (buffer-substring
- (point)
- (save-excursion (end-of-line) (point))))
- (setq message-id nil))
- ;; Extract Date:
- (goto-char (point-min))
- (if (search-forward "\nDate: " nil t)
- (setq date (buffer-substring
- (point)
- (save-excursion (end-of-line) (point))))
- (setq date nil))
- ;; Extract Lines:
- (goto-char (point-min))
- (if (search-forward "\nLines: " nil t)
- (setq lines (string-to-int
- (buffer-substring
- (point)
- (save-excursion (end-of-line) (point)))))
- (setq lines 0))
- ;; Extract Xref:
- (goto-char (point-min))
- (if (search-forward "\nXref: " nil t)
- (setq xref (buffer-substring
- (point)
- (save-excursion (end-of-line) (point))))
- (setq xref nil))
- ;; Extract References:
- (goto-char (point-min))
- (if (search-forward "\nReferences: " nil t)
- (setq references (buffer-substring
- (point)
- (save-excursion (end-of-line) (point))))
- (setq references nil))
- (setq headers
- (cons (vector article subject from
- xref lines date
- message-id references) headers))
- ))
- (setq sequence (cdr sequence))
- (setq count (1+ count))
- (and (numberp nntp-large-newsgroup)
- (> number nntp-large-newsgroup)
- (zerop (% count 20))
- (message "NNSPOOL: %d%% of headers received."
- (/ (* count 100) number)))
- )
- (and (numberp nntp-large-newsgroup)
- (> number nntp-large-newsgroup)
- (message "NNSPOOL: 100%% of headers received."))
- (nreverse headers)
- )))
-
-
-;;;
-;;; Replacement of NNTP Raw Interface.
-;;;
-
-(defun nnspool-open-server (host &optional service)
- "Open news server on HOST.
-If HOST is nil, use value of environment variable `NNTPSERVER'.
-If optional argument SERVICE is non-nil, open by the service name."
- (let ((host (or host (getenv "NNTPSERVER")))
- (status nil))
- (setq nntp-status-message-string "")
- (cond ((and (file-directory-p nnspool-spool-directory)
- (file-exists-p nnspool-active-file)
- (string-equal host (system-name)))
- (setq status (nnspool-open-server-internal host service)))
- ((string-equal host (system-name))
- (setq nntp-status-message-string
- (format "%s has no news spool. Goodbye." host)))
- ((null host)
- (setq nntp-status-message-string "NNTP server is not specified."))
- (t
- (setq nntp-status-message-string
- (format "NNSPOOL: cannot talk to %s." host)))
- )
- status
- ))
-
-(defun nnspool-close-server ()
- "Close news server."
- (nnspool-close-server-internal))
-
-(fset 'nnspool-request-quit (symbol-function 'nnspool-close-server))
-
-(defun nnspool-server-opened ()
- "Return server process status, T or NIL.
-If the stream is opened, return T, otherwise return NIL."
- (and nntp-server-buffer
- (get-buffer nntp-server-buffer)))
-
-(defun nnspool-status-message ()
- "Return server status response as string."
- nntp-status-message-string
- )
-
-(defun nnspool-request-article (id)
- "Select article by message ID (or number)."
- (let ((file (if (stringp id)
- (nnspool-find-article-by-message-id id)
- (concat nnspool-current-directory (prin1-to-string id)))))
- (if (and (stringp file)
- (file-exists-p file)
- (not (file-directory-p file)))
- (save-excursion
- (nnspool-find-file file)))
- ))
-
-(defun nnspool-request-body (id)
- "Select article body by message ID (or number)."
- (if (nnspool-request-article id)
- (save-excursion
- (set-buffer nntp-server-buffer)
- (goto-char (point-min))
- (if (search-forward "\n\n" nil t)
- (delete-region (point-min) (point)))
- t
- )
- ))
-
-(defun nnspool-request-head (id)
- "Select article head by message ID (or number)."
- (if (nnspool-request-article id)
- (save-excursion
- (set-buffer nntp-server-buffer)
- (goto-char (point-min))
- (if (search-forward "\n\n" nil t)
- (delete-region (1- (point)) (point-max)))
- t
- )
- ))
-
-(defun nnspool-request-stat (id)
- "Select article by message ID (or number)."
- (error "NNSPOOL: STAT is not implemented."))
-
-(defun nnspool-request-group (group)
- "Select news GROUP."
- (let ((pathname (nnspool-article-pathname
- (nnspool-replace-chars-in-string group ?. ?/))))
- (if (file-directory-p pathname)
- (setq nnspool-current-directory pathname))
- ))
-
-(defun nnspool-request-list ()
- "List valid newsgoups."
- (save-excursion
- (nnspool-find-file nnspool-active-file)))
-
-(defun nnspool-request-last ()
- "Set current article pointer to the previous article in the current news group."
- (error "NNSPOOL: LAST is not implemented."))
-
-(defun nnspool-request-next ()
- "Advance current article pointer."
- (error "NNSPOOL: NEXT is not implemented."))
-
-(defun nnspool-request-post ()
- "Post a new news in current buffer."
- (save-excursion
- ;; We have to work in the server buffer because of NEmacs hack.
- (copy-to-buffer nntp-server-buffer (point-min) (point-max))
- (set-buffer nntp-server-buffer)
- (apply 'call-process-region
- (point-min) (point-max)
- nnspool-inews-program 'delete t nil nnspool-inews-switches)
- (prog1
- (or (zerop (buffer-size))
- ;; If inews returns strings, it must be error message
- ;; unless SPOOLNEWS is defined.
- ;; This condition is very weak, but there is no good rule
- ;; identifying errors when SPOOLNEWS is defined.
- ;; Suggested by ohm@kaba.junet.
- (string-match "spooled" (buffer-string)))
- ;; Make status message by unfolding lines.
- (subst-char-in-region (point-min) (point-max) ?\n ?\\ 'noundo)
- (setq nntp-status-message-string (buffer-string))
- (erase-buffer))
- ))
-
-
-;;;
-;;; Replacement of Low-Level Interface to NNTP Server.
-;;;
-
-(defun nnspool-open-server-internal (host &optional service)
- "Open connection to news server on HOST by SERVICE (default is nntp)."
- (save-excursion
- (if (not (string-equal host (system-name)))
- (error "NNSPOOL: cannot talk to %s." host))
- ;; Initialize communication buffer.
- (setq nntp-server-buffer (get-buffer-create " *nntpd*"))
- (set-buffer nntp-server-buffer)
- (buffer-flush-undo (current-buffer))
- (erase-buffer)
- (kill-all-local-variables)
- (setq case-fold-search t) ;Should ignore case.
- (setq nntp-server-process nil)
- (setq nntp-server-name host)
- ;; It is possible to change kanji-fileio-code in this hook.
- (run-hooks 'nntp-server-hook)
- t
- ))
-
-(defun nnspool-close-server-internal ()
- "Close connection to news server."
- (if (get-file-buffer nnspool-history-file)
- (kill-buffer (get-file-buffer nnspool-history-file)))
- (if nntp-server-buffer
- (kill-buffer nntp-server-buffer))
- (setq nntp-server-buffer nil)
- (setq nntp-server-process nil))
-
-(defun nnspool-find-article-by-message-id (id)
- "Return full pathname of an article identified by message-ID."
- (save-excursion
- (let ((buffer (get-file-buffer nnspool-history-file)))
- (if buffer
- (set-buffer buffer)
- ;; Finding history file may take lots of time.
- (message "Reading history file...")
- (set-buffer (find-file-noselect nnspool-history-file))
- (message "Reading history file... done")))
- ;; Search from end of the file. I think this is much faster than
- ;; do from the beginning of the file.
- (goto-char (point-max))
- (if (re-search-backward
- (concat "^" (regexp-quote id)
- "[ \t].*[ \t]\\([^ \t/]+\\)/\\([0-9]+\\)[ \t]*$") nil t)
- (let ((group (buffer-substring (match-beginning 1) (match-end 1)))
- (number (buffer-substring (match-beginning 2) (match-end 2))))
- (concat (nnspool-article-pathname
- (nnspool-replace-chars-in-string group ?. ?/))
- number))
- )))
-
-(defun nnspool-find-file (file)
- "Insert FILE in server buffer safely."
- (set-buffer nntp-server-buffer)
- (erase-buffer)
- (condition-case ()
- (progn (insert-file-contents file) t)
- (file-error nil)
- ))
-
-(defun nnspool-article-pathname (group)
- "Make pathname for GROUP."
- (concat (file-name-as-directory nnspool-spool-directory) group "/"))
-
-(defun nnspool-replace-chars-in-string (string from to)
- "Replace characters in STRING from FROM to TO."
- (let ((string (substring string 0)) ;Copy string.
- (len (length string))
- (idx 0))
- ;; Replace all occurence of FROM with TO.
- (while (< idx len)
- (if (= (aref string idx) from)
- (aset string idx to))
- (setq idx (1+ idx)))
- string
- ))
diff --git a/lisp/nntp.el b/lisp/nntp.el
deleted file mode 100644
index 6bb7a741076..00000000000
--- a/lisp/nntp.el
+++ /dev/null
@@ -1,667 +0,0 @@
-;;; NNTP (RFC977) Interface for GNU Emacs
-;; Copyright (C) 1987, 1988, 1989 Fujitsu Laboratories LTD.
-;; Copyright (C) 1987, 1988, 1989, 1990 Masanobu UMEDA
-;; $Header: nntp.el,v 3.10 90/03/23 13:25:27 umerin Locked $
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY. No author or distributor
-;; accepts responsibility to anyone for the consequences of using it
-;; or for whether it serves any particular purpose or works at all,
-;; unless he says so in writing. Refer to the GNU Emacs General Public
-;; License for full details.
-
-;; Everyone is granted permission to copy, modify and redistribute
-;; GNU Emacs, but only under the conditions described in the
-;; GNU Emacs General Public License. A copy of this license is
-;; supposed to have been given to you along with GNU Emacs so you
-;; can know your rights and responsibilities. It should be in a
-;; file named COPYING. Among other things, the copyright notice
-;; and this notice must be preserved on all copies.
-
-;; This implementation is tested on both 1.2a and 1.5 version of the
-;; NNTP package.
-
-;; Troubleshooting of NNTP
-;;
-;; (1) Select routine may signal an error or fall into infinite loop
-;; while waiting for the server response. In this case, you'd better
-;; not use byte-compiled codes but original source. If you still have
-;; a problems with it, set the variable `nntp-buggy-select' to T.
-;;
-;; (2) Emacs may hang up while retrieving headers since too many
-;; requests have been sent to the NNTP server without reading their
-;; replies. In this case, reduce the number of the requests sent to
-;; the server at one time by setting the variable
-;; `nntp-maximum-request' to a lower value.
-;;
-;; (3) If the TCP/IP stream (open-network-stream) is not supported by
-;; emacs, compile and install `tcp.el' and `tcp.c' which is an
-;; emulation program of the stream. If you modified `tcp.c' for your
-;; system, please send me the diffs. I'll include some of them in the
-;; future releases.
-
-(provide 'nntp)
-
-(defvar nntp-server-hook nil
- "*Hooks for the NNTP server.
-If the kanji code of the NNTP server is different from the local kanji
-code, the correct kanji code of the buffer associated with the NNTP
-server must be specified as follows:
-
-(setq nntp-server-hook
- '(lambda ()
- ;; Server's Kanji code is EUC (NEmacs hack).
- (make-local-variable 'kanji-fileio-code)
- (setq kanji-fileio-code 0)))
-
-If you'd like to change something depending on the server in this
-hook, use the variable `nntp-server-name'.")
-
-(defvar nntp-buggy-select (memq system-type '(usg-unix-v fujitsu-uts))
- "*T if your select routine is buggy.
-If the select routine signals error or fall into infinite loop while
-waiting for the server response, the variable must be set to t. In
-case of Fujitsu UTS, it is set to T since `accept-process-output'
-doesn't work properly.")
-
-(defvar nntp-maximum-request 400
- "*The maximum number of the requests sent to the NNTP server at one time.
-If Emacs hangs up while retrieving headers, set the variable to a
-lower value.")
-
-(defvar nntp-large-newsgroup 50
- "*The number of the articles which indicates a large newsgroup.
-If the number of the articles is greater than the value, verbose
-messages will be shown to indicate the current status.")
-
-
-(defconst nntp-version "NNTP 3.10"
- "Version numbers of this version of NNTP.")
-
-(defvar nntp-server-name nil
- "The name of the host running NNTP server.")
-
-(defvar nntp-server-buffer nil
- "Buffer associated with NNTP server process.")
-
-(defvar nntp-server-process nil
- "The NNTP server process.
-You'd better not use this variable in NNTP front-end program but
-instead use `nntp-server-buffer'.")
-
-(defvar nntp-status-message-string nil
- "Save the server response message.
-You'd better not use this variable in NNTP front-end program but
-instead call function `nntp-status-message' to get status message.")
-
-;;;
-;;; Extended Command for retrieving many headers.
-;;;
-;; Retrieving lots of headers by sending command asynchronously.
-;; Access functions to headers are defined as macro.
-
-(defmacro nntp-header-number (header)
- "Return article number in HEADER."
- (` (aref (, header) 0)))
-
-(defmacro nntp-set-header-number (header number)
- "Set article number of HEADER to NUMBER."
- (` (aset (, header) 0 (, number))))
-
-(defmacro nntp-header-subject (header)
- "Return subject string in HEADER."
- (` (aref (, header) 1)))
-
-(defmacro nntp-set-header-subject (header subject)
- "Set article subject of HEADER to SUBJECT."
- (` (aset (, header) 1 (, subject))))
-
-(defmacro nntp-header-from (header)
- "Return author string in HEADER."
- (` (aref (, header) 2)))
-
-(defmacro nntp-set-header-from (header from)
- "Set article author of HEADER to FROM."
- (` (aset (, header) 2 (, from))))
-
-(defmacro nntp-header-xref (header)
- "Return xref string in HEADER."
- (` (aref (, header) 3)))
-
-(defmacro nntp-set-header-xref (header xref)
- "Set article xref of HEADER to xref."
- (` (aset (, header) 3 (, xref))))
-
-(defmacro nntp-header-lines (header)
- "Return lines in HEADER."
- (` (aref (, header) 4)))
-
-(defmacro nntp-set-header-lines (header lines)
- "Set article lines of HEADER to LINES."
- (` (aset (, header) 4 (, lines))))
-
-(defmacro nntp-header-date (header)
- "Return date in HEADER."
- (` (aref (, header) 5)))
-
-(defmacro nntp-set-header-date (header date)
- "Set article date of HEADER to DATE."
- (` (aset (, header) 5 (, date))))
-
-(defmacro nntp-header-id (header)
- "Return Id in HEADER."
- (` (aref (, header) 6)))
-
-(defmacro nntp-set-header-id (header id)
- "Set article Id of HEADER to ID."
- (` (aset (, header) 6 (, id))))
-
-(defmacro nntp-header-references (header)
- "Return references in HEADER."
- (` (aref (, header) 7)))
-
-(defmacro nntp-set-header-references (header ref)
- "Set article references of HEADER to REF."
- (` (aset (, header) 7 (, ref))))
-
-(defun nntp-retrieve-headers (sequence)
- "Return list of article headers specified by SEQUENCE of article id.
-The format of list is
- `([NUMBER SUBJECT FROM XREF LINES DATE MESSAGE-ID REFERENCES] ...)'.
-Reader macros for the vector are defined as `nntp-header-FIELD'.
-Writer macros for the vector are defined as `nntp-set-header-FIELD'.
-News group must be selected before calling me."
- (save-excursion
- (set-buffer nntp-server-buffer)
- (erase-buffer)
- (let ((number (length sequence))
- (last-point (point-min))
- (received 0)
- (count 0)
- (headers nil) ;Result list.
- (article 0)
- (subject nil)
- (message-id)
- (from nil)
- (xref nil)
- (lines 0)
- (date nil)
- (references nil))
- ;; Send HEAD command.
- (while sequence
- (nntp-send-strings-to-server "HEAD" (car sequence))
- (setq sequence (cdr sequence))
- (setq count (1+ count))
- ;; Every 400 header requests we have to read stream in order
- ;; to avoid deadlock.
- (if (or (null sequence) ;All requests have been sent.
- (zerop (% count nntp-maximum-request)))
- (progn
- (accept-process-output)
- (while (progn
- (goto-char last-point)
- ;; Count replies.
- (while (re-search-forward "^[0-9]" nil t)
- (setq received (1+ received)))
- (setq last-point (point))
- (< received count))
- ;; If number of headers is greater than 100, give
- ;; informative messages.
- (and (numberp nntp-large-newsgroup)
- (> number nntp-large-newsgroup)
- (zerop (% received 20))
- (message "NNTP: %d%% of headers received."
- (/ (* received 100) number)))
- (nntp-accept-response))
- ))
- )
- ;; Wait for text of last command.
- (goto-char (point-max))
- (re-search-backward "^[0-9]" nil t)
- (if (looking-at "^[23]")
- (while (progn
- (goto-char (- (point-max) 3))
- (not (looking-at "^\\.\r$")))
- (nntp-accept-response)))
- (and (numberp nntp-large-newsgroup)
- (> number nntp-large-newsgroup)
- (message "NNTP: 100%% of headers received."))
- ;; Now all of replies are received.
- (setq received number)
- ;; First, fold continuation lines.
- (goto-char (point-min))
- (while (re-search-forward "\\(\r?\n[ \t]+\\)+" nil t)
- (replace-match " " t t))
- ;;(delete-non-matching-lines
- ;; "^Subject:\\|^Xref:\\|^From:\\|^Lines:\\|^Date:\\|^References:\\|^[23]")
- (and (numberp nntp-large-newsgroup)
- (> number nntp-large-newsgroup)
- (message "NNTP: Parsing headers..."))
- ;; Then examines replies.
- (goto-char (point-min))
- (while (not (eobp))
- (cond ((looking-at "^[23][0-9][0-9][ \t]+\\([0-9]+\\)[ \t]+\\(<[^>]+>\\)")
- (setq article
- (string-to-int
- (buffer-substring (match-beginning 1) (match-end 1))))
- (setq message-id
- (buffer-substring (match-beginning 2) (match-end 2)))
- (forward-line 1)
- ;; Set default value.
- (setq subject nil)
- (setq xref nil)
- (setq from nil)
- (setq lines 0)
- (setq date nil)
- (setq references nil)
- ;; Thanks go to mly@AI.MIT.EDU (Richard Mlynarik)
- (while (and (not (eobp))
- (not (memq (following-char) '(?2 ?3))))
- (if (looking-at "\\(From\\|Subject\\|Date\\|Lines\\|Xref\\|References\\):[ \t]+\\([^ \t\n]+.*\\)\r$")
- (let ((s (buffer-substring
- (match-beginning 2) (match-end 2)))
- (c (char-after (match-beginning 0))))
- ;; We don't have to worry about letter case.
- (cond ((char-equal c ?F) ;From:
- (setq from s))
- ((char-equal c ?S) ;Subject:
- (setq subject s))
- ((char-equal c ?D) ;Date:
- (setq date s))
- ((char-equal c ?L) ;Lines:
- (setq lines (string-to-int s)))
- ((char-equal c ?X) ;Xref:
- (setq xref s))
- ((char-equal c ?R) ;References:
- (setq references s))
- )))
- (forward-line 1))
- ;; Finished to parse one header.
- (if (null subject)
- (setq subject "(None)"))
- (if (null from)
- (setq from "(Unknown User)"))
- (setq headers
- (cons (vector article subject from
- xref lines date
- message-id references) headers))
- )
- (t (forward-line 1))
- )
- (setq received (1- received))
- (and (numberp nntp-large-newsgroup)
- (> number nntp-large-newsgroup)
- (zerop (% received 20))
- (message "NNTP: Parsing headers... %d%%"
- (/ (* received 100) number)))
- )
- (and (numberp nntp-large-newsgroup)
- (> number nntp-large-newsgroup)
- (message "NNTP: Parsing headers... done"))
- (nreverse headers)
- )))
-
-
-;;;
-;;; Raw Interface to Network News Transfer Protocol (RFC977).
-;;;
-
-(defun nntp-open-server (host &optional service)
- "Open news server on HOST.
-If HOST is nil, use value of environment variable `NNTPSERVER'.
-If optional argument SERVICE is non-nil, open by the service name."
- (let ((host (or host (getenv "NNTPSERVER")))
- (status nil))
- (setq nntp-status-message-string "")
- (cond ((and host (nntp-open-server-internal host service))
- (setq status (nntp-wait-for-response "^[23].*\r$"))
- ;; Do check unexpected close of connection.
- ;; Suggested by feldmark@hanako.stars.flab.fujitsu.junet.
- (if status
- (set-process-sentinel nntp-server-process
- 'nntp-default-sentinel)
- ;; We have to close connection here, since function
- ;; `nntp-server-opened' may return incorrect status.
- (nntp-close-server-internal)
- ))
- ((null host)
- (setq nntp-status-message-string "NNTP server is not specified."))
- )
- status
- ))
-
-(defun nntp-close-server ()
- "Close news server."
- (unwind-protect
- (progn
- ;; Un-set default sentinel function before closing connection.
- (and nntp-server-process
- (eq 'nntp-default-sentinel
- (process-sentinel nntp-server-process))
- (set-process-sentinel nntp-server-process nil))
- ;; We cannot send QUIT command unless the process is running.
- (if (nntp-server-opened)
- (nntp-send-command nil "QUIT"))
- )
- (nntp-close-server-internal)
- ))
-
-(fset 'nntp-request-quit (symbol-function 'nntp-close-server))
-
-(defun nntp-server-opened ()
- "Return server process status, T or NIL.
-If the stream is opened, return T, otherwise return NIL."
- (and nntp-server-process
- (memq (process-status nntp-server-process) '(open run))))
-
-(defun nntp-status-message ()
- "Return server status response as string."
- (if (and nntp-status-message-string
- ;; NNN MESSAGE
- (string-match "[0-9][0-9][0-9][ \t]+\\([^\r]*\\).*$"
- nntp-status-message-string))
- (substring nntp-status-message-string (match-beginning 1) (match-end 1))
- ;; Empty message if nothing.
- ""
- ))
-
-(defun nntp-request-article (id)
- "Select article by message ID (or number)."
- (prog1
- ;; If NEmacs, end of message may look like: "\256\215" (".^M")
- (nntp-send-command "^\\.\r$" "ARTICLE" id)
- (nntp-decode-text)
- ))
-
-(defun nntp-request-body (id)
- "Select article body by message ID (or number)."
- (prog1
- ;; If NEmacs, end of message may look like: "\256\215" (".^M")
- (nntp-send-command "^\\.\r$" "BODY" id)
- (nntp-decode-text)
- ))
-
-(defun nntp-request-head (id)
- "Select article head by message ID (or number)."
- (prog1
- (nntp-send-command "^\\.\r$" "HEAD" id)
- (nntp-decode-text)
- ))
-
-(defun nntp-request-stat (id)
- "Select article by message ID (or number)."
- (nntp-send-command "^[23].*\r$" "STAT" id))
-
-(defun nntp-request-group (group)
- "Select news GROUP."
- ;; 1.2a NNTP's group command is buggy. "^M" (\r) is not appended to
- ;; end of the status message.
- (nntp-send-command "^[23].*$" "GROUP" group))
-
-(defun nntp-request-list ()
- "List valid newsgoups."
- (prog1
- (nntp-send-command "^\\.\r$" "LIST")
- (nntp-decode-text)
- ))
-
-(defun nntp-request-last ()
- "Set current article pointer to the previous article in the current news group."
- (nntp-send-command "^[23].*\r$" "LAST"))
-
-(defun nntp-request-next ()
- "Advance current article pointer."
- (nntp-send-command "^[23].*\r$" "NEXT"))
-
-(defun nntp-request-post ()
- "Post a new news in current buffer."
- (if (nntp-send-command "^[23].*\r$" "POST")
- (progn
- (nntp-encode-text)
- (nntp-send-region-to-server (point-min) (point-max))
- ;; 1.2a NNTP's post command is buggy. "^M" (\r) is not
- ;; appended to end of the status message.
- (nntp-wait-for-response "^[23].*$")
- )))
-
-(defun nntp-default-sentinel (proc status)
- "Default sentinel function for NNTP server process."
- (if (and nntp-server-process
- (not (nntp-server-opened)))
- (error "NNTP: Connection closed.")
- ))
-
-;; Encoding and decoding of NNTP text.
-
-(defun nntp-decode-text ()
- "Decode text transmitted by NNTP.
-0. Delete status line.
-1. Delete `^M' at end of line.
-2. Delete `.' at end of buffer (end of text mark).
-3. Delete `.' at beginning of line."
- (save-excursion
- (set-buffer nntp-server-buffer)
- ;; Insert newline at end of buffer.
- (goto-char (point-max))
- (if (not (bolp))
- (insert "\n"))
- ;; Delete status line.
- (goto-char (point-min))
- (delete-region (point) (progn (forward-line 1) (point)))
- ;; Delete `^M' at end of line.
- ;; (replace-regexp "\r$" "")
- (while (not (eobp))
- (end-of-line)
- (if (= (preceding-char) ?\r)
- (delete-char -1))
- (forward-line 1)
- )
- ;; Delete `.' at end of buffer (end of text mark).
- (goto-char (point-max))
- (forward-line -1) ;(beginning-of-line)
- (if (looking-at "^\\.$")
- (delete-region (point) (progn (forward-line 1) (point))))
- ;; Replace `..' at beginning of line with `.'.
- (goto-char (point-min))
- ;; (replace-regexp "^\\.\\." ".")
- (while (search-forward "\n.." nil t)
- (delete-char -1))
- ))
-
-(defun nntp-encode-text ()
- "Encode text in current buffer for NNTP transmission.
-1. Insert `.' at beginning of line.
-2. Insert `.' at end of buffer (end of text mark)."
- (save-excursion
- ;; Insert newline at end of buffer.
- (goto-char (point-max))
- (if (not (bolp))
- (insert "\n"))
- ;; Replace `.' at beginning of line with `..'.
- (goto-char (point-min))
- ;; (replace-regexp "^\\." "..")
- (while (search-forward "\n." nil t)
- (insert "."))
- ;; Insert `.' at end of buffer (end of text mark).
- (goto-char (point-max))
- (insert ".\n")
- ))
-
-
-;;;
-;;; Synchronous Communication with NNTP Server.
-;;;
-
-(defun nntp-send-command (response cmd &rest args)
- "Wait for server RESPONSE after sending CMD and optional ARGS to server."
- (save-excursion
- ;; Clear communication buffer.
- (set-buffer nntp-server-buffer)
- (erase-buffer)
- (apply 'nntp-send-strings-to-server cmd args)
- (if response
- (nntp-wait-for-response response)
- t)
- ))
-
-(defun nntp-wait-for-response (regexp)
- "Wait for server response which matches REGEXP."
- (save-excursion
- (let ((status t)
- (wait t))
- (set-buffer nntp-server-buffer)
- ;; Wait for status response (RFC977).
- ;; 1xx - Informative message.
- ;; 2xx - Command ok.
- ;; 3xx - Command ok so far, send the rest of it.
- ;; 4xx - Command was correct, but couldn't be performed for some
- ;; reason.
- ;; 5xx - Command unimplemented, or incorrect, or a serious
- ;; program error occurred.
- (nntp-accept-response)
- (while wait
- (goto-char (point-min))
- (cond ((looking-at "[23]")
- (setq wait nil))
- ((looking-at "[45]")
- (setq status nil)
- (setq wait nil))
- (t (nntp-accept-response))
- ))
- ;; Save status message.
- (end-of-line)
- (setq nntp-status-message-string
- (buffer-substring (point-min) (point)))
- (if status
- (progn
- (setq wait t)
- (while wait
- (goto-char (point-max))
- (forward-line -1) ;(beginning-of-line)
- ;;(message (buffer-substring
- ;; (point)
- ;; (save-excursion (end-of-line) (point))))
- (if (looking-at regexp)
- (setq wait nil)
- (message "NNTP: Reading...")
- (nntp-accept-response)
- (message "")
- ))
- ;; Successfully received server response.
- t
- ))
- )))
-
-
-;;;
-;;; Low-Level Interface to NNTP Server.
-;;;
-
-(defun nntp-send-strings-to-server (&rest strings)
- "Send list of STRINGS to news server as command and its arguments."
- (let ((cmd (car strings))
- (strings (cdr strings)))
- ;; Command and each argument must be separeted by one or more spaces.
- (while strings
- (setq cmd (concat cmd " " (car strings)))
- (setq strings (cdr strings)))
- ;; Command line must be terminated by a CR-LF.
- (process-send-string nntp-server-process (concat cmd "\n"))
- ))
-
-(defun nntp-send-region-to-server (begin end)
- "Send current buffer region (from BEGIN to END) to news server."
- (save-excursion
- ;; We have to work in the buffer associated with NNTP server
- ;; process because of NEmacs hack.
- (copy-to-buffer nntp-server-buffer begin end)
- (set-buffer nntp-server-buffer)
- (setq begin (point-min))
- (setq end (point-max))
- ;; `process-send-region' does not work if text to be sent is very
- ;; large. I don't know maximum size of text sent correctly.
- (let ((last nil)
- (size 100)) ;Size of text sent at once.
- (save-restriction
- (narrow-to-region begin end)
- (goto-char begin)
- (while (not (eobp))
- ;;(setq last (min end (+ (point) size)))
- ;; NEmacs gets confused if character at `last' is Kanji.
- (setq last (save-excursion
- (goto-char (min end (+ (point) size)))
- (or (eobp) (forward-char 1)) ;Adjust point
- (point)))
- (process-send-region nntp-server-process (point) last)
- ;; I don't know whether the next codes solve the known
- ;; problem of communication error of GNU Emacs.
- (accept-process-output)
- ;;(sit-for 0)
- (goto-char last)
- )))
- ;; We cannot erase buffer, because reply may be received.
- (delete-region begin end)
- ))
-
-(defun nntp-open-server-internal (host &optional service)
- "Open connection to news server on HOST by SERVICE (default is nntp)."
- (save-excursion
- ;; Use TCP/IP stream emulation package if needed.
- (or (fboundp 'open-network-stream)
- (require 'tcp))
- ;; Initialize communication buffer.
- (setq nntp-server-buffer (get-buffer-create " *nntpd*"))
- (set-buffer nntp-server-buffer)
- (buffer-flush-undo (current-buffer))
- (erase-buffer)
- (kill-all-local-variables)
- (setq case-fold-search t) ;Should ignore case.
- (setq nntp-server-process
- (open-network-stream "nntpd" (current-buffer)
- host (or service "nntp")))
- (setq nntp-server-name host)
- ;; It is possible to change kanji-fileio-code in this hook.
- (run-hooks 'nntp-server-hook)
- ;; Return the server process.
- nntp-server-process
- ))
-
-(defun nntp-close-server-internal ()
- "Close connection to news server."
- (if nntp-server-process
- (delete-process nntp-server-process))
- (if nntp-server-buffer
- (kill-buffer nntp-server-buffer))
- (setq nntp-server-buffer nil)
- (setq nntp-server-process nil))
-
-(defun nntp-accept-response ()
- "Read response of server.
-It is well-known that the communication speed will be much improved by
-defining this function as macro."
- ;; To deal with server process exiting before
- ;; accept-process-output is called.
- ;; Suggested by Jason Venner <jason@violet.berkeley.edu>.
- ;; This is a copy of `nntp-default-sentinel'.
- (or (memq (process-status nntp-server-process) '(open run))
- (error "NNTP: Connection closed."))
- (if nntp-buggy-select
- (progn
- ;; We cannot use `accept-process-output'.
- ;; Fujitsu UTS requires messages during sleep-for. I don't know why.
- (message "NNTP: Reading...")
- (sleep-for 1)
- (message ""))
- (condition-case errorcode
- (accept-process-output nntp-server-process)
- (error
- (cond ((string-equal "select error: Invalid argument" (nth 1 errorcode))
- ;; Ignore select error.
- nil
- )
- (t
- (signal (car errorcode) (cdr errorcode))))
- ))
- ))
diff --git a/lisp/textmodes/nroff-mode.el b/lisp/nroff-mode.el
index 35bf4213615..16e1445080b 100644
--- a/lisp/textmodes/nroff-mode.el
+++ b/lisp/nroff-mode.el
@@ -23,7 +23,7 @@
"Abbrev table used while in nroff mode.")
(defvar nroff-mode-map nil
- "Major mode keymap for nroff mode.")
+ "Major mode keymap for nroff-mode buffers")
(if (not nroff-mode-map)
(progn
(setq nroff-mode-map (make-sparse-keymap))
@@ -37,8 +37,8 @@
(defun nroff-mode ()
"Major mode for editing text intended for nroff to format.
\\{nroff-mode-map}
-Turning on Nroff mode runs `text-mode-hook', then `nroff-mode-hook'.
-Also, try `nroff-electric-mode', for automatically inserting
+Turning on Nroff mode runs text-mode-hook, then nroff-mode-hook.
+Also, try nroff-electric-mode, for automatically inserting
closing requests for requests that are used in matched pairs."
(interactive)
(kill-all-local-variables)
@@ -165,7 +165,7 @@ An argument is a repeat count; negative means move forward."
(defun electric-nroff-newline (arg)
"Insert newline for nroff mode; special if electric-nroff mode.
-In `electric-nroff-mode', if ending a line containing an nroff opening request,
+In electric-nroff-mode, if ending a line containing an nroff opening request,
automatically inserts the matching closing request after point."
(interactive "P")
(let ((completion (save-excursion
@@ -185,11 +185,12 @@ automatically inserts the matching closing request after point."
(forward-char 1))))
(defun electric-nroff-mode (&optional arg)
- "Toggle `nroff-electric-newline' minor mode.
-`nroff-electric-newline' forces Emacs to check for an nroff request at the
-beginning of the line, and insert the matching closing request if necessary.
-This command toggles that mode (off->on, on->off), with an argument,
-turns it on iff arg is positive, otherwise off."
+ "Toggle nroff-electric-newline minor mode
+Nroff-electric-newline forces emacs to check for an nroff
+request at the beginning of the line, and insert the
+matching closing request if necessary.
+This command toggles that mode (off->on, on->off),
+with an argument, turns it on iff arg is positive, otherwise off."
(interactive "P")
(or (eq major-mode 'nroff-mode) (error "Must be in nroff mode"))
(or (assq 'nroff-electric-mode minor-mode-alist)
diff --git a/lisp/nroff-mode.elc b/lisp/nroff-mode.elc
new file mode 100644
index 00000000000..7f76aeec9c2
--- /dev/null
+++ b/lisp/nroff-mode.elc
Binary files differ
diff --git a/lisp/options.el b/lisp/options.el
index e67346cab63..59d89c84bf3 100644
--- a/lisp/options.el
+++ b/lisp/options.el
@@ -67,17 +67,14 @@ Type \\[describe-mode] in that buffer for a list of commands."
(put 'Edit-options-mode 'mode-class 'special)
(defun Edit-options-mode ()
- "\\<Edit-options-mode-map>\
-Major mode for editing Emacs user option settings.
+ "Major mode for editing Emacs user option settings.
Special commands are:
-\\[Edit-options-set] -- set variable point points at. New value read using minibuffer.
-\\[Edit-options-toggle] -- toggle variable, t -> nil, nil -> t.
-\\[Edit-options-t] -- set variable to t.
-\\[Edit-options-nil] -- set variable to nil.
-Changed values made by these commands take effect immediately.
-
+s -- set variable point points at. New value read using minibuffer.
+x -- toggle variable, t -> nil, nil -> t.
+1 -- set variable to t.
+0 -- set variable to nil.
Each variable description is a paragraph.
-For convenience, the characters \\[backward-paragraph] and \\[forward-paragraph] move back and forward by paragraphs."
+For convenience, the characters p and n move back and forward by paragraphs."
(kill-all-local-variables)
(set-syntax-table emacs-lisp-mode-syntax-table)
(use-local-map Edit-options-mode-map)
@@ -87,8 +84,7 @@ For convenience, the characters \\[backward-paragraph] and \\[forward-paragraph]
(setq paragraph-start "^\t")
(setq truncate-lines t)
(setq major-mode 'Edit-options-mode)
- (setq mode-name "Options")
- (run-hooks 'Edit-options-mode-hook))
+ (setq mode-name "Options"))
(defun Edit-options-set () (interactive)
(Edit-options-modify
@@ -106,18 +102,18 @@ For convenience, the characters \\[backward-paragraph] and \\[forward-paragraph]
(defun Edit-options-modify (modfun)
(save-excursion
(let (var pos)
- (re-search-backward "^;; \\|\\`")
+ (re-search-backward "^;; ")
(forward-char 3)
(setq pos (point))
(save-restriction
- (narrow-to-region pos (progn (end-of-line) (1- (point))))
- (goto-char pos)
- (setq var (read (current-buffer))))
+ (narrow-to-region pos (progn (end-of-line) (1- (point))))
+ (goto-char pos)
+ (setq var (read (current-buffer))))
(goto-char pos)
(forward-line 1)
(forward-char 1)
(save-excursion
- (set var (funcall modfun var)))
+ (set var (funcall modfun var)))
(kill-sexp 1)
(prin1 (symbol-value var) (current-buffer)))))
diff --git a/lisp/options.elc b/lisp/options.elc
new file mode 100644
index 00000000000..67659cf3bd7
--- /dev/null
+++ b/lisp/options.elc
Binary files differ
diff --git a/lisp/textmodes/ooutline.el b/lisp/outline.el
index c56a3eb10c6..974895a38cb 100644
--- a/lisp/textmodes/ooutline.el
+++ b/lisp/outline.el
@@ -20,23 +20,16 @@
;; Jan '86, Some new features added by Peter Desnoyers and rewritten by RMS.
(defvar outline-regexp "[*\^l]+"
- "*Regular expression to match the beginning of a heading.
-Any line whose beginning matches this regexp is considered to start a heading.
+ "*Regular expression to match the beginning of a heading line.
+Any line whose beginning matches this regexp is considered a heading.
The recommended way to set this is with a Local Variables: list
-in the file it applies to. See also outline-heading-end-regexp.")
-
-(defvar outline-heading-end-regexp "[\n^M]"
- "*Regular expression to match the end of a heading line.
-You can assume that point is at the beginning of a heading when this
-regexp is searched for. The heading ends at the end of the match.
-The recommended way to set this is with a \"Local Variables:\" list
in the file it applies to.")
(defvar outline-mode-map nil "")
(if outline-mode-map
nil
- (setq outline-mode-map (nconc (make-sparse-keymap) text-mode-map))
+ (setq outline-mode-map (copy-keymap text-mode-map))
(define-key outline-mode-map "\C-c\C-n" 'outline-next-visible-heading)
(define-key outline-mode-map "\C-c\C-p" 'outline-previous-visible-heading)
(define-key outline-mode-map "\C-c\C-i" 'show-children)
@@ -46,11 +39,6 @@ in the file it applies to.")
(define-key outline-mode-map "\C-c\C-f" 'outline-forward-same-level)
(define-key outline-mode-map "\C-c\C-b" 'outline-backward-same-level))
-(defvar outline-minor-mode nil
- "Non-nil if using Outline mode as a minor mode of some other mode.")
-(setq minor-mode-alist (append minor-mode-alist
- (list '(outline-minor-mode " Outl"))))
-
(defun outline-mode ()
"Set major mode for editing outlines with selective display.
Headings are lines which start with asterisks: one for major headings,
@@ -61,21 +49,21 @@ invisible, or visible again. Invisible lines are attached to the end
of the heading, so they move with it, if the line is killed and yanked
back. A heading with text hidden under it is marked with an ellipsis (...).
-Commands:\\<outline-mode-map>
-\\[outline-next-visible-heading] outline-next-visible-heading move by visible headings
-\\[outline-previous-visible-heading] outline-previous-visible-heading
-\\[outline-forward-same-level] outline-forward-same-level similar but skip subheadings
-\\[outline-backward-same-level] outline-backward-same-level
-\\[outline-up-heading] outline-up-heading move from subheading to heading
+Commands:
+C-c C-n outline-next-visible-heading move by visible headings
+C-c C-p outline-previous-visible-heading
+C-c C-f outline-forward-same-level similar but skip subheadings
+C-c C-b outline-backward-same-level
+C-c C-u outline-up-heading move from subheading to heading
-M-x hide-body make all text invisible (not headings).
-M-x show-all make everything in buffer visible.
+Meta-x hide-body make all text invisible (not headings).
+Meta-x show-all make everything in buffer visible.
The remaining commands are used when point is on a heading line.
They apply to some of the body or subheadings of that heading.
-\\[hide-subtree] hide-subtree make body and subheadings invisible.
-\\[show-subtree] show-subtree make body and subheadings visible.
-\\[show-children] show-children make direct subheadings visible.
+C-c C-h hide-subtree make body and subheadings invisible.
+C-c C-s show-subtree make body and subheadings visible.
+C-c C-i show-children make direct subheadings visible.
No effect on body, or subheadings 2 or more levels down.
With arg N, affects subheadings N levels down.
M-x hide-entry make immediately following body invisible.
@@ -84,12 +72,12 @@ M-x hide-leaves make body under heading and under its subheadings invisible.
The subheadings remain visible.
M-x show-branches make all subheadings at all levels visible.
-The variable `outline-regexp' can be changed to control what is a heading.
-A line is a heading if `outline-regexp' matches something at the
+The variable outline-regexp can be changed to control what is a heading.
+A line is a heading if outline-regexp matches something at the
beginning of the line. The longer the match, the deeper the level.
-Turning on outline mode calls the value of `text-mode-hook' and then of
-`outline-mode-hook', if they are non-nil."
+Turning on outline mode calls the value of text-mode-hook and then of
+outline-mode-hook, if they are non-nil."
(interactive)
(kill-all-local-variables)
(setq selective-display t)
@@ -102,44 +90,18 @@ Turning on outline mode calls the value of `text-mode-hook' and then of
(make-local-variable 'paragraph-start)
(setq paragraph-start (concat paragraph-start "\\|^\\("
outline-regexp "\\)"))
- ;; Inhibit auto-filling of header lines.
- (make-local-variable 'auto-fill-inhibit-regexp)
- (setq auto-fill-inhibit-regexp outline-regexp)
(make-local-variable 'paragraph-separate)
(setq paragraph-separate (concat paragraph-separate "\\|^\\("
outline-regexp "\\)"))
(run-hooks 'text-mode-hook 'outline-mode-hook))
-
-(defun outline-minor-mode (arg)
- (interactive "P")
- (setq outline-minor-mode
- (if (null arg) (not outline-minor-mode)
- (> (prefix-numeric-value arg) 0)))
- (if outline-minor-mode
- (progn
- (setq selective-display t)
- (make-local-variable 'outline-old-map)
- (setq outline-old-map (current-local-map))
- (let ((new-map (copy-keymap outline-old-map)))
- (define-key new-map "\C-c"
- (lookup-key outline-mode-map "\C-c"))
- (use-local-map new-map))
- (make-local-variable 'outline-regexp)
- (setq outline-regexp "[ \t]*/\\*")
- (make-local-variable 'outline-heading-end-regexp)
- (setq outline-heading-end-regexp "\\*/[^\n\^M]*[\n\^M]")
- (run-hooks 'outline-minor-mode-hook))
- (progn
- (setq selective-display nil)
- (use-local-map outline-old-map))))
(defun outline-level ()
"Return the depth to which a statement is nested in the outline.
-Point must be at the beginning of a header line. This is actually
-the column number of the end of what `outline-regexp matches'."
+Point must be at the beginning of a header line.
+This is actually the length of whatever outline-regexp matches."
(save-excursion
(looking-at outline-regexp)
- (save-excursion (goto-char (match-end 0)) (current-column))))
+ (- (match-end 0) (match-beginning 0))))
(defun outline-next-preface ()
"Skip forward to just before the next heading line."
@@ -158,7 +120,7 @@ the column number of the end of what `outline-regexp matches'."
(defun outline-back-to-heading ()
"Move to previous (possibly invisible) heading line,
-or to the beginning of this line if it is a heading line."
+or to beginning of this line if it is a heading line."
(beginning-of-line)
(or (outline-on-heading-p)
(re-search-backward (concat "^\\(" outline-regexp "\\)") nil 'move)))
@@ -170,15 +132,10 @@ or to the beginning of this line if it is a heading line."
(and (eq (preceding-char) ?\n)
(looking-at outline-regexp))))
-(defun outline-end-of-heading ()
- (if (re-search-forward outline-heading-end-regexp nil 'move)
- (forward-char -1)))
-
(defun outline-next-visible-heading (arg)
"Move to the next visible heading line.
With argument, repeats or can move backward if negative.
-A heading line is one that starts with a `*' (or that
-`outline-regexp' matches)."
+A heading line is one that starts with a `*' (or that outline-regexp matches)."
(interactive "p")
(if (< arg 0)
(beginning-of-line)
@@ -189,8 +146,7 @@ A heading line is one that starts with a `*' (or that
(defun outline-previous-visible-heading (arg)
"Move to the previous heading line.
With argument, repeats or can move forward if negative.
-A heading line is one that starts with a `*' (or that
-`outline-regexp' matches)."
+A heading line is one that starts with a `*' (or that outline-regexp matches)."
(interactive "p")
(outline-next-visible-heading (- arg)))
@@ -202,14 +158,13 @@ while if FLAG is `\\^M' (control-M) the text is hidden."
(unwind-protect
(subst-char-in-region from to
(if (= flag ?\n) ?\^M ?\n)
- flag)
+ flag t)
(set-buffer-modified-p modp))))
(defun hide-entry ()
"Hide the body directly following this heading."
(interactive)
(outline-back-to-heading)
- (outline-end-of-heading)
(save-excursion
(outline-flag-region (point) (progn (outline-next-preface) (point)) ?\^M)))
@@ -230,17 +185,12 @@ while if FLAG is `\\^M' (control-M) the text is hidden."
(save-restriction
(narrow-to-region start end)
(goto-char (point-min))
- (if (outline-on-heading-p)
- (outline-end-of-heading))
(while (not (eobp))
- (outline-flag-region (point)
- (progn (outline-next-preface) (point)) ?\^M)
+ (outline-flag-region (point) (progn (outline-next-preface) (point)) ?\^M)
(if (not (eobp))
- (progn
- (forward-char
- (if (looking-at "[\n\^M][\n\^M]")
- 2 1))
- (outline-end-of-heading)))))))
+ (forward-char
+ (if (looking-at "[\n\^M][\n\^M]")
+ 2 1)))))))
(defun show-all ()
"Show all of the text in the buffer."
@@ -256,7 +206,6 @@ while if FLAG is `\\^M' (control-M) the text is hidden."
"Hide all body after this heading at deeper levels."
(interactive)
(outline-back-to-heading)
- (outline-end-of-heading)
(hide-region-body (point) (progn (outline-end-of-subtree) (point))))
(defun show-subtree ()
@@ -267,13 +216,12 @@ while if FLAG is `\\^M' (control-M) the text is hidden."
(defun outline-flag-subtree (flag)
(save-excursion
(outline-back-to-heading)
- (outline-end-of-heading)
(outline-flag-region (point)
(progn (outline-end-of-subtree) (point))
flag)))
(defun outline-end-of-subtree ()
- (outline-back-to-heading)
+ (beginning-of-line)
(let ((opoint (point))
(first t)
(level (outline-level)))
@@ -291,17 +239,10 @@ while if FLAG is `\\^M' (control-M) the text is hidden."
(show-children 1000))
(defun show-children (&optional level)
- "Show all direct subheadings of this heading.
-Prefix arg LEVEL is how many levels below the current level should be shown.
-Default is enough to cause the following heading to appear."
- (interactive "P")
- (setq level
- (if level (prefix-numeric-value level)
- (save-excursion
- (beginning-of-line)
- (let ((start-level (outline-level)))
- (outline-next-heading)
- (max 1 (- (outline-level) start-level))))))
+ "Show all direct subheadings of this heading. Optional LEVEL specifies
+how many levels below the current level should be shown."
+ (interactive "p")
+ (or level (setq level 1))
(save-excursion
(save-restriction
(beginning-of-line)
@@ -315,13 +256,11 @@ Default is enough to cause the following heading to appear."
(not (eobp))))
(if (<= (outline-level) level)
(save-excursion
- (outline-flag-region (save-excursion
- (forward-char -1)
- (if (memq (preceding-char) '(?\n ?\^M))
- (forward-char -1))
- (point))
- (progn (outline-end-of-heading) (point))
- ?\n)))))))
+ (let ((end (1+ (point))))
+ (forward-char -1)
+ (if (memq (preceding-char) '(?\n ?\^M))
+ (forward-char -1))
+ (outline-flag-region (point) end ?\n))))))))
(defun outline-up-heading (arg)
"Move to the heading line of which the present line is a subheading.
diff --git a/lisp/outline.elc b/lisp/outline.elc
new file mode 100644
index 00000000000..64e9272d0ea
--- /dev/null
+++ b/lisp/outline.elc
Binary files differ
diff --git a/lisp/textmodes/page.el b/lisp/page.el
index 576e23a7560..19b29d02f08 100644
--- a/lisp/textmodes/page.el
+++ b/lisp/page.el
@@ -20,8 +20,7 @@
(defun forward-page (&optional count)
"Move forward to page boundary. With arg, repeat, or go back if negative.
-A page boundary is any line whose beginning matches the regexp
-`page-delimiter'."
+A page boundary is any line whose beginning matches the regexp page-delimiter."
(interactive "p")
(or count (setq count 1))
(while (and (> count 0) (not (eobp)))
@@ -38,8 +37,7 @@ A page boundary is any line whose beginning matches the regexp
(defun backward-page (&optional count)
"Move backward to page boundary. With arg, repeat, or go fwd if negative.
-A page boundary is any line whose beginning matches the regexp
-`page-delimiter'."
+A page boundary is any line whose beginning matches the regexp page-delimiter."
(interactive "p")
(or count (setq count 1))
(forward-page (- count)))
diff --git a/lisp/page.elc b/lisp/page.elc
new file mode 100644
index 00000000000..22867f35278
--- /dev/null
+++ b/lisp/page.elc
Binary files differ
diff --git a/lisp/textmodes/paragraphs.el b/lisp/paragraphs.el
index 748a08e986a..cb6c25955fe 100644
--- a/lisp/textmodes/paragraphs.el
+++ b/lisp/paragraphs.el
@@ -19,15 +19,13 @@
(defvar paragraph-ignore-fill-prefix nil
- "Non-nil means the paragraph commands are not affected by `fill-prefix'.
+ "Non-nil means the paragraph commands are not affected by fill-prefix.
This is desirable in modes where blank lines are the paragraph delimiters.")
(defun forward-paragraph (&optional arg)
- "Move forward to end of paragraph.
-With arg N, do it N times; negative arg -N means move forward 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.
+ "Move forward to end of paragraph. With arg, do it arg times.
+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."
(interactive "p")
@@ -86,40 +84,31 @@ to which the end of the previous line belongs, or the end of the buffer."
(setq arg (1- 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.
-
-A paragraph start is the beginning of a line which is a
-`first-line-of-paragraph' or which is ordinary text and follows a
-paragraph-separating line; except: if the first real line of a
-paragraph is preceded by a blank line, the paragraph starts at that
-blank line.
-
-See `forward-paragraph' for more information."
+ "Move backward to start of paragraph. With arg, do it arg times.
+A paragraph start is the beginning of a line which is a first-line-of-paragraph
+or which is ordinary text and follows a paragraph-separating line; except:
+if the first real line of a paragraph is preceded by a blank line,
+the paragraph starts at that blank line.
+See forward-paragraph for more information."
(interactive "p")
(or arg (setq arg 1))
(forward-paragraph (- arg)))
(defun mark-paragraph ()
- "Put point at beginning of this paragraph, mark at end.
-The paragraph marked is the one that contains point or follows point."
+ "Put point at beginning of this paragraph, mark at end."
(interactive)
(forward-paragraph 1)
(push-mark nil t)
(backward-paragraph 1))
(defun kill-paragraph (arg)
- "Kill forward to end of paragraph.
-With arg N, kill forward to Nth end of paragraph;
-negative arg -N means kill backward to Nth start of paragraph."
- (interactive "p")
+ "Kill to end of paragraph."
+ (interactive "*p")
(kill-region (point) (progn (forward-paragraph arg) (point))))
(defun backward-kill-paragraph (arg)
- "Kill back to start of paragraph.
-With arg N, kill back to Nth start of paragraph;
-negative arg -N means kill forward to Nth end of paragraph."
- (interactive "p")
+ "Kill back to start of paragraph."
+ (interactive "*p")
(kill-region (point) (progn (backward-paragraph arg) (point))))
(defun transpose-paragraphs (arg)
@@ -153,11 +142,11 @@ negative arg -N means kill forward to Nth end of paragraph."
(end-of-paragraph-text))))))
(defun forward-sentence (&optional arg)
- "Move forward to next`sentence-end'. With argument, repeat.
-With negative argument, move backward repeatedly to `sentence-beginning'.
-
-The variable `sentence-end' is a regular expression that matches ends of
-sentences. Also, every paragraph boundary terminates sentences as well."
+ "Move forward to next sentence-end. With argument, repeat.
+With negative argument, move backward repeatedly to sentence-beginning.
+Sentence ends are identified by the value of sentence-end
+treated as a regular expression. Also, every paragraph boundary
+terminates sentences as well."
(interactive "p")
(or arg (setq arg 1))
(while (< arg 0)
@@ -175,14 +164,14 @@ sentences. Also, every paragraph boundary terminates sentences as well."
(defun backward-sentence (&optional arg)
"Move backward to start of sentence. With arg, do it arg times.
-See `forward-sentence' for more information."
+See forward-sentence for more information."
(interactive "p")
(or arg (setq arg 1))
(forward-sentence (- arg)))
(defun kill-sentence (&optional arg)
"Kill from point to end of sentence.
-With arg, repeat; negative arg -N means kill back to Nth start of sentence."
+With arg, repeat, or backward if negative arg."
(interactive "*p")
(let ((beg (point)))
(forward-sentence arg)
@@ -190,14 +179,14 @@ With arg, repeat; negative arg -N means kill back to Nth start of sentence."
(defun backward-kill-sentence (&optional arg)
"Kill back from point to start of sentence.
-With arg, repeat, or kill forward to Nth end of sentence if negative arg -N."
+With arg, repeat, or forward if negative arg."
(interactive "*p")
(let ((beg (point)))
(backward-sentence arg)
(kill-region beg (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."
(interactive "p")
(push-mark
(save-excursion
diff --git a/lisp/paragraphs.elc b/lisp/paragraphs.elc
new file mode 100644
index 00000000000..ee1d8ded85c
--- /dev/null
+++ b/lisp/paragraphs.elc
Binary files differ
diff --git a/lisp/paths.el b/lisp/paths.el
index 66391e31898..2442bf0f2e8 100644
--- a/lisp/paths.el
+++ b/lisp/paths.el
@@ -24,14 +24,10 @@
;; If these settings are not right, override them with `setq'
;; in site-init.el. Do not change this file.
-(defvar Info-directory-list
- (list "/usr/local/lib/info/"
- (expand-file-name "../info/" exec-directory))
- "List of directories to search for Info documentation files.")
+(defvar Info-directory (expand-file-name "../info/" exec-directory))
(defvar news-path "/usr/spool/news/"
"The root directory below which all news files are stored.")
-
(defvar news-inews-program
(cond ((file-exists-p "/usr/bin/inews") "/usr/bin/inews")
((file-exists-p "/usr/local/inews") "/usr/local/inews")
@@ -40,50 +36,27 @@
(t "inews"))
"Program to post news.")
-(defvar gnus-default-nntp-server ""
- ;; set this to your local server
- "The name of the host running an NNTP server.
-If it is a string such as \":DIRECTORY\", then ~/DIRECTORY
-is used as a news spool. `gnus-nntp-server' is initialised from NNTPSERVER
-environment variable or, if none, this value.")
-
-(defvar gnus-nntp-service "nntp"
- "NNTP service name, usually \"nntp\" or 119).
-Go to a local news spool if its value is nil, in which case `gnus-nntp-server'
-should be set to `(system-name)'.")
-
-(defvar gnus-your-domain nil
- "Your domain name without your host name like: \"stars.flab.Fujitsu.CO.JP\"
-The DOMAINNAME environment variable is used instead if defined. If
-the function `system-name' returns a fully qualified domain name, there is no
-need to define the name.")
-
-(defvar gnus-your-organization ""
- "Your organization like: \"Fujitsu Laboratories Ltd., Kawasaki, Japan.\"
-The `ORGANIZATION' environment variable is used instead if defined.")
-
(defvar mh-progs
- (cond ((file-directory-p "/usr/new/mh") "/usr/new/mh/")
- ((file-directory-p "/usr/local/bin/mh") "/usr/local/bin/mh/")
- ((file-directory-p "/usr/local/mh/") "/usr/local/mh/")
- (t "/usr/local/bin/"))
- "Directory containing MH commands")
+ (cond ((file-directory-p "/usr/bin/mh/") "/usr/bin/mh/") ;Ultrix 4.2
+ ((file-directory-p "/usr/new/mh/") "/usr/new/mh/") ;Ultrix <4.2
+ ((file-directory-p "/usr/local/bin/mh/") "/usr/local/bin/mh/")
+ ((file-directory-p "/usr/local/mh/") "/usr/local/mh/")
+ (t "/usr/local/bin/"))
+ "Directory containing MH commands.")
(defvar mh-lib
- (cond ((file-directory-p "/usr/new/lib/mh") "/usr/new/lib/mh/")
- ((file-directory-p "/usr/local/lib/mh") "/usr/local/lib/mh/")
- (t "/usr/local/bin/mh/"))
- "Directory of MH library")
+ (cond ((file-directory-p "/usr/lib/mh/") "/usr/lib/mh/") ;Ultrix 4.2
+ ((file-directory-p "/usr/new/lib/mh/") "/usr/new/lib/mh/") ;Ultrix <4.2
+ ((file-directory-p "/usr/local/lib/mh/") "/usr/local/lib/mh/")
+ (t "/usr/local/bin/mh/"))
+ "Directory of MH library.")
-(defvar rmail-file-name "~/RMAIL"
+(defconst rmail-file-name "~/RMAIL"
"Name of user's primary mail file.")
-(defvar gnus-startup-file "~/.newsrc"
- "The file listing groups to which user is subscribed.
-Will use `gnus-startup-file'-SERVER instead if exists.")
-
(defconst rmail-spool-directory
- (if (memq system-type '(hpux usg-unix-v unisoft-unix rtu irix))
+ (if (memq system-type '(hpux usg-unix-v unisoft-unix rtu
+ silicon-graphics-unix))
"/usr/mail/"
"/usr/spool/mail/")
"Name of directory used by system mailer for delivering new mail.
@@ -131,18 +104,6 @@ Append a section-number or section-name to get a directory name.")
'("/usr/man/cat.C" "/usr/man/cat.CP" "/usr/man/cat.CT"
"/usr/man/cat.DOS/" "/usr/man/cat.F" "/usr/man/cat.HW"
"/usr/man/cat.M/" "/usr/man/cat.S" "/usr/man/cat.LOCAL"))
- ((file-exists-p "/usr/man/cat3/cat3")
- ;; This is for UMAX.
- '("/usr/man/cat1" "/usr/man/cat2"
- "/usr/man/cat3" "/usr/man/cat3/cat3"
- "/usr/man/cat3/cat3b" "/usr/man/cat3/cat3c"
- "/usr/man/cat3/cat3f" "/usr/man/cat3/cat3m"
- "/usr/man/cat3/cat3n" "/usr/man/cat3/cat3p"
- "/usr/man/cat3/cat3s" "/usr/man/cat3/cat3u"
- "/usr/man/cat3/cat3x" "/usr/man/cat4"
- "/usr/man/cat5" "/usr/man/cat6"
- "/usr/man/cat7" "/usr/man/cat8"
- "/usr/man/catl" "/usr/man/catn"))
((file-exists-p "/usr/man/cat1")
'("/usr/man/cat1" "/usr/man/cat2" "/usr/man/cat3"
"/usr/man/cat4" "/usr/man/cat5" "/usr/man/cat6"
@@ -152,12 +113,7 @@ Append a section-number or section-name to get a directory name.")
"/usr/catman/p_man/man2" "/usr/catman/p_man/man3"
"/usr/catman/p_man/man4" "/usr/catman/p_man/man5"
"/usr/catman/a_man/man1" "/usr/catman/a_man/man7"
- "/usr/catman/a_man/man8" "/usr/catman/local"
- "/usr/catman/a_man/man8" "/usr/catman/local/man1"
- "/usr/catman/local/man2" "/usr/catman/local/man3"
- "/usr/catman/local/man4" "/usr/catman/local/man5"
- "/usr/catman/local/man6" "/usr/catman/local/man7"
- "/usr/catman/local/man8")))
+ "/usr/catman/a_man/man8" "/usr/catman/local")))
"List of directories containing formatted manual pages.")
(defconst abbrev-file-name
diff --git a/lisp/textmodes/picture.el b/lisp/picture.el
index d6915c4b0ae..c0325003e73 100644
--- a/lisp/textmodes/picture.el
+++ b/lisp/picture.el
@@ -23,7 +23,7 @@
(defun move-to-column-force (column)
"Move to column COLUMN in current line.
-Differs from `move-to-column' in that it creates or modifies whitespace
+Differs from move-to-column in that it creates or modifies whitespace
if necessary to attain exactly the specified column."
(move-to-column column)
(let ((col (current-column)))
@@ -135,7 +135,7 @@ The mode line is updated to reflect the current direction."
(message ""))
(defun picture-move ()
- "Move in direction of `picture-vertical-step' and `picture-horizontal-step'."
+ "Move in direction of picture-vertical-step and picture-horizontal-step."
(picture-move-down picture-vertical-step)
(picture-forward-column picture-horizontal-step))
@@ -152,7 +152,7 @@ Do \\[command-apropos] picture-movement to see commands which control motion."
"Move point in direction opposite of current picture motion in Picture mode.
With ARG do it that many times. Useful for delineating rectangles in
conjunction with diagonal picture motion.
-Do \\[command-apropos] `picture-movement' to see commands which control motion."
+Do \\[command-apropos] picture-movement to see commands which control motion."
(interactive "p")
(picture-motion (- arg)))
@@ -162,8 +162,8 @@ Do \\[command-apropos] `picture-movement' to see commands which control motion."
(defun picture-self-insert (arg)
"Insert this character in place of character previously at the cursor.
The cursor then moves in the direction you previously specified
-with the commands `picture-movement-right', `picture-movement-up', etc.
-Do \\[command-apropos] `picture-movement' to see those commands."
+with the commands picture-movement-right, picture-movement-up, etc.
+Do \\[command-apropos] picture-movement to see those commands."
(interactive "p")
(while (> arg 0)
(setq arg (1- arg))
@@ -191,9 +191,9 @@ Do \\[command-apropos] `picture-movement' to see those commands."
(defun picture-clear-line (arg)
"Clear out rest of line; if at end of line, advance to next line.
-Cleared-out line text goes into the kill ring, as do newlines that are
-advanced over. With argument, clear out (and save in kill ring) that
-many lines."
+Cleared-out line text goes into the kill ring, as do
+newlines that are advanced over.
+With argument, clear out (and save in kill ring) that many lines."
(interactive "P")
(if arg
(progn
@@ -247,7 +247,7 @@ It defines a set of \"interesting characters\" to look for when setting
For example, suppose that you are editing a table which is formatted thus:
| foo | bar + baz | 23 *
| bubbles | and + etc | 97 *
-and that `picture-tab-chars' is \"|+*\". Then invoking
+and that picture-tab-chars is \"|+*\". Then invoking
\\[picture-set-tab-stops] on either of the previous lines would result
in the following tab stops
: : : :
@@ -264,13 +264,14 @@ The command \\[picture-tab-search] is defined to move beneath (or to) a
character belonging to this set independent of the tab stops list.")
(defun picture-set-tab-stops (&optional arg)
- "Set value of `tab-stop-list' according to context of this line.
-This controls the behavior of \\[picture-tab]. A tab stop is set at
-every column occupied by an \"interesting character\" that is preceded
-by whitespace. Interesting characters are defined by the variable
-`picture-tab-chars', see its documentation for an example of usage.
-With ARG, just (re)set `tab-stop-list' to its default value. The tab
-stops computed are displayed in the minibuffer with `:' at each stop."
+ "Set value of tab-stop-list according to context of this line.
+This controls the behavior of \\[picture-tab]. A tab stop
+is set at every column occupied by an \"interesting character\" that is
+preceded by whitespace. Interesting characters are defined by the
+variable picture-tab-chars, see its documentation for an example
+of usage. With ARG, just (re)set tab-stop-list to its default value.
+The tab stops computed are displayed in the minibuffer with `:' at
+each stop."
(interactive "P")
(save-excursion
(let (tabs)
@@ -297,7 +298,7 @@ stops computed are displayed in the minibuffer with `:' at each stop."
"Move to column beneath next interesting char in previous line.
With ARG move to column occupied by next interesting character in this
line. The character must be preceded by whitespace.
-\"interesting characters\" are defined by variable `picture-tab-chars'.
+\"interesting characters\" are defined by variable picture-tab-chars.
If no such character is found, move to beginning of line."
(interactive "P")
(let ((target (current-column)))
@@ -321,18 +322,20 @@ If no such character is found, move to beginning of line."
(beginning-of-line))))
(defun picture-tab (&optional arg)
- "Tab transparently (just move point) to next tab stop.
-With prefix arg, overwrite the traversed text with spaces. The tab stop
+ "Tab transparently (move) to next tab stop.
+With ARG overwrite the traversed text with spaces. The tab stop
list can be changed by \\[picture-set-tab-stops] and \\[edit-tab-stops].
-See also documentation for variable `picture-tab-chars'."
+See also documentation for variable picture-tab-chars."
(interactive "P")
- (let* ((opoint (point)))
- (move-to-tab-stop)
+ (let* ((opoint (point))
+ (target (prog2 (tab-to-tab-stop)
+ (current-column)
+ (delete-region opoint (point)))))
+ (move-to-column-force target)
(if arg
- (let (indent-tabs-mode
- (column (current-column)))
+ (let (indent-tabs-mode)
(delete-region opoint (point))
- (indent-to column)))))
+ (indent-to target)))))
;; Picture Rectangles
@@ -343,27 +346,40 @@ The contents can be retrieved by \\[picture-yank-rectangle]")
(defun picture-clear-rectangle (start end &optional killp)
"Clear and save rectangle delineated by point and mark.
The rectangle is saved for yanking by \\[picture-yank-rectangle] and replaced
-with whitespace. The previously saved rectangle, if any, is lost. With
-prefix argument, the rectangle is actually killed, shifting remaining text."
+with whitespace. The previously saved rectangle, if any, is lost.
+With prefix argument, the rectangle is actually killed, shifting remaining
+text."
(interactive "r\nP")
(setq picture-killed-rectangle (picture-snarf-rectangle start end killp)))
(defun picture-clear-rectangle-to-register (start end register &optional killp)
"Clear rectangle delineated by point and mark into REGISTER.
-The rectangle is saved in REGISTER and replaced with whitespace. With
-prefix argument, the rectangle is actually killed, shifting remaining text."
+The rectangle is saved in REGISTER and replaced with whitespace.
+With prefix argument, the rectangle is actually killed, shifting remaining
+text."
(interactive "r\ncRectangle to register: \nP")
(set-register register (picture-snarf-rectangle start end killp)))
(defun picture-snarf-rectangle (start end &optional killp)
(let ((column (current-column))
- (indent-tabs-mode nil))
+ (indent-tabs-mode nil)
+ markpos oldmark)
(prog1 (save-excursion
+ (save-excursion
+ (goto-char (setq oldmark (mark)))
+ (setq markpos (current-column)))
(if killp
(delete-extract-rectangle start end)
(prog1 (extract-rectangle start end)
- (clear-rectangle start end))))
- (move-to-column-force column))))
+ (clear-rectangle start end t))))
+ (move-to-column-force column)
+ ;; Make the mark point at the same column
+ ;; as it did before.
+ (set-marker (mark-marker)
+ (save-excursion
+ (goto-char oldmark)
+ (move-to-column-force markpos)
+ (point))))))
(defun picture-yank-rectangle (&optional insertp)
"Overlay rectangle saved by \\[picture-clear-rectangle]
@@ -526,7 +542,7 @@ they are not defaultly assigned to keys."
(make-local-variable 'picture-vertical-step)
(make-local-variable 'picture-horizontal-step)
(picture-set-motion 0 1)
- (run-hooks 'edit-picture-hook)
+ (run-hooks 'edit-picture-hook 'picture-mode-hook)
(message
(substitute-command-keys
"Type \\[picture-mode-exit] in this buffer to return it to %s mode.")
diff --git a/lisp/picture.elc b/lisp/picture.elc
new file mode 100644
index 00000000000..f8bfa4b8e2a
--- /dev/null
+++ b/lisp/picture.elc
Binary files differ
diff --git a/lisp/play/gomoku.el b/lisp/play/gomoku.el
deleted file mode 100644
index c40c108895f..00000000000
--- a/lisp/play/gomoku.el
+++ /dev/null
@@ -1,1161 +0,0 @@
-;; Gomoku game between you and Emacs
-;; Copyright (C) 1988 Free Software Foundation, Inc.
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 1, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
-;;; Gomoku game between you and GNU Emacs. Last modified on 13 Sep 1988
-;;;
-;;; Written by Ph. Schnoebelen (phs@lifia.imag.fr), 1987, 1988
-;;; with precious advices from J.-F. Rit.
-;;; This has been tested with GNU Emacs 18.50.
-
-(provide 'gomoku)
-
-
-;; RULES:
-;;
-;; Gomoku is a game played between two players on a rectangular board. Each
-;; player, in turn, marks a free square of its choice. The winner is the first
-;; one to mark five contiguous squares in any direction (horizontally,
-;; vertically or diagonally).
-;;
-;; I have been told that, in "The TRUE Gomoku", some restrictions are made
-;; about the squares where one may play, or else there is a known forced win
-;; for the first player. This program has no such restriction, but it does not
-;; know about the forced win, nor do I. Furthermore, you probably do not know
-;; it yourself :-).
-
-
-;; HOW TO INSTALL:
-;;
-;; There is nothing specific w.r.t. installation: just put this file in the
-;; lisp directory and add an autoload for command gomoku in site-init.el. If
-;; you don't want to rebuild Emacs, then every single user interested in
-;; Gomoku will have to put the autoload command in its .emacs file. Another
-;; possibility is to define in your .emacs some command using (require
-;; 'gomoku).
-;;
-;; The most important thing is to BYTE-COMPILE gomoku.el because it is
-;; important that the code be as fast as possible.
-;;
-;; There are two main places where you may want to customize the program: key
-;; bindings and board display. These features are commented in the code. Go
-;; and see.
-
-
-;; HOW TO USE:
-;;
-;; Once this file has been installed, the command "M-x gomoku" will display a
-;; board, the size of which depends on the size of the current window. The
-;; size of the board is easily modified by giving numeric arguments to the
-;; gomoku command and/or by customizing the displaying parameters.
-;;
-;; Emacs plays when it is its turn. When it is your turn, just put the cursor
-;; on the square where you want to play and hit RET, or X, or whatever key you
-;; bind to the command gomoku-human-plays. When it is your turn, Emacs is
-;; idle: you may switch buffers, read your mail, ... Just come back to the
-;; *Gomoku* buffer and resume play.
-
-
-;; ALGORITHM:
-;;
-;; The algorithm is briefly described in section "THE SCORE TABLE". Some
-;; parameters may be modified if you want to change the style exhibited by the
-;; program.
-
-;;;
-;;; GOMOKU MODE AND KEYMAP.
-;;;
-(defvar gomoku-mode-hook nil
- "If non-nil, its value is called on entry to Gomoku mode.")
-
-(defvar gomoku-mode-map nil
- "Local keymap to use in Gomoku mode.")
-
-(if gomoku-mode-map nil
- (setq gomoku-mode-map (make-sparse-keymap))
-
- ;; Key bindings for cursor motion. Arrow keys are just "function"
- ;; keys, see below.
- (define-key gomoku-mode-map "y" 'gomoku-move-nw) ; Y
- (define-key gomoku-mode-map "u" 'gomoku-move-ne) ; U
- (define-key gomoku-mode-map "b" 'gomoku-move-sw) ; B
- (define-key gomoku-mode-map "n" 'gomoku-move-se) ; N
- (define-key gomoku-mode-map "h" 'gomoku-move-left) ; H
- (define-key gomoku-mode-map "l" 'gomoku-move-right) ; L
- (define-key gomoku-mode-map "j" 'gomoku-move-down) ; J
- (define-key gomoku-mode-map "k" 'gomoku-move-up) ; K
- (define-key gomoku-mode-map "\C-n" 'gomoku-move-down) ; C-N
- (define-key gomoku-mode-map "\C-p" 'gomoku-move-up) ; C-P
- (define-key gomoku-mode-map "\C-f" 'gomoku-move-right) ; C-F
- (define-key gomoku-mode-map "\C-b" 'gomoku-move-left) ; C-B
-
- ;; Key bindings for entering Human moves.
- ;; If you have a mouse, you may also bind some mouse click ...
- (define-key gomoku-mode-map "X" 'gomoku-human-plays) ; X
- (define-key gomoku-mode-map "x" 'gomoku-human-plays) ; x
- (define-key gomoku-mode-map "\C-m" 'gomoku-human-plays) ; RET
- (define-key gomoku-mode-map "\C-cp" 'gomoku-human-plays) ; C-C P
- (define-key gomoku-mode-map "\C-cb" 'gomoku-human-takes-back) ; C-C B
- (define-key gomoku-mode-map "\C-cr" 'gomoku-human-resigns) ; C-C R
- (define-key gomoku-mode-map "\C-ce" 'gomoku-emacs-plays) ; C-C E
-
- ;; Key bindings for "function" keys. If your terminal has such
- ;; keys, make sure they are declared through the function-keymap
- ;; keymap (see file keypad.el).
- ;; One problem with keypad.el is that the function-key-sequence
- ;; function is really slow, so slow that you may want to comment out
- ;; the following lines ...
- (if (featurep 'keypad)
- (let (keys)
- (if (setq keys (function-key-sequence ?u)) ; Up Arrow
- (define-key gomoku-mode-map keys 'gomoku-move-up))
- (if (setq keys (function-key-sequence ?d)) ; Down Arrow
- (define-key gomoku-mode-map keys 'gomoku-move-down))
- (if (setq keys (function-key-sequence ?l)) ; Left Arrow
- (define-key gomoku-mode-map keys 'gomoku-move-left))
- (if (setq keys (function-key-sequence ?r)) ; Right Arrow
- (define-key gomoku-mode-map keys 'gomoku-move-right))
-;; (if (setq keys (function-key-sequence ?e)) ; Enter
-;; (define-key gomoku-mode-map keys 'gomoku-human-plays))
-;; (if (setq keys (function-key-sequence ?I)) ; Insert
-;; (define-key gomoku-mode-map keys 'gomoku-human-plays))
- )))
-
-
-
-(defun gomoku-mode ()
- "Major mode for playing Gomoku against Emacs.
-You and Emacs play in turn by marking a free square. You mark it with X
-and Emacs marks it with O. The winner is the first to get five contiguous
-marks horizontally, vertically or in diagonal.
-
-You play by moving the cursor over the square you choose and hitting \\[gomoku-human-plays].
-
-Other useful commands:
-\\{gomoku-mode-map}
-Entry to this mode calls the value of `gomoku-mode-hook' if that value
-is non-nil."
- (interactive)
- (setq major-mode 'gomoku-mode
- mode-name "Gomoku")
- (gomoku-display-statistics)
- (use-local-map gomoku-mode-map)
- (run-hooks 'gomoku-mode-hook))
-
-;;;
-;;; THE BOARD.
-;;;
-
-;; The board is a rectangular grid. We code empty squares with 0, X's with 1
-;; and O's with 6. The rectangle is recorded in a one dimensional vector
-;; containing padding squares (coded with -1). These squares allow us to
-;; detect when we are trying to move out of the board. We denote a square by
-;; its (X,Y) coords, or by the INDEX corresponding to them in the vector. The
-;; leftmost topmost square has coords (1,1) and index gomoku-board-width + 2.
-;; Similarly, vectors between squares may be given by two DX, DY coords or by
-;; one DEPL (the difference between indexes).
-
-(defvar gomoku-board-width nil
- "Number of columns on the Gomoku board.")
-
-(defvar gomoku-board-height nil
- "Number of lines on the Gomoku board.")
-
-(defvar gomoku-board nil
- "Vector recording the actual state of the Gomoku board.")
-
-(defvar gomoku-vector-length nil
- "Length of gomoku-board vector.")
-
-(defvar gomoku-draw-limit nil
- ;; This is usually set to 70% of the number of squares.
- "After how many moves will Emacs offer a draw?")
-
-
-(defun gomoku-xy-to-index (x y)
- "Translate X, Y cartesian coords into the corresponding board index."
- (+ (* y gomoku-board-width) x y))
-
-(defun gomoku-index-to-x (index)
- "Return corresponding x-coord of board INDEX."
- (% index (1+ gomoku-board-width)))
-
-(defun gomoku-index-to-y (index)
- "Return corresponding y-coord of board INDEX."
- (/ index (1+ gomoku-board-width)))
-
-(defun gomoku-init-board ()
- "Create the gomoku-board vector and fill it with initial values."
- (setq gomoku-board (make-vector gomoku-vector-length 0))
- ;; Every square is 0 (i.e. empty) except padding squares:
- (let ((i 0) (ii (1- gomoku-vector-length)))
- (while (<= i gomoku-board-width) ; The squares in [0..width] and in
- (aset gomoku-board i -1) ; [length - width - 1..length - 1]
- (aset gomoku-board ii -1) ; are padding squares.
- (setq i (1+ i)
- ii (1- ii))))
- (let ((i 0))
- (while (< i gomoku-vector-length)
- (aset gomoku-board i -1) ; and also all k*(width+1)
- (setq i (+ i gomoku-board-width 1)))))
-
-;;;
-;;; THE SCORE TABLE.
-;;;
-
-;; Every (free) square has a score associated to it, recorded in the
-;; GOMOKU-SCORE-TABLE vector. The program always plays in the square having
-;; the highest score.
-
-(defvar gomoku-score-table nil
- "Vector recording the actual score of the free squares.")
-
-
-;; The key point point about the algorithm is that, rather than considering
-;; the board as just a set of squares, we prefer to see it as a "space" of
-;; internested 5-tuples of contiguous squares (called qtuples).
-;;
-;; The aim of the program is to fill one qtuple with its O's while preventing
-;; you from filling another one with your X's. To that effect, it computes a
-;; score for every qtuple, with better qtuples having better scores. Of
-;; course, the score of a qtuple (taken in isolation) is just determined by
-;; its contents as a set, i.e. not considering the order of its elements. The
-;; highest score is given to the "OOOO" qtuples because playing in such a
-;; qtuple is winning the game. Just after this comes the "XXXX" qtuple because
-;; not playing in it is just loosing the game, and so on. Note that a
-;; "polluted" qtuple, i.e. one containing at least one X and at least one O,
-;; has score zero because there is no more any point in playing in it, from
-;; both an attacking and a defending point of view.
-;;
-;; Given the score of every qtuple, the score of a given free square on the
-;; board is just the sum of the scores of all the qtuples to which it belongs,
-;; because playing in that square is playing in all its containing qtuples at
-;; once. And it is that function which takes into account the internesting of
-;; the qtuples.
-;;
-;; This algorithm is rather simple but anyway it gives a not so dumb level of
-;; play. It easily extends to "n-dimensional Gomoku", where a win should not
-;; be obtained with as few as 5 contiguous marks: 6 or 7 (depending on n !)
-;; should be preferred.
-
-
-;; Here are the scores of the nine "non-polluted" configurations. Tuning
-;; these values will change (hopefully improve) the strength of the program
-;; and may change its style (rather aggressive here).
-
-(defconst nil-score 7 "Score of an empty qtuple.")
-(defconst Xscore 15 "Score of a qtuple containing one X.")
-(defconst XXscore 400 "Score of a qtuple containing two X's.")
-(defconst XXXscore 1800 "Score of a qtuple containing three X's.")
-(defconst XXXXscore 100000 "Score of a qtuple containing four X's.")
-(defconst Oscore 35 "Score of a qtuple containing one O.")
-(defconst OOscore 800 "Score of a qtuple containing two O's.")
-(defconst OOOscore 15000 "Score of a qtuple containing three O's.")
-(defconst OOOOscore 800000 "Score of a qtuple containing four O's.")
-
-;; These values are not just random: if, given the following situation:
-;;
-;; . . . . . . . O .
-;; . X X a . . . X .
-;; . . . X . . . X .
-;; . . . X . . . X .
-;; . . . . . . . b .
-;;
-;; you want Emacs to play in "a" and not in "b", then the parameters must
-;; satisfy the inequality:
-;;
-;; 6 * XXscore > XXXscore + XXscore
-;;
-;; because "a" mainly belongs to six "XX" qtuples (the others are less
-;; important) while "b" belongs to one "XXX" and one "XX" qtuples. Other
-;; conditions are required to obtain sensible moves, but the previous example
-;; should illustrate the point. If you manage to improve on these values,
-;; please send me a note. Thanks.
-
-
-;; As we choosed values 0, 1 and 6 to denote empty, X and O squares, the
-;; contents of a qtuple is uniquely determined by the sum of its elements and
-;; we just have to set up a translation table.
-
-(defconst gomoku-score-trans-table
- (vector nil-score Xscore XXscore XXXscore XXXXscore 0
- Oscore 0 0 0 0 0
- OOscore 0 0 0 0 0
- OOOscore 0 0 0 0 0
- OOOOscore 0 0 0 0 0
- 0)
- "Vector associating qtuple contents to their score.")
-
-
-;; If you do not modify drastically the previous constants, the only way for a
-;; square to have a score higher than OOOOscore is to belong to a "OOOO"
-;; qtuple, thus to be a winning move. Similarly, the only way for a square to
-;; have a score between XXXXscore and OOOOscore is to belong to a "XXXX"
-;; qtuple. We may use these considerations to detect when a given move is
-;; winning or loosing.
-
-(defconst gomoku-winning-threshold OOOOscore
- "Threshold score beyond which an Emacs move is winning.")
-
-(defconst gomoku-loosing-threshold XXXXscore
- "Threshold score beyond which a human move is winning.")
-
-
-(defun gomoku-strongest-square ()
- "Compute index of free square with highest score, or nil if none."
- ;; We just have to loop other all squares. However there are two problems:
- ;; 1/ The SCORE-TABLE only gives correct scores to free squares. To speed
- ;; up future searches, we set the score of padding or occupied squares
- ;; to -1 whenever we meet them.
- ;; 2/ We want to choose randomly between equally good moves.
- (let ((score-max 0)
- (count 0) ; Number of equally good moves
- (square (gomoku-xy-to-index 1 1)) ; First square
- (end (gomoku-xy-to-index gomoku-board-width gomoku-board-height))
- best-square score)
- (while (<= square end)
- (cond
- ;; If score is lower (i.e. most of the time), skip to next:
- ((< (aref gomoku-score-table square) score-max))
- ;; If score is better, beware of non free squares:
- ((> (setq score (aref gomoku-score-table square)) score-max)
- (if (zerop (aref gomoku-board square)) ; is it free ?
- (setq count 1 ; yes: take it !
- best-square square
- score-max score)
- (aset gomoku-score-table square -1))) ; no: kill it !
- ;; If score is equally good, choose randomly. But first check freeness:
- ((not (zerop (aref gomoku-board square)))
- (aset gomoku-score-table square -1))
- ((= count (random-number (setq count (1+ count))))
- (setq best-square square
- score-max score)))
- (setq square (1+ square))) ; try next square
- best-square))
-
-(defun random-number (n)
- "Return a random integer between 0 and N-1 inclusive."
- (setq n (% (random) n))
- (if (< n 0) (- n) n))
-
-;;;
-;;; INITIALIZING THE SCORE TABLE.
-;;;
-
-;; At initialization the board is empty so that every qtuple amounts for
-;; nil-score. Therefore, the score of any square is nil-score times the number
-;; of qtuples that pass through it. This number is 3 in a corner and 20 if you
-;; are sufficiently far from the sides. As computing the number is time
-;; consuming, we initialize every square with 20*nil-score and then only
-;; consider squares at less than 5 squares from one side. We speed this up by
-;; taking symmetry into account.
-;; Also, as it is likely that successive games will be played on a board with
-;; same size, it is a good idea to save the initial SCORE-TABLE configuration.
-
-(defvar gomoku-saved-score-table nil
- "Recorded initial value of previous score table.")
-
-(defvar gomoku-saved-board-width nil
- "Recorded value of previous board width.")
-
-(defvar gomoku-saved-board-height nil
- "Recorded value of previous board height.")
-
-
-(defun gomoku-init-score-table ()
- "Create the score table vector and fill it with initial values."
- (if (and gomoku-saved-score-table ; Has it been stored last time ?
- (= gomoku-board-width gomoku-saved-board-width)
- (= gomoku-board-height gomoku-saved-board-height))
- (setq gomoku-score-table (copy-sequence gomoku-saved-score-table))
- ;; No, compute it:
- (setq gomoku-score-table
- (make-vector gomoku-vector-length (* 20 nil-score)))
- (let (i j maxi maxj maxi2 maxj2)
- (setq maxi (/ (1+ gomoku-board-width) 2)
- maxj (/ (1+ gomoku-board-height) 2)
- maxi2 (min 4 maxi)
- maxj2 (min 4 maxj))
- ;; We took symmetry into account and could use it more if the board
- ;; would have been square and not rectangular !
- ;; In our case we deal with all (i,j) in the set [1..maxi2]*[1..maxj] U
- ;; [maxi2+1..maxi]*[1..maxj2]. Maxi2 and maxj2 are used because the
- ;; board may well be less than 8 by 8 !
- (setq i 1)
- (while (<= i maxi2)
- (setq j 1)
- (while (<= j maxj)
- (gomoku-init-square-score i j)
- (setq j (1+ j)))
- (setq i (1+ i)))
- (while (<= i maxi)
- (setq j 1)
- (while (<= j maxj2)
- (gomoku-init-square-score i j)
- (setq j (1+ j)))
- (setq i (1+ i))))
- (setq gomoku-saved-score-table (copy-sequence gomoku-score-table)
- gomoku-saved-board-width gomoku-board-width
- gomoku-saved-board-height gomoku-board-height)))
-
-(defun gomoku-nb-qtuples (i j)
- "Return the number of qtuples containing square I,J."
- ;; This function is complicated because we have to deal
- ;; with ugly cases like 3 by 6 boards, but it works.
- ;; If you have a simpler (and correct) solution, send it to me. Thanks !
- (let ((left (min 4 (1- i)))
- (right (min 4 (- gomoku-board-width i)))
- (up (min 4 (1- j)))
- (down (min 4 (- gomoku-board-height j))))
- (+ -12
- (min (max (+ left right) 3) 8)
- (min (max (+ up down) 3) 8)
- (min (max (+ (min left up) (min right down)) 3) 8)
- (min (max (+ (min right up) (min left down)) 3) 8))))
-
-(defun gomoku-init-square-score (i j)
- "Give initial score to square I,J and to its mirror images."
- (let ((ii (1+ (- gomoku-board-width i)))
- (jj (1+ (- gomoku-board-height j)))
- (sc (* (gomoku-nb-qtuples i j) (aref gomoku-score-trans-table 0))))
- (aset gomoku-score-table (gomoku-xy-to-index i j) sc)
- (aset gomoku-score-table (gomoku-xy-to-index ii j) sc)
- (aset gomoku-score-table (gomoku-xy-to-index i jj) sc)
- (aset gomoku-score-table (gomoku-xy-to-index ii jj) sc)))
-
-;;;
-;;; MAINTAINING THE SCORE TABLE.
-;;;
-
-;; We do not provide functions for computing the SCORE-TABLE given the
-;; contents of the BOARD. This would involve heavy nested loops, with time
-;; proportional to the size of the board. It is better to update the
-;; SCORE-TABLE after each move. Updating needs not modify more than 36
-;; squares: it is done in constant time.
-
-(defun gomoku-update-score-table (square dval)
- "Update score table after SQUARE received a DVAL increment."
- ;; The board has already been updated when this function is called.
- ;; Updating scores is done by looking for qtuples boundaries in all four
- ;; directions and then calling update-score-in-direction.
- ;; Finally all squares received the right increment, and then are up to
- ;; date, except possibly for SQUARE itself if we are taking a move back for
- ;; its score had been set to -1 at the time.
- (let* ((x (gomoku-index-to-x square))
- (y (gomoku-index-to-y square))
- (imin (max -4 (- 1 x)))
- (jmin (max -4 (- 1 y)))
- (imax (min 0 (- gomoku-board-width x 4)))
- (jmax (min 0 (- gomoku-board-height y 4))))
- (gomoku-update-score-in-direction imin imax
- square 1 0 dval)
- (gomoku-update-score-in-direction jmin jmax
- square 0 1 dval)
- (gomoku-update-score-in-direction (max imin jmin) (min imax jmax)
- square 1 1 dval)
- (gomoku-update-score-in-direction (max (- 1 y) -4
- (- x gomoku-board-width))
- (min 0 (- x 5)
- (- gomoku-board-height y 4))
- square -1 1 dval)))
-
-(defun gomoku-update-score-in-direction (left right square dx dy dval)
- "Update scores for all squares in the qtuples starting between the LEFTth
-square and the RIGHTth after SQUARE, along the DX, DY direction, considering
-that DVAL has been added on SQUARE."
- ;; We always have LEFT <= 0, RIGHT <= 0 and DEPL > 0 but we may very well
- ;; have LEFT > RIGHT, indicating that no qtuple contains SQUARE along that
- ;; DX,DY direction.
- (cond
- ((> left right)) ; Quit
- (t ; Else ..
- (let (depl square0 square1 square2 count delta)
- (setq depl (gomoku-xy-to-index dx dy)
- square0 (+ square (* left depl))
- square1 (+ square (* right depl))
- square2 (+ square0 (* 4 depl)))
- ;; Compute the contents of the first qtuple:
- (setq square square0
- count 0)
- (while (<= square square2)
- (setq count (+ count (aref gomoku-board square))
- square (+ square depl)))
- (while (<= square0 square1)
- ;; Update the squares of the qtuple beginning in SQUARE0 and ending
- ;; in SQUARE2.
- (setq delta (- (aref gomoku-score-trans-table count)
- (aref gomoku-score-trans-table (- count dval))))
- (cond ((not (zerop delta)) ; or else nothing to update
- (setq square square0)
- (while (<= square square2)
- (if (zerop (aref gomoku-board square)) ; only for free squares
- (aset gomoku-score-table square
- (+ (aref gomoku-score-table square) delta)))
- (setq square (+ square depl)))))
- ;; Then shift the qtuple one square along DEPL, this only requires
- ;; modifying SQUARE0 and SQUARE2.
- (setq square2 (+ square2 depl)
- count (+ count (- (aref gomoku-board square0))
- (aref gomoku-board square2))
- square0 (+ square0 depl)))))))
-
-;;;
-;;; GAME CONTROL.
-;;;
-
-;; Several variables are used to monitor a game, including a GAME-HISTORY (the
-;; list of all (SQUARE . PREVSCORE) played) that allows to take moves back
-;; (anti-updating the score table) and to compute the table from scratch in
-;; case of an interruption.
-
-(defvar gomoku-game-in-progress nil
- "Non-nil if a game is in progress.")
-
-(defvar gomoku-game-history nil
- "A record of all moves that have been played during current game.")
-
-(defvar gomoku-number-of-moves nil
- "Number of moves already played in current game.")
-
-(defvar gomoku-number-of-human-moves nil
- "Number of moves already played by human in current game.")
-
-(defvar gomoku-emacs-played-first nil
- "Non-nil if Emacs played first.")
-
-(defvar gomoku-human-took-back nil
- "Non-nil if Human took back a move during the game.")
-
-(defvar gomoku-human-refused-draw nil
- "Non-nil if Human refused Emacs offer of a draw.")
-
-(defvar gomoku-emacs-is-computing nil
- ;; This is used to detect interruptions. Hopefully, it should not be needed.
- "Non-nil if Emacs is in the middle of a computation.")
-
-
-(defun gomoku-start-game (n m)
- "Initialize a new game on an N by M board."
- (setq gomoku-emacs-is-computing t) ; Raise flag
- (setq gomoku-game-in-progress t)
- (setq gomoku-board-width n
- gomoku-board-height m
- gomoku-vector-length (1+ (* (+ m 2) (1+ n)))
- gomoku-draw-limit (/ (* 7 n m) 10))
- (setq gomoku-game-history nil
- gomoku-number-of-moves 0
- gomoku-number-of-human-moves 0
- gomoku-emacs-played-first nil
- gomoku-human-took-back nil
- gomoku-human-refused-draw nil)
- (gomoku-init-display n m) ; Display first: the rest takes time
- (gomoku-init-score-table) ; INIT-BOARD requires that the score
- (gomoku-init-board) ; table be already created.
- (setq gomoku-emacs-is-computing nil))
-
-(defun gomoku-play-move (square val &optional dont-update-score)
- "Go to SQUARE, play VAL and update everything."
- (setq gomoku-emacs-is-computing t) ; Raise flag
- (cond ((= 1 val) ; a Human move
- (setq gomoku-number-of-human-moves (1+ gomoku-number-of-human-moves)))
- ((zerop gomoku-number-of-moves) ; an Emacs move. Is it first ?
- (setq gomoku-emacs-played-first t)))
- (setq gomoku-game-history
- (cons (cons square (aref gomoku-score-table square))
- gomoku-game-history)
- gomoku-number-of-moves (1+ gomoku-number-of-moves))
- (gomoku-plot-square square val)
- (aset gomoku-board square val) ; *BEFORE* UPDATE-SCORE !
- (if dont-update-score nil
- (gomoku-update-score-table square val) ; previous val was 0: dval = val
- (aset gomoku-score-table square -1))
- (setq gomoku-emacs-is-computing nil))
-
-(defun gomoku-take-back ()
- "Take back last move and update everything."
- (setq gomoku-emacs-is-computing t)
- (let* ((last-move (car gomoku-game-history))
- (square (car last-move))
- (oldval (aref gomoku-board square)))
- (if (= 1 oldval)
- (setq gomoku-number-of-human-moves (1- gomoku-number-of-human-moves)))
- (setq gomoku-game-history (cdr gomoku-game-history)
- gomoku-number-of-moves (1- gomoku-number-of-moves))
- (gomoku-plot-square square 0)
- (aset gomoku-board square 0) ; *BEFORE* UPDATE-SCORE !
- (gomoku-update-score-table square (- oldval))
- (aset gomoku-score-table square (cdr last-move)))
- (setq gomoku-emacs-is-computing nil))
-
-;;;
-;;; SESSION CONTROL.
-;;;
-
-(defvar gomoku-number-of-wins 0
- "Number of games already won in this session.")
-
-(defvar gomoku-number-of-losses 0
- "Number of games already lost in this session.")
-
-(defvar gomoku-number-of-draws 0
- "Number of games already drawn in this session.")
-
-
-(defun gomoku-terminate-game (result)
- "Terminate the current game with RESULT."
- (let (message)
- (cond
- ((eq result 'emacs-won)
- (setq gomoku-number-of-wins (1+ gomoku-number-of-wins))
- (setq message
- (cond ((< gomoku-number-of-moves 20)
- "This was a REALLY QUICK win.")
- (gomoku-human-refused-draw
- "I won... Too bad you refused my offer of a draw !")
- (gomoku-human-took-back
- "I won... Taking moves back will not help you !")
- ((not gomoku-emacs-played-first)
- "I won... Playing first did not help you much !")
- ((and (zerop gomoku-number-of-losses)
- (zerop gomoku-number-of-draws)
- (> gomoku-number-of-wins 1))
- "I'm becoming tired of winning...")
- (t
- "I won."))))
- ((eq result 'human-won)
- (setq gomoku-number-of-losses (1+ gomoku-number-of-losses))
- (setq message
- (cond
- (gomoku-human-took-back
- "OK, you won this one. I, for one, never take my moves back...")
- (gomoku-emacs-played-first
- "OK, you won this one... so what ?")
- (t
- "OK, you won this one. Now, let me play first just once."))))
- ((eq result 'human-resigned)
- (setq gomoku-number-of-wins (1+ gomoku-number-of-wins))
- (setq message "So you resign. That's just one more win for me."))
- ((eq result 'nobody-won)
- (setq gomoku-number-of-draws (1+ gomoku-number-of-draws))
- (setq message
- (cond
- (gomoku-human-took-back
- "This is a draw. I, for one, never take my moves back...")
- (gomoku-emacs-played-first
- "This is a draw. Just chance, I guess.")
- (t
- "This is a draw. Now, let me play first just once."))))
- ((eq result 'draw-agreed)
- (setq gomoku-number-of-draws (1+ gomoku-number-of-draws))
- (setq message
- (cond
- (gomoku-human-took-back
- "Draw agreed. I, for one, never take my moves back...")
- (gomoku-emacs-played-first
- "Draw agreed. You were lucky.")
- (t
- "Draw agreed. Now, let me play first just once."))))
- ((eq result 'crash-game)
- (setq message
- "Sorry, I have been interrupted and cannot resume that game...")))
-
- (gomoku-display-statistics)
- (if message (message message))
- (ding)
- (setq gomoku-game-in-progress nil)))
-
-(defun gomoku-crash-game ()
- "What to do when Emacs detects it has been interrupted."
- (setq gomoku-emacs-is-computing nil)
- (gomoku-terminate-game 'crash-game)
- (sit-for 4) ; Let's see the message
- (gomoku-prompt-for-other-game))
-
-;;;
-;;; INTERACTIVE COMMANDS.
-;;;
-
-(defun gomoku (&optional n m)
- "Start a Gomoku game between you and Emacs.
-If a game is in progress, this command allow you to resume it.
-If optional arguments N and M are given, an N by M board is used.
-
-You and Emacs play in turn by marking a free square. You mark it with X
-and Emacs marks it with O. The winner is the first to get five contiguous
-marks horizontally, vertically or in diagonal.
-
-You play by moving the cursor over the square you choose and hitting
-\\<gomoku-mode-map>\\[gomoku-human-plays].
-Use \\[describe-mode] for more info."
- (interactive)
- (gomoku-switch-to-window)
- (cond
- (gomoku-emacs-is-computing
- (gomoku-crash-game))
- ((not gomoku-game-in-progress)
- (let ((max-width (gomoku-max-width))
- (max-height (gomoku-max-height)))
- (or n (setq n max-width))
- (or m (setq m max-height))
- (cond ((< n 1)
- (error "I need at least 1 column"))
- ((< m 1)
- (error "I need at least 1 row"))
- ((> n max-width)
- (error "I cannot display %d columns in that window" n)))
- (if (and (> m max-height)
- (not (equal m gomoku-saved-board-height))
- ;; Use EQUAL because SAVED-BOARD-HEIGHT may be nil
- (not (y-or-n-p (format "Do you really want %d rows " m))))
- (setq m max-height)))
- (message "One moment, please...")
- (gomoku-start-game n m)
- (if (y-or-n-p "Do you allow me to play first ")
- (gomoku-emacs-plays)
- (gomoku-prompt-for-move)))
- ((y-or-n-p "Shall we continue our game ")
- (gomoku-prompt-for-move))
- (t
- (gomoku-human-resigns))))
-
-(defun gomoku-emacs-plays ()
- "Compute Emacs next move and play it."
- (interactive)
- (gomoku-switch-to-window)
- (cond
- (gomoku-emacs-is-computing
- (gomoku-crash-game))
- ((not gomoku-game-in-progress)
- (gomoku-prompt-for-other-game))
- (t
- (message "Let me think...")
- (let (square score)
- (setq square (gomoku-strongest-square))
- (cond ((null square)
- (gomoku-terminate-game 'nobody-won))
- (t
- (setq score (aref gomoku-score-table square))
- (gomoku-play-move square 6)
- (cond ((>= score gomoku-winning-threshold)
- (gomoku-find-filled-qtuple square 6)
- (gomoku-cross-winning-qtuple)
- (gomoku-terminate-game 'emacs-won))
- ((zerop score)
- (gomoku-terminate-game 'nobody-won))
- ((and (> gomoku-number-of-moves gomoku-draw-limit)
- (not gomoku-human-refused-draw)
- (gomoku-offer-a-draw))
- (gomoku-terminate-game 'draw-agreed))
- (t
- (gomoku-prompt-for-move)))))))))
-
-(defun gomoku-human-plays ()
- "Signal to the Gomoku program that you have played.
-You must have put the cursor on the square where you want to play.
-If the game is finished, this command requests for another game."
- (interactive)
- (gomoku-switch-to-window)
- (cond
- (gomoku-emacs-is-computing
- (gomoku-crash-game))
- ((not gomoku-game-in-progress)
- (gomoku-prompt-for-other-game))
- (t
- (let (square score)
- (setq square (gomoku-point-square))
- (cond ((null square)
- (error "Your point is not on a square. Retry !"))
- ((not (zerop (aref gomoku-board square)))
- (error "Your point is not on a free square. Retry !"))
- (t
- (setq score (aref gomoku-score-table square))
- (gomoku-play-move square 1)
- (cond ((and (>= score gomoku-loosing-threshold)
- ;; Just testing SCORE > THRESHOLD is not enough for
- ;; detecting wins, it just gives an indication that
- ;; we confirm with GOMOKU-FIND-FILLED-QTUPLE.
- (gomoku-find-filled-qtuple square 1))
- (gomoku-cross-winning-qtuple)
- (gomoku-terminate-game 'human-won))
- (t
- (gomoku-emacs-plays)))))))))
-
-(defun gomoku-human-takes-back ()
- "Signal to the Gomoku program that you wish to take back your last move."
- (interactive)
- (gomoku-switch-to-window)
- (cond
- (gomoku-emacs-is-computing
- (gomoku-crash-game))
- ((not gomoku-game-in-progress)
- (message "Too late for taking back...")
- (sit-for 4)
- (gomoku-prompt-for-other-game))
- ((zerop gomoku-number-of-human-moves)
- (message "You have not played yet... Your move ?"))
- (t
- (message "One moment, please...")
- ;; It is possible for the user to let Emacs play several consecutive
- ;; moves, so that the best way to know when to stop taking back moves is
- ;; to count the number of human moves:
- (setq gomoku-human-took-back t)
- (let ((number gomoku-number-of-human-moves))
- (while (= number gomoku-number-of-human-moves)
- (gomoku-take-back)))
- (gomoku-prompt-for-move))))
-
-(defun gomoku-human-resigns ()
- "Signal to the Gomoku program that you may want to resign."
- (interactive)
- (gomoku-switch-to-window)
- (cond
- (gomoku-emacs-is-computing
- (gomoku-crash-game))
- ((not gomoku-game-in-progress)
- (message "There is no game in progress"))
- ((y-or-n-p "You mean, you resign ")
- (gomoku-terminate-game 'human-resigned))
- ((y-or-n-p "You mean, we continue ")
- (gomoku-prompt-for-move))
- (t
- (gomoku-terminate-game 'human-resigned)))) ; OK. Accept it
-
-;;;
-;;; PROMPTING THE HUMAN PLAYER.
-;;;
-
-(defun gomoku-prompt-for-move ()
- "Display a message asking for Human's move."
- (message (if (zerop gomoku-number-of-human-moves)
- "Your move ? (move to a free square and hit X, RET ...)"
- "Your move ?"))
- ;; This may seem silly, but if one omits the following line (or a similar
- ;; one), the cursor may very well go to some place where POINT is not.
- (save-excursion (set-buffer (other-buffer))))
-
-(defun gomoku-prompt-for-other-game ()
- "Ask for another game, and start it."
- (if (y-or-n-p "Another game ")
- (gomoku gomoku-board-width gomoku-board-height)
- (message "Chicken !")))
-
-(defun gomoku-offer-a-draw ()
- "Offer a draw and return T if Human accepted it."
- (or (y-or-n-p "I offer you a draw. Do you accept it ")
- (prog1 (setq gomoku-human-refused-draw t)
- nil)))
-
-;;;
-;;; DISPLAYING THE BOARD.
-;;;
-
-;; You may change these values if you have a small screen or if the squares
-;; look rectangular, but spacings SHOULD be at least 2 (MUST BE at least 1).
-
-(defconst gomoku-square-width 4
- "*Horizontal spacing between squares on the Gomoku board.")
-
-(defconst gomoku-square-height 2
- "*Vertical spacing between squares on the Gomoku board.")
-
-(defconst gomoku-x-offset 3
- "*Number of columns between the Gomoku board and the side of the window.")
-
-(defconst gomoku-y-offset 1
- "*Number of lines between the Gomoku board and the top of the window.")
-
-
-(defun gomoku-max-width ()
- "Largest possible board width for the current window."
- (1+ (/ (- (window-width (selected-window))
- gomoku-x-offset gomoku-x-offset 1)
- gomoku-square-width)))
-
-(defun gomoku-max-height ()
- "Largest possible board height for the current window."
- (1+ (/ (- (window-height (selected-window))
- gomoku-y-offset gomoku-y-offset 2)
- ;; 2 instead of 1 because WINDOW-HEIGHT includes the mode line !
- gomoku-square-height)))
-
-(defun gomoku-point-x ()
- "Return the board column where point is, or nil if it is not a board column."
- (let ((col (- (current-column) gomoku-x-offset)))
- (if (and (>= col 0)
- (zerop (% col gomoku-square-width))
- (<= (setq col (1+ (/ col gomoku-square-width)))
- gomoku-board-width))
- col)))
-
-(defun gomoku-point-y ()
- "Return the board row where point is, or nil if it is not a board row."
- (let ((row (- (count-lines 1 (point)) gomoku-y-offset 1)))
- (if (and (>= row 0)
- (zerop (% row gomoku-square-height))
- (<= (setq row (1+ (/ row gomoku-square-height)))
- gomoku-board-height))
- row)))
-
-(defun gomoku-point-square ()
- "Return the index of the square point is on, or nil if not on the board."
- (let (x y)
- (and (setq x (gomoku-point-x))
- (setq y (gomoku-point-y))
- (gomoku-xy-to-index x y))))
-
-(defun gomoku-goto-square (index)
- "Move point to square number INDEX."
- (gomoku-goto-xy (gomoku-index-to-x index) (gomoku-index-to-y index)))
-
-(defun gomoku-goto-xy (x y)
- "Move point to square at X, Y coords."
- (goto-line (+ 1 gomoku-y-offset (* gomoku-square-height (1- y))))
- (move-to-column (+ gomoku-x-offset (* gomoku-square-width (1- x)))))
-
-(defun gomoku-plot-square (square value)
- "Draw 'X', 'O' or '.' on SQUARE (depending on VALUE), leave point there."
- (gomoku-goto-square square)
- (gomoku-put-char (cond ((= value 1) ?X)
- ((= value 6) ?O)
- (t ?.)))
- (sit-for 0)) ; Display NOW
-
-(defun gomoku-put-char (char)
- "Draw CHAR on the Gomoku screen."
- (if buffer-read-only (toggle-read-only))
- (insert char)
- (delete-char 1)
- (backward-char 1)
- (toggle-read-only))
-
-(defun gomoku-init-display (n m)
- "Display an N by M Gomoku board."
- (buffer-disable-undo (current-buffer))
- (if buffer-read-only (toggle-read-only))
- (erase-buffer)
- (let (string1 string2 string3 string4)
- ;; We do not use gomoku-plot-square which would be too slow for
- ;; initializing the display. Rather we build STRING1 for lines where
- ;; board squares are to be found, and STRING2 for empty lines. STRING1 is
- ;; like STRING2 except for dots every DX squares. Empty lines are filled
- ;; with spaces so that cursor moving up and down remains on the same
- ;; column.
- (setq string1 (concat (make-string (1- gomoku-square-width) ? ) ".")
- string1 (apply 'concat
- (make-list (1- n) string1))
- string1 (concat (make-string gomoku-x-offset ? ) "." string1 "\n")
- string2 (make-string (+ 1 gomoku-x-offset
- (* (1- n) gomoku-square-width))
- ? )
- string2 (concat string2 "\n")
- string3 (apply 'concat
- (make-list (1- gomoku-square-height) string2))
- string3 (concat string3 string1)
- string3 (apply 'concat
- (make-list (1- m) string3))
- string4 (apply 'concat
- (make-list gomoku-y-offset string2)))
- (insert string4 string1 string3))
- (toggle-read-only)
- (gomoku-goto-xy (/ (1+ n) 2) (/ (1+ m) 2)) ; center of the board
- (sit-for 0)) ; Display NOW
-
-(defun gomoku-display-statistics ()
- "Obnoxiously display some statistics about previous games in mode line."
- ;; We store this string in the mode-line-process local variable.
- ;; This is certainly not the cleanest way out ...
- (setq mode-line-process
- (cond
- ((not (zerop gomoku-number-of-draws))
- (format ": Won %d, lost %d, drew %d"
- gomoku-number-of-wins
- gomoku-number-of-losses
- gomoku-number-of-draws))
- ((not (zerop gomoku-number-of-losses))
- (format ": Won %d, lost %d"
- gomoku-number-of-wins
- gomoku-number-of-losses))
- ((zerop gomoku-number-of-wins)
- "")
- ((= 1 gomoku-number-of-wins)
- ": Already won one")
- (t
- (format ": Won %d in a row"
- gomoku-number-of-wins))))
- ;; Then a (standard) kludgy line will force update of mode line.
- (set-buffer-modified-p (buffer-modified-p)))
-
-(defun gomoku-switch-to-window ()
- "Find or create the Gomoku buffer, and display it."
- (interactive)
- (let ((buff (get-buffer "*Gomoku*")))
- (if buff ; Buffer exists:
- (switch-to-buffer buff) ; no problem.
- (if gomoku-game-in-progress
- (gomoku-crash-game)) ; buffer has been killed or something
- (switch-to-buffer "*Gomoku*") ; Anyway, start anew.
- (gomoku-mode))))
-
-;;;
-;;; CROSSING WINNING QTUPLES.
-;;;
-
-;; When someone succeeds in filling a qtuple, we draw a line over the five
-;; corresponding squares. One problem is that the program does not know which
-;; squares ! It only knows the square where the last move has been played and
-;; who won. The solution is to scan the board along all four directions.
-
-(defvar gomoku-winning-qtuple-beg nil
- "First square of the winning qtuple.")
-
-(defvar gomoku-winning-qtuple-end nil
- "Last square of the winning qtuple.")
-
-(defvar gomoku-winning-qtuple-dx nil
- "Direction of the winning qtuple (along the X axis).")
-
-(defvar gomoku-winning-qtuple-dy nil
- "Direction of the winning qtuple (along the Y axis).")
-
-
-(defun gomoku-find-filled-qtuple (square value)
- "Return T if SQUARE belongs to a qtuple filled with VALUEs."
- (or (gomoku-check-filled-qtuple square value 1 0)
- (gomoku-check-filled-qtuple square value 0 1)
- (gomoku-check-filled-qtuple square value 1 1)
- (gomoku-check-filled-qtuple square value -1 1)))
-
-(defun gomoku-check-filled-qtuple (square value dx dy)
- "Return T if SQUARE belongs to a qtuple filled with VALUEs along DX, DY."
- ;; And record it in the WINNING-QTUPLE-... variables.
- (let ((a 0) (b 0)
- (left square) (right square)
- (depl (gomoku-xy-to-index dx dy))
- a+4)
- (while (and (> a -4) ; stretch tuple left
- (= value (aref gomoku-board (setq left (- left depl)))))
- (setq a (1- a)))
- (setq a+4 (+ a 4))
- (while (and (< b a+4) ; stretch tuple right
- (= value (aref gomoku-board (setq right (+ right depl)))))
- (setq b (1+ b)))
- (cond ((= b a+4) ; tuple length = 5 ?
- (setq gomoku-winning-qtuple-beg (+ square (* a depl))
- gomoku-winning-qtuple-end (+ square (* b depl))
- gomoku-winning-qtuple-dx dx
- gomoku-winning-qtuple-dy dy)
- t))))
-
-(defun gomoku-cross-winning-qtuple ()
- "Cross winning qtuple, as found by `gomoku-find-filled-qtuple'."
- (gomoku-cross-qtuple gomoku-winning-qtuple-beg
- gomoku-winning-qtuple-end
- gomoku-winning-qtuple-dx
- gomoku-winning-qtuple-dy))
-
-(defun gomoku-cross-qtuple (square1 square2 dx dy)
- "Cross every square between SQUARE1 and SQUARE2 in the DX, DY direction."
- (save-excursion ; Not moving point from last square
- (let ((depl (gomoku-xy-to-index dx dy)))
- ;; WARNING: this function assumes DEPL > 0 and SQUARE2 > SQUARE1
- (while (not (= square1 square2))
- (gomoku-goto-square square1)
- (setq square1 (+ square1 depl))
- (cond
- ((and (= dx 1) (= dy 0)) ; Horizontal
- (let ((n 1))
- (while (< n gomoku-square-width)
- (setq n (1+ n))
- (forward-char 1)
- (gomoku-put-char ?-))))
- ((and (= dx 0) (= dy 1)) ; Vertical
- (let ((n 1))
- (while (< n gomoku-square-height)
- (setq n (1+ n))
- (next-line 1)
- (gomoku-put-char ?|))))
- ((and (= dx -1) (= dy 1)) ; 1st Diagonal
- (backward-char (/ gomoku-square-width 2))
- (next-line (/ gomoku-square-height 2))
- (gomoku-put-char ?/))
- ((and (= dx 1) (= dy 1)) ; 2nd Diagonal
- (forward-char (/ gomoku-square-width 2))
- (next-line (/ gomoku-square-height 2))
- (gomoku-put-char ?\\))))))
- (sit-for 0)) ; Display NOW
-
-;;;
-;;; CURSOR MOTION.
-;;;
-(defun gomoku-move-left ()
- "Move point backward one column on the Gomoku board."
- (interactive)
- (let ((x (gomoku-point-x)))
- (backward-char (cond ((null x) 1)
- ((> x 1) gomoku-square-width)
- (t 0)))))
-
-(defun gomoku-move-right ()
- "Move point forward one column on the Gomoku board."
- (interactive)
- (let ((x (gomoku-point-x)))
- (forward-char (cond ((null x) 1)
- ((< x gomoku-board-width) gomoku-square-width)
- (t 0)))))
-
-(defun gomoku-move-down ()
- "Move point down one row on the Gomoku board."
- (interactive)
- (let ((y (gomoku-point-y)))
- (next-line (cond ((null y) 1)
- ((< y gomoku-board-height) gomoku-square-height)
- (t 0)))))
-
-(defun gomoku-move-up ()
- "Move point up one row on the Gomoku board."
- (interactive)
- (let ((y (gomoku-point-y)))
- (previous-line (cond ((null y) 1)
- ((> y 1) gomoku-square-height)
- (t 0)))))
-
-(defun gomoku-move-ne ()
- "Move point North East on the Gomoku board."
- (interactive)
- (gomoku-move-up)
- (gomoku-move-right))
-
-(defun gomoku-move-se ()
- "Move point South East on the Gomoku board."
- (interactive)
- (gomoku-move-down)
- (gomoku-move-right))
-
-(defun gomoku-move-nw ()
- "Move point North West on the Gomoku board."
- (interactive)
- (gomoku-move-up)
- (gomoku-move-left))
-
-(defun gomoku-move-sw ()
- "Move point South West on the Gomoku board."
- (interactive)
- (gomoku-move-down)
- (gomoku-move-left))
-
-
diff --git a/lisp/play/mpuz.el b/lisp/play/mpuz.el
deleted file mode 100644
index f4d622ad819..00000000000
--- a/lisp/play/mpuz.el
+++ /dev/null
@@ -1,448 +0,0 @@
-;;; Multiplication puzzle for GNU Emacs
-;;; by Philippe Schnoebelen <phs@lifia.imag.fr>
-;;; Last modified on 11 Nov 1990
-;;; Copyright (C) 1990 Free Software Foundation, Inc.
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY. No author or distributor
-;; accepts responsibility to anyone for the consequences of using it
-;; or for whether it serves any particular purpose or works at all,
-;; unless he says so in writing. Refer to the GNU Emacs General Public
-;; License for full details.
-
-;; Everyone is granted permission to copy, modify and redistribute
-;; GNU Emacs, but only under the conditions described in the
-;; GNU Emacs General Public License. A copy of this license is
-;; supposed to have been given to you along with GNU Emacs so you
-;; can know your rights and responsibilities. It should be in a
-;; file named COPYING. Among other things, the copyright notice
-;; and this notice must be preserved on all copies.
-
-(random t) ; randomize
-
-(defun mpuz-random (n)
- "Return a random integer between 0 and N - 1 inclusive."
- (setq n (% (random) n))
- (if (< n 0) (- n) n))
-
-(defvar mpuz-silent nil
- "*Set this to T if you don't want dings on inputs.")
-
-(defun mpuz-ding ()
- "Dings, unless global variable `mpuz-silent' forbids it."
- (or mpuz-silent (ding t)))
-
-
-;; Mpuz mode and keymaps
-;;----------------------
-(defvar mpuz-mode-hook nil)
-
-(defvar mpuz-mode-map nil
- "Local keymap to use in Mult Puzzle.")
-
-(defvar mpuz-read-map nil
- "Local keymap to use (sometimes) in Mult Puzzle.")
-
-(if mpuz-mode-map nil
- (setq mpuz-mode-map (make-sparse-keymap))
- (define-key mpuz-mode-map "a" 'mpuz-try-letter)
- (define-key mpuz-mode-map "b" 'mpuz-try-letter)
- (define-key mpuz-mode-map "c" 'mpuz-try-letter)
- (define-key mpuz-mode-map "d" 'mpuz-try-letter)
- (define-key mpuz-mode-map "e" 'mpuz-try-letter)
- (define-key mpuz-mode-map "f" 'mpuz-try-letter)
- (define-key mpuz-mode-map "g" 'mpuz-try-letter)
- (define-key mpuz-mode-map "h" 'mpuz-try-letter)
- (define-key mpuz-mode-map "i" 'mpuz-try-letter)
- (define-key mpuz-mode-map "j" 'mpuz-try-letter)
- (define-key mpuz-mode-map "A" 'mpuz-try-letter)
- (define-key mpuz-mode-map "B" 'mpuz-try-letter)
- (define-key mpuz-mode-map "C" 'mpuz-try-letter)
- (define-key mpuz-mode-map "D" 'mpuz-try-letter)
- (define-key mpuz-mode-map "E" 'mpuz-try-letter)
- (define-key mpuz-mode-map "F" 'mpuz-try-letter)
- (define-key mpuz-mode-map "G" 'mpuz-try-letter)
- (define-key mpuz-mode-map "H" 'mpuz-try-letter)
- (define-key mpuz-mode-map "I" 'mpuz-try-letter)
- (define-key mpuz-mode-map "J" 'mpuz-try-letter)
- (define-key mpuz-mode-map "\C-g" 'mpuz-offer-abort)
- (define-key mpuz-mode-map "?" 'describe-mode))
-
-(if mpuz-read-map nil
- (setq mpuz-read-map (make-keymap))
- (fillarray mpuz-read-map 'exit-minibuffer))
-
-(defun mpuz-mode ()
- "Multiplication puzzle with GNU Emacs.
-
-You have to guess which letters stand for which digits in the
-multiplication displayed inside the *Mult Puzzle* buffer.
-
-You may enter a proposal (e.g. A=3) by hitting first the letter A,
-then the digit 3, on your keyboard.
-
-At any time you may leave the game to do other editing work. :-)
-Then you may resume the game with M-x mult-puzzle.
-You may abort a game by hitting \\[keyboard-quit]."
- (interactive)
- (setq major-mode 'mpuz-mode
- mode-name "Mult Puzzle")
- (use-local-map mpuz-mode-map)
- (run-hooks 'mpuz-mode-hook))
-
-
-;; Some variables for statistics
-;;------------------------------
-(defvar mpuz-nb-errors 0
- "Number of errors made in current game.")
-
-(defvar mpuz-nb-completed-games 0
- "Number of games completed.")
-
-(defvar mpuz-nb-cumulated-errors 0
- "Number of errors made in previous games.")
-
-
-;; Some variables for game tracking
-;;---------------------------------
-(defvar mpuz-in-progress nil
- "True if a game is currently in progress.")
-
-(defvar mpuz-found-digits (make-vector 10 nil)
- "A vector recording which digits have been decrypted.")
-
-(defmacro mpuz-digit-solved-p (digit)
- (list 'aref 'mpuz-found-digits digit))
-
-
-;; A puzzle uses a permutation of [0..9] into itself.
-;; We use both the permutation and its inverse.
-;;---------------------------------------------------
-(defvar mpuz-digit-to-letter (make-vector 10 0)
- "A permutation from [0..9] to [0..9].")
-
-(defvar mpuz-letter-to-digit (make-vector 10 0)
- "The inverse of mpuz-digit-to-letter.")
-
-(defmacro mpuz-to-digit (letter)
- (list 'aref 'mpuz-letter-to-digit letter))
-
-(defmacro mpuz-to-letter (digit)
- (list 'aref 'mpuz-digit-to-letter digit))
-
-(defun mpuz-build-random-perm ()
- "Initialize puzzle coding with a random permutation."
- (let ((letters (list 0 1 2 3 4 5 6 7 8 9)) ; new cons cells, because of delq
- (index 10)
- elem)
- (while letters
- (setq elem (nth (mpuz-random index) letters)
- letters (delq elem letters)
- index (1- index))
- (aset mpuz-digit-to-letter index elem)
- (aset mpuz-letter-to-digit elem index))))
-
-
-;; A puzzle also uses a board displaying a mulplication.
-;; Every digit appears in the board, crypted or not.
-;;------------------------------------------------------
-(defvar mpuz-board (make-vector 10 nil)
- "The board associates ot any digit the list of squares where it appears.")
-
-(defun mpuz-put-digit-on-board (number square)
- "Put (last digit of) NUMBER on SQUARE of the puzzle board."
- ;; i.e. push SQUARE on NUMBER square-list
- (setq number (% number 10))
- (aset mpuz-board number (cons square (aref mpuz-board number))))
-
-(defun mpuz-check-all-solved ()
- "Check whether all digits have been solved. Return t if yes."
- (catch 'found
- (let ((digit -1))
- (while (> 10 (setq digit (1+ digit)))
- (if (and (not (mpuz-digit-solved-p digit)) ; unsolved
- (aref mpuz-board digit)) ; and appearing in the puzzle !
- (throw 'found nil))))
- t))
-
-
-;; To build a puzzle, we take two random numbers and multiply them.
-;; We also take a random permutation for encryption.
-;; The random numbers are only use to see which digit appears in which square
-;; of the board. Everything is stored in individual squares.
-;;---------------------------------------------------------------------------
-(defun mpuz-random-puzzle ()
- "Draw random values to be multiplied in a puzzle."
- (mpuz-build-random-perm)
- (fillarray mpuz-board nil) ; erase the board
- (let (A B C D E)
- ;; A,B,C,D & E, are the five rows of our multiplication.
- ;; Choose random values, discarding uninteresting cases.
- (while (progn
- (setq A (mpuz-random 1000)
- B (mpuz-random 100)
- C (* A (% B 10))
- D (* A (/ B 10))
- E (* A B))
- (or (< C 1000) (< D 1000)))) ; forbid leading zeros in C or D
- ;; Individual digits are now put on their respectives squares.
- ;; [NB: A square is a pair <row,column> of the screen.]
- (mpuz-put-digit-on-board A '(2 . 9))
- (mpuz-put-digit-on-board (/ A 10) '(2 . 7))
- (mpuz-put-digit-on-board (/ A 100) '(2 . 5))
- (mpuz-put-digit-on-board B '(4 . 9))
- (mpuz-put-digit-on-board (/ B 10) '(4 . 7))
- (mpuz-put-digit-on-board C '(6 . 9))
- (mpuz-put-digit-on-board (/ C 10) '(6 . 7))
- (mpuz-put-digit-on-board (/ C 100) '(6 . 5))
- (mpuz-put-digit-on-board (/ C 1000) '(6 . 3))
- (mpuz-put-digit-on-board D '(8 . 7))
- (mpuz-put-digit-on-board (/ D 10) '(8 . 5))
- (mpuz-put-digit-on-board (/ D 100) '(8 . 3))
- (mpuz-put-digit-on-board (/ D 1000) '(8 . 1))
- (mpuz-put-digit-on-board E '(10 . 9))
- (mpuz-put-digit-on-board (/ E 10) '(10 . 7))
- (mpuz-put-digit-on-board (/ E 100) '(10 . 5))
- (mpuz-put-digit-on-board (/ E 1000) '(10 . 3))
- (mpuz-put-digit-on-board (/ E 10000) '(10 . 1))))
-
-;; Display
-;;--------
-(defconst mpuz-framework
- "
- . . .
- Number of errors (this game): 0
- x . .
- -------
- . . . .
- Number of completed games: 0
- . . . .
- --------- Average number of errors: 0.00
- . . . . ."
- "The general picture of the puzzle screen, as a string.")
-
-(defun mpuz-create-buffer ()
- "Create (or recreate) the puzzle buffer. Return it."
- (let ((buff (get-buffer-create "*Mult Puzzle*")))
- (save-excursion
- (set-buffer buff)
- (let ((buffer-read-only nil))
- (erase-buffer)
- (insert mpuz-framework)
- (mpuz-paint-board)
- (mpuz-paint-errors)
- (mpuz-paint-statistics)))
- buff))
-
-(defun mpuz-paint-errors ()
- "Paint error count on the puzzle screen."
- (mpuz-switch-to-window)
- (let ((buffer-read-only nil))
- (goto-line 3)
- (move-to-column 49)
- (mpuz-delete-line)
- (insert (prin1-to-string mpuz-nb-errors))))
-
-(defun mpuz-paint-statistics ()
- "Paint statistics about previous games on the puzzle screen."
- (let* ((mean (if (zerop mpuz-nb-completed-games) 0
- (/ (+ mpuz-nb-completed-games (* 200 mpuz-nb-cumulated-errors))
- (* 2 mpuz-nb-completed-games))))
- (frac-part (% mean 100)))
- (let ((buffer-read-only nil))
- (goto-line 7)
- (move-to-column 51)
- (mpuz-delete-line)
- (insert (prin1-to-string mpuz-nb-completed-games))
- (goto-line 9)
- (move-to-column 50)
- (mpuz-delete-line)
- (insert (format "%d.%d%d" (/ mean 100) (/ frac-part 10) (% frac-part 10))))))
-
-(defun mpuz-paint-board ()
- "Paint board situation on the puzzle screen."
- (mpuz-switch-to-window)
- (let ((letter -1))
- (while (> 10 (setq letter (1+ letter)))
- (mpuz-paint-digit (mpuz-to-digit letter))))
- (goto-char (point-min)))
-
-(defun mpuz-paint-digit (digit)
- "Paint all occurrences of DIGIT on the puzzle board."
- ;; (mpuz-switch-to-window)
- (let ((char (if (mpuz-digit-solved-p digit)
- (+ digit ?0)
- (+ (mpuz-to-letter digit) ?A)))
- (square-l (aref mpuz-board digit)))
- (let ((buffer-read-only nil))
- (while square-l
- (goto-line (car (car square-l))) ; line before column !
- (move-to-column (cdr (car square-l)))
- (insert char)
- (delete-char 1)
- (backward-char 1)
- (setq square-l (cdr square-l))))))
-
-(defun mpuz-delete-line ()
- "Clear from point to next newline." ; & put nothing in the kill ring
- (while (not (= ?\n (char-after (point))))
- (delete-char 1)))
-
-(defun mpuz-get-buffer ()
- "Get the puzzle buffer if it exists."
- (get-buffer "*Mult Puzzle*"))
-
-(defun mpuz-switch-to-window ()
- "Find or create the Mult-Puzzle buffer, and display it."
- (let ((buff (mpuz-get-buffer)))
- (or buff (setq buff (mpuz-create-buffer)))
- (switch-to-buffer buff)
- (or buffer-read-only (toggle-read-only))
- (mpuz-mode)))
-
-
-;; Game control
-;;-------------
-(defun mpuz-abort-game ()
- "Abort any puzzle in progess."
- (message "Mult Puzzle aborted.")
- (setq mpuz-in-progress nil
- mpuz-nb-errors 0)
- (fillarray mpuz-board nil)
- (let ((buff (mpuz-get-buffer)))
- (if buff (kill-buffer buff))))
-
-(defun mpuz-start-new-game ()
- "Start a new puzzle."
- (message "Here we go...")
- (setq mpuz-nb-errors 0
- mpuz-in-progress t)
- (fillarray mpuz-found-digits nil) ; initialize mpuz-found-digits
- (mpuz-random-puzzle)
- (mpuz-switch-to-window)
- (mpuz-paint-board)
- (mpuz-paint-errors)
- (mpuz-ask-for-try))
-
-(defun mpuz-offer-new-game ()
- "Ask if user wants to start a new puzzle."
- (if (y-or-n-p "Start a new game ")
- (mpuz-start-new-game)
- (message "OK. I won't.")))
-
-(defun mult-puzzle ()
- "Multiplication puzzle with GNU Emacs."
- ;; Main entry point
- (interactive)
- (mpuz-switch-to-window)
- (if mpuz-in-progress
- (mpuz-offer-abort)
- (mpuz-start-new-game)))
-
-(defun mpuz-offer-abort ()
- "Ask if user wants to abort current puzzle."
- (interactive)
- (if (y-or-n-p "Abort game ")
- (mpuz-abort-game)
- (mpuz-ask-for-try)))
-
-(defun mpuz-ask-for-try ()
- "Ask for user proposal in puzzle."
- (message "Your try ?"))
-
-(defun mpuz-try-letter ()
- "Propose a digit for a letter in puzzle."
- (interactive)
- (if mpuz-in-progress
- (let (letter-char digit digit-char message)
- (setq letter-char (if (or (< last-command-char ?a)
- (> last-command-char ?z))
- last-command-char
- (- last-command-char 32))
- digit (mpuz-to-digit (- letter-char ?A)))
- (cond ((mpuz-digit-solved-p digit)
- (message "%c already solved." letter-char))
- ((null (aref mpuz-board digit))
- (message "%c does not appear." letter-char))
- ((progn (setq message (format "%c = " letter-char))
- ;; <char> has been entered.
- ;; Print "<char> =" and
- ;; read <num> or = <num>
- (read-from-minibuffer message nil mpuz-read-map)
- (if (= last-input-char ?\=)
- (read-from-minibuffer message nil mpuz-read-map))
- (setq digit-char last-input-char)
- (message "%c = %c" letter-char digit-char)
- (or (> digit-char ?9) (< digit-char ?0))) ; bad input
- (ding t))
- (t
- (mpuz-try-proposal letter-char digit-char))))
- (mpuz-offer-new-game)))
-
-(defun mpuz-try-proposal (letter-char digit-char)
- "Propose LETTER-CHAR as code for DIGIT-CHAR."
- (let* ((letter (- letter-char ?A))
- (digit (- digit-char ?0))
- (correct-digit (mpuz-to-digit letter)))
- (cond ((mpuz-digit-solved-p correct-digit)
- (message "%c has already been found."))
- ((= digit correct-digit)
- (message "%c = %c correct !" letter-char digit-char)
- (mpuz-ding)
- (mpuz-correct-guess digit))
- (t ;;; incorrect guess
- (message "%c = %c incorrect !" letter-char digit-char)
- (mpuz-ding)
- (setq mpuz-nb-errors (1+ mpuz-nb-errors))
- (mpuz-paint-errors)))))
-
-(defun mpuz-correct-guess (digit)
- "Handle correct guessing of DIGIT."
- (aset mpuz-found-digits digit t) ; Mark digit as solved
- (mpuz-paint-digit digit) ; Repaint it (now as a digit)
- (if (mpuz-check-all-solved)
- (mpuz-close-game)))
-
-(defun mpuz-close-game ()
- "Housecleaning when puzzle has been solved."
- (setq mpuz-in-progress nil
- mpuz-nb-cumulated-errors (+ mpuz-nb-cumulated-errors mpuz-nb-errors)
- mpuz-nb-completed-games (1+ mpuz-nb-completed-games))
- (mpuz-paint-statistics)
- (let ((message (mpuz-congratulate)))
- (message message)
- (sit-for 4)
- (if (y-or-n-p (concat message " Start a new game "))
- (mpuz-start-new-game)
- (message "Good Bye !"))))
-
-(defun mpuz-congratulate ()
- "Build a congratulation message when puzzle is solved."
- (format "Puzzle solved with %d errors. %s"
- mpuz-nb-errors
- (cond ((= mpuz-nb-errors 0) "That's perfect !")
- ((= mpuz-nb-errors 1) "That's very good !")
- ((= mpuz-nb-errors 2) "That's good.")
- ((= mpuz-nb-errors 3) "That's not bad.")
- ((= mpuz-nb-errors 4) "That's not too bad...")
- ((and (>= mpuz-nb-errors 5)
- (< mpuz-nb-errors 10)) "That's bad !")
- ((and (>= mpuz-nb-errors 10)
- (< mpuz-nb-errors 15)) "That's awful.")
- ((>= mpuz-nb-errors 15) "That's not serious."))))
-
-(defun mpuz-show-solution ()
- "Display solution for debugging purposes."
- (interactive)
- (mpuz-switch-to-window)
- (let (digit list)
- (setq digit -1)
- (while (> 10 (setq digit (1+ digit)))
- (or (mpuz-digit-solved-p digit)
- (setq list (cons digit list))))
- (mapcar 'mpuz-correct-guess list)))
-
-;;; End of mult-puzzle
-
diff --git a/lisp/progmodes/compile.el b/lisp/progmodes/compile.el
deleted file mode 100644
index 8ced79837d1..00000000000
--- a/lisp/progmodes/compile.el
+++ /dev/null
@@ -1,478 +0,0 @@
-;; Run compiler as inferior of Emacs, and parse its error messages.
-;; Copyright (C) 1985, 1986, 1988, 1989 Free Software Foundation, Inc.
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 1, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
-(provide 'compile)
-
-(defvar compilation-error-list nil
- "List of error message descriptors for visiting erring functions.
-Each error descriptor is a list of length two.
-Its car is a marker pointing to an error message.
-Its cadr is a marker pointing to the text of the line the message is about,
- or nil if that is not interesting.
-The value may be t instead of a list;
-this means that the buffer of error messages should be reparsed
-the next time the list of errors is wanted.")
-
-(defvar compilation-old-error-list nil
- "Value of `compilation-error-list' after errors were parsed.")
-
-(defvar compilation-last-error nil
- "List describing the error found by last call to \\[next-error].
-A list of two markers (ERROR-POS CODE-POS),
-pointing to the error message and the erroneous code, respectively.
-CODE-POS can be nil, if the error message has no specific source location.")
-
-(defvar compilation-parse-errors-hook 'compilation-parse-errors
- "Function to call (no args) to parse error messages from a compilation.
-It should read in the source files which have errors
-and set `compilation-error-list' to a list with an element
-for each error message found. See that variable for more info.")
-
-(defvar compilation-error-buffer nil
- "Current compilation buffer for compilation error processing.")
-
-(defvar compilation-parsing-end nil
- "Position of end of buffer when last error messages parsed.")
-
-(defvar compilation-error-message nil
- "Message to print when no more matches for compilation-error-regexp are found")
-
-;; The filename excludes colons to avoid confusion when error message
-;; starts with digits.
-(defvar compilation-error-regexp
- "\\([^ :\n]+\\(: *\\|, line \\|(\\)[0-9]+\\)\\|\\([0-9]+ *of *[^ \n]+\\)\\|\\(\"[^ \n]+\",L[0-9]+\\)"
- "Regular expression for filename/linenumber in error in compilation log.")
-
-(defvar compile-window-height nil
- "*Desired height of compilation window. nil means use Emacs default.")
-
-(defvar compile-command "make -k "
- "Last shell command used to do a compilation; default for next compilation.
-
-Sometimes it is useful for files to supply local values for this variable.
-You might also use mode hooks to specify it in certain modes, like this:
-
- (setq c-mode-hook
- '(lambda () (or (file-exists-p \"makefile\") (file-exists-p \"Makefile\")
- (progn (make-local-variable 'compile-command)
- (setq compile-command
- (concat \"make -k \"
- buffer-file-name))))))")
-
-(defvar compilation-search-path '(nil)
- "List of directories to search for source files named in error messages.
-Elements should be directory names, not file names of directories.
-nil as an element means to try the default directory.")
-
-(defun compile (command)
- "Compile the program including the current buffer. Default: run `make'.
-Runs COMMAND, a shell command, in a separate process asynchronously
-with output going to the buffer `*compilation*'.
-You can then use the command \\[next-error] to find the next error message
-and move to the source code that caused it.
-
-To run more than one compilation at once, start one and rename the
-`*compilation*' buffer to some other name. Then start the next one."
- (interactive (list (read-string "Compile command: " compile-command)))
- (setq compile-command command)
- (save-some-buffers nil nil)
- (compile-internal compile-command "No more errors")
- (and compile-window-height
- (= (window-width) (screen-width))
- (enlarge-window (- (- (screen-height) (window-height))
- compile-window-height) nil)))
-
-(defun grep (command-args)
- "Run grep, with user-specified args, and collect output in a buffer.
-While grep runs asynchronously, you can use the \\[next-error] command
-to find the text that grep hits refer to. It is expected that `grep-command'
-has a `-n' flag, so that line numbers are displayed for each match."
- (interactive
- (list (read-string (concat "Run "
- (substring grep-command 0
- (string-match "[\t ]+" grep-command))
- " (with args): ")
- (progn
- (string-match "-n[\t ]+" grep-command)
- (substring grep-command (match-end 0))))))
- ;; why a redundant string-match? It might not be interactive ...
- (setq grep-command (concat (substring grep-command 0
- (progn
- (string-match "-n" grep-command)
- (match-end 0)))
- " " command-args))
- (compile-internal (concat grep-command " /dev/null")
- "No more grep hits" "grep"))
-
-(defun compile-internal (command error-message
- &optional name-of-mode parser regexp)
- "Run compilation command COMMAND (low level interface).
-ERROR-MESSAGE is a string to print if the user asks to see another error
-and there are no more errors. Third argument NAME-OF-MODE is the name
-to display as the major mode in the `*compilation*' buffer.
-
-Fourth arg PARSER is the error parser function (nil means the default).
-Fifth arg REGEXP is the error message regexp to use (nil means the default).
-The defaults for these variables are the global values of
- `compilation-parse-errors-hook' and `compilation-error-regexp'."
- (save-excursion
- (set-buffer (get-buffer-create "*compilation*"))
- (setq buffer-read-only nil)
- (let ((comp-proc (get-buffer-process (current-buffer))))
- (if comp-proc
- (if (or (not (eq (process-status comp-proc) 'run))
- (yes-or-no-p "A compilation process is running; kill it? "))
- (condition-case ()
- (progn
- (interrupt-process comp-proc)
- (sit-for 1)
- (delete-process comp-proc))
- (error nil))
- (error "Cannot have two processes in `*compilation*' at once"))))
- ;; In case *compilation* is current buffer,
- ;; make sure we get the global values of compilation-error-regexp, etc.
- (kill-all-local-variables))
- (compilation-forget-errors)
- (start-process-shell-command "compilation" "*compilation*" command)
- (with-output-to-temp-buffer "*compilation*"
- (princ "cd ")
- (princ default-directory)
- (terpri)
- (princ command)
- (terpri))
- (let* ((regexp (or regexp compilation-error-regexp))
- (parser (or parser compilation-parse-errors-hook))
- (thisdir default-directory)
- (outbuf (get-buffer "*compilation*"))
- (outwin (get-buffer-window outbuf)))
- (if (eq outbuf (current-buffer))
- (goto-char (point-max)))
- (set-process-sentinel (get-buffer-process outbuf)
- 'compilation-sentinel)
- (save-excursion
- (set-buffer outbuf)
- (if (or (eq compilation-error-buffer outbuf)
- (eq compilation-error-list t)
- (and (null compilation-error-list)
- (not (and (get-buffer-process compilation-error-buffer)
- (eq (process-status compilation-error-buffer)
- 'run)))))
- (setq compilation-error-list t
- compilation-error-buffer outbuf))
- (setq default-directory thisdir)
- (compilation-mode)
- (set-window-start outwin (point-min))
- (setq mode-name (or name-of-mode "Compilation"))
- (setq buffer-read-only t)
- (or (eq outwin (selected-window))
- (set-window-point outwin (point-min))))))
-
-(defvar compilation-mode-map
- (let ((map (make-sparse-keymap)))
- (define-key map "\C-c\C-c" 'compile-goto-error)
- map)
- "Keymap for compilation log buffers.")
-
-(defun compilation-mode ()
- "Major mode for compilation log buffers.
-\\<compilation-mode-map>To visit the source for a line-numbered error,
-move point to the error message line and type \\[compile-goto-error]."
- (interactive)
- (fundamental-mode)
- (use-local-map compilation-mode-map)
- (make-local-variable 'compilation-parse-errors-hook)
- (setq compilation-parse-errors-hook parser)
- (make-local-variable 'compilation-error-message)
- (setq compilation-error-message error-message)
- (make-local-variable 'compilation-error-regexp)
- (setq compilation-error-regexp regexp)
- (buffer-disable-undo (current-buffer))
- (setq major-mode 'compilation-mode)
- (setq mode-name "Compilation")
- ;; Make log buffer's mode line show process state
- (setq mode-line-process '(": %s")))
-
-;; Called when compilation process changes state.
-
-(defun compilation-sentinel (proc msg)
- (cond ((null (buffer-name (process-buffer proc)))
- ;; buffer killed
- (set-process-buffer proc nil))
- ((memq (process-status proc) '(signal exit))
- (let* ((obuf (current-buffer))
- omax opoint)
- ;; save-excursion isn't the right thing if
- ;; process-buffer is current-buffer
- (unwind-protect
- (progn
- ;; Write something in *compilation* and hack its mode line,
- (set-buffer (process-buffer proc))
- (setq omax (point-max) opoint (point))
- (goto-char (point-max))
- (insert ?\n mode-name " " msg)
- (forward-char -1)
- (insert " at " (substring (current-time-string) 0 19))
- (forward-char 1)
- (setq mode-line-process
- (concat ": "
- (symbol-name (process-status proc))))
- ;; If buffer and mode line will show that the process
- ;; is dead, we can delete it now. Otherwise it
- ;; will stay around until M-x list-processes.
- (delete-process proc))
- ;; Force mode line redisplay soon
- (set-buffer-modified-p (buffer-modified-p)))
- (if (and opoint (< opoint omax))
- (goto-char opoint))
- (set-buffer obuf)))))
-
-(defun kill-compilation ()
- "Kill the process made by the \\[compile] command."
- (interactive)
- (let ((buffer
- (if (assq 'compilation-parse-errors-hook (buffer-local-variables))
- (current-buffer)
- (get-buffer "*compilation*"))))
- (if (get-buffer-process buffer)
- (interrupt-process (get-buffer-process buffer)))))
-
-;; Reparse errors or parse more/new errors, if appropriate.
-(defun compile-reinitialize-errors (argp)
- ;; If we are out of errors, or if user says "reparse",
- ;; or if we are in a different buffer from the known errors,
- ;; discard the info we have, to force reparsing.
- (if (or (eq compilation-error-list t)
- (consp argp)
- (if (assq 'compilation-parse-errors-hook (buffer-local-variables))
- (not (eq compilation-error-buffer
- (setq compilation-error-buffer (current-buffer))))))
- (progn (compilation-forget-errors)
- (setq compilation-parsing-end 1)))
- (if compilation-error-list
- nil
- (save-excursion
- (switch-to-buffer compilation-error-buffer)
- (set-buffer-modified-p nil)
- (let ((at-start (= compilation-parsing-end 1)))
- (run-hooks 'compilation-parse-errors-hook)
- ;; Remember the entire list for compilation-forget-errors.
- ;; If this is an incremental parse, append to previous list.
- (if at-start
- (setq compilation-old-error-list compilation-error-list)
- (setq compilation-old-error-list
- (nconc compilation-old-error-list compilation-error-list)))))))
-
-(defun compile-goto-error (&optional argp)
- "Visit the source for the error message point is on.
-Use this command in a compilation log buffer.
-C-u as a prefix arg means to reparse the buffer's error messages first;
-other kinds of prefix arguments are ignored."
- (interactive "P")
- (compile-reinitialize-errors argp)
- (save-excursion
- (beginning-of-line)
- (setq compilation-error-list
- (memq (assoc (point-marker) compilation-old-error-list)
- compilation-old-error-list)))
- ;; Move to another window, so that next-error's window changes
- ;; result in the desired setup.
- (or (one-window-p)
- (other-window -1))
- (next-error 1))
-
-(defun next-error (&optional argp)
- "Visit next compilation error message and corresponding source code.
-This operates on the output from the \\[compile] command.
-If all preparsed error messages have been processed,
-the error message buffer is checked for new ones.
-
-A prefix arg specifies how many error messages to move;
-negative means move back to previous error messages.
-Just C-u as a prefix means reparse the error message buffer
-and start at the first error.
-
-\\[next-error] normally applies to the most recent compilation started,
-but as long as you are in the middle of parsing errors from one compilation
-output buffer, you stay with that compilation output buffer.
-
-Use \\[next-error] in a compilation output buffer to switch to
-processing errors from that compilation.
-
-See variables `compilation-parse-errors-hook' and `compilation-error-regexp'
-for customization ideas. When we return, `compilation-last-error'
-points to the error message and the erroneous code."
- (interactive "P")
- (compile-reinitialize-errors argp)
- (if (consp argp)
- (setq argp nil))
- (let* ((next-errors (nthcdr (+ (- (length compilation-old-error-list)
- (length compilation-error-list)
- 1)
- (prefix-numeric-value argp))
- compilation-old-error-list))
- (next-error (car next-errors)))
- (if (null next-error)
- (save-excursion
- (if argp (if (> (prefix-numeric-value argp) 0)
- (error "Moved past last error")
- (error "Moved back past first error")))
- (set-buffer compilation-error-buffer)
- (compilation-forget-errors)
- (error (concat compilation-error-message
- (if (and (get-buffer-process (current-buffer))
- (eq (process-status (current-buffer))
- 'run))
- " yet" "")))))
- (setq compilation-error-list (cdr next-errors))
- ;; If we have an error to go to, go there.
- (if (null (car (cdr next-error)))
- nil
- (switch-to-buffer (marker-buffer (car (cdr next-error))))
- (goto-char (car (cdr next-error)))
- ;; If narrowing got in the way of going to the right place, widen.
- (or (= (point) (car (cdr next-error)))
- (progn
- (widen)
- (goto-char (car (cdr next-error))))))
- ;; Show compilation buffer in other window, scrolled to this error.
- (let* ((pop-up-windows t)
- (w (display-buffer (marker-buffer (car next-error)))))
- (set-window-point w (car next-error))
- (set-window-start w (car next-error)))
- (setq compilation-last-error next-error)))
-
-;; Set compilation-error-list to nil, and
-;; unchain the markers that point to the error messages and their text,
-;; so that they no longer slow down gap motion.
-;; This would happen anyway at the next garbage collection,
-;; but it is better to do it right away.
-(defun compilation-forget-errors ()
- (while compilation-old-error-list
- (let ((next-error (car compilation-old-error-list)))
- (set-marker (car next-error) nil)
- (if (car (cdr next-error))
- (set-marker (car (cdr next-error)) nil)))
- (setq compilation-old-error-list (cdr compilation-old-error-list)))
- (setq compilation-error-list nil))
-
-(defun compilation-parse-errors ()
- "Parse the current buffer as grep, cc or lint error messages.
-See variable `compilation-parse-errors-hook' for the interface it uses."
- (setq compilation-error-list nil)
- (message "Parsing error messages...")
- (let (text-buffer
- last-filename last-linenum)
- ;; Don't reparse messages already seen at last parse.
- (goto-char compilation-parsing-end)
- ;; Don't parse the first two lines as error messages.
- ;; This matters for grep.
- (if (bobp)
- (forward-line 2))
- (while (re-search-forward compilation-error-regexp nil t)
- (let (linenum filename
- error-marker text-marker)
- ;; Extract file name and line number from error message.
- (save-restriction
- (narrow-to-region (match-beginning 0) (match-end 0))
- (goto-char (point-max))
- (skip-chars-backward "[0-9]")
- ;; If it's a lint message, use the last file(linenum) on the line.
- ;; Normally we use the first on the line.
- (if (= (preceding-char) ?\()
- (progn
- (narrow-to-region (point-min) (1+ (buffer-size)))
- (end-of-line)
- (re-search-backward compilation-error-regexp)
- (skip-chars-backward "^ \t\n")
- (narrow-to-region (point) (match-end 0))
- (goto-char (point-max))
- (skip-chars-backward "[0-9]")))
- ;; Are we looking at a "filename-first" or "line-number-first" form?
- (if (looking-at "[0-9]")
- (progn
- (setq linenum (read (current-buffer)))
- (goto-char (point-min)))
- ;; Line number at start, file name at end.
- (progn
- (goto-char (point-min))
- (setq linenum (read (current-buffer)))
- (goto-char (point-max))
- (skip-chars-backward "^ \t\n")))
- (setq filename (compilation-grab-filename)))
- ;; Locate the erring file and line.
- (if (and (equal filename last-filename)
- (= linenum last-linenum))
- nil
- (beginning-of-line 1)
- (setq error-marker (point-marker))
- ;; text-buffer gets the buffer containing this error's file.
- (if (not (equal filename last-filename))
- (setq last-filename filename
- text-buffer (compilation-find-file filename)
- last-linenum 0))
- (if text-buffer
- ;; Go to that buffer and find the erring line.
- (save-excursion
- (set-buffer text-buffer)
- (if (zerop last-linenum)
- (progn
- (goto-char 1)
- (setq last-linenum 1)))
- (forward-line (- linenum last-linenum))
- (setq last-linenum linenum)
- (setq text-marker (point-marker))
- (setq compilation-error-list
- (cons (list error-marker text-marker)
- compilation-error-list)))))
- (forward-line 1)))
- (setq compilation-parsing-end (point-max)))
- (message "Parsing error messages...done")
- (setq compilation-error-list (nreverse compilation-error-list)))
-
-;; Find or create a buffer for file FILENAME.
-;; Search the directories in compilation-search-path
-;; after trying the current directory.
-(defun compilation-find-file (filename)
- (let ((dirs compilation-search-path)
- result)
- (while (and dirs (null result))
- (let ((name (if (car dirs)
- (concat (car dirs) filename)
- filename)))
- (setq result
- (and (file-exists-p name)
- (find-file-noselect name))))
- (setq dirs (cdr dirs)))
- result))
-
-(defun compilation-grab-filename ()
- "Return a string which is a filename, starting at point.
-Ignore quotes and parentheses around it, as well as trailing colons."
- (if (eq (following-char) ?\")
- (save-restriction
- (narrow-to-region (point)
- (progn (forward-sexp 1) (point)))
- (goto-char (point-min))
- (read (current-buffer)))
- (buffer-substring (point)
- (progn
- (skip-chars-forward "^ :,\n\t(")
- (point)))))
-
-(define-key ctl-x-map "`" 'next-error)
diff --git a/lisp/progmodes/prolog.el b/lisp/prolog.el
index 2ca899a59d0..10903e1fcab 100644
--- a/lisp/progmodes/prolog.el
+++ b/lisp/prolog.el
@@ -22,9 +22,6 @@
(defvar prolog-mode-abbrev-table nil)
(defvar prolog-mode-map nil)
-(defvar prolog-program-name "prolog"
- "*Program name for invoking an inferior Prolog with `run-prolog'.")
-
(defvar prolog-consult-string "reconsult(user).\n"
"*(Re)Consult mode (for C-Prolog and Quintus Prolog). ")
@@ -179,8 +176,7 @@ rigidly along with this one (not yet)."
(t
(save-excursion
(skip-chars-backward " \t")
- ;; Insert one space at least, except at left margin.
- (max (+ (current-column) (if (bolp) 0 1))
+ (max (1+ (current-column)) ;Insert one space at least
comment-column)))
))
@@ -190,6 +186,12 @@ rigidly along with this one (not yet)."
;;;
(defvar inferior-prolog-mode-map nil)
+;; Moved into inferior-prolog-mode
+;;(if inferior-prolog-mode-map
+;; nil
+;; (setq inferior-prolog-mode-map (copy-alist shell-mode-map))
+;; (prolog-mode-commands inferior-prolog-mode-map))
+
(defun inferior-prolog-mode ()
"Major mode for interacting with an inferior Prolog process.
@@ -197,8 +199,8 @@ The following commands are available:
\\{inferior-prolog-mode-map}
Entry to this mode calls the value of prolog-mode-hook with no arguments,
-if that value is non-nil. Likewise with the value of comint-mode-hook.
-prolog-mode-hook is called after comint-mode-hook.
+if that value is non-nil. Likewise with the value of shell-mode-hook.
+prolog-mode-hook is called after shell-mode-hook.
You can send text to the inferior Prolog from other buffers
using the commands send-region, send-string and \\[prolog-consult-region].
@@ -210,27 +212,35 @@ Paragraphs are separated only by blank lines and '%%'. '%'s start comments.
Return at end of buffer sends line as input.
Return not at end copies rest of line to end and sends it.
-\\[comint-kill-input] and \\[backward-kill-word] are kill commands, imitating normal Unix input editing.
-\\[comint-interrupt-subjob] interrupts the shell or its current subjob if any.
-\\[comint-stop-subjob] stops. \\[comint-quit-subjob] sends quit signal."
+\\[shell-send-eof] sends end-of-file as input.
+\\[kill-shell-input] and \\[backward-kill-word] are kill commands, imitating normal Unix input editing.
+\\[interrupt-shell-subjob] interrupts the shell or its current subjob if any.
+\\[stop-shell-subjob] stops, likewise. \\[quit-shell-subjob] sends quit signal, likewise."
(interactive)
- (require 'comint)
- (comint-mode)
- (setq major-mode 'inferior-prolog-mode
- mode-name "Inferior Prolog"
- comint-prompt-regexp "^| [ ?][- ] *")
+ (kill-all-local-variables)
+ (setq major-mode 'inferior-prolog-mode)
+ (setq mode-name "Inferior Prolog")
+ (setq mode-line-process '(": %s"))
(prolog-mode-variables)
- (if inferior-prolog-mode-map nil
- (setq inferior-prolog-mode-map (copy-keymap comint-mode-map))
+ (require 'shell)
+ (if inferior-prolog-mode-map
+ nil
+ (setq inferior-prolog-mode-map (copy-alist shell-mode-map))
(prolog-mode-commands inferior-prolog-mode-map))
(use-local-map inferior-prolog-mode-map)
- (run-hooks 'prolog-mode-hook))
+ (make-local-variable 'last-input-start)
+ (setq last-input-start (make-marker))
+ (make-local-variable 'last-input-end)
+ (setq last-input-end (make-marker))
+ (make-variable-buffer-local 'shell-prompt-pattern)
+ (setq shell-prompt-pattern "^| [ ?][- ] *") ;Set prolog prompt pattern
+ (run-hooks 'shell-mode-hook 'prolog-mode-hook))
(defun run-prolog ()
"Run an inferior Prolog process, input and output via buffer *prolog*."
(interactive)
- (require 'comint)
- (switch-to-buffer (make-comint "prolog" prolog-program-name))
+ (require 'shell)
+ (switch-to-buffer (make-shell "prolog" "prolog"))
(inferior-prolog-mode))
(defun prolog-consult-region (compile beg end)
diff --git a/lisp/prolog.elc b/lisp/prolog.elc
new file mode 100644
index 00000000000..e87c1b23ee0
--- /dev/null
+++ b/lisp/prolog.elc
Binary files differ
diff --git a/lisp/rect.el b/lisp/rect.el
index 3dd06f1be0e..e79b193211c 100644
--- a/lisp/rect.el
+++ b/lisp/rect.el
@@ -111,9 +111,8 @@ and ending with the line where the region ends."
(operate-on-rectangle 'delete-rectangle-line start end t))
(defun delete-extract-rectangle (start end)
- "Delete contents of rectangle and return it as a list of strings.
-Arguments START and END are the corners of the rectangle.
-The value is list of strings, one for each line of the rectangle."
+ "Return and delete contents of rectangle with corners at START and END.
+Value is list of strings, one for each line of the rectangle."
(let (lines)
(operate-on-rectangle 'delete-extract-rectangle-line
start end t)
@@ -181,10 +180,9 @@ but insted winds up to the right of the rectangle."
(point)))
(indent-to column)))
-(defun clear-rectangle (start end)
+(defun clear-rectangle (start end &optional preserve-position)
"Blank out rectangle with corners at point and mark.
-The text previously in the region is overwritten by the blanks.
-When called from a program, requires two args which specify the corners."
+The text previously in the region is overwritten by the blanks."
(interactive "r")
(operate-on-rectangle 'clear-rectangle-line start end t))
@@ -193,7 +191,8 @@ When called from a program, requires two args which specify the corners."
(let ((column (+ (current-column) endextra)))
(delete-region (point)
(progn (goto-char startpos)
- (skip-chars-backward " \t")
+ (or preserve-position
+ (skip-chars-backward " \t"))
(point)))
(indent-to column)))
diff --git a/lisp/rect.elc b/lisp/rect.elc
new file mode 100644
index 00000000000..d6366fb8d57
--- /dev/null
+++ b/lisp/rect.elc
Binary files differ
diff --git a/lisp/register.el b/lisp/register.el
index fd901f99f4a..ead49c35540 100644
--- a/lisp/register.el
+++ b/lisp/register.el
@@ -21,45 +21,36 @@
(defvar register-alist nil
"Alist of elements (NAME . CONTENTS), one for each Emacs register.
NAME is a character (a number). CONTENTS is a string, number,
-screen configuration, mark or list.
-A list represents a rectangle; its elements are strings.")
+mark or list. A list represents a rectangle; its elements are strings.")
(defun get-register (char)
"Return contents of Emacs register named CHAR, or nil if none."
(cdr (assq char register-alist)))
(defun set-register (char value)
- "Set contents of Emacs register named CHAR to VALUE.
-Returns VALUE."
+ "Set contents of Emacs register named CHAR to VALUE."
(let ((aelt (assq char register-alist)))
(if aelt
(setcdr aelt value)
(setq aelt (cons char value))
- (setq register-alist (cons aelt register-alist)))
- value))
+ (setq register-alist (cons aelt register-alist)))))
-(defun point-to-register (char arg)
- "Store current location of point in register REGISTER.
-With prefix argument, store current screen configuration.
-Use \\[jump-to-register] to go to that location or restore that configuration.
+(defun point-to-register (char)
+ "Store current location of point in a register.
Argument is a character, naming the register."
- (interactive "cPoint to register: \nP")
- (set-register char (if arg (current-screen-configuration) (point-marker))))
+ (interactive "cPoint to register: ")
+ (set-register char (point-marker)))
-(fset 'register-to-point 'jump-to-register)
-(defun jump-to-register (char)
+(defun register-to-point (char)
"Move point to location stored in a register.
Argument is a character, naming the register."
- (interactive "cJump to register: ")
+ (interactive "cRegister to point: ")
(let ((val (get-register char)))
- (condition-case ()
- (set-screen-configuration val)
- (error
- (if (markerp val)
- (progn
- (switch-to-buffer (marker-buffer val))
- (goto-char val))
- (error "Register doesn't contain a buffer position or screen configuration"))))))
+ (if (markerp val)
+ (progn
+ (switch-to-buffer (marker-buffer val))
+ (goto-char val))
+ (error "Register doesn't contain a buffer position"))))
;(defun number-to-register (arg char)
; "Store a number in a register.
@@ -133,7 +124,7 @@ Interactively, second arg is non-nil if prefix arg is supplied."
(if (or (integerp val) (markerp val))
(princ (+ 0 val) (current-buffer))
(error "Register does not contain text")))))
- (if (not arg) (exchange-point-and-mark)))
+ (or arg (exchange-point-and-mark)))
(defun copy-to-register (char start end &optional delete-flag)
"Copy region into register REG.
diff --git a/lisp/register.elc b/lisp/register.elc
new file mode 100644
index 00000000000..679adffb4c5
--- /dev/null
+++ b/lisp/register.elc
Binary files differ
diff --git a/lisp/replace.el b/lisp/replace.el
index fabcd11a554..6bbcde4e8b6 100644
--- a/lisp/replace.el
+++ b/lisp/replace.el
@@ -38,10 +38,7 @@ Applies to all lines after point."
(if (< start end)
(delete-region start end))))
(setq start (save-excursion (forward-line 1)
- (point)))
- ;; If the match was empty, avoid matching again at same place.
- (and (not (eobp)) (= (match-beginning 0) (match-end 0))
- (forward-char 1))))))
+ (point)))))))
(fset 'delete-matching-lines 'flush-lines)
(defun flush-lines (regexp)
@@ -61,14 +58,15 @@ Applies to lines after point."
(defun how-many (regexp)
"Print number of matches for REGEXP following point."
(interactive "sHow many matches for (regexp): ")
- (let ((count 0) opoint)
+ (let ((count 0) (opoint -1))
(save-excursion
- (while (and (not (eobp))
- (progn (setq opoint (point))
- (re-search-forward regexp nil t)))
- (if (= opoint (point))
- (forward-char 1)
- (setq count (1+ count))))
+ ;; If we did forward-char on the previous loop,
+ ;; and that brought us to eof, search anyway.
+ (while (and (or (not (eobp)) (/= opoint (point)))
+ (re-search-forward regexp nil t))
+ (if (prog1 (= opoint (point)) (setq opoint (point)))
+ (forward-char 1)
+ (setq count (1+ count))))
(message "%d occurrences" count))))
(defvar occur-mode-map ())
@@ -80,7 +78,6 @@ Applies to lines after point."
(defvar occur-buffer nil)
(defvar occur-nlines nil)
(defvar occur-pos-list nil)
-(defvar occur-last-string "")
(defun occur-mode ()
"Major mode for output from \\[occur].
@@ -104,18 +101,15 @@ in the buffer that the occurrences were found in.
(progn
(setq occur-buffer nil
occur-pos-list nil)
- (error "Buffer in which occurrences were found is deleted")))
+ (error "Buffer in which occurences were found is deleted.")))
(let* ((occur-number (save-excursion
- (beginning-of-line)
- (/ (1- (count-lines (point-min)
- (save-excursion
- (beginning-of-line)
- (point))))
- (cond ((< occur-nlines 0)
- (- 2 occur-nlines))
- ((> occur-nlines 0)
- (+ 2 (* 2 occur-nlines)))
- (t 1)))))
+ (beginning-of-line)
+ (/ (1- (count-lines (point-min) (point)))
+ (cond ((< occur-nlines 0)
+ (- 2 occur-nlines))
+ ((> occur-nlines 0)
+ (+ 2 (* 2 occur-nlines)))
+ (t 1)))))
(pos (nth occur-number occur-pos-list)))
(pop-to-buffer occur-buffer)
(goto-char (marker-position pos))))
@@ -125,41 +119,27 @@ in the buffer that the occurrences were found in.
match. A negative number means to include that many lines before the match.
A positive number means to include that many lines both before and after.")
-(defvar occur-whole-buffer nil
- "If t, occur operates on whole buffer, otherwise occur starts from point.
-default is nil.")
-
(fset 'list-matching-lines 'occur)
-
(defun occur (regexp &optional nlines)
- "Show lines containing a match for REGEXP. If the global variable
-occur-whole-buffer is non-nil, the entire buffer is searched, otherwise
-search begins at point. Interactively, REGEXP defaults to the last REGEXP
-used interactively.
-
-Each line is displayed with NLINES lines before and after,
-or -NLINES before if NLINES is negative.
+ "Show all lines following point containing a match for REGEXP.
+Display each line with NLINES lines before and after,
+ or -NLINES before if NLINES is negative.
NLINES defaults to list-matching-lines-default-context-lines.
Interactively it is the prefix arg.
The lines are shown in a buffer named *Occur*.
It serves as a menu to find any of the occurrences in this buffer.
\\[describe-mode] in that buffer will explain how."
- (interactive (list (setq occur-last-string
- (read-string "List lines matching regexp: "
- occur-last-string))
- current-prefix-arg))
+ (interactive "sList lines matching regexp: \nP")
(setq nlines (if nlines (prefix-numeric-value nlines)
list-matching-lines-default-context-lines))
(let ((first t)
(buffer (current-buffer))
- (linenum 1)
- (prevpos (point-min)))
- (if (not occur-whole-buffer)
- (save-excursion
- (beginning-of-line)
- (setq linenum (1+ (count-lines (point-min) (point))))
- (setq prevpos (point))))
+ linenum prevpos)
+ (save-excursion
+ (beginning-of-line)
+ (setq linenum (1+ (count-lines (point-min) (point))))
+ (setq prevpos (point)))
(with-output-to-temp-buffer "*Occur*"
(save-excursion
(set-buffer standard-output)
@@ -173,14 +153,13 @@ It serves as a menu to find any of the occurrences in this buffer.
(if (eq buffer standard-output)
(goto-char (point-max)))
(save-excursion
- (if occur-whole-buffer
- (beginning-of-buffer))
;; Find next match, but give up if prev match was at end of buffer.
(while (and (not (= prevpos (point-max)))
(re-search-forward regexp nil t))
- (beginning-of-line)
- (setq linenum (+ linenum (count-lines prevpos (point))))
- (setq prevpos (point))
+ (beginning-of-line 1)
+ (save-excursion
+ (setq linenum (+ linenum (count-lines prevpos (point))))
+ (setq prevpos (point)))
(let* ((start (save-excursion
(forward-line (if (< nlines 0) nlines (- nlines)))
(point)))
@@ -228,34 +207,21 @@ C-r to enter recursive edit (\\[exit-recursive-edit] to get out again),
C-w to delete match and recursive edit,
C-l to clear the screen, redisplay, and offer same replacement again,
! to replace all remaining matches with no more questions,
-^ to move point back to previous match."
+^ to move point back to previous match.
+
+Type a Space now to remove this message."
"Help message while in query-replace")
-(defun perform-replace (from-string replacements
- query-flag regexp-flag delimited-flag
- &optional repeat-count)
- "Subroutine of `query-replace'. Its complexity handles interactive queries.
-Don't use this in your own program unless you want to query and set the mark
-just as `query-replace' does. Instead, write a simple loop like this:
- (while (re-search-forward \"foo[ \t]+bar\" nil t)
- (replace-match \"foobar\" nil nil))
-which will run faster and do exactly what you probably want."
+(defun perform-replace (from-string to-string
+ query-flag regexp-flag delimited-flag)
(let ((nocasify (not (and case-fold-search case-replace
(string-equal from-string
(downcase from-string)))))
(literal (not regexp-flag))
(search-function (if regexp-flag 're-search-forward 'search-forward))
(search-string from-string)
- (next-replacement nil)
- (replacement-index 0)
(keep-going t)
- (stack nil)
- (next-rotate-count 0)
- (replace-count 0)
(lastrepl nil)) ;Position after last match considered.
- (if (stringp replacements)
- (setq next-replacement replacements)
- (or repeat-count (setq repeat-count 1)))
(if delimited-flag
(setq search-function 're-search-forward
search-string (concat "\\b"
@@ -263,137 +229,82 @@ which will run faster and do exactly what you probably want."
(regexp-quote from-string))
"\\b")))
(push-mark)
- (undo-boundary)
+ (push-mark)
(while (and keep-going
(not (eobp))
- (funcall search-function search-string nil t)
- (if (eq lastrepl (point))
- (progn
- ;; Don't replace the null string
- ;; right after end of previous replacement.
- (forward-char 1)
- (funcall search-function search-string nil t))
- t))
- ;; If time for a change, advance to next replacement string.
- (if (and (listp replacements)
- (= next-rotate-count replace-count))
- (progn
- (setq next-rotate-count
- (+ next-rotate-count repeat-count))
- (setq next-replacement (nth replacement-index replacements))
- (setq replacement-index (% (1+ replacement-index) (length replacements)))))
- (if (not query-flag)
- (progn
- (replace-match next-replacement nocasify literal)
- (setq replace-count (1+ replace-count)))
+ (progn
+ (set-mark (point))
+ (funcall search-function search-string nil t)))
+ ;; Don't replace the null string
+ ;; right after end of previous replacement.
+ (if (eq lastrepl (point))
+ (forward-char 1)
(undo-boundary)
- (let (done replaced)
- (while (not done)
- ;; Preserve the match data. Process filters and sentinels
- ;; could run inside read-char..
- (let ((data (match-data))
- (help-form
- '(concat "Query replacing "
- (if regexp-flag "regexp " "")
- from-string " with " next-replacement ".\n\n"
- (substitute-command-keys query-replace-help))))
- (setq char help-char)
- (while (or (not (numberp char)) (= char help-char))
- (message "Query replacing %s with %s: " from-string next-replacement)
- (setq char (read-event))
- (if (and (numberp char) (= char ??))
- (setq unread-command-char help-char char help-char)))
- (store-match-data data))
- (cond ((or (= char ?\e)
- (= char ?q))
- (setq keep-going nil)
- (setq done t))
- ((= char ?^)
- (let ((elt (car stack)))
- (goto-char (car elt))
- (setq replaced (eq t (cdr elt)))
+ (if (not query-flag)
+ (replace-match to-string nocasify literal)
+ (let (done replaced)
+ (while (not done)
+ ;; Preserve the match data. Process filters and sentinels
+ ;; could run inside read-char..
+ (let ((data (match-data))
+ (help-form
+ '(concat "Query replacing "
+ (if regexp-flag "regexp " "")
+ from-string " with " to-string ".\n\n"
+ (substitute-command-keys query-replace-help))))
+ (setq char help-char)
+ (while (= char help-char)
+ (message "Query replacing %s with %s: " from-string to-string)
+ (setq char (read-char))
+ (if (= char ??)
+ (setq unread-command-char help-char char help-char)))
+ (store-match-data data))
+ (cond ((or (= char ?\e)
+ (= char ?q))
+ (setq keep-going nil)
+ (setq done t))
+ ((= char ?^)
+ (goto-char (mark))
+ (setq replaced t))
+ ((or (= char ?\ )
+ (= char ?y))
(or replaced
- (store-match-data (cdr elt)))
- (setq stack (cdr stack))))
- ((or (= char ?\ )
- (= char ?y))
- (or replaced
- (replace-match next-replacement nocasify literal))
- (setq done t replaced t))
- ((= char ?\.)
- (or replaced
- (replace-match next-replacement nocasify literal))
- (setq keep-going nil)
- (setq done t replaced t))
- ((= char ?\,)
- (if (not replaced)
- (progn
- (replace-match next-replacement nocasify literal)
- (setq replaced t))))
- ((= char ?!)
- (or replaced
- (replace-match next-replacement nocasify literal))
- (setq done t query-flag nil replaced t))
- ((or (= char ?\177)
- (= char ?n))
- (setq done t))
- ((= char ?\C-l)
- (recenter nil))
- ((= char ?\C-r)
- (store-match-data
- (prog1 (match-data)
- (save-excursion (recursive-edit)))))
- ((= char ?\C-w)
- (delete-region (match-beginning 0) (match-end 0))
- (store-match-data
- (prog1 (match-data)
- (save-excursion (recursive-edit))))
- (setq replaced t))
- (t
- (setq keep-going nil)
- (setq unread-command-char char)
- (setq done t))))
- ;; Record previous position for ^ when we move on.
- ;; Change markers to numbers in the match data
- ;; since lots of markers slow down editing.
- (setq stack
- (cons (cons (point)
- (or replaced
- (mapcar
- (function (lambda (elt)
- (and elt
- (marker-position elt))))
- (match-data))))
- stack))
- (if replaced (setq replace-count (1+ replace-count)))))
- (setq lastrepl (point)))
- (and keep-going stack)))
-
-(defun map-query-replace-regexp (regexp to-strings &optional arg)
- "Replace some matches for REGEXP with various strings, in rotation.
-The second argument TO-STRINGS contains the replacement strings, separated
-by spaces. This command works like `query-replace-regexp' except
-that each successive replacement uses the next successive replacement string,
-wrapping around from the last such string to the first.
-
-Non-interactively, TO-STRINGS may be a list of replacement strings.
-
-A prefix argument N says to use each replacement string N times
-before rotating to the next."
- (interactive "sMap query replace (regexp): \nsQuery replace %s with (space-separated strings): \nP")
- (let (replacements)
- (if (listp to-strings)
- (setq replacements to-strings)
- (while (/= (length to-strings) 0)
- (if (string-match " " to-strings)
- (setq replacements
- (append replacements
- (list (substring to-strings 0
- (string-match " " to-strings))))
- to-strings (substring to-strings
- (1+ (string-match " " to-strings))))
- (setq replacements (append replacements (list to-strings))
- to-strings ""))))
- (perform-replace regexp replacements t t nil arg))
- (message "Done"))
+ (replace-match to-string nocasify literal))
+ (setq done t))
+ ((= char ?\.)
+ (or replaced
+ (replace-match to-string nocasify literal))
+ (setq keep-going nil)
+ (setq done t))
+ ((= char ?\,)
+ (if (not replaced)
+ (progn
+ (replace-match to-string nocasify literal)
+ (setq replaced t))))
+ ((= char ?!)
+ (or replaced
+ (replace-match to-string nocasify literal))
+ (setq done t query-flag nil))
+ ((or (= char ?\177)
+ (= char ?n))
+ (setq done t))
+ ((= char ?\C-l)
+ (recenter nil))
+ ((= char ?\C-r)
+ (store-match-data
+ (prog1 (match-data)
+ (save-excursion (recursive-edit)))))
+ ((= char ?\C-w)
+ (delete-region (match-beginning 0) (match-end 0))
+ (store-match-data
+ (prog1 (match-data)
+ (save-excursion (recursive-edit))))
+ (setq replaced t))
+ (t
+ (setq keep-going nil)
+ (setq unread-command-char char)
+ (setq done t))))))
+ (setq lastrepl (point))))
+ (pop-mark)
+ keep-going))
diff --git a/lisp/replace.elc b/lisp/replace.elc
new file mode 100644
index 00000000000..0b60b47d117
--- /dev/null
+++ b/lisp/replace.elc
Binary files differ
diff --git a/lisp/reposition.el b/lisp/reposition.el
deleted file mode 100644
index 104021a4432..00000000000
--- a/lisp/reposition.el
+++ /dev/null
@@ -1,185 +0,0 @@
-;;; -*- Mode: Emacs-lisp -*-
-;; Copyright (C) 1991 Free Software Foundation, Inc.
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 1, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
-;;; Written by Michael D. Ernst, mernst@theory.lcs.mit.edu, Jan 1991.
-
-;;; Reposition-window makes an entire function definition or comment visible,
-;;; or, if it is already visible, places it at the top of the window;
-;;; additional invocations toggle the visibility of comments preceding the
-;;; code. For the gory details, see the documentation for reposition-window;
-;;; rather than reading that, you may just want to play with it.
-
-;;; This tries pretty hard to do the recentering correctly; the precise
-;;; action depends on what the buffer looks like. If you find a situation
-;;; where it doesn't behave well, let me know. This function is modeled
-;;; after one of the same name in ZMACS, but the code is all-new and the
-;;; behavior in some situations differs.
-
-(defun reposition-window (&optional arg)
- "Make the current definition and/or comment visible.
-Further invocations move it to the top of the window or toggle the
-visibility of comments that precede it.
- Point is left unchanged unless prefix ARG is supplied.
- If the definition is fully onscreen, it is moved to the top of the
-window. If it is partly offscreen, the window is scrolled to get the
-definition (or as much as will fit) onscreen, unless point is in a comment
-which is also partly offscreen, in which case the scrolling attempts to get
-as much of the comment onscreen as possible.
- Initially `reposition-window' attempts to make both the definition and
-preceding comments visible. Further invocations toggle the visibility of
-the comment lines.
- If ARG is non-nil, point may move in order to make the whole defun
-visible (if only part could otherwise be made so), to make the defun line
-visible (if point is in code and it could not be made so, or if only
-comments, including the first comment line, are visible), or to make the
-first comment line visible (if point is in a comment)."
- (interactive "P")
- (let* (;; (here (save-excursion (beginning-of-line) (point)))
- (here (point))
- ;; change this name once I've gotten rid of references to ht.
- ;; this is actually the number of the last screen line
- (ht (- (window-height (selected-window)) 2))
- (line (repos-count-screen-lines (window-start) (point)))
- (comment-height
- ;; The call to max deals with the case of cursor between defuns.
- (max 0
- (repos-count-screen-lines-signed
- ;; the beginning of the preceding comment
- (save-excursion
- (forward-char 1) (end-of-defun -1)
- ;; Skip whitespace, newlines, and form feeds.
- (re-search-forward "[^\\s \n\014]")
- (backward-char 1)
- (point))
- here)))
- (defun-height
- (repos-count-screen-lines-signed
- (save-excursion
- (end-of-defun 1) ; so comments associate with following defuns
- (beginning-of-defun 1)
- (point))
- here))
- ;; This must be positive, so don't use the signed version.
- (defun-depth (repos-count-screen-lines here
- (save-excursion
- (end-of-defun 1)
- (point))))
- (defun-line-onscreen-p
- (and (<= defun-height line)
- (<= (- line defun-height) ht))))
- (cond ((or (= comment-height line)
- (and (= line ht)
- (> comment-height line)
- ;; if defun line offscreen, we should be in case 4
- defun-line-onscreen-p))
- ;; Either first comment line is at top of screen or (point at
- ;; bottom of screen, defun line onscreen, and first comment line
- ;; off top of screen). That is, it looks like we just did
- ;; recenter-definition, trying to fit as much of the comment
- ;; onscreen as possible. Put defun line at top of screen; that
- ;; is, show as much code, and as few comments, as possible.
-
- (if (and arg (> defun-depth (1+ ht)))
- ;; Can't fit whole defun onscreen without moving point.
- (progn (end-of-defun) (beginning-of-defun) (recenter 0))
- (recenter (max defun-height 0)))
- ;;(repos-debug-macro "1")
- )
-
- ((or (= defun-height line)
- (= line 0)
- (and (< line comment-height)
- (< defun-height 0)))
- ;; Defun line or cursor at top of screen, OR cursor in comment
- ;; whose first line is offscreen.
- ;; Avoid moving definition up even if defun runs offscreen;
- ;; we care more about getting the comment onscreen.
-
- (cond ((= line ht)
- ;; cursor on last screen line (and so in a comment)
- (if arg (progn (end-of-defun) (beginning-of-defun)))
- (recenter 0)
- ;;(repos-debug-macro "2a")
- )
-
- ;; This condition, copied from case 4, may not be quite right
-
- ((and arg (< ht comment-height))
- ;; Can't get first comment line onscreen.
- ;; Go there and try again.
- (forward-line (- comment-height))
- (beginning-of-line)
- ;; was (reposition-window)
- (recenter 0)
- ;;(repos-debug-macro "2b")
- )
- (t
- (recenter (min ht comment-height))
- ;;(repos-debug-macro "2c")
- ))
- ;; (recenter (min ht comment-height))
- )
-
- ((and (> (+ line defun-depth -1) ht)
- defun-line-onscreen-p)
- ;; Defun runs off the bottom of the screen and the defun line
- ;; is onscreen.
- ;; Move the defun up.
- (recenter (max 0 (1+ (- ht defun-depth)) defun-height))
- ;;(repos-debug-macro "3")
- )
-
- (t
- ;; If on the bottom line and comment start is offscreen
- ;; then just move all comments offscreen, or at least as
- ;; far as they'll go.
-
- ;; Try to get as much of the comments onscreen as possible.
- (if (and arg (< ht comment-height))
- ;; Can't get defun line onscreen; go there and try again.
- (progn (forward-line (- defun-height))
- (beginning-of-line)
- (reposition-window))
- (recenter (min ht comment-height)))
- ;;(repos-debug-macro "4")
- ))))
-
-;;; Auxiliary functions
-
-;; Return number of screen lines between START and END.
-(defun repos-count-screen-lines (start end)
- (save-excursion
- (save-restriction
- (narrow-to-region start end)
- (goto-char (point-min))
- (vertical-motion (- (point-max) (point-min))))))
-
-;; Return number of screen lines between START and END; returns a negative
-;; number if END precedes START.
-(defun repos-count-screen-lines-signed (start end)
- (let ((lines (repos-count-screen-lines start end)))
- (if (< start end)
- lines
- (- lines))))
-
-; (defmacro repos-debug-macro (case-no)
-; (` (message
-; (concat "Case " (, case-no) ": %s %s %s %s %s")
-; ht line comment-height defun-height defun-depth)))
-
diff --git a/lisp/resume.el b/lisp/resume.el
deleted file mode 100644
index 86866c12763..00000000000
--- a/lisp/resume.el
+++ /dev/null
@@ -1,160 +0,0 @@
-;; Process command line arguments from within a suspended Emacs job
-;; Copyright (C) 1988 Free Software Foundation, Inc.
-
-;; This file is not yet part of GNU Emacs, but soon will be.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY. No author or distributor
-;; accepts responsibility to anyone for the consequences of using it
-;; or for whether it serves any particular purpose or works at all,
-;; unless he says so in writing. Refer to the GNU Emacs General Public
-;; License for full details.
-
-;; Everyone is granted permission to copy, modify and redistribute
-;; GNU Emacs, but only under the conditions described in the
-;; GNU Emacs General Public License. A copy of this license is
-;; supposed to have been given to you along with GNU Emacs so you
-;; can know your rights and responsibilities. It should be in a
-;; file named COPYING. Among other things, the copyright notice
-;; and this notice must be preserved on all copies.
-
-;; Created by: Joe Wells, jbw@bucsf.bu.edu
-;; Created on: 1988?
-;; Last modified by: Joe Wells, jbw@dodge
-;; Last modified on: Thu Jun 14 15:20:41 1990
-;; Filename: resume.el
-;; Purpose: handle command line arguments when resuming suspended job
-
-;; Stephen Gildea suggested bug fix (gildea@bbn.com).
-;; Ideas from Michael DeCorte and other people.
-
-;; For csh users, insert the following alias in your .cshrc file
-;; (after removing the leading double semicolons, of course):
-;;
-;;# The following line could be just EMACS_CMD=emacs, but this depends on
-;;# your site.
-;;if (! $?EMACS_CMD) set EMACS_CMD=emacs
-;;set JOBS_FILE=/tmp/jobs.$USER.$$
-;;set ARGS_FILE=~/.emacs_args
-;;set STOP_PATT='^\[[0-9]*\] *[ +-] Stopped ............ '
-;;set SUNVIEW_CMD='emacstool -nw -f emacstool-init -f server-start'
-;;set X_CMD=\'\''$EMACS_CMD -i -f server-start'
-;;alias emacs \
-;;' \\
-;; jobs >! "$JOBS_FILE" \\
-;; && grep "$STOP_PATT$EMACS_CMD" "$JOBS_FILE" >& /dev/null \\
-;; && echo `pwd` \!* >! "$ARGS_FILE" && ""fg %$EMACS_CMD \\
-;;|| if (! -e ~/.emacs_server || -f ~/.emacs_server) set status=1 \\
-;; && emacsclient \!* \\
-;;|| @ status=1 - $?DISPLAY && eval "$X_CMD -i \!* &" \\
-;;|| @ status=1 - $?WINDOW_PARENT && eval "$SUNVIEW_CMD \!* &" \\
-;;|| ""$EMACS_CMD -nw \!* \\
-;;'
-;;
-;; The alias works as follows:
-;; 1. If there is a suspended Emacs job that is a child of the
-;; current shell, place its arguments in the ~/.emacs_args file and
-;; resume it.
-;; 2. Else if the ~/.emacs_server socket has been created, presume an
-;; Emacs server is running and attempt to connect to it. If no Emacs
-;; server is listening on the socket, this will fail.
-;; 3. Else if the DISPLAY environment variable is set, presume we are
-;; running under X Windows and start a new GNU Emacs process in the
-;; background as an X client.
-;; 4. Else if the WINDOW_PARENT environment variable is set, presume we
-;; are running under SunView and start an emacstool process in the
-;; background.
-;; 5. Else start a regular Emacs process.
-;;
-;; Notes:
-;; The output of the "jobs" command is not piped directly into "grep"
-;; because that would run the "jobs" command in a subshell.
-;; Before resuming a suspended emacs, the current directory and all
-;; command line arguments are placed in a file name ~/.emacs_args.
-;; The "-nw" switch to Emacs means no windowing system.
-
-;; Insert this in your .emacs file:
-;;(setq suspend-resume-hook 'resume-process-args)
-;;(setq suspend-hook 'empty-args-file)
-;;(autoload 'empty-args-file "resume")
-;;(autoload 'resume-process-args "resume")
-
-;; Finally, put the rest in a file named "resume.el" in a lisp library
-;; directory.
-
-(defvar emacs-args-file (expand-file-name "~/.emacs_args")
- "*This file is where arguments are placed for a suspended emacs job.")
-
-(defvar emacs-args-buffer " *Command Line Args*"
- "Buffer that is used by resume-process-args.")
-
-(defun resume-process-args ()
- "This should be called from inside of suspend-resume-hook. This
-grabs the contents of the file whose name is stored in
-emacs-args-file, and processes these arguments like command line
-options."
- (let ((start-buffer (current-buffer))
- (args-buffer (get-buffer-create emacs-args-buffer))
- length args)
- (unwind-protect
- (progn
- (set-buffer args-buffer)
- (erase-buffer)
- ;; get the contents of emacs-args-file
- (condition-case ()
- (let ((result (insert-file-contents emacs-args-file)))
- (setq length (car (cdr result))))
- ;; the file doesn't exist, ergo no arguments
- (file-error
- (erase-buffer)
- (setq length 0)))
- (if (<= length 0)
- (setq args nil)
- ;; get the arguments from the buffer
- (goto-char (point-min))
- (while (not (eobp))
- (skip-chars-forward " \t\n")
- (let ((begin (point)))
- (skip-chars-forward "^ \t\n")
- (setq args (cons (buffer-substring begin (point)) args)))
- (skip-chars-forward " \t\n"))
- ;; arguments are now in reverse order
- (setq args (nreverse args))
- ;; make sure they're not read again
- (erase-buffer))
- (write-buffer-to-file (current-buffer) emacs-args-file)
- ;; if nothing was in buffer, args will be null
- (or (null args)
- (setq default-directory (file-name-as-directory (car args))
- args (cdr args)))
- ;; actually process the arguments
- (command-line-1 args))
- ;; If the command line args don't result in a find-file, the
- ;; buffer will be left in args-buffer. So we change back to the
- ;; original buffer. The reason I don't just use
- ;; (let ((default-directory foo))
- ;; (command-line-1 args))
- ;; in the context of the original buffer is because let does not
- ;; work properly with buffer-local variables.
- (if (eq (current-buffer) args-buffer)
- (set-buffer start-buffer)))))
-
-(defun empty-args-file ()
- "This empties the contents of the file whose name is specified by
-emacs-args-file."
- (save-excursion
- (set-buffer (get-buffer-create emacs-args-buffer))
- (erase-buffer)
- (write-buffer-to-file (current-buffer) emacs-args-file)))
-
-(defun write-buffer-to-file (buffer file)
- "Writes the contents of BUFFER into FILE, if permissions allow."
- (if (not (file-writable-p file))
- (error "No permission to write file %s" file))
- (save-excursion
- (set-buffer buffer)
- (clear-visited-file-modtime)
- (save-restriction
- (widen)
- (write-region (point-min) (point-max) file nil 'quiet))
- (set-buffer-modified-p nil)))
diff --git a/lisp/mail/rfc822.el b/lisp/rfc822.el
index b7e43f62cda..18cf3c96987 100644
--- a/lisp/mail/rfc822.el
+++ b/lisp/rfc822.el
@@ -1,5 +1,5 @@
;; Hairy rfc822 parser for mail and news and suchlike
-;; Copyright (C) 1986-1990 Free Software Foundation, Inc.
+;; Copyright (C) 1986, 1987 Free Software Foundation, Inc.
;; Author Richard Mlynarik.
;; This file is part of GNU Emacs.
@@ -303,4 +303,3 @@
(setq list (nconc (nreverse tem) list)))))
(nreverse list)))
(and buf (kill-buffer buf))))))
-
diff --git a/lisp/rfc822.elc b/lisp/rfc822.elc
new file mode 100644
index 00000000000..099f39919b2
--- /dev/null
+++ b/lisp/rfc822.elc
Binary files differ
diff --git a/lisp/rmail.el b/lisp/rmail.el
new file mode 100644
index 00000000000..54547042b5f
--- /dev/null
+++ b/lisp/rmail.el
@@ -0,0 +1,1433 @@
+;; "RMAIL" mail reader for Emacs.
+;; Copyright (C) 1985, 1986, 1987, 1988, 1990, 1992 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 1, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+;; Souped up by shane@mit-ajax based on ideas of rlk@athena.mit.edu
+;; New features include attribute and keyword support, message
+;; selection by dispatch table, summary by attributes and keywords,
+;; expunging by dispatch table, sticky options for file commands.
+
+(require 'mail-utils)
+(provide 'rmail)
+
+; these variables now declared in loaddefs or paths.el
+;(defvar rmail-spool-directory "/usr/spool/mail/"
+; "This is the name of the directory used by the system mailer for\n\
+;delivering new mail. It's name should end with a slash.")
+;(defvar rmail-dont-reply-to-names
+; nil
+; "*A regexp specifying names to prune of reply to messages.
+;nil means dont reply to yourself.")
+;(defvar rmail-ignored-headers
+; "^via:\\|^mail-from:\\|^origin:\\|^status:\\|^received:\\|^message-id:\\|^summary-line:"
+; "*Gubbish headers one would rather not see.")
+;(defvar rmail-file-name
+; (expand-file-name "~/RMAIL")
+; "")
+;
+;(defvar rmail-delete-after-output nil
+; "*Non-nil means automatically delete a message that is copied to a file.")
+;
+;(defvar rmail-primary-inbox-list
+; '("/usr/spool/mail/$USER" "~/mbox")
+; "")
+
+;; these may be altered by site-init.el to match the format of mmdf files
+;; delimitation used on a given host (delim1 and delim2 from the config
+;; files)
+
+(defvar mmdf-delim1 "^\001\001\001\001\n"
+ "Regexp marking the start of an mmdf message")
+(defvar mmdf-delim2 "^\001\001\001\001\n"
+ "Regexp marking the end of an mmdf message")
+
+(defvar rmail-message-filter nil
+ "If non nil, is a filter function for new headers in RMAIL.
+Called with region narrowed to unformatted header.")
+
+(defvar rmail-mode-map nil)
+
+;; Message counters and markers. Deleted flags.
+
+(defvar rmail-current-message nil)
+(defvar rmail-total-messages nil)
+(defvar rmail-message-vector nil)
+(defvar rmail-deleted-vector nil)
+
+;; These are used by autoloaded rmail-summary.
+
+(defvar rmail-summary-buffer nil)
+(defvar rmail-summary-vector nil)
+
+;; `Sticky' default variables.
+
+;; Last individual label specified to a or k.
+(defvar rmail-last-label nil)
+;; Last set of labels specified to C-M-n or C-M-p or C-M-l.
+(defvar rmail-last-multi-labels nil)
+(defvar rmail-last-file nil)
+(defvar rmail-last-rmail-file nil)
+
+;; Regexp matching the delimiter of messages in UNIX mail format
+;; (UNIX From lines). This is often used with ^ added on the front.
+(defvar rmail-unix-mail-delimiter
+ "From \\([^ \n]*\\(\\|\".*\"[^ \n]*\\)\\) ?\\([^ \n]*\\) \\([^ ]*\\) *\\([0-9]*\\) \\([0-9:]*\\)\\( ?[A-Z]?[A-Z][A-Z]T\\( DST\\)?\\| ?[-+]?[0-9][0-9][0-9][0-9]\\|\\) 19\\([0-9]*\\) *\\(remote from [^\n]*\\)?\n")
+
+;;;; *** Rmail Mode ***
+
+(defun rmail (&optional file-name-arg)
+ "Read and edit incoming mail.
+Moves messages into file named by rmail-file-name (a babyl format file)
+ and edits that file in RMAIL Mode.
+Type \\[describe-mode] once editing that file, for a list of RMAIL commands.
+
+May be called with filename as argument;
+then performs rmail editing on that file,
+but does not copy any new mail into the file."
+ (interactive (if current-prefix-arg
+ (list (read-file-name "Run rmail on RMAIL file: "
+ nil nil t))))
+ (or rmail-last-file
+ (setq rmail-last-file (expand-file-name "~/xmail")))
+ (or rmail-last-rmail-file
+ (setq rmail-last-rmail-file (expand-file-name "~/XMAIL")))
+ (let* ((file-name (expand-file-name (or file-name-arg rmail-file-name)))
+ (existed (get-file-buffer file-name))
+ ;; Don't be confused by apparent local-variables spec
+ ;; in the last message in the RMAIL file.
+ (inhibit-local-variables t))
+ ;; Like find-file, but in the case where a buffer existed
+ ;; and the file was reverted, recompute the message-data.
+ (if (and existed (not (verify-visited-file-modtime existed)))
+ (progn
+ (find-file file-name)
+ (if (and (verify-visited-file-modtime existed)
+ (eq major-mode 'rmail-mode))
+ (progn (rmail-forget-messages)
+ (rmail-set-message-counters))))
+ (find-file file-name))
+ (if (eq major-mode 'rmail-edit-mode)
+ (error "exit rmail-edit-mode before getting new mail"))
+ (if (and existed (eq major-mode 'rmail-mode))
+ nil
+ (rmail-mode)
+ ;; Provide default set of inboxes for primary mail file ~/RMAIL.
+ (and (null rmail-inbox-list)
+ (null file-name-arg)
+ (setq rmail-inbox-list
+ (or rmail-primary-inbox-list
+ (list "~/mbox"
+ (concat rmail-spool-directory
+ (or (getenv "LOGNAME")
+ (getenv "USER")
+ (user-login-name)))))))
+ ;; Convert all or part to Babyl file if possible.
+ (rmail-convert-file)
+ (goto-char (point-max))
+ (if (null rmail-inbox-list)
+ (progn
+ (rmail-set-message-counters)
+ (rmail-show-message))))
+ (rmail-get-new-mail)))
+
+(defun rmail-convert-file ()
+ (let (convert)
+ (widen)
+ (goto-char (point-min))
+ ;; If file doesn't start like a Babyl file,
+ ;; convert it to one, by adding a header and converting each message.
+ (cond ((looking-at "BABYL OPTIONS:"))
+ ((looking-at "Version: 5\n")
+ ;; Losing babyl file made by old version of Rmail.
+ ;; Just fix the babyl file header; don't make a new one,
+ ;; so we don't lose the Labels: file attribute, etc.
+ (let ((buffer-read-only nil))
+ (insert "BABYL OPTIONS:\n")))
+ (t
+ (setq convert t)
+ (rmail-insert-rmail-file-header)))
+ ;; If file was not a Babyl file or if there are
+ ;; Unix format messages added at the end,
+ ;; convert file as necessary.
+ (if (or convert
+ (progn (goto-char (point-max))
+ (search-backward "\^_")
+ (forward-char 1)
+ (looking-at "\n*From ")))
+ (let ((buffer-read-only nil))
+ (message "Converting to Babyl format...")
+ (narrow-to-region (point) (point-max))
+ (rmail-convert-to-babyl-format)
+ (message "Converting to Babyl format...done")))))
+
+(defun rmail-insert-rmail-file-header ()
+ (let ((buffer-read-only nil))
+ (insert "BABYL OPTIONS:
+Version: 5
+Labels:
+Note: This is the header of an rmail file.
+Note: If you are seeing it in rmail,
+Note: it means the file has no messages in it.\n\^_")))
+
+(if rmail-mode-map
+ nil
+ (setq rmail-mode-map (make-keymap))
+ (suppress-keymap rmail-mode-map)
+ (define-key rmail-mode-map "." 'rmail-beginning-of-message)
+ (define-key rmail-mode-map " " 'scroll-up)
+ (define-key rmail-mode-map "\177" 'scroll-down)
+ (define-key rmail-mode-map "n" 'rmail-next-undeleted-message)
+ (define-key rmail-mode-map "p" 'rmail-previous-undeleted-message)
+ (define-key rmail-mode-map "\en" 'rmail-next-message)
+ (define-key rmail-mode-map "\ep" 'rmail-previous-message)
+ (define-key rmail-mode-map "\e\C-n" 'rmail-next-labeled-message)
+ (define-key rmail-mode-map "\e\C-p" 'rmail-previous-labeled-message)
+ (define-key rmail-mode-map "a" 'rmail-add-label)
+ (define-key rmail-mode-map "k" 'rmail-kill-label)
+ (define-key rmail-mode-map "d" 'rmail-delete-forward)
+ (define-key rmail-mode-map "u" 'rmail-undelete-previous-message)
+ (define-key rmail-mode-map "e" 'rmail-expunge)
+ (define-key rmail-mode-map "x" 'rmail-expunge)
+ (define-key rmail-mode-map "s" 'rmail-expunge-and-save)
+ (define-key rmail-mode-map "g" 'rmail-get-new-mail)
+ (define-key rmail-mode-map "h" 'rmail-summary)
+ (define-key rmail-mode-map "\e\C-h" 'rmail-summary)
+ (define-key rmail-mode-map "l" 'rmail-summary-by-labels)
+ (define-key rmail-mode-map "\e\C-l" 'rmail-summary-by-labels)
+ (define-key rmail-mode-map "\e\C-r" 'rmail-summary-by-recipients)
+ (define-key rmail-mode-map "t" 'rmail-toggle-header)
+ (define-key rmail-mode-map "m" 'rmail-mail)
+ (define-key rmail-mode-map "r" 'rmail-reply)
+ (define-key rmail-mode-map "c" 'rmail-continue)
+ (define-key rmail-mode-map "f" 'rmail-forward)
+ (define-key rmail-mode-map "\es" 'rmail-search)
+ (define-key rmail-mode-map "j" 'rmail-show-message)
+ (define-key rmail-mode-map "o" 'rmail-output-to-rmail-file)
+ (define-key rmail-mode-map "\C-o" 'rmail-output)
+ (define-key rmail-mode-map "i" 'rmail-input)
+ (define-key rmail-mode-map "q" 'rmail-quit)
+ (define-key rmail-mode-map ">" 'rmail-last-message)
+ (define-key rmail-mode-map "?" 'describe-mode)
+ (define-key rmail-mode-map "w" 'rmail-edit-current-message)
+ (define-key rmail-mode-map "\C-d" 'rmail-delete-backward))
+
+;; Rmail mode is suitable only for specially formatted data.
+(put 'rmail-mode 'mode-class 'special)
+
+(defun rmail-mode ()
+ "Rmail Mode is used by \\[rmail] for editing Rmail files.
+All normal editing commands are turned off.
+Instead, these commands are available:
+
+. Move point to front of this message (same as \\[beginning-of-buffer]).
+SPC Scroll to next screen of this message.
+DEL Scroll to previous screen of this message.
+n Move to Next non-deleted message.
+p Move to Previous non-deleted message.
+M-n Move to Next message whether deleted or not.
+M-p Move to Previous message whether deleted or not.
+> Move to the last message in Rmail file.
+j Jump to message specified by numeric position in file.
+M-s Search for string and show message it is found in.
+d Delete this message, move to next nondeleted.
+C-d Delete this message, move to previous nondeleted.
+u Undelete message. Tries current message, then earlier messages
+ till a deleted message is found.
+e Expunge deleted messages.
+s Expunge and save the file.
+q Quit Rmail: expunge, save, then switch to another buffer.
+C-x C-s Save without expunging.
+g Move new mail from system spool directory or mbox into this file.
+m Mail a message (same as \\[mail-other-window]).
+c Continue composing outgoing message started before.
+r Reply to this message. Like m but initializes some fields.
+f Forward this message to another user.
+o Output this message to an Rmail file (append it).
+C-o Output this message to a Unix-format mail file (append it).
+i Input Rmail file. Run Rmail on that file.
+a Add label to message. It will be displayed in the mode line.
+k Kill label. Remove a label from current message.
+C-M-n Move to Next message with specified label
+ (label defaults to last one specified).
+ Standard labels: filed, unseen, answered, forwarded, deleted.
+ Any other label is present only if you add it with `a'.
+C-M-p Move to Previous message with specified label
+C-M-h Show headers buffer, with a one line summary of each message.
+C-M-l Like h only just messages with particular label(s) are summarized.
+C-M-r Like h only just messages with particular recipient(s) are summarized.
+t Toggle header, show Rmail header if unformatted or vice versa.
+w Edit the current message. C-c C-c to return to Rmail."
+ (interactive)
+ (kill-all-local-variables)
+ (rmail-mode-1)
+ (rmail-variables)
+ (run-hooks 'rmail-mode-hook))
+
+(defun rmail-mode-1 ()
+ (setq major-mode 'rmail-mode)
+ (setq mode-name "RMAIL")
+ (setq buffer-read-only t)
+ ;; No need to auto save RMAIL files.
+ (setq buffer-auto-save-file-name nil)
+ (if (boundp 'mode-line-modified)
+ (setq mode-line-modified "--- ")
+ (setq mode-line-format
+ (cons "--- " (cdr (default-value 'mode-line-format)))))
+ (use-local-map rmail-mode-map)
+ (set-syntax-table text-mode-syntax-table)
+ (setq local-abbrev-table text-mode-abbrev-table))
+
+(defun rmail-variables ()
+ (make-local-variable 'revert-buffer-function)
+ (setq revert-buffer-function 'rmail-revert)
+ (make-local-variable 'rmail-last-label)
+ (make-local-variable 'rmail-deleted-vector)
+ (make-local-variable 'rmail-keywords)
+ (make-local-variable 'rmail-summary-buffer)
+ (make-local-variable 'rmail-summary-vector)
+ (make-local-variable 'rmail-current-message)
+ (make-local-variable 'rmail-total-messages)
+ (make-local-variable 'require-final-newline)
+ (setq require-final-newline nil)
+ (make-local-variable 'version-control)
+ (setq version-control 'never)
+ (make-local-variable 'file-precious-flag)
+ (setq file-precious-flag t)
+ (make-local-variable 'rmail-message-vector)
+ (make-local-variable 'rmail-last-file)
+ (make-local-variable 'rmail-inbox-list)
+ (setq rmail-inbox-list (rmail-parse-file-inboxes))
+ (make-local-variable 'rmail-keywords)
+ ;; this gets generated as needed
+ (setq rmail-keywords nil))
+
+;; Handle M-x revert-buffer done in an rmail-mode buffer.
+(defun rmail-revert (arg noconfirm)
+ (let (revert-buffer-function)
+ ;; Call our caller again, but this time it does the default thing.
+ (if (revert-buffer arg noconfirm)
+ ;; If the user said "yes", and we changed something,
+ ;; reparse the messages.
+ (progn
+ (rmail-convert-file)
+ (goto-char (point-max))
+ (rmail-set-message-counters)
+ (rmail-show-message)))))
+
+;; Return a list of files from this buffer's Mail: option.
+;; Does not assume that messages have been parsed.
+;; Just returns nil if buffer does not look like Babyl format.
+(defun rmail-parse-file-inboxes ()
+ (save-excursion
+ (save-restriction
+ (widen)
+ (goto-char 1)
+ (cond ((looking-at "BABYL OPTIONS:")
+ (search-forward "\^_" nil 'move)
+ (narrow-to-region 1 (point))
+ (goto-char 1)
+ (if (search-forward "\nMail:" nil t)
+ (progn
+ (narrow-to-region (point) (progn (end-of-line) (point)))
+ (goto-char (point-min))
+ (mail-parse-comma-list))))))))
+
+(defun rmail-expunge-and-save ()
+ "Expunge and save RMAIL file."
+ (interactive)
+ (rmail-expunge)
+ (save-buffer))
+
+(defun rmail-quit ()
+ "Quit out of RMAIL."
+ (interactive)
+ (rmail-expunge-and-save)
+ ;; Don't switch to the summary buffer even if it was recently visible.
+ (if rmail-summary-buffer
+ (bury-buffer rmail-summary-buffer))
+ (let ((obuf (current-buffer)))
+ (switch-to-buffer (other-buffer))
+ (bury-buffer obuf)))
+
+(defun rmail-input (filename)
+ "Run RMAIL on file FILENAME."
+ (interactive "FRun rmail on RMAIL file: ")
+ (rmail filename))
+
+
+;;;; *** Rmail input ***
+
+;; RLK feature not added in this version:
+;; argument specifies inbox file or files in various ways.
+
+(defun rmail-get-new-mail (&optional file-name)
+ "Move any new mail from this RMAIL file's inbox files.
+The inbox files can be specified with the file's Mail: option.
+The variable rmail-primary-inbox-list specifies the inboxes for
+your primary RMAIL file if it has no Mail: option.
+These are normally your ~/mbox and your /usr/spool/mail/$USER.
+
+You can also specify the file to get new mail from. In this
+case, the file of new mail is not changed or deleted.
+Noninteractively, you can pass the inbox file name as an argument.
+Interactively, a prefix argument causes us to read a file name
+and use that file as the inbox."
+ (interactive
+ (list (if current-prefix-arg
+ (read-file-name "Get new mail from file: "))))
+ (or (verify-visited-file-modtime (current-buffer))
+ (progn
+ (find-file (buffer-file-name))
+ (if (verify-visited-file-modtime (current-buffer))
+ (rmail-forget-messages))))
+ (rmail-maybe-set-message-counters)
+ (widen)
+ ;; Get rid of all undo records for this buffer.
+ (or (eq buffer-undo-list t)
+ (setq buffer-undo-list nil))
+ (unwind-protect
+ (let ((opoint (point))
+ (new-messages 0)
+ (delete-files ())
+ ;; If buffer has not changed yet, and has not been saved yet,
+ ;; don't replace the old backup file now.
+ (make-backup-files (and make-backup-files (buffer-modified-p)))
+ (buffer-read-only nil)
+ ;; Don't make undo records for what we do in getting mail.
+ (buffer-undo-list t))
+ (goto-char (point-max))
+ (skip-chars-backward " \t\n") ; just in case of brain damage
+ (delete-region (point) (point-max)) ; caused by require-final-newline
+ (save-excursion
+ (save-restriction
+ (narrow-to-region (point) (point))
+ ;; Read in the contents of the inbox files,
+ ;; renaming them as necessary,
+ ;; and adding to the list of files to delete eventually.
+ (if file-name
+ (rmail-insert-inbox-text (list file-name) nil)
+ (setq delete-files (rmail-insert-inbox-text rmail-inbox-list t)))
+ ;; Scan the new text and convert each message to babyl format.
+ (goto-char (point-min))
+ (save-excursion
+ (setq new-messages (rmail-convert-to-babyl-format)))
+ (or (zerop new-messages)
+ (let (success)
+ (widen)
+ (search-backward "\^_")
+ (narrow-to-region (point) (point-max))
+ (goto-char (1+ (point-min)))
+ (rmail-count-new-messages)
+ (save-buffer)))
+ ;; Delete the old files, now that babyl file is saved.
+ (while delete-files
+ (condition-case ()
+ ;; First, try deleting.
+ (condition-case ()
+ (delete-file (car delete-files))
+ (file-error
+ ;; If we can't delete it, truncate it.
+ (write-region (point) (point) (car delete-files))))
+ (file-error nil))
+ (setq delete-files (cdr delete-files)))))
+ (if (= new-messages 0)
+ (progn (goto-char opoint)
+ (if (or file-name rmail-inbox-list)
+ (message "(No new mail has arrived)")))
+ (message "%d new message%s read"
+ new-messages (if (= 1 new-messages) "" "s"))))
+ ;; Don't leave the buffer screwed up if we get a disk-full error.
+ (rmail-show-message)))
+
+(defun rmail-insert-inbox-text (files renamep)
+ (let (file tofile delete-files movemail popmail)
+ (while files
+ (setq file (expand-file-name (substitute-in-file-name (car files)))
+ ;;>> un*x specific <<
+ tofile (concat file "~"))
+ ;; If getting from mail spool directory,
+ ;; use movemail to move rather than renaming.
+ (setq movemail (equal (file-name-directory file) rmail-spool-directory))
+ (setq popmail (string-match "^po:" (file-name-nondirectory file)))
+ (if popmail (setq file (file-name-nondirectory file)
+ renamep t))
+ (if movemail
+ (progn
+ (setq tofile (expand-file-name
+ ".newmail"
+ ;; Use the directory of this rmail file
+ ;; because it's a nuisance to use the homedir
+ ;; if that is on a full disk and this rmail
+ ;; file isn't.
+ (file-name-directory
+ (expand-file-name buffer-file-name))))
+ ;; On some systems, /usr/spool/mail/foo is a directory
+ ;; and the actual inbox is /usr/spool/mail/foo/foo.
+ (if (file-directory-p file)
+ (setq file (expand-file-name (or (getenv "LOGNAME")
+ (getenv "USER")
+ (user-login-name))
+ file)))))
+ (if popmail
+ (message "Getting mail from post office ...")
+ (if (or (file-exists-p tofile) (file-exists-p file))
+ (message "Getting mail from %s..." file)))
+ ;; Set TOFILE if have not already done so, and
+ ;; rename or copy the file FILE to TOFILE if and as appropriate.
+ (cond ((not renamep)
+ (setq tofile file))
+ ((or (file-exists-p tofile) (and (not popmail)
+ (not (file-exists-p file))))
+ nil)
+ ((and (not movemail) (not popmail))
+ (rename-file file tofile nil)
+ ;; Make the real inbox file empty.
+ ;; Leaving it deleted could cause lossage
+ ;; because mailers often won't create the file.
+ (condition-case ()
+ (write-region (point) (point) file)
+ (file-error nil)))
+ (t
+ (let ((errors nil))
+ (unwind-protect
+ (save-excursion
+ (setq errors (generate-new-buffer " *rmail loss*"))
+ (buffer-flush-undo errors)
+ (call-process
+ (expand-file-name "movemail" exec-directory)
+ nil errors nil file tofile)
+ (if (not (buffer-modified-p errors))
+ ;; No output => movemail won
+ nil
+ (set-buffer errors)
+ (subst-char-in-region (point-min) (point-max)
+ ?\n ?\ )
+ (goto-char (point-max))
+ (skip-chars-backward " \t")
+ (delete-region (point) (point-max))
+ (goto-char (point-min))
+ (if (looking-at "movemail: ")
+ (delete-region (point-min) (match-end 0)))
+ (beep t)
+ (message (concat "movemail: "
+ (buffer-substring (point-min)
+ (point-max))))
+ (sit-for 3)
+ nil))
+ (if errors (kill-buffer errors))))))
+ ;; At this point, TOFILE contains the name to read:
+ ;; Either the alternate name (if we renamed)
+ ;; or the actual inbox (if not renaming).
+ (if (file-exists-p tofile)
+ (let ((omax (point-max)))
+ (goto-char (point-max))
+ (insert-file-contents tofile)
+ (goto-char (point-max))
+ (or (= (preceding-char) ?\n)
+ (= opoint (point-max))
+ (insert ?\n))
+ (setq delete-files (cons tofile delete-files))))
+ (message "")
+ (setq files (cdr files)))
+ delete-files))
+
+;; the rmail-break-forwarded-messages feature is not implemented
+(defun rmail-convert-to-babyl-format ()
+ (let ((count 0) start
+ (case-fold-search nil))
+ (goto-char (point-min))
+ (save-restriction
+ (while (not (eobp))
+ (cond ((looking-at "BABYL OPTIONS:");Babyl header
+ (search-forward "\n\^_")
+ (delete-region (point-min) (point)))
+ ;; Babyl format message
+ ((looking-at "\^L")
+ (or (search-forward "\n\^_" nil t)
+ (progn
+ (message "Invalid Babyl format in inbox!")
+ (sit-for 1)
+ (goto-char (point-max))))
+ (setq count (1+ count))
+ ;; Make sure there is no extra white space after the ^_
+ ;; at the end of the message.
+ ;; Narrowing will make sure that whatever follows the junk
+ ;; will be treated properly.
+ (delete-region (point)
+ (save-excursion
+ (skip-chars-forward " \t\n")
+ (point)))
+ (narrow-to-region (point) (point-max)))
+ ;;*** MMDF format
+ ((let ((case-fold-search t))
+ (looking-at mmdf-delim1))
+ (let ((case-fold-search t))
+ (replace-match "\^L\n0, unseen,,\n*** EOOH ***\n")
+ (setq start (point))
+ (re-search-forward mmdf-delim2 nil t)
+ (replace-match "\^_"))
+ (save-excursion
+ (save-restriction
+ (narrow-to-region start (1- (point)))
+ (goto-char (point-min))
+ (while (search-forward "\n\^_" nil t) ; single char "\^_"
+ (replace-match "\n^_")))) ; 2 chars: "^" and "_"
+ (narrow-to-region (point) (point-max))
+ (setq count (1+ count)))
+ ;;*** Mail format
+ ((looking-at "^From ")
+ (setq start (point))
+ (insert "\^L\n0, unseen,,\n*** EOOH ***\n")
+ (rmail-nuke-pinhead-header)
+ ;; If this message has a Content-Length field,
+ ;; skip to the end of the contents.
+ (let* ((header-end (save-excursion
+ (and (re-search-forward "\n\n" nil t)
+ (point))))
+ (case-fold-search t)
+ (size
+ ;; Get the numeric value from the Content-Length field.
+ (save-excursion
+ ;; Back up to end of prev line,
+ ;; in case the Content-Length field comes first.
+ (forward-char -1)
+ (and (search-forward "\ncontent-length: "
+ header-end t)
+ (let ((beg (point))
+ (eol (progn (end-of-line) (point))))
+ (read (buffer-substring beg eol)))))))
+ (if size
+ (goto-char (+ header-end size))))
+
+ (if (re-search-forward
+ (concat "^[\^_]?\\("
+ rmail-unix-mail-delimiter
+ "\\|"
+ mmdf-delim1 "\\|"
+ "^BABYL OPTIONS:\\|"
+ "\^L\n[01],\\)") nil t)
+ (goto-char (match-beginning 1))
+ (goto-char (point-max)))
+ (setq count (1+ count))
+ (save-excursion
+ (save-restriction
+ (narrow-to-region start (point))
+ (goto-char (point-min))
+ (while (search-forward "\n\^_" nil t); single char
+ (replace-match "\n^_")))); 2 chars: "^" and "_"
+ (insert ?\^_)
+ (narrow-to-region (point) (point-max)))
+ ;;
+ ;;This is a kludge, in case we're wrong about mmdf not
+ ;;allowing anything in between. If it loses, we'll have
+ ;;to look for something else
+ (t (delete-char 1)))))
+ count))
+
+(defun rmail-nuke-pinhead-header ()
+ (save-excursion
+ (save-restriction
+ (let ((start (point))
+ (end (progn
+ (condition-case ()
+ (search-forward "\n\n")
+ (error
+ (goto-char (point-max))
+ (insert "\n\n")))
+ (point)))
+ has-from has-date)
+ (narrow-to-region start end)
+ (let ((case-fold-search t))
+ (goto-char start)
+ (setq has-from (search-forward "\nFrom:" nil t))
+ (goto-char start)
+ (setq has-date (and (search-forward "\nDate:" nil t) (point)))
+ (goto-char start))
+ (let ((case-fold-search nil))
+ (if (re-search-forward (concat "^" rmail-unix-mail-delimiter) nil t)
+ (replace-match
+ (concat
+ ;; Keep and reformat the date if we don't
+ ;; have a Date: field.
+ (if has-date
+ ""
+ ;; If no time zone specified, assume est.
+ (if (= (match-beginning 7) (match-end 7))
+ "Date: \\3, \\5 \\4 \\9 \\6 EST\n"
+ "Date: \\3, \\5 \\4 \\9 \\6\\7\n"))
+ ;; Keep and reformat the sender if we don't
+ ;; have a From: field.
+ (if has-from
+ ""
+ "From: \\1\n")))))))))
+
+;;;; *** Rmail Message Formatting and Header Manipulation ***
+
+(defun rmail-reformat-message (beg end)
+ (goto-char beg)
+ (forward-line 1)
+ (if (/= (following-char) ?0)
+ (error "Bad format in RMAIL file."))
+ (let ((buffer-read-only nil)
+ (delta (- (buffer-size) end)))
+ (delete-char 1)
+ (insert ?1)
+ (forward-line 1)
+ (if (looking-at "Summary-line: ")
+ (forward-line 1))
+ (if (looking-at "\\*\\*\\* EOOH \\*\\*\\*\n")
+ (delete-region (point)
+ (progn (forward-line 1) (point))))
+ (let ((str (buffer-substring (point)
+ (save-excursion (search-forward "\n\n" end 'move)
+ (point)))))
+ (insert str "*** EOOH ***\n")
+ (narrow-to-region (point) (- (buffer-size) delta)))
+ (goto-char (point-min))
+ (if rmail-ignored-headers (rmail-clear-headers))
+ (if rmail-message-filter (funcall rmail-message-filter))))
+
+(defun rmail-clear-headers ()
+ (if (search-forward "\n\n" nil t)
+ (save-restriction
+ (narrow-to-region (point-min) (point))
+ (let ((buffer-read-only nil))
+ (while (let ((case-fold-search t))
+ (goto-char (point-min))
+ (re-search-forward rmail-ignored-headers nil t))
+ (beginning-of-line)
+ (delete-region (point)
+ (progn (re-search-forward "\n[^ \t]")
+ (forward-char -1)
+ (point))))))))
+
+(defun rmail-toggle-header ()
+ "Show original message header if pruned header currently shown, or vice versa."
+ (interactive)
+ (rmail-maybe-set-message-counters)
+ (narrow-to-region (rmail-msgbeg rmail-current-message) (point-max))
+ (let ((buffer-read-only nil))
+ (goto-char (point-min))
+ (forward-line 1)
+ (if (= (following-char) ?1)
+ (progn (delete-char 1)
+ (insert ?0)
+ (forward-line 1)
+ (if (looking-at "Summary-Line:")
+ (forward-line 1))
+ (insert "*** EOOH ***\n")
+ (forward-char -1)
+ (search-forward "\n*** EOOH ***\n")
+ (forward-line -1)
+ (let ((temp (point)))
+ (and (search-forward "\n\n" nil t)
+ (delete-region temp (point))))
+ (goto-char (point-min))
+ (search-forward "\n*** EOOH ***\n")
+ (narrow-to-region (point) (point-max)))
+ (rmail-reformat-message (point-min) (point-max)))))
+
+;;;; *** Rmail Attributes and Keywords ***
+
+;; Make a string describing current message's attributes and keywords
+;; and set it up as the name of a minor mode
+;; so it will appear in the mode line.
+(defun rmail-display-labels ()
+ (let ((blurb "") (beg (point-min-marker)) (end (point-max-marker)))
+ (save-excursion
+ (unwind-protect
+ (progn
+ (widen)
+ (goto-char (rmail-msgbeg rmail-current-message))
+ (forward-line 1)
+ (if (looking-at "[01],")
+ (progn
+ (narrow-to-region (point) (progn (end-of-line) (point)))
+ ;; Truly valid BABYL format requires a space before each
+ ;; attribute or keyword name. Put them in if missing.
+ (let (buffer-read-only)
+ (goto-char (point-min))
+ (while (search-forward "," nil t)
+ (or (looking-at "[ ,]") (eobp)
+ (insert " "))))
+ (goto-char (point-max))
+ (if (search-backward ",," nil 'move)
+ (progn
+ (if (> (point) (1+ (point-min)))
+ (setq blurb (buffer-substring (+ 1 (point-min)) (point))))
+ (if (> (- (point-max) (point)) 2)
+ (setq blurb
+ (concat blurb
+ ";"
+ (buffer-substring (+ (point) 3)
+ (1- (point-max)))))))))))
+ (narrow-to-region beg end)
+ (set-marker beg nil)
+ (set-marker end nil)))
+ (while (string-match " +," blurb)
+ (setq blurb (concat (substring blurb 0 (match-beginning 0)) ","
+ (substring blurb (match-end 0)))))
+ (while (string-match ", +" blurb)
+ (setq blurb (concat (substring blurb 0 (match-beginning 0)) ","
+ (substring blurb (match-end 0)))))
+ (setq mode-line-process
+ (concat " " rmail-current-message "/" rmail-total-messages
+ blurb))))
+
+;; Turn an attribute of the current message on or off according to STATE.
+;; ATTR is the name of the attribute, as a string.
+(defun rmail-set-attribute (attr state)
+ (let ((omax (- (buffer-size) (point-max)))
+ (omin (- (buffer-size) (point-min)))
+ (buffer-read-only nil))
+ (unwind-protect
+ (save-excursion
+ (widen)
+ (goto-char (+ 3 (rmail-msgbeg rmail-current-message)))
+ (let ((curstate (search-backward (concat ", " attr ",")
+ (prog1 (point) (end-of-line)) t)))
+ (or (eq curstate (not (not state)))
+ (if curstate
+ (delete-region (point) (1- (match-end 0)))
+ (beginning-of-line)
+ (forward-char 2)
+ (insert " " attr ","))))
+ (if (string= attr "deleted")
+ (rmail-set-message-deleted-p rmail-current-message state)))
+ (narrow-to-region (max 1 (- (buffer-size) omin))
+ (- (buffer-size) omax))
+ (rmail-display-labels))))
+
+;; Return t if the attributes/keywords line of msg number MSG
+;; contains a match for the regexp LABELS.
+(defun rmail-message-labels-p (msg labels)
+ (goto-char (rmail-msgbeg msg))
+ (forward-char 3)
+ (re-search-backward labels (prog1 (point) (end-of-line)) t))
+
+;;;; *** Rmail Message Selection And Support ***
+
+(defun rmail-msgend (n)
+ (marker-position (aref rmail-message-vector (1+ n))))
+
+(defun rmail-msgbeg (n)
+ (marker-position (aref rmail-message-vector n)))
+
+(defun rmail-widen-to-current-msgbeg (function)
+ "Call FUNCTION with point at start of internal data of current message.
+Assumes that bounds were previously narrowed to display the message in Rmail.
+The bounds are widened enough to move point where desired,
+then narrowed again afterward.
+Assumes that the visible text of the message is not changed by FUNCTION."
+ (save-excursion
+ (let ((obeg (- (point-max) (point-min)))
+ (unwind-protect
+ (progn
+ (narrow-to-region (rmail-msgbeg rmail-current-message)
+ (point-max))
+ (goto-char (point-min))
+ (funcall function))
+ (narrow-to-region (- (point-max) obeg) (point-max)))))))
+
+(defun rmail-forget-messages ()
+ (unwind-protect
+ (if (vectorp rmail-message-vector)
+ (let* ((i 0)
+ (v rmail-message-vector)
+ (n (length v)))
+ (while (< i n)
+ (move-marker (aref v i) nil)
+ (setq i (1+ i)))))
+ (setq rmail-message-vector nil)
+ (setq rmail-deleted-vector nil)))
+
+(defun rmail-maybe-set-message-counters ()
+ (if (not (and rmail-deleted-vector
+ rmail-message-vector
+ rmail-current-message
+ rmail-total-messages))
+ (rmail-set-message-counters)))
+
+(defun rmail-count-new-messages (&optional nomsg)
+ (let* ((case-fold-search nil)
+ (total-messages 0)
+ (messages-head nil)
+ (deleted-head nil))
+ (or nomsg (message "Counting new messages..."))
+ (goto-char (point-max))
+ ;; Put at the end of messages-head
+ ;; the entry for message N+1, which marks
+ ;; the end of message N. (N = number of messages).
+ (search-backward "\^_")
+ (setq messages-head (list (point-marker)))
+ (rmail-set-message-counters-counter (point-min))
+ (setq rmail-current-message (1+ rmail-total-messages))
+ (setq rmail-total-messages
+ (+ rmail-total-messages total-messages))
+ (setq rmail-message-vector
+ (vconcat rmail-message-vector (cdr messages-head)))
+ (aset rmail-message-vector
+ rmail-current-message (car messages-head))
+ (setq rmail-deleted-vector
+ (concat rmail-deleted-vector deleted-head))
+ (setq rmail-summary-vector
+ (vconcat rmail-summary-vector (make-vector total-messages nil)))
+ (goto-char (point-min))
+ (or nomsg (message "Counting new messages...done (%d)" total-messages))))
+
+(defun rmail-set-message-counters ()
+ (rmail-forget-messages)
+ (save-excursion
+ (save-restriction
+ (widen)
+ (let* ((point-save (point))
+ (total-messages 0)
+ (messages-after-point)
+ (case-fold-search nil)
+ (messages-head nil)
+ (deleted-head nil))
+ (message "Counting messages...")
+ (goto-char (point-max))
+ ;; Put at the end of messages-head
+ ;; the entry for message N+1, which marks
+ ;; the end of message N. (N = number of messages).
+ (search-backward "\^_")
+ (setq messages-head (list (point-marker)))
+ (rmail-set-message-counters-counter (min (point) point-save))
+ (setq messages-after-point total-messages)
+ (rmail-set-message-counters-counter)
+ (setq rmail-total-messages total-messages)
+ (setq rmail-current-message
+ (min total-messages
+ (max 1 (- total-messages messages-after-point))))
+ (setq rmail-message-vector
+ (apply 'vector (cons (point-min-marker) messages-head))
+ rmail-deleted-vector (concat "D" deleted-head)
+ rmail-summary-vector (make-vector rmail-total-messages nil))
+ (message "Counting messages...done")))))
+
+(defun rmail-set-message-counters-counter (&optional stop)
+ (while (search-backward "\^_\^L\n" stop t)
+ (setq messages-head (cons (point-marker) messages-head))
+ (save-excursion
+ (setq deleted-head
+ (cons (if (search-backward ", deleted,"
+ (prog1 (point)
+ (forward-line 2))
+ t)
+ ?D ?\ )
+ deleted-head)))
+ (if (zerop (% (setq total-messages (1+ total-messages)) 20))
+ (message "Counting messages...%d" total-messages))))
+
+(defun rmail-beginning-of-message ()
+ "Show current message starting from the beginning."
+ (interactive)
+ (rmail-show-message rmail-current-message))
+
+(defun rmail-show-message (&optional n)
+ "Show message number N (prefix argument), counting from start of file."
+ (interactive "p")
+ (rmail-maybe-set-message-counters)
+ (widen)
+ (if (zerop rmail-total-messages)
+ (progn (narrow-to-region (point-min) (1- (point-max)))
+ (goto-char (point-min))
+ (setq mode-line-process nil))
+ (let (blurb)
+ (if (not n)
+ (setq n rmail-current-message)
+ (cond ((<= n 0)
+ (setq n 1
+ rmail-current-message 1
+ blurb "No previous message"))
+ ((> n rmail-total-messages)
+ (setq n rmail-total-messages
+ rmail-current-message rmail-total-messages
+ blurb "No following message"))
+ (t
+ (setq rmail-current-message n))))
+ (let ((beg (rmail-msgbeg n))
+ (end (rmail-msgend n)))
+ (goto-char beg)
+ (forward-line 1)
+ (if (= (following-char) ?0)
+ (progn
+ (rmail-reformat-message beg end)
+ (rmail-set-attribute "unseen" nil))
+ (search-forward "\n*** EOOH ***\n" end t)
+ (narrow-to-region (point) end))
+ (goto-char (point-min))
+ (rmail-display-labels)
+ (run-hooks 'rmail-show-message-hook)
+ (if blurb
+ (message blurb))))))
+
+(defun rmail-next-message (n)
+ "Show following message whether deleted or not.
+With prefix argument N, moves forward N messages,
+or backward if N is negative."
+ (interactive "p")
+ (rmail-maybe-set-message-counters)
+ (rmail-show-message (+ rmail-current-message n)))
+
+(defun rmail-previous-message (n)
+ "Show previous message whether deleted or not.
+With prefix argument N, moves backward N messages,
+or forward if N is negative."
+ (interactive "p")
+ (rmail-next-message (- n)))
+
+(defun rmail-next-undeleted-message (n)
+ "Show following non-deleted message.
+With prefix argument N, moves forward N non-deleted messages,
+or backward if N is negative."
+ (interactive "p")
+ (rmail-maybe-set-message-counters)
+ (let ((lastwin rmail-current-message)
+ (current rmail-current-message))
+ (while (and (> n 0) (< current rmail-total-messages))
+ (setq current (1+ current))
+ (if (not (rmail-message-deleted-p current))
+ (setq lastwin current n (1- n))))
+ (while (and (< n 0) (> current 1))
+ (setq current (1- current))
+ (if (not (rmail-message-deleted-p current))
+ (setq lastwin current n (1+ n))))
+ (if (/= lastwin rmail-current-message)
+ (rmail-show-message lastwin))
+ (if (< n 0)
+ (message "No previous nondeleted message"))
+ (if (> n 0)
+ (message "No following nondeleted message"))))
+
+(defun rmail-previous-undeleted-message (n)
+ "Show previous non-deleted message.
+With prefix argument N, moves backward N non-deleted messages,
+or forward if N is negative."
+ (interactive "p")
+ (rmail-next-undeleted-message (- n)))
+
+(defun rmail-last-message ()
+ "Show last message in file."
+ (interactive)
+ (rmail-maybe-set-message-counters)
+ (rmail-show-message rmail-total-messages))
+
+(defun rmail-what-message ()
+ (let ((where (point))
+ (low 1)
+ (high rmail-total-messages)
+ (mid (/ rmail-total-messages 2)))
+ (while (> (- high low) 1)
+ (if (>= where (rmail-msgbeg mid))
+ (setq low mid)
+ (setq high mid))
+ (setq mid (+ low (/ (- high low) 2))))
+ (if (>= where (rmail-msgbeg high)) high low)))
+
+(defvar rmail-search-last-regexp nil)
+(defun rmail-search (regexp &optional reversep)
+ "Show message containing next match for REGEXP.
+Search in reverse (earlier messages) with non-nil 2nd arg REVERSEP.
+Interactively, empty argument means use same regexp used last time,
+and reverse search is specified by a negative numeric arg."
+ (interactive
+ (let* ((reversep (< (prefix-numeric-value current-prefix-arg) 0))
+ (prompt (concat (if reversep "Reverse " "") "Rmail search (regexp): "))
+ regexp)
+ (if rmail-search-last-regexp
+ (setq prompt (concat prompt
+ "(default "
+ rmail-search-last-regexp
+ ") ")))
+ (setq regexp (read-string prompt))
+ (cond ((not (equal regexp ""))
+ (setq rmail-search-last-regexp regexp))
+ ((not rmail-search-last-regexp)
+ (error "No previous Rmail search string")))
+ (list rmail-search-last-regexp reversep)))
+ (message "%sRmail search for %s..."
+ (if reversep "Reverse " "")
+ regexp)
+ (rmail-maybe-set-message-counters)
+ (let ((omin (point-min))
+ (omax (point-max))
+ (opoint (point))
+ win
+ (msg rmail-current-message))
+ (unwind-protect
+ (progn
+ (widen)
+ ;; Check messages one by one, advancing message number up or down
+ ;; but searching forward through each message.
+ (if reversep
+ (while (and (null win) (> msg 1))
+ (goto-char (rmail-msgbeg (setq msg (1- msg))))
+ (setq win (re-search-forward
+ regexp (rmail-msgend msg) t)))
+ (while (and (null win) (< msg rmail-total-messages))
+ (goto-char (rmail-msgbeg (setq msg (1+ msg))))
+ (setq win (re-search-forward regexp (rmail-msgend msg) t)))))
+ (if win
+ (progn
+ ;; If this is a reverse search and we found a message,
+ ;; search backward thru this message to position point.
+ (if reversep
+ (progn
+ (goto-char (rmail-msgend msg))
+ (re-search-backward
+ regexp (rmail-msgbeg msg) t)))
+ (setq win (point))
+ (rmail-show-message msg)
+ (message "%sRmail search for %s...done"
+ (if reversep "Reverse " "")
+ regexp)
+ (goto-char win))
+ (goto-char opoint)
+ (narrow-to-region omin omax)
+ (ding)
+ (message "Searched failed: %s" regexp)))))
+
+;;;; *** Rmail Message Deletion Commands ***
+
+(defun rmail-message-deleted-p (n)
+ (= (aref rmail-deleted-vector n) ?D))
+
+(defun rmail-set-message-deleted-p (n state)
+ (aset rmail-deleted-vector n (if state ?D ?\ )))
+
+(defun rmail-delete-message ()
+ "Delete this message and stay on it."
+ (interactive)
+ (rmail-set-attribute "deleted" t))
+
+(defun rmail-undelete-previous-message ()
+ "Back up to deleted message, select it, and undelete it."
+ (interactive)
+ (let ((msg rmail-current-message))
+ (while (and (> msg 0)
+ (not (rmail-message-deleted-p msg)))
+ (setq msg (1- msg)))
+ (if (= msg 0)
+ (error "No previous deleted message")
+ (if (/= msg rmail-current-message)
+ (rmail-show-message msg))
+ (rmail-set-attribute "deleted" nil))))
+
+(defun rmail-delete-forward (&optional backward)
+ "Delete this message and move to next nondeleted one.
+Deleted messages stay in the file until the \\[rmail-expunge] command is given.
+With prefix argument, delete and move backward."
+ (interactive "P")
+ (rmail-set-attribute "deleted" t)
+ (rmail-next-undeleted-message (if backward -1 1)))
+
+(defun rmail-delete-backward ()
+ "Delete this message and move to previous nondeleted one.
+Deleted messages stay in the file until the \\[rmail-expunge] command is given."
+ (interactive)
+ (rmail-delete-forward t))
+
+(defun rmail-expunge ()
+ "Actually erase all deleted messages in the file."
+ (interactive)
+ (message "Expunging deleted messages...")
+ ;; Discard any prior undo information.
+ (or (eq buffer-undo-list t)
+ (setq buffer-undo-list nil))
+ (rmail-maybe-set-message-counters)
+ (let* ((omax (- (buffer-size) (point-max)))
+ (omin (- (buffer-size) (point-min)))
+ (opoint (if (and (> rmail-current-message 0)
+ (= ?D (aref rmail-deleted-vector rmail-current-message)))
+ 0 (- (point) (point-min))))
+ (messages-head (cons (aref rmail-message-vector 0) nil))
+ (messages-tail messages-head)
+ ;; Don't make any undo records for the expunging itself.
+ (buffer-undo-list t)
+ (win))
+ (unwind-protect
+ (save-excursion
+ (widen)
+ (goto-char (point-min))
+ (let ((counter 0)
+ (number 1)
+ (total rmail-total-messages)
+ (new-message-number rmail-current-message)
+ (new-summary nil)
+ (buffer-read-only nil)
+ (messages rmail-message-vector)
+ (deleted rmail-deleted-vector)
+ (summary rmail-summary-vector))
+ (setq rmail-total-messages nil
+ rmail-current-message nil
+ rmail-message-vector nil
+ rmail-deleted-vector nil
+ rmail-summary-vector nil)
+ (while (<= number total)
+ (if (= (aref deleted number) ?D)
+ (progn
+ (delete-region
+ (marker-position (aref messages number))
+ (marker-position (aref messages (1+ number))))
+ (move-marker (aref messages number) nil)
+ (if (> new-message-number counter)
+ (setq new-message-number (1- new-message-number))))
+ (setq counter (1+ counter))
+ (setq messages-tail
+ (setcdr messages-tail
+ (cons (aref messages number) nil)))
+ (setq new-summary
+ (cons (if (= counter number) (aref summary (1- number)))
+ new-summary)))
+ (if (zerop (% (setq number (1+ number)) 20))
+ (message "Expunging deleted messages...%d" number)))
+ (setq messages-tail
+ (setcdr messages-tail
+ (cons (aref messages number) nil)))
+ (setq rmail-current-message new-message-number
+ rmail-total-messages counter
+ rmail-message-vector (apply 'vector messages-head)
+ rmail-deleted-vector (make-string (1+ counter) ?\ )
+ rmail-summary-vector (vconcat (nreverse new-summary))
+ win t)))
+ (message "Expunging deleted messages...done")
+ (if (not win)
+ (narrow-to-region (- (buffer-size) omin) (- (buffer-size) omax)))
+ (rmail-show-message
+ (if (zerop rmail-current-message) 1 nil))
+ (forward-char opoint))))
+
+;;;; *** Rmail Mailing Commands ***
+
+(defun rmail-mail ()
+ "Send mail in another window.
+While composing the message, use \\[mail-yank-original] to yank the
+original message into it."
+ (interactive)
+ (mail-other-window nil nil nil nil nil (current-buffer)))
+
+(defun rmail-continue ()
+ "Continue composing outgoing message previously being composed."
+ (interactive)
+ (mail-other-window t))
+
+(defun rmail-reply (just-sender)
+ "Reply to the current message.
+Normally include CC: to all other recipients of original message;
+prefix argument means ignore them.
+While composing the reply, use \\[mail-yank-original] to yank the
+original message into it."
+ (interactive "P")
+ ;;>> this gets set even if we abort. Can't do anything about it, though.
+ (rmail-set-attribute "answered" t)
+ (rmail-display-labels)
+ (let (from reply-to cc subject date to message-id resent-reply-to)
+ (save-excursion
+ (save-restriction
+ (widen)
+ (goto-char (rmail-msgbeg rmail-current-message))
+ (forward-line 1)
+ (if (= (following-char) ?0)
+ (narrow-to-region
+ (progn (forward-line 2)
+ (point))
+ (progn (search-forward "\n\n" (rmail-msgend rmail-current-message)
+ 'move)
+ (point)))
+ (narrow-to-region (point)
+ (progn (search-forward "\n*** EOOH ***\n")
+ (beginning-of-line) (point))))
+ (setq resent-reply-to (mail-fetch-field "resent-reply-to" t)
+ from (mail-fetch-field "from")
+ reply-to (or resent-reply-to
+ (mail-fetch-field "reply-to" nil t)
+ from)
+ cc (cond (just-sender nil)
+ (resent-reply-to (mail-fetch-field "resent-cc" t))
+ (t (mail-fetch-field "cc" nil t)))
+ subject (or (and resent-reply-to
+ (mail-fetch-field "resent-subject" t))
+ (mail-fetch-field "subject"))
+ date (cond (resent-reply-to
+ (mail-fetch-field "resent-date" t))
+ ((mail-fetch-field "date")))
+ to (cond (resent-reply-to
+ (mail-fetch-field "resent-to" t))
+ ((mail-fetch-field "to" nil t))
+ ;((mail-fetch-field "apparently-to")) ack gag barf
+ (t ""))
+ message-id (cond (resent-reply-to
+ (mail-fetch-field "resent-message-id" t))
+ ((mail-fetch-field "message-id"))))))
+ (and subject
+ (string-match "\\`Re: " subject)
+ (setq subject (substring subject 4)))
+ (mail-other-window nil
+ (mail-strip-quoted-names reply-to)
+ subject
+ (rmail-make-in-reply-to-field from date message-id)
+ (if just-sender
+ nil
+ (let* ((cc-list (rmail-dont-reply-to
+ (mail-strip-quoted-names
+ (if (null cc) to (concat to ", " cc))))))
+ (if (string= cc-list "") nil cc-list)))
+ (current-buffer))))
+
+(defun rmail-make-in-reply-to-field (from date message-id)
+ (if mail-use-rfc822 (require 'rfc822))
+ (let (field)
+ (if (and mail-use-rfc822 from)
+ (let ((tem (car (rfc822-addresses from))))
+ (and message-id
+ (setq field (if (string-match
+ (regexp-quote
+ (if (string-match "@[^@]*\\'" tem)
+ (substring tem
+ 0 (match-beginning 0))
+ tem))
+ message-id)
+ message-id
+ (concat message-id " \"" tem "\""))
+ message-id nil date nil))
+ (or field
+ (setq field (prin1-to-string tem))))
+; (if message-id
+; (setq field message-id message-id nil date nil)
+; (setq field (car (rfc882-addresses from))))
+ )
+ (or field
+ (not from)
+ ;; Compute the sender for the in-reply-to; prefer full name.
+ (let* ((stop-pos (string-match " *at \\| *@ \\| *<" from))
+ (start-pos (if stop-pos 0
+ ;;>> this loses on nested ()'s
+ (let ((pos (string-match " *(" from)))
+ (if (not pos) nil
+ (setq stop-pos (string-match ")" from pos))
+ (if (zerop pos) 0 (+ 2 pos)))))))
+ (setq field (if stop-pos
+ (substring from start-pos stop-pos)
+ from))))
+ (if date (setq field (concat field "'s message of " date)))
+ (if message-id (setq field (concat field " " message-id)))
+ field))
+
+(defun rmail-forward ()
+ "Forward the current message to another user."
+ (interactive)
+ ;;>> this gets set even if we abort. Can't do anything about it, though.
+ (rmail-set-attribute "forwarded" t)
+ (let ((forward-buffer (current-buffer))
+ (subject (concat "["
+ (let ((from (or (mail-fetch-field "From")
+ (mail-fetch-field ">From"))))
+ (if from
+ (concat (mail-strip-quoted-names from) ": ")
+ ""))
+ (or (mail-fetch-field "Subject") "")
+ "]")))
+ ;; If only one window, use it for the mail buffer.
+ ;; Otherwise, use another window for the mail buffer
+ ;; so that the Rmail buffer remains visible
+ ;; and sending the mail will get back to it.
+ (if (if (one-window-p t)
+ (mail nil nil subject)
+ (mail-other-window nil nil subject))
+ (save-excursion
+ (goto-char (point-max))
+ (forward-line 1)
+ (insert-buffer forward-buffer)))))
+
+;;;; *** Rmail Specify Inbox Files ***
+
+(autoload 'set-rmail-inbox-list "rmailmsc"
+ "Set the inbox list of the current RMAIL file to FILE-NAME.
+This may be a list of file names separated by commas.
+If FILE-NAME is empty, remove any inbox list."
+ t)
+
+;;;; *** Rmail Commands for Labels ***
+
+(autoload 'rmail-add-label "rmailkwd"
+ "Add LABEL to labels associated with current RMAIL message.
+Completion is performed over known labels when reading."
+ t)
+
+(autoload 'rmail-kill-label "rmailkwd"
+ "Remove LABEL from labels associated with current RMAIL message.
+Completion is performed over known labels when reading."
+ t)
+
+(autoload 'rmail-next-labeled-message "rmailkwd"
+ "Show next message with LABEL. Defaults to last label used.
+With prefix argument N moves forward N messages with this label."
+ t)
+
+(autoload 'rmail-previous-labeled-message "rmailkwd"
+ "Show previous message with LABEL. Defaults to last label used.
+With prefix argument N moves backward N messages with this label."
+ t)
+
+;;;; *** Rmail Edit Mode ***
+
+(autoload 'rmail-edit-current-message "rmailedit"
+ "Edit the contents of the current message"
+ t)
+
+;;;; *** Rmail Summary Mode ***
+
+(autoload 'rmail-summary "rmailsum"
+ "Display a summary of all messages, one line per message."
+ t)
+
+(autoload 'rmail-summary-by-labels "rmailsum"
+ "Display a summary of all messages with one or more LABELS.
+LABELS should be a string containing the desired labels, separated by commas."
+ t)
+
+(autoload 'rmail-summary-by-recipients "rmailsum"
+ "Display a summary of all messages with the given RECIPIENTS.
+Normally checks the To, From and Cc fields of headers;
+but if PRIMARY-ONLY is non-nil (prefix arg given),
+ only look in the To and From fields.
+RECIPIENTS is a string of names separated by commas."
+ t)
+
+;;;; *** Rmail output messages to files ***
+
+(autoload 'rmail-output-to-rmail-file "rmailout"
+ "Append the current message to an Rmail file named FILE-NAME.
+If the file does not exist, ask if it should be created.
+If file is being visited, the message is appended to the Emacs
+buffer visiting that file."
+ t)
+
+(autoload 'rmail-output "rmailout"
+ "Append this message to Unix mail file named FILE-NAME."
+ t)
+
+;;;; *** Rmail undigestification ***
+
+(autoload 'undigestify-rmail-message "undigest"
+ "Break up a digest message into its constituent messages.
+Leaves original message, deleted, before the undigestified messages."
+ t)
diff --git a/lisp/rmail.elc b/lisp/rmail.elc
new file mode 100644
index 00000000000..d2f8225c8c1
--- /dev/null
+++ b/lisp/rmail.elc
Binary files differ
diff --git a/lisp/mail/rmailedit.el b/lisp/rmailedit.el
index d5c3dfd3361..1523f529937 100644
--- a/lisp/mail/rmailedit.el
+++ b/lisp/rmailedit.el
@@ -23,7 +23,7 @@
(defvar rmail-edit-map nil)
(if rmail-edit-map
nil
- (setq rmail-edit-map (nconc (make-sparse-keymap) text-mode-map))
+ (setq rmail-edit-map (copy-keymap text-mode-map))
(define-key rmail-edit-map "\C-c\C-c" 'rmail-cease-edit)
(define-key rmail-edit-map "\C-c\C-]" 'rmail-abort-edit))
diff --git a/lisp/rmailedit.elc b/lisp/rmailedit.elc
new file mode 100644
index 00000000000..441d0678a6a
--- /dev/null
+++ b/lisp/rmailedit.elc
Binary files differ
diff --git a/lisp/mail/rmailkwd.el b/lisp/rmailkwd.el
index 11b4cf54813..af48e0f7dec 100644
--- a/lisp/mail/rmailkwd.el
+++ b/lisp/rmailkwd.el
@@ -111,7 +111,7 @@ Completion is performed over known labels when reading."
;; Commented functions aren't used by RMAIL but might be nice for user
;; packages that do stuff with RMAIL. Note that rmail-message-labels-p
-;; is in rmail.el now.
+;; is in rmailsum now.
;(defun rmail-message-attribute-p (attribute &optional n)
; "Returns t if ATTRIBUTE on NTH or current message."
@@ -171,18 +171,14 @@ Completion is performed over known labels when reading."
;; Motion on messages with keywords.
-(defun rmail-previous-labeled-message (n labels)
- "Show previous message with one of the labels LABELS.
-LABELS should be a comma-separated list of label names.
-If LABELS is empty, the last set of labels specified is used.
+(defun rmail-previous-labeled-message (n label)
+ "Show previous message with LABEL. Defaults to last labels used.
With prefix argument N moves backward N messages with these labels."
(interactive "p\nsMove to previous msg with labels: ")
- (rmail-next-labeled-message (- n) labels))
+ (rmail-next-labeled-message (- n) label))
(defun rmail-next-labeled-message (n labels)
- "Show next message with one of the labels LABELS.
-LABELS should be a comma-separated list of label names.
-If LABELS is empty, the last set of labels specified is used.
+ "Show next message with LABEL. Defaults to last labels used.
With prefix argument N moves forward N messages with these labels."
(interactive "p\nsMove to next msg with labels: ")
(if (string= labels "")
diff --git a/lisp/rmailkwd.elc b/lisp/rmailkwd.elc
new file mode 100644
index 00000000000..06c19f50d59
--- /dev/null
+++ b/lisp/rmailkwd.elc
Binary files differ
diff --git a/lisp/mail/rmailmsc.el b/lisp/rmailmsc.el
index c57b15c4c3a..833077c5cc9 100644
--- a/lisp/mail/rmailmsc.el
+++ b/lisp/rmailmsc.el
@@ -18,9 +18,9 @@
(defun set-rmail-inbox-list (file-name)
- "Set the inbox list of the current RMAIL file to FILE-NAME.
-This may be a list of file names separated by commas.
-If FILE-NAME is empty, remove any inbox list."
+ "Set the inbox list of the current RMAIL file to FILE-NAME. This may be
+a list of file names separated by commas. If FILE-NAME is empty, remove
+any inbox list."
(interactive "sSet mailbox list to (comma-separated list of filenames): ")
(save-excursion
(let ((names (rmail-parse-file-inboxes))
diff --git a/lisp/rmailmsc.elc b/lisp/rmailmsc.elc
new file mode 100644
index 00000000000..2a4d648dfaa
--- /dev/null
+++ b/lisp/rmailmsc.elc
Binary files differ
diff --git a/lisp/rmailout.el b/lisp/rmailout.el
new file mode 100644
index 00000000000..f946818f0c2
--- /dev/null
+++ b/lisp/rmailout.el
@@ -0,0 +1,126 @@
+;; "RMAIL" mail reader for Emacs: output message to a file.
+;; Copyright (C) 1985, 1987 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 1, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+;; Temporary until Emacs always has this variable.
+(defvar rmail-delete-after-output nil
+ "*Non-nil means automatically delete a message that is copied to a file.")
+
+(defun rmail-output-to-rmail-file (file-name)
+ "Append the current message to an Rmail file named FILE-NAME.
+If the file does not exist, ask if it should be created.
+If file is being visited, the message is appended to the Emacs
+buffer visiting that file."
+ (interactive (list (read-file-name
+ (concat "Output message to Rmail file: (default "
+ (file-name-nondirectory rmail-last-rmail-file)
+ ") ")
+ (file-name-directory rmail-last-rmail-file)
+ rmail-last-rmail-file)))
+ (setq file-name (expand-file-name file-name))
+ (setq rmail-last-rmail-file file-name)
+ (rmail-maybe-set-message-counters)
+ (or (get-file-buffer file-name)
+ (file-exists-p file-name)
+ (if (yes-or-no-p
+ (concat "\"" file-name "\" does not exist, create it? "))
+ (let ((file-buffer (create-file-buffer file-name)))
+ (save-excursion
+ (set-buffer file-buffer)
+ (rmail-insert-rmail-file-header)
+ (let ((require-final-newline nil))
+ (write-region (point-min) (point-max) file-name t 1)))
+ (kill-buffer file-buffer))
+ (error "Output file does not exist")))
+ (save-restriction
+ (widen)
+ ;; Decide whether to append to a file or to an Emacs buffer.
+ (save-excursion
+ (let ((buf (get-file-buffer file-name))
+ (cur (current-buffer))
+ (beg (1+ (rmail-msgbeg rmail-current-message)))
+ (end (1+ (rmail-msgend rmail-current-message))))
+ (if (not buf)
+ (append-to-file beg end file-name)
+ (if (eq buf (current-buffer))
+ (error "Can't output message to same file it's already in"))
+ ;; File has been visited, in buffer BUF.
+ (set-buffer buf)
+ (let ((buffer-read-only nil)
+ (msg (and (boundp 'rmail-current-message)
+ rmail-current-message)))
+ ;; If MSG is non-nil, buffer is in RMAIL mode.
+ (if msg
+ (rmail-maybe-set-message-counters))
+ (widen)
+ (narrow-to-region (point-max) (point-max))
+ (insert-buffer-substring cur beg end)
+ (if msg
+ (progn
+ (goto-char (point-min))
+ (widen)
+ (search-backward "\^_")
+ (narrow-to-region (point) (point-max))
+ (goto-char (1+ (point-min)))
+ (rmail-count-new-messages t)
+ (rmail-show-message msg))))))))
+ (rmail-set-attribute "filed" t)
+ (and rmail-delete-after-output (rmail-delete-forward)))
+
+(defun rmail-output (file-name)
+ "Append this message to Unix mail file named FILE-NAME."
+ (interactive
+ (list
+ (read-file-name
+ (concat "Output message to Unix mail file"
+ (if rmail-last-file
+ (concat " (default "
+ (file-name-nondirectory rmail-last-file)
+ "): " )
+ ": "))
+ (and rmail-last-file (file-name-directory rmail-last-file))
+ rmail-last-file)))
+ (setq file-name (expand-file-name file-name))
+ (setq rmail-last-file file-name)
+ (let ((rmailbuf (current-buffer))
+ (tembuf (get-buffer-create " rmail-output"))
+ (case-fold-search t))
+ (save-excursion
+ (set-buffer tembuf)
+ (erase-buffer)
+ (insert-buffer-substring rmailbuf)
+ (insert "\n")
+ (goto-char (point-min))
+ (insert "From "
+ (if (mail-fetch-field "from")
+ (mail-strip-quoted-names (mail-fetch-field "from"))
+ "unknown")
+ " " (current-time-string) "\n")
+ ;; ``Quote'' "\nFrom " as "\n>From "
+ ;; (note that this isn't really quoting, as there is no requirement
+ ;; that "\n[>]+From " be quoted in the same transparent way.)
+ (while (search-forward "\nFrom " nil t)
+ (forward-char -5)
+ (insert ?>))
+ (append-to-file (point-min) (point-max) file-name))
+ (kill-buffer tembuf))
+ (if (equal major-mode 'rmail-mode)
+ (progn
+ (rmail-set-attribute "filed" t)
+ (and rmail-delete-after-output (rmail-delete-forward)))))
diff --git a/lisp/rmailout.elc b/lisp/rmailout.elc
new file mode 100644
index 00000000000..8362ea92fe7
--- /dev/null
+++ b/lisp/rmailout.elc
Binary files differ
diff --git a/lisp/mail/rmailsum.el b/lisp/rmailsum.el
index fc8854f153d..aa32363f1ce 100644
--- a/lisp/mail/rmailsum.el
+++ b/lisp/rmailsum.el
@@ -59,28 +59,6 @@ RECIPIENTS is a string of names separated by commas."
(if (not primary-only)
(string-match recipients (or (mail-fetch-field "Cc") ""))))))
-(defun rmail-summary-by-regexp (regexp)
- "Display a summary of all messages according to regexp REGEXP.
-If the regular expression is found in the header of the message
-\(including in the date and other lines, as well as the subject line),
-Emacs will list the header line in the RMAIL-summary."
- (interactive "sRegexp to summarize by: ")
- (if (string= regexp "")
- (setq regexp (or rmail-last-regexp
- (error "No regexp specified"))))
- (setq rmail-last-regexp regexp)
- (rmail-new-summary (concat "regexp " regexp)
- 'rmail-message-regexp-p
- regexp))
-
-(defun rmail-message-regexp-p (msg regexp)
- "Return t, if for message number MSG, regexp REGEXP matches in the header."
- (goto-char (rmail-msgbeg msg))
- (let ((end
- (save-excursion
- (search-forward "*** EOOH ***" (point-max)) (point))))
- (re-search-forward regexp end t)))
-
(defun rmail-new-summary (description function &rest args)
"Create a summary of selected messages.
DESCRIPTION makes part of the mode line of the summary buffer.
@@ -112,9 +90,6 @@ nil for FUNCTION means all messages."
(total rmail-total-messages)
(mesg rmail-current-message))
(pop-to-buffer sbuf)
- ;; Our scroll command should always scroll the Rmail buffer.
- (make-local-variable 'other-window-scroll-buffer)
- (setq other-window-scroll-buffer rbuf)
(let ((buffer-read-only nil))
(erase-buffer)
(cond (summary-msgs
@@ -315,20 +290,6 @@ nil for FUNCTION means all messages."
(insert "D"))
(rmail-summary-next-msg 1)))
-(defun rmail-summary-delete-backward ()
- (interactive)
- (let (end)
- (rmail-summary-goto-msg)
- (pop-to-buffer rmail-buffer)
- (rmail-delete-message)
- (pop-to-buffer rmail-summary-buffer)
- (let ((buffer-read-only nil))
- (skip-chars-forward " ")
- (skip-chars-forward "[0-9]")
- (delete-char 1)
- (insert "D"))
- (rmail-summary-next-msg -1)))
-
(defun rmail-summary-undelete ()
(interactive)
(let ((buffer-read-only nil))
@@ -354,11 +315,10 @@ mail message is displayed in the rmail buffer.
n Move to next undeleted message, or arg messages.
p Move to previous undeleted message, or arg messages.
-M-n Move to next, or forward arg messages.
-M-p Move to previous, or previous arg messages.
+C-n Move to next, or forward arg messages.
+C-p Move to previous, or previous arg messages.
j Jump to the message at the cursor location.
d Delete the message at the cursor location and move to next message.
-C-d Delete the message at the cursor location and move to previous message.
u Undelete this or previous deleted message.
q Quit Rmail.
x Exit and kill the summary window.
@@ -423,15 +383,14 @@ Entering this mode calls value of hook variable rmail-summary-mode-hook."
(define-key rmail-summary-mode-map "j" 'rmail-summary-goto-msg)
(define-key rmail-summary-mode-map "n" 'rmail-summary-next-msg)
(define-key rmail-summary-mode-map "p" 'rmail-summary-previous-msg)
- (define-key rmail-summary-mode-map "\en" 'rmail-summary-next-all)
- (define-key rmail-summary-mode-map "\ep" 'rmail-summary-previous-all)
+ (define-key rmail-summary-mode-map "\C-n" 'rmail-summary-next-all)
+ (define-key rmail-summary-mode-map "\C-p" 'rmail-summary-previous-all)
(define-key rmail-summary-mode-map " " 'rmail-summary-scroll-msg-up)
(define-key rmail-summary-mode-map "q" 'rmail-summary-quit)
(define-key rmail-summary-mode-map "u" 'rmail-summary-undelete)
(define-key rmail-summary-mode-map "x" 'rmail-summary-exit)
(define-key rmail-summary-mode-map "\177" 'rmail-summary-scroll-msg-down)
- (define-key rmail-summary-mode-map "d" 'rmail-summary-delete-forward)
- (define-key rmail-summary-mode-map "\C-d" 'rmail-summary-delete-backward))
+ (define-key rmail-summary-mode-map "d" 'rmail-summary-delete-forward))
(defun rmail-summary-scroll-msg-up (&optional dist)
"Scroll other window forward."
diff --git a/lisp/rmailsum.elc b/lisp/rmailsum.elc
new file mode 100644
index 00000000000..d39f5a4e28c
--- /dev/null
+++ b/lisp/rmailsum.elc
Binary files differ
diff --git a/lisp/mail/rnews.el b/lisp/rnews.el
index 64b98ca407b..821c5f4e8f0 100644
--- a/lisp/mail/rnews.el
+++ b/lisp/rnews.el
@@ -72,11 +72,6 @@ While composing the reply, use \\[mail-yank-original] to yank the original
message into it."
t)
-(defvar news-group-hook-alist nil
- "Alist of (GROUP-REGEXP . HOOK) pairs.
-Just before displaying a message, each HOOK is called
-if its GROUP-REGEXP matches the current newsgroup name.")
-
(defvar rmail-last-file (expand-file-name "~/mbox.news"))
;Now in paths.el.
@@ -500,7 +495,7 @@ to a list (a . b)"
(defun news-select-news-group (gp)
(let ((grp (assoc gp news-group-article-assoc)))
(if (null grp)
- (error "Group %s not subscribed to" gp)
+ (error "Group not subscribed to in file %s." news-startup-file)
(progn
(news-update-message-read news-current-news-group
(news-cdar news-point-pdl))
@@ -519,15 +514,16 @@ to a list (a . b)"
(let ((file (concat news-path
(string-subst-char ?/ ?. news-current-news-group)
"/" arg)))
+ (if (= arg
+ (or (news-cadr (memq (news-cdar news-point-pdl) news-list-of-files))
+ 0))
+ (setcdr (car news-point-pdl) arg))
+ (setq news-current-message-number arg)
(if (file-exists-p file)
- (let ((buffer-read-only ()))
- (if (= arg
- (or (news-cadr (memq (news-cdar news-point-pdl) news-list-of-files))
- 0))
- (setcdr (car news-point-pdl) arg))
- (setq news-current-message-number arg)
- (news-read-in-file file)
- (news-set-mode-line))
+ (let ((buffer-read-only nil))
+ (news-read-in-file file)
+ (news-set-mode-line))
+ (news-set-mode-line)
(error "Article %d nonexistent" arg))))
(defun news-force-update ()
@@ -613,13 +609,6 @@ one for moving forward and one for moving backward."
(let ((start (point)))
(insert-file-contents filename)
(news-convert-format)
- ;; Run each hook that applies to the current newsgroup.
- (let ((hooks news-group-hook-alist))
- (while hooks
- (goto-char start)
- (if (string-match (car (car hooks)) news-group-name)
- (funcall (cdr (car hooks))))
- (setq hooks (cdr hooks))))
(goto-char start)
(forward-line 1)
(if (eobp)
@@ -691,10 +680,11 @@ one for moving forward and one for moving backward."
(save-excursion
(if (not (null news-current-news-group))
(news-update-message-read news-current-news-group
- (news-cdar news-point-pdl)))
- (set-buffer newsrcbuf)
+ (news-cdar news-point-pdl)))
+ (switch-to-buffer newsrcbuf)
(while tem
- (setq group (assoc (car tem) news-group-article-assoc))
+ (setq group (assoc (car tem)
+ news-group-article-assoc))
(if (= (news-cadr (news-cadr group)) (news-caddr (news-cadr group)))
nil
(goto-char 0)
diff --git a/lisp/rnews.elc b/lisp/rnews.elc
new file mode 100644
index 00000000000..1dab31f99da
--- /dev/null
+++ b/lisp/rnews.elc
Binary files differ
diff --git a/lisp/mail/rnewspost.el b/lisp/rnewspost.el
index adb65e6f3ab..000520fcd39 100644
--- a/lisp/mail/rnewspost.el
+++ b/lisp/rnewspost.el
@@ -116,13 +116,8 @@ and don't delete any header fields."
(interactive "P")
(mail-yank-original arg)
(exchange-point-and-mark)
- (run-hooks 'news-reply-header-hook))
-
-(defvar news-reply-header-hook
- '(lambda ()
- (insert "In article " news-reply-yank-message-id
- " " news-reply-yank-from " writes:\n\n"))
- "Hook for inserting a header at the top of a yanked message.")
+ (insert "In article " news-reply-yank-message-id
+ " " news-reply-yank-from " writes:\n\n"))
(defun news-reply-newsgroups ()
"Move point to end of Newsgroups: field.
@@ -192,11 +187,11 @@ news-reply-mode."
;; the fcc: and bcc: fields
(let ((mail-self-blind nil)
(mail-archive-file-name nil))
- (mail-setup to subject in-reply-to nil replybuffer nil)
+ (mail-setup to subject in-reply-to nil replybuffer)
(beginning-of-line)
- (kill-line 1)
+ (delete-region (point) (progn (forward-line 1) (point)))
(goto-char (point-max)))
- (mail-setup to subject in-reply-to nil replybuffer nil))
+ (mail-setup to subject in-reply-to nil replybuffer))
;;;(mail-position-on-field "Posting-Front-End")
;;;(insert (emacs-version))
(goto-char (point-max))
diff --git a/lisp/rnewspost.elc b/lisp/rnewspost.elc
new file mode 100644
index 00000000000..f05445290f1
--- /dev/null
+++ b/lisp/rnewspost.elc
Binary files differ
diff --git a/lisp/saveconf.el b/lisp/saveconf.el
new file mode 100644
index 00000000000..68d34fca8d6
--- /dev/null
+++ b/lisp/saveconf.el
@@ -0,0 +1,240 @@
+;;; Save Emacs buffer and window configuration between editing sessions.
+;;; Copyright (C) 1987, 1988 Kyle E. Jones
+;;;
+;;; Verbatim copies of this file may be freely redistributed.
+;;;
+;;; Modified versions of this file may be redistributed provided that this
+;;; notice remains unchanged, the file contains prominent notice of
+;;; author and time of modifications, and redistribution of the file
+;;; is not further restricted in any way.
+;;;
+;;; This file is distributed `as is', without warranties of any kind.
+
+(provide 'saveconf)
+
+(defconst save-context-version "Norma Jean"
+ "A unique string which is placed at the beginning of every saved context
+file. If the string at the beginning of the context file doesn't match the
+value of this variable the `recover-context' command will ignore the file's
+contents.")
+
+(defvar auto-save-and-recover-context nil
+ "*If non-nil the `save-context' command will always be run before Emacs is
+exited. Also upon Emacs startup, if this variable is non-nil and Emacs is
+passed no command line arguments, `recover-context' will be run.")
+
+(defvar save-buffer-context nil
+ "*If non-nil the `save-context' command will save the context
+of buffers that are visiting files, as well as the contexts of buffers
+that have windows.")
+
+(defvar save-context-predicate
+ (function (lambda (w)
+ (and (buffer-file-name (window-buffer w))
+ (not (string-match "^\\(/usr\\)?/tmp/"
+ (buffer-file-name (window-buffer w)))))))
+ "*Value is a predicate function which determines which windows' contexts
+are saved. When the `save-context' command is invoked, this function will
+be called once for each existing Emacs window. The function should accept
+one argument which will be a window object, and should return non-nil if
+the window's context should be saved.")
+
+
+;; kill-emacs' function definition must be saved
+(if (not (fboundp 'just-kill-emacs))
+ (fset 'just-kill-emacs (symbol-function 'kill-emacs)))
+
+;; Make Emacs call recover-context at startup if appropriate.
+(setq top-level
+ (list 'let '((starting-up (not command-line-processed)))
+ (list 'prog1
+ top-level
+ '(and starting-up auto-save-and-recover-context
+ (null (cdr command-line-args)) (recover-context)))))
+
+(defun kill-emacs (&optional query)
+ "End this Emacs session.
+Prefix ARG or optional first ARG non-nil means exit with no questions asked,
+even if there are unsaved buffers. If Emacs is running non-interactively
+and ARG is an integer, then Emacs exits with ARG as its exit code.
+
+If the variable `auto-save-and-restore-context' is non-nil,
+the function save-context will be called first."
+ (interactive "P")
+ ;; check the purify flag. try to save only if this is a dumped Emacs.
+ ;; saving context from a undumped Emacs caused a NULL pointer to be
+ ;; referenced through. I'm not sure why.
+ (if (and auto-save-and-recover-context (null purify-flag))
+ (save-context))
+ (just-kill-emacs query))
+
+(defun save-context ()
+ "Save context of all Emacs windows (files visited and position of point).
+The information goes into a file called .emacs_<username> in the directory
+where the Emacs session was started. The context can be recovered with the
+`recover-context' command, provided you are in the same directory where
+the context was saved.
+
+If the variable `save-buffer-context' is non-nil, the context of all buffers
+visiting files will be saved as well.
+
+Window sizes and shapes are not saved, since these may not be recoverable
+on terminals with a different number of rows and columns."
+ (interactive)
+ (condition-case error-data
+ (let (context-buffer mark save-file-name)
+ (setq save-file-name (concat (original-working-directory)
+ ".emacs_" (user-login-name)))
+ (if (not (file-writable-p save-file-name))
+ (if (file-writable-p (original-working-directory))
+ (error "context is write-protected, %s" save-file-name)
+ (error "can't access directory, %s"
+ (original-working-directory))))
+ ;;
+ ;; set up a buffer for the saved context information
+ ;; Note that we can't set the visited file yet, because by
+ ;; giving the buffer a file to visit we are making it
+ ;; eligible to have it's context saved.
+ ;;
+ (setq context-buffer (get-buffer-create " *Context Info*"))
+ (set-buffer context-buffer)
+ (erase-buffer)
+ (set-buffer-modified-p nil)
+ ;;
+ ;; record the context information
+ ;;
+ (mapcar
+ (function
+ (lambda (w)
+ (cond ((funcall save-context-predicate w)
+ (prin1 (buffer-file-name (window-buffer w)) context-buffer)
+ (princ " " context-buffer)
+ (prin1 (window-point w) context-buffer)
+ (princ "\n" context-buffer)))))
+ (window-list))
+
+ ;;
+ ;; nil is the data sentinel. We will insert it later if we
+ ;; need it but for now just remember where the last line of
+ ;; window context ended.
+ ;;
+ (setq mark (point))
+
+ ;;
+ ;; If `save-buffer-context' is non-nil we save buffer contexts.
+ ;;
+ (if save-buffer-context
+ (mapcar
+ (function
+ (lambda (b)
+ (set-buffer b)
+ (cond (buffer-file-name
+ (prin1 buffer-file-name context-buffer)
+ (princ " " context-buffer)
+ (prin1 (point) context-buffer)
+ (princ "\n" context-buffer)))))
+ (buffer-list)))
+
+ ;;
+ ;; If the context-buffer contains information, we add the version
+ ;; string and sentinels, and write out the saved context.
+ ;; If the context-buffer is empty, we don't create a file at all.
+ ;; If there's an old saved context in this directory we attempt
+ ;; to delete it.
+ ;;
+ (cond ((buffer-modified-p context-buffer)
+ (set-buffer context-buffer)
+ (setq buffer-offer-save nil)
+ ;; sentinel for EOF
+ (insert "nil\n")
+ ;; sentinel for end of window contexts
+ (goto-char mark)
+ (insert "nil\n")
+ ;; version string
+ (goto-char (point-min))
+ (prin1 save-context-version context-buffer)
+ (insert "\n\n")
+ ;; so kill-buffer won't need confirmation later
+ (set-buffer-modified-p nil)
+ ;; save it
+ (write-region (point-min) (point-max) save-file-name
+ nil 'quiet))
+ (t (condition-case data
+ (delete-file save-file-name) (error nil))))
+
+ (kill-buffer context-buffer))
+ (error nil)))
+
+(defun recover-context ()
+ "Recover an Emacs context saved by `save-context' command.
+Files that were visible in windows when the context was saved are visited and
+point is set in each window to what is was when the context was saved."
+ (interactive)
+ ;;
+ ;; Set up some local variables.
+ ;;
+ (condition-case error-data
+ (let (sexpr context-buffer recover-file-name)
+ (setq recover-file-name (concat (original-working-directory)
+ ".emacs_" (user-login-name)))
+ (if (not (file-readable-p recover-file-name))
+ (error "can't access context, %s" recover-file-name))
+ ;;
+ ;; create a temp buffer and copy the saved context into it.
+ ;;
+ (setq context-buffer (get-buffer-create " *Recovered Context*"))
+ (set-buffer context-buffer)
+ (erase-buffer)
+ (insert-file-contents recover-file-name nil)
+ ;; so kill-buffer won't need confirmation later
+ (set-buffer-modified-p nil)
+ ;;
+ ;; If it's empty forget it.
+ ;;
+ (if (zerop (buffer-size))
+ (error "context file is empty, %s" recover-file-name))
+ ;;
+ ;; check the version and make sure it matches ours
+ ;;
+ (setq sexpr (read context-buffer))
+ (if (not (equal sexpr save-context-version))
+ (error "version string incorrect, %s" sexpr))
+ ;;
+ ;; Recover the window contexts
+ ;;
+ (while (setq sexpr (read context-buffer))
+ (select-window (get-largest-window))
+ (if (buffer-file-name)
+ (split-window))
+ (other-window 1)
+ (find-file sexpr)
+ (goto-char (read context-buffer)))
+ ;;
+ ;; Recover buffer contexts, if any.
+ ;;
+ (while (setq sexpr (read context-buffer))
+ (set-buffer (find-file-noselect sexpr))
+ (goto-char (read context-buffer)))
+ (bury-buffer "*scratch*")
+ (kill-buffer context-buffer))
+ (error nil)))
+
+(defun original-working-directory ()
+ (save-excursion
+ (set-buffer (get-buffer-create "*scratch*"))
+ default-directory))
+
+(defun window-list (&optional mini)
+ "Returns a list of Lisp window objects for all Emacs windows.
+Optional first arg MINIBUF t means include the minibuffer window
+in the list, even if it is not active. If MINIBUF is neither t
+nor nil it means to not count the minibuffer window even if it is active."
+ (let* ((first-window (next-window (previous-window (selected-window)) mini))
+ (windows (cons first-window nil))
+ (current-cons windows)
+ (w (next-window first-window mini)))
+ (while (not (eq w first-window))
+ (setq current-cons (setcdr current-cons (cons w nil)))
+ (setq w (next-window w mini)))
+ windows))
+
diff --git a/lisp/progmodes/scheme.el b/lisp/scheme.el
index 9cf1595b7e4..733696eddd3 100644
--- a/lisp/progmodes/scheme.el
+++ b/lisp/scheme.el
@@ -1,5 +1,5 @@
;; Scheme mode, and its idiosyncratic commands.
-;; Copyright (C) 1986, 1987, 1988 Free Software Foundation, Inc.
+;; Copyright (C) 1986, 1987, 1988, 1990 Free Software Foundation, Inc.
;; Adapted from Lisp mode by Bill Rozas, jinx@prep.
;; This file is part of GNU Emacs.
@@ -65,20 +65,20 @@
(modify-syntax-entry ?] ")[ ")
(modify-syntax-entry ?{ "(} ")
(modify-syntax-entry ?} "){ ")
- (modify-syntax-entry ?\| " 23")
+ (modify-syntax-entry ?\| " ")
;; Other atom delimiters
(modify-syntax-entry ?\( "() ")
(modify-syntax-entry ?\) ")( ")
(modify-syntax-entry ?\; "< ")
(modify-syntax-entry ?\" "\" ")
- (modify-syntax-entry ?' " p")
- (modify-syntax-entry ?` " p")
+ (modify-syntax-entry ?' "' ")
+ (modify-syntax-entry ?` "' ")
;; Special characters
- (modify-syntax-entry ?, "_ p")
- (modify-syntax-entry ?@ "_ p")
- (modify-syntax-entry ?# "_ p14")
+ (modify-syntax-entry ?, "' ")
+ (modify-syntax-entry ?@ "' ")
+ (modify-syntax-entry ?# "' ")
(modify-syntax-entry ?\\ "\\ ")))
(defvar scheme-mode-abbrev-table nil "")
@@ -163,7 +163,7 @@ Set this to nil if you normally use another dialect.")
comment-column)))))
(defvar scheme-indent-offset nil "")
-(defvar scheme-indent-function 'scheme-indent-function "")
+(defvar scheme-indent-hook 'scheme-indent-hook "")
(defun scheme-indent-line (&optional whole-exp)
"Indent current line as Scheme code.
@@ -276,17 +276,17 @@ of the start of the containing expression."
(goto-char containing-sexp)
(setq desired-indent (+ scheme-indent-offset (current-column))))
((not (or desired-indent
- (and (boundp 'scheme-indent-function)
- scheme-indent-function
+ (and (boundp 'scheme-indent-hook)
+ scheme-indent-hook
(not retry)
(setq desired-indent
- (funcall scheme-indent-function
+ (funcall scheme-indent-hook
indent-point state)))))
;; Use default indentation if not computed yet
(setq desired-indent (current-column))))
desired-indent)))
-(defun scheme-indent-function (indent-point state)
+(defun scheme-indent-hook (indent-point state)
(let ((normal-indent (current-column)))
(save-excursion
(goto-char (1+ (car (cdr state))))
@@ -298,7 +298,7 @@ of the start of the containing expression."
;; Who cares about this, really?
;(if (not (string-match "\\\\\\||" function)))
(setq function (downcase function))
- (setq method (get (intern-soft function) 'scheme-indent-function))
+ (setq method (get (intern-soft function) 'scheme-indent-hook))
(cond ((integerp method)
(scheme-indent-specform method state indent-point))
(method
@@ -314,7 +314,7 @@ of the start of the containing expression."
body-indent containing-form-column)
;; Move to the start of containing form, calculate indentation
;; to use for non-distinguished forms (> count), and move past the
- ;; function symbol. scheme-indent-function guarantees that there is at
+ ;; function symbol. scheme-indent-hook guarantees that there is at
;; least one word or symbol character following open paren of containing
;; form.
(goto-char containing-form-start)
@@ -381,70 +381,70 @@ of the start of the containing expression."
(scheme-indent-specform 2 state indent-point)
(scheme-indent-specform 1 state indent-point)))
-;; (put 'begin 'scheme-indent-function 0), say, causes begin to be indented
+;; (put 'begin 'scheme-indent-hook 0), say, causes begin to be indented
;; like defun if the first form is placed on the next line, otherwise
;; it is indented like any other form (i.e. forms line up under first).
-(put 'begin 'scheme-indent-function 0)
-(put 'case 'scheme-indent-function 1)
-(put 'delay 'scheme-indent-function 0)
-(put 'do 'scheme-indent-function 2)
-(put 'lambda 'scheme-indent-function 1)
-(put 'let 'scheme-indent-function 'scheme-let-indent)
-(put 'let* 'scheme-indent-function 1)
-(put 'letrec 'scheme-indent-function 1)
-(put 'sequence 'scheme-indent-function 0)
-
-(put 'call-with-input-file 'scheme-indent-function 1)
-(put 'with-input-from-file 'scheme-indent-function 1)
-(put 'with-input-from-port 'scheme-indent-function 1)
-(put 'call-with-output-file 'scheme-indent-function 1)
-(put 'with-output-to-file 'scheme-indent-function 1)
-(put 'with-output-to-port 'scheme-indent-function 1)
+(put 'begin 'scheme-indent-hook 0)
+(put 'case 'scheme-indent-hook 1)
+(put 'delay 'scheme-indent-hook 0)
+(put 'do 'scheme-indent-hook 2)
+(put 'lambda 'scheme-indent-hook 1)
+(put 'let 'scheme-indent-hook 'scheme-let-indent)
+(put 'let* 'scheme-indent-hook 1)
+(put 'letrec 'scheme-indent-hook 1)
+(put 'sequence 'scheme-indent-hook 0)
+
+(put 'call-with-input-file 'scheme-indent-hook 1)
+(put 'with-input-from-file 'scheme-indent-hook 1)
+(put 'with-input-from-port 'scheme-indent-hook 1)
+(put 'call-with-output-file 'scheme-indent-hook 1)
+(put 'with-output-to-file 'scheme-indent-hook 1)
+(put 'with-output-to-port 'scheme-indent-hook 1)
;;;; MIT Scheme specific indentation.
(if scheme-mit-dialect
(progn
- (put 'fluid-let 'scheme-indent-function 1)
- (put 'in-package 'scheme-indent-function 1)
- (put 'let-syntax 'scheme-indent-function 1)
- (put 'local-declare 'scheme-indent-function 1)
- (put 'macro 'scheme-indent-function 1)
- (put 'make-environment 'scheme-indent-function 0)
- (put 'named-lambda 'scheme-indent-function 1)
- (put 'using-syntax 'scheme-indent-function 1)
-
- (put 'with-input-from-string 'scheme-indent-function 1)
- (put 'with-output-to-string 'scheme-indent-function 0)
- (put 'with-values 'scheme-indent-function 1)
-
- (put 'syntax-table-define 'scheme-indent-function 2)
- (put 'list-transform-positive 'scheme-indent-function 1)
- (put 'list-transform-negative 'scheme-indent-function 1)
- (put 'list-search-positive 'scheme-indent-function 1)
- (put 'list-search-negative 'scheme-indent-function 1)
-
- (put 'access-components 'scheme-indent-function 1)
- (put 'assignment-components 'scheme-indent-function 1)
- (put 'combination-components 'scheme-indent-function 1)
- (put 'comment-components 'scheme-indent-function 1)
- (put 'conditional-components 'scheme-indent-function 1)
- (put 'disjunction-components 'scheme-indent-function 1)
- (put 'declaration-components 'scheme-indent-function 1)
- (put 'definition-components 'scheme-indent-function 1)
- (put 'delay-components 'scheme-indent-function 1)
- (put 'in-package-components 'scheme-indent-function 1)
- (put 'lambda-components 'scheme-indent-function 1)
- (put 'lambda-components* 'scheme-indent-function 1)
- (put 'lambda-components** 'scheme-indent-function 1)
- (put 'open-block-components 'scheme-indent-function 1)
- (put 'pathname-components 'scheme-indent-function 1)
- (put 'procedure-components 'scheme-indent-function 1)
- (put 'sequence-components 'scheme-indent-function 1)
- (put 'unassigned\?-components 'scheme-indent-function 1)
- (put 'unbound\?-components 'scheme-indent-function 1)
- (put 'variable-components 'scheme-indent-function 1)))
+ (put 'fluid-let 'scheme-indent-hook 1)
+ (put 'in-package 'scheme-indent-hook 1)
+ (put 'let-syntax 'scheme-indent-hook 1)
+ (put 'local-declare 'scheme-indent-hook 1)
+ (put 'macro 'scheme-indent-hook 1)
+ (put 'make-environment 'scheme-indent-hook 0)
+ (put 'named-lambda 'scheme-indent-hook 1)
+ (put 'using-syntax 'scheme-indent-hook 1)
+
+ (put 'with-input-from-string 'scheme-indent-hook 1)
+ (put 'with-output-to-string 'scheme-indent-hook 0)
+ (put 'with-values 'scheme-indent-hook 1)
+
+ (put 'syntax-table-define 'scheme-indent-hook 2)
+ (put 'list-transform-positive 'scheme-indent-hook 1)
+ (put 'list-transform-negative 'scheme-indent-hook 1)
+ (put 'list-search-positive 'scheme-indent-hook 1)
+ (put 'list-search-negative 'scheme-indent-hook 1)
+
+ (put 'access-components 'scheme-indent-hook 1)
+ (put 'assignment-components 'scheme-indent-hook 1)
+ (put 'combination-components 'scheme-indent-hook 1)
+ (put 'comment-components 'scheme-indent-hook 1)
+ (put 'conditional-components 'scheme-indent-hook 1)
+ (put 'disjunction-components 'scheme-indent-hook 1)
+ (put 'declaration-components 'scheme-indent-hook 1)
+ (put 'definition-components 'scheme-indent-hook 1)
+ (put 'delay-components 'scheme-indent-hook 1)
+ (put 'in-package-components 'scheme-indent-hook 1)
+ (put 'lambda-components 'scheme-indent-hook 1)
+ (put 'lambda-components* 'scheme-indent-hook 1)
+ (put 'lambda-components** 'scheme-indent-hook 1)
+ (put 'open-block-components 'scheme-indent-hook 1)
+ (put 'pathname-components 'scheme-indent-hook 1)
+ (put 'procedure-components 'scheme-indent-hook 1)
+ (put 'sequence-components 'scheme-indent-hook 1)
+ (put 'unassigned\?-components 'scheme-indent-hook 1)
+ (put 'unbound\?-components 'scheme-indent-hook 1)
+ (put 'variable-components 'scheme-indent-hook 1)))
(defun scheme-indent-sexp ()
"Indent each line of the list starting just after point."
diff --git a/lisp/scheme.elc b/lisp/scheme.elc
new file mode 100644
index 00000000000..fca6c89a168
--- /dev/null
+++ b/lisp/scheme.elc
Binary files differ
diff --git a/lisp/textmodes/scribe.el b/lisp/scribe.el
index 48002bd4029..257c93efd5a 100644
--- a/lisp/textmodes/scribe.el
+++ b/lisp/scribe.el
@@ -1,21 +1,21 @@
;; scribe mode, and its ideosyncratic commands.
;; Copyright (C) 1985 Free Software Foundation, Inc.
-;; This file might become part of GNU Emacs.
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 1, or (at your option)
+;; any later version.
;; GNU Emacs is distributed in the hope that it will be useful,
-;; but without any warranty. No author or distributor
-;; accepts responsibility to anyone for the consequences of using it
-;; or for whether it serves any particular purpose or works at all,
-;; unless he says so in writing.
-
-;; Everyone is granted permission to copy, modify and redistribute
-;; GNU Emacs, but only under the conditions described in the
-;; document "GNU Emacs copying permission notice". An exact copy
-;; of the document is supposed to have been given to you along with
-;; GNU Emacs so that you can know how you may redistribute it all.
-;; It should be in a file named COPYING. Among other things, the
-;; copyright notice and this notice must be preserved on all copies.
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
(defvar scribe-mode-syntax-table nil
diff --git a/lisp/scribe.elc b/lisp/scribe.elc
new file mode 100644
index 00000000000..e54d4364876
--- /dev/null
+++ b/lisp/scribe.elc
Binary files differ
diff --git a/lisp/sendmail.el b/lisp/sendmail.el
new file mode 100644
index 00000000000..18a153d24ed
--- /dev/null
+++ b/lisp/sendmail.el
@@ -0,0 +1,469 @@
+;; Mail sending commands for Emacs.
+;; Copyright (C) 1985, 1986 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 1, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+(provide 'sendmail)
+
+;(defconst mail-self-blind nil
+; "Non-nil means insert BCC to self in messages to be sent.
+;This is done when the message is initialized,
+;so you can remove or alter the BCC field to override the default.")
+
+;(defconst mail-interactive nil
+; "Non-nil means when sending a message wait for and display errors.
+;nil means let mailer mail back a message to report errors.")
+
+;(defconst mail-yank-ignored-headers
+; "^via:\\|^mail-from:\\|^origin:\\|^status:\\|^remailed\\|^received:\\|^message-id:\\|^summary-line:\\|^to:\\|^subject:\\|^in-reply-to:\\|^return-path:"
+; "Delete these headers from old message when it's inserted in a reply.")
+;(defvar send-mail-function 'sendmail-send-it
+; "Function to call to send the current buffer as mail.
+;The headers are be delimited by a line which is mail-header-separator"")
+
+; really defined in loaddefs for emacs 17.17+
+;(defvar mail-header-separator "--text follows this line--"
+; "*Line used to separate headers from text in messages being composed.")
+; really defined in loaddefs for emacs 17.17+
+;(defvar mail-archive-file-name nil
+; "*Name of file to write all outgoing messages in, or nil for none.")
+; really defined in loaddefs for emacs 17.17+
+(defvar mail-aliases t
+ "Alias of mail address aliases,
+or t meaning should be initialized from .mailrc.")
+
+(defvar mail-default-reply-to nil
+ "*Address to insert as default Reply-to field of outgoing messages.")
+
+(defvar mail-abbrevs-loaded nil)
+(defvar mail-mode-map nil)
+
+(autoload 'build-mail-aliases "mailalias"
+ "Read mail aliases from ~/.mailrc and set mail-aliases."
+ nil)
+
+(autoload 'expand-mail-aliases "mailalias"
+ "Expand all mail aliases in suitable header fields found between BEG and END.
+Suitable header fields are To, CC and BCC."
+ nil)
+
+(defun mail-setup (to subject in-reply-to cc replybuffer)
+ (if (eq mail-aliases t)
+ (progn
+ (setq mail-aliases nil)
+ (if (file-exists-p "~/.mailrc")
+ (build-mail-aliases))))
+ (setq mail-reply-buffer replybuffer)
+ (goto-char (point-min))
+ (insert "To: ")
+ (save-excursion
+ (if to
+ (progn
+ (insert to "\n")
+ ;;; Here removed code to extract names from within <...>
+ ;;; on the assumption that mail-strip-quoted-names
+ ;;; has been called and has done so.
+ (let ((fill-prefix "\t"))
+ (fill-region (point-min) (point-max))))
+ (newline))
+ (if cc
+ (let ((opos (point))
+ (fill-prefix "\t"))
+ (insert "CC: " cc "\n")
+ (fill-region-as-paragraph opos (point-max))))
+ (if in-reply-to
+ (insert "In-reply-to: " in-reply-to "\n"))
+ (insert "Subject: " (or subject "") "\n")
+ (if mail-default-reply-to
+ (insert "Reply-to: " mail-default-reply-to "\n"))
+ (if mail-self-blind
+ (insert "BCC: " (user-login-name) "\n"))
+ (if mail-archive-file-name
+ (insert "FCC: " mail-archive-file-name "\n"))
+ (insert mail-header-separator "\n"))
+ (if to (goto-char (point-max)))
+ (or to subject in-reply-to
+ (set-buffer-modified-p nil))
+ (run-hooks 'mail-setup-hook))
+
+(defun mail-mode ()
+ "Major mode for editing mail to be sent.
+Separate names of recipients (in To: and Cc: fields) with commas.
+Like Text Mode but with these additional commands:
+C-c C-s mail-send (send the message) C-c C-c mail-send-and-exit
+C-c C-f move to a header field (and create it if there isn't):
+ C-c C-f C-t move to To: C-c C-f C-s move to Subj:
+ C-c C-f C-b move to BCC: C-c C-f C-c move to CC:
+C-c C-w mail-signature (insert ~/.signature at end).
+C-c C-y mail-yank-original (insert current message, in Rmail).
+C-c C-q mail-fill-yanked-message (fill what was yanked)."
+ (interactive)
+ (kill-all-local-variables)
+ (make-local-variable 'mail-reply-buffer)
+ (setq mail-reply-buffer nil)
+ (set-syntax-table text-mode-syntax-table)
+ (use-local-map mail-mode-map)
+ (setq local-abbrev-table text-mode-abbrev-table)
+ (setq major-mode 'mail-mode)
+ (setq mode-name "Mail")
+ (setq buffer-offer-save t)
+ (make-local-variable 'paragraph-separate)
+ (make-local-variable 'paragraph-start)
+ (setq paragraph-start (concat "^" mail-header-separator
+ "$\\|^[ \t]*[-_][-_][-_]+$\\|"
+ paragraph-start))
+ (setq paragraph-separate (concat "^" mail-header-separator
+ "$\\|^[ \t]*[-_][-_][-_]+$\\|"
+ paragraph-separate))
+ (run-hooks 'text-mode-hook 'mail-mode-hook))
+
+(if mail-mode-map
+ nil
+ (setq mail-mode-map (make-sparse-keymap))
+ (define-key mail-mode-map "\C-c?" 'describe-mode)
+ (define-key mail-mode-map "\C-c\C-f\C-t" 'mail-to)
+ (define-key mail-mode-map "\C-c\C-f\C-b" 'mail-bcc)
+ (define-key mail-mode-map "\C-c\C-f\C-c" 'mail-cc)
+ (define-key mail-mode-map "\C-c\C-f\C-s" 'mail-subject)
+ (define-key mail-mode-map "\C-c\C-w" 'mail-signature) ; who
+ (define-key mail-mode-map "\C-c\C-y" 'mail-yank-original)
+ (define-key mail-mode-map "\C-c\C-q" 'mail-fill-yanked-message)
+ (define-key mail-mode-map "\C-c\C-c" 'mail-send-and-exit)
+ (define-key mail-mode-map "\C-c\C-s" 'mail-send))
+
+(defun mail-send-and-exit (arg)
+ "Send message like mail-send, then, if no errors, exit from mail buffer.
+Prefix arg means don't delete this window."
+ (interactive "P")
+ (mail-send)
+ (bury-buffer (current-buffer))
+ (if (and (not arg)
+ (not (one-window-p))
+ (save-excursion
+ (set-buffer (window-buffer (next-window (selected-window) 'not)))
+ (eq major-mode 'rmail-mode)))
+ (delete-window)
+ (switch-to-buffer (other-buffer (current-buffer)))))
+
+(defun mail-send ()
+ "Send the message in the current buffer.
+If mail-interactive is non-nil, wait for success indication
+or error messages, and inform user.
+Otherwise any failure is reported in a message back to
+the user from the mailer."
+ (interactive)
+ (message "Sending...")
+ (funcall send-mail-function)
+ (set-buffer-modified-p nil)
+ (delete-auto-save-file-if-necessary)
+ (message "Sending...done"))
+
+(defun sendmail-send-it ()
+ (let ((errbuf (if mail-interactive
+ (generate-new-buffer " sendmail errors")
+ 0))
+ (tembuf (generate-new-buffer " sendmail temp"))
+ (case-fold-search nil)
+ delimline
+ (mailbuf (current-buffer)))
+ (unwind-protect
+ (save-excursion
+ (set-buffer tembuf)
+ (setq buffer-undo-list t)
+ (erase-buffer)
+ (insert-buffer-substring mailbuf)
+ (goto-char (point-max))
+ ;; require one newline at the end.
+ (or (= (preceding-char) ?\n)
+ (insert ?\n))
+ ;; Change header-delimiter to be what sendmail expects.
+ (goto-char (point-min))
+ (re-search-forward
+ (concat "^" (regexp-quote mail-header-separator) "\n"))
+ (replace-match "\n")
+ (backward-char 1)
+ (setq delimline (point-marker))
+ (if mail-aliases
+ (expand-mail-aliases (point-min) delimline))
+ (goto-char (point-min))
+ ;; ignore any blank lines in the header
+ (while (and (re-search-forward "\n\n\n*" delimline t)
+ (< (point) delimline))
+ (replace-match "\n"))
+ (let ((case-fold-search t))
+ ;; Find and handle any FCC fields.
+ (goto-char (point-min))
+ (if (re-search-forward "^FCC:" delimline t)
+ (mail-do-fcc delimline))
+ ;; If there is a From and no Sender, put it a Sender.
+ (goto-char (point-min))
+ (and (re-search-forward "^From:" delimline t)
+ (not (save-excursion
+ (goto-char (point-min))
+ (re-search-forward "^Sender:" delimline t)))
+ (progn
+ (forward-line 1)
+ (insert "Sender: " (user-login-name) "\n")))
+ ;; don't send out a blank subject line
+ (goto-char (point-min))
+ (if (re-search-forward "^Subject:[ \t]*\n" delimline t)
+ (replace-match ""))
+ (if mail-interactive
+ (save-excursion
+ (set-buffer errbuf)
+ (erase-buffer))))
+ (apply 'call-process-region
+ (append (list (point-min) (point-max)
+ (if (boundp 'sendmail-program)
+ sendmail-program
+ "/usr/lib/sendmail")
+ nil errbuf nil
+ "-oi" "-t")
+ ;; Always specify who from,
+ ;; since some systems have broken sendmails.
+ (list "-f" (user-login-name))
+;;; ;; Don't say "from root" if running under su.
+;;; (and (equal (user-real-login-name) "root")
+;;; (list "-f" (user-login-name)))
+ ;; These mean "report errors by mail"
+ ;; and "deliver in background".
+ (if (null mail-interactive) '("-oem" "-odb"))))
+ (if mail-interactive
+ (save-excursion
+ (set-buffer errbuf)
+ (goto-char (point-min))
+ (while (re-search-forward "\n\n* *" nil t)
+ (replace-match "; "))
+ (if (not (zerop (buffer-size)))
+ (error "Sending...failed to %s"
+ (buffer-substring (point-min) (point-max)))))))
+ (kill-buffer tembuf)
+ (if (bufferp errbuf)
+ (kill-buffer errbuf)))))
+
+(defun mail-do-fcc (header-end)
+ (let (fcc-list
+ (rmailbuf (current-buffer))
+ timezone
+ (tembuf (generate-new-buffer " rmail output"))
+ (case-fold-search t))
+ (save-excursion
+ (goto-char (point-min))
+ (while (re-search-forward "^FCC:[ \t]*" header-end t)
+ (setq fcc-list (cons (buffer-substring (point)
+ (progn
+ (end-of-line)
+ (skip-chars-backward " \t")
+ (point)))
+ fcc-list))
+ (delete-region (match-beginning 0)
+ (progn (forward-line 1) (point))))
+ (set-buffer tembuf)
+ (erase-buffer)
+ (call-process "date" nil t nil)
+ (goto-char (point-min))
+ (re-search-forward
+ "[0-9] \\([A-Za-z][A-Za-z ]*[A-Za-z]\\)[0-9 ]*$")
+ (setq timezone (buffer-substring (match-beginning 1) (match-end 1)))
+ (erase-buffer)
+ (insert "\nFrom " (user-login-name) " "
+ (current-time-string) "\n")
+ ;; Insert the time zone before the year.
+ (forward-char -1)
+ (forward-word -1)
+ (insert timezone " ")
+ (goto-char (point-max))
+ (insert-buffer-substring rmailbuf)
+ ;; Make sure messages are separated.
+ (goto-char (point-max))
+ (insert ?\n)
+ (goto-char 2)
+ ;; ``Quote'' "^From " as ">From "
+ ;; (note that this isn't really quoting, as there is no requirement
+ ;; that "^[>]+From " be quoted in the same transparent way.)
+ (let ((case-fold-search nil))
+ (while (search-forward "\nFrom " nil t)
+ (forward-char -5)
+ (insert ?>)))
+ (while fcc-list
+ (let ((buffer (get-file-buffer (car fcc-list))))
+ (if buffer
+ ;; File is present in a buffer => append to that buffer.
+ (let ((curbuf (current-buffer))
+ (beg (point-min)) (end (point-max)))
+ (save-excursion
+ (set-buffer buffer)
+ (goto-char (point-max))
+ (insert-buffer-substring curbuf beg end)))
+ ;; Else append to the file directly.
+ (write-region (point-min) (point-max) (car fcc-list) t)))
+ (setq fcc-list (cdr fcc-list))))
+ (kill-buffer tembuf)))
+
+(defun mail-to ()
+ "Move point to end of To-field."
+ (interactive)
+ (expand-abbrev)
+ (mail-position-on-field "To"))
+
+(defun mail-subject ()
+ "Move point to end of Subject-field."
+ (interactive)
+ (expand-abbrev)
+ (mail-position-on-field "Subject"))
+
+(defun mail-cc ()
+ "Move point to end of CC-field. Create a CC field if none."
+ (interactive)
+ (expand-abbrev)
+ (or (mail-position-on-field "cc" t)
+ (progn (mail-position-on-field "to")
+ (insert "\nCC: "))))
+
+(defun mail-bcc ()
+ "Move point to end of BCC-field. Create a BCC field if none."
+ (interactive)
+ (expand-abbrev)
+ (or (mail-position-on-field "bcc" t)
+ (progn (mail-position-on-field "to")
+ (insert "\nBCC: "))))
+
+(defun mail-position-on-field (field &optional soft)
+ (let (end
+ (case-fold-search t))
+ (goto-char (point-min))
+ (re-search-forward
+ (concat "^" (regexp-quote mail-header-separator) "\n"))
+ (setq end (match-beginning 0))
+ (goto-char (point-min))
+ (if (re-search-forward (concat "^" (regexp-quote field) ":") end t)
+ (progn
+ (re-search-forward "^[^ \t]" nil 'move)
+ (beginning-of-line)
+ (skip-chars-backward "\n")
+ t)
+ (or soft
+ (progn (goto-char end)
+ (insert field ": \n")
+ (skip-chars-backward "\n")))
+ nil)))
+
+(defun mail-signature ()
+ "Sign letter with contents of ~/.signature file."
+ (interactive)
+ (save-excursion
+ (goto-char (point-max))
+ (insert-file-contents (expand-file-name "~/.signature"))))
+
+(defun mail-fill-yanked-message (&optional justifyp)
+ "Fill the paragraphs of a message yanked into this one.
+Numeric argument means justify as well."
+ (interactive "P")
+ (save-excursion
+ (goto-char (point-min))
+ (search-forward (concat "\n" mail-header-separator "\n") nil t)
+ (fill-individual-paragraphs (point)
+ (point-max)
+ justifyp
+ t)))
+(defun mail-yank-original (arg)
+ "Insert the message being replied to, if any (in rmail).
+Puts point before the text and mark after.
+Indents each nonblank line ARG spaces (default 3).
+Just \\[universal-argument] as argument means don't indent
+and don't delete any header fields."
+ (interactive "P")
+ (if mail-reply-buffer
+ (let ((start (point)))
+ (delete-windows-on mail-reply-buffer)
+ (insert-buffer mail-reply-buffer)
+ (if (consp arg)
+ nil
+ (mail-yank-clear-headers start (mark))
+ (indent-rigidly start (mark)
+ (if arg (prefix-numeric-value arg) 3)))
+ (exchange-point-and-mark)
+ (if (not (eolp)) (insert ?\n)))))
+
+(defun mail-yank-clear-headers (start end)
+ (save-excursion
+ (goto-char start)
+ (if (search-forward "\n\n" end t)
+ (save-restriction
+ (narrow-to-region start (point))
+ (goto-char start)
+ (while (let ((case-fold-search t))
+ (re-search-forward mail-yank-ignored-headers nil t))
+ (beginning-of-line)
+ (delete-region (point)
+ (progn (re-search-forward "\n[^ \t]")
+ (forward-char -1)
+ (point))))))))
+
+;; Put these last, to reduce chance of lossage from quitting in middle of loading the file.
+
+(defun mail (&optional noerase to subject in-reply-to cc replybuffer)
+ "Edit a message to be sent. Argument means resume editing (don't erase).
+Returns with message buffer selected; value t if message freshly initialized.
+While editing message, type C-c C-c to send the message and exit.
+
+Separate names of recipients with commas.
+
+Various special commands starting with C-c are available in sendmail mode
+to move to message header fields:
+\\{mail-mode-map}
+
+If mail-self-blind is non-nil, a BCC to yourself is inserted
+when the message is initialized.
+
+If mail-default-reply-to is non-nil, it should be an address (a string);
+a Reply-to: field with that address is inserted.
+
+If mail-archive-file-name is non-nil, an FCC field with that file name
+is inserted.
+
+If mail-setup-hook is bound, its value is run by means of run-hooks
+after the message is initialized. It can add more default fields.
+See the documentation of run-hooks.
+
+When calling from a program, the second through fifth arguments
+ TO, SUBJECT, IN-REPLY-TO and CC specify if non-nil
+ the initial contents of those header fields.
+ These arguments should not have final newlines.
+The sixth argument REPLYBUFFER is a buffer whose contents
+ should be yanked if the user types C-c C-y."
+ (interactive "P")
+ (switch-to-buffer "*mail*")
+ (setq default-directory (expand-file-name "~/"))
+ (auto-save-mode auto-save-default)
+ (mail-mode)
+ (and (not noerase)
+ (or (not (buffer-modified-p))
+ (y-or-n-p "Unsent message being composed; erase it? "))
+ (progn (erase-buffer)
+ (mail-setup to subject in-reply-to cc replybuffer)
+ t)))
+
+(defun mail-other-window (&optional noerase to subject in-reply-to cc replybuffer)
+ "Like `mail' command, but display mail buffer in another window."
+ (interactive "P")
+ (let ((pop-up-windows t))
+ (pop-to-buffer "*mail*"))
+ (mail noerase to subject in-reply-to cc replybuffer))
+
+;;; Do not add anything but external entries on this page.
diff --git a/lisp/sendmail.elc b/lisp/sendmail.elc
new file mode 100644
index 00000000000..37b2436f202
--- /dev/null
+++ b/lisp/sendmail.elc
Binary files differ
diff --git a/lisp/server.el b/lisp/server.el
index f6518777d2c..7ea05841441 100644
--- a/lisp/server.el
+++ b/lisp/server.el
@@ -1,5 +1,5 @@
;; Lisp code for GNU Emacs running as server process.
-;; Copyright (C) 1986, 1987 Free Software Foundation, Inc.
+;; Copyright (C) 1986, 1987, 1990 Free Software Foundation, Inc.
;; Author William Sommerfeld, wesommer@athena.mit.edu.
;; Changes by peck@sun.com and by rms.
@@ -24,7 +24,7 @@
;;; a server for other processes.
;;; Load this library and do M-x server-edit to enable Emacs as a server.
-;;; Emacs runs the program ../etc/emacsserver as a subprocess
+;;; Emacs runs the program ../etc/server as a subprocess
;;; for communication with clients. If there are no client buffers to edit,
;;; server-edit acts like (switch-to-buffer (other-buffer))
@@ -44,34 +44,22 @@
;;; Your editing commands and Emacs's display output go to and from
;;; the terminal in the usual way. Thus, server operation is possible
;;; only when Emacs can talk to the terminal at the time you invoke
-;;; the client. This is possible in four cases:
+;;; the client. This is possible in two cases:
;;; 1. On a window system, where Emacs runs in one window and the
;;; program that wants to use "the editor" runs in another.
-;;; 2. On a multi-terminal system, where Emacs runs on one terminal and the
-;;; program that wants to use "the editor" runs on another.
-
-;;; 3. When the program that wants to use "the editor" is running
+;;; 2. When the program that wants to use "the editor" is running
;;; as a subprocess of Emacs.
-;;; 4. On a system with job control, when Emacs is suspended, the program
-;;; that wants to use "the editor" will stop and display
-;;; "Waiting for Emacs...". It can then be suspended, and Emacs can be
-;;; brought into the foreground for editing. When done editing, Emacs is
-;;; suspended again, and the client program is brought into the foreground.
-
;;; The buffer local variable "server-buffer-clients" lists
;;; the clients who are waiting for this buffer to be edited.
;;; The global variable "server-clients" lists all the waiting clients,
;;; and which files are yet to be edited for each.
-(defvar server-program "emacsserver"
+(defvar server-program "server"
"*The program to use as the edit server")
-(defvar server-visit-hook nil
- "*List of hooks to call when switching to a buffer for the Emacs server.")
-
(defvar server-process nil
"the current server process")
@@ -85,13 +73,6 @@ When a buffer is marked as \"done\", it is removed from this list.")
(defvar server-buffer-clients nil
"List of clientids for clients requesting editing of current buffer.")
-;; Changing major modes should not erase this local.
-(put 'server-buffer-clients 'permanent-local t)
-
-(defvar server-temp-file-regexp "^/tmp/Re\\|/draft$"
- "*Regexp which should match filenames of temporary files
-which are deleted and reused after each edit
-by the programs that invoke the emacs server.")
(make-variable-buffer-local 'server-buffer-clients)
(setq-default server-buffer-clients nil)
@@ -129,6 +110,9 @@ Prefix arg means just kill any existing server communications subprocess."
(set-process-sentinel server-process nil)
(condition-case () (delete-process server-process) (error nil))))
(condition-case () (delete-file "~/.emacs_server") (error nil))
+ (condition-case ()
+ (delete-file (format "/tmp/esrv%d-%s" (user-uid) (system-name)))
+ (error nil))
;; If we already had a server, clear out associated status.
(while server-clients
(let ((buffer (nth 1 (car server-clients))))
@@ -137,7 +121,8 @@ Prefix arg means just kill any existing server communications subprocess."
nil
(if server-process
(server-log (message "Restarting server")))
- (setq server-process (start-process "server" nil server-program))
+ (let ((process-connection-type nil))
+ (setq server-process (start-process "server" nil server-program)))
(set-process-sentinel server-process 'server-sentinel)
(set-process-filter server-process 'server-process-filter)
(process-kill-without-query server-process)))
@@ -196,8 +181,7 @@ FILES is an alist whose elements are (FILENAME LINENUMBER)."
filen
", write buffer to file? "))
(write-file filen)))
- (set-buffer (find-file-noselect filen))
- (run-hooks 'server-visit-hook)))
+ (set-buffer (find-file-noselect filen))))
(goto-line (nth 1 (car files)))
(setq server-buffer-clients (cons (car client) server-buffer-clients))
(setq client-record (cons (current-buffer) client-record)))
@@ -233,15 +217,11 @@ as a suggestion for what to select next."
(bury-buffer buffer)
next-buffer))
-(defun server-temp-file-p (buffer)
- "Return non-nil if BUFFER contains a file considered temporary.
-These are files whose names suggest they are repeatedly
-reused to pass information to another program.
-
-The variable `server-temp-file-regexp' controls which filenames
-are considered temporary."
- (and (buffer-file-name buffer)
- (string-match server-temp-file-regexp (buffer-file-name buffer))))
+(defun mh-draft-p (buffer)
+ "Return non-nil if this BUFFER is an mh <draft> file.
+Since MH deletes draft *BEFORE* it is edited, the server treats them specially."
+ ;; This may not be appropriately robust for all cases.
+ (string= (buffer-name buffer) "draft"))
(defun server-done ()
"Offer to save current buffer, mark it as \"done\" for clients,
@@ -249,7 +229,7 @@ bury it, and return a suggested buffer to select next."
(let ((buffer (current-buffer)))
(if server-buffer-clients
(progn
- (if (server-temp-file-p buffer)
+ (if (mh-draft-p buffer)
(progn (save-buffer)
(write-region (point-min) (point-max)
(concat buffer-file-name "~"))
@@ -262,15 +242,11 @@ bury it, and return a suggested buffer to select next."
(defun server-edit (&optional arg)
"Switch to next server editing buffer; say \"Done\" for current buffer.
If a server buffer is current, it is marked \"done\" and optionally saved.
+MH <draft> files are always saved and backed up, no questions asked.
When all of a client's buffers are marked as \"done\", the client is notified.
-Temporary files such as MH <draft> files are always saved and backed up,
-no questions asked. The variable `server-temp-file-regexp' controls
-which filenames are considered temporary.
-
If invoked with a prefix argument, or if there is no server process running,
starts server process and that is all. Invoked by \\[server-edit]."
-
(interactive "P")
(if (or arg
(not server-process)
diff --git a/lisp/server.elc b/lisp/server.elc
new file mode 100644
index 00000000000..0a8e8888ed4
--- /dev/null
+++ b/lisp/server.elc
Binary files differ
diff --git a/lisp/shell.el b/lisp/shell.el
index 64c069bf05d..9198a11c535 100644
--- a/lisp/shell.el
+++ b/lisp/shell.el
@@ -1,6 +1,6 @@
-;; -*-Emacs-Lisp-*- run a shell in an Emacs window
-;; Copyright (C) 1985, 1986, 1987, 1990 Free Software Foundation, Inc.
-
+;; Run subshell under Emacs
+;; Copyright (C) 1985, 1986, 1987, 1988 Free Software Foundation, Inc.
+
;; This file is part of GNU Emacs.
;; GNU Emacs is free software; you can redistribute it and/or modify
@@ -17,23 +17,18 @@
;; along with GNU Emacs; see the file COPYING. If not, write to
;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-;;; Hacked from tea.el and shell.el by Olin Shivers (shivers@cs.cmu.edu). 8/88
-;;; Since this mode is built on top of the general command-interpreter-in-
-;;; a-buffer mode (comint mode), it shares a common base functionality,
-;;; and a common set of bindings, with all modes derived from comint mode.
+(provide 'shell)
-;;; For documentation on the functionality provided by comint mode, and
-;;; the hooks available for customising it, see the file comint.el.
+(defvar last-input-start nil
+ "In a shell-mode buffer, marker for start of last unit of input.")
+(defvar last-input-end nil
+ "In a shell-mode buffer, marker for end of last unit of input.")
-;;; Needs fixin:
-;;; When sending text from a source file to a subprocess, the process-mark can
-;;; move off the window, so you can lose sight of the process interactions.
-;;; Maybe I should ensure the process mark is in the window when I send
-;;; text to the process? Switch selectable?
+(defvar shell-mode-map nil)
-(require 'comint)
-(provide 'shell)
+(defvar shell-directory-stack nil
+ "List of directories saved by pushd in this buffer's shell.")
(defvar shell-popd-regexp "popd"
"*Regexp to match subshell commands equivalent to popd.")
@@ -47,346 +42,409 @@
(defvar explicit-shell-file-name nil
"*If non-nil, is file name to use for explicitly requested inferior shell.")
-(defvar explicit-csh-args
- (if (eq system-type 'hpux)
- ;; -T persuades HP's csh not to think it is smarter
- ;; than us about what terminal modes to use.
- '("-i" "-T")
- '("-i"))
- "*Args passed to inferior shell by M-x shell, if the shell is csh.
-Value is a list of strings, which may be nil.")
-
-(defvar shell-dirstack nil
- "List of directories saved by pushd in this buffer's shell.")
-
-(defvar shell-dirstack-query "dirs"
- "Command used by shell-resync-dirlist to query shell.")
-
-(defvar shell-mode-map ())
-(cond ((not shell-mode-map)
- (setq shell-mode-map (copy-keymap comint-mode-map))
- (define-key shell-mode-map "\t" 'comint-dynamic-complete)
- (define-key shell-mode-map "\M-?" 'comint-dynamic-list-completions)))
-
-(defvar shell-mode-hook '()
- "*Hook for customising shell mode")
-
-
-;;; Basic Procedures
-;;; ===========================================================================
-;;;
+;In loaddefs.el now.
+;(defconst shell-prompt-pattern
+; "^[^#$%>]*[#$%>] *"
+; "*Regexp used by Newline command to match subshell prompts.
+;Anything from beginning of line up to the end of what this pattern matches
+;is deemed to be prompt, and is not reexecuted.")
(defun shell-mode ()
"Major mode for interacting with an inferior shell.
-Return after the end of the process' output sends the text from the
- end of process to the end of the current line.
-Return before end of process output copies rest of line to end (skipping
- the prompt) and sends it.
-M-x send-invisible reads a line of text without echoing it, and sends it to
- the shell.
-
-If you accidentally suspend your process, use \\[comint-continue-subjob]
-to continue it.
-
-cd, pushd and popd commands given to the shell are watched by Emacs to keep
-this buffer's default directory the same as the shell's working directory.
-M-x dirs queries the shell and resyncs Emacs' idea of what the current
- directory stack is.
-M-x dirtrack-toggle turns directory tracking on and off.
+Shell name is same as buffer name, sans the asterisks.
+Return at end of buffer sends line as input.
+Return not at end copies rest of line to end and sends it.
+The following commands imitate the usual Unix interrupt and
+editing control characters:
\\{shell-mode-map}
-Customisation: Entry to this mode runs the hooks on comint-mode-hook and
-shell-mode-hook (in that order).
-Variables shell-cd-regexp, shell-pushd-regexp and shell-popd-regexp are used
-to match their respective commands."
+Entry to this mode calls the value of shell-mode-hook with no args,
+if that value is non-nil.
+
+cd, pushd and popd commands given to the shell are watched
+by Emacs to keep this buffer's default directory
+the same as the shell's working directory.
+Variables shell-cd-regexp, shell-pushd-regexp and shell-popd-regexp
+are used to match these command names.
+
+You can send text to the shell (or its subjobs) from other buffers
+using the commands process-send-region, process-send-string
+and lisp-send-defun."
(interactive)
- (comint-mode)
- (setq major-mode 'shell-mode
- mode-name "Shell"
- comint-prompt-regexp shell-prompt-pattern
- comint-input-sentinel 'shell-directory-tracker)
+ (kill-all-local-variables)
+ (setq major-mode 'shell-mode)
+ (setq mode-name "Shell")
+ (setq mode-line-process '(": %s"))
(use-local-map shell-mode-map)
- (make-local-variable 'shell-dirstack)
- (set (make-local-variable 'shell-dirtrackp) t)
+ (make-local-variable 'shell-directory-stack)
+ (setq shell-directory-stack nil)
+ (make-local-variable 'last-input-start)
+ (setq last-input-start (make-marker))
+ (make-local-variable 'last-input-end)
+ (setq last-input-end (make-marker))
(run-hooks 'shell-mode-hook))
+(if shell-mode-map
+ nil
+ (setq shell-mode-map (make-sparse-keymap))
+ (define-key shell-mode-map "\C-m" 'shell-send-input)
+ (define-key shell-mode-map "\C-c\C-d" 'shell-send-eof)
+ (define-key shell-mode-map "\C-c\C-u" 'kill-shell-input)
+ (define-key shell-mode-map "\C-c\C-w" 'backward-kill-word)
+ (define-key shell-mode-map "\C-c\C-c" 'interrupt-shell-subjob)
+ (define-key shell-mode-map "\C-c\C-z" 'stop-shell-subjob)
+ (define-key shell-mode-map "\C-c\C-\\" 'quit-shell-subjob)
+ (define-key shell-mode-map "\C-c\C-o" 'kill-output-from-shell)
+ (define-key shell-mode-map "\C-c\C-r" 'show-output-from-shell)
+ (define-key shell-mode-map "\C-c\C-y" 'copy-last-shell-input))
+(defvar explicit-csh-args
+ (if (eq system-type 'hpux)
+ ;; -T persuades HP's csh not to think it is smarter
+ ;; than us about what terminal modes to use.
+ '("-i" "-T")
+ '("-i"))
+ "Args passed to inferior shell by M-x shell, if the shell is csh.
+Value is a list of strings, which may be nil.")
+
(defun shell ()
"Run an inferior shell, with I/O through buffer *shell*.
If buffer exists but shell process is not running, make new shell.
-If buffer exists and shell process is running, just switch to buffer *shell*.
-
-The shell to use comes from the first non-nil variable found from these:
-explicit-shell-file-name in Emacs, ESHELL in the environment or SHELL in the
-environment. If none is found, /bin/sh is used.
-
-If a file ~/.emacs_SHELLNAME exists, it is given as initial input, simulating
-a start-up file for the shell like .profile or .cshrc. Note that this may
-lose due to a timing error if the shell discards input when it starts up.
-
+Program used comes from variable explicit-shell-file-name,
+ or (if that is nil) from the ESHELL environment variable,
+ or else from SHELL if there is no ESHELL.
+If a file ~/.emacs_SHELLNAME exists, it is given as initial input
+ (Note that this may lose due to a timing error if the shell
+ discards input when it starts up.)
The buffer is put in shell-mode, giving commands for sending input
-and controlling the subjobs of the shell.
+and controlling the subjobs of the shell. See shell-mode.
+See also variable shell-prompt-pattern.
-The shell file name, sans directories, is used to make a symbol name
+The shell file name (sans directories) is used to make a symbol name
such as `explicit-csh-arguments'. If that symbol is a variable,
its value is used as a list of arguments when invoking the shell.
Otherwise, one argument `-i' is passed to the shell.
-\(Type \\[describe-mode] in the shell buffer for a list of commands.)"
+Note that many people's .cshrc files unconditionally clear the prompt.
+If yours does, you will probably want to change it."
+ (interactive)
+ (let* ((prog (or explicit-shell-file-name
+ (getenv "ESHELL")
+ (getenv "SHELL")
+ "/bin/sh"))
+ (name (file-name-nondirectory prog)))
+ (switch-to-buffer
+ (apply 'make-shell "shell" prog
+ (if (file-exists-p (concat "~/.emacs_" name))
+ (concat "~/.emacs_" name))
+ (let ((symbol (intern-soft (concat "explicit-" name "-args"))))
+ (if (and symbol (boundp symbol))
+ (symbol-value symbol)
+ '("-i")))))))
+
+(defun make-shell (name program &optional startfile &rest switches)
+ (let ((buffer (get-buffer-create (concat "*" name "*")))
+ proc status size)
+ (setq proc (get-buffer-process buffer))
+ (if proc (setq status (process-status proc)))
+ (save-excursion
+ (set-buffer buffer)
+ ;; (setq size (buffer-size))
+ (if (memq status '(run stop))
+ nil
+ (if proc (delete-process proc))
+ (setq proc (apply 'start-process name buffer
+ (concat exec-directory "env")
+ (format "TERMCAP=emacs:co#%d:tc=unknown:"
+ (screen-width))
+ "TERM=emacs"
+ "EMACS=t"
+ "-"
+ (or program explicit-shell-file-name
+ (getenv "ESHELL")
+ (getenv "SHELL")
+ "/bin/sh")
+ switches))
+ (cond (startfile
+ ;;This is guaranteed to wait long enough
+ ;;but has bad results if the shell does not prompt at all
+ ;; (while (= size (buffer-size))
+ ;; (sleep-for 1))
+ ;;I hope 1 second is enough!
+ (sleep-for 1)
+ (goto-char (point-max))
+ (insert-file-contents startfile)
+ (setq startfile (buffer-substring (point) (point-max)))
+ (delete-region (point) (point-max))
+ (process-send-string proc startfile)))
+ (setq name (process-name proc)))
+ (goto-char (point-max))
+ (set-marker (process-mark proc) (point))
+ (or (eq major-mode 'shell-mode) (shell-mode)))
+ buffer))
+
+(defvar shell-set-directory-error-hook 'ignore
+ "Function called with no arguments when shell-send-input
+recognizes a change-directory command but gets an error
+trying to change Emacs's default directory.")
+
+(defun shell-send-input ()
+ "Send input to subshell.
+At end of buffer, sends all text after last output
+ as input to the subshell, including a newline inserted at the end.
+When not at end, copies current line to the end of the buffer and sends it,
+after first attempting to discard any prompt at the beginning of the line
+by matching the regexp that is the value of shell-prompt-pattern if possible.
+This regexp should start with \"^\"."
+ (interactive)
+ (or (get-buffer-process (current-buffer))
+ (error "Current buffer has no process"))
+ (end-of-line)
+ (if (eobp)
+ (progn
+ (move-marker last-input-start
+ (process-mark (get-buffer-process (current-buffer))))
+ (insert ?\n)
+ (move-marker last-input-end (point)))
+ (beginning-of-line)
+ ;; Exclude the shell prompt, if any.
+ (re-search-forward shell-prompt-pattern
+ (save-excursion (end-of-line) (point))
+ t)
+ (let ((copy (buffer-substring (point)
+ (progn (forward-line 1) (point)))))
+ (goto-char (point-max))
+ (move-marker last-input-start (point))
+ (insert copy)
+ (move-marker last-input-end (point))))
+ ;; Even if we get an error trying to hack the working directory,
+ ;; still send the input to the subshell.
+ (condition-case ()
+ (save-excursion
+ (goto-char last-input-start)
+ (shell-set-directory))
+ (error (funcall shell-set-directory-error-hook)))
+ (let ((process (get-buffer-process (current-buffer))))
+ (process-send-region process last-input-start last-input-end)
+ (set-marker (process-mark process) (point))))
+
+;;; If this code changes (shell-send-input and shell-set-directory),
+;;; the customization tutorial in
+;;; info/customizing-tutorial must also change, since it explains this
+;;; code. Please let marick@gswd-vms.arpa know of any changes you
+;;; make.
+
+(defun shell-set-directory ()
+ (cond ((and (looking-at shell-popd-regexp)
+ (memq (char-after (match-end 0)) '(?\; ?\n)))
+ (if shell-directory-stack
+ (progn
+ (cd (car shell-directory-stack))
+ (setq shell-directory-stack (cdr shell-directory-stack)))))
+ ((looking-at shell-pushd-regexp)
+ (cond ((memq (char-after (match-end 0)) '(?\; ?\n))
+ (if shell-directory-stack
+ (let ((old default-directory))
+ (cd (car shell-directory-stack))
+ (setq shell-directory-stack
+ (cons old (cdr shell-directory-stack))))))
+ ((memq (char-after (match-end 0)) '(?\ ?\t))
+ (let (dir)
+ (skip-chars-forward "^ ")
+ (skip-chars-forward " \t")
+ (if (file-directory-p
+ (setq dir
+ (expand-file-name
+ (substitute-in-file-name
+ (buffer-substring
+ (point)
+ (progn
+ (skip-chars-forward "^\n \t;")
+ (point)))))))
+ (progn
+ (setq shell-directory-stack
+ (cons default-directory shell-directory-stack))
+ (cd dir)))))))
+ ((looking-at shell-cd-regexp)
+ (cond ((memq (char-after (match-end 0)) '(?\; ?\n))
+ (cd (getenv "HOME")))
+ ((memq (char-after (match-end 0)) '(?\ ?\t))
+ (let (dir)
+ (forward-char 3)
+ (skip-chars-forward " \t")
+ (if (file-directory-p
+ (setq dir
+ (expand-file-name
+ (substitute-in-file-name
+ (buffer-substring
+ (point)
+ (progn
+ (skip-chars-forward "^\n \t;")
+ (point)))))))
+ (cd dir))))))))
+
+(defun shell-send-eof ()
+ "Send eof to subshell (or to the program running under it)."
+ (interactive)
+ (process-send-eof))
+
+(defun kill-output-from-shell ()
+ "Kill all output from shell since last input."
+ (interactive)
+ (goto-char (point-max))
+ (beginning-of-line)
+ (kill-region last-input-end (point))
+ (insert "*** output flushed ***\n")
+ (goto-char (point-max)))
+
+(defun show-output-from-shell ()
+ "Display start of this batch of shell output at top of window.
+Also put cursor there."
+ (interactive)
+ (set-window-start (selected-window) last-input-end)
+ (goto-char last-input-end))
+
+(defun copy-last-shell-input ()
+ "Copy previous shell input, sans newline, and insert before point."
(interactive)
- (cond ((not (comint-check-proc "*shell*"))
- (let* ((prog (or explicit-shell-file-name
- (getenv "ESHELL")
- (getenv "SHELL")
- "/bin/sh"))
- (name (file-name-nondirectory prog))
- (startfile (concat "~/.emacs_" name))
- (xargs-name (intern-soft (concat "explicit-" name "-args"))))
- (set-buffer (apply 'make-comint "shell" prog
- (if (file-exists-p startfile) startfile)
- (if (and xargs-name (boundp xargs-name))
- (symbol-value xargs-name)
- '("-i"))))
- (shell-mode))))
- (switch-to-buffer "*shell*"))
+ (insert (buffer-substring last-input-end last-input-start))
+ (delete-char -1))
+(defun interrupt-shell-subjob ()
+ "Interrupt this shell's current subjob."
+ (interactive)
+ (interrupt-process nil t))
+
+(defun kill-shell-subjob ()
+ "Send kill signal to this shell's current subjob."
+ (interactive)
+ (kill-process nil t))
+
+(defun quit-shell-subjob ()
+ "Send quit signal to this shell's current subjob."
+ (interactive)
+ (quit-process nil t))
+
+(defun stop-shell-subjob ()
+ "Stop this shell's current subjob."
+ (interactive)
+ (stop-process nil t))
+
+(defun kill-shell-input ()
+ "Kill all text since last stuff output by the shell or its subjobs."
+ (interactive)
+ (kill-region (process-mark (get-buffer-process (current-buffer)))
+ (point)))
-;;; Directory tracking
-;;; ===========================================================================
-;;; This code provides the shell mode input sentinel
-;;; SHELL-DIRECTORY-TRACKER
-;;; that tracks cd, pushd, and popd commands issued to the shell, and
-;;; changes the current directory of the shell buffer accordingly.
-;;;
-;;; This is basically a fragile hack, although it's more accurate than
-;;; the original version in shell.el. It has the following failings:
-;;; 1. It doesn't know about the cdpath shell variable.
-;;; 2. It only spots the first command in a command sequence. E.g., it will
-;;; miss the cd in "ls; cd foo"
-;;; 3. More generally, any complex command (like ";" sequencing) is going to
-;;; throw it. Otherwise, you'd have to build an entire shell interpreter in
-;;; emacs lisp. Failing that, there's no way to catch shell commands where
-;;; cd's are buried inside conditional expressions, aliases, and so forth.
-;;;
-;;; The whole approach is a crock. Shell aliases mess it up. File sourcing
-;;; messes it up. You run other processes under the shell; these each have
-;;; separate working directories, and some have commands for manipulating
-;;; their w.d.'s (e.g., the lcd command in ftp). Some of these programs have
-;;; commands that do *not* effect the current w.d. at all, but look like they
-;;; do (e.g., the cd command in ftp). In shells that allow you job
-;;; control, you can switch between jobs, all having different w.d.'s. So
-;;; simply saying %3 can shift your w.d..
-;;;
-;;; The solution is to relax, not stress out about it, and settle for
-;;; a hack that works pretty well in typical circumstances. Remember
-;;; that a half-assed solution is more in keeping with the spirit of Unix,
-;;; anyway. Blech.
-;;;
-;;; One good hack not implemented here for users of programmable shells
-;;; is to program up the shell w.d. manipulation commands to output
-;;; a coded command sequence to the tty. Something like
-;;; ESC | <cwd> |
-;;; where <cwd> is the new current working directory. Then trash the
-;;; directory tracking machinery currently used in this package, and
-;;; replace it with a process filter that watches for and strips out
-;;; these messages.
-
-;;; REGEXP is a regular expression. STR is a string. START is a fixnum.
-;;; Returns T if REGEXP matches STR where the match is anchored to start
-;;; at position START in STR. Sort of like LOOKING-AT for strings.
-(defun shell-front-match (regexp str start)
- (eq start (string-match regexp str start)))
-
-(defun shell-directory-tracker (str)
- "Tracks cd, pushd and popd commands issued to the shell.
-This function is called on each input passed to the shell.
-It watches for cd, pushd and popd commands and sets the buffer's
-default directory to track these commands.
-
-You may toggle this tracking on and off with M-x dirtrack-toggle.
-If emacs gets confused, you can resync with the shell with M-x dirs.
-
-See variables shell-cd-regexp, shell-pushd-regexp, and shell-popd-regexp.
-Environment variables are expanded, see function substitute-in-file-name."
- (condition-case err
- (cond (shell-dirtrackp
- (string-match "^\\s *" str) ; skip whitespace
- (let ((bos (match-end 0))
- (x nil))
- (cond ((setq x (shell-match-cmd-w/optional-arg shell-popd-regexp
- str bos))
- (shell-process-popd (substitute-in-file-name x)))
- ((setq x (shell-match-cmd-w/optional-arg shell-pushd-regexp
- str bos))
- (shell-process-pushd (substitute-in-file-name x)))
- ((setq x (shell-match-cmd-w/optional-arg shell-cd-regexp
- str bos))
- (shell-process-cd (substitute-in-file-name x)))))))
- (error (message (car (cdr err))))))
-
-
-;;; Try to match regexp CMD to string, anchored at position START.
-;;; CMD may be followed by a single argument. If a match, then return
-;;; the argument, if there is one, or the empty string if not. If
-;;; no match, return nil.
-
-(defun shell-match-cmd-w/optional-arg (cmd str start)
- (and (shell-front-match cmd str start)
- (let ((eoc (match-end 0))) ; end of command
- (cond ((shell-front-match "\\s *\\(\;\\|$\\)" str eoc)
- "") ; no arg
- ((shell-front-match "\\s +\\([^ \t\;]+\\)\\s *\\(\;\\|$\\)"
- str eoc)
- (substring str (match-beginning 1) (match-end 1))) ; arg
- (t nil))))) ; something else.
-;;; The first regexp is [optional whitespace, (";" or the end of string)].
-;;; The second regexp is [whitespace, (an arg), optional whitespace,
-;;; (";" or end of string)].
-
-
-;;; popd [+n]
-(defun shell-process-popd (arg)
- (let ((num (if (zerop (length arg)) 0 ; no arg means +0
- (shell-extract-num arg))))
- (if (and num (< num (length shell-dirstack)))
- (if (= num 0) ; condition-case because the CD could lose.
- (condition-case nil (progn (cd (car shell-dirstack))
- (setq shell-dirstack
- (cdr shell-dirstack))
- (shell-dirstack-message))
- (error (message "Couldn't cd.")))
- (let* ((ds (cons nil shell-dirstack))
- (cell (nthcdr (- num 1) ds)))
- (rplacd cell (cdr (cdr cell)))
- (setq shell-dirstack (cdr ds))
- (shell-dirstack-message)))
- (message "Bad popd."))))
-
-
-;;; cd [dir]
-(defun shell-process-cd (arg)
- (condition-case nil (progn (cd (if (zerop (length arg)) (getenv "HOME")
- arg))
- (shell-dirstack-message))
- (error (message "Couldn't cd."))))
-
-
-;;; pushd [+n | dir]
-(defun shell-process-pushd (arg)
- (if (zerop (length arg))
- ;; no arg -- swap pwd and car of shell stack
- (condition-case nil (if shell-dirstack
- (let ((old default-directory))
- (cd (car shell-dirstack))
- (setq shell-dirstack
- (cons old (cdr shell-dirstack)))
- (shell-dirstack-message))
- (message "Directory stack empty."))
- (message "Couldn't cd."))
-
- (let ((num (shell-extract-num arg)))
- (if num ; pushd +n
- (if (> num (length shell-dirstack))
- (message "Directory stack not that deep.")
- (let* ((ds (cons default-directory shell-dirstack))
- (dslen (length ds))
- (front (nthcdr num ds))
- (back (reverse (nthcdr (- dslen num) (reverse ds))))
- (new-ds (append front back)))
- (condition-case nil
- (progn (cd (car new-ds))
- (setq shell-dirstack (cdr new-ds))
- (shell-dirstack-message))
- (error (message "Couldn't cd.")))))
-
- ;; pushd <dir>
- (let ((old-wd default-directory))
- (condition-case nil
- (progn (cd arg)
- (setq shell-dirstack
- (cons old-wd shell-dirstack))
- (shell-dirstack-message))
- (error (message "Couldn't cd."))))))))
-
-;; If STR is of the form +n, for n>0, return n. Otherwise, nil.
-(defun shell-extract-num (str)
- (and (string-match "^\\+[1-9][0-9]*$" str)
- (string-to-int str)))
-
-
-(defun shell-dirtrack-toggle ()
- "Turn directory tracking on and off in a shell buffer."
+(defvar inferior-lisp-mode-map nil)
+(if inferior-lisp-mode-map
+ nil
+ (setq inferior-lisp-mode-map (copy-alist shell-mode-map))
+ (lisp-mode-commands inferior-lisp-mode-map)
+ (define-key inferior-lisp-mode-map "\e\C-x" 'lisp-send-defun))
+
+(defvar inferior-lisp-program "lisp"
+ "*Program name for invoking an inferior Lisp with `run-lisp'.")
+
+(defvar inferior-lisp-load-command "(load \"%s\")\n"
+ "*Format-string for building a Lisp expression to load a file.
+This format string should use %s to substitute a file name
+and should result in a Lisp expression that will command the inferior Lisp
+to load that file. The default works acceptably on most Lisps.
+The string \"(progn (load \\\"%s\\\" :verbose nil :print t) (values))\\\n\"
+produces cosmetically superior output for this application,
+but it works only in Common Lisp.")
+
+(defvar inferior-lisp-prompt "^.*>:? *$"
+ "*Regexp to recognize prompts from the inferior Lisp.
+Default is right for Franz Lisp and kcl.")
+
+(defun inferior-lisp-mode ()
+ "Major mode for interacting with an inferior Lisp process.
+Runs a Lisp interpreter as a subprocess of Emacs, with Lisp I/O
+through an Emacs buffer. Variable inferior-lisp-program controls
+which Lisp interpreter is run. Variables inferior-lisp-prompt
+and inferior-lisp-load-command can customize this mode for different
+Lisp interpreters.
+
+Commands:
+DELETE converts tabs to spaces as it moves back.
+TAB indents for Lisp; with argument, shifts rest
+ of expression rigidly with the current line.
+Meta-Control-Q does TAB on each line starting within following expression.
+Paragraphs are separated only by blank lines. Semicolons start comments.
+
+Return at end of buffer sends line as input.
+Return not at end copies rest of line to end and sends it.
+
+The following commands imitate the usual Unix interrupt and
+editing control characters:
+\\{shell-mode-map}
+
+Entry to this mode calls the value of lisp-mode-hook with no arguments,
+if that value is non-nil. Likewise with the value of shell-mode-hook.
+lisp-mode-hook is called after shell-mode-hook.
+
+You can send text to the inferior Lisp from other buffers
+using the commands process-send-region, process-send-string
+and \\[lisp-send-defun]."
+ (interactive)
+ (kill-all-local-variables)
+ (setq major-mode 'inferior-lisp-mode)
+ (setq mode-name "Inferior Lisp")
+ (setq mode-line-process '(": %s"))
+ (lisp-mode-variables t)
+ (use-local-map inferior-lisp-mode-map)
+ (make-local-variable 'last-input-start)
+ (setq last-input-start (make-marker))
+ (make-local-variable 'last-input-end)
+ (setq last-input-end (make-marker))
+ (run-hooks 'shell-mode-hook 'lisp-mode-hook))
+
+(defun run-lisp ()
+ "Run an inferior Lisp process, input and output via buffer *lisp*."
(interactive)
- (setq shell-dirtrackp (not shell-dirtrackp))
- (message "directory tracking %s."
- (if shell-dirtrackp "ON" "OFF")))
-
-;;; For your typing convenience:
-(fset 'dirtrack-toggle 'shell-dirtrack-toggle)
-
-
-(defun shell-resync-dirs ()
- "Resync the buffer's idea of the current directory stack.
-This command queries the shell with the command bound to
-shell-dirstack-query (default \"dirs\"), reads the next
-line output and parses it to form the new directory stack.
-DON'T issue this command unless the buffer is at a shell prompt.
-Also, note that if some other subprocess decides to do output
-immediately after the query, its output will be taken as the
-new directory stack -- you lose. If this happens, just do the
-command again."
+ (switch-to-buffer (make-shell "lisp" inferior-lisp-program))
+ (inferior-lisp-mode))
+
+(defun lisp-send-defun (display-flag)
+ "Send the current defun to the Lisp process made by M-x run-lisp.
+With argument, force redisplay and scrolling of the *lisp* buffer.
+Variable `inferior-lisp-load-command' controls formatting of
+the `load' form that is set to the Lisp process."
+ (interactive "P")
+ (or (get-process "lisp")
+ (error "No current lisp process"))
+ (save-excursion
+ (end-of-defun)
+ (let ((end (point))
+ (filename (format "/tmp/emlisp%d" (process-id (get-process "lisp")))))
+ (beginning-of-defun)
+ (write-region (point) end filename nil 'nomessage)
+ (process-send-string "lisp" (format inferior-lisp-load-command filename)))
+ (if display-flag
+ (let* ((process (get-process "lisp"))
+ (buffer (process-buffer process))
+ (w (or (get-buffer-window buffer) (display-buffer buffer)))
+ (height (window-height w))
+ (end))
+ (save-excursion
+ (set-buffer buffer)
+ (setq end (point-max))
+ (while (progn
+ (accept-process-output process)
+ (goto-char (point-max))
+ (beginning-of-line)
+ (or (= (point-max) end)
+ (not (looking-at inferior-lisp-prompt)))))
+ (setq end (point-max))
+ (vertical-motion (- 4 height))
+ (set-window-start w (point)))
+ (set-window-point w end)))))
+
+(defun lisp-send-defun-and-go ()
+ "Send the current defun to the inferior Lisp, and switch to *lisp* buffer."
(interactive)
- (let* ((proc (get-buffer-process (current-buffer)))
- (pmark (process-mark proc)))
- (goto-char pmark)
- (insert shell-dirstack-query) (insert "\n")
- (sit-for 0) ; force redisplay
- (comint-send-string proc shell-dirstack-query)
- (comint-send-string proc "\n")
- (set-marker pmark (point))
- (let ((pt (point))) ; wait for 1 line
- ;; This extra newline prevents the user's pending input from spoofing us.
- (insert "\n") (backward-char 1)
- (while (not (looking-at ".+\n"))
- (accept-process-output proc)
- (goto-char pt)))
- (goto-char pmark) (delete-char 1) ; remove the extra newline
- ;; That's the dirlist. grab it & parse it.
- (let* ((dl (buffer-substring (match-beginning 0) (- (match-end 0) 1)))
- (dl-len (length dl))
- (ds '()) ; new dir stack
- (i 0))
- (while (< i dl-len)
- ;; regexp = optional whitespace, (non-whitespace), optional whitespace
- (string-match "\\s *\\(\\S +\\)\\s *" dl i) ; pick off next dir
- (setq ds (cons (substring dl (match-beginning 1) (match-end 1))
- ds))
- (setq i (match-end 0)))
- (let ((ds (reverse ds)))
- (condition-case nil
- (progn (cd (car ds))
- (setq shell-dirstack (cdr ds))
- (shell-dirstack-message))
- (error (message "Couldn't cd.")))))))
-
-;;; For your typing convenience:
-(fset 'dirs 'shell-resync-dirs)
-
-
-;;; Show the current dirstack on the message line.
-;;; Pretty up dirs a bit by changing "/usr/jqr/foo" to "~/foo".
-;;; (This isn't necessary if the dirlisting is generated with a simple "dirs".)
-;;; All the commands that mung the buffer's dirstack finish by calling
-;;; this guy.
-(defun shell-dirstack-message ()
- (let ((msg "")
- (ds (cons default-directory shell-dirstack)))
- (while ds
- (let ((dir (car ds)))
- (if (string-match (format "^%s\\(/\\|$\\)" (getenv "HOME")) dir)
- (setq dir (concat "~/" (substring dir (match-end 0)))))
- (if (string-equal dir "~/") (setq dir "~"))
- (setq msg (concat msg dir " "))
- (setq ds (cdr ds))))
- (message msg)))
+ (lisp-send-defun nil)
+ (switch-to-buffer "*lisp*"))
diff --git a/lisp/shell.elc b/lisp/shell.elc
new file mode 100644
index 00000000000..103b284f564
--- /dev/null
+++ b/lisp/shell.elc
Binary files differ
diff --git a/lisp/simple.el b/lisp/simple.el
new file mode 100644
index 00000000000..c1d5db50fc4
--- /dev/null
+++ b/lisp/simple.el
@@ -0,0 +1,1431 @@
+;; Basic editing commands for Emacs
+;; Copyright (C) 1985, 1986, 1987, 1992 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 1, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+(defun open-line (arg)
+ "Insert a newline and leave point before it.
+With arg, inserts that many newlines."
+ (interactive "*p")
+ (let ((flag (and (bolp) (not (bobp)))))
+ (if flag (forward-char -1))
+ (while (> arg 0)
+ (insert ?\n)
+ (goto-char (1- (point)))
+ (setq arg (1- arg)))
+ (if flag (forward-char 1))))
+
+(defun split-line ()
+ "Split current line, moving portion beyond point vertically down."
+ (interactive "*")
+ (skip-chars-forward " \t")
+ (let ((col (current-column))
+ (pos (point)))
+ (insert ?\n)
+ (indent-to col 0)
+ (goto-char pos)))
+
+(defun quoted-insert (arg)
+ "Read next input character and insert it.
+Useful for inserting control characters.
+You may also type up to 3 octal digits, to insert a character with that code"
+ (interactive "*p")
+ (let ((char (read-quoted-char)))
+ (while (> arg 0)
+ (insert char)
+ (setq arg (1- arg)))))
+
+(defun delete-indentation (&optional arg)
+ "Join this line to previous and fix up whitespace at join.
+With argument, join this line to following line."
+ (interactive "*P")
+ (beginning-of-line)
+ (if arg (forward-line 1))
+ (if (eq (preceding-char) ?\n)
+ (progn
+ (delete-region (point) (1- (point)))
+ (fixup-whitespace))))
+
+(defun fixup-whitespace ()
+ "Fixup white space between objects around point.
+Leave one space or none, according to the context."
+ (interactive "*")
+ (save-excursion
+ (delete-horizontal-space)
+ (if (or (looking-at "^\\|\\s)\\|$")
+ (save-excursion (forward-char -1)
+ (looking-at "\\s(\\|\\s'")))
+ nil
+ (insert ?\ ))))
+
+(defun delete-horizontal-space ()
+ "Delete all spaces and tabs around point."
+ (interactive "*")
+ (skip-chars-backward " \t")
+ (delete-region (point) (progn (skip-chars-forward " \t") (point))))
+
+(defun just-one-space ()
+ "Delete all spaces and tabs around point, leaving one space."
+ (interactive "*")
+ (skip-chars-backward " \t")
+ (if (= (following-char) ? )
+ (forward-char 1)
+ (insert ? ))
+ (delete-region (point) (progn (skip-chars-forward " \t") (point))))
+
+(defun delete-blank-lines ()
+ "On blank line, delete all surrounding blank lines, leaving just one.
+On isolated blank line, delete that one.
+On nonblank line, delete all blank lines that follow it."
+ (interactive "*")
+ (let (thisblank singleblank)
+ (save-excursion
+ (beginning-of-line)
+ (setq thisblank (looking-at "[ \t]*$"))
+ (setq singleblank
+ (and thisblank
+ (not (looking-at "[ \t]*\n[ \t]*$"))
+ (or (bobp)
+ (progn (forward-line -1)
+ (not (looking-at "[ \t]*$")))))))
+ (if thisblank
+ (progn
+ (beginning-of-line)
+ (if singleblank (forward-line 1))
+ (delete-region (point)
+ (if (re-search-backward "[^ \t\n]" nil t)
+ (progn (forward-line 1) (point))
+ (point-min)))))
+ (if (not (and thisblank singleblank))
+ (save-excursion
+ (end-of-line)
+ (forward-line 1)
+ (delete-region (point)
+ (if (re-search-forward "[^ \t\n]" nil t)
+ (progn (beginning-of-line) (point))
+ (point-max)))))))
+
+(defun back-to-indentation ()
+ "Move point to the first non-whitespace character on this line."
+ (interactive)
+ (beginning-of-line 1)
+ (skip-chars-forward " \t"))
+
+(defun newline-and-indent ()
+ "Insert a newline, then indent according to major mode.
+Indentation is done using the current indent-line-function.
+In programming language modes, this is the same as TAB.
+In some text modes, where TAB inserts a tab, this indents to the
+specified left-margin column."
+ (interactive "*")
+ (delete-region (point) (progn (skip-chars-backward " \t") (point)))
+ (newline)
+ (indent-according-to-mode))
+
+(defun reindent-then-newline-and-indent ()
+ "Reindent current line, insert newline, then indent the new line.
+Indentation of both lines is done according to the current major mode,
+which means that the current value of indent-line-function is called.
+In programming language modes, this is the same as TAB.
+In some text modes, where TAB inserts a tab, this indents to the
+specified left-margin column."
+ (interactive "*")
+ (save-excursion
+ (delete-region (point) (progn (skip-chars-backward " \t") (point)))
+ (indent-according-to-mode))
+ (newline)
+ (indent-according-to-mode))
+
+(defun kill-forward-chars (arg)
+ (if (listp arg) (setq arg (car arg)))
+ (if (eq arg '-) (setq arg -1))
+ (kill-region (point) (+ (point) arg)))
+
+(defun kill-backward-chars (arg)
+ (if (listp arg) (setq arg (car arg)))
+ (if (eq arg '-) (setq arg -1))
+ (kill-region (point) (- (point) arg)))
+
+(defun backward-delete-char-untabify (arg &optional killp)
+ "Delete characters backward, changing tabs into spaces.
+Delete ARG chars, and kill (save in kill ring) if KILLP is non-nil.
+Interactively, ARG is the prefix arg (default 1)
+and KILLP is t if prefix arg is was specified."
+ (interactive "*p\nP")
+ (let ((count arg))
+ (save-excursion
+ (while (and (> count 0) (not (bobp)))
+ (if (= (preceding-char) ?\t)
+ (let ((col (current-column)))
+ (forward-char -1)
+ (setq col (- col (current-column)))
+ (insert-char ?\ col)
+ (delete-char 1)))
+ (forward-char -1)
+ (setq count (1- count)))))
+ (delete-backward-char arg killp))
+
+(defun zap-to-char (arg char)
+ "Kill up to (but not including) ARG'th occurrence of CHAR.
+Goes backward if ARG is negative; goes to end of buffer if CHAR not found."
+ (interactive "*p\ncZap to char: ")
+ (kill-region (point) (if (search-forward (char-to-string char) nil t arg)
+ (progn (goto-char (if (> arg 0) (1- (point)) (1+ (point))))
+ (point))
+ (if (> arg 0) (point-max) (point-min)))))
+
+(defun beginning-of-buffer (&optional arg)
+ "Move point to the beginning of the buffer; leave mark at previous position.
+With arg N, put point N/10 of the way from the true beginning.
+Don't use this in Lisp programs!
+\(goto-char (point-min)) is faster and does not set the mark."
+ (interactive "P")
+ (push-mark)
+ (goto-char (if arg
+ (if (> (buffer-size) 10000)
+ ;; Avoid overflow for large buffer sizes!
+ (* (prefix-numeric-value arg)
+ (/ (buffer-size) 10))
+ (/ (+ 10 (* (buffer-size) (prefix-numeric-value arg))) 10))
+ (point-min)))
+ (if arg (forward-line 1)))
+
+(defun end-of-buffer (&optional arg)
+ "Move point to the end of the buffer; leave mark at previous position.
+With arg N, put point N/10 of the way from the true end.
+Don't use this in Lisp programs!
+\(goto-char (point-max)) is faster and does not set the mark."
+ (interactive "P")
+ (push-mark)
+ (goto-char (if arg
+ (- (1+ (buffer-size))
+ (if (> (buffer-size) 10000)
+ ;; Avoid overflow for large buffer sizes!
+ (* (prefix-numeric-value arg)
+ (/ (buffer-size) 10))
+ (/ (* (buffer-size) (prefix-numeric-value arg)) 10)))
+ (point-max)))
+ (if arg (forward-line 1)))
+
+(defun mark-whole-buffer ()
+ "Put point at beginning and mark at end of buffer."
+ (interactive)
+ (push-mark (point))
+ (push-mark (point-max))
+ (goto-char (point-min)))
+
+(defun count-lines-region (start end)
+ "Print number of lines in the region."
+ (interactive "r")
+ (message "Region has %d lines" (count-lines start end)))
+
+(defun what-line ()
+ "Print the current line number (in the buffer) of point."
+ (interactive)
+ (save-restriction
+ (widen)
+ (save-excursion
+ (beginning-of-line)
+ (message "Line %d"
+ (1+ (count-lines 1 (point)))))))
+
+(defun count-lines (start end)
+ "Return number of newlines between START and END."
+ (save-excursion
+ (save-restriction
+ (narrow-to-region start end)
+ (goto-char (point-min))
+ (- (buffer-size) (forward-line (buffer-size))))))
+
+(defun what-cursor-position ()
+ "Print info on cursor position (on screen and within buffer)."
+ (interactive)
+ (let* ((char (following-char))
+ (beg (point-min))
+ (end (point-max))
+ (pos (point))
+ (total (buffer-size))
+ (percent (if (> total 50000)
+ ;; Avoid overflow from multiplying by 100!
+ (/ (+ (/ total 200) (1- pos)) (max (/ total 100) 1))
+ (/ (+ (/ total 2) (* 100 (1- pos))) (max total 1))))
+ (hscroll (if (= (window-hscroll) 0)
+ ""
+ (format " Hscroll=%d" (window-hscroll))))
+ (col (current-column)))
+ (if (= pos end)
+ (if (or (/= beg 1) (/= end (1+ total)))
+ (message "point=%d of %d(%d%%) <%d - %d> column %d %s"
+ pos total percent beg end col hscroll)
+ (message "point=%d of %d(%d%%) column %d %s"
+ pos total percent col hscroll))
+ (if (or (/= beg 1) (/= end (1+ total)))
+ (message "Char: %s (0%o) point=%d of %d(%d%%) <%d - %d> column %d %s"
+ (single-key-description char) char pos total percent beg end col hscroll)
+ (message "Char: %s (0%o) point=%d of %d(%d%%) column %d %s"
+ (single-key-description char) char pos total percent col hscroll)))))
+
+(defun fundamental-mode ()
+ "Major mode not specialized for anything in particular.
+Other major modes are defined by comparison with this one."
+ (interactive)
+ (kill-all-local-variables))
+
+(put 'eval-expression 'disabled t)
+
+;; We define this, rather than making eval interactive,
+;; for the sake of completion of names like eval-region, eval-current-buffer.
+(defun eval-expression (expression)
+ "Evaluate EXPRESSION and print value in minibuffer.
+Value is also consed on to front of variable values 's value."
+ (interactive "xEval: ")
+ (setq values (cons (eval expression) values))
+ (prin1 (car values) t))
+
+(defun edit-and-eval-command (prompt command)
+ "Prompting with PROMPT, let user edit COMMAND and eval result.
+COMMAND is a Lisp expression. Let user edit that expression in
+the minibuffer, then read and evaluate the result."
+ (eval (read-minibuffer prompt
+ (prin1-to-string command))))
+
+(defvar repeat-complex-command-map (copy-alist minibuffer-local-map))
+(define-key repeat-complex-command-map "\ep" 'previous-complex-command)
+(define-key repeat-complex-command-map "\en" 'next-complex-command)
+(defun repeat-complex-command (repeat-complex-command-arg)
+ "Edit and re-evaluate last complex command, or ARGth from last.
+A complex command is one which used the minibuffer.
+The command is placed in the minibuffer as a Lisp form for editing.
+The result is executed, repeating the command as changed.
+If the command has been changed or is not the most recent previous command
+it is added to the front of the command history.
+Whilst editing the command, the following commands are available:
+\\{repeat-complex-command-map}"
+ (interactive "p")
+ (let ((elt (nth (1- repeat-complex-command-arg) command-history))
+ newcmd)
+ (if elt
+ (progn
+ (setq newcmd (read-from-minibuffer "Redo: "
+ (prin1-to-string elt)
+ repeat-complex-command-map
+ t))
+ ;; If command to be redone does not match front of history,
+ ;; add it to the history.
+ (or (equal newcmd (car command-history))
+ (setq command-history (cons newcmd command-history)))
+ (eval newcmd))
+ (ding))))
+
+(defun next-complex-command (n)
+ "Inserts the next element of `command-history' into the minibuffer."
+ (interactive "p")
+ (let ((narg (min (max 1 (- repeat-complex-command-arg n))
+ (length command-history))))
+ (if (= repeat-complex-command-arg narg)
+ (error (if (= repeat-complex-command-arg 1)
+ "No following item in command history"
+ "No preceeding item command history"))
+ (erase-buffer)
+ (setq repeat-complex-command-arg narg)
+ (insert (prin1-to-string (nth (1- repeat-complex-command-arg)
+ command-history)))
+ (goto-char (point-min)))))
+
+(defun previous-complex-command (n)
+ "Inserts the previous element of `command-history' into the minibuffer."
+ (interactive "p")
+ (next-complex-command (- n)))
+
+(defun goto-line (arg)
+ "Goto line ARG, counting from line 1 at beginning of buffer."
+ (interactive "NGoto line: ")
+ (save-restriction
+ (widen)
+ (goto-char 1)
+ (if (eq selective-display t)
+ (re-search-forward "[\n\C-m]" nil 'end (1- arg))
+ (forward-line (1- arg)))))
+
+;Put this on C-x u, so we can force that rather than C-_ into startup msg
+(fset 'advertised-undo 'undo)
+
+(defun undo (&optional arg)
+ "Undo some previous changes.
+Repeat this command to undo more changes.
+A numeric argument serves as a repeat count."
+ (interactive "*p")
+ (let ((modified (buffer-modified-p)))
+ (or (eq (selected-window) (minibuffer-window))
+ (message "Undo!"))
+ (or (eq last-command 'undo)
+ (progn (undo-start)
+ (undo-more 1)))
+ (setq this-command 'undo)
+ (undo-more (or arg 1))
+ (and modified (not (buffer-modified-p))
+ (delete-auto-save-file-if-necessary))))
+
+(defun shell-command (command &optional flag)
+ "Execute string COMMAND in inferior shell; display output, if any.
+Optional second arg non-nil (prefix arg, if interactive)
+means insert output in current buffer after point (leave mark after it)."
+ (interactive "sShell command: \nP")
+ (if flag
+ (progn (barf-if-buffer-read-only)
+ (push-mark)
+ (call-process shell-file-name nil t nil
+ "-c" command)
+ (exchange-point-and-mark))
+ (shell-command-on-region (point) (point) command nil)))
+
+(defun shell-command-on-region (start end command &optional flag interactive)
+ "Execute string COMMAND in inferior shell with region as input.
+Normally display output (if any) in temp buffer;
+Prefix arg means replace the region with it.
+Noninteractive args are START, END, COMMAND, FLAG.
+Noninteractively FLAG means insert output in place of text from START to END,
+and put point at the end, but don't alter the mark."
+ (interactive "r\nsShell command on region: \nP\np")
+ (if flag
+ ;; Replace specified region with output from command.
+ (let ((swap (and interactive (< (point) (mark)))))
+ ;; Don't muck with mark
+ ;; unless called interactively.
+ (and interactive (push-mark))
+ (call-process-region start end shell-file-name t t nil
+ "-c" command)
+ (and interactive swap (exchange-point-and-mark)))
+ (let ((buffer (get-buffer-create "*Shell Command Output*")))
+ (if (eq buffer (current-buffer))
+ ;; If the input is the same buffer as the output,
+ ;; delete everything but the specified region,
+ ;; then replace that region with the output.
+ (progn (delete-region end (point-max))
+ (delete-region (point-min) start)
+ (call-process-region (point-min) (point-max)
+ shell-file-name t t nil
+ "-c" command))
+ ;; Clear the output buffer, then run the command with output there.
+ (save-excursion
+ (set-buffer buffer)
+ (erase-buffer))
+ (call-process-region start end shell-file-name
+ nil buffer nil
+ "-c" command))
+ (if (save-excursion
+ (set-buffer buffer)
+ (> (buffer-size) 0))
+ (set-window-start (display-buffer buffer) 1)
+ (message "(Shell command completed with no output)")))))
+
+(defun universal-argument ()
+ "Begin a numeric argument for the following command.
+Digits or minus sign following \\[universal-argument] make up the numeric argument.
+\\[universal-argument] following the digits or minus sign ends the argument.
+\\[universal-argument] without digits or minus sign provides 4 as argument.
+Repeating \\[universal-argument] without digits or minus sign
+ multiplies the argument by 4 each time."
+ (interactive nil)
+ (let ((c-u 4) (argstartchar last-command-char)
+ char)
+; (describe-arg (list c-u) 1)
+ (setq char (read-char))
+ (while (= char argstartchar)
+ (setq c-u (* 4 c-u))
+; (describe-arg (list c-u) 1)
+ (setq char (read-char)))
+ (prefix-arg-internal char c-u nil)))
+
+(defun prefix-arg-internal (char c-u value)
+ (let ((sign 1))
+ (if (and (numberp value) (< value 0))
+ (setq sign -1 value (- value)))
+ (if (eq value '-)
+ (setq sign -1 value nil))
+; (describe-arg value sign)
+ (while (= ?- char)
+ (setq sign (- sign) c-u nil)
+; (describe-arg value sign)
+ (setq char (read-char)))
+ (while (and (>= char ?0) (<= char ?9))
+ (setq value (+ (* (if (numberp value) value 0) 10) (- char ?0)) c-u nil)
+; (describe-arg value sign)
+ (setq char (read-char)))
+ ;; Repeating the arg-start char after digits
+ ;; terminates the argument but is ignored.
+ (if (eq (lookup-key global-map (make-string 1 char)) 'universal-argument)
+ (setq char (read-char)))
+ (setq prefix-arg
+ (cond (c-u (list c-u))
+ ((numberp value) (* value sign))
+ ((= sign -1) '-)))
+ (setq unread-command-char char)))
+
+;(defun describe-arg (value sign)
+; (cond ((numberp value)
+; (message "Arg: %d" (* value sign)))
+; ((consp value)
+; (message "Arg: C-u factor %d" (car value)))
+; ((< sign 0)
+; (message "Arg: -"))))
+
+(defun digit-argument (arg)
+ "Part of the numeric argument for the next command.
+\\[universal-argument] following digits or minus sign ends the argument."
+ (interactive "P")
+ (prefix-arg-internal last-command-char nil arg))
+
+(defun negative-argument (arg)
+ "Begin a negative numeric argument for the next command.
+\\[universal-argument] following digits or minus sign ends the argument."
+ (interactive "P")
+ (prefix-arg-internal ?- nil arg))
+
+(defun forward-to-indentation (arg)
+ "Move forward ARG lines and position at first nonblank character."
+ (interactive "p")
+ (forward-line arg)
+ (skip-chars-forward " \t"))
+
+(defun backward-to-indentation (arg)
+ "Move backward ARG lines and position at first nonblank character."
+ (interactive "p")
+ (forward-line (- arg))
+ (skip-chars-forward " \t"))
+
+(defun kill-line (&optional arg)
+ "Kill the rest of the current line; if no nonblanks there, kill thru newline.
+With prefix argument, kill that many lines from point.
+Negative arguments kill lines backward.
+
+When calling from a program, nil means \"no arg\",
+a number counts as a prefix arg."
+ (interactive "*P")
+ (kill-region (point)
+ (progn
+ (if arg
+ (forward-line (prefix-numeric-value arg))
+ (if (eobp)
+ (signal 'end-of-buffer nil))
+ (if (looking-at "[ \t]*$")
+ (forward-line 1)
+ (end-of-line)))
+ (point))))
+
+;;;; The kill ring
+
+(defvar kill-ring nil
+ "List of killed text sequences.")
+
+(defconst kill-ring-max 30
+ "*Maximum length of kill ring before oldest elements are thrown away.")
+
+(defvar kill-ring-yank-pointer nil
+ "The tail of the kill ring whose car is the last thing yanked.")
+
+(defun kill-append (string before-p)
+ (setcar kill-ring
+ (if before-p
+ (concat string (car kill-ring))
+ (concat (car kill-ring) string))))
+
+(defun kill-region (beg end)
+ "Kill between point and mark.
+The text is deleted but saved in the kill ring.
+The command \\[yank] can retrieve it from there.
+\(If you want to kill and then yank immediately, use \\[copy-region-as-kill].)
+
+This is the primitive for programs to kill text (as opposed to deleting it).
+Supply two arguments, character numbers indicating the stretch of text
+ to be killed.
+Any command that calls this function is a \"kill command\".
+If the previous command was also a kill command,
+the text killed this time appends to the text killed last time
+to make one entry in the kill ring."
+ (interactive "*r")
+ (if (and (not (eq buffer-undo-list t))
+ (not (eq last-command 'kill-region))
+ (not (eq beg end))
+ ;; This test is here in case someone wants to remove the `*'
+ ;; above, so that the text gets stored in the kill ring
+ ;; even though it doesn't get deleted.
+ (not buffer-read-only))
+ ;; Don't let the undo list be truncated before we can even access it.
+ (let ((undo-high-threshold (+ (- (max beg end) (min beg end)) 100)))
+ (delete-region beg end)
+ ;; Take the same string recorded for undo
+ ;; and put it in the kill-ring.
+ (setq kill-ring (cons (car (car buffer-undo-list)) kill-ring))
+ (if (> (length kill-ring) kill-ring-max)
+ (setcdr (nthcdr (1- kill-ring-max) kill-ring) nil))
+ (setq this-command 'kill-region)
+ (setq kill-ring-yank-pointer kill-ring))
+ (copy-region-as-kill beg end)
+ (delete-region beg end)))
+
+(fset 'kill-ring-save 'copy-region-as-kill)
+
+(defun copy-region-as-kill (beg end)
+ "Save the region as if killed, but don't kill it."
+ (interactive "r")
+ (if (eq last-command 'kill-region)
+ (kill-append (buffer-substring beg end) (< end beg))
+ (setq kill-ring (cons (buffer-substring beg end) kill-ring))
+ (if (> (length kill-ring) kill-ring-max)
+ (setcdr (nthcdr (1- kill-ring-max) kill-ring) nil)))
+ (setq this-command 'kill-region)
+ (setq kill-ring-yank-pointer kill-ring))
+
+(defun append-next-kill ()
+ "Cause following command, if kill, to append to previous kill."
+ (interactive)
+ (if (interactive-p)
+ (setq this-command 'kill-region)
+ (setq last-command 'kill-region)))
+
+(defun rotate-yank-pointer (arg)
+ "Rotate the yanking point in the kill ring."
+ (interactive "p")
+ (let ((length (length kill-ring)))
+ (if (zerop length)
+ (error "Kill ring is empty")
+ (setq kill-ring-yank-pointer
+ (nthcdr (% (+ arg (- length (length kill-ring-yank-pointer)))
+ length)
+ kill-ring)))))
+
+(defun yank-pop (arg)
+ "Replace just-yanked stretch of killed-text with a different stretch.
+This command is allowed only immediately after a yank or a yank-pop.
+At such a time, the region contains a stretch of reinserted
+previously-killed text. yank-pop deletes that text and inserts in its
+place a different stretch of killed text.
+
+With no argument, the previous kill is inserted.
+With argument n, the n'th previous kill is inserted.
+If n is negative, this is a more recent kill.
+
+The sequence of kills wraps around, so that after the oldest one
+comes the newest one."
+ (interactive "*p")
+ (if (not (eq last-command 'yank))
+ (error "Previous command was not a yank"))
+ (setq this-command 'yank)
+ (let ((before (< (point) (mark))))
+ (delete-region (point) (mark))
+ (rotate-yank-pointer arg)
+ (set-mark (point))
+ (insert (car kill-ring-yank-pointer))
+ (if before (exchange-point-and-mark))))
+
+(defun yank (&optional arg)
+ "Reinsert the last stretch of killed text.
+More precisely, reinsert the stretch of killed text most recently
+killed OR yanked.
+With just C-U as argument, same but put point in front (and mark at end).
+With argument n, reinsert the nth most recently killed stretch of killed
+text.
+See also the command \\[yank-pop]."
+ (interactive "*P")
+ (rotate-yank-pointer (if (listp arg) 0
+ (if (eq arg '-) -1
+ (1- arg))))
+ (push-mark (point))
+ (insert (car kill-ring-yank-pointer))
+ (if (consp arg)
+ (exchange-point-and-mark)))
+
+(defun insert-buffer (buffer)
+ "Insert after point the contents of BUFFER.
+Puts mark after the inserted text.
+BUFFER may be a buffer or a buffer name."
+ (interactive "*bInsert buffer: ")
+ (or (bufferp buffer)
+ (setq buffer (get-buffer buffer)))
+ (let (start end newmark)
+ (save-excursion
+ (save-excursion
+ (set-buffer buffer)
+ (setq start (point-min) end (point-max)))
+ (insert-buffer-substring buffer start end)
+ (setq newmark (point)))
+ (push-mark newmark)))
+
+(defun append-to-buffer (buffer start end)
+ "Append to specified buffer the text of the region.
+It is inserted into that buffer before its point.
+
+When calling from a program, give three arguments:
+a buffer or the name of one, and two character numbers
+specifying the portion of the current buffer to be copied."
+ (interactive "BAppend to buffer: \nr")
+ (let ((oldbuf (current-buffer)))
+ (save-excursion
+ (set-buffer (get-buffer-create buffer))
+ (insert-buffer-substring oldbuf start end))))
+
+(defun prepend-to-buffer (buffer start end)
+ "Prepend to specified buffer the text of the region.
+It is inserted into that buffer after its point.
+
+When calling from a program, give three arguments:
+a buffer or the name of one, and two character numbers
+specifying the portion of the current buffer to be copied."
+ (interactive "BPrepend to buffer: \nr")
+ (let ((oldbuf (current-buffer)))
+ (save-excursion
+ (set-buffer (get-buffer-create buffer))
+ (save-excursion
+ (insert-buffer-substring oldbuf start end)))))
+
+(defun copy-to-buffer (buffer start end)
+ "Copy to specified buffer the text of the region.
+It is inserted into that buffer, replacing existing text there.
+
+When calling from a program, give three arguments:
+a buffer or the name of one, and two character numbers
+specifying the portion of the current buffer to be copied."
+ (interactive "BCopy to buffer: \nr")
+ (let ((oldbuf (current-buffer)))
+ (save-excursion
+ (set-buffer (get-buffer-create buffer))
+ (erase-buffer)
+ (save-excursion
+ (insert-buffer-substring oldbuf start end)))))
+
+(defun mark ()
+ "Return this buffer's mark value as integer, or nil if no mark.
+If you are using this in an editing command, you are most likely making
+a mistake; see the documentation of `set-mark'."
+ (marker-position (mark-marker)))
+
+(defun set-mark (pos)
+ "Set this buffer's mark to POS. Don't use this function!
+That is to say, don't use this function unless you want
+the user to see that the mark has moved, and you want the previous
+mark position to be lost.
+
+Normally, when a new mark is set, the old one should go on the stack.
+This is why most applications should use push-mark, not set-mark.
+
+Novice emacs-lisp programmers often try to use the mark for the wrong
+purposes. The mark saves a location for the user's convenience.
+Most editing commands should not alter the mark.
+To remember a location for internal use in the Lisp program,
+store it in a Lisp variable. Example:
+
+ (let ((beg (point))) (forward-line 1) (delete-region beg (point)))."
+
+ (set-marker (mark-marker) pos (current-buffer)))
+
+(defvar mark-ring nil
+ "The list of saved former marks of the current buffer,
+most recent first.")
+(make-variable-buffer-local 'mark-ring)
+
+(defconst mark-ring-max 16
+ "*Maximum size of mark ring. Start discarding off end if gets this big.")
+
+(defun set-mark-command (arg)
+ "Set mark at where point is, or jump to mark.
+With no prefix argument, set mark, and push previous mark on mark ring.
+With argument, jump to mark, and pop into mark off the mark ring.
+
+Novice emacs-lisp programmers often try to use the mark for the wrong
+purposes. See the documentation of `set-mark' for more information."
+ (interactive "P")
+ (if (null arg)
+ (push-mark)
+ (if (null (mark))
+ (error "No mark set in this buffer")
+ (goto-char (mark))
+ (pop-mark))))
+
+(defun push-mark (&optional location nomsg)
+ "Set mark at LOCATION (point, by default) and push old mark on mark ring.
+Displays \"Mark set\" unless the optional second arg NOMSG is non-nil.
+
+Novice emacs-lisp programmers often try to use the mark for the wrong
+purposes. See the documentation of `set-mark' for more information."
+ (if (null (mark))
+ nil
+ (setq mark-ring (cons (copy-marker (mark-marker)) mark-ring))
+ (if (> (length mark-ring) mark-ring-max)
+ (progn
+ (move-marker (car (nthcdr mark-ring-max mark-ring)) nil)
+ (setcdr (nthcdr (1- mark-ring-max) mark-ring) nil))))
+ (set-mark (or location (point)))
+ (or nomsg executing-macro (> (minibuffer-depth) 0)
+ (message "Mark set")))
+
+(defun pop-mark ()
+ "Pop off mark ring into the buffer's actual mark.
+Does not set point. Does nothing if mark ring is empty."
+ (if mark-ring
+ (progn
+ (setq mark-ring (nconc mark-ring (list (copy-marker (mark-marker)))))
+ (set-mark (+ 0 (car mark-ring)))
+ (move-marker (car mark-ring) nil)
+ (if (null (mark)) (ding))
+ (setq mark-ring (cdr mark-ring)))))
+
+(fset 'exchange-dot-and-mark 'exchange-point-and-mark)
+(defun exchange-point-and-mark ()
+ "Put the mark where point is now, and point where the mark is now."
+ (interactive nil)
+ (let ((omark (mark)))
+ (if (null omark)
+ (error "No mark set in this buffer"))
+ (set-mark (point))
+ (goto-char omark)
+ nil))
+
+(defun next-line (arg)
+ "Move cursor vertically down ARG lines.
+If there is no character in the target line exactly under the current column,
+the cursor is positioned after the character in that line which spans this
+column, or at the end of the line if it is not long enough.
+If there is no line in the buffer after this one,
+a newline character is inserted to create a line
+and the cursor moves to that line.
+
+The command \\[set-goal-column] can be used to create
+a semipermanent goal column to which this command always moves.
+Then it does not try to move vertically.
+
+If you are thinking of using this in a Lisp program, consider
+using `forward-line' instead. It is usually easier to use
+and more reliable (no dependence on goal column, etc.)."
+ (interactive "p")
+ (if (= arg 1)
+ (let ((opoint (point)))
+ (forward-line 1)
+ (if (or (= opoint (point))
+ (not (eq (preceding-char) ?\n)))
+ (insert ?\n)
+ (goto-char opoint)
+ (next-line-internal arg)))
+ (next-line-internal arg))
+ nil)
+
+(defun previous-line (arg)
+ "Move cursor vertically up ARG lines.
+If there is no character in the target line exactly over the current column,
+the cursor is positioned after the character in that line which spans this
+column, or at the end of the line if it is not long enough.
+
+The command \\[set-goal-column] can be used to create
+a semipermanent goal column to which this command always moves.
+Then it does not try to move vertically.
+
+If you are thinking of using this in a Lisp program, consider using
+`forward-line' with negative argument instead.. It is usually easier
+to use and more reliable (no dependence on goal column, etc.)."
+ (interactive "p")
+ (next-line-internal (- arg))
+ nil)
+
+(defconst track-eol nil
+ "*Non-nil means vertical motion starting at the end of a line should keep to ends of lines.
+This means moving to the end of each line moved onto.")
+
+(defvar goal-column nil
+ "*Semipermanent goal column for vertical motion, as set by \\[set-goal-column], or nil.")
+
+(defvar temporary-goal-column 0
+ "Current goal column for vertical motion.
+It is the column where point was at the start of current run of vertical motion commands.")
+
+(defun next-line-internal (arg)
+ (if (not (or (eq last-command 'next-line)
+ (eq last-command 'previous-line)))
+ (setq temporary-goal-column
+ (if (and track-eol (eolp))
+ t
+ (current-column))))
+ (if (not (integerp selective-display))
+ (forward-line arg)
+ ;; Move by arg lines, but ignore invisible ones.
+ (while (> arg 0)
+ (vertical-motion 1)
+ (forward-char -1)
+ (forward-line 1)
+ (setq arg (1- arg)))
+ (while (< arg 0)
+ (vertical-motion -1)
+ (beginning-of-line)
+ (setq arg (1+ arg))))
+ (if (eq (or goal-column temporary-goal-column) t)
+ (end-of-line)
+ (move-to-column (or goal-column temporary-goal-column)))
+ nil)
+
+
+(defun set-goal-column (arg)
+ "Set the current horizontal position as a goal for \\[next-line] and \\[previous-line].
+Those commands will move to this position in the line moved to
+rather than trying to keep the same horizontal position.
+With a non-nil argument, clears out the goal column
+so that \\[next-line] and \\[previous-line] resume vertical motion."
+ (interactive "P")
+ (if arg
+ (progn
+ (setq goal-column nil)
+ (message "No goal column"))
+ (setq goal-column (current-column))
+ (message (substitute-command-keys
+ "Goal column %d (use \\[set-goal-column] with an arg to unset it)")
+ goal-column))
+ nil)
+
+(defun transpose-chars (arg)
+ "Interchange characters around point, moving forward one character.
+With prefix arg ARG, effect is to take character before point
+and drag it forward past ARG other characters (backward if ARG negative).
+If no argument and at end of line, the previous two chars are exchanged."
+ (interactive "*P")
+ (and (null arg) (eolp) (forward-char -1))
+ (transpose-subr 'forward-char (prefix-numeric-value arg)))
+
+(defun transpose-words (arg)
+ "Interchange words around point, leaving point at end of them.
+With prefix arg ARG, effect is to take word before or around point
+and drag it forward past ARG other words (backward if ARG negative).
+If ARG is zero, the words around or after point and around or after mark
+are interchanged."
+ (interactive "*p")
+ (transpose-subr 'forward-word arg))
+
+(defun transpose-sexps (arg)
+ "Like \\[transpose-words] but applies to sexps.
+Does not work on a sexp that point is in the middle of
+if it is a list or string."
+ (interactive "*p")
+ (transpose-subr 'forward-sexp arg))
+
+(defun transpose-lines (arg)
+ "Exchange current line and previous line, leaving point after both.
+With argument ARG, takes previous line and moves it past ARG lines.
+With argument 0, interchanges line point is in with line mark is in."
+ (interactive "*p")
+ (transpose-subr (function
+ (lambda (arg)
+ (if (= arg 1)
+ (progn
+ ;; Move forward over a line,
+ ;; but create a newline if none exists yet.
+ (end-of-line)
+ (if (eobp)
+ (newline)
+ (forward-char 1)))
+ (forward-line arg))))
+ arg))
+
+(defun transpose-subr (mover arg)
+ (let (start1 end1 start2 end2)
+ (if (= arg 0)
+ (progn
+ (save-excursion
+ (funcall mover 1)
+ (setq end2 (point))
+ (funcall mover -1)
+ (setq start2 (point))
+ (goto-char (mark))
+ (funcall mover 1)
+ (setq end1 (point))
+ (funcall mover -1)
+ (setq start1 (point))
+ (transpose-subr-1))
+ (exchange-point-and-mark)))
+ (while (> arg 0)
+ (funcall mover -1)
+ (setq start1 (point))
+ (funcall mover 1)
+ (setq end1 (point))
+ (funcall mover 1)
+ (setq end2 (point))
+ (funcall mover -1)
+ (setq start2 (point))
+ (transpose-subr-1)
+ (goto-char end2)
+ (setq arg (1- arg)))
+ (while (< arg 0)
+ (funcall mover -1)
+ (setq start2 (point))
+ (funcall mover -1)
+ (setq start1 (point))
+ (funcall mover 1)
+ (setq end1 (point))
+ (funcall mover 1)
+ (setq end2 (point))
+ (transpose-subr-1)
+ (setq arg (1+ arg)))))
+
+(defun transpose-subr-1 ()
+ (if (> (min end1 end2) (max start1 start2))
+ (error "Don't have two things to transpose"))
+ (let ((word1 (buffer-substring start1 end1))
+ (word2 (buffer-substring start2 end2)))
+ (delete-region start2 end2)
+ (goto-char start2)
+ (insert word1)
+ (goto-char (if (< start1 start2) start1
+ (+ start1 (- (length word1) (length word2)))))
+ (delete-char (length word1))
+ (insert word2)))
+
+(defconst comment-column 32
+ "*Column to indent right-margin comments to.
+Setting this variable automatically makes it local to the current buffer.")
+(make-variable-buffer-local 'comment-column)
+
+(defconst comment-start nil
+ "*String to insert to start a new comment, or nil if no comment syntax defined.")
+
+(defconst comment-start-skip nil
+ "*Regexp to match the start of a comment plus everything up to its body.
+If there are any \\(...\\) pairs, the comment delimiter text is held to begin
+at the place matched by the close of the first pair.")
+
+(defconst comment-end ""
+ "*String to insert to end a new comment.
+Should be an empty string if comments are terminated by end-of-line.")
+
+(defconst comment-indent-hook
+ '(lambda () comment-column)
+ "Function to compute desired indentation for a comment
+given the character number it starts at.")
+
+(defun indent-for-comment ()
+ "Indent this line's comment to comment column, or insert an empty comment."
+ (interactive "*")
+ (beginning-of-line 1)
+ (if (null comment-start)
+ (error "No comment syntax defined")
+ (let* ((eolpos (save-excursion (end-of-line) (point)))
+ cpos indent begpos)
+ (if (re-search-forward comment-start-skip eolpos 'move)
+ (progn (setq cpos (point-marker))
+ ;; Find the start of the comment delimiter.
+ ;; If there were paren-pairs in comment-start-skip,
+ ;; position at the end of the first pair.
+ (if (match-end 1)
+ (goto-char (match-end 1))
+ ;; If comment-start-skip matched a string with internal
+ ;; whitespace (not final whitespace) then the delimiter
+ ;; start at the end of that whitespace.
+ ;; Otherwise, it starts at the beginning of what was matched.
+ (skip-chars-backward " \t" (match-beginning 0))
+ (skip-chars-backward "^ \t" (match-beginning 0)))))
+ (setq begpos (point))
+ ;; Compute desired indent.
+ (if (= (current-column)
+ (setq indent (funcall comment-indent-hook)))
+ (goto-char begpos)
+ ;; If that's different from current, change it.
+ (skip-chars-backward " \t")
+ (delete-region (point) begpos)
+ (indent-to indent))
+ ;; An existing comment?
+ (if cpos
+ (progn (goto-char cpos)
+ (set-marker cpos nil))
+ ;; No, insert one.
+ (insert comment-start)
+ (save-excursion
+ (insert comment-end))))))
+
+(defun set-comment-column (arg)
+ "Set the comment column based on point.
+With no arg, set the comment column to the current column.
+With just minus as arg, kill any comment on this line.
+With any other arg, set comment column to indentation of the previous comment
+ and then align or create a comment on this line at that column."
+ (interactive "P")
+ (if (eq arg '-)
+ (kill-comment nil)
+ (if arg
+ (progn
+ (save-excursion
+ (beginning-of-line)
+ (re-search-backward comment-start-skip)
+ (beginning-of-line)
+ (re-search-forward comment-start-skip)
+ (goto-char (match-beginning 0))
+ (setq comment-column (current-column))
+ (message "Comment column set to %d" comment-column))
+ (indent-for-comment))
+ (setq comment-column (current-column))
+ (message "Comment column set to %d" comment-column))))
+
+(defun kill-comment (arg)
+ "Kill the comment on this line, if any.
+With argument, kill comments on that many lines starting with this one."
+ (interactive "P")
+ (barf-if-buffer-read-only)
+ (let ((count (prefix-numeric-value arg)))
+ (beginning-of-line)
+ (while (> count 0)
+ (let ((eolpos (save-excursion (end-of-line) (point))))
+ (if (re-search-forward comment-start-skip eolpos t)
+ (progn
+ (goto-char (match-beginning 0))
+ (skip-chars-backward " \t")
+ (kill-region (point) eolpos))))
+ (if arg
+ (forward-line 1))
+ (setq count (1- count)))))
+
+(defun backward-word (arg)
+ "Move backward until encountering the end of a word.
+With argument, do this that many times.
+In programs, it is faster to call forward-word with negative arg."
+ (interactive "p")
+ (forward-word (- arg)))
+
+(defun mark-word (arg)
+ "Set mark arg words away from point."
+ (interactive "p")
+ (push-mark
+ (save-excursion
+ (forward-word arg)
+ (point))))
+
+(defun kill-word (arg)
+ "Kill characters forward until encountering the end of a word.
+With argument, do this that many times."
+ (interactive "*p")
+ (kill-region (point) (progn (forward-word arg) (point))))
+
+(defun backward-kill-word (arg)
+ "Kill characters backward until encountering the end of a word.
+With argument, do this that many times."
+ (interactive "*p")
+ (kill-word (- arg)))
+
+(defconst fill-prefix nil
+ "*String for filling to insert at front of new line, or nil for none.
+Setting this variable automatically makes it local to the current buffer.")
+(make-variable-buffer-local 'fill-prefix)
+
+(defun do-auto-fill ()
+ (let ((fill-point
+ (let ((opoint (point)))
+ (save-excursion
+ (move-to-column (1+ fill-column))
+ (skip-chars-backward "^ \t\n")
+ (if (bolp)
+ (re-search-forward "[ \t]" opoint t))
+ (skip-chars-backward " \t")
+ (point)))))
+ ;; If there is a space on the line before fill-point,
+ ;; and nonspaces precede it, break the line there.
+ (if (save-excursion
+ (goto-char fill-point)
+ (not (bolp)))
+ ;; If point is at the fill-point, do not `save-excursion'.
+ ;; Otherwise, if a comment prefix or fill-prefix is inserted,
+ ;; point will end up before it rather than after it.
+ (if (save-excursion
+ (skip-chars-backward " \t")
+ (= (point) fill-point))
+ (indent-new-comment-line)
+ (save-excursion
+ (goto-char fill-point)
+ (indent-new-comment-line))))))
+
+(defconst comment-multi-line nil
+ "*Non-nil means \\[indent-new-comment-line] should continue same comment
+on new line, with no new terminator or starter.")
+
+(defun indent-new-comment-line ()
+ "Break line at point and indent, continuing comment if presently within one.
+The body of the continued comment is indented under the previous comment line."
+ (interactive "*")
+ (let (comcol comstart)
+ (skip-chars-backward " \t")
+ (delete-region (point)
+ (progn (skip-chars-forward " \t")
+ (point)))
+ (insert ?\n)
+ (save-excursion
+ (if (and comment-start-skip
+ (let ((opoint (point)))
+ (forward-line -1)
+ (re-search-forward comment-start-skip opoint t)))
+ ;; The old line is a comment.
+ ;; Set WIN to the pos of the comment-start.
+ ;; But if the comment is empty, look at preceding lines
+ ;; to find one that has a nonempty comment.
+ (let ((win (match-beginning 0)))
+ (while (and (eolp) (not (bobp))
+ (let (opoint)
+ (beginning-of-line)
+ (setq opoint (point))
+ (forward-line -1)
+ (re-search-forward comment-start-skip opoint t)))
+ (setq win (match-beginning 0)))
+ ;; Indent this line like what we found.
+ (goto-char win)
+ (setq comcol (current-column))
+ (setq comstart (buffer-substring (point) (match-end 0))))))
+ (if comcol
+ (let ((comment-column comcol)
+ (comment-start comstart)
+ (comment-end comment-end))
+ (and comment-end (not (equal comment-end ""))
+ (if (not comment-multi-line)
+ (progn
+ (forward-char -1)
+ (insert comment-end)
+ (forward-char 1))
+ (setq comment-column (+ comment-column (length comment-start))
+ comment-start "")))
+ (if (not (eolp))
+ (setq comment-end ""))
+ (insert ?\n)
+ (forward-char -1)
+ (indent-for-comment)
+ (delete-char 1))
+ (if fill-prefix
+ (insert fill-prefix)
+ (indent-according-to-mode)))))
+
+(defun auto-fill-mode (arg)
+ "Toggle auto-fill mode.
+With arg, turn auto-fill mode on iff arg is positive.
+In auto-fill mode, inserting a space at a column beyond fill-column
+automatically breaks the line at a previous space."
+ (interactive "P")
+ (prog1 (setq auto-fill-hook
+ (if (if (null arg)
+ (not auto-fill-hook)
+ (> (prefix-numeric-value arg) 0))
+ 'do-auto-fill
+ nil))
+ ;; update mode-line
+ (set-buffer-modified-p (buffer-modified-p))))
+
+(defun turn-on-auto-fill ()
+ "Unconditionally turn on Auto Fill mode."
+ (auto-fill-mode 1))
+
+(defun set-fill-column (arg)
+ "Set fill-column to current column, or to argument if given.
+fill-column's value is separate for each buffer."
+ (interactive "P")
+ (setq fill-column (if (integerp arg) arg (current-column)))
+ (message "fill-column set to %d" fill-column))
+
+(defun set-selective-display (arg)
+ "Set selective-display to ARG; clear it if no arg.
+When selective-display is a number > 0,
+lines whose indentation is >= selective-display are not displayed.
+selective-display's value is separate for each buffer."
+ (interactive "P")
+ (if (eq selective-display t)
+ (error "selective-display already in use for marked lines"))
+ (setq selective-display
+ (and arg (prefix-numeric-value arg)))
+ (set-window-start (selected-window) (window-start (selected-window)))
+ (princ "selective-display set to " t)
+ (prin1 selective-display t)
+ (princ "." t))
+
+(defun overwrite-mode (arg)
+ "Toggle overwrite mode.
+With arg, turn overwrite mode on iff arg is positive.
+In overwrite mode, printing characters typed in replace existing text
+on a one-for-one basis, rather than pushing it to the right."
+ (interactive "P")
+ (setq overwrite-mode
+ (if (null arg) (not overwrite-mode)
+ (> (prefix-numeric-value arg) 0)))
+ (set-buffer-modified-p (buffer-modified-p))) ;No-op, but updates mode line.
+
+(defconst blink-matching-paren t
+ "*Non-nil means show matching open-paren when close-paren is inserted.")
+
+(defconst blink-matching-paren-distance 4000
+ "*If non-nil, is maximum distance to search for matching open-paren
+when close-paren is inserted.")
+
+(defun blink-matching-open ()
+ "Move cursor momentarily to the beginning of the sexp before point."
+ (and (> (point) (1+ (point-min)))
+ (/= (char-syntax (char-after (- (point) 2))) ?\\ )
+ blink-matching-paren
+ (let* ((oldpos (point))
+ (blinkpos)
+ (mismatch))
+ (save-excursion
+ (save-restriction
+ (if blink-matching-paren-distance
+ (narrow-to-region (max (point-min)
+ (- (point) blink-matching-paren-distance))
+ oldpos))
+ (condition-case ()
+ (setq blinkpos (scan-sexps oldpos -1))
+ (error nil)))
+ (and blinkpos (/= (char-syntax (char-after blinkpos))
+ ?\$)
+ (setq mismatch
+ (/= (char-after (1- oldpos))
+ (logand (lsh (aref (syntax-table)
+ (char-after blinkpos))
+ -8)
+ 255))))
+ (if mismatch (setq blinkpos nil))
+ (if blinkpos
+ (progn
+ (goto-char blinkpos)
+ (if (pos-visible-in-window-p)
+ (sit-for 1)
+ (goto-char blinkpos)
+ (message
+ "Matches %s"
+ (if (save-excursion
+ (skip-chars-backward " \t")
+ (not (bolp)))
+ (buffer-substring (progn (beginning-of-line) (point))
+ (1+ blinkpos))
+ (buffer-substring blinkpos
+ (progn
+ (forward-char 1)
+ (skip-chars-forward "\n \t")
+ (end-of-line)
+ (point)))))))
+ (cond (mismatch
+ (message "Mismatched parentheses"))
+ ((not blink-matching-paren-distance)
+ (message "Unmatched parenthesis"))))))))
+
+;Turned off because it makes dbx bomb out.
+(setq blink-paren-hook 'blink-matching-open)
+
+; this is just something for the luser to see in a keymap -- this is not
+; how quitting works normally!
+(defun keyboard-quit ()
+ "Signal a quit condition."
+ (interactive)
+ (signal 'quit nil))
+
+(define-key global-map "\C-g" 'keyboard-quit)
+
+(defun set-variable (var val)
+ "Set VARIABLE to VALUE. VALUE is a Lisp object.
+When using this interactively, supply a Lisp expression for VALUE.
+If you want VALUE to be a string, you must surround it with doublequotes."
+ (interactive
+ (let* ((var (read-variable "Set variable: "))
+ (minibuffer-help-form
+ '(funcall myhelp))
+ (myhelp
+ (function
+ (lambda ()
+ (with-output-to-temp-buffer "*Help*"
+ (prin1 var)
+ (princ "\nDocumentation:\n")
+ (princ (substring (documentation-property var 'variable-documentation)
+ 1))
+ (if (boundp var)
+ (let ((print-length 20))
+ (princ "\n\nCurrent value: ")
+ (prin1 (symbol-value var))))
+ nil)))))
+ (list var
+ (eval-minibuffer (format "Set %s to value: " var)))))
+ (set var val))
+
+;These commands are defined in editfns.c
+;but they are not assigned to keys there.
+(put 'narrow-to-region 'disabled t)
+(define-key ctl-x-map "n" 'narrow-to-region)
+(define-key ctl-x-map "w" 'widen)
+
+(define-key global-map "\C-j" 'newline-and-indent)
+(define-key global-map "\C-m" 'newline)
+(define-key global-map "\C-o" 'open-line)
+(define-key esc-map "\C-o" 'split-line)
+(define-key global-map "\C-q" 'quoted-insert)
+(define-key esc-map "^" 'delete-indentation)
+(define-key esc-map "\\" 'delete-horizontal-space)
+(define-key esc-map "m" 'back-to-indentation)
+(define-key ctl-x-map "\C-o" 'delete-blank-lines)
+(define-key esc-map " " 'just-one-space)
+(define-key esc-map "z" 'zap-to-char)
+(define-key esc-map "=" 'count-lines-region)
+(define-key ctl-x-map "=" 'what-cursor-position)
+(define-key esc-map "\e" 'eval-expression)
+(define-key ctl-x-map "\e" 'repeat-complex-command)
+(define-key ctl-x-map "u" 'advertised-undo)
+(define-key global-map "\C-_" 'undo)
+(define-key esc-map "!" 'shell-command)
+(define-key esc-map "|" 'shell-command-on-region)
+
+(define-key global-map "\C-u" 'universal-argument)
+(let ((i ?0))
+ (while (<= i ?9)
+ (define-key esc-map (char-to-string i) 'digit-argument)
+ (setq i (1+ i))))
+(define-key esc-map "-" 'negative-argument)
+
+(define-key global-map "\C-k" 'kill-line)
+(define-key global-map "\C-w" 'kill-region)
+(define-key esc-map "w" 'copy-region-as-kill)
+(define-key esc-map "\C-w" 'append-next-kill)
+(define-key global-map "\C-y" 'yank)
+(define-key esc-map "y" 'yank-pop)
+
+(define-key ctl-x-map "a" 'append-to-buffer)
+
+(define-key global-map "\C-@" 'set-mark-command)
+(define-key ctl-x-map "\C-x" 'exchange-point-and-mark)
+
+(define-key global-map "\C-n" 'next-line)
+(define-key global-map "\C-p" 'previous-line)
+(define-key ctl-x-map "\C-n" 'set-goal-column)
+
+(define-key global-map "\C-t" 'transpose-chars)
+(define-key esc-map "t" 'transpose-words)
+(define-key esc-map "\C-t" 'transpose-sexps)
+(define-key ctl-x-map "\C-t" 'transpose-lines)
+
+(define-key esc-map ";" 'indent-for-comment)
+(define-key esc-map "j" 'indent-new-comment-line)
+(define-key esc-map "\C-j" 'indent-new-comment-line)
+(define-key ctl-x-map ";" 'set-comment-column)
+(define-key ctl-x-map "f" 'set-fill-column)
+(define-key ctl-x-map "$" 'set-selective-display)
+
+(define-key esc-map "@" 'mark-word)
+(define-key esc-map "f" 'forward-word)
+(define-key esc-map "b" 'backward-word)
+(define-key esc-map "d" 'kill-word)
+(define-key esc-map "\177" 'backward-kill-word)
+
+(define-key esc-map "<" 'beginning-of-buffer)
+(define-key esc-map ">" 'end-of-buffer)
+(define-key ctl-x-map "h" 'mark-whole-buffer)
+(define-key esc-map "\\" 'delete-horizontal-space)
+
+(fset 'mode-specific-command-prefix (make-sparse-keymap))
+(defconst mode-specific-map (symbol-function 'mode-specific-command-prefix)
+ "Keymap for characters following C-c.")
+(define-key global-map "\C-c" 'mode-specific-command-prefix)
diff --git a/lisp/simple.elc b/lisp/simple.elc
new file mode 100644
index 00000000000..86a7623607e
--- /dev/null
+++ b/lisp/simple.elc
Binary files differ
diff --git a/lisp/simula.defns b/lisp/simula.defns
new file mode 100644
index 00000000000..935e9b4eb72
--- /dev/null
+++ b/lisp/simula.defns
@@ -0,0 +1,185 @@
+(define-abbrev-table 'simula-mode-abbrev-table '(
+ ("putreal" "PutReal" nil 0)
+ ("printfile" "Printfile" nil 0)
+ ("location" "Location" nil 0)
+ ("abs" "Abs" nil 0)
+ ("value" "VALUE" nil 0)
+ ("tanh" "Tanh" nil 0)
+ ("sinh" "Sinh" nil 0)
+ ("digit" "Digit" nil 0)
+ ("arctan" "ArcTan" nil 0)
+ ("arcsin" "ArcSin" nil 0)
+ ("cardinal" "Cardinal" nil 0)
+ ("linkage" "Linkage" nil 0)
+ ("cos" "Cos" nil 0)
+ ("virtual" "VIRTUAL" nil 0)
+ ("outimage" "OutImage" nil 0)
+ ("or" "OR" nil 0)
+ ("false" "FALSE" nil 0)
+ ("outreal" "OutReal" nil 0)
+ ("more" "More" nil 0)
+ ("if" "IF" nil 0)
+ ("histd" "Histd" nil 0)
+ ("getchar" "GetChar" nil 0)
+ ("not" "NOT" nil 0)
+ ("letter" "Letter" nil 0)
+ ("external" "EXTERNAL" nil 0)
+ ("text" "TEXT" nil 0)
+ ("intext" "InText" nil 0)
+ ("gt" "GT" nil 0)
+ ("boolean" "BOOLEAN" nil 0)
+ ("suc" "Suc" nil 0)
+ ("putfrac" "PutFrac" nil 0)
+ ("label" "LABEL" nil 0)
+ ("infile" "InFile" nil 0)
+ ("sub" "Sub" nil 0)
+ ("step" "STEP" nil 0)
+ ("poisson" "Poisson" nil 0)
+ ("locate" "Locate" nil 0)
+ ("accum" "Accum" nil 0)
+ ("out" "Out" nil 0)
+ ("go" "GO" nil 0)
+ ("endfile" "Endfile" nil 0)
+ ("inimage" "InImage" nil 0)
+ ("image" "Image" nil 0)
+ ("hidden" "HIDDEN" nil 0)
+ ("open" "Open" nil 0)
+ ("lastitem" "Lastitem" nil 0)
+ ("array" "ARRAY" nil 0)
+ ("prev" "Prev" nil 0)
+ ("outfrac" "OutFrac" nil 0)
+ ("name" "NAME" nil 0)
+ ("long" "LONG" nil 0)
+ ("getreal" "GetReal" nil 0)
+ ("end" "END" nil 0)
+ ("detach" "Detach" nil 0)
+ ("linear" "Linear" nil 0)
+ ("isorank" "ISORank" nil 0)
+ ("putfix" "PutFix" nil 0)
+ ("hold" "Hold" nil 0)
+ ("delay" "DELAY" nil 0)
+ ("comment" "COMMENT" nil 0)
+ ("while" "WHILE" nil 0)
+ ("rank" "Rank" nil 0)
+ ("randint" "RandInt" nil 0)
+ ("erlang" "Erlang" nil 0)
+ ("constant" "Constant" nil 0)
+ ("strip" "Strip" nil 0)
+ ("setpos" "Setpos" nil 0)
+ ("protected" "PROTECTED" nil 0)
+ ("main" "Main" nil 0)
+ ("ref" "REF" nil 0)
+ ("qua" "QUA" nil 0)
+ ("precede" "Precede" nil 0)
+ ("passivate" "Passivate" nil 0)
+ ("ge" "GE" nil 0)
+ ("discrete" "Discrete" nil 0)
+ ("before" "BEFORE" nil 0)
+ ("options" "OPTIONS" nil 0)
+ ("new" "NEW" nil 0)
+ ("length" "Length" nil 0)
+ ("procedure" "PROCEDURE" nil 0)
+ ("ne" "NE" nil 0)
+ ("to" "TO" nil 0)
+ ("short" "SHORT" nil 0)
+ ("putint" "PutInt" nil 0)
+ ("lt" "LT" nil 0)
+ ("into" "Into" nil 0)
+ ("eq" "EQ" nil 0)
+ ("character" "CHARACTER" nil 0)
+ ("wait" "Wait" nil 0)
+ ("until" "UNTIL" nil 0)
+ ("mod" "Mod" nil 0)
+ ("getfrac" "GetFrac" nil 0)
+ ("current" "Current" nil 0)
+ ("simset" "SimSet" nil 0)
+ ("outtext" "OutText" nil 0)
+ ("arccos" "ArcCos" nil 0)
+ ("start" "Start" nil 0)
+ ("resume" "Resume" nil 0)
+ ("inner" "INNER" nil 0)
+ ("when" "WHEN" nil 0)
+ ("terminate_pogram" "Terminate_Program" nil 0)
+ ("outfile" "OutFile" nil 0)
+ ("isochar" "ISOChar" nil 0)
+ ("time" "Time" nil 0)
+ ("integer" "INTEGER" nil 0)
+ ("then" "THEN" nil 0)
+ ("nextev" "Nextev" nil 0)
+ ("ln" "Ln" nil 0)
+ ("inchar" "InChar" nil 0)
+ ("idle" "Idle" nil 0)
+ ("empty" "Empty" nil 0)
+ ("char" "Char" nil 0)
+ ("last" "Last" nil 0)
+ ("eqv" "EQV" nil 0)
+ ("pred" "Pred" nil 0)
+ ("class" "CLASS" nil 0)
+ ("tan" "Tan" nil 0)
+ ("sqrt" "Sqrt" nil 0)
+ ("sin" "Sin" nil 0)
+ ("blanks" "Blanks" nil 0)
+ ("do" "DO" nil 0)
+ ("and" "AND" nil 0)
+ ("else" "ELSE" nil 0)
+ ("close" "Close" nil 0)
+ ("breakoutimage" "BreakOutImage" nil 0)
+ ("activate" "ACTIVATE" nil 0)
+ ("switch" "SWITCH" nil 0)
+ ("head" "Head" nil 0)
+ ("otherwise" "OTHERWISE" nil 0)
+ ("inint" "InInt" nil 0)
+ ("true" "TRUE" nil 0)
+ ("normal" "Normal" nil 0)
+ ("cosh" "Cosh" nil 0)
+ ("begin" "BEGIN" nil 0)
+ ("outfix" "OutFix" nil 0)
+ ("le" "LE" nil 0)
+ ("evtime" "Evtime" nil 0)
+ ("clear" "Clear" nil 0)
+ ("link" "Link" nil 0)
+ ("goto" "GOTO" nil 0)
+ ("exp" "Exp" nil 0)
+ ("uniform" "Uniform" nil 0)
+ ("real" "REAL" nil 0)
+ ("inreal" "InReal" nil 0)
+ ("getint" "GetInt" nil 0)
+ ("notext" "NOTEXT" nil 0)
+ ("call" "Call" nil 0)
+ ("spacing" "Spacing" nil 0)
+ ("putchar" "PutChar" nil 0)
+ ("sysout" "SysOut" nil 0)
+ ("copy" "Copy" nil 0)
+ ("after" "AFTER" nil 0)
+ ("line" "Line" nil 0)
+ ("for" "FOR" nil 0)
+ ("reactivate" "REACTIVATE" nil 0)
+ ("outint" "OutInt" nil 0)
+ ("directfile" "Directfile" nil 0)
+ ("terminated" "Terminated" nil 0)
+ ("sign" "Sign" nil 0)
+ ("process" "Process" nil 0)
+ ("negexp" "NegExp" nil 0)
+ ("is" "IS" nil 0)
+ ("imp" "IMP" nil 0)
+ ("follow" "Follow" nil 0)
+ ("prior" "PRIOR" nil 0)
+ ("first" "First" nil 0)
+ ("sysin" "SysIn" nil 0)
+ ("simulation" "Simulation" nil 0)
+ ("outchar" "OutChar" nil 0)
+ ("lowten" "LowTen" nil 0)
+ ("inspect" "INSPECT" nil 0)
+ ("histo" "Histo" nil 0)
+ ("eject" "Eject" nil 0)
+ ("this" "THIS" nil 0)
+ ("infrac" "InFrac" nil 0)
+ ("cancel" "Cancel" nil 0)
+ ("linesperpage" "LinesPerPage" nil 0)
+ ("draw" "Draw" nil 0)
+ ("at" "AT" nil 0)
+ ("pos" "Pos" nil 0)
+ ("none" "NONE" nil 0)
+ ("in" "IN" nil 0)
+ ("entier" "Entier" nil 0)
+ ))
diff --git a/lisp/simula.el b/lisp/simula.el
new file mode 100644
index 00000000000..206b639cb5e
--- /dev/null
+++ b/lisp/simula.el
@@ -0,0 +1,827 @@
+;; --- Simula Mode for GNU Emacs
+;; Copyright (C) 1988 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 1, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+;; Written by Ole Bj|rn Hessen.
+;; Disclaimer: This is my first lisp program > 10 lines, and -- most of
+;; all an experiment using reg-exp to represent forms on the screen.
+;; The parser parses simula backward, an impossible job.
+;; Well, I nearly lost!! Luckily, hhe@ifi.uio.no plan to make a better one.
+
+(defvar simula-label "^[A-Za-z_{|}]+:")
+(defvar simula-CE "else\\b\\|when\\b\\|otherwise\\b")
+(defvar simula-CB "end\\b\\|!\\|comment\\b")
+(defvar simula-BE "end\\b")
+(defvar simula-BB "begin\\b")
+(defvar simula-FB "if\\b\\|while\\b\\|inspect\\b\\|for\\b")
+(defvar simula-eol "\n")
+(defvar simula-eof "@") ;the form is postfixed by this string
+
+(defvar simula-extended-form nil
+ "non-nil if want non-standard slowly (extended) form checking")
+
+(defvar simula-mode-syntax-table nil
+ "Syntax table in simula-mode buffers.")
+
+(defvar simula-mode-abbrev-table nil
+ "abbrev table in simula-mode buffers")
+
+(defvar simula-indent-mode 'simula-Nice-indent-mode)
+;;most users want this feature...
+
+(defvar Read-Simula-Keywords nil
+ "non-nil if read keywords already")
+
+(define-abbrev-table 'simula-mode-abbrev-table ())
+
+(defvar Simula-Keyword-Abbrev-File "simula.defns"
+ "nil if not to load the Capitalize Keywords feature")
+
+(defvar simula-mode-ignore-directives t
+ "Set to non nil if doesn't use % comment type lines.")
+
+(if simula-mode-syntax-table
+ ()
+ (let ((table (make-syntax-table)))
+ (modify-syntax-entry ?\n "." table)
+ (modify-syntax-entry ?\f "." table)
+ (modify-syntax-entry ?\" "\"" table)
+ (modify-syntax-entry ?' "\"" table)
+ (modify-syntax-entry ?( "()" table)
+ (modify-syntax-entry ?) ")(" table)
+ (modify-syntax-entry ?* "." table)
+ (modify-syntax-entry ?+ "." table)
+ (modify-syntax-entry ?, "." table)
+ (modify-syntax-entry ?- "." table)
+ (modify-syntax-entry ?. "_" table)
+ (modify-syntax-entry ?_ "w" table)
+ (modify-syntax-entry ?/ "." table)
+ (modify-syntax-entry ?: "." table)
+ (modify-syntax-entry ?; ">" table)
+ (modify-syntax-entry ?< "." table)
+ (modify-syntax-entry ?= "." table)
+ (modify-syntax-entry ?> "." table)
+ (modify-syntax-entry ?[ "(]" table)
+ (modify-syntax-entry ?\\ "." table)
+ (modify-syntax-entry ?] ")[" table)
+ (modify-syntax-entry ?^ "." table)
+ (modify-syntax-entry ?\| "w" table)
+ (modify-syntax-entry ?\{ "w" table)
+ (modify-syntax-entry ?\} "w" table)
+ (modify-syntax-entry ?! "<" table)
+ (setq simula-mode-syntax-table table)))
+
+(defvar simula-mode-map ()
+ "Keymap used in simula mode.")
+
+(if simula-mode-map
+ ()
+ (setq simula-mode-map (make-sparse-keymap))
+ (define-key simula-mode-map "\t" 'simula-indent)
+ (define-key simula-mode-map "\r" 'simula-abbrev-expand-and-lf)
+ (define-key simula-mode-map "" 'backward-delete-char-untabify))
+
+
+(defun simula-mode ()
+ "This is a mode intended to support program development in Simula.."
+ (interactive)
+ (kill-all-local-variables)
+ (use-local-map simula-mode-map)
+ (setq major-mode 'simula-mode)
+ (setq mode-name "Simula")
+ (make-local-variable 'comment-column)
+ (setq comment-column 40)
+ (make-local-variable 'end-comment-column)
+ (setq end-comment-column 75)
+ (set-syntax-table simula-mode-syntax-table)
+ (make-local-variable 'paragraph-start)
+ (setq paragraph-start "^[ \t]*$\\|\\f")
+ (make-local-variable 'paragraph-separate)
+ (setq paragraph-separate paragraph-start)
+ (make-local-variable 'indent-line-function)
+ (setq indent-line-function 'simula-null-indent)
+ (make-local-variable 'require-final-newline)
+ (setq require-final-newline t) ;put a newline at end!
+ (make-local-variable 'comment-start)
+ (setq comment-start "! ")
+ (make-local-variable 'comment-end)
+ (setq comment-end " ;")
+ (make-local-variable 'comment-start-skip)
+ (setq comment-start-skip "!+ *")
+ (make-local-variable 'comment-column)
+ (setq comment-start-skip "! *") ;not quite right, but..
+ (make-local-variable 'parse-sexp-ignore-comments)
+ (setq parse-sexp-ignore-comments nil)
+ (make-local-variable 'comment-multi-line)
+ (setq comment-multi-line t)
+ (setq local-abbrev-table simula-mode-abbrev-table)
+ ;;Capitalize-Simula-Keywords ought to run a hook!!!
+ (if Simula-Keyword-Abbrev-File
+ (progn
+ (setq abbrev-mode t)
+ (if Read-Simula-Keywords
+ ()
+ (condition-case err
+ (read-abbrev-file Simula-Keyword-Abbrev-File)
+ (file-error
+ (with-output-to-temp-buffer "*Help*"
+ (princ "Simula Mode can't load the Capitalize Simula ")
+ (princ "Keyword abbrev file\n\n")
+ (princ "Please do one of the following:\n")
+ (princ "1. Include this line in your .emacs file:\n")
+ (princ " (setq Simula-Keyword-Abbrev-File nil)\n")
+ (princ "2. Make a decent abbrev file by your self\n")
+ (princ "3. Mail obh@ifi.uio.no requesting the abbrev file\n"))))
+ (setq Read-Simula-Keywords t))))
+ (funcall simula-indent-mode) ;set indentation
+ (run-hooks 'simula-mode-hook))
+
+(defun simula-null-indent ()
+ (interactive))
+
+(setq simula-seen-FE nil) ;if seen FE during parsing; non-nil
+(setq simula-form-starter nil) ;string, the FB.
+(setq simula-form nil) ;string, the assembled form
+(setq simula-FB-hpos nil) ;FB's Hpos
+(setq simula-BB-hpos nil) ;BB's Hpos
+(setq simula-hpos nil) ;Hpos of preceeding simula form
+(setq simula-lf-count nil) ;A count of lf seen during parsing
+(setq simula-stack nil) ;A stack of regions representing form
+(setq simula-assemble nil) ;non-nil if assembling forms on stack
+(setq simula-debug nil) ;t if debugging forms
+
+
+;; some simple stack routines.
+(defun simula-push (v)
+ (if simula-assemble (setq simula-stack (cons v simula-stack))))
+
+(defun simula-pop ()
+ (prog1 (car simula-stack)
+ (setq simula-stack (cdr simula-stack))))
+;;The concepts of a stack is now obsolete...
+;;Major rewrite is wanted..
+
+(defun simula-inside-simple-string ()
+ ;returns t if inside a simulask simple string
+ (save-excursion
+ (skip-chars-backward "^\"\n'")
+ (if (bolp) nil
+ (let ((count 1))
+ (while (not (bolp))
+ (forward-char -1)
+ (skip-chars-backward "^\"\n'")
+ (setq count (1+ count)))
+ (= (% count 2) 0)))))
+
+
+;;ignore line starting with a %.
+;;form is evaled until line is not a compiler directive
+;;way is t if going forward
+;;returns with value of form
+;;didn't found how to use the right kind of scoping, so shit!!!
+;; -- HELP --
+
+(defun ignore-simula-directives (pedohejform &optional pedohejway)
+ (interactive)
+ (if simula-mode-ignore-directives (funcall pedohejform)
+ (let ((pedohejval (funcall pedohejform)) (pedohejhere (point)))
+ (beginning-of-line)
+ (while ;while directive line
+ (cond
+ ((not (= (following-char) ?%)) nil)
+ ((or (bobp) (eobp)) nil) ;and not beginning(end) of buffer
+ (t))
+ (if pedohejway (forward-line) (forward-char -1))
+ (setq pedohejval (funcall pedohejform)) ;execute form once more
+ (setq pedohejhere (point)) ;and goto beginning of that line.
+ (beginning-of-line))
+ (if (not (= (following-char) ?%)) (goto-char pedohejhere))
+ pedohejval))) ;return FROM if skipped something
+;Have you seen anybody prefixing a variable with my special password?
+;No? Good!
+
+
+;We are on a line which is _not_ a '%'-line directive,
+;and inside or _just_ after a '! blabla ;' or a 'end blabla ;' comment.
+;Our job is to skip that comment, returning position skipping from or
+;just nil if this is no comment
+
+(defun maybe-skip-simula-comment ()
+ (let ((here (point)) last-end tmp tmp1)
+ (ignore-simula-directives
+ (function
+ (lambda ()
+ (search-backward ";" (point-min) 0)
+ (while (simula-inside-simple-string)
+ (search-backward "\"")
+ (search-backward ";" (point-min) 0)))))
+ (re-search-forward
+ "^%\\|\"\\|!\\|\\bcomment\\b\\|\\bend\\b" here 0)
+ (while (or (= (setq tmp (preceding-char)) ?%)
+ (= tmp ?\"))
+ (if (= tmp ?\") (search-forward "\"" here 0)
+ (forward-line 1)
+ (if (> (point) here) (goto-char here)))
+ (re-search-forward
+ "^%\\|\"\\|!\\|\\bcomment\\b\\|\\bend\\b" here 0))
+ (if (= here (point)) nil ;no comment between "; blabla "
+ (if (= (preceding-char) ?!)
+ (progn ;a "; ! blabla " commentt
+ (forward-char -1)
+ here) ;ignore semicolon.
+ (forward-word -1)
+ (if (looking-at "comment")
+ here ;a "; comment blabla " string
+;; this is a end-comment
+ (setq last-end (point)) ;remember where end started
+ (while
+ (and ;skip directive lines
+ (progn ;and strings.
+ (setq tmp1
+ (re-search-forward
+ "^%\\|\"\\|!\\|\\bcomment\\b\\|\\bend\\b\\|\\bwhen\\b\\|\\belse\\b\\|\\botherwise\\b" here 0))
+ (while (and tmp1
+ (or (= (setq tmp (preceding-char)) ?%)
+ (= tmp ?\")))
+ (if (= tmp ?\") (search-forward "\"" here 0)
+ (forward-line 1))
+ (setq tmp1 (re-search-forward
+ "^%\\|\"\\|!\\|\\bcomment\\b\\|\\bend\\b\\|\\bwhen\\b\\|\\belse\\b\\|\\botherwise\\b" here 0)))
+ tmp1)
+ (cond
+ ((= (preceding-char) ?!) ;a "end ! " is part of end-comment
+ (if last-end ;skip it.
+ t
+ (forward-char -1) nil)) ;seen e.g. "end else !"
+ ;skip back over word
+ ((progn (forward-word -1) nil))
+ ((looking-at "comment")
+ (if (not last-end)
+ nil
+ (forward-word 1) t))
+ (t (setq last-end (if (looking-at "end") (point) nil))
+ (forward-word 1) t))))
+ (if (looking-at "!\\|\\bcomment")
+ here
+ (if last-end
+ (progn (goto-char last-end) here)
+ (goto-char here)
+ nil)))))))
+
+
+;;save this block form
+(defun save-simula-BB-BE()
+ (let ((end (point)) (beg nil))
+ (simula-push end)
+ (simula-back-level) ;goto before the begin at this level
+ (if (not simula-BB-hpos) ;save column number if this the first
+ (setq simula-BB-hpos (current-column)))
+ (setq beg (point))
+ (end-of-line)
+ (simula-push ;save unto stack a block level.
+ (concat
+ "BEGIN"
+ (if (> (point) end) ()
+ (setq simula-lf-count (1+ simula-lf-count))
+ simula-eol) ;there is a lf after the begin
+ " o "
+ (progn
+ (forward-line 2)
+ (if (> (point) end) ()
+ (setq simula-lf-count (1+ simula-lf-count))
+ simula-eol)))) ;and before the end.
+ (simula-push beg)
+ (goto-char beg)))
+
+
+
+
+;;assumes we are inside a begin blabla end sentence.
+;;returns _before_ the begin
+(defun simula-back-level()
+ (interactive)
+ (let ((end-comment))
+ (while
+ (and
+ (not (bobp))
+ (ignore-simula-directives
+ (function
+ (lambda ()
+ (re-search-backward "\\bend\\b\\|\\bbegin\\b" (point-min) 0)
+ (while (simula-inside-simple-string)
+ (search-backward "\"")
+ (re-search-backward "\\bend\\b\\|\\bbegin\\b" (point-min) 0))
+ t)))
+ (if (looking-at "begin")
+ (if (maybe-skip-simula-comment) ;ignore begin in (end)comments
+ (progn (if (looking-at "end") (forward-word 1)) t)
+ nil) ;else exit while.
+ (if (setq end-comment (maybe-skip-simula-comment))
+ (if (looking-at "comment\\|!") t ;then not an end-comment
+ (goto-char end-comment)
+ (simula-back-level)
+ t)
+ (simula-back-level)
+ t)))))
+ (if (not (looking-at "begin"))
+ (error "No matching BEGIN !!!")))
+
+
+
+;on entry cursor is on the line we should indent. It indent this line and
+;predicts the next line's hpos at return value!!
+(defun simula-find-indent (&optional predict-next)
+ (interactive)
+ (let
+ ((not-stop t) ;set to nil if stop parsing, 0 at bolp
+ (simexp 0) ;simexp= simula-lf-count, + simula exp.
+ tmp ch ;last read character
+ indent) ;hpos to indent lines line to.
+ (end-of-line)
+ (ignore-simula-directives ;ignore if this is a directive line
+ (function (lambda () (skip-chars-backward " \t"))))
+ (if (maybe-skip-simula-comment)
+ (if (looking-at "end") (forward-word 1)))
+ (setq simula-lf-count 0
+ simula-assemble t
+ simula-BB-hpos nil
+ simula-FB-hpos nil
+ simula-hpos nil
+ simula-seen-FE nil
+ simula-form nil
+ simula-form-starter nil ;string representing the form-starter
+ simula-stack (list (point) ;a stack of regions or strings.
+ simula-eof))
+ (while not-stop
+ (setq simexp (1+ simexp)) ;count up simula expressions seen.
+ (skip-chars-backward " \t") ;skip ignoring whitespace
+ (if (bobp)
+ (setq not-stop nil) ;stop at start og buffer
+ (if (= (char-syntax (setq ch (preceding-char))) ?w)
+ (forward-word -1) ;back over item (ie. word or char.)
+ (forward-char -1))
+ (cond
+ ((eolp) ;passed a new-line
+ (cond
+ ((numberp not-stop) ;if zero, then stop parsing.
+ (setq not-stop nil)
+ (forward-char 1))
+ (t ;else count up lf's
+ (if (/= simula-lf-count (1- simexp))
+ (setq simula-lf-count (1+ simula-lf-count)))
+ (setq simexp simula-lf-count) ;reset simexp.
+ (simula-push (1+ (point))) ;don't assemble newlines in
+ (ignore-simula-directives ;simula-form
+ (function (lambda () (skip-chars-backward " \t\n"))))
+ (simula-push simula-eol) ;save the newline
+ (simula-push (point))))) ;ignore region skipped
+
+ ((= ch ?\")
+ (save-simula-string)) ;skip the string
+
+ ((= ch ?\')
+ (forward-char -1)
+ (if (search-backward "'" (point-min) t)
+ (forward-char -1) ;skip to before '
+ (error "Unbalanced Character Quote")))
+
+ ((= ch ?:) (forward-word -1))
+
+ ((= ch ?\;) ;semicolon
+ (setq tmp (maybe-skip-simula-comment)) ;is this a comment?
+ (if (and tmp (looking-at "!\\|comment"))
+ (simula-parsed-over (1+ tmp)) ;ignore comments
+ (cond
+ ((and (> simula-lf-count 1) ;abort parsing if FE last exp in
+ (= simula-lf-count (1- simexp))) ;line only
+ (setq not-stop nil) ;stop parsing
+ (simula-stack-trick)) ;goto "next-line"
+ ((if (not tmp) nil ;do more parsing, but forget
+ (forward-word 1) ;the end-comment
+ (simula-parsed-over tmp)
+ nil))
+ ((= simexp 1) (setq simula-seen-FE t))
+ ((> simula-lf-count 0)
+ (simula-push (1+ (point)))
+ (setq simula-assemble nil))))) ;assemble only the last form
+
+ ((looking-at simula-BB)
+ (setq simula-seen-FE nil) ;forget the past
+ (if (> simula-lf-count 1)
+ (setq not-stop (simula-stack-trick)) ;stop here!!
+ (if (not simula-assemble)
+ (progn
+ (setq simula-stack (list (point)
+ (concat "/n o " simula-eof))
+ simula-assemble t)))
+ (if (not simula-BB-hpos)
+ (setq simula-BB-hpos (current-column)))))
+
+ ((and (looking-at simula-CE)
+ (setq tmp (maybe-skip-simula-comment)))
+ (forward-word 1) ;skip past end.
+ (simula-parsed-over tmp))
+
+ ((looking-at simula-BE) (save-simula-BB-BE))
+
+ ((and (not indent) ;if already found, skip this FB
+ (looking-at simula-FB))
+ (setq simula-form-starter
+ (buffer-substring (point) (match-end 0)))
+ (setq simula-FB-hpos (current-column))
+ (if (not (setq indent (Simula-Form-Handler)))
+ (setq simula-FB-hpos nil simula-form nil))
+ (if simula-seen-FE () ;if not seen FE, stop parsing
+ (setq not-stop nil) ;and indent from this line
+ (beginning-of-line))))))
+
+ (setq simula-hpos (current-simula-indentation)) ;save indentation
+ (if simula-form
+ (if (and predict-next simula-seen-FE)
+ (setcdr indent (cdr (Simula-Default-Handler))))
+ (setq indent (Simula-Default-Handler)))
+ indent))
+
+
+(defun simula-parsed-over (from)
+ (skip-chars-backward "\t") ;skip whitespace before comment.
+ (simula-push from) ;forget from
+ (save-excursion
+ (end-of-line) ;if passed newline don't forget
+ (if (< (point) from) ;that
+ (progn
+ (simula-push simula-eol)
+ (setq simula-lf-count (1+ simula-lf-count)))))
+ (simula-push (point))) ;mark region to be skipped past
+
+
+;;some better names wanted.
+(defun simula-stack-trick ()
+ ;;axiom: if skipped back over 2-* lines, then use the indentation
+ ;;of the line after the line where the BB was found. Or if skipped past
+ ;;at least two lines and see ";" + newline. Use next lines indentation.
+ ;;that means one must fix the stack..
+ (forward-line 1)
+ (ignore-simula-directives
+ (function
+ (lambda () (skip-chars-forward " \t\n")
+ (while (= (following-char) ?\!)
+ (search-forward ";" (point-max) 0)
+ (skip-chars-forward " \t\n"))))
+ t)
+ (let ((pointer simula-stack))
+ (while pointer
+ (if (and (numberp (car pointer))
+ (> (point) (car pointer)))
+ (setq simula-stack pointer pointer nil)
+ (setq pointer (cdr pointer))))) nil)
+
+
+(defun save-simula-string ()
+ (simula-push (point)) ;skip string contents
+ (skip-chars-backward "^\"\n" (point-min))
+ (if (= (preceding-char) ?\") nil
+ (error "UnBalanced String Quote \". "))
+ (simula-push (point))
+ (forward-char -1)) ;save the "" unto stack.
+
+
+(defun Simula-Form-Handler ()
+ (let ((handler (intern-soft
+ (concat "Simula-" (capitalize simula-form-starter)
+ "-Handler"))))
+ (if handler (funcall handler) nil)))
+
+
+(defun Simula-Default-Handler ()
+ (prog1
+ (if (and simula-seen-FE
+ (not simula-extended-form)
+ (not (or simula-BB-hpos simula-form)))
+ (list simula-hpos '(0 0))
+ (Simula-Default-Form-Handler Simula-Default-Form))
+ (setq simula-form nil)))
+
+
+
+(defun Simula-Default-Form-Handler (form)
+ (simula-collapse-stack) ;get assembled form
+ (let ((indentation (get-indent-amount form)))
+ (if (not indentation) nil
+ (setq simula-hpos
+ (if (not (bolp))
+ (save-excursion
+ (beginning-of-line)
+ (current-simula-indentation))
+ (current-simula-indentation))
+ indentation (cons (simula-indent-calc (car indentation))
+ (cdr indentation)))
+ indentation))) ;return (hpos (abs relhpos))
+
+(defun simula-collapse-stack ()
+ (let ((last-beg (if simula-assemble (point) (simula-pop)))
+ (pointer simula-stack))
+ (while pointer
+ (if (stringp (car pointer)) (setq pointer (cdr pointer))
+ (if last-beg
+ (progn
+ (setcar pointer (buffer-substring last-beg (car pointer)))
+ (setq last-beg nil pointer (cdr pointer)))
+ (setq last-beg (car pointer))
+ (setcar pointer (car (cdr pointer))) ;delete cons-cell
+ (setcdr pointer (cdr (cdr pointer))))))
+ (setq simula-form (apply 'concat simula-stack)
+ simula-stack (list (point) simula-form))))
+
+(defun get-indent-amount (indent-form-list)
+ (if indent-form-list
+ (if (string-match (car (car indent-form-list)) simula-form)
+ (progn
+ (if simula-debug
+ (with-output-to-temp-buffer "* forms *"
+ (print
+ (concat (car (car indent-form-list))"<---->" simula-form))))
+ (cdr (car indent-form-list)))
+ (get-indent-amount (cdr indent-form-list)))
+ nil))
+
+
+
+;axiom: (bolp) eq t
+(defun current-simula-indentation ()
+ (if (looking-at simula-label) ;skip labels
+ (re-search-forward simula-label)) ;ignore labels
+ (skip-chars-forward " \t") ;skip to first non-blank
+ (current-column)) ;and return with column nubmer
+
+
+(defun simula-indent-calc (amount)
+ (if amount
+ (let ((from (car amount)))
+ (+ (car (cdr amount))
+ (cond
+ ((= 0 from) simula-hpos) ;axiom: exists
+ ((and simula-FB-hpos (= 1 from)) simula-FB-hpos)
+ ((and simula-BB-hpos (= 2 from)) simula-BB-hpos)
+ (simula-hpos))))
+ simula-hpos))
+
+
+(defun simula-indent-line (to)
+ (beginning-of-line)
+ (if (= (following-char) ?\%) ()
+ (let ((space (% to tab-width)) (tabs (/ to tab-width)))
+ (if (looking-at simula-label) ;indent line after label
+ (progn
+ (re-search-forward simula-label) ;ignore labels
+ (if (> (current-column) to)
+ (setq tabs 0 space 1)
+ (insert-char ?\t 1) ;try fill to nearest tab position
+ (if (> (current-column) to) ;else fill blanks.
+ (backward-delete-char 1))
+ (setq to (- to (current-column)))
+ (setq tabs (/ to tab-width) space (% to tab-width)))))
+ (insert-char ?\t tabs) ;insert all the necessary tabs and
+ (insert-char ?\ space) ;spaces to indent line
+ (delete-region
+ (point) (progn (skip-chars-forward " \t" (point-max)) (point))))))
+
+
+(defun simula-abbrev-expand-and-lf (arg)
+ (interactive "p")
+ (expand-abbrev)
+ (insert-char ?\n 1)
+ (forward-char -1)
+ (let ((indent (save-excursion (simula-find-indent t))))
+ (if (progn (beginning-of-line)
+ (skip-chars-forward " \t")
+ (/= (following-char) ?!)) ;Only indent lines not starting with
+ ;a comment or something like it..
+ (simula-indent-line (car indent)))
+ (forward-line 1)
+ (simula-indent-line (simula-indent-calc (car (cdr indent))))))
+
+(defun simula-indent ()
+ (interactive)
+ (simula-indent-line (car (save-excursion (simula-find-indent)))))
+
+(defun Simula-While-Handler ()
+ (Simula-Default-Form-Handler Simula-While-Form))
+
+(defun Simula-If-Handler ()
+ (Simula-Default-Form-Handler Simula-If-Form))
+
+(defun Simula-Inspect-Handler ()
+ (Simula-Default-Form-Handler Simula-Inspect-Form))
+
+(defun Simula-For-Handler ()
+ (Simula-Default-Form-Handler Simula-For-Form))
+
+
+;;;;;; Nice Mode..
+(defun simula-Nice-indent-mode ()
+ (interactive)
+ (setq Simula-While-Form
+ '( ("while.*begin.*end;@" (0 0) (1 0))
+ ("while .*do.*begin\n.*\n.*end;@" (1 0) (0 0))
+ ("while .*do.*begin\n.*@" (1 3) (1 3))
+ ("while .*do.*begin.*@" (0 0) (1 3))
+ ("while .*do\n.*begin\n.*\n.*end;@" (2 0) (0 0))
+ ("while .*do\n.*begin\n.*@" (2 3) (2 3))
+ ("while .*do\n.*begin@" (1 3) (2 3))
+ ("while .*do\n.*;@" (1 3) (0 0))
+ ("while .*do\n.*@" (1 3) (1 3))
+ ("while .*do@" (0 0) (1 3))))
+ (setq Simula-Default-Form
+ '( ("begin.*end;@" (0 0) (0 0))
+ ("while .*do.*begin\n.*\n.*end;@" (0 0) (0 0))
+ ("begin.*@" (0 0) (2 3))
+ ("begin\n.*\n.*end.*@" (0 0) (0 0))
+ ("begin\n.*end;@" (2 3) (0 0))
+ ("begin\n.*\n.*end;@" (2 0) (0 0))
+ ("begin\n.*@" (2 3) (2 3))
+ ("begin\n.*\n@" (2 3) (2 3))
+ ("begin\n*.*\n*.*@" (2 3) (2 3))
+ (".*;@" (0 0) (0 0))
+ ("\n.*;@" (0 0) (0 0))
+ ("\n.*@" (0 0) (0 0))
+ ("." (0 0) (0 3))))
+ (setq Simula-If-Form
+ '( ("if.*begin.*end;@" (0 0) (1 0))
+ ("if .*begin.*@" (0 0) (2 3))
+ ("if .*else@" (0 0) (0 0))
+ ("if .*;@" (0 0) (0 0))
+ ("if .*@" (0 0) (0 3))
+ ("if .*begin.*\n.*@" (2 3) (2 3))
+ ("if .*\n.*;@" (0 3) (0 0))
+ ("if .*\n.*begin.*end.*@" (0 3) (0 0))
+ ("if .*\n.*begin.*@" (0 3) (2 3))
+ ("if .*else\n.*@" (0 3) (0 0))
+ ("if .*\n.*begin.*\n.*@" (2 3) (2 3))
+ ("if .*\n.*begin.*\n.*\n.*end.*@" (2 0) (0 0))
+ ("if .*begin.*\n.*\n.*end;.*@" (0 0) (0 0))
+ ("if .*begin.*\n.*\n.*end@" (2 0) (0 0))
+ ("else if.*@" (0 0) (0 3))
+ ("else@" (0 0) (0 3))
+ ("else.*begin.*@" (0 0) (2 3))
+ ("else.*begin.*\n.*@" (2 3) (2 3))
+ ("else.*begin.*\n.*\n.*end;@" (2 0) (0 0))
+ ("else .*;@" (0 0) (0 0))
+ ("else\n.*begin@" (0 3) (2 3))
+ ("else\n.*begin\n.*@" (2 3) (2 3))
+ ("else\n.*begin\n.*\n.*end.*@" (2 0) (0 0))))
+ (setq Simula-For-Form
+ '( ("for .*begin.*end;@" (0 0) (1 0))
+ ("for .*do.*;@" (0 0) (0 0))
+ ("for .*do@" (0 0) (1 3))
+ ("for .*do\n.*begin@" (1 3) (2 3))
+ ("for .*do\n.*begin\n.*@" (2 3) (2 3))
+ ("for .*do\n.*begin\n.*\n.*end.*@" (1 3) (0 0))
+ ("for .*do\n.*;@" (1 3) (0 0))
+ ("for .*do\n.*begin.*\n.*end.*@" (1 3) (0 0))
+ ("for .*do.*begin@" (0 0) (1 3))
+ ("for .*do.*begin\n.*end.*@" (1 3) (0 0))
+ ("for .*do.*begin\n.*@" (1 3) (1 3))
+ ("for .*do.*begin\n.*\n.*end.*@" (1 0) (0 0))))
+ (setq Simula-Inspect-Form
+ '( ("inspect .*do.*;@" (0 0) (0 0))
+ ("inspect .*do@" (0 0) (1 3))
+ ("inspect .*do\n.*begin.*end.*@" (1 3) (0 0))
+ ("inspect .*do\n.*begin.*@" (1 3) (2 3))
+ ("inspect .*do\n.*begin\n.*end.*@" (2 3) (0 0))
+ ("inspect .*do\n.*begin\n.*\n.*end.*@" (2 0) (0 0))
+ ("inspect .*do.*begin@" (0 0) (2 3))
+ ("inspect .*do.*begin\n.*end.*@" (2 3) (0 0))
+ ("inspect .*do.*begin\n.*@" (2 3) (2 3))
+ ("inspect .*do.*begin\n.*\n.*end.*;@" (2 0) (0 0))
+ ("inspect .*;@" (0 0) (0 0))
+ ("inspect .*@" (0 0) (0 3))
+ ("otherwise@" (0 0) (0 3))
+ ("otherwise\n.*begin@" (0 3) (2 3))
+ ("otherwise\n.*begin\n.*end.*@" (2 3) (0 0))
+ ("otherwise\n.*begin\n.*@" (2 3) (2 3))
+ ("otherwise\n.*begin\n.*\n.*end.*@" (2 0) (0 0))
+ ("otherwise .*begin .*end.*@" (0 0) (0 0))
+ ("otherwise .*begin.*@" (0 0) (2 3))
+ ("otherwise .*begin\n.*end.*@" (2 3) (0 0))
+ ("otherwise .*begin\n.*@" (2 3) (2 3))
+ ("otherwise .*begin\n.*\n.*end.*@" (2 0) (0 0))
+ ("when .*do@" (0 3) (0 6))
+ ("when .*do.*;@" (0 3) (0 0))
+ ("when .*do.*@" (0 3) (0 3))
+ ("when .*do\n.*begin@" (0 6) (2 3))
+ ("when .*do\n.*begin\n.*end;@" (2 3) (0 0))
+ ("when .*do\n.*begin\n.*@" (2 3) (2 3))
+ ("when .*do\n.*begin\n.*\n.*end;@" (2 0) (0 0))
+ ("when .*do\n.*begin\n.*\n.*end@" (2 0) (0 3))
+ ("when .*do\n.*begin .*end;@" (0 6) (0 0))
+ ("when .*do\n.*begin .*end@" (0 6) (0 3)))))
+
+(defun simula-Simed-indent-mode ()
+ ;;Should only indent after begin, so this is a overkill
+ ;;Hopefully, I'll do better when I care for it.
+ (interactive)
+ (setq Simula-While-Form
+ '( ("while .*do.*begin\n.*\nend;@" (1 0) (0 0))
+ ("while .*do.*begin\n.*@" (1 3) (1 3))
+ ("while .*do.*begin.*@" (0 0) (1 3))
+ ("while .*do\n.*begin\n.*\n.*end;@" (1 0) (0 0))
+ ("while .*do\n.*begin\n.*@" (2 3) (2 3))
+ ("while .*do\n.*begin@" (1 0) (1 3))
+ ("while .*do\n.*;@" (1 3) (0 0))
+ ("while .*do\n.*@" (1 3) (1 3))
+ ("while .*do@" (0 0) (1 0))))
+ (setq Simula-Default-Form
+ '( ("begin.*end;@" (0 0) (0 0))
+ ("begin.*@" (0 0) (2 3))
+ ("begin\n.*\nend" (0 0) (0 0))
+ ("begin\n.*end;@" (2 3) (0 0))
+ ("begin\n.*@" (2 3) (2 3))
+ ("begin\n*.*\n*.*@" (2 3) (2 3))
+ (".*;@" (0 0) (0 0))
+ ("\n.*;@" (0 0) (0 0))
+ ("\n.*@" (0 0) (0 0))
+ ("." (0 0) (0 3))))
+ (setq Simula-If-Form
+ '( ("if .*begin.*@" (0 0) (0 3))
+ ("if .*else@" (0 0) (0 0))
+ ("if .*;@" (0 0) (0 0))
+ ("if .*@" (0 0) (0 0))
+ ("if .*begin.*\n.*@" (0 3) (0 3))
+ ("if .*\n.*;@" (0 3) (0 0))
+ ("if .*\n.*begin.*end.*@" (0 0) (0 0))
+ ("if .*\n.*begin.*@" (0 0) (0 3))
+ ("if .*else\n.*@" (0 0) (0 0))
+ ("if .*\n.*begin.*\n.*@" (0 3) (0 3))
+ ("if .*\n.*begin.*\n.*\n.*end.*@" (0 0) (0 0))
+ ("if .*begin.*\n.*\n.*end;.*@" (0 0) (0 0))
+ ("if .*begin.*\n.*\n.*end@" (0 0) (0 0))
+ ("else if.*@" (0 0) (0 0))
+ ("else@" (0 0) (0 0))
+ ("else.*begin.*@" (0 0) (0 3))
+ ("else.*begin.*\n.*@" (0 3) (0 3))
+ ("else.*begin.*\n.*\n.*end;@" (0 0) (0 0))
+ ("else .*;@" (0 0) (0 0))
+ ("else\n.*begin@" (0 0) (0 3))
+ ("else\n.*begin\n.*@" (0 3) (0 3))
+ ("else\n.*begin\n.*\n.*end.*@" (0 0) (0 0))))
+ (setq Simula-For-Form
+ '( ("for .*do.*;@" (0 0) (0 0))
+ ("for .*do@" (0 0) (0 0))
+ ("for .*do\n.*begin@" (0 0) (0 3))
+ ("for .*do\n.*begin\n.*@" (0 3) (0 3))
+ ("for .*do\n.*begin\n.*\n.*end.*@" (0 0) (0 0))
+ ("for .*do\n.*;@" (0 3) (0 0))
+ ("for .*do\n.*begin.*\n.*end.*@" (0 0) (0 0))
+ ("for .*do.*begin@" (0 0) (0 3))
+ ("for .*do.*begin\n.*end.*@" (0 3) (0 0))
+ ("for .*do.*begin\n.*@" (0 3) (0 3))
+ ("for .*do.*begin\n.*\n.*end.*@" (0 0) (0 0))))
+ (setq Simula-Inspect-Form
+ '( ("inspect .*do.*;@" (0 0) (0 0))
+ ("inspect .*do@" (0 0) (0 0))
+ ("inspect .*do\n.*begin.*end.*@" (0 3) (0 0))
+ ("inspect .*do\n.*begin.*@" (0 0) (0 3))
+ ("inspect .*do\n.*begin\n.*end.*@" (0 0) (0 0))
+ ("inspect .*do\n.*begin\n.*\n.*end.*@" (0 0) (0 0))
+ ("inspect .*do.*begin@" (0 0) (0 3))
+ ("inspect .*do.*begin\n.*end.*@" (0 3) (0 0))
+ ("inspect .*do.*begin\n.*@" (0 3) (0 3))
+ ("inspect .*do.*begin\n.*\n.*end.*;@" (0 0) (0 0))
+ ("inspect .*;@" (0 0) (0 0))
+ ("inspect .*@" (0 0) (0 0))
+ ("otherwise@" (0 0) (0 0))
+ ("otherwise\n.*begin@" (0 0) (0 3))
+ ("otherwise\n.*begin\n.*end.*@" (0 3) (0 0))
+ ("otherwise\n.*begin\n.*@" (0 3) (0 3))
+ ("otherwise\n.*begin\n.*\n.*end.*@" (0 0) (0 0))
+ ("otherwise .*begin .*end.*@" (0 0) (0 0))
+ ("otherwise .*begin.*@" (0 0) (0 3))
+ ("otherwise .*begin\n.*end.*@" (0 3) (0 0))
+ ("otherwise .*begin\n.*@" (0 3) (0 3))
+ ("otherwise .*begin\n.*\n.*end.*@" (0 0) (0 0))
+ ("when .*do@" (0 0) (0 0))
+ ("when .*do.*;@" (0 0) (0 0))
+ ("when .*do.*@" (0 0) (0 0))
+ ("when .*do\n.*begin@" (0 0) (0 3))
+ ("when .*do\n.*begin\n.*end;@" (0 3) (0 0))
+ ("when .*do\n.*begin\n.*@" (0 3) (0 3))
+ ("when .*do\n.*begin\n.*\n.*end;@" (0 0) (0 0))
+ ("when .*do\n.*begin\n.*\n.*end@" (0 0) (0 0))
+ ("when .*do\n.*begin .*end;@" (0 3) (0 0))
+ ("when .*do\n.*begin .*end@" (0 3) (0 0)))))
diff --git a/lisp/simula.elc b/lisp/simula.elc
new file mode 100644
index 00000000000..76667f4ba64
--- /dev/null
+++ b/lisp/simula.elc
Binary files differ
diff --git a/lisp/sort.el b/lisp/sort.el
index d494b2e757c..5d185174865 100644
--- a/lisp/sort.el
+++ b/lisp/sort.el
@@ -38,7 +38,6 @@ across a sort record. They will be called many times from within sort-subr.
NEXTRECFUN is called with point at the end of the previous record.
It moves point to the start of the next record.
-It should move point to the end of the buffer if there are no more records.
The first record is assumed to start at the position of point when sort-subr
is called.
@@ -52,12 +51,12 @@ STARTKEYFUN and ENDKEYFUN are called. If STARTKEYFUN is nil, the key
starts at the beginning of the record.
ENDKEYFUN moves from the start of the sort key to the end of the sort key.
-ENDKEYFUN may be nil if STARTKEYFUN returns a value or if it would be the
+ENDRECFUN may be nil if STARTKEYFUN returns a value or if it would be the
same as ENDRECFUN."
(save-excursion
(message "Finding sort keys...")
(let* ((sort-lists (sort-build-lists nextrecfun endrecfun
- startkeyfun endkeyfun))
+ startkeyfun endkeyfun))
(old (reverse sort-lists)))
(if (null sort-lists)
()
@@ -67,7 +66,6 @@ same as ENDRECFUN."
(if (fboundp 'sortcar)
(sortcar sort-lists
(cond ((numberp (car (car sort-lists)))
- ;; This handles both ints and floats.
'<)
((consp (car (car sort-lists)))
'buffer-substring-lessp)
@@ -89,11 +87,10 @@ same as ENDRECFUN."
(if reverse (setq sort-lists (nreverse sort-lists)))
(message "Reordering buffer...")
(sort-reorder-buffer sort-lists old)))
- (message "Reordering buffer... Done"))
- nil)
+ (message "Reordering buffer... Done")))
;; Parse buffer into records using the arguments as Lisp expressions;
-;; return a list of records. Each record looks like (KEY STARTPOS . ENDPOS)
+;; return a list of records. Each record looks like (KEY STARTPOS ENDPOS)
;; where KEY is the sort key (a number or string),
;; and STARTPOS and ENDPOS are the bounds of this record in the buffer.
@@ -131,8 +128,8 @@ same as ENDRECFUN."
(equal (car key) start-rec)
(equal (cdr key) (point)))
(cons key key)
- (cons key (cons start-rec (point))))
- sort-lists)))
+ (list key start-rec (point)))
+ sort-lists)))
(and (not done) nextrecfun (funcall nextrecfun)))
sort-lists))
@@ -140,12 +137,6 @@ same as ENDRECFUN."
(let ((inhibit-quit t)
(last (point-min))
(min (point-min)) (max (point-max)))
- ;; Make sure insertions done for reordering
- ;; do not go after any markers at the end of the sorted region,
- ;; by inserting a space to separate them.
- (goto-char (point-max))
- (insert-before-markers " ")
- (narrow-to-region min (1- (point-max)))
(while sort-lists
(goto-char (point-max))
(insert-buffer-substring (current-buffer)
@@ -154,57 +145,49 @@ same as ENDRECFUN."
(goto-char (point-max))
(insert-buffer-substring (current-buffer)
(nth 1 (car sort-lists))
- (cdr (cdr (car sort-lists))))
- (setq last (cdr (cdr (car old)))
+ (nth 2 (car sort-lists)))
+ (setq last (nth 2 (car old))
sort-lists (cdr sort-lists)
old (cdr old)))
(goto-char (point-max))
(insert-buffer-substring (current-buffer)
last
max)
- ;; Delete the original copy of the text.
- (delete-region min max)
- ;; Get rid of the separator " ".
- (goto-char (point-max))
- (narrow-to-region min (1+ (point)))
- (delete-region (point) (1+ (point)))))
+ (delete-region min max))) ;get rid of old version
(defun sort-lines (reverse beg end)
"Sort lines in region alphabetically; argument means descending order.
Called from a program, there are three arguments:
REVERSE (non-nil means reverse order), BEG and END (region to sort)."
(interactive "P\nr")
- (save-excursion
- (save-restriction
- (narrow-to-region beg end)
- (goto-char (point-min))
- (sort-subr reverse 'forward-line 'end-of-line))))
+ (save-restriction
+ (narrow-to-region beg end)
+ (goto-char (point-min))
+ (sort-subr reverse 'forward-line 'end-of-line)))
(defun sort-paragraphs (reverse beg end)
"Sort paragraphs in region alphabetically; argument means descending order.
Called from a program, there are three arguments:
REVERSE (non-nil means reverse order), BEG and END (region to sort)."
(interactive "P\nr")
- (save-excursion
- (save-restriction
- (narrow-to-region beg end)
- (goto-char (point-min))
- (sort-subr reverse
- (function (lambda () (skip-chars-forward "\n \t\f")))
- 'forward-paragraph))))
+ (save-restriction
+ (narrow-to-region beg end)
+ (goto-char (point-min))
+ (sort-subr reverse
+ (function (lambda () (skip-chars-forward "\n \t\f")))
+ 'forward-paragraph)))
(defun sort-pages (reverse beg end)
"Sort pages in region alphabetically; argument means descending order.
Called from a program, there are three arguments:
REVERSE (non-nil means reverse order), BEG and END (region to sort)."
(interactive "P\nr")
- (save-excursion
- (save-restriction
- (narrow-to-region beg end)
- (goto-char (point-min))
- (sort-subr reverse
- (function (lambda () (skip-chars-forward "\n")))
- 'forward-page))))
+ (save-restriction
+ (narrow-to-region beg end)
+ (goto-char (point-min))
+ (sort-subr reverse
+ (function (lambda () (skip-chars-forward "\n")))
+ 'forward-page)))
(defvar sort-fields-syntax-table nil)
(if sort-fields-syntax-table nil
@@ -216,14 +199,13 @@ REVERSE (non-nil means reverse order), BEG and END (region to sort)."
(modify-syntax-entry ?\ " " table)
(modify-syntax-entry ?\t " " table)
(modify-syntax-entry ?\n " " table)
- (modify-syntax-entry ?\. "_" table) ; for floating pt. numbers. -wsr
(setq sort-fields-syntax-table table)))
(defun sort-numeric-fields (field beg end)
"Sort lines in region numerically by the ARGth field of each line.
Fields are separated by whitespace and numbered from 1 up.
Specified field must contain a number in each line of the region.
-With a negative arg, sorts by the ARGth field counted from the right.
+With a negative arg, sorts by the -ARG'th field, in reverse order.
Called from a program, there are three arguments:
FIELD, BEG and END. BEG and END specify region to sort."
(interactive "p\nr")
@@ -234,36 +216,14 @@ FIELD, BEG and END. BEG and END specify region to sort."
(buffer-substring
(point)
(save-excursion
- ;; This is just wrong! Even without floats...
- ;; (skip-chars-forward "[0-9]")
- (forward-sexp 1)
+ (skip-chars-forward "-0-9")
(point))))))
nil))
-(defun sort-float-fields (field beg end)
- "Sort lines in region numerically by the ARGth field of each line.
-Fields are separated by whitespace and numbered from 1 up. Specified field
-must contain a floating point number in each line of the region. With a
-negative arg, sorts by the ARGth field counted from the right. Called from a
-program, there are three arguments: FIELD, BEG and END. BEG and END specify
-region to sort."
- (interactive "p\nr")
- (sort-fields-1 field beg end
- (function (lambda ()
- (sort-skip-fields (1- field))
- (string-to-float
- (buffer-substring
- (point)
- (save-excursion
- (re-search-forward
- "[+-]?[0-9]*\.?[0-9]*\\([eE][+-]?[0-9]+\\)?")
- (point))))))
- nil))
-
(defun sort-fields (field beg end)
"Sort lines in region lexicographically by the ARGth field of each line.
Fields are separated by whitespace and numbered from 1 up.
-With a negative arg, sorts by the ARGth field counted from the right.
+With a negative arg, sorts by the -ARG'th field, in reverse order.
Called from a program, there are three arguments:
FIELD, BEG and END. BEG and END specify region to sort."
(interactive "p\nr")
@@ -274,32 +234,27 @@ FIELD, BEG and END. BEG and END specify region to sort."
(function (lambda () (skip-chars-forward "^ \t\n")))))
(defun sort-fields-1 (field beg end startkeyfun endkeyfun)
- (let ((tbl (syntax-table)))
- (if (zerop field) (setq field 1))
+ (let ((reverse (< field 0))
+ (tbl (syntax-table)))
+ (setq field (max 1 field (- field)))
(unwind-protect
- (save-excursion
- (save-restriction
- (narrow-to-region beg end)
- (goto-char (point-min))
- (set-syntax-table sort-fields-syntax-table)
- (sort-subr nil
- 'forward-line 'end-of-line
- startkeyfun endkeyfun)))
+ (save-restriction
+ (narrow-to-region beg end)
+ (goto-char (point-min))
+ (set-syntax-table sort-fields-syntax-table)
+ (sort-subr reverse
+ 'forward-line 'end-of-line
+ startkeyfun endkeyfun))
(set-syntax-table tbl))))
(defun sort-skip-fields (n)
- (let ((bol (point))
- (eol (save-excursion (end-of-line 1) (point))))
- (if (> n 0) (forward-word n)
- (end-of-line)
- (forward-word (1+ n)))
- (if (or (and (>= (point) eol) (> n 0))
- ;; this is marginally wrong; if the first line of the sort
- ;; at bob has the wrong number of fields the error won't be
- ;; reported until the next short line.
- (and (< (point) bol) (< n 0)))
+ (let ((eol (save-excursion (end-of-line 1) (point))))
+ (forward-word n)
+ (if (> (point) eol)
(error "Line has too few fields: %s"
- (buffer-substring bol eol)))
+ (buffer-substring (save-excursion
+ (beginning-of-line) (point))
+ eol)))
(skip-chars-forward " \t")))
@@ -319,51 +274,45 @@ With a negative prefix arg sorts in reverse order.
For example: to sort lines in the region by the first word on each line
starting with the letter \"f\",
- RECORD-REGEXP would be \"^.*$\" and KEY would be \"\\=\\<f\\w*\\>\""
- ;; using negative prefix arg to mean "reverse" is now inconsistent with
- ;; other sort-.*fields functions but then again this was before, since it
- ;; didn't use the magnitude of the arg to specify anything.
+ RECORD-REGEXP would be \"^.*$\" and KEY \"\\<f\\w*\\>\""
(interactive "P\nsRegexp specifying records to sort:
sRegexp specifying key within record: \nr")
(cond ((or (equal key-regexp "") (equal key-regexp "\\&"))
(setq key-regexp 0))
((string-match "\\`\\\\[1-9]\\'" key-regexp)
(setq key-regexp (- (aref key-regexp 1) ?0))))
- (save-excursion
- (save-restriction
- (narrow-to-region beg end)
- (goto-char (point-min))
- (let (sort-regexp-record-end) ;isn't dynamic scoping wonderful?
- (re-search-forward record-regexp)
- (setq sort-regexp-record-end (point))
- (goto-char (match-beginning 0))
- (sort-subr reverse
- (function (lambda ()
- (and (re-search-forward record-regexp nil 'move)
- (setq sort-regexp-record-end (match-end 0))
- (goto-char (match-beginning 0)))))
- (function (lambda ()
- (goto-char sort-regexp-record-end)))
- (function (lambda ()
- (let ((n 0))
- (cond ((numberp key-regexp)
- (setq n key-regexp))
- ((re-search-forward
- key-regexp sort-regexp-record-end t)
- (setq n 0))
- (t (throw 'key nil)))
- (condition-case ()
- (if (fboundp 'buffer-substring-lessp)
- (cons (match-beginning n)
- (match-end n))
- (buffer-substring (match-beginning n)
- (match-end n)))
- ;; if there was no such register
- (error (throw 'key nil)))))))))))
+ (save-restriction
+ (narrow-to-region beg end)
+ (goto-char (point-min))
+ (let (sort-regexp-record-end) ;isn't dynamic scoping wonderful?
+ (re-search-forward record-regexp)
+ (setq sort-regexp-record-end (point))
+ (goto-char (match-beginning 0))
+ (sort-subr reverse
+ (function (lambda ()
+ (and (re-search-forward record-regexp nil 'move)
+ (setq sort-regexp-record-end (match-end 0))
+ (goto-char (match-beginning 0)))))
+ (function (lambda ()
+ (goto-char sort-regexp-record-end)))
+ (function (lambda ()
+ (let ((n 0))
+ (cond ((numberp key-regexp)
+ (setq n key-regexp))
+ ((re-search-forward
+ key-regexp sort-regexp-record-end t)
+ (setq n 0))
+ (t (throw 'key nil)))
+ (condition-case ()
+ (if (fboundp 'buffer-substring-lessp)
+ (cons (match-beginning n)
+ (match-end n))
+ (buffer-substring (match-beginning n)
+ (match-end n)))
+ ;; if there was no such register
+ (error (throw 'key nil))))))))))
-(defvar sort-columns-subprocess t)
-
(defun sort-columns (reverse &optional beg end)
"Sort lines in region alphabetically by a certain range of columns.
For the purpose of this command, the region includes
@@ -371,11 +320,9 @@ the entire line that point is in and the entire line the mark is in.
The column positions of point and mark bound the range of columns to sort on.
A prefix argument means sort into reverse order.
-Note that `sort-columns' rejects text that contains tabs,
-because tabs could be split across the specified columns
-and it doesn't know how to handle that. Also, when possible,
-it uses the `sort' utility program, which doesn't understand tabs.
-Use \\[untabify] to convert tabs to spaces before sorting."
+Note that sort-columns uses the sort utility program and therefore
+cannot work on text containing TAB characters. Use M-x untabify
+to convert tabs to spaces before sorting."
(interactive "P\nr")
(save-excursion
(let (beg1 end1 col-beg1 col-end1 col-start col-end)
@@ -391,48 +338,7 @@ Use \\[untabify] to convert tabs to spaces before sorting."
(setq col-end (max col-beg1 col-end1))
(if (search-backward "\t" beg1 t)
(error "sort-columns does not work with tabs. Use M-x untabify."))
- (if (not (eq system-type 'vax-vms))
- ;; Use the sort utility if we can; it is 4 times as fast.
- (call-process-region beg1 end1 "sort" t t nil
- (if reverse "-rt\n" "-t\n")
- (concat "+0." col-start)
- (concat "-0." col-end))
- ;; On VMS, use Emacs's own facilities.
- (save-excursion
- (save-restriction
- (narrow-to-region beg1 end1)
- (goto-char beg1)
- (sort-subr reverse 'forward-line 'end-of-line
- (function (lambda () (move-to-column col-start) nil))
- (function (lambda () (move-to-column col-end) nil)))))))))
-
-(defun reverse-region (beg end)
- "Reverse the order of lines in a region.
-From a program takes two point or marker arguments, BEG and END."
- (interactive "r")
- (if (> beg end)
- (let (mid) (setq mid end end beg beg mid)))
- (save-excursion
- ;; put beg at the start of a line and end and the end of one --
- ;; the largest possible region which fits this criteria
- (goto-char beg)
- (or (bolp) (forward-line 1))
- (setq beg (point))
- (goto-char end)
- ;; the test for bolp is for those times when end is on an empty line;
- ;; it is probably not the case that the line should be included in the
- ;; reversal; it isn't difficult to add it afterward.
- (or (and (eolp) (not (bolp))) (progn (forward-line -1) (end-of-line)))
- (setq end (point-marker))
- ;; the real work. this thing cranks through memory on large regions.
- (let (ll (do t))
- (while do
- (goto-char beg)
- (setq ll (cons (buffer-substring (point) (progn (end-of-line) (point)))
- ll))
- (setq do (/= (point) end))
- (delete-region beg (if do (1+ (point)) (point))))
- (while (cdr ll)
- (insert (car ll) "\n")
- (setq ll (cdr ll)))
- (insert (car ll)))))
+ (call-process-region beg1 end1 "sort" t t nil
+ (if reverse "-rt\n" "-t\n")
+ (concat "+0." col-start)
+ (concat "-0." col-end)))))
diff --git a/lisp/sort.elc b/lisp/sort.elc
new file mode 100644
index 00000000000..3d6931a789d
--- /dev/null
+++ b/lisp/sort.elc
Binary files differ
diff --git a/lisp/textmodes/spell.el b/lisp/spell.el
index d7cd286141b..d7cd286141b 100644
--- a/lisp/textmodes/spell.el
+++ b/lisp/spell.el
diff --git a/lisp/spell.elc b/lisp/spell.elc
new file mode 100644
index 00000000000..62b08e9e2db
--- /dev/null
+++ b/lisp/spell.elc
Binary files differ
diff --git a/lisp/play/spook.el b/lisp/spook.el
index 84fffceeaa1..ed4e16a95ed 100644
--- a/lisp/play/spook.el
+++ b/lisp/spook.el
@@ -1,5 +1,5 @@
;; Spook phrase utility
-;; Copyright (C) 1988 Free Software Foundation, Inc.
+;; Copyright (C) 1988 Free Software Foundation
;; This file is part of GNU Emacs.
diff --git a/lisp/startup.el b/lisp/startup.el
new file mode 100644
index 00000000000..ae709d2f000
--- /dev/null
+++ b/lisp/startup.el
@@ -0,0 +1,238 @@
+;; Process Emacs shell arguments
+;; Copyright (C) 1985, 1986 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 1, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+; These are processed only at the beginning of the argument list.
+; -batch execute noninteractively (messages go to stdout,
+; variable noninteractive set to t)
+; This option must be the first in the arglist.
+; Processed by `main' in emacs.c -- never seen by lisp
+; -t file Specify to use file rather than stdin/stdout
+; as the terminal.
+; This option must be the first in the arglist.
+; Processed by `main' in emacs.c -- never seen by lisp
+; -nw Inhibit the use of any window-system-specific display
+; code; use the current virtual terminal.
+; This option must be the first in the arglist.
+; Processed by `main' in emacs.c -- never seen by lisp
+; -q load no init file
+; -no-init-file same
+; -u user load user's init file
+; -user user same
+
+; These are processed in the order encountered.
+; -f function execute function
+; -funcall function same
+; -l file load file
+; -load file same
+; -i file insert file into buffer
+; -insert file same
+; file visit file
+; -kill kill (exit) emacs
+
+(setq top-level '(normal-top-level))
+
+(defvar command-line-processed nil "t once command line has been processed")
+
+(defconst inhibit-startup-message nil
+ "*Non-nil inhibits the initial startup messages.
+This is for use in your personal init file, once you are familiar
+with the contents of the startup message.")
+
+(defconst inhibit-default-init nil
+ "*Non-nil inhibits loading the `default' library.")
+
+(defconst command-switch-alist nil
+ "Alist of command-line switches.
+Elements look like (SWITCH-STRING . HANDLER-FUNCTION).
+HANDLER-FUNCTION receives switch name as sole arg;
+remaining command-line args are in the variable `command-line-args-left'.")
+
+(defvar term-setup-hook nil
+ "Function to be called after loading terminal-specific lisp code.
+It is called with no arguments. You can use this to override the
+definitions made by the terminal-specific file.")
+
+(defvar window-setup-hook nil)
+
+(defconst initial-major-mode 'lisp-interaction-mode
+ "Major mode command symbol to use for the initial *scratch* buffer.")
+
+(defun normal-top-level ()
+ (if command-line-processed
+ (message "Back to top level.")
+ (setq command-line-processed t)
+ ;; In presence of symlinks, switch to cleaner form of default directory.
+ (if (and (not (eq system-type 'vax-vms))
+ (getenv "PWD")
+ (equal (nthcdr 10 (file-attributes default-directory))
+ (nthcdr 10 (file-attributes (getenv "PWD")))))
+ (setq default-directory (file-name-as-directory (getenv "PWD"))))
+ (unwind-protect
+ (command-line)
+ (and term-setup-hook
+ (funcall term-setup-hook))
+ (and window-setup-hook
+ (funcall window-setup-hook)))))
+
+(defun command-line ()
+ (let ((args (cdr command-line-args))
+ (init (if noninteractive nil (user-login-name)))
+ (done nil))
+ ;; If user has not done su, use current $HOME to find .emacs.
+ (and init (string= init (user-real-login-name))
+ (setq init ""))
+ (while (and (not done) args)
+ (let ((argi (car args)))
+ (if (or (string-equal argi "-q")
+ (string-equal argi "-no-init-file"))
+ (setq init nil
+ args (cdr args))
+ (if (or (string-equal argi "-u")
+ (string-equal argi "-user"))
+ (setq args (cdr args)
+ init (car args)
+ args (cdr args))
+ (setq done t)))))
+ ;; Load user's init file, or load default one.
+ (condition-case error
+ (if init
+ (progn (load (if (eq system-type 'vax-vms)
+ "sys$login:.emacs"
+ (concat "~" init "/.emacs"))
+ t t t)
+ (or inhibit-default-init
+ (let ((inhibit-startup-message nil))
+ ;; Users are supposed to be told their rights.
+ ;; (Plus how to get help and how to undo.)
+ ;; Don't you dare turn this off for anyone
+ ;; except yourself.
+ (load "default" t t)))))
+ (error (message "Error in init file")))
+ (if (get-buffer "*scratch*")
+ (save-excursion
+ (set-buffer "*scratch*")
+ (funcall initial-major-mode)))
+ ;; Load library for our terminal type.
+ ;; User init file can set term-file-prefix to nil to prevent this.
+ (and term-file-prefix (not noninteractive)
+ (if window-system
+ (load (concat term-file-prefix
+ (symbol-name window-system)
+ "-win")
+ t t)
+ (let ((term (getenv "TERM"))
+ hyphend)
+ (while (and term
+ (not (load (concat term-file-prefix term) t t)))
+ ;; Strip off last hyphen and what follows, then try again
+ (if (setq hyphend (string-match "[-_][^-_]+$" term))
+ (setq term (substring term 0 hyphend))
+ (setq term nil))))))
+ (command-line-1 args)
+ (if noninteractive (kill-emacs t))))
+
+(defun command-line-1 (command-line-args-left)
+ (if (null command-line-args-left)
+ (cond ((and (not inhibit-startup-message) (not noninteractive)
+ ;; Don't clobber a non-scratch buffer if init file
+ ;; has selected it.
+ (string= (buffer-name) "*scratch*")
+ (not (input-pending-p)))
+ ;; If there are no switches to procss, we might as well
+ ;; run this hook now, and there may be some need to do it
+ ;; before doing any output.
+ (and term-setup-hook
+ (funcall term-setup-hook))
+ ;; Don't let the hook be run twice.
+ (setq term-setup-hook nil)
+ (and window-setup-hook
+ (funcall window-setup-hook))
+ (setq window-setup-hook nil)
+ (unwind-protect
+ (progn
+ (insert (emacs-version)
+ "
+Copyright (C) 1990 Free Software Foundation, Inc.\n")
+ ;; If keys have their default meanings,
+ ;; use precomputed string to save lots of time.
+ (if (and (eq (key-binding "\C-h") 'help-command)
+ (eq (key-binding "\C-xu") 'advertised-undo)
+ (eq (key-binding "\C-h\C-c") 'describe-copying)
+ (eq (key-binding "\C-h\C-d") 'describe-distribution)
+ (eq (key-binding "\C-h\C-w") 'describe-no-warranty)
+ (eq (key-binding "\C-ht") 'help-with-tutorial))
+ (insert
+ "Type C-h for help; C-x u to undo changes. (`C-' means use CTRL key.)
+
+GNU Emacs comes with ABSOLUTELY NO WARRANTY; type C-h C-w for full details.
+You may give out copies of Emacs; type C-h C-c to see the conditions.
+Type C-h C-d for information on getting the latest version.
+Type C-h t for a tutorial on using Emacs.")
+ (insert (substitute-command-keys
+ "Type \\[help-command] for help; \\[advertised-undo] to undo changes. (`C-' means use CTRL key.)
+
+GNU Emacs comes with ABSOLUTELY NO WARRANTY; type \\[describe-no-warranty] for full details.
+You may give out copies of Emacs; type \\[describe-copying] to see the conditions.
+Type \\[describe-distribution] for information on getting the latest version.
+Type \\[help-with-tutorial] for a tutorial on using Emacs.")))
+ (set-buffer-modified-p nil)
+ (sit-for 120))
+ (save-excursion
+ ;; In case the Emacs server has already selected
+ ;; another buffer, erase the one our message is in.
+ (set-buffer (get-buffer "*scratch*"))
+ (erase-buffer)
+ (set-buffer-modified-p nil)))))
+ (let ((dir default-directory)
+ (line 0))
+ (while command-line-args-left
+ (let ((argi (car command-line-args-left))
+ tem)
+ (setq command-line-args-left (cdr command-line-args-left))
+ (cond ((setq tem (assoc argi command-switch-alist))
+ (funcall (cdr tem) argi))
+ ((or (string-equal argi "-f") ;what the manual claims
+ (string-equal argi "-funcall")
+ (string-equal argi "-e")) ; what the source used to say
+ (setq tem (intern (car command-line-args-left)))
+ (setq command-line-args-left (cdr command-line-args-left))
+ (funcall tem))
+ ((or (string-equal argi "-l")
+ (string-equal argi "-load"))
+ (let ((file (car command-line-args-left)))
+ ;; Take file from default dir if it exists there;
+ ;; otherwise let `load' search for it.
+ (if (file-exists-p (expand-file-name file))
+ (setq file (expand-file-name file)))
+ (load file nil t))
+ (setq command-line-args-left (cdr command-line-args-left)))
+ ((or (string-equal argi "-i")
+ (string-equal argi "-insert"))
+ (insert-file-contents (car command-line-args-left))
+ (setq command-line-args-left (cdr command-line-args-left)))
+ ((string-equal argi "-kill")
+ (kill-emacs t))
+ ((string-match "^\\+[0-9]+\\'" argi)
+ (setq line (string-to-int argi)))
+ (t
+ (find-file (expand-file-name argi dir))
+ (or (zerop line)
+ (goto-line line))
+ (setq line 0))))))))
diff --git a/lisp/startup.elc b/lisp/startup.elc
new file mode 100644
index 00000000000..37f1871b2a9
--- /dev/null
+++ b/lisp/startup.elc
Binary files differ
diff --git a/lisp/play/studly.el b/lisp/studly.el
index 5661b04a3cb..5661b04a3cb 100644
--- a/lisp/play/studly.el
+++ b/lisp/studly.el
diff --git a/lisp/studly.elc b/lisp/studly.elc
new file mode 100644
index 00000000000..309b31a8253
--- /dev/null
+++ b/lisp/studly.elc
Binary files differ
diff --git a/lisp/subr.el b/lisp/subr.el
index ffb4cb58184..cd5dc88dd28 100644
--- a/lisp/subr.el
+++ b/lisp/subr.el
@@ -1,5 +1,5 @@
;; Basic lisp subroutines for Emacs
-;; Copyright (C) 1985, 1986 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 1986, 1990 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -18,28 +18,15 @@
;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-(defun one-window-p (&optional arg)
+(defun one-window-p (&optional nomini)
"Returns non-nil if there is only one window.
Optional arg NOMINI non-nil means don't count the minibuffer
even if it is active."
- (eq (selected-window)
- (next-window (selected-window) (if arg 'arg))))
-
-(defun walk-windows (proc &optional minibuf all-screens)
- "Cycle through all visible windows, calling PROC for each one.
-PROC is called with a window as argument.
-Optional second arg MINIBUF t means count the minibuffer window
-even if not active. If MINIBUF is neither t nor nil it means
-not to count the minibuffer even if it is active.
-Optional third arg ALL-SCREENS t means include all windows in all screens;
-otherwise cycle within the selected screen."
- (let* ((walk-windows-start (selected-window))
- (walk-windows-current walk-windows-start))
- (while (progn
- (setq walk-windows-current
- (next-window walk-windows-current minibuf all-screens))
- (funcall proc walk-windows-current)
- (not (eq walk-windows-current walk-windows-start))))))
+ (let ((base-window (selected-window)))
+ (if (and nomini (eq base-window (minibuffer-window)))
+ (setq base-window (next-window base-window)))
+ (eq base-window
+ (next-window base-window (if nomini 'arg)))))
(defun read-quoted-char (&optional prompt)
"Like `read-char', except that if the first character read is an octal
@@ -77,22 +64,22 @@ Optional argument PROMPT specifies a string to use to prompt the user."
;from mentioning keys that run this command.
(put 'undefined 'suppress-keymap t)
-(defun suppress-keymap (map &optional nodigits)
- "Make MAP override all normally self-inserting keys to be undefined.
-Normally, as an exception, digits and minus-sign are set to make prefix args,
-but optional second arg NODIGITS non-nil treats them like other chars."
- (let ((i 0))
- (while (<= i 127)
- (if (eql (lookup-key global-map (char-to-string i)) 'self-insert-command)
- (define-key map (char-to-string i) 'undefined))
+(defun suppress-keymap (map &optional arg)
+ "Make MAP override all buffer-modifying commands to be undefined.
+Works by knowing which commands are normally buffer-modifying.
+Normally also makes digits set numeric arg,
+but optional second arg NODIGITS non-nil prevents this."
+ (let ((i ? ))
+ (while (< i 127)
+ (aset map i 'undefined)
(setq i (1+ i))))
- (or nodigits
+ (or arg
(let (loop)
- (define-key map "-" 'negative-argument)
+ (aset map ?- 'negative-argument)
;; Make plain numbers do numeric args.
(setq loop ?0)
(while (<= loop ?9)
- (define-key map (char-to-string loop) 'digit-argument)
+ (aset map loop 'digit-argument)
(setq loop (1+ loop))))))
;; now in fns.c
@@ -126,9 +113,7 @@ but optional second arg NODIGITS non-nil treats them like other chars."
(defun substitute-key-definition (olddef newdef keymap)
"Replace OLDDEF with NEWDEF for any keys in KEYMAP now defined as OLDDEF.
-In other words, OLDDEF is replaced with NEWDEF where ever it appears.
-Prefix keymaps reached from KEYMAP are not checked recursively;
-perhaps they ought to be."
+In other words, OLDDEF is replaced with NEWDEF where ever it appears."
(if (arrayp keymap)
(let ((len (length keymap))
(i 0))
@@ -160,11 +145,11 @@ perhaps they ought to be."
(fset 'send-string 'process-send-string)
(fset 'send-region 'process-send-region)
(fset 'show-buffer 'set-window-buffer)
-(fset 'buffer-flush-undo 'buffer-disable-undo)
; alternate names
(fset 'string= 'string-equal)
(fset 'string< 'string-lessp)
+(fset 'mod '%)
(fset 'move-marker 'set-marker)
(fset 'eql 'eq)
(fset 'not 'null)
@@ -208,25 +193,6 @@ If it is a list, the elements are called, in order, with no arguments."
(mapcar 'funcall value)
(funcall value)))))
(setq hooklist (cdr hooklist))))
-
-;; Tell C code how to call this function.
-(defconst run-hooks 'run-hooks
- "Variable by which C primitives find the function `run-hooks'.
-Don't change it.")
-
-(defun add-hook (hook function)
- "Add to the value of HOOK the function FUNCTION unless already present.
-HOOK should be a symbol, and FUNCTION may be any valid function.
-HOOK's value should be a list of functions, not a single function.
-If HOOK is void, it is first set to nil."
- (or (boundp hook) (set hook nil))
- (or (if (consp function)
- ;; Clever way to tell whether a given lambda-expression
- ;; is equal to anything in the hook.
- (let ((tail (assoc (cdr function) (symbol-value hook))))
- (equal function tail))
- (memq function (symbol-value hook)))
- (set hook (cons function hook))))
(defun momentary-string-display (string pos &optional exit-char message)
"Momentarily display STRING in the buffer at POS.
@@ -258,70 +224,18 @@ If MESSAGE is nil, instructions to type EXIT-CHAR are displayed there."
(delete-region pos insert-end)))
(setq buffer-file-name name)
(set-buffer-modified-p modified))))
-
-(defun start-process-shell-command (name buffer &rest args)
- "Start a program in a subprocess. Return the process object for it.
-Args are NAME BUFFER COMMAND &rest COMMAND-ARGS.
-NAME is name for process. It is modified if necessary to make it unique.
-BUFFER is the buffer or (buffer-name) to associate with the process.
- 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.
-Remaining arguments are the arguments for the command.
-Wildcards and redirection are handle as usual in the shell."
- (if (eq system-type 'vax-vms)
- (apply 'start-process name buffer args)
- (start-process name buffer shell-file-name "-c"
- (concat "exec " (mapconcat 'identity args " ")))))
-
-(defun eval-after-load (file form)
- "Arrange that, if FILE is ever loaded, FORM will be run at that time.
-This makes or adds to an entry on `after-load-alist'.
-FILE should be the name of a library, with no directory name."
- (or (assoc file after-load-alist)
- (setq after-load-alist (cons (list file) after-load-alist)))
- (nconc (assoc file after-load-alist) (list form))
- form)
-
-(defun eval-next-after-load (file)
- "Read the following input sexp, and run it whenever FILE is loaded.
-This makes or adds to an entry on `after-load-alist'.
-FILE should be the name of a library, with no directory name."
- (eval-after-load file (read)))
-
-(defmacro defun-inline (name args &rest body)
- "Create an \"inline defun\" (actually a macro).
-Use just like `defun'."
- (nconc (list 'defmacro name '(&rest args))
- (if (stringp (car body))
- (prog1 (list (car body))
- (setq body (or (cdr body) body))))
- (list (list 'cons (list 'quote
- (cons 'lambda (cons args body)))
- 'args))))
-
-(defun user-original-login-name ()
- "Return user's login name from original login.
-This tries to remain unaffected by `su', by looking in environment variables."
- (or (getenv "LOGNAME") (getenv "USER") (user-login-name)))
-(defun force-mode-line-update (&optional all)
- "Force the mode-line of the current buffer to be redisplayed.
-With optional non-nil ALL then force then force redisplay of all mode-lines."
- (if all (save-excursion (set-buffer (other-buffer))))
- (set-buffer-modified-p (buffer-modified-p)))
-
-(defun keyboard-translate (from to)
- "Translate character FROM to TO at a low level.
-This function creates a `keyboard-translate-table' if necessary
-and then modifies one entry in it."
- (or (boundp 'keyboard-translate-table)
- (let ((table (make-string 256))
- (i 0))
- (while (< i 256)
- (aset table i i)
- (setq i (1+ i)))
- (setq keyboard-translate-table table)))
- (aset keyboard-translate-table from to))
+(defun undo-start ()
+ "Move undo-pointer to front of undo records.
+The next call to undo-more will undo the most recently made change."
+ (if (eq buffer-undo-list t)
+ (error "No undo information in this buffer"))
+ (setq pending-undo-list buffer-undo-list))
+
+(defun undo-more (count)
+ "Undo back N undo-boundaries beyond what was already undone recently.
+Call undo-start to get ready to undo recent changes,
+then call undo-more one or more times to undo them."
+ (or pending-undo-list
+ (error "No further undo information"))
+ (setq pending-undo-list (primitive-undo count pending-undo-list)))
diff --git a/lisp/subr.elc b/lisp/subr.elc
new file mode 100644
index 00000000000..45c5fd62145
--- /dev/null
+++ b/lisp/subr.elc
Binary files differ
diff --git a/lisp/sun-curs.el b/lisp/sun-cursors.el
index f290e1b3a76..2a6ca08f2b3 100644
--- a/lisp/sun-curs.el
+++ b/lisp/sun-cursors.el
@@ -174,7 +174,7 @@ Otherwise, ICON should be a vector or the name of a vector of [x y 32-chars]"
(while (> bit 0)
(insert (sc::char-at-bit char bit))
(setq bit (lsh bit -1))))
- (if (eq 1 (% index 2)) (newline))
+ (if (eq 1 (mod index 2)) (newline))
(setq index (1+ index))))
(sc::goto-hotspot))
diff --git a/lisp/sun-fns.el b/lisp/sun-fns.el
index b2ca59203f6..2c12fbc12ba 100644
--- a/lisp/sun-fns.el
+++ b/lisp/sun-fns.el
@@ -1,5 +1,5 @@
;; Subroutines of Mouse handling for Sun windows
-;; Copyright (C) 1987 Free Software Foundation, Inc.
+;; Copyright (C) 1987, 1991, 1992 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -17,6 +17,15 @@
;; along with GNU Emacs; see the file COPYING. If not, write to
;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+;;; Upgrade Apr, 1992, Jeff Peck
+;;; modeline-menu
+;;; modeline resize
+;;; mouse-fill-paragraph(s)
+;;; mouse in Buffer-menu
+;;;
+;;; Fix Aug, 1989, Jeff Peck
+;;; minibuf-prompt-length
+;;;
;;; Submitted Mar. 1987, Jeff Peck
;;; Sun Microsystems Inc. <peck@sun.com>
;;; Conceived Nov. 1986, Stan Jefferson,
@@ -420,13 +429,88 @@ relative X divided by window width."
"Pop-up menu of commands."
(sun-menu-evaluate window x (1- y) 'minibuffer-menu))
+;;; Thanks to Joe Wells for this hack.
+;;; GNU Emacs should supply something better... Oh well.
+(defun minibuf-prompt-length ()
+ "Returns the length of the current minibuffer prompt."
+ (save-window-excursion
+ (select-window (minibuffer-window))
+ (save-excursion
+ (let ((screen-width (screen-width))
+ (point-min (point-min))
+ length)
+ (goto-char point-min)
+ (insert-char ?a screen-width)
+ (goto-char point-min)
+ (vertical-motion 1)
+ (setq length (- screen-width (point)))
+ (goto-char point-min)
+ (delete-char screen-width)
+ length))))
+
(defun mini-move-point (window x y)
- ;; -6 is good for most common cases
- (mouse-move-point window (- x 6) 0))
+ (mouse-move-point window (- x (minibuf-prompt-length)) 0))
(defun mini-set-mark-and-stuff (window x y)
- ;; -6 is good for most common cases
- (mouse-set-mark-and-stuff window (- x 6) 0))
+ (mouse-set-mark-and-stuff window (- x (minibuf-prompt-length)) 0))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; resize from modeline
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defvar *modeline-hit* nil "store original modline-hit data")
+
+(defun modeline-hit (w x y) (interactive)
+ (setq *modeline-hit* (cons w (caddr hit))))
+
+(defun mouse-drag-modeline (w x y) (interactive)
+ (if *modeline-hit*
+ (let ((delta (- (cdr *modeline-hit*) (caddr hit)))
+ (win (car *modeline-hit*)))
+ (setq *modeline-hit* nil)
+ (eval-in-window win (shrink-window delta)))))
+
+;; Modeline drag to resize:
+;; Watch out for interference if you use "up" for something else
+;; For example: '(text up left) is used...
+(global-set-mouse '(modeline middle) 'modeline-hit)
+(global-set-mouse '(modeline up middle) 'mouse-drag-modeline)
+(global-set-mouse '(text up middle) 'mouse-drag-modeline)
+(global-set-mouse '(scrollbar up middle) 'mouse-drag-modeline)
+(global-set-mouse '(minibuffer up middle) 'mouse-drag-modeline)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; modeline-menu functions
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+
+;; parse thru a modeline-menu, finding item under nth character
+(defun nth-menu-elt (n menu)
+ (let ((n (- n (length (caar menu)))))
+ (if (< n 0)
+ (cdar menu)
+ (if (consp (cdr menu))
+ (nth-menu-elt n (cdr menu))
+ (cdar menu)))))
+
+(defun modeline-menu-command (x menu)
+ "*Evaluate the command associated with the character N of the MENU.
+Each element of MENU is of the form (STRING . ACTION). The STRING is
+displayed in the modeline and ACTION to invoked when that string is moused.
+If (commandp ACTION) is true,the ACTION is called interactively;
+otherwise, ACTION is evaled."
+ (let ((command (nth-menu-elt x menu)))
+ (if (commandp command)
+ (call-interactively command)
+ (eval command))))
+
+(defun modeline-menu-string (menu)
+ "*Extract the strings in (cdr MENU) and concatenate them into a string.
+The string in (car MENU) is not included in the returned string.
+ For best results, (length (caar menu)) should equal
+ the prefix in the actual modeline format string."
+ (apply 'concat (mapcar 'car (cdr menu))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -434,19 +518,18 @@ relative X divided by window width."
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun Buffer-at-mouse (w x y)
- "Calls Buffer-menu-buffer from mouse click."
(save-window-excursion
(mouse-move-point w x y)
- (beginning-of-line)
(Buffer-menu-buffer t)))
(defun mouse-buffer-bury (w x y)
"Bury the indicated buffer."
(bury-buffer (Buffer-at-mouse w x y))
+ (list-buffers)
)
(defun mouse-buffer-select (w x y)
- "Put the indicated buffer in selected window."
+ "Select the indicated buffer in other-window."
(switch-to-buffer (Buffer-at-mouse w x y))
(list-buffers)
)
@@ -458,6 +541,13 @@ relative X divided by window width."
(Buffer-menu-delete)
))
+(defun mouse-buffer-mark (w x y)
+ "mark indicated buffer for delete"
+ (save-window-excursion
+ (mouse-move-point w x y)
+ (Buffer-menu-mark)
+ ))
+
(defun mouse-buffer-execute (w x y)
"execute buffer-menu selections"
(save-window-excursion
@@ -465,6 +555,31 @@ relative X divided by window width."
(Buffer-menu-execute)
))
+(defun buffer-modeline-menu-cmd (w x y)
+ (select-window w)
+ ;; goto a line with a buffer, skip first two lines
+ (let ((line-no (count-lines 1 (point))))
+ (if (< line-no 2) (forward-line (- 2 line-no))))
+ (modeline-menu-command x buffer-modeline-menu))
+
+(defvar buffer-modeline-menu '(("--%%-" . (forward-line -1))
+ (" [ " . (forward-line -1))
+ ("Mark " . Buffer-menu-mark)
+ ("Del " . Buffer-menu-delete)
+ ("Save " . Buffer-menu-save)
+ ("Undo " . Buffer-menu-unmark)
+ ("Prev " . (forward-line -1))
+ ("Next " . (forward-line 1))
+ ("Edit " . Buffer-menu-select)
+ ("eXec " . Buffer-menu-execute)
+ ("] " . (forward-line 1))
+ )
+ "*Each element of this list is a character STRING
+\(that is displayed in the modeline\) consed to an ACTION to invoke
+when that string is moused. If (commandp ACTION) is true,
+the ACTION is called interactively; otherwise, ACTION is evaled."
+ )
+
(defun enable-mouse-in-buffer-list ()
"Call this to enable mouse selections in *Buffer List*
LEFT puts the indicated buffer in the selected window.
@@ -472,16 +587,71 @@ relative X divided by window width."
RIGHT marks the indicated buffer for deletion.
MIDDLE-RIGHT deletes the marked buffers.
To unmark a buffer marked for deletion, select it with LEFT."
- (save-window-excursion
- (list-buffers) ; Initialize *Buffer List*
- (set-buffer "*Buffer List*")
- (local-set-mouse '(text middle) 'mouse-buffer-bury)
- (local-set-mouse '(text left) 'mouse-buffer-select)
- (local-set-mouse '(text right) 'mouse-buffer-delete)
- (local-set-mouse '(text middle right) 'mouse-buffer-execute)
- )
+
+ (local-set-mouse '(text left) 'mouse-buffer-select)
+ (local-set-mouse '(text middle) 'mouse-buffer-bury)
+ (local-set-mouse '(text right) 'mouse-buffer-delete)
+ (local-set-mouse '(text middle left) 'mouse-buffer-mark)
+ (local-set-mouse '(text middle right) 'mouse-buffer-execute)
+ (setq mode-line-buffer-identification
+ (list (modeline-menu-string buffer-modeline-menu) "%b"))
+ (local-set-mouse '(modeline left) 'buffer-modeline-menu-cmd)
+ (local-set-mouse '(modeline left double) 'buffer-modeline-menu-cmd)
)
+(defvar buffer-menu-mode-hook nil "run-hooks when entering Buffer Menu mode.")
+
+(if (memq 'enable-mouse-in-buffer-list buffer-menu-mode-hook)
+ nil
+ (setq buffer-menu-mode-hook
+ (cons 'enable-mouse-in-buffer-list buffer-menu-mode-hook)))
+
+;; make sure a new buffer is created using buffer-menu-mode-hook
+(if (get-buffer "*Buffer List*") (kill-buffer "*Buffer List*"))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; mouse fill (useful to re-format mail messages with long lines
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+(defun mouse-fill-paragraph (w x y)
+ "Utility function to fill paragraphs from mouse click,
+useful in Mail to read things that have long lines."
+ (eval-in-window w
+ (mouse-move-point w x y)
+ (let (fill-prefix)
+ (fill-paragraph nil))))
+
+
+(defun fill-some-paragraphs ()
+ "*Fill the succeeding paragraphs that have the same prefix."
+ (interactive)
+ (let (fill-prefix fpr eop beg end)
+ (set-fill-prefix)
+ ;; if no fill-prefix, then match lines beginning with an alpha char.
+ (setq fpr (or fill-prefix "[a-zA-Z]"))
+ (setq fpr (if (let ((sm (string-match "[ \t]*" fpr)))
+ (and sm (= (length fpr) (match-end 0))))
+ ;; if fill-prefix is just TAB-SPACE, then also accept
+ ;; empty lines in the region.
+ (concat "\\(" fpr "\\)\\|\\(^$\\)")
+ (regexp-quote fpr)
+ ))
+ ;; now that we have the prefix, find a region of lines that match:
+ (save-excursion
+ (beginning-of-line 1)
+ (setq beg (point))
+ ;; find lines with similar prefixes:
+ (while (progn (forward-line 1)
+ (setq end (point))
+ (and (not (eobp)) (looking-at fpr))))
+ (fill-region beg end nil))))
+
+;; fill all succeeding paragraphs with this fill prefix
+(defun mouse-fill-paragraphs (w x y)
+ "Utility function to fill paragraphs from mouse click,
+useful in Mail to read things that have long lines."
+ (eval-in-window w
+ (mouse-move-point w x y)
+ (fill-some-paragraphs)))
;;;*******************************************************************
;;;
@@ -586,18 +756,20 @@ To unmark a buffer marked for deletion, select it with LEFT."
;;;
;;; Note: meta of any single button selects window.
-(global-set-mouse '(modeline left) 'mouse-scroll-up)
-(global-set-mouse '(modeline meta left) 'mouse-select-window)
+(global-set-mouse '(modeline double left) 'mouse-scroll-up)
+(global-set-mouse '(modeline shift left) 'mouse-scroll-up)
+(global-set-mouse '(modeline double middle) 'mouse-scroll-proportional)
+(global-set-mouse '(modeline shift middle) 'mouse-scroll-proportional)
+(global-set-mouse '(modeline double right) 'mouse-scroll-down)
+(global-set-mouse '(modeline shift right) 'mouse-scroll-down)
-(global-set-mouse '(modeline middle) 'mouse-scroll-proportional)
+(global-set-mouse '(modeline meta left) 'mouse-select-window)
(global-set-mouse '(modeline meta middle) 'mouse-select-window)
-(global-set-mouse '(modeline control middle) 'mouse-split-horizontally)
-
-(global-set-mouse '(modeline right) 'mouse-scroll-down)
-(global-set-mouse '(modeline meta right) 'mouse-select-window)
+(global-set-mouse '(modeline meta right) 'mouse-select-window)
;;; control-left selects this window, control-right deletes it.
(global-set-mouse '(modeline control left) 'mouse-delete-other-windows)
+(global-set-mouse '(modeline control middle) 'mouse-split-horizontally)
(global-set-mouse '(modeline control right) 'mouse-delete-window)
;; in case of confusion, just select it:
@@ -610,6 +782,7 @@ To unmark a buffer marked for deletion, select it with LEFT."
(global-set-mouse '(modeline shift control meta right) 'mouse-help-region)
(global-set-mouse '(modeline double control meta right) 'mouse-help-region)
+
;;;
;;; Minibuffer Mousemap
;;; Demonstrating some variety:
@@ -618,8 +791,8 @@ To unmark a buffer marked for deletion, select it with LEFT."
(global-set-mouse '(minibuffer middle) 'mini-set-mark-and-stuff)
-(global-set-mouse '(minibuffer shift middle) '(select-previous-complex-command))
-(global-set-mouse '(minibuffer double middle) '(select-previous-complex-command))
+(global-set-mouse '(minibuffer shift middle) '(prev-complex-command))
+(global-set-mouse '(minibuffer double middle) '(prev-complex-command))
(global-set-mouse '(minibuffer control middle) '(next-complex-command 1))
(global-set-mouse '(minibuffer meta middle) '(previous-complex-command 1))
diff --git a/lisp/sun-fns.elc b/lisp/sun-fns.elc
new file mode 100644
index 00000000000..a3269916f07
--- /dev/null
+++ b/lisp/sun-fns.elc
Binary files differ
diff --git a/lisp/sun-keys.el b/lisp/sun-keys.el
index 59fba2a5791..87da264c1b7 100644
--- a/lisp/sun-keys.el
+++ b/lisp/sun-keys.el
@@ -8,7 +8,7 @@
;;;
;;; Copyright (C) 1986 Free Software Foundation, Inc.
;;;
-;;; This file is part of GNU Emacs.
+;; This file is part of GNU Emacs.
;; GNU Emacs is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
@@ -23,6 +23,7 @@
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs; see the file COPYING. If not, write to
;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
;;;
;;; Batten@uk.ac.bham.multics (Ian G. Batten)
;;;
diff --git a/lisp/term/sun-mouse.el b/lisp/sun-mouse.el
index bed2b416c1f..a2f4b938e28 100644
--- a/lisp/term/sun-mouse.el
+++ b/lisp/sun-mouse.el
@@ -1,5 +1,5 @@
;; Mouse handling for Sun windows
-;; Copyright (C) 1987 Free Software Foundation, Inc.
+;; Copyright (C) 1987, 1991 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -19,6 +19,9 @@
;;; Jeff Peck, Sun Microsystems, Jan 1987.
;;; Original idea by Stan Jefferson
+;;
+;; Mar 90 get/set selections
+;; Mar 91 add mouse-help, print bindings dynamically
(provide 'sun-mouse)
@@ -167,7 +170,7 @@ Just like the Common Lisp function of the same name."
(,@ forms))
(set-buffer StartBuffer)))))
-(put 'eval-in-buffer 'lisp-indent-function 1)
+(put 'eval-in-buffer 'lisp-indent-hook 1)
;;; this is used extensively by sun-fns.el
;;;
@@ -178,8 +181,11 @@ Just like the Common Lisp function of the same name."
(progn
(select-window (, window))
(,@ forms))
- (select-window OriginallySelectedWindow)))))
-(put 'eval-in-window 'lisp-indent-function 1)
+ ;; don't go back to window if it has been destroyed...
+ ;; window-point seems to work as an indication of existence
+ (if (window-point OriginallySelectedWindow)
+ (select-window OriginallySelectedWindow))))))
+(put 'eval-in-window 'lisp-indent-hook 1)
;;;
;;; handy utility, generalizes window_loop
@@ -198,7 +204,7 @@ This is a macro, and does not evaluate its arguments."
(select-window
(next-window nil (, yesmini)))))))
(select-window OriginallySelectedWindow)))))
-(put 'eval-in-window 'lisp-indent-function 0)
+(put 'eval-in-window 'lisp-indent-hook 0)
(defun move-to-loc (x y)
"Move cursor to window location X, Y.
@@ -224,6 +230,7 @@ Handles wrapped and horizontally scrolled lines correctly."
))
+(setq *mouse-help* nil) ; flag to display, rather than execute
(defun sun-mouse-handler (&optional hit)
"Evaluates the function or list associated with a mouse hit.
Expecting to read a hit, which is a list: (button x y delta).
@@ -249,10 +256,15 @@ Returns nil."
(mouse-code-to-mouse-list mouse-code)))))
((symbolp form)
(setq this-command form)
- (funcall form *mouse-window* *mouse-x* *mouse-y*))
+ (if *mouse-help*
+ (progn (prin1 (list form *mouse-window* *mouse-x* *mouse-y*))
+ (exit-recursive-edit))
+ (funcall form *mouse-window* *mouse-x* *mouse-y*)))
((listp form)
(setq this-command (car form))
- (eval form))
+ (if *mouse-help*
+ (progn (prin1 form) (exit-recursive-edit))
+ (eval form)))
(t
(error "Mouse action must be symbol or list, but was: %s"
form))))))
@@ -263,6 +275,11 @@ Returns nil."
;; (message (prin1-to-string this-command)) ; to see what your buttons did
nil)
+(defun mouse-help ()
+ (interactive)
+ (let ((*mouse-help* t))
+ (recursive-edit)))
+
(defun sm::combined-hits ()
"Read and return next mouse-hit, include possible double click"
(let ((hit1 (mouse-hit-read)))
@@ -634,20 +651,115 @@ CODE values: 13 = Tool-Position, 14 = Size-in-Pixels, 18 = Size-in-Chars."
;;; Function interface to selection/region
;;; primative functions are defined in sunfns.c
;;;
-(defun sun-yank-selection ()
- "Set mark and yank the contents of the current sunwindows selection
-into the current buffer at point."
+(defun sunview-yank-stuff ()
+ "Set mark and yank the contents of the current TTYSW `STUFF' selection
+into the current buffer at point. The STUFF selection contains the currently
+or previously highlighted text from a TTYSW."
(interactive "*")
(set-mark-command nil)
(insert-string (sun-get-selection)))
+;;;
+(defun display-host ()
+ "Extract <host> from DISPLAY environment variable, or return nil if not specified."
+ (let ((display (getenv "DISPLAY")))
+ (if display
+ (let ((colon_at (string-match ":" display)))
+ (if colon_at
+ (if (not (zerop colon_at))
+ (substring display 0 colon_at)
+ ))))))
+
+;;; get_selection has been extended to work in X
+;;; we extend to work on remote X display...
+(defun sunview-yank-clipboard ()
+ "Set mark and yank the contents of the SunView Clipboard into the
+current buffer at point."
+ (interactive "*")
+ (set-mark-command nil)
+ (let ((host (display-host)))
+ (if host
+ (call-process "rsh" nil t t (display-host) "get_selection" "3")
+ (call-process "get_selection" nil t t "3")))
+ )
+
+(defun sunview-yank-current-selection ()
+ "Set mark and yank the contents of the current SunView selection
+into current buffer at point. The current selection is the currently
+highlighted text in either a textsw or a ttysw."
+ (interactive "*")
+ (set-mark-command nil)
+ (let ((host (display-host)))
+ (if host
+ (call-process "rsh" nil t t (display-host) "get_selection")
+ (call-process "get_selection" nil t t))))
+
+(defun sunview-yank-any-selection (arg)
+ "Yank one of the sunview selections:
+with no arg, the current selection; with minus-only prefix, the clipboard;
+with any other arg, the ttysw STUFF."
+ (interactive "*P")
+ (cond ((null arg) (sunview-yank-current-selection))
+ ((eq arg '-) (sunview-yank-clipboard))
+ (t (sunview-yank-stuff))))
+
+;;; define the selection file used by this emacs
+;;; if not local machine, then automounter must find /net/<host>/tmp
+(defvar owselectionfilex nil "Cache path to ttysw selection file (a kludge!).")
+;;; determine value at runtime, not when this file loaded into temacs
+(defun owselectionfile ()
+ (or owselectionfilex
+ (let* ((host (display-host))
+ (filex
+ (if host
+ (concat "/net/" host "/tmp/ttyselection")
+ "/tmp/ttyselection")))
+ (if (file-exists-p filex)
+ (setq owselectionfilex filex)
+ (progn
+ (message "no TTYSW selection file")
+ nil)
+ ))))
+
+(defun xv-yank-selection ()
+ "Set mark and yank the contents of the current Xview selection
+into the current buffer at point. The STUFF selection contains the currently
+or previously highlighted text from a TTYSW."
+ (interactive "*")
+ (if (owselectionfile)
+ (progn
+ (insert-file (owselectionfile))
+ (exchange-point-and-mark)))
+ )
+
+(defun xv-select-region (beg end)
+ "Set the TTYSW selection to the region in the current buffer."
+ (interactive "r")
+ (if (owselectionfile)
+ (write-region beg end (owselectionfile) nil 'noprint))
+ )
+
+(defun sun-yank-selection ()
+ "Set mark and yank the contents of the current TTYSW `STUFF' or Xview selection
+into the current buffer at point."
+ (interactive "*")
+ (if (getenv "DISPLAY")
+ (xv-yank-selection)
+ (sunview-yank-stuff))
+ )
+
(defun sun-select-region (beg end)
- "Set the sunwindows selection to the region in the current buffer."
+ "Set the TTYSW 'STUFF' or Xview selection to the region in the current buffer."
(interactive "r")
- (sun-set-selection (buffer-substring beg end)))
+ (if (getenv "DISPLAY")
+ (xv-select-region beg end)
+ (sun-set-selection (buffer-substring beg end)))
+ )
+
+
;;;
-;;; Support for emacstool
+;;; support for emacstool
;;; This closes the window instead of stopping emacs.
;;;
(defun suspend-emacstool (&optional stuffstring)
@@ -655,10 +767,12 @@ into the current buffer at point."
you don't want to suspend (there is no way to resume),
just close the window, and wait for reopening."
(interactive)
- (run-hooks 'suspend-hook)
+ (if (and (boundp 'suspend-hook) suspend-hook)
+ (funcall suspend-hook))
(if stuffstring (send-string-to-terminal stuffstring))
(send-string-to-terminal "\033[2t") ; To close EmacsTool window.
- (run-hooks 'suspend-resume-hook))
+ (if (and (boundp 'suspend-resume-hook) suspend-resume-hook)
+ (funcall suspend-resume-hook)))
;;;
;;; initialize mouse maps
;;;
diff --git a/lisp/sun-mouse.elc b/lisp/sun-mouse.elc
new file mode 100644
index 00000000000..b0c4971ff8a
--- /dev/null
+++ b/lisp/sun-mouse.elc
Binary files differ
diff --git a/lisp/term/sup-mouse.el b/lisp/sup-mouse.el
index d03b009136d..d03b009136d 100644
--- a/lisp/term/sup-mouse.el
+++ b/lisp/sup-mouse.el
diff --git a/lisp/sup-mouse.elc b/lisp/sup-mouse.elc
new file mode 100644
index 00000000000..a53ab91c65c
--- /dev/null
+++ b/lisp/sup-mouse.elc
Binary files differ
diff --git a/lisp/superyank.el b/lisp/superyank.el
deleted file mode 100644
index 4d16e6b5e5b..00000000000
--- a/lisp/superyank.el
+++ /dev/null
@@ -1,1212 +0,0 @@
-;; superyank.el -- Version 1.1
-;;
-;; Inserts the message being replied to with various user controlled
-;; citation styles.
-;;
-
-;; This file is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY. No author or distributor
-;; accepts responsibility to anyone for the consequences of using it
-;; or for whether it serves any particular purpose or works at all,
-;; unless he says so in writing. Refer to the GNU Emacs General Public
-;; License for full details.
-
-;; Everyone is granted permission to copy, modify and redistribute
-;; this file, but only under the conditions described in the
-;; GNU Emacs General Public License. A copy of this license is
-;; supposed to have been given to you along with GNU Emacs so you
-;; can know your rights and responsibilities. It should be in a
-;; file named COPYING. Among other things, the copyright notice
-;; and this notice must be preserved on all copies.
-
-;; NAME: Barry A. Warsaw USMAIL: National Institute of Standards
-;; TELE: (301) 975-3460 and Technology (formerly NBS)
-;; UUCP: {...}!uunet!cme-durer!warsaw Rm. B-124, Bldg. 220
-;; ARPA: warsaw@cme.nist.gov Gaithersburg, MD 20899
-
-;; Modification history:
-;;
-;; modified: 14-Jun-1989 baw (better keymap set procedure, rewrite-headers)
-;; modified: 12-Jun-1989 baw (added defvar for sy-use-only-preference-p)
-;; modified: 6-Jun-1989 baw (better sy-rewrite-headers, no kill/yank)
-;; modified: 5-Jun-1989 baw (requires rnewspost.el)
-;; modified: 1-Jun-1989 baw (persistent attribution, sy-open-line)
-;; modified: 31-May-1989 baw (fixed some gnus problems, id'd another)
-;; modified: 22-May-1989 baw (documentation)
-;; modified: 8-May-1989 baw (auto filling of regions)
-;; modified: 1-May-1989 baw (documentation)
-;; modified: 27-Apr-1989 baw (new preference scheme)
-;; modified: 24-Apr-1989 baw (remove gnus headers, attrib scheme, cite lines)
-;; modified: 19-Apr-1989 baw (cite key, fill p, yank region, naming scheme)
-;; modified: 12-Apr-1989 baw (incorp other mail yank features seen on net)
-;; created : 16-Feb-1989 baw (mod vanilla fn indent-rigidly mail-yank-original)
-
-;; Though I wrote this package basically from scratch, as an elisp
-;; learning exercise, it was inspired by postings of similar packages to
-;; the gnu.emacs newsgroup over the past month or so.
-;;
-;; Here's a brief history of how this package developed:
-;;
-;; I as well as others on the net were pretty unhappy about the way emacs
-;; cited replies with the tab or 4 spaces. It looked ugly and made it hard
-;; to distinguish between original and cited lines. I hacked on the function
-;; yank-original to at least give the user the ability to define the citation
-;; character. I posted this simple hack, and others did as well. The main
-;; difference between mine and others was that a space was put after the
-;; citation string on on new citations, but not after previously cited lines:
-;;
-;; >> John wrote this originally
-;; > Jane replied to that
-;;
-;; Then Martin Neitzel posted some code that he developed, derived in part
-;; from code that Ashwin Ram posted previous to that. In Martin's
-;; posting, he introduced a new, and (IMHO) superior, citation style,
-;; eliminating nested citations. Yes, I wanted to join the Small-But-
-;; Growing-Help-Stamp-Out-Nested-Citation-Movement! You should too.
-;;
-;; But Martin's code simply asks the user for the citation string (here
-;; after called the `attribution' string), and I got to thinking, it wouldn't
-;; be that difficult to automate that part. So I started hacking this out.
-;; It proved to be not as simple as I first thought. But anyway here it
-;; is. See the wish list below for future plans (if I have time).
-;;
-;; Type "C-h f mail-yank-original" after this package is loaded to get a
-;; description of what it does and the variables that control it.
-;;
-;; ======================================================================
-;;
-;; Changes wish list
-;;
-;; 1) C-x C-s yanks a region from the RMAIL buffer instead of the
-;; whole buffer
-;;
-;; 2) reparse nested citations to try to recast as non-nested citations
-;; perhaps by checking the References: line
-;;
-;; ======================================================================
-;;
-;; require and provide features
-;;
-(require 'sendmail)
-(provide 'superyank)
-
-;;
-;; ======================================================================
-;;
-;; don't need rnewspost.el to rewrite the header. This only works
-;; with diffs to rnewspost.el that I posted with the original
-;; superyank code.
-;;
-(setq news-reply-header-hook nil)
-
-;; **********************************************************************
-;; start of user defined variables
-;; **********************************************************************
-;;
-;; this section defines variables that control the operation of
-;; super-mail-yank. Most of these are described in the comment section
-;; as well as the DOCSTRING.
-;;
-
-;;
-;; ----------------------------------------------------------------------
-;;
-;; this variable holds the default author's name for citations
-;;
-(defvar sy-default-attribution "Anon"
- "String that describes attribution to unknown person. This string
-should not contain the citation string.")
-
-;;
-;; ----------------------------------------------------------------------
-;;
-;; string used as an end delimiter for both nested and non-nested citations
-;;
-(defvar sy-citation-string ">"
- "String to use as an end-delimiter for citations. This string is
-used in both nested and non-nested citations. For best results, use a
-single character with no trailing space. Most commonly used string
-is: \">\.")
-
-;;
-;; ----------------------------------------------------------------------
-;;
-;; variable controlling citation type, nested or non-nested
-;;
-(defvar sy-nested-citation-p nil
- "Non-nil uses nested citations, nil uses non-nested citations.
-Nested citations are of the style:
-
-I wrote this
-> He wrote this
->> She replied to something he wrote
-
-Non-nested citations are of the style:
-
-I wrote this
-John> He wrote this
-Jane> She originally wrote this")
-
-
-;;
-;; ----------------------------------------------------------------------
-;;
-;; regular expression that matches existing citations
-;;
-(defvar sy-cite-regexp "[a-zA-Z0-9]*>"
- "Regular expression that describes how an already cited line in an
-article begins. The regexp is only used at the beginning of a line,
-so it doesn't need to begin with a '^'.")
-
-;;
-;; ----------------------------------------------------------------------
-;;
-;; regular expression that delimits names from titles in the field that
-;; looks like: (John X. Doe -- Computer Hacker Extraordinaire)
-;;
-(defvar sy-titlecue-regexp "\\s +-+\\s +"
-
- "Regular expression that delineates names from titles in the name
-field. Often, people will set up their name field to look like this:
-
-(John Xavier Doe -- Computer Hacker Extraordinaire)
-
-Set to nil to treat entire field as a name.")
-
-;;
-;; ----------------------------------------------------------------------
-;;
-;;
-(defvar sy-preferred-attribution 2
-
- "This is an integer indicating what the user's preference is in
-attribution style, based on the following key:
-
-0: email address name is preferred
-1: initials are preferred
-2: first name is preferred
-3: last name is preferred
-
-The value of this variable may also be greater than 3, which would
-allow you to prefer the 2nd through nth - 1 name. If the preferred
-attribution is nil or the empty string, then the secondary preferrence
-will be the first name. After that, the entire name alist is search
-until a non-empty, non-nil name is found. If no such name is found,
-then the user is either queried or the default attribution string is
-used depending on the value of sy-confirm-always-p.
-
-Examples:
-
-assume the from: line looks like this:
-
-from: doe@computer.some.where.com (John Xavier Doe)
-
-The following preferences would return these strings:
-
-0: \"doe\"
-1: \"JXD\"
-2: \"John\"
-3: \"Doe\"
-4: \"Xavier\"
-
-anything else would return \"John\".")
-
-;;
-;; ----------------------------------------------------------------------
-;;
-(defvar sy-confirm-always-p t
- "If t, always confirm attribution string before inserting into
-buffer.")
-
-
-;;
-;; ----------------------------------------------------------------------
-;;
-;; informative header hook
-;;
-(defvar sy-rewrite-header-hook 'sy-header-on-said
- "Hook for inserting informative header at the top of the yanked
-message. Set to nil for no header. Here is a list of predefined
-header styles; you can use these as a model to write you own:
-
-sy-header-on-said [default]: On 14-Jun-1989 GMT,
- John Xavier Doe said:
-
-sy-header-inarticle-writes: In article <123456789> John Xavier Doe writes:
-
-sy-header-regarding-writes: Regarding RE: superyank; John Xavier Doe adds:
-
-sy-header-verbose: On 14-Jun-1989 GMT, John Xavier Doe
- from the organization Great Company
- has this to say about article <123456789>
- in newsgroups misc.misc
- concerning RE: superyank
- referring to previous articles <987654321>
-
-You can use the following variables as information strings in your header:
-
-sy-reply-yank-date: the date field [ex: 14-Jun-1989 GMT]
-sy-reply-yank-from: the from field [ex: John Xavier Doe]
-sy-reply-yank-message-id: the message id [ex: <123456789>]
-sy-reply-yank-subject: the subject line [ex: RE: superyank]
-sy-reply-yank-newsgroup: the newsgroup name for GNUS [ex: misc.misc]
-sy-reply-yank-references: the article references [ex: <987654321>]
-sy-reply-yank-organization: the author's organization [ex: Great Company]
-
-If a field can't be found, because it doesn't exist or is not being
-shown, perhaps because of toggle-headers, the corresponding field
-variable will contain the string \"mumble mumble\".")
-
-;;
-;; ----------------------------------------------------------------------
-;;
-;; non-nil means downcase the author's name string
-;;
-(defvar sy-downcase-p nil
- "Non-nil means downcase the author's name string.")
-
-;;
-;; ----------------------------------------------------------------------
-;;
-;; controls removal of leading white spaces
-;;
-(defvar sy-left-justify-p nil
- "If non-nil, delete all leading white space before citing.")
-
-;;
-;; ----------------------------------------------------------------------
-;;
-;; controls auto filling of region
-;;
-(defvar sy-auto-fill-region-p nil
- "If non-nil, automatically fill each paragraph that is cited. If
-nil, do not auto fill each paragraph.")
-
-
-;;
-;; ----------------------------------------------------------------------
-;;
-;; controls use of preferred attribution only, or use of attribution search
-;; scheme if the preferred attrib can't be found.
-;;
-(defvar sy-use-only-preference-p nil
-
- "If non-nil, then only the preferred attribution string will be
-used. If the preferred attribution string can not be found, then the
-sy-default-attribution will be used. If nil, and the preferred
-attribution string is not found, then some secondary scheme will be
-employed to find a suitable attribution string.")
-
-;; **********************************************************************
-;; end of user defined variables
-;; **********************************************************************
-
-;;
-;; ----------------------------------------------------------------------
-;;
-;; The new citation style means we can clean out other headers in addition
-;; to those previously cleaned out. Anyway, we create our own headers.
-;; Also, we want to clean out any headers that gnus puts in. Add to this
-;; for other mail or news readers you may be using.
-;;
-(setq mail-yank-ignored-headers "^via:\\|^origin:\\|^status:\\|^re\\(mail\\|ceiv\\)ed\\|^[a-z-]*message-id:\\|^\\(summary-\\)?line[s]?:\\|^cc:\\|^subject:\\|^\\(\\(in-\\)?reply-\\)?to:\\|^\\(\\(return\\|reply\\)-\\)?path:\\|^\\(posted-\\)?date:\\|^\\(mail-\\)?from:\\|^newsgroup[s]?:\\|^organization:\\|^keywords:\\|^distribution:\\|^references:")
-
-;;
-;; ----------------------------------------------------------------------
-;;
-;; global variables, not user accessable
-;;
-(setq sy-persist-attribution (concat sy-default-attribution "> "))
-(setq sy-reply-yank-date "")
-(setq sy-reply-yank-from "")
-(setq sy-reply-yank-message-id "")
-(setq sy-reply-yank-subject "")
-(setq sy-reply-yank-newsgroups "")
-(setq sy-reply-yank-references "")
-(setq sy-reply-yank-organization "")
-
-;;
-;; ======================================================================
-;;
-;; This section contains primitive functions used in the schemes. They
-;; extract name fields from various parts of the "from:" field based on
-;; the control variables described above.
-;;
-;; Some will use recursion to pick out the correct namefield in the namestring
-;; or the list of initials. These functions all scan a string that contains
-;; the name, ie: "John Xavier Doe". There is no limit on the number of names
-;; in the string. Also note that all white spaces are basically ignored and
-;; are stripped from the returned strings, and titles are ignored if
-;; sy-titlecue-regexp is set to non-nil.
-;;
-;; Others will use methods to try to extract the name from the email
-;; address of the originator. The types of addresses readable are
-;; described above.
-
-;;
-;; ----------------------------------------------------------------------
-;;
-;; try to extract the name from an email address of the form
-;; name%[stuff]
-;;
-;; Unlike the get-name functions above, these functions operate on the
-;; buffer instead of a supplied name-string.
-;;
-(defun sy-%-style-address ()
- (beginning-of-line)
- (buffer-substring
- (progn (re-search-forward "%" (point-max) t)
- (if (not (bolp)) (forward-char -1))
- (point))
- (progn (re-search-backward "^\\|[^a-zA-Z0-9]")
- (point))))
-
-;;
-;; ----------------------------------------------------------------------
-;;
-;; try to extract names from addresses with the form:
-;; [stuff]name@[stuff]
-;;
-(defun sy-@-style-address ()
- (beginning-of-line)
- (buffer-substring
- (progn (re-search-forward "@" (point-max) t)
- (if (not (bolp)) (forward-char -1))
- (point))
- (progn (re-search-backward "^\\|[^a-zA-Z0-0]")
- (if (not (bolp)) (forward-char 1))
- (point))))
-
-;;
-;; ----------------------------------------------------------------------
-;;
-;; try to extract the name from addresses with the form:
-;; [stuff]![stuff]...!name[stuff]
-;;
-(defun sy-!-style-address ()
- (beginning-of-line)
- (buffer-substring
- (progn (while (re-search-forward "!" (point-max) t))
- (point))
- (progn (re-search-forward "[^a-zA-Z0-9]\\|$")
- (if (not (eolp)) (forward-char -1))
- (point))))
-
-;;
-;; ----------------------------------------------------------------------
-;;
-;; using the different email name schemes, try each one until you get a
-;; non-nil entry
-;;
-(defun sy-get-emailname ()
- (let ((en1 (sy-%-style-address))
- (en2 (sy-@-style-address))
- (en3 (sy-!-style-address)))
- (cond
- ((not (string-equal en1 "")) en1)
- ((not (string-equal en2 "")) en2)
- ((not (string-equal en3 "")) en3)
- (t ""))))
-
-;;
-;; ----------------------------------------------------------------------
-;;
-;; returns the "car" of the namestring, really the first namefield
-;;
-;; (sy-string-car "John Xavier Doe")
-;; => "John"
-;;
-(defun sy-string-car (namestring)
- (substring namestring
- (progn (string-match "\\s *" namestring) (match-end 0))
- (progn (string-match "\\s *\\S +" namestring) (match-end 0))))
-
-;;
-;; ----------------------------------------------------------------------
-;;
-;; returns the "cdr" of the namestring, really the whole string from
-;; after the first name field to the end of the string.
-;;
-;; (sy-string-cdr "John Xavier Doe")
-;; => "Xavier Doe"
-;;
-(defun sy-string-cdr (namestring)
- (substring namestring
- (progn (string-match "\\s *\\S +\\s *" namestring)
- (match-end 0))))
-
-;;
-;; ----------------------------------------------------------------------
-;;
-;; convert a namestring to a list of namefields
-;;
-;; (sy-namestring-to-list "John Xavier Doe")
-;; => ("John" "Xavier" "Doe")
-;;
-(defun sy-namestring-to-list (namestring)
- (if (not (string-match namestring ""))
- (append (list (sy-string-car namestring))
- (sy-namestring-to-list (sy-string-cdr namestring)))))
-
-;;
-;; ----------------------------------------------------------------------
-;;
-;; strip the initials from each item in the list and return a string
-;; that is the concatenation of the initials
-;;
-(defun sy-strip-initials (raw-nlist)
- (if (not raw-nlist)
- nil
- (concat (substring (car raw-nlist) 0 1)
- (sy-strip-initials (cdr raw-nlist)))))
-
-
-;;
-;; ----------------------------------------------------------------------
-;;
-;; using the namestring, build a list which is in the following order
-;;
-;; (email, initials, firstname, lastname, name1, name2, name3 ... nameN-1)
-;;
-(defun sy-build-ordered-namelist (namestring)
- (let* ((raw-nlist (sy-namestring-to-list namestring))
- (initials (sy-strip-initials raw-nlist))
- (firstname (car raw-nlist))
- (revnames (reverse (cdr raw-nlist)))
- (lastname (car revnames))
- (midnames (reverse (cdr revnames)))
- (emailnames (sy-get-emailname)))
- (append (list emailnames)
- (list initials)
- (list firstname)
- (list lastname)
- midnames)))
-
-;;
-;; ----------------------------------------------------------------------
-;;
-;; Query the user for the attribution string. Supply sy-default-attribution
-;; as the default choice.
-;;
-(defun sy-query-for-attribution ()
- (concat
- (let* ((prompt (concat "Enter attribution string: (default "
- sy-default-attribution
- ") "))
- (query (read-input prompt))
- (attribution (if (string-equal query "")
- sy-default-attribution
- query)))
- (if sy-downcase-p
- (downcase attribution)
- attribution))
- sy-citation-string))
-
-
-;;
-;; ----------------------------------------------------------------------
-;;
-;; parse the current line for the namestring
-;;
-(defun sy-get-namestring ()
- (save-restriction
- (beginning-of-line)
- (if (re-search-forward "(.*)" (point-max) t)
- (let ((start (progn
- (beginning-of-line)
- (re-search-forward "\\((\\s *\\)\\|$" (point-max) t)
- (point)))
- (end (progn
- (re-search-forward
- (concat "\\(\\s *\\()\\|" sy-titlecue-regexp "\\)\\)\\|$")
- (point-max) t)
- (point))))
- (narrow-to-region start end)
- (let ((start (progn
- (beginning-of-line)
- (point)))
- (end (progn
- (end-of-line)
- (re-search-backward
- (concat "\\s *\\()\\|" sy-titlecue-regexp "\\)$")
- (point-min) t)
- (point))))
- (buffer-substring start end)))
- (let ((start (progn
- (beginning-of-line)
- (re-search-forward "^\"*")
- (point)))
- (end (progn
- (re-search-forward "\\(\\s *[a-zA-Z0-9\\.]+\\)*"
- (point-max) t)
- (point))))
- (buffer-substring start end)))))
-
-
-;;
-;; ----------------------------------------------------------------------
-;;
-;; scan the nlist and return the integer pointing to the first legal
-;; non-empty namestring. Returns the integer pointing to the index
-;; in the nlist of the preferred namestring, or nil if no legal
-;; non-empty namestring could be found.
-;;
-(defun sy-return-preference-n (nlist)
- (let ((p sy-preferred-attribution)
- (exception nil))
- ;;
- ;; check to be sure the index is not out-of-bounds
- ;;
- (cond
- ((< p 0) (setq p 2) (setq exception t))
- ((not (nth p nlist)) (setq p 2) (setq exception t)))
- ;;
- ;; check to be sure that the explicit preference is not empty
- ;;
- (if (string-equal (nth p nlist) "")
- (progn (setq p 0)
- (setq exception t)))
- ;;
- ;; find the first non-empty namestring
- ;;
- (while (and (nth p nlist)
- (string-equal (nth p nlist) ""))
- (setq exception t)
- (setq p (+ p 1)))
- ;;
- ;; return the preference index if non-nil, otherwise nil
- ;;
- (if (or (and exception sy-use-only-preference-p)
- (not (nth p nlist)))
- nil
- p)))
-
-;;
-;;
-;; ----------------------------------------------------------------------
-;;
-;; rebuild the nlist into an alist for completing-read. Use as a guide
-;; the index of the preferred name field. Get the actual preferred
-;; name field base on other factors (see above). If no actual preferred
-;; name field is found, then query the user for the attribution string.
-;;
-;; also note that the nlist is guaranteed to be non-empty. At the very
-;; least it will consist of 4 empty strings ("" "" "" "")
-;;
-(defun sy-nlist-to-alist (nlist)
- (let ((preference (sy-return-preference-n nlist))
- alist
- (n 0))
- ;;
- ;; check to be sure preference is not nil
- ;;
- (if (not preference)
- (setq alist (list (cons (sy-query-for-attribution) nil)))
- ;;
- ;; preference is non-nil
- ;;
- (setq alist (list (cons (nth preference nlist) nil)))
- (while (nth n nlist)
- (if (= n preference) nil
- (setq alist (append alist (list (cons (nth n nlist) nil)))))
- (setq n (+ n 1))))
- alist))
-
-
-
-;;
-;; ----------------------------------------------------------------------
-;;
-;; confirm if desired after the alist has been built
-;;
-(defun sy-get-attribution (alist)
- (concat
- ;;
- ;; check to see if nested citations are to be used
- ;;
- (if sy-nested-citation-p
- ""
- ;;
- ;; check to see if confirmation is needed
- ;; if not, just return the preference (first element in alist)
- ;;
- (if (not sy-confirm-always-p)
- (car (car alist))
- ;;
- ;; confirmation is requested so build the prompt, confirm
- ;; and return the chosen string
- ;;
- (let* (ignore
- (prompt (concat "Complete attribution string: (default "
- (car (car alist))
- ") "))
- ;;
- ;; set up the local completion keymap
- ;;
- (minibuffer-local-must-match-map
- (let ((map (make-sparse-keymap)))
- (define-key map "?" 'minibuffer-completion-help)
- (define-key map " " 'minibuffer-complete-word)
- (define-key map "\t" 'minibuffer-complete)
- (define-key map "\00A" 'exit-minibuffer)
- (define-key map "\00D" 'exit-minibuffer)
- (define-key map "\007"
- '(lambda ()
- (interactive)
- (beep)
- (exit-minibuffer)))
- map))
- ;;
- ;; read the completion
- ;;
- (attribution (completing-read prompt alist))
- ;;
- ;; check attribution string for emptyness
- ;;
- (choice (if (or (not attribution)
- (string-equal attribution ""))
- (car (car alist))
- attribution)))
-
- (if sy-downcase-p
- (downcase choice)
- choice))))
- sy-citation-string))
-
-
-;;
-;; ----------------------------------------------------------------------
-;;
-;; this function will scan the current rmail buffer, narrowing it to the
-;; from: line, then using this, it will try to decipher some names from
-;; that line. It will then build the name alist and try to confirm
-;; its choice of attribution strings. It returns the chosen attribution
-;; string.
-;;
-(defun sy-scan-rmail-for-names (rmailbuffer)
- (save-excursion
- (let ((case-fold-search t)
- alist
- attribution)
- (switch-to-buffer rmailbuffer)
- (goto-char (point-min))
- ;;
- ;; be sure there is a from: line
- ;;
- (if (not (re-search-forward "^from:\\s *" (point-max) t))
- (setq attribution (sy-query-for-attribution))
- ;;
- ;; if there is a from: line, then scan the narrow the buffer,
- ;; grab the namestring, and build the alist, then using this
- ;; get the attribution string.
- ;;
- (save-restriction
- (narrow-to-region (point)
- (progn (end-of-line) (point)))
- (let* ((namestring (sy-get-namestring))
- (nlist (sy-build-ordered-namelist namestring)))
- (setq alist (sy-nlist-to-alist nlist))))
- ;;
- ;; we've built the alist, now confirm the attribution choice
- ;; if appropriate
- ;;
- (setq attribution (sy-get-attribution alist)))
- attribution)))
-
-
-;;
-;; ======================================================================
-;;
-;; the following function insert of citations, writing of headers, filling
-;; paragraphs and general higher level operations
-;;
-
-;;
-;; ----------------------------------------------------------------------
-;;
-;; insert a nested citation
-;;
-(defun sy-insert-citation (start end cite-string)
- (save-excursion
- (goto-char end)
- (setq end (point-marker))
- (goto-char start)
- (or (bolp)
- (forward-line 1))
-
- (let ((fill-prefix (concat cite-string " "))
- (fstart (point))
- (fend (point)))
-
- (while (< (point) end)
- ;;
- ;; remove leading tabs if desired
- ;;
- (if sy-left-justify-p
- (delete-region (point)
- (progn (skip-chars-forward " \t") (point))))
- ;;
- ;; check to see if the current line should be cited
- ;;
- (if (or (eolp)
- (looking-at sy-cite-regexp))
- ;;
- ;; do not cite this line unless nested-citations are to be
- ;; used
- ;;
- (progn
- (or (eolp)
- (if sy-nested-citation-p
- (insert cite-string)))
-
- ;; set fill start and end points
- ;;
- (or (= fstart fend)
- (not sy-auto-fill-region-p)
- (progn (goto-char fend)
- (or (not (eolp))
- (setq fend (+ fend 1)))
- (fill-region-as-paragraph fstart fend)))
- (setq fstart (point))
- (setq fend (point)))
-
- ;; else
- ;;
- (insert fill-prefix)
- (end-of-line)
- (setq fend (point)))
-
- (forward-line 1)))
- (move-marker end nil)))
-
-;;
-;; ----------------------------------------------------------------------
-;;
-;; yank a particular field into a holding variable
-;;
-(defun sy-yank-fields (start)
- (save-excursion
- (goto-char start)
- (setq sy-reply-yank-date (mail-fetch-field "date")
- sy-reply-yank-from (mail-fetch-field "from")
- sy-reply-yank-subject (mail-fetch-field "subject")
- sy-reply-yank-newsgroups (mail-fetch-field "newsgroups")
- sy-reply-yank-references (mail-fetch-field "references")
- sy-reply-yank-message-id (mail-fetch-field "message-id")
- sy-reply-yank-organization (mail-fetch-field "organization"))
- (or sy-reply-yank-date
- (setq sy-reply-yank-date "mumble mumble"))
- (or sy-reply-yank-from
- (setq sy-reply-yank-from "mumble mumble"))
- (or sy-reply-yank-subject
- (setq sy-reply-yank-subject "mumble mumble"))
- (or sy-reply-yank-newsgroups
- (setq sy-reply-yank-newsgroups "mumble mumble"))
- (or sy-reply-yank-references
- (setq sy-reply-yank-references "mumble mumble"))
- (or sy-reply-yank-message-id
- (setq sy-reply-yank-message-id "mumble mumble"))
- (or sy-reply-yank-organization
- (setq sy-reply-yank-organization "mumble mumble"))))
-
-;;
-;; ----------------------------------------------------------------------
-;;
-;; rewrite the header to be more conversational
-;;
-(defun sy-rewrite-headers (start)
- (goto-char start)
- (run-hooks 'sy-rewrite-header-hook))
-
-;;
-;; ----------------------------------------------------------------------
-;;
-;; some different styles of headers
-;;
-(defun sy-header-on-said ()
- (insert-string "\nOn " sy-reply-yank-date ",\n"
- sy-reply-yank-from " said:\n"))
-
-(defun sy-header-inarticle-writes ()
- (insert-string "\nIn article " sy-reply-yank-message-id
- " " sy-reply-yank-from " writes:\n"))
-
-(defun sy-header-regarding-writes ()
- (insert-string "\nRegarding " sy-reply-yank-subject
- "; " sy-reply-yank-from " adds:\n"))
-
-(defun sy-header-verbose ()
- (insert-string "\nOn " sy-reply-yank-date ",\n"
- sy-reply-yank-from "\nfrom the organization "
- sy-reply-yank-organization "\nhad this to say about article "
- sy-reply-yank-message-id "\nin newsgroups "
- sy-reply-yank-newsgroups "\nconcerning "
- sy-reply-yank-subject "\nreferring to previous articles "
- sy-reply-yank-references "\n"))
-
-;;
-;; ----------------------------------------------------------------------
-;;
-;; yank the original article in and attribute
-;;
-(defun sy-yank-original (arg)
-
- "Insert the message being replied to, if any (in rmail/gnus). Puts
-point before the text and mark after. Calls generalized citation
-function sy-insert-citation to cite all allowable lines."
-
- (interactive "P")
- (if mail-reply-buffer
- (let* ((sy-confirm-always-p (if (consp arg)
- t
- sy-confirm-always-p))
- (attribution (sy-scan-rmail-for-names mail-reply-buffer))
- (top (point))
- (start (point))
- (end (progn (delete-windows-on mail-reply-buffer)
- (insert-buffer mail-reply-buffer)
- (mark))))
-
- (sy-yank-fields start)
- (sy-rewrite-headers start)
- (setq start (point))
- (mail-yank-clear-headers top (mark))
- (setq sy-persist-attribution (concat attribution " "))
- (sy-insert-citation start end attribution))
-
- (goto-char top)
- (exchange-point-and-mark)))
-
-
-;;
-;; ----------------------------------------------------------------------
-;;
-;; this is here for compatibility with existing mail/news yankers
-;; overloads the default mail-yank-original
-;;
-(defun mail-yank-original (arg)
-
- "Yank original message buffer into the reply buffer, citing as per
-user preferences. Numeric Argument forces confirmation.
-
-Here is a description of the superyank.el package, what it does and
-what variables control its operation. This was written by Barry
-Warsaw (warsaw@cme.nist.gov, {...}!uunet!cme-durer!warsaw).
-
-A 'Citation' is the acknowledgement of the original author of a mail
-message. There are two general forms of citation. In 'nested
-citations', indication is made that the cited line was written by
-someone *other* that the current message author (or by that author at
-an earlier time). No indication is made as to the identity of the
-original author. Thus, a nested citation after multiple replies would
-look like this (this is after my reply to a previous message):
-
->>John originally wrote this
->>and this as well
-> Jane said that John didn't know
-> what he was talking about
-And that's what I think as well.
-
-In non-nested citations, you won't see multiple \">\" characters at
-the beginning of the line. Non-nested citations will insert an
-informative string at the beginning of a cited line, attributing that
-line to an author. The same message described above might look like
-this if non-nested citations were used:
-
-John> John originally wrote this
-John> and this as well
-Jane> Jane said that John didn't know
-Jane> what he was talking about
-And that's what I think as well.
-
-Notice that my inclusion of Jane's inclusion of John's original
-message did not result in a cited line of the form: Jane>John>. Thus
-no nested citations. The style of citation is controlled by the
-variable `sy-nested-citation-p'. Nil uses non-nested citations and
-non-nil uses old style, nested citations.
-
-The variable `sy-citation-string' is the string to use as a marker for
-a citation, either nested or non-nested. For best results, this
-string should be a single character with no trailing space and is
-typically the character \">\". In non-nested citations this string is
-appended to the attribution string (author's name), along with a
-trailing space. In nested citations, a trailing space is only added
-to a first level citation.
-
-Another important variable is `sy-cite-regexp' which describes strings
-that indicate a previously cited line. This regular expression is
-always used at the beginning of a line so it doesn't need to begin
-with a \"^\" character. Change this variable if you change
-`sy-citation-string'.
-
-The following section only applies to non-nested citations.
-
-This package has a fair amount of intellegence related to deciphering
-the author's name based on information provided by the original
-message buffer. In normal operation, the program will pick out the
-author's first and last names, initials, terminal email address and
-any other names it can find. It will then pick an attribution string
-from this list based on a user defined preference and it will ask for
-confirmation if the user specifies. This package gathers its
-information from the `From:' line of the original message buffer. It
-recognizes From: lines with the following forms:
-
-From: John Xavier Doe <doe@speedy.computer.com>
-From: \"John Xavier Doe\" <doe@speedy.computer.com>
-From: doe@speedy.computer.com (John Xavier Doe)
-From: computer!speedy!doe (John Xavier Doe)
-From: computer!speedy!doe (John Xavier Doe)
-From: doe%speedy@computer.com (John Xavier Doe)
-
-In this case, if confirmation is requested, the following strings will
-be made available for completion and confirmation:
-
-\"John\"
-\"Xavier\"
-\"Doe\"
-\"JXD\"
-\"doe\"
-
-Note that completion is case sensitive. If there was a problem
-picking out a From: line, or any other problem getting even a single
-name, then the user will be queried for an attribution string. The
-default attribution string is set in the variable
-`sy-default-attribution'.
-
-Sometimes people set their name fields so that it also includes a
-title of the form:
-
-From: doe@speedy.computer.com (John Doe -- Hacker Extraordinaire)
-
-To avoid the inclusion of the string \"-- Hacker Extraordinaire\" in
-the name list, the variable `sy-titlecue-regexp' is provided. Its
-default setting will still properly recognize names of the form:
-
-From: xdoe@speedy.computer.com (John Xavier-Doe -- Crazed Hacker)
-
-The variable `sy-preferred-attribution' contains an integer that
-indicates which name field the user prefers to use as the attribution
-string, based on the following key:
-
-0: email address name is preferred
-1: initials are preferred
-2: first name is preferred
-3: last name is preferred
-
-The value can be greater than 3, in which case, you would be
-preferring the 2nd throught nth -1 name. In any case, if the
-preferred name can't be found, then one of two actions will be taken
-depending on the value of the variable `sy-use-only-preference-p'. If
-this is non-nil, then the `sy-default-attribution will be used. If it
-is nil, then a secondary scheme will be employed to find a suitable
-attribution scheme. First, the author's first name will be used. If
-that can't be found than the name list is searched for the first
-non-nil, non-empty name string. If still no name can be found, then
-the user is either queried, or the `sy-default-attribution' is used,
-depending on the value of `sy-confirm-always-p'.
-
-If the variable `sy-confirm-always-p' is non-nil, superyank will always
-confirm the attribution string with the user before inserting it into
-the reply buffer. Confirmation is with completion, but the completion
-list is merely a suggestion; the user can override the list by typing
-in a string of their choice.
-
-The variable `sy-rewrite-header-hook' is a hook that contains a lambda
-expression which rewrites the informative header at the top of the
-yanked message. Set to nil to avoid writing any header.
-
-You can make superyank autofill each paragraph it cites by setting the
-variable `sy-auto-fill-region-p' to non-nil. Or set the variable to nil
-and fill the paragraphs manually with sy-fill-paragraph-manually (see
-below).
-
-Finally, `sy-downcase-p' if non-nil, indicates that you always want to
-downcase the attribution string before insertion, and
-`sy-left-justify-p', if non-nil, indicates that you want to delete all
-leading white space before citing.
-
-Since the almost all yanking in other modes (RMAIL, GNUS) is done
-through the function `mail-yank-original', and since superyank
-overloads this function, cited yanking is automatically bound to the
-C-c C-y key. There are three other smaller functions that are
-provided with superyank and they are bound as below. Try C-h f on
-each function to get more information on these functions.
-
-Key Bindings:
-
-C-c C-y mail-yank-original (superyank's version)
-C-c q sy-fill-paragraph-manually
-C-c C-q sy-fill-paragraph-manually
-C-c i sy-insert-persist-attribution
-C-c C-i sy-insert-persist-attribution
-C-c C-o sy-open-line
-
-
-Summary of variables, with their default values:
-
-sy-default-attribution (default: \"Anon\")
- Attribution to use if no attribution string can be deciphered
- from the original message buffer.
-
-sy-citation-string (default: \">\")
- String to append to the attribution string for citation, for
- best results, it should be one character with no trailing space.
-
-sy-nested-citation-p (default: nil)
- Nil means use non-nested citations, non-nil means use old style
- nested citations.
-
-sy-cite-regexp (default: \"[a-zA-Z0-9]*>\")
- Regular expression that matches the beginning of a previously
- cited line. Always used at the beginning of a line so it does
- not need to start with a \"^\" character.
-
-sy-titlecue-regexp (default: \"\\s +-+\\s +\")
- Regular expression that matches a title delimiter in the name
- field.
-
-sy-preferred-attribution (default: 2)
- Integer indicating user's preferred attribution field.
-
-sy-confirm-always-p (default: t)
- Non-nil says always confirm with completion before inserting
- attribution.
-
-sy-rewrite-header-hook (default: 'sy-header-on-said)
- Hook for inserting informative header at the top of the yanked
- message.
-
-sy-downcase-p (default: nil)
- Non-nil says downcase the attribution string before insertion.
-
-sy-left-justify-p (default: nil)
- Non-nil says delete leading white space before citing.
-
-sy-auto-fill-region-p (default: nil)
- Non-nil says don't auto fill the region. T says auto fill the
- paragraph.
-
-sy-use-only-preference-p (default: nil)
- If nil, use backup scheme when preferred attribution string
- can't be found. If non-nil and preferred attribution string
- can't be found, then use sy-default-attribution."
-
- (interactive "P")
-
- (local-set-key "\C-cq" 'sy-fill-paragraph-manually)
- (local-set-key "\C-c\C-q" 'sy-fill-paragraph-manually)
- (local-set-key "\C-c\i" 'sy-insert-persist-attribution)
- (local-set-key "\C-c\C-i" 'sy-insert-persist-attribution)
- (local-set-key "\C-c\C-o" 'sy-open-line)
-
- (sy-yank-original arg))
-
-
-;;
-;; ----------------------------------------------------------------------
-;;
-;; based on Bruce Israel's "fill-paragraph-properly", and modified from
-;; code posted by David C. Lawrence. Modified to use the persistant
-;; attribution if none could be found from the paragraph.
-;;
-(defun sy-fill-paragraph-manually (arg)
- "Fill paragraph containing or following point, automatically finding
-the sy-cite-regexp and using it as the prefix. If the sy-cite-regexp
-is not in the first line of the paragraph, it makes a guess at what
-the fill-prefix for the paragraph should be by looking at the first
-line and taking anything up to the first alphanumeric character.
-
-Prefix arg means justify both sides of paragraph as well.
-
-This function just does fill-paragraph if the fill-prefix is set. If
-what it deduces to be the paragraph prefix (based on the first line)
-does not precede each line in the region, then the persistant
-attribution is used. The persistant attribution is just the last
-attribution string used to cite lines."
-
- (interactive "P")
- (save-excursion
- (forward-paragraph)
- (or (bolp)
- (newline 1))
-
- (let ((end (point))
- st
- (fill-prefix fill-prefix))
- (backward-paragraph)
- (if (looking-at "\n")
- (forward-char 1))
- (setq st (point))
- (if fill-prefix
- nil
- (untabify st end) ;; die, scurvy tabs!
- ;;
- ;; untabify might have made the paragraph longer character-wise,
- ;; make sure end reflects the correct location of eop.
- ;;
- (forward-paragraph)
- (setq end (point))
- (goto-char st)
- (if (looking-at sy-cite-regexp)
- (setq fill-prefix (concat
- (buffer-substring
- st (progn (re-search-forward sy-cite-regexp)
- (point)))
- " "))
- ;;
- ;; this regexp is is convenient because paragraphs quoted by simple
- ;; indentation must still yield to us <evil laugh>
- ;;
- (while (looking-at "[^a-zA-Z0-9]")
- (forward-char 1))
- (setq fill-prefix (buffer-substring st (point))))
- (next-line 1) (beginning-of-line)
- (while (and (< (point) end)
- (not (string-equal fill-prefix "")))
- ;;
- ;; if what we decided was the fill-prefix does not precede all
- ;; of the lines in the paragraph, we probably goofed. In this
- ;; case set it to the persistant attribution.
- ;;
- (if (looking-at (regexp-quote fill-prefix))
- ()
- (setq fill-prefix sy-persist-attribution))
- (next-line 1)
- (beginning-of-line)))
- (fill-region-as-paragraph st end arg))))
-
-;;
-;; ----------------------------------------------------------------------
-;;
-;; insert the persistant attribution at point
-;;
-(defun sy-insert-persist-attribution ()
- "Insert the persistant attribution at the beginning of the line that
-point is on. This string is the last attribution confirmed and used
-in the yanked reply buffer."
- (interactive)
- (save-excursion
- (beginning-of-line)
- (insert-string sy-persist-attribution)))
-
-
-;;
-;; ----------------------------------------------------------------------
-;;
-;; open a line putting the attribution at the beginning
-
-(defun sy-open-line (arg)
- "Insert a newline and leave point before it. Also inserts the
-persistant attribution at the beginning of the line. With arg,
-inserts that many newlines."
- (interactive "p")
- (save-excursion
- (let ((start (point)))
- (open-line arg)
- (goto-char start)
- (forward-line)
- (while (< 0 arg)
- (sy-insert-persist-attribution)
- (forward-line 1)
- (setq arg (- arg 1))))))
-
diff --git a/lisp/tabify.elc b/lisp/tabify.elc
new file mode 100644
index 00000000000..068065efb54
--- /dev/null
+++ b/lisp/tabify.elc
Binary files differ
diff --git a/lisp/tags.el b/lisp/tags.el
new file mode 100644
index 00000000000..2cef30ae2da
--- /dev/null
+++ b/lisp/tags.el
@@ -0,0 +1,304 @@
+;; Tags facility for Emacs.
+;; Copyright (C) 1985, 1986, 1988 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 1, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+(provide 'tags)
+
+(defvar tag-table-files nil
+ "List of file names covered by current tag table.
+nil means it has not been computed yet; do (tag-table-files) to compute it.")
+
+(defvar last-tag nil
+ "Tag found by the last find-tag.")
+
+(defun visit-tags-table (file)
+ "Tell tags commands to use tag table file FILE.
+FILE should be the name of a file created with the `etags' program.
+A directory name is ok too; it means file TAGS in that directory."
+ (interactive (list (read-file-name "Visit tags table: (default TAGS) "
+ default-directory
+ (concat default-directory "TAGS")
+ t)))
+ (setq file (expand-file-name file))
+ (if (file-directory-p file)
+ (setq file (concat file "TAGS")))
+ (setq tag-table-files nil
+ tags-file-name file))
+
+(defun visit-tags-table-buffer ()
+ "Select the buffer containing the current tag table.
+This is a file whose name is in the variable tags-file-name."
+ (or tags-file-name
+ (call-interactively 'visit-tags-table))
+ (set-buffer (or (get-file-buffer tags-file-name)
+ (progn
+ (setq tag-table-files nil)
+ (find-file-noselect tags-file-name))))
+ (setq tags-file-name buffer-file-name)
+ (or (verify-visited-file-modtime (get-file-buffer tags-file-name))
+ (cond ((yes-or-no-p "Tags file has changed, read new contents? ")
+ (revert-buffer t t)
+ (setq tag-table-files nil))))
+ (or (eq (char-after 1) ?\^L)
+ (error "File %s not a valid tag table" tags-file-name)))
+
+(defun file-of-tag ()
+ "Return the file name of the file whose tags point is within.
+Assumes the tag table is the current buffer.
+File name returned is relative to tag table file's directory."
+ (let ((opoint (point))
+ prev size)
+ (save-excursion
+ (goto-char (point-min))
+ (while (< (point) opoint)
+ (forward-line 1)
+ (end-of-line)
+ (skip-chars-backward "^,\n")
+ (setq prev (point))
+ (setq size (read (current-buffer)))
+ (goto-char prev)
+ (forward-line 1)
+ (forward-char size))
+ (goto-char (1- prev))
+ (buffer-substring (point)
+ (progn (beginning-of-line) (point))))))
+
+(defun tag-table-files ()
+ "Return a list of files in the current tag table.
+File names returned are absolute."
+ (save-excursion
+ (visit-tags-table-buffer)
+ (or tag-table-files
+ (let (files)
+ (goto-char (point-min))
+ (while (not (eobp))
+ (forward-line 1)
+ (end-of-line)
+ (skip-chars-backward "^,\n")
+ (setq prev (point))
+ (setq size (read (current-buffer)))
+ (goto-char prev)
+ (setq files (cons (expand-file-name
+ (buffer-substring (1- (point))
+ (save-excursion
+ (beginning-of-line)
+ (point)))
+ (file-name-directory tags-file-name))
+ files))
+ (forward-line 1)
+ (forward-char size))
+ (setq tag-table-files (nreverse files))))))
+
+;; Return a default tag to search for, based on the text at point.
+(defun find-tag-default ()
+ (save-excursion
+ (while (looking-at "\\sw\\|\\s_")
+ (forward-char 1))
+ (if (re-search-backward "\\sw\\|\\s_" nil t)
+ (progn (forward-char 1)
+ (buffer-substring (point)
+ (progn (forward-sexp -1)
+ (while (looking-at "\\s'")
+ (forward-char 1))
+ (point))))
+ nil)))
+
+(defun find-tag-tag (string)
+ (let* ((default (find-tag-default))
+ (spec (read-string
+ (if default
+ (format "%s(default %s) " string default)
+ string))))
+ (list (if (equal spec "")
+ default
+ spec))))
+
+(defun find-tag (tagname &optional next other-window)
+ "Find tag (in current tag table) whose name contains TAGNAME.
+ Selects the buffer that the tag is contained in
+and puts point at its definition.
+ If TAGNAME is a null string, the expression in the buffer
+around or before point is used as the tag name.
+ If second arg NEXT is non-nil (interactively, with prefix arg),
+searches for the next tag in the tag table
+that matches the tagname used in the previous find-tag.
+
+See documentation of variable tags-file-name."
+ (interactive (if current-prefix-arg
+ '(nil t)
+ (find-tag-tag "Find tag: ")))
+ (let (buffer file linebeg startpos)
+ (save-excursion
+ (visit-tags-table-buffer)
+ (if (not next)
+ (goto-char (point-min))
+ (setq tagname last-tag))
+ (setq last-tag tagname)
+ (while (progn
+ (if (not (search-forward tagname nil t))
+ (error "No %sentries containing %s"
+ (if next "more " "") tagname))
+ (not (looking-at "[^\n\177]*\177"))))
+ (search-forward "\177")
+ (setq file (expand-file-name (file-of-tag)
+ (file-name-directory tags-file-name)))
+ (setq linebeg
+ (buffer-substring (1- (point))
+ (save-excursion (beginning-of-line) (point))))
+ (search-forward ",")
+ (setq startpos (read (current-buffer))))
+ (if other-window
+ (find-file-other-window file)
+ (find-file file))
+ (widen)
+ (push-mark)
+ (let ((offset 1000)
+ found
+ (pat (concat "^" (regexp-quote linebeg))))
+ (or startpos (setq startpos (point-min)))
+ (while (and (not found)
+ (progn
+ (goto-char (- startpos offset))
+ (not (bobp))))
+ (setq found
+ (re-search-forward pat (+ startpos offset) t))
+ (setq offset (* 3 offset)))
+ (or found
+ (re-search-forward pat nil t)
+ (error "%s not found in %s" pat file)))
+ (beginning-of-line))
+ (setq tags-loop-form '(find-tag nil t))
+ ;; Return t in case used as the tags-loop-form.
+ t)
+
+(defun find-tag-other-window (tagname &optional next)
+ "Find tag (in current tag table) whose name contains TAGNAME.
+ Selects the buffer that the tag is contained in in another window
+and puts point at its definition.
+ If TAGNAME is a null string, the expression in the buffer
+around or before point is used as the tag name.
+ If second arg NEXT is non-nil (interactively, with prefix arg),
+searches for the next tag in the tag table
+that matches the tagname used in the previous find-tag.
+
+See documentation of variable tags-file-name."
+ (interactive (if current-prefix-arg
+ '(nil t)
+ (find-tag-tag "Find tag other window: ")))
+ (find-tag tagname next t))
+
+(defvar next-file-list nil
+ "List of files for next-file to process.")
+
+(defun next-file (&optional initialize)
+ "Select next file among files in current tag table.
+Non-nil argument (prefix arg, if interactive)
+initializes to the beginning of the list of files in the tag table."
+ (interactive "P")
+ (if initialize
+ (setq next-file-list (tag-table-files)))
+ (or next-file-list
+ (error "All files processed."))
+ (find-file (car next-file-list))
+ (setq next-file-list (cdr next-file-list)))
+
+(defvar tags-loop-form nil
+ "Form for tags-loop-continue to eval to process one file.
+If it returns nil, it is through with one file; move on to next.")
+
+(defun tags-loop-continue (&optional first-time)
+ "Continue last \\[tags-search] or \\[tags-query-replace] command.
+Used noninteractively with non-nil argument
+to begin such a command. See variable tags-loop-form."
+ (interactive)
+ (if first-time
+ (progn (next-file t)
+ (goto-char (point-min))))
+ (while (not (eval tags-loop-form))
+ (next-file)
+ (message "Scanning file %s..." buffer-file-name)
+ (goto-char (point-min))))
+
+(defun tags-search (regexp)
+ "Search through all files listed in tag table for match for REGEXP.
+Stops when a match is found.
+To continue searching for next match, use command \\[tags-loop-continue].
+
+See documentation of variable tags-file-name."
+ (interactive "sTags search (regexp): ")
+ (if (and (equal regexp "")
+ (eq (car tags-loop-form) 're-search-forward))
+ (tags-loop-continue nil)
+ (setq tags-loop-form
+ (list 're-search-forward regexp nil t))
+ (tags-loop-continue t)))
+
+(defun tags-query-replace (from to &optional delimited)
+ "Query-replace-regexp FROM with TO through all files listed in tag table.
+Third arg DELIMITED (prefix arg) means replace only word-delimited matches.
+If you exit (C-G or ESC), you can resume the query-replace
+with the command \\[tags-loop-continue].
+
+See documentation of variable tags-file-name."
+ (interactive "sTags query replace (regexp): \nsTags query replace %s by: \nP")
+ (setq tags-loop-form
+ (list 'and (list 'save-excursion
+ (list 're-search-forward from nil t))
+ (list 'not (list 'perform-replace from to t t
+ (not (null delimited))))))
+ (tags-loop-continue t))
+
+(defun list-tags (string)
+ "Display list of tags in file FILE.
+FILE should not contain a directory spec
+unless it has one in the tag table."
+ (interactive "sList tags (in file): ")
+ (with-output-to-temp-buffer "*Tags List*"
+ (princ "Tags in file ")
+ (princ string)
+ (terpri)
+ (save-excursion
+ (visit-tags-table-buffer)
+ (goto-char 1)
+ (search-forward (concat "\f\n" string ","))
+ (forward-line 1)
+ (while (not (or (eobp) (looking-at "\f")))
+ (princ (buffer-substring (point)
+ (progn (skip-chars-forward "^\177")
+ (point))))
+ (terpri)
+ (forward-line 1)))))
+
+(defun tags-apropos (string)
+ "Display list of all tags in tag table REGEXP matches."
+ (interactive "sTag apropos (regexp): ")
+ (with-output-to-temp-buffer "*Tags List*"
+ (princ "Tags matching regexp ")
+ (prin1 string)
+ (terpri)
+ (save-excursion
+ (visit-tags-table-buffer)
+ (goto-char 1)
+ (while (re-search-forward string nil t)
+ (beginning-of-line)
+ (princ (buffer-substring (point)
+ (progn (skip-chars-forward "^\177")
+ (point))))
+ (terpri)
+ (forward-line 1)))))
diff --git a/lisp/tags.elc b/lisp/tags.elc
new file mode 100644
index 00000000000..fcef3bd5e3d
--- /dev/null
+++ b/lisp/tags.elc
Binary files differ
diff --git a/lisp/tar-mode.el b/lisp/tar-mode.el
deleted file mode 100644
index c690385064a..00000000000
--- a/lisp/tar-mode.el
+++ /dev/null
@@ -1,1117 +0,0 @@
-;;; -*- Mode: Emacs-Lisp -*-
-
-;;; File: tar-mode.el
-;;; Description: simple editing of tar files from GNU emacs
-;;; Author: Jamie Zawinski <jwz@lucid.com>
-;;; Created: 4 Apr 1990
-;;; Version: 1.21, 10 Mar 91
-
-;;; Copyright (C) 1990, 1991 Free Software Foundation, Inc.
-;;;
-;;; This file is part of GNU Emacs.
-;;;
-;;; GNU Emacs is free software; you can redistribute it and/or modify
-;;; it under the terms of the GNU General Public License as published by
-;;; the Free Software Foundation; either version 1, or (at your option)
-;;; any later version.
-;;;
-;;; GNU Emacs is distributed in the hope that it will be useful,
-;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;;; GNU General Public License for more details.
-;;;
-;;; You should have received a copy of the GNU General Public License
-;;; along with GNU Emacs; see the file COPYING. If not, write to
-;;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
-;;; This package attempts to make dealing with Unix 'tar' archives easier.
-;;; When this code is loaded, visiting a file whose name ends in '.tar' will
-;;; cause the contents of that archive file to be displayed in a Dired-like
-;;; listing. It is then possible to use the customary Dired keybindings to
-;;; extract sub-files from that archive, either by reading them into their own
-;;; editor buffers, or by copying them directly to arbitrary files on disk.
-;;; It is also possible to delete sub-files from within the tar file and write
-;;; the modified archive back to disk, or to edit sub-files within the archive
-;;; and re-insert the modified files into the archive. See the documentation
-;;; string of tar-mode for more info.
-
-;;; To autoload, add this to your .emacs file:
-;;;
-;;; (setq auto-mode-alist (cons '("\\.tar$" . tar-mode) auto-mode-alist))
-;;; (autoload 'tar-mode "tar-mode")
-;;;
-;;; But beware: for certain tar files - those whose very first file has
-;;; a -*- property line - autoloading won't work. See the function
-;;; "tar-normal-mode" to understand why.
-
-;;; This code now understands the extra fields that GNU tar adds to tar files.
-
-;;; This interacts correctly with "uncompress.el" in the Emacs library,
-;;; which you get with
-;;;
-;;; (autoload 'uncompress-while-visiting "uncompress")
-;;; (setq auto-mode-alist (cons '("\\.Z$" . uncompress-while-visiting)
-;;; auto-mode-alist))
-;;;
-;;; Do not attempt to use tar-mode.el with crypt.el, you will lose.
-
-;;; *************** TO DO ***************
-;;;
-;;; o chmod should understand "a+x,og-w".
-;;;
-;;; o It's not possible to add a NEW file to a tar archive; not that
-;;; important, but still...
-;;;
-;;; o In the directory listing, we don't show creation times because I don't
-;;; know how to print an arbitrary date, and I don't really want to have to
-;;; implement decode-universal-time.
-;;;
-;;; o There's code to update the datestamp of edited subfiles, but we set it
-;;; to zero because I don't know how to get the current time as an integer.
-;;;
-;;; o The code is less efficient that it could be - in a lot of places, I
-;;; pull a 512-character string out of the buffer and parse it, when I could
-;;; be parsing it in place, not garbaging a string. Should redo that.
-;;;
-;;; o I'd like a command that searches for a string/regexp in every subfile
-;;; of an archive, where <esc> would leave you in a subfile-edit buffer.
-;;; (Like the Meta-R command of the Zmacs mail reader.)
-;;;
-;;; o Sometimes (but not always) reverting the tar-file buffer does not
-;;; re-grind the listing, and you are staring at the binary tar data.
-;;; Typing 'g' again immediately after that will always revert and re-grind
-;;; it, though. I have no idea why this happens.
-;;;
-;;; o Tar-mode interacts poorly with crypt.el and zcat.el because the tar
-;;; write-file-hook actually writes the file. Instead it should remove the
-;;; header (and conspire to put it back afterwards) so that other write-file
-;;; hooks which frob the buffer have a chance to do their dirty work. There
-;;; might be a problem if the tar write-file-hook does not come *first* on
-;;; the list.
-;;;
-;;; o Block files, sparse files, continuation files, and the various header
-;;; types aren't editable. Actually I don't know that they work at all.
-
-(defvar tar-anal-blocksize 20
- "*The blocksize of tar files written by Emacs, or nil, meaning don't care.
-The blocksize of a tar file is not really the size of the blocks; rather, it is
-the number of blocks written with one system call. When tarring to a tape,
-this is the size of the *tape* blocks, but when writing to a file, it doesn't
-matter much. The only noticeable difference is that if a tar file does not
-have a blocksize of 20, tar will tell you that; all this really controls is
-how many null padding bytes go on the end of the tar file.")
-
-(defvar tar-update-datestamp nil
- "*Whether tar-mode should play fast and loose with sub-file datestamps;
-if this is true, then editing and saving a tar file entry back into its
-tar file will update its datestamp. If false, the datestamp is unchanged.
-You may or may not want this - it is good in that you can tell when a file
-in a tar archive has been changed, but it is bad for the same reason that
-editing a file in the tar archive at all is bad - the changed version of
-the file never exists on disk.
-
-## This doesn't work yet because there's no way to get the current time as
-## an integer - if this var is true, then editing a file sets its date to
-## December 31, 1969 (which happens to be what 0 encodes).")
-
-
-
-;;; First, duplicate some Common Lisp functions; I used to just (require 'cl)
-;;; but "cl.el" was messing some people up (also it's really big).
-
-(defmacro tar-setf (form val)
- "A mind-numbingly simple implementation of setf."
- (let ((mform (macroexpand form (and (boundp 'byte-compile-macro-environment)
- byte-compile-macro-environment))))
- (cond ((symbolp mform) (list 'setq mform val))
- ((not (consp mform)) (error "can't setf %s" form))
- ((eq (car mform) 'aref)
- (list 'aset (nth 1 mform) (nth 2 mform) val))
- ((eq (car mform) 'car)
- (list 'setcar (nth 1 mform) val))
- ((eq (car mform) 'cdr)
- (list 'setcdr (nth 1 mform) val))
- (t (error "don't know how to setf %s" form)))))
-
-(defmacro tar-dolist (control &rest body)
- "syntax: (dolist (var-name list-expr &optional return-value) &body body)"
- (let ((var (car control))
- (init (car (cdr control)))
- (val (car (cdr (cdr control)))))
- (list 'let (list (list '_dolist_iterator_ init))
- (list 'while '_dolist_iterator_
- (cons 'let
- (cons (list (list var '(car _dolist_iterator_)))
- (append body
- (list (list 'setq '_dolist_iterator_
- (list 'cdr '_dolist_iterator_)))))))
- val)))
-
-(defmacro tar-dotimes (control &rest body)
- "syntax: (dolist (var-name count-expr &optional return-value) &body body)"
- (let ((var (car control))
- (n (car (cdr control)))
- (val (car (cdr (cdr control)))))
- (list 'let (list (list '_dotimes_end_ n)
- (list var 0))
- (cons 'while
- (cons (list '< var '_dotimes_end_)
- (append body
- (list (list 'setq var (list '1+ var))))))
- val)))
-
-
-;;; down to business.
-
-(defmacro make-tar-header (name mode uid git size date ck lt ln
- magic uname gname devmaj devmin)
- (list 'vector name mode uid git size date ck lt ln
- magic uname gname devmaj devmin))
-
-(defmacro tar-header-name (x) (list 'aref x 0))
-(defmacro tar-header-mode (x) (list 'aref x 1))
-(defmacro tar-header-uid (x) (list 'aref x 2))
-(defmacro tar-header-gid (x) (list 'aref x 3))
-(defmacro tar-header-size (x) (list 'aref x 4))
-(defmacro tar-header-date (x) (list 'aref x 5))
-(defmacro tar-header-checksum (x) (list 'aref x 6))
-(defmacro tar-header-link-type (x) (list 'aref x 7))
-(defmacro tar-header-link-name (x) (list 'aref x 8))
-(defmacro tar-header-magic (x) (list 'aref x 9))
-(defmacro tar-header-uname (x) (list 'aref x 10))
-(defmacro tar-header-gname (x) (list 'aref x 11))
-(defmacro tar-header-dmaj (x) (list 'aref x 12))
-(defmacro tar-header-dmin (x) (list 'aref x 13))
-
-(defmacro make-tar-desc (data-start tokens)
- (list 'cons data-start tokens))
-
-(defmacro tar-desc-data-start (x) (list 'car x))
-(defmacro tar-desc-tokens (x) (list 'cdr x))
-
-(defconst tar-name-offset 0)
-(defconst tar-mode-offset (+ tar-name-offset 100))
-(defconst tar-uid-offset (+ tar-mode-offset 8))
-(defconst tar-gid-offset (+ tar-uid-offset 8))
-(defconst tar-size-offset (+ tar-gid-offset 8))
-(defconst tar-time-offset (+ tar-size-offset 12))
-(defconst tar-chk-offset (+ tar-time-offset 12))
-(defconst tar-linkp-offset (+ tar-chk-offset 8))
-(defconst tar-link-offset (+ tar-linkp-offset 1))
-;;; GNU-tar specific slots.
-(defconst tar-magic-offset (+ tar-link-offset 100))
-(defconst tar-uname-offset (+ tar-magic-offset 8))
-(defconst tar-gname-offset (+ tar-uname-offset 32))
-(defconst tar-dmaj-offset (+ tar-gname-offset 32))
-(defconst tar-dmin-offset (+ tar-dmaj-offset 8))
-(defconst tar-end-offset (+ tar-dmin-offset 8))
-
-(defun tokenize-tar-header-block (string)
- "Returns a 'tar-header' structure (a list of name, mode, uid, gid, size,
-write-date, checksum, link-type, and link-name)."
- (cond ((< (length string) 512) nil)
- (;(some 'plusp string) ; <-- oops, massive cycle hog!
- (or (not (= 0 (aref string 0))) ; This will do.
- (not (= 0 (aref string 101))))
- (let* ((name-end (1- tar-mode-offset))
- (link-end (1- tar-magic-offset))
- (uname-end (1- tar-gname-offset))
- (gname-end (1- tar-dmaj-offset))
- (link-p (aref string tar-linkp-offset))
- (magic-str (substring string tar-magic-offset (1- tar-uname-offset)))
- (uname-valid-p (or (string= "ustar " magic-str) (string= "GNUtar " magic-str)))
- name
- (nulsexp "[^\000]*\000"))
- (and (string-match nulsexp string tar-name-offset) (setq name-end (min name-end (1- (match-end 0)))))
- (and (string-match nulsexp string tar-link-offset) (setq link-end (min link-end (1- (match-end 0)))))
- (and (string-match nulsexp string tar-uname-offset) (setq uname-end (min uname-end (1- (match-end 0)))))
- (and (string-match nulsexp string tar-gname-offset) (setq gname-end (min gname-end (1- (match-end 0)))))
- (setq name (substring string tar-name-offset name-end)
- link-p (if (or (= link-p 0) (= link-p ?0))
- nil
- (- link-p ?0)))
- (if (and (null link-p) (string-match "/$" name)) (setq link-p 5)) ; directory
- (make-tar-header
- name
- (tar-parse-octal-integer string tar-mode-offset (1- tar-uid-offset))
- (tar-parse-octal-integer string tar-uid-offset (1- tar-gid-offset))
- (tar-parse-octal-integer string tar-gid-offset (1- tar-size-offset))
- (tar-parse-octal-integer string tar-size-offset (1- tar-time-offset))
- (tar-parse-octal-integer string tar-time-offset (1- tar-chk-offset))
- (tar-parse-octal-integer string tar-chk-offset (1- tar-linkp-offset))
- link-p
- (substring string tar-link-offset link-end)
- uname-valid-p
- (and uname-valid-p (substring string tar-uname-offset uname-end))
- (and uname-valid-p (substring string tar-gname-offset gname-end))
- (tar-parse-octal-integer string tar-dmaj-offset (1- tar-dmin-offset))
- (tar-parse-octal-integer string tar-dmin-offset (1- tar-end-offset))
- )))
- (t 'empty-tar-block)))
-
-
-(defun tar-parse-octal-integer (string &optional start end)
- "deletes all your files, and then reboots."
- (if (null start) (setq start 0))
- (if (null end) (setq end (length string)))
- (if (= (aref string start) 0)
- 0
- (let ((n 0))
- (while (< start end)
- (setq n (if (< (aref string start) ?0) n
- (+ (* n 8) (- (aref string start) 48)))
- start (1+ start)))
- n)))
-
-(defun tar-parse-octal-integer-safe (string)
- (let ((L (length string)))
- (if (= L 0) (error "empty string"))
- (tar-dotimes (i L)
- (if (or (< (aref string i) ?0)
- (> (aref string i) ?7))
- (error "'%c' is not an octal digit."))))
- (tar-parse-octal-integer string))
-
-
-(defun checksum-tar-header-block (string)
- "Computes and returns a tar-acceptable checksum for this block."
- (let* ((chk-field-start tar-chk-offset)
- (chk-field-end (+ chk-field-start 8))
- (sum 0)
- (i 0))
- ;; Add up all of the characters except the ones in the checksum field.
- ;; Add that field as if it were filled with spaces.
- (while (< i chk-field-start)
- (setq sum (+ sum (aref string i))
- i (1+ i)))
- (setq i chk-field-end)
- (while (< i 512)
- (setq sum (+ sum (aref string i))
- i (1+ i)))
- (+ sum (* 32 8))))
-
-(defun check-tar-header-block-checksum (hblock desired-checksum file-name)
- "Beep and print a warning if the checksum doesn't match."
- (if (not (= desired-checksum (checksum-tar-header-block hblock)))
- (progn (beep) (message "Invalid checksum for file %s!" file-name))))
-
-(defun recompute-tar-header-block-checksum (hblock)
- "Modifies the given string to have a valid checksum field."
- (let* ((chk (checksum-tar-header-block hblock))
- (chk-string (format "%6o" chk))
- (l (length chk-string)))
- (aset hblock 154 0)
- (aset hblock 155 32)
- (tar-dotimes (i l) (aset hblock (- 153 i) (aref chk-string (- l i 1)))))
- hblock)
-
-
-(defun tar-grind-file-mode (mode string start)
- "Write a \"-rw--r--r-\" representing MODE into STRING beginning at START."
- (aset string start (if (zerop (logand 256 mode)) ?- ?r))
- (aset string (+ start 1) (if (zerop (logand 128 mode)) ?- ?w))
- (aset string (+ start 2) (if (zerop (logand 64 mode)) ?- ?x))
- (aset string (+ start 3) (if (zerop (logand 32 mode)) ?- ?r))
- (aset string (+ start 4) (if (zerop (logand 16 mode)) ?- ?w))
- (aset string (+ start 5) (if (zerop (logand 8 mode)) ?- ?x))
- (aset string (+ start 6) (if (zerop (logand 4 mode)) ?- ?r))
- (aset string (+ start 7) (if (zerop (logand 2 mode)) ?- ?w))
- (aset string (+ start 8) (if (zerop (logand 1 mode)) ?- ?x))
- (if (zerop (logand 1024 mode)) nil (aset string (+ start 2) ?s))
- (if (zerop (logand 2048 mode)) nil (aset string (+ start 5) ?s))
- string)
-
-(defun summarize-tar-header-block (tar-hblock &optional mod-p)
- "Returns a line similar to the output of 'tar -vtf'."
- (let ((name (tar-header-name tar-hblock))
- (mode (tar-header-mode tar-hblock))
- (uid (tar-header-uid tar-hblock))
- (gid (tar-header-gid tar-hblock))
- (uname (tar-header-uname tar-hblock))
- (gname (tar-header-gname tar-hblock))
- (size (tar-header-size tar-hblock))
- (time (tar-header-date tar-hblock))
- (ck (tar-header-checksum tar-hblock))
- (link-p (tar-header-link-type tar-hblock))
- (link-name (tar-header-link-name tar-hblock))
- )
- (let* ((left 11)
- (namew 8)
- (groupw 8)
- (sizew 8)
- (datew 2)
- (slash (1- (+ left namew)))
- (lastdigit (+ slash groupw sizew))
- (namestart (+ lastdigit datew))
- (string (make-string (+ namestart (length name) (if link-p (+ 5 (length link-name)) 0)) 32))
- (type (tar-header-link-type tar-hblock)))
- (aset string 0 (if mod-p ?* ? ))
- (aset string 1
- (cond ((or (eq type nil) (eq type 0)) ?-)
- ((eq type 1) ?l) ; link
- ((eq type 2) ?s) ; symlink
- ((eq type 3) ?c) ; char special
- ((eq type 4) ?b) ; block special
- ((eq type 5) ?d) ; directory
- ((eq type 6) ?p) ; FIFO/pipe
- ((eq type 20) ?*) ; directory listing
- ((eq type 29) ?M) ; multivolume continuation
- ((eq type 35) ?S) ; sparse
- ((eq type 38) ?V) ; volume header
- ))
- (tar-grind-file-mode mode string 2)
- (setq uid (if (= 0 (length uname)) (int-to-string uid) uname))
- (setq gid (if (= 0 (length gname)) (int-to-string gid) gname))
- (setq size (int-to-string size))
- (tar-dotimes (i (min (1- namew) (length uid))) (aset string (- slash i) (aref uid (- (length uid) i 1))))
- (aset string (1+ slash) ?/)
- (tar-dotimes (i (min (1- groupw) (length gid))) (aset string (+ (+ slash 2) i) (aref gid i)))
- (tar-dotimes (i (min sizew (length size))) (aset string (- lastdigit i) (aref size (- (length size) i 1))))
- ;; ## bloody hell, how do I print an arbitrary date??
- (tar-dotimes (i (length name)) (aset string (+ namestart i) (aref name i)))
- (if (or (eq link-p 1) (eq link-p 2))
- (progn
- (tar-dotimes (i 3) (aset string (+ namestart 1 (length name) i) (aref (if (= link-p 1) "==>" "-->") i)))
- (tar-dotimes (i (length link-name)) (aset string (+ namestart 5 (length name) i) (aref link-name i)))))
- string)))
-
-
-(defun tar-summarize-buffer ()
- "Parse the contents of the tar file in the current buffer, and place a
-dired-like listing on the front; then narrow to it, so that only that listing
-is visible (and the real data of the buffer is hidden)."
- (message "parsing tar file...")
- (let* ((result '())
- (pos 1)
- (bs (max 1 (- (buffer-size) 1024))) ; always 2+ empty blocks at end.
- (bs100 (max 1 (/ bs 100)))
- (tokens nil))
- (while (not (eq tokens 'empty-tar-block))
- (let* ((hblock (buffer-substring pos (+ pos 512))))
- (setq tokens (tokenize-tar-header-block hblock))
- (setq pos (+ pos 512))
- (message "parsing tar file...%s%%"
- ;(/ (* pos 100) bs) ; this gets round-off lossage
- (/ pos bs100) ; this doesn't
- )
- (if (eq tokens 'empty-tar-block)
- nil
- (if (null tokens) (error "premature EOF parsing tar file."))
- (if (eq (tar-header-link-type tokens) 20)
- ;; Foo. There's an extra empty block after these.
- (setq pos (+ pos 512)))
- (let ((size (tar-header-size tokens)))
- (if (< size 0)
- (error "%s has size %s - corrupted."
- (tar-header-name tokens) size))
- ;
- ; This is just too slow. Don't really need it anyway....
- ;(check-tar-header-block-checksum
- ; hblock (checksum-tar-header-block hblock)
- ; (tar-header-name tokens))
-
- (setq result (cons (make-tar-desc pos tokens) result))
-
- (if (and (null (tar-header-link-type tokens))
- (> size 0))
- (setq pos
- (+ pos 512 (ash (ash (1- size) -9) 9)) ; this works
- ;(+ pos (+ size (- 512 (rem (1- size) 512)))) ; this doesn't
- ))
- ))))
- (make-local-variable 'tar-parse-info)
- (setq tar-parse-info (nreverse result)))
- (save-excursion
- (goto-char (point-min))
- (let ((buffer-read-only nil))
- (tar-dolist (tar-desc tar-parse-info)
- (insert-string
- (summarize-tar-header-block (tar-desc-tokens tar-desc)))
- (insert-string "\n"))
- (make-local-variable 'tar-header-offset)
- (setq tar-header-offset (point))
- (narrow-to-region 1 tar-header-offset)
- (set-buffer-modified-p nil)))
- (message "parsing tar file...done."))
-
-
-(defvar tar-mode-map nil "*Local keymap for tar-mode listings.")
-
-(if tar-mode-map
- nil
- (setq tar-mode-map (make-keymap))
- (suppress-keymap tar-mode-map)
- (define-key tar-mode-map " " 'tar-next-line)
- (define-key tar-mode-map "c" 'tar-copy)
- (define-key tar-mode-map "d" 'tar-flag-deleted)
- (define-key tar-mode-map "\^D" 'tar-flag-deleted)
- (define-key tar-mode-map "e" 'tar-extract)
- (define-key tar-mode-map "f" 'tar-extract)
- (define-key tar-mode-map "g" 'revert-buffer)
- (define-key tar-mode-map "h" 'describe-mode)
- (define-key tar-mode-map "n" 'tar-next-line)
- (define-key tar-mode-map "\^N" 'tar-next-line)
- (define-key tar-mode-map "o" 'tar-extract-other-window)
- (define-key tar-mode-map "\^C" 'tar-copy)
- (define-key tar-mode-map "p" 'tar-previous-line)
- (define-key tar-mode-map "\^P" 'tar-previous-line)
- (define-key tar-mode-map "r" 'tar-rename-entry)
- (define-key tar-mode-map "u" 'tar-unflag)
- (define-key tar-mode-map "v" 'tar-view)
- (define-key tar-mode-map "x" 'tar-expunge)
- (define-key tar-mode-map "\177" 'tar-unflag-backwards)
- (define-key tar-mode-map "E" 'tar-extract-other-window)
- (define-key tar-mode-map "M" 'tar-chmod-entry)
- (define-key tar-mode-map "G" 'tar-chgrp-entry)
- (define-key tar-mode-map "O" 'tar-chown-entry)
- )
-
-;; tar mode is suitable only for specially formatted data.
-(put 'tar-mode 'mode-class 'special)
-(put 'tar-subfile-mode 'mode-class 'special)
-
-(defun tar-mode ()
- "Major mode for viewing a tar file as a dired-like listing of its contents.
-You can move around using the usual cursor motion commands.
-Letters no longer insert themselves.
-Type 'e' to pull a file out of the tar file and into its own buffer.
-Type 'c' to copy an entry from the tar file into another file on disk.
-
-If you edit a sub-file of this archive (as with the 'e' command) and
-save it with Control-X Control-S, the contents of that buffer will be
-saved back into the tar-file buffer; in this way you can edit a file
-inside of a tar archive without extracting it and re-archiving it.
-
-See also: variables tar-update-datestamp and tar-anal-blocksize.
-\\{tar-mode-map}"
- ;; this is not interactive because you shouldn't be turning this
- ;; mode on and off. You can corrupt things that way.
- (make-local-variable 'tar-header-offset)
- (make-local-variable 'tar-parse-info)
- (make-local-variable 'require-final-newline)
- (setq require-final-newline nil) ; binary data, dude...
- (make-local-variable 'revert-buffer-function)
- (setq revert-buffer-function 'tar-mode-revert)
- (setq major-mode 'tar-mode)
- (setq mode-name "Tar")
- (use-local-map tar-mode-map)
- (auto-save-mode 0)
- (widen)
- (if (and (boundp 'tar-header-offset) tar-header-offset)
- (narrow-to-region 1 tar-header-offset)
- (tar-summarize-buffer))
- (run-hooks 'tar-mode-hook)
- )
-
-
-(defun tar-subfile-mode (p)
- "Minor mode for editing an element of a tar-file.
-This mode redefines ^X^S to save the current buffer back into its
-associated tar-file buffer. You must save that buffer to actually
-save your changes to disk."
- (interactive "P")
- (or (and (boundp 'superior-tar-buffer) superior-tar-buffer)
- (error "This buffer is not an element of a tar file."))
- (or (assq 'tar-subfile-mode minor-mode-alist)
- (setq minor-mode-alist (append minor-mode-alist
- (list '(tar-subfile-mode
- " TarFile")))))
- (make-local-variable 'tar-subfile-mode)
- (setq tar-subfile-mode
- (if (null p)
- (not tar-subfile-mode)
- (> (prefix-numeric-value p) 0)))
- (cond (tar-subfile-mode
- ;; copy the local keymap so that we don't accidentally
- ;; alter a keymap like 'lisp-mode-map' which is shared
- ;; by all buffers in that mode.
- (let ((m (current-local-map)))
- (if m (use-local-map (copy-keymap m))))
- (local-set-key "\^X\^S" 'tar-subfile-save-buffer)
- ;; turn off auto-save.
- (auto-save-mode nil)
- (setq buffer-auto-save-file-name nil)
- (run-hooks 'tar-subfile-mode-hook))
- (t (local-set-key "\^X\^S" 'save-buffer)))
- )
-
-
-(defun tar-mode-revert (&optional no-autosave no-confirm)
- "Revert this buffer and turn on tar mode again, to re-compute the
-directory listing."
- (setq tar-header-offset nil)
- (let ((revert-buffer-function nil))
- (revert-buffer t no-confirm)
- (widen))
- (tar-mode))
-
-
-(defun tar-next-line (p)
- (interactive "p")
- (forward-line p)
- (if (eobp) nil (forward-char 36)))
-
-(defun tar-previous-line (p)
- (interactive "p")
- (tar-next-line (- p)))
-
-(defun tar-current-descriptor (&optional noerror)
- "Returns the tar-descriptor of the current line, or signals an error."
- ;; I wish lines had plists, like in ZMACS...
- (or (nth (count-lines (point-min)
- (save-excursion (beginning-of-line) (point)))
- tar-parse-info)
- (if noerror
- nil
- (error "This line does not describe a tar-file entry."))))
-
-
-(defun tar-extract (&optional other-window-p)
- "*In tar-mode, extract this entry of the tar file into its own buffer."
- (interactive)
- (let* ((view-p (eq other-window-p 'view))
- (descriptor (tar-current-descriptor))
- (tokens (tar-desc-tokens descriptor))
- (name (tar-header-name tokens))
- (size (tar-header-size tokens))
- (link-p (tar-header-link-type tokens))
- (start (+ (tar-desc-data-start descriptor) tar-header-offset -1))
- (end (+ start size)))
- (if link-p
- (error "This is a %s, not a real file."
- (cond ((eq link-p 5) "directory")
- ((eq link-p 20) "tar directory header")
- ((eq link-p 29) "multivolume-continuation")
- ((eq link-p 35) "sparse entry")
- ((eq link-p 38) "volume header")
- (t "link"))))
- (if (zerop size) (error "This is a zero-length file."))
- (let* ((tar-buffer (current-buffer))
- (bufname (concat (file-name-nondirectory name)
- " (" name " in "
- (file-name-nondirectory (buffer-file-name))
- ")"))
- (read-only-p (or buffer-read-only view-p))
- (buffer (get-buffer bufname))
- (just-created nil))
- (if buffer
- nil
- (setq buffer (get-buffer-create bufname))
- (setq just-created t)
- (unwind-protect
- (progn
- (widen)
- (save-excursion
- (set-buffer buffer)
- (insert-buffer-substring tar-buffer start end)
- (goto-char 0)
- (set-visited-file-name name) ; give it a name to decide mode.
- (normal-mode) ; pick a mode.
- (set-visited-file-name nil) ; nuke the name - not meaningful.
- (rename-buffer bufname)
-
- (make-local-variable 'superior-tar-buffer)
- (make-local-variable 'superior-tar-descriptor)
- (setq superior-tar-buffer tar-buffer)
- (setq superior-tar-descriptor descriptor)
- (tar-subfile-mode 1)
-
- (setq buffer-read-only read-only-p)
- (set-buffer-modified-p nil))
- (set-buffer tar-buffer))
- (narrow-to-region 1 tar-header-offset)))
- (if view-p
- (progn
- (view-buffer buffer)
- (and just-created (kill-buffer buffer)))
- (if other-window-p
- (switch-to-buffer-other-window buffer)
- (switch-to-buffer buffer))))))
-
-
-(defun tar-extract-other-window ()
- "*In tar-mode, extract this entry of the tar file into its own buffer."
- (interactive)
- (tar-extract t))
-
-(defun tar-view ()
- "*In tar-mode, view the tar file entry on this line."
- (interactive)
- (tar-extract 'view))
-
-
-(defun tar-read-file-name (&optional prompt)
- "Calls read-file-name, with the default being the file of the current
-tar-file descriptor."
- (or prompt (setq prompt "Copy to: "))
- (let* ((default-file (expand-file-name
- (tar-header-name (tar-desc-tokens
- (tar-current-descriptor)))))
- (target (expand-file-name
- (read-file-name prompt
- (file-name-directory default-file)
- default-file nil))))
- (if (or (string= "" (file-name-nondirectory target))
- (file-directory-p target))
- (setq target (concat (if (string-match "/$" target)
- (substring target 0 (1- (match-end 0)))
- target)
- "/"
- (file-name-nondirectory default-file))))
- target))
-
-
-(defun tar-copy (&optional to-file)
- "*In tar-mode, extract this entry of the tar file into a file on disk.
-If TO-FILE is not supplied, it is prompted for, defaulting to the name of
-the current tar-entry."
- (interactive (list (tar-read-file-name)))
- (let* ((descriptor (tar-current-descriptor))
- (tokens (tar-desc-tokens descriptor))
- (name (tar-header-name tokens))
- (size (tar-header-size tokens))
- (link-p (tar-header-link-type tokens))
- (start (+ (tar-desc-data-start descriptor) tar-header-offset -1))
- (end (+ start size)))
- (if link-p (error "This is a link, not a real file."))
- (if (zerop size) (error "This is a zero-length file."))
- (let* ((tar-buffer (current-buffer))
- buffer)
- (unwind-protect
- (progn
- (setq buffer (generate-new-buffer "*tar-copy-tmp*"))
- (widen)
- (save-excursion
- (set-buffer buffer)
- (insert-buffer-substring tar-buffer start end)
- (set-buffer-modified-p nil) ; in case we abort
- (write-file to-file)
- (message "Copied tar entry %s to %s" name to-file)
- (set-buffer tar-buffer)))
- (narrow-to-region 1 tar-header-offset)
- (if buffer (kill-buffer buffer)))
- )))
-
-
-(defun tar-flag-deleted (p &optional unflag)
- "*In tar mode, mark this sub-file to be deleted from the tar file.
-With a prefix argument, mark that many files."
- (interactive "p")
- (beginning-of-line)
- (tar-dotimes (i (if (< p 0) (- p) p))
- (if (tar-current-descriptor unflag) ; barf if we're not on an entry-line.
- (progn
- (delete-char 1)
- (insert (if unflag " " "D"))))
- (forward-line (if (< p 0) -1 1)))
- (if (eobp) nil (forward-char 36)))
-
-(defun tar-unflag (p)
- "*In tar mode, un-mark this sub-file if it is marked to be deleted.
-With a prefix argument, un-mark that many files forward."
- (interactive "p")
- (tar-flag-deleted p t))
-
-(defun tar-unflag-backwards (p)
- "*In tar mode, un-mark this sub-file if it is marked to be deleted.
-With a prefix argument, un-mark that many files backward."
- (interactive "p")
- (tar-flag-deleted (- p) t))
-
-
-(defun tar-expunge-internal ()
- "Expunge the tar-entry specified by the current line."
- (let* ((descriptor (tar-current-descriptor))
- (tokens (tar-desc-tokens descriptor))
- (line (tar-desc-data-start descriptor))
- (name (tar-header-name tokens))
- (size (tar-header-size tokens))
- (link-p (tar-header-link-type tokens))
- (start (tar-desc-data-start descriptor))
- (following-descs (cdr (memq descriptor tar-parse-info))))
- (if link-p (setq size 0)) ; size lies for hard-links.
- ;;
- ;; delete the current line...
- (beginning-of-line)
- (let ((line-start (point)))
- (end-of-line) (forward-char)
- (let ((line-len (- (point) line-start)))
- (delete-region line-start (point))
- ;;
- ;; decrement the header-pointer to be in synch...
- (setq tar-header-offset (- tar-header-offset line-len))))
- ;;
- ;; delete the data pointer...
- (setq tar-parse-info (delq descriptor tar-parse-info))
- ;;
- ;; delete the data from inside the file...
- (widen)
- (let* ((data-start (+ start tar-header-offset -513))
- (data-end (+ data-start 512 (ash (ash (+ size 511) -9) 9))))
- (delete-region data-start data-end)
- ;;
- ;; and finally, decrement the start-pointers of all following
- ;; entries in the archive. This is a pig when deleting a bunch
- ;; of files at once - we could optimize this to only do the
- ;; iteration over the files that remain, or only iterate up to
- ;; the next file to be deleted.
- (let ((data-length (- data-end data-start)))
- (tar-dolist (desc following-descs)
- (tar-setf (tar-desc-data-start desc)
- (- (tar-desc-data-start desc) data-length))))
- ))
- (narrow-to-region 1 tar-header-offset))
-
-
-(defun tar-expunge (&optional noconfirm)
- "*In tar-mode, delete all the archived files flagged for deletion.
-This does not modify the disk image; you must save the tar file itself
-for this to be permanent."
- (interactive)
- (if (or noconfirm
- (y-or-n-p "expunge files marked for deletion? "))
- (let ((n 0))
- (save-excursion
- (goto-char 0)
- (while (not (eobp))
- (if (looking-at "D")
- (progn (tar-expunge-internal)
- (setq n (1+ n)))
- (forward-line 1)))
- ;; after doing the deletions, add any padding that may be necessary.
- (tar-pad-to-blocksize)
- (narrow-to-region 1 tar-header-offset)
- )
- (if (zerop n)
- (message "nothing to expunge.")
- (message "%s expunged. Be sure to save this buffer." n)))))
-
-
-(defun tar-clear-modification-flags ()
- "remove the stars at the beginning of each line."
- (save-excursion
- (goto-char 0)
- (while (< (point) tar-header-offset)
- (if (looking-at "*")
- (progn (delete-char 1) (insert " ")))
- (forward-line 1))))
-
-
-(defun tar-chown-entry (new-uid)
- "*Change the user-id associated with this entry in the tar file.
-If this tar file was written by GNU tar, then you will be able to edit
-the user id as a string; otherwise, you must edit it as a number.
-You can force editing as a number by calling this with a prefix arg.
-This does not modify the disk image; you must save the tar file itself
-for this to be permanent."
- (interactive (list
- (let ((tokens (tar-desc-tokens (tar-current-descriptor))))
- (if (or current-prefix-arg
- (not (tar-header-magic tokens)))
- (let (n)
- (while (not (numberp (setq n (read-minibuffer
- "New UID number: "
- (format "%s" (tar-header-uid tokens)))))))
- n)
- (read-string "New UID string: " (tar-header-uname tokens))))))
- (cond ((stringp new-uid)
- (tar-setf (tar-header-uname (tar-desc-tokens (tar-current-descriptor)))
- new-uid)
- (tar-alter-one-field tar-uname-offset (concat new-uid "\000")))
- (t
- (tar-setf (tar-header-uid (tar-desc-tokens (tar-current-descriptor)))
- new-uid)
- (tar-alter-one-field tar-uid-offset
- (concat (substring (format "%6o" new-uid) 0 6) "\000 ")))))
-
-
-(defun tar-chgrp-entry (new-gid)
- "*Change the group-id associated with this entry in the tar file.
-If this tar file was written by GNU tar, then you will be able to edit
-the group id as a string; otherwise, you must edit it as a number.
-You can force editing as a number by calling this with a prefix arg.
-This does not modify the disk image; you must save the tar file itself
-for this to be permanent."
- (interactive (list
- (let ((tokens (tar-desc-tokens (tar-current-descriptor))))
- (if (or current-prefix-arg
- (not (tar-header-magic tokens)))
- (let (n)
- (while (not (numberp (setq n (read-minibuffer
- "New GID number: "
- (format "%s" (tar-header-gid tokens)))))))
- n)
- (read-string "New GID string: " (tar-header-gname tokens))))))
- (cond ((stringp new-gid)
- (tar-setf (tar-header-gname (tar-desc-tokens (tar-current-descriptor)))
- new-gid)
- (tar-alter-one-field tar-gname-offset
- (concat new-gid "\000")))
- (t
- (tar-setf (tar-header-gid (tar-desc-tokens (tar-current-descriptor)))
- new-gid)
- (tar-alter-one-field tar-gid-offset
- (concat (substring (format "%6o" new-gid) 0 6) "\000 ")))))
-
-(defun tar-rename-entry (new-name)
- "*Change the name associated with this entry in the tar file.
-This does not modify the disk image; you must save the tar file itself
-for this to be permanent."
- (interactive
- (list (read-string "New name: "
- (tar-header-name (tar-desc-tokens (tar-current-descriptor))))))
- (if (string= "" new-name) (error "zero length name."))
- (if (> (length new-name) 98) (error "name too long."))
- (tar-setf (tar-header-name (tar-desc-tokens (tar-current-descriptor)))
- new-name)
- (tar-alter-one-field 0
- (substring (concat new-name (make-string 99 0)) 0 99)))
-
-
-(defun tar-chmod-entry (new-mode)
- "*Change the protection bits associated with this entry in the tar file.
-This does not modify the disk image; you must save the tar file itself
-for this to be permanent."
- (interactive (list (tar-parse-octal-integer-safe
- (read-string "New protection (octal): "))))
- (tar-setf (tar-header-mode (tar-desc-tokens (tar-current-descriptor)))
- new-mode)
- (tar-alter-one-field tar-mode-offset
- (concat (substring (format "%6o" new-mode) 0 6) "\000 ")))
-
-
-(defun tar-alter-one-field (data-position new-data-string)
- (let* ((descriptor (tar-current-descriptor))
- (tokens (tar-desc-tokens descriptor)))
- (unwind-protect
- (save-excursion
- ;;
- ;; update the header-line.
- (beginning-of-line)
- (let ((p (point)))
- (forward-line 1)
- (delete-region p (point))
- (insert (summarize-tar-header-block tokens) "\n")
- (setq tar-header-offset (point-max)))
-
- (widen)
- (let* ((start (+ (tar-desc-data-start descriptor) tar-header-offset -513)))
- ;;
- ;; delete the old field and insert a new one.
- (goto-char (+ start data-position))
- (delete-region (point) (+ (point) (length new-data-string))) ; <--
- (insert new-data-string) ; <--
- ;;
- ;; compute a new checksum and insert it.
- (let ((chk (checksum-tar-header-block
- (buffer-substring start (+ start 512)))))
- (goto-char (+ start tar-chk-offset))
- (delete-region (point) (+ (point) 8))
- (insert (format "%6o" chk))
- (insert 0)
- (insert ? )
- (tar-setf (tar-header-checksum tokens) chk)
- ;;
- ;; ok, make sure we didn't botch it.
- (check-tar-header-block-checksum
- (buffer-substring start (+ start 512))
- chk (tar-header-name tokens))
- )))
- (narrow-to-region 1 tar-header-offset))))
-
-
-(defun tar-subfile-save-buffer ()
- "In tar subfile mode, write this buffer back into its parent tar-file buffer.
-This doesn't write anything to disk - you must save the parent tar-file buffer
-to make your changes permanent."
- (interactive)
- (if (not (and (boundp 'superior-tar-buffer) superior-tar-buffer))
- (error "this buffer has no superior tar file buffer."))
- (if (not (and (boundp 'superior-tar-descriptor) superior-tar-descriptor))
- (error "this buffer doesn't have an index into its superior tar file!"))
- (save-excursion
- (let ((subfile (current-buffer))
- (subfile-size (buffer-size))
- (descriptor superior-tar-descriptor))
- (set-buffer superior-tar-buffer)
- (let* ((tokens (tar-desc-tokens descriptor))
- (start (tar-desc-data-start descriptor))
- (name (tar-header-name tokens))
- (size (tar-header-size tokens))
- (size-pad (ash (ash (+ size 511) -9) 9))
- (head (memq descriptor tar-parse-info))
- (following-descs (cdr head)))
- (if (not head)
- (error "Can't find this tar file entry in its parent tar file!"))
- (unwind-protect
- (save-excursion
- (widen)
- ;; delete the old data...
- (let* ((data-start (+ start tar-header-offset -1))
- (data-end (+ data-start (ash (ash (+ size 511) -9) 9))))
- (delete-region data-start data-end)
- ;; insert the new data...
- (goto-char data-start)
- (insert-buffer subfile)
- ;;
- ;; pad the new data out to a multiple of 512...
- (let ((subfile-size-pad (ash (ash (+ subfile-size 511) -9) 9)))
- (goto-char (+ data-start subfile-size))
- (insert (make-string (- subfile-size-pad subfile-size) 0))
- ;;
- ;; update the data pointer of this and all following files...
- (tar-setf (tar-header-size tokens) subfile-size)
- (let ((difference (- subfile-size-pad size-pad)))
- (tar-dolist (desc following-descs)
- (tar-setf (tar-desc-data-start desc)
- (+ (tar-desc-data-start desc) difference))))
- ;;
- ;; Update the size field in the header block.
- (let ((header-start (- data-start 512)))
- (goto-char (+ header-start tar-size-offset))
- (delete-region (point) (+ (point) 12))
- (insert (format "%11o" subfile-size))
- (insert ? )
- ;;
- ;; Maybe update the datestamp.
- (if (not tar-update-datestamp)
- nil
- (goto-char (+ header-start tar-time-offset))
- (delete-region (point) (+ (point) 12))
- (insert (format "%11o" 0)) ; ## oops - how to get it??
- (insert ? ))
- ;;
- ;; compute a new checksum and insert it.
- (let ((chk (checksum-tar-header-block
- (buffer-substring header-start data-start))))
- (goto-char (+ header-start tar-chk-offset))
- (delete-region (point) (+ (point) 8))
- (insert (format "%6o" chk))
- (insert 0)
- (insert ? )
- (tar-setf (tar-header-checksum tokens) chk)))
- ;;
- ;; alter the descriptor-line...
- ;;
- (let ((position (- (length tar-parse-info) (length head))))
- (goto-char 1)
- (next-line position)
- (beginning-of-line)
- (let ((p (point))
- (m (set-marker (make-marker) tar-header-offset)))
- (forward-line 1)
- (delete-region p (point))
- (insert-before-markers (summarize-tar-header-block tokens t) "\n")
- (setq tar-header-offset (marker-position m)))
- )))
- ;; after doing the insertion, add any final padding that may be necessary.
- (tar-pad-to-blocksize))
- (narrow-to-region 1 tar-header-offset)))
- (set-buffer-modified-p t) ; mark the tar file as modified
- (set-buffer subfile)
- (set-buffer-modified-p nil) ; mark the tar subfile as unmodified
- (message "saved into tar-buffer \"%s\" - remember to save that buffer!"
- (buffer-name superior-tar-buffer))
- )))
-
-
-(defun tar-pad-to-blocksize ()
- "If we are being anal about tar file blocksizes, fix up the current buffer.
-Leaves the region wide."
- (if (null tar-anal-blocksize)
- nil
- (widen)
- (let* ((last-desc (nth (1- (length tar-parse-info)) tar-parse-info))
- (start (tar-desc-data-start last-desc))
- (tokens (tar-desc-tokens last-desc))
- (link-p (tar-header-link-type tokens))
- (size (if link-p 0 (tar-header-size tokens)))
- (data-end (+ start size))
- (bbytes (ash tar-anal-blocksize 9))
- (pad-to (+ bbytes (* bbytes (/ (1- data-end) bbytes))))
- (buffer-read-only nil) ; ##
- )
- ;; If the padding after the last data is too long, delete some;
- ;; else insert some until we are padded out to the right number of blocks.
- ;;
- (goto-char (+ (or tar-header-offset 0) data-end))
- (if (> (1+ (buffer-size)) (+ (or tar-header-offset 0) pad-to))
- (delete-region (+ (or tar-header-offset 0) pad-to) (1+ (buffer-size)))
- (insert (make-string (- (+ (or tar-header-offset 0) pad-to)
- (1+ (buffer-size)))
- 0)))
- )))
-
-
-(defun maybe-write-tar-file ()
- "Used as a write-file-hook to write tar-files out correctly."
- ;;
- ;; If the current buffer is in tar-mode and has its header-offset set,
- ;; only write out the part of the file after the header-offset.
- ;;
- (if (and (eq major-mode 'tar-mode)
- (and (boundp 'tar-header-offset) tar-header-offset))
- (unwind-protect
- (save-excursion
- (tar-clear-modification-flags)
- (widen)
- ;; Doing this here confuses things - the region gets left too wide!
- ;; I suppose this is run in a context where changing the buffer is bad.
- ;; (tar-pad-to-blocksize)
- (write-region tar-header-offset (1+ (buffer-size)) buffer-file-name nil t)
- ;; return T because we've written the file.
- t)
- (narrow-to-region 1 tar-header-offset)
- t)
- ;; return NIL because we haven't.
- nil))
-
-
-;;; Patch it in.
-
-(defvar tar-regexp "\\.tar$"
- "The regular expression used to identify tar file names.")
-
-(setq auto-mode-alist
- (cons (cons tar-regexp 'tar-mode) auto-mode-alist))
-
-(or (boundp 'write-file-hooks) (setq write-file-hooks nil))
-(or (listp write-file-hooks)
- (setq write-file-hooks (list write-file-hooks)))
-(or (memq 'maybe-write-tar-file write-file-hooks)
- (setq write-file-hooks
- (cons 'maybe-write-tar-file write-file-hooks)))
-
-
-;;; This is a hack. For files ending in .tar, we want -*- lines to be
-;;; completely ignored - if there is one, it applies to the first file
-;;; in the archive, and not the archive itself!
-
-(defun tar-normal-mode (&optional find-file)
- "Choose the major mode for this buffer automatically.
-Also sets up any specified local variables of the file.
-Uses the visited file name, the -*- line, and the local variables spec.
-
-This function is called automatically from `find-file'. In that case,
-if `inhibit-local-variables' is non-`nil' we require confirmation before
-processing a local variables spec. If you run `normal-mode' explicitly,
-confirmation is never required.
-
-Note that this version of this function has been hacked to interact
-correctly with tar files - when visiting a file which matches
-'tar-regexp', the -*- line and local-variables are not examined,
-as they would apply to a file within the archive rather than the archive
-itself."
- (interactive)
- (if (and buffer-file-name
- (string-match tar-regexp buffer-file-name))
- (tar-mode)
- (tar-real-normal-mode find-file)))
-
-
-(if (not (fboundp 'tar-real-normal-mode))
- (fset 'tar-real-normal-mode (symbol-function 'normal-mode)))
-(fset 'normal-mode 'tar-normal-mode)
-
-(provide 'tar-mode)
-
diff --git a/lisp/telnet.el b/lisp/telnet.el
index 77939cf0dd1..2b55679e8e4 100644
--- a/lisp/telnet.el
+++ b/lisp/telnet.el
@@ -1,4 +1,4 @@
-;; Copyright (C) 1985, 1988 Free Software Foundation, Inc.
+;; Copyright (C) 1985 Free Software Foundation
;; This file is part of GNU Emacs.
@@ -16,42 +16,20 @@
;; along with GNU Emacs; see the file COPYING. If not, write to
;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
;; Author William F. Schelter
;;to do fix software types for lispm:
;;to eval current expression. Also to try to send escape keys correctly.
;;essentially we'll want the rubout-handler off.
-;; filter is simplistic but should be okay for typical shell usage.
-;; needs hacking if it is going to deal with asynchronous output in a sane
-;; manner
-
-(require 'comint)
-(provide 'telnet)
-
(defvar telnet-new-line "\r")
(defvar telnet-mode-map nil)
(defvar telnet-prompt-pattern "^[^#$%>]*[#$%>] *")
+(defvar telnet-interrupt-string "\^c" "String sent by C-c.")
+(defvar telnet-count 0)
(defvar telnet-replace-c-g nil)
-(make-variable-buffer-local
- (defvar telnet-remote-echoes t
- "True if the telnet process will echo input."))
-(make-variable-buffer-local
- (defvar telnet-interrupt-string "\C-c" "String sent by C-c."))
-
-(defvar telnet-count 0
- "Number of output strings read from the telnet process
-while looking for the initial password.")
-
-(defvar telnet-initial-count -50
- "Initial value of telnet-count. Should be set to the negative of the
-number of terminal writes telnet will make setting up the host connection.")
-
-(defvar telnet-maximum-count 4
- "Maximum value telnet-count can have.
-After this many passes, we stop looking for initial setup data.
-Should be set to the number of terminal writes telnet will make
-rejecting one login and prompting for the again for a username and password.")
+(defvar telnet-remote-echoes nil)
(defun telnet-interrupt-subjob ()
(interactive)
@@ -60,7 +38,7 @@ rejecting one login and prompting for the again for a username and password.")
(defun telnet-c-z ()
(interactive)
- (send-string nil "\C-z"))
+ (send-string nil ""))
(defun send-process-next-char ()
(interactive)
@@ -70,30 +48,33 @@ rejecting one login and prompting for the again for a username and password.")
(prog1 (read-char)
(setq quit-flag nil))))))
-; initialization on first load.
-(if telnet-mode-map
- nil
- (setq telnet-mode-map (copy-keymap comint-mode-map))
+(setq telnet-mode-map (make-sparse-keymap))
+
+(progn
(define-key telnet-mode-map "\C-m" 'telnet-send-input)
-; (define-key telnet-mode-map "\C-j" 'telnet-send-input)
+ (define-key telnet-mode-map "\C-j" 'telnet-send-input)
+ (define-key telnet-mode-map "\C-c\C-d" 'shell-send-eof)
(define-key telnet-mode-map "\C-c\C-q" 'send-process-next-char)
(define-key telnet-mode-map "\C-c\C-c" 'telnet-interrupt-subjob)
- (define-key telnet-mode-map "\C-c\C-z" 'telnet-c-z))
+ (define-key telnet-mode-map "\C-c\C-z" 'telnet-c-z)
+ (define-key telnet-mode-map "\C-c\C-u" 'kill-shell-input)
+ (define-key telnet-mode-map "\C-c\C-w" 'backward-kill-word)
+ (define-key telnet-mode-map "\C-c\C-o" 'kill-output-from-shell)
+ (define-key telnet-mode-map "\C-c\C-r" 'show-output-from-shell))
;;maybe should have a flag for when have found type
(defun telnet-check-software-type-initialize (string)
"Tries to put correct initializations in. Needs work."
- (let ((case-fold-search t))
- (cond ((string-match "unix" string)
- (setq telnet-prompt-pattern comint-prompt-regexp)
+ (cond ((string-match "unix" string)
+ (setq telnet-prompt-pattern shell-prompt-pattern)
(setq telnet-new-line "\n"))
((string-match "tops-20" string) ;;maybe add telnet-replace-c-g
(setq telnet-prompt-pattern "[@>]*"))
((string-match "its" string)
(setq telnet-prompt-pattern "^[^*>]*[*>] *"))
((string-match "explorer" string) ;;explorer telnet needs work
- (setq telnet-replace-c-g ?\n))))
- (setq comint-prompt-regexp telnet-prompt-pattern))
+ (setq telnet-replace-c-g ?\n))
+ ))
(defun telnet-initial-filter (proc string)
;For reading up to and including password; also will get machine type.
@@ -105,76 +86,133 @@ rejecting one login and prompting for the again for a username and password.")
(let* ((echo-keystrokes 0)
(password (read-password)))
(setq telnet-count 0)
- (send-string proc (concat password telnet-new-line))))
+ (send-string proc (concat password telnet-new-line))))
(t (telnet-check-software-type-initialize string)
(telnet-filter proc string)
- (cond ((> telnet-count telnet-maximum-count)
+ (cond ((> telnet-count 4)
(set-process-filter proc 'telnet-filter))
(t (setq telnet-count (1+ telnet-count)))))))
(defun telnet-filter (proc string)
- (let ((at-end
- (and (eq (process-buffer proc) (current-buffer))
- (= (point) (point-max)))))
- (save-excursion
- (set-buffer (process-buffer proc))
- (goto-char (process-mark proc))
- (let ((now (point)))
- (let ((index 0) c-m)
- (while (setq c-m (string-match "\C-m" string index))
- (insert-before-markers (substring string index c-m))
- (setq index (1+ c-m)))
- (insert-before-markers (substring string index)))
- (and telnet-replace-c-g
- (subst-char-in-region now (point) ?\C-g telnet-replace-c-g)))
-; (if (and (integer-or-marker-p last-input-start)
-; (marker-position last-input-start)
-; telnet-remote-echoes)
-; (delete-region last-input-start last-input-end))
- )
- (if at-end
- (goto-char (point-max)))))
+ (save-excursion
+ (set-buffer (process-buffer proc))
+ (goto-char (point-max))
+ (let ((now (point)))
+ (insert string)
+ (subst-char-in-region now (point) ?\^m ?\ )
+ (and telnet-replace-c-g
+ (subst-char-in-region now (point) ?\^g telnet-replace-c-g)))
+ (if (process-mark proc)
+ (set-marker (process-mark proc) (point)))
+ (if (and (integer-or-marker-p last-input-start)
+ (marker-position last-input-start)
+ telnet-remote-echoes)
+ (delete-region last-input-start last-input-end)))
+ (if (eq (process-buffer proc)
+ (current-buffer))
+ (goto-char (point-max))))
+
+(defun delete-char-or-send-eof (arg killp)
+ "At end of buffer, send eof to subshell. Otherwise delete character."
+ (interactive "p\nP")
+ (if (and (eobp) (not killp))
+ (process-send-eof)
+ (delete-char arg killp)))
(defun telnet-send-input ()
- (interactive)
- (comint-send-input telnet-new-line telnet-remote-echoes))
+ "Send input to remote host
+At end of buffer, sends all text after last output
+as input to the telnet, including a telnet-new-line inserted at the end.
+Not at end, copies current line to the end of the buffer and sends it,
+after first attempting to discard any prompt at the beginning of the line
+by matching the regexp that is the value of telnet-prompt-pattern if possible."
+ (interactive)
+ (let (copied)
+ (end-of-line)
+ (if (eobp)
+ (progn
+ (move-marker last-input-start
+ (process-mark (get-buffer-process (current-buffer))))
+ (move-marker last-input-end (point)))
+ (beginning-of-line)
+ (re-search-forward telnet-prompt-pattern nil t)
+ (let ((copy (buffer-substring (point)
+ (progn (forward-line 1) (point)))))
+ (goto-char (point-max))
+ (move-marker last-input-start (point))
+ (insert copy) (setq copied t)
+ (move-marker last-input-end (point))))
+ (save-excursion
+ (goto-char last-input-start)
+ (let ((process (get-buffer-process (current-buffer))))
+ (send-region process last-input-start last-input-end)
+ (if (not copied) (send-string process telnet-new-line))
+ (set-marker (process-mark process) (point))))))
(defun telnet (arg)
"Open a network login connection to host named HOST (a string).
Communication with HOST is recorded in a buffer *HOST-telnet*.
Normally input is edited in Emacs and sent a line at a time."
(interactive "sOpen telnet connection to host: ")
+ (require 'shell)
(let ((name (concat arg "-telnet" )))
- (switch-to-buffer (make-comint name "telnet"))
+ (switch-to-buffer (make-shell name "telnet"))
(set-process-filter (get-process name) 'telnet-initial-filter)
+ (accept-process-output (get-process name))
(erase-buffer)
(send-string name (concat "open " arg "\n"))
(telnet-mode)
- (setq telnet-count telnet-initial-count)))
+ (setq telnet-count -16)))
+
+(defun read-password ()
+ (let ((answ "") tem)
+ (while (prog1 (not (memq (setq tem (read-char))
+ '(?\C-m ?\n ?\C-g)))
+ (setq quit-flag nil))
+ (setq answ (concat answ (char-to-string tem))))
+ answ))
(defun telnet-mode ()
"This mode is for use during telnet from a buffer to another
-host. It has most of the same commands as comint-mode.
-There is a variable ``telnet-interrupt-string'' which is the character
+host. It has most of the same commands as shell mode.
+There is a variable `telnet-interrupt-string' which is the character
sent to try to stop execution of a job on the remote host.
-Data is sent to the remote host when RET is typed.
-
+Data is sent to the remote host when `return' is typed.
+Thus if you may need to edit the data before sending you
+should use c-n to move down a line. Then you can return
+to alter a previous line. Of course you should not use this
+mode of telnet if you want to run emacs like programs on the
+remote host (at least not yet!).
+
+The following commands imitate the usual Unix interrupt and
+editing control characters:
\\{telnet-mode-map}
Bugs:
---Replaces by a space, really should remove."
+--Replace by a space, really should remove.
+--For Unix interacts poorly with tcsh although csh,sh,ksh are ok."
(interactive)
- (comint-mode)
- (setq major-mode 'telnet-mode
- mode-name "Telnet"
- comint-prompt-regexp telnet-prompt-pattern)
+ (kill-all-local-variables)
+ (setq major-mode 'telnet-mode)
+ (setq mode-name "Telnet")
+ (setq mode-line-process '(": %s"))
+ (make-local-variable 'last-input-start)
(use-local-map telnet-mode-map)
- (run-hooks 'telnet-mode-hook))
+ (let ((tem telnet-prompt-pattern))
+ (make-local-variable 'telnet-prompt-pattern)
+ (setq telnet-prompt-pattern tem))
+ (make-local-variable 'telnet-interrupt-string)
+ (setq telnet-interrupt-string "")
+ (make-local-variable 'telnet-new-line)
+ (setq telnet-new-line "\r")
+ (make-local-variable 'last-input-start)
+ (setq last-input-start (make-marker))
+ (make-local-variable 'last-input-end)
+ (setq last-input-end (make-marker))
+ (make-local-variable 'telnet-remote-echoes)
+ (setq telnet-remote-echoes t)
+ (make-local-variable 'telnet-replace-c-g)
+ (setq telnet-replace-c-g nil))
+
+
-(defun read-password ()
- (let ((answ "") tem)
- (message "Reading password...")
- (while (not (or (= (setq tem (read-char)) ?\^m)
- (= tem ?\n)))
- (setq answ (concat answ (char-to-string tem))))
- answ))
diff --git a/lisp/telnet.elc b/lisp/telnet.elc
new file mode 100644
index 00000000000..7daf74d9db9
--- /dev/null
+++ b/lisp/telnet.elc
Binary files differ
diff --git a/lisp/term-nasty.el b/lisp/term-nasty.el
deleted file mode 100644
index 86a4a1ec30e..00000000000
--- a/lisp/term-nasty.el
+++ /dev/null
@@ -1,21 +0,0 @@
-Some people used to be bothered by the following comments that were
-found in terminal.el. We decided they were distracting, and that it
-was better not to have them there. On the other hand, we didn't want
-to appear to be giving in to the pressure to censor obscenity that
-currently threatens freedom of speech and of the press in the US.
-So we decided to put the comments here.
-
-
-These comments were removed from te-losing-unix.
- ;(what lossage)
- ;(message "fucking-unix: %d" char)
-
-This was before te-process-output.
-;; fucking unix has -such- braindamaged lack of tty control...
-
-And about the need to handle output characters such as C-m, C-g, C-h
-and C-i even though the termcap doesn't say they may be used:
-;fuck me harder
-;again and again!
-;wa12id!!
-;(spiked) \ No newline at end of file
diff --git a/lisp/term/COPYING b/lisp/term/COPYING
new file mode 100644
index 00000000000..9a170375811
--- /dev/null
+++ b/lisp/term/COPYING
@@ -0,0 +1,249 @@
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 1, February 1989
+
+ Copyright (C) 1989 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The license agreements of most software companies try to keep users
+at the mercy of those companies. By contrast, our General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. The
+General Public License applies to the Free Software Foundation's
+software and to any other program whose authors commit to using it.
+You can use it for your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Specifically, the General Public License is designed to make
+sure that you have the freedom to give away or sell copies of free
+software, that you receive source code or can get it if you want it,
+that you can change the software or use pieces of it in new free
+programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of a such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must tell them their rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any program or other work which
+contains a notice placed by the copyright holder saying it may be
+distributed under the terms of this General Public License. The
+"Program", below, refers to any such program or work, and a "work based
+on the Program" means either the Program or any work containing the
+Program or a portion of it, either verbatim or with modifications. Each
+licensee is addressed as "you".
+
+ 1. You may copy and distribute verbatim copies of the Program's source
+code as you receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice and
+disclaimer of warranty; keep intact all the notices that refer to this
+General Public License and to the absence of any warranty; and give any
+other recipients of the Program a copy of this General Public License
+along with the Program. You may charge a fee for the physical act of
+transferring a copy.
+
+ 2. You may modify your copy or copies of the Program or any portion of
+it, and copy and distribute such modifications under the terms of Paragraph
+1 above, provided that you also do the following:
+
+ a) cause the modified files to carry prominent notices stating that
+ you changed the files and the date of any change; and
+
+ b) cause the whole of any work that you distribute or publish, that
+ in whole or in part contains the Program or any part thereof, either
+ with or without modifications, to be licensed at no charge to all
+ third parties under the terms of this General Public License (except
+ that you may choose to grant warranty protection to some or all
+ third parties, at your option).
+
+ c) If the modified program normally reads commands interactively when
+ run, you must cause it, when started running for such interactive use
+ in the simplest and most usual way, to print or display an
+ announcement including an appropriate copyright notice and a notice
+ that there is no warranty (or else, saying that you provide a
+ warranty) and that users may redistribute the program under these
+ conditions, and telling the user how to view a copy of this General
+ Public License.
+
+ d) You may charge a fee for the physical act of transferring a
+ copy, and you may at your option offer warranty protection in
+ exchange for a fee.
+
+Mere aggregation of another independent work with the Program (or its
+derivative) on a volume of a storage or distribution medium does not bring
+the other work under the scope of these terms.
+
+ 3. You may copy and distribute the Program (or a portion or derivative of
+it, under Paragraph 2) in object code or executable form under the terms of
+Paragraphs 1 and 2 above provided that you also do one of the following:
+
+ a) accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of
+ Paragraphs 1 and 2 above; or,
+
+ b) accompany it with a written offer, valid for at least three
+ years, to give any third party free (except for a nominal charge
+ for the cost of distribution) a complete machine-readable copy of the
+ corresponding source code, to be distributed under the terms of
+ Paragraphs 1 and 2 above; or,
+
+ c) accompany it with the information you received as to where the
+ corresponding source code may be obtained. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form alone.)
+
+Source code for a work means the preferred form of the work for making
+modifications to it. For an executable file, complete source code means
+all the source code for all modules it contains; but, as a special
+exception, it need not include source code for modules which are standard
+libraries that accompany the operating system on which the executable
+file runs, or for standard header files or definitions files that
+accompany that operating system.
+
+ 4. You may not copy, modify, sublicense, distribute or transfer the
+Program except as expressly provided under this General Public License.
+Any attempt otherwise to copy, modify, sublicense, distribute or transfer
+the Program is void, and will automatically terminate your rights to use
+the Program under this License. However, parties who have received
+copies, or rights to use copies, from you under this General Public
+License will not have their licenses terminated so long as such parties
+remain in full compliance.
+
+ 5. By copying, distributing or modifying the Program (or any work based
+on the Program) you indicate your acceptance of this license to do so,
+and all its terms and conditions.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the original
+licensor to copy, distribute or modify the Program subject to these
+terms and conditions. You may not impose any further restrictions on the
+recipients' exercise of the rights granted herein.
+
+ 7. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of the license which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+the license, you may choose any version ever published by the Free Software
+Foundation.
+
+ 8. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to humanity, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these
+terms.
+
+ To do so, attach the following notices to the program. It is safest to
+attach them to the start of each source file to most effectively convey
+the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19xx name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the
+appropriate parts of the General Public License. Of course, the
+commands you use may be called something other than `show w' and `show
+c'; they could even be mouse-clicks or menu items--whatever suits your
+program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ program `Gnomovision' (a program to direct compilers to make passes
+ at assemblers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/lisp/term/apollo.el b/lisp/term/apollo.el
new file mode 100644
index 00000000000..3b75d654c50
--- /dev/null
+++ b/lisp/term/apollo.el
@@ -0,0 +1 @@
+(load "term/vt100")
diff --git a/lisp/term/at386.el b/lisp/term/at386.el
new file mode 100644
index 00000000000..65848affb74
--- /dev/null
+++ b/lisp/term/at386.el
@@ -0,0 +1,101 @@
+;;; Dell 325D (UNIX SVR4) as AT386 UNIX PC keyboard definitions
+;;; Based on Brant Cheikes (brant@linc.cis.upenn.edu, manta!brant)
+;;; unixpc.el.
+;;;
+;;; Mark J. Hewitt (mjh@uk.co.kernel)
+;;; 8-apr-91
+;;;
+;;; The AT386 keyboard mapping has three types of prefix keys:
+;;;
+;;; <esc> [ for cursor positioning and keypad
+;;; <esc> O for function keys
+;;; <esc> N for ALT keys
+;;;
+;;; *NOTE* Care is required when using ALT bound as a simple META key.
+;;; It works for most normal key sequences, but some ALT-CTRL
+;;; (aka M-C-x) are intercepted locally. F'rinstance M-C-d would
+;;; break to the kernel debugger, kdb (!).
+;;;
+
+(require 'keypad) ; for keypad-defaults
+
+(defvar Dell-map-1 nil
+ "The <esc>O keys (Function) on the Dell Unix PC.")
+(defvar Dell-map-3 nil
+ "The <esc>[ keys (Right-hand keypads) on the Dell Unix PC.")
+
+(defun enable-function-keys ()
+ "Enable the use of the keypad and function keys.
+Because of the nature of the PC keyboard under Unix,
+this unavoidably breaks a standard Emacs command (M-[);
+therefore, it is not done by default, but only if you give this command."
+ (interactive)
+ (global-set-key "\eO" Dell-map-1)
+ (global-set-key "\eN" 'ESC-prefix)
+ (global-set-key "\e[" Dell-map-3)
+)
+
+;;; Create a few new keypad defaults.
+
+(keypad-default "5" 'set-mark-command)
+(keypad-default "I" 'yank)
+(keypad-default "x" 'call-last-kbd-macro)
+(keypad-default "\C-f" 'info)
+(keypad-default "\C-g" 'overwrite-mode)
+(keypad-default "\C-h" 'auto-fill-mode)
+(keypad-default "\C-i" 'abbrev-mode)
+(keypad-default "\C-j" 'browse-yank)
+; There are no definitions for these functions.
+;(keypad-default "\C-l" 'Dell-132)
+;(keypad-default "\C-m" 'Dell-80)
+(keypad-default "\C-n" 'scroll-other-window)
+(keypad-default "\C-o" 'other-window)
+(keypad-default "\C-p" 'repeat-complex-command)
+
+;; Now populate the maps, if they are enabled.
+
+(if Dell-map-1
+ nil
+ (setq Dell-map-1 (make-keymap)) ; <ESC>O (function key) commands
+ (setup-terminal-keymap Dell-map-1
+ '(("P" . ??) ; F1 (help)
+ ("p" . ?\^f) ; Shift F1 (info)
+ ("Q" . ?\^g) ; F2 (overwrite-mode)
+ ("q" . ?\^g) ; Shift F2 (overwrite-mode)
+ ("R" . ?\^h) ; F3 (auto-fill-mode)
+ ("r" . ?\^h) ; Shift F3 (auto-fill-mode)
+ ("S" . ?\^i) ; F4 (abbrev-mode)
+ ("s" . ?\^i) ; Shift F4 (abbrev-mode)
+ ("T" . ?\^j) ; F5 (browse-yank)
+ ("t" . ?\^j) ; Shift F5 (browse-yank)
+ ("U" . ?\^l) ; F6 (Dell-132)
+ ("u" . ?\^m) ; Shift F6 (Dell-80)
+ ("V" . nil) ; F7
+ ("v" . nil) ; Shift F7
+ ("W" . ?\^n) ; F8 (scroll-other-window)
+ ("w" . ?\^o) ; Shift F8 (other-window)
+ ("X" . nil) ; F9
+ ("x" . nil) ; Shift F9
+ ("Y" . nil) ; F10
+ ("y" . nil) ; Shift F10
+ ("Z" . ?\^p) ; F11 (repeat-complex-command)
+ ("z" . ?\^p) ; Shift F11 (repeat-complex-command)
+ ("A" . ?x) ; F12 (call-last-kbd-macro)
+ ("a" . ?x) ; Shift F12 (call-last-kbd-macro)
+ )))
+
+(if Dell-map-3
+ nil
+ (setq Dell-map-3 (make-sparse-keymap)) ; <ESC>[ commands
+ (setup-terminal-keymap Dell-map-3
+ '(("A" . ?u) ; Up Arrow (previous-line)
+ ("B" . ?d) ; Down Arrow (next-line)
+ ("C" . ?r) ; Right Arrow (forward-char)
+ ("D" . ?l) ; Left Arrow (backward-char)
+ ("H" . ?\^a) ; Home (beginning-of-line)
+ ("Y" . ?\^b) ; End (end-of-line)
+ ("@" . ?I) ; Insert (yank)
+ ("U" . ?N) ; Page Up (scroll-up)
+ ("V" . ?P) ; Shift-Page (scroll-down)
+ ("G" . ?5) ; pad 5 (set-mark-command)
+ )))
diff --git a/lisp/term/bbn.el b/lisp/term/bbn.el
new file mode 100644
index 00000000000..9affcc21281
--- /dev/null
+++ b/lisp/term/bbn.el
@@ -0,0 +1 @@
+(load (concat term-file-prefix "bg") nil t)
diff --git a/lisp/term/bg.el b/lisp/term/bg.el
new file mode 100644
index 00000000000..c1b98910861
--- /dev/null
+++ b/lisp/term/bg.el
@@ -0,0 +1,6 @@
+;; BBN bitgraph terminal.
+
+(load (concat term-file-prefix "vt100") nil t) ;BG keyboard is VT100 clone
+(autoload 'bg-mouse-report "bg-mouse")
+(global-set-key "\e:" 'bg-mouse-report)
+(send-string-to-terminal "\e:0;7;;;360;512;9;16;9;16c")
diff --git a/lisp/term/bgnv.el b/lisp/term/bgnv.el
new file mode 100644
index 00000000000..9affcc21281
--- /dev/null
+++ b/lisp/term/bgnv.el
@@ -0,0 +1 @@
+(load (concat term-file-prefix "bg") nil t)
diff --git a/lisp/term/bgrv.el b/lisp/term/bgrv.el
new file mode 100644
index 00000000000..9affcc21281
--- /dev/null
+++ b/lisp/term/bgrv.el
@@ -0,0 +1 @@
+(load (concat term-file-prefix "bg") nil t)
diff --git a/lisp/term/bobcat.el b/lisp/term/bobcat.el
new file mode 100644
index 00000000000..7abe538ef77
--- /dev/null
+++ b/lisp/term/bobcat.el
@@ -0,0 +1,11 @@
+;;; HP terminals usually encourage using ^H as the rubout character
+
+(let ((the-table (make-string 128 0)))
+ (let ((i 0))
+ (while (< i 128)
+ (aset the-table i i)
+ (setq i (1+ i))))
+ ;; Swap ^H and DEL
+ (aset the-table ?\177 ?\^h)
+ (aset the-table ?\^h ?\177)
+ (setq keyboard-translate-table the-table))
diff --git a/lisp/term/news.el b/lisp/term/news.el
deleted file mode 100644
index 16b79e291c9..00000000000
--- a/lisp/term/news.el
+++ /dev/null
@@ -1,85 +0,0 @@
-;; keypad and function key bindings for the Sony NEWS keyboard.
-;; Copyright (C) 1989 Free Software Foundation, Inc.
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY. No author or distributor
-;; accepts responsibility to anyone for the consequences of using it
-;; or for whether it serves any particular purpose or works at all,
-;; unless he says so in writing. Refer to the GNU Emacs General Public
-;; License for full details.
-
-;; Everyone is granted permission to copy, modify and redistribute
-;; GNU Emacs, but only under the conditions described in the
-;; GNU Emacs General Public License. A copy of this license is
-;; supposed to have been given to you along with GNU Emacs so you
-;; can know your rights and responsibilities. It should be in a
-;; file named COPYING. Among other things, the copyright notice
-;; and this notice must be preserved on all copies.
-
-;; This file effects a mapping from the raw escape sequences of various
-;; keypad and function keys to the symbols used by emacs to represent
-;; those keys. The mapping from key symbol to the function performed
-;; when that key is pressed is handled keyboard-independently by the file
-;; ../keypad.el.
-
-;; Note that his file is also used under X11. For this to work, the variable
-;; names must not change from keyboard file to keyboard file, nor can the
-;; structure of keypad-maps change.
-
-(require 'keypad)
-
-(defvar keypads nil
- "Keypad and function keys keymap for Sony News machine.")
-
-(defvar keypad-maps nil
- "A list of strings sent by the keypad and function keys on the Sony News.
-There is an element for each unique prefix. Each element is of the form
-(PREFIX map map ...), each map being (string . symbol).")
-
-(setq keypad-maps '(("\eO"
- ("P" . function-1)
- ("Q" . function-2)
- ("R" . function-3)
- ("S" . function-4)
- ("T" . function-5)
- ("U" . function-6)
- ("V" . function-7)
- ("W" . function-8)
- ("X" . function-9)
- ("Y" . function-10)
-
- ("m" . keypad-subtract)
- ("k" . keypad-add)
- ("l" . keypad-comma)
- ("n" . keypad-period)
- ("M" . keypad-enter)
-
- ("p" . keypad-0)
- ("q" . keypad-1)
- ("r" . keypad-2)
- ("s" . keypad-3)
- ("t" . keypad-4)
- ("u" . keypad-5)
- ("v" . keypad-6)
- ("w" . keypad-7)
- ("x" . keypad-8)
- ("y" . keypad-9)
-
- ; These three strings are just made up.
- ("a" . execute) ; enter
- ("b" . select) ; nfer
- ("c" . cancel)))) ; xfer
-
-(let ((pads keypad-maps))
- (while pads
- (unwind-protect
- (let* ((prefix (car (car pads)))
- (stringmap (cdr (car pads)))
- (padmap (if (lookup-key global-map prefix)
- (error "Keymap entry for keypad prefix already exisists")
- (make-sparse-keymap))))
- (define-key global-map prefix padmap)
- (setup-terminal-keymap padmap stringmap))
- (setq pads (cdr pads)))))
diff --git a/lisp/term/s4.el b/lisp/term/s4.el
new file mode 100644
index 00000000000..ab81a3bd7c9
--- /dev/null
+++ b/lisp/term/s4.el
@@ -0,0 +1,142 @@
+;; Map s4 function key escape sequences
+;; into the standard slots in function-keymap where we can;
+;; set up terminal-specific bindings where we must
+;;
+;; by: Eric S. Raymond, eric@snark.thyrsus.com
+
+(require 'keypad)
+
+;; First, map as many keys as possible to terminal-independent keycaps
+
+(defvar META-RB-map nil
+ "The META-RB-map maps the ESC-[ function keys on the s4 keyboard.")
+
+(if (not META-RB-map)
+ (progn
+ (setq META-RB-map (lookup-key global-map "\e["))
+ (if (not (keymapp META-RB-map))
+ (setq META-RB-map (make-sparse-keymap))) ;; <ESC>[ commands
+
+ (setup-terminal-keymap META-RB-map
+ '(("A" . ?u) ; up arrow
+ ("B" . ?d) ; down-arrow
+ ("C" . ?r) ; right-arrow
+ ("D" . ?l) ; left-arrow
+ ("U" . ?N) ; 'Page' -> next page
+ ("V" . ?P) ; 'Shift-Page' -> prev page
+ ("H" . ?h) ; 'Home' -> home-key
+ ;; ("J" . ??) ; 'Clear' -> unmapped
+ ))))
+
+(defun enable-arrow-keys ()
+ "Enable the use of the s4 arrow keys for cursor motion.
+Because of the nature of the s4, this unavoidably breaks
+the standard Emacs command ESC [; therefore, it is not done by default,
+but only if you give this command in your .emacs."
+ (global-set-key "\e[" META-RB-map))
+
+(defvar META-N-map nil
+ "META-N-map maps the ESC-N function keys on the s4 keyboard.")
+
+(if (not META-N-map)
+ (progn
+
+ (setq META-N-map (lookup-key global-map "\eN"))
+ (if (not (keymapp META-N-map))
+ (setq META-N-map (make-sparse-keymap))) ;; <ESC>N commands
+ (setup-terminal-keymap META-N-map '(
+ ("a" . ?C) ; 'Rfrsh' -> redraw screen
+ ;; ("A" . ??) ; 'Clear' -> unmapped
+ ;; ("c" . ??) ; 'Move' -> unmapped
+ ;; ("d" . ??) ; 'Copy' -> unmapped
+ ;; ("B" . ??) ; 'Shift-Beg' -> unmapped
+ ;; ("M" . ??) ; 'Shift-Home' -> unmapped
+ ;; ("N" . ??) ; 'Shift-End' -> unmapped
+ ("e" . ?k) ; 'Dlete' -> generic delete (kill-region)
+ ("f" . ?.) ; 'Dlete Char' -> keypad .
+ ("g" . ?1) ; 'Prev' -> keypad 1 (backward-word)
+ ("h" . ?3) ; 'Next' -> keypad 3 (forward-word)
+ ("i" . ?s) ; 'Mark' -> select
+ ;; ("I" . ??) ; 'Select' -> MAPPED BELOW
+ ;; ("j" . ??) ; 'Input Mode' -> unmapped
+ ))
+
+ (define-key global-map "\eN" META-N-map)))
+
+(defvar META-O-map nil
+ "META-O-map maps the META-O function keys on the s4 keyboard.")
+
+(if (not META-O-map)
+ (progn
+
+ (setq META-O-map (lookup-key global-map "\eO"))
+ (if (not (keymapp META-O-map))
+ (setq META-O-map (make-sparse-keymap))) ;; <ESC>O commands
+ (setup-terminal-keymap META-O-map '(
+ ("a" . ?E) ; 'Clear-Line' -> Clear to EOL
+ ("A" . ?S) ; 'Shift-Clear-Line' -> Clear to EOS
+ ("b" . ?\C-@) ; 'Ref' -> function key 0
+ ("c" . ?\C-a) ; 'F1' -> function key 1
+ ("d" . ?\C-b) ; 'F2' -> function key 2
+ ("e" . ?\C-c) ; 'F3' -> function key 3
+ ("f" . ?\C-d) ; 'F4' -> function key 4
+ ("g" . ?\C-e) ; 'F5' -> function key 5
+ ("h" . ?\C-f) ; 'F6' -> function key 6
+ ("i" . ?\C-g) ; 'F7' -> function key 7
+ ("j" . ?\C-h) ; 'F8' -> function key 8
+ ;; ("k" . ??) ; 'Exit' -> MAPPED BELOW
+ ("m" . ??) ; 'Help' -> help-command
+ ;; ("n" . ??) ; 'Creat' -> unmapped
+ ;; ("o" . ??) ; 'Save' -> MAPPED BELOW
+ ;; ("r" . ??) ; 'Opts' -> unmapped
+ ;; ("s" . ??) ; 'Undo' -> MAPPED BELOW
+ ("t" . ?x) ; 'Redo' -> 'do' key
+ ;; ("u" . ??) ; 'Cmd' -> MAPPED BELOW
+ ;; ("v" . ??) ; 'Open' -> MAPPED BELOW
+ ;; ("V" . ??) ; 'Close' -> unmapped
+ ;; ("w" . ??) ; 'Cancel' -> MAPPED BELOW
+ ("x" . ?f) ; 'Find' -> find/replace
+ ;; ("y" . ??) ; 'Rplac' -> MAPPED BELOW
+ ;; ("z" . ??) ; 'Print' -> MAPPED BELOW
+ ))
+
+ (define-key global-map "\eO" META-O-map)))
+
+(defvar META-P-map nil
+ "META-P-map maps the META-P function keys on the s4 keyboard.")
+
+(if (not META-P-map)
+ (progn
+
+ (setq META-P-map (lookup-key global-map "\eP"))
+ (if (not (keymapp META-P-map))
+ (setq META-P-map (make-sparse-keymap))) ;; <ESC>P commands
+ (setup-terminal-keymap META-P-map '(
+ ("a" . ?1) ; Ctrl-1 -> keypad 1
+ ("b" . ?2) ; Ctrl-2 -> keypad 2
+ ("c" . ?3) ; Ctrl-3 -> keypad 3
+ ("d" . ?4) ; Ctrl-4 -> keypad 4
+ ("e" . ?5) ; Ctrl-5 -> keypad 5
+ ("f" . ?6) ; Ctrl-6 -> keypad 6
+ ("g" . ?7) ; Ctrl-7 -> keypad 7
+ ("h" . ?8) ; Ctrl-8 -> keypad 8
+ ("i" . ?9) ; Ctrl-9 -> keypad 9
+ ("j" . ?0) ; Ctrl-0 -> keypad 0
+ ("k" . ?-) ; Ctrl-- -> keypad -
+ ))
+
+ (define-key global-map "\eP" META-P-map)))
+
+;; Now do terminal-specific mappings of keys with no standard-keycap equivalent
+
+;;;(define-key esc-map "9" 'beginning-of-buffer) ;'Begin'
+;;;(define-key esc-map "0" 'end-of-buffer) ;'End'
+(define-key META-N-map "I" 'narrow-to-region) ;'Select'
+(define-key META-O-map "k" 'save-buffers-kill-emacs) ;'Exit'
+(define-key META-O-map "o" 'save-buffer) ;'Save'
+(define-key META-O-map "s" 'undo) ;'Undo'
+(define-key META-O-map "u" 'execute-extended-command) ;'Cmd'
+(define-key META-O-map "v" 'find-file) ;'Open'
+(define-key META-O-map "w" 'keyboard-quit) ;'Cancl'
+(define-key META-O-map "y" 'replace-regexp) ;'Rplac'
+(define-key META-O-map "z" 'lpr-buffer) ;'Print'
diff --git a/lisp/term/sun.el b/lisp/term/sun.el
new file mode 100644
index 00000000000..171bc1c4488
--- /dev/null
+++ b/lisp/term/sun.el
@@ -0,0 +1,333 @@
+;; keybinding for standard default sunterm keys
+;; Copyright (C) 1987 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 1, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+;; Jeff Peck, Sun Microsystems Inc <peck@sun.com>
+;; Mar, 91 better integration with X windows
+
+(defun ignore-key ()
+ "interactive version of ignore"
+ (interactive)
+ (ignore))
+
+(defun unbound-key ()
+ "filler for compound keymaps"
+ (interactive)
+ (error "unbound-key"))
+
+(defun on-window-line-p (n)
+ (save-excursion
+ (beginning-of-line 1)
+ (let ((p (point)))
+ (move-to-window-line n)
+ (equal (point) p))))
+
+(defun scroll-down-in-place (n)
+ (interactive "p")
+ (if (on-window-line-p 0)
+ (progn (scroll-down n) (previous-line n))
+ (previous-line n) (scroll-down n)))
+
+(defun scroll-up-in-place (n)
+ (interactive "p")
+ (if (on-window-line-p -1)
+ (progn (scroll-up n) (next-line n))
+ (next-line n) (scroll-up n)))
+
+(defun kill-region-and-unmark (beg end)
+ "Like kill-region, but pops the mark [which equals point, anyway.]"
+ (interactive "r")
+ (kill-region beg end)
+ (setq this-command 'kill-region-and-unmark)
+ (set-mark-command t))
+
+(defun rerun-prev-command ()
+ "Repeat Previous-complex-command."
+ (interactive)
+ (eval (nth 0 command-history)))
+
+(defvar grep-arg nil "Default arg for RE-search")
+
+;; not sure this all works... or works at all...
+(defun search-command-arg ()
+ ;; if previous minibuf command specified a search string, return it.
+ ;; this way, a call to M-x re-search-forward can pass its arg.
+ (let* ((command (car command-history))
+ (command-name (symbol-name (car command)))
+ (search-arg (car (cdr command)))
+ (search-command
+ (and command-name (string-match "search" command-name))))
+ (and search-command (stringp search-arg) search-arg)))
+
+(defun grep-arg (&optional prompt)
+ "helper function used by research-{backward,forward}"
+ (if (memq last-command '(research-forward research-backward)) grep-arg
+ (let ((this-command this-command) ; save this binding from read-string
+ (default (or (search-command-arg)
+ search-last-regexp
+ grep-arg)))
+ (read-string (or prompt "Regexp arg: ") default))))
+
+(defun research-forward ()
+ "Repeat regexp search forward, using previous search arg if available."
+ (interactive) ;
+ (if (re-search-forward (grep-arg "Regexp search: "))
+ (setq search-last-regexp grep-arg)))
+
+(defun research-backward ()
+ "Repeat regexp search backward, using previous search arg if available."
+ (interactive) ;
+ (if (re-search-backward (grep-arg "Regexp search backward: "))
+ (setq search-last-regexp grep-arg)))
+
+(defun help-for-dummies ()
+ (interactive)
+ (let ((char ?\C-h))
+ (if (or (= char ?\C-h) (= char ??))
+ (save-window-excursion
+ (switch-to-buffer "*Help*")
+ (erase-buffer)
+ (insert (documentation 'help-for-help))
+ (goto-char (point-min))
+ (while (memq char '(?\C-h ?? ?\C-v ?\ ?\177 ?\M-v))
+ (if (memq char '(?\C-v ?\ ))
+ (scroll-up))
+ (if (memq char '(?\177 ?\M-v))
+ (scroll-down))
+ (message "A B C F I K L M N S T V W C-c C-d C-n C-w%s: "
+ (if (pos-visible-in-window-p (point-max))
+ "" " or Space to scroll"))
+ (let ((cursor-in-echo-area t))
+ (setq char (read-char))))))
+ (let ((defn (cdr (assq (downcase char) (cdr help-map)))))
+ (if defn (call-interactively defn) (ding)))))
+
+;;;
+;;; handle sun's extra function keys
+;;; this version for those who run with standard .ttyswrc and no emacstool
+;;;
+;;; sunview picks up expose and open on the way UP,
+;;; so we ignore them on the way down
+;;;
+
+;;; Since .emacs gets loaded before this file, a hook is supplied
+;;; for you to put your own bindings in. Example:
+;(setq sun-esc-bracket t)
+;(setq sun-raw-map-hooks '( ; not your usual hook list
+; (define-key sun-raw-map "211z" 'goto-line) ; R4
+; (define-key sun-raw-map "212z" 'other-window) ; R5
+; (define-key sun-raw-map "213z" 'scroll-other-window) ; R6
+; ))
+
+(defvar sun-esc-bracket nil
+ "*If non-nil, rebind ESC [ as prefix for Sun function keys.")
+
+(defvar sun-raw-map (make-sparse-keymap) "*Keymap for ESC-[ encoded keyboard")
+
+(define-key sun-raw-map "208z" 'unbound-key) ; R1
+(define-key sun-raw-map "209z" 'unbound-key) ; R2
+(define-key sun-raw-map "210z" 'backward-page) ; R3
+(define-key sun-raw-map "213z" 'forward-page) ; R6
+(define-key sun-raw-map "214z" 'beginning-of-buffer) ; R7
+(define-key sun-raw-map "216z" 'scroll-down) ; R9
+(define-key sun-raw-map "215z" 'previous-line) ; R8 (up-arrow)
+(define-key sun-raw-map "217z" 'backward-char) ; R10 (rt-arrow)
+(define-key sun-raw-map "219z" 'forward-char) ; R12 (dn-arrow)
+(define-key sun-raw-map "221z" 'next-line) ; R14 (lf-arrow)
+(define-key sun-raw-map "218z" 'recenter) ; R11
+(define-key sun-raw-map "220z" 'end-of-buffer) ; R13
+(define-key sun-raw-map "222z" 'scroll-up) ; R15
+(define-key sun-raw-map "193z" 'redraw-display) ; Again L1
+(define-key sun-raw-map "194z" 'list-buffers) ; Props L2
+(define-key sun-raw-map "195z" 'undo) ; Undo L3
+(define-key sun-raw-map "196z" 'ignore-key) ; Expose-down L4
+(define-key sun-raw-map "197z" 'sun-select-region) ; Put L5
+(define-key sun-raw-map "198z" 'ignore-key) ; Open-down L6
+(define-key sun-raw-map "199z" 'sun-yank-selection) ; Get L7
+(define-key sun-raw-map "200z" 'exchange-point-and-mark); Find L8
+(define-key sun-raw-map "201z" 'kill-region-and-unmark) ; Delete L9
+(define-key sun-raw-map "207z" 'help-for-help) ; Help Key on Type-4 KBD
+(define-key sun-raw-map "225z" 'toggle-selective-display); T2
+(define-key sun-raw-map "226z" 'scroll-down-in-place) ; T3
+(define-key sun-raw-map "227z" 'scroll-up-in-place) ; T4
+(define-key sun-raw-map "228z" 'shell) ; T5
+(define-key sun-raw-map "229z" 'shrink-window) ; T6
+(define-key sun-raw-map "230z" 'enlarge-window) ; T7
+
+(if sun-esc-bracket
+ (progn
+ (define-key esc-map "[" sun-raw-map) ; Install sun-raw-map
+ (define-key esc-map "[A" 'previous-line ) ; R8
+ (define-key esc-map "[B" 'next-line) ; R14
+ (define-key esc-map "[C" 'forward-char) ; R12
+ (define-key esc-map "[D" 'backward-char) ; R10
+ (define-key esc-map "[[" 'backward-paragraph) ; the original esc-[
+ ))
+
+;;; Since .emacs gets loaded before this file, a hook is supplied
+;;; for you to put your own bindings in.
+
+(defvar sun-raw-map-hooks nil
+ "List of forms to evaluate after setting sun-raw-map.
+This list is processed by: (mapcar 'eval sun-raw-map-hooks)")
+
+(mapcar 'eval sun-raw-map-hooks)
+
+;;; This section adds defintions for the emacstool users
+;;; emacstool event filter converts function keys to C-x*{c}{lrt}
+;;;
+;;; for example the Open key (L7) would be encoded as "\C-x*gl"
+;;; the control, meta, and shift keys modify the character {lrt}
+;;; note that (unshifted) C-l is ",", C-r is "2", and C-t is "4"
+;;;
+;;; {c} is [a-j] for LEFT, [a-i] for TOP, [a-o] for RIGHT.
+;;; A higher level insists on encoding {h,j,l,n}{r} (the arrow keys)
+;;; as ANSI escape sequences. Use the shell command
+;;; % setkeys noarrows
+;;; if you want these to come through for emacstool.
+;;;
+;;; If you are not using EmacsTool,
+;;; you can also use this by creating a .ttyswrc file to do the conversion.
+;;; but it won't include the CONTROL, META, or SHIFT keys!
+;;;
+
+;;; Note: al (STOP), el (EXPOSE) and gl (OPEN) are trapped by EmacsTool,
+;;; so they never make it here.
+
+(defvar meta-flag t)
+
+(defvar suntool-map (make-sparse-keymap)
+ "*Keymap for Emacstool bindings.")
+
+(define-key suntool-map "ar" 'unbound-key) ; R1
+(define-key suntool-map "br" 'unbound-key) ; R2
+(define-key suntool-map "hr" 'previous-line) ; R8 (up-arrow)
+(define-key suntool-map "jr" 'backward-char) ; R10 (rt-arrow)
+(define-key suntool-map "lr" 'forward-char) ; R12 (dn-arrow)
+(define-key suntool-map "nr" 'next-line) ; R14 (lf-arrow)
+(define-key suntool-map "gr" 'beginning-of-buffer) ; r7
+(define-key suntool-map "iR" 'backward-page) ; R9
+(define-key suntool-map "ir" 'scroll-down) ; r9
+(define-key suntool-map "kr" 'recenter) ; r11
+(define-key suntool-map "mr" 'end-of-buffer) ; r13
+(define-key suntool-map "oR" 'forward-page) ; R15
+(define-key suntool-map "or" 'scroll-up) ; r15
+(define-key suntool-map "b\M-L" 'rerun-prev-command) ; M-AGAIN
+(define-key suntool-map "b\M-l" 'repeat-complex-command); M-Again
+(define-key repeat-complex-command-map "\C-x*b\M-l" 'previous-complex-command)
+(define-key suntool-map "bl" 'redraw-display) ; Again L1
+(define-key suntool-map "cl" 'list-buffers) ; Props L2
+(define-key suntool-map "dl" 'undo) ; Undo L3
+(define-key suntool-map "el" 'ignore-key) ; Expose-Top L4
+(define-key suntool-map "fl" 'sun-select-region) ; Put L5
+(define-key suntool-map "f," 'copy-region-as-kill) ; C-Put L5
+(define-key suntool-map "gl" 'ignore-key) ; Open-Open L6
+(define-key suntool-map "hl" 'sun-yank-selection) ; Get L7
+(define-key suntool-map "h\M-l" 'sunview-yank-any-selection) ; M-Get L7
+(define-key suntool-map "h," 'yank) ; C-Get
+;; interactive regexp search ; Find L8
+(define-key suntool-map "iL" 're-isearch-forward) ; FIND (shift-Find)
+(define-key suntool-map "i\M-L" 're-isearch-backward) ; M-FIND (M-shift-Find)
+;; non-interactive versions:
+;; search again, using previous search arg as regexp.
+(define-key suntool-map "il" 'research-forward) ; Find
+(define-key suntool-map "i\M-l" 'research-backward) ; M-Find
+;; supply new arg
+(define-key suntool-map "i," 're-search-forward) ; C-Find
+(define-key suntool-map "i\M-," 're-search-backward) ; C-M-Find
+
+(define-key suntool-map "jL" 'yank) ; DELETE L9
+(define-key suntool-map "jl" 'kill-region-and-unmark) ; Delete
+(define-key suntool-map "j\M-l" 'exchange-point-and-mark); M-Delete
+(define-key suntool-map "j,"
+ '(lambda () (interactive) (pop-mark 1))) ; C-Delete
+(define-key suntool-map "pl" 'describe-mode) ; Help
+(define-key suntool-map "p\M-l" 'command-apropos) ; M-Help
+(define-key suntool-map "pL" 'describe-bindings) ; HELP
+;; Oops, Help is preempted by Xview, may need to modify xvetool
+(define-key suntool-map "p," 'help-for-help) ; C-Help
+(define-key suntool-map "p," 'help-for-dummies) ; C-Help
+
+(define-key suntool-map "bt" 'toggle-selective-display) ; t2
+(define-key suntool-map "cT" '(lambda(n) (interactive "p") (scroll-down n)))
+(define-key suntool-map "dT" '(lambda(n) (interactive "p") (scroll-up n)))
+(define-key suntool-map "ct" 'scroll-down-in-place) ; t3
+(define-key suntool-map "dt" 'scroll-up-in-place) ; t4
+(define-key suntool-map "et" 'shell) ; t5
+(define-key suntool-map "fT" 'shrink-window-horizontally) ; T6
+(define-key suntool-map "gT" 'enlarge-window-horizontally) ; T7
+(define-key suntool-map "ft" 'shrink-window) ; t6
+(define-key suntool-map "gt" 'enlarge-window) ; t7
+(define-key ctl-x-map "*" suntool-map)
+
+;;; Since .emacs gets loaded before this file, a hook is supplied
+;;; for you to put your own bindings in.
+
+;;; Example:
+;(setq suntool-map-hooks '( ; not your usual hook list
+; (define-key suntool-map "c\M-l" 'browse) ; Meta-Props
+; (define-key suntool-map "dr" 'goto-line) ; R4
+; (define-key suntool-map "d2" 'what-line) ; Control-R4
+; ))
+
+(defvar suntool-map-hooks nil
+ "List of forms to evaluate after setting suntool-map.
+This variable is processed by: (mapcar 'eval suntool-map-hooks)")
+
+(mapcar 'eval suntool-map-hooks)
+
+;;;
+;;; If running under emacstool, arrange to call suspend-emacstool
+;;; instead of suspend-emacs.
+;;;
+;;; First mouse blip is a clue that we are in emacstool.
+;;;
+;;; C-x C-@ is the mouse command prefix.
+
+(autoload 'sun-mouse-handler "sun-mouse"
+ "Sun Emacstool handler for mouse blips (not loaded)." t)
+
+(defun sun-mouse-once ()
+ "Converts to emacstool and sun-mouse-handler on first mouse hit."
+ (interactive)
+ (emacstool-init)
+ (sun-mouse-handler) ; Now, execute this mouse blip.
+ )
+(if (not window-system) ; don't do this for X!
+ (define-key ctl-x-map "\C-@" 'sun-mouse-once))
+
+(defun emacstool-init ()
+ "Set up Emacstool window, if you know you are in an emacstool."
+ ;; Make sure sun-mouse and sun-fns are loaded.
+ (require 'sun-fns)
+ (define-key ctl-x-map "\C-@" 'sun-mouse-handler)
+
+ (if (fboundp 'sun-window-init) ()
+ (error "SunWindows support not compiled in: #define HAVE_SUN_WINDOWS in config.h"))
+ (if (and (not (getenv "DISPLAY")) (< (sun-window-init) 0))
+ (message "Not a SunView Window"))
+ (progn
+ (substitute-key-definition 'suspend-emacs 'suspend-emacstool global-map)
+ (substitute-key-definition 'suspend-emacs 'suspend-emacstool esc-map)
+ (substitute-key-definition 'suspend-emacs 'suspend-emacstool ctl-x-map)
+ (send-string-to-terminal
+ (concat "\033]lEmacstool - GNU Emacs " emacs-version "\033\\")))
+ )
+
+;;; If Emacstool is being nice, and informs us of its presence:
+(if (getenv "IN_EMACSTOOL") (emacstool-init))
diff --git a/lisp/term/supdup.el b/lisp/term/supdup.el
new file mode 100644
index 00000000000..4e7ac2ab602
--- /dev/null
+++ b/lisp/term/supdup.el
@@ -0,0 +1,81 @@
+;; Losing unix doesn't know about the -real- control bit
+
+;; there should be some way to conditionalize this on the basis
+;; of %TOFCI -- except that the existing supdup server loses this information!
+;; It isn't clear-cut what to do in the server, as %tofci means that the user
+;; can generate full 9-bit MIT characters, which isn't what the `km' termcap
+;; flag means. On the other hand, being able to generate 8-bit characters
+;; (which is sort of what `km' is) isn't the same as %tofci.
+;; I think the problem is fundamental and cultural and irresolvable.
+
+;; unix supdup server uses 0237 as a control escape.
+;; c-a 001
+;; m-a 341
+;; c-m-a 201
+;; c-1 237 061
+;; m-1 261
+;; c-m-1 237 261
+;; c-m-_ 237 237
+
+(defvar supdup-control-map (make-keymap))
+(fillarray supdup-control-map 'ascii-loses)
+(defvar supdup-control-meta-map (make-keymap))
+(fillarray supdup-control-meta-map 'ascii-loses)
+(define-key supdup-control-meta-map "\C-_" nil) ; this is c-m-_
+(define-key supdup-control-map "\e" supdup-control-meta-map)
+(define-key global-map "\e\C-_" supdup-control-map)
+(let ((n ?0))
+ (while (<= n ?9)
+ (define-key supdup-control-map (char-to-string n) 'supdup-digit-argument)
+ (define-key supdup-control-meta-map (char-to-string n) 'supdup-digit-argument)
+ (setq n (1+ n)))
+ (define-key supdup-control-map "-" 'supdup-digit-argument)
+ (define-key supdup-control-meta-map "-" 'supdup-digit-argument))
+
+(defun ascii-loses ()
+ (interactive)
+ (if (= (aref (this-command-keys) 0) meta-prefix-char)
+ ;; loser typed <esc> c-_ <char>
+ (error "Undefined command: %s"
+ (mapconcat 'text-char-description (this-command-keys) " "))
+ ;; Get here from m-c-_ <char> for c-<char> or m-c-_ m-<char>
+ (error "Ascii loses: c-%s%c"
+ (if (> last-input-char ?\200) "m-" "")
+ (logand last-input-char ?\177))))
+
+
+(defun supdup-digit-argument (p)
+ (interactive "P")
+ (let ((n last-input-char))
+ (if (and (<= (+ ?\200 ?0) n) (<= n (+ ?\200 ?9)))
+ (setq n (- n ?\200)))
+ (cond ((or (= n ?-) (= n ?\M--))
+ (message "Arg: %s" (setq prefix-arg '-)))
+ ((or (< n ?0) (> n ?9))
+ (error "Lossage: %s" (this-command-keys)))
+ (t
+ (setq n (- n ?0))
+ (message "Arg: %d"
+ (setq prefix-arg
+ (cond ((listp p)
+ n)
+ ((eq p '-)
+ (- n))
+ ((>= p 0)
+ (+ (* p 10) n))
+ (t
+ (- (* p 10) n)))))))))
+
+;; Attempt to detect slimebollix machine serving as terminal.
+(if (let ((termcap (getenv "TERMCAP")))
+ (and termcap
+ (string-match ":co#131:li#52:\\|:co#135:li#50:" termcap)))
+ (message "In doing business with Symbolics, you are rewarding a wrong."))
+
+
+;; Mouse support works with Lambdas.
+;(autoload 'sup-mouse-report "sup-mouse"
+; "This command is sent by a special version of Supdup on the LMI Lambda
+;when the mouse is clicked." t)
+;(global-set-key "\C-x\C-@" 'sup-mouse-report)
+
diff --git a/lisp/term/unixpc.el b/lisp/term/unixpc.el
new file mode 100644
index 00000000000..3ebf4d25566
--- /dev/null
+++ b/lisp/term/unixpc.el
@@ -0,0 +1,148 @@
+;;; AT&T UnixPC keyboard definitions
+;;; Brant Cheikes (brant@linc.cis.upenn.edu, manta!brant)
+;;; 4 August 1987
+;;;
+;;; Tested on: GNU Emacs 18.47.1 of Fri Jul 24 1987 on manta (usg-unix-v)
+;;;
+;;; The AT&T Unix PC (aka PC7300, 3B1) has a bizarre keyboard with
+;;; lots of interestingly labeled function keys. This file tries to
+;;; assign useful actions to the function keys. Note that the Shift
+;;; and Ctrl keys have the same effect on function keys, so Shift-F1
+;;; is the same as Ctrl-F1.
+;;;
+;;; Most of the information needed to create this file was taken from
+;;; documentation found in lisp/keypad.el
+;;;
+;;; Bug: The "Beg" and "End" (unshifted) keys are not supported because
+;;; they generate <esc>9 and <esc>0 respectively, and I know not how to
+;;; deal with them.
+
+(require 'keypad)
+
+;;; There seem to be three prefixes for AT&T UnixPC function keys:
+;;; "<esc>O", "<esc>N", and "<esc>[". There seem to be a couple
+;;; keys that just generate "<esc><digit>".
+;;;
+;;; Note: for each mapping, I indicate the key on the Unix PC followed
+;;; by the Emacs command it is bound to (if any). Note that when I
+;;; couldn't figure out anything useful to do with a key, I simply bound
+;;; it to 'previous-line, arbitrarily. My goal was to get keys to do
+;;; "mnemonic" things.
+
+(defvar ATT-map-1 nil
+ "The bulk of the function keys on the AT&T Unix PC.")
+(defvar ATT-map-2 nil
+ "A few other random function keys on the AT&T Unix PC.")
+(defvar ATT-map-3 nil
+ "Some really random function keys on the AT&T Unix PC.")
+
+(defun enable-unixpc-keys ()
+ "Enable the use of the AT&T Unix PC function keys. Because of the
+nature of the Unix PC, this unavoidably breaks several standard Emacs
+prefixes; therefore, it is not done by default, but only if you give
+this command."
+ (interactive)
+ (global-set-key "\eO" ATT-map-1)
+ (global-set-key "\eN" ATT-map-2)
+ (global-set-key "\e[" ATT-map-3))
+
+;;; Create a few new keypad defaults. Here's what I think I'm doing here:
+;;; I look through "keypad.el" to find any unused entries in function-keymap
+;;; and then create my own bindings for them here. Then I use the newly
+;;; created ?x string in the setup-terminal-keymap.
+
+(keypad-default "2" 'advertised-undo)
+(keypad-default "4" 'save-buffers-kill-emacs)
+(keypad-default "5" 'save-buffer)
+(keypad-default "6" 'beginning-of-buffer)
+(keypad-default "8" 'end-of-buffer)
+(keypad-default "w" 'kill-word)
+(keypad-default "p" 'fill-paragraph)
+(keypad-default "," 'copy-region-as-kill)
+
+(if ATT-map-1
+ nil
+ (setq ATT-map-1 (make-keymap)) ; <ESC>O commands
+ (setup-terminal-keymap ATT-map-1
+ '(("a" . ?\^d) ; Clear Line (kill-line)
+ ("A" . ?\^d) ; Shift-Clear Line (kill-line)
+ ("b" . ?u) ; Ref
+ ("B" . ?u) ; Rstrt
+ ("c" . ?u) ; F1
+ ("d" . ?u) ; F2
+ ("e" . ?u) ; F3
+ ("f" . ?u) ; F4
+ ("g" . ?u) ; F5
+ ("h" . ?u) ; F6
+ ("i" . ?u) ; F7
+ ("j" . ?u) ; F8
+ ("k" . ?4) ; Exit (save-buffers-kill-emacs)
+ ("K" . ?4) ; Shift-Exit (save-buffers-kill-emacs)
+ ("m" . ??) ; Help (help-command)
+ ("M" . ??) ; Shift-Help (help-command)
+ ("n" . ?u) ; Creat
+ ("N" . ?u) ; Shift-Creat
+ ("o" . ?5) ; Save (save-buffer)
+ ("O" . ?5) ; Shift-Save (save-buffer)
+ ("r" . ?u) ; Opts
+ ("R" . ?u) ; Shift-Opts
+ ("s" . ?2) ; Undo (advertised-undo)
+ ("S" . ?2) ; Shift-Undo (advertised-undo)
+ ("t" . ?p) ; Redo (fill-paragraph)
+ ("T" . ?p) ; Shift-Redo (fill-paragraph)
+ ("u" . ?u) ; Cmd
+ ("U" . ?u) ; Shift-Cmd
+ ("v" . ?e) ; Open (open-line)
+ ("V" . ?\^d) ; Close (kill-line)
+ ("w" . ?u) ; Cancl
+ ("W" . ?u) ; Shift-Cancl
+ ("x" . ?\^c) ; Find (isearch-forward)
+ ("X" . ?f) ; Shift-Find (re-search-forward)
+ ("y" . ?0) ; Rplac (yank)
+ ("Y" . ?0) ; Shift-Rplac (yank)
+ ("z" . ?u) ; Print
+ )))
+
+(if ATT-map-2
+ nil
+ (setq ATT-map-2 (make-keymap)) ; <ESC>N commands
+ (setup-terminal-keymap ATT-map-2
+ '(("a" . ?C) ; Rfrsh (recenter)
+ ("B" . ?6) ; Shift-Beg (beginning-of-buffer)
+ ("c" . ?0) ; Move (yank)
+ ("C" . ?0) ; Shift-Move (yank)
+ ("d" . ?,) ; Copy (copy-region-as-kill)
+ ("D" . ?,) ; Shift-Copy (copy-region-as-kill)
+ ("e" . ?k) ; Dlete (kill-region)
+ ("E" . ?k) ; Shift-Dlete (kill-region)
+ ("f" . ?.) ; Dlete Char (delete-char)
+ ("F" . ?w) ; Shift-Dlete Char (kill-word)
+ ("g" . ?P) ; Prev (scroll-down)
+ ("G" . ?P) ; Shift-Prev (scroll-down)
+ ("h" . ?N) ; Next (scroll-up)
+ ("H" . ?N) ; Shift-Next (scroll-up)
+ ("i" . ?s) ; Mark (set-mark-command)
+ ("I" . ?s) ; Slect (set-mark-command)
+ ("j" . ?u) ; Input Mode
+ ("J" . ?u) ; Shift-Input Mode
+ ("K" . ?1) ; Shift-LeftArrow (backward-word)
+ ("L" . ?3) ; Shift-RightArrow (forward-word)
+ ("M" . ?h) ; Shift-Home (move-to-window-line)
+ ("N" . ?8) ; Shift-End (end-of-buffer)
+ )))
+
+(if ATT-map-3
+ nil
+ (setq ATT-map-3 (make-keymap)) ; <ESC>[ commands
+ (setup-terminal-keymap ATT-map-3
+ '(("A" . ?u) ; Up Arrow (previous-line)
+ ("B" . ?d) ; Down Arrow (next-line)
+ ("C" . ?r) ; Right Arrow (forward-char)
+ ("D" . ?l) ; Left Arrow (backward-char)
+ ("H" . ?h) ; Home (move-to-window-line)
+ ("J" . ?C) ; Clear (recenter)
+ ("S" . ?9) ; Shift-DownArrow (forward-paragraph)
+ ("T" . ?7) ; Shift-UpArrow (backward-paragraph)
+ ("U" . ?N) ; Page (scroll-up)
+ ("V" . ?P) ; Shift-Page (scroll-down)
+ )))
diff --git a/lisp/term/vt100.el b/lisp/term/vt100.el
new file mode 100644
index 00000000000..435157c9663
--- /dev/null
+++ b/lisp/term/vt100.el
@@ -0,0 +1,66 @@
+;; Map VT100 function key escape sequences
+;; into the standard slots in function-keymap.
+
+(require 'keypad)
+
+(defvar CSI-map nil
+ "The CSI-map maps the CSI function keys on the VT100 keyboard.
+The CSI keys are the arrow keys.")
+
+(if (not CSI-map)
+ (progn
+ (setq CSI-map (lookup-key global-map "\e["))
+ (if (not (keymapp CSI-map))
+ (setq CSI-map (make-sparse-keymap))) ;; <ESC>[ commands
+
+ (setup-terminal-keymap CSI-map
+ '(("A" . ?u) ; up arrow
+ ("B" . ?d) ; down-arrow
+ ("C" . ?r) ; right-arrow
+ ("D" . ?l))))) ; left-arrow
+
+(defun enable-arrow-keys ()
+ "Enable the use of the VT100 arrow keys for cursor motion.
+Because of the nature of the VT100, this unavoidably breaks
+the standard Emacs command ESC [; therefore, it is not done by default,
+but only if you give this command."
+ (interactive)
+ (global-set-key "\e[" CSI-map))
+
+(defvar SS3-map nil
+ "SS3-map maps the SS3 function keys on the VT100 keyboard.
+The SS3 keys are the numeric keypad keys in keypad application mode
+\(DECKPAM). SS3 is DEC's name for the sequence <ESC>O which is
+the common prefix of what these keys transmit.")
+
+(if (not SS3-map)
+ (progn
+
+ (setq SS3-map (lookup-key global-map "\eO"))
+ (if (not (keymapp SS3-map))
+ (setq SS3-map (make-keymap))) ;; <ESC>O commands
+ (setup-terminal-keymap SS3-map
+ '(("A" . ?u) ; up arrow
+ ("B" . ?d) ; down-arrow
+ ("C" . ?r) ; right-arrow
+ ("D" . ?l) ; left-arrow
+ ("M" . ?e) ; Enter
+ ("P" . ?\C-a) ; PF1
+ ("Q" . ?\C-b) ; PF2
+ ("R" . ?\C-c) ; PF3
+ ("S" . ?\C-d) ; PF4
+ ("l" . ?,) ; ,
+ ("m" . ?-) ; -
+ ("n" . ?.) ; .
+ ("p" . ?0) ; 0
+ ("q" . ?1) ; 1
+ ("r" . ?2) ; 2
+ ("s" . ?3) ; 3
+ ("t" . ?4) ; 4
+ ("u" . ?5) ; 5
+ ("v" . ?6) ; 6
+ ("w" . ?7) ; 7
+ ("x" . ?8) ; 8
+ ("y" . ?9))) ; 9
+
+ (define-key global-map "\eO" SS3-map)))
diff --git a/lisp/term/vt101.el b/lisp/term/vt101.el
new file mode 100644
index 00000000000..c35790b72c0
--- /dev/null
+++ b/lisp/term/vt101.el
@@ -0,0 +1 @@
+(load (concat term-file-prefix "vt100") nil t)
diff --git a/lisp/term/vt102.el b/lisp/term/vt102.el
new file mode 100644
index 00000000000..c35790b72c0
--- /dev/null
+++ b/lisp/term/vt102.el
@@ -0,0 +1 @@
+(load (concat term-file-prefix "vt100") nil t)
diff --git a/lisp/term/vt125.el b/lisp/term/vt125.el
new file mode 100644
index 00000000000..c35790b72c0
--- /dev/null
+++ b/lisp/term/vt125.el
@@ -0,0 +1 @@
+(load (concat term-file-prefix "vt100") nil t)
diff --git a/lisp/term/vt131.el b/lisp/term/vt131.el
new file mode 100644
index 00000000000..c35790b72c0
--- /dev/null
+++ b/lisp/term/vt131.el
@@ -0,0 +1 @@
+(load (concat term-file-prefix "vt100") nil t)
diff --git a/lisp/term/vt200.el b/lisp/term/vt200.el
index 162baecd7c1..a394de1cc3d 100644
--- a/lisp/term/vt200.el
+++ b/lisp/term/vt200.el
@@ -1,9 +1,85 @@
-(defun terminal-80-columns ()
- (interactive)
- (send-string-to-terminal "\033[?3l")
- (set-screen-width 80))
+;; vt200 series terminal stuff.
+;; April 1985, Joe Kelsey
+
+(require 'keypad)
-(defun terminal-132-columns ()
+(defvar CSI-map nil
+ "The CSI-map maps the CSI function keys on the VT200 keyboard.
+The CSI keys are the dark function keys, and are only active in
+VT200-mode, except for the arrow keys.")
+
+(defun enable-arrow-keys ()
+ "Enable the use of the VT200 arrow keys and dark function keys.
+Because of the nature of the VT200, this unavoidably breaks
+the standard Emacs command ESC [; therefore, it is not done by default,
+but only if you give this command."
(interactive)
- (send-string-to-terminal "\033[?3h")
- (set-screen-width 132))
+ (global-set-key "\e[" CSI-map))
+
+;; I suggest that someone establish standard mappings for all of
+;; the VT200 CSI function keys into the function-keymap.
+
+(if CSI-map
+ nil
+ (setq CSI-map (make-keymap)) ; <ESC>[ commands
+ (setup-terminal-keymap CSI-map
+ '(("A" . ?u) ; up arrow
+ ("B" . ?d) ; down-arrow
+ ("C" . ?r) ; right-arrow
+ ("D" . ?l) ; left-arrow
+ ("1~" . ?f) ; Find
+ ("2~" . ?I) ; Insert Here
+ ("3~" . ?k) ; Re-move
+ ("4~" . ?s) ; Select
+ ("5~" . ?P) ; Prev Screen
+ ("6~" . ?N) ; Next Screen
+ ("17~" . ?\C-f) ; F6
+ ("18~" . ?\C-g) ; F7
+ ("19~" . ?\C-h) ; F8
+ ("20~" . ?\C-i) ; F9
+ ("21~" . ?\C-j) ; F10
+ ("23~" . ESC-prefix) ; F11 (ESC)
+ ("24~" . ?\C-l) ; F12
+ ("25~" . ?\C-m) ; F13
+ ("26~" . ?\C-n) ; F14
+ ("31~" . ?\C-q) ; F17
+ ("32~" . ?\C-r) ; F18
+ ("33~" . ?\C-s) ; F19
+ ("34~" . ?\C-t) ; F20
+ ("28~" . ??) ; Help
+ ("29~" . ?x)))) ; Do
+
+(defvar SS3-map nil
+ "SS3-map maps the SS3 function keys on the VT200 keyboard.
+The SS3 keys are the numeric keypad keys in keypad application mode
+\(DECKPAM). SS3 is DEC's name for the sequence <ESC>O which is
+the common prefix of what these keys transmit.")
+
+(if SS3-map
+ nil
+ (setq SS3-map (make-keymap)) ; <ESC>O commands
+ (setup-terminal-keymap SS3-map
+ '(("A" . ?u) ; up arrow
+ ("B" . ?d) ; down-arrow
+ ("C" . ?r) ; right-arrow
+ ("D" . ?l) ; left-arrow
+ ("M" . ?e) ; Enter
+ ("P" . ?\C-a) ; PF1
+ ("Q" . ?\C-b) ; PF2
+ ("R" . ?\C-c) ; PF3
+ ("S" . ?\C-d) ; PF4
+ ("l" . ?,) ; ,
+ ("m" . ?-) ; -
+ ("n" . ?.) ; .
+ ("p" . ?0) ; 0
+ ("q" . ?1) ; 1
+ ("r" . ?2) ; 2
+ ("s" . ?3) ; 3
+ ("t" . ?4) ; 4
+ ("u" . ?5) ; 5
+ ("v" . ?6) ; 6
+ ("w" . ?7) ; 7
+ ("x" . ?8) ; 8
+ ("y" . ?9))) ; 9
+
+ (define-key global-map "\eO" SS3-map))
diff --git a/lisp/term/vt220.el b/lisp/term/vt220.el
new file mode 100644
index 00000000000..fdfa64d4f9d
--- /dev/null
+++ b/lisp/term/vt220.el
@@ -0,0 +1 @@
+(load (concat term-file-prefix "vt200") nil t)
diff --git a/lisp/term/vt240.el b/lisp/term/vt240.el
new file mode 100644
index 00000000000..fdfa64d4f9d
--- /dev/null
+++ b/lisp/term/vt240.el
@@ -0,0 +1 @@
+(load (concat term-file-prefix "vt200") nil t)
diff --git a/lisp/term/vt300.el b/lisp/term/vt300.el
new file mode 100644
index 00000000000..fdfa64d4f9d
--- /dev/null
+++ b/lisp/term/vt300.el
@@ -0,0 +1 @@
+(load (concat term-file-prefix "vt200") nil t)
diff --git a/lisp/term/wyse50.el b/lisp/term/wyse50.el
deleted file mode 100644
index 712e1062d00..00000000000
--- a/lisp/term/wyse50.el
+++ /dev/null
@@ -1,235 +0,0 @@
-; Like all the other files in this dir, this one needs to be redone
-; for the new way of handling function keys.
-
-; Terminal mode for Wyse 50
-; should work well for Televideo Tvi 925 though it's an overkill
-; Author Daniel Pfeiffer <pfeiffer@cix.cict.fr> january 1991
-
-(require 'keypad)
-
-; at least some of these should be transferred to keypad.el
-(keypad-default "A" '(lambda () (interactive)
- ; actually insert an empty line
- (beginning-of-line)
- (open-line 1)))
-(keypad-default "E" 'kill-line)
-; (keypad-default "h" 'execute-extended-command)
-(define-key function-keymap "h" 'execute-extended-command) ; bad, bad !!
-(keypad-default "H" 'shell-command)
-(keypad-default "I" '(lambda () (interactive)
- (insert ? ))) ; works even in overwrite-mode
-(keypad-default "L" '(lambda () (interactive)
- ; delete the whole line
- (beginning-of-line)
- (kill-line 1)))
-(keypad-default "M" 'overwrite-mode)
-(keypad-default "\^e" 'shell) ; F5
-(keypad-default "\^f" 'dired) ; F6
-(keypad-default "\^g" 'rnews) ; F7
-(keypad-default "\^h" 'rmail) ; F8
-
-(keypad-default "\^i" 'delete-other-windows) ; F9
-(keypad-default "\^j" 'other-window) ; F10
-(keypad-default "\^k" 'split-window-vertically) ; F11
-
-(keypad-default "\^m" 'help-for-help) ; F13
-(keypad-default "\^n" 'toggle-screen-width) ; F14
-(keypad-default "\^o" 'set-function-key) ; F15
-
-
-; Keys that don't conflict with Emacs defaults
-; I write \M-x and \C-x for what the user types, \ex and \^x for key sequences
-(setup-terminal-keymap global-map
- '(("\M-?" . ?\?) ; Esc ?
- ("\eI" . ?T) ; Shift Tab
- ("\eJ" . ?P) ; Shift Prev PAGE
- ("\eK" . ?N) ; PAGE Next
- ("\eY" . ?C) ; Shift Scrn CLR
- ("\eT" . ?E) ; CLR Line
- ("\^^" . ?h) ; Home
- ("\M-\^^" . ?H) ; Esc Home
- ("\eQ" . ?I) ; INS Char
- ("\eE" . ?A) ; Shift Line INS
- ("\eW" . ?D) ; DEL Char
- ("\eR" . ?L))) ; Shift Line DEL
-
-; Print -- put in some extra security
-(global-set-key "\eP" '(lambda () (interactive)
- (if (y-or-n-p
- (concat "Print buffer "
- (buffer-name) "? "))
- (print-buffer))))
-
-
-; this is an ugly hack for a nasty problem:
-; Wyse 50 takes one character cell to store video attributes (which seems to
-; explain width 79 rather than 80, column 1 is not used!!!).
-; On killing (C-x C-c) the end inverse code (on column 1 of line 24)
-; of the mode line is overwritten AFTER all the y-or-n questions.
-; This causes the attribute to remain in effect until the mode line has
-; scrolled of the screen. Suspending (C-z) does not cause this problem.
-; On such terminals, Emacs should sacrifice the first and last character of
-; each mode line, rather than a whole screen column!
-(setq kill-emacs-hook '(lambda () (interactive)
- (send-string-to-terminal
- (concat "\ea23R" (1+ (screen-width)) "C\eG0"))))
-
-
-; This function does more than its name which was copied from term/vt100.el
-; Some more neutral name should be used thru-out term/*.el to simplify
-; programming term-setup-hook
-(defun enable-arrow-keys ()
- "To be called by term-setup-hook. Overrides 6 Emacs standard keys
-whose functions are then typed as follows:
-C-a Funct left-arrow, C-a C-a
-C-h M-?
-LFD Funct Return, some modes override down-arrow via LFD
-C-k CLR Line
-C-l Shift Scrn CLR
-M-r M-x move-to-window-line, Funct up-arrow or down-arrow are similar
-All special keys except Send, Shift Ins, Shift Home and shifted functions keys
-are assigned some hopefully useful meaning."
- (interactive)
-
- ; Function keys
- (define-key global-map "\^a" (define-prefix-command 'Funct-prefix))
-
- ; Arrow keys
- (setup-terminal-keymap global-map
- '(("\C-a\C-a" . beginning-of-line) ; for auld lang syne
- ("\^a\^m\^m" . newline-and-indent)
-
- ("\^k" . ?u) ; up-arrow
- ("\^j" . ?d) ; down-arrow
- ("\^l" . ?r) ; right-arrow
- ("\^h" . ?l) ; left-arrow
-
- ; Terminal needs both Ins and Repl but Emacs knows how to toggle
- ; with just one key. No need to override Ins which is "\eq".
- ("\er" . ?M) ; Repl
-
- ("\^a\^i\^m" . ?t) ; Funct Tab
-
- ; Function keys F1 thru F16 (we don't define shifted function keys,
- ; they send the same code with the middle character in lowercase.
- ; eg. "Shift F2" is the same as "Funct a" which is more mnemonic but
- ; keypad.el doesn't provide enough codes to accomodate all these)
- ("\^a@\^m" . 1) ("\^aH\^m" . 9)
- ("\^aA\^m" . 2) ("\^aI\^m" . 10)
- ("\^aB\^m" . 3) ("\^aJ\^m" . 11)
- ("\^aC\^m" . 4) ("\^aK\^m" . 12)
- ("\^aD\^m" . 5) ("\^aL\^m" . 13)
- ("\^aE\^m" . 6) ("\^aM\^m" . 14)
- ("\^aF\^m" . 7) ("\^aN\^m" . 15)
- ("\^aG\^m" . 8) ("\^aO\^m" . 16)
-
- ; Funct Arrow keys
- ("\^a\^k\^m" . (lambda (n) (interactive "p")
- (move-to-window-line (1- n))))
- ("\^a\^j\^m" . (lambda (n) (interactive "p")
- (move-to-window-line (- n))))
- ("\^a\^h\^m" . beginning-of-line)
- ("\^a\^l\^m" . end-of-line)))
-
- ; forget self to put memory to some serious use
- (fmakunbound 'enable-arrow-keys))
-
-
-(defun toggle-screen-width ()
- "Alternate between 80 and 132 columns."
- (interactive)
- (if (<= (screen-width) 80)
- (progn
- (send-string-to-terminal "\e`;")
- (set-screen-width 131))
- (send-string-to-terminal "\e`:")
- (set-screen-width 79)))
-
-;-----------------------------------------------------------------------------
-; this function is completely independent of wyse, it should be auto-loadable
-; (presumably from keypad.el) for use in ~/emacs. It should be the only thing
-; users need to know about all this unintelligible "forwarding" gibberish.
-; This paves the way for a save-function-keys (some day or sleepless night)
-; that will edit calls like (set-function-key ?x 'do-whatever) in ~/.emacs.
-(defun set-function-key (key &optional def)
- "Prompt for a function or other special key and assign it a meaning.
-The key must have been \"forwarded\" to a character by term/*.el.
-
-As a function takes two args CHAR and DEF, with DEF as in define-key.
-If your terminals term/*.el forwards a physical key to CHAR (before or after
-calling this function), then that key will mean DEF, else it is ignored.
-CHAR is one of the following:
-For numbered function keys
- 0, 1, ..., 24 (or ?\\^@, ?\\^a, ..., ?\\^x which is the same)
-For keypad keys in application mode
- ?0, ?1, ..., ?9 -- keypad key labelled with that digit,
- but only if that key is not an arrow key (see ?u, ?d, ?r, ?l).
- ?- -- keypad key labelled `-'.
- ?. -- keypad key labelled `.'.
- ?, -- keypad key labelled `,'.
- ?e -- key labelled enter.
-For keys labelled with some words or a symbol
- ?a -- clear all tabs key.
- ?A -- insert line key.
- ?C -- clear screen key.
- ?c -- erase key.
- ?D -- delete character key.
- ?d -- down-arrow.
- ?E -- clear to end of line key.
- ?e -- key labelled enter.
- ?f -- find key or search key.
- ?F -- scroll forward key.
- ?H -- home-down.
- ?h -- home-position key.
- ?I -- insert character key
- If there is just an \"insert\" key, it should be this.
- ?k -- delete key or remove key.
- ?L -- delete line key.
- ?l -- left-arrow.
- ?M -- exit insert mode key.
- ?N -- next page key.
- ?p -- portrait mode.
- ?P -- previous page key.
- ?q -- landscape mode.
- ?r -- right-arrow.
- ?R -- scroll reverse key.
- ?S -- clear to end of screen key.
- ?s -- select key.
- ?t -- clear tab this column key.
- ?T -- set tab this column key.
- ?u -- up-arrow.
- ?x -- do key.
- ?\\? -- help."
- (interactive "kHit key to redefine")
- (let ((map function-keymap))
- (if (integerp key)
- ()
- ; reinvent lookup-key to get (map . char) instead of def of char in map
- (setq map (or (lookup-key global-map
- (substring key 0 (1- (length key))))
- global-map)
- key (string-to-char (substring key (1- (length key)))))
- (while (symbolp map)
- (setq map (symbol-function map)))
- (setq map (if (listp map)
- (cdr (assq key (cdr map)))
- (aref map key)))
- (if (and (consp map)
- (integerp (cdr map)))
- (setq key (cdr map)
- map (car map)) ; function-keymap usually
- (error "Key is not a \"forwarded\" definition.")))
- (if def
- ()
- (setq def (read-command "command (default last keyboard macro): "))
- (if (string-equal (symbol-name def) "")
- (setq def last-kbd-macro))
- (setq command-history ; nonsense really, since you don't see
- (cons ; key as in a function call (?char)
- (list 'set-function-key key
- (if (stringp def) def (list 'quote def)))
- command-history)))
- ; all we do when called as a function
- (define-key map (char-to-string key) def)))
-
-
diff --git a/lisp/term/x-win.el b/lisp/term/x-win.el
index feff6de1865..5d7670a66ac 100644
--- a/lisp/term/x-win.el
+++ b/lisp/term/x-win.el
@@ -1,615 +1,222 @@
;; Parse switches controlling how Emacs interfaces with X window system.
-;; Copyright (C) 1990 Free Software Foundation, Inc.
+;; Copyright (C) 1986, 1988 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY. No author or distributor
-;; accepts responsibility to anyone for the consequences of using it
-;; or for whether it serves any particular purpose or works at all,
-;; unless he says so in writing. Refer to the GNU Emacs General Public
-;; License for full details.
-
-;; Everyone is granted permission to copy, modify and redistribute
-;; GNU Emacs, but only under the conditions described in the
-;; GNU Emacs General Public License. A copy of this license is
-;; supposed to have been given to you along with GNU Emacs so you
-;; can know your rights and responsibilities. It should be in a
-;; file named COPYING. Among other things, the copyright notice
-;; and this notice must be preserved on all copies.
-
-
-;; X-win.el: this file is loaded from ../lisp/startup.el when it recognizes
-;; that X windows are to be used. Command line switches are parsed and those
-;; pertaining to X are processed and removed from the command line. The
-;; X display is opened and hooks are set for popping up the initial window.
-
-;; startup.el will then examine startup files, and eventually call the hooks
-;; which create the first window (s).
-
-;; These are the standard X switches from the Xt Initialize.c file of
-;; Release 4.
-
-;; Command line Resource Manager string
-
-;; +rv *reverseVideo
-;; +synchronous *synchronous
-;; -background *background
-;; -bd *borderColor
-;; -bg *background
-;; -bordercolor *borderColor
-;; -borderwidth .borderWidth
-;; -bw .borderWidth
-;; -display .display
-;; -fg *foreground
-;; -fn *font
-;; -font *font
-;; -foreground *foreground
-;; -geometry .geometry
-;; -iconic .iconic
-;; -name .name
-;; -reverse *reverseVideo
-;; -rv *reverseVideo
-;; -selectionTimeout .selectionTimeout
-;; -synchronous *synchronous
-;; -title .title
-;; -xrm
-
-;; An alist of X options and the function which handles them. See
-;; ../startup.el.
-
-;; This is a temporary work-around while we the separate keymap
-;; stuff isn't yet fixed. These variables aren't used anymore,
-;; but the lisp code wants them to exist. -JimB
-(setq global-mouse-map (make-sparse-keymap))
-(setq global-function-map (make-sparse-keymap))
-
-(setq command-switch-alist
- (append '(("-dm" . x-establish-daemon-mode)
- ("-bw" . x-handle-numeric-switch)
- ("-d" . x-handle-display)
- ("-display" . x-handle-display)
- ("-name" . x-handle-switch)
- ("-T" . x-handle-switch)
- ("-r" . x-handle-switch)
- ("-rv" . x-handle-switch)
- ("-reverse" . x-handle-switch)
- ("-fn" . x-handle-switch)
- ("-font" . x-handle-switch)
- ("-ib" . x-handle-switch)
- ("-g" . x-handle-geometry)
- ("-geometry" . x-handle-geometry)
- ("-fg" . x-handle-switch)
- ("-foreground" . x-handle-switch)
- ("-bg" . x-handle-switch)
- ("-background" . x-handle-switch)
- ("-ms" . x-handle-switch)
- ("-ib" . x-handle-switch)
- ("-iconic" . x-handle-switch)
- ("-cr" . x-handle-switch)
- ("-vb" . x-handle-switch)
- ("-hb" . x-handle-switch)
- ("-bd" . x-handle-switch))
- command-switch-alist))
-
-(defvar x-switches-specified nil)
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 1, or (at your option)
+;; any later version.
-(defconst x-switch-definitions
- '(("-name" name)
- ("-T" name)
- ("-r" lose)
- ("-rv" lose)
- ("-reverse" lose)
- ("-fn" font)
- ("-font" font)
- ("-ib" internal-border-width)
- ("-fg" foreground-color)
- ("-foreground" foreground-color)
- ("-bg" background-color)
- ("-background" background-color)
- ("-ms" mouse-color)
- ("-cr" cursor-color)
- ("-ib" icon-type t)
- ("-iconic" iconic-startup t)
- ("-vb" vertical-scroll-bar t)
- ("-hb" horizontal-scroll-bar t)
- ("-bd" border-color)
- ("-bw" border-width)))
-
-;; Handler for switches of the form "-switch value" or "-switch".
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+(defconst window-system-version window-system-version
+ "*Window system version number now in use.")
+
+(defvar x-sigio-bug nil
+ "Non-NIL means don't use interrupts for input when using X.")
+
+(defvar x-processed-defaults nil
+ "Non-NIL means that user's X defaults have already been processed.")
+
+(defvar x-switches nil
+ "Alist of command switches and values for X window system interface.
+You can set this in your init file, if you want some defaults
+for these switches. Example:
+ (setq x-switches '((\"-r\" . t) (\"-font\" . \"foo\") (\"-b\" . \"8\")))
+This feature is currently broken for X11.")
+
+(if (= window-system-version 10)
+ (setq command-switch-alist
+ (append '(("-r" . x-handle-switch)
+ ("-i" . x-handle-switch)
+ ("-font" . x-handle-switch)
+ ("-w" . x-handle-switch)
+ ("-b" . x-handle-switch)
+ ("-ib" . x-handle-switch)
+ ("-fg" . x-handle-switch)
+ ("-bg" . x-handle-switch)
+ ("-bd" . x-handle-switch)
+ ("-cr" . x-handle-switch)
+ ("-ms" . x-handle-switch))
+ command-switch-alist))
+ (setq command-switch-alist
+ (append '(("-rn" . x-ignore-arg)
+ ("-xrm" . x-ignore-arg)
+ ("-r" . ignore)
+ ("-i" . ignore)
+ ("-rn" . x-ignore-arg)
+ ("-font" . x-ignore-arg)
+ ("-fn" . x-ignore-arg)
+ ("-wn" . x-ignore-arg)
+ ("-in" . x-ignore-arg)
+ ("-w" . x-ignore-arg)
+ ("-geometry" . x-ignore-arg)
+ ("-b" . x-ignore-arg)
+ ("-ib" . x-ignore-arg)
+ ("-fg" . x-ignore-arg)
+ ("-bg" . x-ignore-arg)
+ ("-bd" . x-ignore-arg)
+ ("-cr" . x-ignore-arg)
+ ("-ms" . x-ignore-arg))
+ command-switch-alist)))
+
+(defun x-ignore-arg (&rest ignore)
+ (setq command-line-args-left (cdr command-line-args-left)))
+
+;; This is run after the command args are parsed.
(defun x-handle-switch (switch)
- (let ((aelt (assoc switch x-switch-definitions)))
- (if aelt
- (if (nth 2 aelt)
- (setq x-switches-specified
- (cons (cons (nth 1 aelt) (nth 2 aelt))
- x-switches-specified))
- (setq x-switches-specified
- (cons (cons (nth 1 aelt)
- (car x-invocation-args))
- x-switches-specified)
- x-invocation-args (cdr x-invocation-args))))))
-
-;; Handler for switches of the form "-switch n"
-(defun x-handle-numeric-switch (switch)
- (let ((aelt (assoc switch x-switch-definitions)))
- (if aelt
- (setq x-switches-specified
- (cons (cons (nth 1 aelt)
- (string-to-int (car x-invocation-args)))
- x-switches-specified)
- x-invocation-args
- (cdr x-invocation-args)))))
-
-;; Handle the geometry option
-(defun x-handle-geometry (switch)
- (setq x-switches-specified (append x-switches-specified
- (x-geometry (car x-invocation-args)))
- x-invocation-args (cdr x-invocation-args)))
-
-;; The daemon stuff isn't really useful at the moment.
-(defvar x-daemon-mode nil
- "When set, means initially create just a minibuffer.")
-
-(defun x-establish-daemon-mode (switch)
- (setq x-daemon-mode t))
-
-(defvar x-display-name nil
- "The X display name specifying server and X screen.")
-
-(defun x-handle-display (switch)
- (setq x-display-name (car x-invocation-args)
- x-invocation-args (cdr x-invocation-args)))
-
-;; Here the X-related command line options are processed, before the user's
-;; startup file is loaded. These are present in ARGS (see startup.el).
-;; They are copied to x-invocation args from which the X-related things
-;; are extracted, first the switch (e.g., "-fg") in the following code,
-;; and possible values (e.g., "black") in the option handler code
-;; (e.g., x-handle-switch).
-
-;; When finished, only things not pertaining to X (e.g., "-q", filenames)
-;; are left in ARGS
-
-(defvar x-invocation-args nil)
+ (if (x-handle-switch-1 switch (car command-line-args-left))
+ (setq command-line-args-left (cdr command-line-args-left))))
+
+(defun x-handle-switch-1 (switch arg)
+ (cond ((string= switch "-r")
+ (x-flip-color)
+ nil)
+ ((string= switch "-i")
+ (x-set-icon t)
+ nil)
+ ((string= switch "-font")
+ (x-set-font arg)
+ t)
+ ((string= switch "-b")
+ (x-set-border-width (string-to-int arg))
+ t)
+ ((string= switch "-ib")
+ (x-set-internal-border-width (string-to-int arg))
+ t)
+ ((string= switch "-w")
+ (x-create-x-window arg)
+ t)
+ ((string= switch "-fg")
+ (x-set-foreground-color arg)
+ t)
+ ((string= switch "-bg")
+ (x-set-background-color arg)
+ t)
+ ((string= switch "-bd")
+ (x-set-border-color arg)
+ t)
+ ((string= switch "-cr")
+ (x-set-cursor-color arg)
+ t)
+ ((string= switch "-ms")
+ (x-set-mouse-color arg)
+ t)))
+
+;; Convert a string of the form "WWxHH+XO+YO",
+;; where WW, HH, XO and YO are numerals,
+;; into a list (WW HH XO YO).
+;; "xHH" may be omitted; then 0 is used for HH.
+;; XO and YO may be preceded by - instead of + to make them negative.
+;; Either YO or both XO and YO may be omitted; zero is used.
+(defun x-parse-edge-spec (arg)
+ (let ((cols-by-font 0)
+ (rows-by-font 0)
+ (xoffset 0)
+ (yoffset 0))
+ (if (string-match "^=" arg)
+ (setq cols-by-font (x-extract-number))
+ (error "Invalid X window size/position spec"))
+ (if (string-match "^x" arg) ;get rows-by-font
+ (setq rows-by-font (x-extract-number)))
+ (if (string-match "^[-+]" arg)
+ (setq xoffset (x-extract-number)))
+ (if (string-match "^[-+]" arg)
+ (setq yoffset (x-extract-number)))
+ (or (equal arg "")
+ (error "Invalid X window size/position spec"))
+ (list cols-by-font rows-by-font xoffset yoffset)))
+
+;; Subroutine to extract the next numeral from the front of arg,
+;; returning it and shortening arg to remove its text.
+;; If arg is negative, subtract 1 before returning it.
+(defun x-extract-number ()
+ (if (string-match "^[x=]" arg)
+ (setq arg (substring arg 1)))
+ (or (string-match "[-+]?[0-9]+" arg)
+ (error "Invalid X window size/position spec"))
+ (prog1
+ (+ (string-to-int arg)
+ (if (string-match "^-" arg) -1 0))
+ (setq arg
+ (substring arg
+ (or (string-match "[^0-9]" arg 1)
+ (length arg))))))
+
+(defun x-get-default-args ()
+ (setq x-processed-defaults t)
+ (let (value)
+ (if (not (string= (setq value (x-get-default "bodyfont")) ""))
+ (x-handle-switch-1 "-font" value))
+ (if (string-match "on" (x-get-default "bitmapicon"))
+ (x-handle-switch-1 "-i" t))
+ (if (not (string= (setq value (x-get-default "borderwidth")) ""))
+ (x-handle-switch-1 "-b" value))
+ (if (not (string= (setq value (x-get-default "internalborder")) ""))
+ (x-handle-switch-1 "-ib" value))
+ (if (not (string= (setq value (x-get-default "foreground")) ""))
+ (x-handle-switch-1 "-fg" value))
+ (if (not (string= (setq value (x-get-default "background")) ""))
+ (x-handle-switch-1 "-bg" value))
+ (if (not (string= (setq value (x-get-default "border")) ""))
+ (x-handle-switch-1 "-bd" value))
+ (if (not (string= (setq value (x-get-default "cursor")) ""))
+ (x-handle-switch-1 "-cr" value))
+ (if (not (string= (setq value (x-get-default "mouse")) ""))
+ (x-handle-switch-1 "-ms" value))
+ (if (string-match "on" (x-get-default "reversevideo"))
+ (x-handle-switch-1 "-r" t))))
+
+;; So far we have only defined some functions.
+;; Now we start processing X-related switches
+;; and redefining commands and variables,
+;; only if Emacs has been compiled to support direct interface to X.
(if (eq window-system 'x)
(progn
- (setq window-setup-hook 'x-pop-initial-window
- x-invocation-args args
- args nil)
(require 'x-mouse)
- (require 'screen)
- (setq suspend-hook
- '(lambda ()
- (error "Suspending an emacs running under X makes no sense")))
- (define-key global-map "" 'iconify-emacs)
- (while x-invocation-args
- (let* ((this-switch (car x-invocation-args))
- (aelt (assoc this-switch command-switch-alist)))
- (setq x-invocation-args (cdr x-invocation-args))
- (if aelt
- (funcall (cdr aelt) this-switch)
- (setq args (cons this-switch args)))))
- (setq args (nreverse args))
- (x-open-connection (or x-display-name
- (setq x-display-name (getenv "DISPLAY"))))
- ;;
- ;; This is the place to handle Xresources
- ;;
- )
- (error "Loading x-win.el but not compiled for X"))
-
-
-;; This is the function which creates the first X window. It is called
-;; from startup.el after the user's init file is processed.
-
-(defun x-pop-initial-window ()
- ;; xterm.c depends on using interrupt-driven input.
- (set-input-mode t nil t)
- (setq mouse-motion-handler 'x-track-pointer)
- (setq x-switches-specified (append x-switches-specified
- initial-screen-alist
- screen-default-alist))
- ;; see screen.el for this function
- (pop-initial-screen x-switches-specified)
- (delete-screen terminal-screen))
-
-
-;;
-;; Standard X cursor shapes, courtesy of Mr. Fox, who wanted ALL of them.
-;;
-
-(defconst x-pointer-X-cursor 0)
-(defconst x-pointer-arrow 2)
-(defconst x-pointer-based-arrow-down 4)
-(defconst x-pointer-based-arrow-up 6)
-(defconst x-pointer-boat 8)
-(defconst x-pointer-bogosity 10)
-(defconst x-pointer-bottom-left-corner 12)
-(defconst x-pointer-bottom-right-corner 14)
-(defconst x-pointer-bottom-side 16)
-(defconst x-pointer-bottom-tee 18)
-(defconst x-pointer-box-spiral 20)
-(defconst x-pointer-center-ptr 22)
-(defconst x-pointer-circle 24)
-(defconst x-pointer-clock 26)
-(defconst x-pointer-coffee-mug 28)
-(defconst x-pointer-cross 30)
-(defconst x-pointer-cross-reverse 32)
-(defconst x-pointer-crosshair 34)
-(defconst x-pointer-diamond-cross 36)
-(defconst x-pointer-dot 38)
-(defconst x-pointer-dotbox 40)
-(defconst x-pointer-double-arrow 42)
-(defconst x-pointer-draft-large 44)
-(defconst x-pointer-draft-small 46)
-(defconst x-pointer-draped-box 48)
-(defconst x-pointer-exchange 50)
-(defconst x-pointer-fleur 52)
-(defconst x-pointer-gobbler 54)
-(defconst x-pointer-gumby 56)
-(defconst x-pointer-hand1 58)
-(defconst x-pointer-hand2 60)
-(defconst x-pointer-heart 62)
-(defconst x-pointer-icon 64)
-(defconst x-pointer-iron-cross 66)
-(defconst x-pointer-left-ptr 68)
-(defconst x-pointer-left-side 70)
-(defconst x-pointer-left-tee 72)
-(defconst x-pointer-leftbutton 74)
-(defconst x-pointer-ll-angle 76)
-(defconst x-pointer-lr-angle 78)
-(defconst x-pointer-man 80)
-(defconst x-pointer-middlebutton 82)
-(defconst x-pointer-mouse 84)
-(defconst x-pointer-pencil 86)
-(defconst x-pointer-pirate 88)
-(defconst x-pointer-plus 90)
-(defconst x-pointer-question-arrow 92)
-(defconst x-pointer-right-ptr 94)
-(defconst x-pointer-right-side 96)
-(defconst x-pointer-right-tee 98)
-(defconst x-pointer-rightbutton 100)
-(defconst x-pointer-rtl-logo 102)
-(defconst x-pointer-sailboat 104)
-(defconst x-pointer-sb-down-arrow 106)
-(defconst x-pointer-sb-h-double-arrow 108)
-(defconst x-pointer-sb-left-arrow 110)
-(defconst x-pointer-sb-right-arrow 112)
-(defconst x-pointer-sb-up-arrow 114)
-(defconst x-pointer-sb-v-double-arrow 116)
-(defconst x-pointer-shuttle 118)
-(defconst x-pointer-sizing 120)
-(defconst x-pointer-spider 122)
-(defconst x-pointer-spraycan 124)
-(defconst x-pointer-star 126)
-(defconst x-pointer-target 128)
-(defconst x-pointer-tcross 130)
-(defconst x-pointer-top-left-arrow 132)
-(defconst x-pointer-top-left-corner 134)
-(defconst x-pointer-top-right-corner 136)
-(defconst x-pointer-top-side 138)
-(defconst x-pointer-top-tee 140)
-(defconst x-pointer-trek 142)
-(defconst x-pointer-ul-angle 144)
-(defconst x-pointer-umbrella 146)
-(defconst x-pointer-ur-angle 148)
-(defconst x-pointer-watch 150)
-(defconst x-pointer-xterm 152)
-
-;;
-;; Available colors
-;;
-
-(defvar x-colors '("aquamarine"
- "Aquamarine"
- "medium aquamarine"
- "MediumAquamarine"
- "black"
- "Black"
- "blue"
- "Blue"
- "cadet blue"
- "CadetBlue"
- "cornflower blue"
- "CornflowerBlue"
- "dark slate blue"
- "DarkSlateBlue"
- "light blue"
- "LightBlue"
- "light steel blue"
- "LightSteelBlue"
- "medium blue"
- "MediumBlue"
- "medium slate blue"
- "MediumSlateBlue"
- "midnight blue"
- "MidnightBlue"
- "navy blue"
- "NavyBlue"
- "navy"
- "Navy"
- "sky blue"
- "SkyBlue"
- "slate blue"
- "SlateBlue"
- "steel blue"
- "SteelBlue"
- "coral"
- "Coral"
- "cyan"
- "Cyan"
- "firebrick"
- "Firebrick"
- "brown"
- "Brown"
- "gold"
- "Gold"
- "goldenrod"
- "Goldenrod"
- "medium goldenrod"
- "MediumGoldenrod"
- "green"
- "Green"
- "dark green"
- "DarkGreen"
- "dark olive green"
- "DarkOliveGreen"
- "forest green"
- "ForestGreen"
- "lime green"
- "LimeGreen"
- "medium forest green"
- "MediumForestGreen"
- "medium sea green"
- "MediumSeaGreen"
- "medium spring green"
- "MediumSpringGreen"
- "pale green"
- "PaleGreen"
- "sea green"
- "SeaGreen"
- "spring green"
- "SpringGreen"
- "yellow green"
- "YellowGreen"
- "dark slate grey"
- "DarkSlateGrey"
- "dark slate gray"
- "DarkSlateGray"
- "dim grey"
- "DimGrey"
- "dim gray"
- "DimGray"
- "light grey"
- "LightGrey"
- "light gray"
- "LightGray"
- "gray"
- "grey"
- "Gray"
- "Grey"
- "khaki"
- "Khaki"
- "magenta"
- "Magenta"
- "maroon"
- "Maroon"
- "orange"
- "Orange"
- "orchid"
- "Orchid"
- "dark orchid"
- "DarkOrchid"
- "medium orchid"
- "MediumOrchid"
- "pink"
- "Pink"
- "plum"
- "Plum"
- "red"
- "Red"
- "indian red"
- "IndianRed"
- "medium violet red"
- "MediumVioletRed"
- "orange red"
- "OrangeRed"
- "violet red"
- "VioletRed"
- "salmon"
- "Salmon"
- "sienna"
- "Sienna"
- "tan"
- "Tan"
- "thistle"
- "Thistle"
- "turquoise"
- "Turquoise"
- "dark turquoise"
- "DarkTurquoise"
- "medium turquoise"
- "MediumTurquoise"
- "violet"
- "Violet"
- "blue violet"
- "BlueViolet"
- "wheat"
- "Wheat"
- "white"
- "White"
- "yellow"
- "Yellow"
- "green yellow"
- "GreenYellow")
- "The full list of X colors from the rgb.text file.")
-
-(defun x-defined-colors ()
- "Return a list of colors supported by the current X-Display."
- (let ((all-colors x-colors)
- (this-color nil)
- (defined-colors nil))
- (while all-colors
- (setq this-color (car all-colors)
- all-colors (cdr all-colors))
- (and (x-defined-color this-color)
- (setq defined-colors (cons this-color defined-colors))))
- defined-colors))
-
-
-;;
-;; Function key processing under X. Function keys are received through
-;; in the input stream as Lisp symbols.
-;;
-
-(defun define-function-key (map sym definition)
- (let ((exist (assq sym (cdr map))))
- (if exist
- (setcdr exist definition)
- (setcdr map
- (cons (cons sym definition)
- (cdr map))))))
-
-;; For unused keysyms. If this happens, it's probably a server or
-;; Xlib bug.
-
-(defun weird-x-keysym ()
- (interactive)
- (error "Bizarre X keysym received."))
-(define-function-key global-function-map 'xk-not-serious 'weird-x-keysym)
-
-;; Keypad type things
-
-(define-function-key global-function-map 'xk-home 'beginning-of-line)
-(define-function-key global-function-map 'xk-left 'backward-char)
-(define-function-key global-function-map 'xk-up 'previous-line)
-(define-function-key global-function-map 'xk-right 'forward-char)
-(define-function-key global-function-map 'xk-down 'next-line)
-(define-function-key global-function-map 'xk-prior 'previous-line)
-(define-function-key global-function-map 'xk-next 'next-line)
-(define-function-key global-function-map 'xk-end 'end-of-line)
-(define-function-key global-function-map 'xk-begin 'beginning-of-line)
-
- ;; IsMiscFunctionKey
-
-(define-function-key global-function-map 'xk-select nil)
-(define-function-key global-function-map 'xk-print nil)
-(define-function-key global-function-map 'xk-execute nil)
-(define-function-key global-function-map 'xk-insert nil)
-(define-function-key global-function-map 'xk-undo nil)
-(define-function-key global-function-map 'xk-redo nil)
-(define-function-key global-function-map 'xk-menu nil)
-(define-function-key global-function-map 'xk-find nil)
-(define-function-key global-function-map 'xk-cancel nil)
-(define-function-key global-function-map 'xk-help nil)
-(define-function-key global-function-map 'xk-break nil)
-
- ;; IsKeypadKey
-
-(define-function-key global-function-map 'xk-kp-space
- '(lambda nil (interactive)
- (insert " ")))
-(define-function-key global-function-map 'xk-kp-tab
- '(lambda nil (interactive)
- (insert "\t")))
-(define-function-key global-function-map 'xk-kp-enter
- '(lambda nil (interactive)
- (insert "\n")))
-
-(define-function-key global-function-map 'xk-kp-f1 nil)
-(define-function-key global-function-map 'xk-kp-f2 nil)
-(define-function-key global-function-map 'xk-kp-f3 nil)
-(define-function-key global-function-map 'xk-kp-f4 nil)
-
-(define-function-key global-function-map 'xk-kp-equal
- '(lambda nil (interactive)
- (insert "=")))
-(define-function-key global-function-map 'xk-kp-multiply
- '(lambda nil (interactive)
- (insert "*")))
-(define-function-key global-function-map 'xk-kp-add
- '(lambda nil (interactive)
- (insert "+")))
-(define-function-key global-function-map 'xk-kp-separator
- '(lambda nil (interactive)
- (insert ";")))
-(define-function-key global-function-map 'xk-kp-subtract
- '(lambda nil (interactive)
- (insert "-")))
-(define-function-key global-function-map 'xk-kp-decimal
- '(lambda nil (interactive)
- (insert ".")))
-(define-function-key global-function-map 'xk-kp-divide
- '(lambda nil (interactive)
- (insert "/")))
-
-(define-function-key global-function-map 'xk-kp-0
- '(lambda nil (interactive)
- (insert "0")))
-(define-function-key global-function-map 'xk-kp-1
- '(lambda nil (interactive)
- (insert "1")))
-(define-function-key global-function-map 'xk-kp-2
- '(lambda nil (interactive)
- (insert "2")))
-(define-function-key global-function-map 'xk-kp-3
- '(lambda nil (interactive)
- (insert "3")))
-(define-function-key global-function-map 'xk-kp-4
- '(lambda nil (interactive)
- (insert "4")))
-(define-function-key global-function-map 'xk-kp-5
- '(lambda nil (interactive)
- (insert "5")))
-(define-function-key global-function-map 'xk-kp-6
- '(lambda nil (interactive)
- (insert "6")))
-(define-function-key global-function-map 'xk-kp-7
- '(lambda nil (interactive)
- (insert "7")))
-(define-function-key global-function-map 'xk-kp-8
- '(lambda nil (interactive)
- (insert "8")))
-(define-function-key global-function-map 'xk-kp-9
- '(lambda nil (interactive)
- (insert "9")))
-
- ;; IsFunctionKey
-
-(define-function-key global-function-map 'xk-f1 'rmail)
-(define-function-key global-function-map 'xk-f2 nil)
-(define-function-key global-function-map 'xk-f3 nil)
-(define-function-key global-function-map 'xk-f4 nil)
-(define-function-key global-function-map 'xk-f5 nil)
-(define-function-key global-function-map 'xk-f6 nil)
-(define-function-key global-function-map 'xk-f7 nil)
-(define-function-key global-function-map 'xk-f8 nil)
-(define-function-key global-function-map 'xk-f9 nil)
-(define-function-key global-function-map 'xk-f10 nil)
-(define-function-key global-function-map 'xk-f11 nil)
-(define-function-key global-function-map 'xk-f12 nil)
-(define-function-key global-function-map 'xk-f13 nil)
-(define-function-key global-function-map 'xk-f14 nil)
-(define-function-key global-function-map 'xk-f15 nil)
-(define-function-key global-function-map 'xk-f16 nil)
-(define-function-key global-function-map 'xk-f17 nil)
-(define-function-key global-function-map 'xk-f18 nil)
-(define-function-key global-function-map 'xk-f19 nil)
-(define-function-key global-function-map 'xk-f20 nil)
-(define-function-key global-function-map 'xk-f21 nil)
-(define-function-key global-function-map 'xk-f22 nil)
-(define-function-key global-function-map 'xk-f23 nil)
-(define-function-key global-function-map 'xk-f24 nil)
-(define-function-key global-function-map 'xk-f25 nil)
-(define-function-key global-function-map 'xk-f26 nil)
-(define-function-key global-function-map 'xk-f27 nil)
-(define-function-key global-function-map 'xk-f28 nil)
-(define-function-key global-function-map 'xk-f29 nil)
-(define-function-key global-function-map 'xk-f30 nil)
-(define-function-key global-function-map 'xk-f31 nil)
-(define-function-key global-function-map 'xk-f32 nil)
-(define-function-key global-function-map 'xk-f33 nil)
-(define-function-key global-function-map 'xk-f34 nil)
-(define-function-key global-function-map 'xk-f35 nil)
+ (if (= window-system-version 10)
+ (progn
+ ;; xterm.c depends on using interrupt-driven input.
+ (set-input-mode t nil)
+
+ (defun x-new-display (display)
+ "This function takes one argument, the display where you wish to
+continue your editing session. Your current window will be unmapped and
+the current display will be closed. The new X display will be opened and
+the rubber-band outline of the new window will appear on the new X display."
+ (interactive "sDisplay to switch emacs to: ")
+ (x-change-display display)
+ (x-get-default-args))
+
+ ;; Not defvar! This is not DEFINING this variable, just specifying
+ ;; a value for it.
+ (setq window-setup-hook 'x-pop-up-window)
+
+ ;; Process switch settings made by .emacs file.
+ (while x-switches
+ (x-handle-switch-1 (car (car x-switches)) (cdr (car x-switches)))
+ (setq x-switches (cdr x-switches)))))
+
+ ;; On certain systems, turn off use of sigio, because it's broken.
+ (if x-sigio-bug
+ (set-input-mode nil nil))
+
+ (put 'suspend-emacs 'disabled
+ "Suspending a program running in an X window is silly
+and you would not be able to start it again. Just switch windows instead.\n")
+ (setq suspend-hook '(lambda () (error "Suspending an emacs running under X makes no sense")))
+ (substitute-key-definition 'suspend-emacs nil global-map)
+ (substitute-key-definition 'suspend-emacs nil esc-map)
+ (substitute-key-definition 'suspend-emacs nil ctl-x-map)
+ ;; Not needed any more -- done in C.
+ ;; (if (not x-processed-defaults) (x-get-default-args))
+))
diff --git a/lisp/term/xterm.el b/lisp/term/xterm.el
new file mode 100644
index 00000000000..abb8a85ce0d
--- /dev/null
+++ b/lisp/term/xterm.el
@@ -0,0 +1,2 @@
+;; Don't send the `ti' string when screen is cleared.
+(setq reset-terminal-on-clear nil)
diff --git a/lisp/terminal.el b/lisp/terminal.el
index d2a514048cb..70e83809d78 100644
--- a/lisp/terminal.el
+++ b/lisp/terminal.el
@@ -1,5 +1,5 @@
;; Terminal emulator for GNU Emacs.
-;; Copyright (C) 1986, 1987, 1988, 1989 Free Software Foundation, Inc.
+;; Copyright (C) 1986, 1987 Free Software Foundation, Inc.
;; Written by Richard Mlynarik, November 1986.
;; This file is part of GNU Emacs.
@@ -37,9 +37,9 @@ it through the emulator. Type ? after typing it for a list of
possible commands.
This variable is local to each terminal-emulator buffer.")
-(defvar terminal-scrolling t ;;>> Setting this to T sort-of defeats my whole aim in writing this package...
- "*If non-nil, the terminal-emulator will losingly `scroll' when output occurs
-past the bottom of the screen. If nil, output will win and `wrap' to the top
+(defvar terminal-scrolling t
+ "*If non-nil, the terminal-emulator will `scroll' when output occurs
+past the bottom of the screen. If nil, output will `wrap' to the top
of the screen.
This variable is local to each terminal-emulator buffer.")
@@ -88,8 +88,6 @@ performance.")
(define-key map "\C-o" 'te-flush-pending-output)
(define-key map "m" 'te-toggle-more-processing)
(define-key map "x" 'te-escape-extended-command)
- ;;>> What use is this? Why is it in the default terminal-emulator map?
- (define-key map "w" 'te-edit)
(define-key map "?" 'te-escape-help)
(define-key map (char-to-string help-char) 'te-escape-help)
(setq terminal-escape-map map)))
@@ -100,8 +98,6 @@ performance.")
nil
(setq te-escape-command-alist
'(("Set Escape Character" . te-set-escape-char)
- ;;>> What use is this? Why is it in the default terminal-emulator map?
- ("Edit" . te-edit)
("Refresh" . redraw-display)
("Record Output" . te-set-output-log)
("Photo" . te-set-output-log)
@@ -177,7 +173,7 @@ Other chars following \"%s\" are interpreted as follows:\n"
(princ (substitute-command-keys "\\{terminal-escape-map}\n"))
(princ (format "\nSubcommands of \"%s\" (%s)\n"
(where-is-internal 'te-escape-extended-command
- terminal-escape-map nil t)
+ terminal-escape-map t)
'te-escape-extended-command))
(let ((l (if (fboundp 'sortcar)
(sortcar (copy-sequence te-escape-command-alist)
@@ -258,7 +254,7 @@ Very poor man's file transfer protocol."
(save-excursion
(set-buffer (get-buffer-create name))
(fundamental-mode)
- (buffer-disable-undo (current-buffer))
+ (buffer-flush-undo (current-buffer))
(erase-buffer)))
(setq te-log-buffer (get-buffer name))
(message "Recording terminal emulator output into buffer \"%s\""
@@ -352,7 +348,7 @@ allowing the next page of output to appear"
(princ "Terminal-emulator more break.\n\n")
(princ (format "Type \"%s\" (te-more-break-resume)\n%s\n"
(where-is-internal 'te-more-break-resume
- terminal-more-break-map nil t)
+ terminal-more-break-map t)
(documentation 'te-more-break-resume)))
(princ (substitute-command-keys "\\{terminal-more-break-map}\n"))
(princ "Any other key is passed through to the program
@@ -393,19 +389,16 @@ the terminal emulator."
(defun te-pass-through ()
- "Character is passed to the program running under the terminal emulator.
-One characters is treated specially:
-the terminal escape character (normally C-^)
-lets you type a terminal emulator command."
+ "Send the last character typed through the terminal-emulator
+without any interpretation"
(interactive)
- (cond ((= last-input-char terminal-escape-char)
- (call-interactively 'te-escape))
- (t
- (and terminal-more-processing (null (cdr te-pending-output))
- (te-set-more-count nil))
- (send-string te-process (make-string 1 last-input-char))
- (te-process-output t))))
-
+ (if (eql last-input-char terminal-escape-char)
+ (call-interactively 'te-escape)
+ (and terminal-more-processing
+ (null (cdr te-pending-output))
+ (te-set-more-count nil))
+ (send-string te-process (make-string 1 last-input-char))
+ (te-process-output t)))
(defun te-set-window-start ()
(let* ((w (get-buffer-window (current-buffer)))
@@ -427,82 +420,6 @@ lets you type a terminal emulator command."
(setq length (+ length (length (car tem))) tem (cdr tem)))
length))
-;;>> What use is this terminal-edit stuff anyway?
-;;>> If nothing else, it was written by somebody who didn't
-;;>> competently understand the terminal-emulator...
-
-(defvar terminal-edit-map nil)
-(if terminal-edit-map
- nil
- (setq terminal-edit-map (make-sparse-keymap))
- (define-key terminal-edit-map "\C-c\C-c" 'terminal-cease-edit))
-
-;; Terminal Edit mode is suitable only for specially formatted data.
-(put 'terminal-edit-mode 'mode-class 'special)
-
-(defun terminal-edit-mode ()
- "Major mode for editing the contents of a terminal-emulator buffer.
-The editing commands are the same as in Fundamental mode,
-together with a command \\<terminal-edit-mode-map>to return to terminal emulation: \\[terminal-cease-edit]."
- (use-local-map terminal-edit-map)
- (setq major-mode 'terminal-edit-mode)
- (setq mode-name "Terminal Edit")
- (setq mode-line-modified (default-value 'mode-line-modified))
- (setq mode-line-process nil)
- (run-hooks 'terminal-edit-mode-hook))
-
-(defun te-edit ()
- "Start editing the terminal emulator buffer with ordinary Emacs commands."
- (interactive)
- (terminal-edit-mode)
- (set-buffer-modified-p (buffer-modified-p))
- ;; Make mode line update.
- (if (eq (key-binding "\C-c\C-c") 'terminal-cease-edit)
- (message "Editing: Type C-c C-c to return to Terminal")
- (message (substitute-command-keys
- "Editing: Type \\[terminal-cease-edit] to return to Terminal"))))
-
-(defun terminal-cease-edit ()
- "Finish editing message; switch back to Terminal proper."
- (interactive)
-
- ;;>> emulator will blow out if buffer isn't exactly te-width x te-height
- (let ((buffer-read-only nil))
- (widen)
- (let ((opoint (point-marker))
- (width te-width)
- (h (1- te-height)))
- (goto-char (point-min))
- (while (>= h 0)
- (let ((p (point)))
- (cond ((search-forward "\n" (+ p width) 'move)
- (forward-char -1)
- (insert-char ?\ (- width (- (point) p)))
- (forward-char 1))
- ((eobp)
- (insert-char ?\ (- width (- (point) p))))
- ((= (following-char) ?\n)
- (forward-char 1))
- (t
- (setq p (point))
- (if (search-forward "\n" nil t)
- (delete-region p (1- (point)))
- (delete-region p (point-max))))))
- (if (= h 0)
- (if (not (eobp)) (delete-region (point) (point-max)))
- (if (eobp) (insert ?\n)))
- (setq h (1- h)))
- (goto-char opoint)
- (set-marker opoint nil nil)
- (setq te-saved-point (point))
- (setq te-redisplay-count 0)
- (setq te-more-count -1)))
-
- (setq mode-line-modified (default-value 'mode-line-modified))
- (setq major-mode 'terminal-mode)
- (setq mode-name "terminal")
- (setq mode-line-process '(": %s")))
-
;;;; more break hair
(defun te-more-break ()
@@ -606,6 +523,28 @@ move to start of new line, clear to end of line."
(beginning-of-line)
(te-set-window-start))
+;; ^p ^j
+;; Handle the `do' or `nl' termcap capability.
+;;>> I am not sure why this broken, obsolete, capability is here.
+;;>> Perhaps it is for VIle. No comment was made about why it
+;;>> was added (in "Sun Dec 6 01:22:27 1987 Richard Stallman")
+(defun te-down-vertically-or-scroll ()
+ "Move down a line vertically, or scroll at bottom."
+ (let ((column (current-column)))
+ (end-of-line)
+ (if (eobp)
+ (progn
+ (delete-region (point-min) (+ (point-min) te-width))
+ (goto-char (point-min))
+ (delete-char 1)
+ (goto-char (point-max))
+ (insert ?\n)
+ (insert-char ?\ te-width)
+ (beginning-of-line))
+ (forward-line 1))
+ (move-to-column column))
+ (te-set-window-start))
+
; ^p = x+32 y+32
(defun te-move-to-position ()
;; must offset by #o40 since cretinous unix won't send a 004 char through
@@ -613,7 +552,7 @@ move to start of new line, clear to end of line."
(x (- (te-get-char) 32)))
(if (or (> x te-width)
(> y te-height))
- ()
+ () ;(error "fucked %d %d" x y)
(goto-char (+ (point-min) x (* y (1+ te-width))))
;(te-set-window-start?)
))
@@ -745,7 +684,9 @@ move to start of new line, clear to end of line."
;; Are we living twenty years in the past yet?
(defun te-losing-unix ()
- nil)
+ ;(what lossage)
+ ;(message "fucking-unix: %d" char)
+ )
;; ^i
(defun te-output-tab ()
@@ -755,28 +696,6 @@ move to start of new line, clear to end of line."
(progn (end-of-line) (- (point) p)))))
(goto-char (+ p l))))
-;; ^p ^j
-;; Handle the `do' or `nl' termcap capability.
-;;>> I am not sure why this broken, obsolete, capability is here.
-;;>> Perhaps it is for VIle. No comment was made about why it
-;;>> was added (in "Sun Dec 6 01:22:27 1987 Richard Stallman")
-(defun te-down-vertically-or-scroll ()
- "Move down a line vertically, or scroll at bottom."
- (let ((column (current-column)))
- (end-of-line)
- (if (eobp)
- (progn
- (delete-region (point-min) (+ (point-min) te-width))
- (goto-char (point-min))
- (delete-char 1)
- (goto-char (point-max))
- (insert ?\n)
- (insert-char ?\ te-width)
- (beginning-of-line))
- (forward-line 1))
- (move-to-column column))
- (te-set-window-start))
-
;; Also:
;; ^m => beginning-of-line (for which it -should- be using ^p ^a, right?!!)
;; ^g => te-beep (for which it should use ^p ^g)
@@ -798,7 +717,7 @@ move to start of new line, clear to end of line."
(setq te-log-buffer nil)
(set-buffer te-log-buffer)
(goto-char (point-max))
- (insert-before-markers string)
+ (insert string)
(set-buffer (process-buffer process))))
(setq te-pending-output (nconc te-pending-output (list string)))
(te-update-pending-output-display)
@@ -813,9 +732,7 @@ move to start of new line, clear to end of line."
(setq te-saved-point (point)))
(set-buffer obuf))))
-;; (A version of the following comment which might be distractingly offensive
-;; to some readers has been moved to term-nasty.el.)
-;; unix lacks ITS-style tty control...
+;; fucking unix has -such- braindamaged lack of tty control...
(defun te-process-output (preemptable)
;;>> There seems no good reason to ever disallow preemption
(setq preemptable t)
@@ -900,11 +817,11 @@ move to start of new line, clear to end of line."
;; I don't remember doing so, either.
;; (Perhaps some operating system or
;; other is completely incompetent...)
- (?\C-m . te-beginning-of-line)
- (?\C-g . te-beep)
- (?\C-h . te-backward-char)
- (?\C-i . te-output-tab))))
- 'te-losing-unix)))
+ (?\C-m . te-beginning-of-line) ;fuck me harder
+ (?\C-g . te-beep) ;again and again!
+ (?\C-h . te-backward-char) ;wa12id!!
+ (?\C-i . te-output-tab)))) ;(spiked)
+ 'te-losing-unix))) ;That feels better
(te-redisplay-if-necessary 1))
(and preemptable
(input-pending-p)
@@ -1114,17 +1031,16 @@ work with `terminfo' we will try to use it."
(progn (message
"Note: Meta key disabled due to maybe-eventually-reparable braindamage")
(sit-for 1)))
- (setq inhibit-quit t) ;sport death
- (use-local-map terminal-map)
- (run-hooks 'terminal-mode-hook)
(message "Entering emacs terminal-emulator... Type %s %s for help"
(single-key-description terminal-escape-char)
(mapconcat 'single-key-description
(where-is-internal 'te-escape-help
terminal-escape-map
- nil t)
- " ")))
-
+ t)
+ " "))
+ (setq inhibit-quit t) ;sport death
+ (use-local-map terminal-map)
+ (run-hooks 'terminal-mode-hook))
(defun te-parse-program-and-args (s)
(cond ((string-match "\\`\\([a-zA-Z0-9-+=_.@/:]+[ \t]*\\)+\\'" s)
@@ -1153,7 +1069,7 @@ work with `terminfo' we will try to use it."
One should not call this -- it is an internal function
of the terminal-emulator"
(kill-all-local-variables)
- (buffer-disable-undo (current-buffer))
+ (buffer-flush-undo (current-buffer))
(setq major-mode 'terminal-mode)
(setq mode-name "terminal")
; (make-local-variable 'Helper-return-blurb)
@@ -1196,33 +1112,33 @@ of the terminal-emulator"
;;;; what a complete loss
-(defun te-quote-arg-for-sh (string)
+(defun te-quote-arg-for-sh (fuckme)
(cond ((string-match "\\`[a-zA-Z0-9-+=_.@/:]+\\'"
- string)
- string)
- ((not (string-match "[$]" string))
+ fuckme)
+ fuckme)
+ ((not (string-match "[$]" fuckme))
;; "[\"\\]" are special to sh and the lisp reader in the same way
- (prin1-to-string string))
+ (prin1-to-string fuckme))
(t
(let ((harder "")
- (start 0)
- (end 0))
- (while (cond ((>= start (length string))
+ (cretin 0)
+ (stupid 0))
+ (while (cond ((>= cretin (length fuckme))
nil)
;; this is the set of chars magic with "..." in `sh'
- ((setq end (string-match "[\"\\$]"
- string start))
+ ((setq stupid (string-match "[\"\\$]"
+ fuckme cretin))
t)
(t (setq harder (concat harder
- (substring string start)))
+ (substring fuckme cretin)))
nil))
- (setq harder (concat harder (substring string start end)
+ (setq harder (concat harder (substring fuckme cretin stupid)
;; Can't use ?\\ since `concat'
;; unfortunately does prin1-to-string
;; on fixna. Amazing.
"\\"
- (substring string
- end
- (1+ end)))
- start (1+ end)))
- (concat "\"" harder "\""))))) \ No newline at end of file
+ (substring fuckme
+ stupid
+ (1+ stupid)))
+ cretin (1+ stupid)))
+ (concat "\"" harder "\"")))))
diff --git a/lisp/terminal.elc b/lisp/terminal.elc
new file mode 100644
index 00000000000..13e2bcc0c42
--- /dev/null
+++ b/lisp/terminal.elc
Binary files differ
diff --git a/lisp/tex-mode.el b/lisp/tex-mode.el
new file mode 100644
index 00000000000..d7126a22f1b
--- /dev/null
+++ b/lisp/tex-mode.el
@@ -0,0 +1,465 @@
+;; TeX mode commands.
+;; Copyright (C) 1985, 1986 Free Software Foundation, Inc.
+;; Rewritten following contributions by William F. Schelter
+;; and Dick King (king@kestrel).
+;; Modified August 1986 by Stephen Gildea <mit-erl!gildea> and
+;; Michael Prange <mit-erl!prange> to add LaTeX support and enhance
+;; TeX-region.
+;; Added TeX-directory and reorganized somewhat gildea 21 Nov 86
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 1, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+;; Still to do:
+;; Make TAB indent correctly for TeX code. Then we can make linefeed
+;; do something more useful.
+;;
+;; Have spell understand TeX instead of assuming the entire world
+;; uses nroff.
+;;
+;; The code for finding matching $ needs to be fixed.
+
+(provide 'tex-mode)
+
+(defvar TeX-directory "/tmp/"
+ "*Directory in which to run TeX subjob. Temporary files are
+created in this directory.")
+(defvar TeX-dvi-print-command "lpr -d"
+ "*Command string used by \\[TeX-print] to print a .dvi file.")
+(defvar TeX-show-queue-command "lpq"
+ "*Command string used by \\[TeX-show-print-queue] to show the print queue
+that \\[TeX-print] put your job on.")
+(defvar TeX-default-mode 'plain-TeX-mode
+ "*Mode to enter for a new file when it can't be determined whether
+the file is plain TeX or LaTeX or what.")
+
+(defvar TeX-command nil
+ "The command to run TeX on a file. The name of the file will be appended
+to this string, separated by a space.")
+(defvar TeX-trailer nil
+ "String appended after the end of a region sent to TeX by \\[TeX-region].")
+(defvar TeX-start-of-header nil
+ "String used by \\[TeX-region] to delimit the start of the file's header.")
+(defvar TeX-end-of-header nil
+ "String used by \\[TeX-region] to delimit the end of the file's header.")
+(defvar TeX-shell-cd-command "cd"
+ "Command to give to shell running TeX to change directory. The value of
+TeX-directory will be appended to this, separated by a space.")
+(defvar TeX-zap-file nil
+ "Temporary file name used for text being sent as input to TeX.
+Should be a simple file name with no extension or directory specification.")
+
+(defvar TeX-mode-syntax-table nil
+ "Syntax table used while in TeX mode.")
+
+(defun TeX-define-common-keys (keymap)
+ "Define the keys that we want defined both in TeX-mode
+and in the TeX-shell."
+ (define-key keymap "\C-c\C-k" 'TeX-kill-job)
+ (define-key keymap "\C-c\C-l" 'TeX-recenter-output-buffer)
+ (define-key keymap "\C-c\C-q" 'TeX-show-print-queue)
+ (define-key keymap "\C-c\C-p" 'TeX-print)
+ )
+
+(defvar TeX-mode-map nil "Keymap for TeX mode")
+
+(if TeX-mode-map
+ nil
+ (setq TeX-mode-map (make-sparse-keymap))
+ (TeX-define-common-keys TeX-mode-map)
+ (define-key TeX-mode-map "\"" 'TeX-insert-quote)
+ (define-key TeX-mode-map "\n" 'TeX-terminate-paragraph)
+ (define-key TeX-mode-map "\e}" 'up-list)
+ (define-key TeX-mode-map "\e{" 'TeX-insert-braces)
+ (define-key TeX-mode-map "\C-c\C-r" 'TeX-region)
+ (define-key TeX-mode-map "\C-c\C-b" 'TeX-buffer)
+ (define-key TeX-mode-map "\C-c\C-f" 'TeX-close-LaTeX-block)
+ )
+
+(defvar TeX-shell-map nil
+ "Keymap for the TeX shell. A shell-mode-map with a few additions")
+
+;(fset 'TeX-mode 'tex-mode) ;in loaddefs.
+
+;;; This would be a lot simpler if we just used a regexp search,
+;;; but then it would be too slow.
+(defun tex-mode ()
+ "Major mode for editing files of input for TeX or LaTeX.
+Trys to intuit whether this file is for plain TeX or LaTeX and
+calls plain-tex-mode or latex-mode. If it cannot be determined
+\(e.g., there are no commands in the file), the value of
+TeX-default-mode is used."
+ (interactive)
+ (let (mode slash comment)
+ (save-excursion
+ (goto-char (point-min))
+ (while (and (setq slash (search-forward "\\" nil t))
+ (setq comment (let ((search-end (point)))
+ (save-excursion
+ (beginning-of-line)
+ (search-forward "%" search-end t))))))
+ (if (and slash (not comment))
+ (setq mode (if (looking-at "documentstyle")
+ 'latex-mode
+ 'plain-tex-mode))))
+ (if mode (funcall mode)
+ (funcall TeX-default-mode))))
+
+(fset 'plain-TeX-mode 'plain-tex-mode)
+(fset 'LaTeX-mode 'latex-mode)
+
+(defun plain-tex-mode ()
+ "Major mode for editing files of input for plain TeX.
+Makes $ and } display the characters they match.
+Makes \" insert `` when it seems to be the beginning of a quotation,
+and '' when it appears to be the end; it inserts \" only after a \\.
+
+Use \\[TeX-region] to run TeX on the current region, plus a \"header\"
+copied from the top of the file (containing macro definitions, etc.),
+running TeX under a special subshell. \\[TeX-buffer] does the whole buffer.
+\\[TeX-print] prints the .dvi file made by either of these.
+
+Use \\[validate-TeX-buffer] to check buffer for paragraphs containing
+mismatched $'s or braces.
+
+Special commands:
+\\{TeX-mode-map}
+
+Mode variables:
+TeX-directory
+ Directory in which to create temporary files for TeX jobs
+ run by \\[TeX-region] or \\[TeX-buffer].
+TeX-dvi-print-command
+ Command string used by \\[TeX-print] to print a .dvi file.
+TeX-show-queue-command
+ Command string used by \\[TeX-show-print-queue] to show the print
+ queue that \\[TeX-print] put your job on.
+
+Entering plain-TeX mode calls the value of text-mode-hook,
+then the value of TeX-mode-hook, and then the value
+of plain-TeX-mode-hook."
+ (interactive)
+ (TeX-common-initialization)
+ (setq mode-name "TeX")
+ (setq major-mode 'plain-TeX-mode)
+ (setq TeX-command "tex")
+ (setq TeX-start-of-header "%**start of header")
+ (setq TeX-end-of-header "%**end of header")
+ (setq TeX-trailer "\\bye\n")
+ (run-hooks 'text-mode-hook 'TeX-mode-hook 'plain-TeX-mode-hook))
+
+(defun latex-mode ()
+ "Major mode for editing files of input for LaTeX.
+Makes $ and } display the characters they match.
+Makes \" insert `` when it seems to be the beginning of a quotation,
+and '' when it appears to be the end; it inserts \" only after a \\.
+
+Use \\[TeX-region] to run LaTeX on the current region, plus the preamble
+copied from the top of the file (containing \\documentstyle, etc.),
+running LaTeX under a special subshell. \\[TeX-buffer] does the whole buffer.
+\\[TeX-print] prints the .dvi file made by either of these.
+
+Use \\[validate-TeX-buffer] to check buffer for paragraphs containing
+mismatched $'s or braces.
+
+Special commands:
+\\{TeX-mode-map}
+
+Mode variables:
+TeX-directory
+ Directory in which to create temporary files for TeX jobs
+ run by \\[TeX-region] or \\[TeX-buffer].
+TeX-dvi-print-command
+ Command string used by \\[TeX-print] to print a .dvi file.
+TeX-show-queue-command
+ Command string used by \\[TeX-show-print-queue] to show the print
+ queue that \\[TeX-print] put your job on.
+
+Entering LaTeX mode calls the value of text-mode-hook,
+then the value of TeX-mode-hook, and then the value
+of LaTeX-mode-hook."
+ (interactive)
+ (TeX-common-initialization)
+ (setq mode-name "LaTeX")
+ (setq major-mode 'LaTeX-mode)
+ (setq TeX-command "latex")
+ (setq TeX-start-of-header "\\documentstyle")
+ (setq TeX-end-of-header "\\begin{document}")
+ (setq TeX-trailer "\\end{document}\n")
+ (run-hooks 'text-mode-hook 'TeX-mode-hook 'LaTeX-mode-hook))
+
+(defun TeX-common-initialization ()
+ (kill-all-local-variables)
+ (use-local-map TeX-mode-map)
+ (setq local-abbrev-table text-mode-abbrev-table)
+ (if (null TeX-mode-syntax-table)
+ (progn
+ (setq TeX-mode-syntax-table (make-syntax-table))
+ (set-syntax-table TeX-mode-syntax-table)
+ (modify-syntax-entry ?\\ ".")
+ (modify-syntax-entry ?\f ">")
+ (modify-syntax-entry ?\n ">")
+ (modify-syntax-entry ?$ "$$")
+ (modify-syntax-entry ?% "<")
+ (modify-syntax-entry ?\" ".")
+ (modify-syntax-entry ?& ".")
+ (modify-syntax-entry ?_ ".")
+ (modify-syntax-entry ?@ "_")
+ (modify-syntax-entry ?~ " ")
+ (modify-syntax-entry ?' "w"))
+ (set-syntax-table TeX-mode-syntax-table))
+ (make-local-variable 'paragraph-start)
+ (setq paragraph-start "^[ \t]*$\\|^[\f\\\\%]")
+ (make-local-variable 'paragraph-separate)
+ (setq paragraph-separate paragraph-start)
+ (make-local-variable 'comment-start)
+ (setq comment-start "%")
+ (make-local-variable 'comment-start-skip)
+ (setq comment-start-skip "\\(\\(^\\|[^\\]\\)\\(\\\\\\\\\\)*\\)\\(%+ *\\)")
+ (make-local-variable 'comment-indent-hook)
+ (setq comment-indent-hook 'TeX-comment-indent)
+ (make-local-variable 'TeX-command)
+ (make-local-variable 'TeX-start-of-header)
+ (make-local-variable 'TeX-end-of-header)
+ (make-local-variable 'TeX-trailer))
+
+(defun TeX-comment-indent ()
+ (if (looking-at "%%%")
+ (current-column)
+ (skip-chars-backward " \t")
+ (max (if (bolp) 0 (1+ (current-column)))
+ comment-column)))
+
+(defun TeX-insert-quote (arg)
+ "Insert ``, '' or \" according to preceding character.
+With prefix argument, always insert \" characters."
+ (interactive "P")
+ (if arg
+ (let ((count (prefix-numeric-value arg)))
+ (if (listp arg)
+ (self-insert-command 1) ;C-u always inserts just one
+ (self-insert-command count)))
+ (insert
+ (cond
+ ((or (bobp)
+ (save-excursion
+ (forward-char -1)
+ (looking-at "[ \t\n]\\|\\s(")))
+ "``")
+ ((= (preceding-char) ?\\)
+ ?\")
+ (t "''")))))
+
+(defun validate-TeX-buffer ()
+ "Check current buffer for paragraphs containing mismatched $'s.
+As each such paragraph is found, a mark is pushed at its beginning,
+and the location is displayed for a few seconds."
+ (interactive)
+ (let ((opoint (point)))
+ (goto-char (point-max))
+ ;; Does not use save-excursion
+ ;; because we do not want to save the mark.
+ (unwind-protect
+ (while (and (not (input-pending-p)) (not (bobp)))
+ (let ((end (point)))
+ (search-backward "\n\n" nil 'move)
+ (or (TeX-validate-paragraph (point) end)
+ (progn
+ (push-mark (point))
+ (message "Mismatch found in pararaph starting here")
+ (sit-for 4)))))
+ (goto-char opoint))))
+
+(defun TeX-validate-paragraph (start end)
+ (condition-case ()
+ (save-excursion
+ (save-restriction
+ (narrow-to-region start end)
+ (goto-char start)
+ (forward-sexp (- end start))
+ t))
+ (error nil)))
+
+(defun TeX-terminate-paragraph (inhibit-validation)
+ "Insert two newlines, breaking a paragraph for TeX.
+Check for mismatched braces/$'s in paragraph being terminated.
+A prefix arg inhibits the checking."
+ (interactive "P")
+ (or inhibit-validation
+ (TeX-validate-paragraph
+ (save-excursion
+ (search-backward "\n\n" nil 'move)
+ (point))
+ (point))
+ (message "Paragraph being closed appears to contain a mismatch"))
+ (insert "\n\n"))
+
+(defun TeX-insert-braces ()
+ "Make a pair of braces and be poised to type inside of them."
+ (interactive)
+ (insert ?\{)
+ (save-excursion
+ (insert ?})))
+
+;;; Like TeX-insert-braces, but for LaTeX.
+(defun TeX-close-LaTeX-block ()
+ "Creates an \\end{...} to match \\begin{...} on the current line and
+puts point on the blank line between them."
+ (interactive "*")
+ (let ((fail-point (point)))
+ (end-of-line)
+ (if (re-search-backward "\\\\begin{\\([^}\n]*\\)}"
+ (save-excursion (beginning-of-line) (point)) t)
+ (let ((text (buffer-substring (match-beginning 1) (match-end 1)))
+ (indentation (current-column)))
+ (end-of-line)
+ (delete-horizontal-space)
+ (insert "\n\n")
+ (indent-to indentation)
+ (insert "\\end{" text "}")
+ (forward-line -1))
+ (goto-char fail-point)
+ (ding))))
+
+;;; Invoking TeX in an inferior shell.
+
+;;; Why use a shell instead of running TeX directly? Because if TeX
+;;; gets stuck, the user can switch to the shell window and type at it.
+
+;;; The utility functions:
+
+(defun TeX-start-shell ()
+ (require 'shell)
+ (save-excursion
+ (set-buffer (make-shell "TeX-shell" nil nil "-v"))
+ (setq TeX-shell-map (copy-keymap shell-mode-map))
+ (TeX-define-common-keys TeX-shell-map)
+ (use-local-map TeX-shell-map)
+ (if (zerop (buffer-size))
+ (sleep-for 1))))
+
+(defun set-buffer-directory (buffer directory)
+ "Set BUFFER's default directory to be DIRECTORY."
+ (setq directory (file-name-as-directory (expand-file-name directory)))
+ (if (not (file-directory-p directory))
+ (error "%s is not a directory" directory)
+ (save-excursion
+ (set-buffer buffer)
+ (setq default-directory directory))))
+
+;;; The commands:
+
+;;; It's a kludge that we have to create a special buffer just
+;;; to write out the TeX-trailer. It would nice if there were a
+;;; function like write-region that would write literal strings.
+
+(defun TeX-region (beg end)
+ "Run TeX on the current region. A temporary file (TeX-zap-file) is
+written in directory TeX-directory, and TeX is run in that directory.
+If the buffer has a header, it is written to the temporary file before
+the region itself. The buffer's header is all lines between the
+strings defined by TeX-start-of-header and TeX-end-of-header
+inclusive. The header must start in the first 100 lines. The value
+of TeX-trailer is appended to the temporary file after the region."
+ (interactive "r")
+ (if (get-buffer "*TeX-shell*")
+ (TeX-kill-job)
+ (TeX-start-shell))
+ (or TeX-zap-file (setq TeX-zap-file (make-temp-name "#tz")))
+ (let ((tex-out-file (concat TeX-zap-file ".tex"))
+ (temp-buffer (get-buffer-create " TeX-Output-Buffer"))
+ (zap-directory
+ (file-name-as-directory (expand-file-name TeX-directory))))
+ (save-excursion
+ (save-restriction
+ (widen)
+ (goto-char (point-min))
+ (forward-line 100)
+ (let ((search-end (point))
+ (hbeg (point-min)) (hend (point-min))
+ (default-directory zap-directory))
+ (goto-char (point-min))
+ ;; Initialize the temp file with either the header or nothing
+ (if (search-forward TeX-start-of-header search-end t)
+ (progn
+ (beginning-of-line)
+ (setq hbeg (point)) ;mark beginning of header
+ (if (search-forward TeX-end-of-header nil t)
+ (progn (forward-line 1)
+ (setq hend (point))) ;mark end of header
+ (setq hbeg (point-min))))) ;no header
+ (write-region (min hbeg beg) hend tex-out-file nil nil)
+ (write-region (max beg hend) end tex-out-file t nil))
+ (let ((local-tex-trailer TeX-trailer))
+ (set-buffer temp-buffer)
+ (erase-buffer)
+ ;; make sure trailer isn't hidden by a comment
+ (insert-string "\n")
+ (if local-tex-trailer (insert-string local-tex-trailer))
+ (set-buffer-directory temp-buffer zap-directory)
+ (write-region (point-min) (point-max) tex-out-file t nil))))
+ (set-buffer-directory "*TeX-shell*" zap-directory)
+ (send-string "TeX-shell" (concat TeX-shell-cd-command " "
+ zap-directory "\n"))
+ (send-string "TeX-shell" (concat TeX-command " \""
+ tex-out-file "\"\n")))
+ (TeX-recenter-output-buffer 0))
+
+(defun TeX-buffer ()
+ "Run TeX on current buffer. See \\[TeX-region] for more information."
+ (interactive)
+ (TeX-region (point-min) (point-max)))
+
+(defun TeX-kill-job ()
+ "Kill the currently running TeX job."
+ (interactive)
+ (quit-process "TeX-shell" t))
+
+(defun TeX-recenter-output-buffer (linenum)
+ "Redisplay buffer of TeX job output so that most recent output can be seen.
+The last line of the buffer is displayed on
+line LINE of the window, or centered if LINE is nil."
+ (interactive "P")
+ (let ((tex-shell (get-buffer "*TeX-shell*"))
+ (old-buffer (current-buffer)))
+ (if (null tex-shell)
+ (message "No TeX output buffer")
+ (pop-to-buffer tex-shell)
+ (bury-buffer tex-shell)
+ (goto-char (point-max))
+ (recenter (if linenum
+ (prefix-numeric-value linenum)
+ (/ (window-height) 2)))
+ (pop-to-buffer old-buffer)
+ )))
+
+(defun TeX-print ()
+ "Print the .dvi file made by \\[TeX-region] or \\[TeX-buffer].
+Runs the shell command defined by TeX-dvi-print-command."
+ (interactive)
+ (send-string "TeX-shell"
+ (concat TeX-dvi-print-command " \"" TeX-zap-file ".dvi\"\n"))
+ (TeX-recenter-output-buffer nil))
+
+(defun TeX-show-print-queue ()
+ "Show the print queue that \\[TeX-print] put your job on.
+Runs the shell command defined by TeX-show-queue-command."
+ (interactive)
+ (if (not (get-buffer "*TeX-shell*"))
+ (TeX-start-shell))
+ (send-string "TeX-shell" (concat TeX-show-queue-command "\n"))
+ (TeX-recenter-output-buffer nil))
+
diff --git a/lisp/tex-mode.elc b/lisp/tex-mode.elc
new file mode 100644
index 00000000000..9815ba2064e
--- /dev/null
+++ b/lisp/tex-mode.elc
Binary files differ
diff --git a/lisp/tex-start.el b/lisp/tex-start.el
new file mode 100644
index 00000000000..0184114faf0
--- /dev/null
+++ b/lisp/tex-start.el
@@ -0,0 +1,11 @@
+; This file is for use by TeX82 (see man page) to allow switching to
+; Emacs at a line number given on the command line
+; It assumes that it has been called by:
+; emacs -l tex-start -e startline <linenumber> <file>
+
+(defun startline ()
+ ;(setq command-line-args (cdr command-line-args))
+ (find-file (car (cdr command-line-args-left)))
+ (goto-char (point-min))
+ (forward-line (1- (string-to-int (car command-line-args-left))))
+ (setq command-line-args-left ()))
diff --git a/lisp/textmodes/texinfmt.el b/lisp/texinfmt.el
index 07b2c9136f6..d28f279eb90 100644
--- a/lisp/textmodes/texinfmt.el
+++ b/lisp/texinfmt.el
@@ -1,9 +1,5 @@
-;;;; texinfmt.el
-;;;; Convert Texinfo files to Info files.
-
-;;;; Version 2.00 14 Dec 1990
-
-;; Copyright (C) 1985, 1986, 1988, 1990 Free Software Foundation, Inc.
+;; Convert texinfo files to info files.
+;; Copyright (C) 1985, 1986, 1988 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -21,11 +17,6 @@
;; along with GNU Emacs; see the file COPYING. If not, write to
;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-;; Updated May 1990 to correspond, more or less, to version 2.8 of
-;; texinfo.tex. NOTE: texinfmt.el is being phased out; it is being
-;; replaced by makeinfo.c, which is faster and provides better error
-;; checking.
-;; Robert J. Chassell, bob@ai.mit.edu
(defvar texinfo-format-syntax-table nil)
@@ -66,40 +57,37 @@ Info-split to do these manually."
(message lastmessage)
(texinfo-format-buffer-1)
(if notagify
- nil
+ nil
(if (> (buffer-size) 30000)
- (progn
- (message (setq lastmessage "Making tags table for Info file..."))
- (Info-tagify)))
+ (progn
+ (message (setq lastmessage "Making tags table for Info file..."))
+ (Info-tagify)))
(if (> (buffer-size) 100000)
- (progn
- (message (setq lastmessage "Splitting Info file..."))
- (Info-split))))
+ (progn
+ (message (setq lastmessage "Splitting Info file..."))
+ (Info-split))))
(message (concat lastmessage
- (if (interactive-p) "done. Now save it." "done.")))))
-
+ (if (interactive-p) "done. Now save it." "done.")))))
(defun texinfo-format-buffer-1 ()
(let (texinfo-format-filename
- texinfo-example-start
- texinfo-command-start
- texinfo-command-end
- texinfo-command-name
- texinfo-last-node
- texinfo-vindex
- texinfo-findex
- texinfo-cindex
- texinfo-pindex
- texinfo-tindex
- texinfo-kindex
- texinfo-stack
- texinfo-node-names
- (texinfo-footnote-number 0)
- last-input-buffer
- outfile
- (fill-column fill-column)
- (input-buffer (current-buffer))
- (input-directory default-directory))
+ texinfo-example-start
+ texinfo-command-start
+ texinfo-command-end
+ texinfo-command-name
+ texinfo-last-node
+ texinfo-vindex
+ texinfo-findex
+ texinfo-cindex
+ texinfo-pindex
+ texinfo-tindex
+ texinfo-kindex
+ texinfo-stack
+ texinfo-node-names
+ outfile
+ (fill-column fill-column)
+ (input-buffer (current-buffer))
+ (input-directory default-directory))
(save-excursion
(goto-char (point-min))
(search-forward "@setfilename")
@@ -117,49 +105,47 @@ Info-split to do these manually."
;; Remove @bye at end of file, if it is there.
(goto-char (point-max))
(if (search-backward "@bye" nil t)
- (delete-region (point) (point-max)))
+ (delete-region (point) (point-max)))
;; Make sure buffer ends in a newline.
(or (= (preceding-char) ?\n)
- (insert "\n"))
+ (insert "\n"))
;; Scan the whole buffer, converting to Info format.
(texinfo-format-scan)
;; Return data for indices.
(goto-char (point-min))
(list outfile
- texinfo-vindex texinfo-findex texinfo-cindex
- texinfo-pindex texinfo-tindex texinfo-kindex)))
+ texinfo-vindex texinfo-findex texinfo-cindex
+ texinfo-pindex texinfo-tindex texinfo-kindex)))
(defvar texinfo-region-buffer-name "*Info Region*"
"*Name of the temporary buffer used by \\[texinfo-format-region].")
(defun texinfo-format-region (region-beginning region-ending)
- "Convert the current region of the Texinfo file to Info format.
+ "Convert the the current region of the Texinfo file to Info format.
This lets you see what that part of the file will look like in Info.
The command is bound to \\[texinfo-format-region]. The text that is
converted to Info is stored in a temporary buffer."
(interactive "r")
(message "Converting region to Info format...")
(let (texinfo-command-start
- texinfo-command-end
- texinfo-command-name
- texinfo-vindex
- texinfo-findex
- texinfo-cindex
- texinfo-pindex
- texinfo-tindex
- texinfo-kindex
- texinfo-stack
- texinfo-format-filename
- texinfo-example-start
- texinfo-last-node
- texinfo-node-names
- (texinfo-footnote-number 0)
- last-input-buffer
- (fill-column fill-column)
- (input-buffer (current-buffer))
- (input-directory default-directory)
- filename-beginning
- filename-ending)
+ texinfo-command-end
+ texinfo-command-name
+ texinfo-vindex
+ texinfo-findex
+ texinfo-cindex
+ texinfo-pindex
+ texinfo-tindex
+ texinfo-kindex
+ texinfo-stack
+ texinfo-format-filename
+ texinfo-example-start
+ texinfo-last-node
+ texinfo-node-names
+ (fill-column fill-column)
+ (input-buffer (current-buffer))
+ (input-directory default-directory)
+ filename-beginning
+ filename-ending)
;;; Find a buffer to use.
@@ -171,28 +157,28 @@ converted to Info is stored in a temporary buffer."
(save-excursion
(set-buffer input-buffer)
(save-excursion
- (save-restriction
- (widen)
- (goto-char (point-min))
- ;; Initialize the buffer with the filename
- ;; or else explain that a filename is needed.
- (or (search-forward "@setfilename"
- (save-excursion (forward-line 100) (point)) t)
- (error "The texinfo file needs a line saying: @setfilename <name>"))
- (beginning-of-line)
- (setq filename-beginning (point))
- (forward-line 1)
- (setq filename-ending (point)))))
+ (save-restriction
+ (widen)
+ (goto-char (point-min))
+ ;; Initialize the buffer with the filename
+ ;; or else explain that a filename is needed.
+ (or (search-forward "@setfilename"
+ (save-excursion (forward-line 100) (point)) t)
+ (error "The texinfo file needs a line saying: @setfilename <name>"))
+ (beginning-of-line)
+ (setq filename-beginning (point))
+ (forward-line 1)
+ (setq filename-ending (point)))))
;; Insert the @setfilename line into the buffer.
(insert-buffer-substring input-buffer
- (min filename-beginning region-beginning)
- filename-ending)
+ (min filename-beginning region-beginning)
+ filename-ending)
;; Insert the region into the buffer.
(insert-buffer-substring input-buffer
- (max region-beginning filename-ending)
- region-ending)
+ (max region-beginning filename-ending)
+ region-ending)
(texinfo-mode)
@@ -203,10 +189,10 @@ converted to Info is stored in a temporary buffer."
;; discard everything after that.
(goto-char (point-max))
(if (re-search-backward "^@bye" nil t)
- (delete-region (point) (point-max)))
+ (delete-region (point) (point-max)))
;; Make sure buffer ends in a newline.
(or (= (preceding-char) ?\n)
- (insert "\n"))
+ (insert "\n"))
;; Now convert for real.
(goto-char (point-min))
@@ -214,50 +200,44 @@ converted to Info is stored in a temporary buffer."
(goto-char (point-min)))
(message "Done."))
-
;; Perform those texinfo-to-info conversions that apply to the whole input
;; uniformly.
(defun texinfo-format-scan ()
- ;; Convert left and right quotes to typewriter font quotes.
- (goto-char (point-min))
- (while (search-forward "``" nil t)
- (replace-match "\""))
- (goto-char (point-min))
- (while (search-forward "''" nil t)
- (replace-match "\""))
- ;; Scan for @-commands.
- (goto-char (point-min))
- (while (search-forward "@" nil t)
- (if (looking-at "[@{}'` *]")
- ;; Handle a few special @-followed-by-one-char commands.
- (if (= (following-char) ?*)
- (progn
- ;; remove command
- (delete-region (1- (point)) (1+ (point)))
- ;; insert return if not at end of line;
- ;; else line is already broken.
- (if (not (= (following-char) ?\n))
- (insert ?\n)))
- ;; The other characters are simply quoted. Delete the @.
- (delete-char -1)
- (forward-char 1))
- ;; @ is followed by a command-word; find the end of the word.
- (setq texinfo-command-start (1- (point)))
- (if (= (char-syntax (following-char)) ?w)
- (forward-word 1)
- (forward-char 1))
- (setq texinfo-command-end (point))
- ;; Call the handler for this command.
- (setq texinfo-command-name
- (intern (buffer-substring (1+ texinfo-command-start)
- texinfo-command-end)))
- (let ((cmd (get texinfo-command-name 'texinfo-format)))
- (if cmd (funcall cmd)
- (texinfo-unsupported)))))
- (cond (texinfo-stack
- (goto-char (nth 2 (car texinfo-stack)))
- (error "Unterminated @%s" (car (car texinfo-stack))))))
+ ;; Convert left and right quotes to typewriter font quotes.
+ (goto-char (point-min))
+ (while (search-forward "``" nil t)
+ (replace-match "\""))
+ (goto-char (point-min))
+ (while (search-forward "''" nil t)
+ (replace-match "\""))
+ ;; Scan for @-commands.
+ (goto-char (point-min))
+ (while (search-forward "@" nil t)
+ (if (looking-at "[@{}'` *]")
+ ;; Handle a few special @-followed-by-one-char commands.
+ (if (= (following-char) ?*)
+ ;; @* has no effect, since we are not filling.
+ (delete-region (1- (point)) (1+ (point)))
+ ;; The other characters are simply quoted. Delete the @.
+ (delete-char -1)
+ (forward-char 1))
+ ;; @ is followed by a command-word; find the end of the word.
+ (setq texinfo-command-start (1- (point)))
+ (if (= (char-syntax (following-char)) ?w)
+ (forward-word 1)
+ (forward-char 1))
+ (setq texinfo-command-end (point))
+ ;; Call the handler for this command.
+ (setq texinfo-command-name
+ (intern (buffer-substring (1+ texinfo-command-start)
+ texinfo-command-end)))
+ (let ((cmd (get texinfo-command-name 'texinfo-format)))
+ (if cmd (funcall cmd)
+ (texinfo-unsupported)))))
+ (cond (texinfo-stack
+ (goto-char (nth 2 (car texinfo-stack)))
+ (error "Unterminated @%s" (car (car texinfo-stack))))))
(put 'begin 'texinfo-format 'texinfo-format-begin)
(defun texinfo-format-begin ()
@@ -280,7 +260,6 @@ converted to Info is stored in a temporary buffer."
(skip-chars-forward " ")
(setq start (point))
(end-of-line)
- (skip-chars-backward " ")
(setq texinfo-command-end (1+ (point))))
((looking-at "{")
(setq start (1+ (point)))
@@ -332,19 +311,6 @@ converted to Info is stored in a temporary buffer."
(defun texinfo-discard-command ()
(delete-region texinfo-command-start texinfo-command-end))
-(defun texinfo-optional-braces-discard ()
- "Discard braces following command, if any."
- (goto-char texinfo-command-end)
- (let ((start (point)))
- (cond ((looking-at "[ \t]*\n")) ; do nothing
- ((looking-at "{") ; remove braces, if any
- (forward-list 1)
- (setq texinfo-command-end (point)))
- (t
- (error
- "Invalid `texinfo-optional-braces-discard' format \(need braces?\)")))
- (delete-region texinfo-command-start texinfo-command-end)))
-
(defun texinfo-format-parse-line-args ()
(let ((start (1- (point)))
next beg end
@@ -371,10 +337,6 @@ converted to Info is stored in a temporary buffer."
next beg end
args)
(search-forward "{")
- (save-excursion
- (texinfo-format-expand-region
- (point)
- (save-excursion (up-list 1) (1- (point)))))
(while (/= (preceding-char) ?\})
(skip-chars-forward " \t\n")
(setq beg (point))
@@ -422,42 +384,21 @@ converted to Info is stored in a temporary buffer."
(forward-char 1)
(nreverse args))))
-
-; 19 October 1990
-; @setfilename modifed to work with include files; see @include
-; (defun texinfo-format-setfilename ()
-; (let ((arg (texinfo-parse-arg-discard)))
-; (setq texinfo-format-filename
-; (file-name-nondirectory (expand-file-name arg)))
-; (insert "Info file: "
-; texinfo-format-filename ", -*-Text-*-\n"
-; "produced by texinfo-format-buffer\nfrom "
-; (if (buffer-file-name input-buffer)
-; (concat "file: "
-; (file-name-sans-versions
-; (file-name-nondirectory
-; (buffer-file-name input-buffer))))
-; (concat "buffer " (buffer-name input-buffer)))
-; "\n\n")))
-
(put 'setfilename 'texinfo-format 'texinfo-format-setfilename)
(defun texinfo-format-setfilename ()
(let ((arg (texinfo-parse-arg-discard)))
- (if (eq input-buffer last-input-buffer)
- nil ; only use first setfilename in buffer
- (message "Formatting Info file: %s" arg)
- (setq texinfo-format-filename
- (file-name-nondirectory (expand-file-name arg)))
- (insert "Info file: "
- texinfo-format-filename ", -*-Text-*-\n"
- "produced by texinfo-format-buffer\nfrom "
- (if (buffer-file-name input-buffer)
- (concat "file: "
- (file-name-sans-versions
- (file-name-nondirectory
- (buffer-file-name input-buffer))))
- (concat "buffer " (buffer-name input-buffer)))
- "\n\n"))))
+ (setq texinfo-format-filename
+ (file-name-nondirectory (expand-file-name arg)))
+ (insert "Info file: "
+ texinfo-format-filename ", -*-Text-*-\n"
+ "produced by texinfo-format-buffer\nfrom "
+ (if (buffer-file-name input-buffer)
+ (concat "file: "
+ (file-name-sans-versions
+ (file-name-nondirectory
+ (buffer-file-name input-buffer))))
+ (concat "buffer " (buffer-name input-buffer)))
+ "\n\n")))
(put 'node 'texinfo-format 'texinfo-format-node)
(defun texinfo-format-node ()
@@ -471,8 +412,7 @@ converted to Info is stored in a temporary buffer."
(let ((tem (downcase name)))
(if (assoc tem texinfo-node-names)
(error "Duplicate node name: %s" name)
- (setq texinfo-node-names (cons (list tem) texinfo-node-names))))
- (setq texinfo-footnote-number 0)
+ (setq texinfo-node-names (cons tem texinfo-node-names))))
(or (bolp)
(insert ?\n))
(insert "\^_\nFile: " texinfo-format-filename
@@ -515,11 +455,6 @@ converted to Info is stored in a temporary buffer."
; If fifth argument DOCUMENT is specified, produces
; See section <xref to NODE> [NAME, else NODE], page <xref to NODE>
; of DOCUMENT
-
-; @ref a reference that does not put `See' or `see' in
-; the hardcopy and is the same as @xref in Info
-(put 'ref 'texinfo-format 'texinfo-format-xref)
-
(put 'xref 'texinfo-format 'texinfo-format-xref)
(defun texinfo-format-xref ()
(let ((args (texinfo-format-parse-args)))
@@ -548,9 +483,7 @@ converted to Info is stored in a temporary buffer."
(defun texinfo-format-inforef ()
(let ((args (texinfo-format-parse-args)))
(texinfo-discard-command)
- (if (nth 1 args)
- (insert "*Note " (nth 1 args) ": (" (nth 2 args) ")" (car args))
- (insert "*Note " "(" (nth 2 args) ")" (car args) "::"))))
+ (insert "*Note " (nth 1 args) ": (" (nth 2 args) ")" (car args))))
(put 'chapheading 'texinfo-format 'texinfo-format-chapter)
(put 'ichapter 'texinfo-format 'texinfo-format-chapter)
@@ -596,7 +529,6 @@ converted to Info is stored in a temporary buffer."
(defun texinfo-format-chapter-1 (belowchar)
(let ((arg (texinfo-parse-arg-discard)))
- (message "Formatting: %s ... " arg) ; So we can see where we are.
(insert ?\n arg ?\n "@SectionPAD " belowchar ?\n)
(forward-line -2)))
@@ -625,132 +557,6 @@ converted to Info is stored in a temporary buffer."
(texinfo-discard-command)
(let ((indent-tabs-mode nil))
(center-line)))
-
-(put 'sp 'texinfo-format 'texinfo-format-sp)
-(defun texinfo-format-sp ()
- (let* ((arg (texinfo-parse-arg-discard))
- (num (read arg)))
- (insert-char ?\n num)))
-
-(put 'br 'texinfo-format 'texinfo-format-paragraph-break)
-(defun texinfo-format-paragraph-break ()
- "Force a paragraph break.
-If used within a line, follow `@br' with braces."
- (texinfo-optional-braces-discard)
- ;; insert one return if at end of line;
- ;; else insert two returns, to generate a blank line.
- (if (= (following-char) ?\n)
- (insert ?\n)
- (insert-char ?\n 2)))
-
-
-;;; @footnote
-
-; In Texinfo, footnotes are created with the `@footnote' command.
-; This command is followed immediately by a left brace, then by the text of
-; the footnote, and then by a terminating right brace. The
-; template for a footnote is:
-;
-; @footnote{TEXT}
-;
-; Info has two footnote styles:
-;
-; `End Node'
-; In the "End Node" style, all the footnotes for a single node
-; are placed at the end of that node. The footnotes are
-; separated from the rest of the node by a line of dashes with
-; the word `Footnotes' within it.
-;
-; `Make Node'
-; In the "Make Node" style, all the footnotes for a single node are
-; placed in an automatically constructed node of their own.
-
-(put 'footnote 'texinfo-format 'texinfo-format-footnote)
-
-(defvar texinfo-footnote-style 'MN "\
-*Footnote style, either EN for end node or MN for make node.")
-
-(defvar texinfo-footnote-number)
-
-(defun texinfo-format-footnote ()
- "Format a footnote in either `end node' or `make node' style.
-The texinfo-footnote-style variable controls which style is used."
- (setq texinfo-footnote-number (1+ texinfo-footnote-number))
- (cond ((eq texinfo-footnote-style 'EN) (texinfo-format-end-node))
- ((eq texinfo-footnote-style 'MN) (texinfo-format-make-node))))
-
-(defun texinfo-format-make-node ()
- "Format footnote in `MN', Make Node, style with notes in own node.
-The node is constructed automatically."
- (let* (start
- (arg (texinfo-parse-expanded-arg))
- (node-name-beginning
- (save-excursion
- (re-search-backward
- "^File: \\w+\\(\\w\\|\\s_\\|\\.\\)*[ \t]+Node:")
- (match-end 0)))
- (node-name
- (save-excursion
- (buffer-substring
- (progn (goto-char node-name-beginning) ; skip over node command
- (skip-chars-forward " \t") ; and over spaces
- (point))
- (if (search-forward
- ","
- (save-excursion (end-of-line) (point)) t) ; bound search
- (1- (point))
- (end-of-line) (point))))))
- (texinfo-discard-command)
- (insert (format "(%d) (*note %s-Footnotes::)"
- texinfo-footnote-number node-name))
- (fill-paragraph nil)
- (save-excursion
- (if (re-search-forward "^@node" nil 'move)
- (forward-line -1))
-
- ;; two cases: for the first footnote, we must insert a node header;
- ;; for the second and subsequent footnotes, we need only insert
- ;; the text of the footnote.
-
- (if (save-excursion
- (re-search-backward
- (concat node-name "-Footnotes, Up: ")
- node-name-beginning
- t))
- (progn ; already at least one footnote
- (setq start (point))
- (insert (format "\n(%d) %s\n" texinfo-footnote-number arg))
- (fill-region start (point)))
- ;; else not yet a footnote
- (insert "\n\^_\nFile: " texinfo-format-filename
- " Node: " node-name "-Footnotes, Up: " node-name "\n")
- (setq start (point))
- (insert (format "\n(%d) %s\n" texinfo-footnote-number arg))
- (fill-region start (point))))))
-
-(defun texinfo-format-end-node ()
- "Format footnote in `EN', End Node, style with notes at end of node."
- (let (start
- (arg (texinfo-parse-expanded-arg)))
- (texinfo-discard-command)
- (insert (format "(%d) " texinfo-footnote-number))
- (fill-paragraph nil)
- (save-excursion
- (if (search-forward "\n--------- Footnotes ---------\n" nil t)
- (progn ; already have footnote, put new one before end of node
- (if (re-search-forward "^@node" nil 'move)
- (forward-line -1))
- (setq start (point))
- (insert (format "\n(%d) %s\n" texinfo-footnote-number arg))
- (fill-region start (point)))
- ;; else no prior footnote
- (if (re-search-forward "^@node" nil 'move)
- (forward-line -1))
- (insert "\n--------- Footnotes ---------\n")
- (setq start (point))
- (insert (format "\n(%d) %s\n" texinfo-footnote-number arg))
- (fill-region start (point))))))
-
;; @itemize pushes (itemize "COMMANDS" STARTPOS) on texinfo-stack.
;; @enumerate pushes (enumerate 0 STARTPOS).
@@ -869,47 +675,6 @@ The node is constructed automatically."
(itemfont (car (cdr (car texinfo-stack)))))
(insert ?\b itemfont ?\{ arg "}\n \n"))
(forward-line -2))
-
-
-; @ftable
-
-; The `@ftable' command is like the `@table' command but it also
-; inserts each item in the first column into the function index.
-
-(put 'ftable 'texinfo-format 'texinfo-ftable)
-
-; The following function presumes that the first column of the table
-; should be in `@code' font; but the texinfo.tex source does not
-; presume this.
-; (defun texinfo-ftable ()
-; (texinfo-push-stack 'ftable "@code")
-; (setq fill-column (- fill-column 5))
-; (texinfo-discard-line))
-
-(defun texinfo-ftable ()
- (texinfo-push-stack 'ftable (texinfo-parse-arg-discard))
- (setq fill-column (- fill-column 5)))
-
-(put 'ftable 'texinfo-item 'texinfo-ftable-item)
-(defun texinfo-ftable-item ()
- (let ((item (texinfo-parse-arg-discard))
- (itemfont (car (cdr (car texinfo-stack))))
- (indexvar 'texinfo-findex))
- (insert ?\b itemfont ?\{ item "}\n \n")
- (set indexvar
- (cons
- (list item texinfo-last-node)
- (symbol-value indexvar)))
- (forward-line -2)))
-
-(put 'ftable 'texinfo-end 'texinfo-end-ftable)
-(defun texinfo-end-ftable ()
- (setq fill-column (+ fill-column 5))
- (texinfo-discard-command)
- (let ((stacktop
- (texinfo-pop-stack 'ftable)))
- (texinfo-do-itemize (nth 1 stacktop))))
-
(put 'ifinfo 'texinfo-format 'texinfo-discard-line)
(put 'ifinfo 'texinfo-end 'texinfo-discard-command)
@@ -934,30 +699,6 @@ The node is constructed automatically."
(put 'endtitlepage 'texinfo-format 'texinfo-discard-line)
-; @titlespec an alternative titling command; ignored by Info
-
-(put 'titlespec 'texinfo-format 'texinfo-format-titlespec)
-(defun texinfo-format-titlespec ()
- (delete-region texinfo-command-start
- (progn (search-forward "@end titlespec\n")
- (point))))
-
-(put 'endtitlespec 'texinfo-format 'texinfo-discard-line)
-
-; @today{}
-
-(put 'today 'texinfo-format 'texinfo-format-today)
-
-; Produces Day Month Year style of output. eg `1 Jan 1900'
-; The `@today{}' command requires a pair of braces, like `@dots{}'.
-(defun texinfo-format-today ()
- (texinfo-parse-arg-discard)
- (insert (format "%s %s %s"
- (substring (current-time-string) 8 10)
- (substring (current-time-string) 4 7)
- (substring (current-time-string) -4))))
-
-
(put 'ignore 'texinfo-format 'texinfo-format-ignore)
(defun texinfo-format-ignore ()
(delete-region texinfo-command-start
@@ -967,20 +708,15 @@ The node is constructed automatically."
(put 'endignore 'texinfo-format 'texinfo-discard-line)
(put 'var 'texinfo-format 'texinfo-format-var)
-; @sc a small caps font for TeX; formatted as `var' in Info
-(put 'sc 'texinfo-format 'texinfo-format-var)
(defun texinfo-format-var ()
(insert (upcase (texinfo-parse-arg-discard)))
(goto-char texinfo-command-start))
-; various noops
-
(put 'asis 'texinfo-format 'texinfo-format-noop)
(put 'b 'texinfo-format 'texinfo-format-noop)
(put 't 'texinfo-format 'texinfo-format-noop)
(put 'i 'texinfo-format 'texinfo-format-noop)
(put 'r 'texinfo-format 'texinfo-format-noop)
-(put 'titlefont 'texinfo-format 'texinfo-format-noop)
(put 'key 'texinfo-format 'texinfo-format-noop)
(put 'w 'texinfo-format 'texinfo-format-noop)
(defun texinfo-format-noop ()
@@ -1010,13 +746,10 @@ The node is constructed automatically."
(put 'bullet 'texinfo-format 'texinfo-format-bullet)
(defun texinfo-format-bullet ()
- "Insert an asterisk.
-If used within a line, follow `@bullet' with braces."
- (texinfo-optional-braces-discard)
+ (texinfo-discard-command)
(insert "*"))
(put 'smallexample 'texinfo-format 'texinfo-format-example)
-(put 'smalllisp 'texinfo-format 'texinfo-format-example)
(put 'example 'texinfo-format 'texinfo-format-example)
(put 'quotation 'texinfo-format 'texinfo-format-example)
(put 'lisp 'texinfo-format 'texinfo-format-example)
@@ -1056,41 +789,6 @@ If used within a line, follow `@bullet' with braces."
(end-of-line)
(insert "\n ")))
-
-;; @flushright ... @end flushright
-
-; The @flushright command right justifies every line but leaves the
-; left end ragged.
-
-(put 'flushright 'texinfo-format 'texinfo-format-flushright)
-(defun texinfo-format-flushright ()
- (texinfo-push-stack 'flushright nil)
- (texinfo-discard-line))
-
-(put 'flushright 'texinfo-end 'texinfo-end-flushright)
-(defun texinfo-end-flushright ()
- (texinfo-discard-command)
-
- (let ((stacktop
- (texinfo-pop-stack 'flushright)))
-
- (texinfo-do-flushright (nth 1 stacktop))))
-
-(defun texinfo-do-flushright (from)
- (save-excursion
- (while (progn (forward-line -1)
- (>= (point) from))
-
- (beginning-of-line)
- (insert
- (make-string
- (- fill-column
- (save-excursion
- (end-of-line)
- (current-column)))
- ? )))))
-
-
(put 'ctrl 'texinfo-format 'texinfo-format-ctrl)
(defun texinfo-format-ctrl ()
(let ((str (texinfo-parse-arg-discard)))
@@ -1108,9 +806,7 @@ If used within a line, follow `@bullet' with braces."
(put 'minus 'texinfo-format 'texinfo-format-minus)
(defun texinfo-format-minus ()
- "Insert a minus sign.
-If used within a line, follow `@minus' with braces."
- (texinfo-optional-braces-discard)
+ (texinfo-parse-arg-discard)
(insert "-"))
(put 'dots 'texinfo-format 'texinfo-format-dots)
@@ -1123,8 +819,12 @@ If used within a line, follow `@minus' with braces."
(texinfo-discard-command)
(fill-paragraph nil))
+(put 'sp 'texinfo-format 'texinfo-format-sp)
+(defun texinfo-format-sp ()
+ (texinfo-discard-command)
+ (insert "\n"))
-;;; Index generation
+;; Index generation
(put 'vindex 'texinfo-format 'texinfo-format-vindex)
(defun texinfo-format-vindex ()
@@ -1165,83 +865,7 @@ If used within a line, follow `@minus' with braces."
("pg" . texinfo-pindex)
("ky" . texinfo-kindex)))
-
-;;; @defindex @defcodeindex
-(put 'defindex 'texinfo-format 'texinfo-format-defindex)
-(put 'defcodeindex 'texinfo-format 'texinfo-format-defindex)
-
-(defun texinfo-format-defindex ()
- (let* ((index-name (texinfo-parse-arg-discard)) ; eg: `aa'
- (indexing-command (intern (concat index-name "index")))
- (index-formatting-command ; eg: `texinfo-format-aaindex'
- (intern (concat "texinfo-format-" index-name "index")))
- (index-alist-name ; eg: `texinfo-aaindex'
- (intern (concat "texinfo-" index-name "index"))))
-
- (set index-alist-name nil)
-
- (put indexing-command ; eg, aaindex
- 'texinfo-format
- index-formatting-command) ; eg, texinfo-format-aaindex
-
- ;; eg: "aa" . texinfo-aaindex
- (or (assoc index-name texinfo-indexvar-alist)
- (setq texinfo-indexvar-alist
- (cons
- (cons index-name
- index-alist-name)
- texinfo-indexvar-alist)))
-
- (fset index-formatting-command
- (list 'lambda 'nil
- (list 'texinfo-index
- (list 'quote index-alist-name))))))
-
-
-;;; @synindex @syncodeindex
-
-(put 'synindex 'texinfo-format 'texinfo-format-synindex)
-(put 'syncodeindex 'texinfo-format 'texinfo-format-synindex)
-
-(defun texinfo-format-synindex ()
- (let* ((args (texinfo-parse-arg-discard))
- (second (cdr (read-from-string args)))
- (joiner (symbol-name (car (read-from-string args))))
- (joined (symbol-name (car (read-from-string args second)))))
-
- (if (assoc joiner texinfo-short-index-cmds-alist)
- (put
- (cdr (assoc joiner texinfo-short-index-cmds-alist))
- 'texinfo-format
- (or (cdr (assoc joined texinfo-short-index-format-cmds-alist))
- (intern (concat "texinfo-format-" joined "index"))))
- (put
- (intern (concat joiner "index"))
- 'texinfo-format
- (or (cdr(assoc joined texinfo-short-index-format-cmds-alist))
- (intern (concat "texinfo-format-" joined "index")))))))
-
-(defconst texinfo-short-index-cmds-alist
- '(("cp" . cindex)
- ("fn" . findex)
- ("vr" . vindex)
- ("tp" . tindex)
- ("pg" . pindex)
- ("ky" . kindex)))
-
-(defconst texinfo-short-index-format-cmds-alist
- '(("cp" . texinfo-format-cindex)
- ("fn" . texinfo-format-findex)
- ("vr" . texinfo-format-vindex)
- ("tp" . texinfo-format-tindex)
- ("pg" . texinfo-format-pindex)
- ("ky" . texinfo-format-kindex)))
-
-
-;;; @printindex
-
(put 'printindex 'texinfo-format 'texinfo-format-printindex)
-
(defun texinfo-format-printindex ()
(let ((indexelts (symbol-value
(cdr (assoc (texinfo-parse-arg-discard)
@@ -1250,9 +874,8 @@ If used within a line, follow `@minus' with braces."
(insert "\n* Menu:\n\n")
(setq opoint (point))
(texinfo-print-index nil indexelts)
-
- (if (eq system-type 'vax-vms)
- (texinfo-sort-region opoint (point))
+ (if (eq system-type 'vax-vms)
+ (texinfo-sort-region opoint (point))
(shell-command-on-region opoint (point) "sort -fd" 1))))
(defun texinfo-print-index (file indexelts)
@@ -1267,47 +890,7 @@ If used within a line, follow `@minus' with braces."
(setq indexelts (cdr indexelts))))
-;;; NOTATIONS: @equiv, @error, etc
-
-;; @equiv to show that two expressions are equivalent
-;; @error to show an error message
-;; @expansion to show what a macro expands to
-;; @point to show the location of point in an example
-;; @print to show what an evaluated expression prints
-;; @result to indicate the value returned by an expression
-
-(put 'equiv 'texinfo-format 'texinfo-format-equiv)
-(defun texinfo-format-equiv ()
- (texinfo-parse-arg-discard)
- (insert "=="))
-
-(put 'error 'texinfo-format 'texinfo-format-error)
-(defun texinfo-format-error ()
- (texinfo-parse-arg-discard)
- (insert "error-->"))
-
-(put 'expansion 'texinfo-format 'texinfo-format-expansion)
-(defun texinfo-format-expansion ()
- (texinfo-parse-arg-discard)
- (insert "==>"))
-
-(put 'point 'texinfo-format 'texinfo-format-point)
-(defun texinfo-format-point ()
- (texinfo-parse-arg-discard)
- (insert "-!-"))
-
-(put 'print 'texinfo-format 'texinfo-format-print)
-(defun texinfo-format-print ()
- (texinfo-parse-arg-discard)
- (insert "-|"))
-
-(put 'result 'texinfo-format 'texinfo-format-result)
-(defun texinfo-format-result ()
- (texinfo-parse-arg-discard)
- (insert "=>"))
-
-
-;;;; Description formatting: @deffn, @defun, etc
+;;;; Lisp Definitions
(defun texinfo-format-defun ()
(texinfo-push-stack 'defun nil)
@@ -1319,115 +902,34 @@ If used within a line, follow `@minus' with braces."
(defun texinfo-format-defun-1 (first-p)
(let ((args (texinfo-format-parse-defun-args))
- (command-type (get texinfo-command-name 'texinfo-defun-type))
- (class "")
- (name "")
- (classification "")
- (data-type ""))
+ (type (get texinfo-command-name 'texinfo-defun-type)))
(texinfo-discard-command)
-
- (cond
- ;; Generalized object oriented entity: `category class name [args...]'
- ;; In Info, `Category on class: name ARG'
- ((eq (eval (car command-type)) 'defop-type)
- (setq category (car args))
- (setq class (car (cdr args)))
- (setq name (car args))
- (setq args (cdr (cdr args))))
-
- ;; Specialized object oriented entity: @defmethod, @defivar
- ;; "Instance Variable" `class name [args...]'
- ;; In Info, `Instance variable of class: name'
- ((eq (eval (car command-type)) 'defmethod-type)
- (setq category (car (cdr command-type)))
- (setq class (car args))
- (setq name (car args))
- (setq args (cdr args)))
-
- ;; Generalized function-like or variable-like entity:
- ;; `category name [args...]'
- ;; In Info, `Category: name ARGS'
- ((or (eq (eval (car command-type)) 'deffn-type)
- (eq (eval (car command-type)) 'deftp-type))
- (setq category (car args))
- (setq args (cdr args))
- (setq name (car args)))
-
- ;; Specialized function-like or variable-like entity:
- ;; "Macro" `name [args...]'
- ;; In Info, `Macro: Name ARGS'
- ((eq (eval (car command-type)) 'defun-type)
- (setq category (car (cdr command-type)))
- (setq name (car args)))
-
- ;; Generalized typed-function-like or typed-variable-like entity:
- ;; `Classification data-type name [args...]'
- ;; In Info, `Classification: data-type name ARGS'
- ((or (eq (eval (car command-type)) 'deftypefn-type)
- (eq (eval (car command-type)) 'deftypevr-type))
- (setq classification (car args))
- (setq data-type (car (cdr args)))
- (setq name (car (cdr (cdr args))))
- (setq args (cdr (cdr (cdr args)))))
-
- ;; Specialized typed-function-like or typed-variable-like entity:
- ;; `data-type name [args...]'
- ;; In Info, `Function: data-type name ARGS'
- ;; or, `Variable: data-type name'
- ((or (eq (eval (car command-type)) 'deftypefun-type)
- (eq (eval (car command-type)) 'deftypevar-type))
- (setq classification (car (cdr command-type)))
- (setq data-type (car args))
- (setq name (car (cdr args)))
- (setq args (cdr (cdr args)))))
-
+ (if (eq type 'arg)
+ (progn (setq type (car args))
+ (setq args (cdr args))))
+ (let ((formatter (get texinfo-command-name 'texinfo-defun-format-type)))
+ (if formatter
+ (setq type (funcall formatter type args))))
;; Delete extra newline inserted after previous header line.
(if (not first-p)
(delete-char -1))
-
- (let ((formatter (get texinfo-command-name 'texinfo-defun-format-type)))
- (cond
- ;; if typed function or variable
- ((eq formatter 'texinfo-format-deftypefn-type)
- (insert "* " classification ": " data-type " " name)
- (let ((args args))
- (while args
- (insert " " (car args))
- (setq args (cdr args)))))
- (t
- ;; and if object oriented, set category
- (if (or (eq formatter 'texinfo-format-defop-type)
- (eq formatter 'texinfo-format-defcv-type))
- (setq category (funcall formatter category class)))
- (insert "* " category ": " name)
- (let ((args (cdr args)))
- (while args
- (insert " "
- (if (or (= ?& (aref (car args) 0))
- (eq (eval (car command-type)) 'deftp-type))
- (car args)
- (upcase (car args))))
- (setq args (cdr args)))))))
-
+ (insert "* " type ": " (car args))
+ (let ((args (cdr args)))
+ (while args
+ (insert " "
+ (if (= ?& (aref (car args) 0))
+ (car args)
+ (upcase (car args))))
+ (setq args (cdr args))))
;; Insert extra newline so that paragraph filling does not mess
;; with header line.
(insert "\n\n")
(rplaca (cdr (cdr (car texinfo-stack))) (point))
-
(let ((indexvar (get texinfo-command-name 'texinfo-defun-index))
- (index-formatter
- (get texinfo-command-name 'texinfo-defun-format-index)))
+ (formatter (get texinfo-command-name 'texinfo-defun-format-index)))
(set indexvar
- (cons (list
- (cond
- ;; if object oriented
- ((or (eq index-formatter 'texinfo-format-defop-index)
- (eq index-formatter 'texinfo-format-defcv-index))
- (funcall index-formatter name class))
- ((eq index-formatter 'texinfo-format-deftypefn-index)
- (funcall index-formatter name data-type))
- (t (car args)))
- texinfo-last-node)
+ (cons (list (if formatter (funcall formatter type args) (car args))
+ texinfo-last-node)
(symbol-value indexvar))))))
(defun texinfo-end-defun ()
@@ -1440,95 +942,67 @@ If used within a line, follow `@minus' with braces."
(goto-char start)
(delete-char -1))))
-(defun texinfo-format-defop-type (category class)
- (format "%s on %s" category class))
-
-(defun texinfo-format-defop-index (name class)
- (format "%s on %s" name class))
-
-(defun texinfo-format-defcv-type (category class)
- (format "%s of %s" category class))
-
-(defun texinfo-format-defcv-index (name class)
- (format "%s of %s" name class))
-
(put 'deffn 'texinfo-format 'texinfo-format-defun)
(put 'deffnx 'texinfo-format 'texinfo-format-defunx)
(put 'deffn 'texinfo-end 'texinfo-end-defun)
-(put 'deffn 'texinfo-defun-type '('deffn-type nil))
-(put 'deffnx 'texinfo-defun-type '('deffn-type nil))
+(put 'deffn 'texinfo-defun-type 'arg)
+(put 'deffnx 'texinfo-defun-type 'arg)
(put 'deffn 'texinfo-defun-index 'texinfo-findex)
(put 'deffnx 'texinfo-defun-index 'texinfo-findex)
(put 'defun 'texinfo-format 'texinfo-format-defun)
(put 'defunx 'texinfo-format 'texinfo-format-defunx)
(put 'defun 'texinfo-end 'texinfo-end-defun)
-(put 'defun 'texinfo-defun-type '('defun-type "Function"))
-(put 'defunx 'texinfo-defun-type '('defun-type "Function"))
+(put 'defun 'texinfo-defun-type "Function")
+(put 'defunx 'texinfo-defun-type "Function")
(put 'defun 'texinfo-defun-index 'texinfo-findex)
(put 'defunx 'texinfo-defun-index 'texinfo-findex)
(put 'defmac 'texinfo-format 'texinfo-format-defun)
(put 'defmacx 'texinfo-format 'texinfo-format-defunx)
(put 'defmac 'texinfo-end 'texinfo-end-defun)
-(put 'defmac 'texinfo-defun-type '('defun-type "Macro"))
-(put 'defmacx 'texinfo-defun-type '('defun-type "Macro"))
+(put 'defmac 'texinfo-defun-type "Macro")
+(put 'defmacx 'texinfo-defun-type "Macro")
(put 'defmac 'texinfo-defun-index 'texinfo-findex)
(put 'defmacx 'texinfo-defun-index 'texinfo-findex)
(put 'defspec 'texinfo-format 'texinfo-format-defun)
(put 'defspecx 'texinfo-format 'texinfo-format-defunx)
(put 'defspec 'texinfo-end 'texinfo-end-defun)
-(put 'defspec 'texinfo-defun-type '('defun-type "Special form"))
-(put 'defspecx 'texinfo-defun-type '('defun-type "Special form"))
+(put 'defspec 'texinfo-defun-type "Special form")
+(put 'defspecx 'texinfo-defun-type "Special form")
(put 'defspec 'texinfo-defun-index 'texinfo-findex)
(put 'defspecx 'texinfo-defun-index 'texinfo-findex)
(put 'defvr 'texinfo-format 'texinfo-format-defun)
(put 'defvrx 'texinfo-format 'texinfo-format-defunx)
(put 'defvr 'texinfo-end 'texinfo-end-defun)
-(put 'defvr 'texinfo-defun-type '('deffn-type nil))
-(put 'defvrx 'texinfo-defun-type '('deffn-type nil))
+(put 'defvr 'texinfo-defun-type 'arg)
+(put 'defvrx 'texinfo-defun-type 'arg)
(put 'defvr 'texinfo-defun-index 'texinfo-vindex)
(put 'defvrx 'texinfo-defun-index 'texinfo-vindex)
(put 'defvar 'texinfo-format 'texinfo-format-defun)
(put 'defvarx 'texinfo-format 'texinfo-format-defunx)
(put 'defvar 'texinfo-end 'texinfo-end-defun)
-(put 'defvar 'texinfo-defun-type '('defun-type "Variable"))
-(put 'defvarx 'texinfo-defun-type '('defun-type "Variable"))
+(put 'defvar 'texinfo-defun-type "Variable")
+(put 'defvarx 'texinfo-defun-type "Variable")
(put 'defvar 'texinfo-defun-index 'texinfo-vindex)
(put 'defvarx 'texinfo-defun-index 'texinfo-vindex)
-(put 'defconst 'texinfo-format 'texinfo-format-defun)
-(put 'defconstx 'texinfo-format 'texinfo-format-defunx)
-(put 'defconst 'texinfo-end 'texinfo-end-defun)
-(put 'defconst 'texinfo-defun-type '('defun-type "Constant"))
-(put 'defconstx 'texinfo-defun-type '('defun-type "Constant"))
-(put 'defconst 'texinfo-defun-index 'texinfo-vindex)
-(put 'defconstx 'texinfo-defun-index 'texinfo-vindex)
-
-(put 'defcmd 'texinfo-format 'texinfo-format-defun)
-(put 'defcmdx 'texinfo-format 'texinfo-format-defunx)
-(put 'defcmd 'texinfo-end 'texinfo-end-defun)
-(put 'defcmd 'texinfo-defun-type '('defun-type "Command"))
-(put 'defcmdx 'texinfo-defun-type '('defun-type "Command"))
-(put 'defcmd 'texinfo-defun-index 'texinfo-findex)
-(put 'defcmdx 'texinfo-defun-index 'texinfo-findex)
-
(put 'defopt 'texinfo-format 'texinfo-format-defun)
(put 'defoptx 'texinfo-format 'texinfo-format-defunx)
(put 'defopt 'texinfo-end 'texinfo-end-defun)
-(put 'defopt 'texinfo-defun-type '('defun-type "User Option"))
-(put 'defoptx 'texinfo-defun-type '('defun-type "User Option"))
+(put 'defopt 'texinfo-defun-type "User Option")
+(put 'defoptx 'texinfo-defun-type "User Option")
(put 'defopt 'texinfo-defun-index 'texinfo-vindex)
(put 'defoptx 'texinfo-defun-index 'texinfo-vindex)
(put 'deftp 'texinfo-format 'texinfo-format-defun)
(put 'deftpx 'texinfo-format 'texinfo-format-defunx)
(put 'deftp 'texinfo-end 'texinfo-end-defun)
-(put 'deftp 'texinfo-defun-type '('deftp-type nil))
-(put 'deftpx 'texinfo-defun-type '('deftp-type nil))
+(put 'deftp 'texinfo-defun-type 'arg)
+(put 'deftpx 'texinfo-defun-type 'arg)
(put 'deftp 'texinfo-defun-index 'texinfo-tindex)
(put 'deftpx 'texinfo-defun-index 'texinfo-tindex)
@@ -1537,8 +1011,8 @@ If used within a line, follow `@minus' with braces."
(put 'defop 'texinfo-format 'texinfo-format-defun)
(put 'defopx 'texinfo-format 'texinfo-format-defunx)
(put 'defop 'texinfo-end 'texinfo-end-defun)
-(put 'defop 'texinfo-defun-type '('defop-type nil))
-(put 'defopx 'texinfo-defun-type '('defop-type nil))
+(put 'defop 'texinfo-defun-type 'arg)
+(put 'defopx 'texinfo-defun-type 'arg)
(put 'defop 'texinfo-defun-format-type 'texinfo-format-defop-type)
(put 'defopx 'texinfo-defun-format-type 'texinfo-format-defop-type)
(put 'defop 'texinfo-defun-index 'texinfo-findex)
@@ -1549,8 +1023,8 @@ If used within a line, follow `@minus' with braces."
(put 'defmethod 'texinfo-format 'texinfo-format-defun)
(put 'defmethodx 'texinfo-format 'texinfo-format-defunx)
(put 'defmethod 'texinfo-end 'texinfo-end-defun)
-(put 'defmethod 'texinfo-defun-type '('defmethod-type "Operation"))
-(put 'defmethodx 'texinfo-defun-type '('defmethod-type "Operation"))
+(put 'defmethod 'texinfo-defun-type "Operation")
+(put 'defmethodx 'texinfo-defun-type "Operation")
(put 'defmethod 'texinfo-defun-format-type 'texinfo-format-defop-type)
(put 'defmethodx 'texinfo-defun-format-type 'texinfo-format-defop-type)
(put 'defmethod 'texinfo-defun-index 'texinfo-findex)
@@ -1558,11 +1032,17 @@ If used within a line, follow `@minus' with braces."
(put 'defmethod 'texinfo-defun-format-index 'texinfo-format-defop-index)
(put 'defmethodx 'texinfo-defun-format-index 'texinfo-format-defop-index)
+(defun texinfo-format-defop-type (type args)
+ (format "%s on %s" type (car args)))
+
+(defun texinfo-format-defop-index (type args)
+ (format "%s on %s" (car (cdr args)) (car args)))
+
(put 'defcv 'texinfo-format 'texinfo-format-defun)
(put 'defcvx 'texinfo-format 'texinfo-format-defunx)
(put 'defcv 'texinfo-end 'texinfo-end-defun)
-(put 'defcv 'texinfo-defun-type '('defop-type nil))
-(put 'defcvx 'texinfo-defun-type '('defop-type nil))
+(put 'defcv 'texinfo-defun-type 'arg)
+(put 'defcvx 'texinfo-defun-type 'arg)
(put 'defcv 'texinfo-defun-format-type 'texinfo-format-defcv-type)
(put 'defcvx 'texinfo-defun-format-type 'texinfo-format-defcv-type)
(put 'defcv 'texinfo-defun-index 'texinfo-vindex)
@@ -1573,8 +1053,8 @@ If used within a line, follow `@minus' with braces."
(put 'defivar 'texinfo-format 'texinfo-format-defun)
(put 'defivarx 'texinfo-format 'texinfo-format-defunx)
(put 'defivar 'texinfo-end 'texinfo-end-defun)
-(put 'defivar 'texinfo-defun-type '('defmethod-type "Instance variable"))
-(put 'defivarx 'texinfo-defun-type '('defmethod-type "Instance variable"))
+(put 'defivar 'texinfo-defun-type "Instance variable")
+(put 'defivarx 'texinfo-defun-type "Instance variable")
(put 'defivar 'texinfo-defun-format-type 'texinfo-format-defcv-type)
(put 'defivarx 'texinfo-defun-format-type 'texinfo-format-defcv-type)
(put 'defivar 'texinfo-defun-index 'texinfo-vindex)
@@ -1582,140 +1062,58 @@ If used within a line, follow `@minus' with braces."
(put 'defivar 'texinfo-defun-format-index 'texinfo-format-defcv-index)
(put 'defivarx 'texinfo-defun-format-index 'texinfo-format-defcv-index)
-;;; Typed functions and variables
-
-(defun texinfo-format-deftypefn-type (classification data-type)
- (format "%s" classification data-type))
-
-(defun texinfo-format-deftypefn-index (name data-type)
- (format "%s of type %s" name data-type))
-
-
-(put 'deftypefn 'texinfo-format 'texinfo-format-defun)
-(put 'deftypefnx 'texinfo-format 'texinfo-format-defunx)
-(put 'deftypefn 'texinfo-end 'texinfo-end-defun)
-(put 'deftypefn 'texinfo-defun-type '('deftypefn-type nil))
-(put 'deftypefnx 'texinfo-defun-type '('deftypefn-type nil))
-(put 'deftypefn 'texinfo-defun-format-type 'texinfo-format-deftypefn-type)
-(put 'deftypefnx 'texinfo-defun-format-type 'texinfo-format-deftypefn-type)
-(put 'deftypefn 'texinfo-defun-index 'texinfo-findex)
-(put 'deftypefnx 'texinfo-defun-index 'texinfo-findex)
-(put 'deftypefn 'texinfo-defun-format-index 'texinfo-format-deftypefn-index)
-(put 'deftypefnx 'texinfo-defun-format-index 'texinfo-format-deftypefn-index)
-
-(put 'deftypefun 'texinfo-format 'texinfo-format-defun)
-(put 'deftypefunx 'texinfo-format 'texinfo-format-defunx)
-(put 'deftypefun 'texinfo-end 'texinfo-end-defun)
-(put 'deftypefun 'texinfo-defun-type '('deftypefun-type "Function"))
-(put 'deftypefunx 'texinfo-defun-type '('deftypefun-type "Function"))
-(put 'deftypefun 'texinfo-defun-format-type 'texinfo-format-deftypefn-type)
-(put 'deftypefunx 'texinfo-defun-format-type 'texinfo-format-deftypefn-type)
-(put 'deftypefun 'texinfo-defun-index 'texinfo-findex)
-(put 'deftypefunx 'texinfo-defun-index 'texinfo-findex)
-(put 'deftypefun 'texinfo-defun-format-index 'texinfo-format-deftypefn-index)
-(put 'deftypefunx 'texinfo-defun-format-index 'texinfo-format-deftypefn-index)
-
-(put 'deftypevr 'texinfo-format 'texinfo-format-defun)
-(put 'deftypevrx 'texinfo-format 'texinfo-format-defunx)
-(put 'deftypevr 'texinfo-end 'texinfo-end-defun)
-(put 'deftypevr 'texinfo-defun-type '('deftypefn-type nil))
-(put 'deftypevrx 'texinfo-defun-type '('deftypefn-type nil))
-(put 'deftypevr 'texinfo-defun-format-type 'texinfo-format-deftypefn-type)
-(put 'deftypevrx 'texinfo-defun-format-type 'texinfo-format-deftypefn-type)
-(put 'deftypevr 'texinfo-defun-index 'texinfo-vindex)
-(put 'deftypevrx 'texinfo-defun-index 'texinfo-vindex)
-(put 'deftypevr 'texinfo-defun-format-index 'texinfo-format-deftypefn-index)
-(put 'deftypevrx 'texinfo-defun-format-index 'texinfo-format-deftypefn-index)
-
-(put 'deftypevar 'texinfo-format 'texinfo-format-defun)
-(put 'deftypevarx 'texinfo-format 'texinfo-format-defunx)
-(put 'deftypevar 'texinfo-end 'texinfo-end-defun)
-(put 'deftypevar 'texinfo-defun-type '('deftypevar-type "Variable"))
-(put 'deftypevarx 'texinfo-defun-type '('deftypevar-type "Variable"))
-(put 'deftypevar 'texinfo-defun-format-type 'texinfo-format-deftypefn-type)
-(put 'deftypevarx 'texinfo-defun-format-type 'texinfo-format-deftypefn-type)
-(put 'deftypevar 'texinfo-defun-index 'texinfo-vindex)
-(put 'deftypevarx 'texinfo-defun-index 'texinfo-vindex)
-(put 'deftypevar 'texinfo-defun-format-index 'texinfo-format-deftypefn-index)
-(put 'deftypevarx 'texinfo-defun-format-index 'texinfo-format-deftypefn-index)
+(defun texinfo-format-defcv-type (type args)
+ (format "%s of %s" type (car args)))
+(defun texinfo-format-defcv-index (type args)
+ (format "%s of %s" (car (cdr args)) (car args)))
-;; process included files: `@include' command
-
-;; Updated 19 October 1990
-;; In the original version, include files were ignored by Info but
-;; incorporated in to the printed manual. To make references to the
-;; included file, the Texinfo source file has to refer to the included
-;; files using the `(filename)nodename' format for refering to other
-;; Info files. Also, the included files had to be formatted on their
-;; own. It was just like they were another file.
-
-;; Currently, include files are inserted into the buffer that is
-;; formatted for Info. If large, the resulting info file is split and
-;; tagified. For current include files to work, the master menu must
-;; refer to all the nodes, and the highest level nodes in the include
-;; files must have the correct next, prev, and up pointers.
-
-;; The included file may have an @setfilename and even an @settitle,
-;; but not an /input texinfo
-
-; Original definition:
-; (defun texinfo-format-include ()
-; (let ((filename (texinfo-parse-arg-discard))
-; (default-directory input-directory)
-; subindex)
-; (setq subindex
-; (save-excursion
-; (progn (find-file
-; (cond ((file-readable-p (concat filename ".texinfo"))
-; (concat filename ".texinfo"))
-; ((file-readable-p (concat filename ".texi"))
-; (concat filename ".texi"))
-; ((file-readable-p (concat filename ".tex"))
-; (concat filename ".tex"))
-; ((file-readable-p filename)
-; filename)
-; (t (error "@include'd file %s not found"
-; filename))))
-; (texinfo-format-buffer-1))))
-; (texinfo-subindex 'texinfo-vindex (car subindex) (nth 1 subindex))
-; (texinfo-subindex 'texinfo-findex (car subindex) (nth 2 subindex))
-; (texinfo-subindex 'texinfo-cindex (car subindex) (nth 3 subindex))
-; (texinfo-subindex 'texinfo-pindex (car subindex) (nth 4 subindex))
-; (texinfo-subindex 'texinfo-tindex (car subindex) (nth 5 subindex))
-; (texinfo-subindex 'texinfo-kindex (car subindex) (nth 6 subindex))))
+;; process included files
+(put 'include 'texinfo-format 'texinfo-format-include)
+(defun texinfo-format-include ()
+ (let ((filename (texinfo-parse-arg-discard))
+ (default-directory input-directory)
+ subindex)
+ (setq subindex
+ (save-excursion
+ (progn (find-file
+ (cond ((file-readable-p (concat filename ".texinfo"))
+ (concat filename ".texinfo"))
+ ((file-readable-p (concat filename ".tex"))
+ (concat filename ".tex"))
+ ((file-readable-p filename)
+ filename)
+ (t (error "@include'd file %s not found"
+ filename))))
+ (texinfo-format-buffer-1))))
+ (texinfo-subindex 'texinfo-vindex (car subindex) (nth 1 subindex))
+ (texinfo-subindex 'texinfo-findex (car subindex) (nth 2 subindex))
+ (texinfo-subindex 'texinfo-cindex (car subindex) (nth 3 subindex))
+ (texinfo-subindex 'texinfo-pindex (car subindex) (nth 4 subindex))
+ (texinfo-subindex 'texinfo-tindex (car subindex) (nth 5 subindex))
+ (texinfo-subindex 'texinfo-kindex (car subindex) (nth 6 subindex))))
(defun texinfo-subindex (indexvar file content)
(set indexvar (cons (list 'recurse file content)
(symbol-value indexvar))))
-(put 'include 'texinfo-format 'texinfo-format-include)
-(defun texinfo-format-include ()
- (let ((filename (concat input-directory
- (texinfo-parse-arg-discard)))
- (default-directory input-directory))
- (message "Reading: %s" filename)
- (save-excursion
- (insert-file-contents filename)))
- (setq last-input-buffer input-buffer) ; to bypass setfilename
- )
-
-
;; Lots of bolio constructs do nothing in texinfo.
+(put 'need 'texinfo-format 'texinfo-discard-line-with-args)
(put 'page 'texinfo-format 'texinfo-discard-line-with-args)
(put 'c 'texinfo-format 'texinfo-discard-line-with-args)
(put 'comment 'texinfo-format 'texinfo-discard-line-with-args)
(put 'setchapternewpage 'texinfo-format 'texinfo-discard-line-with-args)
(put 'contents 'texinfo-format 'texinfo-discard-line-with-args)
(put 'summarycontents 'texinfo-format 'texinfo-discard-line-with-args)
-(put 'shortcontents 'texinfo-format 'texinfo-discard-line-with-args)
(put 'nopara 'texinfo-format 'texinfo-discard-line-with-args)
(put 'noindent 'texinfo-format 'texinfo-discard-line-with-args)
(put 'setx 'texinfo-format 'texinfo-discard-line-with-args)
(put 'setq 'texinfo-format 'texinfo-discard-line-with-args)
(put 'settitle 'texinfo-format 'texinfo-discard-line-with-args)
+(put 'defindex 'texinfo-format 'texinfo-discard-line-with-args)
+(put 'synindex 'texinfo-format 'texinfo-discard-line-with-args)
(put 'hsize 'texinfo-format 'texinfo-discard-line-with-args)
(put 'parindent 'texinfo-format 'texinfo-discard-line-with-args)
(put 'lispnarrowing 'texinfo-format 'texinfo-discard-line-with-args)
@@ -1723,7 +1121,6 @@ If used within a line, follow `@minus' with braces."
(put 'headings 'texinfo-format 'texinfo-discard-line-with-args)
(put 'group 'texinfo-format 'texinfo-discard-line-with-args)
(put 'group 'texinfo-end 'texinfo-discard-line-with-args)
-(put 'need 'texinfo-format 'texinfo-discard-line-with-args)
(put 'bye 'texinfo-format 'texinfo-discard-line)
(put 'smallbook 'texinfo-format 'texinfo-discard-line)
@@ -1793,7 +1190,7 @@ For example, invoke
(progn
(if buffer-file-name (kill-buffer (current-buffer)))
(find-file file)
- (buffer-disable-undo (current-buffer))
+ (buffer-flush-undo (current-buffer))
(set-buffer-modified-p nil)
(texinfo-mode)
(message "texinfo formatting %s..." file)
diff --git a/lisp/texinfmt.elc b/lisp/texinfmt.elc
new file mode 100644
index 00000000000..b27eefe2632
--- /dev/null
+++ b/lisp/texinfmt.elc
Binary files differ
diff --git a/lisp/texinfo.el b/lisp/texinfo.el
new file mode 100644
index 00000000000..32306d5edd8
--- /dev/null
+++ b/lisp/texinfo.el
@@ -0,0 +1,175 @@
+;; Major mode for editing texinfo files.
+;; Copyright (C) 1985, 1988 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 1, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+(defvar texinfo-mode-syntax-table nil)
+
+(if texinfo-mode-syntax-table
+ nil
+ (setq texinfo-mode-syntax-table (make-syntax-table))
+ (modify-syntax-entry ?\" " " texinfo-mode-syntax-table)
+ (modify-syntax-entry ?\\ " " texinfo-mode-syntax-table)
+ (modify-syntax-entry ?@ "\\" texinfo-mode-syntax-table)
+ (modify-syntax-entry ?\^q "\\" texinfo-mode-syntax-table)
+ (modify-syntax-entry ?\[ "(]" texinfo-mode-syntax-table)
+ (modify-syntax-entry ?\] ")[" texinfo-mode-syntax-table)
+ (modify-syntax-entry ?{ "(}" texinfo-mode-syntax-table)
+ (modify-syntax-entry ?} "){" texinfo-mode-syntax-table)
+ (modify-syntax-entry ?\' "w" texinfo-mode-syntax-table))
+
+(defvar texinfo-mode-map nil)
+
+(if texinfo-mode-map
+ nil
+ (setq texinfo-mode-map (make-sparse-keymap))
+ (define-key texinfo-mode-map "\C-c\C-f" 'texinfo-format-region)
+ (define-key texinfo-mode-map "\C-c\C-s" 'texinfo-show-structure)
+ (define-key texinfo-mode-map "\e}" 'up-list)
+ (define-key texinfo-mode-map "\e{" 'texinfo-insert-braces)
+ (define-key texinfo-mode-map "\C-c\C-cv" 'texinfo-insert-@var)
+ (define-key texinfo-mode-map "\C-c\C-cs" 'texinfo-insert-@samp)
+ (define-key texinfo-mode-map "\C-c\C-cn" 'texinfo-insert-@node)
+ (define-key texinfo-mode-map "\C-c\C-ci" 'texinfo-insert-@item)
+ (define-key texinfo-mode-map "\C-c\C-ce" 'texinfo-insert-@end)
+ (define-key texinfo-mode-map "\C-c\C-cd" 'texinfo-insert-@dfn)
+ (define-key texinfo-mode-map "\C-c\C-cc" 'texinfo-insert-@code))
+
+(defun texinfo-insert-@var ()
+ "Insert the string @var in a texinfo buffer."
+ (interactive)
+ (insert "@var{}")
+ (backward-char))
+
+(defun texinfo-insert-@samp ()
+ "Insert the string @samp in a texinfo buffer."
+ (interactive)
+ (insert "@samp{}")
+ (backward-char))
+
+(defun texinfo-insert-@node ()
+ "Insert the string @node in a texinfo buffer,
+along with a comment indicating the arguments to @node."
+ (interactive)
+ (insert "@node \n@comment node-name, next, previous, up")
+ (forward-line -1)
+ (forward-char 6))
+
+(defun texinfo-insert-@item ()
+ "Insert the string @item in a texinfo buffer."
+ (interactive)
+ (insert "@item")
+ (newline))
+
+(defun texinfo-insert-@end ()
+ "Insert the string @end in a texinfo buffer."
+ (interactive)
+ (insert "@end "))
+
+(defun texinfo-insert-@dfn ()
+ "Insert the string @dfn in a texinfo buffer."
+ (interactive)
+ (insert "@dfn{}")
+ (backward-char))
+
+(defun texinfo-insert-@code ()
+ "Insert the string @code in a texinfo buffer."
+ (interactive)
+ (insert "@code{}")
+ (backward-char))
+
+(defun texinfo-insert-braces ()
+ "Make a pair of braces and be poised to type inside of them.
+Use \\[up-list] to move forward out of the braces."
+ (interactive)
+ (insert "{}")
+ (backward-char))
+
+(defun texinfo-mode ()
+ "Major mode for editing texinfo files.
+
+ It has these extra commands:
+\\{texinfo-mode-map}
+
+ These are files that are used as input for TeX to make printed manuals
+and also to be turned into Info files by \\[texinfo-format-buffer].
+These files must be written in a very restricted and modified version
+of TeX input format.
+
+ Editing commands are like text-mode except that the syntax table is
+set up so expression commands skip Texinfo bracket groups. To see
+what the Info version of a region of the Texinfo file will look like,
+use \\[texinfo-format-region]. This command runs Info on the current region
+of the Texinfo file and formats it properly.
+
+ You can show the structure of a Texinfo file with \\[texinfo-show-structure].
+This command shows the structure of a Texinfo file by listing the
+lines with the @-sign commands for @node, @chapter, @section and the
+like. These lines are displayed in another window called the *Occur*
+window. In that window, you can position the cursor over one of the
+lines and use \\[occur-mode-goto-occurrence], to jump to the
+corresponding spot in the Texinfo file.
+
+ In addition, Texinfo mode provides commands that insert various
+frequently used @-sign commands into the buffer. You can use these
+commands to save keystrokes. And you can insert balanced braces with
+\\[texinfo-insert-braces] and later use the command \\[up-list] to
+move forward past the closing brace.
+
+Entering Texinfo mode calls the value of text-mode-hook, and then the
+value of texinfo-mode-hook."
+ (interactive)
+ (kill-all-local-variables)
+ (setq mode-name "Texinfo")
+ (setq major-mode 'texinfo-mode)
+ (use-local-map texinfo-mode-map)
+ (set-syntax-table texinfo-mode-syntax-table)
+ (setq local-abbrev-table text-mode-abbrev-table)
+ (make-local-variable 'require-final-newline)
+ (setq require-final-newline t)
+ (make-local-variable 'paragraph-separate)
+ (setq paragraph-separate (concat "^\b\\|^@[a-zA-Z]*[ \n]\\|" paragraph-separate))
+ (make-local-variable 'paragraph-start)
+ (setq paragraph-start (concat "^\b\\|^@[a-zA-Z]*[ \n]\\|" paragraph-start))
+ (make-local-variable 'fill-column)
+ (setq fill-column 72)
+ (make-local-variable 'comment-start)
+ (setq comment-start "@c ")
+ (make-local-variable 'comment-start-skip)
+ (setq comment-start-skip "@c +")
+ (run-hooks 'text-mode-hook 'texinfo-mode-hook))
+
+(defvar texinfo-heading-pattern
+ "^@\\(chapter\\|unnum\\|appendix\\|sect\\|sub\\|heading\\|major\\|node\\)"
+ "This is a regular expression to match Texinfo lines that are chapter
+or sections headings or like such.")
+
+(defun texinfo-show-structure ()
+ "Show the structure of a Texinfo file by listing the lines with the
+@-sign commands for @node, @chapter, @section and the like. Lines
+with structuring commands in them are displayed in another window
+called the *Occur* window. In that window, you can position the
+cursor over one of the lines and use \\[occur-mode-goto-occurrence],
+to jump to the corresponding spot in the Texinfo file."
+ (interactive)
+ (save-excursion
+ (goto-char (point-min))
+ (occur texinfo-heading-pattern))
+ (pop-to-buffer "*Occur*")
+ (goto-char (point-min))
+ (flush-lines "-----"))
diff --git a/lisp/texinfo.elc b/lisp/texinfo.elc
new file mode 100644
index 00000000000..ea4c7061518
--- /dev/null
+++ b/lisp/texinfo.elc
@@ -0,0 +1,84 @@
+
+(defvar texinfo-mode-syntax-table nil)
+
+(if texinfo-mode-syntax-table nil (setq texinfo-mode-syntax-table (make-syntax-table)) (modify-syntax-entry 34 " " texinfo-mode-syntax-table) (modify-syntax-entry 92 " " texinfo-mode-syntax-table) (modify-syntax-entry 64 "\\" texinfo-mode-syntax-table) (modify-syntax-entry 17 "\\" texinfo-mode-syntax-table) (modify-syntax-entry 91 "(]" texinfo-mode-syntax-table) (modify-syntax-entry 93 ")[" texinfo-mode-syntax-table) (modify-syntax-entry 123 "(}" texinfo-mode-syntax-table) (modify-syntax-entry 125 "){" texinfo-mode-syntax-table) (modify-syntax-entry 39 "w" texinfo-mode-syntax-table))
+
+(defvar texinfo-mode-map nil)
+
+(if texinfo-mode-map nil (setq texinfo-mode-map (make-sparse-keymap)) (define-key texinfo-mode-map "" (quote texinfo-format-region)) (define-key texinfo-mode-map "" (quote texinfo-show-structure)) (define-key texinfo-mode-map "}" (quote up-list)) (define-key texinfo-mode-map "{" (quote texinfo-insert-braces)) (define-key texinfo-mode-map "v" (quote texinfo-insert-@var)) (define-key texinfo-mode-map "s" (quote texinfo-insert-@samp)) (define-key texinfo-mode-map "n" (quote texinfo-insert-@node)) (define-key texinfo-mode-map "i" (quote texinfo-insert-@item)) (define-key texinfo-mode-map "e" (quote texinfo-insert-@end)) (define-key texinfo-mode-map "d" (quote texinfo-insert-@dfn)) (define-key texinfo-mode-map "c" (quote texinfo-insert-@code)))
+
+(defun texinfo-insert-@var nil "\
+Insert the string @var in a texinfo buffer." (interactive) (byte-code "ÀˆÁcˆÂ ‡" [nil "@var{}" backward-char] 2))
+
+(defun texinfo-insert-@samp nil "\
+Insert the string @samp in a texinfo buffer." (interactive) (byte-code "ÀˆÁcˆÂ ‡" [nil "@samp{}" backward-char] 2))
+
+(defun texinfo-insert-@node nil "\
+Insert the string @node in a texinfo buffer,
+along with a comment indicating the arguments to @node." (interactive) (byte-code "ÀˆÁcˆÂÃ!ˆÄÅ!‡" [nil "@node
+@comment node-name, next, previous, up" forward-line -1 forward-char 6] 3))
+
+(defun texinfo-insert-@item nil "\
+Insert the string @item in a texinfo buffer." (interactive) (byte-code "ÀˆÁcˆÂ ‡" [nil "@item" newline] 2))
+
+(defun texinfo-insert-@end nil "\
+Insert the string @end in a texinfo buffer." (interactive) (byte-code "ÀˆÁc‡" [nil "@end "] 1))
+
+(defun texinfo-insert-@dfn nil "\
+Insert the string @dfn in a texinfo buffer." (interactive) (byte-code "ÀˆÁcˆÂ ‡" [nil "@dfn{}" backward-char] 2))
+
+(defun texinfo-insert-@code nil "\
+Insert the string @code in a texinfo buffer." (interactive) (byte-code "ÀˆÁcˆÂ ‡" [nil "@code{}" backward-char] 2))
+
+(defun texinfo-insert-braces nil "\
+Make a pair of braces and be poised to type inside of them.
+Use \\[up-list] to move forward out of the braces." (interactive) (byte-code "ÀˆÁcˆÂ ‡" [nil "{}" backward-char] 2))
+
+(defun texinfo-mode nil "\
+Major mode for editing texinfo files.
+
+ It has these extra commands:
+\\{texinfo-mode-map}
+
+ These are files that are used as input for TeX to make printed manuals
+and also to be turned into Info files by \\[texinfo-format-buffer].
+These files must be written in a very restricted and modified version
+of TeX input format.
+
+ Editing commands are like text-mode except that the syntax table is
+set up so expression commands skip Texinfo bracket groups. To see
+what the Info version of a region of the Texinfo file will look like,
+use \\[texinfo-format-region]. This command runs Info on the current region
+of the Texinfo file and formats it properly.
+
+ You can show the structure of a Texinfo file with \\[texinfo-show-structure].
+This command shows the structure of a Texinfo file by listing the
+lines with the @-sign commands for @node, @chapter, @section and the
+like. These lines are displayed in another window called the *Occur*
+window. In that window, you can position the cursor over one of the
+lines and use \\[occur-mode-goto-occurrence], to jump to the
+corresponding spot in the Texinfo file.
+
+ In addition, Texinfo mode provides commands that insert various
+frequently used @-sign commands into the buffer. You can use these
+commands to save keystrokes. And you can insert balanced braces with
+\\[texinfo-insert-braces] and later use the command \\[up-list] to
+move forward past the closing brace.
+
+Entering Texinfo mode calls the value of text-mode-hook, and then the
+value of texinfo-mode-hook." (interactive) (byte-code "͈ΠˆÏ‰ˆÐ‰ˆÑ
+!ˆÒ !ˆ ‰ˆÓÆ!ˆÇ‰ˆÓÈ!ˆÔP‰ˆÓÉ!ˆÔ P‰ ˆÓÊ!ˆÕ‰
+ˆÓË!ˆÖ‰ ˆÓÌ!ˆ×‰ ˆØÙÚ\"‡" [mode-name major-mode texinfo-mode-map texinfo-mode-syntax-table local-abbrev-table text-mode-abbrev-table require-final-newline t paragraph-separate paragraph-start fill-column comment-start comment-start-skip nil kill-all-local-variables "Texinfo" texinfo-mode use-local-map set-syntax-table make-local-variable "^\\|^@[a-zA-Z]*[
+]\\|" 72 "@c " "@c +" run-hooks text-mode-hook texinfo-mode-hook] 12))
+
+(defvar texinfo-heading-pattern "^@\\(chapter\\|unnum\\|appendix\\|sect\\|sub\\|heading\\|major\\|node\\)" "\
+This is a regular expression to match Texinfo lines that are chapter
+or sections headings or like such.")
+
+(defun texinfo-show-structure nil "\
+Show the structure of a Texinfo file by listing the lines with the
+@-sign commands for @node, @chapter, @section and the like. Lines
+with structuring commands in them are displayed in another window
+called the *Occur* window. In that window, you can position the
+cursor over one of the lines and use \\[occur-mode-goto-occurrence],
+to jump to the corresponding spot in the Texinfo file." (interactive) (byte-code "ÁˆŠebˆÂ!)ˆÃÄ!ˆebˆÅÆ!‡" [texinfo-heading-pattern nil occur pop-to-buffer "*Occur*" flush-lines "-----"] 4))
diff --git a/lisp/textmodes/text-mode.el b/lisp/text-mode.el
index ba54cb845f6..6b1e372f12f 100644
--- a/lisp/textmodes/text-mode.el
+++ b/lisp/text-mode.el
@@ -32,11 +32,7 @@
(modify-syntax-entry ?\\ ". " text-mode-syntax-table)
(modify-syntax-entry ?' "w " text-mode-syntax-table))
-(defvar text-mode-map nil
- "Keymap for Text mode.
-Many other modes, such as Mail mode, Outline mode and Indented Text mode,
-inherit all the commands defined in this map.")
-
+(defvar text-mode-map nil "")
(if text-mode-map
()
(setq text-mode-map (make-sparse-keymap))
@@ -53,7 +49,7 @@ inherit all the commands defined in this map.")
(defun text-mode ()
"Major mode for editing text intended for humans to read. Special commands:\\{text-mode-map}
-Turning on text-mode calls the value of the variable `text-mode-hook',
+Turning on text-mode calls the value of the variable text-mode-hook,
if that value is non-nil."
(interactive)
(kill-all-local-variables)
@@ -64,18 +60,17 @@ if that value is non-nil."
(set-syntax-table text-mode-syntax-table)
(run-hooks 'text-mode-hook))
-(defvar indented-text-mode-map ()
- "Keymap for Indented Text mode.
-All the commands defined in Text mode are inherited unless overridden.")
-
+(defvar indented-text-mode-map ())
(if indented-text-mode-map
()
- (setq indented-text-mode-map (nconc (make-sparse-keymap) text-mode-map))
- (define-key indented-text-mode-map "\t" 'indent-relative))
+ (setq indented-text-mode-map (make-sparse-keymap))
+ (define-key indented-text-mode-map "\t" 'indent-relative)
+ (define-key indented-text-mode-map "\es" 'center-line)
+ (define-key indented-text-mode-map "\eS" 'center-paragraph))
(defun indented-text-mode ()
"Major mode for editing indented text intended for humans to read.\\{indented-text-mode-map}
-Turning on indented-text-mode calls the value of the variable `text-mode-hook',
+Turning on indented-text-mode calls the value of the variable text-mode-hook,
if that value is non-nil."
(interactive)
(kill-all-local-variables)
@@ -90,20 +85,8 @@ if that value is non-nil."
(setq major-mode 'indented-text-mode)
(run-hooks 'text-mode-hook))
-(defun change-log-mode ()
- "Major mode for editing ChangeLog files. See M-x add-change-log-entry.
-Almost the same as Indented Text mode, but prevents numeric backups
-and sets `left-margin' to 8 and `fill-column' to 74."
- (interactive)
- (indented-text-mode)
- (setq left-margin 8)
- (setq fill-column 74)
- (make-local-variable 'version-control)
- (setq version-control 'never)
- (run-hooks 'change-log-mode-hook))
-
(defun center-paragraph ()
- "Center each nonblank line in the paragraph at or after point.
+ "Center each line in the paragraph at or after point.
See center-line for more info."
(interactive)
(save-excursion
@@ -114,7 +97,7 @@ See center-line for more info."
(center-region (point) end))))
(defun center-region (from to)
- "Center each nonblank line starting in the region.
+ "Center each line starting in the region.
See center-line for more info."
(interactive "r")
(if (> from to)
@@ -125,13 +108,12 @@ See center-line for more info."
(narrow-to-region from to)
(goto-char from)
(while (not (eobp))
- (or (save-excursion (skip-chars-forward " \t") (eolp))
- (center-line))
+ (center-line)
(forward-line 1)))))
(defun center-line ()
"Center the line point is on, within the width specified by `fill-column'.
-This means adjusting the indentation so that it equals
+This means adjusting the indentation to match
the distance between the end of the text and `fill-column'."
(interactive)
(save-excursion
diff --git a/lisp/text-mode.elc b/lisp/text-mode.elc
new file mode 100644
index 00000000000..712cc34b2bc
--- /dev/null
+++ b/lisp/text-mode.elc
Binary files differ
diff --git a/lisp/textmodes/bib-mode.el b/lisp/textmodes/bib-mode.el
deleted file mode 100644
index af6f2ded3f0..00000000000
--- a/lisp/textmodes/bib-mode.el
+++ /dev/null
@@ -1,233 +0,0 @@
-;; bib-mode, major mode for editing bib files.
-;; Copyright (C) 1989 Free Software Foundation, Inc.
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 1, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
-
-;; Bib-Mode
-;; GNU Emacs code to help maintain databases compatible with (troff)
-;; refer and lookbib. The file bib-file should be set to your
-;; bibliography file. Keys are automagically inserted as you type,
-;; and appropriate keys are presented for various kinds of entries.
-
-(provide 'bib-mode)
-
-(defvar bib-file "~/my-bibliography.bib"
- "Default name of file used by `addbib'.")
-
-(defvar unread-bib-file "~/to-be-read.bib"
- "Default name of file used by `unread-bib' in Bib mode.")
-
-(defvar bib-mode-map (copy-keymap text-mode-map))
-(define-key bib-mode-map "\C-M" 'return-key-bib)
-(define-key bib-mode-map "\C-c\C-u" 'unread-bib)
-(define-key bib-mode-map "\C-c\C-@" 'mark-bib)
-(define-key bib-mode-map "\e`" 'abbrev-mode)
-(defvar bib-mode-abbrev-table nil
- "Abbrev table used in Bib mode")
-
-(defun addbib ()
- "Set up editor to add to troff bibliography file specified
-by global variable `bib-file'. See description of `bib-mode'."
- (interactive)
- (find-file bib-file)
- (goto-char (point-max))
- (bib-mode)
- )
-
-(defun bib-mode ()
- "Mode for editing `lookbib' style bibliographies.
-Hit RETURN to get next % field key.
-If you want to ignore this field, just hit RETURN again.
-Use `text-mode' to turn this feature off.
-
- journal papers: A* T D J V N P K W X
- articles in books & proceedings: A* T D B E* I C P K W X
- tech reports: A* T D R I C K W X
- books: A* T D I C K W X
-
-Fields:
-
-A uthor T itle D ate J ournal
-V olume N umber P age K eywords
-B in book or proceedings E ditor C ity & state
-I nstitution, school, or publisher
-R eport number or 'phd thesis' or 'masters thesis' or 'draft' or
- 'unnumbered' or 'unpublished'
-W here can be found locally (login name, or ailib, etc.)
-X comments (not used in indexing)
-
-\\[unread-bib] appends current entry to a different file (for example,
-a file of papers to be read in the future), given by the value of the
-variable `unread-bib-file'.
-\\[mark-bib] marks current or previous entry.
-Abbreviations are saved in `bib-mode-abbrev-table'.
-Hook can be stored in `bib-mode-hook'.
-Field keys given by variable `bib-assoc'.
-
-Commands:
-\\{bib-mode-map}
-"
- (interactive)
- (text-mode)
- (use-local-map bib-mode-map)
- (setq mode-name "Bib")
- (setq major-mode 'bib-mode)
- (define-abbrev-table 'bib-mode-abbrev-table ())
- (setq local-abbrev-table bib-mode-abbrev-table)
- (abbrev-mode 1)
- (run-hooks 'bib-mode-hook)
- )
-
-(defconst bib-assoc '(
- (" *$" . "%A ")
- ("%A ." . "%A ")
- ("%A $" . "%T ")
- ("%T " . "%D ")
- ("%D " . "%J ")
- ("%J ." . "%V ")
- ("%V " . "%N ")
- ("%N " . "%P ")
- ("%P " . "%K ")
- ("%K " . "%W ")
- ("%W " . "%X ")
- ("%X " . "")
- ("%J $" . "%B ")
- ("%B ." . "%E ")
- ("%E ." . "%E ")
- ("%E $" . "%I ")
- ("%I " . "%C ")
- ("%C " . "%P ")
- ("%B $" . "%R ")
- ("%R " . "%I ")
- )
-
-"Describes bibliographic database format. A line beginning with
-the car of an entry is followed by one beginning with the cdr.
-")
-
-(defun bib-find-key (slots)
- (cond
- ((null slots)
- (if (bobp)
- ""
- (progn (previous-line 1) (bib-find-key bib-assoc))))
- ((looking-at (car (car slots)))
- (cdr (car slots)))
- (t (bib-find-key (cdr slots)))
- ))
-
-
-(defvar bib-auto-capitalize t
-"*True to automatically capitalize appropriate fields in Bib mode.")
-
-(defconst bib-capitalized-fields "%[AETCBIJR]")
-
-(defun return-key-bib ()
- "Magic when user hits return, used by `bib-mode'."
- (interactive)
- (if (eolp)
- (let (empty new-key beg-current end-current)
- (beginning-of-line)
- (setq empty (looking-at "%. $"))
- (if (not empty)
- (progn
- (end-of-line)
- (newline)
- (forward-line -1)
- ))
- (end-of-line)
- (setq end-current (point))
- (beginning-of-line)
- (setq beg-current (point))
- (setq new-key (bib-find-key bib-assoc))
- (if (and (not empty) bib-auto-capitalize
- (looking-at bib-capitalized-fields))
- (save-excursion
- (capitalize-title-region (+ (point) 3) end-current)))
- (goto-char beg-current)
- (if empty
- (kill-line nil)
- (forward-line 1)
- )
- (insert-string new-key))
- (newline)))
-
-(defun mark-bib ()
- "Set mark at beginning of current or previous bib entry, point at end."
- (interactive)
- (beginning-of-line nil)
- (if (looking-at "^ *$") (re-search-backward "[^ \n]" nil 2))
- (re-search-backward "^ *$" nil 2)
- (re-search-forward "^%")
- (beginning-of-line nil)
- (push-mark (point))
- (re-search-forward "^ *$" nil 2)
- (next-line 1)
- (beginning-of-line nil))
-
-(defun unread-bib ()
- "Append current or previous entry to file of unread papers
-named by variable `unread-bib-file'."
- (interactive)
- (mark-bib)
- (if (get-file-buffer unread-bib-file)
- (append-to-buffer (get-file-buffer unread-bib-file) (mark) (point))
- (append-to-file (mark) (point) unread-bib-file)))
-
-
-(defvar capitalize-title-stop-words
- (concat
- "the\\|and\\|of\\|is\\|a\\|an\\|of\\|for\\|in\\|to\\|in\\|on\\|at\\|"
- "by\\|with\\|that\\|its")
- "Words not to be capitialized in a title (unless they're the first word
-in the title).")
-
-(defvar capitalize-title-stop-regexp
- (concat "\\(" capitalize-title-stop-words "\\)\\(\\b\\|'\\)"))
-
-(defun capitalize-title-region (begin end)
- "Like `capitalize-region', but don't capitalize stop words, except the first."
- (interactive "r")
- (let ((case-fold-search nil) (orig-syntax-table (syntax-table)))
- (unwind-protect
- (save-restriction
- (set-syntax-table text-mode-syntax-table)
- (narrow-to-region begin end)
- (goto-char (point-min))
- (if (looking-at "[A-Z][a-z]*[A-Z]")
- (forward-word 1)
- (capitalize-word 1))
- (while (re-search-forward "\\<" nil t)
- (if (looking-at "[A-Z][a-z]*[A-Z]")
- (forward-word 1)
- (if (let ((case-fold-search t))
- (looking-at capitalize-title-stop-regexp))
- (downcase-word 1)
- (capitalize-word 1)))
- ))
- (set-syntax-table orig-syntax-table))))
-
-
-(defun capitalize-title (s)
- "Like `capitalize', but don't capitalize stop words, except the first."
- (save-excursion
- (set-buffer (get-buffer-create "$$$Scratch$$$"))
- (erase-buffer)
- (insert s)
- (capitalize-title-region (point-min) (point-max))
- (buffer-string)))
diff --git a/lisp/textmodes/fill.el b/lisp/textmodes/fill.el
deleted file mode 100644
index d7526a192b5..00000000000
--- a/lisp/textmodes/fill.el
+++ /dev/null
@@ -1,246 +0,0 @@
-;; Fill commands for Emacs
-;; Copyright (C) 1985, 1986 Free Software Foundation, Inc.
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 1, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
-
-(defun set-fill-prefix ()
- "Set the fill-prefix to the current line up to point.
-Filling expects lines to start with the fill prefix and
-reinserts the fill prefix in each resulting line."
- (interactive)
- (setq fill-prefix (buffer-substring
- (save-excursion (beginning-of-line) (point))
- (point)))
- (if (equal fill-prefix "")
- (setq fill-prefix nil))
- (if fill-prefix
- (message "fill-prefix: \"%s\"" fill-prefix)
- (message "fill-prefix cancelled")))
-
-(defconst adaptive-fill-mode t
- "*Non-nil means determine a paragraph's fill prefix from its text.")
-
-(defconst adaptive-fill-regexp "[ \t]*\\([>*] +\\)?"
- "*Regexp to match text at start of line that constitutes indentation.
-If Adaptive Fill mode is enabled, whatever text matches this pattern
-on the second line of a paragraph is used as the standard indentation
-for the paragraph.")
-
-(defun fill-region-as-paragraph (from to &optional justify-flag)
- "Fill region as one paragraph: break lines to fit fill-column.
-Prefix arg means justify too.
-From program, pass args FROM, TO and JUSTIFY-FLAG."
- (interactive "r\nP")
- ;; Don't let Adaptive Fill mode alter the fill prefix permanently.
- (let ((fill-prefix fill-prefix))
- ;; Figure out how this paragraph is indented, if desired.
- (if adaptive-fill-mode
- (save-excursion
- (goto-char (min from to))
- (if (eolp) (forward-line 1))
- (forward-line 1)
- (if (< (point) (max from to))
- (let ((start (point)))
- (re-search-forward adaptive-fill-regexp)
- (setq fill-prefix (buffer-substring start (point))))
- (goto-char (min from to))
- (if (eolp) (forward-line 1))
- ;; If paragraph has only one line, don't assume
- ;; that additional lines would have the same starting
- ;; decoration. Instead, assume they would have white space
- ;; reaching to the same column.
- (re-search-forward adaptive-fill-regexp)
- (setq fill-prefix (make-string (current-column) ?\ )))))
-
- (save-restriction
- (narrow-to-region from to)
- (goto-char (point-min))
- (skip-chars-forward "\n")
- (narrow-to-region (point) (point-max))
- (setq from (point))
- (goto-char (point-max))
- (let ((fpre (and fill-prefix (not (equal fill-prefix ""))
- (regexp-quote fill-prefix))))
- ;; Delete the fill prefix from every line except the first.
- ;; The first line may not even have a fill prefix.
- (and fpre
- (progn
- (if (>= (length fill-prefix) fill-column)
- (error "fill-prefix too long for specified width"))
- (goto-char (point-min))
- (forward-line 1)
- (while (not (eobp))
- (if (looking-at fpre)
- (delete-region (point) (match-end 0)))
- (forward-line 1))
- (goto-char (point-min))
- (and (looking-at fpre) (forward-char (length fill-prefix)))
- (setq from (point)))))
- ;; from is now before the text to fill,
- ;; but after any fill prefix on the first line.
-
- ;; Make sure sentences ending at end of line get an extra space.
- ;; loses on split abbrevs ("Mr.\nSmith")
- (goto-char from)
- (while (re-search-forward "[.?!][])\"']*$" nil t)
- (insert ? ))
-
- ;; Then change all newlines to spaces.
- (subst-char-in-region from (point-max) ?\n ?\ )
-
- ;; Flush excess spaces, except in the paragraph indentation.
- (goto-char from)
- (skip-chars-forward " \t")
- ;; nuke tabs while we're at it; they get screwed up in a fill
- ;; this is quick, but loses when a sole tab follows the end of a sentence.
- ;; actually, it is difficult to tell that from "Mr.\tSmith".
- ;; blame the typist.
- (subst-char-in-region (point) (point-max) ?\t ?\ )
- (while (re-search-forward " *" nil t)
- (delete-region
- (+ (match-beginning 0)
- (if (save-excursion
- (skip-chars-backward " ])\"'")
- (memq (preceding-char) '(?. ?? ?!)))
- 2 1))
- (match-end 0)))
- (goto-char (point-max))
- (delete-horizontal-space)
- (insert " ")
- (goto-char (point-min))
-
- (let ((prefixcol 0))
- (while (not (eobp))
- (move-to-column (1+ fill-column))
- (if (eobp)
- nil
- (skip-chars-backward "^ \n")
- (if (if (zerop prefixcol) (bolp) (>= prefixcol (current-column)))
- (skip-chars-forward "^ \n")
- (forward-char -1)))
- ;; Inserting the newline first prevents losing track of point.
- (skip-chars-backward " ")
- (insert ?\n)
- (delete-horizontal-space)
- (and (not (eobp)) fill-prefix (not (equal fill-prefix ""))
- (progn
- (insert fill-prefix)
- (setq prefixcol (current-column))))
- (and justify-flag (not (eobp))
- (progn
- (forward-line -1)
- (justify-current-line)
- (forward-line 1))))))))
-
-(defun fill-paragraph (arg)
- "Fill paragraph at or after point. Prefix arg means justify as well."
- (interactive "P")
- (save-excursion
- (forward-paragraph)
- (or (bolp) (newline 1))
- (let ((end (point)))
- (backward-paragraph)
- (fill-region-as-paragraph (point) end arg))))
-
-(defun fill-region (from to &optional justify-flag)
- "Fill each of the paragraphs in the region.
-Prefix arg (non-nil third arg, if called from program) means justify as well."
- (interactive "r\nP")
- (save-restriction
- (narrow-to-region from to)
- (goto-char (point-min))
- (while (not (eobp))
- (let ((initial (point))
- (end (progn
- (forward-paragraph 1) (point))))
- (forward-paragraph -1)
- (if (>= (point) initial)
- (fill-region-as-paragraph (point) end justify-flag)
- (goto-char end))))))
-
-(defun justify-current-line ()
- "Add spaces to line point is in, so it ends at `fill-column'."
- (interactive)
- (save-excursion
- (save-restriction
- (let (ncols beg indent)
- (beginning-of-line)
- (forward-char (length fill-prefix))
- (skip-chars-forward " \t")
- (setq indent (current-column))
- (setq beg (point))
- (end-of-line)
- (narrow-to-region beg (point))
- (goto-char beg)
- (while (re-search-forward " *" nil t)
- (delete-region
- (+ (match-beginning 0)
- (if (save-excursion
- (skip-chars-backward " ])\"'")
- (memq (preceding-char) '(?. ?? ?!)))
- 2 1))
- (match-end 0)))
- (goto-char beg)
- (while (re-search-forward "[.?!][])""']*\n" nil t)
- (forward-char -1)
- (insert ? ))
- (goto-char (point-max))
- ;; Note that the buffer bounds start after the indentation,
- ;; so the columns counted by INDENT don't appear in (current-column).
- (setq ncols (- fill-column (current-column) indent))
- (if (search-backward " " nil t)
- (while (> ncols 0)
- (let ((nmove (+ 3 (random 3))))
- (while (> nmove 0)
- (or (search-backward " " nil t)
- (progn
- (goto-char (point-max))
- (search-backward " ")))
- (skip-chars-backward " ")
- (setq nmove (1- nmove))))
- (insert " ")
- (skip-chars-backward " ")
- (setq ncols (1- ncols))))))))
-
-(defun fill-individual-paragraphs (min max &optional justifyp mailp)
- "Fill each paragraph in region according to its individual fill prefix.
-Calling from a program, pass range to fill as first two arguments.
-Optional third and fourth arguments JUSTIFY-FLAG and MAIL-FLAG:
-JUSTIFY-FLAG to justify paragraphs (prefix arg),
-MAIL-FLAG for a mail message, i. e. don't fill header lines."
- (interactive "r\nP")
- (let (fill-prefix)
- (save-restriction
- (save-excursion
- (goto-char min)
- (if mailp
- (while (looking-at "[^ \t\n]*:")
- (forward-line 1)))
- (narrow-to-region (point) max)
- (while (progn
- (skip-chars-forward " \t\n")
- (not (eobp)))
- (setq fill-prefix
- (buffer-substring (point) (progn (beginning-of-line) (point))))
- (let ((fin (save-excursion (forward-paragraph) (point)))
- (start (point)))
- (fill-region-as-paragraph (point) fin justifyp)
- (goto-char start)
- (forward-paragraph)))))))
-
-
diff --git a/lisp/textmodes/ispell4.el b/lisp/textmodes/ispell4.el
deleted file mode 100644
index 782ea43103c..00000000000
--- a/lisp/textmodes/ispell4.el
+++ /dev/null
@@ -1,541 +0,0 @@
-;;This is the GNU EMACS interface to GNU ISPELL version 3.
-;; Copyright (C) 1990 Free Software Foundation, Inc.
-;;
-;;This file is part of GNU ISPELL.
-;;
-;;GNU ISPELL 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 1, or (at your option)
-;;any later version.
-;;
-;;GNU ISPELL is distributed in the hope that it will be useful,
-;;but WITHOUT ANY WARRANTY; without even the implied warranty of
-;;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;;GNU General Public License for more details.
-;;
-;;You should have received a copy of the GNU General Public License
-;;along with GNU ISPELL; see the file COPYING. If not, write to
-;;the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
-(defvar ispell-have-new-look t
- "T if default 'look' program has the -r flag.")
-
-(defvar ispell-enable-tex-parser nil
- "T to enable experimental tex parser in ispell for tex buffers.")
-
-(defvar ispell-process nil "The process running ISPELL")
-(defvar ispell-next-message nil
- "An integer telling where in the *ispell* buffer where
-to look for the next message from the ISPELL program.")
-
-;Each marker in this list points to the start of a word that
-;ispell thought was bad last time it did the :file command.
-;Notice that if the user accepts or inserts a word into his
-;private dictionary, then some "good" words will be on the list.
-;We would like to deal with this by looking up the words again just before
-;presenting them to the user, but that is too slow on machines
-;without the select system call. Therefore, see the variable
-;ispell-recently-accepted.
-(defvar ispell-bad-words nil
- "A list of markers corresponding to the output of the ISPELL :file command.")
-
-;list of words that the user has accepted, but that might still
-;be on the bad-words list
-(defvar ispell-recently-accepted nil)
-
-;t when :dump command needed
-(defvar ispell-dump-needed nil)
-
-(defun ispell-flush-bad-words ()
- (while ispell-bad-words
- (if (markerp (car ispell-bad-words))
- (set-marker (car ispell-bad-words) nil))
- (setq ispell-bad-words (cdr ispell-bad-words)))
- (setq ispell-recently-accepted nil))
-
-(defun kill-ispell ()
- "Kill the ispell process.
-Any changes the your private dictionay
-that have not already been dumped will be lost."
- (interactive)
- (if ispell-process
- (delete-process ispell-process))
- (setq ispell-process nil)
- (ispell-flush-bad-words))
-
-(put 'ispell-startup-error 'error-conditions
- '(ispell-startup-error error))
-(put 'ispell-startup-error 'error-message
- "Problem starting ispell - see buffer *ispell*")
-
-(defun start-ispell ()
- "Start an ispell subprocess; check the version; and display the greeting."
- (message "Starting ispell ...")
- (let ((buf (get-buffer "*ispell*")))
- (if buf
- (kill-buffer buf)))
- (condition-case err
- (setq ispell-process (start-process "ispell" "*ispell*" "ispell" "-S"))
- (file-error (signal 'ispell-startup-error nil)))
- (process-kill-without-query ispell-process)
- (buffer-disable-undo (process-buffer ispell-process))
- (accept-process-output ispell-process)
- (let (last-char)
- (save-excursion
- (set-buffer (process-buffer ispell-process))
- (bury-buffer (current-buffer))
- (setq last-char (- (point-max) 1))
- (while (not (eq (char-after last-char) ?=))
- (cond ((not (eq (process-status ispell-process) 'run))
- (kill-ispell)
- (signal 'ispell-startup-error nil)))
- (accept-process-output ispell-process)
- (setq last-char (- (point-max) 1)))
- (goto-char (point-min))
- (let ((greeting (read (current-buffer))))
- (if (not (= (car greeting) 1))
- (error "Bad ispell version: wanted 1, got %d" (car greeting)))
- (message (car (cdr greeting))))
- (delete-region (point-min) last-char))))
-
-;leaves buffer set to *ispell*, point at '='
-(defun ispell-sync (intr)
- "Make sure ispell is ready for a command."
- (if (or (null ispell-process)
- (not (eq (process-status ispell-process) 'run)))
- (start-ispell))
- (if intr
- (interrupt-process ispell-process))
- (let (last-char)
- (set-buffer (process-buffer ispell-process))
- (bury-buffer (current-buffer))
- (setq last-char (- (point-max) 1))
- (while (not (eq (char-after last-char) ?=))
- (accept-process-output ispell-process)
- (setq last-char (- (point-max) 1)))
- (goto-char last-char)))
-
-(defun ispell-cmd (&rest strings)
- "Send a command to ispell. Choices are:
-
-word any word is checked for spelling. Result is
-
- nil not found
- t spelled ok
- list of strings near misses
-
-:file filename scan the named file, and print the file offsets of
- any misspelled words
-
-:insert word put word in private dictonary
-
-:accept word don't complain about word any more this session
-
-:dump write out the current private dictionary, if necessary.
-
-:reload reread ~/ispell.words
-
-:tex
-:troff
-:generic set type of parser to use when scanning whole files
-"
- (save-excursion
- (ispell-sync t)
- (set-buffer (process-buffer ispell-process))
- (bury-buffer (current-buffer))
- (erase-buffer)
- (setq ispell-next-message (point-min))
- (while strings
- (process-send-string ispell-process (car strings))
- (setq strings (cdr strings)))
- (process-send-string ispell-process "\n")
- (accept-process-output ispell-process)
- (ispell-sync nil)))
-
-(defun ispell-dump ()
- (cond (ispell-dump-needed
- (setq ispell-dump-needed nil)
- (ispell-cmd ":dump"))))
-
-(defun ispell-insert (word)
- (ispell-cmd ":insert " word)
- (if ispell-bad-words
- (setq ispell-recently-accepted (cons word ispell-recently-accepted)))
- (setq ispell-dump-needed t))
-
-(defun ispell-accept (word)
- (ispell-cmd ":accept " word)
- (if ispell-bad-words
- (setq ispell-recently-accepted (cons word ispell-recently-accepted))))
-
-
-(defun ispell-next-message ()
- "Return the next message sent by the ispell subprocess."
- (save-excursion
- (set-buffer (process-buffer ispell-process))
- (bury-buffer (current-buffer))
- (save-restriction
- (goto-char ispell-next-message)
- (narrow-to-region (point)
- (progn (forward-sexp 1) (point)))
- (setq ispell-next-message (point))
- (goto-char (point-min))
- (read (current-buffer)))))
-
-(defun ispell-tex-buffer-p ()
- (memq major-mode '(plain-TeX-mode LaTeX-mode)))
-
-(defun ispell (&optional buf start end)
- "Run ispell over current buffer's visited file.
-First the file is scanned for misspelled words, then ispell
-enters a loop with the following commands for every misspelled word:
-
-DIGIT Near miss selector. If the misspelled word is close to
- some words in the dictionary, they are offered as near misses.
-r Replace. Replace the word with a string you type. Each word
- of your new string is also checked.
-i Insert. Insert this word in your private dictonary (kept in
- `$HOME/ispell.words').
-a Accept. Accept this word for the rest of this editing session,
- but don't put it in your private dictonary.
-l Lookup. Look for a word in the dictionary by fast binary
- search, or search for a regular expression in the dictionary
- using grep.
-SPACE Accept the word this time, but complain if it is seen again.
-q, \\[keyboard-quit] Leave the command loop. You can come back later with \\[ispell-next]."
- (interactive)
- (if (null start)
- (setq start 0))
- (if (null end)
- (setq end 0))
-
- (if (null buf)
- (setq buf (current-buffer)))
- (setq buf (get-buffer buf))
- (if (null buf)
- (error "Can't find buffer"))
- (save-excursion
- (set-buffer buf)
- (let ((filename buffer-file-name)
- (delete-temp nil))
- (unwind-protect
- (progn
- (cond ((null filename)
- (setq filename (make-temp-name "/usr/tmp/ispell"))
- (setq delete-temp t)
- (write-region (point-min) (point-max) filename))
- ((and (buffer-modified-p buf)
- (y-or-n-p (format "Save file %s? " filename)))
- (save-buffer)))
- (message "Ispell scanning file...")
- (if (and ispell-enable-tex-parser
- (ispell-tex-buffer-p))
- (ispell-cmd ":tex")
- (ispell-cmd ":generic"))
- (ispell-cmd (format ":file %s %d %d" filename start end)))
- (if delete-temp
- (condition-case ()
- (delete-file filename)
- (file-error nil)))))
- (message "Parsing ispell output ...")
- (ispell-flush-bad-words)
- (let (pos bad-words)
- (while (numberp (setq pos (ispell-next-message)))
- ;;ispell may check the words on the line following the end
- ;;of the region - therefore, don't record anything out of range
- (if (or (= end 0)
- (< pos end))
- (setq bad-words (cons (set-marker (make-marker) (+ pos 1))
- bad-words))))
- (setq bad-words (cons pos bad-words))
- (setq ispell-bad-words (nreverse bad-words))))
- (cond ((not (markerp (car ispell-bad-words)))
- (setq ispell-bad-words nil)
- (message "No misspellings."))
- (t
- (message "Ispell parsing done.")
- (ispell-next))))
-
-(defun ispell-next ()
- "Resume command loop for most recent ispell command."
- (interactive)
- (unwind-protect
- (catch 'quit
- (save-window-excursion
- (save-excursion
- (let (next)
- (while (markerp (setq next (car ispell-bad-words)))
- (switch-to-buffer (marker-buffer next))
- (push-mark)
- (ispell-point next "at saved position.")
- (setq ispell-bad-words (cdr ispell-bad-words))
- (set-marker next nil))))))
- (cond ((null ispell-bad-words)
- (error "Ispell has not yet been run."))
- ((markerp (car ispell-bad-words))
- (message (substitute-command-keys
- "Type \\[ispell-next] to continue.")))
- ((eq (car ispell-bad-words) nil)
- (setq ispell-bad-words nil)
- (message "No more misspellings (but checker was interrupted.)"))
- ((eq (car ispell-bad-words) t)
- (setq ispell-bad-words nil)
- (message "Ispell done."))
- (t
- (setq ispell-bad-words nil)
- (message "Bad ispell internal list"))))
- (ispell-dump))
-
-
-(defun ispell-word ()
- "Check the spelling of the word under the cursor.
-See `ispell' for more information."
- (interactive)
- (condition-case err
- (catch 'quit
- (save-window-excursion
- (ispell-point (point) "at point."))
- (ispell-dump))
- (ispell-startup-error
- (cond ((y-or-n-p "Problem starting ispell, use old-style spell instead? ")
- (load-library "spell")
- (define-key esc-map "$" 'spell-word)
- (spell-word))))))
-
-(defun ispell-region (start &optional end)
- "Check the spelling for all of the words in the region."
- (interactive "r")
- (ispell (current-buffer) start end))
-
-(defun ispell-letterp (c)
- (and c
- (or (and (>= c ?A) (<= c ?Z))
- (and (>= c ?a) (<= c ?z))
- (>= c 128))))
-
-(defun ispell-letter-or-quotep (c)
- (and c
- (or (and (>= c ?A) (<= c ?Z))
- (and (>= c ?a) (<= c ?z))
- (= c ?')
- (>= c 128))))
-
-(defun ispell-find-word-start ()
- ;;backward to a letter
- (if (not (ispell-letterp (char-after (point))))
- (while (and (not (bobp))
- (not (ispell-letterp (char-after (- (point) 1)))))
- (backward-char)))
- ;;backward to beginning of word
- (while (ispell-letter-or-quotep (char-after (- (point) 1)))
- (backward-char))
- (skip-chars-forward "'"))
-
-(defun ispell-find-word-end ()
- (while (ispell-letter-or-quotep (char-after (point)))
- (forward-char))
- (skip-chars-backward "'"))
-
-(defun ispell-next-word ()
- (while (and (not (eobp))
- (not (ispell-letterp (char-after (point)))))
- (forward-char)))
-
-;if end is nil, then do one word at start
-;otherwise, do all words from the beginning of the word where
-;start points, to the end of the word where end points
-(defun ispell-point (start message)
- (let ((wend (make-marker))
- rescan
- end)
- (save-excursion
- (goto-char start)
- (ispell-find-word-start) ;find correct word start
- (setq start (point-marker))
- (ispell-find-word-end) ;now find correct end
- (setq end (point-marker))
- (if (>= start end)
- (error "No word %s" message))
- (while (< start end)
- (goto-char start)
- (ispell-find-word-end) ;find end of current word
- ;could be before 'end' if
- ;user typed replacement
- ;that is more than one word
- (set-marker wend (point))
- (setq rescan nil)
- (setq word (buffer-substring start wend))
- (cond ((ispell-still-bad word)
- (goto-char start);just to show user where we are working
- (sit-for 0)
- (message (format "Ispell checking %s" word))
- (ispell-cmd word)
- (let ((message (ispell-next-message)))
- (cond ((eq message t)
- (message "%s: ok" word))
- ((or (null message)
- (consp message))
- (setq rescan
- (ispell-command-loop word start wend message)))
- (t
- (error "unknown ispell response %s" message))))))
- (cond ((null rescan)
- (goto-char wend)
- (ispell-next-word)
- (set-marker start (point)))))
- ;;clear the choices buffer; otherwise it's hard for the user to tell
- ;;when we get back to the command loop
- (let ((buf (get-buffer "*ispell choices*")))
- (cond (buf
- (set-buffer buf)
- (erase-buffer))))
- (set-marker start nil)
- (set-marker end nil)
- (set-marker wend nil))))
-
-(defun ispell-still-bad (word)
- (let ((words ispell-recently-accepted)
- (ret t)
- (case-fold-search t))
- (while words
- (cond ((eq (string-match (car words) word) 0)
- (setq ret nil)
- (setq words nil)))
- (setq words (cdr words)))
- ret))
-
-(defun ispell-show-choices (word message first-line)
- ;;if there is only one window on the screen, make the ispell
- ;;messages winow be small. otherwise just use the other window
- (let* ((selwin (selected-window))
- (resize (eq selwin (next-window)))
- (buf (get-buffer-create "*ispell choices*"))
- w)
- (setq w (display-buffer buf))
- (buffer-disable-undo buf)
- (if resize
- (unwind-protect
- (progn
- (select-window w)
- (enlarge-window (- 6 (window-height w))))
- (select-window selwin)))
- (save-excursion
- (set-buffer buf)
- (bury-buffer buf)
- (set-window-point w (point-min))
- (set-window-start w (point-min))
- (erase-buffer)
- (insert first-line "\n")
- (insert
- "SPC skip; A accept; I insert; DIGIT select; R replace; \
-L lookup; Q quit\n")
- (cond ((not (null message))
- (let ((i 0))
- (while (< i 3)
- (let ((j 0))
- (while (< j 3)
- (let* ((n (+ (* j 3) i))
- (choice (nth n message)))
- (cond (choice
- (let ((str (format "%d %s" n choice)))
- (insert str)
- (insert-char ? (- 20 (length str)))))))
- (setq j (+ j 1))))
- (insert "\n")
- (setq i (+ i 1)))))))))
-
-(defun ispell-command-loop (word start end message)
- (let ((flag t)
- (rescan nil)
- first-line)
- (if (null message)
- (setq first-line (concat "No near misses for '" word "'"))
- (setq first-line (concat "Near misses for '" word "'")))
- (while flag
- (ispell-show-choices word message first-line)
- (message "Ispell command: ")
- (let ((c (downcase (read-char)))
- replacement)
- (cond ((and (>= c ?0)
- (<= c ?9)
- (setq replacement (nth (- c ?0) message)))
- (ispell-replace start end replacement)
- (setq flag nil))
- ((= c ?q)
- (throw 'quit nil))
- ((= c ? )
- (setq flag nil))
- ((= c ?r)
- (ispell-replace start end (read-string "Replacement: "))
- (setq rescan t)
- (setq flag nil))
- ((= c ?i)
- (ispell-insert word)
- (setq flag nil))
- ((= c ?a)
- (ispell-accept word)
- (setq flag nil))
- ((= c ?l)
- (let ((val (ispell-do-look word)))
- (setq first-line (car val))
- (setq message (cdr val))))
- ((= c ??)
- (message
- "Type 'C-h d ispell' to the emacs main loop for more help")
- (sit-for 2))
- (t
- (message "Bad ispell command")
- (sit-for 2)))))
- rescan))
-
-(defun ispell-do-look (bad-word)
- (let (regex buf words)
- (cond ((null ispell-have-new-look)
- (setq regex (read-string "Lookup: ")))
- (t
- (setq regex (read-string "Lookup (regex): " "^"))))
- (setq buf (get-buffer-create "*ispell look*"))
- (save-excursion
- (set-buffer buf)
- (delete-region (point-min) (point-max))
- (if ispell-have-new-look
- (call-process "look" nil buf nil "-r" regex)
- (call-process "look" nil buf nil regex))
- (goto-char (point-min))
- (forward-line 10)
- (delete-region (point) (point-max))
- (goto-char (point-min))
- (while (not (= (point-min) (point-max)))
- (end-of-line)
- (setq words (cons (buffer-substring (point-min) (point)) words))
- (forward-line)
- (delete-region (point-min) (point)))
- (kill-buffer buf)
- (cons (format "Lookup '%s'" regex)
- (reverse words)))))
-
-(defun ispell-replace (start end new)
- (goto-char start)
- (insert new)
- (delete-region (point) end))
-
-(defun reload-ispell ()
- "Tell ispell to re-read your private dictionary."
- (interactive)
- (ispell-cmd ":reload"))
-
-(define-key esc-map "$" 'ispell-word)
-;; This conflicts with set-selective-display. What should we do???
-;;(define-key ctl-x-map "$" 'ispell-next)
-
-(defun batch-make-ispell ()
- (byte-compile-file "ispell.el")
- (find-file "ispell.texinfo")
- (let ((old-dir default-directory)
- (default-directory "/tmp"))
- (texinfo-format-buffer))
- (Info-validate)
- (if (get-buffer " *problems in info file*")
- (kill-emacs 1))
- (write-region (point-min) (point-max) "ispell.info"))
-
diff --git a/lisp/textmodes/page-ext.el b/lisp/textmodes/page-ext.el
deleted file mode 100644
index c17fa187551..00000000000
--- a/lisp/textmodes/page-ext.el
+++ /dev/null
@@ -1,745 +0,0 @@
-;;;; page-ext.el
-
-;;; Page handling commands
-;;; by Robert J. Chassell
-
-;;; You may use these commands to handle an address list or other
-;;; small data base.
-
-;;; Copyright (C) 1990 Free Software Foundation
-;;; Please send bug reports to bob@ai.mit.edu
-
-;;; Change Log ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;;
-;;; Version 0.043
-;;; 24 May 1990 - When the cursor is at the end of the pages directory
-;;; buffer (which is empty), a `C-c C-c' (pages-directory-goto)
-;;; command now takes you to the end of the buffer.
-;;;
-;;; Version 0.042
-;;; 16 May 1990 - Since people often handle address and other files
-;;; differently, variable `pages-directory-for-addresses-narrowing-p'
-;;; now specifies whether `pages-directory-goto' should narrow
-;;; addresses buffer to entry to which it goes.
-;;; `pages-directory-buffer-narrowing-p' continues to control
-;;; narrowing of pages buffer.
-;;;
-;;; `add-new-page' documentation string now explains
-;;; that the value of the inserted page-delimiter is a `^L'.
-;;;
-;;; `pages-directory-previous-regexp' definition reworded.
-;;;
-;;; Removed unneeded defvar for `pages-directory-buffer'.
-;;;
-;;; Version 0.041
-;;; 14 May 1990 - `pages-last-search' bound to nil initially.
-;;; Remove unnecessary lines from `search-pages' definition.
-;;;
-;;; Version 0.04
-;;; 18 Mar 1990 - `pages-directory' creates a directory for only the
-;;; accessible portion of the buffer; it does not automatically widen
-;;; the buffer.
-;;;
-;;; However, `pages-directory-for-addresses' does widen the addresses'
-;;; buffer before constructing the addresses' directory.
-;;;
-;;; Version 0.032
-;;; 20 Feb 1990 - `pages-directory-for-addresses' no longer copies
-;;; first line of addresses directory to kill-ring
-;;;
-;;; Remove `(kill-all-local-variables)' line from
-;;; `pages-directory-address-mode' so Emacs will not be told to forget
-;;; the name of the file containing the addresses!
-;;;
-;;; Version 0.031
-;;; 15 Feb 1990 - `pages-directory-goto' no longer erroneously selects
-;;; the entry on the following line when the cursor is at the end of
-;;; the line, but selects the entry on which the cursor rests.
-;;;
-;;; `pages-directory-address-mode' now sets local variables and enables
-;;; `describe-mode' to describe Addresses Directory mode.
-;;;
-;;; `pages-directory-for-addresses' now sets the buffer-modifed flag
-;;; for the Addresses Directory to nil.
-;;;
-;;; The documentation string for both `pages-directory-mode' and
-;;; `pages-directory-address-mode' now provide a lookup for the
-;;; `pages-directory-goto' keybinding.
-;;;
-;;; Version 0.03
-;;; 10 Feb 1990 - Incorporated a specialized extension of the
-;;; `pages-directory' command called `pages-directory-for-addresses'
-;;; and bound it to ctl-x-ctl-p-map "d" for integration with other
-;;; page functions. This function finds a file, creates a directory
-;;; for it using the `pages-directory' command, and displays the
-;;; directory. It is primarily for lists of addresses and the like.
-;;;
-;;; The difference between this and the `pages-directory' command is
-;;; that the `pages-directory-for-addresses' command presumes a
-;;; default addresses file (although you may optionally specify a file
-;;; name) and it switches you to the directory for the file, but the
-;;; `pages-directory' command creates a directory for the current
-;;; buffer, and pops to the directory in another window.
-;;;
-;;; `pages-directory' now places the cursor over the header line of
-;;; the page in which point was located in the pages buffer.
-;;;
-;;; New `set-page-delimiter' command sets the buffer local value of
-;;; the page-delimiter variable. With prefix arg, resets function to
-;;; original value. (Quicker to use than `edit-options'.)
-;;;
-;;; Version 0.02
-;;; 9 Feb 1990 - `pages-directory' now displays the
-;;; first line that contains a non-blank character that follows the
-;;; `page-delimiter'; this may be the rest of the line that contains
-;;; the `page-delimiter' or a line following. (In most instances, the
-;;; line containing a non-blank character is a line of text.)
-;;; Modification includes changes to `pages-copy-header-and-position'.
-;;;
-;;; Each directory created by `pages-directory' now possesses a name
-;;; derived on the name of the pages buffer. Consequently, you may
-;;; create several different directories, one for each pages buffer.
-;;;
-;;; `sort-pages-in-region' no longers requires the text to start on
-;;; the line immediately following the line containing the
-;;; page-delimiter.
-;;;
-;;; `pages-directory-goto' no longer narrows to the page
-;;; automatically. Instead, if you wish it to narrow to the page, set
-;;; variable pages-directory-buffer-narrowing-p to a non-nil value.
-;;; Default is nil; this is an experiment to see whether it is useful
-;;; to see the surrounding context.
-;;;
-;;; Version 0.011
-;;; 2 Feb 1990 - `add-new-page': removed extraneous space.
-;;;
-;;; Version 0.01
-;;; 28 Jan 1990 - Initial definitions.
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-
-;;;; Summary
-
-; The current page commands are:
-
-; forward-page C-x ]
-; backward-page C-x [
-; narrow-to-page C-x p
-; count-lines-page C-x l
-; mark-page C-x C-p (change this to C-x C-p C-m)
-; sort-pages not bound
-; what-page not bound
-
-; The new page handling commands all use `C-x C-p' as a prefix. This
-; means that the key binding for `mark-page' must be changed.
-; Otherwise, no other changes are made to the current commands or
-; their bindings.
-
-; New page handling commands:
-
-; next-page C-x C-p C-n
-; previous-page C-x C-p C-p
-; search-pages C-x C-p C-s
-; add-new-page C-x C-p C-a
-; sort-pages-buffer C-x C-p s
-; set-page-delimiter C-x C-p C-l
-; pages-directory C-x C-p C-d
-; pages-directory-for-addresses C-x C-p d
-; goto-page C-c C-c
-
-
-;;;; Using the page commands
-;
-; The page commands are helpful in several different contexts. For
-; example, programmers often divide source files into sections using the
-; `page-delimiter'; you can use the `pages-directory' command to list
-; the sections.
-
-; You may change the buffer local value of the `page-delimiter' with
-; the `set-page-delimiter' command. This command is bound to `C-x C-p
-; C-l' The command prompts you for a new value for the page-delimiter.
-; Called with a prefix-arg, the command resets the value of the
-; page-delimiter to its original value.
-
-
-;;;; Handling an address list or small data base
-
-; You may use the page commands to handle an address list or other
-; small data base. Put each address or entry on its own page. The
-; first line of text in each page is a `header line' and is listed by
-; the `pages-directory' or `pages-directory-for-addresses' command.
-
-; Specifically:
-;
-; 1. Begin each entry with a `page-delimiter' (which is, by default,
-; `^L' at the beginning of the line).
-;
-; 2. The first line of text in each entry is the `heading line'; it
-; will appear in the pages-directory-buffer which is constructed
-; using the `C-x C-p C-d' (pages-directory) command or the `C-x
-; C-p d' (pages-directory-for-addresses) command.
-;
-; The heading line may be on the same line as the page-delimiter
-; or it may follow after. It is the first non-blank line on the
-; page. Conventionally, the heading line is placed on the line
-; immediately following the line containing page-delimiter.
-;
-; 3. Follow the heading line with the body of the entry. The body
-; extends up to the next `page-delimiter'. The body may be of any
-; length. It is conventional to place a blank line after the last
-; line of the body.
-
-; For example, a file might look like this:
-;
-; FSF
-; Free Software Foundation
-; 675 Massachusetts Avenue
-; Cambridge, MA 02139 USA
-; (617) 876-3296
-; gnu@prep.ai.mit.edu
-;
-;
-; House Subcommittee on Intellectual Property,
-; U.S. House of Representatives,
-; Washington, DC 20515
-;
-; Congressional committee concerned with permitting or preventing
-; monopolistic restictions on the use of software technology
-;
-;
-; George Lakoff
-; ``Women, Fire, and Dangerous Things:
-; What Categories Reveal about the Mind''
-; 1987, Univ. of Chicago Press
-;
-; About philosophy, Whorfian effects, and linguistics.
-;
-;
-; OBI (On line text collection.)
-; Open Book Initiative
-; c/o Software Tool & Die
-; 1330 Beacon St, Brookline, MA 02146 USA
-; (617) 739-0202
-; obi@world.std.com
-
-; In this example, the heading lines are:
-;
-; FSF
-; House Subcommittee on Intellectual Property
-; George Lakoff
-; OBI (On line text collection.)
-
-; The `C-x C-p s' (sort-pages-buffer) command sorts the entries in the
-; buffer alphabetically.
-
-; You may use any of the page commands, including the `next-page',
-; `previous-page', `add-new-page', `mark-page', and `search-pages'
-; commands.
-
-; You may use either the `C-x C-p d' (pages-directory-for-addresses)
-; or the `C-x C-p C-d' (pages-directory) command to construct and
-; dislay a directory of all the heading lines.
-
-; In the directory, you may position the cursor over a heading line
-; and type `C-c C-c' to go to the entry to which it refers in the
-; pages buffer.
-
-; When used in conjunction with the `pages-directory-for-addresses'
-; command, the `C-c C-c' (pages-directory-goto) command narrows to the
-; entry to which it goes. But, when used in conjunction with the
-; `pages-directory' command, the `C-c C-c' (pages-directory-goto)
-; command does not narrow to the entry, but widens the buffer so you
-; can see the context surrounding the entry.
-
-; If you wish, you may create several different directories,
-; one for each different buffer.
-
-;; `pages-directory-for-addresses' in detail
-
-; The `pages-directory-for-addresses' assumes a default addresses
-; file. You do not need to specify the addresses file but merely type
-; `C-x C-p d' from any buffer. The command finds the file, constructs
-; a directory for it, and switches you to the directory. If you call
-; the command with a prefix arg, `C-u C-x C-p d', it prompts you for a
-; file name.
-
-;; `pages-directory' in detail
-
-; Call the `pages-directory' from the buffer for which you want a
-; directory created; it creates a directory for the buffer and pops
-; you to the directory.
-
-; The `pages-directory' command has several options:
-
-; Called with a prefix arg, `C-u C-x C-p C-d', the `pages-directory'
-; prompts you for a regular expression and only lists only those
-; header lines that are part of pages that contain matches to the
-; regexp. In the example above, `C-u C-x C-p C-d 617 RET' would
-; match the telephone area code of the first and fourth entries, so
-; only the header lines of those two entries would appear in the
-; pages-directory-buffer.
-;
-; Called with a numeric argument, the `pages-directory' command
-; lists the number of lines in each page. This is helpful when you
-; are printing hardcopy.
-
-; Called with a negative numeric argument, the `pages-directory'
-; command lists the lengths of pages whose contents match a regexp.
-
-
-;;;; Key bindings for page handling functions
-
-(global-unset-key "\C-x\C-p")
-
-(defvar ctl-x-ctl-p-map (make-sparse-keymap)
- "Keymap for subcommands of C-x C-p, which are for page handling.")
-
-(define-key ctl-x-map "\C-p" 'ctl-x-ctl-p-prefix)
-(fset 'ctl-x-ctl-p-prefix ctl-x-ctl-p-map)
-
-(define-key ctl-x-ctl-p-map "\C-n" 'next-page)
-(define-key ctl-x-ctl-p-map "\C-p" 'previous-page)
-(define-key ctl-x-ctl-p-map "\C-a" 'add-new-page)
-(define-key ctl-x-ctl-p-map "\C-m" 'mark-page)
-(define-key ctl-x-ctl-p-map "\C-s" 'search-pages)
-(define-key ctl-x-ctl-p-map "s" 'sort-pages-buffer)
-(define-key ctl-x-ctl-p-map "\C-l" 'set-page-delimiter)
-(define-key ctl-x-ctl-p-map "\C-d" 'pages-directory)
-(define-key ctl-x-ctl-p-map "d" 'pages-directory-for-addresses)
-
-
-;;;; Page movement function definitions
-
-(defun next-page (&optional count)
- "Move to the next page bounded by the `page-delimiter' variable.
-With arg (prefix if interactive), move that many pages."
- (interactive "p")
- (or count (setq count 1))
- (widen)
- ;; Cannot use forward-page because of problems at page boundaries.
- (while (and (> count 0) (not (eobp)))
- (if (re-search-forward page-delimiter nil t)
- nil
- (goto-char (point-max)))
- (setq count (1- count)))
- (while (and (< count 0) (not (bobp)))
- (if (re-search-backward page-delimiter nil t)
- (goto-char (match-beginning 0))
- (goto-char (point-min)))
- (setq count (1+ count)))
- (narrow-to-page)
- (goto-char (point-min))
- (recenter 0))
-
-(defun previous-page (&optional count)
- "Move to the previous page bounded by the `page-delimiter' variable.
-With arg (prefix if interactive), move that many pages."
- (interactive "p")
- (or count (setq count 1))
- (next-page (- count)))
-
-
-;;;; Adding and searching pages
-
-(defun add-new-page (header-line)
- "Insert new page at point; prompt for header line.
-Page begins with a `^L' as the page-delimiter.
-Point is left in the body of page."
- (interactive "sHeader line: ")
- (widen)
- (insert (format "\n \n%s\n\n" header-line))
- ;; don't renarrow; stay unnarrowed to see context
- (forward-line -1))
-
-(defvar pages-last-search nil
- "Value of last regexp searched for. Initially, nil.")
-
-(defun search-pages (regexp)
- "Search for REGEXP, starting from point, and narrow to page it is in."
- (interactive (list
- (read-string
- (format "Search for `%s' (end with RET): "
- (or pages-last-search "regexp")))))
- (if (equal regexp "")
- (setq regexp pages-last-search)
- (setq pages-last-search regexp))
- (widen)
- (re-search-forward regexp)
- (narrow-to-page))
-
-
-;;;; Sorting pages
-
-(autoload 'sort-subr "sort" "Primary function for sorting." t nil)
-
-(defun sort-pages-in-region (reverse beg end)
- "Sort pages in region alphabetically. Prefix arg means reverse order.
-
-Called from a program, there are three arguments:
-REVERSE (non-nil means reverse order), BEG and END (region to sort)."
-
-;;; This sort function handles ends of pages differently than
-;;; `sort-pages' and works better with lists of addresses and similar
-;;; files.
-
- (interactive "P\nr")
- (save-restriction
- (narrow-to-region beg end)
- (goto-char (point-min))
- ;;; `sort-subr' takes three arguments
- (sort-subr reverse
-
- ;; NEXTRECFUN is called with point at the end of the
- ;; previous record. It moves point to the start of the
- ;; next record.
- (function (lambda ()
- (re-search-forward page-delimiter nil t)
- (skip-chars-forward " \t\n")
- ))
-
- ;; ENDRECFUN is is called with point within the record.
- ;; It should move point to the end of the record.
- (function (lambda ()
- (if (re-search-forward
- page-delimiter
- nil
- t)
- (goto-char (match-beginning 0))
- (goto-char (point-max))))))))
-
-(defun sort-pages-buffer (&optional reverse)
- "Sort pages alphabetically in buffer. Prefix arg means reverse order.
-\(Non-nil arg if not interactive.\)"
-
- (interactive "P")
- (or reverse (setq reverse nil))
- (widen)
- (let ((beginning (point-min))
- (end (point-max)))
- (sort-pages-in-region reverse beginning end)))
-
-
-;;;; Pages directory ancillary definitions
-
-(defvar pages-directory-buffer-narrowing-p nil
- "*If non-nil, `pages-directory-goto' narrows pages buffer to entry.")
-
-(defvar pages-directory-previous-regexp nil
- "Value of previous regexp used by `pages-directory'.
-\(This regular expression may be used to select only those pages that
-contain matches to the regexp.\)")
-
-(defvar pages-buffer nil
- "The buffer for which the pages-directory function creates the directory.")
-
-(defvar pages-directory-prefix "*Directory for:"
- "Prefix of name of temporary buffer for pages-directory.")
-
-(defvar pages-pos-list nil
- "List containing the positions of the pages in the pages-buffer.")
-
-(defvar pages-directory-map nil
- "Keymap for the pages-directory-buffer.")
-
-(if pages-directory-map
- ()
- (setq pages-directory-map (make-sparse-keymap))
- (define-key pages-directory-map "\C-c\C-c"
- 'pages-directory-goto))
-
-(defun set-page-delimiter (regexp reset-p)
- "Set buffer local value of page-delimiter to REGEXP.
-Called interactively with a prefix argument, reset `page-delimiter' to
-its original value.
-
-In a program, non-nil second arg causes first arg to be ignored and
-resets the page-delimiter to the original value."
-
- (interactive
- (if current-prefix-arg
- (list original-page-delimiter nil)
- (list (read-string "Set page-delimiter to regexp: " page-delimiter)
- nil)))
- (make-local-variable 'original-page-delimiter)
- (make-local-variable 'page-delimiter)
- (setq original-page-delimiter
- (or original-page-delimiter page-delimiter))
- (if (not reset-p)
- (setq page-delimiter regexp)
- (setq page-delimiter original-page-delimiter))
- (if (interactive-p)
- (message "The value of `page-delimiter' is now: %s" page-delimiter)))
-
-
-;;;; Pages directory main definitions
-
-(defun pages-directory
- (pages-list-all-headers-p count-lines-p &optional regexp)
- "Display a directory of the page headers in a temporary buffer.
-A header is the first non-blank line after the page-delimiter.
-\\[pages-directory-mode]
-You may move point to one of the lines in the temporary buffer,
-then use \\<pages-directory-goto> to go to the same line in the pages buffer.
-
-In interactive use:
-
- 1. With no prefix arg, display all headers.
-
- 2. With prefix arg, display the headers of only those pages that
- contain matches to a regular expression for which you are
- prompted.
-
- 3. With numeric prefix arg, for every page, print the number of
- lines within each page.
-
- 4. With negative numeric prefix arg, for only those pages that
- match a regular expression, print the number of lines within
- each page.
-
-When called from a program, non-nil first arg means list all headers;
-non-nil second arg means print numbers of lines in each page; if first
-arg is nil, optional third arg is regular expression.
-
-If the buffer is narrowed, the `pages-directory' command creates a
-directory for only the accessible portion of the buffer."
-
- (interactive
- (cond ((not current-prefix-arg)
- (list t nil nil))
- ((listp current-prefix-arg)
- (list nil
- nil
- (read-string
- (format "Select according to `%s' (end with RET): "
- (or pages-directory-previous-regexp "regexp")))))
- ((> (prefix-numeric-value current-prefix-arg) 0)
- (list t t nil))
- ((< (prefix-numeric-value current-prefix-arg) 0)
- (list nil
- t
- (read-string
- (format "Select according to `%s' (end with RET): "
- (or pages-directory-previous-regexp "regexp")))))))
-
- (if (equal regexp "")
- (setq regexp pages-directory-previous-regexp)
- (setq pages-directory-previous-regexp regexp))
-
- (if (interactive-p)
- (message "Creating directory for: %s "
- (buffer-name)))
-
- (let ((buffer (current-buffer))
- (pages-directory-buffer
- (concat pages-directory-prefix " " (buffer-name) " "))
- (linenum 1)
- (pages-buffer-original-position (point))
- (pages-buffer-original-page 0))
-
- ;; `with-output-to-temp-buffer' binds the value of the variable
- ;; `standard-output' to the buffer named as its first argument,
- ;; but does not switch to that buffer.
- (with-output-to-temp-buffer pages-directory-buffer
- (save-excursion
- (set-buffer standard-output)
- (pages-directory-mode)
- (insert
- "==== Pages Directory: use `C-c C-c' to go to page under cursor. ====" ?\n)
- (setq pages-buffer buffer)
- (setq pages-pos-list nil))
-
- (if pages-list-all-headers-p
-
- ;; 1. If no prefix argument, list all headers
- (save-excursion
- (goto-char (point-min))
-
- ;; (a) Point is at beginning of buffer; but the first
- ;; page may not begin with a page-delimiter
- (save-restriction
- ;; If page delimiter is at beginning of buffer, skip it
- (if (and (save-excursion
- (re-search-forward page-delimiter nil t))
- (= 1 (match-beginning 0)))
- (goto-char (match-end 0)))
- (narrow-to-page)
- (pages-copy-header-and-position count-lines-p))
-
- ;; (b) Search within pages buffer for next page-delimiter
- (while (re-search-forward page-delimiter nil t)
- (pages-copy-header-and-position count-lines-p)))
-
- ;; 2. Else list headers whose pages match regexp.
- (save-excursion
- ;; REMOVED save-restriction AND widen FROM HERE
- (goto-char (point-min))
-
- ;; (a) Handle first page
- (save-restriction
- (narrow-to-page)
- ;; search for selection regexp
- (if (save-excursion (re-search-forward regexp nil t))
- (pages-copy-header-and-position count-lines-p)))
-
- ;; (b) Search for next page-delimiter
- (while (re-search-forward page-delimiter nil t)
- (save-restriction
- (narrow-to-page)
- ;; search for selection regexp
- (if (save-excursion (re-search-forward regexp nil t))
- (pages-copy-header-and-position count-lines-p)
- )))))
-
- (set-buffer standard-output)
- ;; Put positions in increasing order to go with buffer.
- (setq pages-pos-list (nreverse pages-pos-list))
- (if (interactive-p)
- (message "%d matching lines in: %s"
- (length pages-pos-list) (buffer-name buffer))))
- (pop-to-buffer pages-directory-buffer)
- (sit-for 0) ; otherwise forward-line fails if N > window height.
- (forward-line (if (= 0 pages-buffer-original-page)
- 1
- pages-buffer-original-page))))
-
-(defun pages-copy-header-and-position (count-lines-p)
- "Copy page header and its position to the Pages Directory.
-Only arg non-nil, count lines in page and insert before header.
-Used by `pages-directory' function."
-
- (let (position line-count)
-
- (if count-lines-p
- (save-excursion
- (save-restriction
- (narrow-to-page)
- (setq line-count (count-lines (point-min) (point-max))))))
-
- ;; Keep track of page for later cursor positioning
- (if (<= (point) pages-buffer-original-position)
- (setq pages-buffer-original-page
- (1+ pages-buffer-original-page)))
-
- (save-excursion
- ;; go to first non-blank char after the page-delimiter
- (skip-chars-forward " \t\n")
- ;; set the marker here; this the place to which the
- ;; `pages-directory-goto' command will go
- (setq position (make-marker))
- (set-marker position (point))
- (let ((start (point))
- (end (save-excursion (end-of-line) (point))))
- ;; change to directory buffer
- (set-buffer standard-output)
- ;; record page position
- (setq pages-pos-list (cons position pages-pos-list))
- ;; insert page header
- (insert-buffer-substring buffer start end))
-
- (if count-lines-p
- (save-excursion
- (beginning-of-line)
- (insert (format "%3d: " line-count))))
-
- (terpri))
- (forward-line 1)))
-
-(defun pages-directory-mode ()
- "Mode for handling the pages-directory buffer.
-
-Move point to one of the lines in this buffer, then use \\[pages-directory-goto] to go
-to the same line in the pages buffer."
-
- (kill-all-local-variables)
- (use-local-map pages-directory-map)
- (setq major-mode 'pages-directory-mode)
- (setq mode-name "Pages-Directory")
- (make-local-variable 'pages-buffer)
- (make-local-variable 'pages-pos-list)
- (make-local-variable 'pages-directory-buffer-narrowing-p))
-
-(defun pages-directory-goto ()
- "Go to the corresponding line in the pages buffer."
-
-;;; This function is mostly a copy of `occur-mode-goto-occurrence'
-
- (interactive)
- (if (or (not pages-buffer)
- (not (buffer-name pages-buffer)))
- (progn
- (setq pages-buffer nil
- pages-pos-list nil)
- (error "Buffer in which pages were found is deleted.")))
- (beginning-of-line)
- (let* ((pages-number (1- (count-lines (point-min) (point))))
- (pos (nth pages-number pages-pos-list))
- (end-of-directory-p (eobp))
- (narrowing-p pages-directory-buffer-narrowing-p))
- (pop-to-buffer pages-buffer)
- (widen)
- (if end-of-directory-p
- (goto-char (point-max))
- (goto-char (marker-position pos)))
- (if narrowing-p (narrow-to-page))))
-
-
-;;;; The `pages-directory-for-addresses' function and ancillary code
-
-(defvar pages-addresses-file-name "~/addresses"
- "*Standard name for file of addresses. Entries separated by `page-delimiter'.
-Used by `pages-directory-for-addresses' function.")
-
-(defvar pages-directory-for-addresses-narrowing-p t
- "*If non-nil, `pages-directory-goto' narrows addresses buffer to entry.")
-
-(defun pages-directory-for-addresses (&optional filename)
- "Find addresses file and display its directory.
-By default, create and display directory of `pages-addresses-file-name'.
-Optional argument is FILENAME. In interactive use, with prefix
-argument, prompt for file name and provide completion.
-
-Move point to one of the lines in the displayed directory,
-then use C-c C-c to go to the same line in the addresses buffer."
-
- (interactive
- (list (if current-prefix-arg
- (read-file-name "Filename: " pages-addresses-file-name))))
-
- (if (interactive-p)
- (message "Creating directory for: %s "
- (or filename pages-addresses-file-name)))
- (if (file-exists-p (or filename pages-addresses-file-name))
- (progn
- (set-buffer
- (find-file-noselect
- (expand-file-name
- (or filename pages-addresses-file-name))))
- (widen)
- (pages-directory t nil nil)
- (pages-directory-address-mode)
- (setq pages-directory-buffer-narrowing-p
- pages-directory-for-addresses-narrowing-p)
- (delete-other-windows)
- (save-excursion
- (goto-char (point-min))
- (delete-region (point) (save-excursion (end-of-line) (point)))
- (insert
- "=== Address List Directory: use `C-c C-c' to go to page under cursor. ===")
- (set-buffer-modified-p nil)
- ))
- (error "No addresses file found!")))
-
-(defun pages-directory-address-mode ()
- "Mode for handling the Addresses Directory buffer.
-
-Move point to one of the lines in this buffer, then use C-c C-c to go
-to the same line in the pages buffer."
-
- (use-local-map pages-directory-map)
- (setq major-mode 'pages-directory-address-mode)
- (setq mode-name "Addresses Directory")
- (make-local-variable 'pages-buffer)
- (make-local-variable 'pages-pos-list)
- (make-local-variable 'pages-directory-buffer-narrowing-p))
-
-;;;;;;;;;;;;;;;; end of page-ext.el ;;;;;;;;;;;;;;;;
diff --git a/lisp/textmodes/refbib.el b/lisp/textmodes/refbib.el
deleted file mode 100644
index 3b376cdd90b..00000000000
--- a/lisp/textmodes/refbib.el
+++ /dev/null
@@ -1,715 +0,0 @@
-;; Convert refer-style bibliographic entries to ones usable by latex bib
-;; Copyright (C) 1989 Free Software Foundation, Inc.
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 1, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
-;; Use: from a buffer containing the refer-style bibliography,
-;; M-x r2b-convert-buffer
-;; Program will prompt for an output buffer name, and will log
-;; warnings during the conversion process in the buffer *Log*.
-
-; HISTORY
-; 9/88, created
-; modified 1/19/89, allow books with editor but no author;
-; added %O ordering field;
-; appended illegal multiple fields, instead of
-; discarding;
-; added rule, a tech report whose %R number
-; contains "ISBN" is really a book
-; added rule, anything with an editor is a book
-; or a proceedings
-; added 'manual type, for items with institution
-; but no author or editor
-; fixed bug so trailing blanks are trimmed
-; added 'proceedings type
-; used "organization" field for proceedings
-; modified 2/16/89, updated help messages
-; modified 2/23/89, include capitalize stop words in r2b stop words,
-; fixed problems with contractions (e.g. it's),
-; caught multiple stop words in a row
-; modified 3/1/89, fixed capitialize-title for first words all caps
-; modified 3/15/89, allow use of " to delimit fields
-; modified 4/18/89, properly "quote" special characters on output
-(provide 'refer-to-bibtex)
-;**********************************************************
-; User Parameters
-
-(defvar r2b-trace-on nil "*trace conversion")
-
-(defvar r2b-journal-abbrevs
- '(
- )
- " Abbreviation list for journal names.
-If the car of an element matches a journal name exactly, it is replaced by
-the cadr when output. Braces must be included if replacement is a
-{string}, but not if replacement is a bibtex abbreviation. The cadr
-may be eliminated if is exactly the same as the car.
- Because titles are capitalized before matching, the abbreviation
-for the journal name should be listed as beginning with a capital
-letter, even if it really doesn't.
- For example, a value of '((\"Aij\" \"{Artificial Intelligence}\")
-(\"Ijcai81\" \"ijcai7\")) would expand Aij to the text string
-\"Artificial Intelligence\", but would replace Ijcai81 with the
-BibTeX macro \"ijcai7\".")
-
-(defvar r2b-booktitle-abbrevs
- '(
- )
- " Abbreviation list for book and proceedings names. If the car of
-an element matches a title or booktitle exactly, it is replaced by
-the cadr when output. Braces must be included if replacement is
-a {string}, but not if replacement is a bibtex abbreviation. The cadr
-may be eliminated if is exactly the same as the car.
- Because titles are capitalized before matching, the abbreviated title
-should be listed as beginning with a capital letter, even if it doesn't.
- For example, a value of '((\"Aij\" \"{Artificial Intelligence}\")
-(\"Ijcai81\" \"ijcai7\")) would expand Aij to the text string
-\"Artificial Intelligence\", but would replace Ijcai81 with the
-BibTeX macro \"ijcai7\".")
-
-(defvar r2b-proceedings-list
- '()
- " Assoc list of books or journals which are really conference proceedings,
-but whose name and whose abbrev expansion (as defined in r2b-journal-abbrevs
-and r2b-booktitle-abbrevs) does not contain the words 'conference' or
-'proceedings'. (Those cases are handled automatically.)
-The entry must match the given data exactly.
- Because titles are capitalized before matching, the items in this list
-should begin with a capital letter.
- For example, suppose the title \"Ijcai81\" is used for the proceedings of
-a conference, and it's expansion is the BibTeX macro \"ijcai7\". Then
-r2b-proceedings-list should be '((\"Ijcai81\") ...). If instead its
-expansion were \"Proceedings of the Seventh International Conference
-on Artificial Intelligence\", then you would NOT need to include Ijcai81
-in r2b-proceedings-list (although it wouldn't cause an error).")
-
-(defvar r2b-additional-stop-words
- "Some\\|What"
- "Words other than the capitialize-title-stop-words
-which are not to be used to build the citation key")
-
-
-(defvar r2b-delimit-with-quote
- t
- "*If true, then use \" to delimit fields, otherwise use braces")
-
-;**********************************************************
-; Utility Functions
-
-(defvar capitalize-title-stop-words
- (concat
- "the\\|and\\|of\\|is\\|a\\|an\\|of\\|for\\|in\\|to\\|in\\|on\\|at\\|"
- "by\\|with\\|that\\|its")
- "Words not to be capitialized in a title (unless they are the first
-word in the title)")
-
-(defvar capitalize-title-stop-regexp
- (concat "\\(" capitalize-title-stop-words "\\)\\(\\b\\|'\\)"))
-
-(defun capitalize-title-region (begin end)
- "Like capitalize-region, but don't capitalize stop words, except the first"
- (interactive "r")
- (let ((case-fold-search nil) (orig-syntax-table (syntax-table)))
- (unwind-protect
- (save-restriction
- (set-syntax-table text-mode-syntax-table)
- (narrow-to-region begin end)
- (goto-char (point-min))
- (if (looking-at "[A-Z][a-z]*[A-Z]")
- (forward-word 1)
- (capitalize-word 1))
- (while (re-search-forward "\\<" nil t)
- (if (looking-at "[A-Z][a-z]*[A-Z]")
- (forward-word 1)
- (if (let ((case-fold-search t))
- (looking-at capitalize-title-stop-regexp))
- (downcase-word 1)
- (capitalize-word 1)))
- ))
- (set-syntax-table orig-syntax-table))))
-
-
-(defun capitalize-title (s)
- "Like capitalize, but don't capitalize stop words, except the first"
- (save-excursion
- (set-buffer (get-buffer-create "$$$Scratch$$$"))
- (erase-buffer)
- (insert s)
- (capitalize-title-region (point-min) (point-max))
- (buffer-string)))
-
-;*********************************************************
-(defun r2b-reset ()
- "unbind defvars, for debugging"
- (interactive)
- (makunbound 'r2b-journal-abbrevs)
- (makunbound 'r2b-booktitle-abbrevs)
- (makunbound 'r2b-proceedings-list)
- (makunbound 'capitalize-title-stop-words)
- (makunbound 'capitalize-title-stop-regexp)
- (makunbound 'r2b-additional-stop-words)
- (makunbound 'r2b-stop-regexp)
- )
-
-(defvar r2b-stop-regexp
- (concat "\\`\\(\\("
- r2b-additional-stop-words "\\|" capitalize-title-stop-words
- "\\)\\('\\w*\\)?\\W+\\)*\\([A-Z0-9]+\\)"))
-
-
-(defun r2b-trace (&rest args)
- (if r2b-trace-on
- (progn
- (apply (function message) args)
- (sit-for 0)
- )))
-
-(defun r2b-match (exp)
- "returns string matched in current buffer"
- (buffer-substring (match-beginning exp) (match-end exp)))
-
-(defvar r2b-out-buf-name "*Out*" "*output from refer-to-bibtex" )
-(defvar r2b-log-name "*Log*" "*logs errors from refer-to-bibtex" )
-(defvar r2b-in-buf nil)
-(defvar r2b-out-buf nil)
-(defvar r2b-log nil)
-
-(defvar r2b-error-found nil)
-
-(setq r2b-variables '(
- r2b-error-found
- r2bv-author
- r2bv-primary-author
- r2bv-date
- r2bv-year
- r2bv-decade
- r2bv-month
- r2bv-title
- r2bv-title-first-word
- r2bv-editor
- r2bv-annote
- r2bv-tr
- r2bv-address
- r2bv-institution
- r2bv-keywords
- r2bv-booktitle
- r2bv-journal
- r2bv-volume
- r2bv-number
- r2bv-pages
- r2bv-booktitle
- r2bv-kn
- r2bv-publisher
- r2bv-organization
- r2bv-school
- r2bv-type
- r2bv-where
- r2bv-note
- r2bv-ordering
- ))
-
-(defun r2b-clear-variables ()
- "set all global vars used by r2b to nil"
- (let ((vars r2b-variables))
- (while vars
- (set (car vars) nil)
- (setq vars (cdr vars)))
- ))
-
-(defun r2b-warning (&rest args)
- (setq r2b-error-found t)
- (princ (apply (function format) args) r2b-log)
- (princ "\n" r2b-log)
- (princ "\n" r2b-out-buf)
- (princ "% " r2b-out-buf)
- (princ (apply (function format) args) r2b-out-buf)
- )
-
-(defun r2b-get-field (var field &optional unique required capitalize)
- "Set VAR to string value of FIELD, if any. If none, VAR is set to
-nil. If multiple fields appear, then separate values with the
-'\\nand\\t\\t', unless UNIQUE is non-nil, in which case log a warning
-and just concatenate the values. Trim off leading blanks and tabs on
-first line, and trailing blanks and tabs of every line. Log a warning
-and set VAR to the empty string if REQUIRED is true. Capitalize as a
-title if CAPITALIZE is true. Returns value of VAR."
- (let (item val (not-past-end t))
- (r2b-trace "snarfing %s" field)
- (goto-char (point-min))
- (while (and not-past-end
- (re-search-forward
- (concat "^" field "\\b[ \t]*\\(.*[^ \t\n]\\)[ \t]*") nil t))
- (setq item (r2b-match 1))
- (while (and (setq not-past-end (zerop (forward-line 1)))
- (not (looking-at "[ \t]*$\\|%")))
- (looking-at "\\(.*[^ \t\n]\\)[ \t]*$")
- (setq item (concat item "\n" (r2b-match 1)))
- )
- (if (null val)
- (setq val item)
- (if unique
- (progn
- (r2b-warning "*Illegal multiple field %s %s" field item)
- (setq val (concat val "\n" item))
- )
- (setq val (concat val "\n\t\tand " item))
- )
- )
- )
- (if (and val capitalize)
- (setq val (capitalize-title val)))
- (set var val)
- (if (and (null val) required)
- (r2b-require var))
- ))
-
-(defun r2b-set-match (var n regexp string )
- "set VAR to the Nth subpattern in REGEXP matched by STRING, or nil if none"
- (set var
- (if (and (stringp string) (string-match regexp string))
- (substring string (match-beginning n) (match-end n))
- nil)
- )
- )
-
-(defvar r2b-month-abbrevs
- '(("jan") ("feb") ("mar") ("apr") ("may") ("jun") ("jul") ("aug")
- ("sep") ("oct") ("nov") ("dec")))
-
-(defun r2b-convert-month ()
- "Try to convert r2bv-month to a standard 3 letter name"
- (if r2bv-month
- (let ((months r2b-month-abbrevs))
- (if (string-match "[^0-9]" r2bv-month)
- (progn
- (while (and months (not (string-match (car (car months))
- r2bv-month)))
- (setq months (cdr months)))
- (if months
- (setq r2bv-month (car (car months)))))
- (progn
- (setq months (car (read-from-string r2bv-month)))
- (if (and (numberp months)
- (> months 0)
- (< months 13))
- (setq r2bv-month (car (nth months r2b-month-abbrevs)))
- (progn
- (r2b-warning "* Ridiculous month")
- (setq r2bv-month nil))
- ))
- ))
- )
- )
-
-(defun r2b-snarf-input ()
- "parse buffer into global variables"
- (let ((case-fold-search t))
- (r2b-trace "snarfing...")
- (sit-for 0)
- (set-buffer r2b-in-buf)
- (goto-char (point-min))
- (princ " " r2b-log)
- (princ (buffer-substring (point) (progn (end-of-line) (point))) r2b-log)
- (terpri r2b-log)
-
- (r2b-get-field 'r2bv-author "%A")
- (r2b-get-field 'r2bv-editor "%E")
- (cond
- (r2bv-author
- (r2b-set-match 'r2bv-primary-author 1
- "\\b\\(\\w+\\)[ \t]*\\($\\|,\\)" r2bv-author)
- )
- (r2bv-editor
- (r2b-set-match 'r2bv-primary-author 1
- "\\b\\(\\w+\\)[ \t]*\\($\\|,\\)" r2bv-editor)
- )
- (t
- (setq r2bv-primary-author "")
- )
- )
-
- (r2b-get-field 'r2bv-date "%D" t t)
- (r2b-set-match 'r2bv-year 0 "[12][0-9][0-9][0-9]" r2bv-date)
- (and (null r2bv-year)
- (r2b-set-match 'r2bv-year 1 "[^0-9]\\([0-9][0-9]\\)$" r2bv-date)
- (setq r2bv-year (concat "19" r2bv-year)))
- (r2b-set-match 'r2bv-decade 1 "..\\(..\\)" r2bv-year)
- (r2b-set-match 'r2bv-month 0
- "[0-9]+/\\|[a-zA-Z]+" r2bv-date)
- (if (and (stringp r2bv-month) (string-match "\\(.*\\)/$" r2bv-month))
- (setq r2bv-month (substring r2bv-month 0 (match-end 1))))
- (r2b-convert-month)
-
- (r2b-get-field 'r2bv-title "%T" t t t)
- (r2b-set-match 'r2bv-title-first-word 4
- r2b-stop-regexp
- r2bv-title)
-
- (r2b-get-field 'r2bv-annote "%X" t )
- (r2b-get-field 'r2bv-tr "%R" t)
- (r2b-get-field 'r2bv-address "%C" t)
- (r2b-get-field 'r2bv-institution "%I" t)
- (r2b-get-field 'r2bv-keywords "%K")
- (r2b-get-field 'r2bv-booktitle "%B" t nil t)
- (r2b-get-field 'r2bv-journal "%J" t nil t)
- (r2b-get-field 'r2bv-volume "%V" t)
- (r2b-get-field 'r2bv-number "%N" t)
- (r2b-get-field 'r2bv-pages "%P" t)
- (r2b-get-field 'r2bv-where "%W" t)
- (r2b-get-field 'r2bv-ordering "%O" t)
- )
- )
-
-
-(defun r2b-put-field (field data &optional abbrevs)
- "print bibtex FIELD = {DATA} if DATA not null; precede
-with a comma and newline; if ABBREVS list is given, then
-try to replace the {DATA} with an abbreviation"
- (if data
- (let (match nodelim multi-line index)
- (cond
- ((and abbrevs (setq match (assoc data abbrevs)))
- (if (null (cdr match))
- (setq data (car match))
- (setq data (car (cdr match))))
- (setq nodelim t))
- ((and (not (equal data ""))
- (not (string-match "[^0-9]" data)))
- (setq nodelim t))
- (t
- (setq index 0)
- (while (string-match "[\\~^]" data index)
- (setq data (concat (substring data 0 (match-beginning 0))
- "\\verb+"
- (substring data (match-beginning 0) (match-end 0))
- "+"
- (substring data (match-end 0))))
- (setq index (+ (match-end 0) 7)))
- (setq index 0)
- (while (string-match "[$&%#_{}]" data index)
- (setq data (concat (substring data 0 (match-beginning 0))
- "\\"
- (substring data (match-beginning 0))))
- (setq index (+ (match-end 0) 1)))
- (setq index 0)
- (if r2b-delimit-with-quote
- (while (string-match "\"" data index)
- (setq data (concat (substring data 0 (match-beginning 0))
- "{\"}"
- (substring data (match-end 0))))
- (setq index (+ (match-end 0) 2))))
- ))
- (princ ", \n ")
- (princ field)
- (princ " =\t")
- (if (not nodelim)
- (if r2b-delimit-with-quote
- (princ "\"")
- (princ "{")))
- (string-match ".*" data)
- (if (> (match-end 0) 59)
- (princ "\n"))
- (princ data)
- (if (not nodelim)
- (if r2b-delimit-with-quote
- (princ "\"")
- (princ "}")))
- )
- ))
-
-
-(defun r2b-require (vars)
- "If any of VARS is null, set to empty string and log error"
- (cond
- ((null vars))
- ((listp vars) (r2b-require (car vars)) (r2b-require (cdr vars)))
- (t
- (if (null (symbol-value vars))
- (progn
- (r2b-warning "*Missing value for field %s" vars)
- (set vars "")
- )))
- )
- )
-
-
-(defmacro r2b-moveq (new old)
- "set NEW to OLD and set OLD to nil"
- (list 'progn (list 'setq new old) (list 'setq old 'nil)))
-
-(defun r2b-isa-proceedings (name)
- "return t if NAME is the name of proceedings"
- (and
- name
- (or
- (string-match "proceedings\\|conference" name)
- (assoc name r2b-proceedings-list)
- (let ((match (assoc name r2b-booktitle-abbrevs)))
- (and match
- (string-match "proceedings\\|conference" (car (cdr match)))))
- )))
-
-(defun r2b-isa-university (name)
- "return t if NAME is a university or similar organization,
-but not a publisher"
- (and
- name
- (string-match "university" name)
- (not (string-match "press" name))
-
- ))
-
-(defun r2b-barf-output ()
- "generate bibtex based on global variables"
- (let ((standard-output r2b-out-buf) (case-fold-search t) match)
-
- (r2b-trace "...barfing")
- (sit-for 0)
- (set-buffer r2b-out-buf)
-
- (setq r2bv-kn (concat r2bv-primary-author r2bv-decade
- r2bv-title-first-word))
-
- (setq r2bv-entry-kind
- (cond
- ((r2b-isa-proceedings r2bv-journal)
- (r2b-moveq r2bv-booktitle r2bv-journal)
- (if (r2b-isa-university r2bv-institution)
- (r2b-moveq r2bv-organization r2bv-institution)
- (r2b-moveq r2bv-publisher r2bv-institution))
- (r2b-moveq r2bv-note r2bv-tr)
- (r2b-require 'r2bv-author)
- 'inproceedings)
- ((r2b-isa-proceedings r2bv-booktitle)
- (if (r2b-isa-university r2bv-institution)
- (r2b-moveq r2bv-organization r2bv-institution)
- (r2b-moveq r2bv-publisher r2bv-institution))
- (r2b-moveq r2bv-note r2bv-tr)
- (r2b-require 'r2bv-author)
- 'inproceedings)
- ((and r2bv-tr (string-match "phd" r2bv-tr))
- (r2b-moveq r2bv-school r2bv-institution)
- (r2b-require 'r2bv-school )
- (r2b-require 'r2bv-author)
- 'phdthesis)
- ((and r2bv-tr (string-match "master" r2bv-tr))
- (r2b-moveq r2bv-school r2bv-institution)
- (r2b-require 'r2bv-school )
- (r2b-require 'r2bv-author)
- 'mastersthesis)
- ((and r2bv-tr (string-match "draft\\|unpublish" r2bv-tr))
- (r2b-moveq r2bv-note r2bv-institution)
- (r2b-require 'r2bv-author)
- 'unpublished)
- (r2bv-journal
- (r2b-require 'r2bv-author)
- 'article)
- (r2bv-booktitle
- (r2b-moveq r2bv-publisher r2bv-institution)
- (r2b-moveq r2bv-note r2bv-tr)
- (r2b-require 'r2bv-publisher)
- (r2b-require 'r2bv-author)
- 'incollection)
- ((and r2bv-author
- (null r2bv-editor)
- (string-match "\\`personal communication\\'" r2bv-title))
- 'misc)
- ((r2b-isa-proceedings r2bv-title)
- (if (r2b-isa-university r2bv-institution)
- (r2b-moveq r2bv-organization r2bv-institution)
- (r2b-moveq r2bv-publisher r2bv-institution))
- (r2b-moveq r2bv-note r2bv-tr)
- 'proceedings)
- ((or r2bv-editor
- (and r2bv-author
- (or
- (null r2bv-tr)
- (string-match "\\bisbn\\b" r2bv-tr))))
- (r2b-moveq r2bv-publisher r2bv-institution)
- (r2b-moveq r2bv-note r2bv-tr)
- (r2b-require 'r2bv-publisher)
- (if (null r2bv-editor)
- (r2b-require 'r2bv-author))
- 'book)
- (r2bv-tr
- (r2b-require 'r2bv-institution)
- (if (string-match
- "\\`\\(\\(.\\|\n\\)+\\)[ \t\n]+\\([^ \t\n]\\)+\\'"
- r2bv-tr)
- (progn
- (setq r2bv-type (substring r2bv-tr 0 (match-end 1)))
- (setq r2bv-number (substring r2bv-tr
- (match-beginning 3)))
- (setq r2bv-tr nil))
- (r2b-moveq r2bv-number r2bv-tr))
- (r2b-require 'r2bv-author)
- 'techreport)
- (r2bv-institution
- (r2b-moveq r2bv-organization r2bv-institution)
- 'manual)
- (t
- 'misc)
- ))
-
- (r2b-require '( r2bv-year))
-
- (if r2b-error-found
- (princ "\n% Warning -- Errors During Conversion Next Entry\n"))
-
- (princ "\n@")
- (princ r2bv-entry-kind)
- (princ "( ")
- (princ r2bv-kn)
-
- (r2b-put-field "author" r2bv-author )
- (r2b-put-field "title" r2bv-title r2b-booktitle-abbrevs)
- (r2b-put-field "year" r2bv-year )
-
- (r2b-put-field "month" r2bv-month r2b-month-abbrevs)
- (r2b-put-field "journal" r2bv-journal r2b-journal-abbrevs)
- (r2b-put-field "volume" r2bv-volume)
- (r2b-put-field "type" r2bv-type)
- (r2b-put-field "number" r2bv-number)
- (r2b-put-field "booktitle" r2bv-booktitle r2b-booktitle-abbrevs)
- (r2b-put-field "editor" r2bv-editor)
- (r2b-put-field "publisher" r2bv-publisher)
- (r2b-put-field "institution" r2bv-institution)
- (r2b-put-field "organization" r2bv-organization)
- (r2b-put-field "school" r2bv-school)
- (r2b-put-field "pages" r2bv-pages)
- (r2b-put-field "address" r2bv-address)
- (r2b-put-field "note" r2bv-note)
- (r2b-put-field "keywords" r2bv-keywords)
- (r2b-put-field "where" r2bv-where)
- (r2b-put-field "ordering" r2bv-ordering)
- (r2b-put-field "annote" r2bv-annote)
-
- (princ " )\n")
- )
- )
-
-
-(defun r2b-convert-record (output-name)
- "transform current bib entry and append to buffer OUTPUT;
-do M-x r2b-help for more info"
- (interactive
- (list (read-string "Output to buffer: " r2b-out-buf-name)))
- (let (rec-end rec-begin not-done)
- (setq r2b-out-buf-name output-name)
- (setq r2b-out-buf (get-buffer-create output-name))
- (setq r2b-in-buf (current-buffer))
- (set-buffer r2b-out-buf)
- (goto-char (point-max))
- (setq r2b-log (get-buffer-create r2b-log-name))
- (set-buffer r2b-log)
- (goto-char (point-max))
- (set-buffer r2b-in-buf)
- (setq not-done (re-search-forward "[^ \t\n]" nil t))
- (if not-done
- (progn
- (re-search-backward "^[ \t]*$" nil 2)
- (re-search-forward "^%")
- (beginning-of-line nil)
- (setq rec-begin (point))
- (re-search-forward "^[ \t]*$" nil 2)
- (setq rec-end (point))
- (narrow-to-region rec-begin rec-end)
- (r2b-clear-variables)
- (r2b-snarf-input)
- (r2b-barf-output)
- (set-buffer r2b-in-buf)
- (widen)
- (goto-char rec-end)
- t)
- nil
- )
- ))
-
-
-(defun r2b-convert-buffer (output-name)
- "transform current buffer and append to buffer OUTPUT;
-do M-x r2b-help for more info"
- (interactive
- (list (read-string "Output to buffer: " r2b-out-buf-name)))
- (save-excursion
- (setq r2b-log (get-buffer-create r2b-log-name))
- (set-buffer r2b-log)
- (erase-buffer))
- (widen)
- (goto-char (point-min))
- (message "Working, please be patient...")
- (sit-for 0)
- (while (r2b-convert-record output-name) t)
- (message "Done, results in %s, errors in %s"
- r2b-out-buf-name r2b-log-name)
- )
-
-(defvar r2b-load-quietly nil "*Don't print help message when loaded")
-
-(defvar r2b-help-message
-" Refer to Bibtex Bibliography Conversion
-
-A refer-style database is of the form:
-
-%A Joe Blow
-%T Great Thoughts I've Thought
-%D 1977
-etc.
-
-This utility converts these kind of databases to bibtex form, for
-users of TeX and LaTex. Instructions:
-1. Visit the file containing the refer-style database.
-2. The command
- M-x r2b-convert-buffer
- converts the entire buffer, appending it's output by default in a
- buffer named *Out*, and logging progress and errors in a buffer
- named *Log*. The original file is never modified.
- Note that results are appended to *Out*, so if that buffer
- buffer already exists and contains material you don't want to
- save, you should kill it first.
-3. Switch to the buffer *Out* and save it as a named file.
-4. To convert a single refer-style entry, simply position the cursor
- at the entry and enter
- M-x r2b-convert-record
- Again output is appended to *Out* and errors are logged in *Log*.
-
-This utility is very robust and pretty smart about determining the
-type of the entry. It includes facilities for expanding refer macros
-to text, or substituting bibtex macros. Do M-x describe-variable on
- r2b-journal-abbrevs
- r2b-booktitle-abbrevs
- r2b-proceedings-list
-for information on these features.
-
-If you don't want to see this help message when you load this utility,
-then include the following line in your .emacs file:
- (setq r2b-load-quietly t)
-To see this message again, perform
- M-x r2b-help")
-
-
-(defun r2b-help ()
- "print help message"
- (interactive)
- (with-output-to-temp-buffer "*Help*"
- (princ r2b-help-message)))
-
-(if (not r2b-load-quietly)
- (r2b-help))
-
-(message "r2b loaded")
-
diff --git a/lisp/textmodes/tex-mode.el b/lisp/textmodes/tex-mode.el
deleted file mode 100644
index 34daea299a3..00000000000
--- a/lisp/textmodes/tex-mode.el
+++ /dev/null
@@ -1,799 +0,0 @@
-;; TeX, LaTeX, and SliTeX mode commands.
-;; Copyright (C) 1985, 1986, 1989 Free Software Foundation, Inc.
-;; Rewritten following contributions by William F. Schelter
-;; and Dick King (king@kestrel).
-;; Supported since 1986 by Stephen Gildea <gildea@erl.mit.edu>
-;; and Michael Prange <prange@erl.mit.edu>.
-;; Various improvements and corrections in Fall, 1989 by
-;; Edward M. Reingold <reingold@cs.uiuc.edu>.
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 1, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
-;; Still to do:
-;; Make TAB indent correctly for TeX code. Then we can make Linefeed
-;; do something more useful.
-;;
-;; Have spell understand TeX instead of assuming the entire world
-;; uses nroff.
-;;
-;; The code for finding matching $ needs to be fixed.
-
-(require 'oshell)
-(provide 'tex-mode)
-
-(defvar tex-directory "./"
- "*Directory in which to run TeX subjob. Temporary files are created here.")
-
-(defvar tex-run-command "tex"
- "*Command used to run TeX subjob.
-The name of the file will be appended to this string, separated by a space.")
-
-(defvar latex-run-command "latex"
- "*Command used to run LaTeX subjob.
-The name of the file will be appended to this string, separated by a space.")
-
-(defvar slitex-run-command "slitex"
- "*Command used to run SliTeX subjob.
-The name of the file will be appended to this string, separated by a space.")
-
-(defvar tex-bibtex-command "bibtex"
- "*Command string used by `tex-bibtex-file' to gather bibliographic data.
-The name of the file will be appended to this string, separated by a space.")
-
-(defvar tex-dvi-print-command "lpr -d"
- "*Command string used by \\[tex-print] to print a .dvi file.")
-
-(defvar tex-dvi-view-command nil
- "*Command string used by \\[tex-view] to display a .dvi file.")
-
-(defvar tex-show-queue-command "lpq"
- "*Command string used by \\[tex-show-print-queue] to show the print queue.
-Should show the queue that \\[tex-print] puts jobs on.")
-
-(defvar tex-default-mode 'plain-tex-mode
- "*Mode to enter for a new file that might be either TeX or LaTeX.
-This variable is used when it can't be determined whether the file
-is plain TeX or LaTeX or what because the file contains no commands.
-Normally set to either 'plain-tex-mode or 'latex-mode.")
-
-(defvar tex-open-quote "``"
- "*String inserted by typing \\[tex-insert-quote] to open a quotation.")
-
-(defvar tex-close-quote "''"
- "*String inserted by typing \\[tex-insert-quote] to close a quotation.")
-
-(defvar tex-command nil
- "Command to run TeX.
-The name of the file will be appended to this string, separated by a space.")
-
-(defvar tex-trailer nil
- "String appended after the end of a region sent to TeX by \\[tex-region].")
-
-(defvar tex-start-of-header nil
- "String used by \\[tex-region] to delimit the start of the file's header.")
-
-(defvar tex-end-of-header nil
- "String used by \\[tex-region] to delimit the end of the file's header.")
-
-(defvar tex-shell-cd-command "cd"
- "Command to give to shell running TeX to change directory.
-The value of tex-directory will be appended to this, separated by a space.")
-
-(defvar tex-zap-file nil
- "Temporary file name used for text being sent as input to TeX.
-Should be a simple file name with no extension or directory specification.")
-
-(defvar tex-last-buffer-texed nil
- "Buffer which was last TeXed.")
-
-(defvar tex-print-file nil
- "File name that \\[tex-print] prints.
-Set by \\[tex-region], \\[tex-buffer], and \\[tex-file].")
-
-(defvar tex-mode-syntax-table nil
- "Syntax table used while in TeX mode.")
-
-(defun tex-define-common-keys (keymap)
- "Define the keys that we want defined both in TeX mode and in the tex-shell."
- (define-key keymap "\C-c\C-k" 'tex-kill-job)
- (define-key keymap "\C-c\C-l" 'tex-recenter-output-buffer)
- (define-key keymap "\C-c\C-q" 'tex-show-print-queue)
- (define-key keymap "\C-c\C-p" 'tex-print)
- (define-key keymap "\C-c\C-v" 'tex-view)
- )
-
-(defvar tex-mode-map nil "Keymap for TeX mode.")
-
-(if tex-mode-map
- nil
- (setq tex-mode-map (make-sparse-keymap))
- (tex-define-common-keys tex-mode-map)
- (define-key tex-mode-map "\"" 'tex-insert-quote)
- (define-key tex-mode-map "\n" 'tex-terminate-paragraph)
- (define-key tex-mode-map "\C-c}" 'up-list)
- (define-key tex-mode-map "\C-c{" 'tex-insert-braces)
- (define-key tex-mode-map "\C-c\C-r" 'tex-region)
- (define-key tex-mode-map "\C-c\C-b" 'tex-buffer)
- (define-key tex-mode-map "\C-c\C-f" 'tex-file)
- (define-key tex-mode-map "\C-c\C-i" 'tex-bibtex-file)
- (define-key tex-mode-map "\C-c\C-o" 'tex-latex-block)
- (define-key tex-mode-map "\C-c\C-e" 'tex-close-latex-block))
-
-(defvar tex-shell-map nil
- "Keymap for the tex-shell. A shell-mode-map with a few additions.")
-
-;(fset 'TeX-mode 'tex-mode) ;in loaddefs.
-
-;;; This would be a lot simpler if we just used a regexp search,
-;;; but then it would be too slow.
-(defun tex-mode ()
- "Major mode for editing files of input for TeX, LaTeX, or SliTeX.
-Tries to determine (by looking at the beginning of the file) whether
-this file is for plain TeX, LaTeX, or SliTeX and calls plain-tex-mode,
-latex-mode, or slitex-mode, respectively. If it cannot be determined,
-such as if there are no commands in the file, the value of tex-default-mode
-is used."
- (interactive)
- (let (mode slash comment)
- (save-excursion
- (goto-char (point-min))
- (while (and (setq slash (search-forward "\\" nil t))
- (setq comment (let ((search-end (point)))
- (save-excursion
- (beginning-of-line)
- (search-forward "%" search-end t))))))
- (if (and slash (not comment))
- (setq mode (if (looking-at "documentstyle")
- (if (looking-at "documentstyle{slides}")
- 'slitex-mode
- 'latex-mode)
- 'plain-tex-mode))))
- (if mode (funcall mode)
- (funcall tex-default-mode))))
-
-(fset 'plain-TeX-mode 'plain-tex-mode)
-(fset 'LaTeX-mode 'latex-mode)
-
-(defun plain-tex-mode ()
- "Major mode for editing files of input for plain TeX.
-Makes $ and } display the characters they match.
-Makes \" insert `` when it seems to be the beginning of a quotation,
-and '' when it appears to be the end; it inserts \" only after a \\.
-
-Use \\[tex-region] to run TeX on the current region, plus a \"header\"
-copied from the top of the file (containing macro definitions, etc.),
-running TeX under a special subshell. \\[tex-buffer] does the whole buffer.
-\\[tex-file] saves the buffer and then processes the file.
-\\[tex-print] prints the .dvi file made by any of these.
-\\[tex-view] previews the .dvi file made by any of these.
-\\[tex-bibtex-file] runs bibtex on the file of the current buffer.
-
-Use \\[validate-tex-buffer] to check buffer for paragraphs containing
-mismatched $'s or braces.
-
-Special commands:
-\\{tex-mode-map}
-
-Mode variables:
-tex-run-command
- Command string used by \\[tex-region] or \\[tex-buffer].
-tex-directory
- Directory in which to create temporary files for TeX jobs
- run by \\[tex-region] or \\[tex-buffer].
-tex-dvi-print-command
- Command string used by \\[tex-print] to print a .dvi file.
-tex-dvi-view-command
- Command string used by \\[tex-view] to preview a .dvi file.
-tex-show-queue-command
- Command string used by \\[tex-show-print-queue] to show the print
- queue that \\[tex-print] put your job on.
-
-Entering Plain-tex mode calls the value of text-mode-hook, then the value of
-tex-mode-hook, and then the value of plain-tex-mode-hook. When the special
-subshell is initiated, the value of tex-shell-hook is called."
- (interactive)
- (tex-common-initialization)
- (setq mode-name "TeX")
- (setq major-mode 'plain-tex-mode)
- (setq tex-command tex-run-command)
- (setq tex-start-of-header "%**start of header")
- (setq tex-end-of-header "%**end of header")
- (setq tex-trailer "\\bye\n")
- (run-hooks 'text-mode-hook 'tex-mode-hook 'plain-tex-mode-hook))
-
-(defun latex-mode ()
- "Major mode for editing files of input for LaTeX.
-Makes $ and } display the characters they match.
-Makes \" insert `` when it seems to be the beginning of a quotation,
-and '' when it appears to be the end; it inserts \" only after a \\.
-
-Use \\[tex-region] to run LaTeX on the current region, plus the preamble
-copied from the top of the file (containing \\documentstyle, etc.),
-running LaTeX under a special subshell. \\[tex-buffer] does the whole buffer.
-\\[tex-file] saves the buffer and then processes the file.
-\\[tex-print] prints the .dvi file made by any of these.
-\\[tex-view] previews the .dvi file made by any of these.
-\\[tex-bibtex-file] runs bibtex on the file of the current buffer.
-
-Use \\[validate-tex-buffer] to check buffer for paragraphs containing
-mismatched $'s or braces.
-
-Special commands:
-\\{tex-mode-map}
-
-Mode variables:
-latex-run-command
- Command string used by \\[tex-region] or \\[tex-buffer].
-tex-directory
- Directory in which to create temporary files for LaTeX jobs
- run by \\[tex-region] or \\[tex-buffer].
-tex-dvi-print-command
- Command string used by \\[tex-print] to print a .dvi file.
-tex-dvi-view-command
- Command string used by \\[tex-view] to preview a .dvi file.
-tex-show-queue-command
- Command string used by \\[tex-show-print-queue] to show the print
- queue that \\[tex-print] put your job on.
-
-Entering Latex mode calls the value of text-mode-hook, then the value of
-tex-mode-hook, and then the value of latex-mode-hook. When the special
-subshell is initiated, the value of tex-shell-hook is called."
- (interactive)
- (tex-common-initialization)
- (setq mode-name "LaTeX")
- (setq major-mode 'latex-mode)
- (setq tex-command latex-run-command)
- (setq tex-start-of-header "\\documentstyle")
- (setq tex-end-of-header "\\begin{document}")
- (setq tex-trailer "\\end{document}\n")
- (run-hooks 'text-mode-hook 'tex-mode-hook 'latex-mode-hook))
-
-(defun slitex-mode ()
- "Major mode for editing files of input for SliTeX.
-Makes $ and } display the characters they match.
-Makes \" insert `` when it seems to be the beginning of a quotation,
-and '' when it appears to be the end; it inserts \" only after a \\.
-
-Use \\[tex-region] to run SliTeX on the current region, plus the preamble
-copied from the top of the file (containing \\documentstyle, etc.),
-running SliTeX under a special subshell. \\[tex-buffer] does the whole buffer.
-\\[tex-file] saves the buffer and then processes the file.
-\\[tex-print] prints the .dvi file made by any of these.
-\\[tex-view] previews the .dvi file made by any of these.
-\\[tex-bibtex-file] runs bibtex on the file of the current buffer.
-
-Use \\[validate-tex-buffer] to check buffer for paragraphs containing
-mismatched $'s or braces.
-
-Special commands:
-\\{tex-mode-map}
-
-Mode variables:
-slitex-run-command
- Command string used by \\[tex-region] or \\[tex-buffer].
-tex-directory
- Directory in which to create temporary files for SliTeX jobs
- run by \\[tex-region] or \\[tex-buffer].
-tex-dvi-print-command
- Command string used by \\[tex-print] to print a .dvi file.
-tex-dvi-view-command
- Command string used by \\[tex-view] to preview a .dvi file.
-tex-show-queue-command
- Command string used by \\[tex-show-print-queue] to show the print
- queue that \\[tex-print] put your job on.
-
-Entering SliTex mode calls the value of text-mode-hook, then the value of
-tex-mode-hook, then the value of latex-mode-hook, and then the value of
-slitex-mode-hook. When the special subshell is initiated, the value of
-tex-shell-hook is called."
- (interactive)
- (tex-common-initialization)
- (setq mode-name "SliTeX")
- (setq major-mode 'slitex-mode)
- (setq tex-command slitex-run-command)
- (setq tex-start-of-header "\\documentstyle{slides}")
- (setq tex-end-of-header "\\begin{document}")
- (setq tex-trailer "\\end{document}\n")
- (run-hooks
- 'text-mode-hook 'tex-mode-hook 'latex-mode-hook 'slitex-mode-hook))
-
-(defun tex-common-initialization ()
- (kill-all-local-variables)
- (use-local-map tex-mode-map)
- (setq local-abbrev-table text-mode-abbrev-table)
- (if (null tex-mode-syntax-table)
- (let ((char 0))
- (setq tex-mode-syntax-table (make-syntax-table))
- (set-syntax-table tex-mode-syntax-table)
- (while (< char ? )
- (modify-syntax-entry char ".")
- (setq char (1+ char)))
- (modify-syntax-entry ?\C-@ "w")
- (modify-syntax-entry ?\t " ")
- (modify-syntax-entry ?\n ">")
- (modify-syntax-entry ?\f ">")
- (modify-syntax-entry ?$ "$$")
- (modify-syntax-entry ?% "<")
- (modify-syntax-entry ?\\ "/")
- (modify-syntax-entry ?\" ".")
- (modify-syntax-entry ?& ".")
- (modify-syntax-entry ?_ ".")
- (modify-syntax-entry ?@ "_")
- (modify-syntax-entry ?~ " ")
- (modify-syntax-entry ?' "w"))
- (set-syntax-table tex-mode-syntax-table))
- (make-local-variable 'paragraph-start)
- (setq paragraph-start "^[ \t]*$\\|^[\f\\\\%]")
- (make-local-variable 'paragraph-separate)
- (setq paragraph-separate paragraph-start)
- (make-local-variable 'comment-start)
- (setq comment-start "%")
- (make-local-variable 'comment-start-skip)
- (setq comment-start-skip "\\(\\(^\\|[^\\]\\)\\(\\\\\\\\\\)*\\)\\(%+ *\\)")
- (make-local-variable 'comment-indent-hook)
- (setq comment-indent-hook 'tex-comment-indent)
- (make-local-variable 'compare-windows-whitespace)
- (setq compare-windows-whitespace 'tex-categorize-whitespace)
- (make-local-variable 'tex-command)
- (make-local-variable 'tex-start-of-header)
- (make-local-variable 'tex-end-of-header)
- (make-local-variable 'tex-trailer))
-
-(defun tex-comment-indent ()
- (if (looking-at "%%%")
- (current-column)
- (skip-chars-backward " \t")
- (max (if (bolp) 0 (1+ (current-column)))
- comment-column)))
-
-(defun tex-categorize-whitespace (backward-limit)
- ;; compare-windows-whitespace is set to this.
- ;; This is basically a finite-state machine.
- ;; Returns a symbol telling how TeX would treat
- ;; the whitespace we are looking at: null, space, or par.
- (let ((category 'null)
- (not-finished t))
- (skip-chars-backward " \t\n\f" backward-limit)
- (while not-finished
- (cond ((looking-at "[ \t]+")
- (goto-char (match-end 0))
- (if (eql category 'null)
- (setq category 'space)))
- ((looking-at "\n")
- (cond ((eql category 'newline)
- (setq category 'par)
- (setq not-finished nil))
- (t
- (setq category 'newline) ;a strictly internal state
- (goto-char (match-end 0)))))
- ((looking-at "\f+")
- (setq category 'par)
- (setq not-finished nil))
- (t
- (setq not-finished nil))))
- (skip-chars-forward " \t\n\f")
- (if (eql category 'newline)
- 'space ;TeX doesn't distinguish
- category)))
-
-(defun tex-insert-quote (arg)
- "Insert the appropriate quote marks for TeX.
-Inserts the value of tex-open-quote (normally ``) or tex-close-quote
-(normally '') depending on the context. With prefix argument, always
-inserts \" characters."
- (interactive "P")
- (if arg
- (self-insert-command (prefix-numeric-value arg))
- (insert
- (cond ((or (bobp)
- (save-excursion
- (forward-char -1)
- (looking-at "\\s(\\|\\s \\|\\s>")))
- tex-open-quote)
- ((= (preceding-char) ?\\)
- ?\")
- (t
- tex-close-quote)))))
-
-(defun validate-tex-buffer ()
- "Check current buffer for paragraphs containing mismatched $'s.
-As each such paragraph is found, a mark is pushed at its beginning,
-and the location is displayed for a few seconds."
- (interactive)
- (let ((opoint (point)))
- (goto-char (point-max))
- ;; Does not use save-excursion
- ;; because we do not want to save the mark.
- (unwind-protect
- (while (and (not (input-pending-p)) (not (bobp)))
- (let ((end (point)))
- (search-backward "\n\n" nil 'move)
- (or (tex-validate-region (point) end)
- (progn
- (push-mark (point))
- (message "Mismatch found in pararaph starting here")
- (sit-for 4)))))
- (goto-char opoint))))
-
-(defun tex-validate-region (start end)
- "Check for mismatched braces or $'s in region.
-Returns t if no mismatches. Returns nil and moves point to suspect
-area if a mismatch is found."
- (interactive "r")
- (let ((failure-point nil) (max-possible-sexps (- end start)))
- (save-excursion
- (condition-case ()
- (save-restriction
- (narrow-to-region start end)
- (goto-char start)
- (while (< 0 (setq max-possible-sexps (1- max-possible-sexps)))
- (forward-sexp 1)))
- (error
- (setq failure-point (point)))))
- (if failure-point
- (progn
- (goto-char failure-point)
- nil)
- t)))
-
-(defun tex-terminate-paragraph (inhibit-validation)
- "Insert two newlines, breaking a paragraph for TeX.
-Check for mismatched braces/$'s in paragraph being terminated.
-A prefix arg inhibits the checking."
- (interactive "P")
- (or inhibit-validation
- (save-excursion
- (tex-validate-region
- (save-excursion
- (search-backward "\n\n" nil 'move)
- (point))
- (point)))
- (message "Paragraph being closed appears to contain a mismatch"))
- (insert "\n\n"))
-
-(defun tex-insert-braces ()
- "Make a pair of braces and be poised to type inside of them."
- (interactive)
- (insert ?\{)
- (save-excursion
- (insert ?})))
-
-;;; Like tex-insert-braces, but for LaTeX.
-(defun tex-latex-block (name)
- "Creates a matching pair of lines \\begin{NAME} and \\end{NAME} at point.
-Puts point on a blank line between them."
- (interactive "*sLaTeX block name: ")
- (let ((col (current-column)))
- (insert (format "\\begin{%s}\n" name))
- (indent-to col)
- (save-excursion
- (insert ?\n)
- (indent-to col)
- (insert-string (format "\\end{%s}" name))
- (if (eobp) (insert ?\n)))))
-
-(defun tex-last-unended-begin ()
- "Leave point at the beginning of the last \\begin{...} that is unended."
- (while (and (re-search-backward "\\(\\\\begin\\s *{\\)\\|\\(\\\\end\\s *{\\)")
- (looking-at "\\\\end{"))
- (tex-last-unended-begin)))
-
-(defun tex-close-latex-block ()
- "Creates an \\end{...} to match the last unclosed \\begin{...}."
- (interactive "*")
- (let ((new-line-needed (bolp))
- text indentation)
- (save-excursion
- (condition-case ERR
- (tex-last-unended-begin)
- (error (error "Couldn't find unended \\begin")))
- (setq indentation (current-column))
- (re-search-forward "\\\\begin\\(\\s *{[^}\n]*}\\)")
- (setq text (buffer-substring (match-beginning 1) (match-end 1))))
- (indent-to indentation)
- (insert "\\end" text)
- (if new-line-needed (insert ?\n))))
-
-;;; Invoking TeX in an inferior shell.
-
-;;; Why use a shell instead of running TeX directly? Because if TeX
-;;; gets stuck, the user can switch to the shell window and type at it.
-
-;;; The utility functions:
-
-(defun tex-start-shell ()
- (save-excursion
- (set-buffer (make-shell "tex-shell" nil nil "-v"))
- (setq tex-shell-map (copy-keymap shell-mode-map))
- (tex-define-common-keys tex-shell-map)
- (use-local-map tex-shell-map)
- (run-hooks 'tex-shell-hook)
- (if (zerop (buffer-size))
- (sleep-for 1))))
-
-(defun set-buffer-directory (buffer directory)
- "Set BUFFER's default directory to be DIRECTORY."
- (setq directory (file-name-as-directory (expand-file-name directory)))
- (if (not (file-directory-p directory))
- (error "%s is not a directory" directory)
- (save-excursion
- (set-buffer buffer)
- (setq default-directory directory))))
-
-;;; The commands:
-
-;;; It's a kludge that we have to create a special buffer just
-;;; to write out the tex-trailer. It would nice if there were a
-;;; function like write-region that would write literal strings.
-
-(defun tex-region (beg end)
- "Run TeX on the current region, via a temporary file.
-The file's name comes from the variable `tex-zap-file' and the
-variable `tex-directory' says where to put it.
-
-If the buffer has a header, the header is given to TeX before the
-region itself. The buffer's header is all lines between the strings
-defined by `tex-start-of-header' and `tex-end-of-header' inclusive.
-The header must start in the first 100 lines of the buffer.
-
-The value of `tex-trailer' is given to TeX as input after the region.
-
-The value of `tex-command' specifies the command to use to run TeX."
- (interactive "r")
- (if (tex-shell-running)
- (tex-kill-job)
- (tex-start-shell))
- (or tex-zap-file
- (setq tex-zap-file (tex-generate-zap-file-name)))
- (let ((tex-out-file (concat tex-zap-file ".tex"))
- (temp-buffer (get-buffer-create " TeX-Output-Buffer"))
- (file-dir (if (buffer-file-name)
- (file-name-directory (buffer-file-name))
- default-directory))
- (zap-directory
- (file-name-as-directory (expand-file-name tex-directory))))
- ;; Delete any junk files or memory files from this temp file,
- ;; since the contents were probably different last time anyway.
- ;; This may also delete the old temp file if any.
- (let ((list (file-name-all-completions (tex-append tex-out-file ".")
- zap-directory)))
- (while list
- (delete-file (expand-file-name (car list) zap-directory))
- (setq list (cdr list))))
- ;; Write the new temp file.
- (save-excursion
- (save-restriction
- (widen)
- (goto-char (point-min))
- (forward-line 100)
- (let ((search-end (point))
- (hbeg (point-min)) (hend (point-min))
- (default-directory zap-directory))
- (goto-char (point-min))
- ;; Initialize the temp file with either the header or nothing
- (if (search-forward tex-start-of-header search-end t)
- (progn
- (beginning-of-line)
- (setq hbeg (point)) ;mark beginning of header
- (if (search-forward tex-end-of-header nil t)
- (progn (forward-line 1)
- (setq hend (point))) ;mark end of header
- (setq hbeg (point-min))))) ;no header
- (write-region (min hbeg beg) hend tex-out-file nil nil)
- (write-region (max beg hend) end tex-out-file t nil))
- (let ((local-tex-trailer tex-trailer))
- (set-buffer temp-buffer)
- (erase-buffer)
- ;; make sure trailer isn't hidden by a comment
- (insert-string "\n")
- (if local-tex-trailer (insert-string local-tex-trailer))
- (set-buffer-directory temp-buffer zap-directory)
- (write-region (point-min) (point-max) tex-out-file t nil))))
- ;; Record in the shell buffer the file name to delete afterward.
- (save-excursion
- (set-buffer (get-buffer "*tex-shell*"))
- (make-local-variable 'tex-last-temp-file)
- (setq tex-last-temp-file tex-out-file))
- (set-process-filter "tex-shell" 'tex-filter)
- (set-buffer-directory "*tex-shell*" zap-directory)
- ;; Run TeX in source file's dir, in case TEXINPUTS uses current dir.
- (send-string "tex-shell" (concat tex-shell-cd-command " " file-dir "\n"))
- (send-string "tex-shell" (concat tex-command " \""
- zap-directory
- tex-out-file "\"\n")))
- (setq tex-last-buffer-texed (current-buffer))
- (setq tex-print-file
- (concat (file-name-as-directory (expand-file-name tex-directory))
- tex-zap-file))
- (tex-recenter-output-buffer 0))
-
-;; This filter is used in the TeX shell buffer
-;; while TeX is running for a tex-region command.
-(defun tex-filter (process string)
- (let ((old (current-buffer)))
- (set-buffer (process-buffer proc))
- (unwind-protect
- (progn (if (= (process-mark proc) (point-max))
- (insert string)
- (save-excursion
- (goto-char (process-mark proc))
- (insert string)))
- (set-marker (process-mark proc) (point))
- ;; Delete the temporary file
- ;; when TeX finishes.
- ;; And stop using this filter.
- (save-excursion
- (forward-line -1)
- (if (looking-at "^Output written on ")
- (progn
- (set-process-filter process nil)
- ;; Delete the temp file just processed
- ;; and any related junk files made by TeX.
- (let ((list (file-name-all-completions
- (tex-append tex-last-temp-file ".")
- zap-directory)))
- (while list
- (delete-file (expand-file-name
- (car list) zap-directory))
- (setq list (cdr list))))))))
- (or (eq old (current-buffer))
- (set-buffer old)))))
-
-(defun tex-buffer ()
- "Run TeX on current buffer. See \\[tex-region] for more information.
-Does not save the buffer, so it's useful for trying
-experimental versions. See \\[tex-file] for an alternative."
- (interactive)
- (tex-region (point-min) (point-max)))
-
-(defun tex-file ()
- "Prompt to save all buffers and run TeX (or LaTeX) on current buffer's file.
-This function is more useful than \\[tex-buffer] when you need the
-`.aux' file of LaTeX to have the correct name."
- (interactive)
- (let ((tex-out-file
- (if (buffer-file-name)
- (file-name-nondirectory (buffer-file-name))
- (error "Buffer does not seem to be associated with any file")))
- (file-dir (file-name-directory (buffer-file-name))))
- (save-some-buffers)
- (if (tex-shell-running)
- (tex-kill-job)
- (tex-start-shell))
- (set-buffer-directory "*tex-shell*" file-dir)
- (send-string "tex-shell" (concat tex-shell-cd-command " " file-dir "\n"))
- (send-string "tex-shell"
- (concat tex-command " \"" tex-out-file "\"\n")))
- (setq tex-last-buffer-texed (current-buffer))
- (setq tex-print-file (buffer-file-name))
- (tex-recenter-output-buffer 0))
-
-(defun tex-generate-zap-file-name ()
- "Generate a unique name suitable for use as a file name."
- ;; Include the shell process number and host name
- ;; in case there are multiple shells (for same or different user).
- (format "#tz%d%s"
- (process-id (get-buffer-process "*tex-shell*"))
- (tex-strip-dots (system-name))))
-
-(defun tex-strip-dots (s)
- (setq s (copy-sequence s))
- (while (string-match "\\." s)
- (aset s (match-beginning 0) ?-))
- s)
-
-;; This will perhaps be useful for modifying TEXINPUTS.
-;; Expand each file name, separated by colons, in the string S.
-(defun tex-expand-files (s)
- (let (elts (start 0))
- (while (string-match ":" s start)
- (setq elts (cons (substring s start (match-beginning 0)) elts))
- (setq start (match-end 0)))
- (or (= start 0)
- (setq elts (cons (substring s start) elts)))
- (mapconcat 'expand-file-name (nreverse elts) ":")))
-
-(defun tex-shell-running ()
- (and (get-process "tex-shell")
- (eq (process-status (get-process "tex-shell")) 'run)))
-
-(defun tex-kill-job ()
- "Kill the currently running TeX job."
- (interactive)
- (if (get-process "tex-shell")
- (quit-process "tex-shell" t)))
-
-(defun tex-recenter-output-buffer (linenum)
- "Redisplay buffer of TeX job output so that most recent output can be seen.
-The last line of the buffer is displayed on
-line LINE of the window, or centered if LINE is nil."
- (interactive "P")
- (let ((tex-shell (get-buffer "*tex-shell*"))
- (old-buffer (current-buffer)))
- (if (null tex-shell)
- (message "No TeX output buffer")
- (pop-to-buffer tex-shell)
- (bury-buffer tex-shell)
- (goto-char (point-max))
- (recenter (if linenum
- (prefix-numeric-value linenum)
- (/ (window-height) 2)))
- (pop-to-buffer old-buffer)
- )))
-
-(defun tex-print ()
- "Print the .dvi file made by \\[tex-region], \\[tex-buffer] or \\[tex-file].
-Runs the shell command defined by tex-dvi-print-command."
- (interactive)
- (let ((print-file-name-dvi (tex-append tex-print-file ".dvi"))
- test-name)
- (if (and (not (equal (current-buffer) tex-last-buffer-texed))
- (file-newer-than-file-p
- (setq test-name (tex-append (buffer-file-name) ".dvi"))
- (tex-append tex-print-file ".dvi")))
- (setq print-file-name-dvi test-name))
- (if (file-exists-p print-file-name-dvi)
- (shell-command
- (concat tex-dvi-print-command " \"" print-file-name-dvi "&\"\n"))
- (error "No appropriate `.dvi' file could be found"))))
-
-(defun tex-view ()
- "Preview the last `.dvi' file made by running TeX under Emacs.
-This means, made using \\[tex-region], \\[tex-buffer] or \\[tex-file].
-The variable `tex-dvi-view-command' specifies the shell command for preview."
- (interactive)
- (let ((tex-dvi-print-command tex-dvi-view-command))
- (tex-print)))
-
-(defun tex-append (file-name suffix)
- "Append to FILENAME the suffix SUFFIX, using same algorithm TeX uses.
-Scans for the first (not last) period.
-No period is retained immediately before SUFFIX,
-so normally SUFFIX starts with one."
- (if (stringp file-name)
- (let ((file (file-name-nondirectory file-name)))
- (concat (file-name-directory file-name)
- (substring file 0
- (string-match "\\." file))
- suffix))
- " "))
-
-(defun tex-show-print-queue ()
- "Show the print queue that \\[tex-print] put your job on.
-Runs the shell command defined by tex-show-queue-command."
- (interactive)
- (if (tex-shell-running)
- (tex-kill-job)
- (tex-start-shell))
- (send-string "tex-shell" (concat tex-show-queue-command "\n"))
- (tex-recenter-output-buffer nil))
-
-(defun tex-bibtex-file ()
- "Run BibTeX on the current buffer's file."
- (interactive)
- (if (tex-shell-running)
- (tex-kill-job)
- (tex-start-shell))
- (let ((tex-out-file
- (tex-append (file-name-nondirectory (buffer-file-name)) ""))
- (file-dir (file-name-directory (buffer-file-name))))
- (set-buffer-directory "*tex-shell*" file-dir)
- (send-string "tex-shell" (concat tex-shell-cd-command " " file-dir "\n"))
- (send-string "tex-shell"
- (concat tex-bibtex-command " \"" tex-out-file "\"\n")))
- (tex-recenter-output-buffer 0))
-
diff --git a/lisp/textmodes/texinfo.el b/lisp/textmodes/texinfo.el
deleted file mode 100644
index ebe0769a71c..00000000000
--- a/lisp/textmodes/texinfo.el
+++ /dev/null
@@ -1,414 +0,0 @@
-;;;; texinfo.el
-;;;; Major mode for editing Texinfo files.
-
-;;;; Version 2.00 14 Dec 1990
-
-;; Copyright (C) 1985, 1988, 1989, 1990 Free Software Foundation, Inc.
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 1, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
-(require 'texnfo-upd)
-(require 'tex-mode)
-(provide 'texinfo)
-
-(defvar texinfo-mode-syntax-table nil)
-
-(if texinfo-mode-syntax-table
- nil
- (setq texinfo-mode-syntax-table (make-syntax-table))
- (modify-syntax-entry ?\" " " texinfo-mode-syntax-table)
- (modify-syntax-entry ?\\ " " texinfo-mode-syntax-table)
- (modify-syntax-entry ?@ "\\" texinfo-mode-syntax-table)
- (modify-syntax-entry ?\^q "\\" texinfo-mode-syntax-table)
- (modify-syntax-entry ?\[ "(]" texinfo-mode-syntax-table)
- (modify-syntax-entry ?\] ")[" texinfo-mode-syntax-table)
- (modify-syntax-entry ?{ "(}" texinfo-mode-syntax-table)
- (modify-syntax-entry ?} "){" texinfo-mode-syntax-table)
- (modify-syntax-entry ?\' "w" texinfo-mode-syntax-table))
-
-(defvar texinfo-mode-map nil)
-
-;; Mode documentation displays commands in reverse order
-;; from how they are listed in the texinfo-mode-map.
-(if texinfo-mode-map
- nil
- (setq texinfo-mode-map (make-sparse-keymap))
-
- (define-key texinfo-mode-map "\C-c\C-t\C-k" 'tex-kill-job)
- (define-key texinfo-mode-map "\C-c\C-t\C-l" 'tex-recenter-output-buffer)
- (define-key texinfo-mode-map "\C-c\C-t\C-q" 'tex-show-print-queue)
- (define-key texinfo-mode-map "\C-c\C-t\C-p" 'texinfo-tex-print)
- (define-key texinfo-mode-map "\C-c\C-t\C-i" 'texinfo-texindex)
- (define-key texinfo-mode-map "\C-c\C-t\C-t" 'texinfo-tex-buffer)
- (define-key texinfo-mode-map "\C-c\C-t\C-r" 'texinfo-tex-region)
-
- (define-key texinfo-mode-map "\C-c\C-i\C-r" 'texinfo-format-region)
- (define-key texinfo-mode-map "\C-c\C-i\C-b" 'texinfo-format-buffer)
-
- (define-key texinfo-mode-map "\C-c\C-u\C-m" 'texinfo-make-menu)
- (define-key texinfo-mode-map "\C-c\C-u\C-n" 'texinfo-update-node)
- (define-key texinfo-mode-map "\C-c\C-u\C-e" 'texinfo-every-node-update)
- (define-key texinfo-mode-map "\C-c\C-u\C-a" 'texinfo-all-menus-update)
-
- (define-key texinfo-mode-map "\C-c\C-s" 'texinfo-show-structure)
-
- (define-key texinfo-mode-map "\"" 'tex-insert-quote)
- (define-key texinfo-mode-map "\e}" 'up-list)
- (define-key texinfo-mode-map "\e{" 'texinfo-insert-braces)
-
- (define-key texinfo-mode-map "\C-c\C-cv" 'texinfo-insert-@var)
- (define-key texinfo-mode-map "\C-c\C-cs" 'texinfo-insert-@samp)
- (define-key texinfo-mode-map "\C-c\C-co" 'texinfo-insert-@noindent)
- (define-key texinfo-mode-map "\C-c\C-cn" 'texinfo-insert-@node)
- (define-key texinfo-mode-map "\C-c\C-ck" 'texinfo-insert-@kbd)
- (define-key texinfo-mode-map "\C-c\C-ci" 'texinfo-insert-@item)
- (define-key texinfo-mode-map "\C-c\C-cx" 'texinfo-insert-@example)
- (define-key texinfo-mode-map "\C-c\C-ce" 'texinfo-insert-@end-example)
- (define-key texinfo-mode-map "\C-c\C-cd" 'texinfo-insert-@dfn)
- (define-key texinfo-mode-map "\C-c\C-cc" 'texinfo-insert-@code))
-
-(defun texinfo-insert-@var ()
- "Insert the string @var in a texinfo buffer."
- (interactive)
- (insert "@var{}")
- (backward-char))
-
-(defun texinfo-insert-@samp ()
- "Insert the string @samp in a texinfo buffer."
- (interactive)
- (insert "@samp{}")
- (backward-char))
-
-(defun texinfo-insert-@noindent ()
- "Insert the string @noindent in a texinfo buffer."
- (interactive)
- (insert "@noindent\n"))
-
-(defun texinfo-insert-@node ()
- "Insert the string @node in a texinfo buffer,
-along with a comment indicating the arguments to @node."
- (interactive)
- (insert "@node \n@comment node-name, next, previous, up")
- (forward-line -1)
- (forward-char 6))
-
-(defun texinfo-insert-@kbd ()
- "Insert the string @kbd in a texinfo buffer."
- (interactive)
- (insert "@kbd{}")
- (backward-char))
-
-(defun texinfo-insert-@item ()
- "Insert the string @item in a texinfo buffer."
- (interactive)
- (insert "@item")
- (newline))
-
-(defun texinfo-insert-@example ()
- "Insert the string @example in a texinfo buffer."
- (interactive)
- (insert "@example\n"))
-
-(defun texinfo-insert-@end-example ()
- "Insert the string @end example in a texinfo buffer."
- (interactive)
- (insert "@end example\n"))
-
-(defun texinfo-insert-@dfn ()
- "Insert the string @dfn in a texinfo buffer."
- (interactive)
- (insert "@dfn{}")
- (backward-char))
-
-(defun texinfo-insert-@code ()
- "Insert the string @code in a texinfo buffer."
- (interactive)
- (insert "@code{}")
- (backward-char))
-
-(defun texinfo-insert-braces ()
- "Make a pair of braces and be poised to type inside of them.
-Use \\[up-list] to move forward out of the braces."
- (interactive)
- (insert "{}")
- (backward-char))
-
-(defun texinfo-mode ()
- "Major mode for editing Texinfo files.
-
- It has these extra commands:
-\\{texinfo-mode-map}
-
- These are files that are used as input for TeX to make printed manuals
-and also to be turned into Info files by \\[texinfo-format-buffer] or
-`makeinfo'. These files must be written in a very restricted and
-modified version of TeX input format.
-
- Editing commands are like text-mode except that the syntax table is
-set up so expression commands skip Texinfo bracket groups. To see
-what the Info version of a region of the Texinfo file will look like,
-use \\[texinfo-format-region]. This command runs Info on the current region
-of the Texinfo file and formats it properly.
-
- You can show the structure of a Texinfo file with \\[texinfo-show-structure].
-This command shows the structure of a Texinfo file by listing the
-lines with the @-sign commands for @chapter, @section, and the like.
-These lines are displayed in another window called the *Occur* window.
-In that window, you can position the cursor over one of the lines and
-use \\[occur-mode-goto-occurrence], to jump to the corresponding spot
-in the Texinfo file.
-
- In addition, Texinfo mode provides commands that insert various
-frequently used @-sign commands into the buffer. You can use these
-commands to save keystrokes. And you can insert balanced braces with
-\\[texinfo-insert-braces] and later use the command \\[up-list] to
-move forward past the closing brace.
-
-Also, Texinfo mode provides functions for automatically creating or
-updating menus and node pointers. These functions
-
- * insert the `Next', `Previous' and `Up' pointers of a node,
- * insert or update the menu for a section, and
- * create a master menu for a Texinfo source file.
-
-Here are the functions:
-
- texinfo-update-node \\[texinfo-update-node]
- texinfo-every-node-update \\[texinfo-every-node-update]
- texinfo-sequential-node-update
-
- texinfo-make-menu \\[texinfo-make-menu]
- texinfo-all-menus-update \\[texinfo-all-menus-update]
- texinfo-master-menu
-
- texinfo-indent-menu-description (column &optional region-p)
-
-The `texinfo-column-for-description' variable specifies the column to
-which menu descriptions are indented.
-
-Passed an argument (a prefix argument, if interactive), the
-`texinfo-update-node' and `texinfo-make-menu' functions do their jobs
-in the region.
-
-To use the updating commands, you must structure your Texinfo file
-hierarchically, such that each `@node' line, with the exception of the
-Top node, is accompanied by some kind of section line, such as an
-`@chapter' or `@section' line.
-
-If the file has a `top' node, it must be called `top' or `Top' and
-be the first node in the file.
-
-Entering Texinfo mode calls the value of text-mode-hook, and then the
-value of texinfo-mode-hook."
- (interactive)
- (text-mode)
- (setq mode-name "texinfo")
- (setq major-mode 'texinfo-mode)
- (use-local-map texinfo-mode-map)
- (set-syntax-table texinfo-mode-syntax-table)
- (make-local-variable 'require-final-newline)
- (setq require-final-newline t)
- (make-local-variable 'paragraph-separate)
- (setq paragraph-separate (concat "^\b\\|^@[a-zA-Z]*[ \n]\\|" paragraph-separate))
- (make-local-variable 'paragraph-start)
- (setq paragraph-start (concat "^\b\\|^@[a-zA-Z]*[ \n]\\|" paragraph-start))
- (make-local-variable 'fill-column)
- (setq fill-column 72)
- (make-local-variable 'comment-start)
- (setq comment-start "@c ")
- (make-local-variable 'comment-start-skip)
- (setq comment-start-skip "@c +")
- (make-local-variable 'words-include-escapes)
- (setq words-include-escapes t)
- (make-local-variable 'tex-start-of-header)
- (setq tex-start-of-header "%**start of header")
- (make-local-variable 'tex-end-of-header)
- (setq tex-end-of-header "%**end of header")
- (make-local-variable 'tex-trailer)
- (setq tex-trailer "@bye\n")
- (run-hooks 'text-mode-hook 'texinfo-mode-hook))
-
-
-;;; Texinfo file structure
-
-; The following is defined in `texnfo-upd.el'
-; (defvar texinfo-section-types-regexp
-; "^@\\(chapter \\|sect\\|sub\\|unnum\\|major\\|heading \\|appendix\\)"
-; "Regexp matching chapter, section, other headings (but not the top node).")
-
-(defun texinfo-show-structure (&optional nodes-too)
- "Show the structure of a Texinfo file.
-List the lines in the file that begin with the @-sign commands for
-@chapter, @section, and the like.
-
-With optional argument (prefix if interactive), list both the lines
-with @-sign commands for @chapter, @section, and the like, and list
-@node lines.
-
-Lines with structuring commands beginning in them are displayed in
-another window called the *Occur* window. In that window, you can
-position the cursor over one of the lines and use
-\\[occur-mode-goto-occurrence],
-to jump to the corresponding spot in the Texinfo file."
-
- (interactive "P")
- (save-excursion
- (goto-char (point-min))
- (if nodes-too
- (occur (concat "\\(^@node\\)\\|" texinfo-section-types-regexp))
- (occur texinfo-section-types-regexp)))
- (pop-to-buffer "*Occur*")
- (goto-char (point-min))
- (flush-lines "-----"))
-
-
-;;; texinfo mode tex and hardcopy printing commands.
-
-;; These commands are for running tex on a region of a texinfo file in
-;; GNU Emacs, or on the whole buffer, and for printing the resulting
-;; .dvi file. The three commands are:
-
-; texinfo-tex-region to run tex on the current region.
-; texinfo-tex-buffer to run tex on the current buffer.
-; texinfo-tex-print to print the .dvi file made by tex
-
-;;; Other useful functions
-
-; These functions are provided by `tex-mode.el' but are bound to keys
-; in texinfo mode.
-
-; tex-kill-job to kill the currently running tex job
-; tex-recenter-output-buffer to redisplay tex job output buffer
-; tex-show-print-queue to show the print queue
-
-; Various variables are provided by `tex-mode.el'
-
-; tex mode variable Default Value
-
-; tex-dvi-print-command "lpr -d"
-; tex-directory "/tmp/"
-; tex-show-queue-command "lpq"
-; tex-shell-cd-command "cd"
-; tex-zap-file nil (created as needed)
-
-
-;;; The tex and print function definitions:
-
-(defvar texinfo-tex-command "tex"
- "*Command used by texinfo-tex-region to run tex on a region.")
-
-(defvar texinfo-texindex-command "texindex"
- "*Command used by texinfo-texindex to sort unsorted index files.")
-
-(defun texinfo-tex-region (beg end)
- "Run tex on the current region. A temporary file (tex-zap-file) is
-written in directory tex-directory, and tex is run in that directory.
-The first line of the file is copied to the temporary file; and
-if the buffer has a header, it is written to the temporary file before
-the region itself. The buffer's header is all lines between the
-strings defined by tex-start-of-header and tex-end-of-header
-inclusive. The header must start in the first 100 lines. The value
-of tex-trailer is appended to the temporary file after the region."
- (interactive "r")
- (if (get-buffer "*tex-shell*")
- (tex-kill-job)
- (tex-start-shell))
- (or tex-zap-file (setq tex-zap-file (make-temp-name "#tz")))
- (let ((tex-out-file (concat tex-zap-file ".tex"))
- (temp-buffer (get-buffer-create " tex-Output-Buffer"))
- (zap-directory
- (file-name-as-directory (expand-file-name tex-directory))))
- (save-excursion
- (save-restriction
- (widen)
- (goto-char (point-min))
- (forward-line 100)
- (let ((search-end (point))
- (hbeg (point-min)) (hend (point-min))
- (default-directory zap-directory))
- (goto-char (point-min))
-
- ;; Copy first line, the `\input texinfo' line, to temp file
- (write-region (point)
- (save-excursion (end-of-line) (point))
- tex-out-file nil nil)
-
- ;; Don't copy first line twice if region includes it.
- (forward-line 1)
- (if (< beg (point)) (setq beg (point)))
-
- ;; Initialize the temp file with either the header or nothing
- (if (search-forward tex-start-of-header search-end t)
- (progn
- (beginning-of-line)
- (setq hbeg (point)) ; Mark beginning of header.
- (if (search-forward tex-end-of-header nil t)
- (progn (beginning-of-line)
- (setq hend (point))) ; Mark end of header.
- (setq hbeg (point-min))))) ; Else no header.
-
- ;; Copy header to temp file.
- (write-region (min hbeg beg) hend tex-out-file t nil)
-
- ;; Copy region to temp file.
- (write-region (max beg hend) end tex-out-file t nil))
-
- ;; This is a kludge to insert the tex-trailer into the tex-out-file.
- ;; We have to create a special buffer in which to insert
- ;; the tex-trailer first because there is no function with
- ;; which to append a literal string directly to a file.
- (let ((local-tex-trailer tex-trailer))
- (set-buffer temp-buffer)
- (erase-buffer)
- ;; make sure trailer isn't hidden by a comment
- (insert-string "\n")
- (if local-tex-trailer (insert-string local-tex-trailer))
- (set-buffer-directory temp-buffer zap-directory)
- (write-region (point-min) (point-max) tex-out-file t nil))))
-
- (set-buffer-directory "*tex-shell*" zap-directory)
- (send-string "tex-shell" (concat tex-shell-cd-command " "
- zap-directory "\n"))
- (send-string "tex-shell" (concat texinfo-tex-command " "
- tex-out-file "\n")))
- (tex-recenter-output-buffer 0))
-
-(defun texinfo-tex-buffer ()
- "Run tex on current buffer.
-See \\[texinfo-tex-region] for more information."
- (interactive)
- (texinfo-tex-region (point-min) (point-max)))
-
-(defun texinfo-texindex ()
- "Run texindex on unsorted index files.
-The index files are made by \\[texinfo-tex-region] or \\[texinfo-tex-buffer].
-Runs the shell command defined by texinfo-texindex-command."
- (interactive)
- (send-string "tex-shell"
- (concat texinfo-texindex-command
- " " tex-zap-file ".??" "\n"))
- (tex-recenter-output-buffer nil))
-
-(defun texinfo-tex-print ()
- "Print .dvi file made by \\[texinfo-tex-region] or \\[texinfo-tex-buffer].
-Runs the shell command defined by tex-dvi-print-command."
- (interactive)
- (send-string "tex-shell"
- (concat tex-dvi-print-command
- " " tex-zap-file ".dvi" "\n"))
- (tex-recenter-output-buffer nil))
-
diff --git a/lisp/textmodes/texnfo-upd.el b/lisp/textmodes/texnfo-upd.el
deleted file mode 100644
index c236d791846..00000000000
--- a/lisp/textmodes/texnfo-upd.el
+++ /dev/null
@@ -1,1726 +0,0 @@
-;;;; texnfo-upd.el
-;;;; A utility for updating nodes and menus in Texinfo files.
-
-;;;; Version 2.00 14 Dec 1990
-
-;;;; Copyright 1989, 1990 Free Software Foundation
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 1, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
-(provide 'texnfo-upd)
-
-
-;;;; Summary
-
-; (Much of the following commentary ought eventually be incorporated
-; into the Texinfo Manual.)
-
-; The node and menu updating functions automatically
-
-; * insert missing `@node' lines,
-; * insert the `Next', `Previous' and `Up' pointers of a node,
-; * insert or update the menu for a section,
-; * create a master menu for a Texinfo source file.
-
-; Passed an argument, the `texinfo-update-node' and
-; `texinfo-make-menu' functions do their jobs in the region.
-
-; These functions replace doing these jobs by hand.
-; You may find them helpful.
-
-; In brief, the functions for creating or updating nodes and menus, are:
-;
-; texinfo-update-node (&optional region-p)
-; texinfo-every-node-update ()
-; texinfo-sequential-node-update (&optional region-p)
-;
-; texinfo-make-menu (&optional region-p)
-; texinfo-all-menus-update ()
-; texinfo-master-menu ()
-;
-; texinfo-insert-node-lines (&optional title-p)
-;
-; texinfo-indent-menu-description (column &optional region-p)
-
-; The `texinfo-column-for-description' variable specifies the column to
-; which menu descriptions are indented.
-
-; Texinfo file structure
-; ----------------------
-
-; To use the updating commands, you must structure your Texinfo file
-; hierarchically. Each `@node' line, with the exception of the top
-; node, must be accompanied by some kind of section line, such as an
-; `@chapter' or `@section' line. Each node-line/section-line
-; combination must look like this:
-
-; @node Lists and Tables, Cross References, Structuring, Top
-; @comment node-name, next, previous, up
-; @chapter Making Lists and Tables
-
-; or like this (without the `@comment' line):
-
-; @node Lists and Tables, Cross References, Structuring, Top
-; @chapter Making Lists and Tables
-
-; If the file has a `top' node, it must be called `top' or `Top' and
-; be the first node in the file.
-
-
-;;;; The updating functions in detail
-; --------------------------------
-
-; The `texinfo-update-node' function without an argument inserts
-; the correct next, previous and up pointers for the node in which
-; point is located (i.e., for the node preceding point).
-
-; With an argument, the `texinfo-update-node' function inserts the
-; correct next, previous and up pointers for the nodes inside the
-; region.
-
-; It does not matter whether the `@node' line has pre-existing
-; `Next', `Previous', or `Up' pointers in it. They are removed.
-
-; The `texinfo-every-node-update' function runs `texinfo-update-node'
-; on the whole buffer.
-
-; The `texinfo-update-node' function inserts the immediately following
-; and preceding node into the `Next' or `Previous' pointers regardless
-; of their hierarchical level. This is only useful for certain kinds
-; of text, like a novel, which you go through sequentially.
-
-; The `texinfo-make-menu' function without an argument creates or
-; updates a menu for the section encompassing the node that follows
-; point. With an argument, it makes or updates menus for the nodes
-; within or part of the marked region.
-
-; Whenever an existing menu is updated, the descriptions from
-; that menu are incorporated into the new menu. This is done by copying
-; descriptions from the existing menu to the entries in the new menu
-; that have the same node names. If the node names are different, the
-; descriptions are not copied to the new menu.
-
-; Menu entries that refer to other Info files are removed since they
-; are not a node within current buffer. This is a deficiency.
-
-; The `texinfo-all-menus-update' function runs `texinfo-make-menu'
-; on the whole buffer.
-
-; The `texinfo-master-menu' function creates an extended menu located
-; after the top node. (The file must have a top node.) The function
-; first updates all the regular menus in the buffer (incorporating the
-; descriptions from pre-existing menus), and then constructs a master
-; menu that includes every entry from every other menu. (However, the
-; function cannot update an already existing master menu; if one
-; exists, it must be removed before calling the function.)
-
-; The `texinfo-indent-menu-description' function indents every
-; description in the menu following point, to the specified column.
-; Non-nil argument (prefix, if interactive) means indent every
-; description in every menu in the region. This function does not
-; indent second and subsequent lines of a multi-line description.
-
-; The `texinfo-insert-node-lines' function inserts `@node' before the
-; `@chapter', `@section', and such like lines of a region in a Texinfo
-; file where the `@node' lines are missing.
-;
-; With a non-nil argument (prefix, if interactive), the function not
-; only inserts `@node' lines but also inserts the chapter or section
-; titles as the names of the corresponding nodes; and inserts titles
-; as node names in pre-existing `@node' lines that lack names.
-;
-; Since node names should be more concise than section or chapter
-; titles, node names so inserted will need to be edited manually.
-
-
-;;;; Menu Making Functions
-
-(defun texinfo-make-menu (&optional region-p)
- "Without any prefix argument, make or update a menu.
-Make the menu for the section enclosing the node found following point.
-
-Non-nil argument (prefix, if interactive) means make or update menus
-for nodes within or part of the marked region.
-
-Whenever a menu exists, and is being updated, the descriptions that
-are associated with node names in the pre-existing menu are
-incorporated into the new menu. Otherwise, the nodes' section titles
-are inserted as descriptions."
-
- (interactive "P")
- (if (not region-p)
- (let ((level (texinfo-hierarchic-level)))
- (texinfo-make-one-menu level)
- (message "Done...updated the menu. You may save the buffer."))
- ;; else
- (message "Making or updating menus... ")
- (let ((beginning (region-beginning))
- (region-end (region-end))
- (level (progn ; find section type following point
- (goto-char (region-beginning))
- (texinfo-hierarchic-level))))
- (if (= region-end beginning)
- (error "Please mark a region!"))
- (save-excursion
- (save-restriction
- (widen)
-
- (while (texinfo-find-lower-level-node level region-end)
- (setq level (texinfo-hierarchic-level)) ; new, lower level
- (texinfo-make-one-menu level))
-
- (while (and (< (point) region-end)
- (texinfo-find-higher-level-node level region-end))
- (setq level (texinfo-hierarchic-level))
- (while (texinfo-find-lower-level-node level region-end)
- (setq level (texinfo-hierarchic-level)) ; new, lower level
- (texinfo-make-one-menu level))))))
- (message "Done...updated menus. You may save the buffer.")))
-
-(defun texinfo-make-one-menu (level)
- "Make a menu of all the appropriate nodes in this section.
-`Appropriate nodes' are those associated with sections that are
-at the level specified by LEVEL. Point is left at the end of menu."
- (let*
- ((case-fold-search t)
- (beginning
- (save-excursion
- (goto-char (texinfo-update-menu-region-beginning level))
- (end-of-line)
- (point)))
- (end (texinfo-update-menu-region-end level))
- (first (texinfo-menu-first-node beginning end))
- (node-name (progn
- (goto-char beginning)
- (texinfo-copy-node-name)))
- (new-menu-list (texinfo-make-menu-list beginning end level)))
- (if (texinfo-old-menu-p beginning first)
- (progn
- (texinfo-incorporate-descriptions new-menu-list)
- (texinfo-delete-old-menu beginning first)))
- (texinfo-insert-menu new-menu-list node-name)))
-
-(defun texinfo-all-menus-update (&optional update-all-nodes-p)
- "Update every regular menu in a Texinfo file.
-You must remove the detailed part of a pre-existing master menu before
-running this command, lest it be partly duplicated.
-
-If called with a non-nil argument, this function first updates all the
-nodes in the buffer before updating the menus."
- (interactive "P")
- (save-excursion
- (mark-whole-buffer)
- (message "Checking for a master menu... ")
- (save-excursion
- (if (re-search-forward texinfo-master-menu-header nil t)
- (error
- "Please remove existing master menu, lest it be partly duplicated!")))
-
- (if update-all-nodes-p
- (progn
- (message "First updating all nodes... ")
- (sleep-for 2)
- (mark-whole-buffer)
- (texinfo-update-node t)))
-
- (message "Updating all menus... ")
- (sleep-for 2)
- (texinfo-make-menu t)
- (message "Done...updated all the menus. You may save the buffer.")))
-
-(defun texinfo-find-lower-level-node (level region-end)
- "Search forward from point for node at any level lower than LEVEL.
-Search is limited to the end of the marked region, REGION-END,
-and to the end of the menu region for the level.
-
-Return t if the node is found, else nil. Leave point at the beginning
-of the node if one is found; else do not move point."
-
- (if (and (< (point) region-end)
- (re-search-forward
- (concat
- "\\(^@node\\).*\n" ; match node line
- "\\(\\(\\(^@c\\).*\n\\)" ; match comment line, if any
- "\\|" ; or
- "\\(^@ifinfo[ ]*\n\\)\\)?" ; ifinfo line, if any
- (eval (cdr (assoc level texinfo-update-menu-lower-regexps))))
- ;; the next higher level node marks the end of this
- ;; section, and no lower level node will be found beyond
- ;; this position even if region-end is farther off
- (texinfo-update-menu-region-end level)
- t))
- (goto-char (match-beginning 1))))
-
-(defun texinfo-find-higher-level-node (level region-end)
- "Search forward from point for node at any higher level than argument LEVEL.
-Search is limited to the end of the marked region, REGION-END.
-
-Return t if the node is found, else nil. Leave point at the beginning
-of the node if one is found; else do not move point."
-
- (if (and (< (point) region-end)
- (re-search-forward
- (concat
- "\\(^@node\\).*\n" ; match node line
- "\\(\\(\\(^@c\\).*\n\\)" ; match comment line, if any
- "\\|" ; or
- "\\(^@ifinfo[ ]*\n\\)\\)?" ; ifinfo line, if any
- (eval ; (won't ever find a `top' node)
- (cdr (assoc level texinfo-update-menu-higher-regexps))))
- nil
- t))
- (goto-char (match-beginning 1))))
-
-
-;;;; Making the list of new menu entries
-
-(defun texinfo-make-menu-list (beginning end level)
- "Make a list of node names and their descriptions.
-Point is left at the end of the menu region, but the menu is not inserted.
-
-First argument is position from which to start making menu list;
-second argument is end of region in which to try to locate entries;
-third argument is the level of the nodes that are the entries.
-
-Node names and descriptions are dotted pairs of strings. Each pair is
-an element of the list. If the description does not exist, the
-element consists only of the node name."
- (goto-char beginning)
- (let (new-menu-list)
- (while (texinfo-menu-locate-entry-p level end)
- (setq new-menu-list
- (cons (cons
- (texinfo-copy-node-name)
- (texinfo-copy-section-title))
- new-menu-list)))
- (reverse new-menu-list)))
-
-(defun texinfo-menu-locate-entry-p (level search-end)
- "Find a node that will be part of menu for this section.
-First argument is a string such as \"section\" specifying the general
-hierarchical level of the menu; second argument is a postion
-specifying the end of the search.
-
-The function returns t if the node is found, else nil. It searches
-forward from point, and leaves point at the beginning of the node.
-
-The function finds entries of the same type. Thus `subsections' and
-`unnumberedsubsecs' will appear in the same menu."
- (if (re-search-forward
- (concat
- "\\(^@node\\).*\n" ; match node line
- "\\(\\(\\(^@c\\).*\n\\)" ; match comment line, if any
- "\\|" ; or
- "\\(^@ifinfo[ ]*\n\\)\\)?" ; ifinfo line, if any
- (eval
- (cdr (assoc level texinfo-update-menu-same-level-regexps))))
- search-end
- t)
- (goto-char (match-beginning 1))))
-
-(defun texinfo-copy-node-name ()
- "Return the node name as a string.
-
-Start with point at the beginning of the node line; copy the text
-after the node command up to the first comma on the line, if any, and
-return the text as a string. Leaves point at the beginning of the
-line. If there is no node name, returns an empty string."
-
- (save-excursion
- (buffer-substring
- (progn (forward-word 1) ; skip over node command
- (skip-chars-forward " \t") ; and over spaces
- (point))
- (if (search-forward
- ","
- (save-excursion (end-of-line) (point)) t) ; bound search
- (1- (point))
- (end-of-line) (point)))))
-
-(defun texinfo-copy-section-title ()
- "Return the title of the section as a string.
-The title is used as a description line in the menu when one does not
-already exist.
-
-Move point to the beginning of the appropriate section line by going
-to the start of the text matched by last regexp searched for, which
-must have been done by `texinfo-menu-locate-entry-p'."
-
- ;; could use the same re-search as in `texinfo-menu-locate-entry-p'
- ;; instead of using `match-beginning'; such a variation would be
- ;; more general, but would waste information already collected
-
- (goto-char (match-beginning 7)) ; match section name
-
- (buffer-substring
- (progn (forward-word 1) ; skip over section type
- (skip-chars-forward " \t") ; and over spaces
- (point))
- (progn (end-of-line) (point))))
-
-
-;;;; Handling the old menu
-
-(defun texinfo-old-menu-p (beginning first)
- "Move point to the beginning of the menu for this section, if any.
-Otherwise move point to the end of the first node of this section.
-Return t if a menu is found, nil otherwise.
-
-First argument is the position of the beginning of the section in which
-the menu will be located; second argument is the position of the first
-node within the section.
-
-If no menu is found, the function inserts two newlines just before the
-end of the section, and leaves point there where a menu ought to be."
- (goto-char beginning)
- (if (not (re-search-forward "^@menu" first 'goto-end))
- (progn (insert "\n\n") (forward-line -2) nil)
- t))
-
-(defun texinfo-incorporate-descriptions (new-menu-list)
- "Copy the old menu line descriptions that exist to the new menu.
-
-Point must be at beginning of old menu.
-
-If the node-name of the new menu entry cannot be found in the old
-menu, use the new section title for the description, but if the
-node-name of the new menu is found in the old menu, replace the
-section title with the old description, whatever it may be.
-
-For this function, the new menu is a list made up of lists of dotted
-pairs in which the first element of the pair is the node name and the
-second element the description. The new menu is changed destructively.
-The old menu is the menu as it appears in the texinfo file."
-
- (let ((new-menu-list-pointer new-menu-list)
- (end-of-menu (texinfo-menu-end)))
- (while new-menu-list
- (save-excursion ; keep point at beginning of menu
- (if (search-forward
- (concat "\* " ; so only menu entries are found
- (car (car new-menu-list))
- ":") ; so only complete entries are found
- end-of-menu
- t)
- (setcdr (car new-menu-list)
- (texinfo-menu-copy-old-description end-of-menu))))
- (setq new-menu-list (cdr new-menu-list)))
- (setq new-menu-list new-menu-list-pointer)))
-
-(defun texinfo-menu-copy-old-description (end-of-menu)
- "Return description field of old menu line as string.
-Point must be located just after the node name. Point left before description.
-Single argument, END-OF-MENU, is position limiting search."
- (skip-chars-forward "[:.,\t\n ]+")
- ;; don't copy a carriage return at line beginning with asterisk!
- ;; do copy a description that begins with an `@'!
- (if (and (looking-at "\\(\\w+\\|@\\)")
- (not (looking-at "\\(^\\* \\|^@end menu\\)")))
- (buffer-substring
- (point)
- (save-excursion
- (re-search-forward "\\(^\\* \\|^@end menu\\)" end-of-menu t)
- (forward-line -1)
- (end-of-line) ; go to end of last description line
- (point)))
- ""))
-
-(defun texinfo-menu-end ()
- "Return position of end of menu. Does not change location of point.
-Signal an error if not end of menu."
- (save-excursion
- (if (re-search-forward "^@end menu" nil t)
- (point)
- (error "Menu does not have an end."))))
-
-(defun texinfo-delete-old-menu (beginning first)
- "Delete the old menu. Point must be in or after menu.
-First argument is position of the beginning of the section in which
-the menu will be located; second argument is the position of the first
-node within the section."
- ;; No third arg to search, so error if search fails.
- (re-search-backward "^@menu" beginning)
- (delete-region (point)
- (save-excursion
- (re-search-forward "^@end menu" first)
- (point))))
-
-
-;;;; Inserting new menu
-
-;; try 32, but perhaps 24 is better
-(defvar texinfo-column-for-description 32
- "*Column at which descriptions start in a Texinfo menu.")
-
-(defun texinfo-insert-menu (menu-list node-name)
- "Insert formatted menu at point.
-Indents the first line of the description, if any, to the value of
-texinfo-column-for-description.
-
-MENU-LIST has form:
-
- \(\(\"node-name1\" . \"description\"\)
- \(\"node-name\" . \"description\"\) ... \)
-
-However, there does not need to be a description field."
-
- (insert "@menu\n")
- (while menu-list
- (if (cdr (car menu-list)) ; menu-list has description entry
- (progn
- (insert
- (format "* %s::" (car (car menu-list)))) ; node-name entry
- (indent-to texinfo-column-for-description 2)
- (insert
- (format "%s\n" (cdr (car menu-list))))) ; description entry
- ;; else menu-list lacks description entry
- (insert
- (format "* %s::\n" (car (car menu-list))))) ; node-name entry
- (setq menu-list (cdr menu-list)))
- (insert "@end menu")
- (message
- "Updated \"%s\" level menu following node: %s ... "
- level node-name))
-
-
-;;;; Handling description indentation
-
-; Since the make-menu functions indent descriptions, these functions
-; are useful primarily for indenting a single menu specially.
-
-(defun texinfo-indent-menu-description (column &optional region-p)
- "Indent every description in menu following point to COLUMN.
-Non-nil argument (prefix, if interactive) means indent every
-description in every menu in the region. Does not indent second and
-subsequent lines of a multi-line description."
-
- (interactive
- "nIndent menu descriptions to (column number): \nP")
- (save-excursion
- (save-restriction
- (widen)
- (if (not region-p)
- (progn
- (re-search-forward "^@menu")
- (texinfo-menu-indent-description column)
- (message
- "Indented descriptions in menu. You may save the buffer."))
- ;;else
- (message "Indenting every menu description in region... ")
- (goto-char (region-beginning))
- (while (and (< (point) (region-end))
- (texinfo-locate-menu-p))
- (forward-line 1)
- (texinfo-menu-indent-description column))
- (message "Indenting done. You may save the buffer.")))))
-
-(defun texinfo-menu-indent-description (to-column-number)
- "Indent the Texinfo file menu description to TO-COLUMN-NUMBER.
-Start with point just after the word `menu' in the `@menu' line and
-leave point on the line before the `@end menu' line. Does not indent
-second and subsequent lines of a multi-line description."
- (let* ((beginning-of-next-line (point)))
- (while (< beginning-of-next-line
- (save-excursion ; beginning of end menu line
- (goto-char (texinfo-menu-end))
- (beginning-of-line)
- (point)))
- (if (search-forward "::" (texinfo-menu-end) t)
- (progn
- (let ((beginning-white-space (point)))
- (skip-chars-forward " \t") ; skip over spaces
- (if (looking-at "\\(@\\|\\w\\)+") ; if there is text
- (progn
- ;; remove pre-existing indentation
- (delete-region beginning-white-space (point))
- (indent-to-column to-column-number))))))
- ;; position point at beginning of next line
- (forward-line 1)
- (setq beginning-of-next-line (point)))))
-
-
-;;;; Making the master menu
-
-(defun texinfo-master-menu (update-all-nodes-menus-p)
- "Make a master menu for a whole Texinfo file.
-Non-nil argument (prefix, if interactive) means first update all
-existing nodes and menus. Remove pre-existing master menu, if there is one.
-
-This function creates a master menu that follows the top node. The
-master menu includes every entry from all the other menus. It
-replaces any existing ordinary menu that follows the top node.
-
-If called with a non-nil argument, this function first updates all the
-menus in the buffer (incorporating descriptions from pre-existing
-menus) before it constructs the master menu.
-
-The function removes the detailed part of an already existing master
-menu. This action depends on the pre-exisitng master menu using the
-standard `texinfo-master-menu-header'.
-
-The master menu has the following format, which is adapted from the
-recommendation in the Texinfo Manual:
-
- * The first part contains the major nodes in the Texinfo file: the
- nodes for the chapters, chapter-like sections, and the major
- appendices. This includes the indices, so long as they are in
- chapter-like sections, such as unnumbered sections.
-
- * The second and subsequent parts contain a listing of the other,
- lower level menus, in order. This way, an inquirer can go
- directly to a particular node if he or she is searching for
- specific information.
-
-Each of the menus in the detailed node listing is introduced by the
-title of the section containing the menu."
-
- (interactive "P")
- (widen)
- (goto-char (point-min))
-
- ;; Move point to location after `top'.
- (if (not (re-search-forward "^@node [ \t]*top[ \t]*\\(,\\|$\\)" nil t))
- (error "This buffer needs a Top node!"))
-
- (let ((first-chapter
- (save-excursion (re-search-forward "^@node") (point))))
- (if (re-search-forward texinfo-master-menu-header first-chapter t)
- ;; Remove detailed master menu listing
- (progn
- (goto-char (match-beginning 0))
- (let ((end-of-detailed-menu-descriptions
- (save-excursion ; beginning of end menu line
- (goto-char (texinfo-menu-end))
- (beginning-of-line) (forward-char -1)
- (point))))
- (delete-region (point) end-of-detailed-menu-descriptions)))))
-
- (if update-all-nodes-menus-p
- (progn
- (message "Making a master menu...first updating all nodes... ")
- (sleep-for 2)
- (mark-whole-buffer)
- (texinfo-update-node t)
-
- (message "Updating all menus... ")
- (sleep-for 2)
- (mark-whole-buffer)
- (texinfo-make-menu t)))
-
- (message "Now making the master menu... ")
- (sleep-for 2)
- (goto-char (point-min))
- (texinfo-insert-master-menu-list
- (texinfo-master-menu-list))
-
- ;; Remove extra newlines that texinfo-insert-master-menu-list
- ;; may have inserted.
-
- (save-excursion
- (goto-char (point-min))
-
- (re-search-forward texinfo-master-menu-header)
- (goto-char (match-beginning 0))
- (insert "\n")
- (delete-blank-lines)
-
- (re-search-backward "^@menu")
- (forward-line -1)
- (delete-blank-lines)
-
- (re-search-forward "^@end menu")
- (forward-line 1)
- (delete-blank-lines))
-
- (message "Done...completed making master menu. You may save the buffer."))
-
-(defun texinfo-master-menu-list ()
- "Return a list of menu entries and header lines for the master menu.
-
-Start with the menu for chapters and indices and then find each
-following menu and the title of the node preceding that menu.
-
-The master menu list has this form:
-
- \(\(\(... \"entry-1-2\" \"entry-1\"\) \"title-1\"\)
- \(\(... \"entry-2-2\" \"entry-2-1\"\) \"title-2\"\)
- ...\)
-
-However, there does not need to be a title field."
-
- (let (master-menu-list)
- (while (texinfo-locate-menu-p)
- (setq master-menu-list
- (cons (list
- (texinfo-copy-menu)
- (texinfo-copy-menu-title))
- master-menu-list)))
- (reverse master-menu-list)))
-
-(defun texinfo-insert-master-menu-list (master-menu-list)
- "Format and insert the master menu in the current buffer."
- (goto-char (point-min))
- (re-search-forward "^@menu")
- (beginning-of-line)
- (delete-region (point) ; buffer must have ordinary top menu
- (save-excursion
- (re-search-forward "^@end menu")
- (point)))
-
- (save-excursion ; leave point at beginning of menu
- ;; Handle top of menu
- (insert "\n@menu\n")
- ;; Insert chapter menu entries
- (setq this-very-menu-list (reverse (car (car master-menu-list))))
- ;;; Tell user what is going on.
- (message "Inserting chapter menu entry: %s ... " this-very-menu-list)
- (while this-very-menu-list
- (insert "* " (car this-very-menu-list) "\n")
- (setq this-very-menu-list (cdr this-very-menu-list)))
-
- (setq master-menu-list (cdr master-menu-list))
-
- (insert texinfo-master-menu-header)
-
- ;; Now, insert all the other menus
-
- ;; The menu master-menu-list has a form like this:
- ;; ((("beta" "alpha") "title-A")
- ;; (("delta" "gamma") "title-B"))
-
- (while master-menu-list
-
- (message
- "Inserting menu for %s .... " (car (cdr (car master-menu-list))))
- ;; insert title of menu section
- (insert "\n" (car (cdr (car master-menu-list))) "\n\n")
-
- ;; insert each menu entry
- (setq this-very-menu-list (reverse (car (car master-menu-list))))
- (while this-very-menu-list
- (insert "* " (car this-very-menu-list) "\n")
- (setq this-very-menu-list (cdr this-very-menu-list)))
-
- (setq master-menu-list (cdr master-menu-list)))
-
- ;; Finish menu
- (insert "@end menu\n\n")))
-
-(defvar texinfo-master-menu-header
- "\n --- The Detailed Node Listing ---\n"
- "String inserted before lower level entries in Texinfo master menu.
-It comes after the chapter-level menu entries.")
-
-(defun texinfo-locate-menu-p ()
- "Find the next menu in the texinfo file.
-If found, leave point after word `menu' on the `@menu' line, and return t.
-If a menu is not found, do not move point and return nil."
- (re-search-forward "\\(^@menu\\)" nil t))
-
-(defun texinfo-copy-menu-title ()
- "Return the title of the section preceding the menu as a string.
-If such a title cannot be found, return an empty string. Do not move
-point."
- (save-excursion
- (if (re-search-backward
- (concat
- "\\(^@node\\).*\n" ; match node line
- "\\(\\(\\(^@c\\).*\n\\)" ; match comment line, if any
- "\\|" ; or
- "\\(^@ifinfo[ ]*\n\\)\\)?" ; ifinfo line, if any
- (eval
- (cdr
- (assoc (texinfo-hierarchic-level)
- texinfo-update-menu-higher-regexps))))
- nil
- t)
- (texinfo-copy-section-title)
- " ")))
-
-(defun texinfo-copy-menu ()
- "Return the entries of an existing menu as a list.
-Start with point just after the word `menu' in the `@menu' line
-and leave point on the line before the `@end menu' line."
- (let* (this-menu-list
- (end-of-menu (texinfo-menu-end)) ; position of end of `@end menu'
- (last-entry (save-excursion ; position of beginning of
- ; last `* ' entry
- (goto-char end-of-menu)
- (re-search-backward "^\* ") ; handle multi-line desc.
- (point))))
- (while (< (point) last-entry)
- (if (re-search-forward "^\* " end-of-menu t)
- (progn
- (setq this-menu-list
- (cons
- (buffer-substring
- (point)
- ;; copy multi-line descriptions
- (save-excursion
- (re-search-forward "\\(^\* \\|^@e\\)" nil t)
- (- (point) 3)))
- this-menu-list)))))
- this-menu-list))
-
-
-;;;; Determining the hierarchical level in the texinfo file
-
-(defun texinfo-specific-section-type ()
- "Return the specific type of next section, as a string.
-For example, \"unnumberedsubsec\". Return \"top\" for top node.
-
-Searches forward for a section. Hence, point must be before the
-section whose type will be found. Does not move point. Signal an
-error if the node is not the top node and a section is not found."
- (save-excursion
- (cond
- ((re-search-forward "^@node [ \t]*top[ \t]*\\(,\\|$\\)"
- (save-excursion
- (end-of-line)
- (point))
- t)
- "top")
- ((re-search-forward texinfo-section-types-regexp nil t)
- (buffer-substring (progn (beginning-of-line) ; copy its name
- (1+ (point)))
- (progn (forward-word 1)
- (point))))
- (t
- (error
- "texinfo-specific-section-type: Chapter or section not found.")))))
-
-(defun texinfo-hierarchic-level ()
- "Return the general hierarchal level of the next node in a texinfo file.
-Thus, a subheading or appendixsubsec is of type subsection."
- (cdr (assoc
- (texinfo-specific-section-type)
- texinfo-section-to-generic-alist)))
-
-
-;;;; Locating the major positions
-
-(defun texinfo-update-menu-region-beginning (level)
- "Locate beginning of higher level section this section is within.
-Return position of the beginning of the node line; do not move point.
-Thus, if this level is subsection, searches backwards for section node.
-Only argument is a string of the general type of section."
-
- (cond
- ((or (string-equal "top" level)
- (string-equal "chapter" level))
- (save-excursion
- (goto-char (point-min))
- (re-search-forward "^@node [ \t]*top[ \t]*\\(,\\|$\\)" nil t)
- (beginning-of-line)
- (point)))
- (t
- (save-excursion
- (re-search-backward
- (concat
- "\\(^@node\\).*\n" ; match node line
- "\\(\\(\\(^@c\\).*\n\\)" ; match comment line, if any
- "\\|" ; or
- "\\(^@ifinfo[ ]*\n\\)\\)?" ; ifinfo line, if any
- (eval
- (cdr (assoc level texinfo-update-menu-higher-regexps))))
- nil
- 'goto-beginning)
- (point)))))
-
-(defun texinfo-update-menu-region-end (level)
- "Locate end of higher level section this section is within.
-Return position; do not move point. Thus, if this level is a
-subsection, find the node for the section this subsection is within.
-If level is top or chapter, returns end of file. Only argument is a
-string of the general type of section."
-
- (save-excursion
- (if (re-search-forward
- (concat
- "\\(^@node\\).*\n" ; match node line
- "\\(\\(\\(^@c\\).*\n\\)" ; match comment line, if any
- "\\|" ; or
- "\\(^@ifinfo[ ]*\n\\)\\)?" ; ifinfo line, if any
- (eval
- (cdr (assoc level texinfo-update-menu-higher-regexps))))
- nil
- 'goto-end)
- (match-beginning 1)
- (point-max))))
-
-(defun texinfo-menu-first-node (beginning end)
- "Locate first node of the section the menu will be placed in.
-Return position; do not move point.
-The menu will be located just before this position.
-
-First argument is the position of the beginning of the section in
-which the menu will be located; second argument is the position of the
-end of that region; it limits the search."
-
- (save-excursion
- (goto-char beginning)
- (forward-line 1)
- (re-search-forward "^@node" end t)
- (beginning-of-line)
- (point)))
-
-
-;;;; Alists and regular expressions for defining hierarchical levels
-
-(defvar texinfo-section-to-generic-alist
- '(("top" . "top")
-
- ("chapter" . "chapter")
- ("unnumbered" . "chapter")
- ("majorheading" . "chapter")
- ("chapheading" . "chapter")
- ("appendix" . "chapter")
-
- ("section" . "section")
- ("unnumberedsec" . "section")
- ("heading" . "section")
- ("appendixsec" . "section")
-
- ("subsection" . "subsection")
- ("unnumberedsubsec" . "subsection")
- ("subheading" . "subsection")
- ("appendixsubsec" . "subsection")
-
- ("subsubsection" . "subsubsection")
- ("unnumberedsubsubsec" . "subsubsection")
- ("subsubheading" . "subsubsection")
- ("appendixsubsubsec" . "subsubsection"))
- "*An alist of specific and corresponding generic Texinfo section types.
-The keys are strings specifying specific types of section; the values
-are strings of their corresponding general types.")
-
-(defvar texinfo-section-types-regexp
- "^@\\(chapter \\|sect\\|sub\\|unnum\\|major\\|chapheading \\|heading \\|appendix\\)"
- "Regexp matching chapter, section, other headings (but not the top node).")
-
-(defvar texinfo-chapter-level-regexp
- "chapter\\|unnumbered \\|appendix \\|majorheading\\|chapheading"
- "Regular expression matching just the Texinfo chapter level headings.")
-
-(defvar texinfo-section-level-regexp
- "section\\|unnumberedsec\\|heading \\|appendixsec"
- "Regular expression matching just the Texinfo section level headings.")
-
-(defvar texinfo-subsection-level-regexp
- "subsection\\|unnumberedsubsec\\|subheading\\|appendixsubsec"
- "Regular expression matching just the Texinfo subsection level headings.")
-
-(defvar texinfo-subsubsection-level-regexp
- "subsubsection\\|unnumberedsubsubsec\\|subsubheading\\|appendixsubsubsec"
- "Regular expression matching just the Texinfo subsubsection level headings.")
-
-(defvar texinfo-update-menu-same-level-regexps
- '(("top" . "top[ \t]+")
- ("chapter" .
- (concat "\\(^@\\)\\(" texinfo-chapter-level-regexp "\\)[ \t]*"))
- ("section" .
- (concat "\\(^@\\)\\(" texinfo-section-level-regexp "\\)[ \t]*"))
- ("subsection" .
- (concat "\\(^@\\)\\(" texinfo-subsection-level-regexp "\\)[ \t]+"))
- ("subsubsection" .
- (concat "\\(^@\\)\\(" texinfo-subsubsection-level-regexp "\\)[ \t]+")))
- "*Regexps for searching for same level sections in a Texinfo file.
-The keys are strings specifying the general hierarchical level in the
-document; the values are regular expressions.")
-
-(defvar texinfo-update-menu-higher-regexps
- '(("top" . "^@node [ \t]*DIR")
- ("chapter" . "^@node [ \t]*top[ \t]*\\(,\\|$\\)")
- ("section" .
- (concat
- "\\(^@\\("
- texinfo-chapter-level-regexp
- "\\)[ \t]*\\)"))
- ("subsection" .
- (concat
- "\\(^@\\("
- texinfo-section-level-regexp
- "\\|"
- texinfo-chapter-level-regexp
- "\\)[ \t]*\\)"))
- ("subsubsection" .
- (concat
- "\\(^@\\("
- texinfo-subsection-level-regexp
- "\\|"
- texinfo-section-level-regexp
- "\\|"
- texinfo-chapter-level-regexp
- "\\)[ \t]*\\)")))
- "*Regexps for searching for higher level sections in a Texinfo file.
-The keys are strings specifying the general hierarchical level in the
-document; the values are regular expressions.")
-
-(defvar texinfo-update-menu-lower-regexps
- '(("top" .
- (concat
- "\\(^@\\("
- texinfo-chapter-level-regexp
- "\\|"
- texinfo-section-level-regexp
- "\\|"
- texinfo-subsection-level-regexp
- "\\|"
- texinfo-subsubsection-level-regexp
- "\\)[ \t]*\\)"))
- ("chapter" .
- (concat
- "\\(^@\\("
- texinfo-section-level-regexp
- "\\|"
- texinfo-subsection-level-regexp
- "\\|"
- texinfo-subsubsection-level-regexp
- "\\)[ \t]*\\)"))
- ("section" .
- (concat
- "\\(^@\\("
- texinfo-subsection-level-regexp
- "\\|"
- texinfo-subsubsection-level-regexp
- "\\)[ \t]+\\)"))
- ("subsection" .
- (concat
- "\\(^@\\("
- texinfo-subsubsection-level-regexp
- "\\)[ \t]+\\)"))
- ("subsubsection" . "nothing lower"))
- "*Regexps for searching for lower level sections in a Texinfo file.
-The keys are strings specifying the general hierarchical level in the
-document; the values are regular expressions.")
-
-
-;;;; Updating a Node
-
-(defun texinfo-update-node (&optional region-p)
- "Without any prefix argument, update the node in which point is located.
-Non-nil argument (prefix, if interactive) means update the nodes in the
-marked region.
-
-The functions for creating or updating nodes and menus, and their
-keybindings, are:
-
- texinfo-update-node (&optional region-p) \\[texinfo-update-node]
- texinfo-every-node-update () \\[texinfo-every-node-update]
- texinfo-sequential-node-update (&optional region-p)
-
- texinfo-make-menu (&optional region-p) \\[texinfo-make-menu]
- texinfo-all-menus-update () \\[texinfo-all-menus-update]
- texinfo-master-menu ()
-
- texinfo-indent-menu-description (column &optional region-p)
-
-The `texinfo-column-for-description' variable specifies the column to
-which menu descriptions are indented. Its default value is 24."
-
- (interactive "P")
- (if (not region-p)
- (let ((auto-fill-hook nil)) ; update a single node
- (if (not (re-search-backward "^@node" (point-min) t))
- (error "Node line not found before this position."))
- (texinfo-update-the-node)
- (message "Done...updated the node. You may save the buffer."))
- ;; else
- (let ((auto-fill-hook nil)
- (beginning (region-beginning))
- (end (region-end)))
- (if (= end beginning)
- (error "Please mark a region!"))
- (save-restriction
- (narrow-to-region beginning end)
- (goto-char beginning)
- (push-mark)
- (while (re-search-forward "^@node" (point-max) t)
- (beginning-of-line)
- (texinfo-update-the-node))
- (message "Done...updated nodes in region. You may save the buffer.")))))
-
-(defun texinfo-every-node-update ()
- "Update every node in a Texinfo file."
- (interactive)
- (save-excursion
- (mark-whole-buffer)
- (texinfo-update-node t)
- (message "Done...updated every node. You may save the buffer.")))
-
-(defun texinfo-update-the-node ()
- "Update one node. Point must be at the beginning of node line.
-Leave point at the end of the node line."
- (texinfo-check-for-node-name)
- (texinfo-delete-existing-pointers)
- (message "Updating node: %s ... " (texinfo-copy-node-name))
- (save-restriction
- (widen)
- (let*
- ((case-fold-search t)
- (level (texinfo-hierarchic-level))
- (beginning (texinfo-update-menu-region-beginning level))
- (end (texinfo-update-menu-region-end level)))
- (if (string-equal level "top")
- (texinfo-top-pointer-case)
- ;; else
- (texinfo-insert-pointer beginning end level 'next)
- (texinfo-insert-pointer beginning end level 'previous)
- (texinfo-insert-pointer beginning end level 'up)
- (texinfo-clean-up-node-line)))))
-
-(defun texinfo-top-pointer-case ()
- "Insert pointers in the Top node. This is a special case.
-
-The `Next' pointer is a pointer to a chapter or section at a lower
-hierarchical level in the file. The `Previous' and `Up' pointers are
-to `(dir)'. Point must be at the beginning of the node line, and is
-left at the end of the node line."
-
- (texinfo-clean-up-node-line)
- (insert ", "
- (save-excursion
- ;; There may be an @chapter or other such command between
- ;; the top node line and the next node line, as a title
- ;; for an `ifinfo' section. This @chapter command must
- ;; must be skipped. So the procedure is to search for
- ;; the next `@node' line, and then copy its name.
- (if (re-search-forward "^@node" nil t)
- (progn
- (beginning-of-line)
- (texinfo-copy-node-name))
- " "))
- ", (dir), (dir)"))
-
-(defun texinfo-check-for-node-name ()
- "Determine whether the node has a node name. Prompt for one if not.
-Point must be at beginning of node line. Does not move point."
- (save-excursion
- (forward-word 1) ; skip over node command
- (skip-chars-forward " \t") ; and over spaces
- (if (not (looking-at "[^,\t\n ]+")) ; regexp based on what info looks for
- ; alternatively, use "[a-zA-Z]+"
- (let ((node-name (read-from-minibuffer "Node name: ")))
- (insert " " node-name)))))
-
-(defun texinfo-delete-existing-pointers ()
- "Delete `Next', `Previous', and `Up' pointers.
-Starts from the current position of the cursor, and searches forward
-on the line for a comma and if one is found, deletes the rest of the
-line, including the comma. Leaves point at beginning of line."
- (if (search-forward "," (save-excursion (end-of-line) (point)) t)
- (progn
- (goto-char (1- (point)))
- (kill-line nil)))
- (beginning-of-line))
-
-(defun texinfo-find-pointer (beginning end level direction)
- "Move point to section associated with next, previous, or up pointer.
-Return type of pointer (either 'normal or 'no-pointer).
-
-The first and second arguments bound the search for a pointer to the
-beginning and end, respectively, of the enclosing higher level
-section. The third argument is a string specifying the general kind
-of section such as \"chapter\ or \"section\". When looking for the
-`Next' pointer, the section found will be at the same hierarchical
-level in the Texinfo file; when looking for the `Previous' pointer,
-the section found will be at the same or higher hierarchical level in
-the Texinfo file; when looking for the `Up' pointer, the section found
-will be at some level higher in the Texinfo file. The fourth argument
-\(one of 'next, 'previous, or 'up\) specifies whether to find the
-`Next', `Previous', or `Up' pointer."
-
- (cond ((eq direction 'next)
- (forward-line 3) ; skip over current node
- (if (re-search-forward
- (eval
- (cdr (assoc level texinfo-update-menu-same-level-regexps)))
- end
- t)
- 'normal
- 'no-pointer))
- ((eq direction 'previous)
- (if (re-search-backward
- (concat
- "\\("
- (eval
- (cdr (assoc level texinfo-update-menu-same-level-regexps)))
- "\\|"
- (eval
- (cdr (assoc level texinfo-update-menu-higher-regexps)))
- "\\)")
- beginning
- t)
- 'normal
- 'no-pointer))
- ((eq direction 'up)
- (if (re-search-backward
- (eval (cdr (assoc level texinfo-update-menu-higher-regexps)))
- (save-excursion
- (goto-char beginning)
- (beginning-of-line)
- (point))
- t)
- 'normal
- 'no-pointer))
- (t
- (error "texinfo-find-pointer: lack proper arguments"))))
-
-(defun texinfo-pointer-name (kind)
- "Return the node name preceding the section command.
-The argument is the kind of section, either normal or no-pointer."
- (let (name)
- (cond ((eq kind 'normal)
- (end-of-line) ; this handles prev node top case
- (re-search-backward ; when point is already
- "^@node" ; at the beginning of @node line
- (save-excursion (forward-line -3))
- t)
- (setq name (texinfo-copy-node-name)))
- ((eq kind 'no-pointer)
- (setq name " "))) ; put a blank in the pointer slot
- name))
-
-(defun texinfo-insert-pointer (beginning end level direction)
- "Insert the `Next', `Previous' or `Up' node name at point.
-Move point forward.
-
-The first and second arguments bound the search for a pointer to the
-beginning and end, respectively, of the enclosing higher level
-section. The third argument is the hierarchical level of the Texinfo
-file, a string such as \"section\". The fourth argument is direction
-towards which the pointer is directed, one of `next, `previous, or
-'up."
-
- (end-of-line)
- (insert
- ", "
- (save-excursion
- (texinfo-pointer-name
- (texinfo-find-pointer beginning end level direction)))))
-
-(defun texinfo-clean-up-node-line ()
- "Remove extra commas, if any, at end of node line."
- (end-of-line)
- (skip-chars-backward ", ")
- (delete-region (point) (save-excursion (end-of-line) (point))))
-
-
-;;;; Updating nodes sequentially
-; These sequential update functions insert `Next' or `Previous'
-; pointers that point to the following or preceding nodes even if they
-; are at higher or lower hierarchical levels. This means that if a
-; section contains one or more subsections, the section's `Next'
-; pointer will point to the subsection and not the following section.
-; (The subsection to which `Next' points will most likely be the first
-; item on the section's menu.)
-
-(defun texinfo-sequential-node-update (&optional region-p)
- "Update one node (or many) in a Texinfo file with sequential pointers.
-
-This function causes the `Next' or `Previous' pointer to point to the
-immediately preceding or following node, even if it is at a higher or
-lower hierarchical level in the document. Continually pressing `n' or
-`p' takes you straight through the file.
-
-Without any prefix argument, update the node in which point is located.
-Non-nil argument (prefix, if interactive) means update the nodes in the
-marked region.
-
-This command makes it awkward to navigate among sections and
-subsections; it should be used only for those documents that are meant
-to be read like a novel rather than a reference, and for which the
-Info `g*' command is inadequate."
-
- (interactive "P")
- (if (not region-p)
- (let ((auto-fill-hook nil)) ; update a single node
- (if (not (re-search-backward "^@node" (point-min) t))
- (error "Node line not found before this position."))
- (texinfo-sequentially-update-the-node)
- (message
- "Done...sequentially updated the node . You may save the buffer."))
- ;; else
- (let ((auto-fill-hook nil)
- (beginning (region-beginning))
- (end (region-end)))
- (if (= end beginning)
- (error "Please mark a region!"))
- (save-restriction
- (narrow-to-region beginning end)
- (goto-char beginning)
- (push-mark)
- (while (re-search-forward "^@node" (point-max) t)
- (beginning-of-line)
- (texinfo-sequentially-update-the-node))
- (message
- "Done...updated the nodes in sequence. You may save the buffer.")))))
-
-(defun texinfo-sequentially-update-the-node ()
- "Update one node such that the pointers are sequential.
-A `Next' or `Previous' pointer points to any preceding or following node,
-regardless of its hierarchical level."
-
- (texinfo-check-for-node-name)
- (texinfo-delete-existing-pointers)
- (message
- "Sequentially updating node: %s ... " (texinfo-copy-node-name))
- (save-restriction
- (widen)
- (let*
- ((case-fold-search t)
- (level (texinfo-hierarchic-level)))
- (if (string-equal level "top")
- (texinfo-top-pointer-case)
- ;; else
- (texinfo-sequentially-insert-pointer level 'next)
- (texinfo-sequentially-insert-pointer level 'previous)
- (texinfo-sequentially-insert-pointer level 'up)
- (texinfo-clean-up-node-line)))))
-
-(defun texinfo-sequentially-find-pointer (level direction)
- "Find next or previous pointer sequentially in Texinfo file, or up pointer.
-Move point to section associated with the pointer. Find point even if
-it is in a different section.
-
-Return type of pointer (either 'normal or 'no-pointer).
-
-The first argument is a string specifying the general kind of section
-such as \"chapter\ or \"section\". The section found will be at the
-same hierarchical level in the Texinfo file, or, in the case of the up
-pointer, some level higher. The second argument (one of 'next,
-'previous, or 'up) specifies whether to find the `Next', `Previous',
-or `Up' pointer."
-
- (cond ((eq direction 'next)
- (forward-line 3) ; skip over current node
- (if (re-search-forward
- texinfo-section-types-regexp
- (point-max)
- t)
- 'normal
- 'no-pointer))
- ((eq direction 'previous)
- (if (re-search-backward
- texinfo-section-types-regexp
- (point-min)
- t)
- 'normal
- 'no-pointer))
- ((eq direction 'up)
- (if (re-search-backward
- (eval (cdr (assoc level texinfo-update-menu-higher-regexps)))
- beginning
- t)
- 'normal
- 'no-pointer))
- (t
- (error "texinfo-sequential-find-pointer: lack proper arguments"))))
-
-(defun texinfo-sequentially-insert-pointer (level direction)
- "Insert the `Next', `Previous' or `Up' node name at point.
-Move point forward.
-
-The first argument is the hierarchical level of the Texinfo file, a
-string such as \"section\". The second argument is direction, one of
-`next, `previous, or 'up."
-
- (end-of-line)
- (insert
- ", "
- (save-excursion
- (texinfo-pointer-name
- (texinfo-sequentially-find-pointer level direction)))))
-
-
-;;;; Inserting `@node' lines
-; The `texinfo-insert-node-lines' function inserts `@node' lines as needed
-; before the `@chapter', `@section', and such like lines of a region
-; in a Texinfo file.
-
-(defun texinfo-insert-node-lines (&optional title-p)
- "Insert missing `@node' lines in region of Texinfo file.
-Non-nil argument (prefix, if interactive) means also to insert the
-section titles as node names; and also to insert the section titles as
-node names in pre-existing @node lines that lack names."
- (interactive "P")
- (save-excursion
- (let ((begin-region (region-beginning))
- (end-region (region-end)))
- (goto-char begin-region)
- (while (< (point) end-region)
- (re-search-forward texinfo-section-types-regexp nil 'end)
- ;; copy title, since most often, we will need it
- (let ((title
- (progn
- (beginning-of-line)
- (forward-word 1)
- (skip-chars-forward " \t")
- (buffer-substring
- (point)
- (save-excursion (end-of-line) (point))))))
- ;; insert a node if necessary
- (if (re-search-backward
- "^@node"
- (save-excursion
- (forward-line -3)
- (point))
- t)
- ;; @node present, and point at beginning of that line
- (forward-word 1)
- ;; else @node missing, insert one
- (progn
- (beginning-of-line) ; beginning of `@section' line
- (insert "@node\n")
- (backward-char 1))) ; leave point just after `@node'
- ;; insert a title if warranted
- (if title-p
- (progn
- (skip-chars-forward " \t")
- ;; use regexp based on what info looks for
- ;; (alternatively, use "[a-zA-Z]+")
- (if (not (looking-at "[^,\t\n ]+"))
- (progn
- (beginning-of-line)
- (forward-word 1)
- (insert " " title)
- (message "Inserted title %s ... " title)))))
- ;; in any case, go forward beyond current section title
- (forward-line 3)))))
- (if title-p
- (message
- "Done inserting node lines and titles. You may save the buffer.")
- (message "Done inserting node lines. You may save the buffer.")))
-
-
-;;;; Update and create menus for multi-file Texinfo sources
-
-;; 1. M-x texinfo-multiple-files-update
-;;
-;; Read the include file list of an outer Texinfo file and
-;; update all highest level nodes in the files listed and insert a
-;; main menu in the outer file after its top node.
-
-;; 2. C-u M-x texinfo-multiple-files-update
-;;
-;; Same as 1, but insert a master menu. (Saves reupdating lower
-;; level menus and nodes.) This command simply reads every menu,
-;; so if the menus are wrong, the master menu will be wrong.
-;; Similarly, if the lower level node pointers are wrong, they
-;; will stay wrong.
-
-;; 3. C-u 2 M-x texinfo-multiple-files-update
-;;
-;; Read the include file list of an outer Texinfo file and
-;; update all nodes and menus in the files listed and insert a
-;; master menu in the outer file after its top node.
-
-;;; Note: these functions:
-;;;
-;;; * Do not save or delete any buffers. You may fill up your memory.
-;;; * Do not handle any pre-existing nodes in outer file.
-;;; Hence, you may need a file for indices.
-
-
-;;;; Auxiliary functions for multiple file updating
-
-(defun texinfo-multi-file-included-list (outer-file)
- "Return a list of the included files in OUTER-FILE."
- (let ((included-file-list (list outer-file))
- start)
- (save-excursion
- (switch-to-buffer (find-file-noselect outer-file))
- (widen)
- (goto-char (point-min))
- (while (re-search-forward "^@include" nil t)
- (skip-chars-forward " \t")
- (setq start (point))
- (end-of-line)
- (skip-chars-backward " \t")
- (setq included-file-list
- (cons (buffer-substring start (point))
- included-file-list)))
- (nreverse included-file-list))))
-
-(defun texinfo-copy-next-section-title ()
- "Return the name of the immediately following section as a string.
-
-Start with point at the beginning of the node line. Leave point at the
-same place. If there is no title, returns an empty string."
-
- (save-excursion
- (end-of-line)
- (let ((section-end (or
- (save-excursion
- (re-search-forward "\\(^@node\\)" nil t)
- (match-beginning 0))
- (point-max))))
- (if (re-search-forward texinfo-section-types-regexp section-end t)
- ;; copy title
- (let ((title
- (buffer-substring
- (progn (forward-word 1) ; skip over section type
- (skip-chars-forward " \t") ; and over spaces
- (point))
- (progn (end-of-line) (point)))))
- title)
- ""))))
-
-(defun texinfo-multi-file-update (files &optional update-everything)
- "Update first node pointers in each file in FILES.
-Return a list of the node names and the title immediate following them.
-
-The first file in the list is an outer file; the remaining are
-files included in the outer file with `@include' commands.
-
-If optional arg UPDATE-EVERYTHING non-nil, update every menu and
-pointer in each of the included files.
-
-Also update the `Top' level node pointers of the outer file.
-
-Requirements:
-
- * the first file in the FILES list must be the outer file,
- * each of the included files must contain exactly one highest
- hierarchical level node,
- * this node must be the first node in the included file,
- * each highest hierarchical level node must be of the same type.
-
-Thus, normally, each included file contains one, and only one,
-chapter.
-
-The menu-list has the form:
-
- \(\(\"node-name1\" . \"title1\"\)
- \(\"node-name2\" . \"title2\"\) ... \)
-
-However, there does not need to be a title field."
-
- (let (menu-list)
-
- ;; Find the name of the first node of the first included file.
- (switch-to-buffer (find-file-noselect (car (cdr files))))
- (widen)
- (goto-char (point-min))
- (if (not (re-search-forward "^@node" nil t))
- (error "No `@node' line found in %s !" (buffer-name)))
- (beginning-of-line)
- (texinfo-check-for-node-name)
- (setq next-node-name (texinfo-copy-node-name))
-
- (setq menu-list
- (cons (cons
- next-node-name
- (texinfo-copy-next-section-title))
- menu-list))
-
- ;; Go to outer file
- (switch-to-buffer (find-file-noselect (car files)))
- (goto-char (point-min))
- (if (not (re-search-forward "^@node [ \t]*top[ \t]*\\(,\\|$\\)" nil t))
- (error "This buffer needs a Top node!"))
- (beginning-of-line)
- (texinfo-delete-existing-pointers)
- (end-of-line)
- (insert ", " next-node-name ", (dir), (dir)")
- (beginning-of-line)
- (setq previous-node-name "Top")
- (setq files (cdr files))
-
- (while files
-
- (if (not (cdr files))
- ;; No next file
- (setq next-node-name "")
- ;; Else,
- ;; find the name of the first node in the next file.
- (switch-to-buffer (find-file-noselect (car (cdr files))))
- (widen)
- (goto-char (point-min))
- (if (not (re-search-forward "^@node" nil t))
- (error "No `@node' line found in %s !" (buffer-name)))
- (beginning-of-line)
- (texinfo-check-for-node-name)
- (setq next-node-name (texinfo-copy-node-name))
- (setq menu-list
- (cons (cons
- next-node-name
- (texinfo-copy-next-section-title))
- menu-list)))
-
- ;; Go to node to be updated.
- (switch-to-buffer (find-file-noselect (car files)))
- (goto-char (point-min))
- (if (not (re-search-forward "^@node" nil t))
- (error "No `@node' line found in %s !" (buffer-name)))
- (beginning-of-line)
- (texinfo-delete-existing-pointers)
- (end-of-line)
- (insert ", " next-node-name ", " previous-node-name ", " up-node-name)
-
- (beginning-of-line)
- (setq previous-node-name (texinfo-copy-node-name))
-
- ;; Update other menus and nodes if requested.
- (if update-everything (texinfo-all-menus-update t))
-
- (setq files (cdr files)))
- (nreverse menu-list)))
-
-(defun texinfo-multi-files-insert-main-menu (menu-list)
- "Insert formatted main menu at point.
-Indents the first line of the description, if any, to the value of
-texinfo-column-for-description."
-
- (insert "@menu\n")
- (while menu-list
- (if (cdr (car menu-list)) ; menu-list has description entry
- (progn
- (insert
- (format "* %s::" (car (car menu-list)))) ; node-name entry
- (indent-to texinfo-column-for-description 2)
- (insert
- (format "%s\n" (cdr (car menu-list))))) ; description entry
- ;; else menu-list lacks description entry
- (insert
- (format "* %s::\n" (car (car menu-list))))) ; node-name entry
- (setq menu-list (cdr menu-list)))
- (insert "@end menu"))
-
-
-(defun texinfo-multi-file-master-menu-list (files-list)
- "Return master menu list from files in FILES-LIST.
-Menu entries in each file collected using `texinfo-master-menu-list'.
-
-The first file in FILES-LIST must be the outer file; the others must
-be the files included within it. A main menu must already exist."
- (save-excursion
- (let (master-menu-list)
- (while files-list
- (switch-to-buffer (find-file-noselect (car files-list)))
- (message "Working on: %s " (current-buffer))
- (goto-char (point-min))
- (setq master-menu-list
- (append master-menu-list (texinfo-master-menu-list)))
- (setq files-list (cdr files-list)))
- master-menu-list)))
-
-
-;;;; The multiple-file update function
-
-(defun texinfo-multiple-files-update
- (outer-file &optional update-everything make-master-menu)
- "Update first node pointers in each file included in OUTER-FILE;
-create or update main menu in the outer file that refers to such nodes.
-This does not create or update menus or pointers within the included files.
-
-With optional MAKE-MASTER-MENU argument (prefix arg, if interactive),
-insert a master menu in OUTER-FILE. This does not create or update
-menus or pointers within the included files.
-
-With optional UPDATE-EVERYTHING argument (numeric prefix arg, if
-interactive), update all the menus and all the `Next', `Previous', and
-`Up' pointers of all the files included in OUTER-FILE before inserting
-a master menu in OUTER-FILE.
-
-The command also updates the `Top' level node pointers of OUTER-FILE.
-
-Notes:
-
- * this command does NOT save any files--you must save the
- outer file and any modified, included files.
-
- * except for the `Top' node, this command does NOT handle any
- pre-existing nodes in the outer file; hence, indices must be
- enclosed in an included file.
-
-Requirements:
-
- * each of the included files must contain exactly one highest
- hierarchical level node,
- * this highest node must be the first node in the included file,
- * each highest hierarchical level node must be of the same type.
-
-Thus, normally, each included file contains one, and only one,
-chapter."
-
- (interactive "fName of outer `include' file: ")
-
- (cond (current-prefix-arg
- (setq make-master-menu (listp current-prefix-arg))
- (setq update-everything (numberp current-prefix-arg))))
-
- (let* ((included-file-list (texinfo-multi-file-included-list outer-file))
- (files included-file-list)
- main-menu-list
- next-node-name
- previous-node-name
- (up-node-name "Top"))
-
-;;; Update the pointers
-;;; and collect the names of the nodes and titles
- (setq main-menu-list (texinfo-multi-file-update files update-everything))
-
-;;; Insert main menu
-
- ;; Go to outer file
- (switch-to-buffer (find-file-noselect (car included-file-list)))
- (if (texinfo-old-menu-p
- (point-min)
- (save-excursion
- (re-search-forward "^@include")
- (beginning-of-line)
- (point)))
-
- ;; If found, leave point after word `menu' on the `@menu' line.
- (progn
- (texinfo-incorporate-descriptions main-menu-list)
- ;; Delete existing menu.
- (beginning-of-line)
- (delete-region
- (point)
- (save-excursion (re-search-forward "^@end menu") (point)))
- ;; Insert main menu
- (texinfo-multi-files-insert-main-menu main-menu-list))
-
- ;; Else no current menu; insert it before `@include'
- (texinfo-multi-files-insert-main-menu main-menu-list))
-
-;;; Insert master menu
-
- (if make-master-menu
- (progn
- ;; First, removing detailed part of any pre-existing master menu
- (goto-char (point-min))
- (if (re-search-forward texinfo-master-menu-header nil t)
- ;; Remove detailed master menu listing
- (progn
- (goto-char (match-beginning 0))
- (let ((end-of-detailed-menu-descriptions
- (save-excursion ; beginning of end menu line
- (goto-char (texinfo-menu-end))
- (beginning-of-line) (forward-char -1)
- (point))))
- (delete-region (point) end-of-detailed-menu-descriptions))))
-
- ;; Create a master menu and insert it
- (texinfo-insert-master-menu-list
- (texinfo-multi-file-master-menu-list
- included-file-list)))))
- (message "Multiple files updated."))
-
-;;;;;;;;;;;;;;;; end texnfo-upd.el ;;;;;;;;;;;;;;;;
diff --git a/lisp/time.el b/lisp/time.el
index 8a1f37f8e18..df5c7d5fe64 100644
--- a/lisp/time.el
+++ b/lisp/time.el
@@ -1,5 +1,5 @@
;; Display time and load in mode line of Emacs.
-;; Copyright (C) 1985, 1986, 1987 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 1986, 1987, 1990 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -29,15 +29,11 @@ Default is system-dependent, and is the same as used by Rmail.")
(defvar display-time-string nil)
-(defvar display-time-hook nil
- "* List of functions to be called when the time is updated on the mode line.")
-
(defun display-time ()
"Display current time and load level in mode line of each buffer.
Updates automatically every minute.
-If `display-time-day-and-date' is non-nil, the current day and date
-are displayed as well.
-After each update, `display-time-hook' is run with `run-hooks'."
+If display-time-day-and-date is non-nil, the current day and date
+are displayed as well."
(interactive)
(let ((live (and display-time-process
(eq (process-status display-time-process) 'run))))
@@ -50,10 +46,11 @@ After each update, `display-time-hook' is run with `run-hooks'."
(setq global-mode-string
(append global-mode-string '(display-time-string))))
(setq display-time-string "")
- (setq display-time-process
- (start-process "display-time" nil
- "wakeup"
- (int-to-string display-time-interval)))
+ (let ((process-connection-type nil))
+ (setq display-time-process
+ (start-process "display-time" nil
+ (concat exec-directory "wakeup")
+ (int-to-string display-time-interval))))
(process-kill-without-query display-time-process)
(set-process-sentinel display-time-process 'display-time-sentinel)
(set-process-filter display-time-process 'display-time-filter)))))
@@ -68,7 +65,27 @@ After each update, `display-time-hook' is run with `run-hooks'."
(defun display-time-filter (proc string)
(let ((time (current-time-string))
- (load (format "%03d" (car (load-average))))
+ (load (condition-case ()
+ (if (zerop (car (load-average))) ""
+ (format "%03d" (car (load-average))))
+ (error
+ (condition-case ()
+ (unwind-protect
+ (save-excursion
+ (set-buffer (get-buffer-create " *uptime*"))
+ (call-process "/usr/ucb/uptime" nil (current-buffer))
+ (goto-char (point-min))
+ (search-forward "average: ")
+ ;; Get the integer part and fraction part,
+ ;; discarding the period.
+ ;; (Because code below adds a period.)
+ (concat
+ (buffer-substring (point)
+ (progn (forward-word 1) (point)))
+ (buffer-substring (1+ (point))
+ (progn (forward-word 1) (point)))))
+ (kill-buffer " *uptime*"))
+ (error "")))))
(mail-spool-file (or display-time-mail-file
(getenv "MAIL")
(concat rmail-spool-directory
@@ -84,8 +101,10 @@ After each update, `display-time-hook' is run with `run-hooks'."
(setq hour 12)))
(setq display-time-string
(concat (format "%d" hour) (substring time 13 16)
- (if pm "pm " "am ")
- (substring load 0 -2) "." (substring load -2)
+ (if pm "pm" "am")
+ (if (string= load "")
+ ""
+ (concat " " (substring load 0 -2) "." (substring load -2)))
(if (and (file-exists-p mail-spool-file)
;; file not empty?
(> (nth 7 (file-attributes mail-spool-file)) 0))
@@ -95,7 +114,6 @@ After each update, `display-time-hook' is run with `run-hooks'."
(if display-time-day-and-date
(setq display-time-string
(concat (substring time 0 11) display-time-string))))
- (run-hooks 'display-time-hook)
;; Force redisplay of all buffers' mode lines to be considered.
(save-excursion (set-buffer (other-buffer)))
(set-buffer-modified-p (buffer-modified-p))
diff --git a/lisp/time.elc b/lisp/time.elc
new file mode 100644
index 00000000000..5e26869c247
--- /dev/null
+++ b/lisp/time.elc
Binary files differ
diff --git a/lisp/timer.el b/lisp/timer.el
deleted file mode 100644
index 7f71f784de9..00000000000
--- a/lisp/timer.el
+++ /dev/null
@@ -1,92 +0,0 @@
-;; Run a function with args at some time in future
-;; Copyright (C) 1990 Free Software Foundation, Inc.
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 1, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
-(defvar timer-process nil)
-(defvar timer-alist ())
-(defvar timer-out "")
-(defvar timer-dont-exit nil
- ;; this is useful for functions which will be doing their own erratic
- ;; rescheduling or people who otherwise expect to use the process frequently
- "If non-nil, don't exit the timer process when no more events are pending.")
-
-(defun run-at-time (time repeat function &rest args)
- "Run a function at a time, and optionally on a regular interval.
-Arguments are TIME, REPEAT, FUNCTION &rest ARGS.
-TIME, a string, can be specified absolutely or relative to now.
-REPEAT, an integer number of seconds, is the interval on which to repeat
-the call to the function."
- (interactive "sRun at time: \nNRepeat interval: \naFunction: ")
- (cond ((or (not timer-process)
- (memq (process-status timer-process) '(exit signal nil)))
- (if timer-process (delete-process timer-process))
- (setq timer-process (start-process "timer" nil "timer")
- timer-alist nil)
- (set-process-filter timer-process 'timer-process-filter)
- (set-process-sentinel timer-process 'timer-process-sentinel)
- (process-kill-without-query timer-process))
- ((eq (process-status timer-process) 'stop)
- (continue-process timer-process)))
- ;; There should be a living, breathing timer process now
- (let ((token (concat (current-time-string) "-" (length timer-alist))))
- (send-string timer-process (concat time "\001" token "\n"))
- (setq timer-alist (cons (list token repeat function args) timer-alist))))
-
-(defun timer-process-filter (proc str)
- (setq timer-out (concat timer-out str))
- (let (do token error)
- (while (string-match "\n" timer-out)
- (setq token (substring timer-out 0 (match-beginning 0))
- do (assoc token timer-alist)
- timer-out (substring timer-out (match-end 0)))
- (cond
- (do (apply (nth 2 do) (nth 3 do)) ; do it
- (if (natnump (nth 1 do)) ; reschedule it
- (send-string proc (concat (nth 1 do) " sec\001" (car do) "\n"))
- (setq timer-alist (delq do timer-alist))))
- ((string-match "timer: \\([^:]+\\): \\([^\001]*\\)\001\\(.*\\)$" token)
- (setq error (substring token (match-beginning 1) (match-end 1))
- do (substring token (match-beginning 2) (match-end 2))
- token (assoc (substring token (match-beginning 3) (match-end 3))
- timer-alist)
- timer-alist (delq token timer-alist))
- (ding 'no-terminate) ; using error function in process filters is rude
- (message "%s for %s; couldn't set at \"%s\"" error (nth 2 token) do))))
- (or timer-alist timer-dont-exit (process-send-eof proc))))
-
-(defun timer-process-sentinel (proc str)
- (let ((stat (process-status proc)))
- (if (eq stat 'stop) (continue-process proc)
- ;; if it exited normally, presumably it was intentional.
- ;; if there were no pending events, who cares that it exited?
- (if (or (not timer-alist) (eq stat 'exit)) ()
- (ding 'no-terminate)
- (message "Timer exited abnormally. All events cancelled."))
- (setq timer-process nil timer-alist nil timer-scratch ""))))
-
-(defun cancel-timer (function)
- "Cancel all events scheduled by ``run-at-time'' which would run FUNCTION."
- (interactive "aCancel function: ")
- (let ((alist timer-alist))
- (while alist
- (if (eq (nth 2 (car alist)) function)
- (setq timer-alist (delq (car alist) timer-alist)))
- (setq alist (cdr alist))))
- (or timer-alist timer-dont-exit (process-send-eof timer-process)))
-
-(provide 'timer)
diff --git a/lisp/uncompress.el b/lisp/uncompress.el
index 6897c7c3ccb..6b782d77820 100644
--- a/lisp/uncompress.el
+++ b/lisp/uncompress.el
@@ -1,18 +1,3 @@
-;; When we are about to make a backup file,
-;; uncompress the file we visited
-;; so that making the backup can work properly.
-;; This is used as a write-file-hook.
-
-(defun uncompress-backup-file ()
- (and buffer-file-name make-backup-files (not buffer-backed-up)
- (not (file-exists-p buffer-file-name))
- (call-process "uncompress" nil nil nil buffer-file-name))
- nil)
-
-(or (assoc "\\.Z$" auto-mode-alist)
- (setq auto-mode-alist
- (cons '("\\.Z$" . uncompress-while-visiting) auto-mode-alist)))
-
(defun uncompress-while-visiting ()
"Temporary \"major mode\" used for .Z files, to uncompress the contents.
It then selects a major mode from the uncompressed file name and contents."
@@ -25,14 +10,10 @@ It then selects a major mode from the uncompressed file name and contents."
(shell-command-on-region (point-min) (point-max) "uncompress" t))
(message "Uncompressing...done")
(set-buffer-modified-p nil)
- (make-local-variable 'write-file-hooks)
- (or (memq 'uncompress-backup-file write-file-hooks)
- (setq write-file-hooks (cons 'uncompress-backup-file write-file-hooks)))
(normal-mode))
-(or (memq 'find-compressed-version find-file-not-found-hooks)
- (setq find-file-not-found-hooks
- (cons 'find-compressed-version find-file-not-found-hooks)))
+(setq auto-mode-alist
+ (cons '("\\.Z$" . uncompress-while-visiting) auto-mode-alist))
(defun find-compressed-version ()
"Hook to read and uncompress the compressed version of a file."
@@ -45,3 +26,6 @@ It then selects a major mode from the uncompressed file name and contents."
(goto-char (point-min))
(setq error nil)
t)))
+
+(setq find-file-not-found-hooks
+ (cons 'find-compressed-version find-file-not-found-hooks))
diff --git a/lisp/textmodes/underline.el b/lisp/underline.el
index 4a9f3dfa823..ef9c7fa3651 100644
--- a/lisp/textmodes/underline.el
+++ b/lisp/underline.el
@@ -42,5 +42,5 @@ which specify the range to operate on."
(let ((end1 (make-marker)))
(move-marker end1 (max start end))
(goto-char (min start end))
- (while (re-search-forward "_\\|_" end1 t)
+ (while (search-forward "_" end1 t)
(delete-char -2)))))
diff --git a/lisp/underline.elc b/lisp/underline.elc
new file mode 100644
index 00000000000..5b4b6b1b9b7
--- /dev/null
+++ b/lisp/underline.elc
Binary files differ
diff --git a/lisp/mail/undigest.el b/lisp/undigest.el
index 583251e990f..590f225a8c2 100644
--- a/lisp/mail/undigest.el
+++ b/lisp/undigest.el
@@ -53,8 +53,7 @@ Leaves original message, deleted, before the undigestified messages."
(goto-char (point-max))
(or (mail-fetch-field "Reply-To")
(mail-fetch-field "To")
- (mail-fetch-field "Apparently-To")
- (mail-fetch-field "From")))
+ (mail-fetch-field "Apparently-To")))
(error "Message is not a digest")))))
(save-excursion
(goto-char (point-max))
diff --git a/lisp/undigest.elc b/lisp/undigest.elc
new file mode 100644
index 00000000000..4326826ce93
--- /dev/null
+++ b/lisp/undigest.elc
Binary files differ
diff --git a/lisp/userlock.el b/lisp/userlock.el
index e74621675a2..39871cc4e4c 100644
--- a/lisp/userlock.el
+++ b/lisp/userlock.el
@@ -78,9 +78,7 @@ You can <q>uit; don't modify this file.")))
This function has two choices: it can return, in which case the modification
of the buffer will proceed, or it can (signal 'file-supersession (file)),
in which case the proposed buffer modification will not be made.
-
-You can rewrite this to use any criterion you like to choose which one to do.
-The buffer in question is current when this function is called."
+You can rewrite this to use any criterion you like to choose which one to do."
(discard-input)
(save-window-excursion
(let (answer)
@@ -118,7 +116,8 @@ If you say `y' to go ahead and modify this buffer,
you risk ruining the work of whoever rewrote the file.
If you say `n', the change you started to make will be aborted.
-Usually, you should type `n' and then `M-x revert-buffer',
-to get the latest version of the file, then make the change again.")))
+You might consider answering `n', running `M-x revert-buffer' to
+bring the text in Emacs into accord with what is on disk, and then
+making the change again.")))
diff --git a/lisp/userlock.elc b/lisp/userlock.elc
new file mode 100644
index 00000000000..edd87dfcdd1
--- /dev/null
+++ b/lisp/userlock.elc
Binary files differ
diff --git a/lisp/version.el b/lisp/version.el
new file mode 100644
index 00000000000..ed412d63de4
--- /dev/null
+++ b/lisp/version.el
@@ -0,0 +1,45 @@
+;; Record version number of Emacs.
+;; Copyright (C) 1985 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 1, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+;; The following line is modified automatically
+;; by loading inc-version.el, each time a new Emacs is dumped.
+(defconst emacs-version "18.59.0" "\
+Version numbers of this version of Emacs.")
+
+(defconst emacs-build-time (current-time-string) "\
+Time at which Emacs was dumped out.")
+
+(defconst emacs-build-system (system-name))
+
+(defun emacs-version () "\
+Return string describing the version of Emacs that is running."
+ (interactive)
+ (if (interactive-p)
+ (message "%s" (emacs-version))
+ (format "GNU Emacs %s of %s %s on %s (%s)"
+ emacs-version
+ (substring emacs-build-time 0
+ (string-match " *[0-9]*:" emacs-build-time))
+ (substring emacs-build-time (string-match "[0-9]*$" emacs-build-time))
+ emacs-build-system system-type)))
+
+;;Local variables:
+;;version-control: never
+;;End:
diff --git a/lisp/emulation/vi.el b/lisp/vi.el
index 324f0b5882d..4b391ec82cc 100644
--- a/lisp/emulation/vi.el
+++ b/lisp/vi.el
@@ -748,7 +748,7 @@ scrolls default amount. The given COUNT is remembered for future scrollings."
"Go down count lines, try to keep at the same column."
(interactive "p")
(setq this-command 'next-line) ; this is a needed trick
- (if (= (point) (or (line-move count) (point)))
+ (if (= (point) (or (next-line-internal count) (point)))
(ding) ; no moving, already at end of buffer
(setq last-command 'next-line)))
diff --git a/lisp/vi.elc b/lisp/vi.elc
new file mode 100644
index 00000000000..bd9620b5c2c
--- /dev/null
+++ b/lisp/vi.elc
Binary files differ
diff --git a/lisp/view.el b/lisp/view.el
index 36f0d7bb63b..636cc38f770 100644
--- a/lisp/view.el
+++ b/lisp/view.el
@@ -1,5 +1,5 @@
;; View: Peruse file or buffer without editing.
-;; Copyright (C) 1985, 1989 Free Software Foundation, Inc.
+;; Copyright (C) 1985 Free Software Foundation, Inc.
;; Principal author K. Shane Hartman
;; This file is part of GNU Emacs.
@@ -26,9 +26,9 @@
nil
(setq view-mode-map (make-keymap))
(fillarray view-mode-map 'View-undefined)
- (define-key view-mode-map "\C-c" 'view-exit)
+ (define-key view-mode-map "\C-c" 'exit-recursive-edit)
(define-key view-mode-map "\C-z" 'suspend-emacs)
- (define-key view-mode-map "q" 'view-exit)
+ (define-key view-mode-map "q" 'exit-recursive-edit)
(define-key view-mode-map "-" 'negative-argument)
(define-key view-mode-map "0" 'digit-argument)
(define-key view-mode-map "1" 'digit-argument)
@@ -74,8 +74,8 @@
(define-key view-mode-map "h" 'Helper-describe-bindings)
(define-key view-mode-map "?" 'Helper-describe-bindings)
(define-key view-mode-map "\C-h" 'Helper-help)
- (define-key view-mode-map "\C-n" 'next-line)
- (define-key view-mode-map "\C-p" 'previous-line)
+ (define-key view-mode-map "\C-n" 'View-next-line)
+ (define-key view-mode-map "\C-p" 'View-previous-line)
(define-key view-mode-map "\C-s" 'isearch-forward)
(define-key view-mode-map "\C-r" 'isearch-backward)
(define-key view-mode-map "s" 'isearch-forward)
@@ -100,13 +100,14 @@ For list of all View commands, type ? or h while viewing.
Calls the value of view-hook if that is non-nil."
(interactive "fView file: ")
- (let ((old-buf (current-buffer))
- (had-a-buf (get-file-buffer file-name))
- (buf-to-view (find-file-noselect file-name)))
- (switch-to-buffer buf-to-view t)
- (view-mode old-buf
- (and (not had-a-buf) (not (buffer-modified-p buf-to-view))
- 'kill-buffer))))
+ (let ((had-a-buf (get-file-buffer file-name))
+ (buf-to-view nil))
+ (unwind-protect
+ (view-mode (prog1 (current-buffer)
+ (switch-to-buffer
+ (setq buf-to-view (find-file-noselect file-name)) t)))
+ (and (not had-a-buf) buf-to-view (not (buffer-modified-p buf-to-view))
+ (kill-buffer buf-to-view)))))
(defun view-buffer (buffer-name)
"View BUFFER in View mode, returning to previous buffer when done.
@@ -118,11 +119,9 @@ For list of all View commands, type ? or h while viewing.
Calls the value of view-hook if that is non-nil."
(interactive "bView buffer: ")
- (let ((old-buf (current-buffer)))
- (switch-to-buffer buffer-name t)
- (view-mode old-buf nil)))
+ (view-mode (prog1 (current-buffer) (switch-to-buffer buffer-name))))
-(defun view-mode (&optional prev-buffer action)
+(defun view-mode (&optional view-return-to-buffer)
"Major mode for viewing text but not editing it.
Letters do not insert themselves. Instead these commands are provided.
Most commands take prefix arguments. Commands dealing with lines
@@ -163,81 +162,26 @@ Entry to this mode calls the value of view-hook if non-nil.
; if you call it without passing a buffer as argument
; and they are not easy to fix.
; (interactive)
- (make-local-variable 'view-old-mode-line-buffer-identification)
- (setq view-old-mode-line-buffer-identification
- mode-line-buffer-identification)
- (make-local-variable 'view-old-buffer-read-only)
- (setq view-old-buffer-read-only buffer-read-only)
- (make-local-variable 'view-old-mode-name)
- (setq view-old-mode-name mode-name)
- (make-local-variable 'view-old-major-mode)
- (setq view-old-major-mode major-mode)
- (make-local-variable 'view-old-local-map)
- (setq view-old-local-map (current-local-map))
- (make-local-variable 'view-old-Helper-return-blurb)
- (setq view-old-Helper-return-blurb
- (and (boundp 'Helper-return-blurb) Helper-return-blurb))
-
- (setq buffer-read-only t)
- (setq mode-line-buffer-identification
- (list
- (if (buffer-file-name)
- "Viewing %f"
- "Viewing %b")))
- (setq mode-name "View")
- (setq major-mode 'view-mode)
- (setq Helper-return-blurb
- (format "continue viewing %s"
+ (let* ((view-buffer-window (selected-window))
+ (view-scroll-size nil))
+ (unwind-protect
+ (let ((buffer-read-only t)
+ (mode-line-buffer-identification
+ (list
(if (buffer-file-name)
- (file-name-nondirectory (buffer-file-name))
- (buffer-name))))
-
- (make-local-variable 'view-exit-action)
- (setq view-exit-action action)
- (make-local-variable 'view-prev-buffer)
- (setq view-prev-buffer prev-buffer)
- (make-local-variable 'view-exit-position)
- (setq view-exit-position (point-marker))
-
- (make-local-variable 'view-scroll-size)
- (setq view-scroll-size nil)
- (make-local-variable 'view-last-regexp)
- (setq view-last-regexp nil)
-
- (beginning-of-line)
- (setq goal-column nil)
-
- (use-local-map view-mode-map)
- (run-hooks 'view-hook)
- (view-helpful-message))
-
-(defun view-exit ()
- "Exit from view-mode.
-If you viewed an existing buffer, that buffer returns to its previous mode.
-If you viewed a file that was not present in Emacs, its buffer is killed."
- (interactive)
- (setq mode-line-buffer-identification
- view-old-mode-line-buffer-identification)
- (setq major-mode view-old-major-mode)
- (setq mode-name view-old-mode-name)
- (use-local-map (current-local-map))
- (setq buffer-read-only view-old-buffer-read-only)
-
- (goto-char view-exit-position)
- (set-marker view-exit-position nil)
-
- ;; Now do something to the buffer that we were viewing
- ;; (such as kill it).
- (let ((viewed-buffer (current-buffer))
- (action view-exit-action))
- (switch-to-buffer view-prev-buffer)
- (if action (funcall action viewed-buffer))))
+ "Viewing %f"
+ "Viewing %b")))
+ (mode-name "View"))
+ (beginning-of-line)
+ (catch 'view-mode-exit (view-mode-command-loop)))
+ (if view-return-to-buffer
+ (switch-to-buffer view-return-to-buffer)))))
(defun view-helpful-message ()
(message
(if (and (eq (key-binding "\C-h") 'Helper-help)
(eq (key-binding "?") 'Helper-describe-bindings)
- (eq (key-binding "\C-c") 'view-exit))
+ (eq (key-binding "\C-c") 'exit-recursive-edit))
"Type C-h for help, ? for commands, C-c to quit"
(substitute-command-keys
"Type \\[Helper-help] for help, \\[Helper-describe-bindings] for commands, \\[exit-recursive-edit] to quit."))))
@@ -247,7 +191,7 @@ If you viewed a file that was not present in Emacs, its buffer is killed."
(ding)
(view-helpful-message))
-(defun view-window-size () (1- (window-height)))
+(defun view-window-size () (1- (window-height view-buffer-window)))
(defun view-scroll-size ()
(min (view-window-size) (or view-scroll-size (view-window-size))))
@@ -255,6 +199,31 @@ If you viewed a file that was not present in Emacs, its buffer is killed."
(defvar view-hook nil
"If non-nil, its value is called when viewing buffer or file.")
+(defun view-mode-command-loop ()
+ (push-mark)
+ (let ((old-local-map (current-local-map))
+ (mark-ring)
+; (view-last-command)
+; (view-last-command-entry)
+; (view-last-command-argument)
+ (view-last-regexp)
+ (Helper-return-blurb
+ (format "continue viewing %s"
+ (if (buffer-file-name)
+ (file-name-nondirectory (buffer-file-name))
+ (buffer-name))))
+ (view-buffer (buffer-name)))
+ (unwind-protect
+ (progn
+ (use-local-map view-mode-map)
+ (run-hooks 'view-hook)
+ (view-helpful-message)
+ (recursive-edit))
+ (save-excursion
+ (set-buffer view-buffer)
+ (use-local-map old-local-map))))
+ (pop-mark))
+
;(defun view-last-command (&optional who what)
; (setq view-last-command-entry this-command)
; (setq view-last-command who)
@@ -387,3 +356,12 @@ invocations return to earlier marks."
(message "Can't find occurrence %d of %s" times regexp)
(sit-for 4))))
+(defun View-previous-line (count)
+ "Move up to start of previous line. Argument is repeat count."
+ (interactive "p")
+ (forward-line (- count)))
+
+(defun View-next-line (count)
+ "Move down to start of next line. Argument is repeat count."
+ (interactive "p")
+ (forward-line count))
diff --git a/lisp/view.elc b/lisp/view.elc
new file mode 100644
index 00000000000..e5b445dacf7
--- /dev/null
+++ b/lisp/view.elc
Binary files differ
diff --git a/lisp/emulation/vip.el b/lisp/vip.el
index da853aa9c36..f41e031bd7d 100644
--- a/lisp/emulation/vip.el
+++ b/lisp/vip.el
@@ -13,10 +13,14 @@
(defvar vip-emacs-local-map nil
"Local map used in emacs mode. \(buffer specific\)")
+(defvar vip-emacs-old-commands nil
+ "Old Emacs definitions of C-x 3 and C-x TAB.")
+
(defvar vip-insert-local-map nil
"Local map used in insert command mode. \(buffer specific\)")
(make-variable-buffer-local 'vip-emacs-local-map)
+(make-variable-buffer-local 'vip-emacs-old-commands)
(make-variable-buffer-local 'vip-insert-local-map)
(defvar vip-insert-point nil
@@ -169,20 +173,31 @@ or insert-mode."
(vip-copy-region-as-kill (point) vip-insert-point)
(vip-repeat-insert-command))
(setq vip-emacs-local-map (current-local-map)
+ vip-emacs-old-commands
+ (cons (lookup-key ctl-x-map "3")
+ (lookup-key ctl-x-map "\C-i"))
vip-emacs-mode-line-buffer-identification
mode-line-buffer-identification
vip-insert-local-map (vip-copy-keymap
- (current-local-map))))
+ (current-local-map)))
+ (define-key ctl-x-map "3" 'vip-buffer-in-two-windows)
+ (define-key ctl-x-map "\C-i" 'insert-file))
(vip-change-mode-line "Vi: ")
(use-local-map vip-mode-map))
((eq new-mode 'insert-mode)
(move-marker vip-insert-point (point))
(if (eq vip-current-mode 'emacs-mode)
- (setq vip-emacs-local-map (current-local-map)
- vip-emacs-mode-line-buffer-identification
- mode-line-buffer-identification
- vip-insert-local-map (vip-copy-keymap
- (current-local-map)))
+ (progn
+ (setq vip-emacs-local-map (current-local-map)
+ vip-emacs-old-commands
+ (cons (lookup-key ctl-x-map "3")
+ (lookup-key ctl-x-map "\C-i"))
+ vip-emacs-mode-line-buffer-identification
+ mode-line-buffer-identification
+ vip-insert-local-map (vip-copy-keymap
+ (current-local-map)))
+ (define-key ctl-x-map "3" 'vip-buffer-in-two-windows)
+ (define-key ctl-x-map "\C-i" 'insert-file))
(setq vip-insert-local-map (vip-copy-keymap
vip-emacs-local-map)))
(vip-change-mode-line "Insert")
@@ -196,6 +211,8 @@ or insert-mode."
'vip-delete-backward-word))
((eq new-mode 'emacs-mode)
(vip-change-mode-line "Emacs:")
+ (define-key ctl-x-map "3" (car vip-emacs-old-commands))
+ (define-key ctl-x-map "\C-i" (cdr vip-emacs-old-commands))
(use-local-map vip-emacs-local-map)))
(setq vip-current-mode new-mode)
(vip-refresh-mode-line))))
@@ -1115,7 +1132,7 @@ beginning of buffer, stop and signal error."
(interactive "P")
(let ((val (vip-p-val arg)) (com (vip-getCom arg)))
(if com (move-marker vip-com-point (point)))
- (line-move val)
+ (next-line-internal val)
(setq this-command 'next-line)
(if com (vip-execute-com 'vip-next-line val com))))
@@ -2017,9 +2034,6 @@ the query replace mode will toggle between string replace and regexp replace."
(define-key vip-mode-map "~" 'vip-nil)
(define-key vip-mode-map "\177" 'vip-delete-backward-char)
-(define-key ctl-x-map "3" 'vip-buffer-in-two-windows)
-(define-key ctl-x-map "\C-i" 'insert-file)
-
(defun vip-version ()
(interactive)
(message "VIP version 3.5 of September 15, 1987"))
@@ -3019,7 +3033,10 @@ vip-s-string"
(vip-enlarge-region beg end)
(write-region (point) (mark) ex-file ex-append t)))
(if (null buffer-file-name) (setq buffer-file-name ex-file))
- (if q-flag (save-buffers-kill-emacs)))
+ (if q-flag
+ (progn
+ (delete-auto-save-file-if-necessary)
+ (kill-buffer (current-buffer)))))
(defun ex-yank ()
"ex yank"
diff --git a/lisp/vip.elc b/lisp/vip.elc
new file mode 100644
index 00000000000..f787720767e
--- /dev/null
+++ b/lisp/vip.elc
Binary files differ
diff --git a/lisp/vms-patch.el b/lisp/vms-patch.el
index 15302b3fd90..3c5e1e8d606 100644
--- a/lisp/vms-patch.el
+++ b/lisp/vms-patch.el
@@ -56,7 +56,8 @@ See also auto-save-file-name-p."
(if buffer-file-name
(concat (file-name-directory buffer-file-name)
"_$"
- (file-name-nondirectory buffer-file-name)
+ (file-name-sans-versions (file-name-nondirectory
+ buffer-file-name))
"$")
(expand-file-name (concat "_$_" (make-legal-file-name (buffer-name)) "$"))))
@@ -81,29 +82,3 @@ If the logical name `EMACS_FILE_NAME' is defined, `find-file' that file."
nil)
(setq suspend-hook 'vms-suspend-hook)
-
-(defun vms-read-directory (dirname switches buffer)
- (save-excursion
- (set-buffer buffer)
- (subprocess-command-to-buffer
- (concat "DIRECTORY " switches " " dirname)
- buffer)
- (goto-char (point-min))
- ;; Remove all the trailing blanks.
- (while (search-forward " \n")
- (forward-char -1)
- (delete-horizontal-space))
- (goto-char (point-min))))
-
-(setq dired-listing-switches
- "/SIZE/DATE/OWNER/WIDTH=(FILENAME=32,SIZE=5)")
-
-(setq print-region-function
- '(lambda (start end command ign1 ign2 ign3 &rest switches)
- (write-region start end "sys$login:delete-me.txt")
- (send-command-to-subprocess
- 1
- (concat command
- " sys$login:delete-me.txt/name=""GNUprintbuffer"" "
- (mapconcat 'identity switches " "))
- nil nil nil)))
diff --git a/lisp/vms-patch.elc b/lisp/vms-patch.elc
new file mode 100644
index 00000000000..edc94a6c4b8
--- /dev/null
+++ b/lisp/vms-patch.elc
Binary files differ
diff --git a/lisp/vmsproc.el b/lisp/vmsproc.el
index b4451a40ad0..c974f88248e 100644
--- a/lisp/vmsproc.el
+++ b/lisp/vmsproc.el
@@ -35,63 +35,37 @@
(define-key command-mode-map "\C-u" 'command-kill-line))
(defun subprocess-input (name str)
- "Handles input from a subprocess. Called by Emacs."
- (if display-subprocess-window
+ "Handles input from a subprocess. Called by Emacs."
+ (if display-subprocess-window
(display-buffer subprocess-buf))
- (let ((old-buffer (current-buffer)))
- (set-buffer subprocess-buf)
- (goto-char (point-max))
- (insert str)
- (insert ?\n)
- (set-buffer old-buffer)))
+ (let ((old-buffer (current-buffer)))
+ (set-buffer subprocess-buf)
+ (goto-char (point-max))
+ (insert str)
+ (insert ?\n)
+ (set-buffer old-buffer)))
(defun subprocess-exit (name)
- "Called by Emacs upon subprocess exit."
- (setq subprocess-running nil))
+ "Called by Emacs upon subprocess exit."
+ (setq subprocess-running nil))
(defun start-subprocess ()
- "Spawns an asynchronous subprocess with output redirected to
+ "Spawns an asynchronous subprocess with output redirected to
the buffer *COMMAND*. Within this buffer, use C-m to send
the last line to the subprocess or to bring another line to
the end."
- (if subprocess-running
- (return t))
- (setq subprocess-buf (get-buffer-create "*COMMAND*"))
- (save-excursion
- (set-buffer subprocess-buf)
- (use-local-map command-mode-map))
- (setq subprocess-running (spawn-subprocess 1 'subprocess-input
- 'subprocess-exit))
- ;; Initialize subprocess so it doesn't panic and die upon
- ;; encountering the first error.
- (and subprocess-running
- (send-command-to-subprocess 1 "ON SEVERE_ERROR THEN CONTINUE")))
-
-(defun subprocess-command-to-buffer (command buffer)
- "Execute COMMAND and redirect output into BUFFER."
- (let (cmd args)
- (setq cmd (substring command 0 (string-match " " command)))
- (setq args (substring command (string-match " " command)))
- (call-process cmd nil buffer nil "*dcl*" args)))
-;BUGS: only the output up to the end of the first image activation is trapped.
-; (if (not subprocess-running)
-; (start-subprocess))
-; (save-excursion
-; (set-buffer buffer)
-; (let ((output-filename (concat "SYS$SCRATCH:OUTPUT-FOR-"
-; (getenv "USER") ".LISTING")))
-; (while (file-exists-p output-filename)
-; (delete-file output-filename))
-; (define-logical-name "SYS$OUTPUT" (concat output-filename "-NEW"))
-; (send-command-to-subprocess 1 command)
-; (send-command-to-subprocess 1 (concat
-; "RENAME " output-filename
-; "-NEW " output-filename))
-; (while (not (file-exists-p output-filename))
-; (sleep-for 1))
-; (define-logical-name "SYS$OUTPUT" nil)
-; (insert-file output-filename)
-; (delete-file output-filename))))
+ (if subprocess-running
+ (return t))
+ (setq subprocess-buf (get-buffer-create "*COMMAND*"))
+ (save-excursion
+ (set-buffer subprocess-buf)
+ (use-local-map command-mode-map))
+ (setq subprocess-running (spawn-subprocess 1 'subprocess-input
+ 'subprocess-exit))
+ ;; Initialize subprocess so it doesn't panic and die upon
+ ;; encountering the first error.
+ (and subprocess-running
+ (send-command-to-subprocess 1 "ON SEVERE_ERROR THEN CONTINUE")))
(defun subprocess-command ()
"Starts asynchronous subprocess if not running and switches to its window."
@@ -99,7 +73,7 @@ the end."
(if (not subprocess-running)
(start-subprocess))
(and subprocess-running
- (progn (pop-to-buffer subprocess-buf) (goto-char (point-max)))))
+ (progn (pop-to-buffer subprocess-buf) (goto-char (point-max)))))
(defun command-send-input ()
"If at last line of buffer, sends the current line to
@@ -110,24 +84,24 @@ line to the last line for resubmission."
(let ((current-line (buffer-substring (point)
(progn (end-of-line) (point)))))
(if (eobp)
- (progn
- (if (not subprocess-running)
- (start-subprocess))
- (if subprocess-running
- (progn
- (beginning-of-line)
- (send-command-to-subprocess 1 current-line)
- (if command-prefix-string
- (progn (beginning-of-line) (insert command-prefix-string)))
- (next-line 1))))
+ (progn
+ (if (not subprocess-running)
+ (start-subprocess))
+ (if subprocess-running
+ (progn
+ (beginning-of-line)
+ (send-command-to-subprocess 1 current-line)
+ (if command-prefix-string
+ (progn (beginning-of-line) (insert command-prefix-string)))
+ (next-line 1))))
;; else -- if not at last line in buffer
(end-of-buffer)
(backward-char)
(next-line 1)
(if (string-equal command-prefix-string
- (substring current-line 0 (length command-prefix-string)))
+ (substring current-line 0 (length command-prefix-string)))
(insert (substring current-line (length command-prefix-string)))
- (insert current-line)))))
+ (insert current-line)))))
(defun command-kill-line()
"Kills the current line. Used in command mode."
diff --git a/lisp/vmsproc.elc b/lisp/vmsproc.elc
new file mode 100644
index 00000000000..516fcb0b505
--- /dev/null
+++ b/lisp/vmsproc.elc
Binary files differ
diff --git a/lisp/vmsx.el b/lisp/vmsx.el
deleted file mode 100644
index a68c6de3796..00000000000
--- a/lisp/vmsx.el
+++ /dev/null
@@ -1,137 +0,0 @@
-;; Run asynchronous VMS subprocesses under Emacs
-;; Copyright (C) 1986 Free Software Foundation, Inc.
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 1, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
-;; Written by Mukesh Prasad.
-
-(defvar display-subprocess-window nil
- "If non-nil, the suprocess window is displayed whenever input is received.")
-
-(defvar command-prefix-string "$ "
- "String to insert to distinguish commands entered by user.")
-
-(defvar subprocess-running nil)
-(defvar command-mode-map nil)
-
-(if command-mode-map
- nil
- (setq command-mode-map (make-sparse-keymap))
- (define-key command-mode-map "\C-m" 'command-send-input)
- (define-key command-mode-map "\C-u" 'command-kill-line))
-
-(defun subprocess-input (name str)
- "Handles input from a subprocess. Called by Emacs."
- (if display-subprocess-window
- (display-buffer subprocess-buf))
- (let ((old-buffer (current-buffer)))
- (set-buffer subprocess-buf)
- (goto-char (point-max))
- (insert str)
- (insert ?\n)
- (set-buffer old-buffer)))
-
-(defun subprocess-exit (name)
- "Called by Emacs upon subprocess exit."
- (setq subprocess-running nil))
-
-(defun start-subprocess ()
- "Spawns an asynchronous subprocess with output redirected to
-the buffer *COMMAND*. Within this buffer, use C-m to send
-the last line to the subprocess or to bring another line to
-the end."
- (if subprocess-running
- (return t))
- (setq subprocess-buf (get-buffer-create "*COMMAND*"))
- (save-excursion
- (set-buffer subprocess-buf)
- (use-local-map command-mode-map))
- (setq subprocess-running (spawn-subprocess 1 'subprocess-input
- 'subprocess-exit))
- ;; Initialize subprocess so it doesn't panic and die upon
- ;; encountering the first error.
- (and subprocess-running
- (send-command-to-subprocess 1 "ON SEVERE_ERROR THEN CONTINUE")))
-
-(defvar subprocess-command-to-buffer-tmpdir "SYS$SCRATCH:"
- "*Put temporary files from subprocess-command-to-buffer here.")
-
-(defun subprocess-command-to-buffer (command buffer)
- "Execute command and redirect output into buffer.
-
-BUGS: only the output up to the end of the first image activation is trapped."
- (if (not subprocess-running)
- (start-subprocess))
- (save-excursion
- (set-buffer buffer)
- (let ((output-filename
- (concat subprocess-command-to-buffer-tmpdir
- "OUTPUT-FOR-" (getenv "USER") ".LISTING")))
- (while (file-attributes output-filename)
- (delete-file output-filename))
- (send-command-to-subprocess 1 (concat "DEFINE/USER SYS$OUTPUT "
- output-filename "-NEW"))
- (send-command-to-subprocess 1 command)
- (send-command-to-subprocess 1 (concat "RENAME " output-filename
- "-NEW " output-filename))
- (while (not (file-attributes output-filename))
- (sleep-for 2))
- (insert-file output-filename))))
-
-(defun subprocess-command ()
- "Starts asynchronous subprocess if not running and switches to its window."
- (interactive)
- (if (not subprocess-running)
- (start-subprocess))
- (and subprocess-running
- (progn (pop-to-buffer subprocess-buf) (goto-char (point-max)))))
-
-(defun command-send-input ()
- "If at last line of buffer, sends the current line to
-the spawned subprocess. Otherwise brings back current
-line to the last line for resubmission."
- (interactive)
- (beginning-of-line)
- (let ((current-line (buffer-substring (point)
- (progn (end-of-line) (point)))))
- (if (eobp)
- (progn
- (if (not subprocess-running)
- (start-subprocess))
- (if subprocess-running
- (progn
- (beginning-of-line)
- (send-command-to-subprocess 1 current-line)
- (if command-prefix-string
- (progn (beginning-of-line) (insert command-prefix-string)))
- (next-line 1))))
- ;; else -- if not at last line in buffer
- (end-of-buffer)
- (backward-char)
- (next-line 1)
- (if (string-equal command-prefix-string
- (substring current-line 0 (length command-prefix-string)))
- (insert (substring current-line (length command-prefix-string)))
- (insert current-line)))))
-
-(defun command-kill-line()
- "Kills the current line. Used in command mode."
- (interactive)
- (beginning-of-line)
- (kill-line))
-
-(define-key esc-map "$" 'subprocess-command)
diff --git a/lisp/window.el b/lisp/window.el
index f16d8942824..ced7e20e663 100644
--- a/lisp/window.el
+++ b/lisp/window.el
@@ -1,5 +1,5 @@
;; GNU Emacs window commands aside from those written in C.
-;; Copyright (C) 1985, 1989 Free Software Foundation, Inc.
+;; Copyright (C) 1985 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -18,59 +18,12 @@
;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-(defun count-windows (&optional minibuf)
- "Returns the number of visible windows.
-Optional arg NO-MINI non-nil means don't count the minibuffer
-even if it is active."
- (let ((count 0))
- (walk-windows (function (lambda ()
- (setq count (+ count 1))))
- minibuf)
- count))
-
-(defun balance-windows ()
- "Makes all visible windows the same size (approximately)."
- (interactive)
- (let ((count 0))
- (walk-windows (function (lambda (w)
- (setq count (+ count 1))))
- 'nomini)
- (let ((size (/ (screen-height) count)))
- (walk-windows (function (lambda (w)
- (select-window w)
- (enlarge-window (- size (window-height)))))
- 'nomini))))
-
(defun split-window-vertically (&optional arg)
"Split current window into two windows, one above the other.
-The uppermost window gets ARG lines and the other gets the rest.
-With no argument, split equally or close to it.
-Both windows display the same buffer now current.
-The new selected window is the one that the current value of point
-appears in.
-
-The value of point can change if the text around point
-is hidden by the new mode line."
+This window becomes the uppermost of the two, and gets
+ARG lines. No arg means split equally."
(interactive "P")
- (let ((old-w (selected-window))
- (old-point (point))
- new-w bottom switch)
- (setq new-w (split-window nil (and arg (prefix-numeric-value arg))))
- (save-excursion
- (set-buffer (window-buffer))
- (goto-char (window-start))
- (vertical-motion (window-height))
- (set-window-start new-w (point))
- (if (> (point) (window-point new-w))
- (set-window-point new-w (point)))
- (vertical-motion -1)
- (setq bottom (point)))
- (if (<= bottom (point))
- (set-window-point old-w (1- bottom)))
- (if (< (window-start new-w) old-point)
- (progn
- (set-window-point new-w old-point)
- (select-window new-w)))))
+ (split-window nil (and arg (prefix-numeric-value arg))))
(defun split-window-horizontally (&optional arg)
"Split current window into two windows side by side.
@@ -89,21 +42,7 @@ ARG columns. No arg means split equally."
(interactive "p")
(shrink-window arg t))
-(defun window-config-to-register (name)
- "Save the current window configuration in register REG (a letter).
-It can be later retrieved using \\[M-x register-to-window-config]."
- (interactive "cSave window configuration in register: ")
- (set-register name (current-window-configuration)))
-
-(defun register-to-window-config (name)
- "Restore (make current) the window configuration in register REG (a letter).
-Use with a register previously set with \\[window-config-to-register]."
- (interactive "cRestore window configuration from register: ")
- (set-window-configuration (get-register name)))
-
(define-key ctl-x-map "2" 'split-window-vertically)
(define-key ctl-x-map "5" 'split-window-horizontally)
-(define-key ctl-x-map "6" 'window-config-to-register)
-(define-key ctl-x-map "7" 'register-to-window-config)
(define-key ctl-x-map "}" 'enlarge-window-horizontally)
(define-key ctl-x-map "{" 'shrink-window-horizontally)
diff --git a/lisp/window.elc b/lisp/window.elc
new file mode 100644
index 00000000000..2aba3d72ee7
--- /dev/null
+++ b/lisp/window.elc
Binary files differ
diff --git a/lisp/x-menu.elc b/lisp/x-menu.elc
new file mode 100644
index 00000000000..b7707c57aa7
--- /dev/null
+++ b/lisp/x-menu.elc
Binary files differ
diff --git a/lisp/x-mouse.el b/lisp/x-mouse.el
new file mode 100644
index 00000000000..be201d71900
--- /dev/null
+++ b/lisp/x-mouse.el
@@ -0,0 +1,295 @@
+;; Mouse support for X window system.
+;; Copyright (C) 1985, 1987 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 1, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+(provide 'x-mouse)
+
+(defconst x-button-right (char-to-string 0))
+(defconst x-button-middle (char-to-string 1))
+(defconst x-button-left (char-to-string 2))
+
+(defconst x-button-right-up (char-to-string 4))
+(defconst x-button-middle-up (char-to-string 5))
+(defconst x-button-left-up (char-to-string 6))
+
+(defconst x-button-s-right (char-to-string 16))
+(defconst x-button-s-middle (char-to-string 17))
+(defconst x-button-s-left (char-to-string 18))
+
+(defconst x-button-s-right-up (char-to-string 20))
+(defconst x-button-s-middle-up (char-to-string 21))
+(defconst x-button-s-left-up (char-to-string 22))
+
+(defconst x-button-m-right (char-to-string 32))
+(defconst x-button-m-middle (char-to-string 33))
+(defconst x-button-m-left (char-to-string 34))
+
+(defconst x-button-m-right-up (char-to-string 36))
+(defconst x-button-m-middle-up (char-to-string 37))
+(defconst x-button-m-left-up (char-to-string 38))
+
+(defconst x-button-c-right (char-to-string 64))
+(defconst x-button-c-middle (char-to-string 65))
+(defconst x-button-c-left (char-to-string 66))
+
+(defconst x-button-c-right-up (char-to-string 68))
+(defconst x-button-c-middle-up (char-to-string 69))
+(defconst x-button-c-left-up (char-to-string 70))
+
+(defconst x-button-m-s-right (char-to-string 48))
+(defconst x-button-m-s-middle (char-to-string 49))
+(defconst x-button-m-s-left (char-to-string 50))
+
+(defconst x-button-m-s-right-up (char-to-string 52))
+(defconst x-button-m-s-middle-up (char-to-string 53))
+(defconst x-button-m-s-left-up (char-to-string 54))
+
+(defconst x-button-c-s-right (char-to-string 80))
+(defconst x-button-c-s-middle (char-to-string 81))
+(defconst x-button-c-s-left (char-to-string 82))
+
+(defconst x-button-c-s-right-up (char-to-string 84))
+(defconst x-button-c-s-middle-up (char-to-string 85))
+(defconst x-button-c-s-left-up (char-to-string 86))
+
+(defconst x-button-c-m-right (char-to-string 96))
+(defconst x-button-c-m-middle (char-to-string 97))
+(defconst x-button-c-m-left (char-to-string 98))
+
+(defconst x-button-c-m-right-up (char-to-string 100))
+(defconst x-button-c-m-middle-up (char-to-string 101))
+(defconst x-button-c-m-left-up (char-to-string 102))
+
+(defconst x-button-c-m-s-right (char-to-string 112))
+(defconst x-button-c-m-s-middle (char-to-string 113))
+(defconst x-button-c-m-s-left (char-to-string 114))
+
+(defconst x-button-c-m-s-right-up (char-to-string 116))
+(defconst x-button-c-m-s-middle-up (char-to-string 117))
+(defconst x-button-c-m-s-left-up (char-to-string 118))
+
+(defvar x-process-mouse-hook nil
+ "Hook to run after each mouse event is processed. Should take two
+arguments; the first being a list (XPOS YPOS) corresponding to character
+offset from top left of screen and the second being a specifier for the
+buttons/keys.
+
+This will normally be set on a per-buffer basis.")
+
+(defun x-flush-mouse-queue ()
+ "Process all queued mouse events."
+ ;; A mouse event causes a special character sequence to be given
+ ;; as keyboard input. That runs this function, which process all
+ ;; queued mouse events and returns.
+ (interactive)
+ (while (> (x-mouse-events) 0)
+ (x-proc-mouse-event)
+ (and (boundp 'x-process-mouse-hook)
+ (symbol-value 'x-process-mouse-hook)
+ (funcall x-process-mouse-hook x-mouse-pos x-mouse-item))))
+
+(define-key global-map "\C-c\C-m" 'x-flush-mouse-queue)
+(define-key global-map "\C-x\C-@" 'x-flush-mouse-queue)
+
+(defun x-mouse-select (arg)
+ "Select Emacs window the mouse is on."
+ (let ((start-w (selected-window))
+ (done nil)
+ (w (selected-window))
+ (rel-coordinate nil))
+ (while (and (not done)
+ (null (setq rel-coordinate
+ (coordinates-in-window-p arg w))))
+ (setq w (next-window w))
+ (if (eq w start-w)
+ (setq done t)))
+ (select-window w)
+ rel-coordinate))
+
+(defun x-mouse-keep-one-window (arg)
+ "Select Emacs window mouse is on, then kill all other Emacs windows."
+ (if (x-mouse-select arg)
+ (delete-other-windows)))
+
+(defun x-mouse-select-and-split (arg)
+ "Select Emacs window mouse is on, then split it vertically in half."
+ (if (x-mouse-select arg)
+ (split-window-vertically nil)))
+
+(defun x-mouse-set-point (arg)
+ "Select Emacs window mouse is on, and move point to mouse position."
+ (let* ((relative-coordinate (x-mouse-select arg))
+ margin-column
+ (rel-x (car relative-coordinate))
+ (rel-y (car (cdr relative-coordinate))))
+ (if relative-coordinate
+ (let ((prompt-width (if (eq (selected-window) (minibuffer-window))
+ minibuffer-prompt-width 0)))
+ (move-to-window-line rel-y)
+ (if (eobp)
+ ;; If text ends before the desired line,
+ ;; always position at end of that line.
+ nil
+ (setq margin-column
+ (if (or truncate-lines (> (window-hscroll) 0))
+ (current-column)
+ ;; If we are using line continuation,
+ ;; compensate if first character on a continuation line
+ ;; does not start precisely at the margin.
+ (- (current-column)
+ (% (current-column) (1- (window-width))))))
+ (move-to-column (+ rel-x (1- (max 1 (window-hscroll)))
+ (if (= (point) 1)
+ (- prompt-width) 0)
+ margin-column)))))))
+
+(defun x-mouse-set-mark (arg)
+ "Select Emacs window mouse is on, and set mark at mouse position.
+Display cursor at that position for a second."
+ (if (x-mouse-select arg)
+ (let ((point-save (point)))
+ (unwind-protect
+ (progn (x-mouse-set-point arg)
+ (push-mark nil t)
+ (sit-for 1))
+ (goto-char point-save)))))
+
+(defun x-cut-text (arg &optional kill)
+ "Copy text between point and mouse position into window system cut buffer.
+Save in Emacs kill ring also."
+ (if (coordinates-in-window-p arg (selected-window))
+ (save-excursion
+ (let ((opoint (point))
+ beg end)
+ (x-mouse-set-point arg)
+ (setq beg (min opoint (point))
+ end (max opoint (point)))
+ (x-store-cut-buffer (buffer-substring beg end))
+ (copy-region-as-kill beg end)
+ (if kill (delete-region beg end))))
+ (message "Mouse not in selected window")))
+
+(defun x-paste-text (arg)
+ "Move point to mouse position and insert window system cut buffer contents."
+ (x-mouse-set-point arg)
+ (insert (x-get-cut-buffer)))
+
+(defun x-cut-and-wipe-text (arg)
+ "Kill text between point and mouse; also copy to window system cut buffer."
+ (x-cut-text arg t))
+
+(defun x-mouse-ignore (arg)
+ "Don't do anything.")
+
+(defun x-buffer-menu (arg)
+ "Pop up a menu of buffers for selection with the mouse."
+ (let ((menu
+ (list "Buffer Menu"
+ (cons "Select Buffer"
+ (let ((tail (buffer-list))
+ head)
+ (while tail
+ (let ((elt (car tail)))
+ (if (not (string-match "^ "
+ (buffer-name elt)))
+ (setq head (cons
+ (cons
+ (format
+ "%14s %s"
+ (buffer-name elt)
+ (or (buffer-file-name elt) ""))
+ elt)
+ head))))
+ (setq tail (cdr tail)))
+ (reverse head))))))
+ (switch-to-buffer (or (x-popup-menu arg menu) (current-buffer)))))
+
+(defun x-help (arg)
+ "Enter a menu-based help system."
+ (let ((selection
+ (x-popup-menu
+ arg
+ '("Help" ("Is there a command that..."
+ ("Command apropos" . command-apropos)
+ ("Apropos" . apropos))
+ ("Key Commands <==> Functions"
+ ("List all keystroke commands" . describe-bindings)
+ ("Describe key briefly" . describe-key-briefly)
+ ("Describe key verbose" . describe-key)
+ ("Describe Lisp function" . describe-function)
+ ("Where is this command" . where-is))
+ ("Manual and tutorial"
+ ("Info system" . info)
+ ("Invoke Emacs tutorial" . help-with-tutorial))
+ ("Odds and ends"
+ ("Last 100 Keystrokes" . view-lossage)
+ ("Describe syntax table" . describe-syntax))
+ ("Modes"
+ ("Describe current major mode" . describe-mode)
+ ("List all keystroke commands" . describe-bindings))
+ ("Administrivia"
+ ("View Emacs news" . view-emacs-news)
+ ("View the GNU Emacs license" . describe-copying)
+ ("Describe distribution" . describe-distribution)
+ ("Describe (non)warranty" . describe-no-warranty))))))
+ (and selection (call-interactively selection))))
+
+; Prevent beeps on button-up. If the button isn't bound to anything, it
+; will beep on button-down.
+(define-key mouse-map x-button-right-up 'x-mouse-ignore)
+(define-key mouse-map x-button-middle-up 'x-mouse-ignore)
+(define-key mouse-map x-button-left-up 'x-mouse-ignore)
+(define-key mouse-map x-button-s-right-up 'x-mouse-ignore)
+(define-key mouse-map x-button-s-middle-up 'x-mouse-ignore)
+(define-key mouse-map x-button-s-left-up 'x-mouse-ignore)
+(define-key mouse-map x-button-m-right-up 'x-mouse-ignore)
+(define-key mouse-map x-button-m-middle-up 'x-mouse-ignore)
+(define-key mouse-map x-button-m-left-up 'x-mouse-ignore)
+(define-key mouse-map x-button-c-right-up 'x-mouse-ignore)
+(define-key mouse-map x-button-c-middle-up 'x-mouse-ignore)
+(define-key mouse-map x-button-c-left-up 'x-mouse-ignore)
+(define-key mouse-map x-button-m-s-right-up 'x-mouse-ignore)
+(define-key mouse-map x-button-m-s-middle-up 'x-mouse-ignore)
+(define-key mouse-map x-button-m-s-left-up 'x-mouse-ignore)
+(define-key mouse-map x-button-c-s-right-up 'x-mouse-ignore)
+(define-key mouse-map x-button-c-s-middle-up 'x-mouse-ignore)
+(define-key mouse-map x-button-c-s-left-up 'x-mouse-ignore)
+(define-key mouse-map x-button-c-m-right-up 'x-mouse-ignore)
+(define-key mouse-map x-button-c-m-middle-up 'x-mouse-ignore)
+(define-key mouse-map x-button-c-m-left-up 'x-mouse-ignore)
+(define-key mouse-map x-button-c-m-s-right-up 'x-mouse-ignore)
+(define-key mouse-map x-button-c-m-s-middle-up 'x-mouse-ignore)
+(define-key mouse-map x-button-c-m-s-left-up 'x-mouse-ignore)
+
+(define-key mouse-map x-button-c-s-left 'x-buffer-menu)
+(define-key mouse-map x-button-c-s-middle 'x-help)
+(define-key mouse-map x-button-c-s-right 'x-mouse-keep-one-window)
+(define-key mouse-map x-button-s-middle 'x-cut-text)
+(define-key mouse-map x-button-s-right 'x-paste-text)
+(define-key mouse-map x-button-c-middle 'x-cut-and-wipe-text)
+(define-key mouse-map x-button-c-right 'x-mouse-select-and-split)
+
+(if (= window-system-version 10)
+ (progn
+ (define-key mouse-map x-button-right 'x-mouse-select)
+ (define-key mouse-map x-button-left 'x-mouse-set-mark)
+ (define-key mouse-map x-button-middle 'x-mouse-set-point))
+ (define-key mouse-map x-button-right 'x-cut-text)
+ (define-key mouse-map x-button-left 'x-mouse-set-point)
+ (define-key mouse-map x-button-middle 'x-paste-text))
diff --git a/lisp/x-mouse.elc b/lisp/x-mouse.elc
new file mode 100644
index 00000000000..669405d302d
--- /dev/null
+++ b/lisp/x-mouse.elc
Binary files differ
diff --git a/lisp/xscheme.el b/lisp/xscheme.el
index 8a281cd0cf9..d8fd3d76b25 100644
--- a/lisp/xscheme.el
+++ b/lisp/xscheme.el
@@ -1,5 +1,5 @@
;; Run Scheme under Emacs
-;; Copyright (C) 1986, 1987, 1989, 1990 Free Software Foundation, Inc.
+;; Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -20,7 +20,7 @@
;;; Requires C-Scheme release 5 or later
;;; Changes to Control-G handler require runtime version 13.85 or later
-;;; $Header: xscheme.el,v 1.26 90/09/11 01:51:20 GMT cph Exp $
+;;; $Header: xscheme.el,v 1.23 89/04/28 22:59:40 GMT cph Rel $
(require 'scheme)
@@ -176,15 +176,13 @@ Blank lines separate paragraphs. Semicolons start comments.
\\{scheme-interaction-mode-map}
Entry to this mode calls the value of scheme-interaction-mode-hook
-with no args, if that value is non-nil.
- Likewise with the value of scheme-mode-hook.
- scheme-interaction-mode-hook is called after scheme-mode-hook."
+with no args, if that value is non-nil."
(interactive)
(kill-all-local-variables)
(scheme-interaction-mode-initialize)
(scheme-mode-variables)
(make-local-variable 'xscheme-previous-send)
- (run-hooks 'scheme-mode-hook 'scheme-interaction-mode-hook))
+ (run-hooks 'scheme-interaction-mode-hook))
(defun scheme-interaction-mode-initialize ()
(use-local-map scheme-interaction-mode-map)
@@ -678,8 +676,6 @@ When called, the current buffer will be the Scheme process-buffer.")
(defvar xscheme-process-filter-alist
'((?D xscheme-enter-debugger-mode
xscheme-process-filter:string-action)
- (?E xscheme-eval
- xscheme-process-filter:string-action)
(?P xscheme-set-prompt-variable
xscheme-process-filter:string-action)
(?R xscheme-enter-interaction-mode
@@ -774,9 +770,6 @@ the remaining input.")
(defun xscheme-unsolicited-read-char ()
nil)
-(defun xscheme-eval (string)
- (eval (car (read-from-string string))))
-
(defun xscheme-message (string)
(if (not (zerop (length string)))
(xscheme-write-message-1 string (format ";%s" string))))
diff --git a/lisp/xscheme.elc b/lisp/xscheme.elc
new file mode 100644
index 00000000000..3594cd13c8d
--- /dev/null
+++ b/lisp/xscheme.elc
Binary files differ
diff --git a/lisp/play/yow.el b/lisp/yow.el
index e574b4fa906..0890144d0e6 100644
--- a/lisp/play/yow.el
+++ b/lisp/yow.el
@@ -1,4 +1,4 @@
-;; Copyright (C) 1985, 1987 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 1987 Free Software Foundation
;; This file is part of GNU Emacs.
@@ -16,8 +16,6 @@
;; along with GNU Emacs; see the file COPYING. If not, write to
;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-(provide 'yow)
-
; Randomize the seed in the random number generator.
(random t)
@@ -26,19 +24,22 @@
; (ie strings terminated by ascii 0 characters. Leading whitespace ignored)
; Everything up to the first \000 is a comment.
(defun yow (&optional n interactive)
- "Return or display a Zippy quotation."
- (interactive "P\np")
+ "Return or display a Zippy quotation"
+ (interactive
+ (if current-prefix-arg
+ (list (prefix-numeric-value current-prefix-arg) t)
+ (list nil t)))
(if (null yow-vector)
(setq yow-vector (snarf-yows)))
- (cond (n (setq n (prefix-numeric-value n)))
- ((>= (setq n (random (length yow-vector))) 0))
+ (cond (n)
+ ((>= (setq n (% (random) (length yow-vector))) 0))
(t (setq n (- n))))
(let ((yow (aref yow-vector n)))
(cond ((not interactive)
yow)
((not (string-match "\n" yow))
(delete-windows-on (get-buffer-create "*Help*"))
- (message "%s" yow))
+ (message yow))
(t
(message "Yow!")
(with-output-to-temp-buffer "*Help*"
diff --git a/lisp/yow.elc b/lisp/yow.elc
new file mode 100644
index 00000000000..a9811121404
--- /dev/null
+++ b/lisp/yow.elc
Binary files differ
diff --git a/lispref/book-spine.texinfo b/lispref/book-spine.texinfo
deleted file mode 100644
index 92b224eb833..00000000000
--- a/lispref/book-spine.texinfo
+++ /dev/null
@@ -1,25 +0,0 @@
-\input texinfo @c -*-texinfo-*-
-@c %**start of header
-@setfilename book-spine
-@settitle book-spine
-@c %**end of header
-
-@c need dot in text so first space command works!
-.
-@sp 7
-
-@center @titlefont{GNU Emacs Lisp Reference Manual}
-@sp 5
-@center GNU
-@center Emacs Version 18
-@center for Unix Users
-@sp 5
-
-@center by
-@center Bil Lewis,
-@center Dan LaLiberte,
-@center and the
-@center GNU Manual Group
-@sp 5
-@center Free Software Foundation
-@bye
diff --git a/man/ChangeLog b/man/ChangeLog
new file mode 100644
index 00000000000..2d2d1b3ee4e
--- /dev/null
+++ b/man/ChangeLog
@@ -0,0 +1,46 @@
+Sun Oct 6 12:07:49 1991 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * texindex.c: Include types.h, fcntl.h.
+
+Fri Feb 22 12:39:44 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * getopt.c, getopt1.c, getopt.h, Makefile: New files.
+
+Thu Jan 24 12:41:33 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * texinfo.tex: Delete spurious character at beginning.
+
+Tue Aug 16 13:09:12 1988 Robert J. Chassell (bob at frosted-flakes.ai.mit.edu)
+
+ * emacs.tex: Corrected two typos. No other changes before
+ Version 19 will be made.
+
+ * vip.texinfo: Removed menu entry Adding Lisp Code in node
+ Customization since the menu entry did not point to anything.
+ Also added an @finalout command to remove overfull hboxes from the
+ printed output.
+
+ * cl.texinfo: Added @bye, \input line and @settitle to file.
+ This file is clearly intended to be a chapter of some other work,
+ but the other work does not yet exist.
+
+Mon Jul 25 17:47:38 1988 Robert J. Chassell (bob at frosted-flakes.ai.mit.edu)
+
+ * texinfo.texinfo: Three typos corrected.
+
+Mon Jul 11 18:02:29 1988 Chris Hanson (cph at kleph)
+
+ * texindex.c (indexify): when comparing to initial strings to
+ decide whether to change the header, must use `strncmp' to avoid
+ comparing entire strings of which initials are a substring.
+
+Sun Jun 26 18:46:16 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * texindex.c (sort_in_core, sort_offline, parsefile):
+ Give up on input file if any line doesn't start with backslash.
+
+Mon May 23 10:41:35 1988 Robert J. Chassell (bob at frosted-flakes.ai.mit.edu)
+
+ * emacs.tex: Update information for obtaining TeX distribution from the
+ University of Washington.
+
diff --git a/man/Makefile b/man/Makefile
new file mode 100644
index 00000000000..b214a736dc3
--- /dev/null
+++ b/man/Makefile
@@ -0,0 +1,8 @@
+all: texindex
+
+clean:
+ rm -f texindex.o texindex
+
+texindex: texindex.o
+ $(CC) -o $@ $(LDFLAGS) $(CFLAGS) $?
+texindex.o: texindex.c
diff --git a/man/README b/man/README
new file mode 100644
index 00000000000..a0ddda5b8b8
--- /dev/null
+++ b/man/README
@@ -0,0 +1,23 @@
+This directory contains the Tex sources of the Emacs manual,
+plus the macro package (texinfo.tex) necessary for processing it.
+
+1) Run tex on emacs.tex, producing emacs.cp, emacs.fn, emacs.ky,
+and emacs.vr (unsorted index files), plus emacs.aux (cross ref file).
+
+2) Compile texindex.c, and run it:
+ `texindex emacs.??'
+This produces sorted index files emacs.cps, emacs.fns, etc.
+that are used as input in step 3.
+
+3) Run tex on emacs.tex again.
+
+4) Now you have a dvi file that you can print.
+
+The latest versions of all the intermediate files are supplied,
+so if you want to print the manual with no change, you can start with
+step 3.
+
+
+The software you need to convert the manual into an Info file is
+available in the texinfo2 distribution, which is separate from the
+Emacs distribution (but is included on the Emacs distribution tape).
diff --git a/man/cl.texinfo b/man/cl.texinfo
new file mode 100644
index 00000000000..2f71dc404a1
--- /dev/null
+++ b/man/cl.texinfo
@@ -0,0 +1,853 @@
+\input texinfo @c -*-texinfo-*-
+@setfilename ../info/cl
+@settitle Common Lisp Extensions
+
+@iftex
+@finalout
+@end iftex
+
+Copyright (C) 1987 Cesar Quiroz
+
+@node Top, Generalities,,(DIR)
+@chapter Common Lisp Extensions
+
+The routines described in this chapter provide some of the functionality of
+Common Lisp inside Emacs Lisp.
+
+@menu
+* gen: Generalities. Things you need to know.
+* sym: Symbols. Gensym, gentemp, keyword-p, @dots{}
+* lis: Lists. List*, pairlis, acons, @dots{}
+* seq: Sequences. Every, any, notevery, notany, @dots{}
+* con: Conditionals. When, unless, case, ecase.
+* ite: Iterations. Do, do*, dolist, dotimes, @dots{}
+* mul: Multiple Values. Values, values-list, @dots{}
+* ari: Integer Arithmetic. Floor, ceiling, round, truncate, @dots{}
+* stf: Generalized Variables. Setf and friends.
+* str: Structures. Like Pascal records or C structs.
+* mis: Miscellanea. Odds and ends that didn't fit elsewhere.
+* tod: To Do. Suggestions for future hackery.
+@end menu
+
+@node Generalities, Symbols, Top, Top
+@section Generalities
+
+This section tells you want you need to know about the routines in the file
+@file{cl.el}, so that you can use them. The distribution also includes
+this documentation and perhaps a few example files.
+
+@subsection License, Availability, Maintenance
+
+These files are covered by the GNU Emacs General Public License (if you
+don't know its terms, try @kbd{@key{C-h} @key{C-c}}) and the statement of
+no warranty (again, you can type @kbd{@key{C-h} @key{C-w}} if you don't
+know its terms) also applies to them. @refill
+
+I, Cesar Quiroz, the original author of the software described here, will
+appreciate hearing about bug reports (and fixes), suggestions and comments,
+applying both to the code and to this documentation. I don't promise to
+act on those communications, but whenever they might conduce to
+improvements of this software, I will make those improvements available to
+the general community through the Free Software Foundation. You can reach
+me at the following net addresses:
+@quotation
+quiroz@@seneca.cs.rochester.edu
+quiroz@@rochester.arpa
+@{allegra | seismo | @dots{} @} ! rochester ! quiroz
+CSNET: Cesar Quiroz at node Rochester
+@end quotation
+
+@subsection Purpose and Limitations
+
+These routines were written with two purposes in mind:
+
+@enumerate
+@item
+To make programming in Emacs Lisp even more compatible with Common Lisp.
+Indeed, my original motivation was to have a @code{do} macro.
+@item
+To facilitate to novice Lisp programmers a chance to practice with
+features commonly found only in expensive implementations of Lisp.
+@end enumerate
+
+In order to satisfy these purposes, the routines were written in such a way
+that it is practical to use them inside Emacs: no effort was given to
+implement features that could slow down the host Emacs unnecessarily nor
+require recoding of the Emacs Lisp interpreter.
+
+For instance, no support is given to floating point arithmetic.
+
+So, I have tried to implement a subset of the functionality of Common Lisp.
+Whatever is implemented, has syntactic and semantic properties like the
+equally named features of Common Lisp, but not all the relevant features
+have been implemented (@pxref{To Do}, for some suggestions). When
+deciding what to include, I have tried to strike a balance between these
+constraints:
+
+@enumerate
+@item
+Keep it simple, I didn't want to spend much time in this idea.
+@item
+Keep it compatible with Common Lisp.
+@item
+Keep it flexible, so my code doesn't oppose a better implementation (when
+this looked hard, I just didn't implement the feature).
+@item
+Keep an eye on the intended use of Emacs Lisp: to support an advanced
+editor. I don't expect that more arithmetic support will be as conducive
+to this goal as having better iterations and conditionals will.
+@end enumerate
+
+For background, the reference is ``Common Lisp: The Language'' by Guy
+Steele Jr. (Digital Press, 1984). For all the features described here
+you can assume that the intent has been to provide the syntax and
+semantics of the features of like name in the book. For the most part,
+this documentation will concentrate on how my routines @i{fail} to
+implement Common Lisp faithfully.
+
+@subsubsection Specific Limitations
+
+Emacs Lisp and Common Lisp differ enough to make some of the emulation
+difficult, expensive or nearly impractical. Some specific limitations are
+stated here:
+
+@enumerate
+@item
+Common Lisp is lexically scoped (mostly), while Emacs Lisp is dynamically
+scoped. Things like @code{block}, @code{return}, @code{tagbody} are then
+practically impossible to imitate correctly (in principle, rewriting
+@code{eval}, @code{apply} and a couple of other functions would suffice,
+problem is that such rewriting amounts to a new interpreter on top
+of the old.) Things like @samp{implicit-blocks},
+@samp{implicit-tagbodies} and the like have not been implemented at all.
+Where they are needed, the most you can assume is that I tried to put
+@samp{implicit-progns} around places where it made sense. @refill
+
+@item
+Emacs Lisp's @code{lambda} does not support all the possible argument
+markers. Similarly, @code{defmacro} doesn't support automatic
+destructuring of the calls. An approximation to a keyword-based calling
+style was implemented, mainly for the sake of @code{defstruct}, but is
+not general enough. @refill
+
+@item
+Emacs Lisp supports arithmetic only on integers.
+
+@item
+Emacs Lisp doesn't support many of the basic types of Common Lisp. In
+particular, there are no arrays beyond vectors and strings (although these
+ones are compatible), characters are essentially small
+integers, etc. @refill
+
+@item
+There are no declarations in Emacs Lisp (in the sense of Common Lisp's
+@code{declare}, @code{proclaim}, @dots{}) nor there is a explicit lattice
+of types. These limitations could be effectively overcome from Lisp code
+(to a extent), but I don't see them as a very pressing need, if a need at
+all in Emacs Lisp. @code{defstruct} can be used to generate new types
+that can be recognized at runtime. @refill
+
+@item
+The Emacs Lisp reader is not programmable. The syntax it accepts is
+almost standard, but it preempts '?' as a dispatching macro of sorts.
+The @code{format} function is incompatible with Common Lisp. There
+isn't a `quasi-constant' notation (the usual @code{backquote} of Common
+Lisp). None of these differences causes any problems when writing Emacs
+Lisp (although the lack of backquoting is felt sorely), but they oppose
+a Common Lisp emulation. @refill
+
+@end enumerate
+
+@subsection Loading and Compiling
+
+The file @file{cl.el} provides the @samp{cl} feature, you can use this to
+test whether these routines have been loaded, or to load them from your
+code (by means of @code{(require 'cl)}). The compiled file is a little
+larger than 50K bytes.
+
+If you need to recompile the sources, make sure you load them first on the
+Emacs that will do the recompilation. This is because many syntactic
+characteristics (like the special forms) have been implemented as macros
+and you need to make sure that macros are known to the compiler before they
+are used.
+
+These extensions work correctly when interpreted in a GNU Emacs of
+version 17.64 or beyond. Compiling them requires a more recent byte
+compiler, preferably one strictly younger than version 18.XX.
+
+@subsection On Line Help
+
+The routines in this file have documentation strings, so you can (and
+should) consult them for the exact syntax allowed. That information is
+not repeated in this manual. Some of the routines are also documented
+explicitly in the Common Lisp reference, their doc-strings begin with
+@samp{[cl]} to represent this fact.
+
+The rest (those without the @samp{[cl]} mark) are auxiliary functions or
+macros used by the rest of the implementation. They are not constrained
+by any standard and are advertised only in as much as they can be useful
+in other applications. @refill
+
+Each of the following sections contains a subsection called `Features
+Provided'. It lists briefly the user-visible features of this
+implementation. In its entries, names by themselves refer to functions.
+Macros and variables are identified by a `MACRO' or a `VARIABLE' ahead
+of their names.
+
+@node Symbols, Lists, Generalities, Top
+@section Symbols
+
+The most important omission is that of a @var{packages} mechanism.
+(For a possible implementation, @pxref{To Do}) Whenever a Common Lisp
+function expects a package, I have substituted an obarray. There is a
+hack to have pseudo-keywords, see below. @refill
+
+There are two other notorious omissions over which I haven't lost any
+sleep. The first is the lack of a @code{remprop} function, which could be
+easily provided if needed. The second is the lack of ways to modify the
+print name of a symbol. This one would probably be good only to
+introduce strange bugs, so I don't miss it. @refill
+
+@subsection Features Provided
+
+@table @code
+@item VARIABLE *gensym-index*
+@itemx VARIABLE *gensym-prefix*
+@itemx VARIABLE *gentemp-index*
+@itemx VARIABLE *gentemp-prefix*
+These variables are used to keep the state of the generator of new names.
+Better leave them alone.
+@item gensym
+@itemx gentemp
+These do the same as the Common Lisp names of like names.
+@item MACRO defkeyword
+@itemx keyword-of
+@item keywordp
+These provide the pseudo-keywords implementation.
+@end table
+
+@subsection Keywords
+
+The lack of packages makes it difficult to implement keywords correctly.
+I have provided a macro @code{defkeyword} that takes a symbol and makes
+sure it evaluates to itself. (So, it is like @code{defconst}.) If your
+programs ever need keywords, put a bunch of calls to @code{defkeyword} at
+the beginning of your code, so when loaded they will be in effect. @refill
+
+The (standard) predicate @code{keywordp} tests to see if the given
+symbol's name begins with a colon and then ensures that it evaluates to
+itself. @refill
+
+The function @code{keyword-of} takes a symbol and returns a keyword of
+like name. @refill
+
+@example
+ (keyword-of 'foo)
+:foo
+ (keyword-of ':bar)
+:bar
+@end example
+
+This feature was added mainly to support @code{defstruct} and the tests of
+the sequence functions. It is fragile and easy to fool.
+
+@subsection New Symbols
+
+A common need (especially when writing macros) is to be able to invent new
+names for things. I provide the @code{gensym} and @code{gentemp}
+functions. The global state needed is kept in the variables
+@code{*gentemp-index*}, @code{*gentemp-prefix*}, @code{*gensym-index*} and
+@code{*gensym-prefix*}. Changing them, especially the index ones, is a
+very bad idea. I am not providing the Common Lisp default prefixes ('G'
+for @code{gensym} and 'T' for @code{gentemp}) because of debugging
+paranoia. My default prefixes are harder to come by when giving sane
+names to things. @refill
+
+@node Lists, Sequences, Symbols, Top
+@section Lists
+
+Lists (indeed, conses) are so deeply involved in Lisp that there seems
+to be little need to justify improving the list handling of a Lisp.
+
+Common Lisp, however, is a rather huge Lisp. I haven't provided all the
+functions in the chapter of lists, mainly because some of them could be
+implemented correctly only if keyword arguments were supported.
+That explains why I haven't rushed to provide
+@code{subst}, @code{sublis}, etc. Also, that explains the rather
+temporary nature of the implementation of @code{member} and
+@code{adjoin}. I will welcome any efforts to extend
+this work. @refill
+
+@subsection Features Provided
+
+@table @code
+@item endp
+@itemx list*
+@itemx list-length
+Very standard utilities. List* has proven especially useful to
+overcome the lack of a real @code{backquote}. In addition, things that
+usually required the relatively clumsy
+@example
+(cons 'a (cons 'b oldlist))
+(append (list a b) oldlist)
+@end example
+can now be simply put:
+@example
+(list* 'a 'b oldlist)
+@end example
+See also @code{acons}.
+
+@item member
+Another well known function. Supports test with @code{eql} only.
+
+@item acons
+@itemx pairlis
+These two are part of the standards association lists implementation. I
+am leaving @code{sublis} as an exercise for the reader.
+
+@item adjoin
+Done mainly for the sake of @code{pushnew}.
+
+@item butlast
+@itemx last
+@itemx ldiff
+Occasionally useful ways to access the last cons or a specified tail of
+a list. I don't remember why there isn't a @code{tailp} here.
+
+@item c[ad][ad][ad][ad]r, up to four a's or d's
+These 28 functions (and their setf inverses) have been provided once and
+for all. Many packages contributed to Emacs Lisp contain macros that
+implement some of these, I think this code will make most of them
+unnecessary.
+
+@item first
+@itemx rest
+@itemx second
+@itemx third
+@itemx fourth
+@itemx fifth
+@itemx sixth
+@itemx seventh
+@itemx eighth
+@itemx ninth
+@itemx tenth
+More standard accessors (and their setf inverses). Not particularly
+useful but easy to provide.
+
+@item setnth
+@itemx setnthcdr
+These functions are non-standard. They are here for @code{defsetf}
+purposes only, but they might be useful on their own.
+
+@end table
+
+@node Sequences, Conditionals, Lists, Top
+@section Sequences
+
+Sequences are partly supported in Emacs Lisp (see, for instance, the
+@code{elt} function). This limited support is compatible with Common
+Lisp, so it should be easy to extend. However, the lack of
+keyword arguments makes many of the functions impossible so far (but, as
+mentioned below, a basic framework for that extension
+is provided here). @refill
+
+The functionality really provided here is given by the functions
+(essentially, predicates) @code{every}, @code{some}, @code{notevery},
+@code{notany}. I have found them useful countless times, so I thought
+to provide them before anything else. @refill
+
+That still leaves many omissions, though.
+
+@subsection Features Provided
+
+@table @code
+@item every
+@itemx notany
+@itemx notevery
+@itemx some
+Extremely useful functions. If your favorite Lisp doesn't have them,
+you are missing a lot.
+
+@item setelt
+A setf-inverse to @code{elt}.
+
+@item add-to-klist
+@itemx build-klist
+@itemx extract-from-klist
+A @dfn{klist} is just an alist whose keys are keywords. I based the
+pseudo-keyword argument support of @code{defstruct} on this idea, but
+their best fit is here, as they could help to write the remaining
+sequence-handling functions (@code{find}, @code{substitute}, @dots{})
+that I didn't provide for the lack of a good keyword
+arguments mechanism. @refill
+
+@item elt-satisfies-if-not-p
+@itemx elt-satisfies-if-p
+@itemx elt-satisfies-test-p
+@itemx elts-match-under-klist-p
+The Common Lisp book defines some of the semantics of sequence functions
+in terms of satisfaction of certain tests. These predicates provide
+that functionality, but I haven't integrated them with the rest of the
+extensions. However, I thought it was better to include them anyway, as
+they can serve somebody else as a starting point.
+
+@end table
+
+
+@node Conditionals, Iterations, Sequences, Top
+@section Conditionals
+
+An elementary incompatibility prevents us from producing true Common
+Lisp here. The @code{if} forms are different. In Emacs Lisp, @code{if}
+can take any number of subforms, there being a @var{condition} form, a
+@var{then} form, and after them any number of @var{else} subforms,
+which are executed in an implicit @code{progn}. Moreover, that style is
+widely used in the Emacs sources, so I thought most impractical to break
+with
+it to support Common Lisp's @code{if} (where only one @var{else} form is
+tolerated). For the most part, I use @code{cond} almost always, so it
+doesn't bother me much. If you use single-branch @code{if}s often,
+consider @code{when} or @code{unless} as alternatives. @refill
+
+@code{case} and @code{ecase} are a convenient way to write things that
+usually end up in a very baroque @code{cond}.
+
+@subsection Features Provided
+
+@table @code
+@item MACRO case
+@itemx MACRO ecase
+@itemx MACRO unless
+@itemx MACRO when
+The standard stuff, completely implemented.
+@end table
+
+@node Iterations, Multiple Values, Conditionals, Top
+@section Iterations
+
+Having a @code{do} macro was my original motivation. The alternatives
+in standard Emacs Lisp are either expensive (recursion) or correspond
+directly to the expansion of my macros:
+@example
+ (macroexpand '
+ (do ((i 0) (j 1 (+ 1 j)))
+ ((> j (foo i)) (cons i bar))
+ (setq i (baz i j))))
+
+(let ((i 0) (j 1))
+ (while (not (> j (foo i)))
+ (setq i (baz i j))
+ (psetq j (+ 1 j)))
+ (cons i bar))
+@end example
+So I prefer to leave to the macros the problem of remembering the
+details right.
+
+The incompatibilities are due to the problems already discussed
+(@pxref{Generalities}, for more details). @refill
+
+If you write Emacs Lisp code often, you will find enough uses for these.
+Examples are cooking up a translation table to move @key{C-s} out of the
+way of multiplexers, switches, concentrators and similar fauna, or
+building keymaps. @refill
+
+@subsection Features Provided
+
+@table @code
+@item MACRO do
+@itemx MACRO do*
+@itemx MACRO dolist
+@itemx MACRO dotimes
+The standard, but for the lack of implicit blocks.
+
+@item MACRO loop
+The basic standard one, not the fancy one. As per the book, warns you
+about atomic entries at the surface of the macro (to guarantee that the
+fancy @code{loop} macros can be made standard later).
+
+@item MACRO do-all-symbols
+@itemx MACRO do-symbols
+These operate on obarrays, the default is the current one.
+
+@end table
+
+@node Multiple Values, Integer Arithmetic, Iterations, Top
+@section Multiple Values
+
+The multiple values mechanism covers (simply and elegantly, in my
+opinion) various common needs:
+
+@enumerate
+@item
+The case where a function returns a composite value, that has to be
+assembled in the callee and disassembled in the caller. An example is
+@code{pair-with-newsyms}.
+@item
+The case where a function might cheaply compute redundant information
+that is useful to the caller only eventually. For instance, routines
+that compute quotients and remainders together, whose callers might be
+more often interested in just receiving the quotient.
+@item
+The case of functions that usually return a useful value, but might need
+to elaborate on occasion (say, returning a reason code too).
+@end enumerate
+
+The general idea is that one such function @i{always} returns the extra
+values, but only callers that are aware of this ability receive them.
+Unaware callers just receive the first value.
+
+I think my implementation is pretty much complete. I am imposing no
+limits on the number of multiple values a function may return, so
+I am not providing the constant @code{multiple-values-limit}. You can
+assume multiple values are bound by the memory
+size only. @refill
+
+@subsection Features Provided
+
+@table @code
+@item values
+@itemx values-list
+These are the forms that produce multiple values.
+
+@item MACRO multiple-value-bind
+@itemx MACRO multiple-value-call
+@itemx MACRO multiple-value-list
+@itemx MACRO multiple-value-prog1
+@itemx MACRO multiple-value-setq
+These are the forms that receive multiple values.
+
+@item VARIABLE *mvalues-count*
+@itemx VARIABLE *mvalues-values*
+Used by the implementation. Don't touch them!
+
+@end table
+
+@node Integer Arithmetic, Generalized Variables, Multiple Values, Top
+@section Integer Arithmetic
+
+I have provided most of the functions that are supposed to act on
+integers. Of those that take arbitrary numbers, I have implemented
+those that have a reasonable implementation if restricted to integers
+only, although some more could be added (like a restricted form of
+@code{expt}).
+
+Being a little worried about the bad fame that affects some
+implementations of the '%' C operator, I have taken perhaps unnecessary
+precautions whenever integer division is concerned (see the function
+@code{safe-idiv}). This should be of interest only when dividing
+numbers that might be negative, but I have preferred here to be safe
+rather than fast. @refill
+
+@subsection Features Provided
+
+@table @code
+@item abs
+@itemx signum
+The usual.
+
+@item gcd
+@itemx lcm
+The usual.
+
+@item isqrt
+A rather annoying function. Only use I can think of: to cut short a
+prime number sieve.
+
+@item evenp
+@itemx oddp
+@itemx plusp
+@itemx minusp
+A few predicates that use to come handy.
+
+@item ceiling
+@itemx floor
+@itemx round
+@itemx truncate
+@itemx mod
+@itemx rem
+The intention is to give everybody his preferred way to divide integers.
+I have tried not to depend on the unreliable semantics of C's integer
+division, I hope I got it right. Read the code when in doubt.
+
+@end table
+
+@node Generalized Variables, Structures, Integer Arithmetic, Top
+@section Generalized Variables
+
+This implementation has many limitations. Take a look to see if you
+want to overcome them, the fixes might prove unnecessarily expensive for
+Emacs purposes. The ones I am clearly aware of:
+
+@enumerate
+@item
+Common Lisp suggests an underlying mechanism (the setf-methods) to
+implement generalized variables. I have used ad-hoc ideas that gave me
+a rather trivial implementation
+that suffers from some inflexibility. As a result, @code{defsetf}
+only admits the simplest form and there is no @code{define-modify-macro}
+nor there are functions to handle the (nonexistent) setf-methods. @refill
+@item
+I haven't implemented (I was uninterested) @code{getf} and friends.
+This shouldn't be hard.
+@end enumerate
+
+In addition to providing this mechanism, I have written @code{defsetf}s
+for almost every accessor I thought of. There is room for improvement
+here, as Emacs Lisp provides many types of its own (buffers, windows,
+keymaps, syntax tables, @dots{}) for which pairs of accessors and
+mutators could be defined.
+
+If you want to check whether a function has a setf-inversor, look at the
+property `:setf-update-fn' of its name. This is a characteristic of my
+implementation, not mandated by Common Lisp, so you
+shouldn't use it in code, but only to determine interactively what can
+be setf'd. @refill
+
+@subsection Features Provided
+
+@table @code
+@item MACRO setf
+@itemx MACRO psetf
+Almost complete implementation. @code{Setf} should handle @code{apply}
+inside itself and not in a @code{defsetf}, but the difference is so
+minute I feel lazy about fixing this. @code{Psetf} is the version where
+the assignments occur in parallel. @refill
+
+@item MACRO defsetf
+Very sketchy implementation. I will appreciate if somebody puts some
+time in implementing the whole works of setf-methods and such.
+
+@itemx MACRO incf
+@itemx MACRO decf
+The usual and standard.
+
+@item MACRO pop
+@itemx MACRO push
+@itemx MACRO pushnew
+Should be the usual, but I haven't had the time to test them properly.
+
+@item MACRO rotatef
+@itemx MACRO shiftf
+Very fancy. Good for implementing history rings and such.
+To swap two values, the following forms are equivalent:
+@example
+(rotatef a b)
+(psetf a b b a)
+(psetq a b b a) ;not good for anything but variables
+@end example
+
+@end table
+
+@node Structures, Miscellanea, Generalized Variables, Top
+@section Structures
+
+I haven't had the time to construct a complete implementation of
+structures, but the part provided should stand on its own for many
+purposes. I am not supporting `BOA constructors', nor typed slots (the
+@code{:type}, @code{:named} and @code{:initial-offset} options), nor
+explicit representational types. The rest should be
+pretty much complete. See the example file @file{fractions.el} for an
+idea of how complete the implementation is, and for exercises. @refill
+
+When writing these functions, I noticed I was incurring in lots of
+auxiliaries. I used dollar signs in their names, in the hope that this
+could prevent clashes with user functions. In retrospect, I should have
+done it in the other sections, too.
+
+
+@subsection Features Provided
+
+@table @code
+@item MACRO defstruct
+Create records (a la C structs) and use them as types in your programs.
+Almost completely standard.
+
+@item make$structure$instance
+This non-standard function implements most of the `guts' of the `make-'
+constructors. It can be used as an example of the pseudo
+keyword-arguments.
+@end table
+
+@node Miscellanea, To Do, Structures, Top
+@section Miscellanea
+
+@subsection Features Provided
+
+@table @code
+@item MACRO psetq
+A parallel-assignments version of @code{setq}, makes the expansions of
+@code{do} and @code{do*} be very similar, as they should. Otherwise
+used to swap two values, now superseded by @code{rotatef}. @refill
+
+@item duplicate-symbols-p
+@itemx pair-with-newsyms
+@itemx reassemble-argslists
+@itemx unzip-list
+@itemx zip-lists
+These are utilities I find useful when parsing a call or generating code
+inside a macro. Non standard.
+@end table
+
+@node To Do, , Miscellanea, Top
+@section To Do
+
+No doubt many people will like to extend the functionality of these
+routines. When considering doing so, please try and do it in such a way
+that your implementation of a subset of the functionality of Common Lisp
+is not inimical with a more extensive or more correct one. For
+definiteness, ask yourself the questions:
+
+@itemize @bullet
+@item
+Will my code run under a correct implementation of Common Lisp?
+@item
+Will a correct implementation of Common Lisp run if my code is loaded?
+@end itemize
+@noindent
+
+The first question tests the pertinence of your extensions. The second
+tries to discover ``extensions'' that prevent correct implementations of
+other features. Please tell me if you notice a case in which my code
+fails to pass any of those tests.
+
+The next subsections propose some more extensions. I hope that they are
+attempted by people learning Lisp, as a way to enhance their
+understanding. Of course, experts are also admitted. @refill
+
+@subsection Keyword Arguments
+
+Some effort has been done to handle keywords almost right. For
+instance, a structure constructor (@pxref{Structures}) can be invoked
+with keyword arguments.
+
+Look for the functions whose names have a @samp{klist} in them. They
+were written to facilitate parsing calls with keyword arguments, but I
+haven't done a complete implementation yet. (Note that @code{member},
+@code{assoc} and perhaps some other function, have to be implemented
+independently of the general framework. More details by Email if you
+want to try
+your hand at this.) @refill
+
+@subsection Mapping Functions
+
+There is enough support to write @code{maplist}, @code{mapl}, etc. Emacs
+Lisp already provides some of the mapping functions, the trick now is to
+code the rest in a very efficient manner, so there will be an incentive
+to use @code{maplist} over an explicit iteration. I have a draft
+implementation, but I don't have the time to test it now.
+
+@subsection Complete the current implementation
+
+Some of the features described above are only a partial implementation
+of the Common Lisp features. Things that cry for a more complete form:
+
+@table @code
+@item defsetf
+Only the simplest format is supported. The most general one is needed
+too. Also, try to get @code{define-setf-method} and
+@code{get-setf-method} to work. @refill
+@item define-modify-macro
+Same as above. The modify-macros provided are all ad hoc.
+@item defstruct
+I think my version recognizes all the options and then proceeds to
+ignore most of them. Making sure that at least good error messages are
+produced would be nice. Also, what about BOA constructors?
+@end table
+
+There are other places where your programming ingenuity would help us
+all. For instance, @code{subst}, @code{sublis} and the like could be
+easily provided in the @var{lists} section. (I haven't done it because
+I wanted to have the keyword arguments stuff first.) @refill
+
+@subsection Hash Tables
+
+A very simple implementation of hash tables would admit only strings as
+keys. For each string and a given number of buckets (a prime is
+desirable here), add the numeric values of all (or of a reasonable
+subset) of the characters and assign the bucket whose index is the
+remainder of the sum modulo the (prime) number of buckets.
+
+A more convenient implementation can then be based on using
+@code{prin1-to-string} on an arbitrary Lisp object and using the output
+string as a key. This should make it easy to write @code{sxhash}.
+Remember that one needs to ensure that @code{(equal x y)} should imply
+that @w{@code{(= (sxhash x) (sxhash y))}}; and also that the keys are
+state-less (so you can write them to a
+file and read them back later). @refill
+
+Don't forget to provide a @code{defsetf} for @code{gethash}.
+
+@subsection Packages
+
+Packages should be easy to implement on top of a good hash table
+implementation, either by using it directly or by reusing some shared
+code. Don't worry too much about efficiency: package qualification has
+no run-time cost, only read- and print-time costs.
+
+The difficult thing is to integrate it correctly. You have to replace
+the built-in functions @code{read} and @code{write}. This is not as bad
+as writing a programmable reader, but still a pain. For starters, your
+routines could remember the default definitions of the above mentioned
+functions: @refill
+
+@example
+(setf def-reader (symbol-function 'read))
+(setf def-printer (symbol-function 'print))
+@dots{}
+@end example
+
+And then your specialized functions could just use @code{apply} to
+exercise the default ones, intercepting their activity in time to do the
+package qualification. You might have to do this to @code{prin1},
+@code{prin1-to-string} and friends. @refill
+
+@subsection Streams and Files
+
+This is the first ``To Do'' that might require doing some C programming.
+The purpose is to construct an efficient byte stream abstraction that
+will allow Streams and Files to be handled. Think of stdio, not Unix
+I/O, because Emacs already runs under other operating systems. Also,
+think of doing it in a way that can be generalized easily (for instance,
+streams kept in memory without a file behind, streams as an interface to
+a windowing system, etc.) Of course, the intended syntax is that of
+Common Lisp.
+
+@subsection Reader and Printer
+
+The Emacs Lisp reader (the C function @code{Fread}) is not reentrant nor
+programmable. It could be fixed as Lisp Code, but that is probably
+uglily expensive (as bad as redoing @code{eval} and @code{apply} to
+support lexical scoping). Doing this extension is probably a bad
+idea: a Common Lisp reader is incompatible with Emacs Lisp code (because
+of the @samp{?\} constructions) and the most important rule to keep in
+mind is that this code is running under Emacs, so the host shouldn't be
+burdened too much with these emulations. Same goes for a more complete
+printer (a Common Lisp @code{format} would be incompatible with the
+Emacs Lisp one). @refill
+
+@subsection Backquote
+Even if the reader is not made programmable nor reentrant, a backquoting
+mechanism could come handy. You need to study the way the current
+reader does @code{quote} and hack from there. This might be a more
+worthwhile extension than the complete rewrite of the reader.
+
+@subsection Wild Ideas
+Perhaps there is a way to implement @code{block}, @code{tagbody},
+@code{return} and friends in spite of the dynamic scoping of Emacs Lisp.
+By this, I mean an adequate definition that preserves remotely the
+original intent and still provides a sensible set of constructs. Other
+dynamically scoped Lisps have these features, so implementing them is
+not necessarily impossible.
+
+In the same spirit of these extensions would be to provide a port of
+something like Flavors
+(was there a PD version from Maryland, for Franz perhaps?) and then
+rephrase the language of major and minor modes in an Object Oriented
+paradigm. @refill
+
+Also, the rather gross @code{loop} macros that are out there in many
+Lisp systems could be helpful to some
+people (but then think of a @code{lisp-indent-hook} that handles them
+properly). @refill
+
+@bye
diff --git a/man/emacs.aux b/man/emacs.aux
new file mode 100644
index 00000000000..74a78dfb80b
--- /dev/null
+++ b/man/emacs.aux
@@ -0,0 +1,706 @@
+'xrdef {Distrib-pg}{3}
+'xrdef {Distrib-snt}{}
+'xrdef {License-pg}{5}
+'xrdef {License-snt}{}
+'xrdef {License-pg}{5}
+'xrdef {License-snt}{}
+'xrdef {License-pg}{6}
+'xrdef {License-snt}{}
+'xrdef {License-pg}{9}
+'xrdef {License-snt}{}
+'xrdef {Intro-pg}{11}
+'xrdef {Intro-snt}{}
+'xrdef {Screen-pg}{13}
+'xrdef {Screen-snt}{Chapter'tie1}
+'xrdef {Point-pg}{13}
+'xrdef {Point-snt}{Section'tie1.1}
+'xrdef {Echo Area-pg}{14}
+'xrdef {Echo Area-snt}{Section'tie1.2}
+'xrdef {Mode Line-pg}{14}
+'xrdef {Mode Line-snt}{Section'tie1.3}
+'xrdef {Mode Line-pg}{17}
+'xrdef {Mode Line-snt}{Chapter'tie2}
+'xrdef {Characters-pg}{17}
+'xrdef {Characters-snt}{Section'tie2.1}
+'xrdef {Keys-pg}{18}
+'xrdef {Keys-snt}{Section'tie2.2}
+'xrdef {Commands-pg}{19}
+'xrdef {Commands-snt}{Section'tie2.3}
+'xrdef {Entering Emacs-pg}{21}
+'xrdef {Entering Emacs-snt}{Chapter'tie3}
+'xrdef {Exiting-pg}{21}
+'xrdef {Exiting-snt}{Section'tie3.1}
+'xrdef {Command Switches-pg}{22}
+'xrdef {Command Switches-snt}{Section'tie3.2}
+'xrdef {Basic-pg}{27}
+'xrdef {Basic-snt}{Chapter'tie4}
+'xrdef {Basic-pg}{27}
+'xrdef {Basic-snt}{Section'tie4.1}
+'xrdef {Basic-pg}{28}
+'xrdef {Basic-snt}{Section'tie4.2}
+'xrdef {Basic-pg}{29}
+'xrdef {Basic-snt}{Section'tie4.3}
+'xrdef {Basic-pg}{29}
+'xrdef {Basic-snt}{Section'tie4.4}
+'xrdef {Basic-pg}{30}
+'xrdef {Basic-snt}{Section'tie4.5}
+'xrdef {Blank Lines-pg}{31}
+'xrdef {Blank Lines-snt}{Section'tie4.6}
+'xrdef {Continuation Lines-pg}{31}
+'xrdef {Continuation Lines-snt}{Section'tie4.7}
+'xrdef {Position Info-pg}{32}
+'xrdef {Position Info-snt}{Section'tie4.8}
+'xrdef {Arguments-pg}{33}
+'xrdef {Arguments-snt}{Section'tie4.9}
+'xrdef {Undo-pg}{35}
+'xrdef {Undo-snt}{Chapter'tie5}
+'xrdef {Minibuffer-pg}{37}
+'xrdef {Minibuffer-snt}{Chapter'tie6}
+'xrdef {Minibuffer File-pg}{37}
+'xrdef {Minibuffer File-snt}{Section'tie6.1}
+'xrdef {Minibuffer Edit-pg}{38}
+'xrdef {Minibuffer Edit-snt}{Section'tie6.2}
+'xrdef {Completion-pg}{39}
+'xrdef {Completion-snt}{Section'tie6.3}
+'xrdef {Completion-pg}{39}
+'xrdef {Completion-snt}{Section'tie6.3.1}
+'xrdef {Completion-pg}{40}
+'xrdef {Completion-snt}{Section'tie6.3.2}
+'xrdef {Repetition-pg}{41}
+'xrdef {Repetition-snt}{Section'tie6.4}
+'xrdef {M-x-pg}{43}
+'xrdef {M-x-snt}{Chapter'tie7}
+'xrdef {Help-pg}{45}
+'xrdef {Help-snt}{Chapter'tie8}
+'xrdef {Help-pg}{46}
+'xrdef {Help-snt}{Section'tie8.1}
+'xrdef {Help-pg}{46}
+'xrdef {Help-snt}{Section'tie8.2}
+'xrdef {Help-pg}{47}
+'xrdef {Help-snt}{Section'tie8.3}
+'xrdef {Help-pg}{48}
+'xrdef {Help-snt}{Section'tie8.4}
+'xrdef {Mark-pg}{49}
+'xrdef {Mark-snt}{Chapter'tie9}
+'xrdef {Setting Mark-pg}{49}
+'xrdef {Setting Mark-snt}{Section'tie9.1}
+'xrdef {Using Region-pg}{50}
+'xrdef {Using Region-snt}{Section'tie9.2}
+'xrdef {Marking Objects-pg}{50}
+'xrdef {Marking Objects-snt}{Section'tie9.3}
+'xrdef {Mark Ring-pg}{51}
+'xrdef {Mark Ring-snt}{Section'tie9.4}
+'xrdef {Mark Ring-pg}{53}
+'xrdef {Mark Ring-snt}{Chapter'tie10}
+'xrdef {Killing-pg}{53}
+'xrdef {Killing-snt}{Section'tie10.1}
+'xrdef {Killing-pg}{53}
+'xrdef {Killing-snt}{Section'tie10.1.1}
+'xrdef {Killing-pg}{54}
+'xrdef {Killing-snt}{Section'tie10.1.2}
+'xrdef {Killing-pg}{55}
+'xrdef {Killing-snt}{Section'tie10.1.3}
+'xrdef {Yanking-pg}{55}
+'xrdef {Yanking-snt}{Section'tie10.2}
+'xrdef {Kill Ring-pg}{56}
+'xrdef {Kill Ring-snt}{Section'tie10.2.1}
+'xrdef {Appending Kills-pg}{56}
+'xrdef {Appending Kills-snt}{Section'tie10.2.2}
+'xrdef {Earlier Kills-pg}{57}
+'xrdef {Earlier Kills-snt}{Section'tie10.2.3}
+'xrdef {Accumulating Text-pg}{58}
+'xrdef {Accumulating Text-snt}{Section'tie10.3}
+'xrdef {Rectangles-pg}{59}
+'xrdef {Rectangles-snt}{Section'tie10.4}
+'xrdef {Registers-pg}{61}
+'xrdef {Registers-snt}{Chapter'tie11}
+'xrdef {RegPos-pg}{61}
+'xrdef {RegPos-snt}{Section'tie11.1}
+'xrdef {RegText-pg}{61}
+'xrdef {RegText-snt}{Section'tie11.2}
+'xrdef {RegRect-pg}{62}
+'xrdef {RegRect-snt}{Section'tie11.3}
+'xrdef {Display-pg}{63}
+'xrdef {Display-snt}{Chapter'tie12}
+'xrdef {Scrolling-pg}{63}
+'xrdef {Scrolling-snt}{Section'tie12.1}
+'xrdef {Horizontal Scrolling-pg}{64}
+'xrdef {Horizontal Scrolling-snt}{Section'tie12.2}
+'xrdef {Selective Display-pg}{64}
+'xrdef {Selective Display-snt}{Section'tie12.3}
+'xrdef {Display Vars-pg}{65}
+'xrdef {Display Vars-snt}{Section'tie12.4}
+'xrdef {Search-pg}{67}
+'xrdef {Search-snt}{Chapter'tie13}
+'xrdef {Incremental Search-pg}{67}
+'xrdef {Incremental Search-snt}{Section'tie13.1}
+'xrdef {Incremental Search-pg}{69}
+'xrdef {Incremental Search-snt}{Section'tie13.1.1}
+'xrdef {Nonincremental Search-pg}{70}
+'xrdef {Nonincremental Search-snt}{Section'tie13.2}
+'xrdef {Word Search-pg}{70}
+'xrdef {Word Search-snt}{Section'tie13.3}
+'xrdef {Regexp Search-pg}{71}
+'xrdef {Regexp Search-snt}{Section'tie13.4}
+'xrdef {Regexps-pg}{72}
+'xrdef {Regexps-snt}{Section'tie13.5}
+'xrdef {Search Case-pg}{76}
+'xrdef {Search Case-snt}{Section'tie13.6}
+'xrdef {Replace-pg}{76}
+'xrdef {Replace-snt}{Section'tie13.7}
+'xrdef {Unconditional Replace-pg}{76}
+'xrdef {Unconditional Replace-snt}{Section'tie13.7.1}
+'xrdef {Regexp Replace-pg}{77}
+'xrdef {Regexp Replace-snt}{Section'tie13.7.2}
+'xrdef {Replacement and Case-pg}{77}
+'xrdef {Replacement and Case-snt}{Section'tie13.7.3}
+'xrdef {Query Replace-pg}{78}
+'xrdef {Query Replace-snt}{Section'tie13.7.4}
+'xrdef {Other Repeating Search-pg}{79}
+'xrdef {Other Repeating Search-snt}{Section'tie13.8}
+'xrdef {Fixit-pg}{81}
+'xrdef {Fixit-snt}{Chapter'tie14}
+'xrdef {Kill Errors-pg}{81}
+'xrdef {Kill Errors-snt}{Section'tie14.1}
+'xrdef {Transpose-pg}{81}
+'xrdef {Transpose-snt}{Section'tie14.2}
+'xrdef {Fixing Case-pg}{82}
+'xrdef {Fixing Case-snt}{Section'tie14.3}
+'xrdef {Spelling-pg}{82}
+'xrdef {Spelling-snt}{Section'tie14.4}
+'xrdef {Files-pg}{85}
+'xrdef {Files-snt}{Chapter'tie15}
+'xrdef {File Names-pg}{85}
+'xrdef {File Names-snt}{Section'tie15.1}
+'xrdef {Visiting-pg}{86}
+'xrdef {Visiting-snt}{Section'tie15.2}
+'xrdef {Saving-pg}{88}
+'xrdef {Saving-snt}{Section'tie15.3}
+'xrdef {Backup-pg}{90}
+'xrdef {Backup-snt}{Section'tie15.3.1}
+'xrdef {Backup Names-pg}{90}
+'xrdef {Backup Names-snt}{Section'tie15.3.1.1}
+'xrdef {Backup Deletion-pg}{91}
+'xrdef {Backup Deletion-snt}{Section'tie15.3.1.2}
+'xrdef {Backup Copying-pg}{91}
+'xrdef {Backup Copying-snt}{Section'tie15.3.1.3}
+'xrdef {Interlocking-pg}{92}
+'xrdef {Interlocking-snt}{Section'tie15.3.2}
+'xrdef {Reverting-pg}{93}
+'xrdef {Reverting-snt}{Section'tie15.4}
+'xrdef {Auto Save-pg}{94}
+'xrdef {Auto Save-snt}{Section'tie15.5}
+'xrdef {Auto Save Files-pg}{94}
+'xrdef {Auto Save Files-snt}{Section'tie15.5.1}
+'xrdef {Auto Save Control-pg}{94}
+'xrdef {Auto Save Control-snt}{Section'tie15.5.2}
+'xrdef {Recover-pg}{95}
+'xrdef {Recover-snt}{Section'tie15.5.3}
+'xrdef {ListDir-pg}{95}
+'xrdef {ListDir-snt}{Section'tie15.6}
+'xrdef {Dired-pg}{96}
+'xrdef {Dired-snt}{Section'tie15.7}
+'xrdef {Dired Enter-pg}{96}
+'xrdef {Dired Enter-snt}{Section'tie15.7.1}
+'xrdef {Dired Edit-pg}{96}
+'xrdef {Dired Edit-snt}{Section'tie15.7.2}
+'xrdef {Dired Deletion-pg}{97}
+'xrdef {Dired Deletion-snt}{Section'tie15.7.3}
+'xrdef {Dired Immed-pg}{98}
+'xrdef {Dired Immed-snt}{Section'tie15.7.4}
+'xrdef {Misc File Ops-pg}{99}
+'xrdef {Misc File Ops-snt}{Section'tie15.8}
+'xrdef {Buffers-pg}{101}
+'xrdef {Buffers-snt}{Chapter'tie16}
+'xrdef {Select Buffer-pg}{101}
+'xrdef {Select Buffer-snt}{Section'tie16.1}
+'xrdef {List Buffers-pg}{102}
+'xrdef {List Buffers-snt}{Section'tie16.2}
+'xrdef {Misc Buffer-pg}{102}
+'xrdef {Misc Buffer-snt}{Section'tie16.3}
+'xrdef {Kill Buffer-pg}{103}
+'xrdef {Kill Buffer-snt}{Section'tie16.4}
+'xrdef {Several Buffers-pg}{104}
+'xrdef {Several Buffers-snt}{Section'tie16.5}
+'xrdef {Windows-pg}{107}
+'xrdef {Windows-snt}{Chapter'tie17}
+'xrdef {Basic Window-pg}{107}
+'xrdef {Basic Window-snt}{Section'tie17.1}
+'xrdef {Split Window-pg}{107}
+'xrdef {Split Window-snt}{Section'tie17.2}
+'xrdef {Other Window-pg}{108}
+'xrdef {Other Window-snt}{Section'tie17.3}
+'xrdef {Pop Up Window-pg}{109}
+'xrdef {Pop Up Window-snt}{Section'tie17.4}
+'xrdef {Change Window-pg}{109}
+'xrdef {Change Window-snt}{Section'tie17.5}
+'xrdef {Major Modes-pg}{111}
+'xrdef {Major Modes-snt}{Chapter'tie18}
+'xrdef {Choosing Modes-pg}{111}
+'xrdef {Choosing Modes-snt}{Section'tie18.1}
+'xrdef {Indentation-pg}{113}
+'xrdef {Indentation-snt}{Chapter'tie19}
+'xrdef {Indentation Commands-pg}{113}
+'xrdef {Indentation Commands-snt}{Section'tie19.1}
+'xrdef {Tab Stops-pg}{114}
+'xrdef {Tab Stops-snt}{Section'tie19.2}
+'xrdef {Just Spaces-pg}{115}
+'xrdef {Just Spaces-snt}{Section'tie19.3}
+'xrdef {Text-pg}{117}
+'xrdef {Text-snt}{Chapter'tie20}
+'xrdef {Text Mode-pg}{117}
+'xrdef {Text Mode-snt}{Section'tie20.1}
+'xrdef {Nroff Mode-pg}{118}
+'xrdef {Nroff Mode-snt}{Section'tie20.1.1}
+'xrdef {TeX Mode-pg}{118}
+'xrdef {TeX Mode-snt}{Section'tie20.1.2}
+'xrdef {TeX Editing-pg}{119}
+'xrdef {TeX Editing-snt}{Section'tie20.1.2.1}
+'xrdef {TeX Print-pg}{120}
+'xrdef {TeX Print-snt}{Section'tie20.1.2.2}
+'xrdef {Texinfo Mode-pg}{122}
+'xrdef {Texinfo Mode-snt}{Section'tie20.1.3}
+'xrdef {Outline Mode-pg}{122}
+'xrdef {Outline Mode-snt}{Section'tie20.1.4}
+'xrdef {Outline Format-pg}{123}
+'xrdef {Outline Format-snt}{Section'tie20.1.4.1}
+'xrdef {Outline Motion-pg}{124}
+'xrdef {Outline Motion-snt}{Section'tie20.1.4.2}
+'xrdef {Outline Visibility-pg}{124}
+'xrdef {Outline Visibility-snt}{Section'tie20.1.4.3}
+'xrdef {Words-pg}{126}
+'xrdef {Words-snt}{Section'tie20.2}
+'xrdef {Sentences-pg}{127}
+'xrdef {Sentences-snt}{Section'tie20.3}
+'xrdef {Paragraphs-pg}{128}
+'xrdef {Paragraphs-snt}{Section'tie20.4}
+'xrdef {Pages-pg}{129}
+'xrdef {Pages-snt}{Section'tie20.5}
+'xrdef {Filling-pg}{130}
+'xrdef {Filling-snt}{Section'tie20.6}
+'xrdef {Auto Fill-pg}{130}
+'xrdef {Auto Fill-snt}{Section'tie20.6.1}
+'xrdef {Fill Commands-pg}{131}
+'xrdef {Fill Commands-snt}{Section'tie20.6.2}
+'xrdef {Fill Prefix-pg}{132}
+'xrdef {Fill Prefix-snt}{Section'tie20.6.3}
+'xrdef {Case-pg}{132}
+'xrdef {Case-snt}{Section'tie20.7}
+'xrdef {Programs-pg}{135}
+'xrdef {Programs-snt}{Chapter'tie21}
+'xrdef {Program Modes-pg}{135}
+'xrdef {Program Modes-snt}{Section'tie21.1}
+'xrdef {Lists-pg}{136}
+'xrdef {Lists-snt}{Section'tie21.2}
+'xrdef {Defuns-pg}{138}
+'xrdef {Defuns-snt}{Section'tie21.3}
+'xrdef {Grinding-pg}{139}
+'xrdef {Grinding-snt}{Section'tie21.4}
+'xrdef {Basic Indent-pg}{139}
+'xrdef {Basic Indent-snt}{Section'tie21.4.1}
+'xrdef {Multi-line Indent-pg}{140}
+'xrdef {Multi-line Indent-snt}{Section'tie21.4.2}
+'xrdef {Lisp Indent-pg}{141}
+'xrdef {Lisp Indent-snt}{Section'tie21.4.3}
+'xrdef {C Indent-pg}{142}
+'xrdef {C Indent-snt}{Section'tie21.4.4}
+'xrdef {Matching-pg}{145}
+'xrdef {Matching-snt}{Section'tie21.5}
+'xrdef {Comments-pg}{145}
+'xrdef {Comments-snt}{Section'tie21.6}
+'xrdef {Comments-pg}{146}
+'xrdef {Comments-snt}{Section'tie21.6.1}
+'xrdef {Comments-pg}{147}
+'xrdef {Comments-snt}{Section'tie21.6.2}
+'xrdef {Macro Expansion-pg}{148}
+'xrdef {Macro Expansion-snt}{Section'tie21.7}
+'xrdef {Balanced Editing-pg}{148}
+'xrdef {Balanced Editing-snt}{Section'tie21.8}
+'xrdef {Lisp Completion-pg}{148}
+'xrdef {Lisp Completion-snt}{Section'tie21.9}
+'xrdef {Documentation-pg}{149}
+'xrdef {Documentation-snt}{Section'tie21.10}
+'xrdef {Change Log-pg}{149}
+'xrdef {Change Log-snt}{Section'tie21.11}
+'xrdef {Tags-pg}{150}
+'xrdef {Tags-snt}{Section'tie21.12}
+'xrdef {Tag Syntax-pg}{151}
+'xrdef {Tag Syntax-snt}{Section'tie21.12.1}
+'xrdef {Create Tag Table-pg}{151}
+'xrdef {Create Tag Table-snt}{Section'tie21.12.2}
+'xrdef {Select Tag Table-pg}{151}
+'xrdef {Select Tag Table-snt}{Section'tie21.12.3}
+'xrdef {Find Tag-pg}{152}
+'xrdef {Find Tag-snt}{Section'tie21.12.4}
+'xrdef {Tags Search-pg}{153}
+'xrdef {Tags Search-snt}{Section'tie21.12.5}
+'xrdef {Tags Stepping-pg}{154}
+'xrdef {Tags Stepping-snt}{Section'tie21.12.6}
+'xrdef {List Tags-pg}{154}
+'xrdef {List Tags-snt}{Section'tie21.12.7}
+'xrdef {Fortran-pg}{154}
+'xrdef {Fortran-snt}{Section'tie21.13}
+'xrdef {Fortran Motion-pg}{155}
+'xrdef {Fortran Motion-snt}{Section'tie21.13.1}
+'xrdef {Fortran Indent-pg}{155}
+'xrdef {Fortran Indent-snt}{Section'tie21.13.2}
+'xrdef {ForIndent Commands-pg}{155}
+'xrdef {ForIndent Commands-snt}{Section'tie21.13.2.1}
+'xrdef {ForIndent Num-pg}{156}
+'xrdef {ForIndent Num-snt}{Section'tie21.13.2.2}
+'xrdef {ForIndent Conv-pg}{156}
+'xrdef {ForIndent Conv-snt}{Section'tie21.13.2.3}
+'xrdef {ForIndent Vars-pg}{156}
+'xrdef {ForIndent Vars-snt}{Section'tie21.13.2.4}
+'xrdef {Fortran Comments-pg}{157}
+'xrdef {Fortran Comments-snt}{Section'tie21.13.3}
+'xrdef {Fortran Columns-pg}{158}
+'xrdef {Fortran Columns-snt}{Section'tie21.13.4}
+'xrdef {Fortran Abbrev-pg}{159}
+'xrdef {Fortran Abbrev-snt}{Section'tie21.13.5}
+'xrdef {Compiling/Testing-pg}{161}
+'xrdef {Compiling/Testing-snt}{Chapter'tie22}
+'xrdef {Compilation-pg}{161}
+'xrdef {Compilation-snt}{Section'tie22.1}
+'xrdef {Lisp Modes-pg}{163}
+'xrdef {Lisp Modes-snt}{Section'tie22.2}
+'xrdef {Lisp Libraries-pg}{163}
+'xrdef {Lisp Libraries-snt}{Section'tie22.3}
+'xrdef {Loading-pg}{163}
+'xrdef {Loading-snt}{Section'tie22.3.1}
+'xrdef {Compiling Libraries-pg}{164}
+'xrdef {Compiling Libraries-snt}{Section'tie22.3.2}
+'xrdef {Mocklisp-pg}{165}
+'xrdef {Mocklisp-snt}{Section'tie22.3.3}
+'xrdef {Lisp Eval-pg}{165}
+'xrdef {Lisp Eval-snt}{Section'tie22.4}
+'xrdef {Lisp Debug-pg}{167}
+'xrdef {Lisp Debug-snt}{Section'tie22.5}
+'xrdef {Lisp Interaction-pg}{169}
+'xrdef {Lisp Interaction-snt}{Section'tie22.6}
+'xrdef {External Lisp-pg}{169}
+'xrdef {External Lisp-snt}{Section'tie22.7}
+'xrdef {Abbrevs-pg}{171}
+'xrdef {Abbrevs-snt}{Chapter'tie23}
+'xrdef {Defining Abbrevs-pg}{171}
+'xrdef {Defining Abbrevs-snt}{Section'tie23.1}
+'xrdef {Expanding Abbrevs-pg}{172}
+'xrdef {Expanding Abbrevs-snt}{Section'tie23.2}
+'xrdef {Editing Abbrevs-pg}{173}
+'xrdef {Editing Abbrevs-snt}{Section'tie23.3}
+'xrdef {Saving Abbrevs-pg}{174}
+'xrdef {Saving Abbrevs-snt}{Section'tie23.4}
+'xrdef {Dynamic Abbrevs-pg}{175}
+'xrdef {Dynamic Abbrevs-snt}{Section'tie23.5}
+'xrdef {Picture-pg}{177}
+'xrdef {Picture-snt}{Chapter'tie24}
+'xrdef {Basic Picture-pg}{177}
+'xrdef {Basic Picture-snt}{Section'tie24.1}
+'xrdef {Insert in Picture-pg}{178}
+'xrdef {Insert in Picture-snt}{Section'tie24.2}
+'xrdef {Tabs in Picture-pg}{179}
+'xrdef {Tabs in Picture-snt}{Section'tie24.3}
+'xrdef {Rectangles in Picture-pg}{179}
+'xrdef {Rectangles in Picture-snt}{Section'tie24.4}
+'xrdef {Sending Mail-pg}{181}
+'xrdef {Sending Mail-snt}{Chapter'tie25}
+'xrdef {Mail Format-pg}{181}
+'xrdef {Mail Format-snt}{Section'tie25.1}
+'xrdef {Mail Headers-pg}{182}
+'xrdef {Mail Headers-snt}{Section'tie25.2}
+'xrdef {Mail Mode-pg}{183}
+'xrdef {Mail Mode-snt}{Section'tie25.3}
+'xrdef {Rmail-pg}{187}
+'xrdef {Rmail-snt}{Chapter'tie26}
+'xrdef {Rmail Scrolling-pg}{187}
+'xrdef {Rmail Scrolling-snt}{Section'tie26.1}
+'xrdef {Rmail Motion-pg}{188}
+'xrdef {Rmail Motion-snt}{Section'tie26.2}
+'xrdef {Rmail Deletion-pg}{189}
+'xrdef {Rmail Deletion-snt}{Section'tie26.3}
+'xrdef {Rmail Inbox-pg}{190}
+'xrdef {Rmail Inbox-snt}{Section'tie26.4}
+'xrdef {Rmail Files-pg}{191}
+'xrdef {Rmail Files-snt}{Section'tie26.5}
+'xrdef {Rmail Output-pg}{192}
+'xrdef {Rmail Output-snt}{Section'tie26.6}
+'xrdef {Rmail Labels-pg}{193}
+'xrdef {Rmail Labels-snt}{Section'tie26.7}
+'xrdef {Rmail Summary-pg}{195}
+'xrdef {Rmail Summary-snt}{Section'tie26.8}
+'xrdef {Rmail Make Summary-pg}{195}
+'xrdef {Rmail Make Summary-snt}{Section'tie26.8.1}
+'xrdef {Rmail Summary Edit-pg}{196}
+'xrdef {Rmail Summary Edit-snt}{Section'tie26.8.2}
+'xrdef {Rmail Reply-pg}{197}
+'xrdef {Rmail Reply-snt}{Section'tie26.9}
+'xrdef {Rmail Editing-pg}{198}
+'xrdef {Rmail Editing-snt}{Section'tie26.10}
+'xrdef {Rmail Digest-pg}{199}
+'xrdef {Rmail Digest-snt}{Section'tie26.11}
+'xrdef {Rmail Digest-pg}{201}
+'xrdef {Rmail Digest-snt}{Chapter'tie27}
+'xrdef {Recursive Edit-pg}{201}
+'xrdef {Recursive Edit-snt}{Section'tie27.1}
+'xrdef {Narrowing-pg}{202}
+'xrdef {Narrowing-snt}{Section'tie27.2}
+'xrdef {Sorting-pg}{202}
+'xrdef {Sorting-snt}{Section'tie27.3}
+'xrdef {Shell-pg}{205}
+'xrdef {Shell-snt}{Section'tie27.4}
+'xrdef {Single Shell-pg}{205}
+'xrdef {Single Shell-snt}{Section'tie27.4.1}
+'xrdef {Interactive Shell-pg}{205}
+'xrdef {Interactive Shell-snt}{Section'tie27.4.2}
+'xrdef {Shell Mode-pg}{206}
+'xrdef {Shell Mode-snt}{Section'tie27.4.3}
+'xrdef {Hardcopy-pg}{207}
+'xrdef {Hardcopy-snt}{Section'tie27.5}
+'xrdef {Dissociated Press-pg}{208}
+'xrdef {Dissociated Press-snt}{Section'tie27.6}
+'xrdef {Amusements-pg}{209}
+'xrdef {Amusements-snt}{Section'tie27.7}
+'xrdef {Emulation-pg}{209}
+'xrdef {Emulation-snt}{Section'tie27.8}
+'xrdef {Customization-pg}{211}
+'xrdef {Customization-snt}{Chapter'tie28}
+'xrdef {Minor Modes-pg}{211}
+'xrdef {Minor Modes-snt}{Section'tie28.1}
+'xrdef {Variables-pg}{211}
+'xrdef {Variables-snt}{Section'tie28.2}
+'xrdef {Examining-pg}{212}
+'xrdef {Examining-snt}{Section'tie28.2.1}
+'xrdef {Edit Options-pg}{213}
+'xrdef {Edit Options-snt}{Section'tie28.2.2}
+'xrdef {Locals-pg}{214}
+'xrdef {Locals-snt}{Section'tie28.2.3}
+'xrdef {File Variables-pg}{215}
+'xrdef {File Variables-snt}{Section'tie28.2.4}
+'xrdef {Keyboard Macros-pg}{216}
+'xrdef {Keyboard Macros-snt}{Section'tie28.3}
+'xrdef {Basic Kbd Macro-pg}{217}
+'xrdef {Basic Kbd Macro-snt}{Section'tie28.3.1}
+'xrdef {Save Kbd Macro-pg}{218}
+'xrdef {Save Kbd Macro-snt}{Section'tie28.3.2}
+'xrdef {Kbd Macro Query-pg}{218}
+'xrdef {Kbd Macro Query-snt}{Section'tie28.3.3}
+'xrdef {Key Bindings-pg}{219}
+'xrdef {Key Bindings-snt}{Section'tie28.4}
+'xrdef {Keymaps-pg}{219}
+'xrdef {Keymaps-snt}{Section'tie28.4.1}
+'xrdef {Rebinding-pg}{221}
+'xrdef {Rebinding-snt}{Section'tie28.4.2}
+'xrdef {Disabling-pg}{222}
+'xrdef {Disabling-snt}{Section'tie28.4.3}
+'xrdef {Syntax-pg}{223}
+'xrdef {Syntax-snt}{Section'tie28.5}
+'xrdef {Syntax Entry-pg}{223}
+'xrdef {Syntax Entry-snt}{Section'tie28.5.1}
+'xrdef {Syntax Change-pg}{225}
+'xrdef {Syntax Change-snt}{Section'tie28.5.2}
+'xrdef {Init File-pg}{225}
+'xrdef {Init File-snt}{Section'tie28.6}
+'xrdef {Init Syntax-pg}{226}
+'xrdef {Init Syntax-snt}{Section'tie28.6.1}
+'xrdef {Init Examples-pg}{227}
+'xrdef {Init Examples-snt}{Section'tie28.6.2}
+'xrdef {Terminal Init-pg}{228}
+'xrdef {Terminal Init-snt}{Section'tie28.6.3}
+'xrdef {Terminal Init-pg}{231}
+'xrdef {Terminal Init-snt}{Chapter'tie29}
+'xrdef {Debugging Init-pg}{231}
+'xrdef {Debugging Init-snt}{Section'tie29.1}
+'xrdef {Quitting-pg}{231}
+'xrdef {Quitting-snt}{Section'tie29.2}
+'xrdef {Lossage-pg}{232}
+'xrdef {Lossage-snt}{Section'tie29.3}
+'xrdef {Stuck Recursive-pg}{232}
+'xrdef {Stuck Recursive-snt}{Section'tie29.3.1}
+'xrdef {Screen Garbled-pg}{233}
+'xrdef {Screen Garbled-snt}{Section'tie29.3.2}
+'xrdef {Text Garbled-pg}{233}
+'xrdef {Text Garbled-snt}{Section'tie29.3.3}
+'xrdef {Unasked-for Search-pg}{233}
+'xrdef {Unasked-for Search-snt}{Section'tie29.3.4}
+'xrdef {Emergency Escape-pg}{233}
+'xrdef {Emergency Escape-snt}{Section'tie29.3.5}
+'xrdef {Total Frustration-pg}{234}
+'xrdef {Total Frustration-snt}{Section'tie29.3.6}
+'xrdef {Bugs-pg}{234}
+'xrdef {Bugs-snt}{Section'tie29.4}
+'xrdef {Bugs-pg}{235}
+'xrdef {Bugs-snt}{Section'tie29.4.1}
+'xrdef {Bugs-pg}{236}
+'xrdef {Bugs-snt}{Section'tie29.4.2}
+'xrdef {Version 19-pg}{239}
+'xrdef {Version 19-snt}{}
+'xrdef {Basic Changes-pg}{239}
+'xrdef {Basic Changes-snt}{}
+'xrdef {New Facilities-pg}{240}
+'xrdef {New Facilities-snt}{}
+'xrdef {Binding Changes-pg}{242}
+'xrdef {Binding Changes-snt}{}
+'xrdef {Changed Commands-pg}{243}
+'xrdef {Changed Commands-snt}{}
+'xrdef {M-x Changes-pg}{244}
+'xrdef {M-x Changes-snt}{}
+'xrdef {New Commands-pg}{245}
+'xrdef {New Commands-snt}{}
+'xrdef {Search Changes-pg}{247}
+'xrdef {Search Changes-snt}{}
+'xrdef {Filling Changes-pg}{248}
+'xrdef {Filling Changes-snt}{}
+'xrdef {TeX Mode Changes-pg}{248}
+'xrdef {TeX Mode Changes-snt}{}
+'xrdef {Shell Changes-pg}{249}
+'xrdef {Shell Changes-snt}{}
+'xrdef {Spell Changes-pg}{250}
+'xrdef {Spell Changes-snt}{}
+'xrdef {Mail Changes-pg}{251}
+'xrdef {Mail Changes-snt}{}
+'xrdef {Tags Changes-pg}{252}
+'xrdef {Tags Changes-snt}{}
+'xrdef {Info Changes-pg}{253}
+'xrdef {Info Changes-snt}{}
+'xrdef {Dired Changes-pg}{253}
+'xrdef {Dired Changes-snt}{}
+'xrdef {Marks in Dired-pg}{253}
+'xrdef {Marks in Dired-snt}{}
+'xrdef {Multiple Files-pg}{254}
+'xrdef {Multiple Files-snt}{}
+'xrdef {Shell Commands in Dired-pg}{255}
+'xrdef {Shell Commands in Dired-snt}{}
+'xrdef {Dired Regexps-pg}{256}
+'xrdef {Dired Regexps-snt}{}
+'xrdef {Dired Case Conversion-pg}{257}
+'xrdef {Dired Case Conversion-snt}{}
+'xrdef {Comparison in Dired-pg}{257}
+'xrdef {Comparison in Dired-snt}{}
+'xrdef {Subdirectories in Dired-pg}{258}
+'xrdef {Subdirectories in Dired-snt}{}
+'xrdef {Hiding Subdirectories-pg}{258}
+'xrdef {Hiding Subdirectories-snt}{}
+'xrdef {Editing Dired Buffer-pg}{259}
+'xrdef {Editing Dired Buffer-snt}{}
+'xrdef {Dired and Find-pg}{259}
+'xrdef {Dired and Find-snt}{}
+'xrdef {GNUS-pg}{260}
+'xrdef {GNUS-snt}{}
+'xrdef {Buffers of GNUS-pg}{260}
+'xrdef {Buffers of GNUS-snt}{}
+'xrdef {GNUS Startup-pg}{261}
+'xrdef {GNUS Startup-snt}{}
+'xrdef {Summary of GNUS-pg}{261}
+'xrdef {Summary of GNUS-snt}{}
+'xrdef {Calendar/Diary-pg}{263}
+'xrdef {Calendar/Diary-snt}{}
+'xrdef {Calendar-pg}{263}
+'xrdef {Calendar-snt}{}
+'xrdef {Diary Entries-pg}{264}
+'xrdef {Diary Entries-snt}{}
+'xrdef {Displaying Diary-pg}{264}
+'xrdef {Displaying Diary-snt}{}
+'xrdef {New Entries-pg}{265}
+'xrdef {New Entries-snt}{}
+'xrdef {European Calendar Style-pg}{266}
+'xrdef {European Calendar Style-snt}{}
+'xrdef {Simple and Fancy-pg}{266}
+'xrdef {Simple and Fancy-snt}{}
+'xrdef {Other Diary Features-pg}{267}
+'xrdef {Other Diary Features-snt}{}
+'xrdef {Startup Diary-pg}{267}
+'xrdef {Startup Diary-snt}{}
+'xrdef {Printing Diary-pg}{267}
+'xrdef {Printing Diary-snt}{}
+'xrdef {Version Control-pg}{268}
+'xrdef {Version Control-snt}{}
+'xrdef {Concepts of VC-pg}{268}
+'xrdef {Concepts of VC-snt}{}
+'xrdef {Editing with VC-pg}{269}
+'xrdef {Editing with VC-snt}{}
+'xrdef {Variables for Check-in/out-pg}{270}
+'xrdef {Variables for Check-in/out-snt}{}
+'xrdef {Log Entries-pg}{271}
+'xrdef {Log Entries-snt}{}
+'xrdef {Change Logs and VC-pg}{271}
+'xrdef {Change Logs and VC-snt}{}
+'xrdef {Comparing Versions-pg}{273}
+'xrdef {Comparing Versions-snt}{}
+'xrdef {VC Status-pg}{274}
+'xrdef {VC Status-snt}{}
+'xrdef {Renaming and VC-pg}{274}
+'xrdef {Renaming and VC-snt}{}
+'xrdef {Snapshots-pg}{274}
+'xrdef {Snapshots-snt}{}
+'xrdef {Making Snapshots-pg}{274}
+'xrdef {Making Snapshots-snt}{}
+'xrdef {Snapshot Caveats-pg}{275}
+'xrdef {Snapshot Caveats-snt}{}
+'xrdef {Version Headers-pg}{276}
+'xrdef {Version Headers-snt}{}
+'xrdef {Emerge-pg}{277}
+'xrdef {Emerge-snt}{}
+'xrdef {Overview of Emerge-pg}{277}
+'xrdef {Overview of Emerge-snt}{}
+'xrdef {Submodes of Emerge-pg}{278}
+'xrdef {Submodes of Emerge-snt}{}
+'xrdef {State of Difference-pg}{279}
+'xrdef {State of Difference-snt}{}
+'xrdef {Merge Commands-pg}{280}
+'xrdef {Merge Commands-snt}{}
+'xrdef {Exiting Emerge-pg}{281}
+'xrdef {Exiting Emerge-snt}{}
+'xrdef {Combining in Emerge-pg}{281}
+'xrdef {Combining in Emerge-snt}{}
+'xrdef {Fine Points of Emerge-pg}{282}
+'xrdef {Fine Points of Emerge-snt}{}
+'xrdef {Debuggers-pg}{282}
+'xrdef {Debuggers-snt}{}
+'xrdef {Starting GUD-pg}{282}
+'xrdef {Starting GUD-snt}{}
+'xrdef {Debugger Operation-pg}{283}
+'xrdef {Debugger Operation-snt}{}
+'xrdef {Commands of GUD-pg}{283}
+'xrdef {Commands of GUD-snt}{}
+'xrdef {GUD Customization-pg}{284}
+'xrdef {GUD Customization-snt}{}
+'xrdef {Other New Modes-pg}{285}
+'xrdef {Other New Modes-snt}{}
+'xrdef {Asm Mode-pg}{285}
+'xrdef {Asm Mode-snt}{}
+'xrdef {Edebug Mode-pg}{286}
+'xrdef {Edebug Mode-snt}{}
+'xrdef {Editing Binary Files-pg}{286}
+'xrdef {Editing Binary Files-snt}{}
+'xrdef {Key Sequence Changes-pg}{286}
+'xrdef {Key Sequence Changes-snt}{}
+'xrdef {Hook Changes-pg}{288}
+'xrdef {Hook Changes-snt}{}
+'xrdef {Manifesto-pg}{291}
+'xrdef {Manifesto-snt}{}
+'xrdef {Manifesto-pg}{291}
+'xrdef {Manifesto-snt}{}
+'xrdef {Manifesto-pg}{291}
+'xrdef {Manifesto-snt}{}
+'xrdef {Manifesto-pg}{292}
+'xrdef {Manifesto-snt}{}
+'xrdef {Manifesto-pg}{292}
+'xrdef {Manifesto-snt}{}
+'xrdef {Manifesto-pg}{292}
+'xrdef {Manifesto-snt}{}
+'xrdef {Manifesto-pg}{293}
+'xrdef {Manifesto-snt}{}
+'xrdef {Manifesto-pg}{293}
+'xrdef {Manifesto-snt}{}
+'xrdef {Manifesto-pg}{294}
+'xrdef {Manifesto-snt}{}
+'xrdef {Glossary-pg}{301}
+'xrdef {Glossary-snt}{}
+'xrdef {Key Index-pg}{317}
+'xrdef {Key Index-snt}{}
+'xrdef {Command Index-pg}{323}
+'xrdef {Command Index-snt}{}
+'xrdef {Variable Index-pg}{331}
+'xrdef {Variable Index-snt}{}
+'xrdef {Concept Index-pg}{335}
+'xrdef {Concept Index-snt}{}
diff --git a/man/emacs.cps b/man/emacs.cps
new file mode 100644
index 00000000000..7d94a3a6bb8
--- /dev/null
+++ b/man/emacs.cps
@@ -0,0 +1,400 @@
+\initial {A}
+\entry {A and B buffers (Emerge)}{277}
+\entry {Abbrev mode}{171}
+\entry {abbrevs}{171}
+\entry {aborting}{232}
+\entry {Adaptive Fill mode}{248}
+\entry {againformation}{208}
+\entry {American date style (Calendar, V19)}{266}
+\entry {apropos}{47}
+\entry {arguments (from shell)}{22}
+\entry {arguments, prefix and numeric}{33}
+\entry {arrow keys}{246}
+\entry {ASCII}{17}
+\entry {Asm mode \r {(V19)}}{285}
+\entry {astronomical calendar}{263}
+\entry {attribute (Rmail)}{193}
+\entry {Auto Fill mode}{130}
+\entry {Auto-Save mode}{94}
+\entry {autoload}{164}
+\initial {B}
+\entry {Backtrace mode}{167}
+\entry {backup file}{90}
+\entry {backups, automatic deleting of}{91}
+\entry {batch mode}{23}
+\entry {binding}{19}
+\entry {blank lines}{31, 147}
+\entry {body lines (Outline mode)}{123}
+\entry {boredom}{209}
+\entry {buffer locking}{92}
+\entry {buffer menu}{104}
+\entry {Buffer Menu mode}{104}
+\entry {Buffer Menu mode \r {(V19)}}{285}
+\entry {buffers}{101}
+\entry {buggestion}{208}
+\entry {bugs}{234}
+\entry {byte code}{164}
+\initial {C}
+\entry {C mode}{135}
+\entry {C-}{17}
+\entry {C-g}{231}
+\entry {C{\tt\char43}{\tt\char43} mode \r {(V19)}}{285}
+\entry {calendar \r {(V19)}}{263}
+\entry {case conversion}{82, 132}
+\entry {case conversion of file names \r {(V19)}}{257}
+\entry {centering}{131}
+\entry {change buffers}{101}
+\entry {change log}{149}
+\entry {character set}{17}
+\entry {checking in files}{268}
+\entry {checking out files}{268}
+\entry {choosing a mode}{111}
+\entry {clipping text}{53}
+\entry {command}{19, 219}
+\entry {command history}{41}
+\entry {command line arguments}{22}
+\entry {command name}{219}
+\entry {comments}{145}
+\entry {compilation errors}{161}
+\entry {completion}{39}
+\entry {completion (symbol names)}{148}
+\entry {continuation line}{31}
+\entry {Control}{17}
+\entry {Control-Meta}{136}
+\entry {copying files}{100}
+\entry {copying text}{55}
+\entry {crashes}{94}
+\entry {creating files}{87}
+\entry {current buffer}{101}
+\entry {current stack frame}{167}
+\entry {cursor}{13, 27}
+\entry {customization}{19, 141, 211}
+\entry {cutting}{53}
+\initial {D}
+\entry {dates, style of writing (Calendar, V19)}{266}
+\entry {DBX}{282}
+\entry {debugger}{167}
+\entry {debuggers}{282}
+\entry {default argument}{37}
+\entry {defuns}{138}
+\entry {deletion}{27, 53}
+\entry {deletion (of files)}{96, 99}
+\entry {deletion (Rmail)}{189}
+\entry {diary and Emacs startup (V19)}{267}
+\entry {diary display (V19)}{264}
+\entry {diary entries (V19)}{264}
+\entry {diary entries, inserting (V19)}{265}
+\entry {digest message}{199}
+\entry {directory listing}{95}
+\entry {Dired}{96}
+\entry {Dired in V19}{253}
+\entry {Dired mode}{96}
+\entry {Dired multiple file ops (V19)}{254}
+\entry {disabled command}{222}
+\entry {disassemble}{165}
+\entry {display of diary (V19)}{264}
+\entry {display time}{16}
+\entry {Distribution}{6}
+\entry {doctor}{234}
+\entry {drastic changes}{93}
+\entry {dribble file}{237}
+\entry {dynamic abbrevs}{175}
+\initial {E}
+\entry {echo area}{14}
+\entry {Edebug mode \r {(V19)}}{286}
+\entry {Edit-Abbrevs mode}{174}
+\entry {editing binary files \r {(V19)}}{286}
+\entry {editing level, recursive}{201, 232}
+\entry {EDT}{209}
+\entry {Electric Nroff mode}{118}
+\entry {Eliza}{234}
+\entry {Emacs initialization file}{225}
+\entry {Emacs version}{236}
+\entry {Emacs-Lisp mode}{165}
+\entry {Emerge (V19)}{277}
+\entry {entering Emacs}{21}
+\entry {environment}{205}
+\entry {error log}{161}
+\entry {ESC replacing META key}{17}
+\entry {etags program}{151}
+\entry {European calendar style (V19)}{266}
+\entry {European date style (Calendar, V19)}{266}
+\entry {exiting}{21, 201}
+\entry {expanded subdirectory (Dired, V19)}{258}
+\entry {expanding subdirectories in Dired (V19)}{258}
+\entry {expansion (of abbrevs)}{171}
+\entry {expansion of C macros}{148}
+\entry {expression}{136}
+\entry {expressions, regular}{71}
+\entry {expunging (Rmail)}{189}
+\initial {F}
+\entry {Fancy Diary mode (V19)}{266}
+\entry {file dates}{92}
+\entry {file directory}{95}
+\entry {file names}{85}
+\entry {files}{29, 85, 86}
+\entry {fill prefix}{132}
+\entry {filling}{130}
+\entry {\code {find} and Dired}{259}
+\entry {flow control in V19}{241}
+\entry {formfeed}{129}
+\entry {Fortran mode}{155}
+\entry {forward a message}{198}
+\entry {French revolutionary calendar}{263}
+\entry {ftp}{241}
+\entry {function}{19, 219}
+\entry {function keys (V19)}{286}
+\initial {G}
+\entry {GDB}{282}
+\entry {General Public License}{5}
+\entry {global keymap}{219}
+\entry {global substitution}{76}
+\entry {{\smallcaps gnus}}{260}
+\entry {goal column}{29}
+\entry {graphic characters}{27}
+\entry {grinding}{139}
+\initial {H}
+\entry {hardcopy}{207}
+\entry {header (TeX mode)}{121}
+\entry {headerline (Dired, V19)}{258}
+\entry {headers (of mail message)}{182}
+\entry {heading lines (Outline mode)}{123}
+\entry {Hebrew calendar}{263}
+\entry {help}{45}
+\entry {Hexl mode \r {(V19)}}{286}
+\entry {hiding in Dired (Dired, V19)}{258}
+\entry {history of commands}{41}
+\entry {history, in minibuffer}{240}
+\entry {hook variable (V19)}{288}
+\entry {hooks for files}{87}
+\entry {horizontal scrolling}{64}
+\initial {I}
+\entry {ignoriginal}{208}
+\entry {in-situ subdirectory (Dired, V19)}{258}
+\entry {inbox file}{190}
+\entry {Incremental search in V19}{247}
+\entry {indentation}{113, 139, 145}
+\entry {Indented Text mode}{117}
+\entry {Inferior Lisp mode}{169}
+\entry {inferior process}{161}
+\entry {Inferior Scheme mode}{163}
+\entry {Info mode in V19}{253}
+\entry {init file}{225}
+\entry {inserted subdirectory (Dired, V19)}{258}
+\entry {insertion}{27}
+\entry {interlocking buffers}{92}
+\entry {invisible lines}{122}
+\entry {Islamic calendar}{263}
+\entry {ISO commercial calendar}{263}
+\entry {\code {ispell} program \r {(V19)}}{250}
+\initial {J}
+\entry {Julian calendar}{264}
+\entry {Julian day number}{263}
+\entry {justification}{131}
+\initial {K}
+\entry {key}{18}
+\entry {key rebinding, permanent}{225}
+\entry {key rebinding, this session}{221}
+\entry {key sequence changes (V19)}{286}
+\entry {keyboard macros}{216}
+\entry {keymap}{19, 219}
+\entry {kill ring}{55}
+\entry {killing}{53}
+\entry {killing Emacs}{21}
+\initial {L}
+\entry {label (Rmail)}{193}
+\entry {LaTeX}{118}
+\entry {libraries}{163}
+\entry {license to copy Emacs}{5}
+\entry {line number}{32}
+\entry {Lisp Interaction mode}{169}
+\entry {Lisp mode}{135, 163}
+\entry {list}{136}
+\entry {listing a directory}{95}
+\entry {loading Lisp code}{163}
+\entry {local keymap}{219}
+\entry {local variables}{214}
+\entry {local variables and Auto Fill}{216}
+\entry {local variables in files}{215}
+\entry {locking and version control}{268}
+\entry {locking buffers}{92}
+\initial {M}
+\entry {M-}{17}
+\entry {macro expansion in C}{148}
+\entry {mail}{181}
+\entry {mail arrival}{16}
+\entry {Mail mode}{183}
+\entry {Mail mode in V19}{251}
+\entry {major modes}{111}
+\entry {make}{161}
+\entry {margin position}{212}
+\entry {mark}{49}
+\entry {mark ring}{51}
+\entry {Markov chain}{208}
+\entry {Marks in Dired (V19)}{253}
+\entry {master file}{268}
+\entry {matching parentheses}{145}
+\entry {Mayan calendar}{264}
+\entry {merge buffer (Emerge)}{277}
+\entry {merging files (V19)}{277}
+\entry {message}{181, 187}
+\entry {message number}{187}
+\entry {Meta}{17, 126}
+\entry {minibuffer}{37, 43, 220}
+\entry {minibuffer history}{240}
+\entry {minor modes}{211}
+\entry {mistakes, correcting}{35, 81}
+\entry {mocklisp}{165}
+\entry {mode hook}{136}
+\entry {mode line}{14, 211}
+\entry {mode selection}{111}
+\entry {modified (buffer)}{87}
+\entry {mouse buttons (V19)}{286}
+\entry {moving text}{55}
+\entry {Multiple file ops, Dired (V19)}{254}
+\initial {N}
+\entry {named configurations (RCS)}{275}
+\entry {narrowing}{202}
+\entry {newline}{27}
+\entry {nonincremental search}{70}
+\entry {normal hook (V19)}{288}
+\entry {nroff}{118}
+\entry {Nroff mode}{118}
+\entry {numeric arguments}{33}
+\initial {O}
+\entry {option}{211, 212}
+\entry {Options mode}{213}
+\entry {other editors}{209}
+\entry {Outline mode}{122}
+\entry {outlines}{122}
+\entry {outragedy}{208}
+\entry {Overwrite mode}{211}
+\initial {P}
+\entry {pages}{129}
+\entry {paragraphs}{128}
+\entry {parentheses}{145}
+\entry {pasting}{55}
+\entry {per-buffer variables}{214}
+\entry {Picture mode}{177}
+\entry {pictures}{177}
+\entry {point}{13, 27}
+\entry {prefix arguments}{33}
+\entry {prefix key}{18}
+\entry {presidentagon}{208}
+\entry {primary mail file}{187}
+\entry {Printing diary (V19)}{267}
+\entry {prompt}{37}
+\entry {properbose}{208}
+\initial {Q}
+\entry {query replace}{78}
+\entry {quitting}{231}
+\entry {quitting (in search)}{68}
+\entry {quoting}{27}
+\initial {R}
+\entry {RCS}{268}
+\entry {read-only buffer}{102}
+\entry {reading netnews}{260}
+\entry {rebinding keys, permanently}{225}
+\entry {rebinding keys, this session}{221}
+\entry {rectangles}{59}
+\entry {rectangles and Picture mode}{179}
+\entry {recursive editing level}{201, 232}
+\entry {recursive minibuffer}{39}
+\entry {regexp}{71}
+\entry {region}{49, 133}
+\entry {registered file}{268}
+\entry {registers}{61}
+\entry {regular expression}{71}
+\entry {remote file access}{241}
+\entry {replacement}{76}
+\entry {reply to a message}{197}
+\entry {restriction}{202}
+\entry {right margin position}{212}
+\entry {Rmail}{187}
+\entry {Rmail in V19}{251}
+\entry {Rmail mode}{187}
+\entry {Rmail Summary mode}{196}
+\initial {S}
+\entry {saving}{86}
+\entry {SCCS}{268}
+\entry {Scheme mode}{135, 163}
+\entry {scratch buffer}{169}
+\entry {screen}{13}
+\entry {scrolling}{63}
+\entry {SDB}{282}
+\entry {searching}{67}
+\entry {selected buffer}{101}
+\entry {selected window}{107}
+\entry {selection of mode}{111}
+\entry {selective display}{122}
+\entry {self-documentation}{45}
+\entry {sentences}{127}
+\entry {setting variables}{212}
+\entry {sexp}{136}
+\entry {shell commands}{205}
+\entry {shell commands, Dired V19}{255}
+\entry {Shell mode}{206}
+\entry {Shell mode in V19}{249}
+\entry {Simple Diary mode (V19)}{266}
+\entry {simultaneous editing}{92}
+\entry {snapshots and version control}{274}
+\entry {sorting}{202}
+\entry {sparse keymap}{221}
+\entry {Spell checking in V19}{250}
+\entry {spelling}{82}
+\entry {string substitution}{76}
+\entry {subdirectories in Dired (V19)}{258}
+\entry {subscribe newsgroups (V19)}{261}
+\entry {subshell}{205}
+\entry {subtree (Outline mode)}{125}
+\entry {summaries in Rmail}{196}
+\entry {summary (Rmail)}{195}
+\entry {suspending}{21}
+\entry {switch buffers}{101}
+\entry {syntax table}{127, 223}
+\initial {T}
+\entry {tag table}{150}
+\entry {tags in V19}{252}
+\entry {techniquitous}{208}
+\entry {television}{56}
+\entry {termscript file}{237}
+\entry {TeX}{118}
+\entry {TeX mode}{118}
+\entry {Tex mode in V19}{248}
+\entry {Texinfo mode}{122}
+\entry {text}{117}
+\entry {Text mode}{117}
+\entry {time displayed in mode line}{16}
+\entry {top level}{14}
+\entry {transposition}{81, 126, 138}
+\entry {truncation}{31}
+\entry {typos}{81}
+\initial {U}
+\entry {undeletion (Rmail)}{190}
+\entry {undigestify}{199}
+\entry {undo}{35}
+\entry {universal argument}{33}
+\entry {unsubscribe newsgroups (V19)}{261}
+\initial {V}
+\entry {variables}{211}
+\entry {version control}{268}
+\entry {version of Emacs}{236}
+\entry {versions, keeping old}{91}
+\entry {vi}{209}
+\entry {VI mode}{209}
+\entry {View mode}{103}
+\entry {viewing}{99}
+\entry {visiting}{86}
+\entry {visiting files}{86}
+\initial {W}
+\entry {widening}{202}
+\entry {windows}{107}
+\entry {word search}{70}
+\entry {words}{82, 126, 133}
+\entry {WordStar mode \r {(V19)}}{285}
+\entry {work file}{268}
+\entry {wrapping}{130}
+\initial {X}
+\entry {xon-xoff in V19}{241}
+\initial {Y}
+\entry {yanking}{55}
diff --git a/man/emacs.fns b/man/emacs.fns
new file mode 100644
index 00000000000..34d63f9555c
--- /dev/null
+++ b/man/emacs.fns
@@ -0,0 +1,686 @@
+\initial {A}
+\entry {\code {abbrev-mode}}{171}
+\entry {\code {abbrev-prefix-mark}}{173}
+\entry {\code {abort-recursive-edit}}{201, 232}
+\entry {\code {add-change-log-entry}}{149}
+\entry {\code {add-change-log-entry \r {(V19)}}}{244}
+\entry {\code {add-change-log-entry-other-window}}{150}
+\entry {\code {add-global-abbrev}}{171}
+\entry {\code {add-hook \r {(V19)}}}{289}
+\entry {\code {add-mode-abbrev}}{172}
+\entry {\code {add-name-to-file}}{99}
+\entry {\code {append-next-kill}}{57}
+\entry {\code {append-to-buffer}}{58}
+\entry {\code {append-to-file}}{58, 99}
+\entry {\code {apropos}}{47}
+\entry {\code {apropros \r {(V19)}}}{246}
+\entry {\code {ask-user-about-lock}}{92}
+\entry {\code {auto-fill-mode}}{130}
+\entry {\code {auto-save-mode}}{95}
+\initial {B}
+\entry {\code {back-to-indentation}}{113}
+\entry {\code {backward-char}}{28}
+\entry {\code {backward-delete-char-untabify}}{136}
+\entry {\code {backward-kill-sentence}}{55, 81, 127}
+\entry {\code {backward-kill-word}}{55, 81, 126}
+\entry {\code {backward-list}}{137}
+\entry {\code {backward-page}}{129}
+\entry {\code {backward-paragraph}}{128}
+\entry {\code {backward-sentence}}{127}
+\entry {\code {backward-sexp}}{137}
+\entry {\code {backward-text-line}}{118}
+\entry {\code {backward-up-list}}{138}
+\entry {\code {backward-word}}{126}
+\entry {\code {batch-byte-compile}}{165}
+\entry {\code {beginning-of-buffer}}{28}
+\entry {\code {beginning-of-defun}}{138}
+\entry {\code {beginning-of-fortran-subprogram}}{155}
+\entry {\code {beginning-of-line}}{28}
+\entry {\code {buffer-enable-undo}}{35}
+\entry {\code {buffer-menu}}{104}
+\entry {\code {byte-compile-file}}{164}
+\entry {\code {byte-recompile-directory}}{164}
+\initial {C}
+\entry {\code {c-beginning-of-statement \r {(V19)}}}{246}
+\entry {\code {c-end-of-statement \r {(V19)}}}{246}
+\entry {\code {c-fill-paragraph \r {(V19)}}}{246, 248}
+\entry {\code {c-indent-line}}{139}
+\entry {\code {c-macro-expand}}{148}
+\entry {\code {c-up-conditional \r {(V19)}}}{246}
+\entry {\code {calendar-count-days-region \r {(V19)}}}{263}
+\entry {\code {calendar-cursor-holidays \r {(V19)}}}{264}
+\entry {\code {calendar-goto-astro-date \r {(V19)}}}{263}
+\entry {\code {calendar-goto-french-date \r {(V19)}}}{263}
+\entry {\code {calendar-goto-hebrew-date \r {(V19)}}}{263}
+\entry {\code {calendar-goto-islamic-date \r {(V19)}}}{263}
+\entry {\code {calendar-goto-iso-date \r {(V19)}}}{263}
+\entry {\code {calendar-goto-julian-date \r {(V19)}}}{264}
+\entry {\code {calendar-print-astro-date \r {(V19)}}}{263}
+\entry {\code {calendar-print-french-date \r {(V19)}}}{263}
+\entry {\code {calendar-print-hebrew-date \r {(V19)}}}{263}
+\entry {\code {calendar-print-islamic-date \r {(V19)}}}{263}
+\entry {\code {calendar-print-iso-date \r {(V19)}}}{263}
+\entry {\code {calendar-print-julian-date \r {(V19)}}}{264}
+\entry {\code {calendar-print-mayan-date \r {(V19)}}}{264}
+\entry {\code {calendar-unmark \r {(V19)}}}{264, 265}
+\entry {\code {call-last-kbd-macro}}{217}
+\entry {\code {cancel-debug-on-entry}}{167}
+\entry {\code {capitalize-word}}{82, 133}
+\entry {\code {center-line}}{131}
+\entry {\code {clear-rectangle}}{60}
+\entry {\code {comint-continue-subjob \r {(V19)}}}{250}
+\entry {\code {comint-dynamic-complete \r {(V19)}}}{249}
+\entry {\code {comint-dynamic-list-completions \r {(V19)}}}{249}
+\entry {\code {comint-kill-output \r {(V19)}}}{250}
+\entry {\code {comint-next-input \r {(V19)}}}{249}
+\entry {\code {comint-next-matching-input \r {(V19)}}}{249}
+\entry {\code {comint-previous-input \r {(V19)}}}{249}
+\entry {\code {comint-previous-matching-input \r {(V19)}}}{249}
+\entry {\code {comint-show-output \r {(V19)}}}{250}
+\entry {\code {command-apropos}}{47}
+\entry {\code {comment-region \r {(V19)}}}{246}
+\entry {\code {compare-windows}}{108}
+\entry {\code {compare-windows \r {(V19)}}}{244}
+\entry {\code {compile}}{161}
+\entry {\code {compile \r {(V19)}}}{245}
+\entry {\code {convert-mocklisp-buffer}}{165}
+\entry {\code {copy-file}}{100}
+\entry {\code {copy-last-shell-input}}{207}
+\entry {\code {copy-region-as-kill}}{56}
+\entry {\code {copy-to-buffer}}{58}
+\entry {\code {copy-to-register}}{62}
+\entry {\code {count-lines-page}}{129}
+\entry {\code {count-lines-region}}{32}
+\entry {\code {count-matches}}{79}
+\entry {\code {count-text-lines}}{118}
+\initial {D}
+\entry {\code {dabbrev-expand}}{175}
+\entry {\code {dbx \r {(V19)}}}{282}
+\entry {\code {debug}}{167}
+\entry {\code {debug-on-entry}}{167}
+\entry {\code {default-value}}{215}
+\entry {\code {define-abbrevs}}{175}
+\entry {\code {define-key}}{222}
+\entry {\code {delete-backward-char}}{27, 53, 81}
+\entry {\code {delete-blank-lines}}{31, 54}
+\entry {\code {delete-char}}{53, 178}
+\entry {\code {delete-file}}{99}
+\entry {\code {delete-horizontal-space}}{54, 114}
+\entry {\code {delete-indentation}}{54, 114}
+\entry {\code {delete-matching-lines}}{79}
+\entry {\code {delete-non-matching-lines}}{79}
+\entry {\code {delete-other-windows}}{109}
+\entry {\code {delete-rectangle}}{60}
+\entry {\code {delete-window}}{109}
+\entry {\code {describe-bindings}}{48}
+\entry {\code {describe-copying}}{48}
+\entry {\code {describe-distribution}}{48}
+\entry {\code {describe-function}}{46, 149}
+\entry {\code {describe-key}}{46}
+\entry {\code {describe-key-briefly}}{46}
+\entry {\code {describe-mode}}{48}
+\entry {\code {describe-no-warranty}}{48}
+\entry {\code {describe-syntax}}{225}
+\entry {\code {describe-variable}}{47, 149, 212}
+\entry {\code {diary \r {(V19)}}}{265}
+\entry {\code {diff \r {(V19)}}}{247}
+\entry {\code {diff-backup \r {(V19)}}}{247}
+\entry {\code {digit-argument}}{33}
+\entry {\code {dired}}{96}
+\entry {\code {dired-backup-diff \r {(V19)}}}{257}
+\entry {\code {dired-change-marks \r {(V19)}}}{254}
+\entry {\code {dired-diff \r {(V19)}}}{257}
+\entry {\code {dired-do-byte-compile \r {(V19)}}}{255}
+\entry {\code {dired-do-chgrp \r {(V19)}}}{255}
+\entry {\code {dired-do-chmod \r {(V19)}}}{255}
+\entry {\code {dired-do-chown \r {(V19)}}}{255}
+\entry {\code {dired-do-compress \r {(V19)}}}{255}
+\entry {\code {dired-do-copy \r {(V19)}}}{254}
+\entry {\code {dired-do-copy-regexp \r {(V19)}}}{256}
+\entry {\code {dired-do-hardlink \r {(V19)}}}{255}
+\entry {\code {dired-do-hardlink-regexp \r {(V19)}}}{256}
+\entry {\code {dired-do-kill-lines \r {(V19)}}}{259}
+\entry {\code {dired-do-load \r {(V19)}}}{255}
+\entry {\code {dired-do-print \r {(V19)}}}{255}
+\entry {\code {dired-do-redisplay \r {(V19)}}}{259}
+\entry {\code {dired-do-rename \r {(V19)}}}{255}
+\entry {\code {dired-do-rename-regexp \r {(V19)}}}{256}
+\entry {\code {dired-do-shell-command \r {(V19)}}}{255}
+\entry {\code {dired-do-symlink \r {(V19)}}}{255}
+\entry {\code {dired-do-symlink-regexp \r {(V19)}}}{256}
+\entry {\code {dired-downcase \r {(V19)}}}{257}
+\entry {\code {dired-flag-files-regexp \r {(V19)}}}{256}
+\entry {\code {dired-hide-all \r {(V19)}}}{259}
+\entry {\code {dired-hide-subdir \r {(V19)}}}{259}
+\entry {\code {dired-mark \r {(V19)}}}{254}
+\entry {\code {dired-mark-directories \r {(V19)}}}{254}
+\entry {\code {dired-mark-executables \r {(V19)}}}{254}
+\entry {\code {dired-mark-files-regexp \r {(V19)}}}{256}
+\entry {\code {dired-mark-symlinks \r {(V19)}}}{254}
+\entry {\code {dired-maybe-insert-subdir \r {(V19)}}}{258}
+\entry {\code {dired-next-subdir \r {(V19)}}}{258}
+\entry {\code {dired-other-window}}{96, 109}
+\entry {\code {dired-prev-subdir \r {(V19)}}}{258}
+\entry {\code {dired-tree-down \r {(V19)}}}{258}
+\entry {\code {dired-tree-up \r {(V19)}}}{258}
+\entry {\code {dired-unmark-all-files \r {(V19)}}}{254}
+\entry {\code {dired-upcase \r {(V19)}}}{257}
+\entry {\code {dirs \r {(V19)}}}{250}
+\entry {\code {disable-command}}{222}
+\entry {\code {disassemble}}{165}
+\entry {\code {display-buffer \r {(V19)}}}{242}
+\entry {\code {display-time}}{16}
+\entry {\code {dissociated-press}}{208}
+\entry {\code {do-auto-save}}{95}
+\entry {\code {doctor}}{234}
+\entry {\code {down-list}}{138}
+\entry {\code {downcase-region}}{133}
+\entry {\code {downcase-word}}{82, 133}
+\initial {E}
+\entry {\code {edebug-defun \r {(V19)}}}{286}
+\entry {\code {edit-abbrevs}}{174}
+\entry {\code {edit-abbrevs-redefine}}{174}
+\entry {\code {edit-options}}{213}
+\entry {\code {edit-picture}}{177}
+\entry {\code {edit-tab-stops}}{114, 117}
+\entry {\code {edit-tab-stops-note-changes}}{114}
+\entry {\code {edt-emulation-off}}{209}
+\entry {\code {edt-emulation-on}}{209}
+\entry {\code {electric-nroff-mode}}{118}
+\entry {\code {emacs-lisp-mode}}{165}
+\entry {\code {emacs-version}}{236}
+\entry {\code {emerge-auto-advance-mode \r {(V19)}}}{279}
+\entry {\code {emerge-buffers \r {(V19)}}}{277}
+\entry {\code {emerge-buffers-with-ancestor \r {(V19)}}}{277}
+\entry {\code {emerge-files \r {(V19)}}}{277}
+\entry {\code {emerge-files-with-ancestor \r {(V19)}}}{277}
+\entry {\code {emerge-skip-prefers-mode \r {(V19)}}}{279}
+\entry {\code {enable-command}}{222}
+\entry {\code {end-kbd-macro}}{217}
+\entry {\code {end-of-buffer}}{28}
+\entry {\code {end-of-defun}}{138}
+\entry {\code {end-of-fortran-subprogram}}{155}
+\entry {\code {end-of-line}}{28}
+\entry {\code {enlarge-window}}{110}
+\entry {\code {enlarge-window-horizontally}}{110}
+\entry {\code {evade-flow-control-on \r {(V19)}}}{241}
+\entry {\code {eval-current-buffer}}{166}
+\entry {\code {eval-defun}}{166}
+\entry {\code {eval-expression}}{166}
+\entry {\code {eval-last-sexp}}{166}
+\entry {\code {eval-region}}{166}
+\entry {\code {exchange-point-and-mark}}{50}
+\entry {\code {execute-extended-command}}{43}
+\entry {\code {exit-recursive-edit}}{201}
+\entry {\code {expand-abbrev}}{172}
+\entry {\code {expand-region-abbrevs}}{173}
+\initial {F}
+\entry {\code {fancy-diary-display \r {(V19)}}}{266}
+\entry {\code {fill-c{\tt\char43}{\tt\char43}-comment \r {(V19)}}}{285}
+\entry {\code {fill-individual-paragraphs}}{132}
+\entry {\code {fill-individual-paragraphs \r {(V19)}}}{248}
+\entry {\code {fill-paragraph}}{131}
+\entry {\code {fill-region}}{131}
+\entry {\code {fill-region-as-paragraph}}{131}
+\entry {\code {fill-region-as-paragraph \r {(V19)}}}{248}
+\entry {\code {find-alternate-file}}{87}
+\entry {\code {find-dired}}{260}
+\entry {\code {find-file}}{87}
+\entry {\code {find-file-other-frame \r {(V19)}}}{245}
+\entry {\code {find-file-other-window}}{87, 109}
+\entry {\code {find-file-read-only-other-window \r {(V19)}}}{246}
+\entry {\code {find-grep-dired}}{260}
+\entry {\code {find-name-dired}}{259}
+\entry {\code {find-tag}}{152}
+\entry {\code {find-tag-other-frame \r {(V19)}}}{246}
+\entry {\code {find-tag-other-window}}{109, 153}
+\entry {\code {find-tag-regexp \r {(V19)}}}{252}
+\entry {\code {fortran-column-ruler}}{159}
+\entry {\code {fortran-comment-region}}{158}
+\entry {\code {fortran-indent-line}}{156}
+\entry {\code {fortran-indent-subprogram}}{156}
+\entry {\code {fortran-mode}}{155}
+\entry {\code {fortran-next-statement}}{155}
+\entry {\code {fortran-previous-statement}}{155}
+\entry {\code {fortran-split-line}}{156}
+\entry {\code {fortran-window-create}}{159}
+\entry {\code {forward-char}}{28}
+\entry {\code {forward-list}}{137}
+\entry {\code {forward-page}}{129}
+\entry {\code {forward-paragraph}}{128}
+\entry {\code {forward-sentence}}{127}
+\entry {\code {forward-sexp}}{137}
+\entry {\code {forward-text-line}}{118}
+\entry {\code {forward-word}}{126}
+\initial {G}
+\entry {\code {gdb \r {(V19)}}}{282}
+\entry {\code {global-set-key}}{221}
+\entry {\code {global-set-key \r {(V19)}}}{288}
+\entry {\code {gnus \r {(V19)}}}{260}
+\entry {\code {gnus-Group-exit \r {(V19)}}}{261}
+\entry {\code {gnus-Group-list-all-groups \r {(V19)}}}{261}
+\entry {\code {gnus-Group-list-groups \r {(V19)}}}{261}
+\entry {\code {gnus-Group-next-group \r {(V19)}}}{262}
+\entry {\code {gnus-Group-next-unread-group \r {(V19)}}}{262}
+\entry {\code {gnus-Group-prev-group \r {(V19)}}}{262}
+\entry {\code {gnus-Group-prev-unread-group \r {(V19)}}}{262}
+\entry {\code {gnus-Group-read-group \r {(V19)}}}{262}
+\entry {\code {gnus-Group-suspend \r {(V19)}}}{261}
+\entry {\code {gnus-Group-unsubscribe-current-group \r {(V19)}}}{261}
+\entry {\code {gnus-Summary-isearch-article \r {(V19)}}}{262}
+\entry {\code {gnus-Summary-next-page \r {(V19)}}}{262}
+\entry {\code {gnus-Summary-next-same-subject \r {(V19)}}}{262}
+\entry {\code {gnus-Summary-next-subject \r {(V19)}}}{262}
+\entry {\code {gnus-Summary-prev-page \r {(V19)}}}{262}
+\entry {\code {gnus-Summary-prev-same-subject \r {(V19)}}}{262}
+\entry {\code {gnus-Summary-prev-subject \r {(V19)}}}{262}
+\entry {\code {gnus-Summary-search-article-forward \r {(V19)}}}{262}
+\entry {\code {gnus-Summary-sort-by-author \r {(V19)}}}{262}
+\entry {\code {gnus-Summary-sort-by-date \r {(V19)}}}{262}
+\entry {\code {gnus-Summary-sort-by-number \r {(V19)}}}{262}
+\entry {\code {gnus-Summary-sort-by-subject \r {(V19)}}}{262}
+\entry {\code {goto-char}}{28}
+\entry {\code {goto-line}}{28}
+\entry {\code {grep}}{162}
+\entry {\code {gud-cont \r {(V19)}}}{284}
+\entry {\code {gud-def \r {(V19)}}}{284}
+\entry {\code {gud-down \r {(V19)}}}{284}
+\entry {\code {gud-finish \r {(V19)}}}{284}
+\entry {\code {gud-next \r {(V19)}}}{284}
+\entry {\code {gud-refresh \r {(V19)}}}{283}
+\entry {\code {gud-step \r {(V19)}}}{284}
+\entry {\code {gud-stepi \r {(V19)}}}{284}
+\entry {\code {gud-up \r {(V19)}}}{284}
+\initial {H}
+\entry {\code {hanoi}}{209}
+\entry {\code {help-with-tutorial}}{27, 48}
+\entry {\code {hide-body}}{125}
+\entry {\code {hide-entry}}{125}
+\entry {\code {hide-leaves}}{125}
+\entry {\code {hide-subtree}}{125}
+\entry {\code {holidays \r {(V19)}}}{264}
+\initial {I}
+\entry {\code {iconify-frame \r {(V19)}}}{245}
+\entry {\code {indent-c-exp}}{140}
+\entry {\code {indent-for-comment}}{145}
+\entry {\code {indent-new-comment-line}}{147}
+\entry {\code {indent-region}}{114, 141}
+\entry {\code {indent-relative}}{114}
+\entry {\code {indent-rigidly}}{114}
+\entry {\code {indent-sexp}}{140}
+\entry {\code {indented-text-mode}}{117}
+\entry {\code {info}}{48}
+\entry {\code {insert-abbrevs}}{175}
+\entry {\code {insert-anniversary-diary-entry \r {(V19)}}}{265}
+\entry {\code {insert-block-diary-entry \r {(V19)}}}{266}
+\entry {\code {insert-cyclic-diary-entry \r {(V19)}}}{266}
+\entry {\code {insert-diary-entry \r {(V19)}}}{265}
+\entry {\code {insert-file}}{99}
+\entry {\code {insert-kbd-macro}}{218}
+\entry {\code {insert-monthly-diary-entry \r {(V19)}}}{265}
+\entry {\code {insert-parentheses}}{148}
+\entry {\code {insert-register}}{62}
+\entry {\code {insert-weekly-diary-entry \r {(V19)}}}{265}
+\entry {\code {insert-yearly-diary-entry \r {(V19)}}}{265}
+\entry {\code {interrupt-shell-subjob}}{207}
+\entry {\code {inverse-add-global-abbrev}}{172}
+\entry {\code {inverse-add-mode-abbrev}}{172}
+\entry {\code {isearch \r {(V19)}}}{247}
+\entry {\code {isearch-backward}}{67}
+\entry {\code {isearch-backward-regexp}}{71}
+\entry {\code {isearch-backward-regexp \r {(V19)}}}{245}
+\entry {\code {isearch-forward}}{67}
+\entry {\code {isearch-forward-regexp}}{71}
+\entry {\code {ispell-buffer \r {(V19)}}}{250}
+\entry {\code {ispell-region \r {(V19)}}}{250}
+\initial {J}
+\entry {\code {just-one-space}}{54}
+\initial {K}
+\entry {\code {kbd-macro-query}}{218}
+\entry {\code {kill-all-abbrevs}}{172}
+\entry {\code {kill-buffer}}{103}
+\entry {\code {kill-comment}}{146}
+\entry {\code {kill-compilation}}{161}
+\entry {\code {kill-ispell \r {(V19)}}}{250}
+\entry {\code {kill-line}}{54, 55}
+\entry {\code {kill-local-variable}}{214}
+\entry {\code {kill-output-from-shell}}{207}
+\entry {\code {kill-rectangle}}{60}
+\entry {\code {kill-region}}{55}
+\entry {\code {kill-sentence}}{55, 127}
+\entry {\code {kill-sexp}}{55, 137}
+\entry {\code {kill-some-buffers}}{103}
+\entry {\code {kill-word}}{55, 126}
+\initial {L}
+\entry {\code {latex-mode}}{118}
+\entry {\code {LaTeX-mode}}{118}
+\entry {\code {lisp-complete-symbol}}{148}
+\entry {\code {lisp-indent-line}}{139}
+\entry {\code {lisp-interaction-mode}}{169}
+\entry {\code {lisp-mode}}{169}
+\entry {\code {lisp-send-defun}}{170}
+\entry {\code {list-abbrevs}}{173}
+\entry {\code {list-buffers}}{102}
+\entry {\code {list-command-history}}{41}
+\entry {\code {list-directory}}{96}
+\entry {\code {list-matching-lines}}{79}
+\entry {\code {list-options}}{213}
+\entry {\code {list-tags}}{154}
+\entry {\code {load}}{163}
+\entry {\code {load-file}}{163}
+\entry {\code {load-library}}{163}
+\entry {\code {local-set-key}}{221}
+\entry {\code {lpr-buffer}}{208}
+\entry {\code {lpr-region}}{208}
+\initial {M}
+\entry {\code {mail}}{181}
+\entry {\code {mail-cc}}{184}
+\entry {\code {mail-fill-yanked-message}}{185}
+\entry {\code {mail-other-frame \r {(V19)}}}{246}
+\entry {\code {mail-other-window}}{109, 181}
+\entry {\code {mail-send}}{184}
+\entry {\code {mail-send-and-exit}}{184}
+\entry {\code {mail-signature}}{184}
+\entry {\code {mail-subject}}{184}
+\entry {\code {mail-to}}{184}
+\entry {\code {mail-yank-original}}{184, 198}
+\entry {\code {make-local-variable}}{214}
+\entry {\code {make-symbolic-link}}{100}
+\entry {\code {make-symbolic-link \r {(V19)}}}{244}
+\entry {\code {make-variable-buffer-local}}{214}
+\entry {\code {manual-entry}}{149}
+\entry {\code {manual-entry \r {(V19)}}}{245}
+\entry {\code {mark-calendar-holidays \r {(V19)}}}{264}
+\entry {\code {mark-defun}}{51, 138}
+\entry {\code {mark-diary-entries \r {(V19)}}}{265}
+\entry {\code {mark-fortran-subprogram}}{155}
+\entry {\code {mark-page}}{51, 129}
+\entry {\code {mark-paragraph}}{51, 128}
+\entry {\code {mark-sexp}}{51, 138}
+\entry {\code {mark-whole-buffer}}{51}
+\entry {\code {mark-word}}{51, 127}
+\entry {\code {minibuffer-complete}}{39}
+\entry {\code {minibuffer-complete-word}}{40}
+\entry {\code {modify-syntax-entry}}{225}
+\entry {\code {move-over-close-and-reindent}}{148}
+\entry {\code {move-to-window-line}}{28}
+\initial {N}
+\entry {\code {name-last-kbd-macro}}{218}
+\entry {\code {narrow-to-region}}{202}
+\entry {\code {negative-argument}}{33}
+\entry {\code {newline}}{27}
+\entry {\code {newline-and-indent}}{140}
+\entry {\code {next-complex-command}}{42}
+\entry {\code {next-error}}{162}
+\entry {\code {next-file}}{154}
+\entry {\code {next-history-element \r {(V19)}}}{240}
+\entry {\code {next-line}}{28}
+\entry {\code {next-matching-history-element \r {(V19)}}}{240}
+\entry {\code {normal-mode}}{112}
+\entry {\code {not-modified}}{88}
+\entry {\code {nroff-mode}}{118}
+\initial {O}
+\entry {\code {occur}}{79}
+\entry {\code {open-dribble-file}}{237}
+\entry {\code {open-line}}{31}
+\entry {\code {open-rectangle}}{60}
+\entry {\code {open-termscript}}{237}
+\entry {\code {other-window}}{108}
+\entry {\code {outline-backward-same-level}}{124}
+\entry {\code {outline-forward-same-level}}{124}
+\entry {\code {outline-mode}}{122}
+\entry {\code {outline-next-visible-heading}}{124}
+\entry {\code {outline-previous-visible-heading}}{124}
+\entry {\code {outline-up-heading}}{124}
+\entry {\code {overwrite-mode}}{211}
+\initial {P}
+\entry {\code {picture-backward-clear-column}}{178}
+\entry {\code {picture-backward-column}}{177}
+\entry {\code {picture-clear-column}}{178}
+\entry {\code {picture-clear-line}}{178}
+\entry {\code {picture-clear-rectangle}}{180}
+\entry {\code {picture-clear-rectangle-to-register}}{180}
+\entry {\code {picture-forward-column}}{177}
+\entry {\code {picture-motion}}{179}
+\entry {\code {picture-motion-reverse}}{179}
+\entry {\code {picture-move-down}}{177}
+\entry {\code {picture-move-up}}{177}
+\entry {\code {picture-movement-down}}{178}
+\entry {\code {picture-movement-left}}{178}
+\entry {\code {picture-movement-ne}}{178}
+\entry {\code {picture-movement-nw}}{178}
+\entry {\code {picture-movement-right}}{178}
+\entry {\code {picture-movement-se}}{178}
+\entry {\code {picture-movement-sw}}{178}
+\entry {\code {picture-movement-up}}{178}
+\entry {\code {picture-newline}}{178}
+\entry {\code {picture-open-line}}{178}
+\entry {\code {picture-set-tab-stops}}{179}
+\entry {\code {picture-tab}}{179}
+\entry {\code {picture-tab-search}}{179}
+\entry {\code {picture-yank-rectangle}}{180}
+\entry {\code {picture-yank-rectangle-from-register}}{180}
+\entry {\code {plain-tex-mode}}{118}
+\entry {\code {plain-TeX-mode}}{118}
+\entry {\code {point-to-register}}{61}
+\entry {\code {prepend-to-buffer}}{58}
+\entry {\code {previous-complex-command}}{42}
+\entry {\code {previous-history-element \r {(V19)}}}{240}
+\entry {\code {previous-line}}{28}
+\entry {\code {previous-matching-history-element \r {(V19)}}}{240}
+\entry {\code {print-buffer}}{208}
+\entry {\code {print-diary-entries \r {(V19)}}}{267}
+\entry {\code {print-region}}{208}
+\initial {Q}
+\entry {\code {query-replace}}{78}
+\entry {\code {query-replace-regexp}}{78}
+\entry {\code {quietly-read-abbrev-file}}{174}
+\entry {\code {quit-shell-subjob}}{207}
+\entry {\code {quoted-insert}}{27}
+\initial {R}
+\entry {\code {re-search-backward}}{72}
+\entry {\code {re-search-forward}}{72}
+\entry {\code {read-abbrev-file}}{174}
+\entry {\code {recenter}}{28, 63}
+\entry {\code {recover-file}}{95}
+\entry {\code {register-to-point}}{61}
+\entry {\code {reload-ispell \r {(V19)}}}{251}
+\entry {\code {rename-buffer}}{103}
+\entry {\code {rename-file}}{99}
+\entry {\code {repeat-complex-command}}{41}
+\entry {\code {replace-regexp}}{76}
+\entry {\code {replace-string}}{76}
+\entry {\code {reposition-window \r {(V19)}}}{245}
+\entry {\code {revert-buffer}}{93}
+\entry {\code {revert-buffer \r {(Dired, V19)}}}{259}
+\entry {\code {revert-buffer \r {(V19)}}}{240}
+\entry {\code {rmail}}{187}
+\entry {\code {rmail-add-label}}{194}
+\entry {\code {rmail-beginning-of-message}}{188}
+\entry {\code {rmail-continue}}{198}
+\entry {\code {rmail-delete-backward}}{190}
+\entry {\code {rmail-delete-forward}}{190}
+\entry {\code {rmail-edit-current-message}}{199}
+\entry {\code {rmail-expunge}}{190}
+\entry {\code {rmail-forward}}{198}
+\entry {\code {rmail-get-new-mail}}{192}
+\entry {\code {rmail-input}}{191}
+\entry {\code {rmail-kill-label}}{194}
+\entry {\code {rmail-last-message}}{189}
+\entry {\code {rmail-mail}}{198}
+\entry {\code {rmail-next-labeled-message}}{194}
+\entry {\code {rmail-next-message}}{189}
+\entry {\code {rmail-next-undeleted-message}}{189}
+\entry {\code {rmail-output}}{192}
+\entry {\code {rmail-output-to-rmail-file}}{192}
+\entry {\code {rmail-previous-labeled-message}}{194}
+\entry {\code {rmail-previous-message}}{189}
+\entry {\code {rmail-previous-undeleted-message}}{189}
+\entry {\code {rmail-quit}}{187}
+\entry {\code {rmail-reply}}{197}
+\entry {\code {rmail-resend \r {(V19)}}}{251}
+\entry {\code {rmail-retry-failure \r {(V19)}}}{251}
+\entry {\code {rmail-save}}{187}
+\entry {\code {rmail-search}}{189}
+\entry {\code {rmail-show-message}}{189}
+\entry {\code {rmail-summary}}{195}
+\entry {\code {rmail-summary-by-labels}}{194, 195}
+\entry {\code {rmail-summary-by-recipients}}{196}
+\entry {\code {rmail-summary-delete-forward}}{197}
+\entry {\code {rmail-summary-exit}}{197}
+\entry {\code {rmail-summary-goto-msg}}{196}
+\entry {\code {rmail-summary-next-all}}{196}
+\entry {\code {rmail-summary-next-msg}}{196}
+\entry {\code {rmail-summary-previous-all}}{196}
+\entry {\code {rmail-summary-previous-msg}}{196}
+\entry {\code {rmail-summary-quit}}{197}
+\entry {\code {rmail-summary-scroll-msg-down}}{197}
+\entry {\code {rmail-summary-scroll-msg-up}}{197}
+\entry {\code {rmail-summary-undelete}}{197}
+\entry {\code {rmail-toggle-header}}{198}
+\entry {\code {rmail-undelete-previous-message}}{190}
+\entry {\code {run-lisp}}{169}
+\initial {S}
+\entry {\code {save-buffer}}{88}
+\entry {\code {save-buffers-kill-emacs}}{21}
+\entry {\code {save-some-buffers}}{88}
+\entry {\code {scroll-bar-mode \r {(V19)}}}{239}
+\entry {\code {scroll-down}}{63}
+\entry {\code {scroll-left}}{64}
+\entry {\code {scroll-other-window}}{108}
+\entry {\code {scroll-right}}{64}
+\entry {\code {scroll-up}}{63}
+\entry {\code {sdb \r {(V19)}}}{283}
+\entry {\code {search-backward}}{70}
+\entry {\code {search-forward}}{70}
+\entry {\code {self-insert}}{27}
+\entry {\code {send-gud-command \r {(V19)}}}{285}
+\entry {\code {send-invisible \r {(V19)}}}{250}
+\entry {\code {send-shell-input}}{207}
+\entry {\code {set-comment-column}}{147}
+\entry {\code {set-fill-column}}{131}
+\entry {\code {set-fill-prefix}}{132}
+\entry {\code {set-gnu-bindings}}{209}
+\entry {\code {set-goal-column}}{29}
+\entry {\code {set-gosmacs-bindings}}{209}
+\entry {\code {set-mark-command}}{49}
+\entry {\code {set-rmail-inbox-list}}{192}
+\entry {\code {set-selective-display}}{64}
+\entry {\code {set-variable}}{212}
+\entry {\code {set-visited-file-name}}{89}
+\entry {\code {setq-default}}{214}
+\entry {\code {shell}}{205}
+\entry {\code {shell-command}}{205}
+\entry {\code {shell-command-on-region}}{205}
+\entry {\code {shell-send-eof}}{207}
+\entry {\code {show-all}}{125}
+\entry {\code {show-all-diary-entries \r {(V19)}}}{265}
+\entry {\code {show-branches}}{125}
+\entry {\code {show-children}}{125}
+\entry {\code {show-entry}}{125}
+\entry {\code {show-output-from-shell}}{207}
+\entry {\code {show-subtree}}{125}
+\entry {\code {sort-columns}}{204}
+\entry {\code {sort-fields}}{203}
+\entry {\code {sort-lines}}{203}
+\entry {\code {sort-numeric-fields}}{203}
+\entry {\code {sort-pages}}{203}
+\entry {\code {sort-paragraphs}}{203}
+\entry {\code {spell-buffer}}{83}
+\entry {\code {spell-region}}{83}
+\entry {\code {spell-string}}{83}
+\entry {\code {spell-word}}{83}
+\entry {\code {split-line}}{113}
+\entry {\code {split-window-horizontally}}{107}
+\entry {\code {split-window-vertically}}{107}
+\entry {\code {start-kbd-macro}}{217}
+\entry {\code {stop-shell-subjob}}{207}
+\entry {\code {substitute-key-definition}}{222}
+\entry {\code {super-apropos \r {(V19)}}}{246}
+\entry {\code {suspend-emacs}}{21}
+\entry {\code {switch-to-buffer}}{101}
+\entry {\code {switch-to-buffer-other-frame \r {(V19)}}}{245}
+\entry {\code {switch-to-buffer-other-window}}{109}
+\initial {T}
+\entry {\code {tab-to-tab-stop}}{114, 117}
+\entry {\code {tabify}}{115}
+\entry {\code {tags-apropos}}{154}
+\entry {\code {tags-loop-continue}}{153}
+\entry {\code {tags-query-replace}}{153}
+\entry {\code {tags-search}}{153}
+\entry {\code {tex-bibtex-file \r {(V19)}}}{248}
+\entry {\code {TeX-buffer}}{121}
+\entry {\code {TeX-close-LaTeX-block}}{120}
+\entry {\code {tex-close-latex-block \r {(V19)}}}{248}
+\entry {\code {TeX-insert-braces}}{120}
+\entry {\code {TeX-insert-quote}}{120}
+\entry {\code {TeX-kill-job}}{121}
+\entry {\code {tex-latex-block \r {(V19)}}}{248}
+\entry {\code {tex-mode}}{118}
+\entry {\code {TeX-mode}}{118}
+\entry {\code {TeX-print}}{121}
+\entry {\code {TeX-recenter-output-buffer}}{121}
+\entry {\code {TeX-region}}{121}
+\entry {\code {TeX-show-print-queue}}{121}
+\entry {\code {TeX-terminate-paragraph}}{120}
+\entry {\code {tex-view \r {(V19)}}}{248}
+\entry {\code {texinfo-mode}}{122}
+\entry {\code {text-mode}}{117}
+\entry {\code {toggle-read-only}}{102}
+\entry {\code {top-level}}{201, 232}
+\entry {\code {transpose-chars}}{28, 81}
+\entry {\code {transpose-lines}}{82}
+\entry {\code {transpose-sexps}}{82, 138}
+\entry {\code {transpose-words}}{82, 126}
+\initial {U}
+\entry {\code {undigestify-rmail-message}}{199}
+\entry {\code {undo}}{35}
+\entry {\code {unexpand-abbrev}}{173}
+\entry {\code {universal-argument}}{33}
+\entry {\code {untabify}}{115}
+\entry {\code {up-list}}{120}
+\entry {\code {upcase-region}}{133}
+\entry {\code {upcase-word}}{82, 133}
+\initial {V}
+\entry {\code {validate-TeX-buffer}}{120}
+\entry {\code {vc-cancel-version \r {(V19)}}}{270}
+\entry {\code {vc-create-snapshot \r {(V19)}}}{275}
+\entry {\code {vc-diff \r {(V19)}}}{273}
+\entry {\code {vc-directory \r {(V19)}}}{274}
+\entry {\code {vc-insert-headers \r {(V19)}}}{276}
+\entry {\code {vc-print-log \r {(V19)}}}{274}
+\entry {\code {vc-register \r {(V19)}}}{270}
+\entry {\code {vc-rename-file \r {(V19)}}}{274}
+\entry {\code {vc-retrieve-snapshot \r {(V19)}}}{275}
+\entry {\code {vc-revert-buffer \r {(V19)}}}{269}
+\entry {\code {vc-toggle-read-only \r {(V19)}}}{269}
+\entry {\code {vc-update-change-log \r {(V19)}}}{272}
+\entry {\code {vi-mode}}{209}
+\entry {\code {view-buffer}}{103}
+\entry {\code {view-buffer \r {(V19)}}}{245}
+\entry {\code {view-diary-entries \r {(V19)}}}{264}
+\entry {\code {view-emacs-news}}{48}
+\entry {\code {view-file}}{99}
+\entry {\code {view-file \r {(V19)}}}{245}
+\entry {\code {view-lossage}}{48}
+\entry {\code {view-register}}{61}
+\entry {\code {vip-mode}}{210}
+\entry {\code {visit-tags-table}}{152}
+\initial {W}
+\entry {\code {what-cursor-position}}{32}
+\entry {\code {what-line}}{32}
+\entry {\code {what-page}}{32}
+\entry {\code {where-is}}{47}
+\entry {\code {widen}}{202}
+\entry {\code {word-search-backward}}{71}
+\entry {\code {word-search-forward}}{71}
+\entry {\code {write-abbrev-file}}{174}
+\entry {\code {write-file}}{89}
+\entry {\code {write-region}}{99}
+\initial {Y}
+\entry {\code {Yank}}{56}
+\entry {\code {yank-pop}}{57}
+\entry {\code {yank-rectangle}}{60}
+\entry {\code {yow}}{209}
+\initial {Z}
+\entry {\code {zap-to-char}}{55}
diff --git a/man/emacs.kys b/man/emacs.kys
new file mode 100644
index 00000000000..8eb290ff4f9
--- /dev/null
+++ b/man/emacs.kys
@@ -0,0 +1,497 @@
+\initial {!}
+\entry {\code {! \r {(Dired, V19)}}}{255}
+\entry {\code {! (query-replace)}}{78}
+\initial {$}
+\entry {\code {$ \r {(Dired, V19)}}}{259}
+\initial {%}
+\entry {\code {% C \r {(Dired, V19)}}}{256}
+\entry {\code {% d \r {(Dired, V19)}}}{256}
+\entry {\code {% H \r {(Dired, V19)}}}{256}
+\entry {\code {% l \r {(Dired, V19)}}}{257}
+\entry {\code {% m \r {(Dired, V19)}}}{256}
+\entry {\code {% R \r {(Dired, V19)}}}{256}
+\entry {\code {% S \r {(Dired, V19)}}}{256}
+\entry {\code {% u \r {(Dired, V19)}}}{257}
+\initial {*}
+\entry {\code {* \r {(Dired, V19)}}}{254}
+\initial {,}
+\entry {\code {, (query-replace)}}{78}
+\initial {.}
+\entry {\code {. (query-replace)}}{78}
+\entry {\code {. (Rmail)}}{188}
+\initial {/}
+\entry {\code {/ \r {(Dired, V19)}}}{254}
+\initial {=}
+\entry {\code {= \r {(Dired, V19)}}}{257}
+\initial {{\tt\char'042}}
+\entry {\code {{\tt\char'042} (TeX mode)}}{120}
+\initial {{\tt\char'100}}
+\entry {\code {{\tt\char'100} \r {(Dired, V19)}}}{254}
+\initial {{\tt\gtr}}
+\entry {\code {{\tt\gtr} (Rmail)}}{189}
+\initial {{\tt\hat}}
+\entry {\code {{\tt\hat} (query-replace)}}{78}
+\initial {{\tt\less}}
+\entry {\code {{\tt\less} \r {(Rmail in V19)}}}{251}
+\initial {A}
+\entry {\code {a (Rmail)}}{194}
+\initial {B}
+\entry {\code {B \r {(Dired, V19)}}}{255}
+\initial {C}
+\entry {\code {c \r {(Dired, V19)}}}{254}
+\entry {\code {C \r {(Dired, V19)}}}{254}
+\entry {\code {c (Rmail)}}{198}
+\entry {\code {C-]}}{201, 232}
+\entry {\code {C-{\_}}}{35}
+\entry {\code {C-a}}{28}
+\entry {\code {C-a \r {(Shell mode in V19)}}}{250}
+\entry {\code {C-b}}{28}
+\entry {\code {C-c}}{18}
+\entry {\code {C-c ' (Picture mode)}}{178}
+\entry {\code {C-c . (Picture mode)}}{178}
+\entry {\code {C-c / (Picture mode)}}{178}
+\entry {\code {C-c ; (Fortran mode)}}{158}
+\entry {\code {C-c ` (Picture mode)}}{178}
+\entry {\code {C-c {\tt\char'173} \r {(TeX mode in V19)}}}{248}
+\entry {\code {C-c {\tt\char'175} \r {(TeX mode in V19)}}}{248}
+\entry {\code {C-c {\tt\gtr} \r {(GUD in V19)}}}{284}
+\entry {\code {C-c {\tt\gtr} (Picture mode)}}{178}
+\entry {\code {C-c {\tt\hat} (Picture mode)}}{178}
+\entry {\code {C-c {\tt\indexbackslash } (Picture mode)}}{178}
+\entry {\code {C-c {\tt\less} \r {(GUD in V19)}}}{284}
+\entry {\code {C-c {\tt\less} (Picture mode)}}{178}
+\entry {\code {C-c C-{\tt\indexbackslash } (Shell mode)}}{207}
+\entry {\code {C-c C-b (Outline mode)}}{124}
+\entry {\code {C-c C-b (Picture mode)}}{179}
+\entry {\code {C-c C-b (TeX mode)}}{121}
+\entry {\code {C-c C-c (Edit Abbrevs)}}{174}
+\entry {\code {C-c C-c (Edit Tab Stops)}}{114}
+\entry {\code {C-c C-c \r {(GUD in V19)}}}{284}
+\entry {\code {C-c C-c (Mail mode)}}{184}
+\entry {\code {C-c C-c (Occur mode)}}{79}
+\entry {\code {C-c C-c (Shell mode)}}{207}
+\entry {\code {C-c C-d (Picture mode)}}{178}
+\entry {\code {C-c C-d (Shell mode)}}{207}
+\entry {\code {C-c C-e \r {(TeX mode in V19)}}}{248}
+\entry {\code {C-c C-f \r {(GUD in V19)}}}{284}
+\entry {\code {C-c C-f (LaTeX mode)}}{120}
+\entry {\code {C-c C-f (Outline mode)}}{124}
+\entry {\code {C-c C-f (Picture mode)}}{179}
+\entry {\code {C-c C-f C-c (Mail mode)}}{184}
+\entry {\code {C-c C-f C-s (Mail mode)}}{184}
+\entry {\code {C-c C-f C-t (Mail mode)}}{184}
+\entry {\code {C-c C-h (Outline mode)}}{125}
+\entry {\code {C-c C-i \r {(GUD in V19)}}}{284}
+\entry {\code {C-c C-i (Outline mode)}}{125}
+\entry {\code {C-c C-k (Picture mode)}}{180}
+\entry {\code {C-c C-k (TeX mode)}}{121}
+\entry {\code {C-c C-l \r {(GUD in V19)}}}{283}
+\entry {\code {C-c C-l (TeX mode)}}{121}
+\entry {\code {C-c C-n (Fortran mode)}}{155}
+\entry {\code {C-c C-n \r {(GUD in V19)}}}{284}
+\entry {\code {C-c C-n (Outline mode)}}{124}
+\entry {\code {C-c C-o \r {(Shell mode in V19)}}}{250}
+\entry {\code {C-c C-o (Shell mode)}}{207}
+\entry {\code {C-c C-o \r {(TeX mode in V19)}}}{248}
+\entry {\code {C-c C-p (Fortran mode)}}{155}
+\entry {\code {C-c C-p (Outline mode)}}{124}
+\entry {\code {C-c C-p (TeX mode)}}{121}
+\entry {\code {C-c C-q (Mail mode)}}{185}
+\entry {\code {C-c C-q (TeX mode)}}{121}
+\entry {\code {C-c C-r (Fortran mode)}}{159}
+\entry {\code {C-c C-r \r {(Shell mode in V19)}}}{250}
+\entry {\code {C-c C-r (Shell mode)}}{207}
+\entry {\code {C-c C-r (TeX mode)}}{121}
+\entry {\code {C-c C-s \r {(GUD in V19)}}}{284}
+\entry {\code {C-c C-s (Mail mode)}}{184}
+\entry {\code {C-c C-s (Outline mode)}}{125}
+\entry {\code {C-c C-u (Outline mode)}}{124}
+\entry {\code {C-c C-u (Shell mode)}}{207}
+\entry {\code {C-c C-v \r {(TeX mode in V19)}}}{248}
+\entry {\code {C-c C-w (Fortran mode)}}{159}
+\entry {\code {C-c C-w (Mail mode)}}{184}
+\entry {\code {C-c C-w (Picture mode)}}{180}
+\entry {\code {C-c C-w (Shell mode)}}{207}
+\entry {\code {C-c C-x (Picture mode)}}{180}
+\entry {\code {C-c C-y (Mail mode)}}{184, 198}
+\entry {\code {C-c C-y (Picture mode)}}{180}
+\entry {\code {C-c C-y (Shell mode)}}{207}
+\entry {\code {C-c C-z (Shell mode)}}{207}
+\entry {\code {C-c TAB (Picture mode)}}{179}
+\entry {\code {C-c \key {TAB} \r {(TeX mode in V19)}}}{248}
+\entry {\code {C-d}}{53}
+\entry {\code {C-d (Rmail)}}{190}
+\entry {\code {C-d \r {(Shell mode in V19)}}}{250}
+\entry {\code {C-e}}{28}
+\entry {\code {C-f}}{28}
+\entry {\code {C-g}}{37}
+\entry {\code {C-h}}{18}
+\entry {\code {C-h a}}{47}
+\entry {\code {C-h a \r {(V19)}}}{246}
+\entry {\code {C-h b}}{48}
+\entry {\code {C-h c}}{46}
+\entry {\code {C-h C-c}}{48}
+\entry {\code {C-h C-d}}{48}
+\entry {\code {C-h C-f \r {(V19)}}}{246}
+\entry {\code {C-h C-k \r {(V19)}}}{246}
+\entry {\code {C-h C-w}}{48}
+\entry {\code {C-h f}}{46, 149}
+\entry {\code {C-h i}}{48}
+\entry {\code {C-h k}}{46}
+\entry {\code {C-h l}}{48}
+\entry {\code {C-h m}}{48}
+\entry {\code {C-h n}}{48}
+\entry {\code {C-h s}}{225}
+\entry {\code {C-h t}}{27, 48}
+\entry {\code {C-h v}}{47, 149, 212}
+\entry {\code {C-h w}}{47}
+\entry {\code {C-k}}{54, 55}
+\entry {\code {C-l}}{28, 63}
+\entry {\code {C-l (query-replace)}}{78}
+\entry {\code {C-M-{\tt\char'100}}}{51, 138}
+\entry {\code {C-M-{\tt\indexbackslash }}}{114, 141}
+\entry {\code {C-M-a}}{138}
+\entry {\code {C-M-a (Fortran mode)}}{155}
+\entry {\code {C-M-b}}{137}
+\entry {\code {C-M-c}}{201}
+\entry {\code {C-M-d}}{138}
+\entry {\code {C-M-d \r {(Dired, V19)}}}{258}
+\entry {\code {C-M-e}}{138}
+\entry {\code {C-M-e (Fortran mode)}}{155}
+\entry {\code {C-M-f}}{137}
+\entry {\code {C-M-f \r {(V19)}}}{244}
+\entry {\code {C-M-h}}{51, 138}
+\entry {\code {C-M-h (Fortran mode)}}{155}
+\entry {\code {C-M-k}}{55, 137}
+\entry {\code {C-M-l (Rmail)}}{194, 195}
+\entry {\code {C-M-l \r {(V19)}}}{245}
+\entry {\code {C-M-m \r {(Rmail in V19)}}}{251}
+\entry {\code {C-M-n}}{137}
+\entry {\code {C-M-n \r {(Dired, V19)}}}{258}
+\entry {\code {C-M-n (Rmail)}}{194}
+\entry {\code {C-M-n \r {(Summary mode)} \r {(GNUS, V19)}}}{262}
+\entry {\code {C-M-o}}{113}
+\entry {\code {C-M-p}}{137}
+\entry {\code {C-M-p \r {(Dired, V19)}}}{258}
+\entry {\code {C-M-p (Rmail)}}{194}
+\entry {\code {C-M-p \r {(Summary mode)} \r {(GNUS, V19)}}}{262}
+\entry {\code {C-M-q}}{140}
+\entry {\code {C-M-q (Fortran mode)}}{156}
+\entry {\code {C-M-r (Rmail)}}{196}
+\entry {\code {C-M-r \r {(V19)}}}{245}
+\entry {\code {C-M-s}}{71}
+\entry {\code {C-M-t}}{82, 138}
+\entry {\code {C-M-u}}{138}
+\entry {\code {C-M-u \r {(Dired, V19)}}}{258}
+\entry {\code {C-M-v}}{38, 108}
+\entry {\code {C-M-w}}{57}
+\entry {\code {C-M-x}}{166, 170}
+\entry {\code {C-n}}{28}
+\entry {\code {C-n \r {(Group mode)} \r {(GNUS, V19)}}}{262}
+\entry {\code {C-n \r {(Rmail summary in V19)}}}{252}
+\entry {\code {C-n (Rmail summary)}}{196}
+\entry {\code {C-n \r {(Summary mode)} \r {(GNUS, V19)}}}{262}
+\entry {\code {C-o}}{31}
+\entry {\code {C-o (Rmail)}}{192}
+\entry {\code {C-o \r {(V19)}}}{243}
+\entry {\code {C-p}}{28}
+\entry {\code {C-p \r {(Group mode)} \r {(GNUS, V19)}}}{262}
+\entry {\code {C-p \r {(Rmail summary in V19)}}}{252}
+\entry {\code {C-p (Rmail summary)}}{196}
+\entry {\code {C-p \r {(Summary mode)} \r {(GNUS, V19)}}}{262}
+\entry {\code {C-q}}{27}
+\entry {\code {C-r}}{67}
+\entry {\code {C-r (query-replace)}}{78}
+\entry {\code {C-s}}{67}
+\entry {\code {C-SPC}}{49}
+\entry {\code {C-t}}{28, 81}
+\entry {\code {C-u}}{33}
+\entry {\code {C-u - C-x ;}}{146}
+\entry {\code {C-u C-{\tt\char'100}}}{51}
+\entry {\code {C-u C-SPC}}{51}
+\entry {\code {C-u TAB}}{140}
+\entry {\code {C-v}}{63}
+\entry {\code {C-w}}{55}
+\entry {\code {C-w (query-replace)}}{78}
+\entry {\code {C-x}}{18}
+\entry {\code {C-x $}}{64}
+\entry {\code {C-x & \r {(GUD in V19)}}}{285}
+\entry {\code {C-x (}}{217}
+\entry {\code {C-x )}}{217}
+\entry {\code {C-x -}}{172}
+\entry {\code {C-x .}}{132}
+\entry {\code {C-x /}}{61}
+\entry {\code {C-x ;}}{147}
+\entry {\code {C-x =}}{32}
+\entry {\code {C-x [}}{129}
+\entry {\code {C-x ]}}{129}
+\entry {\code {C-x `}}{162}
+\entry {\code {C-x {\tt\char'175}}}{110}
+\entry {\code {C-x {\tt\char43}}}{171}
+\entry {\code {C-x {\tt\gtr}}}{64}
+\entry {\code {C-x {\tt\hat}}}{110}
+\entry {\code {C-x {\tt\less}}}{64}
+\entry {\code {C-x 0}}{109}
+\entry {\code {C-x 1}}{109}
+\entry {\code {C-x 2}}{107}
+\entry {\code {C-x 2 \r {(V19)}}}{243}
+\entry {\code {C-x 3 \r {(V19)}}}{242}
+\entry {\code {C-x 4}}{109}
+\entry {\code {C-x 4 .}}{153}
+\entry {\code {C-x 4 a}}{150}
+\entry {\code {C-x 4 a \r {(V19)}}}{244}
+\entry {\code {C-x 4 b}}{101}
+\entry {\code {C-x 4 C-o \r {(V19)}}}{242}
+\entry {\code {C-x 4 d}}{96}
+\entry {\code {C-x 4 f}}{87}
+\entry {\code {C-x 4 m}}{181}
+\entry {\code {C-x 4 r \r {(V19)}}}{246}
+\entry {\code {C-x 5}}{107}
+\entry {\code {C-x 5 \r {(V19)}}}{245}
+\entry {\code {C-x 5 . \r {(V19)}}}{246}
+\entry {\code {C-x 5 b \r {(V19)}}}{245}
+\entry {\code {C-x 5 C-f \r {(V19)}}}{245}
+\entry {\code {C-x 5 m \r {(V19)}}}{246}
+\entry {\code {C-x a}}{58}
+\entry {\code {C-x a \r {(V19)}}}{242}
+\entry {\code {C-x b}}{101}
+\entry {\code {C-x C-a}}{172}
+\entry {\code {C-x C-b}}{102}
+\entry {\code {C-x C-c}}{21}
+\entry {\code {C-x C-d}}{96}
+\entry {\code {C-x C-e}}{166}
+\entry {\code {C-x C-f}}{87}
+\entry {\code {C-x C-h}}{172}
+\entry {\code {C-x C-l}}{133}
+\entry {\code {C-x C-l \r {(V19)}}}{242}
+\entry {\code {C-x C-o}}{31, 54}
+\entry {\code {C-x C-p}}{51, 129}
+\entry {\code {C-x C-q}}{102}
+\entry {\code {C-x C-q \r {(V19)}}}{269}
+\entry {\code {C-x C-s}}{88}
+\entry {\code {C-x C-t}}{82}
+\entry {\code {C-x C-u}}{133}
+\entry {\code {C-x C-u \r {(V19)}}}{242}
+\entry {\code {C-x C-v}}{87}
+\entry {\code {C-x C-v \r {(V19)}}}{244}
+\entry {\code {C-x C-w}}{89}
+\entry {\code {C-x C-x}}{50}
+\entry {\code {C-x d}}{96}
+\entry {\code {C-x DEL}}{55, 81, 127}
+\entry {\code {C-x e}}{217}
+\entry {\code {C-x ESC}}{41}
+\entry {\code {C-x f}}{131}
+\entry {\code {C-x g}}{62}
+\entry {\code {C-x h}}{51}
+\entry {\code {C-x j}}{61}
+\entry {\code {C-x k}}{103}
+\entry {\code {C-x l}}{129}
+\entry {\code {C-x m}}{181}
+\entry {\code {C-x n}}{202}
+\entry {\code {C-x n \r {(V19)}}}{242}
+\entry {\code {C-x o}}{108}
+\entry {\code {C-x q}}{218}
+\entry {\code {C-x r \r {(V19)}}}{242}
+\entry {\code {C-x s}}{88}
+\entry {\code {C-x s \r {(V19)}}}{243}
+\entry {\code {C-x \key {SPC} \r {(V19)}}}{283}
+\entry {\code {C-x TAB}}{114}
+\entry {\code {C-x u}}{35}
+\entry {\code {C-x v = \r {(V19)}}}{273}
+\entry {\code {C-x v a \r {(V19)}}}{272}
+\entry {\code {C-x v c \r {(V19)}}}{270}
+\entry {\code {C-x v d \r {(V19)}}}{274}
+\entry {\code {C-x v h \r {(V19)}}}{276}
+\entry {\code {C-x v i \r {(V19)}}}{270}
+\entry {\code {C-x v l \r {(V19)}}}{274}
+\entry {\code {C-x v r \r {(V19)}}}{275}
+\entry {\code {C-x v s \r {(V19)}}}{275}
+\entry {\code {C-x v u \r {(V19)}}}{269}
+\entry {\code {C-x w}}{202}
+\entry {\code {C-x x}}{62}
+\entry {\code {C-y}}{56}
+\entry {\code {C-z}}{21}
+\entry {\code {C-z \r {(V19)}}}{245}
+\initial {D}
+\entry {\code {d (Rmail summary)}}{197}
+\entry {\code {d (Rmail)}}{190}
+\entry {\code {DEL}}{27, 53, 81, 111, 136}
+\entry {\code {DEL \r {(Group mode)} \r {(GNUS, V19)}}}{262}
+\entry {\code {DEL (query-replace)}}{78}
+\entry {\code {DEL (Rmail summary)}}{197}
+\entry {\code {DEL (Rmail)}}{188}
+\entry {\code {DEL \r {(Summary mode)} \r {(GNUS, V19)}}}{262}
+\initial {E}
+\entry {\code {e \r {(Rmail in V19)}}}{251}
+\entry {\code {e (Rmail)}}{190}
+\entry {\code {ESC}}{18}
+\entry {\code {ESC (query-replace)}}{78}
+\initial {F}
+\entry {\code {f (Rmail)}}{198}
+\initial {G}
+\entry {\code {g \r {(Dired, V19)}}}{259}
+\entry {\code {G \r {(Dired, V19)}}}{255}
+\entry {\code {g (Rmail)}}{192}
+\initial {H}
+\entry {\code {H \r {(Dired, V19)}}}{255}
+\entry {\code {h (Rmail)}}{195}
+\entry {\code {Help}}{45}
+\initial {I}
+\entry {\code {i \r {(Dired, V19)}}}{258}
+\entry {\code {i (Rmail)}}{191}
+\initial {J}
+\entry {\code {j (Rmail summary)}}{196}
+\entry {\code {j (Rmail)}}{189}
+\initial {K}
+\entry {\code {k \r {(Dired, V19)}}}{259}
+\entry {\code {k (rmail)}}{194}
+\initial {L}
+\entry {\code {l \r {(Dired, V19)}}}{259}
+\entry {\code {L \r {(Dired, V19)}}}{255}
+\entry {\code {l \r {(Group mode)} \r {(GNUS, V19)}}}{261}
+\entry {\code {L \r {(Group mode)} \r {(GNUS, V19)}}}{261}
+\entry {\code {l (Rmail)}}{195}
+\entry {\code {LFD}}{111, 140}
+\entry {\code {LFD (TeX mode)}}{120}
+\initial {M}
+\entry {\code {m \r {(Dired, V19)}}}{254}
+\entry {\code {M \r {(Dired, V19)}}}{255}
+\entry {\code {m (Rmail)}}{198}
+\entry {\code {M-!}}{205}
+\entry {\code {M-! \r {(V19)}}}{243}
+\entry {\code {M-$}}{83}
+\entry {\code {M-$ \r {(Dired, V19)}}}{259}
+\entry {\code {M-$ \r {(V19)}}}{250}
+\entry {\code {M-%}}{78}
+\entry {\code {M-'}}{173}
+\entry {\code {M-(}}{148}
+\entry {\code {M-)}}{148}
+\entry {\code {M-,}}{153}
+\entry {\code {M-\r {-}}}{33}
+\entry {\code {M-\r {-} M-c}}{82}
+\entry {\code {M-\r {-} M-l}}{82}
+\entry {\code {M-\r {-} M-u}}{82}
+\entry {\code {M-.}}{152}
+\entry {\code {M-. \r {(V19)}}}{252}
+\entry {\code {M-/}}{175}
+\entry {\code {M-;}}{145}
+\entry {\code {M-=}}{32}
+\entry {\code {M-= \r {(Dired, V19)}}}{257}
+\entry {\code {M-?}}{118}
+\entry {\code {M-? \r {(Shell mode in V19)}}}{249}
+\entry {\code {M-[}}{128}
+\entry {\code {M-]}}{128}
+\entry {\code {M-{\tt\char'100}}}{51, 127}
+\entry {\code {M-{\tt\char'173} (TeX mode)}}{120}
+\entry {\code {M-{\tt\char'173} \r {(V19)}}}{242}
+\entry {\code {M-{\tt\char'174}}}{205}
+\entry {\code {M-{\tt\char'175} (TeX mode)}}{120}
+\entry {\code {M-{\tt\char'175} \r {(V19)}}}{242}
+\entry {\code {M-{\tt\char'176}}}{88}
+\entry {\code {M-{\tt\gtr}}}{28}
+\entry {\code {M-{\tt\hat}}}{54, 114}
+\entry {\code {M-{\tt\hat} \r {(V19)}}}{243}
+\entry {\code {M-{\tt\indexbackslash }}}{54, 114}
+\entry {\code {M-{\tt\less}}}{28}
+\entry {\code {M-1}}{33}
+\entry {\code {M-a}}{127}
+\entry {\code {M-a \r {(C mode in V19)}}}{246}
+\entry {\code {M-b}}{126}
+\entry {\code {M-c}}{133}
+\entry {\code {M-d}}{55, 126}
+\entry {\code {M-DEL}}{55, 81, 126}
+\entry {\code {M-\key {DEL} \r {(Dired, V19)}}}{254}
+\entry {\code {M-e}}{127}
+\entry {\code {M-e \r {(C mode in V19)}}}{246}
+\entry {\code {M-ESC}}{166}
+\entry {\code {M-f}}{126}
+\entry {\code {M-g}}{131}
+\entry {\code {M-g \r {(V19)}}}{242}
+\entry {\code {M-h}}{51, 128}
+\entry {\code {M-i}}{114}
+\entry {\code {M-k}}{55, 127}
+\entry {\code {M-l}}{133}
+\entry {\code {M-LFD}}{147}
+\entry {\code {M-LFD (Fortran mode)}}{156}
+\entry {\code {M-m}}{113}
+\entry {\code {M-n}}{42, 118}
+\entry {\code {M-n \r {(Rmail summary in V19)}}}{252}
+\entry {\code {M-n (Rmail)}}{189}
+\entry {\code {M-n \r {(Shell mode in V19)}}}{249}
+\entry {\code {M-n \r {(V19)}}}{240}
+\entry {\code {M-p}}{42, 118}
+\entry {\code {M-p \r {(Rmail summary in V19)}}}{252}
+\entry {\code {M-p (Rmail)}}{189}
+\entry {\code {M-p \r {(Shell mode in V19)}}}{249}
+\entry {\code {M-p \r {(V19)}}}{240}
+\entry {\code {M-q}}{131}
+\entry {\code {M-q \r {(C mode in V19)}}}{246, 248}
+\entry {\code {M-r}}{28}
+\entry {\code {M-r \r {(Shell mode in V19)}}}{249}
+\entry {\code {M-r \r {(V19)}}}{240}
+\entry {\code {M-s}}{131}
+\entry {\code {M-s (Rmail)}}{189}
+\entry {\code {M-s \r {(Shell mode in V19)}}}{249}
+\entry {\code {M-s \r {(Summary mode)} \r {(GNUS, V19)}}}{262}
+\entry {\code {M-s \r {(V19)}}}{240}
+\entry {\code {M-SPC}}{54}
+\entry {\code {M-t}}{82, 126}
+\entry {\code {M-TAB}}{148, 179}
+\entry {\code {M-\key {TAB} \r {(V19)}}}{252}
+\entry {\code {M-u}}{133}
+\entry {\code {M-v}}{63}
+\entry {\code {M-w}}{56}
+\entry {\code {M-x}}{43}
+\entry {\code {M-x gnus \r {(V19)}}}{260}
+\entry {\code {M-y}}{57}
+\entry {\code {M-z}}{55}
+\entry {\code {M-z \r {(V19)}}}{243}
+\initial {N}
+\entry {\code {n \r {(Group mode)} \r {(GNUS, V19)}}}{262}
+\entry {\code {n \r {(Rmail summary in V19)}}}{252}
+\entry {\code {n (Rmail summary)}}{196}
+\entry {\code {n (Rmail)}}{189}
+\initial {O}
+\entry {\code {O \r {(Dired, V19)}}}{255}
+\entry {\code {o (Rmail)}}{192}
+\initial {P}
+\entry {\code {P \r {(Dired, V19)}}}{255}
+\entry {\code {p \r {(Group mode)} \r {(GNUS, V19)}}}{262}
+\entry {\code {p \r {(Rmail summary in V19)}}}{252}
+\entry {\code {p (Rmail summary)}}{196}
+\entry {\code {p (Rmail)}}{189}
+\initial {Q}
+\entry {\code {q \r {(Group mode)} \r {(GNUS, V19)}}}{261}
+\entry {\code {q (Rmail summary)}}{197}
+\entry {\code {q (Rmail)}}{187}
+\initial {R}
+\entry {\code {R \r {(Dired, V19)}}}{255}
+\entry {\code {r (Rmail)}}{197}
+\entry {\code {RET}}{27}
+\entry {\code {RET (Shell mode)}}{207}
+\initial {S}
+\entry {\code {S \r {(Dired, V19)}}}{255}
+\entry {\code {s (Rmail)}}{187}
+\entry {\code {s \r {(Summary mode)} \r {(GNUS, V19)}}}{262}
+\entry {\code {SPC}}{40}
+\entry {\code {SPC \r {(Group mode)} \r {(GNUS, V19)}}}{262}
+\entry {\code {SPC (query-replace)}}{78}
+\entry {\code {SPC (Rmail summary)}}{197}
+\entry {\code {SPC (Rmail)}}{188}
+\entry {\code {SPC \r {(Summary mode)} \r {(GNUS, V19)}}}{262}
+\initial {T}
+\entry {\code {t (Rmail)}}{198}
+\entry {\code {TAB}}{39, 111, 113, 117, 139}
+\entry {\code {\key {TAB} \r {(Shell mode in V19)}}}{249}
+\initial {U}
+\entry {\code {u \r {(Group mode)} \r {(GNUS, V19)}}}{261}
+\entry {\code {u (Rmail summary)}}{197}
+\entry {\code {u (Rmail)}}{190}
+\initial {W}
+\entry {\code {w (Rmail)}}{199}
+\initial {X}
+\entry {\code {x \r {(Rmail in V19)}}}{251}
+\entry {\code {x (Rmail summary)}}{197}
+\initial {Z}
+\entry {\code {Z \r {(Dired, V19)}}}{255}
+\entry {\code {z \r {(Group mode)} \r {(GNUS, V19)}}}{261}
diff --git a/man/emacs.pgs b/man/emacs.pgs
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/man/emacs.pgs
diff --git a/man/emacs.texi b/man/emacs.texi
new file mode 100644
index 00000000000..069f919f1be
--- /dev/null
+++ b/man/emacs.texi
@@ -0,0 +1,19241 @@
+\input texinfo.tex @c -*-texinfo-*-
+@c %**start of header
+@setfilename ../info/emacs
+@settitle GNU Emacs Manual
+@setchapternewpage odd
+@smallbook
+@c %**end of header
+
+@finalout
+
+@c
+@tex
+%%%% This is special for the Emacs Manual %%%%
+%%%% Robert J. Chassell 10 June 1992
+
+%%%% Use less indentation for Table of Contents
+\global\tocindent = 1.5pc
+\global\def\labelspace{\hskip.5em \relax}
+@end tex
+@c
+
+@ifinfo
+This file documents the GNU Emacs editor.
+
+Copyright (C) 1985, 1986, 1988, 1992 Richard M. Stallman.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+@ignore
+Permission is granted to process this file through Tex and print the
+results, provided the printed document carries copying permission
+notice identical to this one except for the removal of this paragraph
+(this paragraph not being relevant to the printed manual).
+
+@end ignore
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided also that the
+sections entitled ``The GNU Manifesto'', ``Distribution'' and ``GNU
+General Public License'' are included exactly as in the original, and
+provided that the entire resulting derived work is distributed under the
+terms of a permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that the sections entitled ``The GNU Manifesto'',
+``Distribution'' and ``GNU General Public License'' may be included in a
+translation approved by the author instead of in the original English.
+@end ifinfo
+@c
+@c
+@titlepage
+@sp 6
+@center @titlefont{GNU Emacs Manual}
+@sp 4
+@center Seventh Edition, Emacs Version 18.58
+@sp 1
+@center for Unix Users
+@sp 1
+@center February 1988, revised September 1992
+@center (General Public License upgraded, January 1991)
+@sp 5
+@center Richard M. Stallman
+@page
+@vskip 0pt plus 1filll
+Copyright @copyright{} 1985, 1986, 1988, 1992 Richard M. Stallman.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided also that the
+sections entitled ``The GNU Manifesto'', ``Distribution'' and ``GNU
+General Public License'' are included exactly as in the original, and
+provided that the entire resulting derived work is distributed under the
+terms of a permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that the sections entitled ``The GNU Manifesto'',
+``Distribution'' and ``GNU General Public License'' may be included in a
+translation approved by the author instead of in the original English.
+@sp 2
+Cover art by Etienne Suvasa.
+@end titlepage
+@page
+@ifinfo
+@node Top, Distrib,, (DIR)
+@top The Emacs Editor
+
+Emacs is the extensible, customizable, self-documenting real-time
+display editor. This Info file describes how to edit with Emacs
+and some of how to customize it, but not how to extend it.
+
+@end ifinfo
+@menu
+* Distrib:: How to get the latest Emacs distribution.
+* License:: The GNU General Public License gives you permission
+ to redistribute GNU Emacs on certain terms; and also
+ explains that there is no warranty.
+* Intro:: An introduction to Emacs concepts.
+* Glossary:: The glossary.
+* Version 19:: Changes coming in Emacs version 19, to be released.
+* Manifesto:: What's GNU? Gnu's Not Unix!
+
+Indexes, nodes containing large menus
+* Key Index:: An item for each standard Emacs key sequence.
+* Command Index:: An item for each command name.
+* Variable Index:: An item for each documented variable.
+* Concept Index:: An item for each concept.
+
+Important General Concepts
+* Screen:: How to interpret what you see on the screen.
+* Characters:: Emacs's character sets for file contents and for keyboard.
+* Keys:: Key sequences: what you type to request one editing action.
+* Commands:: Commands: named functions run by key sequences to do editing.
+* Entering Emacs:: Starting Emacs from the shell.
+* Command Switches:: Hairy startup options.
+* Exiting:: Stopping or killing Emacs.
+* Basic:: The most basic editing commands.
+* Undo:: Undoing recently made changes in the text.
+* Minibuffer:: Entering arguments that are prompted for.
+* M-x:: Invoking commands by their names.
+* Help:: Commands for asking Emacs about its commands.
+
+Important Text-Changing Commands
+* Mark:: The mark: how to delimit a ``region'' of text.
+* Killing:: Killing text.
+* Yanking:: Recovering killed text. Moving text.
+* Accumulating Text::
+ Other ways of copying text.
+* Rectangles:: Operating on the text inside a rectangle on the screen.
+* Registers:: Saving a text string or a location in the buffer.
+* Display:: Controlling what text is displayed.
+* Search:: Finding or replacing occurrences of a string.
+* Fixit:: Commands especially useful for fixing typos.
+
+Larger Units of Text
+* Files:: All about handling files.
+* Buffers:: Multiple buffers; editing several files at once.
+* Windows:: Viewing two pieces of text at once.
+
+Advanced Features
+* Major Modes:: Text mode vs. Lisp mode vs. C mode ...
+* Indentation:: Editing the white space at the beginnings of lines.
+* Text:: Commands and modes for editing English.
+* Programs:: Commands and modes for editing programs.
+* Compiling/Testing::
+ Compiling, running and debugging programs.
+* Abbrevs:: How to define text abbreviations to reduce
+ the number of characters you must type.
+* Picture:: Editing pictures made up of characters
+ using the quarter-plane screen model.
+* Sending Mail::Sending mail in Emacs.
+* Rmail:: Reading mail in Emacs.
+* Recursive Edit::
+ A command can allow you to do editing
+ "within the command". This is called a
+ `recursive editing level'.
+* Narrowing:: Restricting display and editing to a portion
+ of the buffer.
+* Sorting:: Sorting lines, paragraphs or pages within Emacs.
+* Shell:: Executing shell commands from Emacs.
+* Hardcopy:: Printing buffers or regions.
+* Dissociated Press:: Dissociating text for fun.
+* Amusements:: Various games and hacks.
+* Emulation:: Emulating some other editors with Emacs.
+* Customization:: Modifying the behavior of Emacs.
+
+Recovery from Problems.
+* Quitting:: Quitting and aborting.
+* Lossage:: What to do if Emacs is hung or malfunctioning.
+* Bugs:: How and when to report a bug.
+
+Here are some other nodes which are really inferiors of the ones
+already listed, mentioned here so you can get to them in one step:
+
+Subnodes of Screen
+* Point:: The place in the text where editing commands operate.
+* Echo Area:: Short messages appear at the bottom of the screen.
+* Mode Line:: Interpreting the mode line.
+
+Subnodes of Basic
+* Blank Lines:: Commands to make or delete blank lines.
+* Continuation Lines:: Lines too wide for the screen.
+* Position Info:: What page, line, row, or column is point on?
+* Arguments:: Giving numeric arguments to commands.
+
+Subnodes of Minibuffer
+* Minibuffer File:: Entering file names with the minibuffer.
+* Minibuffer Edit:: How to edit in the minibuffer.
+* Completion:: An abbreviation facility for minibuffer input.
+* Repetition:: Re-executing previous commands that used the minibuffer.
+
+Subnodes of Mark
+* Setting Mark:: Commands to set the mark.
+* Using Region:: Summary of ways to operate on contents of the region.
+* Marking Objects:: Commands to put region around textual units.
+* Mark Ring:: Previous mark positions saved so you can go back there.
+
+Subnodes of Yanking
+* Kill Ring:: Where killed text is stored. Basic yanking.
+* Appending Kills:: Several kills in a row all yank together.
+* Earlier Kills:: Yanking something killed some time ago.
+
+Subnodes of Registers
+* RegPos:: Saving positions in registers.
+* RegText:: Saving text in registers.
+* RegRect:: Saving rectangles in registers.
+
+Subnodes of Display
+* Scrolling:: Moving text up and down in a window.
+* Horizontal Scrolling:: Moving text left and right in a window.
+* Selective Display:: Hiding lines with lots of indentation.
+* Display Vars:: Information on variables for customizing display.
+
+Subnodes of Search
+* Incremental Search:: Search happens as you type the string.
+* Nonincremental Search:: Specify entire string and then search.
+* Word Search:: Search for sequence of words.
+* Regexp Search:: Search for match for a regexp.
+* Regexps:: Syntax of regular expressions.
+* Search Case:: To ignore case while searching, or not.
+* Replace:: Search, and replace some or all matches.
+* Unconditional Replace:: Everything about replacement except for querying.
+* Query Replace:: How to use querying.
+* Other Repeating Search:: Operating on all matches for some regexp.
+
+Subnodes of Fixit
+* Kill Errors:: Commands to kill a batch of recently entered text.
+* Transpose:: Exchanging two characters, words, lines, lists...
+* Fixing Case:: Correcting case of last word entered.
+* Spelling:: Apply spelling checker to a word, or a whole file.
+
+Subnodes of Files
+* File Names:: How to type and edit file name arguments.
+* Visiting:: Visiting a file prepares Emacs to edit the file.
+* Saving:: Saving makes your changes permanent.
+* Backup:: How Emacs saves the old version of your file.
+* Interlocking::How Emacs protects against simultaneous editing
+ of one file by two users.
+* Reverting:: Reverting cancels all the changes not saved.
+* Auto Save:: Auto Save periodically protects against loss of data.
+* ListDir:: Listing the contents of a file directory.
+* Dired:: ``Editing'' a directory to delete, rename, etc.
+ the files in it.
+* Misc File Ops:: Other things you can do on files.
+
+Subnodes of Buffers
+* Select Buffer:: Creating a new buffer or reselecting an old one.
+* List Buffers:: Getting a list of buffers that exist.
+* Misc Buffer:: Renaming; changing read-only status.
+* Kill Buffer:: Killing buffers you no longer need.
+* Several Buffers:: How to go through the list of all buffers
+ and operate variously on several of them.
+
+Subnodes of Windows
+* Basic Window:: Introduction to Emacs windows.
+* Split Window:: New windows are made by splitting existing windows.
+* Other Window:: Moving to another window or doing something to it.
+* Pop Up Window:: Finding a file or buffer in another window.
+* Change Window:: Deleting windows and changing their sizes.
+
+Subnodes of Indentation
+* Indentation Commands:: Various commands and techniques for indentation.
+* Tab Stops:: You can set arbitrary "tab stops" and then
+ indent to the next tab stop when you want to.
+* Just Spaces:: You can request indentation using just spaces.
+
+Subnodes of Text
+* Text Mode:: The major mode for editing text files.
+* Nroff Mode:: The major mode for editing input to the formatter nroff.
+* TeX Mode:: The major mode for editing input to the formatter TeX.
+* Texinfo Mode::The major mode for editing input to the formatter Texinfo.
+* Outline Mode::The major mode for editing outlines.
+* Words:: Moving over and killing words.
+* Sentences:: Moving over and killing sentences.
+* Paragraphs:: Moving over paragraphs.
+* Pages:: Moving over pages.
+* Filling:: Filling or justifying text
+* Case:: Changing the case of text
+
+Subnodes of Programs
+* Program Modes:: Major modes for editing programs.
+* Lists:: Expressions with balanced parentheses.
+ There are editing commands to operate on them.
+* Defuns:: Each program is made up of separate functions.
+ There are editing commands to operate on them.
+* Grinding:: Adjusting indentation to show the nesting.
+* Matching:: Insertion of a close-delimiter flashes matching open.
+* Comments:: Inserting, killing and aligning comments.
+* Balanced Editing:: Inserting two matching parentheses at once, etc.
+* Lisp Completion:: Completion on symbol names in Lisp code.
+* Documentation:: Getting documentation of functions you plan to call.
+* 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.
+* Fortran:: Fortran mode and its special features.
+
+Subnodes of Compiling/Testing
+* Compilation:: Compiling programs in languages other than Lisp
+ (C, Pascal, etc.)
+* Lisp Modes:: Various modes for editing Lisp programs, with
+ different facilities for running the Lisp programs.
+* Lisp Libraries:: Creating Lisp programs to run in Emacs.
+* Lisp Interaction:: Executing Lisp in an Emacs buffer.
+* Lisp Eval:: Executing a single Lisp expression in Emacs.
+* Lisp Debug:: Debugging Lisp programs running in Emacs.
+* External Lisp:: Communicating through Emacs with a separate Lisp.
+
+Subnodes of Abbrevs
+* Defining Abbrevs:: Defining an abbrev, so it will expand when typed.
+* Expanding Abbrevs:: Controlling expansion: prefixes, canceling expansion.
+* Editing Abbrevs:: Viewing or editing the entire list of defined abbrevs.
+* Saving Abbrevs:: Saving the entire list of abbrevs for another session.
+* Dynamic Abbrevs:: Abbreviations for words already in the buffer.
+
+Subnodes of Picture
+* Basic Picture:: Basic concepts and simple commands of Picture mode.
+* Insert in Picture:: Controlling direction of cursor motion
+ after "self-inserting" characters.
+* Tabs in Picture:: Various features for tab stops and indentation.
+* Rectangles in Picture:: Clearing and superimposing rectangles.
+
+Subnodes of Sending Mail
+* Mail Format:: Format of the mail being composed.
+* Mail Headers:: Details of allowed mail header fields.
+* Mail Mode:: Special commands for editing mail being composed.
+
+Subnodes of Rmail
+* Rmail Scrolling:: Scrolling through a message.
+* Rmail Motion:: Moving to another message.
+* Rmail Deletion:: Deleting and expunging messages.
+* Rmail Inbox:: How mail gets into the Rmail file.
+* Rmail Files:: Using multiple Rmail files.
+* Rmail Output:: Copying message out to files.
+* Rmail Labels:: Classifying messages by labeling them.
+* Rmail Summary:: Summaries show brief info on many messages.
+* Rmail Reply:: Sending replies to messages you are viewing.
+* Rmail Editing:: Editing message text and headers in Rmail.
+* Rmail Digest:: Extracting the messages from a digest message.
+
+Subnodes of Shell
+* Single Shell:: Commands to run one shell command and return.
+* Interactive Shell:: Permanent shell taking input via Emacs.
+* Shell Mode:: Special Emacs commands used with permanent shell.
+
+Subnodes of Customization
+* Minor Modes:: Each minor mode is one feature you can turn on
+ independently of any others.
+* Variables:: Many Emacs commands examine Emacs variables
+ to decide what to do; by setting variables,
+ you can control their functioning.
+* Examining:: Examining or setting one variable's value.
+* Edit Options:: Examining or editing list of all variables' values.
+* Locals:: Per-buffer values of variables.
+* File Variables:: How files can specify variable values.
+* Keyboard Macros:: A keyboard macro records a sequence of keystrokes
+ to be replayed with a single command.
+* Key Bindings:: The keymaps say what command each key runs.
+ By changing them, you can "redefine keys".
+* Keymaps:: Definition of the keymap data structure.
+* Rebinding:: How to redefine one key's meaning conveniently.
+* Disabling:: Disabling a command means confirmation is required
+ before it can be executed. This is done to protect
+ beginners from surprises.
+* Syntax:: The syntax table controls how words and expressions
+ are parsed.
+* Init File:: How to write common customizations in the `.emacs' file.
+
+Subnodes of Lossage (and recovery)
+* Stuck Recursive:: `[...]' in mode line around the parentheses.
+* Screen Garbled:: Garbage on the screen.
+* Text Garbled:: Garbage in the text.
+* Unasked-for Search::Spontaneous entry to incremental search.
+* Emergency Escape:: Emergency escape---
+ What to do if Emacs stops responding.
+* Total Frustration:: When you are at your wits' end.
+@end menu
+
+@iftex
+@unnumbered Preface
+
+ This manual documents the use and simple customization of the
+Emacs editor. The reader is not expected to be a programmer. Even simple
+customizations do not require programming skill, but the user who is not
+interested in customizing can ignore the scattered customization hints.
+
+ This is primarily a reference manual, but can also be used as a
+primer. However, I recommend that the newcomer first use the on-line,
+learn-by-doing tutorial, which you get by running Emacs and typing
+@kbd{C-h t}. With it, you learn Emacs by using Emacs on a specially
+designed file which describes commands, tells you when to try them,
+and then explains the results you see. This gives a more vivid
+introduction than a printed manual.
+
+ On first reading, just skim chapters one and two, which describe the
+notational conventions of the manual and the general appearance of the
+Emacs display screen. Note which questions are answered in these chapters,
+so you can refer back later. After reading chapter four you should
+practice the commands there. The next few chapters describe fundamental
+techniques and concepts that are used constantly. You need to understand
+them thoroughly, experimenting with them if necessary.
+
+ To find the documentation on a particular command, look in the index.
+Keys (character commands) and command names have separate indexes. There
+is also a glossary, with a cross reference for each term.
+
+@ignore
+ If you know vaguely what the command
+does, look in the command summary. The command summary contains a line or
+two about each command, and a cross reference to the section of the
+manual that describes the command in more detail; related commands
+are grouped together.
+@end ignore
+
+ This manual comes in two forms: the published form and the Info form.
+The Info form is for on-line perusal with the @code{info} program; it is
+distributed along with GNU Emacs. Both forms contain substantially the
+same text and are generated from a common source file, which is also
+distributed along with GNU Emacs.
+
+ GNU Emacs is a member of the Emacs editor family. There are many Emacs
+editors, all sharing common principles of organization. For information on
+the underlying philosophy of Emacs and the lessons learned from its
+development, write for a copy of AI memo 519a, ``Emacs, the Extensible,
+Customizable Self-Documenting Display Editor'', to Publications Department,
+Artificial Intelligence Lab, 545 Tech Square, Cambridge, MA 02139, USA. At
+last report they charge $2.25 per copy. Another useful publication is LCS
+TM-165, ``A Cookbook for an Emacs'', by Craig Finseth, available from
+Publications Department, Laboratory for Computer Science, 545 Tech Square,
+Cambridge, MA 02139, USA. The price today is $3.
+
+This edition of the manual is intended for use with GNU Emacs installed on
+Unix systems. GNU Emacs can also be used on VMS systems, which have
+different file name syntax and do not support all GNU Emacs features. A
+VMS edition of this manual may appear in the future.
+@end iftex
+
+@node Distrib, License, Top, Top
+@unnumbered Distribution
+
+GNU Emacs is @dfn{free}; this means that everyone is free to use it and
+free to redistribute it on a free basis. GNU Emacs is not in the public
+domain; it is copyrighted and there are restrictions on its
+distribution, but these restrictions are designed to permit everything
+that a good cooperating citizen would want to do. What is not allowed
+is to try to prevent others from further sharing any version of GNU
+Emacs that they might get from you. The precise conditions are found in
+the GNU General Public License that comes with Emacs and also appears
+following this section.
+
+The easiest way to get a copy of GNU Emacs 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 distribution
+version of GNU Emacs from host @file{prep.ai.mit.edu} using anonymous
+login. See the file @file{/u2/emacs/GETTING.GNU.SOFTWARE} on that host
+to find out about your options for copying and which files to use.
+
+You may also receive GNU Emacs when you buy a computer. Computer
+manufacturers are free to distribute copies on the same terms that apply to
+everyone else. These terms require them to give you the full sources,
+including whatever changes they may have made, and to permit you to
+redistribute the GNU Emacs received from them under the usual terms of the
+General Public License. In other words, the program must be free for you
+when you get it, not just free for the manufacturer.
+
+If you cannot get a copy in any of those ways, you can order one from the
+Free Software Foundation. Though Emacs itself is free, our distribution
+service is not. An order form is included at the end of manuals printed by
+the Foundation. It is also included in the file @file{etc/DISTRIB} in the
+Emacs distribution. For further information, write to
+
+@display
+Free Software Foundation
+675 Mass Ave
+Cambridge, MA 02139
+USA
+@end display
+
+The income from distribution fees goes to support the foundation's
+purpose: the development of more free software to distribute just like
+GNU Emacs.
+
+If you find GNU Emacs useful, please @b{send a donation} to the Free
+Software Foundation. This will help support development of the rest of the
+GNU system, and other useful software beyond that. Your donation is tax
+deductible.
+
+@node License, Intro, Distrib, Top
+@unnumbered GNU GENERAL PUBLIC LICENSE
+@center Version 1, February 1989
+@cindex license to copy Emacs
+@cindex General Public License
+
+@display
+Copyright @copyright{} 1989 Free Software Foundation, Inc.
+675 Mass Ave, Cambridge, MA 02139, USA
+
+Everyone is permitted to copy and distribute verbatim copies
+of this license document, but changing it is not allowed.
+@end display
+
+@unnumberedsec Preamble
+
+ The license agreements of most software companies try to keep users
+at the mercy of those companies. By contrast, our General Public
+License is intended to guarantee your freedom to share and change free
+software---to make sure the software is free for all its users. The
+General Public License applies to the Free Software Foundation's
+software and to any other program whose authors commit to using it.
+You can use it for your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Specifically, the General Public License is designed to make
+sure that you have the freedom to give away or sell copies of free
+software, that you receive source code or can get it if you want it,
+that you can change the software or use pieces of it in new free
+programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of a such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must tell them their rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+@tex
+\global\baselineskip 11.5pt
+@end tex
+
+@iftex
+@unnumberedsec TERMS AND CONDITIONS
+@end iftex
+@ifinfo
+@center TERMS AND CONDITIONS
+@end ifinfo
+
+@enumerate
+@item
+This License Agreement applies to any program or other work which
+contains a notice placed by the copyright holder saying it may be
+distributed under the terms of this General Public License. The
+``Program'', below, refers to any such program or work, and a ``work based
+on the Program'' means either the Program or any work containing the
+Program or a portion of it, either verbatim or with modifications. Each
+licensee is addressed as ``you''.
+
+@item
+@cindex Distribution
+You may copy and distribute verbatim copies of the Program's source
+code as you receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice and
+disclaimer of warranty; keep intact all the notices that refer to this
+General Public License and to the absence of any warranty; and give any
+other recipients of the Program a copy of this General Public License
+along with the Program. You may charge a fee for the physical act of
+transferring a copy.
+
+@item
+You may modify your copy or copies of the Program or any portion of
+it, and copy and distribute such modifications under the terms of Paragraph
+1 above, provided that you also do the following:
+
+@itemize @bullet
+@item
+cause the modified files to carry prominent notices stating that
+you changed the files and the date of any change; and
+
+@item
+cause the whole of any work that you distribute or publish, that
+in whole or in part contains the Program or any part thereof, either
+with or without modifications, to be licensed at no charge to all
+third parties under the terms of this General Public License (except
+that you may choose to grant warranty protection to some or all
+third parties, at your option).
+
+@item
+If the modified program normally reads commands interactively when
+run, you must cause it, when started running for such interactive use
+in the simplest and most usual way, to print or display an
+announcement including an appropriate copyright notice and a notice
+that there is no warranty (or else, saying that you provide a
+warranty) and that users may redistribute the program under these
+conditions, and telling the user how to view a copy of this General
+Public License.
+
+@item
+You may charge a fee for the physical act of transferring a
+copy, and you may at your option offer warranty protection in
+exchange for a fee.
+@end itemize
+
+Mere aggregation of another independent work with the Program (or its
+derivative) on a volume of a storage or distribution medium does not bring
+the other work under the scope of these terms.
+
+@item
+You may copy and distribute the Program (or a portion or derivative of
+it, under Paragraph 2) in object code or executable form under the terms of
+Paragraphs 1 and 2 above provided that you also do one of the following:
+
+@itemize @bullet
+@item
+accompany it with the complete corresponding machine-readable
+source code, which must be distributed under the terms of
+Paragraphs 1 and 2 above; or,
+
+@item
+accompany it with a written offer, valid for at least three
+years, to give any third party free (except for a nominal charge
+for the cost of distribution) a complete machine-readable copy of the
+corresponding source code, to be distributed under the terms of
+Paragraphs 1 and 2 above; or,
+
+@item
+accompany it with the information you received as to where the
+corresponding source code may be obtained. (This alternative is
+allowed only for noncommercial distribution and only if you
+received the program in object code or executable form alone.)
+@end itemize
+
+Source code for a work means the preferred form of the work for making
+modifications to it. For an executable file, complete source code means
+all the source code for all modules it contains; but, as a special
+exception, it need not include source code for modules which are standard
+libraries that accompany the operating system on which the executable
+file runs, or for standard header files or definitions files that
+accompany that operating system.
+
+@item
+You may not copy, modify, sublicense, distribute or transfer the
+Program except as expressly provided under this General Public License.
+Any attempt otherwise to copy, modify, sublicense, distribute or transfer
+the Program is void, and will automatically terminate your rights to use
+the Program under this License. However, parties who have received
+copies, or rights to use copies, from you under this General Public
+License will not have their licenses terminated so long as such parties
+remain in full compliance.
+
+@item
+By copying, distributing or modifying the Program (or any work based
+on the Program) you indicate your acceptance of this license to do so,
+and all its terms and conditions.
+
+@item
+Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the original
+licensor to copy, distribute or modify the Program subject to these
+terms and conditions. You may not impose any further restrictions on the
+recipients' exercise of the rights granted herein.
+
+@item
+The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of the license which applies to it and ``any
+later version'', you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+the license, you may choose any version ever published by the Free Software
+Foundation.
+
+@item
+If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+@iftex
+@heading NO WARRANTY
+@end iftex
+@ifinfo
+@center NO WARRANTY
+@end ifinfo
+
+@item
+BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM ``AS IS'' WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+@item
+IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL
+ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES
+ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT
+LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES
+SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE
+WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+@end enumerate
+
+@iftex
+@heading END OF TERMS AND CONDITIONS
+@end iftex
+@ifinfo
+@center END OF TERMS AND CONDITIONS
+@end ifinfo
+
+@tex
+\global\baselineskip 12pt
+@end tex
+
+@page
+@unnumberedsec How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to humanity, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these
+terms.
+
+ To do so, attach the following notices to the program. It is safest to
+attach them to the start of each source file to most effectively convey
+the exclusion of warranty; and each file should have at least the
+``copyright'' line and a pointer to where the full notice is found.
+
+@smallexample
+@var{one line to give the program's name and a brief idea of what it does.}
+Copyright (C) 19@var{yy} @var{name of author}
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+@end smallexample
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+@smallexample
+Gnomovision version 69, Copyright (C) 19@var{yy} @var{name of author}
+Gnomovision comes with ABSOLUTELY NO WARRANTY; for details
+type `show w'. This is free software, and you are welcome
+to redistribute it under certain conditions; type `show c'
+for details.
+@end smallexample
+
+The hypothetical commands `show w' and `show c' should show the
+appropriate parts of the General Public License. Of course, the
+commands you use may be called something other than `show w' and `show
+c'; they could even be mouse-clicks or menu items---whatever suits your
+program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a ``copyright disclaimer'' for the program, if
+necessary. Here is a sample; alter the names:
+
+@example
+Yoyodyne, Inc., hereby disclaims all copyright
+interest in the program `Gnomovision'
+(a program to direct compilers to make passes
+at assemblers) written by James Hacker.
+
+@group
+@var{signature of Ty Coon}, 1 April 1989
+Ty Coon, President of Vice
+@end group
+@end example
+
+That's all there is to it!
+
+@node Intro, Glossary, License, Top
+@unnumbered Introduction
+
+ You are reading about GNU Emacs, the GNU incarnation of the advanced,
+self-documenting, customizable, extensible real-time display editor Emacs.
+(The `G' in `GNU' is not silent.)
+
+ We say that Emacs is a @dfn{display} editor because normally the text
+being edited is visible on the screen and is updated automatically as you
+type your commands. @xref{Screen,Display}.
+
+ We call it a @dfn{real-time} editor because the display is updated very
+frequently, usually after each character or pair of characters you
+type. This minimizes the amount of information you must keep in your
+head as you edit. @xref{Basic,Real-time,Basic Editing}.
+
+ We call Emacs advanced because it provides facilities that go beyond
+simple insertion and deletion: filling of text; automatic indentation of
+programs; viewing two or more files at once; and dealing in terms of
+characters, words, lines, sentences, paragraphs, and pages, as well as
+expressions and comments in several different programming languages. It is
+much easier to type one command meaning ``go to the end of the paragraph''
+than to find that spot with simple cursor keys.
+
+ @dfn{Self-documenting} means that at any time you can type a special
+character, @kbd{Control-h}, to find out what your options are. You can
+also use it to find out what any command does, or to find all the commands
+that pertain to a topic. @xref{Help}.
+
+ @dfn{Customizable} means that you can change the definitions of Emacs
+commands in little ways. For example, if you use a programming language in
+which comments start with @samp{<**} and end with @samp{**>}, you can tell
+the Emacs comment manipulation commands to use those strings
+(@pxref{Comments}). Another sort of customization is rearrangement of the
+command set. For example, if you prefer the four basic cursor motion
+commands (up, down, left and right) on keys in a diamond pattern on the
+keyboard, you can have it. @xref{Customization}.
+
+ @dfn{Extensible} means that you can go beyond simple customization and
+write entirely new commands, programs in the Lisp language to be run by
+Emacs's own Lisp interpreter. Emacs is an ``on-line extensible'' system,
+which means that it is divided into many functions that call each other,
+any of which can be redefined in the middle of an editing session. Any
+part of Emacs can be replaced without making a separate copy of all of
+Emacs. Most of the editing commands of Emacs are written in Lisp already;
+the few exceptions could have been written in Lisp but are written in C for
+efficiency. Although only a programmer can write an extension, anybody can
+use it afterward.
+
+@node Screen, Characters, Concept Index, Top
+@chapter The Organization of the Screen
+@cindex screen
+
+ Emacs divides the screen into several areas, each of which contains
+its own sorts of information. The biggest area, of course, is the one
+in which you usually see the text you are editing.
+
+ When you are using Emacs, the screen is divided into a number of
+@dfn{windows}. Initially there is one text window occupying all but the
+last line, plus the special @dfn{echo area} or @dfn{minibuffer window} in
+the last line. The text window can be subdivided horizontally or
+vertically into multiple text windows, each of which can be used for a
+different file (@pxref{Windows}). The window that the cursor is in is the
+@dfn{selected window}, in which editing takes place. The other windows are
+just for reference unless you select one of them.
+
+ Each text window's last line is a @dfn{mode line} which describes what is
+going on in that window. It is in inverse video if the terminal supports
+that, and contains text that starts like @samp{-----Emacs:@: @var{something}}. Its
+purpose is to indicate what buffer is being displayed above it in the
+window; what major and minor modes are in use; and whether the buffer's
+text has been changed.
+
+@menu
+* Point:: The place in the text where editing commands operate.
+* Echo Area:: Short messages appear at the bottom of the screen.
+* Mode Line:: Interpreting the mode line.
+@end menu
+
+@node Point, Echo Area, Screen, Screen
+@section Point
+@cindex point
+@cindex cursor
+
+ When Emacs is running, the terminal's cursor shows the location at
+which editing commands will take effect. This location is called
+@dfn{point}. Other commands move point through the text, so that you
+can edit at different places in it.
+
+ While the cursor appears to point @var{at} a character, point should be
+thought of as @var{between} two characters; it points @var{before} the character
+that the cursor appears on top of. Sometimes people speak of ``the
+cursor'' when they mean ``point'', or speak of commands that move point as
+``cursor motion'' commands.
+
+ Terminals have only one cursor, and when output is in progress it must
+appear where the typing is being done. This does not mean that point is
+moving. It is only that Emacs has no way to show you the location of point
+except when the terminal is idle.
+
+ If you are editing several files in Emacs, each file has its own point
+location. A file that is not being displayed remembers where point is so
+that it can be seen when you look at that file again.
+
+ When there are multiple text windows, each window has its own point
+location. The cursor shows the location of point in the selected window.
+This also is how you can tell which window is selected. If the same buffer
+appears in more than one window, point can be moved in each window
+independently.
+
+ The term `point' comes from the character @samp{.}, which was the
+command in @sc{teco} (the language in which the original Emacs was written)
+for accessing the value now called `point'.
+
+@node Echo Area, Mode Line, Point, Screen
+@section The Echo Area
+@cindex echo area
+
+ The line at the bottom of the screen (below the mode line) is the
+@dfn{echo area}. It is used to display small amounts of text for several
+purposes.
+
+ @dfn{Echoing} means printing out the characters that you type. Emacs
+never echoes single-character commands, and multi-character commands are
+echoed only if you pause while typing them. As soon as you pause for more
+than a second in the middle of a command, all the characters of the command
+so far are echoed. This is intended to @dfn{prompt} you for the rest of
+the command. Once echoing has started, the rest of the command is echoed
+immediately when you type it. This behavior is designed to give confident
+users fast response, while giving hesitant users maximum feedback. You
+can change this behavior by setting a variable (@pxref{Display Vars}).
+
+ If a command cannot be executed, it may print an @dfn{error message} in
+the echo area. Error messages are accompanied by a beep or by flashing the
+screen. Also, any input you have typed ahead is thrown away when an error
+happens.
+
+ Some commands print informative messages in the echo area. These
+messages look much like error messages, but they are not announced with a
+beep and do not throw away input. Sometimes the message tells you what the
+command has done, when this is not obvious from looking at the text being
+edited. Sometimes the sole purpose of a command is to print a message
+giving you specific information. For example, the command @kbd{C-x =} is
+used to print a message describing the character position of point in the
+text and its current column in the window. Commands that take a long time
+often display messages ending in @samp{...} while they are working, and
+add @samp{done} at the end when they are finished.
+
+ The echo area is also used to display the @dfn{minibuffer}, a window that
+is used for reading arguments to commands, such as the name of a file to be
+edited. When the minibuffer is in use, the echo area begins with a prompt
+string that usually ends with a colon; also, the cursor appears in that line
+because it is the selected window. You can always get out of the
+minibuffer by typing @kbd{C-g}. @xref{Minibuffer}.
+
+@node Mode Line,, Echo Area, Screen
+@section The Mode Line
+@cindex mode line
+@cindex top level
+
+ Each text window's last line is a @dfn{mode line} which describes what is
+going on in that window. When there is only one text window, the mode line
+appears right above the echo area. The mode line is in inverse video if
+the terminal supports that, starts and ends with dashes, and contains text
+like @samp{Emacs:@: @var{something}}.
+
+ If a mode line has something else in place of @samp{Emacs:@: @var{something}},
+then the window above it is in a special subsystem such as Dired. The mode
+line then indicates the status of the subsystem.
+
+ Normally, the mode line has the following appearance:
+
+@example
+--@var{ch}-Emacs: @var{buf} (@var{major} @var{minor})----@var{pos}------
+@end example
+
+@noindent
+This gives information about the buffer being displayed in the window: the
+buffer's name, what major and minor modes are in use, whether the buffer's
+text has been changed, and how far down the buffer you are currently
+looking.
+
+ @var{ch} contains two stars @samp{**} if the text in the buffer has been
+edited (the buffer is ``modified''), or @samp{--} if the buffer has not been
+edited. Exception: for a read-only buffer, it is @samp{%%}.
+
+ @var{buf} is the name of the window's chosen @dfn{buffer}. The chosen buffer
+in the selected window (the window that the cursor is in) is also Emacs's
+selected buffer, the one that editing takes place in. When we speak of
+what some command does to ``the buffer'', we are talking about the
+currently selected buffer. @xref{Buffers}.
+
+ @var{pos} tells you whether there is additional text above the top of the
+screen, or below the bottom. If your file is small and it is all on the
+screen, @var{pos} is @samp{All}. Otherwise, it is @samp{Top} if you are
+looking at the beginning of the file, @samp{Bot} if you are looking at the
+end of the file, or @samp{@var{nn}%}, where @var{nn} is the percentage of
+the file above the top of the screen.@refill
+
+ @var{major} is the name of the @dfn{major mode} in effect in the buffer. At
+any time, each buffer is in one and only one of the possible major modes.
+The major modes available include Fundamental mode (the least specialized),
+Text mode, Lisp mode, and C mode. @xref{Major Modes}, for details
+of how the modes differ and how to select one.@refill
+
+ @var{minor} is a list of some of the @dfn{minor modes} that are turned on
+at the moment in the window's chosen buffer. @samp{Fill} means that Auto
+Fill mode is on. @samp{Abbrev} means that Word Abbrev mode is on.
+@samp{Ovwrt} means that Overwrite mode is on. @xref{Minor Modes}, for more
+information. @samp{Narrow} means that the buffer being displayed has
+editing restricted to only a portion of its text. This is not really a
+minor mode, but is like one. @xref{Narrowing}. @samp{Def} means that a
+keyboard macro is being defined. @xref{Keyboard Macros}.
+
+ Some buffers display additional information after the minor modes. For
+example, Rmail buffers display the current message number and the total
+number of messages. Compilation buffers and Shell mode display the status
+of the subprocess.
+
+ In addition, if Emacs is currently inside a recursive editing level,
+square brackets (@samp{[@dots{}]}) appear around the parentheses that
+surround the modes. If Emacs is in one recursive editing level within
+another, double square brackets appear, and so on. Since this information
+pertains to Emacs in general and not to any one buffer, the square brackets
+appear in every mode line on the screen or not in any of them.
+@xref{Recursive Edit}.@refill
+
+@cindex display time
+@cindex time displayed in mode line
+@findex display-time
+ Emacs can optionally display the time and system load in all mode lines.
+To enable this feature, type @kbd{M-x display-time}. The information added
+to the mode line usually appears after the file name, before the mode names
+and their parentheses. It looks like this:
+
+@example
+@var{hh}:@var{mm}pm @var{l.ll} [@var{d}]
+@end example
+
+@noindent
+(Some fields may be missing if your operating system cannot support them.)
+@var{hh} and @var{mm} are the hour and minute, followed always by @samp{am}
+or @samp{pm}. @var{l.ll} is the average number of running processes in the
+whole system recently. @var{d} is an approximate index of the ratio of
+disk activity to cpu activity for all users.
+
+@cindex mail arrival
+The word @samp{Mail} appears after the load level if there is mail for
+you that you have not read yet.
+
+@vindex mode-line-inverse-video
+ Customization note: the user variable @code{mode-line-inverse-video} controls
+whether the mode line is displayed in inverse video (assuming the
+terminal supports it); @code{nil} means no inverse video. The default
+is @code{t}.
+
+@iftex
+@chapter Characters, Keys and Commands
+
+ This chapter explains the character set used by Emacs for input commands
+and for the contents of files, and also explains the concepts of
+@dfn{keys} and @dfn{commands} which are necessary for understanding how
+your keyboard input is understood by Emacs.
+@end iftex
+
+@node Characters, Keys, Screen, Top
+@section The Emacs Character Set
+@cindex character set
+@cindex ASCII
+
+ GNU Emacs uses the @sc{ascii} character set, which defines 128 different
+character codes. Some of these codes are assigned graphic symbols such
+as @samp{a} and @samp{=}; the rest are control characters, such as
+@kbd{Control-a} (also called @kbd{C-a} for short). @kbd{C-a} gets its name
+from the fact that you type it by holding down the @key{CTRL} key and
+then pressing @kbd{a}. There is no distinction between @kbd{C-a} and
+@kbd{C-A}; they are the same character.@refill
+
+ Some control characters have special names, and special keys you can
+type them with: @key{RET}, @key{TAB}, @key{LFD}, @key{DEL} and @key{ESC}.
+The space character is usually referred to below as @key{SPC}, even though
+strictly speaking it is a graphic character whose graphic happens to be
+blank.@refill
+
+ Emacs extends the 7-bit @sc{ascii} code to an 8-bit code by adding an extra
+bit to each character. This makes 256 possible command characters. The
+additional bit is called Meta. Any @sc{ascii} character can be made Meta;
+examples of Meta characters include @kbd{Meta-a} (@kbd{M-a}, for short),
+@kbd{M-A} (not the same character as @kbd{M-a}, but those two characters
+normally have the same meaning in Emacs), @kbd{M-@key{RET}}, and
+@kbd{M-C-a}. For traditional reasons, @kbd{M-C-a} is usually called
+@kbd{C-M-a}; logically speaking, the order in which the modifier keys
+@key{CTRL} and @key{META} are mentioned does not matter.@refill
+
+@cindex Control
+@cindex Meta
+@cindex C-
+@cindex M-
+@cindex ESC replacing META key
+ Some terminals have a @key{META} key, and allow you to type Meta
+characters by holding this key down. Thus, @kbd{Meta-a} is typed by
+holding down @key{META} and pressing @kbd{a}. The @key{META} key works
+much like the @key{SHIFT} key. Such a key is not always labeled
+@key{META}, however, as this function is often a special option for a key
+with some other primary purpose.@refill
+
+ If there is no @key{META} key, you
+can still type Meta characters using two-character sequences starting with
+@key{ESC}. Thus, to enter @kbd{M-a}, you could type @kbd{@key{ESC} a}. To
+enter @kbd{C-M-a}, you would type @kbd{@key{ESC} C-a}. @key{ESC} is
+allowed on terminals with Meta keys, too, in case you have formed a habit
+of using it.@refill
+
+@vindex meta-flag
+ Emacs believes the terminal has a @key{META} key if the variable
+@code{meta-flag} is non-@code{nil}. Normally this is set automatically
+according to the termcap entry for your terminal type. However, sometimes
+the termcap entry is wrong, and then it is useful to set this variable
+yourself. @xref{Variables}, for how to do this.
+
+ Emacs buffers also use an 8-bit character set, because bytes have 8 bits,
+but only the @sc{ascii} characters are considered meaningful.
+@sc{ascii} graphic characters in Emacs buffers are displayed with
+their graphics. @key{LFD} is the same as a newline character; it is
+displayed by starting a new line. @key{TAB} is displayed by moving to
+the next tab stop column (usually every 8 columns). Other control
+characters are displayed as a caret (@samp{^}) followed by the
+non-control version of the character; thus, @kbd{C-a} is displayed as
+@samp{^A}. Non-@sc{ascii} characters 128 and up are displayed with octal
+escape sequences; thus, character code 243 (octal), also called
+@kbd{M-#} when used as an input character, is displayed as
+@samp{\243}.
+@c !! need glossary definition of octal escape sequence
+
+@node Keys, Commands, Characters, Top
+@section Keys
+
+@cindex key
+@cindex prefix key
+ A @dfn{complete key}---where `key' is short for @dfn{key sequence}---is a
+sequence of keystrokes that are understood by Emacs as a unit, as a single
+command (possibly undefined). Most single characters constitute complete
+keys in the standard Emacs command set; there are also some multi-character
+keys. Examples of complete keys are @kbd{C-a}, @kbd{X}, @key{RET},
+@kbd{C-x C-f} and @kbd{C-x 4 C-f}.@refill
+
+@kindex C-c
+@kindex C-x
+@kindex C-h
+@kindex ESC
+ A @dfn{prefix key} is a sequence of keystrokes that are the beginning of
+a complete key, but not a whole one. Prefix keys and complete keys are
+collectively called @dfn{keys}.
+
+ A prefix key is the beginning of a series of longer sequences that are
+valid keys; adding any single character to the end of the prefix gives a
+valid key, which could be defined as an Emacs command, or could be a prefix
+itself. For example, @kbd{C-x} is standardly defined as a prefix, so
+@kbd{C-x} and the next input character combine to make a two-character key.
+There are 256 different two-character keys starting with @kbd{C-x}, one for
+each possible second character. Many of these two-character keys starting
+with @kbd{C-x} are standardly defined as Emacs commands. Notable examples
+include @kbd{C-x C-f} and @kbd{C-x s} (@pxref{Files}).
+
+ Adding one character to a prefix key does not have to form a complete
+key. It could make another, longer prefix. For example, @kbd{C-x 4} is
+itself a prefix that leads to 256 different three-character keys, including
+@kbd{C-x 4 f}, @w{@kbd{C-x 4 b}} and so on. It would be possible to define one
+of those three-character sequences as a prefix, creating a series of
+four-character keys, but we did not define any of them this way.
+
+ By contrast, the two-character sequence @kbd{C-f C-k} is not a key,
+because the @kbd{C-f} is a complete key in itself. It's impossible to give
+@kbd{C-f C-k} an independent meaning as a command as long as @kbd{C-f}
+retains its meaning. @kbd{C-f C-k} is two commands.@refill
+
+ All told, the prefix keys in Emacs are @kbd{C-c}, @kbd{C-x}, @kbd{C-h},
+@kbd{C-x 4}, and @key{ESC}. But this is not built in; it is just a matter
+of Emacs's standard key bindings. In customizing Emacs, you could make
+new prefix keys, or eliminate these. @xref{Key Bindings}.@refill
+
+ Whether a sequence is a key can be changed by customization. For
+example, if you redefine @kbd{C-f} as a prefix, @kbd{C-f C-k} automatically
+becomes a key (complete, unless you define it too as a prefix).
+Conversely, if you remove the prefix definition of @kbd{C-x 4}, then
+@kbd{C-x 4 f} (or @kbd{C-x 4 @var{anything}}) is no longer a key.
+
+@node Commands, Entering Emacs, Keys, Top
+@section Keys and Commands
+
+@cindex binding
+@cindex customization
+@cindex keymap
+@cindex function
+@cindex command
+ This manual is full of passages that tell you what particular keys do.
+But Emacs does not assign meanings to keys directly. Instead, Emacs
+assigns meanings to @dfn{functions}, and then gives keys their meanings by
+@dfn{binding} them to functions.
+
+ A function is a Lisp object that can be executed as a program. Usually
+it is a Lisp symbol which has been given a function definition; every
+symbol has a name, usually made of a few English words separated by
+dashes, such as @code{next-line} or @code{forward-word}. It also has a
+@dfn{definition} which is a Lisp program; this is what makes the
+function do what it does. Only some functions can be the bindings of
+keys; these are functions whose definitions use @code{interactive} to
+specify how to call them interactively. Such functions are called
+@dfn{commands}, and their names are @dfn{command names}.
+@xref{Defining Commands, , Defining Commands, elisp, The GNU Emacs Lisp
+Manual}, for more information.
+
+ The bindings between keys and functions are recorded in various tables
+called @dfn{keymaps}. @xref{Keymaps}.
+
+ When we say that ``@kbd{C-n} moves down vertically one line'' we are
+glossing over a distinction that is irrelevant in ordinary use but is vital
+in understanding how to customize Emacs. It is the function
+@code{next-line} that is programmed to move down vertically. @kbd{C-n} has
+this effect @i{because} it is bound to that function. If you rebind
+@kbd{C-n} to the function @code{forward-word} then @kbd{C-n} will move
+forward by words instead. Rebinding keys is a common method of
+customization.@refill
+
+ In the rest of this manual, we usually ignore this subtlety to keep
+things simple. To give the customizer the information he needs, we
+state the name of the command which really does the work in parentheses
+after mentioning the key that runs it. For example, we will say that
+``The command @kbd{C-n} (@code{next-line}) moves point vertically down,''
+meaning that @code{next-line} is a command that moves vertically down
+and @kbd{C-n} is a key that is standardly bound to it.
+
+ While we are on the subject of information for customization only, it's a
+good time to tell you about @dfn{variables}. Often the description of a
+command will say, ``To change this, set the variable @code{mumble-foo}.''
+A variable is a name used to remember a value. Most of the variables
+documented in this manual exist just to facilitate customization: some
+command or other part of Emacs examines the variable and behaves
+differently accordingly. Until you are interested in customizing, you can
+ignore the information about variables. When you are ready to be
+interested, read the basic information on variables, and then the
+information on individual variables will make sense. @xref{Variables}.
+
+@node Entering Emacs, Exiting, Commands, Top
+@chapter Entering and Exiting Emacs
+@cindex entering Emacs
+
+ The usual way to invoke Emacs is just to type @kbd{emacs @key{RET}} at
+the shell. Emacs clears the screen and then displays an initial advisor
+message and copyright notice. You can begin typing Emacs commands
+immediately afterward.
+
+ Some operating systems insist on discarding all type-ahead when Emacs
+starts up; they give Emacs no way to prevent this. Therefore, it is
+wise to wait until Emacs clears the screen before typing your first
+editing command.
+
+@vindex initial-major-mode
+ Before Emacs reads the first command, you have not had a chance to give a
+command to specify a file to edit. But Emacs must always have a current
+buffer for editing. In an attempt to do something useful, Emacs presents a
+buffer named @samp{*scratch*} which is in Lisp Interaction mode; you can
+use it to type Lisp expressions and evaluate them, or you can ignore that
+capability and simply doodle. (You can specify a different major mode for
+this buffer by setting the variable @code{initial-major-mode} in your init
+file. @xref{Init File}.)
+
+ It is also possible to specify files to be visited, Lisp files to be
+loaded, and functions to be called, by giving Emacs arguments in the
+shell command line. @xref{Command Switches}.
+
+@node Exiting, Command Switches, Entering Emacs, Top
+@section Exiting Emacs
+@cindex exiting
+@cindex killing Emacs
+@cindex suspending
+
+ There are two commands for exiting Emacs because there are two kinds of
+exiting: @dfn{suspending} Emacs and @dfn{killing} Emacs. @dfn{Suspending} means
+stopping Emacs temporarily and returning control to its superior (usually
+the shell), allowing you to resume editing later in the same Emacs job,
+with the same files, same kill ring, same undo history, and so on. This is
+the usual way to exit. @dfn{Killing} Emacs means destroying the Emacs job.
+You can run Emacs again later, but you will get a fresh Emacs; there is no
+way to resume the same editing session after it has been killed.
+
+@table @kbd
+@item C-z
+Suspend Emacs (@code{suspend-emacs}).
+@item C-x C-c
+Kill Emacs (@code{save-buffers-kill-emacs}).
+@end table
+
+@kindex C-z
+@findex suspend-emacs
+ To suspend Emacs, type @kbd{C-z} (@code{suspend-emacs}). This takes
+you back to the shell from which you invoked Emacs. You can resume
+Emacs with the command @code{%emacs} if you are using the C shell or the
+Bourne-Again shell.
+
+ On systems that do not permit programs to be suspended, @kbd{C-z} runs an
+inferior shell that communicates directly with the terminal, and Emacs
+waits until you exit the subshell. The only way on these systems to get
+back to the shell from which Emacs was run (to log out, for example) is to
+kill Emacs. @kbd{C-d} or @code{exit} are typical commands to exit a
+subshell.
+
+@kindex C-x C-c
+@findex save-buffers-kill-emacs
+ To kill Emacs, type @kbd{C-x C-c} (@code{save-buffers-kill-emacs}). A
+two-character key is used for this to make it harder to type. Unless a
+numeric argument is used, this command first offers to save any modified
+buffers. If you do not save them all, it asks for reconfirmation with
+@kbd{yes} before killing Emacs, since any changes not saved before that will be
+lost forever. Also, if any subprocesses are still running, @kbd{C-x C-c}
+asks for confirmation about them, since killing Emacs will kill the
+subprocesses immediately.
+
+ In most programs running on Unix, certain characters may instantly
+suspend or kill the program. (In Berkeley Unix these characters are
+normally @kbd{C-z} and @kbd{C-c}.) @b{This Unix feature is turned off
+while you are in Emacs.} The meanings of @kbd{C-z} and @kbd{C-x C-c} as
+keys in Emacs were inspired by the standard Berkeley Unix meanings of
+@kbd{C-z} and @kbd{C-c}, but that is their only relationship with
+Unix. You could customize these keys to do anything (@pxref{Keymaps}).
+
+@node Command Switches, Basic, Exiting, Top
+@section Command Line Switches and Arguments
+@cindex command line arguments
+@cindex arguments (from shell)
+
+
+ GNU Emacs supports command line arguments to request various actions
+when invoking Emacs. These are for compatibility with other editors and
+for sophisticated activities. They are not needed for ordinary editing
+with Emacs, so new users can skip this section.
+
+ You may be used to using command line arguments with other editors
+to specify which file to edit. That's because many other editors are
+designed to be started afresh each time you want to edit. You
+edit one file and then exit the editor. The next time you want to edit
+either another file or the same one, you must run the editor again.
+With these editors, it makes sense to use a command line argument
+to say which file to edit.
+
+ The recommended way to use GNU Emacs is to start it only once, just after
+you log in, and do all your editing in the same Emacs process. Each time
+you want to edit a different file, you visit it with the existing Emacs,
+which eventually comes to have many files in it ready for editing. Usually
+you do not kill the Emacs until you are about to log out.
+
+ In the usual style of Emacs use, files are nearly always read by
+typing commands to an editor that is already running. So command line
+arguments for specifying a file when the editor is started are seldom
+used.
+
+ Emacs accepts command-line arguments that specify files to visit,
+functions to call, and other activities and operating modes.
+
+ The command arguments are processed in the order they appear in the
+command argument list; however, certain arguments (the ones in the second
+table) must be at the front of the list if they are used.
+
+ Here are the arguments allowed:
+
+@table @samp
+@item @var{file}
+Visit @var{file} using @code{find-file}. @xref{Visiting}.
+
+@item +@var{linenum} @var{file}
+Visit @var{file} using @code{find-file}, then go to line number
+@var{linenum} in it.
+
+@item -l @var{file}
+@itemx -load @var{file}
+Load a file @var{file} of Lisp code with the function @code{load}.
+@xref{Lisp Libraries}.
+
+@item -f @var{function}
+@itemx -funcall @var{function}
+Call Lisp function @var{function} with no arguments.
+
+@item -i @var{file}
+@itemx -insert @var{file}
+Insert the contents of @var{file} into the current buffer.
+This is like what @kbd{M-x insert-buffer} does; see @ref{Misc File Ops}.
+
+@item -kill
+Exit from Emacs without asking for confirmation.
+@end table
+
+ The following switches are recognized only at the beginning of the
+command line. If more than one of them appears, they must appear in the
+order that they appear in this table.
+
+@table @samp
+@item -t @var{device}
+Use @var{device} as the device for terminal input and output.
+
+@item -d @var{display}
+When running with the X window system, use the display named
+@var{display} to make Emacs's X window.
+
+@item -nw
+Don't use a window system; display text only, using an ordinary terminal
+device. Thus, if you run an X-capable Emacs in an Xterm with
+@samp{emacs -nw}, it displays in the Xterm's own window instead of
+making its own.
+
+@cindex batch mode
+@item -batch
+Run Emacs in @dfn{batch mode}, which means that the text being edited is
+not displayed and the standard Unix interrupt characters such as @kbd{C-z}
+and @kbd{C-c} continue to have their normal effect. Emacs in batch mode
+outputs to @code{stdout} only what would normally be printed in the echo
+area under program control.
+
+Batch mode is used for running programs written in Emacs Lisp from
+shell scripts, makefiles, and so on. Normally the @samp{-l} switch
+or @samp{-f} switch will be used as well, to invoke a Lisp program
+to do the batch processing.
+
+@samp{-batch} implies @samp{-q} (do not load an init file). It also
+causes Emacs to exit after all command switches have been processed. In
+addition, auto-saving is not done except in buffers for which it has
+been explicitly requested.
+
+@item -q
+@itemx -no-init-file
+Do not load your Emacs init file @file{~/.emacs}.
+
+@item -u @var{user}
+@itemx -user @var{user}
+Load @var{user}'s Emacs init file @file{~@var{user}/.emacs} instead of
+your own.
+@end table
+
+ With X Windows, you can use these additional options to specify how to
+display the window. Each option has a corresponding resource name (used
+with @samp{emacs} unless you specify another name with @samp{-rn
+@var{name}}), listed with the option, which lets you specify the same
+parameter using the usual X Windows defaulting mechanism. The
+corresponding generic resource name (used with @samp{Emacs}) is usually
+made by capitalizing the first letter of the individual resource name,
+but in some cases it is a completely different string (which is listed
+below).
+
+@table @code
+@item -rn @var{name}
+Use @var{name} instead of @samp{emacs} when looking for X resources.
+
+@item -font @var{fontname}
+@itemx -fn @var{fontname}
+Use font @var{fontname}.@*
+(Resource @samp{font}.)
+
+@item -wn @var{name}
+Name the window @var{name}.@*
+(Resource @samp{title}.)
+
+@item -i
+Use a bitmap icon (showing the kitchen sink)
+rather than a textual icon.@*
+(Resource @samp{bitmapIcon}.)
+
+@item -in @var{name}
+Name the icon @var{name}. (Resource @samp{iconName}; @samp{Title}).
+
+@item -geometry @var{coords}
+@itemx -w @var{coords}
+Specify the shape and optionally the position
+of the Emacs window in the usual X way.@*
+(Resource @samp{geometry}.)
+
+@item -b @var{width}
+Specify that the window border is @var{width} pixels thick.@*
+(Resource @samp{borderWidth}.)
+
+@item -ib @var{width}
+Leave @var{width} blank pixels between the border
+and the window contents.@*
+(Resource @samp{internalBorder}; @samp{BorderWidth}.)
+
+@item -r
+Use reverse video.@*
+(Resource @samp{reverseVideo}.)
+
+@item -fg @var{color}
+Use color @var{color} for text in the window.@*
+(Resource @samp{foreground}.)
+
+@item -bg @var{color}
+Use the color @var{color} for the background of the window.@*
+(Resource @samp{background}.)
+
+@item -bd @var{color}
+Use color @var{color} for the window border.@*
+(Resource @samp{borderColor}.)
+
+@item -cr @var{color}
+Specify the color, @var{color}, to use for the cursor.@*
+(Resource @samp{cursorColor}; @samp{Foreground}.)
+
+@item -ms @var{color}
+Use color @var{color} for the mouse cursor.@*
+(Resource @samp{pointerColor}; @samp{Foreground}.)
+@end table
+
+@vindex command-line-args
+ The init file can get access to the command line argument values as
+the elements of a list in the variable @code{command-line-args}. (The
+arguments in the second table above will already have been processed and
+will not be in the list.) The init file can override the normal
+processing of the other arguments by setting this variable.
+
+ One way to use command arguments is to visit many files automatically:
+
+@example
+emacs *.c
+@end example
+
+@noindent
+passes each @code{.c} file as a separate argument to Emacs, so that Emacs
+visits each file (@pxref{Visiting}).
+
+ Here is an advanced example that assumes you have a Lisp program
+file called @file{hack-c-program.el} which, when loaded, performs some
+useful operation on current buffer, expected to be a C program.
+
+@smallexample
+emacs -batch foo.c -l hack-c-program -f save-buffer -kill > log
+@end smallexample
+
+@noindent
+This says to visit @file{foo.c}, load @file{hack-c-program.el} (which
+makes changes in the visited file), save @file{foo.c} (note that
+@code{save-buffer} is the function that @kbd{C-x C-s} is bound to), and
+then exit to the shell that this command was done with. @samp{-batch}
+guarantees there will be no problem redirecting output to @file{log},
+because Emacs will not assume that it has a display terminal to work
+with.
+
+@node Basic, Undo, Command Switches, Top
+@chapter Basic Editing Commands
+
+@kindex C-h t
+@findex help-with-tutorial
+ We now give the basics of how to enter text, make corrections, and
+save the text in a file. If this material is new to you, you might
+learn it more easily by running the Emacs learn-by-doing tutorial. To
+do this, type @w{@kbd{Control-h t}} (@code{help-with-tutorial}).
+
+@section Inserting Text
+
+@cindex insertion
+@cindex point
+@cindex cursor
+@cindex graphic characters
+ To insert printing characters into the text you are editing, just type
+them. This inserts the character into the buffer at the cursor (that is,
+at @dfn{point}; @pxref{Point}). The cursor moves forward. Any characters
+after the cursor move forward too. If the text in the buffer is
+@samp{FOOBAR}, with the cursor before the @samp{B}, then if you type
+@kbd{XX}, you get @samp{FOOXXBAR}, with the cursor still before the
+@samp{B}.
+
+@kindex DEL
+@cindex deletion
+ To @dfn{delete} text you have just inserted, use @key{DEL}. @key{DEL}
+deletes the character @var{before} the cursor (not the one that the cursor
+is on top of or under; that is the character @var{after} the cursor). The
+cursor and all characters after it move backwards. Therefore, if you type
+a printing character and then type @key{DEL}, they cancel out.
+
+@kindex RET
+@cindex newline
+ To end a line and start typing a new one, type @key{RET}. This inserts
+a newline character in the buffer. If point is in the middle of a line,
+@key{RET} splits the line. Typing @key{DEL} when the cursor is at the
+beginning of a line rubs out the newline before the line, thus joining the
+line with the preceding line.
+
+ Emacs will split lines automatically when they become too long, if you
+turn on a special mode called @dfn{Auto Fill} mode. @xref{Filling}, for
+how to use Auto Fill mode.
+
+@findex delete-backward-char
+@findex newline
+@findex self-insert
+ Customization information: @key{DEL} in most modes runs the command named
+@code{delete-backward-char}; @key{RET} runs the command @code{newline}, and
+self-inserting printing characters run the command @code{self-insert},
+which inserts whatever character was typed to invoke it. Some major modes
+rebind @key{DEL} to other commands.
+
+@cindex quoting
+@kindex C-q
+@findex quoted-insert
+ Direct insertion works for printing characters and @key{SPC}, but other
+characters act as editing commands and do not insert themselves. If you
+need to insert a control character or a character whose code is above 200
+octal, you must @dfn{quote} it by typing the character @kbd{control-q}
+(@code{quoted-insert}) first. There are two ways to use @kbd{C-q}:@refill
+
+@itemize @bullet
+@item
+@kbd{Control-q} followed by any non-graphic character (even @kbd{C-g})
+inserts that character.
+@item
+@kbd{Control-q} followed by three octal digits inserts the character
+with the specified character code.
+@end itemize
+
+@noindent
+A numeric argument to @kbd{C-q} specifies how many copies of the
+quoted character should be inserted (@pxref{Arguments}).
+
+ If you prefer to have text characters replace (overwrite) existing
+text rather than shove it to the right, you can enable Overwrite mode,
+a minor mode. @xref{Minor Modes}.
+
+@section Changing the Location of Point
+
+ To do more than insert characters, you have to know how to move
+point (@pxref{Point}). Here are a few of the commands for doing that.
+
+@kindex C-a
+@kindex C-e
+@kindex C-f
+@kindex C-b
+@kindex C-n
+@kindex C-p
+@kindex C-l
+@kindex C-t
+@kindex M->
+@kindex M-<
+@kindex M-r
+@findex beginning-of-line
+@findex end-of-line
+@findex forward-char
+@findex backward-char
+@findex next-line
+@findex previous-line
+@findex recenter
+@findex transpose-chars
+@findex beginning-of-buffer
+@findex end-of-buffer
+@findex goto-char
+@findex goto-line
+@findex move-to-window-line
+@table @kbd
+@item C-a
+Move to the beginning of the line (@code{beginning-of-line}).
+@item C-e
+Move to the end of the line (@code{end-of-line}).
+@item C-f
+Move forward one character (@code{forward-char}).
+@item C-b
+Move backward one character (@code{backward-char}).
+@item M-f
+Move forward one word (@code{forward-word}).
+@item M-b
+Move backward one word (@code{backward-word}).
+@item C-n
+Move down one line, vertically (@code{next-line}). This command
+attempts to keep the horizontal position unchanged, so if you start in
+the middle of one line, you end in the middle of the next. When on
+the last line of text, @kbd{C-n} creates a new line and moves onto it.
+@item C-p
+Move up one line, vertically (@code{previous-line}).
+@item C-l
+Clear the screen and reprint everything (@code{recenter}). Text moves
+on the screen to bring point to the center of the window.
+@item M-r
+Move point to left margin on the line halfway down the screen or
+window (@code{move-to-window-line}). Text does not move on the
+screen. A numeric argument says how many screen lines down from the
+top of the window (zero for the top). A negative argument counts from
+the bottom (@minus{}1 for the bottom).
+@item C-t
+Transpose two characters, the ones before and after the cursor
+(@code{transpose-chars}).
+@item M-<
+Move to the top of the buffer (@code{beginning-of-buffer}). With
+numeric argument @var{n}, move to @var{n}/10 of the way from the top.
+@xref{Arguments}, for more information on numeric arguments.@refill
+@item M->
+Move to the end of the buffer (@code{end-of-buffer}).
+@item M-x goto-char
+Read a number @var{n} and move cursor to character number @var{n}.
+Position 1 is the beginning of the buffer.
+@item M-x goto-line
+Read a number @var{n} and move cursor to line number @var{n}. Line 1
+is the beginning of the buffer.
+@item C-x C-n
+@findex set-goal-column
+@cindex goal column
+Use the current column of point as the @dfn{semipermanent goal column} for
+@kbd{C-n} and @kbd{C-p} (@code{set-goal-column}). Henceforth, those
+commands always move to this column in each line moved into, or as
+close as possible given the contents of the line. This goal column remains
+in effect until canceled.
+@item C-u C-x C-n
+Cancel the goal column. Henceforth, @kbd{C-n} and @kbd{C-p} once
+again try to avoid changing the horizontal position, as usual.
+@end table
+
+@vindex track-eol
+ If you set the variable @code{track-eol} to a non-@code{nil} value, then
+@kbd{C-n} and @kbd{C-p} when at the end of the starting line move to the
+end of the line. Normally, @code{track-eol} is @code{nil}.
+
+@section Erasing Text
+
+@table @kbd
+@item @key{DEL}
+Delete the character before the cursor (@code{delete-backward-char}).
+@item C-d
+Delete the character after the cursor (@code{delete-char}).
+@item C-k
+Kill to the end of the line (@code{kill-line}).
+@item M-d
+Kill forward to the end of the next word (@code{kill-word}).
+@item M-@key{DEL}
+Kill back to the beginning of the previous word
+(@code{backward-kill-word}).
+@end table
+
+ You already know about the @key{DEL} key which deletes the character
+before the cursor. Another key, @kbd{Control-d}, deletes the character
+after the cursor, causing the rest of the text on the line to shift left.
+If @kbd{Control-d} is typed at the end of a line, that line and the next
+line are joined together.
+
+ To erase a larger amount of text, use the @kbd{Control-k} key, which
+kills a line at a time. If @kbd{C-k} is done at the beginning or middle of
+a line, it kills all the text up to the end of the line. If @kbd{C-k} is
+done at the end of a line, it joins that line and the next line.
+
+ @xref{Killing}, for more flexible ways of killing text.
+
+@section Files
+
+@cindex files
+ The commands above are sufficient for creating and altering text in an
+Emacs buffer; the more advanced Emacs commands just make things easier.
+But to keep any text permanently you must put it in a @dfn{file}. Files
+are named units of text which are stored by the operating system for you to
+retrieve later by name. To look at or use the contents of a file in any
+way, including editing the file with Emacs, you must specify the file name.
+
+ Consider a file named @file{/usr/rms/foo.c}. In Emacs, to begin editing
+this file, type
+
+@example
+C-x C-f /usr/rms/foo.c @key{RET}
+@end example
+
+@noindent
+Here the file name is given as an @dfn{argument} to the command @kbd{C-x
+C-f} (@code{find-file}). That command uses the @dfn{minibuffer} to
+read the argument, and you type @key{RET} to terminate the argument
+(@pxref{Minibuffer}).@refill
+
+ Emacs obeys the command by @dfn{visiting} the file: creating a buffer,
+copying the contents of the file into the buffer, and then displaying the
+buffer for you to edit. You can make changes in it, and then @dfn{save}
+the file by typing @kbd{C-x C-s} (@code{save-buffer}). This makes the
+changes permanent by copying the altered contents of the buffer back into
+the file @file{/usr/rms/foo.c}. Until then, the changes are only inside
+your Emacs, and the file @file{foo.c} is not changed.@refill
+
+ To create a file, just visit the file with @kbd{C-x C-f} as if it already
+existed. Emacs will make an empty buffer in which you can insert the text
+you want to put in the file. When you save your text with @kbd{C-x C-s},
+the file will be created.
+
+ Of course, there is a lot more to learn about using files. @xref{Files}.
+
+@section Help
+
+ If you forget what a key does, you can find out with the Help character,
+which is @kbd{C-h}. Type @kbd{C-h k} followed by the key you want to know
+about; for example, @kbd{C-h k C-n} tells you all about what @kbd{C-n}
+does. @kbd{C-h} is a prefix key; @kbd{C-h k} is just one of its
+subcommands (the command @code{describe-key}). The other subcommands of
+@kbd{C-h} provide different kinds of help. Type @kbd{C-h} three times
+to get a description of all the help facilities. @xref{Help}.@refill
+
+@menu
+* Blank Lines:: Commands to make or delete blank lines.
+* Continuation Lines:: Lines too wide for the screen.
+* Position Info:: What page, line, row, or column is point on?
+* Arguments:: Numeric arguments for repeating a command.
+@end menu
+
+@page
+@node Blank Lines, Continuation Lines, Basic, Basic
+@section Blank Lines
+
+ Here are special commands and techniques for putting in and taking out
+blank lines.
+
+@c widecommands
+@table @kbd
+@item C-o
+Insert one or more blank lines after the cursor (@code{open-line}).
+@item C-x C-o
+Delete all but one of many consecutive blank lines
+(@code{delete-blank-lines}).
+@end table
+
+@kindex C-o
+@kindex C-x C-o
+@cindex blank lines
+@findex open-line
+@findex delete-blank-lines
+ When you want to insert a new line of text before an existing line, you
+can do it by typing the new line of text, followed by @key{RET}. However,
+it may be easier to see what you are doing if you first make a blank line
+and then insert the desired text into it. This is easy to do using the key
+@kbd{C-o} (@code{open-line}), which inserts a newline after point but leaves
+point in front of the newline. After @kbd{C-o}, type the text for the new
+line. @kbd{C-o F O O} has the same effect as @w{@kbd{F O O @key{RET}},} except for
+the final location of point.
+
+ You can make several blank lines by typing @kbd{C-o} several times, or by
+giving it an argument to tell it how many blank lines to make.
+@xref{Arguments}, for how.
+
+ If you have many blank lines in a row and want to get rid of them, use
+@kbd{C-x C-o} (@code{delete-blank-lines}). When point is on a blank line which
+is adjacent to at least one other blank line, @kbd{C-x C-o} deletes all but
+one of the consecutive blank lines, leaving exactly one. With point on a
+blank line with no other blank line adjacent to it, the sole blank line is
+deleted, leaving none. When point is on a nonblank line, @kbd{C-x C-o}
+deletes any blank lines following that nonblank line.
+
+@node Continuation Lines, Position Info, Blank Lines, Basic
+@section Continuation Lines
+
+@cindex continuation line
+ If you add too many characters to one line, without breaking it with a
+@key{RET}, the line will grow to occupy two (or more) lines on the screen,
+with a @samp{\} at the extreme right margin of all but the last of them.
+The @samp{\} says that the following screen line is not really a distinct
+line in the text, but just the @dfn{continuation} of a line too long to fit
+the screen. Sometimes it is nice to have Emacs insert newlines
+automatically when a line gets too long; for this, use Auto Fill mode
+(@pxref{Filling}).
+
+@vindex truncate-lines
+@cindex truncation
+ Instead of continuation, long lines can be displayed by @dfn{truncation}.
+This means that all the characters that do not fit in the width of the
+screen or window do not appear at all. They remain in the buffer,
+temporarily invisible. @samp{$} is used in the last column instead of
+@samp{\} to inform you that truncation is in effect.
+
+ Continuation can be turned off for a particular buffer by setting the
+variable @code{truncate-lines} to non-@code{nil} in that buffer.
+Truncation instead of continuation also happens whenever horizontal
+scrolling is in use, and optionally whenever side-by-side windows are in
+use (@pxref{Windows}). Altering the value of @code{truncate-lines} makes
+it local to the current buffer; until that time, the default value is in
+effect. The default is initially @code{nil}. @xref{Locals}.@refill
+
+@node Position Info, Arguments, Continuation Lines, Basic
+@section Cursor Position Information
+
+ If you are accustomed to other display editors, you may be surprised that
+Emacs does not always display the page number or line number of point in
+the mode line. This is because the text is stored in a way that makes it
+difficult to compute this information. Displaying them all the time would
+be intolerably slow. They are not needed very often in Emacs anyway,
+but there are commands to compute them and print them.
+
+@table @kbd
+@item M-x what-page
+Print page number of point, and line number within page.
+@item M-x what-line
+Print line number of point in the buffer.
+@item M-=
+Print number of lines in the current region (@code{count-lines-region}).
+@item C-x =
+Print character code of character after point, character position of
+point, and column of point (@code{what-cursor-position}).
+@end table
+
+@findex what-page
+@findex what-line
+@cindex line number
+ There are two commands for printing line numbers. @kbd{M-x what-line}
+counts lines from the beginning of the file and prints the line number
+point is on. The first line of the file is line number 1. These numbers
+can be used as arguments to @kbd{M-x goto-line}. By contrast, @kbd{M-x
+what-page} counts pages from the beginning of the file, and counts lines
+within the page, printing both of them. @xref{Pages}.
+
+@kindex M-=
+@findex count-lines-region
+ While on this subject, we might as well mention @kbd{M-=} (@code{count-lines-region}),
+which prints the number of lines in the region (@pxref{Mark}).
+@xref{Pages}, for the command @kbd{C-x l} which counts the lines in the
+current page.
+
+@kindex C-x =
+@findex what-cursor-position
+ The command @kbd{C-x =} (@code{what-cursor-position}) can be used to find out
+the column that the cursor is in, and other miscellaneous information about
+point. It prints a line in the echo area that looks like this:
+
+@example
+Char: x (0170) point=65986 of 563027(12%) x=44
+@end example
+
+@noindent
+(In fact, this is the output produced when point is before the @samp{x=44}
+in the example.)
+
+ The two values after @samp{Char:} describe the character following point,
+first by showing it and second by giving its octal character code.
+
+ @samp{point=} is followed by the position of point expressed as a character
+count. The front of the buffer counts as position 1, one character later
+as 2, and so on. The next, larger number is the total number of characters
+in the buffer. Afterward in parentheses comes the position expressed as a
+percentage of the total size.
+
+ @samp{x=} is followed by the horizontal position of point, in columns from the
+left edge of the window.
+
+ If the buffer has been narrowed, making some of the text at the beginning and
+the end temporarily invisible, @kbd{C-x =} prints additional text describing the
+current visible range. For example, it might say
+
+@smallexample
+Char: x (0170) point=65986 of 563025(12%) <65102 - 68533> x=44
+@end smallexample
+
+@noindent
+where the two extra numbers give the smallest and largest character position
+that point is allowed to assume. The characters between those two positions
+are the visible ones. @xref{Narrowing}.
+
+ If point is at the end of the buffer (or the end of the visible part),
+@kbd{C-x =} omits any description of the character after point.
+The output looks like
+
+@smallexample
+point=563026 of 563025(100%) x=0
+@end smallexample
+
+@node Arguments,, Position Info, Basic
+@section Numeric Arguments
+@cindex numeric arguments
+@cindex prefix arguments
+@cindex arguments, prefix and numeric
+
+ Any Emacs command can be given a @dfn{numeric argument}. Some commands
+interpret the argument as a repetition count. For example, giving an
+argument of ten to the key @kbd{C-f} (the command @code{forward-char}, move
+forward one character) moves forward ten characters. With these commands,
+no argument is equivalent to an argument of one. Negative arguments are
+allowed. Often they tell a command to move or act backwards.
+
+@kindex M-1
+@kindex M-@t{-}
+@findex digit-argument
+@findex negative-argument
+ If your terminal keyboard has a @key{META} key, the easiest way to
+specify a numeric argument is to type digits and/or a minus sign while
+holding down the @key{META} key. For example,
+@example
+M-5 C-n
+@end example
+@noindent
+would move down five lines. The characters @kbd{Meta-1}, @kbd{Meta-2}, and
+so on, as well as @kbd{Meta--}, do this because they are keys bound to
+commands (@code{digit-argument} and @code{negative-argument}) that are
+defined to contribute to an argument for the next command.
+
+@kindex C-u
+@findex universal-argument
+@cindex universal argument
+ Another way of specifying an argument is to use the @kbd{C-u}
+(@code{universal-argument}) command followed by the digits of the argument.
+With @kbd{C-u}, you can type the argument digits without holding
+down shift keys. To type a negative argument, start with a minus sign.
+Just a minus sign normally means @minus{}1. @kbd{C-u} works on all terminals.
+
+ @kbd{C-u} followed by a character which is neither a digit nor a minus
+sign has the special meaning of ``multiply by four''. It multiplies the
+argument for the next command by four. @kbd{C-u} twice multiplies it by
+sixteen. Thus, @kbd{C-u C-u C-f} moves forward sixteen characters. This
+is a good way to move forward ``fast'', since it moves about 1/5 of a line
+in the usual size screen. Other useful combinations are @kbd{C-u C-n},
+@kbd{C-u C-u C-n} (move down a good fraction of a screen), @kbd{C-u C-u
+C-o} (make ``a lot'' of blank lines), and @kbd{C-u C-k} (kill four
+lines).@refill
+
+ Some commands care only about whether there is an argument, and not about
+its value. For example, the command @kbd{M-q} (@code{fill-paragraph}) with
+no argument fills text; with an argument, it justifies the text as well.
+(@xref{Filling}, for more information on @kbd{M-q}.) Just @kbd{C-u} is a
+handy way of providing an argument for such commands.
+
+ Some commands use the value of the argument as a repeat count, but do
+something peculiar when there is no argument. For example, the command
+@kbd{C-k} (@code{kill-line}) with argument @var{n} kills @var{n} lines,
+including their terminating newlines. But @kbd{C-k} with no argument is
+special: it kills the text up to the next newline, or, if point is right at
+the end of the line, it kills the newline itself. Thus, two @kbd{C-k}
+commands with no arguments can kill a nonblank line, just like @kbd{C-k}
+with an argument of one. (@xref{Killing}, for more information on
+@kbd{C-k}.)@refill
+
+ A few commands treat a plain @kbd{C-u} differently from an ordinary
+argument. A few others may treat an argument of just a minus sign
+differently from an argument of @minus{}1. These unusual cases will be
+described when they come up; they are always for reasons of convenience
+of use of the individual command.
+
+ To insert multiple copies of a digit, you can type @kbd{C-u
+@var{count} C-u @var{digit}}. The second @kbd{C-u} ends the numeric
+argument, so that the following character always acts a key sequence
+to be executed.
+
+@c section Autoarg Mode
+@ignore
+@cindex Autoarg mode
+ Users of @sc{ascii} keyboards may prefer to use Autoarg mode. Autoarg mode
+means that you don't need to type C-U to specify a numeric argument.
+Instead, you type just the digits. Digits followed by an ordinary
+inserting character are themselves inserted, but digits followed by an
+Escape or Control character serve as an argument to it and are not
+inserted. A minus sign can also be part of an argument, but only at the
+beginning. If you type a minus sign following some digits, both the digits
+and the minus sign are inserted.
+
+ To use Autoarg mode, set the variable @code{autoarg-mode} nonzero.
+@xref{Variables}.
+
+ Autoargument digits echo at the bottom of the screen; the first nondigit
+causes them to be inserted or uses them as an argument. To insert some
+digits and nothing else, you must follow them with a Space and then rub it
+out. C-G cancels the digits, while Delete inserts them all and then rubs
+out the last.
+@end ignore
+
+@node Undo, Minibuffer, Basic, Top
+@chapter Undoing Changes
+@cindex undo
+@cindex mistakes, correcting
+
+ Emacs allows all changes made in the text of a buffer to be undone,
+up to a certain amount of change (8000 characters). Each buffer records
+changes individually, and the undo command always applies to the
+current buffer. Usually each editing command makes a separate entry
+in the undo records, but some commands such as @code{query-replace}
+make many entries, and very simple commands such as self-inserting
+characters are often grouped to make undoing less tedious.
+
+@table @kbd
+@item C-x u
+Undo one batch of changes (usually, one command worth) (@code{undo}).
+@item C-_
+The same.
+@end table
+
+@kindex C-x u
+@kindex C-_
+@findex undo
+ The command @kbd{C-x u} or @kbd{C-_} is how you undo. The first time you give
+this command, it undoes the last change. Point moves to the text
+affected by the undo, so you can see what was undone.
+
+ Consecutive repetitions of the @kbd{C-_} or @kbd{C-x u} commands undo earlier
+and earlier changes, back to the limit of what has been recorded. If all
+recorded changes have already been undone, the undo command prints an error
+message and does nothing.
+
+ Any command other than an undo command breaks the sequence of undo
+commands. Starting at this moment, the previous undo commands are
+considered ordinary changes that can themselves be undone. Thus, to
+redo changes you have undone, type @kbd{C-f} or any other command that
+will have no important effect, and then give more undo commands.
+
+ If you notice that a buffer has been modified accidentally, the easiest
+way to recover is to type @kbd{C-_} repeatedly until the stars disappear
+from the front of the mode line. At this time, all the modifications you
+made have been cancelled. If you do not remember whether you changed the
+buffer deliberately, type @kbd{C-_} once, and when you see the last change
+you made undone, you will remember why you made it. If it was an accident,
+leave it undone. If it was deliberate, redo the change as described in the
+preceding paragraph.
+
+ Whenever an undo command makes the stars disappear from the mode line,
+it means that the buffer contents are the same as they were when the
+file was last read in or saved.
+
+@findex buffer-enable-undo
+ Not all buffers record undo information. Buffers whose names start with
+spaces don't; these buffers are used internally by Emacs and its extensions
+to hold text that users don't normally look at or edit. Also, minibuffers,
+help buffers and documentation buffers don't record undo information.
+Use the command @code{buffer-enable-undo} to enable recording undo information
+in the current buffer.
+
+ As editing continues, undo lists get longer and longer. To prevent
+them from using up all available memory space, garbage collection trims
+back their sizes to thresholds you can set. (For this purpose, the
+``size'' of an undo list measures the cons cells that make up the list,
+plus the strings of deleted text.)
+
+@vindex undo-limit
+@vindex undo-strong-limit
+ Two variables control the range of acceptable sizes: @code{undo-limit}
+and @code{undo-strong-limit}. Normally, the most recent changes are
+kept until their size exceeds @code{undo-limit}; all older changes are
+discarded. But if a change pushes the size above
+@code{undo-strong-limit}, it is discarded as well as all older changes.
+One exception: the most recent set of changes is sacred; garbage
+collection never discards that. (In Emacs versions 18.57 and 18.58,
+these variables are called @code{undo-threshold} and
+@code{undo-high-threshold}.)
+
+ The reason the @code{undo} command has two keys, @kbd{C-x u} and
+@kbd{C-_}, set up to run it is that it is worthy of a single-character
+key, but the way to type @kbd{C-_} on some keyboards is not obvious.
+@kbd{C-x u} is an alternative you can type in the same fashion on any
+terminal.
+
+@node Minibuffer, M-x, Undo, Top
+@chapter The Minibuffer
+@cindex minibuffer
+
+ The @dfn{minibuffer} is the facility used by Emacs commands to read
+arguments more complicated than a single number. Minibuffer arguments can
+be file names, buffer names, Lisp function names, Emacs command names, Lisp
+expressions, and many other things, depending on the command reading the
+argument. The usual Emacs editing commands can be used in the minibuffer
+to edit the argument.
+
+@cindex prompt
+ When the minibuffer is in use, it appears in the echo area, and the
+terminal's cursor moves there. The beginning of the minibuffer line
+displays a @dfn{prompt} which says what kind of input you should supply and
+how it will be used. Often this prompt is derived from the name of the
+command that the argument is for. The prompt normally ends with a colon.
+
+@cindex default argument
+ Sometimes a @dfn{default argument} appears in parentheses after the
+colon; it too is part of the prompt. The default will be used as the
+argument value if you enter an empty argument (e.g., just type @key{RET}).
+For example, commands that read buffer names always show a default, which
+is the name of the buffer that will be used if you type just @key{RET}.
+
+@kindex C-g
+ The simplest way to give a minibuffer argument is to type the text you
+want, terminated by @key{RET} which exits the minibuffer. You can get out
+of the minibuffer, canceling the command that it was for, by typing
+@kbd{C-g}.
+
+ Since the minibuffer uses the screen space of the echo area, it can
+conflict with other ways Emacs customarily uses the echo area. Here is how
+Emacs handles such conflicts:
+
+@itemize @bullet
+@item
+If a command gets an error while you are in the minibuffer, this does
+not cancel the minibuffer. However, the echo area is needed for the
+error message and therefore the minibuffer itself is hidden for a
+while. It comes back after a few seconds, or as soon as you type
+anything.
+
+@item
+If in the minibuffer you use a command whose purpose is to print a
+message in the echo area, such as @kbd{C-x =}, the message is printed
+normally, and the minibuffer is hidden for a while. It comes back
+after a few seconds, or as soon as you type anything.
+
+@item
+Echoing of keystrokes does not take place while the minibuffer is in
+use.
+@end itemize
+
+@menu
+* File: Minibuffer File. Entering file names with the minibuffer.
+* Edit: Minibuffer Edit. How to edit in the minibuffer.
+* Completion:: An abbreviation facility for minibuffer input.
+* Repetition:: Re-executing commands that used the minibuffer.
+@end menu
+
+@node Minibuffer File, Minibuffer Edit, Minibuffer, Minibuffer
+@section Minibuffers for File Names
+
+ Sometimes the minibuffer starts out with text in it. For example, when
+you are supposed to give a file name, the minibuffer starts out containing
+the @dfn{default directory}, which ends with a slash. This is to inform
+you which directory the file will be found in if you do not specify a
+directory. For example, the minibuffer might start out with
+
+@example
+Find File: /u2/emacs/src/
+@end example
+
+@noindent
+where @samp{Find File:@: } is the prompt. Typing @kbd{buffer.c} specifies
+the file @file{/u2/emacs/src/buffer.c}. To find files in nearby
+directories, use @kbd{..}; thus, if you type @kbd{../lisp/simple.el}, the
+file that you visit will be the one named @file{/u2/emacs/lisp/simple.el}.
+Alternatively, you can kill with @kbd{M-@key{DEL}} the directory names you
+don't want (@pxref{Words}).@refill
+
+ You can also type an absolute file name, one starting with a slash or a
+tilde, ignoring the default directory. For example, to find the file
+@file{/etc/termcap}, just type the name, giving
+
+@example
+Find File: /u2/emacs/src//etc/termcap
+@end example
+
+@noindent
+Two slashes in a row are not normally meaningful in Unix file names, but
+they are allowed in GNU Emacs. They mean, ``ignore everything before the
+second slash in the pair.'' Thus, @samp{/u2/emacs/src/} is ignored, and
+you get the file @file{/etc/termcap}.
+
+@vindex insert-default-directory
+ If you set @code{insert-default-directory} to @code{nil}, the default directory
+is not inserted in the minibuffer. This way, the minibuffer starts out
+empty. But the name you type, if relative, is still interpreted with
+respect to the same default directory.
+
+@node Minibuffer Edit, Completion, Minibuffer File, Minibuffer
+@section Editing in the Minibuffer
+
+ The minibuffer is an Emacs buffer (albeit a peculiar one), and the usual
+Emacs commands are available for editing the text of an argument you are
+entering.
+
+ Since @key{RET} in the minibuffer is defined to exit the minibuffer,
+inserting a newline into the minibuffer must be done with @kbd{C-o} or with
+@kbd{C-q @key{LFD}}. (Recall that a newline is really the @key{LFD}
+character.)
+
+ The minibuffer has its own window which always has space on the screen
+but acts as if it were not there when the minibuffer is not in use. When
+the minibuffer is in use, its window is just like the others; you can
+switch to another window with @kbd{C-x o}, edit text in other windows and
+perhaps even visit more files, before returning to the minibuffer to submit
+the argument. You can kill text in another window, return to the
+minibuffer window, and then yank the text to use it in the argument.
+@xref{Windows}.
+
+ There are some restrictions on the use of the minibuffer window, however.
+You cannot switch buffers in it---the minibuffer and its window are
+permanently attached. Also, you cannot split or kill the minibuffer
+window. But you can make it taller in the normal fashion with
+@kbd{C-x ^} (@pxref{Change Window}).
+
+@kindex C-M-v
+ If while in the minibuffer you issue a command that displays help text
+of any sort in another window, then that window is identified as the
+one to scroll if you type @kbd{C-M-v} while in the minibuffer. This
+lasts until you exit the minibuffer. This feature comes into play
+if a completing minibuffer gives you a list of possible completions.
+
+@cindex recursive minibuffer
+ Recursive use of the minibuffer is supported by Emacs. However, it is
+easy to do this by accident (because of autorepeating keyboards, for
+example) and get confused. Therefore, most Emacs commands that use the
+minibuffer refuse to operate if the minibuffer window is selected. If the
+minibuffer is active but you have switched to a different window, recursive
+use of the minibuffer is allowed---if you know enough to try to do this,
+you probably will not get confused.
+
+@vindex enable-recursive-minibuffers
+ If you set the variable @code{enable-recursive-minibuffers} to be
+non-@code{nil}, recursive use of the minibuffer is always allowed.
+
+@node Completion, Repetition, Minibuffer Edit, Minibuffer
+@section Completion
+@cindex completion
+
+ When appropriate, the minibuffer provides a @dfn{completion} facility.
+This means that you type enough of the argument to determine the rest,
+based on Emacs's knowledge of which arguments make sense, and Emacs visibly
+fills in the rest, or as much as can be determined from the part you have
+typed.
+
+ When completion is available, certain keys---@key{TAB}, @key{RET}, and @key{SPC}---are
+redefined to complete an abbreviation present in the minibuffer into a
+longer string that it stands for, by matching it against a set of
+@dfn{completion alternatives} provided by the command reading the argument.
+@kbd{?} is defined to display a list of possible completions of what you
+have inserted.
+
+ For example, when the minibuffer is being used by @kbd{Meta-x} to read
+the name of a command, it is given a list of all available Emacs command
+names to complete against. The completion keys match the text in the
+minibuffer against all the command names, find any additional characters of
+the name that are implied by the ones already present in the minibuffer,
+and add those characters to the ones you have given.
+
+ Case is normally significant in completion, because it is significant in
+most of the names that you can complete (buffer names, file names and
+command names). Thus, @samp{fo} will not complete to @samp{Foo}. When you
+are completing a name in which case does not matter, case may be ignored
+for completion's sake if the program said to do so.
+
+@subsection Completion Example
+
+@kindex TAB
+@findex minibuffer-complete
+ A concrete example may help here. If you type @kbd{Meta-x au @key{TAB}},
+the @key{TAB} looks for alternatives (in this case, command names) that
+start with @samp{au}. There are only two: @code{auto-fill-mode} and
+@code{auto-save-mode}. These are the same as far as @code{auto-}, so the
+@samp{au} in the minibuffer changes to @samp{auto-}.@refill
+
+ If you type @key{TAB} again immediately, there are multiple possibilities
+for the very next character---it could be @samp{s} or @samp{f}---so no more
+characters are added; but a list of all possible completions is displayed
+in another window.
+
+ If you go on to type @kbd{f @key{TAB}}, this @key{TAB} sees
+@samp{auto-f}. The only command name starting this way is
+@code{auto-fill-mode}, so completion inserts the rest of that. You
+now have @samp{auto-fill-mode} in the minibuffer after typing just @kbd{au
+@key{TAB} f @key{TAB}}. Note that @key{TAB} has this effect because in the
+minibuffer it is bound to the function @code{minibuffer-complete} when
+completion is supposed to be done.@refill
+
+@subsection Completion Commands
+
+ Here is a list of all the completion commands, defined in the minibuffer
+when completion is available.
+
+@table @kbd
+@item @key{TAB}
+@c !!! added @* to prevent overfull hbox
+Complete the text in the minibuffer as much as possible@*
+(@code{minibuffer-complete}).
+@item @key{SPC}
+Complete the text in the minibuffer but don't add or fill out more
+than one word (@code{minibuffer-complete-word}).
+@item @key{RET}
+Submit the text in the minibuffer as the argument, possibly completing
+first as described below (@code{minibuffer-complete-and-exit}).
+@item ?
+Print a list of all possible completions of the text in the minibuffer
+(@code{minibuffer-list-completions}).
+@end table
+
+@kindex SPC
+@findex minibuffer-complete-word
+ @key{SPC} completes much like @key{TAB}, but never goes beyond the
+next hyphen or space. If you have @samp{auto-f} in the minibuffer and type
+@key{SPC}, it finds that the completion is @samp{auto-fill-mode}, but it
+stops completing after @samp{fill-}. This gives @samp{auto-fill-}.
+Another @key{SPC} at this point completes all the way to
+@samp{auto-fill-mode}. @key{SPC} in the minibuffer runs the function
+@code{minibuffer-complete-word} when completion is available.@refill
+
+ There are three different ways that @key{RET} can work in completing
+minibuffers, depending on how the argument will be used.
+
+@itemize @bullet
+@item
+@dfn{Strict} completion is used when it is meaningless to give any
+argument except one of the known alternatives. For example, when
+@kbd{C-x k} reads the name of a buffer to kill, it is meaningless to
+give anything but the name of an existing buffer. In strict
+completion, @key{RET} refuses to exit if the text in the minibuffer
+does not complete to an exact match.
+
+@item
+@dfn{Cautious} completion is similar to strict completion, except that
+@key{RET} exits only if the text was an exact match already, not
+needing completion. If the text is not an exact match, @key{RET} does
+not exit, but it does complete the text. If it completes to an exact
+match, a second @key{RET} will exit.
+
+Cautious completion is used for reading file names for files that must
+already exist.
+
+@item
+@dfn{Permissive} completion is used when any string whatever is
+meaningful, and the list of completion alternatives is just a guide.
+For example, when @kbd{C-x C-f} reads the name of a file to visit, any
+file name is allowed, in case you want to create a file. In
+permissive completion, @key{RET} takes the text in the minibuffer
+exactly as given, without completing it.
+@end itemize
+
+ The completion commands display a list of all possible completions in a
+window whenever there is more than one possibility for the very next
+character. Also, typing @kbd{?} explicitly requests such a list. The
+list of completions counts as help text, so @kbd{C-M-v} typed in the
+minibuffer scrolls the list.
+
+@vindex completion-ignored-extensions
+ When completion is done on file names, certain file names are usually
+ignored. The variable @code{completion-ignored-extensions} contains a list
+of strings; a file whose name ends in any of those strings is ignored as a
+possible completion. The standard value of this variable has several
+elements including @code{".o"}, @code{".elc"}, @code{".dvi"} and @code{"~"}.
+The effect is that, for example, @samp{foo} can complete to @samp{foo.c}
+even though @samp{foo.o} exists as well. If the only possible completions
+are files that end in ``ignored'' strings, then they are not ignored.@refill
+
+@vindex completion-auto-help
+ Normally, a completion command that finds the next character is undetermined
+automatically displays a list of all possible completions. If the variable
+@code{completion-auto-help} is set to @code{nil}, this does not happen,
+and you must type @kbd{?} to display the possible completions.
+
+@node Repetition,, Completion, Minibuffer
+@section Repeating Minibuffer Commands
+@cindex command history
+@cindex history of commands
+
+ Every command that uses the minibuffer at least once is recorded on a
+special history list, together with the values of the minibuffer arguments,
+so that you can repeat the command easily. In particular, every
+use of @kbd{Meta-x} is recorded, since @kbd{M-x} uses the minibuffer to
+read the command name.
+
+@findex list-command-history
+@c widecommands
+@table @kbd
+@c !!! following generates acceptable underfull hbox
+@item C-x @key{ESC}
+Re-execute a recent minibuffer command @code{repeat-complex-command}).
+@item M-p
+@c !!! added @* to prevent overfull hbox
+Within @kbd{C-x @key{ESC}}, move to the previous recorded command@*
+(@code{previous-complex-command}).
+@item M-n
+Within @kbd{C-x @key{ESC}}, move to the next (more recent) recorded
+command (@code{next-complex-command}).
+@item M-x list-command-history
+Display the entire command history, showing all the commands
+@kbd{C-x @key{ESC}} can repeat, most recent first.
+@end table
+
+@kindex C-x ESC
+@findex repeat-complex-command
+ @kbd{C-x @key{ESC}} is used to re-execute a recent minibuffer-using
+command. With no argument, it repeats the last such command. A numeric
+argument specifies which command to repeat; 1 means the last one, and
+larger numbers specify earlier ones.
+
+ @kbd{C-x @key{ESC}} works by turning the previous command into a Lisp
+expression and then entering a minibuffer initialized with the text for
+that expression. If you type just @key{RET}, the command is repeated as
+before. You can also change the command by editing the Lisp expression.
+Whatever expression you finally submit is what will be executed. The
+repeated command is added to the front of the command history unless it is
+identical to the most recently executed command already there.
+
+ Even if you don't understand Lisp syntax, it will probably be obvious
+which command is displayed for repetition. If you do not change the text,
+you can be sure it will repeat exactly as before.
+
+@kindex M-n
+@kindex M-p
+@findex next-complex-command
+@findex previous-complex-command
+ Once inside the minibuffer for @kbd{C-x @key{ESC}}, if the command shown
+to you is not the one you want to repeat, you can move around the list of
+previous commands using @kbd{M-n} and @kbd{M-p}. @kbd{M-p} replaces the
+contents of the minibuffer with the next earlier recorded command, and
+@kbd{M-n} replaces them with the next later command. After finding the
+desired previous command, you can edit its expression as usual and then
+resubmit it by typing @key{RET} as usual. Any editing you have done on the
+command to be repeated is lost if you use @kbd{M-n} or @kbd{M-p}.
+
+ @kbd{M-p} is more useful than @kbd{M-n}, since more often you will
+initially request to repeat the most recent command and then decide to
+repeat an older one instead. These keys are specially defined within
+@kbd{C-x @key{ESC}} to run the commands @code{previous-complex-command} and
+@code{next-complex-command}.
+
+@vindex command-history
+ The list of previous minibuffer-using commands is stored as a Lisp list
+in the variable @code{command-history}. Each element is a Lisp expression
+which describes one command and its arguments. Lisp programs can reexecute
+a command by feeding the corresponding @code{command-history} element to
+@code{eval}.
+
+@node M-x, Help, Minibuffer, Top
+@chapter Running Commands by Name
+
+ The Emacs commands that are used often or that must be quick to type are
+bound to keys---short sequences of characters---for convenient use. Other
+Emacs commands that do not need to be brief are not bound to keys; to run
+them, you must refer to them by name.
+
+ A command name is, by convention, made up of one or more words, separated
+by hyphens; for example, @code{auto-fill-mode} or @code{manual-entry}. The
+use of English words makes the command name easier to remember than a key
+made up of obscure characters, even though it is more characters to type.
+Any command can be run by name, even if it is also runnable by keys.
+
+@kindex M-x
+@cindex minibuffer
+ The way to run a command by name is to start with @kbd{M-x}, type the
+command name, and finish it with @key{RET}. @kbd{M-x} uses the minibuffer
+to read the command name. @key{RET} exits the minibuffer and runs the
+command.
+
+ Emacs uses the minibuffer for reading input for many different purposes;
+on this occasion, the string @samp{M-x} is displayed at the beginning of
+the minibuffer as a @dfn{prompt} to remind you that your input should be
+the name of a command to be run. @xref{Minibuffer}, for full information
+on the features of the minibuffer.
+
+ You can use completion to enter the command name. For example, the
+command @code{forward-char} can be invoked by name by typing
+
+@example
+M-x forward-char @key{RET}
+
+@exdent or
+
+M-x fo @key{TAB} c @key{RET}
+@end example
+
+@noindent
+Note that @code{forward-char} is the same command that you invoke with
+the key @kbd{C-f}. Any command (interactively callable function) defined
+in Emacs can be called by its name using @kbd{M-x} whether or not any
+keys are bound to it.
+
+ If you type @kbd{C-g} while the command name is being read, you cancel
+the @kbd{M-x} command and get out of the minibuffer, ending up at top level.
+
+ To pass a numeric argument to the command you are invoking with
+@kbd{M-x}, specify the numeric argument before the @kbd{M-x}. @kbd{M-x}
+passes the argument along to the function which it calls. The argument
+value appears in the prompt while the command name is being read.
+
+ Normally, when describing a command that is run by name, we omit the
+@key{RET} that is needed to terminate the name. Thus we might speak of
+@kbd{M-x auto-fill-mode} rather than @kbd{M-x auto-fill-mode @key{RET}}.
+We mention the @key{RET} only when there is a need to emphasize its
+presence, such as when describing a sequence of input that contains a
+command name and arguments that follow it.
+
+@findex execute-extended-command
+ @kbd{M-x} is defined to run the command @code{execute-extended-command},
+which is responsible for reading the name of another command and invoking
+it.
+
+@node Help, Mark, M-x, Top
+@chapter Help
+@kindex Help
+@cindex help
+@cindex self-documentation
+
+ Emacs provides extensive help features which revolve around a single
+character, @kbd{C-h}. @kbd{C-h} is a prefix key that is used only for
+documentation-printing commands. The characters that you can type after
+@kbd{C-h} are called @dfn{help options}. One help option is @kbd{C-h};
+that is how you ask for help about using @kbd{C-h}.
+
+ @kbd{C-h C-h} prints a list of the possible help options, and then asks
+you to go ahead and type the option. It prompts with a string
+
+@smallexample
+A B C F I K L M N S T V W C-c C-d C-n C-w. Type C-h again for more help:
+@end smallexample
+
+@noindent
+and you should type one of those characters.
+
+ Typing a third @kbd{C-h} displays a description of what the options mean;
+it still waits for you to type an option. To cancel, type @kbd{C-g}.
+
+ Here is a summary of the defined help commands.
+
+@table @kbd
+@item C-h a @var{string} @key{RET}
+@c !!! added @* to prevent overfull hbox
+Display a list of commands whose names contain @var{string}@*
+(@code{command-apropos}).
+@item C-h b
+Display a table of all key bindings in effect now; local bindings of
+the current major mode first, followed by all global bindings
+(@code{describe-bindings}).
+@item C-h c @var{key}
+Print the name of the command that @var{key} runs (@code{describe-key-briefly}).
+@kbd{c} is for `character'. For more extensive information on @var{key},
+use @kbd{C-h k}.
+@item C-h f @var{function} @key{RET}
+Display documentation on the Lisp function named @var{function}
+(@code{describe-function}). Note that commands are Lisp functions, so
+a command name may be used.
+@item C-h i
+Run Info, the program for browsing documentation files (@code{info}).
+The complete Emacs manual is available on-line in Info.
+@item C-h k @var{key}
+Display name and documentation of the command @var{key} runs (@code{describe-key}).
+@item C-h l
+Display a description of the last 100 characters you typed
+(@code{view-lossage}).
+@item C-h m
+Display documentation of the current major mode (@code{describe-mode}).
+@item C-h n
+Display documentation of Emacs changes, most recent first
+(@code{view-emacs-news}).
+@item C-h s
+Display current contents of the syntax table, plus an explanation of
+what they mean (@code{describe-syntax}).
+@item C-h t
+Display the Emacs tutorial (@code{help-with-tutorial}).
+@item C-h v @var{var} @key{RET}
+Display the documentation of the Lisp variable @var{var}
+(@code{describe-variable}).
+@item C-h w @var{command} @key{RET}
+Print which keys run the command named @var{command} (@code{where-is}).
+@end table
+
+@section Documentation for a Key
+
+@kindex C-h c
+@findex describe-key-briefly
+ The most basic @kbd{C-h} options are @kbd{C-h c}
+(@code{describe-key-briefly}) and @w{@kbd{C-h k}} (@code{describe-key}).
+@kbd{C-h c @var{key}} prints in the echo area the name of the command that
+@var{key} is bound to. For example, @kbd{C-h c C-f} prints
+@samp{forward-char}. Since command names are chosen to describe what the
+command does, this is a good way to get a very brief description of what
+@var{key} does.@refill
+
+@kindex C-h k
+@findex describe-key
+ @kbd{C-h k @var{key}} is similar but gives more information. It displays
+the documentation string of the command @var{key} is bound to as well as
+its name. This is too big for the echo area, so a window is used for the
+display.
+
+@section Help by Command or Variable Name
+
+@kindex C-h f
+@findex describe-function
+ @kbd{C-h f} (@code{describe-function}) reads the name of a Lisp function
+using the minibuffer, then displays that function's documentation string
+in a window. Since commands are Lisp functions, you can use this to get
+the documentation of a command that is known by name. For example,
+
+@example
+C-h f auto-fill-mode @key{RET}
+@end example
+
+@noindent
+displays the documentation of @code{auto-fill-mode}. This is the only
+way to see the documentation of a command that is not bound to any key
+(one which you would normally call using @kbd{M-x}).
+
+ @kbd{C-h f} is also useful for Lisp functions that you are planning to
+use in a Lisp program. For example, if you have just written the code
+@code{(make-vector len)} and want to be sure that you are using
+@code{make-vector} properly, type
+@w{@kbd{C-h f make-vector @key{RET}}}. Because @kbd{C-h f} allows
+all function names, not just command names, you may find that some of
+your favorite abbreviations that work in @kbd{M-x} don't work in
+@kbd{C-h f}. An abbreviation may be unique among command names yet
+fail to be unique when other function names are allowed.
+
+ The function name for @kbd{C-h f} to describe has a default which is
+used if you type @key{RET} leaving the minibuffer empty. The default is
+the function called by the innermost Lisp expression in the buffer around
+point, @i{provided} that is a valid, defined Lisp function name. For
+example, if point is located following the text @samp{(make-vector (car
+x)}, the innermost list containing point is the one that starts with
+@samp{(make-vector}, so the default is to describe the function
+@code{make-vector}.
+
+ @kbd{C-h f} is often useful just to verify that you have the right
+spelling for the function name. If @kbd{C-h f} mentions a default in the
+prompt, you have typed the name of a defined Lisp function. If that tells
+you what you want to know, just type @kbd{C-g} to cancel the @kbd{C-h f}
+command and go on editing.
+
+@kindex C-h w
+@findex where-is
+ @kbd{C-h w @var{command} @key{RET}} tells you what keys are bound to
+@var{command}. It prints a list of the keys in the echo area.
+Alternatively, it says that the command is not on any keys, which implies
+that you must use @kbd{M-x} to call it.@refill
+
+@kindex C-h v
+@findex describe-variable
+ @kbd{C-h v} (@code{describe-variable}) is like @kbd{C-h f} but describes
+Lisp variables instead of Lisp functions. Its default is the Lisp symbol
+around or before point, but only if that is the name of a known Lisp
+variable. @xref{Variables}.@refill
+
+@section Apropos
+
+@kindex C-h a
+@findex command-apropos
+@cindex apropos
+ A more sophisticated sort of question to ask is, ``What are the commands
+for working with files?'' For this, type @kbd{C-h a file @key{RET}}, which
+displays a list of all command names that contain @samp{file}, such as
+@code{copy-file}, @code{find-file}, and so on. With each command name
+appears a brief description of how to use the command, and what keys you
+can currently invoke it with. For example, it would say that you can
+invoke @code{find-file} by typing @kbd{C-x C-f}. The @kbd{a} in @kbd{C-h
+a} stands for `Apropos'; @kbd{C-h a} runs the Lisp function
+@code{command-apropos}.@refill
+
+ Because @kbd{C-h a} looks only for functions whose names contain the
+string which you specify, you must use ingenuity in choosing the string.
+If you are looking for commands for killing backwards and @kbd{C-h a
+kill-backwards @key{RET}} doesn't reveal any, don't give up. Try just
+@kbd{kill}, or just @kbd{backwards}, or just @kbd{back}. Be persistent.
+Pretend you are playing Adventure. Also note that you can use a
+regular expression as the argument (@pxref{Regexps}).
+
+ Here is a set of arguments to give to @kbd{C-h a} that covers many
+classes of Emacs commands, since there are strong conventions for naming
+the standard Emacs commands. By giving you a feel for the naming
+conventions, this set should also serve to aid you in developing a
+technique for picking @code{apropos} strings.
+
+@quotation
+char, line, word, sentence, paragraph, region, page, sexp, list, defun,
+buffer, screen, window, file, dir, register, mode,
+beginning, end, forward, backward, next, previous, up, down, search, goto,
+kill, delete, mark, insert, yank, fill, indent, case,
+change, set, what, list, find, view, describe.
+@end quotation
+
+@findex apropos
+ To list all Lisp symbols that contain a match for a regexp, not just
+the ones that are defined as commands, use the command @kbd{M-x apropos}
+instead of @kbd{C-h a}.
+
+@section Other Help Commands
+
+@kindex C-h i
+@findex info
+ @kbd{C-h i} (@code{info}) runs the Info program, which is used for
+browsing through structured documentation files. The entire Emacs manual
+is available within Info. Eventually all the documentation of the GNU
+system will be available. Type @kbd{h} after entering Info to run
+a tutorial on using Info.
+
+@kindex C-h l
+@findex view-lossage
+ If something surprising happens, and you are not sure what commands you
+typed, use @kbd{C-h l} (@code{view-lossage}). @kbd{C-h l} prints the last
+100 command characters you typed in. If you see commands that you don't
+know, you can use @kbd{C-h c} to find out what they do.
+
+@kindex C-h m
+@findex describe-mode
+ Emacs has several major modes, each of which redefines a few keys and
+makes a few other changes in how editing works. @kbd{C-h m} (@code{describe-mode})
+prints documentation on the current major mode, which normally describes
+all the commands that are changed in this mode.
+
+@kindex C-h b
+@findex describe-bindings
+ @kbd{C-h b} (@code{describe-bindings}) and @kbd{C-h s}
+(@code{describe-syntax}) present other information about the current
+Emacs mode. @kbd{C-h b} displays a list of all the key bindings now
+in effect; the local bindings of the current major mode first,
+followed by the global bindings (@pxref{Key Bindings}). @kbd{C-h s}
+displays the contents of the syntax table, with explanations of each
+character's syntax (@pxref{Syntax}).@refill
+
+@kindex C-h n
+@findex view-emacs-news
+@kindex C-h t
+@findex help-with-tutorial
+@kindex C-h C-c
+@findex describe-copying
+@kindex C-h C-d
+@findex describe-distribution
+@kindex C-h C-w
+@findex describe-no-warranty
+ The other @kbd{C-h} options display various files of useful
+information. @w{@kbd{C-h C-w}} displays the full details on the complete
+absence of warranty for GNU Emacs. @kbd{C-h n} (@code{view-emacs-news})
+displays the file @file{emacs/etc/NEWS}, which contains documentation on
+Emacs changes arranged chronologically. @kbd{C-h t}
+(@code{help-with-tutorial}) displays the learn-by-doing Emacs tutorial.
+@kbd{C-h C-c} (@code{describe-copying}) displays the file
+@file{emacs/etc/COPYING}, which tells you the conditions you must obey
+in distributing copies of Emacs. @kbd{C-h C-d}
+(@code{describe-distribution}) displays another file named
+@file{emacs/etc/DISTRIB}, which tells you how you can order a copy of
+the latest version of Emacs.
+
+@node Mark, Killing, Help, Top
+@chapter The Mark and the Region
+@cindex mark
+@cindex region
+
+ There are many Emacs commands which operate on an arbitrary contiguous
+part of the current buffer. To specify the text for such a command to
+operate on, you set the @dfn{mark} at one end of it, and move point to the
+other end. The text between point and the mark is called the @dfn{region}.
+You can move point or the mark to adjust the boundaries of the region. It
+doesn't matter which one is set first chronologically, or which one comes
+earlier in the text.
+
+ Once the mark has been set, it remains until it is set again at another
+place. The mark remains fixed with respect to the preceding character if
+text is inserted or deleted in the buffer. Each Emacs buffer has its own
+mark, so that when you return to a buffer that had been selected
+previously, it has the same mark it had before.
+
+ Many commands that insert text, such as @kbd{C-y} (@code{yank}) and
+@kbd{M-x insert-buffer}, position the mark at one end of the inserted
+text---the opposite end from where point is positioned, so that the region
+contains the text just inserted.
+
+ Aside from delimiting the region, the mark is also useful for remembering
+a spot that you may want to go back to. To make this feature more useful,
+Emacs remembers 16 previous locations of the mark, in the @code{mark ring}.
+
+@menu
+* Setting Mark:: Commands to set the mark.
+* Using Region:: Summary of ways to operate on contents of the region.
+* Marking Objects:: Commands to put region around textual units.
+* Mark Ring:: Previous mark positions saved so you can go back there.
+@end menu
+
+@node Setting Mark, Using Region, Mark, Mark
+@section Setting the Mark
+
+ Here are some commands for setting the mark:
+
+@c WideCommands
+@table @kbd
+@item C-@key{SPC}
+Set the mark where point is (@code{set-mark-command}).
+@item C-@@
+The same.
+@item C-x C-x
+Interchange mark and point (@code{exchange-point-and-mark}).
+@end table
+
+ For example, if you wish to convert part of the buffer to all upper-case,
+you can use the @kbd{C-x C-u} (@code{upcase-region}) command, which operates
+on the text in the region. You can first go to the beginning of the text
+to be capitalized, type @kbd{C-@key{SPC}} to put the mark there, move to
+the end, and then type @kbd{C-x C-u}. Or, you can set the mark at the end
+of the text, move to the beginning, and then type @kbd{C-x C-u}. Most
+commands that operate on the text in the region have the word @code{region}
+in their names.
+
+@kindex C-SPC
+@findex set-mark-command
+ The most common way to set the mark is with the @kbd{C-@key{SPC}} command
+(@code{set-mark-command}). This sets the mark where point is. Then you
+can move point away, leaving the mark behind. It is actually incorrect to
+speak of the character @kbd{C-@key{SPC}}; there is no such character. When
+you type @key{SPC} while holding down @key{CTRL}, what you get on most
+terminals is the character @kbd{C-@@}. This is the key actually bound to
+@code{set-mark-command}. But unless you are unlucky enough to have a
+terminal where typing @kbd{C-@key{SPC}} does not produce @kbd{C-@@}, you
+might as well think of this character as @kbd{C-@key{SPC}}.
+
+@kindex C-x C-x
+@findex exchange-point-and-mark
+ Since terminals have only one cursor, there is no way for Emacs to show
+you where the mark is located. You have to remember. The usual solution
+to this problem is to set the mark and then use it soon, before you forget
+where it is. But you can see where the mark is with the command @w{@kbd{C-x
+C-x}} (@code{exchange-point-and-mark}) which puts the mark where point was and
+point where the mark was. The extent of the region is unchanged, but the
+cursor and point are now at the previous location of the mark.
+
+ @kbd{C-x C-x} is also useful when you are satisfied with the location of
+point but want to move the mark; do @kbd{C-x C-x} to put point there and
+then you can move it. A second use of @kbd{C-x C-x}, if necessary, puts
+the mark at the new location with point back at its original location.
+
+@node Using Region, Marking Objects, Setting Mark, Mark
+@section Operating on the Region
+
+ Once you have created an active region, you can do many things to
+the text in it:
+@itemize @bullet
+@item
+Kill it with @kbd{C-w} (@pxref{Killing}).
+@item
+Save it in a register with @kbd{C-x x} (@pxref{Registers}).
+@item
+Save it in a buffer or a file (@pxref{Accumulating Text}).
+@item
+@c !!! added @* to prevent overfull hbox
+Convert case with @kbd{C-x C-l} or @kbd{C-x C-u}@*
+(@pxref{Case}).
+@item
+Evaluate it as Lisp code with @kbd{M-x eval-region} (@pxref{Lisp Eval}).
+@item
+Fill it as text with @kbd{M-g} (@pxref{Filling}).
+@item
+Print hardcopy with @kbd{M-x print-region} (@pxref{Hardcopy}).
+@item
+@c !!! added @* to prevent overfull hbox
+Indent it with @kbd{C-x @key{TAB}} or @kbd{C-M-\}@*
+(@pxref{Indentation}).
+@end itemize
+
+@node Marking Objects, Mark Ring, Using Region, Mark
+@section Commands to Mark Textual Objects
+
+ There are commands for placing point and the mark around a textual
+object such as a word, list, paragraph or page.
+
+@table @kbd
+@item M-@@
+Set mark after end of next word (@code{mark-word}). This command and
+the following one do not move point.
+@item C-M-@@
+Set mark after end of next Lisp expression (@code{mark-sexp}).
+@item M-h
+Put region around current paragraph (@code{mark-paragraph}).
+@item C-M-h
+Put region around current Lisp defun (@code{mark-defun}).
+@item C-x h
+Put region around entire buffer (@code{mark-whole-buffer}).
+@item C-x C-p
+Put region around current page (@code{mark-page}).
+@end table
+
+@kindex M-@@
+@kindex C-M-@@
+@findex mark-word
+@findex mark-sexp
+@kbd{M-@@} (@code{mark-word}) puts the mark at the end of the next word,
+while @kbd{C-M-@@} (@code{mark-sexp}) puts it at the end of the next Lisp
+expression. These characters allow you to save a little typing or
+redisplay, sometimes.
+
+@kindex M-h
+@kindex C-M-h
+@kindex C-x C-p
+@kindex C-x h
+@findex mark-paragraph
+@findex mark-defun
+@findex mark-page
+@findex mark-whole-buffer
+ Other commands set both point and mark, to delimit an object in the
+buffer. @kbd{M-h} (@code{mark-paragraph}) moves point to the beginning of
+the paragraph that surrounds or follows point, and puts the mark at the end
+of that paragraph (@pxref{Paragraphs}). @kbd{M-h} does all that's
+necessary if you wish to indent, case-convert, or kill a whole paragraph.
+@kbd{C-M-h} (@code{mark-defun}) similarly puts point before and the mark
+after the current or following defun (@pxref{Defuns}). @kbd{C-x C-p}
+(@code{mark-page}) puts point before the current page (or the next or
+previous, according to the argument), and mark at the end (@pxref{Pages}).
+The mark goes after the terminating page delimiter (to include it), while
+point goes after the preceding page delimiter (to exclude it). Finally,
+@w{@kbd{C-x h}} (@code{mark-whole-buffer}) sets up the entire buffer as the
+region, by putting point at the beginning and the mark at the end.
+
+@node Mark Ring,, Marking Objects, Mark
+@section The Mark Ring
+
+@kindex C-u C-SPC
+@cindex mark ring
+@kindex C-u C-@@
+ Aside from delimiting the region, the mark is also useful for remembering
+a spot that you may want to go back to. To make this feature more useful,
+Emacs remembers 16 previous locations of the mark, in the @dfn{mark ring}.
+Most commands that set the mark push the old mark onto this ring. To
+return to a marked location, use @kbd{C-u C-@key{SPC}} (or @kbd{C-u C-@@}); this is
+the command @code{set-mark-command} given a numeric argument. It moves
+point to where the mark was, and restores the mark from the ring of former
+marks. So repeated use of this command moves point to all of the old marks
+on the ring, one by one. The marks you see go to the end of the ring,
+so no marks are lost.
+
+ Each buffer has its own mark ring. All editing commands use the current
+buffer's mark ring. In particular, @kbd{C-u C-@key{SPC}} always stays in
+the same buffer.
+
+ Many commands that can move long distances, such as @kbd{M-<}
+(@code{beginning-of-buffer}), start by setting the mark and saving the old
+mark on the mark ring. This is to make it easier for you to move back
+later. Searches do this except when they do not actually move point. You
+can tell when a command sets the mark because @samp{Mark Set} is printed in
+the echo area.
+
+ Another way of remembering positions so you can go back to them is with
+registers (@pxref{RegPos}).
+
+@vindex mark-ring-max
+ The variable @code{mark-ring-max} is the maximum number of entries to
+keep in the mark ring. If that many entries exist and another one is
+pushed, the last one in the list is discarded. Repeating @kbd{C-u
+C-@key{SPC}} circulates through the limited number of entries that are
+currently in the ring.
+
+@vindex mark-ring
+ The variable @code{mark-ring} holds the mark ring itself, as a list of
+marker objects in the order most recent first. This variable is local
+in every buffer.
+
+@iftex
+@chapter Killing and Moving Text
+
+ @dfn{Killing} means erasing text and copying it into the @dfn{kill ring},
+from which it can be retrieved by @dfn{yanking} it. Some other systems
+that have recently become popular use the terms ``cutting'' and ``pasting''
+for these operations.
+
+ The commonest way of moving or copying text with Emacs is to kill it and
+later yank it in one or more places. This is very safe because all the
+text killed recently is remembered, and it is versatile, because the many
+commands for killing syntactic units can also be used for moving those
+units. There are also other ways of copying text for special purposes.
+
+ Emacs has only one kill ring, so you can kill text in one buffer and yank
+it in another buffer.
+
+@end iftex
+
+@node Killing, Yanking, Mark, Top
+@section Deletion and Killing
+@findex delete-char
+@c ??? Should be backward-delete-char
+@findex delete-backward-char
+
+@cindex killing
+@cindex cutting
+@cindex clipping text
+@cindex deletion
+@kindex C-d
+@kindex DEL
+ Most commands which erase text from the buffer save it so that you can
+get it back if you change your mind, or move or copy it to other parts of
+the buffer. These commands are known as @dfn{kill} commands. The rest of
+the commands that erase text do not save it; they are known as @dfn{delete}
+commands. (This distinction is made only for erasure of text in the
+buffer.)
+
+@c !!! following generates acceptable underfull hbox
+ The delete commands include @kbd{C-d} (@code{delete-char}) and
+@key{DEL} (@code{delete-backward-char}), which delete only one character at
+a time, and those commands that delete only spaces or newlines. Commands
+that can destroy significant amounts of nontrivial data generally kill.
+The commands' names and individual descriptions use the words @samp{kill}
+and @samp{delete} to say which they do. If you do a kill or delete command
+by mistake, you can use the @w{@kbd{C-x u}} (@code{undo}) command to undo it
+(@pxref{Undo}).
+
+@subsection Deletion
+
+@table @kbd
+@item C-d
+Delete next character (@code{delete-char}).
+@item @key{DEL}
+Delete previous character (@code{delete-backward-char}).
+@item M-\
+Delete spaces and tabs around point (@code{delete-horizontal-space}).
+@item M-@key{SPC}
+Delete spaces and tabs around point, leaving one space
+(@code{just-one-space}).
+@item C-x C-o
+Delete blank lines around the current line (@code{delete-blank-lines}).
+@item M-^
+Join two lines by deleting the intervening newline, and any indentation
+following it (@code{delete-indentation}).
+@end table
+
+ The most basic delete commands are @kbd{C-d} (@code{delete-char}) and
+@key{DEL} (@code{delete-backward-char}). @kbd{C-d} deletes the character
+after point, the one the cursor is ``on top of''. Point doesn't move.
+@key{DEL} deletes the character before the cursor, and moves point back.
+Newlines can be deleted like any other characters in the buffer; deleting a
+newline joins two lines. Actually, @kbd{C-d} and @key{DEL} aren't always
+delete commands; if given an argument, they kill instead, since they can
+erase more than one character this way.
+
+@kindex M-\
+@findex delete-horizontal-space
+@kindex M-SPC
+@findex just-one-space
+@kindex C-x C-o
+@findex delete-blank-lines
+@kindex M-^
+@findex delete-indentation
+ The other delete commands are those which delete only formatting
+characters: spaces, tabs and newlines. @kbd{M-\} (@code{delete-horizontal-space})
+deletes all the spaces and tab characters before and after point.
+@kbd{M-@key{SPC}} (@code{just-one-space}) does likewise but leaves a single
+space after point, regardless of the number of spaces that existed
+previously (even zero).
+
+ @kbd{C-x C-o} (@code{delete-blank-lines}) deletes all blank lines after
+the current line, and if the current line is blank deletes all blank lines
+preceding the current line as well (leaving one blank line, the current
+line). @kbd{M-^} (@code{delete-indentation}) joins the current line and
+the previous line, or the current line and the next line if given an
+argument, by deleting a newline and all surrounding spaces, possibly
+leaving a single space. @xref{Indentation,M-^}.
+
+@subsection Killing by Lines
+
+@table @kbd
+@item C-k
+Kill rest of line or one or more lines (@code{kill-line}).
+@end table
+
+@kindex C-k
+@findex kill-line
+ The simplest kill command is @kbd{C-k}. If given at the beginning of a
+line, it kills all the text on the line, leaving it blank. If given on a
+blank line, the blank line disappears. As a consequence, if you go to the
+front of a non-blank line and type @kbd{C-k} twice, the line disappears
+completely.
+
+ More generally, @kbd{C-k} kills from point up to the end of the line,
+unless it is at the end of a line. In that case it kills the newline
+following the line, thus merging the next line into the current one.
+Invisible spaces and tabs at the end of the line are ignored when deciding
+which case applies, so if point appears to be at the end of the line, you
+can be sure the newline will be killed.
+
+ If @kbd{C-k} is given a positive argument, it kills that many lines and
+the newlines that follow them (however, text on the current line before
+point is spared). With a negative argument, it kills back to a number of
+line beginnings. An argument of @minus{}2 means kill back to the second line
+beginning. If point is at the beginning of a line, that line beginning
+doesn't count, so @w{@kbd{C-u - 2 C-k}} with point at the front of a line kills
+the two previous lines.
+
+ @kbd{C-k} with an argument of zero kills all the text before point on the
+current line.
+
+@subsection Other Kill Commands
+@findex kill-line
+@findex kill-region
+@findex kill-word
+@findex backward-kill-word
+@findex kill-sexp
+@findex kill-sentence
+@findex backward-kill-sentence
+@kindex M-d
+@kindex M-DEL
+@kindex C-M-k
+@kindex C-x DEL
+@kindex M-k
+@kindex C-k
+@kindex C-w
+
+@c DoubleWideCommands
+@table @kbd
+@item C-w
+Kill region (from point to the mark) (@code{kill-region}).
+@xref{Words}.
+@item M-d
+Kill word (@code{kill-word}).
+@item M-@key{DEL}
+Kill word backwards (@code{backward-kill-word}).
+@item C-x @key{DEL}
+Kill back to beginning of sentence (@code{backward-kill-sentence}).
+@xref{Sentences}.
+@item M-k
+Kill to end of sentence (@code{kill-sentence}).
+@item C-M-k
+Kill sexp (@code{kill-sexp}). @xref{Lists}.
+@item M-z @var{char}
+Kill up to next occurrence of @var{char} (@code{zap-to-char}).
+@end table
+
+ A kill command which is very general is @kbd{C-w} (@code{kill-region}),
+which kills everything between point and the mark. With this command, you
+can kill any contiguous sequence of characters, if you first set the mark
+at one end of them and go to the other end.
+
+@kindex M-z
+@findex zap-to-char
+ A convenient way of killing is combined with searching: @kbd{M-z}
+(@code{zap-to-char}) reads a character and kills from point up to (but not
+including) the next occurrence of that character in the buffer. If there
+is no next occurrence, killing goes to the end of the buffer. A numeric
+argument acts as a repeat count. A negative argument means to search
+backward and kill text before point.
+
+ Other syntactic units can be killed: words, with @kbd{M-@key{DEL}} and
+@kbd{M-d} (@pxref{Words}); sexps, with @kbd{C-M-k} (@pxref{Lists}); and
+sentences, with @kbd{C-x @key{DEL}} and @kbd{M-k}
+(@pxref{Sentences}).@refill
+
+@node Yanking, Accumulating Text, Killing, Top
+@section Yanking
+@cindex moving text
+@cindex copying text
+@cindex kill ring
+@cindex yanking
+@cindex pasting
+
+ @dfn{Yanking} is getting back text which was killed. This is what some
+systems call ``pasting''. The usual way to move or copy text is to kill it
+and then yank it one or more times.
+
+@table @kbd
+@item C-y
+Yank last killed text (@code{yank}).
+@item M-y
+Replace re-inserted killed text with the previously killed text
+(@code{yank-pop}).
+@item M-w
+Save region as last killed text without actually killing it
+(@code{copy-region-as-kill}).
+@item C-M-w
+Append next kill to last batch of killed text (@code{append-next-kill}).
+@end table
+
+@menu
+* Kill Ring:: Where killed text is stored. Basic yanking.
+* Appending Kills:: Several kills in a row all yank together.
+* Earlier Kills:: Yanking something killed some time ago.
+@end menu
+
+@node Kill Ring, Appending Kills, Yanking, Yanking
+@subsection The Kill Ring
+
+@kindex C-y
+@findex Yank
+ All killed text is recorded in the @dfn{kill ring}, a list of blocks of
+text that have been killed. There is only one kill ring, used in all
+buffers, so you can kill text in one buffer and yank it in another buffer.
+This is the usual way to move text from one file to another.
+(@xref{Accumulating Text}, for some other ways.)
+
+ The command @kbd{C-y} (@code{yank}) reinserts the text of the most recent
+kill. It leaves the cursor at the end of the text. It sets the mark at
+the beginning of the text. @xref{Mark}.
+
+ @kbd{C-u C-y} leaves the cursor in front of the text, and sets the mark
+after it. This is only if the argument is specified with just a @kbd{C-u},
+precisely. Any other sort of argument, including @kbd{C-u} and digits, has
+an effect described below (under ``Yanking Earlier Kills'').
+
+@kindex M-w
+@findex copy-region-as-kill
+ If you wish to copy a block of text, you might want to use @kbd{M-w}
+(@code{copy-region-as-kill}), which copies the region into the kill ring
+without removing it from the buffer. This is approximately equivalent to
+@kbd{C-w} followed by @kbd{C-y}, except that @kbd{M-w} does not mark the
+buffer as ``modified'' and does not temporarily change the screen.
+
+@node Appending Kills, Earlier Kills, Kill Ring, Yanking
+@subsection Appending Kills
+
+@cindex television
+ Normally, each kill command pushes a new block onto the kill ring.
+However, two or more kill commands in a row combine their text into a
+single entry, so that a single @kbd{C-y} gets it all back as it was before
+it was killed. This means that you don't have to kill all the text in one
+command; you can keep killing line after line, or word after word, until
+you have killed it all, and you can still get it all back at once. (Thus
+we join television in leading people to kill thoughtlessly.)
+
+ Commands that kill forward from point add onto the end of the previous
+killed text. Commands that kill backward from point add onto the
+beginning. This way, any sequence of mixed forward and backward kill
+commands puts all the killed text into one entry without rearrangement.
+Numeric arguments do not break the sequence of appending kills. For
+example, suppose the buffer contains
+
+@example
+This is the first
+line of sample text
+and here is the third.
+@end example
+
+@noindent
+with point at the beginning of the second line. If you type @kbd{C-k C-u 2
+M-@key{DEL} C-k}, the first @kbd{C-k} kills the text @samp{line of sample
+text}, @kbd{C-u 2 M-@key{DEL}} kills @samp{the first} with the newline that
+followed it, and the second @kbd{C-k} kills the newline after the second
+line. The result is that the buffer contains @samp{This is and here is the
+third.} and a single kill entry contains @samp{the first@key{RET}line of
+sample text@key{RET}}---all the killed text, in its original order.
+
+@kindex C-M-w
+@findex append-next-kill
+ If a kill command is separated from the last kill command by other
+commands (not just numeric arguments), it starts a new entry on the kill
+ring. But you can force it to append by first typing the command
+@kbd{C-M-w} (@code{append-next-kill}) in front of it. The @kbd{C-M-w}
+tells the following command, if it is a kill command, to append the text it
+kills to the last killed text, instead of starting a new entry. With
+@kbd{C-M-w}, you can kill several separated pieces of text and accumulate
+them to be yanked back in one place.@refill
+
+@node Earlier Kills,, Appending Kills, Yanking
+@subsection Yanking Earlier Kills
+
+@kindex M-y
+@findex yank-pop
+ To recover killed text that is no longer the most recent kill, you need
+the @kbd{Meta-y} (@code{yank-pop}) command. @kbd{M-y} can be used only
+after a @kbd{C-y} or another @kbd{M-y}. It takes the text previously
+yanked and replaces it with the text from an earlier kill. So, to recover
+the text of the next-to-the-last kill, you first use @kbd{C-y} to recover
+the last kill, and then use @kbd{M-y} to replace it with the previous
+kill.@refill
+
+ You can think in terms of a ``last yank'' pointer which points at an item
+in the kill ring. Each time you kill, the ``last yank'' pointer moves to
+the newly made item at the front of the ring. @kbd{C-y} yanks the item
+which the ``last yank'' pointer points to. @kbd{M-y} moves the ``last
+yank'' pointer to a different item, and the text in the buffer changes to
+match. Enough @kbd{M-y} commands can move the pointer to any item in the
+ring, so you can get any item into the buffer. Eventually the pointer
+reaches the end of the ring; the next @kbd{M-y} moves it to the first item
+again.
+
+ Yanking moves the ``last yank'' pointer around the ring, but it does not
+change the order of the entries in the ring, which always runs from the
+most recent kill at the front to the oldest one still remembered.
+
+ @kbd{M-y} can take a numeric argument, which tells it how many items to
+advance the ``last yank'' pointer by. A negative argument moves the
+pointer toward the front of the ring; from the front of the ring, it moves
+to the last entry and starts moving forward from there.
+
+ Once the text you are looking for is brought into the buffer, you can
+stop doing @kbd{M-y} commands and it will stay there. It's just a copy of
+the kill ring item, so editing it in the buffer does not change what's in
+the ring. As long as no new killing is done, the ``last yank'' pointer
+remains at the same place in the kill ring, so repeating @kbd{C-y} will
+yank another copy of the same old kill.
+
+ If you know how many @kbd{M-y} commands it would take to find the
+text you want, you can yank that text in one step using @kbd{C-y} with
+a numeric argument. @kbd{C-y} with an argument greater than one
+restores the text the specified number of entries back in the kill
+ring. Thus, @kbd{C-u 2 C-y} gets the next to the last block of killed
+text. It is equivalent to @kbd{C-y M-y}. @kbd{C-y} with a numeric
+argument starts counting from the ``last yank'' pointer, and sets the
+``last yank'' pointer to the entry that it yanks.
+
+@vindex kill-ring-max
+ The length of the kill ring is controlled by the variable
+@code{kill-ring-max}; no more than that many blocks of killed text are
+saved.
+
+@node Accumulating Text, Rectangles, Yanking, Top
+@section Accumulating Text
+@kindex C-x a
+@findex append-to-buffer
+@findex prepend-to-buffer
+@findex copy-to-buffer
+@findex append-to-file
+
+ Usually we copy or move text by killing it and yanking it, but there are
+other ways that are useful for copying one block of text in many places, or
+for copying many scattered blocks of text into one place.
+
+ You can accumulate blocks of text from scattered locations either into a
+buffer or into a file if you like. These commands are described here. You
+can also use Emacs registers for storing and accumulating text.
+@xref{Registers}.
+
+@table @kbd
+@item C-x a
+Append region to contents of specified buffer (@code{append-to-buffer}).
+@item M-x prepend-to-buffer
+Prepend region to contents of specified buffer.
+@item M-x copy-to-buffer
+Copy region into specified buffer, deleting that buffer's old contents.
+@item M-x insert-buffer
+Insert contents of specified buffer into current buffer at point.
+@item M-x append-to-file
+Append region to contents of specified file, at the end.
+@end table
+
+ To accumulate text into a buffer, use the command @kbd{C-x a @var{buffername}}
+(@code{append-to-buffer}), which inserts a copy of the region into the
+buffer @var{buffername}, at the location of point in that buffer. If there
+is no buffer with that name, one is created. If you append text into a
+buffer which has been used for editing, the copied text goes into the
+middle of the text of the buffer, wherever point happens to be in it.
+
+ Point in that buffer is left at the end of the copied text, so successive
+uses of @kbd{C-x a} accumulate the text in the specified buffer in the same
+order as they were copied. Strictly speaking, @kbd{C-x a} does not always
+append to the text already in the buffer; but if @kbd{C-x a} is the only
+command used to alter a buffer, it does always append to the existing text
+because point is always at the end.
+
+ @kbd{M-x prepend-to-buffer} is just like @kbd{C-x a} except that point in
+the other buffer is left before the copied text, so successive prependings
+add text in reverse order. @kbd{M-x copy-to-buffer} is similar except that
+any existing text in the other buffer is deleted, so the buffer is left
+containing just the text newly copied into it.
+
+ You can retrieve the accumulated text from that buffer with @kbd{M-x
+insert-buffer}; this too takes @var{buffername} as an argument. It inserts
+a copy of the text in buffer @var{buffername} into the selected buffer.
+You could alternatively select the other buffer for editing, perhaps moving
+text from it by killing or with @kbd{C-x a}. @xref{Buffers}, for
+background information on buffers.
+
+ Instead of accumulating text within Emacs, in a buffer, you can append
+text directly into a file with @kbd{M-x append-to-file}, which takes
+@var{file-name} as an argument. It adds the text of the region to the end
+of the specified file. The file is changed immediately on disk. This
+command is normally used with files that are @i{not} being visited in
+Emacs. Using it on a file that Emacs is visiting can produce confusing
+results, because the text inside Emacs for that file will not change
+while the file itself changes.
+
+@node Rectangles, Registers, Accumulating Text, Top
+@section Rectangles
+@cindex rectangles
+
+ The rectangle commands affect rectangular areas of the text: all the
+characters between a certain pair of columns, in a certain range of lines.
+Commands are provided to kill rectangles, yank killed rectangles, clear
+them out, or delete them. Rectangle commands are useful with text in
+multicolumnar formats, such as perhaps code with comments at the right,
+or for changing text into or out of such formats.
+
+ When you must specify a rectangle for a command to work on, you do
+it by putting the mark at one corner and point at the opposite corner.
+The rectangle thus specified is called the @dfn{region-rectangle}
+because it is controlled about the same way the region is controlled.
+But remember that a given combination of point and mark values can be
+interpreted either as specifying a region or as specifying a
+rectangle; it is up to the command that uses them to choose the
+interpretation.
+
+@table @kbd
+@item M-x delete-rectangle
+Delete the text of the region-rectangle, moving any following text on
+each line leftward to the left edge of the region-rectangle.
+@item M-x kill-rectangle
+Similar, but also save the contents of the region-rectangle as the
+``last killed rectangle''.
+@item M-x yank-rectangle
+Yank the last killed rectangle with its upper left corner at point.
+@item M-x open-rectangle
+Insert blank space to fill the space of the region-rectangle.
+The previous contents of the region-rectangle are pushed rightward.
+@item M-x clear-rectangle
+Clear the region-rectangle by replacing its contents with spaces.
+@end table
+
+ The rectangle operations fall into two classes: commands deleting and
+moving rectangles, and commands for blank rectangles.
+
+@findex delete-rectangle
+@findex kill-rectangle
+ There are two ways to get rid of the text in a rectangle: you can discard
+the text (delete it) or save it as the ``last killed'' rectangle. The
+commands for these two ways are @kbd{M-x delete-rectangle} and @kbd{M-x
+kill-rectangle}. In either case, the portion of each line that falls inside
+the rectangle's boundaries is deleted, causing following text (if any) on
+the line to move left.
+
+ Note that ``killing'' a rectangle is not killing in the usual sense; the
+rectangle is not stored in the kill ring, but in a special place that
+can only record the most recent rectangle killed. This is because yanking
+a rectangle is so different from yanking linear text that different yank
+commands have to be used and yank-popping is hard to make sense of.
+
+ Inserting a rectangle is the opposite of deleting one. All you need to
+specify is where to put the upper left corner; that is done by putting
+point there. The rectangle's first line is inserted there, the rectangle's
+second line is inserted at a point one line vertically down, and so on.
+The number of lines affected is determined by the height of the saved
+rectangle.
+
+@findex yank-rectangle
+ To insert the last killed rectangle, type @kbd{M-x yank-rectangle}.
+This can be used to convert single-column lists into double-column
+lists; kill the second half of the list as a rectangle and then
+yank it beside the first line of the list.
+
+@findex open-rectangle
+@findex clear-rectangle
+ There are two commands for working with blank rectangles: @kbd{M-x
+clear-rectangle} to blank out existing text, and @kbd{M-x open-rectangle}
+to insert a blank rectangle. Clearing a rectangle is equivalent to
+deleting it and then inserting as blank rectangle of the same size.
+
+ Rectangles can also be copied into and out of registers.
+@xref{RegRect,,Rectangle Registers}.
+
+@node Registers, Display, Rectangles, Top
+@chapter Registers
+@cindex registers
+
+ Emacs @dfn{registers} are places you can save text or positions for
+later use. Text saved in a register can be copied into the buffer
+once or many times; a position saved in a register is used by moving
+point to that position. Rectangles can also be copied into and out of
+registers (@pxref{Rectangles}).
+
+ Each register has a name, which is a single character. A register can
+store either a piece of text or a position or a rectangle, but only one
+thing at any given time. Whatever you store in a register remains
+there until you store something else in that register.
+
+@menu
+* RegPos:: Saving positions in registers.
+* RegText:: Saving text in registers.
+* RegRect:: Saving rectangles in registers.
+@end menu
+
+@table @kbd
+@item M-x view-register @key{RET} @var{r}
+Display a description of what register @var{r} contains.
+@end table
+
+@findex view-register
+ @kbd{M-x view-register} reads a register name as an argument and then
+displays the contents of the specified register.
+
+@node RegPos, RegText, Registers, Registers
+@section Saving Positions in Registers
+
+ Saving a position records a spot in a buffer so that you can move
+back there later. Moving to a saved position reselects the buffer
+and moves point to the spot.
+
+@table @kbd
+@item C-x / @var{r}
+Save location of point in register @var{r} (@code{point-to-register}).
+@item C-x j @var{r}
+Jump to the location saved in register @var{r} (@code{register-to-point}).
+@end table
+
+@kindex C-x /
+@findex point-to-register
+ To save the current location of point in a register, choose a name
+@var{r} and type @kbd{C-x / @var{r}}. The register @var{r} retains
+the location thus saved until you store something else in that
+register.@refill
+
+@kindex C-x j
+@findex register-to-point
+ The command @kbd{C-x j @var{r}} moves point to the location recorded
+in register @var{r}. The register is not affected; it continues to
+record the same location. You can jump to the same position using the
+same register any number of times.
+
+@node RegText, RegRect, RegPos, Registers
+@section Saving Text in Registers
+
+ When you want to insert a copy of the same piece of text frequently, it
+may be impractical to use the kill ring, since each subsequent kill moves
+the piece of text further down on the ring. It becomes hard to keep track
+of what argument is needed to retrieve the same text with @kbd{C-y}. An
+alternative is to store the text in a register with @kbd{C-x x}
+(@code{copy-to-register}) and then retrieve it with @kbd{C-x g}
+(@code{insert-register}).
+
+@table @kbd
+@item C-x x @var{r}
+Copy region into register @var{r} (@code{copy-to-register}).
+@item C-x g @var{r}
+Insert text contents of register @var{r} (@code{insert-register}).
+@end table
+
+@kindex C-x x
+@kindex C-x g
+@findex copy-to-register
+@findex insert-register
+ @kbd{C-x x @var{r}} stores a copy of the text of the region into the
+register named @var{r}. Given a numeric argument, @kbd{C-x x} deletes the
+text from the buffer as well.
+
+ @kbd{C-x g @var{r}} inserts in the buffer the text from register @var{r}.
+Normally it leaves point before the text and places the mark after, but
+with a numeric argument it puts point after the text and the mark before.
+
+@node RegRect,, RegText, Registers
+@section Saving Rectangles in Registers
+
+ A register can contain a rectangle instead of linear text. The rectangle
+is represented as a list of strings. @xref{Rectangles}, for basic
+information on rectangles and how rectangles in the buffer are specified.
+
+@table @kbd
+@c !!! following generates acceptable underfull hbox
+@item C-x r @var{r}
+Copy the region-rectangle into register @var{r} (@code{copy-region-to-rectangle}).
+With numeric argument, delete it as well.
+@item C-x g @var{r}
+Insert the rectangle stored in register @var{r} (if it contains a
+rectangle) (@code{insert-register}).
+@end table
+
+ The @kbd{C-x g} command inserts linear text if the register contains
+that, or inserts a rectangle if the register contains one.
+
+@node Display, Search, Registers, Top
+@chapter Controlling the Display
+
+ Since only part of a large buffer fits in the window, Emacs tries to show
+the part that is likely to be interesting. The display control commands
+allow you to specify which part of the text you want to see.
+
+@table @kbd
+@item C-l
+Clear screen and redisplay, scrolling the selected window to center
+point vertically within it (@code{recenter}).
+@item C-v
+Scroll forward (a windowful or a specified number of lines) (@code{scroll-up}).
+@item M-v
+Scroll backward (@code{scroll-down}).
+@item @var{arg} C-l
+Scroll so point is on line @var{arg} (@code{recenter}).
+@item C-x <
+Scroll text in current window to the left (@code{scroll-left}).
+@item C-x >
+Scroll to the right (@code{scroll-right}).
+@item C-x $
+Make deeply indented lines invisible (@code{set-selective-display}).
+@end table
+
+@menu
+* Scrolling:: Moving text up and down in a window.
+* Horizontal Scrolling:: Moving text left and right in a window.
+* Selective Display:: Hiding lines with lots of indentation.
+* Display Vars:: Information on variables for customizing display.
+@end menu
+
+@node Scrolling, Horizontal Scrolling, Display, Display
+@section Scrolling
+
+ If a buffer contains text that is too large to fit entirely within a
+window that is displaying the buffer, Emacs shows a contiguous section of
+the text. The section shown always contains point.
+
+@cindex scrolling
+ @dfn{Scrolling} means moving text up or down in the window so that
+different parts of the text are visible. Scrolling forward means that text
+moves up, and new text appears at the bottom. Scrolling backward moves
+text down and new text appears at the top.
+
+ Scrolling happens automatically if you move point past the bottom or top
+of the window. You can also explicitly request scrolling with the commands
+in this section.
+
+@ifinfo
+@table @kbd
+@item C-l
+Clear screen and redisplay, scrolling the selected window to center
+point vertically within it (@code{recenter}).
+@item C-v
+Scroll forward (a windowful or a specified number of lines) (@code{scroll-up}).
+@item M-v
+Scroll backward (@code{scroll-down}).
+@item @var{arg} C-l
+Scroll so point is on line @var{arg} (@code{recenter}).
+@end table
+@end ifinfo
+
+@kindex C-l
+@findex recenter
+ The most basic scrolling command is @kbd{C-l} (@code{recenter}) with no
+argument. It clears the entire screen and redisplays all windows. In
+addition, the selected window is scrolled so that point is halfway down
+from the top of the window.
+
+@kindex C-v
+@kindex M-v
+@findex scroll-up
+@findex scroll-down
+ The scrolling commands @kbd{C-v} and @kbd{M-v} let you move all the text
+in the window up or down a few lines. @kbd{C-v} (@code{scroll-up}) with an
+argument shows you that many more lines at the bottom of the window, moving
+the text and point up together as @kbd{C-l} might. @kbd{C-v} with a
+negative argument shows you more lines at the top of the window.
+@kbd{Meta-v} (@code{scroll-down}) is like @kbd{C-v}, but moves in the
+opposite direction.@refill
+
+@vindex next-screen-context-lines
+ To read the buffer a windowful at a time, use @kbd{C-v} with no argument.
+It takes the last two lines at the bottom of the window and puts them at
+the top, followed by nearly a whole windowful of lines not previously
+visible. If point was in the text scrolled off the top, it moves to the
+new top of the window. @kbd{M-v} with no argument moves backward with
+overlap similarly. The number of lines of overlap across a @kbd{C-v} or
+@kbd{M-v} is controlled by the variable @code{next-screen-context-lines}; by
+default, it is two.
+
+ Another way to do scrolling is with @kbd{C-l} with a numeric argument.
+@kbd{C-l} does not clear the screen when given an argument; it only scrolls
+the selected window. With a positive argument @var{n}, it repositions text
+to put point @var{n} lines down from the top. An argument of zero puts
+point on the very top line. Point does not move with respect to the text;
+rather, the text and point move rigidly on the screen. @kbd{C-l} with a
+negative argument puts point that many lines from the bottom of the window.
+For example, @kbd{C-u - 1 C-l} puts point on the bottom line, and @kbd{C-u
+- 5 C-l} puts it five lines from the bottom. Just @kbd{C-u} as argument,
+as in @kbd{C-u C-l}, scrolls point to the center of the screen.
+
+@vindex scroll-step
+ Scrolling happens automatically if point has moved out of the visible
+portion of the text when it is time to display. Usually the scrolling is
+done so as to put point vertically centered within the window. However, if
+the variable @code{scroll-step} has a nonzero value, an attempt is made to
+scroll the buffer by that many lines; if that is enough to bring point back
+into visibility, that is what is done.
+
+@node Horizontal Scrolling,, Scrolling, Display
+@section Horizontal Scrolling
+
+@ifinfo
+@table @kbd
+@item C-x <
+Scroll text in current window to the left (@code{scroll-left}).
+@item C-x >
+Scroll to the right (@code{scroll-right}).
+@end table
+@end ifinfo
+
+@kindex C-x <
+@kindex C-x >
+@findex scroll-left
+@findex scroll-right
+@cindex horizontal scrolling
+ The text in a window can also be scrolled horizontally. This means that
+each line of text is shifted sideways in the window, and one or more
+characters at the beginning of each line are not displayed at all. When a
+window has been scrolled horizontally in this way, text lines are truncated
+rather than continued (@pxref{Continuation Lines}), with a @samp{$} appearing
+in the first column when there is text truncated to the left, and in the
+last column when there is text truncated to the right.
+
+ The command @kbd{C-x <} (@code{scroll-left}) scrolls the selected window
+to the left by @var{n} columns with argument @var{n}. With no argument, it scrolls
+by almost the full width of the window (two columns less, to be precise).
+@kbd{C-x >} (@code{scroll-right}) scrolls similarly to the right.
+The window cannot be scrolled any farther to the right once it is
+displaying normally (with each line starting at the window's left margin);
+attempting to do so has no effect.
+
+@node Selective Display, Display Vars, Display, Display
+@section Selective Display
+@findex set-selective-display
+@kindex C-x $
+
+ Emacs has the ability to hide lines indented more than a certain number
+of columns (you specify how many columns). You can use this to get an
+overview of a part of a program.
+
+ To hide lines, type @kbd{C-x $} (@code{set-selective-display}) with a
+numeric argument @var{n}. (@xref{Arguments}, for how to give the
+argument.) Then lines with at least @var{n} columns of indentation
+disappear from the screen. The only indication of their presence is that
+three dots (@samp{@dots{}}) appear at the end of each visible line that is
+followed by one or more invisible ones.@refill
+
+ The invisible lines are still present in the buffer, and most editing
+commands see them as usual, so it is very easy to put point in the middle
+of invisible text. When this happens, the cursor appears at the end of the
+previous line, after the three dots. If point is at the end of the visible
+line, before the newline that ends it, the cursor appears before the three
+dots.
+
+ The commands @kbd{C-n} and @kbd{C-p} move across the invisible lines as if they
+were not there.
+
+ To make everything visible again, type @kbd{C-x $} with no argument.
+
+@node Display Vars,, Selective Display, Display
+@section Variables Controlling Display
+
+ This section contains information for customization only. Beginning
+users should skip it.
+
+@vindex mode-line-inverse-video
+ The variable @code{mode-line-inverse-video} controls whether the mode
+line is displayed in inverse video (assuming the terminal supports it);
+@code{nil} means don't do so. @xref{Mode Line}.
+
+@vindex inverse-video
+ If the variable @code{inverse-video} is non-@code{nil}, Emacs attempts
+to invert all the lines of the display from what they normally are.
+
+@vindex visible-bell
+ If the variable @code{visible-bell} is non-@code{nil}, Emacs attempts
+to make the whole screen blink when it would normally make an audible bell
+sound. This variable has no effect if your terminal does not have a way
+to make the screen blink.@refill
+
+@vindex no-redraw-on-reenter
+ When you reenter Emacs after suspending, Emacs normally clears the screen
+and redraws the entire display. On some terminals with more than one page
+of memory, it is possible to arrange the termcap entry so that the
+@samp{ti} and @samp{te} strings (output to the terminal when Emacs is
+entered and exited, respectively) switch between pages of memory so as to
+use one page for Emacs and another page for other output. Then you might
+want to set the variable @code{no-redraw-on-reenter} non-@code{nil} so that
+Emacs will assume, when resumed, that the screen page it is using still
+contains what Emacs last wrote there.
+
+@vindex echo-keystrokes
+ The variable @code{echo-keystrokes} controls the echoing of multi-character
+keys; its value is the number of seconds of pause required to cause echoing
+to start, or zero meaning don't echo at all. @xref{Echo Area}.
+
+@vindex ctl-arrow
+ If the variable @code{ctl-arrow} is @code{nil}, control characters in the
+buffer are displayed with octal escape sequences, all except newline and
+tab. Altering the value of @code{ctl-arrow} makes it local to the current
+buffer; until that time, the default value is in effect. The default is
+initially @code{t}. @xref{Locals}.
+
+@vindex tab-width
+ Normally, a tab character in the buffer is displayed as whitespace which
+extends to the next display tab stop position, and display tab stops come
+at intervals equal to eight spaces. The number of spaces per tab is
+controlled by the variable @code{tab-width}, which is made local by
+changing it, just like @code{ctl-arrow}. Note that how the tab character
+in the buffer is displayed has nothing to do with the definition of
+@key{TAB} as a command.
+
+@vindex selective-display-ellipses
+ If you set the variable @code{selective-display-ellipses} to @code{nil},
+the three dots do not appear at the end of a line that precedes invisible
+lines. Then there is no visible indication of the invisible lines.
+This variable too becomes local automatically when set.
+
+@node Search, Fixit, Display, Top
+@chapter Searching and Replacement
+@cindex searching
+
+ Like other editors, Emacs has commands for searching for occurrences of
+a string. The principal search command is unusual in that it is
+@dfn{incremental}; it begins to search before you have finished typing the
+search string. There are also nonincremental search commands more like
+those of other editors.
+
+ Besides the usual @code{replace-string} command that finds all
+occurrences of one string and replaces them with another, Emacs has a fancy
+replacement command called @code{query-replace} which asks interactively
+which occurrences to replace.
+
+@menu
+* Incremental Search:: Search happens as you type the string.
+* Nonincremental Search:: Specify entire string and then search.
+* Word Search:: Search for sequence of words.
+* Regexp Search:: Search for match for a regexp.
+* Regexps:: Syntax of regular expressions.
+* Search Case:: To ignore case while searching, or not.
+* Replace:: Search, and replace some or all matches.
+* Other Repeating Search:: Operating on all matches for some regexp.
+@end menu
+
+@node Incremental Search, Nonincremental Search, Search, Search
+@section Incremental Search
+
+ An incremental search begins searching as soon as you type the first
+character of the search string. As you type in the search string, Emacs
+shows you where the string (as you have typed it so far) would be found.
+When you have typed enough characters to identify the place you want, you
+can stop. Depending on what you will do next, you may or may not need to
+terminate the search explicitly with an @key{ESC} first.
+
+@c WideCommands
+@table @kbd
+@item C-s
+Incremental search forward (@code{isearch-forward}).
+@item C-r
+Incremental search backward (@code{isearch-backward}).
+@end table
+
+@kindex C-s
+@kindex C-r
+@findex isearch-forward
+@findex isearch-backward
+ @kbd{C-s} starts an incremental search. @kbd{C-s} reads characters from
+the keyboard and positions the cursor at the first occurrence of the
+characters that you have typed. If you type @kbd{C-s} and then @kbd{F},
+the cursor moves right after the first @samp{F}. Type an @kbd{O}, and see
+the cursor move to after the first @samp{FO}. After another @kbd{O}, the
+cursor is after the first @samp{FOO} after the place where you started the
+search. Meanwhile, the search string @samp{FOO} has been echoed in the
+echo area.@refill
+
+ The echo area display ends with three dots when actual searching is going
+on. When search is waiting for more input, the three dots are removed.
+(On slow terminals, the three dots are not displayed.)
+
+ If you make a mistake in typing the search string, you can erase
+characters with @key{DEL}. Each @key{DEL} cancels the last character of
+search string. This does not happen until Emacs is ready to read another
+input character; first it must either find, or fail to find, the character
+you want to erase. If you do not want to wait for this to happen, use
+@kbd{C-g} as described below.@refill
+
+ When you are satisfied with the place you have reached, you can type
+@key{ESC}, which stops searching, leaving the cursor where the search
+brought it. Also, any command not specially meaningful in searches stops
+the searching and is then executed. Thus, typing @kbd{C-a} would exit the
+search and then move to the beginning of the line. @key{ESC} is necessary
+only if the next command you want to type is a printing character,
+@key{DEL}, @key{ESC}, or another control character that is special within
+searches (@kbd{C-q}, @kbd{C-w}, @kbd{C-r}, @kbd{C-s} or @kbd{C-y}).
+
+ Sometimes you search for @samp{FOO} and find it, but not the one you
+expected to find. There was a second @samp{FOO} that you forgot about,
+before the one you were looking for. In this event, type another @kbd{C-s}
+to move to the next occurrence of the search string. This can be done any
+number of times. If you overshoot, you can cancel some @kbd{C-s}
+characters with @key{DEL}.
+
+ After you exit a search, you can search for the same string again by
+typing just @kbd{C-s C-s}: the first @kbd{C-s} is the key that invokes
+incremental search, and the second @kbd{C-s} means ``search again''.
+
+ If your string is not found at all, the echo area says @samp{Failing
+I-Search}. The cursor is after the place where Emacs found as much of your
+string as it could. Thus, if you search for @samp{FOOT}, and there is no
+@samp{FOOT}, you might see the cursor after the @samp{FOO} in @samp{FOOL}.
+At this point there are several things you can do. If your string was
+mistyped, you can rub some of it out and correct it. If you like the place
+you have found, you can type @key{ESC} or some other Emacs command to
+``accept what the search offered''. Or you can type @kbd{C-g}, which
+removes from the search string the characters that could not be found (the
+@samp{T} in @samp{FOOT}), leaving those that were found (the @samp{FOO} in
+@samp{FOOT}). A second @kbd{C-g} at that point cancels the search
+entirely, returning point to where it was when the search started.
+
+ If a search is failing and you ask to repeat it by typing another
+@kbd{C-s}, it starts again from the beginning of the buffer. Repeating
+a failing reverse search with @kbd{C-r} starts again from the end. This
+is called @dfn{wrapping around}. @samp{Wrapped} appears in the search
+prompt once this has happened.
+
+@cindex quitting (in search)
+ The @kbd{C-g} ``quit'' character does special things during searches;
+just what it does depends on the status of the search. If the search has
+found what you specified and is waiting for input, @kbd{C-g} cancels the
+entire search. The cursor moves back to where you started the search. If
+@kbd{C-g} is typed when there are characters in the search string that have
+not been found---because Emacs is still searching for them, or because it
+has failed to find them---then the search string characters which have not
+been found are discarded from the search string. With them gone, the
+search is now successful and waiting for more input, so a second @kbd{C-g}
+will cancel the entire search.
+
+ To search for a control character such as @kbd{C-s} or @key{DEL} or
+@key{ESC}, you must quote it by typing @kbd{C-q} first. This function
+of @kbd{C-q} is analogous to its meaning as an Emacs command: it causes
+the following character to be treated the way a graphic character would
+normally be treated in the same context. You can also specify a quoted
+character in octal while searching, just as you can for insertion.
+@xref{Basic}.
+
+ You can change to searching backwards with @kbd{C-r}. If a search fails
+because the place you started was too late in the file, you should do this.
+Repeated @w{@kbd{C-r}} keeps looking for more occurrences backwards. A
+@kbd{C-s} starts going forwards again. @kbd{C-r} in a search can be cancelled
+with @key{DEL}.
+
+ If you know initially that you want to search backwards, you can
+use @kbd{C-r} instead of @kbd{C-s} to start the search, because @kbd{C-r}
+is also a key running a command (@code{isearch-backward}) to search
+backward.
+
+ The characters @kbd{C-y} and @kbd{C-w} can be used in incremental search
+to grab text from the buffer into the search string. This makes it
+convenient to search for another occurrence of text at point. @kbd{C-w}
+copies the word after point as part of the search string, advancing
+point over that word. Another @kbd{C-s} to repeat the search will then
+search for a string including that word. @kbd{C-y} is similar to @kbd{C-w}
+but copies all the rest of the current line into the search string.
+
+ All the characters special in incremental search can be changed by setting
+the following variables:
+
+@vindex search-delete-char
+@vindex search-exit-char
+@vindex search-quote-char
+@vindex search-repeat-char
+@vindex search-reverse-char
+@vindex search-yank-line-char
+@vindex search-yank-word-char
+@table @code
+@item search-delete-char
+Character to delete from incremental search string (normally @key{DEL}).
+@item search-exit-char
+Character to exit incremental search (normally @key{ESC}).
+@item search-quote-char
+Character to quote special characters for incremental search (normally
+@kbd{C-q}).
+@item search-repeat-char
+Character to repeat incremental search forwards (normally @w{@kbd{C-s}}).
+@item search-reverse-char
+Character to repeat incremental search backwards (normally @w{@kbd{C-r}}).
+@item search-yank-line-char
+Character to pull rest of line from buffer into search string
+(normally @kbd{C-y}).
+@item search-yank-word-char
+Character to pull next word from buffer into search string (normally
+@kbd{C-w}).
+@end table
+
+@subsection Slow Terminal Incremental Search
+
+ Incremental search on a slow terminal uses a modified style of display
+that is designed to take less time. Instead of redisplaying the buffer at
+each place the search gets to, it creates a new single-line window and uses
+that to display the line that the search has found. The single-line window
+comes into play as soon as point gets outside of the text that is already
+on the screen.
+
+ When the search is terminated, the single-line window is removed. Only
+at this time is the window in which the search was done redisplayed to show
+its new value of point.
+
+ The three dots at the end of the search string, normally used to indicate
+that searching is going on, are not displayed in slow style display.
+
+@vindex search-slow-speed
+ The slow terminal style of display is used when the terminal baud rate is
+less than or equal to the value of the variable @code{search-slow-speed},
+initially 1200.
+
+@vindex search-slow-window-lines
+ The number of lines to use in slow terminal search display is controlled
+by the variable @code{search-slow-window-lines}. 1 is its normal value.
+
+@node Nonincremental Search, Word Search, Incremental Search, Search
+@section Nonincremental Search
+@cindex nonincremental search
+
+ Emacs also has conventional nonincremental search commands, which require
+you to type the entire search string before searching begins.
+
+@table @kbd
+@item C-s @key{ESC} @var{string} @key{RET}
+Search for @var{string}.
+@item C-r @key{ESC} @var{string} @key{RET}
+Search backward for @var{string}.
+@end table
+
+ To do a nonincremental search, first type @kbd{C-s @key{ESC}}. This
+enters the minibuffer to read the search string; terminate the string with
+@key{RET}, and then the search is done. If the string is not found the
+search command gets an error.
+
+ The way @kbd{C-s @key{ESC}} works is that the @kbd{C-s} invokes
+incremental search, which is specially programmed to invoke nonincremental
+search if the argument you give it is empty. (Such an empty argument would
+otherwise be useless.) @kbd{C-r @key{ESC}} also works this way.
+
+@findex search-forward
+@findex search-backward
+ Forward and backward nonincremental searches are implemented by the
+commands @code{search-forward} and @code{search-backward}. These commands
+may be bound to keys in the usual manner. The reason that incremental
+search is programmed to invoke them as well is that @kbd{C-s @key{ESC}}
+is the traditional sequence of characters used in Emacs to invoke
+nonincremental search.
+
+ However, nonincremental searches performed using @kbd{C-s @key{ESC}} do
+not call @code{search-forward} right away. The first thing done is to see
+if the next character is @kbd{C-w}, which requests a word search.
+@ifinfo
+@xref{Word Search}.
+@end ifinfo
+
+@node Word Search, Regexp Search, Nonincremental Search, Search
+@section Word Search
+@cindex word search
+
+ Word search searches for a sequence of words without regard to how the
+words are separated. More precisely, you type a string of many words,
+using single spaces to separate them, and the string can be found even if
+there are multiple spaces, newlines or other punctuation between the words.
+
+ Word search is useful in editing documents formatted by text formatters.
+If you edit while looking at the printed, formatted version, you can't tell
+where the line breaks are in the source file. With word search, you can
+search without having to know them.
+
+@table @kbd
+@item C-s @key{ESC} C-w @var{words} @key{RET}
+Search for @var{words}, ignoring differences in punctuation.
+@item C-r @key{ESC} C-w @var{words} @key{RET}
+Search backward for @var{words}, ignoring differences in punctuation.
+@end table
+
+ Word search is a special case of nonincremental search and is invoked
+with @kbd{C-s @key{ESC} C-w}. This is followed by the search string, which
+must always be terminated with @key{RET}. Being nonincremental, this
+search does not start until the argument is terminated. It works by
+constructing a regular expression and searching for that. @xref{Regexp
+Search}.
+
+ A backward word search can be done by @kbd{C-r @key{ESC} C-w}.
+
+@findex word-search-forward
+@findex word-search-backward
+ Forward and backward word searches are implemented by the commands
+@code{word-search-forward} and @code{word-search-backward}. These commands
+may be bound to keys in the usual manner. The reason that incremental
+search is programmed to invoke them as well is that @kbd{C-s @key{ESC} C-w}
+is the traditional Emacs sequence of keys for word search.
+
+@node Regexp Search, Regexps, Word Search, Search
+@section Regular Expression Search
+@cindex regular expression
+@cindex expressions, regular
+@cindex regexp
+
+ A @dfn{regular expression} (@dfn{regexp}, for short) is a pattern that
+denotes a set of strings, possibly an infinite set. Searching for matches
+for a regexp is a very powerful operation that editors on Unix systems have
+traditionally offered. In GNU Emacs, you can search for the next match for
+a regexp either incrementally or not.
+
+@kindex C-M-s
+@findex isearch-forward-regexp
+@findex isearch-backward-regexp
+ Incremental search for a regexp is done by typing @kbd{C-M-s}
+(@code{isearch-forward-regexp}). This command reads a search string
+incrementally just like @kbd{C-s}, but it treats the search string as a
+regexp rather than looking for an exact match against the text in the
+buffer. Each time you add text to the search string, you make the regexp
+longer, and the new regexp is searched for. A reverse regexp search command,
+@code{isearch-backward-regexp}, also exists but no key runs it.
+
+ All of the control characters that do special things within an ordinary
+incremental search have the same function in incremental regexp search.
+Typing @kbd{C-s} or @kbd{C-r} immediately after starting the search
+retrieves the last incremental search regexp used; that is to say,
+incremental regexp and non-regexp searches have independent defaults.
+
+ Note that adding characters to the regexp in an incremental regexp search
+does not make the cursor move back and start again. Perhaps it ought to; I
+am not sure. As it stands, if you have searched for @samp{foo} and you
+add @samp{\|bar}, the search will not check for a @samp{bar} in the
+buffer before the @samp{foo}.
+
+@findex re-search-forward
+@findex re-search-backward
+ Nonincremental search for a regexp is done by the functions
+@code{re-search-forward} and @code{re-search-backward}. You can invoke
+these with @kbd{M-x}, or bind them to keys. Also, you can call
+@code{re-search-forward} by way of incremental regexp search with
+@kbd{C-M-s @key{ESC}}.
+
+@node Regexps, Search Case, Regexp Search, Search
+@section Syntax of Regular Expressions
+
+Regular expressions have a syntax in which a few characters are special
+constructs and the rest are @dfn{ordinary}. An ordinary character is a
+simple regular expression which matches that character and nothing else.
+The special characters are @samp{$}, @samp{^}, @samp{.}, @samp{*},
+@samp{+}, @samp{?}, @samp{[}, @samp{]} and @samp{\}; no new special
+characters will be defined. Any other character appearing in a regular
+expression is ordinary, unless a @samp{\} precedes it.@refill
+
+For example, @samp{f} is not a special character, so it is ordinary, and
+therefore @samp{f} is a regular expression that matches the string @samp{f}
+and no other string. (It does @i{not} match the string @samp{ff}.) Likewise,
+@samp{o} is a regular expression that matches only @samp{o}.@refill
+
+Any two regular expressions @var{a} and @var{b} can be concatenated. The
+result is a regular expression which matches a string if @var{a} matches
+some amount of the beginning of that string and @var{b} matches the rest of
+the string.@refill
+
+As a simple example, we can concatenate the regular expressions @samp{f}
+and @samp{o} to get the regular expression @samp{fo}, which matches only
+the string @samp{fo}. Still trivial. To do something nontrivial, you
+need to use one of the special characters. Here is a list of them.
+
+@table @kbd
+@item .@: @r{(Period)}
+is a special character that matches any single character except a newline.
+Using concatenation, we can make regular expressions like @samp{a.b} which
+matches any three-character string which begins with @samp{a} and ends with
+@samp{b}.@refill
+
+@item *
+is not a construct by itself; it is a suffix, which means the
+preceding regular expression is to be repeated as many times as
+possible. In @samp{fo*}, the @samp{*} applies to the @samp{o}, so
+@samp{fo*} matches one @samp{f} followed by any number of @samp{o}s.
+The case of zero @samp{o}s is allowed: @samp{fo*} does match
+@samp{f}.@refill
+
+@samp{*} always applies to the @i{smallest} possible preceding
+expression. Thus, @samp{fo*} has a repeating @samp{o}, not a
+repeating @samp{fo}.@refill
+
+The matcher processes a @samp{*} construct by matching, immediately,
+as many repetitions as can be found. Then it continues with the rest
+of the pattern. If that fails, backtracking occurs, discarding some
+of the matches of the @samp{*}-modified construct in case that makes
+it possible to match the rest of the pattern. For example, matching
+@samp{ca*ar} against the string @samp{caaar}, the @samp{a*} first
+tries to match all three @samp{a}s; but the rest of the pattern is
+@samp{ar} and there is only @samp{r} left to match, so this try fails.
+The next alternative is for @samp{a*} to match only two @samp{a}s.
+With this choice, the rest of the regexp matches successfully.@refill
+
+@item +
+Is a suffix character similar to @samp{*} except that it requires that
+the preceding expression be matched at least once. So, for example,
+@samp{ca+r} will match the strings @samp{car} and @samp{caaaar}
+but not the string @samp{cr}, whereas @samp{ca*r} would match all
+three strings.@refill
+
+@item ?
+Is a suffix character similar to @samp{*} except that it can match the
+preceding expression either once or not at all. For example,
+@samp{ca?r} will match @samp{car} or @samp{cr}; nothing else.
+
+@item [ @dots{} ]
+@samp{[} begins a @dfn{character set}, which is terminated by a
+@samp{]}. In the simplest case, the characters between the two form
+the set. Thus, @samp{[ad]} matches either one @samp{a} or one
+@samp{d}, and @samp{[ad]*} matches any string composed of just
+@samp{a}s and @samp{d}s (including the empty string), from which it
+follows that @samp{c[ad]*r} matches @samp{cr}, @samp{car}, @samp{cdr},
+@samp{caddaar}, etc.@refill
+
+Character ranges can also be included in a character set, by writing
+two characters with a @samp{-} between them. Thus, @samp{[a-z]}
+matches any lower-case letter. Ranges may be intermixed freely with
+individual characters, as in @samp{[a-z$%.]}, which matches any lower
+case letter or @samp{$}, @samp{%} or period.@refill
+
+Note that the usual special characters are not special any more inside
+a character set. A completely different set of special characters
+exists inside character sets: @samp{]}, @samp{-} and @samp{^}.@refill
+
+To include a @samp{]} in a character set, you must make it the first
+character. For example, @samp{[]a]} matches @samp{]} or @samp{a}. To
+include a @samp{-}, write @samp{---}, which is a range containing only
+@samp{-}. To include @samp{^}, make it other than the first character
+in the set.@refill
+
+@item [^ @dots{} ]
+@samp{[^} begins a @dfn{complement character set}, which matches any
+character except the ones specified. Thus, @samp{[^a-z0-9A-Z]}
+matches all characters @i{except} letters and digits.@refill
+
+@samp{^} is not special in a character set unless it is the first
+character. The character following the @samp{^} is treated as if it
+were first (@samp{-} and @samp{]} are not special there).
+
+Note that a complement character set can match a newline, unless
+newline is mentioned as one of the characters not to match.
+
+@item ^
+is a special character that matches the empty string, but only if at
+the beginning of a line in the text being matched. Otherwise it fails
+to match anything. Thus, @samp{^foo} matches a @samp{foo} which occurs
+at the beginning of a line.
+
+@item $
+is similar to @samp{^} but matches only at the end of a line. Thus,
+@samp{xx*$} matches a string of one @samp{x} or more at the end of a line.
+
+@item \
+has two functions: it quotes the special characters (including
+@samp{\}), and it introduces additional special constructs.
+
+Because @samp{\} quotes special characters, @samp{\$} is a regular
+expression which matches only @samp{$}, and @samp{\[} is a regular
+expression which matches only @samp{[}, and so on.@refill
+@end table
+
+Note: for historical compatibility, special characters are treated as
+ordinary ones if they are in contexts where their special meanings make no
+sense. For example, @samp{*foo} treats @samp{*} as ordinary since there is
+no preceding expression on which the @samp{*} can act. It is poor practice
+to depend on this behavior; better to quote the special character anyway,
+regardless of where is appears.@refill
+
+For the most part, @samp{\} followed by any character matches only
+that character. However, there are several exceptions: characters
+which, when preceded by @samp{\}, are special constructs. Such
+characters are always ordinary when encountered on their own. Here
+is a table of @samp{\} constructs.
+
+@table @kbd
+@item \|
+specifies an alternative.
+Two regular expressions @var{a} and @var{b} with @samp{\|} in
+between form an expression that matches anything that either @var{a} or
+@var{b} will match.@refill
+
+Thus, @samp{foo\|bar} matches either @samp{foo} or @samp{bar}
+but no other string.@refill
+
+@samp{\|} applies to the largest possible surrounding expressions. Only a
+surrounding @samp{\( @dots{} \)} grouping can limit the grouping power of
+@samp{\|}.@refill
+
+Full backtracking capability exists to handle multiple uses of @samp{\|}.
+
+@item \( @dots{} \)
+is a grouping construct that serves three purposes:
+
+@enumerate
+@item
+To enclose a set of @samp{\|} alternatives for other operations.
+Thus, @samp{\(foo\|bar\)x} matches either @samp{foox} or @samp{barx}.
+
+@item
+To enclose a complicated expression for the postfix @samp{*} to operate on.
+Thus, @samp{ba\(na\)*} matches @samp{bananana}, etc., with any (zero or
+more) number of @samp{na} strings.@refill
+
+@item
+To mark a matched substring for future reference.
+
+@end enumerate
+
+This last application is not a consequence of the idea of a
+parenthetical grouping; it is a separate feature which happens to be
+assigned as a second meaning to the same @samp{\( @dots{} \)} construct
+because there is no conflict in practice between the two meanings.
+Here is an explanation of this feature:
+
+@item \@var{digit}
+after the end of a @samp{\( @dots{} \)} construct, the matcher remembers the
+beginning and end of the text matched by that construct. Then, later on
+in the regular expression, you can use @samp{\} followed by @var{digit}
+to mean ``match the same text matched the @var{digit}'th time by the
+@samp{\( @dots{} \)} construct.''@refill
+
+The strings matching the first nine @samp{\( @dots{} \)} constructs appearing
+in a regular expression are assigned numbers 1 through 9 in order that the
+open-parentheses appear in the regular expression. @samp{\1} through
+@samp{\9} may be used to refer to the text matched by the corresponding
+@samp{\( @dots{} \)} construct.
+
+For example, @samp{\(.*\)\1} matches any newline-free string that is
+composed of two identical halves. The @samp{\(.*\)} matches the first
+half, which may be anything, but the @samp{\1} that follows must match
+the same exact text.
+
+@item \`
+matches the empty string, provided it is at the beginning
+of the buffer.
+
+@item \'
+matches the empty string, provided it is at the end of
+the buffer.
+
+@item \b
+matches the empty string, provided it is at the beginning or
+end of a word. Thus, @samp{\bfoo\b} matches any occurrence of
+@samp{foo} as a separate word. @samp{\bballs?\b} matches
+@samp{ball} or @samp{balls} as a separate word.@refill
+
+@item \B
+matches the empty string, provided it is @i{not} at the beginning or
+end of a word.
+
+@item \<
+matches the empty string, provided it is at the beginning of a word.
+
+@item \>
+matches the empty string, provided it is at the end of a word.
+
+@item \w
+matches any word-constituent character. The editor syntax table
+determines which characters these are.
+
+@item \W
+matches any character that is not a word-constituent.
+
+@item \s@var{code}
+matches any character whose syntax is @var{code}. @var{code} is a
+character which represents a syntax code: thus, @samp{w} for word
+constituent, @samp{-} for whitespace, @samp{(} for open-parenthesis,
+etc. @xref{Syntax}.@refill
+
+@item \S@var{code}
+matches any character whose syntax is not @var{code}.
+@end table
+
+ Here is a complicated regexp, used by Emacs to recognize the end of a
+sentence together with any whitespace that follows. It is given in Lisp
+syntax to enable you to distinguish the spaces from the tab characters. In
+Lisp syntax, the string constant begins and ends with a double-quote.
+@samp{\"} stands for a double-quote as part of the regexp, @samp{\\} for a
+backslash as part of the regexp, @samp{\t} for a tab and @samp{\n} for a
+newline.
+
+@example
+"[.?!][]\"')]*\\($\\|\t\\| \\)[ \t\n]*"
+@end example
+
+@noindent
+This contains four parts in succession: a character set matching period,
+@samp{?} or @samp{!}; a character set matching close-brackets,
+quotes or parentheses, repeated any number of times; an alternative in
+backslash-parentheses that matches end-of-line, a tab or two spaces; and a
+character set matching whitespace characters, repeated any number of times.
+
+ Note that the above example shows how to write this regexp when
+entering it as part of an Emacs Lisp program. To enter the same regexp
+in an interactive command such as @code{re-search-forward} you must
+spell it differently:
+
+@example
+[.?!][]"')]*\($\|^Q^I\| \)[ ^Q^I^Q^J]*
+@end example
+
+@node Search Case, Replace, Regexps, Search
+@section Searching and Case
+
+@vindex case-fold-search
+ All sorts of searches in Emacs normally ignore the case of the text they
+are searching through; if you specify searching for @samp{FOO}, then
+@samp{Foo} and @samp{foo} are also considered a match. Regexps, and in
+particular character sets, are included: @samp{[aB]} would match @samp{a}
+or @samp{A} or @samp{b} or @samp{B}.@refill
+
+ If you do not want this feature, set the variable @code{case-fold-search}
+to @code{nil}. Then all letters must match exactly, including case. This
+is a per-buffer variable; altering the variable affects only the current
+buffer, but there is a default value which you can change as well.
+@xref{Locals}.
+
+@node Replace, Other Repeating Search, Search Case, Search
+@section Replacement Commands
+@cindex replacement
+@cindex string substitution
+@cindex global substitution
+
+ Global search-and-replace operations are not needed as often in Emacs as
+they are in other editors, but they are available. In addition to the
+simple @code{replace-string} command which is like that found in most
+editors, there is a @code{query-replace} command which asks you, for each
+occurrence of the pattern, whether to replace it.
+
+ The replace commands all replace one string (or regexp) with one
+replacement string. It is possible to perform several replacements in
+parallel using the command @code{expand-region-abbrevs}. @xref{Expanding
+Abbrevs}.
+
+@menu
+* Unconditional Replace:: Replacing all matches for a string.
+* Regexp Replace:: Replacing all matches for a regexp.
+* Replacement and Case:: How replacements preserve case of letters.
+* Query Replace:: How to use querying.
+@end menu
+
+@node Unconditional Replace, Regexp Replace, Replace, Replace
+@subsection Unconditional Replacement
+@findex replace-string
+@findex replace-regexp
+
+@table @kbd
+@item M-x replace-string @key{RET} @var{string} @key{RET} @var{newstring} @key{RET}
+Replace every occurrence of @var{string} with @var{newstring}.
+@item M-x replace-regexp @key{RET} @var{regexp} @key{RET} @var{newstring} @key{RET}
+Replace every match for @var{regexp} with @var{newstring}.
+@end table
+
+ To replace every instance of @samp{foo} after point with @samp{bar}, use
+the command @kbd{M-x replace-string} with the two arguments @samp{foo} and
+@samp{bar}. Replacement occurs only after point, so if you want to cover
+the whole buffer you must go to the beginning first. All occurrences up to
+the end of the buffer are replaced; to limit replacement to part of the
+buffer, narrow to that part of the buffer before doing the replacement
+(@pxref{Narrowing}).
+
+ When @code{replace-string} exits, point is left at the last occurrence
+replaced. The value of point when the @code{replace-string} command was
+issued is remembered on the mark ring; @kbd{C-u C-@key{SPC}} moves back
+there.
+
+ A numeric argument restricts replacement to matches that are surrounded
+by word boundaries.
+
+@node Regexp Replace, Replacement and Case, Unconditional Replace, Replace
+@subsection Regexp Replacement
+
+ @code{replace-string} replaces exact matches for a single string. The
+similar command @code{replace-regexp} replaces any match for a specified
+pattern.
+
+ In @code{replace-regexp}, the @var{newstring} need not be constant. It
+can refer to all or part of what is matched by the @var{regexp}. @samp{\&}
+in @var{newstring} stands for the entire text being replaced.
+@samp{\@var{d}} in @var{newstring}, where @var{d} is a digit, stands for
+whatever matched the @var{d}'th parenthesized grouping in @var{regexp}.
+For example,@refill
+
+@example
+M-x replace-regexp @key{RET} c[ad]+r @key{RET} \&-safe @key{RET}
+@end example
+
+@noindent
+would replace (for example) @samp{cadr} with @samp{cadr-safe} and @samp{cddr}
+with @samp{cddr-safe}.
+
+@example
+M-x replace-regexp @key{RET} \(c[ad]+r\)-safe @key{RET} \1 @key{RET}
+@end example
+
+@noindent
+would perform exactly the opposite replacements. To include a @samp{\}
+in the text to replace with, you must give @samp{\\}.
+
+@node Replacement and Case, Query Replace, Regexp Replace, Replace
+@subsection Replace Commands and Case
+
+@vindex case-replace
+@vindex case-fold-search
+ If the arguments to a replace command are in lower case, it preserves
+case when it makes a replacement. Thus, the command
+
+@example
+M-x replace-string @key{RET} foo @key{RET} bar @key{RET}
+@end example
+
+@noindent
+replaces a lower case @samp{foo} with a lower case @samp{bar}, @samp{FOO}
+with @samp{BAR}, and @samp{Foo} with @samp{Bar}. If upper case letters are
+used in the second argument, they remain upper case every time that
+argument is inserted. If upper case letters are used in the first
+argument, the second argument is always substituted exactly as given, with
+no case conversion. Likewise, if the variable @code{case-replace} is set
+to @code{nil}, replacement is done without case conversion. If
+@code{case-fold-search} is set to @code{nil}, case is significant in
+matching occurrences of @samp{foo} to replace; also, case conversion of the
+replacement string is not done.
+
+@node Query Replace,, Replacement and Case, Replace
+@subsection Query Replace
+@cindex query replace
+
+@table @kbd
+@item M-% @var{string} @key{RET} @var{newstring} @key{RET}
+@itemx M-x query-replace @key{RET} @var{string} @key{RET} @var{newstring} @key{RET}
+Replace some occurrences of @var{string} with @var{newstring}.
+@item M-x query-replace-regexp @key{RET} @var{regexp} @key{RET} @var{newstring} @key{RET}
+Replace some matches for @var{regexp} with @var{newstring}.
+@end table
+
+@kindex M-%
+@findex query-replace
+ If you want to change only some of the occurrences of @samp{foo} to
+@samp{bar}, not all of them, then you cannot use an ordinary
+@code{replace-string}. Instead, use @kbd{M-%} (@code{query-replace}).
+This command finds occurrences of @samp{foo} one by one, displays each
+occurrence and asks you whether to replace it. A numeric argument to
+@code{query-replace} tells it to consider only occurrences that are bounded
+by word-delimiter characters.@refill
+
+@findex query-replace-regexp
+ Aside from querying, @code{query-replace} works just like
+@code{replace-string}, and @code{query-replace-regexp} works
+just like @code{replace-regexp}.@refill
+
+ The things you can type when you are shown an occurrence of @var{string}
+or a match for @var{regexp} are:
+
+@kindex SPC (query-replace)
+@kindex DEL (query-replace)
+@kindex , (query-replace)
+@kindex ESC (query-replace)
+@kindex . (query-replace)
+@kindex ! (query-replace)
+@kindex ^ (query-replace)
+@kindex C-r (query-replace)
+@kindex C-w (query-replace)
+@kindex C-l (query-replace)
+
+@c WideCommands
+@table @kbd
+@item @key{SPC}
+to replace the occurrence with @var{newstring}. This preserves case, just
+like @code{replace-string}, provided @code{case-replace} is non-@code{nil},
+as it normally is.@refill
+
+@item @key{DEL}
+to skip to the next occurrence without replacing this one.
+
+@item , @r{(Comma)}
+to replace this occurrence and display the result. You are then asked
+for another input character, except that since the replacement has
+already been made, @key{DEL} and @key{SPC} are equivalent. You could
+type @kbd{C-r} at this point (see below) to alter the replaced text. You
+could also type @kbd{C-x u} to undo the replacement; this exits the
+@code{query-replace}, so if you want to do further replacement you must use
+@kbd{C-x ESC} to restart (@pxref{Repetition}).
+
+@item @key{ESC}
+to exit without doing any more replacements.
+
+@item .@: @r{(Period)}
+to replace this occurrence and then exit.
+
+@item !
+to replace all remaining occurrences without asking again.
+
+@item ^
+to go back to the location of the previous occurrence (or what used to
+be an occurrence), in case you changed it by mistake. This works by
+popping the mark ring. Only one @kbd{^} in a row is allowed, because
+only one previous replacement location is kept during @code{query-replace}.
+
+@item C-r
+to enter a recursive editing level, in case the occurrence needs to be
+edited rather than just replaced with @var{newstring}. When you are
+done, exit the recursive editing level with @kbd{C-M-c} and the next
+occurrence will be displayed. @xref{Recursive Edit}.
+
+@item C-w
+to delete the occurrence, and then enter a recursive editing level as
+in @kbd{C-r}. Use the recursive edit to insert text to replace the
+deleted occurrence of @var{string}. When done, exit the recursive
+editing level with @kbd{C-M-c} and the next occurrence will be
+displayed.
+
+@item C-l
+to redisplay the screen and then give another answer.
+
+@item C-h
+to display a message summarizing these options, then give another
+answer.
+@end table
+
+ If you type any other character, the @code{query-replace} is exited, and
+the character executed as a command. To restart the @code{query-replace},
+use @kbd{C-x @key{ESC}}, which repeats the @code{query-replace} because it
+used the minibuffer to read its arguments. @xref{Repetition, C-x ESC}.
+
+ To replace every occurrence, you can start @code{query-replace} at the
+beginning of the buffer and type @kbd{!}, or you can use the
+@code{replace-string} command at the beginning of the buffer. To
+replace every occurrence in a part of the buffer, narrow to that part
+and then run @code{replace-string} or @code{query-replace} at the
+beginning of it. @xref{Narrowing}.
+
+@node Other Repeating Search,, Replace, Search
+@section Other Search-and-Loop Commands
+
+ Here are some other commands that find matches for a regular expression.
+They all operate from point to the end of the buffer.
+
+@findex list-matching-lines
+@findex occur
+@findex count-matches
+@findex delete-non-matching-lines
+@findex delete-matching-lines
+@c grosscommands
+@table @kbd
+@item M-x occur
+Print each line that follows point and contains a match for the
+specified regexp. A numeric argument specifies the number of context
+lines to print before and after each matching line; the default is
+none.
+
+@kindex C-c C-c (Occur mode)
+The buffer @samp{*Occur*} containing the output serves as a menu for
+finding the occurrences in their original context. Find an occurrence
+as listed in @samp{*Occur*}, position point there and type @kbd{C-c
+C-c}; this switches to the buffer that was searched and moves point to
+the original of the same occurrence.
+
+@item M-x list-matching-lines
+Synonym for @kbd{M-x occur}.
+
+@item M-x count-matches
+Print the number of matches following point for the specified regexp.
+
+@item M-x delete-non-matching-lines
+Delete each line that follows point and does not contain a match for
+the specified regexp.
+
+@item M-x delete-matching-lines
+Delete each line that follows point and contains a match for the
+specified regexp.
+@end table
+
+@node Fixit, Files, Search, Top
+@chapter Commands for Fixing Typos
+@cindex typos
+@cindex mistakes, correcting
+
+ In this chapter we describe the commands that are especially useful for
+the times when you catch a mistake in your text just after you have made
+it, or change your mind while composing text on line.
+
+@menu
+* Kill Errors:: Commands to kill a batch of recently entered text.
+* Transpose:: Exchanging two characters, words, lines, lists...
+* Fixing Case:: Correcting case of last word entered.
+* Spelling:: Apply spelling checker to a word, or a whole file.
+@end menu
+
+@node Kill Errors, Transpose, Fixit, Fixit
+@section Killing Your Mistakes
+
+@table @kbd
+@item @key{DEL}
+Delete last character (@code{delete-backward-char}).
+@item M-@key{DEL}
+Kill last word (@code{backward-kill-word}).
+@item C-x @key{DEL}
+Kill to beginning of sentence (@code{backward-kill-sentence}).
+@end table
+
+@kindex DEL
+@findex delete-backward-char
+ The @key{DEL} character (@code{delete-backward-char}) is the most
+important correction command. When used among graphic (self-inserting)
+characters, it can be thought of as canceling the last character typed.
+
+@kindex M-DEL
+@kindex C-x DEL
+@findex backward-kill-word
+@findex backward-kill-sentence
+ When your mistake is longer than a couple of characters, it might be more
+convenient to use @kbd{M-@key{DEL}} or @kbd{C-x @key{DEL}}.
+@kbd{M-@key{DEL}} kills back to the start of the last word, and @kbd{C-x
+@key{DEL}} kills back to the start of the last sentence. @kbd{C-x
+@key{DEL}} is particularly useful when you are thinking of what to write as
+you type it, in case you change your mind about phrasing.
+@kbd{M-@key{DEL}} and @kbd{C-x @key{DEL}} save the killed text for
+@kbd{C-y} and @kbd{M-y} to retrieve. @xref{Yanking}.@refill
+
+ @kbd{M-@key{DEL}} is often useful even when you have typed only a few
+characters wrong, if you know you are confused in your typing and aren't
+sure exactly what you typed. At such a time, you cannot correct with
+@key{DEL} except by looking at the screen to see what you did. It requires
+less thought to kill the whole word and start over again.
+
+@node Transpose, Fixing Case, Kill Errors, Fixit
+@section Transposing Text
+
+@table @kbd
+@item C-t
+Transpose two characters (@code{transpose-chars}).
+@item M-t
+Transpose two words (@code{transpose-words}).
+@item C-M-t
+Transpose two balanced expressions (@code{transpose-sexps}).
+@item C-x C-t
+Transpose two lines (@code{transpose-lines}).
+@end table
+
+@cindex transposition
+@kindex C-t
+@findex transpose-chars
+ The common error of transposing two characters can be fixed, when they
+are adjacent, with the @kbd{C-t} command (@code{transpose-chars}). Normally,
+@kbd{C-t} transposes the two characters on either side of point. When
+given at the end of a line, rather than transposing the last character of
+the line with the newline, which would be useless, @kbd{C-t} transposes the
+last two characters on the line. So, if you catch your transposition error
+right away, you can fix it with just a @kbd{C-t}. If you don't catch it so
+fast, you must move the cursor back to between the two transposed
+characters. If you transposed a space with the last character of the word
+before it, the word motion commands are a good way of getting there.
+Otherwise, a reverse search (@kbd{C-r}) is often the best way.
+@xref{Search}.
+
+
+@kindex C-x C-t
+@findex transpose-lines
+@kindex M-t
+@findex transpose-words
+@kindex C-M-t
+@findex transpose-sexps
+ @kbd{Meta-t} (@code{transpose-words}) transposes the word before point
+with the word after point. It moves point forward over a word, dragging
+the word preceding or containing point forward as well. The punctuation
+characters between the words do not move. For example, @w{@samp{FOO, BAR}}
+transposes into @w{@samp{BAR, FOO}} rather than @samp{@w{BAR FOO,}}.
+
+ @kbd{C-M-t} (@code{transpose-sexps}) is a similar command for transposing
+two expressions (@pxref{Lists}), and @kbd{C-x C-t} (@code{transpose-lines})
+exchanges lines. They work like @kbd{M-t} except in determining the
+division of the text into syntactic units.
+
+ A numeric argument to a transpose command serves as a repeat count: it
+tells the transpose command to move the character (word, sexp, line) before
+or containing point across several other characters (words, sexps, lines).
+For example, @kbd{C-u 3 C-t} moves the character before point forward
+across three other characters. This is equivalent to repeating @kbd{C-t}
+three times. @kbd{C-u - 4 M-t} moves the word before point backward across
+four words. @kbd{C-u - C-M-t} would cancel the effect of plain
+@kbd{C-M-t}.@refill
+
+ A numeric argument of zero is assigned a special meaning (because
+otherwise a command with a repeat count of zero would do nothing): to
+transpose the character (word, sexp, line) ending after point with the
+one ending after the mark.
+
+@node Fixing Case, Spelling, Transpose, Fixit
+@section Case Conversion
+
+@table @kbd
+@item M-- M-l
+Convert last word to lower case. Note @kbd{Meta--} is Meta-minus.
+@item M-- M-u
+Convert last word to all upper case.
+@item M-- M-c
+Convert last word to lower case with capital initial.
+@end table
+
+@findex downcase-word
+@findex upcase-word
+@findex capitalize-word
+@kindex M-@t{-} M-l
+@kindex M-@t{-} M-u
+@kindex M-@t{-} M-c
+@cindex case conversion
+@cindex words
+ A very common error is to type words in the wrong case. Because of this,
+the word case-conversion commands @kbd{M-l}, @kbd{M-u} and @kbd{M-c} have a
+special feature when used with a negative argument: they do not move the
+cursor. As soon as you see you have mistyped the last word, you can simply
+case-convert it and go on typing. @xref{Case}.@refill
+
+@node Spelling,, Fixing Case, Fixit
+@section Checking and Correcting Spelling
+@cindex spelling
+
+@c doublewidecommands
+@table @kbd
+@item M-$
+Check and correct spelling of word (@code{spell-word}).
+@item M-x spell-buffer
+Check and correct spelling of each word in the buffer.
+@item M-x spell-region
+Check and correct spelling of each word in the region.
+@item M-x spell-string
+Check spelling of specified word.
+@end table
+
+@kindex M-$
+@findex spell-word
+ To check the spelling of the word before point, and optionally correct it
+as well, use the command @kbd{M-$} (@code{spell-word}). This command runs
+an inferior process containing the @code{spell} program to see whether the
+word is correct English. If it is not, it asks you to edit the word (in
+the minibuffer) into a corrected spelling, and then does a @code{query-replace}
+to substitute the corrected spelling for the old one throughout the buffer.
+
+ If you exit the minibuffer without altering the original spelling, it
+means you do not want to do anything to that word. Then the @code{query-replace}
+is not done.
+
+@findex spell-buffer
+ @kbd{M-x spell-buffer} checks each word in the buffer the same way that
+@code{spell-word} does, doing a @code{query-replace} if appropriate for
+every incorrect word.@refill
+
+@findex spell-region
+ @kbd{M-x spell-region} is similar but operates only on the region, not
+the entire buffer.
+
+@findex spell-string
+ @kbd{M-x spell-string} reads a string as an argument and checks whether
+that is a correctly spelled English word. It prints in the echo area a
+message giving the answer.
+
+@node Files, Buffers, Fixit, Top
+@chapter File Handling
+@cindex files
+
+ The basic unit of stored data in Unix is the @dfn{file}. To edit a file,
+you must tell Emacs to examine the file and prepare a buffer containing a
+copy of the file's text. This is called @dfn{visiting} the file. Editing
+commands apply directly to text in the buffer; that is, to the copy inside
+Emacs. Your changes appear in the file itself only when you @dfn{save} the
+buffer back into the file.
+
+ In addition to visiting and saving files, Emacs can delete, copy, rename,
+and append to files, and operate on file directories.
+
+@menu
+* File Names:: How to type and edit file name arguments.
+* Visiting:: Visiting a file prepares Emacs to edit the file.
+* Saving:: Saving makes your changes permanent.
+* Reverting:: Reverting cancels all the changes not saved.
+* Auto Save:: Auto Save periodically protects against loss of data.
+* ListDir:: Listing the contents of a file directory.
+* Dired:: ``Editing'' a directory to delete, rename, etc.
+ the files in it.
+* Misc File Ops:: Other things you can do on files.
+@end menu
+
+@node File Names, Visiting, Files, Files
+@section File Names
+@cindex file names
+
+ Most Emacs commands that operate on a file require you to specify the
+file name. (Saving and reverting are exceptions; the buffer knows which
+file name to use for them.) File names are specified using the minibuffer
+(@pxref{Minibuffer}). @dfn{Completion} is available, to make it easier to
+specify long file names. @xref{Completion}.
+
+ There is always a @dfn{default file name} which will be used if you type
+just @key{RET}, entering an empty argument. Normally the default file name
+is the name of the file visited in the current buffer; this makes it easy
+to operate on that file with any of the Emacs file commands.
+
+@vindex default-directory
+ Each buffer has a default directory, normally the same as the directory
+of the file visited in that buffer. When Emacs reads a file name, if you
+do not specify a directory, the default directory is used. If you specify
+a directory in a relative fashion, with a name that does not start with a
+slash, it is interpreted with respect to the default directory. The
+default directory is kept in the variable @code{default-directory}, which
+has a separate value in every buffer.
+
+ For example, if the default file name is @file{/u/rms/gnu/gnu.tasks} then
+the default directory is @file{/u/rms/gnu/}. If you type just @samp{foo},
+which does not specify a directory, it is short for @file{/u/rms/gnu/foo}.
+@samp{../.login} would stand for @file{/u/rms/.login}. @samp{new/foo}
+would stand for the filename @file{/u/rms/gnu/new/foo}.
+
+ The command @kbd{M-x pwd} prints the current buffer's default directory,
+and the command @kbd{M-x cd} sets it (to a value read using the
+minibuffer). A buffer's default directory changes only when the @code{cd}
+command is used. A file-visiting buffer's default directory is initialized
+to the directory of the file that is visited there. If a buffer is made
+randomly with @kbd{C-x b}, its default directory is copied from that of the
+buffer that was current at the time.
+
+@vindex insert-default-directory
+ The default directory actually appears in the minibuffer when the
+minibuffer becomes active to read a file name. This serves two purposes:
+it shows you what the default is, so that you can type a relative file name
+and know with certainty what it will mean, and it allows you to edit the
+default to specify a different directory. This insertion of the default
+directory is inhibited if the variable @code{insert-default-directory} is
+set to @code{nil}.
+
+ Note that it is legitimate to type an absolute file name after you enter
+the minibuffer, ignoring the presence of the default directory name as part
+of the text. The final minibuffer contents may look invalid, but that is
+not so. @xref{Minibuffer File}.
+
+ @samp{$} in a file name is used to substitute environment variables. For
+example, if you have used the C shell command @samp{setenv FOO
+rms/hacks} to set up an environment variable named @samp{FOO}, then
+you can use @file{/u/$FOO/test.c} or @file{/u/$@{FOO@}/test.c} as an
+abbreviation for @file{/u/rms/hacks/test.c}. (In the Bourne-Again
+shell, write @code{export FOO=rms/hacks} to define @code{FOO}.) The
+environment variable name consists of all the alphanumeric characters
+after the @samp{$}; alternatively, it may be enclosed in braces after
+the @samp{$}. Note that the @samp{setenv} command affects Emacs only
+if done before Emacs is started.
+@ignore
+In @code{sh}
+
+@example
+FOO=rms/hacks
+export FOO
+@end example
+@end ignore
+
+ To access a file with @samp{$} in its name, type @samp{$$}. This pair
+is converted to a single @samp{$} at the same time as variable substitution
+is performed for single @samp{$}. The Lisp function that performs the
+substitution is called @code{substitute-in-file-name}. The substitution
+is performed only on filenames read as such using the minibuffer.
+
+@node Visiting, Saving, File Names, Files
+@section Visiting Files
+@cindex visiting files
+
+@c WideCommands
+@table @kbd
+@item C-x C-f
+Visit a file (@code{find-file}).
+@item C-x C-v
+Visit a different file instead of the one visited last
+(@code{find-alternate-file}).
+@item C-x 4 C-f
+Visit a file, in another window (@code{find-file-other-window}). Don't
+change this window.
+@end table
+
+@cindex files
+@cindex visiting
+@cindex saving
+ @dfn{Visiting} a file means copying its contents into Emacs where you can
+edit them. Emacs makes a new buffer for each file that you visit. We say
+that the buffer is visiting the file that it was created to hold. Emacs
+constructs the buffer name from the file name by throwing away the
+directory, keeping just the name proper. For example, a file named
+@file{/usr/rms/emacs.tex} would get a buffer named @samp{emacs.tex}. If
+there is already a buffer with that name, a unique name is constructed by
+appending @samp{<2>}, @samp{<3>}, or so on, using the lowest number that
+makes a name that is not already in use.
+
+ Each window's mode line shows the name of the buffer that is being displayed
+in that window, so you can always tell what buffer you are editing.
+
+ The changes you make with Emacs are made in the Emacs buffer. They do
+not take effect in the file that you visited, or any place permanent, until
+you @dfn{save} the buffer. Saving the buffer means that Emacs writes the
+current contents of the buffer into its visited file. @xref{Saving}.
+
+@cindex modified (buffer)
+ If a buffer contains changes that have not been saved, the buffer is said
+to be @dfn{modified}. This is important because it implies that some
+changes will be lost if the buffer is not saved. The mode line displays
+two stars near the left margin if the buffer is modified.
+
+@kindex C-x C-f
+@findex find-file
+ To visit a file, use the command @kbd{C-x C-f} (@code{find-file}). Follow
+the command with the name of the file you wish to visit, terminated by a
+@key{RET}.
+
+ The file name is read using the minibuffer (@pxref{Minibuffer}), with
+defaulting and completion in the standard manner (@pxref{File Names}).
+While in the minibuffer, you can abort @w{@kbd{C-x C-f}} by typing @kbd{C-g}.
+
+ Your confirmation that @kbd{C-x C-f} has completed successfully is the
+appearance of new text on the screen and a new buffer name in the mode
+line. If the specified file does not exist and could not be created, or
+cannot be read, then an error results. The error message is printed in the
+echo area, and includes the file name which Emacs was trying to visit.
+
+ If you visit a file that is already in Emacs, @kbd{C-x C-f} does not make
+another copy. It selects the existing buffer containing that file.
+However, before doing so, it checks that the file itself has not changed
+since you visited or saved it last. If the file has changed, a warning
+message is printed. @xref{Interlocking,,Simultaneous Editing}.
+
+@cindex creating files
+ What if you want to create a file? Just visit it. Emacs prints
+@samp{(New File)} in the echo area, but in other respects behaves as if you
+had visited an existing empty file. If you make any changes and save them,
+the file is created.
+
+@kindex C-x C-v
+@findex find-alternate-file
+ If you visit a nonexistent file unintentionally (because you typed the
+wrong file name), use the @kbd{C-x C-v} (@code{find-alternate-file})
+command to visit the file you wanted. @kbd{C-x C-v} is similar to @kbd{C-x
+C-f}, but it kills the current buffer (after first offering to save it if
+it is modified). @kbd{C-x C-v} is allowed even if the current buffer
+is not visiting a file.
+
+@vindex find-file-run-dired
+ If the file you specify is actually a directory, Dired is called on that
+directory (@pxref{Dired}). This can be inhibited by setting the variable
+@code{find-file-run-dired} to @code{nil}; then it is an error to try to
+visit a directory.
+
+@kindex C-x 4 f
+@findex find-file-other-window
+ @kbd{C-x 4 f} (@code{find-file-other-window}) is like @kbd{C-x C-f}
+except that the buffer containing the specified file is selected in another
+window. The window that was selected before @kbd{C-x 4 f} continues to
+show the same buffer it was already showing. If this command is used when
+only one window is being displayed, that window is split in two, with one
+window showing the same before as before, and the other one showing the
+newly requested file. @xref{Windows}.
+
+@cindex hooks for files
+@vindex find-file-hooks
+@vindex find-file-not-found-hooks
+ There are two hook variables that allow extensions to modify the
+operation of visiting files. Visiting a file that does not exist runs the
+functions in the list @code{find-file-not-found-hooks}; the value of this
+variable is expected to be a list of functions, and the functions are
+called one by one until one of them returns non-@code{nil}. Any visiting
+of a file, whether extant or not, expects @code{find-file-hooks} to
+contain a list of functions and calls them all, one by one. In both cases
+the functions receive no arguments. Visiting a nonexistent file
+runs the @code{find-file-not-found-hooks} first.
+
+ You can put a local variable specification at the end of a file which
+specifies values for Emacs local variables whenever you visit the file.
+@xref{File Variables}.
+
+@node Saving, Reverting, Visiting, Files
+@section Saving Files
+
+ @dfn{Saving} a buffer in Emacs means writing its contents back into the file
+that was visited in the buffer.
+
+@table @kbd
+@item C-x C-s
+Save the current buffer in its visited file (@code{save-buffer}).
+@item C-x s
+Save any or all buffers in their visited files (@code{save-some-buffers}).
+@item M-~
+@c !!! added @* to prevent overfull hbox
+Forget that the current buffer has been changed@*(@code{not-modified}).
+@item C-x C-w
+Save the current buffer in a specified file, and record that file as
+the one visited in the buffer (@code{write-file}).
+@item M-x set-visited-file-name
+Change file the name under which the current buffer will be saved.
+@end table
+
+@kindex C-x C-s
+@findex save-buffer
+ When you wish to save the file and make your changes permanent, type
+@kbd{C-x C-s} (@code{save-buffer}). After saving is finished, @kbd{C-x C-s}
+prints a message such as
+
+@example
+Wrote /u/rms/gnu/gnu.tasks
+@end example
+
+@noindent
+If the selected buffer is not modified (no changes have been made in it
+since the buffer was created or last saved), saving is not really done,
+because it would have no effect. Instead, @kbd{C-x C-s} prints a message
+in the echo area saying
+
+@example
+(No changes need to be written)
+@end example
+
+@kindex C-x s
+@findex save-some-buffers
+ The command @kbd{C-x s} (@code{save-some-buffers}) can save any or all modified
+buffers. First it asks, for each modified buffer, whether to save it.
+These questions should be answered with @kbd{y} or @kbd{n}. @kbd{C-x C-c},
+the key that kills Emacs, invokes @code{save-some-buffers} and therefore
+asks the same questions.
+
+@kindex M-~
+@findex not-modified
+ If you have changed a buffer and do not want the changes to be saved, you
+should take some action to prevent it. Otherwise, each time you use
+@code{save-some-buffers} you are liable to save it by mistake. One thing
+you can do is type @kbd{M-~} (@code{not-modified}), which clears out the
+indication that the buffer is modified. If you do this, none of the save
+commands will believe that the buffer needs to be saved. (@samp{~} is often
+used as a mathematical symbol for `not'; thus @kbd{Meta-~} is `not', metafied.)
+You could also use @code{set-visited-file-name} (see below) to mark the
+buffer as visiting a different file name, one which is not in use for
+anything important. Alternatively, you can undo all the changes made since
+the file was visited or saved, by reading the text from the file again.
+This is called @dfn{reverting}. @xref{Reverting}. You could also undo all
+the changes by repeating the undo command @kbd{C-x u} until you have undone
+all the changes; but this only works if you have not made more changes than
+the undo mechanism can remember.
+
+@findex set-visited-file-name
+ @kbd{M-x set-visited-file-name} alters the name of the file that the
+current buffer is visiting. It reads the new file name using the
+minibuffer. It can be used on a buffer that is not visiting a file, too.
+The buffer's name is changed to correspond to the file it is now visiting
+in the usual fashion (unless the new name is in use already for some other
+buffer; in that case, the buffer name is not changed).
+@code{set-visited-file-name} does not save the buffer in the newly visited
+file; it just alters the records inside Emacs so that, if you save the
+buffer, it will be saved in that file. It also marks the buffer as
+``modified'' so that @kbd{C-x C-s} @i{will} save.
+
+@kindex C-x C-w
+@findex write-file
+ If you wish to mark the buffer as visiting a different file and save it
+right away, use @kbd{C-x C-w} (@code{write-file}). It is precisely
+equivalent to @code{set-visited-file-name} followed by @kbd{C-x C-s}.
+@kbd{C-x C-s} used on a buffer that is not visiting with a file has the
+same effect as @kbd{C-x C-w}; that is, it reads a file name, marks the
+buffer as visiting that file, and saves it there. The default file name in
+a buffer that is not visiting a file is made by combining the buffer name
+with the buffer's default directory.
+
+ If Emacs is about to save a file and sees that the date of the latest
+version on disk does not match what Emacs last read or wrote, Emacs
+notifies you of this fact, because it probably indicates a problem caused
+by simultaneous editing and requires your immediate attention.
+@xref{Interlocking,, Simultaneous Editing}.
+
+@vindex require-final-newline
+ If the variable @code{require-final-newline} is non-@code{nil}, Emacs
+puts a newline at the end of any file that doesn't already end in one,
+every time a file is saved or written.
+
+@vindex write-file-hooks
+ You can implement other ways to write files, and other things to be done
+before writing them, using the hook variable @code{write-file-hooks}. The
+value of this variable should be a list of Lisp functions. When a file is
+to be written, the functions in the list are called, one by one, with no
+arguments. If one of them returns a non-@code{nil} value, Emacs takes this
+to mean that the file has been written in some suitable fashion; the rest
+of the functions are not called, and normal writing is not done.
+
+@menu
+* Backup:: How Emacs saves the old version of your file.
+* Interlocking:: How Emacs protects against simultaneous editing
+ of one file by two users.
+@end menu
+
+@node Backup, Interlocking, Saving, Saving
+@subsection Backup Files
+@cindex backup file
+@vindex make-backup-files
+
+ Because Unix does not provide version numbers in file names, rewriting a
+file in Unix automatically destroys all record of what the file used to
+contain. Thus, saving a file from Emacs throws away the old contents of
+the file---or it would, except that Emacs carefully copies the old contents
+to another file, called the @dfn{backup} file, before actually saving
+(provided the variable @code{make-backup-files} is non-@code{nil};
+backup files are not written if this variable is @code{nil}).
+
+ At your option, Emacs can keep either a single backup file or a series of
+numbered backup files for each file that you edit.
+
+ Emacs makes a backup for a file only the first time the file is saved
+from one buffer. No matter how many times you save a file, its backup file
+continues to contain the contents from before the file was visited.
+Normally this means that the backup file contains the contents from before
+the current editing session; however, if you kill the buffer and then visit
+the file again, a new backup file will be made by the next save.
+
+@menu
+* Names: Backup Names. How backup files are named;
+ Choosing single or numbered backup files.
+* Deletion: Backup Deletion. Emacs deletes excess numbered backups.
+* Copying: Backup Copying. Backups can be made by copying or renaming.
+@end menu
+
+@node Backup Names, Backup Deletion, Backup, Backup
+@subsubsection Single or Numbered Backups
+
+ If you choose to have a single backup file (this is the default),
+the backup file's name is constructed by appending @samp{~} to the
+file name being edited; thus, the backup file for @file{eval.c} would
+be @file{eval.c~}.
+
+ If you choose to have a series of numbered backup files, backup file
+names are made by appending @samp{.~}, the number, and another @samp{~} to
+the original file name. Thus, the backup files of @file{eval.c} would be
+called @file{eval.c.~1~}, @file{eval.c.~2~}, and so on, through names
+like @file{eval.c.~259~} and beyond.
+
+ If protection stops you from writing backup files under the usual names,
+the backup file is written as @file{%backup%~} in your home directory.
+Only one such file can exist, so only the most recently made such backup is
+available.
+
+@vindex version-control
+ The choice of single backup or numbered backups is controlled by the
+variable @code{version-control}. Its possible values are
+
+@table @code
+@item t
+Make numbered backups.
+@item nil
+Make numbered backups for files that have numbered backups already.
+Otherwise, make single backups.
+@item never
+Do not in any case make numbered backups; always make single backups.
+@end table
+
+@noindent
+@code{version-control} may be set locally in an individual buffer to
+control the making of backups for that buffer's file. For example,
+Rmail mode locally sets @code{version-control} to @code{never} to make sure
+that there is only one backup for an Rmail file. @xref{Locals}.
+
+@node Backup Deletion, Backup Copying, Backup Names, Backup
+@subsubsection Automatic Deletion of Backups
+
+@cindex backups, automatic deleting of
+@cindex versions, keeping old
+@vindex kept-old-versions
+@vindex kept-new-versions
+ To prevent unlimited consumption of disk space, Emacs can delete numbered
+backup versions automatically. Generally Emacs keeps the first few backups
+and the latest few backups, deleting any in between. This happens every
+time a new backup is made. The two variables that control the deletion are
+@code{kept-old-versions} and @code{kept-new-versions}. Their values are, respectively
+the number of oldest (lowest-numbered) backups to keep and the number of
+newest (highest-numbered) ones to keep, each time a new backup is made.
+Recall that these values are used just after a new backup version is made;
+that newly made backup is included in the count in @code{kept-new-versions}.
+By default, both variables are 2.
+
+@vindex trim-versions-without-asking
+ If @code{trim-versions-without-asking} is non-@code{nil}, the excess
+middle versions are deleted without a murmur. If it is @code{nil}, the
+default, then you are asked whether the excess middle versions should
+really be deleted.
+
+ Dired's @kbd{.} (Period) command can also be used to delete old versions.
+@xref{Dired}.
+
+@node Backup Copying,, Backup Deletion, Backup
+@subsubsection Copying vs. Renaming
+@c !!!! zzzz change back after fixref
+@c subsubsection Copying vs.@: Renaming
+
+ Backup files can be made by copying the old file or by renaming it. This
+makes a difference when the old file has multiple names. If the old file
+is renamed into the backup file, then the alternate names become names for
+the backup file. If the old file is copied instead, then the alternate
+names remain names for the file that you are editing, and the contents
+accessed by those names will be the new contents.
+
+ The method of making a backup file may also affect the file's owner
+and group. If copying is used, these do not change. If renaming is used,
+you become the file's owner, and the file's group becomes the default
+(different operating systems have different defaults for the group).
+
+ Having the owner change is usually a good idea, because then the owner
+always shows who last edited the file. Also, the owners of the backups
+show who produced those versions. Occasionally there is a file whose
+owner should not change; it is a good idea for such files to contain
+local variable lists to set @code{backup-by-copying-when-mismatch} for
+them alone (@pxref{File Variables}).
+
+@vindex backup-by-copying
+@vindex backup-by-copying-when-linked
+@vindex backup-by-copying-when-mismatch
+ The choice of renaming or copying is controlled by three variables.
+Normally, renaming is done. If the variable @code{backup-by-copying} is
+non-@code{nil}, copying is used. Otherwise, if the variable
+@code{backup-by-copying-when-linked} is non-@code{nil}, then copying is
+done for files that have multiple names, but renaming may still done when
+the file being edited has only one name. If the variable
+@code{backup-by-copying-when-mismatch} is non-@code{nil}, then copying is
+done if renaming would cause the file's owner or group to change. @refill
+
+@node Interlocking,,Backup,Saving
+@subsection Protection against Simultaneous Editing
+
+@cindex buffer locking
+@cindex locking buffers
+@cindex interlocking buffers
+@cindex file dates
+@cindex simultaneous editing
+ Simultaneous editing occurs when two users visit the same file, both make
+changes, and then both save them. If nobody were informed that this was
+happening, whichever user saved first would later find that his changes
+were lost. On some systems, Emacs notices immediately when the second user
+starts to change the file, and issues an immediate warning. When this is
+not possible, or if the second user has gone on to change the file despite
+the warning, Emacs checks later when the file is saved, and issues a second
+warning when a user is about to overwrite a file containing another user's
+changes. If the editing user takes the proper corrective action at this
+point, he can prevent actual loss of work.
+
+@findex ask-user-about-lock
+ When you make the first modification in an Emacs buffer that is visiting
+a file, Emacs records that you have locked the file. (It does this by
+writing another file in a directory reserved for this purpose.) The lock
+is removed when you save the changes. The idea is that the file is locked
+whenever the buffer is modified. If you begin to modify the buffer while
+the visited file is locked by someone else, this constitutes a collision,
+and Emacs asks you what to do. It does this by calling the Lisp function
+@code{ask-user-about-lock}, which you can redefine for the sake of
+customization. The standard definition of this function asks you a
+question and accepts three possible answers:
+
+@table @kbd
+@item s
+Steal the lock. Whoever was already changing the file loses the lock,
+and you gain the lock.
+@item p
+Proceed. Go ahead and edit the file despite its being locked by someone else.
+@item q
+Quit. This causes an error (@code{file-locked}) and the modification you
+were trying to make in the buffer does not actually take place.
+@end table
+
+ Note that locking works on the basis of a file name; if a file has
+multiple names, Emacs does not realize that the two names are the same file
+and cannot prevent two user from editing it simultaneously under different
+names. However, basing locking on names means that Emacs can interlock the
+editing of new files that will not really exist until they are saved.
+
+ Some systems are not configured to allow Emacs to make locks. On
+these systems, Emacs cannot detect trouble in advance, but it still can
+detect it in time to prevent you from overwriting someone else's changes.
+
+ Every time Emacs saves a buffer, it first checks the last-modification
+date of the existing file on disk to see that it has not changed since the
+file was last visited or saved. If the date does not match, it implies
+that changes were made in the file in some other way, and these changes are
+about to be lost if Emacs actually does save. To prevent this, Emacs
+prints a warning message and asks for confirmation before saving.
+Occasionally you will know why the file was changed and know that it does
+not matter; then you can answer @kbd{yes} and proceed. Otherwise, you should
+cancel the save with @kbd{C-g} and investigate the situation.
+
+ The first thing you should do when notified that simultaneous editing has
+already taken place is to list the directory with @kbd{C-u C-x C-d}
+(@pxref{ListDir,,Directory Listing}). This will show the file's
+current author. You should attempt to contact that person to warn him
+or her not to continue editing. Often the next step is to save the
+contents of your Emacs buffer under a different name, and use
+@code{diff} to compare the two files.@refill
+
+ Simultaneous editing checks are also made when you visit with @kbd{C-x
+C-f} a file that is already visited and when you start to modify a file.
+This is not strictly necessary, but it can cause you to find out about the
+problem earlier, when perhaps correction takes less work.
+
+@node Reverting, Auto Save, Saving, Files
+@section Reverting a Buffer
+@findex revert-buffer
+@cindex drastic changes
+
+ If you have made extensive changes to a file and then change your mind
+about them, you can get rid of them by reading in the previous version of
+the file. To do this, use @kbd{M-x revert-buffer}, which operates on the
+current buffer. Since this is a very dangerous thing to do, you must
+confirm it with @kbd{yes}.
+
+ If the current buffer has been auto-saved more recently than it has been
+saved for real, @code{revert-buffer} offers to read the auto save file
+instead of the visited file (@pxref{Auto Save}). This question comes
+before the usual request for confirmation, and demands @kbd{y} or @kbd{n}
+as an answer. If you have started to type @kbd{yes} for confirmation
+without realizing that the other question was going to be asked, the
+@kbd{y} will answer that question, but the @kbd{es} will not be valid
+confirmation. So you will have a chance to cancel the operation with
+@kbd{C-g} and try it again with the answers that you really intend.
+
+ @code{revert-buffer} keeps point at the same distance (measured in
+characters) from the beginning of the file. If the file was edited only
+slightly, you will be at approximately the same piece of text after
+reverting as before. If you have made drastic changes, the same value of
+point in the old file may address a totally different piece of text.
+
+ A buffer reverted from its visited file is marked ``not modified'' until
+another change is made.
+
+ Some kinds of buffers whose contents reflect data bases other than files,
+such as Dired buffers, can also be reverted. For them, reverting means
+recalculating their contents from the appropriate data base. Buffers
+created randomly with @kbd{C-x b} cannot be reverted; @code{revert-buffer}
+reports an error when asked to do so.
+
+@node Auto Save, ListDir, Reverting, Files
+@section Auto-Saving: Protection Against Disasters
+@cindex Auto-Save mode
+@cindex crashes
+
+ Emacs saves all the visited files from time to time (based on counting
+your keystrokes) without being asked. This is called @dfn{auto-saving}.
+It prevents you from losing more than a limited amount of work if the
+system crashes.
+
+ When Emacs determines that it is time for auto-saving, each buffer is
+considered, and is auto-saved if auto-saving is turned on for it and it has
+been changed since the last time it was auto-saved. If any auto-saving is
+done, the message @samp{Auto-saving...} is displayed in the echo area until
+auto-saving is finished. Errors occurring during auto-saving are caught
+so that they do not interfere with the execution of commands you have been
+typing.
+
+@menu
+* Files: Auto Save Files.
+* Control: Auto Save Control.
+* Recover:: Recovering text from auto-save files.
+@end menu
+
+@node Auto Save Files, Auto Save Control, Auto Save, Auto Save
+@subsection Auto-Save Files
+
+ Auto-saving does not normally save in the files that you visited, because
+it can be very undesirable to save a program that is in an inconsistent
+state when you have made half of a planned change. Instead, auto-saving
+is done in a different file called the @dfn{auto-save file}, and the
+visited file is changed only when you request saving explicitly (such as
+with @kbd{C-x C-s}).
+
+ Normally, the auto-save file name is made by appending @samp{#} to the
+front and rear of the visited file name. Thus, a buffer visiting file
+@file{foo.c} would be auto-saved in a file @file{#foo.c#}. Most buffers
+that are not visiting files are auto-saved only if you request it
+explicitly; when they are auto-saved, the auto-save file name is made by
+appending @samp{#%} to the front and @samp{#} to the rear of buffer name.
+For example, the @samp{*mail*} buffer in which you compose messages to be
+sent is auto-saved in a file named @file{#%*mail*#}. Auto-save file names
+are made this way unless you reprogram parts of Emacs to do something
+different (the functions @code{make-auto-save-file-name} and
+@code{auto-save-file-name-p}). The file name to be used for auto-saving
+in a buffer is calculated when auto-saving is turned on in that buffer.
+
+@vindex auto-save-visited-file-name
+ If you want auto-saving to be done in the visited file, set the variable
+@code{auto-save-visited-file-name} to be non-@code{nil}. In this mode,
+there is really no difference between auto-saving and explicit saving.
+
+@vindex delete-auto-save-files
+ A buffer's auto-save file is deleted when you save the buffer in its
+visited file. To inhibit this, set the variable @code{delete-auto-save-files}
+to @code{nil}. Changing the visited file name with @kbd{C-x C-w} or
+@code{set-visited-file-name} renames any auto-save file to go with
+the new visited name.
+
+@node Auto Save Control, Recover, Auto Save Files, Auto Save
+@subsection Controlling Auto-Saving
+
+@vindex auto-save-default
+@findex auto-save-mode
+ Each time you visit a file, auto-saving is turned on for that file's
+buffer if the variable @code{auto-save-default} is non-@code{nil} (but not
+in batch mode; @pxref{Entering Emacs}). The default for this variable is
+@code{t}, so auto-saving is the usual practice for file-visiting buffers.
+Auto-saving can be turned on or off for any existing buffer with the
+command @kbd{M-x auto-save-mode}. Like other minor mode commands, @kbd{M-x
+auto-save-mode} turns auto-saving on with a positive argument, off with a
+zero or negative argument; with no argument, it toggles.
+
+@vindex auto-save-interval
+@findex do-auto-save
+ Emacs does auto-saving periodically based on counting how many characters
+you have typed since the last time auto-saving was done. The variable
+@code{auto-save-interval} specifies how many characters there are between
+auto-saves. By default, it is 300. Emacs also auto-saves whenever you
+call the function @code{do-auto-save}.
+
+ Emacs also does auto-saving whenever it gets a fatal error. This
+includes killing the Emacs job with a shell command such as @code{kill
+%emacs}, or disconnecting a phone line or network connection.
+
+@node Recover,, Auto Save Control, Auto Save
+@subsection Recovering Data from Auto-Saves
+
+@findex recover-file
+ The way to use the contents of an auto-save file to recover from a loss
+of data is with the command @kbd{M-x recover-file @key{RET} @var{file}
+@key{RET}}. This visits @var{file} and then (after your confirmation)
+restores the contents from its auto-save file @file{#@var{file}#}. You
+can then save with @kbd{C-x C-s} to put the recovered text into @var{file}
+itself. For example, to recover file @file{foo.c} from its auto-save file
+@file{#foo.c#}, do:@refill
+
+@example
+M-x recover-file @key{RET} foo.c @key{RET}
+C-x C-s
+@end example
+
+ Before asking for confirmation, @kbd{M-x recover-file} displays a
+directory listing describing the specified file and the auto-save file,
+so you can compare their sizes and dates. If the auto-save file
+is older, @kbd{M-x recover-file} does not offer to read it.
+
+ Auto-saving is disabled by @kbd{M-x recover-file} because using
+this command implies that the auto-save file contains valuable data
+from a past session. If you save the data in the visited file and
+then go on to make new changes, you should turn auto-saving back on
+with @kbd{M-x auto-save-mode}.
+
+@node ListDir, Dired, Auto Save, Files
+@section Listing a File Directory
+
+@cindex file directory
+@cindex directory listing
+@cindex listing a directory
+ Files are classified by Unix into @dfn{directories}. A @dfn{directory
+listing} is a list of all the files in a directory. Emacs provides
+directory listings in brief format (file names only) and verbose format
+(sizes, dates, and authors included).
+
+@table @kbd
+@item C-x C-d @var{dir-or-pattern}
+Print a brief directory listing (@code{list-directory}).
+@item C-u C-x C-d @var{dir-or-pattern}
+Print a verbose directory listing.
+@end table
+
+@findex list-directory
+@kindex C-x C-d
+ The command to print a directory listing is @kbd{C-x C-d} (@code{list-directory}).
+It reads using the minibuffer a file name which is either a directory to be
+listed or a wildcard-containing pattern for the files to be listed. For
+example,
+
+@example
+C-x C-d /u2/emacs/etc @key{RET}
+@end example
+
+@noindent
+lists all the files in directory @file{/u2/emacs/etc}. An example of
+specifying a file name pattern is
+
+@example
+C-x C-d /u2/emacs/src/*.c @key{RET}
+@end example
+
+ Normally, @kbd{C-x C-d} prints a brief directory listing containing just
+file names. A numeric argument (regardless of value) tells it to print a
+verbose listing (like @code{ls -l}).
+
+@vindex list-directory-brief-switches
+@vindex list-directory-verbose-switches
+ The text of a directory listing is obtained by running @code{ls} in an
+inferior process. Two Emacs variables control the switches passed to
+@code{ls}: @code{list-directory-brief-switches} is a string giving the
+switches to use in brief listings (@code{"-CF"} by default), and
+@code{list-directory-verbose-switches} is a string giving the switches to
+use in a verbose listing (@code{"-l"} by default).
+
+@node Dired, Misc File Ops, ListDir, Files
+@section Dired, the Directory Editor
+@cindex Dired
+@cindex deletion (of files)
+
+ Dired makes it easy to delete or visit many of the files in a single
+directory at once. It makes an Emacs buffer containing a listing of the
+directory. You can use the normal Emacs commands to move around in this
+buffer, and special Dired commands to operate on the files.
+
+@menu
+* Enter: Dired Enter. How to invoke Dired.
+* Edit: Dired Edit. Editing the Dired buffer.
+* Deletion: Dired Deletion. Deleting files with Dired.
+* Immed: Dired Immed. Other file operations through Dired.
+@end menu
+
+@node Dired Enter, Dired Edit, Dired, Dired
+@subsection Entering Dired
+
+@findex dired
+@kindex C-x d
+@cindex Dired mode
+@vindex dired-listing-switches
+ To invoke dired, do @kbd{C-x d} or @kbd{M-x dired}. The command reads a
+directory name or wildcard file name pattern as a minibuffer argument just
+like the @code{list-directory} command, @kbd{C-x C-d}. Where @code{dired}
+differs from @code{list-directory} is in naming the buffer after the
+directory name or the wildcard pattern used for the listing, and putting
+the buffer into Dired mode so that the special commands of Dired are
+available in it. The variable @code{dired-listing-switches} is a string
+used as an argument to @code{ls} in making the directory; this string
+@i{must} contain @samp{-l}.
+
+@findex dired-other-window
+@kindex C-x 4 d
+ To display the Dired buffer in another window rather than in the selected
+window, use @kbd{C-x 4 d} (@code{dired-other-window)} instead of @kbd{C-x d}.
+
+@node Dired Edit, Dired Deletion, Dired Enter, Dired
+@subsection Editing in Dired
+
+ Once the Dired buffer exists, you can switch freely between it and other
+Emacs buffers. Whenever the Dired buffer is selected, certain special
+commands are provided that operate on files that are listed. The Dired
+buffer is ``read-only'', and inserting text in it is not useful, so
+ordinary printing characters such as @kbd{d} and @kbd{x} are used for Dired
+commands. Most Dired commands operate on the file described by the line
+that point is on. Some commands perform operations immediately; others
+``flag'' the file to be operated on later.
+
+ Most Dired commands that operate on the current line's file also treat a
+numeric argument as a repeat count, meaning to act on the files of the
+next few lines. A negative argument means to operate on the files of the
+preceding lines, and leave point on the first of those lines.
+
+ All the usual Emacs cursor motion commands are available in Dired
+buffers. Some special purpose commands are also provided. The keys
+@kbd{C-n} and @kbd{C-p} are redefined so that they try to position
+the cursor at the beginning of the filename on the line, rather than
+at the beginning of the line.
+
+ For extra convenience, @key{SPC} and @kbd{n} in Dired are equivalent to
+@kbd{C-n}. @kbd{p} is equivalent to @kbd{C-p}. Moving by lines is done so
+often in Dired that it deserves to be easy to type. @key{DEL} (move up and
+unflag) is often useful simply for moving up.@refill
+
+ The @kbd{g} command in Dired runs @code{revert-buffer} to reinitialize
+the buffer from the actual disk directory and show any changes made in the
+directory by programs other than Dired. All deletion flags in the Dired
+buffer are lost when this is done.
+
+@node Dired Deletion, Dired Immed, Dired Edit, Dired
+@subsection Deleting Files with Dired
+
+ The primary use of Dired is to flag files for deletion and then delete
+them.
+
+@table @kbd
+@item d
+Flag this file for deletion.
+@item u
+Remove deletion-flag on this line.
+@item @key{DEL}
+Remove deletion-flag on previous line, moving point to that line.
+@item x
+Delete the files that are flagged for deletion.
+@item #
+Flag all auto-save files (files whose names start and end with @samp{#})
+for deletion (@pxref{Auto Save}).
+@item ~
+Flag all backup files (files whose names end with @samp{~}) for deletion
+(@pxref{Backup}).
+@item .@: @r{(Period)}
+Flag excess numeric backup files for deletion. The oldest and newest
+few backup files of any one file are exempt; the middle ones are flagged.
+@end table
+
+ You can flag a file for deletion by moving to the line describing the
+file and typing @kbd{d} or @kbd{C-d}. The deletion flag is visible as a
+@samp{D} at the beginning of the line. Point is moved to the beginning of
+the next line, so that repeated @kbd{d} commands flag successive files.
+
+ The files are flagged for deletion rather than deleted immediately to
+avoid the danger of deleting a file accidentally. Until you direct Dired
+to delete the flagged files, you can remove deletion flags using the
+commands @kbd{u} and @key{DEL}. @kbd{u} works just like @kbd{d}, but
+removes flags rather than making flags. @key{DEL} moves upward, removing
+flags; it is like @kbd{u} with numeric argument automatically negated.
+
+ To delete the flagged files, type @kbd{x}. This command first displays a
+list of all the file names flagged for deletion, and requests confirmation
+with @kbd{yes}. Once you confirm, all the flagged files are deleted, and their
+lines are deleted from the text of the Dired buffer. The shortened Dired
+buffer remains selected. If you answer @kbd{no} or quit with @kbd{C-g}, you
+return immediately to Dired, with the deletion flags still present and no
+files actually deleted.
+
+ The @kbd{#}, @kbd{~} and @kbd{.} commands flag many files for
+deletion, based on their names. These commands are useful precisely
+because they do not actually delete any files; you can remove the
+deletion flags from any flagged files that you really wish to keep.@refill
+
+ @kbd{#} flags for deletion all files that appear to have been made by
+auto-saving (that is, files whose names begin and end with @samp{#}).
+@kbd{~} flags for deletion all files that appear to have been made as
+backups for files that were edited (that is, files whose names end with
+@samp{~}).
+
+@vindex dired-kept-versions
+ @kbd{.} (Period) flags just some of the backup files for deletion: only
+numeric backups that are not among the oldest few nor the newest few
+backups of any one file. Normally @code{dired-kept-versions} (not
+@code{kept-new-versions}; that applies only when saving) specifies the
+number of newest versions of each file to keep, and
+@code{kept-old-versions} specifies the number of oldest versions to keep.
+Period with a positive numeric argument, as in @kbd{C-u 3 .}, specifies the
+number of newest versions to keep, overriding @code{dired-kept-versions}.
+A negative numeric argument overrides @code{kept-old-versions}, using minus
+the value of the argument to specify the number of oldest versions of each
+file to keep.@refill
+
+@node Dired Immed,, Dired Deletion, Dired
+@subsection Immediate File Operations in Dired
+
+ Some file operations in Dired take place immediately when they are
+requested.
+
+@table @kbd
+@item c
+Copies the file described on the current line. You must supply a file name
+to copy to, using the minibuffer.
+@item f
+Visits the file described on the current line. It is just like typing
+@kbd{C-x C-f} and supplying that file name. If the file on this line is a
+subdirectory, @kbd{f} actually causes Dired to be invoked on that
+subdirectory. @xref{Visiting}.
+@item o
+Like @kbd{f}, but uses another window to display the file's buffer. The
+Dired buffer remains visible in the first window. This is like using
+@kbd{C-x 4 C-f} to visit the file. @xref{Windows}.
+@item r
+Renames the file described on the current line. You must supply a file
+name to rename to, using the minibuffer.
+@item v
+Views the file described on this line using @kbd{M-x view-file}. Viewing a
+file is like visiting it, but is slanted toward moving around in the file
+conveniently and does not allow changing the file. @xref{Misc File
+Ops,View File}. Viewing a file that is a directory runs Dired on that
+directory.@refill
+@end table
+
+@node Misc File Ops,, Dired, Files
+@section Miscellaneous File Operations
+
+ Emacs has commands for performing many other operations on files.
+All operate on one file; they do not accept wild card file names.
+
+@findex view-file
+@cindex viewing
+ @kbd{M-x view-file} allows you to scan or read a file by sequential
+screenfuls. It reads a file name argument using the minibuffer. After
+reading the file into an Emacs buffer, @code{view-file} reads and displays
+one windowful. You can then type @key{SPC} to scroll forward one windowful,
+or @key{DEL} to scroll backward. Various other commands are provided for
+moving around in the file, but none for changing it; type @kbd{C-h} while
+viewing for a list of them. They are mostly the same as normal Emacs
+cursor motion commands. To exit from viewing, type @kbd{C-c}.
+
+@findex insert-file
+ @kbd{M-x insert-file} inserts a copy of the contents of the specified
+file into the current buffer at point, leaving point unchanged before the
+contents and the mark after them. @xref{Mark}.
+
+@findex write-region
+@findex append-to-file
+ @kbd{M-x write-region} is the inverse of @kbd{M-x insert-file}; it copies
+the contents of the region into the specified file. @kbd{M-x append-to-file}
+adds the text of the region to the end of the specified file.
+
+@findex delete-file
+@cindex deletion (of files)
+ @kbd{M-x delete-file} deletes the specified file, like the @code{rm}
+command in the shell. If you are deleting many files in one directory, it
+may be more convenient to use Dired (@pxref{Dired}).
+
+@findex rename-file
+ @kbd{M-x rename-file} reads two file names @var{old} and @var{new} using
+the minibuffer, then renames file @var{old} as @var{new}. If a file named
+@var{new} already exists, you must confirm with @kbd{yes} or renaming is not
+done; this is because renaming causes the old meaning of the name @var{new}
+to be lost. If @var{old} and @var{new} are on different file systems, the
+file @var{old} is copied and deleted.
+
+@findex add-name-to-file
+ The similar command @kbd{M-x add-name-to-file} is used to add an
+additional name to an existing file without removing its old name.
+The new name must belong on the same file system that the file is on.
+
+@findex copy-file
+@cindex copying files
+ @kbd{M-x copy-file} reads the file @var{old} and writes a new file named
+@var{new} with the same contents. Confirmation is required if a file named
+@var{new} already exists, because copying has the consequence of overwriting
+the old contents of the file @var{new}.
+
+@findex make-symbolic-link
+ @kbd{M-x make-symbolic-link} reads two file names @var{old} and @var{linkname},
+and then creates a symbolic link named @var{linkname} and pointing at @var{old}.
+The effect is that future attempts to open file @var{linkname} will refer
+to whatever file is named @var{old} at the time the opening is done, or
+will get an error if the name @var{old} is not in use at that time.
+Confirmation is required when creating the link if @var{linkname} is in
+use. Note that not all systems support symbolic links.
+
+@node Buffers, Windows, Files, Top
+@chapter Using Multiple Buffers
+
+@cindex buffers
+ The text you are editing in Emacs resides in an object called a
+@dfn{buffer}. Each time you visit a file, a buffer is created to hold the
+file's text. Each time you invoke Dired, a buffer is created to hold the
+directory listing. If you send a message with @kbd{C-x m}, a buffer named
+@samp{*mail*} is used to hold the text of the message. When you ask for a
+command's documentation, that appears in a buffer called @file{*Help*}.
+
+@cindex selected buffer
+@cindex current buffer
+ At any time, one and only one buffer is @dfn{selected}. It is also
+called the @dfn{current buffer}. Often we say that a command operates on
+``the buffer'' as if there were only one; but really this means that the
+command operates on the selected buffer (most commands do).
+
+ When Emacs makes multiple windows, each window has a chosen buffer which
+is displayed there, but at any time only one of the windows is selected and
+its chosen buffer is the selected buffer. Each window's mode line displays
+the name of the buffer that the window is displaying (@pxref{Windows}).
+
+ Each buffer has a name, which can be of any length, and you can select
+any buffer by giving its name. Most buffers are made by visiting files,
+and their names are derived from the files' names. But you can also create
+an empty buffer with any name you want. A newly started Emacs has a buffer
+named @samp{*scratch*} which can be used for evaluating Lisp expressions in
+Emacs. The distinction between upper and lower case matters in buffer
+names.
+
+ Each buffer records individually what file it is visiting, whether it is
+modified, and what major mode and minor modes are in effect in it
+(@pxref{Major Modes}). Any Emacs variable can be made @dfn{local to} a
+particular buffer, meaning its value in that buffer can be different from
+the value in other buffers. @xref{Locals}.
+
+@menu
+* Select Buffer:: Creating a new buffer or reselecting an old one.
+* List Buffers:: Getting a list of buffers that exist.
+* Misc Buffer:: Renaming; changing read-onliness; copying text.
+* Kill Buffer:: Killing buffers you no longer need.
+* Several Buffers:: How to go through the list of all buffers
+ and operate variously on several of them.
+@end menu
+
+@node Select Buffer, List Buffers, Buffers, Buffers
+@section Creating and Selecting Buffers
+@cindex change buffers
+@cindex switch buffers
+
+@table @kbd
+@item C-x b @var{buffer} @key{RET}
+Select or create a buffer named @var{buffer} (@code{switch-to-buffer}).
+@item C-x 4 b @var{buffer} @key{RET}
+Similar, but select a buffer named @var{buffer} in another window
+(@code{switch-to-buffer-other-window}).
+@end table
+
+@kindex C-x 4 b
+@c @findex switch-to-buffer-other-window
+@kindex C-x b
+@findex switch-to-buffer
+ To select the buffer named @var{bufname}, type @kbd{C-x b @var{bufname}
+@key{RET}}. This is the command @code{switch-to-buffer} with argument
+@var{bufname}. You can use completion on an abbreviation for the buffer
+name you want (@pxref{Completion}). An empty argument to @kbd{C-x b}
+specifies the most recently selected buffer that is not displayed in any
+window.@refill
+
+ Most buffers are created by visiting files, or by Emacs commands that
+want to display some text, but you can also create a buffer explicitly by
+typing @kbd{C-x b @var{bufname} @key{RET}}. This makes a new, empty buffer which
+is not visiting any file, and selects it for editing. Such buffers are
+used for making notes to yourself. If you try to save one, you are asked
+for the file name to use. The new buffer's major mode is determined by the
+value of @code{default-major-mode} (@pxref{Major Modes}).
+
+ Note that @kbd{C-x C-f}, and any other command for visiting a file, can
+also be used to switch buffers. @xref{Visiting}.
+
+@node List Buffers, Misc Buffer, Select Buffer, Buffers
+@section Listing Existing Buffers
+
+@table @kbd
+@item C-x C-b
+List the existing buffers (@code{list-buffers}).
+@end table
+
+@kindex C-x C-b
+@findex list-buffers
+ To print a list of all the buffers that exist, type @kbd{C-x C-b}.
+Each line in the list shows one buffer's name, major mode and visited file.
+@samp{*} at the beginning of a line indicates the buffer is ``modified''.
+If several buffers are modified, it may be time to save some with @kbd{C-x
+s} (@pxref{Saving}). @samp{%} indicates a read-only buffer. @samp{.}
+marks the selected buffer. Here is an example of a buffer list:@refill
+
+@smallexample
+ MR Buffer Size Mode File
+ -- ------ ---- ---- ----
+.* emacs.tex 383402 Texinfo /u2/emacs/man/emacs.tex
+ *Help* 1287 Fundamental
+ files.el 23076 Emacs-Lisp /u2/emacs/lisp/files.el
+ % RMAIL 64042 RMAIL /u/rms/RMAIL
+ *% man 747 Dired
+ net.emacs 343885 Fundamental /u/rms/net.emacs
+ fileio.c 27691 C /u2/emacs/src/fileio.c
+ NEWS 67340 Text /u2/emacs/etc/NEWS
+ *scratch* 0 Lisp Interaction
+@end smallexample
+
+@noindent
+Note that the buffer @file{*Help*} was made by a help request; it is not
+visiting any file. The buffer @file{man} was made by Dired on the
+directory @file{/u2/emacs/man/}.
+
+@node Misc Buffer, Kill Buffer, List Buffers, Buffers
+@section Miscellaneous Buffer Operations
+
+@table @kbd
+@item C-x C-q
+Toggle read-only status of buffer (@code{toggle-read-only}).
+@item M-x rename-buffer
+Change the name of the current buffer.
+@item M-x view-buffer
+Scroll through a buffer.
+@end table
+
+@cindex read-only buffer
+@kindex C-x C-q
+@findex toggle-read-only
+@vindex buffer-read-only
+ A buffer can be @dfn{read-only}, which means that commands to change its
+text are not allowed. Normally, read-only buffers are made by subsystems
+such as Dired and Rmail that have special commands to operate on the text;
+a read-only buffer is also made if you visit a file that is protected so
+you cannot write it. If you wish to make changes in a read-only buffer,
+use the command @kbd{C-x C-q} (@code{toggle-read-only}). It makes a
+read-only buffer writable, and makes a writable buffer read-only. This
+works by setting the variable @code{buffer-read-only}, which has a local
+value in each buffer and makes the buffer read-only if its value is
+non-@code{nil}.
+
+@findex rename-buffer
+ @kbd{M-x rename-buffer} changes the name of the current buffer. Specify
+the new name as a minibuffer argument. There is no default. If you
+specify a name that is in use for some other buffer, an error happens and
+no renaming is done.
+
+@findex view-buffer
+@cindex View mode
+ @kbd{M-x view-buffer} is much like @kbd{M-x view-file} (@pxref{Misc File Ops})
+except that it examines an already existing Emacs buffer. View mode
+provides commands for scrolling through the buffer conveniently but not
+for changing it. When you exit View mode, the value of point that resulted
+from your perusal remains in effect.
+
+ The commands @kbd{C-x a} (@code{append-to-buffer}) and @kbd{M-x
+insert-buffer} can be used to copy text from one buffer to another.
+@xref{Accumulating Text}.@refill
+
+@node Kill Buffer, Several Buffers, Misc Buffer, Buffers
+@section Killing Buffers
+
+ After you use Emacs for a while, you may accumulate a large number of
+buffers. You may then find it convenient to eliminate the ones you no
+longer need. There are several commands provided for doing this.
+
+@c WideCommands
+@table @kbd
+@item C-x k
+Kill a buffer, specified by name (@code{kill-buffer}).
+@item M-x kill-some-buffers
+Offer to kill each buffer, one by one.
+@end table
+
+@findex kill-buffer
+@findex kill-some-buffers
+@kindex C-x k
+
+ @kbd{C-x k} (@code{kill-buffer}) kills one buffer, whose name you specify
+in the minibuffer. The default, used if you type just @key{RET} in the
+minibuffer, is to kill the current buffer. If the current buffer is
+killed, another buffer is selected; a buffer that has been selected
+recently but does not appear in any window now is chosen to be selected.
+If the buffer being killed is modified (has unsaved editing) then you are
+asked to confirm with @kbd{yes} before the buffer is killed.
+
+ The command @kbd{M-x kill-some-buffers} asks about each buffer, one by
+one. An answer of @kbd{y} means to kill the buffer. Killing the current
+buffer or a buffer containing unsaved changes selects a new buffer or asks
+for confirmation just like @code{kill-buffer}.
+
+@node Several Buffers,, Kill Buffer, Buffers
+@section Operating on Several Buffers
+@cindex buffer menu
+
+ The @dfn{buffer-menu} facility is like a ``Dired for buffers''; it allows
+you to request operations on various Emacs buffers by editing an Emacs
+buffer containing a list of them. You can save buffers, kill them
+(here called @dfn{deleting} them, for consistency with Dired), or display
+them.
+
+@table @kbd
+@item M-x buffer-menu
+Begin editing a buffer listing all Emacs buffers.
+@end table
+
+@findex buffer-menu
+@cindex Buffer Menu mode
+ The command @code{buffer-menu} writes a list of all Emacs buffers into
+the buffer @samp{*Buffer List*}, and selects that buffer in Buffer Menu
+mode. The buffer is read-only, and can only be changed through the special
+commands described in this section. Most of these commands are graphic
+characters. The usual Emacs cursor motion commands can be used in the
+@samp{*Buffer List*} buffer. The following special commands apply to the
+buffer described on the current line.
+
+@table @kbd
+@item d
+Request to delete (kill) the buffer, then move down. The request
+shows as a @samp{D} on the line, before the buffer name. Requested
+deletions take place when the @kbd{x} command is used.
+@item k
+Synonym for @kbd{d}.
+@item C-d
+Like @kbd{d} but move up afterwards instead of down.
+@item s
+Request to save the buffer. The request shows as an @samp{S} on the
+line. Requested saves take place when the @kbd{x} command is used.
+You may request both saving and deletion for the same buffer.
+@item ~
+Mark buffer ``unmodified''. The command @kbd{~} does this
+immediately when typed.
+@item x
+Perform previously requested deletions and saves.
+@item u
+Remove any request made for the current line, and move down.
+@item @key{DEL}
+Move to previous line and remove any request made for that line.
+@end table
+
+ All the commands that put in or remove flags to request later operations
+also move down a line, and accept a numeric argument as a repeat count,
+unless otherwise specified.
+
+ There are also special commands to use the buffer list to select another
+buffer, and to specify one or more other buffers for display in additional
+windows.
+
+@table @kbd
+@item 1
+Select the buffer in a full-screen window. This command takes effect
+immediately.
+@item 2
+Immediately set up two windows, with this buffer in one, and the
+previously selected buffer (aside from the buffer @samp{*Buffer List*})
+in the other.
+@item f
+Immediately select the buffer in place of the @samp{*Buffer List*} buffer.
+@item o
+Immediately select the buffer in another window as if by @w{@kbd{C-x 4 b}},
+leaving @samp{*Buffer List*} visible.
+@item q
+Immediately select this buffer, and also display in other windows any
+buffers previously flagged with the @kbd{m} command. If there are no
+such buffers, this command is equivalent to @kbd{1}.
+@item m
+Flag this buffer to be displayed in another window if the @kbd{q}
+command is used. The request shows as a @samp{>} at the beginning of
+the line. The same buffer may not have both a delete request and a
+display request.
+@end table
+
+ All that @code{buffer-menu} does directly is create and select a suitable
+buffer, and turn on Buffer Menu mode. Everything else described above is
+implemented by the special commands provided in Buffer Menu mode. One
+consequence of this is that you can switch from the @samp{*Buffer List*}
+buffer to another Emacs buffer, and edit there. You can reselect the
+@code{buffer-menu} buffer later, to perform the operations already
+requested, or you can kill it, or pay no further attention to it.
+
+ The only difference between @code{buffer-menu} and @code{list-buffers} is
+that @code{buffer-menu} selects the @samp{*Buffer List*} buffer and
+@code{list-buffers} does not. If you run @code{list-buffers} (that is,
+type @kbd{C-x C-b}) and select the buffer list manually, you can use all of
+the commands described here.
+
+@node Windows, Major Modes, Buffers, Top
+@chapter Multiple Windows
+@cindex windows
+
+ Emacs can split the screen into two or many windows, which can display
+parts of different buffers, or different parts of one buffer.
+
+@menu
+* Basic Window:: Introduction to Emacs windows.
+* Split Window:: New windows are made by splitting existing windows.
+* Other Window:: Moving to another window or doing something to it.
+* Pop Up Window:: Finding a file or buffer in another window.
+* Change Window:: Deleting windows and changing their sizes.
+@end menu
+
+@node Basic Window, Split Window, Windows, Windows
+@section Concepts of Emacs Windows
+
+ When multiple windows are being displayed, each window has an Emacs
+buffer designated for display in it. The same buffer may appear in more
+than one window; if it does, any changes in its text are displayed in all
+the windows where it appears. But the windows showing the same buffer can
+show different parts of it, because each window has its own value of point.
+
+@cindex selected window
+ At any time, one of the windows is the @dfn{selected window}; the buffer
+this window is displaying is the current buffer. The terminal's cursor
+shows the location of point in this window. Each other window has a
+location of point as well, but since the terminal has only one cursor there
+is no way to show where those locations are.
+
+ Commands to move point affect the value of point for the selected Emacs
+window only. They do not change the value of point in any other Emacs
+window, even one showing the same buffer. The same is true for commands
+such as @kbd{C-x b} to change the selected buffer in the selected window;
+they do not affect other windows at all. However, there are other commands
+such as @kbd{C-x 4 b} that select a different window and switch buffers in
+it. Also, all commands that display information in a window, including
+(for example) @w{@kbd{C-h f}} (@code{describe-function}) and @kbd{C-x C-b}
+(@code{list-buffers}), work by switching buffers in a nonselected window
+without affecting the selected window.
+
+ Each window has its own mode line, which displays the buffer name,
+modification status and major and minor modes of the buffer that is
+displayed in the window. @xref{Mode Line}, for full details on the mode
+line.
+
+@node Split Window, Other Window, Basic Window, Windows
+@section Splitting Windows
+
+@table @kbd
+@item C-x 2
+Split the selected window into two windows, one above the other
+(@code{split-window-vertically}).
+@item C-x 5
+Split the selected window into two windows positioned side by side
+(@code{split-window-horizontally}).
+@end table
+
+@kindex C-x 2
+@findex split-window-vertically
+ The command @kbd{C-x 2} (@code{split-window-vertically}) breaks the
+selected window into two windows, one above the other. Both windows start
+out displaying the same buffer, with the same value of point. By default
+the two windows each get half the height of the window that was split; a
+numeric argument specifies how many lines to give to the top window.
+
+@kindex C-x 5
+@findex split-window-horizontally
+ @kbd{C-x 5} (@code{split-window-horizontally}) breaks the selected
+window into two side-by-side windows. A numeric argument specifies
+how many columns to give the one on the left. A line of vertical bars
+separates the two windows. Windows that are not the full width of the
+screen have mode lines, but they are truncated; also, they do not
+always appear in inverse video, because, the Emacs display routines
+have not been taught how to display a region of inverse video that is
+only part of a line on the screen.
+
+@vindex truncate-partial-width-windows
+ When a window is less than the full width, text lines too long to fit are
+frequent. Continuing all those lines might be confusing. The variable
+@code{truncate-partial-width-windows} can be set non-@code{nil} to force
+truncation in all windows less than the full width of the screen,
+independent of the buffer being displayed and its value for
+@code{truncate-lines}. @xref{Continuation Lines}.@refill
+
+ Horizontal scrolling is often used in side-by-side windows.
+@xref{Display}.
+
+@node Other Window, Pop Up Window, Split Window, Windows
+@section Using Other Windows
+
+@table @kbd
+@item C-x o
+Select another window (@code{other-window}). That is @kbd{o}, not zero.
+@item C-M-v
+Scroll the next window (@code{scroll-other-window}).
+@item M-x compare-windows
+Find next place where the text in the selected window does not match
+the text in the next window.
+@end table
+
+@kindex C-x o
+@findex other-window
+ To select a different window, use @kbd{C-x o} (@code{other-window}).
+That is an @kbd{o}, for `other', not a zero. When there are more than two
+windows, this command moves through all the windows in a cyclic order,
+generally top to bottom and left to right. From the rightmost and
+bottommost window, it goes back to the one at the upper left corner. A
+numeric argument means to move several steps in the cyclic order of
+windows. A negative argument moves around the cycle in the opposite order.
+When the minibuffer is active, the minibuffer is the last window in the
+cycle; you can switch from the minibuffer window to one of the other
+windows, and later switch back and finish supplying the minibuffer argument
+that is requested. @xref{Minibuffer Edit}.
+
+@kindex C-M-v
+@findex scroll-other-window
+ The usual scrolling commands (@pxref{Display}) apply to the selected
+window only, but there is one command to scroll the next window.
+@kbd{C-M-v} (@code{scroll-other-window}) scrolls the window that @w{@kbd{C-x o}}
+would select. It takes arguments, positive and negative, like @kbd{C-v}.
+
+@findex compare-windows
+ The command @kbd{M-x compare-windows} compares the text in the current
+window with that in the next window. Comparison starts at point in each
+window. Point moves forward in each window, a character at a time in each
+window, until the next characters in the two windows are different. Then
+the command is finished.
+
+@node Pop Up Window, Change Window, Other Window, Windows
+@section Displaying in Another Window
+
+@kindex C-x 4
+ @kbd{C-x 4} is a prefix key for commands that select another window
+(splitting the window if there is only one) and select a buffer in that
+window. Different @kbd{C-x 4} commands have different ways of finding the
+buffer to select.
+
+@findex switch-to-buffer-other-window
+@findex find-file-other-window
+@findex find-tag-other-window
+@findex dired-other-window
+@findex mail-other-window
+@table @kbd
+@item C-x 4 b @var{bufname} @key{RET}
+Select buffer @var{bufname} in another window. This runs
+@code{switch-to-buffer-other-window}.
+@item C-x 4 f @var{filename} @key{RET}
+Visit file @var{filename} and select its buffer in another window. This
+runs @code{find-file-other-window}. @xref{Visiting}.
+@item C-x 4 d @var{directory} @key{RET}
+Select a Dired buffer for directory @var{directory} in another window.
+This runs @code{dired-other-window}. @xref{Dired}.
+@item C-x 4 m
+Start composing a mail message in another window. This runs
+@code{mail-other-window}, and its same-window version is @kbd{C-x m}
+(@pxref{Sending Mail}).
+@item C-x 4 .
+Find a tag in the current tag table in another window. This runs
+@code{find-tag-other-window}, the multiple-window variant of @kbd{M-.}
+(@pxref{Tags}).
+@end table
+
+@node Change Window,, Pop Up Window, Windows
+@section Deleting and Rearranging Windows
+
+@table @kbd
+@item C-x 0
+Get rid of the selected window (@code{kill-window}). That is a zero.
+@item C-x 1
+Get rid of all windows except the selected one (@code{delete-other-windows}).
+@item C-x ^
+Make the selected window taller, at the expense of the other(s)
+(@code{enlarge-window}).
+@item C-x @}
+Widen the selected window (@code{enlarge-window-horizontally}).
+@end table
+
+@kindex C-x 0
+@findex delete-window
+ To delete a window, type @kbd{C-x 0} (@code{delete-window}). (That is a
+zero.) The space occupied by the deleted window is distributed among the
+other active windows (but not the minibuffer window, even if that is active
+at the time). Once a window is deleted, its attributes are forgotten;
+there is no automatic way to make another window of the same shape or
+showing the same buffer. But the buffer continues to exist, and you can
+select it in any window with @kbd{C-x b}.
+
+@kindex C-x 1
+@findex delete-other-windows
+ @kbd{C-x 1} (@code{delete-other-windows}) is more powerful than @kbd{C-x 0};
+it deletes all the windows except the selected one (and the minibuffer);
+the selected window expands to use the whole screen except for the echo
+area.
+
+@kindex C-x ^
+@findex enlarge-window
+@kindex C-x @}
+@findex enlarge-window-horizontally
+@vindex window-min-height
+@vindex window-min-width
+ To readjust the division of space among existing windows, use @kbd{C-x ^}
+(@code{enlarge-window}). It makes the currently selected window get one
+line bigger, or as many lines as is specified with a numeric argument.
+With a negative argument, it makes the selected window smaller. @kbd{C-x
+@}} (@code{enlarge-window-horizontally}) makes the selected window wider
+by the specified number of columns. The extra screen space given to a
+window comes from one of its neighbors, if that is possible; otherwise, all
+the competing windows are shrunk in the same proportion. If this makes any
+windows too small, those windows are deleted and their space is divided up.
+The minimum size is specified by the variables @code{window-min-height} and
+@code{window-min-width}.
+
+@node Major Modes, Indentation, Windows, Top
+@chapter Major Modes
+@cindex major modes
+@kindex TAB
+@kindex DEL
+@kindex LFD
+
+ Emacs has many different @dfn{major modes}, each of which customizes
+Emacs for editing text of a particular sort. The major modes are mutually
+exclusive, and each buffer has one major mode at any time. The mode line
+normally contains the name of the current major mode, in parentheses.
+@xref{Mode Line}.
+
+ The least specialized major mode is called @dfn{Fundamental mode}. This
+mode has no mode-specific redefinitions or variable settings, so that each
+Emacs command behaves in its most general manner, and each option is in its
+default state. For editing any specific type of text, such as Lisp code or
+English text, you should switch to the appropriate major mode, such as Lisp
+mode or Text mode.
+
+ Selecting a major mode changes the meanings of a few keys to become more
+specifically adapted to the language being edited. The ones which are
+changed frequently are @key{TAB}, @key{DEL}, and @key{LFD}. In addition,
+the commands which handle comments use the mode to determine how comments
+are to be delimited. 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 for specific purposes by
+Emacs, such as Dired mode for buffers made by Dired (@pxref{Dired}), and
+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
+separate paragraphs. This is so that the paragraph commands remain useful.
+@xref{Paragraphs}. They also cause Auto Fill mode to use the definition of
+@key{TAB} to indent the new lines it creates. This is because most lines
+in a program are usually indented. @xref{Indentation}.
+
+@menu
+* Choosing Modes:: How major modes are specified or chosen.
+@end menu
+
+@node Choosing Modes,,Major Modes,Major Modes
+@section How Major Modes are Chosen
+@cindex mode selection
+@cindex selection of mode
+@cindex choosing a mode
+
+ You can select a major mode explicitly for the current buffer, but
+most of the time Emacs determines which mode to use based on the file
+name or some text in the file.
+
+ Explicit selection of a new major mode is done with a @kbd{M-x} command.
+From the name of a major mode, add @code{-mode} to get the name of a
+command to select that mode. Thus, you can enter Lisp mode by executing
+@kbd{M-x lisp-mode}.
+
+@vindex auto-mode-alist
+ When you visit a file, Emacs usually chooses the right major mode based
+on the file's name. For example, files whose names end in @code{.c} are
+edited in C mode. The correspondence between file names and major mode is
+controlled by the variable @code{auto-mode-alist}. Its value is a list in
+which each element has the form
+
+@example
+(@var{regexp} . @var{mode-function})
+@end example
+
+@noindent
+For example, one element normally found in the list has the form
+@code{(@t{"\\.c$"} . c-mode)}, and it is responsible for selecting C mode
+for files whose names end in @file{.c}. (Note that @samp{\\} is needed in
+Lisp syntax to include a @samp{\} in the string, which is needed to
+suppress the special meaning of @samp{.} in regexps.) The only practical
+way to change this variable is with Lisp code.
+
+ You can specify which major mode should be used for editing a certain
+file by a special sort of text in the first nonblank line of the file. The
+mode name should appear in this line both preceded and followed by
+@samp{-*-}. Other text may appear on the line as well. For example,
+
+@example
+;-*-Lisp-*-
+@end example
+
+@noindent
+tells Emacs to use Lisp mode. Note how the semicolon is used to make Lisp
+treat this line as a comment. Such an explicit specification overrides any
+defaulting based on the file name.
+
+ Another format of mode specification is
+
+@example
+-*-Mode: @var{modename};-*-
+@end example
+
+@noindent
+which allows other things besides the major mode name to be specified.
+However, Emacs does not look for anything except the mode name.
+
+The major mode can also be specified in a local variables list.
+@xref{File Variables}.
+
+@vindex default-major-mode
+ When a file is visited that does not specify a major mode to use, or when
+a new buffer is created with @kbd{C-x b}, the major mode used is that
+specified by the variable @code{default-major-mode}. Normally this 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.
+
+@findex normal-mode
+ The command @kbd{M-x normal-mode} recalculates the major mode from the
+visited file name and the contents of the buffer.
+
+@node Indentation, Text, Major Modes, Top
+@chapter Indentation
+@cindex indentation
+
+@c WideCommands
+@table @kbd
+@item @key{TAB}
+Indent current line ``appropriately'' in a mode-dependent fashion.
+@item @key{LFD}
+Perform @key{RET} followed by @key{TAB} (@code{newline-and-indent}).
+@item M-^
+Merge two lines (@code{delete-indentation}). This would cancel out
+the effect of @key{LFD}.
+@item C-M-o
+Split line at point; text on the line after point becomes a new line
+indented to the same column that it now starts in (@code{split-line}).
+@item M-m
+Move (forward or back) to the first nonblank character on the current
+line (@code{back-to-indentation}).
+@item C-M-\
+Indent several lines to same column (@code{indent-region}).
+@item C-x @key{TAB}
+Shift block of lines rigidly right or left (@code{indent-rigidly}).
+@item M-i
+Indent from point to the next prespecified tab stop column
+(@code{tab-to-tab-stop}).
+@item M-x indent-relative
+Indent from point to under an indentation point in the previous line.
+@end table
+
+@kindex TAB
+@cindex indentation
+ Most programming languages have some indentation convention. For Lisp
+code, lines are indented according to their nesting in parentheses. The
+same general idea is used for C code, though many details are different.
+
+ Whatever the language, to indent a line, use the @key{TAB} command. Each
+major mode defines this command to perform the sort of indentation
+appropriate for the particular language. In Lisp mode, @key{TAB} aligns
+the line according to its depth in parentheses. No matter where in the
+line you are when you type @key{TAB}, it aligns the line as a whole. In C
+mode, @key{TAB} implements a subtle and sophisticated indentation style that
+knows about many aspects of C syntax.
+
+@kindex TAB
+ In Text mode, @key{TAB} runs the command @code{tab-to-tab-stop}, which
+indents to the next tab stop column. You can set the tab stops with
+@kbd{M-x edit-tab-stops}.
+
+@menu
+* Indentation Commands:: Various commands and techniques for indentation.
+* Tab Stops:: You can set arbitrary "tab stops" and then
+ indent to the next tab stop when you want to.
+* Just Spaces:: You can request indentation using just spaces.
+@end menu
+
+@node Indentation Commands, Tab Stops, Indentation, Indentation
+@section Indentation Commands and Techniques
+@c ??? Explain what Emacs has instead of space-indent-flag.
+
+ If you just want to insert a tab character in the buffer, you can type
+@kbd{C-q @key{TAB}}.
+
+@kindex M-m
+@findex back-to-indentation
+@c !!! rewrote to prevent overfull hbox
+ To move over the indentation on a line, type @kbd{Meta-m}.
+This command, given anywhere on a line,
+positions point at the first nonblank character on the line
+(@code{back-to-indentation}).
+
+ To insert an indented line before the current line, do @kbd{C-a C-o
+@key{TAB}}. To make an indented line after the current line, use @kbd{C-e
+@key{LFD}}.
+
+@kindex C-M-o
+@findex split-line
+ @kbd{C-M-o} (@code{split-line}) moves the text from point to the end of
+the line vertically down, so that the current line becomes two lines.
+@kbd{C-M-o} first moves point forward over any spaces and tabs. Then it
+inserts after point a newline and enough indentation to reach the same
+column point is on. Point remains before the inserted newline; in this
+regard, @kbd{C-M-o} resembles @kbd{C-o}.
+
+@kindex M-\
+@kindex M-^
+@findex delete-horizontal-space
+@findex delete-indentation
+ To join two lines cleanly, use the @kbd{Meta-^}
+(@code{delete-indentation}) command to delete the indentation at the
+front of the current line, and the line boundary as well. They are
+replaced by a single space, or by no space if point after joining is at
+the beginning of a line or before a @samp{)} or after a @samp{(}. To
+delete just the indentation of a line, go to the beginning of the line
+and use @kbd{Meta-\} (@code{delete-horizontal-space}), which deletes all
+spaces and tabs around the cursor.
+
+@kindex C-M-\
+@kindex C-x TAB
+@findex indent-region
+@findex indent-rigidly
+ There are also commands for changing the indentation of several lines at
+once. @kbd{Control-Meta-\} (@code{indent-region}) gives each line which
+begins in the region the ``usual'' indentation by invoking @key{TAB} at the
+beginning of the line. A numeric argument specifies the column to indent
+to, and each line is shifted left or right so that its first nonblank
+character appears in that column. @kbd{C-x @key{TAB}}
+(@code{indent-rigidly}) moves all of the lines in the region right by its
+argument (left, for negative arguments). The whole group of lines moves
+rigidly sideways, which is how the command gets its name.@refill
+
+@findex indent-relative
+ @kbd{M-x indent-relative} indents at point based on the previous line
+(actually, the last nonempty line.) It inserts whitespace at point, moving
+point, until it is underneath an indentation point in the previous line.
+An indentation point is the end of a sequence of whitespace or the end of
+the line. If point is farther right than any indentation point in the
+previous line, the whitespace before point is deleted and the first
+indentation point then applicable is used. If no indentation point is
+applicable even then, @code{tab-to-tab-stop} is run (see next section).
+
+ @code{indent-relative} is the definition of @key{TAB} in Indented Text
+mode. @xref{Text}.
+
+@node Tab Stops, Just Spaces, Indentation Commands, Indentation
+@section Tab Stops
+
+@kindex M-i
+@findex tab-to-tab-stop
+ For typing in tables, you can use Text mode's definition of @key{TAB},
+@code{tab-to-tab-stop}. This command inserts indentation before point,
+enough to reach the next tab stop column. If you are not in Text mode,
+this function can be found on @kbd{M-i} anyway.
+
+@findex edit-tab-stops
+@findex edit-tab-stops-note-changes
+@kindex C-c C-c (Edit Tab Stops)
+@vindex tab-stop-list
+ The tab stops used by @kbd{M-i} can be set arbitrarily by the user.
+They are stored in a variable called @code{tab-stop-list}, as a list of
+column-numbers in increasing order.
+
+ The convenient way to set the tab stops is using @kbd{M-x edit-tab-stops},
+which creates and selects a buffer containing a description of the tab stop
+settings. You can edit this buffer to specify different tab stops, and
+then type @kbd{C-c C-c} to make those new tab stops take effect. In the
+tab stop buffer, @w{@kbd{C-c C-c}} runs the function
+@code{edit-tab-stops-note-changes} rather than its usual definition
+@code{save-buffer}. @code{edit-tab-stops} records which buffer was current
+when you invoked it, and stores the tab stops back in that buffer; normally
+all buffers share the same tab stops and changing them in one buffer
+affects all, but if you happen to make @code{tab-stop-list} local in one
+buffer then @code{edit-tab-stops} in that buffer will edit the local
+settings.
+
+ Here is what the text representing the tab stops looks like for ordinary
+tab stops every eight columns.
+
+@example
+ : : : : : :
+0 1 2 3 4
+0123456789012345678901234567890123456789012345678
+To install changes, type C-c C-c
+@end example
+
+ The first line contains a colon at each tab stop. The remaining lines
+are present just to help you see where the colons are and know what to do.
+
+ Note that the tab stops that control @code{tab-to-tab-stop} have nothing
+to do with displaying tab characters in the buffer. @xref{Display Vars},
+for more information on that.
+
+@node Just Spaces,, Tab Stops, Indentation
+@section Tabs vs. Spaces
+
+@vindex indent-tabs-mode
+ Emacs normally uses both tabs and spaces to indent lines. If you prefer,
+all indentation can be made from spaces only. To request this, set
+@code{indent-tabs-mode} to @code{nil}. This is a per-buffer variable;
+altering the variable affects only the current buffer, but there is a
+default value which you can change as well. @xref{Locals}.
+
+@findex tabify
+@findex untabify
+ There are also commands to convert tabs to spaces or vice versa, always
+preserving the columns of all nonblank text. @kbd{M-x tabify} scans the
+region for sequences of spaces, and converts sequences of at least three
+spaces to tabs if that can be done without changing indentation. @kbd{M-x
+untabify} changes all tabs in the region to appropriate numbers of spaces.
+
+@node Text, Programs, Indentation, Top
+@chapter Commands for Human Languages
+@cindex text
+
+ The term @dfn{text} has two widespread meanings in our area of the
+computer field. One is data that is a sequence of characters. Any file
+that you edit with Emacs is text, in this sense of the word. The other
+meaning is more restrictive: a sequence of characters in a human language
+for humans to read (possibly after processing by a text formatter), as
+opposed to a program or commands for a program.
+
+ Human languages have syntactic/stylistic conventions that can be
+supported or used to advantage by editor commands: conventions involving
+words, sentences, paragraphs, and capital letters. This chapter describes
+Emacs commands for all of these things. There are also commands for
+@dfn{filling}, or rearranging paragraphs into lines of approximately equal
+length. The commands for moving over and killing words, sentences
+and paragraphs, while intended primarily for editing text, are also often
+useful for editing programs.
+
+ Emacs has several major modes for editing human language text.
+If the file contains text pure and simple, use Text mode, which customizes
+Emacs in small ways for the syntactic conventions of text. For text which
+contains embedded commands for text formatters, Emacs has other major modes,
+each for a particular text formatter. Thus, for input to @TeX{}, you would
+use @TeX{} mode; for input to nroff, Nroff mode.
+
+@menu
+* Text Mode:: The major modes for editing text files.
+* Nroff Mode:: The major mode for editing input to the formatter nroff.
+* TeX Mode:: The major modes for editing input to the formatter TeX.
+* Outline Mode::The major mode for editing outlines.
+* Words:: Moving over and killing words.
+* Sentences:: Moving over and killing sentences.
+* Paragraphs:: Moving over paragraphs.
+* Pages:: Moving over pages.
+* Filling:: Filling or justifying text
+* Case:: Changing the case of text
+@end menu
+
+@node Text Mode, Words, Text, Text
+@section Text Mode
+
+@findex tab-to-tab-stop
+@findex edit-tab-stops
+@cindex Text mode
+@kindex TAB
+@findex text-mode
+ Editing files of text in a human language ought to be done using Text
+mode rather than Lisp or Fundamental mode. Invoke @kbd{M-x text-mode} to
+enter Text mode. In Text mode, @key{TAB} runs the function
+@code{tab-to-tab-stop}, which allows you to use arbitrary tab stops set
+with @kbd{M-x edit-tab-stops} (@pxref{Tab Stops}). Features concerned with
+comments in programs are turned off except when explicitly invoked. The
+syntax table is changed so that periods are not considered part of a word,
+while apostrophes, backspaces and underlines are.
+
+@findex indented-text-mode
+@cindex Indented Text mode
+ A similar variant mode is Indented Text mode, intended for editing text
+in which most lines are indented. This mode defines @key{TAB} to run
+@code{indent-relative} (@pxref{Indentation}), and makes Auto Fill indent
+the lines it creates. The result is that normally a line made by Auto
+Filling, or by @key{LFD}, is indented just like the previous line. Use
+@kbd{M-x indented-text-mode} to select this mode.
+
+@vindex text-mode-hook
+ Entering Text mode or Indented Text mode calls with no arguments the
+value of the variable @code{text-mode-hook}, if that value exists and is
+not @code{nil}. This value is also called when modes related to Text mode
+are entered; this includes Nroff mode, @TeX{} mode, Outline mode and Mail
+mode. Your hook can look at the value of @code{major-mode} to see which of
+these modes is actually being entered.
+
+@menu
+ Three modes similar to Text mode are of use for editing text that is to
+be passed through a text formatter before achieving the form in which
+humans are to read it.
+
+* Nroff Mode:: The nroff formatter typesets text.
+* TeX Mode:: The TeX formatter typesets text and mathematics.
+* Texinfo Mode::Texinfo provides both on-line information and printed output
+ from the same source file.
+
+ Another similar mode is used for editing outlines. It allows you
+to view the text at various levels of detail. You can view either
+the outline headings alone or both headings and text; you can also
+hide some of the headings at lower levels from view to make the high
+level structure more visible.
+
+* Outline Mode::The major mode for editing outlines.
+@end menu
+
+@node Nroff Mode, TeX Mode, Text Mode, Text Mode
+@subsection Nroff Mode
+
+@cindex nroff
+@cindex Nroff mode
+@findex nroff-mode
+ Nroff mode is a mode like Text mode but modified to handle nroff commands
+present in the text. Invoke @kbd{M-x nroff-mode} to enter this mode. It
+differs from Text mode in only a few ways. All nroff command lines are
+considered paragraph separators, so that filling will never garble the
+nroff commands. Pages are separated by @samp{.bp} commands. Comments
+start with backslash-doublequote. Also, three special commands are
+provided that are not in Text mode:
+
+@findex forward-text-line
+@findex backward-text-line
+@findex count-text-lines
+@kindex M-n
+@kindex M-p
+@kindex M-?
+@table @kbd
+@item M-n
+Move to the beginning of the next line that isn't an nroff command
+(@code{forward-text-line}). An argument is a repeat count.
+@item M-p
+Like @kbd{M-n} but move up (@code{backward-text-line}).
+@item M-?
+Prints in the echo area the number of text lines (lines that are not
+nroff commands) in the region (@code{count-text-lines}).
+@end table
+
+@cindex Electric Nroff mode
+@findex electric-nroff-mode
+ The other feature of Nroff mode is Electric Nroff newline mode. This
+is a minor mode that you can turn on or off with @kbd{M-x
+electric-nroff-mode} (@pxref{Minor Modes}). When the mode is on, each
+time you use @key{RET} to end a line that contains an nroff command that
+opens a kind of grouping, it also inserts the matching nroff command to
+close that grouping, on the following line. For example, if you are at
+the beginning of a line and type @kbd{.@: ( b @key{RET}}, this inserts
+the matching command @samp{.)b} on a new line following point.
+
+@vindex nroff-mode-hook
+ Entering Nroff mode calls with no arguments the value of the variable
+@code{text-mode-hook}, if that value exists and is not @code{nil}; then it
+does the same with the variable @code{nroff-mode-hook}.
+
+@node TeX Mode, Texinfo Mode, Nroff Mode, Text Mode
+@subsection @TeX{} Mode
+@cindex TeX
+@cindex LaTeX
+@cindex TeX mode
+@findex TeX-mode
+@findex tex-mode
+@findex plain-tex-mode
+@findex LaTeX-mode
+@findex plain-TeX-mode
+@findex latex-mode
+
+ @TeX{} is a powerful text formatter written by Donald Knuth; it is also
+free, like GNU Emacs. La@TeX{} is a simplified input format for @TeX{},
+implemented by @TeX{} macros. It comes with @TeX{}.@refill
+
+ Emacs has a special @TeX{} mode for editing @TeX{} input files.
+It provides facilities for checking the balance of delimiters and for
+invoking @TeX{} on all or part of the file.
+
+ @TeX{} mode has two variants, Plain @TeX{} mode and La@TeX{} mode
+(actually two distinct major modes which differ only slightly). They are
+designed for editing the two different input formats. The command @kbd{M-x
+tex-mode} looks at the contents of the buffer to determine whether the
+contents appear to be La@TeX{} input or not; it then selects the
+appropriate mode. If it can't tell which is right (e.g., the buffer is
+empty), the variable @code{TeX-default-mode} controls which mode is used.
+
+ The commands @kbd{M-x plain-tex-mode} and @kbd{M-x latex-mode} explicitly
+select the two variants of @TeX{} mode. Use these commands when @kbd{M-x
+tex-mode} does not guess right.@refill
+
+@menu
+* Editing: TeX Editing. Special commands for editing in TeX mode.
+* Printing: TeX Print. Commands for printing part of a file with TeX.
+@end menu
+
+@c !!! Here is information about obtaining TeX. Update it whenever.
+@c Last updated by RJC on 8 October 1992
+@c based on message from elisabet@@u.washington.edu
+ @TeX{} for Unix systems can be obtained from the University of Washington
+for a distribution fee.
+
+ To order a full distribution, send $200.00 for a 1/2-inch 9-track 1600
+bpi (@code{tar} or @code{cpio}) tape reel, or $210.00 for a 1/4-inch
+4-track QIC-24 (@code{tar} or @code{cpio}) cartridge, to:@refill
+
+@display
+Northwest Computing Support Center
+DR-10, Thomson Hall 35
+University of Washington
+Seattle, Washington 98195
+@end display
+
+@noindent
+Please make checks payable to the University of Washington.@refill
+
+ Prepaid orders are preferred but purchase orders are acceptable;
+however, purchase orders carry an extra charge of $10.00, to pay for
+processing.@refill
+
+ Overseas sites: please add to the base cost $20.00 for shipment via
+air parcel post, or $30.00 for shipment via courier.@refill
+
+ Please check with the Northwest Computing Support Center at the
+University of Washington for current prices and formats:@refill
+
+@example
+@group
+@r{telephone:} (206) 543-6259
+@r{email:} elisabet@@u.washington.edu
+@end group
+@end example
+
+@node TeX Editing,TeX Print,TeX Mode,TeX Mode
+@subsubsection @TeX{} Editing Commands
+
+ Here are the special commands provided in @TeX{} mode for editing the
+text of the file.
+
+@table @kbd
+@item "
+Insert, according to context, either @samp{@`@`} or @samp{"} or
+@samp{@'@'} (@code{TeX-insert-quote}).
+@item @key{LFD}
+Insert a paragraph break (two newlines) and check the previous
+paragraph for unbalanced braces or dollar signs
+(@code{TeX-terminate-paragraph}).
+@item M-x validate-TeX-buffer
+Check each paragraph in the buffer for unbalanced braces or dollar signs.
+@c !!! following generates acceptable underfull hbox
+@item M-@{
+Insert @samp{@{@}} and position point between them (@code{TeX-insert-braces}).
+@item M-@}
+Move forward past the next unmatched close brace (@code{up-list}).
+@item C-c C-f
+Close a block for La@TeX{} (@code{TeX-close-LaTeX-block}).
+@end table
+
+@findex TeX-insert-quote
+@kindex " (TeX mode)
+ In @TeX{}, the character @samp{"} is not normally used; use @samp{``}
+to start a quotation and @samp{''} to end one. @TeX{} mode defines the key
+@kbd{"} to insert @samp{``} after whitespace or an open brace, @samp{"}
+after a backslash, or @samp{''} otherwise. This is done by the command
+@code{TeX-insert-quote}. If you need the character @samp{"} itself in
+unusual contexts, use @kbd{C-q} to insert it. Also, @kbd{"} with a
+numeric argument always inserts that number of @samp{"} characters.
+
+ In @TeX{} mode, @samp{$} has a special syntax code which attempts to
+understand the way @TeX{} math mode delimiters match. When you insert a
+@samp{$} that is meant to exit math mode, the position of the matching
+@samp{$} that entered math mode is displayed for a second. This is the
+same feature that displays the open brace that matches a close brace that
+is inserted. However, there is no way to tell whether a @samp{$} enters
+math mode or leaves it; so when you insert a @samp{$} that enters math
+mode, the previous @samp{$} position is shown as if it were a match, even
+though they are actually unrelated.
+
+@findex TeX-insert-braces
+@kindex M-@{ (TeX mode)
+@findex up-list
+@kindex M-@} (TeX mode)
+ If you prefer to keep braces balanced at all times, you can use @kbd{M-@{}
+(@code{TeX-insert-braces}) to insert a pair of braces. It leaves point
+between the two braces so you can insert the text that belongs inside.
+Afterward, use the command @kbd{M-@}} (@code{up-list}) to move forward
+past the close brace.
+
+@findex validate-TeX-buffer
+@findex TeX-terminate-paragraph
+@kindex LFD (TeX mode)
+ There are two commands for checking the matching of braces. @key{LFD}
+(@code{TeX-terminate-paragraph}) checks the paragraph before point, and
+inserts two newlines to start a new paragraph. It prints a message in the
+echo area if any mismatch is found. @kbd{M-x validate-TeX-buffer} checks
+the entire buffer, paragraph by paragraph. When it finds a paragraph that
+contains a mismatch, it displays point at the beginning of the paragraph
+for a few seconds and pushes a mark at that spot. Scanning continues
+until the whole buffer has been checked or until you type another key.
+The positions of the last several paragraphs with mismatches can be
+found in the mark ring (@pxref{Mark Ring}).
+
+ Note that square brackets and parentheses are matched in @TeX{} mode, not
+just braces. This is wrong for the purpose of checking @TeX{} syntax.
+However, parentheses and square brackets are likely to be used in text as
+matching delimiters and it is useful for the various motion commands and
+automatic match display to work with them.
+
+@findex TeX-close-LaTeX-block
+@kindex C-c C-f (LaTeX mode)
+ In La@TeX{} input, @samp{\begin} and @samp{\end} commands must balance.
+After you insert a @samp{\begin}, use @kbd{C-c C-f}
+(@code{TeX-close-LaTeX-block}) to insert automatically a matching
+@samp{\end} (on a new line following the @samp{\begin}). A blank line is
+inserted between the two, and point is left there.@refill
+
+@node TeX Print,,TeX Editing,TeX Mode
+@subsubsection @TeX{} Printing Commands
+
+ You can invoke @TeX{} as an inferior of Emacs on either the entire
+contents of the buffer or just a region at a time. Running @TeX{} in
+this way on just one chapter is a good way to see what your changes
+look like without taking the time to format the entire file.
+
+@table @kbd
+@item C-c C-r
+Invoke @TeX{} on the current region, plus the buffer's header
+(@code{TeX-region}).
+@item C-c C-b
+Invoke @TeX{} on the entire current buffer (@code{TeX-buffer}).
+@item C-c C-l
+Recenter the window showing output from the inferior @TeX{} so that
+the last line can be seen (@code{TeX-recenter-output-buffer}).
+@item C-c C-k
+Kill the inferior @TeX{} (@code{TeX-kill-job}).
+@item C-c C-p
+Print the output from the last @kbd{C-c C-r} or @kbd{C-c C-b} command
+(@code{TeX-print}).
+@item C-c C-q
+Show the printer queue (@code{TeX-show-print-queue}).
+@end table
+
+@findex TeX-buffer
+@kindex C-c C-b (TeX mode)
+@findex TeX-print
+@kindex C-c C-p (TeX mode)
+@findex TeX-show-print-queue
+@kindex C-c C-q (TeX mode)
+ You can pass the current buffer through an inferior @TeX{} by means of
+@kbd{C-c C-b} (@code{TeX-buffer}). The formatted output appears in a file
+in @file{/tmp}; to print it, type @kbd{C-c C-p} (@code{TeX-print}).
+Afterward use @kbd{C-c C-q} (@code{TeX-show-print-queue}) to view the
+progress of your output towards being printed.
+
+@findex TeX-kill-job
+@kindex C-c C-k (TeX mode)
+@findex TeX-recenter-output-buffer
+@kindex C-c C-l (TeX mode)
+ The console output from @TeX{}, including any error messages, appears in a
+buffer called @samp{*TeX-shell*}. If @TeX{} gets an error, you can switch
+to this buffer and feed it input (this works as in Shell mode;
+@pxref{Interactive Shell}). Without switching to this buffer you can scroll
+it so that its last line is visible by typing @kbd{C-c C-l}.
+
+ Type @kbd{C-c C-k} (@code{TeX-kill-job}) to kill the @TeX{} process if
+you see that its output is no longer useful. Using @kbd{C-c C-b} or
+@kbd{C-c C-r} also kills any @TeX{} process still running.@refill
+
+@findex TeX-region
+@kindex C-c C-r (TeX mode)
+ You can also pass an arbitrary region through an inferior @TeX{} by typing
+@kbd{C-c C-r} (@code{TeX-region}). This is tricky, however, because most files
+of @TeX{} input contain commands at the beginning to set parameters and
+define macros, without which no later part of the file will format
+correctly. To solve this problem, @kbd{C-c C-r} allows you to designate a
+part of the file as containing essential commands; it is included before
+the specified region as part of the input to @TeX{}. The designated part
+of the file is called the @dfn{header}.
+
+@cindex header (TeX mode)
+ To indicate the bounds of the header in Plain @TeX{} mode, you insert two
+special strings in the file. Insert @samp{%**start of header} before the
+header, and @samp{%**end of header} after it. Each string must appear
+entirely on one line, but there may be other text on the line before or
+after. The lines containing the two strings are included in the header.
+If @samp{%**start of header} does not appear within the first 100 lines of
+the buffer, @kbd{C-c C-r} assumes that there is no header.
+
+ In La@TeX{} mode, the header begins with @samp{\documentstyle} and ends
+with @samp{\begin@{document@}}. These are commands that La@TeX{} requires
+you to use in any case, so nothing special needs to be done to identify the
+header.
+
+@vindex TeX-mode-hook
+@vindex LaTeX-mode-hook
+@vindex plain-TeX-mode-hook
+ Entering either kind of @TeX{} mode calls with no arguments the value of
+the variable @code{text-mode-hook}, if that value exists and is not
+@code{nil}; then it does the same with the variable @code{TeX-mode-hook}.
+Finally it does the same with either @code{plain-TeX-mode-hook} or
+@code{LaTeX-mode-hook}.
+
+@node Texinfo Mode, Outline Mode, TeX Mode, Text Mode
+@subsection Texinfo Mode
+@cindex Texinfo mode
+@findex texinfo-mode
+
+Texinfo is a documentation system that uses a single source file to
+produce both on-line information and printed output. This means that
+instead of writing two different documents, one for the on-line help or
+other on-line information and the other for a typeset manual or other
+printed work, you need write only one document. When the work is
+revised, you need revise only one document. (You can read the on-line
+information, known as an @dfn{Info file}, with an Info
+documentation-reading program. @inforef{Top, info, info}, for more
+information about Info.) Texinfo is the format in which documentation
+for GNU utilities and libraries is written.
+
+Texinfo mode provides special features for working with Texinfo files
+including utilities to construct Info menus and pointers automatically,
+keybindings to insert frequently used formatting commands, and
+keybindings for commands to format both for Info and for printing.
+
+Texinfo mode is described in @ref{Texinfo Mode, , Using Texinfo Mode,
+texinfo, Texinfo; The GNU Documentation Format}.
+
+@node Outline Mode,, Texinfo Mode, Text Mode
+@subsection Outline Mode
+@cindex Outline mode
+@cindex outlines
+@cindex selective display
+@cindex invisible lines
+
+@findex outline-mode
+ Outline mode is a major mode much like Text mode but intended for editing
+outlines. It allows you to make parts of the text temporarily invisible
+so that you can see just the overall structure of the outline. Type
+@kbd{M-x outline-mode} to turn on Outline mode in the current buffer.
+
+@vindex outline-mode-hook
+ Entering Outline mode calls with no arguments the value of the variable
+@code{text-mode-hook}, if that value exists and is not @code{nil}; then it
+does the same with the variable @code{outline-mode-hook}.
+
+ When a line is invisible in outline mode, it does not appear on the
+screen. The screen appears exactly as if the invisible line
+were deleted, except that an ellipsis (three periods in a row) appears
+at the end of the previous visible line (only one ellipsis no matter
+how many invisible lines follow).
+
+ All editing commands treat the text of the invisible line as part of the
+previous visible line. For example, @kbd{C-n} moves onto the next visible
+line. Killing an entire visible line, including its terminating newline,
+really kills all the following invisible lines along with it; yanking it
+all back yanks the invisible lines and they remain invisible.
+
+@menu
+* Format: Outline Format. What the text of an outline looks like.
+* Motion: Outline Motion. Special commands for moving through outlines.
+* Visibility: Outline Visibility. Commands to control what is visible.
+@end menu
+
+@node Outline Format,Outline Motion,Outline Mode, Outline Mode
+@subsubsection Format of Outlines
+
+@cindex heading lines (Outline mode)
+@cindex body lines (Outline mode)
+ Outline mode assumes that the lines in the buffer are of two types:
+@dfn{heading lines} and @dfn{body lines}. A heading line represents a topic in the
+outline. Heading lines start with one or more stars; the number of stars
+determines the depth of the heading in the outline structure. Thus, a
+heading line with one star is a major topic; all the heading lines with
+two stars between it and the next one-star heading are its subtopics; and
+so on. Any line that is not a heading line is a body line. Body lines
+belong to the preceding heading line. Here is an example:
+
+@example
+* Food
+
+This is the body,
+which says something about the topic of food.
+
+** Delicious Food
+
+This is the body of the second-level header.
+
+** Distasteful Food
+
+This could have
+a body too, with
+several lines.
+
+*** Dormitory Food
+
+* Shelter
+
+A second first-level topic with its header line.
+@end example
+
+ A heading line together with all following body lines is called
+collectively an @dfn{entry}. A heading line together with all following
+deeper heading lines and their body lines is called a @dfn{subtree}.
+
+@vindex outline-regexp
+ You can customize the criterion for distinguishing heading lines
+by setting the variable @code{outline-regexp}. Any line whose
+beginning has a match for this regexp is considered a heading line.
+Matches that start within a line (not at the beginning) do not count.
+The length of the matching text determines the level of the heading;
+longer matches make a more deeply nested level. Thus, for example,
+if a text formatter has commands @samp{@@chapter}, @samp{@@section}
+and @samp{@@subsection} to divide the document into chapters and
+sections, you could make those lines count as heading lines by
+setting @code{outline-regexp} to @samp{"@@chap\\|@@\\(sub\\)*section"}.
+Note the trick: the two words @samp{chapter} and @samp{section} are equally
+long, but by defining the regexp to match only @samp{chap} we ensure
+that the length of the text matched on a chapter heading is shorter,
+so that Outline mode will know that sections are contained in chapters.
+This works as long as no other command starts with @samp{@@chap}.
+
+ Outline mode makes a line invisible by changing the newline before it
+into an @sc{ascii} Control-M (code 015). Most editing commands that work on
+lines treat an invisible line as part of the previous line because,
+strictly speaking, it @i{is} part of that line, since there is no longer a
+newline in between. When you save the file in Outline mode, Control-M
+characters are saved as newlines, so the invisible lines become ordinary
+lines in the file. But saving does not change the visibility status of a
+line inside Emacs.
+
+@node Outline Motion,Outline Visibility,Outline Format,Outline Mode
+@subsubsection Outline Motion Commands
+
+ There are some special motion commands in Outline mode that move
+backward and forward to heading lines.
+
+@table @kbd
+@item C-c C-n
+Move point to the next visible heading line
+(@code{outline-next-visible-heading}).
+@c !!! following generates acceptable underfull hbox
+@item C-c C-p
+Move point to the previous visible heading line
+(@code{outline-previous-visible-heading}).
+@item C-c C-f
+Move point to the next visible heading line at the same level
+as the one point is on (@code{outline-forward-same-level}).
+@item C-c C-b
+Move point to the previous visible heading line at the same level
+(@code{outline-backward-same-level}).
+@item C-c C-u
+Move point up to a lower-level (more inclusive) visible heading line
+(@code{outline-up-heading}).
+@end table
+
+@findex outline-next-visible-heading
+@findex outline-previous-visible-heading
+@kindex C-c C-n (Outline mode)
+@kindex C-c C-p (Outline mode)
+ @kbd{C-c C-n} (@code{next-visible-heading}) moves down to the next
+heading line. @kbd{C-c C-p} (@code{previous-visible-heading}) moves
+similarly backward. Both accept numeric arguments as repeat counts. The
+names emphasize that invisible headings are skipped, but this is not really
+a special feature. All editing commands that look for lines ignore the
+invisible lines automatically.@refill
+
+@findex outline-up-heading
+@findex outline-forward-same-level
+@findex outline-backward-same-level
+@kindex C-c C-f (Outline mode)
+@kindex C-c C-b (Outline mode)
+@kindex C-c C-u (Outline mode)
+@c !!! written verbosely to prevent overfull hbox
+ More advanced motion commands understand the levels of headings.
+The two commands, @kbd{C-c C-f} (@code{outline-forward-same-level}) and
+@kbd{C-c C-b} (@code{outline-backward-same-level}), move from one
+heading line to another visible heading at the same depth in
+the outline. @kbd{C-c C-u} (@code{outline-up-heading}) moves
+backward to another heading that is less deeply nested.
+
+@node Outline Visibility,,Outline Motion,Outline Mode
+@subsubsection Outline Visibility Commands
+
+ The other special commands of outline mode are used to make lines visible
+or invisible. Their names all start with @code{hide} or @code{show}.
+Most of them fall into pairs of opposites. They are not undoable; instead,
+you can undo right past them. Making lines visible or invisible is simply
+not recorded by the undo mechanism.
+
+@table @kbd
+@item M-x hide-body
+Make all body lines in the buffer invisible.
+@item M-x show-all
+Make all lines in the buffer visible.
+@item C-c C-h
+Make everything under this heading invisible, not including this
+heading itself (@code{hide-subtree}).
+@item C-c C-s
+Make everything under this heading visible, including body,
+subheadings, and their bodies (@code{show-subtree}).
+@item M-x hide-leaves
+Make the body of this heading line, and of all its subheadings,
+invisible.
+@item M-x show-branches
+Make all subheadings of this heading line, at all levels, visible.
+@item C-c C-i
+Make immediate subheadings (one level down) of this heading line
+visible (@code{show-children}).
+@item M-x hide-entry
+Make this heading line's body invisible.
+@item M-x show-entry
+Make this heading line's body visible.
+@end table
+
+@findex hide-entry
+@findex show-entry
+ Two commands that are exact opposites are @kbd{M-x hide-entry} and
+@kbd{M-x show-entry}. They are used with point on a heading line, and
+apply only to the body lines of that heading. The subtopics and their
+bodies are not affected.
+
+@findex hide-subtree
+@findex show-subtree
+@kindex C-c C-s (Outline mode)
+@kindex C-c C-h (Outline mode)
+@cindex subtree (Outline mode)
+ Two more powerful opposites are @kbd{C-c C-h} (@code{hide-subtree}) and
+@kbd{C-c C-s} (@code{show-subtree}). Both expect to be used when point is
+on a heading line, and both apply to all the lines of that heading's
+@dfn{subtree}: its body, all its subheadings, both direct and indirect, and
+all of their bodies. In other words, the subtree contains everything
+following this heading line, up to and not including the next heading of
+the same or higher rank.@refill
+
+@findex hide-leaves
+@findex show-branches
+ Intermediate between a visible subtree and an invisible one is having
+all the subheadings visible but none of the body. There are two commands
+for doing this, depending on whether you want to hide the bodies or
+make the subheadings visible. They are @kbd{M-x hide-leaves} and
+@kbd{M-x show-branches}.
+
+@kindex C-c C-i (Outline mode)
+@findex show-children
+ A little weaker than @code{show-branches} is @kbd{C-c C-i}
+(@code{show-children}). It makes just the direct subheadings
+visible---those one level down. Deeper subheadings remain invisible, if
+they were invisible.@refill
+
+@findex hide-body
+@findex show-all
+ Two commands have a blanket effect on the whole file. @kbd{M-x hide-body}
+makes all body lines invisible, so that you see just the outline structure.
+@kbd{M-x show-all} makes all lines visible. These commands can be thought
+of as a pair of opposites even though @kbd{M-x show-all} applies to more
+than just body lines.
+
+@vindex selective-display-ellipses
+ The use of ellipses at the ends of visible lines can be turned off
+by setting @code{selective-display-ellipses} to @code{nil}. Then there
+is no visible indication of the presence of invisible lines.
+
+@node Words, Sentences, Text Mode, Text
+@section Words
+@cindex words
+@cindex Meta
+
+ Emacs has commands for moving over or operating on words. By convention,
+the keys for them are all @kbd{Meta-} characters.
+
+@c widecommands
+@table @kbd
+@item M-f
+Move forward over a word (@code{forward-word}).
+@item M-b
+Move backward over a word (@code{backward-word}).
+@item M-d
+Kill up to the end of a word (@code{kill-word}).
+@item M-@key{DEL}
+Kill back to the beginning of a word (@code{backward-kill-word}).
+@item M-@@
+Mark the end of the next word (@code{mark-word}).
+@item M-t
+Transpose two words; drag a word forward
+or backward across other words (@code{transpose-words}).
+@end table
+
+ Notice how these keys form a series that parallels the
+character-based @kbd{C-f}, @kbd{C-b}, @kbd{C-d}, @kbd{C-t} and
+@key{DEL}. @kbd{M-@@} is related to @kbd{C-@@}, which is an alias for
+@kbd{C-@key{SPC}}.@refill
+
+@kindex M-f
+@kindex M-b
+@findex forward-word
+@findex backward-word
+ The commands @kbd{Meta-f} (@code{forward-word}) and @kbd{Meta-b}
+(@code{backward-word}) move forward and backward over words. They are thus
+analogous to @kbd{Control-f} and @kbd{Control-b}, which move over single
+characters. Like their @kbd{Control-} analogues, @kbd{Meta-f} and
+@kbd{Meta-b} move several words if given an argument. @kbd{Meta-f} with a
+negative argument moves backward, and @kbd{Meta-b} with a negative argument
+moves forward. Forward motion stops right after the last letter of the
+word, while backward motion stops right before the first letter.@refill
+
+@kindex M-d
+@findex kill-word
+ @kbd{Meta-d} (@code{kill-word}) kills the word after point. To be
+precise, it kills everything from point to the place @kbd{Meta-f} would
+move to. Thus, if point is in the middle of a word, @kbd{Meta-d} kills
+just the part after point. If some punctuation comes between point and the
+next word, it is killed along with the word. (If you wish to kill only the
+next word but not the punctuation before it, simply do @kbd{Meta-f} to get
+the end, and kill the word backwards with @kbd{Meta-@key{DEL}}.)
+@kbd{Meta-d} takes arguments just like @kbd{Meta-f}.
+
+@findex backward-kill-word
+@kindex M-DEL
+ @kbd{Meta-@key{DEL}} (@code{backward-kill-word}) kills the word before
+point. It kills everything from point back to where @kbd{Meta-b} would
+move to. If point is after the space in @w{@samp{FOO, BAR}}, then
+@w{@samp{FOO, }} is killed. (If you wish to kill just @samp{FOO}, do
+@kbd{Meta-b Meta-d} instead of @kbd{Meta-@key{DEL}}.)
+
+@cindex transposition
+@kindex M-t
+@findex transpose-words
+ @kbd{Meta-t} (@code{transpose-words}) exchanges the word before or
+containing point with the following word. The delimiter characters between
+the words do not move. For example, @w{@samp{FOO, BAR}} transposes into
+@w{@samp{BAR, FOO}} rather than @samp{@w{BAR FOO,}}. @xref{Transpose}, for
+more on transposition and on arguments to transposition commands.
+
+@kindex M-@@
+@findex mark-word
+ To operate on the next @var{n} words with an operation which applies
+between point and mark, you can either set the mark at point and then move
+over the words, or you can use the command @kbd{Meta-@@} (@code{mark-word})
+which does not move point, but sets the mark where @kbd{Meta-f} would move
+to. It can be given arguments just like @kbd{Meta-f}.
+
+@cindex syntax table
+ The word commands' understanding of syntax is completely controlled by
+the syntax table. Any character can, for example, be declared to be a word
+delimiter. @xref{Syntax}.
+
+@node Sentences, Paragraphs, Words, Text
+@section Sentences
+@cindex sentences
+
+ The Emacs commands for manipulating sentences and paragraphs are mostly
+on @kbd{Meta-} keys, so as to be like the word-handling commands.
+
+@table @kbd
+@item M-a
+@c !!! added @* to prevent overfull hbox
+Move back to the beginning of the sentence@*
+(@code{backward-sentence}).
+@item M-e
+Move forward to the end of the sentence (@code{forward-sentence}).
+@item M-k
+Kill forward to the end of the sentence (@code{kill-sentence}).
+@item C-x @key{DEL}
+Kill back to the beginning of the sentence (@code{backward-kill-sentence}).
+@end table
+
+@kindex M-a
+@kindex M-e
+@findex backward-sentence
+@findex forward-sentence
+ The commands @kbd{Meta-a} and @kbd{Meta-e} (@code{backward-sentence} and
+@code{forward-sentence}) move to the beginning and end of the current
+sentence, respectively. They were chosen to resemble @kbd{Control-a} and
+@kbd{Control-e}, which move to the beginning and end of a line. Unlike
+them, @kbd{Meta-a} and @w{@kbd{Meta-e}} if repeated or given numeric arguments
+move over successive sentences. Emacs assumes that the typist's convention
+is followed, and thus considers a sentence to end wherever there is a
+@samp{.}, @samp{?} or @samp{!} followed by the end of a line or two spaces,
+with any number of @samp{)}, @samp{]}, @samp{'}, or @samp{"} characters
+allowed in between. A sentence also begins or ends wherever a paragraph
+begins or ends.
+
+ Neither @kbd{M-a} nor @kbd{M-e} moves past the newline or spaces beyond
+the sentence edge at which it is stopping.
+
+@kindex M-k
+@kindex C-x DEL
+@findex kill-sentence
+@findex backward-kill-sentence
+ Just as @kbd{C-a} and @kbd{C-e} have a kill command, @kbd{C-k}, to go
+with them, so @kbd{M-a} and @kbd{M-e} have a corresponding kill command
+@kbd{M-k} (@code{kill-sentence}) which kills from point to the end of the
+sentence. With minus one as an argument it kills back to the beginning of
+the sentence. Larger arguments serve as a repeat count.@refill
+
+ There is a special command, @kbd{C-x @key{DEL}}
+(@code{backward-kill-sentence}) for killing back to the beginning of a
+sentence, because this is useful when you change your mind in the middle of
+composing text.@refill
+
+@vindex sentence-end
+ The variable @code{sentence-end} controls recognition of the end of a
+sentence. It is a regexp that matches the last few characters of a
+sentence, together with the whitespace following the sentence. Its
+normal value is
+
+@example
+"[.?!][]\"')]*\\($\\|\t\\| \\)[ \t\n]*"
+@end example
+
+@noindent
+This example is explained in the section on regexps. @xref{Regexps}.
+
+@node Paragraphs, Pages, Sentences, Text
+@section Paragraphs
+@cindex paragraphs
+@kindex M-[
+@kindex M-]
+@findex backward-paragraph
+@findex forward-paragraph
+
+ The Emacs commands for manipulating paragraphs are also @kbd{Meta-}
+keys.
+
+@table @kbd
+@item M-[
+@c !!! added @* to prevent overfull hbox
+Move back to previous paragraph beginning@*
+(@code{backward-paragraph}).
+@item M-]
+Move forward to next paragraph end (@code{forward-paragraph}).
+@item M-h
+Put point and mark around this or next paragraph (@code{mark-paragraph}).
+@end table
+
+ @kbd{Meta-[} moves to the beginning of the current or previous paragraph,
+while @kbd{Meta-]} moves to the end of the current or next paragraph.
+Blank lines and text formatter command lines separate paragraphs and are
+not part of any paragraph. Also, an indented line starts a new
+paragraph.
+
+ In major modes for programs (as opposed to Text mode), paragraphs begin
+and end only at blank lines. This makes the paragraph commands continue to
+be useful even though there are no paragraphs per se.
+
+ When there is a fill prefix, then paragraphs are delimited by all lines
+which don't start with the fill prefix. @xref{Filling}.
+
+@kindex M-h
+@findex mark-paragraph
+ When you wish to operate on a paragraph, you can use the command
+@kbd{Meta-h} (@code{mark-paragraph}) to set the region around it. This
+command puts point at the beginning and mark at the end of the paragraph
+point was in. If point is between paragraphs (in a run of blank lines, or
+at a boundary), the paragraph following point is surrounded by point and
+mark. If there are blank lines preceding the first line of the paragraph,
+one of these blank lines is included in the region. Thus, for example,
+@kbd{M-h C-w} kills the paragraph around or after point.
+
+@vindex paragraph-start
+@vindex paragraph-separate
+@c !!! Written verbosely to avoid overfull hbox
+ The precise definition of a paragraph boundary is controlled by the
+two variables @code{paragraph-separate} and @code{paragraph-start}. The value
+of @code{paragraph-start} is a regexp that should match any line that
+either starts or separates paragraphs. The value of
+@code{paragraph-separate} is another regexp that should match only lines
+that separate paragraphs without being part of any paragraph. Lines that
+start a new paragraph and are contained in it must match both regexps. For
+example, normally @code{paragraph-start} is @w{@code{"^[ @t{\}t@t{\}n@t{\}f]"}}
+and @code{paragraph-separate} is @w{@code{"^[ @t{\}t@t{\}f]*$"}}.
+
+ Normally it is desirable for page boundaries to separate paragraphs.
+The default values of these variables recognize the usual separator for
+pages.
+
+@node Pages, Filling, Paragraphs, Text
+@section Pages
+
+@cindex pages
+@cindex formfeed
+ Files are often thought of as divided into @dfn{pages} by the
+@dfn{formfeed} character (@sc{ascii} Control-L, octal code 014). For example,
+if a file is printed on a line printer, each page of the file, in this
+sense, will start on a new page of paper. Emacs treats a page-separator
+character just like any other character. It can be inserted with @kbd{C-q
+C-l}, or deleted with @key{DEL}. Thus, you are free to paginate your file
+or not. However, since pages are often meaningful divisions of the file,
+commands are provided to move over them and operate on them.
+
+@c WideCommands
+@table @kbd
+@item C-x [
+Move point to previous page boundary (@code{backward-page}).
+@item C-x ]
+Move point to next page boundary (@code{forward-page}).
+@item C-x C-p
+Put point and mark around this page (or another page) (@code{mark-page}).
+@item C-x l
+Count the lines in this page (@code{count-lines-page}).
+@end table
+
+@kindex C-x [
+@kindex C-x ]
+@findex forward-page
+@findex backward-page
+ The @kbd{C-x [} (@code{backward-page}) command moves point to immediately
+after the previous page delimiter. If point is already right after a page
+delimiter, it skips that one and stops at the previous one. A numeric
+argument serves as a repeat count. The @kbd{C-x ]} (@code{forward-page})
+command moves forward past the next page delimiter.
+
+@kindex C-x C-p
+@findex mark-page
+ The @kbd{C-x C-p} command (@code{mark-page}) puts point at the beginning
+of the current page and the mark at the end. The page delimiter at the end
+is included (the mark follows it). The page delimiter at the front is
+excluded (point follows it). This command can be followed by @kbd{C-w} to
+kill a page which is to be moved elsewhere. If it is inserted after a page
+delimiter, at a place where @kbd{C-x ]} or @kbd{C-x [} would take you, then
+the page will be properly delimited before and after once again.
+
+ A numeric argument to @kbd{C-x C-p} is used to specify which page to go
+to, relative to the current one. Zero means the current page. One means
+the next page, and @minus{}1 means the previous one.
+
+@kindex C-x l
+@findex count-lines-page
+ The @kbd{C-x l} command (@code{count-lines-page}) is good for deciding
+where to break a page in two. It prints in the echo area the total number
+of lines in the current page, and then divides it up into those preceding
+the current line and those following, as in
+
+@example
+Page has 96 (72+25) lines
+@end example
+
+@noindent
+ Notice that the sum is off by one; this is correct if point is not at the
+beginning of a line.
+
+@vindex page-delimiter
+ The variable @code{page-delimiter} should have as its value a regexp that
+matches the beginning of a line that separates pages. This is what defines
+where pages begin. The normal value of this variable is @code{"^@t{\}f"},
+which matches a formfeed character at the beginning of a line.
+
+@node Filling, Case, Pages, Text
+@section Filling Text
+@cindex filling
+@cindex wrapping
+
+ With Auto Fill mode, text can be @dfn{filled} (broken up into lines
+that fit in a specified width) as you insert it. If you alter existing
+text it may no longer be properly filled; then explicit commands for
+filling can be used. (Filling is sometimes called ``wrapping'' in the
+terminology used for other text editors, but we don't use that term,
+because it could just as well refer to the continuation of long lines
+which happens in Emacs if you @emph{don't} fill them.)
+
+@menu
+* Auto Fill:: Auto Fill mode breaks long lines automatically.
+* Fill Commands:: Commands to refill paragraphs and center lines.
+* Fill Prefix:: Filling when every line is indented or in a comment, etc.
+@end menu
+
+@node Auto Fill, Fill Commands, Filling, Filling
+@subsection Auto Fill Mode
+@cindex Auto Fill mode
+
+ @dfn{Auto Fill} mode is a minor mode in which lines are broken
+automatically when they become too wide. Breaking happens only when
+you type a @key{SPC} or @key{RET}.
+
+@table @kbd
+@item M-x auto-fill-mode
+Enable or disable Auto Fill mode.
+@item @key{SPC}
+@itemx @key{RET}
+In Auto Fill mode, break lines when appropriate.
+@end table
+
+@findex auto-fill-mode
+ @kbd{M-x auto-fill-mode} turns Auto Fill mode on if it was off, or off if
+it was on. With a positive numeric argument it always turns Auto Fill mode
+on, and with a negative argument always turns it off. You can see when
+Auto Fill mode is in effect by the presence of the word @samp{Fill} in the
+mode line, inside the parentheses. Auto Fill mode is a minor mode, turned
+on or off for each buffer individually. @xref{Minor Modes}.
+
+ In Auto Fill mode, lines are broken automatically at spaces when they get
+longer than the desired width. Line breaking and rearrangement takes place
+only when you type @key{SPC} or @key{RET}. If you wish to insert a space
+or newline without permitting line-breaking, type @kbd{C-q @key{SPC}} or
+@kbd{C-q @key{LFD}} (recall that a newline is really a linefeed). Also,
+@kbd{C-o} inserts a newline without line breaking.
+
+ Auto Fill mode works well with Lisp mode, because when it makes a new
+line in Lisp mode it indents that line with @key{TAB}. If a line ending in
+a comment gets too long, the text of the comment is split into two
+comment lines. Optionally new comment delimiters are inserted at the end of
+the first line and the beginning of the second so that each line is
+a separate comment; the variable @code{comment-multi-line} controls the
+choice (@pxref{Comments}).
+
+ Auto Fill mode does not refill entire paragraphs. It can break lines but
+cannot merge lines. So editing in the middle of a paragraph can result in
+a paragraph that is not correctly filled. The easiest way to make the
+paragraph properly filled again is usually with the explicit fill commands.
+
+ Many users like Auto Fill mode and want to use it in all text files.
+The section on init files says how to arrange this permanently for yourself.
+@xref{Init File}.
+
+@node Fill Commands, Fill Prefix, Auto Fill, Filling
+@subsection Explicit Fill Commands
+
+@table @kbd
+@item M-q
+Fill current paragraph (@code{fill-paragraph}).
+@item M-g
+Fill each paragraph in the region (@code{fill-region}).
+@item C-x f
+Set the fill column (@code{set-fill-column}).
+@item M-x fill-region-as-paragraph.
+Fill the region, considering it as one paragraph.
+@item M-s
+Center a line.
+@end table
+
+@kindex M-q
+@findex fill-paragraph
+ To refill a paragraph, use the command @kbd{Meta-q}
+(@code{fill-paragraph}). It causes the paragraph that point is inside, or
+the one after point if point is between paragraphs, to be refilled. All
+the line-breaks are removed, and then new ones are inserted where
+necessary. @kbd{M-q} can be undone with @kbd{C-_}. @xref{Undo}.@refill
+
+@kindex M-g
+@findex fill-region
+ To refill many paragraphs, use @kbd{M-g} (@code{fill-region}), which
+divides the region into paragraphs and fills each of them.
+
+@findex fill-region-as-paragraph
+ @kbd{Meta-q} and @kbd{Meta-g} use the same criteria as @kbd{Meta-h}
+for finding paragraph boundaries (@pxref{Paragraphs}). For more
+control, you can use @kbd{M-x fill-region-as-paragraph}, which refills
+everything between point and mark. This command recognizes no paragraph
+separators; it deletes any blank lines found within the region to be
+filled.@refill
+
+@cindex justification
+ A numeric argument to @kbd{M-g} or @kbd{M-q} causes it to @dfn{justify}
+the text as well as filling it. This means that extra spaces are inserted
+to make the right margin line up exactly at the fill column. To remove the
+extra spaces, use @kbd{M-q} or @kbd{M-g} with no argument.@refill
+
+@kindex M-s
+@cindex centering
+@findex center-line
+ The command @kbd{Meta-s} (@code{center-line}) centers the current line
+within the current fill column. With an argument, it centers several lines
+individually and moves past them.
+
+@vindex fill-column
+ The maximum line width for filling is in the variable @code{fill-column}.
+Altering the value of @code{fill-column} makes it local to the current
+buffer; until that time, the default value is in effect. The default is
+initially 70. @xref{Locals}.
+
+@kindex C-x f
+@findex set-fill-column
+ The easiest way to set @code{fill-column} is to use the command @kbd{C-x
+f} (@code{set-fill-column}). With no argument, it sets @code{fill-column}
+to the current horizontal position of point. With a numeric argument, it
+uses that as the new fill column.
+
+@node Fill Prefix,, Fill Commands, Filling
+@subsection The Fill Prefix
+
+@cindex fill prefix
+ To fill a paragraph in which each line starts with a special marker
+(which might be a few spaces, giving an indented paragraph), use the
+@dfn{fill prefix} feature. The fill prefix is a string which Emacs expects
+every line to start with, and which is not included in filling.
+
+@table @kbd
+@item C-x .
+Set the fill prefix (@code{set-fill-prefix}).
+@item M-q
+Fill a paragraph using current fill prefix (@code{fill-paragraph}).
+@item M-x fill-individual-paragraphs
+Fill the region, considering each change of indentation as starting a
+new paragraph.
+@end table
+
+@kindex C-x .
+@findex set-fill-prefix
+ To specify a fill prefix, move to a line that starts with the desired
+prefix, put point at the end of the prefix, and give the command
+@w{@kbd{C-x .}}@: (@code{set-fill-prefix}). That's a period after the
+@kbd{C-x}. To turn off the fill prefix, specify an empty prefix: type
+@w{@kbd{C-x .}}@: with point at the beginning of a line.
+
+ When a fill prefix is in effect, the fill commands remove the fill prefix
+from each line before filling and insert it on each line after filling.
+The fill prefix is also inserted on new lines made automatically by Auto
+Fill mode. Lines that do not start with the fill prefix are considered to
+start paragraphs, both in @kbd{M-q} and the paragraph commands; this is
+just right if you are using paragraphs with hanging indentation (every line
+indented except the first one). Lines which are blank or indented once the
+prefix is removed also separate or start paragraphs; this is what you want
+if you are writing multi-paragraph comments with a comment delimiter on
+each line.
+
+@vindex fill-prefix
+ The fill prefix is stored in the variable @code{fill-prefix}. Its value
+is a string, or @code{nil} when there is no fill prefix. This is a
+per-buffer variable; altering the variable affects only the current buffer,
+but there is a default value which you can change as well. @xref{Locals}.
+
+@findex fill-individual-paragraphs
+ Another way to use fill prefixes is through @kbd{M-x
+fill-individual-paragraphs}. This function divides the region into groups
+of consecutive lines with the same amount and kind of indentation and fills
+each group as a paragraph using its indentation as a fill prefix.
+
+@node Case,, Filling, Text
+@section Case Conversion Commands
+@cindex case conversion
+
+ Emacs has commands for converting either a single word or any arbitrary
+range of text to upper case or to lower case.
+
+@c WideCommands
+@table @kbd
+@item M-l
+Convert following word to lower case (@code{downcase-word}).
+@item M-u
+Convert following word to upper case (@code{upcase-word}).
+@item M-c
+Capitalize the following word (@code{capitalize-word}).
+@item C-x C-l
+Convert region to lower case (@code{downcase-region}).
+@item C-x C-u
+Convert region to upper case (@code{upcase-region}).
+@end table
+
+@kindex M-l
+@kindex M-u
+@kindex M-c
+@cindex words
+@findex downcase-word
+@findex upcase-word
+@findex capitalize-word
+ The word conversion commands are the most useful. @kbd{Meta-l}
+(@code{downcase-word}) converts the word after point to lower case,
+moving past it. Thus, repeating @kbd{Meta-l} converts successive
+words. @kbd{Meta-u} (@code{upcase-word}) converts to all capitals
+instead, while @kbd{Meta-c} (@code{capitalize-word}) puts the letter
+following point into upper case and the rest of the letters in the
+word into lower case. All these commands convert several words at
+once if given an argument. They are especially convenient for
+converting a large amount of text from all upper case to mixed case,
+because you can move through the text using @kbd{M-l}, @kbd{M-u} or
+@kbd{M-c} on each word as appropriate, occasionally using @kbd{M-f}
+instead to skip a word.
+
+ When given a negative argument, the word case conversion commands apply
+to the appropriate number of words before point, but do not move point.
+This is convenient when you have just typed a word in the wrong case: you
+can give the case conversion command and continue typing.
+
+ If a word case conversion command is given in the middle of a word, it
+applies only to the part of the word which follows point. This is just
+like what @kbd{Meta-d} (@code{kill-word}) does. With a negative argument,
+case conversion applies only to the part of the word before point.
+
+@kindex C-x C-l
+@kindex C-x C-u
+@cindex region
+@findex downcase-region
+@findex upcase-region
+ The other case conversion commands are @kbd{C-x C-u}
+(@code{upcase-region}) and @kbd{C-x C-l} (@code{downcase-region}), which
+convert everything between point and mark to the specified case. Point and
+mark do not move.@refill
+
+@node Programs, Compiling/Testing, Text, Top
+@chapter Editing Programs
+
+ Emacs has many commands designed to understand the syntax of programming
+languages such as Lisp and C. These commands can
+
+@itemize @bullet
+@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;
+functions, in C).
+@item
+Show how parentheses balance (@pxref{Matching}).
+@item
+Insert, kill or align comments (@pxref{Comments}).
+@item
+Follow the usual indentation conventions of the language
+(@pxref{Grinding}).
+@end itemize
+
+ The commands for words, sentences and paragraphs are very useful in
+editing code even though their canonical application is for editing human
+language text. Most symbols contain words (@pxref{Words}); sentences can
+be found in strings and comments (@pxref{Sentences}). Paragraphs per se
+are not present in code, but the paragraph commands are useful anyway,
+because Lisp mode and C mode define paragraphs to begin and end at blank
+lines (@pxref{Paragraphs}). Judicious use of blank lines to make the
+program clearer will also provide interesting chunks of text for the
+paragraph commands to work on.
+
+ The selective display feature is useful for looking at the overall
+structure of a function (@pxref{Selective Display}). This feature causes
+only the lines that are indented less than a specified amount to appear
+on the screen.
+
+@menu
+* Program Modes:: Major modes for editing programs.
+* Lists:: Expressions with balanced parentheses.
+ There are editing commands to operate on them.
+* Defuns:: Each program is made up of separate functions.
+ There are editing commands to operate on them.
+* Grinding:: Adjusting indentation to show the nesting.
+* Matching:: Insertion of a close-delimiter flashes matching open.
+* Comments:: Inserting, killing and aligning comments.
+* Macro Expansion:: How to see the results of C macro expansion.
+* Balanced Editing:: Inserting two matching parentheses at once, etc.
+* Lisp Completion:: Completion on symbol names in Lisp code.
+* Documentation:: Getting documentation of functions you plan to call.
+* 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.
+* Fortran:: Fortran mode and its special features.
+@end menu
+
+@node Program Modes, Lists, Programs, Programs
+@section Major Modes for Programming Languages
+
+@cindex Lisp mode
+@cindex C mode
+@cindex Scheme mode
+ Emacs has 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 that 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 forms 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.
+
+@kindex DEL
+@findex backward-delete-char-untabify
+ In most programming languages, indentation is likely to vary from line to
+line. So the major modes for those languages rebind @key{DEL} to treat a
+tab as if it were the equivalent number of spaces (using the command
+@code{backward-delete-char-untabify}). This makes it possible to rub out
+indentation one column at a time without worrying whether it is made up of
+spaces or tabs. Use @kbd{C-b C-d} to delete a tab character before point,
+in these modes.
+
+ Programming language modes define paragraphs to be separated only by
+blank lines, so that the paragraph commands remain useful. Auto Fill mode,
+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
+
+@cindex Control-Meta
+ By convention, Emacs keys for dealing with balanced expressions are
+usually @kbd{Control-Meta-} characters. They tend to be analogous in
+function to their @kbd{Control-} and @kbd{Meta-} equivalents. These commands
+are usually thought of as pertaining to expressions in programming
+languages, but can be useful with any language in which some sort of
+parentheses exist (including English).
+
+@cindex list
+@cindex sexp
+@cindex expression
+ These commands fall into two classes. Some deal only with @dfn{lists}
+(parenthetical groupings). They see nothing except parentheses, brackets,
+braces (whichever ones must balance in the language you are working with),
+and escape characters that might be used to quote those.
+
+ The other commands deal with expressions or @dfn{sexps}. The word `sexp'
+is derived from @dfn{s-expression}, the ancient term for an expression in
+Lisp. But in Emacs, the notion of `sexp' is not limited to Lisp. It
+refers to an expression in whatever language your program is written in.
+Each programming language has its own major mode, which customizes the
+syntax tables so that expressions in that language count as sexps.
+
+ Sexps typically include symbols, numbers, and string constants, as well
+as anything contained in parentheses, brackets or braces.
+
+ In languages that use prefix and infix operators, such as C, it is not
+possible for all expressions to be sexps. For example, C mode does not
+recognize @samp{foo + bar} as a sexp, even though it @i{is} a C expression;
+it recognizes @samp{foo} as one sexp and @samp{bar} as another, with the
+@samp{+} as punctuation between them. This is a fundamental ambiguity:
+both @samp{foo + bar} and @samp{foo} are legitimate choices for the sexp to
+move over if point is at the @samp{f}. Note that @samp{(foo + bar)} is a
+sexp in C mode.
+
+ Some languages have obscure forms of syntax for expressions that nobody
+has bothered to make Emacs understand properly.
+
+@c doublewidecommands
+@table @kbd
+@item C-M-f
+Move forward over a sexp (@code{forward-sexp}).
+@item C-M-b
+Move backward over a sexp (@code{backward-sexp}).
+@item C-M-k
+Kill sexp forward (@code{kill-sexp}).
+@item C-M-u
+Move up and backward in list structure (@code{backward-up-list}).
+@item C-M-d
+Move down and forward in list structure (@code{down-list}).
+@item C-M-n
+Move forward over a list (@code{forward-list}).
+@item C-M-p
+Move backward over a list (@code{backward-list}).
+@item C-M-t
+Transpose expressions (@code{transpose-sexps}).
+@item C-M-@@
+Put mark after following expression (@code{mark-sexp}).
+@end table
+
+@kindex C-M-f
+@kindex C-M-b
+@findex forward-sexp
+@findex backward-sexp
+ To move forward over a sexp, use @kbd{C-M-f} (@code{forward-sexp}). If
+the first significant character after point is an opening delimiter
+(@samp{(} in Lisp; @samp{(}, @samp{[} or @samp{@{} in C), @kbd{C-M-f}
+moves past the matching closing delimiter. If the character begins a
+symbol, string, or number, @kbd{C-M-f} moves over that. If the character
+after point is a closing delimiter, @kbd{C-M-f} gets an error.
+
+ The command @kbd{C-M-b} (@code{backward-sexp}) moves backward over a
+sexp. The detailed rules are like those above for @kbd{C-M-f}, but with
+directions reversed. If there are any prefix characters (singlequote,
+backquote and comma, in Lisp) preceding the sexp, @kbd{C-M-b} moves back
+over them as well.
+
+ @kbd{C-M-f} or @kbd{C-M-b} with an argument repeats that operation the
+specified number of times; with a negative argument, it moves in the
+opposite direction.
+
+ The sexp commands move across comments as if they were whitespace, in
+languages such as C where the comment-terminator can be recognized. 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 a sexp at a time can be done with @kbd{C-M-k} (@code{kill-sexp}).
+@kbd{C-M-k} kills the characters that @kbd{C-M-f} would move over.
+
+@kindex C-M-n
+@kindex C-M-p
+@findex forward-list
+@findex backward-list
+ The @dfn{list commands} move over lists like the sexp commands but skip
+blithely over any number of other kinds of sexps (symbols, strings, etc).
+They are @kbd{C-M-n} (@code{forward-list}) and @kbd{C-M-p}
+(@code{backward-list}). The main reason they are useful is that they
+usually ignore comments (since the comments usually do not contain any
+lists).@refill
+
+@kindex C-M-u
+@kindex C-M-d
+@findex backward-up-list
+@findex down-list
+ @kbd{C-M-n} and @kbd{C-M-p} stay at the same level in parentheses, when
+that's possible. To move @i{up} one (or @var{n}) levels, use @kbd{C-M-u}
+(@code{backward-up-list}).
+@kbd{C-M-u} moves backward up past one unmatched opening delimiter. A
+positive argument serves as a repeat count; a negative argument reverses
+direction of motion and also requests repetition, so it moves forward and
+up one or more levels.@refill
+
+ To move @i{down} in list structure, use @kbd{C-M-d} (@code{down-list}). In Lisp mode,
+where @samp{(} is the only opening delimiter, this is nearly the same as
+searching for a @samp{(}. An argument specifies the number of levels
+of parentheses to go down.
+
+@cindex transposition
+@kindex C-M-t
+@findex transpose-sexps
+ A somewhat random-sounding command which is nevertheless easy to use is
+@kbd{C-M-t} (@code{transpose-sexps}), which drags the previous sexp across
+the next one. An argument serves as a repeat count, and a negative
+argument drags backwards (thus canceling out the effect of @kbd{C-M-t} with
+a positive argument). An argument of zero, rather than doing nothing,
+transposes the sexps ending after point and the mark.
+
+@kindex C-M-@@
+@findex mark-sexp
+ To make the region be the next sexp in the buffer, use @kbd{C-M-@@}
+(@code{mark-sexp}) which sets mark at the same place that @kbd{C-M-f} would
+move to. @kbd{C-M-@@} takes arguments like @kbd{C-M-f}. In particular, a
+negative argument is useful for putting the mark at the beginning of the
+previous sexp.
+
+ The list and sexp commands' understanding of syntax is completely
+controlled by the syntax table. Any character can, for example, be
+declared to be an opening delimiter and act like an open parenthesis.
+@xref{Syntax}.
+
+@node Defuns, Grinding, Lists, Programs
+@section Defuns
+@cindex defuns
+
+ In Emacs, a parenthetical grouping at the top level in the buffer is
+called a @dfn{defun}. The name derives from the fact that most top-level
+lists in a Lisp file are instances of the special form @code{defun}, but
+any top-level parenthetical grouping counts as a defun in Emacs parlance
+regardless of what its contents are, and regardless of the programming
+language in use. For example, in C, the body of a function definition is a
+defun.
+
+@c doublewidecommands
+@table @kbd
+@item C-M-a
+Move to beginning of current or preceding defun
+(@code{beginning-of-defun}).
+@item C-M-e
+Move to end of current or following defun (@code{end-of-defun}).
+@item C-M-h
+Put region around whole current or following defun (@code{mark-defun}).
+@end table
+
+@kindex C-M-a
+@kindex C-M-e
+@kindex C-M-h
+@findex beginning-of-defun
+@findex end-of-defun
+@findex mark-defun
+ The commands to move to the beginning and end of the current defun are
+@kbd{C-M-a} (@code{beginning-of-defun}) and @kbd{C-M-e} (@code{end-of-defun}).
+
+ If you wish to operate on the current defun, use @kbd{C-M-h}
+(@code{mark-defun}) which puts point at the beginning and mark at the end
+of the current or next defun. For example, this is the easiest way to get
+ready to move the defun to a different place in the text. In C mode,
+@kbd{C-M-h} runs the function @code{mark-c-function}, which is almost the
+same as @code{mark-defun}; the difference is that it backs up over the
+argument declarations, function name and returned data type so that the
+entire C function is inside the region.
+
+ Emacs assumes that any open-parenthesis found in the leftmost column is
+the start of a defun. Therefore, @b{never put an open-parenthesis at the
+left margin in a Lisp file unless it is the start of a top level list.
+Never put an open-brace or other opening delimiter at the beginning of a
+line of C code unless it starts the body of a function.} The most likely
+problem case is when you want an opening delimiter at the start of a line
+inside a string. To avoid trouble, put an escape character (@samp{\}, in C
+and Emacs Lisp, @samp{/} in some other Lisp dialects) before the opening
+delimiter. It will not affect the contents of the string.
+
+ In the remotest past, the original Emacs found defuns by moving upward a
+level of parentheses until there were no more levels to go up. This always
+required scanning all the way back to the beginning of the buffer, even for
+a small function. To speed up the operation, Emacs was changed to assume
+that any @samp{(} (or other character assigned the syntactic class of
+opening-delimiter) at the left margin is the start of a defun. This
+heuristic was nearly always right and avoided the costly scan; however,
+it mandated the convention described above.
+
+@node Grinding, Matching, Defuns, Programs
+@section Indentation for Programs
+@cindex indentation
+@cindex grinding
+
+ The best way to keep a program properly indented (``ground'') is to use
+Emacs to re-indent it as you change it. Emacs has commands to indent
+properly either a single line, a specified number of lines, or all of the
+lines inside a single parenthetical grouping.
+
+@menu
+* 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
+@subsection Basic Program Indentation Commands
+
+@c WideCommands
+@table @kbd
+@item @key{TAB}
+Adjust indentation of current line.
+@item @key{LFD}
+Equivalent to @key{RET} followed by @key{TAB} (@code{newline-and-indent}).
+@end table
+
+@kindex TAB
+@findex c-indent-line
+@findex lisp-indent-line
+ The basic indentation command is @key{TAB}, which gives the current line
+the correct indentation as determined from the previous lines. The
+function that @key{TAB} runs depends on the major mode; it is @code{lisp-indent-line}
+in Lisp mode, @code{c-indent-line} in C mode, etc. These functions
+understand different syntaxes for different languages, but they all do
+about the same thing. @key{TAB} in any programming language major mode
+inserts or deletes whitespace at the beginning of the current line,
+independent of where point is in the line. If point is inside the
+whitespace at the beginning of the line, @key{TAB} leaves it at the end of
+that whitespace; otherwise, @key{TAB} leaves point fixed with respect to
+the characters around it.
+
+ Use @kbd{C-q @key{TAB}} to insert a tab at point.
+
+@kindex LFD
+@findex newline-and-indent
+ When entering a large amount of new code, use @key{LFD} (@code{newline-and-indent}),
+which is equivalent to a @key{RET} followed by a @key{TAB}. @key{LFD} creates
+a blank line, and then gives it the appropriate indentation.
+
+ @key{TAB} indents the second and following lines of the body of a
+parenthetical grouping each under the preceding one; therefore, if you
+alter one line's indentation to be nonstandard, the lines below will tend
+to follow it. This is the right behavior in cases where the standard
+result of @key{TAB} is unaesthetic.
+
+ Remember that an open-parenthesis, open-brace or other opening delimiter
+at the left margin is assumed by Emacs (including the indentation routines)
+to be the start of a function. Therefore, you must never have an opening
+delimiter in column zero that is not the beginning of a function, not even
+inside a string. This restriction is vital for making the indentation
+commands fast; you must simply accept it. @xref{Defuns}, for more
+information on this.
+
+@node Multi-line Indent, Lisp Indent, Basic Indent, Grinding
+@subsection Indenting Several Lines
+
+ When you wish to re-indent several lines of code which have been altered
+or moved to a different level in the list structure, you have several
+commands available.
+
+@table @kbd
+@item C-M-q
+Re-indent all the lines within one list (@code{indent-sexp}).
+@item C-u @key{TAB}
+Shift an entire list rigidly sideways so that its first line
+is properly indented.
+@item C-M-\
+Re-indent all lines in the region (@code{indent-region}).
+@end table
+
+@kindex C-M-q
+@findex indent-sexp
+@findex indent-c-exp
+ You can re-indent the contents of a single list by positioning point
+before the beginning of it and typing @kbd{C-M-q} (@code{indent-sexp} in
+Lisp mode, @code{indent-c-exp} in C mode; also bound to other suitable
+functions in other modes). The indentation of the line the sexp starts on
+is not changed; therefore, only the relative indentation within the list,
+and not its position, is changed. To correct the position as well, type a
+@key{TAB} before the @kbd{C-M-q}.
+
+@kindex C-u TAB
+ If the relative indentation within a list is correct but the indentation
+of its beginning is not, go to the line the list begins on and type
+@kbd{C-u @key{TAB}}. When @key{TAB} is given a numeric argument, it moves all the
+lines in the grouping starting on the current line sideways the same amount
+that the current line moves. It is clever, though, and does not move lines
+that start inside strings, or C preprocessor lines when in C mode.
+
+@kindex C-M-\
+@findex indent-region
+ Another way to specify the range to be re-indented is with point and
+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
+@subsection Customizing Lisp Indentation
+@cindex customization
+
+ The indentation pattern for a Lisp expression can depend on the function
+called by the expression. For each Lisp function, you can choose among
+several predefined patterns of indentation, or define an arbitrary one with
+a Lisp program.
+
+ The standard pattern of indentation is as follows: the second line of the
+expression is indented under the first argument, if that is on the same
+line as the beginning of the expression; otherwise, the second line is
+indented underneath the function name. Each following line is indented
+under the previous line whose nesting depth is the same.
+
+@vindex lisp-indent-offset
+ If the variable @code{lisp-indent-offset} is non-@code{nil}, it overrides
+the usual indentation pattern for the second line of an expression, so that
+such lines are always indented @code{lisp-indent-offset} more columns than
+the containing list.
+
+@vindex lisp-body-indent
+ The standard pattern is overridden for certain functions. Functions
+whose names start with @code{def} always indent the second line by
+@code{lisp-body-indention} extra columns beyond the open-parenthesis
+starting the expression.
+
+ The standard pattern can be overridden in various ways for individual
+functions, according to the @code{lisp-indent-hook} property of the
+function name. There are four possibilities for this property:
+
+@table @asis
+@item @code{nil}
+This is the same as no property; the standard indentation pattern is used.
+@item @code{defun}
+The pattern used for function names that start with @code{def} is used for
+this function also.
+@item a number, @var{number}
+The first @var{number} arguments of the function are
+@dfn{distinguished} arguments; the rest are considered the @dfn{body}
+of the expression. A line in the expression is indented according to
+whether the first argument on it is distinguished or not. If the
+argument is part of the body, the line is indented @code{lisp-body-indent}
+more columns than the open-parenthesis starting the containing
+expression. If the argument is distinguished and is either the first
+or second argument, it is indented @i{twice} that many extra columns.
+If the argument is distinguished and not the first or second argument,
+the standard pattern is followed for that line.
+@item a symbol, @var{symbol}
+@var{symbol} should be a function name; that function is called to
+calculate the indentation of a line within this expression. The
+function receives two arguments:
+@table @asis
+@item @var{state}
+The value returned by @code{parse-partial-sexp} (a Lisp primitive for
+indentation and nesting computation) when it parses up to the
+beginning of this line.
+@item @var{pos}
+The position at which the line being indented begins.
+@end table
+@noindent
+It should return either a number, which is the number of columns of
+indentation for that line, or a list whose @sc{car} is such a number. The
+difference between returning a number and returning a list is that a
+number says that all following lines at the same nesting level should
+be indented just like this one; a list says that following lines might
+call for different indentations. This makes a difference when the
+indentation is being computed by @kbd{C-M-q}; if the value is a
+number, @kbd{C-M-q} need not recalculate indentation for the following
+lines 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 @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,
+then @key{TAB} just inserts a tab character in the buffer. Normally,
+this variable is @code{t}, 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 if or body of a while.
+@item c-brace-offset
+Extra indentation for line if it starts 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 line that is a label, or 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. I prefer 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 nonblank character on the line. By setting
+this 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
+will line up right under the open brace. But there is an exception made
+for braces in column zero, such as surrounding a function's body. The
+statements just inside it do not go at column zero. Instead,
+@code{c-brace-offset} and @w{@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 that are within other
+statements, such as the then-clauses of @code{if} statements and the bodies
+of @code{while} statements. This parameter is the difference in
+indentation between the two lines in
+
+@example
+if (x == y)
+ do_it ();
+@end example
+
+@noindent
+Its standard value 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 @code{c-brace-offset} were set to 4, the first example would become
+
+@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, resulting
+in code like this:
+
+@example
+char *
+index (string, c)
+ char *string;
+ int c;
+@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, resulting 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
+standard values.
+
+ I strongly recommend that you try out the indentation style produced by
+the standard settings of these variables, together with putting open braces
+on separate lines. You can see how it looks in all the C source files of
+GNU Emacs.
+
+@node Matching, Comments, Grinding, Programs
+@section Automatic Display Of Matching Parentheses
+@cindex matching parentheses
+@cindex parentheses
+
+ The Emacs parenthesis-matching feature is designed to show automatically
+how parentheses match in the text. Whenever a self-inserting character
+that is a closing delimiter is typed, the cursor moves momentarily to the
+location of the matching opening delimiter, provided that is on the screen.
+If it is not on the screen, some text starting with that opening delimiter
+is displayed in the echo area. Either way, you can tell what grouping is
+being closed off.
+
+ In Lisp, automatic matching applies only to parentheses. In C, it
+applies to braces and brackets too. Emacs knows which characters to regard
+as matching delimiters based on the syntax table, which is set by the major
+mode. @xref{Syntax}.
+
+ If the opening delimiter and closing delimiter are mismatched---such as
+in @samp{[x)}---a warning message is displayed in the echo area. The
+correct matches are specified in the syntax table.
+
+@vindex blink-matching-paren
+@vindex blink-matching-paren-distance
+ Two variables control parenthesis match display. @code{blink-matching-paren}
+turns the feature on or off; @code{nil} turns it off, but the default is
+@code{t} to turn match display on. @code{blink-matching-paren-distance}
+specifies how many characters back to search to find the matching opening
+delimiter. If the match is not found in that far, scanning stops, and
+nothing is displayed. This is to prevent scanning for the matching
+delimiter from wasting lots of time when there is no match. The default
+is 4000.
+
+@node Comments, Macro Expansion, Matching, Programs
+@section Manipulating Comments
+@cindex comments
+@kindex M-;
+@cindex indentation
+@findex indent-for-comment
+
+ The comment commands insert, kill and align comments.
+
+@c WideCommands
+@table @kbd
+@item M-;
+Insert or align comment (@code{indent-for-comment}).
+@item C-x ;
+Set comment column (@code{set-comment-column}).
+@item C-u - C-x ;
+Kill comment on current line (@code{kill-comment}).
+@item M-@key{LFD}
+Like @key{RET} followed by inserting and aligning a comment
+(@code{indent-new-comment-line}).
+@end table
+
+ The command that creates a comment is @kbd{Meta-;} (@code{indent-for-comment}).
+If there is no comment already on the line, a new comment is created,
+aligned at a specific column called the @dfn{comment column}. The comment
+is created by inserting the string Emacs thinks comments should start with
+(the value of @code{comment-start}; see below). Point is left after that
+string. If the text of the line extends past the comment column, then the
+indentation is done to a suitable boundary (usually, at least one space is
+inserted). If the major mode has specified a string to terminate comments,
+that is inserted after point, to keep the syntax valid.
+
+ @kbd{Meta-;} can also be used to align an existing comment. If a line
+already contains the string that starts comments, then @kbd{M-;} just moves
+point after it and re-indents it to the conventional place. Exception:
+comments starting in column 0 are not moved.
+
+ Some major modes have special rules for indenting certain kinds of
+comments in certain contexts. For example, in Lisp code, comments which
+start with two semicolons are indented as if they were lines of code,
+instead of at the comment column. Comments which start with three
+semicolons are supposed to start at the left margin. Emacs understands
+these conventions by indenting a double-semicolon comment using @key{TAB},
+and by not changing the indentation of a triple-semicolon comment at all.
+
+@example
+;; This function is just an example
+;;; Here either two or three semicolons are appropriate.
+(defun foo (x)
+;;; And now, the first part of the function:
+ ;; The following line adds one.
+ (1+ x)) ; This line adds one.
+@end example
+
+ In C code, a comment preceded on its line by nothing but whitespace
+is indented like a line of code.
+
+ Even when an existing comment is properly aligned, @kbd{M-;} is still
+useful for moving directly to the start of the comment.
+
+@kindex C-u - C-x ;
+@findex kill-comment
+ @kbd{C-u - C-x ;} (@code{kill-comment}) kills the comment on the current line,
+if there is one. The indentation before the start of the comment is killed
+as well. If there does not appear to be a comment in the line, nothing is
+done. To reinsert the comment on another line, move to the end of that
+line, do @kbd{C-y}, and then do @kbd{M-;} to realign it. Note that
+@kbd{C-u - C-x ;} is not a distinct key; it is @kbd{C-x ;} (@code{set-comment-column})
+with a negative argument. That command is programmed so that when it
+receives a negative argument it calls @code{kill-comment}. However,
+@code{kill-comment} is a valid command which you could bind directly to a
+key if you wanted to.
+
+@subsection Multiple Lines of Comments
+
+@kindex M-LFD
+@cindex blank lines
+@findex indent-new-comment-line
+ If you are typing a comment and find that you wish to continue it on
+another line, you can use the command @kbd{Meta-@key{LFD}} (@code{indent-new-comment-line}),
+which terminates the comment you are typing, creates a new blank line
+afterward, and begins a new comment indented under the old one. When Auto
+Fill mode is on, going past the fill column while typing a comment causes
+the comment to be continued in just this fashion. If point is not at the
+end of the line when @kbd{M-@key{LFD}} is typed, the text on the rest of
+the line becomes part of the new comment line.
+
+@subsection Options Controlling Comments
+
+@vindex comment-column
+@kindex C-x ;
+@findex set-comment-column
+ The comment column is stored in the variable @code{comment-column}. You
+can set it to a number explicitly. Alternatively, the command @kbd{C-x ;}
+(@code{set-comment-column}) sets the comment column to the column point is
+at. @w{@kbd{C-u C-x ;}} sets the comment column to match the last comment
+before point in the buffer, and then does a @kbd{Meta-;} to align the
+current line's comment under the previous one. Note that @kbd{C-u - C-x ;}
+runs the function @code{kill-comment} as described above.
+
+ @code{comment-column} is a per-buffer variable; altering the variable
+affects only the current buffer, but there is a default value which you can
+change as well. @xref{Locals}. Many major modes initialize this variable
+for the current buffer.
+
+@vindex comment-start-skip
+ The comment commands recognize comments based on the regular expression
+that is the value of the variable @code{comment-start-skip}. This regexp
+should not match the null string. It may match more than the comment
+starting delimiter in the strictest sense of the word; for example, in C
+mode the value of the variable is @code{@t{"/\\*+ *"}}, which matches extra
+stars and spaces after the @samp{/*} itself. (Note that @samp{\\} is
+needed in Lisp syntax to include a @samp{\} in the string, which is needed
+to deny the first star its special meaning in regexp syntax. @xref{Regexps}.)
+
+@vindex comment-start
+@vindex comment-end
+ When a comment command makes a new comment, it inserts the value of
+@code{comment-start} to begin it. The value of @code{comment-end} is
+inserted after point, so that it will follow the text that you will insert
+into the comment. In C mode, @code{comment-start} has the value
+@w{@code{"/* "}} and @code{comment-end} has the value @w{@code{" */"}}.
+
+@vindex comment-multi-line
+ @code{comment-multi-line} controls how @kbd{M-@key{LFD}} (@code{indent-new-comment-line})
+behaves when used inside a comment. If @code{comment-multi-line} is
+@code{nil}, as it normally is, then the comment on the starting line is
+terminated and a new comment is started on the new following line. If
+@code{comment-multi-line} is not @code{nil}, then the new following line is
+set up as part of the same comment that was found on the starting line.
+This is done by not inserting a terminator on the old line, and not
+inserting a starter on the new line. In languages where multi-line comments
+work, the choice of value for this variable is a matter of taste.
+
+@vindex comment-indent-hook
+ The variable @code{comment-indent-hook} should contain a function that
+will be called to compute the indentation for a newly inserted comment or
+for aligning an existing comment. It is set differently by various major
+modes. The function is called with no arguments, but with point at the
+beginning of the comment, or at the end of a line if a new comment is to be
+inserted. It should return the column in which the comment ought to start.
+For example, in Lisp mode, the indent hook function bases its decision
+on how many semicolons begin an existing comment, and on the code in the
+preceding lines.
+
+@node Macro Expansion, Balanced Editing, Comments, Programs
+@section Viewing How C Macros Expand
+@cindex macro expansion in C
+@cindex expansion of C macros
+
+@findex c-macro-expand
+When you are debugging C code that uses macros, sometimes it is hard to
+figure out precisely how the macros expand. The command @kbd{M-x
+c-macro-expand}. It runs the C preprocessor and shows you what
+expansion results from the region. The portion of the buffer before the
+region is also included in preprocessing, for the sake of macros defined
+there, but the output from this part isn't shown.
+
+@node Balanced Editing, Lisp Completion, Macro Expansion, Programs
+@section Editing Without Unbalanced Parentheses
+
+@table @kbd
+@item M-(
+Put parentheses around next sexp(s) (@code{insert-parentheses}).
+@item M-)
+Move past next close parenthesis and re-indent
+(@code{move-over-close-and-reindent}).
+@end table
+
+@kindex M-(
+@kindex M-)
+@findex insert-parentheses
+@findex move-over-close-and-reindent
+ The two commands, @kbd{M-(} (@code{insert-parentheses}) and @kbd{M-)}
+(@code{move-over-close-and-reindent}), are designed to facilitate a style of
+editing which keeps parentheses balanced at all times. @kbd{M-(} inserts a
+pair of parentheses, either together as in @samp{()}, or, if given an
+argument, around the next several sexps, and leaves point after the open
+parenthesis. Instead of typing @w{@kbd{( F O O )}}, you can type @kbd{M-( F O
+O}, which has the same effect except for leaving the cursor before the
+close parenthesis. Then you would type @kbd{M-)}, which moves past the
+close parenthesis, deleting any indentation preceding it (in this example
+there is none), and indenting with @key{LFD} after it.
+
+@node Lisp Completion, Documentation, Balanced Editing, Programs
+@section Completion for Lisp Symbols
+@cindex completion (symbol names)
+
+ Usually completion happens in the minibuffer. But one kind of completion
+is available in all buffers: completion for Lisp symbol names.
+
+@kindex M-TAB
+@findex lisp-complete-symbol
+ The command @kbd{M-@key{TAB}} (@code{lisp-complete-symbol}) takes the
+partial Lisp symbol before point to be an abbreviation, and compares it
+against all nontrivial Lisp symbols currently known to Emacs. Any
+additional characters that they all have in common are inserted at point.
+Nontrivial symbols are those that have function definitions, values or
+properties.
+
+ If there is an open-parenthesis immediately before the beginning of
+the partial symbol, only symbols with function definitions are considered
+as completions.
+
+ If the partial name in the buffer has more than one possible completion
+and they have no additional characters in common, a list of all possible
+completions is displayed in another window.
+
+@node Documentation, Change Log, Lisp Completion, Programs
+@section Documentation Commands
+
+@kindex C-h f
+@findex describe-function
+@kindex C-h v
+@findex describe-variable
+ As you edit Lisp code to be run in Emacs, the commands @kbd{C-h f}
+(@code{describe-function}) and @kbd{C-h v} (@code{describe-variable}) can
+be used to print documentation of functions and variables that you want to
+call. These commands use the minibuffer to read the name of a function or
+variable to document, and display the documentation in a window.
+
+ For extra convenience, these commands provide default arguments based on
+the code in the neighborhood of point. @kbd{C-h f} sets the default to the
+function called in the innermost list containing point. @kbd{C-h v} uses
+the symbol name around or adjacent to point as its default.
+
+@findex manual-entry
+ Documentation on Unix commands, system calls and libraries can be
+obtained with the @kbd{M-x manual-entry} command. This reads a topic as an
+argument, and displays the text on that topic from the Unix manual.
+@code{manual-entry} always searches all 8 sections of the manual, and
+concatenates all the entries that are found. For example, the topic
+@samp{termcap} finds the description of the termcap library from section 3,
+followed by the description of the termcap data base from section 5.
+
+@node Change Log, Tags, Documentation, Programs
+@section Change Logs
+
+@cindex change log
+@findex add-change-log-entry
+ The Emacs command @kbd{M-x add-change-log-entry} helps you keep a record
+of when and why you have changed a program. It assumes that you have a
+file in which you write a chronological sequence of entries describing
+individual changes. The default is to store the change entries in a file
+called @file{ChangeLog} in the same directory as the file you are editing.
+The same @file{ChangeLog} file therefore records changes for all the files
+in the directory.
+
+ A change log entry starts with a header line that contains your name and
+the current date. Aside from these header lines, every line in the
+change log starts with a tab. One entry can describe several changes;
+each change starts with a line starting with a tab and a star.
+@kbd{M-x add-change-log-entry} visits the change log file and creates
+a new entry unless the most recent entry is for today's date and your
+name. In either case, it adds a new line to start the description of
+another change just after the header line of the entry. When @kbd{M-x
+add-change-log-entry} is finished, all is prepared for you to edit in
+the description of what you changed and how. You must then save the
+change log file yourself.
+
+ The change log file is always visited in Indented Text mode, which means
+that @key{LFD} and auto-filling indent each new line like the previous
+line. This is convenient for entering the contents of an entry, which must
+all be indented. @xref{Text Mode}.
+
+@findex add-change-log-entry-other-window
+@kindex C-x 4 a
+ An alternative convenient command for starting a change log entry is
+@w{@kbd{C-x 4 a}} (@code{add-change-log-entry-other-window}). It resembles
+@code{add-change-log-entry} except that it visits the change log in
+another window, and always uses the file @file{./ChangeLog}---it does
+not ask you for the file name.
+
+ Here is an example of the formatting conventions used in the change log
+for Emacs:
+
+@smallexample
+@group
+Wed Jun 26 19:29:32 1985 Richard M. Stallman (rms at mit-prep)
+
+ * xdisp.c (try_window_id):
+ If C-k is done at end of next-to-last line,
+ this fn updates window_end_vpos and cannot leave
+ window_end_pos nonnegative (it is zero, in fact).
+ If display is preempted before lines are output,
+ this is inconsistent. Fix by setting
+ blank_end_of_window to nonzero.
+@end group
+
+@group
+Tue Jun 25 05:25:33 1985 Richard M. Stallman (rms at mit-prep)
+
+ * cmds.c (Fnewline):
+ Call the auto fill hook if appropriate.
+@end group
+
+@group
+ * xdisp.c (try_window_id):
+ If point is found by compute_motion after xp, record that
+ permanently. If display_text_line sets point position wrong
+ (case where line is killed, point is at eob and that line is
+ not displayed), set it again in final compute_motion.
+@end group
+@end smallexample
+
+@node Tags, Fortran, Change Log, Programs
+@section Tag Tables
+@cindex tag table
+
+ A @dfn{tag table} is a description of how a multi-file program is broken
+up into files. It lists the names of the component files and the names and
+positions of the functions in each file. Grouping the related files makes
+it possible to search or replace through all the files with one command.
+Recording the function names and positions makes possible the @kbd{Meta-.}
+command which you can use to find the definition of a function without
+having to know which of the files it is in.
+
+ Tag tables are stored in files called @dfn{tag table files}. The
+conventional name for a tag table file is @file{TAGS}.
+
+ Each entry in the tag table records the name of one tag, the name of the
+file that the tag is defined in (implicitly), and the position in that file
+of the tag's definition.
+
+ Just what names from the described files are recorded in the tag table
+depends on the programming language of the described file. They normally
+include all functions and subroutines, and may also include global
+variables, data types, and anything else convenient. In any case, each
+name recorded is called a @dfn{tag}.
+
+@menu
+* Tag Syntax::
+* Create Tag Table::
+* Select Tag Table::
+* Find Tag::
+* Tags Search::
+* Tags Stepping::
+* List Tags::
+@end menu
+
+@node Tag Syntax, Create Tag Table, Tags, Tags
+@subsection Source File Tag Syntax
+
+ In Lisp code, any function defined with @code{defun}, any variable
+defined with @code{defvar} or @code{defconst}, and in general the first
+argument of any expression that starts with @samp{(def} in column zero, is
+a tag.
+
+ In C code, any C function is a tag, and so is any typedef if @code{-t} is
+specified when the tag table is constructed.
+
+ In Fortran code, functions and subroutines are tags.
+
+ In La@TeX{} text, the argument of any of the commands @code{\chapter},
+@code{\section}, @code{\subsection}, @code{\subsubsection}, @code{\eqno},
+@code{\label}, @code{\ref}, @code{\cite}, @code{\bibitem} and
+@code{\typeout} is a tag.@refill
+
+@node Create Tag Table, Select Tag Table, Tag Syntax, Tags
+@subsection Creating Tag Tables
+@cindex etags program
+
+ The @code{etags} program is used to create a tag table file. It knows
+the syntax of C, Fortran, La@TeX{}, Scheme and Emacs Lisp/Common Lisp. To
+use @code{etags}, type
+
+@example
+etags @var{inputfiles}@dots{}
+@end example
+
+@noindent
+as a shell command. It reads the specified files and writes a tag table
+named @file{TAGS} in the current working directory. @code{etags}
+recognizes the language used in an input file based on its file name and
+contents; there are no switches for specifying the language. The @code{-t}
+switch tells @code{etags} to record typedefs in C code as tags.
+
+ If the tag table data become outdated due to changes in the files
+described in the table, the way to update the tag table is the same way it
+was made in the first place. It is not necessary to do this often.
+
+ If the tag table fails to record a tag, or records it for the wrong file,
+then Emacs cannot possibly find its definition. However, if the position
+recorded in the tag table becomes a little bit wrong (due to some editing
+in the file that the tag definition is in), the only consequence is to slow
+down finding the tag slightly. Even if the stored position is very wrong,
+Emacs will still find the tag, but it must search the entire file for it.
+
+ So you should update a tag table when you define new tags that you want
+to have listed, or when you move tag definitions from one file to another,
+or when changes become substantial. Normally there is no need to update
+the tag table after each edit, or even every day.
+
+@node Select Tag Table, Find Tag, Create Tag Table, Tags
+@subsection Selecting a Tag Table
+
+@vindex tags-file-name
+@findex visit-tags-table
+ Emacs has at any time one @dfn{selected} tag table, and all the commands
+for working with tag tables use the selected one. To select a tag table,
+type @w{@kbd{M-x visit-tags-table}}, which reads the tag table file name as an
+argument. The name @file{TAGS} in the default directory is used as the
+default file name.
+
+ All this command does is store the file name in the variable
+@code{tags-file-name}. Emacs does not actually read in the tag table
+contents until you try to use them. Setting this variable yourself is just
+as good as using @code{visit-tags-table}. The variable's initial value is
+@code{nil}; this value tells all the commands for working with tag tables
+that they must ask for a tag table file name to use.
+
+@node Find Tag, Tags Search, Select Tag Table, Tags
+@subsection Finding a Tag
+
+ The most important thing that a tag table enables you to do is to find
+the definition of a specific tag.
+
+@table @kbd
+@item M-.@: @var{tag}
+Find first definition of @var{tag} (@code{find-tag}).
+@item C-u M-.
+Find next alternate definition of last tag specified.
+@item C-x 4 .@: @var{tag}
+Find first definition of @var{tag}, but display it in another window
+(@code{find-tag-other-window}).
+@end table
+
+@kindex M-.
+@findex find-tag
+ @kbd{M-.}@: (@code{find-tag}) is the command to find the definition of a
+specified tag. It searches through the tag table for that tag, as a
+string, and then uses the tag table info to determine the file that the
+definition is in and the approximate character position in the file of the
+definition. Then @code{find-tag} visits that file, moves point to the
+approximate character position, and starts searching ever-increasing
+distances away for the the text that should appear at the beginning of the
+definition.
+
+ If an empty argument is given (just type @key{RET}), the sexp in the
+buffer before or around point is used as the name of the tag to find.
+@xref{Lists}, for info on sexps.
+
+ The argument to @code{find-tag} need not be the whole tag name; it can be
+a substring of a tag name. However, there can be many tag names containing
+the substring you specify. Since @code{find-tag} works by searching the
+text of the tag table, it finds the first tag in the table that the
+specified substring appears in.
+
+ The way to find other tags that match the substring is to give
+@code{find-tag} a numeric argument, as in @kbd{C-u M-.}; this does not
+read a tag name, but continues searching the tag table's text for
+another tag containing the same substring last used. If you have a real
+@key{META} key, @kbd{M-0 M-.}@: is an easier alternative to @kbd{C-u
+M-.}. (That is a zero in @kbd{M-0}.)
+
+@kindex C-x 4 .
+@findex find-tag-other-window
+ Like most commands that can switch buffers, @code{find-tag} has another
+similar command that displays the new buffer in another window. @kbd{C-x 4
+.}@: invokes the function @code{find-tag-other-window}. (This key sequence
+ends with a period.)
+
+ Emacs comes with a tag table file @file{TAGS}, in the @file{src}
+subdirectory, which includes all the Lisp libraries and all the C
+sources of Emacs. By specifying this file with @code{visit-tags-table}
+and then using @kbd{M-.}@: you can quickly look at the source of any
+Emacs function.
+
+@node Tags Search, Tags Stepping, Find Tag, Tags
+@subsection Searching and Replacing with Tag Tables
+
+ The commands in this section visit and search all the files listed in the
+selected tag table, one by one. For these commands, the tag table serves
+only to specify a sequence of files to search. A related command is
+@kbd{M-x grep} (@pxref{Compilation}).
+
+@table @kbd
+@item M-x tags-search
+Search for the specified regexp through the files in the selected tag
+table.
+@item M-x tags-query-replace
+Perform a @code{query-replace} on each file in the selected tag table.
+@item M-,
+Restart one of the commands above, from the current location of point
+(@code{tags-loop-continue}).
+@end table
+
+@findex tags-search
+ @kbd{M-x tags-search} reads a regexp using the minibuffer, then visits
+the files of the selected tag table one by one, and searches through each
+one for that regexp. It displays the name of the file being searched so
+you can follow its progress. As soon as an occurrence is found,
+@code{tags-search} returns.
+
+@kindex M-,
+@findex tags-loop-continue
+ Having found one match, you probably want to find all the rest. To find
+one more match, type @kbd{M-,} (@code{tags-loop-continue}) to resume the
+@code{tags-search}. This searches the rest of the current buffer, followed
+by the remaining files of the tag table.
+
+@findex tags-query-replace
+ @kbd{M-x tags-query-replace} performs a single @code{query-replace}
+through all the files in the tag table. It reads a string to search for
+and a string to replace with, just like ordinary @w{@kbd{M-x query-replace}}.
+It searches much like @kbd{M-x tags-search} but repeatedly, processing
+matches according to your input. @xref{Replace}, for more information on
+@code{query-replace}.@refill
+
+ It is possible to get through all the files in the tag table with a
+single invocation of @kbd{M-x tags-query-replace}. But since any
+unrecognized character causes the command to exit, you may need to continue
+where you left off. @kbd{M-,} can be used for this. It resumes the last
+tags search or replace command that you did.
+
+ It may have struck you that @code{tags-search} is a lot like @code{grep}.
+You can also run @code{grep} itself as an inferior of Emacs and have Emacs
+show you the matching lines one by one. This works mostly the same as
+running a compilation and having Emacs show you where the errors were.
+@xref{Compilation}.
+
+@node Tags Stepping, List Tags, Tags Search, Tags
+@subsection Stepping Through a Tag Table
+@findex next-file
+
+ If you wish to process all the files in the selected tag table, but
+@kbd{M-x tags-search} and @kbd{M-x tags-query-replace} in particular are not what
+you want, you can use @kbd{M-x next-file}.
+
+@table @kbd
+@item C-u M-x next-file
+With a numeric argument, regardless of its value, visit the first
+file in the tag table, and prepare to advance sequentially by files.
+@item M-x next-file
+Visit the next file in the selected tag table.
+@end table
+
+@node List Tags,, Tags Stepping, Tags
+@subsection Tag Table Inquiries
+
+@table @kbd
+@item M-x list-tags
+Display a list of the tags defined in a specific program file.
+@item M-x tags-apropos
+Display a list of all tags matching a specified regexp.
+@end table
+
+@findex list-tags
+ @kbd{M-x list-tags} reads the name of one of the files described by the
+selected tag table, and displays a list of all the tags defined in that
+file. The ``file name'' argument is really just a string to compare
+against the names recorded in the tag table; it is read as a string rather
+than as a file name. Therefore, completion and defaulting are not
+available, and you must enter the string the same way it appears in the tag
+table. Do not include a directory as part of the file name unless the file
+name recorded in the tag table includes a directory.
+
+@findex tags-apropos
+ @kbd{M-x tags-apropos} is like @code{apropos} for tags. It reads a regexp,
+then finds all the tags in the selected tag table whose entries match that
+regexp, and displays the tag names found.
+
+@node Fortran,, Tags, Programs
+@section Fortran Mode
+@cindex Fortran mode
+
+ Fortran mode provides special motion commands for Fortran statements and
+subprograms, and indentation commands that understand Fortran conventions
+of nesting, line numbers and continuation statements.
+
+ Special commands for comments are provided because Fortran comments are
+unlike those of other languages.
+
+ Built-in abbrevs optionally save typing when you insert Fortran keywords.
+
+@findex fortran-mode
+ Use @kbd{M-x fortran-mode} to switch to this major mode. Doing so calls
+the value of @code{fortran-mode-hook} as a function of no arguments if
+that variable has a value that is not @code{nil}.
+
+@menu
+* Motion: Fortran Motion. Moving point by statements or subprograms.
+* Indent: Fortran Indent. Indentation commands for Fortran.
+* Comments: Fortran Comments. Inserting and aligning comments.
+* Columns: Fortran Columns. Measuring columns for valid Fortran.
+* Abbrev: Fortran Abbrev. Built-in abbrevs for Fortran keywords.
+@end menu
+
+ Fortran mode was contributed by Michael Prange.
+
+@node Fortran Motion, Fortran Indent, Fortran, Fortran
+@subsection Motion Commands
+
+ Fortran mode provides special commands to move by subprograms (functions
+and subroutines) and by statements. There is also a command to put the
+region around one subprogram, convenient for killing it or moving it.
+
+@kindex C-M-a (Fortran mode)
+@kindex C-M-e (Fortran mode)
+@kindex C-M-h (Fortran mode)
+@kindex C-c C-p (Fortran mode)
+@kindex C-c C-n (Fortran mode)
+@findex beginning-of-fortran-subprogram
+@findex end-of-fortran-subprogram
+@findex mark-fortran-subprogram
+@findex fortran-previous-statement
+@findex fortran-next-statement
+
+@table @kbd
+@c !!! following generates acceptable underfull hbox
+@item C-M-a
+Move to beginning of subprogram
+(@code{beginning-of-fortran-subprogram}).
+@item C-M-e
+Move to end of subprogram (@code{end-of-fortran-subprogram}).
+@item C-M-h
+Put point at beginning of subprogram and mark at end
+(@code{mark-fortran-subprogram}).
+@item C-c C-n
+Move to beginning of current or next statement
+(@code{fortran-next-statement}).
+@item C-c C-p
+Move to beginning of current or previous statement
+(@code{fortran-previous-statement}).
+@end table
+
+@node Fortran Indent, Fortran Comments, Fortran Motion, Fortran
+@subsection Fortran Indentation
+
+ Special commands and features are needed for indenting Fortran code in
+order to make sure various syntactic entities (line numbers, comment line
+indicators and continuation line flags) appear in the columns that are
+required for standard Fortran.
+
+@menu
+* Commands: ForIndent Commands. Commands for indenting Fortran.
+* Numbers: ForIndent Num. How line numbers auto-indent.
+* Conv: ForIndent Conv. Conventions you must obey to avoid trouble.
+* Vars: ForIndent Vars. Variables controlling Fortran indent style.
+@end menu
+
+@node ForIndent Commands, ForIndent Num, Fortran Indent, Fortran Indent
+@subsubsection Fortran Indentation Commands
+
+@table @kbd
+@item @key{TAB}
+Indent the current line (@code{fortran-indent-line}).
+@item M-@key{LFD}
+Break the current line and set up a continuation line.
+@item C-M-q
+Indent all the lines of the subprogram point is in
+(@code{fortran-indent-subprogram}).
+@end table
+
+@findex fortran-indent-line
+ @key{TAB} is redefined by Fortran mode to reindent the current line for
+Fortran (@code{fortran-indent-line}). Line numbers and continuation
+markers are indented to their required columns, and the body of the
+statement is independently indented based on its nesting in the program.
+
+@kindex C-M-q (Fortran mode)
+@findex fortran-indent-subprogram
+ The key @kbd{C-M-q} is redefined as @code{fortran-indent-subprogram}, a
+command to reindent all the lines of the Fortran subprogram (function or
+subroutine) containing point.
+
+@kindex M-LFD (Fortran mode)
+@findex fortran-split-line
+ The key @kbd{M-@key{LFD}} is redefined as @code{fortran-split-line}, a
+command to split a line in the appropriate fashion for Fortran. In a
+non-comment line, the second half becomes a continuation line and is
+indented accordingly. In a comment line, both halves become separate
+comment lines.
+
+@node ForIndent Num, ForIndent Conv, ForIndent Commands, Fortran Indent
+@subsubsection Line Numbers and Continuation
+
+ If a number is the first non-whitespace in the line, it is assumed to be
+a line number and is moved to columns 0 through 4. (Columns are always
+counted from 0 in GNU Emacs.) If the text on the line starts with the
+conventional Fortran continuation marker @samp{$}, it is moved to column 5.
+If the text begins with any non whitespace character in column 5, it is
+assumed to be an unconventional continuation marker and remains in column
+5.
+
+@vindex fortran-line-number-indent
+ Line numbers of four digits or less are normally indented one space.
+This amount is controlled by the variable @code{fortran-line-number-indent}
+which is the maximum indentation a line number can have. Line numbers
+are indented to right-justify them to end in column 4 unless that would
+require more than this maximum indentation. The default value of the
+variable is 1.
+
+@vindex fortran-electric-line-number
+ Simply inserting a line number is enough to indent it according to these
+rules. As each digit is inserted, the indentation is recomputed. To turn
+off this feature, set the variable @code{fortran-electric-line-number} to
+@code{nil}. Then inserting line numbers is like inserting anything else.
+
+@node ForIndent Conv, ForIndent Vars, ForIndent Num, Fortran Indent
+@subsubsection Syntactic Conventions
+
+ Fortran mode assumes that you follow certain conventions that simplify
+the task of understanding a Fortran program well enough to indent it
+properly:
+
+@vindex fortran-continuation-char
+@itemize @bullet
+@item
+Two nested @samp{do} loops never share a @samp{continue} statement.
+
+@item
+The same character appears in column 5 of all continuation lines, and
+this character is the value of the variable @code{fortran-continuation-char}.
+By default, this character is @samp{$}.
+@end itemize
+
+@noindent
+If you fail to follow these conventions, the indentation commands may
+indent some lines unaesthetically. However, a correct Fortran program will
+retain its meaning when reindented even if the conventions are not
+followed.
+
+@node ForIndent Vars,, ForIndent Conv, Fortran Indent
+@subsubsection Variables for Fortran Indentation
+
+@vindex fortran-do-indent
+@vindex fortran-if-indent
+@vindex fortran-continuation-indent
+@vindex fortran-check-all-num-for-matching-do
+@vindex fortran-minimum-statement-indent
+ Several additional variables control how Fortran indentation works.
+
+@table @code
+@item fortran-do-indent
+Extra indentation within each level of @samp{do} statement @*(default 3).
+
+@item fortran-if-indent
+Extra indentation within each level of @samp{if} statement @*(default 3).
+
+@item fortran-continuation-indent
+Extra indentation for bodies of continuation lines (default 5).
+
+@item fortran-check-all-num-for-matching-do
+If this is @code{nil}, indentation assumes that each @samp{do}
+statement ends on a @samp{continue} statement. Therefore, when
+computing indentation for a statement other than @samp{continue}, it
+can save time by not checking for a @samp{do} statement ending there.
+If this is non-@code{nil}, indenting any numbered statement must check
+for a @samp{do} that ends there. The default is @code{nil}.
+
+@item fortran-minimum-statement-indent
+Minimum indentation for fortran statements. For standard Fortran,
+this is 6. Statement bodies will never be indented less than this
+much.
+@end table
+
+@node Fortran Comments, Fortran Columns, Fortran Indent, Fortran
+@subsection Comments
+
+ The usual Emacs comment commands assume that a comment can follow a line
+of code. In Fortran, the standard comment syntax requires an entire line
+to be just a comment. Therefore, Fortran mode replaces the standard Emacs
+comment commands and defines some new variables.
+
+ Fortran mode can also handle a nonstandard comment syntax where comments
+start with @samp{!} and can follow other text. Because only some Fortran
+compilers accept this syntax, Fortran mode will not insert such comments
+unless you have said in advance to do so. To do this, set the variable
+@code{comment-start} to @samp{"!"} (@pxref{Variables}).
+
+@table @kbd
+@item M-;
+Align comment or insert new comment (@code{fortran-comment-indent}).
+
+@item C-x ;
+Applies to nonstandard @samp{!} comments only.
+
+@item C-c ;
+Turn all lines of the region into comments, or (with arg)
+turn them back into real code (@code{fortran-comment-region}).
+@end table
+
+ @kbd{M-;} in Fortran mode is redefined as the command
+@code{fortran-comment-indent}. Like the usual @kbd{M-;} command, this
+recognizes any kind of existing comment and aligns its text appropriately;
+if there is no existing comment, a comment is inserted and aligned. But
+inserting and aligning comments are not the same in Fortran mode as in
+other modes.
+
+ When a new comment must be inserted, if the current line is blank, a
+full-line comment is inserted. On a non-blank line, a nonstandard @samp{!}
+comment is inserted if you have said you want to use them. Otherwise a
+full-line comment is inserted on a new line before the current line.
+
+ Nonstandard @samp{!} comments are aligned like comments in other
+languages, but full-line comments are different. In a standard full-line
+comment, the comment delimiter itself must always appear in column zero.
+What can be aligned is the text within the comment. You can choose from
+three styles of alignment by setting the variable
+@code{fortran-comment-indent-style} to one of these values:
+
+@vindex fortran-comment-indent-style
+@vindex fortran-comment-line-column
+@table @code
+@item fixed
+The text is aligned at a fixed column, which is the value of
+@code{fortran-comment-line-column}. This is the default.
+@item relative
+The text is aligned as if it were a line of code, but with an
+additional @code{fortran-comment-line-column} columns of indentation.
+@item nil
+Text in full-line columns is not moved automatically.
+@end table
+
+@vindex fortran-comment-indent-char
+ In addition, you can specify the character to be used to indent within
+full-line comments by setting the variable @code{fortran-comment-indent-char}
+to the character you want to use.
+
+@vindex comment-line-start
+@vindex comment-line-start-skip
+ Fortran mode introduces the two variables, @code{comment-line-start} and
+@code{comment-line-start-skip}, which play for full-line comments the same
+roles played by @code{comment-start} and @code{comment-start-skip} for
+ordinary text-following comments. Normally these are set properly by
+Fortran mode so you do not need to change them.
+
+ The normal Emacs comment command @kbd{C-x ;} has not been redefined.
+If you use @samp{!} comments, this command can be used with them. Otherwise
+it is useless in Fortran mode.
+
+@kindex C-c ; (Fortran mode)
+@findex fortran-comment-region
+@vindex fortran-comment-region
+ The command @kbd{C-c ;} (@code{fortran-comment-region}) turns all the
+lines of the region into comments by inserting the string @samp{C$$$} at
+the front of each one. With a numeric arg, the region is turned back into
+live code by deleting @samp{C$$$} from the front of each line in it. The
+string used for these comments can be controlled by setting the variable
+@code{fortran-comment-region}. Note that here we have an example of a
+command and a variable with the same name; these two uses of the name never
+conflict because in Lisp and in Emacs it is always clear from the context
+which one is meant.
+
+@node Fortran Columns, Fortran Abbrev, Fortran Comments, Fortran
+@subsection Columns
+
+@table @kbd
+@item C-c C-r
+Displays a ``column ruler'' momentarily above the current line
+(@code{fortran-column-ruler}).
+@item C-c C-w
+Splits the current window horizontally so that it is 72 columns wide.
+This may help you avoid going over that limit (@code{fortran-window-create}).
+@end table
+
+@kindex C-c C-r (Fortran mode)
+@findex fortran-column-ruler
+@vindex fortran-column-ruler
+ The command @kbd{C-c C-r} (@code{fortran-column-ruler}) shows a column
+ruler momentarily above the current line. The comment ruler is two lines
+of text that show you the locations of columns with special significance
+in Fortran programs. Square brackets show the limits of the columns for
+line numbers, and curly brackets show the limits of the columns for the
+statement body. Column numbers appear above them.
+
+ Note that the column numbers count from zero, as always in GNU Emacs. As
+a result, the numbers may not be those you are familiar with; but the
+actual positions in the line are standard Fortran.
+
+ The text used to display the column ruler is the value of the variable
+@code{fortran-comment-ruler}. By changing this variable, you can change
+the display.
+
+@kindex C-c C-w (Fortran mode)
+@findex fortran-window-create
+ For even more help, use @kbd{C-c C-w} (@code{fortran-window-create}), a
+command which splits the current window horizontally, making a window 72
+columns wide. By editing in this window you can immediately see when you
+make a line too wide to be correct Fortran.
+
+@node Fortran Abbrev,, Fortran Columns, Fortran
+@subsection Fortran Keyword Abbrevs
+
+ Fortran mode provides many built-in abbrevs for common keywords and
+declarations. These are the same sort of abbrev that you can define
+yourself. To use them, you must turn on Abbrev mode (@pxref{Abbrevs}).
+
+ The built-in abbrevs are unusual in one way: they all start with a
+semicolon. You cannot normally use semicolons in an abbrev, but Fortran
+mode makes this possible by changing the syntax of semicolon to ``word
+constituent''.
+
+ For example, one built-in Fortran abbrev is @samp{;c} for
+@samp{continue}. If you insert @samp{;c} and then insert a punctuation
+character such as a space or a newline, the @samp{;c} will change
+automatically to @samp{continue}, provided Abbrev mode is enabled.@refill
+
+ Type @samp{;?} or @samp{;C-h} to display a list of all the built-in
+Fortran abbrevs and what they stand for.
+
+@node Compiling/Testing, Abbrevs, Programs, Top
+@chapter Compiling and Testing Programs
+
+ The previous chapter discusses the Emacs commands that are useful for
+making changes in programs. This chapter deals with commands that assist
+in the larger process of developing and maintaining programs.
+
+@menu
+* Compilation:: Compiling programs in languages other than Lisp
+ (C, Pascal, etc.)
+* Modes: Lisp Modes. Various modes for editing Lisp programs, with
+ different facilities for running the Lisp programs.
+* Libraries: Lisp Libraries. Creating Lisp programs to run in Emacs.
+* Interaction: Lisp Interaction. Executing Lisp in an Emacs buffer.
+* Eval: Lisp Eval. Executing a single Lisp expression in Emacs.
+* Debug: Lisp Debug. Debugging Lisp programs running in Emacs.
+* External Lisp:: Communicating through Emacs with a separate Lisp.
+@end menu
+
+@node Compilation, Lisp Modes, Compiling/Testing, Compiling/Testing
+@section Running `make', or Compilers Generally
+@cindex inferior process
+@cindex make
+@cindex compilation errors
+@cindex error log
+
+ Emacs can run compilers for noninteractive languages such as C and
+Fortran as inferior processes, feeding the error log into an Emacs buffer.
+It can also parse the error messages and visit the files in which errors
+are found, moving point right to the line where the error occurred.
+
+@table @kbd
+@item M-x compile
+Run a compiler asynchronously under Emacs, with error messages to
+@samp{*compilation*} buffer.
+@item M-x grep
+Run @code{grep} asynchronously under Emacs, with matching lines
+listed in the buffer named @samp{*compilation*}.
+@item M-x kill-compilation
+@itemx M-x kill-grep
+Kill the running compilation or @code{grep} subprocess.
+@item C-x `
+Visit the locus of the next compiler error message or @code{grep} match.
+@end table
+
+@findex compile
+ To run @code{make} or another compiler, do @kbd{M-x compile}. This command
+reads a shell command line using the minibuffer, and then executes the
+specified command line in an inferior shell with output going to the buffer
+named @samp{*compilation*}. The current buffer's default directory is used
+as the working directory for the execution of the command; normally,
+therefore, the makefile comes from this directory.
+
+@vindex compile-command
+ When the shell command line is read, the minibuffer appears containing a
+default command line, which is the command you used the last time you did
+@kbd{M-x compile}. If you type just @key{RET}, the same command line is used
+again. The first @kbd{M-x compile} provides @code{make -k} as the default.
+The default is taken from the variable @code{compile-command}; if the
+appropriate compilation command for a file is something other than
+@code{make -k}, it can be useful to have the file specify a local value for
+@code{compile-command} (@pxref{File Variables}).
+
+ Starting a compilation causes the buffer @samp{*compilation*} to be
+displayed in another window but not selected. Its mode line tells you
+whether compilation is finished, with the word @samp{run} or @samp{exit} inside
+the parentheses. You do not have to keep this buffer visible; compilation
+continues in any case.
+
+@findex kill-compilation
+ To kill the compilation process, do @kbd{M-x kill-compilation}. You will
+see that the mode line of the @samp{*compilation*} buffer changes to say
+@samp{signal} instead of @samp{run}. Starting a new compilation also kills
+any running compilation, as only one can exist at any time. However, this
+requires confirmation before actually killing a compilation that is
+running.@refill
+
+@kindex C-x `
+@findex next-error
+ To parse the compiler error messages, type @kbd{C-x `} (@code{next-error}). The
+character following the @kbd{C-x} is the grave accent, not the single
+quote. This command displays the buffer @samp{*compilation*} in one window
+and the buffer in which the next error occurred in another window. Point
+in that buffer is moved to the line where the error was found. The
+corresponding error message is scrolled to the top of the window in which
+@samp{*compilation*} is displayed.
+
+ The first time @kbd{C-x `} is used after the start of a compilation, it
+parses all the error messages, visits all the files that have error
+messages, and makes markers pointing at the lines that the error messages
+refer to. Then it moves to the first error message location. Subsequent
+uses of @kbd{C-x `} advance down the data set up by the first use. When
+the preparsed error messages are exhausted, the next @kbd{C-x `} checks for
+any more error messages that have come in; this is useful if you start
+editing the compiler errors while the compilation is still going on. If no
+more error messages have come in, @kbd{C-x `} reports an error.
+
+ @kbd{C-u C-x `} discards the preparsed error message data and parses the
+@samp{*compilation*} buffer over again, then displaying the first error.
+This way, you can process the same set of errors again.
+
+@findex grep
+ Instead of running a compiler, you can run @code{grep} and see the lines
+on which matches were found. To do this, type @kbd{M-x grep} with an argument
+line that contains the same arguments you would give @code{grep} when running
+it normally: a @code{grep}-style regexp (usually in singlequotes to quote
+the shell's special characters) followed by filenames which may use wildcards.
+The output from @code{grep} goes in the @samp{*compilation*} buffer and the
+lines that matched can be found with @kbd{C-x `} as if they were compilation
+errors.
+
+ Note: a shell is used to run the compile command, but the shell is told
+that it should be noninteractive. This means in particular that the shell
+starts up with no prompt. If you find your usual shell prompt making an
+unsightly appearance in the @samp{*compilation*} buffer, it means you have
+made a mistake in your shell's init file (@file{.cshrc} or @file{.shrc} or
+@dots{}) by setting the prompt unconditionally. The shell init file should
+set the prompt only if there already is a prompt.
+
+Here is how to do it in @code{csh}:
+
+@example
+if ($?prompt) set prompt = ...
+@end example
+
+Here is how to do it in the Bourne-Again shell:
+
+@example
+@group
+if [ ! "$PS1" ]; then
+ PS1=@dots{}
+fi
+@end group
+@end example
+
+@node Lisp Modes, Lisp Libraries, Compilation, Compiling/Testing
+@section Major Modes for Lisp
+
+@cindex Lisp mode
+@cindex Scheme mode
+@cindex Inferior Scheme mode
+ Emacs has four different major modes for Lisp. They are the same in
+terms of editing commands, but differ in the commands for executing Lisp
+expressions.
+
+@table @asis
+@item Emacs-Lisp mode
+The mode for editing source files of programs to run in Emacs Lisp.
+This mode defines @kbd{C-M-x} to evaluate the current defun.
+@xref{Lisp Libraries}.
+@item Lisp Interaction mode
+The mode for an interactive session with Emacs Lisp. It defines
+@key{LFD} to evaluate the sexp before point and insert its value in the
+buffer. @xref{Lisp Interaction}.
+@item Lisp mode
+The mode for editing source files of programs that run in Lisps other
+than Emacs Lisp. This mode defines @kbd{C-M-x} to send the current defun
+to an inferior Lisp process. @xref{External Lisp}.
+@item Inferior Lisp mode
+The mode for an interactive session with an inferior Lisp process.
+This mode combines the special features of Lisp mode and Shell mode
+(@pxref{Shell Mode}).
+@item Scheme mode
+Like Lisp mode but for Scheme programs.
+@item Inferior Scheme mode
+The mode for an interactive session with an inferior Scheme process.
+@end table
+
+@node Lisp Libraries, Lisp Eval, Lisp Modes, Compiling/Testing
+@section Libraries of Lisp Code for Emacs
+@cindex libraries
+@cindex loading Lisp code
+
+ Lisp code for Emacs editing commands is stored in files whose names
+conventionally end in @file{.el}. This ending tells Emacs to edit them in
+Emacs-Lisp mode (@pxref{Lisp Modes}).
+
+@menu
+* Loading:: Loading libraries of Lisp code into Emacs for use.
+* Compiling Libraries:: Compiling a library makes it load and run faster.
+* Mocklisp:: Converting Mocklisp to Lisp so GNU Emacs can run it.
+@end menu
+
+@node Loading, Compiling Libraries, Lisp Libraries, Lisp Libraries
+@subsection Loading Libraries
+
+@findex load-file
+ To execute a file of Emacs Lisp, use @kbd{M-x load-file}. This command
+reads a file name using the minibuffer and then executes the contents of
+that file as Lisp code. It is not necessary to visit the file first;
+in any case, this command reads the file as found on disk, not text in
+an Emacs buffer.
+
+@findex load
+@findex load-library
+ Once a file of Lisp code is installed in the Emacs Lisp library
+directories, users can load it using @kbd{M-x load-library}. Programs can
+load it by calling @code{load-library}, or with @code{load}, a more primitive
+function that is similar but accepts some additional arguments.
+
+ @kbd{M-x load-library} differs from @kbd{M-x load-file} in that it
+searches a sequence of directories and tries three file names in each
+directory. The three names are, first, the specified name with @file{.elc}
+appended; second, with @file{.el} appended; third, the specified
+name alone. A @file{.elc} file would be the result of compiling the Lisp
+file into byte code; it is loaded if possible in preference to the Lisp
+file itself because the compiled file will load and run faster.
+
+ Because the argument to @code{load-library} is usually not in itself
+a valid file name, file name completion is not available. Indeed, when
+using this command, you usually do not know exactly what file name
+will be used.
+
+@vindex load-path
+ The sequence of directories searched by @kbd{M-x load-library} is
+specified by the variable @code{load-path}, a list of strings that are
+directory names. The default value of the list contains the directory where
+the Lisp code for Emacs itself is stored. If you have libraries of
+your own, put them in a single directory and add that directory
+to @code{load-path}. @code{nil} in this list stands for the current default
+directory, but it is probably not a good idea to put @code{nil} in the
+list. If you find yourself wishing that @code{nil} were in the list,
+most likely what you really want to do is use @kbd{M-x load-file}
+this once.
+
+@cindex autoload
+ Often you do not have to give any command to load a library, because the
+commands defined in the library are set up to @dfn{autoload} that library.
+Running any of those commands causes @code{load} to be called to load the
+library; this replaces the autoload definitions with the real ones from the
+library.
+
+ If autoloading a file does not finish, either because of an error or
+because of a @kbd{C-g} quit, all function definitions made by the file are
+undone automatically. So are any calls to @code{provide}. As a consequence,
+if you use one of the autoloadable commands again, the entire file will be
+loaded a second time. This prevents problems where the command is no
+longer autoloading but it works wrong because not all the file was loaded.
+Function definitions are undone only for autoloading; explicit calls to
+@code{load} do not undo anything if loading is not completed.
+
+@node Compiling Libraries, Mocklisp, Loading, Lisp Libraries
+@subsection Compiling Libraries
+
+@cindex byte code
+ Emacs Lisp code can be compiled into byte-code which loads faster,
+takes up less space when loaded, and executes faster.
+
+@findex byte-compile-file
+ The way to make a byte-code compiled file from an Emacs-Lisp source file
+is with @kbd{M-x byte-compile-file}. The default argument for this
+function is the file visited in the current buffer. It reads the specified
+file, compiles it into byte code, and writes an output file whose name is
+made by appending @file{c} to the input file name. Thus, the file
+@file{rmail.el} would be compiled into @file{rmail.elc}.
+
+@findex byte-recompile-directory
+ To recompile the changed Lisp files in a directory, use @kbd{M-x
+byte-recompile-directory}. Specify just the directory name as an argument.
+Each @file{.el} file that has been byte-compiled before is byte-compiled
+again if it has changed since the previous compilation. A numeric argument
+to this command tells it to offer to compile each @file{.el} file that has
+not already been compiled. You must answer @kbd{y} or @kbd{n} to each
+offer.
+
+@findex batch-byte-compile
+ Emacs can be invoked noninteractively from the shell to do byte compilation
+with the aid of the function @code{batch-byte-compile}. In this case,
+the files to be compiled are specified with command-line arguments.
+Use a shell command of the form
+
+@example
+emacs -batch -f batch-byte-compile @var{files}...
+@end example
+
+ Directory names may also be given as arguments;
+@code{byte-recompile-directory} is invoked (in effect) on each such directory.
+@code{batch-byte-compile} uses all the remaining command-line arguments as
+file or directory names, then kills the Emacs process.
+
+@cindex disassemble
+@findex disassemble
+ @kbd{M-x disassemble} explains the result of byte compilation. Its
+argument is a function name. It displays the byte-compiled code in a help
+window in symbolic form, one instruction per line. If the instruction
+refers to a variable or constant, that is shown too.
+
+@node Mocklisp,,Compiling Libraries,Lisp Libraries
+@subsection Converting Mocklisp to Lisp
+
+@cindex mocklisp
+@findex convert-mocklisp-buffer
+ GNU Emacs can run Mocklisp files by converting them to Emacs Lisp first.
+To convert a Mocklisp file, visit it and then type @kbd{M-x
+convert-mocklisp-buffer}. Then save the resulting buffer of Lisp file in a
+file whose name ends in @file{.el} and use the new file as a Lisp library.
+
+ It does not currently work to byte-compile converted Mocklisp code.
+This is because converted Mocklisp code uses some special Lisp features
+to deal with Mocklisp's incompatible ideas of how arguments are evaluated
+and which values signify ``true'' or ``false''.
+
+@node Lisp Eval, Lisp Debug, Lisp Libraries, Compiling/Testing
+@section Evaluating Emacs-Lisp Expressions
+@cindex Emacs-Lisp mode
+
+@findex emacs-lisp-mode
+ Lisp programs intended to be run in Emacs should be edited in Emacs-Lisp
+mode; this will happen automatically for file names ending in @file{.el}.
+By contrast, Lisp mode itself is used for editing Lisp programs intended
+for other Lisp systems. Emacs-Lisp mode can be selected with the command
+@kbd{M-x emacs-lisp-mode}.
+
+ For testing of Lisp programs to run in Emacs, it is useful to be able to
+evaluate part of the program as it is found in the Emacs buffer. For
+example, after changing the text of a Lisp function definition, evaluating
+the definition installs the change for future calls to the function.
+Evaluation of Lisp expressions is also useful in any kind of editing task
+for invoking noninteractive functions (functions that are not commands).
+
+@table @kbd
+@item M-@key{ESC}
+Read a Lisp expression in the minibuffer, evaluate it, and print the
+value in the minibuffer (@code{eval-expression}).
+@item C-x C-e
+Evaluate the Lisp expression before point, and print the value in the
+minibuffer (@code{eval-last-sexp}).
+@item C-M-x
+Evaluate the defun containing or after point, and print the value in
+the minibuffer (@code{eval-defun}).
+@item M-x eval-region
+Evaluate all the Lisp expressions in the region.
+@item M-x eval-current-buffer
+Evaluate all the Lisp expressions in the buffer.
+@end table
+
+@kindex M-ESC
+@findex eval-expression
+ @kbd{M-@key{ESC}} (@code{eval-expression}) is the most basic command for evaluating
+a Lisp expression interactively. It reads the expression using the
+minibuffer, so you can execute any expression on a buffer regardless of
+what the buffer contains. When the expression is evaluated, the current
+buffer is once again the buffer that was current when @kbd{M-@key{ESC}} was
+typed.
+
+ @kbd{M-@key{ESC}} can easily confuse users who do not understand it,
+especially on keyboards with autorepeat where it can result from holding
+down the @key{ESC} key for too long. Therefore, @code{eval-expression} is
+normally a disabled command. Attempting to use this command asks for
+confirmation and gives you the option of enabling it; once you enable the
+command, confirmation will no longer be required for it.
+@xref{Disabling}.@refill
+
+@kindex C-M-x
+@findex eval-defun
+ In Emacs-Lisp mode, the key @kbd{C-M-x} is bound to the function @code{eval-defun},
+which parses the defun containing or following point as a Lisp expression
+and evaluates it. The value is printed in the echo area. This command is
+convenient for installing in the Lisp environment changes that you have
+just made in the text of a function definition.
+
+@kindex C-x C-e
+@findex eval-last-sexp
+ The command @kbd{C-x C-e} (@code{eval-last-sexp}) performs a similar job
+but is available in all major modes, not just Emacs-Lisp mode. It finds
+the sexp before point, reads it as a Lisp expression, evaluates it, and
+prints the value in the echo area. It is sometimes useful to type in an
+expression and then, with point still after it, type @kbd{C-x C-e}.
+
+ If @kbd{C-M-x} or @kbd{C-x C-e} is given a numeric argument, it prints the value
+by insertion into the current buffer at point, rather than in the echo
+area. The argument value does not matter.
+
+@findex eval-region
+@findex eval-current-buffer
+ The most general command for evaluating Lisp expressions from a buffer is
+@code{eval-region}. @kbd{M-x eval-region} parses the text of the region as one or
+more Lisp expressions, evaluating them one by one. @kbd{M-x eval-current-buffer}
+is similar but evaluates the entire buffer. This is a reasonable way to
+install the contents of a file of Lisp code that you are just ready to
+test. After finding and fixing a bug, use @kbd{C-M-x} on each function
+that you change, to keep the Lisp world in step with the source file.
+
+@node Lisp Debug, Lisp Interaction, Lisp Eval, Compiling/Testing
+@section The Emacs-Lisp Debugger
+@cindex debugger
+
+@vindex debug-on-error
+@vindex debug-on-quit
+ GNU Emacs contains a debugger for Lisp programs executing inside it.
+This debugger is normally not used; many commands frequently get Lisp
+errors when invoked in inappropriate contexts (such as @kbd{C-f} at the end
+of the buffer) and it would be very unpleasant for that to enter a special
+debugging mode. When you want to make Lisp errors invoke the debugger, you
+must set the variable @code{debug-on-error} to non-@code{nil}. Quitting
+with @kbd{C-g} is not considered an error, and @code{debug-on-error} has no
+effect on the handling of @kbd{C-g}. However, if you set
+@code{debug-on-quit} non-@code{nil}, @kbd{C-g} will invoke the debugger.
+This can be useful for debugging an infinite loop; type @kbd{C-g} once the
+loop has had time to reach its steady state. @code{debug-on-quit} has no
+effect on errors.@refill
+
+@findex debug-on-entry
+@findex cancel-debug-on-entry
+@findex debug
+ You can also cause the debugger to be entered when a specified function
+is called, or at a particular place in Lisp code. Use @kbd{M-x
+debug-on-entry} with argument @var{fun-name} to cause function
+@var{fun-name} to enter the debugger as soon as it is called. Use
+@kbd{M-x cancel-debug-on-entry} to make the function stop entering the
+debugger when called. (Redefining the function also does this.) To enter
+the debugger from some other place in Lisp code, you must insert the
+expression @code{(debug)} there and install the changed code with
+@kbd{C-M-x}. @xref{Lisp Eval}.@refill
+
+ When the debugger is entered, it displays the previously selected buffer
+in one window and a buffer named @samp{*Backtrace*} in another window. The
+backtrace buffer contains one line for each level of Lisp function
+execution currently going on. At the beginning of this buffer is a message
+describing the reason that the debugger was invoked (such as, what error
+message if it was invoked due to an error).
+
+@cindex Backtrace mode
+ The backtrace buffer is read-only, and is in a special major mode,
+Backtrace mode, in which letters are defined as debugger commands. The
+usual Emacs editing commands are available; you can switch windows to
+examine the buffer that was being edited at the time of the error, and you
+can also switch buffers, visit files, and do any other sort of editing.
+However, the debugger is a recursive editing level (@pxref{Recursive Edit})
+and it is wise to go back to the backtrace buffer and exit the debugger
+officially when you don't want to use it any more. Exiting the debugger
+kills the backtrace buffer.
+
+@cindex current stack frame
+ The contents of the backtrace buffer show you the functions that are
+executing and the arguments that were given to them. It has the additional
+purpose of allowing you to specify a stack frame by moving point to the line
+describing that frame. The frame whose line point is on is considered the
+@dfn{current frame}. Some of the debugger commands operate on the current
+frame. Debugger commands are mainly used for stepping through code an
+expression at a time. Here is a list of them.
+
+@table @kbd
+@item c
+Exit the debugger and continue execution. In most cases, execution of
+the program continues as if the debugger had never been entered (aside
+from the effect of any variables or data structures you may have
+changed while inside the debugger). This includes entry to the
+debugger due to function entry or exit, explicit invocation, quitting
+or certain errors. Most errors cannot be continued; trying to
+continue one of them causes the same error to occur again.
+@item d
+Continue execution, but enter the debugger the next time a Lisp
+function is called. This allows you to step through the
+subexpressions of an expression, seeing what values the subexpressions
+compute and what else they do.
+
+The stack frame made for the function call which enters the debugger
+in this way will be flagged automatically for the debugger to be called
+when the frame is exited. You can use the @kbd{u} command to cancel
+this flag.
+@item b
+Set up to enter the debugger when the current frame is exited. Frames
+that will invoke the debugger on exit are flagged with stars.
+@item u
+Don't enter the debugger when the current frame is exited. This
+cancels a @kbd{b} command on that frame.
+@item e
+Read a Lisp expression in the minibuffer, evaluate it, and print the
+value in the echo area. This is the same as the command @kbd{M-@key{ESC}},
+except that @kbd{e} is not normally disabled like @kbd{M-@key{ESC}}.
+@item q
+Terminate the program being debugged; return to top-level Emacs
+command execution.
+
+If the debugger was entered due to a @kbd{C-g} but you really want
+to quit, not to debug, use the @kbd{q} command.
+@item r
+Return a value from the debugger. The value is computed by reading an
+expression with the minibuffer and evaluating it.
+
+The value returned by the debugger makes a difference when the debugger
+was invoked due to exit from a Lisp call frame (as requested with @kbd{b});
+then the value specified in the @kbd{r} command is used as the value of
+that frame.
+
+The debugger's return value also matters with many errors. For example,
+@code{wrong-type-argument} errors will use the debugger's return value
+instead of the invalid argument; @code{no-catch} errors will use the
+debugger value as a throw tag instead of the tag that was not found.
+If an error was signaled by calling the Lisp function @code{signal},
+the debugger's return value is returned as the value of @code{signal}.
+@end table
+
+@node Lisp Interaction, External Lisp, Lisp Debug, Compiling/Testing
+@section Lisp Interaction Buffers
+
+@cindex Lisp Interaction mode
+@cindex scratch buffer
+ The buffer @samp{*scratch*} which is selected when Emacs starts up is
+provided for evaluating Lisp expressions interactively inside Emacs. Both
+the expressions you evaluate and their output goes in the buffer.
+
+ The @samp{*scratch*} buffer's major mode is Lisp Interaction mode, which
+is the same as Emacs-Lisp mode except for one command, @key{LFD}. In
+Emacs-Lisp mode, @key{LFD} is an indentation command, as usual. In Lisp
+Interaction mode, @key{LFD} is bound to @code{eval-print-last-sexp}. This
+function reads the Lisp expression before point, evaluates it, and inserts
+the value in printed representation before point.
+
+ Thus, the way to use the @samp{*scratch*} buffer is to insert Lisp expressions
+at the end, ending each one with @key{LFD} so that it will be evaluated.
+The result is a complete typescript of the expressions you have evaluated
+and their values.
+
+@findex lisp-interaction-mode
+ The rationale for this feature is that Emacs must have a buffer when it
+starts up, but that buffer is not useful for editing files since a new
+buffer is made for every file that you visit. The Lisp interpreter
+typescript is the most useful thing I can think of for the initial buffer
+to do. @kbd{M-x lisp-interaction-mode} will put any buffer in Lisp
+Interaction mode.
+
+@node External Lisp,, Lisp Interaction, Compiling/Testing
+@section Running an External Lisp
+
+ Emacs has facilities for running programs in other Lisp systems. You can
+run a Lisp process as an inferior of Emacs, and pass expressions to it to
+be evaluated. You can also pass changed function definitions directly from
+the Emacs buffers in which you edit the Lisp programs to the inferior Lisp
+process.
+
+@findex run-lisp
+@cindex Inferior Lisp mode
+ To run an inferior Lisp process, type @kbd{M-x run-lisp}. This runs the
+program named @code{lisp}, the same program you would run by typing
+@code{lisp} as a shell command, with both input and output going through an
+Emacs buffer named @samp{*lisp*}. That is to say, any ``terminal output''
+from Lisp will go into the buffer, advancing point, and any ``terminal
+input'' for Lisp comes from text in the buffer. To give input to Lisp, go
+to the end of the buffer and type the input, terminated by @key{RET}. The
+@samp{*lisp*} buffer is in Inferior Lisp mode, a mode which has all the
+special characteristics of Lisp mode and Shell mode (@pxref{Shell Mode}).
+
+@findex lisp-mode
+ For the source files of programs to run in external Lisps, use Lisp mode.
+This mode can be selected with @kbd{M-x lisp-mode}, and is used automatically
+for files whose names end in @file{.l} or @file{.lisp}, as most Lisp
+systems usually expect.
+
+@kindex C-M-x
+@findex lisp-send-defun
+ When you edit a function in a Lisp program you are running, the easiest
+way to send the changed definition to the inferior Lisp process is the key
+@kbd{C-M-x}. In Lisp mode, this runs the function @code{lisp-send-defun},
+which finds the defun around or following point and sends it as input to
+the Lisp process. (Emacs can send input to any inferior process regardless
+of what buffer is current.)
+
+ Contrast the meanings of @kbd{C-M-x} in Lisp mode (for editing programs
+to be run in another Lisp system) and Emacs-Lisp mode (for editing Lisp
+programs to be run in Emacs): in both modes it has the effect of installing
+the function definition that point is in, but the way of doing so is
+different according to where the relevant Lisp environment is found.
+@xref{Lisp Modes}.
+
+@node Abbrevs, Picture, Compiling/Testing, Top
+@chapter Abbrevs
+@cindex abbrevs
+@cindex expansion (of abbrevs)
+
+ An @dfn{abbrev} is a word which @dfn{expands}, if you insert it, into some
+different text. Abbrevs are defined by the user to expand in specific
+ways. For example, you might define @samp{foo} as an abbrev expanding to
+@samp{find outer otter}. With this abbrev defined, you would be able to
+get @samp{find outer otter } into the buffer by typing @kbd{f o o @key{SPC}}.
+
+@cindex Abbrev mode
+@findex abbrev-mode
+@vindex abbrev-mode
+ Abbrevs expand only when Abbrev mode (a minor mode) is enabled.
+Disabling Abbrev mode does not cause abbrev definitions to be forgotten,
+but they do not expand until Abbrev mode is enabled again. The command
+@kbd{M-x abbrev-mode} toggles Abbrev mode; with a numeric argument, it
+turns Abbrev mode on if the argument is positive, off otherwise.
+@xref{Minor Modes}. @code{abbrev-mode} is also a variable; Abbrev mode is
+on when the variable is non-@code{nil}. The variable @code{abbrev-mode}
+automatically becomes local to the current buffer when it is set.
+
+ Abbrev definitions can be @dfn{mode-specific}---active only in one major
+mode. Abbrevs can also have @dfn{global} definitions that are active in
+all major modes. The same abbrev can have a global definition and various
+mode-specific definitions for different major modes. A mode specific
+definition for the current major mode overrides a global definition.
+
+ Abbrevs can be defined interactively during the editing session. Lists
+of abbrev definitions can also be saved in files and reloaded in later
+sessions. Some users keep extensive lists of abbrevs that they load in
+every session.
+
+ A second kind of abbreviation facility is called the @dfn{dynamic
+expansion}. Dynamic abbrev expansion happens only when you give an
+explicit command and the result of the expansion depends only on the
+current contents of the buffer. @xref{Dynamic Abbrevs}.
+
+@menu
+* Defining Abbrevs:: Defining an abbrev, so it will expand when typed.
+* Expanding Abbrevs:: Controlling expansion: prefixes, canceling expansion.
+* Editing Abbrevs:: Viewing or editing the entire list of defined abbrevs.
+* Saving Abbrevs:: Saving the entire list of abbrevs for another session.
+* Dynamic Abbrevs:: Abbreviations for words already in the buffer.
+@end menu
+
+@node Defining Abbrevs, Expanding Abbrevs, Abbrevs, Abbrevs
+@section Defining Abbrevs
+
+@table @kbd
+@item C-x +
+Define an abbrev to expand into some text before point
+(@code{add-global-abbrev}).
+@item C-x C-a
+Similar, but define an abbrev available only in the current major mode
+(@code{add-mode-abbrev}).
+@item C-x -
+Define a word in the buffer as an abbrev (@code{inverse-add-global-abbrev}).
+@item C-x C-h
+Define a word in the buffer as a mode-specific abbrev
+(@code{inverse-add-mode-abbrev}).
+@item M-x kill-all-abbrevs
+After this command, there are no abbrev definitions in effect.
+@end table
+
+@kindex C-x +
+@findex add-global-abbrev
+ The usual way to define an abbrev is to enter the text you want the
+abbrev to expand to, position point after it, and type @kbd{C-x +}
+(@code{add-global-abbrev}). This reads the abbrev itself using the
+minibuffer, and then defines it as an abbrev for one or more words before
+point. Use a numeric argument to say how many words before point should be
+taken as the expansion. For example, to define the abbrev @samp{foo} as
+mentioned above, insert the text @samp{find outer otter} and then type
+@kbd{C-u 3 C-x + f o o @key{RET}}.
+
+ An argument of zero to @kbd{C-x +} means to use the contents of the
+region as the expansion of the abbrev being defined.
+
+@kindex C-x C-a
+@findex add-mode-abbrev
+ The command @kbd{C-x C-a} (@code{add-mode-abbrev}) is similar, but
+defines a mode-specific abbrev. Mode specific abbrevs are active only in a
+particular major mode. @kbd{C-x C-a} defines an abbrev for the major mode
+in effect at the time @kbd{C-x C-a} is typed. The arguments work the same
+as for @kbd{C-x +}.
+
+@kindex C-x -
+@findex inverse-add-global-abbrev
+@kindex C-x C-h
+@findex inverse-add-mode-abbrev
+ If the text of the abbrev you want is already in the buffer instead of
+the expansion, use command @kbd{C-x -} (@code{inverse-add-global-abbrev})
+instead of @kbd{C-x +}, or use @kbd{C-x C-h}
+(@code{inverse-add-mode-abbrev}) instead of @kbd{C-x C-a}. These commands
+are called ``inverse'' because they invert the meaning of the argument
+found in the buffer and the argument read using the minibuffer.@refill
+
+ To change the definition of an abbrev, just add the new definition. You
+will be asked to confirm if the abbrev has a prior definition. To remove
+an abbrev definition, give a negative argument to @kbd{C-x +} or @kbd{C-x
+C-a}. You must choose the command to specify whether to kill a global
+definition or a mode-specific definition for the current mode, since those
+two definitions are independent for one abbrev.
+
+@findex kill-all-abbrevs
+ @kbd{M-x kill-all-abbrevs} removes all the abbrev definitions there are.
+
+@node Expanding Abbrevs, Editing Abbrevs, Defining Abbrevs, Abbrevs
+@section Controlling Abbrev Expansion
+
+ An abbrev expands whenever it is present in the buffer just before point
+and a self-inserting punctuation character (@key{SPC}, comma, etc.@:) is
+typed. Most often the way an abbrev is used is to insert the abbrev
+followed by punctuation.
+
+@vindex abbrev-all-caps
+ Abbrev expansion preserves case; thus, @samp{foo} expands into @samp{find
+outer otter}; @samp{Foo} into @samp{Find outer otter}, and @samp{FOO} into
+@samp{FIND OUTER OTTER} or @samp{Find Outer Otter} according to the
+variable @code{abbrev-all-caps} (a non-@code{nil} value chooses the first
+of the two expansions).@refill
+
+ These two commands are used to control abbrev expansion:
+
+@table @kbd
+@item M-'
+Separate a prefix from a following abbrev to be expanded
+(@code{abbrev-prefix-mark}).
+@item C-x '
+@findex expand-abbrev
+Expand the abbrev before point (@code{expand-abbrev}).
+This is effective even when Abbrev mode is not enabled.
+@item M-x unexpand-abbrev
+Undo last abbrev expansion.
+@item M-x expand-region-abbrevs
+Expand some or all abbrevs found in the region.
+@end table
+
+@kindex M-'
+@findex abbrev-prefix-mark
+ You may wish to expand an abbrev with a prefix attached; for example, if
+@samp{cnst} expands into @samp{construction}, you might want to use it to
+enter @samp{reconstruction}. It does not work to type @kbd{recnst},
+because that is not necessarily a defined abbrev. What does work is to use
+the command @kbd{M-'} (@code{abbrev-prefix-mark}) in between the prefix
+@samp{re} and the abbrev @samp{cnst}. First, insert @samp{re}. Then type
+@kbd{M-'}; this inserts a minus sign in the buffer to indicate that it has
+done its work. Then insert the abbrev @samp{cnst}; the buffer now contains
+@samp{re-cnst}. Now insert a punctuation character to expand the abbrev
+@samp{cnst} into @samp{construction}. The minus sign is deleted at this
+point, because @kbd{M-'} left word for this to be done. The resulting text
+is the desired @samp{reconstruction}.@refill
+
+ If you actually want the text of the abbrev in the buffer, rather than
+its expansion, you can accomplish this by inserting the following
+punctuation with @kbd{C-q}. Thus, @kbd{foo C-q -} leaves @samp{foo-} in the
+buffer.
+
+@findex unexpand-abbrev
+ If you expand an abbrev by mistake, you can undo the expansion (replace
+the expansion by the original abbrev text) with @kbd{M-x unexpand-abbrev}.
+@kbd{C-_} (@code{undo}) can also be used to undo the expansion; but first
+it will undo the insertion of the following punctuation character!
+
+@findex expand-region-abbrevs
+ @kbd{M-x expand-region-abbrevs} searches through the region for defined
+abbrevs, and for each one found offers to replace it with its expansion.
+This command is useful if you have typed in text using abbrevs but forgot
+to turn on Abbrev mode first. It may also be useful together with a
+special set of abbrev definitions for making several global replacements at
+once. This command is effective even if Abbrev mode is not enabled.
+
+@node Editing Abbrevs, Saving Abbrevs, Expanding Abbrevs, Abbrevs
+@section Examining and Editing Abbrevs
+
+@table @kbd
+@item M-x list-abbrevs
+Print a list of all abbrev definitions.
+@item M-x edit-abbrevs
+Edit a list of abbrevs; you can add, alter or remove definitions.
+@end table
+
+@findex list-abbrevs
+ The output from @kbd{M-x list-abbrevs} looks like this:
+
+@example
+(lisp-mode-abbrev-table)
+"dk" 0 "define-key"
+(global-abbrev-table)
+"dfn" 0 "definition"
+@end example
+
+@noindent
+(Some blank lines of no semantic significance, and some other abbrev
+tables, have been omitted.)
+
+ A line containing a name in parentheses is the header for abbrevs in a
+particular abbrev table; @code{global-abbrev-table} contains all the global
+abbrevs, and the other abbrev tables that are named after major modes
+contain the mode-specific abbrevs.
+
+ Within each abbrev table, each nonblank line defines one abbrev. The
+word at the beginning is the abbrev. The number that appears is the number
+of times the abbrev has been expanded. Emacs keeps track of this to help
+you see which abbrevs you actually use, in case you decide to eliminate
+those that you don't use often. The string at the end of the line is the
+expansion.
+
+@findex edit-abbrevs
+@kindex C-c C-c (Edit Abbrevs)
+@findex edit-abbrevs-redefine
+@cindex Edit-Abbrevs mode
+ @kbd{M-x edit-abbrevs} allows you to add, change or kill abbrev
+definitions by editing a list of them in an Emacs buffer. The list has the
+same format described above. The buffer of abbrevs is called @samp{*Abbrevs*},
+and is in Edit-Abbrevs mode. This mode redefines the key @kbd{C-c C-c} to
+install the abbrev definitions as specified in the buffer. The command
+that does this is @code{edit-abbrevs-redefine}. Any abbrevs not described
+in the buffer are eliminated when this is done.
+
+ @code{edit-abbrevs} is actually the same as @code{list-abbrevs} except
+that it selects the buffer @samp{*Abbrevs*} whereas @code{list-abbrevs}
+merely displays it in another window.
+
+@node Saving Abbrevs, Dynamic Abbrevs, Editing Abbrevs, Abbrevs
+@section Saving Abbrevs
+
+ These commands allow you to keep abbrev definitions between editing
+sessions.
+
+@table @kbd
+@item M-x write-abbrev-file
+Write a file describing all defined abbrevs.
+@item M-x read-abbrev-file
+Read such a file and define abbrevs as specified there.
+@item M-x quietly-read-abbrev-file
+Similar but do not display a message about what is going on.
+@item M-x define-abbrevs
+Define abbrevs from buffer.
+@item M-x insert-abbrevs
+Insert all abbrevs and their expansions into the buffer.
+@end table
+
+@findex write-abbrev-file
+ @kbd{M-x write-abbrev-file} reads a file name using the minibuffer and
+writes a description of all current abbrev definitions into that file. The
+text stored in the file looks like the output of @kbd{M-x list-abbrevs}.
+This is used to save abbrev definitions for use in a later session.
+
+@findex read-abbrev-file
+@findex quietly-read-abbrev-file
+@vindex abbrev-file-name
+ @kbd{M-x read-abbrev-file} reads a file name using the minibuffer and
+reads the file, defining abbrevs according to the contents of the file.
+@kbd{M-x quietly-read-abbrev-file} is the same except that it does not
+display a message in the echo area saying that it is doing its work; it
+is actually useful primarily in the @file{.emacs} file. If an empty
+argument is given to either of these functions, the file name used is the
+value of the variable @code{abbrev-file-name}, which is by default
+@code{"~/.abbrev_defs"}.
+
+@vindex save-abbrevs
+ Emacs will offer to save abbrevs automatically if you have changed any of
+them, whenever it offers to save all files (for @kbd{C-x s} or @kbd{C-x
+C-c}). This feature can be inhibited by setting the variable
+@code{save-abbrevs} to @code{nil}.
+
+@findex insert-abbrevs
+@findex define-abbrevs
+ The commands @kbd{M-x insert-abbrevs} and @kbd{M-x define-abbrevs} are
+similar to the previous commands but work on text in an Emacs buffer.
+@kbd{M-x insert-abbrevs} inserts text into the current buffer before point,
+describing all current abbrev definitions; @kbd{M-x define-abbrevs} parses
+the entire current buffer and defines abbrevs accordingly.@refill
+
+@node Dynamic Abbrevs,, Saving Abbrevs, Abbrevs
+@section Dynamic Abbrev Expansion
+@cindex dynamic abbrevs
+
+ The abbrev facility described above operates automatically as you insert
+text, but all abbrevs must be defined explicitly. By contrast,
+@dfn{dynamic abbrevs} allow the meanings of abbrevs to be determined
+automatically from the contents of the buffer, but dynamic abbrev expansion
+happens only when you request it explicitly.
+
+@kindex M-/
+@findex dabbrev-expand
+@table @kbd
+@item M-/
+Expand the word in the buffer before point as a @dfn{dynamic abbrev},
+by searching in the buffer for words starting with that abbreviation
+(@code{dabbrev-expand}).
+@end table
+
+ For example, if the buffer contains @samp{does this follow } and you type
+@w{@kbd{f o M-/}}, the effect is to insert @samp{follow} because that is
+the last word in the buffer that starts with @samp{fo}. A numeric
+argument to @kbd{M-/} says to take the second, third, etc.@: distinct
+expansion found looking backward from point. Repeating @kbd{M-/}
+searches for an alternative expansion by looking farther back. After
+the part of the buffer preceding point has been considered, the part
+of the buffer after point is searched.
+
+ Dynamic abbrev expansion is completely independent of Abbrev mode; the
+expansion of a word with @kbd{M-/} is completely independent of whether it
+has a definition as an ordinary abbrev.
+
+@node Picture, Sending Mail, Abbrevs, Top
+@chapter Editing Pictures
+@cindex pictures
+@findex edit-picture
+@cindex Picture mode
+
+ If you want to create a picture made out of text characters (for example,
+a picture of the division of a register into fields, as a comment in a
+program), use the command @code{edit-picture} to enter Picture mode.
+
+ In Picture mode, editing is based on the @dfn{quarter-plane} model of
+text, according to which the text characters lie studded on an area that
+stretches infinitely far to the right and downward. The concept of the end
+of a line does not exist in this model; the most you can say is where the
+last nonblank character on the line is found.
+
+ Of course, Emacs really always considers text as a sequence of
+characters, and lines really do have ends. But in Picture mode most
+frequently-used keys are rebound to commands that simulate the
+quarter-plane model of text. They do this by inserting spaces or by
+converting tabs to spaces.
+
+ Most of the basic editing commands of Emacs are redefined by Picture mode
+to do essentially the same thing but in a quarter-plane way. In addition,
+Picture mode defines various keys starting with the @kbd{C-c} prefix to
+run special picture editing commands.
+
+ One of these keys, @kbd{C-c C-c}, is pretty important. Often a picture
+is part of a larger file that is usually edited in some other major mode.
+@kbd{M-x edit-picture} records the name of the previous major mode, and
+then you can use the @kbd{C-c C-c} command (@code{picture-mode-exit}) to
+restore that mode. @kbd{C-c C-c} also deletes spaces from the ends of
+lines, unless given a numeric argument.
+
+ The commands used in Picture mode all work in other modes (provided the
+@file{picture} library is loaded), but are not bound to keys except in
+Picture mode. Note that the descriptions below talk of moving ``one
+column'' and so on, but all the picture mode commands handle numeric
+arguments as their normal equivalents do.
+
+@vindex picture-mode-hook
+ Turning on Picture mode calls the value of the variable @code{picture-mode-hook}
+as a function, with no arguments, if that value exists and is non-@code{nil}.
+
+@menu
+* Basic Picture:: Basic concepts and simple commands of Picture Mode.
+* Insert in Picture:: Controlling direction of cursor motion
+ after "self-inserting" characters.
+* Tabs in Picture:: Various features for tab stops and indentation.
+* Rectangles in Picture:: Clearing and superimposing rectangles.
+@end menu
+
+@node Basic Picture, Insert in Picture, Picture, Picture
+@section Basic Editing in Picture Mode
+
+@findex picture-forward-column
+@findex picture-backward-column
+@findex picture-move-down
+@findex picture-move-up
+ Most keys do the same thing in Picture mode that they usually do, but do
+it in a quarter-plane style. For example, @kbd{C-f} is rebound to run
+@code{picture-forward-column}, which is defined to move point one column to
+the right, by inserting a space if necessary, so that the actual end of the
+line makes no difference. @kbd{C-b} is rebound to run
+@code{picture-backward-column}, which always moves point left one column,
+converting a tab to multiple spaces if necessary. @kbd{C-n} and @kbd{C-p}
+are rebound to run @code{picture-move-down} and @code{picture-move-up},
+which can either insert spaces or convert tabs as necessary to make sure
+that point stays in exactly the same column. @kbd{C-e} runs
+@code{picture-end-of-line}, which moves to after the last nonblank
+character on the line. There is no need to change @kbd{C-a}, as the choice
+of screen model does not affect beginnings of lines.@refill
+
+@findex picture-newline
+ Insertion of text is adapted to the quarter-plane screen model through
+the use of Overwrite mode (@pxref{Minor Modes}). Self-inserting characters
+replace existing text, column by column, rather than pushing existing text
+to the right. @key{RET} runs @code{picture-newline}, which just moves to
+the beginning of the following line so that new text will replace that
+line.
+
+@findex picture-backward-clear-column
+@findex picture-clear-column
+@findex picture-clear-line
+ Deletion and killing of text are replaced with erasure. @key{DEL}
+(@code{picture-backward-clear-column}) replaces the preceding character
+with a space rather than removing it. @kbd{C-d}
+(@code{picture-clear-column}) does the same thing in a forward direction.
+@kbd{C-k} (@code{picture-clear-line}) really kills the contents of lines,
+but does not ever remove the newlines from the buffer.@refill
+
+@findex picture-open-line
+ To do actual insertion, you must use special commands. @kbd{C-o}
+(@code{picture-open-line}) still creates a blank line, but does so after
+the current line; it never splits a line. @kbd{C-M-o}, @code{split-line},
+makes sense in Picture mode, so it is not changed. @key{LFD}
+(@code{picture-duplicate-line}) inserts below the current line another line
+with the same contents.@refill
+
+@kindex C-c C-d (Picture mode)
+@findex delete-char
+ Real deletion can be done with @kbd{C-w}, or with @kbd{C-c C-d} (which is
+defined as @code{delete-char}, as @kbd{C-d} is in other modes), or with one
+of the picture rectangle commands (@pxref{Rectangles in Picture}).
+
+@node Insert in Picture, Tabs in Picture, Basic Picture, Picture
+@section Controlling Motion after Insert
+
+@findex picture-movement-up
+@findex picture-movement-down
+@findex picture-movement-left
+@findex picture-movement-right
+@findex picture-movement-nw
+@findex picture-movement-ne
+@findex picture-movement-sw
+@findex picture-movement-se
+@kindex C-c < (Picture mode)
+@kindex C-c > (Picture mode)
+@kindex C-c ^ (Picture mode)
+@kindex C-c . (Picture mode)
+@kindex C-c ` (Picture mode)
+@kindex C-c ' (Picture mode)
+@kindex C-c / (Picture mode)
+@kindex C-c \ (Picture mode)
+ Since ``self-inserting'' characters in Picture mode just overwrite and
+move point, there is no essential restriction on how point should be moved.
+Normally point moves right, but you can specify any of the eight orthogonal
+or diagonal directions for motion after a ``self-inserting'' character.
+This is useful for drawing lines in the buffer.
+
+@table @kbd
+@item C-c <
+Move left after insertion (@code{picture-movement-left}).
+@item C-c >
+Move right after insertion (@code{picture-movement-right}).
+@item C-c ^
+Move up after insertion (@code{picture-movement-up}).
+@item C-c .
+Move down after insertion (@code{picture-movement-down}).
+@c !!! added @* to prevent overfull hbox
+@item C-c `
+Move up and left (``northwest'') after insertion@*
+(@code{picture-movement-nw}).
+@item C-c '
+Move up and right (``northeast'') after insertion
+(@code{picture-movement-ne}).
+@item C-c /
+Move down and left (``southwest'') after insertion
+(@code{picture-movement-sw}).
+@item C-c \
+Move down and right (``southeast'') after insertion
+(@code{picture-movement-se}).
+@end table
+
+@kindex C-c C-f (Picture mode)
+@kindex C-c C-b (Picture mode)
+@findex picture-motion
+@findex picture-motion-reverse
+ Two motion commands move based on the current Picture insertion
+direction. The command @kbd{C-c C-f} (@code{picture-motion}) moves in the
+same direction as motion after ``insertion'' currently does, while @kbd{C-c
+C-b} (@code{picture-motion-reverse}) moves in the opposite direction.
+
+@node Tabs in Picture, Rectangles in Picture, Insert in Picture, Picture
+@section Picture Mode Tabs
+
+@kindex M-TAB
+@findex picture-tab-search
+@vindex picture-tab-chars
+ Two kinds of tab-like action are provided in Picture mode.
+Context-based tabbing is done with @kbd{M-@key{TAB}}
+(@code{picture-tab-search}). With no argument, it moves to a point
+underneath the next ``interesting'' character that follows whitespace in
+the previous nonblank line. ``Next'' here means ``appearing at a
+horizontal position greater than the one point starts out at''. With an
+argument, as in @kbd{C-u M-@key{TAB}}, this command moves to the next such
+interesting character in the current line. @kbd{M-@key{TAB}} does not
+change the text; it only moves point. ``Interesting'' characters are
+defined by the variable @code{picture-tab-chars}, which contains a string
+whose characters are all considered interesting. Its default value is
+@code{"!-~"}.@refill
+
+@findex picture-tab
+ @key{TAB} itself runs @code{picture-tab}, which operates based on the
+current tab stop settings; it is the Picture mode equivalent of
+@code{tab-to-tab-stop}. Normally it just moves point, but with a numeric
+argument it clears the text that it moves over.
+
+@kindex C-c TAB (Picture mode)
+@findex picture-set-tab-stops
+ The context-based and tab-stop-based forms of tabbing are brought
+together by the command @kbd{C-c @key{TAB}}, @code{picture-set-tab-stops}.
+This command sets the tab stops to the positions which @kbd{M-@key{TAB}}
+would consider significant in the current line. The use of this command,
+together with @key{TAB}, can get the effect of context-based tabbing. But
+@kbd{M-@key{TAB}} is more convenient in the cases where it is sufficient.
+
+@node Rectangles in Picture,, Tabs in Picture, Picture
+@section Picture Mode Rectangle Commands
+@cindex rectangles and Picture mode
+
+ Picture mode defines commands for working on rectangular pieces of the
+text in ways that fit with the quarter-plane model. The standard rectangle
+commands may also be useful (@pxref{Rectangles}).
+
+@table @kbd
+@item C-c C-k
+Clear out the region-rectangle (@code{picture-clear-rectangle}). With
+argument, kill it.
+@item C-c C-w @var{r}
+Similar but save rectangle contents in register @var{r} first
+(@code{picture-clear-rectangle-to-register}).
+@item C-c C-y
+Copy last killed rectangle into the buffer by overwriting, with upper
+left corner at point (@code{picture-yank-rectangle}). With argument,
+insert instead.
+@item C-c C-x @var{r}
+Similar, but use the rectangle in register @var{r}
+(@code{picture-yank-rectangle-from-register}).
+@end table
+
+@kindex C-c C-k (Picture mode)
+@kindex C-c C-w (Picture mode)
+@findex picture-clear-rectangle
+@findex picture-clear-rectangle-to-register
+ The picture rectangle commands @kbd{C-c C-k}
+(@code{picture-clear-rectangle}) and @kbd{C-c C-w}
+(@code{picture-clear-rectangle-to-register}) differ from the standard
+rectangle commands in that they normally clear the rectangle instead of
+deleting it; this is analogous with the way @kbd{C-d} is changed in Picture
+mode.@refill
+
+ However, deletion of rectangles can be useful in Picture mode, so these
+commands delete the rectangle if given a numeric argument.
+
+@kindex C-c C-y (Picture mode)
+@kindex C-c C-x (Picture mode)
+@findex picture-yank-rectangle
+@findex picture-yank-rectangle-from-register
+ The Picture mode commands for yanking rectangles differ from the standard
+ones in overwriting instead of inserting. This is the same way that
+Picture mode insertion of other text is different from other modes.
+@kbd{C-c C-y} (@code{picture-yank-rectangle}) inserts (by overwriting) the
+rectangle that was most recently killed, while @kbd{C-c C-x}
+(@code{picture-yank-rectangle-from-register}) does likewise for the
+rectangle found in a specified register.
+
+@node Sending Mail, Rmail, Picture, Top
+@chapter Sending Mail
+@cindex mail
+@cindex message
+
+ To send a message in Emacs, you start by typing a command (@kbd{C-x m})
+to select and initialize the @samp{*mail*} buffer. Then you edit the text
+and headers of the message in this buffer, and type another command
+(@kbd{C-c C-c}) to send the message.
+
+@table @kbd
+@item C-x m
+Begin composing a message to send (@code{mail}).
+@item C-x 4 m
+Likewise, but display the message in another window
+(@code{mail-other-window}).
+@item C-c C-c
+In Mail mode, send the message and switch to another buffer
+(@code{mail-send-and-exit}).
+@end table
+
+@kindex C-x m
+@findex mail
+@kindex C-x 4 m
+@findex mail-other-window
+ The command @kbd{C-x m} (@code{mail}) selects a buffer named
+@samp{*mail*} and initializes it with the skeleton of an outgoing message.
+@kbd{C-x 4 m} (@code{mail-other-window}) selects the @samp{*mail*} buffer
+in a different window, leaving the previous current buffer visible.@refill
+
+ Because the mail composition buffer is an ordinary Emacs buffer, you can
+switch to other buffers while in the middle of composing mail, and switch
+back later (or never). If you use the @kbd{C-x m} command again when you
+have been composing another message but have not sent it, you are asked to
+confirm before the old message is erased. If you answer @kbd{n}, the
+@samp{*mail*} buffer is left selected with its old contents, so you can
+finish the old message and send it. @kbd{C-u C-x m} is another way to do
+this. Sending the message marks the @samp{*mail*} buffer ``unmodified'',
+which avoids the need for confirmation when @kbd{C-x m} is next used.
+
+ If you are composing a message in the @samp{*mail*} buffer and want to
+send another message before finishing the first, rename the @samp{*mail*}
+buffer using @kbd{M-x rename-buffer} (@pxref{Misc Buffer}).
+
+@menu
+* Format: Mail Format. Format of the mail being composed.
+* Headers: Mail Headers. Details of allowed mail header fields.
+* Mode: Mail Mode. Special commands for editing mail being composed.
+@end menu
+
+@node Mail Format, Mail Headers, Sending Mail, Sending Mail
+@section The Format of the Mail Buffer
+
+ In addition to the @dfn{text} or contents, a message has @dfn{header
+fields} which say who sent it, when, to whom, why, and so on. Some header
+fields such as the date and sender are created automatically after the
+message is sent. Others, such as the recipient names, must be specified by
+you in order to send the message properly.
+
+ Mail mode provides a few commands to help you edit some header fields,
+and some are preinitialized in the buffer automatically at times. You can
+insert or edit any header fields using ordinary editing commands.
+
+ The line in the buffer that says
+
+@example
+--text follows this line--
+@end example
+
+@vindex mail-header-separator
+@noindent
+is a special delimiter that separates the headers you have specified from
+the text. Whatever follows this line is the text of the message; the
+headers precede it. The delimiter line itself does not appear in the
+message actually sent. The text used for the delimiter line is controlled
+by the variable @code{mail-header-separator}.
+
+Here is an example of what the headers and text in the @samp{*mail*} buffer
+might look like.
+
+@example
+To: rms@@mc
+CC: mly@@mc, rg@@oz
+Subject: The Emacs Manual
+--Text follows this line--
+Please ignore this message.
+@end example
+
+@node Mail Headers, Mail Mode, Mail Format, Sending Mail
+@section Mail Header Fields
+@cindex headers (of mail message)
+
+ There are several header fields you can use in the @samp{*mail*} buffer.
+Each header field starts with a field name at the beginning of a line,
+terminated by a colon. It does not matter whether you use upper or lower
+case in the field name. After the colon and optional whitespace comes the
+contents of the field.
+
+@table @samp
+@item To
+This field contains the mailing addresses to which the message is
+addressed.
+
+@item Subject
+The contents of the @samp{Subject} field should be a piece of text
+that says what the message is about. The reason @samp{Subject} fields
+are useful is that most mail-reading programs can provide a summary of
+messages, listing the subject of each message but not its text.
+
+@item CC
+This field contains additional mailing addresses to send the message
+to, but whose readers should not regard the message as addressed to
+them.
+
+@item BCC
+This field contains additional mailing addresses to send the message
+to, but which should not appear in the header of the message actually
+sent.
+
+@item FCC
+This field contains the name of one file (in Unix mail file format) to
+which a copy of the message should be appended when the message is
+sent.
+
+@item From
+Use the @samp{From} field to say who you are, when the account you are
+using to send the mail is not your own. The contents of the
+@samp{From} field should be a valid mailing address, since replies
+will normally go there.
+
+@item Reply-To
+Use the @samp{Reply-to} field to direct replies to a different
+address, not your own. There is no difference between @samp{From} and
+@samp{Reply-to} in their effect on where replies go, but they convey a
+different meaning to the human who reads the message.
+
+@vindex mail-default-reply-to
+If you set the variable @code{mail-default-reply-to} to a non-@code{nil}
+value, then every message you begin to edit will have a @samp{Reply-to}
+field whose contents are the value of the variable.
+
+@item In-Reply-To
+This field contains a piece of text describing a message you are
+replying to. Some mail systems can use this information to correlate
+related pieces of mail. Normally this field is filled in by Rmail
+when you are replying to a message in Rmail, and you never need to
+think about it (@pxref{Rmail}).
+@end table
+
+The @samp{To}, @samp{CC}, @samp{BCC} and @samp{FCC} fields can appear
+any number of times, to specify many places to send the message.
+
+The @samp{To}, @samp{CC}, and @samp{BCC} fields can have continuation
+lines. All the lines starting with whitespace, following the line on
+which the field starts, are considered part of the field. For
+example,@refill
+
+@example
+@group
+To: foo@@here, this@@there,
+ me@@gnu.cambridge.mass.usa.earth.spiral3281
+@end group
+@end example
+
+If you have a @file{~/.mailrc} file, Emacs will scan it for mail aliases
+the first time you try to send mail in an Emacs session. Aliases found
+in the @samp{To}, @samp{CC}, and @samp{BCC} fields will be expanded where
+appropriate.
+
+@vindex mail-archive-file-name
+ If the variable @code{mail-archive-file-name} is non-@code{nil}, it should be a
+string naming a file; every time you start to edit a message to send,
+an @samp{FCC} field will be put in for that file. Unless you remove the
+@samp{FCC} field, every message will be written into that file when it is
+sent.
+
+@node Mail Mode,, Mail Headers, Sending Mail
+@section Mail Mode
+@cindex Mail mode
+
+ The major mode used in the @samp{*mail*} buffer is Mail mode, which is
+much like Text mode except that various special commands are provided on
+the @w{@kbd{C-c}} prefix. These commands all have to do specifically with
+editing or sending the message.
+
+@table @kbd
+@item C-c C-s
+Send the message, and leave the @samp{*mail*} buffer selected
+(@code{mail-send}).
+@item C-c C-c
+Send the message, and select some other buffer (@code{mail-send-and-exit}).
+@item C-c C-f C-t
+Move to the @samp{To} header field, creating one if there is none
+(@code{mail-to}).
+@item C-c C-f C-s
+Move to the @samp{Subject} header field, creating one if there is
+none (@code{mail-subject}).
+@item C-c C-f C-c
+Move to the @samp{CC} header field, creating one if there is none
+(@code{mail-cc}).
+@item C-c C-w
+Insert the file @file{~/.signature} at the end of the message text
+(@code{mail-signature}).
+@item C-c C-y
+Yank the selected message from Rmail (@code{mail-yank-original}).
+This command does nothing unless your command to start sending a
+message was issued with Rmail.
+@item C-c C-q
+Fill all paragraphs of yanked old messages, each individually
+(@code{mail-fill-yanked-message}).
+@end table
+
+@kindex C-c C-s (Mail mode)
+@kindex C-c C-c (Mail mode)
+@findex mail-send
+@findex mail-send-and-exit
+ There are two ways to send the message. @kbd{C-c C-s} (@code{mail-send})
+sends the message and marks the @samp{*mail*} buffer unmodified, but leaves
+that buffer selected so that you can modify the message (perhaps with new
+recipients) and send it again. @kbd{C-c C-c} (@code{mail-send-and-exit})
+sends and then deletes the window (if there is another window) or switches
+to another buffer. It puts the @samp{*mail*} buffer at the lowest priority
+for automatic reselection, since you are finished with using it. This is
+the usual way to send the message.
+
+@kindex C-c C-f C-t (Mail mode)
+@findex mail-to
+@kindex C-c C-f C-s (Mail mode)
+@findex mail-subject
+@kindex C-c C-f C-c (Mail mode)
+@findex mail-cc
+ Mail mode provides some other special commands that are useful for
+editing the headers and text of the message before you send it. There are
+three commands defined to move point to particular header fields, all based
+on the prefix @kbd{C-c C-f} (@samp{C-f} is for ``field''). They are
+@kbd{C-c C-f C-t} (@code{mail-to}) to move to the @samp{To} field, @kbd{C-c
+C-f C-s} (@code{mail-subject}) for the @samp{Subject} field, and @kbd{C-c
+C-f C-c} (@code{mail-cc}) for the @samp{CC} field. These fields have
+special motion commands because they are the most common fields for the
+user to want to edit.
+
+@kindex C-c C-w (Mail mode)
+@findex mail-signature
+ @kbd{C-c C-w} (@code{mail-signature}) adds a standard piece text at the end of the
+message to say more about who you are. The text comes from the file
+@file{.signature} in your home directory.
+
+@kindex C-c C-y (Mail mode)
+@findex mail-yank-original
+ When mail sending is invoked from the Rmail mail reader using an Rmail
+command, @kbd{C-c C-y} can be used inside the @samp{*mail*} buffer to insert
+the text of the message you are replying to. Normally it indents each line
+of that message four spaces and eliminates most header fields. A numeric
+argument specifies the number of spaces to indent. An argument of just
+@kbd{C-u} says not to indent at all and not to eliminate anything.
+@kbd{C-c C-y} always uses the current message from the @samp{RMAIL} buffer,
+so you can insert several old messages by selecting one in @samp{RMAIL},
+switching to @samp{*mail*} and yanking it, then switching back to
+@samp{RMAIL} to select another.@refill
+
+@kindex C-c C-q (Mail mode)
+@findex mail-fill-yanked-message
+@c !!! the following is verbose to prevent an overfull hbox
+ After using @kbd{C-c C-y}, you can type
+the command @kbd{C-c C-q} (@code{mail-fill-yanked-message}) to
+fill the paragraphs of the yanked old message or messages. One
+use of @kbd{C-c C-q} fills all such paragraphs, each one separately.
+
+@vindex mail-mode-hook
+@vindex mail-setup-hook
+ Turning on Mail mode (which @kbd{C-x m} does automatically) calls the
+value of @code{text-mode-hook}, if it is not void or @code{nil}, and
+then calls the value of @code{mail-mode-hook} if that is not void or
+@code{nil}. Aside from these, the @code{mail} command runs
+@code{mail-setup-hook} whenever it initializes the @samp{*mail*} buffer
+for editing a message.
+
+@node Rmail, Recursive Edit, Sending Mail, Top
+@chapter Reading Mail with Rmail
+@cindex Rmail
+@cindex message
+@findex rmail
+@cindex Rmail mode
+
+ Rmail is an Emacs subsystem for reading and disposing of mail that you
+receive. Rmail stores mail messages in files called @dfn{Rmail
+files}. Reading the message in an Rmail file is done in a special
+major mode, Rmail mode, which redefines most letters to run commands
+for managing mail. To enter Rmail, type @kbd{M-x rmail}. This reads
+your primary mail file, merges new mail in from your inboxes, displays
+the first new message, and lets you begin reading.
+
+@cindex primary mail file
+ Using Rmail in the simplest fashion, you have one Rmail file, @file{~/RMAIL},
+in which all of your mail is saved. It is called your @dfn{primary mail
+file}. In more sophisticated usage, you can copy messages into other Rmail
+files and then edit those files with Rmail.
+
+ Rmail displays only one message at a time. It is called the @dfn{current
+message}. Rmail mode's special commands can do such things as move to
+another message, delete the message, copy the message into another file, or
+send a reply.
+
+@cindex message number
+ Within the Rmail file, messages are arranged sequentially in order
+of receipt. They are also assigned consecutive integers as their
+@dfn{message numbers}. The number of the current message is displayed
+in Rmail's mode line, followed by the total number of messages in the
+file. You can move to a message by specifying its message number
+using the @kbd{j} key (@pxref{Rmail Motion}).
+
+@kindex s (Rmail)
+@findex rmail-save
+ Following the usual conventions of Emacs, changes in an Rmail file become
+permanent only when the file is saved. You can do this with @kbd{s}
+(@code{rmail-save}), which also expunges deleted messages from the file
+first (@pxref{Rmail Deletion}). To save the file without expunging, use
+@kbd{C-x C-s}. Rmail saves the Rmail file spontaneously when moving new
+mail from an inbox file (@pxref{Rmail Inbox}).
+
+@kindex q (Rmail)
+@findex rmail-quit
+ You can exit Rmail with @kbd{q} (@code{rmail-quit}); this expunges and saves the
+Rmail file and then switches to another buffer. But there is no need to
+`exit' formally. If you switch from Rmail to editing in other buffers, and
+never happen to switch back, you have exited. Just make sure to save the
+Rmail file eventually (like any other file you have changed). @kbd{C-x s}
+is a good enough way to do this (@pxref{Saving}).
+
+@menu
+* Scroll: Rmail Scrolling. Scrolling through a message.
+* Motion: Rmail Motion. Moving to another message.
+* Deletion: Rmail Deletion. Deleting and expunging messages.
+* Inbox: Rmail Inbox. How mail gets into the Rmail file.
+* Files: Rmail Files. Using multiple Rmail files.
+* Output: Rmail Output. Copying message out to files.
+* Labels: Rmail Labels. Classifying messages by labeling them.
+* Summary: Rmail Summary. Summaries show brief info on many messages.
+* Reply: Rmail Reply. Sending replies to messages you are viewing.
+* Editing: Rmail Editing. Editing message text and headers in Rmail.
+* Digest: Rmail Digest. Extracting the messages from a digest message.
+@end menu
+
+@node Rmail Scrolling, Rmail Motion, Rmail, Rmail
+@section Scrolling Within a Message
+
+ When Rmail displays a message that does not fit on the screen, it is
+necessary to scroll through it. This could be done with @kbd{C-v}, @kbd{M-v}
+and @kbd{M-<}, but in Rmail scrolling is so frequent that it deserves to be
+easier to type.
+
+@need 1800
+@table @kbd
+@item @key{SPC}
+Scroll forward (@code{scroll-up}).
+@item @key{DEL}
+Scroll backward (@code{scroll-down}).
+@item .
+Scroll to start of message (@code{rmail-beginning-of-message}).
+@end table
+
+@kindex SPC (Rmail)
+@kindex DEL (Rmail)
+ Since the most common thing to do while reading a message is to scroll
+through it by screenfuls, Rmail makes @key{SPC} and @key{DEL} synonyms of
+@kbd{C-v} (@code{scroll-up}) and @kbd{M-v} (@code{scroll-down}).
+
+@kindex . (Rmail)
+@findex rmail-beginning-of-message
+ The command @kbd{.} (@code{rmail-beginning-of-message}) scrolls back to the
+beginning of the selected message. This is not quite the same as @kbd{M-<}:
+for one thing, it does not set the mark; for another, it resets the buffer
+boundaries to the current message if you have changed them.
+
+@node Rmail Motion, Rmail Deletion, Rmail Scrolling, Rmail
+@section Moving Among Messages
+
+ The most basic thing to do with a message is to read it. The way to do
+this in Rmail is to make the message current. You can make any message
+current given its message number using the @kbd{j} command, but the usual
+thing to do is to move sequentially through the file, since this is the
+order of receipt of messages. When you enter Rmail, you are positioned at
+the first new message (new messages are those received since the previous
+use of Rmail), or at the last message if there are no new messages this
+time. Move forward to see the other new messages; move backward to
+reexamine old messages.
+
+@table @kbd
+@item n
+Move to the next nondeleted message, skipping any intervening deleted
+messages (@code{rmail-next-undeleted-message}).
+@item p
+@c !!! added @* to prevent overfull hbox
+Move to the previous nondeleted message@*
+(@code{rmail-previous-undeleted-message}).
+@item M-n
+@c !!! added @* to prevent overfull hbox
+Move to the next message, including deleted messages@*
+(@code{rmail-next-message}).
+@item M-p
+@c !!! added @* to prevent overfull hbox
+Move to the previous message, including deleted messages@*
+(@code{rmail-previous-message}).
+@item j
+Move to the first message. With argument @var{n}, move to
+message number @var{n} (@code{rmail-show-message}).
+@item >
+Move to the last message (@code{rmail-last-message}).
+
+@item M-s @var{regexp} @key{RET}
+Move to the next message containing a match for @var{regexp}
+(@code{rmail-search}). If @var{regexp} is empty, the last regexp used is
+used again.
+
+@item - M-s @var{regexp} @key{RET}
+Move to the previous message containing a match for @var{regexp}.
+If @var{regexp} is empty, the last regexp used is used again.
+@end table
+
+@kindex n (Rmail)
+@kindex p (Rmail)
+@kindex M-n (Rmail)
+@kindex M-p (Rmail)
+@findex rmail-next-undeleted-message
+@findex rmail-previous-undeleted-message
+@findex rmail-next-message
+@findex rmail-previous-message
+ @kbd{n} and @kbd{p} are the usual way of moving among messages in Rmail. They
+move through the messages sequentially, but skip over deleted messages,
+which is usually what you want to do. Their command definitions are named
+@code{rmail-next-undeleted-message} and @code{rmail-previous-undeleted-message}. If
+you do not want to skip deleted messages---for example, if you want to move
+to a message to undelete it---use the variants @kbd{M-n} and @kbd{M-p}
+(@code{rmail-next-message} and @code{rmail-previous-message}). A numeric
+argument to any of these commands serves as a repeat count.@refill
+
+ In Rmail, you can specify a numeric argument by typing the digits.
+It is not necessary to type @kbd{C-u} first.
+
+@kindex M-s (Rmail)
+@findex rmail-search
+ The @kbd{M-s} (@code{rmail-search}) command is Rmail's version of search. The
+usual incremental search command @kbd{C-s} works in Rmail, but it searches
+only within the current message. The purpose of @kbd{M-s} is to search for
+another message. It reads a regular expression (@pxref{Regexps})
+nonincrementally, then searches starting at the beginning of the following
+message for a match. The message containing the match is selected.
+
+ To search backward in the file for another message, give @kbd{M-s} a
+negative argument. In Rmail this can be done with @kbd{- M-s}.
+
+ It is also possible to search for a message based on labels.
+@xref{Rmail Labels}.
+
+@kindex j (Rmail)
+@kindex > (Rmail)
+@findex rmail-show-message
+@findex rmail-last-message
+ To move to a message specified by absolute message number, use @kbd{j}
+(@code{rmail-show-message}) with the message number as argument. With no
+argument, @kbd{j} selects the first message. @kbd{>} (@code{rmail-last-message}) selects
+the last message.
+
+ Each time Rmail selects a message, it calls (with no arguments) the
+value of the variable @code{rmail-show-message-hook}, if that is
+non-@code{nil}.
+
+@node Rmail Deletion, Rmail Inbox, Rmail Motion, Rmail
+@section Deleting Messages
+
+@cindex deletion (Rmail)
+ When you no longer need to keep a message, you can @dfn{delete} it. This
+flags it as ignorable, and some Rmail commands will pretend it is no longer
+present; but it still has its place in the Rmail file, and still has its
+message number.
+
+@cindex expunging (Rmail)
+ @dfn{Expunging} the Rmail file actually removes the deleted messages.
+The remaining messages are renumbered consecutively. Expunging is the only
+action that changes the message number of any message, except for
+undigestifying (@pxref{Rmail Digest}).
+
+@table @kbd
+@item d
+Delete the current message, and move to the next nondeleted message
+(@code{rmail-delete-forward}).
+@item C-d
+Delete the current message, and move to the previous nondeleted
+message (@code{rmail-delete-backward}).
+@item u
+Undelete the current message, or move back to a deleted message and
+undelete it (@code{rmail-undelete-previous-message}).
+@item x
+@itemx e
+Expunge the Rmail file (@code{rmail-expunge}). These two
+commands are synonyms.
+@end table
+
+@kindex d (Rmail)
+@kindex C-d (Rmail)
+@findex rmail-delete-forward
+@findex rmail-delete-backward
+ There are two Rmail commands for deleting messages. Both delete the
+current message and select another message. @kbd{d} (@code{rmail-delete-forward})
+moves to the following message, skipping messages already deleted, while
+@kbd{C-d} (@code{rmail-delete-backward}) moves to the previous nondeleted message.
+If there is no nondeleted message to move to in the specified direction,
+the message that was just deleted remains current.
+
+@cindex undeletion (Rmail)
+@kindex e (Rmail)
+@findex rmail-expunge
+ To make all the deleted messages finally vanish from the Rmail file,
+type @kbd{e} (@code{rmail-expunge}). Until you do this, you can still @dfn{undelete}
+the deleted messages.
+
+@kindex u (Rmail)
+@findex rmail-undelete-previous-message
+ To undelete, type
+@kbd{u} (@code{rmail-undelete-previous-message}), which is designed to cancel the
+effect of a @kbd{d} command (usually). It undeletes the current message
+if the current message is deleted. Otherwise it moves backward to previous
+messages until a deleted message is found, and undeletes that message.
+
+ You can usually undo a @kbd{d} with a @kbd{u} because the @kbd{u} moves
+back to and undeletes the message that the @kbd{d} deleted. But this does
+not work when the @kbd{d} skips a few already-deleted messages that follow
+the message being deleted; then the @kbd{u} command will undelete the last
+of the messages that were skipped. There is no clean way to avoid this
+problem. However, by repeating the @kbd{u} command, you can eventually get
+back to the message that you intended to undelete. You can also reach that
+message with @kbd{M-p} commands and then type @kbd{u}.@refill
+
+ A deleted message has the @samp{deleted} attribute, and as a result
+@samp{deleted} appears in the mode line when the current message is
+deleted. In fact, deleting or undeleting a message is nothing more than
+adding or removing this attribute. @xref{Rmail Labels}.
+
+@node Rmail Inbox, Rmail Files, Rmail Deletion, Rmail
+@section Rmail Files and Inboxes
+@cindex inbox file
+
+ Unix places incoming mail for you in a file that we call your @dfn{inbox}.
+When you start up Rmail, it copies the new messages from your inbox into
+your primary mail file, an Rmail file, which also contains other messages
+saved from previous Rmail sessions. It is in this file that you actually
+read the mail with Rmail. This operation is called @dfn{getting new mail}.
+It can be repeated at any time using the @kbd{g} key in Rmail. The inbox
+file name is @file{/usr/spool/mail/@var{username}} in Berkeley Unix,
+@file{/usr/mail/@var{username}} in System V.
+
+ There are two reasons for having separate Rmail files and inboxes.
+
+@enumerate
+@item
+The format in which Unix delivers the mail in the inbox is not
+adequate for Rmail mail storage. It has no way to record attributes
+(such as @samp{deleted}) or user-specified labels; it has no way to record
+old headers and reformatted headers; it has no way to record cached
+summary line information.
+
+@item
+It is very cumbersome to access an inbox file without danger of losing
+mail, because it is necessary to interlock with mail delivery.
+Moreover, different Unix systems use different interlocking
+techniques. The strategy of moving mail out of the inbox once and for
+all into a separate Rmail file avoids the need for interlocking in all
+the rest of Rmail, since only Rmail operates on the Rmail file.
+@end enumerate
+
+ When getting new mail, Rmail first copies the new mail from the inbox
+file to the Rmail file; then it saves the Rmail file; then it deletes the
+inbox file. This way, a system crash may cause duplication of mail between
+the inbox and the Rmail file, but cannot lose mail.
+
+ Copying mail from an inbox in the system's mailer directory actually puts
+it in an intermediate file @file{~/.newmail}. This is because the
+interlocking is done by a C program that copies to another file.
+@file{~/.newmail} is deleted after mail merging is successful. If there is
+a crash at the wrong time, this file will continue to exist and will be
+used as an inbox the next time you get new mail.
+
+@node Rmail Files, Rmail Output, Rmail Inbox, Rmail
+@section Multiple Mail Files
+
+ Rmail operates by default on your @dfn{primary mail file}, which is named
+@file{~/RMAIL} and receives your incoming mail from your system inbox file.
+But you can also have other mail files and edit them with Rmail. These
+files can receive mail through their own inboxes, or you can move messages
+into them by explicit command in Rmail (@pxref{Rmail Output}).
+
+@table @kbd
+@item i @var{file} @key{RET}
+Read @var{file} into Emacs and run Rmail on it (@code{rmail-input}).
+
+@item M-x set-rmail-inbox-list @key{RET} @var{files} @key{RET}
+Specify inbox file names for current Rmail file to get mail from.
+
+@item g
+Merge new mail from current Rmail file's inboxes
+(@code{rmail-get-new-mail}).
+
+@item C-u g @var{file}
+Merge new mail from inbox file @var{file}.
+@end table
+
+@kindex i (Rmail)
+@findex rmail-input
+ To run Rmail on a file other than your primary mail file, you may use the
+@kbd{i} (@code{rmail-input}) command in Rmail. This visits the file, puts it in
+Rmail mode, and then gets new mail from the file's inboxes if any.
+You can also use @kbd{M-x rmail-input} even when not in Rmail.
+
+ The file you read with @kbd{i} does not have to be in Rmail file format.
+It could also be Unix mail format, or @code{mmdf} format; or it could
+be a mixture of all three, as long as each message belongs to one of
+the three formats. Rmail recognizes all three and converts all the
+messages to proper Rmail format before showing you the file.
+
+@findex set-rmail-inbox-list
+ Each Rmail file can contain a list of inbox file names; you can specify
+this list with @kbd{M-x set-rmail-inbox-list @key{RET} @var{files}
+@key{RET}}. The argument can contain any number of file names, separated
+by commas. It can also be empty, which specifies that this file should
+have no inboxes. Once a list of inboxes is specified, the Rmail file
+remembers it permanently until it is explicitly changed.@refill
+
+@kindex g (Rmail)
+@findex rmail-get-new-mail
+ If an Rmail file has inboxes, new mail is merged in from the inboxes when
+the Rmail file is brought into Rmail, and when the @kbd{g} (@code{rmail-get-new-mail})
+command is used. If the Rmail file specifies no inboxes, then no new mail
+is merged in at these times. A special exception is made for your primary
+mail file in using the standard system inbox for it if it does not specify
+any.
+
+ To merge mail from a file that is not the usual inbox, give the @kbd{g}
+key a numeric argument, as in @kbd{C-u g}. Then it reads a file name and
+merges mail from that file. The inbox file is not deleted or changed in
+any way when @kbd{g} with an argument is used. This is, therefore, a
+general way of merging one file of messages into another.
+
+@node Rmail Output, Rmail Labels, Rmail Files, Rmail
+@section Copying Messages Out to Files
+
+@table @kbd
+@item o @var{file} @key{RET}
+Append a copy of the current message to the file @var{file},
+writing it in Rmail file format (@code{rmail-output-to-rmail-file}).
+
+@item C-o @var{file} @key{RET}
+Append a copy of the current message to the file @var{file},
+writing it in Unix mail file format (@code{rmail-output}).
+@end table
+
+@kindex o (Rmail)
+@findex rmail-output-to-rmail-file
+@kindex C-o (Rmail)
+@findex rmail-output
+ If an Rmail file has no inboxes, how does it get anything in it? By
+explicit @kbd{o} commands.
+
+ @kbd{o} (@code{rmail-output-to-rmail-file}) appends the current message
+in Rmail format to the end of the specified file. This is the best command
+to use to move messages between Rmail files. If the other Rmail file is
+currently visited, the copying is done into the other file's Emacs buffer
+instead. You should eventually save it on disk.
+
+ The @kbd{C-o} (@code{rmail-output}) command in Rmail appends a copy of the current
+message to a specified file, in Unix mail file format. This is useful for
+moving messages into files to be read by other mail processors that do not
+understand Rmail format.
+
+ Copying a message with @kbd{o} or @kbd{C-o} gives the original copy of the
+message the @samp{filed} attribute, so that @samp{filed} appears in the mode
+line when such a message is current.
+
+ Normally you should use only @kbd{o} to output messages to other Rmail
+files, never @kbd{C-o}. But it is also safe if you always use @kbd{C-o},
+never @kbd{o}. When a file is visited in Rmail, the last message is
+checked, and if it is in Unix format, the entire file is scanned and all
+Unix-format messages are converted to Rmail format. (The reason for
+checking the last message is that scanning the file is slow and most Rmail
+files have only Rmail format messages.) If you use @kbd{C-o} consistently,
+the last message is sure to be in Unix format, so Rmail will convert all
+messages properly.
+
+ The case where you might want to use @kbd{C-o} always, instead of @kbd{o}
+always, is when you or other users want to append mail to the same file
+from other mail processors. Other mail processors probably do not know
+Rmail format but do know Unix format.
+
+ In any case, always use @kbd{o} to add to an Rmail file that is being
+visited in Rmail. Adding messages with @kbd{C-o} to the actual disk file
+will trigger a ``simultaneous editing'' warning when you ask to save the
+Emacs buffer, and will be lost if you do save.
+
+@node Rmail Labels, Rmail Summary, Rmail Output, Rmail
+@section Labels
+@cindex label (Rmail)
+@cindex attribute (Rmail)
+
+ Each message can have various @dfn{labels} assigned to it as a means of
+classification. A label has a name; different names mean different labels.
+Any given label is either present or absent on a particular message. A few
+label names have standard meanings and are given to messages automatically
+by Rmail when appropriate; these special labels are called @dfn{attributes}.
+All other labels are assigned by the user.
+
+@table @kbd
+@item a @var{label} @key{RET}
+Assign the label @var{label} to the current message (@code{rmail-add-label}).
+@item k @var{label} @key{RET}
+Remove the label @var{label} from the current message (@code{rmail-kill-label}).
+@item C-M-n @var{labels} @key{RET}
+Move to the next message that has one of the labels @var{labels}
+(@code{rmail-next-labeled-message}).
+@item C-M-p @var{labels} @key{RET}
+Move to the previous message that has one of the labels @var{labels}
+(@code{rmail-previous-labeled-message}).
+@item C-M-l @var{labels} @key{RET}
+Make a summary of all messages containing any of the labels @var{labels}
+(@code{rmail-summary-by-labels}).
+@end table
+
+@noindent
+Specifying an empty string for one these commands means to use the last
+label specified for any of these commands.
+
+@kindex a (Rmail)
+@kindex k (rmail)
+@findex rmail-add-label
+@findex rmail-kill-label
+ The @kbd{a} (@code{rmail-add-label}) and @kbd{k} (@code{rmail-kill-label}) commands allow
+you to assign or remove any label on the current message. If the @var{label}
+argument is empty, it means to assign or remove the same label most
+recently assigned or removed.
+
+ Once you have given messages labels to classify them as you wish, there
+are two ways to use the labels: in moving and in summaries.
+
+@kindex C-M-n (Rmail)
+@kindex C-M-p (Rmail)
+@findex rmail-next-labeled-message
+@findex rmail-previous-labeled-message
+ The command @kbd{C-M-n @var{labels} @key{RET}}
+(@code{rmail-next-labeled-message}) moves to the next message that has one
+of the labels @var{labels}. @var{labels} is one or more label names,
+separated by commas. @kbd{C-M-p} (@code{rmail-previous-labeled-message})
+is similar, but moves backwards to previous messages. A preceding numeric
+argument to either one serves as a repeat count.@refill
+
+@kindex C-M-l (Rmail)
+@findex rmail-summary-by-labels
+ The command @kbd{C-M-l @var{labels} @key{RET}}
+(@code{rmail-summary-by-labels}) displays a summary containing only the
+messages that have at least one of a specified set of messages. The
+argument @var{labels} is one or more label names, separated by commas.
+@xref{Rmail Summary}, for information on summaries.@refill
+
+ If the @var{labels} argument to @kbd{C-M-n}, @kbd{C-M-p} or @kbd{C-M-l} is empty, it means
+to use the last set of labels specified for any of these commands.
+
+ Some labels such as @samp{deleted} and @samp{filed} have built-in meanings and
+are assigned to or removed from messages automatically at appropriate
+times; these labels are called @dfn{attributes}. Here is a list of Rmail
+attributes:
+
+@table @samp
+@item unseen
+Means the message has never been current. Assigned to messages when
+they come from an inbox file, and removed when a message is made
+current.
+@item deleted
+Means the message is deleted. Assigned by deletion commands and
+removed by undeletion commands (@pxref{Rmail Deletion}).
+@item filed
+Means the message has been copied to some other file. Assigned by the
+file output commands (@pxref{Rmail Files}).
+@item answered
+Means you have mailed an answer to the message. Assigned by the @kbd{r}
+command (@code{rmail-reply}). @xref{Rmail Reply}.
+@item forwarded
+Means you have forwarded the message to other users. Assigned by the
+@kbd{f} command (@code{rmail-forward}). @xref{Rmail Reply}.
+@item edited
+Means you have edited the text of the message within Rmail.
+@xref{Rmail Editing}.
+@end table
+
+ All other labels are assigned or removed only by the user, and it is up
+to the user to decide what they mean.
+
+@node Rmail Summary, Rmail Reply, Rmail Labels, Rmail
+@section Summaries
+@cindex summary (Rmail)
+
+ A @dfn{summary} is a buffer containing one line per message that Rmail
+can make and display to give you an overview of the mail in an Rmail file.
+Each line shows the message number, the sender, the labels, and the
+subject. When the summary buffer is selected, various commands can be used
+to select messages by moving in the summary buffer, or delete or undelete
+messages.
+
+ A summary buffer applies to a single Rmail file only; if you are
+editing multiple Rmail files, they have separate summary buffers. The
+summary buffer name is made by appending @samp{-summary} to the Rmail buffer's
+name. Only one summary buffer will be displayed at a time unless you make
+several windows and select the summary buffers by hand.
+
+@menu
+* Rmail Make Summary:: Making various sorts of summaries.
+* Rmail Summary Edit:: Manipulating messages from the summary.
+@end menu
+
+@node Rmail Make Summary, Rmail Summary Edit, Rmail Summary, Rmail Summary
+@subsection Making Summaries
+
+ Here are the commands to create a summary for the current Rmail file.
+Summaries do not update automatically; to make an updated summary, you
+must use one of these commands again.
+
+@table @kbd
+@item h
+@itemx C-M-h
+Summarize all messages (@code{rmail-summary}).
+@item l @var{labels} @key{RET}
+@itemx C-M-l @var{labels} @key{RET}
+Summarize message that have one or more of the specified labels
+(@code{rmail-summary-by-labels}).
+@item C-M-r @var{rcpts} @key{RET}
+Summarize messages that have one or more of the specified recipients
+(@code{rmail-summary-by-recipients}).
+@end table
+
+@kindex h (Rmail)
+@findex rmail-summary
+ The @kbd{h} or @kbd{C-M-h} (@code{rmail-summary}) command fills the summary buffer
+for the current Rmail file with a summary of all the messages in the file.
+It then displays and selects the summary buffer in another window.
+
+@kindex l (Rmail)
+@kindex C-M-l (Rmail)
+@findex rmail-summary-by-labels
+ @kbd{C-M-l @var{labels} @key{RET}} (@code{rmail-summary-by-labels}) makes
+a partial summary mentioning only the messages that have one or more of the
+labels @var{labels}. @var{labels} should contain label names separated by
+commas.@refill
+
+@kindex C-M-r (Rmail)
+@findex rmail-summary-by-recipients
+ @kbd{C-M-r @var{rcpts} @key{RET}} (@code{rmail-summary-by-recipients})
+makes a partial summary mentioning only the messages that have one or more
+of the recipients @var{rcpts}. @var{rcpts} should contain mailing
+addresses separated by commas.@refill
+
+ Note that there is only one summary buffer for any Rmail file; making one
+kind of summary discards any previously made summary.
+
+@node Rmail Summary Edit,, Rmail Make Summary, Rmail Summary
+@subsection Editing in Summaries
+@cindex Rmail Summary mode
+@cindex summaries in Rmail
+
+ Summary buffers are given the major mode Rmail Summary mode, which
+provides the following special commands:
+
+@table @kbd
+@item j
+Select the message described by the line that point is on
+(@code{rmail-summary-goto-msg}).
+@item C-n
+Move to next line and select its message in Rmail
+(@code{rmail-summary-next-all}).
+@item C-p
+Move to previous line and select its message
+(@code{rmail-summary-previous-all}).
+@item n
+Move to next line, skipping lines saying `deleted', and select its
+message (@code{rmail-summary-next-msg}).
+@item p
+Move to previous line, skipping lines saying `deleted', and select
+its message (@code{rmail-summary-previous-msg}).
+@c !!! following generates acceptable underfull hbox
+@item d
+Delete the current line's message, then do like @kbd{n}
+(@code{rmail-summary-delete-forward}).
+@item u
+Undelete and select this message or the previous deleted message in
+the summary (@code{rmail-summary-undelete}).
+@item @key{SPC}
+Scroll the other window (presumably Rmail) forward
+(@code{rmail-summary-scroll-msg-up}).
+@item @key{DEL}
+Scroll the other window backward (@code{rmail-summary-scroll-msg-down}).
+@item x
+Kill the summary window (@code{rmail-summary-exit}).
+@item q
+Exit Rmail (@code{rmail-summary-quit}).
+@end table
+
+@kindex C-n (Rmail summary)
+@kindex C-p (Rmail summary)
+@findex rmail-summary-next-all
+@findex rmail-summary-previous-all
+ The keys @kbd{C-n} and @kbd{C-p} are modified in Rmail Summary mode so that in
+addition to moving point in the summary buffer they also cause the line's
+message to become current in the associated Rmail buffer. That buffer is
+also made visible in another window if it is not already so.
+
+@kindex n (Rmail summary)
+@kindex p (Rmail summary)
+@findex rmail-summary-next-msg
+@findex rmail-summary-previous-msg
+ @kbd{n} and @kbd{p} are similar to @kbd{C-n} and @kbd{C-p}, but skip
+lines that say `message deleted'. They are like the @kbd{n} and @kbd{p}
+keys of Rmail itself. Note, however, that in a partial summary these
+commands move only among the message listed in the summary.@refill
+
+@kindex j (Rmail summary)
+@findex rmail-summary-goto-msg
+ The other Emacs cursor motion commands are not changed in Rmail Summary
+mode, so it is easy to get the point on a line whose message is not
+selected in Rmail. This can also happen if you switch to the Rmail window
+and switch messages there. To get the Rmail buffer back in sync with the
+summary, use the @kbd{j} (@code{rmail-summary-goto-msg}) command, which selects
+in Rmail the message of the current summary line.
+
+@kindex d (Rmail summary)
+@kindex u (Rmail summary)
+@findex rmail-summary-delete-forward
+@findex rmail-summary-undelete
+ Deletion and undeletion can also be done from the summary buffer. They
+always work based on where point is located in the summary buffer, ignoring
+which message is selected in Rmail. @kbd{d} (@code{rmail-summary-delete-forward})
+deletes the current line's message, then moves to the next line whose
+message is not deleted and selects that message. The inverse of this is
+@kbd{u} (@code{rmail-summary-undelete}), which moves back (if necessary) to a line
+whose message is deleted, undeletes that message, and selects it in Rmail.
+
+@kindex SPC (Rmail summary)
+@kindex DEL (Rmail summary)
+@findex rmail-summary-scroll-msg-down
+@findex rmail-summary-scroll-msg-up
+ When moving through messages with the summary buffer, it is convenient to
+be able to scroll the message while remaining in the summary window.
+The commands @key{SPC} (@code{rmail-summary-scroll-msg-up}) and @key{DEL}
+(@code{rmail-summary-scroll-msg-down}) do this. They scroll the message just
+as those same keys do when the Rmail buffer is selected.@refill
+
+@kindex x (Rmail summary)
+@findex rmail-summary-exit
+ When you are finished using the summary, type @kbd{x} (@code{rmail-summary-exit})
+to kill the summary buffer's window.
+
+@kindex q (Rmail summary)
+@findex rmail-summary-quit
+ You can also exit Rmail while in the summary. @kbd{q} (@code{rmail-summary-quit})
+kills the summary window, then saves the Rmail file and switches to another
+buffer.
+
+@node Rmail Reply, Rmail Editing, Rmail Summary, Rmail
+@section Sending Replies
+
+ Rmail has several commands that use Mail mode to send outgoing mail.
+@xref{Sending Mail}, for information on using Mail mode. What are
+documented here are the special commands of Rmail for entering Mail mode.
+Note that the usual keys for sending mail, @kbd{C-x m} and @kbd{C-x 4 m},
+are available in Rmail mode and work just as they usually do.@refill
+
+@table @kbd
+@item m
+Send a message (@code{rmail-mail}).
+@c !!! following generates acceptable underfull hbox
+@item c
+Continue editing already started outgoing message (@code{rmail-continue}).
+@item r
+Send a reply to the current Rmail message (@code{rmail-reply}).
+@item f
+Forward current message to other users (@code{rmail-forward}).
+@end table
+
+@kindex r (Rmail)
+@findex rmail-reply
+@vindex rmail-dont-reply-to
+@cindex reply to a message
+ The most common reason to send a message while in Rmail is to reply to
+the message you are reading. To do this, type @kbd{r}
+(@code{rmail-reply}). This displays the @samp{*mail*} buffer in another
+window, much like @kbd{C-x 4 m}, but preinitializes the @samp{Subject},
+@samp{To}, @samp{CC} and @samp{In-reply-to} header fields based on the
+message being replied to. The @samp{To} field is given the sender of that
+message, and the @samp{CC} gets all the recipients of that message (but
+recipients that match elements of the list @code{rmail-dont-reply-to} are
+omitted; by default, this list contains your own mailing address).@refill
+
+ If you don't want to include the other recipients in the @samp{cc} field,
+you can use a prefix argument to the @kbd{r} command. In Rmail, you can
+do this with @w{@kbd{1 r}}.
+
+ Once you have initialized the @samp{*mail*} buffer this way, sending the
+mail goes as usual (@pxref{Sending Mail}). You can edit the presupplied
+header fields if they are not right for you.
+
+@kindex C-c C-y (Mail mode)
+@findex mail-yank-original
+ One additional Mail mode command is available when mailing is invoked
+from Rmail: @kbd{C-c C-y} (@code{mail-yank-original}) inserts into the outgoing
+message a copy of the current Rmail message; normally this is the message
+you are replying to, but you can also switch to the Rmail buffer, select a
+different message, switch back, and yank new current message. Normally the
+yanked message is indented four spaces and has most header fields deleted
+from it; an argument to @kbd{C-c C-y} specifies the amount to indent, and
+@kbd{C-u C-c C-y} does not indent at all and does not delete any header
+fields.@refill
+
+@kindex f (Rmail)
+@findex rmail-forward
+@cindex forward a message
+ Another frequent reason to send mail in Rmail is to forward the current
+message to other users. @kbd{f} (@code{rmail-forward}) makes this easy by
+preinitializing the @samp{*mail*} buffer with the current message as the
+text, and a subject designating a forwarded message. All you have to do is
+fill in the recipients and send.@refill
+
+@kindex m (Rmail)
+@findex rmail-mail
+ The @kbd{m} (@code{rmail-mail}) command is used to start editing an
+outgoing message that is not a reply. It leaves the header fields empty.
+Its only difference from @kbd{C-x 4 m} is that it makes the Rmail buffer
+accessible for @kbd{C-c y}, just as @kbd{r} does. Thus, @kbd{m} can be
+used to reply to or forward a message; it can do anything @kbd{r} or @kbd{f}
+can do.@refill
+
+@kindex c (Rmail)
+@findex rmail-continue
+ The @kbd{c} (@code{rmail-continue}) command resumes editing the
+@samp{*mail*} buffer, to finish editing an outgoing message you were
+already composing, or to alter a message you have sent.@refill
+
+@node Rmail Editing, Rmail Digest, Rmail Reply, Rmail
+@section Editing Within a Message
+
+ Rmail mode provides a few special commands for moving within and editing
+the current message. In addition, the usual Emacs commands are available
+(except for a few, such as @kbd{C-M-n} and @kbd{C-M-h}, that are redefined by Rmail for
+other purposes). However, the Rmail buffer is normally read-only, and to
+alter it you must use the Rmail command @kbd{w} described below.
+
+@table @kbd
+@item t
+Toggle display of original headers (@code{rmail-toggle-headers}).
+@item w
+Edit current message (@code{rmail-edit-current-message}).
+@end table
+
+@kindex t (Rmail)
+@findex rmail-toggle-header
+@vindex rmail-ignored-headers
+ Rmail reformats the header of each message before displaying it.
+Normally this involves deleting most header fields, on the grounds that
+they are not interesting. The variable @code{rmail-ignored-headers} should
+contain a regexp that matches the header fields to discard in this way.
+The original headers are saved permanently, and to see what they look like,
+use the @kbd{t} (@code{rmail-toggle-headers}) command. This discards the reformatted
+headers of the current message and displays it with the original headers.
+Repeating @kbd{t} reformats the message again. Selecting the message again
+also reformats.
+
+@kindex w (Rmail)
+@findex rmail-edit-current-message
+ The Rmail buffer is normally read-only, and most of the characters you
+would type to modify it (including most letters) are redefined as Rmail
+commands. This is usually not a problem since it is rare to want to change
+the text of a message. When you do want to do this, the way is to type
+@kbd{w} (@code{rmail-edit-current-message}), which changes from Rmail mode into
+Rmail Edit mode, another major mode which is nearly the same as Text mode.
+The mode line illustrates this change.
+
+ In Rmail Edit mode, letters insert themselves as usual and the Rmail
+commands are not available. When you are finished editing the message and
+are ready to go back to Rmail, type @kbd{C-c C-c}, which switches back to
+Rmail mode. Alternatively, you can return to Rmail mode but cancel all the
+editing that you have done by typing @kbd{C-c C-]}.
+
+@vindex rmail-edit-mode-hook
+ Entering Rmail Edit mode calls with no arguments the value of the variable
+@code{text-mode-hook}, if that value exists and is not @code{nil}; then it
+does the same with the variable @code{rmail-edit-mode-hook}. It adds the
+attribute @samp{edited} to the message.
+
+@node Rmail Digest,, Rmail Editing, Rmail
+@section Digest Messages
+@cindex digest message
+@cindex undigestify
+
+ A @dfn{digest message} is a message which exists to contain and carry
+several other messages. Digests are used on moderated mailing lists; all
+the messages that arrive for the list during a period of time such as one
+day are put inside a single digest which is then sent to the subscribers.
+Transmitting the single digest uses much less computer time than
+transmitting the individual messages even though the total size is the
+same, because the per-message overhead in network mail transmission is
+considerable.
+
+@findex undigestify-rmail-message
+ When you receive a digest message, the most convenient way to read it is
+to @dfn{undigestify} it: to turn it back into many individual messages.
+Then you can read and delete the individual messages as it suits you.
+
+ To undigestify a message, select it and then type @kbd{M-x
+undigestify-rmail-message}. This copies each submessage as a separate
+Rmail message and inserts them all following the digest. The digest
+message itself is flagged as deleted.
+
+@iftex
+@chapter Miscellaneous Commands
+
+ This chapter contains several brief topics that do not fit anywhere else.
+
+@end iftex
+@node Recursive Edit, Narrowing, Rmail, Top
+@section Recursive Editing Levels
+@cindex recursive editing level
+@cindex editing level, recursive
+
+ A @dfn{recursive edit} is a situation in which you are using Emacs
+commands to perform arbitrary editing while in the middle of another Emacs
+command. For example, when you type @kbd{C-r} inside of a @code{query-replace},
+you enter a recursive edit in which you can change the current buffer. On
+exiting from the recursive edit, you go back to the @code{query-replace}.
+
+@kindex C-M-c
+@findex exit-recursive-edit
+@cindex exiting
+ @dfn{Exiting} the recursive edit means returning to the unfinished
+command, which continues execution. For example, exiting the recursive
+edit requested by @kbd{C-r} in @code{query-replace} causes query replacing
+to resume. Exiting is done with @kbd{C-M-c} (@code{exit-recursive-edit}).
+
+@kindex C-]
+@findex abort-recursive-edit
+ You can also @dfn{abort} the recursive edit. This is like exiting, but
+also quits the unfinished command immediately. Use the command @kbd{C-]}
+(@code{abort-recursive-edit}) for this. @xref{Quitting}.
+
+ The mode line shows you when you are in a recursive edit by displaying
+square brackets around the parentheses that always surround the major and
+minor mode names. Every window's mode line shows this, in the same way,
+since being in a recursive edit is true of Emacs as a whole rather than
+any particular buffer.
+
+@findex top-level
+ It is possible to be in recursive edits within recursive edits. For
+example, after typing @kbd{C-r} in a @code{query-replace}, you might type a
+command that entered the debugger. In such circumstances, two or more sets
+of square brackets appear in the mode line. Exiting the inner recursive
+edit (such as, with the debugger @kbd{c} command) would resume the command
+where it called the debugger. After the end of this command, you would be
+able to exit the first recursive edit. Aborting also gets out of only one
+level of recursive edit; it returns immediately to the command level of the
+previous recursive edit. So you could immediately abort that one too.
+
+ Alternatively, the command @kbd{M-x top-level} aborts all levels of
+recursive edits, returning immediately to the top level command reader.
+
+ The text being edited inside the recursive edit need not be the same text
+that you were editing at top level. It depends on what the recursive edit
+is for. If the command that invokes the recursive edit selects a different
+buffer first, that is the buffer you will edit recursively. In any case,
+you can switch buffers within the recursive edit in the normal manner (as
+long as the buffer-switching keys have not been rebound). You could
+probably do all the rest of your editing inside the recursive edit,
+visiting files and all. But this could have surprising effects (such as
+stack overflow) from time to time. So remember to exit or abort the
+recursive edit when you no longer need it.
+
+ In general, GNU Emacs tries to avoid using recursive edits. It is
+usually preferable to allow the user to switch among the possible editing
+modes in any order he likes. With recursive edits, the only way to get to
+another state is to go ``back'' to the state that the recursive edit was
+invoked from.
+
+@node Narrowing, Sorting, Recursive Edit, Top
+@section Narrowing
+@cindex widening
+@cindex restriction
+@cindex narrowing
+
+ @dfn{Narrowing} means focusing in on some portion of the buffer, making
+the rest temporarily invisible and inaccessible. Cancelling the narrowing,
+and making the entire buffer once again visible, is called @dfn{widening}.
+The amount of narrowing in effect in a buffer at any time is called the
+buffer's @dfn{restriction}.
+
+@c WideCommands
+@table @kbd
+@item C-x n
+Narrow down to between point and mark (@code{narrow-to-region}).
+@item C-x w
+Widen to make the entire buffer visible again (@code{widen}).
+@end table
+
+ When you have narrowed down to a part of the buffer, that part appears to
+be all there is. You can't see the rest, you can't move into it (motion
+commands won't go outside the visible part), you can't change it in any
+way. However, it is not gone, and if you save the file all the invisible
+text will be saved. In addition to sometimes making it easier to
+concentrate on a single subroutine or paragraph by eliminating clutter,
+narrowing can be used to restrict the range of operation of a replace
+command or repeating keyboard macro. The word @samp{Narrow} appears in the
+mode line whenever narrowing is in effect.
+
+@kindex C-x n
+@findex narrow-to-region
+ The primary narrowing command is @kbd{C-x n} (@code{narrow-to-region}).
+It sets the current buffer's restrictions so that the text in the current
+region remains visible but all text before the region or after the region
+is invisible. Point and mark do not change.
+
+ Because narrowing can easily confuse users who do not understand it,
+@code{narrow-to-region} is normally a disabled command. Attempting to use
+this command asks for confirmation and gives you the option of enabling it;
+once you enable the command, confirmation will no longer be required for
+it. @xref{Disabling}.
+
+@kindex C-x w
+@findex widen
+ The way to undo narrowing is to widen with @kbd{C-x w} (@code{widen}).
+This makes all text in the buffer accessible again.
+
+ You can get information on what part of the buffer you are narrowed down
+to using the @kbd{C-x =} command. @xref{Position Info}.
+
+@node Sorting, Shell, Narrowing, Top
+@section Sorting Text
+@cindex sorting
+
+ Emacs provides several commands for sorting text in the buffer. All
+operate on the contents of the region (the text between point and the
+mark). They divide the text of the region into many @dfn{sort records},
+identify a @dfn{sort key} for each record, and then reorder the records
+into the order determined by the sort keys. The records are ordered so
+that their keys are in alphabetical order, or, for numeric sorting, in
+numeric order. In alphabetic sorting, all upper case letters `A' through
+`Z' come before lower case `a', in accord with the @sc{ascii} character
+sequence.
+
+ The various sort commands differ in how they divide the text into sort
+records and in which part of each record is used as the sort key. Most of
+the commands make each line a separate sort record, but some commands use
+paragraphs or pages as sort records. Most of the sort commands use each
+entire sort record as its own sort key, but some use only a portion of the
+record as the sort key.
+
+@findex sort-lines
+@findex sort-paragraphs
+@findex sort-pages
+@findex sort-fields
+@findex sort-numeric-fields
+@table @kbd
+@item M-x sort-lines
+Divide the region into lines, and sort by comparing the entire
+text of a line. A prefix argument means sort into descending order.
+
+@item M-x sort-paragraphs
+Divide the region into paragraphs, and sort by comparing the entire
+text of a paragraph (except for leading blank lines). A prefix
+argument means sort into descending order.
+
+@item M-x sort-pages
+Divide the region into pages, and sort by comparing the entire
+text of a page (except for leading blank lines). A prefix
+argument means sort into descending order.
+
+@item M-x sort-fields
+Divide the region into lines, and sort by comparing the contents of
+one field in each line. Fields are defined as separated by
+whitespace, so the first run of consecutive non-whitespace characters
+in a line constitutes field 1, the second such run constitutes field
+2, etc.
+
+You specify which field to sort by with a numeric argument: 1 to sort
+by field 1, etc. A negative argument means sort into descending
+order. Thus, minus 2 means sort by field 2 in reverse-alphabetical
+order.
+
+If two lines are equal in the field being compared, their relative order
+in the text is not changed. This enables you to sort by multiple keys:
+sort first by the least significant key, then by the next-to-least
+key, and so on, ending with the most important key.
+
+@item M-x sort-numeric-fields
+Like @kbd{M-x sort-fields} except the specified field is converted
+to a number for each line, and the numbers are compared. @samp{10}
+comes before @samp{2} when considered as text, but after it when
+considered as a number.
+
+@item M-x sort-columns
+Like @kbd{M-x sort-fields} except that the text within each line
+used for comparison comes from a fixed range of columns. See below
+for an explanation.
+@end table
+
+For example, if the buffer contains
+
+@smallexample
+On systems where clash detection (locking of files being edited) is
+implemented, Emacs also checks the first time you modify a buffer
+whether the file has changed on disk since it was last visited or
+saved. If it has, you are asked to confirm that you want to change
+the buffer.
+@end smallexample
+
+@noindent
+then if you apply @kbd{M-x sort-lines} to the entire buffer you get
+
+@smallexample
+On systems where clash detection (locking of files being edited) is
+implemented, Emacs also checks the first time you modify a buffer
+saved. If it has, you are asked to confirm that you want to change
+the buffer.
+whether the file has changed on disk since it was last visited or
+@end smallexample
+
+@noindent
+where the upper case `O' comes before all lower case letters. If you apply
+instead @kbd{C-u 2 M-x sort-fields} you get
+
+@smallexample
+implemented, Emacs also checks the first time you modify a buffer
+saved. If it has, you are asked to confirm that you want to change
+the buffer.
+On systems where clash detection (locking of files being edited) is
+whether the file has changed on disk since it was last visited or
+@end smallexample
+
+@noindent
+where the sort keys were @samp{Emacs}, @samp{If}, @samp{buffer},
+@samp{systems} and @samp{the}.@refill
+
+@findex sort-columns
+ @kbd{M-x sort-columns} requires more explanation. You specify the
+columns by putting point at one of the columns and the mark at the other
+column. Because this means you cannot put point or the mark at the
+beginning of the first line to sort, this command uses an unusual
+definition of `region': all of the line point is in is considered part of
+the region, and so is all of the line the mark is in.
+
+ For example, to sort a table by information found in columns 10 to 15,
+you could put the mark on column 10 in the first line of the table, and
+point on column 15 in the last line of the table, and then use this command.
+Or you could put the mark on column 15 in the first line and point on
+column 10 in the last line.
+
+ This can be thought of as sorting the rectangle specified by point and
+the mark, except that the text on each line to the left or right of the
+rectangle moves along with the text inside the rectangle.
+@xref{Rectangles}.
+
+@node Shell, Hardcopy, Sorting, Top
+@section Running Shell Commands from Emacs
+@cindex subshell
+@cindex shell commands
+
+ Emacs has commands for passing single command lines to inferior shell
+processes; it can also run a shell interactively with input and output to
+an Emacs buffer @samp{*shell*}.
+
+@table @kbd
+@item M-!
+Run a specified shell command line and display the output
+(@code{shell-command}).
+@item M-|
+Run a specified shell command line with region contents as input;
+optionally replace the region with the output
+(@code{shell-command-on-region}).
+@item M-x shell
+Run a subshell with input and output through an Emacs buffer.
+You can then give commands interactively.
+@end table
+
+@menu
+* Single Shell:: How to run one shell command and return.
+* Interactive Shell:: Permanent shell taking input via Emacs.
+* Shell Mode:: Special Emacs commands used with permanent shell.
+@end menu
+
+@node Single Shell, Interactive Shell, Shell, Shell
+@subsection Single Shell Commands
+
+@kindex M-!
+@findex shell-command
+ @kbd{M-!} (@code{shell-command}) reads a line of text using the
+minibuffer and creates an inferior shell to execute the line as a command.
+Standard input from the command comes from the null device. If the shell
+command produces any output, the output goes into an Emacs buffer named
+@samp{*Shell Command Output*}, which is displayed in another window but not
+selected. A numeric argument, as in @kbd{M-1 M-!}, directs this command to
+insert any output into the current buffer. In that case, point is left
+before the output and the mark is set after the output.
+
+@kindex M-|
+@findex shell-command-on-region
+ @kbd{M-|} (@code{shell-command-on-region}) is like @kbd{M-!} but passes
+the contents of the region as input to the shell command, instead of no
+input. If a numeric argument is used, meaning insert output in the current
+buffer, then the old region is deleted first and the output replaces it as
+the contents of the region.@refill
+
+@vindex shell-file-name
+@cindex environment
+ Both @kbd{M-!} and @kbd{M-|} use @code{shell-file-name} to specify the
+shell to use. This variable is initialized based on your @code{SHELL}
+environment variable when Emacs is started. If the file name does not
+specify a directory, the directories in the list @code{exec-path} are
+searched; this list is initialized based on the environment variable
+@code{PATH} when Emacs is started. Your @file{.emacs} file can override
+either or both of these default initializations.@refill
+
+ With @kbd{M-!} and @kbd{M-|}, Emacs has to wait until the shell command
+completes. You can quit with @kbd{C-g}; that terminates the shell command.
+
+@node Interactive Shell, Shell Mode, Single Shell, Shell
+@subsection Interactive Inferior Shell
+
+@findex shell
+ To run a subshell interactively, putting its typescript in an Emacs
+buffer, use @kbd{M-x shell}. This creates (or reuses) a buffer named
+@samp{*shell*} and runs a subshell with input coming from and output going
+to that buffer. That is to say, any ``terminal output'' from the subshell
+will go into the buffer, advancing point, and any ``terminal input'' for
+the subshell comes from text in the buffer. To give input to the subshell,
+go to the end of the buffer and type the input, terminated by @key{RET}.
+
+ Emacs does not wait for the subshell to do anything. You can switch
+windows or buffers and edit them while the shell is waiting, or while it is
+running a command. Output from the subshell waits until Emacs has time to
+process it; this happens whenever Emacs is waiting for keyboard input or
+for time to elapse.
+
+ If you would like multiple subshells, change the name of buffer
+@samp{*shell*} to something different by using @kbd{M-x rename-buffer}. The
+next use of @kbd{M-x shell} will create a new buffer @samp{*shell*} with
+its own subshell. By renaming this buffer as well you can create a third
+one, and so on. All the subshells run independently and in parallel.
+
+@vindex explicit-shell-file-name
+ The file name used to load the subshell is the value of the variable
+@code{explicit-shell-file-name}, if that is non-@code{nil}. Otherwise, the
+environment variable @code{ESHELL} is used, or the environment variable
+@code{SHELL} if there is no @code{ESHELL}. If the file name specified
+is relative, the directories in the list @code{exec-path} are searched
+(@pxref{Single Shell,Single Shell Commands}).@refill
+
+ As soon as the subshell is started, it is sent as input the contents of
+the file @file{~/.emacs_@var{shellname}}, if that file exists, where
+@var{shellname} is the name of the file that the shell was loaded
+from. For example, if you use @code{csh}, the file sent to it is
+@file{~/.emacs_csh}; if you use the Bourne-Again shell, the file sent
+to it is @file{~/.emacs_bash}.@refill
+
+@vindex shell-pushd-regexp
+@vindex shell-popd-regexp
+@vindex shell-cd-regexp
+ @code{cd}, @code{pushd} and @code{popd} commands given to the inferior
+shell are watched by Emacs so it can keep the @samp{*shell*} buffer's
+default directory the same as the shell's working directory. These
+commands are recognized syntactically by examining lines of input that are
+sent. If you use aliases for these commands, you can tell Emacs to
+recognize them also. For example, if the value of the variable
+@code{shell-pushd-regexp} matches the beginning of a shell command line,
+that line is regarded as a @code{pushd} command. Change this variable when
+you add aliases for @samp{pushd}. Likewise, @code{shell-popd-regexp} and
+@code{shell-cd-regexp} are used to recognize commands with the meaning of
+@samp{popd} and @samp{cd}. These commands are recognized only at the
+beginning of a shell command line.@refill
+
+@vindex shell-set-directory-error-hook
+ If Emacs gets an error while trying to handle what it believes is
+a @samp{cd}, @samp{pushd} or @samp{popd} command, and the value of
+@code{shell-set-directory-error-hook} is non-@code{nil}, that value is
+called as a function with no arguments.@refill
+
+@node Shell Mode,, Interactive Shell, Shell
+@subsection Shell Mode
+
+@cindex Shell mode
+ The shell buffer uses Shell mode, which defines several special keys
+attached to the @kbd{C-c} prefix. They are chosen to resemble the usual
+editing and job control characters present in shells that are not under
+Emacs, except that you must type @kbd{C-c} first. Here is a complete list
+of the special key bindings of Shell mode:
+
+@kindex RET (Shell mode)
+@kindex C-c C-d (Shell mode)
+@kindex C-c C-u (Shell mode)
+@kindex C-c C-w (Shell mode)
+@kindex C-c C-c (Shell mode)
+@kindex C-c C-z (Shell mode)
+@kindex C-c C-\ (Shell mode)
+@kindex C-c C-o (Shell mode)
+@kindex C-c C-r (Shell mode)
+@kindex C-c C-y (Shell mode)
+@findex send-shell-input
+@findex shell-send-eof
+@findex interrupt-shell-subjob
+@findex stop-shell-subjob
+@findex quit-shell-subjob
+@findex kill-output-from-shell
+@findex show-output-from-shell
+@findex copy-last-shell-input
+@vindex shell-prompt-pattern
+@table @kbd
+@item @key{RET}
+At end of buffer, send line as input; otherwise, copy current line to end of
+buffer and send it (@code{send-shell-input}). When a line is copied, any
+text at the beginning of the line that matches the variable
+@code{shell-prompt-pattern} is left out; this variable's value should be a
+regexp string that matches the prompts that you use in your subshell.
+@item C-c C-d
+Send end-of-file as input, probably causing the shell or its current
+subjob to finish (@code{shell-send-eof}).
+@item C-c C-u
+Kill all text that has yet to be sent as input (@code{kill-shell-input}).
+@item C-c C-w
+Kill a word before point (@code{backward-kill-word}).
+@item C-c C-c
+Interrupt the shell or its current subjob if any
+(@code{interrupt-shell-subjob}).
+@item C-c C-z
+Stop the shell or its current subjob if any (@code{stop-shell-subjob}).
+@item C-c C-\
+Send quit signal to the shell or its current subjob if any
+(@code{quit-shell-subjob}).
+@item C-c C-o
+Delete last batch of output from shell (@code{kill-output-from-shell}).
+@item C-c C-r
+Scroll top of last batch of output to top of window
+(@code{show-output-from-shell}).
+@item C-c C-y
+Copy the previous bunch of shell input, and insert it into the
+buffer before point (@code{copy-last-shell-input}). No final newline
+is inserted, and the input copied is not resubmitted until you type
+@key{RET}.
+@end table
+
+@node Hardcopy, Dissociated Press, Shell, Top
+@section Hardcopy Output
+@cindex hardcopy
+
+ The Emacs commands for making hardcopy derive their names from the
+Unix commands @samp{print} and @samp{lpr}.
+
+@table @kbd
+@item M-x print-buffer
+Print hardcopy of current buffer using Unix command @samp{print}
+(@samp{lpr -p}). This makes page headings containing the file name
+and page number.
+@item M-x lpr-buffer
+Print hardcopy of current buffer using Unix command @samp{lpr}.
+This makes no page headings.
+@item M-x print-region
+Like @code{print-buffer} but prints only the current region.
+@item M-x lpr-region
+Like @code{lpr-buffer} but prints only the current region.
+@end table
+
+@findex print-buffer
+@findex print-region
+@findex lpr-buffer
+@findex lpr-region
+@vindex lpr-switches
+@vindex lpr-command
+ All the hardcopy commands pass extra switches to the @code{lpr}
+program based on the value of the variable @code{lpr-switches}. Its
+value should be a list of strings, each string a switch starting with
+@samp{-}. For example, the value could be @w{@code{("-Pfoo")}} to print on
+printer @samp{foo}. You can specify an alternative command to run
+instead of @code{lpr} by setting the variable @code{lpr-command}.
+
+@node Dissociated Press, Amusements, Hardcopy, Top
+@section Dissociated Press
+
+@findex dissociated-press
+ @kbd{M-x dissociated-press} is a command for scrambling a file of text
+either word by word or character by character. Starting from a buffer of
+straight English, it produces extremely amusing output. The input comes
+from the current Emacs buffer. Dissociated Press writes its output in a
+buffer named @samp{*Dissociation*}, and redisplays that buffer after every
+couple of lines (approximately) to facilitate reading it.
+
+ @code{dissociated-press} asks every so often whether to continue
+operating. Answer @kbd{n} to stop it. You can also stop at any time by
+typing @kbd{C-g}. The dissociation output remains in the @samp{*Dissociation*}
+buffer for you to copy elsewhere if you wish.
+
+@cindex presidentagon
+ Dissociated Press operates by jumping at random from one point in the
+buffer to another. In order to produce plausible output rather than
+gibberish, it insists on a certain amount of overlap between the end of one
+run of consecutive words or characters and the start of the next. That is,
+if it has just printed out `president' and then decides to jump to a
+different point in the file, it might spot the `ent' in `pentagon' and
+continue from there, producing `presidentagon'. Long sample texts produce
+the best results.
+
+@cindex againformation
+ A positive argument to @kbd{M-x dissociated-press} tells it to operate
+character by character, and specifies the number of overlap characters. A
+negative argument tells it to operate word by word and specifies the number
+of overlap words. In this mode, whole words are treated as the elements to
+be permuted, rather than characters. No argument is equivalent to an
+argument of two. For your againformation, the output goes only into the
+buffer @samp{*Dissociation*}. The buffer you start with is not changed.
+
+@cindex Markov chain
+@cindex ignoriginal
+@cindex techniquitous
+ Dissociated Press produces nearly the same results as a Markov chain
+based on a frequency table constructed from the sample text. It is,
+however, an independent, ignoriginal invention. Dissociated Press
+techniquitously copies several consecutive characters from the sample
+between random choices, whereas a Markov chain would choose randomly for
+each word or character. This makes for more plausible sounding results,
+and runs faster.
+
+@cindex outragedy
+@cindex buggestion
+@cindex properbose
+ It is a mustatement that too much use of Dissociated Press can be a
+developediment to your real work. Sometimes to the point of outragedy.
+And keep dissociwords out of your documentation, if you want it to be well
+userenced and properbose. Have fun. Your buggestions are welcome.
+
+@node Amusements, Emulation, Dissociated Press, Top
+@section Other Amusements
+@cindex boredom
+@findex hanoi
+@findex yow
+
+ If you are a little bit bored, you can try @kbd{M-x hanoi}. If you are
+considerably bored, give it a numeric argument. If you are very very
+bored, try an argument of 9. Sit back and watch.
+
+ When you are frustrated, try the famous Eliza program. Just do
+@kbd{M-x doctor}. End each input by typing @kbd{RET} twice.
+
+ When you are feeling strange, type @kbd{M-x yow}.
+
+@node Emulation, Customization, Amusements, Top
+@section Emulation
+@cindex other editors
+@cindex EDT
+@cindex vi
+
+ GNU Emacs can be programmed to emulate (more or less) most other
+editors. Standard facilities can emulate these:
+
+@table @asis
+@item EDT (DEC VMS editor)
+@findex edt-emulation-on
+@findex edt-emulation-off
+Turn on EDT emulation with @kbd{M-x edt-emulation-on}. @kbd{M-x
+edt-emulation-off} restores normal Emacs command bindings.
+
+Most of the EDT emulation commands are keypad keys, and most standard
+Emacs key bindings are still available. The EDT emulation rebindings
+are done in the global keymap, so there is no problem switching
+buffers or major modes while in EDT emulation.
+
+@item Gosling Emacs
+@findex set-gosmacs-bindings
+@findex set-gnu-bindings
+Turn on emulation of Gosling Emacs (aka Unipress Emacs) with @kbd{M-x
+set-gosmacs-bindings}. This redefines many keys, mostly on the
+@kbd{C-x} and @kbd{ESC} prefixes, to work as they do in Gosmacs.
+@kbd{M-x set-gnu-bindings} returns to normal GNU Emacs by rebinding
+the same keys to the definitions they had at the time @kbd{M-x
+set-gosmacs-bindings} was done.
+
+It is also possible to run Mocklisp code written for Gosling Emacs.
+@xref{Mocklisp}.
+
+@item vi (Berkeley Unix editor)
+@findex vi-mode
+@cindex VI mode
+Turn on vi emulation with @kbd{M-x vi-mode}. This is a major mode
+that replaces the previously established major mode. All of the
+vi commands that, in real vi, enter ``input'' mode are programmed
+in the Emacs emulator to return to the previous major mode. Thus,
+ordinary Emacs serves as vi's ``input'' mode.
+
+Because vi emulation works through major modes, it does not work
+to switch buffers during emulation. Return to normal Emacs first.
+
+If you plan to use vi emulation much, you probably want to bind a key
+to the @code{vi-mode} command.
+
+@item vi (alternate emulator)
+@findex vip-mode
+Another vi emulator said to resemble real vi more thoroughly is
+invoked by @kbd{M-x vip-mode}. ``Input'' mode in this emulator is
+changed from ordinary Emacs so you can use @key{ESC} to go back to
+emulated vi command mode. To get from emulated vi command mode back
+to ordinary Emacs, type @kbd{C-z}.
+
+This emulation does not work through major modes, and it is possible
+to switch buffers in various ways within the emulator. It is not
+so necessary to assign a key to the command @code{vip-mode} as
+it is with @code{vi-mode} because terminating insert mode does
+not use it.
+
+For full information, see the long comment at the beginning of the
+source file, which is @file{lisp/vip.el} in the Emacs distribution.
+@end table
+
+I am interested in hearing which vi emulator users prefer, as well as in
+receiving more complete user documentation for either or both emulators.
+Warning: loading both at once may cause name conficts; no one has checked.
+
+@node Customization, Quitting, Emulation, Top
+@chapter Customization
+@cindex customization
+
+ This chapter talks about various topics relevant to adapting the
+behavior of Emacs in minor ways.
+
+ All kinds of customization affect only the particular Emacs job that you
+do them in. They are completely lost when you kill the Emacs job, and have
+no effect on other Emacs jobs you may run at the same time or later. The
+only way an Emacs job can affect anything outside of it is by writing a
+file; in particular, the only way to make a customization `permanent' is to
+put something in your @file{.emacs} file or other appropriate file to do the
+customization in each session. @xref{Init File}.
+
+@menu
+* Minor Modes:: Each minor mode is one feature you can turn on
+ independently of any others.
+* Variables:: Many Emacs commands examine Emacs variables
+ to decide what to do; by setting variables,
+ you can control their functioning.
+* Keyboard Macros:: A keyboard macro records a sequence of keystrokes
+ to be replayed with a single command.
+* Key Bindings:: The keymaps say what command each key runs.
+ By changing them, you can "redefine keys".
+* Syntax:: The syntax table controls how words and expressions
+ are parsed.
+* Init File:: How to write common customizations in the @file{.emacs} file.
+@end menu
+
+@node Minor Modes, Variables, Customization, Customization
+@section Minor Modes
+@cindex minor modes
+
+@cindex mode line
+ Minor modes are options which you can use or not. For example, Auto Fill
+mode is a minor mode in which @key{SPC} breaks lines between words as you
+type. All the minor modes are independent of each other and of the
+selected major mode. Most minor modes say in the mode line when they are
+on; for example, @samp{Fill} in the mode line means that Auto Fill mode is
+on.
+
+ Append @code{-mode} to the name of a minor mode to get the name of a
+command function that turns the mode on or off. Thus, the command to
+enable or disable Auto Fill mode is called @kbd{M-x auto-fill-mode}. These
+commands are usually invoked with @kbd{M-x}, but you can bind keys to them
+if you wish. With no argument, the function turns the mode on if it was
+off and off if it was on. This is known as @dfn{toggling}. A positive
+argument always turns the mode on, and an explicit zero argument or a
+negative argument always turns it off.
+
+ Auto Fill mode allows you to enter filled text without breaking lines
+explicitly. Emacs inserts newlines as necessary to prevent lines from
+becoming too long. @xref{Filling}.
+
+@cindex Overwrite mode
+@findex overwrite-mode
+ Overwrite mode causes ordinary printing characters to replace existing
+text instead of shoving it over. For example, if the point is in front of
+the @samp{B} in @samp{FOOBAR}, then in Overwrite mode typing a @kbd{G}
+changes it to @samp{FOOGAR}, instead of making it @samp{FOOGBAR} as
+usual.@refill
+
+ Abbrev mode allows you to define abbreviations that automatically expand
+as you type them. For example, @samp{amd} might expand to @samp{abbrev
+mode}. @xref{Abbrevs}, for full information.
+
+@node Variables, Keyboard Macros, Minor Modes, Customization
+@section Variables
+@cindex variables
+@cindex option
+
+ A @dfn{variable} is a Lisp symbol which has a value. The symbol's name
+is also called the name of the variable. Variable names can contain any
+characters, but conventionally they are chosen to be words separated by
+hyphens. A variable can have a documentation string which describes what
+kind of value it should have and how the value will be used.
+
+ Lisp allows any variable to have any kind of value, but most variables
+that Emacs uses require a value of a certain type. Often the value should
+always be a string, or should always be a number. Sometimes we say that a
+certain feature is turned on if a variable is ``non-@code{nil},'' meaning
+that if the variable's value is @code{nil}, the feature is off, but the
+feature is on for @i{any} other value. The conventional value to use to
+turn on the feature---since you have to pick one particular value when you
+set the variable---is @code{t}.
+
+ Emacs uses many Lisp variables for internal recordkeeping, as any Lisp
+program must, but the most interesting variables for you are the ones that
+exist for the sake of customization. Emacs does not (usually) change the
+values of these variables; instead, you set the values, and thereby alter
+and control the behavior of certain Emacs commands. These variables are
+called @dfn{options}. Most options are documented in this manual, and
+appear in the Variable Index (@pxref{Variable Index}).
+
+@cindex right margin position
+@cindex margin position
+ One example of a variable which is an option is @code{fill-column}, which
+specifies the position of the right margin (as a number of characters from
+the left margin) to be used by the fill commands (@pxref{Filling}).
+
+@menu
+* Examining:: Examining or setting one variable's value.
+* Edit Options:: Examining or editing list of all variables' values.
+* Locals:: Per-buffer values of variables.
+* File Variables:: How files can specify variable values.
+@end menu
+
+@node Examining, Edit Options, Variables, Variables
+@subsection Examining and Setting Variables
+@cindex setting variables
+
+@table @kbd
+@item C-h v
+@itemx M-x describe-variable
+Print the value and documentation of a variable.
+@item M-x set-variable
+Change the value of a variable.
+@end table
+
+@kindex C-h v
+@findex describe-variable
+@c !!! following written verbosely to avoid overfull hbox
+ To examine the value of a single variable, type @kbd{C-h v}
+(@code{describe-variable}), which reads a variable name using the
+minibuffer, with completion. It prints both the value and the
+documentation of the variable.
+
+@example
+C-h v fill-column @key{RET}
+@end example
+@noindent
+prints something like
+@smallexample
+@group
+fill-column's value is 72
+
+Documentation:
+*Column beyond which automatic line-wrapping should happen.
+Automatically becomes local when set in any fashion.
+@end group
+@end smallexample
+
+@cindex option
+@noindent
+The star at the beginning of the documentation indicates that this variable
+is an option. @kbd{C-h v} is not restricted to options; it allows any
+variable name.
+
+@findex set-variable
+ If you know which option you want to set, you can set it using @kbd{M-x
+set-variable}. This reads the variable name with the minibuffer (with
+completion), and then reads a Lisp expression for the new value using the
+minibuffer a second time. For example,
+
+@example
+M-x set-variable @key{RET} fill-column @key{RET} 72 @key{RET}
+@end example
+
+@noindent
+sets @code{fill-column} to 72, like executing the Lisp expression
+
+@example
+(setq fill-column 72)
+@end example
+
+ Setting variables in this way, like all means of customizing Emacs
+except where explicitly stated, affects only the current Emacs session.
+
+@node Edit Options, Locals, Examining, Variables
+@subsection Editing Variable Values
+
+@table @kbd
+@item M-x list-options
+Display a buffer listing names, values and documentation of all options.
+@item M-x edit-options
+Change option values by editing a list of options.
+@end table
+
+@findex list-options
+ @kbd{M-x list-options} displays a list of all Emacs option variables, in
+an Emacs buffer named @samp{*List Options*}. Each option is shown with its
+documentation and its current value. Here is what a portion of it might
+look like:
+
+@smallexample
+@group
+;; exec-path:
+("." "/usr/local/bin" "/usr/ucb" "/bin" "/usr/bin" "/u2/emacs/etc")
+*List of directories to search programs to run in subprocesses.
+Each element is a string (directory name)
+or nil (try the default directory).
+;;
+;; fill-column:
+72
+*Column beyond which automatic line-wrapping should happen.
+Automatically becomes local when set in any fashion.
+;;
+@end group
+@end smallexample
+
+@findex edit-options
+@cindex Options mode
+ @kbd{M-x edit-options} goes one step further and immediately selects the
+@samp{*List Options*} buffer; this buffer uses the major mode Options mode,
+which provides commands that allow you to point at an option and change its
+value:
+
+@table @kbd
+@item s
+Set the variable point is in or near to a new value read using the
+minibuffer.
+@item x
+Toggle the variable point is in or near: if the value was @code{nil},
+it becomes @code{t}; otherwise it becomes @code{nil}.
+@item 1
+Set the variable point is in or near to @code{t}.
+@item 0
+Set the variable point is in or near to @code{nil}.
+@item n
+@itemx p
+Move to the next or previous variable.
+@end table
+
+ Changes take effect immediately.
+
+@node Locals, File Variables, Edit Options, Variables
+@subsection Local Variables
+
+@table @kbd
+@item M-x make-local-variable
+Make a variable have a local value in the current buffer.
+@item M-x kill-local-variable
+Make a variable use its global value in the current buffer.
+@item M-x make-variable-buffer-local
+Mark a variable so that setting it will make it local to the
+buffer that is current at that time.
+@end table
+
+@cindex local variables
+ Any variable can be made @dfn{local} to a specific Emacs buffer. This
+means that its value in that buffer is independent of its value in other
+buffers. A few variables are always local in every buffer. Every other
+Emacs variable has a @dfn{global} value which is in effect in all buffers
+that have not made the variable local.
+
+ Major modes always make the variables they set local to the buffer.
+This is why changing major modes in one buffer has no effect on other
+buffers.
+
+@findex make-local-variable
+ @kbd{M-x make-local-variable} reads the name of a variable and makes it
+local to the current buffer. Further changes in this buffer will not
+affect others, and further changes in the global value will not affect this
+buffer.
+
+@findex make-variable-buffer-local
+@cindex per-buffer variables
+ @kbd{M-x make-variable-buffer-local} reads the name of a variable and
+changes the future behavior of the variable so that it will become local
+automatically when it is set. More precisely, once a variable has been
+marked in this way, the usual ways of setting the variable will
+automatically do @code{make-local-variable} first. We call such variables
+@dfn{per-buffer} variables.
+
+@c !!! following paragraph rewritten to avoid overfull hbox
+ Some important variables have been marked per-buffer already. These include
+@code{abbrev-mode}, @code{auto-fill-hook}, @code{case-fold-search},
+@code{ctl-arrow}, @code{comment-column}, @code{fill-column},
+@code{fill-prefix}, @code{indent-tabs-mode}, @code{left-margin},
+@code{mode-line-format}, @code{overwrite-mode},
+@code{selective-display},
+@code{tab-width},
+@code{selective-display-ellipses},
+and @code{truncate-lines}. Some other variables are
+always local in every buffer, but they are used for internal
+purposes.@refill
+
+@findex kill-local-variable
+ @kbd{M-x kill-local-variable} reads the name of a variable and makes it
+cease to be local to the current buffer. The global value of the variable
+henceforth is in effect in this buffer. Setting the major mode kills all
+the local variables of the buffer.
+
+@findex setq-default
+ To set the global value of a variable, regardless of whether the
+variable has a local value in the current buffer, you can use the
+Lisp function @w{@code{setq-default}}. It works like @code{setq}.
+If there is a local value in the current buffer, the local value is
+not affected by @code{setq-default}; thus, the new global value may
+not be visible until you switch to another buffer. For example,
+
+@example
+(setq-default fill-column 72)
+@end example
+
+@noindent
+@code{setq-default} is the only way to set the global value of a variable
+that has been marked with @code{make-variable-buffer-local}.
+
+@findex default-value
+ Programs can look at a variable's default value with @code{default-value}.
+This function takes a symbol as argument and returns its default value.
+The argument is evaluated; usually you must quote it explicitly. For
+example,
+
+@example
+(default-value 'fill-column)
+@end example
+
+@node File Variables,, Locals, Variables
+@subsection Local Variables in Files
+@cindex local variables in files
+
+ A file can contain a @dfn{local variables list}, which specifies the
+values to use for certain Emacs variables when that file is edited.
+Visiting the file checks for a local variables list and makes each variable
+in the list local to the buffer in which the file is visited, with the
+value specified in the file.
+
+ A local variables list goes near the end of the file, in the last page.
+(It is often best to put it on a page by itself.) The local variables list
+starts with a line containing the string @samp{Local Variables:}, and ends
+with a line containing the string @samp{End:}. In between come the
+variable names and values, one set per line, as @samp{@var{variable}:@:
+@var{value}}. The @var{value}s are not evaluated; they are used literally.
+
+ The line which starts the local variables list does not have to say just
+@samp{Local Variables:}. If there is other text before @samp{Local
+Variables:}, that text is called the @dfn{prefix}, and if there is other
+text after, that is called the @dfn{suffix}. If these are present, each
+entry in the local variables list should have the prefix before it and the
+suffix after it. This includes the @samp{End:} line. The prefix and
+suffix are included to disguise the local variables list as a comment so
+that the compiler or text formatter will not be perplexed by it. If you do
+not need to disguise the local variables list as a comment in this way, do
+not bother with a prefix or a suffix.@refill
+
+ Two ``variable'' names are special in a local variables list: a value for
+the variable @code{mode} really sets the major mode, and a value for the
+variable @code{eval} is simply evaluated as an expression and the value is
+ignored. These are not real variables; setting such variables in any other
+context has no such effect. If @code{mode} is used in a local variables
+list, it should be the first entry in the list.
+
+ Here is an example of a local variables list:
+
+@example
+;;; Local Variables: ***
+;;; mode:lisp ***
+;;; comment-column:0 ***
+;;; comment-start: ";;; " ***
+;;; comment-end:"***" ***
+;;; End: ***
+@end example
+
+ Note that the prefix is @samp{;;; } and the suffix is @samp{ ***}. Note also
+that comments in the file begin with and end with the same strings.
+Presumably the file contains code in a language which is like Lisp
+(like it enough for Lisp mode to be useful) but in which comments start
+and end in that way. The prefix and suffix are used in the local
+variables list to make the list appear as comments when the file is read
+by the compiler or interpreter for that language.
+
+ The start of the local variables list must be no more than 3000
+characters from the end of the file, and must be in the last page if the
+file is divided into pages. Otherwise, Emacs will not notice it is there.
+The purpose of this is so that a stray @samp{Local Variables:}@: not in the
+last page does not confuse Emacs, and so that visiting a long file that is
+all one page and has no local variables list need not take the time to
+search the whole file.
+
+@cindex local variables and Auto Fill
+ You may be tempted to try to turn on Auto Fill mode with a local variable
+list. That is a mistake. The choice of Auto Fill mode or not is a matter
+of individual taste, not a matter of the contents of particular files.
+If you want to use Auto Fill, set up major mode hooks with your @file{.emacs}
+file to turn it on (when appropriate) for you alone (@pxref{Init File}).
+Don't try to use a local variable list that would impose your taste on
+everyone.
+
+@vindex inhibit-local-variables
+ If you are concerned that you might visit a file containing a Trojan-horse
+local variable specification, you can prevent local variables processing
+by setting the variable @code{inhibit-local-variables} to a non-@code{nil}
+value. Emacs will display the local variables specification and then ask
+you whether to process it.
+
+@node Keyboard Macros, Key Bindings, Variables, Customization
+@section Keyboard Macros
+
+@cindex keyboard macros
+ A @dfn{keyboard macro} is a command defined by the user to abbreviate a
+sequence of keys. For example, if you discover that you are about to type
+@kbd{C-n C-d} forty times, you can speed your work by defining a keyboard
+macro to do @kbd{C-n C-d} and calling it with a repeat count of forty.
+
+@c widecommands
+@table @kbd
+@item C-x (
+Start defining a keyboard macro (@code{start-kbd-macro}).
+@item C-x )
+End the definition of a keyboard macro (@code{end-kbd-macro}).
+@item C-x e
+Execute the most recent keyboard macro (@code{call-last-kbd-macro}).
+@item C-u C-x (
+Re-execute last keyboard macro, then add more keys to its @w{definition}.
+@item C-x q
+When this point is reached during macro execution, ask for confirmation
+(@code{kbd-macro-query}).
+@item M-x name-last-kbd-macro
+Give a command name (for the duration of the session) to the most
+recently defined keyboard macro.
+@item M-x insert-kbd-macro
+Insert in the buffer a keyboard macro's definition, as Lisp code.
+@end table
+
+ Keyboard macros differ from ordinary Emacs commands in that they are
+written in the Emacs command language rather than in Lisp. This makes it
+easier for the novice to write them, and makes them more convenient as
+temporary hacks. However, the Emacs command language is not powerful
+enough as a programming language to be useful for writing anything
+intelligent or general. For such things, Lisp must be used.
+
+ You define a keyboard macro while executing the commands which are the
+definition. Put differently, as you are defining a keyboard macro, the
+definition is being executed for the first time. This way, you can see
+what the effects of your commands are, so that you don't have to figure
+them out in your head. When you are finished, the keyboard macro is
+defined and also has been, in effect, executed once. You can then do the
+whole thing over again by invoking the macro.
+
+@menu
+* Basic Kbd Macro:: Defining and running keyboard macros.
+* Save Kbd Macro:: Giving keyboard macros names; saving them in files.
+* Kbd Macro Query:: Keyboard macros that do different things each use.
+@end menu
+
+@node Basic Kbd Macro, Save Kbd Macro, Keyboard Macros, Keyboard Macros
+@subsection Basic Use
+
+@kindex C-x (
+@kindex C-x )
+@kindex C-x e
+@findex start-kbd-macro
+@findex end-kbd-macro
+@findex call-last-kbd-macro
+ To start defining a keyboard macro, type the @kbd{C-x (} command
+(@code{start-kbd-macro}). From then on, your keys continue to be
+executed, but also become part of the definition of the macro. @samp{Def}
+appears in the mode line to remind you of what is going on. When you are
+finished, the @kbd{C-x )} command (@code{end-kbd-macro}) terminates the
+definition (without becoming part of it!).
+
+@example
+@group
+@exdent For example,
+
+C-x ( M-F foo C-x )
+@end group
+@end example
+
+@noindent
+defines a macro to move forward a word and then insert @samp{foo}.
+
+ The macro thus defined can be invoked again with the @kbd{C-x e} command
+(@code{call-last-kbd-macro}), which may be given a repeat count as a
+numeric argument to execute the macro many times. @kbd{C-x )} can also be
+given a repeat count as an argument, in which case it repeats the macro
+that many times right after defining it, but defining the macro counts as
+the first repetition (since it is executed as you define it). So, giving
+@kbd{C-x )} an argument of 4 executes the macro immediately 3 additional
+times. An argument of zero to @kbd{C-x e} or @kbd{C-x )} means repeat the
+macro indefinitely (until it gets an error or you type @kbd{C-g}).
+
+ If you wish to repeat an operation at regularly spaced places in the
+text, define a macro and include as part of the macro the commands to move
+to the next place you want to use it. For example, if you want to change
+each line, you should position point at the start of a line, and define a
+macro to change that line and leave point at the start of the next line.
+Then repeating the macro will operate on successive lines.
+
+ After you have terminated the definition of a keyboard macro, you can add
+to the end of its definition by typing @kbd{C-u C-x (}. This is equivalent
+to plain @kbd{C-x (} followed by retyping the whole definition so far. As
+a consequence it re-executes the macro as previously defined.
+
+ One limitation on the use of keyboard macros is that if you exit a
+recursive edit within a macro that was not entered within the macro,
+then the execution of the macro stops at that point. In Emacs 18, View
+mode uses a recursive edit, so exiting View mode is an occasion for such
+a problem.
+
+@node Save Kbd Macro, Kbd Macro Query, Basic Kbd Macro, Keyboard Macros
+@subsection Naming and Saving Keyboard Macros
+
+@findex name-last-kbd-macro
+ If you wish to save a keyboard macro for longer than until you define the
+next one, you must give it a name using @kbd{M-x name-last-kbd-macro}.
+This reads a name as an argument using the minibuffer and defines that name
+to execute the macro. The macro name is a Lisp symbol, and defining it in
+this way makes it a valid command name for calling with @kbd{M-x} or for
+binding a key to with @code{global-set-key} (@pxref{Keymaps}). If you
+specify a name that has a prior definition other than another keyboard
+macro, an error message is printed and nothing is changed.
+
+@findex insert-kbd-macro
+ Once a macro has a command name, you can save its definition in a file.
+Then it can be used in another editing session. First visit the file
+you want to save the definition in. Then use the command
+
+@example
+M-x insert-kbd-macro @key{RET} @var{macroname} @key{RET}
+@end example
+
+@noindent
+This inserts some Lisp code that, when executed later, will define the same
+macro with the same definition it has now. You need not understand Lisp
+code to do this, because @code{insert-kbd-macro} writes the Lisp code for you.
+Then save the file. The file can be loaded with @code{load-file}
+(@pxref{Lisp Libraries}). If the file you save in is your init file
+@file{~/.emacs} (@pxref{Init File}) then the macro will be defined each
+time you run Emacs.
+
+ If you give @code{insert-kbd-macro} a prefix argument, it makes
+additional Lisp code to record the keys (if any) that you have bound to the
+keyboard macro, so that the macro will be reassigned the same keys when you
+load the file.
+
+@node Kbd Macro Query,, Save Kbd Macro, Keyboard Macros
+@subsection Executing Macros with Variations
+
+@kindex C-x q
+@findex kbd-macro-query
+ Using @kbd{C-x q} (@code{kbd-macro-query}), you can get an effect similar
+to that of @code{query-replace}, where the macro asks you each time around
+whether to make a change. When you are defining the macro, type @kbd{C-x
+q} at the point where you want the query to occur. During macro
+definition, the @kbd{C-x q} does nothing, but when the macro is invoked the
+@kbd{C-x q} reads a character from the terminal to decide whether to
+continue.
+
+ The special answers are @key{SPC}, @key{DEL}, @kbd{C-d}, @kbd{C-l} and
+@kbd{C-r}. Any other character terminates execution of the keyboard macro
+and is then read as a command. @key{SPC} means to continue. @key{DEL}
+means to skip the remainder of this repetition of the macro, starting again
+from the beginning in the next repetition. @kbd{C-d} means to skip the
+remainder of this repetition and cancel further repetition. @kbd{C-l}
+redraws the screen and asks you again for a character to say what to do.
+@kbd{C-r} enters a recursive editing level, in which you can perform
+editing which is not part of the macro. When you exit the recursive edit
+using @kbd{C-M-c}, you are asked again how to continue with the keyboard
+macro. If you type a @key{SPC} at this time, the rest of the macro
+definition is executed. It is up to you to leave point and the text in a
+state such that the rest of the macro will do what you want.@refill
+
+ @kbd{C-u C-x q}, which is @kbd{C-x q} with a numeric argument, performs a
+different function. It enters a recursive edit reading input from the
+keyboard, both when you type it during the definition of the macro, and
+when it is executed from the macro. During definition, the editing you do
+inside the recursive edit does not become part of the macro. During macro
+execution, the recursive edit gives you a chance to do some particularized
+editing. @xref{Recursive Edit}.
+
+@node Key Bindings, Syntax, Keyboard Macros, Customization
+@section Customizing Key Bindings
+
+ This section deals with the @dfn{keymaps} which define the bindings
+between keys and functions, and shows how you can customize these bindings.
+@cindex command
+@cindex function
+@cindex command name
+
+ A command is a Lisp function whose definition provides for interactive
+use. Like every Lisp function, a command has a function name, a Lisp
+symbol whose name usually consists of lower case letters and hyphens.
+
+@menu
+* Keymaps:: Definition of the keymap data structure.
+ Names of Emacs's standard keymaps.
+* Rebinding:: How to redefine one key's meaning conveniently.
+* Disabling:: Disabling a command means confirmation is required
+ before it can be executed. This is done to protect
+ beginners from surprises.
+@end menu
+
+@node Keymaps, Rebinding, Key Bindings, Key Bindings
+@subsection Keymaps
+@cindex keymap
+
+@cindex global keymap
+@vindex global-map
+ The bindings between characters and command functions are recorded in
+data structures called @dfn{keymaps}. Emacs has many of these. One, the
+@dfn{global} keymap, defines the meanings of the single-character keys that
+are defined regardless of major mode. It is the value of the variable
+@code{global-map}.
+
+@cindex local keymap
+@vindex c-mode-map
+@vindex lisp-mode-map
+ Each major mode has another keymap, its @dfn{local keymap}, which
+contains overriding definitions for the single-character keys that are to
+be redefined in that mode. Each buffer records which local keymap is
+installed for it at any time, and the current buffer's local keymap is the
+only one that directly affects command execution. The local keymaps for
+Lisp mode, C mode, and many other major modes always exist even when not in
+use. They are the values of the variables @code{lisp-mode-map},
+@code{c-mode-map}, and so on. For major modes less often used, the local
+keymap is sometimes constructed only when the mode is used for the first
+time in a session. This is to save space.
+
+@cindex minibuffer
+@vindex minibuffer-local-map
+@vindex minibuffer-local-ns-map
+@vindex minibuffer-local-completion-map
+@vindex minibuffer-local-must-match-map
+@vindex repeat-complex-command-map
+ There are local keymaps for the minibuffer too; they contain various
+completion and exit commands.
+
+@itemize @bullet
+@item
+@code{minibuffer-local-map} is used for ordinary input (no completion).
+@item
+@code{minibuffer-local-ns-map} is similar, except that @key{SPC} exits
+just like @key{RET}. This is used mainly for Mocklisp compatibility.
+@item
+@code{minibuffer-local-completion-map} is for permissive completion.
+@item
+@code{minibuffer-local-must-match-map} is for strict completion and
+for cautious completion.
+@item
+@code{repeat-complex-command-map} is for use in @kbd{C-x @key{ESC}}.
+@end itemize
+
+@vindex ctl-x-map
+@vindex help-map
+@vindex esc-map
+ Finally, each prefix key has a keymap which defines the key sequences
+that start with it. For example, @code{ctl-x-map} is the keymap used for
+characters following a @kbd{C-x}.
+
+@itemize @bullet
+@item
+@code{ctl-x-map} is the variable name for the map used for characters that
+follow @kbd{C-x}.
+@item
+@code{help-map} is used for characters that follow @kbd{C-h}.
+@item
+@code{esc-map} is for characters that follow @key{ESC}. Thus, all Meta
+characters are actually defined by this map.
+@item
+@code{ctl-x-4-map} is for characters that follow @kbd{C-x 4}.
+@item
+@code{mode-specific-map} is for characters that follow @kbd{C-c}.
+@end itemize
+
+ The definition of a prefix key is just the keymap to use for looking up
+the following character. Actually, the definition is sometimes a Lisp
+symbol whose function definition is the following character keymap. The
+effect is the same, but it provides a command name for the prefix key that
+can be used as a description of what the prefix key is for. Thus, the
+binding of @kbd{C-x} is the symbol @code{Ctl-X-Prefix}, whose function
+definition is the keymap for @kbd{C-x} commands, the value of
+@code{ctl-x-map}.@refill
+
+ Prefix key definitions of this sort can appear in either the global map
+or a local map. The definitions of @kbd{C-c}, @kbd{C-x}, @kbd{C-h} and @key{ESC}
+as prefix keys appear in the global map, so these prefix keys are always
+available. Major modes can locally redefine a key as a prefix by putting
+a prefix key definition for it in the local map.@refill
+
+ A mode can also put a prefix definition of a global prefix character such
+as @kbd{C-x} into its local map. This is how major modes override the
+definitions of certain keys that start with @kbd{C-x}. This case is
+special, because the local definition does not entirely replace the global
+one. When both the global and local definitions of a key are other
+keymaps, the next character is looked up in both keymaps, with the local
+definition overriding the global one as usual. So, the character after the
+@kbd{C-x} is looked up in both the major mode's own keymap for redefined
+@kbd{C-x} commands and in @code{ctl-x-map}. If the major mode's own keymap
+for @kbd{C-x} commands contains @code{nil}, the definition from the global
+keymap for @kbd{C-x} commands is used.@refill
+
+@cindex sparse keymap
+ A keymap is actually a Lisp object. The simplest form of keymap is a
+Lisp vector of length 128. The binding for a character in such a keymap is
+found by indexing into the vector with the character as an index. A keymap
+can also be a Lisp list whose @sc{car} is the symbol @code{keymap} and whose
+remaining elements are pairs of the form @code{(@var{char} .@: @var{binding})}.
+Such lists are called @dfn{sparse keymaps} because they are used when most
+of the characters' entries will be @code{nil}. Sparse keymaps are used
+mainly for prefix characters.
+
+ Keymaps are only of length 128, so what about Meta characters, whose
+codes are from 128 to 255? A key that contains a Meta character actually
+represents it as a sequence of two characters, the first of which is
+@key{ESC}. So the key @kbd{M-a} is really represented as @kbd{@key{ESC}
+a}, and its binding is found at the slot for @samp{a} in
+@code{esc-map}.@refill
+
+@node Rebinding, Disabling, Keymaps, Key Bindings
+@subsection Changing Key Bindings Interactively
+@cindex key rebinding, this session
+@cindex rebinding keys, this session
+@cindex rebinding keys, this session
+
+ The way to redefine an Emacs key is to change its entry in a keymap.
+You can change the global keymap, in which case the change is effective in
+all major modes (except those that have their own overriding local
+definitions for the same key). Or you can change the current buffer's
+local map, which affects all buffers using the same major mode.
+@findex global-set-key
+@findex local-set-key
+
+@table @kbd
+@item M-x global-set-key @key{RET} @var{key} @var{cmd} @key{RET}
+Defines @var{key} globally to run @var{cmd}.
+@item M-x local-set-key @key{RET} @var{key} @var{cmd} @key{RET}
+Defines @var{key} locally (in the major mode now in effect) to run
+@var{cmd}.
+@end table
+
+ For example,
+
+@example
+M-x global-set-key @key{RET} C-f next-line @key{RET}
+@end example
+
+@noindent
+would redefine @kbd{C-f} to move down a line. The fact that @var{cmd} is
+read second makes it serve as a kind of confirmation for @var{key}.
+
+ These functions offer no way to specify a particular prefix keymap as the
+one to redefine in, but that is not necessary, as you can include prefixes
+in @var{key}. @var{key} is read by reading characters one by one until
+they amount to a complete key (that is, not a prefix key). Thus, if you
+type @kbd{C-f} for @var{key}, that's the end; the minibuffer is entered
+immediately to read @var{cmd}. But if you type @kbd{C-x}, another
+character is read; if that is @kbd{4}, another character is read, and so
+on. For example,@refill
+
+@example
+M-x global-set-key @key{RET} C-x 4 $ spell-other-window @key{RET}
+@end example
+
+@noindent
+would redefine @kbd{C-x 4 $} to run the (fictitious) command
+@code{spell-other-window}.
+
+ All the key sequences which consist of @kbd{C-c} followed by a letter
+are supposed to be reserved for user customization. That is, Emacs Lisp
+libraries should not define any of these commands.
+
+@findex define-key
+@findex substitute-key-definition
+ The most general way to modify a keymap is the function @code{define-key},
+used in Lisp code (such as your @file{.emacs} file). @code{define-key}
+takes three arguments: the keymap, the key to modify in it, and the new
+definition. @xref{Init File}, for an example. @code{substitute-key-definition}
+is used similarly; it takes three arguments, an old definition, a new
+definition and a keymap, and redefines in that keymap all keys that were
+previously defined with the old definition to have the new definition
+instead.
+
+@node Disabling,, Rebinding, Key Bindings
+@subsection Disabling Commands
+@cindex disabled command
+
+ Disabling a command marks the command as requiring confirmation before it
+can be executed. The purpose of disabling a command is to prevent
+beginning users from executing it by accident and being confused.
+
+ The direct mechanism for disabling a command is to have a non-@code{nil}
+@code{disabled} property on the Lisp symbol for the command. These
+properties are normally set up by the user's @file{.emacs} file with
+Lisp expressions such as
+
+@example
+(put 'delete-region 'disabled t)
+@end example
+
+ If the value of the @code{disabled} property is a string, that string
+is included in the message printed when the command is used:
+
+@example
+(put 'delete-region 'disabled
+ "Text deleted this way cannot be yanked back!\n")
+@end example
+
+@findex disable-command
+@findex enable-command
+ You can make a command disabled either by editing the @file{.emacs} file
+directly or with the command @kbd{M-x disable-command}, which edits the
+@file{.emacs} file for you. @xref{Init File}.
+
+ Attempting to invoke a disabled command interactively in Emacs causes the
+display of a window containing the command's name, its documentation, and
+some instructions on what to do immediately; then Emacs asks for input
+saying whether to execute the command as requested, enable it and execute,
+or cancel it. If you decide to enable the command, you are asked whether to
+do this permanently or just for the current session. Enabling permanently
+works by automatically editing your @file{.emacs} file. You can use
+@kbd{M-x enable-command} at any time to enable any command permanently.
+
+ Whether a command is disabled is independent of what key is used to
+invoke it; it also applies if the command is invoked using @kbd{M-x}.
+Disabling a command has no effect on calling it as a function from Lisp
+programs.
+
+@node Syntax, Init File, Key Bindings, Customization
+@section The Syntax Table
+@cindex syntax table
+
+ All the Emacs commands which parse words or balance parentheses are
+controlled by the @dfn{syntax table}. The syntax table says which
+characters are opening delimiters, which are parts of words, which are
+string quotes, and so on. Actually, each major mode has its own syntax
+table (though sometimes related major modes use the same one) which it
+installs in each buffer that uses that major mode. The syntax table
+installed in the current buffer is the one that all commands use, so we
+call it ``the'' syntax table. A syntax table is a Lisp object, a vector of
+length 256 whose elements are numbers.
+
+@menu
+* Entry: Syntax Entry. What the syntax table records for each character.
+* Change: Syntax Change. How to change the information.
+@end menu
+
+@node Syntax Entry, Syntax Change, Syntax, Syntax
+@subsection Information about Each Character
+
+ The syntax table entry for a character is a number that encodes six
+pieces of information:
+
+@itemize @bullet
+@item
+The syntactic class of the character, represented as a small integer.
+@item
+The matching delimiter, for delimiter characters only.
+The matching delimiter of @samp{(} is @samp{)}, and vice versa.
+@item
+A flag saying whether the character is the first character of a
+two-character comment starting sequence.
+@item
+A flag saying whether the character is the second character of a
+two-character comment starting sequence.
+@item
+A flag saying whether the character is the first character of a
+two-character comment ending sequence.
+@item
+A flag saying whether the character is the second character of a
+two-character comment ending sequence.
+@end itemize
+
+ The syntactic classes are stored internally as small integers, but are
+usually described to or by the user with characters. For example, @samp{(}
+is used to specify the syntactic class of opening delimiters. Here is a
+table of syntactic classes, with the characters that specify them.
+
+@table @samp
+@item @w{ }
+The class of whitespace characters.
+@item -
+Another name for the class of whitespace characters.
+@item w
+The class of word-constituent characters.
+@item _
+The class of characters that are part of symbol names but not words.
+This class is represented by @samp{_} because the character @samp{_}
+has this class in both C and Lisp.
+@item .
+The class of punctuation characters that do not fit into any other
+special class.
+@item (
+The class of opening delimiters.
+@item )
+The class of closing delimiters.
+@item '
+The class of expression-adhering characters. These characters are
+part of a symbol if found within or adjacent to one, and are part
+of a following expression if immediately preceding one, but are like
+whitespace if surrounded by whitespace.
+@item "
+The class of string-quote characters. They match each other in pairs,
+and the characters within the pair all lose their syntactic
+significance except for the @samp{\} and @samp{/} classes of escape
+characters, which can be used to include a string-quote inside the
+string.
+@item $
+The class of self-matching delimiters. This is intended for @TeX{}'s
+@samp{$}, which is used both to enter and leave math mode. Thus,
+a pair of matching @samp{$} characters surround each piece of math mode
+@TeX{} input. A pair of adjacent @samp{$} characters act like a single
+one for purposes of matching.
+
+@item /
+The class of escape characters that always just deny the following
+character its special syntactic significance. The character after one
+of these escapes is always treated as alphabetic.
+@item \
+The class of C-style escape characters. In practice, these are
+treated just like @samp{/}-class characters, because the extra
+possibilities for C escapes (such as being followed by digits) have no
+effect on where the containing expression ends.
+@item <
+The class of comment-starting characters. Only single-character
+comment starters (such as @samp{;} in Lisp mode) are represented this
+way.
+@item >
+The class of comment-ending characters. Newline has this syntax in
+Lisp mode.
+@end table
+
+@vindex parse-sexp-ignore-comments
+ The characters flagged as part of two-character comment delimiters can
+have other syntactic functions most of the time. For example, @samp{/} and
+@samp{*} in C code, when found separately, have nothing to do with
+comments. The comment-delimiter significance overrides when the pair of
+characters occur together in the proper order. Only the list and sexp
+commands use the syntax table to find comments; the commands specifically
+for comments have other variables that tell them where to find comments.
+And the list and sexp commands notice comments only if
+@code{parse-sexp-ignore-comments} is non-@code{nil}. This variable is set
+to @code{nil} in modes where comment-terminator sequences are liable to
+appear where there is no comment; for example, in Lisp mode where the
+comment terminator is a newline but not every newline ends a comment.
+
+@node Syntax Change,, Syntax Entry, Syntax
+@subsection Altering Syntax Information
+
+ It is possible to alter a character's syntax table entry by storing a new
+number in the appropriate element of the syntax table, but it would be hard
+to determine what number to use. Therefore, Emacs provides a command that
+allows you to specify the syntactic properties of a character in a
+convenient way.
+
+@findex modify-syntax-entry
+ @kbd{M-x modify-syntax-entry} is the command to change a character's
+syntax. It can be used interactively, and is also the means used by major
+modes to initialize their own syntax tables. Its first argument is the
+character to change. The second argument is a string that specifies the
+new syntax. When called from Lisp code, there is a third, optional
+argument, which specifies the syntax table in which to make the change. If
+not supplied, or if this command is called interactively, the third
+argument defaults to the current buffer's syntax table.
+
+@enumerate
+@item
+The first character in the string specifies the syntactic class. It
+is one of the characters in the previous table (@pxref{Syntax Entry}).
+
+@item
+The second character is the matching delimiter. For a character that
+is not an opening or closing delimiter, this should be a space, and may
+be omitted if no following characters are needed.
+
+@item
+The remaining characters are flags. The flag characters allowed are
+
+@table @samp
+@item 1
+Flag this character as the first of a two-character comment starting sequence.
+@item 2
+Flag this character as the second of a two-character comment starting sequence.
+@item 3
+Flag this character as the first of a two-character comment ending sequence.
+@item 4
+Flag this character as the second of a two-character comment ending sequence.
+@end table
+@end enumerate
+
+@kindex C-h s
+@findex describe-syntax
+ A description of the contents of the current syntax table can be
+displayed with @kbd{C-h s} (@code{describe-syntax}). The description of
+each character includes both the string you would have to give to
+@code{modify-syntax-entry} to set up that character's current syntax, and
+some English to explain that string if necessary.
+
+@node Init File,, Syntax, Customization
+@section The Init File, .emacs
+@cindex init file
+@cindex Emacs initialization file
+@cindex key rebinding, permanent
+@cindex rebinding keys, permanently
+
+ When Emacs is started, it normally loads the file @file{.emacs} in your
+home directory. This file, if it exists, should contain Lisp code. It is
+called your @dfn{init file}. The command line switches @samp{-q} and
+@samp{-u} can be used to tell Emacs whether to load an init file
+(@pxref{Entering Emacs}).
+
+ There can also be a @dfn{default init file}, which is the library named
+@file{default.el}, found via the standard search path for libraries. The
+Emacs distribution contains no such library; your site may create one for
+local customizations. If this library exists, it is loaded whenever you
+start Emacs. But your init file, if any, is loaded first; if it sets
+@code{inhibit-default-init} non-@code{nil}, then @file{default} is not
+loaded.
+
+ If you have a large amount of code in your @file{.emacs} file, you
+should move it into another file named @file{@var{something}.el},
+byte-compile it (@pxref{Lisp Libraries}), and make your @file{.emacs}
+file load the other file using @code{load}.
+
+@menu
+* Init Syntax:: Syntax of constants in Emacs Lisp.
+* Init Examples:: How to do some things with an init file.
+* Terminal Init:: Each terminal type can have an init file.
+* Debugging Init:: How to debug your @file{.emacs} file.
+@end menu
+
+@node Init Syntax, Init Examples, Init File, Init File
+@subsection Init File Syntax
+
+ The @file{.emacs} file contains one or more Lisp function call
+expressions. Each of these consists of a function name followed by
+arguments, all surrounded by parentheses. For example, @code{(setq
+fill-column 60)} represents a call to the function @code{setq} which is
+used to set the variable @code{fill-column} (@pxref{Filling}) to 60.
+
+ The second argument to @code{setq} is an expression for the new value of
+the variable. This can be a constant, a variable, or a function call
+expression. In @file{.emacs}, constants are used most of the time. They can be:
+
+@table @asis
+@item Numbers:
+Numbers are written in decimal, with an optional initial minus sign.
+
+@item Strings:
+Lisp string syntax is the same as C string syntax with a few extra
+features. Use a double-quote character to begin and end a string constant.
+
+Newlines and special characters may be present literally in strings. They
+can also be represented as backslash sequences: @samp{\n} for newline,
+@samp{\b} for backspace, @samp{\r} for carriage return, @samp{\t} for tab,
+@samp{\f} for formfeed (control-l), @samp{\e} for escape, @samp{\\} for a
+backslash, @samp{\"} for a double-quote, or @samp{\@var{ooo}} for the
+character whose octal code is @var{ooo}. Backslash and double-quote are
+the only characters for which backslash sequences are mandatory.
+
+@samp{\C-} can be used as a prefix for a control character, as in
+@w{@samp{\C-s}} for @sc{ascii} Control-S, and @samp{\M-} can be used as a prefix for
+a meta character, as in @samp{\M-a} for Meta-A or @samp{\M-\C-a} for
+Control-Meta-A.
+
+@item Characters:
+Lisp character constant syntax consists of a @samp{?} followed by
+either a character or an escape sequence starting with @samp{\}.
+Examples: @code{?x}, @code{?\n}, @code{?\"}, @code{?\)}. Note that
+strings and characters are not interchangeable in Lisp; some contexts
+require one and some contexts require the other.
+
+@item True:
+@code{t} stands for `true'.
+
+@item False:
+@code{nil} stands for `false'.
+
+@item Other Lisp objects:
+Write a single-quote (') followed by the Lisp object you want.
+@end table
+
+@node Init Examples, Terminal Init, Init Syntax, Init File
+@subsection Init File Examples
+
+ Here are some examples of doing certain commonly desired things with
+Lisp expressions:
+
+@itemize @bullet
+@item
+Make @key{TAB} in C mode just insert a tab if point is in the middle of a
+line.
+
+@example
+(setq c-tab-always-indent nil)
+@end example
+
+Here we have a variable whose value is normally @code{t} for `true'
+and the alternative is @code{nil} for `false'.
+
+@item
+Make searches case sensitive by default (in all buffers that do not
+override this).
+
+@example
+(setq-default case-fold-search nil)
+@end example
+
+This sets the default value, which is effective in all buffers that do
+not have local values for the variable. Setting @code{case-fold-search}
+with @code{setq} affects only the current buffer's local value, which
+is not what you probably want to do in an init file.
+
+@item
+Make Text mode the default mode for new buffers.
+
+@example
+(setq default-major-mode 'text-mode)
+@end example
+
+Note that @code{text-mode} is used because it is the command for entering
+the mode we want. A single-quote is written before it to make a symbol
+constant; otherwise, @code{text-mode} would be treated as a variable name.
+
+@item
+Turn on Auto Fill mode automatically in Text mode and related modes.
+
+@example
+(setq text-mode-hook
+ '(lambda () (auto-fill-mode 1)))
+@end example
+
+Here we have a variable whose value should be a Lisp function. The
+function we supply is a list starting with @code{lambda}, and a single
+quote is written in front of it to make it (for the purpose of this
+@code{setq}) a list constant rather than an expression. Lisp functions
+are not explained here, but for mode hooks it is enough to know that
+@code{(auto-fill-mode 1)} is an expression that will be executed when
+Text mode is entered, and you could replace it with any other expression
+that you like, or with several expressions in a row.
+
+@example
+(setq text-mode-hook 'turn-on-auto-fill)
+@end example
+
+This is another way to accomplish the same result.
+@code{turn-on-auto-fill} is a symbol whose function definition is
+@code{(lambda () (auto-fill-@w{mode 1}))}.
+
+@item
+Load the installed Lisp library named @file{foo} (actually a file
+@file{foo.elc} or @file{foo.el} in a standard Emacs directory).
+
+@example
+(load "foo")
+@end example
+
+When the argument to @code{load} is a relative pathname, not starting
+with @samp{/} or @samp{~}, @code{load} searches the directories in
+@code{load-path} (@pxref{Loading}).
+
+@item
+Load the compiled Lisp file @file{foo.elc} from your home directory.
+
+@example
+(load "~/foo.elc")
+@end example
+
+Here an absolute file name is used, so no searching is done.
+
+@item
+Rebind the key @kbd{C-x l} to run the function @code{make-symbolic-link}.
+
+@example
+(global-set-key "\C-xl" 'make-symbolic-link)
+@end example
+
+or
+
+@example
+(define-key global-map "\C-xl" 'make-symbolic-link)
+@end example
+
+Note once again the single-quote used to refer to the symbol
+@code{make-symbolic-link} instead of its value as a variable.
+
+@item
+Do the same thing for C mode only.
+
+@example
+(define-key c-mode-map "\C-xl" 'make-symbolic-link)
+@end example
+
+@item
+Redefine all keys which now run @code{next-line} in Fundamental mode
+so that they run @code{forward-line} instead.
+
+@example
+(substitute-key-definition 'next-line 'forward-line
+ global-map)
+@end example
+
+@item
+Make @kbd{C-x C-v} undefined.
+
+@example
+(global-unset-key "\C-x\C-v")
+@end example
+
+One reason to undefine a key is so that you can make it a prefix.
+Simply defining @kbd{C-x C-v @var{anything}} would make @kbd{C-x C-v}
+a prefix, but @kbd{C-x C-v} must be freed of any non-prefix definition
+first.
+
+@item
+Make @samp{$} have the syntax of punctuation in Text mode.
+Note the use of a character constant for @samp{$}.
+
+@example
+(modify-syntax-entry ?\$ "." text-mode-syntax-table)
+@end example
+
+@item
+Enable the use of the command @code{eval-expression} without confirmation.
+
+@example
+(put 'eval-expression 'disabled nil)
+@end example
+@end itemize
+
+@node Terminal Init, Debugging Init, Init Examples, Init File
+@subsection Terminal-specific Initialization
+
+ Each terminal type can have a Lisp library to be loaded into Emacs when
+it is run on that type of terminal. For a terminal type named
+@var{termtype}, the library is called @file{term/@var{termtype}} and it is
+found by searching the directories @code{load-path} as usual and trying the
+suffixes @samp{.elc} and @samp{.el}. Normally it appears in the
+subdirectory @file{term} of the directory where most Emacs libraries are
+kept.@refill
+
+ The usual purpose of the terminal-specific library is to define the
+escape sequences used by the terminal's function keys using the library
+@file{keypad.el}. See the file
+@file{term/vt100.el} for an example of how this is done.@refill
+
+ When the terminal type contains a hyphen, only the part of the name
+before the first hyphen is significant in choosing the library name.
+Thus, terminal types @samp{aaa-48} and @samp{aaa-30-rv} both use
+the library @file{term/aaa}. The code in the library can use
+@code{(getenv "TERM")} to find the full terminal type name.@refill
+
+@vindex term-file-prefix
+ The library's name is constructed by concatenating the value of the
+variable @code{term-file-prefix} and the terminal type. Your @file{.emacs}
+file can prevent the loading of the terminal-specific library by setting
+@code{term-file-prefix} to @code{nil}.
+
+@vindex term-setup-hook
+ The value of the variable @code{term-setup-hook}, if not @code{nil}, is
+called as a function of no arguments at the end of Emacs initialization,
+after both your @file{.emacs} file and any terminal-specific library have
+been read in. You can set the value in the @file{.emacs} file to override
+part of any of the terminal-specific libraries and to define
+initializations for terminals that do not have a library.@refill
+
+@node Debugging Init,, Terminal Init, Init File
+@subsection Debugging Your @file{.emacs} File
+
+ Ordinarily, Emacs traps errors that occur while reading @file{.emacs}.
+This is convenient, most of the time, because it means you can still get
+an Emacs in which you can edit. But it causes inconvenience because
+there is no way to enter the debugger if there is an error.
+
+ But you can run the @file{.emacs} file explicitly in an Emacs that is
+already set up, and debug errors at that time.
+
+@example
+M-x set-variable
+debug-on-error
+t
+M-x load-file
+~/.emacs
+@end example
+
+ In Emacs 19, use the @samp{-debug-init} option if you want errors in
+@file{.emacs} to enter the debugger.
+
+@iftex
+@chapter Correcting Mistakes (Yours or Emacs's)
+
+ If you type an Emacs command you did not intend, the results are often
+mysterious. This chapter tells what you can do to cancel your mistake or
+recover from a mysterious situation. Emacs bugs and system crashes are
+also considered.
+@end iftex
+
+@node Quitting, Lossage, Customization, Top
+@section Quitting and Aborting
+@cindex quitting
+
+@table @kbd
+@item C-g
+Quit. Cancel running or partially typed command.
+@item C-]
+Abort innermost recursive editing level and cancel the command which
+invoked it (@code{abort-recursive-edit}).
+@item M-x top-level
+Abort all recursive editing levels that are currently executing.
+@item C-x u
+Cancel an already-executed command, usually (@code{undo}).
+@end table
+
+ There are two ways of cancelling commands which are not finished
+executing: @dfn{quitting} with @kbd{C-g}, and @dfn{aborting} with @kbd{C-]}
+or @kbd{M-x top-level}. Quitting is cancelling a partially typed command
+or one which is already running. Aborting is getting out of a recursive
+editing level and cancelling the command that invoked the recursive edit.
+
+@cindex quitting
+@cindex C-g
+ Quitting with @kbd{C-g} is used for getting rid of a partially typed
+command, or a numeric argument that you don't want. It also stops a
+running command in the middle in a relatively safe way, so you can use it
+if you accidentally give a command which takes a long time. In particular,
+it is safe to quit out of killing; either your text will @var{all} still be
+there, or it will @var{all} be in the kill ring (or maybe both). Quitting
+an incremental search does special things documented under searching; in
+general, it may take two successive @kbd{C-g} characters to get out of a
+search. @kbd{C-g} works by setting the variable @code{quit-flag} to
+@code{t} the instant @kbd{C-g} is typed; Emacs Lisp checks this variable
+frequently and quits if it is non-@code{nil}. @kbd{C-g} is only actually
+executed as a command if it is typed while Emacs is waiting for input.
+
+ If you quit twice in a row before the first @kbd{C-g} is recognized, you
+activate the ``emergency escape'' feature and return to the shell.
+@xref{Emergency Escape}.
+
+@cindex recursive editing level
+@cindex editing level, recursive
+@cindex aborting
+@findex abort-recursive-edit
+@kindex C-]
+ Aborting with @kbd{C-]} (@code{abort-recursive-edit}) is used to get out
+of a recursive editing level and cancel the command which invoked it.
+Quitting with @kbd{C-g} does not do this, and could not do this, because it
+is used to cancel a partially typed command @i{within} the recursive
+editing level. Both operations are useful. For example, if you are in the
+Emacs debugger (@pxref{Lisp Debug}) and have typed @kbd{C-u 8} to enter a
+numeric argument, you can cancel that argument with @kbd{C-g} and remain in
+the debugger.
+
+@findex top-level
+ The command @kbd{M-x top-level} is equivalent to ``enough'' @kbd{C-]}
+commands to get you out of all the levels of recursive edits that you are
+in. @kbd{C-]} gets you out one level at a time, but @kbd{M-x top-level}
+goes out all levels at once. Both @kbd{C-]} and @kbd{M-x top-level} are
+like all other commands, and unlike @kbd{C-g}, in that they are effective
+only when Emacs is ready for a command. @kbd{C-]} is an ordinary key and
+has its meaning only because of its binding in the keymap.
+@xref{Recursive Edit}.
+
+ @kbd{C-x u} (@code{undo}) is not strictly speaking a way of cancelling a
+command, but you can think of it as cancelling a command already finished
+executing. @xref{Undo}.
+
+@node Lossage, Bugs, Quitting, Top
+@section Dealing with Emacs Trouble
+
+ This section describes various conditions in which Emacs fails to work,
+and how to recognize them and correct them.
+
+@menu
+* Stuck Recursive:: `[...]' in mode line around the parentheses
+* Screen Garbled:: Garbage on the screen
+* Text Garbled:: Garbage in the text
+* Unasked-for Search:: Spontaneous entry to incremental search
+* Emergency Escape:: Emergency escape---
+ What to do if Emacs stops responding
+* Total Frustration:: When you are at your wits' end.
+@end menu
+
+@node Stuck Recursive, Screen Garbled, Lossage, Lossage
+@subsection Recursive Editing Levels
+
+ Recursive editing levels are important and useful features of Emacs, but
+they can seem like malfunctions to the user who does not understand them.
+
+ If the mode line has square brackets @samp{[@dots{}]} around the parentheses
+that contain the names of the major and minor modes, you have entered a
+recursive editing level. If you did not do this on purpose, or if you
+don't understand what that means, you should just get out of the recursive
+editing level. To do so, type @kbd{M-x top-level}. This is called getting
+back to top level. @xref{Recursive Edit}.
+
+@node Screen Garbled, Text Garbled, Stuck Recursive, Lossage
+@subsection Garbage on the Screen
+
+ If the data on the screen looks wrong, the first thing to do is see
+whether the text is really wrong. Type @kbd{C-l}, to redisplay the entire
+screen. If it appears correct after this, the problem was entirely in the
+previous screen update.
+
+ Display updating problems often result from an incorrect termcap entry
+for the terminal you are using. The file @file{etc/TERMS} in the Emacs
+distribution gives the fixes for known problems of this sort.
+@file{INSTALL} contains general advice for these problems in one of its
+sections. Very likely there is simply insufficient padding for certain
+display operations. To investigate the possibility that you have this sort
+of problem, try Emacs on another terminal made by a different manufacturer.
+If problems happen frequently on one kind of terminal but not another kind,
+it is likely to be a bad termcap entry, though it could also be due to a
+bug in Emacs that appears for terminals that have or that lack specific
+features.
+
+@node Text Garbled, Unasked-for Search, Screen Garbled, Lossage
+@subsection Garbage in the Text
+
+ If @kbd{C-l} shows that the text is wrong, try undoing the changes to it
+using @kbd{C-x u} until it gets back to a state you consider correct. Also
+try @kbd{C-h l} to find out what command you typed to produce the observed
+results.
+
+ If a large portion of text appears to be missing at the beginning or
+end of the buffer, check for the word @samp{Narrow} in the mode line.
+If it appears, the text is still present, but marked off-limits.
+To make it visible again, type @kbd{C-x w}. @xref{Narrowing}.
+
+@node Unasked-for Search, Emergency Escape, Text Garbled, Lossage
+@subsection Spontaneous Entry to Incremental Search
+
+ If Emacs spontaneously displays @samp{I-search:} at the bottom of the
+screen, it means that the terminal is sending @kbd{C-s} and @kbd{C-q}
+according to the poorly designed @samp{xon/xoff} ``flow control''
+protocol. You should try to prevent this by putting the terminal in a
+mode where it will not use flow control or giving it enough padding
+that it will never send a @kbd{C-s}. If that cannot be done, you must
+tell Emacs to expect flow control to be used, until you can get a
+properly designed terminal.
+
+ Information on how to do these things can be found in the file
+@file{INSTALL} in the Emacs distribution.
+
+@node Emergency Escape, Total Frustration, Unasked-for Search, Lossage
+@subsection Emergency Escape
+
+ Because at times there have been bugs causing Emacs to loop without
+checking @code{quit-flag}, a special feature causes Emacs to be suspended
+immediately if you type a second @kbd{C-g} while the flag is already set,
+so you can always get out of GNU Emacs. Normally Emacs recognizes and
+clears @code{quit-flag} (and quits!) quickly enough to prevent this from
+happening.
+
+ When you resume Emacs after a suspension caused by multiple @kbd{C-g}, it
+asks two questions before going back to what it had been doing:
+
+@example
+Auto-save? (y or n)
+Abort (and dump core)? (y or n)
+@end example
+
+@noindent
+Answer each one with @kbd{y} or @kbd{n} followed by @key{RET}.
+
+ Saying @kbd{y} to @samp{Auto-save?} causes immediate auto-saving of all
+modified buffers in which auto-saving is enabled.
+
+ Saying @kbd{y} to @samp{Abort (and dump core)?} causes an illegal instruction to be
+executed, dumping core. This is to enable a wizard to figure out why Emacs
+was failing to quit in the first place. Execution does not continue
+after a core dump. If you answer @kbd{n}, execution does continue. With
+luck, GNU Emacs will ultimately check @code{quit-flag} and quit normally.
+If not, and you type another @kbd{C-g}, it is suspended again.
+
+ If Emacs is not really hung, just slow, you may invoke the double
+@kbd{C-g} feature without really meaning to. Then just resume and answer
+@kbd{n} to both questions, and you will arrive at your former state.
+Presumably the quit you requested will happen soon.
+
+ The double-@kbd{C-g} feature may be turned off when Emacs is running under
+a window system, since the window system always enables you to kill Emacs
+or to create another window and run another program.
+
+@node Total Frustration,, Emergency Escape, Lossage
+@subsection Help for Total Frustration
+@cindex Eliza
+@cindex doctor
+
+ If using Emacs (or something else) becomes terribly frustrating and none
+of the techniques described above solve the problem, Emacs can still help
+you.
+
+ First, if the Emacs you are using is not responding to commands, type
+@kbd{C-g C-g} to get out of it and then start a new one.
+
+@findex doctor
+ Second, type @kbd{M-x doctor @key{RET}}.
+
+ The doctor will make you feel better. Each time you say something to
+the doctor, you must end it by typing @key{RET} @key{RET}. This lets the
+doctor know you are finished.
+
+@node Bugs, Version 19, Lossage, Top
+@section Reporting Bugs
+
+@cindex bugs
+ Sometimes you will encounter a bug in Emacs. Although we cannot promise
+we can or will fix the bug, and we might not even agree that it is a bug,
+we want to hear about bugs you encounter in case we do want to fix them.
+
+ To make it possible for us to fix a bug, you must report it. In order
+to do so effectively, you must know when and how to do it.
+
+@subsection When Is There a Bug
+
+ If Emacs executes an illegal instruction, or dies with an operating
+system error message that indicates a problem in the program (as opposed to
+something like ``disk full''), then it is certainly a bug.
+
+ If Emacs updates the display in a way that does not correspond to what is
+in the buffer, then it is certainly a bug. If a command seems to do the
+wrong thing but the problem corrects itself if you type @kbd{C-l}, it is a
+case of incorrect display updating.
+
+ Taking forever to complete a command can be a bug, but you must make
+certain that it was really Emacs's fault. Some commands simply take a long
+time. Type @kbd{C-g} and then @kbd{C-h l} to see whether the input Emacs
+received was what you intended to type; if the input was such that you
+@var{know} it should have been processed quickly, report a bug. If you
+don't know whether the command should take a long time, find out by looking
+in the manual or by asking for assistance.
+
+ If a command you are familiar with causes an Emacs error message in a
+case where its usual definition ought to be reasonable, it is probably a
+bug.
+
+ If a command does the wrong thing, that is a bug. But be sure you know
+for certain what it ought to have done. If you aren't familiar with the
+command, or don't know for certain how the command is supposed to work,
+then it might actually be working right. Rather than jumping to
+conclusions, show the problem to someone who knows for certain.
+
+ Finally, a command's intended definition may not be best for editing
+with. This is a very important sort of problem, but it is also a matter of
+judgment. Also, it is easy to come to such a conclusion out of ignorance
+of some of the existing features. It is probably best not to complain
+about such a problem until you have checked the documentation in the usual
+ways, feel confident that you understand it, and know for certain that what
+you want is not available. If you are not sure what the command is
+supposed to do after a careful reading of the manual, check the index and
+glossary for any terms that may be unclear. If you still do not
+understand, this indicates a bug in the manual. The manual's job is to
+make everything clear. It is just as important to report documentation
+bugs as program bugs.
+
+ If the on-line documentation string of a function or variable disagrees
+with the manual, one of them must be wrong, so report the bug.
+
+@subsection How to Report a Bug
+
+@cindex version of Emacs
+@cindex Emacs version
+@findex emacs-version
+ When you decide that there is a bug, it is important to report it and to
+report it in a way which is useful. What is most useful is an exact
+description of what commands you type, starting with the shell command to
+run Emacs, until the problem happens. Always include the version number
+of Emacs that you are using; type @kbd{M-x emacs-version} to print this.
+
+ The most important principle in reporting a bug is to report @var{facts},
+not hypotheses or categorizations. It is always easier to report the facts,
+but people seem to prefer to strain to posit explanations and report
+them instead. If the explanations are based on guesses about how Emacs is
+implemented, they will be useless; we will have to try to figure out what
+the facts must have been to lead to such speculations. Sometimes this is
+impossible. But in any case, it is unnecessary work for us.
+
+ For example, suppose that you type @kbd{C-x C-f /glorp/baz.ugh
+@key{RET}}, visiting a file which (you know) happens to be rather large,
+and Emacs prints out @samp{I feel pretty today}. The best way to report
+the bug is with a sentence like the preceding one, because it gives all the
+facts and nothing but the facts.
+
+ Do not assume that the problem is due to the size of the file and say,
+``When I visit a large file, Emacs prints out @samp{I feel pretty today}.''
+This is what we mean by ``guessing explanations''. The problem is just as
+likely to be due to the fact that there is a @samp{z} in the file name. If
+this is so, then when we got your report, we would try out the problem with
+some ``large file'', probably with no @samp{z} in its name, and not find
+anything wrong. There is no way in the world that we could guess that we
+should try visiting a file with a @samp{z} in its name.
+
+ Alternatively, the problem might be due to the fact that the file starts
+with exactly 25 spaces. For this reason, you should make sure that you
+inform us of the exact contents of any file that is needed to reproduce the
+bug. What if the problem only occurs when you have typed the @kbd{C-x C-a}
+command previously? This is why we ask you to give the exact sequence of
+characters you typed since starting to use Emacs.
+
+ You should not even say ``visit a file'' instead of @kbd{C-x C-f} unless
+you @i{know} that it makes no difference which visiting command is used.
+Similarly, rather than saying ``if I have three characters on the line,''
+say ``after I type @w{@kbd{@key{RET} A B C} @key{RET} C-p},'' if that is
+the way you entered the text.
+
+ If you are not in Fundamental mode when the problem occurs, you should
+say what mode you are in.
+
+ If the manifestation of the bug is an Emacs error message, it is
+important to report not just the text of the error message but a backtrace
+showing how the Lisp program in Emacs arrived at the error. To make the
+backtrace, you must execute the Lisp expression
+@code{(setq @w{debug-on-error t})} before the error happens (that is to
+say, you must execute that expression and then make the bug happen). This
+causes the Lisp debugger to run (@pxref{Lisp Debug}). The debugger's
+backtrace can be copied as text into the bug report. This use of the
+debugger is possible only if you know how to make the bug happen again. Do
+note the error message the first time the bug happens, so if you can't make
+it happen again, you can report at least that.
+
+ Check whether any programs you have loaded into the Lisp world, including
+your @file{.emacs} file, set any variables that may affect the functioning
+of Emacs. Also, see whether the problem happens in a freshly started Emacs
+without loading your @file{.emacs} file (start Emacs with the @code{-q} switch
+to prevent loading the init file.) If the problem does @var{not} occur
+then, it is essential that we know the contents of any programs that you
+must load into the Lisp world in order to cause the problem to occur.
+
+ If the problem does depend on an init file or other Lisp programs that
+are not part of the standard Emacs system, then you should make sure it is
+not a bug in those programs by complaining to their maintainers first.
+After they verify that they are using Emacs in a way that is supposed to
+work, they should report the bug.
+
+ If you can tell us a way to cause the problem without visiting any files,
+please do so. This makes it much easier to debug. If you do need files,
+make sure you arrange for us to see their exact contents. For example, it
+can often matter whether there are spaces at the ends of lines, or a
+newline after the last line in the buffer (nothing ought to care whether
+the last line is terminated, but tell that to the bugs).
+
+@findex open-dribble-file
+@cindex dribble file
+ The easy way to record the input to Emacs precisely is to write a
+dribble file; execute the Lisp expression
+
+@example
+(open-dribble-file "~/dribble")
+@end example
+
+@noindent
+using @kbd{Meta-@key{ESC}} or from the @samp{*scratch*} buffer just after starting
+Emacs. From then on, all Emacs input will be written in the specified
+dribble file until the Emacs process is killed.
+
+@findex open-termscript
+@cindex termscript file
+ For possible display bugs, it is important to report the terminal type
+(the value of environment variable @code{TERM}), the complete termcap entry
+for the terminal from @file{/etc/termcap} (since that file is not identical
+on all machines), and the output that Emacs actually sent to the terminal.
+The way to collect this output is to execute the Lisp expression
+
+@example
+(open-termscript "~/termscript")
+@end example
+
+@noindent
+using @kbd{Meta-@key{ESC}} or from the @samp{*scratch*} buffer just
+after starting Emacs. From then on, all output from Emacs to the terminal
+will be written in the specified termscript file as well, until the Emacs
+process is killed. If the problem happens when Emacs starts up, put this
+expression into your @file{.emacs} file so that the termscript file will
+be open when Emacs displays the screen for the first time. Be warned:
+it is often difficult, and sometimes impossible, to fix a terminal-dependent
+bug without access to a terminal of the type that stimulates the bug.@refill
+
+ The address for reporting bugs is
+
+@format
+GNU Emacs Bugs
+Free Software Foundation
+675 Mass Ave
+Cambridge, MA 02139
+@end format
+
+@noindent
+or send email either to @samp{bug-gnu-emacs@@prep.ai.mit.edu} (Internet)
+or to @samp{uunet!prep.ai.mit.edu!bug-gnu-emacs} (Usenet).
+
+ Once again, we do not promise to fix the bug; but if the bug is serious,
+or ugly, or easy to fix, chances are we will want to.
+
+@node Version 19, Manifesto, Bugs, Top
+@unnumbered Version 19 Antenews
+
+This chapter prematurely describes new features of Emacs 19, in
+anticipation of its release. We have included this so that the version
+18 manuals don't become obsolete as soon as Emacs 19 comes out. This
+list mentions only features that would belong in @cite{The GNU Emacs
+Manual}; changes relevant to Emacs Lisp programming will be documented
+in the next revision of @cite{The GNU Emacs Lisp Manual}.
+
+@menu
+* Basic Changes:: Changes every user must know.
+* New Facilities:: Changes every user will want to know.
+* Binding Changes:: Ordinary commands that have been moved. Important!.
+* Changed Commands:: Ordinary commands that have new features. Important!
+* M-x Changes:: Changes in commands you run with @kbd{M-x}. Important!
+* New Commands:: Commands that have been added
+ that we expect many users to want to use.
+* Search Changes:: Changes in incremental search. Some are important.
+
+The rest of the changes you can pretty much ignore unless you are interested.
+
+* Filling Changes:: Changes in fill commands.
+* TeX Mode Changes:: Changes in the commands for editing TeX files
+ and running TeX.
+* Shell Changes:: Major changes in all the modes that run subprograms.
+* Spell Changes:: These commands now use ispell instead of spell.
+* Tags Changes:: Changes in Tags facility.
+* Mail Changes:: Changes in both Sendmail mode and Rmail mode.
+* Info Changes:: New commands in Info.
+* Dired Changes:: Powerful new features in Dired.
+* GNUS:: An alternative news reader.
+* Calendar/Diary:: The calendar feature now lets you move to different
+ dates and convert to and from other calendars.
+ You can also display related entries from your diary
+ file.
+* Version Control:: A convenient interface to RCS or SCCS.
+* Emerge:: A new feature for merging files interactively.
+* Debuggers:: Running debuggers (GDB, DBX, SDB) under Emacs.
+* Other New Modes:: Miscellaneous new and changed major modes.
+* Key Sequence Changes:: You can now bind key sequences that include function
+ keys and mouse clicks.
+* Hook Changes:: Hook variables have been renamed more systematically.
+@end menu
+
+@node Basic Changes
+@section Basic Changes
+
+We have made changes to help Emacs use fewer resources and make it less
+likely to become irreparably hung. While these changes don't alter the
+commands of Emacs, they are important enough to be worth mentioning.
+
+You can quit with @kbd{C-g} while Emacs is waiting to read or write a
+file---provided the operating system will allow you to interrupt the
+system call that is hung. (Unfortunately, most NFS implementations
+won't allow interruption.)
+
+When you kill buffers, Emacs now returns memory to the operating system,
+thus reducing the size of the Emacs process. The space that you free up
+by killing buffers can now be reused for other buffers no matter what
+their sizes, or reused by other processes if Emacs doesn't need it.
+
+@subheading Multiple X Windows
+
+When using X windows, you can now create more than one window at the X
+level. Each X window displays a @dfn{frame} which can contain one or
+several Emacs windows. Each frame has its own echo area and normally
+its own minibuffer. (To avoid confusion, we reserve the word
+``window'' for the subdivisions that Emacs implements, and never use
+it to refer to a frame.) The easiest way to create additional frames
+is with the @kbd{C-x 5} prefix character (@pxref{New Commands, , New
+Everyday Commands}).
+
+@c ??? Change not yet made
+@findex scroll-bar-mode @r{(V19)}
+Emacs windows can now have scroll bars; use the @code{scroll-bar-mode}
+command to turn scroll bars on or off. With no argument, it toggles the
+use of scroll bars. With an argument, it turns use of scroll bars on if
+and only if the argument is positive. This command applies to all
+frames, including frames yet to be created. (You can control scroll
+bars on a frame by frame basis by writing a Lisp program.)
+
+@subheading Undo Improvements
+
+@c ??? Change not yet made
+Undoing a deletion now puts the cursor position where it was just before
+the deletion.
+
+@subheading Auto Save Improvements
+
+@vindex auto-save-timeout @r{(V19)}
+Emacs now does garbage collection and auto saving while it is waiting
+for input, which often avoids the need to do these things while you are
+typing. The variable @code{auto-save-timeout} says how many seconds
+Emacs should wait, after you stop typing, before it does an auto save
+and perhaps also a garbage collection. (The actual time period varies
+also according to the size of the buffer---longer for longer buffers,
+since auto saving itself is slower for long buffers.) This way, Emacs
+does not interrupt or delay your typing.
+
+In Emacs 18, when auto saving detects that a buffer has shrunk greatly,
+it refrains from auto saving that buffer and displays a warning. In
+version 19, it also turns off Auto Save mode in that buffer, so that you
+won't get the same warning repeatedly. If you reenable Auto Save mode
+in that buffer, Emacs will start saving it again despite the shrinkage.
+
+@findex revert-buffer @r{(V19)}
+In Emacs 19, @code{revert-buffer} no longer offers to revert from the
+latest auto-save file. That option hasn't been very useful since the
+change to keep more undo information.
+
+The command @code{recover-file} no longer turns off Auto Save mode.
+
+@subheading File Local Variables
+
+@vindex enable-local-variables @r{(V19)}
+@vindex inhibit-local-variables @r{(V19)}
+The user option for controlling whether files can set local variables is
+called @code{enable-local-variables} in Emacs 19, rather than
+@code{inhibit-local-variables}. A value of @code{t} means
+local-variables lists are obeyed; @code{nil} means they are ignored;
+anything else means query the user.
+
+@node New Facilities
+@section New Basic Facilities
+
+@cindex minibuffer history
+@cindex history, in minibuffer
+@kindex M-p @r{(V19)}
+@kindex M-n @r{(V19)}
+@findex next-history-element @r{(V19)}
+@findex previous-history-element @r{(V19)}
+You can now get back recent minibuffer inputs conveniently. While in
+the minibuffer, type @kbd{M-p} (@code{previous-history-element}) to fetch
+the next earlier minibuffer input, and use @kbd{M-n}
+(@code{next-history-element}) to fetch the next later input.
+
+@findex previous-matching-history-element @r{(V19)}
+@findex next-matching-history-element @r{(V19)}
+@kindex M-r @r{(V19)}
+@kindex M-s @r{(V19)}
+There are also commands to search forward or backward through the
+history. As of this writing, they search for history elements that
+match a regular expression that you specify with the minibuffer.
+@kbd{M-r} (@code{previous-matching-history-element}) searches older
+elements in the history, while @kbd{M-s}
+(@code{next-matching-history-element}) searches newer elements. By
+special dispensation, these commands can always use the minibuffer to
+read their arguments even though you are already in the minibuffer when
+you issue them.
+
+We may have changed the precise way these commands work by the time you
+use Emacs 19. Perhaps they will search for a match for the string given
+so far in the minibuffer; perhaps they will search for a literal match
+rather than a regular expression match; perhaps they will only accept
+matches at the beginning of a history element; perhaps they will read
+the string to search for incrementally like @kbd{C-s}. We want to
+choose an interface that is convenient, flexible and natural, and these
+goals are somewhat contradictory. To find out what interface is
+actually available, type @kbd{C-h f previous-matching-history-element}.
+
+The history feature is available for all uses of the minibuffer, but
+there are separate history lists for different kinds of input. For
+example, there is a list for file names, used by all the commands that
+read file names. There is a list for arguments of commands like
+@code{query-replace}. There are also very specific history lists, such
+as the one that @code{compile} uses for compilation commands.
+
+@subheading Remote File Access
+
+@cindex ftp
+@cindex remote file access
+You can refer to files on other machines using a special file name syntax:
+
+@example
+@group
+/@var{host}:@var{filename}
+/@var{user}@@@var{host}:@var{filename}
+@end group
+@end example
+
+When you do this, Emacs uses the FTP program to read and write files on
+the specified host. It logs in through FTP using your user name or the
+name @var{user}. It may ask you for a password from time to time; this
+is used for logging in on @var{host}.
+
+@subheading Using Flow Control
+
+@cindex flow control in V19
+@cindex xon-xoff in V19
+There is now a convenient way to enable flow control when your terminal
+or your connection won't work without it. Suppose you want to do this
+on VT-100 and H19 terminals; put the following in your @file{.emacs}
+file:
+
+@findex evade-flow-control-on @r{(V19)}
+@example
+(evade-flow-control-on "vt100" "h19")
+@end example
+
+When flow control is enabled, you must type @kbd{C-\} to get the effect
+of a @kbd{C-s}, and type @kbd{C-^} to get the effect of a @kbd{C-q}.
+
+@subheading Controlling Backup File Names
+
+@vindex version-control @r{(V19)}
+@vindex VERSION_CONTROL
+The default setting of the Lisp variable @code{version-control} now
+comes from the environment variable @code{VERSION_CONTROL}. Thus, you
+can select a style of backup file naming for Emacs and other GNU
+utilities all together.
+
+@node Binding Changes
+@section Changed Key Bindings
+
+@table @kbd
+@item M-@{
+@kindex M-@{ @r{(V19)}
+This is the new key sequence for @code{backward-paragraph}. The old key
+sequence for this, @kbd{M-[}, is now undefined by default.
+
+The reason for this change is to avoid conflict with the sequences that
+function keys send on most terminals.
+
+@item M-@}
+@kindex M-@} @r{(V19)}
+This is the new key sequence for @code{forward-paragraph}. The old key
+sequence for this, @kbd{M-]}, is now undefined by default.
+
+We changed this to go along with @kbd{M-@{}.
+
+@item C-x C-u
+@itemx C-x C-l
+@kindex C-x C-u @r{(V19)}
+@kindex C-x C-l @r{(V19)}
+The two commands, @kbd{C-x C-u} (@code{upcase-region}) and @kbd{C-x
+C-l} (@code{downcase-region}), are now disabled by default; these
+keys seem to be often hit by accident, and can be quite
+destructive if their effects are not noticed immediately.
+
+@item C-x 3
+@kindex C-x 3 @r{(V19)}
+@kbd{C-x 3} is now the key binding for @code{split-window-horizontally},
+which splits a window into two side-by-side windows. This used to be
+@kbd{C-x 5}.
+
+@item @kbd{C-x 4 C-o}
+@kindex C-x 4 C-o @r{(V19)}
+@findex display-buffer @r{(V19)}
+This key now runs @code{display-buffer}, which displays a specified
+buffer in another window without selecting it.
+
+@item M-g
+@kindex M-g @r{(V19)}
+@kbd{M-g} is now undefined. It used to run the command @code{fill-region}.
+This command used to be run more often by mistake than on purpose.
+
+@item C-x a
+@itemx C-x n
+@itemx C-x r
+@kindex C-x a @r{(V19)}
+@kindex C-x n @r{(V19)}
+@kindex C-x r @r{(V19)}
+Three new prefix keys have been created to make many of the @w{@kbd{C-x}}
+commands more systematic: @w{@kbd{C-x a}}, @w{@kbd{C-x n}} and @w{@kbd{C-x r}}.
+@w{@kbd{C-x a}} is used for abbreviation commands, @w{@kbd{C-x n}} for commands
+pertaining to narrowing, and @w{@kbd{C-x r}} for register and rectangle
+commands. These are the new bindings, in detail:
+
+@table @kbd
+@item C-x a l
+@code{add-mode-abbrev} (previously @kbd{C-x C-a}).
+@item C-x a g
+@code{add-global-abbrev} (previously @kbd{C-x +}).
+@item C-x a i g
+@code{inverse-add-mode-abbrev} (previously @kbd{C-x C-h}).
+@item C-x a i l
+@code{inverse-add-global-abbrev} (previously @kbd{C-x -}).
+@item C-x a e
+@code{expand-abbrev} (previously @kbd{C-x '}).
+
+@sp 1
+
+@item C-x n n
+@code{narrow-to-region} (previously @kbd{C-x n}).
+@item C-x n p
+@code{narrow-to-page} (previously @kbd{C-x p}).
+@item C-x n w
+@code{widen} (previously @kbd{C-x w}).
+
+@sp 1
+
+@item C-x r C-@key{SPC}
+@code{point-to-register} (previously @kbd{C-x /}).
+@item C-x r @key{SPC}
+Also @code{point-to-register} (previously @kbd{C-x /}).
+@item C-x r j
+@code{jump-to-register} (previously @kbd{C-x j}).
+@item C-x r s
+@code{copy-to-register} (previously @kbd{C-x x}).
+@item C-x r i
+@code{insert-register} (previously @kbd{C-x g}).
+@item C-x r r
+@code{copy-rectangle-to-register} (previously @kbd{C-x r}).
+@item C-x r k
+@code{kill-rectangle} (no previous key binding).
+@item C-x r y
+@code{yank-rectangle} (no previous key binding).
+@item C-x r o
+@code{open-rectangle} (no previous key binding).
+@item C-x r f
+@code{frame-configuration-to-register} (a new command)
+saves the state of all windows in all frames.
+Use @kbd{C-x r j} to restore the configuration.
+@c !!! following generates acceptable underfull hbox
+@item C-x r w
+@code{window-configuration-to-register} (a new command)
+saves the state of all windows in the selected frame.
+Use @kbd{C-x r j} to restore the configuration.
+@end table
+
+The old key bindings @kbd{C-x /}, @kbd{C-x j}, @kbd{C-x x} and @kbd{C-x
+g} have not yet been removed. The other old key bindings listed have
+been removed. The old key binding @kbd{C-x a}, which was
+@code{append-to-buffer}, was removed to make way for a prefix key; now
+@code{append-to-buffer} has no keybinding.
+
+@item C-x v
+@kbd{C-x v} is a new prefix character, used for version control commands.
+@xref{Version Control}.
+@end table
+
+@node Changed Commands
+@section Changed Everyday Commands
+
+@table @kbd
+@item C-o
+@kindex C-o @r{(V19)}
+When you have a fill prefix, the command @kbd{C-o} inserts the prefix on
+the newly created line.
+
+@item M-^
+@kindex M-^ @r{(V19)}
+When you have a fill prefix, the command @kbd{M-^} deletes the prefix
+(if it occurs) after the newline that it deletes.
+
+@item M-z
+@kindex M-z @r{(V19)}
+The @kbd{M-z} command (@code{zap-to-char}) now kills through the target
+character. In version 18, it killed up to but not including the target
+character.
+
+@item M-!
+@kindex M-! @r{(V19)}
+The command @kbd{M-!} (@code{shell-command}) now runs the specified
+shell command asynchronously if it ends in @samp{&}, just as the shell
+does.
+
+@item C-x 2
+@kindex C-x 2 @r{(V19)}
+@vindex split-window-keep-point @r{(V19)}
+The @kbd{C-x 2} command (@code{split-window-vertically}) now tries to
+avoid scrolling by putting point in whichever window happens to contain
+the screen line the cursor is already on. If you don't like this, you
+can turn it off by setting @code{split-window-keep-point} to
+@code{nil}.
+
+@item C-x s
+@kindex C-x s @r{(V19)}
+The @kbd{C-x s} command (@code{save-some-buffers}) now gives you more
+options when it asks whether to save a particular buffer. The options
+are analogous to those of @code{query-replace}. Here they are:
+
+@table @kbd
+@item y
+Save this buffer and ask about the rest of the buffers.
+@item n
+Don't save this buffer, but ask about the rest of the buffers.
+@item !
+Save this buffer and all the rest with no more questions.
+@c !!! following generates acceptable underfull hbox
+@item @key{ESC}
+Terminate @code{save-some-buffers} without any more saving.
+@item .
+@c !!! following written verbosely to avoid overfull hbox
+Save only this buffer, then exit @code{save-some-buffers} without even asking
+about other buffers.
+@item C-r
+View the buffer that you are currently being asked about. When you exit
+View mode, you get back to @code{save-some-buffers}, which asks the
+question again.
+@item C-h
+Display a help message about these options.
+@end table
+
+@item C-x C-v
+@kindex C-x C-v @r{(V19)}
+This command (@kbd{find-alternate-file}) now inserts the entire current
+file name in the minibuffer. This is convenient if you made a small
+mistake in typing it. Point goes after the last slash, before the last
+file name component, so if you want to replace it entirely, you can use
+@kbd{C-k} right away to delete it.
+
+@item C-M-f
+@kindex C-M-f @r{(V19)}
+Expression and list commands such as @kbd{C-M-f} now ignore parentheses
+within comments in Lisp mode.
+@end table
+
+@node M-x Changes
+@section Changes in Common @kbd{M-x} Commands
+
+@table @asis
+@item @kbd{M-x make-symbolic-link}
+@findex make-symbolic-link @r{(V19)}
+This command now does not expand its second argument. This lets you
+make a link with a target that is a relative file name.
+
+@item @kbd{M-x add-change-log-entry}
+@itemx @kbd{C-x 4 a}
+@findex add-change-log-entry @r{(V19)}
+@kindex C-x 4 a @r{(V19)}
+These commands now automatically insert the name of the file and often
+the name of the function that you changed. They also handle grouping of
+entries.
+
+There is now a special major mode for editing @file{ChangeLog} files.
+It makes filling work conveniently. Each bunch of grouped entries is
+one paragraph, and each collection of entries from one person on one day
+is considered a page.
+
+@item @kbd{M-x compare-windows}
+@findex compare-windows @r{(V19)}
+With a prefix argument, @code{compare-windows} ignores changes in
+whitespace. If the variable @code{compare-ignore-case} is
+non-@code{nil}, it ignores differences in case as well.
+
+@item @kbd{M-x view-buffer}
+@itemx @kbd{M-x view-file}
+@findex view-buffer @r{(V19)}
+@findex view-file @r{(V19)}
+The View commands (such as @kbd{M-x view-buffer} and @kbd{M-x
+view-file}) no longer use recursive edits; instead, they switch
+temporarily to a different major mode (View mode) specifically designed
+for moving around through a buffer without editing it.
+
+@item @kbd{M-x manual-entry}
+@findex manual-entry @r{(V19)}
+@kbd{M-x manual-entry} now uses View mode for the buffer showing the
+man page.
+
+@item @kbd{M-x compile}
+@findex compile @r{(V19)}
+You can repeat any previous @code{compile} conveniently using the
+minibuffer history commands, while in the minibuffer entering the
+compilation command.
+
+While a compilation is going on, the string @samp{Compiling} appears
+in the mode line. When this string disappears, the compilation is
+finished.
+
+The buffer of compiler messages is in Compilation mode. This mode
+provides the keys @key{SPC} and @key{DEL} to scroll by screenfuls, and
+@kbd{M-n} and @kbd{M-p} to move to the next or previous error message.
+You can also use @kbd{M-@{} and @kbd{M-@}} to move up or down to an
+error message for a different source file. Use @kbd{C-c C-c} on any
+error message to find the corresponding source code.
+
+Emacs 19 has a more general parser for compiler messages. For example, it
+can understand messages from lint, and from certain C compilers whose
+error message format is unusual.
+@end table
+
+@node New Commands
+@section New Everyday Commands
+
+@table @asis
+@item @kbd{C-z}
+@kindex C-z @r{(V19)}
+@findex iconify-frame @r{(V19)}
+When you are using X windows, @kbd{C-z} (@code{iconify-frame}) now
+iconifies the current frame.
+
+@item @kbd{C-M-l}
+@kindex C-M-l @r{(V19)}
+@findex reposition-window @r{(V19)}
+The @kbd{C-M-l} command (@code{reposition-window}) scrolls the current
+window heuristically in a way designed to get useful information onto
+the screen. For example, in a Lisp file, this command tries to get the
+entire current defun onto the screen if possible.
+
+@item @kbd{C-M-r}
+@kindex C-M-r @r{(V19)}
+@findex isearch-backward-regexp @r{(V19)}
+@c !!! following written verbosely to avoid overfull hbox
+The @kbd{C-M-r} key now runs the command @code{isearch-backward-regexp},
+which does reverse incremental regexp search.
+
+@item @kbd{C-x 5}
+@kindex C-x 5 @r{(V19)}
+The prefix key @kbd{C-x 5} is analogous to @kbd{C-x 4}, with parallel
+subcommands. The difference is that @kbd{C-x 5} commands create a new
+frame rather than just a new window.
+
+@item @kbd{C-x 5 C-f}
+@itemx @kbd{C-x 5 b}
+@kindex C-x 5 C-f @r{(V19)}
+@kindex C-x 5 b @r{(V19)}
+@findex find-file-other-frame @r{(V19)}
+@findex switch-to-buffer-other-frame @r{(V19)}
+These new commands switch to a specified file or buffer in a new frame
+(when using X windows). The commands' names are
+@code{find-file-other-frame} and @code{switch-to-buffer-other-frame}.
+
+@item @kbd{C-x 5 m}
+@kindex C-x 5 m @r{(V19)}
+@findex mail-other-frame @r{(V19)}
+Start outgoing mail in another frame (@code{mail-other-frame}).
+
+@item @kbd{C-x 5 .}
+@kindex C-x 5 . @r{(V19)}
+@findex find-tag-other-frame @r{(V19)}
+Find a tag in another frame (@code{find-tag-other-frame}).
+
+@item @kbd{C-x 4 r}
+@kindex C-x 4 r @r{(V19)}
+@findex find-file-read-only-other-window @r{(V19)}
+This is now @code{find-file-read-only-other-window}.
+
+@item arrow keys
+@cindex arrow keys
+The arrow keys now have default bindings to move in the appropriate
+directions.
+
+@item @kbd{C-h C-f}
+@itemx @kbd{C-h C-k}
+@kindex C-h C-f @r{(V19)}
+@kindex C-h C-k @r{(V19)}
+These new help commands enter Info and display the node for a given
+Emacs function name or key sequence, respectively.
+
+@item @kbd{M-a}
+@itemx @kbd{M-e}
+@kindex M-a @r{(C mode in V19)}
+@kindex M-e @r{(C mode in V19)}
+@findex c-beginning-of-statement @r{(V19)}
+@findex c-end-of-statement @r{(V19)}
+In C mode, @kbd{M-a} and @kbd{M-e} now move by complete C statements
+(@code{c-beginning-of-statement} and @code{c-end-of-statement}).
+
+@item @kbd{M-q}
+@kindex M-q @r{(C mode in V19)}
+@findex c-fill-paragraph @r{(V19)}
+@kbd{M-q} in C mode now runs @code{c-fill-paragraph}, which is designed
+for filling C comments. (We assume you don't want to fill the actual C
+code in a C program.)
+
+@item @kbd{M-x c-up-conditional}
+@findex c-up-conditional @r{(V19)}
+In C mode, @code{c-up-conditional} moves back to the containing
+preprocessor conditional, setting the mark where point was previously.
+
+A prefix argument acts as a repeat count. With a negative argument,
+this command moves forward to the end of the containing preprocessor
+conditional. When going backwards, @samp{#elif} acts like @samp{#else}
+followed by @samp{#if}. When going forwards, @samp{#elif} is ignored.
+
+@item @kbd{M-x comment-region}
+@findex comment-region @r{(V19)}
+The @code{comment-region} command adds comment delimiters to the lines
+that start in the region, thus commenting them out. With a negative
+argument, it deletes comment delimiters from the lines in the
+region---this is the inverse of the effect of @code{comment-region}
+without an argument.
+
+With a positive argument, @code{comment-region} adds comment delimiters
+but duplicates the last character of the comment start sequence as many
+times as the argument specifies. This is a way of calling attention to
+the comment. In Lisp, you should use an argument of at least two, because
+the indentation convention for single semicolon comments does not leave
+them at the beginning of a line.
+
+@item @kbd{M-x super-apropos}
+@findex super-apropos @r{(V19)}
+This command is like @code{apropos} except that it searches for a
+regular expression instead of merely a substring.
+
+@findex apropros @r{(V19)}
+@kindex C-h a @r{(V19)}
+If you use a prefix argument (regardless of its value) with
+@code{apropos} or @code{super-apropos}, they also search documentation
+strings for matches as well as symbol names. The prefix argument also
+controls looking up and printing the key bindings of all commands.
+
+@item @kbd{M-x diff}
+@findex diff @r{(V19)}
+@vindex diff-switches @r{(V19)}
+This new command compares two files, displaying the differences in an
+Emacs buffer. The options for the @code{diff} program come from the
+variable @code{diff-switches}, whose value should be a string.
+
+The buffer of differences has Compilation mode as its major mode, so you
+can use @kbd{C-x `} to visit successive changed locations in the two
+source files, or you can move to a particular hunk of changes and type
+@kbd{C-c C-c} to move to the corresponding source. You can also use the
+other special commands of Compilation mode: @key{SPC} and @key{DEL} for
+scrolling, and @kbd{M-p} and @kbd{M-n} for cursor motion.
+
+@item @kbd{M-x diff-backup}
+@findex diff-backup @r{(V19)}
+The command @code{diff-backup} compares a specified file with its most
+recent backup. If you specify the name of a backup file,
+@code{diff-backup} compares it with the source file that it is a backup
+of.
+@end table
+
+@node Search Changes
+@section Changes in Incremental Search
+
+The most important change in incremental search is that @key{RET} now
+terminates a search, and @key{ESC} does not. The other changes are
+useful, but not vital to know about.
+
+@cindex Incremental search in V19
+@findex isearch @r{(V19)}
+@itemize @bullet
+@item
+The character to terminate an incremental search is now @key{RET}. This
+is for compatibility with the way most other arguments are read.
+
+To search for a newline in an incremental search, type @key{LFD} (also
+known as @kbd{C-j}).
+
+(This change is somewhat of an experiment; it might be taken back by
+the time Emacs 19 is really released.)
+
+@item
+Incremental search now maintains a ring of previous search strings. Use
+@kbd{M-p} and @kbd{M-n} to move through the ring to pick a search string
+to reuse. These commands leave the selected search ring element in the
+minibuffer, where you can edit it. Type @key{RET} to finish editing and
+search for the chosen string.
+
+@item
+When there is an upper-case letter in the search
+string, then the search is case sensitive.
+
+@item
+Incremental search is now implemented as a major mode. When you type
+@kbd{C-s}, it switches temporarily to a different keymap which defines
+each key to do what it ought to do for incremental search. This has
+next to no effect on the user-visible behavior of searching, but makes
+it easier to customize that behavior.
+@end itemize
+
+@node Filling Changes
+@section Changes in Fill Commands
+
+@itemize @bullet
+@item
+@findex fill-individual-paragraphs @r{(V19)}
+@code{fill-individual-paragraphs} now has two modes. Its default mode
+is that any change in indentation starts a new paragraph. The alternate
+mode is that only separator lines separate paragraphs; this can handle
+paragraphs with extra indentation on the first line. To select the
+alternate mode, set @code{fill-individual-varying-indent} to a
+non-@code{nil} value.
+
+@item
+@cindex Adaptive Fill mode
+@findex fill-region-as-paragraph @r{(V19)}
+Filling is now partially controlled by a new minor mode, Adaptive Fill
+mode. When this mode is enabled (and it is enabled by default), if you
+use @code{fill-region-as-paragraph} on an indented paragraph and you
+don't have a fill prefix, it uses the indentation of the second line of
+the paragraph as the fill prefix.
+
+Adaptive Fill mode doesn't have much effect on @kbd{M-q} in most major
+modes, because an indented line will probably count as a paragraph
+starter and thus each line of an indented paragraph will be considered
+a paragraph of its own.
+
+@item
+@kindex M-q @r{(C mode in V19)}
+@findex c-fill-paragraph @r{(V19)}
+@kbd{M-q} in C mode now runs @code{c-fill-paragraph}, which is designed
+for filling C comments. (We assume you don't want to fill the actual C
+code in a C program.)
+@end itemize
+
+@node TeX Mode Changes
+@section Changes in @TeX{} Mode
+
+@cindex Tex mode in V19
+@kindex C-c @{ @r{(TeX mode in V19)}
+@kindex C-c @} @r{(TeX mode in V19)}
+The old @TeX{} mode bindings of @kbd{M-@{} and @kbd{M-@}} have been
+moved to @kbd{C-c @{} and @kbd{C-c @}}. (These commands are
+@code{up-list} and @code{tex-insert-braces}; they are the @TeX{}
+equivalents of @kbd{M-(} and @kbd{M-)}.)
+
+@c !!! following generates acceptable underfull hbox
+@kindex C-c C-e @r{(TeX mode in V19)}
+@kindex C-c C-o @r{(TeX mode in V19)}
+@findex tex-latex-block @r{(V19)}
+@findex tex-close-latex-block @r{(V19)}
+The new command @kbd{C-c C-o} (@code{tex-latex-block}) inserts a
+matching @samp{\begin}--@samp{\end} pair. The new command @kbd{C-c C-e}
+(@code{tex-close-latex-block}) inserts a matching @samp{\end} for the
+last unterminated @samp{\begin}.
+
+@kindex C-c @key{TAB} @r{(TeX mode in V19)}
+@findex tex-bibtex-file @r{(V19)}
+You can run Bib@TeX{} on the current file using @kbd{C-c @key{TAB}}
+(@code{tex-bibtex-file}).
+
+@kindex C-c C-v @r{(TeX mode in V19)}
+@findex tex-view @r{(V19)}
+There is a new command @kbd{C-c C-v} (@code{tex-view}) for running a
+DVI previewer.
+
+@vindex tex-directory @r{(V19)}
+You can specify the directory to use for running @TeX{} by setting the
+variable @code{tex-directory}. @code{"."} is the default value. If
+your environment variable @code{TEXINPUTS} contains relative directory
+names, or if your files contains @samp{\input} commands with relative
+file names, then @code{tex-directory} @emph{must} be @code{"."} or you
+will get the wrong results. Otherwise, it is safe to specify some other
+directory, such as @file{/tmp}.
+
+There is now a third variant of @TeX{} mode, for Sli@TeX{}. This is in
+addition to the variants for plain @TeX{} and La@TeX{}. As before, the
+correct variant is chosen automatically when you visit a file.
+
+@node Shell Changes
+@section Changes in Shell Mode
+
+@cindex Shell mode in V19
+Shell mode has been completely replaced with a new implementation.
+The basic idea is the same: Emacs runs a subshell, and all input
+and output to the subshell go through the shell buffer. But the
+special commands of Shell mode have been redesigned.
+
+@table @kbd
+@item @key{TAB}
+@kindex @key{TAB} @r{(Shell mode in V19)}
+@findex comint-dynamic-complete @r{(V19)}
+Complete the file name before point in the shell buffer
+(@code{comint-dynamic-complete}).
+
+@item M-?
+@kindex M-? @r{(Shell mode in V19)}
+@findex comint-dynamic-list-completions @r{(V19)}
+To get a list of all possible completions of the file name before, type
+@kbd{M-?} (@code{comint-dynamic-list-completions}).
+
+@item M-p
+@itemx M-n
+@kindex M-p @r{(Shell mode in V19)}
+@kindex M-n @r{(Shell mode in V19)}
+@findex comint-next-input @r{(V19)}
+@findex comint-previous-input @r{(V19)}
+There is a new convenient history mechanism for repeating previous
+shell inputs. Use the command @kbd{M-p} (@code{comint-previous-input}) to
+recall the last input; it copies the text of that input to the place
+where you are editing. If you repeat @w{@kbd{M-p}}, it replaces the copied
+input with successively earlier inputs. @kbd{M-n} is similar but goes in the
+opposite direction, towards the present (@code{comint-next-input}).
+
+When you find the previous input you want, you can resubmit it by typing
+@key{RET}, or you can edit it first and then resubmit it if you wish.
+
+These shell history commands operate outside the minibuffer, but they
+are completely analogous to the minibuffer history commands.
+
+@item M-r
+@itemx M-s
+@kindex M-r @r{(Shell mode in V19)}
+@kindex M-s @r{(Shell mode in V19)}
+@findex comint-previous-matching-input @r{(V19)}
+@findex comint-next-matching-input @r{(V19)}
+You can also use @kbd{M-r} and @kbd{M-s} to search for (respectively)
+earlier or later inputs starting with a given string. First type the
+string, then type @kbd{M-r} (@code{comint-previous-matching-input}) to
+yank a previous input from the history which starts with that string.
+You can repeat @kbd{M-r} to find successively earlier inputs starting
+with the same string.
+
+You can start moving in the opposite direction (toward more recent
+inputs) by typing @kbd{M-s} (@code{comint-next-matching-input}) instead
+of @kbd{M-r}. As long as you don't use any commands except @kbd{M-r}
+and @kbd{M-s}, they keep using the same string that you had entered
+initially.
+
+These commands serve a purpose similar to that of @kbd{M-r} and
+@kbd{M-s} in the minibuffer, but do not work in quite the same way. We
+may change the interface of these commands, as well as that of the
+analogous minibuffer commands; one goal will be to make the two sets of
+commands compatible. But we haven't yet figured out which of the
+possible interfaces is best. To find out what interface is actually
+supported in Emacs 19, type @kbd{C-h f comint-previous-matching-input
+@key{RET}}.
+
+@item C-c C-o
+@kindex C-c C-o @r{(Shell mode in V19)}
+@findex comint-kill-output @r{(V19)}
+Kill the last batch of output from a shell command
+(@code{comint-kill-output}). This is useful if a shell command spews
+out lots of output that just gets in the way.
+
+@item C-c C-r
+@kindex C-c C-r @r{(Shell mode in V19)}
+@findex comint-show-output @r{(V19)}
+Scroll to display the
+beginning of the last batch of output at the top of the window; it also
+moves the cursor there (@code{comint-show-output}).
+
+@item C-a
+@kindex C-a @r{(Shell mode in V19)}
+If you type @kbd{C-a} on a line that starts with a shell prompt, it
+moves to the end of the prompt, not to the very beginning of the line.
+
+@item C-d
+@kindex C-d @r{(Shell mode in V19)}
+Typed at the end of the shell buffer, @kbd{C-d} sends EOF to the
+subshell. Typed at any other position in the buffer, @kbd{C-d}
+deletes a character as usual.
+
+@item M-x dirs
+@findex dirs @r{(V19)}
+If Emacs gets confused while trying to track changes in the shell's
+current directory, type @kbd{M-x dirs} to re-synchronize.
+
+@item M-x send-invisible
+@findex send-invisible @r{(V19)}
+This command reads a line of text without echoing it, and sends it to
+the shell.
+
+@item M-x comint-continue-subjob
+@findex comint-continue-subjob @r{(V19)}
+If you accidentally suspend your process, use this command to continue it.
+@end table
+
+@node Spell Changes
+@section Changes in Spell Checking
+
+@cindex Spell checking in V19
+@cindex @code{ispell} program @r{(V19)}
+@findex kill-ispell @r{(V19)}
+Emacs 19 uses the Ispell program for spelling correction instead of the
+Unix spell program. Ispell has many advantages; one is that it can be
+started the first time you check a word, and left running thereafter,
+which makes further checking much faster. If you want to get rid of the
+Ispell process, use @kbd{M-x kill-ispell}.
+
+@findex ispell-buffer @r{(V19)}
+@findex ispell-region @r{(V19)}
+To check the entire current buffer, use @kbd{M-x ispell-buffer}. Use
+@kbd{M-x ispell-region} to check just the current region.
+
+@kindex M-$ @r{(V19)}
+Ispell commands often involve interactive replacement of words.
+You can interrupt the interactive replacement with @kbd{C-g}.
+You can restart it again afterward with @kbd{C-u M-$}.
+
+Interactive replacement shows you one misspelling at a time and asks you
+what to do. To answer, type one of the following characters:
+
+@table @kbd
+@item @var{digit}
+Replace the word (this time) with one of the displayed near-misses.
+The digit you use says which near-miss to use.
+
+@item a
+Accept this word this time.
+
+@item i
+Insert this word in your private dictionary
+so that Ispell will consider it correct it from now on.
+
+@item r
+Replace the word this time with a string typed by you.
+@end table
+
+When the Ispell process starts, it reads your private dictionary which
+is the file @file{~/ispell.words}. Words that you ``insert'' with the
+@kbd{i} command are added to that file, but not right away---only at the
+end of the interactive replacement procedure.
+
+@c !!! Written verbosely to avoid overfull hbox.
+@findex reload-ispell @r{(V19)}
+Use the @kbd{M-x reload-ispell} command
+to reload your private dictionary from
+@file{~/ispell.words} if you edit the file outside of Ispell.
+
+@node Mail Changes
+@section Changes in Mail Reading and Sending
+
+@cindex Mail mode in V19
+@samp{%} is now a word-separator character in Mail mode. This is because
+that character frequently appears in addresses.
+
+@vindex mail-signature @r{(V19)}
+If you set the variable @code{mail-signature} non-@code{nil}, then
+@code{mail} inserts the contents of your @file{.signature} file
+automatically when it initializes a mail buffer. If you don't want your
+signature in a particular message, just delete it from the buffer before
+you send the message.
+
+@vindex mail-yank-prefix @r{(V19)}
+You can specify the text to insert at the beginning of each line when
+you use @kbd{C-c C-y} to yank the message you are replying to. Set
+@code{mail-yank-prefix} to the desired string. A value of @code{nil}
+(the default) means to use indentation, as in Emacs 18. If you use
+@kbd{C-u} by itself as the prefix argument to @kbd{C-c C-y}, then it
+does not insert anything at the beginning of the lines, regardless of
+the value of @code{mail-yank-prefix}.
+
+@findex unrmail
+You can easily convert an Rmail file to system mailbox format with the
+command @code{unrmail}. This command reads two arguments, the name of
+the Rmail file to convert, and the name of the new mailbox file.
+The Rmail file is unchanged by this command.
+
+@cindex Rmail in V19
+Rmail now initially positions you at the first message in the Rmail file
+that you have not seen. This may not be a message that just arrived; it
+may have arrived in a previous session during which you did not select
+it. You can then read all the unseen messages going forwards.
+
+@kindex C-M-m @r{(Rmail in V19)}
+@findex rmail-retry-failure @r{(V19)}
+When a message that you sent ``bounces'' back to you, you can retry
+sending it by typing @kbd{C-M-m} (@code{rmail-retry-failure}) on the
+failure message.
+
+@findex rmail-resend @r{(V19)}
+By contrast, the new command @kbd{M-x rmail-resend} is used for
+forwarding a message and marking it as ``resentby'' you,
+with the special header fields @samp{Resent-by:} and @samp{Resent-to:}.
+
+@kindex < @r{(Rmail in V19)}
+Another new Rmail command is @kbd{<}, which moves to the first message.
+(This is for symmetry with @kbd{>}.) @kbd{<} is actually an alias for
+@kbd{j}.
+
+@kindex e @r{(Rmail in V19)}
+@kindex x @r{(Rmail in V19)}
+@c !!!! overfull hbox cured by ugly change
+@kbd{e} (@code{rmail-edit-current-message}) is now the command
+to edit a message. To expunge, type @kbd{x}. We know
+this will surprise people some of the time, but the surprise will not be
+disastrous---if you type @kbd{e} meaning to expunge, just type @kbd{C-c
+C-c} to leave Rmail Edit mode, and then type @kbd{x}.
+
+@vindex rmail-output-file-alist
+The variable @code{rmail-output-file-alist} now controls the default
+for the file to output a message to.
+
+@kindex C-n @r{(Rmail summary in V19)}
+@kindex C-p @r{(Rmail summary in V19)}
+@kindex M-n @r{(Rmail summary in V19)}
+@kindex M-p @r{(Rmail summary in V19)}
+@kindex p @r{(Rmail summary in V19)}
+@kindex n @r{(Rmail summary in V19)}
+In the Rmail summary, @kbd{C-n} and @kbd{C-p} are now ordinary cursor
+motion commands. To move in the summary @emph{and} select a new
+message, use @kbd{n} and @kbd{p} (which skip deleted messages) or
+@kbd{M-n} and @kbd{M-p} (which stop at all messages). These are, of
+course, the same commands you would use in the Rmail buffer.
+
+@node Tags Changes
+@section Changes in Tags Commands
+
+@cindex tags in V19
+@kindex M-. @r{(V19)}
+@kbd{M-.} (@code{find-tag}) and the other commands to find a tag now
+look first for an exact match in the tags table, and try substring
+matches only afterward.
+
+Another change in @kbd{M-.} is that it has no effect on what @kbd{M-,}
+will do subsequently. You can no longer use @kbd{M-,} to find the next
+similar tag; instead, use @kbd{M-.} with a prefix argument.
+
+@findex find-tag-regexp @r{(V19)}
+The new command @code{find-tag-regexp} successively visits the tags that
+match a specified regular expression.
+
+You can now use more than one tags table. Using @code{visit-tags-table}
+to load a new tags table does not discard the other tables previously
+loaded. The other tags commands use all the tags tables that are
+loaded; the first one they use is the one that mentions the current
+visited file.
+
+You can specify a precise list of tags tables by setting the variable
+@code{tags-table-list} to a list of strings, like this:
+
+@c keep this on two lines for formatting in smallbook
+@example
+@group
+(setq tags-table-list
+ '("~/emacs" "/usr/local/lib/emacs/src"))
+@end group
+@end example
+
+@noindent
+This tells @code{find-tag} to look at the @file{TAGS} files in your
+@file{~/emacs} directory and in the @file{/usr/local/lib/emacs/src}
+directory. The order depends on which file you are in and which tags
+table mentions that file, as explained above.
+
+@kindex M-@key{TAB} @r{(V19)}
+You can now use the tags table for completion of names during ordinary
+editing. The command @kbd{M-@key{TAB}} (except in Emacs Lisp and Lisp
+Interaction modes) completes the identifier in the buffer before point,
+using the set of all tags as the list of possible completions.
+
+@code{tags-query-replace} and @code{tags-search} now create buffers only
+temporarily for the files that they have to search (those which are not
+already visited in Emacs buffers). If one of these files contains a
+match for the search pattern, then its buffer continues to exist;
+otherwise, it is killed.
+
+@node Info Changes
+@section Changes in Info
+
+@cindex Info mode in V19
+There are new commands in Info mode.
+
+@c I don't think individual index entries for these commands
+@c are useful. I don't think anyone would ever look them up.--RMS.
+@table @kbd
+@item ]
+Move forward a node, going up and down levels as needed in a depth-first
+tree walk. This command treats all the nodes in the file as forming a
+single sequence in which the ``children'' of a node follow that node.
+It is the equivalent of reading a printed manual sequentially.
+
+@item [
+Similar, but move backward.
+
+@item <
+Move to the top node of the current Info file.
+
+@item >
+Move to the last node of the file.
+
+@c ??? Not done yet
+@item @key{SPC}
+Scroll through this node, or advance to the next node in depth-first
+order (like @kbd{]}).
+
+@c ??? Not done yet
+@item i @var{string} @key{RET}
+Move to the node associated with @var{string} in the index or indices of
+this manual. If there is more than one match for @var{string}, the
+@kbd{i} command finds the first match.
+
+@c ??? Not done yet
+@item ,
+Find the next match for the string in the previous @kbd{i} command, and
+go to that node.
+@end table
+
+If you click the middle mouse button near a cross-reference,
+menu item or node pointer while in Info, you will go to the node
+which is referenced.
+
+@vindex Info-directory-list @r{(V19)}
+@vindex INFOPATH
+The variable @code{Info-directory-list} specifies a list of directory
+names that contain Info files. Each time Info looks for an Info file,
+it searches all these directories. This makes it easy to install the
+Info files that come with various packages. You can specify the path
+with the environment variable @code{INFOPATH}.
+
+@node Dired Changes
+@section Changes in Dired
+
+@cindex Dired in V19
+Dired has many new features which allow you to do these things:
+
+@itemize @bullet
+@item
+Make distinguishable types of marks for different operations.
+
+@item
+Rename, copy, or make links to many files at once.
+
+@item
+Display contents of subdirectories in the same Dired buffer as the
+parent directory.
+@end itemize
+
+@menu
+* Marks in Dired:: Flagging for deletion vs marking for other actions.
+* Multiple Files:: How to copy, rename, print, compress, etc.
+ either one file or several files.
+* Shell Commands in Dired:: Running a shell command on the marked files.
+* Dired Regexps:: Using patterns to rename multiple files.
+* Dired Case Conversion:: Converting file names to upper or lower case.
+* Comparison in Dired:: Running `diff' by way of Dired.
+* Subdirectories in Dired:: Adding subdirectories to the Dired buffer.
+* Hiding Subdirectories:: Making subdirectories visible or invisible.
+* Editing Dired Buffer:: Discarding lines for files of no interest.
+* Dired and Find:: Using `find' to select the files for Dired to show.
+@end menu
+
+@node Marks in Dired
+@subsection Setting and Clearing Marks
+
+@cindex Marks in Dired (V19)
+There are now two kinds of marker that you can put on a file in Dired:
+@samp{D} for deletion, and @samp{*} for any other kind of operation.
+The @kbd{x} command deletes only files marked with @samp{D}, and most
+other Dired commands operate only on the files marked with @samp{*}.
+
+To mark files with @samp{D} (also called @dfn{flagging} the files), you
+can use @kbd{d} as usual. Here are some commands for marking with
+@samp{*} (and also for unmarking):
+
+@table @kbd
+@kindex m @r{(Dired, V19)}
+@findex dired-mark @r{(V19)}
+@item m
+Mark the current file with @samp{*}, for an
+operation other than deletion (@code{dired-mark}).
+
+@kindex * @r{(Dired, V19)}
+@findex dired-mark-executables @r{(V19)}
+@item *
+Mark all executable files (@code{dired-mark-executables}).
+With a prefix argument, unmark all those files.
+
+@item @@
+@kindex @@ @r{(Dired, V19)}
+@findex dired-mark-symlinks @r{(V19)}
+Mark all symbolic links (@code{dired-mark-symlinks}). With a
+prefix argument, unmark all those files.
+
+@item /
+@kindex / @r{(Dired, V19)}
+@findex dired-mark-directories @r{(V19)}
+Mark all files which are actually directories, except for @file{.} and
+@file{..} (@code{dired-mark-directories}). With a prefix argument,
+unmark all those files.
+
+@item M-@key{DEL}
+@kindex M-@key{DEL} @r{(Dired, V19)}
+@findex dired-unmark-all-files @r{(V19)}
+Remove a specific or
+all marks from every file (@code{dired-unmark-all-files}).
+With an argument, query for each marked file.
+Type your help character, usually @kbd{C-h}, at that time for help.
+
+@item c @var{old} @var{new}
+@kindex c @r{(Dired, V19)}
+@findex dired-change-marks @r{(V19)}
+Replace all marks that use the character @var{old} with marks that use
+the character @var{new}. You can use almost any character as a mark
+character by means of this command, to distinguish various classes of
+files. If @var{old} is @samp{ }, then the command operates on all
+unmarked files; if @var{new} is @samp{ }, then the command unmarks the
+files it acts on.
+
+To illustrate the power of this command, here is how to put @samp{*}
+marks on all the files that were unmarked, while unmarking all those
+that had @samp{*} marks:
+
+@example
+c * t c SPC * c t SPC
+@end example
+@end table
+
+@node Multiple Files
+@subsection Operating on Multiple Files
+
+@cindex Multiple file ops, Dired (V19)
+@cindex Dired multiple file ops (V19)
+The Dired commands to operate on files (rename them, copy them, and so
+on) have been generalized to work on multiple files. There are also
+some additional commands in this series.
+
+All of these commands use the same convention to decide which files to
+manipulate:
+
+@itemize @bullet
+@item
+If you give the command a numeric prefix argument @var{n}, it operates
+on the next @var{n} files, starting with the current file.
+
+@item
+Otherwise, if there are marked files, the commands operate on all the
+marked files.
+
+@item
+Otherwise, the command operates on the current file only.
+@end itemize
+
+Here are the commands that operate on multiple files in this way:
+
+@table @kbd
+@findex dired-do-copy @r{(V19)}
+@kindex C @r{(Dired, V19)}
+@item C
+Copy the specified files (@code{dired-do-copy}). You must
+specify a directory to copy into, or (if copying a single file) a new
+name.
+
+@vindex dired-copy-preserve-time @r{(V19)}
+If @code{dired-copy-preserve-time} is non-@code{nil}, then copying with
+this command sets the modification time of the new file to be the same
+as that of the old file.
+
+@findex dired-do-rename @r{(V19)}
+@kindex R @r{(Dired, V19)}
+@item R
+Rename the specified files (@code{dired-do-rename}). You must
+specify a directory to rename into, or (if renaming a single file) a new
+name.
+
+Dired automatically changes the visited file name of buffers associated
+with renamed files so that they refer to the new names.
+
+@findex dired-do-hardlink @r{(V19)}
+@kindex H @r{(Dired, V19)}
+@item H
+Make hard links to the specified
+files (@code{dired-do-hardlink}).
+You must specify a directory to make the links in, or (if making
+just one link) the name to give the link.
+
+@findex dired-do-symlink @r{(V19)}
+@kindex S @r{(Dired, V19)}
+@item S
+Make symbolic links to the specified
+files (@code{dired-do-symlink}).
+You must specify a directory to make the links in, or (if making
+just one link) the name to give the link.
+
+@findex dired-do-chmod @r{(V19)}
+@kindex M @r{(Dired, V19)}
+@item M
+Change the mode (also called ``permission bits'')
+of the specified files (@code{dired-do-chmod}). This calls the
+@code{chmod} program, so you can describe the desired mode change with
+any argument that @code{chmod} would handle.
+
+@findex dired-do-chgrp @r{(V19)}
+@kindex G @r{(Dired, V19)}
+@item G
+Change the group of the specified files (@code{dired-do-chgrp}).
+
+@vindex dired-chown-program @r{(V19)}
+@findex dired-do-chown @r{(V19)}
+@kindex O @r{(Dired, V19)}
+@item O
+Change the owner of the specified
+files (@code{dired-do-chown}).
+(On most systems, only the superuser can do this.)
+
+The variable @code{dired-chown-program} specifies the name of the
+program to use to do the work (different systems put @code{chown} in
+different places.
+
+@findex dired-do-compress @r{(V19)}
+@kindex Z @r{(Dired, V19)}
+@item Z
+@c !!! Rewrote to prevent overfull hbox.
+Compress or uncompress the specified files.
+If the file appears to be a compressed file, it is uncompressed;
+otherwise, it is compressed (@code{dired-do-compress}).
+
+@findex dired-do-load @r{(V19)}
+@kindex L @r{(Dired, V19)}
+@item L
+Load the specified Emacs Lisp files (@code{dired-do-load}).
+
+@findex dired-do-byte-compile @r{(V19)}
+@kindex B @r{(Dired, V19)}
+@item B
+Byte compile the specified Emacs Lisp files
+(@code{dired-do-byte-compile}).
+
+@findex dired-do-print @r{(V19)}
+@kindex P @r{(Dired, V19)}
+@item P
+Print the specified files (@code{dired-do-print}). This command uses
+the variables @code{lpr-command} and @code{lpr-switches} just as
+@code{lpr-file} does (@pxref{Hardcopy}).
+@end table
+
+@node Shell Commands in Dired
+@subsection Shell Commands in Dired
+@cindex shell commands, Dired V19
+
+@findex dired-do-shell-command @r{(V19)}
+@kindex ! @r{(Dired, V19)}
+The dired command @kbd{!} (@code{dired-do-shell-command}) reads a shell
+command string in the minibuffer and runs the shell command on all the
+specified files. There are two ways of applying a shell command to
+multiple files:
+
+@itemize @bullet
+@item
+If you use @samp{*} in the shell command, then it runs just once, with
+the list of file names substituted for the @samp{*}.
+
+Thus, @kbd{! tar cf foo.tar * @key{RET}} runs @code{tar} on the entire
+list of file names, putting them into one tar file @file{foo.tar}. The
+file names are inserted in the order that they appear in the Dired
+buffer.
+
+@item
+If the command string doesn't contain @samp{*}, then it runs once
+@emph{for each file}, with the file name attached at the end.
+
+For example, @kbd{! uudecode @key{RET}} runs @code{uudecode} on each
+file.
+@end itemize
+
+What if you want to run the shell command once for each file but with
+the file name inserted in the middle? Or if you want to use the file
+names in a more complicated fashion? Use a shell loop. For example,
+this shell command would run @code{uuencode} on each of the specified
+files, writing the output into a corresponding @file{.uu} file:
+
+@example
+for file in *; uuencode $file $file >$file.uu; done
+@end example
+
+The working directory for the shell command is the top level directory
+of the Dired buffer.
+
+The @kbd{!} command does not attempt to update the Dired buffer to show
+new or modified files, because it doesn't know what those files might
+be. Type @kbd{g} to update the Dired buffer.
+
+@node Dired Regexps
+@subsection Regular Expression File Name Substitution
+
+Here are commands that select files according to a regular
+expression:
+
+@table @kbd
+@findex dired-mark-files-regexp @r{(V19)}
+@kindex % m @r{(Dired, V19)}
+@item % m @var{regexp} @key{RET}
+Mark all files whose names match the regular expression @var{regexp}
+(@code{dired-mark-files-regexp}).
+
+Only the non-directory part of the file name is used in matching. Use
+@samp{^} and @samp{$} to anchor matches. Exclude subdirs by hiding
+them (@pxref{Hiding Subdirectories}).
+
+@item % d @var{regexp} @key{RET}
+@findex dired-flag-files-regexp @r{(V19)}
+@kindex % d @r{(Dired, V19)}
+Flag for deletion all files whose names match the regular expression
+@var{regexp} (@code{dired-flag-files-regexp}).
+
+@item % R @var{from} @key{RET} @var{to} @key{RET}
+@kindex % R @r{(Dired, V19)}
+@findex dired-do-rename-regexp @r{(V19)}
+@itemx % C @var{from} @key{RET} @var{to} @key{RET}
+@kindex % C @r{(Dired, V19)}
+@findex dired-do-copy-regexp @r{(V19)}
+@itemx % H @var{from} @key{RET} @var{to} @key{RET}
+@kindex % H @r{(Dired, V19)}
+@findex dired-do-hardlink-regexp @r{(V19)}
+@itemx % S @var{from} @key{RET} @var{to} @key{RET}
+@kindex % S @r{(Dired, V19)}
+@findex dired-do-symlink-regexp @r{(V19)}
+These four commands rename, copy, make hard links and make soft links,
+in each case computing the new name by regular expression substitution
+from the name of the old file.
+@end table
+
+The four regular expression substitution commands effectively perform
+@code{query-replace-regexp} on the selected file names in the Dired
+buffer. They read two arguments: a regular expression @var{from}, and a
+substitution pattern @var{to}. Each selected file name is matched
+against the regular expression, and then the part which matched is
+replaced with the substitution pattern. You can use @samp{\&} and
+@samp{\@var{digit}} in the substitution pattern to refer to all or part
+of the old file name.
+@c ??? xref{???query replace???}.
+
+Thus, @kbd{% R ^.*$ @key{RET} x-\& @key{RET}} renames each selected file
+by prepending @samp{x-} to its name. The inverse of this is to remove
+@samp{x-} from the front of each file name. One way to do that is
+@kbd{% R ^x-.*$ @key{RET} \& @key{RET}}; another is @w{@kbd{% R ^x-
+@key{RET} @key{RET}}}. (Use @samp{^} and @samp{$} to anchor matches that
+should span the whole filename.)
+
+If the regular expression matches more than once in a file name,
+only the first match is replaced.
+
+Normally, the replacement process does not consider the directory names;
+it operates on the file name within the directory. If you specify a
+prefix argument of zero, then replacement affects the entire file name.
+
+Often you will want to apply the command to all files matching the same
+@var{regexp} that you use in the command. To do this, mark those files
+with @w{@kbd{% m @var{regexp} @key{RET}}}, then use the same regular
+expression in @kbd{% R}. To make this easier, @kbd{% R} uses the
+last regular expression specified in a @kbd{%} command as a default.
+
+@node Dired Case Conversion
+@subsection Dired Case Conversion
+@cindex case conversion of file names @r{(V19)}
+
+Here are commands for changing the case of selected files:
+
+@table @code
+@findex dired-upcase @r{(V19)}
+@kindex % u @r{(Dired, V19)}
+@item % u
+Rename each of the selected files to an
+upper case name (@code{dired-upcase}).
+
+@item % l
+@findex dired-downcase @r{(V19)}
+@kindex % l @r{(Dired, V19)}
+Rename each of the selected files to
+a lower case name (@code{dired-downcase}).
+@end table
+
+@node Comparison in Dired
+@subsection File Comparison with Dired
+
+Here are two commands to run @code{diff} on selected files:
+
+@table @kbd
+@findex dired-diff @r{(V19)}
+@kindex = @r{(Dired, V19)}
+@item =
+Compare the current file with another file (the file at the mark), by
+running the @code{diff} program (@code{dired-diff}). The file at the
+mark is the first argument of @code{diff}, and the file at point is the
+second argument.
+
+@findex dired-backup-diff @r{(V19)}
+@kindex M-= @r{(Dired, V19)}
+@item M-=
+Compare the current file with its
+backup file (@code{dired-backup-diff}).
+If there are several numerical backups, use the most
+recent one. If this file is a backup, compare it to its
+original. The backup file is the first file given to @code{diff}.
+@end table
+
+@node Subdirectories in Dired
+@subsection Subdirectories in Dired
+@cindex subdirectories in Dired (V19)
+@cindex expanding subdirectories in Dired (V19)
+
+One Dired buffer can now display more than one directory.
+
+The simplest way to include multiple directories is to specify the
+options @samp{-lR} for running @code{ls}. That produces a recursive
+directory listing showing all subdirectories, all within the same Dired
+buffer.
+
+But the simplest way is not usually the most convenient way---usually
+the complete recursive listing is more than you want. So there is a
+Dired command to insert a single subdirectory into the Dired buffer:
+
+@table @kbd
+@findex dired-maybe-insert-subdir @r{(V19)}
+@kindex i @r{(Dired, V19)}
+@item i
+@cindex inserted subdirectory (Dired, V19)
+@cindex expanded subdirectory (Dired, V19)
+@cindex in-situ subdirectory (Dired, V19)
+@cindex headerline (Dired, V19)
+Use the @kbd{i} (@code{dired-maybe-insert-subdir}) command on a line
+that describes a file which is a directory. It inserts the contents of
+that directory into the same Dired buffer. Inserted subdirectory
+contents follow the top-level directory of the Dired buffer, just as
+they do in @samp{ls -lR} output.
+
+If the subdirectory's contents are already present in the buffer, the
+@kbd{i} command just moves to it (type @kbd{l}
+(@code{dired-do-redisplay}) to refresh it). It sets the Emacs mark
+before moving, so @kbd{C-x C-x} takes you back to the old position in
+the buffer.
+@end table
+
+When you have subdirectories in the Dired buffer, you can use the page
+motion commands @kbd{C-x [} and @kbd{C-x ]} to move by entire directories.
+
+The following commands move up and down in the tree of directories
+in one Dired buffer:
+
+@table @kbd
+@findex dired-tree-up @r{(V19)}
+@kindex C-M-u @r{(Dired, V19)}
+@item C-M-u
+Go up to the parent directory's headerline (@code{dired-tree-up}).
+
+@findex dired-tree-down @r{(V19)}
+@kindex C-M-d @r{(Dired, V19)}
+@item C-M-d
+Go down in the tree, to the first
+subdirectory's headerline (@code{dired-tree-down}).
+@end table
+
+The following commands move forwards and backwards to subdirectory headerlines:
+
+@table @kbd
+@findex dired-next-subdir @r{(V19)}
+@kindex C-M-n @r{(Dired, V19)}
+@item C-M-n
+Go to next subdirectory headerline,
+regardless of level (@code{dired-next-subdir}).
+
+@findex dired-prev-subdir @r{(V19)}
+@kindex C-M-p @r{(Dired, V19)}
+@item C-M-p
+@c !!! added @* to prevent overfull hbox
+Go to previous subdirectory headerline,
+regardless of level@*
+(@code{dired-prev-subdir}).
+@end table
+
+@node Hiding Subdirectories
+@subsection Hiding Subdirectories
+
+@cindex hiding in Dired (Dired, V19)
+@dfn{Hiding} a subdirectory means to make it invisible, except for its
+headerline. Files inside a hidden subdirectory are never considered by
+Dired. For example, the commands to operate on marked files ignore
+files in hidden directories even if they are marked. Thus you can use
+hiding to temporarily exclude subdirectories from operations without
+having to remove the markers.
+
+The hiding commands toggle; that is they unhide what was hidden and vice
+versa.
+
+@table @kbd
+@item $
+@findex dired-hide-subdir @r{(V19)}
+@kindex $ @r{(Dired, V19)}
+Hide or reveal the current subdirectory and move point to the next
+subdirectory (@code{dired-hide-subdir}). A prefix argument serves as
+a repeat count.
+
+@item M-$
+@findex dired-hide-all @r{(V19)}
+@kindex M-$ @r{(Dired, V19)}
+Hide all subdirectories, leaving only their header lines
+(@code{dired-hide-all}). Or, if any subdirectory is currently hidden,
+make all subdirectories visible again. You can use this command to get
+an overview in very deep directory trees or to move quickly to
+subdirectories far away.
+@end table
+
+@node Editing Dired Buffer
+@subsection Editing the Dired Buffer
+
+@table @kbd
+@kindex l @r{(Dired, V19)}
+@findex dired-do-redisplay @r{(V19)}
+@item l
+@c !!! rewrote to prevent overfull hbox
+Update the specified files in a Dired buffer. This means reading their
+current status from the file system and changing the buffer to reflect
+it properly (@code{dired-do-redisplay}).
+
+If you use this command on a subdirectory header line, it updates the
+contents of the subdirectory.
+
+@kindex g @r{(Dired, V19)}
+@findex revert-buffer @r{(Dired, V19)}
+@item g
+Update the entire contents of the Dired buffer
+(@code{revert-buffer}). Preserve all marks except for those on files
+that have vanished. Hidden subdirectories are updated but remain
+hidden.
+
+@kindex k @r{(Dired, V19)}
+@findex dired-do-kill-lines @r{(V19)}
+@item k
+Kill all marked lines (@code{dired-do-kill-lines}). With a prefix
+argument, kill that many lines starting with the current line.
+
+This command does not delete files; it just deletes text from the Dired
+buffer.
+
+If you kill the line for a file that is a directory, then its contents
+are also deleted from the buffer. Typing @kbd{C-u k} on the header line
+for a subdirectory is another way to delete a subdirectory from the
+Dired buffer.
+
+The @kbd{g} command will bring back any individual lines that you have
+killed in this way, but not subdirectories---you must use @kbd{i} to
+reinsert each subdirectory.
+@end table
+
+@node Dired and Find
+@subsection Dired and @code{find}
+@cindex @code{find} and Dired
+
+ You can select a set of files for display in a Dired buffer more
+flexibly by using the @code{find} utility to choose the files.
+
+@findex find-name-dired
+To search for files with names matching a wildcard pattern use
+@code{find-name-dired}. Its arguments are @var{directory} and
+@var{pattern}. It selects all the files in @var{directory} or its
+subdirectories whose own names match @var{pattern}.
+
+The files thus selected are displayed in a Dired buffer in which the
+ordinary Dired commands are available.
+
+@findex find-grep-dired
+If you want to test the contents of files, rather than their names, use
+@code{find-grep-dired}. This command takes two minibuffer arguments,
+@var{directory} and @var{regexp}; it selects all the files in
+@var{directory} or its subdirectories that contain a match for
+@var{regexp}. It works by running @code{find} and @code{grep}.
+
+@findex find-dired
+The most general command in this series is @code{find-dired}, which lets
+you specify any condition that @code{find} can test. It takes two
+minibuffer arguments, @var{directory} and @var{find-args}; it runs
+@code{find} in @var{directory} with @var{find-args} as the
+arguments to @code{find} that specify which files to accept. To use this
+command, you need to know how to use @code{find}.
+
+@node GNUS
+@section GNUS
+@cindex @sc{gnus}
+@cindex reading netnews
+
+@sc{gnus} is an Emacs subsystem for reading and responding to netnews. You
+can use @sc{gnus} to browse through news groups, look at summaries of
+articles in specific group, and read articles of interest. You can
+respond to authors or write replies to all the readers of a news group.
+
+This document introduces @sc{gnus} and describes several basic features.
+Full documentation will appear in @cite{The GNU Emacs Extensions Manual}.
+
+@kindex M-x gnus @r{(V19)}
+@findex gnus @r{(V19)}
+To start @sc{gnus}, type @kbd{M-x gnus @key{RET}}.
+
+@menu
+* Buffers of GNUS:: The Newsgroups, Summary and Article buffers.
+* GNUS Startup:: What you should know about starting GNUS.
+* Summary of GNUS:: A short description of the basic GNUS commands.
+@end menu
+
+@node Buffers of GNUS
+@subsection @sc{GNUS}'s Three Buffers
+
+@sc{gnus} creates and uses three Emacs buffers, each with its own
+particular purpose and its own major mode.
+
+The @dfn{Newsgroup buffer} contains a list of newsgroups. This is the
+first buffer that @sc{gnus} displays when it starts up. Normally the list
+contains only the newsgroups to which you subscribe (which are listed in
+your @file{.newsrc} file) and which contain unread articles. Use this
+buffer to select a specific newsgroup.
+
+The @dfn{Summary buffer} lists the articles in a single newsgroup,
+including their subjects, their numbers, and who posted them. @sc{gnus}
+creates a Summary buffer for a newsgroup when you select the group in
+the Newsgroup buffer. Use this buffer to select an article, and to move
+around in an article.
+
+The @dfn{Article buffer} displays the text of an article. You rarely
+need to select this buffer because you can read the text while keeping
+the Summary buffer selected.
+
+@node GNUS Startup
+@subsection When @sc{GNUS} Starts Up
+
+At startup, @sc{gnus} reads your @file{.newsrc} news initialization file
+and attempts to communicate with the local news server, which is a
+repository of news articles. The news server need not be the same
+computer you are logged in on.
+
+If you start @sc{gnus} and connect to the server, but do not see any
+newsgroups listed in the Newsgroup buffer, type @kbd{L} to get a listing
+of all the newsgroups. Then type @kbd{u} to unsubscribe from particular
+newsgroups. (Move the cursor using @kbd{n} and @kbd{p} or the usual
+Emacs commands.) When you quit with @kbd{q}, @sc{gnus} automatically
+records the subscribed groups in your @file{.newsrc} initialization
+file. (You do not have to edit this file yourself, although you may.)
+Next time you start @sc{gnus}, you will see only the subscribed groups.
+
+@node Summary of GNUS
+@subsection Summary of GNUS Commands
+
+Reading news is a two step process:
+
+@enumerate
+@item
+Choose a newsgroup in the Newsgroup buffer.
+
+@item
+Choose an article in the Summary buffer. The article is displayed in
+the Article buffer in a large window, below the Summary buffer in its
+small window.
+@end enumerate
+
+Each buffer has commands particular to it, but commands that do the same
+things have similar keybindings. Here are commands for the Newsgroup
+and Summary buffers:
+
+@table @kbd
+@kindex z @r{(Group mode)} @r{(GNUS, V19)}
+@findex gnus-Group-suspend @r{(V19)}
+@item z
+In the Newsgroup buffer, suspend @sc{gnus}. You can return to @sc{gnus} later by
+selecting the Newsgroup buffer and typing @kbd{g} to get newly arrived
+articles.
+
+@kindex q @r{(Group mode)} @r{(GNUS, V19)}
+@findex gnus-Group-exit @r{(V19)}
+@item q
+In the Newsgroup buffer, update your @file{.newsrc} initialization file
+and quit @sc{gnus}.
+
+In the Summary buffer, exit the current newsgroup and return to the
+Newsgroup buffer. Thus, typing @kbd{q} twice quits @sc{gnus}.
+
+@kindex L @r{(Group mode)} @r{(GNUS, V19)}
+@findex gnus-Group-list-all-groups @r{(V19)}
+@item L
+In the Newsgroup buffer, list all the newsgroups available on your news
+server. This may be a long list!
+
+@kindex l @r{(Group mode)} @r{(GNUS, V19)}
+@findex gnus-Group-list-groups @r{(V19)}
+@item l
+In the Newsgroup buffer, list only the newsgroups to which you subscribe
+and which contain unread articles.
+
+@kindex u @r{(Group mode)} @r{(GNUS, V19)}
+@findex gnus-Group-unsubscribe-current-group @r{(V19)}
+@cindex subscribe newsgroups (V19)
+@cindex unsubscribe newsgroups (V19)
+@item u
+In the Newsgroup buffer, unsubscribe from (or subscribe to) the
+newsgroup listed in the line that point is on. When you quit @sc{gnus} by
+typing @kbd{q}, @sc{gnus} lists your subscribed-to newsgroups in your
+@file{.newsrc} file. The next time you start @sc{gnus}, you see only the
+newsgroups listed in your @file{.newsrc} file.
+
+You may also edit your @file{.newsrc} file directly in Emacs. First quit
+@sc{gnus}, then visit the @file{.newsrc} file. For example, you can remove
+all the @file{alt.} groups by going to the beginning of the file and
+typing @kbd{M-x flush-lines RET alt RET}. Next time you start @sc{gnus}, you
+will see only the newsgroups still listed in the @file{.newsrc} file.
+
+@kindex SPC @r{(Group mode)} @r{(GNUS, V19)}
+@findex gnus-Group-read-group @r{(V19)}
+@item @key{SPC}
+In the Newsgroup buffer, select the group on the line under the cursor
+and display the first unread article in that group.
+
+@kindex SPC @r{(Summary mode)} @r{(GNUS, V19)}
+@findex gnus-Summary-next-page @r{(V19)}
+@need 1000
+In the Summary buffer,
+
+@itemize @minus
+@item
+Select the article on the line under the cursor if none is selected.
+
+@item
+Scroll the text of the article if one is selected.
+
+@item
+Select the next unread article if at the end of the current article.
+@end itemize
+
+Thus, you can move through all the articles by repeatedly typing @key{SPC}.
+
+@kindex DEL @r{(Group mode)} @r{(GNUS, V19)}
+@item @key{DEL}
+In the Newsgroup Buffer, move point to the previous newsgroup containing
+unread articles.
+
+@kindex DEL @r{(Summary mode)} @r{(GNUS, V19)}
+@findex gnus-Summary-prev-page @r{(V19)}
+In the Summary buffer, scroll the text of the article backwards.
+
+@kindex n @r{(Group mode)} @r{(GNUS, V19)}
+@findex gnus-Group-next-unread-group @r{(V19)}
+@item n
+Move point to the next unread newsgroup, or select the next unread
+article.
+
+@kindex p @r{(Group mode)} @r{(GNUS, V19)}
+@findex gnus-Group-prev-unread-group @r{(V19)}
+@item p
+Move point to the previous unread newsgroup, or select the previous
+unread article.
+
+@kindex C-n @r{(Group mode)} @r{(GNUS, V19)}
+@findex gnus-Group-next-group @r{(V19)}
+@kindex C-p @r{(Group mode)} @r{(GNUS, V19)}
+@findex gnus-Group-prev-group @r{(V19)}
+@kindex C-n @r{(Summary mode)} @r{(GNUS, V19)}
+@findex gnus-Summary-next-subject @r{(V19)}
+@kindex C-p @r{(Summary mode)} @r{(GNUS, V19)}
+@findex gnus-Summary-prev-subject @r{(V19)}
+@itemx C-n
+@itemx C-p
+Move point to the next or previous item, even if it is marked as read.
+This does not select the article or newsgroup on that line.
+
+@kindex s @r{(Summary mode)} @r{(GNUS, V19)}
+@findex gnus-Summary-isearch-article @r{(V19)}
+@item s
+In the Summary buffer, do an incremental search of the current text in
+the Article buffer, just as if you switched to the Article buffer and
+typed @kbd{C-s}.
+
+@kindex M-s @r{(Summary mode)} @r{(GNUS, V19)}
+@findex gnus-Summary-search-article-forward @r{(V19)}
+@item M-s @var{regexp} RET
+In the Summary buffer, search forward for articles containing a match
+for @var{regexp}.
+
+@c kindex C-c C-s C-n @r{(Summary mode)} @r{(GNUS, V19)}
+@findex gnus-Summary-sort-by-number @r{(V19)}
+@c kindex C-c C-s C-s @r{(Summary mode)} @r{(GNUS, V19)}
+@findex gnus-Summary-sort-by-subject @r{(V19)}
+@c kindex C-c C-s C-d @r{(Summary mode)} @r{(GNUS, V19)}
+@findex gnus-Summary-sort-by-date @r{(V19)}
+@c kindex C-c C-s C-a @r{(Summary mode)} @r{(GNUS, V19)}
+@findex gnus-Summary-sort-by-author @r{(V19)}
+@item C-c C-s C-n
+@itemx C-c C-s C-s
+@itemx C-c C-s C-d
+@itemx C-c C-s C-a
+In the Summary buffer, sort the list of articles by number, subject,
+date, or author.
+
+@kindex C-M-n @r{(Summary mode)} @r{(GNUS, V19)}
+@findex gnus-Summary-next-same-subject @r{(V19)}
+@kindex C-M-p @r{(Summary mode)} @r{(GNUS, V19)}
+@findex gnus-Summary-prev-same-subject @r{(V19)}
+@item C-M-n
+@itemx C-M-p
+In the Summary buffer, read the next or previous article with the same
+subject as the current article.
+@end table
+
+@ignore
+@node Where to Look
+@subsection Where to Look Further
+
+@c Too many references to the name of the manual if done with xref in TeX!
+@sc{gnus} is powerful and customizable. Here are references to a few
+@ifinfo
+additional topics:
+
+@end ifinfo
+@iftex
+additional topics in @cite{The GNUS Manual}:
+
+@itemize @bullet
+@item
+Follow discussions on specific topics.@*
+See section ``Thread-based Reading''.
+
+@item
+Read digests. See section ``Digest Articles''
+
+@item
+Refer to and jump to the parent of the current article.@*
+See section ``Referencing Articles''.
+
+
+@item
+Refer to articles by using Message-IDs included in the messages.@*
+See section ``Article Commands''.
+
+@item
+Save articles. See section ``Saving Articles''.
+
+@item
+Create filters that preselect which articles you will see, according to
+regular expressions in the articles or their headers.@*
+See section ``Kill File''.
+
+@item
+Send an article to a newsgroup.@*
+See section ``Posting Articles''.
+@end itemize
+@end iftex
+@ifinfo
+@itemize @bullet
+@item
+Follow discussions on specific topics.@*
+@xref{Thread-based Reading, , Reading Based on Conversation Threads,
+gnus, The GNUS Manual}.
+
+@item
+Read digests. @xref{Digest Articles, , , gnus, The GNUS Manual}.
+
+@item
+Refer to and jump to the parent of the current article.@*
+@xref{Referencing Articles, , , gnus, The GNUS Manual}.
+
+
+@item
+Refer to articles by using Message-IDs included in the messages.@*
+@xref{Article Commands, , , gnus, The GNUS Manual}.
+
+@item
+Save articles. @xref{Saving Articles, , , gnus, The GNUS Manual}.
+
+@item
+Create filters that preselect which articles you will see, according to
+regular expressions in the articles or their headers.@*
+@xref{Kill File, , , gnus, The GNUS Manual}.
+
+@item
+Send an article to a newsgroup.@*
+@xref{Posting Articles, , , gnus, The GNUS Manual}.
+@end itemize
+@end ifinfo
+@end ignore
+
+@node Calendar/Diary
+@section Calendar and Diary
+
+The calendar facility in Emacs 19 is almost completely new, and it
+comes with a diary feature. You can use the diary to keep track of
+appointments, anniversaries, and other events.
+@c ??? reference to top node, Diary in GNU Emacs Calendar
+@c @xref{diary, , Diary, calendar, The GNU Emacs Calendar}, for more
+@c complete information.
+
+To use the diary, you must write diary entries in a particular file,
+called your @dfn{diary file}. Its name is @file{~/diary}. Emacs
+displays the entries for particular dates by finding them in the diary
+file, formatting them, and displaying them in a diary display buffer.
+
+@menu
+* Calendar:: New features of the calendar proper.
+* Entries: Diary Entries. The location and form of a diary entry.
+* New Entries:: Inserting diary entries using the calendar.
+* Displaying Diary:: How to display diary entries from the calendar.
+* European Calendar Style :: Day-month-year style for dates.
+* Simple and Fancy:: The diary has two modes for display.
+* Other Diary Features:: The diary has many advanced commands.
+* Startup Diary:: How to display your diary when you start Emacs.
+* Printing Diary:: Print selected entries of the diary.
+@end menu
+
+@node Calendar
+@subsection Calendar
+@cindex calendar @r{(V19)}
+
+In Emacs 19 you can use ordinary Emacs cursor commands to move through
+the calendar, which scrolls automatically to display different months or
+different years. Character motion translates to days, line motion to
+weeks, sentence and paragraph motion to months, and page motion to
+years. The vertical and horizontal scroll commands also handle the
+calendar suitably.
+
+@c The index entries for the key bindings of Calendar and Diary modes
+@c are commented out because they don't seem very useful.
+@c @kindex p d (Calendar mode)
+@c @kindex g d (Calendar mode)
+@c @kindex . (Calendar mode)
+@kbd{p d} displays the selected date as a day within the year. @kbd{g
+d} selects a date given as month, day, year. Type @kbd{.} to go back
+to today's date.
+
+@c @kindex M-= (Calendar mode)
+@findex calendar-count-days-region @r{(V19)}
+The command @kbd{M-=}, which normally gives the number of lines in the
+region, in Calendar mode gives the number of days in the region
+(@code{calendar-count-days-region}).
+
+The calendar facility also knows about other important calendars. The
+commands for these come in pairs; the commands to convert @emph{to}
+another calendar start with the @kbd{p} prefix (short for ``print''),
+and the commands to convert from another calendar start with the @kbd{g}
+prefix (short for ``go to''). Here is a complete list:
+
+@c !!! Insert line breaks to prevent overfull hboxes.
+@table @asis
+@item @kbd{g a}, @kbd{p a}
+@findex calendar-print-astro-date @r{(V19)}
+@findex calendar-goto-astro-date @r{(V19)}
+@cindex astronomical calendar
+@cindex Julian day number
+The astronomical calendar, a simple count of days elapsed since noon,
+Monday, January 1, 4713 B.C. on the Julian calendar. The number of days
+elapsed is also called the @dfn{Julian day number}
+(@code{calendar-goto-astro-date}, @code{calendar-print-astro-date}).
+
+@item @kbd{g c}, @kbd{p c}
+@c @kindex g c (Calendar mode)
+@c @kindex p c (Calendar mode)
+@findex calendar-print-iso-date @r{(V19)}
+@findex calendar-goto-iso-date @r{(V19)}
+@cindex ISO commercial calendar
+ISO commercial calendar@*
+(@code{calendar-goto-iso-date}, @code{calendar-print-iso-date}).
+
+@item @kbd{g f}, @kbd{p f}
+@c @kindex p f (Calendar mode)
+@findex calendar-goto-french-date @r{(V19)}
+@findex calendar-print-french-date @r{(V19)}
+@cindex French revolutionary calendar
+@c !!! added @* to prevent overfull hbox
+French revolutionary calendar@*
+(@code{calendar-goto-french-date},@*
+@code{calendar-print-french-date}).
+
+@item @kbd{g h}, @kbd{p h}
+@c @kindex g h (Calendar mode)
+@c @kindex p h (Calendar mode)
+@findex calendar-print-hebrew-date @r{(V19)}
+@findex calendar-goto-hebrew-date @r{(V19)}
+@cindex Hebrew calendar
+@c !!! added @* to prevent overfull hbox
+Hebrew calendar@*
+(@code{calendar-goto-hebrew-date},@*
+@code{calendar-print-hebrew-date}).
+
+@item @kbd{g i}, @kbd{p i}
+@c @kindex g i (Calendar mode)
+@c @kindex p i (Calendar mode)
+@findex calendar-print-islamic-date @r{(V19)}
+@findex calendar-goto-islamic-date @r{(V19)}
+@cindex Islamic calendar
+@c !!! added @* to prevent overfull hbox
+Islamic calendar@*
+(@code{calendar-goto-islamic-date},@*
+@code{calendar-print-islamic-date}).
+
+@item @kbd{g j}, @kbd{p j}
+@c @kindex g j (Calendar mode)
+@c @kindex p j (Calendar mode)
+@findex calendar-print-julian-date @r{(V19)}
+@findex calendar-goto-julian-date @r{(V19)}
+@cindex Julian calendar
+@c !!! added @* to prevent overfull hbox
+Julian calendar@*
+(@code{calendar-goto-julian-date},@*
+@code{calendar-print-julian-date}).
+
+@item @kbd{p m}
+@c @kindex p m (Calendar mode)
+@findex calendar-print-mayan-date @r{(V19)}
+@cindex Mayan calendar
+Mayan calendar (@code{calendar-print-mayan-date}).
+@end table
+
+@ignore
+ Several commands are needed to handle selecting dates in the Mayan
+calendar.
+
+@table @kbd
+@item g m l @var{baktun}.@var{katun}.@var{tun}.@var{uinic}.@var{kin} @key{RET}
+@cindex long count @r{(V19)}
+Move point to a date specified in the Mayan long count calendar
+(@code{calendar-goto-long-count-date}). The argument consists of numbers
+separated by periods.
+@item g m p t @var{number} @var{name} @key{RET}
+@cindex tzolkin @r{(V19)}
+Move point to the previous occurrence of a specified date in the Mayan
+tzolkin calendar (@code{calendar-previous-tzolkin-date}). Here @var{name}
+is one of the twenty tzolkin day names, and @var{number} is between 1 and 13.
+@item g m n t @var{number} @var{name} @key{RET}
+Move point to the next occurrence of a specified date in the
+tzolkin calendar (@code{calendar-next-tzolkin-date}).
+@item g m p h @var{kin} @var{uinal} @key{RET}
+@cindex haab @r{(V19)}
+Move point to the previous occurrence of a specified date in the Mayan
+haab calendar (@code{calendar-previous-haab-date}). Here @var{uinal}
+is a haab month name, and @var{kin} is a number from 1 to 19 (or 0).
+@item g m n h @var{kin} @var{uinal} @key{RET}
+Move point to the next occurrence of a specified date in the
+haab calendar (@code{calendar-next-haab-date}).
+@item g m p c @var{number} @var{name} @var{kin} @var{uinal} @key{RET}
+@cindex calendar round @r{(V19)}
+Move point to the previous occurrence of a specified date in the Mayan
+calendar round (@code{calendar-previous-calendar-round-date}). Specify
+a tzolkin date followed by a haab date.
+@item g m n c @var{number} @var{name} @var{kin} @var{uinal} @key{RET}
+Move point to the next occurrence of a specified date in the
+calendar round (@code{calendar-next-calendar-round-date}).
+@end table
+@end ignore
+
+@findex calendar-cursor-holidays @r{(V19)}
+@findex mark-calendar-holidays @r{(V19)}
+@findex calendar-unmark @r{(V19)}
+The calendar also knows the dates of standard holidays. Type @kbd{h}
+(@code{calendar-cursor-holidays}) to display a list of holidays for the
+selected date. This list appears in another window. Type @kbd{x}
+(@code{mark-calendar-holidays}) to mark each day that is a holiday with
+@samp{*} in the calendar itself. The command @kbd{u}
+(@code{calendar-unmark}) turns off this marking.
+
+@findex holidays @r{(V19)}
+At any time, you can use @kbd{M-x holidays} to display a list of
+holidays for the present month and the preceding and following months.
+
+@node Diary Entries
+@subsection Diary Entries
+@cindex diary entries (V19)
+
+@vindex diary-file @r{(V19)}
+To use the diary feature, you must write @dfn{diary entries} that
+describe plans associated with particular dates, and put them in your
+@dfn{diary file}, which is normally the file @file{~/diary}. You can
+specify a different name for it by setting the variable
+@code{diary-file}; you would do this before using any of the commands
+that operate on the diary.
+
+Diary file entries follow a simple convention: begin entries with a date
+at the beginning of a line, followed optionally by a time, and then by
+the text of the entry:
+
+@example
+@var{date} @var{optional-time-of-day} @var{text-of-entry}
+@end example
+
+@noindent
+To continue an entry over two or more lines, indent the second and
+subsequent lines. The lines of the entry after the first are called
+@dfn{continuation lines}. Other lines in the diary file that are not
+part of any entry are comment lines; Emacs does not display these.
+
+When you make diary entries using Calendar mode, Emacs inserts the date
+for you in the appropriate format and places the cursor so you can type
+the text of the entry.
+
+You can write entries in any order and Emacs will display the entries by
+date. However, time-of-day entries can be sorted chronologically only
+in a diary mode called Fancy mode; in Simple mode, Emacs displays
+time-of-day entries in their order in the diary file.
+
+@node Displaying Diary
+@subsection Calendar Commands to Display Diary Entries
+@cindex diary display (V19)
+@cindex display of diary (V19)
+
+In Calendar mode, use the following commands to display your diary
+entries:
+
+@table @kbd
+@findex view-diary-entries @r{(V19)}
+@c @kindex d (Calendar mode) @r{(V19)}
+@item d
+Display any diary entries for the date under the cursor
+(@code{view-diary-entries}).
+
+With a numeric argument, Emacs shows the diary entries for that many
+successive days, starting with and including the date under the cursor.
+Thus, @kbd{2 d} displays all the entries for the selected date and for
+the following day.
+
+@findex show-all-diary-entries @r{(V19)}
+@c @kindex s (Calendar mode) @r{(V19)}
+@item s
+Display your entire diary file (@code{show-all-diary-entries}).
+
+@findex mark-diary-entries @r{(V19)}
+@c @kindex m (Calendar mode) @r{(V19)}
+@item m
+In the calendar, mark all visible dates that have diary entries
+(@code{mark-diary-entries}).
+
+@findex calendar-unmark @r{(V19)}
+@c @kindex u (Calendar mode) @r{(V19)}
+@item u
+Unmark the calendar (@code{calendar-unmark}).
+@end table
+
+At any time, not just in Calendar mode, you can display today's diary
+entries by typing:
+
+@findex diary @r{(V19)}
+@example
+M-x diary
+@end example
+
+@noindent
+With a prefix argument @var{n}, this command displays diary entries for
+@var{n} successive days, starting from and including today.
+
+@node New Entries
+@subsection Calendar Commands for Making Diary Entries
+@cindex diary entries, inserting (V19)
+
+Calendar mode provides several commands to help you make diary file
+entries. These commands work by visiting the diary file and inserting
+the date information; you must finish the job by inserting the text of
+the entry, and then save the diary file with @kbd{C-x C-s}. The
+commands are:
+
+@table @kbd
+@findex insert-diary-entry @r{(V19)}
+@c @kindex i d (Calendar mode) @r{(V19)}
+@item i d
+Add a diary entry for the selected date in the calendar
+(@code{insert-diary-entry}).
+
+@findex insert-weekly-diary-entry @r{(V19)}
+@c @kindex i w (Calendar mode) @r{(V19)}
+@item i w
+Add a diary entry for the selected day of the week
+(@code{insert-weekly-diary-entry}). This entry is displayed each week
+on the selected day.
+
+@findex insert-monthly-diary-entry @r{(V19)}
+@c @kindex i m (Calendar mode) @r{(V19)}
+@item i m
+Add a diary entry for the selected day of the month
+(@code{insert-monthly-diary-entry}). This entry is displayed each month
+on the selected day.
+
+@findex insert-yearly-diary-entry @r{(V19)}
+@c @kindex i y (Calendar mode) @r{(V19)}
+@item i y
+Add a diary entry for the selected day of the year
+(@code{insert-yearly-diary-entry}). This entry is displayed each year
+on the selected day.
+@end table
+
+Here are commands for entering more complex kinds of diary entries in
+Calendar mode. These kinds of entries operate properly only in Fancy
+Diary Display mode (@pxref{Simple and Fancy}).
+
+@table @kbd
+@findex insert-anniversary-diary-entry @r{(V19)}
+@c @kindex i a (Calendar mode diary) @r{(V19)}
+@item i a
+Add an anniversary diary entry for the selected date
+(@code{insert-anniversary-diary-entry}).
+
+Select the date you want remembered, in the proper year---if it is a
+birthday, remember to go to the person's year of birth! Then type
+@kbd{i a} and enter the text of the entry.
+
+In the textual part of the entry you can type @samp{%d}. When Emacs
+displays the entry in the diary buffer, the @samp{%d} is replaced by the
+number of years since the date. Thus, if you use @samp{%d years old} as
+the text of the entry, it will display as @samp{53 years old} on the
+53rd birthday.
+
+@findex insert-cyclic-diary-entry @r{(V19)}
+@c @kindex i c (Calendar mode diary) @r{(V19)}
+@item i c
+Add a cyclic diary entry starting at the date
+(@code{insert-cyclic-diary-entry}). An entry is displayed on a
+specified starting date and then is repeatedly displayed at the
+specified interval. This is useful for ten day cycles of preventive
+maintenance and similar activities.
+
+To use this command, first select the start date. The command reads the
+interval (the number of days between repetitions) using the minibuffer,
+then inserts the beginning of the entry.
+
+@findex insert-block-diary-entry @r{(V19)}
+@c @kindex i b (Calendar mode diary) @r{(V19)}
+@item i b
+Add a block diary entry for the current region
+(@code{insert-block-diary-entry}). With a block entry, Emacs
+writes the same message in the display for successive days.
+
+Position point and mark at the beginning and end of the block of days
+you want entered and type @kbd{i b}. This sets up the diary entry's
+date info and positions point so you can write the text of the entry.
+People usually use this command for trips or vacations.
+@end table
+
+@node European Calendar Style
+@subsection European Calendar Style
+@cindex European date style (Calendar, V19)
+@cindex American date style (Calendar, V19)
+@cindex dates, style of writing (Calendar, V19)
+
+By default, Emacs interprets and displays diary dates in civilian
+American form, @samp{@var{month}/@var{day}/@var{year}}:
+@samp{2/15/1993}, or @samp{February 15, 1993}.
+
+@vindex european-calendar-style @r{(V19)}
+@cindex European calendar style (V19)
+Alternatively, you can specify the European calendar style for writing
+dates: @samp{@var{day}/@var{month}/@var{year}}, @samp{15/2/1993} or
+@samp{15 February 1993}. To do this, set the variable
+@code{european-calendar-style} to @code{t}, before using any calendar or
+diary command. This also affects display of dates.
+
+ Here's how to do this in your @file{.emacs} file:
+
+@example
+(setq european-calendar-style t)
+@end example
+
+@node Simple and Fancy
+@subsection Simple and Fancy Diary Display
+@cindex Simple Diary mode (V19)
+@cindex Fancy Diary mode (V19)
+
+There are two modes for displaying a subset of diary entries: Simple
+mode and Fancy mode. Fancy mode provides a more dramatic display for
+the diary, and can also display the actual matching date for diary
+entries that match more than one date.
+
+@vindex diary-display-hook @r{(V19)}
+@findex fancy-diary-display @r{(V19)}
+By default, Emacs uses Simple mode, which is quicker than Fancy mode.
+Another advantage of Simple mode is that you can edit the displayed
+diary entries ``in place'' and save them. When you use Fancy mode, it
+is useless to edit the displayed subset of the diary; instead you must
+visit the diary file separately. To select Fancy mode, set
+@code{diary-display-hook} to @code{fancy-diary-display} like this:
+
+@example
+(setq diary-display-hook 'fancy-diary-display)
+@end example
+
+@node Other Diary Features
+@subsection Other Diary Features
+
+Here are some additional diary features. These will be explained in
+full in @cite{The GNU Emacs Extensions Manual}.
+
+You can schedule meetings on a date such as the first Tuesday of every
+month. This is called an @dfn{offset} date. The diary has commands
+for specifying such meetings, but not in Calendar mode. To create
+such an entry, you need to edit the diary file yourself.
+@c !!! reference to diary offset in
+@c !!! xref{diary offset, , Offset Events, calendar, The GNU Emacs
+@c !!! Calendar}, for more information.
+
+You can make entries according to Hebrew and Islamic dates. Calendar
+mode provides commands of the form @kbd{i h d} to add a diary entry
+for the Hebrew date corresponding to the selected date and @kbd{i i d}
+to add a diary entry for the Islamic date corresponding to the selected
+date. You can make entries that repeat every week, month, or year.
+Before using these commands, you must set the
+@code{nongregorian-diary-listing-hook} and the
+@code{nongregorian-diary-marking-hook} in your @file{.emacs} file.
+@c !!! reference to Hebrew/Islamic Entries in The GNU Emacs Calendar
+@c !!! @xref{Hebrew/Islamic Entries, , Hebrew- and Islamic-Date Diary
+@c !!! Entries, calendar, The GNU Emacs Calendar}.
+
+You can include other diary files in your diary display. This way, a
+group of people can share a common diary file.
+@c !!! reference to Including Diary Files in The GNU Emacs Calendar
+@c !!! xref{Including Diary Files, , Including Other Diary Files, calendar, The
+@c !!! GNU Emacs Calendar}.
+
+@node Startup Diary
+@subsection Displaying your Diary on Emacs Startup
+@cindex diary and Emacs startup (V19)
+
+If you start a new Emacs each day, you might want to display your diary
+automatically at that time. To do so, put this in your @file{.emacs}
+file:
+
+@example
+(diary)
+@end example
+
+If you want to see both the calendar and your diary at startup, use this
+instead:
+
+@example
+@group
+(setq view-diary-entries-initially t)
+(calendar)
+@end group
+@end example
+
+@node Printing Diary
+@subsection Printing the Displayed Part of the Diary
+@cindex Printing diary (V19)
+
+@findex print-diary-entries @r{(V19)}
+To print the selected diary entries as they appear on the screen, use
+@kbd{M-x print-diary-entries}. The same variables that customize
+@code{lpr-buffer} also affect this command.
+
+In Simple mode, the diary display buffer uses selective display
+(@pxref{Selective Display}). This means that what you see on the screen
+is just part of the text in the Emacs buffer. The diary entries that
+don't apply to the dates you asked for are still in the buffer, but
+hidden. The ordinary printing commands such as @code{lpr-buffer} would
+not do what you want; they print the entire text, including the hidden
+parts. This is why we need @code{print-diary-entries}.
+
+@node Version Control
+@section Version Control
+@cindex version control
+
+ @dfn{Version control systems} are packages that can record multiple
+versions of a source file, usually storing the unchanged parts of the
+file just once. Version control systems also record history information
+such as the creation time of each version, who created it, and a
+description of what was changed in that version.
+
+ The GNU project recommends the version control system known as RCS,
+which is free software and available from the Free Software Foundation.
+Emacs supports use of either RCS or SCCS (a proprietary, but widely
+used, version control system that is not quite as powerful as RCS)
+through a facility called VC. The same Emacs commands work with either
+RCS or SCCS, so you hardly have to know which one of them you are
+using.
+
+@menu
+* Concepts of VC::
+* Editing with VC::
+* Variables for Check-in/out::
+* Comparing Versions::
+* VC Status::
+* Renaming and VC::
+* Snapshots::
+* Log Entries::
+* Change Logs and VC::
+* Version Headers::
+@end menu
+
+@node Concepts of VC
+@subsection Concepts of Version Control
+@cindex RCS
+@cindex SCCS
+@cindex master file
+@cindex registered file
+@cindex work file
+
+ When a file is under version control, we also say that it is
+@dfn{registered} in the version control system. Each registered file
+has a corresponding @dfn{master file} which represents the file's
+present state plus its change history, so that you can reconstruct from
+it either the current version or any specified earlier version. Usually
+the master file also records a change comment for each version.
+
+ The file that is maintained under version control is sometimes called
+the @dfn{work file} corresponding to its master file.
+
+@cindex checking out files
+@cindex checking in files
+@cindex locking and version control
+ To examine a file, you @dfn{check it out}. This extracts a version
+of the file (typically, the most recent) from the master. If you want
+to edit the file, you must check it out @dfn{locked}. Only one user can
+do this at a time for any given source file. When you are done with
+your editing, you must @dfn{check in} the new version. This records the
+new version in the master file, and unlocks the source file so that
+other people can lock it and thus modify it.
+
+ These are the basic operations of version control.
+Checking in and checking out both use the single Emacs command
+@w{@kbd{C-x C-q}} (@code{vc-toggle-read-only}).
+
+@node Editing with VC
+@subsection Editing with Version Control
+
+ When you visit a file that is maintained using version control, the
+mode line displays @samp{RCS} or @samp{SCCS} to inform you that version
+control is in use, and also (in case you care) which low-level system
+the file is actually stored in. Normally, such a source file is
+read-only, and the mode line indicates this with @samp{%%}.)
+
+ These are the commands that you use to edit a file maintained with
+version control:
+
+@table @kbd
+@item C-x C-q
+Check the visited file in or out.
+
+@item C-x v u
+Revert the buffer and the file to the last checked in version.
+
+@item C-x v c
+Remove the last-entered change from the master for the visited file.
+This undoes your last check-in.
+
+@item C-x v i
+Register the visited file in version control.
+@end table
+
+@noindent
+(@kbd{C-x v} is the prefix key for version control commands; all of these
+commands except for @kbd{C-x C-q} start with @kbd{C-x v}.)
+
+@kindex C-x C-q @r{(V19)}
+@findex vc-toggle-read-only @r{(V19)}
+ If you want to edit the file, type @kbd{C-x C-q}
+(@code{vc-toggle-read-only}). This @dfn{checks out} and locks the file,
+so that you can edit it. The file is writable after check-out, but only
+for you, not for anyone else.
+
+@vindex vc-make-backups @r{(V19)}
+ Emacs does not save backup files for source files that are maintained
+with version control. If you want to make backup files despite version
+control, set the variable @code{vc-make-backups} to a non-@code{nil} value.
+
+ When you are finished editing the file, type @kbd{C-x C-q} again.
+When used on a file that is checked out, this command checks the file
+in. But check-in does not start immediately; first, you must enter a
+@dfn{log entry}---a description of the changes in the new version.
+@kbd{C-x C-q} pops up a buffer for you to enter this in. When you are
+finished typing in the log entry, type @kbd{C-c C-c} to terminate it; this is
+when actual check-in takes place.
+
+ Once you have checked in your changes, the file is unlocked, so that
+other users can lock it and modify it.
+
+@vindex vc-keep-workfiles @r{(V19)}
+ Normally the work file exists all the time, whether it is locked or
+not. If you set @code{vc-keep-workfiles} to @code{nil}, then checking
+in a new version with @kbd{C-x C-q} deletes the work file; but any
+attempt to visit the file with Emacs creates it again.
+
+ Actually, it is not impossible to lock a file that someone else has
+locked. If you try to check out a file that is locked, @kbd{C-x C-q}
+asks you whether you want to ``steal the lock.'' If you say yes, the
+file becomes locked by you, but a message is sent to the person who had
+formerly locked the file, to inform him or her of what has happened.
+
+@kindex C-x v u @r{(V19)}
+@findex vc-revert-buffer @r{(V19)}
+ If you want to discard your current set of changes and revert to the
+last version checked in, use @kbd{C-x v u} (@code{vc-revert-buffer}).
+This cancels your last check-out, leaving the file unlocked. If you want
+to make a different set of changes, you must first check the file out
+again. @kbd{C-x v u} requies confirmation, unless it sees that
+you haven't made any changes since the last checked-in version.
+
+ @kbd{C-x v u} is also the command to use if you lock a file and then
+don't actually change it.
+
+@kindex C-x v c @r{(V19)}
+@findex vc-cancel-version @r{(V19)}
+ You can even cancel a change after checking it in, with @kbd{C-x v c}
+(@code{vc-cancel-version}). Normally, @kbd{C-x v c} reverts your
+workfile and buffer to the previous version (the one that precedes the
+version that is deleted), but you can prevent the reversion by giving
+the command a prefix argument. Then the buffer does not change.
+
+ This command with a prefix argument is useful when you have checked in
+a change and then discover a trivial error in it; you can cancel the
+erroneous check-in, fix the error, and repeat the check-in.
+
+ Be careful when invoking @kbd{C-x v c}, as it is easy to throw away a
+lot of work with it. To help you be careful, this command always asks
+for confirmation with @samp{yes}.
+
+@kindex C-x v i @r{(V19)}
+@findex vc-register @r{(V19)}
+ You can register the visited file for version control using
+@w{@kbd{C-x v i}} (@code{vc-register}). This uses RCS if RCS
+is installed on your system; otherwise, it uses SCCS.
+
+ By default, the initial version number is 1.1. If you want to use a
+different number, give @kbd{C-x v i} a prefix argument; then it reads
+the initial version number using the minibuffer.
+
+ After @kbd{C-x v i}, the file is unlocked and read-only. Type
+@kbd{C-x C-q} if you wish to edit it.
+
+@vindex vc-initial-comment @r{(V19)}
+ If @code{vc-initial-comment} is non-@code{nil}, @kbd{C-x v i} reads
+an initial comment (much like a log entry) to describe the purpose of
+this source file.
+
+@node Variables for Check-in/out
+@subsection Variables Affecting Check-in and Check-out
+@c There is no need to tell users about vc-master-templates.
+
+@vindex vc-suppress-confirm @r{(V19)}
+ If @code{vc-suppress-confirm} is non-@code{nil}, then @kbd{C-x C-q}
+and @kbd{C-x v i} can save the current buffer without asking, and
+@kbd{C-x v u} also operates without asking for confirmation.
+(This variable does not affect @kbd{C-x v c}; that is so drastic
+that it should always ask for confirmation.)
+
+@vindex vc-command-messages @r{(V19)}
+ VC mode does much of its work by running the shell commands for RCS
+and SCCS. If @code{vc-command-messages} is non-@code{nil}, VC displays
+messages to indicate which shell commands it runs, and additional
+messages when the commands finish.
+
+ Normally, VC assumes that it can deduce the locked/unlocked state of
+files by looking at the file permissions of the work file; this is
+fast. However, if the @file{RCS} or @file{SCCS} subdirectory is
+actually a symbolic link, then VC does not trust the file permissions to
+reflect this status.
+
+@vindex vc-mistrust-permissions @r{(V19)}
+You can specify the criterion for whether to trust the file permissions
+by setting the variable @code{vc-mistrust-permissions}. Its value may
+be @code{t} (always mistrust the file permissions and check the master
+file), @code{nil} (always trust the file permissions), or a function of
+one argument which makes the decision. The argument is the directory
+name of the @file{RCS} or @file{SCCS} subdirectory. A non-@code{nil}
+value from the function says to mistrust the file permissions.
+
+ If you find that the file permissions of work files are changed
+erroneously, then you can set @code{vc-mistrust-permissions} to @code{t}
+so that VC always checks the master file.
+
+@node Log Entries
+@subsection Log Entries
+
+When you're editing an initial or change comment for inclusion in a
+master file, finish your entry by typing @kbd{C-c C-c}.
+
+@table @kbd
+@item C-c C-c
+Finish the comment edit normally (@code{vc-finish-logentry}).
+This finishes check-in.
+@end table
+
+To abort check-in, just don't type @kbd{C-c C-c} in that buffer. You
+can switch buffers and do other editing. As long as you don't try to
+check in another file, the comment you were editing remains in its
+buffer, and you can go back to that buffer at any time to complete the
+check-in.
+
+If you change several source files for the same reason, it is often
+convenient to specify the same log entry for many of the files. To do
+this, use the history of previous log entries. The commands
+@kbd{M-n}, @kbd{M-p}, @kbd{M-s} and @kbd{M-r} for doing this work just
+like the minibuffer history commands (except that they don't use the
+minibuffer).
+
+The history of previous log entries is actually stored in previous pages
+of the log entry editing buffer; they are normally hidden by narrowing.
+
+@vindex vc-log-mode-hook @r{(V19)}
+Each time you check in a file, the log entry buffer is put into VC Log
+mode, which involves running two hook variables: @code{text-mode-hook}
+and @code{vc-log-mode-hook}.
+
+@node Change Logs and VC
+@subsection Change Logs and VC
+
+Emacs users often record brief summaries of program changes in a file
+called @file{ChangeLog}, which is kept in the same directory as the
+source files, and is usually meant to be distributed along with the
+source files. You can maintain @file{ChangeLog} from the version
+control logs with the following command.
+
+@table @kbd
+@item C-x v a
+@kindex C-x v a @r{(V19)}
+@findex vc-update-change-log @r{(V19)}
+Visit the current directory's change log file and create new entries for
+versions checked in since the most recent entry in the change log file
+(@code{vc-update-change-log}).
+
+This command works with RCS only; it does not work with SCCS.
+@end table
+
+For example, suppose the first line of @file{ChangeLog} is dated 10
+April 1992, and suppose the only check-in since then was by Nathaniel
+Bowditch to @file{rcs2log} on 8 May 1992 with log text @samp{Ignore log
+messages that start with `#'.}. Then @kbd{C-x v a} visits
+@file{ChangeLog} and inserts text like this:
+
+@example
+@group
+Fri May 8 21:45:00 1992 Nathaniel Bowditch (nat@@apn.org)
+
+ * rcs2log: Ignore log messages that start with `#'.
+@end group
+@end example
+
+@noindent
+You can then further edit as you wish.
+
+A log entry whose text begins with @samp{#} is not copied to
+@file{ChangeLog}. For example, if you merely fix some misspellings in
+comments, you can log the change with an entry beginning with @samp{#}
+to avoid putting such trivia into @file{ChangeLog}.
+
+When @kbd{C-x v a} adds several change log entries at once, it groups
+related log entries together if they all are checked in by the same
+author at nearly the same time. If the log entries for several such
+files all have the same text, it coalesces them into a single entry.
+For example, suppose the most recent check-ins have the following log
+entries:
+
+@example
+@exdent For @file{vc.texinfo}:
+Fix expansion typos.
+@exdent For @file{vc.el}:
+Don't call expand-file-name.
+@exdent For @file{vc-hooks.el}:
+Don't call expand-file-name.
+@end example
+
+They appear like this in @file{ChangeLog}:
+
+@example
+@group
+Wed Apr 1 08:57:59 1992 Nathaniel Bowditch (nat@@apn.org)
+
+ * vc.texinfo: Fix expansion typos.
+
+ * vc.el, vc-hooks.el: Don't call expand-file-name.
+@end group
+@end example
+
+Normally, @kbd{C-x v a} separates log entries by a blank line, but you
+can mark several related log entries to be clumped together (without an
+intervening blank line) by starting the text of each related log entry
+with a label of the form @w{@samp{@{@var{clumpname}@} }}. The label
+itself is not copied to @file{ChangeLog}. For example, suppose the log
+entries are:
+
+@example
+@exdent For @file{vc.texinfo}:
+@{expand@} Fix expansion typos.
+@exdent For @file{vc.el}:
+@{expand@} Don't call expand-file-name.
+@exdent For @file{vc-hooks.el}:
+@{expand@} Don't call expand-file-name.
+@end example
+
+Then the text in @file{ChangeLog} looks like this:
+
+@example
+@group
+Wed Apr 1 08:57:59 1992 Nathaniel Bowditch (nat@@apn.org)
+
+ * vc.texinfo: Fix expansion typos.
+ * vc.el, vc-hooks.el: Don't call expand-file-name.
+@end group
+@end example
+
+Normally, the log entry for file @file{foo} is displayed as @samp{* foo:
+@var{text of log entry}}. But by convention, the @samp{:} after
+@file{foo} is omitted if the text of the log entry starts with
+@w{@samp{(@var{functionname}): }}. For example, if the log entry for
+@file{vc.el} is @samp{(vc-do-command): Check call-process status.}, then
+the text in @file{ChangeLog} looks like this:
+
+@example
+@group
+Wed May 6 10:53:00 1992 Nathaniel Bowditch (nat@@apn.org)
+
+ * vc.el (vc-do-command): Check call-process status.
+@end group
+@end example
+
+@node Comparing Versions
+@subsection Comparing Versions
+
+@findex vc-diff @r{(V19)}
+@kindex C-x v = @r{(V19)}
+ To compare two versions of a file, use @kbd{C-x v =} (@code{vc-diff}).
+
+ Plain @kbd{C-x v =} compares the current buffer contents (saving them
+in the file if necessary) with the last checked-in version of the file.
+With a prefix argument, @kbd{C-x v =} reads a filename and two version
+numbers, and compares those versions of the file you specify.
+
+ If you supply a directory name instead of the name of a work file,
+this command compares the two specified versions of all registered files
+in that directory and its subdirectories. You can also specify a
+snapshot name (@pxref{Snapshots}) instead of one or both version
+numbers.
+
+ You can specify a checked-in version by its number; you can specify
+the most recent checked-in version with @samp{-}; and you can specify
+the current buffer contents with @samp{+}. Thus, you can compare two
+checked-in versions, or compare a checked-in version with the text you
+are editing.
+@c ??? + and - as args are not implemented yet.
+
+@c ??? Currently it uses vc-diff-options.
+ This command works by running the @code{diff} utility, getting the
+options from the variable @code{diff-switches}. It displays the output
+in a special buffer in another window.
+
+@node VC Status
+@subsection VC Status Commands
+
+@kindex C-x v l @r{(V19)}
+@findex vc-print-log @r{(V19)}
+ To get the detailed version control status of one file, type @kbd{C-x
+v l} (@code{vc-print-log}). It displays the history of changes to the
+current file, including the text of the log entries. The output appears
+in a separate window.
+
+ When you are working on a large program, it's often useful to find all
+the files that are currently locked, or all the files maintained in
+version control at all. You can do so using these commands, both of
+which operate on the branch of the file system starting at the current
+directory.
+
+@kindex C-x v d @r{(V19)}
+@findex vc-directory @r{(V19)}
+ You can use @kbd{C-x v d} (@code{vc-directory}) to show all the locked
+files in or beneath the current directory. This includes all files that
+are locked by any user.
+
+ With a prefix argument, @kbd{C-x v d} shows all the version control
+activity in the current directory---it lists all files in or beneath the
+current directory that are maintained with version control.
+
+@node Renaming and VC
+@subsection Renaming VC Work Files and Master Files
+
+@findex vc-rename-file @r{(V19)}
+ When you rename a registered file, you must also rename its master
+file correspondingly to get proper results. Use @code{vc-rename-file}
+to rename the source file as you specify, and rename its master file
+accordingly. It also updates any snapshots (@pxref{Snapshots}) that
+mention the file, so that they use the new name; despite this, the
+snapshot thus modified may not completely work (@pxref{Snapshot
+Caveats}).
+
+ You cannot use @code{vc-rename-file} on a file that is locked by
+someone else.
+
+ @code{vc-rename-file} is not bound to a key because it's not likely
+to be used frequently.
+
+@node Snapshots
+@subsection Snapshots
+@cindex snapshots and version control
+
+ A @dfn{snapshot} is a named set of file versions (one for each
+registered file) that you can treat as a unit. One important kind of
+snapshot is a @dfn{release}, a (theoretically) stable version of the
+system that is ready for distribution to users.
+
+@menu
+* Making Snapshots:: The snapshot facilities.
+* Snapshot Caveats:: Things to be careful of, when using snapshots.
+@end menu
+
+@node Making Snapshots
+@subsubsection Making and Using Snapshots
+
+ There are two basic commands for snapshots; one makes a
+snapshot with a given name, the other retrieves a named snapshot.
+
+@table @code
+@item C-x v s @var{name} @key{RET}
+@kindex C-x v s @r{(V19)}
+@findex vc-create-snapshot @r{(V19)}
+Define the last saved versions of every registered file in or under the
+current directory as a snapshot named @var{name}
+(@code{vc-create-snapshot}).
+
+@item C-x v r @var{name} @key{RET}
+@kindex C-x v r @r{(V19)}
+@findex vc-retrieve-snapshot @r{(V19)}
+Check out all registered files at or below the current directory level
+using whatever versions correspond to the snapshot @var{name}
+(@code{vc-retrieve-snapshot}).
+
+This function reports an error if any files are locked at or below the
+current directory, without changing anything; this is to avoid
+overwriting work in progress.
+@end table
+
+You shouldn't need to use @code{vc-retrieve-snapshot} very often; you
+can get difference reports between two snapshots without retrieving
+either one, using @kbd{C-x =} (@pxref{Comparing Versions}). Thus,
+retrieving a snapshot is only necessary if you need to study or compile
+portions of the snapshot.
+
+A snapshot uses a very small amount of resources---just enough to record
+the list of file names and which version belongs to the snapshot. Thus,
+you need not hesitate to create snapshots whenever they are useful.
+
+You can give a snapshot name as an argument to @kbd{C-x v =}
+(@pxref{Comparing Versions}). Thus, you can use it to compare a
+snapshot against the current files, or two snapshots against each other,
+or a snapshot against a named version.
+
+@node Snapshot Caveats
+@subsubsection Snapshot Caveats
+
+@cindex named configurations (RCS)
+VC's snapshot facilities are modeled on RCS's named-configuration
+support. They use RCS's native facilities for this, so under VC
+snapshots made using RCS are visible even when you bypass VC.
+
+@c !!! worded verbosely to avoid overfull hbox.
+For SCCS, VC implements snapshots itself. The files it uses contain
+name/file/version-number triples. These snapshots are visible only
+through VC.
+
+File renaming and deletion can create some difficulties with snapshots.
+This is not a VC-specific problem, but a general design issue in version
+control systems that no one has solved very well yet.
+
+If you rename a registered file, you need to rename its master along
+with it (the function @code{vc-rename-file} does this automatically).
+If you are using SCCS, you must also update the records of the snapshot,
+to mention the file by its new name (@code{vc-rename-file} does this,
+too). This makes the snapshot remain valid for retrieval, but it does
+not solve all problems.
+
+For example, some of the files in the program probably refer to others
+by name. At the very least, the makefile probably mentions the file
+that you renamed. If you retrieve an old snapshot, the renamed file
+is retrieved under its new name, which is not the name that the makefile
+expects. So the program won't really work.
+
+If you use snapshots, don't rename either work files or master files
+except by means of @code{vc-rename-file}. It knows how to update
+snapshots so that you can still retrieve them. An old snapshot that
+refers to a master file that no longer exists under the recorded name is
+invalid; VC can no longer retrieve it. It would be beyond the scope of this
+manual to explain enough about RCS and SCCS to teach the reader how to
+update the snapshots by hand.
+
+@node Version Headers
+@subsection Inserting Version Control Headers
+
+ Sometimes it is convenient to put version identification strings
+directly into working files. Certain special strings called
+@dfn{version headers} are replaced in each successive version by the
+number of that version.
+
+@kindex C-x v h @r{(V19)}
+@findex vc-insert-headers @r{(V19)}
+ You can use the @kbd{C-x v h} command (@code{vc-insert-headers}) to
+insert a suitable header string.
+
+@table @kbd
+@item C-x v h
+Insert headers in a file for use with your version-control system.
+@end table
+
+@vindex vc-header-string @r{(V19)}
+@c ??? Currently the name is vc-header-strings
+The default header string is @samp{$ld$} for RCS and @samp{%W%} for
+SCCS. You can specify other headers to insert by setting the variable
+@code{vc-header-string}. Its value (if non-@code{nil}) should be the
+string to be inserted. You can also specify a list of strings; then
+each string in the list is inserted as a separate header on a line of
+its own. (It is often important to use ``superfluous'' backslashes when
+writing a Lisp string constant for this use, to prevent the string in
+the constant from being interpreted as a header itself if the Emacs Lisp
+file containing it is maintained with version control.)
+
+@vindex vc-comment-alist @r{(V19)}
+Each header is inserted surrounded by tabs, inside comment delimiters,
+on a new line at the start of the buffer. Normally the ordinary comment
+start and comment end strings of the current mode are used, but for
+certain modes, there are special comment delimiters for this purpose;
+the variable @code{vc-comment-alist} specifies them. Each element of
+this list has the form @code{(@var{mode} @var{starter} @var{ender})}.
+
+@vindex vc-static-header-alist @r{(V19)}
+@code{vc-static-header-alist} is consulted to add further strings based
+on the name of the buffer. Its value should be a list of
+dotted pairs; the @sc{car} of each pair is a regular expression that
+should match the buffer name, and the @sc{cdr} is the format to use on
+each header. A string is inserted for each file name pattern that
+matches the buffer name, and for each header taken from
+@code{vc-header-string}. The default value for
+@code{vc-static-header-alist} is:
+
+@example
+@group
+(("\\.c$" .
+ "\n#ifndef lint\nstatic char vcid[] = \"\%s\";\n\
+#endif /* lint */\n"))
+@end group
+@end example
+
+@noindent
+which specifies insertion of a string of this form:
+
+@example
+@group
+
+#ifndef lint
+static char vcid[] = "@var{header-string}";
+#endif /* lint */
+@end group
+@end example
+
+@node Emerge
+@section Emerge
+@cindex Emerge (V19)
+@cindex merging files (V19)
+
+It's not unusual for programmers to get their signals crossed and modify
+the same program in two different directions. To recover from this
+confusion, you need to merge the two versions. Emerge makes this
+easier.
+
+@menu
+* Overview of Emerge::
+* Submodes of Emerge::
+* State of Difference::
+* Merge Commands::
+* Exiting Emerge::
+* Combining in Emerge::
+* Fine Points of Emerge::
+@end menu
+
+@node Overview of Emerge
+@subsection Overview of Emerge
+
+To start Emerge, run one of these four commands:
+
+@table @kbd
+@item M-x emerge-files
+@findex emerge-files @r{(V19)}
+Merge two specified files.
+
+@item M-x emerge-files-with-ancestor
+@findex emerge-files-with-ancestor @r{(V19)}
+Merge two specified files, with reference to a common ancestor.
+
+@item M-x emerge-buffers
+@findex emerge-buffers @r{(V19)}
+Merge two buffers (the currently accessible portions).
+
+@item M-x emerge-buffers-with-ancestor
+@findex emerge-buffers-with-ancestor @r{(V19)}
+Merge two buffers (the currently accessible portions) with reference to a
+common ancestor in another buffer.
+@end table
+
+@cindex merge buffer (Emerge)
+@cindex A and B buffers (Emerge)
+The Emerge commands compare two texts, and display the results in three
+buffers: one for each input text (the @dfn{A buffer} and the @dfn{B
+buffer}), and one (the @dfn{merge buffer}) where merging takes place.
+The merge buffer does not show just the differences. Rather, it shows
+you the full text, but wherever the input texts differ, you can choose
+which one of them to include in the merge buffer.
+
+If a common ancestor version is available, from which the two texts to
+be merged were both derived, Emerge can use it to guess which
+alternative is right. Wherever one current version agrees with the
+ancestor, Emerge presumes that the other current version is a deliberate
+change which should be kept in the merged version. Use the
+``with-ancestor'' commands if you want to specify a common ancestor
+text. These commands read three file or buffer names---variant A,
+variant B, and the common ancestor.
+
+After the comparison is done and the buffers are prepared, the actual
+merging starts. You control the merging interactively by editing the
+merge buffer. The merge buffer shows you a full merged text, not just
+differences. For each point where the input texts differ, you can
+choose which one of them to include in the merge buffer.
+
+The merge buffer has a special major mode, Emerge mode, with commands
+for making these choices. But you can also edit the buffer with
+ordinary Emacs commands.
+
+At any given time, the attention of Emerge is focused on one particular
+difference, called the @dfn{selected} difference. This difference is
+marked off in the three buffers by
+
+@example
+vvvvvvvvvvvvvvvvvvvv
+@end example
+
+@noindent
+above and
+
+@example
+^^^^^^^^^^^^^^^^^^^^
+@end example
+
+@noindent
+below. Emerge numbers all the differences sequentially and the mode
+line always shows the number of the selected difference.
+
+Normally, the merge buffer starts out with the A version of the text.
+But when the A version of a part of the buffer agrees with the common
+ancestor, then the B version is preferred for that part.
+
+Normally, Emerge stores the merged output in place of the first input
+text (the A file or buffer). If you give a prefix argument to
+@code{emerge-files} or @code{emerge-files-with-ancestor}, it reads the
+name of the output file using the minibuffer. (This is the last file
+name those commands read.)
+
+If you abort Emerge with @kbd{C-u q}, the output is not saved.
+
+@node Submodes of Emerge
+@subsection Submodes of Emerge
+
+You can choose between two modes for giving merge commands: Fast mode
+and Edit mode. In Fast mode, basic Emerge commands are single
+characters, but ordinary Emacs commands are disabled. This is
+convenient if you use only Emerge commands.
+
+In Edit mode, all Emerge commands start with the prefix character
+@kbd{C-c}, and the normal Emacs commands are also available. This
+allows editing the merge buffer, but slows down Emerge operations.
+
+Use @kbd{e} to switch to Edit mode, and @kbd{f} to switch to Fast mode.
+The mode line indicates Edit and Fast modes with @samp{E} and @samp{F}.
+
+Emerge has two additional submodes that affect how particular merge
+commands work: Auto Advance mode and Skip Prefers mode.
+
+If Auto Advance mode is in effect, the @kbd{a} and @kbd{b} commands
+advance to the next difference. This lets you go through the merge
+faster doing ordinary things. The mode line indicates Auto Advance mode
+with @samp{A}.
+
+If Skip Prefers mode is in effect, the @kbd{n} and @kbd{p} commands skip
+over differences in states prefer-A and prefer-B. Thus you will only
+see differences for which neither version is presumed ``correct''. The
+mode line indicates Skip Prefers mode with @samp{S}.
+
+@findex emerge-auto-advance-mode @r{(V19)}
+@findex emerge-skip-prefers-mode @r{(V19)}
+Use the command @code{emerge-auto-advance-mode} to set or clear Auto
+Advance mode. Use @code{emerge-skip-prefers-mode} to set or clear Skip
+Prefers mode. A positive argument turns the mode on, a nonpositive
+argument turns it off, and no argument toggles it.
+
+@node State of Difference
+@subsection State of a Difference
+
+In the merge buffer, a difference is marked
+@samp{vvvvvvvvvvvvvvvvvvvv} above and @samp{^^^^^^^^^^^^^^^^^^^^}
+below. Such a difference can have one of seven states:
+
+@table @asis
+@item A
+The difference is showing the A version. The @kbd{a} command always
+produces this state; the mode line indicates it with @samp{A}.
+
+@item B
+The difference is showing the B version. The @kbd{b} command always
+produces this state; the mode line indicates it with @samp{B}.
+
+@item default-A
+@itemx default-B
+The difference is showing the A or the B state by default, because you
+haven't made a choice. All differences start in the default-A state
+(and thus the merge buffer is a copy of the A buffer), except those for
+which one alternative is ``preferred'' (see below).
+
+When you select a difference, its state changes from default-A or
+default-B to plain A or B. Thus, the selected difference never has
+state default-A or default-B, and these states are never displayed in
+the mode line.
+
+The command @kbd{d a} chooses default-A as the default state, and @kbd{d
+b} chooses default-B. This chosen default applies to all differences
+which you haven't selected and for which no alternative is preferred.
+If you are moving through the merge sequentially, the differences you
+haven't selected are those following the selected one. Thus, while
+moving sequentially, you can effectively make the A version the default
+for some sections of the merge buffer and the B version the default for
+others by using @kbd{d a} and @kbd{d b} at the end of each section.
+
+@item prefer-A
+@itemx prefer-B
+The difference is showing the A or B state because it is
+@dfn{preferred}. This means that you haven't made an explicit choice,
+but one alternative seems likely to be right because the other
+alternative agrees with the common ancestor. Thus, where the A buffer
+agrees with the common ancestor, the B version is preferred, because
+chances are it is the one that was actually changed.
+
+These two states are displayed in the mode line as @samp{A*} and @samp{B*}.
+
+@item combined
+The difference is showing a combination of the A and B states, as a
+result of the @kbd{x c} or @kbd{x C} commands.
+
+Once a difference is in this state, the @kbd{a} and @kbd{b} commands
+don't do anything to it unless you give them a prefix argument.
+
+The mode line displays this state as @samp{comb}.
+@end table
+
+@node Merge Commands
+@subsection Merge Commands
+
+Here are the Merge commands for Fast mode; in Edit mode, precede these with
+@kbd{C-c} and turn all the letters into control characters.
+
+@table @kbd
+@item p
+Select the previous difference.
+
+@item n
+Select the next difference.
+
+@item a
+Choose the A version of this difference.
+
+@item b
+Choose the B version of this difference.
+
+@item j
+Select a particular difference; specify the sequence number of that
+difference as a prefix argument.
+
+@item M-x emerge-select-difference
+@c ??? This isn't true yet.
+Select the run of differences containing the current location. You can
+use this command in the merge buffer or in the A or B buffer.
+
+@item q
+Quit---finish the merge. With an argument, abort the merge.
+
+@item f
+Go into fast mode.
+
+@item e
+Go into edit mode.
+
+@item l
+Recenter (like @kbd{C-l}) all three windows.
+
+@item -
+Specify part of a prefix numeric argument.
+@c Don't use itemx here, it is confusing in printed output!
+@itemx @var{digit}
+Also specify part of a prefix numeric argument.
+
+@item d a
+Choose the A version as the default from here down in
+the merge buffer.
+
+@item d b
+Choose the B version as the default from here down in
+the merge buffer.
+
+@item c a
+Copy the A version of this difference into the kill ring.
+
+@item c b
+Copy the B version of this difference into the kill ring.
+
+@item i a
+Insert the A version of this difference at the point.
+
+@item i b
+Insert the B version of this difference at the point.
+
+@item m
+Put the point and mark around the difference region.
+
+@item ^
+Scroll all three windows down (like @kbd{M-v}).
+
+@item v
+Scroll all three windows up (like @kbd{C-v}).
+
+@item <
+Scroll all three windows left (like @kbd{C-x <}).
+
+@item >
+Scroll all three windows right (like @kbd{C-x >}).
+
+@item |
+Reset horizontal scroll on all three windows.
+
+@item x 1
+Shrink the merge window to one line. (Use @kbd{C-u l} to restore it
+to full size.)
+
+@item x c
+Combine the two versions of this difference.
+
+@item x f
+Show the files/buffers Emerge is operating on in Help window.
+(Use @kbd{C-u l} to restore windows.)
+
+@item x j
+Join this difference with the following one.
+(@kbd{C-u x j} joins this difference with the previous one.)
+
+@item x s
+Split this difference into two differences. Before you use this
+command, position point in each of the three buffers to the place where
+you want to split the difference.
+
+@item x t
+Trim identical lines off top and bottom of the difference.
+Such lines occur when the A and B versions are
+identical but differ from the ancestor version.
+@end table
+
+@node Exiting Emerge
+@subsection Exiting Emerge
+
+The @kbd{q} (@code{emerge-quit}) command finishes the merge, storing the
+results into the output file. It restores the A and B buffers to their
+proper contents, or kills them if they were created by Emerge. It also
+disables the Emerge commands in the merge buffer, since executing them
+later could damage the contents of the various buffers.
+
+@kbd{C-u q} aborts the merge. Aborting means that Emerge does not write
+the output file.
+
+If Emerge was called from another Lisp program, then its return value
+is @code{t} or @code{nil} to indicate success or failure.
+
+@node Combining in Emerge
+@subsection Combining the Two Versions
+
+Sometimes you want to keep @emph{both} alternatives for a particular
+locus. To do this, use @kbd{x c}, which edits the merge buffer like this:
+
+@example
+@group
+#ifdef NEW
+@var{version from A file}
+#else /* NEW */
+@var{version from B file}
+#endif /* NEW */
+@end group
+@end example
+
+@vindex emerge-combine-template @r{(V19)}
+While this example shows C preprocessor conditionals delimiting the two
+alternative versions, you can specify the strings you want by setting
+the variable @code{emerge-combine-template} to a list of three strings.
+The default setting, which produces the results shown above, looks like this:
+
+@example
+@group
+("#ifdef NEW\n"
+ "#else /* NEW */\n"
+ "#endif /* NEW */\n")
+@end group
+@end example
+@c ??? This is not how it currently works;
+@c ??? emerge.el needs to be changed.
+
+@c ??? Must change the mechanism that disables saving during emerge
+@c ??? to use a write-file-function instead.
+
+@c ??? Emerge should use flag strings that start with # for C programs
+@c ??? and with ; for Lisp programs.
+
+@node Fine Points of Emerge
+@subsection Fine Points of Emerge
+
+You can have any number of merges going at once---just don't use any
+one buffer as input to more than one merge at once, since that will
+cause the read-only/modified/auto-save status save-and-restore to
+screw up.
+
+Starting Emerge can take a long time because it needs to compare the
+files. Emacs can't do anything else until @code{diff} finishes. Perhaps in
+the future someone will change Emerge to do the comparison in the
+background when the input files are large---then you could keep on doing
+other things with Emacs until Emerge gets ready to accept commands.
+
+@ignore
+@c ??? This name hasn't been changed yet.
+@vindex emerge-ok-lines-regexp @r{(V19)}
+Emerge tests each of the lines that differ against the regular
+expression @code{emerge-ok-lines-regexp}. If a line fails to fit the
+pattern, then Emerge displays a warning instead of displaying the merge
+buffer. After you get the warning, you must switch to the merge buffer
+and either continue the merge or abort it.
+@end ignore
+
+@vindex emerge-startup-hook @r{(V19)}
+After the merge has been set up, Emerge runs the hooks in
+@code{emerge-startup-hook}.
+
+During the merge, you musn't try to edit the A and B buffers yourself.
+Emerge modifies them temporarily, but ultimately puts them back the way
+they were.
+
+@node Debuggers
+@section Running Debuggers Under Emacs
+@cindex debuggers
+@cindex GDB
+@cindex DBX
+@cindex SDB
+
+@c Do you believe in GUD?
+The GUD (Grand Unified Debugger) library provides an interface to various
+symbolic debuggers from within Emacs. We recommend the debugger GDB,
+which is free software, but you can also run DBX or SDB if you have them.
+
+@menu
+* Starting GUD:: How to start a debugger subprocess.
+* Debugger Operation:: Connection between the debugger and source buffers.
+* Commands of GUD:: Keybindings for common commands.
+* GUD Customization:: Defining your own commands for GUD.
+@end menu
+
+@node Starting GUD
+@subsection Starting GUD
+
+There are three commands for starting a debugger. Each corresponds to a
+particular debugger program.
+
+@table @kbd
+@item M-x gdb @key{RET} @var{file} @key{RET}
+@itemx M-x dbx @key{RET} @var{file} @key{RET}
+@findex gdb @r{(V19)}
+@findex dbx @r{(V19)}
+Run GDB or DBX in a subprocess of Emacs. Both of these commands select
+the buffer used for input and output to the debugger.
+
+@item M-x sdb @key{RET} @var{file} @key{RET}
+@findex sdb @r{(V19)}
+Run SDB in a subprocess of Emacs. SDB's messages do not mention file
+names, so the Emacs interface to SDB depends on having a tags table
+(@pxref{Tags}) to find which file each function is in. If you have not
+visited a tags table or the tags table doesn't list one of the
+functions, you get a message saying @samp{The sdb support requires a
+valid tags table to work}. If this happens, generate a valid tags table
+in the working directory and try again.
+@end table
+
+You can only run one debugger process at a time.
+
+@node Debugger Operation
+@subsection Debugger Operation
+
+When you run a debugger with GUD, the debugger displays source files
+via Emacs---Emacs finds the source file and moves point to the line
+where the program is executing. An arrow (@samp{=>}) indicates the
+current execution line, and it stays put even if you move the cursor.
+
+You can start editing the file at any time. The arrow is not part of
+the file's text; it appears only on the screen. If you do modify a
+source file, keep in mind that inserting or deleting lines will throw
+off the arrow's positioning; GUD has no way of figuring out which line
+corresponded before your changes to the line number in a debugger
+message. Also, you'll typically have to recompile and restart the
+program for your changes to be reflected in the debugger's tables.
+
+If you wish, you can control your debugger process entirely through the
+debugger buffer, which uses a variant of Shell mode. All the usual
+commands for your debugger are available, and you can use the Shell mode
+history commands to repeat them.
+
+@node Commands of GUD
+@subsection Commands of GUD
+
+GUD provides a command available in all buffers for setting
+breakpoints. This command is defined globally because you need to use
+it in the source files' buffers.
+
+@table @kbd
+@item C-x @key{SPC}
+@kindex C-x @key{SPC} @r{(V19)}
+Set a breakpoint on the line that point is on.
+@end table
+
+The debugger buffer has a number of keybindings for invoking common
+debugging commands quickly:
+
+@table @kbd
+@item C-c C-l
+@kindex C-c C-l @r{(GUD in V19)}
+@findex gud-refresh @r{(V19)}
+Display in another window the last line referred to in the GUD
+buffer (that is, the line indicated in the last location message).
+This runs the command @code{gud-refresh}.
+
+@item C-c C-s
+@kindex C-c C-s @r{(GUD in V19)}
+@findex gud-step @r{(V19)}
+Execute a single line of code (@code{gud-step}). If the code contains
+a function call, execution stops after entering the called function.
+
+@item C-c C-n
+@kindex C-c C-n @r{(GUD in V19)}
+@findex gud-next @r{(V19)}
+Execute a single line of code, stepping across entire function calls
+at full speed (@code{gud-next}).
+
+@item C-c C-i
+@kindex C-c C-i @r{(GUD in V19)}
+@findex gud-stepi @r{(V19)}
+Execute a single machine instruction (@code{gud-stepi}).
+
+@item C-c C-c
+@kindex C-c C-c @r{(GUD in V19)}
+@findex gud-cont @r{(V19)}
+Continue execution until the next breakpoint, or other event that would
+normally stop the program (@code{gud-cont}).
+@end table
+
+The above commands are common to all supported debuggers. If you are
+using GDB or (some versions of) DBX, these additional commands are available:
+
+@table @kbd
+@item C-c <
+@kindex C-c < @r{(GUD in V19)}
+@findex gud-up @r{(V19)}
+Select the next enclosing stack frame (@code{gud-up}). This is
+equivalent to the @samp{up} command.
+
+@item C-c >
+@kindex C-c > @r{(GUD in V19)}
+@findex gud-down @r{(V19)}
+Select the next inner stack frame (@code{gud-down}). This is
+equivalent to the @samp{down} command.
+@end table
+
+If you are using GDB, two additional keybindings are available:
+
+@table @kbd
+@item C-c C-f
+@kindex C-c C-f @r{(GUD in V19)}
+@findex gud-finish @r{(V19)}
+Run the program until the selected stack frame returns (or until it
+stops for some other reason).
+
+@item @key{TAB}
+Complete the symbol in the buffer before point, using the set of all
+symbols known to GDB.
+@end table
+
+These commands interpret a prefix argument as a repeat count, when that
+makes sense.
+
+After each command that changes the program counter, GUD displays the
+new current source line, and updates the location of the arrow.
+
+@node GUD Customization
+@subsection GUD Customization
+
+@vindex gdb-mode-hook
+@vindex dbx-mode-hook
+@vindex sdb-mode-hook
+On startup, GUD executes one of the following hooks:
+@code{gdb-mode-hook}, if you are using GDB; @code{dbx-mode-hook}, if you
+are using DBX; and @code{sdb-mode-hook}, if you are using SDB. You can
+use these hooks to define custom keybindings for the debugger
+interaction buffer.
+
+Here is a convenient way to define a command that sends a particular
+command string to the debugger, and set up a key binding for it in the
+debugger interaction buffer:
+
+@findex gud-def @r{(V19)}
+@example
+(gud-def @var{function} @var{cmdstring} @var{binding} @var{docstring})
+@end example
+
+ This defines a command named @var{function} which sends
+@var{cmdstring} to the debugger process, with documentation string
+@var{docstring}, and binds it to @var{binding} in the debugger buffer's
+mode. (If @var{binding} is @code{nil}, this defines the command but
+does not make a binding for it; you can make a binding explicitly,
+perhaps using one of the above hooks.)
+
+ Commands defined with @code{gud-def} handle prefix arguments by
+passing them to the debugger, appended to end of @var{cmdstring} with a
+space in between. (This use of prefix arguments works with GDB and DBX,
+but not with SDB.)
+
+You can also set up commands that you can send to the debugger while in
+another buffer, such as a source file. Set the variable
+@code{gud-commands} to a list of strings containing debugger commands
+you might want to send.
+
+@table @kbd
+@item C-x &
+@kindex C-x & @r{(GUD in V19)}
+@findex send-gud-command @r{(V19)}
+Send a custom command to the debugger process
+(@code{send-gud-command}). Normally, send the @sc{car} of the
+@code{gud-commands} list; a prefix argument specifies which element of
+that list to use (counting from 0).
+
+If the string contains @samp{%s}, @kbd{C-x &} substitutes a numeric
+value found in the buffer at or near point. It looks for decimal,
+octal, or hexadecimal numbers, with @samp{0x} allowed. This lets you
+define commands to chase pointers whose numeric values have been
+displayed.
+@end table
+
+@node Other New Modes
+@section Other New Modes
+
+There is now a Perl mode for editing Perl programs and an Icon mode
+for editing Icon programs.
+
+@cindex C++ mode @r{(V19)}
+@findex fill-c++-comment @r{(V19)}
+C++ mode is like C mode, except that it understands C++ comment syntax
+and certain other differences between C and C++. It also has a command
+@code{fill-c++-comment} which fills a paragraph made of comment lines.
+The command @code{comment-region} is useful in C++ mode for commenting
+out several consecutive lines, or removing the commenting out of such
+lines.
+
+@cindex WordStar mode @r{(V19)}
+WordStar emulation is available---type @kbd{M-x wordstar-mode}.
+For more information, type @kbd{C-h f wordstar-mode @key{RET}}.
+
+@cindex Buffer Menu mode @r{(V19)}
+The command @kbd{C-o} in Buffer Menu mode now displays the current
+line's buffer in another window but does not select it. This is like
+the existing command @kbd{o} which selects the current line's buffer in
+another window.
+
+@menu
+* Asm Mode:: A major mode for editing assembler files.
+* Edebug Mode:: A new Lisp debugger.
+* Editing Binary Files::Hexl mode lets you edit a binary file as numbers.
+@end menu
+
+@node Asm Mode
+@subsection Asm Mode
+
+@cindex Asm mode @r{(V19)}
+Asm mode is a new major mode for editing files of assembler code.
+It defines these commands:
+
+@table @kbd
+@item @key{TAB}
+@code{tab-to-tab-stop}.
+@item @key{LFD}
+Insert a newline and then indent using @code{tab-to-tab-stop}.
+@item :
+Insert a colon and then remove the indentation from before the label
+preceding colon. Then do @code{tab-to-tab-stop}.
+@item ;
+Insert or align a comment.
+@end table
+
+@node Edebug Mode
+@subsection Edebug Mode
+@cindex Edebug mode @r{(V19)}
+
+Edebug is a new source-level debugger for Emacs Lisp programs.
+
+@findex edebug-defun @r{(V19)}
+To use Edebug, use the command @kbd{M-x edebug-defun} to ``evaluate'' a
+function definition in an Emacs Lisp file. We put ``evaluate'' in
+quotation marks because it doesn't just evaluate the function, it also
+inserts additional information to support source-level debugging.
+
+You must also do this:
+
+@example
+(setq debugger 'edebug-debug)
+@end example
+
+@noindent
+to cause errors and single-stepping to use Edebug instead of the usual
+Emacs Lisp debugger.
+
+@c ??? Need xref to Edebug manual
+For more information, see @cite{The Emacs Extensions Manual}, which
+should be included in the Emacs 19 distribution.
+
+@node Editing Binary Files
+@subsection Editing Binary Files
+
+@cindex Hexl mode @r{(V19)}
+@cindex editing binary files @r{(V19)}
+There is a new major mode for editing binary files: Hexl mode. To use
+it, use @kbd{M-x hexl-find-file} instead of @kbd{C-x C-f} to visit the
+file. This command converts the file's contents to hexadecimal and lets
+you edit the translation. When you save the file, it is converted
+automatically back to binary.
+
+You can also use @kbd{M-x hexl-mode} to translate an existing buffer
+into hex. This is useful if you visit a file normally and discover it
+is a binary file.
+
+Hexl mode has a few other commands:
+
+@c I don't think individual index entries for these commands are useful--RMS.
+@table @kbd
+@item C-M-d
+Insert a byte with a code typed in decimal.
+
+@item C-M-o
+Insert a byte with a code typed in octal.
+
+@item C-M-x
+Insert a byte with a code typed in hex.
+
+@item C-x [
+Move to the beginning of a 1k-byte ``page''.
+
+@item C-x ]
+Move to the end of a 1k-byte ``page''.
+
+@item M-g
+Move to an address specified in hex.
+
+@item M-j
+Move to an address specified in decimal.
+
+@item C-c C-c
+Leave Hexl mode, going back to the major mode this buffer had before you
+invoked @code{hexl-mode}.
+@end table
+
+@node Key Sequence Changes
+@section Changes in Key Sequences
+@cindex function keys (V19)
+@cindex mouse buttons (V19)
+@cindex key sequence changes (V19)
+
+In Emacs 18, a key sequence was a sequence of characters, which
+represented keyboard input.
+
+In Emacs 19, you can still use a sequence of characters as a key
+sequence, but you aren't limited to characters. You can also use Lisp
+symbols which represent terminal function keys or mouse buttons. If the
+function key has a word as its label, then that word is also the name of
+the symbol which represents the function key. Other function keys
+are assigned Lisp names as follows:
+
+@table @asis
+@item @code{kp-add}, @code{kp-decimal}, @code{kp-divide}, @dots{}
+Keypad keys (to the right of the regular keyboard), with names or punctuation
+@item @code{kp-0}, @code{kp-1}, @dots{}
+Keypad keys with digits
+@item @code{kp-f1}, @code{kp-f2}, @code{kp-f3}, @code{kp-f4}
+Keypad PF keys
+@item @code{left}, @code{up}, @code{right}, @code{down}
+Cursor arrow keys
+@end table
+
+A key sequence which contains non-characters must be a vector rather
+than a string.
+
+Thus, to bind function key @samp{f1} to @code{rmail}, write the
+following:
+
+@example
+(global-set-key [f1] 'rmail)
+@end example
+
+@noindent
+(To find the name of a key, type @kbd{C-h k} and then the key.)
+
+To bind the right-arrow key to the command @code{forward-char},
+you can use this expression:
+
+@example
+(global-set-key [right] 'forward-char)
+@end example
+
+@noindent
+using the Lisp syntax for a vector containing the symbol @code{right}.
+
+And this is how to make @kbd{C-x @key{RIGHTARROW}} move forward a page:
+
+@example
+(global-set-key [?\C-x right] 'forward-page)
+@end example
+
+@noindent
+where @code{?\C-x} is the Lisp syntax for an integer whose value is the
+code for the character @kbd{C-x}.
+
+You can use modifier keys such as @key{CTRL}, @key{META} and @key{SHIFT}
+with function keys. To represent these modifiers, prepend the strings
+@samp{C-}, @samp{M-} and @samp{S-} to the symbol name. Thus, here is
+how to make @kbd{M-@key{RIGHTARROW}} move forward a word:
+
+@example
+(global-set-key [M-right] 'forward-word)
+@end example
+
+Emacs uses symbols to designate mouse buttons, too.
+The ordinary mouse events in Emacs are @dfn{click} events; these
+happen when you press a button and release it without moving the mouse.
+You can also get @dfn{drag} events, when you move the mouse while
+holding the button down. Drag events happen when you finally let go
+of the button.
+
+The symbols for basic click events are @code{mouse-1} for the leftmost
+button, @code{mouse-2} for the next, and so on. Here is how you can
+redefine the second mouse button to split the current window:
+
+@findex global-set-key @r{(V19)}
+@example
+(global-set-key [mouse-2] 'split-window-vertically)
+@end example
+
+The symbols for drag events are similar, but have the prefix @samp{drag-}
+before the word @samp{mouse}. For example, dragging the left button
+generates a @code{drag-mouse-1} event.
+
+You can also request events when the mouse button is pressed down.
+These events start with @samp{down-} instead of @samp{drag-}. Such
+events are generated only if they have key bindings. When you get a
+button-down event, a corresponding click or drag event will always
+follow.
+
+The symbols for mouse events also indicate the status of the modifier
+keys, with the usual prefixes @samp{C-}, @samp{M-} and @samp{S-}.
+These always follow @samp{drag-} or @samp{down-}.
+@c ??? This is a change; currently they precede.
+
+When mouse events occur in special parts of a frame or window, such as a
+mode line or a scroll bar, the event symbol shows nothing special. The
+information about the special part is implicit in other data (the screen
+location of the event). But @code{read-key-sequence} figures out this
+aspect of the event, and encodes it with make-believe prefix keys, all
+of which are symbols: @code{mode-line}, @code{vertical-line},
+@code{horizontal-scrollbar} and @code{vertical-scrollbar}. Thus, to
+define the command for clicking the left button in a mode line, you
+could use this key sequence:
+
+@example
+[mode-line mouse-1]
+@end example
+
+You are not limited to defining individual function keys or mouse
+buttons; these can appear anywhere in a key sequence, just as characters
+can. You can even mix together all three kinds of inputs in one key
+sequence---but mixing mouse buttons with keyboard inputs is probably not
+convenient for actual use.
+
+@node Hook Changes
+@section Changes Regarding Hooks
+@cindex normal hook (V19)
+@cindex hook variable (V19)
+
+A @dfn{hook variable} is a variable that exists so that you can store in
+it functions for Emacs to call on certain occasions. (The functions that
+you put in hook variables are called @dfn{hook functions}.) Emacs 19
+has a new convention for naming hook variables that indicates more
+reliably how to use them.
+
+All the variables whose names end in @samp{-hook} are @dfn{normal
+hooks}; their values are lists of functions to be called with no
+arguments. You can use @code{add-hook} (see below) to install hook
+functions in these hooks. We have made all Emacs hooks into normal
+hooks except when there is some reason this won't work.
+
+A few hook-like variables are @dfn{abnormal}---they don't use the normal
+convention. This is either because the user-supplied functions receive
+arguments, or because their return values matter. These variables have
+names that end in @samp{-function} (if the value is a single function)
+or @samp{-functions} (if the value is a list of functions).
+
+Thus, you can always tell from the variable's name precisely how to
+install a new hook function in the variable. If the name indicates a
+normal hook, then you also know how to write your hook function.
+
+@findex add-hook @r{(V19)}
+To add a hook function to a normal hook, use @code{add-hook}. It takes
+care of adding a new hook function to any functions already installed in
+a given hook. It takes two arguments, the hook symbol and the function
+to add. For example,
+
+@example
+(add-hook 'text-mode-hook 'my-text-hook-function)
+@end example
+
+@noindent
+is how to arrange to call @code{my-text-hook-function} when entering
+Text mode or related modes.
+@vindex pre-abbrev-expand-hook @r{(V19)}
+@vindex kill-buffer-hook @r{(V19)}
+Two new hooks are worth noting here. Expansion of an abbrev
+first runs the hook @code{pre-abbrev-expand-hook}.
+@code{kill-buffer-hook} now runs whenever a buffer is killed.
+@c end antenews
+
+@node Manifesto,, Version 19, Top
+@unnumbered The GNU Manifesto
+
+@b{By Richard M. Stallman, 1986}
+
+@unnumberedsec What's GNU? Gnu's Not Unix!
+
+GNU, which stands for Gnu's Not Unix, is the name for the complete
+Unix-compatible software system which I am writing so that I can give it
+away free to everyone who can use it. Several other volunteers are helping
+me. Contributions of time, money, programs and equipment are greatly
+needed.
+
+So far we have an Emacs text editor with Lisp for writing editor commands,
+a source level debugger, a yacc-compatible parser generator, a linker, and
+around 35 utilities. A shell (command interpreter) is nearly completed. A
+new portable optimizing C compiler has compiled itself and may be released
+this year. An initial kernel exists but many more features are needed to
+emulate Unix. When the kernel and compiler are finished, it will be
+possible to distribute a GNU system suitable for program development. We
+will use @TeX{} as our text formatter, but an nroff is being worked on. We
+will use the free, portable X window system as well. After this we will
+add a portable Common Lisp, an Empire game, a spreadsheet, and hundreds of
+other things, plus on-line documentation. We hope to supply, eventually,
+everything useful that normally comes with a Unix system, and more.
+
+GNU will be able to run Unix programs, but will not be identical to Unix.
+We will make all improvements that are convenient, based on our experience
+with other operating systems. In particular, we plan to have longer
+filenames, file version numbers, a crashproof file system, filename
+completion perhaps, terminal-independent display support, and perhaps
+eventually a Lisp-based window system through which several Lisp programs
+and ordinary Unix programs can share a screen. Both C and Lisp will be
+available as system programming languages. We will try to support UUCP,
+MIT Chaosnet, and Internet protocols for communication.
+
+GNU is aimed initially at machines in the 68000/16000 class with virtual
+memory, because they are the easiest machines to make it run on. The extra
+effort to make it run on smaller machines will be left to someone who wants
+to use it on them.
+
+To avoid horrible confusion, please pronounce the `G' in the word `GNU'
+when it is the name of this project.
+
+@unnumberedsec Why I Must Write GNU
+
+I consider that the golden rule requires that if I like a program I must
+share it with other people who like it. Software sellers want to divide
+the users and conquer them, making each user agree not to share with
+others. I refuse to break solidarity with other users in this way. I
+cannot in good conscience sign a nondisclosure agreement or a software
+license agreement. For years I worked within the Artificial Intelligence
+Lab to resist such tendencies and other inhospitalities, but eventually
+they had gone too far: I could not remain in an institution where such
+things are done for me against my will.
+
+So that I can continue to use computers without dishonor, I have decided to
+put together a sufficient body of free software so that I will be able to
+get along without any software that is not free. I have resigned from the
+AI lab to deny MIT any legal excuse to prevent me from giving GNU away.
+
+@unnumberedsec Why GNU Will Be Compatible with Unix
+
+Unix is not my ideal system, but it is not too bad. The essential features
+of Unix seem to be good ones, and I think I can fill in what Unix lacks
+without spoiling them. And a system compatible with Unix would be
+convenient for many other people to adopt.
+
+@unnumberedsec How GNU Will Be Available
+
+GNU is not in the public domain. Everyone will be permitted to modify and
+redistribute GNU, but no distributor will be allowed to restrict its
+further redistribution. That is to say, proprietary modifications will not
+be allowed. I want to make sure that all versions of GNU remain free.
+
+@unnumberedsec Why Many Other Programmers Want to Help
+
+I have found many other programmers who are excited about GNU and want to
+help.
+
+Many programmers are unhappy about the commercialization of system
+software. It may enable them to make more money, but it requires them to
+feel in conflict with other programmers in general rather than feel as
+comrades. The fundamental act of friendship among programmers is the
+sharing of programs; marketing arrangements now typically used essentially
+forbid programmers to treat others as friends. The purchaser of software
+must choose between friendship and obeying the law. Naturally, many decide
+that friendship is more important. But those who believe in law often do
+not feel at ease with either choice. They become cynical and think that
+programming is just a way of making money.
+
+By working on and using GNU rather than proprietary programs, we can be
+hospitable to everyone and obey the law. In addition, GNU serves as an
+example to inspire and a banner to rally others to join us in sharing.
+This can give us a feeling of harmony which is impossible if we use
+software that is not free. For about half the programmers I talk to, this
+is an important happiness that money cannot replace.
+
+@unnumberedsec How You Can Contribute
+
+I am asking computer manufacturers for donations of machines and money.
+I'm asking individuals for donations of programs and work.
+
+One consequence you can expect if you donate machines is that GNU will run
+on them at an early date. The machines should be complete, ready to use
+systems, approved for use in a residential area, and not in need of
+sophisticated cooling or power.
+
+I have found very many programmers eager to contribute part-time work for
+GNU. For most projects, such part-time distributed work would be very hard
+to coordinate; the independently-written parts would not work together.
+But for the particular task of replacing Unix, this problem is absent. A
+complete Unix system contains hundreds of utility programs, each of which
+is documented separately. Most interface specifications are fixed by Unix
+compatibility. If each contributor can write a compatible replacement for
+a single Unix utility, and make it work properly in place of the original
+on a Unix system, then these utilities will work right when put together.
+Even allowing for Murphy to create a few unexpected problems, assembling
+these components will be a feasible task. (The kernel will require closer
+communication and will be worked on by a small, tight group.)
+
+If I get donations of money, I may be able to hire a few people full or
+part time. The salary won't be high by programmers' standards, but I'm
+looking for people for whom building community spirit is as important as
+making money. I view this as a way of enabling dedicated people to devote
+their full energies to working on GNU by sparing them the need to make a
+living in another way.
+
+@unnumberedsec Why All Computer Users Will Benefit
+
+Once GNU is written, everyone will be able to obtain good system software
+free, just like air.
+
+This means much more than just saving everyone the price of a Unix license.
+It means that much wasteful duplication of system programming effort will
+be avoided. This effort can go instead into advancing the state of the
+art.
+
+Complete system sources will be available to everyone. As a result, a user
+who needs changes in the system will always be free to make them himself,
+or hire any available programmer or company to make them for him. Users
+will no longer be at the mercy of one programmer or company which owns the
+sources and is in sole position to make changes.
+
+Schools will be able to provide a much more educational environment by
+encouraging all students to study and improve the system code. Harvard's
+computer lab used to have the policy that no program could be installed on
+the system if its sources were not on public display, and upheld it by
+actually refusing to install certain programs. I was very much inspired by
+this.
+
+Finally, the overhead of considering who owns the system software and what
+one is or is not entitled to do with it will be lifted.
+
+Arrangements to make people pay for using a program, including licensing of
+copies, always incur a tremendous cost to society through the cumbersome
+mechanisms necessary to figure out how much (that is, which programs) a
+person must pay for. And only a police state can force everyone to obey
+them. Consider a space station where air must be manufactured at great
+cost: charging each breather per liter of air may be fair, but wearing the
+metered gas mask all day and all night is intolerable even if everyone can
+afford to pay the air bill. And the TV cameras everywhere to see if you
+ever take the mask off are outrageous. It's better to support the air
+plant with a head tax and chuck the masks.
+
+Copying all or parts of a program is as natural to a programmer as
+breathing, and as productive. It ought to be as free.
+
+@unnumberedsec Some Easily Rebutted Objections to GNU's Goals
+
+@quotation
+``Nobody will use it if it is free, because that means they can't rely
+on any support.''
+
+``You have to charge for the program to pay for providing the
+support.''
+@end quotation
+
+If people would rather pay for GNU plus service than get GNU free without
+service, a company to provide just service to people who have obtained GNU
+free ought to be profitable.
+
+We must distinguish between support in the form of real programming work
+and mere handholding. The former is something one cannot rely on from a
+software vendor. If your problem is not shared by enough people, the
+vendor will tell you to get lost.
+
+If your business needs to be able to rely on support, the only way is to
+have all the necessary sources and tools. Then you can hire any available
+person to fix your problem; you are not at the mercy of any individual.
+With Unix, the price of sources puts this out of consideration for most
+businesses. With GNU this will be easy. It is still possible for there to
+be no available competent person, but this problem cannot be blamed on
+distribution arrangements. GNU does not eliminate all the world's problems,
+only some of them.
+
+Meanwhile, the users who know nothing about computers need handholding:
+doing things for them which they could easily do themselves but don't know
+how.
+
+Such services could be provided by companies that sell just hand-holding
+and repair service. If it is true that users would rather spend money and
+get a product with service, they will also be willing to buy the service
+having got the product free. The service companies will compete in quality
+and price; users will not be tied to any particular one. Meanwhile, those
+of us who don't need the service should be able to use the program without
+paying for the service.
+
+@quotation
+``You cannot reach many people without advertising,
+and you must charge for the program to support that.''
+
+``It's no use advertising a program people can get free.''
+@end quotation
+
+There are various forms of free or very cheap publicity that can be used to
+inform numbers of computer users about something like GNU. But it may be
+true that one can reach more microcomputer users with advertising. If this
+is really so, a business which advertises the service of copying and
+mailing GNU for a fee ought to be successful enough to pay for its
+advertising and more. This way, only the users who benefit from the
+advertising pay for it.
+
+On the other hand, if many people get GNU from their friends, and such
+companies don't succeed, this will show that advertising was not really
+necessary to spread GNU. Why is it that free market advocates don't want
+to let the free market decide this?
+
+@quotation
+``My company needs a proprietary operating system
+to get a competitive edge.''
+@end quotation
+
+GNU will remove operating system software from the realm of competition.
+You will not be able to get an edge in this area, but neither will your
+competitors be able to get an edge over you. You and they will compete in
+other areas, while benefitting mutually in this one. If your business is
+selling an operating system, you will not like GNU, but that's tough on
+you. If your business is something else, GNU can save you from being
+pushed into the expensive business of selling operating systems.
+
+I would like to see GNU development supported by gifts from many
+manufacturers and users, reducing the cost to each.
+
+@quotation
+``Don't programmers deserve a reward for their creativity?''
+@end quotation
+
+If anything deserves a reward, it is social contribution. Creativity can
+be a social contribution, but only in so far as society is free to use the
+results. If programmers deserve to be rewarded for creating innovative
+programs, by the same token they deserve to be punished if they restrict
+the use of these programs.
+
+@quotation
+``Shouldn't a programmer be able to ask for a reward for his creativity?''
+@end quotation
+
+There is nothing wrong with wanting pay for work, or seeking to maximize
+one's income, as long as one does not use means that are destructive. But
+the means customary in the field of software today are based on
+destruction.
+
+Extracting money from users of a program by restricting their use of it is
+destructive because the restrictions reduce the amount and the ways that
+the program can be used. This reduces the amount of wealth that humanity
+derives from the program. When there is a deliberate choice to restrict,
+the harmful consequences are deliberate destruction.
+
+The reason a good citizen does not use such destructive means to become
+wealthier is that, if everyone did so, we would all become poorer from the
+mutual destructiveness. This is Kantian ethics; or, the Golden Rule.
+Since I do not like the consequences that result if everyone hoards
+information, I am required to consider it wrong for one to do so.
+Specifically, the desire to be rewarded for one's creativity does not
+justify depriving the world in general of all or part of that creativity.
+
+@quotation
+``Won't programmers starve?''
+@end quotation
+
+I could answer that nobody is forced to be a programmer. Most of us cannot
+manage to get any money for standing on the street and making faces. But
+we are not, as a result, condemned to spend our lives standing on the
+street making faces, and starving. We do something else.
+
+But that is the wrong answer because it accepts the questioner's implicit
+assumption: that without ownership of software, programmers cannot possibly
+be paid a cent. Supposedly it is all or nothing.
+
+The real reason programmers will not starve is that it will still be
+possible for them to get paid for programming; just not paid as much as
+now.
+
+Restricting copying is not the only basis for business in software. It is
+the most common basis because it brings in the most money. If it were
+prohibited, or rejected by the customer, software business would move to
+other bases of organization which are now used less often. There are
+always numerous ways to organize any kind of business.
+
+Probably programming will not be as lucrative on the new basis as it is
+now. But that is not an argument against the change. It is not considered
+an injustice that sales clerks make the salaries that they now do. If
+programmers made the same, that would not be an injustice either. (In
+practice they would still make considerably more than that.)
+
+@quotation
+``Don't people have a right to control how their creativity is used?''
+@end quotation
+
+``Control over the use of one's ideas'' really constitutes control over
+other people's lives; and it is usually used to make their lives more
+difficult.
+
+People who have studied the issue of intellectual property rights carefully
+(such as lawyers) say that there is no intrinsic right to intellectual
+property. The kinds of supposed intellectual property rights that the
+government recognizes were created by specific acts of legislation for
+specific purposes.
+
+For example, the patent system was established to encourage inventors to
+disclose the details of their inventions. Its purpose was to help society
+rather than to help inventors. At the time, the life span of 17 years for
+a patent was short compared with the rate of advance of the state of the
+art. Since patents are an issue only among manufacturers, for whom the
+cost and effort of a license agreement are small compared with setting up
+production, the patents often do not do much harm. They do not obstruct
+most individuals who use patented products.
+
+The idea of copyright did not exist in ancient times, when authors
+frequently copied other authors at length in works of non-fiction. This
+practice was useful, and is the only way many authors' works have survived
+even in part. The copyright system was created expressly for the purpose
+of encouraging authorship. In the domain for which it was
+invented---books, which could be copied economically only on a printing
+press---it did little harm, and did not obstruct most of the individuals
+who read the books.
+
+All intellectual property rights are just licenses granted by society
+because it was thought, rightly or wrongly, that society as a whole would
+benefit by granting them. But in any particular situation, we have to ask:
+are we really better off granting such license? What kind of act are we
+licensing a person to do?
+
+The case of programs today is very different from that of books a hundred
+years ago. The fact that the easiest way to copy a program is from one
+neighbor to another, the fact that a program has both source code and
+object code which are distinct, and the fact that a program is used rather
+than read and enjoyed, combine to create a situation in which a person who
+enforces a copyright is harming society as a whole both materially and
+spiritually; in which a person should not do so regardless of whether the
+law enables him to.
+
+@quotation
+``Competition makes things get done better.''
+@end quotation
+
+The paradigm of competition is a race: by rewarding the winner, we
+encourage everyone to run faster. When capitalism really works this way,
+it does a good job; but its defenders are wrong in assuming it always works
+this way. If the runners forget why the reward is offered and become
+intent on winning, no matter how, they may find other strategies---such as,
+attacking other runners. If the runners get into a fist fight, they will
+all finish late.
+
+Proprietary and secret software is the moral equivalent of runners in a
+fist fight. Sad to say, the only referee we've got does not seem to
+object to fights; he just regulates them (``For every ten yards you run,
+you can fire one shot''). He really ought to break them up, and penalize
+runners for even trying to fight.
+
+@quotation
+``Won't everyone stop programming without a monetary incentive?''
+@end quotation
+
+Actually, many people will program with absolutely no monetary incentive.
+Programming has an irresistible fascination for some people, usually the
+people who are best at it. There is no shortage of professional musicians
+who keep at it even though they have no hope of making a living that way.
+
+But really this question, though commonly asked, is not appropriate to the
+situation. Pay for programmers will not disappear, only become less. So
+the right question is, will anyone program with a reduced monetary
+incentive? My experience shows that they will.
+
+For more than ten years, many of the world's best programmers worked at the
+Artificial Intelligence Lab for far less money than they could have had
+anywhere else. They got many kinds of non-monetary rewards: fame and
+appreciation, for example. And creativity is also fun, a reward in itself.
+
+Then most of them left when offered a chance to do the same interesting
+work for a lot of money.
+
+What the facts show is that people will program for reasons other than
+riches; but if given a chance to make a lot of money as well, they will
+come to expect and demand it. Low-paying organizations do poorly in
+competition with high-paying ones, but they do not have to do badly if the
+high-paying ones are banned.
+
+@quotation
+``We need the programmers desperately. If they demand that we
+stop helping our neighbors, we have to obey.''
+@end quotation
+
+You're never so desperate that you have to obey this sort of demand.
+Remember: millions for defense, but not a cent for tribute!
+
+@quotation
+``Programmers need to make a living somehow.''
+@end quotation
+
+In the short run, this is true. However, there are plenty of ways that
+programmers could make a living without selling the right to use a program.
+This way is customary now because it brings programmers and businessmen the
+most money, not because it is the only way to make a living. It is easy to
+find other ways if you want to find them. Here are a number of examples.
+
+A manufacturer introducing a new computer will pay for the porting of
+operating systems onto the new hardware.
+
+The sale of teaching, hand-holding and maintenance services could also
+employ programmers.
+
+People with new ideas could distribute programs as freeware, asking for
+donations from satisfied users, or selling hand-holding services. I have
+met people who are already working this way successfully.
+
+Users with related needs can form users' groups, and pay dues. A group
+would contract with programming companies to write programs that the
+group's members would like to use.
+
+All sorts of development can be funded with a Software Tax:
+
+@quotation
+Suppose everyone who buys a computer has to pay x percent of
+the price as a software tax. The government gives this to
+an agency like the NSF to spend on software development.
+
+But if the computer buyer makes a donation to software development
+himself, he can take a credit against the tax. He can donate to
+the project of his own choosing---often, chosen because he hopes to
+use the results when it is done. He can take a credit for any amount
+of donation up to the total tax he had to pay.
+
+The total tax rate could be decided by a vote of the payers of
+the tax, weighted according to the amount they will be taxed on.
+
+The consequences:
+
+@itemize @bullet
+@item
+The computer-using community supports software development.
+@item
+This community decides what level of support is needed.
+@item
+Users who care which projects their share is spent on
+can choose this for themselves.
+@end itemize
+@end quotation
+
+In the long run, making programs free is a step toward the post-scarcity
+world, where nobody will have to work very hard just to make a living.
+People will be free to devote themselves to activities that are fun, such
+as programming, after spending the necessary ten hours a week on required
+tasks such as legislation, family counseling, robot repair and asteroid
+prospecting. There will be no need to be able to make a living from
+programming.
+
+We have already greatly reduced the amount of work that the whole society
+must do for its actual productivity, but only a little of this has
+translated itself into leisure for workers because much nonproductive
+activity is required to accompany productive activity. The main causes of
+this are bureaucracy and isometric struggles against competition. Free
+software will greatly reduce these drains in the area of software
+production. We must do this, in order for technical gains in productivity
+to translate into less work for us.
+
+@node Glossary, Key Index, Intro, Top
+@unnumbered Glossary
+
+@table @asis
+@need 150
+@item Abbrev
+An abbrev is a text string which expands into a different text string
+when present in the buffer. For example, you might define a short
+word as an abbrev for a long phrase that you want to insert
+frequently. @xref{Abbrevs}.
+
+@need 150
+@item Aborting
+Aborting means getting out of a recursive edit (q.v.@:). The
+commands @kbd{C-]} and @kbd{M-x top-level} are used for this.
+@xref{Quitting}.
+
+@need 150
+@item Auto Fill mode
+Auto Fill mode is a minor mode in which text that you insert is
+automatically broken into lines of fixed width. @xref{Filling}.
+
+@need 150
+@item Auto Saving
+Auto saving is when Emacs automatically stores the contents of an
+Emacs buffer in a specially-named file so that the information will
+not be lost if the buffer is lost due to a system error or user error.
+@xref{Auto Save}.
+
+@need 150
+@item Backup File
+A backup file records the contents that a file had before the current
+editing session. Emacs makes backup files automatically to help you
+track down or cancel changes you later regret making. @xref{Backup}.
+
+@need 150
+@item Balance Parentheses
+Emacs can balance parentheses manually or automatically. Manual
+balancing is done by the commands to move over balanced expressions
+(@pxref{Lists}). Automatic balancing is done by blinking the
+parenthesis that matches one just inserted (@pxref{Matching,,Matching
+Parens}).
+
+@need 150
+@item Bind
+To bind a key is to change its binding (q.v.@:). @xref{Rebinding}.
+
+@need 150
+@item Binding
+A key gets its meaning in Emacs by having a binding which is a
+command (q.v.@:), a Lisp function that is run when the key is typed.
+@xref{Commands,Binding}. Customization often involves rebinding a
+character to a different command function. The bindings of all keys
+are recorded in the keymaps (q.v.@:). @xref{Keymaps}.
+
+@need 150
+@item Blank Lines
+Blank lines are lines that contain only whitespace. Emacs has several
+commands for operating on the blank lines in the buffer.
+
+@need 150
+@item Buffer
+The buffer is the basic editing unit; one buffer corresponds to one
+piece of text being edited. You can have several buffers, but at any
+time you are editing only one, the `selected' buffer, though several
+can be visible when you are using multiple windows. @xref{Buffers}.
+
+@need 150
+@item Buffer Selection History
+Emacs keeps a buffer selection history which records how recently each
+Emacs buffer has been selected. This is used for choosing a buffer to
+select. @xref{Buffers}.
+
+@need 150
+@item C-
+@samp{C} in the name of a character is an abbreviation for Control.
+@xref{Characters,C-}.
+
+@need 150
+@item C-M-
+@samp{C-M-} in the name of a character is an abbreviation for
+Control-Meta. @xref{Characters,C-M-}.
+
+@need 150
+@item Case Conversion
+Case conversion means changing text from upper case to lower case or
+vice versa. @xref{Case}, for the commands for case conversion.
+
+@need 150
+@item Characters
+Characters form the contents of an Emacs buffer; also, Emacs commands
+are invoked by keys (q.v.@:), which are sequences of one or more
+characters. @xref{Characters}.
+
+@need 150
+@item Command
+A command is a Lisp function specially defined to be able to serve as
+a key binding in Emacs. When you type a key (q.v.@:), its binding
+(q.v.@:) is looked up in the relevant keymaps (q.v.@:) to find the
+command to run. @xref{Commands}.
+
+@need 150
+@item Command Name
+A command name is the name of a Lisp symbol which is a command
+(@pxref{Commands}). You can invoke any command by its name using
+@kbd{M-x} (@pxref{M-x}).
+
+@need 150
+@item Comments
+A comment is text in a program which is intended only for humans
+reading the program, and is marked specially so that it will be
+ignored when the program is loaded or compiled. Emacs offers special
+commands for creating, aligning and killing comments.
+@xref{Comments}.
+
+@need 150
+@item Compilation
+Compilation is the process of creating an executable program from
+source code. Emacs has commands for compiling files of Emacs Lisp
+code (@pxref{Lisp Libraries}) and programs in C and other languages
+(@pxref{Compilation}).
+
+@need 150
+@item Complete Key
+A complete key is a character or sequence of characters which, when typed
+by the user, fully specifies one action to be performed by Emacs. For
+example, @kbd{X} and @kbd{Control-f} and @kbd{Control-x m} are keys. Keys
+derive their meanings from being bound (q.v.@:) to commands (q.v.@:).
+Thus, @kbd{X} is conventionally bound to a command to insert @samp{X} in
+the buffer; @kbd{C-x m} is conventionally bound to a command to begin
+composing a mail message. @xref{Keys}.
+
+@need 150
+@item Completion
+Completion is what Emacs does when it automatically fills out an
+abbreviation for a name into the entire name. Completion is done for
+minibuffer (q.v.@:) arguments when the set of possible valid inputs
+is known; for example, on command names, buffer names, and
+file names. Completion occurs when @key{TAB}, @key{SPC} or @key{RET}
+is typed. @xref{Completion}.@refill
+
+@need 150
+@item Continuation Line
+When a line of text is longer than the width of the screen, it
+takes up more than one screen line when displayed. We say that the
+text line is continued, and all screen lines used for it after the
+first are called continuation lines. @xref{Basic,Continuation,Basic
+Editing}.
+
+@need 150
+@item Control-Character
+@sc{ascii} characters with octal codes 0 through 037, and also code 0177,
+do not have graphic images assigned to them. These are the control
+characters. Any control character can be typed by holding down the
+@key{CTRL} key and typing some other character; some have special keys
+on the keyboard. @key{RET}, @key{TAB}, @key{ESC}, @key{LFD} and
+@key{DEL} are all control characters. @xref{Characters}.@refill
+
+@need 150
+@item Copyleft
+A copyleft is a notice giving the public legal permission to redistribute
+a program or other work of art. Copylefts are used by leftists to enrich
+the public just as copyrights are used by rightists to gain power over
+the public.
+
+@need 150
+@item Current Buffer
+The current buffer in Emacs is the Emacs buffer on which most editing
+commands operate. You can select any Emacs buffer as the current one.
+@xref{Buffers}.
+
+@need 150
+@item Current Line
+The line point is on (@pxref{Point}).
+
+@need 150
+@item Current Paragraph
+The paragraph that point is in. If point is between paragraphs, the
+current paragraph is the one that follows point. @xref{Paragraphs}.
+
+@need 150
+@item Current Defun
+The defun (q.v.@:) that point is in. If point is between defuns, the
+current defun is the one that follows point. @xref{Defuns}.
+
+@need 150
+@item Cursor
+The cursor is the rectangle on the screen which indicates the position
+called point (q.v.@:) at which insertion and deletion takes place.
+The cursor is on or under the character that follows point. Often
+people speak of `the cursor' when, strictly speaking, they mean
+`point'. @xref{Basic,Cursor,Basic Editing}.
+
+@need 150
+@item Customization
+Customization is making minor changes in the way Emacs works. It is
+often done by setting variables (@pxref{Variables}) or by rebinding
+keys (@pxref{Keymaps}).
+
+@need 150
+@item Default Argument
+The default for an argument is the value that will be assumed if you
+do not specify one. When the minibuffer is used to read an argument,
+the default argument is used if you just type @key{RET}.
+@xref{Minibuffer}.
+
+@need 150
+@item Default Directory
+When you specify a file name that does not start with @samp{/} or @samp{~},
+it is interpreted relative to the current buffer's default directory.
+@xref{Minibuffer File,Default Directory}.
+
+@need 150
+@item Defun
+A defun is a list at the top level of parenthesis or bracket structure
+in a program. It is so named because most such lists in Lisp programs
+are calls to the Lisp function @code{defun}. @xref{Defuns}.
+
+@need 150
+@item @key{DEL}
+@key{DEL} is a character that runs the command to delete one character of
+text. @xref{Basic,DEL,Basic Editing}.
+
+@need 150
+@item Deletion
+Deletion means erasing text without saving it. Emacs deletes text
+only when it is expected not to be worth saving (all whitespace, or
+only one character). The alternative is killing (q.v.@:).
+@xref{Killing,Deletion}.
+
+@need 150
+@item Deletion of Files
+Deleting a file means erasing it from the file system.
+@xref{Misc File Ops}.
+
+@need 150
+@item Deletion of Messages
+Deleting a message means flagging it to be eliminated from your mail
+file. This can be undone by undeletion until the mail file is expunged.
+@xref{Rmail Deletion}.
+
+@need 150
+@item Deletion of Windows
+Deleting a window means eliminating it from the screen. Other windows
+expand to use up the space. The deleted window can never come back,
+but no actual text is thereby lost. @xref{Windows}.
+
+@need 150
+@item Directory
+Files in the Unix file system are grouped into file directories.
+@xref{ListDir,,Directories}.
+
+@need 150
+@item Dired
+Dired is the Emacs facility that displays the contents of a file
+directory and allows you to ``edit the directory'', performing
+operations on the files in the directory. @xref{Dired}.
+
+@need 150
+@item Disabled Command
+A disabled command is one that you may not run without special
+confirmation. The usual reason for disabling a command is that it is
+confusing for beginning users. @xref{Disabling}.
+
+@need 150
+@item Dribble File
+A file into which Emacs writes all the characters that the user types
+on the keyboard. Dribble files are used to make a record for
+debugging Emacs bugs. Emacs does not make a dribble file unless you
+tell it to. @xref{Bugs}.
+
+@need 150
+@item Echo Area
+The echo area is the bottom line of the screen, used for echoing the
+arguments to commands, for asking questions, and printing brief
+messages (including error messages). @xref{Echo Area}.
+
+@need 150
+@item Echoing
+Echoing is acknowledging the receipt of commands by displaying them
+(in the echo area). Emacs never echoes single-character keys; longer
+keys echo only if you pause while typing them.
+
+@need 150
+@item Error
+An error occurs when an Emacs command cannot execute in the current
+circumstances. When an error occurs, execution of the command stops
+(unless the command has been programmed to do otherwise) and Emacs
+reports the error by printing an error message (q.v.). Type-ahead
+is discarded. Then Emacs is ready to read another editing command.
+
+@need 150
+@item Error Messages
+Error messages are single lines of output printed by Emacs when the
+user asks for something impossible to do (such as, killing text
+forward when point is at the end of the buffer). They appear in the
+echo area, accompanied by a beep.
+
+@need 150
+@item @key{ESC}
+@key{ESC} is a character, used to end incremental searches and as a
+prefix for typing Meta characters on keyboards lacking a @key{META}
+key. Unlike the @key{META} key (which, like the @key{SHIFT} key, is held
+down while another character is typed), the @key{ESC} key is pressed
+once and applies to the next character typed.
+
+@need 150
+@item Fill Prefix
+The fill prefix is a string that should be expected at the beginning
+of each line when filling is done. It is not regarded as part of the
+text to be filled. @xref{Filling}.
+
+@need 150
+@item Filling
+Filling text means moving text from line to line so that all the lines
+are approximately the same length. @xref{Filling}.
+
+@need 150
+@item Global
+Global means `independent of the current environment; in effect
+throughout Emacs'. It is the opposite of local (q.v.@:). Particular
+examples of the use of `global' appear below.
+
+@need 150
+@item Global Abbrev
+A global definition of an abbrev (q.v.@:) is effective in all major
+modes that do not have local (q.v.@:) definitions for the same abbrev.
+@xref{Abbrevs}.
+
+@need 150
+@item Global Keymap
+The global keymap (q.v.@:) contains key bindings that are in effect
+except when overridden by local key bindings in a major mode's local
+keymap (q.v.@:). @xref{Keymaps}.
+
+@need 150
+@item Global Substitution
+Global substitution means replacing each occurrence of one string by
+another string through a large amount of text. @xref{Replace}.
+
+@need 150
+@item Global Variable
+The global value of a variable (q.v.@:) takes effect in all buffers
+that do not have their own local (q.v.@:) values for the variable.
+@xref{Variables}.
+
+@need 150
+@item Graphic Character
+Graphic characters are those assigned pictorial images rather than
+just names. All the non-Meta (q.v.@:) characters except for the
+Control (q.v.@:) characters are graphic characters. These include
+letters, digits, punctuation, and spaces; they do not include
+@key{RET} or @key{ESC}. In Emacs, typing a graphic character inserts
+that character (in ordinary editing modes). @xref{Basic,,Basic Editing}.
+
+@need 150
+@item Grinding
+Grinding means adjusting the indentation in a program to fit the
+nesting structure. @xref{Indentation,Grinding}.
+
+@need 150
+@item Hardcopy
+Hardcopy means printed output. Emacs has commands for making printed
+listings of text in Emacs buffers. @xref{Hardcopy}.
+
+@need 150
+@item @key{HELP}
+You can type @key{HELP} at any time to ask what options you have, or
+to ask what any command does. @key{HELP} is really @kbd{Control-h}.
+@xref{Help}.
+
+@need 150
+@item Inbox
+An inbox is a file in which mail is delivered by the operating system.
+Rmail transfers mail from inboxes to mail files (q.v.) in which the
+mail is then stored permanently or until explicitly deleted.
+@xref{Rmail Inbox}.
+
+@need 150
+@item Indentation
+Indentation means blank space at the beginning of a line. Most
+programming languages have conventions for using indentation to
+illuminate the structure of the program, and Emacs has special
+features to help you set up the correct indentation.
+@xref{Indentation}.
+
+@need 150
+@item Insertion
+Insertion means copying text into the buffer, either from the keyboard
+or from some other place in Emacs.
+
+@need 150
+@item Justification
+Justification means adding extra spaces to lines of text to make them
+come exactly to a specified width. @xref{Filling,Justification}.
+
+@need 150
+@item Keyboard Macros
+Keyboard macros are a way of defining new Emacs commands from
+sequences of existing ones, with no need to write a Lisp program.
+@xref{Keyboard Macros}.
+
+@need 150
+@item Key
+A key is a sequence of characters that, when input to Emacs, specify
+or begin to specify a single action for Emacs to perform. That is,
+the sequence is not more than a single unit. If the key is enough to
+specify one action, it is a complete key (q.v.); if it is less than
+enough, it is a prefix key (q.v.). @xref{Keys}.
+
+@need 150
+@item Keymap
+The keymap is the data structure that records the bindings (q.v.@:) of
+keys to the commands that they run. For example, the keymap binds the
+character @kbd{C-n} to the command function @code{next-line}.
+@xref{Keymaps}.
+
+@need 150
+@item Kill Ring
+The kill ring is where all text you have killed recently is saved.
+You can reinsert any of the killed text still in the ring; this is
+called yanking (q.v.@:). @xref{Yanking}.
+
+@need 150
+@item Killing
+Killing means erasing text and saving it on the kill ring so it can be
+yanked (q.v.@:) later. Some other systems call this ``cutting''.
+Most Emacs commands to erase text do killing, as opposed to deletion
+(q.v.@:). @xref{Killing}.
+
+@need 150
+@item Killing Jobs
+Killing a job (such as, an invocation of Emacs) means making it cease
+to exist. Any data within it, if not saved in a file, is lost.
+@xref{Exiting}.
+
+@need 150
+@item List
+A list is, approximately, a text string beginning with an open
+parenthesis and ending with the matching close parenthesis. In C mode
+and other non-Lisp modes, groupings surrounded by other kinds of matched
+delimiters appropriate to the language, such as braces, are also
+considered lists. Emacs has special commands for many operations on
+lists. @xref{Lists}.
+
+@need 150
+@item Local
+Local means `in effect only in a particular context'; the relevant
+kind of context is a particular function execution, a particular
+buffer, or a particular major mode. It is the opposite of `global'
+(q.v.@:). Specific uses of `local' in Emacs terminology appear below.
+
+@need 150
+@item Local Abbrev
+A local abbrev definition is effective only if a particular major mode
+is selected. In that major mode, it overrides any global definition
+for the same abbrev. @xref{Abbrevs}.
+
+@need 150
+@item Local Keymap
+A local keymap is used in a particular major mode; the key bindings
+(q.v.@:) in the current local keymap override global bindings of the
+same keys. @xref{Keymaps}.
+
+@need 150
+@item Local Variable
+A local value of a variable (q.v.@:) applies to only one buffer.
+@xref{Locals}.
+
+@need 150
+@item M-
+@kbd{M-} in the name of a character is an abbreviation for @key{META},
+one of the modifier keys that can accompany any character.
+@xref{Characters}.
+
+@need 150
+@item M-C-
+@samp{M-C-} in the name of a character is an abbreviation for
+Control-Meta; it means the same thing as @samp{C-M-}. If your
+terminal lacks a real @key{META} key, you type a Control-Meta character by
+typing @key{ESC} and then typing the corresponding Control character.
+@xref{Characters,C-M-}.
+
+@need 150
+@item M-x
+@kbd{M-x} is the key which is used to call an Emacs command by name.
+This is how commands that are not bound to keys are called.
+@xref{M-x}.
+
+@need 150
+@item Mail
+Mail means messages sent from one user to another through the computer
+system, to be read at the recipient's convenience. Emacs has commands for
+composing and sending mail, and for reading and editing the mail you have
+received. @xref{Sending Mail}. @xref{Rmail}, for how to read mail.
+
+@need 150
+@item Mail File
+A mail file is a file which is edited using Rmail and in which Rmail
+stores mail. @xref{Rmail}.
+
+@need 150
+@item Major Mode
+The major modes are a mutually exclusive set of options each of which
+configures Emacs for editing a certain sort of text. Ideally, each
+programming language has its own major mode. @xref{Major Modes}.
+
+@need 150
+@item Mark
+The mark points to a position in the text. It specifies one end of
+the region (q.v.@:), point being the other end. Many commands operate
+on all the text from point to the mark. @xref{Mark}.
+
+@need 150
+@item Mark Ring
+The mark ring is used to hold several recent previous locations of the
+mark, just in case you want to move back to them. @xref{Mark Ring}.
+
+@need 150
+@item Message
+See `mail'.
+
+@need 150
+@item Meta
+Meta is the name of a modifier bit which a command character may have.
+It is present in a character if the character is typed with the
+@key{META} key held down. Such characters are given names that start
+with @kbd{Meta-}. For example, @kbd{Meta-<} is typed by holding down
+@key{META} and at the same time typing @kbd{<} (which itself is done,
+on most terminals, by holding down @key{SHIFT} and typing @kbd{,}).
+@xref{Characters,Meta}.
+
+@need 150
+@item Meta Character
+A Meta character is one whose character code includes the Meta bit.
+
+@need 150
+@item Minibuffer
+The minibuffer is the window that appears when necessary inside the
+echo area (q.v.@:), used for reading arguments to commands.
+@xref{Minibuffer}.
+
+@need 150
+@item Minor Mode
+A minor mode is an optional feature of Emacs which can be switched on
+or off independently of all other features. Each minor mode has a
+command to turn it on or off. @xref{Minor Modes}.
+
+@need 150
+@item Mode Line
+The mode line is the line at the bottom of each text window (q.v.@:),
+which gives status information on the buffer displayed in that window.
+@xref{Mode Line}.
+
+@need 150
+@item Modified Buffer
+A buffer (q.v.@:) is modified if its text has been changed since the
+last time the buffer was saved (or since when it was created, if it
+has never been saved). @xref{Saving}.
+
+@need 150
+@item Moving Text
+Moving text means erasing it from one place and inserting it in
+another. This is done by killing (q.v.@:) and then yanking (q.v.@:).
+@xref{Killing}.
+
+@need 150
+@item Named Mark
+A named mark is a register (q.v.@:) in its role of recording a
+location in text so that you can move point to that location.
+@xref{Registers}.
+
+@need 150
+@item Narrowing
+Narrowing means creating a restriction (q.v.@:) that limits editing in
+the current buffer to only a part of the text in the buffer. Text
+outside that part is inaccessible to the user until the boundaries are
+widened again, but it is still there, and saving the file saves it
+all. @xref{Narrowing}.
+
+@need 150
+@item Newline
+@key{LFD} characters in the buffer terminate lines of text and are
+called newlines. @xref{Characters,Newline}.
+
+@need 150
+@item Numeric Argument
+A numeric argument is a number, specified before a command, to change
+the effect of the command. Often the numeric argument serves as a
+repeat count. @xref{Arguments}.
+
+@need 150
+@item Option
+An option is a variable (q.v.@:) that exists so that you can customize
+Emacs by giving it a new value. @xref{Variables}.
+
+@need 150
+@item Overwrite Mode
+Overwrite mode is a minor mode. When it is enabled, ordinary text
+characters replace the existing text after point rather than pushing
+it to the right. @xref{Minor Modes}.
+
+@need 150
+@item Page
+A page is a unit of text, delimited by formfeed characters (@sc{ascii}
+Control-L, code 014) coming at the beginning of a line. Some Emacs
+commands are provided for moving over and operating on pages.
+@xref{Pages}.
+
+@need 150
+@item Paragraphs
+Paragraphs are the medium-size unit of English text. There are
+special Emacs commands for moving over and operating on paragraphs.
+@xref{Paragraphs}.
+
+@need 150
+@item Parsing
+We say that Emacs parses words or expressions in the text being
+edited. Really, all it knows how to do is find the other end of a
+word or expression. @xref{Syntax}.
+
+@need 150
+@item Point
+Point is the place in the buffer at which insertion and deletion
+occur. Point is considered to be between two characters, not at one
+character. The terminal's cursor (q.v.@:) indicates the location of
+point. @xref{Basic,Point}.
+
+@need 150
+@item Prefix Key
+A prefix key is a key (q.v.@:) whose sole function is to introduce a
+set of multi-character keys. @kbd{Control-x} is an example of prefix
+key; thus, any two-character sequence starting with @kbd{C-x} is also
+a legitimate key. @xref{Keys}.
+
+@need 150
+@item Primary Mail File
+Your primary mail file is the file named @samp{RMAIL} in your home
+directory, where all mail that you receive is stored by Rmail unless you
+make arrangements to do otherwise. @xref{Rmail}.
+
+@need 150
+@item Prompt
+A prompt is text printed to ask the user for input. Printing a prompt
+is called prompting. Emacs prompts always appear in the echo area
+(q.v.@:). One kind of prompting happens when the minibuffer is used
+to read an argument (@pxref{Minibuffer}); the echoing which happens
+when you pause in the middle of typing a multicharacter key is also a
+kind of prompting (@pxref{Echo Area}).
+
+@need 150
+@item Quitting
+Quitting means cancelling a partially typed command or a running
+command, using @kbd{C-g}. @xref{Quitting}.
+
+@need 150
+@item Quoting
+Quoting means depriving a character of its usual special significance.
+In Emacs this is usually done with @kbd{Control-q}. What constitutes special
+significance depends on the context and on convention. For example,
+an ``ordinary'' character as an Emacs command inserts itself; so in
+this context, a special character is any character that does not
+normally insert itself (such as @key{DEL}, for example), and quoting
+it makes it insert itself as if it were not special. Not all contexts
+allow quoting. @xref{Basic,Quoting,Basic Editing}.
+
+@need 150
+@item Read-only Buffer
+A read-only buffer is one whose text you are not allowed to change.
+Normally Emacs makes buffers read-only when they contain text which
+has a special significance to Emacs; for example, Dired buffers.
+Visiting a file that is write protected also makes a read-only buffer.
+@xref{Buffers}.
+
+@need 150
+@item Recursive Editing Level
+A recursive editing level is a state in which part of the execution of
+a command involves asking the user to edit some text. This text may
+or may not be the same as the text to which the command was applied.
+The mode line indicates recursive editing levels with square brackets
+(@samp{[} and @samp{]}). @xref{Recursive Edit}.
+
+@need 150
+@item Redisplay
+Redisplay is the process of correcting the image on the screen to
+correspond to changes that have been made in the text being edited.
+@xref{Screen,Redisplay}.
+
+@need 150
+@item Regexp
+See `regular expression'.
+
+@need 150
+@item Region
+The region is the text between point (q.v.@:) and the mark (q.v.@:).
+Many commands operate on the text of the region. @xref{Mark,Region}.
+
+@need 150
+@item Registers
+Registers are named slots in which text or buffer positions or
+rectangles can be saved for later use. @xref{Registers}.
+
+@need 150
+@item Regular Expression
+A regular expression is a pattern that can match various text strings;
+for example, @samp{l[0-9]+} matches @samp{l} followed by one or more
+digits. @xref{Regexps}.
+
+@need 150
+@item Replacement
+See `global substitution'.
+
+@need 150
+@item Restriction
+A buffer's restriction is the amount of text, at the beginning or the
+end of the buffer, that is temporarily invisible and inaccessible.
+Giving a buffer a nonzero amount of restriction is called narrowing
+(q.v.). @xref{Narrowing}.
+
+@need 150
+@item @key{RET}
+@key{RET} is a character that in Emacs runs the command to insert a
+newline into the text. It is also used to terminate most arguments
+read in the minibuffer (q.v.@:). @xref{Characters,Return}.
+
+@need 150
+@item Saving
+Saving a buffer means copying its text into the file that was visited
+(q.v.@:) in that buffer. This is the way text in files actually gets
+changed by your Emacs editing. @xref{Saving}.
+
+@need 150
+@item Scrolling
+Scrolling means shifting the text in the Emacs window so as to see a
+different part of the buffer. @xref{Display,Scrolling}.
+
+@need 150
+@item Searching
+Searching means moving point to the next occurrence of a specified
+string. @xref{Search}.
+
+@need 150
+@item Selecting
+Selecting a buffer means making it the current (q.v.@:) buffer.
+@xref{Buffers,Selecting}.
+
+@need 150
+@item Self-documentation
+Self-documentation is the feature of Emacs which can tell you what any
+command does, or give you a list of all commands related to a topic
+you specify. You ask for self-documentation with the help character,
+@kbd{C-h}. @xref{Help}.
+
+@need 150
+@item Sentences
+Emacs has commands for moving by or killing by sentences.
+@xref{Sentences}.
+
+@need 150
+@item Sexp
+A sexp (short for `s-expression') is the basic syntactic unit of Lisp
+in its textual form: either a list, or Lisp atom. Many Emacs commands
+operate on sexps. The term `sexp' is generalized to languages other
+than Lisp, to mean a syntactically recognizable expression.
+@xref{Lists,Sexps}.
+
+@need 150
+@item Simultaneous Editing
+Simultaneous editing means two users modifying the same file at once.
+Simultaneous editing if not detected can cause one user to lose his
+work. Emacs detects all cases of simultaneous editing and warns the
+user to investigate them. @xref{Interlocking,,Simultaneous Editing}.
+
+@need 150
+@item String
+A string is a kind of Lisp data object which contains a sequence of
+characters. Many Emacs variables are intended to have strings as
+values. The Lisp syntax for a string consists of the characters in
+the string with a @samp{"} before and another @samp{"} after. A
+@samp{"} that is part of the string must be written as @samp{\"} and a
+@samp{\} that is part of the string must be written as @samp{\\}. All
+other characters, including newline, can be included just by writing
+them inside the string; however, escape sequences as in C, such as
+@samp{\n} for newline or @samp{\241} using an octal character code,
+are allowed as well.
+
+@need 150
+@item String Substitution
+See `global substitution'.
+
+@need 150
+@item Syntax Table
+The syntax table tells Emacs which characters are part of a word,
+which characters balance each other like parentheses, etc.
+@xref{Syntax}.
+
+@need 150
+@item Tag Table
+A tag table is a file that serves as an index to the function
+definitions in one or more other files. @xref{Tags}.
+
+@need 150
+@item Termscript File
+A termscript file contains a record of all characters sent by Emacs to
+the terminal. It is used for tracking down bugs in Emacs redisplay.
+Emacs does not make a termscript file unless you tell it to.
+@xref{Bugs}.
+
+@need 150
+@item Text
+Two meanings (@pxref{Text}):
+
+@need 150
+@itemize @bullet
+@need 150
+@item
+Data consisting of a sequence of characters, as opposed to binary
+numbers, images, graphics commands, executable programs, and the like.
+The contents of an Emacs buffer are always text in this sense.
+@need 150
+@item
+Data consisting of written human language, as opposed to programs,
+or following the stylistic conventions of human language.
+@end itemize
+
+@need 150
+@item Top Level
+Top level is the normal state of Emacs, in which you are editing the
+text of the file you have visited. You are at top level whenever you
+are not in a recursive editing level (q.v.@:) or the minibuffer
+(q.v.@:), and not in the middle of a command. You can get back to top
+level by aborting (q.v.@:) and quitting (q.v.@:). @xref{Quitting}.
+
+@need 150
+@item Transposition
+Transposing two units of text means putting each one into the place
+formerly occupied by the other. There are Emacs commands to transpose
+two adjacent characters, words, sexps (q.v.@:) or lines
+(@pxref{Transpose}).
+
+@need 150
+@item Truncation
+Truncating text lines in the display means leaving out any text on a
+line that does not fit within the right margin of the window
+displaying it. See also `continuation line'.
+@xref{Basic,Truncation,Basic Editing}.
+
+@need 150
+@item Undoing
+Undoing means making your previous editing go in reverse, bringing
+back the text that existed earlier in the editing session.
+@xref{Undo}.
+
+@need 150
+@item Variable
+A variable is an object in Lisp that can store an arbitrary value.
+Emacs uses some variables for internal purposes, and has others (known
+as `options' (q.v.@:)) just so that you can set their values to
+control the behavior of Emacs. The variables used in Emacs that you
+are likely to be interested in are listed in the Variables Index in
+this manual. @xref{Variables}, for information on variables.
+
+@need 150
+@item Visiting
+Visiting a file means loading its contents into a buffer (q.v.@:)
+where they can be edited. @xref{Visiting}.
+
+@need 150
+@item Whitespace
+Whitespace is any run of consecutive formatting characters (space,
+tab, newline, and backspace).
+
+@need 150
+@item Widening
+Widening is removing any restriction (q.v.@:) on the current buffer;
+it is the opposite of narrowing (q.v.@:). @xref{Narrowing}.
+
+@need 150
+@item Window
+Emacs divides the screen into one or more windows, each of which can
+display the contents of one buffer (q.v.@:) at any time.
+@xref{Screen}, for basic information on how Emacs uses the screen.
+@xref{Windows}, for commands to control the use of windows.
+
+@need 150
+@item Word Abbrev
+Synonymous with `abbrev'.
+
+@need 150
+@item Word Search
+Word search is searching for a sequence of words, considering the
+punctuation between them as insignificant. @xref{Word Search}.
+
+@need 150
+@item Yanking
+Yanking means reinserting text previously killed. It can be used to
+undo a mistaken kill, or for copying or moving text. Some other
+systems call this ``pasting''. @xref{Yanking}.
+@end table
+
+@node Key Index, Command Index, Glossary, Top
+@unnumbered Key (Character) Index
+@printindex ky
+
+@node Command Index, Variable Index, Key Index, Top
+@unnumbered Command and Function Index
+@printindex fn
+
+@node Variable Index, Concept Index, Command Index, Top
+@unnumbered Variable Index
+@printindex vr
+
+@node Concept Index, Screen, Variable Index, Top
+@unnumbered Concept Index
+@printindex cp
+
+@tex
+\global\baselineskip 11.5pt
+@end tex
+
+@summarycontents
+@contents
+@bye
diff --git a/man/emacs.vrs b/man/emacs.vrs
new file mode 100644
index 00000000000..86f39341edd
--- /dev/null
+++ b/man/emacs.vrs
@@ -0,0 +1,217 @@
+\initial {A}
+\entry {\code {abbrev-all-caps}}{172}
+\entry {\code {abbrev-file-name}}{174}
+\entry {\code {abbrev-mode}}{171}
+\entry {\code {auto-mode-alist}}{112}
+\entry {\code {auto-save-default}}{95}
+\entry {\code {auto-save-interval}}{95}
+\entry {\code {auto-save-timeout \r {(V19)}}}{240}
+\entry {\code {auto-save-visited-file-name}}{94}
+\initial {B}
+\entry {\code {backup-by-copying}}{91}
+\entry {\code {backup-by-copying-when-linked}}{91}
+\entry {\code {backup-by-copying-when-mismatch}}{91}
+\entry {\code {blink-matching-paren}}{145}
+\entry {\code {blink-matching-paren-distance}}{145}
+\entry {\code {buffer-read-only}}{102}
+\initial {C}
+\entry {\code {c-argdecl-indent}}{144}
+\entry {\code {c-auto-newline}}{142}
+\entry {\code {c-brace-imaginary-offset}}{143}
+\entry {\code {c-brace-offset}}{144}
+\entry {\code {c-continued-statement-offset}}{144}
+\entry {\code {c-indent-level}}{143}
+\entry {\code {c-label-offset}}{144}
+\entry {\code {c-mode-hook}}{136}
+\entry {\code {c-mode-map}}{219}
+\entry {\code {c-tab-always-indent}}{142}
+\entry {\code {case-fold-search}}{76, 77}
+\entry {\code {case-replace}}{77}
+\entry {\code {command-history}}{42}
+\entry {\code {command-line-args}}{25}
+\entry {\code {comment-column}}{147}
+\entry {\code {comment-end}}{147}
+\entry {\code {comment-indent-hook}}{148}
+\entry {\code {comment-line-start}}{158}
+\entry {\code {comment-line-start-skip}}{158}
+\entry {\code {comment-multi-line}}{147}
+\entry {\code {comment-start}}{147}
+\entry {\code {comment-start-skip}}{147}
+\entry {\code {compile-command}}{161}
+\entry {\code {completion-auto-help}}{41}
+\entry {\code {completion-ignored-extensions}}{41}
+\entry {\code {ctl-arrow}}{65}
+\entry {\code {ctl-x-map}}{220}
+\initial {D}
+\entry {\code {dbx-mode-hook}}{284}
+\entry {\code {debug-on-error}}{167}
+\entry {\code {debug-on-quit}}{167}
+\entry {\code {default-directory}}{85}
+\entry {\code {default-major-mode}}{112}
+\entry {\code {delete-auto-save-files}}{94}
+\entry {\code {diary-display-hook \r {(V19)}}}{266}
+\entry {\code {diary-file \r {(V19)}}}{264}
+\entry {\code {diff-switches \r {(V19)}}}{247}
+\entry {\code {dired-chown-program \r {(V19)}}}{255}
+\entry {\code {dired-copy-preserve-time \r {(V19)}}}{255}
+\entry {\code {dired-kept-versions}}{98}
+\entry {\code {dired-listing-switches}}{96}
+\initial {E}
+\entry {\code {echo-keystrokes}}{65}
+\entry {\code {emacs-lisp-mode-hook}}{136}
+\entry {\code {emerge-combine-template \r {(V19)}}}{282}
+\entry {\code {emerge-startup-hook \r {(V19)}}}{282}
+\entry {\code {enable-local-variables \r {(V19)}}}{240}
+\entry {\code {enable-recursive-minibuffers}}{39}
+\entry {\code {esc-map}}{220}
+\entry {\code {european-calendar-style \r {(V19)}}}{266}
+\entry {\code {explicit-shell-file-name}}{206}
+\initial {F}
+\entry {\code {fill-column}}{131}
+\entry {\code {fill-prefix}}{132}
+\entry {\code {find-file-hooks}}{87}
+\entry {\code {find-file-not-found-hooks}}{87}
+\entry {\code {find-file-run-dired}}{87}
+\entry {\code {fortran-check-all-num-for-matching-do}}{157}
+\entry {\code {fortran-column-ruler}}{159}
+\entry {\code {fortran-comment-indent-char}}{158}
+\entry {\code {fortran-comment-indent-style}}{158}
+\entry {\code {fortran-comment-line-column}}{158}
+\entry {\code {fortran-comment-region}}{158}
+\entry {\code {fortran-continuation-char}}{156}
+\entry {\code {fortran-continuation-indent}}{157}
+\entry {\code {fortran-do-indent}}{157}
+\entry {\code {fortran-electric-line-number}}{156}
+\entry {\code {fortran-if-indent}}{157}
+\entry {\code {fortran-line-number-indent}}{156}
+\entry {\code {fortran-minimum-statement-indent}}{157}
+\initial {G}
+\entry {\code {gdb-mode-hook}}{284}
+\entry {\code {global-map}}{219}
+\initial {H}
+\entry {\code {help-map}}{220}
+\initial {I}
+\entry {\code {indent-tabs-mode}}{115}
+\entry {\code {Info-directory-list \r {(V19)}}}{253}
+\entry {\code {INFOPATH}}{253}
+\entry {\code {inhibit-local-variables}}{216}
+\entry {\code {inhibit-local-variables \r {(V19)}}}{240}
+\entry {\code {initial-major-mode}}{21}
+\entry {\code {insert-default-directory}}{38, 85}
+\entry {\code {inverse-video}}{65}
+\initial {K}
+\entry {\code {kept-new-versions}}{91}
+\entry {\code {kept-old-versions}}{91}
+\entry {\code {kill-buffer-hook \r {(V19)}}}{289}
+\entry {\code {kill-ring-max}}{58}
+\initial {L}
+\entry {\code {LaTeX-mode-hook}}{121}
+\entry {\code {lisp-body-indent}}{141}
+\entry {\code {lisp-indent-offset}}{141}
+\entry {\code {lisp-interaction-mode-hook}}{136}
+\entry {\code {lisp-mode-hook}}{136}
+\entry {\code {lisp-mode-map}}{219}
+\entry {\code {list-directory-brief-switches}}{96}
+\entry {\code {list-directory-verbose-switches}}{96}
+\entry {\code {load-path}}{164}
+\entry {\code {lpr-command}}{208}
+\entry {\code {lpr-switches}}{208}
+\initial {M}
+\entry {\code {mail-archive-file-name}}{183}
+\entry {\code {mail-default-reply-to}}{183}
+\entry {\code {mail-header-separator}}{182}
+\entry {\code {mail-mode-hook}}{185}
+\entry {\code {mail-setup-hook}}{185}
+\entry {\code {mail-signature \r {(V19)}}}{251}
+\entry {\code {mail-yank-prefix \r {(V19)}}}{251}
+\entry {\code {make-backup-files}}{90}
+\entry {\code {mark-ring}}{52}
+\entry {\code {mark-ring-max}}{51}
+\entry {\code {meta-flag}}{17}
+\entry {\code {minibuffer-local-completion-map}}{220}
+\entry {\code {minibuffer-local-map}}{220}
+\entry {\code {minibuffer-local-must-match-map}}{220}
+\entry {\code {minibuffer-local-ns-map}}{220}
+\entry {\code {mode-line-inverse-video}}{16, 65}
+\entry {\code {muddle-mode-hook}}{136}
+\initial {N}
+\entry {\code {next-screen-context-lines}}{63}
+\entry {\code {no-redraw-on-reenter}}{65}
+\entry {\code {nroff-mode-hook}}{118}
+\initial {O}
+\entry {\code {outline-mode-hook}}{122}
+\entry {\code {outline-regexp}}{123}
+\initial {P}
+\entry {\code {page-delimiter}}{129}
+\entry {\code {paragraph-separate}}{128}
+\entry {\code {paragraph-start}}{128}
+\entry {\code {parse-sexp-ignore-comments}}{224}
+\entry {\code {picture-mode-hook}}{177}
+\entry {\code {picture-tab-chars}}{179}
+\entry {\code {plain-TeX-mode-hook}}{121}
+\entry {\code {pre-abbrev-expand-hook \r {(V19)}}}{289}
+\initial {R}
+\entry {\code {repeat-complex-command-map}}{220}
+\entry {\code {require-final-newline}}{89}
+\entry {\code {rmail-dont-reply-to}}{197}
+\entry {\code {rmail-edit-mode-hook}}{199}
+\entry {\code {rmail-ignored-headers}}{198}
+\entry {\code {rmail-output-file-alist}}{252}
+\initial {S}
+\entry {\code {save-abbrevs}}{175}
+\entry {\code {scheme-mode-hook}}{136}
+\entry {\code {scroll-step}}{64}
+\entry {\code {sdb-mode-hook}}{284}
+\entry {\code {search-delete-char}}{69}
+\entry {\code {search-exit-char}}{69}
+\entry {\code {search-quote-char}}{69}
+\entry {\code {search-repeat-char}}{69}
+\entry {\code {search-reverse-char}}{69}
+\entry {\code {search-slow-speed}}{70}
+\entry {\code {search-slow-window-lines}}{70}
+\entry {\code {search-yank-line-char}}{69}
+\entry {\code {search-yank-word-char}}{69}
+\entry {\code {selective-display-ellipses}}{66, 126}
+\entry {\code {sentence-end}}{128}
+\entry {\code {shell-cd-regexp}}{206}
+\entry {\code {shell-file-name}}{205}
+\entry {\code {shell-popd-regexp}}{206}
+\entry {\code {shell-prompt-pattern}}{207}
+\entry {\code {shell-pushd-regexp}}{206}
+\entry {\code {shell-set-directory-error-hook}}{206}
+\entry {\code {split-window-keep-point \r {(V19)}}}{243}
+\initial {T}
+\entry {\code {tab-stop-list}}{114}
+\entry {\code {tab-width}}{66}
+\entry {\code {tags-file-name}}{152}
+\entry {\code {term-file-prefix}}{229}
+\entry {\code {term-setup-hook}}{229}
+\entry {\code {tex-directory \r {(V19)}}}{248}
+\entry {\code {TeX-mode-hook}}{121}
+\entry {\code {text-mode-hook}}{117}
+\entry {\code {track-eol}}{29}
+\entry {\code {trim-versions-without-asking}}{91}
+\entry {\code {truncate-lines}}{31}
+\entry {\code {truncate-partial-width-windows}}{108}
+\initial {U}
+\entry {\code {undo-limit}}{36}
+\entry {\code {undo-strong-limit}}{36}
+\initial {V}
+\entry {\code {vc-command-messages \r {(V19)}}}{270}
+\entry {\code {vc-comment-alist \r {(V19)}}}{276}
+\entry {\code {vc-header-string \r {(V19)}}}{276}
+\entry {\code {vc-initial-comment \r {(V19)}}}{270}
+\entry {\code {vc-keep-workfiles \r {(V19)}}}{269}
+\entry {\code {vc-log-mode-hook \r {(V19)}}}{271}
+\entry {\code {vc-make-backups \r {(V19)}}}{269}
+\entry {\code {vc-mistrust-permissions \r {(V19)}}}{271}
+\entry {\code {vc-static-header-alist \r {(V19)}}}{276}
+\entry {\code {vc-suppress-confirm \r {(V19)}}}{270}
+\entry {\code {version-control}}{90}
+\entry {\code {version-control \r {(V19)}}}{241}
+\entry {\code {VERSION{\_}CONTROL}}{241}
+\entry {\code {visible-bell}}{65}
+\initial {W}
+\entry {\code {window-min-height}}{110}
+\entry {\code {window-min-width}}{110}
+\entry {\code {write-file-hooks}}{89}
diff --git a/man/regex.texinfo b/man/regex.texinfo
new file mode 100644
index 00000000000..87529a5ee28
--- /dev/null
+++ b/man/regex.texinfo
@@ -0,0 +1,588 @@
+\input texinfo
+@comment -*- Mode: texinfo -*-
+@comment This documents the GNU regex library
+@setfilename regex
+
+@comment >> @code{"foo"} for literal strings vs @b{"foo"} vs @code{foo}
+@comment >> (this file is presently using the last --- it looks ok in
+@comment >> info; wait to see what it looks like under botex)
+
+
+@comment >> superior of (dir) is temporary
+@node top, syntax, , (dir)
+@comment node-name, next, previous, up
+@chapter @dfn{regex} regular expression matching library.
+
+@section Overview
+
+Regular expression matching allows you to test whether a string fits
+into a specific syntactic shape. You can also search a string for a
+substring that fits a pattern.
+
+A regular expression describes a set of strings. The simplest case is
+one that describes a particular string; for example, the string @samp{foo}
+when regarded as a regular expression matches @samp{foo} and nothing else.
+Nontrivial regular expressions use certain special constructs so that
+they can match more than one string. For example, the regular expression
+@samp{foo\|bar} matches either the string @samp{foo} or the string @samp{bar}; the
+regular expression @samp{c[ad]*r} matches any of the strings @samp{cr}, @samp{car},
+@samp{cdr}, @samp{caar}, @samp{cadddar} and all other such strings with any number of
+@samp{a}'s and @samp{d}'s.
+
+The first step in matching a regular expression is to compile it.
+You must supply the pattern string and also a pattern buffer to hold
+the compiled result. That result contains the pattern in an internal
+format that is easier to use in matching.
+
+Having compiled a pattern, you can match it against strings. You can
+match the compiled pattern any number of times against different
+strings.
+
+@menu
+* syntax:: Syntax of regular expressions
+* directives:: Meaning of characters as regex string directives.
+* emacs:: Additional character directives available
+ only for use within Emacs.
+* programming:: Using the regex library from C programs
+* unix:: Unix-compatible entry-points to regex library
+@end menu
+
+@node syntax, directives, top, top
+@comment node-name, next, previous, up
+@section Syntax of Regular Expressions
+
+Regular expressions have a syntax in which a few characters are special
+constructs and the rest are @dfn{ordinary}. An ordinary character is a
+simple regular expression which matches that character and nothing else.
+The special characters are @samp{$}, @samp{^}, @samp{.}, @samp{*},
+@samp{+}, @samp{?}, @samp{[}, @samp{]} and @samp{\}. Any other character
+appearing in a regular expression is ordinary, unless a @samp{\} precedes
+it.@refill
+
+For example, @samp{f} is not a special character, so it is ordinary,
+and therefore @samp{f} is a regular expression that matches the string @samp{f}
+and no other string. (It does @emph{not} match the string @samp{ff}.) Likewise,
+@samp{o} is a regular expression that matches only @samp{o}.
+
+Any two regular expressions @var{a} and @var{b} can be concatenated.
+The result is a regular expression which matches a string if @var{a}
+matches some amount of the beginning of that string and @var{b}
+matches the rest of the string.
+
+As a simple example, we can concatenate the regular expressions
+@samp{f} and @samp{o} to get the regular expression @samp{fo},
+which matches only the string @samp{fo}. Still trivial.
+
+Note: for Unix compatibility, special characters are treated as
+ordinary ones if they are in contexts where their special meanings
+make no sense. For example, @samp{*foo} treats @samp{*} as ordinary since
+there is no preceding expression on which the @samp{*} can act.
+It is poor practice to depend on this behavior; better to quote
+the special character anyway, regardless of where is appears.
+
+
+@node directives, emacs , syntax, top
+@comment node-name, next, previous, up
+
+@ifinfo
+The following are the characters and character sequences which have
+special meaning within regular expressions.
+Any character not mentioned here is not special; it stands for exactly
+itself for the purposes of searching and matching. @xref{syntax}.
+@end ifinfo
+
+@table @samp
+@item .
+is a special character that matches anything except a newline.
+Using concatenation, we can make regular expressions like @samp{a.b} which
+matches any three-character string which begins with @samp{a} and ends with @samp{b}.@refill
+
+@item *
+is not a construct by itself; it is a suffix, which means the preceding
+regular expression is to be repeated as many times as possible. In @samp{fo*},
+the @samp{*} applies to the @samp{o}, so @samp{fo*} matches @samp{f} followed by any number of @samp{o}'s.@refill
+
+The case of zero @samp{o}'s is allowed: @samp{fo*} does match @samp{f}.@refill
+
+@samp{*} always applies to the @emph{smallest} possible preceding expression.
+Thus, @samp{fo*} has a repeating @samp{o}, not a repeating @samp{fo}.@refill
+
+The matcher processes a @samp{*} construct by matching, immediately, as many
+repetitions as can be found. Then it continues with the rest of the
+pattern. If that fails, backtracking occurs, discarding some of
+the matches of the @samp{*}'d construct in case that makes it possible
+to match the rest of the pattern. For example, matching @samp{c[ad]*ar}
+against the string @samp{caddaar}, the @samp{[ad]*} first matches @samp{addaa},
+but this does not allow the next @samp{a} in the pattern to match.
+So the last of the matches of @samp{[ad]} is undone and the following
+@samp{a} is tried again. Now it succeeds.@refill
+
+@item +
+@samp{+} is like @samp{*} except that at least one match for the preceding
+pattern is required for @samp{+}. Thus, @samp{c[ad]+r} does not match
+@samp{cr} but does match anything else that @samp{c[ad]*r} would match.
+
+@item ?
+@samp{?} is like @samp{*} except that it allows either zero or one match
+for the preceding pattern. Thus, @samp{c[ad]?r} matches @samp{cr} or
+@samp{car} or @samp{cdr}, and nothing else.
+
+@item [ @dots{} ]
+@samp{[} begins a @dfn{character set}, which is terminated by a @samp{]}.
+In the simplest case, the characters between the two form the set.
+Thus, @samp{[ad]} matches either @samp{a} or @samp{d},
+and @samp{[ad]*} matches any string of @samp{a}'s and @samp{d}'s
+(including the empty string), from which it follows that
+@samp{c[ad]*r} matches @samp{car}, etc.@refill
+
+Character ranges can also be included in a character set, by writing two
+characters with a @samp{-} between them. Thus, @samp{[a-z]} matches
+any lower-case letter. Ranges may be intermixed freely with
+individual characters, as in @samp{[a-z$%.]}, which matches any
+lower case letter or @samp{$}, @samp{%} or period.@refill
+
+Note that the usual special characters are not special any more inside a
+character set. A completely different set of special characters exists
+inside character sets: @samp{]}, @samp{-} and @samp{^}.@refill
+
+To include a @samp{]} in a character set, you must make it
+the first character. For example, @samp{[]a]} matches @samp{]} or @samp{a}.
+To include a @samp{-}, you must use it in a context where it cannot possibly
+indicate a range: that is, as the first character, or immediately
+after a range.@refill
+
+@item [^ @dots{} ]
+@samp{[^} begins a @dfn{complement character set}, which matches any
+character except the ones specified. Thus, @samp{[^a-z0-9A-Z]}
+matches all characters @emph{except} letters and digits.@refill
+
+@samp{^} is not special in a character set unless it is the first character.
+The character following the @samp{^} is treated as if it were first
+(it may be a @samp{-} or a @samp{]}).@refill
+
+@item ^
+is a special character that matches the empty string -- but only
+if at the beginning of a line in the text being matched. Otherwise
+it fails to match anything. Thus, @samp{^foo} matches a @samp{foo}
+which occurs at the beginning of a line.@refill
+
+@item $
+is similar to @samp{^} but matches only at the end of a line.
+Thus, @samp{xx*$} matches a string of one or more @samp{x}'s
+at the end of a line.@refill
+
+@item \
+has two functions: it quotes the above special characters
+(including @samp{\}), and it introduces additional special constructs.@refill
+
+Because @samp{\} quotes special characters, @samp{\$} is a regular
+expression which matches only @samp{$}, and @samp{\[} is a regular
+expression which matches only @samp{[}, and so on.@refill
+
+For the most part, @samp{\} followed by any character matches only that
+character. However, there are several exceptions: characters which, when
+preceded by @samp{\}, are special constructs. Such characters are always
+ordinary when encountered on their own.@refill
+
+No new special characters will ever be defined. All extensions to
+the regular expression syntax are made by defining new two-character
+constructs that begin with @samp{\}.@refill
+
+@item \|
+specifies an alternative.
+Two regular expressions @var{a} and @var{b} with @samp{\|} in
+between form an expression that matches anything that either @var{a} or
+@var{b} will match.@refill
+
+Thus, @samp{foo\|bar} matches either @samp{foo} or @samp{bar}
+but no other string.@refill
+
+@samp{\|} applies to the largest possible surrounding expressions. Only a
+surrounding @samp{\( @dots{} \)} grouping can limit the grouping power of
+@samp{\|}.@refill
+
+Full backtracking capability exists when multiple @samp{\|}'s are used.@refill
+
+@item \( @dots{} \)
+is a grouping construct that serves three purposes:
+
+@enumerate
+@item
+To enclose a set of @samp{\|} alternatives for other operations.
+Thus, @samp{\(foo\|bar\)x} matches either @samp{foox} or @samp{barx}.
+
+@item
+To enclose a complicated expression for the postfix @samp{*} to operate on.
+Thus, @samp{ba\(na\)*} matches @samp{bananana}, etc., with any (zero or
+more) number of @samp{na}'s.@refill
+
+@item
+To mark a matched substring for future reference.
+
+@end enumerate
+
+This last application is not a consequence of the idea of a parenthetical
+grouping; it is a separate feature which happens to be assigned as a
+second meaning to the same @samp{\( @dots{} \)} construct because there is no
+conflict in practice between the two meanings. Here is an explanation
+of this feature:@refill
+
+@item \@var{digit}
+After the end of a @samp{\( @dots{} \)} construct, the matcher remembers the
+beginning and end of the text matched by that construct. Then, later on
+in the regular expression, you can use @samp{\} followed by @var{digit}
+to mean ``match the same text matched the @var{digit}'th time by the
+@samp{\( @dots{} \)} construct.'' The @samp{\( @dots{} \)} constructs
+are numbered in order of commencement in the regexp.@refill
+
+The strings matching the first nine @samp{\( @dots{} \)} constructs appearing
+in a regular expression are assigned numbers 1 through 9 in order of their
+beginnings.
+@samp{\1} through @samp{\9} may be used to refer to the text matched by
+the corresponding @samp{\( @dots{} \)} construct.@refill
+
+For example, @samp{\(.*\)\1} matches any string that is composed of two
+identical halves. The @samp{\(.*\)} matches the first half, which may be
+anything, but the @samp{\1} that follows must match the same exact text.@refill
+
+@item \b
+matches the empty string, but only if it is at the beginning or
+end of a word. Thus, @samp{\bfoo\b} matches any occurrence of
+@samp{foo} as a separate word. @samp{\bball\(s\|\)\b} matches
+@samp{ball} or @samp{balls} as a separate word.@refill
+
+@item \B
+matches the empty string, provided it is @emph{not} at the beginning or
+end of a word.@refill
+
+@item \<
+matches the empty string, but only if it is at the beginning
+of a word.
+
+@item \>
+matches the empty string, but only if it is at the end of a word.
+
+@item \w
+matches any word-constituent character.
+
+@item \W
+matches any character that is not a word-constituent.
+@end table
+
+There are a number of additional @samp{\} regexp directives available for use
+within Emacs only.
+@ifinfo
+(@pxref{emacs}).
+@comment no need to make a tex xref to something one line down!
+@end ifinfo
+
+@node emacs, programming, directives, top
+@comment node-name, next, previous, up
+@subsection Constructs Available in Emacs Only
+
+@table @samp
+@item \`
+matches the empty string, but only if it is at the beginning
+of the buffer.@refill
+
+@item \'
+matches the empty string, but only if it is at the end of
+the buffer.@refill
+
+@item \s@var{code}
+matches any character whose syntax is @var{code}.
+@var{code} is a letter which represents a syntax code:
+thus, @samp{w} for word constituent, @samp{-} for
+whitespace, @samp{(} for open-parenthesis, etc.
+See the documentation for the Emacs function @samp{modify-syntax-entry}
+for further details.@refill
+
+Thus, @samp{\s(} matches any character with open-parenthesis syntax.
+
+@item \S@var{code}
+matches any character whose syntax is not @var{code}.
+@end table
+
+@node programming, compiling, emacs, top
+@comment node-name, next, previous, up
+@section Programming using the @code{regex} library
+
+@ifinfo
+The subnodes accessible from this menu give information on entry
+points and data structures which C programs need to interface to the
+@code{regex} library.
+@end ifinfo
+
+@menu
+* compiling:: How to compile regular expressions
+* matching:: Matching compiled regular expressions
+* searching:: Searching for compiled regular expressions
+* translation:: Translating characters into other characters
+ (for both compilation and matching)
+* registers:: determining what was matched
+* split:: matching data which is split into two pieces
+* unix:: Unix-compatible entry-points to regex library
+@end menu
+
+@node compiling, matching, programming , programming
+@comment node-name, next, previous, up
+@subsection Compiling a Regular Expression
+
+To compile a regular expression, you must supply a pattern buffer.
+This is a structure defined, in the include file @file{regex.h}, as follows:
+
+@example
+struct re_pattern_buffer
+ @{
+ char *buffer /* Space holding the compiled pattern commands. */
+ int allocated /* Size of space that buffer points to */
+ int used /* Length of portion of buffer actually occupied */
+ char *fastmap; /* Pointer to fastmap, if any, or zero if none. */
+ /* re_search uses the fastmap, if there is one,
+ to skip quickly over totally implausible
+ characters */
+ char *translate;
+ /* Translate table to apply to characters before
+ comparing, or zero for no translation.
+ The translation is applied to a pattern when
+ it is compiled and to data when it is matched. */
+ char fastmap_accurate;
+ /* Set to zero when a new pattern is stored,
+ set to one when the fastmap is updated from it. */
+ @};
+@end example
+
+Before compiling a pattern, you must initialize the @code{buffer} field to
+point to a block of memory obtained with @code{malloc},
+and the @code{allocated} field to the size of that block, in bytes.
+The pattern compiler will replace this block with a larger one if necessary.
+
+You must also initialize the @code{translate} field to point to the translate
+table that you will use when you match the compiled pattern, or to zero
+if you will use no translate table when you match. @xref{translation}.
+
+Then call @code{re_compile_pattern} to compile a regular expression
+into the buffer:
+@example
+re_compile_pattern (@var{regex}, @var{regex_size}, @var{buf})
+@end example
+
+@var{regex} is the address of the regular expression (@code{char *}),
+@var{regex_size} is its length (@code{int}),
+@var{buf} is the address of the buffer (@code{struct re_pattern_buffer *}).
+
+@code{re_compile_pattern} returns zero if it succeeds in compiling the regular
+expression. In that case, @code{*buf} now contains the results.
+Otherwise, @code{re_compile_pattern} returns a string which serves as
+an error message.
+
+After compiling, if you wish to search for the pattern, you must
+initialize the @code{fastmap} component of the pattern buffer.
+@xref{searching}.
+
+@node matching, searching, compiling, programming
+@comment node-name, next, previous, up
+@subsection Matching a Compiled Pattern
+
+Once a regular expression has been compiled into a pattern buffer,
+you can match the pattern buffer against a string with @code{re_match}.
+
+@example
+re_match (@var{buf}, @var{string}, @var{size}, @var{pos}, @var{regs})
+@end example
+
+@var{buf} is, once again, the address of the buffer (@code{struct re_pattern_buffer *}).
+@var{string} is the string to be matched (@code{char *}).
+@var{size} is the length of that string (@code{int}).
+@var{pos} is the position within the string at which to begin matching (@code{int}).
+The beginning of the string is position 0.
+@var{regs} is described below. Normally it is zero. @xref{registers}.
+
+@code{re_match} returns @code{-1} if the pattern does not match; otherwise,
+it returns the length of the portion of @code{string} which was matched.
+
+For example, suppose that @var{buf} points to a buffer containing the result
+of compiling @code{x*}, @var{string} points to @code{xxxxxy}, and @var{size} is @code{6}.
+Suppose that @var{pos} is @code{2}. Then the last three @code{x}'s will be matched,
+so @code{re_match} will return @code{3}.
+If @var{pos} is zero, the value will be @code{5}.
+If @var{pos} is @code{5} or @code{6}, the value will be zero, meaning that the null string
+was successfully matched.
+Note that since @code{x*} matches the empty string, it will never entirely fail.
+
+It is up to the caller to avoid passing a value of @var{pos} that results in
+matching outside the specified string. @var{pos} must not be negative and
+must not be greater than @var{size}.
+
+@node searching, translation, matching, programming
+@comment node-name, next, previous, up
+@subsection Searching for a Match
+
+Searching means trying successive starting positions for a match until a
+match is found. To search, you supply a compiled pattern buffer. Before
+searching you must initialize the @code{fastmap} field of the pattern
+buffer (see below).
+
+@example
+re_search (@var{buf}, @var{string}, @var{size}, @var{startpos}, @var{range}, @var{regs})
+@end example
+
+@noindent
+is called like @code{re_match} except that the @var{pos} argument is
+replaced by two arguments @var{startpos} and @var{range}. @code{re_search}
+tests for a match starting at index @var{startpos}, then at
+@code{@var{startpos} + 1}, and so on. It tries @var{range} consecutive
+positions before giving up and returning @code{-1}. If a match is found,
+@code{re_search} returns the index at which the match was found.@refill
+
+If @var{range} is negative, @var{re_search} tries starting positions
+@var{startpos}, @code{@var{startpos} - 1}, @dots{} in that order.
+@code{|@var{range}|} is the number of tries made.@refill
+
+It is up to the caller to avoid passing value of @var{startpos} and
+@var{range} that result in matching outside the specified string.
+@var{startpos} must be between zero and @var{size}, inclusive, and so must
+@code{@var{startpos} + @var{range} - 1} (if @var{range} is positive) or
+@code{@var{startpos} + @var{range} + 1} (if @var{range} is negative).@refill
+
+If you may be searching over a long distance (that is, trying many
+different match starting points) with a compiled pattern, you should use a
+@dfn{fastmap} in it. This is a block of 256 bytes, whose address is
+placed in the @code{fastmap} component of the pattern buffer. The first
+time you search for a particular compiled pattern, the fastmap is set so
+that @code{@var{fastmap}[@var{ch}]} is nonzero if the character @var{ch}
+might possibly start a match for this pattern. @code{re_search} checks
+each character against the fastmap so that it can skip more quickly over
+non-matches.
+
+If you do not want a fastmap, store zero in the @code{fastmap} component of the
+pattern buffer before calling @code{re_search}.
+
+In either case, you must initialize this component in a pattern buffer
+before you can use that buffer in a search; but you can choose as an
+initial value either zero or the address of a suitable block of memory.
+
+If you compile a new pattern in an existing pattern buffer, it is not
+necessary to reinitialize the @code{fastmap} component (unless you
+wish to override your previous choice).
+
+@node translation, registers, searching, programming
+@comment node-name, next, previous, up
+@subsection Translate Tables
+
+With a translate table, you can apply a transformation to all characters
+before they are compared. For example, a table that maps lower case letters
+into upper case (or vice versa) causes differences in case to be ignored
+by matching.
+
+A translate table is a block of 256 bytes. Each character of raw data is
+used as an index in the translate table. The value found there is used
+instead of the original character. Each character in a regular
+expression, except for the syntactic constructs, is translated when the
+expression is compiled. Each character of a string being matched is
+translated whenever it is compared or tested.
+
+A suitable translate table to ignore differences in case maps all
+characters into themselves, except for lower case letters, which are
+mapped into the corresponding upper case letters.
+It could be initialized by:
+
+@example
+for (i = 0; i < 0400; i++)
+ table[i] = i;
+for (i = 'a'; i <= 'z'; i++)
+ table[i] = i - 040;
+@end example
+
+You specify the use of a translate table by putting its address in the
+@var{translate} component of the compiled pattern buffer. If this component
+is zero, no translation is done. Since both compilation and matching use
+the translate table, you must use the same table contents for both
+operations or confusing things will happen.
+
+@node registers, split, translation, programming
+@comment node-name, next, previous, up
+@subsection Registers: or ``What Did the @samp{\( @dots{} \)} Groupings Actually Match?''
+
+If you want to find out, after the match, what each of the first nine
+@samp{\( @dots{} \)} groupings actually matched, you can pass the @var{regs} argument
+to the match or search function. Pass the address of a structure of this type:
+
+@example
+struct re_registers
+ @{
+ int start[RE_NREGS];
+ int end[RE_NREGS];
+ @};
+@end example
+
+ @code{re_match} and @code{re_search} will store into this structure the
+data you want. @code{@var{regs}->start[@var{reg}]} will be the index in
+@var{string} of the beginning of the data matched by the @var{reg}'th
+@samp{\( @dots{} \)} grouping, and @code{@var{regs}->end[@var{reg}]} will
+be the index of the end of that data (the index of the first character
+beyond those matched). The values in the start and end arrays at
+indexes greater than the number of @samp{\( @dots{} \)} groupings
+present in the regular expression will be set to the value -1. Register
+numbers start at 1 and run to @code{RE_NREGS - 1} (normally @code{9}).
+@code{@var{regs}->start[0]} and @code{@var{regs}->end[0]} are similar but
+describe the extent of the substring matched by the entire pattern.@refill
+
+ Both @code{struct re_registers} and @code{RE_NREGS} are defined in @file{regex.h}.
+
+@node split, unix, registers, programming
+@comment node-name, next, previous, up
+@subsection Matching against Split Data
+
+The functions @code{re_match_2} and @code{re_search_2} allow one to match in or search
+data which is divided into two strings.
+
+@code{re_match_2} works like @code{re_match} except that two data strings and
+sizes must be given.
+
+@example
+re_match_2 (@var{buf}, @var{string1}, @var{size1}, @var{string2}, @var{size2}, @var{pos}, @var{regs})
+@end example
+
+The matcher regards the contents of @var{string1} as effectively followed by
+the contents of @var{string2}, and matches the combined string against the
+pattern in @var{buf}.
+
+@code{re_search_2} is likewise similar to @code{re_search}:
+
+@example
+re_search_2 (@var{buf}, @var{string1}, @var{size1}, @var{string2}, @var{size2}, @var{startpos}, @var{range}, @var{regs})
+@end example
+
+The value returned by @var{re_search_2} is an index into the combined data
+made up of @var{string1} and @var{string2}. It never exceeds @code{@var{size1} + @var{size2}}.
+The values returned in the @var{regs} structure (if there is one) are likewise
+indices in the combined data.
+
+@node unix, , split, programming
+@comment node-name, next, previous, up
+@subsection Unix-Compatible Entry Points
+
+The standard Berkeley Unix way to compile a regular expression is to call
+@code{re_comp}. This function takes a single argument, the address of the
+regular expression, which is assumed to be terminated by a null character.
+
+@code{re_comp} does not ask you to specify a pattern buffer because it has its
+own pattern buffer --- just one. Using @code{re_comp}, one may match only the
+most recently compiled regular expression.
+
+The value of @code{re_comp} is zero for success or else an error message string,
+as for @code{re_compile_pattern}.
+
+Calling @code{re_comp} with the null string as argument it has no effect;
+the contents of the buffer remain unchanged.
+
+The standard Berkeley Unix way to match the last regular expression compiled
+is to call @code{re_exec}. This takes a single argument, the address of
+the string to be matched. This string is assumed to be terminated by
+a null character. Matching is tried starting at each position in the
+string. @code{re_exec} returns @code{1} for success or @code{0} for failure.
+One cannot find out how long a substring was matched, nor what the
+@samp{\( @dots{} \)} groupings matched.
+
+@bye
diff --git a/man/split-man b/man/split-man
new file mode 100755
index 00000000000..cf1141c4d03
--- /dev/null
+++ b/man/split-man
@@ -0,0 +1,14 @@
+dviselect -i emacs.dvi -o emacs1.dvi 1-20
+dviselect -i emacs.dvi -o emacs21.dvi 21-40
+dviselect -i emacs.dvi -o emacs41.dvi 41-60
+dviselect -i emacs.dvi -o emacs61.dvi 61-80
+dviselect -i emacs.dvi -o emacs81.dvi 81-100
+dviselect -i emacs.dvi -o emacs101.dvi 101-120
+dviselect -i emacs.dvi -o emacs121.dvi 121-140
+dviselect -i emacs.dvi -o emacs141.dvi 141-160
+dviselect -i emacs.dvi -o emacs161.dvi 161-180
+dviselect -i emacs.dvi -o emacs181.dvi 181-200
+dviselect -i emacs.dvi -o emacs201.dvi 201-220
+dviselect -i emacs.dvi -o emacs221.dvi 221-240
+dviselect -i emacs.dvi -o emacs241.dvi 241-
+dviselect -i emacs.dvi -o emacs0.dvi _20-0
diff --git a/man/termcap.aux b/man/termcap.aux
new file mode 100644
index 00000000000..b7746c203a3
--- /dev/null
+++ b/man/termcap.aux
@@ -0,0 +1,135 @@
+'xrdef {Introduction-title}{Introduction}
+'xrdef {Introduction-pg}{1}
+'xrdef {Introduction-snt}{}
+'xrdef {Library-title}{Chapter 1: The Termcap Library}
+'xrdef {Library-pg}{3}
+'xrdef {Library-snt}{Chapter'tie1}
+'xrdef {Preparation-title}{Chapter 1: The Termcap Library}
+'xrdef {Preparation-pg}{3}
+'xrdef {Preparation-snt}{Section'tie1.1}
+'xrdef {Find-title}{Chapter 1: The Termcap Library}
+'xrdef {Find-pg}{3}
+'xrdef {Find-snt}{Section'tie1.2}
+'xrdef {Interrogate-title}{Chapter 1: The Termcap Library}
+'xrdef {Interrogate-pg}{5}
+'xrdef {Interrogate-snt}{Section'tie1.3}
+'xrdef {Initialize-title}{Chapter 1: The Termcap Library}
+'xrdef {Initialize-pg}{7}
+'xrdef {Initialize-snt}{Section'tie1.4}
+'xrdef {Padding-title}{Chapter 1: The Termcap Library}
+'xrdef {Padding-pg}{8}
+'xrdef {Padding-snt}{Section'tie1.5}
+'xrdef {Why Pad-title}{Chapter 1: The Termcap Library}
+'xrdef {Why Pad-pg}{8}
+'xrdef {Why Pad-snt}{Section'tie1.5.1}
+'xrdef {Describe Padding-title}{Chapter 1: The Termcap Library}
+'xrdef {Describe Padding-pg}{9}
+'xrdef {Describe Padding-snt}{Section'tie1.5.2}
+'xrdef {Output Padding-title}{Chapter 1: The Termcap Library}
+'xrdef {Output Padding-pg}{10}
+'xrdef {Output Padding-snt}{Section'tie1.5.3}
+'xrdef {Parameters-title}{Chapter 1: The Termcap Library}
+'xrdef {Parameters-pg}{11}
+'xrdef {Parameters-snt}{Section'tie1.6}
+'xrdef {Encode Parameters-title}{Chapter 1: The Termcap Library}
+'xrdef {Encode Parameters-pg}{12}
+'xrdef {Encode Parameters-snt}{Section'tie1.6.1}
+'xrdef {Using Parameters-title}{Chapter 1: The Termcap Library}
+'xrdef {Using Parameters-pg}{14}
+'xrdef {Using Parameters-snt}{Section'tie1.6.2}
+'xrdef {tparam-title}{Chapter 1: The Termcap Library}
+'xrdef {tparam-pg}{14}
+'xrdef {tparam-snt}{Section'tie1.6.2.1}
+'xrdef {tgoto-title}{Chapter 1: The Termcap Library}
+'xrdef {tgoto-pg}{15}
+'xrdef {tgoto-snt}{Section'tie1.6.2.2}
+'xrdef {Data Base-title}{Chapter 2: The Format of the Data Base}
+'xrdef {Data Base-pg}{17}
+'xrdef {Data Base-snt}{Chapter'tie2}
+'xrdef {Format-title}{Chapter 2: The Format of the Data Base}
+'xrdef {Format-pg}{17}
+'xrdef {Format-snt}{Section'tie2.1}
+'xrdef {Capability Format-title}{Chapter 2: The Format of the Data Base}
+'xrdef {Capability Format-pg}{18}
+'xrdef {Capability Format-snt}{Section'tie2.2}
+'xrdef {Naming-title}{Chapter 2: The Format of the Data Base}
+'xrdef {Naming-pg}{19}
+'xrdef {Naming-snt}{Section'tie2.3}
+'xrdef {Inheriting-title}{Chapter 2: The Format of the Data Base}
+'xrdef {Inheriting-pg}{20}
+'xrdef {Inheriting-snt}{Section'tie2.4}
+'xrdef {Capabilities-title}{Chapter 3: Definitions of the Terminal Capabilities}
+'xrdef {Capabilities-pg}{23}
+'xrdef {Capabilities-snt}{Chapter'tie3}
+'xrdef {Basic-title}{Chapter 3: Definitions of the Terminal Capabilities}
+'xrdef {Basic-pg}{23}
+'xrdef {Basic-snt}{Section'tie3.1}
+'xrdef {Screen Size-title}{Chapter 3: Definitions of the Terminal Capabilities}
+'xrdef {Screen Size-pg}{25}
+'xrdef {Screen Size-snt}{Section'tie3.2}
+'xrdef {Cursor Motion-title}{Chapter 3: Definitions of the Terminal Capabilities}
+'xrdef {Cursor Motion-pg}{25}
+'xrdef {Cursor Motion-snt}{Section'tie3.3}
+'xrdef {Wrapping-title}{Chapter 3: Definitions of the Terminal Capabilities}
+'xrdef {Wrapping-pg}{29}
+'xrdef {Wrapping-snt}{Section'tie3.4}
+'xrdef {Scrolling-title}{Chapter 3: Definitions of the Terminal Capabilities}
+'xrdef {Scrolling-pg}{30}
+'xrdef {Scrolling-snt}{Section'tie3.5}
+'xrdef {Windows-title}{Chapter 3: Definitions of the Terminal Capabilities}
+'xrdef {Windows-pg}{31}
+'xrdef {Windows-snt}{Section'tie3.6}
+'xrdef {Clearing-title}{Chapter 3: Definitions of the Terminal Capabilities}
+'xrdef {Clearing-pg}{32}
+'xrdef {Clearing-snt}{Section'tie3.7}
+'xrdef {Insdel Line-title}{Chapter 3: Definitions of the Terminal Capabilities}
+'xrdef {Insdel Line-pg}{33}
+'xrdef {Insdel Line-snt}{Section'tie3.8}
+'xrdef {Insdel Char-title}{Chapter 3: Definitions of the Terminal Capabilities}
+'xrdef {Insdel Char-pg}{34}
+'xrdef {Insdel Char-snt}{Section'tie3.9}
+'xrdef {Standout-title}{Chapter 3: Definitions of the Terminal Capabilities}
+'xrdef {Standout-pg}{38}
+'xrdef {Standout-snt}{Section'tie3.10}
+'xrdef {Underlining-title}{Chapter 3: Definitions of the Terminal Capabilities}
+'xrdef {Underlining-pg}{42}
+'xrdef {Underlining-snt}{Section'tie3.11}
+'xrdef {Cursor Visibility-title}{Chapter 3: Definitions of the Terminal Capabilities}
+'xrdef {Cursor Visibility-pg}{43}
+'xrdef {Cursor Visibility-snt}{Section'tie3.12}
+'xrdef {Bell-title}{Chapter 3: Definitions of the Terminal Capabilities}
+'xrdef {Bell-pg}{43}
+'xrdef {Bell-snt}{Section'tie3.13}
+'xrdef {Keypad-title}{Chapter 3: Definitions of the Terminal Capabilities}
+'xrdef {Keypad-pg}{43}
+'xrdef {Keypad-snt}{Section'tie3.14}
+'xrdef {Meta Key-title}{Chapter 3: Definitions of the Terminal Capabilities}
+'xrdef {Meta Key-pg}{45}
+'xrdef {Meta Key-snt}{Section'tie3.15}
+'xrdef {Initialization-title}{Chapter 3: Definitions of the Terminal Capabilities}
+'xrdef {Initialization-pg}{45}
+'xrdef {Initialization-snt}{Section'tie3.16}
+'xrdef {Pad Specs-title}{Chapter 3: Definitions of the Terminal Capabilities}
+'xrdef {Pad Specs-pg}{46}
+'xrdef {Pad Specs-snt}{Section'tie3.17}
+'xrdef {Status Line-title}{Chapter 3: Definitions of the Terminal Capabilities}
+'xrdef {Status Line-pg}{47}
+'xrdef {Status Line-snt}{Section'tie3.18}
+'xrdef {Half-Line-title}{Chapter 3: Definitions of the Terminal Capabilities}
+'xrdef {Half-Line-pg}{48}
+'xrdef {Half-Line-snt}{Section'tie3.19}
+'xrdef {Printer-title}{Chapter 3: Definitions of the Terminal Capabilities}
+'xrdef {Printer-pg}{48}
+'xrdef {Printer-snt}{Section'tie3.20}
+'xrdef {Summary-title}{Chapter 4: Summary of Capability Names}
+'xrdef {Summary-pg}{51}
+'xrdef {Summary-snt}{Chapter'tie4}
+'xrdef {Var Index-title}{Variable and Function Index}
+'xrdef {Var Index-pg}{57}
+'xrdef {Var Index-snt}{}
+'xrdef {Cap Index-title}{Capability Index}
+'xrdef {Cap Index-pg}{59}
+'xrdef {Cap Index-snt}{}
+'xrdef {Index-title}{Concept Index}
+'xrdef {Index-pg}{63}
+'xrdef {Index-snt}{}
diff --git a/man/termcap.cps b/man/termcap.cps
new file mode 100644
index 00000000000..f869ec396e6
--- /dev/null
+++ b/man/termcap.cps
@@ -0,0 +1,61 @@
+\initial {%}
+\entry {%}{12}
+\initial {A}
+\entry {appearance modes}{38}
+\initial {B}
+\entry {bell}{43}
+\initial {C}
+\entry {clearing the screen}{32}
+\entry {command character}{24}
+\entry {cursor motion}{25}
+\initial {D}
+\entry {delete character}{34}
+\entry {delete line}{33}
+\entry {delete mode}{35}
+\entry {description format}{17}
+\initial {E}
+\entry {erasing}{32}
+\initial {G}
+\entry {generic terminal type}{24}
+\initial {H}
+\entry {home position}{26}
+\initial {I}
+\entry {inheritance}{20}
+\entry {initialization}{45}
+\entry {insert character}{34}
+\entry {insert line}{33}
+\entry {insert mode}{35}
+\initial {L}
+\entry {line speed}{10}
+\initial {M}
+\entry {magic cookie}{38}
+\entry {meta key}{45}
+\initial {N}
+\entry {names of terminal types}{19}
+\initial {O}
+\entry {overstrike}{23}
+\initial {P}
+\entry {padding}{8, 46}
+\entry {parameters}{11}
+\entry {printer}{48}
+\initial {R}
+\entry {repeat output}{24}
+\entry {reset}{45}
+\initial {S}
+\entry {screen size}{19, 25}
+\entry {scrolling}{30}
+\entry {standout}{38}
+\entry {status line}{47}
+\entry {Superbee}{24}
+\initial {T}
+\entry {tab stops}{45}
+\entry {termcap}{1}
+\entry {terminal flags (kernel)}{7}
+\initial {U}
+\entry {underlining}{42}
+\initial {V}
+\entry {visibility}{43}
+\entry {visible bell}{43}
+\initial {W}
+\entry {window}{31}
+\entry {wrapping}{19, 29}
diff --git a/man/termcap.fns b/man/termcap.fns
new file mode 100644
index 00000000000..4b79237c764
--- /dev/null
+++ b/man/termcap.fns
@@ -0,0 +1,16 @@
+\initial {B}
+\entry {BC}{16}
+\initial {O}
+\entry {ospeed}{10}
+\initial {P}
+\entry {PC}{10}
+\initial {T}
+\entry {\code {tgetent}}{3}
+\entry {\code {tgetflag}}{5}
+\entry {\code {tgetnum}}{5}
+\entry {\code {tgetstr}}{5}
+\entry {\code {tgoto}}{15}
+\entry {\code {tparam}}{14}
+\entry {\code {tputs}}{10}
+\initial {U}
+\entry {UP}{16}
diff --git a/man/termcap.kys b/man/termcap.kys
new file mode 100644
index 00000000000..12d41e1e0ab
--- /dev/null
+++ b/man/termcap.kys
@@ -0,0 +1,153 @@
+\initial {A}
+\entry {\code {ae}}{41}
+\entry {\code {al}}{33}
+\entry {\code {AL}}{33}
+\entry {\code {am}}{29}
+\entry {\code {as}}{41}
+\initial {B}
+\entry {\code {bc}}{28}
+\entry {\code {bl}}{43}
+\entry {\code {bs}}{28}
+\entry {\code {bt}}{28}
+\entry {\code {bw}}{27}
+\initial {C}
+\entry {\code {CC}}{24}
+\entry {\code {cd}}{32}
+\entry {\code {ce}}{32}
+\entry {\code {ch}}{27}
+\entry {\code {cl}}{32}
+\entry {\code {cm}}{26}
+\entry {\code {CM}}{27}
+\entry {\code {co}}{25}
+\entry {\code {cr}}{26}
+\entry {\code {cs}}{30}
+\entry {\code {cS}}{30}
+\entry {\code {ct}}{46}
+\entry {\code {cv}}{27}
+\initial {D}
+\entry {\code {da}}{31}
+\entry {\code {db}}{31}
+\entry {\code {dB}}{47}
+\entry {\code {dc}}{38}
+\entry {\code {dC}}{47}
+\entry {\code {DC}}{38}
+\entry {\code {dF}}{47}
+\entry {\code {dl}}{33}
+\entry {\code {DL}}{33}
+\entry {\code {dm}}{38}
+\entry {\code {dN}}{47}
+\entry {\code {do}}{26}
+\entry {\code {DO}}{27}
+\entry {\code {ds}}{47}
+\entry {\code {dT}}{47}
+\initial {E}
+\entry {\code {ec}}{32}
+\entry {\code {ed}}{38}
+\entry {\code {ei}}{36}
+\entry {\code {eo}}{23}
+\entry {\code {es}}{47}
+\initial {F}
+\entry {\code {ff}}{27}
+\entry {\code {fs}}{47}
+\initial {G}
+\entry {\code {gn}}{24}
+\initial {H}
+\entry {\code {hc}}{24}
+\entry {\code {hd}}{48}
+\entry {\code {ho}}{26}
+\entry {\code {hs}}{47}
+\entry {\code {hu}}{48}
+\entry {\code {hz}}{24}
+\initial {I}
+\entry {\code {i1}}{46}
+\entry {\code {i3}}{46}
+\entry {\code {ic}}{36}
+\entry {\code {IC}}{36}
+\entry {\code {if}}{46}
+\entry {\code {im}}{36}
+\entry {\code {in}}{36}
+\entry {\code {ip}}{36}
+\entry {\code {is}}{46}
+\entry {\code {it}}{46}
+\initial {K}
+\entry {\code {K1\dots {}K5}}{44}
+\entry {\code {k1\dots {}k9}}{44}
+\entry {\code {kA\dots {}kT}}{44}
+\entry {\code {ka\dots {}ku}}{43}
+\entry {\code {km}}{45}
+\initial {L}
+\entry {\code {l0\dots {}l9}}{44}
+\entry {\code {le}}{26}
+\entry {\code {LE}}{27}
+\entry {\code {li}}{25}
+\entry {\code {ll}}{26}
+\entry {\code {lm}}{31}
+\initial {M}
+\entry {\code {mb}}{41}
+\entry {\code {md}}{41}
+\entry {\code {me}}{41}
+\entry {\code {mh}}{41}
+\entry {\code {mi}}{36}
+\entry {\code {mk}}{41}
+\entry {\code {mm}}{45}
+\entry {\code {mo}}{45}
+\entry {\code {mp}}{41}
+\entry {\code {mr}}{41}
+\entry {\code {ms}}{41, 42}
+\initial {N}
+\entry {\code {nc}}{28}
+\entry {\code {nd}}{26}
+\entry {\code {nl}}{28}
+\entry {\code {ns}}{31}
+\entry {\code {nw}}{27}
+\initial {O}
+\entry {\code {os}}{23}
+\initial {P}
+\entry {\code {pb}}{46}
+\entry {\code {pc}}{46}
+\entry {\code {pf}}{48}
+\entry {\code {po}}{48}
+\entry {\code {pO}}{48}
+\entry {\code {ps}}{48}
+\initial {R}
+\entry {\code {rc}}{27}
+\entry {\code {RI}}{27}
+\entry {\code {rp}}{24}
+\entry {\code {rs}}{46}
+\initial {S}
+\entry {\code {sa}}{41}
+\entry {\code {sc}}{27}
+\entry {\code {se}}{41}
+\entry {\code {sf}}{30}
+\entry {\code {SF}}{30}
+\entry {\code {sg}}{41}
+\entry {\code {so}}{41}
+\entry {\code {sr}}{30}
+\entry {\code {SR}}{30}
+\entry {\code {st}}{46}
+\initial {T}
+\entry {\code {ta}}{27}
+\entry {\code {te}}{46}
+\entry {\code {ti}}{45}
+\entry {\code {ts}}{47}
+\initial {U}
+\entry {\code {uc}}{42}
+\entry {\code {ue}}{42}
+\entry {\code {ug}}{42}
+\entry {\code {ul}}{42}
+\entry {\code {up}}{26}
+\entry {\code {UP}}{27}
+\entry {\code {us}}{42}
+\initial {V}
+\entry {\code {vb}}{43}
+\entry {\code {ve}}{43}
+\entry {\code {vi}}{43}
+\entry {\code {vs}}{43}
+\initial {W}
+\entry {\code {wi}}{32}
+\entry {\code {ws}}{48}
+\initial {X}
+\entry {\code {xb}}{24}
+\entry {\code {xn}}{29}
+\entry {\code {xs}}{41}
+\entry {\code {xt}}{28, 41}
diff --git a/man/termcap.texi b/man/termcap.texi
new file mode 100644
index 00000000000..e50f78eb46b
--- /dev/null
+++ b/man/termcap.texi
@@ -0,0 +1,3417 @@
+\input texinfo @c -*-texinfo-*-
+@setfilename ../info/termcap
+@settitle The Termcap Library
+@ifinfo
+This file documents the termcap library of the GNU system.
+
+Copyright (C) 1988 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+@ignore
+Permission is granted to process this file through TeX and print the
+results, provided the printed document carries copying permission
+notice identical to this one except for the removal of this paragraph
+(this paragraph not being relevant to the printed manual).
+
+@end ignore
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the entire
+resulting derived work is distributed under the terms of a permission
+notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that this permission notice may be stated in a translation approved
+by the Foundation.
+@end ifinfo
+
+@setchapternewpage odd
+@titlepage
+@sp 6
+@center @titlefont{Termcap}
+@sp 1
+@center The Termcap Library and Data Base
+@sp 4
+@center Second Edition
+@sp 1
+@center August 1992
+@sp 5
+@center Richard M. Stallman
+@sp 1
+@center Free Software Foundation
+@page
+@vskip 0pt plus 1filll
+Copyright @copyright{} 1988 Free Software Foundation, Inc.
+
+Published by the Free Software Foundation
+(675 Mass Ave, Cambridge MA 02139).
+Printed copies are available for $10 each.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the entire
+resulting derived work is distributed under the terms of a permission
+notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that this permission notice may be stated in a translation approved
+by the Foundation.
+@end titlepage
+@page
+
+@synindex vr fn
+
+@node Top, Introduction, (DIR), (DIR)
+
+@menu
+* Introduction::What is termcap? Why this manual?
+* Library:: The termcap library functions.
+* Data Base:: What terminal descriptions in @file{/etc/termcap} look like.
+* Capabilities::Definitions of the individual terminal capabilities:
+ how to write them in descriptions, and how to use
+ their values to do display updating.
+* Summary:: Brief table of capability names and their meanings.
+* Var Index:: Index of C functions and variables.
+* Cap Index:: Index of termcap capabilities.
+* Index:: Concept index.
+@end menu
+
+@node Introduction, Library, Top, Top
+@unnumbered Introduction
+
+@cindex termcap
+@dfn{Termcap} is a library and data base that enables programs to use
+display terminals in a terminal-independent manner. It originated in
+Berkeley Unix.
+
+The termcap data base describes the capabilities of hundreds of different
+display terminals in great detail. Some examples of the information
+recorded for a terminal could include how many columns wide it is, what
+string to send to move the cursor to an arbitrary position (including how
+to encode the row and column numbers), how to scroll the screen up one or
+several lines, and how much padding is needed for such a scrolling
+operation.
+
+The termcap library is provided for easy access this data base in programs
+that want to do terminal-independent character-based display output.
+
+This manual describes the GNU version of the termcap library, which has
+some extensions over the Unix version. All the extensions are identified
+as such, so this manual also tells you how to use the Unix termcap.
+
+The GNU version of the termcap library is available free as source code,
+for use in free programs, and runs on Unix and VMS systems (at least). You
+can find it in the GNU Emacs distribution in the files @file{termcap.c} and
+@file{tparam.c}.
+
+This manual was written for the GNU project, whose goal is to develop a
+complete free operating system upward-compatible with Unix for user
+programs. The project is approximately two thirds complete. For more
+information on the GNU project, including the GNU Emacs editor and the
+mostly-portable optimizing C compiler, send one dollar to
+
+@display
+Free Software Foundation
+675 Mass Ave
+Cambridge, MA 02139
+@end display
+
+@node Library, Data Base, Introduction, Top
+@chapter The Termcap Library
+
+The termcap library is the application programmer's interface to the
+termcap data base. It contains functions for the following purposes:
+
+@itemize @bullet
+@item
+Finding the description of the user's terminal type (@code{tgetent}).
+
+@item
+Interrogating the description for information on various topics
+(@code{tgetnum}, @code{tgetflag}, @code{tgetstr}).
+
+@item
+Computing and performing padding (@code{tputs}).
+
+@item
+Encoding numeric parameters such as cursor positions into the
+terminal-specific form required for display commands (@code{tparam},
+@code{tgoto}).
+@end itemize
+
+@menu
+* Preparation:: Preparing to use the termcap library.
+* Find:: Finding the description of the terminal being used.
+* Interrogate:: Interrogating the description for particular capabilities.
+* Initialize:: Initialization for output using termcap.
+* Padding:: Outputting padding.
+* Parameters:: Encoding parameters such as cursor positions.
+@end menu
+
+@node Preparation, Find, Library, Library
+@section Preparing to Use the Termcap Library
+
+To use the termcap library in a program, you need two kinds of preparation:
+
+@itemize @bullet
+@item
+The compiler needs declarations of the functions and variables in the
+library.
+
+On GNU systems, it suffices to include the header file
+@file{termcap.h} in each source file that uses these functions and
+variables.@refill
+
+On Unix systems, there is often no such header file. Then you must
+explictly declare the variables as external. You can do likewise for
+the functions, or let them be implicitly declared and cast their
+values from type @code{int} to the appropriate type.
+
+We illustrate the declarations of the individual termcap library
+functions with ANSI C prototypes because they show how to pass the
+arguments. If you are not using the GNU C compiler, you probably
+cannot use function prototypes, so omit the argument types and names
+from your declarations.
+
+@item
+The linker needs to search the library. Usually either
+@samp{-ltermcap} or @samp{-ltermlib} as an argument when linking will
+do this.@refill
+@end itemize
+
+@node Find, Interrogate, Preparation, Library
+@section Finding a Terminal Description: @code{tgetent}
+
+@findex tgetent
+An application program that is going to use termcap must first look up the
+description of the terminal type in use. This is done by calling
+@code{tgetent}, whose declaration in ANSI Standard C looks like:
+
+@example
+int tgetent (char *@var{buffer}, char *@var{termtype});
+@end example
+
+@noindent
+This function finds the description and remembers it internally so that
+you can interrogate it about specific terminal capabilities
+(@pxref{Interrogate}).
+
+The argument @var{termtype} is a string which is the name for the type of
+terminal to look up. Usually you would obtain this from the environment
+variable @code{TERM} using @code{getenv ("TERM")}.
+
+If you are using the GNU version of termcap, you can alternatively ask
+@code{tgetent} to allocate enough space. Pass a null pointer for
+@var{buffer}, and @code{tgetent} itself allocates the storage using
+@code{malloc}. In this case the returned value on success is the address
+of the storage, cast to @code{int}. But normally there is no need for you
+to look at the address. Do not free the storage yourself.@refill
+
+With the Unix version of termcap, you must allocate space for the
+description yourself and pass the address of the space as the argument
+@var{buffer}. There is no way you can tell how much space is needed, so
+the convention is to allocate a buffer 2048 characters long and assume that
+is enough. (Formerly the convention was to allocate 1024 characters and
+assume that was enough. But one day, for one kind of terminal, that was
+not enough.)
+
+No matter how the space to store the description has been obtained,
+termcap records its address internally for use when you later interrogate
+the description with @code{tgetnum}, @code{tgetstr} or @code{tgetflag}. If
+the buffer was allocated by termcap, it will be freed by termcap too if you
+call @code{tgetent} again. If the buffer was provided by you, you must
+make sure that its contents remain unchanged for as long as you still plan
+to interrogate the description.@refill
+
+The return value of @code{tgetent} is @minus{}1 if there is some difficulty
+accessing the data base of terminal types, 0 if the data base is accessible
+but the specified type is not defined in it, and some other value
+otherwise.
+
+Here is how you might use the function @code{tgetent}:
+
+@example
+#ifdef unix
+static char term_buffer[2048];
+#else
+#define term_buffer 0
+#endif
+
+init_terminal_data ()
+@{
+ char *termtype = getenv ("TERM");
+ int success;
+
+ if (termtype == 0)
+ fatal ("Specify a terminal type with `setenv TERM <yourtype>'.\n");
+
+ success = tgetent (term_buffer, termtype);
+ if (success < 0)
+ fatal ("Could not access the termcap data base.\n");
+ if (success == 0)
+ fatal ("Terminal type `%s' is not defined.\n", termtype);
+@}
+@end example
+
+@noindent
+Here we assume the function @code{fatal} prints an error message and exits.
+
+If the environment variable @code{TERMCAP} is defined, its value is used to
+override the terminal type data base. The function @code{tgetent} checks
+the value of @code{TERMCAP} automatically. If the value starts with
+@samp{/} then it is taken as a file name to use as the data base file,
+instead of @file{/etc/termcap} which is the standard data base. If the
+value does not start with @samp{/} then it is itself used as the terminal
+description, provided that the terminal type @var{termtype} is among the
+types it claims to apply to. @xref{Data Base}, for information on the
+format of a terminal description.@refill
+
+@node Interrogate, Initialize, Find, Library
+@section Interrogating the Terminal Description
+
+Each piece of information recorded in a terminal description is called a
+@dfn{capability}. Each defined terminal capability has a two-letter code
+name and a specific meaning. For example, the number of columns is named
+@samp{co}. @xref{Capabilities}, for definitions of all the standard
+capability names.
+
+Once you have found the proper terminal description with @code{tgetent}
+(@pxref{Find}), your application program must @dfn{interrogate} it for
+various terminal capabilities. You must specify the two-letter code of
+the capability whose value you seek.
+
+Capability values can be numeric, boolean (capability is either present or
+absent) or strings. Any particular capability always has the same value
+type; for example, @samp{co} always has a numeric value, while @samp{am}
+(automatic wrap at margin) is always a flag, and @samp{cm} (cursor motion
+command) always has a string value. The documentation of each capability
+says which type of value it has.@refill
+
+There are three functions to use to get the value of a capability,
+depending on the type of value the capability has. Here are their
+declarations in ANSI C:
+
+@findex tgetnum
+@findex tgetflag
+@findex tgetstr
+@example
+int tgetnum (char *@var{name});
+int tgetflag (char *@var{name});
+char *tgetstr (char *@var{name}, char **@var{area});
+@end example
+
+@table @code
+@item tgetnum
+Use @code{tgetnum} to get a capability value that is numeric. The
+argument @var{name} is the two-letter code name of the capability. If
+the capability is present, @code{tgetnum} returns the numeric value
+(which is nonnegative). If the capability is not mentioned in the
+terminal description, @code{tgetnum} returns @minus{}1.
+
+@item tgetflag
+Use @code{tgetflag} to get a boolean value. If the capability
+@var{name} is present in the terminal description, @code{tgetflag}
+returns 1; otherwise, it returns 0.
+
+@item tgetstr
+Use @code{tgetstr} to get a string value. It returns a pointer to a
+string which is the capability value, or a null pointer if the
+capability is not present in the terminal description.
+
+There are two ways @code{tgetstr} can find space to store the string value:
+
+@itemize @bullet
+@item
+You can ask @code{tgetstr} to allocate the space. Pass a null
+pointer for the argument @var{area}, and @code{tgetstr} will use
+@code{malloc} to allocate storage big enough for the value.
+Termcap will never free this storage or refer to it again; you
+should free it when you are finished with it.
+
+This method is more robust, since there is no need to guess how
+much space is needed. But it is supported only by the GNU
+termcap library.
+
+@item
+You can provide the space. Provide for the argument @var{area} the
+address of a pointer variable of type @code{char *}. Before calling
+@code{tgetstr}, initialize the variable to point at available space.
+Then @code{tgetstr} will store the string value in that space and will
+increment the pointer variable to point after the space that has been
+used. You can use the same pointer variable for many calls to
+@code{tgetstr}.
+
+There is no way to determine how much space is needed for a single
+string, and no way for you to prevent or handle overflow of the area
+you have provided. However, you can be sure that the total size of
+all the string values you will obtain from the terminal description is
+no greater than the size of the description (unless you get the same
+capability twice). You can determine that size with @code{strlen} on
+the buffer you provided to @code{tgetent}. See below for an example.
+
+Providing the space yourself is the only method supported by the Unix
+version of termcap.
+@end itemize
+@end table
+
+Note that you do not have to specify a terminal type or terminal
+description for the interrogation functions. They automatically use the
+description found by the most recent call to @code{tgetent}.
+
+Here is an example of interrogating a terminal description for various
+capabilities, with conditionals to select between the Unix and GNU methods
+of providing buffer space.
+
+@example
+char *tgetstr ();
+
+char *cl_string, *cm_string;
+int height;
+int width;
+int auto_wrap;
+
+char PC; /* For tputs. */
+char *BC; /* For tgoto. */
+char *UP;
+
+interrogate_terminal ()
+@{
+#ifdef UNIX
+ /* Here we assume that an explicit term_buffer
+ was provided to tgetent. */
+ char *buffer
+ = (char *) malloc (strlen (term_buffer));
+#define BUFFADDR &buffer
+#else
+#define BUFFADDR 0
+#endif
+
+ char *temp;
+
+ /* Extract information we will use. */
+ cl_string = tgetstr ("cl", BUFFADDR);
+ cm_string = tgetstr ("cm", BUFFADDR);
+ auto_wrap = tgetflag ("am");
+ height = tgetnum ("li");
+ width = tgetnum ("co");
+
+ /* Extract information that termcap functions use. */
+ temp = tgetstr ("pc", BUFFADDR);
+ PC = temp ? *temp : 0;
+ BC = tgetstr ("le", BUFFADDR);
+ UP = tgetstr ("up", BUFFADDR);
+@}
+@end example
+
+@noindent
+@xref{Padding}, for information on the variable @code{PC}. @xref{Using
+Parameters}, for information on @code{UP} and @code{BC}.
+
+@node Initialize, Padding, Interrogate, Library
+@section Initialization for Use of Termcap
+@cindex terminal flags (kernel)
+
+Before starting to output commands to a terminal using termcap,
+an application program should do two things:
+
+@itemize @bullet
+@item
+Initialize various global variables which termcap library output
+functions refer to. These include @code{PC} and @code{ospeed} for
+padding (@pxref{Output Padding}) and @code{UP} and @code{BC} for
+cursor motion (@pxref{tgoto}).@refill
+
+@item
+Tell the kernel to turn off alteration and padding of horizontal-tab
+characters sent to the terminal.
+@end itemize
+
+To turn off output processing in Berkeley Unix you would use @code{ioctl}
+with code @code{TIOCLSET} to set the bit named @code{LLITOUT}, and clear
+the bits @code{ANYDELAY} using @code{TIOCSETN}. In POSIX or System V, you
+must clear the bit named @code{OPOST}. Refer to the system documentation
+for details.@refill
+
+If you do not set the terminal flags properly, some older terminals will
+not work. This is because their commands may contain the characters that
+normally signify newline, carriage return and horizontal tab---characters
+which the kernel thinks it ought to modify before output.
+
+When you change the kernel's terminal flags, you must arrange to restore
+them to their normal state when your program exits. This implies that the
+program must catch fatal signals such as @code{SIGQUIT} and @code{SIGINT}
+and restore the old terminal flags before actually terminating.
+
+Modern terminals' commands do not use these special characters, so if you
+do not care about problems with old terminals, you can leave the kernel's
+terminal flags unaltered.
+
+@node Padding, Parameters, Initialize, Library
+@section Padding
+@cindex padding
+
+@dfn{Padding} means outputting null characters following a terminal display
+command that takes a long time to execute. The terminal description says
+which commands require padding and how much; the function @code{tputs},
+described below, outputs a terminal command while extracting from it the
+padding information, and then outputs the padding that is necessary.
+
+@menu
+* Why Pad:: Explanation of padding.
+* Describe Padding:: The data base says how much padding a terminal needs.
+* Output Padding:: Using @code{tputs} to output the needed padding.
+@end menu
+
+@node Why Pad, Describe Padding, Padding, Padding
+@subsection Why Pad, and How
+
+Most types of terminal have commands that take longer to execute than they
+do to send over a high-speed line. For example, clearing the screen may
+take 20msec once the entire command is received. During that time, on a
+9600 bps line, the terminal could receive about 20 additional output
+characters while still busy clearing the screen. Every terminal has a
+certain amount of buffering capacity to remember output characters that
+cannot be processed yet, but too many slow commands in a row can cause the
+buffer to fill up. Then any additional output that cannot be processed
+immediately will be lost.
+
+To avoid this problem, we normally follow each display command with enough
+useless charaters (usually null characters) to fill up the time that the
+display command needs to execute. This does the job if the terminal throws
+away null characters without using up space in the buffer (which most
+terminals do). If enough padding is used, no output can ever be lost. The
+right amount of padding avoids loss of output without slowing down
+operation, since the time used to transmit padding is time that nothing
+else could be done.
+
+The number of padding characters needed for an operation depends on the
+line speed. In fact, it is proportional to the line speed. A 9600 baud
+line transmits about one character per msec, so the clear screen command in
+the example above would need about 20 characters of padding. At 1200 baud,
+however, only about 3 characters of padding are needed to fill up 20msec.
+
+@node Describe Padding, Output Padding, Why Pad, Padding
+@subsection Specifying Padding in a Terminal Description
+
+In the terminal description, the amount of padding required by each display
+command is recorded as a sequence of digits at the front of the command.
+These digits specify the padding time in msec. They can be followed
+optionally by a decimal point and one more digit, which is a number of
+tenths of msec.
+
+Sometimes the padding needed by a command depends on the cursor position.
+For example, the time taken by an ``insert line'' command is usually
+proportional to the number of lines that need to be moved down or cleared.
+An asterisk (@samp{*}) following the padding time says that the time
+should be multiplied by the number of screen lines affected by the command.
+
+@example
+:al=1.3*\E[L:
+@end example
+
+@noindent
+is used to describe the ``insert line'' command for a certain terminal.
+The padding required is 1.3 msec per line affected. The command itself is
+@samp{@key{ESC} [ L}.
+
+The padding time specified in this way tells @code{tputs} how many pad
+characters to output. @xref{Output Padding}.
+
+Two special capability values affect padding for all commands. These are
+the @samp{pc} and @samp{pb}. The variable @samp{pc} specifies the
+character to pad with, and @samp{pb} the speed below which no padding is
+needed. The defaults for these variables, a null character and 0,
+are correct for most terminals. @xref{Pad Specs}.
+
+@node Output Padding,, Describe Padding, Padding
+@subsection Performing Padding with @code{tputs}
+@cindex line speed
+
+@findex tputs
+Use the termcap function @code{tputs} to output a string containing an
+optional padding spec of the form described above (@pxref{Describe
+Padding}). The function @code{tputs} strips off and decodes the padding
+spec, outputs the rest of the string, and then outputs the appropriate
+padding. Here is its declaration in ANSI C:
+
+@example
+char PC;
+short ospeed;
+
+int tputs (char *@var{string}, int @var{nlines}, int (*@var{outfun}) ());
+@end example
+
+Here @var{string} is the string (including padding spec) to be output;
+@var{nlines} is the number of lines affected by the operation, which is
+used to multiply the amount of padding if the padding spec ends with a
+@samp{*}. Finally, @var{outfun} is a function (such as @code{fputchar})
+that is called to output each character. When actually called,
+@var{outfun} should expect one argument, a character.
+
+@vindex ospeed
+@vindex PC
+The operation of @code{tputs} is controlled by two global variables,
+@code{ospeed} and @code{PC}. The value of @code{ospeed} is supposed to be
+the terminal output speed, encoded as in the @code{ioctl} system call which
+gets the speed information. This is needed to compute the number of
+padding characters. The value of @code{PC} is the character used for
+padding.
+
+You are responsible for storing suitable values into these variables before
+using @code{tputs}. The value stored into the @code{PC} variable should be
+taken from the @samp{pc} capability in the terminal description (@pxref{Pad
+Specs}). Store zero in @code{PC} if there is no @samp{pc}
+capability.@refill
+
+The argument @var{nlines} requires some thought. Normally, it should be
+the number of lines whose contents will be cleared or moved by the command.
+For cursor motion commands, or commands that do editing within one line,
+use the value 1. For most commands that affect multiple lines, such as
+@samp{al} (insert a line) and @samp{cd} (clear from the cursor to the end
+of the screen), @var{nlines} should be the screen height minus the current
+vertical position (origin 0). For multiple insert and scroll commands such
+as @samp{AL} (insert multiple lines), that same value for @var{nlines} is
+correct; the number of lines being inserted is @i{not} correct.@refill
+
+If a ``scroll window'' feature is used to reduce the number of lines
+affected by a command, the value of @var{nlines} should take this into
+account. This is because the delay time required depends on how much work
+the terminal has to do, and the scroll window feature reduces the work.
+@xref{Scrolling}.
+
+Commands such as @samp{ic} and @samp{dc} (insert or delete characters) are
+problematical because the padding needed by these commands is proportional
+to the number of characters affected, which is the number of columns from
+the cursor to the end of the line. It would be nice to have a way to
+specify such a dependence, and there is no need for dependence on vertical
+position in these commands, so it is an obvious idea to say that for these
+commands @var{nlines} should really be the number of columns affected.
+However, the definition of termcap clearly says that @var{nlines} is always
+the number of lines affected, even in this case, where it is always 1. It
+is not easy to change this rule now, because too many programs and terminal
+descriptions have been written to follow it.
+
+Because @var{nlines} is always 1 for the @samp{ic} and @samp{dc} strings,
+there is no reason for them to use @samp{*}, but some of them do. These
+should be corrected by deleting the @samp{*}. If, some day, such entries
+have disappeared, it may be possible to change to a more useful convention
+for the @var{nlines} argument for these operations without breaking any
+programs.
+
+@node Parameters,, Padding, Library
+@section Filling In Parameters
+@cindex parameters
+
+Some terminal control strings require numeric @dfn{parameters}. For
+example, when you move the cursor, you need to say what horizontal and
+vertical positions to move it to. The value of the terminal's @samp{cm}
+capability, which says how to move the cursor, cannot simply be a string of
+characters; it must say how to express the cursor position numbers and
+where to put them within the command.
+
+The specifications of termcap include conventions as to which string-valued
+capabilities require parameters, how many parameters, and what the
+parameters mean; for example, it defines the @samp{cm} string to take
+two parameters, the vertical and horizontal positions, with 0,0 being the
+upper left corner. These conventions are described where the individual
+commands are documented.
+
+Termcap also defines a language used within the capability definition for
+specifying how and where to encode the parameters for output. This language
+uses character sequences starting with @samp{%}. (This is the same idea as
+@code{printf}, but the details are different.) The language for parameter
+encoding is described in this section.
+
+A program that is doing display output calls the functions @code{tparam} or
+@code{tgoto} to encode parameters according to the specifications. These
+functions produce a string containing the actual commands to be output (as
+well a padding spec which must be processed with @code{tputs};
+@pxref{Padding}).
+
+@menu
+* Encode Parameters:: The language for encoding parameters.
+* Using Parameters:: Outputting a string command with parameters.
+@end menu
+
+@node Encode Parameters, Using Parameters, Parameters, Parameters
+@subsection Describing the Encoding
+@cindex %
+
+A terminal command string that requires parameters contains special
+character sequences starting with @samp{%} to say how to encode the
+parameters. These sequences control the actions of @code{tparam} and
+@code{tgoto}.
+
+The parameters values passed to @code{tparam} or @code{tgoto} are
+considered to form a vector. A pointer into this vector determines
+the next parameter to be processed. Some of the @samp{%}-sequences
+encode one parameter and advance the pointer to the next parameter.
+Other @samp{%}-sequences alter the pointer or alter the parameter
+values without generating output.
+
+For example, the @samp{cm} string for a standard ANSI terminal is written
+as @samp{\E[%i%d;%dH}. (@samp{\E} stands for @key{ESC}.) @samp{cm} by
+convention always requires two parameters, the vertical and horizontal goal
+positions, so this string specifies the encoding of two parameters. Here
+@samp{%i} increments the two values supplied, and each @samp{%d} encodes
+one of the values in decimal. If the cursor position values 20,58 are
+encoded with this string, the result is @samp{\E[21;59H}.
+
+First, here are the @samp{%}-sequences that generate output. Except for
+@samp{%%}, each of them encodes one parameter and advances the pointer
+to the following parameter.
+
+@table @samp
+@item %%
+Output a single @samp{%}. This is the only way to represent a literal
+@samp{%} in a terminal command with parameters. @samp{%%} does not
+use up a parameter.
+
+@item %d
+As in @code{printf}, output the next parameter in decimal.
+
+@item %2
+Like @samp{%02d} in @code{printf}: output the next parameter in
+decimal, and always use at least two digits.
+
+@item %3
+Like @samp{%03d} in @code{printf}: output the next parameter in
+decimal, and always use at least three digits. Note that @samp{%4}
+and so on are @emph{not} defined.
+
+@item %.
+Output the next parameter as a single character whose ASCII code is
+the parameter value. Like @samp{%c} in @code{printf}.
+
+@item %+@var{char}
+Add the next parameter to the character @var{char}, and output the
+resulting character. For example, @samp{%+ } represents 0 as a space,
+1 as @samp{!}, etc.
+@end table
+
+The following @samp{%}-sequences specify alteration of the parameters
+(their values, or their order) rather than encoding a parameter for output.
+They generate no output; they are used only for their side effects
+on the parameters. Also, they do not advance the ``next parameter'' pointer
+except as explicitly stated. Only @samp{%i}, @samp{%r} and @samp{%>} are
+defined in standard Unix termcap. The others are GNU extensions.@refill
+
+@table @samp
+@item %i
+Increment the next two parameters. This is used for terminals that
+expect cursor positions in origin 1. For example, @samp{%i%d,%d} would
+output two parameters with @samp{1} for 0, @samp{2} for 1, etc.
+
+@item %r
+Interchange the next two parameters. This is used for terminals whose
+cursor positioning command expects the horizontal position first.
+
+@item %s
+Skip the next parameter. Do not output anything.
+
+@item %b
+Back up one parameter. The last parameter used will become once again
+the next parameter to be output, and the next output command will use
+it. Using @samp{%b} more than once, you can back up any number of
+parameters, and you can refer to each parameter any number of times.
+
+@item %>@var{c1}@var{c2}
+Conditionally increment the next parameter. Here @var{c1} and
+@var{c2} are characters which stand for their ASCII codes as numbers.
+If the next parameter is greater than the ASCII code of @var{c1}, the
+ASCII code of @var{c2} is added to it.@refill
+
+@item %a @var{op} @var{type} @var{pos}
+Perform arithmetic on the next parameter, do not use it up, and do not
+output anything. Here @var{op} specifies the arithmetic operation,
+while @var{type} and @var{pos} together specify the other operand.
+
+Spaces are used above to separate the operands for clarity; the spaces
+don't appear in the data base, where this sequence is exactly five
+characters long.
+
+The character @var{op} says what kind of arithmetic operation to
+perform. It can be any of these characters:
+
+@table @samp
+@item =
+assign a value to the next parameter, ignoring its old value.
+The new value comes from the other operand.
+
+@item +
+add the other operand to the next parameter.
+
+@item -
+subtract the other operand from the next parameter.
+
+@item *
+multiply the next parameter by the other operand.
+
+@item /
+divide the next parameter by the other operand.
+@end table
+
+The ``other operand'' may be another parameter's value or a constant;
+the character @var{type} says which. It can be:
+
+@table @samp
+@item p
+Use another parameter. The character @var{pos} says which
+parameter to use. Subtract 64 from its ASCII code to get the
+position of the desired parameter relative to this one. Thus,
+the character @samp{A} as @var{pos} means the parameter after the
+next one; the character @samp{?} means the parameter before the
+next one.
+
+@item c
+Use a constant value. The character @var{pos} specifies the
+value of the constant. The 0200 bit is cleared out, so that 0200
+can be used to represent zero.
+@end table
+@end table
+
+The following @samp{%}-sequences are special purpose hacks to compensate
+for the weird designs of obscure terminals. They modify the next parameter
+or the next two parameters but do not generate output and do not use up any
+parameters. @samp{%m} is a GNU extension; the others are defined in
+standard Unix termcap.
+
+@table @samp
+@item %n
+Exclusive-or the next parameter with 0140, and likewise the parameter
+after next.
+
+@item %m
+Complement all the bits of the next parameter and the parameter after next.
+
+@item %B
+Encode the next parameter in BCD. It alters the value of the
+parameter by adding six times the quotient of the parameter by ten.
+Here is a C statement that shows how the new value is computed:
+
+@example
+@var{parm} = (@var{parm} / 10) * 16 + @var{parm} % 10;
+@end example
+
+@item %D
+Transform the next parameter as needed by Delta Data terminals.
+This involves subtracting twice the remainder of the parameter by 16.
+
+@example
+@var{parm} -= 2 * (@var{parm} % 16);
+@end example
+@end table
+
+@node Using Parameters,, Encode Parameters, Parameters
+@subsection Sending Display Commands with Parameters
+
+The termcap library functions @code{tparam} and @code{tgoto} serve as the
+analog of @code{printf} for terminal string parameters. The newer function
+@code{tparam} is a GNU extension, more general but missing from Unix
+termcap. The original parameter-encoding function is @code{tgoto}, which
+is preferable for cursor motion.
+
+@menu
+* tparam:: The general case, for GNU termcap only.
+* tgoto:: The special case of cursor motion.
+@end menu
+
+@node tparam, tgoto, Using Parameters, Using Parameters
+@subsubsection @code{tparam}
+
+@findex tparam
+The function @code{tparam} can encode display commands with any number of
+parameters and allows you to specify the buffer space. It is the preferred
+function for encoding parameters for all but the @samp{cm} capability. Its
+ANSI C declaration is as follows:
+
+@example
+char *tparam (char *@var{ctlstring}, char *@var{buffer}, int @var{size}, int @var{parm1},...)
+@end example
+
+The arguments are a control string @var{ctlstring} (the value of a terminal
+capability, presumably), an output buffer @var{buffer} and @var{size}, and
+any number of integer parameters to be encoded. The effect of
+@code{tparam} is to copy the control string into the buffer, encoding
+parameters according to the @samp{%} sequences in the control string.
+
+You describe the output buffer by its address, @var{buffer}, and its size
+in bytes, @var{size}. If the buffer is not big enough for the data to be
+stored in it, @code{tparam} calls @code{malloc} to get a larger buffer. In
+either case, @code{tparam} returns the address of the buffer it ultimately
+uses. If the value equals @var{buffer}, your original buffer was used.
+Otherwise, a new buffer was allocated, and you must free it after you are
+done with printing the results. If you pass zero for @var{size} and
+@var{buffer}, @code{tparam} always allocates the space with @code{malloc}.
+
+All capabilities that require parameters also have the ability to specify
+padding, so you should use @code{tputs} to output the string produced by
+@code{tparam}. @xref{Padding}. Here is an example.
+
+@example
+@{
+ char *buf;
+ char buffer[40];
+
+ buf = tparam (command, buffer, 40, parm);
+ tputs (buf, 1, fputchar);
+ if (buf != buffer)
+ free (buf);
+@}
+@end example
+
+If a parameter whose value is zero is encoded with @samp{%.}-style
+encoding, the result is a null character, which will confuse @code{tputs}.
+This would be a serious problem, but luckily @samp{%.} encoding is used
+only by a few old models of terminal, and only for the @samp{cm}
+capability. To solve the problem, use @code{tgoto} rather than
+@code{tparam} to encode the @samp{cm} capability.@refill
+
+@node tgoto,, tparam, Using Parameters
+@subsubsection @code{tgoto}
+
+@findex tgoto
+The special case of cursor motion is handled by @code{tgoto}. There
+are two reasons why you might choose to use @code{tgoto}:
+
+@itemize @bullet
+@item
+For Unix compatibility, because Unix termcap does not have @code{tparam}.
+
+@item
+For the @samp{cm} capability, since @code{tgoto} has a special feature
+to avoid problems with null characters, tabs and newlines on certain old
+terminal types that use @samp{%.} encoding for that capability.
+@end itemize
+
+Here is how @code{tgoto} might be declared in ANSI C:
+
+@example
+char *tgoto (char *@var{cstring}, int @var{hpos}, int @var{vpos})
+@end example
+
+There are three arguments, the terminal description's @samp{cm} string and
+the two cursor position numbers; @code{tgoto} computes the parametrized
+string in an internal static buffer and returns the address of that buffer.
+The next time you use @code{tgoto} the same buffer will be reused.
+
+@vindex UP
+@vindex BC
+Parameters encoded with @samp{%.} encoding can generate null characters,
+tabs or newlines. These might cause trouble: the null character because
+@code{tputs} would think that was the end of the string, the tab because
+the kernel or other software might expand it into spaces, and the newline
+becaue the kernel might add a carriage-return, or padding characters
+normally used for a newline. To prevent such problems, @code{tgoto} is
+careful to avoid these characters. Here is how this works: if the target
+cursor position value is such as to cause a problem (that is to say, zero,
+nine or ten), @code{tgoto} increments it by one, then compensates by
+appending a string to move the cursor back or up one position.
+
+The compensation strings to use for moving back or up are found in global
+variables named @code{BC} and @code{UP}. These are actual external C
+variables with upper case names; they are declared @code{char *}. It is up
+to you to store suitable values in them, normally obtained from the
+@samp{le} and @samp{up} terminal capabilities in the terminal description
+with @code{tgetstr}. Alternatively, if these two variables are both zero,
+the feature of avoiding nulls, tabs and newlines is turned off.
+
+It is safe to use @code{tgoto} for commands other than @samp{cm} only if
+you have stored zero in @code{BC} and @code{UP}.
+
+Note that @code{tgoto} reverses the order of its operands: the horizontal
+position comes before the vertical position in the arguments to
+@code{tgoto}, even though the vertical position comes before the horizontal
+in the parameters of the @samp{cm} string. If you use @code{tgoto} with a
+command such as @samp{AL} that takes one parameter, you must pass the
+parameter to @code{tgoto} as the ``vertical position''.@refill
+
+@node Data Base, Capabilities, Library, Top
+@chapter The Format of the Data Base
+
+The termcap data base of terminal descriptions is stored in the file
+@file{/etc/termcap}. It contains terminal descriptions, blank lines, and
+comments.
+
+A terminal description starts with one or more names for the terminal type.
+The information in the description is a series of @dfn{capability names}
+and values. The capability names have standard meanings
+(@pxref{Capabilities}) and their values describe the terminal.
+
+@menu
+* Format:: Overall format of a terminal description.
+* Capability Format:: Format of capabilities within a description.
+* Naming:: Naming conventions for terminal types.
+* Inheriting:: Inheriting part of a description from
+ a related terminal type.
+@end menu
+
+@node Format, Capability Format, Data Base, Data Base
+@section Terminal Description Format
+@cindex description format
+
+Aside from comments (lines starting with @samp{#}, which are ignored), each
+nonblank line in the termcap data base is a terminal description.
+A terminal description is nominally a single line, but it can be split
+into multiple lines by inserting the two characters @samp{\ newline}.
+This sequence is ignored wherever it appears in a description.
+
+The preferred way to split the description is between capabilities: insert
+the four characters @samp{: \ newline tab} immediately before any colon.
+This allows each sub-line to start with some indentation. This works
+because, after the @samp{\ newline} are ignored, the result is @samp{: tab
+:}; the first colon ends the preceding capability and the second colon
+starts the next capability. If you split with @samp{\ newline} alone, you
+may not add any indentation after them.
+
+Here is a real example of a terminal description:
+
+@example
+dw|vt52|DEC vt52:\
+ :cr=^M:do=^J:nl=^J:bl=^G:\
+ :le=^H:bs:cd=\EJ:ce=\EK:cl=\EH\EJ:cm=\EY%+ %+ :co#80:li#24:\
+ :nd=\EC:ta=^I:pt:sr=\EI:up=\EA:\
+ :ku=\EA:kd=\EB:kr=\EC:kl=\ED:kb=^H:
+@end example
+
+Each terminal description begins with several names for the terminal type.
+The names are separated by @samp{|} characters, and a colon ends the last
+name. The first name should be two characters long; it exists only for the
+sake of very old Unix systems and is never used in modern systems. The
+last name should be a fully verbose name such as ``DEC vt52'' or ``Ann
+Arbor Ambassador with 48 lines''. The other names should include whatever
+the user ought to be able to specify to get this terminal type, such as
+@samp{vt52} or @samp{aaa-48}. @xref{Naming}, for information on how to
+choose terminal type names.
+
+After the terminal type names come the terminal capabilities, separated by
+colons and with a colon after the last one. Each capability has a
+two-letter name, such as @samp{cm} for ``cursor motion string'' or @samp{li}
+for ``number of display lines''.
+
+@node Capability Format, Naming, Format, Data Base
+@section Writing the Capabilities
+
+There are three kinds of capabilities: flags, numbers, and strings. Each
+kind has its own way of being written in the description. Each defined
+capability has by convention a particular kind of value; for example,
+@samp{li} always has a numeric value and @samp{cm} always a string value.
+
+A flag capability is thought of as having a boolean value: the value is
+true if the capability is present, false if not. When the capability is
+present, just write its name between two colons.
+
+A numeric capability has a value which is a nonnegative number. Write the
+capability name, a @samp{#}, and the number, between two colons. For
+example, @samp{@dots{}:li#48:@dots{}} is how you specify the @samp{li}
+capability for 48 lines.@refill
+
+A string-valued capability has a value which is a sequence of characters.
+Usually these are the characters used to perform some display operation.
+Write the capability name, a @samp{=}, and the characters of the value,
+between two colons. For example, @samp{@dots{}:cm=\E[%i%d;%dH:@dots{}} is
+how the cursor motion command for a standard ANSI terminal would be
+specified.@refill
+
+Special characters in the string value can be expressed using
+@samp{\}-escape sequences as in C; in addition, @samp{\E} stands for
+@key{ESC}. @samp{^} is also a kind of escape character; @samp{^} followed
+by @var{char} stands for the control-equivalent of @var{char}. Thus,
+@samp{^a} stands for the character control-a, just like @samp{\001}.
+@samp{\} and @samp{^} themselves can be represented as @samp{\\} and
+@samp{\^}.@refill
+
+To include a colon in the string, you must write @samp{\072}. You might
+ask, ``Why can't @samp{\:} be used to represent a colon?'' The reason is
+that the interrogation functions do not count slashes while looking for a
+capability. Even if @samp{:ce=ab\:cd:} were interpreted as giving the
+@samp{ce} capability the value @samp{ab:cd}, it would also appear to define
+@samp{cd} as a flag.
+
+The string value will often contain digits at the front to specify padding
+(@pxref{Padding}) and/or @samp{%}-sequences within to specify how to encode
+parameters (@pxref{Parameters}). Although these things are not to be
+output literally to the terminal, they are considered part of the value of
+the capability. They are special only when the string value is processed
+by @code{tputs}, @code{tparam} or @code{tgoto}. By contrast, @samp{\} and
+@samp{^} are considered part of the syntax for specifying the characters
+in the string.
+
+Let's look at the VT52 example again:
+
+@example
+dw|vt52|DEC vt52:\
+ :cr=^M:do=^J:nl=^J:bl=^G:\
+ :le=^H:bs:cd=\EJ:ce=\EK:cl=\EH\EJ:cm=\EY%+ %+ :co#80:li#24:\
+ :nd=\EC:ta=^I:pt:sr=\EI:up=\EA:\
+ :ku=\EA:kd=\EB:kr=\EC:kl=\ED:kb=^H:
+@end example
+
+Here we see the numeric-valued capabilities @samp{co} and @samp{li}, the
+flags @samp{bs} and @samp{pt}, and many string-valued capabilities. Most
+of the strings start with @key{ESC} represented as @samp{\E}. The rest
+contain control characters represented using @samp{^}. The meanings of the
+individual capabilities are defined elsewhere (@pxref{Capabilities}).
+
+@node Naming, Inheriting, Capability Format, Data Base
+@section Terminal Type Name Conventions
+@cindex names of terminal types
+
+There are conventions for choosing names of terminal types. For one thing,
+all letters should be in lower case. The terminal type for a terminal in
+its most usual or most fundamental mode of operation should not have a
+hyphen in it.
+
+If the same terminal has other modes of operation which require
+different terminal descriptions, these variant descriptions are given
+names made by adding suffixes with hyphens. Such alternate descriptions
+are used for two reasons:
+
+@itemize @bullet
+@item
+When the terminal has a switch that changes its behavior. Since the
+computer cannot tell how the switch is set, the user must tell the
+computer by choosing the appropriate terminal type name.
+
+@cindex wrapping
+For example, the VT-100 has a setup flag that controls whether the
+cursor wraps at the right margin. If this flag is set to ``wrap'',
+you must use the terminal type @samp{vt100-am}. Otherwise you must
+use @samp{vt100-nam}. Plain @samp{vt100} is defined as a synonym for
+either @samp{vt100-am} or @samp{vt100-nam} depending on the
+preferences of the local site.@refill
+
+The standard suffix @samp{-am} stands for ``automatic margins''.
+
+@item
+To give the user a choice in how to use the terminal. This is done
+when the terminal has a switch that the computer normally controls.
+
+@cindex screen size
+For example, the Ann Arbor Ambassador can be configured with many
+screen sizes ranging from 20 to 60 lines. Fewer lines make bigger
+characters but more lines let you see more of what you are editing.
+As a result, users have different preferences. Therefore, termcap
+provides terminal types for many screen sizes. If you choose type
+@samp{aaa-30}, the terminal will be configured to use 30 lines; if you
+choose @samp{aaa-48}, 48 lines will be used, and so on.
+@end itemize
+
+Here is a list of standard suffixes and their conventional meanings:
+
+@table @samp
+@item -w
+Short for ``wide''. This is a mode that gives the terminal more
+columns than usual. This is normally a user option.
+
+@item -am
+``Automatic margins''. This is an alternate description for use when
+the terminal's margin-wrap switch is on; it contains the @samp{am}
+flag. The implication is that normally the switch is off and the
+usual description for the terminal says that the switch is off.
+
+@item -nam
+``No automatic margins''. The opposite of @samp{-am}, this names an
+alternative description which lacks the @samp{am} flag. This implies
+that the terminal is normally operated with the margin-wrap switch
+turned on, and the normal description of the terminal says so.
+
+@item -na
+``No arrows''. This terminal description initializes the terminal to
+keep its arrow keys in local mode. This is a user option.
+
+@item -rv
+``Reverse video''. This terminal description causes text output for
+normal video to appear as reverse, and text output for reverse video
+to come out as normal. Often this description differs from the usual
+one by interchanging the two strings which turn reverse video on and
+off.@refill
+
+This is a user option; you can choose either the ``reverse video''
+variant terminal type or the normal terminal type, and termcap will
+obey.
+
+@item -s
+``Status''. Says to enable use of a status line which ordinary output
+does not touch (@pxref{Status Line}).
+
+Some terminals have a special line that is used only as a status line.
+For these terminals, there is no need for an @samp{-s} variant; the
+status line commands should be defined by default. On other
+terminals, enabling a status line means removing one screen line from
+ordinary use and reducing the effective screen height. For these
+terminals, the user can choose the @samp{-s} variant type to request
+use of a status line.
+
+@item -@var{nlines}
+Says to operate with @var{nlines} lines on the screen, for terminals
+such as the Ambassador which provide this as an option. Normally this
+is a user option; by choosing the terminal type, you control how many
+lines termcap will use.
+
+@item -@var{npages}p
+Says that the terminal has @var{npages} pages worth of screen memory,
+for terminals where this is a hardware option.
+
+@item -unk
+Says that description is not for direct use, but only for reference in
+@samp{tc} capabilities. Such a description is a kind of subroutine,
+because it describes the common characteristics of several variant
+descriptions that would use other suffixes in place of @samp{-unk}.
+@end table
+
+@node Inheriting,, Naming, Data Base
+@section Inheriting from Related Descriptions
+
+@cindex inheritance
+When two terminal descriptions are similar, their identical parts do not
+need to be given twice. Instead, one of the two can be defined in terms of
+the other, using the @samp{tc} capability. We say that one description
+@dfn{refers to} the other, or @dfn{inherits from} the other.
+
+The @samp{tc} capability must be the last one in the terminal description,
+and its value is a string which is the name of another terminal type which
+is referred to. For example,
+
+@example
+N9|aaa|ambassador|aaa-30|ann arbor ambassador/30 lines:\
+ :ti=\E[2J\E[30;0;0;30p:\
+ :te=\E[60;0;0;30p\E[30;1H\E[J:\
+ :li#30:tc=aaa-unk:
+@end example
+
+@noindent
+defines the terminal type @samp{aaa-30} (also known as plain @samp{aaa}) in
+terms of @samp{aaa-unk}, which defines everything about the Ambassador that
+is independent of screen height. The types @samp{aaa-36}, @samp{aaa-48}
+and so on for other screen heights are likewise defined to inherit from
+@samp{aaa-unk}.
+
+The capabilities overridden by @samp{aaa-30} include @samp{li}, which says
+how many lines there are, and @samp{ti} and @samp{te}, which configure the
+terminal to use that many lines.
+
+The effective terminal description for type @samp{aaa} consists of the text
+shown above followed by the text of the description of @samp{aaa-unk}. The
+@samp{tc} capability is handled automatically by @code{tgetent}, which
+finds the description thus referenced and combines the two descriptions
+(@pxref{Find}). Therefore, only the implementor of the terminal
+descriptions needs to think about using @samp{tc}. Users and application
+programmers do not need to be concerned with it.
+
+Since the reference terminal description is used last, capabilities
+specified in the referring description override any specifications of the
+same capabilities in the reference description.
+
+The referring description can cancel out a capability without specifying
+any new value for it by means of a special trick. Write the capability in
+the referring description, with the character @samp{@@} after the capability
+name, as follows:
+
+@example
+NZ|aaa-30-nam|ann arbor ambassador/30 lines/no automatic-margins:\
+ :am@@:tc=aaa-30:
+@end example
+
+@node Capabilities, Summary, Data Base, Top
+@chapter Definitions of the Terminal Capabilities
+
+This section is divided into many subsections, each for one aspect of
+use of display terminals. For writing a display program, you usually need
+only check the subsections for the operations you want to use. For writing
+a terminal description, you must read each subsection and fill in the
+capabilities described there.
+
+String capabilities that are display commands may require numeric
+parameters (@pxref{Parameters}). Most such capabilities do not use
+parameters. When a capability requires parameters, this is explicitly
+stated at the beginning of its definition. In simple cases, the first or
+second sentence of the definition mentions all the parameters, in the order
+they should be given, using a name
+@iftex
+in italics
+@end iftex
+@ifinfo
+in upper case
+@end ifinfo
+for each one. For example, the @samp{rp} capability is a command that
+requires two parameters; its definition begins as follows:
+
+@quotation
+String of commands to output a graphic character @var{c}, repeated @var{n}
+times.
+@end quotation
+
+In complex cases or when there are many parameters, they are described
+explicitly.
+
+When a capability is described as obsolete, this means that programs should
+not be written to look for it, but terminal descriptions should still be
+written to provide it.
+
+When a capability is described as very obsolete, this means that it should
+be omitted from terminal descriptions as well.
+
+@menu
+* Basic:: Basic characteristics.
+* Screen Size:: Screen size, and what happens when it changes.
+* Cursor Motion:: Various ways to move the cursor.
+* Scrolling:: Pushing text up and down on the screen.
+* Wrapping:: What happens if you write a character in the last column.
+* Windows:: Limiting the part of the window that output affects.
+* Clearing:: Erasing one or many lines.
+* Insdel Line:: Making new blank lines in mid-screen; deleting lines.
+* Insdel Char:: Inserting and deleting characters within a line.
+* Standout:: Highlighting some of the text.
+* Underlining:: Underlining some of the text.
+* Cursor Visibility:: Making the cursor more or less easy to spot.
+* Bell:: Attracts user's attention; not localized on the screen.
+* Keypad:: Recognizing when function keys or arrows are typed.
+* Meta Key:: @key{META} acts like an extra shift key.
+* Initialization:: Commands used to initialize or reset the terminal.
+* Pad Specs:: Info for the kernel on how much padding is needed.
+* Status Line:: A status line displays ``background'' information.
+* Half-Line:: Moving by half-lines, for superscripts and subscripts.
+* Printer:: Controlling auxiliary printers of display terminals.
+@end menu
+
+@node Basic, Screen Size, Capabilities, Capabilities
+@section Basic Characteristics
+
+This section documents the capabilities that describe the basic and
+nature of the terminal, and also those that are relevant to the output
+of graphic characters.
+
+@table @samp
+@item os
+@kindex os
+@cindex overstrike
+Flag whose presence means that the terminal can overstrike. This
+means that outputting a graphic character does not erase whatever was
+present in the same character position before. The terminals that can
+overstrike include printing terminals, storage tubes (all obsolete
+nowadays), and many bit-map displays.
+
+@item eo
+@kindex eo
+Flag whose presence means that outputting a space erases a character
+position even if the terminal supports overstriking. If this flag is
+not present and overstriking is supported, output of a space has no
+effect except to move the cursor.
+
+(On terminals that do not support overstriking, you can always assume
+that outputting a space at a position erases whatever character was
+previously displayed there.)
+
+@item gn
+@kindex gn
+@cindex generic terminal type
+Flag whose presence means that this terminal type is a generic type
+which does not really describe any particular terminal. Generic types
+are intended for use as the default type assigned when the user
+connects to the system, with the intention that the user should
+specify what type he really has. One example of a generic type
+is the type @samp{network}.
+
+Since the generic type cannot say how to do anything interesting with
+the terminal, termcap-using programs will always find that the
+terminal is too weak to be supported if the user has failed to specify
+a real terminal type in place of the generic one. The @samp{gn} flag
+directs these programs to use a different error message: ``You have
+not specified your real terminal type'', rather than ``Your terminal
+is not powerful enough to be used''.
+
+@item hc
+@kindex hc
+Flag whose presence means this is a hardcopy terminal.
+
+@item rp
+@kindex rp
+@cindex repeat output
+String of commands to output a graphic character @var{c}, repeated @var{n}
+times. The first parameter value is the ASCII code for the desired
+character, and the second parameter is the number of times to repeat the
+character. Often this command requires padding proportional to the
+number of times the character is repeated. This effect can be had by
+using parameter arithmetic with @samp{%}-sequences to compute the
+amount of padding, then generating the result as a number at the front
+of the string so that @code{tputs} will treat it as padding.
+
+@item hz
+@kindex hz
+Flag whose presence means that the ASCII character @samp{~} cannot be
+output on this terminal because it is used for display commands.
+
+Programs handle this flag by checking all text to be output and
+replacing each @samp{~} with some other character(s). If this is not
+done, the screen will be thoroughly garbled.
+
+The old Hazeltine terminals that required such treatment are probably
+very rare today, so you might as well not bother to support this flag.
+
+@item CC
+@kindex CC
+@cindex command character
+String whose presence means the terminal has a settable command
+character. The value of the string is the default command character
+(which is usually @key{ESC}).
+
+All the strings of commands in the terminal description should be
+written to use the default command character. If you are writing an
+application program that changes the command character, use the
+@samp{CC} capability to figure out how to translate all the display
+commands to work with the new command character.
+
+Most programs have no reason to look at the @samp{CC} capability.
+
+@item xb
+@kindex xb
+@cindex Superbee
+Flag whose presence identifies Superbee terminals which are unable to
+transmit the characters @key{ESC} and @kbd{Control-C}. Programs which
+support this flag are supposed to check the input for the code sequences
+sent by the @key{F1} and @key{F2} keys, and pretend that @key{ESC}
+or @kbd{Control-C} (respectively) had been read. But this flag is
+obsolete, and not worth supporting.
+@end table
+
+@node Screen Size, Cursor Motion, Basic, Capabilities
+@section Screen Size
+@cindex screen size
+
+A terminal description has two capabilities, @samp{co} and @samp{li},
+that describe the screen size in columns and lines. But there is more
+to the question of screen size than this.
+
+On some operating systems the ``screen'' is really a window and the
+effective width can vary. On some of these systems, @code{tgetnum}
+uses the actual width of the window to decide what value to return for
+the @samp{co} capability, overriding what is actually written in the
+terminal description. On other systems, it is up to the application
+program to check the actual window width using a system call. For
+example, on BSD 4.3 systems, the system call @code{ioctl} with code
+@code{TIOCGWINSZ} will tell you the current screen size.
+
+On all window systems, termcap is powerless to advise the application
+program if the user resizes the window. Application programs must
+deal with this possibility in a system-dependent fashion. On some
+systems the C shell handles part of the problem by detecting changes
+in window size and setting the @code{TERMCAP} environment variable
+appropriately. This takes care of application programs that are
+started subsequently. It does not help application programs already
+running.
+
+On some systems, including BSD 4.3, all programs using a terminal get
+a signal named @code{SIGWINCH} whenever the screen size changes.
+Programs that use termcap should handle this signal by using
+@code{ioctl TIOCGWINSZ} to learn the new screen size.
+
+@table @samp
+@item co
+@kindex co
+@cindex screen size
+Numeric value, the width of the screen in character positions. Even
+hardcopy terminals normally have a @samp{co} capability.
+
+@item li
+@kindex li
+Numeric value, the height of the screen in lines.
+@end table
+
+@node Cursor Motion, Wrapping, Screen Size, Capabilities
+@section Cursor Motion
+@cindex cursor motion
+
+Termcap assumes that the terminal has a @dfn{cursor}, a spot on the screen
+where a visible mark is displayed, and that most display commands take
+effect at the position of the cursor. It follows that moving the cursor
+to a specified location is very important.
+
+There are many terminal capabilities for different cursor motion
+operations. A terminal description should define as many as possible, but
+most programs do not need to use most of them. One capability, @samp{cm},
+moves the cursor to an arbitrary place on the screen; this by itself is
+sufficient for any application as long as there is no need to support
+hardcopy terminals or certain old, weak displays that have only relative
+motion commands. Use of other cursor motion capabilities is an
+optimization, enabling the program to output fewer characters in some
+common cases.
+
+If you plan to use the relative cursor motion commands in an application
+program, you must know what the starting cursor position is. To do this,
+you must keep track of the cursor position and update the records each
+time anything is output to the terminal, including graphic characters.
+In addition, it is necessary to know whether the terminal wraps after
+writing in the rightmost column. @xref{Wrapping}.
+
+One other motion capability needs special mention: @samp{nw} moves the
+cursor to the beginning of the following line, perhaps clearing all the
+starting line after the cursor, or perhaps not clearing at all. This
+capability is a least common denominator that is probably supported even by
+terminals that cannot do most other things such as @samp{cm} or @samp{do}.
+Even hardcopy terminals can support @samp{nw}.
+
+@table @asis
+@item @samp{cm}
+@kindex cm
+String of commands to position the cursor at line @var{l}, column @var{c}.
+Both parameters are origin-zero, and are defined relative to the
+screen, not relative to display memory.
+
+All display terminals except a few very obsolete ones support @samp{cm},
+so it is acceptable for an application program to refuse to operate on
+terminals lacking @samp{cm}.
+
+@item @samp{ho}
+@kindex ho
+@cindex home position
+String of commands to move the cursor to the upper left corner of the
+screen (this position is called the @dfn{home position}). In
+terminals where the upper left corner of the screen is not the same as
+the beginning of display memory, this command must go to the upper
+left corner of the screen, not the beginning of display memory.
+
+Every display terminal supports this capability, and many application
+programs refuse to operate if the @samp{ho} capability is missing.
+
+@item @samp{ll}
+@kindex ll
+String of commands to move the cursor to the lower left corner of the
+screen. On some terminals, moving up from home position does this,
+but programs should never assume that will work. Just output the
+@samp{ll} string (if it is provided); if moving to home position and
+then moving up is the best way to get there, the @samp{ll} command
+will do that.
+
+@item @samp{cr}
+@kindex cr
+String of commands to move the cursor to the beginning of the line it
+is on. If this capability is not specified, many programs assume
+they can use the ASCII carriage return character for this.
+
+@item @samp{le}
+@kindex le
+String of commands to move the cursor left one column. Unless the
+@samp{bw} flag capability is specified, the effect is undefined if the
+cursor is at the left margin; do not use this command there. If
+@samp{bw} is present, this command may be used at the left margin, and
+it wraps the cursor to the last column of the preceding line.
+
+@item @samp{nd}
+@kindex nd
+String of commands to move the cursor right one column. The effect is
+undefined if the cursor is at the right margin; do not use this
+command there, not even if @samp{am} is present.
+
+@item @samp{up}
+@kindex up
+String of commands to move the cursor vertically up one line. The
+effect of sending this string when on the top line is undefined;
+programs should never use it that way.
+
+@item @samp{do}
+@kindex do
+String of commands to move the cursor vertically down one line. The
+effect of sending this string when on the bottom line is undefined;
+programs should never use it that way.
+
+The original idea was that this string would not contain a newline
+character and therefore could be used without disabling the kernel's usual
+habit of converting of newline into a carriage-return newline sequence.
+But many terminal descriptions do use newline in the @samp{do} string, so
+this is not possible; a program which sends the @samp{do} string must
+disable output conversion in the kernel (@pxref{Initialize}).
+
+@item @samp{bw}
+@kindex bw
+Flag whose presence says that @samp{le} may be used in column zero
+to move to the last column of the preceding line. If this flag
+is not present, @samp{le} should not be used in column zero.
+
+@item @samp{nw}
+@kindex nw
+String of commands to move the cursor to start of next line, possibly
+clearing rest of line (following the cursor) before moving.
+
+@item @samp{DO}, @samp{UP}, @samp{LE}, @samp{RI}
+@kindex DO
+@kindex LE
+@kindex RI
+@kindex UP
+Strings of commands to move the cursor @var{n} lines down vertically,
+up vertically, or @var{n} columns left or right. Do not attempt to
+move past any edge of the screen with these commands; the effect of
+trying that is undefined. Only a few terminal descriptions provide
+these commands, and most programs do not use them.
+
+@item @samp{CM}
+@kindex CM
+String of commands to position the cursor at line @var{l}, column
+@var{c}, relative to display memory. Both parameters are origin-zero.
+This capability is present only in terminals where there is a
+difference between screen-relative and memory-relative addressing, and
+not even in all such terminals.
+
+@item @samp{ch}
+@kindex ch
+String of commands to position the cursor at column @var{c} in the
+same line it is on. This is a special case of @samp{cm} in which the
+vertical position is not changed. The @samp{ch} capability is
+provided only when it is faster to output than @samp{cm} would be in
+this special case. Programs should not assume most display terminals
+have @samp{ch}.
+
+@item @samp{cv}
+@kindex cv
+String of commands to position the cursor at line @var{l} in the same
+column. This is a special case of @samp{cm} in which the horizontal
+position is not changed. The @samp{cv} capability is provided only
+when it is faster to output than @samp{cm} would be in this special
+case. Programs should not assume most display terminals have
+@samp{cv}.
+
+@item @samp{sc}
+@kindex sc
+String of commands to make the terminal save the current cursor
+position. Only the last saved position can be used. If this
+capability is present, @samp{rc} should be provided also. Most
+terminals have neither.
+
+@item @samp{rc}
+@kindex rc
+String of commands to make the terminal restore the last saved cursor
+position. If this capability is present, @samp{sc} should be provided
+also. Most terminals have neither.
+
+@item @samp{ff}
+@kindex ff
+String of commands to advance to the next page, for a hardcopy
+terminal.
+
+@item @samp{ta}
+@kindex ta
+String of commands to move the cursor right to the next hardware tab
+stop column. Missing if the terminal does not have any kind of
+hardware tabs. Do not send this command if the kernel's terminal
+modes say that the kernel is expanding tabs into spaces.
+
+@item @samp{bt}
+@kindex bt
+String of commands to move the cursor left to the previous hardware
+tab stop column. Missing if the terminal has no such ability; many
+terminals do not. Do not send this command if the kernel's terminal
+modes say that the kernel is expanding tabs into spaces.
+@end table
+
+The following obsolete capabilities should be included in terminal
+descriptions when appropriate, but should not be looked at by new programs.
+
+@table @samp
+@item nc
+@kindex nc
+Flag whose presence means the terminal does not support the ASCII
+carriage return character as @samp{cr}. This flag is needed because
+old programs assume, when the @samp{cr} capability is missing, that
+ASCII carriage return can be used for the purpose. We use @samp{nc}
+to tell the old programs that carriage return may not be used.
+
+New programs should not assume any default for @samp{cr}, so they need
+not look at @samp{nc}. However, descriptions should contain @samp{nc}
+whenever they do not contain @samp{cr}.
+
+@item xt
+@kindex xt
+Flag whose presence means that the ASCII tab character may not be used
+for cursor motion. This flag exists because old programs assume, when
+the @samp{ta} capability is missing, that ASCII tab can be used for
+the purpose. We use @samp{xt} to tell the old programs not to use tab.
+
+New programs should not assume any default for @samp{ta}, so they need
+not look at @samp{xt} in connection with cursor motion. Note that
+@samp{xt} also has implications for standout mode (@pxref{Standout}).
+It is obsolete in regard to cursor motion but not in regard to
+standout.
+
+In fact, @samp{xt} means that the terminal is a Teleray 1061.
+
+@item bc
+@kindex bc
+Very obsolete alternative name for the @samp{le} capability.
+
+@item bs
+@kindex bs
+Flag whose presence means that the ASCII character backspace may be
+used to move the cursor left. Obsolete; look at @samp{le} instead.
+
+@item nl
+@kindex nl
+Obsolete capability which is a string that can either be used to move
+the cursor down or to scroll. The same string must scroll when used
+on the bottom line and move the cursor when used on any other line.
+New programs should use @samp{do} or @samp{sf}, and ignore @samp{nl}.
+
+If there is no @samp{nl} capability, some old programs assume they can
+use the newline character for this purpose. These programs follow a
+bad practice, but because they exist, it is still desirable to define
+the @samp{nl} capability in a terminal description if the best way to
+move down is @emph{not} a newline.
+@end table
+
+@node Wrapping, Scrolling, Cursor Motion, Capabilities
+@section Wrapping
+@cindex wrapping
+
+@dfn{Wrapping} means moving the cursor from the right margin to the left
+margin of the following line. Some terminals wrap automatically when a
+graphic character is output in the last column, while others do not. Most
+application programs that use termcap need to know whether the terminal
+wraps. There are two special flag capabilities to describe what the
+terminal does when a graphic character is output in the last column.
+
+@table @samp
+@item am
+@kindex am
+Flag whose presence means that writing a character in the last column
+causes the cursor to wrap to the beginning of the next line.
+
+If @samp{am} is not present, writing in the last column leaves the
+cursor at the place where the character was written.
+
+Writing in the last column of the last line should be avoided on
+terminals with @samp{am}, as it may or may not cause scrolling to
+occur (@pxref{Scrolling}). Scrolling is surely not what you would
+intend.
+
+If your program needs to check the @samp{am} flag, then it also needs
+to check the @samp{xn} flag which indicates that wrapping happens in a
+strange way. Many common terminals have the @samp{xn} flag.
+
+@item xn
+@kindex xn
+Flag whose presence means that the cursor wraps in a strange way. At
+least two distinct kinds of strange behavior are known; the termcap
+data base does not contain anything to distinguish the two.
+
+On Concept-100 terminals, output in the last column wraps the cursor
+almost like an ordinary @samp{am} terminal. But if the next thing
+output is a newline, it is ignored.
+
+DEC VT-100 terminals (when the wrap switch is on) do a different
+strange thing: the cursor wraps only if the next thing output is
+another graphic character. In fact, the wrap occurs when the
+following graphic character is received by the terminal, before the
+character is placed on the screen.
+
+On both of these terminals, after writing in the last column a
+following graphic character will be displayed in the first column of
+the following line. But the effect of relative cursor motion
+characters such as newline or backspace at such a time depends on the
+terminal. The effect of erase or scrolling commands also depends on
+the terminal. You can't assume anything about what they will do on a
+terminal that has @samp{xn}. So, to be safe, you should never do
+these things at such a time on such a terminal.
+
+To be sure of reliable results on a terminal which has the @samp{xn}
+flag, output a @samp{cm} absolute positioning command after writing in
+the last column. Another safe thing to do is to output carriage-return
+newline, which will leave the cursor at the beginning of the following
+line.
+@end table
+
+@node Scrolling, Windows, Wrapping, Capabilities
+@section Scrolling
+@cindex scrolling
+
+@dfn{Scrolling} means moving the contents of the screen up or down one or
+more lines. Moving the contents up is @dfn{forward scrolling}; moving them
+down is @dfn{reverse scrolling}.
+
+Scrolling happens after each line of output during ordinary output on most
+display terminals. But in an application program that uses termcap for
+random-access output, scrolling happens only when explicitly requested with
+the commands in this section.
+
+Some terminals have a @dfn{scroll region} feature. This lets you limit
+the effect of scrolling to a specified range of lines. Lines outside the
+range are unaffected when scrolling happens. The scroll region feature
+is available if either @samp{cs} or @samp{cS} is present.
+
+@table @samp
+@item sf
+@kindex sf
+String of commands to scroll the screen one line up, assuming it is
+output with the cursor at the beginning of the bottom line.
+
+@item sr
+@kindex sr
+String of commands to scroll the screen one line down, assuming it is
+output with the cursor at the beginning of the top line.
+
+@item SF
+@kindex SF
+String of commands to scroll the screen @var{n} lines up, assuming it
+is output with the cursor at the beginning of the bottom line.
+
+@item SR
+@kindex SR
+String of commands to scroll the screen @var{n} line down, assuming it
+is output with the cursor at the beginning of the top line.
+
+@item cs
+@kindex cs
+String of commands to set the scroll region. This command takes two
+parameters, @var{start} and @var{end}, which are the line numbers
+(origin-zero) of the first line to include in the scroll region and of
+the last line to include in it. When a scroll region is set,
+scrolling is limited to the specified range of lines; lines outside
+the range are not affected by scroll commands.
+
+Do not try to move the cursor outside the scroll region. The region
+remains set until explicitly removed. To remove the scroll region,
+use another @samp{cs} command specifying the full height of the
+screen.
+
+The cursor position is undefined after the @samp{cs} command is set,
+so position the cursor with @samp{cm} immediately afterward.
+
+@item cS
+@kindex cS
+String of commands to set the scroll region using parameters in
+different form. The effect is the same as if @samp{cs} were used.
+Four parameters are required:
+
+@enumerate
+@item
+Total number of lines on the screen.
+@item
+Number of lines above desired scroll region.
+@item
+Number of lines below (outside of) desired scroll region.
+@item
+Total number of lines on the screen, the same as the first parameter.
+@end enumerate
+
+This capability is a GNU extension that was invented to allow the Ann
+Arbor Ambassador's scroll-region command to be described; it could
+also be done by putting non-Unix @samp{%}-sequences into a @samp{cs}
+string, but that would have confused Unix programs that used the
+@samp{cs} capability with the Unix termcap. Currently only GNU Emacs
+uses the @samp{cS} capability.
+
+@item ns
+@kindex ns
+Flag which means that the terminal does not normally scroll for
+ordinary sequential output. For modern terminals, this means that
+outputting a newline in ordinary sequential output with the cursor on
+the bottom line wraps to the top line. For some obsolete terminals,
+other things may happen.
+
+The terminal may be able to scroll even if it does not normally do so.
+If the @samp{sf} capability is provided, it can be used for scrolling
+regardless of @samp{ns}.
+
+@item da
+@kindex da
+Flag whose presence means that lines scrolled up off the top of the
+screen may come back if scrolling down is done subsequently.
+
+The @samp{da} and @samp{db} flags do not, strictly speaking, affect
+how to scroll. But programs that scroll usually need to clear the
+lines scrolled onto the screen, if these flags are present.
+
+@item db
+@kindex db
+Flag whose presence means that lines scrolled down off the bottom of
+the screen may come back if scrolling up is done subsequently.
+
+@item lm
+@kindex lm
+Numeric value, the number of lines of display memory that the terminal
+has. A value of zero means that the terminal has more display memory
+than can fit on the screen, but no fixed number of lines. (The number
+of lines may depend on the amount of text in each line.)
+@end table
+
+Any terminal description that defines @samp{SF} should also define @samp{sf};
+likewise for @samp{SR} and @samp{sr}. However, many terminals can only
+scroll by one line at a time, so it is common to find @samp{sf} and not
+@samp{SF}, or @samp{sr} without @samp{SR}.@refill
+
+Therefore, all programs that use the scrolling facilities should be
+prepared to work with @samp{sf} in the case that @samp{SF} is absent, and
+likewise with @samp{sr}. On the other hand, an application program that
+uses only @samp{sf} and not @samp{SF} is acceptable, though slow on some
+terminals.@refill
+
+When outputting a scroll command with @code{tputs}, the @var{nlines}
+argument should be the total number of lines in the portion of the screen
+being scrolled. Very often these commands require padding proportional to
+this number of lines. @xref{Padding}.
+
+@node Windows, Clearing, Scrolling, Capabilities
+@section Windows
+@cindex window
+
+A @dfn{window}, in termcap, is a rectangular portion of the screen to which
+all display operations are restricted. Wrapping, clearing, scrolling,
+insertion and deletion all operate as if the specified window were all the
+screen there was.
+
+@table @samp
+@item wi
+@kindex wi
+String of commands to set the terminal output screen window.
+This string requires four parameters, all origin-zero:
+@enumerate
+@item
+The first line to include in the window.
+@item
+The last line to include in the window.
+@item
+The first column to include in the window.
+@item
+The last column to include in the window.
+@end enumerate
+@end table
+
+Most terminals do not support windows.
+
+@node Clearing, Insdel Line, Windows, Capabilities
+@section Clearing Parts of the Screen
+@cindex erasing
+@cindex clearing the screen
+
+There are several terminal capabilities for clearing parts of the screen
+to blank. All display terminals support the @samp{cl} string, and most
+display terminals support all of these capabilities.
+
+@table @samp
+@item cl
+@kindex cl
+String of commands to clear the entire screen and position the cursor
+at the upper left corner.
+
+@item cd
+@kindex cd
+String of commands to clear the line the cursor is on, and all the
+lines below it, down to the bottom of the screen. This command string
+should be used only with the cursor in column zero; their effect is
+undefined if the cursor is elsewhere.
+
+@item ce
+@kindex ce
+String of commands to clear from the cursor to the end of the current
+line.
+
+@item ec
+@kindex ec
+String of commands to clear @var{n} characters, starting with the
+character that the cursor is on. This command string is expected to
+leave the cursor position unchanged. The parameter @var{n} should never
+be large enough to reach past the right margin; the effect of such a
+large parameter would be undefined.
+@end table
+
+Clear to end of line (@samp{ce}) is extremely important in programs that
+maintain an updating display. Nearly all display terminals support this
+operation, so it is acceptable for a an application program to refuse to
+work if @samp{ce} is not present. However, if you do not want this
+limitation, you can accomplish clearing to end of line by outputting spaces
+until you reach the right margin. In order to do this, you must know the
+current horizontal position. Also, this technique assumes that writing a
+space will erase. But this happens to be true on all the display terminals
+that fail to support @samp{ce}.
+
+@node Insdel Line, Insdel Char, Clearing, Capabilities
+@section Insert/Delete Line
+
+@cindex insert line
+@cindex delete line
+@dfn{Inserting a line} means creating a blank line in the middle
+of the screen, and pushing the existing lines of text apart. In fact,
+the lines above the insertion point do not change, while the lines below
+move down, and one is normally lost at the bottom of the screen.
+
+@dfn{Deleting a line} means causing the line to disappear from the screen,
+closing up the gap by moving the lines below it upward. A new line
+appears at the bottom of the screen. Usually this line is blank, but
+on terminals with the @samp{db} flag it may be a line previously moved
+off the screen bottom by scrolling or line insertion.
+
+Insertion and deletion of lines is useful in programs that maintain an
+updating display some parts of which may get longer or shorter. They are
+also useful in editors for scrolling parts of the screen, and for
+redisplaying after lines of text are killed or inserted.
+
+Many terminals provide commands to insert or delete a single line at the
+cursor position. Some provide the ability to insert or delete several
+lines with one command, using the number of lines to insert or delete as a
+parameter. Always move the cursor to column zero before using any of
+these commands.
+
+@table @samp
+@item al
+@kindex al
+String of commands to insert a blank line before the line the cursor
+is on. The existing line, and all lines below it, are moved down.
+The last line in the screen (or in the scroll region, if one is set)
+disappears and in most circumstances is discarded. It may not be
+discarded if the @samp{db} is present (@pxref{Scrolling}).
+
+The cursor must be at the left margin before this command is used.
+This command does not move the cursor.
+
+@item dl
+@kindex dl
+String of commands to delete the line the cursor is on. The following
+lines move up, and a blank line appears at the bottom of the screen
+(or bottom of the scroll region). If the terminal has the @samp{db}
+flag, a nonblank line previously pushed off the screen bottom may
+reappear at the bottom.
+
+The cursor must be at the left margin before this command is used.
+This command does not move the cursor.
+
+@item AL
+@kindex AL
+String of commands to insert @var{n} blank lines before the line that
+the cursor is on. It is like @samp{al} repeated @var{n} times, except
+that it is as fast as one @samp{al}.
+
+@item DL
+@kindex DL
+String of commands to delete @var{n} lines starting with the line that
+the cursor is on. It is like @samp{dl} repeated @var{n} times, except
+that it is as fast as one @samp{dl}.
+@end table
+
+Any terminal description that defines @samp{AL} should also define
+@samp{al}; likewise for @samp{DL} and @samp{dl}. However, many terminals
+can only insert or delete one line at a time, so it is common to find
+@samp{al} and not @samp{AL}, or @samp{dl} without @samp{DL}.@refill
+
+Therefore, all programs that use the insert and delete facilities should be
+prepared to work with @samp{al} in the case that @samp{AL} is absent, and
+likewise with @samp{dl}. On the other hand, it is acceptable to write
+an application that uses only @samp{al} and @samp{dl} and does not look
+for @samp{AL} or @samp{DL} at all.@refill
+
+If a terminal does not support line insertion and deletion directly,
+but does support a scroll region, the effect of insertion and deletion
+can be obtained with scrolling. However, it is up to the individual
+user program to check for this possibility and use the scrolling
+commands to get the desired result. It is fairly important to implement
+this alternate strategy, since it is the only way to get the effect of
+line insertion and deletion on the popular VT100 terminal.
+
+Insertion and deletion of lines is affected by the scroll region on
+terminals that have a settable scroll region. This is useful when it is
+desirable to move any few consecutive lines up or down by a few lines.
+@xref{Scrolling}.
+
+The line pushed off the bottom of the screen is not lost if the terminal
+has the @samp{db} flag capability; instead, it is pushed into display
+memory that does not appear on the screen. This is the same thing that
+happens when scrolling pushes a line off the bottom of the screen.
+Either reverse scrolling or deletion of a line can bring the apparently
+lost line back onto the bottom of the screen. If the terminal has the
+scroll region feature as well as @samp{db}, the pushed-out line really
+is lost if a scroll region is in effect.
+
+When outputting an insert or delete command with @code{tputs}, the
+@var{nlines} argument should be the total number of lines from the cursor
+to the bottom of the screen (or scroll region). Very often these commands
+require padding proportional to this number of lines. @xref{Padding}.
+
+For @samp{AL} and @samp{DL} the @var{nlines} argument should @emph{not}
+depend on the number of lines inserted or deleted; only the total number of
+lines affected. This is because it is just as fast to insert two or
+@var{n} lines with @samp{AL} as to insert one line with @samp{al}.
+
+@node Insdel Char, Standout, Insdel Line, Capabilities
+@section Insert/Delete Character
+@cindex insert character
+@cindex delete character
+
+@dfn{Inserting a character} means creating a blank space in the middle of a
+line, and pushing the rest of the line rightward. The character in the
+rightmost column is lost.
+
+@dfn{Deleting a character} means causing the character to disappear from
+the screen, closing up the gap by moving the rest of the line leftward. A
+blank space appears in the rightmost column.
+
+Insertion and deletion of characters is useful in programs that maintain an
+updating display some parts of which may get longer or shorter. It is also
+useful in editors for redisplaying the results of editing within a line.
+
+Many terminals provide commands to insert or delete a single character at
+the cursor position. Some provide the ability to insert or delete several
+characters with one command, using the number of characters to insert or
+delete as a parameter.
+
+@cindex insert mode
+Many terminals provide an insert mode in which outputting a graphic
+character has the added effect of inserting a position for that character.
+A special command string is used to enter insert mode and another is used
+to exit it. The reason for designing a terminal with an insert mode rather
+than an insert command is that inserting character positions is usually
+followed by writing characters into them. With insert mode, this is as
+fast as simply writing the characters, except for the fixed overhead of
+entering and leaving insert mode. However, when the line speed is great
+enough, padding may be required for the graphic characters output in insert
+mode.
+
+Some terminals require you to enter insert mode and then output a special
+command for each position to be inserted. Or they may require special
+commands to be output before or after each graphic character to be
+inserted.
+
+@cindex delete mode
+Deletion of characters is usually accomplished by a straightforward command
+to delete one or several positions; but on some terminals, it is necessary
+to enter a special delete mode before using the delete command, and leave
+delete mode afterward. Sometimes delete mode and insert mode are the same
+mode.
+
+Some terminals make a distinction between character positions in which a
+space character has been output and positions which have been cleared. On
+these terminals, the effect of insert or delete character runs to the first
+cleared position rather than to the end of the line. In fact, the effect
+may run to more than one line if there is no cleared position to stop the
+shift on the first line. These terminals are identified by the @samp{in}
+flag capability.
+
+On terminals with the @samp{in} flag, the technique of skipping over
+characters that you know were cleared, and then outputting text later on in
+the same line, causes later insert and delete character operations on that
+line to do nonstandard things. A program that has any chance of doing this
+must check for the @samp{in} flag and must be careful to write explicit
+space characters into the intermediate columns when @samp{in} is present.
+
+A plethora of terminal capabilities are needed to describe all of this
+complexity. Here is a list of them all. Following the list, we present
+an algorithm for programs to use to take proper account of all of these
+capabilities.
+
+@table @samp
+@item im
+@kindex im
+String of commands to enter insert mode.
+
+If the terminal has no special insert mode, but it can insert
+characters with a special command, @samp{im} should be defined with a
+null value, because the @samp{vi} editor assumes that insertion of a
+character is impossible if @samp{im} is not provided.
+
+New programs should not act like @samp{vi}. They should pay attention
+to @samp{im} only if it is defined.
+
+@item ei
+@kindex ei
+String of commands to leave insert mode. This capability must be
+present if @samp{im} is.
+
+On a few old terminals the same string is used to enter and exit
+insert mode. This string turns insert mode on if it was off, and off
+it it was on. You can tell these terminals because the @samp{ei}
+string equals the @samp{im} string. If you want to support these
+terminals, you must always remember accurately whether insert mode is
+in effect. However, these terminals are obsolete, and it is
+reasonable to refuse to support them. On all modern terminals, you
+can safely output @samp{ei} at any time to ensure that insert mode is
+turned off.
+
+@item ic
+@kindex ic
+String of commands to insert one character position at the cursor.
+The cursor does not move.
+
+If outputting a graphic character while in insert mode is sufficient
+to insert the character, then the @samp{ic} capability should be
+defined with a null value.
+
+If your terminal offers a choice of ways to insert---either use insert
+mode or use a special command---then define @samp{im} and do not define
+@samp{ic}, since this gives the most efficient operation when several
+characters are to be inserted. @emph{Do not} define both strings, for
+that means that @emph{both} must be used each time insertion is done.
+
+@item ip
+@kindex ip
+String of commands to output following an inserted graphic character
+in insert mode. Often it is used just for a padding spec, when padding
+is needed after an inserted character (@pxref{Padding}).
+
+@item IC
+@kindex IC
+String of commands to insert @var{n} character positions at and after
+the cursor. It has the same effect as repeating the @samp{ic} string
+and a space, @var{n} times.
+
+If @samp{IC} is provided, application programs may use it without first
+entering insert mode.
+
+@item mi
+@kindex mi
+Flag whose presence means it is safe to move the cursor while in insert
+mode and assume the terminal remains in insert mode.
+
+@item in
+@kindex in
+Flag whose presence means that the terminal distinguishes between
+character positions in which space characters have been output and
+positions which have been cleared.
+@end table
+
+An application program can assume that the terminal can do character
+insertion if @emph{any one of} the capabilities @samp{IC}, @samp{im},
+@samp{ic} or @samp{ip} is provided.
+
+To insert @var{n} blank character positions, move the cursor to the place
+to insert them and follow this algorithm:
+
+@enumerate
+@item
+If an @samp{IC} string is provided, output it with parameter @var{n}
+and you are finished. Otherwise (or if you don't want to bother to
+look for an @samp{IC} string) follow the remaining steps.
+
+@item
+Output the @samp{im} string, if there is one, unless the terminal is
+already in insert mode.
+
+@item
+Repeat steps 4 through 6, @var{n} times.
+
+@item
+Output the @samp{ic} string if any.
+
+@item
+Output a space.
+
+@item
+Output the @samp{ip} string if any.
+
+@item
+Output the @samp{ei} string, eventually, to exit insert mode. There
+is no need to do this right away. If the @samp{mi} flag is present,
+you can move the cursor and the cursor will remain in insert mode;
+then you can do more insertion elsewhere without reentering insert
+mode.
+@end enumerate
+
+To insert @var{n} graphic characters, position the cursor and follow this
+algorithm:
+
+@enumerate
+@item
+If an @samp{IC} string is provided, output it with parameter @var{n},
+then output the graphic characters, and you are finished. Otherwise
+(or if you don't want to bother to look for an @samp{IC} string)
+follow the remaining steps.
+
+@item
+Output the @samp{im} string, if there is one, unless the terminal is
+already in insert mode.
+
+@item
+For each character to be output, repeat steps 4 through 6.
+
+@item
+Output the @samp{ic} string if any.
+
+@item
+Output the next graphic character.
+
+@item
+Output the @samp{ip} string if any.
+
+@item
+Output the @samp{ei} string, eventually, to exit insert mode. There
+is no need to do this right away. If the @samp{mi} flag is present,
+you can move the cursor and the cursor will remain in insert mode;
+then you can do more insertion elsewhere without reentering insert
+mode.
+@end enumerate
+
+Note that this is not the same as the original Unix termcap specifications
+in one respect: it assumes that the @samp{IC} string can be used without
+entering insert mode. This is true as far as I know, and it allows you be
+able to avoid entering and leaving insert mode, and also to be able to
+avoid the inserted-character padding after the characters that go into the
+inserted positions.
+
+Deletion of characters is less complicated; deleting one column is done by
+outputting the @samp{dc} string. However, there may be a delete mode that
+must be entered with @samp{dm} in order to make @samp{dc} work.
+
+@table @samp
+@item dc
+@kindex dc
+String of commands to delete one character position at the cursor. If
+@samp{dc} is not present, the terminal cannot delete characters.
+
+@item DC
+@kindex DC
+String of commands to delete @var{n} characters starting at the cursor.
+It has the same effect as repeating the @samp{dc} string @var{n} times.
+Any terminal description that has @samp{DC} also has @samp{dc}.
+
+@item dm
+@kindex dm
+String of commands to enter delete mode. If not present, there is no
+delete mode, and @samp{dc} can be used at any time (assuming there is
+a @samp{dc}).
+
+@item ed
+@kindex ed
+String of commands to exit delete mode. This must be present if
+@samp{dm} is.
+@end table
+
+To delete @var{n} character positions, position the cursor and follow these
+steps:
+
+@enumerate
+@item
+If the @samp{DC} string is present, output it with parameter @var{n}
+and you are finished. Otherwise, follow the remaining steps.
+
+@item
+Output the @samp{dm} string, unless you know the terminal is already
+in delete mode.
+
+@item
+Output the @samp{dc} string @var{n} times.
+
+@item
+Output the @samp{ed} string eventually. If the flag capability
+@samp{mi} is present, you can move the cursor and do more deletion
+without leaving and reentering delete mode.
+@end enumerate
+
+As with the @samp{IC} string, we have departed from the original termcap
+specifications by assuming that @samp{DC} works without entering delete
+mode even though @samp{dc} would not.
+
+If the @samp{dm} and @samp{im} capabilities are both present and have the
+same value, it means that the terminal has one mode for both insertion and
+deletion. It is useful for a program to know this, because then it can do
+insertions after deletions, or vice versa, without leaving insert/delete
+mode and reentering it.
+
+@node Standout, Underlining, Insdel Char, Capabilities
+@section Standout and Appearance Modes
+@cindex appearance modes
+@cindex standout
+@cindex magic cookie
+
+@dfn{Appearance modes} are modifications to the ways characters are
+displayed. Typical appearance modes include reverse video, dim, bright,
+blinking, underlined, invisible, and alternate character set. Each kind of
+terminal supports various among these, or perhaps none.
+
+For each type of terminal, one appearance mode or combination of them that
+looks good for highlighted text is chosen as the @dfn{standout mode}. The
+capabilities @samp{so} and @samp{se} say how to enter and leave standout
+mode. Programs that use appearance modes only to highlight some text
+generally use the standout mode so that they can work on as many terminals
+as possible. Use of specific appearance modes other than ``underlined''
+and ``alternate character set'' is rare.
+
+Terminals that implement appearance modes fall into two general classes as
+to how they do it.
+
+In some terminals, the presence or absence of any appearance mode is
+recorded separately for each character position. In these terminals, each
+graphic character written is given the appearance modes current at the time
+it is written, and keeps those modes until it is erased or overwritten.
+There are special commands to turn the appearance modes on or off for
+characters to be written in the future.
+
+In other terminals, the change of appearance modes is represented by a
+marker that belongs to a certain screen position but affects all following
+screen positions until the next marker. These markers are traditionally
+called @dfn{magic cookies}.
+
+The same capabilities (@samp{so}, @samp{se}, @samp{mb} and so on) for
+turning appearance modes on and off are used for both magic-cookie
+terminals and per-character terminals. On magic cookie terminals, these
+give the commands to write the magic cookies. On per-character terminals,
+they change the current modes that affect future output and erasure. Some
+simple applications can use these commands without knowing whether or not
+they work by means of cookies.
+
+However, a program that maintains and updates a display needs to know
+whether the terminal uses magic cookies, and exactly what their effect is.
+This information comes from the @samp{sg} capability.
+
+The @samp{sg} capability is a numeric capability whose presence indicates
+that the terminal uses magic cookies for appearance modes. Its value is
+the number of character positions that a magic cookie occupies. Usually
+the cookie occupies one or more character positions on the screen, and these
+character positions are displayed as blank, but in some terminals the
+cookie has zero width.
+
+The @samp{sg} capability describes both the magic cookie to turn standout
+on and the cookie to turn it off. This makes the assumption that both
+kinds of cookie have the same width on the screen. If that is not true,
+the narrower cookie must be ``widened'' with spaces until it has the same
+width as the other.
+
+On some magic cookie terminals, each line always starts with normal
+display; in other words, the scope of a magic cookie never extends over
+more than one line. But on other terminals, one magic cookie affects all
+the lines below it unless explicitly canceled. Termcap does not define any
+way to distinguish these two ways magic cookies can work. To be safe, it
+is best to put a cookie at the beginning of each line.
+
+On some per-character terminals, standout mode or other appearance modes
+may be canceled by moving the cursor. On others, moving the cursor has no
+effect on the state of the appearance modes. The latter class of terminals
+are given the flag capability @samp{ms} (``can move in standout''). All
+programs that might have occasion to move the cursor while appearance modes
+are turned on must check for this flag; if it is not present, they should
+reset appearance modes to normal before doing cursor motion.
+
+A program that has turned on only standout mode should use @samp{se} to
+reset the standout mode to normal. A program that has turned on only
+alternate character set mode should use @samp{ae} to return it to normal.
+If it is possible that any other appearance modes are turned on, use the
+@samp{me} capability to return them to normal.
+
+Note that the commands to turn on one appearance mode, including @samp{so}
+and @samp{mb} @dots{} @samp{mr}, if used while some other appearance modes
+are turned on, may combine the two modes on some terminals but may turn off
+the mode previously enabled on other terminals. This is because some
+terminals do not have a command to set or clear one appearance mode without
+changing the others. Programs should not attempt to use appearance modes
+in combination except with @samp{sa}, and when switching from one single
+mode to another should always turn off the previously enabled mode and then
+turn on the new desired mode.
+
+On some old terminals, the @samp{so} and @samp{se} commands may be the same
+command, which has the effect of turning standout on if it is off, or off
+it is on. It is therefore risky for a program to output extra @samp{se}
+commands for good measure. Fortunately, all these terminals are obsolete.
+
+Programs that update displays in which standout-text may be replaced with
+non-standout text must check for the @samp{xs} flag. In a per-character
+terminal, this flag says that the only way to remove standout once written is
+to clear that portion of the line with the @samp{ce} string or something
+even more powerful (@pxref{Clearing}); just writing new characters at those
+screen positions will not change the modes in effect there. In a magic
+cookie terminal, @samp{xs} says that the only way to remove a cookie is to
+clear a portion of the line that includes the cookie; writing a different
+cookie at the same position does not work.
+
+Such programs must also check for the @samp{xt} flag, which means that the
+terminal is a Teleray 1061. On this terminal it is impossible to position
+the cursor at the front of a magic cookie, so the only two ways to remove a
+cookie are (1) to delete the line it is on or (2) to position the cursor at
+least one character before it (possibly on a previous line) and output the
+@samp{se} string, which on these terminals finds and removes the next
+@samp{so} magic cookie on the screen. (It may also be possible to remove a
+cookie which is not at the beginning of a line by clearing that line.) The
+@samp{xt} capability also has implications for the use of tab characters,
+but in that regard it is obsolete (@xref{Cursor Motion}).
+
+@table @samp
+@item so
+@kindex so
+String of commands to enter standout mode.
+
+@item se
+@kindex se
+String of commands to leave standout mode.
+
+@item sg
+@kindex sg
+Numeric capability, the width on the screen of the magic cookie. This
+capability is absent in terminals that record appearance modes
+character by character.
+
+@item ms
+@kindex ms
+Flag whose presence means that it is safe to move the cursor while the
+appearance modes are not in the normal state. If this flag is absent,
+programs should always reset the appearance modes to normal before
+moving the cursor.
+
+@item xs
+@kindex xs
+Flag whose presence means that the only way to reset appearance modes
+already on the screen is to clear to end of line. On a per-character
+terminal, you must clear the area where the modes are set. On a magic
+cookie terminal, you must clear an area containing the cookie.
+See the discussion above.
+
+@item xt
+@kindex xt
+Flag whose presence means that the cursor cannot be positioned right
+in front of a magic cookie, and that @samp{se} is a command to delete
+the next magic cookie following the cursor. See discussion above.
+
+@item mb
+@kindex mb
+String of commands to enter blinking mode.
+
+@item md
+@kindex md
+String of commands to enter double-bright mode.
+
+@item mh
+@kindex mh
+String of commands to enter half-bright mode.
+
+@item mk
+@kindex mk
+String of commands to enter invisible mode.
+
+@item mp
+@kindex mp
+String of commands to enter protected mode.
+
+@item mr
+@kindex mr
+String of commands to enter reverse-video mode.
+
+@item me
+@kindex me
+String of commands to turn off all appearance modes, including
+standout mode and underline mode. On some terminals it also turns off
+alternate character set mode; on others, it may not. This capability
+must be present if any of @samp{mb} @dots{} @samp{mr} is present.
+
+@item as
+@kindex as
+String of commands to turn on alternate character set mode. This mode
+assigns some or all graphic characters an alternate picture on the
+screen. There is no standard as to what the alternate pictures look
+like.
+
+@item ae
+@kindex ae
+String of commands to turn off alternate character set mode.
+
+@item sa
+@kindex sa
+String of commands to turn on an arbitrary combination of appearance
+modes. It accepts 9 parameters, each of which controls a particular
+kind of appearance mode. A parameter should be 1 to turn its appearance
+mode on, or zero to turn that mode off. Most terminals do not support
+the @samp{sa} capability, even among those that do have various
+appearance modes.
+
+The nine parameters are, in order, @var{standout}, @var{underline},
+@var{reverse}, @var{blink}, @var{half-bright}, @var{double-bright},
+@var{blank}, @var{protect}, @var{alt char set}.
+@end table
+
+@node Underlining, Cursor Visibility, Standout, Capabilities
+@section Underlining
+@cindex underlining
+
+Underlining on most terminals is a kind of appearance mode, much like
+standout mode. Therefore, it may be implemented using magic cookies or as
+a flag in the terminal whose current state affects each character that is
+output. @xref{Standout}, for a full explanation.
+
+The @samp{ug} capability is a numeric capability whose presence indicates
+that the terminal uses magic cookies for underlining. Its value is the
+number of character positions that a magic cookie for underlining occupies;
+it is used for underlining just as @samp{sg} is used for standout. Aside
+from the simplest applications, it is impossible to use underlining
+correctly without paying attention to the value of @samp{ug}.
+
+@table @samp
+@item us
+@kindex us
+String of commands to turn on underline mode or to output a magic cookie
+to start underlining.
+
+@item ue
+@kindex ue
+String of commands to turn off underline mode or to output a magic
+cookie to stop underlining.
+
+@item ug
+@kindex ug
+Width of magic cookie that represents a change of underline mode;
+or missing, if the terminal does not use a magic cookie for this.
+
+@item ms
+@kindex ms
+Flag whose presence means that it is safe to move the cursor while the
+appearance modes are not in the normal state. Underlining is an
+appearance mode. If this flag is absent, programs should always turn
+off underlining before moving the cursor.
+@end table
+
+There are two other, older ways of doing underlining: there can be a
+command to underline a single character, or the output of @samp{_}, the
+ASCII underscore character, as an overstrike could cause a character to be
+underlined. New programs need not bother to handle these capabilities
+unless the author cares strongly about the obscure terminals which support
+them. However, terminal descriptions should provide these capabilities
+when appropriate.
+
+@table @samp
+@item uc
+@kindex uc
+String of commands to underline the character under the cursor, and
+move the cursor right.
+
+@item ul
+@kindex ul
+Flag whose presence means that the terminal can underline by
+overstriking an underscore character (@samp{_}); some terminals can do
+this even though they do not support overstriking in general. An
+implication of this flag is that when outputting new text to overwrite
+old text, underscore characters must be treated specially lest they
+underline the old text instead.
+@end table
+
+@node Cursor Visibility, Bell, Underlining, Capabilities
+@section Cursor Visibility
+@cindex visibility
+
+Some terminals have the ability to make the cursor invisible, or to enhance
+it. Enhancing the cursor is often done by programs that plan to use the
+cursor to indicate to the user a position of interest that may be anywhere
+on the screen---for example, the Emacs editor enhances the cursor on entry.
+Such programs should always restore the cursor to normal on exit.
+
+@table @samp
+@item vs
+@kindex vs
+String of commands to enhance the cursor.
+
+@item vi
+@kindex vi
+String of commands to make the cursor invisible.
+
+@item ve
+@kindex ve
+String of commands to return the cursor to normal.
+@end table
+
+If you define either @samp{vs} or @samp{vi}, you must also define @samp{ve}.
+
+@node Bell, Keypad, Cursor Visibility, Capabilities
+@section Bell
+@cindex bell
+@cindex visible bell
+
+Here we describe commands to make the terminal ask for the user to pay
+attention to it.
+
+@table @samp
+@item bl
+@kindex bl
+String of commands to cause the terminal to make an audible sound. If
+this capability is absent, the terminal has no way to make a suitable
+sound.
+
+@item vb
+@kindex vb
+String of commands to cause the screen to flash to attract attention
+(``visible bell''). If this capability is absent, the terminal has no
+way to do such a thing.
+@end table
+
+@node Keypad, Meta Key, Bell, Capabilities
+@section Keypad and Function Keys
+
+Many terminals have arrow and function keys that transmit specific
+character sequences to the computer. Since the precise sequences used
+depend on the terminal, termcap defines capabilities used to say what the
+sequences are. Unlike most termcap string-valued capabilities, these are
+not strings of commands to be sent to the terminal, rather strings that
+are received from the terminal.
+
+Programs that expect to use keypad keys should check, initially, for a
+@samp{ks} capability and send it, to make the keypad actually transmit.
+Such programs should also send the @samp{ke} string when exiting.
+
+@table @asis
+@item @samp{ks}
+@kindex ka@dots{}ku
+String of commands to make the function keys transmit. If this
+capability is not provided, but the others in this section are,
+programs may assume that the function keys always transmit.
+
+@item @samp{ke}
+String of commands to make the function keys work locally. This
+capability is provided only if @samp{ks} is.
+
+@item @samp{kl}
+String of input characters sent by typing the left-arrow key. If this
+capability is missing, you cannot expect the terminal to have a
+left-arrow key that transmits anything to the computer.
+
+@item @samp{kr}
+String of input characters sent by typing the right-arrow key.
+
+@item @samp{ku}
+String of input characters sent by typing the up-arrow key.
+
+@item @samp{kd}
+String of input characters sent by typing the down-arrow key.
+
+@item @samp{kh}
+String of input characters sent by typing the ``home-position'' key.
+
+@item @samp{K1} @dots{} @samp{K5}
+@kindex K1@dots{}K5
+Strings of input characters sent by the five other keys in a 3-by-3
+array that includes the arrow keys, if the keyboard has such a 3-by-3
+array. Note that one of these keys may be the ``home-position'' key,
+in which case one of these capabilities will have the same value as
+the @samp{kh} key.
+
+@item @samp{k0}
+String of input characters sent by function key 10 (or 0, if the terminal
+has one labeled 0).
+
+@item @samp{k1} @dots{} @samp{k9}
+@kindex k1@dots{}k9
+Strings of input characters sent by function keys 1 through 9,
+provided for those function keys that exist.
+
+@item @samp{kn}
+Number: the number of numbered function keys, if there are more than
+10.
+
+@item @samp{l0} @dots{} @samp{l9}
+@kindex l0@dots{}l9
+Strings which are the labels appearing on the keyboard on the keys
+described by the capabilities @samp{k0} @dots{} @samp{l9}. These
+capabilities should be left undefined if the labels are @samp{f0} or
+@samp{f10} and @samp{f1} @dots{} @samp{f9}.@refill
+
+@item @samp{kH}
+@kindex kA@dots{}kT
+String of input characters sent by the ``home down'' key, if there is
+one.
+
+@item @samp{kb}
+String of input characters sent by the ``backspace'' key, if there is
+one.
+
+@item @samp{ka}
+String of input characters sent by the ``clear all tabs'' key, if there
+is one.
+
+@item @samp{kt}
+String of input characters sent by the ``clear tab stop this column''
+key, if there is one.
+
+@item @samp{kC}
+String of input characters sent by the ``clear screen'' key, if there is
+one.
+
+@item @samp{kD}
+String of input characters sent by the ``delete character'' key, if
+there is one.
+
+@item @samp{kL}
+String of input characters sent by the ``delete line'' key, if there is
+one.
+
+@item @samp{kM}
+String of input characters sent by the ``exit insert mode'' key, if
+there is one.
+
+@item @samp{kE}
+String of input characters sent by the ``clear to end of line'' key, if
+there is one.
+
+@item @samp{kS}
+String of input characters sent by the ``clear to end of screen'' key,
+if there is one.
+
+@item @samp{kI}
+String of input characters sent by the ``insert character'' or ``enter
+insert mode'' key, if there is one.
+
+@item @samp{kA}
+String of input characters sent by the ``insert line'' key, if there is
+one.
+
+@item @samp{kN}
+String of input characters sent by the ``next page'' key, if there is
+one.
+
+@item @samp{kP}
+String of input characters sent by the ``previous page'' key, if there is
+one.
+
+@item @samp{kF}
+String of input characters sent by the ``scroll forward'' key, if there
+is one.
+
+@item @samp{kR}
+String of input characters sent by the ``scroll reverse'' key, if there
+is one.
+
+@item @samp{kT}
+String of input characters sent by the ``set tab stop in this column''
+key, if there is one.
+
+@item @samp{ko}
+String listing the other function keys the terminal has. This is a
+very obsolete way of describing the same information found in the
+@samp{kH} @dots{} @samp{kT} keys. The string contains a list of
+two-character termcap capability names, separated by commas. The
+meaning is that for each capability name listed, the terminal has a
+key which sends the string which is the value of that capability. For
+example, the value @samp{:ko=cl,ll,sf,sr:} says that the terminal has
+four function keys which mean ``clear screen'', ``home down'',
+``scroll forward'' and ``scroll reverse''.@refill
+@end table
+
+@node Meta Key, Initialization, Keypad, Capabilities
+@section Meta Key
+
+@cindex meta key
+A Meta key is a key on the keyboard that modifies each character you type
+by controlling the 0200 bit. This bit is on if and only if the Meta key is
+held down when the character is typed. Characters typed using the Meta key
+are called Meta characters. Emacs uses Meta characters as editing
+commands.
+
+@table @samp
+@item km
+@kindex km
+Flag whose presence means that the terminal has a Meta key.
+
+@item mm
+@kindex mm
+String of commands to enable the functioning of the Meta key.
+
+@item mo
+@kindex mo
+String of commands to disable the functioning of the Meta key.
+@end table
+
+If the terminal has @samp{km} but does not have @samp{mm} and @samp{mo}, it
+means that the Meta key always functions. If it has @samp{mm} and
+@samp{mo}, it means that the Meta key can be turned on or off. Send the
+@samp{mm} string to turn it on, and the @samp{mo} string to turn it off.
+I do not know why one would ever not want it to be on.
+
+@node Initialization, Pad Specs, Meta Key, Capabilities
+@section Initialization
+@cindex reset
+@cindex initialization
+@cindex tab stops
+
+@table @samp
+@item ti
+@kindex ti
+String of commands to put the terminal into whatever special modes are
+needed or appropriate for programs that move the cursor
+nonsequentially around the screen. Programs that use termcap to do
+full-screen display should output this string when they start up.
+
+@item te
+@kindex te
+String of commands to undo what is done by the @samp{ti} string.
+Programs that output the @samp{ti} string on entry should output this
+string when they exit.
+
+@item is
+@kindex is
+String of commands to initialize the terminal for each login session.
+
+@item if
+@kindex if
+String which is the name of a file containing the string of commands
+to initialize the terminal for each session of use. Normally @samp{is}
+and @samp{if} are not both used.
+
+@item i1
+@itemx i3
+@kindex i1
+@kindex i3
+Two more strings of commands to initialize the terminal for each login
+session. The @samp{i1} string (if defined) is output before @samp{is}
+or @samp{if}, and the @samp{i3} string (if defined) is output after.
+
+The reason for having three separate initialization strings is to make
+it easier to define a group of related terminal types with slightly
+different initializations. Define two or three of the strings in the
+basic type; then the other types can override one or two of the
+strings.
+
+@item rs
+@kindex rs
+String of commands to reset the terminal from any strange mode it may
+be in. Normally this includes the @samp{is} string (or other commands
+with the same effects) and more. What would go in the @samp{rs}
+string but not in the @samp{is} string are annoying or slow commands
+to bring the terminal back from strange modes that nobody would
+normally use.
+
+@item it
+@kindex it
+Numeric value, the initial spacing between hardware tab stop columns
+when the terminal is powered up. Programs to initialize the terminal
+can use this to decide whether there is a need to set the tab stops.
+If the initial width is 8, well and good; if it is not 8, then the
+tab stops should be set; if they cannot be set, the kernel is told
+to convert tabs to spaces, and other programs will observe this and do
+likewise.
+
+@item ct
+@kindex ct
+String of commands to clear all tab stops.
+
+@item st
+@kindex st
+String of commands to set tab stop at current cursor column on all
+lines.
+@end table
+
+@node Pad Specs, Status Line, Initialization, Capabilities
+@section Padding Capabilities
+@cindex padding
+
+There are two terminal capabilities that exist just to explain the proper
+way to obey the padding specifications in all the command string
+capabilities. One, @samp{pc}, must be obeyed by all termcap-using
+programs.
+
+@table @samp
+@item pb
+@kindex pb
+Numeric value, the lowest baud rate at which padding is actually
+needed. Programs may check this and refrain from doing any padding at
+lower speeds.
+
+@item pc
+@kindex pc
+String of commands for padding. The first character of this string is
+to be used as the pad character, instead of using null characters for
+padding. If @samp{pc} is not provided, use null characters. Every
+program that uses termcap must look up this capability and use it to
+set the variable @code{PC} that is used by @code{tputs}.
+@xref{Padding}.
+@end table
+
+Some termcap capabilities exist just to specify the amount of padding that
+the kernel should give to cursor motion commands used in ordinary
+sequential output.
+
+@table @samp
+@item dC
+@kindex dC
+Numeric value, the number of msec of padding needed for the
+carriage-return character.
+
+@item dN
+@kindex dN
+Numeric value, the number of msec of padding needed for the newline
+(linefeed) character.
+
+@item dB
+@kindex dB
+Numeric value, the number of msec of padding needed for the backspace
+character.
+
+@item dF
+@kindex dF
+Numeric value, the number of msec of padding needed for the formfeed
+character.
+
+@item dT
+@kindex dT
+Numeric value, the number of msec of padding needed for the tab
+character.
+@end table
+
+In some systems, the kernel uses the above capabilities; in other systems,
+the kernel uses the paddings specified in the string capabilities
+@samp{cr}, @samp{sf}, @samp{le}, @samp{ff} and @samp{ta}. Descriptions of
+terminals which require such padding should contain the @samp{dC} @dots{}
+@samp{dT} capabilities and also specify the appropriate padding in the
+corresponding string capabilities. Since no modern terminals require
+padding for ordinary sequential output, you probably won't need to do
+either of these things.
+
+@node Status Line, Half-Line, Pad Specs, Capabilities
+@section Status Line
+
+@cindex status line
+A @dfn{status line} is a line on the terminal that is not used for ordinary
+display output but instead used for a special message. The intended use is
+for a continuously updated description of what the user's program is doing,
+and that is where the name ``status line'' comes from, but in fact it could
+be used for anything. The distinguishing characteristic of a status line
+is that ordinary output to the terminal does not affect it; it changes only
+if the special status line commands of this section are used.
+
+@table @samp
+@item hs
+@kindex hs
+Flag whose presence means that the terminal has a status line. If a
+terminal description specifies that there is a status line, it must
+provide the @samp{ts} and @samp{fs} capabilities.
+
+@item ts
+@kindex ts
+String of commands to move the terminal cursor into the status line.
+Usually these commands must specifically record the old cursor
+position for the sake of the @samp{fs} string.
+
+@item fs
+@kindex fs
+String of commands to move the cursor back from the status line to its
+previous position (outside the status line).
+
+@item es
+@kindex es
+Flag whose presence means that other display commands work while
+writing the status line. In other words, one can clear parts of it,
+insert or delete characters, move the cursor within it using @samp{ch}
+if there is a @samp{ch} capability, enter and leave standout mode, and
+so on.
+
+@item ds
+@kindex ds
+String of commands to disable the display of the status line. This
+may be absent, if there is no way to disable the status line display.
+
+@item ws
+@kindex ws
+Numeric value, the width of the status line. If this capability is
+absent in a terminal that has a status line, it means the status line
+is the same width as the other lines.
+
+Note that the value of @samp{ws} is sometimes as small as 8.
+@end table
+
+@node Half-Line, Printer, Status Line, Capabilities
+@section Half-Line Motion
+
+Some terminals have commands for moving the cursor vertically by half-lines,
+useful for outputting subscripts and superscripts. Mostly it is hardcopy
+terminals that have such features.
+
+@table @samp
+@item hu
+@kindex hu
+String of commands to move the cursor up half a line. If the terminal
+is a display, it is your responsibility to avoid moving up past the
+top line; however, most likely the terminal that supports this is a
+hardcopy terminal and there is nothing to be concerned about.
+
+@item hd
+@kindex hd
+String of commands to move the cursor down half a line. If the
+terminal is a display, it is your responsibility to avoid moving down
+past the bottom line, etc.
+@end table
+
+@node Printer,, Half-Line, Capabilities
+@section Controlling Printers Attached to Terminals
+@cindex printer
+
+Some terminals have attached hardcopy printer ports. They may be able to
+copy the screen contents to the printer; they may also be able to redirect
+output to the printer. Termcap does not have anything to tell the program
+whether the redirected output appears also on the screen; it does on some
+terminals but not all.
+
+@table @samp
+@item ps
+@kindex ps
+String of commands to cause the contents of the screen to be printed.
+If it is absent, the screen contents cannot be printed.
+
+@item po
+@kindex po
+String of commands to redirect further output to the printer.
+
+@item pf
+@kindex pf
+String of commands to terminate redirection of output to the printer.
+This capability must be present in the description if @samp{po} is.
+
+@item pO
+@kindex pO
+String of commands to redirect output to the printer for next @var{n}
+characters of output, regardless of what they are. Redirection will
+end automatically after @var{n} characters of further output. Until
+then, nothing that is output can end redirection, not even the
+@samp{pf} string if there is one. The number @var{n} should not be
+more than 255.
+
+One use of this capability is to send non-text byte sequences (such as
+bit-maps) to the printer.
+@end table
+
+Most terminals with printers do not support all of @samp{ps}, @samp{po} and
+@samp{pO}; any one or two of them may be supported. To make a program that
+can send output to all kinds of printers, it is necessary to check for all
+three of these capabilities, choose the most convenient of the ones that
+are provided, and use it in its own appropriate fashion.
+
+@node Summary, Var Index, Capabilities, Top
+@chapter Summary of Capability Names
+
+Here are all the terminal capability names in alphabetical order
+with a brief description of each. For cross references to their definitions,
+see the index of capability names (@pxref{Cap Index}).
+
+@table @samp
+@item ae
+String to turn off alternate character set mode.
+@item al
+String to insert a blank line before the cursor.
+@item AL
+String to insert @var{n} blank lines before the cursor.
+@item am
+Flag: output to last column wraps cursor to next line.
+@item as
+String to turn on alternate character set mode.like.
+@item bc
+Very obsolete alternative name for the @samp{le} capability.
+@item bl
+String to sound the bell.
+@item bs
+Obsolete flag: ASCII backspace may be used for leftward motion.
+@item bt
+String to move the cursor left to the previous hardware tab stop column.
+@item bw
+Flag: @samp{le} at left margin wraps to end of previous line.
+@item CC
+String to change terminal's command character.
+@item cd
+String to clear the line the cursor is on, and following lines.
+@item ce
+String to clear from the cursor to the end of the line.
+@item ch
+String to position the cursor at column @var{c} in the same line.
+@item cl
+String to clear the entire screen and put cursor at upper left corner.
+@item cm
+String to position the cursor at line @var{l}, column @var{c}.
+@item CM
+String to position the cursor at line @var{l}, column
+@var{c}, relative to display memory.
+@item co
+Number: width of the screen.
+@item cr
+String to move cursor sideways to left margin.
+@item cs
+String to set the scroll region.
+@item cS
+Alternate form of string to set the scroll region.
+@item ct
+String to clear all tab stops.
+@item cv
+String to position the cursor at line @var{l} in the same column.
+@item da
+Flag: data scrolled off top of screen may be scrolled back.
+@item db
+Flag: data scrolled off bottom of screen may be scrolled back.
+@item dB
+Obsolete number: msec of padding needed for the backspace character.
+@item dc
+String to delete one character position at the cursor.
+@item dC
+Obsolete number: msec of padding needed for the carriage-return character.
+@item DC
+String to delete @var{n} characters starting at the cursor.
+@item dF
+Obsolete number: msec of padding needed for the formfeed character.
+@item dl
+String to delete the line the cursor is on.
+@item DL
+String to delete @var{n} lines starting with the cursor's line.
+@item dm
+String to enter delete mode.
+@item dN
+Obsolete number: msec of padding needed for the newline character.
+@item do
+String to move the cursor vertically down one line.
+@item DO
+String to move cursor vertically down @var{n} lines.
+@item ds
+String to disable the display of the status line.
+@item dT
+Obsolete number: msec of padding needed for the tab character.
+@item ec
+String of commands to clear @var{n} characters at cursor.
+@item ed
+String to exit delete mode.
+@item ei
+String to leave insert mode.
+@item eo
+Flag: output of a space can erase an overstrike.
+@item es
+Flag: other display commands work while writing the status line.
+@item ff
+String to advance to the next page, for a hardcopy terminal.
+@item fs
+String to move the cursor back from the status line to its
+previous position (outside the status line).
+@item gn
+Flag: this terminal type is generic, not real.
+@item hc
+Flag: hardcopy terminal.
+@item hd
+String to move the cursor down half a line.
+@item ho
+String to position cursor at upper left corner.
+@item hs
+Flag: the terminal has a status line.
+@item hu
+String to move the cursor up half a line.
+@item hz
+Flag: terminal cannot accept @samp{~} as output.
+@item i1
+String to initialize the terminal for each login session.
+@item i3
+String to initialize the terminal for each login session.
+@item ic
+String to insert one character position at the cursor.
+@item IC
+String to insert @var{n} character positions at the cursor.
+@item if
+String naming a file of commands to initialize the terminal.
+@item im
+String to enter insert mode.
+@item in
+Flag: outputting a space is different from moving over empty positions.
+@item ip
+String to output following an inserted character in insert mode.
+@item is
+String to initialize the terminal for each login session.
+@item it
+Number: initial spacing between hardware tab stop columns.
+@item k0
+String of input sent by function key 0 or 10.
+@item k1 @dots{} k9
+Strings of input sent by function keys 1 through 9.
+@item K1 @dots{} K5
+Strings sent by the five other keys in 3-by-3 array with arrows.
+@item ka
+String of input sent by the ``clear all tabs'' key.
+@item kA
+String of input sent by the ``insert line'' key.
+@item kb
+String of input sent by the ``backspace'' key.
+@item kC
+String of input sent by the ``clear screen'' key.
+@item kd
+String of input sent by typing the down-arrow key.
+@item kD
+String of input sent by the ``delete character'' key.
+@item ke
+String to make the function keys work locally.
+@item kE
+String of input sent by the ``clear to end of line'' key.
+@item kF
+String of input sent by the ``scroll forward'' key.
+@item kh
+String of input sent by typing the ``home-position'' key.
+@item kH
+String of input sent by the ``home down'' key.
+@item kI
+String of input sent by the ``insert character'' or ``enter
+insert mode'' key.
+@item kl
+String of input sent by typing the left-arrow key.
+@item kL
+String of input sent by the ``delete line'' key.
+@item km
+Flag: the terminal has a Meta key.
+@item kM
+String of input sent by the ``exit insert mode'' key.
+@item kn
+Numeric value, the number of numbered function keys.
+@item kN
+String of input sent by the ``next page'' key.
+@item ko
+Very obsolete string listing the terminal's named function keys.
+@item kP
+String of input sent by the ``previous page'' key.
+@item kr
+String of input sent by typing the right-arrow key.
+@item kR
+String of input sent by the ``scroll reverse'' key.
+@item ks
+String to make the function keys transmit.
+@item kS
+String of input sent by the ``clear to end of screen'' key.
+@item kt
+String of input sent by the ``clear tab stop this column'' key.
+@item kT
+String of input sent by the ``set tab stop in this column'' key.
+@item ku
+String of input sent by typing the up-arrow key.
+@item l0
+String on keyboard labelling function key 0 or 10.
+@item l1 @dots{} l9
+Strings on keyboard labelling function keys 1 through 9.
+@item le
+String to move the cursor left one column.
+@item LE
+String to move cursor left @var{n} columns.
+@item li
+Number: height of the screen.
+@item ll
+String to position cursor at lower left corner.
+@item lm
+Number: lines of display memory.
+@item mb
+String to enter blinking mode.
+@item md
+String to enter double-bright mode.
+@item me
+String to turn off all appearance modes
+@item mh
+String to enter half-bright mode.
+@item mi
+Flag: cursor motion in insert mode is safe.
+@item mk
+String to enter invisible mode.
+@item mm
+String to enable the functioning of the Meta key.
+@item mo
+String to disable the functioning of the Meta key.
+@item mp
+String to enter protected mode.
+@item mr
+String to enter reverse-video mode.
+@item ms
+Flag: cursor motion in standout mode is safe.
+@item nc
+Obsolete flag: do not use ASCII carriage-return on this terminal.
+@item nd
+String to move the cursor right one column.
+@item nl
+Obsolete alternative name for the @samp{do} and @samp{sf} capabilities.
+@item ns
+Flag: the terminal does not normally scroll for sequential output.
+@item nw
+String to move to start of next line, possibly clearing rest of old line.
+@item os
+Flag: terminal can overstrike.
+@item pb
+Number: the lowest baud rate at which padding is actually needed.
+@item pc
+String containing character for padding.
+@item pf
+String to terminate redirection of output to the printer.
+@item po
+String to redirect further output to the printer.
+@item pO
+String to redirect @var{n} characters ofoutput to the printer.
+@item ps
+String to print the screen on the attached printer.
+@item rc
+String to move to last saved cursor position.
+@item RI
+String to move cursor right @var{n} columns.
+@item rp
+String to output character @var{c} repeated @var{n} times.
+@item rs
+String to reset the terminal from any strange modes.
+@item sa
+String to turn on an arbitrary combination of appearance modes.
+@item sc
+String to save the current cursor position.
+@item se
+String to leave standout mode.
+@item sf
+String to scroll the screen one line up.
+@item SF
+String to scroll the screen @var{n} lines up.
+@item sg
+Number: width of magic standout cookie. Absent if magic cookies are
+not used.
+@item so
+String to enter standout mode.
+@item sr
+String to scroll the screen one line down.
+@item SR
+String to scroll the screen @var{n} line down.
+@item st
+String to set tab stop at current cursor column on all lines.
+programs.
+@item ta
+String to move the cursor right to the next hardware tab stop column.
+@item te
+String to return terminal to settings for sequential output.
+@item ti
+String to initialize terminal for random cursor motion.
+@item ts
+String to move the terminal cursor into the status line.
+@item uc
+String to underline one character and move cursor right.
+@item ue
+String to turn off underline mode
+@item ug
+Number: width of underlining magic cookie. Absent if underlining
+doesn't use magic cookies.
+@item ul
+Flag: underline by overstriking with an underscore.
+@item up
+String to move the cursor vertically up one line.
+@item UP
+String to move cursor vertically up @var{n} lines.
+@item us
+String to turn on underline mode
+@item vb
+String to make the screen flash.
+@item ve
+String to return the cursor to normal.
+@item vi
+String to make the cursor invisible.
+@item vs
+String to enhance the cursor.
+@item wi
+String to set the terminal output screen window.
+@item ws
+Number: the width of the status line.
+@item xb
+Flag: superbee terminal.
+@item xn
+Flag: cursor wraps in a strange way.
+@item xs
+Flag: clearing a line is the only way to clear the appearance modes of
+positions in that line (or, only way to remove magic cookies on that
+line).
+@item xt
+Flag: Teleray 1061; several strange characteristics.
+@end table
+
+@node Var Index, Cap Index, Summary, Top
+@unnumbered Variable and Function Index
+
+@printindex fn
+
+@node Cap Index, Index, Var Index, Top
+@unnumbered Capability Index
+
+@printindex ky
+
+@node Index,, Cap Index, Top
+@unnumbered Concept Index
+
+@printindex cp
+
+@contents
+@bye
diff --git a/man/texindex.c b/man/texindex.c
new file mode 100644
index 00000000000..c6696e77ba8
--- /dev/null
+++ b/man/texindex.c
@@ -0,0 +1,1594 @@
+/* Prepare Tex index dribble output into an actual index.
+ Copyright (C) 1987 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ In other words, you are welcome to use, share and improve this program.
+ You are forbidden to forbid anyone else to use, share and improve
+ what you give them. Help stamp out software-hoarding! */
+
+
+#include <stdio.h>
+#include <ctype.h>
+
+#ifdef VMS
+#include <file.h>
+
+#define EXIT_SUCCESS ((1 << 28) | 1)
+#define EXIT_FATAL ((1 << 28) | 4)
+#define unlink delete
+#define tell(fd) lseek(fd, 0L, 1)
+#else
+#include <sys/types.h>
+#include <sys/fcntl.h>
+#include <sys/file.h>
+
+#define EXIT_SUCCESS 0
+#define EXIT_FATAL 1
+#endif
+
+
+#ifndef L_XTND
+#define L_XTND 2
+#endif
+
+/* When sorting in core, this structure describes one line
+ and the position and length of its first keyfield. */
+
+struct lineinfo
+ {
+ char *text; /* The actual text of the line */
+ union
+ { /* The start of the key (for textual comparison) */
+ char *text;
+ long number; /* or the numeric value (for numeric comparison) */
+ } key;
+ long keylen; /* Length of key field */
+ };
+
+/* This structure describes a field to use as a sort key */
+
+struct keyfield
+ {
+ int startwords; /* # words to skip */
+ int startchars; /* and # additional chars to skip, to start of field */
+ int endwords; /* similar, from beg (or end) of line, to find end of field */
+ int endchars;
+ char ignore_blanks; /* Ignore spaces and tabs within the field */
+ char fold_case; /* Convert upper case to lower before comparing */
+ char reverse; /* Compare in reverse order */
+ char numeric; /* Parse text as an integer and compare the integers */
+ char positional; /* Sort according to position within the file */
+ char braced; /* Count balanced-braced groupings as fields */
+ };
+
+/* Vector of keyfields to use */
+
+struct keyfield keyfields[3];
+
+/* Number of keyfields stored in that vector. */
+
+int num_keyfields = 3;
+
+/* Vector of input file names, terminated with a zero (null pointer) */
+
+char **infiles;
+
+/* Vector of corresponding output file names, or zero meaning default it */
+
+char **outfiles;
+
+/* Length of `infiles' */
+
+int num_infiles;
+
+/* Pointer to the array of pointers to lines being sorted */
+
+char **linearray;
+
+/* The allocated length of `linearray'. */
+
+long lines;
+
+/* Directory to use for temporary files. On Unix, it ends with a slash. */
+
+char *tempdir;
+
+/* Start of filename to use for temporary files. */
+
+char *tempbase;
+
+/* Number of last temporary file. */
+
+int tempcount;
+
+/* Number of last temporary file already deleted.
+ Temporary files are deleted by `flush_tempfiles' in order of creation. */
+
+int last_deleted_tempcount;
+
+/* During in-core sort, this points to the base of the data block
+ which contains all the lines of data. */
+
+char *text_base;
+
+/* Additional command switches */
+
+int keep_tempfiles; /* Nonzero means do not delete tempfiles -- for debugging */
+
+/* Forward declarations of functions in this file */
+
+void decode_command ();
+void sort_in_core ();
+void sort_offline ();
+char **parsefile ();
+char *find_field ();
+char *find_pos ();
+long find_value ();
+char *find_braced_pos ();
+char *find_braced_end ();
+void writelines ();
+int compare_full ();
+long readline ();
+int merge_files ();
+int merge_direct ();
+char *concat ();
+char *maketempname ();
+void flush_tempfiles ();
+char *tempcopy ();
+
+extern char *mktemp ();
+
+#define MAX_IN_CORE_SORT 500000
+
+int
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ int i;
+
+ tempcount = 0;
+ last_deleted_tempcount = 0;
+
+ /* Describe the kind of sorting to do. */
+ /* The first keyfield uses the first braced field and folds case */
+ keyfields[0].braced = 1;
+ keyfields[0].fold_case = 1;
+ keyfields[0].endwords = -1;
+ keyfields[0].endchars = -1;
+ /* The second keyfield uses the second braced field, numerically */
+ keyfields[1].braced = 1;
+ keyfields[1].numeric = 1;
+ keyfields[1].startwords = 1;
+ keyfields[1].endwords = -1;
+ keyfields[1].endchars = -1;
+ /* The third keyfield (which is ignored while discarding duplicates)
+ compares the whole line */
+ keyfields[2].endwords = -1;
+ keyfields[2].endchars = -1;
+
+ decode_command (argc, argv);
+
+ tempbase = mktemp (concat ("txiXXXXXX", "", ""));
+
+ /* Process input files completely, one by one. */
+
+ for (i = 0; i < num_infiles; i++)
+ {
+ int desc;
+ long ptr;
+ char *outfile;
+ char *p;
+
+ desc = open (infiles[i], 0, 0);
+ if (desc < 0) pfatal_with_name (infiles[i]);
+ lseek (desc, 0, L_XTND);
+ ptr = tell (desc);
+ close (desc);
+
+ outfile = outfiles[i];
+ if (!outfile)
+ {
+ outfile = concat (infiles[i], "s", "");
+ }
+
+ if (ptr < MAX_IN_CORE_SORT)
+ /* Sort a small amount of data */
+ sort_in_core (infiles[i], ptr, outfile);
+ else
+ sort_offline (infiles[i], ptr, outfile);
+ }
+
+ flush_tempfiles (tempcount);
+ exit (EXIT_SUCCESS);
+}
+
+/* This page decodes the command line arguments to set the parameter variables
+ and set up the vector of keyfields and the vector of input files */
+
+void
+decode_command (argc, argv)
+ int argc;
+ char **argv;
+{
+ int i;
+ char **ip;
+ char **op;
+
+ /* Store default values into parameter variables */
+
+#ifdef VMS
+ tempdir = "sys$scratch:";
+#else
+ tempdir = "/tmp/";
+#endif
+
+ keep_tempfiles = 0;
+
+ /* Allocate argc input files, which must be enough. */
+
+ infiles = (char **) xmalloc (argc * sizeof (char *));
+ outfiles = (char **) xmalloc (argc * sizeof (char *));
+ ip = infiles;
+ op = outfiles;
+
+ /* First find all switches that control the default kind-of-sort */
+
+ for (i = 1; i < argc; i++)
+ {
+ int tem = classify_arg (argv[i]);
+ char c;
+ char *p;
+
+ if (tem <= 0)
+ {
+ *ip++ = argv[i];
+ *op++ = 0;
+ continue;
+ }
+ if (tem > 1)
+ {
+ if (i + 1 == argc)
+ fatal ("switch %s given with no argument following it", argv[i]);
+ else if (!strcmp (argv[i], "-T"))
+ tempdir = argv[i + 1];
+ else if (!strcmp (argv[i], "-o"))
+ *(op - 1) = argv[i + 1];
+ i += tem - 1;
+ continue;
+ }
+
+ p = &argv[i][1];
+ while (c = *p++)
+ switch (c)
+ {
+ case 'k':
+ keep_tempfiles = 1;
+ break;
+
+ default:
+ fatal ("invalid command switch %c", c);
+ }
+ switchdone: ;
+ }
+
+ /* Record number of keyfields, terminate list of filenames */
+
+ num_infiles = ip - infiles;
+ *ip = 0;
+}
+
+/* Return 0 for an argument that is not a switch;
+ for a switch, return 1 plus the number of following arguments that the switch swallows.
+*/
+
+int
+classify_arg (arg)
+ char *arg;
+{
+ if (!strcmp (arg, "-T") || !strcmp (arg, "-o"))
+ return 2;
+ if (arg[0] == '-')
+ return 1;
+ return 0;
+}
+
+/* Create a name for a temporary file */
+
+char *
+maketempname (count)
+ int count;
+{
+ char tempsuffix[10];
+ sprintf (tempsuffix, "%d", count);
+ return concat (tempdir, tempbase, tempsuffix);
+}
+
+/* Delete all temporary files up to the specified count */
+
+void
+flush_tempfiles (to_count)
+ int to_count;
+{
+ if (keep_tempfiles) return;
+ while (last_deleted_tempcount < to_count)
+ unlink (maketempname (++last_deleted_tempcount));
+}
+
+/* Copy an input file into a temporary file, and return the temporary file name */
+
+#define BUFSIZE 1024
+
+char *
+tempcopy (idesc)
+ int idesc;
+{
+ char *outfile = maketempname (++tempcount);
+ int odesc;
+ char buffer[BUFSIZE];
+
+ odesc = open (outfile, O_WRONLY | O_CREAT, 0666);
+
+ if (odesc < 0) pfatal_with_name (outfile);
+
+ while (1)
+ {
+ int nread = read (idesc, buffer, BUFSIZE);
+ write (odesc, buffer, nread);
+ if (!nread) break;
+ }
+
+ close (odesc);
+
+ return outfile;
+}
+
+/* Compare two lines, provided as pointers to pointers to text,
+ according to the specified set of keyfields */
+
+int
+compare_full (line1, line2)
+ char **line1, **line2;
+{
+ int i;
+
+ /* Compare using the first keyfield;
+ if that does not distinguish the lines, try the second keyfield; and so on. */
+
+ for (i = 0; i < num_keyfields; i++)
+ {
+ long length1, length2;
+ char *start1 = find_field (&keyfields[i], *line1, &length1);
+ char *start2 = find_field (&keyfields[i], *line2, &length2);
+ int tem = compare_field (&keyfields[i], start1, length1, *line1 - text_base,
+ start2, length2, *line2 - text_base);
+ if (tem)
+ {
+ if (keyfields[i].reverse)
+ return - tem;
+ return tem;
+ }
+ }
+
+ return 0; /* Lines match exactly */
+}
+
+/* Compare two lines described by structures
+ in which the first keyfield is identified in advance.
+ For positional sorting, assumes that the order of the lines in core
+ reflects their nominal order. */
+
+int
+compare_prepared (line1, line2)
+ struct lineinfo *line1, *line2;
+{
+ int i;
+ int tem;
+ char *text1, *text2;
+
+ /* Compare using the first keyfield, which has been found for us already */
+ if (keyfields->positional)
+ {
+ if (line1->text - text_base > line2->text - text_base)
+ tem = 1;
+ else
+ tem = -1;
+ }
+ else if (keyfields->numeric)
+ tem = line1->key.number - line2->key.number;
+ else
+ tem = compare_field (keyfields, line1->key.text, line1->keylen, 0, line2->key.text, line2->keylen, 0);
+ if (tem)
+ {
+ if (keyfields->reverse)
+ return - tem;
+ return tem;
+ }
+
+ text1 = line1->text;
+ text2 = line2->text;
+
+ /* Compare using the second keyfield;
+ if that does not distinguish the lines, try the third keyfield; and so on. */
+
+ for (i = 1; i < num_keyfields; i++)
+ {
+ long length1, length2;
+ char *start1 = find_field (&keyfields[i], text1, &length1);
+ char *start2 = find_field (&keyfields[i], text2, &length2);
+ int tem = compare_field (&keyfields[i], start1, length1, text1 - text_base,
+ start2, length2, text2 - text_base);
+ if (tem)
+ {
+ if (keyfields[i].reverse)
+ return - tem;
+ return tem;
+ }
+ }
+
+ return 0; /* Lines match exactly */
+}
+
+/* Like compare_full but more general.
+ You can pass any strings, and you can say how many keyfields to use.
+ `pos1' and `pos2' should indicate the nominal positional ordering of
+ the two lines in the input. */
+
+int
+compare_general (str1, str2, pos1, pos2, use_keyfields)
+ char *str1, *str2;
+ long pos1, pos2;
+ int use_keyfields;
+{
+ int i;
+
+ /* Compare using the first keyfield;
+ if that does not distinguish the lines, try the second keyfield; and so on. */
+
+ for (i = 0; i < use_keyfields; i++)
+ {
+ long length1, length2;
+ char *start1 = find_field (&keyfields[i], str1, &length1);
+ char *start2 = find_field (&keyfields[i], str2, &length2);
+ int tem = compare_field (&keyfields[i], start1, length1, pos1, start2, length2, pos2);
+ if (tem)
+ {
+ if (keyfields[i].reverse)
+ return - tem;
+ return tem;
+ }
+ }
+
+ return 0; /* Lines match exactly */
+}
+
+/* Find the start and length of a field in `str' according to `keyfield'.
+ A pointer to the starting character is returned, and the length
+ is stored into the int that `lengthptr' points to. */
+
+char *
+find_field (keyfield, str, lengthptr)
+ struct keyfield *keyfield;
+ char *str;
+ long *lengthptr;
+{
+ char *start;
+ char *end;
+ char *(*fun) ();
+
+ if (keyfield->braced) fun = find_braced_pos;
+ else fun = find_pos;
+
+ start = ( *fun )(str, keyfield->startwords, keyfield->startchars,
+ keyfield->ignore_blanks);
+ if (keyfield->endwords < 0)
+ {
+ if (keyfield->braced)
+ end = find_braced_end (start);
+ else
+ {
+ end = start;
+ while (*end && *end != '\n') end++;
+ }
+ }
+ else
+ {
+ end = ( *fun )(str, keyfield->endwords, keyfield->endchars, 0);
+ if (end - str < start - str) end = start;
+ }
+ *lengthptr = end - start;
+ return start;
+}
+
+/* Find a pointer to a specified place within `str',
+ skipping (from the beginning) `words' words and then `chars' chars.
+ If `ignore_blanks' is nonzero, we skip all blanks
+ after finding the specified word. */
+
+char *
+find_pos (str, words, chars, ignore_blanks)
+ char *str;
+ int words, chars;
+ int ignore_blanks;
+{
+ int i;
+ char *p = str;
+
+ for (i = 0; i < words; i++)
+ {
+ char c;
+ /* Find next bunch of nonblanks and skip them. */
+ while ((c = *p) == ' ' || c == '\t') p++;
+ while ((c = *p) && c != '\n' && !(c == ' ' || c == '\t')) p++;
+ if (!*p || *p == '\n') return p;
+ }
+
+ while (*p == ' ' || *p == '\t') p++;
+
+ for (i = 0; i < chars; i++)
+ {
+ if (!*p || *p == '\n') break;
+ p++;
+ }
+ return p;
+}
+
+/* Like find_pos but assumes that each field is surrounded by braces
+ and that braces within fields are balanced. */
+
+char *
+find_braced_pos (str, words, chars, ignore_blanks)
+ char *str;
+ int words, chars;
+ int ignore_blanks;
+{
+ int i;
+ int bracelevel;
+ char *p = str;
+ char c;
+
+ for (i = 0; i < words; i++)
+ {
+ bracelevel = 1;
+ while ((c = *p++) != '{' && c != '\n' && c);
+ if (c != '{')
+ return p - 1;
+ while (bracelevel)
+ {
+ c = *p++;
+ if (c == '{') bracelevel++;
+ if (c == '}') bracelevel--;
+ if (c == '\\') c = *p++; /* \ quotes braces and \ */
+ if (c == 0 || c == '\n') return p-1;
+ }
+ }
+
+ while ((c = *p++) != '{' && c != '\n' && c);
+
+ if (c != '{')
+ return p-1;
+
+ if (ignore_blanks)
+ while ((c = *p) == ' ' || c == '\t') p++;
+
+ for (i = 0; i < chars; i++)
+ {
+ if (!*p || *p == '\n') break;
+ p++;
+ }
+ return p;
+}
+
+/* Find the end of the balanced-brace field which starts at `str'.
+ The position returned is just before the closing brace. */
+
+char *
+find_braced_end (str)
+ char *str;
+{
+ int bracelevel;
+ char *p = str;
+ char c;
+
+ bracelevel = 1;
+ while (bracelevel)
+ {
+ c = *p++;
+ if (c == '{') bracelevel++;
+ if (c == '}') bracelevel--;
+ if (c == '\\') c = *p++;
+ if (c == 0 || c == '\n') return p-1;
+ }
+ return p - 1;
+}
+
+long
+find_value (start, length)
+ char *start;
+ long length;
+{
+ while (length != 0L) {
+ if (isdigit(*start))
+ return atol(start);
+ length--;
+ start++;
+ }
+ return 0l;
+}
+
+/* Vector used to translate characters for comparison.
+ This is how we make all alphanumerics follow all else,
+ and ignore case in the first sorting. */
+int char_order[256];
+
+init_char_order ()
+{
+ int i;
+ for (i = 1; i < 256; i++)
+ char_order[i] = i;
+
+ for (i = '0'; i <= '9'; i++)
+ char_order[i] += 512;
+
+ for (i = 'a'; i <= 'z'; i++) {
+ char_order[i] = 512 + i;
+ char_order[i + 'A' - 'a'] = 512 + i;
+ }
+}
+
+/* Compare two fields (each specified as a start pointer and a character count)
+ according to `keyfield'. The sign of the value reports the relation between the fields */
+
+int
+compare_field (keyfield, start1, length1, pos1, start2, length2, pos2)
+ struct keyfield *keyfield;
+ char *start1;
+ long length1;
+ long pos1;
+ char *start2;
+ long length2;
+ long pos2;
+{
+ if (keyfields->positional)
+ {
+ if (pos1 > pos2)
+ return 1;
+ else
+ return -1;
+ }
+ if (keyfield->numeric)
+ {
+ long value = find_value (start1, length1) - find_value (start2, length2);
+ if (value > 0) return 1;
+ if (value < 0) return -1;
+ return 0;
+ }
+ else
+ {
+ char *p1 = start1;
+ char *p2 = start2;
+ char *e1 = start1 + length1;
+ char *e2 = start2 + length2;
+
+ int fold_case = keyfield->fold_case;
+
+ while (1)
+ {
+ int c1, c2;
+
+ if (p1 == e1) c1 = 0;
+ else c1 = *p1++;
+ if (p2 == e2) c2 = 0;
+ else c2 = *p2++;
+
+ if (char_order[c1] != char_order[c2])
+ return char_order[c1] - char_order[c2];
+ if (!c1) break;
+ }
+
+ /* Strings are equal except possibly for case. */
+ p1 = start1;
+ p2 = start2;
+ while (1)
+ {
+ int c1, c2;
+
+ if (p1 == e1) c1 = 0;
+ else c1 = *p1++;
+ if (p2 == e2) c2 = 0;
+ else c2 = *p2++;
+
+ if (c1 != c2)
+ /* Reverse sign here so upper case comes out last. */
+ return c2 - c1;
+ if (!c1) break;
+ }
+
+ return 0;
+ }
+}
+
+/* A `struct linebuffer' is a structure which holds a line of text.
+ `readline' reads a line from a stream into a linebuffer
+ and works regardless of the length of the line. */
+
+struct linebuffer
+ {
+ long size;
+ char *buffer;
+ };
+
+/* Initialize a linebuffer for use */
+
+void
+initbuffer (linebuffer)
+ struct linebuffer *linebuffer;
+{
+ linebuffer->size = 200;
+ linebuffer->buffer = (char *) xmalloc (200);
+}
+
+/* Read a line of text from `stream' into `linebuffer'.
+ Return the length of the line. */
+
+long
+readline (linebuffer, stream)
+ struct linebuffer *linebuffer;
+ FILE *stream;
+{
+ char *buffer = linebuffer->buffer;
+ char *p = linebuffer->buffer;
+ char *end = p + linebuffer->size;
+
+ while (1)
+ {
+ int c = getc (stream);
+ if (p == end)
+ {
+ buffer = (char *) xrealloc (buffer, linebuffer->size *= 2);
+ p += buffer - linebuffer->buffer;
+ end += buffer - linebuffer->buffer;
+ linebuffer->buffer = buffer;
+ }
+ if (c < 0 || c == '\n')
+ {
+ *p = 0;
+ break;
+ }
+ *p++ = c;
+ }
+
+ return p - buffer;
+}
+
+/* Sort an input file too big to sort in core. */
+
+void
+sort_offline (infile, nfiles, total, outfile)
+ char *infile;
+ long total;
+ char *outfile;
+{
+ int ntemps = 2 * (total + MAX_IN_CORE_SORT - 1) / MAX_IN_CORE_SORT; /* More than enough */
+ char **tempfiles = (char **) xmalloc (ntemps * sizeof (char *));
+ FILE *istream = fopen (infile, "r");
+ int i;
+ struct linebuffer lb;
+ long linelength;
+ int failure = 0;
+
+ initbuffer (&lb);
+
+ /* Read in one line of input data. */
+
+ linelength = readline (&lb, istream);
+
+ if (lb.buffer[0] != '\\')
+ {
+ error ("%s: not a texinfo index file", infile);
+ return;
+ }
+
+ /* Split up the input into `ntemps' temporary files, or maybe fewer,
+ and put the new files' names into `tempfiles' */
+
+ for (i = 0; i < ntemps; i++)
+ {
+ char *outname = maketempname (++tempcount);
+ FILE *ostream = fopen (outname, "w");
+ long tempsize = 0;
+
+ if (!ostream) pfatal_with_name (outname);
+ tempfiles[i] = outname;
+
+ /* Copy lines into this temp file as long as it does not make file "too big"
+ or until there are no more lines. */
+
+ while (tempsize + linelength + 1 <= MAX_IN_CORE_SORT)
+ {
+ tempsize += linelength + 1;
+ fputs (lb.buffer, ostream);
+ putc ('\n', ostream);
+
+ /* Read another line of input data. */
+
+ linelength = readline (&lb, istream);
+ if (!linelength && feof (istream)) break;
+
+ if (lb.buffer[0] != '\\')
+ {
+ error ("%s: not a texinfo index file", infile);
+ failure = 1;
+ goto fail;
+ }
+ }
+ fclose (ostream);
+ if (feof (istream)) break;
+ }
+
+ free (lb.buffer);
+
+ fail:
+ /* Record number of temp files we actually needed. */
+
+ ntemps = i;
+
+ /* Sort each tempfile into another tempfile.
+ Delete the first set of tempfiles and put the names of the second into `tempfiles' */
+
+ for (i = 0; i < ntemps; i++)
+ {
+ char *newtemp = maketempname (++tempcount);
+ sort_in_core (&tempfiles[i], MAX_IN_CORE_SORT, newtemp);
+ if (!keep_tempfiles)
+ unlink (tempfiles[i]);
+ tempfiles[i] = newtemp;
+ }
+
+ if (failure)
+ return;
+
+ /* Merge the tempfiles together and indexify */
+
+ merge_files (tempfiles, ntemps, outfile);
+}
+
+/* Sort `infile', whose size is `total',
+ assuming that is small enough to be done in-core,
+ then indexify it and send the output to `outfile' (or to stdout). */
+
+void
+sort_in_core (infile, total, outfile)
+ char *infile;
+ long total;
+ char *outfile;
+{
+ char **nextline;
+ char *data = (char *) xmalloc (total + 1);
+ char *file_data;
+ long file_size;
+ int i;
+ FILE *ostream = stdout;
+ struct lineinfo *lineinfo;
+
+ /* Read the contents of the file into the moby array `data' */
+
+ int desc = open (infile, 0, 0);
+
+ if (desc < 0)
+ fatal ("failure reopening %s", infile);
+ for (file_size = 0; ; )
+ {
+ if ((i = read (desc, data + file_size, total - file_size)) <= 0)
+ break;
+ file_size += i;
+ }
+ file_data = data;
+ data[file_size] = 0;
+
+ close (desc);
+
+ if (file_size > 0 && data[0] != '\\')
+ {
+ error ("%s: not a texinfo index file", infile);
+ return;
+ }
+
+ init_char_order ();
+
+ /* Sort routines want to know this address */
+
+ text_base = data;
+
+ /* Create the array of pointers to lines, with a default size frequently enough. */
+
+ lines = total / 50;
+ if (!lines) lines = 2;
+ linearray = (char **) xmalloc (lines * sizeof (char *));
+
+ /* `nextline' points to the next free slot in this array.
+ `lines' is the allocated size. */
+
+ nextline = linearray;
+
+ /* Parse the input file's data, and make entries for the lines. */
+
+ nextline = parsefile (infile, nextline, file_data, file_size);
+ if (nextline == 0)
+ {
+ error ("%s: not a texinfo index file", infile);
+ return;
+ }
+
+ /* Sort the lines */
+
+ /* If we have enough space, find the first keyfield of each line in advance.
+ Make a `struct lineinfo' for each line, which records the keyfield
+ as well as the line, and sort them. */
+
+ lineinfo = (struct lineinfo *) malloc ((nextline - linearray) * sizeof (struct lineinfo));
+
+ if (lineinfo)
+ {
+ struct lineinfo *lp;
+ char **p;
+
+ for (lp = lineinfo, p = linearray; p != nextline; lp++, p++)
+ {
+ lp->text = *p;
+ lp->key.text = find_field (keyfields, *p, &lp->keylen);
+ if (keyfields->numeric)
+ lp->key.number = find_value (lp->key.text, lp->keylen);
+ }
+
+ qsort (lineinfo, nextline - linearray, sizeof (struct lineinfo), compare_prepared);
+
+ for (lp = lineinfo, p = linearray; p != nextline; lp++, p++)
+ *p = lp->text;
+
+ free (lineinfo);
+ }
+ else
+ qsort (linearray, nextline - linearray, sizeof (char *), compare_full);
+
+ /* Open the output file */
+
+ if (outfile)
+ {
+ ostream = fopen (outfile, "w");
+ if (!ostream)
+ pfatal_with_name (outfile);
+ }
+
+ writelines (linearray, nextline - linearray, ostream);
+ if (outfile) fclose (ostream);
+
+ free (linearray);
+ free (data);
+}
+
+/* Parse an input string in core into lines.
+ DATA is the input string, and SIZE is its length.
+ Data goes in LINEARRAY starting at NEXTLINE.
+ The value returned is the first entry in LINEARRAY still unused.
+ Value 0 means input file contents are invalid. */
+
+char **
+parsefile (filename, nextline, data, size)
+ char *filename;
+ char **nextline;
+ char *data;
+ long size;
+{
+ char *p, *end;
+ char **line = nextline;
+
+ p = data;
+ end = p + size;
+ *end = 0;
+
+ while (p != end)
+ {
+ if (p[0] != '\\')
+ return 0;
+
+ *line = p;
+ while (*p && *p != '\n') p++;
+ if (p != end) p++;
+
+ line++;
+ if (line == linearray + lines)
+ {
+ char **old = linearray;
+ linearray = (char **) xrealloc (linearray, sizeof (char *) * (lines *= 4));
+ line += linearray - old;
+ }
+ }
+
+ return line;
+}
+
+/* Indexification is a filter applied to the sorted lines
+ as they are being written to the output file.
+ Multiple entries for the same name, with different page numbers,
+ get combined into a single entry with multiple page numbers.
+ The first braced field, which is used for sorting, is discarded.
+ However, its first character is examined, folded to lower case,
+ and if it is different from that in the previous line fed to us
+ a \initial line is written with one argument, the new initial.
+
+ If an entry has four braced fields, then the second and third
+ constitute primary and secondary names.
+ In this case, each change of primary name
+ generates a \primary line which contains only the primary name,
+ and in between these are \secondary lines which contain
+ just a secondary name and page numbers.
+*/
+
+/* The last primary name we wrote a \primary entry for.
+ If only one level of indexing is being done, this is the last name seen */
+char *lastprimary;
+int lastprimarylength; /* Length of storage allocated for lastprimary */
+
+/* Similar, for the secondary name. */
+char *lastsecondary;
+int lastsecondarylength;
+
+/* Zero if we are not in the middle of writing an entry.
+ One if we have written the beginning of an entry but have not
+ yet written any page numbers into it.
+ Greater than one if we have written the beginning of an entry
+ plus at least one page number. */
+int pending;
+
+/* The initial (for sorting purposes) of the last primary entry written.
+ When this changes, a \initial {c} line is written */
+
+char * lastinitial;
+
+int lastinitiallength;
+
+/* When we need a string of length 1 for the value of lastinitial,
+ store it here. */
+
+char lastinitial1[2];
+
+/* Initialize static storage for writing an index */
+
+void
+init_index ()
+{
+ pending = 0;
+ lastinitial = lastinitial1;
+ lastinitial1[0] = 0;
+ lastinitial1[1] = 0;
+ lastinitiallength = 0;
+ lastprimarylength = 100;
+ lastprimary = (char *) xmalloc (lastprimarylength + 1);
+ bzero (lastprimary, lastprimarylength + 1);
+ lastsecondarylength = 100;
+ lastsecondary = (char *) xmalloc (lastsecondarylength + 1);
+ bzero (lastsecondary, lastsecondarylength + 1);
+}
+
+/* Indexify. Merge entries for the same name,
+ insert headers for each initial character, etc. */
+
+indexify (line, ostream)
+ char *line;
+ FILE *ostream;
+{
+ char *primary, *secondary, *pagenumber;
+ int primarylength, secondarylength, pagelength;
+ int len = strlen (line);
+ int nosecondary;
+ int initiallength;
+ char *initial;
+ char initial1[2];
+ register char *p;
+
+ /* First, analyze the parts of the entry fed to us this time */
+
+ p = find_braced_pos (line, 0, 0, 0);
+ if (*p == '{')
+ {
+ initial = p;
+ /* Get length of inner pair of braces starting at p,
+ including that inner pair of braces. */
+ initiallength = find_braced_end (p + 1) + 1 - p;
+ }
+ else
+ {
+ initial = initial1;
+ initial1[0] = *p;
+ initial1[1] = 0;
+ initiallength = 1;
+
+ if (initial1[0] >= 'a' && initial1[0] <= 'z')
+ initial1[0] -= 040;
+ }
+
+ pagenumber = find_braced_pos (line, 1, 0, 0);
+ pagelength = find_braced_end (pagenumber) - pagenumber;
+ if (pagelength == 0)
+ abort ();
+
+ primary = find_braced_pos (line, 2, 0, 0);
+ primarylength = find_braced_end (primary) - primary;
+
+ secondary = find_braced_pos (line, 3, 0, 0);
+ nosecondary = !*secondary;
+ if (!nosecondary)
+ secondarylength = find_braced_end (secondary) - secondary;
+
+ /* If the primary is different from before, make a new primary entry */
+ if (strncmp (primary, lastprimary, primarylength))
+ {
+ /* Close off current secondary entry first, if one is open */
+ if (pending)
+ {
+ fputs ("}\n", ostream);
+ pending = 0;
+ }
+
+ /* If this primary has a different initial, include an entry for the initial */
+ if (initiallength != lastinitiallength ||
+ strncmp (initial, lastinitial, initiallength))
+ {
+ fprintf (ostream, "\\initial {");
+ fwrite (initial, 1, initiallength, ostream);
+ fprintf (ostream, "}\n", initial);
+ if (initial == initial1)
+ {
+ lastinitial = lastinitial1;
+ *lastinitial1 = *initial1;
+ }
+ else
+ {
+ lastinitial = initial;
+ }
+ lastinitiallength = initiallength;
+ }
+
+ /* Make the entry for the primary. */
+ if (nosecondary)
+ fputs ("\\entry {", ostream);
+ else
+ fputs ("\\primary {", ostream);
+ fwrite (primary, primarylength, 1, ostream);
+ if (nosecondary)
+ {
+ fputs ("}{", ostream);
+ pending = 1;
+ }
+ else
+ fputs ("}\n", ostream);
+
+ /* Record name of most recent primary */
+ if (lastprimarylength < primarylength)
+ {
+ lastprimarylength = primarylength + 100;
+ lastprimary = (char *) xrealloc (lastprimary,
+ 1 + lastprimarylength);
+ }
+ strncpy (lastprimary, primary, primarylength);
+ lastprimary[primarylength] = 0;
+
+ /* There is no current secondary within this primary, now */
+ lastsecondary[0] = 0;
+ }
+
+ /* Should not have an entry with no subtopic following one with a subtopic */
+
+ if (nosecondary && *lastsecondary)
+ error ("entry %s follows an entry with a secondary name", line);
+
+ /* Start a new secondary entry if necessary */
+ if (!nosecondary && strncmp (secondary, lastsecondary, secondarylength))
+ {
+ if (pending)
+ {
+ fputs ("}\n", ostream);
+ pending = 0;
+ }
+
+ /* Write the entry for the secondary. */
+ fputs ("\\secondary {", ostream);
+ fwrite (secondary, secondarylength, 1, ostream);
+ fputs ("}{", ostream);
+ pending = 1;
+
+ /* Record name of most recent secondary */
+ if (lastsecondarylength < secondarylength)
+ {
+ lastsecondarylength = secondarylength + 100;
+ lastsecondary = (char *) xrealloc (lastsecondary,
+ 1 + lastsecondarylength);
+ }
+ strncpy (lastsecondary, secondary, secondarylength);
+ lastsecondary[secondarylength] = 0;
+ }
+
+ /* Here to add one more page number to the current entry */
+ if (pending++ != 1)
+ fputs (", ", ostream); /* Punctuate first, if this is not the first */
+ fwrite (pagenumber, pagelength, 1, ostream);
+}
+
+/* Close out any unfinished output entry */
+
+void
+finish_index (ostream)
+ FILE *ostream;
+{
+ if (pending)
+ fputs ("}\n", ostream);
+ free (lastprimary);
+ free (lastsecondary);
+}
+
+/* Copy the lines in the sorted order.
+ Each line is copied out of the input file it was found in. */
+
+void
+writelines (linearray, nlines, ostream)
+ char **linearray;
+ int nlines;
+ FILE *ostream;
+{
+ char **stop_line = linearray + nlines;
+ char **next_line;
+
+ init_index ();
+
+ /* Output the text of the lines, and free the buffer space */
+
+ for (next_line = linearray; next_line != stop_line; next_line++)
+ {
+ /* If -u was specified, output the line only if distinct from previous one. */
+ if (next_line == linearray
+ /* Compare previous line with this one, using only the explicitly specd keyfields */
+ || compare_general (*(next_line - 1), *next_line, 0L, 0L, num_keyfields - 1))
+ {
+ char *p = *next_line;
+ char c;
+ while ((c = *p++) && c != '\n');
+ *(p-1) = 0;
+ indexify (*next_line, ostream);
+ }
+ }
+
+ finish_index (ostream);
+}
+
+/* Assume (and optionally verify) that each input file is sorted;
+ merge them and output the result.
+ Returns nonzero if any input file fails to be sorted.
+
+ This is the high-level interface that can handle an unlimited number of files. */
+
+#define MAX_DIRECT_MERGE 10
+
+int
+merge_files (infiles, nfiles, outfile)
+ char **infiles;
+ int nfiles;
+ char *outfile;
+{
+ char **tempfiles;
+ int ntemps;
+ int i;
+ int value = 0;
+ int start_tempcount = tempcount;
+
+ if (nfiles <= MAX_DIRECT_MERGE)
+ return merge_direct (infiles, nfiles, outfile);
+
+ /* Merge groups of MAX_DIRECT_MERGE input files at a time,
+ making a temporary file to hold each group's result. */
+
+ ntemps = (nfiles + MAX_DIRECT_MERGE - 1) / MAX_DIRECT_MERGE;
+ tempfiles = (char **) xmalloc (ntemps * sizeof (char *));
+ for (i = 0; i < ntemps; i++)
+ {
+ int nf = MAX_DIRECT_MERGE;
+ if (i + 1 == ntemps)
+ nf = nfiles - i * MAX_DIRECT_MERGE;
+ tempfiles[i] = maketempname (++tempcount);
+ value |= merge_direct (&infiles[i * MAX_DIRECT_MERGE], nf, tempfiles[i]);
+ }
+
+ /* All temporary files that existed before are no longer needed
+ since their contents have been merged into our new tempfiles.
+ So delete them. */
+ flush_tempfiles (start_tempcount);
+
+ /* Now merge the temporary files we created. */
+
+ merge_files (tempfiles, ntemps, outfile);
+
+ free (tempfiles);
+
+ return value;
+}
+
+/* Assume (and optionally verify) that each input file is sorted;
+ merge them and output the result.
+ Returns nonzero if any input file fails to be sorted.
+
+ This version of merging will not work if the number of
+ input files gets too high. Higher level functions
+ use it only with a bounded number of input files. */
+
+int
+merge_direct (infiles, nfiles, outfile)
+ char **infiles;
+ int nfiles;
+ char *outfile;
+{
+ char **ip = infiles;
+ struct linebuffer *lb1, *lb2;
+ struct linebuffer **thisline, **prevline;
+ FILE **streams;
+ int i;
+ int nleft;
+ int lossage = 0;
+ int *file_lossage;
+ struct linebuffer *prev_out = 0;
+ FILE *ostream = stdout;
+
+ if (outfile)
+ {
+ ostream = fopen (outfile, "w");
+ }
+ if (!ostream) pfatal_with_name (outfile);
+
+ init_index ();
+
+ if (nfiles == 0)
+ {
+ if (outfile)
+ fclose (ostream);
+ return 0;
+ }
+
+ /* For each file, make two line buffers.
+ Also, for each file, there is an element of `thisline'
+ which points at any time to one of the file's two buffers,
+ and an element of `prevline' which points to the other buffer.
+ `thisline' is supposed to point to the next available line from the file,
+ while `prevline' holds the last file line used,
+ which is remembered so that we can verify that the file is properly sorted. */
+
+ /* lb1 and lb2 contain one buffer each per file */
+ lb1 = (struct linebuffer *) xmalloc (nfiles * sizeof (struct linebuffer));
+ lb2 = (struct linebuffer *) xmalloc (nfiles * sizeof (struct linebuffer));
+
+ /* thisline[i] points to the linebuffer holding the next available line in file i,
+ or is zero if there are no lines left in that file. */
+ thisline = (struct linebuffer **) xmalloc (nfiles * sizeof (struct linebuffer *));
+ /* prevline[i] points to the linebuffer holding the last used line from file i.
+ This is just for verifying that file i is properly sorted. */
+ prevline = (struct linebuffer **) xmalloc (nfiles * sizeof (struct linebuffer *));
+ /* streams[i] holds the input stream for file i. */
+ streams = (FILE **) xmalloc (nfiles * sizeof (FILE *));
+ /* file_lossage[i] is nonzero if we already know file i is not properly sorted. */
+ file_lossage = (int *) xmalloc (nfiles * sizeof (int));
+
+ /* Allocate and initialize all that storage */
+
+ for (i = 0; i < nfiles; i++)
+ {
+ initbuffer (&lb1[i]);
+ initbuffer (&lb2[i]);
+ thisline[i] = &lb1[i];
+ prevline[i] = &lb2[i];
+ file_lossage[i] = 0;
+ streams[i] = fopen (infiles[i], "r");
+ if (!streams[i])
+ pfatal_with_name (infiles[i]);
+
+ readline (thisline[i], streams[i]);
+ }
+
+ /* Keep count of number of files not at eof */
+ nleft = nfiles;
+
+ while (nleft)
+ {
+ struct linebuffer *best = 0;
+ struct linebuffer *exch;
+ int bestfile = -1;
+ int i;
+
+ /* Look at the next avail line of each file; choose the least one. */
+
+ for (i = 0; i < nfiles; i++)
+ {
+ if (thisline[i] &&
+ (!best ||
+ 0 < compare_general (best->buffer, thisline[i]->buffer,
+ (long) bestfile, (long) i, num_keyfields)))
+ {
+ best = thisline[i];
+ bestfile = i;
+ }
+ }
+
+ /* Output that line, unless it matches the previous one and we don't want duplicates */
+
+ if (!(prev_out &&
+ !compare_general (prev_out->buffer, best->buffer, 0L, 1L, num_keyfields - 1)))
+ indexify (best->buffer, ostream);
+ prev_out = best;
+
+ /* Now make the line the previous of its file, and fetch a new line from that file */
+
+ exch = prevline[bestfile];
+ prevline[bestfile] = thisline[bestfile];
+ thisline[bestfile] = exch;
+
+ while (1)
+ {
+ /* If the file has no more, mark it empty */
+
+ if (feof (streams[bestfile]))
+ {
+ thisline[bestfile] = 0;
+ nleft--; /* Update the number of files still not empty */
+ break;
+ }
+ readline (thisline[bestfile], streams[bestfile]);
+ if (thisline[bestfile]->buffer[0] || !feof (streams[bestfile])) break;
+ }
+ }
+
+ finish_index (ostream);
+
+ /* Free all storage and close all input streams */
+
+ for (i = 0; i < nfiles; i++)
+ {
+ fclose (streams[i]);
+ free (lb1[i].buffer);
+ free (lb2[i].buffer);
+ }
+ free (file_lossage);
+ free (lb1);
+ free (lb2);
+ free (thisline);
+ free (prevline);
+ free (streams);
+
+ if (outfile)
+ fclose (ostream);
+
+ return lossage;
+}
+
+/* Print error message and exit. */
+
+fatal (s1, s2)
+ char *s1, *s2;
+{
+ error (s1, s2);
+ exit (EXIT_FATAL);
+}
+
+/* Print error message. `s1' is printf control string, `s2' is arg for it. */
+
+error (s1, s2)
+ char *s1, *s2;
+{
+ printf ("texindex: ");
+ printf (s1, s2);
+ printf ("\n");
+}
+
+perror_with_name (name)
+ char *name;
+{
+#ifdef VMS
+#include <errno.h>
+ extern noshare int sys_nerr;
+ extern noshare char *sys_errlist[];
+#else
+ extern int errno, sys_nerr;
+ extern char *sys_errlist[];
+#endif
+ char *s;
+
+ if (errno < sys_nerr)
+ s = concat ("", sys_errlist[errno], " for %s");
+ else
+ s = "cannot open %s";
+ error (s, name);
+}
+
+pfatal_with_name (name)
+ char *name;
+{
+ extern int errno, sys_nerr;
+ extern char *sys_errlist[];
+ char *s;
+
+ if (errno < sys_nerr)
+ s = concat ("", sys_errlist[errno], " for %s");
+ else
+ s = "cannot open %s";
+ fatal (s, name);
+}
+
+/* Return a newly-allocated string whose contents concatenate those of s1, s2, s3. */
+
+char *
+concat (s1, s2, s3)
+ char *s1, *s2, *s3;
+{
+ int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
+ char *result = (char *) xmalloc (len1 + len2 + len3 + 1);
+
+ strcpy (result, s1);
+ strcpy (result + len1, s2);
+ strcpy (result + len1 + len2, s3);
+ *(result + len1 + len2 + len3) = 0;
+
+ return result;
+}
+
+/* Like malloc but get fatal error if memory is exhausted. */
+
+int
+xmalloc (size)
+ int size;
+{
+ int result = malloc (size);
+ if (!result)
+ fatal ("virtual memory exhausted", 0);
+ return result;
+}
+
+
+int
+xrealloc (ptr, size)
+ char *ptr;
+ int size;
+{
+ int result = realloc (ptr, size);
+ if (!result)
+ fatal ("virtual memory exhausted");
+ return result;
+}
+
+bzero (b, length)
+ register char *b;
+ register int length;
+{
+#ifdef VMS
+ short zero = 0;
+ long max_str = 65535;
+
+ while (length > max_str) {
+ (void) LIB$MOVC5 (&zero, &zero, &zero, &max_str, b);
+ length -= max_str;
+ b += max_str;
+ }
+ (void) LIB$MOVC5 (&zero, &zero, &zero, &length, b);
+#else
+ while (length-- > 0)
+ *b++ = 0;
+#endif /* not VMS */
+}
diff --git a/man/texinfo.aux b/man/texinfo.aux
new file mode 100644
index 00000000000..73c83dc9c29
--- /dev/null
+++ b/man/texinfo.aux
@@ -0,0 +1,345 @@
+'xrdef {License-title}{Licensing Information}
+'xrdef {License-pg}{1}
+'xrdef {License-snt}{}
+'xrdef {Overview-title}{Chapter 1: Overview of Texinfo}
+'xrdef {Overview-pg}{3}
+'xrdef {Overview-snt}{Chapter'tie1}
+'xrdef {Info File-title}{Chapter 1: Overview of Texinfo}
+'xrdef {Info File-pg}{4}
+'xrdef {Info File-snt}{Section'tie1.1}
+'xrdef {Printed Manual-title}{Chapter 1: Overview of Texinfo}
+'xrdef {Printed Manual-pg}{5}
+'xrdef {Printed Manual-snt}{Section'tie1.2}
+'xrdef {Conventions-title}{Chapter 1: Overview of Texinfo}
+'xrdef {Conventions-pg}{6}
+'xrdef {Conventions-snt}{Section'tie1.3}
+'xrdef {Short Sample-title}{Chapter 1: Overview of Texinfo}
+'xrdef {Short Sample-pg}{7}
+'xrdef {Short Sample-snt}{Section'tie1.4}
+'xrdef {Texinfo Mode-title}{Chapter 2: Using Texinfo Mode}
+'xrdef {Texinfo Mode-pg}{11}
+'xrdef {Texinfo Mode-snt}{Chapter'tie2}
+'xrdef {Info on a Region-title}{Chapter 2: Using Texinfo Mode}
+'xrdef {Info on a Region-pg}{11}
+'xrdef {Info on a Region-snt}{Section'tie2.1}
+'xrdef {Showing the Structure-title}{Chapter 2: Using Texinfo Mode}
+'xrdef {Showing the Structure-pg}{12}
+'xrdef {Showing the Structure-snt}{Section'tie2.2}
+'xrdef {Inserting-title}{Chapter 2: Using Texinfo Mode}
+'xrdef {Inserting-pg}{12}
+'xrdef {Inserting-snt}{Section'tie2.3}
+'xrdef {Beginning a File-title}{Chapter 3: Beginning a Texinfo File}
+'xrdef {Beginning a File-pg}{15}
+'xrdef {Beginning a File-snt}{Chapter'tie3}
+'xrdef {Header-title}{Chapter 3: Beginning a Texinfo File}
+'xrdef {Header-pg}{16}
+'xrdef {Header-snt}{Section'tie3.1}
+'xrdef {First Line-title}{Chapter 3: Beginning a Texinfo File}
+'xrdef {First Line-pg}{16}
+'xrdef {First Line-snt}{Section'tie3.1.1}
+'xrdef {Start-of-Header-title}{Chapter 3: Beginning a Texinfo File}
+'xrdef {Start-of-Header-pg}{17}
+'xrdef {Start-of-Header-snt}{Section'tie3.1.2}
+'xrdef {Setfilename-title}{Chapter 3: Beginning a Texinfo File}
+'xrdef {Setfilename-pg}{17}
+'xrdef {Setfilename-snt}{Section'tie3.1.3}
+'xrdef {Settitle-title}{Chapter 3: Beginning a Texinfo File}
+'xrdef {Settitle-pg}{18}
+'xrdef {Settitle-snt}{Section'tie3.1.4}
+'xrdef {Setchapternewpage-title}{Chapter 3: Beginning a Texinfo File}
+'xrdef {Setchapternewpage-pg}{18}
+'xrdef {Setchapternewpage-snt}{Section'tie3.1.5}
+'xrdef {End-of-Header-title}{Chapter 3: Beginning a Texinfo File}
+'xrdef {End-of-Header-pg}{18}
+'xrdef {End-of-Header-snt}{Section'tie3.1.6}
+'xrdef {Permissions for Info-title}{Chapter 3: Beginning a Texinfo File}
+'xrdef {Permissions for Info-pg}{19}
+'xrdef {Permissions for Info-snt}{Section'tie3.2}
+'xrdef {Titlepage & Copyright Page-title}{Chapter 3: Beginning a Texinfo File}
+'xrdef {Titlepage & Copyright Page-pg}{19}
+'xrdef {Titlepage & Copyright Page-snt}{Section'tie3.3}
+'xrdef {Titlepage-title}{Chapter 3: Beginning a Texinfo File}
+'xrdef {Titlepage-pg}{19}
+'xrdef {Titlepage-snt}{Section'tie3.3.1}
+'xrdef {Center-title}{Chapter 3: Beginning a Texinfo File}
+'xrdef {Center-pg}{20}
+'xrdef {Center-snt}{Section'tie3.3.2}
+'xrdef {Copyright & Printed Permissions-title}{Chapter 3: Beginning a Texinfo File}
+'xrdef {Copyright & Printed Permissions-pg}{20}
+'xrdef {Copyright & Printed Permissions-snt}{Section'tie3.3.3}
+'xrdef {Top Node-title}{Chapter 3: Beginning a Texinfo File}
+'xrdef {Top Node-pg}{21}
+'xrdef {Top Node-snt}{Section'tie3.4}
+'xrdef {License and Distribution-title}{Chapter 3: Beginning a Texinfo File}
+'xrdef {License and Distribution-pg}{22}
+'xrdef {License and Distribution-snt}{Section'tie3.5}
+'xrdef {Ending a File-title}{Chapter 4: Ending a Texinfo File}
+'xrdef {Ending a File-pg}{25}
+'xrdef {Ending a File-snt}{Chapter'tie4}
+'xrdef {Contents-title}{Chapter 4: Ending a Texinfo File}
+'xrdef {Contents-pg}{25}
+'xrdef {Contents-snt}{Section'tie4.1}
+'xrdef {Indices-title}{Chapter 4: Ending a Texinfo File}
+'xrdef {Indices-pg}{26}
+'xrdef {Indices-snt}{Section'tie4.2}
+'xrdef {Index Entries-title}{Chapter 4: Ending a Texinfo File}
+'xrdef {Index Entries-pg}{27}
+'xrdef {Index Entries-snt}{Section'tie4.2.1}
+'xrdef {Combining Indices-title}{Chapter 4: Ending a Texinfo File}
+'xrdef {Combining Indices-pg}{28}
+'xrdef {Combining Indices-snt}{Section'tie4.2.2}
+'xrdef {Printing Indices & Menus-title}{Chapter 4: Ending a Texinfo File}
+'xrdef {Printing Indices & Menus-pg}{29}
+'xrdef {Printing Indices & Menus-snt}{Section'tie4.2.3}
+'xrdef {Structuring-title}{Chapter 5: Node and Chapter Structuring}
+'xrdef {Structuring-pg}{31}
+'xrdef {Structuring-snt}{Chapter'tie5}
+'xrdef {Chapter-title}{Chapter 5: Node and Chapter Structuring}
+'xrdef {Chapter-pg}{33}
+'xrdef {Chapter-snt}{Section'tie5.1}
+'xrdef {Unnumbered and Appendix-title}{Chapter 5: Node and Chapter Structuring}
+'xrdef {Unnumbered and Appendix-pg}{34}
+'xrdef {Unnumbered and Appendix-snt}{Section'tie5.2}
+'xrdef {Section-title}{Chapter 5: Node and Chapter Structuring}
+'xrdef {Section-pg}{34}
+'xrdef {Section-snt}{Section'tie5.3}
+'xrdef {Section-title}{Chapter 5: Node and Chapter Structuring}
+'xrdef {Section-pg}{34}
+'xrdef {Section-snt}{Section'tie5.4}
+'xrdef {Subsection-title}{Chapter 5: Node and Chapter Structuring}
+'xrdef {Subsection-pg}{34}
+'xrdef {Subsection-snt}{Section'tie5.5}
+'xrdef {Subsection-title}{Chapter 5: Node and Chapter Structuring}
+'xrdef {Subsection-pg}{35}
+'xrdef {Subsection-snt}{Section'tie5.6}
+'xrdef {Subsubsection-title}{Chapter 5: Node and Chapter Structuring}
+'xrdef {Subsubsection-pg}{35}
+'xrdef {Subsubsection-snt}{Section'tie5.7}
+'xrdef {Node-title}{Chapter 5: Node and Chapter Structuring}
+'xrdef {Node-pg}{35}
+'xrdef {Node-snt}{Section'tie5.8}
+'xrdef {Menu-title}{Chapter 5: Node and Chapter Structuring}
+'xrdef {Menu-pg}{37}
+'xrdef {Menu-snt}{Section'tie5.9}
+'xrdef {Quotations and Examples-title}{Chapter 6: Making Quotations and Examples}
+'xrdef {Quotations and Examples-pg}{39}
+'xrdef {Quotations and Examples-snt}{Chapter'tie6}
+'xrdef {Quotation-title}{Chapter 6: Making Quotations and Examples}
+'xrdef {Quotation-pg}{39}
+'xrdef {Quotation-snt}{Section'tie6.1}
+'xrdef {Example-title}{Chapter 6: Making Quotations and Examples}
+'xrdef {Example-pg}{40}
+'xrdef {Example-snt}{Section'tie6.2}
+'xrdef {Display-title}{Chapter 6: Making Quotations and Examples}
+'xrdef {Display-pg}{40}
+'xrdef {Display-snt}{Section'tie6.3}
+'xrdef {Lists and Tables-title}{Chapter 7: Making Lists and Tables}
+'xrdef {Lists and Tables-pg}{41}
+'xrdef {Lists and Tables-snt}{Chapter'tie7}
+'xrdef {Itemize-title}{Chapter 7: Making Lists and Tables}
+'xrdef {Itemize-pg}{41}
+'xrdef {Itemize-snt}{Section'tie7.1}
+'xrdef {Enumerate-title}{Chapter 7: Making Lists and Tables}
+'xrdef {Enumerate-pg}{42}
+'xrdef {Enumerate-snt}{Section'tie7.2}
+'xrdef {Table-title}{Chapter 7: Making Lists and Tables}
+'xrdef {Table-pg}{43}
+'xrdef {Table-snt}{Section'tie7.3}
+'xrdef {Itemx-title}{Chapter 7: Making Lists and Tables}
+'xrdef {Itemx-pg}{44}
+'xrdef {Itemx-snt}{Section'tie7.3.1}
+'xrdef {Cross References-title}{Chapter 8: Making Cross References}
+'xrdef {Cross References-pg}{47}
+'xrdef {Cross References-snt}{Chapter'tie8}
+'xrdef {Xref-title}{Chapter 8: Making Cross References}
+'xrdef {Xref-pg}{47}
+'xrdef {Xref-snt}{Section'tie8.1}
+'xrdef {Pxref-title}{Chapter 8: Making Cross References}
+'xrdef {Pxref-pg}{50}
+'xrdef {Pxref-snt}{Section'tie8.2}
+'xrdef {Inforef-title}{Chapter 8: Making Cross References}
+'xrdef {Inforef-pg}{50}
+'xrdef {Inforef-snt}{Section'tie8.3}
+'xrdef {Formatting Paragraphs-title}{Chapter 9: Formatting Paragraphs}
+'xrdef {Formatting Paragraphs-pg}{51}
+'xrdef {Formatting Paragraphs-snt}{Chapter'tie9}
+'xrdef {Refilling & Noindent-title}{Chapter 9: Formatting Paragraphs}
+'xrdef {Refilling & Noindent-pg}{51}
+'xrdef {Refilling & Noindent-snt}{Section'tie9.1}
+'xrdef {Refill-title}{Chapter 9: Formatting Paragraphs}
+'xrdef {Refill-pg}{51}
+'xrdef {Refill-snt}{Section'tie9.1.1}
+'xrdef {Noindent-title}{Chapter 9: Formatting Paragraphs}
+'xrdef {Noindent-pg}{52}
+'xrdef {Noindent-snt}{Section'tie9.1.2}
+'xrdef {Breaks Blank-Lines Groups-title}{Chapter 9: Formatting Paragraphs}
+'xrdef {Breaks Blank-Lines Groups-pg}{53}
+'xrdef {Breaks Blank-Lines Groups-snt}{Section'tie9.2}
+'xrdef {Line Breaks-title}{Chapter 9: Formatting Paragraphs}
+'xrdef {Line Breaks-pg}{53}
+'xrdef {Line Breaks-snt}{Section'tie9.2.1}
+'xrdef {Sp-title}{Chapter 9: Formatting Paragraphs}
+'xrdef {Sp-pg}{53}
+'xrdef {Sp-snt}{Section'tie9.2.2}
+'xrdef {Br-title}{Chapter 9: Formatting Paragraphs}
+'xrdef {Br-pg}{54}
+'xrdef {Br-snt}{Section'tie9.2.3}
+'xrdef {W-title}{Chapter 9: Formatting Paragraphs}
+'xrdef {W-pg}{54}
+'xrdef {W-snt}{Section'tie9.2.4}
+'xrdef {Page-title}{Chapter 9: Formatting Paragraphs}
+'xrdef {Page-pg}{54}
+'xrdef {Page-snt}{Section'tie9.2.5}
+'xrdef {Group-title}{Chapter 9: Formatting Paragraphs}
+'xrdef {Group-pg}{54}
+'xrdef {Group-snt}{Section'tie9.2.6}
+'xrdef {Need-title}{Chapter 9: Formatting Paragraphs}
+'xrdef {Need-pg}{54}
+'xrdef {Need-snt}{Section'tie9.2.7}
+'xrdef {Marking Text-title}{Chapter 10: Marking Text Within a Paragraph}
+'xrdef {Marking Text-pg}{57}
+'xrdef {Marking Text-snt}{Chapter'tie10}
+'xrdef {Specifying-title}{Chapter 10: Marking Text Within a Paragraph}
+'xrdef {Specifying-pg}{57}
+'xrdef {Specifying-snt}{Section'tie10.1}
+'xrdef {Code-title}{Chapter 10: Marking Text Within a Paragraph}
+'xrdef {Code-pg}{58}
+'xrdef {Code-snt}{Section'tie10.1.1}
+'xrdef {Samp-title}{Chapter 10: Marking Text Within a Paragraph}
+'xrdef {Samp-pg}{59}
+'xrdef {Samp-snt}{Section'tie10.1.2}
+'xrdef {File-title}{Chapter 10: Marking Text Within a Paragraph}
+'xrdef {File-pg}{59}
+'xrdef {File-snt}{Section'tie10.1.3}
+'xrdef {Kbd-title}{Chapter 10: Marking Text Within a Paragraph}
+'xrdef {Kbd-pg}{60}
+'xrdef {Kbd-snt}{Section'tie10.1.4}
+'xrdef {Key-title}{Chapter 10: Marking Text Within a Paragraph}
+'xrdef {Key-pg}{60}
+'xrdef {Key-snt}{Section'tie10.1.5}
+'xrdef {Ctrl-title}{Chapter 10: Marking Text Within a Paragraph}
+'xrdef {Ctrl-pg}{61}
+'xrdef {Ctrl-snt}{Section'tie10.1.6}
+'xrdef {Var-title}{Chapter 10: Marking Text Within a Paragraph}
+'xrdef {Var-pg}{62}
+'xrdef {Var-snt}{Section'tie10.1.7}
+'xrdef {Dfn-title}{Chapter 10: Marking Text Within a Paragraph}
+'xrdef {Dfn-pg}{63}
+'xrdef {Dfn-snt}{Section'tie10.1.8}
+'xrdef {Cite-title}{Chapter 10: Marking Text Within a Paragraph}
+'xrdef {Cite-pg}{63}
+'xrdef {Cite-snt}{Section'tie10.1.9}
+'xrdef {Braces Atsigns Periods-title}{Chapter 10: Marking Text Within a Paragraph}
+'xrdef {Braces Atsigns Periods-pg}{63}
+'xrdef {Braces Atsigns Periods-snt}{Section'tie10.2}
+'xrdef {Inserting An Atsign-title}{Chapter 10: Marking Text Within a Paragraph}
+'xrdef {Inserting An Atsign-pg}{63}
+'xrdef {Inserting An Atsign-snt}{Section'tie10.2.1}
+'xrdef {Insert Left Brace-title}{Chapter 10: Marking Text Within a Paragraph}
+'xrdef {Insert Left Brace-pg}{64}
+'xrdef {Insert Left Brace-snt}{Section'tie10.2.2}
+'xrdef {Insert Left Brace-title}{Chapter 10: Marking Text Within a Paragraph}
+'xrdef {Insert Left Brace-pg}{64}
+'xrdef {Insert Left Brace-snt}{Section'tie10.2.3}
+'xrdef {Insert Colon-title}{Chapter 10: Marking Text Within a Paragraph}
+'xrdef {Insert Colon-pg}{64}
+'xrdef {Insert Colon-snt}{Section'tie10.2.4}
+'xrdef {Insert Period-title}{Chapter 10: Marking Text Within a Paragraph}
+'xrdef {Insert Period-pg}{64}
+'xrdef {Insert Period-snt}{Section'tie10.2.5}
+'xrdef {Dots Bullets Tex-title}{Chapter 10: Marking Text Within a Paragraph}
+'xrdef {Dots Bullets Tex-pg}{65}
+'xrdef {Dots Bullets Tex-snt}{Section'tie10.3}
+'xrdef {Dots-title}{Chapter 10: Marking Text Within a Paragraph}
+'xrdef {Dots-pg}{65}
+'xrdef {Dots-snt}{Section'tie10.3.1}
+'xrdef {Bullet-title}{Chapter 10: Marking Text Within a Paragraph}
+'xrdef {Bullet-pg}{65}
+'xrdef {Bullet-snt}{Section'tie10.3.2}
+'xrdef {Tex-title}{Chapter 10: Marking Text Within a Paragraph}
+'xrdef {Tex-pg}{65}
+'xrdef {Tex-snt}{Section'tie10.3.3}
+'xrdef {Emphasis-title}{Chapter 10: Marking Text Within a Paragraph}
+'xrdef {Emphasis-pg}{66}
+'xrdef {Emphasis-snt}{Section'tie10.4}
+'xrdef {Emph and Strong-title}{Chapter 10: Marking Text Within a Paragraph}
+'xrdef {Emph and Strong-pg}{66}
+'xrdef {Emph and Strong-snt}{Section'tie10.4.1}
+'xrdef {Fonts-title}{Chapter 10: Marking Text Within a Paragraph}
+'xrdef {Fonts-pg}{66}
+'xrdef {Fonts-snt}{Section'tie10.4.2}
+'xrdef {Conditionals-title}{Chapter 11: Conditionals}
+'xrdef {Conditionals-pg}{67}
+'xrdef {Conditionals-snt}{Chapter'tie11}
+'xrdef {Using Tex Commands-title}{Chapter 11: Conditionals}
+'xrdef {Using Tex Commands-pg}{67}
+'xrdef {Using Tex Commands-snt}{Section'tie11.1}
+'xrdef {Printing Hardcopy-title}{Chapter 12: Printing Hardcopy}
+'xrdef {Printing Hardcopy-pg}{69}
+'xrdef {Printing Hardcopy-snt}{Chapter'tie12}
+'xrdef {Requirements-title}{Chapter 12: Printing Hardcopy}
+'xrdef {Requirements-pg}{71}
+'xrdef {Requirements-snt}{Section'tie12.1}
+'xrdef {Compile-Command-title}{Chapter 12: Printing Hardcopy}
+'xrdef {Compile-Command-pg}{72}
+'xrdef {Compile-Command-snt}{Section'tie12.2}
+'xrdef {Creating an Info File-title}{Chapter 13: Creating an On-line Info file}
+'xrdef {Creating an Info File-pg}{73}
+'xrdef {Creating an Info File-snt}{Chapter'tie13}
+'xrdef {Installing an Info File-title}{Chapter 13: Creating an On-line Info file}
+'xrdef {Installing an Info File-pg}{74}
+'xrdef {Installing an Info File-snt}{Section'tie13.1}
+'xrdef {Catching Mistakes-title}{Chapter 14: Catching Mistakes}
+'xrdef {Catching Mistakes-pg}{77}
+'xrdef {Catching Mistakes-snt}{Chapter'tie14}
+'xrdef {Debugging with Info-title}{Chapter 14: Catching Mistakes}
+'xrdef {Debugging with Info-pg}{77}
+'xrdef {Debugging with Info-snt}{Section'tie14.1}
+'xrdef {Using the Emacs Lisp Debugger-title}{Chapter 14: Catching Mistakes}
+'xrdef {Using the Emacs Lisp Debugger-pg}{78}
+'xrdef {Using the Emacs Lisp Debugger-snt}{Section'tie14.1.1}
+'xrdef {Debugging with Tex-title}{Chapter 14: Catching Mistakes}
+'xrdef {Debugging with Tex-pg}{80}
+'xrdef {Debugging with Tex-snt}{Section'tie14.2}
+'xrdef {Using texinfo-show-structure-title}{Chapter 14: Catching Mistakes}
+'xrdef {Using texinfo-show-structure-pg}{81}
+'xrdef {Using texinfo-show-structure-snt}{Section'tie14.3}
+'xrdef {Using Occur-title}{Chapter 14: Catching Mistakes}
+'xrdef {Using Occur-pg}{82}
+'xrdef {Using Occur-snt}{Section'tie14.3.1}
+'xrdef {Running Info-Validate-title}{Chapter 14: Catching Mistakes}
+'xrdef {Running Info-Validate-pg}{83}
+'xrdef {Running Info-Validate-snt}{Section'tie14.4}
+'xrdef {Info-Validating a Large File-title}{Chapter 14: Catching Mistakes}
+'xrdef {Info-Validating a Large File-pg}{84}
+'xrdef {Info-Validating a Large File-snt}{Section'tie14.4.1}
+'xrdef {Splitting-title}{Chapter 14: Catching Mistakes}
+'xrdef {Splitting-pg}{85}
+'xrdef {Splitting-snt}{Section'tie14.4.2}
+'xrdef {Command Syntax-title}{Appendix \char65: {\tt\char'100}-Command Syntax}
+'xrdef {Command Syntax-pg}{87}
+'xrdef {Command Syntax-snt}{Appendix'tie'char65}
+'xrdef {Include Files-title}{Appendix \char66: Include Files}
+'xrdef {Include Files-pg}{89}
+'xrdef {Include Files-snt}{Appendix'tie'char66}
+'xrdef {Include Files-title}{Appendix \char66: Include Files}
+'xrdef {Include Files-pg}{89}
+'xrdef {Include Files-snt}{Section'tie'char66.1}
+'xrdef {TeX Input-title}{Appendix \char67: \TeX{} Input Initialization}
+'xrdef {TeX Input-pg}{91}
+'xrdef {TeX Input-snt}{Appendix'tie'char67}
+'xrdef {Sample Permissions-title}{Appendix \char68: Standard text for Copying Permissions}
+'xrdef {Sample Permissions-pg}{93}
+'xrdef {Sample Permissions-snt}{Appendix'tie'char68}
+'xrdef {Ifinfo Permissions-title}{Appendix \char68: Standard text for Copying Permissions}
+'xrdef {Ifinfo Permissions-pg}{94}
+'xrdef {Ifinfo Permissions-snt}{Section'tie'char68.1}
+'xrdef {Titlepage Permissions-title}{Appendix \char68: Standard text for Copying Permissions}
+'xrdef {Titlepage Permissions-pg}{94}
+'xrdef {Titlepage Permissions-snt}{Section'tie'char68.2}
+'xrdef {Command Index-title}{Command Index}
+'xrdef {Command Index-pg}{97}
+'xrdef {Command Index-snt}{}
+'xrdef {Concept Index-title}{Concept Index}
+'xrdef {Concept Index-pg}{99}
+'xrdef {Concept Index-snt}{}
diff --git a/man/texinfo.cps b/man/texinfo.cps
new file mode 100644
index 00000000000..3677c01470a
--- /dev/null
+++ b/man/texinfo.cps
@@ -0,0 +1,211 @@
+\initial {{\tt\char'100}}
+\entry {{\tt\char'100}-Command Syntax}{87}
+\initial {B}
+\entry {Badly referenced nodes}{83}
+\entry {Beginning a Texinfo file}{15}
+\entry {Beginning line of a Texinfo file}{16}
+\entry {Braces, inserting}{63}
+\entry {Breaks in a line}{53}
+\entry {Breaks in a paragraph}{54}
+\entry {Bullets, inserting}{65}
+\initial {C}
+\entry {Catching errors with Info Formatting}{77}
+\entry {Catching errors with TeX Formatting}{80}
+\entry {Catching mistakes}{77}
+\entry {Centering a line}{20}
+\entry {Chapter structuring}{31}
+\entry {Characteristics of the Info file}{4}
+\entry {Characteristics, printed manual}{5}
+\entry {Checking for badly referenced nodes}{83}
+\entry {Combining Indices}{28}
+\entry {Commands to insert single characters}{63}
+\entry {Commands, inserting them}{12}
+\entry {Commands, specifying them within text}{57}
+\entry {Compile command for formatting}{72}
+\entry {Conditionals}{67}
+\entry {Contents, Table of}{25}
+\entry {Conventions, syntactic}{6}
+\entry {Copying permissions}{93}
+\entry {Copyright}{20}
+\entry {Copyright page}{19}
+\entry {Correcting mistakes}{77}
+\entry {Creating an on-line Info file}{73}
+\entry {Creating indices}{26}
+\entry {Cross references}{47}
+\entry {Cross references using inforef}{50}
+\entry {Cross references using pxref}{50}
+\entry {Cross references using xref}{47}
+\entry {cshrc initialization file}{91}
+\initial {D}
+\entry {Debugger, using the Emacs Lisp}{78}
+\entry {Debugging the Texinfo structure}{77}
+\entry {Debugging with Info Formatting}{77}
+\entry {Debugging with TeX Formatting}{80}
+\entry {Defining the entries of an index}{27}
+\entry {Definitions, specifying them within text}{57}
+\entry {Dir directory for Info installation}{74}
+\entry {Display}{40}
+\entry {Distribution}{22}
+\entry {Dots, inserting}{65}
+\initial {E}
+\entry {Emacs}{11}
+\entry {Emacs Lisp debugger}{78}
+\entry {Emphasizing text}{66}
+\entry {end-of-header}{18}
+\entry {Ending a Texinfo file}{25}
+\entry {Entries for an index}{27}
+\entry {Enumerate}{42}
+\entry {Examples}{39, 40}
+\initial {F}
+\entry {File beginning}{15}
+\entry {File ending}{25}
+\entry {File structure, showing it}{12}
+\entry {Files, specifying them within text}{57}
+\entry {Finding badly referenced nodes}{83}
+\entry {First line of a Texinfo file}{16}
+\entry {Formatting a file for Info}{73}
+\entry {Formatting paragraphs}{51}
+\entry {Formatting requirements}{71}
+\entry {Formatting with the compile command}{72}
+\entry {Frequently used commands, inserting them}{12}
+\initial {G}
+\entry {General syntactic conventions}{6}
+\entry {Generating menus with indices}{29}
+\entry {GNU Emacs}{11}
+\entry {Group}{54}
+\initial {H}
+\entry {Hardcopy, printing it}{69}
+\entry {Header for Texinfo files}{16}
+\entry {Highlighting}{57}
+\entry {Holding text together vertically}{54}
+\initial {I}
+\entry {Ifinfo}{67}
+\entry {Ifinfo permissions}{94}
+\entry {Iftex}{67}
+\entry {Include files}{89}
+\entry {Index entries}{27}
+\entry {Indices}{26}
+\entry {Indices, combining them}{28}
+\entry {Indices, printing}{29}
+\entry {Indices, sorting}{69}
+\entry {Indices, two letter names}{28}
+\entry {Indirect subfiles}{73}
+\entry {Info file characteristics}{4}
+\entry {Info file installation}{74}
+\entry {Info file requirement for {\tt\char'100}setfilename}{17}
+\entry {Info file, splitting manually}{85}
+\entry {Info validating a large file}{84}
+\entry {Info, creating an on-line file}{73}
+\entry {Info, formatting on a region}{11}
+\entry {Info-validate, running the command}{83}
+\entry {Inforef for cross references}{50}
+\entry {Inserting braces, {\tt\char'100} and periods}{63}
+\entry {Inserting dots}{65}
+\entry {Inserting frequently used commands}{12}
+\entry {Installing an Info file}{74}
+\entry {Itemize}{41}
+\entry {Itemx}{44}
+\initial {L}
+\entry {License agreement}{22}
+\entry {Line breaks}{53}
+\entry {Line breaks, preventing}{54}
+\entry {Line spacing}{53}
+\entry {Lists and tables, making them}{41}
+\entry {Local variables}{72}
+\entry {Looking for badly referenced nodes}{83}
+\initial {M}
+\entry {Making a printed manual}{69}
+\entry {Making a tag table manually}{84}
+\entry {Making cross references}{47}
+\entry {Making lists and tables}{41}
+\entry {Marking text within a paragraph}{57}
+\entry {Master menu}{21}
+\entry {Menus}{37}
+\entry {Menus generated with indices}{29}
+\entry {Mistakes, catching}{77}
+\entry {Mode, using Texinfo}{11}
+\initial {N}
+\entry {Names for indices}{28}
+\entry {Need}{54}
+\entry {Node and chapter structuring}{31}
+\entry {Node structuring}{31}
+\entry {Nodes, catching mistakes}{77}
+\entry {Nodes, checking for badly referenced nodes}{83}
+\entry {Nodes, correcting mistakes}{77}
+\initial {O}
+\entry {Occur, using the command}{82}
+\entry {Overview of Texinfo}{3}
+\initial {P}
+\entry {Page breaks}{54}
+\entry {Pages, starting odd}{18}
+\entry {Paragraph breaks}{54}
+\entry {Paragraphs, formatting}{51}
+\entry {Periods, inserting}{63}
+\entry {Permissions}{93}
+\entry {Permissions, printed}{20}
+\entry {Preface}{23}
+\entry {Preventing indentation in the printed text}{51}
+\entry {Printed manual characteristics}{5}
+\entry {Printed permissions}{20}
+\entry {Printing an index}{29}
+\entry {Printing hardcopy}{69}
+\entry {Problems, catching}{77}
+\entry {profile initialization file}{91}
+\entry {Pxref for cross references}{50}
+\initial {Q}
+\entry {Quotations}{39}
+\initial {R}
+\entry {References}{47}
+\entry {Refilling paragraphs automatically}{51}
+\entry {Requirements for formatting}{71}
+\entry {Running Info}{73}
+\entry {Running Info on a region}{11}
+\entry {Running Info-validate}{83}
+\entry {Running Info-validate on a large file}{84}
+\initial {S}
+\entry {Sample texinfo file}{7}
+\entry {Setfilename command}{17}
+\entry {Showing the structure of a file}{12, 81}
+\entry {Single characters, commands to insert}{63}
+\entry {Sorting indices}{69}
+\entry {Spaces from line to line}{53}
+\entry {Special typesetting commands}{65}
+\entry {Specifying commands, files and the like}{57}
+\entry {Splitting an Info file manually}{85}
+\entry {start-of-header}{17}
+\entry {Starting chapters}{18}
+\entry {Structure of a file, showing it}{12}
+\entry {Structure of Texinfo, catching mistakes}{77}
+\entry {Structuring of nodes and chapters}{31}
+\entry {Syntactic conventions}{6}
+\initial {T}
+\entry {Table of contents}{25}
+\entry {Tables and lists, making them}{41}
+\entry {Tables, making two-column}{43}
+\entry {Tag table, making manually}{84}
+\entry {TeX commands, using them}{67}
+\entry {TeX Input Initialization}{91}
+\entry {TeX-logo, inserting}{65}
+\entry {Texinfo file beginning}{15}
+\entry {Texinfo file ending}{25}
+\entry {Texinfo file header}{16}
+\entry {Texinfo file structure, showing it}{12}
+\entry {Texinfo mode}{11}
+\entry {Texinfo overview}{3}
+\entry {texinfo-show-structure for catching mistakes}{81}
+\entry {TEXINPUTS environment variable}{91}
+\entry {Titlepage}{19}
+\entry {Titlepage permissions}{94}
+\entry {Top node}{21}
+\entry {Two letter names for indices}{28}
+\entry {Typesetting commands for dots and the like}{65}
+\initial {U}
+\entry {Using occur}{82}
+\entry {Using TeX commands}{67}
+\entry {Using texinfo-show-structure to catch mistakes}{81}
+\entry {Using the Emacs Lisp debugger}{78}
+\initial {V}
+\entry {Validating a large file}{84}
+\entry {Vertically holding text together}{54}
+\initial {X}
+\entry {Xref for cross references}{47}
diff --git a/man/texinfo.fns b/man/texinfo.fns
new file mode 100644
index 00000000000..28ee9f08e98
--- /dev/null
+++ b/man/texinfo.fns
@@ -0,0 +1,97 @@
+\initial {*}
+\entry {\code {*}}{53}
+\initial {A}
+\entry {\code {appendix}}{34}
+\entry {\code {appendixsec}}{34}
+\entry {\code {appendixsubsec}}{35}
+\entry {\code {appendixsubsubsec}}{35}
+\entry {\code {asterisk}}{53}
+\entry {\code {at-sign colons}}{64}
+\entry {\code {at-sign periods}}{64}
+\entry {\code {at-signs}}{63}
+\initial {B}
+\entry {\code {b (bold font)}}{66}
+\entry {\code {br (paragraph breaks)}}{54}
+\entry {\code {bullet}}{65}
+\entry {\code {bye}}{25}
+\initial {C}
+\entry {\code {center}}{20}
+\entry {\code {chapter}}{33}
+\entry {\code {cite}}{63}
+\entry {\code {code}}{58}
+\entry {\code {copyright}}{21}
+\entry {\code {ctrl}}{61}
+\initial {D}
+\entry {\code {dfn}}{63}
+\entry {\code {display}}{40}
+\entry {\code {dots}}{65}
+\initial {E}
+\entry {\code {emph}}{66}
+\entry {\code {end}}{39, 41}
+\entry {\code {enumerate}}{42}
+\entry {\code {example}}{40}
+\initial {F}
+\entry {\code {file}}{59}
+\entry {\code {filll}}{20}
+\initial {G}
+\entry {\code {group}}{54}
+\initial {I}
+\entry {\code {i (italic font)}}{66}
+\entry {\code {ifinfo}}{67}
+\entry {\code {iftex}}{67}
+\entry {\code {inforef}}{50}
+\entry {\code {item}}{42, 43}
+\entry {\code {itemize}}{41}
+\entry {\code {itemx}}{44}
+\initial {K}
+\entry {\code {kbd}}{60}
+\entry {\code {key}}{60}
+\initial {L}
+\entry {\code {left-braces}}{64}
+\initial {M}
+\entry {\code {menu}}{37}
+\initial {N}
+\entry {\code {need}}{54}
+\entry {\code {node}}{31}
+\entry {\code {noindent}}{52}
+\initial {P}
+\entry {\code {page}}{54}
+\entry {\code {pxref}}{50}
+\initial {Q}
+\entry {\code {quotation}}{39}
+\initial {R}
+\entry {\code {refill}}{51}
+\entry {\code {right-braces}}{64}
+\initial {S}
+\entry {\code {samp}}{59}
+\entry {\code {section}}{34}
+\entry {\code {setchapternewpage}}{18}
+\entry {\code {setfilename}}{17}
+\entry {\code {settitle}}{18}
+\entry {\code {sp (line spacing)}}{53}
+\entry {\code {start-of-header}}{17}
+\entry {\code {strong}}{66}
+\entry {\code {subsection}}{34}
+\entry {\code {subsubsection}}{35}
+\initial {T}
+\entry {\code {t (typewriter font)}}{66}
+\entry {\code {table}}{43}
+\entry {\code {TeX}}{65}
+\entry {\code {texindex (for sorting indices)}}{69}
+\entry {\code {texinfo-format-buffer}}{73}
+\entry {\code {texinfo-format-region}}{11}
+\entry {\code {texinfo-show-structure}}{81}
+\entry {\code {titlefont}}{20}
+\entry {\code {titlepage}}{19}
+\initial {U}
+\entry {\code {unnumbered}}{34}
+\entry {\code {unnumberedsec}}{34}
+\entry {\code {unnumberedsubsec}}{35}
+\entry {\code {unnumberedsubsubsec}}{35}
+\initial {V}
+\entry {\code {var}}{62}
+\entry {\code {vskip}}{20}
+\initial {W}
+\entry {\code {w (preventing a line break)}}{54}
+\initial {X}
+\entry {\code {xref}}{47}
diff --git a/man/texinfo.tex b/man/texinfo.tex
new file mode 100755
index 00000000000..44e8f8d4562
--- /dev/null
+++ b/man/texinfo.tex
@@ -0,0 +1,2665 @@
+%% TeX macros to handle texinfo files
+
+% Copyright (C) 1985, 1986, 1988, 1990 Free Software Foundation, Inc.
+
+%This texinfo.tex file 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 1, or (at
+%your option) any later version.
+
+%This texinfo.tex file is distributed in the hope that it will be
+%useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+%of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+%General Public License for more details.
+
+%You should have received a copy of the GNU General Public License
+%along with this texinfo.tex file; see the file COPYING. If not, write
+%to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,
+%USA.
+
+
+%In other words, you are welcome to use, share and improve this program.
+%You are forbidden to forbid anyone else to use, share and improve
+%what you give them. Help stamp out software-hoarding!
+
+\def\texinfoversion{2.29}
+\message{Loading texinfo package [Version \texinfoversion]:}
+\message{}
+
+% Print the version number if in a .fmt file.
+\everyjob{\message{[Texinfo version \texinfoversion]}\message{}}
+
+% Save some parts of plain tex whose names we will redefine.
+
+\let\ptexlbrace=\{
+\let\ptexrbrace=\}
+\let\ptexdots=\dots
+\let\ptexdot=\.
+\let\ptexstar=\*
+\let\ptexend=\end
+\let\ptexbullet=\bullet
+\let\ptexb=\b
+\let\ptexc=\c
+\let\ptexi=\i
+\let\ptext=\t
+\let\ptexl=\l
+\let\ptexL=\L
+
+\def\tie{\penalty 10000\ } % Save plain tex definition of ~.
+
+\message{Basics,}
+\chardef\other=12
+
+\hyphenation{ap-pen-dix}
+\hyphenation{mini-buf-fer mini-buf-fers}
+\hyphenation{eshell}
+
+% Margin to add to right of even pages, to left of odd pages.
+\newdimen \bindingoffset \bindingoffset=0pt
+\newdimen \normaloffset \normaloffset=\hoffset
+\newdimen\pagewidth \newdimen\pageheight
+\pagewidth=\hsize \pageheight=\vsize
+
+%---------------------Begin change-----------------------
+%
+% Dimensions to add cropmarks at corners Added by P. A. MacKay, 12 Nov. 1986
+%
+\newdimen\cornerlong \newdimen\cornerthick
+\newdimen \topandbottommargin
+\newdimen \outerhsize \newdimen \outervsize
+\cornerlong=1pc\cornerthick=.3pt % These set size of cropmarks
+\outerhsize=7in
+\outervsize=9.5in
+\topandbottommargin=.75in
+%
+%---------------------End change-----------------------
+
+% \onepageout takes a vbox as an argument. Note that \pagecontents
+% does insertions itself, but you have to call it yourself.
+\chardef\PAGE=255 \output={\onepageout{\pagecontents\PAGE}}
+\def\onepageout#1{\hoffset=\normaloffset
+\ifodd\pageno \advance\hoffset by \bindingoffset
+\else \advance\hoffset by -\bindingoffset\fi
+{\escapechar=`\\\relax % makes sure backslash is used in output files.
+\shipout\vbox{{\let\hsize=\pagewidth \makeheadline} \pagebody{#1}%
+{\let\hsize=\pagewidth \makefootline}}}%
+\advancepageno \ifnum\outputpenalty>-20000 \else\dosupereject\fi}
+
+
+% Here is a modification of the main output routine for Near East Publications
+% This provides right-angle cropmarks at all four corners.
+% The contents of the page are centerlined into the cropmarks,
+% and any desired binding offset is added as an \hskip on either
+% site of the centerlined box. (P. A. MacKay, 12 November, 1986)
+%
+\def\croppageout#1{\hoffset=0pt % make sure this doesn't mess things up
+ \shipout
+ \vbox to \outervsize{\hsize=\outerhsize
+ \vbox{\line{\ewtop\hfill\ewtop}}
+ \nointerlineskip
+ \line{\vbox{\moveleft\cornerthick\nstop}
+ \hfill
+ \vbox{\moveright\cornerthick\nstop}}
+ \vskip \topandbottommargin
+ \centerline{\ifodd\pageno\hskip\bindingoffset\fi
+ \vbox{
+ {\let\hsize=\pagewidth \makeheadline}
+ \pagebody{#1}
+ {\let\hsize=\pagewidth \makefootline}}
+ \ifodd\pageno\else\hskip\bindingoffset\fi}
+ \vskip \topandbottommargin plus1fill minus1fill
+ \boxmaxdepth\cornerthick
+ \line{\vbox{\moveleft\cornerthick\nsbot}
+ \hfill
+ \vbox{\moveright\cornerthick\nsbot}}
+ \nointerlineskip
+ \vbox{\line{\ewbot\hfill\ewbot}}
+ }
+ \advancepageno
+ \ifnum\outputpenalty>-20000 \else\dosupereject\fi}
+%
+% Do @cropmarks to get crop marks
+\def\cropmarks{\let\onepageout=\croppageout }
+
+\def\pagebody#1{\vbox to\pageheight{\boxmaxdepth=\maxdepth #1}}
+{\catcode`\@ =11
+\gdef\pagecontents#1{\ifvoid\topins\else\unvbox\topins\fi
+\dimen@=\dp#1 \unvbox#1
+\ifvoid\footins\else\vskip\skip\footins\footnoterule \unvbox\footins\fi
+\ifr@ggedbottom \kern-\dimen@ \vfil \fi}
+}
+
+%
+% Here are the rules for the cropmarks. Note that they are
+% offset so that the space between them is truly \outerhsize or \outervsize
+% (P. A. MacKay, 12 November, 1986)
+%
+\def\ewtop{\vrule height\cornerthick depth0pt width\cornerlong}
+\def\nstop{\vbox
+ {\hrule height\cornerthick depth\cornerlong width\cornerthick}}
+\def\ewbot{\vrule height0pt depth\cornerthick width\cornerlong}
+\def\nsbot{\vbox
+ {\hrule height\cornerlong depth\cornerthick width\cornerthick}}
+
+% Parse an argument, then pass it to #1.
+% The argument can be delimited with [...] or with "..." or braces
+% or it can be a whole line.
+% #1 should be a macro which expects
+% an ordinary undelimited TeX argument.
+
+\def\parsearg #1{\let\next=#1\begingroup\obeylines\futurelet\temp\parseargx}
+
+\def\parseargx{%
+\ifx \obeyedspace\temp \aftergroup\parseargdiscardspace \else%
+\aftergroup \parseargline %
+\fi \endgroup}
+
+{\obeyspaces %
+\gdef\parseargdiscardspace {\begingroup\obeylines\futurelet\temp\parseargx}}
+
+\gdef\obeyedspace{\ }
+
+\def\parseargline{\begingroup \obeylines \parsearglinex}
+{\obeylines %
+\gdef\parsearglinex #1^^M{\endgroup \next {#1}}}
+
+\def\flushcr{\ifx\par\lisppar \def\next##1{}\else \let\next=\relax \fi \next}
+
+%% These are used to keep @begin/@end levels from running away
+%% Call \inENV within environments (after a \begingroup)
+\newif\ifENV \ENVfalse \def\inENV{\ifENV\relax\else\ENVtrue\fi}
+\def\ENVcheck{%
+\ifENV\errmessage{Still within an environment. Type Return to continue.}
+\endgroup\fi} % This is not perfect, but it should reduce lossage
+
+% @begin foo is the same as @foo, for now.
+\newhelp\EMsimple{Type <Return> to continue}
+
+\outer\def\begin{\parsearg\beginxxx}
+
+\def\beginxxx #1{%
+\expandafter\ifx\csname #1\endcsname\relax
+{\errhelp=\EMsimple \errmessage{Undefined command @begin #1}}\else
+\csname #1\endcsname\fi}
+
+%% @end foo executes the definition of \Efoo.
+%% foo can be delimited by doublequotes or brackets.
+
+\def\end{\parsearg\endxxx}
+
+\def\endxxx #1{%
+\expandafter\ifx\csname E#1\endcsname\relax
+\expandafter\ifx\csname #1\endcsname\relax
+\errmessage{Undefined command @end #1}\else
+\errorE{#1}\fi\fi
+\csname E#1\endcsname}
+\def\errorE#1{
+{\errhelp=\EMsimple \errmessage{@end #1 not within #1 environment}}}
+
+% Single-spacing is done by various environments.
+
+\newskip\singlespaceskip \singlespaceskip = \baselineskip
+\def\singlespace{%
+{\advance \baselineskip by -\singlespaceskip
+\kern \baselineskip}%
+\baselineskip=\singlespaceskip
+}
+
+%% Simple single-character @ commands
+
+% @@ prints an @
+% Kludge this until the fonts are right (grr).
+\def\@{{\tt \char '100}}
+
+% Define @` and @' to be the same as ` and '
+% but suppressing ligatures.
+\def\`{{`}}
+\def\'{{'}}
+
+% Used to generate quoted braces.
+
+\def\mylbrace {{\tt \char '173}}
+\def\myrbrace {{\tt \char '175}}
+\let\{=\mylbrace
+\let\}=\myrbrace
+
+% @: forces normal size whitespace following.
+\def\:{\spacefactor=1000 }
+
+% @* forces a line break.
+\def\*{\hfil\break\hbox{}\ignorespaces}
+
+% @. is an end-of-sentence period.
+\def\.{.\spacefactor=3000 }
+
+% @w prevents a word break
+\def\w #1{\hbox{#1}}
+
+% @group ... @end group forces ... to be all on one page.
+
+\def\group{\begingroup% \inENV ???
+\def \Egroup{\egroup\endgroup}
+\vbox\bgroup}
+
+% @need space-in-mils
+% forces a page break if there is not space-in-mils remaining.
+
+\newdimen\mil \mil=0.001in
+
+\def\need{\parsearg\needx}
+
+\def\needx #1{\par %
+\begingroup %
+\dimen0=\pagetotal %
+\advance \dimen0 by #1\mil %
+\ifdim \dimen0>\pagegoal \vfill\eject \fi %
+\endgroup}
+
+
+% @br forces paragraph break
+
+\let\br = \par
+
+% @dots{} output some dots
+
+\def\dots{$\ldots$}
+
+% @page forces the start of a new page
+
+\def\page{\par\vfill\supereject}
+
+% @exdent text....
+% outputs text on separate line in roman font, starting at standard page margin
+
+\def\exdent{\errmessage{@exdent in filled text}}
+ % @lisp, etc, define \exdent locally from \internalexdent
+
+{\obeyspaces
+\gdef\internalexdent{\parsearg\exdentzzz}}
+
+\def\exdentzzz #1{{\advance \leftskip by -\lispnarrowing
+\advance \hsize by -\leftskip
+\advance \hsize by -\rightskip
+\leftline{{\rm#1}}}}
+
+% @include file insert text of that file as input.
+
+\def\include{\parsearg\includezzz}
+\def\includezzz #1{{\def\thisfile{#1}\input #1
+}}
+
+\def\thisfile{}
+
+% @center line outputs that line, centered
+
+\def\center{\parsearg\centerzzz}
+\def\centerzzz #1{{\advance\hsize by -\leftskip
+\advance\hsize by -\rightskip
+\centerline{#1}}}
+
+% @sp n outputs n lines of vertical space
+
+\def\sp{\parsearg\spxxx}
+\def\spxxx #1{\par \vskip #1\baselineskip}
+
+% @comment ...line which is ignored...
+% @c is the same as @comment
+% @ignore ... @end ignore is another way to write a comment
+
+\def\comment{\catcode 64=\other \catcode 123=\other \catcode 125=\other%
+\parsearg \commentxxx}
+
+\def\commentxxx #1{\catcode 64=0 \catcode 123=1 \catcode 125=2 }
+
+\let\c=\comment
+
+% Prevent errors for section commands.
+% Used in @ignore and in failing conditionals.
+\def\ignoresections{%
+\let\chapter=\relax
+\let\unnumbered=\relax
+\let\unnumberedsec=\relax
+\let\unnumberedsection=\relax
+\let\unnumberedsubsec=\relax
+\let\unnumberedsubsection=\relax
+\let\unnumberedsubsubsec=\relax
+\let\unnumberedsubsubsection=\relax
+\let\section=\relax
+\let\subsec=\relax
+\let\subsubsec=\relax
+\let\subsection=\relax
+\let\subsubsection=\relax
+\let\appendix=\relax
+\let\appendixsec=\relax
+\let\appendixsection=\relax
+\let\appendixsubsec=\relax
+\let\appendixsubsection=\relax
+\let\appendixsubsubsec=\relax
+\let\appendixsubsubsection=\relax
+}
+
+\def\ignore{\begingroup\ignoresections\ignorexxx}
+\long\def\ignorexxx #1\end ignore{\endgroup\ignorespaces}
+
+\def\direntry{\begingroup\direntryxxx}
+\long\def\direntryxxx #1\end direntry{\endgroup\ignorespaces}
+
+% Conditionals to test whether a flag is set.
+
+\outer\def\ifset{\begingroup\ignoresections\parsearg\ifsetxxx}
+
+\def\ifsetxxx #1{\endgroup
+\expandafter\ifx\csname IF#1\endcsname\relax \let\temp=\ifsetfail
+\else \let\temp=\relax \fi
+\temp}
+\def\Eifset{}
+\def\ifsetfail{\begingroup\ignoresections\ifsetfailxxx}
+\long\def\ifsetfailxxx #1\end ifset{\endgroup\ignorespaces}
+
+\outer\def\ifclear{\begingroup\ignoresections\parsearg\ifclearxxx}
+
+\def\ifclearxxx #1{\endgroup
+\expandafter\ifx\csname IF#1\endcsname\relax \let\temp=\relax
+\else \let\temp=\ifclearfail \fi
+\temp}
+\def\Eifclear{}
+\def\ifclearfail{\begingroup\ignoresections\ifclearfailxxx}
+\long\def\ifclearfailxxx #1\end ifclear{\endgroup\ignorespaces}
+
+% Some texinfo constructs that are trivial in tex
+
+\def\iftex{}
+\def\Eiftex{}
+\def\ifinfo{\begingroup\ignoresections\ifinfoxxx}
+\long\def\ifinfoxxx #1\end ifinfo{\endgroup\ignorespaces}
+
+\long\def\menu #1\end menu{}
+\def\asis#1{#1}
+
+% @math means output in math mode.
+% We don't use $'s directly in the definition of \math because control
+% sequences like \math are expanded when the toc file is written. Then,
+% we read the toc file back, the $'s will be normal characters (as they
+% should be, according to the definition of Texinfo). So we must use a
+% control sequence to switch into and out of math mode.
+%
+% This isn't quite enough for @math to work properly in indices, but it
+% seems unlikely it will ever be needed there.
+%
+\let\implicitmath = $
+\def\math#1{\implicitmath #1\implicitmath}
+
+\def\node{\ENVcheck\parsearg\nodezzz}
+\def\nodezzz#1{\nodexxx [#1,]}
+\def\nodexxx[#1,#2]{\gdef\lastnode{#1}}
+\let\lastnode=\relax
+
+\def\donoderef{\ifx\lastnode\relax\else
+\expandafter\expandafter\expandafter\setref{\lastnode}\fi
+\let\lastnode=\relax}
+
+\def\unnumbnoderef{\ifx\lastnode\relax\else
+\expandafter\expandafter\expandafter\unnumbsetref{\lastnode}\fi
+\let\lastnode=\relax}
+
+\def\appendixnoderef{\ifx\lastnode\relax\else
+\expandafter\expandafter\expandafter\appendixsetref{\lastnode}\fi
+\let\lastnode=\relax}
+
+\let\refill=\relax
+
+% @setfilename is done at the beginning of every texinfo file.
+% So open here the files we need to have open while reading the input.
+% This makes it possible to make a .fmt file for texinfo.
+\def\setfilename{%
+ \readauxfile
+ \opencontents
+ \openindices
+ \fixbackslash % Turn off hack to swallow `\input texinfo'.
+ \global\let\setfilename=\comment % Ignore extra @setfilename cmds.
+ \comment % Ignore the actual filename.
+}
+
+\outer\def\bye{\pagealignmacro\tracingstats=1\ptexend}
+
+\def\inforef #1{\inforefzzz #1,,,,**}
+\def\inforefzzz #1,#2,#3,#4**{See Info file \file{\losespace#3{}}, node `\losespace#1{}'}
+\def\losespace #1{#1}
+
+\message{fonts,}
+
+% Font-change commands.
+
+%% Try out Computer Modern fonts at \magstephalf
+\font\tenrm=cmr10 scaled \magstephalf
+\font\tentt=cmtt10 scaled \magstephalf
+% Instead of cmb10, you many want to use cmbx10.
+% cmbx10 is a prettier font on its own, but cmb10
+% looks better when embedded in a line with cmr10.
+\font\tenbf=cmb10 scaled \magstephalf
+\font\tenit=cmti10 scaled \magstephalf
+\font\tensl=cmsl10 scaled \magstephalf
+\font\tensf=cmss10 scaled \magstephalf
+\def\li{\sf}
+\font\tensc=cmcsc10 scaled \magstephalf
+
+% Fonts for @defun, etc.
+\font\defbf=cmbx10 scaled \magstep1 %was 1314
+\font\deftt=cmtt10 scaled \magstep1
+\def\df{\let\tt=\deftt \defbf}
+
+% Font for title
+% There seems to have been a confusion: two definitions of this font.
+% It is not clear why, or which one is better.
+\font\titlerm = cmbx12 scaled \magstep3
+
+% Fonts for indices and small examples.
+% We actually use the slanted font rather than the italic,
+% because texinfo normally uses the slanted fonts for that.
+\font\ninett=cmtt9
+\font\indit=cmsl9 \font\indrm=cmr9
+\let\indtt=\ninett
+\def\indbf{\indrm} \def\indsl{\indit}
+\def\indexfonts{\let\it=\indit \let\sl=\indsl \let\bf=\indbf \let\rm=\indrm
+\let\tt=\indtt}
+
+% Fonts for headings
+\font\chaprm=cmbx12 scaled \magstep2
+\font\chapit=cmti12 scaled \magstep2
+\font\chapsl=cmsl12 scaled \magstep2
+\font\chaptt=cmtt12 scaled \magstep2
+\font\chapsf=cmss12 scaled \magstep2
+\let\chapbf=\chaprm
+
+\font\secrm=cmbx12 scaled \magstep1
+\font\secit=cmti12 scaled \magstep1
+\font\secsl=cmsl12 scaled \magstep1
+\font\sectt=cmtt12 scaled \magstep1
+\font\secsf=cmss12 scaled \magstep1
+\font\secbf=cmbx12 scaled \magstep1
+
+% \font\ssecrm=cmbx10 scaled \magstep1 % This size an fontlooked bad.
+% \font\ssecit=cmti10 scaled \magstep1 % The letters were too crowded.
+% \font\ssecsl=cmsl10 scaled \magstep1
+% \font\ssectt=cmtt10 scaled \magstep1
+% \font\ssecsf=cmss10 scaled \magstep1
+
+%\font\ssecrm=cmb10 scaled 1315 % Note the use of cmb rather than cmbx.
+%\font\ssecit=cmti10 scaled 1315 % Also, the size is a little larger than
+%\font\ssecsl=cmsl10 scaled 1315 % being scaled magstep1.
+%\font\ssectt=cmtt10 scaled 1315
+%\font\ssecsf=cmss10 scaled 1315
+
+%\let\ssecbf=\ssecrm
+
+\font\ssecrm=cmbx12 scaled \magstephalf
+\font\ssecit=cmti12 scaled \magstephalf
+\font\ssecsl=cmsl12 scaled \magstephalf
+\font\ssectt=cmtt12 scaled \magstephalf
+\font\ssecsf=cmss12 scaled \magstephalf
+\font\ssecbf=cmbx12 scaled \magstephalf
+
+
+\def\textfonts{\let\rm=\tenrm\let\it=\tenit\let\sl=\tensl\let\bf=\tenbf%
+\let\smallcaps=\tensc\let\sf=\tensf}
+\def\chapfonts{\let\rm=\chaprm\let\it=\chapit\let\sl=\chapsl\let\bf=\chapbf\let\tt=\chaptt\let\sf=\chapsf}
+\def\secfonts{\let\rm=\secrm\let\it=\secit\let\sl=\secsl\let\bf=\secbf\let\tt=\sectt\let\sf=\secsf}
+\def\subsecfonts{\let\rm=\ssecrm\let\it=\ssecit\let\sl=\ssecsl\let\bf=\ssecbf\let\tt=\ssectt\let\sf=\ssecsf}
+% Count depth in font-changes, for error checks
+\newcount\fontdepth \fontdepth=0
+
+% Font for table of contents.
+\font\truesecrm=cmr12
+
+%% Add scribe-like font environments, plus @l for inline lisp (usually sans
+%% serif) and @ii for TeX italic
+
+% \smartitalic{ARG} outputs arg in italics, followed by an italic correction
+% unless the following character is such as not to need one.
+\def\smartitalicx{\ifx\next,\else\ifx\next-\else\ifx\next.\else\/\fi\fi\fi}
+\def\smartitalic#1{{\sl #1}\futurelet\next\smartitalicx}
+
+\let\i=\smartitalic
+\let\var=\smartitalic
+\let\dfn=\smartitalic
+\let\emph=\smartitalic
+\let\cite=\smartitalic
+
+\def\b#1{{\bf #1}}
+\let\strong=\b
+
+\def\t#1{{\tt \rawbackslash \frenchspacing #1}\null}
+\let\ttfont = \t
+%\def\samp #1{`{\tt \rawbackslash \frenchspacing #1}'\null}
+\def\samp #1{`\tclose{#1}'\null}
+\def\key #1{{\tt \uppercase{#1}}\null}
+\def\ctrl #1{{\tt \rawbackslash \hat}#1}
+
+\let\file=\samp
+
+% @code is a modification of @t,
+% which makes spaces the same size as normal in the surrounding text.
+\newdimen\tclosesave
+\newdimen\tcloserm
+\def\tclose#1{{\rm \tcloserm=\fontdimen2\font \tt \tclosesave=\fontdimen2\font
+\fontdimen2\font=\tcloserm
+\def\ {{\fontdimen2\font=\tclosesave{} }}%
+ \rawbackslash \frenchspacing #1\fontdimen2\font=\tclosesave}\null}
+\let\code=\tclose
+%\let\exp=\tclose %Was temporary
+
+% @kbd is like @code, except that if the argument is just one @key command,
+% then @kbd has no effect.
+
+\def\xkey{\key}
+\def\kbdfoo#1#2#3\par{\def\one{#1}\def\three{#3}\def\threex{??}%
+\ifx\one\xkey\ifx\threex\three \key{#2}%
+\else\tclose{\look}\fi
+\else\tclose{\look}\fi}
+
+\def\kbd#1{\def\look{#1}\expandafter\kbdfoo\look??\par}
+
+\def\l#1{{\li #1}\null} %
+
+\def\r#1{{\rm #1}} % roman font
+% Use of \lowercase was suggested.
+\def\sc#1{{\smallcaps#1}} % smallcaps font
+\def\ii#1{{\it #1}} % italic font
+
+\message{page headings,}
+
+\newskip\titlepagetopglue \titlepagetopglue = 1.5in
+\newskip\titlepagebottomglue \titlepagebottomglue = 2pc
+
+% First the title page. Must do @settitle before @titlepage.
+\def\titlefont#1{{\titlerm #1}}
+
+\newtoks\realeverypar
+\newif\ifseenauthor
+\newif\iffinishedtitlepage
+
+\def\titlepage{\begingroup \parindent=0pt \textfonts
+ \let\subtitlerm=\tenrm
+% I deinstalled the following change because \cmr12 is undefined.
+% This change was not in the ChangeLog anyway. --rms.
+% \let\subtitlerm=\cmr12
+ \def\subtitlefont{\subtitlerm \normalbaselineskip = 13pt \normalbaselines}%
+ %
+ \font\authorrm = cmbx12 scaled \magstep1
+ \def\authorfont{\authorrm \normalbaselineskip = 16pt \normalbaselines}%
+ %
+ % Leave some space at the very top of the page.
+ \vglue\titlepagetopglue
+ %
+ % Now you can print the title using @title.
+ \def\title{\parsearg\titlezzz}%
+ \def\titlezzz##1{\leftline{\titlefont{##1}}
+ % print a rule at the page bottom also.
+ \finishedtitlepagefalse
+ \vskip4pt \hrule height 4pt \vskip4pt}%
+ % No rule at page bottom unless we print one at the top with @title.
+ \finishedtitlepagetrue
+ %
+ % Now you can put text using @subtitle.
+ \def\subtitle{\parsearg\subtitlezzz}%
+ \def\subtitlezzz##1{{\subtitlefont \rightline{##1}}}%
+ %
+ % @author should come last, but may come many times.
+ \def\author{\parsearg\authorzzz}%
+ \def\authorzzz##1{\ifseenauthor\else\vskip 0pt plus 1filll\seenauthortrue\fi
+ {\authorfont \leftline{##1}}}%
+ %
+ % Most title ``pages'' are actually two pages long, with space
+ % at the top of the second. We don't want the ragged left on the second.
+ \let\oldpage = \page
+ \def\page{%
+ \iffinishedtitlepage\else
+ \finishtitlepage
+ \fi
+ \oldpage
+ \let\page = \oldpage
+ \hbox{}}%
+% \def\page{\oldpage \hbox{}}
+}
+
+\def\Etitlepage{%
+ \iffinishedtitlepage\else
+ \finishtitlepage
+ \fi
+ \endgroup\page\HEADINGSon
+}
+
+\def\finishtitlepage{%
+ \vskip4pt \hrule height 2pt
+ \vskip\titlepagebottomglue
+ \finishedtitlepagetrue
+}
+
+%%% Set up page headings and footings.
+
+\let\thispage=\folio
+
+\newtoks \evenheadline % Token sequence for heading line of even pages
+\newtoks \oddheadline % Token sequence for heading line of odd pages
+\newtoks \evenfootline % Token sequence for footing line of even pages
+\newtoks \oddfootline % Token sequence for footing line of odd pages
+
+% Now make Tex use those variables
+\headline={{\textfonts\rm \ifodd\pageno \the\oddheadline \else \the\evenheadline \fi}}
+\footline={{\textfonts\rm \ifodd\pageno \the\oddfootline \else \the\evenfootline \fi}}
+
+% Commands to set those variables.
+% For example, this is what @headings on does
+% @evenheading @thistitle|@thispage|@thischapter
+% @oddheading @thischapter|@thispage|@thistitle
+% @evenfooting @thisfile||
+% @oddfooting ||@thisfile
+
+\def\evenheading{\parsearg\evenheadingxxx}
+\def\oddheading{\parsearg\oddheadingxxx}
+\def\everyheading{\parsearg\everyheadingxxx}
+
+\def\evenfooting{\parsearg\evenfootingxxx}
+\def\oddfooting{\parsearg\oddfootingxxx}
+\def\everyfooting{\parsearg\everyfootingxxx}
+
+{\catcode`\@=0 %
+
+\gdef\evenheadingxxx #1{\evenheadingyyy #1@|@|@|@|\finish}
+\gdef\evenheadingyyy #1@|#2@|#3@|#4\finish{%
+\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\oddheadingxxx #1{\oddheadingyyy #1@|@|@|@|\finish}
+\gdef\oddheadingyyy #1@|#2@|#3@|#4\finish{%
+\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\everyheadingxxx #1{\everyheadingyyy #1@|@|@|@|\finish}
+\gdef\everyheadingyyy #1@|#2@|#3@|#4\finish{%
+\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}
+\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\evenfootingxxx #1{\evenfootingyyy #1@|@|@|@|\finish}
+\gdef\evenfootingyyy #1@|#2@|#3@|#4\finish{%
+\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\oddfootingxxx #1{\oddfootingyyy #1@|@|@|@|\finish}
+\gdef\oddfootingyyy #1@|#2@|#3@|#4\finish{%
+\global\oddfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\everyfootingxxx #1{\everyfootingyyy #1@|@|@|@|\finish}
+\gdef\everyfootingyyy #1@|#2@|#3@|#4\finish{%
+\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}
+\global\oddfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+%
+}% unbind the catcode of @.
+
+% @headings double turns headings on for double-sided printing.
+% @headings single turns headings on for single-sided printing.
+% @headings off turns them off.
+% @headings on same as @headings double, retained for compatibility.
+% By default, they are off.
+
+\def\headings #1 {\csname HEADINGS#1\endcsname}
+
+\def\HEADINGSoff{
+\global\evenheadline={\hfil} \global\evenfootline={\hfil}
+\global\oddheadline={\hfil} \global\oddfootline={\hfil}}
+\HEADINGSoff
+% When we turn headings on, set the page number to 1.
+% For double-sided printing, put current file name in lower left corner,
+% chapter name on inside top of right hand pages, document
+% title on inside top of left hand pages, and page numbers on outside top
+% edge of all pages.
+\def\HEADINGSdouble{
+%\pagealignmacro
+\global\pageno=1
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\folio\hfil\thistitle}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+}
+% For single-sided printing, chapter title goes across top left of page,
+% page number on top right.
+\def\HEADINGSsingle{
+%\pagealignmacro
+\global\pageno=1
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\thischapter\hfil\folio}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+}
+\def\HEADINGSon{\HEADINGSdouble}
+
+% Subroutines used in generating headings
+% Produces Day Month Year style of output.
+\def\today{\number\day\space
+\ifcase\month\or
+January\or February\or March\or April\or May\or June\or
+July\or August\or September\or October\or November\or December\fi
+\space\number\year}
+
+% Use this if you want the Month Day, Year style of output.
+%\def\today{\ifcase\month\or
+%January\or February\or March\or April\or May\or June\or
+%July\or August\or September\or October\or November\or December\fi
+%\space\number\day, \number\year}
+
+% @settitle line... specifies the title of the document, for headings
+% It generates no output of its own
+
+\def\thistitle{No Title}
+\def\settitle{\parsearg\settitlezzz}
+\def\settitlezzz #1{\gdef\thistitle{#1}}
+
+\message{tables,}
+
+% @tabs -- simple alignment
+
+% These don't work. For one thing, \+ is defined as outer.
+% So these macros cannot even be defined.
+
+%\def\tabs{\parsearg\tabszzz}
+%\def\tabszzz #1{\settabs\+#1\cr}
+%\def\tabline{\parsearg\tablinezzz}
+%\def\tablinezzz #1{\+#1\cr}
+%\def\&{&}
+
+% Tables -- @table, @ftable, @item(x), @kitem(x), @xitem(x).
+
+% default indentation of table text
+\newdimen\tableindent \tableindent=.8in
+% default indentation of @itemize and @enumerate text
+\newdimen\itemindent \itemindent=.3in
+% margin between end of table item and start of table text.
+\newdimen\itemmargin \itemmargin=.1in
+
+% used internally for \itemindent minus \itemmargin
+\newdimen\itemmax
+
+% Note @table and @ftable define @item, @itemx, etc., with these defs.
+% They also define \itemindex
+% to index the item name in whatever manner is desired (perhaps none).
+
+\def\internalBitem{\smallbreak \parsearg\itemzzz}
+\def\internalBitemx{\par \parsearg\itemzzz}
+
+\def\internalBxitem "#1"{\def\xitemsubtopix{#1} \smallbreak \parsearg\xitemzzz}
+\def\internalBxitemx "#1"{\def\xitemsubtopix{#1} \par \parsearg\xitemzzz}
+
+\def\internalBkitem{\smallbreak \parsearg\kitemzzz}
+\def\internalBkitemx{\par \parsearg\kitemzzz}
+
+\def\kitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \lastfunction}}\itemzzz {#1}}
+
+\def\xitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \xitemsubtopic}}\itemzzz {#1}}
+
+\def\itemzzz #1{\begingroup %
+\advance \hsize by -\rightskip %
+\advance \hsize by -\leftskip %
+\setbox0=\hbox{\itemfont{#1}}%
+\itemindex{#1}%
+\parskip=0in %
+\noindent %
+\ifdim \wd0>\itemmax %
+\vadjust{\penalty 10000}%
+\hbox to \hsize{\hskip -\tableindent\box0\hss}\ %
+\else %
+\hbox to 0pt{\hskip -\tableindent\box0\hss}%
+\fi %
+\endgroup %
+}
+
+\def\item{\errmessage{@item while not in a table}}
+\def\itemx{\errmessage{@itemx while not in a table}}
+\def\kitem{\errmessage{@kitem while not in a table}}
+\def\kitemx{\errmessage{@kitemx while not in a table}}
+\def\xitem{\errmessage{@xitem while not in a table}}
+\def\xitemx{\errmessage{@xitemx while not in a table}}
+
+%% Contains a kludge to get @end[description] to work
+\def\description{\tablez{\dontindex}{1}{}{}{}{}}
+
+\def\table{\begingroup\inENV\obeylines\obeyspaces\tablex}
+{\obeylines\obeyspaces%
+\gdef\tablex #1^^M{%
+\tabley\dontindex#1 \endtabley}}
+
+\def\ftable{\begingroup\inENV\obeylines\obeyspaces\ftablex}
+{\obeylines\obeyspaces%
+\gdef\ftablex #1^^M{%
+\tabley\fnitemindex#1 \endtabley}}
+
+\def\dontindex #1{}
+\def\fnitemindex #1{\doind {fn}{\code{#1}}}%
+
+{\obeyspaces %
+\gdef\tabley#1#2 #3 #4 #5 #6 #7\endtabley{\endgroup%
+\tablez{#1}{#2}{#3}{#4}{#5}{#6}}}
+
+\def\tablez #1#2#3#4#5#6{%
+\aboveenvbreak %
+\begingroup %
+\def\Edescription{\Etable}% Neccessary kludge.
+\let\itemindex=#1%
+\ifnum 0#3>0 \advance \leftskip by #3\mil \fi %
+\ifnum 0#4>0 \tableindent=#4\mil \fi %
+\ifnum 0#5>0 \advance \rightskip by #5\mil \fi %
+\def\itemfont{#2}%
+\itemmax=\tableindent %
+\advance \itemmax by -\itemmargin %
+\advance \leftskip by \tableindent %
+\parindent = 0pt
+\parskip = \smallskipamount
+\ifdim \parskip=0pt \parskip=2pt \fi%
+\def\Etable{\endgraf\endgroup\afterenvbreak}%
+\let\item = \internalBitem %
+\let\itemx = \internalBitemx %
+\let\kitem = \internalBkitem %
+\let\kitemx = \internalBkitemx %
+\let\xitem = \internalBxitem %
+\let\xitemx = \internalBxitemx %
+}
+
+% This is the counter used by @enumerate, which is really @itemize
+
+\newcount \itemno
+
+\def\itemize{\parsearg\itemizezzz}
+
+\def\itemizezzz #1{\itemizey {#1}{\Eitemize}}
+
+\def\itemizey #1#2{%
+\aboveenvbreak %
+\begingroup %
+\itemno = 0 %
+\itemmax=\itemindent %
+\advance \itemmax by -\itemmargin %
+\advance \leftskip by \itemindent %
+\parindent = 0pt
+\parskip = \smallskipamount
+\ifdim \parskip=0pt \parskip=2pt \fi%
+\def#2{\endgraf\endgroup\afterenvbreak}%
+\def\itemcontents{#1}%
+\let\item=\itemizeitem}
+
+\def\bullet{$\ptexbullet$}
+\def\minus{$-$}
+
+% Set sfcode to normal for the chars that usually have another value.
+% These are `.?!:;,'
+\def\frenchspacing{\sfcode46=1000 \sfcode63=1000 \sfcode33=1000
+ \sfcode58=1000 \sfcode59=1000 \sfcode44=1000 }
+
+\def\enumerate{\itemizey{\the\itemno.}\Eenumerate\flushcr}
+
+% Definition of @item while inside @itemize.
+
+\def\itemizeitem{%
+\advance\itemno by 1
+{\let\par=\endgraf \smallbreak}%
+\ifhmode \errmessage{\in hmode at itemizeitem}\fi
+{\parskip=0in \hskip 0pt
+\hbox to 0pt{\hss \itemcontents\hskip \itemmargin}%
+\vadjust{\penalty 300}}%
+\flushcr}
+
+\message{indexing,}
+% Index generation facilities
+
+% Define \newwrite to be identical to plain tex's \newwrite
+% except not \outer, so it can be used within \newindex.
+{\catcode`\@=11
+\gdef\newwrite{\alloc@7\write\chardef\sixt@@n}}
+
+% \newindex {foo} defines an index named foo.
+% It automatically defines \fooindex such that
+% \fooindex ...rest of line... puts an entry in the index foo.
+% It also defines \fooindfile to be the number of the output channel for
+% the file that accumulates this index. The file's extension is foo.
+% The name of an index should be no more than 2 characters long
+% for the sake of vms.
+
+\def\newindex #1{
+\expandafter\newwrite \csname#1indfile\endcsname% Define number for output file
+\openout \csname#1indfile\endcsname \jobname.#1 % Open the file
+\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex
+\noexpand\doindex {#1}}
+}
+
+% @defindex foo == \newindex{foo}
+
+\def\defindex{\parsearg\newindex}
+
+% Define @defcodeindex, like @defindex except put all entries in @code.
+
+\def\newcodeindex #1{
+\expandafter\newwrite \csname#1indfile\endcsname% Define number for output file
+\openout \csname#1indfile\endcsname \jobname.#1 % Open the file
+\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex
+\noexpand\docodeindex {#1}}
+}
+
+\def\defcodeindex{\parsearg\newcodeindex}
+
+% @synindex foo bar makes index foo feed into index bar.
+% Do this instead of @defindex foo if you don't want it as a separate index.
+\def\synindex #1 #2 {%
+\expandafter\let\expandafter\synindexfoo\expandafter=\csname#2indfile\endcsname
+\expandafter\let\csname#1indfile\endcsname=\synindexfoo
+\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex
+\noexpand\doindex {#2}}%
+}
+
+% @syncodeindex foo bar similar, but put all entries made for index foo
+% inside @code.
+\def\syncodeindex #1 #2 {%
+\expandafter\let\expandafter\synindexfoo\expandafter=\csname#2indfile\endcsname
+\expandafter\let\csname#1indfile\endcsname=\synindexfoo
+\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex
+\noexpand\docodeindex {#2}}%
+}
+
+% Define \doindex, the driver for all \fooindex macros.
+% Argument #1 is generated by the calling \fooindex macro,
+% and it is "foo", the name of the index.
+
+% \doindex just uses \parsearg; it calls \doind for the actual work.
+% This is because \doind is more useful to call from other macros.
+
+% There is also \dosubind {index}{topic}{subtopic}
+% which makes an entry in a two-level index such as the operation index.
+
+\def\doindex#1{\edef\indexname{#1}\parsearg\singleindexer}
+\def\singleindexer #1{\doind{\indexname}{#1}}
+
+% like the previous two, but they put @code around the argument.
+\def\docodeindex#1{\edef\indexname{#1}\parsearg\singlecodeindexer}
+\def\singlecodeindexer #1{\doind{\indexname}{\code{#1}}}
+
+\def\indexdummies{%
+\def\_{{\realbackslash normalunderscore}}%
+\def\w{\realbackslash w }%
+\def\bf{\realbackslash bf }%
+\def\rm{\realbackslash rm }%
+\def\sl{\realbackslash sl }%
+\def\sf{\realbackslash sf}%
+\def\tt{\realbackslash tt}%
+\def\gtr{\realbackslash gtr}%
+\def\less{\realbackslash less}%
+\def\hat{\realbackslash hat}%
+\def\char{\realbackslash char}%
+\def\TeX{\realbackslash TeX}%
+\def\dots{\realbackslash dots }%
+\def\copyright{\realbackslash copyright }%
+\def\tclose##1{\realbackslash tclose {##1}}%
+\def\code##1{\realbackslash code {##1}}%
+\def\samp##1{\realbackslash samp {##1}}%
+\def\t##1{\realbackslash r {##1}}%
+\def\r##1{\realbackslash r {##1}}%
+\def\i##1{\realbackslash i {##1}}%
+\def\b##1{\realbackslash b {##1}}%
+\def\cite##1{\realbackslash cite {##1}}%
+\def\key##1{\realbackslash key {##1}}%
+\def\file##1{\realbackslash file {##1}}%
+\def\var##1{\realbackslash var {##1}}%
+\def\kbd##1{\realbackslash kbd {##1}}%
+}
+
+% \indexnofonts no-ops all font-change commands.
+% This is used when outputting the strings to sort the index by.
+\def\indexdummyfont#1{#1}
+\def\indexdummytex{TeX}
+\def\indexdummydots{...}
+
+\def\indexnofonts{%
+\let\w=\indexdummyfont
+\let\t=\indexdummyfont
+\let\r=\indexdummyfont
+\let\i=\indexdummyfont
+\let\b=\indexdummyfont
+\let\emph=\indexdummyfont
+\let\strong=\indexdummyfont
+\let\cite=\indexdummyfont
+\let\sc=\indexdummyfont
+%Don't no-op \tt, since it isn't a user-level command
+% and is used in the definitions of the actuve chars like <, >, |...
+%\let\tt=\indexdummyfont
+\let\tclose=\indexdummyfont
+\let\code=\indexdummyfont
+\let\file=\indexdummyfont
+\let\samp=\indexdummyfont
+\let\kbd=\indexdummyfont
+\let\key=\indexdummyfont
+\let\var=\indexdummyfont
+\let\TeX=\indexdummytex
+\let\dots=\indexdummydots
+}
+
+% To define \realbackslash, we must make \ not be an escape.
+% We must first make another character (@) an escape
+% so we do not become unable to do a definition.
+
+{\catcode`\@=0 \catcode`\\=\other
+@gdef@realbackslash{\}}
+
+\let\indexbackslash=0 %overridden during \printindex.
+
+\def\doind #1#2{%
+{\indexdummies % Must do this here, since \bf, etc expand at this stage
+\count10=\lastpenalty %
+\escapechar=`\\%
+{\let\folio=0% Expand all macros now EXCEPT \folio
+\def\rawbackslashxx{\indexbackslash}% \indexbackslash isn't defined now
+% so it will be output as is; and it will print as backslash in the indx.
+%
+% Now process the index-string once, with all font commands turned off,
+% to get the string to sort the index by.
+{\indexnofonts
+\xdef\temp1{#2}%
+}%
+% Now produce the complete index entry. We process the index-string again,
+% this time with font commands expanded, to get what to print in the index.
+\edef\temp{%
+\write \csname#1indfile\endcsname{%
+\realbackslash entry {\temp1}{\folio}{#2}}}%
+\temp }%
+\penalty\count10}}
+
+\def\dosubind #1#2#3{%
+{\indexdummies % Must do this here, since \bf, etc expand at this stage
+\count10=\lastpenalty %
+\escapechar=`\\%
+{\let\folio=0%
+\def\rawbackslashxx{\indexbackslash}%
+%
+% Now process the index-string once, with all font commands turned off,
+% to get the string to sort the index by.
+{\indexnofonts
+\xdef\temp1{#2 #3}%
+}%
+% Now produce the complete index entry. We process the index-string again,
+% this time with font commands expanded, to get what to print in the index.
+\edef\temp{%
+\write \csname#1indfile\endcsname{%
+\realbackslash entry {\temp1}{\folio}{#2}{#3}}}%
+\temp }%
+\penalty\count10}}
+
+% The index entry written in the file actually looks like
+% \entry {sortstring}{page}{topic}
+% or
+% \entry {sortstring}{page}{topic}{subtopic}
+% The texindex program reads in these files and writes files
+% containing these kinds of lines:
+% \initial {c}
+% before the first topic whose initial is c
+% \entry {topic}{pagelist}
+% for a topic that is used without subtopics
+% \primary {topic}
+% for the beginning of a topic that is used with subtopics
+% \secondary {subtopic}{pagelist}
+% for each subtopic.
+
+% Define the user-accessible indexing commands
+% @findex, @vindex, @kindex, @cindex.
+
+\def\findex {\fnindex}
+\def\kindex {\kyindex}
+\def\cindex {\cpindex}
+\def\vindex {\vrindex}
+\def\tindex {\tpindex}
+\def\pindex {\pgindex}
+
+\def\cindexsub {\begingroup\obeylines\cindexsub}
+{\obeylines %
+\gdef\cindexsub "#1" #2^^M{\endgroup %
+\dosubind{cp}{#2}{#1}}}
+
+% Define the macros used in formatting output of the sorted index material.
+
+% This is what you call to cause a particular index to get printed.
+% Write
+% @unnumbered Function Index
+% @printindex fn
+
+\def\printindex{\parsearg\doprintindex}
+
+\def\doprintindex#1{\tex %
+\catcode`\%=\other\catcode`\&=\other\catcode`\#=\other
+\catcode`\$=\other\catcode`\_=\other
+\catcode`\~=\other
+% The following don't help, since the chars were translated
+% when the raw index was written, and their fonts were discarded
+% due to \indexnofonts.
+%\catcode`\"=\active
+%\catcode`\^=\active
+%\catcode`\_=\active
+%\catcode`\|=\active
+%\catcode`\<=\active
+%\catcode`\>=\active
+\def\indexbackslash{\rawbackslashxx}
+\indexfonts\rm \tolerance=9500 \advance\baselineskip -1pt
+\begindoublecolumns
+\openin 1 \jobname.#1s
+\ifeof 1 \else \closein 1 \input \jobname.#1s
+\fi
+\enddoublecolumns
+\Etex}
+
+% These macros are used by the sorted index file itself.
+% Change them to control the appearance of the index.
+
+% Same as \bigskipamount except no shrink.
+% \balancecolumns gets confused if there is any shrink.
+\newskip\initialskipamount \initialskipamount 12pt plus4pt
+
+\outer\def\initial #1{%
+{\let\tentt=\sectt \let\tt=\sectt \let\sf=\sectt
+\ifdim\lastskip<\initialskipamount
+\removelastskip \penalty-200 \vskip \initialskipamount\fi
+\line{\secbf#1\hfill}\kern 2pt\penalty10000}}
+
+\outer\def\entry #1#2{
+{\parfillskip=0in \parskip=0in \parindent=0in
+\hangindent=1in \hangafter=1%
+\noindent\hbox{#1}\indexdotfill #2\par
+}}
+
+% Like \dotfill except takes at least 1 em.
+\def\indexdotfill{\cleaders\hbox{$\mathsurround=0pt \mkern1.5mu . \mkern1.5mu$}\hskip 1em plus 1fill}
+
+\def\primary #1{\line{#1\hfil}}
+
+\newskip\secondaryindent \secondaryindent=0.5cm
+
+\def\secondary #1#2{
+{\parfillskip=0in \parskip=0in
+\hangindent =1in \hangafter=1
+\noindent\hskip\secondaryindent\hbox{#1}\indexdotfill #2\par
+}}
+
+%% Define two-column mode, which is used in indexes.
+%% Adapted from the TeXBook, page 416
+\catcode `\@=11
+
+\newbox\partialpage
+
+\newdimen\doublecolumnhsize \doublecolumnhsize = 3.11in
+\newdimen\doublecolumnvsize \doublecolumnvsize = 19.1in
+\newdimen\availdimen@
+
+\def\begindoublecolumns{\begingroup
+ \output={\global\setbox\partialpage=\vbox{\unvbox255\kern -\topskip \kern \baselineskip}}\eject
+ \output={\doublecolumnout} \hsize=\doublecolumnhsize \vsize=\doublecolumnvsize}
+\def\enddoublecolumns{\output={\balancecolumns}\eject
+ \endgroup \pagegoal=\vsize}
+
+\def\doublecolumnout{\splittopskip=\topskip \splitmaxdepth=\maxdepth
+ \dimen@=\pageheight \advance\dimen@ by-\ht\partialpage
+ \setbox0=\vsplit255 to\dimen@ \setbox2=\vsplit255 to\dimen@
+ \onepageout\pagesofar \unvbox255 \penalty\outputpenalty}
+\def\pagesofar{\unvbox\partialpage %
+ \hsize=\doublecolumnhsize % have to restore this since output routine
+% changes it to set cropmarks (P. A. MacKay, 12 Nov. 1986)
+ \wd0=\hsize \wd2=\hsize \hbox to\pagewidth{\box0\hfil\box2}}
+\def\balancecolumns{%
+% Unset the glue.
+ \setbox255=\vbox{\unvbox255}
+ \dimen@=\ht255
+ \advance\dimen@ by\topskip \advance\dimen@ by-\baselineskip
+ \divide\dimen@ by2
+ \availdimen@=\pageheight \advance\availdimen@ by-\ht\partialpage
+% If the remaining data is too big for one page,
+% output one page normally, then work with what remains.
+ \ifdim \dimen@>\availdimen@
+ {
+ \splittopskip=\topskip \splitmaxdepth=\maxdepth
+ \dimen@=\pageheight \advance\dimen@ by-\ht\partialpage
+ \setbox0=\vsplit255 to\dimen@ \setbox2=\vsplit255 to\dimen@
+ \onepageout\pagesofar
+ }
+% Recompute size of what remains, in case we just output some of it.
+ \dimen@=\ht255
+ \advance\dimen@ by\topskip \advance\dimen@ by-\baselineskip
+ \divide\dimen@ by2
+ \fi
+ \setbox0=\vbox{\unvbox255}
+ \splittopskip=\topskip
+ {\vbadness=10000 \loop \global\setbox3=\copy0
+ \global\setbox1=\vsplit3 to\dimen@
+ \ifdim\ht3>\dimen@ \global\advance\dimen@ by1pt \repeat}
+ \setbox0=\vbox to\dimen@{\unvbox1} \setbox2=\vbox to\dimen@{\unvbox3}
+ \pagesofar}
+
+\catcode `\@=\other
+\message{sectioning,}
+% Define chapters, sections, etc.
+
+\newcount \chapno
+\newcount \secno
+\newcount \subsecno
+\newcount \subsubsecno
+
+% This counter is funny since it counts through charcodes of letters A, B, ...
+\newcount \appendixno \appendixno = `\@
+\def\appendixletter{\char\the\appendixno}
+
+\newwrite \contentsfile
+% This is called from \setfilename.
+\def\opencontents{\openout \contentsfile = \jobname.toc}
+
+% Each @chapter defines this as the name of the chapter.
+% page headings and footings can use it. @section does likewise
+
+\def\thischapter{} \def\thissection{}
+\def\seccheck#1{\if \pageno<0 %
+\errmessage{@#1 not allowed after generating table of contents}\fi
+%
+}
+
+\def\chapternofonts{%
+\let\rawbackslash=\relax%
+\let\frenchspacing=\relax%
+\def\TeX{\realbackslash TeX}
+\def\dots{\realbackslash dots}
+\def\copyright{\realbackslash copyright}
+\def\tt{\realbackslash tt}
+\def\bf{\realbackslash bf }
+\def\w{\realbackslash w}
+\def\less{\realbackslash less}
+\def\gtr{\realbackslash gtr}
+\def\hat{\realbackslash hat}
+\def\char{\realbackslash char}
+\def\tclose##1{\realbackslash tclose {##1}}
+\def\code##1{\realbackslash code {##1}}
+\def\samp##1{\realbackslash samp {##1}}
+\def\r##1{\realbackslash r {##1}}
+\def\b##1{\realbackslash b {##1}}
+\def\key##1{\realbackslash key {##1}}
+\def\file##1{\realbackslash file {##1}}
+\def\kbd##1{\realbackslash kbd {##1}}
+% These are redefined because @smartitalic wouldn't work inside xdef.
+\def\i##1{\realbackslash i {##1}}
+\def\cite##1{\realbackslash cite {##1}}
+\def\var##1{\realbackslash var {##1}}
+\def\emph##1{\realbackslash emph {##1}}
+\def\dfn##1{\realbackslash dfn {##1}}
+}
+
+\outer\def\chapter{\parsearg\chapterzzz}
+\def\chapterzzz #1{\seccheck{chapter}%
+\secno=0 \subsecno=0 \subsubsecno=0 \global\advance \chapno by 1 \message{Chapter \the\chapno}%
+\chapmacro {#1}{\the\chapno}%
+\gdef\thissection{#1}%
+\gdef\thischaptername{#1}%
+% We don't substitute the actual chapter name into \thischapter
+% because we don't want its macros evaluated now.
+\xdef\thischapter{Chapter \the\chapno: \noexpand\thischaptername}%
+{\chapternofonts%
+\edef\temp{{\realbackslash chapentry {#1}{\the\chapno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\donoderef %
+}}
+
+\outer\def\appendix{\parsearg\appendixzzz}
+\def\appendixzzz #1{\seccheck{appendix}%
+\secno=0 \subsecno=0 \subsubsecno=0 \global\advance \appendixno by 1 \message{Appendix \appendixletter}%
+\chapmacro {#1}{Appendix \appendixletter}%
+\gdef\thissection{#1}%
+\gdef\thischaptername{#1}%
+\xdef\thischapter{Appendix \appendixletter: \noexpand\thischaptername}%
+{\chapternofonts%
+\edef\temp{{\realbackslash chapentry {#1}{Appendix \appendixletter}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\appendixnoderef %
+}}
+
+\outer\def\unnumbered{\parsearg\unnumberedzzz}
+\def\unnumberedzzz #1{\seccheck{unnumbered}%
+\secno=0 \subsecno=0 \subsubsecno=0 \message{(#1)}
+\unnumbchapmacro {#1}%
+\gdef\thischapter{#1}\gdef\thissection{#1}%
+{\chapternofonts%
+\edef\temp{{\realbackslash unnumbchapentry {#1}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\unnumbnoderef %
+}}
+
+\outer\def\section{\parsearg\sectionzzz}
+\def\sectionzzz #1{\seccheck{section}%
+\subsecno=0 \subsubsecno=0 \global\advance \secno by 1 %
+\gdef\thissection{#1}\secheading {#1}{\the\chapno}{\the\secno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash secentry %
+{#1}{\the\chapno}{\the\secno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\donoderef %
+\penalty 10000 %
+}}
+
+\outer\def\appendixsection{\parsearg\appendixsectionzzz}
+\outer\def\appendixsec{\parsearg\appendixsectionzzz}
+\def\appendixsectionzzz #1{\seccheck{appendixsection}%
+\subsecno=0 \subsubsecno=0 \global\advance \secno by 1 %
+\gdef\thissection{#1}\secheading {#1}{\appendixletter}{\the\secno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash secentry %
+{#1}{\appendixletter}{\the\secno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\appendixnoderef %
+\penalty 10000 %
+}}
+
+\outer\def\unnumberedsec{\parsearg\unnumberedseczzz}
+\def\unnumberedseczzz #1{\seccheck{unnumberedsec}%
+\plainsecheading {#1}\gdef\thissection{#1}%
+{\chapternofonts%
+\edef\temp{{\realbackslash unnumbsecentry{#1}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\unnumbnoderef %
+\penalty 10000 %
+}}
+
+\outer\def\subsection{\parsearg\subsectionzzz}
+\def\subsectionzzz #1{\seccheck{subsection}%
+\gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 %
+\subsecheading {#1}{\the\chapno}{\the\secno}{\the\subsecno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash subsecentry %
+{#1}{\the\chapno}{\the\secno}{\the\subsecno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\donoderef %
+\penalty 10000 %
+}}
+
+\outer\def\appendixsubsec{\parsearg\appendixsubseczzz}
+\def\appendixsubseczzz #1{\seccheck{appendixsubsec}%
+\gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 %
+\subsecheading {#1}{\appendixletter}{\the\secno}{\the\subsecno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash subsecentry %
+{#1}{\appendixletter}{\the\secno}{\the\subsecno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\appendixnoderef %
+\penalty 10000 %
+}}
+
+\outer\def\unnumberedsubsec{\parsearg\unnumberedsubseczzz}
+\def\unnumberedsubseczzz #1{\seccheck{unnumberedsubsec}%
+\plainsecheading {#1}\gdef\thissection{#1}%
+{\chapternofonts%
+\edef\temp{{\realbackslash unnumbsubsecentry{#1}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\unnumbnoderef %
+\penalty 10000 %
+}}
+
+\outer\def\subsubsection{\parsearg\subsubsectionzzz}
+\def\subsubsectionzzz #1{\seccheck{subsubsection}%
+\gdef\thissection{#1}\global\advance \subsubsecno by 1 %
+\subsubsecheading {#1}{\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash subsubsecentry %
+{#1}{\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}{\noexpand\folio}}}%\
+\escapechar=`\\%
+\write \contentsfile \temp %
+\donoderef %
+\penalty 10000 %
+}}
+
+\outer\def\appendixsubsubsec{\parsearg\appendixsubsubseczzz}
+\def\appendixsubsubseczzz #1{\seccheck{appendixsubsubsec}%
+\gdef\thissection{#1}\global\advance \subsubsecno by 1 %
+\subsubsecheading {#1}{\appendixletter}{\the\secno}{\the\subsecno}{\the\subsubsecno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash subsubsecentry{#1}%
+{\appendixletter}{\the\secno}{\the\subsecno}{\the\subsubsecno}{\noexpand\folio}}}%\
+\escapechar=`\\%
+\write \contentsfile \temp %
+\appendixnoderef %
+\penalty 10000 %
+}}
+
+\outer\def\unnumberedsubsubsec{\parsearg\unnumberedsubsubseczzz}
+\def\unnumberedsubsubseczzz #1{\seccheck{unnumberedsubsubsec}%
+\plainsecheading {#1}\gdef\thissection{#1}%
+{\chapternofonts%
+\edef\temp{{\realbackslash unnumbsubsubsecentry{#1}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\unnumbnoderef %
+\penalty 10000 %
+}}
+
+% These are variants which are not "outer", so they can appear in @ifinfo.
+\def\infounnumbered{\parsearg\unnumberedzzz}
+\def\infounnumberedsec{\parsearg\unnumberedseczzz}
+\def\infounnumberedsubsec{\parsearg\unnumberedsubseczzz}
+\def\infounnumberedsubsubsec{\parsearg\unnumberedsubsubseczzz}
+
+\def\infoappendix{\parsearg\appendixzzz}
+\def\infoappendixsec{\parsearg\appendixseczzz}
+\def\infoappendixsubsec{\parsearg\appendixsubseczzz}
+\def\infoappendixsubsubsec{\parsearg\appendixsubsubseczzz}
+
+\def\infochapter{\parsearg\chapterzzz}
+\def\infosection{\parsearg\sectionzzz}
+\def\infosubsection{\parsearg\subsectionzzz}
+\def\infosubsubsection{\parsearg\subsubsectionzzz}
+
+% Define @majorheading, @heading and @subheading
+
+\def\majorheading{\parsearg\majorheadingzzz}
+\def\majorheadingzzz #1{%
+{\advance\chapheadingskip by 10pt \chapbreak }%
+{\chapfonts \line{\rm #1\hfill}}\bigskip \par\penalty 200}
+
+\def\chapheading{\parsearg\chapheadingzzz}
+\def\chapheadingzzz #1{\chapbreak %
+{\chapfonts \line{\rm #1\hfill}}\bigskip \par\penalty 200}
+
+\def\heading{\parsearg\secheadingi}
+
+\def\subheading{\parsearg\subsecheadingi}
+
+\def\subsubheading{\parsearg\subsubsecheadingi}
+
+% These macros generate a chapter, section, etc. heading only
+% (including whitespace, linebreaking, etc. around it),
+% given all the information in convenient, parsed form.
+
+%%% Args are the skip and penalty (usually negative)
+\def\dobreak#1#2{\par\ifdim\lastskip<#1\removelastskip\penalty#2\vskip#1\fi}
+
+\def\setchapterstyle #1 {\csname CHAPF#1\endcsname}
+
+%%% Define plain chapter starts, and page on/off switching for it
+% Parameter controlling skip before chapter headings (if needed)
+
+\newskip \chapheadingskip \chapheadingskip = 30pt plus 8pt minus 4pt
+
+\def\chapbreak{\dobreak \chapheadingskip {-4000}}
+\def\chappager{\par\vfill\supereject}
+\def\chapoddpage{\chappager \ifodd\pageno \else \hbox to 0pt{} \chappager\fi}
+
+\def\setchapternewpage #1 {\csname CHAPPAG#1\endcsname}
+
+\def\CHAPPAGoff{
+\global\let\pchapsepmacro=\chapbreak
+\global\let\pagealignmacro=\chappager}
+
+\def\CHAPPAGon{
+\global\let\pchapsepmacro=\chappager
+\global\let\pagealignmacro=\chappager
+\global\def\HEADINGSon{\HEADINGSsingle}}
+
+\def\CHAPPAGodd{
+\global\let\pchapsepmacro=\chapoddpage
+\global\let\pagealignmacro=\chapoddpage
+\global\def\HEADINGSon{\HEADINGSdouble}}
+
+\CHAPPAGon
+
+\def\CHAPFplain{
+\global\let\chapmacro=\chfplain
+\global\let\unnumbchapmacro=\unnchfplain}
+
+\def\chfplain #1#2{%
+ \pchapsepmacro
+ {%
+ \chapfonts
+ \leftline{\rm #2\enspace #1}%
+ }%
+ \bigskip
+ \penalty5000
+}
+
+\def\unnchfplain #1{%
+\pchapsepmacro %
+{\chapfonts \line{\rm #1\hfill}}\bigskip \par\penalty 10000 %
+}
+\CHAPFplain % The default
+
+\def\unnchfopen #1{%
+\chapoddpage {\chapfonts \line{\rm #1\hfill}}\bigskip \par\penalty 10000 %
+}
+
+\def\chfopen #1#2{\chapoddpage {\chapfonts
+\vbox to 3in{\vfil \hbox to\hsize{\hfil #2} \hbox to\hsize{\hfil #1} \vfil}}%
+\par\penalty 5000 %
+}
+
+\def\CHAPFopen{
+\global\let\chapmacro=\chfopen
+\global\let\unnumbchapmacro=\unnchfopen}
+
+% Parameter controlling skip before section headings.
+
+\newskip \subsecheadingskip \subsecheadingskip = 17pt plus 8pt minus 4pt
+\def\subsecheadingbreak{\dobreak \subsecheadingskip {-500}}
+
+\newskip \secheadingskip \secheadingskip = 21pt plus 8pt minus 4pt
+\def\secheadingbreak{\dobreak \secheadingskip {-1000}}
+
+
+% Section fonts are the base font at magstep2, which produces
+% a size a bit more than 14 points in the default situation.
+
+\def\secheading #1#2#3{\secheadingi {#2.#3\enspace #1}}
+\def\plainsecheading #1{\secheadingi {#1}}
+\def\secheadingi #1{{\advance \secheadingskip by \parskip %
+\secheadingbreak}%
+{\secfonts \line{\rm #1\hfill}}%
+\ifdim \parskip<10pt \kern 10pt\kern -\parskip\fi \penalty 10000 }
+
+
+% Subsection fonts are the base font at magstep1,
+% which produces a size of 12 points.
+
+\def\subsecheading #1#2#3#4{\subsecheadingi {#2.#3.#4\enspace #1}}
+\def\subsecheadingi #1{{\advance \subsecheadingskip by \parskip %
+\subsecheadingbreak}%
+{\subsecfonts \line{\rm #1\hfill}}%
+\ifdim \parskip<10pt \kern 10pt\kern -\parskip\fi \penalty 10000 }
+
+\def\subsubsecfonts{\subsecfonts} % Maybe this should change:
+ % Perhaps make sssec fonts scaled
+ % magstep half
+\def\subsubsecheading #1#2#3#4#5{\subsubsecheadingi {#2.#3.#4.#5\enspace #1}}
+\def\subsubsecheadingi #1{{\advance \subsecheadingskip by \parskip %
+\subsecheadingbreak}%
+{\subsubsecfonts \line{\rm #1\hfill}}%
+\ifdim \parskip<10pt \kern 10pt\kern -\parskip\fi \penalty 10000}
+
+
+\message{toc printing,}
+
+% Finish up the main text and prepare to read what we've written
+% to \contentsfile.
+
+\def\startcontents#1{%
+ \ifnum \pageno>0
+ \pagealignmacro
+ \immediate\closeout \contentsfile
+ \pageno = -1 % Request roman numbered pages.
+ \fi
+ % Don't need to put `Contents' or `Short Contents' in the headline.
+ % It is abundantly clear what they are.
+ \unnumbchapmacro{#1}\def\thischapter{}%
+ \begingroup % Set up to handle contents files properly.
+ \catcode`\\=0 \catcode`\{=1 \catcode`\}=2 \catcode`\@=11
+ \raggedbottom % Worry more about breakpoints than the bottom.
+ \advance\hsize by -1in % Don't use the full line length.
+}
+
+
+% Normal (long) toc.
+\outer\def\contents{%
+ \startcontents{Table of Contents}%
+ \input \jobname.toc
+ \endgroup
+ \vfill \eject
+}
+
+% And just the chapters.
+\outer\def\summarycontents{%
+ \startcontents{Short Contents}%
+ %
+ \let\chapentry = \shortchapentry
+ \let\unnumbchapentry = \shortunnumberedentry
+ % We want a true roman here for the page numbers.
+ \secfonts \let\rm = \truesecrm \rm
+ \advance\baselineskip by 1pt % Open it up a little.
+ \def\secentry ##1##2##3##4{}
+ \def\unnumbsecentry ##1##2{}
+ \def\subsecentry ##1##2##3##4##5{}
+ \def\unnumbsubsecentry ##1##2{}
+ \def\subsubsecentry ##1##2##3##4##5##6{}
+ \def\unnumbsubsubsecentry ##1##2{}
+ \input \jobname.toc
+ \endgroup
+ \vfill \eject
+}
+\let\shortcontents = \summarycontents
+
+% These macros generate individual entries in the table of contents.
+% The first argument is the chapter or section name.
+% The last argument is the page number.
+% The arguments in between are the chapter number, section number, ...
+
+% Chapter-level things, for both the long and short contents.
+\def\chapentry#1#2#3{\dochapentry{#2\labelspace#1}{#3}}
+\def\shortchapentry#1#2#3{%
+ \line{{#2\labelspace #1}\dotfill\doshortpageno{#3}}%
+}
+
+\def\unnumbchapentry#1#2{\dochapentry{#1}{#2}}
+\def\shortunnumberedentry#1#2{%
+ \line{#1\dotfill\doshortpageno{#2}}%
+}
+
+% Sections.
+\def\secentry#1#2#3#4{\dosecentry{#2.#3\labelspace#1}{#4}}
+\def\unnumbsecentry#1#2{\dosecentry{#1}{#2}}
+
+% Subsections.
+\def\subsecentry#1#2#3#4#5{\dosubsecentry{#2.#3.#4\labelspace#1}{#5}}
+\def\unnumbsubsecentry#1#2{\dosubsecentry{#1}{#2}}
+
+% And subsubsections.
+\def\subsubsecentry#1#2#3#4#5#6{\dosubsubsecentry{#2.#3.#4.#5\labelspace#1}{#6}}
+\def\unnumbsubsubsecentry#1#2{\dosubsubsecentry{#1}{#2}}
+
+
+% This parameter controls the indentation of the various levels.
+\newdimen\tocindent \tocindent = 3pc
+
+% Now for the actual typesetting. In all these, #1 is the text and #2 is the
+% page number.
+%
+% If the toc has to be broken over pages, we would want to be at chapters
+% if at all possible; hence the \penalty.
+\def\dochapentry#1#2{%
+ \penalty-300 \vskip\baselineskip
+ \line{\chapentryfonts #1\dotfill \dopageno{#2}}%
+ \nobreak\vskip .25\baselineskip
+}
+
+\def\dosecentry#1#2{%
+ \line{\secentryfonts \hskip\tocindent #1\dotfill \dopageno{#2}}%
+}
+
+\def\dosubsecentry#1#2{%
+ \line{\subsecentryfonts \hskip2\tocindent #1\dotfill \dopageno{#2}}%
+}
+
+\def\dosubsubsecentry#1#2{%
+ \line{\subsubsecentryfonts \hskip3\tocindent #1\dotfill \dopageno{#2}}%
+}
+
+% Space between chapter (or whatever) number and the title.
+\def\labelspace{\hskip1em \relax}
+
+\def\dopageno#1{{\rm #1}}
+\def\doshortpageno#1{{\rm #1}}
+
+\def\chapentryfonts{\secfonts \rm}
+\def\secentryfonts{\textfonts}
+\let\subsecentryfonts = \textfonts
+\let\subsubsecentryfonts = \textfonts
+
+
+\message{environments,}
+
+% Since these characters are used in examples, it should be an even number of
+% \tt widths. Each \tt character is 1en, so two makes it 1em.
+% Furthermore, these definitions must come after we define our fonts.
+\newbox\dblarrowbox \newbox\longdblarrowbox
+\newbox\pushcharbox \newbox\bullbox
+\newbox\equivbox \newbox\errorbox
+
+\let\ptexequiv = \equiv
+
+{\tentt
+\global\setbox\dblarrowbox = \hbox to 1em{\hfil$\Rightarrow$\hfil}
+\global\setbox\longdblarrowbox = \hbox to 1em{\hfil$\mapsto$\hfil}
+\global\setbox\pushcharbox = \hbox to 1em{\hfil$\dashv$\hfil}
+\global\setbox\equivbox = \hbox to 1em{\hfil$\ptexequiv$\hfil}
+% Adapted from the manmac format (p.420 of TeXbook)
+\global\setbox\bullbox = \hbox to 1em{\kern.15em\vrule height .75ex width .85ex
+ depth .1ex\hfil}
+}
+
+\def\point{$\star$}
+
+\def\result{\leavevmode\raise.15ex\copy\dblarrowbox}
+\def\expansion{\leavevmode\raise.1ex\copy\longdblarrowbox}
+\def\print{\leavevmode\lower.1ex\copy\pushcharbox}
+
+\def\equiv{\leavevmode\lower.1ex\copy\equivbox}
+
+% Does anyone really want this?
+% \def\bull{\leavevmode\copy\bullbox}
+
+% Adapted from the TeXbook's \boxit.
+{\tentt \global\dimen0 = 3em}% Width of the box.
+\dimen2 = .55pt % Thickness of rules
+% The text. (`r' is open on the right, `e' somewhat less so on the left.)
+\setbox0 = \hbox{\kern-.75pt \tensf error\kern-1.5pt}
+
+\global\setbox\errorbox=\hbox to \dimen0{\hfil
+ \hsize = \dimen0 \advance\hsize by -5.8pt % Space to left+right.
+ \advance\hsize by -2\dimen2 % Rules.
+ \vbox{
+ \hrule height\dimen2
+ \hbox{\vrule width\dimen2 \kern3pt % Space to left of text.
+ \vtop{\kern2.4pt \box0 \kern2.4pt}% Space above/below.
+ \kern3pt\vrule width\dimen2}% Space to right.
+ \hrule height\dimen2}
+ \hfil}
+
+% The @error{} command.
+\def\error{\leavevmode\lower.7ex\copy\errorbox}
+
+% @tex ... @end tex escapes into raw Tex temporarily.
+% One exception: @ is still an escape character, so that @end tex works.
+% But \@ or @@ will get a plain tex @ character.
+
+\def\tex{\begingroup
+\catcode `\\=0 \catcode `\{=1 \catcode `\}=2
+\catcode `\$=3 \catcode `\&=4 \catcode `\#=6
+\catcode `\^=7 \catcode `\_=8 \catcode `\~=13 \let~=\tie
+\catcode `\%=14
+\catcode`\"=12
+\catcode`\==12
+\catcode`\|=12
+\catcode`\<=12
+\catcode`\>=12
+\escapechar=`\\
+%
+\let\{=\ptexlbrace
+\let\}=\ptexrbrace
+\let\.=\ptexdot
+\let\*=\ptexstar
+\let\dots=\ptexdots
+\def\@={@}%
+\let\bullet=\ptexbullet
+\let\b=\ptexb \let\c=\ptexc \let\i=\ptexi \let\t=\ptext \let\l=\ptexl
+\let\L=\ptexL
+%
+\let\Etex=\endgroup}
+
+% Define @lisp ... @endlisp.
+% @lisp does a \begingroup so it can rebind things,
+% including the definition of @endlisp (which normally is erroneous).
+
+% Amount to narrow the margins by for @lisp.
+\newskip\lispnarrowing \lispnarrowing=0.4in
+
+% This is the definition that ^M gets inside @lisp
+% phr: changed space to \null, to avoid overfull hbox problems.
+{\obeyspaces%
+\gdef\lisppar{\null\endgraf}}
+
+% Cause \obeyspaces to make each Space cause a word-separation
+% rather than the default which is that it acts punctuation.
+% This is because space in tt font looks funny.
+{\obeyspaces %
+\gdef\sepspaces{\def {\ }}}
+
+\newskip\aboveenvskipamount \aboveenvskipamount= 0pt
+\def\aboveenvbreak{{\advance\aboveenvskipamount by \parskip
+\endgraf \ifdim\lastskip<\aboveenvskipamount
+\removelastskip \penalty-50 \vskip\aboveenvskipamount \fi}}
+
+\def\afterenvbreak{\endgraf \ifdim\lastskip<\aboveenvskipamount
+\removelastskip \penalty-50 \vskip\aboveenvskipamount \fi}
+
+\def\lisp{\aboveenvbreak\begingroup\inENV %This group ends at the end of the @lisp body
+\hfuzz=12truept % Don't be fussy
+% Make spaces be word-separators rather than space tokens.
+\sepspaces %
+% Single space lines
+\singlespace %
+% The following causes blank lines not to be ignored
+% by adding a space to the end of each line.
+\let\par=\lisppar
+\def\Elisp{\endgroup\afterenvbreak}%
+\parskip=0pt
+\advance \leftskip by \lispnarrowing
+\parindent=0pt
+\let\exdent=\internalexdent
+\obeyspaces \obeylines \tt \rawbackslash
+\def\next##1{}\next}
+
+
+\let\example=\lisp
+\def\Eexample{\Elisp}
+
+\let\smallexample=\lisp
+\def\Esmallexample{\Elisp}
+
+% Macro for 9 pt. examples, necessary to print with 5" lines.
+% From Pavel@xerox. This is not really used unless the
+% @smallbook command is given.
+
+\def\smalllispx{\aboveenvbreak\begingroup\inENV
+% This group ends at the end of the @lisp body
+\hfuzz=12truept % Don't be fussy
+% Make spaces be word-separators rather than space tokens.
+\sepspaces %
+% Single space lines
+\singlespace %
+% The following causes blank lines not to be ignored
+% by adding a space to the end of each line.
+\let\par=\lisppar
+\def\Esmalllisp{\endgroup\afterenvbreak}%
+\parskip=0pt
+\advance \leftskip by \lispnarrowing
+\parindent=0pt
+\let\exdent=\internalexdent
+\obeyspaces \obeylines \ninett \indexfonts \rawbackslash
+\def\next##1{}\next}
+
+% This is @display; same as @lisp except use roman font.
+
+\def\display{\begingroup\inENV %This group ends at the end of the @display body
+\aboveenvbreak
+% Make spaces be word-separators rather than space tokens.
+\sepspaces %
+% Single space lines
+\singlespace %
+% The following causes blank lines not to be ignored
+% by adding a space to the end of each line.
+\let\par=\lisppar
+\def\Edisplay{\endgroup\afterenvbreak}%
+\parskip=0pt
+\advance \leftskip by \lispnarrowing
+\parindent=0pt
+\let\exdent=\internalexdent
+\obeyspaces \obeylines
+\def\next##1{}\next}
+
+% This is @format; same as @lisp except use roman font and don't narrow margins
+
+\def\format{\begingroup\inENV %This group ends at the end of the @format body
+\aboveenvbreak
+% Make spaces be word-separators rather than space tokens.
+\sepspaces %
+\singlespace %
+% The following causes blank lines not to be ignored
+% by adding a space to the end of each line.
+\let\par=\lisppar
+\def\Eformat{\endgroup\afterenvbreak}
+\parskip=0pt \parindent=0pt
+\obeyspaces \obeylines
+\def\next##1{}\next}
+
+% @flushleft and @flushright
+
+\def\flushleft{\begingroup\inENV %This group ends at the end of the @format body
+\aboveenvbreak
+% Make spaces be word-separators rather than space tokens.
+\sepspaces %
+% The following causes blank lines not to be ignored
+% by adding a space to the end of each line.
+% This also causes @ to work when the directive name
+% is terminated by end of line.
+\let\par=\lisppar
+\def\Eflushleft{\endgroup\afterenvbreak}%
+\parskip=0pt \parindent=0pt
+\obeyspaces \obeylines
+\def\next##1{}\next}
+
+\def\flushright{\begingroup\inENV %This group ends at the end of the @format body
+\aboveenvbreak
+% Make spaces be word-separators rather than space tokens.
+\sepspaces %
+% The following causes blank lines not to be ignored
+% by adding a space to the end of each line.
+% This also causes @ to work when the directive name
+% is terminated by end of line.
+\let\par=\lisppar
+\def\Eflushright{\endgroup\afterenvbreak}%
+\parskip=0pt \parindent=0pt
+\advance \leftskip by 0pt plus 1fill
+\obeyspaces \obeylines
+\def\next##1{}\next}
+
+% @quotation - narrow the margins.
+
+\def\quotation{\begingroup\inENV %This group ends at the end of the @quotation body
+{\parskip=0pt % because we will skip by \parskip too, later
+\aboveenvbreak}%
+\singlespace
+\parindent=0pt
+\def\Equotation{\par\endgroup\afterenvbreak}%
+\advance \rightskip by \lispnarrowing
+\advance \leftskip by \lispnarrowing}
+
+\message{defuns,}
+% Define formatter for defuns
+% First, allow user to change definition object font (\df) internally
+\def\setdeffont #1 {\csname DEF#1\endcsname}
+
+\newskip\defbodyindent \defbodyindent=.4in
+\newskip\defargsindent \defargsindent=50pt
+\newskip\deftypemargin \deftypemargin=12pt
+\newskip\deflastargmargin \deflastargmargin=18pt
+
+\newcount\parencount
+% define \functionparens, which makes ( and ) and & do special things.
+% \functionparens affects the group it is contained in.
+\def\activeparens{%
+\catcode`\(=\active \catcode`\)=\active \catcode`\&=\active
+\catcode`\[=\active \catcode`\]=\active}
+{\activeparens % Now, smart parens don't turn on until &foo (see \amprm)
+\gdef\functionparens{\boldbrax\let&=\amprm\parencount=0 }
+\gdef\boldbrax{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb}
+
+% Definitions of (, ) and & used in args for functions.
+% This is the definition of ( outside of all parentheses.
+\gdef\oprm#1 {{\rm\char`\(}#1 \bf \let(=\opnested %
+\global\advance\parencount by 1 }
+%
+% This is the definition of ( when already inside a level of parens.
+\gdef\opnested{\char`\(\global\advance\parencount by 1 }
+%
+\gdef\clrm{% Print a paren in roman if it is taking us back to depth of 0.
+% also in that case restore the outer-level definition of (.
+\ifnum \parencount=1 {\rm \char `\)}\sl \let(=\oprm \else \char `\) \fi
+\global\advance \parencount by -1 }
+% If we encounter &foo, then turn on ()-hacking afterwards
+\gdef\amprm#1 {{\rm\&#1}\let(=\oprm \let)=\clrm\ }
+%
+\gdef\normalparens{\boldbrax\let&=\ampnr}
+} % End of definition inside \activeparens
+%% These parens (in \boldbrax) actually are a little bolder than the
+%% contained text. This is especially needed for [ and ]
+\def\opnr{{\sf\char`\(}} \def\clnr{{\sf\char`\)}} \def\ampnr{\&}
+\def\lbrb{{\bf\char`\[}} \def\rbrb{{\bf\char`\]}}
+
+% First, defname, which formats the header line itself.
+% #1 should be the function name.
+% #2 should be the type of definition, such as "Function".
+
+\def\defname #1#2{%
+\leftskip = 0in %
+\noindent %
+\setbox0=\hbox{\hskip \deflastargmargin{\rm #2}\hskip \deftypemargin}%
+\dimen0=\hsize \advance \dimen0 by -\wd0 % compute size for first line
+\dimen1=\hsize \advance \dimen1 by -\defargsindent %size for continuations
+\parshape 2 0in \dimen0 \defargsindent \dimen1 %
+% Now output arg 2 ("Function" or some such)
+% ending at \deftypemargin from the right margin,
+% but stuck inside a box of width 0 so it does not interfere with linebreaking
+\rlap{\rightline{{\rm #2}\hskip \deftypemargin}}%
+\tolerance=10000 \hbadness=10000 % Make all lines underfull and no complaints
+{\df #1}\enskip % Generate function name
+}
+
+% Actually process the body of a definition
+% #1 should be the terminating control sequence, such as \Edefun.
+% #2 should be the "another name" control sequence, such as \defunx.
+% #3 should be the control sequence that actually processes the header,
+% such as \defunheader.
+
+\def\defparsebody #1#2#3{\begingroup\inENV% Environment for definitionbody
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2{\begingroup\obeylines\activeparens\spacesplit#3}%
+\parindent=0in \leftskip=\defbodyindent \rightskip=\defbodyindent %
+\begingroup %
+\catcode 61=\active %
+\obeylines\activeparens\spacesplit#3}
+
+\def\defmethparsebody #1#2#3#4 {\begingroup\inENV %
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2##1 {\begingroup\obeylines\activeparens\spacesplit{#3{##1}}}%
+\parindent=0in \leftskip=\defbodyindent \rightskip=\defbodyindent %
+\begingroup\obeylines\activeparens\spacesplit{#3{#4}}}
+
+\def\defopparsebody #1#2#3#4#5 {\begingroup\inENV %
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2##1 ##2 {\def#4{##1}%
+\begingroup\obeylines\activeparens\spacesplit{#3{##2}}}%
+\parindent=0in \leftskip=\defbodyindent %
+\begingroup\obeylines\activeparens\spacesplit{#3{#5}}}
+
+% Split up #2 at the first space token.
+% call #1 with two arguments:
+% the first is all of #2 before the space token,
+% the second is all of #2 after that space token.
+% If #2 contains no space token, all of it is passed as the first arg
+% and the second is passed as empty.
+
+{\obeylines
+\gdef\spacesplit#1#2^^M{\endgroup\spacesplitfoo{#1}#2 \relax\spacesplitfoo}%
+\long\gdef\spacesplitfoo#1#2 #3#4\spacesplitfoo{%
+\ifx\relax #3%
+#1{#2}{}\else #1{#2}{#3#4}\fi}}
+
+% So much for the things common to all kinds of definitions.
+
+% Define @defun.
+
+% First, define the processing that is wanted for arguments of \defun
+% Use this to expand the args and terminate the paragraph they make up
+
+\def\defunargs #1{\functionparens \sl
+% Expand, preventing hyphenation at `-' chars.
+% Note that groups don't affect changes in \hyphenchar.
+\hyphenchar\sl=0
+#1%
+\hyphenchar\sl=45
+\ifnum\parencount=0 \else \errmessage{unbalanced parens in @def arguments}\fi%
+\interlinepenalty=10000
+\advance\rightskip by 0pt plus 1fil
+\endgraf\penalty 10000\vskip -\parskip\penalty 10000%
+}
+
+\def\deftypefunargs #1{%
+% Expand, preventing hyphenation at `-' chars.
+% Note that groups don't affect changes in \hyphenchar.
+\functionparens
+\code{#1}%
+\interlinepenalty=10000
+\advance\rightskip by 0pt plus 1fil
+\endgraf\penalty 10000\vskip -\parskip\penalty 10000%
+}
+
+% Do complete processing of one @defun or @defunx line already parsed.
+
+% @deffn Command forward-char nchars
+
+\def\deffn{\defmethparsebody\Edeffn\deffnx\deffnheader}
+
+\def\deffnheader #1#2#3{\doind {fn}{\code{#2}}%
+\begingroup\defname {#2}{#1}\defunargs{#3}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @defun == @deffn Function
+
+\def\defun{\defparsebody\Edefun\defunx\defunheader}
+
+\def\defunheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index
+\begingroup\defname {#1}{Function}%
+\defunargs {#2}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @deftypefun int foobar (int @var{foo}, float @var{bar})
+
+\def\deftypefun{\defparsebody\Edeftypefun\deftypefunx\deftypefunheader}
+
+% #1 is the data type. #2 is the name and args.
+\def\deftypefunheader #1#2{\deftypefunheaderx{#1}#2 \relax}
+% #1 is the data type, #2 the name, #3 the args.
+\def\deftypefunheaderx #1#2 #3\relax{\doind {fn}{\code{#2}}% Make entry in function index
+\begingroup\defname {\code{#1} #2}{Function}%
+\deftypefunargs {#3}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @deftypefn {Library Function} int foobar (int @var{foo}, float @var{bar})
+
+\def\deftypefn{\defmethparsebody\Edeftypefn\deftypefnx\deftypefnheader}
+
+% #1 is the classification. #2 is the data type. #3 is the name and args.
+\def\deftypefnheader #1#2#3{\deftypefnheaderx{#1}{#2}#3 \relax}
+% #1 is the classification, #2 the data type, #3 the name, #4 the args.
+\def\deftypefnheaderx #1#2#3 #4\relax{\doind {fn}{\code{#3}}% Make entry in function index
+\begingroup\defname {\code{#2} #3}{#1}%
+\deftypefunargs {#4}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @defmac == @deffn Macro
+
+\def\defmac{\defparsebody\Edefmac\defmacx\defmacheader}
+
+\def\defmacheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index
+\begingroup\defname {#1}{Macro}%
+\defunargs {#2}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @defspec == @deffn Special Form
+
+\def\defspec{\defparsebody\Edefspec\defspecx\defspecheader}
+
+\def\defspecheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index
+\begingroup\defname {#1}{Special Form}%
+\defunargs {#2}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% This definition is run if you use @defunx
+% anywhere other than immediately after a @defun or @defunx.
+
+\def\deffnx #1 {\errmessage{@deffnx in invalid context}}
+\def\defunx #1 {\errmessage{@defunx in invalid context}}
+\def\defmacx #1 {\errmessage{@defmacx in invalid context}}
+\def\defspecx #1 {\errmessage{@defspecx in invalid context}}
+\def\deftypefnx #1 {\errmessage{@deftypefnx in invalid context}}
+\def\deftypeunx #1 {\errmessage{@deftypeunx in invalid context}}
+
+% @defmethod, and so on
+
+% @defop {Funny Method} foo-class frobnicate argument
+
+\def\defop #1 {\def\defoptype{#1}%
+\defopparsebody\Edefop\defopx\defopheader\defoptype}
+
+\def\defopheader #1#2#3{\dosubind {fn}{\code{#2}}{on #1}% Make entry in function index
+\begingroup\defname {#2}{\defoptype{} on #1}%
+\defunargs {#3}\endgroup %
+}
+
+% @defmethod == @defop Method
+
+\def\defmethod{\defmethparsebody\Edefmethod\defmethodx\defmethodheader}
+
+\def\defmethodheader #1#2#3{\dosubind {fn}{\code{#2}}{on #1}% entry in function index
+\begingroup\defname {#2}{Method on #1}%
+\defunargs {#3}\endgroup %
+}
+
+% @defcv {Class Option} foo-class foo-flag
+
+\def\defcv #1 {\def\defcvtype{#1}%
+\defopparsebody\Edefcv\defcvx\defcvarheader\defcvtype}
+
+\def\defcvarheader #1#2#3{%
+\dosubind {vr}{\code{#2}}{of #1}% Make entry in var index
+\begingroup\defname {#2}{\defcvtype{} of #1}%
+\defvarargs {#3}\endgroup %
+}
+
+% @defivar == @defcv {Instance Variable}
+
+\def\defivar{\defmethparsebody\Edefivar\defivarx\defivarheader}
+
+\def\defivarheader #1#2#3{%
+\dosubind {vr}{\code{#2}}{of #1}% Make entry in var index
+\begingroup\defname {#2}{Instance Variable of #1}%
+\defvarargs {#3}\endgroup %
+}
+
+% These definitions are run if you use @defmethodx, etc.,
+% anywhere other than immediately after a @defmethod, etc.
+
+\def\defopx #1 {\errmessage{@defopx in invalid context}}
+\def\defmethodx #1 {\errmessage{@defmethodx in invalid context}}
+\def\defcvx #1 {\errmessage{@defcvx in invalid context}}
+\def\defivarx #1 {\errmessage{@defivarx in invalid context}}
+
+% Now @defvar
+
+% First, define the processing that is wanted for arguments of @defvar.
+% This is actually simple: just print them in roman.
+% This must expand the args and terminate the paragraph they make up
+\def\defvarargs #1{\normalparens #1%
+\interlinepenalty=10000
+\endgraf\penalty 10000\vskip -\parskip\penalty 10000}
+
+% @defvr Counter foo-count
+
+\def\defvr{\defmethparsebody\Edefvr\defvrx\defvrheader}
+
+\def\defvrheader #1#2#3{\doind {vr}{\code{#2}}%
+\begingroup\defname {#2}{#1}\defvarargs{#3}\endgroup}
+
+% @defvar == @defvr Variable
+
+\def\defvar{\defparsebody\Edefvar\defvarx\defvarheader}
+
+\def\defvarheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index
+\begingroup\defname {#1}{Variable}%
+\defvarargs {#2}\endgroup %
+}
+
+% @defopt == @defvr {User Option}
+
+\def\defopt{\defparsebody\Edefopt\defoptx\defoptheader}
+
+\def\defoptheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index
+\begingroup\defname {#1}{User Option}%
+\defvarargs {#2}\endgroup %
+}
+
+% @deftypevar int foobar
+
+\def\deftypevar{\defparsebody\Edeftypevar\deftypevarx\deftypevarheader}
+
+% #1 is the data type. #2 is the name.
+\def\deftypevarheader #1#2{\doind {vr}{\code{#2}}% Make entry in variables index
+\begingroup\defname {\code{#1} #2}{Variable}%
+\interlinepenalty=10000
+\endgraf\penalty 10000\vskip -\parskip\penalty 10000
+\endgroup}
+
+% @deftypevr {Global Flag} int enable
+
+\def\deftypevr{\defmethparsebody\Edeftypevr\deftypevrx\deftypevrheader}
+
+\def\deftypevrheader #1#2#3{\doind {vr}{\code{#3}}%
+\begingroup\defname {\code{#2} #3}{#1}
+\interlinepenalty=10000
+\endgraf\penalty 10000\vskip -\parskip\penalty 10000
+\endgroup}
+
+% This definition is run if you use @defvarx
+% anywhere other than immediately after a @defvar or @defvarx.
+
+\def\defvrx #1 {\errmessage{@defvrx in invalid context}}
+\def\defvarx #1 {\errmessage{@defvarx in invalid context}}
+\def\defoptx #1 {\errmessage{@defoptx in invalid context}}
+\def\deftypevarx #1 {\errmessage{@deftypevarx in invalid context}}
+\def\deftypevrx #1 {\errmessage{@deftypevrx in invalid context}}
+
+% Now define @deftp
+% Args are printed in bold, a slight difference from @defvar.
+
+\def\deftpargs #1{\bf \defvarargs{#1}}
+
+% @deftp Class window height width ...
+
+\def\deftp{\defmethparsebody\Edeftp\deftpx\deftpheader}
+
+\def\deftpheader #1#2#3{\doind {tp}{\code{#2}}%
+\begingroup\defname {#2}{#1}\deftpargs{#3}\endgroup}
+
+% This definition is run if you use @deftpx, etc
+% anywhere other than immediately after a @deftp, etc.
+
+\def\deftpx #1 {\errmessage{@deftpx in invalid context}}
+
+\message{cross reference,}
+% Define cross-reference macros
+\newwrite \auxfile
+
+\newif\ifhavexrefs % True if xref values are known.
+\newif\ifwarnedxrefs % True if we warned once that they aren't known.
+
+% \setref{foo} defines a cross-reference point named foo.
+
+\def\setref#1{%
+\dosetq{#1-title}{Ytitle}%
+\dosetq{#1-pg}{Ypagenumber}%
+\dosetq{#1-snt}{Ysectionnumberandtype}}
+
+\def\unnumbsetref#1{%
+\dosetq{#1-title}{Ytitle}%
+\dosetq{#1-pg}{Ypagenumber}%
+\dosetq{#1-snt}{Ynothing}}
+
+\def\appendixsetref#1{%
+\dosetq{#1-title}{Ytitle}%
+\dosetq{#1-pg}{Ypagenumber}%
+\dosetq{#1-snt}{Yappendixletterandtype}}
+
+% \xref, \pxref, and \ref generate cross-references to specified points.
+% For \xrefX, #1 is the node name, #2 the name of the Info
+% cross-reference, #3 the printed node name, #4 the name of the Info
+% file, #5 the name of the printed manual. All but the node name can be
+% omitted.
+%
+\def\pxref#1{see \xrefX[#1,,,,,,,]}
+\def\xref#1{See \xrefX[#1,,,,,,,]}
+\def\ref#1{\xrefX[#1,,,,,,,]}
+\def\xrefX[#1,#2,#3,#4,#5,#6]{\begingroup%
+\def\printedmanual{\ignorespaces #5}%
+\def\printednodename{\ignorespaces #3}%
+%
+\setbox1=\hbox{\i{\printedmanual}}%
+\setbox0=\hbox{\printednodename}%
+\ifdim \wd0=0pt%
+\def\printednodename{\ignorespaces #1}%
+%%% Uncommment the following line to make the actual chapter or section title
+%%% appear inside the square brackets.
+%\def\printednodename{#1-title}%
+\fi%
+%
+%
+% If we use \unhbox0 and \unhbox1 to print the node names, TeX does
+% not insert empty discretionaries after hyphens, which means that it
+% will not find a line break at a hyphen in a node names. Since some
+% manuals are best written with fairly long node names, containing
+% hyphens, this is a loss. Therefore, we simply give the text of
+% the node name again, so it is as if TeX is seeing it for the first
+% time.
+\ifdim \wd1>0pt
+section `\printednodename' in \printedmanual
+\else%
+\turnoffactive%
+\refx{#1-snt}{} [\printednodename], page\tie\refx{#1-pg}{}%
+\fi
+\endgroup}
+
+% \dosetq is the interface for calls from other macros
+
+% Use \turnoffactive so that punctuation chars such as underscore
+% work in node names.
+\def\dosetq #1#2{{\let\folio=0 \turnoffactive%
+\edef\next{\write\auxfile{\internalsetq {#1}{#2}}}%
+\next}}
+
+% \internalsetq {foo}{page} expands into CHARACTERS 'xrdef {foo}{...expansion of \Ypage...}
+% When the aux file is read, ' is the escape character
+
+\def\internalsetq #1#2{'xrdef {#1}{\csname #2\endcsname}}
+
+% Things to be expanded by \internalsetq
+
+\def\Ypagenumber{\folio}
+
+\def\Ytitle{\thischapter}
+
+\def\Ynothing{}
+
+\def\Ysectionnumberandtype{%
+\ifnum\secno=0 Chapter\xreftie\the\chapno %
+\else \ifnum \subsecno=0 Section\xreftie\the\chapno.\the\secno %
+\else \ifnum \subsubsecno=0 %
+Section\xreftie\the\chapno.\the\secno.\the\subsecno %
+\else %
+Section\xreftie\the\chapno.\the\secno.\the\subsecno.\the\subsubsecno %
+\fi \fi \fi }
+
+\def\Yappendixletterandtype{%
+\ifnum\secno=0 Appendix\xreftie'char\the\appendixno %
+\else \ifnum \subsecno=0 Section\xreftie'char\the\appendixno.\the\secno %
+\else \ifnum \subsubsecno=0 %
+Section\xreftie'char\the\appendixno.\the\secno.\the\subsecno %
+\else %
+Section\xreftie'char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno %
+\fi \fi \fi }
+
+\gdef\xreftie{'tie}
+
+% Use TeX 3.0's \inputlineno to get the line number, for better error
+% messages, but if we're using an old version of TeX, don't do anything.
+%
+\ifx\inputlineno\thisisundefined
+ \let\linenumber = \empty % Non-3.0.
+\else
+ \def\linenumber{\the\inputlineno:\space}
+\fi
+
+% Define \refx{NAME}{SUFFIX} to reference a cross-reference string named NAME.
+% If its value is nonempty, SUFFIX is output afterward.
+
+\def\refx#1#2{%
+ \expandafter\ifx\csname X#1\endcsname\relax
+ % If not defined, say something at least.
+ $\langle$un\-de\-fined$\rangle$%
+ \ifhavexrefs
+ \message{\linenumber Undefined cross reference `#1'.}%
+ \else
+ \ifwarnedxrefs\else
+ \global\warnedxrefstrue
+ \message{Cross reference values unknown; you must run TeX again.}%
+ \fi
+ \fi
+ \else
+ % It's defined, so just use it.
+ \csname X#1\endcsname
+ \fi
+ #2% Output the suffix in any case.
+}
+
+% Read the last existing aux file, if any. No error if none exists.
+
+% This is the macro invoked by entries in the aux file.
+\def\xrdef #1#2{
+{\catcode`\'=\other\expandafter \gdef \csname X#1\endcsname {#2}}}
+
+\def\readauxfile{%
+\begingroup
+\catcode `\^^@=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\^^C=\other
+\catcode `\^^D=\other
+\catcode `\^^E=\other
+\catcode `\^^F=\other
+\catcode `\^^G=\other
+\catcode `\^^H=\other
+\catcode `\ =\other
+\catcode `\^^L=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\^^[=\other
+\catcode `\^^\=\other
+\catcode `\^^]=\other
+\catcode `\^^^=\other
+\catcode `\^^_=\other
+\catcode `\@=\other
+\catcode `\^=\other
+\catcode `\~=\other
+\catcode `\[=\other
+\catcode `\]=\other
+\catcode`\"=\other
+\catcode`\_=\other
+\catcode`\|=\other
+\catcode`\<=\other
+\catcode`\>=\other
+\catcode `\$=\other
+\catcode `\#=\other
+\catcode `\&=\other
+% the aux file uses ' as the escape.
+% Turn off \ as an escape so we do not lose on
+% entries which were dumped with control sequences in their names.
+% For example, 'xrdef {$\leq $-fun}{page ...} made by @defun ^^
+% Reference to such entries still does not work the way one would wish,
+% but at least they do not bomb out when the aux file is read in.
+\catcode `\{=1 \catcode `\}=2
+\catcode `\%=\other
+\catcode `\'=0
+\catcode `\\=\other
+\openin 1 \jobname.aux
+\ifeof 1 \else \closein 1 \input \jobname.aux \global\havexrefstrue
+\fi
+% Open the new aux file. Tex will close it automatically at exit.
+\openout \auxfile=\jobname.aux
+\endgroup}
+
+
+% Footnotes.
+
+\newcount \footnoteno
+
+\def\supereject{\par\penalty -20000\footnoteno =0 }
+
+\let\ptexfootnote=\footnote
+
+{\catcode `\@=11
+\long\gdef\footnote #1{\global\advance \footnoteno by \@ne
+\edef\thisfootno{$^{\the\footnoteno}$}%
+\let\@sf\empty
+\ifhmode\edef\@sf{\spacefactor\the\spacefactor}\/\fi
+\thisfootno\@sf \footnotezzz{#1}}
+% \parsearg\footnotezzz}
+
+\long\gdef\footnotezzz #1{\insert\footins{
+\interlinepenalty\interfootnotelinepenalty
+\splittopskip\ht\strutbox % top baseline for broken footnotes
+\splitmaxdepth\dp\strutbox \floatingpenalty\@MM
+\leftskip\z@skip \rightskip\z@skip \spaceskip\z@skip \xspaceskip\z@skip
+\footstrut\hang\textindent{\thisfootno}#1\strut}}
+
+}%end \catcode `\@=11
+
+% End of control word definitions.
+
+\message{and turning on texinfo input format.}
+
+\def\openindices{%
+ \newindex{cp}%
+ \newcodeindex{fn}%
+ \newcodeindex{vr}%
+ \newcodeindex{tp}%
+ \newcodeindex{ky}%
+ \newcodeindex{pg}%
+}
+
+% Set some numeric style parameters, for 8.5 x 11 format.
+
+%\hsize = 6.5in
+\parindent 15pt
+\parskip 18pt plus 1pt
+\baselineskip 15pt
+\advance\topskip by 1.2cm
+
+% Prevent underfull vbox error messages.
+\vbadness=10000
+
+% Use @smallbook to reset parameters for 7x9.5 format
+\def\smallbook{
+\global\lispnarrowing = 0.3in
+\global\baselineskip 12pt
+\global\parskip 3pt plus 1pt
+\global\hsize = 5in
+\global\doublecolumnhsize=2.4in \global\doublecolumnvsize=15.0in
+\global\vsize=7.5in
+\global\tolerance=700
+\global\hfuzz=1pt
+
+\global\pagewidth=\hsize
+\global\pageheight=\vsize
+
+\global\let\smalllisp=\smalllispx
+\global\let\smallexample=\smalllispx
+\global\def\Esmallexample{\Esmalllisp}
+}
+
+%% For a final copy, take out the rectangles
+%% that mark overfull boxes (in case you have decided
+%% that the text looks ok even though it passes the margin).
+\def\finalout{\overfullrule=0pt}
+
+% Define macros to output various characters with catcode for normal text.
+\catcode`\"=\other
+\catcode`\~=\other
+\catcode`\^=\other
+\catcode`\_=\other
+\catcode`\|=\other
+\catcode`\<=\other
+\catcode`\>=\other
+\catcode`\+=\other
+\def\normaldoublequote{"}
+\def\normaltilde{~}
+\def\normalcaret{^}
+\def\normalunderscore{_}
+\def\normalverticalbar{|}
+\def\normalless{<}
+\def\normalgreater{>}
+\def\normalplus{+}
+
+% This macro is used to make a character print one way in ttfont
+% where it can probably just be output, and another way in other fonts,
+% where something hairier probably needs to be done.
+%
+% #1 is what to print if we are indeed using \tt; #2 is what to print
+% otherwise. Since all the Computer Modern typewriter fonts have zero
+% interword stretch (and shrink), and it is reasonable to expect all
+% typewriter fonts to have this, we can check that font parameter.
+%
+\def\ifusingtt#1#2{\ifdim \fontdimen3\the\font=0pt #1\else #2\fi}
+
+% Turn off all special characters except @
+% (and those which the user can use as if they were ordinary).
+% Most of these we simply print from the \tt font, but for some, we can
+% use math or other variants that look better in normal text.
+
+\catcode`\"=\active
+\def\activedoublequote{{\tt \char '042}}
+\let"=\activedoublequote
+\catcode`\~=\active
+\def~{{\tt \char '176}}
+\chardef\hat=`\^
+\catcode`\^=\active
+\def^{{\tt \hat}}
+
+\catcode`\_=\active
+\def_{\ifusingtt\normalunderscore\_}
+% Subroutine for the previous macro.
+\def\_{\leavevmode \kern.06em \vbox{\hrule width.3em height.1ex}}
+
+\catcode`\|=\active
+\def|{{\tt \char '174}}
+\chardef \less=`\<
+\catcode`\<=\active
+\def<{{\tt \less}}
+\chardef \gtr=`\>
+\catcode`\>=\active
+\def>{{\tt \gtr}}
+\catcode`\+=\active
+\def+{{\tt \char 43}}
+%\catcode 27=\active
+%\def^^[{$\diamondsuit$}
+
+% Used sometimes to turn off (effectively) the active characters
+% even after parsing them.
+\def\turnoffactive{\let"=\normaldoublequote
+\let~=\normaltilde
+\let^=\normalcaret
+\let_=\normalunderscore
+\let|=\normalverticalbar
+\let<=\normalless
+\let>=\normalgreater
+\let+=\normalplus}
+
+% Set up an active definition for =, but don't enable it most of the time.
+{\catcode`\==\active
+\global\def={{\tt \char 61}}}
+
+\catcode`\@=0
+
+% \rawbackslashxx output one backslash character in current font
+\global\chardef\rawbackslashxx=`\\
+%{\catcode`\\=\other
+%@gdef@rawbackslashxx{\}}
+
+% \rawbackslash redefines \ as input to do \rawbackslashxx.
+{\catcode`\\=\active
+@gdef@rawbackslash{@let\=@rawbackslashxx }}
+
+% \normalbackslash outputs one backslash in fixed width font.
+\def\normalbackslash{{\tt\rawbackslashxx}}
+
+% Say @foo, not \foo, in error messages.
+\escapechar=`\@
+
+% \catcode 17=0 % Define control-q
+\catcode`\\=\active
+
+% If a .fmt file is being used, we don't want the `\input texinfo' to show up.
+% That is what \eatinput is for; after that, the `\' should revert to printing
+% a backslash.
+%
+@gdef@eatinput input texinfo{@fixbackslash}
+@global@let\ = @eatinput
+
+% On the other hand, perhaps the file did not have a `\input texinfo'. Then
+% the first `\{ in the file would cause an error. This macro tries to fix
+% that, assuming it is called before the first `\' could plausibly occur.
+%
+@gdef@fixbackslash{@ifx\@eatinput @let\ = @normalbackslash @fi}
+
+%% These look ok in all fonts, so just make them not special. The @rm below
+%% makes sure that the current font starts out as the newly loaded cmr10
+@catcode`@$=@other @catcode`@%=@other @catcode`@&=@other @catcode`@#=@other
+
+@textfonts
+@rm
diff --git a/man/texinfo.texi b/man/texinfo.texi
new file mode 100644
index 00000000000..c6fe74666aa
--- /dev/null
+++ b/man/texinfo.texi
@@ -0,0 +1,5141 @@
+\input texinfo @c -*-texinfo-*-
+@comment %**start of header (This is for running Texinfo on a region.)
+@setfilename ../info/texinfo
+@settitle Texinfo 1.1
+@comment %**end of header (This is for running Texinfo on a region.)
+
+@iftex
+@finalout
+@end iftex
+
+@ifinfo
+This file documents Texinfo, a documentation system that uses a single
+source file to produce both on-line help and a printed manual.
+
+This is edition 1.1 of the Texinfo documentation, and is for the Texinfo
+that is distributed as part of Version 18 of GNU Emacs.
+
+Copyright (C) 1988 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+@ignore
+Permission is granted to process this file through TeX and print the
+results, provided the printed document carries copying permission
+notice identical to this one except for the removal of this paragraph
+(this paragraph not being relevant to the printed manual).
+
+@end ignore
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the entire
+resulting derived work is distributed under the terms of a permission
+notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that this permission notice may be stated in a translation approved
+by the Foundation.
+@end ifinfo
+
+@setchapternewpage odd
+@titlepage
+@sp 11
+@center @titlefont{Texinfo}
+@sp 2
+@center The GNU Documentation Format
+@sp 2
+@center by Richard M. Stallman and Robert J. Chassell
+@sp 2
+@center Edition 1.1
+@sp 2
+@center May 1988
+
+@comment Include the Distribution inside the titlepage environment so
+@c that headings are turned off.
+
+@page
+@vskip 0pt plus 1filll
+Copyright @copyright{} 1988 Free Software Foundation, Inc.
+
+@sp 2
+This is version 1.1 of the Texinfo documentation, and is for @*
+the Texinfo that is distributed as part of Version 18 of GNU Emacs.
+@sp 2
+
+Published by the Free Software Foundation @*
+675 Massachusetts Avenue, @*
+Cambridge, MA 02139 USA @*
+Printed copies are available for $10 each.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the entire
+resulting derived work is distributed under the terms of a permission
+notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that this permission notice may be stated in a translation approved
+by the Foundation.
+
+@end titlepage
+
+
+@node Top, License, (dir), (dir)
+
+@menu
+* License:: Licensing information.
+* Overview:: What is Texinfo?
+* Texinfo Mode:: Special features in GNU Emacs.
+* Beginning a File:: What to put at the beginning of a Texinfo file.
+* Ending a File:: What to put at the end of a Texinfo file.
+* Structuring:: How to make nodes and chapters.
+* Quotations and Examples:: How to insert quotations and examples.
+* Lists and Tables:: How to make lists and tables.
+* Cross References:: How to make cross references.
+* Formatting Paragraphs:: How to format paragraphs.
+* Marking Text:: How to mark code, definitions, variables etc.
+* Conditionals:: Putting text in only Info or the printed work.
+* Printing Hardcopy:: How to print a hardcopy of the manual.
+* Creating an Info File:: How to create an on-line Info file.
+* Catching Mistakes:: How to find problems.
+
+Indices, nodes containing large menus
+
+* Command Index:: An item for each @@-command.
+* Concept Index:: An item for each concept.
+
+A detailed node listing
+
+Overview
+* Info File:: Characteristics of the Info file.
+* Printed Manual:: Characteristics of the printed manual.
+* Conventions:: General syntactic conventions.
+* Short Sample:: A short sample Texinfo file.
+
+Using Texinfo Mode
+* Info on a Region:: Formatting a region for Info.
+* Showing the Structure:: Showing the structure of a file.
+* Inserting:: Inserting frequently used commands.
+
+Beginning a Texinfo File.
+* First Line:: The first line of a Texinfo file.
+* Start-of-Header:: Identifying the start of the header.
+* Setfilename:: Specifying the name of the Info file.
+* Settitle:: Specifying the title used by the headings.
+* Setchapternewpage:: Starting chapters on odd numbered pages.
+* Titlepage:: The title and copyright page.
+* Center:: Centering a line.
+* Copyright & Printed Permissions:: Ensuring free distributability.
+* Top Node:: The master menu.
+* License and Distribution:: Your are free to copy and distribute this.
+
+Ending a Texinfo File
+* Contents:: Generating tables of contents.
+* Indices:: Generating indices.
+* Index Entries:: Defining the entries of an index.
+* Combining Indices:: Putting two or more indices together.
+* Printing Indices & Menus:: Printing an index and generating menus.
+
+Node and Chapter Structuring
+* Chapter:: Creating a chapter.
+* Unnumbered and Appendix:: Chapter-like parts.
+* Section:: Creating sections
+* Subsection:: Creating subsections.
+* Subsubsection:: Creating subsubsections.
+
+* Node:: Creating nodes.
+* Menu:: Creating menus.
+
+
+Making quotations and examples
+* Quotation:: Inserting long quotations.
+* Example:: Inserting examples of code and the like.
+* Display:: Inserting displayed text.
+
+Making lists and two column tables
+* Itemize:: Creating itemized lists.
+* Enumerate:: Creating enumerated lists.
+* Table:: Creating two column tables.
+* Itemx:: Putting an extra item in the
+ first column of a table.
+
+Making Cross References
+* Xref:: Making a regular cross reference.
+* Pxref:: Making a parenthetical cross reference.
+* Inforef:: Making a cross reference to an Info file.
+
+
+Formatting Paragraphs
+* Refilling & Noindent:: Refilling paragraphs
+ and preventing indentation
+* Refill:: Using the @code{@@refill} command.
+* Noindent:: Using the @code{@@noindent} command.
+
+
+Breaks, Blank Lines and Groups
+* Line Breaks:: Inserting line breaks in @TeX{}.
+* Sp:: Inserting blank lines.
+* Br:: Inserting paragraph breaks.
+* W:: Preventing line breaks.
+* Page:: Starting new pages.
+* Group:: Holding text together on one page.
+* Need:: Keeping text together.
+
+Marking Text Within a Paragraph
+* Code:: A literal example of a piece of a program.
+* Samp:: A literal example of a sequence of characters.
+* File:: The name of a file.
+* Kbd:: The names of keys or else characters you type.
+* Key:: The conventional name for a key on a keyboard.
+* Ctrl:: Indicates the ASCII control character.
+* Var:: A variable.
+* Dfn:: The introductory or defining use of a term.
+* Cite:: The name of a book.
+
+Inserting Braces, @samp{@@} and Periods
+* Braces Atsigns Periods:: Inserting braces, @samp{@@} and periods.
+* Dots Bullets Tex:: Inserting dots, bullets and the @TeX{} logo
+* Emphasis:: Emphasizing text.
+
+Emphasizing Text
+* Emph and Strong:: Emphasizing text.
+* Fonts:: Selecting italic, bold or typewriter fonts.
+
+Creating an Info File
+* Installing an Info File:: Putting the Info file in the
+ @file{info} directory.
+
+Catching Mistakes
+* Debugging with Info:: Catching errors with info formatting.
+* Using the Emacs Lisp Debugger:: Using the Emacs Lisp Debugger
+* Debugging with Tex:: Catching errors with @TeX{} formatting.
+* Using texinfo-show-structure:: Using @code{texinfo-show-structure}
+ to catch mistakes.
+* Using Occur:: Using @code{occur} to catch mistakes.
+* Running Info-Validate:: Checking for unreferenced nodes.
+
+Finding badly referenced nodes
+* Info-Validating a Large File:: Running @code{Info-validate}
+ on a large file.
+* Splitting:: Splitting a file manually.
+
+Appendices
+* Command Syntax:: Details about the syntax.
+* Include Files:: Making one printed file out of
+ several Info files.
+* TeX Input:: Where @TeX{} finds its @samp{\input} file.
+* Sample Permissions:: You may copy GNU Software.
+* Ifinfo Permissions:: What to put in the `ifinfo' section.
+* Titlepage Permissions:: What to put in the `@@titlepage' section.
+@end menu
+
+@node License, Overview, Top, Top
+@comment node-name, next, previous, up
+@unnumbered Licensing Information
+
+ The programs currently being distributed that relate to Texinfo
+include two portions of GNU Emacs, plus two other separate programs
+(@code{texindex} and @code{texinfo.tex}). These programs are
+@dfn{free}; this means that everyone is free to use them and free to
+redistribute them on a free basis. The Texinfo related programs are not
+in the public domain; they are copyrighted and there are restrictions on
+their distribution, but these restrictions are designed to permit
+everything that a good cooperating citizen would want to do. What is
+not allowed is to try to prevent others from further sharing any version
+of these programs that they might get from you.
+
+ Specifically, we want to make sure that you have the right to give
+away copies of the programs that relate to Texinfo, that you receive
+source code or else can get it if you want it, that you can change these
+programs or use pieces of them in new free programs, and that you know
+you can do these things.
+
+ To make sure that everyone has such rights, we have to forbid you to
+deprive anyone else of these rights. For example, if you distribute
+copies of the Texinfo related programs, you must give the recipients all
+the rights that you have. You must make sure that they, too, receive or
+can get the source code. And you must tell them their rights.
+
+ Also, for our own protection, we must make certain that everyone finds
+out that there is no warranty for the programs that relate to Texinfo.
+If these programs are modified by someone else and passed on, we want
+their recipients to know that what they have is not what we distributed,
+so that any problems introduced by others will not reflect on our
+reputation.
+
+ The precise conditions of the licenses for the programs currently
+being distributed that relate to Texinfo are found in the General Public
+Licenses that accompany them. The programs that are part of GNU Emacs
+are covered by the GNU Emacs copying terms (@pxref{License, , , emacs,
+The GNU Emacs Manual}), and other programs are covered by licenses that
+are contained in their source files.
+
+@node Overview, Texinfo Mode, License, Top
+@comment node-name, next, previous, up
+@chapter Overview of Texinfo
+@cindex Overview of Texinfo
+@cindex Texinfo overview
+
+Texinfo is a documentation system that uses a single source file for both
+on-line help and a printed manual. This means that instead of writing two
+different documents, one for the on-line help and the other for the printed
+manual, only one document needs to be written. When the system is revised,
+only one file has to be revised.@refill
+
+Using Texinfo, you can create a document with the normal features of a book
+such as chapters, sections, cross references and indices. The chapters and
+sections of the printed manual can be made to correspond to the nodes of
+the on-line help. The cross references and indices can be used in both the
+on-line help and in the printed document. Indices are generated
+semi-automatically. The @cite{GNU Emacs Manual} is a good example of a
+Texinfo file.@refill
+
+To make the printed manual, the Texinfo source file is processed by the
+@TeX{} typesetting program; the resulting DVI file can be typeset and
+printed as a book. To make the on-line help, the Texinfo source file is by
+processed the @kbd{M-x texinfo-format-buffer} command; the resulting Info
+file is installed in the @file{info} directory.@refill
+
+Since the Texinfo source file is used for a dual task---to create both the
+on-line help and the printed manual---it must be written in a special
+format that uses @@-commands (words preceded by an @samp{@@}) to indicate
+chapters, sections, nodes, examples, index entries and the like.@refill
+
+Before writing a Texinfo source file, you should be familiar with the
+on-line Info documentation reading program. (@inforef{Info, info, info},
+for more information.) If you are writing a document that will be both
+on-line and printed, you will need both Info and @TeX{}.
+
+To make an Info file, you use the @kbd{M-x texinfo-format-buffer} command
+in GNU Emacs.@refill
+
+To make a printed manual, you need to use @TeX{}, a powerful,
+sophisticated typesetting program written by Donald Knuth. @TeX{} is
+freely distributable. It is written in a dialect of Pascal called WEB and
+can be compiled either in Pascal or (by using a conversion program that
+comes with the @TeX{} distribution) in C. (For information about getting
+@TeX{}, @pxref{TeX Mode, , , emacs, The GNU Emacs Manual})
+
+When @TeX{} processes a Texinfo source file, @TeX{} makes use of a macro
+definitions file called @file{texinfo.tex} that comes with the GNU Emacs
+distribution in the @file{emacs/man} sources directory. (The first line of
+every Texinfo file has a command that says @code{\input texinfo}; this
+tells @TeX{} to use the @file{texinfo.tex} file.)@refill
+
+If the @file{texinfo.tex} file has not already been copied to the directory
+which contains the other @TeX{} macro definition files when Emacs was
+installed, you will probably want to copy it to that directory. Usually,
+this is the @file{/usr/lib/tex/macros} directory. For more information,
+@pxref{TeX Input, , @TeX{} Input Initialization}
+
+Documentation for GNU utilities and libraries should be written in Texinfo
+format.
+
+@menu
+* Info File:: Characteristics of the Info file.
+* Printed Manual:: Characteristics of the Printed Manual.
+* Conventions:: General Syntactic Conventions.
+* Short Sample:: A short sample Texinfo file.
+@end menu
+
+@node Info File, Printed Manual, , Overview
+@comment node-name, next, previous, up
+@section Characteristics of the Info file
+@cindex Characteristics of the Info file
+@cindex Info file characteristics
+
+A Texinfo file can be transformed into a printed manual and an on-line Info
+file.
+
+An on-line Info file is a file formatted so that the Info documentation
+reading program can operate on it. Info files are divided into pieces
+called @dfn{nodes}, each of which contains the discussion of one topic.
+Each node has a name, and contains both text for the user to read and
+pointers to other nodes, which are identified by their names. The Info
+program displays one node at a time, and provides commands with which the
+user can move to the other nodes to which the current node points.
+
+@ifinfo
+@inforef{Info, info, info}, for more information about using Info.
+@end ifinfo
+
+Normally, most of the nodes are arranged in a tree which branches down.
+Each node may have any number of child nodes that describe subtopics of the
+node's topic. The names of these child nodes, if any, are listed in a
+@dfn{menu} within the parent node; this allows certain Info commands to
+be used to move to one of the child nodes. Each child node records the
+parent node name, as its `Up' pointer. Thus, if a node were at the logical
+level of a `chapter', its child nodes would be `sections'; likewise,
+the child nodes of a section would be subsections.
+
+The root of the tree is the top node of the file, through which users
+enter the file from the Info directory. By convention, this node is always
+called @samp{Top}. This node normally contains just a brief summary of the
+file's purpose, and a large menu through which the rest of the file is
+reached.
+
+Generally you enter the Info file from the top; then you can either traverse
+the file systematically by going from node to node or you can search large
+menus that correspond to indices and go directly to the node that has the
+information you want.
+
+If you want to read through an Info file in sequence, as if it were a
+printed manual, you can get the whole file with the advanced Info command
+@kbd{g *}. (@inforef{Expert, info, info}.)@refill
+
+All the children of any one parent are linked together in a bidirectional
+chain of `Next' and `Previous' pointers. This means that all the nodes
+that are logically parallel to sections within a chapter are all linked
+together. Normally the order in this chain is the same as the order of the
+children in the parent's menu. The last child has no `Next' pointer, and
+the first child normally has the parent as its `Previous' pointer (as well
+as its `Up' pointer, of course).
+
+Structuring the nodes in a tree is a matter of convention, not a
+requirement. In fact, the `Up', `Previous' and `Next' pointers of a node
+can point to any other nodes, and the menu can contain any other nodes.
+The structure of nodes can be any directed graph. But it is usually more
+comprehensible to make it a tree. Info provides another kind of pointer
+between nodes, called a reference, that can be sprinkled through the text
+of a node. This is usually the best way to represent links that do not fit
+the tree structure.
+
+Most often the nodes fall into a strict tree structure that corresponds to
+the structure of chapters and sections in the printed
+manual. But there are times when this is not right for the material being
+discussed. Therefore, Texinfo uses separate commands to specify the node
+structure of the Info file and the section structure of the printed manual.
+Also, Texinfo requires that you specify menus explicitly, rather than
+generate them automatically based on an assumed tree structure.
+
+@node Printed Manual, Conventions, Info File, Top
+@comment node-name, next, previous, up
+@section Characteristics of the Printed Manual
+@cindex Printed manual characteristics
+@cindex Characteristics, printed manual
+
+A Texinfo file can be formatted and typeset as a printed manual. The
+printed manual will be the same as any other book; it will have a title
+page, copyright page, table of contents, and preface as you would expect,
+as well as chapters, numbered or unnumbered sections and subsections, not
+to mention page headers, cross references and indices.
+
+Texinfo can be used for writing a book without ever having the intention of
+converting it into on-line help. Texinfo can be used for writing a novel;
+and it can even be used to write a memo, although this application is not
+recommended since electronic mail is so much easier.
+
+Texinfo uses the formatting language called @TeX{} for typesetting. A file
+called @file{texinfo.tex} contains information (definitions or
+@dfn{macros}) that @TeX{} uses when it typesets a Texinfo file. (The
+macros tell @TeX{} how to convert the Texinfo @@-commands to @TeX{}
+commands which @TeX{} can then process to create the typeset document.)
+@file{texinfo.tex} contains the specifications for printing a document,
+either with 7 inch by 9.25 inch pages or with 8.5 inch by 11 inch pages.
+(This is 178 mm by 235 mm or else 216 mm by 280 mm.) Also, by changing the
+parameters in @file{texinfo.tex} you can easily change the size of the
+printed document. In addition, you can readily change the style in which
+the printed document is formatted; for example, you can change the sizes and
+fonts used, the amount of indentation for each paragraph, the degree to
+which words are hyphenated, and the like. By changing the specifications,
+you can make a book look dignified, old and serious, or light-hearted,
+young and cheery.@refill
+
+@TeX{} is very powerful and has a great many features. Because a Texinfo
+file must be able to present information both on a character-only terminal
+in Info form and in a typeset book, the commands that Texinfo supports are
+necessarily limited.
+
+
+@node Conventions, Short Sample, Printed Manual, Overview
+@comment node-name, next, previous, up
+@section General Syntactic Conventions
+@cindex General syntactic conventions
+@cindex Syntactic conventions
+@cindex Conventions, syntactic
+
+
+Texinfo files contain a strictly limited set of constructs. The strict
+limits make it possible for Texinfo files to be understood both by @TeX{}
+and by the code which converts them into Info files.
+
+All ASCII printing characters except @samp{@@}, @samp{@{} and @samp{@}} can
+appear in body text in a Texinfo file and stand for themselves. @samp{@@}
+is the escape character which introduces commands. @samp{@{} and @samp{@}}
+should be used only to surround arguments to certain commands. @samp{@{}
+and @samp{@}} appearing anywhere else will be treated by @TeX{} as a
+grouping but treated by the code that produces an Info file as themselves;
+this inconsistency is undesirable, so don't let it occur. To put one of
+these special characters into the document, put an @samp{@@} character in
+front of it. For example, you would insert @samp{@@@@}, @samp{@@@{}, and
+@samp{@@@}}.@refill
+
+It is customary in @TeX{} to use doubled single-quote characters to begin
+and end quotations, @samp{``} like these @samp{''}. This convention should
+be followed in Texinfo files. Also, three hyphens in a row, @samp{---},
+are used for a dash---like this. In @TeX{}, a single or even a double
+hyphen produces a dash that is shorter than you want.@refill
+
+@comment Remove for version 19
+
+@TeX{} ignores the line-breaks in the input text, except for blank lines,
+which separate paragraphs. Info generally preserves the line breaks that
+are present in the input file. Therefore, break the lines in the Texinfo
+file the way you want them to appear in the output Info file, and let
+@TeX{} take care of itself.
+
+Since Info does not normally refill paragraphs when it processes them, a
+line with @@-commands in it will sometimes look bad after Info has run on
+it. To cause Info to refill the paragraph after finishing with the other
+processing, you need to put the command @code{@@refill} at the end of the
+paragraph. (@xref{Refilling & Noindent, , Refilling paragraphs and
+Preventing indentation}.)@refill
+
+To prevent a paragraph from being indented in the printed manual, put the
+command @code{@@noindent} on a line by itself before the start of the text
+that should not be indented.
+
+If you mark off a region of the Texinfo file with the @code{@@iftex} and
+@code{@@end iftex} commands so that the region will appear only in the
+printed copy, you can use @TeX{} commands that cannot be used in the Info
+file.
+
+In order to be made into a printed manual, a Texinfo file @strong{must}
+begin with lines that looks like
+
+@example
+\input texinfo @@c -*-texinfo-*-
+@@setfilename @var{info-file-name}
+@@settitle @var{Name of Manual}
+@end example
+
+@noindent
+The @samp{\input texinfo} line tells @TeX{} to use the @file{texinfo.tex}
+file. This line is usually followed by a start-of-header line (not shown
+here) and then by the @samp{@@setfilename @var{info-file-name}} and
+@samp{@@settitle @var{Name of Manual}} lines. These two lines are needed
+to provide a name for the Info file and to specify the name used on the
+left-hand page headers of the printed manual.@refill
+
+The two lines that contain the @code{@@setfilename} and @code{@@settitle}
+commands usually are sandwiched between the start-of-header line and the
+end-of-header line. (@xref{Start-of-Header}, for more information.) The
+start-of-header and end-of-header lines are needed if you are going to run
+@TeX{} or Info on just part of a file.@refill
+
+@node Short Sample, , Conventions, Overview
+@comment node-name, next, previous, up
+@section A Short Sample Texinfo File
+@cindex Sample texinfo file
+
+A Texinfo file looks like the following, which is a complete but very short
+Texinfo file. The @code{@@comment} command introduces comments that will
+not appear in either the Info file or the printed manual; they are for the
+person who reads the Texinfo file.
+
+The first part of the file, from @samp{\input texinfo} through to
+@samp{@@end titlepage}, looks more intimidating than it is. Most of the
+material is standard boilerplate; when you write a manual, you just put in
+the name of your own manual in this section.@refill
+
+All the commands that tell @TeX{} how to typeset the printed manual and
+tell @code{texinfo-format-buffer} how to create an Info file are preceded
+by @samp{@@}; thus, @code{@@node} indicates a node and @code{@@chapter}
+indicates the start of a chapter.
+
+@example
+\input texinfo @@c -*-texinfo-*-
+@@setfilename name-of-texinfo-file
+@@settitle Name of Manual
+@@setchapternewpage odd
+
+@@ifinfo
+@@comment The following line inserts the copyright notice
+@@comment into the Info file.
+Copyright @@copyright@{@} 1988 Free Software Foundation, Inc.
+@@end ifinfo
+
+@@comment The titlepage section does not appear in the Info file.
+@@titlepage
+@@sp 10
+@@comment The title is printed in a large font.
+@@center @@titlefont@{Sample Title@}
+
+@@comment The following two commands start the copyright page
+@@comment for the printed manual. This will not appear in the Info file.
+@@page
+@@vskip 0pt plus 1filll
+Copyright @@copyright@{@} year copyright-owner
+@@end titlepage
+
+@@comment The Top node contains the master menu for the Info file.
+@@comment This appears only in the Info file, not the printed manual.
+
+@@node Top, First Chapter, (dir), (dir)
+@@comment node-name, next, previous, up
+
+@@menu
+* First Chapter:: The first chapter is the
+ only chapter in this sample.
+@@end menu
+
+@@node First Chapter, , Top, Top
+@@comment node-name, next, previous, up
+@@chapter First Chapter
+@@cindex Reference to First Chapter
+
+This is the contents of the first chapter.
+
+Here is a numbered list.
+
+@@enumerate
+@@item
+This is the first item.
+
+@@item
+This is the second item.
+@@end enumerate
+
+The @@kbd@{M-x texinfo-format-buffer@} command transforms a Texinfo file
+like this into an Info file; and @@TeX@{@} typesets it for a printed
+manual.
+
+@@node Concept Index, , Previous Node, Top
+@@comment node-name, next, previous, up
+@@unnumbered Concept Index
+
+@@printindex cp
+
+@@contents
+@@bye
+@end example
+
+Here is what the contents of the first chapter of the sample look like:
+
+@quotation
+
+This is the contents of the first chapter.
+
+Here is a numbered list.
+
+@enumerate
+@item
+This is the first item.
+
+@item
+This is the second item.
+@end enumerate
+
+The @kbd{M-x texinfo-format-buffer} command transforms a Texinfo file like
+this into an Info file; and @TeX{} typesets it for a printed manual.
+@end quotation
+
+@node Texinfo Mode, Beginning a File, Overview, Top
+@comment node-name, next, previous, up
+@chapter Using Texinfo Mode
+@cindex Texinfo mode
+@cindex Mode, using Texinfo
+@cindex GNU Emacs
+@cindex Emacs
+
+In GNU Emacs, Texinfo mode is a major mode for editing Texinfo files.
+This means that Emacs has commands and features especially designed for
+working with Texinfo files. Like all other Emacs features, you can
+customize or enhance these as you wish. In particular, the keybindings are
+very easy to change. The keybindings described here are the default or
+standard ones.
+
+The major features of Texinfo mode are:
+
+@itemize @bullet
+@item
+Paragraph filling control.
+
+@item
+A command to show the structure of the file.
+
+@item
+Pre-defined keystroke commands to insert commonly used strings of text.
+
+@item
+Formatting a part of a file for Info, rather than the whole file.
+@end itemize
+
+In general, in Texinfo mode, the GNU Emacs editing commands are like those
+in text-mode. The major difference is that the paragraph separation
+variable and syntax table are set up so expression commands skip Texinfo
+bracket groups. This means, for example, that the @kbd{M-q}
+(@code{fill-paragraph}) command will refill a paragraph but not the
+@@-command on a line adjacent to it.@refill
+
+By convention, the Texinfo file name shall end with the extension
+@file{.texinfo} so that Emacs knows to use Texinfo mode for editing it.
+
+@menu
+* Info on a Region:: Formatting part of a file for Info.
+* Showing the Structure:: Showing the structure of a file.
+* Inserting:: Inserting frequently used commands.
+@end menu
+
+@node Info on a Region, Showing the Structure, Texinfo Mode, Texinfo Mode
+@comment node-name, next, previous, up
+@section Formatting a Region for Info
+@cindex Running Info on a region
+@cindex Info, formatting on a region
+@findex texinfo-format-region
+
+To see what part of a Texinfo file will look like after it has been
+transformed into an Info file, use the command @kbd{C-c C-f}
+(@code{texinfo-format-region}). This command formats the current region of
+the Texinfo file for Info and writes it to a temporary buffer called
+@samp{*Info Region*}.@refill
+
+For @code{texinfo-format-region} to work, the file @strong{must} include a
+line that has @code{@@setfilename} in its header.@refill
+
+The command is:
+
+@table @kbd
+@item C-c C-f
+texinfo-format-region
+@end table
+
+@node Showing the Structure, Inserting, Info on a Region, Texinfo Mode
+@comment node-name, next, previous, up
+@section Showing the Structure of a File
+@cindex Showing the structure of a file
+@cindex Structure of a file, showing it
+@cindex File structure, showing it
+@cindex Texinfo file structure, showing it
+
+You can show the structure of a Texinfo file by using the @kbd{C-c C-s}
+command (@code{texinfo-show-structure}). This command shows the structure
+of a Texinfo file by listing the lines with the @@-commands for
+@code{@@node}, @code{@@chapter}, @code{@@section} and the like. These
+lines are displayed in another window called the @samp{*Occur*} window. In
+that window, you can position the cursor over one of the lines and use the
+@kbd{C-c C-c} command (@code{occur-mode-goto-occurrence}), to jump to the
+corresponding spot in the Texinfo file.@refill
+
+The two commands are:
+
+@table @kbd
+@item C-c C-s
+texinfo-show-structure
+
+@item C-c C-c
+occur-mode-goto-occurrence
+@end table
+
+Often, when you are working on a manual, you will be interested only in the
+structure of the current chapter. In this case, you can mark off the
+region of the buffer that you are interested in with the @kbd{C-x n}
+(@code{narrow-to-region}) command and @code{texinfo-show-structure} will
+work on only that region. (To see the whole buffer again, use @kbd{C-x w}
+(@code{widen}).)@refill
+
+@node Inserting, , Showing the Structure, Texinfo Mode
+@comment node-name, next, previous, up
+@section Inserting Frequently Used Commands
+@cindex Inserting frequently used commands
+@cindex Frequently used commands, inserting them
+@cindex Commands, inserting them
+
+Texinfo mode provides commands that insert various frequently used
+@@-commands into the buffer. You can use these commands to save
+keystrokes. And you can insert balanced curly braces with the @kbd{M-@{}
+command, (@code{texinfo-insert-braces}) and later use the @kbd{M-@}}
+command (@code{up-list}) to move forward past the closing brace.@refill
+
+The special commands are invoked by typing @kbd{C-c} twice and then the
+first letter of the @@-command.
+
+@table @kbd
+@item C-c C-c c
+texinfo-insert-@@code
+
+@item C-c C-c d
+texinfo-insert-@@dfn
+
+@item C-c C-c e
+texinfo-insert-@@end
+
+@item C-c C-c i
+texinfo-insert-@@item
+
+@item C-c C-c n
+texinfo-insert-@@node
+
+@item C-c C-c s
+texinfo-insert-@@samp
+
+@item C-c C-c v
+texinfo-insert-@@var
+
+@item M-@{
+texinfo-insert-braces
+
+@item M-@}
+up-list
+@end table
+
+This list was generated by analyzing the frequency with which commands were
+used in the @cite{GNU Emacs Manual} and the @cite{GDB Manual}. If you wish
+to add your own insert commands, you can bind a keyboard macro to a key, use
+abbreviations or extend the code in @file{texinfo.el}.
+
+@node Beginning a File, Ending a File, Texinfo Mode, Top
+@comment node-name, next, previous, up
+@chapter Beginning a Texinfo File
+@cindex Beginning a Texinfo file
+@cindex Texinfo file beginning
+@cindex File beginning
+
+Various pieces of information have to be provided to Texinfo at the
+beginning of a Texinfo file, such as the name of the file, the title
+of the document and the like. Generally, the beginning of a Texinfo file
+has four parts:
+
+@enumerate
+@item
+The header, marked by start-of-header and end-of-header lines, that
+includes the commands for naming the Texinfo file and telling @TeX{} what
+definitions' file to use when processing the file.
+
+@item
+A section, marked by the @code{@@ifinfo} and @code{@@end ifinfo} commands,
+that contains a short statement of what the file is about, the copyright
+notice and copying permissions. This section appears only in the Info file.
+
+@item
+A section, marked by the @code{@@titlepage} and @code{@@end titlepage}
+commands, that contains the title page, the copyright page and copying
+permissions. This section appears only in the printed manual.
+
+@item
+The @samp{Top} node that contains an extensive menu for the whole Info
+file. The contents of this node only appear in the Info file.
+@end enumerate
+
+If the Texinfo file has a section containing licensing information and a
+warranty disclaimer, that section usually follows the @samp{Top} node. The
+licensing section will be followed by a preface or else by the first
+chapter of the manual.
+
+Since the copyright notice and the copying permissions are in sections that
+appear only in the Info file or only in the printed manual, this
+information has to be repeated twice.
+
+The following sample shows what is needed.
+
+@example
+\input texinfo @@c -*-texinfo-*-
+@@comment %**start of header (This is for running Texinfo on a region.)
+@@setfilename name-of-texinfo-file
+@@settitle Name of Manual
+@@setchapternewpage odd
+@@comment %**end of header (This is for running Texinfo on a region.)
+
+@@ifinfo
+This file documents @dots{}
+
+Copyright @@copyright@{@} year copyright-owner
+
+Permission is granted to @dots{}
+@@end ifinfo
+
+@@titlepage
+@@sp 10
+@@center @@titlefont@{Name of Manual When Printed@}
+@@sp 2
+@@center Subtitle, If Any
+@@sp 2
+@@center Author
+
+@@comment The following two commands start the copyright page.
+@@page
+@@vskip 0pt plus 1filll
+Copyright @@copyright@{@} year copyright-owner
+
+Published by @dots{}
+
+Permission is granted to @dots{}
+@@end titlepage
+
+
+@@node Top, Overview, (dir), (dir)
+
+@@menu
+* First Chapter:: The first chapter is usually an overview.
+* Second Chapter:: @dots{}
+ <many more menu items here>
+@@end menu
+
+@@node First Chapter, Second Chapter, top, top
+@@comment node-name, next, previous, up
+@@chapter First Chapter
+@@cindex Reference to First Chapter
+@end example
+
+@menu
+* Header:: Necessary first lines.
+* Permissions for Info:: Copyright notice and copying permissions.
+* Titlepage & Copyright Page:: Printed title and copyright pages.
+* Top Node:: The top node and master menu.
+* License and Distribution:: The importance of the license.
+@end menu
+
+@node Header, Permissions for Info , Beginning a File, Beginning a File
+@comment node-name, next, previous, up
+@section The Texinfo File Header
+@cindex Header for Texinfo files
+@cindex Texinfo file header
+
+Texinfo files start with at least three lines that provide Info and @TeX{}
+with necessary information. If you want to run @TeX{} on just a part of
+the Texinfo File, you also have to mark these heading lines with
+start-of-header and end-of-header lines.@refill
+
+@menu
+* First Line:: The first line of a Texinfo file.
+* Start-of-Header:: Identifying the start of the header.
+* Setfilename:: Specifying the name of the Info file.
+* Settitle:: Specifying the title used by the headings.
+* Setchapternewpage:: Starting chapters on odd numbered pages.
+* End-of-Header:: Identifying the end of the header.
+@end menu
+
+@node First Line, Start-of-Header, Header, Header
+@comment node-name, next, previous, up
+@subsection The First Line of a Texinfo File
+@cindex First line of a Texinfo file
+@cindex Beginning line of a Texinfo file
+
+
+Every Texinfo file that is to be the top-level input to @TeX{} must begin
+with a line that looks like this:
+
+@example
+\input texinfo @@c -*-texinfo-*-
+@end example
+
+@noindent
+The line serves two functions:
+
+@enumerate
+@item
+When the file is processed by @TeX{}, it loads the macros needed for
+processing a Texinfo file. These are in a file called @file{texinfo.tex}
+which is usually located in the @file{/usr/lib/tex/macros} directory.@refill
+
+@item
+When the file is edited in GNU Emacs, it causes Texinfo mode to be used.@refill
+@end enumerate
+
+The @samp{\input texinfo} line should be followed by the start-of-header
+line. This makes it possible for the command for running @TeX{} on a part
+of the Texinfo file (@code{texinfo-hardcopy-region}) to operate. The
+reason for this is that the @code{texinfo-hardcopy-region} command will
+look on the line preceding the start-of-header line for the @samp{\input
+texinfo} line.
+
+@node Start-of-Header, Setfilename, First Line, Header
+@comment node-name, next, previous, up
+@subsection @samp{start-of-header}
+@cindex start-of-header
+@findex start-of-header
+
+The start-of-header line should immediately follow the first line of the
+Texinfo file.
+
+@ifinfo
+The @code{texinfo-hardcopy-region} command will look at the
+line preceding the start-of-header line to find the @samp{\input
+texinfo} line.
+@end ifinfo
+
+Usually, the start-of-header line looks like this:
+
+@example
+@@comment %**start of header (This is for running Texinfo on a region.)
+@end example
+
+The reason for the odd string of characters (@samp{%**}) is so that the
+@code{texinfo-hardcopy-region} command does not accidently find something
+that it shouldn't when it is looking for the header.
+
+In the default configuration, the phrase @samp{(This is for running Texinfo
+on a region.)} is not needed and is just included to make it easier for
+someone reading the Texinfo file.
+
+The start-of-header line and the end-of-header line are Texinfo mode
+variables that you can change.
+
+@node Setfilename, Settitle, Start-of-Header, Header
+@comment node-name, next, previous, up
+@subsection @@setfilename
+@cindex Setfilename command
+@cindex Info file requirement for @@setfilename
+@findex setfilename
+
+In order to be made into an Info file, a Texinfo file must contain a line
+that looks like this:
+@example
+@@setfilename @var{info-file-name}
+@end example
+
+@noindent
+This line specifies the name of the Info file to be generated. In fact, there
+can be other things in the file before this line, but they are ignored in
+the generation of an Info file. The @code{@@setfilename} line is ignored
+when a printed manual is generated.
+
+@node Settitle, Setchapternewpage, Setfilename, Header
+@comment node-name, next, previous, up
+@subsection @@settitle
+@findex settitle
+
+In order to be made into a printed manual file, a Texinfo file must contain
+a line that specifies the title of the manual. Texinfo uses this
+information during printing to put the title on every other page as a
+heading; Texinfo puts the current chapter title on the other pages.
+Texinfo can find the name of the chapter title from the information
+provided by the @code{@@chapter} command, but you must tell it the manual
+title with @code{@@settitle}:
+
+@example
+@@settitle @var{Title}
+@end example
+
+@noindent
+This command, on a line by itself, causes @var{title} to be used for the
+headings. Usually, you will use the same words for the title on the title
+page and for the title specified by this command for the headings, but the
+two could be different. For example, the title on the title page may be
+longer than the title specified by the @code{settitle} command.
+
+The @code{@@settitle} command should precede everything that generates
+actual output.
+
+@node Setchapternewpage, End-of-Header, Settitle, Header
+@comment node-name, next, previous, up
+@subsection @@setchapternewpage
+@cindex Starting chapters
+@cindex Pages, starting odd
+@findex setchapternewpage
+
+Conventionally, chapters start on the page on the right hand side of a
+book; and the right hand page has an odd number. To make sure that Texinfo
+does this, you can use the command @code{@@setchapternewpage}. For
+example, to cause each chapter to start on a fresh odd-numbered page:
+
+@example
+@@setchapternewpage odd
+@end example
+
+Page numbering is turned on by the @code{@@end titlepage} command, so the
+@code{@@setchapternewpage} should come before it. Although it can occur
+anywhere in the beginning of the file, it is most convenient to put it in
+this location.
+
+
+@node End-of-Header, , Setchapternewpage, Header
+@comment node-name, next, previous, up
+@subsection @samp{end-of-header}
+@cindex end-of-header
+
+The end-of-header line should follow the line containing the
+@code{@@setchapternewpage} command.
+
+Usually, the end-of-header line looks like this:
+
+@example
+@@comment %**end of header (This is for running Texinfo on a region.)
+@end example
+
+@ifinfo
+In the default configuration, the phrase @samp{(This is for running Texinfo
+on a region.)} is not needed and is just included to make it easier for
+someone reading the Texinfo file.
+
+The reason for the odd string of characters (`%**') is so that the
+@code{texinfo-hardcopy-region} command does not accidently find something
+that it shouldn't when it is looking for the header.
+
+The start-of-header line and the end-of-header line are Texinfo mode
+variables that you can change.
+@end ifinfo
+
+@iftex
+Also, @pxref{Start-of-Header}
+@end iftex
+
+@node Permissions for Info, Titlepage & Copyright Page, Header, Beginning a File
+@comment node-name, next, previous, up
+@section Copying Permissions for Info
+
+Since the title page and the copyright page appear only in the printed copy
+of the manual, the same information has to inserted in a section that
+appears only in the Info file. This section usually contains a brief
+description of the contents of the Info file, a copyright notice and
+copying permissions.
+
+The copyright notice should read:
+
+@example
+Copyright @var{year} @var{copyright-owner}
+@end example
+
+@noindent
+and be put on a line by itself.
+
+Standard text for the copyright permissions is contained in the appendix.
+@xref{Ifinfo Permissions}, for the complete text.
+
+@node Titlepage & Copyright Page, Top Node, Permissions for Info, Beginning a File
+@comment node-name, next, previous, up
+@section The Title and Copyright Pages
+@cindex Titlepage
+@cindex Copyright page
+
+The title and copyright pages appear in the printed manual, but not in the
+Info file. Because of this, it is possible to use a couple of slightly
+obscure @TeX{} typesetting commands that could not be used in an Info file.
+In addition, this part of the beginning of a Texinfo file contains the text
+of the copying permissions that will appear in the printed manual.
+
+@menu
+* Titlepage:: Creating a title page for the printed manual.
+* Center:: Centering a line.
+* Copyright & Printed Permissions:: Inserting the copyright notice
+ and printed permissions.
+@end menu
+
+@node Titlepage, Center , Titlepage & Copyright Page, Titlepage & Copyright Page
+@comment node-name, next, previous, up
+@subsection @@titlepage
+@cindex Titlepage
+@findex titlepage
+
+Start the material for the title page and following copyright page with
+@code{@@titlepage} on a line by itself and end it with @code{@@end
+titlepage} on a line by itself. The title page and copyright page material
+appears only in the printed manual, not in the Info file.
+
+Also, the @code{@@end titlepage} command starts a new page and turns on
+page numbering (generation of headings). Therefore, all the material that
+you want to appear on unnumbered pages should be put between the
+@code{@@titlepage} and @code{@@end titlepage} commands. By using the
+@code{@@page} command you can force a page break within the region
+delineated by the @code{@@titlepage} and @code{@@end titlepage} commands
+and create more than one unnumbered page. This is how the copyright page
+is produced.@refill
+
+@findex titlefont
+To select a large font suitable for the title itself, you can use the
+command @code{@@titlefont}. For example:
+
+@example
+@@center @@titlefont@{Texinfo@}
+@end example
+
+Also, you can use @code{@@sp} commands to adjust vertical spacing.
+For example:
+
+@example
+@@sp 2
+@end example
+
+@noindent
+In the sample, the spacing was chosen to fit an 8 1/2 by 11 inch manual.
+
+@node Center, Copyright & Printed Permissions, Titlepage, Titlepage & Copyright Page
+@comment node-name, next, previous, up
+@subsection @@center
+@cindex Centering a line
+@findex center
+
+A line containing @code{@@center @var{text}} produces a line of output
+containing @var{text}, centered between the margins.@refill
+
+
+
+@node Copyright & Printed Permissions,, Center, Titlepage & Copyright Page
+@comment node-name, next, previous, up
+@subsection The Copyright Page and Printed Permissions
+@cindex Copyright
+@cindex Printed permissions
+@cindex Permissions, printed
+
+By international treaty, the copyright notice for a book should either be
+on the title page or on the back of the title page. Other locations in a
+book are not official and do not provide copyright protection. The
+copyright notice should include the year followed by the name of the person
+or organization who has the copyright.
+
+When the copyright notice is on the back of the title page, the page is not
+numbered. Therefore, in Texinfo, the information on the copyright page
+should be within the region delineated by the @code{@@titlepage} and
+@code{@@end titlepage} commands.@refill
+
+@findex vskip
+@findex filll
+To cause a page break, the @code{@@page} command is used. In the sample,
+the @code{@@page} command is followed by the somewhat mysterious line that
+reads: @samp{@@vskip 0pt plus 1filll}. This is a line that uses @TeX{}
+commands to push the copyright notice and the other text on the copyright
+page towards the bottom of the page. The @code{@@vskip} command means to
+skip lines and put in white space. The @samp{0pt plus 1filll} means to put
+in zero points of mandatory white space, and as much optional white space
+as needed. Note the use of three @samp{l}s in the word @samp{filll}; this
+is the correct use in @TeX{}.@refill
+
+@findex copyright
+The @code{@@copyright@{@}} command generates a @samp{c} inside a circle.
+The copyright notice itself has the following legally defined sequence:
+
+@example
+Copyright @copyright{} @var{year} @var{copyright-owner}
+@end example
+
+It is customary to put information on how to get a manual after the
+copyright notice (the address of the Free Software Foundation, for example)
+and the permissions.
+
+Note that the permissions have to be repeated here as well as in the
+`ifinfo' section that immediately follows the header since this section
+appears only in the printed manual and the `ifinfo' section appears only in
+the Info file.
+
+Standard text for the permissions appears in the appendix.
+@xref{Sample Permissions}.
+
+@node Top Node, License and Distribution, Titlepage & Copyright Page, Beginning a File
+@comment node-name, next, previous, up
+@section The Top Node and Master Menu
+@cindex Top node
+@cindex Master menu
+
+The @samp{Top} node contains an extensive, master menu for the whole Info
+file. The contents of this node appear only in the Info file. Nothing in
+this node should appear in the printed file. Since a node line by itself
+and a menu by itself are not printed, the contents of this node do not have
+to be within a region delineated by @code{@@ifinfo} and @code{@@end ifinfo}
+commands. However, any text within the node should be marked off in that
+manner. You may want to put a short summary before the master menu inside
+a region delineated by @code{@@ifinfo} and @code{@@end ifinfo} commands.
+Usually, the `Previous' and `Up' nodes refer to the top level directory of
+the whole Info system, with pointers to @samp{(dir)}.@refill
+
+Generally, the top menu is divided into parts.
+
+@itemize @bullet
+
+@item
+The first part contains the major nodes in the Texinfo file: the nodes for
+the chapters, chapter-like sections and the major appendices.
+
+@item
+The second part contains entries for the indices. In an Info file, it is
+very useful to have indices here at the beginning of the file in the top
+node rather than at the end, as in a printed book.
+
+@item
+The third and subsequent parts contain a listing of the other, lower level
+nodes, often ordered by chapter. This way, an inquirer can go directly to
+a particular node if he or she is searching for specific information.
+(These nodes are not required; use them if you think they are a
+convenience.)
+@end itemize
+
+Each section in the menu can be introduced a descriptive line. So long as
+the line does not begin with an asterisk, it will not be treated as a menu
+item. (@xref{Menu, , Making Menus}, for more information.)
+
+For example, the Top node of this manual looks like this (but with many
+more entries):
+
+@example
+@@node Top, Overview, (dir), (dir)
+
+@@menu
+* Overview:: What is Texinfo?
+* Texinfo Mode:: Special features in GNU Emacs.
+@dots{}
+
+Indices, nodes containing large menus
+
+* Command Index:: An item for each @@-command.
+* Concept Index:: An item for each concept.
+
+A detailed node listing
+
+Overview
+* Info File:: Characteristics of the Info file.
+* Printed Manual:: Characteristics of the printed manual.
+
+Using Texinfo Mode
+* Info on a Region:: Formatting a region for Info.
+* Showing the Structure:: Showing the structure of a file.
+@dots{}
+@dots{}
+@end example
+
+
+@node License and Distribution, , Top Node, Beginning a File
+@comment node-name, next, previous, up
+@section Licensing and Distribution Information
+@cindex Distribution
+@cindex License agreement
+
+If the Texinfo file has a section containing the ``General Public License''
+and the distribution information and a warranty disclaimer, this section
+usually follows the @samp{Top} node. The licensing and distribution
+information and the disclaimer are followed by a preface or else by the
+first chapter of the manual.
+
+The licensing agreement is very important to Project GNU documentation and
+software. Without it, you may find that you can no longer get the software
+or its documentation. This sounds paradoxical, but the state of the world
+is such that documentation and software that does not have a
+``restrictive'' license to make them freely distributable may be lost to
+the public. This has happened.@refill
+
+For a good example of the text that could be used for the Distribution,
+General Public License and NO WARRANTY sections of your document, see the
+latest version of the @cite{GNU Emacs Manual}.
+
+@cindex Preface
+Although a preface is not a required part of a Texinfo file, it is very
+helpful. Ideally, it should state clearly and concisely what the file is
+about and who would be interested in reading it. In general, the preface
+would follow the licensing and distribution information, although sometimes
+people put it earlier in the document. Usually, a preface is put in an
+@code{@@unnumbered} section. (@xref{Unnumbered and Appendix}.)
+
+@node Ending a File, Structuring, Beginning a File, Top
+@comment node-name, next, previous, up
+@chapter Ending a Texinfo File
+@cindex Ending a Texinfo file
+@cindex Texinfo file ending
+@cindex File ending
+@findex bye
+
+The end of a Texinfo file should include the indices, the commands to
+generate detailed and summary tables of contents and the @@-command
+that tells @TeX{} that it has reached the end of the file.
+
+For example, a Texinfo file might be ended as follows:
+
+@example
+@@node Concept Index, , Previous Node, Top
+@@comment node-name, next, previous, up
+@@unnumbered Concept Index
+
+@@printindex cp
+
+@@contents
+@@bye
+@end example
+
+The @code{@@bye} command should be on a line by itself and every Texinfo
+file must end with such a line. This command terminates @TeX{} processing
+and forces out unfinished pages.@refill
+
+@menu
+* Contents:: Generating a table of contents
+* Indices:: Generating, sorting and printing indices
+@end menu
+
+@node Contents, Indices , , Ending a File
+@comment node-name, next, previous, up
+@section Generating a Table of Contents
+@cindex Table of contents
+@cindex Contents, Table of
+
+The commands @code{@@chapter}, @code{@@section}, etc., supply the
+information to make up a table of contents, but they do not cause an actual
+table to be generated. To do this, you must use the commands
+@code{@@contents} and @code{@@summarycontents}.@refill
+
+@table @code
+
+@item @@contents
+The table of contents command outputs (into a printed manual) a complete
+table of contents, based on the @code{@@chapter}, @code{@@unnumbered} and
+other sectioning commands. This command should be used on a line by
+itself.@refill
+
+@item @@summarycontents
+The summary contents command generates a summary table of contents that
+lists only the chapters (and appendices and unnumbered chapters); sections,
+subsections and subsubsections are omitted. This command should be used on
+a line by itself. Only large manuals need a summary table of
+contents.@refill
+@end table
+
+You can use either one of these commands, or both. Each command
+automatically generates a chapter-like heading at the top of the page.
+Tables of contents should be generated at the very end of the manual, just
+before the @code{@@bye} command; the tables of contents commands should
+follow any indices that are output, so that the indices will appear in the
+contents.@refill
+
+@group
+@example
+@var{indices}@dots{}
+@@summarycontents
+@@contents
+@@bye
+@end example
+@end group
+
+The commands @code{@@contents} and @code{@@summarycontents} are ignored when an
+Info file is being generated.
+
+@node Indices, , Contents, Ending a File
+@comment node-name, next, previous, up
+@section Creating Indices
+@cindex Indices
+@cindex Creating indices
+
+Using Texinfo, you can generate printed indices and Info file menus without
+having to sort and collate entries manually. Texinfo will do this for you
+automatically. Each index covers a certain kind of entry (functions, or
+variables, or concepts, etc.)@: and lists all of those entries in
+alphabetical order, together with information on how to find the discussion
+of each entry. In a printed manual, this information consists of page
+numbers. In an Info file, it consists of a menu item leading to the first
+node referenced.
+
+When you are making index entries, it is good practice to think of the
+different categories under which people may look for something. Different
+people @emph{do not} think of the same words when they look something up.
+They think of different words. A helpful index will have items indexed
+under all the different words that people may use. For example, someone might
+think it obvious that the two letter names for indices should be listed
+under ``Indices, two letter names'', since the word ``Index'' is the
+general concept. But another reader may remember the specific concept of
+two letter names and search for the entry listed as ``Two letter names for
+indices''. A good index will have both entries and will help both kinds of
+user.
+
+Like typesetting, the construction of an index is a highly skilled,
+professional art, the subtleties of which are not appreciated until you
+have to do it yourself.
+
+Normally, six indices are provided for:
+
+@itemize @bullet
+@item
+A @dfn{program index} listing names of programs and leading to the places
+where those programs are documented.@refill
+
+@item
+A @dfn{function index} listing functions (such as, entry points of
+libraries).@refill
+
+@item
+A @dfn{variables index} listing variables (such as, external variables of
+libraries).@refill
+
+@item
+A @dfn{data type index} listing data types (such as, structures defined in
+header files).@refill
+
+@item
+A @dfn{keystroke index} listing keyboard commands.@refill
+
+@item
+A @dfn{concept index} listing concepts that are discussed.@refill
+@end itemize
+
+@noindent
+Not every manual needs all of these. This manual has two indices: a
+concept index and an @@-command index (that uses the function index but is
+called a command index in the chapter heading). Two or more indices can be
+combined into one using the @code{@@synindex} command. @xref{Combining
+Indices}.
+
+@menu
+* Index Entries:: Defining the entries of an index
+* Combining Indices::
+* Printing Indices & Menus::
+@end menu
+
+@node Index Entries, Combining Indices, , Indices
+@comment node-name, next, previous, up
+@subsection Defining the Entries of an Index
+@cindex Defining the entries of an index
+@cindex Index entries
+@cindex Entries for an index
+
+The data to make an index comes from many individual commands scattered
+throughout the Texinfo source file. Each command says to add one entry to
+a particular index; after processing, it will give the current page number
+or node name as the reference.
+
+@table @code
+@item @@cindex @var{concept}
+Make an entry in the concept index for @var{concept}, referring to the
+current page or node.@refill
+@item @@findex @var{function}
+Make an entry in the function index for @var{function}, referring to the
+current page or node.@refill
+@item @@vindex @var{variable}
+Make an entry in the variable index for @var{variable}, referring to the
+current page or node.@refill
+@item @@pindex @var{program}
+Make an entry in the program index for @var{program}, referring to the
+current page or node.@refill
+@item @@kindex @var{key}
+Make an entry in the key index for @var{key}, referring to the
+current page or node.@refill
+@item @@tindex @var{data type}
+Make an entry in the data type index for @var{data type}, referring to the
+current page or node.@refill
+@end table
+
+If the same name is indexed on several pages, all the pages are listed in
+the printed manual's index. However, @strong{only} the @strong{first} node
+referenced will appear in the index of an Info file. This means that it is
+best to write indices in which each entry will refer to only one place in the
+Texinfo file. Fortunately, this constraint is a feature rather than loss
+since it means that the index will be easy to use. Otherwise, it can be
+easy to create an index which has many pages listed for an entry and you
+don't know which one you need.@refill
+
+You are not actually required to use indices for their canonical
+purposes. For example, you might wish to index some C preprocessor macros.
+You could put them in the function index along with actual functions, just
+by writing @code{@@findex} commands for them; then, when you print the
+``function index'', you could give it the title `Function and Macro Index'
+and all will be consistent for the reader. Or you could put the macros in
+with the data types by writing @code{@@tindex} commands for them, and give
+that index a suitable title so the reader will understand.@refill
+
+@node Combining Indices, Printing Indices & Menus, Index Entries, Indices
+@comment node-name, next, previous, up
+@subsection Combining Indices
+@cindex Combining Indices
+@cindex Indices, combining them
+
+Sometimes you will want to combine two disparate indices such as functions
+and variables, perhaps because you have few enough of one of them that
+a separate index for them would look silly.
+
+You could put variables into the function index by writing @code{@@findex}
+commands for them instead of @code{@@vindex} commands, and produce a
+consistent manual by printing the function index with the title `Function
+and Variable Index' and not printing the `Variable Index' at all; but this
+is not a robust procedure. It works only as long as your document is never
+included in part of or together with another document that is designed to
+have a separate variable index; if you did that, the variables from your
+document and those from the other would not end up together.
+
+What you should do instead when you want functions and variables in one
+index is to index the variables with @code{@@vindex} as they should be, but
+use the @code{@@synindex} command to redirect these @code{@@vindex}
+commands to the function index. @code{@@synindex} takes two arguments: the
+name of an index to redirect, and the name of an index to redirect it to.
+For this purpose, the indices are given two-letter names:
+@cindex Two letter names for indices
+@cindex Indices, two letter names
+@cindex Names for indices
+
+@table @samp
+@item cp
+the concept index
+@item vr
+the variable index
+@item fn
+the function index
+@item ky
+the key index
+@item pg
+the program index
+@item tp
+the data type index
+@end table
+
+Thus, @code{@@synindex vr fn} at the front of a Texinfo file
+will cause all entries designated for the variable index to go to
+the function index instead.
+
+@node Printing Indices & Menus, , Combining Indices, Indices
+@comment node-name, next, previous, up
+@subsection Printing an Index and Generating Menus
+@cindex Printing an index
+@cindex Indices, printing
+@cindex Generating menus with indices
+@cindex Menus generated with indices
+
+To print an index means to include it as part of a manual or Info file.
+This does not happen automatically just because you use @code{@@cindex} or
+other index-entry generating commands in the Texinfo file; those just cause
+the raw data for the index to be accumulated. To print an index, you must
+include the @code{@@printindex} command at the place in the document where
+you want the index to appear. Also, for the case of the printed manual,
+you must run a program called @code{texindex} to sort the raw data to
+produce a sorted index file, which is what will actually be used to print
+the index.@refill
+
+The Texinfo command that is used to print indices is @code{@@printindex}.
+It takes the two-letter index name (@pxref{Combining Indices}) as an
+argument without braces, and reads the corresponding sorted index file and
+formats it appropriately into an index.@refill
+
+@ifinfo
+The two-letter index names are:
+
+@table @samp
+@item cp
+the concept index.
+@item vr
+the variable index.
+@item fn
+the function index.
+@item ky
+the key index.
+@item pg
+the program index.
+@item tp
+the data type index.
+@end table
+@end ifinfo
+
+@code{@@printindex} does not generate a chapter heading for the index.
+Consequently, you should precede the command with a suitable section or
+chapter command (usually @code{@@unnumbered}) to supply the chapter heading
+and put the index into the table of contents. And before that, you will
+probably put a @code{@@node} command. For example,@refill
+
+@example
+@@node Variables Index, Concept Index, Function Index, Top
+@@comment node-name, next, previous, up
+@@unnumbered Variable Index
+
+@@printindex vr
+
+@@node Concept Index, , Variables Index, Top
+@@comment node-name, next, previous, up
+@@unnumbered Concept Index
+
+@@printindex cp
+
+@@summarycontents
+@@contents
+@@bye
+@end example
+
+In @TeX{}, @code{@@printindex} needs a sorted index file to work from.
+@TeX{} does not know how to do sorting; this is one of the main
+deficiencies of @TeX{}. You must invoke the program @code{texindex} to do
+so, giving it the names of the raw index files to be sorted as arguments.
+You do not have to run @code{texindex} on all of them; only the ones you
+are going to print. (@xref{Printing Hardcopy}, for more information.)
+
+@node Structuring, Quotations and Examples, Ending a File, Top
+@comment node-name, next, previous, up
+@chapter Node and Chapter Structuring
+@cindex Node and chapter structuring
+@cindex Chapter structuring
+@cindex Node structuring
+@cindex Structuring of nodes and chapters
+@findex node
+
+The chapter structuring commands divide a document into a hierarchy of
+chapters, sections, subsections and subsubsections. These commands
+generate large headings.
+
+In a printed manual, the table of contents is based on the information
+specified by the chapter structuring commands.
+
+Although the chapter structuring commands used for creating a printed
+document are entirely different from the node commands for structuring an
+Info file, you are likely to use the two kinds of command together since
+the single Texinfo file is usually designed to be read both as an Info file
+and as a printed manual. The only time you are likely to use the chapter
+structuring commands without using the node structuring commands is if you
+are writing a document that will never be put into Info format, for
+example, a novel, a letter, an article or a memorandum.
+
+It is unlikely that you will ever write a Texinfo file that is only
+intended as an on-line Info file and not as a printable document. However,
+Texinfo is flexible enough so that you can do this if you wish.
+
+Although a Texinfo file can be structured in a variety of ways, it is
+usually structured like a book with chapters, sections, subsections and the
+like. This structure can also be visualized as a tree (or rather as an
+upside down tree) with the root at the top and each level corresponding to
+chapters or sections or whatnot. In Info format, you reach the nodes on
+each level by using the the `Next' and `Previous' pointers in the node
+line. For example, you go from one chapter to the next or previous chapter
+by using the the pointers to the next and previous chapters. In Info, you
+go the level above by using an `Up' pointer and you go to the level below
+through a `Menu'. In the printed manual, cross references are indicated by
+page and section numbers; in the on-line file, cross references are
+specified by inline menu items.
+
+@group
+Here is a diagram that shows a Texinfo file with three chapters;
+each chapter has two sections.
+
+@example
+ top
+ |
+ |
+ ---------------------------------------------
+ | | |
+ | | |
+ Chapter 1 Chapter 2 Chapter 3
+ | | |
+ | | |
+ ---------- ---------- ----------
+ | | | | | |
+ Sect. 1.1 Sect. 1.2 Sect. 2.1 Sect. 2.2 Sect. 3.1 Sect. 3.2
+
+@end example
+@end group
+
+In this structure, the node for Chapter 2 looks like this:
+
+@example
+@@node Chapter 2, Chapter 3, Chapter 1, top
+@@comment node-name, next, previous, up
+@end example
+
+To get to Sections 2.1 and 2.2, you need a menu inside of Chapter 2 that
+says:
+
+@example
+ @@menu
+ * Sect. 2.1:: Description of this section.
+ * Sect. 2.2::
+ @@end menu
+@end example
+
+@noindent
+This menu is located inside Chapter 2, after the beginning of the chapter,
+just before Section 2.1.
+
+Note that a menu entry has three parts: the menu item name, the name of the
+node and, optionally, a description of the item (in that order). If the
+menu item name and the name of the node are the same, you can put two
+colons after the item name, as is shown in the example. (If the second part
+is different from the first, the first part is terminated by a colon and
+the second part terminated by a tab, newline, comma or period.)
+(@xref{Menu}.)
+
+The node for Sect. 2.1 will look like this:
+
+@example
+ @@node Sect. 2.1, Sect. 2.2, , Chapter 2
+ @@comment node-name, next, previous, up
+@end example
+
+This node does not have a `Previous' node.
+
+
+Usually, an @code{@@node} command and a chapter structuring command are
+used in sequence, along with indexing commands. For example, the node for
+the chapter on ending a file looks like this:
+
+@group
+@example
+@@node Ending a File, Structuring, Beginning a File, Top
+@@comment node-name, next, previous, up
+@@chapter Ending a Texinfo File
+@@cindex Ending a Texinfo file
+@@cindex Texinfo file ending
+@@cindex File ending
+@end example
+@end group
+
+The chapter structuring commands fall into four groups that have the
+characteristics of chapters, sections, subsections and subsubsections.
+The groups are:
+
+@group
+@table @code
+@item @@chapter
+@itemx @@unnumbered
+@itemx @@appendix
+For chapters and chapter-like parts of a document.
+
+@item @@section
+@itemx @@unnumberedsec
+@itemx @@appendixsec
+For sections and section-like parts of a document.
+
+@item @@subsection
+@itemx @@unnumberedsubsec
+@itemx @@appendixsubsec
+For subsections and subsection-like parts of a document.
+
+@item @@subsubsection
+@itemx @@unnumberedsubsubsec
+@itemx @@appendixsubsubsec
+For subsubsections and subsubsection-like parts of a document.
+@end table
+@end group
+
+In the sections that follow, the chapter structuring commands are described
+first and then the @code{@@node} and @code{@@menu} commands.
+
+@menu
+* Chapter::
+* Unnumbered and Appendix::
+* Section::
+* Subsection::
+* Subsubsection::
+* Node::
+* Menu::
+@end menu
+
+@node Chapter, Unnumbered and Appendix, , Structuring
+@comment node-name, next, previous, up
+@section @@chapter
+@findex chapter
+
+@code{@@chapter} identifies a chapter in the document. It is followed by a
+single argument which is the rest of the line, as in
+
+@example
+@@chapter Node and Chapter Structuring
+@end example
+
+In @TeX{}, it creates a chapter in the document, specifying the chapter
+title.
+
+In the Info file, @code{@@chapter} causes its argument to appear on a line
+by itself, with a line of asterisks inserted underneath. Thus, the above
+example produces the following output:@refill
+
+@example
+Node and Chapter Structuring
+****************************
+@end example
+
+@node Unnumbered and Appendix, Section, Chapter, Structuring
+@comment node-name, next, previous, up
+@section @@unnumbered, @@appendix
+@findex unnumbered
+@findex appendix
+
+These commands are equivalent to @code{@@chapter} for Info file output.
+(@xref{Chapter}.) In a printed manual, they generate chapters that are
+numbered differently in the table of contents. @code{@@unnumbered}
+chapters appear without chapter numbers of any kind, and @code{@@appendix}
+chapters are given a letter instead of a number.
+
+@node Section, Subsection, Unnumbered and Appendix, Structuring
+@comment node-name, next, previous, up
+@section @@section
+@findex section
+
+@code{@@section} is like @code{@@chapter} except that in @TeX{} it makes a
+section rather than a chapter. (@xref{Chapter}.) Sections go within
+chapters. In the Info file, @code{@@chapter} and @code{@@section} differ
+only in that @code{@@section} underlines with @samp{=}. For example,@refill
+
+@example
+This is a section
+=================
+@end example
+
+@section @@unnumberedsec, @@appendixsec
+@findex unnumberedsec
+@findex appendixsec
+
+Use these constructs for sections within chapters made by
+@code{@@unnumbered} or @code{@@appendix}. (@xref{Section}.)@refill
+
+@node Subsection, Subsubsection, Section, Structuring
+@comment node-name, next, previous, up
+@section @@subsection
+@findex subsection
+
+Subsections are to sections as sections are to chapters. (@xref{Section}.)
+They are underlined with @samp{-}. For example,@refill
+
+@example
+This is a subsection
+--------------------
+@end example
+
+@section @@unnumberedsubsec, @@appendixsubsec
+@findex unnumberedsubsec
+@findex appendixsubsec
+
+Use these constructs for subsections within sections within chapters made
+by @code{@@unnumberedsec} or @code{@@appendixsec}. (@xref{Subsection}.)@refill
+
+@node Subsubsection, Node, Subsection, Structuring
+@comment node-name, next, previous, up
+@section @@subsubsection And Other Subsection Commands
+@findex unnumberedsubsubsec
+@findex appendixsubsubsec
+@findex subsubsection
+
+Subsubsections are to subsections as subsections are to sections.
+(@xref{Subsection}.) They are underlined with periods. The equivalent
+commands for @code{@@unnumberedsubsec} and @code{@@appendixsubsec} are
+@code{@@unnumberedsubsubsec} and @code{@@appendixsubsubsec}. For
+example,@refill
+
+@example
+This is a subsubsection
+.......................
+@end example
+
+
+@node Node, Menu, Subsubsection, Structuring
+@comment node-name, next, previous, up
+@section @@node
+
+@code{@@node} defines the beginning of a new node in the Info output file
+(@inforef{Top, info, info}.). It is followed by four arguments, separated
+by commas, that make up the rest of the line. Since it is often hard to
+remember the order in which are arguments are listed, @code{texinfo-mode}
+provides the @kbd{C-c C-c n} command (@code{texinfo-insert-@@node}) which
+automatically inserts a comment line listing the arguments. For
+example,@refill
+
+@example
+@@node Texinfo Mode, Beginning a File, Overview, Top
+@@comment node-name, next, previous, up
+@end example
+
+@noindent
+defines a node named @samp{Texinfo Mode}, whose `Next' pointer is to node
+@samp{Beginning a File}, whose `Previous' pointer is to node
+@samp{Overview}, and whose `Up' pointer is to node @samp{Top}. What this
+means is that Texinfo changes @w{@code{@@node @var{args}}} into the special
+text string necessary to separate Info nodes and to identify the node that
+is starting and say what nodes it points to.@refill
+
+The pointer names should be the names of nodes defined elsewhere. For this
+example, nodes named @samp{Beginning a File}, @samp{Overview} and
+@samp{Top} should be defined elsewhere in the file with other @code{@@node}
+commands. It does not matter whether they are before or after the node
+that refers to them.@refill
+
+Normally, a node's `Up' pointer should point at the node whose menu
+mentions that node. The node's `Next' pointer should point at the node
+that follows that node and its `Previous' pointer should point at the node
+that precedes it in that menu.@refill
+
+In @TeX{}, @code{@@node} is nearly ignored. It generates no text. Its
+only function is to identify the name to use for cross-references to the
+chapter or section which follows the @code{@@node} command and which which
+makes up the body of the node. (Cross references are made with
+@code{@@xref}. @xref{Cross References}.)@refill
+
+@code{@@node} should be followed immediately by a chapter-structuring
+command such as @code{@@chapter}, @code{@@section}, @code{@@subsection} or
+@code{@@subsubsection}.@refill
+
+The easiest way to write a node is to use the Texinfo mode keyboard command
+@kbd{C-c C-c n} to insert @samp{@@node} and a comment line listing the
+names of each of the pointers in their proper order. This way you won't
+lose track of which arguments are for which pointers. The template is
+especially useful if you are not familiar with Texinfo. It is important to
+pick a suitable node name. Generally, these begin with an uppercase letter
+as if the node name were a heading for a chapter or section. Do not use
+any of the Texinfo @@-commands in the name; these commands confuse Info.
+The node name should be informative. Unfortunately, long names will not
+fit onto the line, which can be awkward. Sometimes it is better to use
+long but informative names rather than short ones.
+
+Some people insert the names of the `Next', `Previous' and `Up' pointers at
+the same time they insert the node's own name. This is because it is
+easier to keep track of the node structure as you create a document than it
+is to sort it out after you have dozens of nodes. Others wait to insert
+the `Next', `Previous' and `Up' pointers until they have a nearly final
+version of the document. This is because they expect to change the
+organization of the document while they write it and insert or delete
+sections and move them around. The command @code{texinfo-show-structure}
+can be used to find the `Next', `Previous' and `Up' pointers of a node.
+(See @xref{Using texinfo-show-structure}.)
+
+However you do it, it is best to name the node whenever you write the
+section so you can easily make cross references to the section. A large
+number of cross references are an especially important feature of a good
+Info file.
+
+After you have inserted the node-line, you should immediately write an
+@@-command for the chapter or section and insert its name. Next, (and this
+is important!), put in several index entries. Usually, you will find at
+least two and often as many as four or five ways of referring to the node
+in the index. Use them all. This will make it much easier for people to
+find the node.@refill
+
+The top node of the file, named @samp{Top}, should have as its parent the
+name of a node in another file, where there is a menu that leads to this
+file. Specify the file name in parentheses. If the file is to be
+installed directly in the Info directory file, use @samp{(dir)} as the
+parent of the top node; this is short for @samp{(dir)top}, the node @samp{top}
+in the file @file{dir}, which is the main menu of Info. For example,@refill
+
+@example
+@@node Top, Overview, (dir), (dir)
+@@comment node-name, next, previous, up
+@end example
+
+For more information about installing an Info file in the @file{info}
+directory, @pxref{Installing an Info File}
+
+@node Menu, , Node, Structuring
+@comment node-name, next, previous, up
+@section @@menu
+@cindex Menus
+@findex menu
+
+Info file nodes can contain @dfn{menus} which point to other nodes. You
+must type the menus in by hand, and surround them with lines containing
+@code{@@menu} and @code{@@end menu}. In Info, the @code{@@menu} line
+changes into @samp{* Menu:}, which indicates the beginning of a menu to the
+Info program. Otherwise, the contents are unchanged by Texinfo, except for
+the processing of any other @@-commands within. The entire menu construct
+has no effect in the printed manual and will not appear there.@refill
+
+By convention, a menu is put at the end of a node. This way, it is easy
+for someone using Info to find the menu, using the @kbd{M->}
+(@code{end-of-buffer}) command.
+
+In a menu, every line that begins with a @samp{*} lists a single topic. A
+line that does not start with a @samp{*} will also appear in the menu and
+can be used as a comment.
+
+A menu item has three parts:
+
+@enumerate
+@item
+The menu item name.
+
+@item
+The name of the node.
+
+@item
+A description of the item.
+@end enumerate
+
+@noindent
+Only the first part is required. This part is the name of the topic---the
+name of the menu item that the user must give to the @kbd{m} command to
+select this topic when using Info. The first part comes right after the
+asterisk and a space, and is followed by a colon, spaces and tabs, and then
+the name of the node which discusses that topic. The name of the node is
+terminated by a tab, comma, newline or period. If the node name and topic
+name are the same, rather than give the name twice, put two colons after
+the name instead. For example, @samp{* Name::}. (You should do this
+whenever possible, since it reduces visual clutter in the menu).
+
+If the second part is present, it may be terminated with a tab, comma, or
+newline; or with a period.
+
+For example,@refill
+
+@group
+@example
+@@menu
+A Section on Foo and Switches
+* Foo:: The node named Foo tells you how to go fooing.
+* Sw: Switches. Type @@code@{m Sw@} to see node @@code@{Switches@}
+ which describes the switches available here.
+@@end menu
+@end example
+@end group
+
+@noindent
+produces
+
+@group
+@example
+* menu:
+
+A Section on Foo and Switches
+* Foo:: The node named foo tells you how to go fooing.
+* Sw: Switches. Type `m Sw' to see node `Switches'
+ which describes the switches available here.
+@end example
+@end group
+
+In this example, the menu has two items. @samp{Foo} is both a menu item
+name and the name of the node referred to by that item. @samp{Sw} is the
+other menu item name, and it refers to the node named @samp{Switches}.
+Since no file name is specified with @samp{Foo} or @samp{Switches}, they
+must be the names of other nodes in the same Info file.
+
+Nodes in other Info files can be referred to by putting the file name in
+parentheses at the beginning of the node name. For example,
+
+@example
+@@menu
+* Outlining: (emacs) Outline Mode. The major mode for editing outlines.
+* Rebinding: (emacs) Rebinding. How to redefine the meaning of a key.
+@@end menu
+@end example
+
+@noindent
+When this is done, the item has to have at least two parts: the first part
+is the menu item name and the second part is the name of the node.
+
+@node Quotations and Examples, Lists and Tables, Structuring, Top
+@comment node-name, next, previous, up
+@chapter Making Quotations and Examples
+@cindex Quotations
+@cindex Examples
+
+Quotations and examples are blocks of text, consisting of one or more whole
+paragraphs that are set off from the bulk of the text and treated
+differently. They are usually indented.
+
+In Texinfo, an insertion is always begun by writing an @@-command on a line
+by itself, and ended by writing an @code{@@end} command that is also on a
+line by itself. For instance, an @dfn{example} is a kind of insertion that
+is begun with @code{@@example} and ended with @code{@@end example}.@refill
+@findex end
+
+There are three commands for quotations and examples:
+
+@table @code
+@item @@quotation
+Used to indicated text that is quoted.@refill
+
+@item @@example
+Used to illustrate code, commands and the like in a fixed width font
+without filling.@refill
+
+@item @@display
+Used for illustrative text.
+@end table
+
+@menu
+* Quotation::
+* Example::
+* Display::
+@end menu
+
+@node Quotation, Example, , Quotations and Examples
+@comment node-name, next, previous, up
+@section @@quotation
+@cindex Quotations
+@findex quotation
+
+@code{@@quotation} is used to indicate text that is excerpted from another
+(real or hypothetical) printed work. The inside of a quotation is
+processed normally except that
+
+@enumerate
+@item
+The margins are narrower.
+@item
+Paragraphs are not indented.
+@item
+Interline spacing and interparagraph spacing are reduced.
+@end enumerate
+
+Thus, the input
+
+@example
+@@quotation
+This is
+a foo.
+@@end quotation
+@end example
+
+@noindent
+produces in the printed manual
+
+@quotation
+@quotation
+This is a foo.
+@end quotation
+@end quotation
+
+@noindent
+and in the Info file
+
+@quotation
+@example
+This is
+a foo.
+@end example
+@end quotation
+
+@node Example, Display, Quotation, Quotations and Examples
+@comment node-name, next, previous, up
+@section @@example
+@cindex Examples
+@findex example
+
+@code{@@example} is used to indicate an example that is not part of the
+running text. In the printed manual, this is done by switching to
+a fixed width font, turning off filling, and making extra spaces
+and blank lines significant. In the Info file, an analogous result
+is obtained by indenting each line with five extra spaces.
+
+@code{@@example} should appear on a line by itself; this line will
+disappear from the output. Mark the end of the example with a line
+containing @code{@@end example}, which will likewise disappear. For
+example:@refill
+
+@example
+@@example
+mv foo bar
+@@end example
+@end example
+
+@noindent
+produces
+
+@example
+mv foo bar
+@end example
+
+Since the lines containing @code{@@example} and @code{@@end example} will
+disappear, you will want to put a blank line before the @code{@@example} and
+another blank line after the @code{@@end example}. (Remember that blank
+lines between the beginning @code{@@example} and the ending @code{@@end
+example} will appear in the output.)@refill
+
+Don't use tabs in lines of an example! @TeX{} has trouble with tabs: it
+treats them like single spaces, and that is not what they look like.
+
+@node Display, , Example, Quotations and Examples
+@comment node-name, next, previous, up
+@section @@display
+@cindex Display
+@findex display
+
+@code{@@display} is just like @code{@@example} except that, in the
+printed manual, @code{@@display} does not select the fixed-width font.
+In fact, it does not specify the font at all, so that the text appears
+in the same font it would have appeared in without the @code{@@display}.@refill
+
+
+@node Lists and Tables, Cross References, Quotations and Examples, Top
+@comment node-name, next, previous, up
+@chapter Making Lists and Tables
+@cindex Making lists and tables
+@cindex Lists and tables, making them
+@cindex Tables and lists, making them
+
+Texinfo has several ways of making lists and two-column tables. Lists can
+be bulleted or numbered while two-column tables can highlight the items in
+the first column.
+
+For example, this is an enumerated list:
+
+@enumerate
+@item
+This is a numbered item.
+
+@item
+This is the second item in this list.
+
+@item
+This is the third item on this list.
+@end enumerate
+
+Texinfo will automatically indent the text in lists or tables and number an
+enumerated list. This last feature is useful if you are reordering the
+list, since you do not have to renumber it yourself.
+
+Lists or tables are always begun by an @@-command on a line by itself and
+ended with an @code{@@end} command on a line by itself. For example, an
+enumerated list begins with the command @code{@@enumerate} and ends with
+the command @code{@@end enumerate}; and an itemized list begins with the
+command @code{@@itemize} and ends with the command @code{@@end
+itemize}.@refill
+@findex end
+
+The elements of a list are begun with the @code{@@item} command.
+
+Here is an itemized list of the different kinds of table and lists:
+
+@itemize @bullet
+@item
+Itemized lists with or without bullets.
+
+@item
+Numbered lists.
+
+@item
+two-column tables with highlighting.
+@end itemize
+
+@menu
+* Itemize::
+* Enumerate::
+* Table::
+@end menu
+
+@node Itemize, Enumerate, , Lists and Tables
+@comment node-name, next, previous, up
+@section @@itemize
+@cindex Itemize
+@findex itemize
+
+@code{@@itemize} is used to produce sequences of indented paragraphs, with
+a mark inside the left margin at the beginning of each paragraph. The rest
+of the line that starts with @code{@@itemize} should contain the character
+or Texinfo commands to generate such a mark. Usually, it is the @@-command
+@code{@@bullet}. Whatever mark you choose, ultimately, it should result in
+a single character in the Texinfo file, or the indentation will come out
+wrong. When you write the command, omit the @samp{@{@}} after the command
+if you use just one command and nothing else.
+
+The text of the indented paragraphs themselves come after the @code{@@itemize},
+up to another line that says @code{@@end itemize}.
+
+Before each paragraph for which a mark in the margin is desired, place a
+line that says just @code{@@item}. Don't put any other text on this line.
+@findex item
+
+Info indents the lines in an itemized list by five columns, but it does not
+fill them. This can produce lines in the Info file that are too wide. You
+can either write shorter lines in the Texinfo file by setting the fill
+column to five columns less than it is normally, or else you can tell Info
+to refill the paragraphs by adding the @@-command @code{@@refill} to the
+end of the paragraph. (@xref{Refill}, for more information about the use of
+the @code{@@refill} command.)
+
+Usually, you should put a blank line before an @code{@@item}. This puts a
+blank like in the Info file. Except when the entries are very brief, a
+blank line looks better.
+
+Here is an example of the use of @code{@@itemize}, followed by the output
+it produces. Note that @code{@@bullet} produces a @samp{*} in Texinfo and
+a round dot in @TeX{}.
+
+@group
+@example
+@@itemize @@bullet
+@@item
+Some text for foo.
+
+@@item
+Some text
+for bar.
+@@end itemize
+@end example
+@end group
+
+@noindent
+produces
+
+@group
+@quotation
+@itemize @bullet
+@item
+Some text for foo.
+
+@item
+Some text
+for bar.
+@end itemize
+@end quotation
+@end group
+
+@node Enumerate, Table, Itemize, Lists and Tables
+@comment node-name, next, previous, up
+@section @@enumerate
+@cindex Enumerate
+@findex enumerate
+
+@code{@@enumerate} is like @code{@@itemize} except that the marks in the
+left margin contain successive integers starting with 1. (@xref{Itemize}.)
+Do not put any argument on the same line as @code{@@enumerate}.@refill
+
+@group
+@example
+@@enumerate
+@@item
+Some text for foo.
+@@item
+Some text
+for bar.
+@@end enumerate
+@end example
+@end group
+
+@noindent
+produces
+
+@quotation
+@enumerate
+@item
+Some text for foo.
+@item
+Some text
+for bar.
+@end enumerate
+@end quotation
+
+If you want, you can put a blank line between the entries in the list.
+This often makes it easier to read the Info file. For example,
+
+
+@group
+@example
+@@enumerate
+@@item
+This is the first item.
+
+@@item
+This is the second item.
+@@end enumerate
+@end example
+@end group
+
+@ifinfo
+Info indents the lines of the enumerated list by five columns, but it does
+not fill them. As a result, the lines in the Info file may be too wide.
+To prevent this, you can either write shorter lines in the Texinfo file
+file by setting the fill column to five columns less than it is normally,
+or else you can tell Info to refill the paragraphs by adding the @@-command
+@code{@@refill} to the end of the paragraph. (@xref{Refill}, for more
+information about the use of the @code{@@refill} command.)
+@end ifinfo
+
+@iftex
+Info indents the lines of the enumerated list by five columns, but it does
+not fill them, just as it does with an itemized list. You may want to use
+shorter lines for text within an enumerated list or use the @code{@@refill}
+command at the end of the paragraph. (@xref{Refill}, for more information
+about the use of the @code{@@refill} command.)
+@end iftex
+
+@node Table, , Enumerate, Lists and Tables
+@comment node-name, next, previous, up
+@section @@table
+@cindex Tables, making two-column
+@findex table
+
+@code{@@table} is similar to @code{@@itemize}, but allows you to specify a
+name or heading line for each item. (@xref{Itemize}.) The command is used
+to produce two-column tables, and is especially useful for glossaries and
+explanatory exhibits.@refill
+
+You must follow each use of @code{@@item} inside of @code{@@table} with
+text to serve as the heading line for that item. This text is put on the
+same line as the @code{@@item} command. Each heading line is put into the
+first column of the table and the supporting text, which you put on the line
+following the line beginning with @code{@@item}, goes into the second
+column.@refill
+@findex item
+
+Also, @code{@@table} itself must be followed by an argument that is a
+Texinfo command such as @code{@@code}, @code{@@var}, @code{@@kbd} or
+@code{@@asis}. Although these commands are usually followed by arguments
+in braces, in this case you use the command name without an argument.
+(@code{@@item} supplies the argument.) This command will be applied to
+the text that goes into the first column of each item and determines how it
+will be highlighted. For example, @code{@@samp} will cause the text in the
+first column to be highlighted as if it were acted on by an @code{@@samp}
+command.@refill
+
+@code{@@asis} is a command that does nothing; in that case, each item will
+come out without highlighting, unless that particular piece of text
+contains @@-commands for highlighting.@refill
+
+(Various other command names might work with @code{@@table}. However, only
+commands that normally take arguments in braces may be used.)@refill
+
+@ifinfo
+Usually, you should put a blank line before an @code{@@item}. This puts a
+blank like in the Info file. Except when the entries are very brief, a
+blank line looks better.
+@end ifinfo
+
+The following table, for example, highlights the text in the first column
+as if each item were acted on by an @code{@@samp} command:@refill
+
+@example
+@@table @@samp
+@@item foo
+This is the text for
+@@samp@{foo@}.
+
+@@item bar
+Text for @@samp@{bar@}.
+@@end table
+@end example
+
+@noindent
+produces
+
+@quotation
+@table @samp
+@item foo
+This is the text for
+@samp{foo}.
+@item bar
+Text for @samp{bar}.
+@end table
+@end quotation
+
+Info indents the lines of text in the second column, but does not fill
+them. As a result, the lines in the Info file may be too wide. To prevent
+this, cause Info to refill the paragraphs after processing by adding the
+@@-command @code{@@refill} to the end of the paragraph. (@xref{Refill}, for
+more information about the use of the @code{@@refill} command.)
+
+If you want to list two or more named items with a single block of text,
+use the @code{@@itemx} command.
+
+@menu
+* Itemx::
+@end menu
+
+@node Itemx, , Table, Table
+@comment node-name, next, previous, up
+@subsection @@itemx
+@cindex Itemx
+@findex itemx
+
+@code{@@itemx} is used inside a @code{@@table} when you have two or more
+named items for the same block of text. Use @code{@@itemx} for all but the
+first of the items. It works exactly like @code{@@item} except that it
+does not generate extra vertical space above the item text.
+For example,@refill
+
+@example
+@@table @@code
+@@item upcase
+@@itemx downcase
+These two functions accept a character or a string as argument,
+and return the corresponding upper case (lower case) character
+or string. @@refill
+@@end table
+@end example
+
+@noindent
+produces
+
+@quotation
+@table @code
+@item upcase
+@itemx downcase
+These two functions accept a character or a string as argument,
+and return the corresponding upper case (lower case) character
+or string. @refill
+@end table
+@end quotation
+
+A more complicated example of the use of @code{@@itemx} comes from the
+chapter on structuring commands. Here is how the list showing how
+the chapter structuring commands fall into four groups was constructed.
+(@xref{Structuring, , Chapter Structuring Commands}.)
+
+@group
+@example
+@@table @@code
+@@item @@@@chapter
+@@itemx @@@@unnumbered
+@@itemx @@@@appendix
+For chapters and chapter-like parts of a document.
+
+@@item @@@@section
+@@itemx @@@@unnumberedsec
+@@itemx @@@@appendixsec
+For sections and section-like parts of a document.
+
+@@item @@@@subsection
+@@itemx @@@@unnumberedsubsec
+@@itemx @@@@appendixsubsec
+For subsections and subsection-like parts of a document.
+
+@@item @@@@subsubsection
+@@itemx @@@@unnumberedsubsubsec
+@@itemx @@@@appendixsubsubsec
+For subsubsections and similar parts of a document.
+@@end table
+@end example
+@end group
+
+@noindent
+and this is what the resulting table looks like:
+
+
+@table @code
+
+@item @@chapter
+@itemx @@unnumbered
+@itemx @@appendix
+For chapters and chapter-like parts of a document.
+
+@item @@section
+@itemx @@unnumberedsec
+@itemx @@appendixsec
+For sections and section-like parts of a document.
+
+@item @@subsection
+@itemx @@unnumberedsubsec
+@itemx @@appendixsubsec
+For subsections and subsection-like parts of a document.
+
+@item @@subsubsection
+@itemx @@unnumberedsubsubsec
+@itemx @@appendixsubsubsec
+For subsubsections and similar parts of a document.
+@end table
+
+
+Also, either column of a table can be empty.
+
+@node Cross References, Formatting Paragraphs, Lists and Tables, Top
+@comment node-name, next, previous, up
+@chapter Making Cross References
+@cindex Making cross references
+@cindex Cross references
+@cindex References
+
+Cross references are used to refer the reader to other parts of the same or
+different Texinfo files. In Texinfo, @dfn{nodes} are the points to which
+cross-references can refer.
+
+In general, a document should be designed so that it can be read
+sequentially. People soon tire of flipping back and forth to find
+information that should be presented to them as they need it. However,
+there will be information (often too detailed for whatever the current
+context may be) that is related to whatever is presented and to which
+reference should be made. More important, in an on-line help system or in
+a reference manual, readers do @emph{not} read everything in sequence from
+beginning to end. Instead, they look up what they need. For this reason,
+such creations should contain many cross references to help the reader find
+other information that he or she may not have read.
+
+Although nodes are not a fundamental concept in a printed manual, they
+still serve to define a cross-reference point and the variants of
+@code{@@xref} still serve to make references. Thus, if you are writing a
+manual that will only be printed, and will not be used on-line, you
+continue to use the @code{@@node} command for when you make cross
+references.
+
+There are several kinds of cross reference command.
+
+@table @code
+@item @@xref
+Used to start a sentence in the printed manual saying, `See @dots{}' @*
+or an entry in the Info file saying @samp{*note @dots{}}.
+
+@item @@pxref
+Used to make a reference that starts with a lowercase @samp{see} @*
+and is usually contained within parentheses.@refill
+
+@item @@inforef
+Used to make a reference to an Info file for which there is no printed
+manual.@refill
+@end table
+
+@menu
+* Xref::
+* Pxref::
+* Inforef::
+@end menu
+
+
+@node Xref, Pxref, Cross References, Cross References
+@comment node-name, next, previous, up
+@section @@xref
+@cindex Xref for cross references
+@findex xref
+@cindex Cross references using xref
+
+@code{@@xref} generates a cross-reference. In Texinfo, it turns into
+an Info cross-reference which the Info @samp{f} command can use
+to go directly to another node. In @TeX{}, it turns into a sentence
+of the form
+
+@example
+See section @var{section} [@var{topic}], page @var{page}
+@end example
+
+@noindent
+but does not generate a period to end it.
+
+@code{@@xref} must refer to an Info node created by @code{@@node}, by the
+node's name.
+
+@code{@@xref} is followed by an argument inside braces; but actually the
+text inside the braces is treated as several arguments, separated by
+commas. Whitespace after these commas is ignored. A period or comma
+@strong{must} follow the closing brace of an @code{@@xref}. It is required
+to terminate the cross reference. This period or comma will appear in the
+output, both in the Info file and in the printed manual.
+
+The simplest form of @code{@@xref} takes one argument, the name of another
+node in the same Info file. Here we show the input text, followed by a
+blank line and then the output text for Info files and the output text for
+printed manuals.
+
+@example
+@@xref@{node-name@}, for more info.
+
+*note node-name::, for more info.
+@end example
+
+@quotation
+See section @var{nnn} [node-name], page @var{ppp}, for more info.
+@end quotation
+
+With two arguments, the second one is used as the name of the Info
+cross-reference, while the first argument is still the node that the
+cross-reference points to:
+
+@example
+@@xref@{node-name, name-for-note@}, for more info.
+
+*note name-for-note: node-name, for more info.
+@end example
+
+@quotation
+See section @var{nnn} [node-name], page @var{ppp}, for more info.
+@end quotation
+
+A third argument replaces the node name when it actually appears in the
+@TeX{} output. It should state the topic discussed by the section being
+referenced. Often, you will want to use initial uppercase letters so it
+will be easier to read when the reference is printed. Use a third argument
+when the node name is unsuitable because of syntax, grammar or diction.
+
+@example
+@@xref@{node-name, name-for-note, Topic Description@}, for more info.
+
+*note name-for-note: node-name, for more info.
+@end example
+
+@quotation
+See section @var{nnn} [Topic Description], page @var{ppp}, for more info.
+@end quotation
+
+If a third argument is given and the second one is empty,
+then the third argument serves both purposes:
+
+@example
+@@xref@{node-name, , Topic Description@}, for more info.
+
+*note Topic Description: node-name, for more info.
+@end example
+
+@quotation
+See section @var{nnn} [Topic Description], page @var{ppp}, for more info.
+@end quotation
+
+A fourth argument specifies the name of the Info file in which the
+referenced node is located, assuming it is not the one in which the
+reference appears. @code{@@xref} with only four arguments is used when the
+reference is not within one Info file, but is within a single printed
+manual---when multiple Texinfo files are incorporated into the same @TeX{}
+run but make separate Info files. (This is seldom the case and usually you
+will use five arguments if you are making a reference that is outside the
+current Info file.)
+
+@example
+@@xref@{node-name, name-for-note, Topic, info-file-name@},
+for more info.
+
+*note name-for-note: (info-file-name) node-name, for more info.
+@end example
+
+@quotation
+See section @var{nnn} [Topic], page @var{ppp}, for more info.
+@end quotation
+
+A fifth argument is used when you are making a reference to another Info
+file which is also part of another printed manual. Write the title of the
+manual in this slot. Since a different manual is made during a different
+@TeX{} run, the printed reference will not have a page number.
+
+@noindent
+Whenever you refer to another manual, use this version of @code{@@xref}
+with five arguments.
+
+@example
+@@xref@{node-name, name-for-note, Topic, info-file-name, A Printed Manual@},
+for more info.
+
+*note name-for-note: (info-file-name) node-name, for more info.
+@end example
+
+@quotation
+See section Topic of @i{A Printed Manual}, for more info.
+@end quotation
+
+@noindent
+The name of the printed manual will be typeset in italics.
+
+Often, you will leave out the second argument when you use the long version
+of @code{@@xref}. In this case, the third argument, the topic description,
+will replace the node name:
+
+
+@example
+@@xref@{node-name, , Topic Description, info-file-name, A Printed Manual@},
+for more info.
+
+*note Topic Description: (info-file-name) node-name, for more info.
+@end example
+
+@quotation
+See section Topic Description of @i{A Printed Manual}, for more info.
+@end quotation
+
+
+@node Pxref, Inforef, Xref, Cross References
+@comment node-name, next, previous, up
+@section @@pxref
+@cindex Cross references using pxref
+@cindex Pxref for cross references
+@findex pxref
+
+@code{@@pxref} is nearly the same as @code{@@xref}; it differs in only
+two ways:
+
+@enumerate
+@item
+The output starts with lower case `see' rather than `See'.@refill
+@item
+A period is generated automatically in the Info file output to end the Info
+cross-reference, but no period is generated for the printed manual.@refill
+@end enumerate
+
+The purpose of @code{@@pxref} is to be used inside parentheses as part of
+another sentence. In the printed manual, no period is needed after the
+cross reference text itself (within the parentheses), but a period is
+needed after the cross reference text in the Info file because only thus
+can Info recognize the end of the cross-reference. @code{@@pxref} spares
+you the need to use complicated methods to put a period into one form of
+the output and not the other.
+
+@code{@@pxref} can be used with up to five arguments just like
+@code{@@xref}. (@xref{Xref}.)@refill
+
+@node Inforef, , Pxref, Cross References
+@comment node-name, next, previous, up
+@section @@inforef
+@cindex Inforef for cross references
+@cindex Cross references using inforef
+@findex inforef
+
+@code{@@inforef} is used for cross-references to Info files for which there
+are no printed manuals. Even in a printed manual, @code{@@inforef}
+generates a reference directing the user to look in an Info file.
+@code{@@inforef} takes exactly three arguments. The syntax is
+@code{@@inforef@{@var{node}, @var{name}, @var{file}@}}.
+
+@example
+@@inforef@{node-name, name-for-note, info-file-name@}, for more information.
+
+*note name-for-note: (info-file-name) node-name, for more information.
+@end example
+
+@quotation
+See Info file @file{info-file-name}, node `node-name', for more information.
+@end quotation
+
+@node Formatting Paragraphs, Marking Text, Cross References, Top
+@comment node-name, next, previous, up
+@chapter Formatting Paragraphs
+@cindex Formatting paragraphs
+@cindex Paragraphs, formatting
+
+Usually, a Texinfo file will be processed both by @TeX{} and by the
+@kbd{M-x texinfo-format-buffer} command. Consequently, you must make sure
+that text will come out looking right both in the printed manual and in the
+on-line help.@refill
+
+For example, unless told otherwise, @kbd{M-x texinfo-format-buffer} will
+not refill a paragraph after processing it although @TeX{} will. This
+means that a paragraph with numerous or large @@-commands may not look
+properly filled after processing by Info. The @@-commands are removed from
+the text but the lines are not refilled so some are much shorter than they
+were. To cause the @kbd{M-x texinfo-format-buffer} command to refill such
+a paragraph, put @code{@@refill} at the end of the paragraph.@refill
+
+@TeX{} may also format a document improperly. For example, page breaks may
+occur in the ``wrong place''; to control this, text can be held together by a
+group command that keeps the text within the group from being split across
+two pages.
+
+@iftex
+The first section that follows is about refilling and preventing
+indentation; the second section is about line and paragraph breaks,
+creating blank lines, and grouping text.
+@end iftex
+
+@menu
+* Refilling & Noindent:: Refilling paragraphs & preventing indentation
+* Breaks Blank-Lines Groups:: Line and paragraph breaks, blank lines, grouping
+@end menu
+
+@node Refilling & Noindent, Breaks Blank-Lines Groups, Formatting Paragraphs, Formatting Paragraphs
+@comment node-name, next, previous, up
+@section Refilling Paragraphs and Preventing Indentation
+@cindex Refilling paragraphs automatically
+@cindex Preventing indentation in the printed text
+
+The @code{@@refill} and @code{@@noindent} commands are used just after or
+just before paragraphs which, after processing by either Info or @TeX{},
+might look bad. The @code{@@refill} command refills a paragraph in the
+Info file after all the other processing has been done. In the printed
+manual, the @code{@@noindent} command prevents a piece of text that is a
+continuation of the preceding paragraph from being indented as if it were a
+new paragraph.@refill
+
+@menu
+* Refill:: Refilling an info paragraph after other processing.
+* Noindent:: Preventing paragraph indentation in continuation text.
+@end menu
+
+@node Refill, Noindent, Refilling & Noindent, Refilling & Noindent
+@comment node-name, next, previous, up
+@subsection @@refill
+@findex refill
+
+If a paragraph contains sizable @@-constructs, it may look badly filled
+after @code{texinfo-format-buffer} is through with it.
+
+Put @code{@@refill} at the end of the paragraph to tell
+@code{texinfo-format-buffer} to refill the paragraph after finishing all
+other processing on it. @code{@@refill} has no effect on @TeX{}, which
+always fills everything that ought to be filled. For example,@refill
+
+@example
+To use @@code@{foo@}, pass @@samp@{xx%$@} and @@var@{flag@} and type @@kbd@{x@}
+after running @@code@{make-foo@}.@@refill
+@end example
+
+@noindent
+produces (in the Info file)
+
+@example
+To use `foo', pass `xx%$' and FLAG and type `x' after running `make-foo'.
+@end example
+
+@noindent
+whereas without the @code{@@refill} it would produce
+
+@example
+To use `foo', pass `xx%$' and FLAG and type `x'
+after running `make-foo'.
+@end example
+
+@noindent
+with the line broken at the same place as in the Texinfo input file.
+
+Do not put a space before @code{@@refill}; otherwise the command might be
+put at the beginning of the line when you refill the paragraph in the
+Texinfo file with @kbd{M-q} (@code{fill-paragraph}). If this were to
+happen, the @code{@@refill} command might fail to work
+
+@node Noindent, , Refill, Refilling & Noindent
+@comment node-name, next, previous, up
+@subsection @@noindent
+@findex noindent
+
+If you have text following an @code{@@example} or other similar ``special
+paragraph'' that reads as a continuation of the text before the
+@code{@@example}, it is good to prevent this text from being indented as a
+new paragraph. To accomplish this, put @code{@@noindent} on a line by
+itself before the start of the text that should not be indented. For
+example,@refill
+
+@example
+@@example
+This is an example
+@@end example
+
+@@noindent
+This line will not be indented.
+@end example
+
+@noindent
+produces
+
+@example
+This is an example
+@end example
+
+@noindent
+This line will not be indented.
+
+To adjust the number of blank lines properly in the Info file output,
+remember that the line containing @code{@@noindent} does not generate a
+blank line, and neither does the @code{@@end example} line.
+
+In the Texinfo source file for this documentation, each of the lines that
+says `produces' is preceded by a line containing @code{@@noindent}.
+
+@node Breaks Blank-Lines Groups, , Refilling & Noindent, Formatting Paragraphs
+@comment node-name, next, previous, up
+@section Breaks, Blank Lines and Groups
+
+Texinfo has several commands for making blank lines, for forcing paragraph
+and page breaks in the printed manual and for preventing text from running
+from one page to the next.
+
+@table @code
+@item @@*
+Force a line break in the printed manual. This
+command has no effect on the Info file.@refill
+
+@item @@sp
+Generate blank lines in both the printed manual and in the Info file.@refill
+
+@item @@br
+Force a paragraph break in the printed manual. This command has no effect
+on the Info file.@refill
+
+@item @@w
+Prevent text from being split across two lines in the printed manual. This
+command has no effect on the Info file.@refill
+
+@item @@page
+Start a new page in the printed manual. This
+command has no effect on the Info file.@refill
+
+@item @@group
+Hold text together that must appear on one printed page. This
+command has no effect on the Info file.@refill
+
+@item @@need
+Start a new printed page if required space not on this one. This
+command has no effect on the Info file.@refill
+@end table
+
+@menu
+* Line Breaks:: Force a line break in the printed manual.
+* Sp:: Generate blank lines.
+* Br:: Force a paragraph break in the printed manual.
+* W:: Prevent a paragraph break in the printed manual.
+* Page:: Start a new page in the printed manual.
+* Group:: Hold text together that must appear on one printed page.
+* Need:: Start a new printed page if required space not on this one.
+@end menu
+
+
+@node Line Breaks, Sp, Breaks Blank-Lines Groups, Breaks Blank-Lines Groups
+@comment node-name, next, previous, up
+@subsection @@*
+@findex asterisk
+@findex *
+@cindex Line breaks
+@cindex Breaks in a line
+
+
+@code{@@*} forces a line break in the printed manual. It has no effect on
+the Info file output, where line breaks follow those in the source file.
+If you want a line break at a certain spot in both forms of output, break
+the line there in the source file and put @code{@@*} at the end of the
+line.
+
+
+@node Sp, Br, Line Breaks, Breaks Blank-Lines Groups
+@comment node-name, next, previous, up
+@subsection @@sp
+@findex sp (line spacing)
+@cindex Spaces from line to line
+@cindex Line spacing
+
+A line containing @code{@@sp @var{n}} generates @var{n} blank lines of
+space in either the printed manual or the Info file. For example,
+
+@example
+@@sp 2
+@end example
+
+@noindent
+generates two blank lines.
+
+@node Br, W, Sp, Breaks Blank-Lines Groups
+@comment node-name, next, previous, up
+@subsection @@br
+@findex br (paragraph breaks)
+@cindex Paragraph breaks
+@cindex Breaks in a paragraph
+
+In a printed manual, a line containing @code{@@br} forces a paragraph
+break; in the Info file output, it does nothing (not even a blank line
+results from it).
+
+@node W, Page, Br, Breaks Blank-Lines Groups
+@comment node-name, next, previous, up
+@subsection @@w
+@findex w (preventing a line break)
+@cindex Line breaks, preventing
+
+In a printed manual, @code{@@w@{@var{text}@}} outputs @var{text} and prohibits
+line breaks within @var{text}. @code{@@w} has no effect on the Info file
+output; it is the same as would result from just @var{text}.
+
+
+@node Page, Group, W, Breaks Blank-Lines Groups
+@comment node-name, next, previous, up
+@subsection @@page
+@cindex Page breaks
+@findex page
+
+A line containing @code{@@page} starts a new page in a printed manual. The
+line has no effect on Info files since they are not paginated.
+
+@node Group, Need, Page, Breaks Blank-Lines Groups
+@comment node-name, next, previous, up
+@subsection @@group
+@cindex Group
+@cindex Holding text together vertically
+@cindex Vertically holding text together
+@findex group
+
+A line containing @code{@@group} begins an unsplittable vertical group,
+which must appear entirely on one page. The group is terminated by a line
+containing @code{@@end group}. These two lines produce no output of their
+own, and in the Info file output they have no effect at all.
+
+If you forget to end a group, you may get strange and unfathomable error
+messages when you run @TeX{}. This is because @TeX{} keeps trying to put
+the rest of the Texinfo file into the group and error messages do not start
+to get generated until @TeX{} has gone a long way. It's a good rule of
+thumb to look for a missing @code{@@end group} if you get incomprehensible
+error messages in @TeX{}.
+
+@node Need, , Group, Breaks Blank-Lines Groups
+@comment node-name, next, previous, up
+@subsection @@need
+@cindex Need
+@findex need
+
+A line containing @code{@@need @var{n}} starts a new page in a printed
+manual if fewer than @var{n} mils (thousandths of an inch) remain on the
+current page. The line has no effect on Info files since they are not
+paginated.@refill
+
+@node Marking Text, Conditionals , Formatting Paragraphs, Top
+@comment node-name, next, previous, up
+@chapter Marking Text Within a Paragraph
+@cindex Marking text within a paragraph
+
+In Texinfo, text within a paragraph can be marked in a variety of ways.
+The most important way is to specify whether a word or phrase is a
+definition, a metasyntactic variable, a literal example of a program or
+what not.
+
+In addition, there are special commands for inserting single characters
+that have special meaning in Texinfo, such as braces, and for inserting
+symbols with special handling, such as dots and bullets. Finally, there
+are ways to emphasize words.
+
+@menu
+* Specifying:: Specifying commands, files and so on.
+* Braces Atsigns Periods:: Inserting braces, @samp{@@} and periods.
+* Dots Bullets Tex:: Inserting dots, bullets and the @TeX{} logo
+* Emphasis:: Emphasizing text.
+@end menu
+
+@node Specifying, Braces Atsigns Periods, , Marking Text
+@comment node-name, next, previous, up
+@section Specifying Definitions, Files, Commands etc.
+@cindex Highlighting
+@cindex Specifying commands, files and the like
+@cindex Definitions, specifying them within text
+@cindex Commands, specifying them within text
+@cindex Files, specifying them within text
+
+Texinfo has a variety of commands for specifying just what kind of object a
+piece of text refers to. Metasyntactic variables, for example, are marked
+by one @@-command and code by another. Texinfo uses this information to
+determine how to highlight the text. Since the pieces of text are labelled
+by commands that tell what kind of object they are, it is easy to change
+the way Texinfo formats and typesets such text. For example, code is
+usually illustrated in a typewriter font, but it would be easy to change
+the way Texinfo highlights code to use another font. This change would not
+effect how metasyntatic variables are highlighted. If straight typesetting
+commands were used in the body of the file, you would have to check every
+single occurrence to make sure that you were changing code and not
+something else that should not be changed.
+
+In addition, the commands can be used to generate useful information from
+the file, such as lists of functions or file names. It is possible, for
+example, to write code in Emacs Lisp (or a keyboard macro) to insert an
+index entry after every paragraph that contains the text labelled by a
+specified command. You could do this to construct an index of functions if
+you had not already made the entries.
+
+The commands serve a variety of purposes:
+
+@table @code
+@item @@code
+Indicates text that is a literal example of a piece of a program.@refill
+
+@item @@samp
+Indicates text that is a literal example of a sequence of characters.@refill
+
+@item @@file
+Indicates the name of a file.@refill
+
+@item @@kbd
+Indicates the names of keys on the keyboard or characters you type.@refill
+
+@item @@key
+Used for the conventional name for a key on a keyboard.@refill
+
+@item @@ctrl
+Indicates an ASCII control character.
+
+@item @@var
+Indicates a metasyntactic variable.
+
+@item @@dfn
+Indicates the introductory or defining use of a term.
+
+@item @@cite
+Indicates the name of a book.
+@end table
+
+
+
+@menu
+* Code:: A literal example of a piece of a program.
+* Samp:: A literal example of a sequence of characters.
+* File:: The name of a file.
+* Kbd:: The names of keys or else characters you type.
+* Key:: The conventional name for a key on a keyboard.
+* Ctrl:: Indicates the ASCII control character.
+* Var:: A variable.
+* Dfn:: The introductory or defining use of a term.
+* Cite:: The name of a book.
+@end menu
+
+@node Code, Samp, , Specifying
+@comment node-name, next, previous, up
+@subsection @@code
+@findex code
+
+@code{@@code} is used to indicate text that is a piece of a program which
+consists of entire syntactic tokens. The text follows, enclosed in braces.
+
+For example, @code{@@code} is used for an expression in a program, the name
+of a variable or function used in a program, or a keyword. @code{@@code}
+is not used for a piece of a token, such as when speaking about the
+characters used in a token; for example, when you are explaining what
+letters or printable symbols can be used in the names of functions. It is
+also not used for input to programs unless the input is written in a
+language that is like a programming language. For example, it is not used
+for the single character commands of GNU Emacs although it is used for the
+names of Emacs Lisp functions that the keyboard commands invoke.
+
+You should also @code{@@code} for command names in command languages that
+resemble programming languages, such as Texinfo or the shell. Note,
+however, that @code{@@code} is not used for options such as @samp{-c} when
+such options stand alone. There is some argument as to whether an entire
+shell command incorporating an option should be written using @code{@@code}
+or @code{@@samp}.@refill
+
+It is an error to alter the case of a word inside an @code{@@code}
+command. This is a particularly insidious error if the language being
+documented is case sensitive. If the command is @code{printf}, then
+@code{Printf} is a misspelling. If you do not like having such a command
+with lower case at the beginning of a sentence, you may wish to rearrange
+the sentence.
+
+In the printed manual, @code{@@code} puts the argument in bold face.
+In the Info file, it uses `@dots{}' quotation. For example:
+
+@example
+To compare two files, showing text inserted or removed, use @@code@{diff@}.
+@end example
+
+@noindent
+produces
+
+@quotation
+To compare two files, showing text inserted or removed, use @code{diff}.
+@end quotation
+
+@iftex
+In the Info file, it looks like this:
+
+@example
+@dots{}, use `diff'
+@end example
+@end iftex
+
+@node Samp, File, Code, Specifying
+@comment node-name, next, previous, up
+@subsection @@samp
+@findex samp
+
+@code{@@samp} is used to indicate text that is a literal example of a
+sequence of characters in a file, string, pattern, etc. The text follows,
+enclosed in braces. The argument appears within `@dots{}' quotation in
+both the Info file and the printed manual; in addition, it is printed in a
+fixed-width font.
+
+@example
+To match @@samp@{foo@} at the end of the line, use the regexp @@samp@{foo$@}.
+@end example
+
+@noindent
+produces
+
+@quotation
+To match @samp{foo} at the end of the line, use the regexp @samp{foo$}.
+@end quotation
+
+Any time you are referring to single characters, you should use @code{@@samp}
+unless @code{@@kbd} is more appropriate. Basically, @code{@@samp} is a
+catchall for whatever is not covered by @code{@@code}, @code{@@file},
+@code{@@kbd}.
+
+Punctuation marks that are part of the English text that surrounds the
+strings you are specifying are @emph{never} included within the braces. In
+the following sentence, for example, the commas and period are outside of
+the braces:
+
+@example
+A symbol name ends in @@samp@{a@}, @@samp@{b@}, or @@samp@{c@}.
+@end example
+
+@node File, Kbd, Samp, Specifying
+@comment node-name, next, previous, up
+@subsection @@file
+@findex file
+
+@code{@@file} is used to indicate text that is the name of a file or
+directory. Currently, it is equivalent to @code{@@samp} in its effects on
+the output. For example,@refill
+
+@example
+The @@file@{.el@} files are in
+the @@file@{/gnu/emacs/lisp@} directory.
+@end example
+
+@noindent
+produces
+
+@quotation
+The @file{.el} files are in
+the @file{/gnu/emacs/lisp} directory.
+@end quotation
+
+@node Kbd, Key, File, Specifying
+@comment node-name, next, previous, up
+@subsection @@kbd
+@findex kbd
+
+@code{@@kbd} is used much like @code{@@code}. The difference is that
+@code{@@kbd} is for names of keys on the keyboard, or of characters you can
+type. For example, to refer to the command @kbd{M-a}, you would use
+
+@example
+@@kbd@{M-a@}
+@end example
+
+@noindent
+and to refer to @kbd{M-x shell}, you would use
+
+@example
+@@kbd@{M-x shell@}
+@end example
+
+The @code{@@kbd} command has the same effect as @code{@@code} in Info,
+but may produce a different font in a printed manual.@refill
+
+You can embed another @@-command inside the braces of a @code{@@kbd}
+command. This is the way to describe a command that would be described
+more verbosely as ``press an @samp{r} and then press the @key{RET} key'':
+
+@example
+@@kbd@{r @@key@{RET@}@}
+@end example
+
+@noindent
+This produces: @kbd{r @key{RET}}
+
+You also use the @code{@@kbd} command if you are spelling out the letters
+you type; for example:
+
+@example
+To give the @@code@{logout@} command,
+type the characters @@kbd@{l o g o u t @@key@{RET@}@}.
+@end example
+
+@noindent
+This produces
+
+@quotation
+To give the @code{logout} command,
+type the characters @kbd{l o g o u t @key{RET}}.
+@end quotation
+
+@node Key, Ctrl, Kbd, Specifying
+@comment node-name, next, previous, up
+@subsection @@key
+@findex key
+
+@code{@@key} is used for the conventional name for a key on a keyboard, as
+in
+
+@example
+@@key@{RET@}
+@end example
+
+Often, @code{@@key} is used within the argument of a @code{@@kbd}
+command, whenever the sequence of characters to be typed includes one or
+more keys that are described by name.@refill
+
+For example, to produce @kbd{C-x @key{ESC}} you would use
+
+@example
+@@kbd@{C-x @@key@{ESC@}@}
+@end example
+
+
+The recommended names to use for keys are in upper case and are
+
+@table @t
+@item SPC
+Space.
+@item RET
+Return.
+@item LFD
+Linefeed.
+@item TAB
+Tab.
+@item BS
+Backspace.
+@item ESC
+Escape.
+@item DEL
+Delete.
+@item SFT
+Shift.
+@item CTL
+Control.
+@item META
+Meta.
+@end table
+
+There are subtleties to handling words like `meta' or `ctrl' which are
+names of shift keys. When mentioning a character in which the shift key is
+used, such as @kbd{Meta-a}, use the @code{@@kbd} command alone without the
+@code{@@key} command, but when you are referring to shift key in isolation,
+use the @code{@@key} command. For example, you would use
+@samp{@@kbd@{Meta-a@}} to produce @kbd{Meta-a} and @samp{@@key@{META@}} to
+produce @key{META}.
+
+@node Ctrl, Var, Key, Specifying
+@comment node-name, next, previous, up
+@subsection @@ctrl
+@findex ctrl
+
+@code{@@ctrl} is used to describe an ASCII control character. The pattern
+of usage is @code{@@ctrl@{@var{ch}@}}, where @var{ch} is an ASCII character
+whose control-equivalent is wanted. Thus, you put in an @samp{f} when
+you want to indicate a @samp{control-f}
+
+Thus, to specify @samp{control-f}, you would enter
+
+@example
+@@ctrl@{f@}
+@end example
+
+@noindent
+which produces
+
+@quotation
+@ctrl{f}
+@end quotation
+
+In the Info file, this generates the specified control character, output
+literally into the file. This is done so a user can copy the specified
+control character (along with whatever else he or she wants) into another
+Emacs buffer and use it. Since the `control-h',`control-i', and
+`control-j' characters are formatting characters, they should not be
+indicated this way.@refill
+
+In a printed manual, this generates text to describe or identify that
+control character: an uparrow followed by the character @var{ch}.
+
+@node Var, Dfn, Ctrl, Specifying
+@comment node-name, next, previous, up
+@subsection @@var
+@findex var
+
+@code{@@var} is used to indicate metasyntactic variables. A metasyntactic
+variable is something that stands for another piece of text. You would use
+a metasyntactic variable in the documentation of a function to describe the
+arguments that are passed to that function.
+
+@code{@@var} is not used for names of particular variables in programming
+languages. For example, the Texinfo variable @code{texinfo-tex-command} is
+not a metasyntactic variable.
+
+Its effect in the Info file is to upcase the argument; in the printed
+manual, to italicize it. Example:
+
+@example
+To delete file @@var@{filename@}, type @@code@{rm @@var@{filename@}@}.
+@end example
+
+@noindent
+produces
+
+@quotation
+To delete file @var{filename}, type @code{rm @var{filename}}.
+@end quotation
+
+In some documentation styles, metasyntactic variables are shown with angle
+brackets, for example:
+
+@example
+@dots{}, type rm <filename>
+@end example
+
+@node Dfn, Cite, Var, Specifying
+@comment node-name, next, previous, up
+@subsection @@dfn
+@findex dfn
+
+@code{@@dfn} is used to identify the introductory or defining use of a
+technical term. The command should be used only in a passage whose purpose
+is to introduce a term which will be used again or which the reader ought
+to know. Mere passing mention of a term for the first time doesn't deserve
+@code{@@dfn}. It generates italics in the printed manual, and double
+quotation marks in the Info file. Example:
+
+@example
+Getting rid of a file is called @@dfn@{deleting@} it.
+@end example
+
+@noindent
+produces
+
+@quotation
+Getting rid of a file is called @dfn{deleting} it.
+@end quotation
+
+@node Cite, , Dfn, Specifying
+@comment node-name, next, previous, up
+@subsection @@cite
+@findex cite
+
+@code{@@cite} is used for the name of a book. It produces italics
+in the printed manual, and quotation marks in the Info file.
+
+
+@node Braces Atsigns Periods, Dots Bullets Tex, Specifying , Marking Text
+@comment node-name, next, previous, up
+@section Inserting Braces, @samp{@@} and Periods
+@cindex Inserting braces, @@ and periods
+@cindex Braces, inserting
+@cindex Periods, inserting
+@cindex Single characters, commands to insert
+@cindex Commands to insert single characters
+
+@samp{@@} and curly braces are special characters in Texinfo. This means
+that you have to put an @samp{@@} in front of these characters in order to
+insert them into text.
+
+Periods are also special. Depending on whether the period is inside of or
+at the end of a sentence, less or more space is inserted after a period in
+a typeset manual. Since it is not always possible for Texinfo to determine
+when a period ends a sentence and when it is used in an abbreviation,
+special commands are needed. (Usually, Texinfo figures out how to handle
+periods, so you don't have to use the special commands; you just enter a
+period as you would if you were using a typewriter, which means you put two
+spaces after the period that ends a sentence and after a colon.)@refill
+
+@menu
+* Inserting an Atsign:: inserting an atsign.
+* Insert Left Brace:: Inserting a left brace.
+* Insert Colon:: Preventing unintended additional whitespace.
+* Insert Period:: Inserting a period that does end a sentence.
+@end menu
+
+@node Inserting An Atsign, Insert Left Brace, , Braces Atsigns Periods
+@comment node-name, next, previous, up
+@subsection @@@@
+@findex at-signs
+@comment for version 19: this does not work findex @@
+
+@code{@@@@} stands for a single @@ in either printed or Info output.
+
+@node Insert Left Brace, Insert Colon, Inserting an Atsign, Braces Atsigns Periods
+@comment node-name, next, previous, up
+@subsection @@@{
+@findex left-braces
+@comment for version 19: this does not work findex @{
+
+@code{@@@{} stands for a single @{ in either printed or Info output.
+
+@subsection @@@}
+@findex right-braces
+@comment for version 19: this does not work findex @}
+
+@code{@@@}} stands for a single @} in either printed or Info output.
+
+@node Insert Colon, Insert Period, Insert Left Brace, Braces Atsigns Periods
+@comment node-name, next, previous, up
+@subsection @@:
+@findex at-sign colons
+@comment for version 19: this does not work findex @:
+
+@code{@@:}@: is used after a character such as period or colon which
+normally causes @TeX{} to increase the width of the following whitespace,
+to suppress that effect. For example, it can be used after periods that
+end abbreviations and do not end sentences. @code{@@:}@: has no effect
+on the Info file output.
+
+@example
+It displays @@code@{Foo:@}@@: at that time.
+@end example
+
+@noindent
+produces
+
+@quotation
+It displays @code{Foo:}@: at that time.
+@end quotation
+
+The meanings of @code{@@:}@: and @code{@@.}@: in Texinfo are designed to
+work well with the Emacs sentence motion commands. This means they are
+different from their meanings in some other formatting systems that use
+@@-commands.
+
+@refill
+
+@node Insert Period, , Insert Colon, Braces Atsigns Periods
+@comment node-name, next, previous, up
+@subsection @@.
+@findex at-sign periods
+@comment for version 19: this does not work at-sign period
+
+@code{@@.}@: stands for a period that really does end a sentence, useful
+when @TeX{} would otherwise assume by its heuristics that that is not so.
+This happens when there is a single-capital-letter word at the end of a
+sentence: @TeX{} normally guesses that it is an abbreviation.
+
+In the Info file output, @code{@@.}@: is equivalent to a simple @samp{.}.
+The Texinfo program preserves the amount of space that you use, so put
+two spaces after a period if you intend it to be the end of a sentence
+(as well as using @code{@@.}, if necessary, for the printed manual's sake).
+
+@example
+Give it to X. Give it to X@@. Give it to X@@.
+@end example
+
+@noindent
+produces
+
+@quotation
+Give it to X. Give it to X@. Give it to X@.
+@end quotation
+
+@node Dots Bullets Tex, Emphasis, Braces Atsigns Periods, Marking Text
+@comment node-name, next, previous, up
+@section Inserting Dots, Bullets and @TeX{}
+@cindex Dots, inserting
+@cindex Bullets, inserting
+@cindex TeX-logo, inserting
+@cindex Special typesetting commands
+@cindex Typesetting commands for dots and the like
+
+An ellipsis, a line of dots, is typeset differently than a string of
+periods; more whitespace is put between the dots in the ellipsis than is
+put between the periods. Because of this, a special command is used in
+Texinfo for inserting dots. Also, the trademark, @TeX{}, is typeset in a
+special fashion and it needs an @@-command, as does the command for
+inserting the copyright symbol. The @code{@@bullet} command is special,
+too. Each of these commands is followed by a pair of braces, @samp{@{@}},
+without any whitespace between the name of the command and the braces.
+
+@menu
+* Dots:: Inserting dots.
+* Bullet:: Inserting bullets.
+* Tex:: Inserting the @TeX{} trademark.
+@end menu
+
+@node Dots, Bullet, , Dots Bullets Tex
+@comment node-name, next, previous, up
+@subsection @@dots@{@}
+@findex dots
+@cindex Inserting dots
+@cindex Dots, inserting
+
+
+@code{@@dots@{@}} generates an ellipsis which is three dots in a row,
+appropriately spaced, like this: `@dots{}'. Do not simply write three
+periods in the input file; that would work for the Info file output, but
+would produce the wrong amount of space between the periods in the printed
+manual.
+
+@iftex
+Here is an ellipsis: @dots{}
+
+Here are three periods in a row: ...
+
+The three periods in a row are closer together than the dots in the ellipsis.
+
+@end iftex
+
+@node Bullet, Tex, Dots, Dots Bullets Tex
+@comment node-name, next, previous, up
+@subsection @@bullet@{@}
+@findex bullet
+
+@code{@@bullet@{@}} generates a large round dot, or the closest possible
+thing to one.
+
+Here is a bullet: @bullet{}
+
+@node Tex, , Bullet, Dots Bullets Tex
+@comment node-name, next, previous, up
+@subsection @@TeX@{@}
+@findex TeX
+
+@code{@@TeX@{@}} generates `@TeX{}'. In a printed manual, this is a special
+logo that is different from three ordinary letters.
+
+
+
+@node Emphasis, , Dots Bullets Tex, Marking Text
+@comment node-name, next, previous, up
+@section Emphasizing Text
+@cindex Emphasizing text
+
+Usually, Texinfo changes the font automatically to mark words in the text
+according to what category the words belong to. The @code{@@code} command,
+for example, does this. Most often, this is the best way to mark specified
+words. However, sometimes you will want to emphasize text directly.
+Texinfo has two ways to do this: commands that tell Texinfo to emphasize
+the text but leave the method to the program, and commands that specify the
+font to use. The first method is generally the best and it makes it
+possible to change the style of a document without have to re-edit it line
+by line.
+
+@menu
+* Emph and Strong:: Emphasizing text.
+* Fonts:: Selecting italic, bold or typewriter fonts.
+@end menu
+
+@node Emph and Strong, Fonts, , Emphasis
+@comment node-name, next, previous, up
+@subsection @@emph and @@strong
+@findex emph
+@findex strong
+
+@code{@@emph} and @code{@@strong} are two forms of emphasis. @code{@@strong}
+is stronger.
+
+In printed output, @code{@@emph} produces @emph{italics} and @code{@@strong}
+produces @strong{bold}.
+
+In the Info file, both of these commands put asterisks around the
+argument.
+
+@node Fonts, , Emph and Strong, Emphasis
+@comment node-name, next, previous, up
+@subsection @@i, @@b and @@t
+@findex i (italic font)
+@findex b (bold font)
+@findex t (typewriter font)
+
+These three commands specify font changes in the printed manual and have no
+effect in the Info file. @code{@@i} requests @i{italic} font (in some
+versions of @TeX{}, a slanted font is used), @code{@@b} requests @b{bold}
+face, and @code{@@t} requests the @t{fixed-width} font used by
+@code{@@kbd}. All three commands apply to an argument that follows,
+surrounded by braces.@refill
+
+If possible, you should avoid using these three commands. If you find a
+need to use one, it probably indicates a lack in the Texinfo language.
+
+@node Conditionals, Printing Hardcopy, Marking Text, Top
+@comment node-name, next, previous, up
+@chapter Conditionals
+@cindex Conditionals
+@cindex Ifinfo
+@cindex Iftex
+@findex ifinfo
+@findex iftex
+
+
+You may not always be able to use the same text for both the printed manual
+and the on-line Info file. In this case, you can use the conditional
+commands to specify which text is for the printed manual and which is for
+the Info file.
+
+@code{@@ifinfo} begins text that should be ignored by @TeX{} when it
+typesets the printed manual. The text appears only in the Info file. The
+@code{@@ifinfo} command should appear on a line by itself. End the
+info-only text with a line containing @code{@@end ifinfo} by itself. At
+the beginning of a Texinfo file, the Info permissions are contained within a
+region marked by @code{@@ifinfo} and @code{@@end ifinfo}.@refill
+
+Likewise, @code{@@iftex} and @code{@@end iftex} lines delimit text that
+will not appear in the Info file but will appear in the printed manual.@refill
+
+For example,
+
+@example
+@@iftex
+This text will appear only in the printed manual.
+@@end iftex
+
+
+@@ifinfo
+However, this text will appear only in the info manual.
+@@end ifinfo
+@end example
+
+@noindent
+The preceding example produces the following. Note how you only see one of
+the two lines, depending on whether you are reading the on-line Info version
+or the printed version of this manual.
+
+
+@iftex
+This text will appear only in the printed manual.
+@end iftex
+
+@ifinfo
+However, this text will appear only in the info manual.
+@end ifinfo
+
+The @code{@@titlepage} command is a special variant of @code{@@iftex} that
+is used for making the title and copyright pages of the printed manual.
+
+@menu
+* Using Tex Commands:: Using commands from regular @TeX{}.
+@end menu
+
+@node Using Tex Commands, , Conditionals, Conditionals
+@comment node-name, next, previous, up
+@section Using @TeX{} Commands
+@cindex Using TeX commands
+@cindex TeX commands, using them
+
+Inside a region delineated by @code{@@iftex} and @code{@@end iftex}, you
+can embed ordinary @TeX{} commands. Info will ignore these commands since
+they are only in that part of the file that is seen by @TeX{}. The @TeX{}
+commands are the same as any @TeX{} commands except that an @samp{@@}
+replaces the @samp{\} used by @TeX{}. For example, in the
+@code{@@titlepage} section of a Texinfo file, the @TeX{} command
+@code{@@vskip} is used to format the copyright page.@refill
+
+You can enter @TeX{} completely, and use @samp{\} in the @TeX{} commands by
+delineating a region with the @code{@@tex} and @code{@@end tex} commands.
+(These commands automatically put the region inside of @code{@@iftex} and
+@code{@@end iftex} commands.) For example,@refill
+
+@example
+@@tex
+Here you would put text with @TeX{} commands;
+such as $\bigl(x\in A(n)\bigm|x\in B(n)\bigr)$
+that will appear only in the printed manual.
+@@end tex
+@end example
+
+@noindent
+In the Info file, nothing between @code{@@tex} and @code{@@end tex} will
+appear.@refill
+
+@iftex
+In the printed manual, the mathematics will look like this:
+
+@tex
+$\bigl(x\in A(n)\bigm|x\in B(n)\bigr)$
+@end tex
+@end iftex
+
+@node Printing Hardcopy, Creating an Info File, Conditionals, Top
+@comment node-name, next, previous, up
+@chapter Printing Hardcopy
+@cindex Printing hardcopy
+@cindex Hardcopy, printing it
+@cindex Making a printed manual
+@cindex Sorting indices
+@cindex Indices, sorting
+@findex texindex (for sorting indices)
+
+There are three shell commands for printing a hardcopy of a Texinfo file.
+One is for formatting the file, the second is for sorting the index and the
+third is for printing the formatted document. When you use the shell
+commands, you can either work directly in the operating system shell or
+work within a shell inside of GNU Emacs.
+
+The typesetting program @TeX{} is used for formatting a Texinfo file.
+@TeX{} is a very powerful typesetting program and, if used right, does an
+exceptionally good job. The @@-commands in a Texinfo file are translated
+by a file called @file{texinfo.tex} into commands that @TeX{} understands.
+(That is why the beginning of every Texinfo file starts with the line that
+says @samp{\input texinfo}; this command tells @TeX{} to use the
+@file{texinfo.tex} file in processing the Texinfo file. Customarily,
+@file{texinfo.tex} is in a directory called @file{/usr/lib/tex/macros}.)
+@code{texinfo-format-buffer} reads the very same @@-commands in the Texinfo
+file and processes them differently from @TeX{} to make an Info
+file.@refill
+
+Usually, the @TeX{} formatting command is the shell command @code{tex}
+followed by the name of the Texinfo file. The @TeX{} command produces a
+formatted DVI file as well as several auxiliary files containing indices,
+cross references, etc. The DVI file (for @dfn{DeVice Independent} file)
+can be printed on a wide variety of printers.@refill
+
+The @TeX{} formatting command itself does not sort the indices. This is a
+misfeature of @TeX{}. Hence, to generate a printed index, you first need a
+sorted index to work from.@refill
+
+@TeX{} outputs raw, unsorted index files under names that obey a standard
+convention. These names are the name of your main input file to @TeX{},
+with everything after the first period thrown away, and the two letter
+names of indices added at the end. For example, the raw index output files
+for the input file @file{foo.texinfo} would be @file{foo.cp},
+@file{foo.vr}, @file{foo.fn}, @file{foo.tp}, @file{foo.pg} and
+@file{foo.ky}. Those are exactly the arguments to give to @code{texindex}.
+Or else, you can use @samp{??} as ``wild-cards'' and give the command in
+this form:@refill
+
+@example
+texindex foo.??
+@end example
+
+For each file specified, @code{texindex} generates a sorted index file
+whose name is made by appending @samp{s} to the input file name. The
+@code{@@printindex} command knows to look for a file of that name.
+@code{texindex} does not alter the raw index output file. After you have
+sorted the indices, you need to rerun the @TeX{} command on the Texinfo
+file. This regenerates a formatted DVI file with the index entries in the
+correct order.@refill
+
+To summarize, this is a three step process:
+
+@enumerate
+@item
+Run the @TeX{} command on the Texinfo file. This generates the formatted
+DVI file as well as the raw index files with two letter extensions.@refill
+
+@item
+Run the shell command @code{texindex} on the raw index files to sort them.
+The arguments to @code{texindex} are the names of the raw index files.
+@code{texindex} creates sorted index files whose names are the names of the
+raw index files with an @samp{s} appended. To cause @code{texindex} to
+sort all the raw index files, append @samp{??} to the Texinfo file name in
+place of the @file{.texinfo} extension.@refill
+
+@item
+Rerun the @TeX{} command on the Texinfo file. This regenerates a formatted
+DVI file with the index entries in the correct order. This second run also
+makes all the cross references correct as well. (The tables of contents
+are always correct.)@refill
+@end enumerate
+
+You need not run @code{texindex} after each @TeX{} run. If you don't, the
+next @TeX{} run will use whatever sorted index files happen to exist from
+the previous use of @code{texindex}. This is usually ok while you are
+debugging.
+
+Finally, the document can be printed out with the DVI print command
+(a shell command). Depending on the system used, the DVI print command
+will be a command such as @code{lpr -d}. The DVI print command may require
+a file name without any extension or with a @samp{.dvi} extension.
+
+The following commands, for example, sort the indices, format and print
+the @cite{Bison Manual} (where @samp{%} is the shell prompt):
+
+@example
+% tex bison.texinfo
+% texindex bison.??
+% tex bison.texinfo
+% lpr -d bison.dvi
+@end example
+
+@noindent
+(Remember that the words for the shell commands may be different at your
+site; but these are commonly used versions.)
+
+It is often most convenient to give formatting and printing commands from a
+shell within GNU Emacs. This way, you can easily keep track of errors. To
+create a shell within Emacs, type @kbd{M-x shell}. In this shell, you can
+format and print the document. You can switch to and from this shell while
+it is running and do other things. If you are formatting a very long
+document on a slow machine, this can be very convenient; on a VAX 750, for
+example, formatting often takes 8 seconds or more per page depending on how
+loaded the computer is. Faster machines take correspondingly less time.
+
+@menu
+* Requirements:: Formatting requirements.
+* Compile-Command:: Formatting with the compile command.
+@end menu
+
+@node Requirements, Compile-Command, , Printing Hardcopy
+@comment node-name, next, previous, up
+@section Formatting Requirements
+@cindex Requirements for formatting
+@cindex Formatting requirements
+
+Every Texinfo file that is to be input to @TeX{} must begin with a line
+that looks like
+
+@example
+\input texinfo @@c -*-texinfo-*-
+@end example
+
+@noindent
+This serves two functions.
+
+@enumerate
+@item
+When the file is processed by @TeX{}, it loads the macros needed for
+processing a Texinfo file.@refill
+@item
+When the file is edited in Emacs, it causes Texinfo mode to be used.@refill
+@end enumerate
+
+Every Texinfo file must end with a line saying
+
+@example
+@@bye
+@end example
+
+which terminates @TeX{} processing and forces out unfinished pages.
+
+You also have to include two lines that specify the Info file name and the
+title of the printed manual:
+
+@example
+@@setfilename @var{name-of-texinfo-file}
+@@settitle @var{Name of Manual}
+@end example
+
+You might also want to include a line saying
+
+@example
+@@setchapternewpage odd
+@end example
+
+@noindent
+to cause each chapter to start on a fresh odd-numbered page.
+
+By default, @TeX{} typesets pages for printing in an 8.5 by 11 inch
+format. However, you can direct @TeX{} to typeset a document in a 7 by
+9.25 inch format that is suitable for bound books by inserting the
+following command on a line by itself at the beginning of the Texinfo
+file, before the @code{@@setchapternewpage} command:
+
+@example
+@@smallbook
+@end example
+
+@noindent
+The Free Software Foundation distributes printed copies of the @cite{GNU
+Emacs Manual} in this size.
+
+Finally, @TeX{} sometimes is unable to typeset a line without extending
+it into the right margin. This can occur when @TeX{} comes upon what it
+interprets as a long word that it cannot hyphenate, like a net address,
+or a very long title. When this happens, @TeX{} prints an error message
+like this:
+
+@example
+Overfull \hbox (20.76302pt too wide)
+@end example
+
+@noindent
+and gives the line number along with the text of the offending line
+marked at all the places that @TeX{} knows to hyphenate words. (In
+@TeX{} lines are in `horizontal boxes', hence the term, `hbox'.)
+
+If the Texinfo file has an overfull hbox, you can rewrite the sentence
+so the overfull hbox does not occur or you can decide to leave it. A
+small excursion into the right margin often does not matter and may not
+even be noticable. However, unless told otherwise, @TeX{} will print a
+large, ugly, black rectangle beside every line that is overfull. This is
+so you will notice the location of the problem if you are correcting a
+draft. To prevent such monstrosities from marring your final printout,
+put the following in the beginning of the Texinfo file on lines of their
+own, before the @code{@@setchapternewpage} command:
+
+@example
+@@iftex
+@@finalout
+@@end iftex
+@end example
+
+@xref{Titlepage}, for information about creating a title page.
+@xref{Contents}, for information about creating a table of contents.@refill
+
+@node Compile-Command, , Requirements, Printing Hardcopy
+@comment node-name, next, previous, up
+@section Using Local Variables and the Compile Command
+@cindex Local variables
+@cindex Compile command for formatting
+@cindex Formatting with the compile command
+
+Another way to give the @TeX{} formatting command to Texinfo is to put that
+command in a @dfn{local variables list} at the end of the Texinfo file.
+You can then specify the @TeX{} formatting command as a
+@code{compile-command} and have Emacs run the @TeX{} formatting command by
+giving the command @kbd{M-x compile}. This creates a special shell called
+the @samp{*compilation buffer*}. For example, at the end of the
+@file{gdb.texinfo} file, after the @code{@@bye}, you would put the
+following:@refill
+
+@example
+@@c Local Variables:
+@@c compile-command: "tex gdb.texinfo"
+@@c End:
+@end example
+
+@noindent
+This technique is most often used by programmers who compile programs
+this way.
+
+@node Creating an Info File, Catching Mistakes, Printing Hardcopy, Top
+@comment node-name, next, previous, up
+@chapter Creating an On-line Info file
+@cindex Creating an on-line Info file
+@cindex Running Info
+@cindex Info, creating an on-line file
+@cindex Formatting a file for Info
+@cindex Indirect subfiles
+@findex texinfo-format-buffer
+
+In GNU Emacs, using Texinfo mode, you can see what part or all of a Texinfo
+file will look like in Info by using the keyboard command @kbd{C-c C-f}
+(@code{texinfo-format-region}). This formats a region and displays in a
+temporary buffer called @samp{*Info Region*}; however, this command does
+not turn on Info reading program---it just displays what the region will
+look like. The @code{texinfo-format-region} command is described more
+extensively in the chapter on using Texinfo mode. @xref{Info on a Region}.
+@refill
+
+In GNU Emacs, the way to create a working Info file is to visit the file
+and invoke
+
+@example
+@kbd{M-x texinfo-format-buffer}
+@end example
+
+@noindent
+A new buffer is created and the Info file text is generated there.
+@kbd{C-x C-s} will save it under the name specified in the
+@code{@@setfilename} command.@refill
+
+If the Texinfo file has more than 30,000 bytes,
+@code{texinfo-format-buffer} will automatically create a @dfn{tag table}
+for it. With a tag table, Info can jump to new nodes more quickly than it
+can otherwise. In addition, if the file has more than 100,000 bytes in it,
+@code{texinfo-format-buffer} will split the file into shorter Indirect
+subfiles of about 50,000 bytes each. Files are split so that Info does not
+have to make a large buffer to hold the whole of a large Info file;
+instead, Info allocates just enough memory for the small, split off file
+that is needed at the time. This way, Emacs avoids wasting memory when you
+run Info. (Before splitting was implemented, Info files were always short
+and @dfn{include} files were designed as a way to create a single, large
+printed manual out of the smaller Info files. @xref{Include Files}, for
+more information.)@refill
+
+When the file is split, Info itself works through a shortened version of
+the original file that contains the tag table and references to the files
+that were split off. The split off files are called @dfn{indirect} files.
+
+The split off files have names that are created by appending @samp{-1},
+@samp{-2}, @samp{-3} and so on to the file names specified by the
+@code{@@setfilename} command. The shortened version of the original file
+continues to have the name specified by @code{@@setfilename}.
+
+At one stage in writing this document, for example, the Info file was saved
+as @file{test-texinfo} and that file looked like this:
+
+@group
+@example
+Info file: test-texinfo, -*-Text-*-
+produced by texinfo-format-buffer
+from file: new-texinfo-manual.texinfo
+
+^_
+Indirect:
+test-texinfo-1: 102
+test-texinfo-2: 50422
+test-texinfo-3: 101300
+^_^L
+Tag table:
+(Indirect)
+Node: overview^?104
+Node: info file^?1271
+Node: printed manual^?4853
+Node: conventions^?6855
+@dots{}
+@end example
+@end group
+
+@noindent
+(But @file{test-texinfo} had far more nodes than are shown here.) Each of
+the split off, indirect files, @file{test-texinfo-1},
+@file{test-texinfo-2}, and @file{test-texinfo-3}, is listed in this file
+after the line that says @samp{Indirect:}. The tag table is listed after
+the line that says @samp{Tag table:}. @refill
+
+You cannot run the @kbd{M-x Info-validate} node checking command on indirect
+files. For information on how to prevent files from being split and how to
+validate the structure of the nodes, @pxref{Info-Validating a Large
+File}@refill
+
+@menu
+* Installing an Info File:: Putting the Info file in the info directory.
+@end menu
+
+@node Installing an Info File, , Creating an Info File, Creating an Info File
+@comment node-name, next, previous, up
+@section Installing an Info file
+@cindex Installing an Info file
+@cindex Info file installation
+@cindex Dir directory for Info installation
+
+An Info file is usually installed in the GNU Emacs directory called
+@file{info}. For Info to work, this directory must contain all the Info
+files, including the split off files. In addition, the @file{info}
+directory must have a file that serves as a top level directory for the
+Info system. This file is called @file{dir}.
+
+
+For example, in the @file{info} directory, the file called @file{dir} has
+the top level menu for all the Info files in the system. This file has a
+master menu that looks like this:
+
+@example
+* Menu:
+
+* Info: (info). Documentation browsing system.
+* Emacs: (emacs). The extensible self-documenting text editor.
+* Texinfo: (texinfo). With one source file, make either a printed
+ manual using TeX or an Info file using
+ Texinfo.
+@end example
+
+To add a new Info file, just add it to this menu. For example, if you
+were adding documentation for GDB, you would make the following entry:
+
+@example
+* GDB: (gdb). The source-level C debugger.
+@end example
+
+@noindent
+The first item is the menu item name; it is followed by a colon. The
+second item is the name of the Info file, in parentheses; it is followed by
+a period. The third part of the entry is the description of the item.
+
+
+
+The top node of the file, named @samp{top}, should have as its parent the
+name of a node in another file, where there is a menu that leads to this
+file. Specify the file name in parentheses. If the file is to be
+installed directly in the Info directory file, use @samp{(dir)} as the
+parent of the top node; this is short for @samp{(dir)top}, the node @samp{top}
+in the file @file{dir}, which is the main menu of Info.
+
+
+
+
+@node Catching Mistakes, Command Syntax, Creating an Info File, Top
+@comment node-name, next, previous, up
+@chapter Catching Mistakes
+@cindex Structure of Texinfo, catching mistakes
+@cindex Nodes, catching mistakes
+@cindex Nodes, correcting mistakes
+@cindex Catching mistakes
+@cindex Correcting mistakes
+@cindex Mistakes, catching
+@cindex Problems, catching
+@cindex Debugging the Texinfo structure
+
+Besides mistakes with the content of what ever you are describing, there
+are two kinds of mistake you can make with Texinfo: you can make mistakes
+with @@-commands, and you can make mistakes with the structure of the
+nodes and chapters.
+
+There are two tools for catching the first kind of mistake and two for
+catching the second.
+
+For finding problems with @@-commands, your best action is to run @kbd{M-x
+texinfo-format-region} on regions of your file as you write it. In Texinfo
+mode, the @code{texinfo-format-region} command is bound to @kbd{C-c C-f}.
+In addition, you can run @TeX{} on the whole file.@refill
+
+For finding problems with the structure of nodes and chapters, you can use
+@kbd{C-c C-s} (@code{texinfo-show-structure}) (and the related @code{occur}
+command) and you can use the @kbd{M-x Info-validate} command.
+
+
+@menu
+* Debugging with Info:: Catching errors with info formatting.
+* Debugging with Tex:: Catching errors with @TeX{} formatting.
+* Using texinfo-show-structure:: Using @code{texinfo-show-structure}
+ to catch mistakes.
+* Running Info-Validate:: Checking for unreferenced nodes.
+@end menu
+
+
+@node Debugging with Info, Debugging with Tex, , Catching Mistakes
+@comment node-name, next, previous, up
+@section Catching Errors with Info Formatting
+@cindex Catching errors with Info Formatting
+@cindex Debugging with Info Formatting
+
+After you have written part of a Texinfo file, you can use the @kbd{M-x
+texinfo-format-region} command to see whether the region formats properly.
+In Texinfo mode, this command is bound to the keyboard command @kbd{C-c
+C-f}.
+
+If you have made a mistake with an @@-command, @kbd{M-x
+texinfo-format-region} will stop processing at or after the error and give
+an error message. To see where in the file the error occurred, switch to
+the @samp{*Info Region*} buffer; the cursor will be in a position that is
+after the location of the error. Also, the text will not be formatted
+after the place the error occurred.@refill
+
+For example, if you accidently end a menu with the command @code{@@end
+menus} with an `s' on the end, instead of with @code{@@end menu}, you will
+get an error message that says:
+
+@example
+@@end menus is not handled by texinfo.
+@end example
+
+@noindent
+The cursor will stop at the point in the file where the error occurs, or
+not long after it. It will look like this:
+
+@group
+@example
+@@menu
+* Using texinfo-show-structure:: Using @code{texinfo-show-structure}
+ to catch mistakes.
+* Running Info-Validate:: Checking for unreferenced nodes.
+@@end menus
+@end example
+@end group
+
+The @code{texinfo-format-region} command does not always recognize errors.
+For example, no errors were reported when @code{texinfo-format-region} was
+run on the whole itemized list of which the following is a part:
+
+@example
+name of the Texinfo file as an extension. The @@samp@{??@} are `wildcards'
+that cause the shell to substitute all the raw index files. (@@xref@{sorting
+indices), for more information about sorting indices.) @@refill
+@@cindex Sorting indices
+@@cindex Indices, sorting
+
+@@item
+@@emph@{Third@}, rerun the @@TeX@{@} command on the Texinfo file. This
+regenerates a formatted DVI file with the index entries in the correct
+order. This second run also makes all the cross references and table of
+contents correct as well.
+@end example
+
+@noindent
+Instead, @code{texinfo-format-region} ran without reporting the error, but
+it produced output with very long lines, containing some of the original
+@code{@@cindex} commands mixed in. (It is not practical to display these
+over long lines here.
+
+However, when @code{texinfo-format-region} was run on part of the list
+that is shown, it did give an error message, @samp{Search failed:
+"[@{,@}"}. (This error message is explained in the section on using the
+Emacs Lisp Debugger, @pxref{Using the Emacs Lisp Debugger})
+
+Sometimes @code{texinfo-format-region} will stop long after the original
+error; this is because it does not discover the problem until then. In this
+case, you will have to backtrack.@refill
+
+@node Using the Emacs Lisp Debugger, , ,Debugging with Info
+@comment node-name, next, previous, up
+@subsection Using the Emacs Lisp Debugger
+@cindex Using the Emacs Lisp debugger
+@cindex Emacs Lisp debugger
+@cindex Debugger, using the Emacs Lisp
+
+If an error is especially elusive, you can turn on the Emacs Lisp debugger
+and look at the backtrace; this tells you where in the
+@code{texinfo-format-region} function the problem occurred. You can turn
+on the debugger with the command:@refill
+
+@example
+M-x set-variable @key{RET} debug-on-error @key{RET} t
+@end example
+
+@noindent
+and turn it off with
+
+@example
+M-x set-variable @key{RET} debug-on-error @key{RET} nil
+@end example
+
+Often, when you are using the debugger, it is easier to follow what is
+going on if you use the Emacs Lisp files that are not byte-compiled. The
+byte-compiled sources send octal numbers to the debugger that may look
+mysterious. To use the uncompiled source files, load @file{texinfmt.el}
+and @file{texinfo.el} with the @kbd{M-x load-file} command.@refill
+
+The debugger will not catch an error if @code{texinfo-format-region} does
+not detect one. In the example shown above, @code{texinfo-format-region}
+did not find the error when the whole list was formatted, but only when
+part of the list was formatted. When @code{texinfo-format-region} did not
+find an error, the debugger did not find one either. @refill
+
+However, when @code{texinfo-format-region} did report an error, it invoked
+the debugger. This is the backtrace it produced:
+
+@example
+Signalling: (search-failed "[@},]")
+ re-search-forward("[@},]")
+ (while ...)
+ (let ...)
+ texinfo-format-parse-args()
+ (let ...)
+ texinfo-format-xref()
+ funcall(texinfo-format-xref)
+ (if ...)
+ (let ...)
+ (if ...)
+ (while ...)
+ texinfo-format-scan()
+ (save-excursion ...)
+ (let ...)
+ texinfo-format-region(103370 103631)
+* call-interactively(texinfo-format-region)
+@end example
+
+The backtrace is read from the bottom up. @code{texinfo-format-region} was
+called interactively; and it, in turn, called various functions, including
+@code{texinfo-format-scan}, @code{texinfo-format-xref} and
+@code{texinfo-format-parse-args}. Inside the function
+@code{texinfo-format-parse-args}, the function @code{re-search-forward} was
+called; it was this function that could not find the missing right hand
+brace.@refill
+
+@xref{Lisp Debug, , Debugging Emacs Lisp, emacs, The GNU Emacs Manual}, for
+more information.@refill
+
+
+
+@node Debugging with Tex, Using texinfo-show-structure, Debugging with Info, Catching Mistakes
+@comment node-name, next, previous, up
+@section Catching Errors with @TeX{} Formatting
+@cindex Catching errors with TeX Formatting
+@cindex Debugging with TeX Formatting
+
+You can also catch mistakes when you format a file with @TeX{}.
+
+
+Usually, you will want to do this after you have run
+@code{texinfo-format-buffer} on the same file.
+@code{texinfo-format-buffer} is usually faster and sometimes gives error
+messages that make more sense. @xref{Debugging with Info}, for more
+information.@refill
+
+For example, @TeX{} was run on the same itemized list discussed
+in the section on the use of @code{texinfo-format-region}
+(@pxref{Debugging with Info}); the fragment with the error looked like
+this:
+
+@example
+name of the texinfo file as an extension. The @@samp@{??@} are `wildcards'
+that cause the shell to substitute all the raw index files. (@@xref@{sorting
+indices, for more information about sorting indices.) @@refill
+@end example
+
+@noindent
+This produced the following output, after which @TeX{} stopped:
+
+@example
+Runaway argument?
+@{sorting indices, for more information about sorting indices.) @@refill @@ETC.
+! Paragraph ended before \xref was complete.
+<to be read again>
+ \par
+l.27
+
+?
+@end example
+
+In this case, @TeX{} produced an accurate and understandable error message:
+@samp{Paragraph ended before \xref was complete.} (Note, however, that
+@TeX{} translated the @samp{@@} into a @samp{\}.) Also, @samp{\par} is an
+internal @TeX{} command of no relevance to Texinfo.)
+
+Unfortunately, @TeX{} is not always so helpful, and sometimes you have to be
+truly a Sherlock Holmes to discover what went wrong.
+
+In any case, if you run into a problem like this, you can do one of two
+things.
+
+@enumerate
+@item
+You can tell @TeX{} to continue running and to ignore errors
+as best it can by typing @kbd{r @key{RET}} at the
+@samp{?} prompt.@refill
+
+This is often the best thing to do. However, beware: the one error may
+produce a cascade of additional error messages as it consequences are felt
+through the rest of the file.@refill
+
+@item
+You can tell @TeX{} to stop this run by typing @kbd{x @key{RET}}
+at the @samp{?} prompt.
+@end enumerate
+
+Sometimes @TeX{} will format a file without producing error messages even
+though there is a problem. This usually occurs if a command is not ended
+but @TeX{} is able to continue processing anyhow. For example, if you fail
+to end an itemized list with the @code{@@end itemize} command, @TeX{} will
+write a DVI file that you can print out. The only error message that
+@TeX{} will give you is the somewhat mysterious comment that
+
+@example
+(\end occurred inside a group at level 1)
+@end example
+
+@noindent
+However, if you print the DVI file, you will find that the text of the file
+that follows the itemized list is entirely indented as if it were part of
+the last item in the itemized list. The error message is the way @TeX{}
+says that it expected to find an @code{@@end} command somewhere in the
+file; but that it could not locate where it was needed. @refill
+
+Another source of notoriously hard to find errors is a missing @code{@@end
+group} command. If you ever are stumped by incomprehensible errors, look
+for a missing @code{@@end group} command first.@refill
+
+If you do not have the header lines in the file, @TeX{} may stop in the
+beginning of its run and display output that looks like the following.
+The @samp{*} indicates that @TeX{} is waiting for input.@refill
+
+@example
+This is TeX, Version 2.0 for Berkeley UNIX (preloaded format=plain-cm
+87.10.25) (#tz-bar-a02987.tex [1])
+*
+@end example
+
+@noindent
+In this case, simply type @kbd{\end @key{RET}} after the asterisk. Then
+put the header lines into the Texinfo file and run the @TeX{} command
+again.@refill
+
+
+@node Using texinfo-show-structure, Running Info-Validate, Debugging with Tex, Catching Mistakes
+@comment node-name, next, previous, up
+@section Using @code{texinfo-show-structure}
+@cindex Showing the structure of a file
+@cindex Using texinfo-show-structure to catch mistakes
+@cindex texinfo-show-structure for catching mistakes
+@findex texinfo-show-structure
+
+It is not always easy to keep track of the nodes, chapters, sections and
+subsections of a Texinfo file. This is especially true if you are revising
+or adding to a Texinfo file that someone else has written.
+
+In GNU Emacs, in Texinfo mode, there is a command that will list all the
+lines that begin with the @@-commands that specify the structure: @@node,
+@@chapter, @@section, @@appendix and so on. This is the
+@code{texinfo-show-structure} command. It is bound to the keyboard command
+@kbd{C-c C-s}. @code{texinfo-show-structure} displays the lines that begin
+with the node and chapter structuring @@-commands in another window called
+the @samp{*Occur*} buffer. For example, when @code{texinfo-show-structure}
+is run on the first part of this chapter, it produces the following:@refill
+
+@example
+Lines matching
+"^@@\\(chapter\\|unnum\\|appendix\\|sect\\|sub\\|heading\\|major
+\\|node\\)" in buffer new-texinfo-manual.texinfo.
+ 2:@@node catching mistakes, @@-Command Syntax, running info, top
+ 4:@@chapter Catching Mistakes
+ 41:@@node debugging with info, debugging with tex, , catching mistakes
+ 43:@@section Catching errors with Info Formatting
+@end example
+
+This means that lines 2, 4, 41 and 43 began with @code{@@node},
+@code{@@chapter}, @code{@@node}, and @code{@@section} respectively. If you
+move your cursor into the @samp{*Occur*} window, you can position the
+cursor over one of the lines and use the @kbd{C-c C-c} command
+(@code{occur-mode-goto-occurrence}), to jump to the corresponding spot in
+the Texinfo file.
+@xref{Other Repeating Search, , Using Occur, emacs, The GNU Emacs Manual},
+for more information about @code{occur-mode-goto-occurrence}.@refill
+
+The first line in the @samp{*Occur*} window describes the @dfn{regular
+expression} specified by @var{texinfo-heading-pattern}. This regular
+expression is the pattern that @code{texinfo-show-structure} looks for.
+@xref{Regexps, , Using Regular Expressions, emacs, The GNU Emacs Manual},
+for more information.@refill
+
+When you give the @code{texinfo-show-structure} command, it will show the
+structure of the whole buffer. If you want to see the structure of just a
+part of the buffer, of one chapter, for example, use the @kbd{C-x n}
+(@code{narrow-to-region}) command to mark the region. (@xref{Narrowing, ,
+, emacs, The GNU Emacs Manual}.) This is how the example used above was
+generated. (To see the whole buffer again, use @kbd{C-x w}
+(@code{widen}).)@refill
+
+You can remind yourself of the structure of a Texinfo file by looking at
+the list in the @samp{*Occur*} window; and if you have mis-named a node
+or left out a section, you can correct the mistake.
+
+@menu
+* Using Occur::
+@end menu
+
+@node Using Occur, , Using texinfo-show-structure, Using texinfo-show-structure
+@comment node-name, next, previous, up
+@subsection Using @code{occur}
+@cindex Using occur
+@cindex Occur, using the command
+
+Sometimes the @code{texinfo-show-structure} command produces too much
+information. Perhaps you want to remind yourself of the overall structure
+of a Texinfo file, and are overwhelmed by the detailed list produced by
+@code{texinfo-show-structure}. In this case, you can use the @code{occur}
+command itself. To do this, type
+
+@example
+@kbd{M-x occur}
+@end example
+
+@noindent
+and then, when prompted, type a @dfn{regexp}, a regular expression for the
+pattern you want to match.
+(@xref{Regexps, , Regular Expressions, emacs, The GNU Emacs Manual}.)
+@code{occur} works from the current location of
+the cursor in the buffer to the end of the buffer. If you want to run
+@code{occur} on the whole buffer, place the cursor at the beginning of the
+buffer. For example, to see all the lines that contain the word
+@samp{@@chapter} in them, just type @samp{@@chapter}. This will produce a
+list of the chapters. It will also list all the sentences with
+@samp{@@chapter} in the middle of the line. If you want to see only those
+lines that start with the word @samp{@@chapter}, type @samp{^@@chapter}
+when prompted by @code{occur}. If you want to see all the lines that end
+with a word or phrase, end the last word with a @samp{$}; for example,
+@samp{catching mistakes$}. This can be helpful when you want to see all
+the nodes that are part of the same chapter or section and therefore have
+the same `Up' pointer.@refill
+
+@xref{Other Repeating Search, , Using Occur, emacs , The GNU Emacs Manual},
+for more information.@refill
+
+@node Running Info-Validate, , Using texinfo-show-structure, Catching Mistakes
+@comment node-name, next, previous, up
+@section Finding Badly Referenced Nodes
+@cindex Running Info-validate
+@cindex Info-validate, running the command
+@cindex Nodes, checking for badly referenced nodes
+@cindex Checking for badly referenced nodes
+@cindex Looking for badly referenced nodes
+@cindex Finding badly referenced nodes
+@cindex Badly referenced nodes
+
+You can check whether any of the `Next', `Previous', `Up' or other node
+pointers fail to point to a node with the @code{Info-validate} command.
+This command checks that every node pointer points to an existing node.
+
+To use this command, you first need to load the @code{info} library and then do
+@kbd{M-x Info-validate}.
+
+@example
+@kbd{M-x load-library @key{RET} info @key{RET}}
+@kbd{M-x Info-validate}
+@end example
+
+@noindent
+(Note that all the @code{Info} commands require an uppercase `I'.)
+
+If your file is ok, you will receive a message that says ``File appears
+valid''. However, if you have a pointer that does not point to a node,
+error messages will be displayed in a buffer called @samp{*problems in
+info file*}.
+
+For example, @code{Info-validate} was run on a test file that contained
+only the first node of this manual. One of the messages said:
+
+@example
+In node "Overview", invalid Next: Texinfo Mode
+@end example
+
+@noindent
+This meant that the node called @samp{Overview} had a `Next' pointer that
+did not point to anything (which was true in this case, since the test file
+had only one node in it).
+
+Now suppose we add a node named @samp{Texinfo Mode} to our test case
+but we don't specify a `Previous' for this node. Then we will get
+the following error message:
+
+@example
+In node "Texinfo Mode", should have Previous: Overview
+@end example
+
+@noindent
+This is because every `Next' pointer should be matched by a
+`Previous' (in the node where the `Next' points) which points back.
+
+@code{Info-validate} also checks that all menu items and cross-references
+point to actual nodes.
+
+Significantly, @code{Info-validate} does not work with large files that
+have been split. (Info thinks of a large file as being over 100,000 bytes,
+approximately.) In order to use @code{Info-validate} on a large file, you
+must run @code{texinfo-format-buffer} with an argument so that it does not
+split the Info file, and then create a tag table.
+
+@menu
+* Info-Validating a Large File:: Running @code{Info-validate} on a large file.
+* Splitting:: Splitting a file manually.
+@end menu
+
+@node Info-Validating a Large File, Splitting, Running Info-Validate, Running Info-Validate
+@comment node-name, next, previous, up
+@subsection Running @code{Info-validate} on a Large File.
+@cindex Running Info-validate on a large file
+@cindex Info validating a large file
+@cindex Validating a large file
+
+
+You can run @code{Info-validate} only on a single Info file. The command
+will not work on indirect subfiles that are generated when the master file
+is split. If you have a large file (longer than 100,000 bytes), you need
+to run the @code{texinfo-format-buffer} command in such a way that it does
+not create indirect subfiles. You will also need to create a tag table.
+When you have done this, you can run @code{Info-validate} and look for
+badly referenced nodes.@refill
+
+After you have validated the node structure, you can rerun
+@code{texinfo-format-buffer} in the normal way so it will construct the tag
+table and split the file automatically or, you can make the tag table and
+split the file manually.@refill
+
+To prevent the @code{texinfo-format-buffer} command from splitting a
+Texinfo file into smaller Info files, give a prefix to the @kbd{M-x
+texinfo-format-buffer} command:
+
+@example
+C-u M-x texinfo-format-buffer
+@end example
+
+@noindent
+When you do this, Texinfo will not split the file and will not create a tag
+table for it. @refill
+@cindex Making a tag table manually
+@cindex Tag table, making manually
+
+Before you can run @kbd{M-x Info-validate} on the Info file, you need to
+create a tag table for it. In order to do this, you first need to load the
+@code{info} library into Emacs with the following command:@refill
+
+@example
+M-x load-library @key{RET} info @key{RET}
+@end example
+
+@noindent
+Then you can give the command:
+
+@example
+M-x Info-tagify
+@end example
+
+This creates a file which you can validate.@refill
+
+@example
+M-x Info-validate
+@end example
+
+After you have checked the validity of the nodes, you can either run
+@kbd{M-x texinfo-format-buffer} as you would normally, or else tagify and
+split the file manually with the two commands @code{Info-tagify} and
+@code{Info-split}.@refill
+
+@node Splitting, ,Info-Validating a Large File , Running Info-Validate
+@comment node-name, next, previous, up
+@subsection Splitting a File Manually
+@cindex Splitting an Info file manually
+@cindex Info file, splitting manually
+
+If the file has more than 100,000 or so bytes in it, you should split it or
+else let the @code{texinfo-format-buffer} command do it for you
+automatically. (Generally you will let @code{texinfo-format-buffer} do
+this job for you. @xref{Creating an Info File}.)@refill
+
+The split off files are called the indirect subfiles.
+
+Info files are split to save memory. With smaller files, Emacs does not
+have make such a large buffer to hold the information. This way, Emacs
+can save memory.
+
+If the Info file has more than 30 nodes, you should also make a tag table for
+it. @xref{Info-Validating a Large File}, for information about creating a
+tag table.
+
+Before running @code{Info-split}, you need to load the @code{info} library
+into Emacs by giving the command @kbd{M-x load-library @key{RET} info
+@key{RET}}. After you have done this, you can give the two commands:@refill
+
+@example
+M-x Info-tagify
+M-x Info-split
+@end example
+
+@noindent
+(Note that the @samp{I} in @samp{Info} is uppercase.)
+
+When you use the @code{Info-split} command, the buffer is modified into a
+(small) Info file which lists the indirect subfiles. This file should be
+saved in place of the original visited file. The indirect subfiles are
+written in the same directory the original file is in, with names generated
+by appending @samp{-} and a number to the original file name.
+
+The primary file still functions as an Info file, but it contains just
+the tag table and a directory of subfiles.
+
+@c ;;;;;;;;;;;;;;;; Appendix starts here ;;;;;;;;;;;;;;;;
+
+@node Command Syntax, Include Files , Catching Mistakes , Top
+@comment node-name, next, previous, up
+@appendix @@-Command Syntax
+@cindex @@-Command Syntax
+
+The character @samp{@@} is used to start special Texinfo commands. (It has the
+same meaning that @samp{\} has in plain @TeX{}.) Syntactically, there
+are three classes of @@-commands:
+
+@table @asis
+@item 1. Non-alphabetic commands: @@ followed by a punctuation character.
+These commands are always part of the text within a paragraph, and
+never take any argument. The two characters (@@ and the other one)
+are complete in themselves. For example, @code{@@.}, @code{@@:},
+@code{@@@{} and @code{@@@}}.@refill
+
+@item 2. Alphabetic commands used within a paragraph.
+These commands have @@ followed by a letter or a word, followed by an
+argument within braces. For example, the command @code{@@dfn} indicates
+the introductory or defining use of a term; it is used as follows: @samp{In
+Texinfo, @@-commands are @@dfn@{mark-up@} commands.}@refill
+
+@item 3. Alphabetic commands used outside of paragraphs.
+Each such command occupies an entire line. The line starts with @@,
+followed by the name of the command (a word) such as @code{@@center} or
+@code{@@cindex}. If no argument is needed, the word is followed by the end
+of the line. If there is an argument, it is separated from the command
+name by a space.@refill
+@end table
+
+Thus, the alphabetic commands fall into two classes that have different
+argument syntax. You cannot tell which class a command falls in by the
+appearance of its name, but you can tell by the command's meaning: if it
+makes sense to use the command together with other words as part of a
+paragraph, the command is in class 2 and must be followed by an argument in
+braces; otherwise, it is in class 3 and uses the rest of the line as its
+argument.
+
+The purpose of having different syntax for commands of classes 2 and 3 is
+to make the Texinfo file easier to read, and also to help the GNU Emacs
+paragraph and filling commands work properly. There is only one exception
+to this rule: the command @code{@@refill}, which is always used at the end
+of a paragraph immediately following the final period or other punctuation
+character. @code{@@refill} takes no argument. @code{@@refill} never
+confuses the Emacs paragraph commands because it cannot start at the
+beginning of a line.@refill
+
+
+@node Include Files, TeX Input, Command Syntax, Top
+@comment node-name, next, previous, up
+@appendix Include Files
+@cindex Include files
+
+When Info was first created, it was customary to create many small Info
+files on one subject. By doing this, Emacs did not have to make a large
+buffer to hold the whole of a large Info file; instead, Emacs allocated
+just enough memory for the small Info file that was needed at the time.
+This way, Emacs could avoid wasting memory. Include files were designed as
+a way to create a single, large printed manual out of several smaller Info
+files.
+
+However, because large Info files can now be split, include files are no
+longer strictly necessary and they are used infrequently. Most often, they
+are now used in projects where several different people are writing
+different sections of a document simultaneously.
+
+@appendixsec How Include Files Work
+
+In a Texinfo file, a line of the form @code{@@include @file{filename}} is
+ignored when the Info file is generated, but in a printed manual it causes
+the contents of the file @file{filename} to be processed and included in the
+manual. The contents of the file @file{filename} can be ignored by Info
+because the first file can refer to @file{filename} with menus as well as
+cross references. In the Info system, all the information is, as it were,
+`in one place'. However, when two printed manuals are made from two
+separate Texinfo files, the two manuals are separate, and even if they give
+each other as references, the references are to separate documents.
+Consequently, you will sometimes want to create a comprehensive, printed
+manual that contains all the necessary information together in one place.
+
+@code{@@include} files are special Texinfo files that are used only for
+making such a comprehensive manual. They are listed inside an outer file
+that contains nothing but the beginning and end matter of a Texinfo file
+and a number of @code{@@include} commands listing the included files.
+
+An @code{@@include} file--a file that will be listed inside an outer file
+and processed with the @code{@@include} command--should not start with
+@samp{\input texinfo}, as that has already been done by the outer file, and
+the character @samp{\} has already been redefined to generate a backslash
+in the output. Instead, an @code{@@include} file usually begins with a
+node; it lacks the beginning and ending of a Texinfo file that are
+described in the chapters on beginning and ending a file. @xref{Beginning
+a File}, and @pxref{Ending a File} @refill
+
+Likewise, an @code{@@include} file should not end with @code{@@bye}, since
+that would terminate @TeX{} processing immediately.
+
+Here is an example of a outer Texinfo file with @code{@@include} files
+within it:@refill
+
+@example
+\input texinfo @@c -*-texinfo-*-
+@@setfilename include
+@@settitle Include Manual
+
+@@setchapternewpage odd
+@@titlepage
+@@sp 12
+@@center @@titlefont@{Include Manual@}
+@@sp 2
+@@center by Whom Ever
+
+@@page
+Copyright @@copyright@{@} 1988 Free Software Foundation, Inc.
+@@end titlepage
+
+@@include foo.texinfo
+@@include bar.texinfo
+
+@@unnumbered Concept Index
+@@printindex cp
+
+@@summarycontents
+@@contents
+
+@@bye
+@end example
+
+@node TeX Input, Sample Permissions, Include Files, Top
+@comment node-name, next, previous, up
+@appendix @TeX{} Input Initialization
+@cindex TeX Input Initialization
+@cindex TEXINPUTS environment variable
+@cindex profile initialization file
+@cindex cshrc initialization file
+
+You must put an input command on the first line of every Texinfo file to
+tell @TeX{} to use the @file{texinfo.tex} file when it is processing the
+Texinfo source file. Otherwise @TeX{} will not know what to do with the
+@@-commands. (The @TeX{} input command is written as @samp{\input
+texinfo}. @xref{First Line}.)@refill
+
+@TeX{} needs to be told where to find the @file{texinfo.tex} file that you
+have told it to input. The preferred way to do this is to put
+@file{texinfo.tex} in the default inputs directory, which is the
+@file{/usr/lib/tex/macros} directory. If this is done (as it usually is
+when GNU Emacs is installed), @TeX{} will find the file and you don't have
+to do anything. Alternatively, you can put @file{texinfo.tex} in the
+directory in which the Texinfo source file is located.@refill
+
+However, you may want to specify the location of the @code{\input} file
+yourself. One way to do this is to write the complete path for the file
+after the @code{\input} command. Another way is to set the
+@samp{TEXINPUTS} environment variable in your @file{.cshrc} or
+@file{.profile} file. The @samp{TEXINPUTS} environment variable will tell
+@TeX{} where to find the @file{texinfo.tex} file and any other file that
+you might want @TeX{} to use.@refill
+
+Whether you use a @file{.cshrc} or @file{.profile} file depends on whether
+you use @samp{csh} or @samp{sh} for your shell command interpreter. When
+you use @samp{csh}, it looks to the @file{.cshrc} file for initialization
+information, and when you use @samp{sh}, it looks to the @file{.profile}
+file.@refill
+
+In a @file{.cshrc} file, you could use the following @code{csh} command
+sequence:@refill
+
+@example
+setenv TEXINPUTS .:/usr/me/mylib:/usr/lib/tex/macros
+@end example
+
+@noindent
+In a @file{.profile} file, you could use the following @code{sh} command
+sequence:
+
+@example
+TEXINPUTS=.:/usr/me/mylib:/usr/lib/tex/macros
+export TEXINPUTS
+@end example
+
+@noindent
+This would cause @TeX{} to look for @file{\input} file first in the current
+directory, indicated by the @samp{.}, then in a hypothetical user's
+@file{me/mylib} directory, and finally in the system library.@refill
+
+@node Sample Permissions, Command Index, TeX Input, Top
+@comment node-name, next, previous, up
+@appendix Standard text for Copying Permissions
+@cindex Permissions
+@cindex Copying permissions
+
+Texinfo files should contain sections that tell the readers that they have
+the right to copy and distribute the Info file, the printed manual and any
+accompanying software. This appendix contains the standard text of the
+Free Software Foundation copying permission notice. For an example of the
+text that could be used for the Distribution, General Public License and NO
+WARRANTY sections of a document, see the latest version of the @cite{GNU
+Emacs Manual}.
+
+The texts of the Free Software Foundation copying permission notice in the
+@code{@@ifinfo} section and in the @code{@@titlepage} section are slightly
+different.
+
+The @code{@@ifinfo} section usually begins with a line that says what the
+file documents. This is what a person looking at the file will first read
+if he or she reads the unprocessed Texinfo file or if he or she uses the
+advanced Info command @kbd{g *}. @inforef{Expert, info, info}, for more
+information. (If the reader uses the regular Info commands, he or she will
+usually start reading at the first node and skip this first section, which
+is not in a node.)
+
+In the @code{@@ifinfo} section, the summary sentence should be followed by
+a copyright notice and then by the copying permission notice. One of the
+copying permission paragraphs is enclosed in @code{@@ignore} and
+@code{@@end ignore} commands. This paragraph states that the Texinfo file
+can be processed through @TeX{} and printed, provided the printed manual
+carries the proper copying permission notice. This paragraph is not made
+part of the Info file since it is not relevant to the Info file; but it is
+a mandatory part of the Texinfo file since it permits people to process the
+Texinfo file in @TeX{}.@refill
+
+In the printed manual, the Free Software Foundation copying permission
+notice follows the copyright notice and publishing information and is
+located within the region delineated by the @code{@@titlepage} and
+@code{@@end titlepage} commands. The copying permission notice is exactly
+the same as the notice in the @code{@@ifinfo} section except that the
+paragraph enclosed in @code{@@ignore} and @code{@@end ignore} commands is
+not part of the notice.@refill
+
+To make it simpler to copy the permission notice into each section of the
+Texinfo file, the complete permission notices for each section are
+reproduced in full below even though most of the information is
+redundant.@refill
+
+Note that you my have to specify the correct name of a section mentioned in
+the permission notice. For example, in the @cite{GDB Manual}, the name of
+the section referring to the General Public License is called the ``GDB
+General Public License'', but in the sample shown below, that section is
+referred to generically as the ``General Public License''.
+
+@menu
+* Ifinfo Permissions::
+* Titlepage Permissions::
+@end menu
+
+
+@node Ifinfo Permissions, Titlepage Permissions, Sample Permissions, Sample Permissions
+@comment node-name, next, previous, up
+@appendixsec Ifinfo Copying Permissions
+@cindex Ifinfo permissions
+
+In the @code{@@ifinfo} section of the Texinfo file, the standard Free
+Software Foundation permission notices reads as follows:
+
+@example
+This file documents @dots{}
+
+Copyright 1988 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+@@ignore
+Permission is granted to process this file through TeX and print the
+results, provided the printed document carries a copying permission
+notice identical to this one except for the removal of this paragraph
+(this paragraph not being relevant to the printed manual).
+
+@@end ignore
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided also that the
+sections entitled ``Distribution'' and ``General Public License'' are
+included exactly as in the original, and provided that the entire
+resulting derived work is distributed under the terms of a permission
+notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that the sections entitled ``Distribution'' and ``General Public
+License'' may be included in a translation approved by the author instead
+of in the original English.
+@end example
+
+@node Titlepage Permissions, , Ifinfo Permissions, Sample Permissions
+@comment node-name, next, previous, up
+@appendixsec Titlepage Copying Permissions
+@cindex Titlepage permissions
+
+In the @code{@@titlepage} section of the Texinfo file, the standard Free
+Software Foundation copying permission notices follows the copyright notice
+and publishing information. The standard phrasing is:
+
+@example
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided also that the
+sections entitled ``Distribution'' and ``General Public License'' are
+included exactly as in the original, and provided that the entire
+resulting derived work is distributed under the terms of a permission
+notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that the sections entitled ``Distribution'' and ``General Public
+License'' may be included in a translation approved by the author instead
+of in the original English.
+@end example
+
+@node Command Index, Concept Index, Sample Permissions, Top
+@comment node-name, next, previous, up
+@unnumbered Command Index
+
+(When used in a Texinfo file, @@-commands are preceded by an
+@samp{@@}.)@refill
+
+@printindex fn
+
+@node Concept Index, , Command Index, Top
+@comment node-name, next, previous, up
+@unnumbered Concept Index
+
+@printindex cp
+
+@summarycontents
+@contents
+@bye
diff --git a/man/vip.texinfo b/man/vip.texinfo
new file mode 100644
index 00000000000..ba4411a5e38
--- /dev/null
+++ b/man/vip.texinfo
@@ -0,0 +1,1960 @@
+% -*-texinfo-*-
+
+% Follow the following instructions to print the VIP manual.
+%
+% Run tex on this file:
+%
+% tex vip.texinfo
+%
+% This creates vip.dvi and some files for cross references and
+% indices. Since the manual contains key index and concept
+% index, it is necessary to create sorted index files for
+% them. It is also necessary to edit the file vip.kys. This
+% is done as follows.
+%
+% texindex vip.ky vip.cp
+% sed -e '/\\initial/ d' -e 's/{[^ ]* /{/' vip.kys > tmp
+% mv tmp vip.kys
+% tex vip.texinfo
+%
+% The dvi file created by the second run of tex can be used
+% for printing.
+
+\input texinfo
+
+@setfilename ../info/vip
+@settitle VIP
+
+@iftex
+@finalout
+@end iftex
+
+@titlepage
+@sp 10
+@center @titlefont{VIP}
+@sp 1
+@center A Vi Package for GNU Emacs
+@center (Version 3.5, September 15, 1987)
+@sp 2
+@center Masahiko Sato
+@sp 2
+@end titlepage
+
+@unnumbered Distribution
+
+Copyright @copyright{} 1987 Masahiko Sato.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+@ignore
+Permission is granted to process this file through Tex and print the
+results, provided the printed document carries copying permission
+notice identical to this one except for the removal of this paragraph
+(this paragraph not being relevant to the printed manual).
+
+@end ignore
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the entire
+resulting derived work is distributed under the terms of a permission
+notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the same conditions as for modified versions.
+
+@ifinfo
+@node Top, Survey,, (DIR)
+
+VIP
+***
+
+VIP is a Vi emulating package written in Emacs Lisp. VIP implements most
+Vi commands including Ex commands. It is therefore hoped that this package
+will enable you to do Vi style editing under the powerful GNU Emacs
+environment. This info file describes the usage of VIP assuming that you
+are fairly accustomed to Vi but not so much with Emacs. Also we will
+concentrate mainly on differences from Vi, especially features unique to
+VIP.
+
+It is recommended that you read nodes on survey and on customization before
+you start using VIP. Other nodes may be visited as needed.
+
+Comments and bug reports are welcome. Please send messages to
+@code{ms@@Sail.Stanford.Edu} if you are outside of Japan and to
+@code{masahiko@@sato.riec.tohoku.junet} if you are in Japan.@refill
+
+@end ifinfo
+
+@menu
+* Survey:: A survey of VIP.
+* Vi Commands:: Details of Vi commands.
+* Ex Commands:: Details of Ex commands.
+* Customization:: How to customize VIP.
+@end menu
+@iftex
+@unnumbered Introduction
+
+VIP is a Vi emulating package written in Emacs Lisp. VIP implements most
+Vi commands including Ex commands. It is therefore hoped that this package
+will enable you to do Vi style editing under the powerful GNU Emacs
+environment. This manual describes the usage of VIP assuming that you are
+fairly accustomed to Vi but not so much with Emacs. Also we will
+concentrate mainly on differences from Vi, especially features unique to
+VIP.
+
+It is recommended that you read chapters on survey and on customization
+before you start using VIP. Other chapters may be used as future
+references.
+
+Comments and bug reports are welcome. Please send messages to
+@code{ms@@Sail.Stanford.Edu} if you are outside of Japan and to
+@code{masahiko@@unsun.riec.tohoku.junet} if you are in Japan.
+@end iftex
+
+@node Survey, Basic Concepts, Top, Top
+@chapter A Survey of VIP
+
+In this chapter we describe basics of VIP with emphasis on the features not
+found in Vi and on how to use VIP under GNU Emacs.
+
+@menu
+* Basic Concepts:: Basic concepts in Emacs.
+* Loading VIP:: How to load VIP automatically.
+* Modes in VIP:: VIP has three modes, which are orthogonal to modes
+ in Emacs.
+* Differences from Vi:: Differences of VIP from Vi is explained.
+@end menu
+
+@node Basic Concepts, Loading VIP, Survey, Survey
+@section Basic Concepts
+
+We begin by explaining some basic concepts of Emacs. These concepts are
+explained in more detail in the GNU Emacs Manual.
+
+@cindex buffer
+@cindex point
+@cindex mark
+@cindex text
+@cindex looking at
+@cindex end (of buffer)
+@cindex region
+
+Conceptually, a @dfn{buffer} is just a string of ASCII characters and two
+special characters @key{PNT} (@dfn{point}) and @key{MRK} (@dfn{mark}) such
+that the character @key{PNT} occurs exactly once and @key{MRK} occurs at
+most once. The @dfn{text} of a buffer is obtained by deleting the
+occurrences of @key{PNT} and @key{MRK}. If, in a buffer, there is a
+character following @key{PNT} then we say that point is @dfn{looking at}
+the character; otherwise we say that point is @dfn{at the end of buffer}.
+@key{PNT} and @key{MRK} are used
+to indicate positions in a buffer and they are not part of the text of the
+buffer. If a buffer contains a @key{MRK} then the text between @key{MRK}
+and @key{PNT} is called the @dfn{region} of the buffer.@refill
+
+@cindex window
+
+Emacs provides (multiple) @dfn{windows} on the screen, and you can see the
+content of a buffer through the window associated with the buffer. The
+cursor of the screen is always positioned on the character after @key{PNT}.
+@refill
+
+@cindex mode
+@cindex keymap
+@cindex local keymap
+@cindex global keymap
+
+A @dfn{keymap} is a table that records the bindings between characters and
+command functions. There is the @dfn{global keymap} common to all the
+buffers. Each buffer has its @dfn{local keymap} that determines the
+@dfn{mode} of the buffer. Local keymap overrides global keymap, so that if
+a function is bound to some key in the local keymap then that function will
+be executed when you type the key. If no function is bound to a key in the
+local map, however, the function bound to the key in the global map becomes
+in effect.@refill
+
+@node Loading VIP, Modes in VIP, Basic Concepts, Survey
+@section Loading VIP
+
+The recommended way to load VIP automatically is to include the line:
+@example
+(load "vip")
+@end example
+@noindent
+in your @file{.emacs} file. The @file{.emacs} file is placed in your home
+directory and it will be executed every time you invoke Emacs. If you wish
+to be in vi mode whenver Emacs starts up, you can include the following
+line in your @file{.emacs} file instead of the above line:
+@example
+(setq term-setup-hook 'vip-mode)
+@end example
+@noindent
+(@xref{Vi Mode}, for the explanation of vi mode.)
+
+Even if your @file{.emacs} file does not contain any of the above lines,
+you can load VIP and enter vi mode by typing the following from within
+Emacs.
+@example
+M-x vip-mode
+@end example
+@noindent
+
+@node Modes in VIP, Emacs Mode, Loading VIP, Survey
+@section Modes in VIP
+
+@kindex 032 @kbd{C-z} (@code{vip-change-mode-to-vi})
+@kindex 0301 @kbd{C-x C-z} (@code{suspend-emacs})
+
+Loading VIP has the effect of globally binding @kbd{C-z} (@kbd{Control-z})
+to the function @code{vip-change-mode-to-vi}. The default binding of @kbd{C-z}
+in GNU Emacs is @code{suspend-emacs}, but, you can also call
+@code{suspend-emacs} by typing @kbd{C-x C-z}. Other than this, all the
+key bindings of Emacs remain the same after loading VIP.@refill
+
+@cindex vi mode
+
+Now, if you hit @kbd{C-z}, the function @code{vip-change-mode-to-vi} will be
+called and you will be in @dfn{vi mode}. (Some major modes may locally bind
+@kbd{C-z} to some special functions. In such cases, you can call
+@code{vip-change-mode-to-vi} by @code{execute-extended-command} which is
+invoked by @kbd{M-x}. Here @kbd{M-x} means @kbd{Meta-x}, and if your
+terminal does not have a @key{META} key you can enter it by typing
+@kbd{@key{ESC} x}. The same effect can also be achieve by typing
+@kbd{M-x vip-mode}.)@refill
+
+@cindex mode line
+
+You can observe the change of mode by looking at the @dfn{mode line}. For
+instance, if the mode line is:@refill
+@example
+-----Emacs: *scratch* (Lisp Interaction)----All------------
+@end example
+@noindent
+then it will change to:
+@example
+-----Vi: *scratch* (Lisp Interaction)----All------------
+@end example
+@noindent
+Thus the word @samp{Emacs} in the mode line will change to @samp{Vi}.
+
+@cindex insert mode
+@cindex emacs mode
+
+You can go back to the original @dfn{emacs mode} by typing @kbd{C-z} in
+vi mode. Thus @kbd{C-z} toggles between these two modes.@refill
+
+Note that modes in VIP exist orthogonally to modes in Emacs. This means
+that you can be in vi mode and at the same time, say, shell mode.
+
+Vi mode corresponds to Vi's command mode. From vi mode you can enter
+@dfn{insert mode} (which corresponds to Vi's insert mode) by usual Vi command
+keys like @kbd{i}, @kbd{a}, @kbd{o} @dots{} etc.
+
+In insert mode, the mode line will look like this:
+@example
+-----Insert *scratch* (Lisp Interaction)----All------------
+@end example
+@noindent
+You can exit from insert mode by hitting @key{ESC} key as you do in Vi.
+
+That VIP has three modes may seem very complicated, but in fact it is not
+so. VIP is implemented so that you can do most editing remaining only
+in the two modes for Vi (that is vi mode and insert mode).
+
+@ifinfo
+The figure below shows the transition of three modes in VIP.
+@display
+
+
+ === C-z ==> == i,o ... ==>
+emacs mode vi mode insert mode
+ <== X-z === <=== ESC ====
+@end display
+@end ifinfo
+
+@menu
+* Emacs Mode:: This is the mode you should know better.
+* Vi Mode:: Vi commands are executed in this mode.
+* Insert Mode:: You can enter text, and also can do editing if you
+ know enough Emacs commands.
+@end menu
+
+@node Emacs Mode, Vi Mode, Modes in VIP, Modes in VIP
+@subsection Emacs Mode
+
+@kindex 032 @kbd{C-z} (@code{vip-change-mode-to-vi})
+
+You will be in this mode just after you loaded VIP. You can do all
+normal Emacs editing in this mode. Note that the key @kbd{C-z} is globally
+bound to @code{vip-change-mode-to-vi}. So, if you type @kbd{C-z} in this mode
+then you will be in vi mode.@refill
+
+@node Vi Mode, Insert Mode, Emacs Mode, Modes in VIP
+@subsection Vi Mode
+
+This mode corresponds to Vi's command mode. Most Vi commands work as they
+do in Vi. You can go back to emacs mode by typing @kbd{C-z}. You can
+enter insert mode, just as in Vi, by typing @kbd{i}, @kbd{a} etc.
+
+@node Insert Mode, Differences from Vi, Vi Mode, Modes in VIP
+@subsection Insert Mode
+
+The key bindings in this mode is the same as in the emacs mode except for
+the following 4 keys. So, you can move around in the buffer and change
+its content while you are in insert mode.
+
+@table @kbd
+@item @key{ESC}
+@kindex 033 @kbd{ESC} (@code{vip-change-mode-to-vi}) (insert mode)
+This key will take you back to vi mode.
+@item C-h
+@kindex 010 @kbd{C-h} (@code{vip-delete-backward-char}) (insert mode)
+Delete previous character.
+@item C-w
+@kindex 027 @kbd{C-w} (@code{vip-delete-backward-word}) (insert mode)
+Delete previous word.
+@item C-z
+@kindex 032 @kbd{C-z} (@code{vip-ESC}) (insert mode)
+Typing this key has the same effect as typing @key{ESC} in emacs mode.
+Thus typing @kbd{C-z x} in insert mode will have the same effect as typing
+@kbd{ESC x} in emacs mode.
+@end table
+
+@node Differences from Vi, Undoing, Insert Mode, Survey
+@section Differences from Vi
+
+The major differences from Vi are explained below.
+
+@menu
+* Undoing:: You can undo more in VIP.
+* Changing:: Commands for changing the text.
+* Searching:: Search commands.
+* z Command:: You can now use zH, zM and zL as well as z- etc.
+* Counts:: Some Vi commands which do not accept a count now
+ accept one.
+* Marking:: You can now mark the current point, beginning of
+ the buffer etc.
+* Region Commands:: You can now give a region as an argument for delete
+ commands etc.
+* New Commands:: Some new commands not available in Vi are added.
+* New Bindings:: Bindings of some keys are changed for the
+ convenience of editing under Emacs.
+* Window Commands:: Commands for moving among windows etc.
+* Buffer Commands:: Commands for selecting buffers etc.
+* File Commands:: Commands for visiting files etc.
+* Misc Commands:: Other useful commands.
+@end menu
+
+@node Undoing, Changing, Differences from Vi, Differences from Vi
+@subsection Undoing
+
+@kindex 165 @kbd{u} (@code{vip-undo})
+@kindex 056 @kbd{.} (@code{vip-repeat})
+
+You can repeat undoing by the @kbd{.} key. So, @kbd{u} will undo
+a single change, while @kbd{u .@: .@: .@:}, for instance, will undo 4 previous
+changes. Undo is undoable as in Vi. So the content of the buffer will
+be the same before and after @kbd{u u}.@refill
+
+@node Changing, Searching, Undoing, Differences from Vi
+@subsection Changing
+
+Some commands which change a small number of characters are executed
+slightly differently. Thus, if point is at the beginning of a word
+@samp{foo} and you wished to change it to @samp{bar} by typing @w{@kbd{c w}},
+then VIP will prompt you for a new word in the minibuffer by the prompt
+@samp{foo => }. You can then enter @samp{bar} followed by @key{RET} or
+@key{ESC} to complete the command. Before you enter @key{RET} or
+@key{ESC} you can abort the command by typing @kbd{C-g}. In general,
+@kindex 007 @kbd{C-g} (@code{vip-keyboard-quit})
+you can abort a partially formed command by typing @kbd{C-g}.@refill
+
+@node Searching, z Command, Changing, Differences from Vi
+@subsection Searching
+
+@kindex 057 @kbd{/} (@code{vip-search-forward})
+@kindex 077 @kbd{?} (@code{vip-search-backward})
+
+As in Vi, searching is done by @kbd{/} and @kbd{?}. The string will be
+searched literally by default. To invoke a regular expression search,
+first execute the search command @kbd{/} (or @kbd{?}) with empty search
+string. (I.e, type @kbd{/} followed by @key{RET}.)
+A search for empty string will toggle the search mode between vanilla
+search and regular expression search. You cannot give an offset to the
+search string. (It is a limitation.) By default, search will wrap around
+the buffer as in Vi. You can change this by rebinding the variable
+@code{vip-search-wrap-around}. @xref{Customization}, for how to do this.@refill
+
+@node z Command, Counts, Searching, Differences from Vi
+@subsection z Command
+
+@kindex 1723 @kbd{z H} (@code{vip-line-to-top})
+@kindex 1721 @kbd{z RET} (@code{vip-line-to-top})
+@kindex 1723 @kbd{z M} (@code{vip-line-to-middle})
+@kindex 1722 @kbd{z .} (@code{vip-line-to-middle})
+@kindex 1723 @kbd{z L} (@code{vip-line-to-bottom})
+@kindex 1722 @kbd{z -} (@code{vip-line-to-bottom})
+
+For those of you who cannot remember which of @kbd{z} followed by @key{RET},
+@kbd{.}@: and @kbd{-} do what. You can also use @kbd{z} followed by @kbd{H},
+@kbd{M} and @kbd{L} to place the current line in the Home (Middle, and
+Last) line of the window.@refill
+
+@node Counts, Marking, z Command, Differences from Vi
+@subsection Counts
+
+Some Vi commands which do not accept a count now accept one
+
+@table @kbd
+@item p
+@itemx P
+@kindex 160 @kbd{p} (@code{vip-put-back})
+@kindex 120 @kbd{P} (@code{vip-Put-back})
+Given counts, text will be yanked (in Vi's sense) that many times. Thus
+@kbd{3 p} is the same as @kbd{p p p}.
+@item o
+@itemx O
+@kindex 157 @kbd{o} (@code{vip-open-line})
+@kindex 117 @kbd{O} (@code{vip-Open-line})
+Given counts, that many copies of text will be inserted. Thus
+@kbd{o a b c @key{ESC}} will insert 3 lines of @samp{abc} below the current
+line.
+@item /
+@itemx ?
+@kindex 057 @kbd{/} (@code{vip-search-forward})
+@kindex 077 @kbd{?} (@code{vip-search-backward})
+Given a count @var{n}, @var{n}-th occurrence will be searched.
+@end table
+
+@node Marking, Region Commands, Counts, Differences from Vi
+@subsection Marking
+
+Typing an @kbd{m} followed by a lower case character @var{ch} marks the
+point to the register named @var{ch} as in Vi. In addition to these, we
+have following key bindings for marking.
+
+@kindex 155 @kbd{m} (@code{vip-mark-point})
+
+@table @kbd
+@item m <
+Set mark at the beginning of buffer.
+@item m >
+Set mark at the end of buffer.
+@item m .
+Set mark at point (and push old mark on mark ring).
+@item m ,
+Jump to mark (and pop mark off the mark ring).
+@end table
+
+@node Region Commands, New Commands, Marking, Differences from Vi
+@subsection Region Commands
+
+@cindex region
+
+Vi operators like @kbd{d}, @kbd{c} etc. are usually used in combination
+with motion commands. It is now possible to use current region as the
+argument to these operators. (A @dfn{region} is a part of buffer
+delimited by point and mark.) The key @kbd{r} is used for this purpose.
+Thus @kbd{d r} will delete the current region. If @kbd{R} is used instead
+of @kbd{r} the region will first be enlarged so that it will become the
+smallest region containing the original region and consisting of whole
+lines. Thus @kbd{m .@: d R} will have the same effect as @kbd{d d}.@refill
+
+@node New Commands, New Bindings, Region Commands, Differences from Vi
+@subsection Some New Commands
+
+Note that the keys below (except for @kbd{R}) are not used in Vi.
+
+@table @kbd
+@item C-a
+@kindex 001 @kbd{C-a} (@code{vip-beginning-of-line})
+Move point to the beginning of line.
+@item C-n
+@kindex 016 @kbd{C-n} (@code{vip-next-window})
+If you have two or more windows in the screen, this key will move point to
+the next window.
+@item C-o
+@kindex 017 @kbd{C-o} (@code{vip-open-line-at-point})
+Insert a newline and leave point before it, and then enter insert mode.
+@item C-r
+@kindex 022 @kbd{C-r} (@code{isearch-backward})
+Backward incremental search.
+@item C-s
+@kindex 023 @kbd{C-s} (@code{isearch-forward})
+Forward incremental search.
+@item C-c
+@itemx C-x
+@itemx @key{ESC}
+@kindex 003 @kbd{C-c} (@code{vip-ctl-c})
+@kindex 0300 @kbd{C-x} (@code{vip-ctl-x})
+@kindex 033 @kbd{ESC} (@code{vip-ESC})
+These keys will exit from vi mode and return to emacs mode temporarily. If
+you hit one of these keys, Emacs will be in emacs mode and will believe
+that you hit that key in emacs mode. For example, if you hit @kbd{C-x}
+followed by @kbd{2}, then the current window will be split into 2 and you
+will be in vi mode again.
+@item \
+@kindex 134 @kbd{\} (@code{vip-escape-to-emacs})
+Escape to emacs mode. Hitting @kbd{\} will take you to emacs mode, and you
+can execute a single Emacs command. After executing the Emacs command you
+will be in vi mode again. You can give a count before typing @kbd{\}.
+Thus @kbd{5 \ *}, as well as @kbd{\ C-u 5 *}, will insert @samp{*****}
+before point. Similarly @kbd{1 0 \ C-p} will move the point 10 lines above
+the current line.@refill
+@item K
+@kindex 113 @kbd{K} (@code{vip-kill-buffer})
+Kill current buffer if it is not modified. Useful when you selected a
+buffer which you did not want.
+@item Q
+@itemx R
+@kindex 121 @kbd{Q} (@code{vip-query-replace})
+@kindex 122 @kbd{R} (@code{vip-replace-string})
+@kbd{Q} is for query replace and @kbd{R} is for replace. By default,
+string to be replaced are treated literally. If you wish to do a regular
+expression replace, first do replace with empty string as the string to be
+replaced. In this way, you can toggle between vanilla and regular
+expression replacement.
+@item v
+@itemx V
+@kindex 166 @kbd{v} (@code{vip-find-file})
+@kindex 126 @kbd{V} (@code{vip-find-file-other-window})
+These keys are used to Visit files. @kbd{v} will switch to a buffer
+visiting file whose name can be entered in the minibuffer. @kbd{V} is
+similar, but will use window different from the current window.
+@item #
+@kindex 0430 @kbd{#} (@code{vip-command-argument})
+If followed by a certain character @var{ch}, it becomes an operator whose
+argument is the region determined by the motion command that follows.
+Currently, @var{ch} can be one of @kbd{c}, @kbd{C}, @kbd{g}, @kbd{q} and
+@kbd{s}.@refill
+@item # c
+@kindex 0432 @kbd{# c} (@code{downcase-region})
+Change upper case characters in the region to lower case
+(@code{downcase-region}).
+@item # C
+@kindex 0431 @kbd{# C} (@code{upcase-region})
+Change lower case characters in the region to upper case. For instance,
+@kbd{# C 3 w} will capitalize 3 words from the current point
+(@code{upcase-region}).
+@item # g
+@kindex 0432 @kbd{# g} (@code{vip-global-execute})
+Execute last keyboard macro for each line in the region
+(@code{vip-global-execute}).@refill
+@item # q
+@kindex 0432 @kbd{# q} (@code{vip-quote-region})
+Insert specified string at the beginning of each line in the region
+(@code{vip-quote-region}).
+@item # s
+@kindex 0432 @kbd{# s} (@code{spell-region})
+Check spelling of words in the region (@code{spell-region}).
+@item *
+@kindex 052 @kbd{*} (@code{vip-call-last-kbd-macro})
+Call last keyboard macro.
+@end table
+
+@node New Bindings, Window Commands, New Commands, Differences from Vi
+@subsection New Key Bindings
+
+In VIP the meanings of some keys are entirely different from Vi. These key
+bindings are done deliberately in the hope that editing under Emacs will
+become easier. It is however possible to rebind these keys to functions
+which behave similarly as in Vi. @xref{Customizing Key Bindings}, for
+details.
+
+@table @kbd
+@item C-g
+@itemx g
+@kindex 007 @kbd{C-g} (@code{vip-keyboard-quit})
+@kindex 147 @kbd{g} (@code{vip-info-on-file})
+In Vi, @kbd{C-g} is used to get information about the file associated to
+the current buffer. Here, @kbd{g} will do that, and @kbd{C-g} is
+used to abort a command (this is for compatibility with emacs mode.)
+@item SPC
+@itemx @key{RET}
+@kindex 040 @kbd{SPC} (@code{vip-scroll})
+@kindex 015 @kbd{RET} (@code{vip-scroll-back})
+Now these keys will scroll up and down the text of current window.
+Convenient for viewing the text.
+@item s
+@itemx S
+@kindex 163 @kbd{s} (@code{vip-switch-to-buffer})
+@kindex 123 @kbd{S} (@code{vip-switch-to-buffer-other-window})
+They are used to switch to a specified buffer. Useful for switching to
+already existing buffer since buffer name completion is provided. Also
+a default buffer will be given as part of the prompt, to which you can
+switch by just typing @key{RET} key. @kbd{s} is used to select buffer
+in the current window, while @kbd{S} selects buffer in another window.
+@item C
+@itemx X
+@kindex 103 @kbd{C} (@code{vip-ctl-c-equivalent})
+@kindex 1300 @kbd{X} (@code{vip-ctl-x-equivalent})
+These keys will exit from vi mode and return to emacs mode temporarily.
+If you type @kbd{C} (@kbd{X}), Emacs will be in emacs mode and will believe
+that you have typed @kbd{C-c} (@kbd{C-x}, resp.) in emacs mode. Moreover,
+if the following character you type is an upper case letter, then Emacs
+will believe that you have typed the corresponding control character.
+You will be in vi mode again after the command is executed. For example,
+typing @kbd{X S} in vi mode is the same as typing @kbd{C-x C-s} in emacs
+mode. You get the same effect by typing @kbd{C-x C-s} in vi mode, but
+the idea here is that you can execute useful Emacs commands without typing
+control characters. For example, if you hit @kbd{X} (or @kbd{C-x}) followed
+by @kbd{2}, then the current window will be split into 2 and you will be in
+vi mode again.@refill
+@end table
+
+In addition to these, @code{ctl-x-map} is slightly modified:
+
+@kindex 1301 @kbd{X 3} (@code{vip-buffer-in-two-windows})
+
+@table @kbd
+@item X 3
+@itemx C-x 3
+This is equivalent to @kbd{C-x 1 C-x 2} (1 + 2 = 3).
+@end table
+
+@node Window Commands, Buffer Commands, New Bindings, Differences from Vi
+@subsection Window Commands
+
+In this and following subsections, we give a summary of key bindings for
+basic functions related to windows, buffers and files.
+
+@table @kbd
+@item C-n
+@kindex 016 @kbd{C-n} (@code{vip-next-window})
+Switch to next window.
+@item X 1
+@itemx C-x 1
+@kindex 1301 @kbd{X 1} (@code{delete-other-windows})
+Delete other windows.
+@item X 2
+@itemx C-x 2
+@kindex 1301 @kbd{X 2} (@code{split-window-vertically})
+Split current window into two windows.
+@item X 3
+@itemx C-x 3
+@kindex 1301 @kbd{X 3} (@code{vip-buffer-in-two-windows})
+Show current buffer in two windows.
+@end table
+
+@node Buffer Commands, File Commands, Window Commands, Differences from Vi
+@subsection Buffer Commands
+
+@table @kbd
+@item s
+@kindex 163 @kbd{s} (@code{vip-switch-to-buffer})
+Switch to the specified buffer in the current window
+(@code{vip-switch-to-buffer}).
+@item S
+@kindex 123 @kbd{S} (@code{vip-switch-to-buffer-other-window})
+Switch to the specified buffer in another window
+(@code{vip-switch-to-buffer-other-window}).
+@item K
+@kindex 113 @kbd{K} (@code{vip-kill-buffer})
+Kill the current buffer if it is not modified.
+@item X S
+@itemx C-x C-s
+@kindex 1302 @kbd{X S} (@code{save-buffer})
+Save the current buffer in the file associated to the buffer.
+@end table
+
+@node File Commands, Misc Commands, Buffer Commands, Differences from Vi
+@subsection File Commands
+
+@table @kbd
+@item v
+@kindex 166 @kbd{v} (@code{vip-find-file})
+Visit specified file in the current window.
+@item V
+@kindex 126 @kbd{V} (@code{vip-find-file-other-window})
+Visit specified file in another window.
+@item X W
+@itemx C-x C-w
+@kindex 1302 @kbd{X W} (@code{write-file})
+Write current buffer into the specified file.
+@item X I
+@itemx C-x C-i
+@kindex 1302 @kbd{X I} (@code{insert-file})
+
+Insert specified file at point.
+@end table
+
+@node Misc Commands, Vi Commands, File Commands, Differences from Vi
+@subsection Miscellaneous Commands
+
+@table @kbd
+@item X (
+@itemx C-x (
+@kindex 1301 @kbd{X (} (@code{start-kbd-macro})
+Start remembering keyboard macro.
+@item X )
+@itemx C-x )
+@kindex 1301 @kbd{X )} (@code{end-kbd-macro})
+Finish remembering keyboard macro.
+@item *
+@kindex 052 @kbd{*} (@code{vip-call-last-kbd-macro})
+Call last remembered keyboard macro.
+@item X Z
+@itemx C-x C-z
+@kindex 1302 @kbd{X Z} (@code{suspend-emacs})
+Suspend Emacs.
+@item Z Z
+Exit Emacs.
+@itemx Q
+Query replace.
+@itemx R
+Replace.
+@end table
+
+@node Vi Commands, Numeric Arguments, Misc Commands, Top
+@chapter Vi Commands
+
+This chapter describes Vi commands other than Ex commands implemented in
+VIP. Except for the last section which discusses insert mode, all the
+commands described in this chapter are to be used in vi mode.
+
+@menu
+* Numeric Arguments:: Many commands accept numeric arguments
+* Important Keys:: Some very important keys.
+* Buffers and Windows:: Commands for handling buffers and windows.
+* Files:: Commands for handling files.
+* Viewing the Buffer:: How you can view the current buffer.
+* Mark Commands:: Marking positions in a buffer.
+* Motion Commands:: Commands for moving point.
+* Modifying Commands:: Commands for modifying the buffer.
+@end menu
+
+@node Numeric Arguments, Important Keys, Vi Commands, Vi Commands
+@section Numeric Arguments
+
+@cindex numeric arguments
+@cindex count
+@kindex 061 @kbd{1} (numeric argument)
+@kindex 062 @kbd{2} (numeric argument)
+@kindex 063 @kbd{3} (numeric argument)
+@kindex 064 @kbd{4} (numeric argument)
+@kindex 065 @kbd{5} (numeric argument)
+@kindex 066 @kbd{6} (numeric argument)
+@kindex 067 @kbd{7} (numeric argument)
+@kindex 068 @kbd{8} (numeric argument)
+@kindex 069 @kbd{9} (numeric argument)
+
+Most Vi commands accept a @dfn{numeric argument} which can be supplied as
+a prefix to the commands. A numeric argument is also called a @dfn{count}.
+In many cases, if a count is given, the command is executed that many times.
+For instance, @kbd{5 d d} deletes 5 lines while simple @kbd{d d} deletes a
+line. In this manual the metavariable @var{n} will denote a count.@refill
+
+@node Important Keys, Buffers and Windows, Numeric Arguments, Vi Commands
+@section Important Keys
+
+The keys @kbd{C-g} and @kbd{C-l} are unique in that their associated
+functions are the same in any of emacs, vi and insert mode.
+
+@table @kbd
+@item C-g
+@kindex 007 @kbd{C-g} (@code{vip-keyboard-quit})
+Quit. Cancel running or partially typed command (@code{keyboard-quit}).
+@item C-l
+@kindex 014 @kbd{C-l} (@code{recenter})
+Clear the screen and reprint everything (@code{recenter}).
+@end table
+
+In Emacs many commands are bound to the key strokes that start with
+@kbd{C-x}, @kbd{C-c} and @key{ESC}. These commands can be
+accessed from vi mode as easily as from emacs mode.@refill
+
+@table @kbd
+@item C-x
+@itemx C-c
+@itemx @key{ESC}
+@kindex 003 @kbd{C-c} (@code{vip-ctl-c})
+@kindex 0300 @kbd{C-x} (@code{vip-ctl-x})
+@kindex 033 @kbd{ESC} (@code{vip-ESC})
+Typing one of these keys have the same effect as typing it in emacs mode.
+Appropriate command will be executed according as the keys you type after
+it. You will be in vi mode again after the execution of the command.
+For instance, if you type @kbd{@key{ESC} <} (in vi mode) then the cursor will
+move to the beginning of the buffer and you will still be in vi mode.
+@item C
+@itemx X
+@kindex 103 @kbd{C} (@code{vip-ctl-c-equivalent})
+@kindex 1300 @kbd{X} (@code{vip-ctl-x-equivalent})
+Typing one of these keys have the effect of typing the corresponding
+control character in emacs mode. Moreover, if you type an upper case
+character following it, that character will also be translated to the
+corresponding control character. Thus typing @kbd{X W} in vi mode is the
+same as typing @kbd{C-x C-w} in emacs mode. You will be in vi mode again
+after the execution of a command.
+@item \
+@kindex 134 @kbd{\} (@code{vip-escape-to-emacs})
+Escape to emacs mode. Hitting the @kbd{\} key will take you to emacs mode,
+and you can execute a single Emacs command. After executing the
+Emacs command you will be in vi mode again. You can give a count before
+typing @kbd{\}. Thus @kbd{5 \ +}, as well as @kbd{\ C-u 5 +}, will insert
+@samp{+++++} before point.@refill
+@end table
+
+@node Buffers and Windows, Files, Important Keys, Vi Commands
+@section Buffers and Windows
+
+@cindex buffer
+@cindex selected buffer
+@cindex current buffer
+
+In Emacs the text you edit is stored in a @dfn{buffer}.
+See GNU Emacs Manual, for details. There is always one @dfn{selected}
+buffer which is called the @dfn{current buffer}.@refill
+
+@cindex window
+@cindex modified (buffer)
+
+You can see the contents of buffers through @dfn{windows} created by Emacs.
+When you have multiple windows on the screen only one of them is selected.
+Each buffer has a unique name, and each window has a mode line which shows
+the name of the buffer associated with the window and other information
+about the status of the buffer. You can change the format of the mode
+line, but normally if you see @samp{**} at the beginning of a mode line it
+means that the buffer is @dfn{modified}. If you write out the content of
+the buffer to a file, then the buffer will become not modified. Also if
+you see @samp{%%} at the beginning of the mode line, it means that the file
+associated with the buffer is write protected.
+
+We have the following commands related to windows and buffers.
+
+@table @kbd
+@item C-n
+@kindex 016 @kbd{C-n} (@code{vip-next-window})
+Move cursor to the next-window (@code{vip-next-window}).
+@item X 1
+@kindex 1301 @kbd{X 1} (@code{delete-other-windows})
+Delete other windows and make the selected window fill the screen
+@*(@code{delete-other-windows}).
+@item X 2
+@kindex 1301 @kbd{X 2} (@code{split-window-vertically})
+Split current window into two windows (@code{split-window-vertically}).
+@item X 3
+@kindex 1301 @kbd{X 3} (@code{vip-buffer-in-two-windows})
+Show current buffer in two windows.
+@item s @var{buffer} @key{RET}
+@kindex 163 @kbd{s} (@code{vip-switch-to-buffer})
+Select or create a buffer named @var{buffer} (@code{vip-switch-to-buffer}).
+@item S @var{buffer} @key{RET}
+@kindex 123 @kbd{S} (@code{vip-switch-to-buffer-other-window})
+Similar but select a buffer named @var{buffer} in another window
+@*(@code{vip-switch-to-buffer-other-window}).
+@item K
+@kindex 113 @kbd{K} (@code{vip-kill-buffer})
+Kill the current buffer if it is not modified or if it is not associated
+with a file @*(@code{vip-kill-buffer}).
+@item X B
+@kindex 1302 @kbd{X B} (@code{list-buffers})
+List the existing buffers (@code{list-buffers}).
+@end table
+
+@cindex buffer name completion
+
+As @dfn{buffer name completion} is provided, you have only to type in
+initial substring of the buffer name which is sufficient to identify it
+among names of existing buffers. After that, if you hit @key{TAB} the rest
+of the buffer name will be supplied by the system, and you can confirm it
+by @key{RET}. The default buffer name to switch to will also be prompted,
+and you can select it by giving a simple @key{RET}. See GNU Emacs Manual
+for details of completion.
+
+@node Files, Viewing the Buffer, Buffers and Windows, Vi Commands
+@section Files
+
+We have the following commands related to files. They are used to visit,
+save and insert files.
+
+@table @kbd
+@item v @var{file} @key{RET}
+@kindex 166 @kbd{v} (@code{vip-find-file})
+Visit specified file in the current window (@code{vip-find-file}).
+@item V @var{file} @key{RET}
+@kindex 126 @kbd{V} (@code{vip-find-file-other-window})
+Visit specified file in another window (@code{vip-find-file-other-window}).
+@item X S
+@kindex 1302 @kbd{X S} (@code{save-buffer})
+Save current buffer to the file associated with the buffer. If no file is
+associated with the buffer, the name of the file to write out the content
+of the buffer will be asked in the minibuffer.
+@item X W @var{file} @key{RET}
+@kindex 1302 @kbd{X W} (@code{write-file})
+Write current buffer into a specified file.
+@item X I @var{file} @key{RET}
+@kindex 1302 @kbd{X I} (@code{insert-file})
+Insert a specified file at point.
+@item g
+@kindex 147 @kbd{g} (@code{vip-info-on-file})
+Give information on the file associated with the current buffer. Tell you
+the name of the file associated with the buffer, the line number of the
+current point and total line numbers in the buffer. If no file is
+associated with the buffer, this fact will be indicated by the null file
+name @samp{""}.
+@end table
+
+@cindex visiting (a file)
+@cindex default directory
+
+In Emacs, you can edit a file by @dfn{visiting} it. If you wish to visit a
+file in the current window, you can just type @kbd{v}. Emacs maintains the
+@dfn{default directory} which is specific to each buffer. Suppose, for
+instance, that the default directory of the current buffer is
+@file{/usr/masahiko/lisp/}. Then you will get the following prompt in the
+minibuffer.@refill
+@example
+visit file: /usr/masahiko/lisp/
+@end example
+@noindent
+@cindex file name completion
+If you wish to visit, say, @file{vip.el} in this directory, then you can
+just type @samp{vip.el} followed by @key{RET}. If the file @file{vip.el}
+already exists in the directory, Emacs will visit that file, and if not,
+the file will be created. Emacs will use the file name (@file{vip.el}, in
+this case) as the name of the buffer visiting the file. In order to make
+the buffer name unique, Emacs may append @samp{<2>}, @samp{<3>} etc., to
+the buffer name. As the @dfn{file name completion} is provided here, you
+can sometime save typing. For instance, suppose there is only one file in the
+default directory whose name starts with @samp{v}, that is @samp{vip.el}.
+Then if you just type @kbd{v @key{TAB}} then it will be completed to
+@samp{vip.el}. Thus, in this case, you just have to type @kbd{v v @key{TAB}
+@key{RET}} to visit @file{/usr/masahiko/lisp/vip.el}. Continuing the
+example, let us now suppose that you wished to visit the file
+@file{/usr/masahiko/man/vip.texinfo}. Then to the same prompt which you get
+after you typed @kbd{v}, you can enter @samp{/usr/masahiko/man/vip.texinfo} or
+@samp{../man/vip.texinfo} followed by @key{RET}.
+
+Use @kbd{V} instead of @kbd{v}, if you wish to visit a file in another
+window.
+
+You can verify which file you are editing by typing @kbd{g}. (You can also
+type @kbd{X B} to get nformation on other buffers too.) If you type
+@kbd{g} you will get an information like below in the echo area:@refill
+@example
+"/usr/masahiko/man/vip.texinfo" line 921 of 1949
+@end example
+
+After you edited the buffer (@samp{vip.texinfo}, in our example) for a while,
+you may wish to save it in a file. If you wish to save it in the file
+associated with the buffer (@file{/usr/masahiko/man/vip.texinfo}, in this
+case), you can just say @kbd{X S}. If you wish to save it in another file,
+you can type @kbd{X W}. You will then get a similar prompt as you get for
+@kbd{v}, to which you can enter the file name.@refill
+
+@node Viewing the Buffer, Mark Commands, Files, Vi Commands
+@section Viewing the Buffer
+
+In this and next section we discuss commands for moving around in the
+buffer. These command do not change the content of the buffer. The
+following commands are useful for viewing the content of the current
+buffer.
+
+@table @kbd
+@item @key{SPC}
+@itemx C-f
+@kindex 040 @kbd{SPC} (@code{vip-scroll})
+@kindex 006 @kbd{C-f} (@code{vip-scroll-back})
+Scroll text of current window upward almost full screen. You can go
+@i{forward} in the buffer by this command (@code{vip-scroll}).
+@item @key{RET}
+@itemx C-b
+@kindex 015 @kbd{RET} (@code{vip-scroll-back})
+@kindex 002 @kbd{C-b} (@code{vip-scroll-back})
+Scroll text of current window downward almost full screen. You can go
+@i{backward} in the buffer by this command (@code{vip-scroll-back}).
+@itemx C-d
+@kindex 004 @kbd{C-d} (@code{vip-scroll-up})
+Scroll text of current window upward half screen. You can go
+@i{down} in the buffer by this command (@code{vip-scroll-down}).
+@itemx C-u
+@kindex 025 @kbd{C-u} (@code{vip-scroll-down})
+Scroll text of current window downward half screen. You can go
+@i{up} in the buffer by this command (@code{vip-scroll-up}).
+@item C-y
+@kindex 031 @kbd{C-y} (@code{vip-scroll-down-one})
+Scroll text of current window upward by one line (@code{vip-scroll-down-one}).
+@item C-e
+@kindex 005 @kbd{C-e} (@code{vip-scroll-up-one})
+Scroll text of current window downward by one line (@code{vip-scroll-up-one}).
+@end table
+@noindent
+You can repeat these commands by giving a count. Thus, @kbd{2 @key{SPC}}
+has the same effect as @kbd{@key{SPC} @key{SPC}}.
+
+The following commands reposition point in the window.
+
+@table @kbd
+@item z H
+@itemx z @key{RET}
+@kindex 1723 @kbd{z H} (@code{vip-line-to-top})
+@kindex 1721 @kbd{z RET} (@code{vip-line-to-top})
+Put point on the top (@i{home}) line in the window. So the current line
+becomes the top line in the window. Given a count @var{n}, point will be
+placed in the @var{n}-th line from top (@code{vip-line-to-top}).
+@item z M
+@itemx z .
+@kindex 1723 @kbd{z M} (@code{vip-line-to-middle})
+@kindex 1722 @kbd{z .} (@code{vip-line-to-middle})
+Put point on the @i{middle} line in the window. Given a count @var{n},
+point will be placed in the @var{n}-th line from the middle line
+(@code{vip-line-to-middle}).
+@item z L
+@itemx z -
+@kindex 1723 @kbd{z L} (@code{vip-line-to-bottom})
+@kindex 1722 @kbd{z -} (@code{vip-line-to-bottom})
+Put point on the @i{bottom} line in the window. Given a count @var{n},
+point will be placed in the @var{n}-th line from bottom
+(@code{vip-line-to-bottom}).
+@item C-l
+Center point in window and redisplay screen (@code{recenter}).
+@end table
+
+@node Mark Commands, Motion Commands, Viewing the Buffer, Vi Commands
+@section Mark Commands
+
+The following commands are used to mark positions in the buffer.
+
+@table @kbd
+@item m @var{ch}
+@kindex 155 @kbd{m} (@code{vip-mark-point})
+Store current point in the register @var{ch}. @var{ch} must be a lower
+case character between @kbd{a} and @kbd{z}.
+@item m <
+Set mark at the beginning of current buffer.
+@item m >
+Set mark at the end of current buffer.
+@item m .
+Set mark at point.
+@item m ,
+Jump to mark (and pop mark off the mark ring).
+@end table
+
+@cindex mark ring
+
+Emacs uses the @dfn{mark ring} to store marked positions. The commands
+@kbd{m <}, @kbd{m >} and @kbd{m .}@: not only set mark but also add it as the
+latest element of the mark ring (replacing the oldest one). By repeating
+the command `@kbd{m ,}' you can visit older and older marked positions. You
+will eventually be in a loop as the mark ring is a ring.
+
+@node Motion Commands, Searching and Replacing, Mark Commands, Vi Commands
+@section Motion Commands
+
+Commands for moving around in the current buffer are collected here. These
+commands are used as an `argument' for the delete, change and yank commands
+to be described in the next section.
+
+@table @kbd
+@item h
+@kindex 150 @kbd{h} (@code{vip-backward-char})
+Move point backward by one character. Signal error if point is at the
+beginning of buffer, but (unlike Vi) do not complain otherwise
+(@code{vip-backward-char}).
+@item l
+@kindex 154 @kbd{l} (@code{vip-forward-char})
+Move point backward by one character. Signal error if point is at the
+end of buffer, but (unlike Vi) do not complain otherwise
+(@code{vip-forward-char}).
+@item j
+@kindex 152 @kbd{j} (@code{vip-next-line})
+Move point to the next line keeping the current column. If point is on the
+last line of the buffer, a new line will be created and point will move to
+that line (@code{vip-next-line}).
+@item k
+@kindex 153 @kbd{k} (@code{vip-previous-line})
+Move point to the previous line keeping the current column
+(@code{vip-next-line}).
+@item +
+@kindex 053 @kbd{+} (@code{vip-next-line-at-bol})
+Move point to the next line at the first non-white character. If point is
+on the last line of the buffer, a new line will be created and point will
+move to the beginning of that line (@code{vip-next-line-at-bol}).
+@item -
+@kindex 055 @kbd{-} (@code{vip-previous-line-at-bol})
+Move point to the previous line at the first non-white character
+(@code{vip-previous-line-at-bol}).
+@end table
+@noindent
+If a count is given to these commands, the commands will be repeated that
+many times.
+
+@table @kbd
+@item 0
+@kindex 060 @kbd{0} (@code{vip-beginning-of-line})
+Move point to the beginning of line (@code{vip-beginning-of-line}).
+@item ^
+@kindex 136 @kbd{^} (@code{vip-bol-and-skip-white})
+Move point to the first non-white character on the line
+(@code{vip-bol-and-skip-white}).
+@item $
+@kindex 044 @kbd{$} (@code{vip-goto-eol})
+Move point to the end of line (@code{vip-goto-eol}).
+@item @var{n} |
+@kindex 174 @kbd{|} (@code{vip-goto-col})
+Move point to the @var{n}-th column on the line (@code{vip-goto-col}).
+@end table
+@noindent
+Except for the @kbd{|} command, these commands neglect a count.
+
+@cindex word
+
+@table @kbd
+@item w
+@kindex 167 @kbd{w} (@code{vip-forward-word})
+Move point forward to the beginning of the next word
+(@code{vip-forward-word}).
+@item W
+@kindex 127 @kbd{W} (@code{vip-forward-Word})
+Move point forward to the beginning of the next word, where a @dfn{word} is
+considered as a sequence of non-white characters (@code{vip-forward-Word}).
+@item b
+@kindex 142 @kbd{b} (@code{vip-backward-word})
+Move point backward to the beginning of a word (@code{vip-backward-word}).
+@item B
+@kindex 102 @kbd{B} (@code{vip-backward-Word})
+Move point backward to the beginning of a word, where a @i{word} is
+considered as a sequence of non-white characters (@code{vip-forward-Word}).
+@item e
+@kindex 145 @kbd{e} (@code{vip-end-of-word})
+Move point forward to the end of a word (@code{vip-end-of-word}).
+@item E
+@kindex 105 @kbd{E} (@code{vip-end-of-Word})
+Move point forward to the end of a word, where a @i{word} is
+considered as a sequence of non-white characters (@code{vip-end-of-Word}).
+@end table
+@noindent
+@cindex syntax table
+Here the meaning of the word `word' for the @kbd{w}, @kbd{b} and @kbd{e}
+commands is determined by the @dfn{syntax table} effective in the current
+buffer. Each major mode has its syntax mode, and therefore the meaning of
+a word also changes as the major mode changes. See GNU Emacs Manual for
+details of syntax table.
+
+@table @kbd
+@item H
+@kindex 110 @kbd{H} (@code{vip-window-top})
+Move point to the beginning of the @i{home} (top) line of the window.
+Given a count @var{n}, go to the @var{n}-th line from top
+(@code{vip-window-top}).
+@item M
+@kindex 115 @kbd{M} (@code{vip-window-middle})
+Move point to the beginning of the @i{middle} line of the window. Given
+a count @var{n}, go to the @var{n}-th line from the middle line
+(@code{vip-window-middle}).
+@item L
+@kindex 114 @kbd{L} (@code{vip-window-bottom})
+Move point to the beginning of the @i{lowest} (bottom) line of the
+window. Given count, go to the @var{n}-th line from bottom
+(@code{vip-window-bottom}).
+@end table
+@noindent
+These commands can be used to go to the desired line visible on the screen.
+
+@table @kbd
+@item (
+@kindex 050 @kbd{(} (@code{vip-backward-sentence})
+Move point backward to the beginning of the sentence
+(@code{vip-backward-sentence}).
+@item )
+@kindex 051 @kbd{)} (@code{vip-forward-sentence})
+Move point forward to the end of the sentence
+(@code{vip-forward-sentence}).
+@item @{
+@kindex 173 @kbd{@{} (@code{vip-backward-paragraph})
+Move point backward to the beginning of the paragraph
+(@code{vip-backward-paragraph}).
+@item @}
+@kindex 175 @kbd{@}} (@code{vip-forward-paragraph})
+Move point forward to the end of the paragraph
+(@code{vip-forward-paragraph}).
+@end table
+@noindent
+A count repeats the effect for these commands.
+
+@table @kbd
+@item G
+@kindex 107 @kbd{G} (@code{vip-goto-line})
+Given a count @var{n}, move point to the @var{n}-th line in the buffer on
+the first non-white character. Without a count, go to the end of the buffer
+(@code{vip-goto-line}).
+@item ` `
+@kindex 140 @kbd{`} (@code{vip-goto-mark})
+Exchange point and mark (@code{vip-goto-mark}).
+@item ` @var{ch}
+Move point to the position stored in the register @var{ch}. @var{ch} must
+be a lower case letter.
+@item ' '
+@kindex 047 @kbd{'} (@code{vip-goto-mark-and-skip-white})
+Exchange point and mark, and then move point to the first non-white
+character on the line (@code{vip-goto-mark-and-skip-white}).
+@item ' @var{ch}
+Move point to the position stored in the register @var{ch} and skip to the
+first non-white character on the line. @var{ch} must be a lower case letter.
+@item %
+@kindex 045 @kbd{%} (@code{vip-paren-match})
+Move point to the matching parenthesis if point is looking at @kbd{(},
+@kbd{)}, @kbd{@{}, @kbd{@}}, @kbd{[} or @kbd{]}
+@*(@code{vip-paren-match}).
+@end table
+@noindent
+The command @kbd{G} mark point before move, so that you can return to the
+original point by @kbd{` `}. The original point will also be stored in
+the mark ring.
+
+The following commands are useful for moving points on the line. A count
+will repeat the effect.
+
+@table @kbd
+@item f @var{ch}
+@kindex 146 @kbd{f} (@code{vip-find-char-forward})
+Move point forward to the character @var{ch} on the line. Signal error if
+@var{ch} could not be found (@code{vip-find-char-forward}).
+@item F @var{ch}
+@kindex 106 @kbd{F} (@code{vip-find-char-backward})
+Move point backward to the character @var{ch} on the line. Signal error if
+@var{ch} could not be found (@code{vip-find-char-backward}).
+@item t @var{ch}
+@kindex 164 @kbd{t} (@code{vip-goto-char-forward})
+Move point forward upto the character @var{ch} on the line. Signal error if
+@var{ch} could not be found (@code{vip-goto-char-forward}).
+@item T @var{ch}
+@kindex 124 @kbd{T} (@code{vip-goto-char-backward})
+Move point backward upto the character @var{ch} on the line. Signal error if
+@var{ch} could not be found (@code{vip-goto-char-backward}).
+@item ;
+@kindex 073 @kbd{;} (@code{vip-repeat-find})
+Repeat previous @kbd{f}, @kbd{t}, @kbd{F} or @kbd{T} command
+(@code{vip-repeat-find}).
+@item ,
+@kindex 054 @kbd{,} (@code{vip-repeat-find-opposite})
+Repeat previous @kbd{f}, @kbd{t}, @kbd{F} or @kbd{T} command, in the
+opposite direction (@code{vip-repeat-find-opposite}).
+@end table
+
+@node Searching and Replacing, Modifying Commands, Motion Commands, Vi Commands
+@section Searching and Replacing
+
+Following commands are available for searching and replacing.
+
+@cindex regular expression (search)
+
+@table @kbd
+@item / @var{string} @key{RET}
+@kindex 057 @kbd{/} (@code{vip-search-forward})
+Search the first occurrence of the string @var{string} forward starting
+from point. Given a count @var{n}, the @var{n}-th occurrence of
+@var{string} will be searched. If the variable @code{vip-re-search} has value
+@code{t} then @dfn{regular expression} search is done and the string
+matching the regular expression @var{string} is found. If you give an
+empty string as @var{string} then the search mode will change from vanilla
+search to regular expression search and vice versa
+(@code{vip-search-forward}).
+@item ? @var{string} @key{RET}
+@kindex 077 @kbd{?} (@code{vip-search-backward})
+Same as @kbd{/}, except that search is done backward
+(@code{vip-search-backward}).
+@item n
+@kindex 156 @kbd{n} (@code{vip-search-next})
+Search the previous search pattern in the same direction as before
+(@code{vip-search-next}).
+@item N
+@kindex 116 @kbd{N} (@code{vip-search-Next})
+Search the previous search pattern in the opposite direction
+(@code{vip-search-Next}).
+@item C-s
+@kindex 023 @kbd{C-s} (@code{isearch-forward})
+Search forward incrementally. See GNU Emacs Manual for details
+(@code{isearch-forward}).
+@item C-r
+@kindex 022 @kbd{C-r} (@code{isearch-backward})
+Search backward incrementally (@code{isearch-backward}).
+@cindex vanilla (replacement)
+@cindex regular expression (replacement)
+@item R @var{string} RET @var{newstring}
+@kindex 122 @kbd{R} (@code{vip-replace-string})
+There are two modes of replacement, @dfn{vanilla} and @dfn{regular expression}.
+If the mode is @i{vanilla} you will get a prompt @samp{Replace string:},
+and if the mode is @i{regular expression} you will ge a prompt
+@samp{Replace regexp:}. The mode is initially @i{vanilla}, but you can
+toggle these modes by giving a null string as @var{string}. If the mode is
+vanilla, this command replaces every occurrence of @var{string} with
+@var{newstring}. If the mode is regular expression, @var{string} is
+treated as a regular expression and every string matching the regular
+expression is replaced with @var{newstring} (@code{vip-replace-string}).
+@item Q @var{string} RET @var{newstring}
+@kindex 121 @kbd{Q} (@code{vip-query-replace})
+Same as @kbd{R} except that you will be asked form confirmation before each
+replacement
+@*(@code{vip-query-replace}).
+@item r @var{ch}
+@kindex 162 @kbd{r} (@code{vip-replace-char})
+Replace the character point is looking at by the character @var{ch}. Give
+count, replace that many characters by @var{ch} (@code{vip-replace-char}).
+@end table
+@noindent
+The commands @kbd{/} and @kbd{?} mark point before move, so that you can
+return to the original point by @w{@kbd{` `}}.
+
+@node Modifying Commands, Delete Commands, Searching and Replacing, Vi Commands
+@section Modifying Commands
+
+In this section, commands for modifying the content of a buffer are
+described. These commands affect the region determined by a motion command
+which is given to the commands as their argument.
+
+@cindex point commands
+@cindex line commands
+
+We classify motion commands into @dfn{point commands} and
+@dfn{line commands}. The point commands are as follows:
+@example
+@kbd{h}, @kbd{l}, @kbd{0}, @kbd{^}, @kbd{$}, @kbd{w}, @kbd{W}, @kbd{b}, @kbd{B}, @kbd{e}, @kbd{E}, @kbd{(}, @kbd{)}, @kbd{/}, @kbd{?}, @kbd{`}, @kbd{f}, @kbd{F}, @kbd{t}, @kbd{T}, @kbd{%}, @kbd{;}, @kbd{,}
+@end example
+@noindent
+The line commands are as follows:
+@example
+@kbd{j}, @kbd{k}, @kbd{+}, @kbd{-}, @kbd{H}, @kbd{M}, @kbd{L}, @kbd{@{}, @kbd{@}}, @kbd{G}, @kbd{'}
+@end example
+@noindent
+@cindex expanding (region)
+If a point command is given as an argument to a modifying command, the
+region determined by the point command will be affected by the modifying
+command. On the other hand, if a line command is given as an argument to a
+modifying command, the region determined by the line command will be
+enlarged so that it will become the smallest region properly containing the
+region and consisting of whole lines (we call this process @dfn{expanding
+the region}), and then the enlarged region will be affected by the modifying
+command.
+
+@menu
+* Delete Commands:: Commands for deleting text.
+* Yank Commands:: Commands for yanking text in Vi's sense.
+* Put Back Commands:: Commands for putting bake deleted/yanked text.
+* Change Commands:: Commands for changing text.
+@end menu
+@node Delete Commands, Yank Commands, Modifying Commands, Modifying Commands
+@subsection Delete Commands
+
+@table @kbd
+@item d @var{motion-command}
+@kindex 1440 @kbd{d} (@code{vip-command-argument})
+Delete the region determined by the motion command @var{motion-command}.
+@end table
+@noindent
+For example, @kbd{d $} will delete the region between point and end of
+current line since @kbd{$} is a point command that moves point to end of line.
+@kbd{d G} will delete the region between the beginning of current line and
+end of the buffer, since @kbd{G} is a line command. A count given to the
+command above will become the count for the associated motion command.
+Thus, @kbd{3 d w} will delete three words.
+
+@kindex 042 @kbd{"} (@code{vip-command-argument})
+It is also possible to save the deleted text into a register you specify.
+For example, you can say @kbd{" t 3 d w} to delete three words and save it
+to register @kbd{t}. The name of a register is a lower case letter between
+@kbd{a} and @kbd{z}. If you give an upper case letter as an argument to
+a delete command, then the deleted text will be appended to the content of
+the register having the corresponding lower case letter as its name. So,
+@kbd{" T d w} will delete a word and append it to register @kbd{t}. Other
+modifying commands also accept a register name as their argument, and we
+will not repeat similar explanations.
+
+We have more delete commands as below.
+
+@table @kbd
+@item d d
+@kindex 1442 @kbd{d d}
+Delete a line. Given a count @var{n}, delete @var{n} lines.
+@item d r
+@kindex 1442 @kbd{d r}
+Delete current region.
+@item d R
+@kindex 1441 @kbd{d R}
+Expand current region and delete it.
+@item D
+@kindex 104 @kbd{D} (@code{vip-kill-line})
+Delete to the end of a line (@code{vip-kill-line}).
+@item x
+@kindex 170 @kbd{x} (@code{vip-delete-char})
+Delete a character after point. Given @var{n}, delete @var{n} characters
+(@code{vip-delete-char}).
+@item @key{DEL}
+@kindex 177 @kbd{DEL} (@code{vip-delete-backward-char})
+Delete a character before point. Given @var{n}, delete @var{n} characters
+(@code{vip-delete-backward-char}).
+@end table
+
+@node Yank Commands, Put Back Commands, Delete Commands, Modifying Commands
+@subsection Yank Commands
+
+@cindex yank
+
+Yank commands @dfn{yank} a text of buffer into a (usually anonymous) register.
+Here the word `yank' is used in Vi's sense. Thus yank commands do not
+alter the content of the buffer, and useful only in combination with
+commands that put back the yanked text into the buffer.
+
+@table @kbd
+@item y @var{motion-command}
+@kindex 1710 @kbd{y} (@code{vip-command-argument})
+Yank the region determined by the motion command @var{motion-command}.
+@end table
+@noindent
+For example, @kbd{y $} will yank the text between point and the end of line
+into an anonymous register, while @kbd{"c y $} will yank the same text into
+register @kbd{c}.
+
+Use the following command to yank consecutive lines of text.
+
+@table @kbd
+@item y y
+@itemx Y
+@kindex 131 @kbd{Y} (@code{vip-yank-line})
+@kindex 1712 @kbd{y y} (@code{vip-yank-line})
+Yank a line. Given @var{n}, yank @var{n} lines (@code{vip-yank-line}).
+@item y r
+@kindex 1712 @kbd{y r}
+Yank current region.
+@item y R
+@kindex 1711 @kbd{y R}
+Expand current region and yank it.
+@end table
+
+@node Put Back Commands, Change Commands, Yank Commands, Modifying Commands
+@subsection Put Back Commands
+Deleted or yanked texts can be put back into the buffer by the command
+below.
+
+@table @kbd
+@item p
+@kindex 160 @kbd{p} (@code{vip-put-back})
+Insert, after the character point is looking at, most recently
+deleted/yanked text from anonymous register. Given a register name
+argument, the content of the named register will be put back. Given a
+count, the command will be repeated that many times. This command also
+checks if the text to put back ends with a new line character, and if so
+the text will be put below the current line (@code{vip-put-back}).
+@item P
+@kindex 120 @kbd{P} (@code{vip-Put-back})
+Insert at point most recently deleted/yanked text from anonymous register.
+Given a register name argument, the content of the named register will
+be put back. Given a count, the command will be repeated that many times.
+This command also checks if the text to put back ends with a new line
+character, and if so the text will be put above the current line rather
+than at point (@code{vip-Put-back}).
+@end table
+@noindent
+@cindex number register
+Thus, @kbd{" c p} will put back the content of the register @kbd{c} into the
+buffer. It is also possible to specify @dfn{number register} which is a
+numeral between @kbd{1} and @kbd{9}. If the number register @var{n} is
+specified, @var{n}-th previously deleted/yanked text will be put back. It
+is an error to specify a number register for the delete/yank commands.
+
+@node Change Commands, Repeating and Undoing Modifications, Put Back Commands, Modifying Commands
+@subsection Change Commands
+
+Most commonly used change command takes the following form.
+
+@table @kbd
+@item c @var{motion-command}
+@kindex 1430 @kbd{c} (@code{vip-command-argument})
+Replace the content of the region determined by the motion command
+@var{motion-command} by the text you type. If the motion command is a
+point command then you will type the text into minibuffer, and if the
+motion command is a line command then the region will be deleted first and
+you can insert the text in @var{insert mode}.
+@end table
+@noindent
+For example, if point is at the beginning of a word @samp{foo} and you
+wish to change it to @samp{bar}, you can type @kbd{c w}. Then, as @kbd{w}
+is a point command, you will get the prompt @samp{foo =>} in the
+minibuffer, for which you can type @kbd{b a r @key{RET}} to complete the change
+command.@refill
+
+@table @kbd
+@item c c
+@kindex 1432 @kbd{c c}
+Change a line. Given a count, that many lines are changed.
+@item c r
+@kindex 1432 @kbd{c r}
+Change current region.
+@item c R
+@kindex 1431 @kbd{c R}
+Expand current region and change it.
+@end table
+
+@node Repeating and Undoing Modifications, Other Vi Commands, Change Commands, Modifying Commands
+@subsection Repeating and Undoing Modifications
+
+VIP records the previous modifying command, so that it is easy to repeat
+it. It is also very easy to undo changes made by modifying commands.
+
+@table @kbd
+@item u
+@kindex 165 @kbd{u} (@code{vip-undo})
+Undo the last change. You can undo more by repeating undo by the repeat
+command @samp{.}. For example, you can undo 5 previous changes by typing
+@samp{u....}. If you type @samp{uu}, then the second @samp{u} undoes the
+first undo command (@code{vip-undo}).
+@item .
+@kindex 056 @kbd{.} (@code{vip-repeat})
+Repeat the last modifying command. Given count @var{n} it becomes the new
+count for the repeated command. Otherwise, the count for the last
+modifying command is used again (@code{vip-repeat}).
+@end table
+
+@node Other Vi Commands, Commands in Insert Mode, Repeating and Undoing Modifications, Vi Commands
+@section Other Vi Commands
+
+Miscellaneous Vi commands are collected here.
+
+@table @kbd
+@item Z Z
+@kindex 132 @kbd{Z Z} (@code{save-buffers-kill-emacs})
+Exit Emacs. If modified buffers exist, you will be asked whether you wish
+to save them or not (@code{save-buffers-kill-emacs}).
+@item !@: @var{motion-command} @var{format-command}
+@itemx @var{n} !@: !@: @var{format-command}
+@kindex 041 @kbd{!} (@code{vip-command-argument})
+The region determined by the motion command @var{motion-command} will be
+given to the shell command @var{format-command} and the region will be
+replaced by its output. If a count is given, it will be passed to
+@var{motion-command}. For example, @samp{3!Gsort} will sort the region
+between point and the 3rd line. If @kbd{!} is used instead of
+@var{motion-command} then @var{n} lines will be processed by
+@var{format-command} (@code{vip-command-argument}).
+@item J
+@kindex 112 @kbd{J} (@code{vip-join-lines})
+Join two lines. Given count, join that many lines. A space will be
+inserted at each junction (@code{vip-join-lines}).
+@item < @var{motion-command}
+@itemx @var{n} < <
+@kindex 074 @kbd{<} (@code{vip-command-argument})
+Shift region determined by the motion command @var{motion-command} to
+left by @var{shift-width} (default is 8). If @kbd{<} is used instead of
+@var{motion-command} then shift @var{n} lines
+@*(@code{vip-command-argument}).
+@item > @var{motion-command}
+@itemx @var{n} > >
+@kindex 076 @kbd{>} (@code{vip-command-argument})
+Shift region determined by the motion command @var{motion-command} to
+right by @var{shift-width} (default is 8). If @kbd{<} is used instead of
+@var{motion-command} then shift @var{n} lines
+@*(@code{vip-command-argument}).
+@item = @var{motion-command}
+@kindex 075 @kbd{=} (@code{vip-command-argument})
+Indent region determined by the motion command @var{motion-command}. If
+@kbd{=} is used instead of @var{motion-command} then indent @var{n} lines
+(@code{vip-command-argument}).
+@item *
+@kindex 052 @kbd{*} (@code{vip-call-last-kbd-macro})
+Call last remembered keyboard macro.
+@item #
+A new vi operator. @xref{New Commands}, for more details.
+@end table
+
+The following keys are reserved for future extensions, and currently
+assigned to a function that just beeps (@code{vip-nil}).
+
+@kindex 046 @kbd{&} (@code{vip-nil})
+@kindex 100 @kbd{@@} (@code{vip-nil})
+@kindex 125 @kbd{U} (@code{vip-nil})
+@kindex 133 @kbd{[} (@code{vip-nil})
+@kindex 135 @kbd{]} (@code{vip-nil})
+@kindex 137 @kbd{_} (@code{vip-nil})
+@kindex 161 @kbd{q} (@code{vip-nil})
+@kindex 176 @kbd{~} (@code{vip-nil})
+
+@example
+&, @@, U, [, ], _, q, ~
+@end example
+
+VIP uses a special local keymap to interpret key strokes you enter in vi
+mode. The following keys are bound to @var{nil} in the keymap. Therefore,
+these keys are interpreted by the global keymap of Emacs. We give below a
+short description of the functions bound to these keys in the global
+keymap. See GNU Emacs Manual for details.
+
+@table @kbd
+@item C-@@
+@kindex 000 @kbd{C-@@} (@code{set-mark-command})
+Set mark and push previous mark on mark ring (@code{set-mark-command}).
+@item TAB
+@kindex 011 @kbd{TAB} (@code{indent-for-tab-command})
+Indent line for current major mode (@code{indent-for-tab-command}).
+@item LFD
+@kindex 012 @kbd{LFD} (@code{newline-and-indent})
+Insert a newline, then indent according to mode (@code{newline-and-indent}).
+@item C-k
+@kindex 013 @kbd{C-k} (@code{kill-line})
+Kill the rest of the current line; before a newline, kill the newline.
+With prefix argument, kill that many lines from point. Negative arguments
+kill lines backward (@code{kill-line}).
+@item C-l
+@kindex 014 @kbd{C-l} (@code{recenter})
+Clear the screen and reprint everything (@code{recenter}).
+@item @var{n} C-p
+@kindex 020 @kbd{C-p} (@code{previous-line})
+Move cursor vertically up @var{n} lines (@code{previous-line}).
+@item C-q
+@kindex 021 @kbd{C-q} (@code{quoted-insert})
+Read next input character and insert it. Useful for inserting control
+characters
+@*(@code{quoted-insert}).
+@item C-r
+@kindex 022 @kbd{C-r} (@code{isearch-backward})
+Search backward incrementally (@code{isearch-backward}).
+@item C-s
+@kindex 023 @kbd{C-s} (@code{isearch-forward})
+Search forward incrementally (@code{isearch-forward}).
+@item @var{n} C-t
+@kindex 024 @kbd{C-t} (@code{transpose-chars})
+Interchange charcters around point, moving forward one character. With
+count @var{n}, take character before point and drag it forward past @var{n}
+other characters. If no argument and at end of line, the previous two
+characters are exchanged (@code{transpose-chars}).
+@item @var{n} C-v
+@kindex 026 @kbd{C-v} (@code{scroll-up})
+Scroll text upward @var{n} lines. If @var{n} is not given, scroll near
+full screen (@code{scroll-up}).
+@item C-w
+@kindex 027 @kbd{C-w} (@code{kill-region})
+Kill between point and mark. The text is save in the kill ring. The
+command @kbd{P} or @kbd{p} can retrieve it from kill ring
+(@code{kill-region}).
+@end table
+
+@node Commands in Insert Mode, Ex Commands, Other Vi Commands, Vi Commands
+@section Insert Mode
+
+You can enter insert mode by one of the following commands. In addition to
+these, you will enter insert mode if you give a change command with a line
+command as the motion command. Insert commands are also modifying commands
+and you can repeat them by the repeat command @kbd{.} (@code{vip-repeat}).
+
+@table @kbd
+@item i
+@kindex 151 @kbd{i} (@code{vip-insert})
+Enter insert mode at point (@code{vip-insert}).
+@item I
+@kindex 111 @kbd{I} (@code{vip-Insert})
+Enter insert mode at the first non white character on the line
+(@code{vip-Insert}).
+@item a
+@kindex 141 @kbd{a} (@code{vip-append})
+Move point forward by one character and then enter insert mode
+(@code{vip-append}).
+@item A
+@kindex 101 @kbd{A} (@code{vip-Append})
+Enter insert mode at end of line (@code{vip-Append}).
+@item o
+@kindex 157 @kbd{o} (@code{vip-open-line})
+Open a new line below the current line and enter insert mode
+(@code{vip-open-line}).
+@item O
+@kindex 117 @kbd{O} (@code{vip-Open-line})
+Open a new line above the current line and enter insert mode
+(@code{vip-Open-line}).
+@item C-o
+@kindex 017 @kbd{C-o} (@code{vip-open-line-at-point})
+Insert a newline and leave point before it, and then enter insert mode
+@*(@code{vip-open-line-at-point}).
+@end table
+
+Insert mode is almost like emacs mode. Only the following 4 keys behave
+differently from emacs mode.
+
+@table @kbd
+@item @key{ESC}
+@kindex 033 @kbd{ESC} (@code{vip-change-mode-to-vi}) (insert mode)
+This key will take you back to vi mode (@code{vip-change-mode-to-vi}).
+@item C-h
+@kindex 010 @kbd{C-h} (@code{delete-backward-char}) (insert mode)
+Delete previous character (@code{delete-backward-char}).
+@item C-w
+@kindex 027 @kbd{C-w} (@code{vip-delete-backward-word}) (insert mode)
+Delete previous word (@code{vip-delete-backward-word}).
+@item C-z
+@kindex 032 @kbd{C-z} (@code{vip-ESC}) (insert mode)
+This key simulates @key{ESC} key in emacs mode. For instance, typing
+@kbd{C-z x} in insert mode iw the same as typing @kbd{ESC x} in emacs mode
+(@code{vip-ESC}).
+@end table
+@noindent
+You can also bind @kbd{C-h} to @code{help-command} if you like.
+(@xref{Customizing Key Bindings}, for details.) Binding @kbd{C-h} to
+@code{help-command} has the effect of making the meaning of @kbd{C-h}
+uniform among emacs, vi and insert modes.
+
+When you enter insert mode, VIP records point as the start point of
+insertion, and when you leave insert mode the region between point and
+start point is saved for later use by repeat command etc. Therefore, repeat
+command will not really repeat insertion if you move point by emacs
+commands while in insert mode.
+
+@node Ex Commands, Ex Command Reference, Commands in Insert Mode, Top
+@chapter Ex Commands
+
+@kindex 072 @kbd{:} (@code{vip-ex})
+
+In vi mode, you can execute an Ex command @var{ex-command} by typing:
+@example
+@kbd{:@: @var{ex-command} @key{RET}}
+@end example
+Every Ex command follows the following pattern:
+@example
+@var{address command} @kbd{!}@: @var{parameters count flags}
+@end example
+@noindent
+@cindex address
+where all parts are optional. For the syntax of @dfn{address}, the reader
+is referred to the reference manual of Ex.
+
+@cindex magic
+@cindex regular expression
+
+In the current version of VIP, searching by Ex commands is always
+@dfn{magic}. That is, search patterns are always treated as @dfn{regular
+expressions}. For example, a typical forward search would be invoked by
+@kbd{:/@var{pat}/}. If you wish to include @samp{/} as part of
+@var{pat} you must preceded it by @samp{\}. VIP strips off these @kbd{\}'s
+before @kbd{/} and the resulting @var{pat} becomes the actual search
+pattern. Emacs provides a different and richer class or regular
+expressions than Vi/Ex, and VIP uses Emacs' regular expressions. See GNU
+Emacs Manual for details of regular expressions.
+
+Several Ex commands can be entered in a line by separating them by a pipe
+character @samp{|}.
+
+@menu
+* Ex Command Reference:: Explain all the Ex commands available in VIP.
+@end menu
+@node Ex Command Reference, Customization, Ex Commands, Ex Commands
+@section Ex Command Reference
+In this section we briefly explain all the Ex commands supported by VIP.
+Most Ex commands expect @var{address} as their argument, and they use
+default addresses if they are not explicitly given. In the following, such
+default addresses will be shown in parentheses.
+
+Most command names can and preferably be given in abbreviated forms. In
+the following, optional parts of command names will be enclosed in
+brackets. For example, @samp{co[py]} will mean that copy command can be
+give as @samp{co} or @samp{cop} or @samp{copy}.
+
+If @var{command} is empty, point will move to the beginning of the line
+specified by the @var{address}. If @var{address} is also empty, point will
+move to the beginning of the current line.
+
+@cindex flag
+
+Some commands accept @dfn{flags} which are one of @kbd{p}, @kbd{l} and
+@kbd{#}. If @var{flags} are given, the text affected by the commands will
+be displayed on a temporary window, and you will be asked to hit return to
+continue. In this way, you can see the text affected by the commands
+before the commands will be executed. If you hit @kbd{C-g} instead of
+@key{RET} then the commands will be aborted. Note that the meaning of
+@var{flags} is different in VIP from that in Vi/Ex.
+
+@table @kbd
+@item (.,.@:) co[py] @var{addr} @var{flags}
+@itemx (.,.@:) t @var{addr} @var{flags}
+Place a copy of specified lines after @var{addr}. If @var{addr} is
+@kbd{0}, it will be placed before the first line.
+@item (.,.@:) d[elete] @var{register} @var{count} @var{flags}
+Delete specified lines. Text will be saved in a named @var{register} if a
+lower case letter is given, and appended to a register if a capital letter is
+given.
+@item e[dit] !@: +@var{addr} @var{file}
+@itemx e[x] !@: +@var{addr} @var{file}
+@itemx vi[sual] !@: +@var{addr} @var{file}
+Edit a new file @var{file} in the current window. The command will abort
+if current buffer is modified, which you can override by giving @kbd{!}.
+If @kbd{+}@var{addr} is given, @var{addr} becomes the current line.
+@item file
+Give information about the current file.
+@item (1,$) g[lobal] !@: /@var{pat}/ @var{cmds}
+@itemx (1,$) v /@var{pat}/ @var{cmds}
+Among specified lines first mark each line which matches the regular
+expression @var{pat}, and then execute @var{cmds} on each marked line.
+If @kbd{!}@: is given, @var{cmds} will be executed on each line not matching
+@var{pat}. @kbd{v} is same as @kbd{g!}.
+@item (.,.+1) j[oin] !@: @var{count} @var{flags}
+Join specified lines into a line. Without @kbd{!}, a space character will
+be inserted at each junction.
+@item (.@:) k @var{ch}
+@itemx (.@:) mar[k] @var{ch}
+Mark specified line by a lower case character @var{ch}. Then the
+addressing form @kbd{'}@var{ch} will refer to this line. No white space is
+required between @kbd{k} and @var{ch}. A white space is necessary between
+@kbd{mark} and @var{ch}, however.
+@item map @var{ch} @var{rhs}
+Define a macro for vi mode. After this command, the character @var{ch}
+will be expanded to @var{rhs} in vi mode.
+@item (.,.@:) m[ove] @var{addr}
+Move specified lines after @var{addr}.
+@item (.@:) pu[t] @var{register}
+Put back previously deleted or yanked text. If @var{register} is given,
+the text saved in the register will be put back; otherwise, last deleted or
+yanked text will be put back.
+@item q[uit] !
+Quit from Emacs. If modified buffers with associated files exist, you will
+be asked whether you wish to save each of them. At this point, you may
+choose not to quit, by hitting @kbd{C-g}. If @kbd{!}@: is given, exit from
+Emacs without saving modified buffers.
+@item (.@:) r[ead] @var{file}
+Read in the content of the file @var{file} after the specified line.
+@item (.@:) r[ead] !@: @var{command}
+Read in the output of the shell command @var{command} after the specified
+line.
+@item se[t]
+Set a variable's value. @xref{Customizing Constants}, for the list of variables
+you can set.
+@item sh[ell]
+Run a subshell in a window.
+@item (.,.@:) s[ubstitute] /@var{pat}/@var{repl}/ @var{options} @var{count} @var{flags}
+@itemx (.,.@:) & @var{options} @var{count} @var{flags}
+On each specified line, the first occurrence of string matching regular
+expression @var{pat} is replaced by replacement pattern @var{repl}. Option
+characters are @kbd{g} and @kbd{c}. If global option character @kbd{g}
+appears as part of @var{options}, all occurrences are substituted. If
+confirm option character @kbd{c} appears, you will be asked to give
+confirmation before each substitution. If @kbd{/@var{pat}/@var{repl}/} is
+missing, the last substitution is repeated.
+@item st[op]
+Suspend Emacs.
+@item ta[g] @var{tag}
+@cindex tag
+@cindex selected tag table
+Find first definition of @var{tag}. If no @var{tag} is given, previously
+given @var{tag} is used and next alternate definition is find. By default,
+the file @file{TAGS} in the current directory becomes the @dfn{selected tag
+table}. You can select another tag table by @kbd{set} command.
+@xref{Customizing Constants}, for details.
+@item und[o]
+Undo the last change.
+@item unm[ap] @var{ch}
+The macro expansion associated with @var{ch} is removed.
+@item ve[rsion]
+Tell the version number of VIP.
+@item (1,$) w[rite] !@: @var{file}
+Write out specified lines into file @var{file}. If no @var{file} is given,
+text will be written to the file associated to the current buffer. Unless
+@kbd{!}@: is given, if @var{file} is different from the file associated to
+the current buffer and if the file @var{file} exists, the command will not
+be executed. Unlike Ex, @var{file} becomes the file associated to the
+current buffer.
+@item (1,$) w[rite]>> @var{file}
+Write out specified lines at the end of file @var{file}. @var{file}
+becomes the file associated to the current buffer.
+@item (1,$) wq !@: @var{file}
+Same as @kbd{write} and then @kbd{quit}. If @kbd{!}@: is given, same as
+@kbd{write !}@: then @kbd{quit}.
+@item (.,.) y[ank] @var{register} @var{count}
+Save specified lines into register @var{register}. If no register is
+specified, text will be saved in an anonymous register.
+@item @var{addr} !@: @var{command}
+Execute shell command @var{command}. The output will be shown in a new
+window. If @var{addr} is given, specified lines will be used as standard
+input to @var{command}.
+@item ($) =
+Print the line number of the addressed line.
+@item (.,.) > @var{count} @var{flags}
+Shift specified lines to the right. The variable @code{vip-shift-width}
+(default value is 8) determines the amount of shift.
+@item (.,.) < @var{count} @var{flags}
+Shift specified lines to the left. The variable @code{vip-shift-width}
+(default value is 8) determines the amount of shift.
+@item (.,.@:) ~ @var{options} @var{count} @var{flags}
+Repeat the previous @kbd{substitute} command using previous search pattern
+as @var{pat} for matching.
+@end table
+
+The following Ex commands are available in Vi, but not implemented in VIP.
+@example
+@kbd{abbreviate}, @kbd{list}, @kbd{next}, @kbd{print}, @kbd{preserve}, @kbd{recover}, @kbd{rewind}, @kbd{source},
+@kbd{unabbreviate}, @kbd{xit}, @kbd{z}
+@end example
+
+@node Customization, Customizing Constants, Ex Command Reference, Top
+@chapter Customization
+
+If you have a file called @file{.vip} in your home directory, then it
+will also be loaded when VIP is loaded. This file is thus useful for
+customizing VIP.
+
+@menu
+* Customizing Constants:: How to change values of constants.
+* Customizing Key Bindings:: How to change key bindings.
+@end menu
+
+@node Customizing Constants, Customizing Key Bindings, Customization, Customization
+@section Customizing Constants
+An easy way to customize VIP is to change the values of constants used
+in VIP. Here is the list of the constants used in VIP and their default
+values.
+
+@table @code
+@item vip-shift-width 8
+The number of columns shifted by @kbd{>} and @kbd{<} command.
+@item vip-re-replace nil
+If @code{t} then do regexp replace, if @code{nil} then do string replace.
+@item vip-search-wrap-around t
+If @code{t}, search wraps around the buffer.
+@item vip-re-search nil
+If @code{t} then search is reg-exp search, if @code{nil} then vanilla
+search.
+@item vip-case-fold-search nil
+If @code{t} search ignores cases.
+@item vip-re-query-replace nil
+If @code{t} then do reg-exp replace in query replace.
+@item vip-open-with-indent nil
+If @code{t} then indent to the previous current line when open a new line
+by @kbd{o} or @kbd{O} command.
+@item vip-tags-file-name "TAGS"
+The name of the file used as the tag table.
+@item vip-help-in-insert-mode nil
+If @code{t} then @key{C-h} is bound to @code{help-command} in insert mode,
+if @code{nil} then it sis bound to @code{delete-backward-char}.
+@end table
+@noindent
+You can reset these constants in VIP by the Ex command @kbd{set}. Or you
+can include a line like this in your @file{.vip} file:
+@example
+(setq vip-case-fold-search t)
+@end example
+
+@node Customizing Key Bindings,, Customizing Constants, Customization
+@section Customizing Key Bindings
+
+@cindex local keymap
+
+VIP uses @code{vip-command-mode-map} as the @dfn{local keymap} for vi mode.
+For example, in vi mode, @key{SPC} is bound to the function
+@code{vip-scroll}. But, if you wish to make @key{SPC} and some other keys
+ behave like Vi, you can include the following lines in your @file{.vip}
+file.
+
+@example
+(define-key vip-command-mode-map "\C-g" 'vip-info-on-file)
+(define-key vip-command-mode-map "\C-h" 'vip-backward-char)
+(define-key vip-command-mode-map "\C-m" 'vip-next-line-at-bol)
+(define-key vip-command-mode-map " " 'vip-forward-char)
+(define-key vip-command-mode-map "g" 'vip-keyboard-quit)
+(define-key vip-command-mode-map "s" 'vip-substitute)
+(define-key vip-command-mode-map "C" 'vip-change-to-eol)
+(define-key vip-command-mode-map "R" 'vip-change-to-eol)
+(define-key vip-command-mode-map "S" 'vip-substitute-line)
+(define-key vip-command-mode-map "X" 'vip-delete-backward-char)
+@end example
+
+@unnumbered Key Index
+
+@printindex ky
+
+@unnumbered Concept Index
+@printindex cp
+
+@contents
+@bye
diff --git a/oldXMenu/Activate.c b/oldXMenu/Activate.c
new file mode 100644
index 00000000000..2a34b60315b
--- /dev/null
+++ b/oldXMenu/Activate.c
@@ -0,0 +1,531 @@
+/* $Header: Activate.c,v 1.16 88/02/02 19:08:46 jim Exp $ */
+/* Copyright Massachusetts Institute of Technology 1985 */
+
+#include "copyright.h"
+
+/*
+ * XMenu: MIT Project Athena, X Window system menu package
+ *
+ * XMenuActivate - Maps a given menu to the display and activates
+ * the menu for user selection. The user is allowed to
+ * specify which pane and selection will be current,
+ * the X and Y location of the menu (relative to the
+ * parent window) and the mouse button event mask that
+ * will be used to identify a selection request.
+ *
+ * A menu selection is shown to be current by placing
+ * a highlight box around the selection as the mouse
+ * cursor enters its active region. Inactive selections
+ * will not be highlited. As the mouse cursor moved
+ * from one menu pane to another menu pane the pane being
+ * entered is raised and made current and the pane being
+ * left is lowered.
+ *
+ * Anytime XMenuActivate returns, the p_num and
+ * s_num are left at their last known values (i.e.,
+ * the last known current pane and selection indices).
+ * The following are the defined return states:
+ *
+ * 1) If at any time an error occurs the data
+ * pointer is left untouched and XM_FAILURE
+ * is returned.
+ *
+ * 2) When a selection request is recieved (i.e.,
+ * when the specified mouse event occurs) the
+ * data pointer will be set to the data
+ * associated with the particular selection
+ * current at the time of the selection request
+ * and XM_SUCCESS is returned.
+ *
+ * 3) If no selection was current at the time a
+ * selection request is made the data pointer
+ * will be left untouched and XM_NO_SELECT will
+ * be returned.
+ *
+ * 4) If the selection that was current at the time
+ * a selection request is made is not an active
+ * selection the data pointer will be left
+ * untouched and XM_IA_SELECT will be returned.
+ *
+ * Since X processes events in an asynchronous manner
+ * it is likely that XMenuActivate will encounter
+ * a "foreign event" while it is executing. Foreign
+ * events are handled in one of three ways:
+ *
+ * 1) The event is discarded. This is the default
+ * mode and requires no action on the part of the
+ * application.
+ *
+ * 2) The application has identified an asynchronous
+ * event handler that will be called and the
+ * foreign event handed off to it. Note:
+ * AEQ mode disables this mode temporarily.
+ *
+ * 3) The application has enabled asynchronous event
+ * queueing mode. In this mode all foreign events
+ * will be queued up untill XMenuActivate
+ * terminates; at which time they will be
+ * returned to the X event queue. As long as
+ * AEQ mode is enabled any asynchronous event
+ * handler as temporarily disabled.
+ *
+ * Any events encountered while taking down the menu
+ * (i.e., exposure events from occluded windows) will
+ * automatically be returned to the X event queue after
+ * XMenuActivate has cleaned the queue of any of its own
+ * events that are no longer needed.
+ *
+ * Author: Tony Della Fera, DEC
+ * March 12, 1986
+ *
+ */
+
+#include "XMenuInt.h"
+
+int
+XMenuActivate(display, menu, p_num, s_num, x_pos, y_pos, event_mask, data)
+ register Display *display; /* Display to put menu on. */
+ register XMenu *menu; /* Menu to activate. */
+ int *p_num; /* Pane number selected. */
+ int *s_num; /* Selection number selected. */
+ int x_pos; /* X coordinate of menu position. */
+ int y_pos; /* Y coordinate of menu position. */
+ unsigned int event_mask; /* Mouse button event mask. */
+ char **data; /* Pointer to return data value. */
+{
+ int status; /* X routine call status. */
+ int orig_x; /* Upper left menu origin X coord. */
+ int orig_y; /* Upper left menu origin Y coord. */
+ int ret_val; /* Return value. */
+
+ register XMPane *p_ptr; /* Current XMPane. */
+ register XMPane *event_xmp; /* Event XMPane pointer. */
+ register XMPane *cur_p; /* Current pane. */
+ register XMSelect *cur_s; /* Current selection. */
+ XMWindow *event_xmw; /* Event XMWindow pointer. */
+ XEvent event; /* X input event. */
+ XEvent peek_event; /* X input peek ahead event. */
+
+ Bool selection = False; /* Selection has been made. */
+ Bool forward = True; /* Moving forward in the pane list. */
+
+ Window root, child;
+ int root_x, root_y, win_x, win_y;
+ unsigned int mask;
+
+ /*
+ * Define and allocate a foreign event queue to hold events
+ * that don't belong to XMenu. These events are later restored
+ * to the X event queue.
+ */
+ typedef struct _xmeventque {
+ XEvent event;
+ struct _xmeventque *next;
+ } XMEventQue;
+
+ XMEventQue *feq = NULL; /* Foreign event queue. */
+ XMEventQue *feq_tmp; /* Foreign event queue temporary. */
+
+ /*
+ * If there are no panes in the menu then return failure
+ * because the menu is not initialized.
+ */
+ if (menu->p_count == 0) {
+ _XMErrorCode = XME_NOT_INIT;
+ return(XM_FAILURE);
+ }
+
+ /*
+ * Find the desired current pane.
+ */
+ cur_p = _XMGetPanePtr(menu, *p_num);
+ if (cur_p == NULL) {
+ return(XM_FAILURE);
+ }
+ cur_p->activated = cur_p->active;
+
+ /*
+ * Find the desired current selection.
+ * If the current selection index is out of range a null current selection
+ * will be assumed and the cursor will be placed in the current pane
+ * header.
+ */
+ cur_s = _XMGetSelectionPtr(cur_p, *s_num);
+
+ /*
+ * Compute origin of menu so that cursor is in
+ * Correct pane and selection.
+ */
+ _XMTransToOrigin(display,
+ menu,
+ cur_p, cur_s,
+ x_pos, y_pos,
+ &orig_x, &orig_y);
+ menu->x_pos = orig_x; /* Store X and Y coords of menu. */
+ menu->y_pos = orig_y;
+
+ if (XMenuRecompute(display, menu) == XM_FAILURE) {
+ return(XM_FAILURE);
+ }
+
+ /*
+ * Flush the window creation queue.
+ * This batches all window creates since lazy evaluation
+ * is more efficient than individual evaluation.
+ * This routine also does an XFlush().
+ */
+ if (_XMWinQueFlush(display, menu, cur_p, cur_s) == _FAILURE) {
+ return(XM_FAILURE);
+ }
+
+ /*
+ * Make sure windows are in correct order (in case we were passed
+ * an already created menu in incorrect order.)
+ */
+ for(p_ptr = menu->p_list->next; p_ptr != cur_p; p_ptr = p_ptr->next)
+ XRaiseWindow(display, p_ptr->window);
+ for(p_ptr = menu->p_list->prev; p_ptr != cur_p->prev; p_ptr = p_ptr->prev)
+ XRaiseWindow(display, p_ptr->window);
+
+ /*
+ * Make sure all selection windows are mapped.
+ */
+ for (
+ p_ptr = menu->p_list->next;
+ p_ptr != menu->p_list;
+ p_ptr = p_ptr->next
+ ){
+ XMapSubwindows(display, p_ptr->window);
+ }
+
+ /*
+ * Synchronize the X buffers and the event queue.
+ * From here on, all events in the queue that don't belong to
+ * XMenu are sent back to the application via an application
+ * provided event handler or discarded if the application has
+ * not provided an event handler.
+ */
+ XSync(display, 0);
+
+ /*
+ * Grab the mouse for menu input.
+ */
+
+ status = XGrabPointer(
+ display,
+ menu->parent,
+ True,
+ event_mask,
+ GrabModeAsync,
+ GrabModeAsync,
+ None,
+ menu->mouse_cursor,
+ CurrentTime
+ );
+ if (status == _X_FAILURE) {
+ _XMErrorCode = XME_GRAB_MOUSE;
+ return(XM_FAILURE);
+ }
+
+ /*
+ * Map the menu panes.
+ */
+ XMapWindow(display, cur_p->window);
+ for (p_ptr = menu->p_list->next;
+ p_ptr != cur_p;
+ p_ptr = p_ptr->next)
+ XMapWindow(display, p_ptr->window);
+ for (p_ptr = cur_p->next;
+ p_ptr != menu->p_list;
+ p_ptr = p_ptr->next)
+ XMapWindow(display, p_ptr->window);
+
+ XRaiseWindow(display, cur_p->window); /* Make sure current */
+ /* pane is on top. */
+
+ cur_s = NULL; /* Clear current selection. */
+
+ /*
+ * Begin event processing loop.
+ */
+ while (1) {
+ XNextEvent(display, &event); /* Get next event. */
+ switch (event.type) { /* Dispatch on the event type. */
+ case Expose:
+ event_xmp = (XMPane *)XLookUpAssoc(display,
+ menu->assoc_tab,
+ event.xexpose.window);
+ if (event_xmp == NULL) {
+ /*
+ * If AEQ mode is enabled then queue the event.
+ */
+ if (menu->aeq) {
+ feq_tmp = (XMEventQue *)malloc(sizeof(XMEventQue));
+ if (feq_tmp == NULL) {
+ _XMErrorCode = XME_CALLOC;
+ return(XM_FAILURE);
+ }
+ feq_tmp->event = event;
+ feq_tmp->next = feq;
+ feq = feq_tmp;
+ }
+ else if (_XMEventHandler) (*_XMEventHandler)(&event);
+ break;
+ }
+ if (event_xmp->activated) {
+ XSetWindowBackground(display,
+ event_xmp->window,
+ menu->bkgnd_color);
+ }
+ else {
+ XSetWindowBackgroundPixmap(display,
+ event_xmp->window,
+ menu->inact_pixmap);
+ }
+ _XMRefreshPane(display, menu, event_xmp);
+ break;
+ case EnterNotify:
+ /*
+ * First wait a small period of time, and see
+ * if another EnterNotify event follows hard on the
+ * heels of this one. i.e., the user is simply
+ * "passing through". If so, ignore this one.
+ */
+
+ event_xmw = (XMWindow *)XLookUpAssoc(display,
+ menu->assoc_tab,
+ event.xcrossing.window);
+ if (event_xmw == NULL) break;
+ if (event_xmw->type == SELECTION) {
+ /*
+ * We have entered a selection.
+ */
+ /* if (XPending(display) == 0) usleep(150000); */
+ if (XPending(display) != 0) {
+ XPeekEvent(display, &peek_event);
+ if(peek_event.type == LeaveNotify) {
+ break;
+ }
+ }
+ cur_s = (XMSelect *)event_xmw;
+ /*
+ * If the pane we are in is active and the
+ * selection entered is active then activate
+ * the selection.
+ */
+ if (cur_p->active && cur_s->active) {
+ cur_s->activated = 1;
+ _XMRefreshSelection(display, menu, cur_s);
+ }
+ }
+ else {
+ /*
+ * We have entered a pane.
+ */
+ /* if (XPending(display) == 0) usleep(150000); */
+ if (XPending(display) != 0) {
+ XPeekEvent(display, &peek_event);
+ if (peek_event.type == EnterNotify) break;
+ }
+ XQueryPointer(display,
+ menu->parent,
+ &root, &child,
+ &root_x, &root_y,
+ &win_x, &win_y,
+ &mask);
+ event_xmp = (XMPane *)XLookUpAssoc(display,
+ menu->assoc_tab,
+ child);
+ if (event_xmp == NULL) break;
+ if (event_xmp == cur_p) break;
+ if (event_xmp->serial > cur_p->serial) forward = True;
+ else forward = False;
+ p_ptr = cur_p;
+ while (p_ptr != event_xmp) {
+ if (forward) p_ptr = p_ptr->next;
+ else p_ptr = p_ptr->prev;
+ XRaiseWindow(display, p_ptr->window);
+ }
+ if (cur_p->activated) {
+ cur_p->activated = False;
+ XSetWindowBackgroundPixmap(display,
+ cur_p->window,
+ menu->inact_pixmap);
+ _XMRefreshPane(display, menu, cur_p);
+ }
+ if (event_xmp->active) event_xmp->activated = True;
+ cur_p = event_xmp;
+ }
+ break;
+ case LeaveNotify:
+ event_xmw = (XMWindow *)XLookUpAssoc(
+ display,
+ menu->assoc_tab,
+ event.xcrossing.window
+ );
+ if (event_xmw == NULL) break;
+ if(cur_s == NULL) break;
+
+ /*
+ * If the current selection was activated then
+ * deactivate it.
+ */
+ if (cur_s->activated) {
+ cur_s->activated = False;
+ _XMRefreshSelection(display, menu, cur_s);
+ }
+ cur_s = NULL;
+ break;
+
+ case ButtonPress:
+ case ButtonRelease:
+ *p_num = cur_p->serial;
+ /*
+ * Check to see if there is a current selecion.
+ */
+ if (cur_s != NULL) {
+ /*
+ * Set the selection number to the current selection.
+ */
+ *s_num = cur_s->serial;
+ /*
+ * If the current selection was activated then
+ * we have a valid selection otherwise we have
+ * an inactive selection.
+ */
+ if (cur_s->activated) {
+ *data = cur_s->data;
+ ret_val = XM_SUCCESS;
+ }
+ else {
+ ret_val = XM_IA_SELECT;
+ }
+ }
+ else {
+ /*
+ * No selection was current.
+ */
+ ret_val = XM_NO_SELECT;
+ }
+ selection = True;
+ break;
+ default:
+ /*
+ * If AEQ mode is enabled then queue the event.
+ */
+ if (menu->aeq) {
+ feq_tmp = (XMEventQue *)malloc(sizeof(XMEventQue));
+ if (feq_tmp == NULL) {
+ _XMErrorCode = XME_CALLOC;
+ return(XM_FAILURE);
+ }
+ feq_tmp->event = event;
+ feq_tmp->next = feq;
+ feq = feq_tmp;
+ }
+ else if (_XMEventHandler) (*_XMEventHandler)(&event);
+ }
+ /*
+ * If a selection has been made, break out of the event loop.
+ */
+ if (selection == True) break;
+ }
+
+ /*
+ * Unmap the menu.
+ */
+ for ( p_ptr = menu->p_list->next;
+ p_ptr != menu->p_list;
+ p_ptr = p_ptr->next)
+ {
+ XUnmapWindow(display, p_ptr->window);
+ }
+
+ /*
+ * Ungrab the mouse.
+ */
+ XUngrabPointer(display, CurrentTime);
+
+ /*
+ * Restore bits under where the menu was if we managed
+ * to save them and free the pixmap.
+ */
+
+ /*
+ * If there is a current selection deactivate it.
+ */
+ if (cur_s != NULL) cur_s->activated = 0;
+
+ /*
+ * Deactivate the current pane.
+ */
+ cur_p->activated = 0;
+ XSetWindowBackgroundPixmap(display, cur_p->window, menu->inact_pixmap);
+
+ /*
+ * Synchronize the X buffers and the X event queue.
+ */
+ XSync(display, 0);
+
+ /*
+ * Dispatch any events remaining on the queue.
+ */
+ while (QLength(display)) {
+ /*
+ * Fetch the next event.
+ */
+ XNextEvent(display, &event);
+
+ /*
+ * Discard any events left on the queue that belong to XMenu.
+ * All others are held and then returned to the event queue.
+ */
+ switch (event.type) {
+ case Expose:
+ case EnterNotify:
+ case LeaveNotify:
+ case ButtonPress:
+ case ButtonRelease:
+ /*
+ * Does this event belong to one of XMenu's windows?
+ * If so, discard it and process the next event.
+ * If not fall through and treat it as a foreign event.
+ */
+ event_xmp = (XMPane *)XLookUpAssoc(
+ display,
+ menu->assoc_tab,
+ event.xbutton.window
+ );
+ if (event_xmp != NULL) continue;
+ default:
+ /*
+ * This is a foreign event.
+ * Queue it for later return to the X event queue.
+ */
+ feq_tmp = (XMEventQue *)malloc(sizeof(XMEventQue));
+ if (feq_tmp == NULL) {
+ _XMErrorCode = XME_CALLOC;
+ return(XM_FAILURE);
+ }
+ feq_tmp->event = event;
+ feq_tmp->next = feq;
+ feq = feq_tmp;
+ }
+ }
+ /*
+ * Return any foreign events that were queued to the X event queue.
+ */
+ while (feq != NULL) {
+ feq_tmp = feq;
+ XPutBackEvent(display, &feq_tmp->event);
+ feq = feq_tmp->next;
+ free((char *)feq_tmp);
+ }
+
+ /*
+ * Return successfully.
+ */
+ _XMErrorCode = XME_NO_ERROR;
+ return(ret_val);
+
+}
diff --git a/oldXMenu/AddPane.c b/oldXMenu/AddPane.c
new file mode 100644
index 00000000000..f17330151d4
--- /dev/null
+++ b/oldXMenu/AddPane.c
@@ -0,0 +1,103 @@
+#include "copyright.h"
+
+/* $Header: AddPane.c,v 1.3 87/12/20 12:03:52 rws Exp $ */
+/* Copyright Massachusetts Institute of Technology 1985 */
+
+/*
+ * XMenu: MIT Project Athena, X Window system menu package
+ *
+ * XMenuAddPane - Adds a pane to an XMenu object.
+ *
+ * Author: Tony Della Fera, DEC
+ * August, 1985
+ *
+ */
+
+#include "XMenuInt.h"
+
+int
+XMenuAddPane(display, menu, label, active)
+ Display *display;
+ register XMenu *menu; /* Menu object to be modified. */
+ register char *label; /* Selection label. */
+ int active; /* Make selection active? */
+{
+ register XMPane *pane; /* Newly created pane. */
+ register XMSelect *select; /* Initial selection for the new pane. */
+
+ int label_length; /* Label length in characters. */
+ int label_width; /* Label width in pixels. */
+
+ /*
+ * Check for NULL pointers!
+ */
+ if (label == NULL) {
+ _XMErrorCode = XME_ARG_BOUNDS;
+ return(XM_FAILURE);
+ }
+
+ /*
+ * Calloc the XMPane structure and the initial XMSelect.
+ */
+ pane = (XMPane *)calloc(1, sizeof(XMPane));
+ if (pane == NULL) {
+ _XMErrorCode = XME_CALLOC;
+ return(XM_FAILURE);
+ }
+ select = (XMSelect *)calloc(1, sizeof(XMSelect));
+ if (select == NULL) {
+ _XMErrorCode = XME_CALLOC;
+ return(XM_FAILURE);
+ }
+
+ /*
+ * Determine label size.
+ */
+ label_length = strlen(label);
+ label_width = XTextWidth(menu->p_fnt_info,
+ label,
+ label_length);
+
+ /*
+ * Set up the initial selection.
+ * Values not explicitly set are zeroed by calloc.
+ */
+ select->next = select;
+ select->prev = select;
+ select->type = SL_HEADER;
+ select->serial = -1;
+ select->parent_p = pane;
+
+ /*
+ * Fill the XMPane structure.
+ * X and Y position are set to 0 since a recompute will follow.
+ */
+ pane->type = PANE;
+ pane->active = active;
+ pane->serial = -1;
+ pane->label = label;
+ pane->label_width = label_width;
+ pane->label_length = label_length;
+ pane->s_list = select;
+
+ /*
+ * Insert the pane at the end of the pane list.
+ */
+ insque(pane, menu->p_list->prev);
+
+ /*
+ * Update the pane count.
+ */
+ menu->p_count++;
+
+ /*
+ * Schedule a recompute.
+ */
+ menu->recompute = 1;
+
+ /*
+ * Return the pane number just added.
+ */
+ _XMErrorCode = XME_NO_ERROR;
+ return((menu->p_count - 1));
+}
diff --git a/oldXMenu/AddSel.c b/oldXMenu/AddSel.c
new file mode 100644
index 00000000000..76294d40897
--- /dev/null
+++ b/oldXMenu/AddSel.c
@@ -0,0 +1,93 @@
+#include "copyright.h"
+
+/* $Header: AddSel.c,v 1.4 87/12/20 12:04:00 rws Exp $ */
+/* Copyright Massachusetts Institute of Technology 1985 */
+
+/*
+ * XMenu: MIT Project Athena, X Window system menu package
+ *
+ * XMenuAddSelection - Adds a selection to an XMenu object.
+ *
+ * Author: Tony Della Fera, DEC
+ * August, 1985
+ *
+ */
+
+#include "XMenuInt.h"
+
+int
+XMenuAddSelection(display, menu, p_num, data, label, active)
+ Display *display;
+ register XMenu *menu; /* Menu object to be modified. */
+ register int p_num; /* Pane number to be modified. */
+ char *data; /* Data value. */
+ char *label; /* Selection label. */
+ int active; /* Make selection active? */
+{
+ register XMPane *pane; /* Pane containing the new selection. */
+ register XMSelect *select; /* Newly created selection. */
+
+
+ int label_length; /* Label lenght in characters. */
+ int label_width; /* Label width in pixels. */
+
+ /*
+ * Check for NULL pointers!
+ */
+ if (label == NULL) {
+ _XMErrorCode = XME_ARG_BOUNDS;
+ return(XM_FAILURE);
+ }
+ /*
+ * Find the right pane.
+ */
+ pane = _XMGetPanePtr(menu, p_num);
+ if (pane == NULL) return(XM_FAILURE);
+
+ /*
+ * Calloc the XMSelect structure.
+ */
+ select = (XMSelect *)calloc(1, sizeof(XMSelect));
+ if (select == NULL) {
+ _XMErrorCode = XME_CALLOC;
+ return(XM_FAILURE);
+ }
+ /*
+ * Determine label size.
+ */
+ label_length = strlen(label);
+ label_width = XTextWidth(menu->s_fnt_info, label, label_length);
+
+ /*
+ * Fill the XMSelect structure.
+ */
+ select->type = SELECTION;
+ select->active = active;
+ select->serial = -1;
+ select->label = label;
+ select->label_width = label_width;
+ select->label_length = label_length;
+ select->data = data;
+ select->parent_p = pane;
+
+ /*
+ * Insert the selection at the end of the selection list.
+ */
+ insque(select, pane->s_list->prev);
+
+ /*
+ * Update the selection count.
+ */
+ pane->s_count++;
+
+ /*
+ * Schedule a recompute.
+ */
+ menu->recompute = 1;
+
+ /*
+ * Return the selection number just added.
+ */
+ _XMErrorCode = XME_NO_ERROR;
+ return((pane->s_count - 1));
+}
diff --git a/oldXMenu/ChangeLog b/oldXMenu/ChangeLog
new file mode 100644
index 00000000000..4e4ff4cfd2f
--- /dev/null
+++ b/oldXMenu/ChangeLog
@@ -0,0 +1,69 @@
+Sun Oct 18 17:46:43 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * XMakeAssoc.c (XMakeAssoc): Use malloc, not Xmalloc.
+ * XCrAssoc.c (XCreateAssocTable): Use malloc and calloc directly.
+ * XDelAssoc.c (XDeleteAssoc): Use free, not Xfree.
+ * XDestAssoc.c (XDestroyAssocTable): Likewise.
+
+Sat Oct 17 17:35:03 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * XDelAssoc.c, XLookAssoc.c, XCrAssoc.c, XDestAssoc.c, XMakeAssoc.c:
+ Use Xlib.h, not Xlibint.h.
+ * XLookAssoc.c, XMakeAssoc.c, XCrAssoc.c (NULL): Defined.
+ * XMakeAssoc.c, XCrAssoc.c: Include errno.h. Declare errno.
+ * XMakeAssoc.c (_XIOErrorFunction): Declared.
+
+Sat Sep 19 03:44:41 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * XDelAssoc.c, XLookAssoc.c, XCrAssoc.c, XDestAssoc.c, XMakeAssoc.c:
+ Specify dir X11/ when including Xlibint.h.
+
+Thu Sep 17 18:46:54 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * XDelAssoc.c, XLookAssoc.c, XCrAssoc.c, XDestAssoc.c, XMakeAssoc.c:
+ New files.
+
+ * Makefile (SRCS, OBJS): Compile those files.
+
+Fri Jan 31 23:45:10 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * Makefile (clean): Delete object files and library.
+ (distclean): New target.
+
+Wed Jan 29 14:38:32 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * Makefile (libXMenu11.a): Put `-' on ranlib line.
+
+Mon Jan 27 15:25:35 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * Makefile (EXTRA): New variable.
+ (libXMenu11.a): Use that.
+
+ * insque.c: New file.
+
+Sun Jan 26 00:43:25 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * Makefile (CC): Assignment commented out.
+
+Sat Nov 16 06:27:39 1991 Noah Friedman (friedman at nutrimat)
+
+ * copyright.h: New file (copied from X11R4 distribution)
+ * All files: Replaced occurrences of #include <X11/copyright.h>
+ with #include "copyright.h"
+
+Fri Oct 25 00:03:06 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * XMenu.h (enum _xmmode): Remove spurious comma.
+
+ * X10.h: New file.
+ * XMenu.h, XMenuInt.h: Include X10.h from this dir.
+
+Tue Nov 13 17:17:59 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * XMenu.h (struct _xmenu): Use unsigned long for colors.
+
+Mon Nov 12 18:55:06 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * Internal.c: Declare argument `display' in some functions.
+
+
diff --git a/oldXMenu/ChgPane.c b/oldXMenu/ChgPane.c
new file mode 100644
index 00000000000..bba8048b1ee
--- /dev/null
+++ b/oldXMenu/ChgPane.c
@@ -0,0 +1,66 @@
+#include "copyright.h"
+
+/* $Header: ChgPane.c,v 1.3 87/12/20 12:04:05 rws Exp $ */
+/* Copyright Massachusetts Institute of Technology 1985 */
+
+/*
+ * XMenu: MIT Project Athena, X Window system menu package
+ *
+ * XMenuChangePane - Change the label of a menu pane.
+ *
+ * Author: Tony Della Fera, DEC
+ * December 19, 1985
+ *
+ */
+
+#include "XMenuInt.h"
+
+int
+XMenuChangePane(menu, p_num, label)
+ register XMenu *menu; /* Menu object to be modified. */
+ register int p_num; /* Pane number to be modified. */
+ char *label; /* Selection label. */
+{
+ register XMPane *p_ptr; /* XMPane pointer. */
+
+ int label_length; /* Label lenght in characters. */
+ int label_width; /* Label width in pixels. */
+
+ /*
+ * Check for NULL pointers!
+ */
+ if (label == NULL) {
+ _XMErrorCode = XME_ARG_BOUNDS;
+ return(XM_FAILURE);
+ }
+
+ /*
+ * Find the right pane.
+ */
+ p_ptr = _XMGetPanePtr(menu, p_num);
+ if (p_ptr == NULL) return(XM_FAILURE);
+
+ /*
+ * Determine label size.
+ */
+ label_length = strlen(label);
+ label_width = XTextWidth(menu->p_fnt_info, label, label_length);
+
+ /*
+ * Change the pane data.
+ */
+ p_ptr->label = label;
+ p_ptr->label_width = label_width;
+ p_ptr->label_length = label_length;
+
+ /*
+ * Schedule a recompute.
+ */
+ menu->recompute = 1;
+
+ /*
+ * Return the pane number just changed.
+ */
+ _XMErrorCode = XME_NO_ERROR;
+ return(p_num);
+}
diff --git a/oldXMenu/ChgSel.c b/oldXMenu/ChgSel.c
new file mode 100644
index 00000000000..d51ad9d180a
--- /dev/null
+++ b/oldXMenu/ChgSel.c
@@ -0,0 +1,88 @@
+#include "copyright.h"
+
+/* $Header: ChgSel.c,v 1.4 88/02/02 19:08:57 jim Exp $ */
+/* Copyright Massachusetts Institute of Technology 1985 */
+
+/*
+ * XMenu: MIT Project Athena, X Window system menu package
+ *
+ * XMenuChangeSelection - Change a menu selection.
+ *
+ * Author: Tony Della Fera, DEC
+ * December 19, 1985
+ *
+ */
+
+#include "XMenuInt.h"
+
+int
+XMenuChangeSelection(display, menu, p_num, s_num, data, data_sw, label, label_sw)
+ Display *display; /* previously opened display. */
+ register XMenu *menu; /* Menu object to be modified. */
+ register int p_num; /* Pane number to be modified. */
+ register int s_num; /* Selection number to modified. */
+ char *data; /* Data value. */
+ int data_sw; /* Change to new data value? */
+ char *label; /* Selection label. */
+ int label_sw; /* Change to new label? */
+{
+ register XMPane *p_ptr; /* XMPane pointer. */
+ register XMSelect *s_ptr; /* XMSelect pointer. */
+
+ int label_length; /* Label lenght in characters. */
+ int label_width; /* Label width in pixels. */
+
+ /*
+ * Check for NULL pointers!
+ */
+ if (label == NULL) {
+ _XMErrorCode = XME_ARG_BOUNDS;
+ return(XM_FAILURE);
+ }
+
+ /*
+ * Find the right pane.
+ */
+ p_ptr = _XMGetPanePtr(menu, p_num);
+ if (p_ptr == NULL) return(XM_FAILURE);
+
+ /*
+ * Find the right selection.
+ */
+ s_ptr = _XMGetSelectionPtr(p_ptr, s_num);
+ if (s_ptr == NULL) return(XM_FAILURE);
+
+ /*
+ * Reset the label?
+ */
+ if (label_sw) {
+ /*
+ * Determine label size.
+ */
+ label_length = strlen(label);
+ label_width = XTextWidth(menu->s_fnt_info, label, label_length);
+
+ /*
+ * Change the selection data.
+ */
+ s_ptr->label = label;
+ s_ptr->label_width = label_width;
+ s_ptr->label_length = label_length;
+
+ /*
+ * Schedule a recompute.
+ */
+ menu->recompute = 1;
+ }
+
+ /*
+ * Reset the data?
+ */
+ if (data_sw) s_ptr->data = data;
+
+ /*
+ * Return successfully.
+ */
+ _XMErrorCode = XME_NO_ERROR;
+ return(s_num);
+}
diff --git a/oldXMenu/Create.c b/oldXMenu/Create.c
new file mode 100644
index 00000000000..02a186b6e15
--- /dev/null
+++ b/oldXMenu/Create.c
@@ -0,0 +1,746 @@
+/* $Header: Create.c,v 1.14 88/02/02 19:02:31 jim Exp $ */
+/* Copyright Massachusetts Institute of Technology 1985 */
+
+#include "copyright.h"
+
+/*
+ * XMenu: MIT Project Athena, X Window system menu package
+ *
+ * XMenuCreate - Creates an X window system menu object.
+ *
+ * Author: Tony Della Fera, DEC
+ * January 23, 1986
+ *
+ */
+
+#include "XMenuInt.h"
+
+
+#include <X11/bitmaps/dimple1>
+#include <X11/bitmaps/dimple3>
+#include <X11/bitmaps/gray1>
+#include <X11/bitmaps/gray3>
+#include <X11/bitmaps/cross_weave>
+
+#include <X11/bitmaps/left_ptr>
+#include <X11/bitmaps/left_ptrmsk>
+#include <X11/bitmaps/right_ptr>
+#include <X11/bitmaps/right_ptrmsk>
+#include <X11/bitmaps/cntr_ptr>
+#include <X11/bitmaps/cntr_ptrmsk>
+#include <X11/bitmaps/stipple>
+
+
+#define DEF_FREEZE 0
+#define DEF_REVERSE 0
+#define DEF_MENU_STYLE LEFT
+#define DEF_MENU_MODE BOX
+#define DEF_INACT_PNUM 3
+#define MAX_INACT_PNUM 4
+
+#define DEF_P_STYLE CENTER
+
+#define DEF_P_EVENTS (EnterWindowMask | ExposureMask)
+#define DEF_P_FNT_NAME "fixed"
+#define DEF_P_SPREAD 0.5
+#define DEF_P_BDR_WIDTH 2
+
+#define DEF_S_STYLE LEFT
+#define DEF_S_EVENTS (EnterWindowMask | LeaveWindowMask)
+#define DEF_S_FNT_NAME "fixed"
+#define DEF_S_SPREAD 0.10
+#define DEF_S_BDR_WIDTH 1
+
+#define XASSOC_TABLE_SIZE 64
+
+#define TILE_BUF_SIZE 5
+
+int atoi();
+double atof();
+
+XMenu *
+XMenuCreate(display, parent, def_env)
+ Display *display; /* ID of previously opened display */
+ Window parent; /* Window ID of the menu's parent window. */
+ register char *def_env; /* X Defaults program environment name. */
+{
+ register int i; /* Loop counter. */
+ register int j; /* Loop counter. */
+ register char *def_val; /* X Default value temp variable. */
+
+ register XMenu *menu; /* Pointer to the new menu. */
+ XMStyle menu_style; /* Menu display style. */
+ XMMode menu_mode; /* Menu display mode. */
+ XMPane *pane; /* Pane list header. */
+ XAssocTable *assoc_tab; /* XAssocTable pointer. */
+
+ int freeze; /* Freeze server mode. */
+ int reverse; /* Reverse video mode. */
+
+ XMStyle p_style; /* Pane display style. */
+ char *p_fnt_name; /* Flag font name. */
+ XFontStruct *p_fnt_info; /* Flag font structure */
+ int p_fnt_pad; /* Flag font padding in pixels. */
+ double p_spread; /* Pane spread in flag height fractions. */
+ int p_fnt_height; /* Pane character height. */
+ int p_bdr_width; /* Pane border width. */
+ int flag_height; /* Flag window height. */
+ int p_height; /* Pane window height. */
+ int p_x_off; /* Pane X offset. */
+ int p_y_off; /* Pane Y offset. */
+ GC pane_GC; /* Pane graphics context. */
+
+ XMStyle s_style; /* Selection display style. */
+ char *s_fnt_name; /* Selection font name. */
+ XFontStruct *s_fnt_info; /* Selection font structure. */
+ int s_fnt_pad; /* Selection font padding in pixels. */
+ int s_fnt_height; /* Selection font character height */
+ double s_spread; /* Select spread in line height fractions. */
+ int s_bdr_width; /* Highlight border width. */
+ int s_height; /* Selection window height. */
+ int s_x_off; /* Selection window X offset. */
+ int s_y_off; /* Selection window Y offset. */
+ GC normal_select_GC; /* GC used for normal video selection. */
+ GC inverse_select_GC; /* GC used for inverse video selection. */
+ GC inact_GC; /* GC for inactive pane header and */
+ /* selections. */
+ GC inact_GC_noexpose;
+
+ XColor color_def; /* Temp color definition holder. */
+ XColor screen_def; /* Temp screen color defintion holder */
+ XColor p_bdr_color; /* Color of border. */
+ XColor s_bdr_color; /* Color of highlight. */
+ XColor p_frg_color; /* Color of pane foreground color. */
+ XColor s_frg_color; /* Color of selection foreground. */
+ XColor bkgnd_color; /* Color of background.. */
+ XColor mouse_color; /* Color of mouse cursor. */
+ Cursor mouse_cursor; /* Mouse cursor. */
+ Pixmap inact_bitmap; /* Menu inactive pixmap. */
+
+ int inact_pnum; /* Inactive background pattern number. */
+
+ Pixel p_bdr_pixel; /* Pane border pixel. */
+ Pixel s_bdr_pixel; /* Selection border pixel. */
+ Pixel p_frg_pixel; /* Pane forground pixel. */
+ Pixel s_frg_pixel; /* Selection forground pixel. */
+ Pixel bkgnd_pixel; /* Menu background pixel. */
+
+ int *width, *height;
+ Pixmap *bitmap;
+ int *x_hot, *y_hot;
+ int status; /* Return code from XReadBitmapFile. */
+
+ Pixmap cursor; /* Cursor pixmap holder. */
+ Pixmap cursor_mask; /* Cursor mask pixmap holder. */
+ Pixmap stipple_pixmap; /* Stippple mask for half-tone text. */
+ unsigned long valuemask;
+ XGCValues *values;
+
+
+ /*
+ * Calloc the XMenu structure and the initial pane.
+ */
+ menu = (XMenu *)calloc(1, sizeof(XMenu));
+ if (menu == NULL) {
+ _XMErrorCode = XME_CALLOC;
+ return(NULL);
+ }
+ pane = (XMPane *)calloc(1, sizeof(XMPane));
+ if (pane == NULL) {
+ _XMErrorCode = XME_CALLOC;
+ return(NULL);
+ }
+
+ /*
+ * Create the XAssocTable
+ */
+ assoc_tab = (XAssocTable *)XCreateAssocTable(XASSOC_TABLE_SIZE);
+ if(assoc_tab == NULL) {
+ _XMErrorCode= XME_CREATE_ASSOC;
+ return(NULL);
+ }
+
+ /*
+ * Set up the default environment name.
+ */
+ if (def_env == NULL || *def_env == '\0') def_env = "XMenu";
+
+ /*
+ * Set up internal fail-safe defaults.
+ */
+ freeze = DEF_FREEZE;
+ reverse = DEF_REVERSE;
+ menu_style = DEF_MENU_STYLE;
+ menu_mode = DEF_MENU_MODE;
+ inact_pnum = DEF_INACT_PNUM;
+
+ p_style = DEF_P_STYLE;
+ p_spread = DEF_P_SPREAD;
+ p_fnt_name = DEF_P_FNT_NAME;
+ p_bdr_width = DEF_P_BDR_WIDTH;
+
+ s_style = DEF_S_STYLE;
+ s_spread = DEF_S_SPREAD;
+ s_fnt_name = DEF_S_FNT_NAME;
+ s_bdr_width = DEF_S_BDR_WIDTH;
+
+ /*
+ * Get default values from X.
+ */
+ def_val = XGetDefault(display, def_env, "MenuFreeze");
+ if (def_val != NULL) {
+ if (strcmp(def_val, "on") == 0) freeze = 1;
+ else if (strcmp(def_val, "off") == 0) freeze = 0;
+ }
+
+ def_val = XGetDefault(display, def_env, "MenuReverseVideo");
+ if (def_val != NULL) {
+ if (strcmp(def_val, "on") == 0) reverse = 1;
+ else if (strcmp(def_val, "off") == 0) reverse = 0;
+ }
+
+ def_val = XGetDefault(display, def_env, "MenuStyle");
+ if (def_val != NULL) {
+ if (strcmp(def_val, "right_hand") == 0) menu_style = RIGHT;
+ else if (strcmp(def_val, "left_hand") == 0) menu_style = LEFT;
+ else if (strcmp(def_val, "center") == 0) menu_style = CENTER;
+ }
+
+ def_val = XGetDefault(display, def_env, "MenuMode");
+ if (def_val != NULL) {
+ if (strcmp(def_val, "box") == 0) menu_mode = BOX;
+ else if (strcmp(def_val, "invert") == 0) menu_mode = INVERT;
+ }
+
+ def_val = XGetDefault(display, def_env, "MenuMouse");
+ if (
+ def_val != NULL &&
+ DisplayCells(display, DefaultScreen(display)) > 2 &&
+ XAllocNamedColor(display,
+ DefaultColormap(display, DefaultScreen(display)),
+ def_val,
+ &mouse_color, &color_def)
+ );
+ else if (reverse &&
+ XAllocNamedColor(display,
+ DefaultColormap(display, DefaultScreen(display)),
+ "white",
+ &mouse_color, &color_def)
+ );
+
+ else if (XAllocNamedColor(display,
+ DefaultColormap(display, DefaultScreen(display)),
+ "black",
+ &mouse_color, &color_def)
+ );
+
+ else ;
+
+ def_val = XGetDefault(display, def_env, "MenuBackground");
+ if (
+ def_val != NULL &&
+ DisplayCells(display, DefaultScreen(display)) > 2 &&
+ XAllocNamedColor(display,
+ DefaultColormap(display, DefaultScreen(display)),
+ def_val,
+ &bkgnd_color, &color_def)
+ );
+ else if (reverse &&
+ XAllocNamedColor(display,
+ DefaultColormap(display, DefaultScreen(display)),
+ "black",
+ &bkgnd_color, &color_def)
+ );
+ else if (XAllocNamedColor(display,
+ DefaultColormap(display, DefaultScreen(display)),
+ "white",
+ &bkgnd_color, &color_def)
+ );
+ else;
+
+ def_val = XGetDefault(display, def_env, "MenuInactivePattern");
+ if (def_val != NULL) {
+ if (strcmp(def_val, "dimple1") == 0) inact_pnum = 0;
+ else if (strcmp(def_val, "dimple3") == 0) inact_pnum = 1;
+ else if (strcmp(def_val, "gray1") == 0) inact_pnum = 2;
+ else if (strcmp(def_val, "gray3") == 0) inact_pnum = 3;
+ else if (strcmp(def_val, "cross_weave") == 0) inact_pnum = 4;
+ }
+
+ def_val = XGetDefault(display, def_env, "PaneStyle");
+ if (def_val != NULL) {
+ if (strcmp(def_val, "flush_left") == 0) p_style = LEFT;
+ else if (strcmp(def_val, "flush_right") == 0) p_style = RIGHT;
+ else if (strcmp(def_val, "center") == 0) p_style = CENTER;
+ }
+
+ def_val = XGetDefault(display, def_env, "PaneFont");
+ if (def_val != NULL) p_fnt_name = def_val;
+
+ def_val = XGetDefault(display, def_env, "PaneForeground");
+ if (
+ def_val != NULL &&
+ DisplayCells(display, DefaultScreen(display)) > 2
+ )
+ XAllocNamedColor(display, DefaultColormap(display,
+ DefaultScreen(display)),
+ def_val,
+ &p_frg_color, &color_def);
+
+ else if (reverse) XAllocNamedColor(display,
+ DefaultColormap(display,
+ DefaultScreen(display)),
+ "white",
+ &p_frg_color, &color_def);
+ else XAllocNamedColor(display,
+ DefaultColormap(display, DefaultScreen(display)),
+ "black",
+ &p_frg_color, &color_def);
+
+ def_val = XGetDefault(display, def_env, "PaneBorder");
+ if (
+ def_val != NULL &&
+ DisplayCells(display, DefaultScreen(display)) > 2 &&
+ XAllocNamedColor(display,
+ DefaultColormap(display, DefaultScreen(display)),
+ def_val,
+ &p_bdr_color, &color_def)
+ );
+ else if (reverse &&
+ XAllocNamedColor(display,
+ DefaultColormap(display, DefaultScreen(display)),
+ "white",
+ &p_bdr_color, &color_def)
+ );
+ else XAllocNamedColor(display,
+ DefaultColormap(display, DefaultScreen(display)),
+ "black",
+ &p_bdr_color, &color_def);
+
+ def_val = XGetDefault(display, def_env, "PaneBorderWidth");
+ if (def_val != NULL) p_bdr_width = atoi(def_val);
+
+ def_val = XGetDefault(display, def_env, "PaneSpread");
+ if (def_val != NULL) p_spread = atof(def_val);
+
+ def_val = XGetDefault(display, def_env, "SelectionStyle");
+ if (def_val != NULL) {
+ if (strcmp(def_val, "flush_left") == 0) s_style = LEFT;
+ else if (strcmp(def_val, "flush_right") == 0) s_style = RIGHT;
+ else if (strcmp(def_val, "center") == 0) s_style = CENTER;
+ }
+
+ def_val = XGetDefault(display, def_env, "SelectionFont");
+ if (def_val != NULL) s_fnt_name = def_val;
+
+ def_val = XGetDefault(display, def_env, "SelectionForeground");
+ if (
+ def_val != NULL &&
+ DisplayCells(display, DefaultScreen(display)) > 2 &&
+ XAllocNamedColor(display,
+ DefaultColormap(display, DefaultScreen(display)),
+ def_val,
+ &s_frg_color, &color_def)
+ );
+ else if (reverse &&
+ XAllocNamedColor(display,
+ DefaultColormap(display, DefaultScreen(display)),
+ "white",
+ &s_frg_color, &color_def)
+ ) ;
+ else if (XAllocNamedColor(display,
+ DefaultColormap(display, DefaultScreen(display)),
+ "black",
+ &s_frg_color, &color_def)
+ ) ;
+ else ;
+
+
+ def_val = XGetDefault(display, def_env, "SelectionBorder");
+ if (
+ def_val != NULL &&
+ DisplayCells(display, DefaultScreen(display)) > 2 &&
+ XAllocNamedColor(display,
+ DefaultColormap(display, DefaultScreen(display)),
+ def_val,
+ &s_bdr_color, &color_def)
+ ) ;
+ else if (reverse &&
+ XAllocNamedColor(display,
+ DefaultColormap(display, DefaultScreen(display)),
+ "white",
+ &s_bdr_color, &color_def)
+ ) ;
+ else if (XAllocNamedColor(display,
+ DefaultColormap(display, DefaultScreen(display)),
+ "black",
+ &s_bdr_color, &color_def)
+ ) ;
+ else ;
+
+ def_val = XGetDefault(display, def_env, "SelectionBorderWidth");
+ if (def_val != NULL) s_bdr_width = atoi(def_val);
+
+ def_val = XGetDefault(display, def_env, "SelectionSpread");
+ if (def_val != NULL) s_spread = atof(def_val);
+
+ /*
+ * Create and store the inactive pattern pixmap.
+ */
+ switch (inact_pnum)
+ {
+ case 0:
+ inact_bitmap = XCreateBitmapFromData(
+ display,
+ RootWindow(display, DefaultScreen(display)),
+ dimple1_bits,
+ 16, 16
+ );
+ break;
+ case 1:
+ inact_bitmap = XCreateBitmapFromData(
+ display,
+ RootWindow(display, DefaultScreen(display)),
+ dimple3_bits,
+ 16,16);
+ break;
+ case 2:
+ inact_bitmap = XCreateBitmapFromData(
+ display, RootWindow(display, DefaultScreen(display)),
+ gray1_bits, 16, 16);
+ break;
+ case 3:
+ inact_bitmap = XCreateBitmapFromData(
+ display,
+ RootWindow(display, DefaultScreen(display)),
+ gray3_bits, 16, 16);
+ break;
+ case 4:
+ inact_bitmap = XCreateBitmapFromData(
+ display,
+ RootWindow(display, DefaultScreen(display)),
+ cross_weave_bits, 16, 16);
+ break;
+ default:
+ break;
+
+ }
+ if (inact_bitmap == NULL) {
+ _XMErrorCode = XME_STORE_BITMAP;
+ return(NULL);
+ }
+
+ /*
+ * Load the mouse cursor.
+ */
+
+ switch (menu_style) {
+ case LEFT:
+ cursor = XCreateBitmapFromData(display,
+ RootWindow(display,
+ DefaultScreen(display)),
+ left_ptr_bits,
+ left_ptr_width,
+ left_ptr_height);
+ cursor_mask = XCreateBitmapFromData(display,
+ RootWindow(display,
+ DefaultScreen(display)),
+ left_ptrmsk_bits,
+ left_ptrmsk_width,
+ left_ptrmsk_height);
+ mouse_cursor = XCreatePixmapCursor(
+ display,
+ cursor, cursor_mask,
+ &mouse_color, &bkgnd_color,
+ left_ptr_x_hot,
+ left_ptr_y_hot
+ );
+ XFreePixmap(display, cursor);
+ XFreePixmap(display, cursor_mask);
+ break;
+ case RIGHT:
+ cursor = XCreateBitmapFromData(display,
+ RootWindow(display,
+ DefaultScreen(display)),
+ right_ptr_bits,
+ right_ptr_width,
+ right_ptr_height);
+ cursor_mask = XCreateBitmapFromData(display,
+ RootWindow(display,
+ DefaultScreen(display)),
+ right_ptrmsk_bits,
+ right_ptrmsk_width,
+ right_ptrmsk_height);
+ mouse_cursor = XCreatePixmapCursor(
+ display,
+ cursor, cursor_mask,
+ &mouse_color, &bkgnd_color,
+ right_ptr_x_hot,
+ right_ptr_y_hot
+ );
+ XFreePixmap(display, cursor);
+ XFreePixmap(display, cursor_mask);
+ break;
+ case CENTER:
+ cursor = XCreateBitmapFromData(display,
+ RootWindow(display,
+ DefaultScreen(display)),
+ cntr_ptr_bits,
+ cntr_ptr_width,
+ cntr_ptr_height);
+ cursor_mask = XCreateBitmapFromData(display,
+ RootWindow(display,
+ DefaultScreen(display)),
+ cntr_ptrmsk_bits,
+ cntr_ptrmsk_width,
+ cntr_ptrmsk_height);
+ mouse_cursor = XCreatePixmapCursor(
+ display,
+ cursor, cursor_mask,
+ &mouse_color, &bkgnd_color,
+ cntr_ptr_x_hot,
+ cntr_ptr_y_hot
+ );
+ XFreePixmap(display, cursor);
+ XFreePixmap(display, cursor_mask);
+ break;
+ default:
+ /* Error! Invalid style parameter. */
+ _XMErrorCode = XME_STYLE_PARAM;
+ return(NULL);
+ }
+ if (mouse_cursor == _X_FAILURE) {
+ _XMErrorCode = XME_CREATE_CURSOR;
+ return(NULL);
+ }
+
+ /*
+ * Open the pane and selection fonts.
+ */
+
+ p_fnt_info = XLoadQueryFont(display, p_fnt_name);
+ if (p_fnt_info == NULL) {
+ _XMErrorCode = XME_OPEN_FONT;
+ return(NULL);
+
+ }
+
+ s_fnt_info = XLoadQueryFont(display, s_fnt_name);
+ if (s_fnt_info == NULL) {
+ _XMErrorCode = XME_OPEN_FONT;
+ return(NULL);
+ }
+ /*
+ * Calculate the fixed padding value in pixels for each font.
+ */
+ p_fnt_height = p_fnt_info->max_bounds.ascent + p_fnt_info->max_bounds.descent;
+ s_fnt_height = s_fnt_info->max_bounds.ascent + s_fnt_info->max_bounds.descent;
+ p_fnt_pad = s_spread * p_fnt_height;
+ s_fnt_pad = s_spread * s_fnt_height;
+
+ /*
+ * Calculate fixed height and offset requirements.
+ */
+ flag_height = p_fnt_height + (p_fnt_pad << 1);
+
+ p_height = 0;
+ p_y_off = flag_height + p_bdr_width;
+ p_x_off = p_y_off * p_spread;
+
+ s_height = s_fnt_height + (s_fnt_pad << 1) + (s_bdr_width << 1);
+ s_y_off = s_height;
+ s_x_off = p_x_off;
+
+ /*
+ * Set up the pane list header.
+ */
+ pane->next = pane;
+ pane->prev = pane;
+ pane->type = PL_HEADER;
+ pane->serial = -1;
+
+ /*
+ * Initialize the internal pane and selection creation queues.
+ */
+ _XMWinQueInit();
+
+ /*
+ * Create pane, active, and inactive GC's.
+ */
+ values = (XGCValues *)malloc(sizeof(XGCValues));
+ valuemask = (GCForeground | GCBackground | GCFont | GCLineWidth);
+
+ /*
+ * First, pane.
+ */
+
+ values->foreground = p_frg_color.pixel;
+ values->background = bkgnd_color.pixel;
+ values->font = p_fnt_info->fid;
+ values->line_width = p_bdr_width;
+
+ pane_GC = XCreateGC(
+ display,
+ RootWindow(display, DefaultScreen(display)),
+ valuemask,
+ values);
+ /*
+ * Then normal video selection.
+ */
+
+ values->foreground = s_frg_color.pixel;
+ values->background = bkgnd_color.pixel;
+ values->font = s_fnt_info->fid;
+ values->line_width = s_bdr_width;
+ normal_select_GC = XCreateGC(display,
+ RootWindow(display, DefaultScreen(display)),
+ valuemask,
+ values);
+ /*
+ * Inverse video selection.
+ */
+
+ values->foreground = bkgnd_color.pixel;
+ values->background = s_frg_color.pixel;
+ values->font = s_fnt_info->fid;
+ values->line_width = s_bdr_width;
+ inverse_select_GC = XCreateGC(display,
+ RootWindow(display, DefaultScreen(display)),
+ valuemask,
+ values);
+ stipple_pixmap = XCreateBitmapFromData(display,
+ RootWindow(display,
+ DefaultScreen(display)),
+ stipple_bits,
+ stipple_width,
+ stipple_height);
+
+ /*
+ * Finally, inactive pane header and selections
+ */
+ valuemask |= (GCFillStyle | GCStipple);
+ values->foreground = s_frg_color.pixel;
+ values->background = bkgnd_color.pixel;
+ values->font = s_fnt_info->fid;
+ values->line_width = s_bdr_width;
+ values->fill_style = FillStippled;
+ values->stipple = stipple_pixmap;
+
+ inact_GC = XCreateGC(display,
+ RootWindow(display, DefaultScreen(display)),
+ valuemask,
+ values);
+
+ valuemask |= (GCGraphicsExposures);
+ values->graphics_exposures = False;
+ inact_GC_noexpose = XCreateGC (display,
+ RootWindow (display,
+ DefaultScreen (display)),
+ valuemask, values);
+
+
+ /*
+ * Construct the XMenu object.
+ */
+ /* -------------------- Menu data -------------------- */
+ menu->menu_style = menu_style;
+ menu->menu_mode = menu_mode;
+ menu->freeze = freeze;
+ menu->aeq = 0;
+ menu->recompute = 1;
+ menu->parent = parent;
+ menu->height = 0;
+ menu->width = 0;
+ menu->mouse_cursor = mouse_cursor;
+ menu->assoc_tab = assoc_tab;
+ menu->p_list = pane;
+ /* -------------------- Pane window data -------------------- */
+ menu->p_style = p_style;
+ menu->p_events = DEF_P_EVENTS;
+ menu->p_fnt_info = p_fnt_info;
+ menu->p_fnt_pad = p_fnt_pad;
+ menu->p_spread = p_spread;
+ menu->p_bdr_width = p_bdr_width;
+ menu->flag_height = flag_height;
+ menu->p_width = 0;
+ menu->p_height = p_height;
+ menu->p_x_off = p_x_off;
+ menu->p_y_off = p_y_off;
+ menu->p_count = 0;
+ menu->pane_GC = pane_GC;
+ menu->x_pos = 0;
+ menu->y_pos = 0;
+ /* -------------------- Selection window data -------------------- */
+ menu->s_style = s_style;
+ menu->s_events = DEF_S_EVENTS;
+ menu->s_fnt_info = s_fnt_info;
+ menu->s_fnt_pad = s_fnt_pad;
+ menu->s_spread = s_spread;
+ menu->s_bdr_width = s_bdr_width; /* unnecessary */
+ menu->s_width = 0;
+ menu->s_height = s_height;
+ menu->s_x_off = s_x_off;
+ menu->s_y_off = s_y_off;
+ menu->s_count = 0;
+ menu->normal_select_GC = normal_select_GC;
+ menu->inverse_select_GC = inverse_select_GC;
+ menu->inact_GC = inact_GC;
+ /* -------------------- Color data -------------------- */
+ menu->p_bdr_color = p_bdr_color.pixel;
+ menu->s_bdr_color = s_bdr_color.pixel;
+ menu->p_frg_color = p_frg_color.pixel;
+ menu->s_frg_color = s_frg_color.pixel;
+ menu->bkgnd_color = bkgnd_color.pixel;
+ /* -------------------- Pixmap data -------------------- */
+ menu->p_bdr_pixmap = NULL;
+ menu->s_bdr_pixmap = NULL;
+ menu->p_frg_pixmap = NULL;
+ menu->s_frg_pixmap = NULL;
+ menu->bkgnd_pixmap = NULL;
+ if (DisplayPlanes (display, DefaultScreen (display)) == 1)
+ menu->inact_pixmap = inact_bitmap;
+ else
+ {
+ int loop;
+
+ menu->inact_pixmap = XCreatePixmap (display,
+ parent,
+ 16,
+ 16,
+ DisplayPlanes (display,
+ DefaultScreen (display)));
+ if (menu->inact_pixmap == NULL)
+ {
+ _XMErrorCode = XME_STORE_BITMAP;
+ return(NULL);
+ }
+
+ XCopyPlane (display, inact_bitmap, menu->inact_pixmap,
+ inact_GC_noexpose, 0, 0, 16, 16, 0, 0, 1);
+
+/*
+ for (loop = 0;
+ loop < DisplayPlanes (display, DefaultScreen (display));
+ loop++)
+ {
+ XCopyPlane (display,
+ inact_bitmap,
+ menu->inact_pixmap,
+ inact_GC,
+ 0,
+ 0,
+ 16,
+ 16,
+ 0,
+ 0,
+ (1 << loop));
+ }
+*/
+ }
+
+ /*
+ * Return the completed XMenu.
+ */
+ _XMErrorCode = XME_NO_ERROR;
+ return(menu);
+}
diff --git a/oldXMenu/DelPane.c b/oldXMenu/DelPane.c
new file mode 100644
index 00000000000..65172556498
--- /dev/null
+++ b/oldXMenu/DelPane.c
@@ -0,0 +1,88 @@
+#include "copyright.h"
+
+/* $Header: DelPane.c,v 1.2 87/12/20 12:04:26 rws Exp $ */
+/* Copyright Massachusetts Institute of Technology 1985 */
+
+/*
+ * XMenu: MIT Project Athena, X Window system menu package
+ *
+ * XMenuDeletePane - Deletes a pane from an XMenu object.
+ *
+ * Author: Tony Della Fera, DEC
+ * 20-Nov-85
+ *
+ */
+
+#include "XMenuInt.h"
+
+int
+XMenuDeletePane(display, menu, p_num)
+ register Display *display; /* Previously opened display */
+ register XMenu *menu; /* Menu object to be modified. */
+ register int p_num; /* Pane number to be deleted. */
+{
+ register XMPane *p_ptr; /* Pointer to pane being deleted. */
+ register XMSelect *s_ptr; /* Pointer to selections being deleted. */
+ register XMSelect *s_next; /* Pointer to next selection to be deleted. */
+
+ /*
+ * Find the right pane.
+ */
+ p_ptr = _XMGetPanePtr(menu, p_num);
+ if (p_ptr == NULL) return(XM_FAILURE);
+
+ /*
+ * Remove the pane from the association table.
+ */
+ XDeleteAssoc(display, menu->assoc_tab, p_ptr->window);
+
+ /*
+ * Remove the pane from the pane list and update
+ * the pane count.
+ */
+ remque(p_ptr);
+ menu->p_count--;
+
+ /*
+ * Remove all the selections in the pane from the
+ * association table and free their XMSelect structures.
+ */
+ for (
+ s_ptr = p_ptr->s_list->next;
+ s_ptr != p_ptr->s_list;
+ s_ptr = s_next
+ ) {
+ XDeleteAssoc(display, menu->assoc_tab, s_ptr->window);
+ s_next = s_ptr->next;
+ free(s_ptr);
+ }
+ free(p_ptr->s_list);
+
+ if (p_ptr->window) {
+ /*
+ * Destroy the selection transparencies.
+ */
+ XDestroySubwindows(display, p_ptr->window);
+
+ /*
+ * Destroy the pane window.
+ */
+ XDestroyWindow(display, p_ptr->window);
+ }
+
+ /*
+ * Free the pane's XMPane structure.
+ */
+ free(p_ptr);
+
+ /*
+ * Schedule a recompute.
+ */
+ menu->recompute = 1;
+
+ /*
+ * Return the pane number just deleted.
+ */
+ _XMErrorCode = XME_NO_ERROR;
+ return(p_num);
+}
diff --git a/oldXMenu/DelSel.c b/oldXMenu/DelSel.c
new file mode 100644
index 00000000000..f92e35e17c1
--- /dev/null
+++ b/oldXMenu/DelSel.c
@@ -0,0 +1,72 @@
+#include "copyright.h"
+
+/* $Header: DelSel.c,v 1.3 87/12/20 12:04:32 rws Exp $ */
+/* Copyright Massachusetts Institute of Technology 1985 */
+
+/*
+ * XMenu: MIT Project Athena, X Window system menu package
+ *
+ * XMenuDeleteSelection - Deletes a selection from an XMenu object.
+ *
+ * Author: Tony Della Fera, DEC
+ * 20-Nov-85
+ *
+ */
+
+#include "XMenuInt.h"
+
+int
+XMenuDeleteSelection(display, menu, p_num, s_num)
+ register Display *display; /* Previously opened display. */
+ register XMenu *menu; /* Menu object to be modified. */
+ register int p_num; /* Pane number to be deleted. */
+ register int s_num; /* Selection number to be deleted. */
+{
+ register XMPane *p_ptr; /* Pointer to pane being deleted. */
+ register XMSelect *s_ptr; /* Pointer to selections being deleted. */
+
+ /*
+ * Find the right pane.
+ */
+ p_ptr = _XMGetPanePtr(menu, p_num);
+ if (p_ptr == NULL) return(XM_FAILURE);
+
+ /*
+ * Find the right selection.
+ */
+ s_ptr = _XMGetSelectionPtr(p_ptr, s_num);
+ if (s_ptr == NULL) return(XM_FAILURE);
+
+ /*
+ * Remove the selection from the association table.
+ */
+ XDeleteAssoc(display, menu->assoc_tab, s_ptr->window);
+
+ /*
+ * Remove the selection from the parent pane's selection
+ * list and update the selection count.
+ */
+ remque(s_ptr);
+ p_ptr->s_count--;
+
+ /*
+ * Destroy the selection transparency.
+ */
+ if (s_ptr->window) XDestroyWindow(display, s_ptr->window);
+
+ /*
+ * Free the selection's XMSelect structure.
+ */
+ free(s_ptr);
+
+ /*
+ * Schedule a recompute.
+ */
+ menu->recompute = 1;
+
+ /*
+ * Return the selection number just deleted.
+ */
+ _XMErrorCode = XME_NO_ERROR;
+ return(s_num);
+}
diff --git a/oldXMenu/Destroy.c b/oldXMenu/Destroy.c
new file mode 100644
index 00000000000..82b201bb2cd
--- /dev/null
+++ b/oldXMenu/Destroy.c
@@ -0,0 +1,116 @@
+#include "copyright.h"
+
+/* $Header: Destroy.c,v 1.2 87/12/20 12:04:48 rws Exp $ */
+/* Copyright Massachusetts Institute of Technology 1985 */
+
+/*
+ * XMenu: MIT Project Athena, X Window system menu package
+ *
+ * XMenuDestroy - Free all resources associated with and XMenu.
+ *
+ * Author: Tony Della Fera, DEC
+ * August, 1985
+ *
+ */
+
+#include "XMenuInt.h"
+
+XMenuDestroy(display, menu)
+ Display *display;
+ register XMenu *menu; /* Menu object to destroy. */
+{
+ register XMPane *p_ptr; /* Pointer to the current pane. */
+ register XMPane *p_next; /* Pointer to the next pane. */
+ register XMSelect *s_ptr; /* Pointer to the current selection. */
+ register XMSelect *s_next; /* Pointer to the next selection. */
+
+ /*
+ * Destroy the selection and pane X windows and free
+ * their corresponding XMWindows.
+ */
+ for (
+ p_ptr = menu->p_list->next;
+ p_ptr != menu->p_list;
+ p_ptr = p_next
+ ) {
+ for (
+ s_ptr = p_ptr->s_list->next;
+ s_ptr != p_ptr->s_list;
+ s_ptr = s_next
+ ) {
+ s_next = s_ptr->next;
+ free(s_ptr);
+ }
+ if (p_ptr->window) {
+ XDestroySubwindows(display, p_ptr->window);
+ XDestroyWindow(display, p_ptr->window);
+ }
+ p_next = p_ptr->next;
+ free(p_ptr);
+ }
+
+ /*
+ * Destroy the association table.
+ */
+ XDestroyAssocTable(menu->assoc_tab);
+
+ /*
+ * Free the mouse cursor.
+ */
+ XFreeCursor(display, menu->mouse_cursor);
+
+ /*
+ * Free the fonts.
+ */
+ XFreeFont(display, menu->p_fnt_info);
+ XFreeFont(display, menu->s_fnt_info);
+
+ /*
+ * Free the pixmaps.
+ */
+/* XFreePixmap(display, menu->p_bdr_pixmap);
+ XFreePixmap(display, menu->s_bdr_pixmap);
+ XFreePixmap(display, menu->p_frg_pixmap);
+ XFreePixmap(display, menu->s_frg_pixmap);
+ XFreePixmap(display, menu->bkgnd_pixmap); */
+ XFreePixmap(display, menu->inact_pixmap);
+
+ /*
+ * Free the color cells.
+ */
+ if ((menu->p_bdr_color != BlackPixel(display, DefaultScreen(display))) && (menu->p_bdr_color != WhitePixel(display, DefaultScreen(display))))
+ XFreeColors(
+ display,
+ DefaultColormap(display, DefaultScreen(display)),
+ &menu->p_bdr_color,
+ 1, 0);
+ if ((menu->s_bdr_color != BlackPixel(display, DefaultScreen(display))) && (menu->s_bdr_color != WhitePixel(display, DefaultScreen(display))))
+ XFreeColors(
+ display,
+ DefaultColormap(display, DefaultScreen(display)),
+ &menu->s_bdr_color,
+ 1, 0);
+ if ((menu->p_frg_color != BlackPixel(display, DefaultScreen(display))) && (menu->p_frg_color != WhitePixel(display, DefaultScreen(display))))
+ XFreeColors(
+ display,
+ DefaultColormap(display, DefaultScreen(display)),
+ &menu->p_frg_color,
+ 1, 0);
+ if ((menu->s_frg_color != BlackPixel(display, DefaultScreen(display))) && (menu->s_frg_color != WhitePixel(display, DefaultScreen(display))))
+ XFreeColors(
+ display,
+ DefaultColormap(display, DefaultScreen(display)),
+ &menu->s_frg_color,
+ 1, 0);
+ if ((menu->bkgnd_color != BlackPixel(display, DefaultScreen(display))) && (menu->bkgnd_color != WhitePixel(display, DefaultScreen(display))))
+ XFreeColors(
+ display,
+ DefaultColormap(display, DefaultScreen(display)),
+ &menu->bkgnd_color,
+ 1, 0);
+
+ /*
+ * Free the XMenu.
+ */
+ free(menu);
+}
diff --git a/oldXMenu/Error.c b/oldXMenu/Error.c
new file mode 100644
index 00000000000..96dc908b256
--- /dev/null
+++ b/oldXMenu/Error.c
@@ -0,0 +1,30 @@
+#include "copyright.h"
+
+/* $Header: Error.c,v 1.2 87/12/20 12:04:53 rws Exp $ */
+/* Copyright Massachusetts Institute of Technology 1985 */
+
+/*
+ * XMenu: MIT Project Athena, X Window system menu package
+ *
+ * XMenuError - Returns a string description of the current
+ * XMenu error status flag.
+ *
+ * Author: Tony Della Fera, DEC
+ * August, 1985
+ *
+ */
+
+#include "XMenuInt.h"
+
+char *
+XMenuError()
+{
+ char message[128]; /* Error message buffer. */
+
+ if ((_XMErrorCode < XME_CODE_COUNT) && (_XMErrorCode >= 0)) {
+ return(_XMErrorList[_XMErrorCode]);
+ }
+ sprintf(message, "Unknown _XMErrorCode: %d", _XMErrorCode);
+ return(message);
+}
+
diff --git a/oldXMenu/EvHand.c b/oldXMenu/EvHand.c
new file mode 100644
index 00000000000..5852e1b8454
--- /dev/null
+++ b/oldXMenu/EvHand.c
@@ -0,0 +1,26 @@
+#include "copyright.h"
+
+/* $Header: EvHand.c,v 1.2 87/12/20 12:04:57 rws Exp $ */
+/* Copyright Massachusetts Institute of Technology 1985 */
+
+/*
+ * XMenu: MIT Project Athena, X Window system menu package
+ *
+ * XMenuEventHandler - Set the XMenu asynchronous event handler.
+ *
+ * Author: Tony Della Fera, DEC
+ * December 19, 1985
+ *
+ */
+
+#include "XMenuInt.h"
+
+XMenuEventHandler(handler)
+ int (*handler)();
+{
+ /*
+ * Set the global event handler variable.
+ */
+ _XMEventHandler = handler;
+}
+
diff --git a/oldXMenu/FindPane.c b/oldXMenu/FindPane.c
new file mode 100644
index 00000000000..59bf3ab29b3
--- /dev/null
+++ b/oldXMenu/FindPane.c
@@ -0,0 +1,64 @@
+#include "copyright.h"
+
+/* $Header: FindPane.c,v 1.2 87/12/20 12:05:03 rws Exp $ */
+/* Copyright Massachusetts Institute of Technology 1985 */
+
+/*
+ * XMenu: MIT Project Athena, X Window system menu package
+ *
+ * XMenuFindPane - Find the first menu pane who's label matches a
+ * particular string.
+ *
+ * Author: Tony Della Fera, DEC
+ * January 22, 1986
+ *
+ */
+
+#include "XMenuInt.h"
+
+int
+XMenuFindPane(menu, label)
+ register XMenu *menu;
+ register char *label;
+{
+ register XMPane *p_ptr;
+ register int i = 0;
+
+ /*
+ * Check for NULL pointers!
+ */
+ if (label == NULL) {
+ _XMErrorCode = XME_ARG_BOUNDS;
+ return(XM_FAILURE);
+ }
+
+ /*
+ * Find the pane who's label matches the given label.
+ */
+ for (
+ p_ptr = menu->p_list->next;
+ p_ptr != menu->p_list;
+ p_ptr = p_ptr->next
+ ){
+ if (p_ptr->label_length == 0) {
+ if (*label == '\0') {
+ _XMErrorCode = XME_NO_ERROR;
+ return (i);
+ }
+ }
+ else {
+ if (strncmp (label, p_ptr->label, p_ptr->label_length) == 0) {
+ _XMErrorCode = XME_NO_ERROR;
+ return (i);
+ }
+ }
+ i++;
+ }
+
+ /*
+ * If we get here then we have not found
+ * a match.
+ */
+ _XMErrorCode = XME_P_NOT_FOUND;
+ return (XM_FAILURE);
+}
diff --git a/oldXMenu/FindSel.c b/oldXMenu/FindSel.c
new file mode 100644
index 00000000000..e0bb0b29582
--- /dev/null
+++ b/oldXMenu/FindSel.c
@@ -0,0 +1,72 @@
+#include "copyright.h"
+
+/* $Header: FindSel.c,v 1.2 87/12/20 12:05:07 rws Exp $ */
+/* Copyright Massachusetts Institute of Technology 1985 */
+
+/*
+ * XMenu: MIT Project Athena, X Window system menu package
+ *
+ * XMenuFindSelection - Find the first selection in a pane who's
+ * label matches a particular string.
+ *
+ * Author: Tony Della Fera, DEC
+ * January 22, 1986
+ *
+ */
+
+#include "XMenuInt.h"
+
+int
+XMenuFindSelection(menu, p_num, label)
+ register XMenu *menu;
+ int p_num;
+ register char *label;
+{
+ register XMPane *p_ptr;
+ register XMSelect *s_ptr;
+ register int i = 0;
+
+ /*
+ * Check for NULL pointers!
+ */
+ if (label == NULL) {
+ _XMErrorCode = XME_ARG_BOUNDS;
+ return(XM_FAILURE);
+ }
+
+ /*
+ * Find the right pane.
+ */
+ p_ptr = _XMGetPanePtr(menu, p_num);
+ if (p_ptr == NULL) return(XM_FAILURE);
+
+ /*
+ * Find the right selection.
+ */
+ for (
+ s_ptr = p_ptr->s_list->next;
+ s_ptr != p_ptr->s_list;
+ s_ptr = s_ptr->next
+ ){
+ if (s_ptr->label_length == 0) {
+ if (*label == '\0') {
+ _XMErrorCode = XME_NO_ERROR;
+ return (i);
+ }
+ }
+ else {
+ if (strncmp (label, s_ptr->label, s_ptr->label_length) == 0) {
+ _XMErrorCode = XME_NO_ERROR;
+ return (i);
+ }
+ }
+ i++;
+ }
+
+ /*
+ * If we get here then we have not found
+ * a match.
+ */
+ _XMErrorCode = XME_S_NOT_FOUND;
+ return (XM_FAILURE);
+}
diff --git a/oldXMenu/Imakefile b/oldXMenu/Imakefile
new file mode 100644
index 00000000000..869aff9e2bb
--- /dev/null
+++ b/oldXMenu/Imakefile
@@ -0,0 +1,87 @@
+ HEADERS = XMenu.h
+ LINTLIBS = ../lib/X/llib-lX.ln
+ INSTALLFLAGS = $(INSTINCFLAGS)
+ RANLIB = ranlib -t
+
+SRCS = Activate.c \
+ AddPane.c \
+ AddSel.c \
+ ChgPane.c \
+ ChgSel.c \
+ Create.c \
+ DelPane.c \
+ DelSel.c \
+ Destroy.c \
+ Error.c \
+ EvHand.c \
+ FindPane.c \
+ FindSel.c \
+ InsPane.c \
+ InsSel.c \
+ Internal.c \
+ Locate.c \
+ Post.c \
+ Recomp.c \
+ SetAEQ.c \
+ SetFrz.c \
+ SetPane.c \
+ SetSel.c
+
+OBJS = Activate.o \
+ AddPane.o \
+ AddSel.o \
+ ChgPane.o \
+ ChgSel.o \
+ Create.o \
+ DelPane.o \
+ DelSel.o \
+ Destroy.o \
+ Error.o \
+ EvHand.o \
+ FindPane.o \
+ FindSel.o \
+ InsPane.o \
+ InsSel.o \
+ Internal.o \
+ Locate.o \
+ Post.o \
+ Recomp.o \
+ SetAEQ.o \
+ SetFrz.o \
+ SetPane.o \
+ SetSel.o
+
+#if DebugOldLibXMenu && ProfileOldLibXMenu
+DebuggedAndProfiledLibraryObjectRule()
+#else
+# if DebugOldLibXMenu
+DebuggedLibraryObjectRule()
+# else
+# if ProfileOldLibXMenu
+ProfiledLibraryObjectRule()
+# else
+NormalLibraryObjectRule()
+# endif
+# endif
+#endif
+
+NormalLibraryTarget(XMenu11,$(OBJS))
+LintLibraryTarget(XMenu11,$(SRCS))
+InstallLibrary(XMenu11,$(USRLIBDIR))
+#if InstallLintLibs
+InstallLintLibrary(XMenu11,$(LINTLIBDIR))
+#endif
+InstallMultiple($(HEADERS),$(INCDIR))
+
+#if ProfileOldLibXMenu
+ProfiledLibraryTarget(XMenu11,$(OBJS))
+InstallLibrary(XMenu11_p,$(USRLIBDIR))
+#endif
+
+#if DebugOldLibXMenu
+DebuggedLibraryTarget(XMenu11,$(OBJS))
+#endif
+
+DependTarget()
+
+NormalLintTarget($(SRCS))
diff --git a/oldXMenu/InsPane.c b/oldXMenu/InsPane.c
new file mode 100644
index 00000000000..4d5634524e2
--- /dev/null
+++ b/oldXMenu/InsPane.c
@@ -0,0 +1,111 @@
+#include "copyright.h"
+
+/* $Header: InsPane.c,v 1.3 87/12/20 12:05:11 rws Exp $ */
+/* Copyright Massachusetts Institute of Technology 1985 */
+
+/*
+ * XMenu: MIT Project Athena, X Window system menu package
+ *
+ * XMenuInsertPane - Inserts a pane into an XMenu object in
+ * a particular position.
+ *
+ * Author: Tony Della Fera, DEC
+ * 20-Nov-85
+ *
+ */
+
+#include "XMenuInt.h"
+
+int
+XMenuInsertPane(menu, p_num, label, active)
+ register XMenu *menu; /* Menu object to be modified. */
+ register int p_num; /* Pane number of new pane. */
+ char *label; /* Selection label. */
+ int active; /* Make selection active? */
+{
+ register XMPane *p_ptr; /* XMPane pointer. */
+ register XMPane *pane; /* Newly created pane. */
+ register XMSelect *select; /* Initial selection for the new pane. */
+
+ int label_length; /* Label lenght in characters. */
+ int label_width; /* Label width in pixels. */
+
+ /*
+ * Check for NULL pointers!
+ */
+ if (label == NULL) {
+ _XMErrorCode = XME_ARG_BOUNDS;
+ return(XM_FAILURE);
+ }
+
+ /*
+ * Find the pane number one less than the one specified since that
+ * is the pane after which the insertion will occur.
+ */
+ p_ptr = _XMGetPanePtr(menu, (p_num - 1));
+ if (p_ptr == NULL) return(XM_FAILURE);
+
+ /*
+ * Calloc the XMPane structure and the initial XMSelect.
+ */
+ pane = (XMPane *)calloc(1, sizeof(XMPane));
+ if (pane == NULL) {
+ _XMErrorCode = XME_CALLOC;
+ return(XM_FAILURE);
+ }
+ select = (XMSelect *)calloc(1, sizeof(XMSelect));
+ if (select == NULL) {
+ _XMErrorCode = XME_CALLOC;
+ return(XM_FAILURE);
+ }
+
+ /*
+ * Determine label size.
+ */
+ label_length = strlen(label);
+ label_width = XTextWidth(menu->p_fnt_info, label, label_length);
+
+ /*
+ * Set up the initial selection.
+ * Values not explicitly set are zeroed by calloc.
+ */
+ select->next = select;
+ select->prev = select;
+ select->type = SL_HEADER;
+ select->serial = -1;
+ select->parent_p = pane;
+
+ /*
+ * Fill the XMPane structure.
+ */
+ pane->type = PANE;
+ pane->active = active;
+ pane->serial = -1;
+ pane->label = label;
+ pane->label_width = label_width;
+ pane->label_length = label_length;
+ pane->s_list = select;
+
+ /*
+ * Insert the pane after the pane with the pane
+ * number one less than the desired number for the
+ * new pane.
+ */
+ insque(pane, p_ptr);
+
+ /*
+ * Update the pane count.
+ */
+ menu->p_count++;
+
+ /*
+ * Schedule a recompute.
+ */
+ menu->recompute = 1;
+
+ /*
+ * Return the number of the pane just added.
+ */
+ _XMErrorCode = XME_NO_ERROR;
+ return(p_num);
+}
diff --git a/oldXMenu/InsSel.c b/oldXMenu/InsSel.c
new file mode 100644
index 00000000000..d5ebc8197e9
--- /dev/null
+++ b/oldXMenu/InsSel.c
@@ -0,0 +1,105 @@
+#include "copyright.h"
+
+/* $Header: InsSel.c,v 1.3 87/12/20 12:05:16 rws Exp $ */
+/* Copyright Massachusetts Institute of Technology 1985 */
+
+/*
+ * XMenu: MIT Project Athena, X Window system menu package
+ *
+ * XMenuInsertSelection - Inserts a selection into an XMenu object
+ *
+ * Author: Tony Della Fera, DEC
+ * 20-Nov-85
+ *
+ */
+
+#include "XMenuInt.h"
+
+int
+XMenuInsertSelection(menu, p_num, s_num, data, label, active)
+ register XMenu *menu; /* Menu object to be modified. */
+ register int p_num; /* Pane number to be modified. */
+ register int s_num; /* Selection number of new selection. */
+ char *data; /* Data value. */
+ char *label; /* Selection label. */
+ int active; /* Make selection active? */
+{
+ register XMPane *p_ptr; /* XMPane pointer. */
+ register XMSelect *s_ptr; /* XMSelect pointer. */
+
+ XMSelect *select; /* Newly created selection. */
+
+ int label_length; /* Label lenght in characters. */
+ int label_width; /* Label width in pixels. */
+
+ /*
+ * Check for NULL pointers!
+ */
+ if (label == NULL) {
+ _XMErrorCode = XME_ARG_BOUNDS;
+ return(XM_FAILURE);
+ }
+
+ /*
+ * Find the right pane.
+ */
+ p_ptr = _XMGetPanePtr(menu, p_num);
+ if (p_ptr == NULL) return(XM_FAILURE);
+
+ /*
+ * Find the selection number one less than the one specified since that
+ * is the selection after which the insertion will occur.
+ */
+ s_ptr = _XMGetSelectionPtr(p_ptr, (s_num - 1));
+ if (s_ptr == NULL) return(XM_FAILURE);
+
+ /*
+ * Calloc the XMSelect structure.
+ */
+ select = (XMSelect *)calloc(1, sizeof(XMSelect));
+ if (select == NULL) {
+ _XMErrorCode = XME_CALLOC;
+ return(XM_FAILURE);
+ }
+
+ /*
+ * Determine label size.
+ */
+ label_length = strlen(label);
+ label_width = XTextWidth(menu->s_fnt_info, label, label_length);
+
+
+ /*
+ * Fill the XMSelect structure.
+ */
+ select->type = SELECTION;
+ select->active = active;
+ select->serial = -1;
+ select->label = label;
+ select->label_width = label_width;
+ select->label_length = label_length;
+ select->data = data;
+ select->parent_p = p_ptr;
+
+ /*
+ * Insert the selection after the selection with the selection
+ * number one less than the desired number for the new selection.
+ */
+ insque(select, s_ptr);
+
+ /*
+ * Update the selection count.
+ */
+ p_ptr->s_count++;
+
+ /*
+ * Schedule a recompute.
+ */
+ menu->recompute = 1;
+
+ /*
+ * Return the selection number just inserted.
+ */
+ _XMErrorCode = XME_NO_ERROR;
+ return(s_num);
+}
diff --git a/oldXMenu/Internal.c b/oldXMenu/Internal.c
new file mode 100644
index 00000000000..80645ae3d9c
--- /dev/null
+++ b/oldXMenu/Internal.c
@@ -0,0 +1,988 @@
+#include "copyright.h"
+
+/* $Header: Internal.c,v 1.12 87/12/20 12:05:22 rws Exp $ */
+/* Copyright Massachusetts Institute of Technology 1985 */
+
+/*
+ * XMenu: MIT Project Athena, X Window system menu package
+ *
+ * XMenuInternal.c - XMenu internal (not user visable) routines.
+ *
+ * Author: Tony Della Fera, DEC
+ * November, 1985
+ *
+ */
+
+#include "XMenuInt.h"
+
+/*
+ * Toggle color macro.
+ */
+#define toggle_color(x) \
+ ((x) == menu->bkgnd_color ? menu->s_frg_color : menu->bkgnd_color)
+
+/*
+ * Internal Window creation queue sizes.
+ */
+#define S_QUE_SIZE 300
+#define P_QUE_SIZE 20
+#define BUFFER_SIZE (S_QUE_SIZE >= P_QUE_SIZE ? S_QUE_SIZE : P_QUE_SIZE)
+
+
+/*
+ * XMWinQue - Internal window creation queue datatype.
+ */
+typedef struct _xmwinquedef {
+ int sq_size;
+ XMSelect *sq[S_QUE_SIZE];
+ XMSelect **sq_ptr;
+ int pq_size;
+ XMPane *pq[P_QUE_SIZE];
+ XMPane **pq_ptr;
+} XMWinQue;
+
+/*
+ * _XMWinQue - Internal static window creation queue.
+ */
+static Bool _XMWinQueIsInit = False;
+static XMWinQue _XMWinQue;
+
+/*
+ * _XMErrorCode - Global XMenu error code.
+ */
+int _XMErrorCode = XME_NO_ERROR;
+/*
+ * _XMErrorList - Global XMenu error code discription strings.
+ */
+char *
+_XMErrorList[XME_CODE_COUNT] = {
+ "No error", /* XME_NO_ERROR */
+ "Menu not initialized", /* XME_NOT_INIT */
+ "Argument out of bounds", /* XME_ARG_BOUNDS */
+ "Pane not found", /* XME_P_NOT_FOUND */
+ "Selection not found", /* XME_S_NOT_FOUND */
+ "Invalid menu style parameter", /* XME_STYLE_PARAM */
+ "Unable to grab mouse", /* XME_GRAB_MOUSE */
+ "Unable to interpret locator", /* XME_INTERP_LOC */
+ "Unable to calloc memory", /* XME_CALLOC */
+ "Unable to create XAssocTable", /* XME_CREATE_ASSOC */
+ "Unable to store bitmap", /* XME_STORE_BITMAP */
+ "Unable to make tile pixmaps", /* XME_MAKE_TILES */
+ "Unable to make pixmap", /* XME_MAKE_PIXMAP */
+ "Unable to create cursor", /* XME_CREATE_CURSOR */
+ "Unable to open font", /* XME_OPEN_FONT */
+ "Unable to create windows", /* XME_CREATE_WINDOW */
+ "Unable to create transparencies", /* XME_CREATE_TRANSP */
+};
+
+/*
+ * _XMEventHandler - Internal event handler variable.
+ */
+int (*_XMEventHandler)() = NULL;
+
+
+
+/*
+ * _XMWinQueInit - Internal routine to initialize the window
+ * queue.
+ */
+_XMWinQueInit()
+{
+ /*
+ * If the queue is not initialized initialize it.
+ */
+ if (!_XMWinQueIsInit) {
+ /*
+ * Blank the queue structure.
+ */
+ bzero(&_XMWinQue, sizeof(XMWinQue));
+
+ /*
+ * Initialize the next free location pointers.
+ */
+ _XMWinQue.sq_ptr = _XMWinQue.sq;
+ _XMWinQue.pq_ptr = _XMWinQue.pq;
+ }
+}
+
+
+
+/*
+ * _XMWinQueAddPane - Internal routine to add a pane to the pane
+ * window queue.
+ */
+int
+_XMWinQueAddPane(display, menu, p_ptr)
+ register Display *display;
+ register XMenu *menu; /* Menu being manipulated. */
+ register XMPane *p_ptr; /* XMPane being queued. */
+{
+ /*
+ * If the queue is currently full then flush it.
+ */
+ if (_XMWinQue.pq_size == P_QUE_SIZE) {
+ if (_XMWinQueFlush(display, menu, 0, 0) == _FAILURE) return(_FAILURE);
+ }
+
+ /*
+ * Insert the new XMPane pointer and increment the queue pointer
+ * and the queue size.
+ */
+ *_XMWinQue.pq_ptr = p_ptr;
+ _XMWinQue.pq_ptr++;
+ _XMWinQue.pq_size++;
+
+ /*
+ * All went well, return successfully.
+ */
+ _XMErrorCode = XME_NO_ERROR;
+ return(_SUCCESS);
+}
+
+
+
+/*
+ * _XMWinQueAddSelection - Internal routine to add a selection to
+ * the selection window queue.
+ */
+int
+_XMWinQueAddSelection(display, menu, s_ptr)
+ register Display *display;
+ register XMenu *menu; /* Menu being manipulated. */
+ register XMSelect *s_ptr; /* XMSelection being queued. */
+{
+ /*
+ * If this entry will overflow the queue then flush it.
+ */
+ if (_XMWinQue.sq_size == S_QUE_SIZE) {
+ if (_XMWinQueFlush(display, menu, 0, 0) == _FAILURE) return(_FAILURE);
+ }
+
+ /*
+ * Insert the new XMSelect pointer and increment the queue pointer
+ * and the queue size.
+ */
+ *_XMWinQue.sq_ptr = s_ptr;
+ _XMWinQue.sq_ptr++;
+ _XMWinQue.sq_size++;
+
+ /*
+ * All went well, return successfully.
+ */
+ _XMErrorCode = XME_NO_ERROR;
+ return(_SUCCESS);
+}
+
+
+
+/*
+ * _XMWinQueFlush - Internal routine to flush the pane and
+ * selection window queues.
+ */
+int
+_XMWinQueFlush(display, menu, pane, select)
+ register Display *display;
+ register XMenu *menu; /* Menu being manipulated. */
+ register XMPane *pane; /* Current pane. */
+{
+ register int pq_index; /* Pane queue index. */
+ register int sq_index; /* Selection queue index. */
+ register XMPane *p_ptr; /* XMPane pointer. */
+ register XMSelect *s_ptr; /* XMSelect pointer. */
+ unsigned long valuemask; /* Which attributes to set. */
+ XSetWindowAttributes *attributes; /* Attributes to be set. */
+
+ /*
+ * If the pane window queue is not empty...
+ */
+
+ if (_XMWinQue.pq_size > 0) {
+ /*
+ * set up attributes for pane window to be created.
+ */
+ valuemask = (CWBackPixmap | CWBorderPixel | CWOverrideRedirect);
+ attributes = (XSetWindowAttributes *)malloc(sizeof(XSetWindowAttributes));
+ attributes->border_pixel = menu->p_bdr_color;
+ attributes->background_pixmap = menu->inact_pixmap;
+ attributes->override_redirect = True;
+
+ /*
+ * Create all the pending panes in order, so that the
+ * current pane will be on top, with the others
+ * stacked appropriately under it.
+ */
+ for (pq_index = _XMWinQue.pq_size - 1;
+ pq_index >= 0;
+ pq_index--)
+ {
+ p_ptr = _XMWinQue.pq[pq_index]; /* Retrieve next pane. */
+ if (p_ptr == pane) break;
+ p_ptr->window = XCreateWindow(display,
+ menu->parent,
+ p_ptr->window_x,
+ p_ptr->window_y,
+ p_ptr->window_w,
+ p_ptr->window_h,
+ menu->p_bdr_width,
+ CopyFromParent,
+ InputOutput,
+ CopyFromParent,
+ valuemask,
+ attributes);
+ XMakeAssoc(display, menu->assoc_tab, p_ptr->window, p_ptr);
+ XSelectInput(display, p_ptr->window, menu->p_events);
+ }
+ for (pq_index = 0;
+ pq_index < _XMWinQue.pq_size;
+ pq_index++)
+ {
+ p_ptr = _XMWinQue.pq[pq_index]; /* Retrieve next pane. */
+ p_ptr->window = XCreateWindow(display,
+ menu->parent,
+ p_ptr->window_x,
+ p_ptr->window_y,
+ p_ptr->window_w,
+ p_ptr->window_h,
+ menu->p_bdr_width,
+ CopyFromParent,
+ InputOutput,
+ CopyFromParent,
+ valuemask,
+ attributes);
+ XMakeAssoc(display, menu->assoc_tab, p_ptr->window, p_ptr);
+ XSelectInput(display, p_ptr->window, menu->p_events);
+ if (p_ptr == pane) break;
+ }
+
+ /*
+ * Reset the pane queue pointer and size.
+ */
+ _XMWinQue.pq_size = 0;
+ _XMWinQue.pq_ptr = _XMWinQue.pq;
+ }
+
+ /*
+ * If the selection window queue is not empty...
+ */
+
+ if (_XMWinQue.sq_size > 0) {
+
+ for (sq_index = 0; sq_index < _XMWinQue.sq_size; sq_index++) {
+ /*
+ * Retrieve the XMSelect pointer.
+ */
+ s_ptr = _XMWinQue.sq[sq_index];
+ s_ptr->window = XCreateWindow(display,
+ s_ptr->parent_p->window,
+ s_ptr->window_x,
+ s_ptr->window_y,
+ s_ptr->window_w,
+ s_ptr->window_h,
+ 0, /* border width*/
+ CopyFromParent,
+ InputOnly,
+ CopyFromParent,
+ 0,
+ attributes);
+
+ /*
+ * Insert the new window id and its
+ * associated XMSelect structure into the
+ * assoction table.
+ */
+ XMakeAssoc(display, menu->assoc_tab, s_ptr->window, s_ptr);
+ XSelectInput(display, s_ptr->window, menu->s_events);
+ }
+
+ /*
+ * Reset the selection queue pointer and size.
+ */
+ _XMWinQue.sq_size = 0;
+ _XMWinQue.sq_ptr = _XMWinQue.sq;
+ }
+
+ /*
+ * Flush X's internal queues.
+ */
+ XFlush(display);
+
+ /*
+ * All went well, return successfully.
+ */
+ _XMErrorCode = XME_NO_ERROR;
+ return(_SUCCESS);
+}
+
+
+
+/*
+ * _XMGetPanePtr - Given a menu pointer and a pane index number, return
+ * a pane pointer that points to the indexed pane.
+ */
+XMPane *
+_XMGetPanePtr(menu, p_num)
+ register XMenu *menu; /* Menu to find the pane in. */
+ register int p_num; /* Index number of pane to find. */
+{
+ register XMPane *p_ptr; /* Pane pointer to be returned. */
+ register int i; /* Loop counter. */
+
+ /*
+ * Is the pane number out of range?
+ */
+ if ((p_num < 0) || (p_num > (menu->p_count - 1))) {
+ _XMErrorCode = XME_P_NOT_FOUND;
+ return(NULL);
+ }
+
+ /*
+ * Find the right pane.
+ */
+ p_ptr = menu->p_list->next;
+ for (i = 0; i < p_num; i++) p_ptr = p_ptr->next;
+
+ /*
+ * Return successfully.
+ */
+ _XMErrorCode = XME_NO_ERROR;
+ return(p_ptr);
+}
+
+
+
+/*
+ * _XMGetSelectionPtr - Given pane pointer and a selection index number,
+ * return a selection pointer that points to the
+ * indexed selection.
+ */
+XMSelect *
+_XMGetSelectionPtr(p_ptr, s_num)
+ register XMPane *p_ptr; /* Pane to find the selection in. */
+ register int s_num; /* Index number of the selection to find. */
+{
+ register XMSelect *s_ptr; /* Selection pointer to be returned. */
+ register int i; /* Loop counter. *./
+
+ /*
+ * Is the selection number out of range?
+ */
+ if ((s_num < 0) || (s_num > (p_ptr->s_count - 1))) {
+ _XMErrorCode = XME_S_NOT_FOUND;
+ return(NULL);
+ }
+
+ /*
+ * Find the right selection.
+ */
+ s_ptr = p_ptr->s_list->next;
+ for (i = 0; i < s_num; i++) s_ptr = s_ptr->next;
+
+ /*
+ * Return successfully.
+ */
+ _XMErrorCode = XME_NO_ERROR;
+ return(s_ptr);
+}
+
+
+
+/*
+ * _XMRecomputeGlobals - Internal subroutine to recompute menu wide
+ * global values.
+ */
+_XMRecomputeGlobals(display, menu)
+ register Display *display; /*X11 display variable. */
+ register XMenu *menu; /* Menu object to compute from. */
+{
+ register XMPane *p_ptr; /* Pane pointer. */
+ register XMSelect *s_ptr; /* Selection pointer. */
+
+ register int max_p_label = 0; /* Maximum pane label width. */
+ register int max_s_label = 0; /* Maximum selection label width. */
+ register int s_count = 0; /* Maximum selection count. */
+
+ int p_s_pad; /* Pane <-> selection padding. */
+ int p_s_diff; /* Pane <-> selection seperation. */
+
+ int p_height; /* Pane window height. */
+ int p_width; /* Pane window width. */
+ int s_width; /* Selection window width. */
+
+ int screen; /* DefaultScreen holder. */
+
+ /*
+ * For each pane...
+ */
+ for (
+ p_ptr = menu->p_list->next;
+ p_ptr != menu->p_list;
+ p_ptr = p_ptr->next
+ ){
+
+ /*
+ * Recompute maximum pane label width.
+ */
+ max_p_label = max(max_p_label, p_ptr->label_width);
+
+ /*
+ * Recompute maximum selection count.
+ */
+ s_count = max(s_count, p_ptr->s_count);
+
+ /*
+ * For each selection in the current pane...
+ */
+ for (
+ s_ptr = p_ptr->s_list->next;
+ s_ptr != p_ptr->s_list;
+ s_ptr = s_ptr->next
+ ){
+
+ /*
+ * Recompute maximum selection label width.
+ */
+ max_s_label = max(max_s_label, s_ptr->label_width);
+ }
+ }
+
+ /*
+ * Recompute pane height.
+ */
+ p_height = (menu->flag_height << 1) + (menu->s_y_off * s_count);
+
+ /*
+ * Recompute horizontal padding between the pane window and the
+ * selection windows.
+ */
+ p_s_pad = menu->p_x_off << 1;
+
+ /*
+ * Recompute pane and selection window widths.
+ * This is done by first computing the window sizes from the maximum
+ * label widths. If the spacing between the selection window and the
+ * containing pane window is less than the pane selection padding value
+ * (twice the pane X offset) then change the size of the pane to be
+ * the size of the selection window plus the padding. If, however the
+ * spacing between the selection window and the containing pane window
+ * is more than the pane selection padding value increase the size of
+ * the selection to its maximum possible value (the pane width minus
+ * the pane selection padding value).
+ */
+ p_width = max_p_label + p_s_pad;
+ s_width = max_s_label + (menu->s_fnt_pad << 1) + (menu->s_bdr_width << 1);
+ p_s_diff = p_width - s_width;
+ if (p_s_diff < p_s_pad) {
+ p_width = s_width + p_s_pad;
+ }
+ else if (p_s_diff > p_s_pad) {
+ s_width = p_width - p_s_pad;
+ }
+
+ /*
+ * Reset menu wide global values.
+ */
+ menu->s_count = s_count;
+ menu->p_height = p_height;
+ menu->p_width = p_width;
+ menu->s_width = s_width;
+
+ /*
+ * Ensure that the origin of the menu is placed so that
+ * None of the panes ore selections are off the screen.
+ */
+ screen = DefaultScreen(display);
+ if (menu->x_pos + menu->width > DisplayWidth(display, screen))
+ menu->x_pos = DisplayWidth(display, screen) - menu->width;
+ else if (menu->x_pos < 0) menu->x_pos = 0;
+ if(menu->y_pos + menu->height > DisplayHeight(display, screen))
+ menu->y_pos = DisplayHeight(display, screen) - menu->height;
+ else if (menu->y_pos < 0) menu->y_pos = 0;
+}
+
+
+/*
+ * _XMRecomputePane - Internal subroutine to recompute pane
+ * window dependencies.
+ */
+int
+_XMRecomputePane(display, menu, p_ptr, p_num)
+ register Display *display; /* Standard X display variable. */
+ register XMenu *menu; /* Menu object being recomputed. */
+ register XMPane *p_ptr; /* Pane pointer. */
+ register int p_num; /* Pane sequence number. */
+{
+ register int window_x; /* Recomputed window X coordinate. */
+ register int window_y; /* Recomputed window Y coordinate. */
+
+ unsigned long change_mask; /* Value mask to reconfigure window. */
+ XWindowChanges *changes; /* Values to use in configure window. */
+
+ register Bool config_p = False; /* Reconfigure pane window? */
+
+ /*
+ * Update the pane serial number.
+ */
+ p_ptr->serial = p_num;
+
+ /*
+ * Recompute window X and Y coordinates.
+ */
+ switch (menu->menu_style) {
+ case LEFT:
+ window_x = menu->p_x_off * ((menu->p_count - 1) - p_num);
+ window_y = menu->p_y_off * ((menu->p_count - 1) - p_num);
+ break;
+ case RIGHT:
+ window_x = menu->p_x_off * p_num;
+ window_y = menu->p_y_off * ((menu->p_count - 1) - p_num);
+ break;
+ case CENTER:
+ window_x = 0;
+ window_y = menu->p_y_off * ((menu->p_count - 1) - p_num);
+ break;
+ default:
+ /* Error! Invalid style parameter. */
+ _XMErrorCode = XME_STYLE_PARAM;
+ return(_FAILURE);
+ }
+ window_x += menu->x_pos;
+ window_y += menu->y_pos;
+
+ /*
+ * If the newly compute pane coordinates differ from the
+ * current coordinates, reset the current coordinates and
+ * reconfigure the pane.
+ */
+ if (
+ (window_x != p_ptr->window_x) ||
+ (window_y != p_ptr->window_y)
+ ){
+ /*
+ * Reset the coordinates and schedule
+ * the pane for reconfiguration.
+ */
+ p_ptr->window_x = window_x;
+ p_ptr->window_y = window_y;
+ config_p = True;
+ }
+
+ /*
+ * If the local pane width and height differs from the
+ * menu pane width and height, reset the local values.
+ */
+ if (
+ (p_ptr->window_w != menu->p_width) ||
+ (p_ptr->window_h != menu->p_height)
+ ){
+ /*
+ * Reset window width and height and schedule
+ * the pane for reconfiguration.
+ */
+ p_ptr->window_w = menu->p_width;
+ p_ptr->window_h = menu->p_height;
+ config_p = True;
+ }
+
+ /*
+ * If we need to reconfigure the pane window do it now.
+ */
+ if (config_p == True) {
+ /*
+ * If the pane window has already been created then
+ * reconfigure the existing window, otherwise queue
+ * it for creation with the new configuration.
+ */
+ if (p_ptr->window) {
+ change_mask = (CWX | CWY | CWWidth | CWHeight);
+ changes = (XWindowChanges *)malloc(sizeof(XWindowChanges));
+ changes->x = p_ptr->window_x;
+ changes->y = p_ptr->window_y;
+ changes->width = p_ptr->window_w;
+ changes->height = p_ptr->window_h;
+
+ XConfigureWindow(
+ display,
+ p_ptr->window,
+ change_mask,
+ changes
+ );
+ free(changes);
+
+ }
+ else {
+ if (_XMWinQueAddPane(display, menu, p_ptr) == _FAILURE) {
+ return(_FAILURE);
+ }
+ }
+ }
+
+ /*
+ * Recompute label X position.
+ */
+ switch (menu->p_style) {
+ case LEFT:
+ p_ptr->label_x = menu->p_x_off + menu->p_fnt_pad;
+ break;
+ case RIGHT:
+ p_ptr->label_x = menu->p_width -
+ (p_ptr->label_width + menu->p_x_off + menu->p_fnt_pad);
+ break;
+ case CENTER:
+ p_ptr->label_x = (menu->p_width - p_ptr->label_width) >> 1;
+ break;
+ default:
+ /* Error! Invalid style parameter. */
+ _XMErrorCode = XME_STYLE_PARAM;
+ return(_FAILURE);
+ }
+ /*
+ * Recompute label Y positions.
+ */
+ p_ptr->label_uy = menu->p_fnt_pad + menu->p_fnt_info->max_bounds.ascent;
+ p_ptr->label_ly = (menu->p_height - menu->p_fnt_pad - menu->p_fnt_info->max_bounds.descent);
+
+ /*
+ * All went well, return successfully.
+ */
+ _XMErrorCode = XME_NO_ERROR;
+ return(_SUCCESS);
+}
+
+
+
+/*
+ * _XMRecomputeSelection - Internal subroutine to recompute
+ * selection window dependencies.
+ */
+int
+_XMRecomputeSelection(display, menu, s_ptr, s_num)
+ register Display *display;
+ register XMenu *menu; /* Menu object being recomputed. */
+ register XMSelect *s_ptr; /* Selection pointer. */
+ register int s_num; /* Selection sequence number. */
+{
+ register Bool config_s = False; /* Reconfigure selection window? */
+ XWindowChanges *changes; /* Values to change in configure. */
+ unsigned long change_mask; /* Value mask for XConfigureWindow. */
+
+ /*
+ * If the selection serial numbers are out of order, begin
+ * resequencing selections. Recompute selection window coordinates
+ * and serial number.
+ *
+ * When selections are created they are given a serial number of
+ * -1, this causes this routine to give a new selection
+ * its initial coordinates and serial number.
+ */
+ if (s_ptr->serial != s_num) {
+ /*
+ * Fix the sequence number.
+ */
+ s_ptr->serial = s_num;
+ /*
+ * Recompute window X and Y coordinates.
+ */
+ s_ptr->window_x = menu->s_x_off;
+ s_ptr->window_y = menu->flag_height + (menu->s_y_off * s_num);
+ /*
+ * We must reconfigure the window.
+ */
+ config_s = True;
+ }
+
+ /*
+ * If the local selection width and height differs from the
+ * menu selection width and height, reset the local values.
+ */
+ if (
+ (s_ptr->window_w != menu->s_width) ||
+ (s_ptr->window_h != menu->s_height)
+ ){
+ /*
+ * We must reconfigure the window.
+ */
+ config_s = True;
+ /*
+ * Reset window width and height.
+ */
+ s_ptr->window_w = menu->s_width;
+ s_ptr->window_h = menu->s_height;
+ }
+
+ /*
+ * If we need to reconfigure the selection window do it now.
+ */
+ if (config_s == True) {
+ /*
+ * If the selection window has already been created then
+ * reconfigure the existing window, otherwise queue it
+ * for creation with the new configuration.
+ */
+ if (s_ptr->window) {
+ changes = (XWindowChanges *)malloc(sizeof(XWindowChanges));
+ change_mask = (CWX | CWY | CWWidth | CWHeight);
+ changes = (XWindowChanges *)malloc(sizeof(XWindowChanges));
+ changes->x = s_ptr->window_x;
+ changes->y = s_ptr->window_y;
+ changes->width = s_ptr->window_w;
+ changes->height = s_ptr->window_h;
+
+ XConfigureWindow(
+ display,
+ s_ptr->window,
+ change_mask,
+ changes
+ );
+ free(changes);
+
+ }
+ else {
+ if (_XMWinQueAddSelection(display, menu, s_ptr) == _FAILURE) {
+ return(_FAILURE);
+ }
+ }
+ }
+
+ /*
+ * Recompute label X position.
+ */
+ switch (menu->s_style) {
+ case LEFT:
+ s_ptr->label_x = menu->s_bdr_width + menu->s_fnt_pad + s_ptr->window_x;
+ break;
+ case RIGHT:
+ s_ptr->label_x = s_ptr->window_x + menu->s_width -
+ (s_ptr->label_width + menu->s_bdr_width + menu->s_fnt_pad);
+ break;
+ case CENTER:
+ s_ptr->label_x = s_ptr->window_x + ((menu->s_width - s_ptr->label_width) >> 1);
+ break;
+ default:
+ /* Error! Invaild style parameter. */
+ _XMErrorCode = XME_STYLE_PARAM;
+ return(_FAILURE);
+ }
+ /*
+ * Recompute label Y position.
+ */
+ s_ptr->label_y = s_ptr->window_y + menu->s_fnt_info->max_bounds.ascent + menu->s_fnt_pad + menu->s_bdr_width;
+
+ /*
+ * All went well, return successfully.
+ */
+ _XMErrorCode = XME_NO_ERROR;
+ return(_SUCCESS);
+}
+
+
+
+/*
+ * _XMTransToOrigin - Internal subroutine to translate the point at
+ * the center of the current pane and selection to the
+ * the menu origin.
+ *
+ * WARNING! ****** Be certain that all menu depencies have been
+ * recomputed before calling this routine or
+ * unpredictable results will follow.
+ */
+_XMTransToOrigin(display, menu, p_ptr, s_ptr, x_pos, y_pos, orig_x, orig_y)
+ Display *display; /* Not used. Included for consistency. */
+ register XMenu *menu; /* Menu being computed against. */
+ register XMPane *p_ptr; /* Current pane pointer. */
+ register XMSelect *s_ptr; /* Current selection pointer. */
+ int x_pos; /* X coordinate of point to translate. */
+ int y_pos; /* Y coordinate of point to translate. */
+ int *orig_x; /* Return value X coord. of the menu origin. */
+ int *orig_y; /* Return value Y coord. of the menu origin. */
+{
+ register int l_orig_x; /* Local X coordinate of the menu origin. */
+ register int l_orig_y; /* Local Y coordinate of the menu origin. */
+
+ /*
+ * Translate the menu origin such that the cursor hot point will be in the
+ * center of the desired current selection and pane.
+ * If the current selection pointer is NULL then assume that the hot point
+ * will be in the center of the current pane flag.
+ */
+
+ if (s_ptr == NULL) {
+ /*
+ * Translate from the center of the pane flag to the upper left
+ * of the current pane window.
+ */
+ l_orig_x = x_pos - (menu->p_width >> 1) - menu->p_bdr_width;
+ l_orig_y = y_pos - (menu->flag_height >> 1) - menu->p_bdr_width;
+ }
+ else {
+ /*
+ * First translate from the center of the current selection
+ * to the upper left of the current selection window.
+ */
+ l_orig_x = x_pos - (menu->s_width >> 1);
+ l_orig_y = y_pos - (menu->s_height >> 1);
+
+ /*
+ * Then translate to the upper left of the current pane window.
+ */
+ l_orig_x -= (s_ptr->window_x + menu->p_bdr_width);
+ l_orig_y -= (s_ptr->window_y + menu->p_bdr_width);
+ }
+
+ /*
+ * Finally translate to the upper left of the menu.
+ */
+ l_orig_x -= (p_ptr->window_x - menu->x_pos);
+ l_orig_y -= (p_ptr->window_y - menu->y_pos);
+
+ /*
+ * Set the return values.
+ */
+ *orig_x = l_orig_x;
+ *orig_y = l_orig_y;
+}
+
+/*
+ * _XMRefreshPane - Internal subroutine to completely refresh
+ * the contents of a pane.
+ */
+_XMRefreshPane(display, menu, pane)
+ register Display *display;
+ register XMenu *menu;
+ register XMPane *pane;
+{
+ register XMSelect *s_list = pane->s_list;
+ register XMSelect *s_ptr;
+
+ /*
+ * First clear the pane.
+ */
+ XClearWindow(display, pane->window);
+ if (!pane->activated) {
+ XFillRectangle(display,
+ pane->window,
+ menu->inverse_select_GC,
+ pane->label_x - menu->p_fnt_pad,
+ pane->label_uy - menu->p_fnt_info->max_bounds.ascent - menu->p_fnt_pad,
+ pane->label_width + (menu->p_fnt_pad << 1),
+ menu->flag_height);
+
+ XFillRectangle(display,
+ pane->window,
+ menu->inverse_select_GC,
+ pane->label_x - menu->p_fnt_pad,
+ pane->label_ly - menu->p_fnt_info->max_bounds.ascent - menu->p_fnt_pad,
+ pane->label_width + (menu->p_fnt_pad << 1),
+ menu->flag_height);
+ }
+ if (!pane->active) {
+ XDrawString(display,
+ pane->window,
+ menu->inact_GC,
+ pane->label_x, pane->label_uy,
+ pane->label, pane->label_length);
+ XDrawString(display,
+ pane->window,
+ menu->inact_GC,
+ pane->label_x, pane->label_ly,
+ pane->label, pane->label_length);
+ }
+ else {
+ XDrawString(display,
+ pane->window,
+ menu->pane_GC,
+ pane->label_x, pane->label_uy,
+ pane->label, pane->label_length);
+ XDrawString(display,
+ pane->window,
+ menu->pane_GC,
+ pane->label_x, pane->label_ly,
+ pane->label, pane->label_length);
+
+ /*
+ * Finally refresh each selection if the pane is activated.
+ */
+ if (pane->activated) {
+ for (s_ptr = s_list->next; s_ptr != s_list; s_ptr = s_ptr->next)
+ _XMRefreshSelection(display, menu, s_ptr);
+ }
+ }
+}
+
+
+
+
+/*
+ * _XMRefreshSelection - Internal subroutine that refreshes
+ * a single selection window.
+ */
+_XMRefreshSelection(display, menu, select)
+ register Display *display;
+ register XMenu *menu;
+ register XMSelect *select;
+{
+ register int width = select->window_w;
+ register int height = select->window_h;
+ register int bdr_width = menu->s_bdr_width;
+
+ if (select->activated) {
+ if (menu->menu_mode == INVERT) {
+ XFillRectangle(display,
+ select->parent_p->window,
+ menu->normal_select_GC,
+ select->window_x, select->window_y,
+ width, height);
+ XDrawString(display,
+ select->parent_p->window,
+ menu->inverse_select_GC,
+ select->label_x,
+ select->label_y,
+ select->label, select->label_length);
+ }
+ else {
+ /*
+ * Using BOX mode.
+ * Since most drawing routines with arbitrary width lines
+ * are slow compared to raster-ops lets use a raster-op to
+ * draw the boxes.
+ */
+
+ XDrawRectangle(display,
+ select->parent_p->window,
+ menu->normal_select_GC,
+ select->window_x + (bdr_width >> 1),
+ select->window_y + (bdr_width >> 1 ),
+ width - bdr_width,
+ height - bdr_width);
+ XDrawString(display,
+ select->parent_p->window,
+ menu->normal_select_GC,
+ select->label_x,
+ select->label_y,
+ select->label, select->label_length);
+ }
+ }
+ else {
+ XClearArea(display,
+ select->parent_p->window,
+ select->window_x, select->window_y,
+ width, height,
+ False);
+ if (select->active) {
+ XDrawString(display,
+ select->parent_p->window,
+ menu->normal_select_GC,
+ select->label_x,
+ select->label_y,
+ select->label, select->label_length);
+ }
+ else {
+ XDrawString(display,
+ select->parent_p->window,
+ menu->inact_GC,
+ select->label_x,
+ select->label_y,
+ select->label, select->label_length);
+ }
+ }
+}
+
diff --git a/oldXMenu/Locate.c b/oldXMenu/Locate.c
new file mode 100644
index 00000000000..ab7263fb038
--- /dev/null
+++ b/oldXMenu/Locate.c
@@ -0,0 +1,78 @@
+#include "copyright.h"
+
+/* $Header: Locate.c,v 1.5 88/02/02 19:09:02 jim Exp $ */
+/* Copyright Massachusetts Institute of Technology 1985 */
+
+/*
+ * XMenu: MIT Project Athena, X Window system menu package
+ *
+ * XMenuLocate - Return data necessary to position and locate
+ * a menu on the screen.
+ *
+ * Author: Tony Della Fera, DEC
+ * January 11, 1985
+ *
+ */
+
+#include "XMenuInt.h"
+
+int
+XMenuLocate(display, menu, p_num, s_num, x_pos, y_pos, ul_x, ul_y, width, height)
+ register Display *display; /* Previously opened display. */
+ register XMenu *menu; /* Menu object being located. */
+ int p_num; /* Active pane number. */
+ int s_num; /* Active selection number. */
+ int x_pos; /* X coordinate of mouse active position. */
+ int y_pos; /* Y coordinate of mouse active position. */
+ int *ul_x; /* Returned upper left menu X coordinate. */
+ int *ul_y; /* Returned upper left menu Y coordinate. */
+ int *width; /* Returned menu width. */
+ int *height; /* Returned menu height. */
+{
+ register XMPane *p_ptr; /* XMPane pointer. */
+ register XMSelect *s_ptr; /* XMSelect pointer. */
+
+ /*
+ * Are the position arguments positive?
+ */
+ if ((x_pos <= 0) || (y_pos <= 0)) {
+ _XMErrorCode = XME_ARG_BOUNDS;
+ return(XM_FAILURE);
+ }
+
+ /*
+ * Find the right pane.
+ */
+ p_ptr = _XMGetPanePtr(menu, p_num);
+ if (p_ptr == NULL) return(XM_FAILURE);
+
+ /*
+ * Find the right selection.
+ */
+ s_ptr = _XMGetSelectionPtr(p_ptr, s_num);
+
+ /*
+ * Check to see that the menu's dependencies have been
+ * recomputed and are up to date. If not, do it now.
+ */
+ if (menu->recompute) XMenuRecompute(display, menu);
+
+ /*
+ * Compute the new menu origin such that the active point lies
+ * in the center of the desired active pane and selection.
+ * This sets the values of ul_x and ul_y.
+ */
+ _XMTransToOrigin(display, menu, p_ptr, s_ptr, x_pos, y_pos, ul_x, ul_y);
+
+ /*
+ * Set remaining return argument values.
+ */
+ *width = menu->width;
+ *height = menu->height;
+
+ /*
+ * Return successfully.
+ */
+ _XMErrorCode = XME_NO_ERROR;
+ return(XM_SUCCESS);
+}
diff --git a/oldXMenu/Makefile b/oldXMenu/Makefile
new file mode 100644
index 00000000000..da1934a69d4
--- /dev/null
+++ b/oldXMenu/Makefile
@@ -0,0 +1,90 @@
+# Uncomment following line if linking temacs complains about missing insque.
+# EXTRA=insque.o
+
+ AS = as
+# CC = cc
+ CPP = /lib/cpp
+ LD = ld
+ TAGS = etags
+ RM = rm -f
+ MV = mv
+ LN = ln -s
+ RANLIB = ranlib
+ AR = ar clq
+ LS = ls
+ LINTOPTS = -axz
+ LINTLIBFLAG = -C
+ MAKE = make
+ STD_DEFINES =
+ CDEBUGFLAGS = -O
+ RM_CMD = $(RM) *.CKP *.ln *.BAK *.bak *.o core errs ,* *~ *.a \
+ tags TAGS make.log
+
+SRCS = Activate.c \
+ AddPane.c \
+ AddSel.c \
+ ChgPane.c \
+ ChgSel.c \
+ Create.c \
+ DelPane.c \
+ DelSel.c \
+ Destroy.c \
+ Error.c \
+ EvHand.c \
+ FindPane.c \
+ FindSel.c \
+ InsPane.c \
+ InsSel.c \
+ Internal.c \
+ Locate.c \
+ Post.c \
+ Recomp.c \
+ SetAEQ.c \
+ SetFrz.c \
+ SetPane.c \
+ SetSel.c \
+ XDelAssoc.c XLookAssoc.c XCrAssoc.c XDestAssoc.c XMakeAssoc.c
+
+OBJS = Activate.o \
+ AddPane.o \
+ AddSel.o \
+ ChgPane.o \
+ ChgSel.o \
+ Create.o \
+ DelPane.o \
+ DelSel.o \
+ Destroy.o \
+ Error.o \
+ EvHand.o \
+ FindPane.o \
+ FindSel.o \
+ InsPane.o \
+ InsSel.o \
+ Internal.o \
+ Locate.o \
+ Post.o \
+ Recomp.o \
+ SetAEQ.o \
+ SetFrz.o \
+ SetPane.o \
+ SetSel.o \
+ XDelAssoc.o XLookAssoc.o XCrAssoc.o XDestAssoc.o XMakeAssoc.o
+
+.c.o:
+ $(RM) $@
+ $(CC) -c $(CFLAGS) $*.c
+
+all:: libXMenu11.a
+
+libXMenu11.a: $(OBJS) $(EXTRA)
+ $(RM) $@
+ $(AR) $@ $(OBJS) $(EXTRA)
+ -$(RANLIB) $@
+#If running ranlib fails, probably there is none.
+#That's ok. So don't stop the build.
+
+distclean: clean
+clean::
+ $(RM_CMD) \#* libXMenu11.a *.o
+tags::
+ $(TAGS) -t *.[ch]
diff --git a/oldXMenu/Post.c b/oldXMenu/Post.c
new file mode 100644
index 00000000000..f2429ac89d5
--- /dev/null
+++ b/oldXMenu/Post.c
@@ -0,0 +1,85 @@
+#include "copyright.h"
+
+/* $Header: Post.c,v 1.3 87/12/20 12:05:40 rws Exp $ */
+/* Copyright Massachusetts Institute of Technology 1985 */
+
+/*
+ * XMenu: MIT Project Athena, X Window system menu package
+ *
+ * XMenuPost - Maps a given menu to the display and activates
+ * the menu for user selection. The user is allowed to
+ * specify the mouse button event mask that will be used
+ * to identify a selection request. When a selection
+ * request is recieved (i.e., when the specified mouse
+ * event occurs) the data returned will be either the
+ * data associated with the particular selection active
+ * at the time of the selection request or NULL if no
+ * selection was active. A menu selection is shown to
+ * be active by placing a highlight box around the
+ * selection as the mouse cursor enters its active
+ * region. Inactive selections will not be highlighted.
+ * As the mouse cursor moved from one menu pane
+ * to another menu pane the pane being entered is raised
+ * and activated and the pane being left is inactivated.
+ * If an error occurs NULL will be returned with the
+ * p_num set to POST_ERROR, s_num set to
+ * NO_SELECTION and _XMErrorCode set to an
+ * appropriate value.
+ * Every time the routine returns successfully the
+ * p_num and s_num indices will be set to indicate
+ * the currently active pane and/or selection. If the
+ * mouse was not in a selection window at the time
+ * s_num will be set to NO_SELECTION.
+ *
+ * Author: Tony Della Fera, DEC
+ * August, 1984
+ *
+ */
+
+#include "XMenuInt.h"
+
+char *
+XMenuPost(display, menu, p_num, s_num, x_pos, y_pos, event_mask)
+ register Display *display; /* Previously opened display. */
+ register XMenu *menu; /* Menu to post. */
+ register int *p_num; /* Pane number selected. */
+ register int *s_num; /* Selection number selected. */
+ register int x_pos; /* X coordinate of menu position. */
+ register int y_pos; /* Y coordinate of menu position. */
+ int event_mask; /* Mouse button event mask. */
+{
+ register int stat; /* Routine call return status. */
+ char *data; /* Return data. */
+
+ /*
+ * Set up initial pane and selection assumptions.
+ */
+
+ /*
+ * Make the procedure call.
+ */
+ stat = XMenuActivate(
+ display,
+ menu,
+ p_num, s_num,
+ x_pos, y_pos,
+ event_mask,
+ &data);
+
+ /*
+ * Check the return value and return accordingly.
+ */
+ switch (stat) {
+ case XM_FAILURE:
+ *p_num = POST_ERROR;
+ *s_num = NO_SELECTION;
+ return(NULL);
+ case XM_NO_SELECT:
+ case XM_IA_SELECT:
+ *s_num = NO_SELECTION;
+ return(NULL);
+ case XM_SUCCESS:
+ default:
+ return(data);
+ }
+}
diff --git a/oldXMenu/README b/oldXMenu/README
new file mode 100644
index 00000000000..c9d76894a91
--- /dev/null
+++ b/oldXMenu/README
@@ -0,0 +1,4 @@
+As of Release 2 of the X Window System, Version 11 from MIT, the XMenu
+library no longer supported. It is not used in any software supplied
+by MIT and its use is not encouraged.
+
diff --git a/oldXMenu/Recomp.c b/oldXMenu/Recomp.c
new file mode 100644
index 00000000000..69153656b1b
--- /dev/null
+++ b/oldXMenu/Recomp.c
@@ -0,0 +1,104 @@
+#include "copyright.h"
+
+/* $Header: Recomp.c,v 1.5 87/12/20 12:05:46 rws Exp $ */
+/* Copyright Massachusetts Institute of Technology 1985 */
+
+/*
+ * XMenu: MIT Project Athena, X Window system menu package
+ *
+ * XMenuRecompute - Recompute XMenu object dependencies.
+ *
+ * Author: Tony Della Fera, DEC
+ * September, 1985
+ *
+ */
+
+#include "XMenuInt.h"
+
+int
+XMenuRecompute(display, menu)
+ Display *display;
+ register XMenu *menu; /* Menu object to be recomputed. */
+{
+ register XMPane *p_ptr; /* Pane pointer. */
+ register XMSelect *s_ptr; /* Selection pointer. */
+
+ register int p_num; /* Pane serial number. */
+ register int s_num; /* Selection serial number. */
+
+ /*
+ * If there are no panes in the menu then return failure
+ * beacuse the menu is not initialized.
+ */
+ if (menu->p_count == 0) {
+ _XMErrorCode = XME_NOT_INIT;
+ return(XM_FAILURE);
+ }
+
+ /*
+ * Recompute menu wide global values: pane window size,
+ * selection size and maximum selection count.
+ */
+ _XMRecomputeGlobals(display, menu);
+
+ /*
+ * For each pane in the menu...
+ */
+
+ p_num = 0;
+ for (
+ p_ptr = menu->p_list->next;
+ p_ptr != menu->p_list;
+ p_ptr = p_ptr->next
+ ){
+ /*
+ * Recompute pane dependencies.
+ */
+ if (_XMRecomputePane(display, menu, p_ptr, p_num) == _FAILURE) {
+ return(XM_FAILURE);
+ }
+ p_num++;
+
+ /*
+ * For each selection in the pane...
+ */
+ s_num = 0;
+ for (
+ s_ptr = p_ptr->s_list->next;
+ s_ptr != p_ptr->s_list;
+ s_ptr = s_ptr->next
+ ) {
+ /*
+ * Recompute selection dependencies.
+ */
+ if (_XMRecomputeSelection(display, menu, s_ptr, s_num) == _FAILURE) {
+ return(XM_FAILURE);
+ }
+ s_num++;
+ }
+ }
+
+ /*
+ * Recompute menu size.
+ */
+ if (menu->menu_style == CENTER) {
+ menu->width = menu->p_width + (menu->p_bdr_width << 1);
+ }
+ else {
+ menu->width = menu->p_width + (menu->p_bdr_width << 1) +
+ ((menu->p_count - 1) * menu->p_x_off);
+ }
+ menu->height = menu->p_height + (menu->p_bdr_width << 1) +
+ ((menu->p_count - 1) * menu->p_y_off);
+
+ /*
+ * Reset the recompute flag.
+ */
+ menu->recompute = 0;
+
+ /*
+ * Return successfully.
+ */
+ _XMErrorCode = XME_NO_ERROR;
+ return(XM_SUCCESS);
+}
diff --git a/oldXMenu/SetAEQ.c b/oldXMenu/SetAEQ.c
new file mode 100644
index 00000000000..03a09c7bf51
--- /dev/null
+++ b/oldXMenu/SetAEQ.c
@@ -0,0 +1,29 @@
+#include "copyright.h"
+
+/* $Header: SetAEQ.c,v 1.2 87/12/20 12:05:51 rws Exp $ */
+/* Copyright Massachusetts Institute of Technology 1985 */
+
+/*
+ * XMenu: MIT Project Athena, X Window system menu package
+ *
+ * XMenuSetAEQ - Set Asynchronous event queueing mode.
+ * When enabled asynchronous events will be queue while
+ * a menu is being displayed and restored to the X
+ * event queue when the menu is taken down.
+ *
+ * Author: Tony Della Fera, DEC
+ * March 12, 1986
+ *
+ */
+
+#include "XMenuInt.h"
+
+XMenuSetAEQ(menu, aeq)
+ register XMenu *menu; /* Menu object to be modified. */
+ register int aeq; /* AEQ mode? */
+{
+ /*
+ * Set the AEQ mode switch.
+ */
+ menu->aeq = aeq;
+}
diff --git a/oldXMenu/SetFrz.c b/oldXMenu/SetFrz.c
new file mode 100644
index 00000000000..dc1448cbc8a
--- /dev/null
+++ b/oldXMenu/SetFrz.c
@@ -0,0 +1,28 @@
+#include "copyright.h"
+
+/* $Header: SetFrz.c,v 1.2 87/12/20 12:05:56 rws Exp $ */
+/* Copyright Massachusetts Institute of Technology 1985 */
+
+/*
+ * XMenu: MIT Project Athena, X Window system menu package
+ *
+ * XMenuSetFreeze - Forcibly set the menu freeze mode switch
+ * overriding the Xdefaults setting.
+ * This is necessary in some situations.
+ *
+ * Author: Tony Della Fera, DEC
+ * January 29, 1986
+ *
+ */
+
+#include "XMenuInt.h"
+
+XMenuSetFreeze(menu, freeze)
+ register XMenu *menu; /* Menu object to be modified. */
+ register int freeze; /* Freeze mode? */
+{
+ /*
+ * Set the freeze mode switch.
+ */
+ menu->freeze = freeze;
+}
diff --git a/oldXMenu/SetPane.c b/oldXMenu/SetPane.c
new file mode 100644
index 00000000000..e2da3b910fc
--- /dev/null
+++ b/oldXMenu/SetPane.c
@@ -0,0 +1,43 @@
+#include "copyright.h"
+
+/* $Header: SetPane.c,v 1.4 87/12/20 12:06:03 rws Exp $ */
+/* Copyright Massachusetts Institute of Technology 1985 */
+
+/*
+ * XMenu: MIT Project Athena, X Window system menu package
+ *
+ * XMenuSetPane - Set a menu pane to be active or inactive.
+ *
+ * Author: Tony Della Fera, DEC
+ * August, 1985
+ *
+ */
+
+#include "XMenuInt.h"
+
+int
+XMenuSetPane(menu, p_num, active)
+ register XMenu *menu; /* Menu object to be modified. */
+ register int p_num; /* Pane number to be modified. */
+ register int active; /* Make selection active? */
+{
+ register XMPane *p_ptr; /* XMPane pointer. */
+
+ /*
+ * Find the right pane.
+ */
+ p_ptr = _XMGetPanePtr(menu, p_num);
+ if (p_ptr == NULL) return(XM_FAILURE);
+
+ /*
+ * Set its active switch.
+ */
+ p_ptr->active = active;
+ if (p_ptr->active == False) p_ptr->activated = False;
+
+ /*
+ * Return the pane number just set.
+ */
+ _XMErrorCode = XME_NO_ERROR;
+ return(p_num);
+}
diff --git a/oldXMenu/SetSel.c b/oldXMenu/SetSel.c
new file mode 100644
index 00000000000..9576876bed9
--- /dev/null
+++ b/oldXMenu/SetSel.c
@@ -0,0 +1,50 @@
+#include "copyright.h"
+
+/* $Header: SetSel.c,v 1.3 87/12/20 12:06:07 rws Exp $ */
+/* Copyright Massachusetts Institute of Technology 1985 */
+
+/*
+ * XMenu: MIT Project Athena, X Window system menu package
+ *
+ * XMenuSetSelection - Set a menu selection to be active or inactive.
+ *
+ * Author: Tony Della Fera, DEC
+ * August, 1985
+ *
+ */
+
+#include "XMenuInt.h"
+
+int
+XMenuSetSelection(menu, p_num, s_num, active)
+ register XMenu *menu; /* Menu object to be modified. */
+ register int p_num; /* Pane number to be modified. */
+ register int s_num; /* Selection number to modified. */
+ int active; /* Make selection active? */
+{
+ register XMPane *p_ptr; /* XMPane pointer. */
+ register XMSelect *s_ptr; /* XMSelect pointer. */
+
+ /*
+ * Find the right pane.
+ */
+ p_ptr = _XMGetPanePtr(menu, p_num);
+ if (p_ptr == NULL) return(XM_FAILURE);
+
+ /*
+ * Find the right selection.
+ */
+ s_ptr = _XMGetSelectionPtr(p_ptr, s_num);
+ if (s_ptr == NULL) return(XM_FAILURE);
+
+ /*
+ * Set its active switch.
+ */
+ s_ptr->active = active;
+
+ /*
+ * Return the selection number just set.
+ */
+ _XMErrorCode = XME_NO_ERROR;
+ return(s_num);
+}
diff --git a/oldXMenu/X10.h b/oldXMenu/X10.h
new file mode 100644
index 00000000000..5b802a8bed8
--- /dev/null
+++ b/oldXMenu/X10.h
@@ -0,0 +1,78 @@
+/* $Header: X10.h,v 8.1 89/07/27 14:16:10 merge Exp $ */
+/*
+ * Copyright 1985, 1986, 1987 by the Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of M.I.T. not be used in advertising
+ * or publicity pertaining to distribution of the software without specific,
+ * written prior permission. M.I.T. makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * The X Window System is a Trademark of MIT.
+ *
+ */
+
+
+/*
+ * X10.h - Header definition and support file for the C subroutine
+ * interface library for V10 support routines.
+ */
+#ifndef _X10_H_
+#define _X10_H_
+
+/* Used in XDraw and XDrawFilled */
+
+typedef struct {
+ short x, y;
+ unsigned short flags;
+} Vertex;
+
+/* The meanings of the flag bits. If the bit is 1 the predicate is true */
+
+#define VertexRelative 0x0001 /* else absolute */
+#define VertexDontDraw 0x0002 /* else draw */
+#define VertexCurved 0x0004 /* else straight */
+#define VertexStartClosed 0x0008 /* else not */
+#define VertexEndClosed 0x0010 /* else not */
+/*#define VertexDrawLastPoint 0x0020 */ /* else don't */
+
+/*
+The VertexDrawLastPoint option has not been implemented in XDraw and
+XDrawFilled so it shouldn't be defined.
+*/
+
+/*
+ * XAssoc - Associations used in the XAssocTable data structure. The
+ * associations are used as circular queue entries in the association table
+ * which is contains an array of circular queues (buckets).
+ */
+typedef struct _XAssoc {
+ struct _XAssoc *next; /* Next object in this bucket. */
+ struct _XAssoc *prev; /* Previous obejct in this bucket. */
+ Display *display; /* Display which ownes the id. */
+ XID x_id; /* X Window System id. */
+ char *data; /* Pointer to untyped memory. */
+} XAssoc;
+
+/*
+ * XAssocTable - X Window System id to data structure pointer association
+ * table. An XAssocTable is a hash table whose buckets are circular
+ * queues of XAssoc's. The XAssocTable is constructed from an array of
+ * XAssoc's which are the circular queue headers (bucket headers).
+ * An XAssocTable consists an XAssoc pointer that points to the first
+ * bucket in the bucket array and an integer that indicates the number
+ * of buckets in the array.
+ */
+typedef struct {
+ XAssoc *buckets; /* Pointer to first bucket in bucket array.*/
+ int size; /* Table size (number of buckets). */
+} XAssocTable;
+
+XAssocTable *XCreateAssocTable();
+char *XLookUpAssoc();
+
+#endif /* _X10_H_ */
diff --git a/oldXMenu/XCrAssoc.c b/oldXMenu/XCrAssoc.c
new file mode 100644
index 00000000000..6074a3b089b
--- /dev/null
+++ b/oldXMenu/XCrAssoc.c
@@ -0,0 +1,67 @@
+/* $XConsortium: XCrAssoc.c,v 10.17 91/01/06 12:04:57 rws Exp $ */
+/* Copyright Massachusetts Institute of Technology 1985 */
+
+/*
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation, and that the name of M.I.T. not be used in advertising or
+publicity pertaining to distribution of the software without specific,
+written prior permission. M.I.T. makes no representations about the
+suitability of this software for any purpose. It is provided "as is"
+without express or implied warranty.
+*/
+
+#include "X11/Xlib.h"
+#include "X10.h"
+#include "errno.h"
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+extern int errno;
+
+/*
+ * XCreateAssocTable - Create an XAssocTable. The size argument should be
+ * a power of two for efficiency reasons. Some size suggestions: use 32
+ * buckets per 100 objects; a reasonable maximum number of object per
+ * buckets is 8. If there is an error creating the XAssocTable, a NULL
+ * pointer is returned.
+ */
+XAssocTable *XCreateAssocTable(size)
+ register int size; /* Desired size of the table. */
+{
+ register XAssocTable *table; /* XAssocTable to be initialized. */
+ register XAssoc *buckets; /* Pointer to the first bucket in */
+ /* the bucket array. */
+
+ /* Malloc the XAssocTable. */
+ if ((table = (XAssocTable *)malloc(sizeof(XAssocTable))) == NULL) {
+ /* malloc call failed! */
+ errno = ENOMEM;
+ return(NULL);
+ }
+
+ /* malloc the buckets (actually just their headers). */
+ buckets = (XAssoc *)calloc((unsigned)size, (unsigned)sizeof(XAssoc));
+ if (buckets == NULL) {
+ /* calloc call failed! */
+ errno = ENOMEM;
+ return(NULL);
+ }
+
+ /* Insert table data into the XAssocTable structure. */
+ table->buckets = buckets;
+ table->size = size;
+
+ while (--size >= 0) {
+ /* Initialize each bucket. */
+ buckets->prev = buckets;
+ buckets->next = buckets;
+ buckets++;
+ }
+
+ return(table);
+}
diff --git a/oldXMenu/XDelAssoc.c b/oldXMenu/XDelAssoc.c
new file mode 100644
index 00000000000..f45509cd143
--- /dev/null
+++ b/oldXMenu/XDelAssoc.c
@@ -0,0 +1,72 @@
+/* $XConsortium: XDelAssoc.c,v 10.19 91/01/06 12:06:39 rws Exp $ */
+/* Copyright Massachusetts Institute of Technology 1985 */
+
+/*
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation, and that the name of M.I.T. not be used in advertising or
+publicity pertaining to distribution of the software without specific,
+written prior permission. M.I.T. makes no representations about the
+suitability of this software for any purpose. It is provided "as is"
+without express or implied warranty.
+*/
+
+/* #include "X11/Xlibint.h" */
+#include "X11/Xlib.h"
+#include "X10.h"
+void remque();
+struct qelem {
+ struct qelem *q_forw;
+ struct qelem *q_back;
+ char q_data[1];
+};
+
+/*
+ * XDeleteAssoc - Delete an association in an XAssocTable keyed on
+ * an XId. An association may be removed only once. Redundant
+ * deletes are meaningless (but cause no problems).
+ */
+XDeleteAssoc(dpy, table, x_id)
+ register Display *dpy;
+ register XAssocTable *table;
+ register XID x_id;
+{
+ int hash;
+ register XAssoc *bucket;
+ register XAssoc *Entry;
+
+ /* Hash the XId to get the bucket number. */
+ hash = x_id & (table->size - 1);
+ /* Look up the bucket to get the entries in that bucket. */
+ bucket = &table->buckets[hash];
+ /* Get the first entry in the bucket. */
+ Entry = bucket->next;
+
+ /* Scan through the entries in the bucket for the right XId. */
+ for (; Entry != bucket; Entry = Entry->next) {
+ if (Entry->x_id == x_id) {
+ /* We have the right XId. */
+ if (Entry->display == dpy) {
+ /* We have the right display. */
+ /* We have the right entry! */
+ /* Remove it from the queue and */
+ /* free the entry. */
+ remque((struct qelem *)Entry);
+ free((char *)Entry);
+ return;
+ }
+ /* Oops, identical XId's on different displays! */
+ continue;
+ }
+ if (Entry->x_id > x_id) {
+ /* We have gone past where it should be. */
+ /* It is apparently not in the table. */
+ return;
+ }
+ }
+ /* It is apparently not in the table. */
+ return;
+}
+
diff --git a/oldXMenu/XDestAssoc.c b/oldXMenu/XDestAssoc.c
new file mode 100644
index 00000000000..4afffbb77e2
--- /dev/null
+++ b/oldXMenu/XDestAssoc.c
@@ -0,0 +1,49 @@
+/* $XConsortium: XDestAssoc.c,v 10.17 91/02/08 13:11:50 rws Exp $ */
+/* Copyright Massachusetts Institute of Technology 1985 */
+
+/*
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation, and that the name of M.I.T. not be used in advertising or
+publicity pertaining to distribution of the software without specific,
+written prior permission. M.I.T. makes no representations about the
+suitability of this software for any purpose. It is provided "as is"
+without express or implied warranty.
+*/
+
+#include "X11/Xlib.h"
+#include "X10.h"
+
+/*
+ * XDestroyAssocTable - Destroy (free the memory associated with)
+ * an XAssocTable.
+ */
+XDestroyAssocTable(table)
+ register XAssocTable *table;
+{
+ register int i;
+ register XAssoc *bucket;
+ register XAssoc *Entry, *entry_next;
+
+ /* Free the buckets. */
+ for (i = 0; i < table->size; i++) {
+ bucket = &table->buckets[i];
+ for (
+ Entry = bucket->next;
+ Entry != bucket;
+ Entry = entry_next
+ ) {
+ entry_next = Entry->next;
+ free((char *)Entry);
+ }
+ }
+
+ /* Free the bucket array. */
+ free((char *)table->buckets);
+
+ /* Free the table. */
+ free((char *)table);
+}
+
diff --git a/oldXMenu/XLookAssoc.c b/oldXMenu/XLookAssoc.c
new file mode 100644
index 00000000000..a7a5d77f83d
--- /dev/null
+++ b/oldXMenu/XLookAssoc.c
@@ -0,0 +1,67 @@
+/* $XConsortium: XLookAssoc.c,v 10.16 91/01/06 12:09:24 rws Exp $ */
+/* Copyright Massachusetts Institute of Technology 1985 */
+
+/*
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation, and that the name of M.I.T. not be used in advertising or
+publicity pertaining to distribution of the software without specific,
+written prior permission. M.I.T. makes no representations about the
+suitability of this software for any purpose. It is provided "as is"
+without express or implied warranty.
+*/
+
+#include "X11/Xlib.h"
+#include "X10.h"
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+/*
+ * XLookUpAssoc - Retrieve the data stored in an XAssocTable by its XId.
+ * If an appropriately matching XId can be found in the table the routine will
+ * return apointer to the data associated with it. If the XId can not be found
+ * in the table the routine will return a NULL pointer. All XId's are relative
+ * to the currently active Display.
+ */
+caddr_t XLookUpAssoc(dpy, table, x_id)
+ register Display *dpy;
+ register XAssocTable *table; /* XAssocTable to search in. */
+ register XID x_id; /* XId to search for. */
+{
+ int hash;
+ register XAssoc *bucket;
+ register XAssoc *Entry;
+
+ /* Hash the XId to get the bucket number. */
+ hash = x_id & (table->size - 1);
+ /* Look up the bucket to get the entries in that bucket. */
+ bucket = &table->buckets[hash];
+ /* Get the first entry in the bucket. */
+ Entry = bucket->next;
+
+ /* Scan through the entries in the bucket for the right XId. */
+ for (; Entry != bucket; Entry = Entry->next) {
+ if (Entry->x_id == x_id) {
+ /* We have the right XId. */
+ if (Entry->display == dpy) {
+ /* We have the right display. */
+ /* We have the right entry! */
+ return(Entry->data);
+ }
+ /* Oops, identical XId's on different displays! */
+ continue;
+ }
+ if (Entry->x_id > x_id) {
+ /* We have gone past where it should be. */
+ /* It is apparently not in the table. */
+ return(NULL);
+ }
+ }
+ /* It is apparently not in the table. */
+ return(NULL);
+}
+
diff --git a/oldXMenu/XMakeAssoc.c b/oldXMenu/XMakeAssoc.c
new file mode 100644
index 00000000000..6791b7aa47b
--- /dev/null
+++ b/oldXMenu/XMakeAssoc.c
@@ -0,0 +1,107 @@
+/* $XConsortium: XMakeAssoc.c,v 10.18 91/01/06 12:09:28 rws Exp $ */
+/* Copyright Massachusetts Institute of Technology 1985 */
+
+/*
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation, and that the name of M.I.T. not be used in advertising or
+publicity pertaining to distribution of the software without specific,
+written prior permission. M.I.T. makes no representations about the
+suitability of this software for any purpose. It is provided "as is"
+without express or implied warranty.
+*/
+
+#include "X11/Xlib.h"
+#include "X10.h"
+#include <errno.h>
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+extern int errno;
+
+extern int (*_XIOErrorFunction)(); /* X system error reporting routine. */
+
+void insque();
+struct qelem {
+ struct qelem *q_forw;
+ struct qelem *q_back;
+ char q_data[1];
+};
+/*
+ * XMakeAssoc - Insert data into an XAssocTable keyed on an XId.
+ * Data is inserted into the table only once. Redundant inserts are
+ * meaningless (but cause no problems). The queue in each association
+ * bucket is sorted (lowest XId to highest XId).
+ */
+XMakeAssoc(dpy, table, x_id, data)
+ register Display *dpy;
+ register XAssocTable *table;
+ register XID x_id;
+ register caddr_t data;
+{
+ int hash;
+ register XAssoc *bucket;
+ register XAssoc *Entry;
+ register XAssoc *new_entry;
+
+ /* Hash the XId to get the bucket number. */
+ hash = x_id & (table->size - 1);
+ /* Look up the bucket to get the entries in that bucket. */
+ bucket = &table->buckets[hash];
+ /* Get the first entry in the bucket. */
+ Entry = bucket->next;
+
+ /* If (Entry != bucket), the bucket is empty so make */
+ /* the new entry the first entry in the bucket. */
+ /* if (Entry == bucket), the we have to search the */
+ /* bucket. */
+ if (Entry != bucket) {
+ /* The bucket isn't empty, begin searching. */
+ /* If we leave the for loop then we have either passed */
+ /* where the entry should be or hit the end of the bucket. */
+ /* In either case we should then insert the new entry */
+ /* before the current value of "Entry". */
+ for (; Entry != bucket; Entry = Entry->next) {
+ if (Entry->x_id == x_id) {
+ /* Entry has the same XId... */
+ if (Entry->display == dpy) {
+ /* Entry has the same Display... */
+ /* Therefore there is already an */
+ /* entry with this XId and Display, */
+ /* reset its data value and return. */
+ Entry->data = data;
+ return;
+ }
+ /* We found an association with the right */
+ /* id but the wrong display! */
+ continue;
+ }
+ /* If the current entry's XId is greater than the */
+ /* XId of the entry to be inserted then we have */
+ /* passed the location where the new XId should */
+ /* be inserted. */
+ if (Entry->x_id > x_id) break;
+ }
+ }
+
+ /* If we are here then the new entry should be inserted just */
+ /* before the current value of "Entry". */
+ /* Create a new XAssoc and load it with new provided data. */
+ new_entry = (XAssoc *) malloc(sizeof(XAssoc));
+ if (new_entry == NULL) {
+ /* Malloc failed! */
+ errno = ENOMEM;
+ (*_XIOErrorFunction)(dpy);
+ }
+ new_entry->display = dpy;
+ new_entry->x_id = x_id;
+ new_entry->data = data;
+
+ /* Insert the new entry. */
+ insque((struct qelem *)new_entry, (struct qelem *)Entry->prev);
+}
+
diff --git a/oldXMenu/XMenu.h b/oldXMenu/XMenu.h
new file mode 100644
index 00000000000..2405f3cb9d0
--- /dev/null
+++ b/oldXMenu/XMenu.h
@@ -0,0 +1,262 @@
+#include "copyright.h"
+
+/* $Header: XMenu.h,v 1.5 87/12/04 10:26:47 swick Exp $ */
+/* Copyright Massachusetts Institute of Technology 1985 */
+
+/*
+ * XMenu: MIT Project Athena, X Window system menu package
+ *
+ * XMenu.h - Include file for the MIT Project Athena
+ * XMenu X window system menu package.
+ *
+ * Author: Tony Della Fera, DEC
+ * August, 1984
+ */
+
+#ifndef _XMenu_h_
+#define _XMenu_h_
+
+#include <X11/Xutil.h>
+#include "X10.h"
+
+#define FAILURE -1
+#define SUCCESS 1
+#define POST_ERROR -1
+#define NO_SELECTION -1
+
+#define XM_FAILURE -1
+#define XM_SUCCESS 1
+#define XM_NO_SELECT 2
+#define XM_IA_SELECT 3
+
+#define XME_CODE_COUNT 17
+
+#define XME_NO_ERROR 0
+#define XME_NOT_INIT 1
+#define XME_ARG_BOUNDS 2
+#define XME_P_NOT_FOUND 3
+#define XME_S_NOT_FOUND 4
+#define XME_STYLE_PARAM 5
+#define XME_GRAB_MOUSE 6
+#define XME_INTERP_LOC 7
+#define XME_CALLOC 8
+#define XME_CREATE_ASSOC 9
+#define XME_STORE_BITMAP 10
+#define XME_MAKE_TILES 11
+#define XME_MAKE_PIXMAP 12
+#define XME_CREATE_CURSOR 13
+#define XME_OPEN_FONT 14
+#define XME_CREATE_WINDOW 15
+#define XME_CREATE_TRANSP 16
+
+/*
+ * XMenu error code and error list definitions.
+ */
+extern int _XMErrorCode;
+extern char *_XMErrorList[];
+
+/*
+ * Define the XMWindow datatypes.
+ *
+ * An XMWindow is either an XMPane or an XMSelect.
+ *
+ * XMWindow is wrapper used to identify the constant window
+ * information that makes up XMPane and XMSelect objects.
+ *
+ * An XMPane is a menu pane made up of one or more XMSelect and a label.
+ *
+ * An XMSelect is a menu selection object with a label and a data pointer.
+ */
+typedef enum _xmwintype {PANE, SELECTION, PL_HEADER, SL_HEADER} XMWType;
+
+typedef struct _xmwindow {
+ struct _xmwindow *next; /* Next obj pointer (for insque). */
+ struct _xmwindow *prev; /* Prev obj pointer (for insque). */
+ XMWType type; /* Type of window. */
+ Window window; /* X Window Id. */
+ int window_x; /* Window upper left X coordinate. */
+ int window_y; /* Window upper left y coordinate. */
+ int window_w; /* Window width. */
+ int window_h; /* Window height. */
+ int active; /* Window active? */
+ int activated; /* Window activated? */
+ int pad_l1; /* ---- */
+ char *pad_l2; /* ---- */
+ int pad_l3; /* ---- */
+ int pad_l4; /* ---- */
+ int pad_l5; /* ---- */
+ int pad_l6; /* ---- */
+ int pad_l7; /* ---- */
+ int pad_l8; /* ---- */
+ struct _xmwindow *pad_l9; /* ---- */
+ char *pad_l10; /* ---- */
+ struct _xmwindow *pad_l11; /* ---- */
+} XMWindow;
+
+typedef struct _xmpane {
+ struct _xmpane *next; /* Next obj pointer (for insque). */
+ struct _xmpane *prev; /* Prev obj pointer (for insque). */
+ XMWType type; /* Type of window. */
+ Window window; /* X Window Id. */
+ int window_x; /* Window upper left X coordinate. */
+ int window_y; /* Window upper left y coordinate. */
+ int window_w; /* Window width. */
+ int window_h; /* Window height. */
+ int active; /* Window active? */
+ int activated; /* Window activated? */
+ int serial; /* -- Pane serial number. */
+ char *label; /* -- Pane label. */
+ int label_width; /* -- Pane label width in pixels. */
+ int label_length; /* -- Pane label length in chars. */
+ int label_x; /* -- Pane label X offset. */
+ int label_uy; /* -- Pane label upper Y offset. */
+ int label_ly; /* -- Pane label lower Y offset. */
+ int s_count; /* -- Selections in this pane. */
+ struct _xmselect *s_list; /* -- Selection window list. */
+ char *pad_l10; /* ---- */
+ struct _xmwindow *pad_l11; /* ---- */
+} XMPane;
+
+typedef struct _xmselect {
+ struct _xmselect *next; /* Next obj pointer (for insque). */
+ struct _xmselect *prev; /* Prev obj pointer (for insque). */
+ XMWType type; /* Type of window. */
+ Window window; /* X Window Id. */
+ Window parent; /* X Window id of parent window. */
+ int window_x; /* Window upper left X coordinate. */
+ int window_y; /* Window upper left y coordinate. */
+ int window_w; /* Window width. */
+ int window_h; /* Window height. */
+ int active; /* Window active? */
+ int activated; /* Window activated? */
+ int serial; /* -- Selection serial number. */
+ char *label; /* -- Selection label. */
+ int label_width; /* -- Selection label width in pixels. */
+ int label_length; /* -- Selection label length in chars. */
+ int label_x; /* -- Selection label X offset. */
+ int label_y; /* -- Selection label Y offset. */
+ int pad_l7; /* ---- */
+ int pad_l8; /* ---- */
+ struct _xmwindow *pad_l9; /* ---- */
+ char *data; /* -- Selection data pointer. */
+ struct _xmpane *parent_p; /* -- Selection parent pane structure. */
+} XMSelect;
+
+
+/*
+ * Define the XMStyle datatype.
+ *
+ * Menu presentation style information.
+ *
+ */
+typedef enum _xmstyle {
+ LEFT, /* Left oriented obejct. */
+ RIGHT, /* Right oriented obejct. */
+ CENTER /* Center oriented object. */
+} XMStyle;
+
+
+/*
+ * Define the XMMode datatype.
+ *
+ * Menu presentation mode information.
+ *
+ */
+typedef enum _xmmode {
+ BOX, /* BOXed graphic rendition. */
+ INVERT /* INVERTed graphic rendition. */
+} XMMode;
+
+
+/*
+ * Define the XMenu datatype.
+ *
+ * All dimensions are in pixels unless otherwise noted.
+ */
+typedef struct _xmenu {
+ /* -------------------- Menu data -------------------- */
+ XMStyle menu_style; /* Menu display style. */
+ XMMode menu_mode; /* Menu display mode. */
+ int freeze; /* Freeze server mode? */
+ int aeq; /* Asynchronous Event Queueing mode? */
+ int recompute; /* Recompute menu dependecies? */
+ Window parent; /* Menu's parent window. */
+ int width; /* Overall menu width. */
+ int height; /* Overall menu height. */
+ int x_pos; /* Oveall menu origin. */
+ int y_pos; /* Overall menu origin. */
+ Cursor mouse_cursor; /* Mouse cursor raster. */
+ XAssocTable *assoc_tab; /* XMWindow association table. */
+ XMPane *p_list; /* List of XMPanes. */
+ /* -------------------- Pane window data -------------------- */
+ XMStyle p_style; /* Pane display style. */
+ int p_events; /* Pane window X events. */
+ XFontStruct *p_fnt_info; /* Flag font info structure. */
+ GC pane_GC; /* Pane graphics context. */
+ int p_fnt_pad; /* Fixed flag font padding in pixels. */
+ double p_spread; /* Pane spread in flag height fractions. */
+ int p_bdr_width; /* Pane border width. */
+ int flag_height; /* Flag height. */
+ int p_width; /* Menu pane width. */
+ int p_height; /* Menu pane height. */
+ int p_x_off; /* Pane window X offset. */
+ int p_y_off; /* Pane window Y offset. */
+ int p_count; /* Number of panes per menu. */
+ /* -------------------- Selection window data -------------------- */
+ XMStyle s_style; /* Selection display style. */
+ int s_events; /* Selection window X events. */
+ XFontStruct *s_fnt_info; /* Body font info structure. */
+ int s_fnt_pad; /* Fixed body font padding in pixels. */
+ double s_spread; /* Select spread in line height fractions. */
+ int s_bdr_width; /* Select border width. */
+ int s_width; /* Selection window width. */
+ int s_height; /* Selection window height. */
+ int s_x_off; /* Selection window X offset. */
+ int s_y_off; /* Selection window Y offset. */
+ int s_count; /* Maximum number of selections per pane. */
+ GC normal_select_GC; /* GC used for inactive selections. */
+ GC inverse_select_GC; /* GC used for active (current) selection. */
+ GC inact_GC; /* GC used for inactive selections and */
+ /* panes headers. */
+ /* -------------------- Color data -------------------- */
+ unsigned long p_bdr_color; /* Color of pane border pixmap. */
+ unsigned long s_bdr_color; /* Color of selection border pixmap. */
+ unsigned long p_frg_color; /* Color of pane foreground pixmap. */
+ unsigned long s_frg_color; /* Color of selection pixmap. */
+ unsigned long bkgnd_color; /* Color of menu background pixmap. */
+ /* -------------------- Pixmap data -------------------- */
+ Pixmap p_bdr_pixmap; /* Pane border pixmap. */
+ Pixmap s_bdr_pixmap; /* Selection border pixmap. */
+ Pixmap p_frg_pixmap; /* Pane foreground pixmap. */
+ Pixmap s_frg_pixmap; /* Selection foreground pixmap. */
+ Pixmap bkgnd_pixmap; /* Menu background pixmap. */
+ Pixmap inact_pixmap; /* Menu inactive pixmap. */
+} XMenu;
+
+/*
+ * XMenu library routine declarations.
+ */
+XMenu *XMenuCreate();
+int XMenuAddPane();
+int XMenuAddSelection();
+int XMenuInsertPane();
+int XMenuInsertSelection();
+int XMenuFindPane();
+int XMenuFindSelection();
+int XMenuChangePane();
+int XMenuChangeSelection();
+int XMenuSetPane();
+int XMenuSetSelection();
+int XMenuRecompute();
+int XMenuEventHandler(); /* No value actually returned. */
+int XMenuLocate();
+int XMenuSetFreeze(); /* No value actually returned. */
+int XMenuActivate();
+char *XMenuPost();
+int XMenuDeletePane();
+int XMenuDeleteSelection();
+int XMenuDestroy(); /* No value actually returned. */
+char *XMenuError();
+
+#endif
+/* Don't add after this point. */
diff --git a/oldXMenu/XMenuInt.h b/oldXMenu/XMenuInt.h
new file mode 100644
index 00000000000..8ab5200819a
--- /dev/null
+++ b/oldXMenu/XMenuInt.h
@@ -0,0 +1,60 @@
+
+/* $Header: XMenuInt.h,v 1.1 87/08/04 10:29:03 toddb Exp $ */
+/* Copyright Massachusetts Institute of Technology 1985 */
+
+/*
+ * XMenu: MIT Project Athena, X Window system menu package
+ *
+ * XMenuInternal.h - Internal menu system include file for the
+ * MIT Project Athena XMenu X window system
+ * menu package.
+ *
+ * Author: Tony Della Fera, DEC
+ * October, 1985
+ */
+
+#ifndef _XMenuInternal_h_
+#define _XMenuInternal_h_
+
+#include <X11/Xlib.h>
+#include "X10.h"
+#include <stdio.h>
+#include "XMenu.h"
+
+#define min(x, y) ((x) <= (y) ? (x) : (y))
+#define max(x, y) ((x) >= (y) ? (x) : (y))
+#define abs(a) ((a) < 0 ? -(a) : (a))
+
+#define _X_FAILURE -1
+
+#define _SUCCESS 1
+#define _FAILURE -1
+
+/*
+ * XMenu internal event handler variable.
+ */
+extern int (*_XMEventHandler)();
+
+#ifndef Pixel
+#define Pixel unsigned long
+#endif
+
+/*
+ * Internal routine declarations.
+ */
+int _XMWinQueInit(); /* No value actually returned. */
+int _XMWinQueAddPane();
+int _XMWinQueAddSelection();
+int _XMWinQueFlush();
+XMPane *_XMGetPanePtr();
+XMSelect *_XMGetSelectionPtr();
+int _XMRecomputeGlobals(); /* No value actually returned. */
+int _XMRecomputePane();
+int _XMRecomputeSelection();
+int _XMTransToOrigin(); /* No value actually returned. */
+int _XMRefreshPane(); /* No value actually returned. */
+int _XMRefreshSelections(); /* No value actually returned. */
+int _XMHighlightSelection(); /* No value actually returned. */
+
+#endif
+/* Don't add stuff after this #endif */
diff --git a/oldXMenu/copyright.h b/oldXMenu/copyright.h
new file mode 100644
index 00000000000..1a87b46f1be
--- /dev/null
+++ b/oldXMenu/copyright.h
@@ -0,0 +1,19 @@
+/* $Header: copyright.h,v 8.0 88/08/19 13:47:05 nathanm Exp $ */
+/*
+
+Copyright 1985, 1986, 1987 by the Massachusetts Institute of Technology
+
+Permission to use, copy, modify, and distribute this
+software and its documentation for any purpose and without
+fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright
+notice and this permission notice appear in supporting
+documentation, and that the name of M.I.T. not be used in
+advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+M.I.T. makes no representations about the suitability of
+this software for any purpose. It is provided "as is"
+without express or implied warranty.
+
+*/
+
diff --git a/oldXMenu/insque.c b/oldXMenu/insque.c
new file mode 100644
index 00000000000..dd1a0ac6fc7
--- /dev/null
+++ b/oldXMenu/insque.c
@@ -0,0 +1,38 @@
+/* This file implements the insque and remque functions of BSD.
+ It is not compiled by default, because that change would be too risky
+ to install right now. If you find that HAVE_X_MENU leads to linker errors
+ because these functions are undefined, then compile this file
+ and arrange to link it in. */
+
+struct qelem {
+ struct qelem *q_forw;
+ struct qelem *q_back;
+ char q_data[1];
+};
+
+/* Insert ELEM into a doubly-linked list, after PREV. */
+
+void
+insque (elem, prev)
+ struct qelem *elem, *prev;
+{
+ struct qelem *next = prev->q_forw;
+ prev->q_forw = elem;
+ if (next)
+ next->q_back = elem;
+ elem->q_forw = next;
+ elem->q_back = prev;
+}
+
+/* Unlink ELEM from the doubly-linked list that it is in. */
+
+remque (elem)
+ struct qelem *elem;
+{
+ struct qelem *next = elem->q_forw;
+ struct qelem *prev = elem->q_back;
+ if (next)
+ next->q_back = prev;
+ if (prev)
+ prev->q_forw = next;
+}
diff --git a/shortnames/COPYING b/shortnames/COPYING
new file mode 100644
index 00000000000..9a170375811
--- /dev/null
+++ b/shortnames/COPYING
@@ -0,0 +1,249 @@
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 1, February 1989
+
+ Copyright (C) 1989 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The license agreements of most software companies try to keep users
+at the mercy of those companies. By contrast, our General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. The
+General Public License applies to the Free Software Foundation's
+software and to any other program whose authors commit to using it.
+You can use it for your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Specifically, the General Public License is designed to make
+sure that you have the freedom to give away or sell copies of free
+software, that you receive source code or can get it if you want it,
+that you can change the software or use pieces of it in new free
+programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of a such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must tell them their rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any program or other work which
+contains a notice placed by the copyright holder saying it may be
+distributed under the terms of this General Public License. The
+"Program", below, refers to any such program or work, and a "work based
+on the Program" means either the Program or any work containing the
+Program or a portion of it, either verbatim or with modifications. Each
+licensee is addressed as "you".
+
+ 1. You may copy and distribute verbatim copies of the Program's source
+code as you receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice and
+disclaimer of warranty; keep intact all the notices that refer to this
+General Public License and to the absence of any warranty; and give any
+other recipients of the Program a copy of this General Public License
+along with the Program. You may charge a fee for the physical act of
+transferring a copy.
+
+ 2. You may modify your copy or copies of the Program or any portion of
+it, and copy and distribute such modifications under the terms of Paragraph
+1 above, provided that you also do the following:
+
+ a) cause the modified files to carry prominent notices stating that
+ you changed the files and the date of any change; and
+
+ b) cause the whole of any work that you distribute or publish, that
+ in whole or in part contains the Program or any part thereof, either
+ with or without modifications, to be licensed at no charge to all
+ third parties under the terms of this General Public License (except
+ that you may choose to grant warranty protection to some or all
+ third parties, at your option).
+
+ c) If the modified program normally reads commands interactively when
+ run, you must cause it, when started running for such interactive use
+ in the simplest and most usual way, to print or display an
+ announcement including an appropriate copyright notice and a notice
+ that there is no warranty (or else, saying that you provide a
+ warranty) and that users may redistribute the program under these
+ conditions, and telling the user how to view a copy of this General
+ Public License.
+
+ d) You may charge a fee for the physical act of transferring a
+ copy, and you may at your option offer warranty protection in
+ exchange for a fee.
+
+Mere aggregation of another independent work with the Program (or its
+derivative) on a volume of a storage or distribution medium does not bring
+the other work under the scope of these terms.
+
+ 3. You may copy and distribute the Program (or a portion or derivative of
+it, under Paragraph 2) in object code or executable form under the terms of
+Paragraphs 1 and 2 above provided that you also do one of the following:
+
+ a) accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of
+ Paragraphs 1 and 2 above; or,
+
+ b) accompany it with a written offer, valid for at least three
+ years, to give any third party free (except for a nominal charge
+ for the cost of distribution) a complete machine-readable copy of the
+ corresponding source code, to be distributed under the terms of
+ Paragraphs 1 and 2 above; or,
+
+ c) accompany it with the information you received as to where the
+ corresponding source code may be obtained. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form alone.)
+
+Source code for a work means the preferred form of the work for making
+modifications to it. For an executable file, complete source code means
+all the source code for all modules it contains; but, as a special
+exception, it need not include source code for modules which are standard
+libraries that accompany the operating system on which the executable
+file runs, or for standard header files or definitions files that
+accompany that operating system.
+
+ 4. You may not copy, modify, sublicense, distribute or transfer the
+Program except as expressly provided under this General Public License.
+Any attempt otherwise to copy, modify, sublicense, distribute or transfer
+the Program is void, and will automatically terminate your rights to use
+the Program under this License. However, parties who have received
+copies, or rights to use copies, from you under this General Public
+License will not have their licenses terminated so long as such parties
+remain in full compliance.
+
+ 5. By copying, distributing or modifying the Program (or any work based
+on the Program) you indicate your acceptance of this license to do so,
+and all its terms and conditions.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the original
+licensor to copy, distribute or modify the Program subject to these
+terms and conditions. You may not impose any further restrictions on the
+recipients' exercise of the rights granted herein.
+
+ 7. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of the license which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+the license, you may choose any version ever published by the Free Software
+Foundation.
+
+ 8. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to humanity, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these
+terms.
+
+ To do so, attach the following notices to the program. It is safest to
+attach them to the start of each source file to most effectively convey
+the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19xx name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the
+appropriate parts of the General Public License. Of course, the
+commands you use may be called something other than `show w' and `show
+c'; they could even be mouse-clicks or menu items--whatever suits your
+program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ program `Gnomovision' (a program to direct compilers to make passes
+ at assemblers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/shortnames/Makefile b/shortnames/Makefile
new file mode 100644
index 00000000000..fcb5a4dae28
--- /dev/null
+++ b/shortnames/Makefile
@@ -0,0 +1,44 @@
+S = ../src
+LENGTH = 7
+FILES = $S/*.[ch]
+NAMES = names $(LENGTH)
+DUPS = dups $(LENGTH)
+INC = /usr/include
+
+remap.h : duplist2 defines
+ cat header.h >$@
+ defines <duplist2 >>$@
+
+duplist2 : duplist exclude
+ comm -13 exclude duplist >$@
+
+duplist : dups names
+ cat $(FILES) | $(NAMES) | sort | uniq | $(DUPS) | sort | uniq >$@
+
+# There are two files, reserved and special, which contain the names of
+# strings which must not be remapped. In general, reserved contains strings
+# which are meaningful to the C preprocessor or compiler, and "special"
+# contains special emacs strings that must not be remapped (they are the
+# basename of an include file for example; actually this is a holdover from
+# when sed or m4 was used to do the remapping, not needed with cpp remapping).
+#
+# Note, because "cut" is braindamaged and does not return explicit status,
+# and since the status returned to make is that of the last program in the
+# pipeline, we filter the final result through cat to avoid killing make.
+
+exclude : reserved special
+ cat reserved special >tempfile
+ grep "^#[ \t]*define" $(INC)/*.h | tr -s "\040\011#()" ":::::" | cut -f3 -d: | cat >>tempfile
+ grep "^#[ \t]*define" $(INC)/sys/*.h | tr -s "\040\011#()" ":::::" | cut -f3 -d: | cat >>tempfile
+ grep "^#[ \t]*define" $S/*.[ch] | tr -s "\040\011#()" ":::::" | cut -f3 -d: | cat >>tempfile
+ sort <tempfile | uniq >$@
+ rm -f tempfile
+
+dups : dups.c
+ $(CC) -O -o $@ $?
+
+names : names.c
+ $(CC) -O -o $@ $?
+
+defines : defines.c
+ $(CC) -O -o $@ $?
diff --git a/shortnames/defines.c b/shortnames/defines.c
new file mode 100644
index 00000000000..ba8ab5437dd
--- /dev/null
+++ b/shortnames/defines.c
@@ -0,0 +1,14 @@
+#include <stdio.h>
+
+int count;
+
+main ()
+{
+ char buffer[512];
+
+ while (gets (buffer))
+ {
+ printf ("#define %s zz%4.4dzz\n", buffer, count++);
+ }
+ return (0);
+}
diff --git a/shortnames/dups.c b/shortnames/dups.c
new file mode 100644
index 00000000000..79764ec9f03
--- /dev/null
+++ b/shortnames/dups.c
@@ -0,0 +1,62 @@
+/*
+ * Quick and dirty program to select adjacent records that are common
+ * in the first <arg> character positions.
+ *
+ */
+
+#include <stdio.h>
+
+#define MAXSIZE 512
+
+char ping[MAXSIZE];
+char pong[MAXSIZE];
+
+int flipflop = 0;
+int size = MAXSIZE-1;
+
+main (argc, argv)
+ int argc;
+ char *argv[];
+{
+ register int index;
+ char *newbuf();
+
+ if (argc == 2)
+ {
+ size = atoi (argv[1]);
+ }
+ while (newbuf() != NULL)
+ {
+ for (index=0; index < size; index++)
+ {
+ if (ping[index] != pong[index])
+ {
+ break;
+ }
+ }
+ if (index == size)
+ {
+ printf ("%s\n", ping);
+ printf ("%s\n", pong);
+ }
+ }
+ return (0);
+}
+
+char *
+newbuf ()
+{
+ char *bufp;
+
+ if (flipflop)
+ {
+ bufp = ping;
+ flipflop = 0;
+ }
+ else
+ {
+ bufp = pong;
+ flipflop = 1;
+ }
+ return (gets (bufp));
+}
diff --git a/shortnames/header.h b/shortnames/header.h
new file mode 100644
index 00000000000..5d7eea047fa
--- /dev/null
+++ b/shortnames/header.h
@@ -0,0 +1,10 @@
+/* Header file to remap longnames to shortnames. Note that not
+ all cpp's support longnames. In particular, most pre 5.2 UniSoft
+ ports only support 16 unique characters. To bootstrap GNU emacs
+ to a 5.0 UniPlus+ system I had to port the 5.2 cpp (with FLEXNAMES)
+ to the development system. This was about a 1 hour job with sources.
+ Alternatively, m4 can probably be used but this is not as clean and
+ requires some changes to the default make rules (add rule to go from
+ a ".cm4" file to a ".c" file and rule to go from a ".hm4" file to
+ a ".h" file. There are too many changes for sed to handle in a single
+ pass. Fred Fish, UniSoft Systems. */
diff --git a/shortnames/names.c b/shortnames/names.c
new file mode 100644
index 00000000000..e4beff95a18
--- /dev/null
+++ b/shortnames/names.c
@@ -0,0 +1,99 @@
+/*
+ * A quick and dirty C program to spit out possible identifiers
+ * from a stream of *.c and *.h files. Takes a single parameter
+ * which specifies the minimum length of an identifier to be
+ * extracted.
+ *
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+
+#define FIRSTCHAR(a) (isalpha(a) || (a)=='_')
+#define OTHERCHAR(a) (FIRSTCHAR(a) || isdigit(a))
+#define TRUE 1
+#define FALSE 0
+
+int size = 0;
+char buffer[512];
+char *bp = buffer;
+
+main (argc, argv)
+ int argc;
+ char *argv[];
+{
+ register int ch;
+ register int spitout;
+ register int eating_comment;
+
+ if (argc == 2)
+ {
+ size = atoi (argv[1]);
+ }
+ spitout = FALSE;
+ eating_comment = FALSE;
+ while ((ch = getchar()) != EOF)
+ {
+ if (ch == '/')
+ {
+ if ((ch = getchar()) == EOF)
+ {
+ fprintf (stderr, "unexpected EOF!\n");
+ exit (1);
+ }
+ else
+ {
+ if (ch == '*')
+ {
+ eating_comment = TRUE;
+ }
+ else
+ {
+ ungetc (ch, stdin);
+ }
+ }
+ }
+ else if (eating_comment && ch == '*')
+ {
+ if ((ch = getchar()) == EOF)
+ {
+ fprintf (stderr, "unexpected EOF!\n");
+ exit (1);
+ }
+ else
+ {
+ if (ch == '/')
+ {
+ eating_comment = FALSE;
+ }
+ else
+ {
+ ungetc (ch, stdin);
+ }
+ }
+ }
+ else if (!eating_comment)
+ {
+ if (!spitout && FIRSTCHAR(ch))
+ {
+ spitout = TRUE;
+ *bp++ = ch;
+ }
+ else if (spitout && OTHERCHAR(ch))
+ {
+ *bp++ = ch;
+ }
+ else if (spitout)
+ {
+ *bp++ = '\000';
+ bp = buffer;
+ if (strlen (bp) >= size)
+ {
+ printf ("%s\n", bp);
+ }
+ spitout = FALSE;
+ }
+ }
+ }
+ return (0);
+}
diff --git a/shortnames/reserved b/shortnames/reserved
new file mode 100644
index 00000000000..d5b8b9c9440
--- /dev/null
+++ b/shortnames/reserved
@@ -0,0 +1,34 @@
+int
+char
+float
+double
+struct
+union
+long
+short
+unsigned
+auto
+extern
+register
+typedef
+static
+goto
+return
+sizeof
+break
+continue
+if
+else
+for
+do
+while
+switch
+case
+default
+entry
+include
+define
+defined
+undef
+undefined
+undefine
diff --git a/shortnames/special b/shortnames/special
new file mode 100644
index 00000000000..5da3a13214e
--- /dev/null
+++ b/shortnames/special
@@ -0,0 +1,23 @@
+buffer
+cm
+commands
+config
+dispextern
+environ
+indent
+lisp
+macros
+paths
+process
+regex
+setpgrp
+syntax
+termchar
+termhooks
+termopts
+undo
+window
+HAVE_X_MENU
+HAVE_X_WINDOWS
+CANNOT_DUMP
+CANNOT_UNEXEC
diff --git a/src/.dbxinit b/src/.dbxinit
new file mode 100644
index 00000000000..dcd57cfd36e
--- /dev/null
+++ b/src/.dbxinit
@@ -0,0 +1,15 @@
+ignore 14
+catch 18
+ignore 20
+ignore 23
+alias s step
+alias n next
+alias c cont
+alias st status
+alias r run
+alias l list
+alias f file
+alias q quit
+alias w where
+alias d delete
+alias p print
diff --git a/src/COPYING b/src/COPYING
new file mode 100644
index 00000000000..9a170375811
--- /dev/null
+++ b/src/COPYING
@@ -0,0 +1,249 @@
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 1, February 1989
+
+ Copyright (C) 1989 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The license agreements of most software companies try to keep users
+at the mercy of those companies. By contrast, our General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. The
+General Public License applies to the Free Software Foundation's
+software and to any other program whose authors commit to using it.
+You can use it for your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Specifically, the General Public License is designed to make
+sure that you have the freedom to give away or sell copies of free
+software, that you receive source code or can get it if you want it,
+that you can change the software or use pieces of it in new free
+programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of a such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must tell them their rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any program or other work which
+contains a notice placed by the copyright holder saying it may be
+distributed under the terms of this General Public License. The
+"Program", below, refers to any such program or work, and a "work based
+on the Program" means either the Program or any work containing the
+Program or a portion of it, either verbatim or with modifications. Each
+licensee is addressed as "you".
+
+ 1. You may copy and distribute verbatim copies of the Program's source
+code as you receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice and
+disclaimer of warranty; keep intact all the notices that refer to this
+General Public License and to the absence of any warranty; and give any
+other recipients of the Program a copy of this General Public License
+along with the Program. You may charge a fee for the physical act of
+transferring a copy.
+
+ 2. You may modify your copy or copies of the Program or any portion of
+it, and copy and distribute such modifications under the terms of Paragraph
+1 above, provided that you also do the following:
+
+ a) cause the modified files to carry prominent notices stating that
+ you changed the files and the date of any change; and
+
+ b) cause the whole of any work that you distribute or publish, that
+ in whole or in part contains the Program or any part thereof, either
+ with or without modifications, to be licensed at no charge to all
+ third parties under the terms of this General Public License (except
+ that you may choose to grant warranty protection to some or all
+ third parties, at your option).
+
+ c) If the modified program normally reads commands interactively when
+ run, you must cause it, when started running for such interactive use
+ in the simplest and most usual way, to print or display an
+ announcement including an appropriate copyright notice and a notice
+ that there is no warranty (or else, saying that you provide a
+ warranty) and that users may redistribute the program under these
+ conditions, and telling the user how to view a copy of this General
+ Public License.
+
+ d) You may charge a fee for the physical act of transferring a
+ copy, and you may at your option offer warranty protection in
+ exchange for a fee.
+
+Mere aggregation of another independent work with the Program (or its
+derivative) on a volume of a storage or distribution medium does not bring
+the other work under the scope of these terms.
+
+ 3. You may copy and distribute the Program (or a portion or derivative of
+it, under Paragraph 2) in object code or executable form under the terms of
+Paragraphs 1 and 2 above provided that you also do one of the following:
+
+ a) accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of
+ Paragraphs 1 and 2 above; or,
+
+ b) accompany it with a written offer, valid for at least three
+ years, to give any third party free (except for a nominal charge
+ for the cost of distribution) a complete machine-readable copy of the
+ corresponding source code, to be distributed under the terms of
+ Paragraphs 1 and 2 above; or,
+
+ c) accompany it with the information you received as to where the
+ corresponding source code may be obtained. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form alone.)
+
+Source code for a work means the preferred form of the work for making
+modifications to it. For an executable file, complete source code means
+all the source code for all modules it contains; but, as a special
+exception, it need not include source code for modules which are standard
+libraries that accompany the operating system on which the executable
+file runs, or for standard header files or definitions files that
+accompany that operating system.
+
+ 4. You may not copy, modify, sublicense, distribute or transfer the
+Program except as expressly provided under this General Public License.
+Any attempt otherwise to copy, modify, sublicense, distribute or transfer
+the Program is void, and will automatically terminate your rights to use
+the Program under this License. However, parties who have received
+copies, or rights to use copies, from you under this General Public
+License will not have their licenses terminated so long as such parties
+remain in full compliance.
+
+ 5. By copying, distributing or modifying the Program (or any work based
+on the Program) you indicate your acceptance of this license to do so,
+and all its terms and conditions.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the original
+licensor to copy, distribute or modify the Program subject to these
+terms and conditions. You may not impose any further restrictions on the
+recipients' exercise of the rights granted herein.
+
+ 7. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of the license which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+the license, you may choose any version ever published by the Free Software
+Foundation.
+
+ 8. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to humanity, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these
+terms.
+
+ To do so, attach the following notices to the program. It is safest to
+attach them to the start of each source file to most effectively convey
+the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19xx name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the
+appropriate parts of the General Public License. Of course, the
+commands you use may be called something other than `show w' and `show
+c'; they could even be mouse-clicks or menu items--whatever suits your
+program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ program `Gnomovision' (a program to direct compilers to make passes
+ at assemblers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/src/ChangeLog b/src/ChangeLog
new file mode 100644
index 00000000000..41ee211a173
--- /dev/null
+++ b/src/ChangeLog
@@ -0,0 +1,4372 @@
+Fri Oct 30 18:10:34 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * Version 18.59 released.
+
+Thu Oct 29 04:35:15 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * s-sco3-2-1.h, s-sco3-2-2.h: New files.
+
+ * s-sco.h [HAVE_X11] (BSTRING, HAVE_RANDOM, LIB_STANDARD): Defined.
+ [HAVE_X11] (LIBS_SYSTEM): #undef if defined above.
+ [SCO_SOCKETS] (HAVE_TIMEVAL, USE_UTIME): Defined.
+
+Tue Oct 27 14:33:37 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * m-next.h (ORDINARY_LINK): Defined.
+ (LIB_STANDARD, NO_REMAP): #if 0'd.
+ (KERNEL_FILE): Defined.
+
+ * unexmips.c: Clear text_section->s_scnptr.
+
+Sun Oct 25 00:44:32 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * process.c (wait_reading_process_input) [sun || apollo]:
+ Don't try to deliver SIGIO if SIGIO is not defined.
+
+Sat Oct 24 00:32:07 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * x11term.c (internal_socket_read): Process Mod1Mask for multichar
+ keys as well as one-char keys.
+
+Fri Oct 23 20:52:19 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * s-aix3-2.h (index, rindex): #undef them.
+
+ * hftctl.c (hft_alrm, GT_ACK): Cast arg of `signal'.
+
+ * x11term.c (XInitWindow): If can't find font, try font `fixed'.
+
+ * m-ibmrs6000.h (BIG_ENDIAN): Define as 4321.
+
+Wed Oct 21 18:24:12 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * m-sparc.h: Change the HAVE_SUN_WINDOWS conditional.
+
+ * sunfns.c: New version from Peck.
+
+Sun Oct 18 04:07:15 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * x11term.c (XInitWindow): Fix typo in NO_X_DESTROY_DATABASE test.
+
+ * s-esix5r4.h (BROKEN_FIONREAD): Defined.
+
+Fri Oct 16 04:27:07 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * fns.c (Fload_average): Handle NeXT like convex.
+
+ * unexnext.c: New version from Lennart_Lovstrand@NeXT.COM.
+
+ * emacs.c (main) [NeXT]: Make malloc_cookie external.
+
+ * s-vms5-5.h: New file.
+
+Sat Oct 10 07:41:06 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * m-ibmps2-aix.h [__GNUC__ >= 2] (LIB_STANDARD): Don't define.
+
+Fri Oct 9 01:08:36 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * m-ibmrs6000.h (PTY_ITERATION, etc.): Definitions deleted.
+ (SPECIFY_X11R4): Don't define if already defined.
+ * s-aix3-2.h (SPECIFY_X11R4): Defined.
+
+ * m-mips4.h: If __GNUC__, undef LINKER.
+ Change LD_SWITCH_MACHINE to pass switches via GCC; add -g.
+
+ * m-pyrmips.h: New file.
+
+Tue Oct 6 00:54:20 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * fileio.c (directory_file_name): Don't clobber the envvar
+ when handling top-level rooted dir.
+
+ * link.com: Fix the code that tests which compiler was used.
+
+ * m-ibmps2-aix.h [USG_SHARED_LIBRARIES]: Define ORDINARY_LINK.
+ Undef LIB_STANDARD. Modify LD_SWITCH_MACHINE.
+
+ * ymakefile (LIB_STANDARD): If ORDINARY_LINK, default this to empty.
+
+ * emacs.c (main) [NeXT]: Call malloc_jumpstart.
+
+ * unexnext.c: New file.
+ * m-next.h, s-mach2.h: New files.
+
+Sun Oct 4 19:18:25 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * s-sco.h (HAVE_TIMEVAL): Turned off.
+
+Sat Oct 3 00:22:57 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * ymakefile (STARTFILES): Do use pre-crt0.o even if ORDINARY_LINK.
+ * emacs.c: Don't define __main, etc., if ORDINARY_LINK.
+
+ * s-sunos4-0.h, s-sunos4-1.h (LD_SWITCH_SYSTEM):
+ If GCC 2, use -static instead of -Bstatic.
+
+Fri Oct 2 02:27:39 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * unexmips.c (mark_x): Declare static.
+
+ * callint.c (Fcall_interactively):
+ Cast to unsigned char when setting `string'.
+
+Thu Oct 1 20:41:26 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * s-hpux7.h (NO_X_DESTROY_DATABASE): Defined.
+ * s-hpux8.h (NO_X_DESTROY_DATABASE): Undef it.
+ * x11term.c (XInitWindow): Add NO_X_DESTROY_DATABASE conditional.
+
+ * process.c (Fopen_network_stream): Use -1, not INADDR_NONE.
+
+Mon Sep 21 01:45:34 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * alloc.c (mark_object): Avoid car-recursion in some common cases.
+
+Sun Sep 20 15:02:57 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * emacs.c (__do_clobal_ctors, __main): Defined.
+ (__CTOR_LIST__, __DTOR_LIST__): Add 0 as second elt.
+
+ * getpagesize.h: If POSIX, include unistd.h and use sysconf.
+
+ * s-sol2.h: New file.
+
+ * fileio.c: Don't include sys/dir.h.
+
+ * s-usg5-4.h (LIBS_SYSTEM): Move non-default libraries here.
+ (LIB_STANDARD, START_FILES): Deleted.
+ (ORDINARY_LINK): Defined.
+
+ * ymakefile [ORDINARY_LINK]: Default LD to $(CC)
+ and make START_FILES and LIB_STANDARD empty.
+ (C_SWITCH_X_MACHINE, C_SWITCH_X_SYSTEM): New macros, default empty.
+ (CFLAGS): Use them.
+
+Thu Sep 17 18:49:39 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * ymakefile (LIBX): Don't use -loldX.
+
+Sat Sep 12 03:20:22 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * s-esix5r4.h (LIB_X11_LIB): Use -lX11, don't specify lib file name.
+ (LIB_STANDARD): Defined.
+ (BSTRING): Defined.
+ (C_SWITCH_SYSTEM): Deleted; we define BSTRING directly.
+
+ * sysdep.c (init_sys_modes): Handle VDSUSP like V_DSUSP.
+ Use CDISABLE, not CDEL.
+ Turn off IEXTEN if it exists.
+ (CDISABLE): New macro; may be defined from CDEL.
+
+ * syntax.c (syntax_spec_code): Make elts unsigned.
+
+Thu Sep 10 03:48:18 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * s-aix3-1.h (HAVE_GETHOSTNAME): Defined.
+
+Mon Aug 31 13:57:44 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * emacs.c (__do_global_ctors, __do_global_ctors_aux): New dummy fns.
+ (__CTOR_LIST__, __DTOR_LIST__): New dummy variables.
+
+Fri Aug 28 22:30:25 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * unexmips.c (unexec): Allow sectins in any order.
+ Adjust addresses of rdata section as well as data section.
+
+Tue Aug 25 17:59:29 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * m-intel386.h [J386BSD] (LOAD_AVE_TYPE, LOAD_AVE_CVT): Defined.
+
+ * s-386bsd.h: New file.
+
+Fri Aug 21 22:50:34 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * process.c (WCOREDUMP): Define only if not defined.
+ (create_process) [HAVE_SETSID]: Use TIOCSCTTY if exists.
+
+Tue Aug 11 17:29:22 1992 Roland McGrath (roland@geech.gnu.ai.mit.edu)
+
+ * x11term.c (db, db2): Don't initialize, as it breaks dumping.
+
+Fri Aug 7 19:38:28 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * vms-pwd.h: Renamed from pwd.h.
+ * editfns.c, fileio.c, sysdep.c, filelock.c: #includes changed.
+
+Wed Aug 5 00:47:16 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * m-delta.h (SIGNALS_VIA_CHARACTERS): Defined.
+
+ * process.c (process_send_signal): Refer to SIGTSTP only if defined.
+
+Tue Jul 28 12:39:58 MET 1992 Francesco Potorti` (pot@cnuce.cnr.IT)
+
+ * m-delta.h: Added #define mot_delta for alloca.s to recognise it.
+ (CLASH_DETECTION): Defined, since now OK with short filenames.
+ (LOAD_AVE_TYPE): Deleted.
+ (C_ALLOCA): Deleted; new alloca.s should work.
+ (KERNEL_FILE): Defined.
+ (sigsetmask): Add #undef, since -lbsd supplies sigsetmask.
+ (SYSV_SYSTEM_DIR, HAVE_CLOSEDIR): Defined.
+ (BSTRING, HAVE_DUP2): Defined.
+ (LIBS_SYSTEM): Use -lbsd here,
+ (LIB_STANDARD): not here (deleted).
+ (HAVE_X_WINDOWS): Deleted--X is not standard.
+ (USG_SYS_TIME): Defined.
+ (BAT68K): Deleted; replaced by USG_SYS_TIME.
+
+Mon Jul 27 15:59:29 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * s-isc2-2.h (HAVE_SOCKETS, HAVE_SELECT): Defined.
+ * s-isc3-0.h: Instead of here.
+
+Fri Jul 24 15:28:51 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * dispnew.c (remake_screen_structures): Update echo_area_contents
+ along with message_buf.
+ * dispextern.h (echo_area_contents): Declare it.
+
+ * xdisp.c (display_text_line): Init p1prev as 0. Test at end.
+
+Sun Jul 19 14:00:40 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * process.c (allocate_pty): Wait until we fail to open three ptys
+ in a row before concluding that we've reached the end of the ptys.
+
+Sat Jul 18 15:21:19 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * unexec.c (mark_x): Return 0 on success, -1 on failure.
+ (unexec): Return what mark_x returns.
+
+Mon Jul 13 23:04:30 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * x11term.c: (x_term_init): Use black_color and white_color
+ for color names that correspond to preallocated pixel values.
+ (x_term_init, XFlipColor): Handle inverse video for mous_color
+ and curs_color by swapping between fore_color and back_color.
+ * x11fns.c (Fx_set_*_color): Use black_color and white_color.
+ Free the old color if and if it was allocated.
+ Free the old color name as well.
+ (x_set_cursor_colors): Use black_color and white_color.
+
+Sat Jul 11 14:18:56 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * fns.c, callproc.c: Doc fix.
+
+Fri Jul 10 13:45:51 1992 Jody Winston (jody@shell.com)
+
+ * x11term.c (XInitWindow): Free databases from XrmGetStringDatabase.
+
+Tue Jul 7 11:22:17 1992 Jim Blandy (jimb@pogo.cs.oberlin.edu)
+
+ * regex.c. (re_compile_pattern): The temporary variable used when
+ applying the translation map to character sets should be an
+ unsigned char, not a char.
+
+Mon Jul 6 17:19:48 1992 Roland McGrath (roland@churchy.gnu.ai.mit.edu)
+
+ * x11fns.c: Move lisp.h and window.h and undef NULL after all other
+ includes.
+
+Sun Jul 5 17:48:46 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * s-isc3-0.h: New file.
+
+Sat Jun 27 19:08:06 1992 Jim Blandy (jimb@pogo.cs.oberlin.edu)
+
+ * regex.c (re_compile_pattern): Apply the translation map to
+ contents of character sets, too.
+
+Thu Jun 25 14:07:39 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * sysdep.c: On dgux, undef _BSD_TTY_FLAVOR before including sgtty.h.
+
+ * window.c (scroll_command): If context lines exceed window
+ height, scroll by one line.
+
+Mon Jun 22 21:38:39 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * m-targon31.h (SEGMENT_MASK): Defined.
+ (NO_REMAP): Deleted.
+ (HAVE_PTYS, HAVE_SOCKETS, HAVE_SYSVIPC, BSTRING): Defined.
+ [__GNUC__] (SYSTEM_MALLOC, HAVE_ALLOCA, alloca): Defined.
+
+ * syntax.h (SYNTAX, SYNTAX_MATCH, SYNTAX_COMSTART_FIRST, etc.)
+ Cast character to unsigned char before indexing.
+
+Fri Jun 12 15:36:17 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * s-dgux4-31.h: New file.
+
+Fri Jun 12 05:37:39 1992 Jim Blandy (jimb@pogo.cs.oberlin.edu)
+
+ * xdisp.c (display_echo_area_contents): After displaying
+ echo_area_contents on the first line of the minibuffer window,
+ display blank lines on all the other lines of the window.
+
+Thu Jun 11 11:51:07 1992 Paul Eggert (eggert@twinsun.com)
+
+ * callproc.c (Fcall_process_region): Return Fcall_process's status.
+
+Wed Jun 10 16:45:25 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * sysdep.c (sys_signal): Fix erroneous name for sigaction.
+
+Wed May 27 23:41:59 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * m-ibmrs6000.h (PTY_ITERATION, PTY_NAME_SPRINTF): Defined.
+ (PTY_TTY_NAME_SPRINTF): Defined.
+
+Sat May 23 22:07:04 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * sink11.h, sink11mask.h: Use unsigned char to avoid warnings.
+
+Thu May 21 16:34:56 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * alloca.c: Make symlink to master copy.
+
+Mon May 18 22:04:35 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * dispnew.c (Fding): If have arg, don't end a keyboard macro.
+
+Sun May 17 02:57:17 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * keyboard.c (Fdiscard_input): Clear Vquit_flag to nil.
+
+Sat May 16 00:47:36 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * Use cursor color for hollow cursors.
+ * x11fns.c (Fx_set_cursor_color, Fx_set_background_color):
+ Modify XXgc_curs_rev.
+ * x11term.c (CursorToggle): Use XXgc_curs_rev.
+ (XNewFont, XFlipColor, XInitWindow): Update XXgc_curs_rev.
+
+ * x11fns.c (Fx_set_background_color, Fx_set_foreground_color):
+ (Fx_set_border_color, Fx_set_cursor_color): Free old color.
+
+Thu May 14 22:21:46 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * callproc.c (Fcall_process): Fix one-off testing if args[3] is valid.
+
+Wed May 13 15:39:38 1992 Jim Blandy (jimb@wookumz.gnu.ai.mit.edu)
+
+ * buffer.c (init_buffer_once): Don't disable undo for *scratch*
+ buffer here. There is no good symmetrical place to re-enable it,
+ although garbage collection used to do so. Do it in
+ ../lisp/loadup.el instead.
+
+Tue May 12 23:54:33 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * fileio.c: Include config.h first thing.
+
+ * process.c (wait_reading_process_input):
+ Make C-g really quit in sit-for case.
+ * keyboard.c (clear_input_pending): New subroutine.
+
+ * ymakefile (LD_SWITCH_SYSTEM): Don't use -X with GCC.
+
+Tue May 12 16:02:15 1992 Jim Blandy (jimb@wookumz.gnu.ai.mit.edu)
+
+ * alloc.c (Fgarbage_collect): Don't call truncate_undo_list on
+ buffers whose undo list is t.
+
+Thu May 7 18:47:14 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * m-seq386.h: Tentatively make this the same as m-sequent.h.
+
+Tue May 5 11:30:44 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * m-tad68k (SECTION_ALIGNMENT): Increase to 256k.
+ (NBPC, HAVE_RANDOM): Defined.
+
+Thu Apr 30 18:17:26 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * s-sco.h (PTY_NAME_SPRINTF, PTY_TTY_NAME_SPRINTF): Defined.
+
+Tue Apr 28 19:55:01 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * s-irix4-0.h: Turn on pty stuff. Declare getpty only ifdef emacs.
+ (WNOHANG): Defined.
+
+Tue Apr 28 15:39:53 1992 Jim Blandy (jimb@wookumz.gnu.ai.mit.edu)
+
+ * syntax.c (Fmodify_syntax_entry): Note that '-' is a synonym for
+ ' ' (both denote whitespace), that '\\' denotes the escape class,
+ and that '/' denotes the character-quote class. The description
+ used to claim that '\\' denoted the character-quote class, and
+ neglected to mention '-' and '/'.
+
+Mon Apr 27 16:15:13 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * alloca.s [mot_delta]: Use `global', and a colon after the label.
+
+Sat Apr 25 15:40:37 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * s-osf1.h: New file.
+ * m-pmax.h [OSF1]: Undef C_ALLOCA, define HAVE_ALLOCA.
+
+Wed Apr 22 19:19:37 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * s-sco.h (USG_SYS_TIME): Defined.
+ (HAVE_SOCKETS, LIBS_SYSTEM, HAVE_GETTIMEOFDAY): Only if SCO_SOCKETS.
+
+Tue Apr 21 10:44:59 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * ymakefile (x11term.o): Add gettime.h, emacssignal.h, xkeys-aix.h.
+
+Mon Apr 20 15:13:34 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * s-sco.h (HAVE_TIMEVAL, HAVE_SELECT, HAVE_PTYS, HAVE_SOCKETS):
+ (LIBS_SYSTEM, BSTRING, HAVE_GETTIMEOFDAY): Defined.
+
+Sun Apr 19 13:12:22 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * m-seq386.h: New file.
+
+Sun Apr 19 00:43:17 1992 Jim Blandy (jimb@wookumz.gnu.ai.mit.edu)
+
+ * fileio.c (directory_file_name): Check slen before fetching dst[slen].
+
+Sat Apr 18 11:59:13 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * fileio.c: Move HAVE_TIMEVAL and HPUX_NET conds above lisp.h include.
+
+ * indent.c (compute_motion): Fix skipping invis lines and
+ truncation at right margin.
+
+Fri Apr 17 11:33:50 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * dispnew.c (direct_output_forward_char): Handle edges of window.
+
+ * filelock.c (lock_superlock, lock_file_1): Handle NO_FCHMOD.
+ * m-dpx2.h (fchmod): Deleted.
+ (NO_FCHMOD): Defined.
+
+ * ymakefile (x11term.o, dired.o, UNEXEC): Add or fix deps.
+
+Fri Apr 17 05:44:46 1992 Jim Blandy (jimb@wookumz.gnu.ai.mit.edu)
+
+ * callint.c (Fcall_interactively): Check for quits when following
+ function chain.
+
+Wed Apr 15 00:34:05 1992 Jim Blandy (jimb@pogo.cs.oberlin.edu)
+
+ * callint.c (Fcall_interactively): When the interactive spec is
+ a string, it may be relocated while reading the arguments. To
+ avoid this, make a copy of the spec to refer to, instead of
+ using a pointer to the data of the spec string.
+
+Fri Apr 10 15:13:49 1992 Jim Blandy (jimb@wookumz.gnu.ai.mit.edu)
+
+ * ymakefile (dispnew.o): Note that this depends on lisp.h.
+
+Sat Apr 4 20:29:07 1992 Roland McGrath (roland@churchy.gnu.ai.mit.edu)
+
+ * indent.c (pos_tab_offset): Add missing ).
+
+Mon Mar 30 01:02:12 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * s-irix4-0.h: Fix typo `#ifdef 0'.
+
+Sun Mar 29 21:02:14 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * s-dgux.h: Change #if 0 to #ifndef COFF.
+ Don't define COFF if ELF is defined.
+ [not COFF] (C_COMPILER, LINKER, MAKE_COMMAND): New defs.
+
+ * process.c (process_send_signal): If SIGNALS_VIA_CHARACTERS,
+ disable the alternative code for using characters.
+
+Sat Mar 28 15:41:38 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * regex.c (re_match_2): Check for exactly -1 in regend.
+
+Fri Mar 27 02:29:16 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * data.c (arith_driver, Frem): Detect division by 0 by hand.
+ (arith_error): Call Fsignal again if it returns.
+
+ * indent.c (pos_tab_offset): Handle windows not ending at right margin.
+ * xdisp.c (try_window, try_window_id, display_text_line): Likewise.
+
+Mon Mar 23 22:09:00 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * keyboard.c (Fexecute_extended_command): Enlarge and write
+ this_command_keys properly.
+
+ * filelock.c (CREATE_LOCK_FILE_NAME): New macro; two definitions.
+ (SHORT_FILE_NAMES): New parameter macro.
+ (lock_file, unlock_file, Ffile_locked_p): Use it.
+ (fill_in_lock_short_file_name): New function.
+
+Sun Mar 22 23:10:01 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * process.c (Fopen_network_stream): Try host number first,
+ then host name.
+
+ * callproc.c, data.c, dispnew.c, emacs.c, keyboard.c, malloc.c:
+ * process.c, sysdep.c: Include sys/types.h before signal.h.
+ * s-isc2-2.h: Don't include sys/types.h.
+
+ * filetypes.h: New file.
+ * dired.c, fileio.c, filelock.c, filemode.c: Include filetypes.h.
+ * lread.c, sysdep.c: Likewise.
+
+Fri Mar 20 13:56:32 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * m-delta.h (mot_delta): New macro.
+ * alloca.s [mot_delta]: Treat this almost like hp9000s300.
+
+Thu Mar 12 15:34:51 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * process.c (process_send_signal): Test SIGNALS_VIA_CHARACTERS.
+ * s-irix3-3.h, s-isc2-2.h: Define SIGNALS_VIA_CHARACTERS.
+ * s-isc2-2.h: Include sys/types.h.
+ (TIOCGPGRP): Defined.
+
+Wed Mar 11 00:05:25 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * window.c: Doc fix.
+
+ * sysdep.c (OSPEED, SETOSPEED): Define only if undefined.
+
+ * process.c (process_send_signal): Fix up pfa conditional.
+
+Tue Mar 10 11:14:11 1992 Jim Blandy (jimb@pogo.cs.oberlin.edu)
+
+ * xdisp.c (redisplay_window): If the start position is forced,
+ constrain in to be within the visible range.
+
+Sat Mar 7 02:01:00 1992 Chris Hanson (cph@klia.ai.mit.edu)
+
+ * process.c (create_process): Don't execute SETUP_SLAVE_PTY or
+ child_setup_tty if using pipes. System V using STREAMS gets
+ errors when this is done.
+
+ * s-newsos5.h: New file for Sony NEWS-OS release 5.
+ * m-mips.h [NEWSOS5]: Changes so this file can be used with it.
+
+ * m-mips.h (XUINT, XSET, XUNMARK): Add parentheses to eliminate
+ warnings from GCC. Reindent to fit in 80 columns.
+
+Sat Mar 7 01:36:58 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * sysdep.c (rename) [__STDC__]: Make args match ANSI spec.
+
+ * m-ibmrs6000.h (signal): Define, as in m-intel386.h.
+
+ * dispnew.c (change_screen_size): Don't queue change if size is same.
+
+Thu Mar 5 17:26:35 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * m-intel386.h [USG5_4] (C_ALLOCA): Defined.
+
+ * unexmips.c (unexec): Use data_start, not DATA_START,
+ setting data_section->s_scnptr.
+
+ * ymakefile (LINKER): Define specially for GCC 2.
+
+ * m-delta.h (LIB_STANDARD): Add -lbsd.
+ (HAVE_TIMEVAL, HAVE_GETTIMEOFDAY, HAVE_SELECT, HAVE_SOCKETS):
+ (BROKEN_FIONREAD, USE_UTIME, HAVE_X_WINDOWS): New macros.
+ (LD_SWITCH_MACHINE): Deleted.
+
+ * x11term.c (stringFuncVal): Handle function key 10.
+
+ * x11term.c (XT_GetDefaults): Use CLASS with the cname.
+
+ * m-iris4d.h (XUINT, XSET, XUNMARK): Add parens for clarity.
+
+ * unexaix.c (unexec): Delete spurious semicolons from #ifdefs.
+ (make_hdr, mark_x, copy_text_and_data, copy_sym): Add static
+ forward decls.
+ (unrelocate_symbols): Cast initial values of t_start and d_start.
+
+ * hftctl.c: Include sys/uio.h.
+ Declare hfskbd and hfqry static at first.
+
+ * dispnew.c (direct_output_for_insert): Add parens around &&.
+
+ * lisp.h (XINT): Add parens for clarity.
+
+ * m-ibmrs6000.h (C_SWITCH_MACHINE): Value now empty.
+
+ * s-usg5-4.h (SYSV_STREAMS): Defined.
+ (HAVE_SOCKETS): Defined. This is an experiment.
+
+ * m-pfa50.h: New file.
+ * unexec.c (adjust_lnnoptrs): Handle pfa like amdahl_uts.
+ * process.c (create_process): Handle pfa like stride.
+ (process_send_signal): Add pfa conditional.
+ * sysdep.c [pfa]: Include sys/file.h.
+
+ * emacs.c [USG5]: Don't include fcntl.h twice.
+
+Tue Mar 3 17:37:46 1992 Chris Hanson (cph at kleph)
+
+ * unexec.c: Don't declare sbrk if compiling for HP-UX, because
+ the correct declaration is already supplied by <unistd.h>.
+
+Sat Feb 29 23:26:14 1992 Noah Friedman (friedman@nutrimat.gnu.ai.mit.edu)
+
+ * sysdep.c (get_system_name): use gethostname for USG systems if
+ HAVE_GETHOSTNAME defined.
+ * s-hpux7.h, s-irix3-3.h (HAVE_GETHOSTNAME): define it.
+
+Tue Feb 18 14:01:01 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * Version 18.58 released.
+
+ * process.c (create_process): Really don't use variable `sigchld'.
+
+Sun Feb 16 00:40:47 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * fileio.c: Doc fix.
+
+ * x11term.c: Define NULL if nec after all system headers.
+
+Fri Feb 14 02:50:33 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * m-news-risc.h (LINKER): #undef it.
+
+Thu Feb 13 17:54:46 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * x11term.c (XTflash): Wait just .15 sec.
+
+ * process.c, sysdep.c: Don't include termio.h if NO_TERMIO.
+ (TIOCGPGRP): If TRITON88, define as alias for FIOGETOWN.
+ * m-triton88.h: New file.
+
+Wed Feb 12 12:19:16 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * ymakefile ($(OLDXMENU)): If ln fails, use cp.
+
+ * m-tek4300.h (tek4300): Don't define if defined already.
+
+ * m-intel386.h (LIB_STANDARD): Add missing #endif.
+
+Tue Feb 11 16:23:15 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * process.c (BROKEN_O_NONBLOCK): New parameter; undefine O_NONBLOCK.
+ * m-pmax.h (BROKEN_O_NONBLOCK): Defined.
+ * m-vax.h (BROKEN_O_NONBLOCK): Defined, if ultrix.
+
+Mon Feb 10 21:14:38 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * data.c (Fset_default): Handle the case of mask < 0.
+
+ * s-isc3-2.h: File deleted. s-isc2-2.h does work for 3.2.
+
+Sun Feb 9 23:25:05 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * undo.c (Fprimitive_undo): Use Finsert_before_markers.
+
+Sat Feb 8 01:44:14 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * sysdep.c (child_setup_tty) [IRIS_4D]: Make sure we have VSWTCH char.
+
+ * m-intel386.h (HAVE_ALLOCA): Inhibit if C_ALLOCA.
+ (LIB_STANDARD): Alternate USG value if __GNUC__ or C_ALLOCA
+ * s-sco.h (alloca): Define C_ALLOCA or define alloca as builtin.
+ (BROKEN_TIOCWINSZ): Defined.
+
+ * s-isc2-2.h (SIGTSTP): Don't #undef this.
+
+ * process.c (PTY_OPEN): Handle new macro.
+
+Fri Feb 7 23:07:58 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * fileio.c (Fmake_symbolic_link): If error, try deleting link name
+ and then retry. Read first arg, not second, as raw string.
+
+Thu Feb 6 15:24:25 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * s-hpux7.h: Renamed from s-hpux.h.
+ * s-hpux8.h: Include s-hpux7.h.
+
+ * s-isc3-2.h: New file.
+
+Wed Feb 5 19:39:21 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * gettime.h: On DPX2, include sys/time.h.
+
+Tue Feb 4 01:03:05 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * s-sco.h (DONT_DEFINE_SIGNAL): Defined.
+
+ * window.c (window_scroll): If NOERROR, return indication of failure.
+ (Fscroll_other_window): Signal at end the error inhibited before.
+
+ * s-aix3-2.h: New file.
+
+Mon Feb 3 17:05:05 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * callproc.c (Fcall_process): Clear synch_process_* earlier.
+
+ * x11term.c (XT_Set_Size_Hints) [not X11R4]: Turn off "old, broken"
+ code to set min_width and min_height fields.
+
+ * x11term.c: Undo Jan 27 change.
+
+ * m-intel860.h: New file.
+
+Sun Feb 2 16:49:11 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * sysdep.c [_SEQUENT_]: Include stropts.h.
+
+ * sysdep.c, process.c, x11term.c, keyboard.c: Fix comments on #endif.
+
+Sat Feb 1 14:21:31 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * x11term.c (x_init_1): No args for setpgrp if USG.
+
+ * m-iris4d.h (C_SWITCH_MACHINE): Deleted.
+
+ * dispnew.c (remake_screen_structures): Put spaces in message_buf.
+ (make_screen_structure): Fill with spaces even if EMPTY.
+
+ * x11term.c (XT_Set_Size_Hints): Handle window gravity.
+
+Fri Jan 31 04:15:12 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * Makefile (distclean): Depend on clean; delete redundant stuff.
+
+ * x11term.c (XT_Set_Size_Hints): Test X11R4, not PBaseSize.
+ (X11R4): Default based on PBaseSize or SPECIFY_X11R4.
+ (SPECIFY_X11R4): New parameter macro.
+ * m-ibmrs6000.h (SPECIFY_X11R4): Defined.
+
+ * ymakefile (LIB_GCC, GNULIB_VAR): Handle GCC 2.
+
+ * s-hpux8.h (OLDXMENU_OPTIONS): New definition.
+
+ * s-sunos4-1.h (C_SWITCH_SYSTEM): Delete leading space.
+
+ * s-sunos4-0.h (SYSTEM_MALLOC): Deleted.
+
+Thu Jan 30 01:44:47 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * malloc.c (malloc): If SUNOS_LOCALTIME_BUG, get at least 16 bytes.
+
+ * dispnew.c (update_line): Prevent nlen from getting <0.
+
+ * x11term.c (XT_Set_Size_Hints): Test PBaseSize, not XICCC.
+
+ * m-orion105.h (C_DEBUG_SWITCH, LIBS_DEBUG): Defs deleted.
+
+Wed Jan 29 14:37:42 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * m-iris4d.h (C_SWITCH_MACHINE): New definition.
+
+Tue Jan 28 00:46:18 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * fileio.c (Fwrite_region): Remove Alliant conditional.
+ * crt0.c: Conditionals for ALLIANT_2800.
+ * m-all2800.h: New file.
+ * unexfx2800.c: New file.
+
+ * m-mips4.h (C_DEBUG_SWITCH): Alternate defn for GCC.
+
+ * sysdep.c [VMS] (sys_write): Special case for fixed-length
+ with carriage-control characters.
+
+ * s-isc2-2.h (NOMULTIPLEJOBS): Undef this.
+
+Mon Jan 27 18:57:26 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * s-isc2-2.h (LIB_STANDARD): Add -lPW.
+
+ * dispnew.c (update_line): ALLIANT patch to work around compiler bug.
+
+ * lread.c (readevalloop): Make forward declaration static.
+
+ * m-mips4.h (LD_SWITCH_MACHINE): Alternate definition if using GCC.
+
+ * dispnew.c (update_screen): If force, don't call detect_input_pending.
+
+ * x11term.c: #undef NULL before stdio.h.
+
+ * dispnew.c (make_screen_structure): Fill lines with spaces to start.
+
+ * s-hpux8.h (NO_SIOCTL_H): Defined.
+
+Sun Jan 26 00:33:35 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * dispnew.c: Fix doc string of visible-bell.
+
+ * m-mips.h (C_SWITCH_MACHINE): Defined, instead of C_SWITCH_SYSTEM.
+ (LINKER): Defined, if BSD.
+
+Sat Jan 25 16:01:00 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * fileio.c (Fexpand_file_name): When removing / from end of newdir,
+ don't change `/' to `'.
+
+ * dired.c (file_name_completion_stat): Try stat, then lstat.
+
+ * unexelf.c: Fix typo in last change.
+
+ * fileio.c (Finsert_file_contents) [AIX]: Don't open mpx files.
+
+ * fileio.c (Fmake_symbolic_link): Use `s' to read second arg.
+
+ * dispnew.c: Include errno.h.
+
+Thu Jan 23 14:03:44 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * s-usg5-4.h (LIBX10_SYSTEM): Add #undef.
+ (GNULIB): Definition deleted--done in ymakefile.
+ (LIB_STANDARD): Don't use GNULIB.
+ (HAVE_TCATTR): Defined.
+
+ * lisp.h (XINT): Add extra parens.
+
+ * unexelf.c: Handle rounding of section boundaries.
+ (round_up): New function.
+
+Wed Jan 22 22:32:28 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * m-tad68.h: New file.
+
+Tue Jan 21 21:49:43 1992 (Eric Youngdale at youngdale@v6550c.nrl.navy.mil)
+
+ * sysdep.c (sys_access) [VMS]: Fix bug whereby the default rather
+ than the actual privileges were used to determine if we have
+ file access.
+
+Mon Jan 20 12:41:27 1992 (Eric Youngdale at youngdale@v6550c.nrl.navy.mil)
+
+ * fileio.c (Finsert_file_contents) [VMS]: Adjust st_size
+ if file has fixed length records and implied carriage control.
+
+Sun Jan 19 23:39:10 1992 (Eric Youngdale at youngdale@v6550c.nrl.navy.mil)
+
+ * compile.com: Delete useless object file generated when sensing
+ the presence of a C compiler. Prevent user from seeing error
+ message when sensing C compiler.
+
+Sun Jan 19 11:29:00 1992 (Eric Youngdale at youngdale@v6550c.nrl.navy.mil)
+
+ * fileio.c (file_name_as_directory): Cast result of `index'.
+ (directory_file_name): Likewise.
+ * sysdep.c (getpwnam): Cast result of egetenv.
+
+ * vmsfns.c: Don't include syidef.h if using GCC.
+
+Sat Jan 18 23:16:41 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * Makefile (xmakefile): Write formfeed and tab literally.
+
+Sat Jan 18 13:41:54 1992 (Eric Youngdale at youngdale@v6550c.nrl.navy.mil)
+
+ * compile.com: Automatically use whichever C compiler is installed.
+
+Fri Jan 17 15:43:29 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * process.c (process_send_signal): Undo Nov 23 change.
+
+ * process.c (wait_reading_process_input): Use timeout_subtract.
+ * x11term.c (XTflash): Likewise.
+ * dispnew.c (Fsleep_for): Likewise.
+ (timeout_subtract): New function to subtract struct timeval.
+
+Thu Jan 16 01:47:48 1992 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * m-delta88.h: New file.
+
+ * window.c (window_scroll): New arg `noerror'.
+ (scroll_command, Fscroll_other_window): Pass that arg.
+
+ * indent.c (compute_motion): Don't pack vpos and hpos into one int;
+ use separate variables hpos/vpos and prev_hpos/prev_vpos.
+ (vmotion): Use largest int as tovpos arg to compute_motion.
+
+Wed Jan 15 03:39:37 1992 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * x11term.c (XT_GetDefaults): Use Xrm functions, then XGetDefault.
+ Include Xresource.h.
+
+ * callproc.c (Fcall_process): Get return status from
+ synch_process_death and synch_process_retcode.
+ * process.c (sigchld_handler): Set those vars.
+
+Sun Jan 12 17:05:53 1992 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * ymakefile (OLDXMENU_OPTIONS): New macro, used compiling oldxmenu.
+ * s-sunos4-1.h (OLDXMENU_OPTIONS): New definition.
+ (LD_SWITCH_SYSTEM, C_SWITCH_SYSTEM): New definitions.
+ * s-sunos4.h: File deleted.
+
+Fri Jan 10 15:56:11 1992 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * m-hp9000s800.h (S_IFLNK): Don't #undef this.
+
+ * s-hpux.h (CLASH_DETECTION): Define it.
+
+Thu Jan 9 00:25:15 1992 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * sysdep.c, process.c: Include sys/termios.h if NEED_TERMIOS.
+
+Tue Jan 7 23:38:33 1992 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * x11term.c (XTflash): Wait 1/4 sec even if interrupts come.
+
+ * process.c: Doc fix.
+
+Wed Jan 1 02:12:50 1992 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * window.c (init_window_once): Call make_window with no args.
+
+ * keyboard.c (command_loop_1): Move label directly_done.
+
+Tue Dec 31 15:53:00 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * emacssignal.h (signal_full_mask, signal_empty_mask): Vars renamed.
+ (sigmask): Copy from SIGEMPTYMASK.
+ (sys_sigpause): Argument is a mask.
+ (SIGFULLMASK, sigunblock, sys_sigdel): New non-POSIX definitions.
+ * sysdep.c (sigunblock): Definition removed.
+ (wait_for_termination): Change call to sigpause.
+ (signal_full_mask, signal_empty_mask): Vars renamed.
+ (signal_handler_t): Add missing `typedef'.
+
+ * s-dgux.h: Remove MAKING_MAKEFILE conditional.
+ Don't include signal.h.
+ (C_COMPILER, LINKER, MAKE_COMMAND): New definitions.
+ (LD_SWITCH_SYSTEM, START_FILES, LIBS_SYSTEM): New definitions.
+
+ * ymakefile (CC, MAKE): Set these variables from optional macros.
+ Change all uses of `make' to ${MAKE}.
+
+ * term.c (term_init): Change buffer size and malloc'd size to 4092.
+
+Fri Dec 13 17:22:42 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * s-isc2-2.h (LIBS_SYSTEM): Defined.
+
+Mon Dec 9 20:50:53 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * process.c (Fopen_network_stream): Handle EINTR from connect,
+ but turn off interrupts anyway.
+
+ * emacs.c (main): Do tzset if HAVE_TZSET.
+ * s-sunos4.h: Define HAVE_TZSET.
+
+Sat Dec 7 21:00:21 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * s-aix3-1.h (FIRST_PTY_LETTER): Deleted.
+ (PTY_ITERATION, PTY_NAME_SPRINTF, PTY_TTY_NAME_SPRINTF): New macros.
+
+Fri Dec 6 15:14:18 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * minibuf.c (read_minibuf_unwind): Clear readonlyness of minibuffer.
+
+Tue Dec 3 22:07:36 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * dispnew.c (change_screen_size_1): New arg FORCE forces redisplay.
+ (change_screen_size): Likewise. All callers changed.
+ (update_screen): Do the real work.
+ * x11term.c (internal_socket_read): Pass 1 for new arg.
+
+Mon Dec 2 23:14:29 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * lisp.h: Turn text after #endif, #else into real comment.
+
+Thu Nov 28 01:37:13 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * m-ibmps2-aix.h (HAVE_SETSID, HAVE_TCATTR): Defined.
+ (LIB_STANDARD): Remove -lbsd and -lrts.
+ Suggested by tranle@intellicorp.com.
+
+ * sysdep.c (child_setup_tty) [AIX]: If process_send_signal will use
+ chars, make sure we have chars for VQUIT and VINTR.
+
+ * lisp.h (DEFVARPERBUFFER, DEFVAR_PER_BUFFER):
+ Don't omit 3d arg to defvar_per_buffer.
+
+Sat Nov 23 16:51:13 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * emacs.c (main) [BSD4_3]: Call tzset.
+
+ * process.c (process_send_signal): On AIX, don't try sending character.
+
+Wed Nov 20 21:46:18 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * m-convex.h (XINT): Use submacros VSIGNBIT, VALLBITS.
+
+Tue Nov 19 16:11:57 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * config.h-dist (X11): Define only if HAVE_X_WINDOWS.
+
+ * s-irix3-3.h (IRIX): Defined.
+ * sysdep.c (get_system_name): Special code for IRIX.
+
+Sat Nov 16 16:53:44 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * s-irix3-3.h (HAVE_SETSID): Define here.
+ * s-irix4-0.h: Instead of here.
+
+ * process.c (process_send_signal): New code for Iris.
+
+Thu Nov 14 18:01:56 1991 Jim Blandy (jimb at wombat.gnu.ai.mit.edu)
+
+ * eval.c (specbind): Check that the thing being bound is a symbol.
+ (funcall_lambda): Signal an invalid-function error if the
+ arguments are not all symbols.
+
+Fri Oct 25 14:53:40 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * xdisp.c (redisplay): Properly compute TAB_OFFSET for compute_motion.
+
+ * s-irix4-0.h: New file.
+
+ * ymakefile: Fix comments on #endifs.
+
+ * unexmips.c (unexec): Get rid of error check about mismatch
+ in number of sections.
+
+ * s-irix3-3.h (C_ALLOCA): Defined.
+
+Tue Oct 22 01:41:09 1991 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * process.c (wait_reading_process_input): Redisplay if screen_garbaged.
+ Call do_pending_window_change first.
+ Include dispextern.h.
+ * ymakefile (process.o): Added dependency.
+
+Mon Oct 21 23:05:15 1991 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * buffer.c: Doc fix.
+
+Sun Oct 20 18:41:06 1991 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * x11term.c (XTflash): Flash just center quarter of window.
+
+Sat Oct 19 11:39:03 1991 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * process.c (create_process): Set bit in input_wait_mask before fork,
+ so sigchld_handler can clear it properly at any time.
+
+ * cmds.c (Fforward_line): Moving nowhere at eob after non-newline
+ should return 1, not 0.
+
+ * s-hpux.h (LD_SWITCH_SYSTEM): Defn deleted.
+ * s-hpux8.h (LD_SWITCH_SYSTEM): Move -L here.
+ (LIB_X11_LIB): Moved from here. Definition deleted.
+
+ * m-intel386.h (signal): Optionally don't define it.
+ * s-isc2-2.h (DONT_DEFINE_SIGNAL): Define this.
+
+ * x11term.c (internal_socket_read):
+ Do window size change immediately if currently waiting for input.
+ * dispextern.h (waiting_for_input): Declared here.
+
+Sun Oct 13 05:20:50 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * config.h-dist (PURESIZE): Increase to 120000 if no X.
+
+ * m-intel386.h: Fix typo in #endif.
+
+ * ymakefile: Use C style comment, not #.
+
+Sat Oct 12 14:34:26 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * x11term.c (internal_socket_read):
+ Threshold for real size change was off by one.
+
+ * emacs.c (main) [AIX]: Handle SIGURG, not SIGIOINT.
+
+Tue Oct 8 00:43:19 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * x11term.h: Never include X10.h.
+ * xmenu.c: Include it here.
+
+Tue Oct 8 00:07:47 1991 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * search.c (syms_of_search): Set re_max_failures here.
+ (compile_pattern): Not here.
+
+Sun Oct 6 14:47:52 1991 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * config.h-dist (X11): Define this by default.
+
+Sat Oct 5 14:00:22 1991 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * search.c (compile_pattern): Use bigger than default re_max_failures.
+
+ * x11fns.c: Move lisp.h and window.h later; undef NULL just before.
+
+Tue Sep 24 03:20:07 1991 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * alloca.c: Test __STDC__, not X3J11.
+ Do nothing if alloca is defined as a macro.
+
+Sun Sep 22 03:39:58 1991 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * editfns.c (Ffollowing_char): Really return 0 at eob.
+
+ * m-tandem-s2.h: Near complete rewrite.
+
+Sun Sep 15 17:36:02 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * ymakefile (paths.h, config.h): Never copy, always fail.
+
+Sat Sep 14 02:08:39 1991 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * dired.c (file_name_completion): Copy two improvements in ignoring
+ case from Ftry_completion: of inexact matches, prefer one that doesn't
+ change the case, and preserve user's input case whenever we can't
+ add any more text.
+
+ * process.c (create_process): Give subtty its permanent value
+ right from the start. Duplicate the descriptor.
+ Handle system call failures opening pty or pipes.
+
+ * sysdep.c (tcgetattr): Just one definition, if not HAVE_TCATTR.
+ [HAVE_TERMIO]: Coalesce duplicate definition and include.
+
+ * process.c (close_process_descs): Close subtty of proc if open.
+
+ * x11fns.c (Fcoordinates_in_window_p): Don't consider minibuf prompt.
+ That's now in x-mouse.el.
+
+Wed Sep 11 20:44:27 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * ymakefile (paths.h, config.h): Don't use sh -c. Get rid of @.
+
+Tue Sep 10 23:18:13 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * ymakefile (paths.h, config.h): Use explicit file names, not $?, $@.
+
+Mon Sep 9 20:32:35 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * crt0.c (start1): Declare static before first use.
+
+ * lread.c (read1): Don't accept integer containing quoted chars.
+
+Sun Sep 8 22:13:50 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * eval.c (Feval): Don't allow return without correcting backtrace_list.
+ (Ffuncall): Likewise.
+
+Tue Sep 3 20:49:28 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * sysdep.c (wait_for_termination): Use sleep loop instead of `pause'.
+
+Mon Sep 2 14:57:52 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * search.c (Fstring_match, search_buffer): Real Lisp error on overflow.
+
+ * lread.c (map_obarray): Don't die if obarray contains non-symbol.
+
+Sat Aug 31 14:38:51 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * sysdep.c (wait_for_termination): Make use of sysv sigpause.
+ * s-usg5-3.h (HAVE_SYSV_SIGPAUSE): Defined.
+
+ * emacs.c (main): Ignore SIGDANGER on aix.
+
+Thu Aug 29 01:29:47 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * editfns.c: Doc fix.
+
+Mon Aug 26 22:00:16 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * data.c (Fset): When this buffer sees default value,
+ thoroughly set the default value right away.
+
+Sat Aug 24 15:07:16 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * callproc.c: Doc fix.
+
+ * keyboard.c (Fopen_dribble_file): Handle closing the file.
+
+Thu Aug 22 01:37:40 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * commands.h (quit_char): Declare it.
+ * minibuf.c (temp_echo_area_contents): Use that var.
+
+Fri Aug 16 16:04:22 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * s-hpux.h (LD_SWITCH_SYSTEM): Defined.
+ * fileio.c: Changed a HPUX conditional to HPUX_NET.
+
+Mon Aug 12 21:29:05 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * abbrev.c (Fexpand_abbrev): Don't let capitalization go past point.
+
+Sat Aug 10 15:16:02 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * sysdep.c (sys_suspend): Don't use & before array name.
+
+ * sysdep.c [BROKEN_FIONREAD]: Undefine FASYNC.
+
+ * m-tandem-s2.h (START_FILES, LIB_STANDARD): Added.
+
+Fri Aug 2 14:01:24 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * s-aix3-1.h (HAVE_TCATTR): Defined.
+ * sysdep.c (HAVE_TERMIO definitions): Add HAVE_TCATTR inside IBMR2AIX.
+
+Thu Aug 1 18:38:29 1991 Roland McGrath (roland@churchy.gnu.ai.mit.edu)
+
+ * fileio.c (Fexpand_file_name): Avoid doing strlen (0).
+
+Thu Aug 1 12:31:38 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * emacs.c (main): Add SIGIO conditional within AIX conditional.
+
+ * xdisp.c (try_window_id): Compute proper position for screen bottom
+ when all changes are below the screen.
+ When first computing bp, don't go more than HEIGHT + 1 lines.
+
+Tue Jul 30 21:50:59 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * x11fns.c (Fx_proc_mouse_event): Clear out shift-lock bit.
+
+Sat Jul 27 13:43:29 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * window.c (init_window_once): Increment window_select_count.
+
+ * keymap.c (Fkeymapp): Doc fix.
+ (Fcopy_keymap): Don't recursively copy keymaps inside symbols.
+
+Mon Jul 22 21:26:00 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * s-dgux.h, m-aviion.h: New files.
+
+ * emacs.c (main) [POSIX_SIGNALS]: Call init_signal.
+
+ * fns.c (Fload_average) [DGUX]: Add alternate code.
+
+ * sysdep.c [DGUX] (sys_siglist): New variable.
+
+ * sysdep.c (_sobuf): Unsigned chars if DGUX.
+
+ * sysdep.c (init_signals, sys_signal, sys_sigpause): New functions.
+ (sys_sigblock, sys_sigunblock, sys_sigsetmask): New functions.
+
+ * emacssignal.h: New file.
+ * data.c, keyboard.c, process.c, sysdep.c, x11term.h: Include it.
+ * data.c (arith_error): Use SIGEMPTYMASK.
+ * keyboard.c (sigfree, sigunblockx): Use SIGEMPTYMASK.
+ (get_input_pending): Use SIGMASKTYPE.
+ * keyboard.c (sigholdx, sigblockx): Use sigmask.
+ * process.c (create_process): Use sigmask.
+ * sysdep.c (wait_for_termination): Use them.
+ [FASYNC] (request_sigio): Use sigunblock.
+ * x11term.h (BLOCK_INPUT_DECLARE): Use SIGMASKTYPE.
+ * x11term.c (sigunblockx): Use SIGEMPTYMASK.
+
+ * process.h (subtty): New slot.
+ * process.c (create_process): Set it.
+ (process_send_signal): Use it.
+
+ * sysdep.c [DGUX]: Include file.h.
+
+ * xdisp.c (try_window_id): Always update window_end_* if successful.
+
+Sun Jul 21 17:01:38 1991 Jim Blandy (jimb at geech.gnu.ai.mit.edu)
+
+ * editfns.c (init_editfns): If neither of the environment
+ variables are set, DON'T set Vuser_name to Vuser_real_name; it's
+ supposed to reflect the EFFECTIVE uid.
+ Get the full name according to Vuser_name if it differs from
+ Vuser_real_name, not if they are equal.
+ And pass Vuser_name to getpwnam in that case instead of user_name,
+ which might be 0.
+
+Fri Jul 19 15:15:59 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * keyboard.c (read_avail_input) [SYSV_STREAMS]: Don't alter O_NDELAY.
+ * x11term.c (x_init_1) [SYSV_STREAMS]: Don't close the old descriptor.
+
+Thu Jul 18 20:14:11 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * process.c (process_send_signal): Handle case where there is no pgrp.
+
+Mon Jul 15 04:48:44 1991 Jim Blandy (jimb at pogo.gnu.ai.mit.edu)
+
+ * process.c (status_notify): GCPRO tail.
+
+Sat Jul 13 16:53:15 1991 Jim Blandy (jimb at geech.gnu.ai.mit.edu)
+
+ * eval.c (Fapply): If we use funcall_args, GCPRO it.
+ And when we call Ffuncall with funcall_args, tell it the correct
+ length of funcall_args, no matter which branch allocated it.
+ (Feval): If we're calling a subr that takes MANY args, don't
+ UNGCPRO until after we call the subr.
+ * callint.c (Fcall_interactively): Don't UNGCPRO until after
+ Ffuncall returns.
+
+Tue Jul 9 13:27:25 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * sysdep.c (discard_tty_input): Do nothing if read_socket_hook.
+
+Mon Jul 8 22:04:15 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * process.c (create_process): Use O_NOCTTY whenever defined,
+ unless USG.
+
+Sun Jul 7 15:47:50 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * process.c (Fprocess_send_eof): If using a pipe, close it.
+ (close_process_descs): Check IN and OUT for nonzeroness.
+
+Thu Jul 4 00:18:48 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * process.c (process_send_signal): Use interrupt chars
+ to send certain signals to the process group.
+ (TIOCGETC): Undefine this if it is not really usable.
+
+Tue Jul 2 15:05:25 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * bytecode.c (Fbyte_code): Don't take away GC protection
+ of args given to Ffuncall. Ffuncall expects the caller to protect.
+
+Mon Jul 1 22:28:59 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * indent.c (invalidate_current_column): New function.
+ * editfns.c (Fwiden, Fnarrow_to_region): Call it.
+
+Sun Jun 30 16:56:33 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * keyboard.c (init_keyboard): Test HAVE_TERMIO instead of USG.
+
+ * ymakefile (LIBES): Put gnulib before libc.
+
+ * process.c (list_processes_1): Handle status of network streams.
+
+Sat Jun 29 11:59:22 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * search.c: Doc fixes.
+
+ * x11fns.c (Fx_set_foreground_color): Fix prompt.
+
+Sat May 25 02:05:57 1991 Roland McGrath (roland@geech.gnu.ai.mit.edu)
+
+ * dispnew.c [__GNU_LIBRARY__] (PENDING_OUTPUT_COUNT): Changed FILE
+ member names for recent GNU stdio.h reorganization.
+
+Sat May 18 13:10:24 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * process.c (Fprocess_status): Finish handling network connections
+ right.
+
+Thu May 16 12:16:41 1991 Jim Blandy (jimb at geech.gnu.ai.mit.edu)
+
+ * eval.c (Ffuncall): Don't gcpro args if we decide to
+ garbage-collect; in functions that take MANY arguments, the caller
+ gcpros the arguments.
+
+Tue May 14 21:38:59 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * keyboard.c (read_command_char): Exit at eof if noninteractive.
+
+Mon May 13 14:40:03 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * eval.c (call1, call2, call3): Reorder actions in NO_ARG_ARRAY case.
+
+ * print.c (strout): Set message_buf_print if appropriate.
+
+Wed May 8 16:59:41 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * insdel.c (insert_from_string, insert_from_string_before_markers):
+ New functions.
+ * editfns.c (Finsert, Finsert_before_markers): Use them.
+
+ * eval.c (apply1, call1, call2, call3): Protect arg vector.
+
+ * eval.c (Fapply): Protect funcall_args.
+
+Tue May 7 18:06:52 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * s-hpux8.h: New file.
+
+ * fileio.c [HPUX8]: Don't include errnet.h.
+
+ * unexhp9k800.c (unexec): Local variable i to avoid compiler bug?
+
+ * sysdep.c (insque) [WRONG_NAME_INSQUE]: New function.
+ * s-386ix.h (WRONG_NAME_INSQUE): Define it.
+
+Sat May 4 12:35:42 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * minibuf.c (Ftry_completion): If ignoring case, and all else equal,
+ try to preserve the case of the characters in the input.
+
+ * keymap.c (describe_map_tree): `maps' no longer register var.
+
+ * lread.c (init_read): If Vload_path was set specially before dumping,
+ preserve it by default.
+
+Fri May 3 15:19:07 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * x11term.c (internal_socket_read): Accept XK_Prior and XK_Next
+ explicitly as function keys. Process arrow keys on AIX
+ as on other systems.
+
+ * x11term.c (internal_socket_read):
+ Don't set x_focus_flag for a FocusIn that is not NotifyNormal.
+
+Fri May 3 00:29:20 1991 Jim Blandy (jimb at pogo.gnu.ai.mit.edu)
+
+ * x11term.c (delayed_size_change): Added extern declaration for
+ this variable, so the Expose and GraphicsExpose event handlers can
+ do nothing if there is a pending size change.
+ (configure_pending): Variable deleted, since the job
+ it used to do is now handled by delayed_size_change.
+ (internal_socket_read): rows and cols are now local to the
+ ConfigureNotify case, which now calls change_screen_size directly,
+ and asks for the size change to be put off until it can be handled
+ comfortably; the Expose case now doesn't deal with resizes at all,
+ and does not bother to redraw any text if there is a pending
+ screen size change. This eliminates an annoying flicker when the
+ window is resized. GraphicsExpose case follows a similar
+ inhibition.
+ (x_term_init): Don't initialize configure_pending, since it no
+ longer exists.
+ (XT_Set_Size_Hints): When calling change_screen_size, ask that the
+ size change not be delayed.
+ * dispnew.c (in_display): Variable deleted. It was only tested by
+ change_screen_size to see if the change should be delayed, only
+ set by the SIGWINCH handler and the X ConfigureNotify code, and
+ then only to tell change_screen_size what to do. It looks like a
+ parameter to me.
+ (window_change_signal): Instead of incrementing in_display,
+ calling change_screen_size, and then decrimenting, just ask
+ change_screen_size to delay the change.
+ (change_screen_size): Add an argument DELAYED, which indicates
+ that now is not a good time to do the size change, and that it
+ should be put off until a more convenient juncture.
+ (Fset_screen_height, Fset_screen_width): When calling
+ change_screen_size, ask that the size change not be delayed.
+ * keyboard.c (Fsuspend_emacs): Ditto.
+ * window.c (Fset_window_configuration): Ditto.
+ * xterm.c (xfixscreen, XSetWindowSize): Ditto.
+
+Wed May 1 12:30:51 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * keymap.c (describe_map_tree): GCPRO maps.
+
+Tue Apr 30 23:54:29 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * process.c (wait_reading_process_input):
+ Check NETCONN_P when checking for EIO.
+
+Tue Apr 30 14:28:45 1991 Jim Blandy (jimb at churchy.gnu.ai.mit.edu)
+
+ * window.c (save_window_save): Always get the selected window's
+ value of point from its buffer, not just when it's also the
+ current buffer.
+
+Mon Apr 29 23:36:30 1991 Jim Blandy (jimb at churchy.gnu.ai.mit.edu)
+
+ * abbrev.c (Fdefine_abbrev): When type-checking arguments, allow
+ EXPANSION to be nil.
+
+Sat Apr 27 21:56:59 1991 Jim Blandy (jimb at pogo.gnu.ai.mit.edu)
+
+ * keyboard.c (syms_of_keyboard): Qtop_level is initialized and
+ staticpro'd in syms_of_data too. Don't staticpro (or initialize)
+ it again here.
+
+ * macros.c (syms_of_macros): Since executing-macro and
+ executing-kbd-macro are actually the same variable, use
+ DEFVAR_LISP_NOPRO for the second one so it doesn't get staticpro'd
+ twice.
+
+ * process.c (syms_of_process): Don't staticpro or initialize Qexit
+ here, since syms_of_eval already does this and it's bad to
+ staticpro something twice.
+ (Qexit): Remove declaration here, so there will be a compilation
+ error if someone rearranges eval.c without fixing the Qexit stuff.
+ * eval.c (syms_of_eval): Add comment here to say that
+ syms_of_process cares about Qexit too.
+
+ * lread.c (init_obarray): Don't staticpro Vobarray, since the
+ DEFVAR_LISP in syms_of_read takes care of that.
+
+Sun Apr 21 14:44:33 1991 Roland McGrath (roland at albert.gnu.ai.mit.edu)
+
+ * filelock.c (lock_file_owner_name): Declare type of arg properly.
+
+Mon Apr 15 16:35:35 1991 Eric Youngdale (youngdale@v6550c.nrl.navy.mil)
+
+ * alloc.c (pure): No need to initialize under VMS. If we do
+ initialize the executable is 132000 bytes larger
+
+ * callproc.c, emacs.c: Fix def of environ when compiling with GCC
+ under VMS.
+
+ * fileio.c: fix data type of vms_file_written.
+
+ * malloc.c: Add a couple of type casts.
+
+ * s-vms.h: Define cfree. This keeps VAXCRTL memory management
+ functions from getting their grubby fingers in our memory.
+
+ * s-vms.h, vmsmap.c: Give proper name to sdata such that $D$ATA
+ and __DATA correctly bracket the impure memory. Increase size of
+ sdata and DATA_START, to make sure that impure memory starts at an
+ address > 8191, since otherwise garbage collection gets very
+ confused and Emacs bombs with peculiar errors.
+
+ Remove some flotsam in mapin_data - someone was trying to save the
+ argv and argc parameters, but never bothered to pass them in the
+ first place. This was wrong to begin with, since the reason the
+ argv and argc parameters were saved in the dump file was that
+ calloc was not defined as sys_calloc in s-vms.h
+
+ * sysdep.c: Include strings.h, and fix data type of dummy. Add
+ check to make sure that va_count is not already defined.
+
+ * vmsfns.c: Add type cast.
+
+Sun Apr 14 22:56:47 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * compile.com: Comments added for how to use GCC.
+ * link.com: Alternative command for linking if GCC is in use.
+
+ * malloc.c: Add forward decl for `malloc'.
+
+Sat Apr 13 18:10:28 1991 Eric Youngdale (youngdale@v6550c.nrl.navy.mil)
+
+ * sysdep.c (creat_copy_attrs, rename_sans_version): Always set
+ protection to O:REWD when creating file. Added new function
+ rename_sans_version, which strips the version number from the target
+ filename, renames the temporary file to this filename, and then
+ sets the file protection of this new file to be the same as the file
+ being edited.
+
+ * fileio.c (write-region): Use rename_sans_version instead of rename.
+
+Sun Apr 14 00:26:45 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * xdisp.c (display_text_line, display_string):
+ Don't go past endp for multi-column chars.
+
+Fri Apr 12 20:26:28 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * editfns.c (init_editfns): Turn off polling.
+
+Tue Apr 9 19:25:22 1991 Richard Stallman (rms at apple-gunkies)
+
+ * sysdep.c (child_setup_tty): Turn off erase & kill chars for BSD.
+
+ * editfns.c (init_editfns): Don't call getpwnam (0).
+
+Thu Apr 4 14:56:33 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * editfns.c (clip_to_bounds): Not static.
+
+ * vmsfns.c (vms_trnlog): Increased size of str to 256 elements.
+ (vms_symbol): Increased size of str to 1025 elements.
+
+Wed Apr 3 21:13:09 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * window.c (unshow_buffer): Keep PT in bounds when setting it.
+
+Tue Apr 2 17:57:37 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * process.c (Fprocess_status): Test of childp was backwards.
+
+Mon Apr 1 00:06:36 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * emacs.c: Include headers to get FIONREAD, as in keyboard.c.
+
+Sun Mar 31 15:38:48 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * dired.c (file_name_completion_stat): Use lstat.
+ * fileio.c (Ffile_exists_p): Use lstat.
+
+ * getpagesize.h [VMS]: Include param.h from Emacs.
+ * malloc.c (vms_current_brk): Delete spurious ampersand.
+ * s-vms.h (getppid): New macro.
+ (sdata): Alternate declaration for GNU C.
+ (Vminibuffer_completion_table, etc.): New macros.
+ * sysdep.c [VMS]: Include pwd.h from Emacs. Use sys/file.h if GCC.
+ (F_SETFL) [VMS]: Undefine this, to control conditionals.
+ (bzero, bcopy) [VMS]: Don't take address of `length'.
+ (getpwnam): Make `full' unsigned.
+ (creat_copy_attrs): Add some casts.
+ (sys_access): Change prvmask and CHECKPRIV to use bitfields.
+ Add some casts.
+ (vmserrstr): Add a cast.
+ * vmsmap.c (mapin_data, mapout_data): Add some casts.
+ (sdata, edata): Alternate declarations for GNU C.
+ * vmsfns.c: Include clidef.h and syidef.h.
+ (getjpi, translate_id): Add cast.
+ (translate_id): Make p unsigned.
+ (Fvms_system_into, Fsetprv): Likewise for other variables.
+ (Fspawn_subprocess): Cast call to xmalloc.
+ (vms_version_fn, vms_trnlog, vms_symbol): Add casts.
+
+ * minibuf.c (Ftry_completion): Fix error in previous change.
+
+ * editfns.c, filelock.c [VMS]: Use pwd.h from Emacs, not from system.
+ * fileio.c [VMS]: Likewise. Also include stddef.h, string.h.
+ Include perror.h only once.
+ (expand_file_name): Cast result of index.
+
+ * window.c (replace_window, unshow_buffer, save_window_save):
+ Add forward declarations. Make some return void.
+ * keymap.c (insert_first_line): Likewise.
+ * lread.c (read_escape): Likewise.
+ * unexec.c (make_hdr, copy_text_and_data, copy_sym, mark_x): Likewise.
+ * x11term.c (XInitWindow): Likewise.
+
+ * x11term.c: Cast args to avoid warnings from XLib fns.
+
+Sat Mar 30 17:53:09 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * sysdep.c (sys_sleep, input_wait_timeout): Don't use & on constant.
+ (sys_access): Likewise.
+ (sys_creat): Define va_count.
+ * vmsfns.c (Fspawn_subprocess, create_mbx): Don't use & on constant.
+ (translate_id, vms_version_fn, vms_proclist
+ (JPI$_MASTER_PID, JPI$_CLINAME): Don't define if already defined.
+ (CLI$M_NOWAIT, SYI$_VERSION): Likewise.
+
+ * lastfile.c, filelock.c, process.c: Add a dummy function if VMS.
+
+ * fileio.c: Change VMS conditionals for header files.
+
+ * dir.h (dir$t_name, dir$t_linkname): Use standard syntax for pointer.
+
+ * callproc.c (environ) [VMS and __GNUC__]: Different declaration.
+
+Mon Mar 25 17:53:38 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * minibuf.c (Ftry_completion): Fix handling of matches aside from case.
+
+ * dispnew.c (update_line): Crash if obody[-1] is clobbered.
+
+Sun Mar 24 21:15:45 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * x11term.c (x_io_error_handler): Raise a signal to kill Emacs.
+
+ * m-news-risc.h (LD_SWITCH_MACHINE): New definition if USG.
+ (LOAD_AVE_TYPE): Likewise.
+ (START_FILES, LIB_STANDARD): Undef before m-mips.h.
+ (alloca): Use built-in with GCC.
+
+Sat Mar 23 16:14:43 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * fileio.c (directory_file_name): Fix off-by-one testing slen at end.
+ (Fexpand_file_name): Remove excess slash from end of user's home dir.
+
+Fri Mar 22 18:19:21 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * s-usg5-4.h (DATA_SEG_BITS): Definition deleted.
+ * m-intel386.h (DATA_SEG_BITS): Define here if USG5_4.
+
+Thu Mar 21 17:16:15 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * m-mips.h: INHIBIT_BSD_TIME prevents including bsd/sys/time.h.
+
+ * m-news-risc.h: Add conditionals for USG.
+
+ * unexmips.c [sony]: Include getpagesize.h and fcntl.h.
+
+Tue Mar 19 17:30:09 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * keyboard.c (read_avail_input): Raise SIGHUP if no input on AIX.
+
+Mon Mar 18 18:38:55 1991 Roland McGrath (roland at geech.ai.mit.edu)
+
+ * minibuf.c (assoc_for_completion): Add missing defn of local var.
+
+Mon Mar 18 17:09:40 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * xkeys-aix.h: Turn on redefinition of backspace.
+
+ * x11term.c (x_term_init): Handle X_DEFAULT_FONT.
+
+Sun Mar 17 23:50:50 1991 Richard Stallman (rms@mole.ai.mit.edu)
+
+ * minibuf.c (assoc_for_completion): New function.
+ (do_completion): Use that to check for exact match.
+
+Thu Mar 14 17:06:14 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * fileio.c (Fwrite_region): On VMS, don't try rewriting old version.
+
+Mon Mar 11 21:09:02 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * xdisp.c (redisplay, try_window_id): Special case for change
+ at beginning of line, if using selective display.
+
+Sun Mar 10 19:44:50 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * fileio.c (Fmake_symbolic_link): Don't expand FILENAME.
+
+Sat Mar 9 22:59:19 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * eval.c (Fcatch, internal_condition_case): Fill in c.handlerlist.
+
+ * buffer.c (Frename_buffer): Refuse to rename a minibuffer.
+
+Fri Mar 8 02:52:31 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * m-intel386.h (signal): Maybe define if USG.
+
+ * keyboard.c (echo_char): Don't have a space at end of echobuf.
+
+Wed Mar 6 14:32:14 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * s-vms.h (DATA_START): Remove `+ 512'.
+
+Tue Mar 5 14:04:03 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * emacs.c, xterm.c:
+ Handle BROKEN_FIONREAD, to undef FIONREAD and SIGIO.
+
+ * m-amdahl.h (LIBX11_SYSTEM): Undefine it.
+
+Sun Mar 3 17:15:44 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * sysdep.c (MEMORY_IN_STRING_H): New compilation flag.
+ * s-isc2-2.h: New file.
+
+ * emacs.c: Use EQ rather than NULL.
+ Include stdio.h after lisp.h, and preserve its meaning of NULL.
+
+ * gettime.h: New file. Handles time.h and/or sys/time.h.
+ * process.c, x11term.c, x11fns.c: Use that, not those others directly.
+ Make sure to include sys/socket.h first, if have sockets.
+
+Tue Feb 26 23:44:05 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * s-vms.h (calloc): Define it like malloc, etc.
+
+Tue Feb 26 15:07:30 1991 Jim Blandy (jimb at churchy.ai.mit.edu)
+
+ * editfns.c (in_accessible_range): Deleted - insufficently general.
+ (clip_to_bounds): New function, much like in_accessible_range,
+ except that the upper and lower bounds are arguments.
+ (goto_char, save_restriction_restore): Rewritten to use
+ clip_to_bounds instead of in_accessible_range.
+
+Mon Feb 25 23:44:31 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * x11term.c (xfixscreen): Move static var outside function.
+
+Sun Feb 24 15:57:05 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * m-amdahl.h (C_OPTIMIZE_SWITCH): Don't define if already defined.
+ (HAVE_TIMEVAL, MISSING_UTIMES, HAVE_SELECT, HAVE_PTYS, HAVE_SOCKETS):
+ (BSTRING, BROKEN_FIONREAD, LIBX11_MACHINE): New macros.
+ * process.c, x11term.c (sys/time.h): Treat uts like aix.
+
+ * xdisp.c (message_buf_print): New variable.
+ * dispextern.h: Declare it.
+ * xdisp.c (message): Store 0 there.
+ * print.c (printchar): Use and set it.
+
+ * process.c (wait_reading_process_input): Use NETCONN_P.
+
+Sat Feb 23 15:22:57 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * process.c (send_process): Handle EAGAIN like EWOULDBLOCK.
+
+Fri Feb 22 15:47:47 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * xkeys-aix.h: Move unmodified keys to the end.
+
+Thu Feb 21 14:55:21 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * window.h (prev_echo_area_contents): Declare it.
+ * minibuf.c (do_completion): Clear that var before temporary message.
+
+ * fileio.c (report_file_error): Don't downcase "I/O".
+
+Sat Feb 9 13:23:05 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * sysdep.c (TERMINAL): Move the definitions inside other #ifdef's.
+ (tcgetattr): New sym. Define as macro if not HAVE_TCATTR.
+ Use instead of ioctl TIOCGETP.
+ (discard_tty_input, child_setup_tty, init_sys_modes, reset_sys_modes):
+ If HAVE_TCATTR, use tcsetattr.
+ (init_sys_modes): Handle VSUSP, V_DSUSP if HAVE_TCATTR.
+
+ * vmsmap.c (mapin_data): Save and restore argv; copy the strings.
+
+ * m-amdahl.h (NO_SIOCTL_H): Defined.
+
+ * x11fns.c, x11term.c: Include fcntl.h only once.
+
+ * window.c (syms_of_window): New variable minibuffer-prompt-width.
+
+ * emacs.c (decode_env_path): Ignore EVARNAME if 0.
+ * lread.c (init_read): Change call.
+ * callproc.c (init_callproc): Likewise.
+
+ * sysdep.c (dup2): Rewrite of non-F_DUPFD case.
+
+Fri Feb 8 00:03:24 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * m-intel386.h (LOAD_AVE_CVT): Add extra parens.
+ * s-usg5-4.h (LIBX11_SYSTEM): #undef it.
+
+Thu Feb 7 12:47:24 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * search.c (Fmatch_data): Return ints for values above buf size.
+
+ * callint.c (global_map): Make declaration extern.
+ * process.c (Qexit): Likewise.
+
+Wed Feb 6 02:55:40 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * dispnew.c (update_line): If nlen becomes 0, go to just_erase.
+
+ * process.c (create_process): On Apollo, use O_NOCTTY to open pty.
+
+ * process.c (wait_reading_process_input): Special case APOLLO like sun.
+
+ * sysdep.c (discard_tty_input): Use TIOCFLUSH on Apollo.
+ (init_sys_modes): Avoid TIOCSTART on Apollo.
+
+ * keyboard.c (command_loop_1):
+ Don't clear last_command when start macro.
+
+ * window.c (init_window_once): Set use_time to 1 for root_window.
+
+Tue Feb 5 00:27:33 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * xdisp.c (display_text_line, display_string):
+ Don't write past end of available space.
+ * dispnew.c (update_line): Don't clobber the null that follows
+ the writable space in a screen line.
+
+ * x11fns.c: Always include ioctl.h except on VMS.
+
+ * keyboard.c (this_command_keys): Now type unsigned char *.
+ (read_command_char, Fexecute_command_char): Cast to proper type.
+ (init_keyboard): Likewise.
+
+Mon Feb 4 17:50:45 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * s-sunos4-0.h: Renamed from s-sunos4.h.
+ (read, write, open, close): Macro defs moved to s-sunos4-1.h.
+ (INTERRUPTABLE_*): Likewise.
+ * s-sunos4-1.h: New file.
+
+Sun Feb 3 21:50:00 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * Makefile, ymakefile (SHELL): Force use of sh.
+
+ * s-usg5-4.h (USG5_4): Define it.
+ (LOAD_AVE_*): Don't define them.
+ * m-intel386.h (LOAD_AVE_*): Define, if USG5_4.
+
+ * buffer.c (Fbuffer_local_variables): Omit slots with no names.
+
+Sat Feb 2 11:45:44 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * process.c (Fprocess_status): For net stream, return Qopen or Qclosed.
+
+ * eval.c (struct catchtag): New slot `handlerlist'.
+ (internal_catch): Record that.
+ (unbind_catch): Use that.
+
+Thu Jan 31 16:13:41 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * x11term.c (XTfeep): Pass 0 as second arg to XBell.
+
+Tue Jan 29 14:55:06 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * unexec.c (make_hdr) [TPIX]: Set f_hdr.f_nscns and f_thdr.f_scnptr.
+
+ * sysdep.c [BROKEN_TIOCGWINSZ]: Undef TIOCGWINSZ.
+
+ * malloc.c (cfree): New function.
+
+ * process.c (wait_reading_process_input): Don't ignore
+ a zero-length read on a network connection. Do close it.
+
+ * sysdep.c (hft_init, hft_reset): Pass &junk as arg to HFQERROR.
+
+Fri Jan 25 16:40:33 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * Version 18.57 released.
+
+ * eval.c (Fthrow, Fsignal): Restore poll-suppress count, don't crash.
+
+ * regex.c (re_match_2): Value of PTR_CHAR_POS is off by 1; compensate.
+
+Thu Jan 24 12:43:35 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * x11term.c (XT_GetDefaults): Support XBACKWARDS.
+
+Wed Jan 16 18:57:00 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * Version 18.56 released.
+
+Tue Jan 15 13:13:36 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * sysdep.c (init_sys_modes):
+ Don't mess with VSUSP, V_DSUSP except on a Mips.
+
+ * process.c (create_process): Use SETUP_SLAVE_PTY if defined.
+
+ * s-usg5-4.h (HAVE_PTYS, HAVE_SETSID): Defined.
+ (HAVE_WAIT_HEADER, WAITTYPE, wait3, WRETCODE): New macros.
+ (TIOCSIGSEND): Alias for TIOCSIGNAL.
+ (FIRST_PTY_LETTER): Overridden.
+ (PTY_NAME_SPRINTF, PTY_TTY_NAME_SPRINTF, SETUP_SLAVE_PTY): New macros.
+
+ * m-ibmrs6000.h (LINKER): Add -bnodelcsect.
+
+ * x11fns.c (Fx_get_default): XBACKWARDS flips XGetDefault args.
+
+Mon Jan 14 13:30:32 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * sysdep.c (hft_init, hft_reset): Do nothing if not HFT.
+
+ * m-ibmrs6000.h (CANNOT_DUMP): Undefine it.
+ (UNEXEC): Define it.
+ (PURE_SEG_BITS, SHMKEY): Define only if CANNOT_DUMP.
+ (LINKER): Override it.
+
+Sun Jan 13 23:10:34 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * s-usg5-4.h (LOAD_AVE_CVT): Cast value to int.
+
+Sat Jan 12 14:50:45 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * s-irix3-3.h (HAVE_SYSVIPC): Defined.
+
+Fri Jan 11 11:45:19 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * emacs.c (Fkill_emacs): Turn off SIGIO before exiting.
+
+ * s-usg5-3.h (USG5_3): Define it.
+ * m-ibmps2-aix.h [USG5_3]: Define TEXT_START as 0.
+ Don't define DATA_START or DATA_END or TEXT_END or DATA_SEG_BITS.
+ Override various other symbols at end of file.
+
+ * m-tower32v3.h (VALBITS, GCTYPEBITS): Use 26 bits for pointer.
+
+Thu Jan 10 12:33:20 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * x11fns.c (Fx_debug, Fx_get_cut_buffer, Fx_get_*_color):
+ Call check_xterm.
+
+ * fileio.c (Fcopy_file): Always close descriptors.
+
+ * s-sunos4.h: read, write, open and close are interruptable.
+
+Tue Jan 8 20:46:34 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * keyboard.c (input_available_signal): If FIONREAD fails, do SIGHUP.
+
+Sun Jan 6 23:25:24 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * sysdep.c (init_sys_modes): Turn off VSUSP and V_DSUSP if they exist.
+
+Thu Jan 3 17:30:46 1991 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * search.c (search_buffer): Return starting position if count == 0.
+
+Thu Dec 27 13:54:20 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * m-tower32.h: Add comments for how to optimize.
+ * m-tower32v3.h: New file.
+
+ * fileio.c (Fwrite_region): Save errno around unlock_file.
+
+Thu Dec 20 18:09:19 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * term.c (ins_del_lines): Handle scroll region wrt chars_wasted.
+
+Wed Dec 19 19:04:27 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * alloc.c (memory_full): Use preallocated arg to Fsignal.
+ (syms_of_alloc): Preallocate it.
+
+ * bytecode.c (Fbyte_code): Consider GC in each loop.
+
+Wed Dec 12 16:17:56 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * keyboard.c (command_loop_1): Really bind inhibit-quit.
+
+ * abbrev.c (Fdefine_abbrevs): Don't crash when EXPANSION is nil.
+
+Wed Dec 12 03:35:47 1990 Chris Hanson (cph at kleph)
+
+ * keyboard.c (command_loop_1): Bind inhibit-quit to t while
+ displaying message over active minibuffer.
+
+ (get_input_pending): If quit-flag is set by read_avail_input,
+ count that as an input character.
+
+Mon Dec 10 00:11:29 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * m-pmax.h (SYSTEM_MALLOC): Define it.
+
+ * search.c: Doc fix.
+
+ * process.c (wait_reading_process_input): Ignore failure with EIO.
+
+ * process.c (create_process): Delete duplicate sigsetmask.
+
+Sun Dec 9 23:38:51 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * m-ibmrt.h (RTPC_REGISTER_BUG, SHORT_CAST_BUG): Macros deleted.
+ (C_SWITCH_MACHINE): Use -D to define alloca.
+ (SIGN_EXTEND_CHAR): Use a cast.
+
+Sun Dec 2 15:39:18 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * fns.c (Fload_average): Add IRIS conditional.
+
+ * m-iris4d.h (LOAD_AVE_CONVERT): Divide by 1024.
+
+ * s-irix3-3.h (ADDR_CORRECT): Macro deleted.
+ (LIBS_MACHINE): Macro deleted.
+ (LDAV_SYMBOL): Delete the `_' from start of symbol.
+
+ * process.c (status_notify): Was failing to UNGCPRO for dead buffer.
+
+Fri Nov 30 18:07:13 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * process.c (read_process_output, exec_sentinel): Don't catch errors.
+
+ * keyboard.c (read_command_char): Save and restore getcjmp.
+
+Thu Nov 29 16:57:02 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * x11term.c (XT_Set_Size_Hints): Rewrite XICCC case.
+
+ * process.c (status_convert): Use WRETCODE for exited process.
+
+Wed Nov 28 18:02:40 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * x11term.c (x_term_init):
+ Use progname as XXidentity even if matches CLASS.
+ * x11term.h (CLASS): Use Emacs, not emacs.
+
+ * s-386ix.h (ISC): New macro.
+
+Tue Nov 27 14:19:44 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * dispnew.c (PENDING_OUTPUT_COUNT): Alternate defn for GNU library.
+
+Mon Nov 26 14:34:12 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * x11term.c (XTfeep): Do nothing unless HAVE_SELECT and HAVE_TIMEVAL.
+
+ * s-sunos4.h (O_NDELAY): Don't define this.
+
+ * s-usg5-4.h (LIB_STANDARD): Add libucb.a.
+
+ * print.c (Fwith_output_to_temp_buffer): Don't eval first arg twice.
+
+Thu Nov 22 14:24:00 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * m-hp9000s300.h (LOAD_AVE_TYPE, LOAD_AVE_CVT): Override for BSD.
+
+ * doc.c (Fsubstitute_command_keys): Use IDX only around GC points.
+ Get rid of SEND.
+
+Wed Nov 21 14:43:01 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * m-mips4.h (MIPS2): Undefine this.
+
+ * x11term.c (internal_socket_read):
+ Avoid redrawing cursor when no change.
+
+Tue Nov 20 17:12:41 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * process.c (sigchld_handler): Don't look for new proc if found old.
+
+ * x11term.c (internal_socket_read): Record whether have explicit focus.
+ Handle LeaveNotify events accordingly.
+
+ * fns.c (Fyes_or_no_p): Protect PROMPT for entire loop.
+ * process.c (status_notify): Protect MSG.
+
+ * doc.c (Fsubstitute_command_keys): Protect STR and don't keep a
+ pointer to the middle of it.
+ * keyboard.c (Fsuspend_emacs): Protect STUFFSTRING.
+ (cmd_error): Protect TAIL while printing.
+ * keymap.c (describe_alist): Protect ELT_PREFIX and TEM2.
+ (describe_vector): Likewise for ELT_PREFIX and TEM1.
+ (insert_first_line): Protect STR.
+
+ * process.c (Fstart_process): Set BUFFER before other string vars
+ so a gc in Fget_buffer_create won't clobber them.
+
+ * process.c (Fopen_network_stream): Protect various args.
+ * print.c (Fprin1_to_string, Fprint): Protect OBJ.
+ * fileio.c (Frename_file): Protect args.
+ * search.c (Freplace_match): Protect STRING.
+
+ * dispnew.c (syms_of_dispnew): Don't clobber Vwindow_system_version
+ if CANNOT_DUMP.
+
+Mon Nov 19 17:56:18 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * emacs.c (Fkill_emacs): Protect ARG.
+
+ * fileio.c (Fadd_name_to_file): Protect the args.
+ (Fcopy_file, Fmake_symbolic_link): Likewise.
+ (Finsert_file_contents): Protect FILENAME.
+
+ * buffer.c (Fbury_buffer): Don't init BUF1.
+
+ * eval.c (Fbacktrace): Protect TAIL from GC.
+
+ * scroll.c (CalcIDCosts1): Use calculate_costs_hook.
+ * x11term.c (x_term_init): Set up the hook.
+ (XTcalculate_costs): New function.
+ * dispnew.c (init_display): Call calculate_costs here.
+ * term.c (term_init): Not here.
+
+Thu Nov 15 16:29:18 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * lread.c (Feval_region): Check type of B.
+
+ * dired.c (file_name_completion): Use CHECK_STRING on FILE.
+
+Tue Nov 13 12:04:10 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * process.c (sigchld_handler): If pid not recognized, look for a
+ process recorded with pid -1.
+ (create_process): Set pid to -1 before the fork.
+ Store correct pid right after the fork.
+ Don't change sigchld handler on system V.
+
+ * keyboard.c (input_poll_signal, start_polling): Use polling_period.
+ (syms_of_keyboard): Initialize it and make it a Lisp var.
+
+ * malloc.c: Use vlimit on VMS.
+
+ * process.c (create_process): Handle HAVE_SETSID when not USG.
+
+ * x11term.c (XT_GetDefaults): Handle temp_useBitmap.
+ (xDefaultsValueTable): Handle bitmapIcon.
+
+ * fileio.c (err_str): New macro.
+ (Finsert_file_contents, Fwrite_region): Use it in error messages.
+
+Mon Nov 12 17:18:00 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * insdel.c (del_range): Supply missing arg to gap_left.
+
+ * indent.c (Findent_to): Don't fail to return a value.
+
+ * process.c (run_filter): New function.
+ (read_process_output, exec_sentinel): Use it to call the function.
+
+Sun Nov 11 00:37:50 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * xdisp.c (try_window_id): When checking val.hpos < 0,
+ to update tab_offset, correct for hscroll.
+
+ * ymakefile (xemacs): Link xemacs to temacs if HAVE_SHM.
+
+ * m-ibmrs6000.h (HAVE_SHM): Undefine this since does not work.
+
+ * fns.c (Fnthcdr): Stop loop if reach end.
+
+ * dispnew.c: Undef SIGIO if no FIONREAD.
+ Include fcntl.h if HAVE_TERMIO.
+
+Fri Nov 9 23:22:37 1990 Chris Hanson (cph at kleph)
+
+ * eval.c (struct catchtag): Add new element `poll_suppress_count',
+ which records the value of that variable at the time the catchtag
+ is bound.
+ (internal_catch): Initialize the new element.
+ (Fcondition_case): Likewise.
+ (internal_condition_case): Likewise.
+ (Fthrow): Instead of calling `barf_if_polling_suppressed', abort
+ if current value of `poll_suppress_count' is different from what
+ it was when the catchtag was bound.
+
+ * keyboard.c (barf_if_polling_suppressed): Delete this, it's not
+ referred to anymore.
+
+Tue Nov 6 21:37:36 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * process.c (wait_reading_process_input): Don't read input
+ from more than one process between calls to `select'.
+
+ * m-ibmrs6000.h (CANNOT_DUMP): Define this.
+
+ * process.c (create_process): Unblock SIGCHLD in the child.
+
+Mon Nov 5 18:38:18 1990 Chris Hanson (cph at kleph)
+
+ * keyboard.c: Define and initialize the variable
+ `poll_suppress_count' even when polling is not being used.
+ * lisp.h: Extern the variable `poll_suppress_count'.
+
+ * lisp.h (struct handler): Add new element `poll_suppress_count',
+ which records the value of that variable at the time the handler
+ is bound.
+ * eval.c (Fcondition_case): Initialize new element.
+ (internal_condition_case): Likewise.
+ (Fsignal): Instead of calling `barf_if_polling_suppressed', abort
+ if current value of `poll_suppress_count' is different from what
+ it was when the handler was bound.
+
+Fri Nov 2 15:13:17 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * malloc.c (get_lim_data): Test !BSD4_1, not BSD4_2.
+
+ * callint.c (syms_of_callint):
+ Initialize Vprefix_arg and Vcurrent_prefix_arg.
+
+Fri Nov 2 01:34:47 1990 Chris Hanson (cph at kleph)
+
+ * keyboard.c (barf_if_polling_suppressed): Don't do anything
+ unless `read_socket_hook' is nonzero.
+
+ * keyboard.c (barf_if_polling_suppressed): Define this again, but
+ don't do anything if `initialized' is not set.
+ * eval.c (Fthrow): Call it.
+ (Fsignal): Call it.
+
+ * lisp.h: Define `Qinhibit_quit'.
+ * eval.c: Likewise.
+
+Fri Nov 2 01:09:20 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * process.c (read_process_output): Inhibit quit in filter.
+ (exec_sentinel): Likewise.
+
+Wed Oct 31 18:13:08 1990 Chris Hanson (cph at kleph)
+
+ * keyboard.c (barf_if_polling_suppressed): Delete this function.
+ (quit_throw_to_read_command_char): Inline call to it here.
+ * eval.c (Fthrow, Fsignal): Delete calls to it.
+
+Wed Oct 31 00:45:39 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * process.c (wait_reading_process_output): Don't turn off polling.
+
+ * keyboard.c (barf_if_polling_suppressed): New function.
+ (quit_throw_to_read_command_char): Call it.
+ * eval.c (Fthrow): Call it.
+ (Fsignal): Call it.
+
+Thu Oct 25 22:39:24 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * x11fns.c (Fx_store_cut_buffer): Clear selection owner.
+
+Wed Oct 24 15:18:14 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * ymakefile (GNULIB_VAR): New make variable.
+ (LIBES): Use that, not LIB_GCC directly.
+ (LIB_GCC): Renamed from GNULIB. Don't define if already defined.
+
+Tue Oct 23 01:19:25 1990 Roland McGrath (roland at churchy.ai.mit.edu)
+
+ * x11fns.c, x11term.c: Include header for FIONREAD.
+
+Mon Oct 22 14:07:45 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * scroll.c (struct matrix_elt): Use ints for costs.
+ * dispextern.h (INFINITY): Moved here from scroll.c.
+ * dispnew.c (scrolling): If new line not enabled, draw cost = INFINITY.
+
+ * keyboard.c (quit_char): New variable.
+ (init_keyboard): Initialize it.
+ (Fset_input_mode): New optional arg to set quit_char.
+ (command_loop_1, read_command_char, kbd_buffer_store_char):
+ (read_avail_input, input_available_signal): Use quit_char, not C-g.
+ * sysdep.c (init_sys_modes): Use quit_char to set special chars.
+ * x11term.c (x_init_1): Call to Fset_input_mode fixed.
+
+Sun Oct 21 15:21:39 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * sysdep.c (select): Handle timeout == 0. Add var local_timeout.
+
+ * ymakefile (LIBES): Put LIBS_SYSTEM and LIBS_MACHINE after LIBX.
+
+ * x11fns.c: After config.h, maybe undef FIONREAD and SIGIO.
+
+ * alloc.c (Fcons, Fmake_vector, Fmake_symbol, Fmake_marker):
+ (make_uninit_string): Use VALIDATE_LISP_STORAGE.
+ (VALIDATE_LISP_STORAGE): New macro.
+
+ * fileio.c (Fcopy_file): Detect error closing output.
+
+Sat Oct 20 00:59:31 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * xdisp.c (message, message1): Clear noninteractive_need_newline.
+
+Fri Oct 19 17:25:48 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * buffer.c: Doc fix.
+
+Thu Oct 18 13:43:50 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * m-intel386.h (alloca): Define as builtin, if using GCC.
+
+ * ymakefile (GNULIB): New macro.
+ (LIBES): Use that macro. Fixes linking if compiled with GCC.
+
+ * m-att3b.h (NEED_PTEM_H): Define this for 3b2.
+
+ * s-aix3-1.h (SYSV_SYSTEM_DIR): Define it.
+
+ * print.c (print): Improve error message for bad data type.
+
+Wed Oct 17 12:04:18 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * m-delta.h (C_DEBUG_SWITCH): Don't define this.
+
+Tue Oct 16 13:23:37 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * x11fns.c (Fx_get_default): Test for XXidentity non-empty.
+
+ * data.c (arith_error): Reestablish handler on VMS.
+
+ * process.c (status_convert): If killed by signal, use WTERMSIG.
+
+Mon Oct 15 00:27:43 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * alloc.c (truncate_all_undos): New subroutine.
+
+ * keyboard.c (start_polling, stop_polling): New functions.
+ (input_poll_signal): New function, handles periodic alarms.
+ (read_command_char): Turn off polling temporarily.
+ * xdisp.c (redisplay): Likewise.
+ * process.c (wait_reading_process_input, create_process): Likewise.
+ * x11term.h (BLOCK_INPUT, UNBLOCK_INPUT): Likewise.
+ * xterm.c (XTflash, flashback): Likewise.
+
+ * process.c (wait_reading_process_input): Undo last change.
+
+ * process.c (create_process): Don't turn off handling of SIGCHLD.
+ Just set a flag if a signal comes in when not wanted.
+ (create_process_sigchld): New signal handler.
+
+Sun Oct 14 15:26:29 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * alloca.s [new hp assembler]: Avoid putting sp above stack top.
+
+ * crt0.c [new hp assembler]: Double flag_fpa and flag_68881 if %d2!=0.
+
+ * x11term.c: Choose time.h or sys/time.h as in process.c.
+
+ * alloc.c (Fmake_marker): Delete debugging abort.
+
+Thu Oct 11 11:58:40 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * m-ibmps2-aix.h (LOAD_AVE_TYPE, LOAD_AVE_CVT): Define them.
+ (C_DEBUG_SWITCH): Delete -fstrength-reduce.
+
+ * x11term.c (XT_GetDefaults): Try more alternatives for each option.
+
+ * unexmips.c (unexec): Add conditional for MIPS2.
+
+Wed Oct 10 16:36:23 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * m-iris4d.h (LIBS_MACHINE): Use -lsun, don't use -lPW.
+
+ * unexelf.c: New file.
+ * s-usg5-4.h: New file.
+ * unexec.c [USG_SHARED_LIBARARIES]: Numerous changes under this cond.
+ (copy_text_and_data): New second argument.
+
+ * process.c (wait_reading_process_input): If not using interrupts,
+ and using X, check every second for input from X.
+
+Tue Oct 9 14:10:30 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * x11term.c [BAT68K]: Include sys/time.h.
+ (x_clear_end_of_line): Fix typo inside #ifdef.
+
+ * m-delta.h: Never use HAVE_ALLOCA.
+ Don't define HAVE_SOCKETS.
+ Don't alter HAVE_X_WINDOWS or X11.
+ Other changes inside HAVE_X_WINDOW conditional.
+
+ * window.c (window_loop): In case 6, don't do Fset_buffer.
+
+ * m-news-risc.h: New file.
+
+ * dispnew.c (init_display): Cast result of egetenv.
+
+ * m-ibmrt-aix.h (PTY_TTY_NAME_SPRINTF): Use fd, not ptyv.
+
+Mon Oct 8 18:55:20 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * sysdep.c (sys_open, sys_close, sys_read, sys_write):
+ Don't handle EAGAIN.
+
+ * process.c (wait_reading_process_input): Handle nread==-1
+ for O_NDELAY like O_NONBLOCK. See james@bigtex.cactus.org.
+
+ * s-vms.h (LINK_CTRL_SHARE): Turn on again.
+ tranle@intellicorp.com found it needed in VMS 5.3.
+
+ * emacs.c (main): Move VMS declaration of environ outside function.
+
+ * vmsfns.c (Fdefault_subproc_input_handler): InsCstr -> insert.
+
+Sun Oct 7 22:48:33 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * m-pmax.h (START_FILES): Handle crt0.o in different dir in Ultrix 4.0.
+
+ * s-sunos4.h (O_NDELAY): Define only if not defined.
+
+Mon Oct 1 13:51:03 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * sysdep.c (sys_open, sys_close, sys_read, sys_write):
+ Handle EAGAIN like EINTR.
+
+Sun Sep 30 16:37:26 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * sysdep.c: Include various headers for ptys, for hpux, aix, and sysv.
+
+ * dispnew.c (preserve_other_columns): Fix args to second bcopy.
+
+ * term.c (output_chars): Fix braino updating len after TS_repeat.
+
+Sat Sep 29 00:04:31 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * x11fns.c (Fcoordinates_in_window_p): Don't fail in minibuffer.
+
+ * x11term.c (internal_socket_read): Backwards if in FocusOut.
+
+ * term.c (fatal): Declare argument str.
+
+ * alloca.s: Handle ns32000 like ns16000.
+
+ * ymakefile (LIB_X11_LIB): New parameter,default -lX11.
+ (LIBX): Use that.
+
+ * Makefile (xmakefile): Delete junk.c at the beginning.
+
+ * process.c (sigchld_handler): Don't clear bit in wait mask
+ if process is deactivated already.
+
+ * hftctl.c: Include termios.h before termio.h.
+ Define TCGETS and TCSETS if nec.
+ Give some forward declarations for the static functions.
+ Reformat in usual GNU style.
+
+ * m-orion105.h (LOAD_AVE_TYPE, FSCALE): Changed from double and 1.0.
+
+ * xkeys-aix.h: Don't modify delete and backspace.
+ If the user has already remapped the keyboard,
+ this would only mess things up.
+
+ * m-delta.h: New file.
+
+Fri Sep 28 17:57:46 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * malloc.c (morecore): Don't block SIGTRAP, SIGILL, SIGSTOP, SIGTSTP.
+
+ * Eliminate all mallocs in signal handlers.
+
+ * process.h (struct process): New slots raw_status_low, raw_status_high
+ * process.c (sigchld_handler): Don't compute status list here.
+ Just set raw_status_...
+ (update_status): New function; compute status from raw_status_...
+ (make_process, Fdelete_process, Fprocess_status):
+ (Fprocess_exit_status, list_processes_1, wait_reading_process_input):
+ (send_process, process_send_signal, sigchld_handler, status_notify):
+ Set or test raw_status...
+
+ * dispnew.c (window_change_signal): Don't do it, just make it pending.
+ (do_pending_window_change): New function. Really change the size.
+ (hold_window_change, unhold_window_change): Functions deleted.
+ * xdisp.c (redisplay, message, message1): Use do_pending_window_change.
+ * process.c (wait_reading_process_output): Likewise, after select.
+
+ * alloc.c (malloc_warning): Just save the string.
+ (pending_malloc_warning): New variable.
+ (display_malloc_warning): Really display the message in a buffer.
+ * keyboard.c (command_loop_1): Call display_malloc_warning if needed.
+
+ * fns.c (Frequire): Undo certain things on failure, like autoload.
+
+Thu Sep 27 20:59:54 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * sysdep.c (select): Use process_tick and update_tick,
+ not child_changed.
+
+ * m-convex.h (LIB_STANDARD, LIBS_MACHINE): remove these, they
+ cause an unnecessary C1/C2 dependency.
+
+ * m-convex.h (LD_SWITCH_MACHINE): use -e__start to specify
+ where crt0.c begins.
+
+ * m-convex.h (HAVE_SETSID): define; must call setsid()
+ when creating an inferior with a different controlling tty.
+ * process.c (create_process): rearrange so that HAVE_SETSID
+ will be seen when not under USG.
+
+ * m-convex.h (S_IFMT etc): define in case of posix compilation.
+
+ * m-convex.h (FIRST_PTY_LETTER): do it at runtime.
+ * unexconvex.c (first_pty_letter): routine to locate lowest pty.
+
+ * unexconvex.c: Rewrite so it can cope with thread-local sections.
+
+ * m-sequent.h, m-cydra5.h, m-ibmrt-aix.h: Change ptyname to pty_name.
+
+ * alloc.c (Fmake_marker): Abort if called from signal handler.
+
+Wed Sep 26 18:39:42 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * m-mips4.h: New file.
+
+Sun Sep 23 14:25:45 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * keyboard.c (Fsuspend_emacs): Check screen size after resume.
+
+Tue Sep 18 09:21:44 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * window.c (Fsplit_window): For horizontal split, put excess
+ column on left.
+
+Mon Sep 17 11:22:45 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * emacs.c (main) [USG_SHARED_LIBRARIES]: Call brk.
+
+Sun Sep 16 22:23:10 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * window.c (save_window_save): New arg MAXWINDOW.
+ (Fcurrent_window_configuration): Pass that arg.
+
+Tue Sep 11 16:25:53 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * unexaix.c, m-ibmr2.h, s-aix3-1.h, xkeys-aix.h: New files.
+
+ * ymakefile (LD): Allow override with LINKER.
+ (mallocobj): Handle SYSTEM_MALLOC without HAVE_ALLOCA.
+ (xemacs): Use -nl option if HAVE_SHM.
+
+ * x11term.c (XMOD_Alt, ...): New static variables.
+ (stringFuncVal): Don't define it if AIX.
+ (internal_socket_read): Don't map function keys if AIX.
+ Handle ControlMask like Mod1Mask.
+ (XInitWindow): If AIX, insert xkeys-aix.h.
+
+ * sysdep.c: Change IBMRTAIX conditionals to AIX.
+ Move hft.h to the top.
+ [IBMR2AIX]: Use termios.h and change macros accordingly.
+ (child_setup_tty): Change IBMRTAIX to AIX.
+ (setpgrp_of_tty): Handle IBMR2AIX.
+ (init_sys_modes): Handle IBMR2AIX. Output special things for AIX.
+ (reset_sys_modes): Output special things for AIX.
+ (hft_init, hft_reset): Conditionals for IBMR2AIX.
+
+ * process.c: Change IBMRTAIX to AIX controlling time.h.
+ [AIX]: Include sys/pty.h and unistd.h.
+ (wait_reading_process_input): If AIX, handle EBADF differently.
+ (create_process): Handle HAVE_SETSID. Change conditional to AIX.
+
+ * lisp.h (XPNTR): New definition if HAVE_SHM.
+ (NULL): Undef before defining.
+
+ * emacs.c (main): If HAVE_SHM, call map_in_data.
+ Use AIX, not IBMRTAIX, for signal conditional.
+ (Fdump_emacs_data): New function if HAVE_SHM.
+ (Fdump_emacs): Don't define if HAVE_SHM.
+
+ * alloc.c (pure, PUREBEG): If HAVE_SHM, define place for a segment.
+
+Thu Sep 6 00:01:05 1990 Chris Hanson (cph at kleph)
+
+ * x11term.c (CursorToggle): If the cursor is in the modeline,
+ don't display it, just say we did.
+
+ * process.c (wait_reading_process_input): Don't initialize
+ `Available'.
+ (sigchld_handler): Take the process input channel out of
+ `input_wait_mask' if the process has died.
+ (init_process): Must initialize `input_wait_mask' to contain
+ standard input.
+
+Mon Sep 3 14:00:11 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * process.c: Use fd_set for args of select, if appropriate.
+ (SELECT_TYPE): Always define this as type to use.
+ (FD_SET, FD_CLR, FD_ISSET, FD_ZERO): New access macros.
+ (input_wait_mask): Use SELECT_TYPE. All refs changed.
+ (wait_reading_process_input): Use SELECT_TYPE and new macros.
+
+ * x11term.c (CursorToggle): Abort if on inverse-video line.
+
+Tue Aug 28 23:15:12 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * regex.c (re_match_2): For case duplicate, refuse to match
+ a register with invalid contents.
+
+Tue Aug 28 17:01:40 1990 Chris Hanson (cph at kleph)
+
+ * dispnew.c (N_PREEMPTIONS): remove illegal semicolon from
+ definition.
+ (update_screen): fix typo, `num_input_characters' should be
+ `num_input_chars'.
+ Initialize preemption-debugging variables to impossible values so
+ that they are disabled.
+
+Tue Aug 28 15:10:28 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * regex.c (re_search_2): Propagate serious error indication.
+
+ * dispnew.c (scroll_screen_lines): Mark newly empty lines as empty.
+ (scrolling): Give up if any line in current_screen not enabled.
+
+Mon Aug 27 12:42:22 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * lread.c (load_unwind): Free the stream object.
+
+ * sysdep.c (wait_for_kbd_input): Frob waiting_for_input here.
+ * keyboard.c (kbd_buffer_read_command_char): Not here.
+
+ * sysdep.c (wait_for_kbd_input): Clear process_ef before snarfing
+ process input.
+
+ * fileio.c (Fdirectory_file_name): On VMS, leave space for log name.
+
+ * sysdep.c (init_sys_modes): Clear process_ef only the first time.
+
+ * vmsfns.c (process_exit): Logic of deletion was wrong.
+ (Fspawn_subprocess): Correctly reuse existing struct process_list.
+
+Sun Aug 26 22:09:23 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * dispnew.c (update_screen): Record preemption events
+ in special history array `preemptions'.
+ Let programmer force a preemption from the debugger.
+
+Sat Aug 25 14:22:39 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * xdisp.c (try_window_id): Record info for debugging.
+
+ * x11term.c (CursorToggle): If in highlighted line, call dummy.
+
+Thu Aug 23 16:41:11 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * process.c (wait_reading_process_output):
+ Don't deactivate process for eof if SIGCHLD is defined.
+ That used to mask the proper exit status.
+
+Wed Aug 22 12:40:29 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * m-plexus.h (LD_SWITCH_MACHINE): New macro.
+
+Mon Aug 20 23:29:08 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * malloc.c (malloc_usable_size, memalign): Count size of header
+ properly.
+
+Thu Aug 16 13:51:23 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * keymap.c (apropos1): At least 1 space between fn name and keys.
+
+Wed Aug 15 14:44:12 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * term.c (calculate_costs): Make DC_ICcost one element larger.
+
+ * process.c (allocate_pty, create_process):
+ (Fopen_network_stream, wait_reading_process_input):
+ Use O_NONBLOCK if it is defined.
+ (wait_reading_process_input): Ignore nread == 0 if using O_NDELAY.
+
+ * process.c (pty_name): New name for ptyname.
+
+Tue Aug 14 22:13:00 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * fileio.c (Finsert_file_contents): Ensure `i' appears initialized.
+
+ * process.c (create_process) [HPUX]: Avoid calling signal;
+ HPUX has sigsetmask.
+
+Mon Aug 13 18:32:16 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * x11term.c (x_term_init): Turn off use of XIgnoreError.
+ (internal_socket_read): Turn off O_NDELAY if FIOSNBIO will be used.
+
+ * xmenu.c (list_of_items, list_of_panes): Fix typos in wta errors.
+
+Sat Aug 11 19:00:49 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * m-convex.h (C_SWITCH_MACHINE, LIB_STANDARD, LIBS_MACHINE):
+ (LD_SWITCH_MACHINE): Add definitions for Convex V 4.0.
+
+Wed Aug 8 13:50:25 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * x11term.c (internal_socket_read): Make XComposeStatus static.
+
+Tue Aug 7 16:11:57 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * sysdep.c [NEED_PTEM_H]: New flag macro says include ptem.h.
+
+ * x11term.c (XTfeep): Call XFlush.
+
+ * x11term.c (XT_Set_Size_Hints): Move resize after setting hints.
+
+Mon Aug 6 23:48:00 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * x11fns.c (Fx_set_background_color): Set bkgd color of cursor GC.
+
+Sun Jul 29 14:16:05 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * x11term.c (local_cursor_vpos, local_cursor_hpos):
+ New variables, used throughout this file instead of cursor_*.
+ (XTupdate_end): Move cursor to last specified position.
+ This makes cursor_in_echo_area work.
+
+ * Makefile (CPP): Use $(CC).
+
+ * editfns.c (init_editfns): Fix typos.
+
+Sat Jul 28 22:14:16 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * doprnt.c (doprnt): Support negative width for %s.
+
+Fri Jul 27 17:15:20 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * dispnew.c (change_screen_size): Set screen_garbaged.
+
+Mon Jul 23 15:51:01 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * scroll.c (CalcLID): Run loop screen_height times.
+ (calculate_scrolling): Offset *_cost by -1.
+
+Tue Jul 17 17:42:46 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * m-mips.h: Fix unterminated comment.
+
+ * fileio.c (Finsert_file_contents): Initialize I exiting main loop.
+
+ * fileio.c (barf_or_query_if_file_exists): Fix bad arg to Fsignal.
+
+Tue Jul 10 15:54:25 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * process.c (wait_reading_process_input):
+ Test of wait_proc->status was backwards.
+
+ * sysdep.c: New parameter NO_SIOCTL_H.
+ * s-386ix.h: New file.
+
+Mon Jul 9 14:33:07 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * m-pmax.h: Undef LD_SWITCH_MACHINE, change DATA_START
+ and DATA_SEG_BITS.
+
+Thu Jul 5 15:34:31 1990 Richard Stallman (rms at mole.ai.mit.edu)
+
+ * s-iris3-6.h (HAVE_GETWD): Define this.
+ (KERNEL_FILE): Change to /unix.
+ (sigsetmask, sigblock, NEED_ERRNO, C_SWITCH_MACHINE): Turn off.
+ (SIGIO): Don't undefine it.
+ (LIBS_MACHINE): Remove -lbsd.
+
+ * term.c (calculate_costs): Fix typo allocating DC_ICcost.
+
+Thu Jul 5 13:38:24 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * minibuf.c (Fall_completions, do_completion): Treat nil as alist.
+ (Ftry_completion): Likewise.
+
+Sun Jul 1 17:21:40 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * sysdep.c: Undefine TIOCGETC if BROKEN_TIOCGETC defined.
+ * s-usg5-3.h: Define BROKEN_TIOCGETC.
+
+Thu Jun 28 13:44:46 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * term.c (calculate_costs): Always allocate chars_wasted and copybuf.
+ Clear chars_wasted.
+
+ * xdisp.c (display_text_line): Check p1prev against startp for `...'.
+
+Tue Jun 26 12:37:45 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * fileio.c (Fdo_auto_save): If don't save because file has shrunk,
+ that still counts as trying.
+
+Sun Jun 24 14:30:17 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * x11term.c (dumprectangle, CursorToggle, dumpchars): Use new
+ screen data structures.
+ * xterm.c (dumprectangle, CursorToggle, dumpchars): Likewise.
+ Also, use current_screen in place of active_screen
+ since in fact only that screen matrix was ever used.
+
+ * dispextern.h: Add `extern' to variable declarations.
+
+Sat Jun 23 14:12:01 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * process.c [HPUX]: Undefine TIOCGPGRP.
+
+ * editfns.c, fileio.c, filelock.c [HPUX]: Include stdio.h.
+
+ * s-hpux.h: Inclusion of wait.h moved from m-hp9000s300.h.
+ (HAVE_RENAME): Define this.
+ * sysdep.c (HAVE_RANDOM): Define this on hpux with x11.
+ (rename): Check HAVE_RENAME.
+
+ * lread.c (read_escape): Don't use \a.
+
+Wed Jun 20 12:44:16 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * m-sun2.h: Add comment for dealing with 68881.
+
+Tue Jun 19 01:36:26 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * m-ibmps2-aix.h: Define C_DEBUG_SWITCH to optimize for gcc.
+ Define LIB_STANDARD rather than LIBS_MACHINE.
+ Define HAVE_PTYS, HAVE_SOCKETS, HAVE_SYSVIPC, X_DEFAULT_FONT.
+ Undefine sigsetmask.
+
+ * sysdep.c: Don't include sioctl.h on aix386.
+
+ * process.c: Use HAVE_WAIT_HEADER.
+
+Sun Jun 17 17:57:31 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * insdel.c (insert): Error if buffer would get too long.
+ * fileio.c (Finsert_file_contents): Likewise.
+
+Sat Jun 16 23:31:41 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * syntax.c (scan_lists, scan_sexps_forward): Allow Squote in symbols.
+
+Sun May 27 18:33:35 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * process.h (struct Lisp_Process): Add element pty_flag.
+ * process.c (create_process): Initialize that.
+ (process_send_signal): Ignore current_process if no pty.
+
+ * syntax.c (scan_sexps_forward): Initialize curlevel->last.
+
+Sat May 26 03:15:22 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * keyboard.c (command_loop_1): Clear this_command_key_count here.
+ (Fread_key_sequence): And here.
+ (read_key_sequence): Not here.
+
+ * indent.c (current_column): Detect special case when point == BEGV.
+
+ * window.c (unshow_buffer): Don't set pt in selected window's buffer.
+
+ * process.c (status_message): Fix screwup in Qexit case.
+
+Fri May 25 15:10:30 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * dispnew.c (update_screen):
+ Add missing else in handling cursor_in_echo_area.
+
+ * window.c (Fselect_window): Always get point from the new window.
+ * xdisp.c (redisplay_window): Eliminate lpoint. Alter opoint
+ if point should be changed permanently in the selected window.
+
+ * xdisp.c (decode_mode_spec): Don't truncate buffer or file name.
+
+ * editfns.c (Finsert_buffer_substring): Don't fail to set beg, end.
+
+ * dispnew.c (safe_bcopy): Fix backwards conditional.
+ Do both cases explicitly; don't use bcopy.
+ (scroll_screen_lines): Fix amount to rotate by for AMOUNT < 0.
+
+Tue May 22 20:50:33 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * Renamings: Renamed functions include
+ move_cursor, bell, read_command_char, insert, output_chars,
+ self_insert_internal, set_buffer_internal.
+ Variables echo_area_contents, cursor_hpos, cursor_vpos, meta_key,
+ update_mode_lines, current_buffer.
+ Macros SET_PT, FROM_KBD, FETCH_CHARS.
+
+ * keyboard.c (defkey): Function deleted. ndefkey used instead.
+ (Vglobal_map, global_map, Vesc_map, Vctl_x_map): Now type Lisp_Object.
+
+Mon May 21 14:32:37 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * buffer.h (struct buffer_text): Component renamed.
+ All refs changed to macros below.
+ (MODIFF, BUF_MODIFF): New macros.
+
+ * xdisp.c (redisplay_window): Fix backward conditional on point_vpos.
+
+ * xdisp.c (redisplay_window): Set bf_cur directly.
+ * buffer.c (SetBfx): Function deleted.
+
+Sun May 20 17:27:06 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * keyboard.c (command_loop_level): New variable.
+ Used in place of RecurseDepth, but different meaning.
+ (recursive_edit_1): New function.
+ (Frecursive_edit): Call that.
+ * minibuf.c (read_minibuf): Call recursive_edit_1.
+ * xdisp.c (RecurseDepth): Variable deleted.
+
+ * print.c: Include dispextern.h.
+ (printchar, strout): Use message_buf.
+
+ * scroll.c (CalcIDCosts): Dynamically allocate ILcost, etc.
+ (ILcost, DLcost, ILncost, DLncost): Now pointers.
+ (do_scrolling): Use alloca for queue.
+
+ * term.c (calculate_costs):
+ Dynamically allocate chars_wasted, copybuf, DC_ICcost.
+ Set RPov based on actual width.
+ (chars_wasted, copybuf, DC_ICcost): Now pointers.
+
+ * term.c (term_init): Don't use MScreenWidth, MScreenLength at all.
+ * sysdep.c (get_screen_size): Likewise.
+ * dispnew.c (change_screen_size_1): Likewise.
+
+ * dispnew.c (remake_screen_structures): Allocate message_buf.
+ * xdisp.c (message_buf): Now is a pointer.
+
+Sat May 19 15:10:11 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * keyboard.c (get_char): Don't echo dash if have other echo area text.
+
+Fri May 18 15:03:06 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * lread.c (openp): Fix error setting fd after failing `access'.
+
+ * dired.c (file_name_completion): Use scmp to compare names.
+
+ * sysdep.c (setup_pty): New function.
+
+Thu May 17 15:58:05 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * malloc.c (calloc): New function.
+
+ * minibuf.c (Fall_completions): Protect STRING from gc.
+ Copy ALIST to TAIL to protect it.
+
+ * paths.h-dist: Doc fix.
+
+ * process.h (struct Lisp_Process): New components status
+ contains process status in Lispy form. Replaces flags and reason.
+ New components tick and update_tick record need for attention.
+ * process.c: All references updated.
+ (status_convert, decode_status, status_message): New functions.
+ (pty): Return a descriptor or -1.
+ (send_process): Function deleted.
+ (send_process_1): Renamed to send_process.
+ (process_send_signal, sigchld_handler, status_notify): Renamed fns.
+ * sysdep.c (setup_pty): New function.
+
+ * print.c (internal_with_output_to_temp_buffer):
+ Save and restore the current buffer.
+
+Sat May 12 18:09:30 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * process.c (create_process) [not USG]: Put subproc in pgrp 0.
+
+ * buffer.c (SetBfp): Don't bother with selected window or its point.
+ * window.c (Fselect_window): Always set pointm of old window.
+
+Thu May 10 18:20:10 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * dispnew.c (make_screen_structure): Clear out enable vector.
+
+Wed May 9 16:55:30 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * insdel.c (make_gap): Arg is amount of new gap to create.
+ All calls changed.
+
+ * buffer.c (Fget_buffer_create):
+ -2 in buffer_local_flags means init the slot.
+
+ * buffer.c (SetBfp, Frename_buffer): Local cleanups.
+
+ * buffer.c (Fset_buffer): Check for deleted buffer.
+ (SetBfp): Don't check.
+ * print.c (PRINTPREPARE): Use Fset_buffer.
+
+Tue May 8 23:00:00 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * buffer.h (struct text): Represent the buffer dimensions
+ with new slots, memory, begv, pt, gpt, zv, z and gap_size.
+ (BEGV, etc.): Use new slots.
+ (CharAt): Likewise.
+ (BufferSafeCeiling, BufferSafeFloor): Use new slots; fix old bugs.
+ (bf_p1, bf_s1, etc.): Old macros deleted.
+
+ * buffer.c (Fget_buffer_create): Set up memory and new slots.
+ (Fkill_buffer): Likewise.
+
+ * insdel.c (move_gap, gap_left, gap_right, make_gap): Update new slots.
+ (del_range, InsCStr): Likewise.
+ * fileio.c (Finsert_file_contents): Likewise.
+ * window.c (temp_output_buffer_show): Likewise.
+ * xdisp.c (decode_mode_spec, try_window_id): Likewise.
+
+ * buffer.c (ModExist): Function deleted.
+
+ * buffer.h (struct buffer): Make the syntax table a Lisp object.
+ * alloc.c (mark_buffer): No need to treat it specially.
+ * syntax.c (Fsyntax_table, Fset_syntax_table, Fdescribe_syntax):
+ (Fmodify_syntax_entry): Adjust for this change.
+ * buffer.c (reset_buffer_local_variables): Need not be special.
+ (init_buffer_once): Make this slot a defaulted local variable.
+ * syntax.h: Adjust macros for this change.
+ (Vstandard_syntax_table): Define as macro, in buffer_defaults.
+ * syntax.c (syms_of_syntax): Don't staticpro it here.
+ (Fset_syntax_table): Set the flag in local_var_flags.
+
+ * marker.c (Fset_marker): Don't unchain marker if has no buffer.
+ (set_marker_restricted): Likewise.
+ * alloc.c (gc_sweep): Likewise.
+ * editfns.c (save_excursion_restore): Likewise.
+
+ * editfns.c (insert1): New function.
+ * keyboard.c (get_char): Echo area message turns off echoing.
+
+ * keyboard.c (record_auto_save): New function.
+ * fileio.c (Fdo_auto_save): Call it.
+
+ * dispnew.c (rotate_vector): Was rotating backwards.
+
+ * insdel.c (make_gap): Complete rewrite.
+ (gap_left): New argument NEWGAP.
+
+Sat May 5 13:00:00 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * search.c (skip_chars): Eliminate PointLeft and PointRight.
+ * cmds.c (SelfInsert): Likewise.
+
+ * search.c (Flooking_at, search_buffer): Use new accessors.
+ * indent.c (Fcurrent_column): Likewise.
+ * minibuf.c (read_minibuf): Likewise.
+ * regex.c (re_match_2): Use PTR_CHAR_POS.
+ * editfns.c (Fbuffer_size, Fnarrow_to_region, Fbuffer_substring):
+ (Fbuffer_string, Finsert_buffer_substring): Likewise.
+ (save_restriction_restore): Likewise.
+ * dispnew.c (direct_output_for_insert): Likewise.
+ * fileio.c (Fwrite_region, Finsert_file_contents): Likewise.
+ (Fdo_auto_save): Likewise.
+ * insdel.c (move_gap, gap_left, gap_right, make_gap): Likewise.
+ (InsCStr, del_range, modify_region): Likewise.
+ * process.c (Fprocess_send_region): Likewise.
+ * xdisp.c (try_window, try_window_id, display_text_line): Likewise.
+ (redisplay): Likewise.
+ * buffer.c (list_buffers_1): Likewise.
+ * marker.c (marker_position, Fset_marker, set_marker_restricted):
+ (Fmarker_position): Likewise.
+ * window.c (unshow_buffer, Fset_window_configuration): Likewise.
+ (Fset_window_buffer): Likewise.
+
+ * editfns.c (save_restriction_restore): Use a macro to alter point.
+
+ * lread.c (readchar): Use new accessors, and avoid knowing about
+ the text field of a buffer.
+ * window.c (Fpos_visible_in_window_p): Likewise.
+
+Thu May 3 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * editfns.c (init_editfns): Store system and user names as
+ strings to avoid arbitrary limits.
+
+ * keymap.c (describe_vector, describe_alist): Make elt_prefix
+ and elt_describer responsible for indentation and newlines.
+ Local cleanups.
+ (describe_command): Do indentation and newline.
+ (describe_map): Add space to end of prefix.
+ * syntax.c (describe_syntax): Do indentation and newline.
+
+ * keymap.c (Fdefine_key, Flookup_key): Local cleanups.
+
+ * xdisp.c (redisplay_window): Fix calls to try_window.
+
+ * term.c (write_chars): Local cleanup.
+ (term_init): Local cleanup.
+ For c100, substitute only in the cm string.
+ No need to keep the address of the start of the string area.
+
+ * editfns.c: Eliminate all use of DEFSIMPLE and DEFPRED.
+ * dispnew.c, indent.c, keyboard.c: Likewise.
+
+Mon Apr 30 20:00:00 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * sysdep.c (sys_suspend): Use save_signal_handlers and
+ restore_signal_handlers to save and restore signal state.
+
+ * indent.c (Findent_to): Merge guts of indentation into here.
+ (position_indentation): Scan with a pointer, for speed.
+
+ * casefiddle.c (operate_on_word): Just return the other end.
+ (Fupcase_word, Fdowncase_word, Fcapitalize_word):
+ Pass that value to casify_region.
+
+Wed Apr 25 15:10:00 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * keymap.c: Minor changes.
+
+ * lread.c (Fload): Minor changes.
+
+ * macros.c (Fstart_kbd_macro): Local cleanup.
+
+ * minibuf.c (read_minibuf): Local cleanup.
+
+ * search.c (Freplace_match, Fregexp_quote): Local cleanups.
+
+ * search.c (Fstore_match_data): Handle ints and markers properly.
+
+ * syntax.c: Flush incorrect comment.
+
+ * sysdep.c (init_baud_rate, init_sys_modes, tabs_safe_p):
+ (get_screen_size): Local cleanups.
+
+ * data.c (Fstring_to_int): Delete disabled feature
+ of accepting `yes' and `no'.
+
+ * dispnew.c (current_screen, new_screen, temp_screen): New vars.
+ (remake_screen_structures, make_screen_structure):
+ (free_screen_structure): New functions.
+ (make_display_lines, new_display_line, return_display_line):
+ Functions deleted.
+ (change_screen_size_1, init_display): Use the new functions.
+ (cancel_line, clear_screen_records, get_display_line):
+ Rewritten for new data structures.
+ (preserve_other_columns, preserve_my_columns): Likewise.
+ (cancel_my_columns, direct_output*): Likewise.
+ (update_screen, update_line, quit_error_check, scrolling): Likewise.
+ (scroll_screen_lines): Likewise.
+ (rotate_vector, safe_bcopy): New subroutines.
+ * scroll.c (do_scrolling): Rewritten for new data structures.
+ * xdisp.c (display_minibuf_message, redisplay): Likewise.
+ (display_text_line, display_mode_line): Likewise.
+ (display_mode_element, display_string): Likewise.
+
+ * xdisp.c (decode_mode_spec): Local cleanups.
+ (display_mode_element): Pass proper arg MAXWIDTH to decode_mode_spec.
+ (display_text_line): Pointers now unsigned.
+
+ * dispnew.c (line_hash_code, line_draw_cost): Cleaned up.
+ Args are different, and hash computation too.
+
+ * dispnew.c (update_screen): Rearrange buffer-emptying code.
+
+ * editfns.c (in_accessible_range): New function.
+ (Fgoto_char, save_restriction_restore): Use it.
+ (save_excursion_save, Fcurrent_time_string): Local cleanups.
+
+ * emacs.c (Fkill_emacs): Don't ask any questions.
+ * process.c (Fprocess_kill_without_query): New arg; new return value.
+ (count_active_processes): Function deleted.
+
+ * emacs.c (Fdump_emacs): Local cleanup.
+
+ * fileio.c (Finsert_file, Fwrite_region): Local cleanups.
+
+ * fns.c (Fsubstring): Local cleanup.
+
+ * keyboard.c (echo_prompt, echo_char, echo_dash, echo): New functions.
+ (cancel_echoing): Likewise.
+ (immediate_echo, echoptr): New variables.
+ (command_loop_1, request_echo, get_char, read_key_sequence):
+ (set_waiting_for_input, interrupt_signal): Related changes.
+
+ * keyboard.c (this_command_key...): New variables.
+ (Fexecute_extended_command, Fthis_command_keys): Related changes.
+ (init_keyboard, get_char): Likewise.
+
+ * keyboard.c (get_char): New way to decide when to auto-save.
+ Other local cleanups.
+ (command_loop_1): New criterion for undo boundary.
+
+Tue Apr 24 12:00:00 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * buffer.c (bf_text): Variable deleted.
+ (Fkill_buffer, SetBfp): Delete code that worked with it.
+ * editfns.c (Fwiden, Fnarrow_to_region): Related changes.
+ (save_restriction_save, save_restriction_restore): Likewise.
+ (Finsert_buffer_substring): Likewise.
+ * fileio.c (Fdo_auto_save): Likewise.
+ * insdel.c (make_gap): Likewise.
+ * lread.c (readchar): Likewise.
+ * marker.c (Fmarker_position, marker_position): Likewise.
+ (Fset_marker, set_marker_restricted): Likewise.
+ * window.c (Fset_window_buffer, Fpos_visible_in_window_p): Likewise.
+ * xdisp.c (redisplay): Likewise.
+
+ * xdisp.c (redisplay, redisplay_preserve_echo_area):
+ Two functions replace DoDsp. All callers changed.
+
+ * xdisp.c (redisplay, redisplay_window): Eliminate `inhibit_hairy_id'.
+ (redisplay_window): No return value. Local cleanups.
+
+ * xdisp.c: Fix various inaccurate comments.
+
+ * xdisp.c (try_window): No return value.
+
+Sat Apr 21 18:05:19 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * sysdep.c (random, srandom): Don't define if HAVE_RANDOM.
+
+Thu Apr 19 12:00:00 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * abbrev.c (Fdefine_mode_abbrev): Clean up error message.
+
+ * alloc.c (Fmake_marker): Delete `modified' field.
+ * insdel.c (adjust_markers): Likewise.
+
+ * undo.c: Complete rewrite.
+ * undo.h: File deleted.
+ * alloc.c (Fgarbage_collect): Call truncate_undo_list.
+ (syms_of_alloc): Define vars undo-threshold and undo-high-threshold.
+ * buffer.c (Fget_buffer_create): Set undo_list to t or nil.
+ (Fbuffer_flush_undo, Fbuffer_enable_undo): Likewise.
+ (Fkill_buffer): Likewise.
+ (init_buffer_once): Set up local variable buffer-undo-list.
+ (syms_of_buffer): Likewise.
+ * fileio.c (Finsert_buffer): Store nil in undo_list.
+
+Tue Apr 17 03:24:01 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * buffer.h (struct buffer): Delete minor_modes.
+ * buffer.c (Fget_buffer_create):
+
+Mon Apr 16 13:17:43 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * s-sunos4.h (SYSTEM_MALLOC): Define it.
+
+Sat Apr 14 16:48:21 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * window.c (set_window_height, set_window_width):
+ Don't delete top-level windows.
+
+Wed Apr 11 15:10:19 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * sysdep.c [HPUX] (perror): Function deleted.
+
+Tue Apr 10 20:39:46 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * process.c (sig_process): Use TIOCSIGSEND if available.
+
+Fri Mar 30 14:42:10 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * alloc.c (xmalloc, xrealloc): Avoid failure if size is 0.
+
+Wed Mar 21 18:19:12 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * m-sun3.h (C_SWITCH_MACHINE): Use -fsoft.
+
+Thu Mar 15 02:41:53 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * x11term.c (internal_socket_read): Change type of 1st arg to
+ XRefreshKeyboardMapping and XLookupString.
+
+ * undo.c (Fundo_more): Fix error message.
+
+Tue Feb 13 18:34:54 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * process.c: If _h_BSDTYPES, include time.h, not sys/time.h.
+
+Thu Feb 1 02:11:41 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * m-ibmps2-aix.h (SIGN_EXTEND_CHAR): Cast to `signed char'.
+
+Thu Jan 18 12:56:06 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * search.c (skip_chars): Never go past edge of buffer.
+
+Mon Jan 8 10:56:42 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * editfns.c (Fchar_after): Set N after coercing marker.
+
+Thu Dec 28 18:12:08 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * process.c (create_process): Unhold SIGCHLD in the child.
+
+Wed Dec 27 19:10:35 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * process.c (create_process): Fix bad HPUX conditional at sigsetmask.
+
+Mon Dec 25 00:10:57 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * x11term.c (internal_socket_read): Handle explicit focus events.
+ (XInitWindow): Add them to event mask.
+
+ * fns.c (Fmapconcat): Gcpro SEP around mapcar1.
+
+Fri Dec 15 13:27:03 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * process.c (read_process_output): Return -1 if read does.
+ (wait_reading_process_input): Handle EWOULDBLOCK.
+
+Fri Nov 17 17:18:15 1989 Joseph Arceneaux (jla at spiff)
+
+ * xmenu.c (XEmacsMenu): Use ButtonReleasedMask for X11.
+
+Thu Nov 9 13:10:02 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * m-sparc.h (C_OPTIMIZE_SWITCH): Use -O if GCC.
+
+Wed Nov 8 14:05:37 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * marker.c (Fset_marker): Don't force position into visible range.
+ (set_marker_restricted): New function does what Fset_marker did.
+ * window.c: Change many calls to use the new function.
+
+ * search.c (Fstore_match_data): Accept integers as well as
+ markers.
+ A marker pointing nowhere, treat as 0.
+
+Mon Nov 6 02:00:40 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * search.c (Fmatch_data): Report 0 as integer 0;
+ don't convert to a marker.
+
+ * m-mips.h [USG]: Undef NOMULTIPLEJOBS.
+ Define SYSV_SYSTEM_DIR and undef NONSYSTEM_DIR_LIBRARY.
+ Define utimes as alias for utime. Undef BSTRING.
+ [unconditional]: Undef LOAD_AVE_TYPE.
+ [BSD]: Define COFF and TERMINFO.
+ Undef MAIL_USE_FLOCK and HAVE_UNION_WAIT.
+ Define C_SWITCH_SYSTEM and LD_SWITCH_SYSTEM.
+ Define START_FILES and LIB_STANDARD as in USG.
+ * m-pmax.h: Add stuff to cancel that out.
+
+ * sysdep.c: Handle BROKEN_FIONREAD.
+
+Thu Nov 2 12:30:20 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * alloc.c (staticvec) [__GNUC__]: Make this a simple vector of pointers
+ rather than an alias for a vector of chars.
+
+Thu Oct 26 20:24:55 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * x11term.c (x_init_1): Negate arg to fcntl F_SETOWN
+ if F_SETOWN_SOCK_NEG.
+ * xterm.c (x_init_1): Likewise.
+ * keyboard.c (Fset_input_mode) [NO_SOCK_SIGIO]:
+ No interrupt input if using a socket.
+ * m-sequent.h: Define NO_SOCK_SIGIO, F_SETOWN_SOCK_NEG, MAIL_USE_FLOCK.
+
+Wed Oct 18 17:55:37 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * m-pyramid.h (NO_ARG_ARRAY): Define if using GCC.
+
+Tue Oct 17 03:08:08 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * vmsfns.c (process_command_input): Call clear_waiting_for_input.
+
+Fri Oct 13 20:29:42 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * x11fns.c (Fx_get_mouse_input): Read in all kbd input, to get event.
+ * keyboard.c (consume_available_input): New fn that does this.
+ (read_avail_input): No longer requires kbd_count == 0.
+ Can now be subroutine for consume_available_input.
+
+Wed Oct 11 14:55:23 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * termcap.c (tgetent, gobble_line): Always store null at end of bfr.
+ Allocate one extra byte at end to ensure space.
+ Clean up order of arithmetic when updating ptrs into buffer
+ after xrealloc.
+
+Tue Oct 3 12:29:18 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * m-hp9000s800.h (XUNMARK): Delete definition.
+
+Fri Sep 22 00:40:16 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * x11fns.c (Fx_get_mouse_event): Fix typo, Fcond => Fcons.
+ Do set Vx_mouse_item. Wait using Fsleep_for.
+ Convert meta from 8-bit to 2-bit, as in Fx_proc_mouse_event.
+
+Fri Aug 18 17:00:47 1989 Richard Stallman (rms at hobbes.ai.mit.edu)
+
+ * Version 18.55 released.
+
+ * vmsfns.c: Define PRV$V_... syms if prvdef.h does not.
+
+Sun Aug 13 14:50:28 1989 Richard Stallman (rms at hobbes.ai.mit.edu)
+
+ * xfns.c (Fx_proc_mouse_event, Fx_get_mouse_event):
+ Set new var Vx_mouse_abs_pos, for sake of xmenu.c.
+ (syms_of_xfns): Make this a Lisp variable.
+
+ * x11fns.c (Fx_get_mouse_event): Fix like Fx_proc_mouse_event.
+ (syms_of_xfns): Initialize the variable.
+
+Fri Aug 11 21:24:19 1989 Richard Stallman (rms at hobbes.ai.mit.edu)
+
+ * dispnew.c: Handle BROKEN_FIONREAD as in other files.
+
+ * x11fns.c (Fx_proc_mouse_event): Set Vx_mouse_abs_pos right.
+ * xmenu.c (XEmacsMenu): Use that rather than XQueryPointer
+ to decide where to put the menu.
+
+Sun Aug 6 17:57:54 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * process.c [HPUX, !NOMULTIPLEJOBS, !WAITTYPE]:
+ Treat this case like BSD, regarding sys/wait.h.
+
+ * m-hp9000s300.h: Don't include sys/wait.h if NOT_C_CODE.
+ If we do include it, also define WRETCODE.
+ * alloca.s: Define NOT_C_CODE.
+
+Sat Aug 5 16:25:04 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * m-ibmps2-aix.h (HAVE_CLOSEDIR): Define this.
+ * sysdep.c (closedir): Don't define if HAVE_CLOSEDIR.
+
+ * m-hp9000s300.h: Include sys/wait.h and define WAITTYPE,
+ unless NO_SHORTNAMES.
+
+ * process.c [BSD]: If O_NDELAY missing in file.h, include fcntl.h.
+
+Wed Aug 2 20:31:13 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * m-ibmrt-aix.h (LIBS_MACHINE): Delete X libraries--redundant.
+
+ * x11term.c [AIX]: Include sys/time.h as well as time.h.
+
+ * search.c (Freplace_match): Bug in substituting \N if match was empty.
+
+Wed Jul 26 01:41:25 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * sysdep.c (wait_for_termination): Treat HPUX version 6 like BSD.
+
+ * process.c: If NEED_BSDTTY, include bsdtty.h.
+ If WAITTYPE already defined, don't include wait.h
+ and don't alter the related macros.
+ (child_sig): On HPUX, if have WNOHANG, loop around as on BSD.
+ (create_process): On HPUX, frob the signal mask as on BSD.
+
+ * m-intel386.h (LOAD_AVE_*): Expect different type and encoding.
+
+Thu Jul 20 00:53:05 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * sysdep.c: Don't include sioctl.h on mips.
+
+ * buffer.c (Flist_buffers): Pass prefix as arg.
+
+ * editfns.c (Finsert_char): Insert at most 256 chars at a whack.
+
+ * x11term.c (internal_socket_read): Pass 0 as fifth arg
+ to XLookupString.
+
+ * keyboard.c (command_loop_1): Finalize keyboard macro storage
+ only when there is no prefix argument.
+
+ * callproc.c (Fcall_process) [USG,HAVE_PTYS]:
+ With these parameters, do setpgrp here.
+ (child_setup): Instead of here.
+ Note that process.c already did setpgrp before calling
+ child_setup, with these parameters.
+
+ * m-ibmps2-aix.h: New file.
+ * m-ibmrt-aix.h: Define AIX.
+ * sysdep.c: Change IBMRTAIX to AIX in certain conditionals.
+ (Those pertaining to the hf library or system calls.)
+
+Tue Jul 4 21:00:30 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * fileio.c (Finsert_file_contents): Check for negative file length.
+
+Fri Jun 23 15:48:21 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * Makefile (clean, distclean): Delete libXMenu11.a.
+
+Thu Jun 22 18:51:06 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * m-mips.h (LIBS_MACHINE): Don't define if BSD.
+ * keyboard.c (force_input_signal): New function: raise SIGIO and force
+ read_socket_hook to be called.
+ * xmenu.c (Fx_popup_menu): Call that after menu disappears.
+
+Fri Jun 16 22:17:12 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * ymakefile: New var OLDXMENU for filename of libXMenu.a.
+ Put it in LIBX, not XOBJ. Make temacs depend on it.
+
+Thu Jun 15 20:15:29 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * ymakefile [HAVE_X11, HAVE_X_MENU]: Assume Xmenu came with Emacs
+ and must be built.
+
+ * xmenu.c: Load "../oldXMenu/XMenu.h" instead of <X11/XMenu.h>.
+
+ * x11term.c (xfixscreen): Really act only every 100th time.
+
+Thu Jun 8 12:54:03 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * m-pmax.h: New file.
+
+Wed Jun 7 13:54:22 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * alloca.s [hp9000s300]: Increase MAXREG for fpregs.
+
+ * sysdep.c (init_sys_modes, reset_sys_modes): Take TIOCGLTC code
+ outside of HAVE_TERMIO conditionals.
+
+ * m-hp9000s300.h: Undefine NOMULTIPLEJOBS.
+ Define NEED_BSDTTY if not NOMULTIPLEJOBS.
+
+ * crt0.c [hp9000s300]: Set flag_fpa. Define float_loc.
+
+ * m-hp9000s800.h: Define NEED_BSDTTY here.
+ * s-hpux.h: Not here.
+
+Tue Jun 6 19:25:17 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * s-hpux.h: Define NEED_BSDTTY.
+
+Tue May 30 18:45:21 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * x11fns.c (x_set_cursor_colors): Don't let the background match
+ the mouse.
+ * x11term.c (XFlipColor): Change mous_color earlier.
+
+Tue May 23 22:18:53 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * search.c (skip_chars): Dumb error checking for \.
+
+Sun May 21 00:43:24 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * callproc.c (child_setup): Undo previous change.
+ setpgrp is needed on USG.
+
+ * xmenu.c (Fx_popup_menu): Prevent sigio int during XQueryPointer.
+
+Mon May 15 21:59:38 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * editfns.c (Fsubst_char_in_region): If NOUNDO, do increment tick,
+ but maybe also increment save-tick.
+
+Sat May 13 14:17:57 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * sysdep.c (init_sys_modes) [IBMRTAIX]: Typo; had s for sg.
+
+Fri May 12 22:09:26 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * s-usg5-3.h: Define HAVE_SYSVIPC.
+
+ * m-7300.h: Undefine SHORTNAMES.
+
+Mon May 1 02:10:04 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * x11term.c [USG]: Use sys/time.h, not time.h, if IRIS_4D.
+
+ * sysdep.c [USG]: Don't include sioctl.h if IRIS_4D.
+
+Wed Apr 26 16:14:12 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * Version 18.54 released.
+
+ * xdisp.c (Fredraw_display): Don't do set_terminal_modes if
+ reset_terminal_on_clear is 0.
+
+Tue Apr 25 22:02:48 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * m-news.h: Define m68000 if not defined.
+
+Mon Apr 24 01:26:40 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * m/m-mips.h [USG]: Define LIBS_TERMCAP.
+ If HAVE_X11, define HAVE_VFORK.
+ Delete defns of XMARKBIT, XSETMARKBIT.
+ [BSD]: Add alternative linker switches; don't override sys
+ facility options.
+
+ * sysdep.c: Include ioctl.h if mips.
+
+Wed Apr 19 20:26:23 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * ymakefile: use HAVE_X11 as alias for X11.
+
+Tue Apr 18 00:17:46 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * process.c: Don't define wstopsig, wtersig if already defined.
+
+ * sysdep.c [VMS] (sys_getenv): Copy the string before returning it.
+
+ * m-alliant.h: Define `vector'.
+
+Thu Apr 13 12:55:14 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * process.c (wait_reading_process_input) [sun]: If SIGIO failed
+ to be sent, send it by hand.
+
+Wed Apr 12 01:42:23 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * window.c (Fdelete_other_windows): recenter window to avoid scrolling.
+
+Tue Apr 11 00:18:10 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * indent.c: Include screen.h.
+
+ * indent.c (pos_tab_offset, Fvertical_motion): Compute internal width
+ correctly and uniformly.
+
+ * xdisp.c (try_window, try_window_id): Use exact internal width
+ to update tab_offset.
+ (try_window_id): pos_tab_offset value needs adjustment only if
+ starting a line in middle of a character.
+
+Sat Apr 8 16:38:40 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * sysdep.c [USG]: If TIOCGWINSZ defined, include sioctl.h.
+
+Thu Apr 6 11:52:43 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * eval.c (Fbacktrace): Set Vprint_level to 3 throughout.
+
+ * fns.c (Fload_average): nlist data structure is funny on convex.
+
+ * window.c (scroll_command): scroll at least 1 line in specd direction.
+
+ * cm.c (calccost): NTABS was off by 1 sometimes; take account of
+ the starting position modulo 8.
+
+ * fileio.c (Fexpand_file_name): Don't simplify /../ at start of name.
+
+ * callint.c: doc fixes.
+
+ * process.c (create_process):
+ On all USG systems, not just IRIS and AIX, don't pre-open pty's tty.
+ Move the setpgrp done for USG (no real change).
+ Tell child_setup to do a setpgrp.
+ * callproc.c (child_setup): New arg says whether to setpgrp.
+ Never setpgrp on USG.
+ (Fcall_process): Tell child_setup not to setpgrp.
+
+ * sysdep.c (init_sys_modes, reset_sys_modes): Don't try to hack
+ TIOCGLTC, TIOCGETC, etc. if HAVE_TERMIO.
+ Don't bother to undef these for XENIX.
+
+Mon Apr 3 17:43:28 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * ymakefile (LIBES): Put LIBX first; it may depend on LIBS_MACHINE.
+
+ * m-sequent.h: Define HAVE_ALLOCA.
+
+Sun Apr 2 12:03:53 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * term.c (term_init): Can't use scroll region if no abs positioning.
+
+Sat Apr 1 00:51:52 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * process.c (Fopen_network_stream): close desc. if connect fails.
+
+Fri Mar 31 17:49:53 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * minibuf.c (Fall_completions): gcprotect ALLMATCHES and TAIL,
+ not STRING.
+
+ * keyboard.c (read_avail_input): Handle EBADSLT like EAGAIN.
+
+Wed Mar 29 09:13:39 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * term.c (term_init): Either ic or ip or im or IC => can insert chars.
+
+ * minibuf.c (read_minibuf_unwind): Ensure minibuf writable for erasure.
+
+Thu Feb 23 07:03:47 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * m-convex.h: Undefine NO_ARG_ARRAY.
+ Changed defns of DATA_SEG_BITS and XINT.
+ Define alloca for GCC compilation.
+
+Fri Feb 17 01:47:30 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * m-ibmrt-aix.h: Define BROKEN_FIONREAD.
+
+Thu Feb 16 03:23:31 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * keymap.c (Fdefine_prefix_command): Set both value and fn defn,
+ with separate syms specified for each purpose.
+
+Wed Feb 15 22:34:58 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * callproc.c (Fcall_process): Open /dev/null with O_WRONLY.
+
+Tue Feb 14 11:48:44 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * window.c (window_scroll): Allow scrolling to very end (empty screen)
+ if that's exactly where we wanted to scroll to.
+
+Sat Feb 11 01:14:39 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * data.c (Fkill_local_variable): New local to simplify big stmt.
+
+Thu Feb 9 06:37:24 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * xdisp.c (display_text_line): cvt chars to glyfs for overlay arrow.
+
+ * sysdep.c (init_sys_modes, child_setup_tty) [IBMRTAIX]:
+ Don't ignore BRK, and don't signal it.
+
+ * process.c (pty): An IBMRTAIX conditional.
+ (create_process): Another here.
+
+Wed Feb 8 13:24:39 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * keymap.c (Fdefine_prefix_command): Use Ffset, not Fset.
+
+Mon Feb 6 12:58:58 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * fileio.c (Fset_visited_file_modtime): New fn.
+
+ * xfns.c (Fx_create_screen) [X10]: XCreateWindow wants pixmaps as args.
+
+Fri Feb 3 01:16:49 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * dispnew.c (Fsit_for): It accepts 3 args.
+
+Thu Feb 2 23:07:43 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * xterm.c (XTread_socket): For X10, make EVENT an XKeyPressedEvent.
+ (x_set_resize_hint): Call XSetResizeHint.
+
+ * process.c: Declare interrupt_input.
+
+ * sysdep.c (init_sys_modes): TIOCSTART, not TCSTART.
+
+Sat Jan 28 15:39:03 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * xterm.h (struct x_display): `GC' renamed `gc' in all field names.
+ Field `ColorMap' renamed to `color_map'.
+ (face_gc_values): face_GC_values renamed.
+
+Sat Jan 28 15:39:03 1989 Joe Arceneaux (rms at sugar-bombs.ai.mit.edu)
+
+ * xterm.h (face_GC): Var deleted.
+ (struct x_display): New field face_GC.
+ (VSCROLL_WIDTH, HSCROLL_WIDTH): Moved here.
+ (MINWIDTH, MINHEIGHT, MAXWIDTH, MAXHEIGHT): New vars. Eliminate them!
+ (BLACK_PIX_DEFAULT): Typo in definition.
+ (WHITE_PIX_DEFAULT): Typos in definitions; was the black default.
+
+ * xterm.c: Include ioctl.h only if BSD.
+ Include termio.h otherwise.
+ (XMapWindow) [X11]: Typo in definition.
+ (METABIT): New definition; maybe not needed.
+ (hostname, id_name, invocation_name, Vcommand_line_args): New vars
+ declared for main icon title.
+ (x_debug): Init to 1 if XDEBUG defined.
+ (dumpglyfs) [X11]: Changed args to XDrawImageString.
+ If debugging, do XFlushQueue.
+ Use screen's face_gc rather than old global one.
+ (XTflash) [not BSD]: avoid `struct itimerval'; use `alarm'.
+ (events): New table of event type names.
+ (XTread_socket): EVENT is now an XEvent even on x10.
+ Translate modifier key 1 into meta-bit.
+ For EnterNotify event, don't dumpborder or x_new_selected_screen
+ if there is an x_focus_screen.
+ For LeaveNotify event, don't ignore due to nonzero subwindow.
+ For ConfigureNotify, change screen size.
+ Do `select' check for SIGHUP only if HAVE_SELECT.
+ (x_new_selected_screen): An arg, SCREEN.
+ (x_display_cursor): dumpglyfs args changed.
+ (x_draw_box): Add GC arg to XDrawRectangle; change other args.
+ (clear_cursor): Change args to XClearArea.
+ (dumpborder): check x_input_screen, not selected_screen.
+ (x_text_icon): For X11, new arg to XGetDefault.
+ Cast values stored in icon_label.
+ (x_term_init): Hair to calculate name for icon.
+ Don't init_sigio unless SIGIO defined.
+ Call Fset_input_mode.
+ For X11, new arg to XGetDefault.
+ Set _Xdebug if debugging.
+ (x_new_font) Use XGetFont.
+ Get GC values from the screen structure.
+ (x_reset_cursor): Don't call XRecolorCursor.
+ (x_set_window_size): Call x_wm_set_size_hint, not x_set_size_hint.
+ (x_set_resize_hint): For X11, call x_wm_set_size_hint.
+ (x_wm_set_size_hint, x_wm_set_window_state, x_wm_set_icon_pixmap):
+ (x_wm_set_icon_position): New fns for X11.
+
+ * xfns.c: For X11, include Xutil.h
+ (VSCROLL_WIDTH): Moved to xterm.h.
+ (face_GC): Don't declare it.
+ (id_name): Declare this.
+ (x_decode_color): Check `white' and `black' first of all.
+ (x_set_foreground_color) [X11]: Reset foreground and background.
+ (x_set_background_color) [X11]: Missing arg to XSetWindowBackground.
+ (x_set_cursor_color) [X11]: Reset foreground and background.
+ (x_read_mouse_position) [X11]: Changed call to XQueryPointer.
+ (x_set_mouse_position) [X11]: Add args to XWarpPointer.
+ (Fx_create_screen): Set some temporary geometry parms at the beginning.
+ For X11, changed setup of iconidentity, and implement rubber-banding.
+ For X11, implement merging individual geometry parms.
+ For X11, changed args to XCreateSimpleWindow.
+ For X11, call x_wm_set_size_hint.
+ Specify name when creating icon.
+ Don't call XSetForeground, XSetBackground before making border tile.
+ New var `cursor_bits'. Init the screen's GC's.
+
+ * screen.c (Frubber_band_rectangle): For X11, just return nil.
+
+Tue Jan 24 01:59:31 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * buffer.c (Fbuffer_modified_tick): New fn.
+
+ * window.c (Fnext_window): Accept 3 args from Lisp.
+
+Mon Jan 23 16:39:36 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * sysdep.c (sys_suspend): Handle case of SIGTSTP but not BSD.
+
+Fri Jan 20 14:26:12 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * sysdep.c (init_sys_modes): Do TIOCSTART if def, like TCXONC.
+
+Thu Jan 19 03:04:58 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * process.c (wait_reading_process_input): New 2nd arg is extra usecs.
+ All callers changed.
+ * dispnew.c (Fsit_for, Fsleep_for): New 2nd arg says 1st arg
+ counts in milliseconds.
+
+ * buffer.c (Fkill_all_local_variables): Implement permanent locals.
+
+Wed Jan 18 14:08:35 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * keymap.c (get_keyelt): Allow indirection within (STRING . DEFN).
+
+Mon Jan 16 17:26:08 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * process.c (wait_reading_process_input): If select returns there
+ is kbd input, but detect_input_pending can't find it, signal SIGIO.
+ This may avoid the X loop-on-logout bug.
+
+ * process.c (wait_reading_process_input): Flush fix_screen_hook.
+ * termhooks.h, term.c: likewise.
+
+ * xdisp.c (Fredraw_display): Don't do set_terminal_modes.
+ * dispnew.c (Fredraw_screen): likewise.
+
+ * eval.c (Fcond): If no args, return nil.
+
+Sun Jan 15 15:41:13 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * eval.c (Fbacktrace_frame): Require one arg. Return nil if too high.
+
+Sat Jan 14 17:50:56 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * minibuf.c (read_minibuf): Set Vminibuf_scroll_window before
+ switching windows.
+
+ * xterm.c (XTread_socket): If no HAVE_SELECT, wait for input
+ if new arg WAITP is non0. Do this by not bothering to test for
+ presence of input before reading some.
+ Check for dead connection only if new arg EXPECTED is nonzero.
+ All callers changed (keyboard and sysdep).
+
+ * Simplify keyboard input.
+ * keyboard.c (read_avail_input): Don't assume buffer is empty.
+ Don't call get_input_pending; do FIONREAD here.
+ Don't do FIONREAD if read_socket_hook, just tell it don't wait.
+ Arg EXPECTED is passed to read_socket_hook.
+ (input_available_signal): Use read_avail_input.
+ (gobble_input): Use read_avail_input; arg EXPECTED passed along.
+ (get_input_pending): let gobble_input do the work.
+
+ * VMS keyboard input should have interrupt_input nonzero.
+ * keyboard.c (Fset_input_mode, init_keyboard): [VMS] Always set
+ interrupt_input to 1.
+ (get_input_pending): Special case deleted.
+
+Fri Jan 13 01:21:00 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * fileio.c (auto_save_1): Always make auto-save file owner-writable.
+
+ * eval.c (Fbacktrace_frame): New fn.
+
+ * buffer.h: Define `fieldlist' field in a buffer.
+ * buffer.c (Fregion_fields): Return list of fields overlapping
+ specified region.
+ (syms_of_buffer): New variable buffer-field-list.
+ (reset_buffer): Clear the fieldlist.
+ (init_buffer_once): Set up default and flag for buffer-field-list.
+ * insdel.c (prepare_to_modify_buffer): If check_protected_fields,
+ call Fregion_fields to detect error.
+ Delete buffer_modify_hook.
+
+ * callint.c (Fcall_interactively): Bind `command-debug-status'
+ for each interactive command.
+
+ * keyboard.c (command_loop_1): Count # commands read.
+ (num_input_keys): New Lisp variable.
+
+ * m/m-gould.h, m/m-ibmrt-aix.h, m/m-sequent.h, m/m-sparc.h,
+ m/m-sun3.h, m/m-symmetry.h: Define A_TEXT_SEEK.
+ * unexec.c (copy_text_and_data): Don't check A_TEXT_OFFSET,
+ just A_TEXT_SEEK.
+ * unexconvex.c: Likewise.
+
+ * unexconvex.c: machine/*.h unconditionally.
+
+ * process.c (pty): Delete RTU, HPUX, IRIS alternatives to
+ PTY_NAME_SPRINTF, PTY_TTY_NAME_SPRINTF.
+ * s/s-hpux.h: Define PTY_NAME_SPRINTF, PTY_TTY_NAME_SPRINTF.
+ * s/s-rtu.h: Likewise.
+ * s/s-iris*.h: Define PTY_TTY_NAME_SPRINTF.
+
+ * sunfns.c (Fsun_change_cursor_icon): Avoid ambiguity in eval order.
+
+Thu Jan 12 18:28:29 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * data.c (Fdefault_value): If var set up with default value as current,
+ take the current value slot, more up to date than the default slot.
+
+Wed Jan 11 15:22:14 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * dispnew.c (init_display): don't handle SIGWINCH if using X.
+
+ * fileio.c (Fdo_auto_save): If file has shrunk, turn off auto-save.
+ This avoids duplicate messages and allows M-x auto-save to turn it on.
+
+ * lread.c (Fload): Look in Vafter_load_alist.
+ (syms_of_load): Define after-load-alist.
+
+Sat Jan 7 01:43:47 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * dired.c (Fdirectory_files): 4th arg NOSORT non-nil means don't sort.
+
+ * syntax.c (scan_lists): Change Sendcomment case so that
+ ignoring comments works even for newline-terminated comments.
+
+ * minibuf.c (read_minibuf): Default Vminibuf_scroll_window
+ to the window that was selected.
+
+Fri Jan 6 02:51:46 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * fns.c (do_yes_or_no_p): Typo, call2 => call1.
+
+ * eval.c (Fbacktrace): Each frame item should have a newline.
+
+ * emacs.c (Fkill_emacs): Don't run hook if noninteractive.
+
+ * eval.c: Define Vrun_hooks.
+ (syms_of_eval): Initialize Vrun_hooks.
+
+ * indent.c (Fmove_to_column): Use del_range; Fdelete_backward non ex.
+
+ * ymakefile (objs, floatfns.o): Re-add this file.
+ (LIBX): Install X11 case.
+
+ * ymakefile (LIB_GCC): Now a cpp macro, like all other LIB_...
+ Define null if not using GCC.
+
+ * lread.c (unreadchar): New function to unread a char
+ by stuffing it back into its stream. Now unread chars
+ work properly between multiple reads.
+ (UNREAD): Now calls that function.
+ (readchar): Don't us `unrch'; variable deleted.
+ (various): Don't initialize `unrch'.
+ (readevalloop): No need to save and restore `unrch'.
+ (read1): Don't unread a -1.
+
+ * keymap.c (get_keyelt): If keymap defn is (STRING . FOO),
+ remove just FOO. Will help HierarKey.
+
+Thu Jan 5 14:49:14 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * unexmips.c [IRIS_4D]: Don't include fcntl.h.
+ (unexec): Look for LIT8, LIT4 sections iff they are defined.
+
+ * buffer.c (Fkill_all_local_variables): Force redisplay of mode lines.
+
+Mon Jan 2 13:52:58 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * emacs.c (main): Do the setpgrp before handling -t.
+
+ * keyboard.c (Fsuspend_emacs): Use run-hooks to run suspend-hook
+ and suspend-resume-hook.
+
+ * buffer.c (Fkill_buffer): Execute kill-buffer-hooks
+ with buffer to be killed as current buffer.
+
+ * buffer.c (count_modified_buffers): ModExist renamed.
+
+ * emacs.c (Fkill-emacs): Execute kill-emacs-hook.
+
+ * fileio.c (auto_save_1): Set auto_save_mode_bits from visited file.
+ (Fwrite_region) [not VMS]: If auto-saving, write file with that mode.
+
+ * fileio.c (Fwrite_region): If START is a string, write that string.
+
+Sun Jan 1 14:00:50 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * lisp.h (XMARKBIT, XSETMARKBIT): If mark bit is sign bit,
+ use sign-test for XMARKBIT; value is then 1 or 0.
+ Make XSETMARKBIT test 2nd arg for nonzeroness only.
+
+ * m/m-mips.h: Last batch of changes are only for USG.
+ (XMARKBIT, XSETMARKBIT): Deleted; the new default ones are good.
+
+ * editfns.c (Fformat): Use princ for %s.
+ New format %S converts everything (even strings) with prin1.
+ * doprnt.c (doprnt): Treat %s like %S.
+
+ * print.c (Fprin1_to_string): Opt 3nd arg non-nil does princ.
+
+Sat Dec 31 14:18:31 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * data.c (Fstring_to_int): Correct max # args.
+
+Fri Dec 30 02:14:11 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * ymakefile (LIBES, LIB_GCC): If using GCC, link with gnulib.
+
+Thu Dec 29 18:50:10 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * editfns.c: Many doc improvements.
+
+Wed Dec 28 02:34:04 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * lisp.h (CHECK_NATNUM): New macro.
+
+ * indent.c (Fmove_to_column): 2nd arg t means indent till spec'd column
+ or change tab to spaces if necessary.
+
+ * m/m-iris4d.h: (conditionally) delete DEFAULT_ENTRY_ADDRESS
+ and change START_FILES and LIB_STANDARD.
+
+ * s/s-iris3-6.h: Define sigblock as no-op.
+
+ * m/m-mips.h: Cancel defn of VIRT_ADDR_VARIES, `static'.
+ Undef SIGIO. Define BROKEN_FIONREAD.
+ Define various HAVE_... flags a la BSD.
+ Add options, libraries for linking and compilation.
+
+ * unexmips.c (unexec): Handle additional optional sections now likely.
+ New scheme for recording what sections there are.
+ Make handling of the LIT8,LIT4 sections conditional (not on IRIS).
+
+ * fns.c (do_yes_or_no_p): New interface to Lisp function yes-or-no-p.
+ Allows the user to redefine that function.
+ All callers of Fyes_or_no_p changed.
+
+ * data.c (Fmakunbound): Don't allow nil or t as arg.
+
+ * m/m-orion105.h (LOAD_AVE_TYPE): Now `long'.
+
+Tue Dec 27 23:44:41 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * dispnew.c (unhold_window_change):
+ Don't signal SIGWINCH. Instead, do pending size-changes here,
+ while holding any new size-changes that arrive, so they become
+ pending. Loop around to get the new pending ones.
+ (change_screen_size): Clear any previous pending size-change.
+
+ * search.c (place): Was clipping to (1- (point-max)) by mistake.
+
+Sat Dec 24 17:45:38 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * window.c (Fdelete_window): Give all this window's space
+ to one adjacent sibling.
+
+Fri Dec 23 01:16:18 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * keymap.c (describe_alist): Don't lose on non-cons-cell alist elts.
+ (Fwhere_is_internal): Don't fail to step down the alist.
+ (Faccessible_keymaps): Considerable confusion in alist case.
+
+ * lread.c (Feval_current_buffer, Feval_region):
+ Save and restore point as a marker, not a number.
+ Don't restore it at all if printflag is t.
+
+ * print.c (float_to_string): Mostly rewritten; output format
+ is now a printf %-spec.
+ (Qfloat_output_format): Doc changed to match.
+
+Thu Dec 22 12:22:24 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * ymakefile (obj): Include floatfns.o.
+ * data.c (syms_of_data): Fix typo Snumberp_or_marker_p.
+
+ * Allow keymaps to have other keymaps as tails.
+ Thus, one keymap can inherit from another.
+ * keymap.c (Fwhere_is_internal): Ignore non-cons elements of alist.
+ (Faccessible_keymaps): Support symbols as alist indices.
+ Ignore alist elements that aren't conses.
+
+ * m/m-sun386.h (LDAV_SYMBOL): Define as "avenrun" with no underscore.
+
+ * lread.c (read_escape): Support ANSI C `\x...' hex escapes.
+
+ * bytecode.c (Fbyte_code): fix jump operators for change in `pc'.
+
+Wed Dec 21 19:39:27 1988 Joe Arceneaux (jla at gracilis.ai.mit.edu)
+
+ * ymakefile: Commented #endif LISP_FLOAT_TYPE. Also changed
+ the code pertaining to X11 to use the same files as X10.
+
+ * bytecode.c (Fbyte_code): Declared unsigned char *pc.
+
+Mon Dec 19 17:27:14 1988 Joe Arceneaux (jla at apple-gunkies.ai.mit.edu)
+
+ * xterm.c: Finished a first cut of the X11 version.
+
+Sun Dec 18 13:08:17 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * sysdep.c (select): `buf' is now unsigned char.
+
+Fri Dec 16 18:00:36 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * m/m-elxsi.h: Don't define WORD_MACHINE or CANNOT_DUMP.
+ Do define symbols for load average.
+ Define COFF and ADJUST_EXEC_HEADER.
+
+Fri Dec 16 13:56:51 1988 Joe Arceneaux (jla at apple-gunkies.ai.mit.edu)
+
+ * sink.h,sinkmask.h: Same file now works for both X10 and X11.
+ * xterm.c,xfns.c (x_text_icon) Can now take new name as parameter.
+
+Fri Dec 16 11:07:20 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * m/m-is386.h: No need to undef HAVE_PTYS, HAVE_SOCKETS, SYSV_PTYS
+ since s-usg5-3.h no longer defines them.
+
+Wed Dec 14 17:52:51 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * bytecode.el (Fbyte_code): Cache the pointer in the string
+ to avoid recalculating it at each fetch.
+ Also turn off the error check for stack overflow/underflow.
+
+Wed Dec 14 14:51:24 1988 Joe Arceneaux (jla at apple-gunkies.ai.mit.edu)
+
+ * xfns.c: Made the first cut for X11 version.
+ * xterm.c: (x_reset_cursor) Did the X11 version.
+
+Wed Dec 14 13:02:30 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * keyboard.c (Fexecute_mouse_event): Set Vmouse_event. Doc fix.
+ Run Vmouse_hook at the end.
+ (syms_of_keyboard): Define var `mouse-hook'.
+
+Tue Dec 13 10:55:27 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * term.c (insert_glyfs): Typo, was fetching G twice.
+
+Sat Dec 10 17:37:28 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * keymap.c (describe_buffer_bindings): Print mouse bindings too.
+ (describe_map): If have a chartab, use mouse-describe-key for prefixes.
+ * keymap.c (describe_{map,map_tree,alist}, describe_vector):
+ Extra arg mapping chars to their names. Calls changed.
+ * syntax.c (describe_syntax_1): Call changed.
+
+ * keymap.c (Vglobal_mouse_map): Make it exist unconditionally.
+
+ * keymap.c (apropos1): Clean up.
+ Do where-is-internal only if there is a function definition.
+ Use mouse-describe-key to turn mouse key sequences into strings.
+ (Fwhere_is): Check the mouse map too;
+ (Fwhere_is_internal): New arg is global map to use.
+ All callers changed in keypad.c and doc.c.
+ (where_is_string): New fn cvts result of Fwhere_is_internal to string.
+
+Fri Dec 9 23:40:16 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * emacs.c (stack_bottom): New variable, set in main.
+ * alloc.c (Fgarbage_collect): Save a copy of the entire stack contents.
+
+Wed Dec 7 17:07:47 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * editfns.c (Funix_umask, Funix_sync): New functions.
+
+ * process.c (Fsignal_process): New function.
+
+Tue Dec 6 21:03:22 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * editfns.c (Fsubst_char_in_region): Fix typo in when to un-modify buf.
+
+Mon Dec 5 14:42:23 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * process.c (create_process): Take the usg's setpgrp and the close-and
+ -open of the tty outside the TIOCNOTTY conditional, since TIOCNOTTY
+ is always missing outside BSD. Now the TIOCNOTTY conditional controls
+ only the TIOCNOTTY.
+
+Sun Dec 4 11:15:15 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * lread.c (Feval_current_buffer, Feval_region):
+ If there is an error, don't restore original point.
+
+ * s-hpux.h (SHORT_CAST_BUG): Define this, for HPUX version 6.2.
+
+ * ymakefile (THIS_IS_YMAKEFILE): Define macro to tell m- files
+ to do special things.
+
+ * m/m-ns16000.h: (LOAD_AVE_TYPE, etc.): Don't define them if USG.
+ * m/m-ns16000.h [USG]: Define various macros differently.
+ (munnari!sibyl.eleceng.ua.oz.au!ian@uunet.uu.net).
+
+ * sysdep.c (reset_sys_modes): Don't output a CR here.
+ * term.c (reset_terminal_modes): Do it here, but first
+ do a newline if it's a magic cookie terminal.
+
+ * sysdep.c (sys_suspend) [USG]: Use `nice' to set subshell pri. to 0.
+
+ * sysdep.c (TIOCSETN) [USG]: Use TCSETAW, not TCSETA.
+
+ * sysdep.c (setpriority) [USG]: No longer a no-op; use `nice'.
+
+ * keymap.c (Fwhere_is_internal): New 4th arg inhibits looking thru
+ indirect definitions--so you can search for one.
+
+ * alloc.c, fns.c, search.c: Doc fix.
+
+Thu Dec 1 16:46:51 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * process.c (read_process_output): Insert with insert_before_markers.
+
+ * filelock.c (lock_file_1, lock_superlock):
+ If USG, use chmod instead of fchmod.
+
+ * environ.c (Fsetenv): Doc fix.
+
+Fri Nov 25 13:41:15 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * eval.c (do_autoload): Verify FUNNAME is a symbol.
+
+Thu Nov 17 23:26:03 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * fileio.c (Fread_file_name): New arg specifies initial minibuf cntnts.
+ * callint.c (Fcall_interactively): Calls changed.
+
+Sat Oct 8 03:20:07 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * insdel.c (make_gap): Error if buffer size exceeds range of Lisp int.
+
+Thu Oct 6 05:34:48 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * window.c (Fsplit_window): Prevent error in Fset_window_buffer.
+
+ * sysdep.c (gettimeofday): Store -1 thru tzp so caller knows invalid.
+
+ * xdisp.c (message): Pass 0 as new arg to doprnt.
+ * callint.c (Fcall_interactively): Likewise.
+ * editfns.c (format1):
+ * doprnt.c (doprnt): Allow 0 as FORMAT_END arg meaning null-terminated.
+
+Wed Oct 5 18:43:53 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * keyboard.c: If UNIPLUS, include ioctl.h.
+
+ * sysdep.c (utime): Use new flag IRIS_UTIME, not IRIS.
+ * s-iris*.h: Define that flag.
+
+Tue Oct 4 21:04:42 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * term.c (term_init): If have `im' capability, permit ins/del char
+ even without `ic'.
+
+Mon Oct 3 00:32:34 1988 Richard Stallman (rms at corn-chex.ai.mit.edu)
+
+ * m/m-hp9000s300.h: Conditionals for BSD vs HPUX.
+
+ * ymakefile: Look for C_SWITCH_SITE, LD_SWITCH_SITE.
+
+Fri Sep 30 15:48:51 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * editfns.c (Fformat): Allow nulls in the format.
+ * doprnt.c (doprnt): likewise. End of format string is new arg.
+
+Wed Sep 28 15:25:37 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * m/m-7300.h: Undefine SHORTNAMES. Supposedly newer Unix now.
+
+ * print.c (print): Support new var print_length.
+ (syms_of_print): Define Lisp var print-length.
+ * eval.c (Fbacktrace): Print unevalled form with print_length = 3.
+
+ * Makefile (tags): Add TAGS as alternate target.
+ Process the files in ../lisp/term.
+
+Tue Sep 27 00:55:47 1988 Richard Stallman (rms at corn-chex.ai.mit.edu)
+
+ * doprnt.c (doprnt): Handle %-20s.
+ * editfns.c (Fformat): Likewise (make enough space for it).
+
+ * minibuf.c (do_completion): If get "Complete but not unique" twice
+ in a row, display all completions. New var last_exact_completion.
+
+Mon Sep 26 19:19:23 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+* * dispnew.c (baud_rate): Now a Lisp variable, not a function.
+ * termcap.c (tputs) [emacs]: Use baud_rate as the speed.
+
+Mon Sep 19 00:06:16 1988 Richard Stallman (rms at gluteus.ai.mit.edu)
+
+ * window.c (Fset_window_configuration): Set deleted windows' buffer
+ to nil, via new function delete_all_subwindows.
+ * window.c (Fset_window_buffer): Reject deleted windows.
+ * window.c (init_window_once): Init the ->buffer fields
+ to satisfy error check in Fset_window_buffer.
+
+* * xmenu.c (Fx_popup_menu): 1st arg is now ((X Y) WINDOW).
+
+ * process.c (child_sig): If synch process terminates, clear
+ synch_process_pid and record synch_process_death.
+* * callproc.c (Fcall_process): return synch_process_death.
+ Always set synch_process_pid and do it with SIGCHLD masked off.
+ * sysdep.c (wait_for_termination) [subprocesses and not VMS]:
+ Use alarms to check every second whether synch_process_pid is 0.
+
+Sat Sep 17 17:14:32 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * xdisp.c (redisplay_window): If window-point is outside restriction
+ then correct it in the window.
+ * window.c (Fdelete_buffer): Don't change buffer's point to a value
+ outside its restriction.
+
+ * sysdep.c (init_sys_modes) [MULTI_SCREEN]: Set Vterminal_screen's
+ garbaged bit.
+
+Fri Sep 16 01:13:09 1988 Richard Stallman (rms at corn-chex.ai.mit.edu)
+
+ * keyboard.c (kbd_buffer_get_char): VMS now uses same code as Unix.
+
+ * vmsproc.c: New file for VMS only.
+ * callproc.c [VMS]: Omit Fcall_process and child_setup_tty.
+ * emacs.c (main) [VMS]: Call init_vmsproc and syms_of_vmsproc.
+
+ * lread.c (OBARRAY_SIZE): Change slightly to 509 (prime).
+
+* * keyboard.c, dispnew.c, term.c, xterm.c (meta_flag): MetaFlag renamed.
+ * keyboard.c (Fset_input_mode): 3rd arg sets meta_flag.
+ (syms_of_keyboard): Variable meta-flag deleted.
+ * sysdep.c (init_sys_modes): Don't override parity settings
+ if meta_flag is 0.
+
+Thu Sep 15 23:29:12 1988 Richard Stallman (rms at corn-chex.ai.mit.edu)
+
+* * search.c (Fsearch_forward, etc.): All buffer-search functions
+ return new the value of point if they succeed.
+
+Tue Sep 13 12:00:22 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * cmds.c (Fnewline): Correct test of ARG1 to inhibit auto-fill.
+
+Mon Sep 12 16:39:32 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * window.c (Fdelete_window): Put nil as buffer of the deleted window.
+ This makes select-window get an error earlier.
+
+Tue Sep 6 20:43:10 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * search.c (search_buffer, string_match, looking_at):
+ Report matcher stack overflow as error, not just failure to match.
+
+ * data.c (Fmake_local_variable): Add local variable to simplify
+ too-complex expression.
+
+ * fileio.c (Fdo_auto_save): No "file has shrunk" msg if < 5000 chars.
+
+Local Variables:
+mode: indented-text
+left-margin: 8
+fill-column: 74
+version-control: never
+End:
diff --git a/src/Makefile.in b/src/Makefile
index dfc51a0ec29..98fde55d448 100644
--- a/src/Makefile.in
+++ b/src/Makefile
@@ -1,8 +1,5 @@
-MAKE = make
-# BSD doesn't have it as a default.
-
-CC = gcc
CPP = $(CC) -E
+MAKE = make # BSD doesn't have it as a default.
#Note: an alternative is CPP = /lib/cpp
# Just to avoid uncertainty.
@@ -15,11 +12,11 @@ doall:
#This is used in making a distribution.
#Do not use it on development directories!
-distclean:
- -rm -f paths.h config.h emacs-* temacs xemacs xmakefile core *~ \#* *.o
+distclean: clean
+ -rm -f paths.h config.h emacs-* *~ log*
clean:
- -rm -f temacs xemacs xmakefile core \#* *.o
+ -rm -f temacs xemacs xmakefile core \#* *.o libXMenu11.a
xemacs: xmakefile doxemacs
@@ -36,9 +33,9 @@ dotemacs:
xmakefile: ymakefile config.h
-rm -f xmakefile junk.c
cp ymakefile junk.c
- $(CPP) junk.c | sed -e 's/^#.*//' -e 's/^[ \f\t][ \f\t]*$$//' -e 's/^ / /' | \
+ $(CPP) junk.c | sed -e 's/^#.*//' -e 's/^[ ][ ]*$$//' -e 's/^ / /' | \
sed -n -e '/^..*$$/p' > xmakefile
rm -f junk.c
-tags TAGS:
- etags [a-z]*.h [a-z]*.c ../lisp/[a-z]*.el ../lisp/term/[a-z]*.el
+tags:
+ etags [a-z]*.h [a-z]*.c ../lisp/[a-z]*.el
diff --git a/src/README b/src/README
new file mode 100644
index 00000000000..7ce61995353
--- /dev/null
+++ b/src/README
@@ -0,0 +1,26 @@
+This directory contains the source files for the C component of GNU Emacs.
+Nothing in this directory is needed for using Emacs once it is built
+and installed, if the dumped Emacs (on Unix systems) or the Emacs
+executable and map files (on VMS systems) are copied elsewhere.
+
+On Unix, building is controlled by a makefile called `xmakefile'
+that is generated with machine-dependent contents from `ymakefile'
+using `cpp'. `Makefile' just invokes `cpp' to produce `xmakefile'
+and then runs `make' on `xmakefile'.
+
+See the file VMSBUILD in this directory for instructions on compiling,
+linking and building Emacs on VMS.
+
+The files `*.com' and `temacs.opt' are used on VMS only.
+The files `vlimit.h', `ioclt.h' and `param.h' are stubs to
+allow compilation on VMS with the minimum amount of #ifdefs.
+
+`uaf.h' contains VMS uaf structure definitions. This is only needed if
+you define READ_SYSUAF. This should only be done for single-user
+systems where you are not overly concerned with security, since it
+either requires that you install Emacs with SYSPRV or make SYSUAF.DAT
+world readable. Otherwise, Emacs can determine information about the
+current user, but no one else.
+
+`pwd.h' contains definitions for VMS to be able to correctly simulate
+`getpwdnam' and `getpwduid'.
diff --git a/src/TAGS b/src/TAGS
new file mode 100644
index 00000000000..a19e5755614
--- /dev/null
+++ b/src/TAGS
@@ -0,0 +1,6961 @@
+
+acldef.h,0
+
+buffer.h,457
+#define BUF_BEG(60,2434
+#define BUF_BEGV(62,2530
+#define BUF_BEG_ADDR(75,3033
+#define BUF_CHAR_ADDRESS(87,3505
+#define BUF_GAP_SIZE(83,3324
+#define BUF_GPT(66,2700
+#define BUF_MODIFF(72,2948
+#define BUF_PT(64,2618
+#define BUF_Z(70,2886
+#define BUF_ZV(68,2804
+#define BufferSafeCeiling(266,10301
+#define BufferSafeFloor(268,10372
+#define FETCH_CHAR(262,10067
+#define PTR_CHAR_POS(92,3711
+#define SET_BUF_PT(80,3245
+#define SET_BUF_ZV(79,3187
+
+chpdef.h,0
+
+cm.h,46
+#define cmat(93,2972
+#define cmplus(94,3023
+
+commands.h,20
+#define Ctl(21,794
+
+dir.h,0
+
+dispextern.h,0
+
+emacssignal.h,311
+#define sigblock(19,594
+#define sighold(22,796
+#define sigmask(11,222
+#define sigmask(47,1377
+#define sigpause(18,528
+#define sigrelse(23,842
+#define sigsetmask(21,728
+#define sigunblock(20,660
+#define sigunblock(51,1443
+#define sys_sigdel(31,1120
+#define sys_sigdel(56,1571
+int (*sys_signal 25,889
+
+filetypes.h,0
+
+getpagesize.h,112
+#define getpagesize(17,192
+#define getpagesize(20,280
+#define getpagesize(23,357
+#define getpagesize(28,468
+
+gettime.h,0
+
+indent.h,0
+
+ioctl.h,0
+
+lisp.h,2660
+#define CHECK_BUFFER(504,14997
+#define CHECK_CONS(495,14676
+#define CHECK_IMPURE(527,15869
+#define CHECK_IMPURE(537,16250
+#define CHECK_IMPURE(544,16479
+#define CHECK_LIST(489,14449
+#define CHECK_MARKER(516,15434
+#define CHECK_NUMBER(513,15327
+#define CHECK_NUMBER_COERCE_MARKER(519,15543
+#define CHECK_PROCESS(510,15215
+#define CHECK_STRING(492,14567
+#define CHECK_SYMBOL(498,14779
+#define CHECK_VECTOR(501,14888
+#define CHECK_WINDOW(507,15106
+#define CONSP(486,14356
+#define DEFUN(600,19086
+#define DEFVARBOOL(616,19608
+#define DEFVARINT(617,19673
+#define DEFVARLISP(615,19543
+#define DEFVARPERBUFFER(618,19736
+#define DEFVAR_BOOL(623,19964
+#define DEFVAR_INT(624,20030
+#define DEFVAR_LISP(621,19820
+#define DEFVAR_LISP_NOPRO(622,19886
+#define DEFVAR_PER_BUFFER(625,20094
+#define DOWNCASE(686,21687
+#define EQ(487,14400
+#define GCPRO1(721,22845
+#define GCPRO2(725,22967
+#define GCPRO3(730,23170
+#define GCPRO4(736,23452
+#define LOWERCASEP(669,21166
+#define NOCASEP(674,21312
+#define NULL(484,14256
+#define UPCASE(678,21441
+#define UPCASE1(682,21567
+#define UPPERCASEP(665,21082
+#define XBUFFER(393,11894
+#define XCONS(392,11845
+#define XFASTINT(269,8286
+#define XFASTINT(359,10771
+#define XFUNCTION(398,12150
+#define XGCTYPE(325,9973
+#define XGCTYPE(383,11628
+#define XINT(274,8440
+#define XINT(363,10905
+#define XINT(365,10947
+#define XINTPTR(401,12301
+#define XMARK(343,10379
+#define XMARK(386,11743
+#define XMARKBIT(335,10237
+#define XMARKBIT(384,11661
+#define XMARKER(399,12202
+#define XOBJFWD(400,12255
+#define XPNTR(286,8792
+#define XPNTR(295,9176
+#define XPNTR(297,9251
+#define XPNTR(369,11039
+#define XPROCESS(403,12387
+#define XSET(314,9542
+#define XSET(374,11209
+#define XSETBUFFER(406,12489
+#define XSETCONS(405,12443
+#define XSETFUNCTION(411,12727
+#define XSETINT(302,9328
+#define XSETINT(370,11068
+#define XSETINTPTR(414,12873
+#define XSETMARKBIT(339,10301
+#define XSETMARKBIT(385,11698
+#define XSETMARKER(412,12777
+#define XSETOBJFWD(413,12825
+#define XSETPNTR(310,9483
+#define XSETPNTR(372,11161
+#define XSETPROCESS(416,12969
+#define XSETSTRING(409,12631
+#define XSETSUBR(408,12585
+#define XSETSYMBOL(410,12679
+#define XSETTYPE(264,8070
+#define XSETTYPE(355,10580
+#define XSETUINT(306,9420
+#define XSETUINT(371,11114
+#define XSETVECTOR(407,12537
+#define XSETWINDOW(415,12921
+#define XSTRING(396,12044
+#define XSUBR(395,11995
+#define XSYMBOL(397,12097
+#define XTYPE(260,7992
+#define XTYPE(354,10533
+#define XUINT(281,8656
+#define XUINT(368,11010
+#define XUNMARK(347,10437
+#define XUNMARK(387,11778
+#define XVECTOR(394,11942
+#define XWINDOW(402,12339
+
+m-7300.h,34
+#define SIGN_EXTEND_CHAR(48,1470
+
+m-all2800.h,64
+#define LOAD_AVE_CVT(88,2871
+#define SIGN_EXTEND_CHAR(49,1701
+
+m-alliant.h,34
+#define SIGN_EXTEND_CHAR(53,1761
+
+m-alliant1.h,0
+
+m-alliant4.h,29
+#define LOAD_AVE_CVT(17,432
+
+m-altos.h,34
+#define SIGN_EXTEND_CHAR(38,1277
+
+m-amdahl.h,57
+#define SIGN_EXTEND_CHAR(55,1840
+#define XINT(130,4227
+
+m-apollo.h,34
+#define SIGN_EXTEND_CHAR(37,1227
+
+m-att3b.h,108
+#define SIGN_EXTEND_CHAR(49,1743
+#define XADDRFIX(144,4720
+#define XINT(130,4279
+#define XTYPE(142,4637
+
+m-aviion.h,90
+#define ADDR_CORRECT(133,4257
+#define SIGN_EXTEND_CHAR(48,1574
+#define alloca(111,3477
+
+m-bullx20.h,82
+#define SIGN_EXTEND_CHAR(50,1730
+#define bcopy(108,3646
+#define bzero(109,3689
+
+m-celerity.h,64
+#define LOAD_AVE_CVT(58,1749
+#define SIGN_EXTEND_CHAR(42,1327
+
+m-convex.h,87
+#define LOAD_AVE_CVT(74,2227
+#define SIGN_EXTEND_CHAR(48,1573
+#define XINT(120,3741
+
+m-cydra5.h,64
+#define LOAD_AVE_CVT(74,2354
+#define SIGN_EXTEND_CHAR(48,1577
+
+m-delta.h,34
+#define SIGN_EXTEND_CHAR(50,1678
+
+m-delta88.h,34
+#define SIGN_EXTEND_CHAR(58,1975
+
+m-dpx2-200.h,0
+
+m-dpx2-300.h,0
+
+m-dpx2.h,66
+#define LOAD_AVE_CVT(143,4539
+#define SIGN_EXTEND_CHAR(114,3680
+
+m-dual.h,34
+#define SIGN_EXTEND_CHAR(42,1345
+
+m-elxsi.h,34
+#define SIGN_EXTEND_CHAR(49,1606
+
+m-gec63.h,154
+#define SIGN_EXTEND_CHAR(37,1223
+#define XPNTR(69,1931
+#define XSET(72,2036
+#define XSETPNTR(70,1965
+#define XSETTYPE(67,1854
+#define XTYPE(66,1786
+
+m-gould.h,96
+#define A_TEXT_OFFSET(117,3612
+#define LOAD_AVE_CVT(76,2318
+#define SIGN_EXTEND_CHAR(48,1606
+
+m-hp9000s300.h,143
+#define LOAD_AVE_CVT(86,2512
+#define LOAD_AVE_CVT(122,3558
+#define SIGN_EXTEND_CHAR(58,1788
+#define bcopy(163,4671
+#define bzero(164,4707
+
+m-hp9000s800.h,322
+#define LOAD_AVE_CVT(77,2393
+#define SIGN_EXTEND_CHAR(48,1568
+#define XMARKBIT(148,4560
+#define XSET(142,4297
+#define XSETINT(145,4428
+#define XSETMARKBIT(149,4590
+#define XSETPNTR(147,4516
+#define XSETUINT(146,4472
+#define XUINT(140,4223
+#define XUNMARK(152,4717
+#define bcopy(179,5585
+#define bzero(180,5621
+
+m-ibmps2-aix.h,90
+#define LOAD_AVE_CVT(182,5226
+#define SIGN_EXTEND_CHAR(47,1555
+#define alloca(195,5713
+
+m-ibmrs6000.h,198
+#define ADDR_CORRECT(97,3000
+#define A_TEXT_OFFSET(91,2829
+#define N_BADMAG(88,2734
+#define N_SYMOFF(90,2797
+#define N_TXTOFF(89,2764
+#define SIGN_EXTEND_CHAR(43,1438
+#define signal(142,4323
+
+m-ibmrt-aix.h,245
+#define ADDR_CORRECT(94,2918
+#define A_TEXT_OFFSET(89,2753
+#define N_BADMAG(86,2658
+#define N_SYMOFF(88,2721
+#define N_TXTOFF(87,2688
+#define SIGN_EXTEND_CHAR(43,1435
+#define bcmp(177,6209
+#define bzero(176,6168
+#define killpg(179,6274
+
+m-ibmrt.h,64
+#define LOAD_AVE_CVT(75,2362
+#define SIGN_EXTEND_CHAR(48,1561
+
+m-intel386.h,174
+#define LOAD_AVE_CVT(75,2343
+#define LOAD_AVE_CVT(88,2748
+#define LOAD_AVE_CVT(98,3027
+#define SIGN_EXTEND_CHAR(47,1549
+#define alloca(169,4938
+#define signal(177,5111
+
+m-intel860.h,89
+#define LOAD_AVE_CVT(77,2405
+#define SIGN_EXTEND_CHAR(47,1543
+#define alloca(114,3353
+
+m-iris4d.h,274
+#define LOAD_AVE_CVT(82,2487
+#define SIGN_EXTEND_CHAR(48,1581
+#define XMARKBIT(181,5591
+#define XSET(174,5323
+#define XSETINT(177,5458
+#define XSETMARKBIT(182,5621
+#define XSETPNTR(179,5546
+#define XSETUINT(178,5502
+#define XUINT(172,5247
+#define XUNMARK(183,5693
+
+m-irist.h,120
+#define LOAD_AVE_CVT(109,3650
+ Date: 04 May 87 23:53:11 PDT 25,970
+#define SIGN_EXTEND_CHAR(78,2816
+ if 34,1383
+
+m-is386.h,0
+
+m-isi-ov.h,154
+#define A_TEXT_OFFSET(84,2233
+#define A_TEXT_SEEK(85,2272
+#define LOAD_AVE_CVT(64,1718
+#define LOAD_AVE_CVT(66,1788
+#define SIGN_EXTEND_CHAR(39,1239
+
+m-masscomp.h,64
+#define LOAD_AVE_CVT(76,2412
+#define SIGN_EXTEND_CHAR(48,1587
+
+m-mega68.h,64
+#define LOAD_AVE_CVT(57,1627
+#define SIGN_EXTEND_CHAR(41,1293
+
+m-mg1.h,64
+#define LOAD_AVE_CVT(78,2783
+#define SIGN_EXTEND_CHAR(49,1815
+
+m-mips.h,217
+#define LOAD_AVE_CVT(77,2381
+#define SIGN_EXTEND_CHAR(48,1555
+#define XSET(176,5239
+#define XSETINT(181,5400
+#define XSETPNTR(183,5488
+#define XSETUINT(182,5444
+#define XUINT(174,5161
+#define XUNMARK(185,5533
+
+m-mips4.h,0
+
+m-news-risc.h,24
+#define alloca(66,1167
+
+m-news.h,64
+#define LOAD_AVE_CVT(63,1733
+#define SIGN_EXTEND_CHAR(47,1393
+
+m-next.h,95
+#define A_TEXT_OFFSET(66,1960
+#define LOAD_AVE_CVT(60,1726
+#define SIGN_EXTEND_CHAR(44,1375
+
+m-ns16000.h,64
+#define LOAD_AVE_CVT(53,1603
+#define SIGN_EXTEND_CHAR(37,1266
+
+m-ns32000.h,34
+#define SIGN_EXTEND_CHAR(48,1610
+
+m-nu.h,34
+#define SIGN_EXTEND_CHAR(42,1342
+
+m-orion.h,64
+#define LOAD_AVE_CVT(75,2180
+#define SIGN_EXTEND_CHAR(55,1687
+
+m-orion105.h,89
+#define LOAD_AVE_CVT(62,1922
+#define SIGN_EXTEND_CHAR(44,1488
+#define sigmask(66,2078
+
+m-pfa50.h,109
+#define SIGN_EXTEND_CHAR(38,1326
+#define XGCTYPE(84,2527
+#define XTYPE(83,2465
+#define sigblock(110,3044
+
+m-plexus.h,34
+#define SIGN_EXTEND_CHAR(48,1570
+
+m-pmax.h,0
+
+m-pyramid.h,64
+#define LOAD_AVE_CVT(64,1901
+#define SIGN_EXTEND_CHAR(49,1513
+
+m-pyrmips.h,216
+#define LOAD_AVE_CVT(68,1963
+#define SIGN_EXTEND_CHAR(52,1533
+#define XSET(100,3021
+#define XSETINT(103,3152
+#define XSETPNTR(105,3240
+#define XSETUINT(104,3196
+#define XUINT(98,2947
+#define XUNMARK(107,3285
+
+m-seq386.h,0
+
+m-sequent.h,96
+#define A_TEXT_OFFSET(133,4218
+#define LOAD_AVE_CVT(91,2830
+#define SIGN_EXTEND_CHAR(51,1678
+
+m-sgi3000.h,0
+
+m-sparc.h,96
+#define A_TEXT_OFFSET(113,3277
+#define LOAD_AVE_CVT(73,2011
+#define SIGN_EXTEND_CHAR(42,1382
+
+m-stride.h,64
+#define LOAD_AVE_CVT(78,2442
+#define SIGN_EXTEND_CHAR(47,1565
+
+m-sun1.h,64
+#define LOAD_AVE_CVT(60,1698
+#define SIGN_EXTEND_CHAR(37,1223
+
+m-sun2.h,64
+#define LOAD_AVE_CVT(64,1875
+#define SIGN_EXTEND_CHAR(39,1378
+
+m-sun3.h,30
+#define A_TEXT_OFFSET(14,334
+
+m-sun386.h,30
+#define LOAD_AVE_CVT(35,1155
+
+m-tad68k.h,34
+#define SIGN_EXTEND_CHAR(48,1645
+
+m-tahoe.h,64
+#define LOAD_AVE_CVT(67,1836
+#define SIGN_EXTEND_CHAR(41,1272
+
+m-tandem-s2.h,0
+
+m-targon31.h,89
+#define LOAD_AVE_CVT(77,2409
+#define SIGN_EXTEND_CHAR(48,1567
+#define alloca(106,3397
+
+m-tek4300.h,64
+#define LOAD_AVE_CVT(66,1933
+#define SIGN_EXTEND_CHAR(47,1512
+
+m-template.h,64
+#define LOAD_AVE_CVT(74,2330
+#define SIGN_EXTEND_CHAR(48,1553
+
+m-tower32.h,34
+#define SIGN_EXTEND_CHAR(48,1590
+
+m-tower32v3.h,34
+#define SIGN_EXTEND_CHAR(48,1590
+
+m-triton88.h,0
+
+m-ustation.h,64
+#define LOAD_AVE_CVT(76,2368
+#define SIGN_EXTEND_CHAR(48,1567
+
+m-vax.h,94
+#define LOAD_AVE_CVT(63,1899
+#define LOAD_AVE_CVT(75,2138
+#define SIGN_EXTEND_CHAR(37,1236
+
+m-wicat.h,82
+#define SIGN_EXTEND_CHAR(48,1555
+#define bcopy(140,4003
+#define bzero(141,4038
+
+macros.h,0
+
+ndir.h,27
+#define rewinddir(51,1216
+
+param.h,0
+
+process.h,29
+#define ChannelMask(76,2938
+
+regex.h,0
+
+s-386bsd.h,37
+#define PENDING_OUTPUT_COUNT(31,771
+
+s-386ix.h,0
+
+s-aix3-1.h,29
+#define sigsetmask(175,4626
+
+s-aix3-2.h,0
+
+s-bsd4-1.h,0
+
+s-bsd4-2.h,0
+
+s-bsd4-3.h,0
+
+s-dgux.h,130
+#define _longjmp(208,6237
+#define _setjmp(207,6199
+#define getpgrp(203,6137
+#define setpgrp(202,6092
+#define signal(262,7517
+
+s-dgux4-31.h,0
+
+s-esix.h,0
+
+s-esix5r4.h,0
+
+s-hpux7.h,52
+#define WRETCODE(259,7124
+#define killpg(252,6984
+
+s-hpux8.h,0
+
+s-iris3-5.h,60
+#define ADDR_CORRECT(180,4936
+#define sigsetmask(139,3708
+
+s-iris3-6.h,87
+#define ADDR_CORRECT(185,5043
+#define sigblock(144,3839
+#define sigsetmask(143,3793
+
+s-irix3-3.h,0
+
+s-irix4-0.h,0
+
+s-isc2-2.h,0
+
+s-isc3-0.h,0
+
+s-mach2.h,0
+
+s-newsos5.h,0
+
+s-osf1.h,0
+
+s-rtu.h,24
+#define fsync(156,4813
+
+s-sco.h,23
+#define alloca(34,655
+
+s-sco3-2-1.h,44
+#define bcopy(16,436
+#define bzero(14,372
+
+s-sco3-2-2.h,0
+
+s-sco3-2-4.h,0
+
+s-sol2.h,0
+
+s-sunos4-0.h,0
+
+s-sunos4-1.h,0
+
+s-template.h,0
+
+s-umax.h,0
+
+s-unipl5-0.h,60
+#define ADDR_CORRECT(180,5028
+#define sigsetmask(151,4205
+
+s-unipl5-2.h,60
+#define ADDR_CORRECT(174,4695
+#define sigsetmask(145,3872
+
+s-usg5-0.h,60
+#define ADDR_CORRECT(179,4988
+#define sigsetmask(144,3931
+
+s-usg5-2-2.h,60
+#define ADDR_CORRECT(178,4976
+#define sigsetmask(143,3919
+
+s-usg5-2.h,60
+#define ADDR_CORRECT(178,4989
+#define sigsetmask(143,3932
+
+s-usg5-3.h,60
+#define ADDR_CORRECT(195,5352
+#define sigsetmask(158,4243
+
+s-usg5-4.h,51
+#define WRETCODE(109,2882
+#define wait3(107,2798
+
+s-vms.h,39
+#define PENDING_OUTPUT_COUNT(251,8090
+
+s-vms4-0.h,0
+
+s-vms4-2.h,0
+
+s-vms4-4.h,0
+
+s-vms5-5.h,0
+
+s-xenix.h,60
+#define ADDR_CORRECT(204,5924
+#define sigsetmask(175,5085
+
+sink.h,0
+
+sink11.h,0
+
+sink11mask.h,0
+
+sinkmask.h,0
+
+syntax.h,208
+#define SYNTAX(51,2020
+#define SYNTAX_COMEND_FIRST(74,3170
+#define SYNTAX_COMEND_SECOND(77,3297
+#define SYNTAX_COMSTART_FIRST(68,2911
+#define SYNTAX_COMSTART_SECOND(71,3040
+#define SYNTAX_MATCH(57,2258
+
+termchar.h,0
+
+termhooks.h,0
+
+termopts.h,0
+
+uaf.h,0
+
+vlimit.h,0
+
+vms-pwd.h,0
+
+vmspaths.h,0
+
+window.h,0
+
+x11term.h,152
+#define BLOCK_INPUT(12,244
+#define BLOCK_INPUT(15,388
+#define BLOCK_INPUT_DECLARE(10,172
+#define UNBLOCK_INPUT(13,312
+#define UNBLOCK_INPUT(16,426
+
+xkeys-aix.h,0
+
+xterm.h,390
+#define BLOCK_INPUT(23,320
+#define BLOCK_INPUT_DECLARE(22,268
+#define BLOCK_INPUT_DECLARE(50,908
+#define RESIGNAL_INPUT(27,486
+#define RESIGNAL_INPUT(54,1040
+#define SIGNAL_INPUT(25,442
+#define SIGNAL_INPUT_WHILE(34,615
+#define UNBLOCK_INPUT(24,388
+#define UNBLOCK_INPUT(52,960
+#define UNBLOCK_INPUT_RESIGNAL(41,745
+#define UNBLOCK_INPUT_RESIGNAL(56,1133
+#define sigmask(17,207
+
+abbrev.c,676
+DEFUN ("abbrev-expansion", Fabbrev_expansion,189,5635
+DEFUN ("abbrev-symbol", Fabbrev_symbol,163,4833
+DEFUN ("clear-abbrev-table", Fclear_abbrev_table,87,2581
+DEFUN ("define-abbrev", Fdefine_abbrev,102,2962
+DEFUN ("define-abbrev-table", Fdefine_abbrev_table,423,12265
+DEFUN ("define-global-abbrev", Fdefine_global_abbrev,138,4010
+DEFUN ("define-mode-abbrev", Fdefine_mode_abbrev,149,4373
+DEFUN ("expand-abbrev", Fexpand_abbrev,204,6133
+ Finsert_abbrev_table_description,383,11229
+DEFUN ("make-abbrev-table", Fmake_abbrev_table,80,2389
+DEFUN ("unexpand-abbrev", Funexpand_abbrev,314,9361
+describe_abbrev 361,10672
+syms_of_abbrev 460,13290
+write_abbrev 342,10235
+
+alloc.c,1279
+DEFUN ("cons", Fcons,202,5385
+DEFUN ("garbage-collect", Fgarbage_collect,796,21342
+DEFUN ("list", Flist,234,6294
+DEFUN ("make-list", Fmake_list,253,6737
+DEFUN ("make-marker", Fmake_marker,422,11091
+DEFUN ("make-string", Fmake_string,525,14138
+DEFUN ("make-symbol", Fmake_symbol,355,9375
+DEFUN ("make-vector", Fmake_vector,275,7258
+DEFUN ("purecopy", Fpurecopy,673,18178
+DEFUN ("vector", Fvector,306,8139
+#define STRING_FULLSIZE(508,13669
+#define VALIDATE_LISP_STORAGE(34,1185
+build_string 559,14984
+clear_marks 933,25417
+compact_strings 1368,35666
+display_malloc_warning 115,3435
+free_cons 195,5266
+gc_sweep 1188,31561
+init_alloc 1529,40182
+init_alloc_once 1510,39728
+init_cons 185,5011
+init_marker 413,10852
+init_strings 512,13761
+init_symbol 346,9136
+make_pure_string 624,16986
+make_pure_vector 658,17836
+make_string 548,14767
+make_uninit_string 566,15085
+malloc_warning 109,3361
+malloc_warning_1 98,2944
+mark_buffer 1168,31126
+mark_object 999,27001
+#define max(28,918
+memory_full 125,3684
+pure_cons 643,17471
+int pure[PURESIZE / sizeof 81,2401
+int pure[PURESIZE / sizeof 83,2483
+char staticvec1[NSTATICS * sizeof 730,19487
+staticpro 737,19688
+syms_of_alloc 1535,40223
+truncate_all_undos 1488,39136
+xmalloc 134,3831
+xrealloc 147,4048
+
+alloca.c,47
+alloca 141,3996
+find_stack_direction 85,2553
+
+buffer.c,1598
+DEFUN ("barf-if-buffer-read-only", Fbarf_if_buffer_read_only,742,21565
+DEFUN ("buffer-enable-undo", Fbuffer_enable_undo,520,15258
+DEFUN ("buffer-file-name", Fbuffer_file_name,336,9855
+DEFUN ("buffer-flush-undo", Fbuffer_flush_undo,510,15016
+DEFUN ("buffer-list", Fbuffer_list,106,3582
+DEFUN ("buffer-local-variables", Fbuffer_local_variables,348,10214
+DEFUN ("buffer-modified-p", Fbuffer_modified_p,408,12172
+DEFUN ("buffer-name", Fbuffer_name,309,9122
+DEFUN ("bury-buffer", Fbury_buffer,752,21883
+DEFUN ("current-buffer", Fcurrent_buffer,711,20468
+DEFUN ("erase-buffer", Ferase_buffer,897,26503
+DEFUN ("generate-new-buffer", Fgenerate_new_buffer,279,8359
+DEFUN ("get-buffer", Fget_buffer,113,3726
+DEFUN ("get-buffer-create", Fget_buffer_create,150,4850
+DEFUN ("get-file-buffer", Fget_file_buffer,128,4151
+DEFUN ("kill-all-local-variables", Fkill_all_local_variables,1012,29950
+DEFUN ("kill-buffer", Fkill_buffer,540,15726
+DEFUN ("list-buffers", Flist_buffers,996,29374
+DEFUN ("other-buffer", Fother_buffer,481,14139
+DEFUN ("pop-to-buffer", Fpop_to_buffer,692,19820
+DEFUN ("rename-buffer", Frename_buffer,456,13390
+DEFUN ("set-buffer", Fset_buffer,720,20687
+DEFUN ("set-buffer-modified-p", Fset_buffer_modified_p,427,12642
+DEFUN ("switch-to-buffer", Fswitch_to_buffer,660,18784
+init_buffer 1129,34366
+init_buffer_once 1044,31085
+keys_of_buffer 1354,43702
+list_buffers_1 932,27451
+nsberror 98,3409
+record_buffer 635,18208
+reset_buffer 233,6942
+reset_buffer_local_variables(249,7323
+set_buffer_internal 790,22915
+syms_of_buffer 1147,34839
+validate_region 911,26981
+
+bytecode.c,118
+#define DISCARD(139,3430
+DEFUN ("byte-code", Fbyte_code,146,3573
+#define PUSH(131,3274
+syms_of_bytecode 727,14021
+
+callint.c,259
+DEFUN ("call-interactively", Fcall_interactively,135,4548
+DEFUN ("interactive", Finteractive,87,3470
+DEFUN ("prefix-numeric-value", Fprefix_numeric_value,460,13569
+check_mark 127,4375
+quotify_arg 98,3732
+quotify_args 110,4023
+syms_of_callint 486,14130
+
+callproc.c,234
+DEFUN ("call-process", Fcall_process,100,2475
+DEFUN ("call-process-region", Fcall_process_region,287,6866
+call_process_cleanup 78,2088
+child_setup 334,8569
+init_callproc 429,11108
+#define max(46,1198
+syms_of_callproc 465,12187
+
+casefiddle.c,583
+DEFUN ("capitalize", Fcapitalize,88,2249
+DEFUN ("capitalize-region", Fcapitalize_region,152,4200
+DEFUN ("capitalize-word", Fcapitalize_word,217,5963
+DEFUN ("downcase", Fdowncase,80,2043
+DEFUN ("downcase-region", Fdowncase_region,140,3785
+DEFUN ("downcase-word", Fdowncase_word,205,5597
+DEFUN ("upcase", Fupcase,72,1845
+DEFUN ("upcase-region", Fupcase_region,128,3378
+DEFUN ("upcase-word", Fupcase_word,193,5239
+casify_object 30,983
+casify_region 100,2689
+keys_of_casefiddle 244,6703
+operate_on_word 177,4929
+syms_of_casefiddle 231,6424
+upcase_initials_region 169,4799
+
+cm.c,179
+Wcm_clear 380,9432
+Wcm_init 392,9553
+addcol 71,1619
+at 61,1504
+calccost 147,3842
+cmcostinit 107,2475
+cmgoto 279,7037
+cmputc 44,1159
+evalcost 37,1113
+losecursor 269,6937
+
+cmds.c,524
+DEFUN ("backward-char", Fbackward_char,55,1475
+DEFUN ("beginning-of-line", Fbeginning_of_line,102,2662
+DEFUN ("delete-backward-char", Fdelete_backward_char,180,4427
+DEFUN ("delete-char", Fdelete_char,146,3643
+DEFUN ("end-of-line", Fend_of_line,119,3081
+DEFUN ("forward-char", Fforward_char,30,967
+DEFUN ("forward-line", Fforward_line,70,1833
+DEFUN ("newline", Fnewline,208,5295
+DEFUN ("self-insert-command", Fself_insert_command,193,4902
+keys_of_cmds 330,8442
+self_insert_internal 250,6417
+syms_of_cmds 305,7788
+
+crt0.c,209
+_start 96,3451
+_start 119,3847
+_start(141,4250
+_start 215,5914
+_start 298,7839
+_start(503,12645
+static foo 276,7442
+start1 127,3993
+start1 223,6030
+start1 311,8103
+start1 313,8130
+start1 481,12333
+
+data.c,2874
+DEFUN ("1+", Fadd1,1328,36298
+DEFUN ("aref", Faref,940,27011
+Farray_length 991,28478
+DEFUN ("arrayp", Farrayp,219,5197
+DEFUN ("aset", Faset,965,27733
+DEFUN ("ash", Fash,1290,35277
+DEFUN ("atom", Fatom,147,3706
+DEFUN ("boundp", Fboundp,369,8665
+DEFUN ("bufferp", Fbufferp,239,5691
+DEFUN ("car", Fcar,287,6827
+DEFUN ("car-safe", Fcar_safe,303,7158
+DEFUN ("cdr", Fcdr,314,7406
+DEFUN ("cdr-safe", Fcdr_safe,330,7737
+DEFUN ("char-or-string-p", Fchar_or_string_p,276,6520
+DEFUN ("consp", Fconsp,138,3537
+DEFUN ("default-value", Fdefault_value,608,15266
+DEFUN ("eq", Feq,119,3210
+DEFUN ("=", Feqlsign,1003,28779
+DEFUN ("fboundp", Ffboundp,379,8924
+DEFUN ("fmakunbound", Ffmakunbound,398,9412
+DEFUN ("fset", Ffset,437,10409
+DEFUN (">=", Fgeq,1055,29994
+DEFUN (">", Fgtr,1029,29371
+DEFUN ("int-to-string", Fint_to_string,1092,30807
+DEFUN ("integer-or-marker-p", Finteger_or_marker_p,257,6064
+DEFUN ("integerp", Fintegerp,174,4299
+DEFUN ("kill-local-variable", Fkill_local_variable,889,25531
+DEFUN ("<=", Fleq,1042,29677
+DEFUN ("listp", Flistp,156,3896
+DEFUN ("logand", Flogand,1263,34639
+DEFUN ("logior", Flogior,1272,34849
+DEFUN ("lognot", Flognot,1348,36697
+DEFUN ("logxor", Flogxor,1281,35058
+DEFUN ("lsh", Flsh,1309,35769
+DEFUN ("<", Flss,1016,29068
+DEFUN ("make-local-variable", Fmake_local_variable,838,23736
+DEFUN ("make-variable-buffer-local", Fmake_variable_buffer_local,801,22303
+DEFUN ("makunbound", Fmakunbound,389,9206
+DEFUN ("markerp", Fmarkerp,248,5873
+DEFUN ("max", Fmax,1245,34222
+DEFUN ("min", Fmin,1254,34430
+DEFUN ("-", Fminus,1197,33145
+DEFUN ("natnump", Fnatnump,183,4473
+DEFUN ("/=", Fneq,1068,30314
+DEFUN ("nlistp", Fnlistp,165,4094
+DEFUN ("null", Fnull,129,3393
+DEFUN ("+", Fplus,1188,32961
+DEFUN ("/", Fquo,1217,33622
+DEFUN ("%", Frem,1226,33820
+DEFUN ("sequencep", Fsequencep,228,5417
+DEFUN ("set", Fset,633,16041
+DEFUN ("set-default", Fset_default,726,19784
+DEFUN ("setcar", Fsetcar,341,7985
+DEFUN ("setcdr", Fsetcdr,354,8302
+DEFUN ("setplist", Fsetplist,450,10820
+DEFUN ("setq-default", Fsetq_default,785,21868
+DEFUN ("string-to-int", Fstring_to_int,1104,31107
+DEFUN ("stringp", Fstringp,210,5023
+DEFUN ("1-", Fsub1,1338,36497
+DEFUN ("subrp", Fsubrp,267,6343
+DEFUN ("symbol-function", Fsymbol_function,407,9638
+DEFUN ("symbol-name", Fsymbol_name,426,10152
+DEFUN ("symbol-plist", Fsymbol_plist,418,9956
+DEFUN ("symbol-value", Fsymbol_value,535,12832
+DEFUN ("symbolp", Fsymbolp,192,4675
+DEFUN ("*", Ftimes,1208,33430
+DEFUN ("vectorp", Fvectorp,201,4849
+DEFUN ("zerop", Fzerop,1081,30622
+args_out_of_range 76,2417
+args_out_of_range_3 84,2555
+arith_error 1599,44050
+do_symval_forwarding 466,11225
+init_data 1621,44490
+make_number 92,2722
+pure_write_error 70,2339
+sign_extend_lisp_int 108,3019
+store_symval_forwarding 495,11823
+syms_of_data 1359,36907
+wrong_type_argument 49,1749
+
+dired.c,491
+DEFUN ("directory-files", Fdirectory_files,73,1721
+DEFUN ("file-attributes", Ffile_attributes,416,11462
+DEFUN ("file-name-all-completions", Ffile_name_all_completions,160,4307
+DEFUN ("file-name-all-versions", Ffile_name_all_versions,171,4604
+DEFUN ("file-name-completion", Ffile_name_completion,140,3478
+#define NAMLEN(31,962
+#define NAMLEN(42,1184
+file_name_completion 183,4907
+file_name_completion_stat 377,10514
+make_time 409,11336
+#define min(58,1399
+syms_of_dired 487,13873
+
+dispnew.c,1440
+DEFUN ("baud-rate", Fbaud_rate,1351,37928
+DEFUN ("ding", Fding,1378,38620
+DEFUN ("open-termscript", Fopen_termscript,1194,33027
+DEFUN ("screen-height", Fscreen_height,1238,34459
+DEFUN ("screen-width", Fscreen_width,1245,34633
+DEFUN ("send-string-to-terminal", Fsend_string_to_terminal,1360,38113
+DEFUN ("set-screen-height", Fset_screen_height,1214,33601
+DEFUN ("set-screen-width", Fset_screen_width,1226,34031
+DEFUN ("sit-for", Fsit_for,1504,41552
+DEFUN ("sleep-for", Fsleep_for,1409,39193
+#define PENDING_OUTPUT_COUNT(82,2066
+#define PENDING_OUTPUT_COUNT(84,2143
+bell 1398,38963
+cancel_line 345,8765
+cancel_my_columns 563,14897
+change_screen_size 1297,36240
+change_screen_size_1 1318,36882
+clear_screen_records 351,8836
+count_blanks 1177,32753
+count_match 1185,32866
+direct_output_for_insert 584,15674
+direct_output_forward_char 637,17231
+do_pending_window_change 1271,35292
+free_screen_structure 263,7015
+get_display_line 363,9099
+init_display 1567,43189
+line_draw_cost 321,8164
+line_hash_code 278,7343
+make_screen_structure 224,5795
+#define max(74,1733
+#define min(75,1775
+preserve_other_columns 522,13666
+quit_error_check 791,21526
+remake_screen_structures 188,4760
+rotate_vector 473,12578
+safe_bcopy 490,12950
+scroll_screen_lines 393,9899
+scrolling 803,21744
+syms_of_display 1634,44793
+timeval_subtract 1476,40717
+update_line 876,24089
+update_screen 666,18180
+window_change_signal 1253,34821
+
+doc.c,293
+DEFUN ("documentation", Fdocumentation,103,2474
+DEFUN ("documentation-property", Fdocumentation_property,151,4180
+DEFUN ("Snarf-documentation", Fsnarf_documentation,167,4696
+DEFUN ("substitute-command-keys", Fsubstitute_command_keys,278,7748
+get_doc_string 39,1091
+syms_of_doc 425,11982
+
+doprnt.c,15
+doprnt 26,966
+
+editfns.c,2442
+DEFUN ("bobp", Fbobp,408,10985
+DEFUN ("bolp", Fbolp,428,11439
+DEFUN ("buffer-string", Fbuffer_string,643,16397
+DEFUN ("buffer-substring", Fbuffer_substring,626,15954
+DEFUN ("buffer-size", Fbufsize,338,9217
+DEFUN ("char-after", Fchar_after,447,11867
+DEFUN ("char-equal", Fchar_equal,1018,26672
+DEFUN ("char-to-string", Fchar_to_string,122,3575
+DEFUN ("current-time-string", Fcurrent_time_string,511,13386
+DEFUN ("delete-region", Fdelete_region,752,19086
+DEFUN ("eobp", Feobp,418,11219
+DEFUN ("eolp", Feolp,437,11626
+DEFUN ("following-char", Ffollchar,384,10479
+DEFUN ("format", Fformat,901,23506
+DEFUN ("getenv", Fgetenv,1035,27222
+DEFUN ("goto-char", Fgoto_char,190,4923
+DEFUN ("insert", Finsert,527,13732
+DEFUN ("insert-before-markers", Finsert_before_markers,559,14390
+DEFUN ("insert-buffer-substring", Finsert_buffer_substring,652,16628
+DEFUN ("insert-char", Finsert_char,593,15235
+DEFUN ("mark", Fmark,231,5933
+DEFUN ("mark-marker", Fmark_marker,241,6257
+DEFUN ("message", Fmessage,882,22868
+DEFUN ("narrow-to-region", Fnarrow_to_region,776,19757
+DEFUN ("point", Fpoint,161,4397
+DEFUN ("point-marker", Fpoint_marker,171,4600
+DEFUN ("point-max", Fpoint_max,365,9922
+DEFUN ("point-max-marker", Fpoint_max_marker,376,10222
+DEFUN ("point-min", Fpoint_min,347,9402
+DEFUN ("point-min-marker", Fpoint_min_marker,357,9658
+DEFUN ("preceding-char", Fprevchar,396,10729
+DEFUN ("region-beginning", Fregion_beginning,216,5582
+DEFUN ("region-end", Fregion_end,223,5755
+DEFUN ("save-excursion", Fsave_excursion,321,8708
+DEFUN ("save-restriction", Fsave_restriction,859,21991
+DEFUN ("set-mark", Fset_mark,251,6565
+DEFUN ("string-to-char", Fstring_to_char,134,3815
+DEFUN ("subst-char-in-region", Fsubst_char_in_region,711,18062
+DEFUN ("system-name", Fsystem_name,504,13225
+DEFUN ("user-full-name", Fuser_full_name,497,13059
+DEFUN ("user-login-name", Fuser_login_name,466,12292
+DEFUN ("user-real-login-name", Fuser_real_login_name,474,12513
+DEFUN ("user-real-uid", Fuser_real_uid,490,12900
+DEFUN ("user-uid", Fuser_uid,483,12750
+DEFUN ("widen", Fwiden,764,19425
+buildmark 152,4245
+clip_to_bounds 179,4753
+format1 996,26244
+format1 999,26337
+init_editfns 49,1428
+insert1 521,13670
+#define max(39,1064
+#define min(38,1022
+region_limit 204,5306
+save_excursion_restore 295,7928
+save_excursion_save 286,7696
+save_restriction_restore 828,21285
+save_restriction_save 815,20899
+syms_of_editfns 1052,27649
+
+emacs.c,366
+DEFUN ("dump-emacs", Fdump_emacs,673,16359
+DEFUN ("dump-emacs-data", Fdump_emacs_data,642,15620
+DEFUN ("kill-emacs", Fkill_emacs,577,14314
+__do_clobal_ctors 222,5186
+__do_clobal_ctors_aux 224,5210
+__do_global_dtors 226,5238
+__main 230,5358
+decode_env_path 724,17538
+fatal_error_signal 137,3333
+init_cmdargs 186,4360
+main 236,5440
+syms_of_emacs 753,18070
+
+environ.c,331
+DEFUN ("getenv", Fgetenv,258,6379
+DEFUN ("setenv", Fsetenv,284,7178
+current_environ 208,5295
+egetenv 137,3690
+get_current_environ 171,4399
+getenv 130,3583
+getenv_1 72,1745
+init_environ 311,7752
+initialize_environment_alist 56,1429
+set_environment_alist 35,1016
+size_of_current_environ 146,3852
+syms_of_environ 304,7649
+
+eval.c,1811
+DEFUN ("and", Fand,196,5000
+DEFUN ("apply", Fapply,1469,38837
+DEFUN ("autoload", Fautoload,1180,31385
+DEFUN ("backtrace", Fbacktrace,2050,52779
+DEFUN ("backtrace-debug", Fbacktrace_debug,2028,52236
+DEFUN ("catch", Fcatch,772,19856
+DEFUN ("commandp", Fcommandp,1130,29770
+DEFUN ("cond", Fcond,245,6042
+DEFUN ("condition-case", Fcondition_case,914,23823
+DEFUN ("defconst", Fdefconst,539,13532
+DEFUN ("defmacro", Fdefmacro,488,11940
+DEFUN ("defun", Fdefun,470,11455
+DEFUN ("defvar", Fdefvar,509,12651
+DEFUN ("eval", Feval,1272,34099
+DEFUN ("funcall", Ffuncall,1672,43489
+DEFUN ("function", Ffunction,421,9850
+DEFUN ("if", Fif,226,5571
+DEFUN ("interactive-p", Finteractive_p,432,10144
+DEFUN ("let", Flet,617,15879
+DEFUN ("let*", FletX,582,14945
+DEFUN ("macroexpand", Fmacroexpand,693,17766
+DEFUN ("or", For,166,4433
+DEFUN ("prog1", Fprog1,315,7654
+DEFUN ("prog2", Fprog2,348,8320
+DEFUN ("progn", Fprogn,277,6879
+DEFUN ("quote", Fquote,413,9665
+DEFUN ("setq", Fsetq,383,9003
+DEFUN ("signal", Fsignal,1017,26508
+DEFUN ("throw", Fthrow,855,22212
+DEFUN ("unwind-protect", Funwind_protect,885,22907
+DEFUN ("user-variable-p", Fuser_variable_p,563,14310
+DEFUN ("while", Fwhile,671,17350
+apply1 1555,41214
+apply_lambda 1811,47068
+call0 1588,41948
+call1 1597,42081
+call2 1622,42543
+call3 1648,43041
+call_debugger 143,3802
+do_autoload 1242,33270
+do_debug_on_call 154,4093
+error 1121,29611
+find_handler_clause 1081,28541
+funcall_lambda 1856,48200
+grow_specpdl 1909,49469
+init_eval 131,3619
+init_eval_once 123,3432
+internal_catch 795,20616
+internal_condition_case 979,25687
+record_unwind_protect 1953,50632
+specbind 1931,50063
+syms_of_eval 2104,54045
+top_level_set 2009,51905
+top_level_value 1994,51622
+un_autoload 1219,32737
+unbind_catch 836,21825
+unbind_to 1966,50911
+
+fileio.c,2234
+DEFUN ("add-name-to-file", Fadd_name_to_file,1200,29934
+DEFUN ("clear-visited-file-modtime", Fclear_visited_file_modtime,2008,52242
+DEFUN ("copy-file", Fcopy_file,1045,25150
+DEFUN ("define-logical-name", Fdefine_logical_name,1299,33301
+DEFUN ("delete-file", Fdelete_file,1135,27842
+DEFUN ("directory-file-name", Fdirectory_file_name,418,10168
+DEFUN ("do-auto-save", Fdo_auto_save,2042,53029
+DEFUN ("expand-file-name", Fexpand_file_name,457,11410
+DEFUN ("file-directory-p", Ffile_directory_p,1462,37598
+DEFUN ("file-exists-p", Ffile_exists_p,1369,35084
+DEFUN ("file-modes", Ffile_modes,1479,38165
+DEFUN ("file-name-absolute-p", Ffile_name_absolute_p,1346,34482
+DEFUN ("file-name-as-directory", Ffile_name_as_directory,258,5853
+DEFUN ("file-name-directory", Ffile_name_directory,131,2916
+DEFUN ("file-name-nondirectory", Ffile_name_nondirectory,160,3654
+DEFUN ("file-newer-than-file-p", Ffile_newer_than_file_p,1539,39908
+DEFUN ("file-readable-p", Ffile_readable_p,1387,35600
+DEFUN ("file-symlink-p", Ffile_symlink_p,1400,35989
+DEFUN ("file-writable-p", Ffile_writable_p,1442,36978
+DEFUN ("insert-file-contents", Finsert_file_contents,1574,40738
+DEFUN ("make-symbolic-link", Fmake_symbolic_link,1241,31325
+DEFUN ("make-temp-name", Fmake_temp_name,446,11113
+DEFUN ("read-file-name", Fread_file_name,2215,58187
+DEFUN ("read-file-name-internal", Fread_file_name_internal,2137,56152
+DEFUN ("recent-auto-save-p", Frecent_auto_save_p,2126,55778
+DEFUN ("rename-file", Frename_file,1148,28305
+DEFUN ("set-buffer-auto-saved", Fset_buffer_auto_saved,2115,55432
+DEFUN ("set-file-modes", Fset_file_modes,1494,38536
+DEFUN ("substitute-in-file-name", Fsubstitute_in_file_name,800,19443
+DEFUN ("sysnetunam", Fsysnetunam,1327,34062
+DEFUN ("verify-visited-file-modtime", Fverify_visited_file_modtime,1974,51189
+DEFUN ("write-region", Fwrite_region,1706,44252
+auto_save_1 2034,52906
+auto_save_error 2019,52544
+barf_or_query_if_file_exists 1019,24454
+close_file_unwind 1568,40664
+directory_file_name 287,6807
+e_write 1941,50598
+#define err_str(52,1224
+expand_and_dir_to_file 993,23722
+file_name_as_directory 186,4272
+#define max(95,1882
+#define min(94,1840
+report_file_error 110,2324
+syms_of_fileio 2275,60006
+
+filelock.c,600
+# define CREATE_LOCK_FILE_NAME(104,2953
+# define CREATE_LOCK_FILE_NAME(110,3115
+DEFUN ("file-locked-p", Ffile_locked_p,398,9605
+DEFUN ("lock-buffer", Flock_buffer,357,8583
+DEFUN ("unlock-buffer", Funlock_buffer,375,9034
+current_lock_owner 268,6945
+current_lock_owner_1 283,7287
+static dummy 50,1211
+fill_in_lock_file_name 156,4325
+fill_in_lock_short_file_name 176,4640
+lock_file 119,3295
+lock_file_1 216,5820
+lock_file_owner_name 63,1442
+lock_if_free 244,6378
+lock_superlock 315,7793
+syms_of_filelock 421,10162
+unlock_all_files 341,8228
+unlock_buffer 390,9413
+unlock_file 300,7549
+
+filemode.c,73
+filemodestring 78,2555
+ftypelet(102,3253
+rwx 155,4052
+setst 168,4368
+
+fns.c,1454
+DEFUN ("append", Fappend,205,5060
+DEFUN ("assoc", Fassoc,529,13491
+DEFUN ("assq", Fassq,489,12469
+DEFUN ("concat", Fconcat,216,5396
+DEFUN ("copy-alist", Fcopy_alist,374,9429
+DEFUN ("copy-sequence", Fcopy_sequence,238,6110
+DEFUN ("delq", Fdelq,569,14596
+DEFUN ("elt", Felt,453,11582
+DEFUN ("equal", Fequal,779,19324
+DEFUN ("featurep", Ffeaturep,1302,32124
+DEFUN ("fillarray", Ffillarray,833,20779
+DEFUN ("get", Fget,734,18159
+DEFUN ("identity", Fidentity,75,1886
+DEFUN ("length", Flength,104,2629
+DEFUN ("load-average", Fload_average,1143,28250
+DEFUN ("mapcar", Fmapcar,1011,24814
+DEFUN ("mapconcat", Fmapconcat,975,23922
+DEFUN ("memq", Fmemq,471,12004
+DEFUN ("nconc", Fnconc,879,21817
+DEFUN ("nreverse", Fnreverse,601,15328
+DEFUN ("nth", Fnth,444,11364
+DEFUN ("nthcdr", Fnthcdr,427,11026
+DEFUN ("provide", Fprovide,1317,32645
+DEFUN ("put", Fput,752,18631
+DEFUN ("random", Frandom,83,2021
+DEFUN ("rassq", Frassq,549,14051
+DEFUN ("require", Frequire,1332,33076
+DEFUN ("reverse", Freverse,622,15764
+DEFUN ("sort", Fsort,643,16345
+DEFUN ("string-equal", Fstring_equal,138,3266
+DEFUN ("string-lessp", Fstring_lessp,157,3896
+DEFUN ("substring", Fsubstring,400,10147
+DEFUN ("vconcat", Fvconcat,227,5765
+DEFUN ("y-or-n-p", Fy_or_n_p,1032,25344
+DEFUN ("yes-or-no-p", Fyes_or_no_p,1082,26721
+assq_no_quit 513,13140
+concat 250,6505
+concat2 192,4821
+mapcar1 926,22827
+merge 675,17144
+nconc2 866,21611
+syms_of_fns 1364,34019
+
+hftctl.c,176
+#define BYTE4(99,4062
+GT_ACK 214,7466
+#define HFTYPE(97,4006
+#define RD_BUF(102,4162
+WR_REQ 302,10707
+hfqry 202,7170
+hfskbd 191,6889
+hft_alrm 279,9676
+hftctl 122,4733
+
+indent.c,501
+DEFUN ("current-column", Fcurrent_column,50,1592
+DEFUN ("current-indentation", Fcurrent_indentation,235,6018
+DEFUN ("indent-to", Findent_to,187,4824
+DEFUN ("move-to-column", Fmove_to_column,284,7056
+DEFUN ("vertical-motion", Fvertical_motion,591,15252
+ToCol 152,4157
+compute_motion 346,8676
+current_column 74,2396
+invalidate_current_column 68,2327
+#define max(36,1110
+#define min(35,1068
+pos_tab_offset 480,12270
+position_indentation 248,6358
+syms_of_indent 617,16110
+vmotion 505,12836
+
+insdel.c,339
+InsStr 244,5626
+adjust_markers 166,3931
+del_range 356,8312
+gap_left 41,1218
+gap_right 104,2505
+insert 254,5849
+insert_before_markers 333,7722
+insert_char 236,5509
+insert_from_string 292,6770
+insert_from_string_before_markers 344,7989
+make_gap 198,4546
+modify_region 404,9285
+move_gap 29,960
+prepare_to_modify_buffer 416,9575
+
+keyboard.c,2235
+DEFUN ("abort-recursive-edit", Fabort_recursive_edit,572,13916
+DEFUN ("command-execute", Fcommand_execute,1647,40381
+DEFUN ("discard-input", Fdiscard_input,1840,45730
+DEFUN ("execute-extended-command", Fexecute_extended_command,1710,42036
+DEFUN ("exit-recursive-edit", Fexit_recursive_edit,563,13640
+DEFUN ("input-pending-p", Finput_pending_p,1778,44013
+DEFUN ("open-dribble-file", Fopen_dribble_file,1822,45288
+DEFUN ("read-key-sequence", Fread_key_sequence,1623,39635
+DEFUN ("recent-keys", Frecent_keys,1788,44329
+DEFUN ("recursion-depth", Frecursion_depth,1813,45066
+DEFUN ("recursive-edit", Frecursive_edit,363,9103
+DEFUN ("set-input-mode", Fset_input_mode,2094,52892
+DEFUN ("suspend-emacs", Fsuspend_emacs,1858,46092
+DEFUN ("this-command-keys", Fthis_command_keys,1806,44849
+DEFUN ("top-level", Ftop_level,556,13507
+cancel_echoing 349,8841
+clear_input_pending 1773,43964
+clear_waiting_for_input 1972,49427
+cmd_error 419,10273
+command_loop 504,12243
+command_loop_1 587,14343
+command_loop_2 528,12921
+consume_available_input 1236,30348
+detect_input_pending 1762,43649
+echo 327,8448
+echo_char 279,7528
+echo_dash 311,8118
+echo_prompt 264,7254
+fast_read_one_key 1434,35107
+force_input_read 1172,28327
+get_input_pending 1184,28589
+gobble_input 1341,33017
+init_keyboard 2128,54012
+input_available_signal 1357,33235
+input_poll_signal 848,20957
+interrupt_signal 1992,50107
+kbd_buffer_read_command_char 1109,26879
+kbd_buffer_store_char 1079,26406
+keys_of_keyboard 2281,58985
+#define max(255,7015
+#define min(254,6980
+print_help 1064,26035
+quit_throw_to_read_command_char 2079,52574
+read_avail_input 1256,30893
+read_command_char 901,21947
+read_key_sequence 1497,36596
+record_auto_save 356,8985
+recursive_edit_1 388,9764
+recursive_edit_unwind 408,10087
+request_echo 802,20103
+set_waiting_for_input 1948,48856
+#define sigblockx(210,5788
+#define sigblockx(218,6025
+#define sigfree(208,5695
+#define sigholdx(209,5739
+#define sigpausex(212,5885
+#define sigpausex(220,6102
+#define sigunblockx(211,5836
+#define sigunblockx(219,6062
+start_polling 863,21255
+stop_polling 881,21532
+stuff_buffered_input 1919,48225
+syms_of_keyboard 2178,55160
+top_level_1 544,13159
+top_level_2 538,13098
+
+keymap.c,1915
+DEFUN ("accessible-keymaps", Faccessible_keymaps,553,14523
+DEFUN ("apropos", Fapropos,1214,29789
+DEFUN ("copy-keymap", Fcopy_keymap,232,5721
+DEFUN ("current-global-map", Fcurrent_global_map,546,14372
+DEFUN ("current-local-map", Fcurrent_local_map,539,14186
+DEFUN ("define-key", Fdefine_key,272,7003
+DEFUN ("define-prefix-command", Fdefine_prefix_command,504,13360
+DEFUN ("describe-bindings", Fdescribe_bindings,868,21922
+DEFUN ("global-key-binding", Fglobal_key_binding,430,11046
+DEFUN ("global-set-key", Fglobal_set_key,442,11453
+DEFUN ("global-unset-key", Fglobal_unset_key,482,12778
+DEFUN ("key-binding", Fkey_binding,389,9888
+DEFUN ("key-description", Fkey_description,605,15967
+DEFUN ("keymapp", Fkeymapp,113,3125
+DEFUN ("local-key-binding", Flocal_key_binding,416,10615
+DEFUN ("local-set-key", Flocal_set_key,459,12071
+DEFUN ("local-unset-key", Flocal_unset_key,492,13048
+DEFUN ("lookup-key", Flookup_key,336,8688
+DEFUN ("make-keymap", Fmake_keymap,65,1836
+DEFUN ("make-sparse-keymap", Fmake_sparse_keymap,75,2118
+DEFUN ("single-key-description", Fsingle_key_description,679,17183
+DEFUN ("text-char-description", Ftext_char_description,722,17948
+DEFUN ("use-global-map", Fuse_global_map,514,13641
+DEFUN ("use-local-map", Fuse_local_map,525,13890
+DEFUN ("where-is", Fwhere_is,848,21205
+DEFUN ("where-is-internal", Fwhere_is_internal,737,18310
+access_keymap 189,4829
+apropos1 1146,28226
+apropos_accum 1133,27875
+describe_alist 995,25040
+describe_buffer_bindings 880,22314
+describe_command 948,23899
+describe_map 975,24542
+describe_map_tree 915,23212
+describe_vector 1051,26222
+get_keyelt 169,4385
+get_keymap 162,4288
+get_keymap_1 138,3786
+insert_first_line 1185,29242
+keys_of_keymap 1325,33329
+#define min(28,909
+ndefkey 89,2542
+push_key_description 616,16333
+push_text_char_description 697,17588
+store_in_keymap 207,5210
+syms_of_keymap 1237,30659
+synkey 102,2866
+
+lastfile.c,22
+static dummy 40,1506
+
+lread.c,1085
+DEFUN ("eval-current-buffer", Feval_current_buffer,418,10471
+DEFUN ("eval-region", Feval_region,439,11140
+DEFUN ("get-file-char", Fget_file_char,152,3793
+DEFUN ("intern", Fintern,933,22501
+DEFUN ("intern-soft", Fintern_soft,964,23283
+DEFUN ("load", Fload,164,4047
+DEFUN ("mapatoms", Fmapatoms,1068,25761
+DEFUN ("read", Fread,470,12158
+DEFUN ("read-char", Fread_char,136,3474
+DEFUN ("read-from-string", Fread_from_string,502,13200
+#define UNREAD(129,3309
+absolute_filename_p 239,6228
+check_obarray 899,21664
+defalias 1136,27471
+defsubr 1126,27263
+defvar_bool 1167,28298
+defvar_int 1153,27987
+defvar_lisp 1180,28594
+defvar_lisp_nopro 1196,29034
+defvar_per_buffer 1212,29446
+hash_string 1021,24821
+init_obarray 1086,26160
+init_read 1235,30066
+intern 916,22070
+load_unwind 228,5985
+map_obarray 1040,25172
+mapatoms_1 1062,25672
+oblookup 985,23847
+openp 264,6999
+read0 545,14406
+read1 565,14770
+read_escape 818,20341
+read_list 757,18824
+read_vector 725,18028
+static int readchar 68,1795
+readevalloop 360,9381
+syms_of_read 1282,31353
+unreadpure 353,9264
+
+macros.c,380
+DEFUN ("call-last-kbd-macro", Fcall_last_kbd_macro,137,3802
+DEFUN ("end-kbd-macro", Fend_kbd_macro,72,2084
+DEFUN ("execute-kbd-macro", Fexecute_kbd_macro,165,4552
+DEFUN ("start-kbd-macro", Fstart_kbd_macro,41,1132
+finalize_kbd_macro_chars 132,3735
+init_macros 207,5618
+keys_of_macros 238,6479
+pop_kbd_macro 155,4376
+store_kbd_macro_char 113,3205
+syms_of_macros 215,5718
+
+malloc.c,523
+#define ASSERT(176,5873
+#define ASSERT(179,5974
+#define CHAIN(164,5419
+calloc 607,16050
+cfree 621,16276
+free 488,13322
+get_lim_data 748,18703
+get_lim_data 764,18953
+get_lim_data 771,19046
+getpool 374,10270
+malloc 413,11140
+malloc_init 218,6870
+malloc_mem_free 719,18126
+malloc_mem_used 700,17869
+malloc_stats 675,17506
+malloc_usable_size 233,7154
+memalign 630,16350
+morecore 244,7387
+realloc 545,14491
+#define start_of_data(108,3475
+#define start_of_data(113,3535
+sys_sbrk 827,20989
+valloc 657,17217
+
+marker.c,294
+DEFUN ("copy-marker", Fcopy_marker,265,6431
+DEFUN ("marker-buffer", Fmarker_buffer,27,879
+DEFUN ("marker-position", Fmarker_position,45,1394
+DEFUN ("set-marker", Fset_marker,74,2047
+marker_position 244,5990
+set_marker_restricted 138,3645
+syms_of_marker 291,7063
+unchain_marker 199,5039
+
+minibuf.c,1458
+DEFUN ("all-completions", Fall_completions,546,16915
+DEFUN ("completing-read", Fcompleting_read,654,19925
+DEFUN ("display-completion-list", Fdisplay_completion_list,981,28898
+DEFUN ("eval-minibuffer", Feval_minibuffer,258,8273
+DEFUN ("exit-minibuffer", Fexit_minibuffer,1056,31120
+DEFUN ("minibuffer-complete", Fminibuffer_complete,811,24527
+DEFUN ("minibuffer-complete-and-exit", Fminibuffer_complete_and_exit,832,24952
+DEFUN ("minibuffer-complete-word", Fminibuffer_complete_word,870,25696
+DEFUN ("minibuffer-completion-help", Fminibuffer_completion_help,1026,30241
+DEFUN ("minibuffer-depth", Fminibuffer_depth,1063,31267
+DEFUN ("read-buffer", Fread_buffer,325,10555
+DEFUN ("read-command", Fread_command,291,9522
+DEFUN ("read-from-minibuffer", Fread_from_minibuffer,224,6867
+DEFUN ("read-function", Fread_function,302,9833
+DEFUN ("read-minibuffer", Fread_minibuffer,245,7765
+DEFUN ("read-no-blanks-input", Fread_no_blanks_input,279,9089
+DEFUN ("read-string", Fread_string,270,8744
+DEFUN ("read-variable", Fread_variable,313,10153
+DEFUN ("self-insert-and-exit", Fself_insert_and_exit,1048,30919
+DEFUN ("try-completion", Ftry_completion,354,11417
+assoc_for_completion 785,23936
+do_completion 715,21967
+get_minibuffer 172,5291
+init_minibuf_once 1071,31470
+keys_of_minibuf 1154,34197
+#define min(29,939
+read_minibuf 79,2354
+read_minibuf_unwind 202,6006
+scmp 525,16597
+syms_of_minibuf 1077,31556
+temp_echo_area_contents 682,21275
+
+mocklisp.c,436
+DEFUN ("insert-string", Finsert_string,197,4972
+DEFUN ("ml-arg", Fml_arg,116,2815
+DEFUN ("ml-if", Fml_if,45,1283
+DEFUN ("ml-interactive", Fml_interactive,127,3172
+DEFUN ("ml-nargs", Fml_nargs,108,2600
+DEFUN ("ml-prefix-argument-loop", Fml_prefix_argument_loop,147,3732
+DEFUN ("ml-provide-prefix-argument", Fml_provide_prefix_argument,134,3375
+DEFUN ("ml-substr", Fml_substr,179,4371
+ml_apply 96,2352
+syms_of_mocklisp 228,5680
+
+pre-crt0.c,0
+
+print.c,540
+DEFUN ("prin1", Fprin1,338,8274
+DEFUN ("prin1-to-string", Fprin1_to_string,366,9078
+DEFUN ("princ", Fprinc,394,9902
+DEFUN ("print", Fprint,416,10503
+DEFUN ("terpri", Fterpri,320,7881
+DEFUN ("with-output-to-temp-buffer", Fwith_output_to_temp_buffer,284,6814
+DEFUN ("write-char", Fwrite_char,191,4917
+#define PRINTCHAR(92,2885
+internal_with_output_to_temp_buffer 264,6387
+print 452,11426
+printchar 98,3027
+strout 141,3797
+syms_of_print 673,16494
+temp_output_buffer_setup 246,6011
+write_string 211,5407
+write_string_1 228,5707
+
+process.c,3023
+#define FD_CLR(270,6528
+#define FD_ISSET(271,6571
+#define FD_SET(269,6486
+#define FD_ZERO(272,6614
+DEFUN ("accept-process-output", Faccept_process_output,1541,40832
+DEFUN ("continue-process", Fcontinue_process,2342,63420
+DEFUN ("delete-process", Fdelete_process,630,15492
+DEFUN ("get-buffer-process", Fget_buffer_process,583,14363
+DEFUN ("get-process", Fget_process,572,14071
+DEFUN ("interrupt-process", Finterrupt_process,2293,61738
+DEFUN ("kill-process", Fkill_process,2308,62345
+DEFUN ("list-processes", Flist_processes,951,24532
+DEFUN ("open-network-stream", Fopen_network_stream,1369,35955
+DEFUN ("process-buffer", Fprocess_buffer,755,19548
+DEFUN ("process-command", Fprocess_command,730,18784
+DEFUN ("process-exit-status", Fprocess_exit_status,692,17551
+DEFUN ("process-filter", Fprocess_filter,792,20638
+DEFUN ("process-id", Fprocess_id,708,18138
+DEFUN ("process-kill-without-query", Fprocess_kill_without_query,827,21667
+DEFUN ("process-list", Fprocess_list,962,24860
+DEFUN ("process-mark", Fprocess_mark,767,19858
+DEFUN ("process-name", Fprocess_name,719,18456
+DEFUN ("process-send-eof", Fprocess_send_eof,2356,63833
+DEFUN ("process-send-region", Fprocess_send_region,2098,56514
+DEFUN ("process-send-string", Fprocess_send_string,2121,57113
+DEFUN ("process-sentinel", Fprocess_sentinel,816,21376
+DEFUN ("process-status", Fprocess_status,657,16400
+DEFUN ("processp", Fprocessp,564,13898
+DEFUN ("quit-process", Fquit_process,2318,62678
+DEFUN ("set-process-buffer", Fset_process_buffer,742,19202
+DEFUN ("set-process-filter", Fset_process_filter,777,20095
+DEFUN ("set-process-sentinel", Fset_process_sentinel,803,20934
+DEFUN ("start-process", Fstart_process,969,25011
+DEFUN ("stop-process", Fstop_process,2328,63026
+DEFUN ("waiting-for-user-input-p", Fwaiting_for_user_input_p,2020,54563
+#define NETCONN_P(123,2849
+#define NETCONN_P(125,2924
+#define WCOREDUMP(151,3779
+#define WCOREDUMP(162,3975
+#define WIFEXITED(146,3635
+#define WIFEXITED(186,4468
+#define WIFSIGNALED(145,3575
+#define WIFSIGNALED(183,4374
+#define WIFSTOPPED(144,3534
+#define WIFSTOPPED(180,4302
+#define WRETCODE(147,3672
+#define WRETCODE(161,3943
+#define WSTOPSIG(148,3701
+#define WSTOPSIG(177,4244
+#define WTERMSIG(149,3730
+#define WTERMSIG(174,4188
+allocate_pty 405,10185
+close_process_descs 1519,40380
+create_process 1062,27562
+create_process_1 1034,26973
+create_process_sigchld 1052,27441
+deactivate_process 1491,39644
+decode_status 339,8560
+static dummy 29,1005
+exec_sentinel 2655,72178
+get_process 607,15017
+init_process 2677,72719
+kill_buffer_processes 2389,64730
+list_processes_1 843,22195
+make_process 507,12435
+process_send_signal 2142,57820
+read_process_output 1949,52680
+remove_process 552,13638
+run_filter 1936,52289
+send_process 2042,55085
+send_process_trap 2033,54946
+sigchld_handler 2430,66243
+status_convert 320,8028
+status_message 366,9075
+status_notify 2555,69354
+syms_of_process 2698,73082
+update_status 306,7665
+wait_reading_process_input 1582,42328
+
+regex.c,531
+#define PATFETCH(140,3614
+#define PATFETCH_RAW(145,3747
+#define PATPUSH(138,3572
+#define SIGN_EXTEND_CHAR(100,2436
+#define SYNTAX(49,1571
+bcmp_translate 1537,39895
+error 1718,44565
+init_syntax_once 60,1708
+insert_jump 679,16174
+main 1630,42648
+print_buf 1679,43653
+printchar 1704,44340
+re_comp 1558,40305
+re_compile_fastmap 700,16836
+re_compile_pattern 172,4457
+re_exec 1580,40767
+re_match 1004,24329
+re_match_2 1036,25423
+re_search 881,20973
+re_search_2 903,21776
+re_set_syntax 113,2793
+store_jump 662,15726
+
+scroll.c,239
+CalcIDCosts 429,13526
+CalcIDCosts1 464,14845
+CalcLID 491,15737
+calculate_scrolling 93,3268
+do_scrolling 226,7572
+#define max(27,937
+#define min(28,979
+scroll_cost 375,11666
+scrolling_1 58,1834
+scrolling_max_lines_saved 331,10607
+
+search.c,1140
+DEFUN ("looking-at", Flooking_at,109,3300
+DEFUN ("match-beginning", Fmatch_beginning,1101,32918
+DEFUN ("match-data", Fmatch_data,1123,33789
+DEFUN ("match-end", Fmatch_end,1112,33363
+DEFUN ("re-search-backward", Fre_search_backward,929,27320
+DEFUN ("re-search-forward", Fre_search_forward,947,28255
+DEFUN ("regexp-quote", Fregexp_quote,1213,36101
+DEFUN ("replace-match", Freplace_match,963,29052
+DEFUN ("search-backward", Fsearch_backward,868,24233
+DEFUN ("search-forward", Fsearch_forward,884,25022
+DEFUN ("skip-chars-backward", Fskip_chars_backward,295,7783
+DEFUN ("skip-chars-forward", Fskip_chars_forward,282,7247
+DEFUN ("store-match-data", Fstore_match_data,1167,35011
+DEFUN ("string-match", Fstring_match,158,4394
+DEFUN ("word-search-backward", Fword_search_backward,899,25785
+DEFUN ("word-search-forward", Fword_search_forward,914,26563
+compile_pattern 71,2539
+find_next_newline 276,7129
+match_limit 1085,32541
+#define max(28,919
+#define min(29,961
+scan_buffer 199,5615
+search_buffer 453,11352
+search_command 385,9639
+signal_failure 102,3189
+skip_chars 305,8084
+syms_of_search 1269,37303
+wordify 824,23345
+
+sunfns.c,644
+#define CHECK_GFX(72,2332
+#define CtoSX(64,2109
+#define CtoSY(65,2151
+ Fsit_for_millisecs,163,5489
+ Fsleep_for_millisecs,195,6416
+ Fsun_change_cursor_icon,222,6915
+DEFUN ("sun-get-selection", Fsun_get_selection,354,10081
+ Fsun_menu_internal,436,12164
+DEFUN ("sun-set-selection", Fsun_set_selection,332,9491
+DEFUN ("sun-window-init", Fsun_window_init,113,3897
+DEFUN ("update-display", Fupdate_display,209,6666
+#define StoCX(68,2223
+#define StoCY(69,2265
+make_menu_label 415,11671
+sel_clear 287,8559
+sel_read 294,8644
+sel_write 278,8393
+sun_item_create 366,10369
+sun_menu_create 395,11179
+syms_of_sunfns(509,14367
+
+syntax.c,927
+DEFUN ("backward-prefix-chars", Fbackward_prefix_chars,762,19167
+DEFUN ("char-syntax", Fchar_syntax,138,4387
+DEFUN ("copy-syntax-table", Fcopy_syntax_table,70,1898
+DEFUN ("describe-syntax", Fdescribe_syntax,353,10079
+DEFUN ("forward-word", Fforward_word,427,11482
+DEFUN ("modify-syntax-entry", Fmodify_syntax_entry,179,6254
+DEFUN ("parse-partial-sexp", Fparse_partial_sexp,1036,26570
+DEFUN ("scan-lists", Fscan_lists,719,17600
+DEFUN ("scan-sexps", Fscan_sexps,743,18502
+DEFUN ("set-syntax-table", Fset_syntax_table,92,2560
+DEFUN ("standard-syntax-table", Fstandard_syntax_table,61,1683
+DEFUN ("syntax-table", Fsyntax_table,53,1482
+DEFUN ("syntax-table-p", Fsyntax_table_p,30,986
+char_quoted 705,17318
+check_syntax_table 42,1275
+describe_syntax 236,7597
+describe_syntax_1 343,9827
+init_syntax_once 1067,27601
+scan_lists 450,11996
+scan_sexps_forward 797,20336
+scan_words 368,10634
+syms_of_syntax 1105,28941
+
+sysdep.c,3361
+#define DESCRIPTOR(2933,69402
+#define ITEMSETUP(2946,69684
+#define OSPEED(192,4306
+#define OSPEED(226,5133
+#define OSPEED(379,8013
+#define SETOSPEED(195,4373
+#define SETOSPEED(229,5192
+#define TABS_OK(197,4454
+#define TABS_OK(231,5250
+#define TABS_OK(380,8049
+bcmp 2159,50144
+bcopy 2136,49739
+bzero 2113,49199
+child_setup_tty 591,12843
+closedir 2746,64341
+closedir 2786,65228
+cnv_uaf_pw 3819,90391
+creat_copy_attrs 3427,80318
+croak 2654,61193
+croak 4177,99004
+define_logical_name 3951,93567
+delete_logical_name 3965,93989
+discard_tty_input 383,8124
+dup2 2599,60191
+end_kbd_input 1487,35486
+end_of_data 1683,40254
+end_of_text 1667,39984
+execvp 3985,94324
+flush_pending_output 570,12263
+get_screen_size 1197,28202
+get_system_name 1714,40870
+get_uaf_name 3688,87404
+get_uaf_uic 3752,88855
+getppid 3312,77857
+getpwnam 3854,91568
+getpwuid 3896,92384
+gettimeofday 2636,60877
+getwd 2481,58040
+getwd 3296,77632
+hft_init 4211,99419
+hft_reset 4264,101090
+init_baud_rate 432,9079
+init_sigio 818,18650
+init_sigio 1559,37340
+init_sigio 1966,46575
+init_signals 2045,47745
+init_sys_modes 923,20458
+init_vms_input 1364,32731
+input_wait_timeout 1513,36043
+insque(4200,99312
+kbd_input_ast 1403,33503
+link 4110,97761
+#define min(30,1006
+opendir 2760,64656
+perror 2584,59928
+queue_kbd_input 1388,33168
+long random 2180,50620
+random 2208,51020
+random 4186,99134
+read_input_waiting 1913,45717
+readdir 2807,65595
+readdirver 2866,67495
+rename 2507,58692
+rename 3991,94391
+rename_sans_version 4048,95996
+request_sigio 833,18870
+request_sigio 855,19258
+request_sigio 872,19482
+request_sigio 1569,37421
+request_sigio 1982,46799
+reset_sigio 826,18763
+reset_sigio 1564,37379
+reset_sigio 1974,46686
+reset_sys_modes 1234,29080
+restore_signal_handlers 804,18395
+save_signal_handlers 793,18158
+select 1781,42425
+select_alarm 1767,42170
+set_exclusive_use 457,9553
+setpgrp 3982,94309
+setpgrp_of_tty 676,15540
+setpriority 1942,46245
+setpriority 2528,59066
+setpriority 3979,94290
+setup_pty 1313,30891
+sigbit 2030,47443
+sigfree 2021,47293
+sigholdx 2001,47039
+sigisheld 2008,47129
+sigunhold 2014,47200
+srandom 2185,50660
+srandom 2214,51118
+srandom 4192,99232
+start_of_data 1647,39547
+start_of_text 1604,38038
+stop_vms_input 1378,32973
+stuff_char 419,8815
+sys_abort 2270,52468
+sys_access 2958,70110
+sys_access 3071,73156
+sys_access_reinit 3065,73115
+sys_close 2349,54264
+sys_creat 3505,82531
+sys_fwrite 3621,85543
+sys_getenv 2233,51499
+sys_getuid 3329,78139
+sys_open 1956,46409
+sys_open 2334,54010
+sys_read 2364,54462
+sys_read 3335,78202
+sys_sigblock 2085,48735
+sys_signal 2056,47918
+sys_sigpause 2072,48360
+sys_sigsetmask 2101,49015
+sys_sigunblock 2093,48873
+sys_sleep 1545,37004
+sys_suspend 699,15923
+sys_translate_unix 3216,76471
+sys_translate_vms 3162,75632
+sys_write 2377,54680
+sys_write 3345,78375
+sys_write 3374,79048
+tabs_safe_p 1179,27786
+#define tcgetattr(201,4598
+ulimit 3976,94276
+unrequest_sigio 843,19026
+unrequest_sigio 862,19349
+unrequest_sigio 877,19532
+unrequest_sigio 1574,37470
+unrequest_sigio 1989,46871
+utimes 2550,59342
+utimes 2566,59577
+#define va_count(3501,82459
+vfork 2539,59179
+vlimit 3916,92825
+vms_truncate 3641,86195
+vmserrstr 2909,68896
+wait_for_kbd_input 1442,34234
+wait_for_termination 485,10127
+wait_without_blocking 468,9720
+
+term.c,1066
+#define OUTPUT(32,1047
+#define OUTPUT1(33,1105
+#define OUTPUT1_IF(36,1269
+#define OUTPUTL(34,1145
+#define OUTPUT_IF(35,1196
+background_highlight 320,9440
+calculate_costs 922,23314
+calculate_ins_del_char_costs 864,21794
+change_line_highlight 392,11518
+clear_end_of_line 520,14285
+clear_end_of_line_raw 534,14754
+clear_screen 492,13689
+clear_to_end 465,13249
+delete_chars 704,18200
+fatal 1233,33153
+highlight_if_desired 333,9674
+ins_del_lines 741,18836
+insert_chars 651,17253
+#define max(29,962
+#define min(30,1004
+move_cursor 427,12490
+output_chars 567,15474
+per_line_cost 851,21602
+raw_move_cursor 446,12882
+reassert_line_highlight 371,10893
+reset_terminal_modes 206,7179
+ring_bell 183,6783
+set_scroll_region 253,8012
+set_terminal_modes 193,6949
+set_terminal_window 239,7735
+string_cost 829,21188
+string_cost_one_line 840,21400
+term_init 972,24733
+turn_off_highlight 296,8988
+turn_off_insert 282,8583
+turn_on_highlight 306,9141
+turn_on_insert 275,8492
+update_begin 221,7488
+update_end 227,7563
+write_standout_marker 354,10376
+
+termcap.c,340
+compare_contin 523,11183
+find_capability 88,2121
+gobble_line 562,12292
+legal_filename_p 299,6278
+main 613,13398
+memory_out 47,1418
+name_match 507,10840
+scan_file 466,10051
+tgetent 326,6840
+tgetflag 110,2464
+tgetnum 100,2301
+tgetst1 149,3586
+tgetstr 123,2847
+tprint 639,13795
+tputs 231,5099
+xmalloc 54,1507
+xrealloc 64,1630
+
+terminfo.c,16
+tparam 37,1276
+
+tparam.c,63
+main 263,6694
+tgoto 68,2148
+tparam 44,1718
+tparam1 81,2354
+
+undo.c,252
+DEFUN ("primitive-undo", Fprimitive_undo,198,5716
+DEFUN ("undo-boundary", Fundo_boundary,119,3635
+record_change 100,3047
+record_delete 71,2222
+record_first_change 111,3371
+record_insert 33,1157
+syms_of_undo 283,7926
+truncate_undo_list 141,4366
+
+unexaix.c,390
+#define ADDR_CORRECT(240,8117
+#define ERROR0(256,8342
+#define ERROR1(257,8405
+#define ERROR2(258,8470
+#define PERROR(161,6104
+#define PERROR(164,6174
+adjust_lnnoptrs 716,19853
+copy_sym 636,17693
+copy_text_and_data 573,16157
+make_hdr 324,9920
+mark_x 674,18446
+report_error 246,8195
+report_error_1 261,8545
+unexec 280,8855
+unrelocate_symbols 766,20888
+write_segment 592,16523
+
+unexconvex.c,305
+#define ERROR0(212,7619
+#define ERROR1(213,7682
+#define ERROR2(214,7747
+#define PERROR(169,6622
+copy_sym 536,15868
+copy_text_and_data 475,14367
+first_pty_letter 589,16942
+make_hdr 273,9175
+mark_x 569,16512
+report_error 203,7490
+report_error_1 217,7822
+unexec 231,8036
+write_segment(486,14531
+
+unexec.c,442
+#define ADDR_CORRECT(271,9076
+#define ERROR0(287,9301
+#define ERROR1(288,9364
+#define ERROR2(289,9429
+#define N_BADMAG(249,8418
+#define N_SYMOFF(232,8038
+#define N_TXTOFF(231,8003
+#define PERROR(159,6122
+#define PERROR(162,6192
+adjust_lnnoptrs 929,26108
+copy_sym 844,23894
+copy_text_and_data 684,19319
+make_hdr 352,10805
+mark_x 886,24689
+report_error 277,9154
+report_error_1 292,9504
+unexec 311,9814
+write_segment 802,22730
+
+unexelf.c,195
+#define NEW_PROGRAM_H(345,13212
+#define NEW_SECTION_H(341,12998
+#define OLD_PROGRAM_H(343,13105
+#define OLD_SECTION_H(339,12891
+#define fatal(330,12672
+round_up 353,13392
+unexec 372,13750
+
+unexenix.c,161
+#define READ(55,2156
+#define SEEK(64,2481
+#define WRITE(60,2326
+check_exec 80,2856
+copyrec 211,6784
+fatal_unexec 249,7556
+mark_x 235,7246
+unexec 86,2899
+
+unexfx2800.c,13
+unexec 5,60
+
+unexhp9k800.c,254
+calculate_checksum(230,7324
+copy_file(245,7597
+copy_rest(264,8048
+display_header(279,8372
+#define min(48,1749
+read_header(183,5963
+#define roundup(47,1678
+save_data_space(115,3859
+unexec(53,1863
+update_file_ptrs(132,4339
+write_header(211,6712
+
+unexmips.c,123
+#define READ(48,1694
+#define SEEK(57,2023
+#define WRITE(53,1866
+fatal_unexec 303,9282
+mark_x 289,8972
+unexec 90,2895
+
+unexnext.c,204
+fatal_unexec(94,2486
+filldatagap(153,3926
+get_data_region(174,4333
+grow(61,1797
+my_free(232,5415
+my_malloc(219,5222
+read_macho(106,2669
+save_command(79,2144
+unexec(390,8538
+unexec_doit(241,5525
+
+unexshm.c,44
+map_in_data 69,2373
+map_out_data 229,7266
+
+vms-pp.c,195
+static char *buy(93,2845
+check_pp(180,5140
+static char *gather_word(106,3101
+init_table(123,3445
+main(65,2108
+process_line(157,4513
+replace_word(233,6860
+static char *skip_white(115,3288
+
+vmsfns.c,1008
+ Fdefault_subproc_input_handler,285,9542
+ Fsend_command_to_subprocess,378,11966
+DEFUN ("setprv", Fsetprv,589,16782
+DEFUN ("shrink-to-icon", Fshrink_to_icon,933,25536
+DEFUN ("spawn-subprocess", Fspawn_subprocess,296,9849
+DEFUN ("stop-subprocess", Fstop_subprocess,398,12506
+DEFUN ("vms-system-info", Fvms_system_info,645,18372
+create_mbx 528,15377
+exit_ast 418,12965
+getjpi 749,21536
+init_vmsfns 961,26585
+kill_vms_processes 506,14848
+mbx_input_ast 561,16207
+mbx_msg 370,11817
+process_command_input 431,13232
+process_exit 475,14323
+start_mbx_input 569,16316
+syms_of_vmsfns 967,26647
+translate_id 691,20145
+vms_account 770,22107
+vms_cliname 777,22226
+vms_grp 784,22345
+vms_image 791,22456
+vms_owner 798,22574
+vms_parent 805,22689
+vms_pid 812,22810
+vms_prcnam 819,22921
+vms_proclist 912,25075
+vms_symbol 890,24522
+vms_terminal 826,23038
+vms_trnlog 870,23949
+vms_uic_int 833,23159
+vms_uic_str 840,23274
+vms_username 847,23389
+vms_version_fn 854,23510
+write_to_mbx 580,16585
+
+vmsmap.c,63
+mapin_data 79,2656
+mapout_data 143,4312
+write_data 210,6017
+
+window.c,2739
+#define CURBEG(1204,31880
+#define CURSIZE(1207,31953
+ Fcurrent_window_configuration,1796,48848
+DEFUN ("delete-other-windows", Fdelete_other_windows,662,17588
+DEFUN ("delete-window", Fdelete_window,340,9849
+DEFUN ("delete-windows-on", Fdelete_windows_on,672,17834
+DEFUN ("display-buffer", Fdisplay_buffer,944,25148
+DEFUN ("enlarge-window", Fenlarge_window,1162,30827
+DEFUN ("get-buffer-window", Fget_buffer_window,651,17278
+DEFUN ("get-largest-window", Fget_largest_window,644,17116
+DEFUN ("get-lru-window", Fget_lru_window,631,16738
+DEFUN ("minibuffer-window", Fminibuffer_window,124,3497
+DEFUN ("move-to-window-line", Fmove_to_window_line,1563,41664
+DEFUN ("next-window", Fnext_window,453,12643
+DEFUN ("other-window", Fother_window,527,14707
+DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p,131,3654
+DEFUN ("previous-window", Fprevious_window,491,13726
+DEFUN ("recenter", Frecenter,1518,40511
+DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows,687,18173
+DEFUN ("save-window-excursion", Fsave_window_excursion,1913,52396
+DEFUN ("scroll-down", Fscroll_down,1426,37791
+DEFUN ("scroll-left", Fscroll_left,1436,38078
+DEFUN ("scroll-other-window", Fscroll_other_window,1468,39028
+DEFUN ("scroll-right", Fscroll_right,1452,38551
+DEFUN ("scroll-up", Fscroll_up,1416,37513
+DEFUN ("select-window", Fselect_window,898,23900
+DEFUN ("selected-window", Fselected_window,117,3313
+DEFUN ("set-window-buffer", Fset_window_buffer,835,22066
+ Fset_window_configuration,1633,43717
+DEFUN ("set-window-hscroll", Fset_window_hscroll,239,6499
+DEFUN ("set-window-point", Fset_window_point,305,8700
+DEFUN ("set-window-start", Fset_window_start,320,9126
+DEFUN ("shrink-window", Fshrink_window,1173,31157
+DEFUN ("split-window", Fsplit_window,1055,28097
+DEFUN ("window-buffer", Fwindow_buffer,202,5471
+DEFUN ("window-edges", Fwindow_edges,258,7083
+DEFUN ("window-height", Fwindow_height,210,5668
+DEFUN ("window-hscroll", Fwindow_hscroll,231,6268
+DEFUN ("window-point", Fwindow_point,276,7731
+DEFUN ("window-start", Fwindow_start,297,8472
+DEFUN ("window-width", Fwindow_width,218,5884
+DEFUN ("windowp", Fwindowp,83,2383
+#define MINSIZE(1200,31758
+#define SAVED_WINDOW_N(1629,43588
+change_window_height 1214,32158
+count_windows 1782,48451
+decode_window 192,5294
+init_window_once 1932,52978
+keys_of_window 2047,56791
+make_dummy_parent 1026,27523
+make_window 92,2568
+replace_window 420,11822
+save_window_save 1831,50203
+scroll_command 1394,37014
+set_window_height 708,18786
+set_window_width 773,20496
+syms_of_window 1963,53959
+temp_output_buffer_show 997,26817
+unshow_buffer 873,23104
+window_height 1185,31492
+window_loop 554,15161
+window_scroll 1328,35587
+window_width 1193,31628
+
+x11fns.c,1716
+DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,588,14584
+DEFUN ("x-color-p", Fx_color_p,458,11686
+DEFUN ("x-debug", Fx_debug,933,23823
+DEFUN ("x-flip-color", Fx_flip_color,170,4124
+DEFUN ("x-get-background-color", Fx_get_background_color,482,12137
+DEFUN ("x-get-border-color", Fx_get_border_color,494,12398
+DEFUN ("x-get-cursor-color", Fx_get_cursor_color,506,12643
+DEFUN ("x-get-cut-buffer", Fx_get_cut_buffer,782,19977
+DEFUN ("x-get-default", Fx_get_default,530,13136
+DEFUN ("x-get-foreground-color", Fx_get_foreground_color,470,11876
+DEFUN ("x-get-mouse-color", Fx_get_mouse_color,518,12888
+DEFUN ("x-get-mouse-event", Fx_get_mouse_event,701,17711
+DEFUN ("x-mouse-events", Fx_mouse_events,627,15749
+DEFUN ("x-proc-mouse-event", Fx_proc_mouse_event,640,15991
+DEFUN ("x-rebind-key", Fx_rebind_key,848,21445
+DEFUN ("x-rebind-keys", Fx_rebind_keys,891,22800
+DEFUN ("x-set-background-color", Fx_set_background_color,229,5708
+DEFUN ("x-set-bell", Fx_set_bell,152,3746
+DEFUN ("x-set-border-color", Fx_set_border_color,285,7404
+DEFUN ("x-set-border-width", Fx_set_border_width,800,20356
+DEFUN ("x-set-cursor-color", Fx_set_cursor_color,347,8868
+DEFUN ("x-set-font", Fx_set_font,561,13980
+DEFUN ("x-set-foreground-color", Fx_set_foreground_color,179,4291
+DEFUN ("x-set-internal-border-width", Fx_set_internal_border_width,824,20846
+DEFUN ("x-set-mouse-color", Fx_set_mouse_color,397,10265
+DEFUN ("x-store-cut-buffer", Fx_store_cut_buffer,760,19354
+XCleanUp 958,24251
+XExitWithCoreDump 927,23772
+XRedrawDisplay 953,24207
+#define abs(73,1876
+check_xterm 146,3652
+#define max(76,1994
+#define min(75,1953
+#define sgn(74,1915
+syms_of_xfns 967,24370
+x_set_cursor_colors 429,11039
+
+x11term.c,1549
+ClearCursor 826,21283
+CursorToggle 739,18572
+HLmode 282,7839
+XExitGracefully 1536,36125
+XFlipColor 2211,51321
+XIgnoreError 1542,36174
+XInitWindow 2589,60011
+XNewFont 2175,50725
+XSetFeep 2142,50046
+XSetFlash 2137,50001
+XSetWindowSize(2579,59813
+XT_CalcForFont(2153,50299
+XT_GetDefaults 1582,36860
+XT_Set_Class_Hints(2273,52698
+XT_Set_Command_Line(2293,53068
+XT_Set_Host(2306,53266
+XT_Set_Icon_Title(2364,54327
+XT_Set_Size_Hints(2397,54931
+XT_Set_Title(2324,53688
+XT_Set_WM_Hints(2542,58979
+XT_Set_Zoom_Sizes(2532,58819
+XTcalculate_costs 1008,25092
+XTchange_line_highlight 303,8277
+XTclear_end_of_line 390,10083
+XTclear_screen 480,12184
+XTdelete_chars 1030,25494
+XTfeep 719,18012
+XTflash 655,16441
+XTins_del_lines 989,24729
+XTinsert_chars 1018,25326
+XTmove_cursor 339,9065
+XToutput_chars 644,16250
+XTread_socket 1125,27700
+XTreassert_line_highlight 294,8079
+XTreset_terminal_modes 471,12064
+XTset_terminal_modes 317,8663
+XTset_terminal_window 976,24523
+XTupdate_begin 855,21809
+XTupdate_end 882,22291
+cleanup 381,9948
+dumpchars 509,12699
+dumprectangle 905,22702
+internal_socket_read(1297,30257
+#define max(137,3727
+#define min(136,3688
+scraplines 1082,26629
+#define sigblockx(142,3835
+#define sigunblockx(141,3786
+char *stringFuncVal(1143,28031
+char *stringFuncVal(1229,29272
+stufflines 1042,25725
+updateline 541,13801
+writechars 583,14831
+x_clear_end_of_line 432,11151
+x_error_handler 1687,39658
+x_init_1 2100,48963
+x_io_error_handler 1697,39898
+x_term_init 1708,40097
+xfixscreen 1549,36237
+
+xdisp.c,602
+DEFUN ("redraw-display", Fredraw_display,153,4862
+decode_mode_spec 1812,52629
+display_echo_area_contents 240,7038
+display_mode_element 1624,47432
+display_mode_line 1576,45684
+display_string 1962,56201
+display_text_line 1276,38311
+init_xdisp 2105,60043
+mark_window_display_accurate 532,15554
+#define max(42,1276
+message 181,5818
+message1 217,6606
+#define min(41,1234
+redisplay 298,8782
+redisplay_all_windows 575,16568
+redisplay_preserve_echo_area 520,15315
+redisplay_window 589,16823
+redisplay_windows 582,16674
+syms_of_xdisp 2060,58314
+try_window 834,23897
+try_window_id 889,25822
+
+xfns.c,2220
+DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,574,14138
+DEFUN ("x-change-display", Fx_change_display,1014,26570
+DEFUN ("x-color-p", Fx_color_p,414,10177
+DEFUN ("x-create-x-window", Fx_create_x_window,812,20859
+DEFUN ("x-debug", Fx_debug,1317,35883
+DEFUN ("x-flip-color", Fx_flip_color,181,4285
+DEFUN ("x-get-background-color", Fx_get_background_color,435,10629
+DEFUN ("x-get-border-color", Fx_get_border_color,445,10875
+DEFUN ("x-get-cursor-color", Fx_get_cursor_color,455,11105
+DEFUN ("x-get-cut-buffer", Fx_get_cut_buffer,773,19904
+DEFUN ("x-get-default", Fx_get_default,475,11568
+DEFUN ("x-get-foreground-color", Fx_get_foreground_color,425,10383
+DEFUN ("x-get-mouse-color", Fx_get_mouse_color,465,11335
+DEFUN ("x-get-mouse-event", Fx_get_mouse_event,680,17300
+DEFUN ("x-mouse-events", Fx_mouse_events,609,15330
+DEFUN ("x-pop-up-window", Fx_pop_up_window,154,3720
+DEFUN ("x-proc-mouse-event", Fx_proc_mouse_event,632,15828
+DEFUN ("x-rebind-key", Fx_rebind_key,1232,33261
+DEFUN ("x-rebind-keys", Fx_rebind_keys,1277,34824
+DEFUN ("x-rubber-band", Fx_rubber_band,789,20262
+DEFUN ("x-set-background-color", Fx_set_background_color,236,5690
+DEFUN ("x-set-bell", Fx_set_bell,163,3898
+DEFUN ("x-set-border-color", Fx_set_border_color,286,7020
+DEFUN ("x-set-border-width", Fx_set_border_width,850,21865
+DEFUN ("x-set-cursor-color", Fx_set_cursor_color,331,8148
+DEFUN ("x-set-font", Fx_set_font,510,12404
+DEFUN ("x-set-foreground-color", Fx_set_foreground_color,190,4455
+DEFUN ("x-set-icon", Fx_set_icon,495,12074
+DEFUN ("x-set-internal-border-width", Fx_set_internal_border_width,927,24076
+DEFUN ("x-set-keyboard-enable", Fx_set_keyboard_enable,723,18746
+DEFUN ("x-set-mouse-color", Fx_set_mouse_color,370,9074
+DEFUN ("x-set-mouse-inform-flag", Fx_set_mouse_inform_flag,745,19236
+DEFUN ("x-set-window-edges", Fx_set_window_edges,546,13331
+DEFUN ("x-store-cut-buffer", Fx_store_cut_buffer,755,19488
+XCleanUp 1339,36298
+XExitWithCoreDump 1309,35774
+XRedrawDisplay 1334,36253
+XRestoreDisplay 1009,26486
+#define abs(44,1243
+check_xterm 148,3622
+grey_p 843,21701
+#define max(47,1361
+#define min(46,1320
+#define sgn(45,1282
+syms_of_xfns 1348,36417
+window_fetch 1168,31490
+
+xmenu.c,252
+DEFUN ("x-popup-menu",Fx_popup_menu,111,2622
+#define X11ONLY(70,1906
+#define X11ONLY(73,1959
+XEmacsMenu(226,5750
+XMenuQuit 106,2572
+list_of_items 391,10841
+list_of_panes 349,9446
+#define max(79,2054
+#define min(78,2011
+syms_of_xmenu 344,9396
+
+xterm.c,1307
+ClearCursor 710,16429
+CursorToggle 639,14490
+HLmode 204,5103
+XBitmapIcon 1204,27908
+XExitGracefully 1239,28545
+XFlipColor 1738,42180
+XNewFont 1712,41557
+XPopUpWindow 1841,44583
+XSetFeep 1707,41513
+XSetFlash 1702,41467
+XSetOffset 1800,43680
+XSetWindowSize 1828,44198
+XTchange_line_highlight 225,5515
+XTclear_end_of_line 325,7563
+XTclear_screen 417,9354
+XTdelete_chars 884,20666
+XTextIcon 1218,28150
+XTfeep 619,13963
+XTflash 566,12737
+XTins_del_lines 861,20277
+XTinsert_chars 873,20476
+XTmove_cursor 270,6508
+XToutput_chars 549,12386
+XTread_socket 1006,23618
+XTreassert_line_highlight 215,5309
+XTreset_terminal_modes 408,9226
+XTset_terminal_modes 243,5994
+XTset_terminal_window 849,20061
+XTupdate_begin 739,17053
+XTupdate_end 764,17506
+cleanup 315,7415
+dumpchars 448,9882
+dumpqueue 1680,40990
+dumprectangle 784,17912
+fixxrepbuffer 1926,46580
+flashback 598,13463
+loadxrepbuffer 1901,46003
+#define max(96,2471
+#define min(95,2432
+refreshicon 1191,27646
+scraplines 951,22247
+#define sigblockx(98,2548
+#define sigunblockx(97,2510
+spacecheck 1878,45472
+stufflines 895,20887
+unloadxrepbuffer 1912,46255
+writechars 482,11047
+x_clear_end_of_line 368,8457
+x_init_1 1647,40252
+x_io_error 1247,28653
+x_io_error 1258,28854
+x_term_init 1330,31030
+xfixscreen 1276,29294
+
+../lisp/abbrev.el,733
+(defun abbrev-mode 22,819
+(defun abbrev-prefix-mark 239,8271
+(defun add-abbrev 186,6466
+(defun add-global-abbrev 177,6092
+(defun add-mode-abbrev 163,5621
+(defun define-abbrevs 108,3577
+(defun edit-abbrevs 87,2791
+(defvar edit-abbrevs-map 33,1207
+(defun edit-abbrevs-mode 79,2557
+(defun edit-abbrevs-redefine 102,3417
+(defun expand-region-abbrevs 251,8704
+(defun insert-abbrevs 49,1708
+(defun inverse-add-abbrev 222,7695
+(defun inverse-add-global-abbrev 214,7370
+(defun inverse-add-mode-abbrev 201,6955
+(defun kill-all-abbrevs 41,1480
+(defun list-abbrevs 61,2038
+(defun prepare-abbrev-list-buffer 66,2170
+(defun quietly-read-abbrev-file 141,4831
+(defun read-abbrev-file 132,4458
+(defun write-abbrev-file 147,5064
+
+../lisp/abbrevlist.el,37
+(defun list-one-abbrev-table 24,896
+
+../lisp/ada.el,1517
+(defun ada-array 202,7408
+(defun ada-backward-to-same-indent 188,6898
+(defun ada-bind 614,19336
+(defvar ada-bind-opts 588,18322
+(defun ada-case 215,7757
+(defun ada-compile 599,18744
+(defun ada-declare-block 229,8089
+(defun ada-display-comment 579,18065
+(defun ada-else 287,9438
+(defun ada-elsif 360,11650
+(defun ada-exception 279,9267
+(defun ada-exception-block 253,8678
+(defun ada-exit 295,9591
+(defun ada-find-listing 608,19110
+(defun ada-for-loop 317,10405
+(defun ada-forward-to-same-indent 195,7147
+(defun ada-function-spec 442,13936
+(defun ada-get-arg-list 424,13305
+(defun ada-go-to-this-indent 175,6414
+(defun ada-header 340,11057
+(defun ada-if 349,11399
+(defvar ada-indent 85,3224
+(defun ada-inline-comment 570,17720
+(defvar ada-lib-dir-name 587,18248
+(defun ada-library-name 590,18383
+(defun ada-loop 369,11879
+(defun ada-mode 87,3306
+(defvar ada-mode-map 39,1374
+(defvar ada-mode-syntax-table 9,315
+(defun ada-newline 158,5979
+(defun ada-options-for-bind 595,18580
+(defun ada-package-body 402,12747
+(defun ada-package-spec 390,12427
+(defun ada-paired-parens 564,17572
+(defun ada-private 416,13134
+(defun ada-procedure-spec 451,14202
+(defun ada-record 516,16263
+(defun ada-separate 494,15701
+(defun ada-subprogram-body 478,15256
+(defun ada-subtype 526,16456
+(defun ada-tab 165,6148
+(defun ada-tabsize 153,5814
+(defun ada-type 533,16694
+(defun ada-untab 170,6284
+(defun ada-when 308,10130
+(defun ada-while-loop 543,17036
+(defun get-ada-subprogram-name 458,14415
+
+../lisp/add-log.el,86
+(defun add-change-log-entry 21,823
+(defun add-change-log-entry-other-window 84,3060
+
+../lisp/autoinsert.el,115
+(defvar auto-insert-alist 51,1915
+(defvar auto-insert-directory 62,2416
+(defun insert-auto-insert-files 65,2516
+
+../lisp/backquote.el,950
+(defmacro ` 93,3619
+(defconst backquote-splice 88,3487
+(defconst backquote-unquote 84,3381
+(defmacro bq-caar 69,2968
+(defmacro bq-cadr 72,3020
+(defmacro bq-cdar 75,3072
+(defun bq-evalappend 282,10705
+(defun bq-evalcons 248,9733
+(defconst bq-evalfns 182,7565
+(defun bq-evallist 273,10420
+(defun bq-evalnil 293,11028
+(defun bq-evalquote 259,10104
+(defun bq-id 130,5275
+(defun bq-iterative-list-builder 157,6589
+(defun bq-make-list 134,5343
+(defun bq-make-maker 111,4624
+(defmacro bq-push 64,2827
+(defun bq-quoteappend 234,9323
+(defun bq-quotecar 132,5296
+(defun bq-quotecons 209,8580
+(defconst bq-quotefns 188,7726
+(defun bq-quotelist 228,9143
+(defun bq-quotenil 242,9576
+(defun bq-quotequote 222,8934
+(defconst bq-singles 125,5156
+(defun bq-spliceappend 314,11619
+(defun bq-splicecons 300,11255
+(defconst bq-splicefns 176,7412
+(defun bq-splicelist 310,11512
+(defun bq-splicenil 317,11678
+(defun bq-splicequote 306,11396
+
+../lisp/bg-mouse.el,963
+(defconst bg-button-c 36,1366
+(defconst bg-button-l 37,1391
+(defconst bg-button-m 35,1341
+(defconst bg-button-r 34,1316
+(defun bg-command-execute 270,9339
+(defun bg-get-tty-num 214,7338
+(defconst bg-in-minibuf 40,1474
+(defconst bg-in-modeline 38,1416
+(defconst bg-in-scrollbar 39,1444
+(defun bg-insert-moused-sexp 180,6248
+(defun bg-kill-region 176,6153
+(defconst bg-most-positive-fixnum 139,4955
+(defvar bg-mouse-fast-select-window 29,1057
+(defun bg-mouse-line-to-bottom 171,5977
+(defun bg-mouse-line-to-center 165,5775
+(defun bg-mouse-line-to-top 160,5622
+(defun bg-mouse-report 47,1598
+(defun bg-move-by-percentage 141,4999
+(defun bg-move-point-to-x-y 233,7973
+(defun bg-program-mouse 275,9455
+(defun bg-set-mark 112,4233
+(defun bg-set-point 105,3991
+(defun bg-window-from-x-y 250,8730
+(defun bg-yank 119,4406
+(defun bg-yank-or-pop 130,4643
+(defun bind-bg-mouse-click 285,9806
+(defconst semicolon 43,1558
+(defun yank-pop-1 126,4585
+
+../lisp/bibtex.el,1235
+(define-abbrev-table 'bibtex-mode-abbrev-table 29,1312
+(defun bibtex-Article 188,7000
+(defun bibtex-Book 193,7153
+(defun bibtex-Booklet 199,7329
+(defun bibtex-InBook 210,7683
+(defun bibtex-InCollection 216,7881
+(defun bibtex-InProceedings 223,8077
+(defun bibtex-Manual 229,8278
+(defun bibtex-MastersThesis 235,8434
+(defun bibtex-Misc 240,8582
+(defun bibtex-PhdThesis 245,8709
+(defun bibtex-Proceedings 250,8849
+(defun bibtex-TechReport 255,9016
+(defun bibtex-Unpublished 261,9180
+(defun bibtex-entry 170,6483
+(defun bibtex-find-it 279,9575
+(defun bibtex-make-entry 180,6821
+(defun bibtex-make-opt-entry 184,6906
+(defun bibtex-mode 32,1413
+(defvar bibtex-mode-abbrev-table 28,1271
+(defvar bibtex-mode-map 30,1363
+(defvar bibtex-mode-syntax-table 27,1230
+(defun bibtex-move-outside-of-entry 157,6201
+(defun bibtex-next-position 273,9451
+(defun bibtex-remove-double-quotes 307,10183
+(defun bibtex-remove-opt 292,9866
+(defun bibtex-string 266,9305
+(defmenu bibtex-sun-entry-menu 372,12175
+(defun bibtex-sun-environment 422,14135
+(defmenu bibtex-sun-menu401,13356
+(defun bibtex-sun-menu-eval 418,13996
+(defun bibtex-x-environment 361,11748
+(defun bibtex-x-help 328,10588
+(defun kill-current-line 301,10071
+
+../lisp/blackbox.el,655
+(defun bb-bol 108,2552
+(defun bb-delete 222,5638
+(defun bb-done 176,4200
+(defun bb-down 96,2365
+(defun bb-eol 103,2472
+(defun bb-goto 208,5214
+(defun bb-init-board 55,1501
+(defun bb-insert-board 66,1781
+(defun bb-left 82,2143
+(defun bb-member 218,5457
+(defun bb-outside-box 205,5143
+(defun bb-place-ball 124,2853
+(defun bb-right 75,2032
+(defun bb-romp 113,2633
+(defun bb-show-bogus-balls 190,4712
+(defun bb-show-bogus-balls-2 194,4860
+(defun bb-trace-ray 134,3149
+(defun bb-trace-ray-2 162,3772
+(defun bb-up 89,2255
+(defun bb-update-board 211,5291
+(defun blackbox 39,1090
+(defun blackbox-mode 25,741
+(defvar blackbox-mode-map 6,100
+
+../lisp/buff-menu.el,679
+(defun Buffer-menu-1-window 248,8566
+(defun Buffer-menu-2-window 265,9097
+(defun Buffer-menu-backup-unmark 136,5269
+(defun Buffer-menu-buffer 83,3559
+(defvar Buffer-menu-buffer-column 81,3521
+(defun Buffer-menu-delete 143,5459
+(defun Buffer-menu-delete-backwards 154,5761
+(defun Buffer-menu-execute 188,6695
+(defun Buffer-menu-mark 111,4528
+(defun Buffer-menu-mode 51,2298
+(defvar Buffer-menu-mode-map 24,976
+(defun Buffer-menu-not-modified 174,6327
+(defun Buffer-menu-other-window 260,8911
+(defun Buffer-menu-save 162,6010
+(defun Buffer-menu-select 220,7668
+(defun Buffer-menu-this-window 255,8769
+(defun Buffer-menu-unmark 122,4818
+(defun buffer-menu 99,4096
+
+../lisp/bytecomp.el,5359
+(defun batch-byte-compile 1125,39486
+(defun batch-byte-compile-file 1155,40851
+(defconst byte-add1 145,5058
+(defconst byte-aref 133,4739
+(defconst byte-aset 134,4763
+(defconst byte-bobp 172,5850
+(defconst byte-bolp 171,5825
+(defconst byte-call 46,1761
+(defconst byte-car 125,4543
+(defconst byte-catch 94,3365
+(defconst byte-cdr 126,4566
+(defconst byte-char-after 163,5556
+(defun byte-compile 302,10555
+(defun byte-compile-and 990,34808
+(defun byte-compile-body 890,31132
+(defun byte-compile-catch 1033,36198
+(defun byte-compile-concat 721,25207
+(defun byte-compile-cond 951,33337
+(defun byte-compile-cond-1 956,33460
+(defun byte-compile-condition-case 1057,37267
+(defun byte-compile-constant 486,17388
+(defvar byte-compile-constants 24,946
+(defvar byte-compile-constnum 22,858
+(defvar byte-compile-depth 35,1408
+(defun byte-compile-discard 924,32240
+(defun byte-compile-file 203,7080
+(defun byte-compile-file-form 271,9505
+(defun byte-compile-find-vars 372,13206
+(defun byte-compile-find-vars-1 381,13521
+(defun byte-compile-form 439,15652
+(defun byte-compile-function-form 775,26949
+(defun byte-compile-goto 1083,38131
+(defun byte-compile-if 929,32403
+(defun byte-compile-indent-to 783,27231
+(defun byte-compile-insert 793,27548
+(defun byte-compile-interactive-p 700,24559
+(defun byte-compile-lambda 308,10805
+(defun byte-compile-let 830,28795
+(defun byte-compile-let* 848,29511
+(defun byte-compile-list 704,24691
+(defvar byte-compile-macro-environment 27,1074
+(defun byte-compile-make-tag 1073,37879
+(defvar byte-compile-maxdepth 37,1476
+(defun byte-compile-maybe-two-args 764,26551
+(defun byte-compile-minus 742,25844
+(defun byte-compile-no-args 656,22764
+(defun byte-compile-noop 887,31068
+(defun byte-compile-normal-call 469,16627
+(defun byte-compile-one-arg 664,23072
+(defun byte-compile-or 1006,35297
+(defun byte-compile-out 1098,38624
+(defun byte-compile-out-1 1117,39249
+(defun byte-compile-out-const 1110,38992
+(defun byte-compile-out-tag 1076,37930
+(defvar byte-compile-output 32,1285
+(defvar byte-compile-pc 30,1208
+(defun byte-compile-prog1 902,31504
+(defun byte-compile-prog2 915,31994
+(defun byte-compile-progn 883,30948
+(defun byte-compile-push-constant 501,18036
+(defun byte-compile-quote 810,28126
+(defun byte-compile-save-excursion 863,30132
+(defun byte-compile-save-restriction 869,30358
+(defun byte-compile-save-window-excursion 1040,36526
+(defun byte-compile-setq 814,28249
+(defun byte-compile-setq-default 805,27933
+(defun byte-compile-store-goto 1090,38384
+(defun byte-compile-substring 689,24116
+(defun byte-compile-three-args 679,23692
+(defun byte-compile-top-level 328,11463
+(defun byte-compile-two-args 671,23362
+(defun byte-compile-unwind-protect 1047,36837
+(defun byte-compile-variable-ref 476,16932
+(defun byte-compile-while 1020,35734
+(defun byte-compile-with-output-to-temp-buffer 875,30608
+(defconst byte-concat2 141,4953
+(defconst byte-concat3 142,4980
+(defconst byte-concat4 143,5007
+(defconst byte-condition-case 101,3645
+(defconst byte-cons 127,4589
+(defconst byte-consp 119,4397
+(defconst byte-constant 51,1910
+(defconst byte-constant-limit 53,1989
+(defconst byte-constant2 56,2076
+(defconst byte-current-buffer 173,5875
+(defconst byte-current-column 166,5657
+(defconst byte-diff 151,5201
+(defconst byte-discard 79,2838
+(defconst byte-dup 82,2921
+(defconst byte-eobp 170,5800
+(defconst byte-eolp 169,5775
+(defconst byte-eq 122,4474
+(defconst byte-eqlsign 146,5082
+(defconst byte-following-char 164,5587
+(defconst byte-fset 138,4877
+(defconst byte-geq 150,5178
+(defconst byte-get 139,4901
+(defconst byte-goto 59,2183
+(defconst byte-goto-char 159,5441
+(defconst byte-goto-if-nil 62,2253
+(defconst byte-goto-if-nil-else-pop 68,2441
+(defconst byte-goto-if-not-nil 65,2343
+(defconst byte-goto-if-not-nil-else-pop 72,2583
+(defconst byte-gtr 147,5109
+(defconst byte-indent-to 167,5692
+(defconst byte-insert 160,5470
+(defconst byte-interactive-p 177,6017
+(defconst byte-length 132,4713
+(defconst byte-leq 149,5155
+(defconst byte-list1 128,4613
+(defconst byte-list2 129,4638
+(defconst byte-list3 130,4663
+(defconst byte-list4 131,4688
+(defconst byte-listp 121,4449
+(defconst byte-lss 148,5132
+(defconst byte-max 154,5275
+(defconst byte-memq 123,4496
+(defconst byte-min 155,5298
+(defconst byte-negate 152,5225
+(defconst byte-not 124,4520
+(defconst byte-nth 117,4347
+(defconst byte-plus 153,5251
+(defconst byte-point 157,5322
+(defconst byte-point-max 161,5496
+(defconst byte-point-min 162,5526
+(defconst byte-preceding-char 165,5622
+(defconst byte-read-char 175,5941
+(defun byte-recompile-directory 179,6053
+(defconst byte-return 76,2733
+(defconst byte-save-excursion 85,3002
+(defconst byte-save-restriction 91,3236
+(defconst byte-save-window-excursion 88,3115
+(defconst byte-set 137,4854
+(defconst byte-set-buffer 174,5910
+(defconst byte-stringp 120,4422
+(defconst byte-sub1 144,5034
+(defconst byte-substring 140,4924
+(defconst byte-symbol-function 136,4819
+(defconst byte-symbol-value 135,4787
+(defconst byte-symbolp 118,4370
+(defconst byte-temp-output-buffer-setup 105,3813
+(defconst byte-temp-output-buffer-show 111,4068
+(defconst byte-unbind 48,1830
+(defconst byte-unwind-protect 97,3482
+(defconst byte-varbind 44,1689
+(defconst byte-varref 40,1548
+(defconst byte-varset 42,1618
+
+../lisp/c-fill.el,397
+(defun c-comment 85,3179
+(defvar c-comment-hanging-indent 61,2357
+(defvar c-comment-indenting 59,2250
+(defvar c-comment-mode-map 71,2693
+(defvar c-comment-starting-blank 57,2148
+(defvar c-hang-already-done 63,2460
+(defun do-indented-auto-fill 185,6285
+(defun get-current-fill 214,7166
+(defun replace-letter 261,8555
+(defun set-fill-and-fill 162,5678
+(defun set-fill-and-return 173,5960
+
+../lisp/c-mode.el,1057
+(define-abbrev-table 'c-mode-abbrev-table 23,903
+(defconst c-argdecl-indent 69,2759
+(defconst c-auto-newline 79,3218
+(defun c-backward-to-noncomment 493,18265
+(defun c-backward-to-start-of-continued-exp 510,18739
+(defun c-backward-to-start-of-if 518,18949
+(defconst c-brace-imaginary-offset 65,2537
+(defconst c-brace-offset 67,2654
+(defun c-comment-indent 165,6650
+(defconst c-continued-brace-offset 75,3061
+(defconst c-continued-statement-offset 73,2962
+(defun c-indent-command 258,9404
+(defconst c-indent-level 63,2442
+(defun c-indent-line 292,10595
+(defun c-inside-parens-p 248,9124
+(defconst c-label-offset 71,2853
+(defun c-mode 87,3548
+(defvar c-mode-abbrev-table 21,827
+(defvar c-mode-map 25,950
+(defvar c-mode-syntax-table 44,1661
+(defconst c-tab-always-indent 83,3368
+(defun calculate-c-indent 338,12127
+(defun calculate-c-indent-within-comment 475,17693
+(defun electric-c-brace 173,6930
+(defun electric-c-semi 201,7685
+(defun electric-c-terminator 208,7898
+(defun indent-c-exp 543,19653
+(defun mark-c-function 534,19446
+
+../lisp/cal.el,272
+(defun calendar 52,2476
+(defvar calendar-hook 39,1804
+(defun day-number 142,6178
+(defun day-of-week 158,6787
+(defun generate-month 176,7337
+(defun insert-indented 213,9143
+(defun leap-year-p 135,5992
+(defvar offset-calendar-hook 46,2202
+(defun star-date 233,9768
+
+../lisp/chistory.el,428
+(defun Command-history-setup 111,4360
+(defvar command-history-hook 121,4778
+(defvar command-history-map 124,4884
+(defun command-history-mode 134,5236
+(defun default-command-history-filter 72,2970
+(defvar default-command-history-filter-garbage56,2163
+(defun list-command-history 82,3390
+(defvar list-command-history-filter 65,2570
+(defvar list-command-history-max 78,3207
+(defun repeat-matching-complex-command 29,1116
+
+../lisp/cl-indent.el,373
+(defun common-lisp-indent-hook 58,2045
+(defun lisp-indent-259 185,8343
+(defun lisp-indent-do 310,13781
+(defun lisp-indent-function-lambda-hack 323,14269
+(defvar lisp-indent-maximum-backtracking 38,1149
+(defun lisp-indent-report-bad-format 178,8081
+(defun lisp-indent-tagbody 284,12694
+(defvar lisp-tag-body-indentation 47,1526
+(defvar lisp-tag-indentation 43,1379
+
+../lisp/cl.el,6308
+(defvar *gensym-index* 327,12195
+(defvar *gensym-prefix* 330,12271
+(defvar *gentemp-index* 302,11259
+(defvar *gentemp-prefix* 305,11337
+(defvar *mvalues-count* 1249,44919
+(defvar *mvalues-values* 1247,44846
+(defkeyword :conc-name 2064,71894
+(defkeyword :copier 2065,71952
+(defkeyword :count 1056,36946
+(defkeyword :end 1051,36591
+(defkeyword :end1 1054,36797
+(defkeyword :end2 1055,36871
+(defkeyword :from-end 1057,37002
+(defkeyword :include 2062,71778
+(defkeyword :initial-offset 2069,72184
+(defkeyword :key 1048,36392
+(defkeyword :named 2063,71836
+(defkeyword :predicate 1049,36459
+(defkeyword :predicate 2066,72010
+(defkeyword :print-function 2067,72068
+(defkeyword :setf-update-doc1642,58940
+(defkeyword :setf-update-fn1637,58745
+(defkeyword :start 1050,36533
+(defkeyword :start1 1052,36650
+(defkeyword :start2 1053,36723
+(defkeyword :structure-doc 2071,72243
+(defkeyword :structure-indices 2074,72443
+(defkeyword :structure-initforms 2075,72510
+(defkeyword :structure-slots 2073,72382
+(defkeyword :structure-slotsn 2072,72317
+(defkeyword :test 1046,36248
+(defkeyword :test-not 1047,36320
+(defkeyword :type 2068,72126
+(defun abs 1399,51138
+(defun acons 1018,35229
+(defun add-to-klist 1173,41930
+(defun adjoin 864,31344
+(defsetf apply1740,63162
+(defsetf aref1760,63898
+(defun build$accessors$for 2367,85476
+(defun build-klist 188,7009
+(defun butlast 847,30750
+(defun caaaar 933,32996
+(defsetf caaaar1872,66401
+(defun caaadr 937,33102
+(defsetf caaadr1876,66501
+(defun caaar 901,32291
+(defsetf caaar1840,65624
+(defun caadar 941,33208
+(defsetf caadar1880,66601
+(defun caaddr 953,33526
+(defsetf caaddr1892,66900
+(defun caadr 905,32379
+(defsetf caadr1844,65721
+(defun caar 885,32011
+(defsetf caar1824,65246
+(defun cadaar 945,33314
+(defsetf cadaar1884,66701
+(defun cadadr 957,33632
+(defsetf cadadr1896,67001
+(defun cadar 909,32467
+(defsetf cadar1848,65818
+(defun caddar 965,33844
+(defsetf caddar1904,67201
+(defun cadddr 977,34162
+(defsetf cadddr1916,67501
+(defun caddr 917,32643
+(defsetf caddr1856,66013
+(defun cadr 889,32081
+(defsetf cadr1828,65342
+(defsetf car 1820,65146
+(defmacro case 382,14095
+(defun case-clausify 424,15683
+(defun cdaaar 949,33420
+(defsetf cdaaar1888,66801
+(defun cdaadr 961,33738
+(defsetf cdaadr1900,67101
+(defun cdaar 913,32555
+(defsetf cdaar1852,65916
+(defun cdadar 969,33950
+(defsetf cdadar1908,67301
+(defun cdaddr 985,34375
+(defsetf cdaddr1924,67701
+(defun cdadr 921,32731
+(defsetf cdadr1860,66110
+(defun cdar 893,32151
+(defsetf cdar1832,65436
+(defun cddaar 973,34056
+(defsetf cddaar1912,67401
+(defun cddadr 981,34269
+(defsetf cddadr1920,67601
+(defun cddar 925,32819
+(defsetf cddar1864,66207
+(defun cdddar 989,34481
+(defsetf cdddar1928,67801
+(defun cddddr 993,34587
+(defsetf cddddr1932,67901
+(defun cdddr 929,32907
+(defsetf cdddr1868,66304
+(defun cddr 897,32221
+(defsetf cddr1836,65530
+(defsetf cdr 1822,65196
+(defun ceiling 1524,55144
+(defun check-do-endforms 567,21640
+(defun check-do-stepforms 543,20864
+(defmacro decf 1964,68624
+(defmacro defkeyword 267,10294
+(defmacro defsetf 1705,61367
+(defmacro defstruct 2078,72583
+(defmacro do 489,18223
+(defmacro do* 515,19528
+(defmacro do-all-symbols 720,27142
+(defmacro do-symbols 688,25921
+(defmacro dolist 627,23568
+(defmacro dotimes 656,24657
+(defun duplicate-symbols-p 230,9048
+(defmacro ecase 401,14828
+(defun eighth 785,28904
+(defsetf eighth1804,64780
+(defsetf elt1772,64072
+(defun elt-satisfies-if-not-p 1202,43119
+(defun elt-satisfies-if-p 1194,42764
+(defun elt-satisfies-test-p 1178,42091
+(defun elts-match-under-klist-p 1211,43560
+(defun endp 801,29191
+(defun evenp 1395,51054
+(defun every 1078,37958
+(defun extract$indices 2356,85034
+(defun extract-do*-steps 599,22637
+(defun extract-do-inits 576,21887
+(defun extract-do-steps 592,22367
+(defun extract-from-klist 1167,41661
+(defun fifth 773,28666
+(defsetf fifth1792,64499
+(defun first 757,28377
+(defsetf first1776,64127
+(defun floor 1502,54490
+(defun fourth 769,28586
+(defsetf fourth1788,64405
+(defun gcd 1417,51513
+(defun gensym 333,12369
+(defun gentemp 308,11437
+(defsetf get1937,68002
+(defmacro incf 1958,68435
+(defun isqrt 1473,53523
+(defun keyword-of 286,10815
+(defun keywordp 276,10587
+(defun last 808,29384
+(defun lcm 1451,52816
+(defun ldiff 874,31639
+(defun list* 853,30985
+(defun list-length 816,29650
+(defmacro loop 728,27383
+(defun make$structure$instance 2418,87881
+(defun member 835,30409
+(defun minusp 1387,50879
+(defun mod 1593,57256
+(defmacro multiple-value-bind 1312,47676
+(defmacro multiple-value-call 1298,47021
+(defmacro multiple-value-list 1283,46335
+(defmacro multiple-value-prog1 1341,49136
+(defmacro multiple-value-setq 1328,48456
+(defun mv-bind-clausify 1357,49876
+(defun ninth 789,28984
+(defsetf ninth1808,64874
+(defun notany 1097,38859
+(defun notevery 1116,39753
+(defsetf nth1764,63953
+(defsetf nthcdr1768,64008
+(defun oddp 1391,50966
+(defun pair-with-newsyms 126,4612
+(defun pairlis 1023,35385
+(defun parse$defstruct$args 2172,77130
+(defun parse$defstruct$options 2232,79717
+(defun plusp 1383,50790
+(defmacro pop 1978,69099
+(defun process$slots 2205,78606
+(defmacro psetf 1993,69619
+(defmacro psetq 58,2410
+(defmacro push 1970,68813
+(defmacro pushnew 1974,68952
+(defun reassemble-argslists 170,6323
+(defun rem 1599,57486
+(defun rest 797,29140
+(defsetf rest1816,65058
+(defmacro rotatef 2032,70910
+(defun round 1568,56436
+(defun safe-idiv 1612,58021
+(defun second 761,28428
+(defsetf second1780,64219
+(defun select-stepping-forms 606,22909
+(defun setelt 1139,40704
+(defmacro setf 1646,59104
+(defun setnth 999,34759
+(defun setnthcdr 1003,34874
+(defun seventh 781,28822
+(defsetf seventh1800,64683
+(defmacro shiftf 2014,70281
+(defun signum 1407,51313
+(defun simplify$inits 2345,84617
+(defun sixth 777,28744
+(defsetf sixth1796,64591
+(defun some 1059,37057
+(defsetf symbol-function1941,68063
+(defsetf symbol-plist1945,68150
+(defsetf symbol-value1949,68239
+(defun tenth 793,29062
+(defsetf tenth1812,64966
+(defun third 765,28508
+(defsetf third1784,64313
+(defun truncate 1546,55795
+(defmacro unless 373,13726
+(defun unzip-list 154,5711
+(defun values 1259,45411
+(defun values-list 1270,45844
+(defmacro when 369,13574
+(defun zip-lists 138,5093
+
+../lisp/cmacexp.el,27
+(defun c-macro-expand 2,1
+
+../lisp/compare-w.el,31
+(defun compare-windows 21,821
+
+../lisp/compile.el,560
+(defvar compilation-error-list 27,1061
+(defvar compilation-error-message 40,1624
+(defvar compilation-error-regexp45,1838
+(defun compilation-forget-errors 206,7871
+(defun compilation-grab-filename 304,11580
+(defun compilation-parse-errors 216,8253
+(defvar compilation-parsing-end 37,1523
+(defvar compilation-process 22,871
+(defun compilation-sentinel 118,4694
+(defun compile 49,2025
+(defun compile1 67,2851
+(define-key ctl-x-map 318,12015
+(defun grep 59,2514
+(defun kill-compilation 152,5861
+(defun kill-grep 158,6033
+(defun next-error 164,6195
+
+../lisp/dabbrev.el,396
+(defun dabbrev-expand 75,2920
+(defvar dabbrevs-backward-only 47,1925
+(defvar dabbrevs-limit 43,1771
+(defun dabbrevs-search 192,7617
+(defvar last-dabbrevs-abbrev-location 63,2468
+(defvar last-dabbrevs-abbreviation 55,2183
+(defvar last-dabbrevs-direction 59,2331
+(defvar last-dabbrevs-expansion 67,2618
+(defvar last-dabbrevs-expansion-location 71,2759
+(defvar last-dabbrevs-table 51,2054
+
+../lisp/dbx.el,303
+(defvar dbx-break-point29,994
+(defun dbx-filter 118,4548
+(defvar dbx-process 26,927
+(defun dbx-stop-at 157,5917
+(defvar dbx-trace-flag 23,876
+(defun dbx-trace-mode 104,4060
+(defun dbx-where 134,5032
+(defun inferior-dbx-mode 41,1431
+(defvar inferior-dbx-mode-map 33,1138
+(defun run-dbx 92,3540
+
+../lisp/debug.el,498
+(defun cancel-debug-on-entry 238,8039
+(defun debug 23,852
+(defun debug-on-entry 224,7424
+(defun debug-on-entry-1 248,8414
+(defun debugger-continue 107,3577
+(defun debugger-eval-expression 181,5849
+(defun debugger-frame 155,5046
+(defun debugger-frame-clear 168,5444
+(defun debugger-frame-number 123,4076
+(defconst debugger-frame-offset 153,5007
+(defun debugger-mode 209,6900
+(defvar debugger-mode-map 190,6116
+(defun debugger-return-value 113,3732
+(defun debugger-step-through 99,3280
+
+../lisp/dired.el,1421
+(defun dired 67,2283
+(defun dired-add-entry 456,16503
+(defun dired-backup-unflag 235,8733
+(defun dired-byte-recompile 536,19305
+(defun dired-chgrp 554,19851
+(defun dired-chmod 546,19614
+(defun dired-chown 562,20092
+(defun dired-clean-directory 343,12274
+(defun dired-collect-file-versions 375,13734
+(defun dired-compress 478,17372
+(defun dired-copy-file 448,16233
+(defun dired-do-deletions 579,20684
+(defun dired-find-buffer 53,1919
+(defun dired-find-file 252,9174
+(defun dired-find-file-other-window 264,9556
+(defun dired-flag-auto-save-files 324,11705
+(defun dired-flag-backup-and-auto-save-files 425,15408
+(defun dired-flag-backup-files 405,14848
+(defun dired-flag-file-deleted 209,7975
+(defun dired-flag-this-line-for-DEATH 400,14750
+(defun dired-get-filename 269,9723
+(defun dired-map-dired-file-lines 308,11163
+(defun dired-mode 147,5657
+(defvar dired-mode-map 109,3890
+(defun dired-move-to-filename 294,10698
+(defun dired-next-line 240,8874
+(defun dired-noselect 84,3034
+(defun dired-other-window 78,2745
+(defun dired-previous-line 246,9021
+(defun dired-readin 30,1157
+(defun dired-redisplay 572,20423
+(defun dired-rename-file 433,15669
+(defun dired-repeat-over-lines 190,7457
+(defun dired-revert 98,3547
+(defun dired-summary 219,8248
+(defun dired-trample-file-versions 389,14283
+(defun dired-uncompress 507,18331
+(defun dired-unflag 225,8469
+(defun dired-view-file 257,9315
+
+../lisp/disass.el,331
+(defconst byte-code-vector251,8414
+(defun disassemble 36,1212
+(defun disassemble-1 108,3697
+(defvar disassemble-column-1-indent 24,899
+(defvar disassemble-column-2-indent 26,943
+(defun disassemble-internal 51,1902
+(defun disassemble-offset 209,7146
+(defvar disassemble-recursive-indent 28,987
+(defun write-spaces 241,8125
+
+../lisp/dissociate.el,33
+(defun dissociated-press 21,816
+
+../lisp/doctex.el,106
+(defun LaTeXify-DOC 27,898
+(defvar LaTeXify-DOC-style 19,580
+(defvar LaTeXify-DOC-style-options 24,790
+
+../lisp/doctor.el,3047
+(defmacro $ 38,1258
+(defun // 36,1240
+(defun doctor 836,27617
+(defun doctor-$ 42,1349
+(defun doctor-adjectivep 1176,38255
+(defun doctor-adverbp 1184,38437
+(defun doctor-alcohol 1485,47335
+(defun doctor-articlep 1187,38527
+(defun doctor-assm 1405,44824
+(defun doctor-build 1383,44233
+(defun doctor-caddr 22,866
+(defun doctor-cadr 21,828
+(defun doctor-cddr 23,911
+(defun doctor-chat 1614,50946
+(defun doctor-colorp 1200,38927
+(defun doctor-concat 1399,44656
+(defun doctor-conj 1445,46040
+(defun doctor-correct-spelling 943,30935
+(defun doctor-death 1582,50104
+(defun doctor-def 991,32220
+(defun doctor-define 969,31633
+(defun doctor-defq 979,31858
+(defun doctor-desire 1487,47385
+(defun doctor-desire1 1418,45259
+(defun doctor-doc 878,28728
+(defun doctor-drug 1503,47949
+(defun doctor-eliza 1598,50513
+(defun doctor-family 1587,50208
+(defun doctor-fear 1516,48278
+(defun doctor-fix-2 1268,40548
+(defun doctor-fixup 1240,40153
+(defun doctor-forget 996,32333
+(defun doctor-foul 1584,50156
+(defun doctor-getnoun 1147,37490
+(defun doctor-go 1414,45125
+(defun doctor-hate 1521,48429
+(defun doctor-hates 1532,48790
+(defun doctor-hates1 1536,48863
+(defun doctor-howdy 1430,45573
+(defun doctor-huh 1421,45314
+(defun doctor-love 1546,49091
+(defun doctor-loves 1539,48939
+(defun doctor-mach 1571,49834
+(defun doctor-make-string 1393,44513
+(defun doctor-math 1606,50744
+(defun doctor-meaning 561,18001
+(defun doctor-member 25,950
+(defun doctor-mode 57,1768
+(defvar doctor-mode-map 50,1552
+(defun doctor-modifierp 1171,38139
+(defun doctor-mood 1513,48187
+(defun doctor-nmbrp 1190,38579
+(defun doctor-nounp 1038,33581
+(defun doctor-othermodifierp 1213,39262
+(defun doctor-plural 1122,36694
+(defun doctor-possess 1344,43040
+(defun doctor-possessivepronounp 1210,39183
+(defun doctor-prepp 1223,39675
+(defun doctor-pronounp 1046,33789
+(defmacro doctor-put-meaning 563,18053
+(defun doctor-qloves 1543,49012
+(defun doctor-query 1000,32458
+(defun doctor-read-print 850,28009
+(defun doctor-read-token 868,28447
+(defun doctor-readin 860,28220
+(defun doctor-remem 1427,45477
+(defun doctor-remember 1231,39927
+(defun doctor-replace 1306,41781
+(defun doctor-ret-or-read 842,27762
+(defun doctor-rms 1592,50321
+(defun doctor-rthing 1425,45427
+(defun doctor-school 1596,50458
+(defun doctor-setprep 1134,37081
+(defun doctor-sexnoun 1575,49923
+(defun doctor-sexverb 1577,49967
+(defun doctor-short 1457,46398
+(defun doctor-shorten 952,31213
+(defun doctor-sizep 1206,39080
+(defun doctor-sports 1604,50689
+(defun doctor-state 1510,48094
+(defun doctor-subjsearch 1024,33062
+(defun doctor-svo 1327,42356
+(defun doctor-symptoms 1528,48665
+(defun doctor-toke 1507,48043
+(defun doctor-txtype 1359,43488
+(defun doctor-type 1236,40066
+(defun doctor-type-symbol 1365,43676
+(defun doctor-verbp 1119,36603
+(defun doctor-vowelp 1303,41725
+(defun doctor-when 1438,45837
+(defun doctor-wherego 1317,42087
+(defun doctor-zippy 1608,50794
+(defun make-doctor-variables 74,2358
+(defun random-range 31,1093
+
+../lisp/ebuff-menu.el,405
+(defun Electric-buffer-menu-exit 194,7330
+(defun Electric-buffer-menu-mode 108,3618
+(defun Electric-buffer-menu-mode-view-buffer 231,8694
+(defun Electric-buffer-menu-quit 211,7879
+(defun Electric-buffer-menu-select 203,7568
+(defun Electric-buffer-menu-undefined 217,8100
+(defun electric-buffer-list 31,1112
+(defun electric-buffer-menu-looper 92,3123
+(defvar electric-buffer-menu-mode-map 30,1069
+
+../lisp/echistory.el,265
+(defun Electric-command-history-redo-expression 25,925
+(defun Electric-history-quit 144,6389
+(defun Electric-history-undefined 138,6232
+(defun electric-command-history 78,3650
+(defvar electric-command-history-hook 75,3540
+(defvar electric-history-map 37,1416
+
+../lisp/edt-doc.el,0
+
+../lisp/edt.el,3012
+(defvar GOLD-map 318,11380
+(define-key GOLD-map 329,11801
+(define-key GOLD-map 330,11875
+(define-key GOLD-map 331,11941
+(define-key GOLD-map 332,12010
+(define-key GOLD-map 333,12076
+(define-key GOLD-map 334,12123
+(define-key GOLD-map 335,12185
+(define-key GOLD-map 336,12247
+(define-key GOLD-map 337,12309
+(define-key GOLD-map 340,12408
+(define-key GOLD-map 341,12470
+(define-key GOLD-map 342,12532
+(define-key GOLD-map 343,12594
+(define-key GOLD-map 344,12656
+(define-key GOLD-map 345,12718
+(define-key GOLD-map 346,12780
+(define-key GOLD-map 347,12842
+(define-key GOLD-map 348,12904
+(define-key GOLD-map 349,12966
+(define-key GOLD-map 350,13028
+(define-key GOLD-map 351,13080
+(define-key GOLD-map 352,13132
+(define-key GOLD-map 353,13202
+(define-key GOLD-map 354,13272
+(define-key GOLD-map 355,13342
+(define-key GOLD-map 356,13412
+(define-key GOLD-map 357,13482
+(define-key GOLD-map 358,13552
+(define-key GOLD-map 359,13622
+(define-key GOLD-map 360,13692
+(define-key GOLD-map 361,13762
+(define-key GOLD-map 362,13832
+(define-key GOLD-map 363,13902
+(defun advance-direction 192,6190
+(defun backup-direction 205,6772
+(defun backward-line 131,4349
+(defun backward-to-word 125,4196
+(defun beginning-of-window 218,7363
+(defun case-flip-character 233,7709
+(defun define-keypad-key 322,11542
+(defun delete-current-char 75,2597
+(defun delete-current-line 30,1186
+(defun delete-current-word 55,1971
+(defun delete-previous-char 83,2919
+(defun delete-previous-word 65,2281
+(defun delete-to-eol 43,1613
+(defun edt-bind-gold-keypad 368,14124
+(defun edt-emulation-off 287,9868
+(defun edt-emulation-on 266,8705
+(defvar edt-last-deleted-chars 27,1082
+(defvar edt-last-deleted-lines 23,886
+(defvar edt-last-deleted-words 25,984
+(defun forward-to-word 119,4030
+(define-key function-keymap 298,10404
+(define-key function-keymap 299,10463
+(define-key function-keymap 300,10520
+(define-key function-keymap 301,10582
+(define-key function-keymap 302,10642
+(define-key function-keymap 303,10702
+(define-key function-keymap 304,10757
+(define-key function-keymap 305,10818
+(define-key function-keymap 306,10889
+(define-key function-keymap 307,10943
+(define-key function-keymap 308,10995
+(define-key function-keymap 309,11046
+(define-key function-keymap 310,11092
+(define-key function-keymap 311,11146
+(define-key function-keymap 312,11197
+(define-key function-keymap 313,11256
+(defun goto-percent 180,5772
+(defun indent-or-fill-region 244,8055
+(defun line-to-bottom-of-window 223,7471
+(defun line-to-top-of-window 228,7592
+(defun mark-section-wisely 251,8298
+(defun move-to-beginning 170,5504
+(defun move-to-end 175,5644
+(defun next-end-of-line 106,3658
+(defun next-paragraph 149,4921
+(defun previous-end-of-line 113,3868
+(defun previous-paragraph 160,5219
+(defun scroll-window-down 137,4505
+(defun scroll-window-up 143,4716
+(defun undelete-chars 101,3513
+(defun undelete-lines 91,3243
+(defun undelete-words 96,3378
+(defun update-mode-line 187,6033
+
+../lisp/ehelp.el,704
+(defvar ehelp-map 322,10982
+(defun electric-command-apropos 311,10817
+(defun electric-describe-bindings 303,10631
+(defun electric-describe-function 295,10441
+(defun electric-describe-key 278,10104
+(defun electric-describe-mode 282,10189
+(defun electric-describe-syntax 307,10726
+(defun electric-describe-variable 299,10536
+(defun electric-help-command-loop 126,4677
+(defun electric-help-exit 174,6369
+(defun electric-help-help 213,7467
+(defvar electric-help-map 22,816
+(defun electric-help-mode 47,1745
+(defun electric-help-retain 179,6445
+(defun electric-help-undefined 203,7130
+(defun electric-helpify 226,8011
+(defun electric-view-lossage 286,10276
+(defun with-electric-help 59,2180
+
+../lisp/electric.el,129
+(defun Electric-command-loop 68,2919
+(defun Electric-pop-up-window 146,5454
+(defun shrink-window-if-larger-than-buffer 25,987
+
+../lisp/emacsbug.el,64
+(defvar bug-gnu-emacs 27,1114
+(defun report-emacs-bug 30,1235
+
+../lisp/files.el,3044
+(defun after-find-file 288,11077
+(defun append-to-file 843,32331
+(defconst auto-save-default 101,4188
+(defun auto-save-file-name-p 991,38049
+(defun auto-save-mode 949,36441
+(defconst auto-save-visited-file-name 104,4289
+(defconst automount-dir-prefix 239,9208
+(defun backup-buffer 524,20000
+(defconst backup-by-copying 49,2061
+(defconst backup-by-copying-when-linked 53,2206
+(defconst backup-by-copying-when-mismatch 58,2467
+(defun backup-extract-version 641,24676
+(defun backup-file-name-p 598,22867
+(defun basic-save-buffer 695,27105
+(defconst buffer-offer-save 66,2907
+(defun cd 155,6329
+(defun create-file-buffer 230,8811
+(defvar ctl-x-4-map 1074,41322
+(define-key ctl-x-4-map 1078,41471
+(define-key ctl-x-4-map 1079,41524
+(define-key ctl-x-4-map 1080,41580
+(define-key ctl-x-map 1062,40819
+(define-key ctl-x-map 1063,40860
+(define-key ctl-x-map 1064,40908
+(define-key ctl-x-map 1065,40959
+(define-key ctl-x-map 1066,41010
+(define-key ctl-x-map 1067,41053
+(define-key ctl-x-map 1068,41099
+(define-key ctl-x-map 1069,41141
+(define-key ctl-x-map 1071,41220
+(define-key ctl-x-map 1072,41266
+(define-key ctl-x-map 1077,41428
+(defun delete-auto-save-file-if-necessary 684,26680
+(defconst delete-auto-save-files 21,840
+(defvar dired-kept-versions 82,3507
+(define-key esc-map 1070,41181
+(defun file-name-sans-versions 582,22241
+(defun file-nlinks 647,24861
+(defconst file-precious-flag 72,3133
+(defun find-alternate-file 204,7934
+(defun find-backup-file-name 606,23255
+(defun find-file 183,7199
+(defvar find-file-hooks 122,4991
+(defun find-file-noselect 242,9318
+(defvar find-file-not-found-hooks 115,4704
+(defun find-file-other-window 190,7415
+(defun find-file-read-only 197,7696
+(defconst find-file-run-dired 112,4595
+(defun hack-local-variables 393,15025
+(defconst ignore-local-eval 138,5706
+(defconst inhibit-local-variables 132,5395
+(defun insert-file 836,32078
+(defvar kept-new-versions 92,3829
+(defvar kept-old-versions 89,3724
+(defun kill-some-buffers 932,35960
+(defun list-directory 1002,38507
+(defconst list-directory-brief-switches 997,38273
+(defconst list-directory-verbose-switches 999,38388
+(defun load-file 166,6693
+(defun load-library 171,6830
+(defun make-auto-save-file-name 978,37580
+(defun make-backup-file-name 593,22685
+(defconst make-backup-files 31,1223
+(defun normal-mode 325,12391
+(defun not-modified 823,31669
+(defun pwd 150,6208
+(defun recover-file 907,34881
+(defun rename-auto-save-file 966,37073
+(defconst require-final-newline 96,3972
+(defun revert-buffer 854,32768
+(defvar revert-buffer-function 851,32662
+(defconst save-abbrevs 108,4464
+(defun save-buffer 651,24982
+(defun save-buffers-kill-emacs 1037,39844
+(defun save-some-buffers 786,30473
+(defun set-auto-mode 346,13285
+(defun set-visited-file-name 471,17971
+(defun switch-to-buffer-other-window 177,6995
+(defun toggle-read-only 829,31844
+(defvar trim-versions-without-asking 85,3597
+(defvar version-control 76,3285
+(defun write-file 515,19701
+(defvar write-file-hooks 127,5190
+
+../lisp/fill.el,265
+(defun fill-individual-paragraphs 226,8031
+(defconst fill-individual-varying-indent 20,816
+(defun fill-paragraph 137,5196
+(defun fill-region 148,5491
+(defun fill-region-as-paragraph 41,1666
+(defun justify-current-line 165,6014
+(defun set-fill-prefix 27,1186
+
+../lisp/flame.el,1236
+(define-element "adjective")232,8560
+(define-element "der-term")233,8589
+(define-element "group-adj")234,8617
+(define-element "paper")237,8700
+(define-element "person")238,8725
+(define-element "quality")231,8533
+(define-element "reason")239,8751
+(define-element "sentence")230,8505
+(define-element "statement")235,8646
+(define-element "thing")236,8675
+(defun *flame 241,8778
+(defvar adjective63,2391
+(defvar adjective-loop 73,2751
+(defun append-suffixes-hack 286,9811
+(defmacro define-element 221,8145
+(defvar der-term75,2804
+(defvar der-term-loop 86,3238
+(defun flame 254,9048
+(defun flame-expand 244,8827
+(defun flame1 269,9432
+(defun flame2 264,9320
+(defun flatten 249,8943
+(defvar group-adj106,3834
+(defvar group-adj-loop 118,4268
+(defvar paper192,7237
+(defvar paper-loop 197,7377
+(defvar person200,7419
+(defvar person-loop 208,7708
+(defun psychoanalyze-flamer 296,10116
+(defvar quality53,2090
+(defvar quality-loop 61,2344
+(defvar reason210,7752
+(defvar reason-loop 219,8101
+(defvar sentence15,468
+(defun sentence-ify 274,9594
+(defvar sentence-loop 50,2039
+(defvar statement120,4321
+(defvar statement-loop 189,7183
+(defun string-ify 279,9716
+(defvar thing89,3289
+(defvar thing-loop 103,3792
+
+../lisp/float.el,1097
+(defun abs 137,4704
+(defconst decimal-digits 58,2189
+(defconst exp-base 52,2007
+(defconst expt-digits 61,2272
+(defun extract-match 149,5074
+(defun f 285,9456
+(defun f% 224,7665
+(defun f* 186,6260
+(defun f+ 169,5718
+(defun f- 180,6070
+(defun f/ 204,6949
+(defun f/= 263,8836
+(defun f< 253,8582
+(defun f<= 258,8703
+(defun f= 230,7827
+(defun f> 234,7933
+(defun f>= 248,8435
+(defun fabs 140,4776
+(defun fashl 120,4084
+(defun fashr 123,4191
+(defun fint 315,10445
+(defun float-to-string 326,10893
+(defconst floating-point-regexp81,2949
+(defun floatp 280,9277
+(defun fmax 272,9061
+(defun fmin 268,8960
+(defun ftrunc 301,9918
+(defun fzerop 276,9168
+(defconst high-bit-mask 93,3276
+(defun hihalf 160,5505
+(defun int-to-hex-string 289,9577
+(defun lohalf 163,5608
+(defconst mantissa-bits 55,2090
+(defconst mantissa-half-minval 79,2892
+(defconst mantissa-maxval 68,2445
+(defconst mantissa-minval 73,2653
+(defconst maxbit 65,2381
+(defun normalize 126,4300
+(defun same-sign 146,4963
+(defconst second-bit-mask 96,3370
+(defun string-to-float 395,13149
+(defun xor 143,4886
+
+../lisp/fortran.el,1828
+(defun beginning-of-fortran-subprogram 404,17561
+(defun calculate-fortran-indent 497,20893
+(defvar comment-line-start 42,1581
+(defvar comment-line-start-skip 45,1670
+(defun delete-horizontal-regexp 379,16624
+(defun end-of-fortran-subprogram 413,17894
+(defun fortran-abbrev-help 344,15381
+(defun fortran-abbrev-start 333,14934
+(defvar fortran-check-all-num-for-matching-do 62,2312
+(defun fortran-check-for-matching-do 633,26583
+(defvar fortran-column-ruler78,2955
+(defun fortran-column-ruler 352,15650
+(defun fortran-comment-hook 265,12392
+(defvar fortran-comment-indent-char 54,2041
+(defvar fortran-comment-indent-style 34,1267
+(defvar fortran-comment-line-column 39,1497
+(defvar fortran-comment-region 69,2596
+(defun fortran-comment-region 307,13872
+(defvar fortran-continuation-char 65,2443
+(defvar fortran-continuation-indent 31,1171
+(defun fortran-current-line-indentation 554,23336
+(defvar fortran-do-indent 25,1017
+(defvar fortran-electric-line-number 72,2720
+(defun fortran-electric-line-number 387,16950
+(defvar fortran-if-indent 28,1094
+(defun fortran-indent-comment 271,12526
+(defun fortran-indent-line 470,19920
+(defun fortran-indent-subprogram 488,20602
+(defun fortran-indent-to-column 577,24178
+(defvar fortran-line-number-indent 58,2163
+(defun fortran-line-number-indented-correctly-p 622,26167
+(defvar fortran-minimum-statement-indent 48,1763
+(defun fortran-mode 182,8873
+(defvar fortran-mode-abbrev-table 132,5671
+(defvar fortran-mode-map 102,4023
+(defvar fortran-mode-syntax-table 85,3263
+(defconst fortran-mode-version 83,3223
+(defun fortran-next-statement 455,19350
+(defun fortran-previous-statement 430,18422
+(defun fortran-split-line 370,16286
+(defvar fortran-startup-message 75,2844
+(defun fortran-window-create 361,16030
+(defun mark-fortran-subprogram 422,18194
+
+../lisp/ftp.el,683
+(defun ftp-asynchronous-input-sentinel 254,9378
+(defun ftp-asynchronous-output-sentinel 258,9553
+(defun ftp-command 224,8532
+(defun ftp-find-file 73,2534
+(defun ftp-find-file-or-directory 99,3888
+(defun ftp-list-directory 86,3202
+(defun ftp-login 210,8064
+(defvar ftp-password-alist 24,945
+(defun ftp-read-file-name 65,2252
+(defun ftp-revert-buffer 360,13031
+(defun ftp-sentinel 263,9735
+(defun ftp-setup-buffer 188,7339
+(defun ftp-setup-write-file-hooks 330,11996
+(defun ftp-synchronous-input-sentinel 256,9465
+(defun ftp-synchronous-output-sentinel 260,9643
+(defun ftp-write-file 140,5407
+(defun ftp-write-file-hook 343,12474
+(defun read-ftp-user-password 26,994
+
+../lisp/gdb.el,960
+(def-gdb "cont" 95,3384
+(def-gdb "down" 99,3579
+(def-gdb "finish" 97,3435
+(def-gdb "next" 94,3318
+(def-gdb "step" 92,3194
+(def-gdb "stepi" 93,3256
+(def-gdb "up" 98,3501
+(define-key ctl-x-map 74,2665
+(define-key ctl-x-map 75,2703
+(defvar current-gdb-buffer 148,5321
+(defmacro def-gdb 80,2846
+(defun gdb 153,5419
+(defun gdb-break 343,12204
+(defun gdb-call 324,11616
+(defvar gdb-command-name 150,5354
+(defvar gdb-commands 371,13110
+(defun gdb-display-frame 290,10347
+(defun gdb-display-line 305,11034
+(defun gdb-filter 182,6680
+(defun gdb-filter-accumulate-marker 189,6896
+(defun gdb-filter-insert 222,8022
+(defun gdb-filter-scan-input 212,7674
+(defun gdb-maybe-delete-prompt 333,11898
+(defun gdb-mode 101,3661
+(defvar gdb-mode-map 66,2488
+(defvar gdb-prompt-pattern 63,2387
+(defun gdb-read-address(353,12521
+(defun gdb-refresh 284,10205
+(defun gdb-sentinel 248,8945
+(defun gdb-set-buffer 172,6273
+(defun send-gdb-command 375,13228
+
+../lisp/gosmacs.el,331
+(defun gosmacs-next-window 83,2876
+(defun gosmacs-previous-window 77,2640
+(defun line-to-top-of-window 99,3442
+(defvar non-gosmacs-binding-alist 21,812
+(defun rebind-and-record 57,1919
+(defun scroll-one-line-down 94,3273
+(defun scroll-one-line-up 89,3105
+(defun set-gnu-bindings 72,2468
+(defun set-gosmacs-bindings 23,852
+
+../lisp/grow-vers.el,0
+
+../lisp/hanoi.el,138
+(defun hanoi 18,277
+(defun hanoi-draw-ring 182,5170
+(defun hanoi-move-ring 128,3404
+(defun hanoi-topos 10,135
+(defun hanoi0 115,3111
+
+../lisp/help.el,1215
+(defun command-apropos 287,9775
+(defun describe-copying 134,4611
+(defun describe-distribution 128,4423
+(defun describe-function 230,8095
+(defun describe-key 105,3715
+(defun describe-key-briefly 82,2667
+(defun describe-mode 119,4176
+(defun describe-no-warranty 141,4819
+(defun describe-variable 260,8933
+(defun function-called-at-point 218,7766
+(define-key global-map 24,901
+(defun help-for-help 167,5569
+(defvar help-map 21,811
+(define-key help-map 27,977
+(define-key help-map 28,1021
+(define-key help-map 30,1063
+(define-key help-map 31,1110
+(define-key help-map 32,1162
+(define-key help-map 33,1213
+(define-key help-map 35,1257
+(define-key help-map 37,1303
+(define-key help-map 38,1351
+(define-key help-map 40,1392
+(define-key help-map 41,1437
+(define-key help-map 43,1483
+(define-key help-map 45,1516
+(define-key help-map 47,1557
+(define-key help-map 49,1599
+(define-key help-map 50,1645
+(define-key help-map 52,1689
+(define-key help-map 54,1733
+(define-key help-map 56,1780
+(define-key help-map 58,1817
+(defun help-with-tutorial 60,1863
+(defun print-help-return-message 92,3073
+(defun variable-at-point 251,8718
+(defun view-emacs-news 149,5035
+(defun view-lossage 154,5189
+
+../lisp/helper.el,416
+(defun Helper-describe-bindings 124,4302
+(defun Helper-describe-function 101,3602
+(defun Helper-describe-key 95,3433
+(defun Helper-describe-key-briefly 89,3267
+(defun Helper-describe-mode 113,3992
+(defun Helper-describe-variable 107,3797
+(defun Helper-help 131,4512
+(defvar Helper-help-map 37,1411
+(defun Helper-help-options 82,3037
+(defun Helper-help-scroller 52,2090
+(defvar Helper-return-blurb 29,1150
+
+../lisp/hideif.el,2773
+(defun backward-ifdef 597,19309
+(defun define-hide-ifdef-mode-map 132,5204
+(defun down-ifdef 618,19823
+(defun forward-ifdef 578,18824
+(defun hide-ifdef-block 960,30028
+(defun hide-ifdef-define 886,27909
+(defvar hide-ifdef-define-alist 1004,31202
+(defvar hide-ifdef-env 301,10754
+(defvar hide-ifdef-evaluator 294,10534
+(defun hide-ifdef-guts 831,26311
+(defvar hide-ifdef-hiding 168,6700
+(defvar hide-ifdef-hiding 849,26772
+(defvar hide-ifdef-initially 845,26650
+(defvar hide-ifdef-lines 858,27060
+(defvar hide-ifdef-mode 165,6623
+(defun hide-ifdef-mode 182,7081
+(defvar hide-ifdef-mode-map 122,4898
+(defvar hide-ifdef-mode-map-before 128,5064
+(defconst hide-ifdef-mode-prefix-key 125,4969
+(defvar hide-ifdef-read-only 852,26841
+(defun hide-ifdef-region 279,10145
+(defun hide-ifdef-set-define-alist 1020,31646
+(defun hide-ifdef-toggle-outside-read-only 872,27515
+(defun hide-ifdef-toggle-read-only 861,27165
+(defun hide-ifdef-undef 892,28091
+(defun hide-ifdef-use-define-alist 1028,31908
+(defun hide-ifdefs 899,28283
+(defun hif-canonicalize 488,16075
+(defun hif-compress-define-list 1007,31292
+(defconst hif-cpp-prefix 333,11452
+(defun hif-defined 317,11132
+(defconst hif-else-regexp 336,11641
+(defconst hif-end-of-comment 352,12258
+(defconst hif-endif-regexp 337,11699
+(defun hif-endif-to-ifdef 560,18292
+(defun hif-expr 424,14466
+(defun hif-factor 444,14943
+(defun hif-find-any-ifX 504,16572
+(defun hif-find-ifdef-block 936,29426
+(defun hif-find-next-relevant 513,16816
+(defun hif-find-previous-relevant 523,17192
+(defun hif-find-range 703,22149
+(defun hif-hide-line 745,23496
+(defun hif-ifdef-to-endif 544,17811
+(defconst hif-ifndef-regexp 334,11506
+(defconst hif-ifx-else-endif-regexp338,11759
+(defconst hif-ifx-regexp 335,11568
+(defun hif-infix-to-prefix 342,11869
+(defun hif-looking-at-else 539,17746
+(defun hif-looking-at-endif 537,17682
+(defun hif-looking-at-ifX 535,17592
+(defun hif-lookup 310,10979
+(defun hif-make-range 688,21651
+(defun hif-nexttoken 417,14288
+(defun hif-outline-flag-region 262,9582
+(defvar hif-outside-read-only 855,26950
+(defun hif-parse-if-exp 408,14049
+(defun hif-possibly-hide 795,25083
+(defun hif-range-else 693,21834
+(defun hif-range-else-p 691,21740
+(defun hif-range-end 694,21879
+(defun hif-range-start 692,21788
+(defun hif-recurse-on 785,24824
+(defun hif-set-var 305,10834
+(defun hif-show-all 274,10000
+(defun hif-show-ifdef-region 285,10354
+(defun hif-term 434,14702
+(defconst hif-token-regexp 351,12195
+(defun hif-tokenize 355,12297
+(defvar hif-undefined-symbol 298,10674
+(defun hif-update-mode-line 160,6484
+(defun next-ifdef 643,20430
+(defun previous-ifdef 659,20846
+(defun show-ifdef-block 981,30609
+(defun show-ifdefs 924,29067
+(defun up-ifdef 630,20099
+
+../lisp/icon.el,1058
+(define-abbrev-table 'icon-mode-abbrev-table 29,1140
+(defun beginning-of-icon-defun 410,15161
+(defun calculate-icon-indent 262,9882
+(defun electric-icon-brace 157,6491
+(defun end-of-icon-defun 417,15393
+(defconst icon-auto-newline 79,3363
+(defun icon-backward-to-noncomment 360,13755
+(defun icon-backward-to-start-of-continued-exp 371,14050
+(defun icon-backward-to-start-of-if 386,14434
+(defconst icon-brace-imaginary-offset 69,2867
+(defconst icon-brace-offset 71,2990
+(defun icon-comment-indent 149,6211
+(defconst icon-continued-brace-offset 75,3200
+(defconst icon-continued-statement-offset 73,3098
+(defun icon-indent-command 187,7277
+(defconst icon-indent-level 67,2766
+(defun icon-indent-line 221,8492
+(defun icon-is-continuation-line 349,13366
+(defun icon-is-continued-line 381,14328
+(defun icon-mode 87,3702
+(defvar icon-mode-abbrev-table 27,1058
+(defvar icon-mode-map 31,1190
+(defvar icon-mode-syntax-table 45,1780
+(defconst icon-tab-always-indent 83,3516
+(defun indent-icon-exp 424,15591
+(defun mark-icon-function 401,14938
+
+../lisp/inc-vers.el,0
+
+../lisp/indent.el,660
+(define-key ctl-x-map 224,7292
+(defun edit-tab-stops 163,5342
+(defvar edit-tab-stops-buffer 159,5201
+(defvar edit-tab-stops-map 152,4906
+(defun edit-tab-stops-note-changes 195,6355
+(define-key esc-map 223,7249
+(define-key esc-map 225,7336
+(define-key global-map 222,7196
+(defun indent-according-to-mode 26,928
+(defun indent-for-tab-command 31,1068
+(defun indent-region 81,2575
+(defvar indent-region-function 77,2426
+(defun indent-relative 117,3633
+(defun indent-relative-maybe 112,3510
+(defun indent-rigidly 45,1456
+(defun indent-to-left-margin 64,2113
+(defun insert-tab 38,1283
+(defvar tab-stop-list148,4772
+(defun tab-to-tab-stop 209,6757
+
+../lisp/info.el,1509
+(defun Info-cease-edit 692,23474
+(defvar Info-current-file 36,1344
+(defvar Info-current-node 43,1578
+(defvar Info-current-subfile 39,1427
+(defvar Info-directory 33,1263
+(defun Info-directory 387,13202
+(defun Info-edit 676,22909
+(defvar Info-edit-map 662,22498
+(defun Info-edit-mode 669,22711
+(defvar Info-enable-active-nodes 29,1105
+(defvar Info-enable-edit 26,995
+(defun Info-exit 545,18308
+(defun Info-extract-menu-counting 511,17315
+(defun Info-extract-menu-item 499,16925
+(defun Info-extract-menu-node-name 432,14821
+(defun Info-extract-pointer 336,11629
+(defun Info-fifth-menu-item 540,18166
+(defun Info-find-node 60,2188
+(defun Info-first-menu-item 520,17594
+(defun Info-follow-reference 392,13312
+(defun Info-following-node-name 346,11945
+(defun Info-fourth-menu-item 535,18022
+(defun Info-goto-node 251,8660
+(defun Info-help 556,18581
+(defvar Info-history 22,865
+(defun Info-last 373,12714
+(defvar Info-last-search 268,9445
+(defun Info-menu 452,15381
+(defun Info-menu-item-sequence 447,15267
+(defun Info-mode 616,20783
+(defvar Info-mode-map 581,19287
+(defun Info-next 358,12317
+(defun Info-prev 363,12442
+(defun Info-read-subfile 176,6471
+(defun Info-search 271,9529
+(defun Info-second-menu-item 525,17736
+(defun Info-select-node 210,7534
+(defun Info-set-mode-line 238,8329
+(defun Info-summary 564,18747
+(defvar Info-tag-table-marker 46,1664
+(defun Info-third-menu-item 530,17880
+(defun Info-undefined 551,18490
+(defun Info-up 368,12589
+(defun info 50,1825
+
+../lisp/informat.el,206
+(defun Info-split 75,2501
+(defun Info-tagify 22,838
+(defun Info-validate 142,4887
+(defun Info-validate-node-name 284,9366
+(defun Info-validate-tags-table 307,9912
+(defun batch-info-validate 344,11005
+
+../lisp/isearch.el,198
+(defun isearch 60,2599
+(defun isearch-message 273,10134
+(defun isearch-pop 298,11019
+(defun isearch-push-state 311,11349
+(defun isearch-search 317,11520
+(defun nonincremental-search 353,12761
+
+../lisp/kermit.el,452
+(defun kermit-clean-filter 153,7343
+(defun kermit-clean-off 180,8317
+(defun kermit-clean-on 172,8021
+(defun kermit-default-cr 137,6640
+(defun kermit-default-nl 145,6978
+(defun kermit-esc 87,4907
+(defvar kermit-esc-char 85,4849
+(defun kermit-send-char 94,5137
+(define-key shell-mode-map 101,5340
+(define-key shell-mode-map 102,5388
+(define-key shell-mode-map 104,5507
+(define-key shell-mode-map 135,6585
+(defun shell-send-input-cr 106,5557
+
+../lisp/keypad.el,109
+(defun function-key-sequence 146,5526
+(defun keypad-default 88,3099
+(defun setup-terminal-keymap 125,4412
+
+../lisp/ledit.el,520
+(defconst ledit-buffer 33,1276
+(defconst ledit-compile-file 30,1149
+(defun ledit-from-lisp-mode 134,4505
+(defun ledit-go-to-lisp 77,2589
+(defun ledit-go-to-liszt 91,3008
+(defun ledit-mode 118,3921
+(defvar ledit-mode-map 24,897
+(defconst ledit-read-file 28,1037
+(defun ledit-save-defun 43,1718
+(defun ledit-save-region 53,1991
+(defun ledit-setup 106,3475
+(defun ledit-zap-defun-to-lisp 59,2174
+(defun ledit-zap-defun-to-liszt 65,2304
+(defconst ledit-zap-file 26,926
+(defun ledit-zap-region-to-lisp 71,2437
+
+../lisp/life.el,550
+(defun abs 96,4052
+(defun life 98,4090
+(defun life-compute-neighbor-deltas 170,6364
+(defconst life-current-generation 92,3924
+(defun life-display-generation 264,9845
+(defun life-expand-plane-if-needed 222,8300
+(defun life-extinct-quit 269,9959
+(defconst life-generation-string 94,4013
+(defun life-grim-reaper 186,6863
+(defun life-increment-generation 182,6715
+(defun life-insert-random-pattern 177,6575
+(defconst life-neighbor-deltas 85,3704
+(defconst life-patterns23,883
+(defun life-setup 119,4697
+(defconst life-window-start 89,3873
+
+../lisp/lisp-mode.el,995
+(define-abbrev-table 'lisp-mode-abbrev-table 60,2628
+(defun calculate-lisp-indent 276,9893
+(defun emacs-lisp-mode 104,4264
+(defvar emacs-lisp-mode-map 97,4044
+(defvar emacs-lisp-mode-syntax-table 22,863
+(defun eval-defun 212,7795
+(defun eval-last-sexp 197,7386
+(defun eval-print-last-sexp 183,7024
+(defun indent-code-rigidly 547,21067
+(defun indent-sexp 477,18413
+(defconst lisp-body-indent 402,15098
+(defun lisp-comment-indent 224,8135
+(defun lisp-indent-defform 449,17432
+(defconst lisp-indent-hook 235,8454
+(defun lisp-indent-hook 368,13737
+(defun lisp-indent-line 237,8504
+(defconst lisp-indent-offset 234,8417
+(defun lisp-indent-specform 404,15132
+(defun lisp-interaction-mode 163,6245
+(defvar lisp-interaction-mode-map 155,5933
+(defun lisp-mode 129,5080
+(defvar lisp-mode-abbrev-table 23,908
+(defun lisp-mode-commands 92,3869
+(defvar lisp-mode-map 121,4841
+(defvar lisp-mode-syntax-table 21,824
+(defun lisp-mode-variables 62,2678
+(defun lisp-send-defun 150,5779
+
+../lisp/lisp.el,528
+(defun backward-kill-sexp 93,3101
+(defun backward-list 51,1688
+(defun backward-sexp 29,1092
+(defun backward-up-list 68,2252
+(defun beginning-of-defun 99,3306
+(defun buffer-end 108,3642
+(defun down-list 58,1896
+(defun end-of-defun 111,3709
+(defun forward-list 44,1444
+(defun forward-sexp 21,819
+(defun insert-parentheses 158,4920
+(defun kill-sexp 85,2845
+(defun lisp-complete-symbol 188,5862
+(defun mark-defun 149,4702
+(defun mark-sexp 36,1290
+(defun move-past-close-and-reindent 175,5481
+(defun up-list 75,2485
+
+../lisp/loaddefs.el,4101
+(defvar auto-mode-alist 162,6404
+(defconst case-replace 105,4162
+(defvar compile-command 130,5134
+(defvar ctl-x-4-map 205,7864
+(define-key ctl-x-4-map 223,8429
+(define-key ctl-x-4-map 404,14918
+(define-key ctl-x-4-map 1165,42872
+(define-key ctl-x-4-map 1346,49318
+(define-key ctl-x-map 337,12621
+(define-key ctl-x-map 392,14556
+(define-key ctl-x-map 707,25743
+(define-key ctl-x-map 1166,42920
+(define-key ctl-x-map 1764,64975
+(define-key ctl-x-map 1766,65023
+(define-key ctl-x-map 1767,65069
+(define-key ctl-x-map 1768,65115
+(define-key ctl-x-map 1769,65160
+(define-key ctl-x-map 1770,65204
+(define-key ctl-x-map 1774,65339
+(define-key ctl-x-map 1782,65642
+(define-key ctl-x-map 1784,65697
+(define-key ctl-x-map 1785,65739
+(define-key ctl-x-map 1786,65780
+(define-key ctl-x-map 1788,65857
+(define-key ctl-x-map 1790,65934
+(define-key ctl-x-map 1937,72009
+(define-key ctl-x-map 1938,72056
+(define-key ctl-x-map 1939,72103
+(define-key ctl-x-map 1940,72158
+(define-key ctl-x-map 1942,72258
+(defvar dired-listing-switches 133,5250
+(defconst display-time-day-and-date 157,6239
+(define-key esc-map 349,13051
+(define-key esc-map 1303,48055
+(define-key esc-map 1330,48781
+(define-key esc-map 1381,50357
+(define-key esc-map 1749,64363
+(define-key esc-map 1750,64405
+(define-key esc-map 1751,64448
+(define-key esc-map 1752,64494
+(define-key esc-map 1753,64533
+(define-key esc-map 1754,64572
+(define-key esc-map 1755,64611
+(define-key esc-map 1756,64653
+(define-key esc-map 1757,64696
+(define-key esc-map 1758,64744
+(define-key esc-map 1759,64786
+(define-key esc-map 1760,64826
+(define-key esc-map 1761,64871
+(define-key esc-map 1762,64926
+(define-key esc-map 1772,65260
+(define-key esc-map 1773,65301
+(define-key esc-map 1776,65385
+(define-key esc-map 1777,65430
+(define-key esc-map 1778,65474
+(define-key esc-map 1779,65515
+(define-key esc-map 1780,65559
+(define-key esc-map 1781,65602
+(define-key esc-map 1877,69352
+(define-key esc-map 1933,71928
+(define-key esc-map 1941,72213
+(defconst function-keymap 85,3335
+(define-key global-map 1875,69255
+(define-key global-map 1876,69303
+(defvar indent-line-function 110,4375
+(defun isearch-backward 1820,67139
+(defun isearch-backward-regexp 1827,67284
+(defun isearch-forward 1792,65981
+(defun isearch-forward-regexp 1812,66892
+(defconst ledit-go-to-lisp-string 152,6037
+(defconst ledit-go-to-liszt-string 154,6132
+(defconst ledit-save-files 150,5935
+(defconst lpr-switches 137,5402
+(defvar mail-aliases 1126,41511
+(defconst mail-archive-file-name 1123,41402
+(defconst mail-header-separator 1120,41266
+(defconst mail-interactive 1113,40826
+(defconst mail-self-blind 1108,40620
+(defvar mail-use-rfc822 1169,42976
+(defconst mail-yank-ignored-headers 1117,40989
+(defvar minor-mode-alist 74,2924
+(defconst mode-line-buffer-identification 44,1892
+(defconst mode-line-modified 57,2436
+(defconst mode-line-process 51,2226
+(defconst only-global-abbrevs 113,4466
+(defconst page-delimiter 102,4067
+(defconst paragraph-separate 94,3712
+(defconst paragraph-start 92,3599
+(defun query-replace 1879,69406
+(defun query-replace-regexp 1893,70043
+(defun replace-regexp 1920,71316
+(defun replace-string 1909,70810
+(defvar rmail-default-dont-reply-to-names 1037,37968
+(defvar rmail-delete-after-output 1052,38783
+(defconst rmail-dont-reply-to-names 1033,37814
+(defconst rmail-ignored-headers 1049,38586
+(defconst rmail-primary-inbox-list 1044,38336
+(defconst search-delete-char 1851,68208
+(defconst search-exit-char 1849,68133
+(defconst search-exit-option 1859,68614
+(defvar search-last-regexp 1840,67744
+(defvar search-last-string 1835,67535
+(defconst search-quote-char 1853,68301
+(defconst search-repeat-char 1845,67951
+(defconst search-reverse-char 1847,68041
+(defvar search-slow-speed 1868,69013
+(defvar search-slow-window-lines 1862,68722
+(defconst search-yank-line-char 1857,68507
+(defconst search-yank-word-char 1855,68403
+(defconst send-mail-function 1104,40444
+(defconst sentence-end 98,3884
+(defconst shell-prompt-pattern 145,5683
+(defvar tags-file-name 140,5508
+
+../lisp/loadup.el,0
+
+../lisp/lpr.el,171
+(defun lpr-buffer 29,1079
+(defvar lpr-command 24,931
+(defun lpr-region 41,1532
+(defun print-buffer 35,1297
+(defun print-region 47,1749
+(defun print-region-1 53,1983
+
+../lisp/macros.el,100
+(defun insert-kbd-macro 36,1460
+(defun kbd-macro-query 65,2550
+(defun name-last-kbd-macro 21,837
+
+../lisp/mail-utils.el,257
+(defun mail-comma-list-regexp 198,7080
+(defun mail-fetch-field 151,5419
+(defun mail-parse-comma-list 183,6712
+(defun mail-string-delete 29,1063
+(defun mail-strip-quoted-names 36,1332
+(defvar mail-use-rfc822 24,883
+(defun rmail-dont-reply-to 116,4175
+
+../lisp/mailalias.el,105
+(defun build-mail-aliases 81,3257
+(defun define-mail-alias 123,4729
+(defun expand-mail-aliases 23,937
+
+../lisp/mailpost.el,33
+(defun post-mail-send-it 15,342
+
+../lisp/makesum.el,66
+(defun double-column 76,2757
+(defun make-command-summary 21,820
+
+../lisp/man.el,91
+(defun insert-man-file 145,4909
+(defun manual-entry 20,828
+(defun nuke-nroff-bs 93,3261
+
+../lisp/medit.el,443
+(defconst medit-buffer 29,1165
+(defun medit-goto-mdl 75,2555
+(defun medit-mode 104,3601
+(defconst medit-mode-hook 101,3477
+(defconst medit-mode-map 92,3117
+(defun medit-save-buffer 51,1918
+(defun medit-save-define 34,1360
+(defconst medit-save-files 31,1266
+(defun medit-save-region 45,1716
+(defun medit-zap-buffer 69,2429
+(defun medit-zap-define-to-mdl 57,2118
+(defconst medit-zap-file 27,1048
+(defun medit-zap-region-mdl 63,2280
+
+../lisp/meese.el,35
+(defun protect-innocence-hook 1,0
+
+../lisp/mh-e.el,11526
+(defun make-local-vars 1545,54172
+(defun mh-add-msgs-to-seq 2355,80891
+(defun mh-add-to-sequence 2444,83988
+(defvar mh-annotate-char 1797,62184
+(defvar mh-annotate-field 1800,62266
+(defun mh-annotate-msg 2578,88135
+(defun mh-auto-fill-for-letter 1846,63983
+(defvar mh-before-quit-hook 82,3119
+(defvar mh-before-send-letter-hook 76,2906
+(defun mh-burst-digest 354,12168
+(defvar mh-bury-show-buffer 146,5340
+(defun mh-check-whom 1911,65907
+(defvar mh-clean-message-header 106,3752
+(defun mh-clean-msg-header 1314,45313
+(defvar mh-cmd-note 176,6579
+(defun mh-compose-and-send-mail 2014,68928
+(defvar mh-compose-letter-function 72,2731
+(defun mh-copy-line-to-point 2477,84990
+(defun mh-copy-msg 368,12770
+(defun mh-copy-seq-to-point 2471,84774
+(defvar mh-cur-scan-msg-regexp 212,7882
+(defvar mh-current-folder 1436,49623
+(defun mh-define-sequence 2453,84231
+(defun mh-define-sequences 2439,83858
+(defun mh-delete-a-msg 1215,41961
+(defun mh-delete-line 1347,46463
+(defvar mh-delete-list 1441,49974
+(defun mh-delete-msg 383,13376
+(defun mh-delete-msg-from-seq 408,14289
+(defun mh-delete-msg-no-motion 396,13844
+(defun mh-delete-scan-msgs 1761,61117
+(defun mh-delete-seq-locally 2338,80301
+(defvar mh-delete-yanked-msg-window 149,5446
+(defvar mh-deleted-msg-regexp 191,7040
+(defun mh-display-msg 1252,43205
+(defvar mh-do-not-confirm 142,5195
+(defun mh-do-pick-search 1949,66893
+(defvar mh-draft-folder 274,10006
+(defvar mh-e-RCS-id)3,72
+(defun mh-edit-again 424,14837
+(defun mh-exec-cmd 2491,85335
+(defun mh-exec-cmd-daemon 2527,86463
+(defun mh-exec-cmd-output 2517,86111
+(defun mh-exec-cmd-quiet 2506,85779
+(defun mh-exec-lib-cmd-output 2548,87154
+(defun mh-execute-commands 445,15600
+(defun mh-expand-file-name 2723,92618
+(defun mh-extract-rejected-mail 456,15932
+(defun mh-find-path 2731,92949
+(defun mh-find-seq 2209,76016
+(defun mh-first-msg 479,16820
+(defvar mh-first-msg-num 1447,50356
+(defvar mh-flagged-scan-msg-regexp 208,7685
+(defvar mh-folder-filename 1438,49765
+(defvar mh-folder-list 271,9936
+(defun mh-folder-mode 1467,50959
+(defvar mh-folder-mode-hook 66,2565
+(defvar mh-folder-mode-map 252,9368
+(define-key mh-folder-mode-map 2820,96131
+(define-key mh-folder-mode-map 2821,96176
+(define-key mh-folder-mode-map 2822,96221
+(define-key mh-folder-mode-map 2823,96275
+(define-key mh-folder-mode-map 2824,96330
+(define-key mh-folder-mode-map 2825,96379
+(define-key mh-folder-mode-map 2826,96432
+(define-key mh-folder-mode-map 2827,96494
+(define-key mh-folder-mode-map 2828,96552
+(define-key mh-folder-mode-map 2829,96602
+(define-key mh-folder-mode-map 2830,96657
+(define-key mh-folder-mode-map 2831,96711
+(define-key mh-folder-mode-map 2832,96765
+(define-key mh-folder-mode-map 2833,96832
+(define-key mh-folder-mode-map 2834,96896
+(define-key mh-folder-mode-map 2835,96951
+(define-key mh-folder-mode-map 2836,97005
+(define-key mh-folder-mode-map 2837,97060
+(define-key mh-folder-mode-map 2838,97120
+(define-key mh-folder-mode-map 2839,97174
+(define-key mh-folder-mode-map 2840,97230
+(define-key mh-folder-mode-map 2841,97286
+(define-key mh-folder-mode-map 2842,97336
+(define-key mh-folder-mode-map 2843,97391
+(define-key mh-folder-mode-map 2844,97440
+(define-key mh-folder-mode-map 2845,97498
+(define-key mh-folder-mode-map 2846,97549
+(define-key mh-folder-mode-map 2847,97606
+(define-key mh-folder-mode-map 2848,97663
+(define-key mh-folder-mode-map 2849,97716
+(define-key mh-folder-mode-map 2850,97764
+(define-key mh-folder-mode-map 2851,97809
+(define-key mh-folder-mode-map 2852,97854
+(define-key mh-folder-mode-map 2853,97900
+(define-key mh-folder-mode-map 2854,97949
+(define-key mh-folder-mode-map 2855,97999
+(define-key mh-folder-mode-map 2856,98048
+(define-key mh-folder-mode-map 2857,98105
+(define-key mh-folder-mode-map 2858,98154
+(define-key mh-folder-mode-map 2859,98199
+(define-key mh-folder-mode-map 2860,98244
+(define-key mh-folder-mode-map 2861,98306
+(define-key mh-folder-mode-map 2862,98357
+(define-key mh-folder-mode-map 2863,98408
+(define-key mh-folder-mode-map 2864,98472
+(define-key mh-folder-mode-map 2865,98535
+(define-key mh-folder-mode-map 2866,98594
+(defun mh-folder-name-p 2397,82336
+(defun mh-forward 485,16919
+(defun mh-fully-kill-draft 2173,74876
+(defun mh-get-field 2762,94252
+(defun mh-get-msg-num 2691,91572
+(defun mh-get-new-mail 1595,55834
+(defvar mh-good-msg-regexp 188,6933
+(defun mh-goto-cur-msg 1684,58787
+(defun mh-goto-header-end 2809,95819
+(defun mh-goto-msg 530,18644
+(defun mh-in-header-p 1856,64234
+(defun mh-inc-folder 559,19643
+(defvar mh-inc-folder-hook 79,3011
+(defvar mh-ins-buf-prefix 138,5026
+(defvar mh-ins-string 89,3333
+(defun mh-insert-fields 2778,94807
+(defun mh-insert-letter 2097,72025
+(defun mh-insert-prefix-string 2164,74604
+(defun mh-insert-signature 1904,65692
+(defun mh-internal-seq 2390,82112
+(defun mh-invalidate-show-buffer 1301,44942
+(defvar mh-invisible-headers226,8366
+(defun mh-kill-folder 580,20489
+(defvar mh-last-destination 249,9285
+(defun mh-last-msg 597,21065
+(defvar mh-last-msg-num 1448,50419
+(defun mh-letter-mode 1803,62337
+(defvar mh-letter-mode-hook 69,2648
+(defvar mh-letter-mode-map 255,9438
+(define-key mh-letter-mode-map 2871,98682
+(define-key mh-letter-mode-map 2872,98742
+(define-key mh-letter-mode-map 2873,98802
+(define-key mh-letter-mode-map 2874,98860
+(define-key mh-letter-mode-map 2875,98920
+(define-key mh-letter-mode-map 2876,98980
+(define-key mh-letter-mode-map 2877,99037
+(define-key mh-letter-mode-map 2878,99094
+(define-key mh-letter-mode-map 2879,99149
+(define-key mh-letter-mode-map 2880,99206
+(define-key mh-letter-mode-map 2881,99263
+(define-key mh-letter-mode-map 2882,99327
+(define-key mh-letter-mode-map 2883,99385
+(define-key mh-letter-mode-map 2884,99446
+(define-key mh-letter-mode-map 2885,99506
+(define-key mh-letter-mode-map 2886,99570
+(defvar mh-letter-mode-syntax-table 261,9607
+(defun mh-list-folders 605,21231
+(defun mh-list-to-string 2558,87484
+(defvar mh-lpr-command-format 121,4356
+(defun mh-make-folder 1451,50482
+(defun mh-make-folder-list 2647,90441
+(defun mh-make-folder-mode-line 1640,57429
+(defun mh-make-pick-template 1932,66506
+(defun mh-make-seq 2203,75870
+(defun mh-map-over-seqs 2431,83548
+(defun mh-map-to-seq-msgs 2420,83222
+(defun mh-mapc 315,11338
+(defun mh-maybe-show 1420,49133
+(defun mh-msg-filename 2710,92176
+(defun mh-msg-filenames 2718,92411
+(defun mh-msg-is-in-seq 620,21634
+(defvar mh-msg-number-regexp 200,7335
+(defun mh-msg-search-pat 2705,92046
+(defvar mh-msg-search-regexp 204,7496
+(defun mh-msg-to-seq 2228,76443
+(defun mh-narrow-to-seq 630,21931
+(defvar mh-narrowed-to-seq 1446,50289
+(defun mh-new-draft-name 1394,48367
+(defvar mh-next-direction 1445,50216
+(defun mh-next-msg 1403,48645
+(defun mh-next-pick-field 1986,68096
+(defvar mh-next-seq-num 1440,49916
+(defun mh-next-undeleted-msg 646,22504
+(defun mh-notate 2590,88567
+(defun mh-notate-if-in-one-seq 2411,82846
+(defun mh-notate-seq 2405,82603
+(defun mh-notate-user-sequences 2379,81796
+(defvar mh-note-dist 185,6831
+(defvar mh-note-forw 182,6733
+(defvar mh-note-repl 179,6634
+(defun mh-outstanding-commands-p 1780,61752
+(defun mh-pack-folder 660,22899
+(defun mh-pack-folder-1 1697,59113
+(defun mh-page-digest 795,27587
+(defun mh-page-digest-backwards 815,28226
+(defun mh-page-msg 835,28857
+(defvar mh-partial-folder-mode-line-annotation 219,8164
+(defvar mh-pick-mode-map 258,9526
+(define-key mh-pick-mode-map 2891,99664
+(define-key mh-pick-mode-map 2892,99724
+(define-key mh-pick-mode-map 2893,99782
+(define-key mh-pick-mode-map 2894,99840
+(define-key mh-pick-mode-map 2895,99898
+(define-key mh-pick-mode-map 2896,99956
+(define-key mh-pick-mode-map 2897,100014
+(define-key mh-pick-mode-map 2898,100069
+(define-key mh-pick-mode-map 2899,100124
+(define-key mh-pick-mode-map 2900,100179
+(define-key mh-pick-mode-map 2901,100234
+(define-key mh-pick-mode-map 2902,100289
+(defun mh-pipe-msg 674,23395
+(defun mh-position-on-field 2796,95393
+(defun mh-previous-page 842,29047
+(defvar mh-previous-seq 284,10264
+(defun mh-previous-undeleted-msg 853,29336
+(defvar mh-previous-window-config 281,10178
+(defvar mh-print-background 127,4628
+(defun mh-print-msg 865,29677
+(defun mh-process-commands 1719,59834
+(defun mh-process-daemon 2541,86934
+(defun mh-process-or-undo-commands 1707,59453
+(defun mh-prompt-for-folder 2606,88961
+(defmacro mh-push 290,10390
+(defun mh-put-msg-in-seq 913,31447
+(defun mh-quit 784,27250
+(defvar mh-quit-hook 85,3226
+(defun mh-read-draft 1352,46602
+(defun mh-read-folder-sequences 2258,77548
+(defun mh-read-msg-list 2308,79327
+(defun mh-read-msg-range 2675,91215
+(defun mh-read-seq 2238,76785
+(defun mh-read-seq-default 2233,76584
+(defun mh-recenter 2189,75385
+(defvar mh-recenter-summary-p 135,4913
+(defvar mh-recursive-folders 166,6245
+(defvar mh-redist-full-contents 59,2378
+(defun mh-redistribute 937,32339
+(defun mh-refile-a-msg 1229,42355
+(defvar mh-refile-list 1442,50035
+(defun mh-refile-msg 687,23941
+(defun mh-refile-or-write-again 708,24620
+(defvar mh-refiled-msg-regexp 194,7133
+(defun mh-regenerate-headers 1570,54905
+(defvar mh-rejected-letter-start232,8663
+(defun mh-remove-folder-from-folder-list 2669,91040
+(defun mh-remove-msg-from-seq 2344,80462
+(defun mh-remove-seq 2331,80097
+(defun mh-rename-seq 2368,81429
+(defun mh-reply 724,25250
+(defvar mh-reply-default-reply-to 161,6010
+(defun mh-rescan-folder 926,31906
+(defun mh-rmail 325,11476
+(defun mh-scan-folder 1554,54436
+(defun mh-search-folder 996,34469
+(defvar mh-searching-folder 1929,66438
+(defvar mh-seen-list 1444,50160
+(defun mh-send 1009,34853
+(defvar mh-send-args 1794,62108
+(defun mh-send-letter 2050,70514
+(defun mh-send-other-window 1020,35279
+(defun mh-send-sub 1027,35511
+(defvar mh-sent-from-folder 1788,61949
+(defvar mh-sent-from-msg 1791,62030
+(defun mh-seq-containing-msg 2217,76182
+(defun mh-seq-from-command 2288,78670
+(defvar mh-seq-list 1443,50102
+(defmacro mh-seq-msgs 2207,75968
+(defmacro mh-seq-name 2205,75920
+(defun mh-seq-names 2282,78484
+(defun mh-seq-to-msgs 2212,76070
+(defun mh-set-folder-list 2641,90251
+(defun mh-set-folder-modified-p 1775,61610
+(defun mh-set-mode-name 1425,49281
+(defun mh-set-scan-mode 1410,48852
+(defun mh-show 1053,36444
+(defvar mh-show-buffer 1437,49690
+(defvar mh-show-buffer-mode-line-buffer-id 215,7977
+(defun mh-show-message-in-other-window 1309,45161
+(defvar mh-showing 1439,49839
+(defun mh-smail 337,11812
+(defun mh-smail-other-window 344,11950
+(defun mh-sort-folder 1074,37246
+(defvar mh-summary-height 132,4817
+(defun mh-to-fcc 1892,65345
+(defun mh-to-field 1865,64483
+(defvar mh-to-field-choices 239,9032
+(defun mh-toggle-showing 1086,37642
+(defun mh-undefine-sequence 2464,84587
+(defun mh-undo 1094,37814
+(defun mh-undo-folder 1142,39505
+(defun mh-undo-msg 1130,39158
+(defun mh-unmark-all-headers 1661,58147
+(defvar mh-unseen-seq 278,10117
+(defun mh-unshar-buffer 1166,40278
+(defvar mh-unshar-default-directory 169,6355
+(defun mh-unshar-msg 1158,39920
+(defvar mh-user-path 246,9234
+(defvar mh-valid-scan-line 197,7229
+(defvar mh-visible-headers 111,3954
+(defun mh-visit-folder 1190,41252
+(defmacro mh-when 294,10451
+(defun mh-widen 1201,41647
+(defun mh-write-msg-to-file 977,33766
+(defun mh-yank-cur-msg 2123,73132
+(defvar mh-yank-from-start-of-msg 154,5670
+(defvar mh-yank-hooks92,3437
+(defvar mhl-formfile 116,4176
+(defmacro with-mh-folder-updating 298,10522
+
+../lisp/mim-mode.el,1720
+(define-abbrev-table 'mim-mode-abbrev-table 87,3510
+(defun abs 853,35639
+(defun backward-down-mim-object 372,15545
+(defun backward-kill-mim-object 326,13864
+(defun backward-mim-object 308,13241
+(defun backward-up-mim-object 388,16191
+(defun begin-mim-comment 803,33714
+(defun beginning-of-DEFINE 408,16970
+(defun calculate-mim-indent 462,19012
+(defun end-of-DEFINE 421,17505
+(defun find-mim-definition 783,33151
+(defun forward-down-mim-object 347,14536
+(defun forward-kill-mim-object 320,13657
+(defun forward-mim-object 264,11317
+(defun forward-mim-objects 292,12535
+(defun forward-up-mim-object 378,15781
+(defvar indent-mim-arglist 116,4603
+(defvar indent-mim-comment 109,4415
+(defun indent-mim-comment 696,29746
+(defconst indent-mim-hook 89,3560
+(defun indent-mim-hook 621,26286
+(defun indent-mim-line 731,31259
+(defun indent-mim-object 764,32368
+(defun indent-mim-offset 669,28699
+(defun inside-adecl-or-trailer-p 843,35412
+(defun inside-atom-p 285,12254
+(defun line-to-top-of-window 259,11191
+(defun mark-mim-object 314,13429
+(defvar mim-body-indent 112,4489
+(defvar mim-down-parens-only 139,5613
+(defun mim-mode 150,5990
+(defvar mim-mode-hook 83,3360
+(defvar mim-mode-hysterical-bindings 34,1161
+(defvar mim-mode-map 39,1363
+(defvar mim-mode-syntax-table 41,1390
+(defvar mim-stop-for-slop 143,5747
+(defconst mim-whitespace 81,3324
+(defun newline-and-mim-indent 742,31668
+(defun next-char 857,35717
+(defun next-mim-object 435,17983
+(defun open-mim-line 752,32043
+(defun previous-mim-object 455,18772
+(defun raise-mim-line 332,14043
+(defun replace-in-mim-object 394,16418
+(defun sign 849,35567
+(defun skip-mim-whitespace 838,35240
+(defun transpose-mim-objects 401,16694
+
+../lisp/mim-syntax.el,75
+(defun fast-syntax-check-mim 76,2664
+(defun slow-syntax-check-mim 24,869
+
+../lisp/mlconvert.el,135
+(defun convert-mocklisp-buffer 20,826
+(defun fix-mlisp-symbols 68,2232
+(defun fix-mlisp-syntax 54,1854
+(defun ml-expansion 91,2818
+
+../lisp/mlsupport.el,3259
+(defun >> 43,1507
+(defun append-region-to-buffer 147,4420
+(defun argc 250,6978
+(defun argv 256,7136
+(defun auto-execute 126,3821
+(defun backward-character 168,5038
+(defun beginning-of-window 284,7795
+(defun bind-to-key 72,2228
+(defun case-region-capitalize 245,6867
+(defun case-region-lower 239,6739
+(defun case-region-upper 242,6804
+(defun case-word-capitalize 228,6491
+(defun case-word-lower 222,6365
+(defun case-word-upper 225,6429
+(defun copy-region-to-buffer 144,4337
+(defmacro declare-buffer-specific 31,1044
+(defmacro declare-global 91,2725
+(defun define-hooked-global-abbrev 219,6264
+(defun define-hooked-local-abbrev 216,6165
+(defun define-keymap 51,1683
+(defun delete-next-character 153,4596
+(defun delete-next-word 156,4667
+(defun delete-previous-character 162,4886
+(defun delete-previous-word 159,4774
+(defun delete-region-to-buffer 140,4219
+(defun delete-to-kill-buffer 180,5292
+(defun end-of-window 287,7856
+(defun erase-region 137,4161
+(defmacro error-occurred 94,2844
+(defun execute-mlisp-line 368,10253
+(defun execute-monitor-command 317,8846
+(defun exit-emacs 270,7483
+(defun filter-region 310,8558
+(defun forward-character 165,4970
+(defun invisible-argc 262,7300
+(defun invisible-argv 266,7392
+(defmacro is-bound 88,2604
+(defun kill-to-end-of-line 116,3543
+(defun last-key-struck 366,10207
+(defun line-to-top-of-window 327,9231
+(defun local-bind-to-key 60,1914
+(defun ml-autoload 76,2349
+(defun ml-buffer-size 278,7694
+(defun ml-casify-word 231,6562
+(defun ml-current-column 197,5680
+(defun ml-current-indent 200,5734
+(defun ml-define-string-macro 79,2414
+(defmacro ml-defun 23,839
+(defun ml-defun-1 26,913
+(defun ml-message 114,3474
+(defun ml-modify-syntax-entry 376,10444
+(defun ml-newline 171,5108
+(defun ml-newline-and-indent 186,5419
+(defun ml-next-line 174,5164
+(defun ml-next-page 339,9548
+(defun ml-next-window 351,9877
+(defun ml-not 46,1574
+(defun ml-prefix-argument 100,3025
+(defun ml-previous-line 177,5224
+(defun ml-previous-page 330,9304
+(defun ml-previous-window 354,9936
+(defun ml-print 106,3213
+(defun ml-re-search-backward 300,8235
+(defun ml-re-search-forward 294,8045
+(defun ml-search-backward 297,8142
+(defun ml-search-forward 291,7954
+(defun ml-set 112,3425
+(defun ml-set-default 37,1281
+(defun ml-substr 404,11288
+(defun ml-use-global-map 57,1831
+(defun ml-use-local-map 54,1750
+(defun move-dot-to-x-y 371,10313
+(defun move-to-comment-column 134,4097
+(defun narrow-region 183,5357
+(defun newline-and-backup 191,5552
+(defun novalue 44,1550
+(defun page-next-window 342,9616
+(defun prepend-region-to-buffer 150,4507
+(defun previous-command 281,7751
+(defun provide-prefix-arg 48,1617
+(defun push-back-character 82,2486
+(defun quote-char 194,5618
+(defun region-around-match 203,5793
+(defun region-to-string 207,5897
+(defun return-prefix-argument 97,2959
+(defvar saved-command-line-args 248,6940
+(defun scroll-one-line-down 360,10069
+(defun scroll-one-line-up 357,10003
+(defun set-auto-fill-hook 123,3750
+(defmacro setq-default 34,1202
+(defun split-current-window 363,10139
+(defun to-col 85,2556
+(defun use-abbrev-table 210,5989
+(defvar use-csh-option-f 307,8458
+(defun use-syntax-table 324,9123
+(defvar use-users-shell 303,8334
+
+../lisp/modula2.el,1006
+(defun execute-monitor-command 367,10078
+(defun m2-begin 146,5132
+(defun m2-begin-comment 341,9439
+(defun m2-case 153,5271
+(defun m2-compile 353,9673
+(defvar m2-compile-command 13,321
+(defun m2-definition 163,5505
+(defun m2-else 171,5755
+(defun m2-end-comment 347,9557
+(defun m2-export 331,9255
+(defun m2-for 180,5947
+(defun m2-header 194,6321
+(defun m2-if 206,6707
+(defun m2-import 335,9324
+(defvar m2-indent 75,2363
+(defun m2-link 358,9801
+(defvar m2-link-command 16,397
+(defvar m2-link-name 19,467
+(defun m2-loop 216,6960
+(defvar m2-mode-map 40,1092
+(defvar m2-mode-syntax-table 10,236
+(defun m2-module 226,7138
+(defun m2-newline 134,4819
+(defun m2-or 234,7388
+(defun m2-procedure 242,7522
+(defun m2-record 274,8174
+(defun m2-stdio 283,8322
+(defun m2-tab 141,4999
+(defun m2-toggle 404,11197
+(defun m2-type 297,8719
+(defun m2-until 303,8799
+(defun m2-var 313,8969
+(defun m2-visit 372,10273
+(defun m2-while 320,9062
+(defun m2-with 263,7984
+(defun modula-2-mode 77,2443
+
+../lisp/novice.el,101
+(defun disable-command 89,3347
+(defun disabled-command-hook 26,1023
+(defun enable-command 70,2614
+
+../lisp/nroff-mode.el,353
+(defun backward-text-line 124,4484
+(defun count-text-lines 92,3390
+(defun electric-nroff-mode 187,6160
+(defun electric-nroff-newline 166,5430
+(defun forward-text-line 106,3932
+(defconst nroff-brace-table130,4709
+(defun nroff-comment-indent 71,2886
+(defun nroff-mode 37,1430
+(defvar nroff-mode-abbrev-table 22,834
+(defvar nroff-mode-map 25,915
+
+../lisp/options.el,299
+(defun Edit-options-mode 69,2310
+(defvar Edit-options-mode-map54,1814
+(defun Edit-options-modify 102,3491
+(defun Edit-options-nil 99,3404
+(defun Edit-options-set 89,3067
+(defun Edit-options-t 96,3321
+(defun Edit-options-toggle 93,3210
+(defun edit-options 45,1519
+(defun list-options 21,813
+
+../lisp/outline.el,997
+(defun hide-body 177,7121
+(defun hide-entry 164,6722
+(defun hide-leaves 205,7892
+(defun hide-region-body 182,7244
+(defun hide-subtree 200,7764
+(defun outline-back-to-heading 121,5183
+(defun outline-backward-same-level 308,10925
+(defun outline-end-of-subtree 223,8388
+(defun outline-flag-region 153,6320
+(defun outline-flag-subtree 216,8212
+(defun outline-forward-same-level 280,10057
+(defun outline-get-last-sibling 324,11414
+(defun outline-get-next-sibling 296,10546
+(defun outline-level 98,4374
+(defun outline-mode 42,1801
+(defvar outline-mode-map 28,1154
+(defun outline-next-heading 114,4951
+(defun outline-next-preface 106,4674
+(defun outline-next-visible-heading 135,5640
+(defun outline-on-heading-p 128,5455
+(defun outline-previous-visible-heading 146,6037
+(defvar outline-regexp 22,892
+(defun outline-up-heading 265,9597
+(defun show-all 195,7635
+(defun show-branches 236,8717
+(defun show-children 241,8846
+(defun show-entry 171,6936
+(defun show-subtree 211,8085
+
+../lisp/page.el,175
+(defun backward-page 38,1412
+(defun count-lines-page 91,3201
+(defun forward-page 21,813
+(defun mark-page 45,1686
+(defun narrow-to-page 59,2127
+(defun what-page 109,3762
+
+../lisp/paragraphs.el,551
+(defun backward-kill-paragraph 109,4078
+(defun backward-kill-sentence 180,6483
+(defun backward-paragraph 86,3268
+(defun backward-sentence 165,6028
+(defun end-of-paragraph-text 134,4923
+(defun forward-paragraph 25,1005
+(defun forward-sentence 144,5184
+(defun kill-paragraph 104,3933
+(defun kill-sentence 172,6255
+(defun mark-end-of-sentence 188,6727
+(defun mark-paragraph 97,3762
+(defvar paragraph-ignore-fill-prefix 21,813
+(defun start-of-paragraph-text 119,4399
+(defun transpose-paragraphs 114,4240
+(defun transpose-sentences 196,6929
+
+../lisp/paths.el,448
+(defvar Info-directory 27,1073
+(defconst abbrev-file-name 119,5173
+(defconst manual-formatted-dir-prefix84,3452
+(defconst manual-formatted-dirlist90,3717
+(defconst manual-program 76,3033
+(defvar mh-lib47,1915
+(defvar mh-progs39,1557
+(defvar news-inews-program31,1243
+(defvar news-path 29,1143
+(defconst rmail-file-name 54,2210
+(defconst rmail-spool-directory57,2286
+(defconst sendmail-program65,2559
+(defconst term-file-prefix 71,2748
+
+../lisp/picture.el,1643
+(defun edit-picture 469,17814
+(defvar edit-picture-hook 465,17662
+(defun move-to-column-force 24,898
+(defun picture-backward-clear-column 187,6379
+(defun picture-backward-column 57,2001
+(defun picture-clean 569,22641
+(defun picture-clear-column 176,6030
+(defun picture-clear-line 192,6540
+(defun picture-clear-rectangle 346,12105
+(defun picture-clear-rectangle-to-register 355,12550
+(defun picture-duplicate-line 227,7666
+(defun picture-end-of-line 42,1418
+(defun picture-forward-column 51,1799
+(defconst picture-horizontal-step 74,2545
+(defun picture-insert-rectangle 407,14795
+(defconst picture-killed-rectangle 342,11925
+(defun picture-mode-exit 553,21944
+(defconst picture-mode-map 425,15372
+(defun picture-motion 142,4701
+(defun picture-motion-reverse 151,5125
+(defun picture-move 137,4502
+(defun picture-move-down 63,2203
+(defun picture-move-up 77,2653
+(defun picture-movement-down 98,3244
+(defun picture-movement-left 88,2968
+(defun picture-movement-ne 108,3529
+(defun picture-movement-nw 103,3383
+(defun picture-movement-right 83,2827
+(defun picture-movement-se 118,3822
+(defun picture-movement-sw 113,3675
+(defun picture-movement-up 93,3108
+(defun picture-newline 207,7101
+(defun picture-open-line 219,7462
+(defun picture-self-insert 162,5520
+(defun picture-set-motion 123,3969
+(defun picture-set-tab-stops 266,9214
+(defun picture-snarf-rectangle 363,12959
+(defun picture-tab 324,11355
+(defvar picture-tab-chars 241,7979
+(defun picture-tab-search 297,10439
+(defconst picture-vertical-step 71,2441
+(defun picture-yank-rectangle 384,13638
+(defun picture-yank-rectangle-from-register 395,14177
+
+../lisp/prolog.el,766
+(define-abbrev-table 'prolog-mode-abbrev-table 53,1951
+(defun end-of-prolog-clause 164,5441
+(defun inferior-prolog-mode 195,6284
+(defvar inferior-prolog-mode-map 187,6051
+(defun prolog-comment-indent 172,5721
+(defvar prolog-compile-string 28,1129
+(defun prolog-consult-region 246,8340
+(defun prolog-consult-region-and-go 261,8912
+(defvar prolog-consult-string 25,1018
+(defvar prolog-eof-string 31,1220
+(defun prolog-indent-level 117,4088
+(defun prolog-indent-line 99,3535
+(defvar prolog-indent-width 35,1368
+(defun prolog-mode 84,3083
+(defvar prolog-mode-abbrev-table 22,948
+(defun prolog-mode-commands 75,2835
+(defvar prolog-mode-map 23,986
+(defvar prolog-mode-syntax-table 21,910
+(defun prolog-mode-variables 55,2003
+(defun run-prolog 239,8131
+
+../lisp/rect.el,644
+(defun clear-rectangle 183,6648
+(defun clear-rectangle-line 189,6912
+(defun delete-extract-rectangle 113,4132
+(defun delete-extract-rectangle-line 72,2676
+(defun delete-rectangle 105,3795
+(defun delete-rectangle-line 69,2579
+(defun extract-rectangle 121,4427
+(defun extract-rectangle-line 77,2862
+(defun insert-rectangle 143,5252
+(defun kill-rectangle 131,4769
+(defvar killed-rectangle 128,4694
+(defun open-rectangle 165,5950
+(defun open-rectangle-line 172,6262
+(defun operate-on-rectangle 21,816
+(defun rectangle-coerce-tab 199,7226
+(defun spaces-string 97,3585
+(defconst spaces-strings94,3490
+(defun yank-rectangle 138,5103
+
+../lisp/register.el,371
+(defun append-to-register 139,4827
+(defun copy-rectangle-to-register 165,5909
+(defun copy-to-register 129,4423
+(defun get-register 26,1044
+(defun insert-register 112,3788
+(defun point-to-register 38,1435
+(defun prepend-to-register 152,5366
+(defvar register-alist 21,810
+(defun register-to-point 44,1642
+(defun set-register 30,1174
+(defun view-register 83,2994
+
+../lisp/replace.el,427
+(defun flush-lines 44,1695
+(defun how-many 58,2212
+(defun keep-lines 22,861
+(defvar list-matching-lines-default-context-lines 117,4167
+(defun occur 123,4484
+(defvar occur-buffer 78,2911
+(defun occur-mode 82,2992
+(defun occur-mode-goto-occurrence 96,3485
+(defvar occur-mode-map 72,2742
+(defvar occur-nlines 79,2937
+(defvar occur-pos-list 80,2963
+(defun perform-replace 215,7719
+(defconst query-replace-help202,7143
+
+../lisp/rfc822.el,364
+(defun rfc822-addresses 263,8724
+(defun rfc822-addresses-1 157,4602
+(defun rfc822-bad-address 24,930
+(defun rfc822-looking-at 80,2455
+(defun rfc822-nuke-whitespace 47,1651
+(defun rfc822-snarf-domain 124,3726
+(defun rfc822-snarf-frob-list 129,3847
+(defun rfc822-snarf-subdomain 112,3299
+(defun rfc822-snarf-word 95,2821
+(defun rfc822-snarf-words 107,3189
+
+../lisp/rmail.el,2550
+(defvar mmdf-delim1 55,2130
+(defvar mmdf-delim2 57,2221
+(defun rmail 94,3474
+(defun rmail-beginning-of-message 939,34383
+(defun rmail-clear-headers 706,26250
+(defun rmail-continue 1227,43991
+(defun rmail-convert-file 149,5569
+(defun rmail-convert-to-babyl-format 551,21166
+(defun rmail-count-new-messages 867,31728
+(defvar rmail-current-message 68,2539
+(defun rmail-delete-backward 1142,41034
+(defun rmail-delete-forward 1134,40690
+(defun rmail-delete-message 1116,40145
+(defvar rmail-deleted-vector 71,2642
+(defun rmail-display-labels 751,27782
+(defun rmail-expunge 1148,41252
+(defun rmail-expunge-and-save 351,13946
+(defun rmail-forget-messages 848,31226
+(defun rmail-forward 1334,47671
+(defun rmail-get-new-mail 379,14648
+(defun rmail-input 368,14390
+(defun rmail-insert-inbox-text 458,17757
+(defun rmail-insert-rmail-file-header 179,6637
+(defvar rmail-last-file 84,2999
+(defvar rmail-last-label 81,2872
+(defun rmail-last-message 1027,37258
+(defvar rmail-last-multi-labels 83,2962
+(defvar rmail-last-rmail-file 85,3028
+(defun rmail-mail 1220,43766
+(defun rmail-make-in-reply-to-field 1295,46382
+(defun rmail-maybe-set-message-counters 860,31538
+(defun rmail-message-deleted-p 1110,39972
+(defvar rmail-message-filter 60,2311
+(defun rmail-message-labels-p 819,30205
+(defvar rmail-message-vector 70,2608
+(defun rmail-mode 233,9159
+(defun rmail-mode-1 282,11483
+(defvar rmail-mode-map 64,2460
+(defun rmail-msgbeg 829,30496
+(defun rmail-msgend 826,30415
+(defun rmail-next-message 982,35692
+(defun rmail-next-undeleted-message 997,36180
+(defun rmail-nuke-pinhead-header 643,24311
+(defun rmail-parse-file-inboxes 336,13519
+(defun rmail-previous-message 990,35963
+(defun rmail-previous-undeleted-message 1020,37022
+(defun rmail-quit 357,14064
+(defun rmail-reformat-message 682,25450
+(defun rmail-reply 1232,44125
+(defun rmail-revert 321,12969
+(defun rmail-search 1046,37784
+(defvar rmail-search-last-regexp 1045,37746
+(defun rmail-set-attribute 795,29351
+(defun rmail-set-message-counters 894,32805
+(defun rmail-set-message-counters-counter 925,33908
+(defun rmail-set-message-deleted-p 1113,40048
+(defun rmail-show-message 944,34537
+(defvar rmail-summary-buffer 75,2725
+(defvar rmail-summary-vector 76,2759
+(defun rmail-toggle-header 720,26682
+(defvar rmail-total-messages 69,2574
+(defun rmail-undelete-previous-message 1121,40270
+(defvar rmail-unix-mail-delimiter89,3198
+(defun rmail-variables 296,11962
+(defun rmail-what-message 1033,37417
+(defun rmail-widen-to-current-msgbeg 832,30572
+
+../lisp/rmailedit.el,172
+(defun rmail-abort-edit 99,3639
+(defun rmail-cease-edit 64,2492
+(defun rmail-edit-current-message 49,1842
+(defvar rmail-edit-map 23,844
+(defun rmail-edit-mode 33,1182
+
+../lisp/rmailkwd.el,661
+(defun rmail-add-label 40,1472
+(defun rmail-attribute-p 153,5483
+(defconst rmail-attributes29,1126
+(defconst rmail-deleted-label 34,1299
+(defun rmail-force-make-label 166,5906
+(defun rmail-install-keyword 236,8393
+(defun rmail-keyword-p 157,5607
+(defvar rmail-keywords 38,1442
+(defun rmail-keywords 215,7702
+(defun rmail-kill-label 46,1708
+(defvar rmail-label-obarray 25,1003
+(defun rmail-make-label 161,5729
+(defun rmail-next-labeled-message 180,6410
+(defun rmail-parse-file-keywords 220,7894
+(defun rmail-previous-labeled-message 174,6123
+(defun rmail-quote-label-name 169,5986
+(defun rmail-read-label 52,1955
+(defun rmail-set-label 68,2381
+
+../lisp/rmailmsc.el,36
+(defun set-rmail-inbox-list 20,778
+
+../lisp/rmailout.el,114
+(defvar rmail-delete-after-output 22,895
+(defun rmail-output 86,3275
+(defun rmail-output-to-rmail-file 25,1011
+
+../lisp/rmailsum.el,862
+(defun rmail-make-basic-summary-line 184,6397
+(defun rmail-make-summary-line 109,4123
+(defun rmail-make-summary-line-1 125,4666
+(defun rmail-message-recipients-p 52,2017
+(defun rmail-new-summary 62,2476
+(defun rmail-summary 23,831
+(defun rmail-summary-by-labels 28,966
+(defun rmail-summary-by-recipients 40,1489
+(defun rmail-summary-delete-forward 279,9455
+(defun rmail-summary-exit 423,14330
+(defun rmail-summary-goto-msg 341,11599
+(defun rmail-summary-mode 310,10373
+(defvar rmail-summary-mode-map 377,12689
+(defun rmail-summary-next-all 254,8669
+(defun rmail-summary-next-msg 264,8949
+(defun rmail-summary-previous-all 259,8805
+(defun rmail-summary-previous-msg 275,9328
+(defun rmail-summary-quit 417,14204
+(defun rmail-summary-scroll-msg-down 406,13902
+(defun rmail-summary-scroll-msg-up 395,13605
+(defun rmail-summary-undelete 293,9829
+
+../lisp/rnews.el,2910
+(defun caesar-region 908,33060
+(defmacro news-/ 151,6096
+(defun news-add-news-group 842,30768
+(defvar news-buffer 126,5087
+(defmacro news-caadr 135,5457
+(defmacro news-cadar 134,5393
+(defmacro news-caddr 133,5329
+(defmacro news-cadr 131,5227
+(defun news-caesar-buffer-body 946,34574
+(defmacro news-cdadr 136,5521
+(defmacro news-cdar 132,5278
+(defvar news-certification-file 82,3239
+(defun news-convert-format 618,22785
+(defvar news-current-certifiable 100,4081
+(defvar news-current-certifications 97,3936
+(defvar news-current-group-begin 95,3861
+(defvar news-current-group-end 96,3899
+(defvar news-current-message-number 120,4829
+(defvar news-current-news-group 94,3824
+(defun news-delete-headers 650,23736
+(defun news-exit 660,24026
+(defun news-find-first-and-last 146,5915
+(defun news-find-first-or-last 159,6300
+(defun news-force-update 529,19910
+(defun news-get-certifications 213,8232
+(defun news-get-motion-lists 594,22122
+(defun news-get-new-news 398,15548
+(defun news-get-pruned-list-of-files 740,26972
+(defun news-goto-message 505,19113
+(defun news-goto-news-group 487,18472
+(defvar news-group-article-assoc 118,4788
+(defun news-group-certification 201,7820
+(defvar news-ignored-headers85,3362
+(defun news-list-news-groups 444,17132
+(defvar news-list-of-files 109,4414
+(defvar news-list-of-files-possibly-bogus 112,4540
+(defun news-make-link-to-message 892,32520
+(defvar news-max-plausible-gap 141,5689
+(defvar news-message-filter 103,4185
+(defun news-mode 302,11838
+(defvar news-mode-map 89,3661
+(defun news-move-to-group 564,21166
+(defun news-next-group 576,21604
+(defun news-next-message 535,20144
+(defvar news-no-jumps-p 125,5060
+(defun news-parse-range 381,15057
+(defvar news-point-pdl 124,5000
+(defun news-previous-group 585,21854
+(defun news-previous-message 556,20901
+(defmacro news-push 128,5153
+(defun news-read-files-into-buffer 802,29206
+(defvar news-read-first-time-p 90,3688
+(defun news-read-in-file 607,22539
+(defun news-save-item-in-file 735,26774
+(defun news-select-message 512,19338
+(defun news-select-news-group 495,18771
+(defun news-set-current-certifiable 205,7918
+(defun news-set-current-group-certification 245,9268
+(defun news-set-message-counters 264,10060
+(defun news-set-minor-modes 251,9549
+(defun news-set-mode-line 467,17859
+(defun news-show-all-headers 638,23372
+(defvar news-startup-file 81,3175
+(defvar news-total-current-group 121,4895
+(defun news-unsubscribe-current-group 718,26137
+(defun news-unsubscribe-group 712,25920
+(defvar news-unsubscribe-groups 123,4964
+(defun news-unsubscribe-internal 724,26383
+(defmacro news-update-message-read 375,14911
+(defun news-update-newsrc-file 674,24567
+(defvar news-user-group-list 92,3789
+(defmacro news-wins 138,5586
+(defun news-write-certifications 231,8759
+(defvar rmail-last-file 75,2995
+(defun rnews 179,7106
+(defun string-subst-char 366,14649
+
+../lisp/rnewspost.el,616
+(defun news-inews 207,8624
+(defun news-mail-other-window 380,14803
+(defun news-mail-reply 244,9984
+(defun news-post-news 351,13634
+(defun news-reply 272,10948
+(defun news-reply-distribution 148,6437
+(defun news-reply-followup-to 132,5747
+(defun news-reply-keywords 159,6868
+(defun news-reply-mode 69,3257
+(defvar news-reply-mode-map 50,2172
+(defun news-reply-newsgroups 122,5418
+(defun news-reply-signature 175,7430
+(defun news-reply-summary 167,7155
+(defvar news-reply-yank-from102,4773
+(defvar news-reply-yank-message-id106,4860
+(defun news-reply-yank-original 110,4959
+(defun news-setup 180,7596
+
+../lisp/saveconf.el,323
+(defvar auto-save-and-recover-context 21,820
+(defun kill-emacs 55,2239
+(defun original-working-directory 222,7922
+(defun recover-context 168,6221
+(defvar save-buffer-context 26,1082
+(defun save-context 71,2948
+(defvar save-context-predicate31,1271
+(defconst save-context-version 15,536
+(defun window-list 227,8051
+
+../lisp/scheme.el,892
+(define-abbrev-table 'scheme-mode-abbrev-table 85,2816
+(defun calculate-scheme-indent 203,6931
+(defun next-sexp-as-string 364,13322
+(defvar scheme-body-indent 310,11338
+(defun scheme-comment-indent 153,5282
+(defun scheme-indent-defform 351,12973
+(defvar scheme-indent-hook 166,5669
+(defun scheme-indent-hook 289,10502
+(defun scheme-indent-line 168,5721
+(defvar scheme-indent-offset 165,5632
+(defun scheme-indent-sexp 449,16883
+(defun scheme-indent-specform 312,11373
+(defun scheme-let-indent 378,13788
+(defvar scheme-mit-dialect 149,5138
+(defun scheme-mode 121,4136
+(defvar scheme-mode-abbrev-table 84,2775
+(defun scheme-mode-commands 110,3786
+(defun scheme-mode-initialize 144,5008
+(defvar scheme-mode-line-process 108,3748
+(defvar scheme-mode-map 115,3971
+(defvar scheme-mode-syntax-table 30,1174
+(defun scheme-mode-variables 87,2868
+(defun would-be-symbol 361,13238
+
+../lisp/scribe.el,870
+(defun scribe 141,5197
+(defun scribe-begin 200,7193
+(defun scribe-bold-word 190,6873
+(defun scribe-bracket-region-be 235,8077
+(defun scribe-chapter 214,7537
+(defconst scribe-close-parentheses 40,1459
+(defvar scribe-electric-parenthesis 33,1221
+(defvar scribe-electric-quote 30,1108
+(defun scribe-end 207,7367
+(defun scribe-envelop-word 146,5302
+(defvar scribe-fancy-paragraphs 27,992
+(defun scribe-insert-environment 243,8284
+(defun scribe-insert-quote 250,8461
+(defun scribe-italicize-word 195,7030
+(defun scribe-mode 89,3409
+(defvar scribe-mode-abbrev-table 24,909
+(defvar scribe-mode-map 63,2196
+(defvar scribe-mode-syntax-table 21,826
+(defconst scribe-open-parentheses 37,1372
+(defun scribe-parenthesis 286,9791
+(defun scribe-section 221,7715
+(defun scribe-subsection 228,7893
+(defun scribe-tab 134,5048
+(defun scribe-underline-word 185,6710
+
+../lisp/sendmail.el,682
+(defun mail 420,14376
+(defvar mail-abbrevs-loaded 53,2259
+(defvar mail-aliases 46,2043
+(defun mail-bcc 338,11856
+(defun mail-cc 330,11632
+(defvar mail-default-reply-to 50,2152
+(defun mail-do-fcc 259,9369
+(defun mail-fill-yanked-message 373,12846
+(defun mail-mode 104,3816
+(defvar mail-mode-map 54,2292
+(defun mail-other-window 462,15997
+(defun mail-position-on-field 346,12085
+(defun mail-send 163,6235
+(defun mail-send-and-exit 149,5763
+(defun mail-setup 65,2604
+(defun mail-signature 366,12643
+(defun mail-subject 324,11496
+(defun mail-to 318,11375
+(defun mail-yank-clear-headers 403,13846
+(defun mail-yank-original 384,13210
+(defun sendmail-send-it 176,6650
+
+../lisp/server.el,499
+(defun mh-draft-p 220,8713
+(defvar server-buffer-clients 74,3122
+(defun server-buffer-done 191,7734
+(defvar server-clients 68,2865
+(defun server-done 226,8976
+(defun server-edit 242,9521
+(defun server-log 84,3539
+(defvar server-previous-string 66,2829
+(defvar server-process 63,2768
+(defun server-process-filter 132,5387
+(defvar server-program 60,2691
+(defun server-sentinel 92,3712
+(defun server-start 98,3934
+(defun server-switch-buffer 257,10186
+(defun server-visit-files 163,6653
+
+../lisp/shell.el,1161
+(defun copy-last-shell-input 308,11114
+(defvar explicit-csh-args102,3807
+(defvar explicit-shell-file-name 42,1442
+(defvar inferior-lisp-load-command 350,12337
+(defun inferior-lisp-mode 363,12967
+(defvar inferior-lisp-mode-map 340,11990
+(defvar inferior-lisp-program 347,12233
+(defvar inferior-lisp-prompt 359,12826
+(defun interrupt-shell-subjob 314,11315
+(defun kill-output-from-shell 292,10640
+(defun kill-shell-input 334,11788
+(defun kill-shell-subjob 319,11437
+(defvar last-input-end 25,940
+(defvar last-input-start 23,842
+(defun lisp-send-defun 411,14818
+(defun lisp-send-defun-and-go 446,16090
+(defun make-shell 146,5592
+(defun quit-shell-subjob 324,11559
+(defun run-lisp 405,14625
+(defun shell 111,4120
+(defvar shell-cd-regexp 39,1354
+(defvar shell-directory-stack 30,1064
+(defun shell-mode 52,1825
+(defvar shell-mode-map 28,1035
+(defvar shell-popd-regexp 33,1163
+(defvar shell-pushd-regexp 36,1257
+(defun shell-send-eof 287,10513
+(defun shell-send-input 192,7202
+(defun shell-set-directory 238,9021
+(defvar shell-set-directory-error-hook 187,6993
+(defun show-output-from-shell 301,10891
+(defun stop-shell-subjob 329,11681
+
+../lisp/simple.el,5523
+(defun append-next-kill 595,21107
+(defun append-to-buffer 670,23631
+(defun auto-fill-mode 1210,42385
+(defun back-to-indentation 123,3856
+(defun backward-delete-char-untabify 164,5340
+(defun backward-kill-word 1116,39250
+(defun backward-to-indentation 506,17939
+(defun backward-word 1095,38644
+(defun beginning-of-buffer 192,6410
+(defun blink-matching-open 1269,44528
+(defconst blink-matching-paren 1262,44271
+(defconst blink-matching-paren-distance 1265,44380
+(defconst comment-column 993,34925
+(defconst comment-end 1006,35477
+(defconst comment-indent-hook1010,35617
+(defconst comment-multi-line 1153,40493
+(defconst comment-start 998,35122
+(defconst comment-start-skip 1001,35235
+(defun copy-region-as-kill 584,20658
+(defun copy-to-buffer 697,24669
+(defun count-lines 247,8176
+(defun count-lines-region 232,7776
+(define-key ctl-x-map 1359,47205
+(define-key ctl-x-map 1360,47250
+(define-key ctl-x-map 1370,47646
+(define-key ctl-x-map 1374,47820
+(define-key ctl-x-map 1376,47912
+(define-key ctl-x-map 1377,47964
+(define-key ctl-x-map 1396,48598
+(define-key ctl-x-map 1399,48693
+(define-key ctl-x-map 1403,48837
+(define-key ctl-x-map 1408,49020
+(define-key ctl-x-map 1413,49216
+(define-key ctl-x-map 1414,49263
+(define-key ctl-x-map 1415,49307
+(define-key ctl-x-map 1425,49644
+(defun delete-blank-lines 91,2885
+(defun delete-horizontal-space 76,2405
+(defun delete-indentation 53,1733
+(defun digit-argument 488,17312
+(defun do-auto-fill 1127,39652
+(defun edit-and-eval-command 300,10190
+(defun end-of-buffer 208,7005
+(define-key esc-map 1365,47418
+(define-key esc-map 1367,47504
+(define-key esc-map 1368,47549
+(define-key esc-map 1369,47600
+(define-key esc-map 1371,47696
+(define-key esc-map 1372,47737
+(define-key esc-map 1373,47775
+(define-key esc-map 1375,47869
+(define-key esc-map 1379,48045
+(define-key esc-map 1380,48085
+(define-key esc-map 1387,48302
+(define-key esc-map 1391,48433
+(define-key esc-map 1392,48479
+(define-key esc-map 1394,48562
+(define-key esc-map 1406,48933
+(define-key esc-map 1407,48975
+(define-key esc-map 1410,49068
+(define-key esc-map 1411,49113
+(define-key esc-map 1412,49163
+(define-key esc-map 1417,49358
+(define-key esc-map 1418,49394
+(define-key esc-map 1419,49433
+(define-key esc-map 1420,49473
+(define-key esc-map 1421,49509
+(define-key esc-map 1423,49558
+(define-key esc-map 1424,49604
+(define-key esc-map 1426,49690
+(defun eval-expression 293,9934
+(defun exchange-point-and-mark 789,28141
+(defconst fill-prefix 1122,39435
+(defun fixup-whitespace 64,2064
+(defun forward-to-indentation 500,17762
+(defun fundamental-mode 283,9570
+(define-key global-map 1329,46262
+(define-key global-map 1362,47285
+(define-key global-map 1363,47336
+(define-key global-map 1364,47376
+(define-key global-map 1366,47458
+(define-key global-map 1378,48008
+(define-key global-map 1382,48136
+(define-key global-map 1389,48347
+(define-key global-map 1390,48389
+(define-key global-map 1393,48525
+(define-key global-map 1398,48644
+(define-key global-map 1401,48749
+(define-key global-map 1402,48791
+(define-key global-map 1405,48885
+(define-key global-map 1431,49918
+(defvar goal-column 848,30288
+(defun goto-line 355,12447
+(defun indent-for-comment 1015,35778
+(defun indent-new-comment-line 1157,40652
+(defun insert-buffer 654,23139
+(defun just-one-space 82,2605
+(defun keyboard-quit 1324,46168
+(defun kill-append 542,18970
+(defun kill-backward-chars 159,5192
+(defun kill-comment 1077,38054
+(defun kill-forward-chars 154,5045
+(defun kill-line 512,18122
+(defun kill-region 548,19125
+(defvar kill-ring 533,18706
+(defconst kill-ring-max 536,18765
+(defvar kill-ring-yank-pointer 539,18867
+(defun kill-word 1110,39039
+(defun mark 712,25226
+(defvar mark-ring 737,26243
+(defconst mark-ring-max 742,26384
+(defun mark-whole-buffer 225,7602
+(defun mark-word 1102,38880
+(defconst mode-specific-map 1429,49800
+(defun negative-argument 494,17540
+(defun newline-and-indent 129,4024
+(defun next-complex-command 335,11697
+(defun next-line 799,28406
+(defun next-line-internal 855,30574
+(defun open-line 21,832
+(defun overwrite-mode 1251,43833
+(defun pop-mark 777,27723
+(defun prefix-arg-internal 455,16246
+(defun prepend-to-buffer 683,24140
+(defun previous-complex-command 350,12283
+(defun previous-line 827,29412
+(defun push-mark 760,27007
+(defun quoted-insert 43,1416
+(defun reindent-then-newline-and-indent 140,4456
+(defun repeat-complex-command 310,10693
+(defvar repeat-complex-command-map 307,10483
+(define-key repeat-complex-command-map 308,10553
+(define-key repeat-complex-command-map 309,10625
+(defun rotate-yank-pointer 602,21319
+(defun set-comment-column 1054,37210
+(defun set-fill-column 1229,42964
+(defun set-goal-column 880,31274
+(defun set-mark 718,25464
+(defun set-mark-command 745,26489
+(defun set-selective-display 1236,43239
+(defun set-variable 1331,46310
+(defun shell-command 384,13337
+(defun shell-command-on-region 397,13850
+(defun split-line 33,1168
+(defvar temporary-goal-column 851,30405
+(defconst track-eol 844,30113
+(defun transpose-chars 897,31926
+(defun transpose-lines 922,32966
+(defun transpose-sexps 915,32744
+(defun transpose-subr 940,33514
+(defun transpose-subr-1 980,34488
+(defun transpose-words 906,32362
+(defun turn-on-auto-fill 1225,42869
+(defun undo 368,12837
+(defun universal-argument 437,15518
+(defun what-cursor-position 255,8422
+(defun what-line 237,7935
+(defun yank 637,22574
+(defun yank-pop 613,21650
+(defun zap-to-char 183,6001
+
+../lisp/simula.el,1705
+(define-abbrev-table 'simula-mode-abbrev-table 50,1886
+(defvar Read-Simula-Keywords 47,1814
+(defun Simula-Default-Form-Handler 522,17970
+(defun Simula-Default-Handler 511,17701
+(defun Simula-For-Handler 632,21601
+(defun Simula-Form-Handler 504,17521
+(defun Simula-If-Handler 626,21437
+(defun Simula-Inspect-Handler 629,21514
+(defvar Simula-Keyword-Abbrev-File 52,1938
+(defun Simula-While-Handler 623,21354
+(defun current-simula-indentation 566,19412
+(defun get-indent-amount 551,19014
+(defun ignore-simula-directives 199,7257
+(defun maybe-skip-simula-comment 224,8287
+(defun save-simula-BB-BE(288,10373
+(defun save-simula-string 495,17247
+(defvar simula-BB 30,1287
+(defvar simula-BE 29,1259
+(defvar simula-CB 28,1214
+(defvar simula-CE 27,1160
+(defvar simula-FB 31,1317
+(defun simula-Nice-indent-mode 637,21700
+(defun simula-Simed-indent-mode 735,25496
+(defun simula-abbrev-expand-and-lf 605,20759
+(defun simula-back-level(316,11150
+(defun simula-collapse-stack 536,18440
+(defvar simula-eof 33,1402
+(defvar simula-eol 32,1377
+(defvar simula-extended-form 35,1467
+(defun simula-find-indent 348,12114
+(defun simula-indent 619,21243
+(defun simula-indent-calc 573,19660
+(defun simula-indent-line 585,19973
+(defvar simula-indent-mode 44,1726
+(defun simula-inside-simple-string 179,6719
+(defvar simula-label 26,1120
+(defun simula-mode 100,3697
+(defvar simula-mode-abbrev-table 41,1647
+(defvar simula-mode-ignore-directives 55,2045
+(defvar simula-mode-map 89,3378
+(defvar simula-mode-syntax-table 38,1567
+(defun simula-null-indent 154,5841
+(defun simula-parsed-over 461,16117
+(defun simula-pop 173,6551
+(defun simula-push 170,6461
+(defun simula-stack-trick 474,16525
+
+../lisp/sort.el,425
+(defun sort-build-lists 99,3882
+(defun sort-columns 316,11714
+(defun sort-fields 223,8234
+(defun sort-fields-1 236,8767
+(defvar sort-fields-syntax-table 192,7190
+(defun sort-lines 158,5909
+(defun sort-numeric-fields 204,7554
+(defun sort-pages 180,6752
+(defun sort-paragraphs 168,6295
+(defun sort-regexp-fields 261,9476
+(defun sort-reorder-buffer 136,5245
+(defun sort-skip-fields 250,9183
+(defun sort-subr 24,908
+
+../lisp/spell.el,174
+(defun spell-buffer 29,1096
+(defvar spell-command 21,822
+(defvar spell-filter 24,893
+(defun spell-region 52,1917
+(defun spell-string 113,3903
+(defun spell-word 38,1490
+
+../lisp/spook.el,243
+(defun pick-random 89,3000
+(defun shuffle-vector 97,3273
+(defun snarf-spooks 71,2385
+(defun spook 52,1846
+(defvar spook-phrase-default-count 42,1601
+(defvar spook-phrases-file 39,1496
+(defvar spook-vector 45,1682
+(defun spook1 64,2223
+
+../lisp/startup.el,363
+(defun command-line 94,3485
+(defun command-line-1 151,5392
+(defvar command-line-processed 51,1881
+(defconst command-switch-alist 61,2249
+(defconst inhibit-default-init 58,2159
+(defconst inhibit-startup-message 53,1959
+(defconst initial-major-mode 74,2747
+(defun normal-top-level 77,2872
+(defvar term-setup-hook 67,2502
+(defvar window-setup-hook 72,2715
+
+../lisp/studly.el,90
+(defun studlify-buffer 45,1192
+(defun studlify-region 3,32
+(defun studlify-word 36,907
+
+../lisp/subr.el,419
+(defvar ctl-x-map 168,5566
+(defun error 54,2088
+(defvar esc-map 172,5703
+(defvar global-map 163,5390
+(defun momentary-string-display 197,6684
+(defvar mouse-map 176,5845
+(defun one-window-p 21,826
+(defun read-quoted-char 31,1211
+(defun run-hooks 179,5926
+(defun substitute-key-definition 114,3913
+(defun suppress-keymap 67,2424
+(defun undefined 59,2251
+(defun undo-more 235,8119
+(defun undo-start 228,7854
+
+../lisp/sun-cursors.el,859
+(defmacro defcursor 30,1059
+(defun sc::char-at-bit 181,5878
+(defvar sc::cursors 28,1009
+(defun sc::display-icon 167,5493
+(defun sc::edit-icon-help 136,4570
+(defmenu sc::edit-icon-help-menu129,4415
+(defun sc::goto-hotspot 163,5384
+(defun sc::hotspot 158,5279
+(defun sc::make-cursor 124,4259
+(defmenu sc::menu104,3611
+(defun sc::menu-choose-cursor 143,4791
+(defun sc::menu-function 101,3524
+(defun sc::menu-item-for-cursor 154,5154
+(defun sc::pack-buffer-to-cursor 139,4679
+(defun sc::pack-buffer-to-icon 184,5953
+(defun sc::pack-one-char 201,6528
+(defun sc::pack-one-line 193,6228
+(defun sc::pic-ins-at-mouse 93,3255
+(defun sc::quit-edit 119,4137
+(defcursor sc:box 53,1781
+(defun sc:edit-cursor 77,2605
+(defcursor sc:fat-left-arrow 49,1635
+(defcursor sc:hourglass 57,1899
+(defcursor sc:right-arrow 43,1467
+(defun sc:set-cursor 63,2089
+
+../lisp/sun-fns.el,2722
+(defvar *modeline-hit* 462,15450
+(defvar *mouse-drag-window* 111,3737
+(defvar *mouse-drag-x* 112,3770
+(defvar *mouse-drag-y* 113,3797
+(defun Buffer-at-mouse 520,17703
+(defvar buffer-menu-mode-hook 602,20432
+(defvar buffer-modeline-menu 565,18831
+(defun buffer-modeline-menu-cmd 558,18571
+(defconst cursor-pause-milliseconds 60,2309
+(defmenu delete-window-menu370,12622
+(defmenu emacs-menu389,13190
+(defun emacs-menu-eval 401,13566
+(defmenu emacs-quit-menu385,13096
+(defun enable-mouse-in-buffer-list 583,19548
+(defmenu expand-menu366,12485
+(defun fill-some-paragraphs 624,21282
+(defun indicate-region 63,2426
+(defun mini-move-point 451,15054
+(defun mini-set-mark-and-stuff 454,15152
+(defun minibuf-prompt-length 434,14594
+(defmenu minibuffer-menu 421,14152
+(defun minibuffer-menu-eval 428,14370
+(defun modeline-hit 464,15513
+(defun modeline-menu-command 497,16714
+(defun modeline-menu-string 508,17183
+(defun mouse-bottom-to-line 350,11956
+(defun mouse-buffer-bury 525,17819
+(defun mouse-buffer-delete 537,18096
+(defun mouse-buffer-execute 551,18410
+(defun mouse-buffer-mark 544,18255
+(defun mouse-buffer-select 531,17945
+(defun mouse-call-kbd-macro 149,4928
+(defun mouse-copy-thing 222,7417
+(defun mouse-delete-other-windows 289,9861
+(defun mouse-delete-window 293,9994
+(defun mouse-drag-modeline 467,15602
+(defun mouse-drag-move-point 115,3825
+(defun mouse-drag-set-mark-stuff 122,4025
+(defun mouse-exch-pt-and-mark 143,4798
+(defun mouse-expand-horizontally 405,13695
+(defun mouse-expand-vertically 411,13861
+(defun mouse-fill-paragraph 615,21031
+(defun mouse-fill-paragraphs 649,22218
+(defmenu mouse-help-menu374,12747
+(defun mouse-kill-thing 189,6343
+(defun mouse-kill-thing-there 195,6522
+(defun mouse-line-to-bottom 346,11791
+(defun mouse-line-to-middle 354,12119
+(defun mouse-line-to-top 338,11522
+(defun mouse-mark-thing 155,5080
+(defun mouse-middle-to-line 358,12287
+(defun mouse-move-point 77,2785
+(defun mouse-move-thing 230,7721
+(defun mouse-save-thing 204,6823
+(defun mouse-save-thing-there 212,7115
+(defun mouse-save/delete/yank 254,8544
+(defun mouse-scroll-down 314,10692
+(defun mouse-scroll-proportional 318,10809
+(defun mouse-scroll-up 310,10557
+(defun mouse-select-or-drag-move-point 134,4536
+(defun mouse-select-previous-buffer 414,13948
+(defun mouse-select-window 285,9753
+(defun mouse-set-mark 86,3059
+(defun mouse-set-mark-and-select 96,3318
+(defun mouse-set-mark-and-stuff 102,3478
+(defun mouse-split-horizontally 277,9436
+(defun mouse-split-vertically 281,9596
+(defun mouse-top-to-line 342,11658
+(defun mouse-undo 297,10097
+(defun mouse-yank-at-mouse 249,8374
+(defun mouse-yank-at-point 238,8014
+(defun nth-menu-elt 489,16537
+
+../lisp/sun-keys.el,235
+(defun sun-function-keys-bind-key 46,1601
+(defvar sun-function-keys-command-list 39,1385
+(defun sun-function-keys-describe-bindings 53,1839
+(defun sun-function-keys-dispatch 31,1080
+(defun sun-function-keys-write-bindings 61,2155
+
+../lisp/sun-mouse.el,2881
+(defun copy-mousemap 58,1877
+(defvar current-global-mousemap 782,28049
+(defun define-mouse 62,1966
+(defmacro defmenu 591,20974
+(defun describe-mouse-bindings 542,19146
+(defun describe-mouse-briefly 556,19636
+(defun display-host 663,24156
+(defmacro eval-in-buffer 163,5662
+(defmacro eval-in-window 177,6094
+(defmacro eval-in-windows 195,6715
+(defvar extra-click-wait 41,1335
+(defun global-set-mouse 79,2820
+(defun local-set-mouse 87,3229
+(defun logtest 116,4227
+(defun make-mousemap 54,1800
+(defun menu-create 585,20809
+(defun minibuffer-window-p 226,7766
+(defun mouse-code-function-pairs-of-region 478,17053
+(defun mouse-code-to-mouse-list 425,15268
+(defun mouse-event-code 408,14707
+(defun mouse-help 278,9844
+(defun mouse-help-menu 564,19989
+(defun mouse-help-region 570,20277
+(defun mouse-hit-read 297,10486
+(defun mouse-list-to-mouse-code 418,15074
+(defun mouse-lookup 443,15778
+(defun mouse-mask-lookup 452,16116
+(defvar mouse-prefix1 318,11373
+(defvar mouse-prefix2 321,11481
+(defun mouse-region-to-code 414,14942
+(defun mouse-second-hit 325,11591
+(defun mouse-union 462,16464
+(defun mouse-union-first-prefered 473,16837
+(defun mousemap-get 440,15705
+(defun mousemap-set 433,15489
+(defun move-to-loc 209,7250
+(defun one-line-doc-string 493,17580
+(defun owselectionfile 710,25920
+(defvar owselectionfilex 708,25770
+(defun print-mouse-bindings 518,18249
+(defun print-mouse-format 504,17978
+(defvar scrollbar-width 45,1482
+(defconst sm::ButtonBits 126,4410
+(defconst sm::DoubleBits 128,4527
+(defconst sm::ShiftmaskBits 127,4456
+(defconst sm::UpBits 129,4566
+(defun sm::combined-hits 283,9931
+(defun sm::event-bindings 522,18391
+(defun sm::font-size 629,22874
+(defmacro sm::hit-button 135,4723
+(defmacro sm::hit-code 132,4632
+(defmacro sm::hit-delta 151,5342
+(defmacro sm::hit-double 141,4970
+(defmacro sm::hit-shiftmask 138,4841
+(defmacro sm::hit-up 144,5104
+(defmacro sm::hit-up-p 153,5392
+(defmacro sm::hit-x 147,5197
+(defmacro sm::hit-y 149,5265
+(defconst sm::keyword-alist 402,14489
+(defmacro sm::loc-w 159,5526
+(defmacro sm::loc-x 160,5571
+(defmacro sm::loc-y 161,5616
+(defun sm::menu-kludge 640,23308
+(defvar sm::menu-kludge-x 635,23131
+(defvar sm::menu-kludge-y 637,23219
+(defun sm::window-region 374,13533
+(defun sm::window-xy 346,12631
+(defun sun-get-frame-data 612,22020
+(defun sun-menu-evaluate 597,21195
+(defun sun-mouse-handler 234,7993
+(defun sun-select-region 751,27050
+(defun sun-yank-selection 742,26800
+(defun sunview-yank-any-selection 697,25316
+(defun sunview-yank-clipboard 675,24554
+(defun sunview-yank-current-selection 686,24891
+(defun sunview-yank-stuff 654,23841
+(defun suspend-emacstool 765,27394
+(defun use-global-mousemap 97,3693
+(defun use-local-mousemap 101,3820
+(defun window-line-end 394,14213
+(defun xv-select-region 735,26591
+(defun xv-yank-selection 724,26238
+
+../lisp/sup-mouse.el,471
+(defconst mouse-2center 42,1593
+(defconst mouse-2left 41,1568
+(defconst mouse-2right 43,1620
+(defconst mouse-3center 46,1672
+(defconst mouse-3left 45,1647
+(defconst mouse-3right 47,1699
+(defconst mouse-center 38,1516
+(defconst mouse-left 37,1492
+(defconst mouse-right 39,1542
+(defun sup-get-tty-num 171,5201
+(defvar sup-mouse-fast-select-window 34,1367
+(defun sup-mouse-report 51,1741
+(defun sup-move-point-to-x-y 185,5629
+(defun sup-pos-to-window 192,5814
+
+../lisp/tabify.el,47
+(defun tabify 37,1320
+(defun untabify 21,815
+
+../lisp/tags.el,570
+(defun file-of-tag 61,2283
+(defun find-tag 132,4254
+(defun find-tag-default 109,3697
+(defun find-tag-other-window 190,6185
+(defun find-tag-tag 122,4029
+(defvar last-tag 27,994
+(defun list-tags 267,9114
+(defun next-file 209,6926
+(defvar next-file-list 206,6853
+(defvar tag-table-files 23,835
+(defun tag-table-files 82,2929
+(defun tags-apropos 288,9737
+(defun tags-loop-continue 225,7515
+(defvar tags-loop-form 221,7360
+(defun tags-query-replace 252,8460
+(defun tags-search 238,7961
+(defun visit-tags-table 30,1053
+(defun visit-tags-table-buffer 44,1586
+
+../lisp/telnet.el,636
+(defun delete-char-or-send-eof 115,4154
+(defun read-password 167,6196
+(defun send-process-next-char 43,1455
+(defun telnet 152,5592
+(defun telnet-c-z 39,1392
+(defun telnet-check-software-type-initialize 66,2349
+(defvar telnet-count 30,1136
+(defun telnet-filter 96,3513
+(defun telnet-initial-filter 79,2870
+(defvar telnet-interrupt-string 29,1075
+(defun telnet-interrupt-subjob 34,1227
+(defun telnet-mode 175,6418
+(defvar telnet-mode-map 27,995
+(defvar telnet-new-line 26,965
+(defvar telnet-prompt-pattern 28,1024
+(defvar telnet-remote-echoes 32,1192
+(defvar telnet-replace-c-g 31,1160
+(defun telnet-send-input 122,4380
+
+../lisp/terminal.el,2466
+(defvar explicit-shell-file-name 899,29072
+(defun te-backward-char 634,20503
+(defun te-beep 653,20800
+(defun te-beginning-of-line 630,20439
+(defun te-clear-rest-of-line 564,18678
+(defun te-clear-rest-of-screen 572,18872
+(defun te-clear-screen 582,19139
+(defun te-delete 645,20666
+(defun te-delete-char 670,21162
+(defun te-delete-lines 613,19967
+(defun te-disable-more-processing 291,9689
+(defun te-do-scrolling 296,9812
+(defun te-do-wrapping 301,9915
+(defun te-down-vertically-or-scroll 531,17834
+(defun te-enable-more-processing 286,9570
+(defun te-escape 136,4951
+(defvar te-escape-command-alist 95,3517
+(defun te-escape-extended-command 200,7027
+(defun te-escape-extended-command-unread 216,7461
+(defun te-escape-help 160,5667
+(defun te-filter 706,21959
+(defun te-flush-pending-output 373,12376
+(defun te-forward-char 639,20585
+(defun te-get-char 837,26751
+(defun te-insert-lines 596,19483
+(defun te-insert-spaces 658,20847
+(defun te-losing-unix 686,21478
+(defun te-more-break 425,14146
+(defun te-more-break-advance-one-line 360,11941
+(defun te-more-break-flush-pending-output 366,12128
+(defun te-more-break-help 341,11204
+(defun te-more-break-resume 334,11009
+(defun te-more-break-unread 322,10582
+(defun te-more-break-unwind 459,15396
+(defun te-move-to-position 549,18298
+(defun te-newline 502,16886
+(defun te-output-tab 692,21569
+(defun te-parse-program-and-args 1045,35551
+(defun te-pass-through 391,13035
+(defun te-pending-output-length 416,13921
+(defun te-process-output 736,23090
+(defun te-quote-arg-for-sh 1115,38219
+(defun te-redisplay-if-necessary 858,27543
+(defun te-sentinel 878,28298
+(defun te-set-escape-char 221,7599
+(defun te-set-more-count 479,16039
+(defun te-set-output-log 241,8236
+(defun te-set-redisplay-interval 307,10028
+(defun te-set-window-start 403,13440
+(defvar te-stty-string 895,28890
+(defun te-stuff-string 233,7972
+(defun te-tofu 263,8946
+(defun te-toggle 269,9039
+(defun te-toggle-more-processing 275,9181
+(defun te-toggle-scrolling 281,9408
+(defun te-update-pending-output-display 866,27885
+(defun terminal-emulator 902,29189
+(defvar terminal-escape-char 32,1146
+(defvar terminal-escape-map 63,2432
+(defvar terminal-map 64,2465
+(defun terminal-mode 1067,36306
+(defvar terminal-more-break-insertion60,2342
+(defvar terminal-more-break-map 65,2491
+(defvar terminal-more-processing 46,1767
+(defvar terminal-redisplay-interval 53,2056
+(defvar terminal-scrolling 40,1522
+
+../lisp/tex-mode.el,1149
+(defun TeX-buffer 421,15163
+(defun TeX-close-LaTeX-block 318,11286
+(defvar TeX-command 49,1923
+(defun TeX-comment-indent 239,9021
+(defun TeX-common-initialization 204,7729
+(defvar TeX-default-mode 45,1770
+(defun TeX-define-common-keys 68,2799
+(defvar TeX-directory 37,1393
+(defvar TeX-dvi-print-command 40,1515
+(defvar TeX-end-of-header 56,2275
+(defun TeX-insert-braces 310,11083
+(defun TeX-insert-quote 246,9196
+(defun TeX-kill-job 426,15314
+(defvar TeX-mode-map 77,3130
+(defvar TeX-mode-syntax-table 65,2722
+(defun TeX-print 449,16033
+(defun TeX-recenter-output-buffer 431,15426
+(defun TeX-region 369,12982
+(defvar TeX-shell-cd-command 58,2381
+(defvar TeX-shell-map 92,3662
+(defun TeX-show-print-queue 457,16326
+(defvar TeX-show-queue-command 42,1619
+(defvar TeX-start-of-header 54,2165
+(defun TeX-start-shell 344,12118
+(defun TeX-terminate-paragraph 296,10623
+(defvar TeX-trailer 52,2063
+(defun TeX-validate-paragraph 286,10408
+(defvar TeX-zap-file 61,2554
+(defun latex-mode 164,6246
+(defun plain-tex-mode 124,4753
+(defun set-buffer-directory 354,12416
+(defun tex-mode 99,3904
+(defun validate-TeX-buffer 266,9721
+
+../lisp/tex-start.el,24
+(defun startline 6,217
+
+../lisp/texinfmt.el,3972
+(defun batch-texinfo-format 1157,40445
+(defvar texinfo-cindex)25,920
+(defun texinfo-description 623,20765
+(defun texinfo-discard-command 311,10083
+(defun texinfo-discard-line 434,13740
+(defun texinfo-discard-line-with-args 1127,39356
+(defun texinfo-do-itemize 641,21366
+(defun texinfo-end-defun 935,30746
+(defun texinfo-end-enumerate 604,20170
+(defun texinfo-end-example 771,25866
+(defun texinfo-end-itemize 590,19742
+(defun texinfo-end-table 631,21041
+(defun texinfo-enumerate 598,19987
+(defun texinfo-enumerate-item 665,22074
+(defvar texinfo-findex)24,896
+(defun texinfo-format-TeX 798,26635
+(defun texinfo-format-\. 547,18263
+(defun texinfo-format-\: 552,18381
+(defun texinfo-format-begin 243,8094
+(defun texinfo-format-begin-end 250,8292
+(defun texinfo-format-buffer 47,1833
+(defun texinfo-format-buffer-1 72,2736
+(defun texinfo-format-bullet 748,24916
+(defun texinfo-format-center 556,18492
+(defun texinfo-format-chapter 495,15987
+(defun texinfo-format-chapter-1 530,17741
+(defun texinfo-format-cindex 834,27566
+(defun texinfo-format-code 731,24319
+(defun texinfo-format-copyright 803,26772
+(defun texinfo-format-ctrl 793,26474
+(defun texinfo-format-defcv-index 1068,36607
+(defun texinfo-format-defcv-type 1065,36522
+(defun texinfo-format-defn 743,24746
+(defun texinfo-format-defop-index 1038,35168
+(defun texinfo-format-defop-type 1035,35083
+(defun texinfo-format-defun 895,29374
+(defun texinfo-format-defun-1 903,29574
+(defun texinfo-format-defunx 900,29509
+(defun texinfo-format-dots 813,27034
+(defun texinfo-format-emph 737,24534
+(defun texinfo-format-end 247,8219
+(defun texinfo-format-example 759,25383
+(defun texinfo-format-exdent 779,26112
+(defun texinfo-format-expand-region 297,9724
+(defun texinfo-format-findex 838,27687
+(defun texinfo-format-iftex 683,22685
+(defun texinfo-format-ignore 703,23294
+(defun texinfo-format-include 1073,36787
+(defun texinfo-format-inforef 483,15408
+(defun texinfo-format-kindex 850,28050
+(defun texinfo-format-menu 429,13608
+(defun texinfo-format-minus 808,26907
+(defun texinfo-format-node 404,12918
+(defun texinfo-format-noop 722,23968
+(defun texinfo-format-parse-args 335,10762
+(defun texinfo-format-parse-defun-args 359,11435
+(defun texinfo-format-parse-line-args 314,10179
+(defun texinfo-format-pindex 842,27808
+(defun texinfo-format-printindex 869,28581
+(defun texinfo-format-pxref 472,15092
+(defun texinfo-format-refill 818,27166
+(defun texinfo-format-region 123,4239
+(defun texinfo-format-scan 206,6714
+(defun texinfo-format-section 507,16589
+(defun texinfo-format-sectionpad 536,17968
+(defun texinfo-format-setfilename 388,12354
+(defun texinfo-format-sp 823,27296
+(defun texinfo-format-subsection 517,17106
+(defun texinfo-format-subsubsection 527,17668
+(defvar texinfo-format-syntax-table 21,830
+(defun texinfo-format-tex 689,22862
+(defun texinfo-format-tindex 846,27929
+(defun texinfo-format-titlepage 695,23047
+(defun texinfo-format-var 711,23526
+(defun texinfo-format-vindex 830,27445
+(defun texinfo-format-xref 459,14679
+(defun texinfo-ftable 617,20580
+(defun texinfo-index 853,28118
+(defconst texinfo-indexvar-alist860,28316
+(defun texinfo-item 655,21754
+(defun texinfo-itemize 585,19566
+(defun texinfo-itemize-item 659,21888
+(defvar texinfo-kindex)28,992
+(defvar texinfo-last-node)29,1016
+(defvar texinfo-node-names)30,1043
+(defun texinfo-parse-arg-discard 307,9982
+(defun texinfo-parse-expanded-arg 274,9003
+(defun texinfo-parse-line-arg 256,8494
+(defvar texinfo-pindex)26,944
+(defun texinfo-pop-stack 575,19212
+(defun texinfo-print-index 881,28968
+(defun texinfo-push-stack 570,19081
+(defvar texinfo-region-buffer-name 120,4117
+(defun texinfo-sort-region 1133,39624
+(defun texinfo-sort-startkeyfun 1141,39909
+(defun texinfo-subindex 1096,37732
+(defun texinfo-table 612,20411
+(defun texinfo-table-item 673,22342
+(defvar texinfo-tindex)27,968
+(defun texinfo-unsupported 1153,40308
+(defvar texinfo-vindex)23,872
+
+../lisp/texinfo.el,481
+(defvar texinfo-heading-pattern157,5954
+(defun texinfo-insert-@code 90,3245
+(defun texinfo-insert-@dfn 84,3111
+(defun texinfo-insert-@end 79,2996
+(defun texinfo-insert-@item 73,2867
+(defun texinfo-insert-@node 65,2605
+(defun texinfo-insert-@samp 59,2468
+(defun texinfo-insert-@var 53,2334
+(defun texinfo-insert-braces 96,3382
+(defun texinfo-mode 103,3581
+(defvar texinfo-mode-map 36,1486
+(defvar texinfo-mode-syntax-table 21,825
+(defun texinfo-show-structure 162,6173
+
+../lisp/text-mode.el,355
+(define-abbrev-table 'text-mode-abbrev-table 26,981
+(defun center-line 114,3875
+(defun center-paragraph 88,3230
+(defun center-region 99,3521
+(defun indented-text-mode 71,2531
+(defvar indented-text-mode-map 63,2228
+(defun text-mode 50,1755
+(defvar text-mode-abbrev-table 24,903
+(defvar text-mode-map 35,1292
+(defvar text-mode-syntax-table 21,824
+
+../lisp/time.el,256
+(defun display-time 32,1176
+(defun display-time-filter 66,2487
+(defvar display-time-interval 27,1052
+(defvar display-time-mail-file 21,844
+(defvar display-time-process 25,1017
+(defun display-time-sentinel 58,2231
+(defvar display-time-string 30,1142
+
+../lisp/uncompress.el,77
+(defun find-compressed-version 18,670
+(defun uncompress-while-visiting 1,0
+
+../lisp/underline.el,67
+(defun underline-region 21,843
+(defun ununderline-region 36,1315
+
+../lisp/undigest.el,41
+(defun undigestify-rmail-message 22,842
+
+../lisp/unused.el,163
+(defun backward-to-word 28,908
+(defun forward-to-word 21,629
+(defun mark-beginning-of-buffer 5,197
+(defun mark-end-of-buffer 10,321
+(defun upcase-char 15,433
+
+../lisp/userlock.el,178
+(defun ask-user-about-lock 28,1057
+(defun ask-user-about-lock-help 63,2287
+(defun ask-user-about-supersession-help 110,4036
+(defun ask-user-about-supersession-threat 76,2806
+
+../lisp/version.el,136
+(defconst emacs-build-system 29,1095
+(defconst emacs-build-time 26,1004
+(defconst emacs-version 23,924
+(defun emacs-version 31,1140
+
+../lisp/vi.el,4775
+(defun vi-abort-ins 709,29395
+(defun vi-adjust-window 1267,50838
+(defun vi-append-at-end-of-line 564,24202
+(defun vi-ask-for-info 1328,53133
+(defun vi-back-to-old-mode 79,3462
+(defun vi-backward-blank-delimited-word 1172,47392
+(defun vi-backward-find-char 875,35443
+(defun vi-backward-kill-line 701,29198
+(defun vi-backward-upto-char 887,35856
+(defun vi-backward-windowfull 718,29651
+(defun vi-beginning-of-buffer 618,25679
+(defun vi-call-named-change-or-macro 1308,52331
+(defun vi-change-case 1315,52707
+(defun vi-change-rest-of-line 569,24368
+(defun vi-char-argument 780,31704
+(defvar vi-com-map 95,3971
+(defun vi-debugging 69,3164
+(defun vi-delete-op 1028,41653
+(defun vi-digit-argument 816,33136
+(defun vi-ding(449,19935
+(defun vi-do-old-mode-C-c-command 1375,55045
+(defun vi-effective-range 999,40370
+(defun vi-end-of-blank-delimited-word 1184,47827
+(defun vi-end-of-insert-state 510,22062
+(defun vi-end-of-word 899,36275
+(defun vi-ex-cmd 464,20239
+(defun vi-execute-op 964,38697
+(defun vi-expose-line-above 775,31549
+(defun vi-expose-line-below 734,30163
+(defun vi-find-char 847,34349
+(defun vi-find-matching-paren 1165,47141
+(defun vi-first-redo-insertion 526,22716
+(defun vi-forward-blank-delimited-word 1178,47608
+(defun vi-forward-find-char 881,35651
+(defun vi-forward-upto-char 893,36067
+(defun vi-forward-windowfull 739,30316
+(defun vi-forward-word 1208,48555
+(defun vi-get-mark 1149,46583
+(defun vi-goto-char-mark 811,33006
+(defun vi-goto-column 1277,51253
+(defun vi-goto-command-state 542,23584
+(defun vi-goto-insert-state 494,21249
+(defun vi-goto-line 611,25494
+(defun vi-goto-line-mark 806,32867
+(defun vi-goto-mark 791,32224
+(defun vi-home-window-line 1190,48060
+(defun vi-indent-op 1132,45934
+(defvar vi-ins-length 311,14205
+(defvar vi-ins-overwrt-p 317,14365
+(defvar vi-ins-point 308,14113
+(defvar vi-ins-prefix-code 320,14455
+(defvar vi-ins-repetition 314,14274
+(defun vi-insert-after 598,25165
+(defun vi-insert-before 606,25370
+(defun vi-insert-before-first-nonwhite 574,24527
+(defvar vi-insert-state 333,14960
+(defun vi-isearch-backward 638,26303
+(defun vi-isearch-forward 628,25949
+(defun vi-join-lines 690,28813
+(defun vi-kill-char 1231,49344
+(defun vi-kill-line 553,23909
+(defun vi-kill-region 559,24097
+(defvar vi-last-change-command 326,14677
+(defvar vi-last-find-char 323,14565
+(defvar vi-last-shell-command 330,14841
+(defun vi-last-window-line 1196,48234
+(defun vi-locate-def 1412,56381
+(defvar vi-mark-alist 299,13846
+(defun vi-mark-lines 1356,54319
+(defun vi-mark-region 1338,53524
+(defun vi-middle-window-line 1202,48415
+(defun vi-mode 387,16886
+(defvar vi-mode-old-case-fold 352,15524
+(defvar vi-mode-old-local-map 343,15263
+(defvar vi-mode-old-major-mode 349,15438
+(defvar vi-mode-old-mode-name 346,15352
+(defun vi-mode-setup 361,15755
+(defun vi-more-redo-insertion 535,23228
+(defun vi-name-last-change-or-macro 1292,51553
+(defun vi-narrow-op 1141,46284
+(defun vi-next-line 747,30517
+(defun vi-next-line-first-nonwhite 755,30830
+(defun vi-open-above 579,24666
+(defun vi-open-below 588,24907
+(defun vi-operator 941,37607
+(defun vi-prefix-char-value 934,37435
+(defun vi-prefix-numeric-value 831,33656
+(defun vi-previous-line-first-nonwhite 761,31078
+(defun vi-put-after 1098,44523
+(defun vi-put-before 1068,43200
+(defun vi-query-replace 1255,50426
+(defun vi-quote-words 1393,55642
+(defun vi-raw-numeric-prefix 827,33528
+(defun vi-readonly-mode 90,3834
+(defun vi-redo-last-change-command 1219,48893
+(defun vi-repeat-command-of 992,40101
+(defun vi-repeat-last-find-char 866,35078
+(defun vi-repeat-last-search 666,27549
+(defun vi-replace 1261,50633
+(defun vi-replace-1-char 907,36532
+(defun vi-replace-chars 915,36835
+(defvar vi-replaced-string 461,20173
+(defvar vi-replacing-string 462,20205
+(defun vi-reverse-last-find-char 838,33934
+(defun vi-reverse-last-search 676,28052
+(defun vi-save-all-and-exit 454,19990
+(defvar vi-scroll-amount 302,13934
+(defun vi-scroll-down-window 726,29856
+(defun vi-scroll-up-window 767,31244
+(defun vi-search-backward 657,27103
+(defun vi-search-forward 648,26662
+(defvar vi-search-last-command 340,15146
+(defun vi-set-last-change-command 1215,48743
+(defun vi-set-mark 1153,46718
+(defun vi-shell-op 1103,44654
+(defun vi-shift-op 1117,45323
+(defvar vi-shift-width 305,14046
+(defun vi-split-open-line 1432,57083
+(defun vi-string-end-with-nl-p 1063,42991
+(defun vi-substitute-chars 921,36971
+(defun vi-substitute-lines 929,37246
+(defun vi-switch-mode 29,1472
+(defvar vi-tilde-map 44,2182
+(defun vi-transpose-objects 1237,49534
+(defun vi-undefined 481,20931
+(defun vi-unimplemented 487,21082
+(defun vi-verify-spelling 1362,54465
+(defun vi-yank-line 1056,42716
+(defun vi-yank-op 1042,42174
+
+../lisp/view.el,870
+(defun View-back-to-mark 334,13759
+(defun View-goto-line 240,9704
+(defun View-next-line 364,14665
+(defun View-previous-line 359,14516
+(defun View-scroll-lines-backward 294,11840
+(defun View-scroll-lines-forward 249,9957
+(defun View-scroll-lines-forward-set-scroll-size 273,10822
+(defun View-scroll-one-more-line 288,11646
+(defun View-search-last-regexp-backward 327,13455
+(defun View-search-last-regexp-forward 320,13156
+(defun View-search-regexp-backward 313,12714
+(defun View-search-regexp-forward 303,12201
+(defun View-undefined 189,8292
+(defun view-buffer 112,5108
+(defun view-file 93,4341
+(defun view-helpful-message 180,7886
+(defvar view-hook 199,8535
+(defun view-mode 124,5631
+(defun view-mode-command-loop 202,8624
+(defvar view-mode-map 24,880
+(defun view-scroll-size 196,8438
+(defun view-search 343,14084
+(defun view-window-size 194,8369
+
+../lisp/vip.el,11995
+(defvar ex-addresses 2051,65610
+(defvar ex-append 2090,66294
+(defvar ex-buffer 2057,65705
+(defun ex-command 3062,97289
+(defun ex-copy 2624,83632
+(defvar ex-count 2060,65751
+(defun ex-delete 2655,84610
+(defun ex-edit 2688,85687
+(defvar ex-file 2084,66223
+(defvar ex-flag 2054,65662
+(defvar ex-g-flag 2063,65796
+(defvar ex-g-pat 2075,66060
+(defvar ex-g-variant 2066,65848
+(defun ex-global 2708,86268
+(defun ex-goto 2616,83445
+(defun ex-line 2767,88262
+(defun ex-line-no 3082,97879
+(defun ex-line-subr 2797,89198
+(defvar ex-map 2078,66114
+(defun ex-map 2838,90440
+(defun ex-mark 2815,89772
+(defvar ex-offset 2088,66270
+(defun ex-put 2878,91675
+(defun ex-quit 2886,91914
+(defun ex-read 2895,92160
+(defvar ex-reg-exp 2069,65942
+(defvar ex-repl 2072,66003
+(defun ex-search-address 2460,78615
+(defun ex-set 2921,92876
+(defun ex-shell 2926,92995
+(defun ex-substitute 2931,93068
+(defvar ex-tag 2081,66186
+(defun ex-tag 2995,95140
+(defvar ex-token 2048,65567
+(defvar ex-token-type 2044,65458
+(defun ex-unmap 2863,91173
+(defvar ex-variant 2086,66245
+(defun ex-write 3016,95724
+(defun ex-yank 3041,96594
+(defun vip-Append 844,27757
+(defun vip-ESC 366,12254
+(defvar vip-F-char 78,2478
+(defun vip-Insert 854,28031
+(defun vip-Open-line 882,28781
+(defun vip-P-val 523,17500
+(defun vip-Put-back 1690,53263
+(defun vip-Region 956,30621
+(defun vip-append 834,27467
+(defun vip-append-to-register 545,17977
+(defun vip-backward-Word 1095,34821
+(defun vip-backward-char 1010,32409
+(defun vip-backward-paragraph 1431,45510
+(defun vip-backward-sentence 1413,44960
+(defun vip-backward-word 1055,33638
+(defun vip-beginning-of-line 1106,35191
+(defun vip-binding-of 323,10678
+(defun vip-bol-and-skip-white 1114,35471
+(defun vip-buffer-in-two-windows 1484,46649
+(defconst vip-case-fold-search 99,2915
+(defun vip-change 1758,55392
+(defun vip-change-mode 165,4771
+(defun vip-change-mode-line 226,7238
+(defun vip-change-mode-to-emacs 279,9056
+(defun vip-change-mode-to-insert 274,8937
+(defun vip-change-mode-to-vi 269,8830
+(defun vip-change-subr 1763,55532
+(defun vip-change-to-eol 1166,37234
+(defun vip-check-sub 2101,66544
+(defvar vip-com-point 32,1067
+(defun vip-command-argument 499,16859
+(defun vip-copy-keymap 159,4663
+(defun vip-copy-region-as-kill 220,7017
+(defun vip-ctl-c 371,12364
+(defun vip-ctl-c-equivalent 1876,58802
+(defun vip-ctl-h 381,12592
+(defun vip-ctl-key-equivalent 1886,59052
+(defun vip-ctl-x 376,12478
+(defun vip-ctl-x-equivalent 1881,58927
+(defvar vip-current-major-mode 50,1691
+(defvar vip-current-mode 38,1239
+(defvar vip-d-char 72,2346
+(defvar vip-d-com 62,2037
+(defun vip-default-ex-addresses 2383,75946
+(defun vip-delete-backward-char 1724,54443
+(defun vip-delete-backward-word 1899,59392
+(defun vip-delete-char 1710,53970
+(defun vip-describe-arg 481,16302
+(defun vip-digit-argument 493,16675
+(defvar vip-emacs-local-map 13,455
+(defvar vip-emacs-mode-line-buffer-identification 44,1422
+(defvar vip-emacs-old-commands 16,543
+(defun vip-end-of-Word 1082,34431
+(defun vip-end-of-word 1041,33291
+(defun vip-end-with-a-newline-p 794,26046
+(defun vip-enlarge-region 754,24825
+(defun vip-escape-to-emacs 338,11196
+(defun vip-ex 2274,72532
+(defun vip-exchange-point-and-mark 1865,58553
+(defun vip-execute-com 551,18223
+(defun vip-execute-ex-command 2558,81203
+(defvar vip-f-char 75,2424
+(defvar vip-f-forward 81,2532
+(defvar vip-f-offset 84,2591
+(defun vip-find-char 1192,37870
+(defun vip-find-char-backward 1261,40379
+(defun vip-find-char-forward 1221,38949
+(defun vip-find-file 1631,51518
+(defun vip-find-file-other-window 1639,51738
+(defun vip-forward-Word 1064,33897
+(defun vip-forward-char 1001,32064
+(defun vip-forward-paragraph 1422,45235
+(defun vip-forward-sentence 1404,44689
+(defun vip-forward-word 1022,32784
+(defun vip-get-editor-command 287,9213
+(defun vip-get-ex-address 2394,76325
+(defun vip-get-ex-address-subr 2418,77146
+(defun vip-get-ex-buffer 2473,78979
+(defun vip-get-ex-com-subr 2109,66813
+(defun vip-get-ex-command 2352,75082
+(defun vip-get-ex-count 2499,79708
+(defun vip-get-ex-file 2524,80341
+(defun vip-get-ex-opt-gc 2367,75584
+(defun vip-get-ex-pat 2325,74303
+(defun vip-get-ex-token 2175,69336
+(defun vip-getCom 534,17737
+(defun vip-getcom 528,17610
+(defun vip-global-execute 766,25175
+(defun vip-goto-char-backward 1280,40996
+(defun vip-goto-char-forward 1242,39756
+(defun vip-goto-col 142,4186
+(defun vip-goto-eol 1122,35774
+(defun vip-goto-line 1179,37462
+(defun vip-goto-mark 1825,57243
+(defun vip-goto-mark-and-skip-white 1831,57398
+(defun vip-goto-mark-subr 1837,57602
+(defconst vip-help-in-insert-mode 108,3164
+(defun vip-info-on-file 1647,51980
+(defvar vip-inhibit-startup-message 117,3428
+(defun vip-insert 827,27247
+(defvar vip-insert-local-map 19,628
+(defvar vip-insert-point 26,883
+(defun vip-join-lines 1741,54970
+(defun vip-keyboard-quit 1870,58661
+(defun vip-kill-buffer 1613,50990
+(defun vip-kill-line 1171,37345
+(defvar vip-last-shell-com 56,1871
+(defun vip-line 933,30066
+(defun vip-line-to-bottom 1368,43761
+(defun vip-line-to-middle 1363,43613
+(defun vip-line-to-top 1358,43501
+(defun vip-looking-back 2096,66367
+(defmacro vip-loop 123,3536
+(defun vip-mark-beginning-of-buffer 1800,56560
+(defun vip-mark-end-of-buffer 1807,56742
+(defun vip-mark-point 1814,56912
+(defun vip-message-conditions 358,12014
+(defun vip-mode 234,7555
+(define-key vip-mode-map 1912,59633
+(define-key vip-mode-map 1913,59685
+(define-key vip-mode-map 1914,59735
+(define-key vip-mode-map 1915,59779
+(define-key vip-mode-map 1916,59827
+(define-key vip-mode-map 1917,59879
+(define-key vip-mode-map 1918,59924
+(define-key vip-mode-map 1919,59976
+(define-key vip-mode-map 1920,60023
+(define-key vip-mode-map 1921,60073
+(define-key vip-mode-map 1922,60124
+(define-key vip-mode-map 1923,60181
+(define-key vip-mode-map 1924,60231
+(define-key vip-mode-map 1925,60275
+(define-key vip-mode-map 1926,60329
+(define-key vip-mode-map 1927,60388
+(define-key vip-mode-map 1929,60429
+(define-key vip-mode-map 1930,60471
+(define-key vip-mode-map 1931,60523
+(define-key vip-mode-map 1932,60576
+(define-key vip-mode-map 1933,60628
+(define-key vip-mode-map 1934,60672
+(define-key vip-mode-map 1935,60719
+(define-key vip-mode-map 1936,60758
+(define-key vip-mode-map 1937,60818
+(define-key vip-mode-map 1938,60871
+(define-key vip-mode-map 1939,60923
+(define-key vip-mode-map 1940,60974
+(define-key vip-mode-map 1941,61026
+(define-key vip-mode-map 1942,61082
+(define-key vip-mode-map 1943,61138
+(define-key vip-mode-map 1944,61180
+(define-key vip-mode-map 1946,61231
+(define-key vip-mode-map 1947,61284
+(define-key vip-mode-map 1948,61334
+(define-key vip-mode-map 1949,61384
+(define-key vip-mode-map 1950,61434
+(define-key vip-mode-map 1951,61484
+(define-key vip-mode-map 1952,61534
+(define-key vip-mode-map 1953,61584
+(define-key vip-mode-map 1954,61634
+(define-key vip-mode-map 1955,61684
+(define-key vip-mode-map 1957,61735
+(define-key vip-mode-map 1958,61773
+(define-key vip-mode-map 1959,61820
+(define-key vip-mode-map 1960,61872
+(define-key vip-mode-map 1961,61924
+(define-key vip-mode-map 1962,61976
+(define-key vip-mode-map 1963,62027
+(define-key vip-mode-map 1965,62067
+(define-key vip-mode-map 1966,62109
+(define-key vip-mode-map 1967,62158
+(define-key vip-mode-map 1968,62210
+(define-key vip-mode-map 1969,62255
+(define-key vip-mode-map 1970,62302
+(define-key vip-mode-map 1971,62356
+(define-key vip-mode-map 1972,62401
+(define-key vip-mode-map 1973,62447
+(define-key vip-mode-map 1974,62489
+(define-key vip-mode-map 1975,62535
+(define-key vip-mode-map 1976,62582
+(define-key vip-mode-map 1977,62631
+(define-key vip-mode-map 1978,62680
+(define-key vip-mode-map 1979,62727
+(define-key vip-mode-map 1980,62772
+(define-key vip-mode-map 1981,62816
+(define-key vip-mode-map 1982,62865
+(define-key vip-mode-map 1983,62915
+(define-key vip-mode-map 1984,62980
+(define-key vip-mode-map 1985,63034
+(define-key vip-mode-map 1986,63073
+(define-key vip-mode-map 1987,63131
+(define-key vip-mode-map 1988,63179
+(define-key vip-mode-map 1989,63231
+(define-key vip-mode-map 1990,63276
+(define-key vip-mode-map 1992,63333
+(define-key vip-mode-map 1993,63372
+(define-key vip-mode-map 1994,63424
+(define-key vip-mode-map 1995,63463
+(define-key vip-mode-map 1996,63517
+(define-key vip-mode-map 1997,63556
+(define-key vip-mode-map 1999,63602
+(define-key vip-mode-map 2000,63644
+(define-key vip-mode-map 2001,63693
+(define-key vip-mode-map 2002,63745
+(define-key vip-mode-map 2003,63797
+(define-key vip-mode-map 2004,63844
+(define-key vip-mode-map 2005,63897
+(define-key vip-mode-map 2006,63945
+(define-key vip-mode-map 2007,63994
+(define-key vip-mode-map 2008,64036
+(define-key vip-mode-map 2009,64081
+(define-key vip-mode-map 2010,64130
+(define-key vip-mode-map 2011,64178
+(define-key vip-mode-map 2012,64224
+(define-key vip-mode-map 2013,64271
+(define-key vip-mode-map 2014,64316
+(define-key vip-mode-map 2015,64360
+(define-key vip-mode-map 2016,64399
+(define-key vip-mode-map 2017,64447
+(define-key vip-mode-map 2018,64499
+(define-key vip-mode-map 2019,64552
+(define-key vip-mode-map 2020,64592
+(define-key vip-mode-map 2021,64637
+(define-key vip-mode-map 2022,64685
+(define-key vip-mode-map 2023,64732
+(define-key vip-mode-map 2024,64784
+(define-key vip-mode-map 2025,64832
+(define-key vip-mode-map 2026,64883
+(define-key vip-mode-map 2027,64934
+(define-key vip-mode-map 2028,64985
+(define-key vip-mode-map 2029,65036
+(define-key vip-mode-map 2031,65088
+(define-key vip-mode-map 2032,65142
+(define-key vip-mode-map 2033,65186
+(define-key vip-mode-map 2034,65239
+(define-key vip-mode-map 2035,65278
+(defun vip-next-line 1130,36024
+(defun vip-next-line-at-bol 1139,36316
+(defun vip-nil 2092,66318
+(defun vip-open-line 864,28321
+(defun vip-open-line-at-point 900,29266
+(defconst vip-open-with-indent 105,3087
+(defun vip-other-window 1323,42398
+(defun vip-p-val 517,17350
+(defun vip-paren-match 1376,43914
+(defun vip-prefix-arg-com 406,13459
+(defun vip-prefix-arg-value 393,12935
+(defun vip-previous-line 1148,36619
+(defun vip-previous-line-at-bol 1157,36922
+(defun vip-push-mark-silent 130,3745
+(defun vip-put-back 1666,52466
+(defun vip-query-replace 1775,55781
+(defun vip-quote-region 776,25461
+(defvar vip-quote-string 112,3313
+(defconst vip-re-query-replace 102,2985
+(defconst vip-re-replace 69,2250
+(defconst vip-re-search 90,2715
+(defun vip-read-string 799,26208
+(defun vip-refresh-mode-line 155,4561
+(defun vip-region 948,30407
+(defun vip-repeat 690,22967
+(defun vip-repeat-find 1298,41608
+(defun vip-repeat-find-opposite 1309,41964
+(defun vip-repeat-insert-command 816,26776
+(defun vip-replace-char 964,30837
+(defun vip-replace-char-subr 971,31131
+(defun vip-replace-string 977,31296
+(defvar vip-s-forward 96,2858
+(defvar vip-s-string 93,2808
+(defun vip-scroll 1443,45805
+(defun vip-scroll-back 1454,46021
+(defun vip-scroll-down 1459,46126
+(defun vip-scroll-down-one 1465,46280
+(defun vip-scroll-up 1470,46379
+(defun vip-scroll-up-one 1476,46529
+(defun vip-search 1533,48288
+(defun vip-search-Next 1580,50001
+(defun vip-search-backward 1513,47549
+(defun vip-search-forward 1493,46816
+(defun vip-search-next 1572,49697
+(defconst vip-search-wrap-around 87,2647
+(defconst vip-shift-width 66,2166
+(defun vip-special-prefix-com 710,23848
+(defun vip-string-tail 746,24647
+(defun vip-substitute 913,29596
+(defun vip-substitute-line 925,29943
+(defun vip-switch-to-buffer 1591,50378
+(defun vip-switch-to-buffer-other-window 1602,50673
+(defvar vip-tags-file-name 115,3392
+(defun vip-undo 729,24347
+(defun vip-undo-more 737,24493
+(defvar vip-use-register 59,1949
+(defun vip-version 2037,65338
+(defun vip-window-bottom 1349,43223
+(defun vip-window-middle 1340,42911
+(defun vip-window-top 1331,42638
+(defun vip-yank 1658,52286
+(defun vip-yank-defun 750,24744
+(defun vip-yank-line 939,30237
+
+../lisp/vms-patch.el,223
+(defun auto-save-file-name-p 64,2488
+(defun create-file-buffer 26,947
+(defun make-auto-save-file-name 50,1923
+(defun make-legal-file-name 34,1398
+(defun vms-suspend-hook 78,3068
+(defun vms-suspend-resume-hook 70,2749
+
+../lisp/vmsproc.el,383
+(defun command-kill-line(106,3841
+(defvar command-mode-map 29,1105
+(defvar command-prefix-string 25,974
+(defun command-send-input 78,2790
+(defvar display-subprocess-window 22,856
+(define-key esc-map 112,3973
+(defun start-subprocess 52,1777
+(defun subprocess-command 70,2512
+(defun subprocess-exit 48,1669
+(defun subprocess-input 37,1331
+(defvar subprocess-running 28,1073
+
+../lisp/window.el,292
+(define-key ctl-x-map 45,1670
+(define-key ctl-x-map 46,1722
+(define-key ctl-x-map 47,1776
+(define-key ctl-x-map 48,1832
+(defun enlarge-window-horizontally 35,1407
+(defun shrink-window-horizontally 40,1538
+(defun split-window-horizontally 28,1124
+(defun split-window-vertically 21,838
+
+../lisp/x-menu.el,508
+(defmacro caar 20,778
+(defmacro cdar 23,841
+(defun x-menu-activate 96,3289
+(defun x-menu-add-item 68,2335
+(defvar x-menu-assoc-buffer 44,1625
+(defun x-menu-change-associated-buffer 60,2083
+(defun x-menu-create-menu 49,1762
+(defun x-menu-delete-item 85,2966
+(defvar x-menu-item-spacing 46,1659
+(defvar x-menu-item-width 42,1564
+(defvar x-menu-items-alist 43,1593
+(defvar x-menu-items-per-line 41,1531
+(defvar x-menu-max-width 40,1503
+(defun x-menu-mode 26,904
+(defun x-menu-pick-entry 136,4703
+
+../lisp/x-mouse.el,3355
+(define-key global-map 107,4054
+(define-key global-map 108,4110
+(define-key mouse-map 255,8978
+(define-key mouse-map 256,9035
+(define-key mouse-map 257,9093
+(define-key mouse-map 258,9149
+(define-key mouse-map 259,9208
+(define-key mouse-map 260,9268
+(define-key mouse-map 261,9326
+(define-key mouse-map 262,9385
+(define-key mouse-map 263,9445
+(define-key mouse-map 264,9503
+(define-key mouse-map 265,9562
+(define-key mouse-map 266,9622
+(define-key mouse-map 267,9680
+(define-key mouse-map 268,9741
+(define-key mouse-map 269,9803
+(define-key mouse-map 270,9863
+(define-key mouse-map 271,9924
+(define-key mouse-map 272,9986
+(define-key mouse-map 273,10046
+(define-key mouse-map 274,10107
+(define-key mouse-map 275,10169
+(define-key mouse-map 276,10229
+(define-key mouse-map 277,10292
+(define-key mouse-map 278,10356
+(define-key mouse-map 280,10419
+(define-key mouse-map 281,10475
+(define-key mouse-map 282,10526
+(define-key mouse-map 283,10593
+(define-key mouse-map 284,10646
+(define-key mouse-map 285,10700
+(define-key mouse-map 286,10762
+(defun x-buffer-menu 200,7105
+(defconst x-button-c-left 49,1818
+(defconst x-button-c-left-up 53,1969
+(defconst x-button-c-m-left 73,2743
+(defconst x-button-c-m-left-up 77,2902
+(defconst x-button-c-m-middle 72,2692
+(defconst x-button-c-m-middle-up 76,2847
+(defconst x-button-c-m-right 71,2642
+(defconst x-button-c-m-right-up 75,2793
+(defconst x-button-c-m-s-left 81,3063
+(defconst x-button-c-m-s-left-up 85,3229
+(defconst x-button-c-m-s-middle 80,3009
+(defconst x-button-c-m-s-middle-up 84,3172
+(defconst x-button-c-m-s-right 79,2956
+(defconst x-button-c-m-s-right-up 83,3116
+(defconst x-button-c-middle 48,1769
+(defconst x-button-c-middle-up 52,1917
+(defconst x-button-c-right 47,1721
+(defconst x-button-c-right-up 51,1866
+(defconst x-button-c-s-left 65,2432
+(defconst x-button-c-s-left-up 69,2589
+(defconst x-button-c-s-middle 64,2381
+(defconst x-button-c-s-middle-up 68,2535
+(defconst x-button-c-s-right 63,2331
+(defconst x-button-c-s-right-up 67,2482
+(defconst x-button-left 25,933
+(defconst x-button-left-up 29,1075
+(defconst x-button-m-left 41,1519
+(defconst x-button-m-left-up 45,1670
+(defconst x-button-m-middle 40,1470
+(defconst x-button-m-middle-up 44,1618
+(defconst x-button-m-right 39,1422
+(defconst x-button-m-right-up 43,1567
+(defconst x-button-m-s-left 57,2121
+(defconst x-button-m-s-left-up 61,2278
+(defconst x-button-m-s-middle 56,2070
+(defconst x-button-m-s-middle-up 60,2224
+(defconst x-button-m-s-right 55,2020
+(defconst x-button-m-s-right-up 59,2171
+(defconst x-button-middle 24,887
+(defconst x-button-middle-up 28,1026
+(defconst x-button-right 23,842
+(defconst x-button-right-up 27,978
+(defconst x-button-s-left 33,1220
+(defconst x-button-s-left-up 37,1371
+(defconst x-button-s-middle 32,1171
+(defconst x-button-s-middle-up 36,1319
+(defconst x-button-s-right 31,1123
+(defconst x-button-s-right-up 35,1268
+(defun x-cut-and-wipe-text 193,6918
+(defun x-cut-text 173,6232
+(defun x-flush-mouse-queue 95,3599
+(defun x-help 223,7724
+(defun x-mouse-ignore 197,7052
+(defun x-mouse-keep-one-window 125,4547
+(defun x-mouse-select 110,4167
+(defun x-mouse-select-and-split 130,4715
+(defun x-mouse-set-mark 162,5901
+(defun x-mouse-set-point 135,4890
+(defun x-paste-text 188,6755
+(defvar x-process-mouse-hook 87,3285
+
+../lisp/xscheme.el,4273
+(defun reset-scheme 86,3401
+(defun run-scheme 72,2935
+(defvar scheme-band-name 30,1102
+(defun scheme-debugger-mode 219,8729
+(defun scheme-debugger-mode-commands 235,9298
+(defun scheme-debugger-mode-initialize 230,9132
+(defvar scheme-debugger-mode-map 241,9496
+(defun scheme-debugger-self-insert 249,9812
+(defun scheme-interaction-mode 110,4150
+(defun scheme-interaction-mode-commands 192,7710
+(defun scheme-interaction-mode-initialize 187,7532
+(defvar scheme-interaction-mode-map 197,7937
+(defvar scheme-program-arguments 33,1179
+(defvar scheme-program-name 27,1013
+(defvar xscheme-allow-output-p 456,17075
+(defvar xscheme-allow-pipelined-evaluation 36,1291
+(defun xscheme-cd 825,29369
+(defun xscheme-coerce-prompt 805,28708
+(defvar xscheme-control-g-disabled-p 452,16887
+(defconst xscheme-control-g-synchronization-p 447,16631
+(defun xscheme-debugger-mode-p 263,10260
+(defun xscheme-default-command-line 99,3878
+(defun xscheme-display-process-buffer 761,27281
+(defun xscheme-enable-control-g 758,27202
+(defun xscheme-enter-debugger-mode 254,9959
+(defun xscheme-enter-input-wait 750,26971
+(defun xscheme-enter-interaction-mode 206,8338
+(defun xscheme-evaluation-commands 54,2065
+(defun xscheme-exit-input-wait 754,27087
+(defvar xscheme-filter-input 475,17746
+(defun xscheme-finish-gc 746,26842
+(defun xscheme-goto-output-point 655,23567
+(defun xscheme-guarantee-newlines 639,23214
+(defun xscheme-interrupt-commands 62,2464
+(defun xscheme-message 773,27641
+(defvar xscheme-mode-string 474,17713
+(defun xscheme-modeline-initialize 660,23729
+(defun xscheme-modeline-redisplay 669,24026
+(defun xscheme-output-goto 801,28613
+(defun xscheme-parse-command-line 507,18827
+(defvar xscheme-previous-send 434,16113
+(defun xscheme-process-buffer 539,19648
+(defun xscheme-process-buffer-current-p 547,19899
+(defun xscheme-process-buffer-window 543,19769
+(defvar xscheme-process-command-line 431,16012
+(defun xscheme-process-filter 574,20829
+(defvar xscheme-process-filter-alist676,24205
+(defun xscheme-process-filter-initialize 566,20524
+(defun xscheme-process-filter-output 621,22628
+(defvar xscheme-process-filter-state 437,16210
+(defun xscheme-process-filter:simple-action 725,26126
+(defun xscheme-process-filter:string-action 729,26244
+(defun xscheme-process-running-p 533,19450
+(defun xscheme-process-sentinel 553,20077
+(defvar xscheme-prompt 460,17222
+(defvar xscheme-prompt-alist816,29010
+(defun xscheme-prompt-for-confirmation 830,29496
+(defun xscheme-prompt-for-expression 833,29611
+(defun xscheme-prompt-for-expression-exit 846,30093
+(defvar xscheme-prompt-for-expression-map 837,29770
+(defun xscheme-region-expression-p 852,30311
+(defvar xscheme-runlight-string 473,17676
+(defconst xscheme-runlight:gc 740,26656
+(defconst xscheme-runlight:input 737,26539
+(defconst xscheme-runlight:running 734,26432
+(defvar xscheme-running-p 443,16471
+(defun xscheme-select-process-buffer 307,11735
+(defun xscheme-send-breakpoint-interrupt 381,14278
+(defun xscheme-send-buffer 367,13820
+(defun xscheme-send-char 374,14078
+(defun xscheme-send-control-g-interrupt 391,14573
+(defun xscheme-send-control-u-interrupt 406,15086
+(defun xscheme-send-control-x-interrupt 411,15249
+(defun xscheme-send-current-line 353,13450
+(defun xscheme-send-definition 327,12516
+(defun xscheme-send-interrupt 421,15662
+(defun xscheme-send-next-expression 341,12997
+(defun xscheme-send-previous-expression 347,13223
+(defun xscheme-send-proceed 386,14426
+(defun xscheme-send-region 318,12174
+(defun xscheme-send-string 272,10469
+(defun xscheme-send-string-1 289,11160
+(defun xscheme-send-string-2 295,11366
+(defun xscheme-set-prompt 795,28421
+(defun xscheme-set-prompt-variable 792,28344
+(defun xscheme-set-runlight 665,23912
+(defvar xscheme-signal-death-message 51,1943
+(defun xscheme-start-gc 743,26768
+(defvar xscheme-start-hook 469,17504
+(defun xscheme-start-process 479,17810
+(defvar xscheme-startup-message41,1541
+(defvar xscheme-string-accumulator 463,17288
+(defvar xscheme-string-receiver 466,17399
+(defun xscheme-unsolicited-read-char 770,27592
+(defun xscheme-wait-for-process 528,19351
+(defun xscheme-write-message-1 782,27967
+(defun xscheme-write-value 777,27773
+(defun xscheme-yank-previous-send 301,11585
+
+../lisp/yow.el,113
+(defun psychoanalyze-pinhead 73,2515
+(defun snarf-yows 49,1738
+(defun yow 26,1073
+(defvar yow-vector 48,1683
diff --git a/src/VMSBUILD b/src/VMSBUILD
new file mode 100644
index 00000000000..4b5340a0874
--- /dev/null
+++ b/src/VMSBUILD
@@ -0,0 +1,67 @@
+How to compile, link and build GNU Emacs under VMS.
+
+
+A runnable Emacs on VMS consists of two files, an exe file and
+a map file. (It also refers to a DOC file in the [-.etc] sibling directory.
+These files are made automatically and kept straight by Emacs version number.)
+
+For an Emacs being built and tested, these files are `temacs.exe' and
+`temacs.dump' in this directory.
+
+For an installed Emacs, these files are `emacs.exe' and
+`emacs.dump' in the directory above this one. These names are known
+only in the file `emacs.com', also in that directory.
+
+Before you can run Emacs or compile or build any part of Emacs,
+you must run `emacs.com'. It sets up logical names that are used
+by everything else.
+
+Before compiling anything on VMS, you must copy `config.h-dist' to
+`config.h' and make sure it is set up for VMS, using files `m-vax.h'
+and `s-vms4-4.h'. Also copy `vmspaths.h' to `paths.h'.
+`paths.h-dist' is for Unix only. (On VMS versions before 4.4, the
+file names have `_' in place of `-', and you should use `s-vms.h'
+rather than `s-vms4-4.h'.)
+
+Execute `compile.com' to recompile all files that need recompilation.
+ Alternatively, execute `precomp.com' to define a command `ccom' that
+ can be used to recompile individual files. `ccom' works by executing
+ `ccom.com'.
+
+ If you compile with optimization, note that in compiler version
+ 3.0 there is a bug affecting inline functions. So you must specify
+ /OPTIMIZE=NOINLINE when compiling `dispnew.c'. If you still have problems,
+ try using /NOOPT.
+
+Compilation will give you lots of warnings about symbols longer than 30
+ characters. You must just ignore them. Alternatively, you can
+ compile the C program `vms-pp.c' and run all the .c and .h files
+ through that program and then compile the results.
+ (On VMS versions before 4.4, the program is called `vms_pp.c'.)
+
+ **If you use `vms-pp.c', please save the originals .c and .h files
+ and distribute them rather than the transformed files
+ if you wish to distribute copies of Emacs. Help minimize confusion!**
+
+Execute `link.com' to link the compiled files into `temacs.exe'.
+ This process uses `temacs.opt'. You will get lots of linker warnings
+ telling you that there were compiler warnings. Just ignore them.
+
+Execute `[-.etc]complink.com' to compile and link the files
+ in the [emacs.etc] directory. This must be done before
+ `[-.etc]makedoc.com' can be run.
+
+Execute `[-.etc]makedoc.com' to create or update the file `[-.etc]doc.'.
+ This must be done if that file does not yet exist or if any of
+ the Emacs C sources or preloaded Lisp sources has changed.
+ It must be done before `build.com' is run in order to take effect.
+
+Execute `build.com' to run `temacs.exe', initialize it and preload
+ some Lisp code, and dump the map file `temacs.dump' containing a copy
+ of all the impure storage after initialization.
+
+Execute `testemacs.com' to define the `runtemacs' command
+ to run `temacs.exe' with its map file `temacs.dump'.
+
+To install an Emacs, rename `temacs.dump' as `[-]emacs.dump' and
+ rename `temacs.exe' as `[-]emacs.exe'.
diff --git a/src/XTests.c b/src/XTests.c
deleted file mode 100644
index 9c1d3666bdb..00000000000
--- a/src/XTests.c
+++ /dev/null
@@ -1,189 +0,0 @@
-#include <X11/Xlib.h>
-#include <X11/X.h>
-#include <X11/Xutil.h>
-#include <X11/Xresource.h>
-#include "XTests.h"
-#include <stdio.h>
-
-static Display *dpy;
-
-static void
-quit (dpy)
- Display *dpy;
-{
- XCloseDisplay (dpy);
- exit (0);
-}
-
-static Colormap screen_colormap;
-
-static unsigned long
-obtain_color (color)
- char *color;
-{
- int exists;
- XColor color_def;
-
- if (!screen_colormap)
- screen_colormap = DefaultColormap (dpy, DefaultScreen (dpy));
-
- exists = XParseColor (dpy, screen_colormap, color, &color_def)
- && XAllocColor (dpy, screen_colormap, &color_def);
- if (exists)
- return color_def.pixel;
-
- fprintf (stderr, "Can't get color; using black.");
- return BlackPixel (dpy, DefaultScreen (dpy));
-}
-
-static char *visual_strings[] =
-{
- "StaticGray ",
- "GrayScale ",
- "StaticColor",
- "PseudoColor",
- "TrueColor ",
- "DirectColor"
-};
-
-main (argc,argv)
- int argc;
- char *argv[];
-{
- char *dpy_string;
- int n;
- long mask;
- Visual *my_visual;
- XVisualInfo *vinfo, visual_template;
- XEvent event;
- Window window;
- Screen *scr;
- XGCValues gc_values;
- GC fill_gc, pix_gc, line_xor_gc, line_xor_inv_gc;
- int i;
- int x, y, width, height, geometry, gravity;
- char *geo;
- char default_geo[] = "80x40+0+0";
- int depth;
- Pixmap pix;
- char *string = "Kill the head and the body will die.";
- char dash_list[] = {6, 4, 6, 4};
- int dashes = 4;
-
- if (argc < 2)
- dpy_string = "localhost:0.0";
- else
- dpy_string = argv[1];
-
- if (argc >= 3)
- {
- XSizeHints hints;
-
- printf ("Geometry: %s\t(default: %s)\n", argv[2], default_geo);
- geo = argv[2];
- XWMGeometry (dpy, DefaultScreen (dpy), geo, default_geo,
- 3, &hints, &x, &y, &width, &height, &gravity);
- }
-
- dpy = XOpenDisplay (dpy_string);
- if (!dpy)
- {
- printf ("Can' open display %s\n", dpy_string);
- exit (1);
- }
-
- window = XCreateSimpleWindow (dpy, DefaultRootWindow (dpy),
- 300, 300, 300, 300, 1,
- BlackPixel (dpy, DefaultScreen (dpy)),
- WhitePixel (dpy, DefaultScreen (dpy)));
- XSelectInput (dpy, window, ButtonPressMask | KeyPressMask
- | EnterWindowMask | LeaveWindowMask);
-
- gc_values.foreground = obtain_color ("blue");
- gc_values.background = WhitePixel (dpy, DefaultScreen (dpy));
- fill_gc = XCreateGC (dpy, window, GCForeground | GCBackground,
- &gc_values);
-
- gc_values.foreground = obtain_color ("red");
- gc_values.function = GXor;
- gc_values.line_width = 3;
- gc_values.line_style = LineOnOffDash;
- gc_values.cap_style = CapRound;
- gc_values.join_style = JoinRound;
- line_xor_gc = XCreateGC (dpy, window,
- GCForeground | GCBackground | GCLineStyle
- | GCJoinStyle | GCCapStyle | GCLineWidth
- | GCFunction,
- &gc_values);
- XSetDashes (dpy, line_xor_gc, 0, dash_list, dashes);
-
- gc_values.background = WhitePixel (dpy, DefaultScreen (dpy));
- gc_values.foreground = obtain_color ("blue");
- line_xor_inv_gc = XCreateGC (dpy, window,
- GCForeground | GCBackground
- | GCLineWidth | GCFunction,
- &gc_values);
-
- depth = DefaultDepthOfScreen (ScreenOfDisplay (dpy, DefaultScreen (dpy)));
- pix = XCreateBitmapFromData (dpy, window, page_glyf_bits,
- page_glyf_width, page_glyf_height);
-
- XMapWindow (dpy, window);
- XFlush (dpy);
-
- while (1)
- {
- XNextEvent (dpy, &event);
- switch (event.type)
- {
- case ButtonPress:
-#if 0
- if (event.xbutton.state && ShiftMask)
-#endif
- switch (event.xbutton.button)
- {
- case Button1:
- XDrawLine (dpy, window, line_xor_gc, 25, 75, 125, 75);
- XFlush (dpy);
- XDrawLine (dpy, window, line_xor_gc, 25, 75, 125, 75);
- break;
-
- case Button2:
- XDrawLine (dpy, window, line_xor_gc, 25, 75, 125, 75);
- break;
-
- case Button3:
- XDrawLine (dpy, window, line_xor_gc, 25, 75, 125, 75);
- break;
- }
- break;
-
- case KeyPress:
- {
- char buf[20];
- int n;
- XComposeStatus status;
- KeySym keysym;
-
- n = XLookupString (&event, buf, 20, &keysym,
- (XComposeStatus *) &status);
-
- if (n == 1 && buf[0] == 'q')
- quit (dpy);
- }
- break;
-
- case EnterNotify:
- XCopyPlane (dpy, pix, window, fill_gc, 0, 0,
- page_glyf_width, page_glyf_height, 100, 100, 1L);
- XFillRectangle (dpy, window, fill_gc, 50, 50, 50, 50);
- break;
-
- case LeaveNotify:
- XClearWindow (dpy, window);
- break;
- }
-
- XFlush (dpy);
- }
-}
diff --git a/src/abbrev.c b/src/abbrev.c
index 0412a062bcf..22eda59ddd7 100644
--- a/src/abbrev.c
+++ b/src/abbrev.c
@@ -75,6 +75,7 @@ Lisp_Object Vlast_abbrev_text;
int last_abbrev_point;
+extern Lisp_Object oblookup ();
DEFUN ("make-abbrev-table", Fmake_abbrev_table, Smake_abbrev_table, 0, 0, 0,
"Create a new, empty abbrev table object.")
@@ -99,18 +100,16 @@ DEFUN ("clear-abbrev-table", Fclear_abbrev_table, Sclear_abbrev_table, 1, 1, 0,
}
DEFUN ("define-abbrev", Fdefine_abbrev, Sdefine_abbrev, 3, 5, 0,
- "Define an abbrev in TABLE named NAME, to expand to EXPANSION and call HOOK.\n\
-NAME and EXPANSION are strings.\n\
-To undefine an abbrev, define it with EXPANSION = nil.\n\
-If HOOK is non-nil, it should be a function of no arguments;\n\
-it is called after EXPANSION is inserted.")
+ "Define an abbrev in TABLE named NAME, to expand to EXPANSION or call HOOK.\n\
+NAME and EXPANSION are strings. HOOK is a function or nil.\n\
+To undefine an abbrev, define it with EXPANSION = nil")
(table, name, expansion, hook, count)
Lisp_Object table, name, expansion, hook, count;
{
Lisp_Object sym, oexp, ohook, tem;
CHECK_VECTOR (table, 0);
CHECK_STRING (name, 1);
- if (!NULL (expansion))
+ if (! NULL (expansion))
CHECK_STRING (expansion, 2);
if (NULL (count))
count = make_number (0);
@@ -163,11 +162,9 @@ DEFUN ("define-mode-abbrev", Fdefine_mode_abbrev, Sdefine_mode_abbrev, 2, 2,
DEFUN ("abbrev-symbol", Fabbrev_symbol, Sabbrev_symbol, 1, 2, 0,
"Return the symbol representing abbrev named ABBREV.\n\
-This symbol's name is ABBREV, but it is not the canonical symbol of that name;\n\
-it is interned in an abbrev-table rather than the normal obarray.\n\
-The value is nil if that abbrev is not defined.\n\
+Value is nil if that abbrev is not defined.\n\
Optional second arg TABLE is abbrev table to look it up in.\n\
-The default is to try buffer's mode-specific abbrev table, then global table.")
+Default is try buffer's mode-specific abbrev table, then global table.")
(abbrev, table)
Lisp_Object abbrev, table;
{
@@ -191,8 +188,7 @@ The default is to try buffer's mode-specific abbrev table, then global table.")
DEFUN ("abbrev-expansion", Fabbrev_expansion, Sabbrev_expansion, 1, 2, 0,
"Return the string that ABBREV expands into in the current buffer.\n\
-Optionally specify an abbrev table as second arg;\n\
-then ABBREV is looked up in that table only.")
+Optionally specify an abbrev table; then ABBREV is looked up in that table only.")
(abbrev, table)
Lisp_Object abbrev, table;
{
@@ -206,14 +202,14 @@ then ABBREV is looked up in that table only.")
Returns 1 if an expansion is done. */
DEFUN ("expand-abbrev", Fexpand_abbrev, Sexpand_abbrev, 0, 0, "",
- "Expand the abbrev before point, if there is an abbrev there.\n\
-Effective when explicitly called even when `abbrev-mode' is nil.\n\
+ "Expand the abbrev before point, if it is an abbrev.\n\
+Effective when explicitly called even when abbrev-mode is not enabled.\n\
Returns t if expansion took place.")
()
{
- register char *buffer, *p;
- register int wordstart, wordend, idx;
- int whitecnt;
+ char buffer[200];
+ register char *p = buffer;
+ register int wordstart, idx;
int uccount = 0, lccount = 0;
register Lisp_Object sym;
Lisp_Object expansion, hook, tem;
@@ -232,21 +228,9 @@ Returns t if expansion took place.")
else
wordstart = scan_words (point, -1);
- if (!wordstart)
+ if (!wordstart || point - wordstart >= sizeof buffer || point <= wordstart)
return Qnil;
- wordend = scan_words (wordstart, 1);
- if (!wordend)
- return Qnil;
-
- if (wordend > point)
- wordend = point;
- whitecnt = point - wordend;
- if (wordend <= wordstart)
- return Qnil;
-
- p = buffer = (char *) alloca (wordend - wordstart);
-
for (idx = wordstart; idx < point; idx++)
{
register int c = FETCH_CHAR (idx);
@@ -261,32 +245,34 @@ Returns t if expansion took place.")
sym = oblookup (current_buffer->abbrev_table, buffer, p - buffer);
else
XFASTINT (sym) = 0;
- if (XTYPE (sym) == Lisp_Int || NULL (XSYMBOL (sym)->value))
+ if (XTYPE (sym) == Lisp_Int ||
+ NULL (XSYMBOL (sym)->value))
sym = oblookup (Vglobal_abbrev_table, buffer, p - buffer);
- if (XTYPE (sym) == Lisp_Int || NULL (XSYMBOL (sym)->value))
+ if (XTYPE (sym) == Lisp_Int ||
+ NULL (XSYMBOL (sym)->value))
return Qnil;
- if (INTERACTIVE && !EQ (minibuf_window, selected_window))
+ if (FROM_KBD && !EQ (minibuf_window, selected_window))
{
- SET_PT (wordend);
+ SET_PT (wordstart + p - buffer);
Fundo_boundary ();
}
SET_PT (wordstart);
Vlast_abbrev_text
- = Fbuffer_substring (make_number (wordstart), make_number (wordend));
- del_range (wordstart, wordend);
+ = Fbuffer_substring (make_number (point),
+ make_number (point + (p - buffer)));
+ del_range (point, point + (p - buffer));
/* Now sym is the abbrev symbol. */
Vlast_abbrev = sym;
- last_abbrev_point = wordstart;
+ last_abbrev_point = point;
if (XTYPE (XSYMBOL (sym)->plist) == Lisp_Int)
XSETINT (XSYMBOL (sym)->plist,
XINT (XSYMBOL (sym)->plist) + 1); /* Increment use count */
expansion = XSYMBOL (sym)->value;
- insert_from_string (expansion, 0, XSTRING (expansion)->size);
- SET_PT (point + whitecnt);
+ insert (XSTRING (expansion)->data, XSTRING (expansion)->size);
if (uccount && !lccount)
{
@@ -308,10 +294,14 @@ Returns t if expansion took place.")
else if (uccount)
{
/* Abbrev included some caps. Cap first initial of expansion */
+ int old_zv = ZV;
idx = point;
+ /* Don't let Fcapitalize_word operate on text after point. */
+ ZV = point;
SET_PT (wordstart);
Fcapitalize_word (make_number (1));
SET_PT (idx);
+ ZV = old_zv;
}
hook = XSYMBOL (sym)->function;
@@ -322,15 +312,13 @@ Returns t if expansion took place.")
}
DEFUN ("unexpand-abbrev", Funexpand_abbrev, Sunexpand_abbrev, 0, 0, "",
- "Undo the expansion of the last abbrev that expanded.\n\
-This differs from ordinary undo in that other editing done since then\n\
-is not undone.")
+ "Undo the expansion of the last abbrev that expanded.")
()
{
int opoint = point;
int adjust = 0;
if (last_abbrev_point < BEGV
- || last_abbrev_point > ZV)
+ || last_abbrev_point >= ZV)
return Qnil;
SET_PT (last_abbrev_point);
if (XTYPE (Vlast_abbrev_text) == Lisp_String)
@@ -341,8 +329,8 @@ is not undone.")
XSET (val, Lisp_String, XSYMBOL (Vlast_abbrev)->value);
adjust = XSTRING (val)->size;
del_range (point, point + adjust);
- insert_from_string (Vlast_abbrev_text, 0,
- XSTRING (Vlast_abbrev_text)->size);
+ insert (XSTRING (Vlast_abbrev_text)->data,
+ XSTRING (Vlast_abbrev_text)->size);
adjust -= XSTRING (Vlast_abbrev_text)->size;
Vlast_abbrev_text = Qnil;
}
@@ -393,13 +381,13 @@ describe_abbrev (sym, stream)
DEFUN ("insert-abbrev-table-description",
Finsert_abbrev_table_description, Sinsert_abbrev_table_description,
- 1, 2, 0,
- "Insert before point a full description of abbrev table named NAME.\n\
+ 2, 2, 0,
+ "Insert before point a description of abbrev table named NAME.\n\
NAME is a symbol whose value is an abbrev table.\n\
-If optional 2nd arg HUMAN is non-nil, a human-readable description is inserted.\n\
-Otherwise the description is an expression,\n\
-a call to `define-abbrev-table', which would\n\
-define the abbrev table NAME exactly as it is currently defined.")
+If 2nd arg READABLE is non-nil, a readable description is inserted.\n\
+Otherwise description is an expression,\n\
+a call to define-abbrev-table which would\n\
+define NAME exactly as it is currently defined.")
(name, readable)
Lisp_Object name, readable;
{
@@ -414,19 +402,19 @@ define the abbrev table NAME exactly as it is currently defined.")
if (!NULL (readable))
{
- insert_string ("(");
+ InsStr ("(");
Fprin1 (name, stream);
- insert_string (")\n\n");
+ InsStr (")\n\n");
map_obarray (table, describe_abbrev, stream);
- insert_string ("\n\n");
+ InsStr ("\n\n");
}
else
{
- insert_string ("(define-abbrev-table '");
+ InsStr ("(define-abbrev-table '");
Fprin1 (name, stream);
- insert_string (" '(\n");
+ InsStr (" '(\n");
map_obarray (table, write_abbrev, stream);
- insert_string (" ))\n\n");
+ InsStr (" ))\n\n");
}
return Qnil;
@@ -435,7 +423,7 @@ define the abbrev table NAME exactly as it is currently defined.")
DEFUN ("define-abbrev-table", Fdefine_abbrev_table, Sdefine_abbrev_table,
2, 2, 0,
"Define TABNAME (a symbol) as an abbrev table name.\n\
-Define abbrevs in it according to DEFINITIONS, which is a list of elements\n\
+Define abbrevs in it according to DEFINITIONS, a list of elements\n\
of the form (ABBREVNAME EXPANSION HOOK USECOUNT).")
(tabname, defns)
Lisp_Object tabname, defns;
@@ -472,7 +460,7 @@ of the form (ABBREVNAME EXPANSION HOOK USECOUNT).")
syms_of_abbrev ()
{
DEFVAR_LISP ("abbrev-table-name-list", &Vabbrev_table_name_list,
- "List of symbols whose values are abbrev tables.");
+ "List of symbols whose values are abbrev tables.");
Vabbrev_table_name_list = Fcons (intern ("fundamental-mode-abbrev-table"),
Fcons (intern ("global-abbrev-table"),
Qnil));
@@ -490,36 +478,35 @@ for any particular abbrev defined in both.");
current_buffer->abbrev_table = Vfundamental_mode_abbrev_table;
DEFVAR_LISP ("last-abbrev", &Vlast_abbrev,
- "The abbrev-symbol of the last abbrev expanded. See `abbrev-symbol'.");
+ "The abbrev-symbol of the last abbrev expanded.");
DEFVAR_LISP ("last-abbrev-text", &Vlast_abbrev_text,
"The exact text of the last abbrev expanded.\n\
nil if the abbrev has already been unexpanded.");
DEFVAR_INT ("last-abbrev-location", &last_abbrev_point,
- "The location of the start of the last abbrev expanded.");
+ "The location of the last abbrev expanded.");
Vlast_abbrev = Qnil;
Vlast_abbrev_text = Qnil;
last_abbrev_point = 0;
DEFVAR_LISP ("abbrev-start-location", &Vabbrev_start_location,
- "Buffer position for `expand-abbrev' to use as the start of the abbrev.\n\
+ "Buffer position for expand-abbrev to use as the start of the abbrev.\n\
nil means use the word before point as the abbrev.\n\
-Calling `expand-abbrev' sets this to nil.");
+Set to nil each time expand-abbrev is called.");
Vabbrev_start_location = Qnil;
DEFVAR_LISP ("abbrev-start-location-buffer", &Vabbrev_start_location_buffer,
- "Buffer that `abbrev-start-location' has been set for.\n\
-Trying to expand an abbrev in any other buffer clears `abbrev-start-location'.");
+ "Buffer that abbrev-start-location has been set for.\n\
+Trying to expand an abbrev in any other buffer clears abbrev-start-location.");
Vabbrev_start_location_buffer = Qnil;
DEFVAR_PER_BUFFER ("local-abbrev-table", &current_buffer->abbrev_table,
"Local (mode-specific) abbrev table of current buffer.");
DEFVAR_BOOL ("abbrevs-changed", &abbrevs_changed,
- "Set non-nil by defining or altering any word abbrevs.\n\
-This causes `save-some-buffers' to offer to save the abbrevs.");
+ "Set non-nil by defining or altering any word abbrevs.");
abbrevs_changed = 0;
DEFVAR_BOOL ("abbrev-all-caps", &abbrev_all_caps,
diff --git a/src/acldef.h b/src/acldef.h
new file mode 100644
index 00000000000..cc4085c6aab
--- /dev/null
+++ b/src/acldef.h
@@ -0,0 +1,40 @@
+#define ACL$K_LENGTH 12
+#define ACL$C_LENGTH 12
+#define ACL$C_FILE 1
+#define ACL$C_DEVICE 2
+#define ACL$C_JOBCTL_QUEUE 3
+#define ACL$C_COMMON_EF_CLUSTER 4
+#define ACL$C_LOGICAL_NAME_TABLE 5
+#define ACL$C_PROCESS 6
+#define ACL$C_GROUP_GLOBAL_SECTION 7
+#define ACL$C_SYSTEM_GLOBAL_SECTION 8
+#define ACL$C_ADDACLENT 1
+#define ACL$C_DELACLENT 2
+#define ACL$C_MODACLENT 3
+#define ACL$C_FNDACLENT 4
+#define ACL$C_FNDACETYP 5
+#define ACL$C_DELETEACL 6
+#define ACL$C_READACL 7
+#define ACL$C_ACLLENGTH 8
+#define ACL$C_READACE 9
+#define ACL$C_RLOCK_ACL 10
+#define ACL$C_WLOCK_ACL 11
+#define ACL$C_UNLOCK_ACL 12
+#define ACL$S_ADDACLENT 255
+#define ACL$S_DELACLENT 255
+#define ACL$S_MODACLENT 255
+#define ACL$S_FNDACLENT 255
+#define ACL$S_FNDACETYP 255
+#define ACL$S_DELETEACL 255
+#define ACL$S_READACL 512
+#define ACL$S_ACLLENGTH 4
+#define ACL$S_READACE 255
+#define ACL$S_RLOCK_ACL 4
+#define ACL$S_WLOCK_ACL 4
+#define ACL$S_UNLOCK_ACL 4
+#define ACL$S_ACLDEF 16
+#define ACL$L_FLINK 0
+#define ACL$L_BLINK 4
+#define ACL$W_SIZE 8
+#define ACL$B_TYPE 10
+#define ACL$L_LIST 12
diff --git a/src/alloc.c b/src/alloc.c
new file mode 100644
index 00000000000..06b7b818f7f
--- /dev/null
+++ b/src/alloc.c
@@ -0,0 +1,1581 @@
+/* Storage allocation and gc for GNU Emacs Lisp interpreter.
+ Copyright (C) 1985, 1986 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#include "config.h"
+#include "lisp.h"
+#ifndef standalone
+#include "buffer.h"
+#include "window.h"
+#endif
+
+#define max(A,B) ((A) > (B) ? (A) : (B))
+
+/* Macro to verify that storage intended for Lisp objects is not
+ out of range to fit in the space for a pointer.
+ ADDRESS is the start of the block, and SIZE
+ is the amount of space within which objects can start. */
+#define VALIDATE_LISP_STORAGE(address, size) \
+do \
+ { \
+ Lisp_Object val; \
+ XSET (val, Lisp_Cons, (char *) address + size); \
+ if ((char *) XCONS (val) != (char *) address + size) \
+ { \
+ free (address); \
+ memory_full (); \
+ } \
+ } while (0)
+
+/* Number of bytes of consing done since the last gc */
+int consing_since_gc;
+
+/* Number of bytes of consing since gc before another gc should be done. */
+int gc_cons_threshold;
+
+/* value of consing_since_gc when undos were last truncated. */
+int consing_at_last_truncate;
+
+/* Nonzero during gc */
+int gc_in_progress;
+
+#ifndef VIRT_ADDR_VARIES
+extern
+#endif /* VIRT_ADDR_VARIES */
+ int malloc_sbrk_used;
+
+#ifndef VIRT_ADDR_VARIES
+extern
+#endif /* VIRT_ADDR_VARIES */
+ int malloc_sbrk_unused;
+
+/* Two thresholds controlling how much undo information to keep. */
+int undo_threshold;
+int undo_high_threshold;
+
+/* Non-nil means defun should do purecopy on the function definition */
+Lisp_Object Vpurify_flag;
+
+/* Argument we give to Fsignal when memory is full.
+ Preallocated since perhaps we can't allocate it when memory is full. */
+Lisp_Object memory_exhausted_message;
+
+#ifndef HAVE_SHM
+#ifdef VMS
+int pure[PURESIZE / sizeof (int)]; /*no need to initialize - wasted space*/
+#else
+int pure[PURESIZE / sizeof (int)] = {0,}; /* Force it into data space! */
+#endif /* NOT VMS */
+#define PUREBEG (char *) pure
+#else
+#define pure PURE_SEG_BITS /* Use shared memory segment */
+#define PUREBEG (char *)PURE_SEG_BITS
+#endif /* not HAVE_SHM */
+
+/* Index in pure at which next pure object will be allocated. */
+int pureptr;
+
+/* If nonzero, this is a warning delivered by malloc and not yet displayed. */
+char *pending_malloc_warning;
+
+Lisp_Object
+malloc_warning_1 (str)
+ Lisp_Object str;
+{
+ Fprinc (str, Vstandard_output);
+ write_string ("\nKilling some buffers may delay running out of memory.\n", -1);
+ write_string ("However, certainly by the time you receive the 95% warning,\n", -1);
+ write_string ("you should clean up, kill this Emacs, and start a new one.", -1);
+ return Qnil;
+}
+
+/* malloc calls this if it finds we are near exhausting storage */
+malloc_warning (str)
+ char *str;
+{
+ pending_malloc_warning = str;
+}
+
+display_malloc_warning ()
+{
+ register Lisp_Object val;
+
+ val = build_string (pending_malloc_warning);
+ pending_malloc_warning = 0;
+ internal_with_output_to_temp_buffer (" *Danger*", malloc_warning_1, val);
+}
+
+/* Called if malloc returns zero */
+memory_full ()
+{
+ while (1)
+ Fsignal (Qerror, memory_exhausted_message);
+}
+
+/* like malloc and realloc but check for no memory left */
+
+long *
+xmalloc (size)
+ int size;
+{
+ register long *val;
+ /* Avoid failure if malloc (0) returns 0. */
+ if (size == 0)
+ size = 1;
+ val = (long *) malloc (size);
+ if (!val) memory_full ();
+ return val;
+}
+
+long *
+xrealloc (block, size)
+ long *block;
+ int size;
+{
+ register long *val;
+ /* Avoid failure if malloc (0) returns 0. */
+ if (size == 0)
+ size = 1;
+ val = (long *) realloc (block, size);
+ if (!val) memory_full ();
+ return val;
+}
+
+/* Allocation of cons cells */
+/* We store cons cells inside of cons_blocks, allocating a new
+ cons_block with malloc whenever necessary. Cons cells reclaimed by
+ GC are put on a free list to be reallocated before allocating
+ any new cons cells from the latest cons_block.
+
+ Each cons_block is just under 1016 bytes long,
+ since malloc really allocates in units of powers of two
+ and uses 8 bytes for its own overhead. */
+
+#define CONS_BLOCK_SIZE \
+ ((1016 - sizeof (struct cons_block *)) / sizeof (struct Lisp_Cons))
+
+struct cons_block
+ {
+ struct cons_block *next;
+ struct Lisp_Cons conses[CONS_BLOCK_SIZE];
+ };
+
+struct cons_block *cons_block;
+int cons_block_index;
+
+struct Lisp_Cons *cons_free_list;
+
+void
+init_cons ()
+{
+ cons_block = (struct cons_block *) malloc (sizeof (struct cons_block));
+ cons_block->next = 0;
+ bzero (cons_block->conses, sizeof cons_block->conses);
+ cons_block_index = 0;
+ cons_free_list = 0;
+}
+
+/* Explicitly free a cons cell. */
+free_cons (ptr)
+ struct Lisp_Cons *ptr;
+{
+ XFASTINT (ptr->car) = (int) cons_free_list;
+ cons_free_list = ptr;
+}
+
+DEFUN ("cons", Fcons, Scons, 2, 2, 0,
+ "Create a new cons, give it CAR and CDR as components, and return it.")
+ (car, cdr)
+ Lisp_Object car, cdr;
+{
+ register Lisp_Object val;
+
+ if (cons_free_list)
+ {
+ XSET (val, Lisp_Cons, cons_free_list);
+ cons_free_list = (struct Lisp_Cons *) XFASTINT (cons_free_list->car);
+ }
+ else
+ {
+ if (cons_block_index == CONS_BLOCK_SIZE)
+ {
+ register struct cons_block *new = (struct cons_block *) malloc (sizeof (struct cons_block));
+ if (!new) memory_full ();
+ VALIDATE_LISP_STORAGE (new, sizeof *new);
+ new->next = cons_block;
+ cons_block = new;
+ cons_block_index = 0;
+ XSET (val, Lisp_Cons, &cons_block->conses[CONS_BLOCK_SIZE - 1]);
+ }
+ XSET (val, Lisp_Cons, &cons_block->conses[cons_block_index++]);
+ }
+ XCONS (val)->car = car;
+ XCONS (val)->cdr = cdr;
+ consing_since_gc += sizeof (struct Lisp_Cons);
+ return val;
+}
+
+DEFUN ("list", Flist, Slist, 0, MANY, 0,
+ "Return a newly created list whose elements are the arguments (any number).")
+ (nargs, args)
+ int nargs;
+ register Lisp_Object *args;
+{
+ register Lisp_Object len, val, val_tail;
+
+ XFASTINT (len) = nargs;
+ val = Fmake_list (len, Qnil);
+ val_tail = val;
+ while (!NULL (val_tail))
+ {
+ XCONS (val_tail)->car = *args++;
+ val_tail = XCONS (val_tail)->cdr;
+ }
+ return val;
+}
+
+DEFUN ("make-list", Fmake_list, Smake_list, 2, 2, 0,
+ "Return a newly created list of length LENGTH, with each element being INIT.")
+ (length, init)
+ register Lisp_Object length, init;
+{
+ register Lisp_Object val;
+ register int size;
+
+ if (XTYPE (length) != Lisp_Int || XINT (length) < 0)
+ length = wrong_type_argument (Qnatnump, length);
+ size = XINT (length);
+
+ val = Qnil;
+ while (size-- > 0)
+ val = Fcons (init, val);
+ return val;
+}
+
+/* Allocation of vectors */
+
+struct Lisp_Vector *all_vectors;
+
+DEFUN ("make-vector", Fmake_vector, Smake_vector, 2, 2, 0,
+ "Return a newly created vector of length LENGTH, with each element being INIT.")
+ (length, init)
+ register Lisp_Object length, init;
+{
+ register int sizei, index;
+ register Lisp_Object vector;
+ register struct Lisp_Vector *p;
+
+ if (XTYPE (length) != Lisp_Int || XINT (length) < 0)
+ length = wrong_type_argument (Qnatnump, length);
+ sizei = XINT (length);
+
+ p = (struct Lisp_Vector *) malloc (sizeof (struct Lisp_Vector) + (sizei - 1) * sizeof (Lisp_Object));
+ if (p == 0)
+ memory_full ();
+ VALIDATE_LISP_STORAGE (p, 0);
+
+ XSET (vector, Lisp_Vector, p);
+ consing_since_gc += sizeof (struct Lisp_Vector) + (sizei - 1) * sizeof (Lisp_Object);
+
+ p->size = sizei;
+ p->next = all_vectors;
+ all_vectors = p;
+
+ for (index = 0; index < sizei; index++)
+ p->contents[index] = init;
+
+ return vector;
+}
+
+DEFUN ("vector", Fvector, Svector, 0, MANY, 0,
+ "Return a newly created vector with our arguments (any number) as its elements.")
+ (nargs, args)
+ register int nargs;
+ Lisp_Object *args;
+{
+ register Lisp_Object len, val;
+ register int index;
+ register struct Lisp_Vector *p;
+
+ XFASTINT (len) = nargs;
+ val = Fmake_vector (len, Qnil);
+ p = XVECTOR (val);
+ for (index = 0; index < nargs; index++)
+ p->contents[index] = args[index];
+ return val;
+}
+
+/* Allocation of symbols.
+ Just like allocation of conses!
+
+ Each symbol_block is just under 1016 bytes long,
+ since malloc really allocates in units of powers of two
+ and uses 8 bytes for its own overhead. */
+
+#define SYMBOL_BLOCK_SIZE \
+ ((1016 - sizeof (struct symbol_block *)) / sizeof (struct Lisp_Symbol))
+
+struct symbol_block
+ {
+ struct symbol_block *next;
+ struct Lisp_Symbol symbols[SYMBOL_BLOCK_SIZE];
+ };
+
+struct symbol_block *symbol_block;
+int symbol_block_index;
+
+struct Lisp_Symbol *symbol_free_list;
+
+void
+init_symbol ()
+{
+ symbol_block = (struct symbol_block *) malloc (sizeof (struct symbol_block));
+ symbol_block->next = 0;
+ bzero (symbol_block->symbols, sizeof symbol_block->symbols);
+ symbol_block_index = 0;
+ symbol_free_list = 0;
+}
+
+DEFUN ("make-symbol", Fmake_symbol, Smake_symbol, 1, 1, 0,
+ "Return a newly allocated uninterned symbol whose name is NAME.\n\
+Its value and function definition are void, and its property list is NIL.")
+ (str)
+ Lisp_Object str;
+{
+ register Lisp_Object val;
+ register struct Lisp_Symbol *p;
+
+ CHECK_STRING (str, 0);
+
+ if (symbol_free_list)
+ {
+ XSET (val, Lisp_Symbol, symbol_free_list);
+ symbol_free_list
+ = (struct Lisp_Symbol *) XFASTINT (symbol_free_list->value);
+ }
+ else
+ {
+ if (symbol_block_index == SYMBOL_BLOCK_SIZE)
+ {
+ struct symbol_block *new = (struct symbol_block *) malloc (sizeof (struct symbol_block));
+ if (!new) memory_full ();
+ VALIDATE_LISP_STORAGE (new, sizeof *new);
+ new->next = symbol_block;
+ symbol_block = new;
+ symbol_block_index = 0;
+ }
+ XSET (val, Lisp_Symbol, &symbol_block->symbols[symbol_block_index++]);
+ }
+ p = XSYMBOL (val);
+ p->name = XSTRING (str);
+ p->plist = Qnil;
+ p->value = Qunbound;
+ p->function = Qunbound;
+ p->next = 0;
+ consing_since_gc += sizeof (struct Lisp_Symbol);
+ return val;
+}
+
+/* Allocation of markers.
+ Works like allocation of conses. */
+
+#define MARKER_BLOCK_SIZE \
+ ((1016 - sizeof (struct marker_block *)) / sizeof (struct Lisp_Marker))
+
+struct marker_block
+ {
+ struct marker_block *next;
+ struct Lisp_Marker markers[MARKER_BLOCK_SIZE];
+ };
+
+struct marker_block *marker_block;
+int marker_block_index;
+
+struct Lisp_Marker *marker_free_list;
+
+void
+init_marker ()
+{
+ marker_block = (struct marker_block *) malloc (sizeof (struct marker_block));
+ marker_block->next = 0;
+ bzero (marker_block->markers, sizeof marker_block->markers);
+ marker_block_index = 0;
+ marker_free_list = 0;
+}
+
+DEFUN ("make-marker", Fmake_marker, Smake_marker, 0, 0, 0,
+ "Return a newly allocated marker which does not point at any place.")
+ ()
+{
+ register Lisp_Object val;
+ register struct Lisp_Marker *p;
+
+ if (marker_free_list)
+ {
+ XSET (val, Lisp_Marker, marker_free_list);
+ marker_free_list
+ = (struct Lisp_Marker *) XFASTINT (marker_free_list->chain);
+ }
+ else
+ {
+ if (marker_block_index == MARKER_BLOCK_SIZE)
+ {
+ struct marker_block *new = (struct marker_block *) malloc (sizeof (struct marker_block));
+ if (!new) memory_full ();
+ VALIDATE_LISP_STORAGE (new, sizeof *new);
+ new->next = marker_block;
+ marker_block = new;
+ marker_block_index = 0;
+ }
+ XSET (val, Lisp_Marker, &marker_block->markers[marker_block_index++]);
+ }
+ p = XMARKER (val);
+ p->buffer = 0;
+ p->bufpos = 0;
+ p->chain = Qnil;
+ consing_since_gc += sizeof (struct Lisp_Marker);
+ return val;
+}
+
+/* Allocation of strings */
+
+/* Strings reside inside of string_blocks. The entire data of the string,
+ both the size and the contents, live in part of the `chars' component of a string_block.
+ The `pos' component is the index within `chars' of the first free byte.
+
+ first_string_block points to the first string_block ever allocated.
+ Each block points to the next one with its `next' field.
+ The `prev' fields chain in reverse order.
+ The last one allocated is the one currently being filled.
+ current_string_block points to it.
+
+ The string_blocks that hold individual large strings
+ go in a separate chain, started by large_string_blocks. */
+
+
+/* String blocks contain this many useful bytes.
+ 8184 is power of 2, minus 8 for malloc overhead. */
+#define STRING_BLOCK_SIZE (8184 - sizeof (struct string_block_head))
+
+/* A string bigger than this gets its own specially-made string block
+ if it doesn't fit in the current one. */
+#define STRING_BLOCK_OUTSIZE 1024
+
+struct string_block_head
+ {
+ struct string_block *next, *prev;
+ int pos;
+ };
+
+struct string_block
+ {
+ struct string_block *next, *prev;
+ int pos;
+ char chars[STRING_BLOCK_SIZE];
+ };
+
+/* This points to the string block we are now allocating strings. */
+
+struct string_block *current_string_block;
+
+/* This points to the oldest string block, the one that starts the chain. */
+
+struct string_block *first_string_block;
+
+/* Last string block in chain of those made for individual large strings. */
+
+struct string_block *large_string_blocks;
+
+/* If SIZE is the length of a string, this returns how many bytes
+ the string occupies in a string_block (including padding). */
+
+#define STRING_FULLSIZE(SIZE) \
+(((SIZE) + 2 * sizeof (int)) & ~(sizeof (int) - 1))
+
+void
+init_strings ()
+{
+ current_string_block = (struct string_block *) malloc (sizeof (struct string_block));
+ first_string_block = current_string_block;
+ consing_since_gc += sizeof (struct string_block);
+ current_string_block->next = 0;
+ current_string_block->prev = 0;
+ current_string_block->pos = 0;
+ large_string_blocks = 0;
+}
+
+static Lisp_Object make_uninit_string ();
+
+DEFUN ("make-string", Fmake_string, Smake_string, 2, 2, 0,
+ "Return a newly created string of length LENGTH, with each element being INIT.\n\
+Both LENGTH and INIT must be numbers.")
+ (length, init)
+ Lisp_Object length, init;
+{
+ register Lisp_Object val;
+ register unsigned char *p, *end, c;
+
+ if (XTYPE (length) != Lisp_Int || XINT (length) < 0)
+ length = wrong_type_argument (Qnatnump, length);
+ CHECK_NUMBER (init, 1);
+ val = make_uninit_string (XINT (length));
+ c = XINT (init);
+ p = XSTRING (val)->data;
+ end = p + XSTRING (val)->size;
+ while (p != end)
+ *p++ = c;
+ *p = 0;
+ return val;
+}
+
+Lisp_Object
+make_string (contents, length)
+ char *contents;
+ int length;
+{
+ register Lisp_Object val;
+ val = make_uninit_string (length, 0);
+ bcopy (contents, XSTRING (val)->data, length);
+ return val;
+}
+
+Lisp_Object
+build_string (str)
+ char *str;
+{
+ return make_string (str, strlen (str));
+}
+
+static Lisp_Object
+make_uninit_string (length)
+ int length;
+{
+ register Lisp_Object val;
+ register int fullsize = STRING_FULLSIZE (length);
+
+ if (length < 0) abort ();
+
+ if (fullsize <= STRING_BLOCK_SIZE - current_string_block->pos)
+ /* This string can fit in the current string block */
+ {
+ XSET (val, Lisp_String,
+ (struct Lisp_String *) (current_string_block->chars + current_string_block->pos));
+ current_string_block->pos += fullsize;
+ }
+ else if (fullsize > STRING_BLOCK_OUTSIZE)
+ /* This string gets its own string block */
+ {
+ register struct string_block *new
+ = (struct string_block *) malloc (sizeof (struct string_block_head) + fullsize);
+ if (!new) memory_full ();
+ VALIDATE_LISP_STORAGE (new, 0);
+ consing_since_gc += sizeof (struct string_block_head) + fullsize;
+ new->pos = fullsize;
+ new->next = large_string_blocks;
+ large_string_blocks = new;
+ XSET (val, Lisp_String,
+ (struct Lisp_String *) ((struct string_block_head *)new + 1));
+ }
+ else
+ /* Make a new current string block and start it off with this string */
+ {
+ register struct string_block *new
+ = (struct string_block *) malloc (sizeof (struct string_block));
+ if (!new) memory_full ();
+ VALIDATE_LISP_STORAGE (new, sizeof *new);
+ consing_since_gc += sizeof (struct string_block);
+ current_string_block->next = new;
+ new->prev = current_string_block;
+ new->next = 0;
+ current_string_block = new;
+ new->pos = fullsize;
+ XSET (val, Lisp_String,
+ (struct Lisp_String *) current_string_block->chars);
+ }
+
+ XSTRING (val)->size = length;
+ XSTRING (val)->data[length] = 0;
+
+ return val;
+}
+
+/* Must get an error if pure storage is full,
+ since if it cannot hold a large string
+ it may be able to hold conses that point to that string;
+ then the string is not protected from gc. */
+
+Lisp_Object
+make_pure_string (data, length)
+ char *data;
+ int length;
+{
+ register Lisp_Object new;
+ register int size = sizeof (int) + length + 1;
+
+ if (pureptr + size > PURESIZE)
+ error ("Pure Lisp storage exhausted");
+ XSET (new, Lisp_String, PUREBEG + pureptr);
+ XSTRING (new)->size = length;
+ bcopy (data, XSTRING (new)->data, length);
+ XSTRING (new)->data[length] = 0;
+ pureptr += (size + sizeof (int) - 1)
+ / sizeof (int) * sizeof (int);
+ return new;
+}
+
+Lisp_Object
+pure_cons (car, cdr)
+ Lisp_Object car, cdr;
+{
+ register Lisp_Object new;
+
+ if (pureptr + sizeof (struct Lisp_Cons) > PURESIZE)
+ error ("Pure Lisp storage exhausted");
+ XSET (new, Lisp_Cons, PUREBEG + pureptr);
+ pureptr += sizeof (struct Lisp_Cons);
+ XCONS (new)->car = Fpurecopy (car);
+ XCONS (new)->cdr = Fpurecopy (cdr);
+ return new;
+}
+
+Lisp_Object
+make_pure_vector (len)
+ int len;
+{
+ register Lisp_Object new;
+ register int size = sizeof (struct Lisp_Vector) + (len - 1) * sizeof (Lisp_Object);
+
+ if (pureptr + size > PURESIZE)
+ error ("Pure Lisp storage exhausted");
+
+ XSET (new, Lisp_Vector, PUREBEG + pureptr);
+ pureptr += size;
+ XVECTOR (new)->size = len;
+ return new;
+}
+
+DEFUN ("purecopy", Fpurecopy, Spurecopy, 1, 1, 0,
+ "Make a copy of OBJECT in pure storage.\n\
+Recursively copies contents of vectors and cons cells.\n\
+Does not copy symbols.")
+ (obj)
+ register Lisp_Object obj;
+{
+ register Lisp_Object new, tem;
+ register int i;
+
+ if (NULL (Vpurify_flag))
+ return obj;
+
+ if ((PNTR_COMPARISON_TYPE) XPNTR (obj) < (PNTR_COMPARISON_TYPE) ((char *) pure + PURESIZE)
+ && (PNTR_COMPARISON_TYPE) XPNTR (obj) >= (PNTR_COMPARISON_TYPE) pure)
+ return obj;
+
+#ifdef SWITCH_ENUM_BUG
+ switch ((int) XTYPE (obj))
+#else
+ switch (XTYPE (obj))
+#endif
+ {
+ case Lisp_Marker:
+ error ("Attempt to copy a marker to pure storage");
+
+ case Lisp_Cons:
+ return pure_cons (XCONS (obj)->car, XCONS (obj)->cdr);
+
+ case Lisp_String:
+ return make_pure_string (XSTRING (obj)->data, XSTRING (obj)->size);
+
+ case Lisp_Vector:
+ new = make_pure_vector (XVECTOR (obj)->size);
+ for (i = 0; i < XVECTOR (obj)->size; i++)
+ {
+ tem = XVECTOR (obj)->contents[i];
+ XVECTOR (new)->contents[i] = Fpurecopy (tem);
+ }
+ return new;
+
+ default:
+ return obj;
+ }
+}
+
+/* Recording what needs to be marked for gc. */
+
+struct gcpro *gcprolist;
+
+#define NSTATICS 200
+
+int staticidx = 0;
+
+#ifdef __GNUC__
+Lisp_Object *staticvec[NSTATICS] = {0};
+#else
+char staticvec1[NSTATICS * sizeof (Lisp_Object *)] = {0};
+#define staticvec ((Lisp_Object **) staticvec1)
+#endif
+
+/* Put an entry in staticvec, pointing at the variable whose address is given */
+
+void
+staticpro (varaddress)
+ Lisp_Object *varaddress;
+{
+ staticvec[staticidx++] = varaddress;
+ if (staticidx >= NSTATICS)
+ abort ();
+}
+
+struct catchtag
+ {
+ Lisp_Object tag;
+ Lisp_Object val;
+ struct catchtag *next;
+/* jmp_buf jmp; /* We don't need this for GC purposes */
+ };
+
+extern struct catchtag *catchlist;
+
+struct backtrace
+ {
+ struct backtrace *next;
+ Lisp_Object *function;
+ Lisp_Object *args; /* Points to vector of args. */
+ int nargs; /* length of vector */
+ /* if nargs is UNEVALLED, args points to slot holding list of unevalled args */
+ char evalargs;
+ };
+
+extern struct backtrace *backtrace_list;
+
+/* Two flags that are set during GC in the `size' component
+ of a string or vector. On some machines, these flags
+ are defined by the m- file to be different bits. */
+
+/* On vector, means it has been marked.
+ On string size field or a reference to a string,
+ means not the last reference in the chain. */
+
+#ifndef ARRAY_MARK_FLAG
+#define ARRAY_MARK_FLAG ((MARKBIT >> 1) & ~MARKBIT)
+#endif /* no ARRAY_MARK_FLAG */
+
+/* Any slot that is a Lisp_Object can point to a string
+ and thus can be put on a string's reference-chain
+ and thus may need to have its ARRAY_MARK_FLAG set.
+ This includes the slots whose markbits are used to mark
+ the containing objects. */
+
+#if ARRAY_MARK_FLAG == MARKBIT
+you lose
+#endif
+
+int total_conses, total_markers, total_symbols, total_string_size, total_vector_size;
+int total_free_conses, total_free_markers, total_free_symbols;
+
+static void mark_object (), mark_buffer ();
+static void clear_marks (), gc_sweep ();
+static void compact_strings ();
+
+DEFUN ("garbage-collect", Fgarbage_collect, Sgarbage_collect, 0, 0, "",
+ "Reclaim storage for Lisp objects no longer needed.\n\
+Returns info on amount of space in use:\n\
+ ((USED-CONSES . FREE-CONSES) (USED-SYMS . FREE-SYMS)\n\
+ (USED-MARKERS . FREE-MARKERS) USED-STRING-CHARS USED-VECTOR-SLOTS)\n\
+Garbage collection happens automatically if you cons more than\n\
+gc-cons-threshold bytes of Lisp data since previous garbage collection.")
+ ()
+{
+ register struct gcpro *tail;
+ register struct specbinding *bind;
+ struct catchtag *catch;
+ struct handler *handler;
+ register struct backtrace *backlist;
+ register Lisp_Object tem;
+ char *omessage = echo_area_contents;
+
+ register int i;
+
+ if (!noninteractive)
+ message1 ("Garbage collecting...");
+
+ /* Don't keep command history around forever */
+ tem = Fnthcdr (make_number (30), Vcommand_history);
+ if (CONSP (tem))
+ XCONS (tem)->cdr = Qnil;
+ /* Likewise for undo information. */
+ truncate_all_undos ();
+
+ gc_in_progress = 1;
+
+/* clear_marks (); */
+
+ /* In each "large string", set the MARKBIT of the size field.
+ That enables mark_object to recognize them. */
+ {
+ register struct string_block *b;
+ for (b = large_string_blocks; b; b = b->next)
+ ((struct Lisp_String *)(&b->chars[0]))->size |= MARKBIT;
+ }
+
+ /* Mark all the special slots that serve as the roots of accessibility.
+
+ Usually the special slots to mark are contained in particular structures.
+ Then we know no slot is marked twice because the structures don't overlap.
+ In some cases, the structures point to the slots to be marked.
+ For these, we use MARKBIT to avoid double marking of the slot. */
+
+ for (i = 0; i < staticidx; i++)
+ mark_object (staticvec[i]);
+ for (tail = gcprolist; tail; tail = tail->next)
+ for (i = 0; i < tail->nvars; i++)
+ if (!XMARKBIT (tail->var[i]))
+ {
+ mark_object (&tail->var[i]);
+ XMARK (tail->var[i]);
+ }
+ for (bind = specpdl; bind != specpdl_ptr; bind++)
+ {
+ mark_object (&bind->symbol);
+ mark_object (&bind->old_value);
+ }
+ for (catch = catchlist; catch; catch = catch->next)
+ {
+ mark_object (&catch->tag);
+ mark_object (&catch->val);
+ }
+ for (handler = handlerlist; handler; handler = handler->next)
+ {
+ mark_object (&handler->handler);
+ mark_object (&handler->var);
+ }
+ for (backlist = backtrace_list; backlist; backlist = backlist->next)
+ {
+ if (!XMARKBIT (*backlist->function))
+ {
+ mark_object (backlist->function);
+ XMARK (*backlist->function);
+ }
+ if (backlist->nargs == UNEVALLED || backlist->nargs == MANY)
+ i = 0;
+ else
+ i = backlist->nargs - 1;
+ for (; i >= 0; i--)
+ if (!XMARKBIT (backlist->args[i]))
+ {
+ mark_object (&backlist->args[i]);
+ XMARK (backlist->args[i]);
+ }
+ }
+
+ gc_sweep ();
+
+ /* Clear the mark bits that we set in certain root slots. */
+
+ for (tail = gcprolist; tail; tail = tail->next)
+ for (i = 0; i < tail->nvars; i++)
+ XUNMARK (tail->var[i]);
+ for (backlist = backtrace_list; backlist; backlist = backlist->next)
+ {
+ XUNMARK (*backlist->function);
+ if (backlist->nargs == UNEVALLED || backlist->nargs == MANY)
+ i = 0;
+ else
+ i = backlist->nargs - 1;
+ for (; i >= 0; i--)
+ XUNMARK (backlist->args[i]);
+ }
+ XUNMARK (buffer_defaults.name);
+ XUNMARK (buffer_local_symbols.name);
+
+/* clear_marks (); */
+ gc_in_progress = 0;
+
+ consing_since_gc = 0;
+ consing_at_last_truncate = 0;
+ if (gc_cons_threshold < 10000)
+ gc_cons_threshold = 10000;
+
+ if (omessage)
+ message1 (omessage);
+ else if (!noninteractive)
+ message1 ("Garbage collecting...done");
+
+ return Fcons (Fcons (make_number (total_conses),
+ make_number (total_free_conses)),
+ Fcons (Fcons (make_number (total_symbols),
+ make_number (total_free_symbols)),
+ Fcons (Fcons (make_number (total_markers),
+ make_number (total_free_markers)),
+ Fcons (make_number (total_string_size),
+ Fcons (make_number (total_vector_size),
+ Qnil)))));
+}
+
+#if 0
+static void
+clear_marks ()
+{
+ /* Clear marks on all conses */
+ {
+ register struct cons_block *cblk;
+ register int lim = cons_block_index;
+
+ for (cblk = cons_block; cblk; cblk = cblk->next)
+ {
+ register int i;
+ for (i = 0; i < lim; i++)
+ XUNMARK (cblk->conses[i].car);
+ lim = CONS_BLOCK_SIZE;
+ }
+ }
+ /* Clear marks on all symbols */
+ {
+ register struct symbol_block *sblk;
+ register int lim = symbol_block_index;
+
+ for (sblk = symbol_block; sblk; sblk = sblk->next)
+ {
+ register int i;
+ for (i = 0; i < lim; i++)
+ {
+ XUNMARK (sblk->symbols[i].plist);
+ }
+ lim = SYMBOL_BLOCK_SIZE;
+ }
+ }
+ /* Clear marks on all markers */
+ {
+ register struct marker_block *sblk;
+ register int lim = marker_block_index;
+
+ for (sblk = marker_block; sblk; sblk = sblk->next)
+ {
+ register int i;
+ for (i = 0; i < lim; i++)
+ XUNMARK (sblk->markers[i].chain);
+ lim = MARKER_BLOCK_SIZE;
+ }
+ }
+ /* Clear mark bits on all buffers */
+ {
+ register struct buffer *nextb = all_buffers;
+
+ while (nextb)
+ {
+ XUNMARK (nextb->name);
+ nextb = nextb->next;
+ }
+ }
+}
+#endif
+
+/* Mark reference to a Lisp_Object. If the object referred to
+ has not been seen yet, recursively mark all the references contained in it.
+
+ If the object referenced is a short string, the referrencing slot
+ is threaded into a chain of such slots, pointed to from
+ the `size' field of the string. The actual string size
+ lives in the last slot in the chain. We recognize the end
+ because it is < (unsigned) STRING_BLOCK_SIZE. */
+
+static void
+mark_object (objptr)
+ Lisp_Object *objptr;
+{
+ register Lisp_Object obj;
+
+ obj = *objptr;
+ XUNMARK (obj);
+
+ loop:
+
+ if ((PNTR_COMPARISON_TYPE) XPNTR (obj) < (PNTR_COMPARISON_TYPE) ((char *) pure + PURESIZE)
+ && (PNTR_COMPARISON_TYPE) XPNTR (obj) >= (PNTR_COMPARISON_TYPE) pure)
+ return;
+
+#ifdef SWITCH_ENUM_BUG
+ switch ((int) XGCTYPE (obj))
+#else
+ switch (XGCTYPE (obj))
+#endif
+ {
+ case Lisp_String:
+ {
+ register struct Lisp_String *ptr = XSTRING (obj);
+
+ if (ptr->size & MARKBIT)
+ /* A large string. Just set ARRAY_MARK_FLAG. */
+ ptr->size |= ARRAY_MARK_FLAG;
+ else
+ {
+ /* A small string. Put this reference
+ into the chain of references to it.
+ The address OBJPTR is even, so if the address
+ includes MARKBIT, put it in the low bit
+ when we store OBJPTR into the size field. */
+
+ if (XMARKBIT (*objptr))
+ {
+ XFASTINT (*objptr) = ptr->size;
+ XMARK (*objptr);
+ }
+ else
+ XFASTINT (*objptr) = ptr->size;
+ if ((int)objptr & 1) abort ();
+ ptr->size = (int) objptr & ~MARKBIT;
+ if ((int) objptr & MARKBIT)
+ ptr->size ++;
+ }
+ }
+ break;
+
+ case Lisp_Vector:
+ case Lisp_Window:
+ case Lisp_Process:
+ case Lisp_Window_Configuration:
+ {
+ register struct Lisp_Vector *ptr = XVECTOR (obj);
+ register int size = ptr->size;
+ register int i;
+
+ if (size & ARRAY_MARK_FLAG) break; /* Already marked */
+ ptr->size |= ARRAY_MARK_FLAG; /* Else mark it */
+ for (i = 0; i < size; i++) /* and then mark its elements */
+ mark_object (&ptr->contents[i]);
+ }
+ break;
+
+#if 0
+ case Lisp_Temp_Vector:
+ {
+ register struct Lisp_Vector *ptr = XVECTOR (obj);
+ register int size = ptr->size;
+ register int i;
+
+ for (i = 0; i < size; i++) /* and then mark its elements */
+ mark_object (&ptr->contents[i]);
+ }
+ break;
+#endif 0
+
+ case Lisp_Symbol:
+ {
+ register struct Lisp_Symbol *ptr = XSYMBOL (obj);
+ struct Lisp_Symbol *ptrx;
+
+ if (XMARKBIT (ptr->plist)) break;
+ XMARK (ptr->plist);
+ XSETTYPE (*(Lisp_Object *) &ptr->name, Lisp_String);
+ mark_object (&ptr->name);
+ mark_object ((Lisp_Object *) &ptr->value);
+ mark_object (&ptr->function);
+ mark_object (&ptr->plist);
+ ptr = ptr->next;
+ if (ptr)
+ {
+ ptrx = ptr; /* Use pf ptrx avoids compiler bug on Sun */
+ XSETSYMBOL (obj, ptrx);
+ goto loop;
+ }
+ }
+ break;
+
+ case Lisp_Marker:
+ XMARK (XMARKER (obj)->chain);
+ /* DO NOT mark thru the marker's chain.
+ The buffer's markers chain does not preserve markers from gc;
+ instead, markers are removed from the chain when they are freed by gc. */
+ break;
+
+ case Lisp_Cons:
+ case Lisp_Buffer_Local_Value:
+ case Lisp_Some_Buffer_Local_Value:
+ {
+ register struct Lisp_Cons *ptr = XCONS (obj);
+ if (XMARKBIT (ptr->car)) break;
+ XMARK (ptr->car);
+ /* If the cdr is nil, avoid recursion for the car. */
+ if (EQ (ptr->cdr, Qnil))
+ {
+ objptr = &ptr->car;
+ obj = ptr->car;
+ XUNMARK (obj);
+ goto loop;
+ }
+ /* If the cdr is (INTEGER . nil), mark the cdr first,
+ to avoid recursion for the car. This case occurs
+ in every compiled function. */
+ if (XTYPE (ptr->cdr) == Lisp_Cons
+ && XGCTYPE (XCONS (ptr->cdr)->car) == Lisp_Int
+ && EQ (XCONS (ptr->cdr)->cdr, Qnil))
+ {
+ mark_object (&ptr->cdr);
+ objptr = &ptr->car;
+ obj = ptr->car;
+ XUNMARK (obj);
+ goto loop;
+ }
+ mark_object (&ptr->car);
+ objptr = &ptr->cdr;
+ obj = ptr->cdr;
+ goto loop;
+ }
+
+ case Lisp_Buffer:
+ if (!XMARKBIT (XBUFFER (obj)->name))
+ mark_buffer (obj);
+ break;
+
+ case Lisp_Int:
+ case Lisp_Void:
+ case Lisp_Subr:
+ case Lisp_Intfwd:
+ case Lisp_Boolfwd:
+ case Lisp_Objfwd:
+ case Lisp_Buffer_Objfwd:
+ case Lisp_Internal_Stream:
+ /* Don't bother with Lisp_Buffer_Objfwd,
+ since all markable slots in current buffer marked anyway. */
+ /* Don't need to do Lisp_Objfwd, since the places they point
+ are protected with staticpro. */
+ break;
+
+ default:
+ abort ();
+ }
+}
+
+/* Mark the pointers in a buffer structure. */
+
+static void
+mark_buffer (buf)
+ Lisp_Object buf;
+{
+ Lisp_Object tem;
+ register struct buffer *buffer = XBUFFER (buf);
+ register Lisp_Object *ptr;
+
+ /* This is the buffer's markbit */
+ mark_object (&buffer->name);
+ XMARK (buffer->name);
+
+ for (ptr = &buffer->name + 1;
+ (char *)ptr < (char *)buffer + sizeof (struct buffer);
+ ptr++)
+ mark_object (ptr);
+}
+
+/* Find all structures not marked, and free them. */
+
+static void
+gc_sweep ()
+{
+ total_string_size = 0;
+ compact_strings ();
+
+ /* Put all unmarked conses on free list */
+ {
+ register struct cons_block *cblk;
+ register int lim = cons_block_index;
+ register int num_free = 0, num_used = 0;
+
+ cons_free_list = 0;
+
+ for (cblk = cons_block; cblk; cblk = cblk->next)
+ {
+ register int i;
+ for (i = 0; i < lim; i++)
+ if (!XMARKBIT (cblk->conses[i].car))
+ {
+ XFASTINT (cblk->conses[i].car) = (int) cons_free_list;
+ num_free++;
+ cons_free_list = &cblk->conses[i];
+ }
+ else
+ {
+ num_used++;
+ XUNMARK (cblk->conses[i].car);
+ }
+ lim = CONS_BLOCK_SIZE;
+ }
+ total_conses = num_used;
+ total_free_conses = num_free;
+ }
+
+ /* Put all unmarked symbols on free list */
+ {
+ register struct symbol_block *sblk;
+ register int lim = symbol_block_index;
+ register int num_free = 0, num_used = 0;
+
+ symbol_free_list = 0;
+
+ for (sblk = symbol_block; sblk; sblk = sblk->next)
+ {
+ register int i;
+ for (i = 0; i < lim; i++)
+ if (!XMARKBIT (sblk->symbols[i].plist))
+ {
+ XFASTINT (sblk->symbols[i].value) = (int) symbol_free_list;
+ symbol_free_list = &sblk->symbols[i];
+ num_free++;
+ }
+ else
+ {
+ num_used++;
+ sblk->symbols[i].name
+ = XSTRING (*(Lisp_Object *) &sblk->symbols[i].name);
+ XUNMARK (sblk->symbols[i].plist);
+ }
+ lim = SYMBOL_BLOCK_SIZE;
+ }
+ total_symbols = num_used;
+ total_free_symbols = num_free;
+ }
+
+#ifndef standalone
+ /* Put all unmarked markers on free list.
+ Dechain each one first from the buffer it points into. */
+ {
+ register struct marker_block *mblk;
+ struct Lisp_Marker *tem1;
+ register int lim = marker_block_index;
+ register int num_free = 0, num_used = 0;
+
+ marker_free_list = 0;
+
+ for (mblk = marker_block; mblk; mblk = mblk->next)
+ {
+ register int i;
+ for (i = 0; i < lim; i++)
+ if (!XMARKBIT (mblk->markers[i].chain))
+ {
+ Lisp_Object tem;
+ tem1 = &mblk->markers[i]; /* tem1 avoids Sun compiler bug */
+ XSET (tem, Lisp_Marker, tem1);
+ if (tem1->buffer)
+ unchain_marker (tem);
+ XFASTINT (mblk->markers[i].chain) = (int) marker_free_list;
+ marker_free_list = &mblk->markers[i];
+ num_free++;
+ }
+ else
+ {
+ num_used++;
+ XUNMARK (mblk->markers[i].chain);
+ }
+ lim = MARKER_BLOCK_SIZE;
+ }
+
+ total_markers = num_used;
+ total_free_markers = num_free;
+ }
+
+ /* Free all unmarked buffers */
+ {
+ register struct buffer *buffer = all_buffers, *prev = 0, *next;
+
+ while (buffer)
+ if (!XMARKBIT (buffer->name))
+ {
+ if (prev)
+ prev->next = buffer->next;
+ else
+ all_buffers = buffer->next;
+ next = buffer->next;
+ free (buffer);
+ buffer = next;
+ }
+ else
+ {
+ XUNMARK (buffer->name);
+ prev = buffer, buffer = buffer->next;
+ }
+ }
+
+#endif standalone
+
+ /* Free all unmarked vectors */
+ {
+ register struct Lisp_Vector *vector = all_vectors, *prev = 0, *next;
+ total_vector_size = 0;
+
+ while (vector)
+ if (!(vector->size & ARRAY_MARK_FLAG))
+ {
+ if (prev)
+ prev->next = vector->next;
+ else
+ all_vectors = vector->next;
+ next = vector->next;
+ free (vector);
+ vector = next;
+ }
+ else
+ {
+ vector->size &= ~ARRAY_MARK_FLAG;
+ total_vector_size += vector->size;
+ prev = vector, vector = vector->next;
+ }
+ }
+
+ /* Free all "large strings" not marked with ARRAY_MARK_FLAG. */
+ {
+ register struct string_block *sb = large_string_blocks, *prev = 0, *next;
+
+ while (sb)
+ if (!(((struct Lisp_String *)(&sb->chars[0]))->size & ARRAY_MARK_FLAG))
+ {
+ if (prev)
+ prev->next = sb->next;
+ else
+ large_string_blocks = sb->next;
+ next = sb->next;
+ free (sb);
+ sb = next;
+ }
+ else
+ {
+ ((struct Lisp_String *)(&sb->chars[0]))->size
+ &= ~ARRAY_MARK_FLAG & ~MARKBIT;
+ total_string_size += ((struct Lisp_String *)(&sb->chars[0]))->size;
+ prev = sb, sb = sb->next;
+ }
+ }
+}
+
+/* Compactify strings, relocate references to them, and
+ free any string blocks that become empty. */
+
+static void
+compact_strings ()
+{
+ /* String block of old strings we are scanning. */
+ register struct string_block *from_sb;
+ /* A preceding string block (or maybe the same one)
+ where we are copying the still-live strings to. */
+ register struct string_block *to_sb;
+ int pos;
+ int to_pos;
+
+ to_sb = first_string_block;
+ to_pos = 0;
+
+ /* Scan each existing string block sequentially, string by string. */
+ for (from_sb = first_string_block; from_sb; from_sb = from_sb->next)
+ {
+ pos = 0;
+ /* POS is the index of the next string in the block. */
+ while (pos < from_sb->pos)
+ {
+ register struct Lisp_String *nextstr
+ = (struct Lisp_String *) &from_sb->chars[pos];
+
+ register struct Lisp_String *newaddr;
+ register int size = nextstr->size;
+
+ /* NEXTSTR is the old address of the next string.
+ Just skip it if it isn't marked. */
+ if ((unsigned) size > STRING_BLOCK_SIZE)
+ {
+ /* It is marked, so its size field is really a chain of refs.
+ Find the end of the chain, where the actual size lives. */
+ while ((unsigned) size > STRING_BLOCK_SIZE)
+ {
+ if (size & 1) size ^= MARKBIT | 1;
+ size = *(int *)size & ~MARKBIT;
+ }
+
+ total_string_size += size;
+
+ /* If it won't fit in TO_SB, close it out,
+ and move to the next sb. Keep doing so until
+ TO_SB reaches a large enough, empty enough string block.
+ We know that TO_SB cannot advance past FROM_SB here
+ since FROM_SB is large enough to contain this string.
+ Any string blocks skipped here
+ will be patched out and freed later. */
+ while (to_pos + STRING_FULLSIZE (size)
+ > max (to_sb->pos, STRING_BLOCK_SIZE))
+ {
+ to_sb->pos = to_pos;
+ to_sb = to_sb->next;
+ to_pos = 0;
+ }
+ /* Compute new address of this string
+ and update TO_POS for the space being used. */
+ newaddr = (struct Lisp_String *) &to_sb->chars[to_pos];
+ to_pos += STRING_FULLSIZE (size);
+
+ /* Copy the string itself to the new place. */
+ if (nextstr != newaddr)
+ bcopy (nextstr, newaddr, size + 1 + sizeof (int));
+
+ /* Go through NEXTSTR's chain of references
+ and make each slot in the chain point to
+ the new address of this string. */
+ size = newaddr->size;
+ while ((unsigned) size > STRING_BLOCK_SIZE)
+ {
+ register Lisp_Object *objptr;
+ if (size & 1) size ^= MARKBIT | 1;
+ objptr = (Lisp_Object *)size;
+
+ size = XFASTINT (*objptr) & ~MARKBIT;
+ if (XMARKBIT (*objptr))
+ {
+ XSET (*objptr, Lisp_String, newaddr);
+ XMARK (*objptr);
+ }
+ else
+ XSET (*objptr, Lisp_String, newaddr);
+ }
+ /* Store the actual size in the size field. */
+ newaddr->size = size;
+ }
+ pos += STRING_FULLSIZE (size);
+ }
+ }
+
+ /* Close out the last string block still used and free any that follow. */
+ to_sb->pos = to_pos;
+ current_string_block = to_sb;
+
+ from_sb = to_sb->next;
+ to_sb->next = 0;
+ while (from_sb)
+ {
+ to_sb = from_sb->next;
+ free (from_sb);
+ from_sb = to_sb;
+ }
+
+ /* Free any empty string blocks further back in the chain.
+ This loop will never free first_string_block, but it is very
+ unlikely that that one will become empty, so why bother checking? */
+
+ from_sb = first_string_block;
+ while (to_sb = from_sb->next)
+ {
+ if (to_sb->pos == 0)
+ {
+ if (from_sb->next = to_sb->next)
+ from_sb->next->prev = from_sb;
+ free (to_sb);
+ }
+ else
+ from_sb = to_sb;
+ }
+}
+
+truncate_all_undos ()
+{
+ register struct buffer *nextb = all_buffers;
+
+ consing_at_last_truncate = consing_since_gc;
+
+ while (nextb)
+ {
+ /* If a buffer's undo list is Qt, that means that undo is
+ turned off in that buffer. Calling truncate_undo_list on
+ Qt tends to return NULL, which effectively turns undo back on.
+ So don't call truncate_undo_list if undo_list is Qt. */
+ if (! EQ (nextb->undo_list, Qt))
+ nextb->undo_list
+ = truncate_undo_list (nextb->undo_list, undo_threshold,
+ undo_high_threshold);
+ nextb = nextb->next;
+ }
+}
+
+/* Initialization */
+
+init_alloc_once ()
+{
+ /* Used to do Vpurify_flag = Qt here, but Qt isn't set up yet! */
+ pureptr = 0;
+ all_vectors = 0;
+ init_strings ();
+ init_cons ();
+ init_symbol ();
+ init_marker ();
+ gcprolist = 0;
+ staticidx = 0;
+ consing_since_gc = 0;
+ gc_cons_threshold = 100000;
+#ifdef VIRT_ADDR_VARIES
+ malloc_sbrk_unused = 1<<22; /* A large number */
+ malloc_sbrk_used = 100000; /* as reasonable as any number */
+#endif /* VIRT_ADDR_VARIES */
+}
+
+init_alloc ()
+{
+ gcprolist = 0;
+}
+
+void
+syms_of_alloc ()
+{
+ memory_exhausted_message = Fcons (build_string ("Memory exhausted"), Qnil);
+ staticpro (&memory_exhausted_message);
+
+ DEFVAR_INT ("gc-cons-threshold", &gc_cons_threshold,
+ "*Number of bytes of consing between garbage collections.");
+
+ DEFVAR_INT ("pure-bytes-used", &pureptr,
+ "Number of bytes of sharable Lisp data allocated so far.");
+
+#if 0
+ DEFVAR_INT ("data-bytes-used", &malloc_sbrk_used,
+ "Number of bytes of unshared memory allocated in this session.");
+
+ DEFVAR_INT ("data-bytes-free", &malloc_sbrk_unused,
+ "Number of bytes of unshared memory remaining available in this session.");
+#endif
+
+ DEFVAR_LISP ("purify-flag", &Vpurify_flag,
+ "Non-nil means loading Lisp code in order to dump an executable.");
+
+ DEFVAR_INT ("undo-threshold", &undo_threshold,
+ "Keep no more undo information once it exceeds this size.\n\
+This threshold is applied when garbage collection happens.\n\
+The size is counted as the number of bytes occupied,\n\
+which includes both saved text and other data.");
+ undo_threshold = 15000;
+ DEFVAR_INT ("undo-high-threshold", &undo_high_threshold,
+ "Don't keep more than this much size of undo information.\n\
+A command which pushes past this size is itself forgotten.\n\
+This threshold is applied when garbage collection happens.\n\
+The size is counted as the number of bytes occupied,\n\
+which includes both saved text and other data.");
+ undo_high_threshold = 20000;
+
+ defsubr (&Scons);
+ defsubr (&Slist);
+ defsubr (&Svector);
+ defsubr (&Smake_list);
+ defsubr (&Smake_vector);
+ defsubr (&Smake_string);
+ defsubr (&Smake_symbol);
+ defsubr (&Smake_marker);
+ defsubr (&Spurecopy);
+ defsubr (&Sgarbage_collect);
+}
diff --git a/src/alloca.c b/src/alloca.c
new file mode 100644
index 00000000000..c1ff22227f8
--- /dev/null
+++ b/src/alloca.c
@@ -0,0 +1,194 @@
+/*
+ alloca -- (mostly) portable public-domain implementation -- D A Gwyn
+
+ last edit: 86/05/30 rms
+ include config.h, since on VMS it renames some symbols.
+ Use xmalloc instead of malloc.
+
+ This implementation of the PWB library alloca() function,
+ which is used to allocate space off the run-time stack so
+ that it is automatically reclaimed upon procedure exit,
+ was inspired by discussions with J. Q. Johnson of Cornell.
+
+ It should work under any C implementation that uses an
+ actual procedure stack (as opposed to a linked list of
+ frames). There are some preprocessor constants that can
+ be defined when compiling for your specific system, for
+ improved efficiency; however, the defaults should be okay.
+
+ The general concept of this implementation is to keep
+ track of all alloca()-allocated blocks, and reclaim any
+ that are found to be deeper in the stack than the current
+ invocation. This heuristic does not reclaim storage as
+ soon as it becomes invalid, but it will do so eventually.
+
+ As a special case, alloca(0) reclaims storage without
+ allocating any. It is a good idea to use alloca(0) in
+ your main control loop, etc. to force garbage collection.
+*/
+#ifndef lint
+static char SCCSid[] = "@(#)alloca.c 1.1"; /* for the "what" utility */
+#endif
+
+#ifdef emacs
+#include "config.h"
+#ifdef static
+/* actually, only want this if static is defined as ""
+ -- this is for usg, in which emacs must undefine static
+ in order to make unexec workable
+ */
+#ifndef STACK_DIRECTION
+you
+lose
+-- must know STACK_DIRECTION at compile-time
+#endif /* STACK_DIRECTION undefined */
+#endif /* static */
+#endif /* emacs */
+
+#ifndef alloca /* If compiling with GCC, this file's not needed. */
+
+#ifdef __STDC__
+typedef void *pointer; /* generic pointer type */
+#else
+typedef char *pointer; /* generic pointer type */
+#endif
+
+#define NULL 0 /* null pointer constant */
+
+extern void free();
+extern pointer xmalloc();
+
+/*
+ Define STACK_DIRECTION 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
+*/
+
+#ifndef STACK_DIRECTION
+#define STACK_DIRECTION 0 /* direction unknown */
+#endif
+
+#if STACK_DIRECTION != 0
+
+#define STACK_DIR STACK_DIRECTION /* known at compile-time */
+
+#else /* STACK_DIRECTION == 0; need run-time code */
+
+static int stack_dir; /* 1 or -1 once known */
+#define STACK_DIR stack_dir
+
+static void
+find_stack_direction (/* void */)
+{
+ static char *addr = NULL; /* address of first
+ `dummy', once known */
+ auto char dummy; /* to get stack address */
+
+ if (addr == NULL)
+ { /* initial entry */
+ addr = &dummy;
+
+ find_stack_direction (); /* recurse once */
+ }
+ else /* second entry */
+ if (&dummy > addr)
+ stack_dir = 1; /* stack grew upward */
+ else
+ stack_dir = -1; /* stack grew downward */
+}
+
+#endif /* STACK_DIRECTION == 0 */
+
+/*
+ An "alloca header" is used to:
+ (a) chain together all alloca()ed blocks;
+ (b) keep track of stack depth.
+
+ It is very important that sizeof(header) agree with malloc()
+ alignment chunk size. The following default should work okay.
+*/
+
+#ifndef ALIGN_SIZE
+#define ALIGN_SIZE sizeof(double)
+#endif
+
+typedef union hdr
+{
+ char align[ALIGN_SIZE]; /* to force sizeof(header) */
+ struct
+ {
+ union hdr *next; /* for chaining headers */
+ char *deep; /* for stack depth measure */
+ } h;
+} header;
+
+/*
+ alloca( size ) returns a pointer to at least `size' bytes of
+ storage which will be automatically reclaimed upon exit from
+ the procedure that called alloca(). Originally, this space
+ was supposed to be taken from the current stack frame of the
+ caller, but that method cannot be made to work for some
+ implementations of C, for example under Gould's UTX/32.
+*/
+
+static header *last_alloca_header = NULL; /* -> last alloca header */
+
+pointer
+alloca (size) /* returns pointer to storage */
+ unsigned size; /* # bytes to allocate */
+{
+ auto char probe; /* probes stack depth: */
+ register char *depth = &probe;
+
+#if STACK_DIRECTION == 0
+ if (STACK_DIR == 0) /* unknown growth direction */
+ find_stack_direction ();
+#endif
+
+ /* Reclaim garbage, defined as all alloca()ed storage that
+ was allocated from deeper in the stack than currently. */
+
+ {
+ register header *hp; /* traverses linked list */
+
+ for (hp = last_alloca_header; hp != NULL;)
+ if ((STACK_DIR > 0 && hp->h.deep > depth)
+ || (STACK_DIR < 0 && hp->h.deep < depth))
+ {
+ register header *np = hp->h.next;
+
+ free ((pointer) hp); /* collect garbage */
+
+ hp = np; /* -> next header */
+ }
+ else
+ break; /* rest are not deeper */
+
+ last_alloca_header = hp; /* -> last valid storage */
+ }
+
+ if (size == 0)
+ return NULL; /* no allocation required */
+
+ /* Allocate combined header + user data storage. */
+
+ {
+ register pointer new = xmalloc (sizeof (header) + size);
+ /* address of header */
+
+ ((header *)new)->h.next = last_alloca_header;
+ ((header *)new)->h.deep = depth;
+
+ last_alloca_header = (header *)new;
+
+ /* User storage begins just after header. */
+
+ return (pointer)((char *)new + sizeof(header));
+ }
+}
+
+#endif /* no alloca */
diff --git a/src/alloca.s b/src/alloca.s
new file mode 100644
index 00000000000..4c14c691b2e
--- /dev/null
+++ b/src/alloca.s
@@ -0,0 +1,320 @@
+/* `alloca' standard 4.2 subroutine for 68000's and 16000's and others.
+ Also has _setjmp and _longjmp for pyramids.
+ Copyright (C) 1985, 1986, 1988 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* Both 68000 systems I have run this on have had broken versions of alloca.
+ Also, I am told that non-berkeley systems do not have it at all.
+ So replace whatever system-provided alloca there may be
+ on all 68000 systems. */
+
+#define NOT_C_CODE
+#include "config.h"
+
+#ifndef HAVE_ALLOCA /* define this to use system's alloca */
+
+#ifndef hp9000s300
+#ifndef m68k
+#ifndef m68000
+#ifndef WICAT
+#ifndef ns32000
+#ifndef ns16000
+#ifndef sequent
+#ifndef pyramid
+#ifndef ATT3B5
+#ifndef XENIX
+you
+lose!!
+#endif /* XENIX */
+#endif /* ATT3B5 */
+#endif /* pyramid */
+#endif /* sequent */
+#endif /* ns32000 */
+#endif /* ns16000 */
+#endif /* WICAT */
+#endif /* m68000 */
+#endif /* m68k */
+#endif /* hp9000s300 */
+
+
+#if defined (hp9000s300) || defined (mot_delta)
+#ifdef mot_delta
+ file "alloca.s"
+; This syntax is what pot@fly.cnuce.cnr.it says we should use.
+ global alloca
+alloca:
+#endif
+#ifdef OLD_HP_ASSEMBLER
+ data
+ text
+ globl _alloca
+_alloca
+ move.l (sp)+,a0 ; pop return addr from top of stack
+ move.l (sp)+,d0 ; pop size in bytes from top of stack
+ add.l #ROUND,d0 ; round size up to long word
+ and.l #MASK,d0 ; mask out lower two bits of size
+ sub.l d0,sp ; allocate by moving stack pointer
+ tst.b PROBE(sp) ; stack probe to allocate pages
+ move.l sp,d0 ; return pointer
+ add.l #-4,sp ; new top of stack
+ jmp (a0) ; not a normal return
+MASK equ -4 ; Longword alignment
+ROUND equ 3 ; ditto
+PROBE equ -128 ; safety buffer for C compiler scratch
+ data
+#else /* new hp assembler syntax */
+/*
+ The new compiler does "move.m <registers> (%sp)" to save registers,
+ so we must copy the saved registers when we mung the sp.
+ The old compiler did "move.m <register> <offset>(%a6)", which
+ gave us no trouble
+ */
+ text
+ set PROBE,-128 # safety for C frame temporaries
+ set MAXREG,22 # d2-d7, a2-a5, fp2-fp7 may have been saved
+ global _alloca
+_alloca:
+ mov.l (%sp)+,%a0 # return addess
+ mov.l (%sp)+,%d0 # number of bytes to allocate
+ mov.l %sp,%a1 # save old sp for register copy
+ mov.l %sp,%d1 # compute new sp
+ sub.l %d0,%d1 # space requested
+ and.l &-4,%d1 # round down to longword
+ sub.l &MAXREG*4,%d1 # space for saving registers
+ mov.l %d1,%sp # save new value of sp
+ tst.b PROBE(%sp) # create pages (sigh)
+ mov.l %a2,%d1 # save reg a2
+ mov.l %sp,%a2
+ move.w &MAXREG-1,%d0
+copy_regs_loop: /* save caller's saved registers */
+ mov.l (%a1)+,(%a2)+
+ dbra %d0,copy_regs_loop
+ mov.l %a2,%d0 # return value
+ mov.l %d1,%a2 # restore a2
+ add.l &-4,%sp # adjust tos
+ jmp (%a0) # rts
+#endif /* new hp assembler */
+#else
+#ifdef m68k /* SGS assembler totally different */
+ file "alloca.s"
+ global alloca
+alloca:
+ mov.l (%sp)+,%a1 # pop return addr from top of stack
+ mov.l (%sp)+,%d0 # pop size in bytes from top of stack
+ add.l &R%1,%d0 # round size up to long word
+ and.l &-4,%d0 # mask out lower two bits of size
+ sub.l %d0,%sp # allocate by moving stack pointer
+ tst.b P%1(%sp) # stack probe to allocate pages
+ mov.l %sp,%a0 # return pointer as pointer
+ mov.l %sp,%d0 # return pointer as int to avoid disaster
+ add.l &-4,%sp # new top of stack
+ jmp (%a1) # not a normal return
+ set S%1,64 # safety factor for C compiler scratch
+ set R%1,3+S%1 # add to size for rounding
+ set P%1,-132 # probe this far below current top of stack
+
+#else /* not m68k */
+
+#ifdef m68000
+
+#ifdef WICAT
+/*
+ * Registers are saved after the corresponding link so we have to explicitly
+ * move them to the top of the stack where they are expected to be.
+ * Since we do not know how many registers were saved in the calling function
+ * we must assume the maximum possible (d2-d7,a2-a5). Hence, we end up
+ * wasting some space on the stack.
+ *
+ * The large probe (tst.b) attempts to make up for the fact that we have
+ * potentially used up the space that the caller probed for its own needs.
+ */
+ .procss m0
+ .config "68000 1"
+ .module _alloca
+MAXREG: .const 10
+ .sect text
+ .global _alloca
+_alloca:
+ move.l (sp)+,a1 ; pop return address
+ move.l (sp)+,d0 ; pop allocation size
+ move.l sp,d1 ; get current SP value
+ sub.l d0,d1 ; adjust to reflect required size...
+ sub.l #MAXREG*4,d1 ; ...and space needed for registers
+ and.l #-4,d1 ; backup to longword boundry
+ move.l sp,a0 ; save old SP value for register copy
+ move.l d1,sp ; set the new SP value
+ tst.b -4096(sp) ; grab an extra page (to cover caller)
+ move.l a2,d1 ; save callers register
+ move.l sp,a2
+ move.w #MAXREG-1,d0 ; # of longwords to copy
+loop: move.l (a0)+,(a2)+ ; copy registers...
+ dbra d0,loop ; ...til there are no more
+ move.l a2,d0 ; end of register area is addr for new space
+ move.l d1,a2 ; restore saved a2.
+ addq.l #4,sp ; caller will increment sp by 4 after return.
+ move.l d0,a0 ; return value in both a0 and d0.
+ jmp (a1)
+ .end _alloca
+#else
+
+/* Some systems want the _, some do not. Win with both kinds. */
+.globl _alloca
+_alloca:
+.globl alloca
+alloca:
+ movl sp@+,a0
+ movl a7,d0
+ subl sp@,d0
+ andl #~3,d0
+ movl d0,sp
+ tstb sp@(0) /* Make stack pages exist */
+ /* Needed on certain systems
+ that lack true demand paging */
+ addql #4,d0
+ jmp a0@
+
+#endif /* not WICAT */
+#endif /* m68000 */
+#endif /* not m68k */
+#endif /* not hp9000s300 */
+
+#if defined (ns16000) || defined (ns32000)
+
+ .text
+ .align 2
+/* Some systems want the _, some do not. Win with both kinds. */
+.globl _alloca
+_alloca:
+.globl alloca
+alloca:
+
+/* Two different assembler syntaxes are used for the same code
+ on different systems. */
+
+#ifdef sequent
+#define IM
+#define REGISTER(x) x
+#else
+#define IM $
+#define REGISTER(x) 0(x)
+#endif
+
+/*
+ * The ns16000 is a little more difficult, need to copy regs.
+ * Also the code assumes direct linkage call sequence (no mod table crap).
+ * We have to copy registers, and therefore waste 32 bytes.
+ *
+ * Stack layout:
+ * new sp -> junk
+ * registers (copy)
+ * r0 -> new data
+ * | (orig retval)
+ * | (orig arg)
+ * old sp -> regs (orig)
+ * local data
+ * fp -> old fp
+ */
+
+ movd tos,r1 /* pop return addr */
+ negd tos,r0 /* pop amount to allocate */
+ sprd sp,r2
+ addd r2,r0
+ bicb IM/**/3,r0 /* 4-byte align */
+ lprd sp,r0
+ adjspb IM/**/36 /* space for regs, +4 for caller to pop */
+ movmd 0(r2),4(sp),IM/**/4 /* copy regs */
+ movmd 0x10(r2),0x14(sp),IM/**/4
+ jump REGISTER(r1) /* funky return */
+#endif /* ns16000 or ns32000. */
+
+#ifdef pyramid
+
+.globl _alloca
+
+_alloca: addw $3,pr0 # add 3 (dec) to first argument
+ bicw $3,pr0 # then clear its last 2 bits
+ subw pr0,sp # subtract from SP the val in PR0
+ andw $-32,sp # keep sp aligned on multiple of 32.
+ movw sp,pr0 # ret. current SP
+ ret
+
+#ifdef PYRAMID_OLD /* This isn't needed in system version 4. */
+.globl __longjmp
+.globl _longjmp
+.globl __setjmp
+.globl _setjmp
+
+__longjmp: jump _longjmp
+__setjmp: jump _setjmp
+#endif
+
+#endif /* pyramid */
+
+#ifdef ATT3B5
+
+ .align 4
+ .globl alloca
+
+alloca:
+ movw %ap, %r8
+ subw2 $9*4, %r8
+ movw 0(%r8), %r1 /* pc */
+ movw 4(%r8), %fp
+ movw 8(%r8), %sp
+ addw2 %r0, %sp /* make room */
+ movw %sp, %r0 /* return value */
+ jmp (%r1) /* continue... */
+
+#endif /* ATT3B5 */
+
+#ifdef XENIX
+
+.386
+
+_TEXT segment dword use32 public 'CODE'
+assume cs:_TEXT
+
+;-------------------------------------------------------------------------
+
+public _alloca
+_alloca proc near
+
+ pop ecx ; return address
+ pop eax ; amount to alloc
+ add eax,3 ; round it to 32-bit boundary
+ and al,11111100B ;
+ mov edx,esp ; current sp in edx
+ sub edx,eax ; lower the stack
+ xchg esp,edx ; start of allocation in esp, old sp in edx
+ mov eax,esp ; return ptr to base in eax
+ push [edx+8] ; save poss. stored reg. values (esi,edi,ebx)
+ push [edx+4] ; on lowered stack
+ push [edx] ;
+ sub esp,4 ; allow for 'add esp, 4'
+ jmp ecx ; jump to return address
+
+_alloca endp
+
+_TEXT ends
+
+end
+
+#endif /* XENIX */
+
+#endif /* not HAVE_ALLOCA */
diff --git a/src/buffer.c b/src/buffer.c
new file mode 100644
index 00000000000..672dc1f56e2
--- /dev/null
+++ b/src/buffer.c
@@ -0,0 +1,1359 @@
+/* Buffer manipulation primitives for GNU Emacs.
+ Copyright (C) 1985, 1986, 1987, 1988, 1990 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#include <sys/param.h>
+
+#ifndef MAXPATHLEN
+/* in 4.1, param.h fails to define this. */
+#define MAXPATHLEN 1024
+#endif /* not MAXPATHLEN */
+
+#ifdef NULL
+#undef NULL
+#endif
+#include "config.h"
+#include "lisp.h"
+#include "window.h"
+#include "commands.h"
+#include "buffer.h"
+#include "syntax.h"
+
+struct buffer *current_buffer; /* the current buffer */
+
+/* First buffer in chain of all buffers (in reverse order of creation).
+ Threaded through ->next. */
+
+struct buffer *all_buffers;
+
+/* This structure holds the default values of the buffer-local variables
+ defined with DEFVAR_PER_BUFFER, that have special slots in each buffer.
+ The default value occupies the same slot in this structure
+ as an individual buffer's value occupies in that buffer.
+ Setting the default value also goes through the alist of buffers
+ and stores into each buffer that does not say it has a local value. */
+
+struct buffer buffer_defaults;
+/* A Lisp_Object pointer to the above, used for staticpro */
+static Lisp_Object Vbuffer_defaults;
+
+/* This structure marks which slots in a buffer have corresponding
+ default values in buffer_defaults.
+ Each such slot has a nonzero value in this structure.
+ The value has only one nonzero bit.
+
+ When a buffer has its own local value for a slot,
+ the bit for that slot (found in the same slot in this structure)
+ is turned on in the buffer's local_var_flags slot.
+
+ If a slot in this structure is -1, then even though there may
+ be a DEFVAR_PER_BUFFER for the slot, there is no default value for it;
+ and the corresponding slot in buffer_defaults is not used.
+
+ If a slot is -2, then there is no DEFVAR_PER_BUFFER for it,
+ but there is a default value which is copied into each buffer.
+
+ If a slot in this structure corresponding to a DEFVAR_PER_BUFFER is
+ zero, that is a bug */
+
+struct buffer buffer_local_flags;
+
+/* This structure holds the names of symbols whose values may be
+ buffer-local. It is indexed and accessed in the same way as the above. */
+
+struct buffer buffer_local_symbols;
+/* A Lisp_Object pointer to the above, used for staticpro */
+static Lisp_Object Vbuffer_local_symbols;
+
+Lisp_Object Fset_buffer ();
+
+/* Alist of all buffer names vs the buffers. */
+/* This used to be a variable, but is no longer,
+ to prevent lossage due to user rplac'ing this alist or its elements. */
+Lisp_Object Vbuffer_alist;
+
+Lisp_Object Qfundamental_mode, Qmode_class;
+
+Lisp_Object QSFundamental; /* A string "Fundamental" */
+
+/* For debugging; temporary. See set_buffer_internal. */
+/* Lisp_Object Qlisp_mode, Vcheck_symbol; */
+
+nsberror (spec)
+ Lisp_Object spec;
+{
+ if (XTYPE (spec) == Lisp_String)
+ error ("No buffer named %s", XSTRING (spec)->data);
+ error ("Invalid buffer argument");
+}
+
+DEFUN ("buffer-list", Fbuffer_list, Sbuffer_list, 0, 0, 0,
+ "Return a list of all buffers.")
+ ()
+{
+ return Fmapcar (Qcdr, Vbuffer_alist);
+}
+
+DEFUN ("get-buffer", Fget_buffer, Sget_buffer, 1, 1, 0,
+ "Return the buffer named NAME (a string).\n\
+It is found by looking up NAME in buffer-alist.\n\
+If there is no buffer named NAME, nil is returned.\n\
+NAME may also be a buffer; it is returned.")
+ (name)
+ register Lisp_Object name;
+{
+ if (XTYPE (name) == Lisp_Buffer)
+ return name;
+ CHECK_STRING (name, 0);
+
+ return Fcdr (Fassoc (name, Vbuffer_alist));
+}
+
+DEFUN ("get-file-buffer", Fget_file_buffer, Sget_file_buffer, 1, 1, 0,
+ "Return the buffer visiting file FILENAME (a string).\n\
+If there is no such buffer, nil is returned.")
+ (filename)
+ register Lisp_Object filename;
+{
+ register Lisp_Object tail, buf, tem;
+ CHECK_STRING (filename, 0);
+ filename = Fexpand_file_name (filename, Qnil);
+
+ for (tail = Vbuffer_alist; CONSP (tail); tail = XCONS (tail)->cdr)
+ {
+ buf = Fcdr (XCONS (tail)->car);
+ if (XTYPE (buf) != Lisp_Buffer) continue;
+ if (XTYPE (XBUFFER (buf)->filename) != Lisp_String) continue;
+ tem = Fstring_equal (XBUFFER (buf)->filename, filename);
+ if (!NULL (tem))
+ return buf;
+ }
+ return Qnil;
+}
+
+DEFUN ("get-buffer-create", Fget_buffer_create, Sget_buffer_create, 1, 1, 0,
+ "Like get-buffer but creates a buffer named NAME and returns it if none already exists.")
+ (name)
+ register Lisp_Object name;
+{
+ register Lisp_Object buf, function, tem;
+ int count = specpdl_ptr - specpdl;
+ register struct buffer *b;
+ register unsigned char *data;
+ /* register struct buffer *bx; */
+
+ buf = Fget_buffer (name);
+ if (!NULL (buf)) return buf;
+
+ b = (struct buffer *) malloc (sizeof (struct buffer));
+ if (!b) memory_full ();
+
+ BUF_GAP_SIZE (b) = 20;
+ data = (unsigned char *) malloc (BUF_GAP_SIZE (b));
+ if (!data)
+ {
+ free (b);
+ memory_full ();
+ }
+ BUF_BEG_ADDR (b) = data;
+ BUF_PT (b) = 1;
+ BUF_GPT (b) = 1;
+ BUF_BEGV (b) = 1;
+ BUF_ZV (b) = 1;
+ BUF_Z (b) = 1;
+ BUF_MODIFF (b) = 1;
+
+ /* Put this on the chain of all buffers including killed ones. */
+ b->next = all_buffers;
+ all_buffers = b;
+
+ /* Put this in the alist of all live buffers. */
+ XSET (buf, Lisp_Buffer, b);
+#if 0
+ XSETTYPE (buf, Lisp_Buffer);
+ bx = b; /* Use of bx avoids compiler bug on Sun */
+ XSETBUFFER (buf, bx);
+#endif
+ Vbuffer_alist = nconc2 (Vbuffer_alist, Fcons (Fcons (name, buf), Qnil));
+
+ b->mark = Fmake_marker ();
+ b->markers = Qnil;
+ b->name = name;
+
+ /* Enable undo in this buffer unless name starts with a space. */
+ if (XSTRING (name)->data[0] != ' ')
+ b->undo_list = Qnil;
+ else
+ b->undo_list = Qt;
+
+ reset_buffer (b);
+
+ function = buffer_defaults.major_mode;
+ if (NULL (function))
+ {
+ tem = Fget (current_buffer->major_mode, Qmode_class);
+ if (EQ (tem, Qnil))
+ function = current_buffer->major_mode;
+ }
+
+ if (NULL (function) || EQ (function, Qfundamental_mode))
+ return buf;
+
+ /* To select a nonfundamental mode,
+ select the buffer temporarily and then call the mode function. */
+
+ record_unwind_protect (save_excursion_restore, save_excursion_save ());
+
+ Fset_buffer (buf);
+ call0 (function);
+
+ unbind_to (count);
+ return buf;
+}
+
+/* Reinitialize everything about a buffer except its name and contents. */
+
+void
+reset_buffer (b)
+ register struct buffer *b;
+{
+ b->filename = Qnil;
+ b->directory = (current_buffer) ? current_buffer->directory : Qnil;
+ b->modtime = 0;
+ b->save_modified = 1;
+ b->save_length = 0;
+ b->last_window_start = 1;
+ b->backed_up = Qnil;
+ b->auto_save_modified = 0;
+ b->auto_save_file_name = Qnil;
+ b->read_only = Qnil;
+ reset_buffer_local_variables(b);
+}
+
+reset_buffer_local_variables(b)
+ register struct buffer *b;
+{
+ register int offset;
+
+ /* Reset the major mode to Fundamental, together with all the
+ things that depend on the major mode.
+ default-major-mode is handled at a higher level.
+ We ignore it here. */
+ b->major_mode = Qfundamental_mode;
+ b->keymap = Qnil;
+ b->abbrev_table = Vfundamental_mode_abbrev_table;
+ b->mode_name = QSFundamental;
+
+ /* Reset all per-buffer variables to their defaults. */
+ b->local_var_alist = Qnil;
+ b->local_var_flags = 0;
+
+ /* For each slot that has a default value,
+ copy that into the slot. */
+
+ for (offset = (char *)&buffer_local_flags.name - (char *)&buffer_local_flags;
+ offset < sizeof (struct buffer);
+ offset += sizeof (Lisp_Object)) /* sizeof int == sizeof Lisp_Object */
+ if (*(int *)(offset + (char *) &buffer_local_flags) > 0
+ || *(int *)(offset + (char *) &buffer_local_flags) == -2)
+ *(Lisp_Object *)(offset + (char *)b) =
+ *(Lisp_Object *)(offset + (char *)&buffer_defaults);
+}
+
+DEFUN ("generate-new-buffer", Fgenerate_new_buffer, Sgenerate_new_buffer,
+ 1, 1, 0,
+ "Creates and returns a buffer named NAME if one does not already exist,\n\
+else tries adding successive suffixes to NAME until a new buffer-name is\n\
+formed, then creates and returns a new buffer with that new name.")
+ (name)
+ register Lisp_Object name;
+{
+ register Lisp_Object gentemp, tem;
+ int count;
+ char number[10];
+
+ CHECK_STRING (name, 0);
+
+ tem = Fget_buffer (name);
+ if (NULL (tem))
+ return Fget_buffer_create (name);
+
+ count = 1;
+ while (1)
+ {
+ sprintf (number, "<%d>", ++count);
+ gentemp = concat2 (name, build_string (number));
+ tem = Fget_buffer (gentemp);
+ if (NULL (tem))
+ return Fget_buffer_create (gentemp);
+ }
+}
+
+
+DEFUN ("buffer-name", Fbuffer_name, Sbuffer_name, 0, 1, 0,
+ "Return the name of BUFFER, as a string.\n\
+No arg means return name of current buffer.")
+ (buffer)
+ register Lisp_Object buffer;
+{
+ if (NULL (buffer))
+ return current_buffer->name;
+ CHECK_BUFFER (buffer, 0);
+ return XBUFFER (buffer)->name;
+}
+
+#ifdef NOTDEF /* Useless. If you need this, you should be using `eq'
+ DEFUN ("buffer-number", Fbuffer_number, Sbuffer_number, 0, 1, 0,
+ "Return the number of BUFFER.\n\
+ No arg means return number of current buffer.")
+ (buffer)
+ Lisp_Object buffer;
+ {
+ if (NULL (buffer))
+ return current_buffer->number;
+ CHECK_BUFFER (buffer, 0);
+ return XBUFFER (buffer)->number;
+ }
+ */
+#endif NOTDEF
+
+DEFUN ("buffer-file-name", Fbuffer_file_name, Sbuffer_file_name, 0, 1, 0,
+ "Return name of file BUFFER is visiting, or NIL if none.\n\
+No argument means use current buffer as BUFFER.")
+ (buffer)
+ register Lisp_Object buffer;
+{
+ if (NULL (buffer))
+ return current_buffer->filename;
+ CHECK_BUFFER (buffer, 0);
+ return XBUFFER (buffer)->filename;
+}
+
+DEFUN ("buffer-local-variables", Fbuffer_local_variables,
+ Sbuffer_local_variables, 0, 1, 0,
+ "Return alist of variables that are buffer-local in BUFFER.\n\
+No argument means use current buffer as BUFFER.\n\
+Each element of the value looks like (SYMBOL . VALUE).\n\
+Note that storing new VALUEs in these elements\n\
+does not change the local values.")
+ (buffer)
+ register Lisp_Object buffer;
+{
+ register struct buffer *buf;
+ register Lisp_Object val;
+
+ if (NULL (buffer))
+ buf = current_buffer;
+ else
+ {
+ CHECK_BUFFER (buffer, 0);
+ buf = XBUFFER (buffer);
+ }
+
+ {
+ /* Reference each variable in the alist in our current buffer.
+ If inquiring about the current buffer, this gets the current values,
+ so store them into the alist so the alist is up to date.
+ If inquiring about some other buffer, this swaps out any values
+ for that buffer, making the alist up to date automatically. */
+ register Lisp_Object tem;
+ for (tem = buf->local_var_alist; CONSP (tem); tem = XCONS (tem)->cdr)
+ {
+ Lisp_Object v1 = Fsymbol_value (XCONS (XCONS (tem)->car)->car);
+ if (buf == current_buffer)
+ XCONS (XCONS (tem)->car)->cdr = v1;
+ }
+ }
+
+ /* Make a copy of the alist, to return it. */
+ val = Fcopy_alist (buf->local_var_alist);
+
+ /* Add on all the variables stored in special slots. */
+ {
+ register int offset, mask;
+
+ for (offset = (char *)&buffer_local_symbols.name - (char *)&buffer_local_symbols;
+ offset < sizeof (struct buffer);
+ offset += (sizeof (int))) /* sizeof int == sizeof Lisp_Object */
+ {
+ mask = *(int *)(offset + (char *) &buffer_local_flags);
+ if (mask == -1 || (buf->local_var_flags & mask))
+ if (XTYPE (*(Lisp_Object *)(offset + (char *)&buffer_local_symbols))
+ == Lisp_Symbol)
+ val = Fcons (Fcons (*(Lisp_Object *)(offset + (char *)&buffer_local_symbols),
+ *(Lisp_Object *)(offset + (char *)buf)),
+ val);
+ }
+ }
+ return (val);
+}
+
+
+DEFUN ("buffer-modified-p", Fbuffer_modified_p, Sbuffer_modified_p,
+ 0, 1, 0,
+ "Return t if BUFFER is modified since file last read in or saved.\n\
+No argument means use current buffer as BUFFER.")
+ (buffer)
+ register Lisp_Object buffer;
+{
+ register struct buffer *buf;
+ if (NULL (buffer))
+ buf = current_buffer;
+ else
+ {
+ CHECK_BUFFER (buffer, 0);
+ buf = XBUFFER (buffer);
+ }
+
+ return buf->save_modified < BUF_MODIFF (buf) ? Qt : Qnil;
+}
+
+DEFUN ("set-buffer-modified-p", Fset_buffer_modified_p, Sset_buffer_modified_p,
+ 1, 1, 0,
+ "Mark current buffer as modified or unmodified according to FLAG.")
+ (flag)
+ register Lisp_Object flag;
+{
+ register int already;
+ register Lisp_Object fn;
+
+#ifdef CLASH_DETECTION
+ /* If buffer becoming modified, lock the file.
+ If buffer becoming unmodified, unlock the file. */
+
+ fn = current_buffer->filename;
+ if (!NULL (fn))
+ {
+ already = current_buffer->save_modified < MODIFF;
+ if (!already && !NULL (flag))
+ lock_file (fn);
+ else if (already && NULL (flag))
+ unlock_file (fn);
+ }
+#endif /* CLASH_DETECTION */
+
+ current_buffer->save_modified = NULL (flag) ? MODIFF : 0;
+ update_mode_lines++;
+ return flag;
+}
+
+DEFUN ("rename-buffer", Frename_buffer, Srename_buffer, 1, 1,
+ "sRename buffer (to new name): ",
+ "Change current buffer's name to NEWNAME (a string).")
+ (name)
+ register Lisp_Object name;
+{
+ register Lisp_Object tem, buf;
+
+ CHECK_STRING (name, 0);
+ tem = Fget_buffer (name);
+ if (!NULL (tem))
+ error ("Buffer name \"%s\" is in use", XSTRING (name)->data);
+
+ XSET (buf, Lisp_Buffer, current_buffer);
+ tem = Fmemq (buf, Vminibuffer_list);
+ if (!NULL (tem))
+ error ("Cannot rename a minibuffer");
+
+ current_buffer->name = name;
+ Fsetcar (Frassq (buf, Vbuffer_alist), name);
+ if (NULL (current_buffer->filename) && !NULL (current_buffer->auto_save_file_name))
+ call0 (intern ("rename-auto-save-file"));
+ return Qnil;
+}
+
+DEFUN ("other-buffer", Fother_buffer, Sother_buffer, 0, 1, 0,
+ "Return most recently selected buffer other than BUFFER.\n\
+Buffers not visible in windows are preferred to visible buffers.\n\
+If no other exists, the buffer *scratch* is returned.\n\
+If BUFFER is omitted or nil, some interesting buffer is returned.")
+ (buffer)
+ register Lisp_Object buffer;
+{
+ register Lisp_Object tail, buf, notsogood, tem;
+ notsogood = Qnil;
+
+ for (tail = Vbuffer_alist; !NULL (tail); tail = Fcdr (tail))
+ {
+ buf = Fcdr (Fcar (tail));
+ if (EQ (buf, buffer))
+ continue;
+ if (XSTRING (XBUFFER (buf)->name)->data[0] == ' ')
+ continue;
+ tem = Fget_buffer_window (buf);
+ if (NULL (tem))
+ return buf;
+ if (NULL (notsogood))
+ notsogood = buf;
+ }
+ if (!NULL (notsogood))
+ return notsogood;
+ return Fget_buffer_create (build_string ("*scratch*"));
+}
+
+DEFUN ("buffer-flush-undo", Fbuffer_flush_undo, Sbuffer_flush_undo, 1, 1, 0,
+ "Make BUFFER stop keeping undo information.")
+ (buf)
+ register Lisp_Object buf;
+{
+ CHECK_BUFFER (buf, 0);
+ XBUFFER (buf)->undo_list = Qt;
+ return Qnil;
+}
+
+DEFUN ("buffer-enable-undo", Fbuffer_enable_undo, Sbuffer_enable_undo,
+ 0, 1, "",
+ "Start keeping undo information for buffer BUFFER (default is current buffer).")
+ (buf)
+ register Lisp_Object buf;
+{
+ if (NULL (buf))
+ {
+ if (EQ (current_buffer->undo_list, Qt))
+ current_buffer->undo_list = Qnil;
+ }
+ else
+ {
+ CHECK_BUFFER (buf, 0);
+ if (EQ (XBUFFER (buf)->undo_list, Qt))
+ XBUFFER (buf)->undo_list = Qnil;
+ }
+ return Qnil;
+}
+
+DEFUN ("kill-buffer", Fkill_buffer, Skill_buffer, 1, 1, "bKill buffer: ",
+ "One arg, a string or a buffer. Get rid of the specified buffer.\n\
+Any processes that have this buffer as the `process-buffer' are killed\n\
+with `delete-process'.")
+ (bufname)
+ Lisp_Object bufname;
+{
+ Lisp_Object buf;
+ register struct buffer *b;
+ register Lisp_Object tem;
+ register struct Lisp_Marker *m;
+ struct gcpro gcpro1, gcpro2;
+
+ if (NULL (bufname))
+ buf = Fcurrent_buffer ();
+ else
+ buf = Fget_buffer (bufname);
+ if (NULL (buf))
+ nsberror (bufname);
+
+ b = XBUFFER (buf);
+
+ if (FROM_KBD && !NULL (b->filename)
+ && BUF_MODIFF (b) > b->save_modified)
+ {
+ GCPRO2 (buf, bufname);
+ tem = Fyes_or_no_p (format1 ("Buffer %s modified; kill anyway? ",
+ XSTRING (b->name)->data));
+ UNGCPRO;
+ if (NULL (tem))
+ return Qnil;
+ }
+
+ /* We have no more questions to ask. Verify that it is valid
+ to kill the buffer. This must be done after the questions
+ since anything can happen within Fyes_or_no_p. */
+
+ /* Don't kill the minibuffer now current. */
+ if (EQ (buf, XWINDOW (minibuf_window)->buffer))
+ return Qnil;
+
+ if (NULL (b->name))
+ return Qnil;
+
+ /* Make this buffer not be current.
+ In the process, notice if this is the sole visible buffer
+ and give up if so. */
+ if (b == current_buffer)
+ {
+ tem = Fother_buffer (buf);
+ Fset_buffer (tem);
+ if (b == current_buffer)
+ return Qnil;
+ }
+
+ /* Now there is no question: we can kill the buffer. */
+
+#ifdef CLASH_DETECTION
+ /* Unlock this buffer's file, if it is locked. */
+ unlock_buffer (b);
+#endif /* CLASH_DETECTION */
+
+#ifdef subprocesses
+ kill_buffer_processes (buf);
+#endif subprocesses
+
+ tem = Vinhibit_quit;
+ Vinhibit_quit = Qt;
+ Vbuffer_alist = Fdelq (Frassq (buf, Vbuffer_alist), Vbuffer_alist);
+ Freplace_buffer_in_windows (buf);
+ Vinhibit_quit = tem;
+
+ /* Unchain all markers of this buffer
+ and leave them pointing nowhere. */
+ for (tem = b->markers; !EQ (tem, Qnil); )
+ {
+ m = XMARKER (tem);
+ m->buffer = 0;
+ tem = m->chain;
+ m->chain = Qnil;
+ }
+ b->markers = Qnil;
+
+ b->name = Qnil;
+ b->undo_list = Qnil;
+ free (BUF_BEG_ADDR (b));
+
+ return Qnil;
+}
+
+/* Put the element for buffer `buf' at the front of buffer-alist.
+ This is done when a buffer is selected "visibly".
+ It keeps buffer-alist in the order of recency of selection
+ so that other_buffer will return something nice. */
+
+record_buffer (buf)
+ Lisp_Object buf;
+{
+ register Lisp_Object link, prev;
+
+ prev = Qnil;
+ for (link = Vbuffer_alist; CONSP (link); link = XCONS (link)->cdr)
+ {
+ if (EQ (XCONS (XCONS (link)->car)->cdr, buf))
+ break;
+ prev = link;
+ }
+
+ /* Effectively do Vbuffer_alist = Fdelq (link, Vbuffer_alist)
+ but cannot use Fdelq here it that allows quitting. */
+
+ if (NULL (prev))
+ Vbuffer_alist = XCONS (Vbuffer_alist)->cdr;
+ else
+ XCONS (prev)->cdr = XCONS (XCONS (prev)->cdr)->cdr;
+
+ XCONS(link)->cdr = Vbuffer_alist;
+ Vbuffer_alist = link;
+}
+
+DEFUN ("switch-to-buffer", Fswitch_to_buffer, Sswitch_to_buffer, 1, 2, "BSwitch to buffer: ",
+ "Select buffer BUFFER in the current window.\n\
+BUFFER may be a buffer or a buffer name.\n\
+Optional second arg NORECORD non-nil means\n\
+do not put this buffer at the front of the list of recently selected ones.\n\
+\n\
+WARNING: This is NOT the way to work on another buffer temporarily\n\
+within a Lisp program! Use `set-buffer' instead. That avoids messing with\n\
+the window-buffer correspondances.")
+ (bufname, norecord)
+ Lisp_Object bufname, norecord;
+{
+ register Lisp_Object buf;
+
+ if (EQ (minibuf_window, selected_window))
+ error ("Cannot switch buffers in minibuffer window");
+
+ if (NULL (bufname))
+ buf = Fother_buffer (Fcurrent_buffer ());
+ else
+ buf = Fget_buffer_create (bufname);
+ Fset_buffer (buf);
+ if (NULL (norecord))
+ record_buffer (buf);
+
+ Fset_window_buffer (EQ (selected_window, minibuf_window)
+ ? Fnext_window (minibuf_window, Qnil) : selected_window,
+ buf);
+
+ return Qnil;
+}
+
+DEFUN ("pop-to-buffer", Fpop_to_buffer, Spop_to_buffer, 1, 2, 0,
+ "Select buffer BUFFER in some window, preferably a different one.\n\
+If pop-up-windows is non-nil, windows can be split to do this.\n\
+If second arg OTHER-WINDOW is non-nil, insist on finding another\n\
+window even if BUFFER is already visible in the selected window.")
+ (bufname, other)
+ Lisp_Object bufname, other;
+{
+ register Lisp_Object buf;
+ if (NULL (bufname))
+ buf = Fother_buffer (Fcurrent_buffer ());
+ else
+ buf = Fget_buffer_create (bufname);
+ Fset_buffer (buf);
+ record_buffer (buf);
+ Fselect_window (Fdisplay_buffer (buf, other));
+ return Qnil;
+}
+
+DEFUN ("current-buffer", Fcurrent_buffer, Scurrent_buffer, 0, 0, 0,
+ "Return the current buffer as a Lisp buffer object.")
+ ()
+{
+ register Lisp_Object buf;
+ XSET (buf, Lisp_Buffer, current_buffer);
+ return buf;
+}
+
+DEFUN ("set-buffer", Fset_buffer, Sset_buffer, 1, 1, 0,
+ "Set the current buffer to the buffer or buffer name supplied as argument.\n\
+That buffer will then be the default for editing operations and printing.\n\
+This function's effect can't last past end of current command\n\
+because returning to command level\n\
+selects the chosen buffer of the current window,\n\
+and this function has no effect on what buffer that is.\n\
+See also `save-excursion' when you want to select a buffer temporarily.\n\
+Use `switch-to-buffer' or `pop-to-buffer' for interactive buffer selection.")
+ (bufname)
+ register Lisp_Object bufname;
+{
+ register Lisp_Object buffer;
+ buffer = Fget_buffer (bufname);
+ if (NULL (buffer))
+ nsberror (bufname);
+ if (NULL (XBUFFER (buffer)->name))
+ error ("Selecting deleted buffer");
+ set_buffer_internal (XBUFFER (buffer));
+ return buffer;
+}
+
+DEFUN ("barf-if-buffer-read-only", Fbarf_if_buffer_read_only,
+ Sbarf_if_buffer_read_only, 0, 0, 0,
+ "Signal a buffer-read-only error if the current buffer is read-only.")
+ ()
+{
+ while (!NULL (current_buffer->read_only))
+ Fsignal (Qbuffer_read_only, (Fcons (Fcurrent_buffer (), Qnil)));
+ return Qnil;
+}
+
+DEFUN ("bury-buffer", Fbury_buffer, Sbury_buffer, 0, 1, "",
+ "Put BUFFER at the end of the list of all buffers.\n\
+There it is the least likely candidate for other-buffer to return;\n\
+thus, the least likely buffer for \\[switch-to-buffer] to select by default.\n\
+BUFFER is also removed from the selected window if it was displayed there.")
+ (buf)
+ register Lisp_Object buf;
+{
+ register Lisp_Object aelt, link;
+
+ if (NULL (buf))
+ {
+ XSET (buf, Lisp_Buffer, current_buffer);
+ Fswitch_to_buffer (Fother_buffer (buf), Qnil);
+ }
+ else
+ {
+ Lisp_Object buf1;
+
+ buf1 = Fget_buffer (buf);
+ if (NULL (buf1))
+ nsberror (buf);
+ buf = buf1;
+ }
+
+ aelt = Frassq (buf, Vbuffer_alist);
+ link = Fmemq (aelt, Vbuffer_alist);
+ Vbuffer_alist = Fdelq (aelt, Vbuffer_alist);
+ XCONS (link)->cdr = Qnil;
+ Vbuffer_alist = nconc2 (Vbuffer_alist, link);
+ return Qnil;
+}
+
+extern int last_known_column_point;
+
+/* Set the current buffer to B, which is a C pointer,
+ rather than a Lisp object. */
+
+set_buffer_internal (b)
+ register struct buffer *b;
+{
+ register struct buffer *swb = 0;
+ register struct buffer *old_buf;
+ register Lisp_Object tail, valcontents;
+ enum Lisp_Type tem;
+
+ if (current_buffer == b)
+ return;
+
+#if 0
+ if (XWINDOW (selected_window) != 0)
+ swb = NULL (selected_window) ? 0 : XBUFFER (XWINDOW (selected_window)->buffer);
+#endif
+
+ windows_or_buffers_changed = 1;
+
+ /* Vcheck_symbol is set up to the symbol paragraph-start
+ in order to check for the bug that clobbers it. */
+/* if (current_buffer && EQ (current_buffer->major_mode, Qlisp_mode)
+ && XFASTINT (Vcheck_symbol) != 0
+ && !NULL (Vcheck_symbol))
+ {
+ valcontents = XSYMBOL (Vcheck_symbol)->value;
+ if (XTYPE (valcontents) != Lisp_Some_Buffer_Local_Value)
+ abort ();
+ if (current_buffer == XBUFFER (XCONS (XCONS (valcontents)->cdr)->car)
+ && (XTYPE (XCONS (valcontents)->car) != Lisp_String
+ || XSTRING (XCONS (valcontents)->car)->size != 6))
+ abort ();
+ }
+*/
+
+#if 0
+ if (current_buffer == swb && !NULL (selected_window))
+ Fset_marker (XWINDOW (selected_window)->pointm, make_number (point),
+ XWINDOW (selected_window)->buffer);
+#endif
+ old_buf = current_buffer;
+ current_buffer = b;
+#if 0
+ if (b == swb)
+ {
+ SET_PT (marker_position (XWINDOW (selected_window)->pointm));
+ if (point < BEGV)
+ point = BEGV;
+ if (point > ZV)
+ point = ZV;
+ }
+#endif
+ last_known_column_point = -1; /* invalidate indentation cache */
+
+ /* Look down buffer's list of local Lisp variables
+ to find and update any that forward into C variables. */
+
+ for (tail = b->local_var_alist; !NULL (tail); tail = XCONS (tail)->cdr)
+ {
+ valcontents = XSYMBOL (XCONS (XCONS (tail)->car)->car)->value;
+ if ((XTYPE (valcontents) == Lisp_Buffer_Local_Value
+ || XTYPE (valcontents) == Lisp_Some_Buffer_Local_Value)
+ && (tem = XTYPE (XCONS (valcontents)->car),
+ (tem == Lisp_Boolfwd || tem == Lisp_Intfwd
+ || tem == Lisp_Objfwd)))
+ /* Just reference the variable
+ to cause it to become set for this buffer. */
+ Fsymbol_value (XCONS (XCONS (tail)->car)->car);
+ }
+
+ /* Do the same with any others that were local to the previous buffer */
+
+ if (old_buf)
+ for (tail = old_buf->local_var_alist; !NULL (tail); tail = XCONS (tail)->cdr)
+ {
+ valcontents = XSYMBOL (XCONS (XCONS (tail)->car)->car)->value;
+ if ((XTYPE (valcontents) == Lisp_Buffer_Local_Value
+ || XTYPE (valcontents) == Lisp_Some_Buffer_Local_Value)
+ && (tem = XTYPE (XCONS (valcontents)->car),
+ (tem == Lisp_Boolfwd || tem == Lisp_Intfwd
+ || tem == Lisp_Objfwd)))
+ /* Just reference the variable
+ to cause it to become set for this buffer. */
+ Fsymbol_value (XCONS (XCONS (tail)->car)->car);
+ }
+ /* Vcheck_symbol is set up to the symbol paragraph-start
+ in order to check for the bug that clobbers it. */
+/*if (EQ (b->major_mode, Qlisp_mode)
+ && Vcheck_symbol
+ && !NULL (Vcheck_symbol))
+ {
+ valcontents = XSYMBOL (Vcheck_symbol)->value;
+ if (XTYPE (valcontents) != Lisp_Some_Buffer_Local_Value)
+ abort ();
+ if (b == XBUFFER (XCONS (XCONS (valcontents)->cdr)->car)
+ && (XTYPE (XCONS (valcontents)->car) != Lisp_String
+ || XSTRING (XCONS (valcontents)->car)->size != 6))
+ abort ();
+ Fsymbol_value (Vcheck_symbol);
+ valcontents = XSYMBOL (Vcheck_symbol)->value;
+ if (b != XBUFFER (XCONS (XCONS (valcontents)->cdr)->car)
+ || XTYPE (XCONS (valcontents)->car) != Lisp_String
+ || XSTRING (XCONS (valcontents)->car)->size != 6)
+ abort ();
+ }
+ */
+}
+
+DEFUN ("erase-buffer", Ferase_buffer, Serase_buffer, 0, 0, 0,
+ "Delete the entire contents of the current buffer.")
+ ()
+{
+ Fwiden ();
+ del_range (BEG, Z);
+ current_buffer->last_window_start = 1;
+ /* Prevent warnings, or suspension of auto saving, that would happen
+ if future size is less than past size. Use of erase-buffer
+ implies that the future text is not really related to the past text. */
+ XFASTINT (current_buffer->save_length) = 0;
+ return Qnil;
+}
+
+validate_region (b, e)
+ register Lisp_Object *b, *e;
+{
+ register int i;
+
+ CHECK_NUMBER_COERCE_MARKER (*b, 0);
+ CHECK_NUMBER_COERCE_MARKER (*e, 1);
+
+ if (XINT (*b) > XINT (*e))
+ {
+ i = XFASTINT (*b); /* This is legit even if *b is < 0 */
+ *b = *e;
+ XFASTINT (*e) = i; /* because this is all we do with i. */
+ }
+
+ if (!(BEGV <= XINT (*b) && XINT (*b) <= XINT (*e)
+ && XINT (*e) <= ZV))
+ args_out_of_range (*b, *e);
+}
+
+Lisp_Object
+list_buffers_1 (files)
+ Lisp_Object files;
+{
+ register Lisp_Object tail, tem, buf;
+ Lisp_Object col1, col2, col3, minspace;
+ register struct buffer *old = current_buffer, *b;
+ int desired_point = 0;
+
+ XFASTINT (col1) = 19;
+ XFASTINT (col2) = 25;
+ XFASTINT (col3) = 40;
+ XFASTINT (minspace) = 1;
+
+ Fset_buffer (Vstandard_output);
+
+ tail = intern ("Buffer-menu-mode");
+ if (!EQ (tail, current_buffer->major_mode)
+ && (tem = Ffboundp (tail), !NULL (tem)))
+ call0 (tail);
+ Fbuffer_flush_undo (Vstandard_output);
+ current_buffer->read_only = Qnil;
+
+ write_string ("\
+ MR Buffer Size Mode File\n\
+ -- ------ ---- ---- ----\n", -1);
+
+ for (tail = Vbuffer_alist; !NULL (tail); tail = Fcdr (tail))
+ {
+ buf = Fcdr (Fcar (tail));
+ b = XBUFFER (buf);
+ /* Don't mention the minibuffers. */
+ if (XSTRING (b->name)->data[0] == ' ')
+ continue;
+ /* Optionally don't mention buffers that lack files. */
+ if (!NULL (files) && NULL (b->filename))
+ continue;
+ /* Identify the current buffer. */
+ if (b == old)
+ desired_point = point;
+ write_string (b == old ? "." : " ", -1);
+ /* Identify modified buffers */
+ write_string (BUF_MODIFF (b) > b->save_modified ? "*" : " ", -1);
+ write_string (NULL (b->read_only) ? " " : "% ", -1);
+ Fprinc (b->name, Qnil);
+ Findent_to (col1, make_number (2));
+ XFASTINT (tem) = BUF_Z (b) - BUF_BEG (b);
+ Fprin1 (tem, Qnil);
+ Findent_to (col2, minspace);
+ Fprinc (b->mode_name, Qnil);
+ Findent_to (col3, minspace);
+ if (!NULL (b->filename))
+ Fprinc (b->filename, Qnil);
+ write_string ("\n", -1);
+ }
+
+ current_buffer->read_only = Qt;
+ set_buffer_internal (old);
+/* Foo. This doesn't work since temp_output_buffer_show sets point to 1
+ if (desired_point)
+ BUF_PT (XBUFFER (Vstandard_output)) = desired_point;
+ */
+ return Qnil;
+}
+
+DEFUN ("list-buffers", Flist_buffers, Slist_buffers, 0, 1, "P",
+ "Display a list of names of existing buffers.\n\
+Inserts it in buffer *Buffer List* and displays that.\n\
+Note that buffers with names starting with spaces are omitted.\n\
+Non-null optional arg FILES-ONLY means mention only file buffers.\n\
+\n\
+The M column contains a * for buffers that are modified.\n\
+The R column contains a % for buffers that are read-only.")
+ (files)
+ Lisp_Object files;
+{
+ internal_with_output_to_temp_buffer ("*Buffer List*",
+ list_buffers_1, files);
+ return Qnil;
+}
+
+DEFUN ("kill-all-local-variables", Fkill_all_local_variables, Skill_all_local_variables,
+ 0, 0, 0,
+ "Eliminate all the buffer-local variable values of the current buffer.\n\
+This buffer will then see the default values of all variables.")
+ ()
+{
+ register Lisp_Object alist, sym, tem;
+
+ for (alist = current_buffer->local_var_alist; !NULL (alist); alist = XCONS (alist)->cdr)
+ {
+ sym = XCONS (XCONS (alist)->car)->car;
+
+ /* Need not do anything if some other buffer's binding is now encached. */
+ tem = XCONS (XCONS (XSYMBOL (sym)->value)->cdr)->car;
+ if (XBUFFER (tem) == current_buffer)
+ {
+ /* Symbol is set up for this buffer's old local value.
+ Set it up for the current buffer with the default value. */
+
+ tem = XCONS (XCONS (XSYMBOL (sym)->value)->cdr)->cdr;
+ XCONS (tem)->car = tem;
+ XCONS (XCONS (XSYMBOL (sym)->value)->cdr)->car = Fcurrent_buffer ();
+ store_symval_forwarding (sym, XCONS (XSYMBOL (sym)->value)->car,
+ XCONS (tem)->cdr);
+ }
+ }
+
+ reset_buffer_local_variables (current_buffer);
+ return Qnil;
+}
+
+extern Lisp_Object Vprin1_to_string_buffer; /* in print.c */
+init_buffer_once ()
+{
+ register Lisp_Object tem;
+
+ /* Make sure all markable slots in buffer_defaults
+ are initialized reasonably, so mark_buffer won't choke. */
+ reset_buffer (&buffer_defaults);
+ reset_buffer (&buffer_local_symbols);
+ XSET (Vbuffer_defaults, Lisp_Buffer, &buffer_defaults);
+ XSET (Vbuffer_local_symbols, Lisp_Buffer, &buffer_local_symbols);
+
+ /* Set up the default values of various buffer slots. */
+ /* Must do these before making the first buffer! */
+
+ /* real setup is done in loaddefs.el */
+ buffer_defaults.mode_line_format = build_string ("%-");
+ buffer_defaults.abbrev_mode = Qnil;
+ buffer_defaults.overwrite_mode = Qnil;
+ buffer_defaults.case_fold_search = Qt;
+ buffer_defaults.auto_fill_hook = Qnil;
+ buffer_defaults.selective_display = Qnil;
+ buffer_defaults.selective_display_ellipses = Qt;
+ buffer_defaults.abbrev_table = Qnil;
+ buffer_defaults.undo_list = Qnil;
+
+ XFASTINT (buffer_defaults.tab_width) = 8;
+ buffer_defaults.truncate_lines = Qnil;
+ buffer_defaults.ctl_arrow = Qt;
+
+ XFASTINT (buffer_defaults.fill_column) = 70;
+ XFASTINT (buffer_defaults.left_margin) = 0;
+
+ /* Assign the local-flags to the slots that have default values.
+ The local flag is a bit that is used in the buffer
+ to say that it has its own local value for the slot.
+ The local flag bits are in the local_var_flags slot of the buffer. */
+
+ /* Nothing can work if this isn't true */
+ if (sizeof (int) != sizeof (Lisp_Object)) abort ();
+
+ /* 0 means not a lisp var, -1 means always local, else mask */
+ bzero (&buffer_local_flags, sizeof buffer_local_flags);
+ XFASTINT (buffer_local_flags.filename) = -1;
+ XFASTINT (buffer_local_flags.directory) = -1;
+ XFASTINT (buffer_local_flags.backed_up) = -1;
+ XFASTINT (buffer_local_flags.save_length) = -1;
+ XFASTINT (buffer_local_flags.auto_save_file_name) = -1;
+ XFASTINT (buffer_local_flags.read_only) = -1;
+ XFASTINT (buffer_local_flags.major_mode) = -1;
+ XFASTINT (buffer_local_flags.mode_name) = -1;
+ XFASTINT (buffer_local_flags.undo_list) = -1;
+
+ XFASTINT (buffer_local_flags.mode_line_format) = 1;
+ XFASTINT (buffer_local_flags.abbrev_mode) = 2;
+ XFASTINT (buffer_local_flags.overwrite_mode) = 4;
+ XFASTINT (buffer_local_flags.case_fold_search) = 8;
+ XFASTINT (buffer_local_flags.auto_fill_hook) = 0x10;
+ XFASTINT (buffer_local_flags.selective_display) = 0x20;
+ XFASTINT (buffer_local_flags.selective_display_ellipses) = 0x40;
+ XFASTINT (buffer_local_flags.tab_width) = 0x80;
+ XFASTINT (buffer_local_flags.truncate_lines) = 0x100;
+ XFASTINT (buffer_local_flags.ctl_arrow) = 0x200;
+ XFASTINT (buffer_local_flags.fill_column) = 0x400;
+ XFASTINT (buffer_local_flags.left_margin) = 0x800;
+ XFASTINT (buffer_local_flags.abbrev_table) = 0x1000;
+ XFASTINT (buffer_local_flags.syntax_table) = 0x2000;
+
+ Vbuffer_alist = Qnil;
+ current_buffer = 0;
+ all_buffers = 0;
+
+ QSFundamental = build_string ("Fundamental");
+
+ Qfundamental_mode = intern ("fundamental-mode");
+ buffer_defaults.major_mode = Qfundamental_mode;
+
+ Qmode_class = intern ("mode-class");
+
+ Vprin1_to_string_buffer = Fget_buffer_create (build_string (" prin1"));
+ /* super-magic invisible buffer */
+ Vbuffer_alist = Qnil;
+
+ Fset_buffer (Fget_buffer_create (build_string ("*scratch*")));
+}
+
+init_buffer ()
+{
+ char buf[MAXPATHLEN+1];
+
+ Fset_buffer (Fget_buffer_create (build_string ("*scratch*")));
+ if (getwd (buf) == 0)
+ fatal ("`getwd' failed: %s.\n", buf);
+
+#ifndef VMS
+ /* Maybe this should really use some standard subroutine
+ whose definition is filename syntax dependent. */
+ if (buf[strlen (buf) - 1] != '/')
+ strcat (buf, "/");
+#endif /* not VMS */
+ current_buffer->directory = build_string (buf);
+}
+
+/* initialize the buffer routines */
+syms_of_buffer ()
+{
+ staticpro (&Vbuffer_defaults);
+ staticpro (&Vbuffer_local_symbols);
+ staticpro (&Qfundamental_mode);
+ staticpro (&Qmode_class);
+ staticpro (&QSFundamental);
+ staticpro (&Vbuffer_alist);
+
+/*staticpro (&Qlisp_mode);
+ Qlisp_mode = intern ("lisp-mode");
+*/
+
+ /* All these use DEFVAR_LISP_NOPRO because the slots in
+ buffer_defaults will all be marked via Vbuffer_defaults. */
+
+ DEFVAR_LISP_NOPRO ("default-mode-line-format",
+ &buffer_defaults.mode_line_format,
+ "Default mode-line-format for buffers that do not override it.\n\
+This is the same as (default-value 'mode-line-format).");
+
+ DEFVAR_LISP_NOPRO ("default-abbrev-mode",
+ &buffer_defaults.abbrev_mode,
+ "Default abbrev-mode for buffers that do not override it.\n\
+This is the same as (default-value 'abbrev-mode).");
+
+ DEFVAR_LISP_NOPRO ("default-ctl-arrow",
+ &buffer_defaults.ctl_arrow,
+ "Default ctl-arrow for buffers that do not override it.\n\
+This is the same as (default-value 'ctl-arrow).");
+
+ DEFVAR_LISP_NOPRO ("default-truncate-lines",
+ &buffer_defaults.truncate_lines,
+ "Default truncate-lines for buffers that do not override it.\n\
+This is the same as (default-value 'truncate-lines).");
+
+ DEFVAR_LISP_NOPRO ("default-fill-column",
+ &buffer_defaults.fill_column,
+ "Default fill-column for buffers that do not override it.\n\
+This is the same as (default-value 'fill-column).");
+
+ DEFVAR_LISP_NOPRO ("default-left-margin",
+ &buffer_defaults.left_margin,
+ "Default left-margin for buffers that do not override it.\n\
+This is the same as (default-value 'left-margin).");
+
+ DEFVAR_LISP_NOPRO ("default-tab-width",
+ &buffer_defaults.tab_width,
+ "Default tab-width for buffers that do not override it.\n\
+This is the same as (default-value 'tab-width).");
+
+ DEFVAR_LISP_NOPRO ("default-case-fold-search",
+ &buffer_defaults.case_fold_search,
+ "Default case-fold-search for buffers that do not override it.\n\
+This is the same as (default-value 'case-fold-search).");
+
+ DEFVAR_PER_BUFFER ("mode-line-format", &current_buffer->mode_line_format, 0);
+
+/* This doc string is too long for cpp; cpp dies.
+ DEFVAR_PER_BUFFER ("mode-line-format", &current_buffer->mode_line_format,
+ "Template for displaying mode line for current buffer.\n\
+Each buffer has its own value of this variable.\n\
+Value may be a string, a symbol or a list or cons cell.\n\
+For a symbol, its value is used (but it is ignored if t or nil).\n\
+ A string appearing directly as the value of a symbol is processed verbatim\n\
+ in that the %-constructs below are not recognized.\n\
+For a list whose car is a symbol, the symbol's value is taken,\n\
+ and if that is non-nil, the cadr of the list is processed recursively.\n\
+ Otherwise, the caddr of the list (if there is one) is processed.\n\
+For a list whose car is a string or list, each element is processed\n\
+ recursively and the results are effectively concatenated.\n\
+For a list whose car is an integer, the cdr of the list is processed\n\
+ and padded (if the number is positive) or truncated (if negative)\n\
+ to the width specified by that number.\n\
+A string is printed verbatim in the mode line except for %-constructs:\n\
+ (%-constructs are allowed when the string is the entire mode-line-format\n\
+ or when it is found in a cons-cell or a list)\n\
+ %b -- print buffer name. %f -- print visited file name.\n\
+ %* -- print *, % or hyphen. %m -- print value of mode-name (obsolete).\n\
+ %s -- print process status. %M -- print value of global-mode-string. (obs)\n\
+ %p -- print percent of buffer above top of window, or top, bot or all.\n\
+ %n -- print Narrow if appropriate.\n\
+ %[ -- print one [ for each recursive editing level. %] similar.\n\
+ %% -- print %. %- -- print infinitely many dashes.\n\
+Decimal digits after the % specify field width to which to pad.");
+*/
+
+ DEFVAR_LISP_NOPRO ("default-major-mode", &buffer_defaults.major_mode,
+ "*Major mode for new buffers. Defaults to fundamental-mode.\n\
+nil here means use current buffer's major mode.");
+
+ DEFVAR_PER_BUFFER ("major-mode", &current_buffer->major_mode,
+ "Symbol for current buffer's major mode.");
+
+ DEFVAR_PER_BUFFER ("abbrev-mode", &current_buffer->abbrev_mode,
+ "Non-nil turns on automatic expansion of abbrevs when inserted.\n\
+Automatically becomes local when set in any fashion.");
+
+ DEFVAR_PER_BUFFER ("case-fold-search", &current_buffer->case_fold_search,
+ "*Non-nil if searches should ignore case.\n\
+Automatically becomes local when set in any fashion.");
+
+ DEFVAR_PER_BUFFER ("mode-name", &current_buffer->mode_name,
+ "Pretty name of current buffer's major mode (a string).");
+
+ DEFVAR_PER_BUFFER ("fill-column", &current_buffer->fill_column,
+ "*Column beyond which automatic line-wrapping should happen.\n\
+Automatically becomes local when set in any fashion.");
+
+ DEFVAR_PER_BUFFER ("left-margin", &current_buffer->left_margin,
+ "*Column for the default indent-line-function to indent to.\n\
+Linefeed indents to this column in Fundamental mode.\n\
+Automatically becomes local when set in any fashion.");
+
+ DEFVAR_PER_BUFFER ("tab-width", &current_buffer->tab_width,
+ "*Distance between tab stops (for display of tab characters), in columns.\n\
+Automatically becomes local when set in any fashion.");
+
+ DEFVAR_PER_BUFFER ("ctl-arrow", &current_buffer->ctl_arrow,
+ "*Non-nil means display control chars with uparrow.\n\
+Nil means use backslash and octal digits.\n\
+Automatically becomes local when set in any fashion.");
+
+ DEFVAR_PER_BUFFER ("truncate-lines", &current_buffer->truncate_lines,
+ "*Non-nil means do not display continuation lines;\n\
+give each line of text one screen line.\n\
+Automatically becomes local when set in any fashion.\n\
+\n\
+Note that this is overridden by the variable\n\
+truncate-partial-width-windows if that variable is non-nil\n\
+and this buffer is not full-screen width.");
+
+ DEFVAR_PER_BUFFER ("default-directory", &current_buffer->directory,
+ "Name of default directory of current buffer. Should end with slash.");
+
+ DEFVAR_PER_BUFFER ("auto-fill-hook", &current_buffer->auto_fill_hook,
+ "Function called (if non-nil) after self-inserting a space at column beyond fill-column");
+
+ DEFVAR_PER_BUFFER ("buffer-file-name", &current_buffer->filename,
+ "Name of file visited in current buffer, or nil if not visiting a file.");
+
+ DEFVAR_PER_BUFFER ("buffer-auto-save-file-name",
+ &current_buffer->auto_save_file_name,
+ "Name of file for auto-saving current buffer,\n\
+or nil if buffer should not be auto-saved.");
+
+ DEFVAR_PER_BUFFER ("buffer-read-only", &current_buffer->read_only,
+ "Non-nil if this buffer is read-only.");
+
+ DEFVAR_PER_BUFFER ("buffer-backed-up", &current_buffer->backed_up,
+ "Non-nil if this buffer's file has been backed up.\n\
+Backing up is done before the first time the file is saved.");
+
+ DEFVAR_PER_BUFFER ("buffer-saved-size", &current_buffer->save_length,
+ "Length of current buffer when last read in, saved or auto-saved.\n\
+0 initially.");
+
+ DEFVAR_PER_BUFFER ("selective-display", &current_buffer->selective_display,
+ "t enables selective display:\n\
+ after a ^M, all the rest of the line is invisible.\n\
+ ^M's in the file are written into files as newlines.\n\
+Integer n as value means display only lines\n\
+ that start with less than n columns of space.\n\
+Automatically becomes local when set in any fashion.");
+
+ DEFVAR_PER_BUFFER ("selective-display-ellipses",
+ &current_buffer->selective_display_ellipses,
+ "t means display ... on previous line when a line is invisible.\n\
+Automatically becomes local when set in any fashion.");
+
+ DEFVAR_PER_BUFFER ("overwrite-mode", &current_buffer->overwrite_mode,
+ "Non-nil if self-insertion should replace existing text.\n\
+Automatically becomes local when set in any fashion.");
+
+ DEFVAR_PER_BUFFER ("buffer-undo-list", &current_buffer->undo_list,
+ "List of undo entries in current buffer.");
+
+/*DEFVAR_LISP ("debug-check-symbol", &Vcheck_symbol,
+ "Don't ask.");
+*/
+ defsubr (&Sbuffer_list);
+ defsubr (&Sget_buffer);
+ defsubr (&Sget_file_buffer);
+ defsubr (&Sget_buffer_create);
+ defsubr (&Sgenerate_new_buffer);
+ defsubr (&Sbuffer_name);
+/*defsubr (&Sbuffer_number);*/
+ defsubr (&Sbuffer_file_name);
+ defsubr (&Sbuffer_local_variables);
+ defsubr (&Sbuffer_modified_p);
+ defsubr (&Sset_buffer_modified_p);
+ defsubr (&Srename_buffer);
+ defsubr (&Sother_buffer);
+ defsubr (&Sbuffer_flush_undo);
+ defsubr (&Sbuffer_enable_undo);
+ defsubr (&Skill_buffer);
+ defsubr (&Serase_buffer);
+ defsubr (&Sswitch_to_buffer);
+ defsubr (&Spop_to_buffer);
+ defsubr (&Scurrent_buffer);
+ defsubr (&Sset_buffer);
+ defsubr (&Sbarf_if_buffer_read_only);
+ defsubr (&Sbury_buffer);
+ defsubr (&Slist_buffers);
+ defsubr (&Skill_all_local_variables);
+}
+
+keys_of_buffer ()
+{
+ ndefkey (Vctl_x_map, 'b', "switch-to-buffer");
+ ndefkey (Vctl_x_map, 'k', "kill-buffer");
+ ndefkey (Vctl_x_map, Ctl ('B'), "list-buffers");
+}
diff --git a/src/buffer.h b/src/buffer.h
index f475bbdbafe..a4990664570 100644
--- a/src/buffer.h
+++ b/src/buffer.h
@@ -18,50 +18,35 @@ along with GNU Emacs; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-#ifdef lint
-#include "undo.h"
-#endif /* lint */
+#define SET_PT PT =
-
-#define SET_PT(position) (current_buffer->text.pt = (position))
+/* Just for laughs, use the same names as in ITS TECO, around 1973. */
/* Character position of beginning of buffer. */
#define BEG (1)
-
/* Character position of beginning of accessible range of buffer. */
#define BEGV (current_buffer->text.begv)
-
-/* Character position of point in buffer. The "+ 0" makes this
- not an l-value, so you can't assign to it. Use SET_PT instead. */
-#define PT (current_buffer->text.pt + 0)
-
+/* Character position of point in buffer. */
+#define PT (current_buffer->text.pt)
/* Character position of gap in buffer. */
#define GPT (current_buffer->text.gpt)
-
/* Character position of end of accessible range of buffer. */
#define ZV (current_buffer->text.zv)
-
/* Character position of end of buffer. */
#define Z (current_buffer->text.z)
-
/* Modification count. */
#define MODIFF (current_buffer->text.modiff)
/* Address of beginning of buffer. */
#define BEG_ADDR (current_buffer->text.beg)
-
/* Address of beginning of accessible range of buffer. */
#define BEGV_ADDR (&FETCH_CHAR (current_buffer->text.begv))
-
/* Address of point in buffer. */
#define PT_ADDR (&FETCH_CHAR (current_buffer->text.pt))
-
/* Address of beginning of gap in buffer. */
#define GPT_ADDR (current_buffer->text.beg + current_buffer->text.gpt - 1)
-
/* Address of end of gap in buffer. */
#define GAP_END_ADDR (current_buffer->text.beg + current_buffer->text.gpt + current_buffer->text.gap_size - 1)
-
/* Address of end of accessible range of buffer. */
#define ZV_ADDR (&FETCH_CHAR (current_buffer->text.zv))
@@ -73,22 +58,16 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Character position of beginning of buffer. */
#define BUF_BEG(buf) (1)
-
/* Character position of beginning of accessible range of buffer. */
#define BUF_BEGV(buf) ((buf)->text.begv)
-
/* Character position of point in buffer. */
#define BUF_PT(buf) ((buf)->text.pt)
-
/* Character position of gap in buffer. */
#define BUF_GPT(buf) ((buf)->text.gpt)
-
/* Character position of end of accessible range of buffer. */
#define BUF_ZV(buf) ((buf)->text.zv)
-
/* Character position of end of buffer. */
#define BUF_Z(buf) ((buf)->text.z)
-
/* Modification count. */
#define BUF_MODIFF(buf) ((buf)->text.modiff)
@@ -111,34 +90,33 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Convert the address of a char in the buffer into a character position. */
#define PTR_CHAR_POS(ptr) \
-((ptr) - (current_buffer)->text.beg \
- - (ptr - (current_buffer)->text.beg < (unsigned) GPT ? 0 : GAP_SIZE) \
- + 1)
+((ptr) - (current_buffer)->text.beg \
+ - (ptr - (current_buffer)->text.beg < (unsigned) GPT ? 0 : GAP_SIZE))
struct buffer_text
{
- unsigned char *beg; /* Actual address of buffer contents. */
- int begv; /* Index of beginning of accessible range. */
- int pt; /* Position of point in buffer. */
- int gpt; /* Index of gap in buffer. */
- int zv; /* Index of end of accessible range. */
- int z; /* Index of end of buffer. */
- int gap_size; /* Size of buffer's gap */
- int modiff; /* This counts buffer-modification events
- for this buffer. It is incremented for
- each such event, and never otherwise
- changed. */
-
+ /* Actual address of buffer contents. */
+ unsigned char *beg;
+ /* Values of BEGV ... Z in this buffer. */
+ int begv;
+ int pt;
+ int gpt;
+ int zv;
+ int z;
+ /* Value of GAP_SIZE in this buffer. */
+ int gap_size;
+ /* This counts buffer-modification events for this buffer.
+ It is incremented for each such event, and never otherwise changed. */
+ int modiff;
};
struct buffer
{
/* Everything before the `name' slot must be of a non-Lisp_Object type,
- and every slot after `name' must be a Lisp_Object.
-
- Check out mark_buffer (alloc.c) to see why.
+ and every slot after `name' must be a Lisp_Object
+ This is known about by both mark_buffer (alloc.c) and
+ Flist_buffer_local_variables (buffer.c)
*/
-
/* This structure holds the coordinates of the buffer contents. */
struct buffer_text text;
/* Next buffer, in chain of all buffers including killed buffers.
@@ -148,22 +126,22 @@ struct buffer
/* Flags saying which DEFVAR_PER_BUFFER variables
are local to this buffer. */
int local_var_flags;
- /* Value of text.modified as of when visited file was read or written. */
+ /* Value of text.modified as of when visited file was read or written. */
int save_modified;
+ /* the value of text.modified at the last auto-save. */
+ int auto_save_modified;
/* Set to the modtime of the visited file when read or written.
-1 means visited file was nonexistent.
0 means visited file modtime unknown; in no case complain
about any mismatch on next save attempt. */
int modtime;
- /* the value of text.modiff at the last auto-save. */
- int auto_save_modified;
/* Position in buffer at which display started
the last time this buffer was displayed */
int last_window_start;
/* This is a special exception -- as this slot should not be
marked by gc_sweep, and as it is not lisp-accessible as
- a local variable -- so we regard it as not really being of type
+ a local variable -- so re regard it as not really being of type
Lisp_Object */
/* the markers that refer to this buffer.
This is actually a single marker ---
@@ -178,12 +156,11 @@ struct buffer
/* the name of this buffer */
Lisp_Object name;
- /* Nuked: buffer number, assigned when buffer made Lisp_Object number;*/
/* the name of the file associated with this buffer */
Lisp_Object filename;
/* Dir for expanding relative pathnames */
Lisp_Object directory;
- /* true iff this buffer has been been backed
+ /* True iff this buffer has been been backed
up (if you write to its associated file
and it hasn't been backed up, then a
backup will be made) */
@@ -207,14 +184,14 @@ struct buffer
Lisp_Object major_mode;
/* Pretty name of major mode (eg "Lisp") */
Lisp_Object mode_name;
- /* Format string for mode line */
+ /* Format description for mode line */
Lisp_Object mode_line_format;
/* Keys that are bound local to this buffer */
Lisp_Object keymap;
/* This buffer's local abbrev table */
Lisp_Object abbrev_table;
- /* This buffer's syntax table. */
+ /* This buffer's syntax table. */
Lisp_Object syntax_table;
/* Values of several buffer-local variables */
@@ -224,13 +201,8 @@ struct buffer
Lisp_Object tab_width;
Lisp_Object fill_column;
Lisp_Object left_margin;
- /* Function to call when insert space past fill column */
- Lisp_Object auto_fill_function;
-
- /* String of length 256 mapping each char to its lower-case version. */
- Lisp_Object downcase_table;
- /* String of length 256 mapping each char to its upper-case version. */
- Lisp_Object upcase_table;
+ /* Function to call when insert space past fiull column */
+ Lisp_Object auto_fill_hook;
/* Non-nil means do not display continuation lines */
Lisp_Object truncate_lines;
@@ -239,31 +211,18 @@ struct buffer
/* Non-nil means do selective display;
See doc string in syms_of_buffer (buffer.c) for details. */
Lisp_Object selective_display;
-#ifndef old
/* Non-nil means show ... at end of line followed by invisible lines. */
Lisp_Object selective_display_ellipses;
-#endif
- /* Alist of (FUNCTION . STRING) for each minor mode enabled in buffer. */
- Lisp_Object minor_modes;
/* t if "self-insertion" should overwrite */
Lisp_Object overwrite_mode;
/* non-nil means abbrev mode is on. Expand abbrevs automatically. */
Lisp_Object abbrev_mode;
- /* Display table to use for text in this buffer. */
- Lisp_Object display_table;
- /* Translate table for case-folding search. */
- Lisp_Object case_canon_table;
- /* Inverse translate (equivalence class) table for case-folding search. */
- Lisp_Object case_eqv_table;
/* Changes in the buffer are recorded here for undo.
t means don't record anything. */
Lisp_Object undo_list;
-
- /* List of fields in this buffer. */
- Lisp_Object fieldlist;
};
-extern struct buffer *current_buffer;
+extern struct buffer *current_buffer; /* points to the current buffer */
/* This structure holds the default values of the buffer-local variables
defined with DefBufferLispVar, that have special slots in each buffer.
@@ -295,63 +254,17 @@ extern struct buffer buffer_local_flags;
extern struct buffer buffer_local_symbols;
-/* Point in the current buffer. */
+/* Some aliases for info about the current buffer. */
-#define point (current_buffer->text.pt + 0)
+#define point current_buffer->text.pt
/* Return character at position n. No range checking */
#define FETCH_CHAR(n) *(((n)>= GPT ? GAP_SIZE : 0) + (n) + BEG_ADDR - 1)
+
+/* BufferSafeCeiling (resp. BufferSafeFloor), when applied to n, return */
+/* the max (resp. min) p such that &FETCH_CHAR (p) - &FETCH_CHAR (n) == p - n */
+#define BufferSafeCeiling(n) (((n) < GPT && GPT < ZV ? GPT : ZV) - 1)
-/* BUFFER_CEILING_OF (resp. BUFFER_FLOOR_OF), when applied to n, return
- the max (resp. min) p such that
-
- &FETCH_CHAR (p) - &FETCH_CHAR (n) == p - n */
-
-#define BUFFER_CEILING_OF(n) (((n) < GPT && GPT < ZV ? GPT : ZV) - 1)
-#define BUFFER_FLOOR_OF(n) (BEGV <= GPT && GPT <= (n) ? GPT : BEGV)
+#define BufferSafeFloor(n) (BEGV <= GPT && GPT <= (n) ? GPT : BEGV)
extern void reset_buffer ();
-
-/* Functions to call before and after each text change. */
-extern Lisp_Object Vbefore_change_function;
-extern Lisp_Object Vafter_change_function;
-extern Lisp_Object Vfirst_change_function;
-
-/* Fields.
-
-A field is like a marker but it defines a region rather than a
-point. Like a marker, a field is asocated with a buffer.
-The field mechanism uses the marker mechanism in the
-sense that its start and end points are maintained as markers
-updated in the usual way as the buffer changes.
-
-A field can be protected or unprotected. If it is protected,
-no modifications can be made that affect the field in its buffer,
-when protected field checking is enabled.
-
-Each field also contains an alist, in which you can store
-whatever you like. */
-
-/* Slots in a field: */
-
-#define FIELD_BUFFER(f) (XVECTOR(f)->contents[1])
-#define FIELD_START_MARKER(f) (XVECTOR(f)->contents[2])
-#define FIELD_END_MARKER(f) (XVECTOR(f)->contents[3])
-#define FIELD_PROTECTED_FLAG(f) (XVECTOR(f)->contents[4])
-#define FIELD_ALIST(f) (XVECTOR(f)->contents[5])
-
-/* Allocation of buffer data. */
-#ifdef REL_ALLOC
-#define BUFFER_ALLOC(data,size) ((unsigned char *) r_alloc (&data, (size)))
-#define BUFFER_REALLOC(data,size) ((unsigned char *) r_re_alloc (&data, (size)))
-#define BUFFER_FREE(data) (r_alloc_free (&data))
-#define R_ALLOC_DECLARE(var,data) (r_alloc_declare (&var, (data)))
-#else
-#define BUFFER_ALLOC(data,size) (data = (unsigned char *) malloc ((size)))
-#define BUFFER_REALLOC(data,size) ((unsigned char *) realloc ((data), (size)))
-#define BUFFER_FREE(data) (free ((data)))
-#define R_ALLOC_DECLARE(var,data)
-#endif
-
-/* A search buffer, with a fastmap allocated and ready to go. */
-extern struct re_pattern_buffer searchbuf;
diff --git a/src/build.com b/src/build.com
new file mode 100644
index 00000000000..c0dff1d242f
--- /dev/null
+++ b/src/build.com
@@ -0,0 +1,5 @@
+$ ! VMS command file to run `temacs.exe' and dump the data file `temacs.dump'.
+$ if f$search("temacs.dump;") .nes. "" then delete temacs.dump;*
+$ temacs :== $emacs_library:[src]temacs -batch
+$ temacs -l inc-vers
+$ temacs -l loadup.el dump
diff --git a/src/bytecode.c b/src/bytecode.c
new file mode 100644
index 00000000000..1a7cd7d73ca
--- /dev/null
+++ b/src/bytecode.c
@@ -0,0 +1,734 @@
+/* Execution of byte code produced by bytecomp.el.
+ Copyright (C) 1985, 1986, 1987 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#include "config.h"
+#include "lisp.h"
+#include "buffer.h"
+
+Lisp_Object Qbytecode;
+
+/* Byte codes: */
+
+#define Bvarref 010
+#define Bvarset 020
+#define Bvarbind 030
+#define Bcall 040
+#define Bunbind 050
+
+#define Bnth 070
+#define Bsymbolp 071
+#define Bconsp 072
+#define Bstringp 073
+#define Blistp 074
+#define Beq 075
+#define Bmemq 076
+#define Bnot 077
+#define Bcar 0100
+#define Bcdr 0101
+#define Bcons 0102
+#define Blist1 0103
+#define Blist2 0104
+#define Blist3 0105
+#define Blist4 0106
+#define Blength 0107
+#define Baref 0110
+#define Baset 0111
+#define Bsymbol_value 0112
+#define Bsymbol_function 0113
+#define Bset 0114
+#define Bfset 0115
+#define Bget 0116
+#define Bsubstring 0117
+#define Bconcat2 0120
+#define Bconcat3 0121
+#define Bconcat4 0122
+#define Bsub1 0123
+#define Badd1 0124
+#define Beqlsign 0125
+#define Bgtr 0126
+#define Blss 0127
+#define Bleq 0130
+#define Bgeq 0131
+#define Bdiff 0132
+#define Bnegate 0133
+#define Bplus 0134
+#define Bmax 0135
+#define Bmin 0136
+
+#define Bpoint 0140
+#define Bmark 0141 /* no longer generated as of v18 */
+#define Bgoto_char 0142
+#define Binsert 0143
+#define Bpoint_max 0144
+#define Bpoint_min 0145
+#define Bchar_after 0146
+#define Bfollowing_char 0147
+#define Bpreceding_char 0150
+#define Bcurrent_column 0151
+#define Bindent_to 0152
+#define Bscan_buffer 0153 /* No longer generated as of v18 */
+#define Beolp 0154
+#define Beobp 0155
+#define Bbolp 0156
+#define Bbobp 0157
+#define Bcurrent_buffer 0160
+#define Bset_buffer 0161
+#define Bread_char 0162
+#define Bset_mark 0163 /* this loser is no longer generated as of v18 */
+#define Binteractive_p 0164 /* Needed since interactive-p takes unevalled args */
+
+#define Bconstant2 0201
+#define Bgoto 0202
+#define Bgotoifnil 0203
+#define Bgotoifnonnil 0204
+#define Bgotoifnilelsepop 0205
+#define Bgotoifnonnilelsepop 0206
+#define Breturn 0207
+#define Bdiscard 0210
+#define Bdup 0211
+
+#define Bsave_excursion 0212
+#define Bsave_window_excursion 0213
+#define Bsave_restriction 0214
+#define Bcatch 0215
+
+#define Bunwind_protect 0216
+#define Bcondition_case 0217
+#define Btemp_output_buffer_setup 0220
+#define Btemp_output_buffer_show 0221
+
+#define Bconstant 0300
+#define CONSTANTLIM 0100
+
+/* Fetch the next byte from the bytecode stream */
+
+#define FETCH ((unsigned char *)XSTRING (bytestr)->data)[pc++]
+
+/* Fetch two bytes from the bytecode stream
+ and make a 16-bit number out of them */
+
+#define FETCH2 (op = FETCH, op + (FETCH << 8))
+
+/* Push x onto the execution stack. */
+
+#define PUSH(x) (*++stackp = (x))
+
+/* Pop a value off the execution stack. */
+
+#define POP (*stackp--)
+
+/* Discard n values from the execution stack. */
+
+#define DISCARD(n) (stackp -= (n))
+
+/* Get the value which is at the top of the execution stack, but don't pop it. */
+
+#define TOP (*stackp)
+
+
+DEFUN ("byte-code", Fbyte_code, Sbyte_code, 3, 3, 0,
+ "")
+ (bytestr, vector, maxdepth)
+ Lisp_Object bytestr, vector, maxdepth;
+{
+ struct gcpro gcpro1, gcpro2, gcpro3;
+ int count = specpdl_ptr - specpdl;
+ register int pc = 0;
+ register int op;
+ Lisp_Object *stack;
+ register Lisp_Object *stackp;
+ Lisp_Object *stacke;
+ register Lisp_Object v1, v2;
+ register Lisp_Object *vectorp = XVECTOR (vector)->contents;
+
+ CHECK_STRING (bytestr, 0);
+ if (XTYPE (vector) != Lisp_Vector)
+ vector = wrong_type_argument (Qvectorp, vector);
+ CHECK_NUMBER (maxdepth, 2);
+
+ stackp = (Lisp_Object *) alloca (XFASTINT (maxdepth) * sizeof (Lisp_Object));
+ bzero (stackp, XFASTINT (maxdepth) * sizeof (Lisp_Object));
+ GCPRO3 (bytestr, vector, *stackp);
+ gcpro3.nvars = XFASTINT (maxdepth);
+
+ --stackp;
+ stack = stackp;
+ stacke = stackp + XFASTINT (maxdepth);
+
+ while (1)
+ {
+ if (stackp > stacke)
+ error ("Stack overflow in byte code (byte compiler bug), pc = %d", pc);
+ if (stackp < stack)
+ error ("Stack underflow in byte code (byte compiler bug), pc = %d", pc);
+ switch (op = FETCH)
+ {
+ case Bvarref+6:
+ op = FETCH;
+ goto varref;
+
+ case Bvarref+7:
+ op = FETCH2;
+ goto varref;
+
+ case Bvarref: case Bvarref+1: case Bvarref+2: case Bvarref+3:
+ case Bvarref+4: case Bvarref+5:
+ op = op - Bvarref;
+ varref:
+ v1 = vectorp[op];
+ if (XTYPE (v1) != Lisp_Symbol)
+ v2 = Fsymbol_value (v1);
+ else
+ {
+ v2 = XSYMBOL (v1)->value;
+#ifdef SWITCH_ENUM_BUG
+ switch ((int) XTYPE (v2))
+#else
+ switch (XTYPE (v2))
+#endif
+ {
+ case Lisp_Symbol:
+ if (!EQ (v2, Qunbound))
+ break;
+ case Lisp_Intfwd:
+ case Lisp_Boolfwd:
+ case Lisp_Objfwd:
+ case Lisp_Buffer_Local_Value:
+ case Lisp_Some_Buffer_Local_Value:
+ case Lisp_Buffer_Objfwd:
+ case Lisp_Void:
+ v2 = Fsymbol_value (v1);
+ }
+ }
+ PUSH (v2);
+ break;
+
+ case Bvarset+6:
+ op = FETCH;
+ goto varset;
+
+ case Bvarset+7:
+ op = FETCH2;
+ goto varset;
+
+ case Bvarset: case Bvarset+1: case Bvarset+2: case Bvarset+3:
+ case Bvarset+4: case Bvarset+5:
+ op -= Bvarset;
+ varset:
+ Fset (vectorp[op], POP);
+ break;
+
+ case Bvarbind+6:
+ op = FETCH;
+ goto varbind;
+
+ case Bvarbind+7:
+ op = FETCH2;
+ goto varbind;
+
+ case Bvarbind: case Bvarbind+1: case Bvarbind+2: case Bvarbind+3:
+ case Bvarbind+4: case Bvarbind+5:
+ op -= Bvarbind;
+ varbind:
+ specbind (vectorp[op], POP);
+ break;
+
+ case Bcall+6:
+ op = FETCH;
+ goto docall;
+
+ case Bcall+7:
+ op = FETCH2;
+ goto docall;
+
+ case Bcall: case Bcall+1: case Bcall+2: case Bcall+3:
+ case Bcall+4: case Bcall+5:
+ op -= Bcall;
+ docall:
+ DISCARD(op);
+ /* Ffuncall now follows the standard convention that a
+ function with MANY args relies on the caller to protect. */
+#if 0
+ /* Remove protection from the args we are giving to Ffuncall.
+ FFuncall will protect them, and double protection would
+ cause disasters. */
+ gcpro3.nvars = &TOP - stack - 1;
+#endif
+ TOP = Ffuncall (op + 1, &TOP);
+#if 0
+ gcpro3.nvars = XFASTINT (maxdepth);
+#endif
+ break;
+
+ case Bunbind+6:
+ op = FETCH;
+ goto dounbind;
+
+ case Bunbind+7:
+ op = FETCH2;
+ goto dounbind;
+
+ case Bunbind: case Bunbind+1: case Bunbind+2: case Bunbind+3:
+ case Bunbind+4: case Bunbind+5:
+ op -= Bunbind;
+ dounbind:
+ unbind_to (specpdl_ptr - specpdl - op);
+ break;
+
+ case Bgoto:
+ QUIT;
+ op = FETCH2; /* pc = FETCH2 loses since FETCH2 contains pc++ */
+ /* A loop always uses a plain goto to jump back.
+ So this makes sure we consider GC in each loop. */
+ if (op < pc && consing_since_gc > gc_cons_threshold)
+ Fgarbage_collect ();
+ pc = op;
+ break;
+
+ case Bgotoifnil:
+ QUIT;
+ op = FETCH2;
+ if (NULL (POP))
+ pc = op;
+ break;
+
+ case Bgotoifnonnil:
+ QUIT;
+ op = FETCH2;
+ if (!NULL (POP))
+ pc = op;
+ break;
+
+ case Bgotoifnilelsepop:
+ QUIT;
+ op = FETCH2;
+ if (NULL (TOP))
+ pc = op;
+ else DISCARD(1);
+ break;
+
+ case Bgotoifnonnilelsepop:
+ QUIT;
+ op = FETCH2;
+ if (!NULL (TOP))
+ pc = op;
+ else DISCARD(1);
+ break;
+
+ case Breturn:
+ v1 = POP;
+ goto exit;
+
+ case Bdiscard:
+ DISCARD(1);
+ break;
+
+ case Bdup:
+ v1 = TOP;
+ PUSH (v1);
+ break;
+
+ case Bconstant2:
+ PUSH (vectorp[FETCH2]);
+ break;
+
+ case Bsave_excursion:
+ record_unwind_protect (save_excursion_restore, save_excursion_save ());
+ break;
+
+ case Bsave_window_excursion:
+ TOP = Fsave_window_excursion (TOP);
+ break;
+
+ case Bsave_restriction:
+ record_unwind_protect (save_restriction_restore, save_restriction_save ());
+ break;
+
+ case Bcatch:
+ v1 = POP;
+ TOP = internal_catch (TOP, Feval, v1);
+ break;
+
+ case Bunwind_protect:
+ record_unwind_protect (0, POP);
+ (specpdl_ptr - 1)->symbol = Qnil;
+ break;
+
+ case Bcondition_case:
+ v1 = POP;
+ v1 = Fcons (POP, v1);
+ TOP = Fcondition_case (Fcons (TOP, v1));
+ break;
+
+ case Btemp_output_buffer_setup:
+ temp_output_buffer_setup (XSTRING (TOP)->data);
+ TOP = Vstandard_output;
+ break;
+
+ case Btemp_output_buffer_show:
+ v1 = POP;
+ temp_output_buffer_show (TOP);
+ TOP = v1;
+ /* pop binding of standard-output */
+ unbind_to (specpdl_ptr - specpdl - 1);
+ break;
+
+ case Bnth:
+ v1 = POP;
+ v2 = TOP;
+ CHECK_NUMBER (v2, 0);
+ op = XINT (v2);
+ immediate_quit = 1;
+ while (--op >= 0)
+ {
+ if (CONSP (v1))
+ v1 = XCONS (v1)->cdr;
+ else if (!NULL (v1))
+ {
+ immediate_quit = 0;
+ v1 = wrong_type_argument (Qlistp, v1);
+ immediate_quit = 1;
+ op++;
+ }
+ }
+ immediate_quit = 0;
+ goto docar;
+
+ case Bsymbolp:
+ TOP = XTYPE (TOP) == Lisp_Symbol ? Qt : Qnil;
+ break;
+
+ case Bconsp:
+ TOP = CONSP (TOP) ? Qt : Qnil;
+ break;
+
+ case Bstringp:
+ TOP = XTYPE (TOP) == Lisp_String ? Qt : Qnil;
+ break;
+
+ case Blistp:
+ TOP = CONSP (TOP) || NULL (TOP) ? Qt : Qnil;
+ break;
+
+ case Beq:
+ v1 = POP;
+ TOP = EQ (v1, TOP) ? Qt : Qnil;
+ break;
+
+ case Bmemq:
+ v1 = POP;
+ TOP = Fmemq (TOP, v1);
+ break;
+
+ case Bnot:
+ TOP = NULL (TOP) ? Qt : Qnil;
+ break;
+
+ case Bcar:
+ v1 = TOP;
+ docar:
+ if (CONSP (v1)) TOP = XCONS (v1)->car;
+ else if (NULL (v1)) TOP = Qnil;
+ else Fcar (wrong_type_argument (Qlistp, v1));
+ break;
+
+ case Bcdr:
+ v1 = TOP;
+ if (CONSP (v1)) TOP = XCONS (v1)->cdr;
+ else if (NULL (v1)) TOP = Qnil;
+ else Fcdr (wrong_type_argument (Qlistp, v1));
+ break;
+
+ case Bcons:
+ v1 = POP;
+ TOP = Fcons (TOP, v1);
+ break;
+
+ case Blist1:
+ TOP = Fcons (TOP, Qnil);
+ break;
+
+ case Blist2:
+ v1 = POP;
+ TOP = Fcons (TOP, Fcons (v1, Qnil));
+ break;
+
+ case Blist3:
+ DISCARD(2);
+ TOP = Flist (3, &TOP);
+ break;
+
+ case Blist4:
+ DISCARD(3);
+ TOP = Flist (4, &TOP);
+ break;
+
+ case Blength:
+ TOP = Flength (TOP);
+ break;
+
+ case Baref:
+ v1 = POP;
+ TOP = Faref (TOP, v1);
+ break;
+
+ case Baset:
+ v2 = POP; v1 = POP;
+ TOP = Faset (TOP, v1, v2);
+ break;
+
+ case Bsymbol_value:
+ TOP = Fsymbol_value (TOP);
+ break;
+
+ case Bsymbol_function:
+ TOP = Fsymbol_function (TOP);
+ break;
+
+ case Bset:
+ v1 = POP;
+ TOP = Fset (TOP, v1);
+ break;
+
+ case Bfset:
+ v1 = POP;
+ TOP = Ffset (TOP, v1);
+ break;
+
+ case Bget:
+ v1 = POP;
+ TOP = Fget (TOP, v1);
+ break;
+
+ case Bsubstring:
+ v2 = POP; v1 = POP;
+ TOP = Fsubstring (TOP, v1, v2);
+ break;
+
+ case Bconcat2:
+ DISCARD(1);
+ TOP = Fconcat (2, &TOP);
+ break;
+
+ case Bconcat3:
+ DISCARD(2);
+ TOP = Fconcat (3, &TOP);
+ break;
+
+ case Bconcat4:
+ DISCARD(3);
+ TOP = Fconcat (4, &TOP);
+ break;
+
+ case Bsub1:
+ v1 = TOP;
+ if (XTYPE (v1) == Lisp_Int)
+ {
+ XSETINT (v1, XINT (v1) - 1);
+ TOP = v1;
+ }
+ else
+ TOP = Fsub1 (v1);
+ break;
+
+ case Badd1:
+ v1 = TOP;
+ if (XTYPE (v1) == Lisp_Int)
+ {
+ XSETINT (v1, XINT (v1) + 1);
+ TOP = v1;
+ }
+ else
+ TOP = Fadd1 (v1);
+ break;
+
+ case Beqlsign:
+ v2 = POP; v1 = TOP;
+ CHECK_NUMBER_COERCE_MARKER (v1, 0);
+ CHECK_NUMBER_COERCE_MARKER (v2, 0);
+ TOP = XINT (v1) == XINT (v2) ? Qt : Qnil;
+ break;
+
+ case Bgtr:
+ v1 = POP;
+ TOP = Fgtr (TOP, v1);
+ break;
+
+ case Blss:
+ v1 = POP;
+ TOP = Flss (TOP, v1);
+ break;
+
+ case Bleq:
+ v1 = POP;
+ TOP = Fleq (TOP, v1);
+ break;
+
+ case Bgeq:
+ v1 = POP;
+ TOP = Fgeq (TOP, v1);
+ break;
+
+ case Bdiff:
+ DISCARD(1);
+ TOP = Fminus (2, &TOP);
+ break;
+
+ case Bnegate:
+ v1 = TOP;
+ if (XTYPE (v1) == Lisp_Int)
+ {
+ XSETINT (v1, - XINT (v1));
+ TOP = v1;
+ }
+ else
+ TOP = Fminus (1, &TOP);
+ break;
+
+ case Bplus:
+ DISCARD(1);
+ TOP = Fplus (2, &TOP);
+ break;
+
+ case Bmax:
+ DISCARD(1);
+ TOP = Fmax (2, &TOP);
+ break;
+
+ case Bmin:
+ DISCARD(1);
+ TOP = Fmin (2, &TOP);
+ break;
+
+ case Bpoint:
+ XFASTINT (v1) = point;
+ PUSH (v1);
+ break;
+
+ case Bmark: /* this loser is no longer generated as of v18 */
+ PUSH (Fmarker_position (current_buffer->mark));
+ break;
+
+ case Bgoto_char:
+ TOP = Fgoto_char (TOP);
+ break;
+
+ case Binsert:
+ TOP = Finsert (1, &TOP);
+ break;
+
+ case Bpoint_max:
+ XFASTINT (v1) = ZV;
+ PUSH (v1);
+ break;
+
+ case Bpoint_min:
+ XFASTINT (v1) = BEGV;
+ PUSH (v1);
+ break;
+
+ case Bchar_after:
+ TOP = Fchar_after (TOP);
+ break;
+
+ case Bfollowing_char:
+ XFASTINT (v1) = PT == ZV ? 0 : FETCH_CHAR (point);
+ PUSH (v1);
+ break;
+
+ case Bpreceding_char:
+ XFASTINT (v1) = point == BEGV ? 0 : FETCH_CHAR (point - 1);
+ PUSH (v1);
+ break;
+
+ case Bcurrent_column:
+ XFASTINT (v1) = current_column ();
+ PUSH (v1);
+ break;
+
+ case Bindent_to:
+ TOP = Findent_to (TOP, Qnil);
+ break;
+
+ case Bscan_buffer:
+ /* Get an appropriate error. */
+ Fsymbol_function (intern ("scan-buffer"));
+ break;
+
+ case Beolp:
+ PUSH (Feolp ());
+ break;
+
+ case Beobp:
+ PUSH (Feobp ());
+ break;
+
+ case Bbolp:
+ PUSH (Fbolp ());
+ break;
+
+ case Bbobp:
+ PUSH (Fbobp ());
+ break;
+
+ case Bcurrent_buffer:
+ PUSH (Fcurrent_buffer ());
+ break;
+
+ case Bset_buffer:
+ TOP = Fset_buffer (TOP);
+ break;
+
+ case Bread_char:
+ PUSH (Fread_char ());
+ QUIT;
+ break;
+
+ case Bset_mark: /* this loser is no longer generated as of v18 */
+ /* TOP = Fset_mark (TOP); */
+ TOP = Fset_marker (current_buffer->mark, TOP, Fcurrent_buffer ());
+ break;
+
+ case Binteractive_p:
+ PUSH (Finteractive_p ());
+ break;
+
+ default:
+ if ((op -= Bconstant) < (unsigned)CONSTANTLIM)
+ PUSH (vectorp[op]);
+ }
+ }
+
+ exit:
+ UNGCPRO;
+ /* Binds and unbinds are supposed to be compiled balanced. */
+ if (specpdl_ptr - specpdl != count)
+ abort ();
+ return v1;
+}
+
+syms_of_bytecode ()
+{
+ Qbytecode = intern ("byte-code");
+ staticpro (&Qbytecode);
+
+ defsubr (&Sbyte_code);
+}
+
diff --git a/src/callint.c b/src/callint.c
new file mode 100644
index 00000000000..eb57928254e
--- /dev/null
+++ b/src/callint.c
@@ -0,0 +1,522 @@
+/* Call a Lisp function interactively.
+ Copyright (C) 1985, 1986, 1992 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#include "config.h"
+#include "lisp.h"
+#include "buffer.h"
+#include "commands.h"
+#include "window.h"
+
+extern Lisp_Object global_map;
+
+extern int num_input_chars;
+
+Lisp_Object Vprefix_arg, Vcurrent_prefix_arg, Qminus;
+Lisp_Object Qcall_interactively;
+Lisp_Object Vcommand_history;
+
+extern Lisp_Object ml_apply ();
+extern Lisp_Object Fread_buffer (), Fread_key_sequence (), Fread_file_name ();
+
+/* This comment supplies the doc string for interactive,
+ for make-docfile to see. We cannot put this in the real DEFUN
+ due to limits in the Unix cpp.
+
+DEFUN ("interactive", Ffoo, Sfoo, 0, 0, 0,
+ "Specify a way of parsing arguments for interactive use of a function.\n\
+For example, write\n\
+ (defun fun (arg) \"Doc string\" (interactive \"p\") ...use arg...)\n\
+to make arg be the prefix numeric argument when foo is called as a command.\n\
+This is actually a declaration rather than a function;\n\
+ it tells call-interactively how to read arguments\n\
+ to pass to the function.\n\
+When actually called, interactive just returns nil.\n\
+\n\
+The argument of interactive is usually a string containing a code letter\n\
+ followed by a prompt. (Some code letters do not use I/O to get\n\
+ the argument and do not need prompts.) To prompt for multiple arguments,\n\
+ give a code letter, its prompt, a newline, and another code letter, etc.\n\
+If the argument is not a string, it is evaluated to get a list of\n\
+ arguments to pass to the function.\n\
+Just (interactive) means pass no args when calling interactively.\n\
+\nCode letters available are:\n\
+a -- Function name: symbol with a function definition.\n\
+b -- Name of existing buffer.\n\
+B -- Name of buffer, possibly nonexistent.\n\
+c -- Character.\n\
+C -- Command name: symbol with interactive function definition.\n\
+d -- Value of point as number. Does not do I/O.\n\
+D -- Directory name.\n\
+f -- Existing file name.\n\
+F -- Possibly nonexistent file name.\n\
+k -- Key sequence (string).\n\
+m -- Value of mark as number. Does not do I/O.\n\
+n -- Number read using minibuffer.\n\
+N -- Prefix arg converted to number, or if none, do like code `n'.\n\
+p -- Prefix arg converted to number. Does not do I/O.\n\
+P -- Prefix arg in raw form. Does not do I/O.\n\
+r -- Region: point and mark as 2 numeric args, smallest first. Does no I/O.\n\
+s -- Any string.\n\
+S -- Any symbol.\n\
+v -- Variable name: symbol that is user-variable-p.\n\
+x -- Lisp expression read but not evaluated.\n\
+X -- Lisp expression read and evaluated.\n\
+In addition, if the first character of the string is '*' then an error is\n\
+ signaled if the buffer is read-only.\n\
+ This happens before reading any arguments.")
+*/
+
+/* ARGSUSED */
+DEFUN ("interactive", Finteractive, Sinteractive, 0, UNEVALLED, 0,
+ 0 /* See immediately above */)
+ (args)
+ Lisp_Object args;
+{
+ return Qnil;
+}
+
+/* Quotify EXP: if EXP is constant, return it.
+ If EXP is not constant, return (quote EXP). */
+Lisp_Object
+quotify_arg (exp)
+ register Lisp_Object exp;
+{
+ if (XTYPE (exp) != Lisp_Int && XTYPE (exp) != Lisp_String
+ && !NULL (exp) && !EQ (exp, Qt))
+ return Fcons (Qquote, Fcons (exp, Qnil));
+
+ return exp;
+}
+
+/* Modify EXP by quotifying each element (except the first). */
+Lisp_Object
+quotify_args (exp)
+ Lisp_Object exp;
+{
+ register Lisp_Object tail;
+ register struct Lisp_Cons *ptr;
+ for (tail = exp; CONSP (tail); tail = ptr->cdr)
+ {
+ ptr = XCONS (tail);
+ ptr->car = quotify_arg (ptr->car);
+ }
+ return exp;
+}
+
+char *callint_argfuns[]
+ = {"", "point", "mark", "region-beginning", "region-end"};
+
+static void
+check_mark ()
+{
+ Lisp_Object tem = Fmarker_buffer (current_buffer->mark);
+ if (NULL (tem) || (XBUFFER (tem) != current_buffer))
+ error ("The mark is not set now");
+}
+
+
+DEFUN ("call-interactively", Fcall_interactively, Scall_interactively, 1, 2, 0,
+ "Call FUNCTION, reading args according to its interactive calling specs.\n\
+The function contains a specification of how to do the argument reading.\n\
+In the case of user-defined functions, this is specified by placing a call\n\
+to the function `interactive' at the top level of the function body.\n\
+See `interactive'.\n\
+\n\
+Optional second arg RECORD-FLAG non-nil\n\
+means unconditionally put this command in the command-history.\n\
+Otherwise, this is done only if an arg is read using the minibuffer.")
+ (function, record)
+ Lisp_Object function, record;
+{
+ Lisp_Object *args, *visargs;
+ unsigned char **argstrings;
+ Lisp_Object fun;
+ Lisp_Object funcar;
+ Lisp_Object specs;
+ Lisp_Object teml;
+
+ Lisp_Object prefix_arg;
+ unsigned char *string;
+ unsigned char *tem;
+ int *varies;
+ register int i, j;
+ int count, foo;
+ char prompt[100];
+ char prompt1[100];
+ char *tem1;
+ int arg_from_tty = 0;
+ struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
+ extern char *index ();
+
+ /* Save this now, since use ofminibuffer will clobber it. */
+ prefix_arg = Vcurrent_prefix_arg;
+
+ retry:
+
+ for (fun = function;
+ XTYPE (fun) == Lisp_Symbol && !EQ (fun, Qunbound);
+ fun = XSYMBOL (fun)->function)
+ {
+ QUIT;
+ }
+
+ if (XTYPE (fun) == Lisp_Subr)
+ {
+ string = (unsigned char *) XSUBR (fun)->prompt;
+ if (!string)
+ {
+ lose:
+ function = wrong_type_argument (Qcommandp, function, 0);
+ goto retry;
+ }
+ else if ((int) string == 1)
+ return call0 (function);
+ }
+ else if (!CONSP (fun))
+ goto lose;
+ else if (funcar = Fcar (fun), EQ (funcar, Qautoload))
+ {
+ GCPRO2 (function, prefix_arg);
+ do_autoload (fun, function);
+ UNGCPRO;
+ goto retry;
+ }
+ else if (EQ (funcar, Qlambda))
+ {
+ specs = Fassq (Qinteractive, Fcdr (Fcdr (fun)));
+ if (NULL (specs))
+ goto lose;
+ specs = Fcar (Fcdr (specs));
+ if (XTYPE (specs) == Lisp_String)
+ {
+ /* Make a copy of string so that if a GC relocates specs,
+ `string' will still be valid. */
+ string = (unsigned char *) alloca (XSTRING (specs)->size + 1);
+ bcopy (XSTRING (specs)->data, string, XSTRING (specs)->size + 1);
+ }
+ else
+ {
+ i = num_input_chars;
+ specs = Feval (specs);
+ if (i != num_input_chars || !NULL (record))
+ Vcommand_history
+ = Fcons (Fcons (function, quotify_args (Fcopy_sequence (specs))),
+ Vcommand_history);
+ return apply1 (function, specs);
+ }
+ }
+ else if (EQ (funcar, Qmocklisp))
+ return ml_apply (fun, Qinteractive);
+ else
+ goto lose;
+
+ /* Here if function specifies a string to control parsing the defaults */
+
+ /* First character '*' means barf if buffer read-only */
+ if (*string == '*')
+ {
+ string++;
+ if (!NULL (current_buffer->read_only))
+ Fbarf_if_buffer_read_only ();
+ }
+
+ tem = string;
+ for (j = 0; *tem; j++)
+ {
+ if (*tem == 'r') j++;
+ tem = (unsigned char *) index (tem, '\n');
+ if (tem) tem++;
+ else tem = (unsigned char *) "";
+ }
+ count = j;
+
+ args = (Lisp_Object *) alloca ((count + 1) * sizeof (Lisp_Object));
+ visargs = (Lisp_Object *) alloca ((count + 1) * sizeof (Lisp_Object));
+ argstrings = (unsigned char **) alloca ((count + 1) * sizeof (char *));
+ varies = (int *) alloca ((count + 1) * sizeof (int));
+
+ for (i = 0; i < (count + 1); i++)
+ {
+ args[i] = Qnil;
+ visargs[i] = Qnil;
+ varies[i] = 0;
+ }
+
+ GCPRO4 (prefix_arg, function, *args, *visargs);
+ gcpro3.nvars = (count + 1);
+ gcpro4.nvars = (count + 1);
+
+ tem = string;
+ for (i = 1; *tem; i++)
+ {
+ strncpy (prompt1, tem + 1, sizeof prompt1 - 1);
+ prompt1[sizeof prompt1 - 1] = 0;
+ tem1 = index (prompt1, '\n');
+ if (tem1) *tem1 = 0;
+ /* Fill argstrings with a vector of C strings
+ corresponding to the Lisp strings in visargs. */
+ for (j = 1; j < i; j++)
+ argstrings[j]
+ = EQ (visargs[j], Qnil)
+ ? (unsigned char *) ""
+ : XSTRING (visargs[j])->data;
+
+ doprnt (prompt, sizeof prompt, prompt1, j - 1, argstrings + 1);
+
+ switch (*tem)
+ {
+ case 'a': /* Symbol defined as a function */
+ visargs[i] = Fcompleting_read (build_string (prompt),
+ Vobarray, Qfboundp, Qt, Qnil);
+ /* Passing args[i] directly stimulates compiler bug */
+ teml = visargs[i];
+ args[i] = Fintern (teml, Qnil);
+ break;
+
+ case 'b': /* Name of existing buffer */
+ args[i] = Fcurrent_buffer ();
+ if (EQ (selected_window, minibuf_window))
+ args[i] = Fother_buffer (args[i]);
+ args[i] = Fread_buffer (build_string (prompt), args[i], Qt);
+ break;
+
+ case 'B': /* Name of buffer, possibly nonexistent */
+ args[i] = Fread_buffer (build_string (prompt),
+ Fother_buffer (Fcurrent_buffer ()), Qnil);
+ break;
+
+ case 'c': /* Character */
+ message1 (prompt);
+ args[i] = Fread_char ();
+ /* Passing args[i] directly stimulates compiler bug */
+ teml = args[i];
+ visargs[i] = Fchar_to_string (teml);
+ break;
+
+ case 'C': /* Command: symbol with interactive function */
+ visargs[i] = Fcompleting_read (build_string (prompt),
+ Vobarray, Qcommandp, Qt, Qnil);
+ /* Passing args[i] directly stimulates compiler bug */
+ teml = visargs[i];
+ args[i] = Fintern (teml, Qnil);
+ break;
+
+ case 'd': /* Value of point. Does not do I/O. */
+ XFASTINT (args[i]) = point;
+ /* visargs[i] = Qnil; */
+ varies[i] = 1;
+ break;
+
+ case 'D': /* Directory name. */
+ args[i] = Fread_file_name (build_string (prompt), Qnil,
+ current_buffer->directory, Qlambda);
+ break;
+
+ case 'f': /* Existing file name. */
+ /* On VMS, treat 'f' like 'F', because 'f' fails to work
+ for multivalued logical names or for explicit versions. */
+#ifndef VMS
+ args[i] = Fread_file_name (build_string (prompt),
+ Qnil, Qnil, Qlambda);
+ break;
+#endif
+
+ case 'F': /* Possibly nonexistent file name. */
+ args[i] = Fread_file_name (build_string (prompt),
+ Qnil, Qnil, Qnil);
+ break;
+
+ case 'k': /* Key sequence (string) */
+ args[i] = Fread_key_sequence (build_string (prompt));
+ teml = args[i];
+ visargs[i] = Fkey_description (teml);
+ break;
+
+ case 'm': /* Value of mark. Does not do I/O. */
+ check_mark ();
+ /* visargs[i] = Qnil; */
+ XFASTINT (args[i]) = marker_position (current_buffer->mark);
+ varies[i] = 2;
+ break;
+
+ case 'N': /* Prefix arg, else number from minibuffer */
+ if (!NULL (prefix_arg))
+ goto have_prefix_arg;
+ case 'n': /* Read number from minibuffer. */
+ do
+ args[i] = Fread_minibuffer (build_string (prompt), Qnil);
+ while (XTYPE (args[i]) != Lisp_Int);
+ visargs[i] = last_minibuf_string;
+ break;
+
+ case 'P': /* Prefix arg in raw form. Does no I/O. */
+ args[i] = prefix_arg;
+ /* visargs[i] = Qnil; */
+ varies[i] = -1;
+ break;
+
+ case 'p': /* Prefix arg converted to number. No I/O. */
+ have_prefix_arg:
+ args[i] = Fprefix_numeric_value (prefix_arg);
+ /* visargs[i] = Qnil; */
+ varies[i] = -1;
+ break;
+
+ case 'r': /* Region, point and mark as 2 args. */
+ check_mark ();
+ /* visargs[i+1] = Qnil; */
+ foo = marker_position (current_buffer->mark);
+ /* visargs[i] = Qnil; */
+ XFASTINT (args[i]) = point < foo ? point : foo;
+ varies[i] = 3;
+ XFASTINT (args[++i]) = point > foo ? point : foo;
+ varies[i] = 4;
+ break;
+
+ case 's': /* String read via minibuffer. */
+ args[i] = Fread_string (build_string (prompt), Qnil);
+ break;
+
+ case 'S': /* Any symbol. */
+ visargs[i] = read_minibuf (Vminibuffer_local_ns_map,
+ Qnil,
+ build_string (prompt),
+ 0);
+ /* Passing args[i] directly stimulates compiler bug */
+ teml = visargs[i];
+ args[i] = Fintern (teml, Qnil);
+ break;
+
+ case 'v': /* Variable name: symbol that is
+ user-variable-p. */
+ args[i] = Fread_variable (build_string (prompt));
+ visargs[i] = last_minibuf_string;
+ break;
+
+ case 'x': /* Lisp expression read but not evaluated */
+ args[i] = Fread_minibuffer (build_string (prompt), Qnil);
+ visargs[i] = last_minibuf_string;
+ break;
+
+ case 'X': /* Lisp expression read and evaluated */
+ args[i] = Feval_minibuffer (build_string (prompt), Qnil);
+ visargs[i] = last_minibuf_string;
+ break;
+
+ default:
+ error ("Invalid control letter \"%c\" (%03o) in interactive calling string",
+ *tem, *tem);
+ }
+
+ if (varies[i] == 0)
+ arg_from_tty = 1;
+
+ if (NULL (visargs[i]) && XTYPE (args[i]) == Lisp_String)
+ visargs[i] = args[i];
+
+ tem = (unsigned char *) index (tem, '\n');
+ if (tem) tem++;
+ else tem = (unsigned char *) "";
+ }
+
+ QUIT;
+
+ args[0] = function;
+
+ if (arg_from_tty || !NULL (record))
+ {
+ visargs[0] = function;
+ for (i = 1; i < count + 1; i++)
+ if (varies[i] > 0)
+ visargs[i] = Fcons (intern (callint_argfuns[varies[i]]), Qnil);
+ else
+ visargs[i] = quotify_arg (args[i]);
+ Vcommand_history = Fcons (Flist (count + 1, visargs),
+ Vcommand_history);
+ }
+
+ teml = Ffuncall (count + 1, args);
+ UNGCPRO;
+ return teml;
+}
+
+DEFUN ("prefix-numeric-value", Fprefix_numeric_value, Sprefix_numeric_value,
+ 1, 1, 0,
+ "Return numeric meaning of raw prefix argument ARG.\n\
+A raw prefix argument is what you get from (interactive \"P\").")
+ (raw)
+ Lisp_Object raw;
+{
+ Lisp_Object val;
+
+ if (NULL (raw))
+ XFASTINT (val) = 1;
+ else if (XTYPE (raw) == Lisp_Symbol)
+ {
+ XFASTINT (val) = 0;
+ XSETINT (val, -1);
+ }
+ else if (CONSP (raw))
+ val = XCONS (raw)->car;
+ else if (XTYPE (raw) == Lisp_Int)
+ val = raw;
+ else
+ XFASTINT (val) = 1;
+
+ return val;
+}
+
+syms_of_callint ()
+{
+ Qminus = intern ("-");
+ staticpro (&Qminus);
+
+ Qcall_interactively = intern ("call-interactively");
+ staticpro (&Qcall_interactively);
+
+ DEFVAR_LISP ("prefix-arg", &Vprefix_arg,
+ "The value of the prefix argument for the next editing command.\n\
+It may be a number, or the symbol - for just a minus sign as arg,\n\
+or a list whose car is a number for just one or more C-U's\n\
+or nil if no argument has been specified.\n\
+\n\
+You cannot examine this variable to find the argument for this command\n\
+since it has been set to nil by the time you can look.\n\
+Instead, you should use the variable current-prefix-arg, although\n\
+normally commands can get this prefix argument with (interactive \"P\").");
+ Vprefix_arg = Qnil;
+
+ DEFVAR_LISP ("current-prefix-arg", &Vcurrent_prefix_arg,
+ "The value of the prefix argument for this editing command.\n\
+It may be a number, or the symbol - for just a minus sign as arg,\n\
+or a list whose car is a number for just one or more C-U's\n\
+or nil if no argument has been specified.\n\
+This is what (interactive \"P\") returns.");
+ Vcurrent_prefix_arg = Qnil;
+
+ DEFVAR_LISP ("command-history", &Vcommand_history,
+ "List of recent commands that read arguments from terminal.\n\
+Each command is represented as a form to evaluate.");
+ Vcommand_history = Qnil;
+
+ defsubr (&Sinteractive);
+ defsubr (&Scall_interactively);
+ defsubr (&Sprefix_numeric_value);
+}
diff --git a/src/callproc.c b/src/callproc.c
new file mode 100644
index 00000000000..607d09b65f4
--- /dev/null
+++ b/src/callproc.c
@@ -0,0 +1,487 @@
+/* Synchronous subprocess invocation for GNU Emacs.
+ Copyright (C) 1985, 1986, 1987, 1988, 1990 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* This must precede sys/signal.h on certain machines. */
+#include <sys/types.h>
+#include <signal.h>
+
+#include "config.h"
+
+#define PRIO_PROCESS 0
+#include <sys/file.h>
+#ifdef USG5
+#include <fcntl.h>
+#endif
+
+#ifndef O_RDONLY
+#define O_RDONLY 0
+#endif
+
+#ifndef O_WRONLY
+#define O_WRONLY 1
+#endif
+
+#include "lisp.h"
+#include "commands.h"
+#include "buffer.h"
+#include "paths.h"
+
+#define max(a, b) ((a) > (b) ? (a) : (b))
+
+Lisp_Object Vexec_path, Vexec_directory;
+
+Lisp_Object Vshell_file_name;
+
+#ifndef MAINTAIN_ENVIRONMENT
+/* List of strings to append to front of environment of
+ all subprocesses when they are started. */
+
+Lisp_Object Vprocess_environment;
+#endif
+
+#ifdef BSD4_1
+/* Set nonzero when a synchronous subprocess is made,
+ and set to zero again when it is observed to die.
+ We wait for this to be zero in order to wait for termination. */
+int synch_process_pid;
+#endif /* BSD4_1 */
+
+/* True iff we are about to fork off a synchronous process or if we
+ are waiting for it. */
+int synch_process_alive;
+
+/* Nonzero => this is a string explaining death of synchronous subprocess. */
+char *synch_process_death;
+
+/* Exit code of synchronous subprocess if positive,
+ minus the signal number if negative. */
+int synch_process_retcode;
+
+Lisp_Object
+call_process_cleanup (fdpid)
+ Lisp_Object fdpid;
+{
+ register Lisp_Object fd, pid;
+ fd = Fcar (fdpid);
+ pid = Fcdr (fdpid);
+ close (XFASTINT (fd));
+ kill (XFASTINT (pid), SIGKILL);
+ return Qnil;
+}
+
+#ifdef VMS
+#ifdef __GNUC__
+#define environ $$PsectAttributes_NOSHR$$environ
+extern char **environ;
+#else
+extern noshare char **environ;
+#endif
+#else
+extern char **environ;
+#endif
+
+DEFUN ("call-process", Fcall_process, Scall_process, 1, MANY, 0,
+ "Call PROGRAM in separate process.\n\
+Program's input comes from file INFILE (nil means /dev/null).\n\
+Insert output in BUFFER before point; t means current buffer;\n\
+ nil for BUFFER means discard it; 0 means discard and don't wait.\n\
+Fourth arg DISPLAY non-nil means redisplay buffer as output is inserted.\n\
+Remaining arguments are strings passed as command arguments to PROGRAM.\n\
+Returns nil if BUFFER is 0; otherwise waits for PROGRAM to terminate\n\
+and returns a numeric exit status or a signal description string.\n\
+If you quit, the process is killed with SIGKILL.")
+ (nargs, args)
+ int nargs;
+ register Lisp_Object *args;
+{
+ Lisp_Object display, buffer, path;
+ int fd[2];
+ int filefd;
+ register int pid;
+ char buf[1024];
+ int count = specpdl_ptr - specpdl;
+ register unsigned char **new_argv
+ = (unsigned char **) alloca ((max (2, nargs - 2)) * sizeof (char *));
+ struct buffer *old = current_buffer;
+
+ CHECK_STRING (args[0], 0);
+
+ if (nargs <= 1 || NULL (args[1]))
+#ifdef VMS
+ args[1] = build_string ("NLA0:");
+#else
+ args[1] = build_string ("/dev/null");
+#endif /* not VMS */
+ else
+ args[1] = Fexpand_file_name (args[1], current_buffer->directory);
+
+ CHECK_STRING (args[1], 1);
+
+ {
+ register Lisp_Object tem;
+ buffer = tem = args[2];
+ if (nargs <= 2)
+ buffer = Qnil;
+ else if (!(EQ (tem, Qnil) || EQ (tem, Qt)
+ || XFASTINT (tem) == 0))
+ {
+ buffer = Fget_buffer (tem);
+ CHECK_BUFFER (buffer, 2);
+ }
+ }
+
+ display = nargs > 3 ? args[3] : Qnil;
+
+ {
+ register int i;
+ for (i = 4; i < nargs; i++)
+ {
+ CHECK_STRING (args[i], i);
+ new_argv[i - 3] = XSTRING (args[i])->data;
+ }
+ /* Program name is first command arg */
+ new_argv[0] = XSTRING (args[0])->data;
+ new_argv[i - 3] = 0;
+ }
+
+ filefd = open (XSTRING (args[1])->data, O_RDONLY, 0);
+ if (filefd < 0)
+ {
+ report_file_error ("Opening process input file", Fcons (args[1], Qnil));
+ }
+ /* Search for program; barf if not found. */
+ openp (Vexec_path, args[0], "", &path, 1);
+ if (NULL (path))
+ {
+ close (filefd);
+ report_file_error ("Searching for program", Fcons (args[0], Qnil));
+ }
+ new_argv[0] = XSTRING (path)->data;
+
+ if (XTYPE (buffer) == Lisp_Int)
+#ifdef VMS
+ fd[1] = open ("NLA0:", 0), fd[0] = -1;
+#else
+ fd[1] = open ("/dev/null", O_WRONLY), fd[0] = -1;
+#endif /* not VMS */
+ else
+ {
+ pipe (fd);
+#if 0
+ /* Replaced by close_process_descs */
+ set_exclusive_use (fd[0]);
+#endif
+ }
+
+ synch_process_death = 0;
+ synch_process_retcode = 0;
+
+ {
+ /* child_setup must clobber environ in systems with true vfork.
+ Protect it from permanent change. */
+ register char **save_environ = environ;
+ register int fd1 = fd[1];
+ char **env;
+
+#ifdef MAINTAIN_ENVIRONMENT
+ env = (char **) alloca (size_of_current_environ ());
+ get_current_environ (env);
+#else
+ env = environ;
+#endif /* MAINTAIN_ENVIRONMENT */
+
+ pid = vfork ();
+#ifdef BSD4_1
+ /* cause SIGCHLD interrupts to look for this pid. */
+ synch_process_pid = pid;
+#endif /* BSD4_1 */
+
+ if (pid == 0)
+ {
+ if (fd[0] >= 0)
+ close (fd[0]);
+#ifdef USG
+#ifdef HAVE_PTYS
+ setpgrp ();
+#endif
+#endif
+ child_setup (filefd, fd1, fd1, new_argv, env);
+ }
+
+ environ = save_environ;
+
+ close (filefd);
+ close (fd1);
+ }
+
+ if (pid < 0)
+ {
+ close (fd[0]);
+ report_file_error ("Doing vfork", Qnil);
+ }
+
+ if (XTYPE (buffer) == Lisp_Int)
+ {
+#ifndef subprocesses
+ wait_without_blocking ();
+#endif subprocesses
+ return Qnil;
+ }
+
+ record_unwind_protect (call_process_cleanup,
+ Fcons (make_number (fd[0]), make_number (pid)));
+
+
+ if (XTYPE (buffer) == Lisp_Buffer)
+ Fset_buffer (buffer);
+
+ immediate_quit = 1;
+ QUIT;
+
+ {
+ register int nread;
+
+ while ((nread = read (fd[0], buf, sizeof buf)) > 0)
+ {
+ immediate_quit = 0;
+ if (!NULL (buffer))
+ insert (buf, nread);
+ if (!NULL (display) && FROM_KBD)
+ redisplay_preserve_echo_area ();
+ immediate_quit = 1;
+ QUIT;
+ }
+ }
+
+ /* Wait for it to terminate, unless it already has. */
+ wait_for_termination (pid);
+
+ immediate_quit = 0;
+
+ set_buffer_internal (old);
+
+ unbind_to (count);
+
+ if (synch_process_death)
+ return build_string (synch_process_death);
+ return make_number (synch_process_retcode);
+}
+
+DEFUN ("call-process-region", Fcall_process_region, Scall_process_region,
+ 3, MANY, 0,
+ "Send text from START to END to a process running PROGRAM.\n\
+Delete the text if DELETE is non-nil.\n\
+Insert output in BUFFER before point; t means current buffer;\n\
+ nil for BUFFER means discard it; 0 means discard and don't wait.\n\
+Sixth arg DISPLAY non-nil means redisplay buffer as output is inserted.\n\
+Remaining arguments are strings passed as command arguments to PROGRAM.\n\
+Returns nil if BUFFER is 0; otherwise waits for PROGRAM to terminate\n\
+and returns a numeric exit status or a signal description string.\n\
+If you quit, the process is killed with SIGKILL.")
+ (nargs, args)
+ int nargs;
+ register Lisp_Object *args;
+{
+ register Lisp_Object filename_string, start, end, status;
+ char tempfile[20];
+
+ strcpy (tempfile, "/tmp/emacsXXXXXX");
+ mktemp (tempfile);
+
+ filename_string = build_string (tempfile);
+ start = args[0];
+ end = args[1];
+ Fwrite_region (start, end, filename_string, Qnil, Qlambda);
+
+ if (!NULL (args[3]))
+ Fdelete_region (start, end);
+
+ args[3] = filename_string;
+ status = Fcall_process (nargs - 2, args + 2);
+ unlink (tempfile);
+ return status;
+}
+
+/* This is the last thing run in a newly forked inferior
+ either synchronous or asynchronous.
+ Copy descriptors IN, OUT and ERR as descriptors 0, 1 and 2.
+ Initialize inferior's priority, pgrp, connected dir and environment.
+ then exec another program based on new_argv.
+
+ This function may change environ for the superior process.
+ Therefore, the superior process must save and restore the value
+ of environ around the vfork and the call to this function.
+
+ ENV is the environment */
+
+child_setup (in, out, err, new_argv, env)
+ int in, out, err;
+ register char **new_argv;
+ char **env;
+{
+ register int pid = getpid();
+
+ setpriority (PRIO_PROCESS, pid, 0);
+
+#ifdef subprocesses
+ /* Close Emacs's descriptors that this process should not have. */
+ close_process_descs ();
+#endif
+
+ /* Note that use of alloca is always safe here. It's obvious for systems
+ that do not have true vfork or that have true (stack) alloca.
+ If using vfork and C_ALLOCA it is safe because that changes
+ the superior's static variables as if the superior had done alloca
+ and will be cleaned up in the usual way. */
+
+ if (XTYPE (current_buffer->directory) == Lisp_String)
+ {
+ register unsigned char *temp;
+ register int i;
+
+ i = XSTRING (current_buffer->directory)->size;
+ temp = (unsigned char *) alloca (i + 2);
+ bcopy (XSTRING (current_buffer->directory)->data, temp, i);
+ if (temp[i - 1] != '/') temp[i++] = '/';
+ temp[i] = 0;
+ chdir (temp);
+ }
+
+#ifndef MAINTAIN_ENVIRONMENT
+ /* Set `env' to a vector of the strings in Vprocess_environment. */
+ {
+ register Lisp_Object tem;
+ register char **new_env;
+ register int new_length;
+
+ new_length = 0;
+ for (tem = Vprocess_environment;
+ (XTYPE (tem) == Lisp_Cons
+ && XTYPE (XCONS (tem)->car) == Lisp_String);
+ tem = XCONS (tem)->cdr)
+ new_length++;
+
+ /* new_length + 1 to include terminating 0 */
+ env = new_env = (char **) alloca ((new_length + 1) * sizeof (char *));
+
+ /* Copy the env strings into new_env. */
+ for (tem = Vprocess_environment;
+ (XTYPE (tem) == Lisp_Cons
+ && XTYPE (XCONS (tem)->car) == Lisp_String);
+ tem = XCONS (tem)->cdr)
+ *new_env++ = (char *) XSTRING (XCONS (tem)->car)->data;
+ *new_env = 0;
+ }
+#endif /* Not MAINTAIN_ENVIRONMENT */
+
+ close (0);
+ close (1);
+ close (2);
+
+ dup2 (in, 0);
+ dup2 (out, 1);
+ dup2 (err, 2);
+ close (in);
+ close (out);
+ close (err);
+
+#ifdef USG
+#ifndef HAVE_PTYS
+ setpgrp (); /* No arguments but equivalent in this case */
+#endif
+#else
+ setpgrp (pid, pid);
+#endif /* USG */
+ setpgrp_of_tty (pid);
+
+#ifdef vipc
+ something missing here;
+#endif vipc
+
+ /* execvp does not accept an environment arg so the only way
+ to pass this environment is to set environ. Our caller
+ is responsible for restoring the ambient value of environ. */
+ environ = env;
+ execvp (new_argv[0], new_argv);
+
+ write (1, "Couldn't exec the program ", 26);
+ write (1, new_argv[0], strlen (new_argv[0]));
+ _exit (1);
+}
+
+init_callproc ()
+{
+ register char * sh;
+ extern char **environ;
+ register char **envp;
+ Lisp_Object execdir;
+
+ /* Turn PATH_EXEC into a path. Don't look at environment. */
+ Vexec_path = decode_env_path (0, PATH_EXEC);
+ Vexec_directory = Ffile_name_as_directory (Fcar (Vexec_path));
+ Vexec_path = nconc2 (decode_env_path ("PATH", ""), Vexec_path);
+
+ execdir = Fdirectory_file_name (Vexec_directory);
+ if (access (XSTRING (execdir)->data, 0) < 0)
+ {
+ printf ("Warning: executable/documentation dir (%s) does not exist.\n",
+ XSTRING (Vexec_directory)->data);
+ sleep (2);
+ }
+
+ sh = (char *) egetenv ("SHELL");
+ Vshell_file_name = build_string (sh ? sh : "/bin/sh");
+
+#ifndef MAINTAIN_ENVIRONMENT
+ /* The equivalent of this operation was done
+ in init_environ in environ.c if MAINTAIN_ENVIRONMENT */
+ Vprocess_environment = Qnil;
+#ifndef CANNOT_DUMP
+ if (initialized)
+#endif
+ for (envp = environ; *envp; envp++)
+ Vprocess_environment = Fcons (build_string (*envp),
+ Vprocess_environment);
+#endif /* MAINTAIN_ENVIRONMENT */
+}
+
+syms_of_callproc ()
+{
+ DEFVAR_LISP ("shell-file-name", &Vshell_file_name,
+ "*File name to load inferior shells from.\n\
+Initialized from the SHELL environment variable.");
+
+ DEFVAR_LISP ("exec-path", &Vexec_path,
+ "*List of directories to search programs to run in subprocesses.\n\
+Each element is a string (directory name) or nil (try default directory).");
+
+ DEFVAR_LISP ("exec-directory", &Vexec_directory,
+ "Directory that holds programs that come with GNU Emacs,\n\
+intended for Emacs to invoke.");
+
+#ifndef MAINTAIN_ENVIRONMENT
+ DEFVAR_LISP ("process-environment", &Vprocess_environment,
+ "List of strings to append to environment of subprocesses that are started.\n\
+Each string should have the format ENVVARNAME=VALUE.");
+#endif
+
+ defsubr (&Scall_process);
+ defsubr (&Scall_process_region);
+}
diff --git a/src/casefiddle.c b/src/casefiddle.c
index d508deb5d60..467ffa976f2 100644
--- a/src/casefiddle.c
+++ b/src/casefiddle.c
@@ -1,5 +1,5 @@
/* GNU Emacs case conversion functions.
- Copyright (C) 1985 Free Software Foundation, Inc.
+ Copyright (C) 1985, 1990 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -70,9 +70,7 @@ casify_object (flag, obj)
}
DEFUN ("upcase", Fupcase, Supcase, 1, 1, 0,
- "Convert argument to upper case and return that.\n\
-The argument may be a character or string. The result has the same type.\n\
-The argument object is not altered. See also `capitalize'.")
+ "One arg, a character or string. Convert it to upper case and return that.")
(obj)
Lisp_Object obj;
{
@@ -80,9 +78,7 @@ The argument object is not altered. See also `capitalize'.")
}
DEFUN ("downcase", Fdowncase, Sdowncase, 1, 1, 0,
- "Convert argument to lower case and return that.\n\
-The argument may be a character or string. The result has the same type.\n\
-The argument object is not altered.")
+ "One arg, a character or string. Convert it to lower case and return that.")
(obj)
Lisp_Object obj;
{
@@ -90,11 +86,8 @@ The argument object is not altered.")
}
DEFUN ("capitalize", Fcapitalize, Scapitalize, 1, 1, 0,
- "Convert argument to capitalized form and return that.\n\
-This means that each word's first character is upper case\n\
-and the rest is lower case.\n\
-The argument may be a character or string. The result has the same type.\n\
-The argument object is not altered.")
+ "One arg, a character or string. Convert it to capitalized form and return that.\n\
+This means that each word's first character is upper case and the rest is lower case.")
(obj)
Lisp_Object obj;
{
@@ -112,12 +105,8 @@ casify_region (flag, b, e)
register int c;
register int inword = flag == CASE_DOWN;
- if (EQ (b, e))
- /* Not modifying because nothing marked */
- return;
-
validate_region (&b, &e);
- modify_region (XFASTINT (b), XFASTINT (e));
+ prepare_to_modify_buffer ();
record_change (XFASTINT (b), XFASTINT (e) - XFASTINT (b));
for (i = XFASTINT (b); i < XFASTINT (e); i++)
@@ -133,17 +122,14 @@ casify_region (flag, b, e)
inword = SYNTAX (c) == Sword;
}
- signal_after_change (XFASTINT (b),
- XFASTINT (e) - XFASTINT (b),
- XFASTINT (e) - XFASTINT (b));
+ modify_region (XFASTINT (b), XFASTINT (e));
}
DEFUN ("upcase-region", Fupcase_region, Supcase_region, 2, 2, "r",
"Convert the region to upper case. In programs, wants two arguments.\n\
These arguments specify the starting and ending character numbers of\n\
the region to operate on. When used as a command, the text between\n\
-point and the mark is operated on.\n\
-See also `capitalize-region'.")
+point and the mark is operated on.")
(b, e)
Lisp_Object b, e;
{
@@ -164,11 +150,12 @@ point and the mark is operated on.")
}
DEFUN ("capitalize-region", Fcapitalize_region, Scapitalize_region, 2, 2, "r",
- "Convert the region to capitalized form.\n\
+ "Convert the region to upper case. In programs, wants two arguments.\n\
+These arguments specify the starting and ending character numbers of\n\
+the region to operate on. When used as a command, the text between\n\
+point and the mark is operated on.\n\
Capitalized form means each word's first character is upper case\n\
-and the rest of it is lower case.\n\
-In programs, give two arguments, the starting and ending\n\
-character positions to operate on.")
+and the rest of it is lower case.")
(b, e)
Lisp_Object b, e;
{
@@ -190,30 +177,26 @@ Lisp_Object
operate_on_word (arg)
Lisp_Object arg;
{
- Lisp_Object val, end;
+ Lisp_Object end, val;
int farend;
CHECK_NUMBER (arg, 0);
farend = scan_words (point, XINT (arg));
if (!farend)
farend = XINT (arg) > 0 ? ZV : BEGV;
-
end = point > farend ? point : farend;
SET_PT (end);
XFASTINT (val) = farend;
-
return val;
}
DEFUN ("upcase-word", Fupcase_word, Supcase_word, 1, 1, "p",
"Convert following word (or ARG words) to upper case, moving over.\n\
-With negative argument, convert previous words but do not move.\n\
-See also `capitalize-word'.")
+With negative argument, convert previous words but do not move.")
(arg)
Lisp_Object arg;
{
Lisp_Object opoint;
-
XFASTINT (opoint) = point;
casify_region (CASE_UP, opoint, operate_on_word (arg));
return Qnil;
@@ -260,9 +243,9 @@ syms_of_casefiddle ()
keys_of_casefiddle ()
{
- initial_define_key (control_x_map, Ctl('U'), "upcase-region");
- initial_define_key (control_x_map, Ctl('L'), "downcase-region");
- initial_define_key (meta_map, 'u', "upcase-word");
- initial_define_key (meta_map, 'l', "downcase-word");
- initial_define_key (meta_map, 'c', "capitalize-word");
+ ndefkey (Vctl_x_map, Ctl('U'), "upcase-region");
+ ndefkey (Vctl_x_map, Ctl('L'), "downcase-region");
+ ndefkey (Vesc_map, 'u', "upcase-word");
+ ndefkey (Vesc_map, 'l', "downcase-word");
+ ndefkey (Vesc_map, 'c', "capitalize-word");
}
diff --git a/src/casetab.c b/src/casetab.c
deleted file mode 100644
index 6d419bfe30f..00000000000
--- a/src/casetab.c
+++ /dev/null
@@ -1,250 +0,0 @@
-/* GNU Emacs routines to deal with case tables.
- Copyright (C) 1987 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 1, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-/* Written by Howard Gayle. See chartab.c for details. */
-
-#include "config.h"
-#include "lisp.h"
-#include "buffer.h"
-
-Lisp_Object Qcase_table_p;
-Lisp_Object Vascii_downcase_table, Vascii_upcase_table;
-Lisp_Object Vascii_canon_table, Vascii_eqv_table;
-
-void compute_trt_inverse ();
-
-DEFUN ("case-table-p", Fcase_table_p, Scase_table_p, 1, 1, 0,
- "Return t iff ARG is a case table.\n\
-See `set-case-table' for more information on these data structures.")
- (table)
- Lisp_Object table;
-{
- Lisp_Object down, up, canon, eqv;
- down = Fcar_safe (table);
- up = Fcar_safe (Fcdr_safe (table));
- canon = Fcar_safe (Fcdr_safe (Fcdr_safe (table)));
- eqv = Fcar_safe (Fcdr_safe (Fcdr_safe (Fcdr_safe (table))));
-
-#define STRING256_P(obj) \
- (XTYPE (obj) == Lisp_String && XSTRING (obj)->size == 256)
-
- return (STRING256_P (down)
- && (NULL (up) || STRING256_P (up))
- && ((NULL (canon) && NULL (eqv))
- || (STRING256_P (canon) && STRING256_P (eqv)))
- ? Qt : Qnil);
-}
-
-static Lisp_Object
-check_case_table (obj)
- Lisp_Object obj;
-{
- register Lisp_Object tem;
-
- while (tem = Fcase_table_p (obj), NULL (tem))
- obj = wrong_type_argument (Qcase_table_p, obj, 0);
- return (obj);
-}
-
-DEFUN ("current-case-table", Fcurrent_case_table, Scurrent_case_table, 0, 0, 0,
- "Return the case table of the current buffer.")
- ()
-{
- Lisp_Object down, up, canon, eqv;
-
- down = current_buffer->downcase_table;
- up = current_buffer->upcase_table;
- canon = current_buffer->case_canon_table;
- eqv = current_buffer->case_eqv_table;
-
- return Fcons (down, Fcons (up, Fcons (canon, Fcons (eqv, Qnil))));
-}
-
-DEFUN ("standard-case-table", Fstandard_case_table,
- Sstandard_case_table, 0, 0, 0,
- "Return the standard case table.\n\
-This is the one used for new buffers.")
- ()
-{
- return Fcons (Vascii_downcase_table,
- Fcons (Vascii_upcase_table,
- Fcons (Vascii_canon_table,
- Fcons (Vascii_eqv_table, Qnil))));
-}
-
-DEFUN ("set-case-table", Fset_case_table, Sset_case_table, 1, 1, 0,
- "Select a new case table for the current buffer.\n\
-A case table is a list (DOWNCASE UPCASE CANONICALIZE EQUIVALENCES)\n\
- where each element is either nil or a string of length 256.\n\
-DOWNCASE maps each character to its lower-case equivalent.\n\
-UPCASE maps each character to its upper-case equivalent;\n\
- if lower and upper case characters are in 1-1 correspondence,\n\
- you may use nil and the upcase table will be deduced from DOWNCASE.\n\
-CANONICALIZE maps each character to a canonical equivalent;\n\
- any two characters that are related by case-conversion have the same\n\
- canonical equivalent character.\n\
-EQUIVALENCES is a map that cyclicly permutes each equivalence class\n\
- (of characters with the same canonical equivalent).\n\
-Both CANONICALIZE and EQUIVALENCES may be nil, in which case\n\
- both are deduced from DOWNCASE and UPCASE.")
- (table)
- Lisp_Object table;
-{
- set_case_table (table, 0);
-}
-
-DEFUN ("set-standard-case-table",
- Fset_standard_case_table, Sset_standard_case_table, 1, 1, 0,
- "Select a new standard case table for new buffers.\n\
-See `set-case-table' for more info on case tables.")
- (table)
- Lisp_Object table;
-{
- set_case_table (table, 1);
-}
-
-set_case_table (table, standard)
- Lisp_Object table;
- int standard;
-{
- Lisp_Object down, up, canon, eqv;
-
- check_case_table (table);
-
- down = Fcar_safe (table);
- up = Fcar_safe (Fcdr_safe (table));
- canon = Fcar_safe (Fcdr_safe (Fcdr_safe (table)));
- eqv = Fcar_safe (Fcdr_safe (Fcdr_safe (Fcdr_safe (table))));
-
- if (NULL (up))
- {
- up = Fmake_string (make_number (256), make_number (0));
- compute_trt_inverse (XSTRING (down)->data, XSTRING (up)->data);
- }
-
- if (NULL (canon))
- {
- register int i;
- unsigned char *upvec = XSTRING (up)->data;
- unsigned char *downvec = XSTRING (down)->data;
-
- canon = Fmake_string (make_number (256), make_number (0));
- eqv = Fmake_string (make_number (256), make_number (0));
-
- /* Set up the CANON vector; for each character,
- this sequence of upcasing and downcasing ought to
- get the "preferred" lowercase equivalent. */
- for (i = 0; i < 256; i++)
- XSTRING (canon)->data[i] = downvec[upvec[downvec[i]]];
-
- compute_trt_inverse (XSTRING (canon)->data, XSTRING (eqv)->data);
- }
-
- if (standard)
- {
- Vascii_downcase_table = down;
- Vascii_upcase_table = up;
- Vascii_canon_table = canon;
- Vascii_eqv_table = eqv;
- }
- else
- {
- current_buffer->downcase_table = down;
- current_buffer->upcase_table = up;
- current_buffer->case_canon_table = canon;
- current_buffer->case_eqv_table = eqv;
- }
- return table;
-}
-
-/* Given a translate table TRT, store the inverse mapping into INVERSE.
- Since TRT is not one-to-one, INVERSE is not a simple mapping.
- Instead, it divides the space of characters into equivalence classes.
- All characters in a given class form one circular list, chained through
- the elements of INVERSE. */
-
-void
-compute_trt_inverse (trt, inverse)
- register unsigned char *trt;
- register unsigned char *inverse;
-{
- register int i = 0400;
- register unsigned char c, q;
-
- while (i--)
- inverse[i] = i;
- i = 0400;
- while (i--)
- {
- if ((q = trt[i]) != (unsigned char) i)
- {
- c = inverse[q];
- inverse[q] = i;
- inverse[i] = c;
- }
- }
-}
-
-init_casetab_once ()
-{
- register int i;
- Lisp_Object tem;
-
- tem = Fmake_string (make_number (256), make_number (0));
- Vascii_downcase_table = tem;
- Vascii_canon_table = tem;
-
- for (i = 0; i < 256; i++)
- XSTRING (tem)->data[i] = (i >= 'A' && i <= 'Z') ? i + 040 : i;
-
- tem = Fmake_string (make_number (256), make_number (0));
- Vascii_upcase_table = tem;
- Vascii_eqv_table = tem;
-
- for (i = 0; i < 256; i++)
- XSTRING (tem)->data[i]
- = ((i >= 'A' && i <= 'Z')
- ? i + ('a' - 'A')
- : ((i >= 'a' && i <= 'z')
- ? i + ('A' - 'a')
- : i));
-}
-
-syms_of_casetab ()
-{
- Qcase_table_p = intern ("case-table-p");
- staticpro (&Qcase_table_p);
- staticpro (&Vascii_downcase_table);
- staticpro (&Vascii_upcase_table);
- staticpro (&Vascii_canon_table);
- staticpro (&Vascii_eqv_table);
-
- defsubr (&Scase_table_p);
- defsubr (&Scurrent_case_table);
- defsubr (&Sstandard_case_table);
- defsubr (&Sset_case_table);
- defsubr (&Sset_standard_case_table);
-
-#if 0
- DEFVAR_LISP ("ascii-downcase-table", &Vascii_downcase_table,
- "String mapping ASCII characters to lowercase equivalents.");
- DEFVAR_LISP ("ascii-upcase-table", &Vascii_upcase_table,
- "String mapping ASCII characters to uppercase equivalents.");
-#endif
-}
diff --git a/src/ccom.com b/src/ccom.com
new file mode 100644
index 00000000000..bf7918b1bf3
--- /dev/null
+++ b/src/ccom.com
@@ -0,0 +1,2 @@
+$ ! VMS command file used by the `ccom' command.
+$ cc /debug /nolist /define="emacs" 'p1'
diff --git a/src/chpdef.h b/src/chpdef.h
new file mode 100644
index 00000000000..43f7bbf4345
--- /dev/null
+++ b/src/chpdef.h
@@ -0,0 +1,38 @@
+#define CHP$_END 0
+#define CHP$_ACCESS 1
+#define CHP$_FLAGS 2
+#define CHP$_PRIV 3
+#define CHP$_ACMODE 4
+#define CHP$_ACCLASS 5
+#define CHP$_RIGHTS 6
+#define CHP$_ADDRIGHTS 7
+#define CHP$_MODE 8
+#define CHP$_MODES 9
+#define CHP$_MINCLASS 10
+#define CHP$_MAXCLASS 11
+#define CHP$_OWNER 12
+#define CHP$_PROT 13
+#define CHP$_ACL 14
+#define CHP$_AUDITNAME 15
+#define CHP$_ALARMNAME 16
+#define CHP$_MATCHEDACE 17
+#define CHP$_PRIVUSED 18
+#define CHP$_MAX_CODE 19
+#define CHP$M_SYSPRV 1
+#define CHP$M_BYPASS 2
+#define CHP$M_UPGRADE 4
+#define CHP$M_DOWNGRADE 8
+#define CHP$M_GRPPRV 16
+#define CHP$M_READALL 32
+#define CHP$V_SYSPRV 0
+#define CHP$V_BYPASS 1
+#define CHP$V_UPGRADE 2
+#define CHP$V_DOWNGRADE 3
+#define CHP$V_GRPPRV 4
+#define CHP$V_READALL 5
+#define CHP$M_READ 1
+#define CHP$M_WRITE 2
+#define CHP$M_USEREADALL 4
+#define CHP$V_READ 0
+#define CHP$V_WRITE 1
+#define CHP$V_USEREADALL 2
diff --git a/src/cm.c b/src/cm.c
new file mode 100644
index 00000000000..3befe2c1bdb
--- /dev/null
+++ b/src/cm.c
@@ -0,0 +1,405 @@
+/* Cursor motion subroutines for GNU Emacs.
+ Copyright (C) 1985 Free Software Foundation, Inc.
+ based primarily on public domain code written by Chris Torek
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#include "config.h"
+#include <stdio.h>
+#include "cm.h"
+#include "termhooks.h"
+
+#define BIG 9999 /* 9999 good on VAXen. For 16 bit machines
+ use about 2000.... */
+
+char *tgoto ();
+
+extern char *BC, *UP;
+
+int cost; /* sums up costs */
+
+/* ARGSUSED */
+evalcost (c)
+ char c;
+{
+ cost++;
+}
+
+void
+cmputc (c)
+ char c;
+{
+ if (termscript)
+ fputc (c & 0177, termscript);
+ putchar (c & 0177);
+}
+
+/* NEXT TWO ARE DONE WITH MACROS */
+#if 0
+/*
+ * Assume the cursor is at row row, column col. Normally used only after
+ * clearing the screen, when the cursor is at (0, 0), but what the heck,
+ * let's let the guy put it anywhere.
+ */
+
+static
+at (row, col) {
+ curY = row;
+ curX = col;
+}
+
+/*
+ * Add n columns to the current cursor position.
+ */
+
+static
+addcol (n) {
+ curX += n;
+
+ /*
+ * If cursor hit edge of screen, what happened?
+ * N.B.: DO NOT!! write past edge of screen. If you do, you
+ * deserve what you get. Furthermore, on terminals with
+ * autowrap (but not magicwrap), don't write in the last column
+ * of the last line.
+ */
+
+ if (curX == Wcm.cm_cols) {
+ /*
+ * Well, if magicwrap, still there, past the edge of the
+ * screen (!). If autowrap, on the col 0 of the next line.
+ * Otherwise on last column.
+ */
+
+ if (Wcm.cm_magicwrap)
+ ; /* "limbo" */
+ else if (Wcm.cm_autowrap) {
+ curX = 0;
+ curY++; /* Beware end of screen! */
+ }
+ else
+ curX--;
+ }
+}
+#endif
+
+/*
+ * (Re)Initialize the cost factors, given the output speed of the terminal
+ * in the variable ospeed. (Note: this holds B300, B9600, etc -- ie stuff
+ * out of <sgtty.h>.)
+ */
+
+cmcostinit ()
+{
+ char *p;
+
+#define COST(x,e) (x ? (cost = 0, tputs (x, 1, e), cost) : BIG)
+#define CMCOST(x,e) ((x == 0) ? BIG : (p = tgoto(x, 0, 0), COST(p ,e)))
+
+ Wcm.cc_up = COST (Wcm.cm_up, evalcost);
+ Wcm.cc_down = COST (Wcm.cm_down, evalcost);
+ Wcm.cc_left = COST (Wcm.cm_left, evalcost);
+ Wcm.cc_right = COST (Wcm.cm_right, evalcost);
+ Wcm.cc_home = COST (Wcm.cm_home, evalcost);
+ Wcm.cc_cr = COST (Wcm.cm_cr, evalcost);
+ Wcm.cc_ll = COST (Wcm.cm_ll, evalcost);
+ Wcm.cc_tab = Wcm.cm_tabwidth ? COST (Wcm.cm_tab, evalcost) : BIG;
+
+ /*
+ * These last three are actually minimum costs. When (if) they are
+ * candidates for the least-cost motion, the real cost is computed.
+ * (Note that "0" is the assumed to generate the minimum cost.
+ * While this is not necessarily true, I have yet to see a terminal
+ * for which is not; all the terminals that have variable-cost
+ * cursor motion seem to take straight numeric values. --ACT)
+ */
+
+ Wcm.cc_abs = CMCOST (Wcm.cm_abs, evalcost);
+ Wcm.cc_habs = CMCOST (Wcm.cm_habs, evalcost);
+ Wcm.cc_vabs = CMCOST (Wcm.cm_vabs, evalcost);
+
+#undef CMCOST
+#undef COST
+}
+
+/*
+ * Calculate the cost to move from (srcy, srcx) to (dsty, dstx) using
+ * up and down, and left and right, motions, and tabs. If doit is set
+ * actually perform the motion.
+ */
+
+static
+calccost (srcy, srcx, dsty, dstx, doit)
+{
+ register int deltay,
+ deltax,
+ c,
+ totalcost;
+ int ntabs,
+ n2tabs,
+ tabx,
+ tab2x,
+ tabcost;
+ register char *p;
+
+ /* If have just wrapped on a terminal with xn,
+ don't believe the cursor position: give up here
+ and force use of absolute positioning. */
+
+ if (curX == Wcm.cm_cols)
+ goto fail;
+
+ totalcost = 0;
+ if ((deltay = dsty - srcy) == 0)
+ goto x;
+ if (deltay < 0)
+ p = Wcm.cm_up, c = Wcm.cc_up, deltay = -deltay;
+ else
+ p = Wcm.cm_down, c = Wcm.cc_down;
+ if (c == BIG) { /* caint get thar from here */
+ if (doit)
+ printf ("OOPS");
+ return c;
+ }
+ totalcost = c * deltay;
+ if (doit)
+ while (--deltay >= 0)
+ tputs (p, 1, cmputc);
+x:
+ if ((deltax = dstx - srcx) == 0)
+ goto done;
+ if (deltax < 0) {
+ p = Wcm.cm_left, c = Wcm.cc_left, deltax = -deltax;
+ goto dodelta; /* skip all the tab junk */
+ }
+ /* Tabs (the toughie) */
+ if (Wcm.cc_tab >= BIG || !Wcm.cm_usetabs)
+ goto olddelta; /* forget it! */
+
+ /*
+ * ntabs is # tabs towards but not past dstx; n2tabs is one more
+ * (ie past dstx), but this is only valid if that is not past the
+ * right edge of the screen. We can check that at the same time
+ * as we figure out where we would be if we use the tabs (which
+ * we will put into tabx (for ntabs) and tab2x (for n2tabs)).
+ */
+
+ ntabs = (deltax + srcx % Wcm.cm_tabwidth) / Wcm.cm_tabwidth;
+ n2tabs = ntabs + 1;
+ tabx = (srcx / Wcm.cm_tabwidth + ntabs) * Wcm.cm_tabwidth;
+ tab2x = tabx + Wcm.cm_tabwidth;
+
+ if (tab2x >= Wcm.cm_cols) /* too far (past edge) */
+ n2tabs = 0;
+
+ /*
+ * Now set tabcost to the cost for using ntabs, and c to the cost
+ * for using n2tabs, then pick the minimum.
+ */
+
+ /* cost for ntabs + cost for right motion */
+ tabcost = ntabs ? ntabs * Wcm.cc_tab + (dstx - tabx) * Wcm.cc_right
+ : BIG;
+
+ /* cost for n2tabs + cost for left motion */
+ c = n2tabs ? n2tabs * Wcm.cc_tab + (tab2x - dstx) * Wcm.cc_left
+ : BIG;
+
+ if (c < tabcost) /* then cheaper to overshoot & back up */
+ ntabs = n2tabs, tabcost = c, tabx = tab2x;
+
+ if (tabcost >= BIG) /* caint use tabs */
+ goto newdelta;
+
+ /*
+ * See if tabcost is less than just moving right
+ */
+
+ if (tabcost < (deltax * Wcm.cc_right)) {
+ totalcost += tabcost; /* use the tabs */
+ if (doit)
+ while (--ntabs >= 0)
+ tputs (Wcm.cm_tab, 1, cmputc);
+ srcx = tabx;
+ }
+
+ /*
+ * Now might as well just recompute the delta.
+ */
+
+newdelta:
+ if ((deltax = dstx - srcx) == 0)
+ goto done;
+olddelta:
+ if (deltax > 0)
+ p = Wcm.cm_right, c = Wcm.cc_right;
+ else
+ p = Wcm.cm_left, c = Wcm.cc_left, deltax = -deltax;
+
+dodelta:
+ if (c == BIG) { /* caint get thar from here */
+fail:
+ if (doit)
+ printf ("OOPS");
+ return BIG;
+ }
+ totalcost += c * deltax;
+ if (doit)
+ while (--deltax >= 0)
+ tputs (p, 1, cmputc);
+done:
+ return totalcost;
+}
+
+losecursor ()
+{
+ curY = -1;
+}
+
+#define USEREL 0
+#define USEHOME 1
+#define USELL 2
+#define USECR 3
+
+cmgoto (row, col)
+{
+ int homecost,
+ crcost,
+ llcost,
+ relcost,
+ directcost;
+ int use;
+ char *p,
+ *dcm;
+
+ /* First the degenerate case */
+ if (row == curY && col == curX) /* already there */
+ return;
+
+ if (curY >= 0 && curX >= 0)
+ {
+ /*
+ * Pick least-cost motions
+ */
+
+ relcost = calccost (curY, curX, row, col, 0);
+ use = USEREL;
+ if ((homecost = Wcm.cc_home) < BIG)
+ homecost += calccost (0, 0, row, col, 0);
+ if (homecost < relcost)
+ relcost = homecost, use = USEHOME;
+ if ((llcost = Wcm.cc_ll) < BIG)
+ llcost += calccost (Wcm.cm_rows - 1, 0, row, col, 0);
+ if (llcost < relcost)
+ relcost = llcost, use = USELL;
+ if ((crcost = Wcm.cc_cr) < BIG) {
+ if (Wcm.cm_autolf)
+ if (curY + 1 >= Wcm.cm_rows)
+ crcost = BIG;
+ else
+ crcost += calccost (curY + 1, 0, row, col, 0);
+ else
+ crcost += calccost (curY, 0, row, col, 0);
+ }
+ if (crcost < relcost)
+ relcost = crcost, use = USECR;
+ directcost = Wcm.cc_abs, dcm = Wcm.cm_abs;
+ if (row == curY && Wcm.cc_habs < BIG)
+ directcost = Wcm.cc_habs, dcm = Wcm.cm_habs;
+ else if (col == curX && Wcm.cc_vabs < BIG)
+ directcost = Wcm.cc_vabs, dcm = Wcm.cm_vabs;
+ }
+ else
+ {
+ directcost = 0, relcost = 100000;
+ dcm = Wcm.cm_abs;
+ }
+
+ /*
+ * In the following comparison, the = in <= is because when the costs
+ * are the same, it looks nicer (I think) to move directly there.
+ */
+ if (directcost <= relcost)
+ {
+ /* compute REAL direct cost */
+ cost = 0;
+ p = dcm == Wcm.cm_habs ? tgoto (dcm, row, col) :
+ tgoto (dcm, col, row);
+ tputs (p, 1, evalcost);
+ if (cost <= relcost)
+ { /* really is cheaper */
+ tputs (p, 1, cmputc);
+ curY = row, curX = col;
+ return;
+ }
+ }
+
+ switch (use)
+ {
+ case USEHOME:
+ tputs (Wcm.cm_home, 1, cmputc);
+ curY = 0, curX = 0;
+ break;
+
+ case USELL:
+ tputs (Wcm.cm_ll, 1, cmputc);
+ curY = Wcm.cm_rows - 1, curX = 0;
+ break;
+
+ case USECR:
+ tputs (Wcm.cm_cr, 1, cmputc);
+ if (Wcm.cm_autolf)
+ curY++;
+ curX = 0;
+ break;
+ }
+
+ (void) calccost (curY, curX, row, col, 1);
+ curY = row, curX = col;
+}
+
+/* Clear out all terminal info.
+ Used before copying into it the info on the actual terminal.
+ */
+
+Wcm_clear ()
+{
+ bzero (&Wcm, sizeof Wcm);
+ UP = 0;
+ BC = 0;
+}
+
+/*
+ * Initialized stuff
+ * Return 0 if can do CM.
+ */
+
+Wcm_init ()
+{
+ /* Check that we know the size of the screen.... */
+ if (Wcm.cm_rows <= 0 || Wcm.cm_cols <= 0)
+ return - 1;
+ if (Wcm.cm_abs && !Wcm.cm_ds)
+ return 0;
+ /* Require up and left, and, if no absolute, down and right */
+ if (!Wcm.cm_up || !Wcm.cm_left)
+ return - 1;
+ if (!Wcm.cm_abs && (!Wcm.cm_down || !Wcm.cm_right))
+ return - 1;
+ return 0;
+}
diff --git a/src/cm.h b/src/cm.h
new file mode 100644
index 00000000000..9675b498688
--- /dev/null
+++ b/src/cm.h
@@ -0,0 +1,100 @@
+/* Cursor motion calculation definitions for GNU Emacs
+ Copyright (C) 1985 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* This structure holds everything needed to do cursor motion except the pad
+ character (PC) and the output speed of the terminal (ospeed), which
+ termcap wants in global variables. */
+
+extern struct cm {
+ /* Cursor position */
+ int cm_curY, /* current row */
+ cm_curX; /* current column */
+ /* -1 in either one means position unknown */
+ /* Capabilities from termcap(5) (including extensions) */
+ char *cm_up, /* up (up) */
+ *cm_down, /* down (do) */
+ *cm_left, /* left (bs) */
+ *cm_right, /* right (nd) */
+ *cm_home, /* home (ho) */
+ *cm_cr, /* carriage return (cr) */
+ *cm_ll, /* last line (ll) */
+ *cm_abs, /* absolute (cm) */
+ *cm_habs, /* horizontal absolute (ch) */
+ *cm_vabs, /* vertical absolute (cv) */
+ *cm_ds, /* "don't send" string (ds) */
+ *cm_tab; /* tab (ta) */
+ int cm_tabwidth, /* tab width (tw) */
+ cm_cols, /* Number of cols on screen (co) */
+ cm_rows; /* Number of rows on screen (li) */
+ unsigned int
+ cm_autowrap:1, /* autowrap flag (am) */
+ cm_magicwrap:1, /* vt100s: cursor stays in last col but
+ will wrap if next char is printing (xn) */
+ cm_usetabs:1, /* if set, use tabs */
+ cm_autolf:1, /* \r performs a \r\n (rn) */
+ cm_losewrap:1; /* if reach right margin, forget cursor location */
+ /* Costs */
+ int cc_up, /* cost for up */
+ cc_down, /* etc */
+ cc_left,
+ cc_right,
+ cc_home,
+ cc_cr,
+ cc_ll,
+ cc_abs, /* abs costs are actually min costs */
+ cc_habs,
+ cc_vabs,
+ cc_tab;
+} Wcm;
+
+extern char PC; /* Pad character */
+extern short ospeed; /* Output speed (from sg_ospeed) */
+
+/* Shorthand */
+#ifndef NoCMShortHand
+#define curY Wcm.cm_curY
+#define curX Wcm.cm_curX
+#define Up Wcm.cm_up
+#define Down Wcm.cm_down
+#define Left Wcm.cm_left
+#define Right Wcm.cm_right
+#define Home Wcm.cm_home
+#define CR Wcm.cm_cr
+#define LastLine Wcm.cm_ll
+#define TabWidth Wcm.cm_tabwidth
+#define DontSend Wcm.cm_ds
+#define AbsPosition Wcm.cm_abs
+#define ColPosition Wcm.cm_habs
+#define RowPosition Wcm.cm_vabs
+#define AutoWrap Wcm.cm_autowrap
+#define MagicWrap Wcm.cm_magicwrap
+#define UseTabs Wcm.cm_usetabs
+#define AutoLF Wcm.cm_autolf
+#define ScreenRows Wcm.cm_rows
+#define ScreenCols Wcm.cm_cols
+
+#define cmat(row,col) (curY = (row), curX = (col))
+#define cmplus(n) {if ((curX += (n)) >= ScreenCols && !MagicWrap)\
+ {if (Wcm.cm_losewrap) curY = -1; \
+ else if (AutoWrap) curX = 0, curY++; else curX--;}}
+
+extern void cmputc ();
+
+#endif
diff --git a/src/cmds.c b/src/cmds.c
index 18821e24b06..e31f99524cd 100644
--- a/src/cmds.c
+++ b/src/cmds.c
@@ -1,5 +1,5 @@
/* Simple built-in editing commands.
- Copyright (C) 1985 Free Software Foundation, Inc.
+ Copyright (C) 1985, 1990 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -24,7 +24,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "buffer.h"
#include "syntax.h"
-Lisp_Object Qkill_forward_chars, Qkill_backward_chars, Vblink_paren_function;
+Lisp_Object Qkill_forward_chars, Qkill_backward_chars, Vblink_paren_hook;
DEFUN ("forward-char", Fforward_char, Sforward_char, 0, 1, "p",
@@ -68,13 +68,11 @@ On attempt to pass beginning or end of buffer, stop and signal error.")
}
DEFUN ("forward-line", Fforward_line, Sforward_line, 0, 1, "p",
- "Move ARG lines forward (backward if ARG is negative).\n\
-Precisely, if point is on line I, move to the start of line I + ARG.\n\
+ "If point is on line i, move to the start of line i + ARG.\n\
If there isn't room, go as far as possible (no error).\n\
-Returns the count of lines left to move. If moving forward,\n\
-that is ARG - number of lines moved; if backward, ARG + number moved.\n\
-With positive ARG, a non-empty line at the end counts as one line\n\
- successfully moved (for the return value).")
+Returns the count of lines left to move.\n\
+With positive ARG, a non-empty line traversed at end of buffer \n\
+ counts as one line successfully moved (for the return value).")
(n)
Lisp_Object n;
{
@@ -94,7 +92,7 @@ With positive ARG, a non-empty line at the end counts as one line\n\
pos = scan_buffer ('\n', pos2, count - negp, &shortage);
if (shortage > 0
&& (negp
- || (ZV >= BEGV
+ || (ZV > BEGV && pos != pos2
&& FETCH_CHAR (pos - 1) != '\n')))
shortage--;
SET_PT (pos);
@@ -193,29 +191,23 @@ ARG was explicitly specified.")
}
DEFUN ("self-insert-command", Fself_insert_command, Sself_insert_command, 1, 1, "p",
- "Insert the character you type.\n\
-Whichever character you type to run this command is inserted.")
+ "Insert this character. Prefix arg is repeat-count.")
(arg)
Lisp_Object arg;
{
CHECK_NUMBER (arg, 0);
- /* Barf if the key that invoked this was not a character. */
- if (XTYPE (last_command_char) != Lisp_Int)
- bitch_at_user ();
- else
- while (XINT (arg) > 0)
- {
- XFASTINT (arg)--; /* Ok since old and new vals both nonneg */
- internal_self_insert (XINT (last_command_char), XFASTINT (arg) != 0);
- }
-
+ while (XINT (arg) > 0)
+ {
+ XFASTINT (arg)--; /* Ok since old and new vals both nonneg */
+ self_insert_internal (last_command_char, XFASTINT (arg) != 0);
+ }
return Qnil;
}
DEFUN ("newline", Fnewline, Snewline, 0, 1, "P",
"Insert a newline. With arg, insert that many newlines.\n\
-In Auto Fill mode, if no numeric arg, break the preceding line if it's long.")
+In Auto Fill mode, can break the preceding line if no numeric arg.")
(arg1)
Lisp_Object arg1;
{
@@ -233,8 +225,8 @@ In Auto Fill mode, if no numeric arg, break the preceding line if it's long.")
than inserting at the ebginning fo a line,
And the textual result is the same.
So if at beginning, pretend to be at the end.
- Must avoid internal_self_insert in that case since point is wrong.
- Luckily internal_self_insert's special features all do nothing in that case. */
+ Must avoid self_insert_internal in that case since point is wrong.
+ Luckily self_insert_internal's special features all do nothing in that case. */
flag = point > BEGV && FETCH_CHAR (point - 1) == '\n';
if (flag)
@@ -245,7 +237,7 @@ In Auto Fill mode, if no numeric arg, break the preceding line if it's long.")
if (flag)
insert (&c1, 1);
else
- internal_self_insert ('\n', !NULL (arg1));
+ self_insert_internal ('\n', !NULL (arg1));
XFASTINT (arg)--; /* Ok since old and new vals both nonneg */
}
@@ -255,7 +247,7 @@ In Auto Fill mode, if no numeric arg, break the preceding line if it's long.")
return Qnil;
}
-internal_self_insert (c1, noautofill)
+self_insert_internal (c1, noautofill)
char c1;
int noautofill;
{
@@ -265,9 +257,6 @@ internal_self_insert (c1, noautofill)
register enum syntaxcode synt;
register int c = c1;
- if (!NULL (Vbefore_change_function) || !NULL (Vafter_change_function))
- hairy = 1;
-
if (!NULL (current_buffer->overwrite_mode)
&& point < ZV
&& c != '\n' && FETCH_CHAR (point) != '\n'
@@ -289,12 +278,12 @@ internal_self_insert (c1, noautofill)
}
if ((c == ' ' || c == '\n')
&& !noautofill
- && !NULL (current_buffer->auto_fill_function)
+ && !NULL (current_buffer->auto_fill_hook)
&& current_column () > XFASTINT (current_buffer->fill_column))
{
if (c1 != '\n')
insert (&c1, 1);
- call0 (current_buffer->auto_fill_function);
+ call0 (current_buffer->auto_fill_hook);
if (c1 == '\n')
insert (&c1, 1);
hairy = 1;
@@ -303,9 +292,9 @@ internal_self_insert (c1, noautofill)
insert (&c1, 1);
synt = SYNTAX (c);
if ((synt == Sclose || synt == Smath)
- && !NULL (Vblink_paren_function) && INTERACTIVE)
+ && !NULL (Vblink_paren_hook) && FROM_KBD)
{
- call0 (Vblink_paren_function);
+ call0 (Vblink_paren_hook);
hairy = 1;
}
return hairy;
@@ -321,10 +310,9 @@ syms_of_cmds ()
Qkill_forward_chars = intern ("kill-forward-chars");
staticpro (&Qkill_forward_chars);
- DEFVAR_LISP ("blink-paren-function", &Vblink_paren_function,
- "Function called, if non-nil, whenever a close parenthesis is inserted.\n\
-More precisely, a char with closeparen syntax is self-inserted.");
- Vblink_paren_function = Qnil;
+ DEFVAR_LISP ("blink-paren-hook", &Vblink_paren_hook,
+ "Function called, if non-nil, whenever a char with closeparen syntax is self-inserted.");
+ Vblink_paren_hook = Qnil;
defsubr (&Sforward_char);
defsubr (&Sbackward_char);
@@ -343,15 +331,15 @@ keys_of_cmds ()
{
int n;
- initial_define_key (global_map, Ctl('M'), "newline");
- initial_define_key (global_map, Ctl('I'), "self-insert-command");
+ ndefkey (Vglobal_map, Ctl('M'), "newline");
+ ndefkey (Vglobal_map, Ctl('I'), "self-insert-command");
for (n = 040; n < 0177; n++)
- initial_define_key (global_map, n, "self-insert-command");
-
- initial_define_key (global_map, Ctl ('A'), "beginning-of-line");
- initial_define_key (global_map, Ctl ('B'), "backward-char");
- initial_define_key (global_map, Ctl ('D'), "delete-char");
- initial_define_key (global_map, Ctl ('E'), "end-of-line");
- initial_define_key (global_map, Ctl ('F'), "forward-char");
- initial_define_key (global_map, 0177, "delete-backward-char");
+ ndefkey (Vglobal_map, n, "self-insert-command");
+
+ ndefkey (Vglobal_map, Ctl ('A'), "beginning-of-line");
+ ndefkey (Vglobal_map, Ctl ('B'), "backward-char");
+ ndefkey (Vglobal_map, Ctl ('D'), "delete-char");
+ ndefkey (Vglobal_map, Ctl ('E'), "end-of-line");
+ ndefkey (Vglobal_map, Ctl ('F'), "forward-char");
+ ndefkey (Vglobal_map, 0177, "delete-backward-char");
}
diff --git a/src/commands.h b/src/commands.h
index de2c7e3c3d3..80c3c4e444a 100644
--- a/src/commands.h
+++ b/src/commands.h
@@ -20,17 +20,13 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#define Ctl(c) ((c)&037)
-/* Define the names of keymaps, just so people can refer to
- them in calls to initial_define_key */
+/* Define the names of keymaps, just so people can refer to them in calls to defkey */
-extern Lisp_Object global_map;
+extern Lisp_Object Vglobal_map;
-extern Lisp_Object meta_map;
+extern Lisp_Object Vesc_map;
-extern Lisp_Object control_x_map;
-
-/* Keymap for mouse commands. */
-extern Lisp_Object Vglobal_mouse_map;
+extern Lisp_Object Vctl_x_map;
extern Lisp_Object Vminibuffer_local_map;
@@ -43,7 +39,7 @@ extern Lisp_Object Vminibuffer_local_completion_map;
extern Lisp_Object Vminibuffer_local_must_match_map;
/* Last character of last key sequence. */
-extern Lisp_Object last_command_char;
+extern int last_command_char;
/* Command character to be re-read, or -1 */
extern int unread_command_char;
@@ -54,11 +50,13 @@ extern Lisp_Object last_command;
/* Nonzero means ^G can quit instantly */
extern int immediate_quit;
+/* Character that causes a quit. Normally C-g. */
+extern int quit_char;
+
extern Lisp_Object Vexecuting_macro;
/* Nonzero if input is coming from the keyboard */
-
-#define INTERACTIVE (NULL (Vexecuting_macro) && !noninteractive)
+#define FROM_KBD (NULL (Vexecuting_macro) && !noninteractive)
/* Set this nonzero to force reconsideration of mode line. */
diff --git a/src/compile.com b/src/compile.com
new file mode 100644
index 00000000000..0a62638bf55
--- /dev/null
+++ b/src/compile.com
@@ -0,0 +1,91 @@
+$ set noverify
+$ ! VMS command file to recompile all .C files which need recompilation.
+$ ! These are all .C files that have no .OBJ files or that are newer
+$ ! than the corresponding .OBJ files. This file is self contained
+$ ! and does not require you to do anything before running it.
+$ !***
+$ !*** Mukesh Prasad compile.com Nov. 18, 1985
+$ !***
+$ !*** Compile all .C files in the directory 'sourcedir'.
+$ !*** If an argument is present, compiles all files, otherwise
+$ !*** compiles only files modified since last compile.
+$ !***
+$
+$! First we try to sense which C compiler we have available.
+$!
+$set noon !do not bomb if an error occurs.
+$assign nla0: sys$output
+$assign nla0: sys$error !so we do not get an error message about this.
+$cc nla0:compiler_check.c
+$if $status.eq.%x38090 then goto try_gcc
+$goto have_compiler
+$!
+$try_gcc:
+$gcc nla0:compiler_check.c
+$if $status.eq.%x38090 then goto whoops
+$ CC :== GCC
+$goto have_compiler
+$!
+$whoops:
+$write sys$output "You must have a C compiler to build Emacs. Sorry."
+$deassign sys$output
+$deassign sys$error
+$exit %x38090
+$!
+$!
+$have_compiler:
+$deassign sys$output
+$deassign sys$error
+$set on
+$if f$search("compiler_check.obj").nes."" then dele/nolog compiler_check.obj;
+$write sys$output "Building Emacs with the ''cc' compiler."
+$
+$ @precomp
+$ @recomp dispnew.c
+$ @recomp scroll.c
+$ @recomp xdisp.c
+$ @recomp window.c
+$ @recomp term.c
+$ @recomp cm.c
+$ @recomp emacs.c
+$ @recomp keyboard.c
+$ @recomp macros.c
+$ @recomp keymap.c
+$ @recomp sysdep.c
+$ @recomp buffer.c
+$ @recomp filelock.c
+$ @recomp insdel.c
+$ @recomp marker.c
+$ @recomp minibuf.c
+$ @recomp fileio.c
+$ @recomp dired.c
+$ @recomp filemode.c
+$ @recomp cmds.c
+$ @recomp casefiddle.c
+$ @recomp indent.c
+$ @recomp search.c
+$ @recomp regex.c
+$ @recomp undo.c
+$ @recomp alloc.c
+$ @recomp data.c
+$ @recomp doc.c
+$ @recomp editfns.c
+$ @recomp callint.c
+$ @recomp eval.c
+$ @recomp fns.c
+$ @recomp print.c
+$ @recomp lread.c
+$ @recomp abbrev.c
+$ @recomp syntax.c
+$ @recomp mocklisp.c
+$ @recomp bytecode.c
+$ @recomp process.c
+$ @recomp callproc.c
+$ @recomp vmsfns.c
+$ @recomp doprnt.c
+$ @recomp vmsmap.c
+$ @recomp termcap.c
+$ @recomp tparam.c
+$ @recomp lastfile.c
+$ @recomp malloc.c
+$ @recomp alloca.c
diff --git a/src/config.in b/src/config.h-dist
index f34b20117a4..6132c09d8f8 100644
--- a/src/config.in
+++ b/src/config.h-dist
@@ -3,37 +3,34 @@
This file is part of GNU Emacs.
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY. No author or distributor
-accepts responsibility to anyone for the consequences of using it
-or for whether it serves any particular purpose or works at all,
-unless he says so in writing. Refer to the GNU Emacs General Public
-License for full details.
+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.
-Everyone is granted permission to copy, modify and redistribute
-GNU Emacs, but only under the conditions described in the
-GNU Emacs General Public License. A copy of this license is
-supposed to have been given to you along with GNU Emacs so you
-can know your rights and responsibilities. It should be in a
-file named COPYING. Among other things, the copyright notice
-and this notice must be preserved on all copies. */
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-/* The configuration script links system.h to a s- file that describes
- the system type you are using.
+/* Include here a s- file that describes the system type you are using.
See the file ../etc/MACHINES for a list of systems and
the names of the s- files to use for them.
See s-template.h for documentation on writing s- files. */
-#include "system.h"
+#include "s-bsd4-2.h"
-/* The configuration script links machine.h to a m- file that
- describes the machine and system you use.
+/* Include here a m- file that describes the machine and system you use.
See the file ../etc/MACHINES for a list of machines and
the names of the m- files to use for them.
See m-template.h for info on what m- files should define.
*/
-#include "machine.h"
+#include "m-vax.h"
/* Load in the conversion definitions if this system
needs them and the source file being compiled has not
@@ -50,10 +47,12 @@ and this notice must be preserved on all copies. */
/* #define HAVE_X_WINDOWS */
-/* Define HAVE_X11 if you want to use version 11 of X windows.
+/* Define X11 if you want to use version 11 of X windows.
Otherwise, Emacs expects to use version 10. */
-#define HAVE_X11
+#ifdef HAVE_X_WINDOWS
+#define X11
+#endif
/* Define HAVE_X_MENU if you want to use the X window menu system.
This appears to work on some machines that support X
@@ -90,22 +89,14 @@ and this notice must be preserved on all copies. */
/* #define AMPERSAND_FULL_NAME */
-/* Maximum screen width we handle. */
-
-#define MScreenWidth 300
-
-/* Maximum screen length we handle. */
-
-#define MScreenLength 300
-
/* # bytes of pure Lisp code to leave space for.
- Note that s-vms.h, m-sun2.h and m-sparc.h may override this default. */
+ Note that s-vms.h and m-sun2.h may override this default. */
#ifndef PURESIZE
#ifdef HAVE_X_WINDOWS
#define PURESIZE 122000
#else
-#define PURESIZE 118000
+#define PURESIZE 120000
#endif
#endif
@@ -117,33 +108,3 @@ and this notice must be preserved on all copies. */
/* #define HIGHPRI */
-/* support `getenv' and `setenv' in Emacs (unix only) */
-#define MAINTAIN_ENVIRONMENT
-
-/* Define LISP_FLOAT_TYPE if you want emacs to support floating-point
- numbers. */
-
-/* #define LISP_FLOAT_TYPE */
-
-/* Define GNU_MALLOC if you want to use the *new* GNU memory allocator. */
-
-/* #define GNU_MALLOC */
-
-/* Define REL_ALLOC if you want to use the relocating allocator for
- buffer space. */
-
-/* #define REL_ALLOC */
-
-/* Define LD_SWITCH_SITE to contain any special flags your loader may
- need. For instance, if you've defined HAVE_X_WINDOWS above and your
- X libraries aren't in a place that your loader can find on its own,
- you might want to add "-L/..." or something similar. */
-
-/* #define LD_SWITCH_SITE */
-
-/* Define C_SWITCH_SITE to contain any special flags your compiler may
- need. For instance, if you've defined HAVE_X_WINDOWS above and your
- X include files aren't in a place that your compiler can find on its
- own, you might want to add "-I/..." or something similar. */
-
-/* #define C_SWITCH_SITE */
diff --git a/src/crt0.c b/src/crt0.c
new file mode 100644
index 00000000000..1035054f07e
--- /dev/null
+++ b/src/crt0.c
@@ -0,0 +1,535 @@
+/* C code startup routine.
+ Copyright (C) 1985, 1986 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+In other words, you are welcome to use, share and improve this program.
+You are forbidden to forbid anyone else to use, share and improve
+what you give them. Help stamp out software-hoarding! */
+
+
+/* The standard Vax 4.2 Unix crt0.c cannot be used for Emacs
+ because it makes `envron' an initialized variable.
+ It is easiest to have a special crt0.c on all machines
+ though I don't know whether other machines actually need it. */
+
+/* On the vax and 68000, in BSD4.2 and USG5.2,
+ this is the data format on startup:
+ (vax) ap and fp are unpredictable as far as I know; don't use them.
+ sp -> word containing argc
+ word pointing to first arg string
+ [word pointing to next arg string]... 0 or more times
+ 0
+Optionally:
+ [word pointing to environment variable]... 1 or more times
+ ...
+ 0
+And always:
+ first arg string
+ [next arg string]... 0 or more times
+*/
+
+/* On the 16000, at least in the one 4.2 system I know about,
+ the initial data format is
+ sp -> word containing argc
+ word containing argp
+ word pointing to first arg string, and so on as above
+*/
+
+#include "config.h"
+
+/* ******** WARNING ********
+ Do not insert any data definitions before data_start!
+ Since this is the first file linked, the address of the following
+ variable should correspond to the start of initialized data space.
+ On some systems this is a constant that is independent of the text
+ size for shared executables. On others, it is a function of the
+ text size. In short, this seems to be the most portable way to
+ discover the start of initialized data space dynamically at runtime,
+ for either shared or unshared executables, on either swapping or
+ virtual systems. It only requires that the linker allocate objects
+ in the order encountered, a reasonable model for most Unix systems.
+ Similarly, note that the address of _start() should be the start
+ of text space. Fred Fish, UniSoft Systems Inc. */
+
+int data_start = 0;
+
+#ifdef NEED_ERRNO
+int errno;
+#endif
+
+#ifndef DONT_NEED_ENVIRON
+char **environ;
+#endif
+
+#if defined(orion) || defined(pyramid) || defined(celerity) || defined(ALLIANT) || defined(clipper)
+
+#ifdef ALLIANT
+/* _start must initialize _curbrk and _minbrk on the first startup;
+ when starting up after dumping, it must initialize them to what they were
+ before the dumping, since they are in the shared library and
+ are not dumped. See ADJUST_EXEC_HEADER in m-alliant.h. */
+extern unsigned char *_curbrk, *_minbrk;
+extern unsigned char end;
+unsigned char *_setbrk = &end;
+#ifdef ALLIANT_2800
+unsigned char *_end = &end;
+#endif
+#endif
+
+#ifndef DUMMIES
+#define DUMMIES
+#endif
+
+_start (DUMMIES argc, argv, envp)
+ int argc;
+ char **argv, **envp;
+{
+#ifdef ALLIANT
+#ifdef ALLIANT_2800
+ _curbrk = _end;
+ _minbrk = _end;
+#else
+ _curbrk = _setbrk;
+ _minbrk = _setbrk;
+#endif
+#endif
+
+ environ = envp;
+
+ exit (main (argc, argv, envp));
+}
+
+#endif /* orion or pyramid or celerity or alliant or clipper */
+
+#if defined (ns16000) && !defined (sequent) && !defined (UMAX)
+
+_start ()
+{
+/* On 16000, _start pushes fp onto stack */
+ start1 ();
+}
+
+/* ignore takes care of skipping the fp value pushed in start. */
+static
+start1 (ignore, argc, argv)
+ int ignore;
+ int argc;
+ register char **argv;
+{
+ environ = argv + argc + 1;
+
+ if (environ == *argv)
+ environ--;
+ exit (main (argc, argv, environ));
+}
+#endif /* ns16000, not sequent and not UMAX */
+
+#ifdef UMAX
+_start()
+{
+ asm(" exit [] # undo enter");
+ asm(" .set exitsc,1");
+ asm(" .set sigcatchall,0x400");
+
+ asm(" .globl _exit");
+ asm(" .globl start");
+ asm(" .globl __start");
+ asm(" .globl _main");
+ asm(" .globl _environ");
+ asm(" .globl _sigvec");
+ asm(" .globl sigentry");
+
+ asm("start:");
+ asm(" br .xstart");
+ asm(" .org 0x20");
+ asm(" .double p_glbl,0,0xf00000,0");
+ asm(" .org 0x30");
+ asm(".xstart:");
+ asm(" adjspb $8");
+ asm(" movd 8(sp),0(sp) # argc");
+ asm(" addr 12(sp),r0");
+ asm(" movd r0,4(sp) # argv");
+ asm("L1:");
+ asm(" movd r0,r1");
+ asm(" addqd $4,r0");
+ asm(" cmpqd $0,0(r1) # null args term ?");
+ asm(" bne L1");
+ asm(" cmpd r0,0(4(sp)) # end of 'env' or 'argv' ?");
+ asm(" blt L2");
+ asm(" addqd $-4,r0 # envp's are in list");
+ asm("L2:");
+ asm(" movd r0,8(sp) # env");
+ asm(" movd r0,@_environ # indir is 0 if no env ; not 0 if env");
+ asm(" movqd $0,tos # setup intermediate signal handler");
+ asm(" addr @sv,tos");
+ asm(" movzwd $sigcatchall,tos");
+ asm(" jsr @_sigvec");
+ asm(" adjspb $-12");
+ asm(" jsr @_main");
+ asm(" adjspb $-12");
+ asm(" movd r0,tos");
+ asm(" jsr @_exit");
+ asm(" adjspb $-4");
+ asm(" addr @exitsc,r0");
+ asm(" svc");
+ asm(" .align 4 # sigvec arg");
+ asm("sv:");
+ asm(" .double sigentry");
+ asm(" .double 0");
+ asm(" .double 0");
+
+ asm(" .comm p_glbl,1");
+}
+#endif /* UMAX */
+
+#ifdef CRT0_DUMMIES
+
+/* Define symbol "start": here; some systems want that symbol. */
+#ifdef DOT_GLOBAL_START
+asm(" .text ");
+asm(" .globl start ");
+asm(" start: ");
+#endif /* DOT_GLOBAL_START */
+
+#ifdef NODOT_GLOBAL_START
+asm(" text ");
+asm(" global start ");
+asm(" start: ");
+#endif /* NODOT_GLOBAL_START */
+
+static start1 ();
+
+_start ()
+{
+/* On vax, nothing is pushed here */
+/* On sequent, bogus fp is pushed here */
+ start1 ();
+}
+
+static
+start1 (CRT0_DUMMIES argc, xargv)
+ int argc;
+ char *xargv;
+{
+ register char **argv = &xargv;
+ environ = argv + argc + 1;
+
+ if ((char *)environ == xargv)
+ environ--;
+ exit (main (argc, argv, environ));
+}
+#else /* not CRT0_DUMMIES */
+
+/* "m68k" and "m68000" both stand for m68000 processors,
+ but with different program-entry conventions.
+ This is a kludge. Now that the CRT0_DUMMIES mechanism above exists,
+ most of these machines could use the vax code above
+ with some suitable definition of CRT0_DUMMIES.
+ Then the symbol m68k could be flushed.
+ But I don't want to risk breaking these machines
+ in a version 17 patch release, so that change is being put off. */
+
+#ifdef m68k /* Can't do it all from C */
+ asm (" global _start");
+ asm (" text");
+ asm ("_start:");
+#ifndef NU
+#ifdef STRIDE
+ asm (" comm havefpu%,2");
+#else /* m68k, not STRIDE */
+ asm (" comm splimit%,4");
+#endif /* STRIDE */
+ asm (" global exit");
+ asm (" text");
+#ifdef STRIDE
+ asm (" trap &3");
+ asm (" mov.w %d0,havefpu%");
+#else /* m68k, not STRIDE */
+ asm (" mov.l %d0,splimit%");
+#endif /* STRIDE */
+#endif /* not NU */
+ asm (" jsr start1");
+ asm (" mov.l %d0,(%sp)");
+ asm (" jsr exit");
+ asm (" mov.l &1,%d0"); /* d0 = 1 => exit */
+ asm (" trap &0");
+#else /* m68000, not m68k */
+
+#ifdef m68000
+
+#ifdef ISI68K
+/* Added by ESM Sun May 24 12:44:02 1987 to get new ISI library to work */
+#ifdef BSD4_3
+static foo () {
+#endif
+ asm (" .globl is68020");
+ asm ("is68020:");
+#ifndef BSD4_3
+ asm (" .long 0x00000000");
+ asm (" .long 0xffffffff");
+/* End of stuff added by ESM */
+#endif
+ asm (" .text");
+ asm (" .globl __start");
+ asm ("__start:");
+ asm (" .word 0");
+ asm (" link fp,#0");
+ asm (" jbsr _start1");
+ asm (" unlk fp");
+ asm (" rts");
+#ifdef BSD4_3
+ }
+#endif
+#else /* not ISI68K */
+
+_start ()
+{
+/* On 68000, _start pushes a6 onto stack */
+ start1 ();
+}
+#endif /* not ISI68k */
+#endif /* m68000 */
+#endif /* m68k */
+
+#if defined(m68k) || defined(m68000)
+/* ignore takes care of skipping the a6 value pushed in start. */
+static
+#if defined(m68k)
+start1 (argc, xargv)
+#else
+start1 (ignore, argc, xargv)
+#endif
+ int argc;
+ char *xargv;
+{
+ register char **argv = &xargv;
+ environ = argv + argc + 1;
+
+ if ((char *)environ == xargv)
+ environ--;
+ exit (main (argc, argv, environ));
+}
+
+#endif /* m68k or m68000 */
+
+#endif /* not CRT0_DUMMIES */
+
+#ifdef hp9000s300
+int argc_value;
+char **argv_value;
+#ifdef OLD_HP_ASSEMBLER
+ asm(" text");
+ asm(" globl __start");
+ asm(" globl _exit");
+ asm(" globl _main");
+ asm("__start");
+ asm(" dc.l 0");
+ asm(" subq.w #0x1,d0");
+ asm(" move.w d0,float_soft");
+ asm(" move.l 0x4(a7),d0");
+ asm(" beq.s skip_1");
+ asm(" move.l d0,a0");
+ asm(" clr.l -0x4(a0)");
+ asm("skip_1");
+ asm(" move.l a7,a0");
+ asm(" subq.l #0x8,a7");
+ asm(" move.l (a0),(a7)");
+ asm(" move.l (a0),_argc_value");
+ asm(" addq.l #0x4,a0");
+ asm(" move.l a0,0x4(a7)");
+ asm(" move.l a0,_argv_value");
+ asm("incr_loop");
+ asm(" tst.l (a0)+");
+ asm(" bne.s incr_loop");
+ asm(" move.l 0x4(a7),a1");
+ asm(" cmp.l (a1),a0");
+ asm(" blt.s skip_2");
+ asm(" subq.l #0x4,a0");
+ asm("skip_2");
+ asm(" move.l a0,0x8(a7)");
+ asm(" move.l a0,_environ");
+ asm(" jsr _main");
+ asm(" addq.l #0x8,a7");
+ asm(" move.l d0,-(a7)");
+ asm(" jsr _exit");
+ asm(" move.w #0x1,d0");
+ asm(" trap #0x0");
+ asm(" comm float_soft,4");
+/* float_soft is allocated in this way because C would
+ put an underscore character in its name otherwise. */
+
+#else /* new hp assembler */
+
+ asm(" text");
+ asm(" global float_loc");
+ asm(" set float_loc,0xFFFFB000");
+ asm(" global fpa_loc");
+ asm(" set fpa_loc,0xfff08000");
+ asm(" global __start");
+ asm(" global _exit");
+ asm(" global _main");
+ asm("__start:");
+ asm(" byte 0,0,0,0");
+ asm(" subq.w &1,%d0");
+ asm(" mov.w %d0,float_soft");
+ asm(" mov.w %d1,flag_68881");
+#ifndef HPUX_68010
+ asm(" beq.b skip_float");
+ asm(" fmov.l &0x7400,%fpcr");
+/* asm(" fmov.l &0x7480,%fpcr"); */
+#endif /* HPUX_68010 */
+ asm("skip_float:");
+ asm(" mov.l %a0,%d0");
+ asm(" add.l %d0,%d0");
+ asm(" subx.w %d1,%d1");
+ asm(" mov.w %d1,flag_68010");
+ asm(" add.l %d0,%d0");
+ asm(" subx.w %d1,%d1");
+ asm(" mov.w %d1,flag_fpa");
+ asm(" tst.l %d2");
+ asm(" ble.b skip_3");
+ asm(" lsl flag_68881");
+ asm(" lsl flag_fpa");
+ asm("skip_3:");
+ asm(" mov.l 4(%a7),%d0");
+ asm(" beq.b skip_1");
+ asm(" mov.l %d0,%a0");
+ asm(" clr.l -4(%a0)");
+ asm("skip_1:");
+ asm(" mov.l %a7,%a0");
+ asm(" subq.l &8,%a7");
+ asm(" mov.l (%a0),(%a7)");
+ asm(" mov.l (%a0),_argc_value");
+ asm(" addq.l &4,%a0");
+ asm(" mov.l %a0,4(%a7)");
+ asm(" mov.l %a0,_argv_value");
+ asm("incr_loop:");
+ asm(" tst.l (%a0)+");
+ asm(" bne.b incr_loop");
+ asm(" mov.l 4(%a7),%a1");
+ asm(" cmp.l %a0,(%a1)");
+ asm(" blt.b skip_2");
+ asm(" subq.l &4,%a0");
+ asm("skip_2:");
+ asm(" mov.l %a0,8(%a7)");
+ asm(" mov.l %a0,_environ");
+ asm(" jsr _main");
+ asm(" addq.l &8,%a7");
+ asm(" mov.l %d0,-(%a7)");
+ asm(" jsr _exit");
+ asm(" mov.w &1,%d0");
+ asm(" trap &0");
+ asm(" comm float_soft, 4");
+ asm(" comm flag_68881, 4");
+ asm(" comm flag_68010, 4");
+ asm(" comm flag_fpa, 4");
+
+#endif /* new hp assembler */
+#endif /* hp9000s300 */
+
+#ifdef GOULD
+
+/* startup code has to be in near text rather
+ than fartext as allocated by the C compiler. */
+ asm(" .text");
+ asm(" .align 2");
+ asm(" .globl __start");
+ asm(" .text");
+ asm("__start:");
+/* setup base register b1 (function base). */
+ asm(" .using b1,.");
+ asm(" tpcbr b1");
+/* setup base registers b3 through b7 (data references). */
+ asm(" file basevals,b3");
+/* setup base register b2 (stack pointer); it should be
+ aligned on a 8-word boundary; but because it is pointing
+ to argc, its value should be remembered (in r5). */
+ asm(" movw b2,r4");
+ asm(" movw b2,r5");
+ asm(" andw #~0x1f,r4");
+ asm(" movw r4,b2");
+/* allocate stack frame to do some work. */
+ asm(" subea 16w,b2");
+/* initialize signal catching for UTX/32 1.2; this is
+ necessary to make restart from saved image work. */
+ asm(" movea sigcatch,r1");
+ asm(" movw r1,8w[b2]");
+ asm(" svc #1,#150");
+/* setup address of argc for start1. */
+ asm(" movw r5,8w[b2]");
+ asm(" func #1,_start1");
+ asm(" halt");
+/* space for ld to store base register initial values. */
+ asm(" .align 5");
+ asm("basevals:");
+ asm(" .word __base3,__base4,__base5,__base6,__base7");
+
+static
+start1 (xargc)
+ int *xargc;
+{
+ register int argc;
+ register char **argv;
+
+ argc = *xargc;
+ argv = (char **)(xargc) + 1;
+ environ = argv + argc + 1;
+
+ if (environ == argv)
+ environ--;
+ exit (main (argc, argv, environ));
+
+}
+
+#endif /* GOULD */
+
+#ifdef elxsi
+extern int errno;
+extern char **environ;
+
+_start()
+{
+ register int r;
+
+ errno = 0;
+ environ = *(&environ + 8);
+ _stdinit();
+ r = main(*(&environ + 6), *(&environ + 7), environ);
+ exit(r);
+ _exit(r);
+}
+#endif /* elxsi */
+
+
+#ifdef sparc
+asm (".global __start");
+asm (".text");
+asm ("__start:");
+asm (" mov 0, %fp");
+asm (" ld [%sp + 64], %o0");
+asm (" add %sp, 68, %o1");
+asm (" sll %o0, 2, %o2");
+asm (" add %o2, 4, %o2");
+asm (" add %o1, %o2, %o2");
+asm (" sethi %hi(_environ), %o3");
+asm (" st %o2, [%o3+%lo(_environ)]");
+asm (" andn %sp, 7, %sp");
+asm (" call _main");
+asm (" sub %sp, 24, %sp");
+asm (" call __exit");
+asm (" nop");
+
+#endif /* sparc */
diff --git a/src/data.c b/src/data.c
new file mode 100644
index 00000000000..fd0d7234f0b
--- /dev/null
+++ b/src/data.c
@@ -0,0 +1,1635 @@
+/* Primitive operations on Lisp data types for GNU Emacs Lisp interpreter.
+ Copyright (C) 1985, 1986 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* This must precede sys/signal.h on certain machines. */
+#include <sys/types.h>
+#include <signal.h>
+
+#include "config.h"
+#include "lisp.h"
+
+#ifndef standalone
+#include "buffer.h"
+#endif
+
+#include "emacssignal.h"
+
+Lisp_Object Qnil, Qt, Qquote, Qlambda, Qsubr, Qunbound;
+Lisp_Object Qerror_conditions, Qerror_message, Qtop_level;
+Lisp_Object Qerror, Qquit, Qwrong_type_argument, Qargs_out_of_range;
+Lisp_Object Qvoid_variable, Qvoid_function;
+Lisp_Object Qsetting_constant, Qinvalid_read_syntax;
+Lisp_Object Qinvalid_function, Qwrong_number_of_arguments, Qno_catch;
+Lisp_Object Qend_of_file, Qarith_error;
+Lisp_Object Qbeginning_of_buffer, Qend_of_buffer, Qbuffer_read_only;
+Lisp_Object Qintegerp, Qnatnump, Qsymbolp, Qlistp, Qconsp;
+Lisp_Object Qstringp, Qarrayp, Qsequencep, Qbufferp;
+Lisp_Object Qchar_or_string_p, Qmarkerp, Qinteger_or_marker_p, Qvectorp;
+Lisp_Object Qboundp, Qfboundp;
+Lisp_Object Qcdr;
+
+Lisp_Object
+wrong_type_argument (predicate, value)
+ register Lisp_Object predicate, value;
+{
+ register Lisp_Object tem;
+ do
+ {
+ if (!EQ (Vmocklisp_arguments, Qt))
+ {
+ if (XTYPE (value) == Lisp_String &&
+ (EQ (predicate, Qintegerp) || EQ (predicate, Qinteger_or_marker_p)))
+ return Fstring_to_int (value, Qt);
+ if (XTYPE (value) == Lisp_Int && EQ (predicate, Qstringp))
+ return Fint_to_string (value);
+ }
+ value = Fsignal (Qwrong_type_argument, Fcons (predicate, Fcons (value, Qnil)));
+ tem = call1 (predicate, value);
+ }
+ while (NULL (tem));
+ return value;
+}
+
+pure_write_error ()
+{
+ error ("Attempt to modify read-only object");
+}
+
+void
+args_out_of_range (a1, a2)
+ Lisp_Object a1, a2;
+{
+ while (1)
+ Fsignal (Qargs_out_of_range, Fcons (a1, Fcons (a2, Qnil)));
+}
+
+void
+args_out_of_range_3 (a1, a2, a3)
+ Lisp_Object a1, a2, a3;
+{
+ while (1)
+ Fsignal (Qargs_out_of_range, Fcons (a1, Fcons (a2, Fcons (a3, Qnil))));
+}
+
+Lisp_Object
+make_number (num)
+ int num;
+{
+ register Lisp_Object val;
+ XSET (val, Lisp_Int, num);
+ return val;
+}
+
+/* On some machines, XINT needs a temporary location.
+ Here it is, in case it is needed. */
+
+int sign_extend_temp;
+
+/* On a few machines, XINT can only be done by calling this. */
+
+int
+sign_extend_lisp_int (num)
+ int num;
+{
+ if (num & (1 << (VALBITS - 1)))
+ return num | ((-1) << VALBITS);
+ else
+ return num & ((1 << VALBITS) - 1);
+}
+
+/* Data type predicates */
+
+DEFUN ("eq", Feq, Seq, 2, 2, 0,
+ "T if the two args are the same Lisp object.")
+ (obj1, obj2)
+ Lisp_Object obj1, obj2;
+{
+ if (EQ (obj1, obj2))
+ return Qt;
+ return Qnil;
+}
+
+DEFUN ("null", Fnull, Snull, 1, 1, 0, "T if OBJECT is nil.")
+ (obj)
+ Lisp_Object obj;
+{
+ if (NULL (obj))
+ return Qt;
+ return Qnil;
+}
+
+DEFUN ("consp", Fconsp, Sconsp, 1, 1, 0, "T if OBJECT is a cons cell.")
+ (obj)
+ Lisp_Object obj;
+{
+ if (XTYPE (obj) == Lisp_Cons)
+ return Qt;
+ return Qnil;
+}
+
+DEFUN ("atom", Fatom, Satom, 1, 1, 0, "T if OBJECT is not a cons cell. This includes nil.")
+ (obj)
+ Lisp_Object obj;
+{
+ if (XTYPE (obj) == Lisp_Cons)
+ return Qnil;
+ return Qt;
+}
+
+DEFUN ("listp", Flistp, Slistp, 1, 1, 0, "T if OBJECT is a list. This includes nil.")
+ (obj)
+ Lisp_Object obj;
+{
+ if (XTYPE (obj) == Lisp_Cons || NULL (obj))
+ return Qt;
+ return Qnil;
+}
+
+DEFUN ("nlistp", Fnlistp, Snlistp, 1, 1, 0, "T if OBJECT is not a list. Lists include nil.")
+ (obj)
+ Lisp_Object obj;
+{
+ if (XTYPE (obj) == Lisp_Cons || NULL (obj))
+ return Qnil;
+ return Qt;
+}
+
+DEFUN ("integerp", Fintegerp, Sintegerp, 1, 1, 0, "T if OBJECT is a number.")
+ (obj)
+ Lisp_Object obj;
+{
+ if (XTYPE (obj) == Lisp_Int)
+ return Qt;
+ return Qnil;
+}
+
+DEFUN ("natnump", Fnatnump, Snatnump, 1, 1, 0, "T if OBJECT is a nonnegative number.")
+ (obj)
+ Lisp_Object obj;
+{
+ if (XTYPE (obj) == Lisp_Int && XINT (obj) >= 0)
+ return Qt;
+ return Qnil;
+}
+
+DEFUN ("symbolp", Fsymbolp, Ssymbolp, 1, 1, 0, "T if OBJECT is a symbol.")
+ (obj)
+ Lisp_Object obj;
+{
+ if (XTYPE (obj) == Lisp_Symbol)
+ return Qt;
+ return Qnil;
+}
+
+DEFUN ("vectorp", Fvectorp, Svectorp, 1, 1, 0, "T if OBJECT is a vector.")
+ (obj)
+ Lisp_Object obj;
+{
+ if (XTYPE (obj) == Lisp_Vector)
+ return Qt;
+ return Qnil;
+}
+
+DEFUN ("stringp", Fstringp, Sstringp, 1, 1, 0, "T if OBJECT is a string.")
+ (obj)
+ Lisp_Object obj;
+{
+ if (XTYPE (obj) == Lisp_String)
+ return Qt;
+ return Qnil;
+}
+
+DEFUN ("arrayp", Farrayp, Sarrayp, 1, 1, 0, "T if OBJECT is an array (string or vector).")
+ (obj)
+ Lisp_Object obj;
+{
+ if (XTYPE (obj) == Lisp_Vector || XTYPE (obj) == Lisp_String)
+ return Qt;
+ return Qnil;
+}
+
+DEFUN ("sequencep", Fsequencep, Ssequencep, 1, 1, 0,
+ "T if OBJECT is a sequence (list or array).")
+ (obj)
+ register Lisp_Object obj;
+{
+ if (CONSP (obj) || NULL (obj) ||
+ XTYPE (obj) == Lisp_Vector || XTYPE (obj) == Lisp_String)
+ return Qt;
+ return Qnil;
+}
+
+DEFUN ("bufferp", Fbufferp, Sbufferp, 1, 1, 0, "T if OBJECT is an editor buffer.")
+ (obj)
+ Lisp_Object obj;
+{
+ if (XTYPE (obj) == Lisp_Buffer)
+ return Qt;
+ return Qnil;
+}
+
+DEFUN ("markerp", Fmarkerp, Smarkerp, 1, 1, 0, "T if OBJECT is a marker (editor pointer).")
+ (obj)
+ Lisp_Object obj;
+{
+ if (XTYPE (obj) == Lisp_Marker)
+ return Qt;
+ return Qnil;
+}
+
+DEFUN ("integer-or-marker-p", Finteger_or_marker_p, Sinteger_or_marker_p, 1, 1, 0,
+ "T if OBJECT is an integer or a marker (editor pointer).")
+ (obj)
+ register Lisp_Object obj;
+{
+ if (XTYPE (obj) == Lisp_Marker || XTYPE (obj) == Lisp_Int)
+ return Qt;
+ return Qnil;
+}
+
+DEFUN ("subrp", Fsubrp, Ssubrp, 1, 1, 0, "T if OBJECT is a built-in function.")
+ (obj)
+ Lisp_Object obj;
+{
+ if (XTYPE (obj) == Lisp_Subr)
+ return Qt;
+ return Qnil;
+}
+
+DEFUN ("char-or-string-p", Fchar_or_string_p, Schar_or_string_p, 1, 1, 0, "T if OBJECT is a character (a number) or a string.")
+ (obj)
+ register Lisp_Object obj;
+{
+ if (XTYPE (obj) == Lisp_Int || XTYPE (obj) == Lisp_String)
+ return Qt;
+ return Qnil;
+}
+
+/* Extract and set components of lists */
+
+DEFUN ("car", Fcar, Scar, 1, 1, 0,
+ "Return the car of CONSCELL. If arg is nil, return nil.")
+ (list)
+ register Lisp_Object list;
+{
+ while (1)
+ {
+ if (XTYPE (list) == Lisp_Cons)
+ return XCONS (list)->car;
+ else if (EQ (list, Qnil))
+ return Qnil;
+ else
+ list = wrong_type_argument (Qlistp, list);
+ }
+}
+
+DEFUN ("car-safe", Fcar_safe, Scar_safe, 1, 1, 0,
+ "Return the car of OBJECT if it is a cons cell, or else nil.")
+ (object)
+ Lisp_Object object;
+{
+ if (XTYPE (object) == Lisp_Cons)
+ return XCONS (object)->car;
+ else
+ return Qnil;
+}
+
+DEFUN ("cdr", Fcdr, Scdr, 1, 1, 0,
+ "Return the cdr of CONSCELL. If arg is nil, return nil.")
+ (list)
+ register Lisp_Object list;
+{
+ while (1)
+ {
+ if (XTYPE (list) == Lisp_Cons)
+ return XCONS (list)->cdr;
+ else if (EQ (list, Qnil))
+ return Qnil;
+ else
+ list = wrong_type_argument (Qlistp, list);
+ }
+}
+
+DEFUN ("cdr-safe", Fcdr_safe, Scdr_safe, 1, 1, 0,
+ "Return the cdr of OBJECT if it is a cons cell, or else nil.")
+ (object)
+ Lisp_Object object;
+{
+ if (XTYPE (object) == Lisp_Cons)
+ return XCONS (object)->cdr;
+ else
+ return Qnil;
+}
+
+DEFUN ("setcar", Fsetcar, Ssetcar, 2, 2, 0,
+ "Set the car of CONSCELL to be NEWCAR. Returns NEWCAR.")
+ (cell, newcar)
+ register Lisp_Object cell, newcar;
+{
+ if (XTYPE (cell) != Lisp_Cons)
+ cell = wrong_type_argument (Qconsp, cell);
+
+ CHECK_IMPURE (cell);
+ XCONS (cell)->car = newcar;
+ return newcar;
+}
+
+DEFUN ("setcdr", Fsetcdr, Ssetcdr, 2, 2, 0,
+ "Set the cdr of CONSCELL to be NEWCDR. Returns NEWCDR.")
+ (cell, newcdr)
+ register Lisp_Object cell, newcdr;
+{
+ if (XTYPE (cell) != Lisp_Cons)
+ cell = wrong_type_argument (Qconsp, cell);
+
+ CHECK_IMPURE (cell);
+ XCONS (cell)->cdr = newcdr;
+ return newcdr;
+}
+
+/* Extract and set components of symbols */
+
+DEFUN ("boundp", Fboundp, Sboundp, 1, 1, 0, "T if SYMBOL's value is not void.")
+ (sym)
+ register Lisp_Object sym;
+{
+ CHECK_SYMBOL (sym, 0);
+ return (XTYPE (XSYMBOL (sym)->value) == Lisp_Void
+ || EQ (XSYMBOL (sym)->value, Qunbound))
+ ? Qnil : Qt;
+}
+
+DEFUN ("fboundp", Ffboundp, Sfboundp, 1, 1, 0, "T if SYMBOL's function definition is not void.")
+ (sym)
+ register Lisp_Object sym;
+{
+ CHECK_SYMBOL (sym, 0);
+ return (XTYPE (XSYMBOL (sym)->function) == Lisp_Void
+ || EQ (XSYMBOL (sym)->function, Qunbound))
+ ? Qnil : Qt;
+}
+
+DEFUN ("makunbound", Fmakunbound, Smakunbound, 1, 1, 0, "Make SYMBOL's value be void.")
+ (sym)
+ register Lisp_Object sym;
+{
+ CHECK_SYMBOL (sym, 0);
+ XSYMBOL (sym)->value = Qunbound;
+ return sym;
+}
+
+DEFUN ("fmakunbound", Ffmakunbound, Sfmakunbound, 1, 1, 0, "Make SYMBOL's function definition be void.")
+ (sym)
+ register Lisp_Object sym;
+{
+ CHECK_SYMBOL (sym, 0);
+ XSYMBOL (sym)->function = Qunbound;
+ return sym;
+}
+
+DEFUN ("symbol-function", Fsymbol_function, Ssymbol_function, 1, 1, 0,
+ "Return SYMBOL's function definition.")
+ (sym)
+ register Lisp_Object sym;
+{
+ CHECK_SYMBOL (sym, 0);
+ if (EQ (XSYMBOL (sym)->function, Qunbound))
+ return Fsignal (Qvoid_function, Fcons (sym, Qnil));
+ return XSYMBOL (sym)->function;
+}
+
+DEFUN ("symbol-plist", Fsymbol_plist, Ssymbol_plist, 1, 1, 0, "Return SYMBOL's property list.")
+ (sym)
+ register Lisp_Object sym;
+{
+ CHECK_SYMBOL (sym, 0);
+ return XSYMBOL (sym)->plist;
+}
+
+DEFUN ("symbol-name", Fsymbol_name, Ssymbol_name, 1, 1, 0, "Return SYMBOL's name, a string.")
+ (sym)
+ register Lisp_Object sym;
+{
+ register Lisp_Object name;
+
+ CHECK_SYMBOL (sym, 0);
+ XSET (name, Lisp_String, XSYMBOL (sym)->name);
+ return name;
+}
+
+DEFUN ("fset", Ffset, Sfset, 2, 2, 0,
+ "Set SYMBOL's function definition to NEWVAL, and return NEWVAL.")
+ (sym, newdef)
+ register Lisp_Object sym, newdef;
+{
+ CHECK_SYMBOL (sym, 0);
+ if (!NULL (Vautoload_queue) && !EQ (XSYMBOL (sym)->function, Qunbound))
+ Vautoload_queue = Fcons (Fcons (sym, XSYMBOL (sym)->function),
+ Vautoload_queue);
+ XSYMBOL (sym)->function = newdef;
+ return newdef;
+}
+
+DEFUN ("setplist", Fsetplist, Ssetplist, 2, 2, 0,
+ "Set SYMBOL's property list to NEWVAL, and return NEWVAL.")
+ (sym, newplist)
+ register Lisp_Object sym, newplist;
+{
+ CHECK_SYMBOL (sym, 0);
+ XSYMBOL (sym)->plist = newplist;
+ return newplist;
+}
+
+/* Getting and setting values of symbols */
+
+/* Given the raw contents of a symbol value cell,
+ return the Lisp value of the symbol. */
+
+Lisp_Object
+do_symval_forwarding (valcontents)
+ register Lisp_Object valcontents;
+{
+ register Lisp_Object val;
+#ifdef SWITCH_ENUM_BUG
+ switch ((int) XTYPE (valcontents))
+#else
+ switch (XTYPE (valcontents))
+#endif
+ {
+ case Lisp_Intfwd:
+ XSET (val, Lisp_Int, *XINTPTR (valcontents));
+ return val;
+
+ case Lisp_Boolfwd:
+ if (*XINTPTR (valcontents))
+ return Qt;
+ return Qnil;
+
+ case Lisp_Objfwd:
+ return *XOBJFWD (valcontents);
+
+ case Lisp_Buffer_Objfwd:
+ return *(Lisp_Object *)(XUINT (valcontents) + (char *)current_buffer);
+ }
+ return valcontents;
+}
+
+void
+store_symval_forwarding (sym, valcontents, newval)
+ Lisp_Object sym;
+ register Lisp_Object valcontents, newval;
+{
+#ifdef SWITCH_ENUM_BUG
+ switch ((int) XTYPE (valcontents))
+#else
+ switch (XTYPE (valcontents))
+#endif
+ {
+ case Lisp_Intfwd:
+ CHECK_NUMBER (newval, 1);
+ *XINTPTR (valcontents) = XINT (newval);
+ break;
+
+ case Lisp_Boolfwd:
+ *XINTPTR (valcontents) = NULL(newval) ? 0 : 1;
+ break;
+
+ case Lisp_Objfwd:
+ *XOBJFWD (valcontents) = newval;
+ break;
+
+ case Lisp_Buffer_Objfwd:
+ *(Lisp_Object *)(XUINT (valcontents) + (char *)current_buffer) = newval;
+ break;
+
+ default:
+ valcontents = XSYMBOL (sym)->value;
+ if (XTYPE (valcontents) == Lisp_Buffer_Local_Value ||
+ XTYPE (valcontents) == Lisp_Some_Buffer_Local_Value)
+ XCONS (XSYMBOL (sym)->value)->car = newval;
+ else
+ XSYMBOL (sym)->value = newval;
+ }
+}
+
+/* Note that it must not be possible to quit within this function.
+ Great care is required for this. */
+
+DEFUN ("symbol-value", Fsymbol_value, Ssymbol_value, 1, 1, 0, "Return SYMBOL's value.")
+ (sym)
+ Lisp_Object sym;
+{
+ register Lisp_Object valcontents, tem1;
+ register Lisp_Object val;
+ CHECK_SYMBOL (sym, 0);
+ valcontents = XSYMBOL (sym)->value;
+
+ retry:
+#ifdef SWITCH_ENUM_BUG
+ switch ((int) XTYPE (valcontents))
+#else
+ switch (XTYPE (valcontents))
+#endif
+ {
+ case Lisp_Buffer_Local_Value:
+ case Lisp_Some_Buffer_Local_Value:
+ /* valcontents is a list
+ (REALVALUE BUFFER CURRENT-ALIST-ELEMENT . DEFAULT-VALUE)).
+
+ CURRENT-ALIST-ELEMENT is a pointer to an element of BUFFER's
+ local_var_alist, that being the element whose car is this variable.
+ Or it can be a pointer to the (CURRENT-ALIST-ELEMENT . DEFAULT-VALUE), if BUFFER
+ does not have an element in its alist for this variable.
+
+ If the current buffer is not BUFFER, we store the current REALVALUE value into
+ CURRENT-ALIST-ELEMENT, then find the appropriate alist element for
+ the buffer now current and set up CURRENT-ALIST-ELEMENT.
+ Then we set REALVALUE out of that element, and store into BUFFER.
+ Note that REALVALUE can be a forwarding pointer. */
+
+ tem1 = XCONS (XCONS (valcontents)->cdr)->car;
+ if (NULL (tem1) || current_buffer != XBUFFER (tem1))
+ {
+ tem1 = XCONS (XCONS (XCONS (valcontents)->cdr)->cdr)->car;
+ Fsetcdr (tem1, do_symval_forwarding (XCONS (valcontents)->car));
+ tem1 = assq_no_quit (sym, current_buffer->local_var_alist);
+ if (NULL (tem1))
+ tem1 = XCONS (XCONS (valcontents)->cdr)->cdr;
+ XCONS (XCONS (XCONS (valcontents)->cdr)->cdr)->car = tem1;
+ XSET (XCONS (XCONS (valcontents)->cdr)->car, Lisp_Buffer, current_buffer);
+ store_symval_forwarding (sym, XCONS (valcontents)->car, Fcdr (tem1));
+ }
+ valcontents = XCONS (valcontents)->car;
+ goto retry;
+
+ case Lisp_Intfwd:
+ XSET (val, Lisp_Int, *XINTPTR (valcontents));
+ return val;
+
+ case Lisp_Boolfwd:
+ if (*XINTPTR (valcontents))
+ return Qt;
+ return Qnil;
+
+ case Lisp_Objfwd:
+ return *XOBJFWD (valcontents);
+
+ case Lisp_Buffer_Objfwd:
+ return *(Lisp_Object *)(XUINT (valcontents) + (char *)current_buffer);
+
+ case Lisp_Symbol:
+ /* For a symbol, check whether it is 'unbound. */
+ if (!EQ (valcontents, Qunbound))
+ break;
+ /* drops through! */
+ case Lisp_Void:
+ return Fsignal (Qvoid_variable, Fcons (sym, Qnil));
+ }
+ return valcontents;
+}
+
+DEFUN ("default-value", Fdefault_value, Sdefault_value, 1, 1, 0,
+ "Return SYMBOL's default value.\n\
+This is the value that is seen in buffers that do not have their own values\n\
+for this variable.")
+ (sym)
+ Lisp_Object sym;
+{
+ register Lisp_Object valcontents;
+
+ CHECK_SYMBOL (sym, 0);
+ valcontents = XSYMBOL (sym)->value;
+ if (XTYPE (valcontents) == Lisp_Buffer_Objfwd)
+ {
+ register int idx = XUINT (valcontents);
+
+ if (*(int *) (idx + (char *) &buffer_local_flags) != 0)
+ return *(Lisp_Object *)(idx + (char *) &buffer_defaults);
+ }
+
+ if (XTYPE (valcontents) == Lisp_Buffer_Local_Value ||
+ XTYPE (valcontents) == Lisp_Some_Buffer_Local_Value)
+ return XCONS (XCONS (XCONS (valcontents)->cdr)->cdr)->cdr;
+ return Fsymbol_value (sym);
+}
+
+DEFUN ("set", Fset, Sset, 2, 2, 0,
+ "Set SYMBOL's value to NEWVAL, and return NEWVAL.")
+ (sym, newval)
+ register Lisp_Object sym, newval;
+{
+#ifndef RTPC_REGISTER_BUG
+ register Lisp_Object valcontents, tem1, current_alist_element;
+#else /* RTPC_REGISTER_BUG */
+ register Lisp_Object tem1;
+ Lisp_Object valcontents, current_alist_element;
+#endif /* RTPC_REGISTER_BUG */
+
+ CHECK_SYMBOL (sym, 0);
+ if (NULL (sym) || EQ (sym, Qt))
+ return Fsignal (Qsetting_constant, Fcons (sym, Qnil));
+ valcontents = XSYMBOL (sym)->value;
+
+ if (XTYPE (valcontents) == Lisp_Buffer_Objfwd)
+ {
+ register int idx = XUINT (valcontents);
+ register int mask = *(int *)(idx + (char *) &buffer_local_flags);
+ if (mask > 0)
+ current_buffer->local_var_flags |= mask;
+ }
+
+ if (XTYPE (valcontents) == Lisp_Buffer_Local_Value
+ || XTYPE (valcontents) == Lisp_Some_Buffer_Local_Value)
+ {
+ /* valcontents is a list
+ (REALVALUE BUFFER CURRENT-ALIST-ELEMENT . DEFAULT-VALUE)).
+
+ CURRENT-ALIST-ELEMENT is a pointer to an element of BUFFER's
+ local_var_alist, that being the element whose car is this variable.
+ Or it can be a pointer to the (CURRENT-ALIST-ELEMENT . DEFAULT-VALUE),
+ if BUFFER does not have an element in its alist for this variable.
+
+ If the current buffer is not BUFFER, we store the current REALVALUE value into
+ CURRENT-ALIST-ELEMENT, then find the appropriate alist element for
+ the buffer now current and set up CURRENT-ALIST-ELEMENT.
+ Then we set REALVALUE out of that element, and store into BUFFER.
+ Note that REALVALUE can be a forwarding pointer. */
+
+ current_alist_element = XCONS (XCONS (XCONS (valcontents)->cdr)->cdr)->car;
+ if (current_buffer
+ != ((XTYPE (valcontents) == Lisp_Some_Buffer_Local_Value)
+ /* If the current buffer is already cached,
+ we don't need to change that fact. */
+ ? XBUFFER (XCONS (XCONS (valcontents)->cdr)->car)
+ /* If setting the variable should make it local,
+ it's not enough if the current buffer is already cached.
+ We need to make sure it has a local value for the var. */
+ : XBUFFER (XCONS (current_alist_element)->car)))
+ {
+ /* "Swap out" the buffer that was previously cached. */
+ Fsetcdr (current_alist_element,
+ do_symval_forwarding (XCONS (valcontents)->car));
+
+ /* Encache the current buffer. */
+ tem1 = Fassq (sym, current_buffer->local_var_alist);
+ if (NULL (tem1))
+ {
+ /* This buffer sees the default value still.
+ If type is Lisp_Some_Buffer_Local_Value, set the default value.
+ If type is Lisp_Buffer_Local_Value, give this buffer a local value
+ and set that. */
+ if (XTYPE (valcontents) == Lisp_Some_Buffer_Local_Value)
+ tem1 = XCONS (XCONS (valcontents)->cdr)->cdr;
+ else
+ {
+ tem1 = Fcons (sym, Fcdr (current_alist_element));
+ current_buffer->local_var_alist = Fcons (tem1, current_buffer->local_var_alist);
+ }
+ }
+ /* Set the CURRENT-ALIST-ELEMENT slot to fit this buffer. */
+ current_alist_element = tem1;
+ XCONS (XCONS (XCONS (valcontents)->cdr)->cdr)->car = tem1;
+ /* Record this buffer in the BUFFER slot. */
+ XSET (XCONS (XCONS (valcontents)->cdr)->car,
+ Lisp_Buffer, current_buffer);
+ /* Now the CURRENT-ALIST-ELEMENT slot in VALCONTENTS
+ is correct for the current buffer. */
+ }
+ /* If the current buffer sees the default value,
+ set the default value in the CURRENT-ALIST-ELEMENT right now.
+ Don't wait till some other buffer gets cached. */
+ if (XCONS (XCONS (valcontents)->cdr)->cdr == current_alist_element)
+ XCONS (current_alist_element)->cdr = newval;
+ valcontents = XCONS (valcontents)->car;
+ }
+ store_symval_forwarding (sym, valcontents, newval);
+ return newval;
+}
+
+DEFUN ("set-default", Fset_default, Sset_default, 2, 2, 0,
+ "Set SYMBOL's default value to VAL. SYMBOL and VAL are evaluated.\n\
+The default value is seen in buffers that do not have their own values\n\
+for this variable.")
+ (sym, value)
+ Lisp_Object sym, value;
+{
+ register Lisp_Object valcontents, current_alist_element, alist_element_buffer;
+
+ CHECK_SYMBOL (sym, 0);
+ valcontents = XSYMBOL (sym)->value;
+
+ /* Handle variables like case-fold-search that have special slots
+ in the buffer. Make them work apparently like Lisp_Buffer_Local_Value
+ variables. */
+ if (XTYPE (valcontents) == Lisp_Buffer_Objfwd)
+ {
+ register int idx = XUINT (valcontents);
+#ifndef RTPC_REGISTER_BUG
+ register struct buffer *b;
+#else
+ struct buffer *b;
+#endif
+ register int mask = *(int *) (idx + (char *) &buffer_local_flags);
+
+ if (mask < 0)
+ /* -1 means the variable is always local in every buffer.
+ Set the default value, but not any of the local values. */
+ *(Lisp_Object *)(idx + (char *) &buffer_defaults) = value;
+
+ if (mask > 0)
+ {
+ /* Positive means a value that is local in some buffers.
+ Set the default value, and also the corresponding slot
+ in buffers where the variable is not local. */
+ *(Lisp_Object *)(idx + (char *) &buffer_defaults) = value;
+ for (b = all_buffers; b; b = b->next)
+ if (!(b->local_var_flags & mask))
+ *(Lisp_Object *)(idx + (char *) b) = value;
+ }
+ return value;
+ }
+
+ if (XTYPE (valcontents) != Lisp_Buffer_Local_Value &&
+ XTYPE (valcontents) != Lisp_Some_Buffer_Local_Value)
+ return Fset (sym, value);
+
+ /* Store new value into the DEFAULT-VALUE slot */
+ XCONS (XCONS (XCONS (valcontents)->cdr)->cdr)->cdr = value;
+
+ /* If that slot is current, we must set the REALVALUE slot too */
+ current_alist_element = XCONS (XCONS (XCONS (valcontents)->cdr)->cdr)->car;
+ alist_element_buffer = Fcar (current_alist_element);
+ if (EQ (alist_element_buffer, current_alist_element))
+ store_symval_forwarding (sym, XCONS (valcontents)->car, value);
+
+ return value;
+}
+
+DEFUN ("setq-default", Fsetq_default, Ssetq_default, 2, UNEVALLED, 0,
+ "Set SYMBOL's default value to VAL. VAL is evaluated; SYMBOL is not.\n\
+The default value is seen in buffers that do not have their own values\n\
+for this variable.")
+ (args)
+ Lisp_Object args;
+{
+ register Lisp_Object val;
+ struct gcpro gcpro1;
+
+ GCPRO1 (args);
+ val = Feval (Fcar (Fcdr (args)));
+ UNGCPRO;
+ return Fset_default (Fcar (args), val);
+}
+
+DEFUN ("make-variable-buffer-local", Fmake_variable_buffer_local, Smake_variable_buffer_local,
+ 1, 1, "vMake Variable Buffer Local: ",
+ "Make VARIABLE have a separate value for each buffer.\n\
+At any time, the value for the current buffer is in effect.\n\
+There is also a default value which is seen in any buffer which has not yet\n\
+set its own value.\n\
+The function `default-value' gets the default value and `set-default' sets it.\n\
+Using `set' or `setq' to set the variable causes it to have a separate value\n\
+for the current buffer if it was previously using the default value.")
+ (sym)
+ register Lisp_Object sym;
+{
+ register Lisp_Object tem, valcontents;
+
+ CHECK_SYMBOL (sym, 0);
+
+ if (EQ (sym, Qnil) || EQ (sym, Qt))
+ error ("Symbol %s may not be buffer-local", XSYMBOL (sym)->name->data);
+
+ valcontents = XSYMBOL (sym)->value;
+ if ((XTYPE (valcontents) == Lisp_Buffer_Local_Value) ||
+ (XTYPE (valcontents) == Lisp_Buffer_Objfwd))
+ return sym;
+ if (XTYPE (valcontents) == Lisp_Some_Buffer_Local_Value)
+ {
+ XSETTYPE (XSYMBOL (sym)->value, Lisp_Buffer_Local_Value);
+ return sym;
+ }
+ if (EQ (valcontents, Qunbound))
+ XSYMBOL (sym)->value = Qnil;
+ tem = Fcons (Qnil, Fsymbol_value (sym));
+ XCONS (tem)->car = tem;
+ XSYMBOL (sym)->value = Fcons (XSYMBOL (sym)->value, Fcons (Fcurrent_buffer (), tem));
+ XSETTYPE (XSYMBOL (sym)->value, Lisp_Buffer_Local_Value);
+ return sym;
+}
+
+DEFUN ("make-local-variable", Fmake_local_variable, Smake_local_variable,
+ 1, 1, "vMake Local Variable: ",
+ "Make VARIABLE have a separate value in the current buffer.\n\
+Other buffers will continue to share a common default value.\n\
+See also `make-variable-buffer-local'.")
+ (sym)
+ register Lisp_Object sym;
+{
+ register Lisp_Object tem, valcontents;
+
+ CHECK_SYMBOL (sym, 0);
+
+ if (EQ (sym, Qnil) || EQ (sym, Qt))
+ error ("Symbol %s may not be buffer-local", XSYMBOL (sym)->name->data);
+
+ valcontents = XSYMBOL (sym)->value;
+ if ((XTYPE (valcontents) == Lisp_Buffer_Local_Value) ||
+ (XTYPE (valcontents) == Lisp_Buffer_Objfwd))
+ return sym;
+ /* Make sure sym is set up to hold per-buffer values */
+ if (XTYPE (valcontents) != Lisp_Some_Buffer_Local_Value)
+ {
+ if (EQ (valcontents, Qunbound))
+ XSYMBOL (sym)->value = Qnil;
+ tem = Fcons (Qnil, Fsymbol_value (sym));
+ XCONS (tem)->car = tem;
+ XSYMBOL (sym)->value = Fcons (XSYMBOL (sym)->value, Fcons (Qnil, tem));
+ XSETTYPE (XSYMBOL (sym)->value, Lisp_Some_Buffer_Local_Value);
+ }
+ /* Make sure this buffer has its own value of sym */
+ tem = Fassq (sym, current_buffer->local_var_alist);
+ if (NULL (tem))
+ {
+ current_buffer->local_var_alist
+ = Fcons (Fcons (sym, XCONS (XCONS (XCONS (XSYMBOL (sym)->value)->cdr)->cdr)->cdr),
+ current_buffer->local_var_alist);
+
+ /* Make sure symbol does not think it is set up for this buffer;
+ force it to look once again for this buffer's value */
+ {
+ /* This local variable avoids "expression to complex" on IBM RT. */
+ Lisp_Object xs;
+
+ xs = XSYMBOL (sym)->value;
+ if (current_buffer == XBUFFER (XCONS (XCONS (xs)->cdr)->car))
+ XCONS (XCONS (XSYMBOL (sym)->value)->cdr)->car = Qnil;
+ }
+ }
+ return sym;
+}
+
+DEFUN ("kill-local-variable", Fkill_local_variable, Skill_local_variable,
+ 1, 1, "vKill Local Variable: ",
+ "Make VARIABLE no longer have a separate value in the current buffer.\n\
+From now on the default value will apply in this buffer.")
+ (sym)
+ register Lisp_Object sym;
+{
+ register Lisp_Object tem, valcontents;
+
+ CHECK_SYMBOL (sym, 0);
+
+ valcontents = XSYMBOL (sym)->value;
+
+ if (XTYPE (valcontents) == Lisp_Buffer_Objfwd)
+ {
+ register int idx = XUINT (valcontents);
+ register int mask = *(int *) (idx + (char *) &buffer_local_flags);
+
+ if (mask > 0)
+ {
+ *(Lisp_Object *)(idx + (char *) current_buffer)
+ = *(Lisp_Object *)(idx + (char *) &buffer_defaults);
+ current_buffer->local_var_flags &= ~mask;
+ }
+ return sym;
+ }
+
+ if (XTYPE (valcontents) != Lisp_Buffer_Local_Value &&
+ XTYPE (valcontents) != Lisp_Some_Buffer_Local_Value)
+ return sym;
+
+ /* Get rid of this buffer's alist element, if any */
+
+ tem = Fassq (sym, current_buffer->local_var_alist);
+ if (!NULL (tem))
+ current_buffer->local_var_alist = Fdelq (tem, current_buffer->local_var_alist);
+
+ /* Make sure symbol does not think it is set up for this buffer;
+ force it to look once again for this buffer's value */
+ {
+ Lisp_Object sv;
+ sv = XSYMBOL (sym)->value;
+ if (current_buffer == XBUFFER (XCONS (XCONS (sv)->cdr)->car))
+ XCONS (XCONS (sv)->cdr)->car = Qnil;
+ }
+
+ return sym;
+}
+
+/* Extract and set vector and string elements */
+
+DEFUN ("aref", Faref, Saref, 2, 2, 0,
+ "Return the element of ARRAY at index INDEX.\n\
+ARRAY may be a vector or a string. INDEX starts at 0.")
+ (vector, idx)
+ register Lisp_Object vector;
+ Lisp_Object idx;
+{
+ register int idxval;
+
+ CHECK_NUMBER (idx, 1);
+ idxval = XINT (idx);
+ if (XTYPE (vector) != Lisp_Vector && XTYPE (vector) != Lisp_String)
+ vector = wrong_type_argument (Qarrayp, vector);
+ if (idxval < 0 || idxval >= XVECTOR (vector)->size)
+ args_out_of_range (vector, idx);
+ if (XTYPE (vector) == Lisp_Vector)
+ return XVECTOR (vector)->contents[idxval];
+ else
+ {
+ Lisp_Object val;
+ XFASTINT (val) = (unsigned char) XSTRING (vector)->data[idxval];
+ return val;
+ }
+}
+
+DEFUN ("aset", Faset, Saset, 3, 3, 0,
+ "Store into the element of ARRAY at index INDEX the value NEWVAL.\n\
+ARRAY may be a vector or a string. INDEX starts at 0.")
+ (vector, idx, newelt)
+ register Lisp_Object vector;
+ Lisp_Object idx, newelt;
+{
+ register int idxval;
+
+ CHECK_NUMBER (idx, 1);
+ idxval = XINT (idx);
+ if (XTYPE (vector) != Lisp_Vector && XTYPE (vector) != Lisp_String)
+ vector = wrong_type_argument (Qarrayp, vector);
+ if (idxval < 0 || idxval >= XVECTOR (vector)->size)
+ args_out_of_range (vector, idx);
+ CHECK_IMPURE (vector);
+
+ if (XTYPE (vector) == Lisp_Vector)
+ XVECTOR (vector)->contents[idxval] = newelt;
+ else
+ XSTRING (vector)->data[idxval] = XINT (newelt);
+
+ return newelt;
+}
+
+Lisp_Object
+Farray_length (vector)
+ register Lisp_Object vector;
+{
+ register Lisp_Object size;
+ if (XTYPE (vector) != Lisp_Vector && XTYPE (vector) != Lisp_String)
+ vector = wrong_type_argument (Qarrayp, vector);
+ XFASTINT (size) = XVECTOR (vector)->size;
+ return size;
+}
+
+/* Arithmetic functions */
+
+DEFUN ("=", Feqlsign, Seqlsign, 2, 2, 0,
+ "T if two args, both numbers, are equal.")
+ (num1, num2)
+ register Lisp_Object num1, num2;
+{
+ CHECK_NUMBER_COERCE_MARKER (num1, 0);
+ CHECK_NUMBER_COERCE_MARKER (num2, 0);
+
+ if (XINT (num1) == XINT (num2))
+ return Qt;
+ return Qnil;
+}
+
+DEFUN ("<", Flss, Slss, 2, 2, 0,
+ "T if first arg is less than second arg. Both must be numbers.")
+ (num1, num2)
+ register Lisp_Object num1, num2;
+{
+ CHECK_NUMBER_COERCE_MARKER (num1, 0);
+ CHECK_NUMBER_COERCE_MARKER (num2, 0);
+
+ if (XINT (num1) < XINT (num2))
+ return Qt;
+ return Qnil;
+}
+
+DEFUN (">", Fgtr, Sgtr, 2, 2, 0,
+ "T if first arg is greater than second arg. Both must be numbers.")
+ (num1, num2)
+ register Lisp_Object num1, num2;
+{
+ CHECK_NUMBER_COERCE_MARKER (num1, 0);
+ CHECK_NUMBER_COERCE_MARKER (num2, 0);
+
+ if (XINT (num1) > XINT (num2))
+ return Qt;
+ return Qnil;
+}
+
+DEFUN ("<=", Fleq, Sleq, 2, 2, 0,
+ "T if first arg is less than or equal to second arg. Both must be numbers.")
+ (num1, num2)
+ register Lisp_Object num1, num2;
+{
+ CHECK_NUMBER_COERCE_MARKER (num1, 0);
+ CHECK_NUMBER_COERCE_MARKER (num2, 0);
+
+ if (XINT (num1) <= XINT (num2))
+ return Qt;
+ return Qnil;
+}
+
+DEFUN (">=", Fgeq, Sgeq, 2, 2, 0,
+ "T if first arg is greater than or equal to second arg. Both must be numbers.")
+ (num1, num2)
+ register Lisp_Object num1, num2;
+{
+ CHECK_NUMBER_COERCE_MARKER (num1, 0);
+ CHECK_NUMBER_COERCE_MARKER (num2, 0);
+
+ if (XINT (num1) >= XINT (num2))
+ return Qt;
+ return Qnil;
+}
+
+DEFUN ("/=", Fneq, Sneq, 2, 2, 0,
+ "T if first arg is not equal to second arg. Both must be numbers.")
+ (num1, num2)
+ register Lisp_Object num1, num2;
+{
+ CHECK_NUMBER_COERCE_MARKER (num1, 0);
+ CHECK_NUMBER_COERCE_MARKER (num2, 0);
+
+ if (XINT (num1) != XINT (num2))
+ return Qt;
+ return Qnil;
+}
+
+DEFUN ("zerop", Fzerop, Szerop, 1, 1, 0, "T if NUMBER is zero.")
+ (num)
+ register Lisp_Object num;
+{
+ CHECK_NUMBER (num, 0);
+
+ if (!XINT (num))
+ return Qt;
+ return Qnil;
+}
+
+DEFUN ("int-to-string", Fint_to_string, Sint_to_string, 1, 1, 0,
+ "Convert INT to a string by printing it in decimal, with minus sign if negative.")
+ (num)
+ Lisp_Object num;
+{
+ char buffer[20];
+
+ CHECK_NUMBER (num, 0);
+ sprintf (buffer, "%d", XINT (num));
+ return build_string (buffer);
+}
+
+DEFUN ("string-to-int", Fstring_to_int, Sstring_to_int, 1, 1, 0,
+ "Convert STRING to an integer by parsing it as a decimal number.")
+ (str)
+ register Lisp_Object str;
+{
+ CHECK_STRING (str, 0);
+ return make_number (atoi (XSTRING (str)->data));
+}
+
+enum arithop
+ { Aadd, Asub, Amult, Adiv, Alogand, Alogior, Alogxor, Amax, Amin };
+
+Lisp_Object
+arith_driver
+ (code, nargs, args)
+ enum arithop code;
+ int nargs;
+ register Lisp_Object *args;
+{
+ register Lisp_Object val;
+ register int argnum;
+ register int accum;
+ register int next;
+
+#ifdef SWITCH_ENUM_BUG
+ switch ((int) code)
+#else
+ switch (code)
+#endif
+ {
+ case Alogior:
+ case Alogxor:
+ case Aadd:
+ case Asub:
+ accum = 0; break;
+ case Amult:
+ accum = 1; break;
+ case Alogand:
+ accum = -1; break;
+ }
+
+ for (argnum = 0; argnum < nargs; argnum++)
+ {
+ val = args[argnum]; /* using args[argnum] as argument to CHECK_NUMBER_... */
+ CHECK_NUMBER_COERCE_MARKER (val, argnum);
+ args[argnum] = val; /* runs into a compiler bug. */
+ next = XINT (args[argnum]);
+#ifdef SWITCH_ENUM_BUG
+ switch ((int) code)
+#else
+ switch (code)
+#endif
+ {
+ case Aadd: accum += next; break;
+ case Asub:
+ if (!argnum && nargs != 1)
+ next = - next;
+ accum -= next;
+ break;
+ case Amult: accum *= next; break;
+ case Adiv:
+ if (!argnum) accum = next;
+ else
+ {
+ /* Some systems fail to trap this right. */
+ if (!XINT (next))
+ while (1)
+ Fsignal (Qarith_error, Qnil);
+
+ accum /= next;
+ }
+ break;
+ case Alogand: accum &= next; break;
+ case Alogior: accum |= next; break;
+ case Alogxor: accum ^= next; break;
+ case Amax: if (!argnum || next > accum) accum = next; break;
+ case Amin: if (!argnum || next < accum) accum = next; break;
+ }
+ }
+
+ XSET (val, Lisp_Int, accum);
+ return val;
+}
+
+DEFUN ("+", Fplus, Splus, 0, MANY, 0,
+ "Return sum of any number of numbers.")
+ (nargs, args)
+ int nargs;
+ Lisp_Object *args;
+{
+ return arith_driver (Aadd, nargs, args);
+}
+
+DEFUN ("-", Fminus, Sminus, 0, MANY, 0,
+ "Negate number or subtract numbers.\n\
+With one arg, negates it. With more than one arg,\n\
+subtracts all but the first from the first.")
+ (nargs, args)
+ int nargs;
+ Lisp_Object *args;
+{
+ return arith_driver (Asub, nargs, args);
+}
+
+DEFUN ("*", Ftimes, Stimes, 0, MANY, 0,
+ "Returns product of any number of numbers.")
+ (nargs, args)
+ int nargs;
+ Lisp_Object *args;
+{
+ return arith_driver (Amult, nargs, args);
+}
+
+DEFUN ("/", Fquo, Squo, 2, MANY, 0,
+ "Returns first argument divided by rest of arguments.")
+ (nargs, args)
+ int nargs;
+ Lisp_Object *args;
+{
+ return arith_driver (Adiv, nargs, args);
+}
+
+DEFUN ("%", Frem, Srem, 2, 2, 0,
+ "Returns remainder of first arg divided by second.")
+ (num1, num2)
+ register Lisp_Object num1, num2;
+{
+ Lisp_Object val;
+
+ CHECK_NUMBER (num1, 0);
+ CHECK_NUMBER (num2, 1);
+
+ /* Some systems fail to trap this right. */
+ if (!XINT (num2))
+ while (1)
+ Fsignal (Qarith_error, Qnil);
+
+ XSET (val, Lisp_Int, XINT (num1) % XINT (num2));
+ return val;
+}
+
+DEFUN ("max", Fmax, Smax, 1, MANY, 0,
+ "Return largest of all the arguments (which must be numbers.)")
+ (nargs, args)
+ int nargs;
+ Lisp_Object *args;
+{
+ return arith_driver (Amax, nargs, args);
+}
+
+DEFUN ("min", Fmin, Smin, 1, MANY, 0,
+ "Return smallest of all the arguments (which must be numbers.)")
+ (nargs, args)
+ int nargs;
+ Lisp_Object *args;
+{
+ return arith_driver (Amin, nargs, args);
+}
+
+DEFUN ("logand", Flogand, Slogand, 0, MANY, 0,
+ "Return bitwise and of all the arguments (numbers).")
+ (nargs, args)
+ int nargs;
+ Lisp_Object *args;
+{
+ return arith_driver (Alogand, nargs, args);
+}
+
+DEFUN ("logior", Flogior, Slogior, 0, MANY, 0,
+ "Return bitwise or of all the arguments (numbers).")
+ (nargs, args)
+ int nargs;
+ Lisp_Object *args;
+{
+ return arith_driver (Alogior, nargs, args);
+}
+
+DEFUN ("logxor", Flogxor, Slogxor, 0, MANY, 0,
+ "Return bitwise exclusive-or of all the arguments (numbers).")
+ (nargs, args)
+ int nargs;
+ Lisp_Object *args;
+{
+ return arith_driver (Alogxor, nargs, args);
+}
+
+DEFUN ("ash", Fash, Sash, 2, 2, 0,
+ "Return VALUE with its bits shifted left by COUNT.\n\
+If COUNT is negative, shifting is actually to the right.\n\
+In this case, the sign bit is duplicated.")
+ (num1, num2)
+ register Lisp_Object num1, num2;
+{
+ register Lisp_Object val;
+
+ CHECK_NUMBER (num1, 0);
+ CHECK_NUMBER (num2, 1);
+
+ if (XINT (num2) > 0)
+ XSET (val, Lisp_Int, XINT (num1) << XFASTINT (num2));
+ else
+ XSET (val, Lisp_Int, XINT (num1) >> -XINT (num2));
+ return val;
+}
+
+DEFUN ("lsh", Flsh, Slsh, 2, 2, 0,
+ "Return VALUE with its bits shifted left by COUNT.\n\
+If COUNT is negative, shifting is actually to the right.\n\
+In this case, zeros are shifted in on the left.")
+ (num1, num2)
+ register Lisp_Object num1, num2;
+{
+ register Lisp_Object val;
+
+ CHECK_NUMBER (num1, 0);
+ CHECK_NUMBER (num2, 1);
+
+ if (XINT (num2) > 0)
+ XSET (val, Lisp_Int, (unsigned) XFASTINT (num1) << XFASTINT (num2));
+ else
+ XSET (val, Lisp_Int, (unsigned) XFASTINT (num1) >> -XINT (num2));
+ return val;
+}
+
+DEFUN ("1+", Fadd1, Sadd1, 1, 1, 0,
+ "Return NUMBER plus one.")
+ (num)
+ register Lisp_Object num;
+{
+ CHECK_NUMBER_COERCE_MARKER (num, 0);
+ XSETINT (num, XFASTINT (num) + 1);
+ return num;
+}
+
+DEFUN ("1-", Fsub1, Ssub1, 1, 1, 0,
+ "Return NUMBER minus one.")
+ (num)
+ register Lisp_Object num;
+{
+ CHECK_NUMBER_COERCE_MARKER (num, 0);
+ XSETINT (num, XFASTINT (num) - 1);
+ return num;
+}
+
+DEFUN ("lognot", Flognot, Slognot, 1, 1, 0,
+ "Return the bitwise complement of ARG.")
+ (num)
+ register Lisp_Object num;
+{
+ CHECK_NUMBER (num, 0);
+ XSETINT (num, ~XFASTINT (num));
+ return num;
+}
+
+void
+syms_of_data ()
+{
+ Qquote = intern ("quote");
+ Qlambda = intern ("lambda");
+ Qsubr = intern ("subr");
+ Qerror_conditions = intern ("error-conditions");
+ Qerror_message = intern ("error-message");
+ Qtop_level = intern ("top-level");
+
+ Qerror = intern ("error");
+ Qquit = intern ("quit");
+ Qwrong_type_argument = intern ("wrong-type-argument");
+ Qargs_out_of_range = intern ("args-out-of-range");
+ Qvoid_function = intern ("void-function");
+ Qvoid_variable = intern ("void-variable");
+ Qsetting_constant = intern ("setting-constant");
+ Qinvalid_read_syntax = intern ("invalid-read-syntax");
+
+ Qinvalid_function = intern ("invalid-function");
+ Qwrong_number_of_arguments = intern ("wrong-number-of-arguments");
+ Qno_catch = intern ("no-catch");
+ Qend_of_file = intern ("end-of-file");
+ Qarith_error = intern ("arith-error");
+ Qbeginning_of_buffer = intern ("beginning-of-buffer");
+ Qend_of_buffer = intern ("end-of-buffer");
+ Qbuffer_read_only = intern ("buffer-read-only");
+
+ Qlistp = intern ("listp");
+ Qconsp = intern ("consp");
+ Qsymbolp = intern ("symbolp");
+ Qintegerp = intern ("integerp");
+ Qnatnump = intern ("natnump");
+ Qstringp = intern ("stringp");
+ Qarrayp = intern ("arrayp");
+ Qsequencep = intern ("sequencep");
+ Qbufferp = intern ("bufferp");
+ Qvectorp = intern ("vectorp");
+ Qchar_or_string_p = intern ("char-or-string-p");
+ Qmarkerp = intern ("markerp");
+ Qinteger_or_marker_p = intern ("integer-or-marker-p");
+ Qboundp = intern ("boundp");
+ Qfboundp = intern ("fboundp");
+
+ Qcdr = intern ("cdr");
+
+ /* ERROR is used as a signaler for random errors for which nothing else is right */
+
+ Fput (Qerror, Qerror_conditions,
+ Fcons (Qerror, Qnil));
+ Fput (Qerror, Qerror_message,
+ build_string ("error"));
+
+ Fput (Qquit, Qerror_conditions,
+ Fcons (Qquit, Qnil));
+ Fput (Qquit, Qerror_message,
+ build_string ("Quit"));
+
+ Fput (Qwrong_type_argument, Qerror_conditions,
+ Fcons (Qwrong_type_argument, Fcons (Qerror, Qnil)));
+ Fput (Qwrong_type_argument, Qerror_message,
+ build_string ("Wrong type argument"));
+
+ Fput (Qargs_out_of_range, Qerror_conditions,
+ Fcons (Qargs_out_of_range, Fcons (Qerror, Qnil)));
+ Fput (Qargs_out_of_range, Qerror_message,
+ build_string ("Args out of range"));
+
+ Fput (Qvoid_function, Qerror_conditions,
+ Fcons (Qvoid_function, Fcons (Qerror, Qnil)));
+ Fput (Qvoid_function, Qerror_message,
+ build_string ("Symbol's function definition is void"));
+
+ Fput (Qvoid_variable, Qerror_conditions,
+ Fcons (Qvoid_variable, Fcons (Qerror, Qnil)));
+ Fput (Qvoid_variable, Qerror_message,
+ build_string ("Symbol's value as variable is void"));
+
+ Fput (Qsetting_constant, Qerror_conditions,
+ Fcons (Qsetting_constant, Fcons (Qerror, Qnil)));
+ Fput (Qsetting_constant, Qerror_message,
+ build_string ("Attempt to set a constant symbol"));
+
+ Fput (Qinvalid_read_syntax, Qerror_conditions,
+ Fcons (Qinvalid_read_syntax, Fcons (Qerror, Qnil)));
+ Fput (Qinvalid_read_syntax, Qerror_message,
+ build_string ("Invalid read syntax"));
+
+ Fput (Qinvalid_function, Qerror_conditions,
+ Fcons (Qinvalid_function, Fcons (Qerror, Qnil)));
+ Fput (Qinvalid_function, Qerror_message,
+ build_string ("Invalid function"));
+
+ Fput (Qwrong_number_of_arguments, Qerror_conditions,
+ Fcons (Qwrong_number_of_arguments, Fcons (Qerror, Qnil)));
+ Fput (Qwrong_number_of_arguments, Qerror_message,
+ build_string ("Wrong number of arguments"));
+
+ Fput (Qno_catch, Qerror_conditions,
+ Fcons (Qno_catch, Fcons (Qerror, Qnil)));
+ Fput (Qno_catch, Qerror_message,
+ build_string ("No catch for tag"));
+
+ Fput (Qend_of_file, Qerror_conditions,
+ Fcons (Qend_of_file, Fcons (Qerror, Qnil)));
+ Fput (Qend_of_file, Qerror_message,
+ build_string ("End of file during parsing"));
+
+ Fput (Qarith_error, Qerror_conditions,
+ Fcons (Qarith_error, Fcons (Qerror, Qnil)));
+ Fput (Qarith_error, Qerror_message,
+ build_string ("Arithmetic error"));
+
+ Fput (Qbeginning_of_buffer, Qerror_conditions,
+ Fcons (Qbeginning_of_buffer, Fcons (Qerror, Qnil)));
+ Fput (Qbeginning_of_buffer, Qerror_message,
+ build_string ("Beginning of buffer"));
+
+ Fput (Qend_of_buffer, Qerror_conditions,
+ Fcons (Qend_of_buffer, Fcons (Qerror, Qnil)));
+ Fput (Qend_of_buffer, Qerror_message,
+ build_string ("End of buffer"));
+
+ Fput (Qbuffer_read_only, Qerror_conditions,
+ Fcons (Qbuffer_read_only, Fcons (Qerror, Qnil)));
+ Fput (Qbuffer_read_only, Qerror_message,
+ build_string ("Buffer is read-only"));
+
+ staticpro (&Qnil);
+ staticpro (&Qt);
+ staticpro (&Qquote);
+ staticpro (&Qlambda);
+ staticpro (&Qsubr);
+ staticpro (&Qunbound);
+ staticpro (&Qerror_conditions);
+ staticpro (&Qerror_message);
+ staticpro (&Qtop_level);
+
+ staticpro (&Qerror);
+ staticpro (&Qquit);
+ staticpro (&Qwrong_type_argument);
+ staticpro (&Qargs_out_of_range);
+ staticpro (&Qvoid_function);
+ staticpro (&Qvoid_variable);
+ staticpro (&Qsetting_constant);
+ staticpro (&Qinvalid_read_syntax);
+ staticpro (&Qwrong_number_of_arguments);
+ staticpro (&Qinvalid_function);
+ staticpro (&Qno_catch);
+ staticpro (&Qend_of_file);
+ staticpro (&Qarith_error);
+ staticpro (&Qbeginning_of_buffer);
+ staticpro (&Qend_of_buffer);
+ staticpro (&Qbuffer_read_only);
+
+ staticpro (&Qlistp);
+ staticpro (&Qconsp);
+ staticpro (&Qsymbolp);
+ staticpro (&Qintegerp);
+ staticpro (&Qnatnump);
+ staticpro (&Qstringp);
+ staticpro (&Qarrayp);
+ staticpro (&Qsequencep);
+ staticpro (&Qbufferp);
+ staticpro (&Qvectorp);
+ staticpro (&Qchar_or_string_p);
+ staticpro (&Qmarkerp);
+ staticpro (&Qinteger_or_marker_p);
+ staticpro (&Qboundp);
+ staticpro (&Qfboundp);
+ staticpro (&Qcdr);
+
+ defsubr (&Seq);
+ defsubr (&Snull);
+ defsubr (&Slistp);
+ defsubr (&Snlistp);
+ defsubr (&Sconsp);
+ defsubr (&Satom);
+ defsubr (&Sintegerp);
+ defsubr (&Snatnump);
+ defsubr (&Ssymbolp);
+ defsubr (&Sstringp);
+ defsubr (&Svectorp);
+ defsubr (&Sarrayp);
+ defsubr (&Ssequencep);
+ defsubr (&Sbufferp);
+ defsubr (&Smarkerp);
+ defsubr (&Sinteger_or_marker_p);
+ defsubr (&Ssubrp);
+ defsubr (&Schar_or_string_p);
+ defsubr (&Scar);
+ defsubr (&Scdr);
+ defsubr (&Scar_safe);
+ defsubr (&Scdr_safe);
+ defsubr (&Ssetcar);
+ defsubr (&Ssetcdr);
+ defsubr (&Ssymbol_function);
+ defsubr (&Ssymbol_plist);
+ defsubr (&Ssymbol_name);
+ defsubr (&Smakunbound);
+ defsubr (&Sfmakunbound);
+ defsubr (&Sboundp);
+ defsubr (&Sfboundp);
+ defsubr (&Sfset);
+ defsubr (&Ssetplist);
+ defsubr (&Ssymbol_value);
+ defsubr (&Sset);
+ defsubr (&Sdefault_value);
+ defsubr (&Sset_default);
+ defsubr (&Ssetq_default);
+ defsubr (&Smake_variable_buffer_local);
+ defsubr (&Smake_local_variable);
+ defsubr (&Skill_local_variable);
+ defsubr (&Saref);
+ defsubr (&Saset);
+ defsubr (&Sint_to_string);
+ defsubr (&Sstring_to_int);
+ defsubr (&Seqlsign);
+ defsubr (&Slss);
+ defsubr (&Sgtr);
+ defsubr (&Sleq);
+ defsubr (&Sgeq);
+ defsubr (&Sneq);
+ defsubr (&Szerop);
+ defsubr (&Splus);
+ defsubr (&Sminus);
+ defsubr (&Stimes);
+ defsubr (&Squo);
+ defsubr (&Srem);
+ defsubr (&Smax);
+ defsubr (&Smin);
+ defsubr (&Slogand);
+ defsubr (&Slogior);
+ defsubr (&Slogxor);
+ defsubr (&Slsh);
+ defsubr (&Sash);
+ defsubr (&Sadd1);
+ defsubr (&Ssub1);
+ defsubr (&Slognot);
+}
+
+arith_error (signo)
+ int signo;
+{
+#ifdef USG
+ /* USG systems forget handlers when they are used;
+ must reestablish each time */
+ signal (signo, arith_error);
+#endif /* USG */
+#ifdef VMS
+ /* VMS systems are like USG. */
+ signal (signo, arith_error);
+#endif /* VMS */
+#ifdef BSD4_1
+ sigrelse (SIGFPE);
+#else /* not BSD4_1 */
+ sigsetmask (SIGEMPTYMASK);
+#endif /* not BSD4_1 */
+
+ while (1)
+ Fsignal (Qarith_error, Qnil);
+}
+
+init_data ()
+{
+ /* Don't do this if just dumping out.
+ We don't want to call `signal' in this case
+ so that we don't have trouble with dumping
+ signal-delivering routines in an inconsistent state. */
+#ifndef CANNOT_DUMP
+ if (!initialized)
+ return;
+#endif /* CANNOT_DUMP */
+ signal (SIGFPE, arith_error);
+#ifdef uts
+ signal (SIGEMT, arith_error);
+#endif /* uts */
+}
diff --git a/src/dir.h b/src/dir.h
new file mode 100644
index 00000000000..6858c41ca44
--- /dev/null
+++ b/src/dir.h
@@ -0,0 +1,105 @@
+/* GNU Emacs VMS directory definition file.
+ Copyright (C) 1986 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ * Files-11 Ver. 2 directory structure (VMS V4.x - long names)
+ */
+#ifndef DIR$K_LENGTH
+
+#define DIR$C_FID 0
+#define DIR$C_LINKNAME 1
+#define DIR$K_LENGTH 6
+#define DIR$C_LENGTH 6
+#define DIR$S_DIRDEF 6
+#define DIR$W_SIZE 0
+#define DIR$W_VERLIMIT 2
+#define DIR$B_FLAGS 4
+#define DIR$S_TYPE 3
+#define DIR$V_TYPE 0
+#define DIR$V_NEXTREC 6
+#define DIR$V_PREVREC 7
+#define DIR$B_NAMECOUNT 5
+#define DIR$S_NAME 80
+#define DIR$T_NAME 6
+
+#define DIR$K_VERSION 8
+#define DIR$C_VERSION 8
+#define DIR$S_DIRDEF1 8
+#define DIR$W_VERSION 0
+#define DIR$S_FID 6
+#define DIR$W_FID 2
+#define DIR$W_FID_NUM 2
+#define DIR$W_FID_SEQ 4
+#define DIR$W_FID_RVN 6
+#define DIR$B_FID_RVN 6
+#define DIR$B_FID_NMX 7
+
+#define DIR$S_DIRDEF2 1
+#define DIR$T_LINKNAME 0
+
+typedef struct dir$_name {
+/* short dir$w_size; /* if you read with RMS, it eats this... */
+ short dir$w_verlimit; /* maximum number of versions */
+ union {
+ unsigned char dir_b_flags;
+#define dir$b_flags dir__b_flags.dir_b_flags
+ struct {
+ unsigned char dir_v_type: DIR$S_TYPE;
+#define dir$v_type dir__b_flags.dir___b_flags.dir_v_type
+ unsigned char: 3;
+ unsigned char dir_v_nextrec: 1;
+#define dir$v_nextrec dir__b_flags.dir___b_flags.dir_v_nextrec
+ unsigned char dir_v_prevrec: 1;
+#define dir$v_prevrec dir__b_flags.dir___b_flags.dir_v_prevrec
+ } dir___b_flags;
+ } dir__b_flags;
+ unsigned char dir$b_namecount;
+#ifdef __GNUC__
+ char dir$t_name[0];
+#else
+ char dir$t_name[];
+#endif
+} dir$_dirdef; /* only the fixed first part */
+
+typedef struct dir$_version {
+ short dir$w_version;
+ short dir$w_fid_num;
+ short dir$w_fid_seq;
+ union {
+ short dir_w_fid_rvn;
+#define dir$w_fid_rvn dir__w_fid_rvn.dir_w_fid_rvn
+ struct {
+ char dir_b_fid_rvn;
+#define dir$b_fid_rvn dir__w_fid_rvn.dir___w_fid_rvn.dir_b_fid_rvn
+ char dir_b_fid_nmx;
+#define dir$b_fid_nmx dir__w_fid_rvn.dir___w_fid_rvn.dir_b_fid_nmx
+ } dir___w_fid_rvn;
+ } dir__w_fid_rvn;
+} dir$_dirdef1; /* one for each version of the file */
+
+typedef
+struct dir$_linkname {
+#ifdef __GNUC__
+ char dir$t_linkname[0];
+#else
+ char dir$t_linkname[];
+#endif
+} dir$_dirdef2;
+
+#endif
diff --git a/src/dired.c b/src/dired.c
index feb68ed0506..8a0a5c41fb3 100644
--- a/src/dired.c
+++ b/src/dired.c
@@ -53,7 +53,7 @@ extern struct direct *readdir ();
#include "commands.h"
#include "regex.h"
-#include "search.h"
+#include "filetypes.h"
#define min(a, b) ((a) < (b) ? (a) : (b))
@@ -64,31 +64,34 @@ extern struct direct *readdir ();
#define lstat stat
#endif
+extern int completion_ignore_case;
+
Lisp_Object Vcompletion_ignored_extensions;
Lisp_Object Qcompletion_ignore_case;
-DEFUN ("directory-files", Fdirectory_files, Sdirectory_files, 1, 4, 0,
+DEFUN ("directory-files", Fdirectory_files, Sdirectory_files, 1, 3, 0,
"Return a list of names of files in DIRECTORY.\n\
-There are three optional arguments:\n\
-If FULL is non-nil, absolute pathnames of the files are returned.\n\
-If MATCH is non-nil, only pathnames containing that regexp are returned.\n\
-If NOSORT is non-nil, the list is not sorted--its order is unpredictable.\n\
- NOSORT is useful if you plan to sort the result yourself.")
- (dirname, full, match, nosort)
- Lisp_Object dirname, full, match, nosort;
+If FULL is non-NIL, absolute pathnames of the files are returned.\n\
+If MATCH is non-NIL, only pathnames containing that regexp are returned.")
+ (dirname, full, match)
+ Lisp_Object dirname, full, match;
{
DIR *d;
+ char slashfilename[MAXNAMLEN+2];
+ char *filename = slashfilename;
int length;
Lisp_Object list, name;
+ /* In search.c */
+ extern struct re_pattern_buffer searchbuf;
+
if (!NULL (match))
{
CHECK_STRING (match, 3);
/* Compile it now so we don't get an error after opendir */
#ifdef VMS
- compile_pattern (match, &searchbuf,
- buffer_defaults.downcase_table->contents);
+ compile_pattern (match, &searchbuf, (char *) downcase_table);
#else
compile_pattern (match, &searchbuf, 0);
#endif
@@ -100,6 +103,10 @@ If NOSORT is non-nil, the list is not sorted--its order is unpredictable.\n\
list = Qnil;
length = XSTRING (dirname)->size;
+#ifndef VMS
+ if (length == 0 || XSTRING (dirname)->data[length - 1] != '/')
+ *filename++ = '/';
+#endif /* VMS */
/* Loop reading blocks */
while (1)
@@ -111,38 +118,20 @@ If NOSORT is non-nil, the list is not sorted--its order is unpredictable.\n\
len = NAMLEN (dp);
if (dp->d_ino)
{
- if (NULL (match)
- || (0 <= re_search (&searchbuf, dp->d_name, len, 0, len, 0)))
+ strncpy (filename, dp->d_name, len);
+ filename[len] = 0;
+ if (NULL (match) ||
+ (0 <= re_search (&searchbuf, filename, len, 0, len, 0)))
{
if (!NULL (full))
- {
- int index = XSTRING (dirname)->size;
- int total = len + index;
-#ifndef VMS
- if (length == 0
- || XSTRING (dirname)->data[length - 1] != '/')
- total++;
-#endif /* VMS */
-
- name = make_uninit_string (total);
- bcopy (XSTRING (dirname)->data, XSTRING (name)->data,
- index);
-#ifndef VMS
- if (length == 0
- || XSTRING (dirname)->data[length - 1] != '/')
- XSTRING (name)->data[index++] = '/';
-#endif /* VMS */
- bcopy (dp->d_name, XSTRING (name)->data + index, len);
- }
+ name = concat2 (dirname, build_string (slashfilename));
else
- name = make_string (dp->d_name, len);
+ name = build_string (filename);
list = Fcons (name, list);
}
}
}
closedir (d);
- if (!NULL (nosort))
- return list;
return Fsort (Fnreverse (list), Qstring_lessp);
}
@@ -151,8 +140,8 @@ Lisp_Object file_name_completion ();
DEFUN ("file-name-completion", Ffile_name_completion, Sfile_name_completion,
2, 2, 0,
"Complete file name FILE in directory DIR.\n\
-Returns the longest string\n\
-common to all filenames in DIR that start with FILE.\n\
+Returns the longest string common to all filenames in DIR\n\
+that start with FILE.\n\
If there is only one and FILE matches it exactly, returns t.\n\
Returns nil if DIR contains no name starting with FILE.")
(file, dirname)
@@ -170,8 +159,7 @@ Returns nil if DIR contains no name starting with FILE.")
DEFUN ("file-name-all-completions", Ffile_name_all_completions,
Sfile_name_all_completions, 2, 2, 0,
- "Return a list of all completions of file name FILE in directory DIR.\n\
-These are all file names in directory DIR which begin with FILE.")
+ "Return a list of all completions of file name FILE in directory DIR.")
(file, dirname)
Lisp_Object file, dirname;
{
@@ -197,7 +185,6 @@ file_name_completion (file, dirname, all_flag, ver_flag)
int all_flag, ver_flag;
{
DIR *d;
- DIRENTRY *dp;
int bestmatchsize, skip;
register int compare, matchsize;
unsigned char *p1, *p2;
@@ -219,21 +206,17 @@ file_name_completion (file, dirname, all_flag, ver_flag)
if (ver_flag)
readfunc = readdirver;
file = Fupcase (file);
-#else /* not VMS */
+#endif /* VMS */
+
CHECK_STRING (file, 0);
-#endif /* not VMS */
dirname = Fexpand_file_name (dirname, Qnil);
bestmatch = Qnil;
- /* With passcount = 0, ignore files that end in an ignored extension.
+ /* passcount = 0, ignore files that end in an ignored extension.
If nothing found then try again with passcount = 1, don't ignore them.
If looking for all completions, start with passcount = 1,
- so always take even the ignored ones.
-
- ** It would not actually be helpful to the user to ignore any possible
- completions when making a list of them.** */
-
+ so always take even the ignored ones. */
for (passcount = !!all_flag; NULL (bestmatch) && passcount < 2; passcount++)
{
if (!(d = opendir (XSTRING (Fdirectory_file_name (dirname))->data)))
@@ -326,6 +309,32 @@ file_name_completion (file, dirname, all_flag, ver_flag)
matchsize = scmp(p1, p2, compare);
if (matchsize < 0)
matchsize = compare;
+ if (completion_ignore_case)
+ {
+ /* If this is an exact match except for case,
+ use it as the best match rather than one that is not
+ an exact match. This way, we get the case pattern
+ of the actual match. */
+ if ((matchsize == len
+ && matchsize < XSTRING (bestmatch)->size)
+ ||
+ /* If there is no exact match ignoring case,
+ prefer a match that does not change the case
+ of the input. */
+ (((matchsize == len)
+ ==
+ (matchsize == XSTRING (bestmatch)->size))
+ /* If there is more than one exact match aside from
+ case, and one of them is exact including case,
+ prefer that one. */
+ && !bcmp (p2, XSTRING (file)->data, XSTRING (file)->size)
+ && bcmp (p1, XSTRING (file)->data, XSTRING (file)->size)))
+ {
+ bestmatch = make_string (dp->d_name, len);
+ if (directoryp)
+ bestmatch = Ffile_name_as_directory (bestmatch);
+ }
+ }
/* If this dirname all matches,
see if implicit following slash does too. */
if (directoryp
@@ -333,18 +342,30 @@ file_name_completion (file, dirname, all_flag, ver_flag)
&& bestmatchsize > matchsize
&& p1[matchsize] == '/')
matchsize++;
- bestmatchsize = min (matchsize, bestmatchsize);
+ bestmatchsize = matchsize;
}
}
}
closedir (d);
}
- unbind_to (count, Qnil);
+ unbind_to (count);
if (all_flag || NULL (bestmatch))
return bestmatch;
- if (matchcount == 1 && bestmatchsize == XSTRING (file)->size)
+
+ /* If we are ignoring case, and there is no exact match,
+ and no additional text was supplied,
+ don't change the case of what the user typed. */
+ if (completion_ignore_case && bestmatchsize == XSTRING (file)->size
+ && XSTRING (bestmatch)->size > bestmatchsize)
+ return file;
+
+ /* Return t if the supplied string is an exact match (counting case);
+ it does not require any change to be made. */
+ if (matchcount == 1 && bestmatchsize == XSTRING (file)->size
+ && !bcmp (XSTRING (bestmatch)->data, XSTRING (file)->data,
+ bestmatchsize))
return Qt;
return Fsubstring (bestmatch, make_number (0), make_number (bestmatchsize));
quit:
@@ -371,7 +392,17 @@ file_name_completion_stat (dirname, dp, st_addr)
bcopy (dp->d_name, fullname + pos, len);
fullname[pos + len] = 0;
+#ifdef S_IFLNK
+ /* Use ordinary stat first, if that succeeds,
+ so that a symlink pointing to a directory is considered a directory.
+ Afterward, use lstat, so that a link pointing to nowhere
+ at least seems to exist. */
+ if (stat (fullname, st_addr) >= 0)
+ return 0;
+ return lstat (fullname, st_addr);
+#else
return stat (fullname, st_addr);
+#endif
}
Lisp_Object
@@ -398,13 +429,12 @@ Otherwise, list elements are:\n\
8. File modes, as a string of ten letters or dashes as in ls -l.\n\
9. t iff file's gid would change if file were deleted and recreated.\n\
10. inode number.\n\
-11. Device number.\n\
\n\
If file does not exists, returns nil.")
(filename)
Lisp_Object filename;
{
- Lisp_Object values[12];
+ Lisp_Object values[11];
Lisp_Object dirname;
struct stat s;
struct stat sdir;
@@ -451,8 +481,7 @@ If file does not exists, returns nil.")
#undef BSD4_2 /* ok, you can look again without throwing up */
#endif
values[10] = make_number (s.st_ino);
- values[11] = make_number (s.st_dev);
- return Flist (sizeof(values) / sizeof(values[0]), values);
+ return Flist (11, values);
}
syms_of_dired ()
@@ -471,8 +500,6 @@ syms_of_dired ()
#endif /* VMS */
DEFVAR_LISP ("completion-ignored-extensions", &Vcompletion_ignored_extensions,
- "*Completion ignores filenames ending in any string in this list.\n\
-This variable does not affect lists of possible completions,\n\
-but does affect the commands that actually do completions.");
+ "*Completion ignores filenames ending in any string in this list.");
Vcompletion_ignored_extensions = Qnil;
}
diff --git a/src/dispextern.h b/src/dispextern.h
new file mode 100644
index 00000000000..d3dc8941072
--- /dev/null
+++ b/src/dispextern.h
@@ -0,0 +1,91 @@
+/* Interface definitions for display code.
+ Copyright (C) 1985, 1990 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* Nonzero means do not assume anything about current
+ contents of actual terminal screen */
+
+extern int screen_garbaged;
+
+/* Desired terminal cursor position (to show position of point),
+ origin zero. */
+
+extern int cursor_hpos, cursor_vpos;
+
+/* Nonzero means last display completed
+ and cursor is really at cursor_hpos, cursor_vpos.
+ Zero means it was preempted. */
+
+extern int display_completed;
+
+/* Nonzero while trying to read keyboard input at main program level. */
+
+extern int waiting_for_input;
+
+struct matrix
+{
+ /* Height of this matrix. */
+ int height;
+ /* Width of this matrix. */
+ int width;
+ /* Vector of used widths of lines, indexed by vertical position. */
+ int *used;
+ /* Vector of line contents.
+ m->contents[V][H] is the character at position V, H.
+ Note that ->contents[...][screen_width] is always 0
+ and so is ->contents[...][-1]. */
+ unsigned char **contents;
+ /* Long vector from which the line contents are taken. */
+ unsigned char *total_contents;
+ /* Vector indicating, for each line, whether it is highlighted. */
+ char *highlight;
+ /* Vector indicating, for each line, whether its contents mean anything. */
+ char *enable;
+};
+
+/* Current screen contents. */
+extern struct matrix *current_screen;
+/* Screen contents to be displayed. */
+extern struct matrix *new_screen;
+/* Temporary buffer for screen contents. */
+extern struct matrix *temp_screen;
+
+/* Get ready to display on screen line VPOS at column HPOS
+ and return the string where the text of that line is stored. */
+
+unsigned char *get_display_line ();
+
+/* Buffer used by `message' for formatting a message, and by print.c. */
+extern char *message_buf;
+
+/* Nonzero means message_buf is being used by print. */
+extern int message_buf_print;
+
+/* Message to display instead of minibuffer contents
+ This is what the functions error and message make,
+ and command echoing uses it as well.
+ It overrides the minibuf_prompt as well as the buffer. */
+extern char *echo_area_contents;
+
+/* All costs measured in characters.
+ So no cost can exceed the area of a screen, measured in characters.
+ This should not be more than million.
+ Meanwhile, we can add lots of millions together without overflow. */
+
+#define INFINITY 1000000
diff --git a/src/dispnew.c b/src/dispnew.c
new file mode 100644
index 00000000000..38cef720952
--- /dev/null
+++ b/src/dispnew.c
@@ -0,0 +1,1671 @@
+/* Newly written part of redisplay code.
+ Copyright (C) 1985, 1986, 1987, 1988, 1990 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* This must precede sys/signal.h on certain machines. */
+#include <sys/types.h>
+#include <signal.h>
+
+#include "config.h"
+#include <stdio.h>
+#include <errno.h>
+
+#ifdef HAVE_TIMEVAL
+#ifdef HPUX
+#include <time.h>
+#else
+#include <sys/time.h>
+#endif
+#endif
+
+#ifdef HAVE_TERMIO
+#include <termio.h>
+#ifdef TCOUTQ
+#undef TIOCOUTQ
+#define TIOCOUTQ TCOUTQ
+#include <fcntl.h>
+#endif /* TCOUTQ defined */
+#else
+#ifndef VMS
+#include <sys/ioctl.h>
+#endif /* not VMS */
+#endif /* not HAVE_TERMIO */
+
+/* Allow m- file to inhibit use of FIONREAD. */
+#ifdef BROKEN_FIONREAD
+#undef FIONREAD
+#endif
+
+/* We are unable to use interrupts if FIONREAD is not available,
+ so flush SIGIO so we won't try. */
+#ifndef FIONREAD
+#ifdef SIGIO
+#undef SIGIO
+#endif
+#endif
+
+#undef NULL
+
+#include "termchar.h"
+#include "termopts.h"
+#include "cm.h"
+#include "dispextern.h"
+#include "lisp.h"
+#include "buffer.h"
+#include "window.h"
+#include "commands.h"
+
+#define max(a, b) ((a) > (b) ? (a) : (b))
+#define min(a, b) ((a) < (b) ? (a) : (b))
+
+#ifndef PENDING_OUTPUT_COUNT
+/* Get number of chars of output now in the buffer of a stdio stream.
+ This ought to be built in in stdio, but it isn't.
+ Some s- files override this because their stdio internals differ. */
+#ifdef __GNU_LIBRARY__
+#define PENDING_OUTPUT_COUNT(FILE) ((FILE)->__bufp - (FILE)->__buffer)
+#else
+#define PENDING_OUTPUT_COUNT(FILE) ((FILE)->_ptr - (FILE)->_base)
+#endif
+#endif /* No PENDING_OUTPUT_COUNT */
+
+/* Nonzero means do not assume anything about current
+ contents of actual terminal screen */
+
+int screen_garbaged;
+
+/* Desired terminal cursor position (to show position of point),
+ origin zero */
+
+int cursor_hpos, cursor_vpos;
+
+/* Nonzero means last display completed and cursor is really at
+ cursor_hpos, cursor_vpos. Zero means it was preempted. */
+
+int display_completed;
+
+/* Lisp variable visible-bell; enables use of screen-flash
+ instead of audible bell. */
+
+int visible_bell;
+
+/* Invert the color of the whole screen, at a low level. */
+
+int inverse_video;
+
+/* Line speed of the terminal. */
+
+int baud_rate;
+
+/* nil or a symbol naming the window system
+ under which emacs is running
+ ('x is the only current possibility). */
+
+Lisp_Object Vwindow_system;
+
+/* Version number of window system, or nil if no window system. */
+
+Lisp_Object Vwindow_system_version;
+
+/* Nonzero means reading single-character input with prompt
+ so put cursor on minibuffer after the prompt. */
+
+int cursor_in_echo_area;
+
+/* Nonzero means finish redisplay regardless of available input.
+ This is used with X windows to avoid a weird timing-dependent bug. */
+
+int force_redisplay;
+
+/* Description of actual screen contents. */
+
+struct matrix *current_screen;
+
+/* Description of desired screen contents. */
+
+struct matrix *new_screen;
+
+/* Buffer sometimes used to hold partial screen contents. */
+
+struct matrix *temp_screen;
+
+/* Stdio stream being used for copy of all terminal output. */
+
+FILE *termscript;
+
+/* Structure for info on cursor positioning */
+
+struct cm Wcm;
+
+int delayed_size_change; /* 1 means SIGWINCH happened when not safe. */
+int delayed_screen_height; /* Remembered new screen height. */
+int delayed_screen_width; /* Remembered new screen width. */
+
+/* This buffer records the history of display preemption. */
+
+struct preempt
+{
+ /* Number of keyboard characters read so far at preempt. */
+ int keyboard_char_count;
+ /* Vertical position at which preemption occurred. */
+ int vpos;
+};
+
+#define N_PREEMPTIONS 50
+
+/* Circular buffer recording recent display preemptions. */
+struct preempt preemptions[N_PREEMPTIONS];
+
+/* Index of next element in preemptions. */
+int preemption_index;
+
+/* Set these variables in the debugger to force a display preemption. */
+int debug_preemption_vpos = -1;
+int debug_preemption_char_count = -1;
+
+extern int num_input_chars;
+
+/* Free and reallocate current_screen and new_screen. */
+
+struct matrix *make_screen_structure ();
+
+remake_screen_structures ()
+{
+ int i;
+
+ if (current_screen)
+ free_screen_structure (current_screen);
+ if (new_screen)
+ free_screen_structure (new_screen);
+ if (temp_screen)
+ free_screen_structure (temp_screen);
+
+ current_screen = make_screen_structure (0);
+ new_screen = make_screen_structure (0);
+ temp_screen = make_screen_structure (1);
+
+ if (message_buf)
+ {
+ /* The echo_area_contents, used by error and message, may be pointing at
+ the string we are replacing. If so, update it. */
+ int repair_echo_area_contents = echo_area_contents == message_buf;
+
+ message_buf = (char *) xrealloc (message_buf, screen_width + 1);
+
+ if (repair_echo_area_contents) echo_area_contents = message_buf;
+ }
+ else
+ message_buf = (char *) xmalloc (screen_width + 1);
+
+ /* This may fix a problem of occasionally displaying garbage in the echo area
+ after a resize in X Windows. */
+ for (i = 0; i < screen_width; i++)
+ message_buf[i] = ' ';
+ message_buf[screen_width] = 0;
+}
+
+struct matrix *
+make_screen_structure (empty)
+ int empty;
+{
+ int i;
+ struct matrix *new = (struct matrix *) xmalloc (sizeof (struct matrix));
+
+ new->height = screen_height;
+ new->width = screen_width;
+ new->highlight = (char *) xmalloc (screen_height);
+ new->enable = (char *) xmalloc (screen_height);
+ new->contents = (unsigned char **) xmalloc (screen_height * sizeof (char *));
+ new->used = (int *) xmalloc (screen_height * sizeof (int));
+ if (empty)
+ {
+ /* Make the buffer used by decode_mode_spec. */
+ new->total_contents = (unsigned char *) xmalloc (screen_width + 2);
+ for (i = 0; i < screen_width; i++)
+ new->total_contents[i] = ' ';
+ new->total_contents[screen_width] = 0;
+ }
+ else
+ {
+ /* Add 2 to leave extra bytes at beginning and end of each line. */
+ new->total_contents = (unsigned char *) xmalloc (screen_height * (screen_width + 2));
+ for (i = 0; i < screen_height; i++)
+ {
+ int j;
+
+ new->contents[i] = new->total_contents + i * (screen_width + 2) + 1;
+ new->contents[i][screen_width] = 0;
+ new->contents[i][-1] = 0;
+ for (j = 0; j < screen_width; j++)
+ new->contents[i][j] = ' ';
+ }
+ }
+ bzero (new->enable, screen_height);
+ return new;
+}
+
+free_screen_structure (matrix)
+ struct matrix *matrix;
+{
+ if (matrix->total_contents)
+ free (matrix->total_contents);
+ free (matrix->contents);
+ free (matrix->highlight);
+ free (matrix->enable);
+ free (matrix->used);
+ free (matrix);
+}
+
+/* Return the hash code of contents of line VPOS of screen-matrix M. */
+
+int
+line_hash_code (m, vpos)
+ struct matrix *m;
+ int vpos;
+{
+ register unsigned char *body;
+ register int h = 0;
+ /* Give all lighlighted lines the same hash code
+ so as to encourage scrolling to leave them in place. */
+ if (m->highlight[vpos])
+ return -1;
+
+ body = m->contents[vpos];
+
+ if (must_write_spaces)
+ {
+ while (1)
+ {
+ int c = *body++;
+ if (c == 0)
+ break;
+ h = (((h << 4) + (h >> 24)) & 0x0fffffff) + c - ' ';
+ }
+ }
+ else
+ {
+ while (1)
+ {
+ int c = *body++;
+ if (c == 0)
+ break;
+ h = (((h << 4) + (h >> 24)) & 0x0fffffff) + c;
+ }
+ }
+ if (h)
+ return h;
+ return 1;
+}
+
+/* Return number of characters in line in M at vpos VPOS,
+ except don't count leading and trailing spaces
+ unless the terminal requires those to be explicitly output. */
+
+int
+line_draw_cost (m, vpos)
+ struct matrix *m;
+ int vpos;
+{
+ register unsigned char *body;
+ register int i;
+
+ if (must_write_spaces)
+ return m->used[vpos];
+
+ body = m->contents[vpos];
+ for (i = m->used[vpos]; i > 0 && body[i - 2] == ' '; i--);
+
+ i -= count_blanks (body);
+ return max (i, 0);
+}
+
+/* The functions on this page are the interface from xdisp.c to redisplay.
+
+ The only other interface into redisplay is through setting
+ cursor_hpos and cursor_vpos (in xdisp.c) and setting screen_garbaged. */
+
+/* cancel_line eliminates any request to display a line at position `vpos' */
+
+cancel_line (vpos)
+ int vpos;
+{
+ new_screen->enable[vpos] = 0;
+}
+
+clear_screen_records ()
+{
+ int i;
+
+ bzero (current_screen->enable, screen_height);
+}
+
+/* Get ready to display on line `vpos'
+ and set it up for outputting starting at `hpos' within it.
+ Return the text string where that line is stored. */
+
+unsigned char *
+get_display_line (vpos, hpos)
+ int vpos;
+ register int hpos;
+{
+ if (new_screen->enable[vpos] && new_screen->used[vpos] > hpos)
+ abort ();
+ if (! new_screen->enable[vpos])
+ {
+ new_screen->used[vpos] = 0;
+ new_screen->highlight[vpos] = 0;
+ new_screen->enable[vpos] = 1;
+ }
+
+ if (hpos > new_screen->used[vpos])
+ {
+ unsigned char *p = new_screen->contents[vpos] + new_screen->used[vpos];
+ unsigned char *end = new_screen->contents[vpos] + hpos;
+ new_screen->used[vpos] = hpos;
+ while (p != end)
+ *p++ = ' ';
+ }
+
+ return new_screen->contents[vpos];
+}
+
+/* Scroll lines from vpos `from' up to but not including vpos `end'
+ down by `amount' lines (`amount' may be negative).
+ Returns nonzero if done, zero if terminal cannot scroll them. */
+
+int
+scroll_screen_lines (from, end, amount)
+ int from, end, amount;
+{
+ register int i;
+
+ if (!line_ins_del_ok)
+ return 0;
+
+ if (amount == 0)
+ return 1;
+ if (amount > 0)
+ {
+ set_terminal_window (end + amount);
+ if (!scroll_region_ok)
+ ins_del_lines (end, -amount);
+ ins_del_lines (from, amount);
+ set_terminal_window (0);
+
+ rotate_vector (current_screen->contents + from,
+ sizeof (char *) * (end + amount - from),
+ amount * sizeof (char *));
+ safe_bcopy (current_screen->used + from,
+ current_screen->used + from + amount,
+ (end - from) * sizeof current_screen->used[0]);
+ safe_bcopy (current_screen->highlight + from,
+ current_screen->highlight + from + amount,
+ (end - from) * sizeof current_screen->highlight[0]);
+ safe_bcopy (current_screen->enable + from,
+ current_screen->enable + from + amount,
+ (end - from) * sizeof current_screen->enable[0]);
+ /* Mark the lines made empty by scrolling as enabled, empty and
+ normal video. */
+ bzero (current_screen->used + from,
+ amount * sizeof current_screen->used[0]);
+ bzero (current_screen->highlight + from,
+ amount * sizeof current_screen->highlight[0]);
+ for (i = from; i < from + amount; i++)
+ {
+ current_screen->contents[i][0] = '\0';
+ current_screen->enable[i] = 1;
+ }
+ }
+ if (amount < 0)
+ {
+ set_terminal_window (end);
+ ins_del_lines (from + amount, amount);
+ if (!scroll_region_ok)
+ ins_del_lines (end + amount, -amount);
+ set_terminal_window (0);
+
+ rotate_vector (current_screen->contents + from + amount,
+ sizeof (char *) * (end - from - amount),
+ (end - from) * sizeof (char *));
+ safe_bcopy (current_screen->used + from,
+ current_screen->used + from + amount,
+ (end - from) * sizeof current_screen->used[0]);
+ safe_bcopy (current_screen->highlight + from,
+ current_screen->highlight + from + amount,
+ (end - from) * sizeof current_screen->highlight[0]);
+ safe_bcopy (current_screen->enable + from,
+ current_screen->enable + from + amount,
+ (end - from) * sizeof current_screen->enable[0]);
+ /* Mark the lines made empty by scrolling as enabled, empty and
+ normal video. */
+ bzero (current_screen->used + end + amount,
+ - amount * sizeof current_screen->used[0]);
+ bzero (current_screen->highlight + end + amount,
+ - amount * sizeof current_screen->highlight[0]);
+ for (i = end + amount; i < end; i++)
+ {
+ current_screen->contents[i][0] = '\0';
+ current_screen->enable[i] = 1;
+ }
+ }
+ return 1;
+}
+
+/* Rotate a vector of SIZE bytes, by DISTANCE bytes.
+ DISTANCE may be negative. */
+
+rotate_vector (vector, size, distance)
+ char *vector;
+ int size;
+ int distance;
+{
+ char *temp = (char *) alloca (size);
+
+ if (distance < 0)
+ distance += size;
+
+ bcopy (vector, temp + distance, size - distance);
+ bcopy (vector + size - distance, temp, distance);
+ bcopy (temp, vector, size);
+}
+
+/* Like bcopy except never gets confused by overlap. */
+
+safe_bcopy (from, to, size)
+ char *from, *to;
+ int size;
+{
+ register char *endf;
+ register char *endt;
+
+ if (size == 0)
+ return;
+ if (from > to)
+ {
+ /* If destination is lower in memory, we can go from the beginning. */
+ endf = from + size;
+ while (from != endf)
+ *to++ = *from++;
+ return;
+ }
+
+ /* If destination is higher in memory, we can go backwards from the end. */
+ endf = from + size;
+ endt = to + size;
+
+ do
+ *--endt = *--endf;
+ while (endf != from);
+}
+
+/* After updating a window w that isn't the full screen wide,
+ copy all the columns that w does not occupy
+ from current_screen to new_screen,
+ so that update_screen will not change those columns. */
+
+preserve_other_columns (w)
+ struct window *w;
+{
+ register int vpos;
+ int start = XFASTINT (w->left);
+ int end = XFASTINT (w->left) + XFASTINT (w->width);
+ int bot = XFASTINT (w->top) + XFASTINT (w->height);
+
+ for (vpos = XFASTINT (w->top); vpos < bot; vpos++)
+ {
+ if (current_screen->enable[vpos] && new_screen->enable[vpos])
+ {
+ if (start > 0)
+ {
+ int len;
+
+ bcopy (current_screen->contents[vpos],
+ new_screen->contents[vpos], start);
+ len = min (start, current_screen->used[vpos]);
+ if (new_screen->used[vpos] < len)
+ new_screen->used[vpos] = len;
+ }
+ if (current_screen->used[vpos] > end
+ && new_screen->used[vpos] < current_screen->used[vpos])
+ {
+ while (new_screen->used[vpos] < end)
+ new_screen->contents[vpos][new_screen->used[vpos]++] = ' ';
+ bcopy (current_screen->contents[vpos] + end,
+ new_screen->contents[vpos] + end,
+ current_screen->used[vpos] - end);
+ new_screen->used[vpos] = current_screen->used[vpos];
+ }
+ }
+ }
+}
+
+/* On discovering that the redisplay for a window was no good,
+ cancel the columns of that window,
+ so that when the window is displayed over again
+ get_display_line will not complain. */
+
+cancel_my_columns (w)
+ struct window *w;
+{
+ register int vpos;
+ register int start = XFASTINT (w->left);
+ register int bot = XFASTINT (w->top) + XFASTINT (w->height);
+
+ for (vpos = XFASTINT (w->top); vpos < bot; vpos++)
+ if (new_screen->enable[vpos] && new_screen->used[vpos] >= start)
+ new_screen->used[vpos] = start;
+}
+
+/* These functions try to perform directly and immediately on the screen
+ the necessary output for one change in the buffer.
+ They may return 0 meaning nothing was done if anything is difficult,
+ or 1 meaning the output was performed properly.
+ They assume that the screen was up to date before the buffer
+ change being displayed. THey make various other assumptions too;
+ see command_loop_1 where these are called. */
+
+int
+direct_output_for_insert (c)
+ int c;
+{
+#ifndef COMPILER_REGISTER_BUG
+ register
+#endif COMPILER_REGISTER_BUG
+ struct window *w = XWINDOW (selected_window);
+#ifndef COMPILER_REGISTER_BUG
+ register
+#endif COMPILER_REGISTER_BUG
+ int hpos = cursor_hpos;
+#ifndef COMPILER_REGISTER_BUG
+ register
+#endif COMPILER_REGISTER_BUG
+ int vpos = cursor_vpos;
+
+ /* Give up if about to continue line */
+ if (hpos - XFASTINT (w->left) + 1 + 1 >= XFASTINT (w->width)
+
+ /* Avoid losing if cursor is in invisible text off left margin */
+ || (XINT (w->hscroll) && hpos == XFASTINT (w->left))
+
+ /* Give up if cursor outside window (in minibuf, probably) */
+ || cursor_vpos < XFASTINT (w->top)
+ || cursor_vpos >= XFASTINT (w->top) + XFASTINT (w->height)
+
+ /* Give up if cursor not really at cursor_hpos, cursor_vpos */
+ || !display_completed
+
+ /* Give up if w is minibuffer and a message is being displayed there */
+ || (EQ (selected_window, minibuf_window) && echo_area_contents))
+ return 0;
+
+ current_screen->contents[vpos][hpos] = c;
+ unchanged_modified = MODIFF;
+ beg_unchanged = GPT - BEG;
+ XFASTINT (w->last_point) = point;
+ XFASTINT (w->last_point_x) = cursor_hpos;
+ XFASTINT (w->last_modified) = MODIFF;
+
+ reassert_line_highlight (0, cursor_vpos);
+ output_chars (&current_screen->contents[vpos][hpos], 1);
+ fflush (stdout);
+ ++cursor_hpos;
+ if (hpos == current_screen->used[vpos])
+ {
+ current_screen->used[vpos] = hpos + 1;
+ current_screen->contents[vpos][hpos + 1] = 0;
+ }
+ return 1;
+}
+
+int
+direct_output_forward_char (n)
+ int n;
+{
+ register struct window *w = XWINDOW (selected_window);
+
+ /* Avoid losing if cursor is in invisible text off left margin */
+ if (XINT (w->hscroll) && cursor_hpos == XFASTINT (w->left))
+ return 0;
+ /* Don't lose if we are in the truncated text at the end. */
+ if (cursor_hpos >= XFASTINT (w->left) + XFASTINT (w->width) - 1)
+ return 0;
+ /* Don't move past the window edges. */
+ if (cursor_hpos + n >= XFASTINT (w->left) + XFASTINT (w->width) - 1)
+ return 0;
+ if (cursor_hpos + n <= XFASTINT (w->left))
+ return 0;
+
+ cursor_hpos += n;
+ XFASTINT (w->last_point_x) = cursor_hpos;
+ XFASTINT (w->last_point) = point;
+ move_cursor (cursor_vpos, cursor_hpos);
+ fflush (stdout);
+ return 1;
+}
+
+/* Update the actual terminal screen based on the data in new_screen.
+ Value is nonzero if redisplay stopped due to pending input.
+ FORCE nonzero means do not stop for pending input. */
+
+update_screen (force, inhibit_hairy_id)
+ int force;
+ int inhibit_hairy_id;
+{
+ register struct display_line **p;
+ register struct display_line *l, *lnew;
+ register int i;
+ int pause;
+ int preempt_count = baud_rate / 2400 + 1;
+ extern input_pending;
+
+ if (screen_height == 0) abort (); /* Some bug zeros some core */
+
+ if (force_redisplay)
+ force = 1;
+
+ if (!force)
+ detect_input_pending ();
+ if (!force
+ && ((num_input_chars == debug_preemption_char_count
+ && debug_preemption_vpos == screen_height - 1)
+ || input_pending))
+ {
+ pause = screen_height;
+ goto do_pause;
+ }
+
+ update_begin ();
+
+ if (!line_ins_del_ok)
+ inhibit_hairy_id = 1;
+
+ /* Don't compute for i/d line if just want cursor motion. */
+ for (i = 0; i < screen_height; i++)
+ if (new_screen->enable)
+ break;
+
+ /* Try doing i/d line, if not yet inhibited. */
+ if (!inhibit_hairy_id && i < screen_height)
+ force |= scrolling ();
+
+ /* Update the individual lines as needed. Do bottom line first. */
+
+ if (new_screen->enable[screen_height - 1])
+ update_line (screen_height - 1);
+ for (i = 0; i < screen_height - 1 && (force || !input_pending); i++)
+ {
+ if (!force && num_input_chars == debug_preemption_char_count
+ && debug_preemption_vpos == i)
+ break;
+ if (new_screen->enable[i])
+ {
+ /* Flush out every so many lines.
+ Also flush out if likely to have more than 1k buffered
+ otherwise. I'm told that telnet connections get really
+ screwed by more than 1k output at once. */
+ int outq = PENDING_OUTPUT_COUNT (stdout);
+ if (outq > 900
+ || (outq > 20 && ((i - 1) % preempt_count == 0)))
+ {
+ fflush (stdout);
+ if (preempt_count == 1)
+ {
+#ifdef TIOCOUTQ
+ if (ioctl (0, TIOCOUTQ, &outq) < 0)
+ /* Probably not a tty. Ignore the error and reset
+ * the outq count. */
+ outq = PENDING_OUTPUT_COUNT (stdout);
+#endif
+ outq *= 10;
+ sleep (outq / baud_rate);
+ }
+ }
+ if ((i - 1) % preempt_count == 0 && !force)
+ detect_input_pending ();
+ /* Now update this line. */
+ update_line (i);
+ }
+ }
+ pause = (i < screen_height - 1) ? i + 1 : 0;
+
+ /* Now just clean up termcap drivers and set cursor, etc. */
+ if (!pause)
+ {
+ if (cursor_in_echo_area < 0)
+ move_cursor (screen_height - 1, 0);
+ else if (cursor_in_echo_area > 0
+ && !current_screen->enable[screen_height - 1])
+ move_cursor (screen_height - 1, 0);
+ else if (cursor_in_echo_area)
+ move_cursor (screen_height - 1,
+ min (screen_width - 1,
+ current_screen->used[screen_height - 1]));
+ else
+ move_cursor (cursor_vpos, max (min (cursor_hpos, screen_width - 1), 0));
+ }
+
+ update_end ();
+
+ if (termscript)
+ fflush (termscript);
+ fflush (stdout);
+
+ /* Here if output is preempted because input is detected. */
+ do_pause:
+
+ if (screen_height == 0) abort (); /* Some bug zeros some core */
+ display_completed = !pause;
+ if (pause)
+ {
+ preemptions[preemption_index].vpos = pause - 1;
+ preemptions[preemption_index].keyboard_char_count = num_input_chars;
+ preemption_index++;
+ if (preemption_index == N_PREEMPTIONS)
+ preemption_index = 0;
+ }
+
+ bzero (new_screen->enable, screen_height);
+ return pause;
+}
+
+/* Called when about to quit, to check for doing so
+ at an improper time. */
+
+void
+quit_error_check ()
+{
+ if (new_screen == 0)
+ return;
+ if (new_screen->enable[0])
+ abort ();
+ if (new_screen->enable[screen_height - 1])
+ abort ();
+}
+
+/* Decide what insert/delete line to do, and do it */
+
+scrolling ()
+{
+ int unchanged_at_top, unchanged_at_bottom;
+ int window_size;
+ int changed_lines;
+ int *old_hash = (int *) alloca (screen_height * sizeof (int));
+ int *new_hash = (int *) alloca (screen_height * sizeof (int));
+ int *draw_cost = (int *) alloca (screen_height * sizeof (int));
+ register int i;
+ int free_at_end_vpos = screen_height;
+
+ /* Compute hash codes of all the lines.
+ Also calculate number of changed lines,
+ number of unchanged lines at the beginning,
+ and number of unchanged lines at the end. */
+
+ changed_lines = 0;
+ unchanged_at_top = 0;
+ unchanged_at_bottom = screen_height;
+ for (i = 0; i < screen_height; i++)
+ {
+ /* Give up on this scrolling if some old lines are not enabled. */
+ if (!current_screen->enable[i])
+ return 0;
+ old_hash[i] = line_hash_code (current_screen, i);
+ if (!new_screen->enable[i])
+ new_hash[i] = old_hash[i];
+ else
+ new_hash[i] = line_hash_code (new_screen, i);
+ if (old_hash[i] != new_hash[i])
+ {
+ changed_lines++;
+ unchanged_at_bottom = screen_height - i - 1;
+ }
+ else if (i == unchanged_at_top)
+ unchanged_at_top++;
+ /* If line is not changing, its redraw cost is infinite,
+ since we can't redraw it. */
+ if (!new_screen->enable[i])
+ draw_cost[i] = INFINITY;
+ else
+ draw_cost[i] = line_draw_cost (new_screen, i);
+ }
+
+ /* If changed lines are few, don't allow preemption, don't scroll. */
+ if (changed_lines < baud_rate / 2400 || unchanged_at_bottom == screen_height)
+ return 1;
+
+ window_size = screen_height - unchanged_at_top - unchanged_at_bottom;
+
+ if (scroll_region_ok)
+ free_at_end_vpos -= unchanged_at_bottom;
+ else if (memory_below_screen)
+ free_at_end_vpos = -1;
+
+ /* If large window, fast terminal and few lines in common between
+ current_screen and new_screen, don't bother with i/d calc. */
+ if (window_size >= 18 && baud_rate > 2400
+ && (window_size >=
+ 10 * scrolling_max_lines_saved (unchanged_at_top,
+ screen_height - unchanged_at_bottom,
+ old_hash, new_hash, draw_cost)))
+ return 0;
+
+ scrolling_1 (window_size, unchanged_at_top, unchanged_at_bottom,
+ draw_cost + unchanged_at_top - 1,
+ old_hash + unchanged_at_top - 1,
+ new_hash + unchanged_at_top - 1,
+ free_at_end_vpos - unchanged_at_top);
+
+ return 0;
+}
+
+update_line (vpos)
+ int vpos;
+{
+ register unsigned char *obody, *nbody, *op1, *op2, *np1;
+ int tem;
+ int osp, nsp, begmatch, endmatch, olen, nlen;
+ int save;
+ unsigned char *temp;
+
+ /* Check for highlighting change. */
+ if (new_screen->highlight[vpos]
+ != (current_screen->enable[vpos] && current_screen->highlight[vpos]))
+ {
+ change_line_highlight (new_screen->highlight[vpos], vpos,
+ (current_screen->enable[vpos]
+ ? current_screen->used[vpos] : 0));
+ current_screen->enable[vpos] = 0;
+ }
+ else
+ reassert_line_highlight (new_screen->highlight[vpos], vpos);
+
+ /* ??? */
+ if (! current_screen->enable[vpos])
+ {
+ olen = 0;
+ }
+ else
+ {
+ obody = current_screen->contents[vpos];
+ olen = current_screen->used[vpos];
+
+ /* Check for bugs that clobber obody[-1].
+ Such bugs might well clobber more than that,
+ so we need to find them, not try to ignore them. */
+ if (obody[-1] != 0)
+ abort ();
+
+ if (! current_screen->highlight[vpos])
+ {
+ /* Note obody[-1] is always 0. */
+ if (!must_write_spaces)
+ while (obody[olen - 1] == ' ')
+ olen--;
+ }
+ else
+ {
+ /* For an inverse-video line, remember we gave it
+ spaces all the way to the screen edge
+ so that the reverse video extends all the way across. */
+ while (olen < screen_width - 1)
+ obody[olen++] = ' ';
+ }
+ }
+
+ /* One way or another, this will enable the line being updated. */
+ current_screen->enable[vpos] = 1;
+ current_screen->used[vpos] = new_screen->used[vpos];
+#if !defined (ALLIANT) || defined (ALLIANT_2800)
+ current_screen->highlight[vpos] = new_screen->highlight[vpos];
+#else
+ {
+ /* Work around for compiler bug in cc on FX/80 which causes
+ "dispnew.c", line 896: compiler error: no table entry for op OREG. */
+ char tmp;
+ tmp = new_screen->highlight[vpos];
+ current_screen->highlight[vpos] = tmp;
+ }
+#endif
+
+ if (!new_screen->enable[vpos])
+ {
+ nlen = 0;
+ goto just_erase;
+ }
+
+ nbody = new_screen->contents[vpos];
+ nlen = new_screen->used[vpos];
+
+ /* Pretend trailing spaces are not there at all,
+ unless for one reason or another we must write all spaces. */
+ /* We know that the previous character byte contains 0. */
+ if (! new_screen->highlight[vpos])
+ {
+ if (!must_write_spaces)
+ while (nlen > 0 && nbody[nlen - 1] == ' ')
+ nlen--;
+ if (nlen == 0)
+ goto just_erase;
+ }
+ else
+ {
+ /* For an inverse-video line, give it extra trailing spaces
+ all the way to the screen edge
+ so that the reverse video extends all the way across. */
+ while (nlen < screen_width - 1)
+ nbody[nlen++] = ' ';
+ }
+
+ /* If there's no i/d char, quickly do the best we can without it. */
+ if (!char_ins_del_ok)
+ {
+ int i,j;
+
+ for (i = 0; i < nlen; i++)
+ {
+ if (i >= olen || nbody[i] != obody[i])
+ {
+ /* We found a non-matching char. */
+ move_cursor (vpos, i);
+ for (j = 1; (i + j < nlen &&
+ (i + j >= olen || nbody[i+j] != obody[i+j]));
+ j++);
+ /* Output this run of non-matching chars. */
+ output_chars (nbody + i, j);
+ i += j - 1;
+ /* Now find the next non-match. */
+ }
+ }
+ /* Clear the rest of the line, or the non-clear part of it. */
+ if (olen > nlen)
+ {
+ move_cursor (vpos, nlen);
+ clear_end_of_line (olen);
+ }
+
+ /* Exchange contents between current_screen and new_screen. */
+ temp = new_screen->contents[vpos];
+ new_screen->contents[vpos] = current_screen->contents[vpos];
+ current_screen->contents[vpos] = temp;
+ return;
+ }
+
+ if (!olen)
+ {
+ nsp = (must_write_spaces || new_screen->highlight[vpos])
+ ? 0 : count_blanks (nbody);
+ if (nlen > nsp)
+ {
+ move_cursor (vpos, nsp);
+ output_chars (nbody + nsp, nlen - nsp);
+ }
+
+ /* Exchange contents between current_screen and new_screen. */
+ temp = new_screen->contents[vpos];
+ new_screen->contents[vpos] = current_screen->contents[vpos];
+ current_screen->contents[vpos] = temp;
+ return;
+ }
+
+ obody[olen] = 1;
+ save = nbody[nlen];
+ nbody[nlen] = 0;
+
+ /* Compute number of leading blanks in old and new contents. */
+ osp = count_blanks (obody);
+ if (!new_screen->highlight[vpos])
+ nsp = count_blanks (nbody);
+ else
+ nsp = 0;
+
+ /* Compute number of matching chars starting with first nonblank. */
+ begmatch = count_match (obody + osp, nbody + nsp);
+
+ /* Spaces in new match implicit space past the end of old. */
+ /* A bug causing this to be a no-op was fixed in 18.29. */
+ if (!must_write_spaces && osp + begmatch == olen)
+ {
+ np1 = nbody + nsp;
+ while (np1[begmatch] == ' ')
+ begmatch++;
+ }
+
+ /* Avoid doing insert/delete char
+ just cause number of leading spaces differs
+ when the following text does not match. */
+ if (begmatch == 0 && osp != nsp)
+ osp = nsp = min (osp, nsp);
+
+ /* Find matching characters at end of line */
+ op1 = obody + olen;
+ np1 = nbody + nlen;
+ op2 = op1 + begmatch - min (olen - osp, nlen - nsp);
+ while (op1 > op2 && op1[-1] == np1[-1])
+ {
+ op1--;
+ np1--;
+ }
+ endmatch = obody + olen - op1;
+
+ /* Put correct value back in nbody[nlen].
+ This is important because direct_output_for_insert
+ can write into the line at a later point. */
+ nbody[nlen] = save;
+ /* Likewise, make sure that the null after the usable space in obody
+ always remains a null. */
+ obody[olen] = 0;
+
+ /* tem gets the distance to insert or delete.
+ endmatch is how many characters we save by doing so.
+ Is it worth it? */
+
+ tem = (nlen - nsp) - (olen - osp);
+ if (endmatch && tem && endmatch <= DCICcost[tem])
+ endmatch = 0;
+
+ /* nsp - osp is the distance to insert or delete.
+ begmatch + endmatch is how much we save by doing so.
+ Is it worth it? */
+
+ if (begmatch + endmatch > 0 && nsp != osp
+ && begmatch + endmatch <= DCICcost[nsp - osp])
+ {
+ begmatch = 0;
+ endmatch = 0;
+ osp = nsp = min (osp, nsp);
+ }
+
+ /* Now go through the line, inserting, writing and deleting as appropriate. */
+
+ if (osp > nsp)
+ {
+ move_cursor (vpos, nsp);
+ delete_chars (osp - nsp);
+ }
+ else if (nsp > osp)
+ {
+ /* If going to delete chars later in line
+ and insert earlier in the line,
+ must delete first to avoid losing data in the insert */
+ if (endmatch && nlen < olen + nsp - osp)
+ {
+ move_cursor (vpos, nlen - endmatch + osp - nsp);
+ delete_chars (olen + nsp - osp - nlen);
+ olen = nlen - (nsp - osp);
+ }
+ move_cursor (vpos, osp);
+ insert_chars ((char *)0, nsp - osp);
+ }
+ olen += nsp - osp;
+
+ tem = nsp + begmatch + endmatch;
+ if (nlen != tem || olen != tem)
+ {
+ move_cursor (vpos, nsp + begmatch);
+ if (!endmatch || nlen == olen)
+ {
+ /* If new text being written reaches right margin,
+ there is no need to do clear-to-eol at the end.
+ (and it would not be safe, since cursor is not
+ going to be "at the margin" after the text is done) */
+ if (nlen == screen_width)
+ olen = 0;
+ output_chars (nbody + nsp + begmatch, nlen - tem);
+#ifdef obsolete
+/* the following code loses disastrously if tem == nlen.
+ Rather than trying to fix that case, I am trying the simpler
+ solution found above. */
+ /* If the text reaches to the right margin,
+ it will lose one way or another (depending on AutoWrap)
+ to clear to end of line after outputting all the text.
+ So pause with one character to go and clear the line then. */
+ if (nlen == screen_width && fast_clear_end_of_line && olen > nlen)
+ {
+ /* endmatch must be zero, and tem must equal nsp + begmatch */
+ output_chars (nbody + tem, nlen - tem - 1);
+ clear_end_of_line (olen);
+ olen = 0; /* Don't let it be cleared again later */
+ output_chars (nbody + nlen - 1, 1);
+ }
+ else
+ output_chars (nbody + nsp + begmatch, nlen - tem);
+#endif
+ }
+ else if (nlen > olen)
+ {
+ output_chars (nbody + nsp + begmatch, olen - tem);
+ insert_chars (nbody + nsp + begmatch + olen - tem, nlen - olen);
+ olen = nlen;
+ }
+ else if (olen > nlen)
+ {
+ output_chars (nbody + nsp + begmatch, nlen - tem);
+ delete_chars (olen - nlen);
+ olen = nlen;
+ }
+ }
+
+ just_erase:
+ /* If any unerased characters remain after the new line, erase them. */
+ if (olen > nlen)
+ {
+ move_cursor (vpos, nlen);
+ clear_end_of_line (olen);
+ }
+
+ /* Exchange contents between current_screen and new_screen. */
+ temp = new_screen->contents[vpos];
+ new_screen->contents[vpos] = current_screen->contents[vpos];
+ current_screen->contents[vpos] = temp;
+}
+
+count_blanks (str)
+ char *str;
+{
+ register char *p = str;
+ while (*str++ == ' ');
+ return str - p - 1;
+}
+
+count_match (str1, str2)
+ char *str1, *str2;
+{
+ register char *p1 = str1;
+ register char *p2 = str2;
+ while (*p1++ == *p2++);
+ return p1 - str1 - 1;
+}
+
+DEFUN ("open-termscript", Fopen_termscript, Sopen_termscript,
+ 1, 1, "FOpen termscript file: ",
+ "Start writing all terminal output to FILE as well as the terminal.\n\
+FILE = nil means just close any termscript file currently open.")
+ (file)
+ Lisp_Object file;
+{
+ if (termscript != 0) fclose (termscript);
+ termscript = 0;
+
+ if (! NULL (file))
+ {
+ file = Fexpand_file_name (file, Qnil);
+ termscript = fopen (XSTRING (file)->data, "w");
+ if (termscript == 0)
+ report_file_error ("Opening termscript", Fcons (file, Qnil));
+ }
+ return Qnil;
+}
+
+DEFUN ("set-screen-height", Fset_screen_height, Sset_screen_height, 1, 2, 0,
+ "Tell redisplay that the screen has LINES lines.\n\
+Optional second arg non-nil means that redisplay should use LINES lines\n\
+but that the idea of the actual height of the screen should not be changed.")
+ (n, pretend)
+ Lisp_Object n, pretend;
+{
+ CHECK_NUMBER (n, 0);
+ change_screen_size (XINT (n), 0, !NULL (pretend), 0, 0);
+ return Qnil;
+}
+
+DEFUN ("set-screen-width", Fset_screen_width, Sset_screen_width, 1, 2, 0,
+ "Tell redisplay that the screen has COLS columns.\n\
+Optional second arg non-nil means that redisplay should use COLS columns\n\
+but that the idea of the actual width of the screen should not be changed.")
+ (n, pretend)
+ Lisp_Object n, pretend;
+{
+ CHECK_NUMBER (n, 0);
+ change_screen_size (0, XINT (n), !NULL (pretend), 0, 0);
+ return Qnil;
+}
+
+DEFUN ("screen-height", Fscreen_height, Sscreen_height, 0, 0, 0,
+ "Return number of lines on screen available for display.")
+ ()
+{
+ return make_number (screen_height);
+}
+
+DEFUN ("screen-width", Fscreen_width, Sscreen_width, 0, 0, 0,
+ "Return number of columns on screen available for display.")
+ ()
+{
+ return make_number (screen_width);
+}
+
+#ifdef SIGWINCH
+window_change_signal ()
+{
+ int width, height;
+ extern int errno;
+ int old_errno = errno;
+
+ get_screen_size (&width, &height);
+ /* Record the new size, but don't reallocate the data structures now.
+ Let that be done later outside of the signal handler. */
+ change_screen_size (height, width, 0, 1, 0);
+ signal (SIGWINCH, window_change_signal);
+
+ errno = old_errno;
+}
+#endif /* SIGWINCH */
+
+/* Do any change in screen size that was requested by a signal. */
+
+do_pending_window_change ()
+{
+ /* If change_screen_size should have run before, run it now. */
+ while (delayed_size_change)
+ {
+ int newwidth = delayed_screen_width;
+ int newheight = delayed_screen_height;
+ delayed_size_change = 0;
+ change_screen_size_1 (newheight, newwidth, 0, 0);
+ }
+}
+
+/* Change the screen height and/or width. Values may be given as zero to
+ indicate no change is to take place.
+
+ PRETEND is normally 0; 1 means change used-size only but don't
+ change the size used for calculations; -1 means don't redisplay.
+
+ If DELAYED, don't change the screen size now; just record the new
+ size and do the actual change at a more convenient time. The
+ SIGWINCH handler and the X Windows ConfigureNotify code use this,
+ because they can both be called at inconvenient times.
+
+ FORCE means finish redisplay now regardless of pending input.
+ This is effective only is DELAYED is not set. */
+
+change_screen_size (newlength, newwidth, pretend, delayed, force)
+ register int newlength, newwidth, pretend, delayed, force;
+{
+ /* Don't queue a size change if we won't really do anything. */
+ if ((newlength == 0 || newlength == screen_height)
+ && (newwidth == 0 || newwidth == screen_width))
+ return;
+ /* If we can't deal with the change now, queue it for later. */
+ if (delayed)
+ {
+ delayed_screen_width = newwidth;
+ delayed_screen_height = newlength;
+ delayed_size_change = 1;
+ }
+ else
+ {
+ delayed_size_change = 0;
+ change_screen_size_1 (newlength, newwidth, pretend, force);
+ }
+}
+
+change_screen_size_1 (newlength, newwidth, pretend, force)
+ register int newlength, newwidth, pretend, force;
+{
+ if ((newlength == 0 || newlength == screen_height)
+ && (newwidth == 0 || newwidth == screen_width))
+ return;
+ if (newlength && newlength != screen_height)
+ {
+ set_window_height (XWINDOW (minibuf_window)->prev, newlength - 1, 0);
+ XFASTINT (XWINDOW (minibuf_window)->top) = newlength - 1;
+ set_window_height (minibuf_window, 1, 0);
+ screen_height = newlength;
+ if (pretend <= 0)
+ ScreenRows = newlength;
+ set_terminal_window (0);
+ }
+ if (newwidth && newwidth != screen_width)
+ {
+ set_window_width (XWINDOW (minibuf_window)->prev, newwidth, 0);
+ set_window_width (minibuf_window, newwidth, 0);
+ screen_width = newwidth;
+ if (pretend <= 0)
+ ScreenCols = newwidth;
+ }
+ remake_screen_structures ();
+ screen_garbaged = 1;
+ calculate_costs ();
+ force_redisplay += force;
+ if (pretend >= 0)
+ redisplay_preserve_echo_area ();
+ force_redisplay -= force;
+}
+
+DEFUN ("baud-rate", Fbaud_rate, Sbaud_rate, 0, 0, 0,
+ "Return the output baud rate of the terminal.")
+ ()
+{
+ Lisp_Object temp;
+ XSET (temp, Lisp_Int, baud_rate);
+ return temp;
+}
+
+DEFUN ("send-string-to-terminal", Fsend_string_to_terminal,
+ Ssend_string_to_terminal, 1, 1, 0,
+ "Send STRING to the terminal without alteration.\n\
+Control characters in STRING will have terminal-dependent effects.")
+ (str)
+ Lisp_Object str;
+{
+ CHECK_STRING (str, 0);
+ fwrite (XSTRING (str)->data, 1, XSTRING (str)->size, stdout);
+ fflush (stdout);
+ if (termscript)
+ {
+ fwrite (XSTRING (str)->data, 1, XSTRING (str)->size, termscript);
+ fflush (termscript);
+ }
+ return Qnil;
+}
+
+DEFUN ("ding", Fding, Sding, 0, 1, 0,
+ "Beep, or flash the screen.\n\
+Terminates any keyboard macro currently executing unless an argument\n\
+is given.")
+ (arg)
+ Lisp_Object arg;
+{
+ if (!NULL (arg))
+ {
+ if (noninteractive)
+ putchar (07);
+ else
+ ring_bell ();
+ fflush (stdout);
+ }
+ else
+ bell ();
+ return Qnil;
+}
+
+bell ()
+{
+ if (noninteractive)
+ putchar (07);
+ else if (!FROM_KBD) /* Stop executing a keyboard macro. */
+ error ("Keyboard macro terminated by a command ringing the bell");
+ else
+ ring_bell ();
+ fflush (stdout);
+}
+
+DEFUN ("sleep-for", Fsleep_for, Ssleep_for, 1, 1, 0,
+ "Pause, without updating display, for ARG seconds.")
+ (n)
+ Lisp_Object n;
+{
+ register int t;
+#ifndef subprocesses
+#ifdef HAVE_TIMEVAL
+ struct timeval timeout, end_time, garbage1;
+#endif /* HAVE_TIMEVAL */
+#endif /* no subprocesses */
+
+ CHECK_NUMBER (n, 0);
+ t = XINT (n);
+ if (t <= 0)
+ return Qnil;
+
+#ifdef subprocesses
+ wait_reading_process_input (t, 0, 0);
+#else /* No subprocesses */
+ immediate_quit = 1;
+ QUIT;
+
+#ifdef VMS
+ sys_sleep (t);
+#else /* not VMS */
+/* The reason this is done this way
+ (rather than defined (H_S) && defined (H_T))
+ is because the VMS preprocessor doesn't grok `defined' */
+#ifdef HAVE_SELECT
+#ifdef HAVE_TIMEVAL
+ gettimeofday (&end_time, &garbage1);
+ end_time.tv_sec += t;
+
+ while (1)
+ {
+ gettimeofday (&timeout, &garbage1);
+
+ /* In effect, timeout = end_time - timeout.
+ Break if result would be negative. */
+ if (timeval_subtract (&timeout, end_time, timeout))
+ break;
+
+ if (!select (1, 0, 0, 0, &timeout))
+ break;
+ }
+#else /* not HAVE_TIMEVAL */
+ /* Is it safe to quit out of `sleep'? I'm afraid to trust it. */
+ sleep (t);
+#endif /* HAVE_TIMEVAL */
+#else /* not HAVE_SELECT */
+ sleep (t);
+#endif /* HAVE_SELECT */
+#endif /* not VMS */
+
+ immediate_quit = 0;
+#endif /* no subprocesses */
+ return Qnil;
+}
+
+#ifdef HAVE_TIMEVAL
+
+/* Subtract the `struct timeval' values X and Y,
+ storing the result in RESULT.
+ Return 1 if the difference is negative, otherwise 0. */
+
+int
+timeval_subtract (result, x, y)
+ struct timeval *result, x, y;
+{
+ /* Perform the carry for the later subtraction by updating y.
+ This is safer because on some systems
+ the tv_sec member is unsigned. */
+ if (x.tv_usec < y.tv_usec)
+ {
+ int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
+ y.tv_usec -= 1000000 * nsec;
+ y.tv_sec += nsec;
+ }
+ if (x.tv_usec - y.tv_usec > 1000000)
+ {
+ int nsec = (y.tv_usec - x.tv_usec) / 1000000;
+ y.tv_usec += 1000000 * nsec;
+ y.tv_sec -= nsec;
+ }
+
+ /* Compute the time remaining to wait. tv_usec is certainly positive. */
+ result->tv_sec = x.tv_sec - y.tv_sec;
+ result->tv_usec = x.tv_usec - y.tv_usec;
+
+ /* Return indication of whether the result should be considered negative. */
+ return x.tv_sec < y.tv_sec;
+}
+#endif /* HAVE_TIMEVAL */
+
+DEFUN ("sit-for", Fsit_for, Ssit_for, 1, 2, 0,
+ "Perform redisplay, then wait for ARG seconds or until input is available.\n\
+Optional second arg non-nil means don't redisplay.\n\
+Redisplay is preempted as always if input arrives, and does not happen\n\
+if input is available before it starts.\n\
+Value is t if waited the full time with no input arriving.")
+ (n, nodisp)
+ Lisp_Object n, nodisp;
+{
+#ifndef subprocesses
+#ifdef HAVE_TIMEVAL
+ struct timeval timeout;
+#else
+ int timeout_sec;
+#endif
+ int waitchannels;
+#endif /* no subprocesses */
+
+ CHECK_NUMBER (n, 0);
+
+ if (detect_input_pending ())
+ return Qnil;
+
+ if (EQ (nodisp, Qnil))
+ redisplay_preserve_echo_area ();
+ if (XINT (n) > 0)
+ {
+#ifdef subprocesses
+#ifdef SIGIO
+ gobble_input ();
+#endif /* SIGIO */
+ wait_reading_process_input (XINT (n), 1, 1);
+#else /* not subprocesses */
+ immediate_quit = 1;
+ QUIT;
+
+ waitchannels = 1;
+#ifdef VMS
+ input_wait_timeout (XINT (n));
+#else /* not VMS */
+#ifndef HAVE_TIMEVAL
+ timeout_sec = XINT (n);
+ select (1, &waitchannels, 0, 0, &timeout_sec);
+#else /* HAVE_TIMEVAL */
+ timeout.tv_sec = XINT (n);
+ timeout.tv_usec = 0;
+ select (1, &waitchannels, 0, 0, &timeout);
+#endif /* HAVE_TIMEVAL */
+#endif /* not VMS */
+
+ immediate_quit = 0;
+#endif /* not subprocesses */
+ }
+ return detect_input_pending () ? Qnil : Qt;
+}
+
+char *terminal_type;
+
+/* Initialization done when Emacs fork is started, before doing stty. */
+/* Determine terminal type and set terminal_driver */
+/* Then invoke its decoding routine to set up variables
+ in the terminal package */
+
+init_display ()
+{
+#ifdef HAVE_X_WINDOWS
+ extern Lisp_Object Vxterm;
+ Vxterm = Qnil;
+#endif
+
+ Vwindow_system = Qnil;
+ meta_key = 0;
+ inverse_video = 0;
+ cursor_in_echo_area = 0;
+ terminal_type = (char *) 0;
+
+ if (!inhibit_window_system)
+ {
+#ifdef HAVE_X_WINDOWS
+ extern char *alternate_display;
+ char *disp = (char *) egetenv ("DISPLAY");
+
+ /* Note KSH likes to provide an empty string as an envvar value. */
+ if (alternate_display || (disp && *disp))
+ {
+ x_term_init ();
+ Vxterm = Qt;
+ Vwindow_system = intern ("x");
+#ifdef X11
+ Vwindow_system_version = make_number (11);
+#else
+ Vwindow_system_version = make_number (10);
+#endif
+ goto term_init_done;
+ }
+#endif /* HAVE_X_WINDOWS */
+ ;
+ }
+ /* Record we aren't using a window system. */
+ inhibit_window_system = 1;
+
+ /* Look at the TERM variable */
+ terminal_type = (char *) getenv ("TERM");
+ if (!terminal_type)
+ {
+#ifdef VMS
+ fprintf (stderr, "Please specify your terminal type.\n\
+For types defined in VMS, use set term /device=TYPE.\n\
+For types not defined in VMS, use define emacs_term \"TYPE\".\n\
+\(The quotation marks are necessary since terminal types are lower case.)\n");
+#else
+ fprintf (stderr, "Please set the environment variable TERM; see tset(1).\n");
+#endif
+ exit (1);
+ }
+ term_init (terminal_type);
+
+ term_init_done:
+ remake_screen_structures ();
+ calculate_costs ();
+
+#ifdef SIGWINCH
+#ifndef CANNOT_DUMP
+ if (initialized)
+#endif /* CANNOT_DUMP */
+ if (inhibit_window_system)
+ signal (SIGWINCH, window_change_signal);
+#endif /* SIGWINCH */
+}
+
+syms_of_display ()
+{
+ defsubr (&Sopen_termscript);
+ defsubr (&Sding);
+ defsubr (&Ssit_for);
+ defsubr (&Sscreen_height);
+ defsubr (&Sscreen_width);
+ defsubr (&Sset_screen_height);
+ defsubr (&Sset_screen_width);
+ defsubr (&Ssleep_for);
+ defsubr (&Sbaud_rate);
+ defsubr (&Ssend_string_to_terminal);
+
+ DEFVAR_BOOL ("inverse-video", &inverse_video,
+ "*Non-nil means use inverse-video.");
+ DEFVAR_BOOL ("visible-bell", &visible_bell,
+ "*Non-nil means try to flash the screen to represent a bell.\n\
+Note: for X windows, you must use x-set-bell instead.");
+ DEFVAR_BOOL ("no-redraw-on-reenter", &no_redraw_on_reenter,
+ "*Non-nil means no need to redraw entire screen after suspending.\n\
+It is up to you to set this variable to inform Emacs.");
+ DEFVAR_LISP ("window-system", &Vwindow_system,
+ "A symbol naming the window-system under which Emacs is running,\n\
+\(such as `x'), or nil if emacs is running on an ordinary terminal.");
+ DEFVAR_LISP ("window-system-version", &Vwindow_system_version,
+ "Version number of the window system Emacs is running under.");
+ DEFVAR_BOOL ("cursor-in-echo-area", &cursor_in_echo_area,
+ "Non-nil means put cursor in minibuffer after any message displayed there.");
+
+ /* Initialize `window-system', unless init_display already decided it. */
+#ifdef CANNOT_DUMP
+ if (noninteractive)
+#endif
+ {
+ Vwindow_system_version = Qnil;
+ Vwindow_system = Qnil;
+ }
+}
diff --git a/src/doc.c b/src/doc.c
new file mode 100644
index 00000000000..4bba1fc81a1
--- /dev/null
+++ b/src/doc.c
@@ -0,0 +1,434 @@
+/* Record indices of function doc strings stored in a file.
+ Copyright (C) 1985, 1986 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#include "config.h"
+#include "lisp.h"
+#include "buffer.h"
+
+#include <sys/types.h>
+#include <sys/file.h> /* Must be after sys/types.h for USG and BSD4_1*/
+
+#ifdef USG5
+#include <fcntl.h>
+#endif
+
+#ifndef O_RDONLY
+#define O_RDONLY 0
+#endif
+
+Lisp_Object Vdoc_file_name;
+
+Lisp_Object
+get_doc_string (filepos)
+ long filepos;
+{
+ char buf[512 * 32 + 1];
+ register int fd;
+ register char *name;
+ register char *p, *p1;
+ register int count;
+ extern char *index ();
+
+ if (XTYPE (Vexec_directory) != Lisp_String
+ || XTYPE (Vdoc_file_name) != Lisp_String)
+ return Qnil;
+
+ name = (char *) alloca (XSTRING (Vexec_directory)->size
+ + XSTRING (Vdoc_file_name)->size + 8);
+ strcpy (name, XSTRING (Vexec_directory)->data);
+ strcat (name, XSTRING (Vdoc_file_name)->data);
+#ifdef VMS
+#ifndef VMS4_4
+ /* For VMS versions with limited file name syntax,
+ convert the name to something VMS will allow. */
+ p = name;
+ while (*p)
+ {
+ if (*p == '-')
+ *p = '_';
+ p++;
+ }
+#endif /* not VMS4_4 */
+#ifdef VMS4_4
+ strcpy (name, sys_translate_unix (name));
+#endif /* VMS4_4 */
+#endif /* VMS */
+
+ fd = open (name, O_RDONLY, 0);
+ if (fd < 0)
+ error ("Cannot open doc string file \"%s\"", name);
+ if (0 > lseek (fd, filepos, 0))
+ {
+ close (fd);
+ error ("Position %ld out of range in doc string file \"%s\"",
+ filepos, name);
+ }
+ p = buf;
+ while (p != buf + sizeof buf - 1)
+ {
+ count = read (fd, p, 512);
+ p[count] = 0;
+ if (!count)
+ break;
+ p1 = index (p, '\037');
+ if (p1)
+ {
+ *p1 = 0;
+ p = p1;
+ break;
+ }
+ p += count;
+ }
+ close (fd);
+ return make_string (buf, p - buf);
+}
+
+DEFUN ("documentation", Fdocumentation, Sdocumentation, 1, 1, 0,
+ "Return the documentation string of FUNCTION.")
+ (fun1)
+ Lisp_Object fun1;
+{
+ Lisp_Object fun;
+ Lisp_Object funcar;
+ Lisp_Object tem;
+
+ fun = fun1;
+ while (XTYPE (fun) == Lisp_Symbol)
+ fun = Fsymbol_function (fun);
+ if (XTYPE (fun) == Lisp_Subr)
+ {
+ if (XSUBR (fun)->doc == 0) return Qnil;
+ if ((int) XSUBR (fun)->doc >= 0)
+ return Fsubstitute_command_keys (build_string (XSUBR (fun)->doc));
+ return Fsubstitute_command_keys (get_doc_string (- (int) XSUBR (fun)->doc));
+ }
+ if (XTYPE (fun) == Lisp_Vector)
+ return build_string ("Prefix command (definition is a Lisp vector of subcommands).");
+ if (XTYPE (fun) == Lisp_String)
+ return build_string ("Keyboard macro.");
+ if (!CONSP (fun))
+ return Fsignal (Qinvalid_function, Fcons (fun, Qnil));
+ funcar = Fcar (fun);
+ if (XTYPE (funcar) != Lisp_Symbol)
+ return Fsignal (Qinvalid_function, Fcons (fun, Qnil));
+ if (XSYMBOL (funcar) == XSYMBOL (Qkeymap))
+ return build_string ("Prefix command (definition is a list whose cdr is an alist of subcommands.)");
+ if (XSYMBOL (funcar) == XSYMBOL (Qlambda)
+ || XSYMBOL (funcar) == XSYMBOL (Qautoload))
+ {
+ tem = Fcar (Fcdr (Fcdr (fun)));
+ if (XTYPE (tem) == Lisp_String)
+ return Fsubstitute_command_keys (tem);
+ if (XTYPE (tem) == Lisp_Int && XINT (tem) >= 0)
+ return Fsubstitute_command_keys (get_doc_string (XFASTINT (tem)));
+ return Qnil;
+ }
+ if (XSYMBOL (funcar) == XSYMBOL (Qmocklisp))
+ return Qnil;
+ if (XSYMBOL (funcar) == XSYMBOL (Qmacro))
+ return Fdocumentation (Fcdr (fun));
+ else
+ return Fsignal (Qinvalid_function, Fcons (fun, Qnil));
+}
+
+DEFUN ("documentation-property", Fdocumentation_property,
+ Sdocumentation_property, 2, 2, 0,
+ "Return the documentation string that is SYMBOL's PROP property.\n\
+This differs from using `get' only in that it can refer to strings\n\
+stored in the etc/DOC file.")
+ (sym, prop)
+ Lisp_Object sym, prop;
+{
+ register Lisp_Object tem;
+
+ tem = Fget (sym, prop);
+ if (XTYPE (tem) == Lisp_Int)
+ tem = get_doc_string (XINT (tem) > 0 ? XINT (tem) : - XINT (tem));
+ return Fsubstitute_command_keys (tem);
+}
+
+DEFUN ("Snarf-documentation", Fsnarf_documentation, Ssnarf_documentation,
+ 1, 1, 0,
+ "Used during Emacs initialization, before dumping runnable Emacs,\n\
+to find pointers to doc strings stored in etc/DOC... and\n\
+record them in function definitions.\n\
+One arg, FILENAME, a string which does not include a directory.\n\
+The file is found in ../etc now; found in the exec-directory\n\
+when doc strings are referred to later in the dumped Emacs.")
+ (filename)
+ Lisp_Object filename;
+{
+ int fd;
+ char buf[1024 + 1];
+ register int filled;
+ register int pos;
+ register char *p, *end;
+ Lisp_Object sym, fun, tem;
+ char *name;
+ extern char *index ();
+
+ CHECK_STRING (filename, 0);
+
+#ifndef CANNOT_DUMP
+ name = (char *) alloca (XSTRING (filename)->size + 8);
+ strcpy (name, "../etc/");
+#else /* CANNOT_DUMP */
+ CHECK_STRING (Vexec_directory, 0);
+ name = (char *) alloca (XSTRING (filename)->size +
+ XSTRING (Vexec_directory)->size + 1);
+ strcpy (name, XSTRING (Vexec_directory)->data);
+#endif /* CANNOT_DUMP */
+ strcat (name, XSTRING (filename)->data); /*** Add this line ***/
+#ifdef VMS
+#ifndef VMS4_4
+ /* For VMS versions with limited file name syntax,
+ convert the name to something VMS will allow. */
+ p = name;
+ while (*p)
+ {
+ if (*p == '-')
+ *p = '_';
+ p++;
+ }
+#endif /* not VMS4_4 */
+#ifdef VMS4_4
+ strcpy (name, sys_translate_unix (name));
+#endif /* VMS4_4 */
+#endif /* VMS */
+
+ fd = open (name, O_RDONLY, 0);
+ if (fd < 0)
+ report_file_error ("Opening doc string file",
+ Fcons (build_string (name), Qnil));
+ Vdoc_file_name = filename;
+ filled = 0;
+ pos = 0;
+ while (1)
+ {
+ if (filled < 512)
+ filled += read (fd, &buf[filled], sizeof buf - 1 - filled);
+ if (!filled)
+ break;
+
+ buf[filled] = 0;
+ p = buf;
+ end = buf + (filled < 512 ? filled : filled - 128);
+ while (p != end && *p != '\037') p++;
+ /* p points to ^_Ffunctionname\n or ^_Vvarname\n. */
+ if (p != end)
+ {
+ end = index (p, '\n');
+ sym = oblookup (Vobarray, p + 2, end - p - 2);
+ if (XTYPE (sym) == Lisp_Symbol)
+ {
+ if (p[1] == 'V')
+ {
+ /* Install file-position as variable-documentation property
+ and make it negative for a user-variable
+ (doc starts with a `*'). */
+ Fput (sym, Qvariable_documentation,
+ make_number ((pos + end + 1 - buf)
+ * (end[1] == '*' ? -1 : 1)));
+ }
+ else if (p[1] == 'F')
+ {
+ fun = XSYMBOL (sym)->function;
+ if (XTYPE (fun) == Lisp_Subr)
+ XSUBR (fun)->doc = (char *) - (pos + end + 1 - buf);
+ else if (CONSP (fun))
+ {
+ tem = XCONS (fun)->car;
+ if (EQ (tem, Qlambda) || EQ (tem, Qautoload))
+ {
+ tem = Fcdr (Fcdr (fun));
+ if (CONSP (tem) &&
+ XTYPE (XCONS (tem)->car) == Lisp_Int)
+ XFASTINT (XCONS (tem)->car) = (pos + end + 1 - buf);
+ }
+ }
+ }
+ else error ("DOC file invalid at position %d", pos);
+ }
+ }
+ pos += end - buf;
+ filled -= end - buf;
+ bcopy (end, buf, filled);
+ }
+ close (fd);
+ return Qnil;
+}
+
+DEFUN ("substitute-command-keys", Fsubstitute_command_keys,
+ Ssubstitute_command_keys, 1, 1, 0,
+ "Return the STRING with substrings of the form \\=\\[COMMAND]\n\
+replaced by either: a keystroke sequence that will invoke COMMAND,\n\
+or \"M-x COMMAND\" if COMMAND is not on any keys.\n\
+Substrings of the form \\=\\{MAPVAR} are replaced by summaries\n\
+\(made by describe-bindings) of the value of MAPVAR, taken as a keymap.\n\
+Substrings of the form \\=\\<MAPVAR> specify to use the value of MAPVAR\n\
+as the keymap for future \\=\\[COMMAND] substrings.\n\
+\\=\\= quotes the following character and is discarded;\n\
+thus, \\=\\=\\=\\= puts \\=\\= into the output, and \\=\\=\\=\\[ puts \\=\\[ into the output.")
+ (str)
+ Lisp_Object str;
+{
+ unsigned char *buf;
+ int changed = 0;
+ register unsigned char *strp;
+ register unsigned char *bufp;
+ int idx;
+ int bsize;
+ unsigned char *new;
+ register Lisp_Object tem;
+ Lisp_Object keymap;
+ unsigned char *start;
+ int length;
+ struct gcpro gcpro1;
+
+ if (NULL (str))
+ return Qnil;
+
+ CHECK_STRING (str, 0);
+ GCPRO1 (str);
+
+ keymap = current_buffer->keymap;
+
+ bsize = XSTRING (str)->size;
+ bufp = buf = (unsigned char *) xmalloc (bsize);
+
+ strp = (unsigned char *) XSTRING (str)->data;
+ while (strp - (unsigned char *) XSTRING (str)->data < XSTRING (str)->size)
+ {
+ if (strp[0] == '\\' && strp[1] == '=')
+ {
+ /* \= quotes the next character;
+ thus, to put in \[ without its special meaning, use \=\[. */
+ changed = 1;
+ *bufp++ = strp[2];
+ strp += 3;
+ }
+ else if (strp[0] == '\\' && strp[1] == '[')
+ {
+ changed = 1;
+ strp += 2; /* skip \[ */
+ start = strp;
+
+ while (strp - (unsigned char *) XSTRING (str)->data < XSTRING (str)->size
+ && *strp != ']')
+ strp++;
+ length = strp - start;
+ strp++; /* skip ] */
+
+ /* Save STRP in IDX. */
+ idx = strp - (unsigned char *) XSTRING (str)->data;
+ tem = Fintern (make_string (start, length), Qnil);
+ tem = Fwhere_is_internal (tem, keymap, Qt);
+
+ if (NULL (tem)) /* but not on any keys */
+ {
+ new = (unsigned char *) xrealloc (buf, bsize += 4);
+ bufp += new - buf;
+ buf = new;
+ bcopy ("M-x ", bufp, 4);
+ bufp += 4;
+ goto subst;
+ }
+ else
+ { /* function is on a key */
+ tem = Fkey_description (tem);
+ goto subst_string;
+ }
+ }
+ /* \{foo} is replaced with a summary of the keymap (symeval foo).
+ \<foo> just sets the keymap used for \[cmd]. */
+ else if (strp[0] == '\\' && (strp[1] == '{' || strp[1] == '<'))
+ {
+ struct buffer *oldbuf;
+ Lisp_Object name;
+
+ changed = 1;
+ strp += 2; /* skip \{ or \< */
+ start = strp;
+
+ while (strp - (unsigned char *) XSTRING (str)->data < XSTRING (str)->size
+ && *strp != '}' && *strp != '>')
+ strp++;
+ length = strp - start;
+ strp++; /* skip } or > */
+
+ /* Save STRP in IDX. */
+ idx = strp - (unsigned char *) XSTRING (str)->data;
+
+ oldbuf = current_buffer;
+ set_buffer_internal (XBUFFER (Vprin1_to_string_buffer));
+ name = Fintern (make_string (start, length), Qnil);
+ if ((tem = (Fboundp (name)), NULL (tem)) ||
+ (tem = (Fsymbol_value (name)), NULL (tem)) ||
+ (tem = (get_keymap_1 (tem, 0)), NULL (tem)))
+ {
+ name = Fsymbol_name (name);
+ InsStr ("\nUses keymap \"");
+ insert (XSTRING (name)->data, XSTRING (name)->size);
+ InsStr ("\", which is not currently defined.\n");
+ if (start[-1] == '<') keymap = Qnil;
+ }
+ else if (start[-1] == '<')
+ keymap = tem;
+ else
+ describe_map_tree (tem, 1, Qnil);
+ tem = Fbuffer_string ();
+ Ferase_buffer ();
+ set_buffer_internal (oldbuf);
+
+ subst_string:
+ start = XSTRING (tem)->data;
+ length = XSTRING (tem)->size;
+ subst:
+ new = (unsigned char *) xrealloc (buf, bsize += length);
+ bufp += new - buf;
+ buf = new;
+ bcopy (start, bufp, length);
+ bufp += length;
+ /* Check STR again in case gc relocated it. */
+ strp = (unsigned char *) XSTRING (str)->data + idx;
+ }
+ else /* just copy other chars */
+ *bufp++ = *strp++;
+ }
+
+ if (changed) /* don't bother if nothing substituted */
+ tem = make_string (buf, bufp - buf);
+ else
+ tem = str;
+ UNGCPRO;
+ free (buf);
+ return tem;
+}
+
+syms_of_doc ()
+{
+ staticpro (&Vdoc_file_name);
+ Vdoc_file_name = Qnil;
+
+ defsubr (&Sdocumentation);
+ defsubr (&Sdocumentation_property);
+ defsubr (&Ssnarf_documentation);
+ defsubr (&Ssubstitute_command_keys);
+}
diff --git a/src/doprnt.c b/src/doprnt.c
index 731afe400cc..ad414b7c0c2 100644
--- a/src/doprnt.c
+++ b/src/doprnt.c
@@ -23,50 +23,27 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h>
#include <ctype.h>
-/* Generate output from a format-spec FORMAT,
- terminated at position FORMAT_END.
- Output goes in BUFFER, which has room for BUFSIZE chars.
- If the output does not fit, truncate it to fit.
- Returns the number of characters stored into BUFFER.
- ARGS points to the vector of arguments, and NARGS says how many.
- A double counts as two arguments. */
-
-doprnt (buffer, bufsize, format, format_end, nargs, args)
+doprnt (buffer, bufsize, format, nargs, args)
char *buffer;
register int bufsize;
char *format;
- char *format_end;
int nargs;
char **args;
{
int cnt = 0; /* Number of arg to gobble next */
register char *fmt = format; /* Pointer into format string */
register char *bufptr = buffer; /* Pointer into output buffer.. */
- /* Use this for sprintf unless we need something really big. */
- char tembuf[100];
- /* Size of sprintf_buffer. */
- int size_allocated = 100;
- /* Buffer to use for sprintf. Either tembuf or same as BIG_BUFFER. */
- char *sprintf_buffer = tembuf;
- /* Buffer we have got with malloc. */
- char *big_buffer = 0;
+ char tembuf[80];
register int tem;
char *string;
char fmtcpy[20];
int minlen;
- int size; /* Field width factor; e.g., %90d */
-
- if (format_end == 0)
- format_end = format + strlen (format);
bufsize--;
- while (fmt != format_end && bufsize > 0) /* Loop until end of format
- string or buffer full */
+ while (*fmt && bufsize > 0) /* Loop until end of format string or buffer full */
{
if (*fmt == '%') /* Check for a '%' character */
{
- int size_bound;
-
fmt++;
/* Copy this one %-spec into fmtcopy. */
string = fmtcpy;
@@ -79,52 +56,23 @@ doprnt (buffer, bufsize, format, format_end, nargs, args)
fmt++;
}
*string = 0;
- /* Get an idea of how much space we might need. */
- size_bound = atoi (&fmtcpy[1]) + 50;
- /* Make sure we have that much. */
- if (size_bound > size_allocated)
- {
- if (big_buffer)
- big_buffer = (char *) xrealloc (big_buffer, size_bound);
- else
- big_buffer = (char *) xmalloc (size_bound);
- sprintf_buffer = big_buffer;
- size_allocated = size_bound;
- }
minlen = 0;
switch (*fmt++)
{
default:
error ("Invalid format operation %%%c", fmt[-1]);
-/* case 'b': */
+ case 'b':
case 'd':
case 'o':
case 'x':
if (cnt == nargs)
error ("Format string wants too many arguments");
- sprintf (sprintf_buffer, fmtcpy, args[cnt++]);
- /* Now copy into final output, truncating as nec. */
- string = sprintf_buffer;
+ sprintf (tembuf, fmtcpy, args[cnt++]);
+ /* Now copy tembuf into final output, truncating as nec. */
+ string = tembuf;
goto doit;
- case 'f':
- case 'e':
- case 'g':
- {
- union { double d; char *half[2]; } u;
- if (cnt + 1 == nargs)
- error ("Format string wants too many arguments");
- u.half[0] = args[cnt++];
- u.half[1] = args[cnt++];
- sprintf (sprintf_buffer, fmtcpy, u.d);
- /* Now copy into final output, truncating as nec. */
- string = sprintf_buffer;
- goto doit;
- }
-
- case 'S':
- string[-1] = 's';
case 's':
if (cnt == nargs)
error ("Format string wants too many arguments");
@@ -176,10 +124,6 @@ doprnt (buffer, bufsize, format, format_end, nargs, args)
bufsize--;
};
- /* If we had to malloc something, free it. */
- if (big_buffer)
- free (big_buffer);
-
*bufptr = 0; /* Make sure our string end with a '\0' */
return bufptr - buffer;
}
diff --git a/src/editfns.c b/src/editfns.c
new file mode 100644
index 00000000000..05a707e537e
--- /dev/null
+++ b/src/editfns.c
@@ -0,0 +1,1111 @@
+/* Lisp functions pertaining to editing.
+ Copyright (C) 1985, 1986, 1987, 1990 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#include "config.h"
+#ifdef hpux
+/* needed by <pwd.h> */
+#include <stdio.h>
+#undef NULL
+#endif
+
+#ifdef VMS
+#include "vms-pwd.h"
+#else
+#include <pwd.h>
+#endif
+
+#include "lisp.h"
+#include "buffer.h"
+#include "window.h"
+
+#define min(a, b) ((a) < (b) ? (a) : (b))
+#define max(a, b) ((a) > (b) ? (a) : (b))
+
+/* Some static data, and a function to initialize it for each run */
+
+static Lisp_Object Vsystem_name;
+static Lisp_Object Vuser_real_name; /* login name of current user ID */
+static Lisp_Object Vuser_full_name; /* full name of current user */
+static Lisp_Object Vuser_name; /* user name from USER or LOGNAME. */
+
+void
+init_editfns ()
+{
+ char *user_name;
+ register unsigned char *p, *q;
+ struct passwd *pw; /* password entry for the current user */
+ Lisp_Object tem;
+ extern char *index ();
+
+ /* Turn off polling so the SIGALRM won't bother getpwuid. */
+ stop_polling ();
+
+ /* Set up system_name even when dumping. */
+
+ Vsystem_name = build_string (get_system_name ());
+ p = XSTRING (Vsystem_name)->data;
+ while (*p)
+ {
+ if (*p == ' ' || *p == '\t')
+ *p = '-';
+ p++;
+ }
+
+#ifndef CANNOT_DUMP
+ /* Don't bother with this on initial start when just dumping out */
+ if (!initialized)
+ return;
+#endif /* not CANNOT_DUMP */
+
+ pw = (struct passwd *) getpwuid (getuid ());
+ Vuser_real_name = build_string (pw ? pw->pw_name : "unknown");
+
+ /* Get the effective user name, by consulting environment variables,
+ or the effective uid if those are unset. */
+ user_name = (char *) getenv ("USER");
+ if (!user_name)
+ user_name = (char *) getenv ("LOGNAME"); /* USG equivalent */
+ if (!user_name)
+ {
+ pw = (struct passwd *) getpwuid (geteuid ());
+ user_name = pw ? pw->pw_name : "unknown";
+ }
+ Vuser_name = build_string (user_name);
+
+ /* If the user name claimed in the environment vars differs from
+ the real uid, use the claimed name to find the full name. */
+ tem = Fstring_equal (Vuser_name, Vuser_real_name);
+ if (NULL (tem))
+ pw = (struct passwd *) getpwnam (XSTRING (Vuser_name)->data);
+
+ p = (unsigned char *) (pw ? USER_FULL_NAME : "unknown");
+ q = (unsigned char *) index (p, ',');
+ Vuser_full_name = make_string (p, q ? q - p : strlen (p));
+
+#ifdef AMPERSAND_FULL_NAME
+ p = XSTRING (Vuser_full_name)->data;
+ q = (unsigned char *) index (p, '&');
+ /* Substitute the login name for the &, upcasing the first character. */
+ if (q)
+ {
+ char *r
+ = (char *) alloca (strlen (p) + XSTRING (Vuser_name)->size + 1);
+ bcopy (p, r, q - p);
+ r[q - p] = 0;
+ strcat (r, XSTRING (Vuser_real_name)->data);
+ r[q - p] = UPCASE (r[q - p]);
+ strcat (r, q + 1);
+ Vuser_full_name = build_string (r);
+ }
+#endif /* AMPERSAND_FULL_NAME */
+
+ start_polling ();
+}
+
+DEFUN ("char-to-string", Fchar_to_string, Schar_to_string, 1, 1, 0,
+ "Convert arg CHAR to a string containing that character.")
+ (n)
+ Lisp_Object n;
+{
+ char c;
+ CHECK_NUMBER (n, 0);
+
+ c = XINT (n);
+ return make_string (&c, 1);
+}
+
+DEFUN ("string-to-char", Fstring_to_char, Sstring_to_char, 1, 1, 0,
+ "Convert arg STRING to a character, the first character of that string.")
+ (str)
+ register Lisp_Object str;
+{
+ register Lisp_Object val;
+ register struct Lisp_String *p;
+ CHECK_STRING (str, 0);
+
+ p = XSTRING (str);
+ if (p->size)
+ XFASTINT (val) = ((unsigned char *) p->data)[0];
+ else
+ XFASTINT (val) = 0;
+ return val;
+}
+
+static Lisp_Object
+buildmark (val)
+ int val;
+{
+ register Lisp_Object mark;
+ mark = Fmake_marker ();
+ Fset_marker (mark, make_number (val), Qnil);
+ return mark;
+}
+
+DEFUN ("point", Fpoint, Spoint, 0, 0, 0,
+ "Return value of point, as an integer.\n\
+Beginning of buffer is position (point-min)")
+ ()
+{
+ Lisp_Object temp;
+ XFASTINT (temp) = point;
+ return temp;
+}
+
+DEFUN ("point-marker", Fpoint_marker, Spoint_marker, 0, 0, 0,
+ "Return value of point, as a marker object.")
+ ()
+{
+ return buildmark (point);
+}
+
+int
+clip_to_bounds (lower, num, upper)
+ int lower, num, upper;
+{
+ if (num < lower)
+ return lower;
+ else if (num > upper)
+ return upper;
+ else
+ return num;
+}
+
+DEFUN ("goto-char", Fgoto_char, Sgoto_char, 1, 1, "NGoto char: ",
+ "One arg, a number. Set point to that number.\n\
+Beginning of buffer is position (point-min), end is (point-max).")
+ (n)
+ register Lisp_Object n;
+{
+ register int charno;
+ CHECK_NUMBER_COERCE_MARKER (n, 0);
+ charno = XINT (n);
+ SET_PT (clip_to_bounds (BEGV, charno, ZV));
+ return n;
+}
+
+static Lisp_Object
+region_limit (beginningp)
+ int beginningp;
+{
+ register Lisp_Object m;
+ m = Fmarker_position (current_buffer->mark);
+ if (NULL (m)) error ("There is no region now");
+ if ((point < XFASTINT (m)) == beginningp)
+ return (make_number (point));
+ else
+ return (m);
+}
+
+DEFUN ("region-beginning", Fregion_beginning, Sregion_beginning, 0, 0, 0,
+ "Return position of beginning of region, as an integer.")
+ ()
+{
+ return (region_limit (1));
+}
+
+DEFUN ("region-end", Fregion_end, Sregion_end, 0, 0, 0,
+ "Return position of end of region, as an integer.")
+ ()
+{
+ return (region_limit (0));
+}
+
+#if 0 /* now in lisp code */
+DEFUN ("mark", Fmark, Smark, 0, 0, 0,
+ "Return this buffer's mark value as integer, or nil if no mark.\n\
+If you are using this in an editing command, you are most likely making\n\
+a mistake; see the documentation of `set-mark'.")
+ ()
+{
+ return Fmarker_position (current_buffer->mark);
+}
+#endif /* commented out code */
+
+DEFUN ("mark-marker", Fmark_marker, Smark_marker, 0, 0, 0,
+ "Return this buffer's mark, as a marker object.\n\
+Watch out! Moving this marker changes the mark position.\n\
+The marker will not point anywhere if mark is not set.")
+ ()
+{
+ return current_buffer->mark;
+}
+
+#if 0 /* this is now in lisp code */
+DEFUN ("set-mark", Fset_mark, Sset_mark, 1, 1, 0,
+ "Set this buffer's mark to POS. Don't use this function!\n\
+That is to say, don't use this function unless you want\n\
+the user to see that the mark has moved, and you want the previous\n\
+mark position to be lost.\n\
+\n\
+Normally, when a new mark is set, the old one should go on the stack.\n\
+This is why most applications should use push-mark, not set-mark.\n\
+\n\
+Novice programmers often try to use the mark for the wrong purposes.\n\
+The mark saves a location for the user's convenience.\n\
+Most editing commands should not alter the mark.\n\
+To remember a location for internal use in the Lisp program,\n\
+store it in a Lisp variable. Example:\n\
+\n\
+ (let ((beg (point))) (forward-line 1) (delete-region beg (point))).")
+ (pos)
+ Lisp_Object pos;
+{
+ if (NULL (pos))
+ {
+ current_buffer->mark = Qnil;
+ return Qnil;
+ }
+ CHECK_NUMBER_COERCE_MARKER (pos, 0);
+
+ if (NULL (current_buffer->mark))
+ current_buffer->mark = Fmake_marker ();
+
+ Fset_marker (current_buffer->mark, pos, Qnil);
+ return pos;
+}
+#endif /* commented-out code */
+
+Lisp_Object
+save_excursion_save ()
+{
+ register int visible = XBUFFER (XWINDOW (selected_window)->buffer) == current_buffer;
+
+ return Fcons (Fpoint_marker (),
+ Fcons (Fcopy_marker (current_buffer->mark), visible ? Qt : Qnil));
+}
+
+Lisp_Object
+save_excursion_restore (info)
+ register Lisp_Object info;
+{
+ register Lisp_Object tem;
+
+ tem = Fmarker_buffer (Fcar (info));
+ /* If buffer being returned to is now deleted, avoid error */
+ /* Otherwise could get error here while unwinding to top level
+ and crash */
+ /* In that case, Fmarker_buffer returns nil now. */
+ if (NULL (tem))
+ return Qnil;
+ Fset_buffer (tem);
+ tem = Fcar (info);
+ Fgoto_char (tem);
+ unchain_marker (tem);
+ tem = Fcar (Fcdr (info));
+ Fset_marker (current_buffer->mark, tem, Fcurrent_buffer ());
+ if (XMARKER (tem)->buffer)
+ unchain_marker (tem);
+ tem = Fcdr (Fcdr (info));
+ if (!NULL (tem) && current_buffer != XBUFFER (XWINDOW (selected_window)->buffer))
+ Fswitch_to_buffer (Fcurrent_buffer (), Qnil);
+ return Qnil;
+}
+
+DEFUN ("save-excursion", Fsave_excursion, Ssave_excursion, 0, UNEVALLED, 0,
+ "Save point (and mark), execute BODY, then restore point and mark.\n\
+Executes BODY just like PROGN. Point and mark values are restored\n\
+even in case of abnormal exit (throw or error).")
+ (args)
+ Lisp_Object args;
+{
+ register Lisp_Object val;
+ int count = specpdl_ptr - specpdl;
+
+ record_unwind_protect (save_excursion_restore, save_excursion_save ());
+
+ val = Fprogn (args);
+ unbind_to (count);
+ return val;
+}
+
+DEFUN ("buffer-size", Fbufsize, Sbufsize, 0, 0, 0,
+ "Return the number of characters in the current buffer.")
+ ()
+{
+ Lisp_Object temp;
+ XFASTINT (temp) = Z - BEG;
+ return temp;
+}
+
+DEFUN ("point-min", Fpoint_min, Spoint_min, 0, 0, 0,
+ "Return the minimum permissible value of point in the current buffer.\n\
+This is 1, unless a clipping restriction is in effect.")
+ ()
+{
+ Lisp_Object temp;
+ XFASTINT (temp) = BEGV;
+ return temp;
+}
+
+DEFUN ("point-min-marker", Fpoint_min_marker, Spoint_min_marker, 0, 0, 0,
+ "Return a marker to the beginning of the currently visible part of the buffer.\n\
+This is the beginning, unless a clipping restriction is in effect.")
+ ()
+{
+ return buildmark (BEGV);
+}
+
+DEFUN ("point-max", Fpoint_max, Spoint_max, 0, 0, 0,
+ "Return the maximum permissible value of point in the current buffer.\n\
+This is (1+ (buffer-size)), unless a clipping restriction is in effect,\n\
+in which case it is less.")
+ ()
+{
+ Lisp_Object temp;
+ XFASTINT (temp) = ZV;
+ return temp;
+}
+
+DEFUN ("point-max-marker", Fpoint_max_marker, Spoint_max_marker, 0, 0, 0,
+ "Return a marker to the end of the currently visible part of the buffer.\n\
+This is the actual end, unless a clipping restriction is in effect.")
+ ()
+{
+ return buildmark (ZV);
+}
+
+DEFUN ("following-char", Ffollchar, Sfollchar, 0, 0, 0,
+ "Return the character following point, as a number.")
+ ()
+{
+ Lisp_Object temp;
+ if (point >= ZV)
+ XFASTINT (temp) = 0;
+ else
+ XFASTINT (temp) = FETCH_CHAR (point);
+ return temp;
+}
+
+DEFUN ("preceding-char", Fprevchar, Sprevchar, 0, 0, 0,
+ "Return the character preceding point, as a number.")
+ ()
+{
+ Lisp_Object temp;
+ if (point <= BEGV)
+ XFASTINT (temp) = 0;
+ else
+ XFASTINT (temp) = FETCH_CHAR (point - 1);
+ return temp;
+}
+
+DEFUN ("bobp", Fbobp, Sbobp, 0, 0, 0,
+ "Return T if point is at the beginning of the buffer.\n\
+If the buffer is narrowed, this means the beginning of the narrowed part.")
+ ()
+{
+ if (point == BEGV)
+ return Qt;
+ return Qnil;
+}
+
+DEFUN ("eobp", Feobp, Seobp, 0, 0, 0,
+ "Return T if point is at the end of the buffer.\n\
+If the buffer is narrowed, this means the end of the narrowed part.")
+ ()
+{
+ if (point == ZV)
+ return Qt;
+ return Qnil;
+}
+
+DEFUN ("bolp", Fbolp, Sbolp, 0, 0, 0,
+ "Return T if point is at the beginning of a line.")
+ ()
+{
+ if (point == BEGV || FETCH_CHAR (point - 1) == '\n')
+ return Qt;
+ return Qnil;
+}
+
+DEFUN ("eolp", Feolp, Seolp, 0, 0, 0,
+ "Return T if point is at the end of a line.\n\
+`End of a line' includes point being at the end of the buffer.")
+ ()
+{
+ if (point == ZV || FETCH_CHAR (point) == '\n')
+ return Qt;
+ return Qnil;
+}
+
+DEFUN ("char-after", Fchar_after, Schar_after, 1, 1, 0,
+ "One arg, POS, a number. Return the character in the current buffer\n\
+at position POS.\n\
+If POS is out of range, the value is NIL.")
+ (pos)
+ Lisp_Object pos;
+{
+ register Lisp_Object val;
+ register int n;
+
+ CHECK_NUMBER_COERCE_MARKER (pos, 0);
+
+ n = XINT (pos);
+ if (n < BEGV || n >= ZV) return Qnil;
+
+ XFASTINT (val) = FETCH_CHAR (n);
+ return val;
+}
+
+DEFUN ("user-login-name", Fuser_login_name, Suser_login_name, 0, 0, 0,
+ "Return the name under which user logged in, as a string.\n\
+This is based on the effective uid, not the real uid.")
+ ()
+{
+ return Vuser_name;
+}
+
+DEFUN ("user-real-login-name", Fuser_real_login_name, Suser_real_login_name,
+ 0, 0, 0,
+ "Return the name of the user's real uid, as a string.\n\
+Differs from user-login-name when running under su.")
+ ()
+{
+ return Vuser_real_name;
+}
+
+DEFUN ("user-uid", Fuser_uid, Suser_uid, 0, 0, 0,
+ "Return the effective uid of Emacs, as an integer.")
+ ()
+{
+ return make_number (geteuid ());
+}
+
+DEFUN ("user-real-uid", Fuser_real_uid, Suser_real_uid, 0, 0, 0,
+ "Return the real uid of Emacs, as an integer.")
+ ()
+{
+ return make_number (getuid ());
+}
+
+DEFUN ("user-full-name", Fuser_full_name, Suser_full_name, 0, 0, 0,
+ "Return the full name of the user logged in, as a string.")
+ ()
+{
+ return Vuser_full_name;
+}
+
+DEFUN ("system-name", Fsystem_name, Ssystem_name, 0, 0, 0,
+ "Return the name of the machine you are running on, as a string.")
+ ()
+{
+ return Vsystem_name;
+}
+
+DEFUN ("current-time-string", Fcurrent_time_string, Scurrent_time_string, 0, 0, 0,
+ "Return the current time, as a human-readable string.")
+ ()
+{
+ long current_time = time (0);
+ register char *tem = (char *) ctime (&current_time);
+ tem [24] = 0;
+ return build_string (tem);
+}
+
+insert1 (arg)
+ Lisp_Object arg;
+{
+ Finsert (1, &arg);
+}
+
+DEFUN ("insert", Finsert, Sinsert, 0, MANY, 0,
+ "Any number of args, strings or chars. Insert them after point, moving point forward.")
+ (nargs, args)
+ int nargs;
+ register Lisp_Object *args;
+{
+ register int argnum;
+ register Lisp_Object tem;
+ char str[1];
+
+ for (argnum = 0; argnum < nargs; argnum++)
+ {
+ tem = args[argnum];
+ retry:
+ if (XTYPE (tem) == Lisp_Int)
+ {
+ str[0] = XINT (tem);
+ insert (str, 1);
+ }
+ else if (XTYPE (tem) == Lisp_String)
+ {
+ insert_from_string (tem, 0, XSTRING (tem)->size);
+ }
+ else
+ {
+ tem = wrong_type_argument (Qchar_or_string_p, tem);
+ goto retry;
+ }
+ }
+ return Qnil;
+}
+
+DEFUN ("insert-before-markers", Finsert_before_markers, Sinsert_before_markers, 0, MANY, 0,
+ "Any number of args, strings or chars. Insert them after point,\n\
+moving point forward. Also, any markers pointing at the insertion point\n\
+get relocated to point after the newly inserted text.")
+ (nargs, args)
+ int nargs;
+ register Lisp_Object *args;
+{
+ register int argnum;
+ register Lisp_Object tem;
+ char str[1];
+
+ for (argnum = 0; argnum < nargs; argnum++)
+ {
+ tem = args[argnum];
+ retry:
+ if (XTYPE (tem) == Lisp_Int)
+ {
+ str[0] = XINT (tem);
+ insert_before_markers (str, 1);
+ }
+ else if (XTYPE (tem) == Lisp_String)
+ {
+ insert_from_string_before_markers (tem, 0, XSTRING (tem)->size);
+ }
+ else
+ {
+ tem = wrong_type_argument (Qchar_or_string_p, tem);
+ goto retry;
+ }
+ }
+ return Qnil;
+}
+
+DEFUN ("insert-char", Finsert_char, Sinsert_char, 2, 2, 0,
+ "Insert COUNT (second arg) copies of CHAR (first arg).\n\
+Both arguments are required.")
+ (chr, count)
+ Lisp_Object chr, count;
+{
+ register unsigned char *string;
+ register int strlen;
+ register int i, n;
+
+ CHECK_NUMBER (chr, 0);
+ CHECK_NUMBER (count, 1);
+
+ n = XINT (count);
+ if (n <= 0)
+ return Qnil;
+ strlen = max (n, 256);
+ string = (unsigned char *) alloca (strlen);
+ for (i = 0; i < strlen; i++)
+ string[i] = XFASTINT (chr);
+ while (n >= strlen)
+ {
+ insert (string, strlen);
+ n -= strlen;
+ }
+ if (n > 0)
+ insert (string, n);
+ return Qnil;
+}
+
+
+/* Return a string with the contents of the current region */
+
+DEFUN ("buffer-substring", Fbuffer_substring, Sbuffer_substring, 2, 2, 0,
+ "Return the contents of part of the current buffer as a string.\n\
+The two arguments specify the start and end, as character numbers.")
+ (b, e)
+ Lisp_Object b, e;
+{
+ register int beg, end;
+
+ validate_region (&b, &e);
+ beg = XINT (b);
+ end = XINT (e);
+
+ if (beg < GPT && end > GPT)
+ move_gap (beg);
+ return make_string (&FETCH_CHAR (beg), end - beg);
+}
+
+DEFUN ("buffer-string", Fbuffer_string, Sbuffer_string, 0, 0, 0,
+ "Return the contents of the current buffer as a string.")
+ ()
+{
+ if (BEGV < GPT && ZV > GPT)
+ move_gap (BEGV);
+ return make_string (BEGV_ADDR, ZV - BEGV);
+}
+
+DEFUN ("insert-buffer-substring", Finsert_buffer_substring, Sinsert_buffer_substring,
+ 1, 3, 0,
+ "Insert before point a substring of the contents buffer BUFFER.\n\
+BUFFER may be a buffer or a buffer name.\n\
+Arguments START and END are character numbers specifying the substring.\n\
+They default to the beginning and the end of BUFFER.")
+ (buf, b, e)
+ Lisp_Object buf, b, e;
+{
+ register int beg, end, exch;
+ register struct buffer *bp;
+
+ buf = Fget_buffer (buf);
+ bp = XBUFFER (buf);
+
+ if (NULL (b))
+ beg = BUF_BEGV (bp);
+ else
+ {
+ CHECK_NUMBER_COERCE_MARKER (b, 0);
+ beg = XINT (b);
+ }
+ if (NULL (e))
+ end = BUF_ZV (bp);
+ else
+ {
+ CHECK_NUMBER_COERCE_MARKER (e, 1);
+ end = XINT (e);
+ }
+
+ if (beg > end)
+ exch = beg, beg = end, end = exch;
+
+ /* Move the gap or create enough gap in the current buffer. */
+
+ if (point != GPT)
+ move_gap (point);
+ if (GAP_SIZE < end - beg)
+ make_gap (end - beg - GAP_SIZE);
+
+ if (!(BUF_BEGV (bp) <= beg
+ && beg <= end
+ && end <= BUF_ZV (bp)))
+ args_out_of_range (b, e);
+
+ /* Now the actual insertion will not do any gap motion,
+ so it matters not if BUF is the current buffer. */
+
+ if (beg < BUF_GPT (bp))
+ {
+ insert (BUF_CHAR_ADDRESS (bp, beg), min (end, BUF_GPT (bp)) - beg);
+ beg = min (end, BUF_GPT (bp));
+ }
+ if (beg < end)
+ insert (BUF_CHAR_ADDRESS (bp, beg), end - beg);
+
+ return Qnil;
+}
+
+DEFUN ("subst-char-in-region", Fsubst_char_in_region,
+ Ssubst_char_in_region, 4, 5, 0,
+ "From START to END, replace FROMCHAR with TOCHAR each time it occurs.\n\
+If optional arg NOUNDO is non-nil, don't record this change for undo\n\
+and don't mark the buffer as really changed.")
+ (start, end, fromchar, tochar, noundo)
+ Lisp_Object start, end, fromchar, tochar, noundo;
+{
+ register int pos, stop, look;
+
+ validate_region (&start, &end);
+ CHECK_NUMBER (fromchar, 2);
+ CHECK_NUMBER (tochar, 3);
+
+ pos = XINT (start);
+ stop = XINT (end);
+ look = XINT (fromchar);
+
+ modify_region (pos, stop);
+ if (! NULL (noundo))
+ {
+ if (MODIFF - 1 == current_buffer->save_modified)
+ current_buffer->save_modified++;
+ if (MODIFF - 1 == current_buffer->auto_save_modified)
+ current_buffer->auto_save_modified++;
+ }
+
+ while (pos < stop)
+ {
+ if (FETCH_CHAR (pos) == look)
+ {
+ if (NULL (noundo))
+ record_change (pos, 1);
+ FETCH_CHAR (pos) = XINT (tochar);
+ }
+ pos++;
+ }
+
+ return Qnil;
+}
+
+DEFUN ("delete-region", Fdelete_region, Sdelete_region, 2, 2, "r",
+ "Delete the text between point and mark.\n\
+When called from a program, expects two arguments,\n\
+character numbers specifying the stretch to be deleted.")
+ (b, e)
+ Lisp_Object b, e;
+{
+ validate_region (&b, &e);
+ del_range (XINT (b), XINT (e));
+ return Qnil;
+}
+
+DEFUN ("widen", Fwiden, Swiden, 0, 0, "",
+ "Remove restrictions from current buffer, allowing full text to be seen and edited.")
+ ()
+{
+ BEGV = BEG;
+ SET_BUF_ZV (current_buffer, Z);
+ clip_changed = 1;
+ /* Changing the buffer bounds invalidates any recorded current column. */
+ invalidate_current_column ();
+ return Qnil;
+}
+
+DEFUN ("narrow-to-region", Fnarrow_to_region, Snarrow_to_region, 2, 2, "r",
+ "Restrict editing in this buffer to the current region.\n\
+The rest of the text becomes temporarily invisible and untouchable\n\
+but is not deleted; if you save the buffer in a file, the invisible\n\
+text is included in the file. \\[widen] makes all visible again.\n\
+\n\
+When calling from a program, pass two arguments; character numbers\n\
+bounding the text that should remain visible.")
+ (b, e)
+ register Lisp_Object b, e;
+{
+ register int i;
+
+ CHECK_NUMBER_COERCE_MARKER (b, 0);
+ CHECK_NUMBER_COERCE_MARKER (e, 1);
+
+ if (XINT (b) > XINT (e))
+ {
+ i = XFASTINT (b);
+ b = e;
+ XFASTINT (e) = i;
+ }
+
+ if (!(BEG <= XINT (b) && XINT (b) <= XINT (e) && XINT (e) <= Z))
+ args_out_of_range (b, e);
+
+ BEGV = XFASTINT (b);
+ SET_BUF_ZV (current_buffer, XFASTINT (e));
+ if (point < XFASTINT (b))
+ SET_PT (XFASTINT (b));
+ if (point > XFASTINT (e))
+ SET_PT (XFASTINT (e));
+ clip_changed = 1;
+ /* Changing the buffer bounds invalidates any recorded current column. */
+ invalidate_current_column ();
+ return Qnil;
+}
+
+Lisp_Object
+save_restriction_save ()
+{
+ register Lisp_Object bottom, top;
+ /* Note: I tried using markers here, but it does not win
+ because insertion at the end of the saved region
+ does not advance top and is considered "outside" the saved region. */
+ XFASTINT (bottom) = BEGV - BEG;
+ XFASTINT (top) = Z - ZV;
+
+ return Fcons (Fcurrent_buffer (), Fcons (bottom, top));
+}
+
+Lisp_Object
+save_restriction_restore (data)
+ Lisp_Object data;
+{
+ register struct buffer *buf;
+ register int newhead, newtail;
+ register Lisp_Object tem;
+
+ buf = XBUFFER (XCONS (data)->car);
+
+ data = XCONS (data)->cdr;
+
+ tem = XCONS (data)->car;
+ newhead = XINT (tem);
+ tem = XCONS (data)->cdr;
+ newtail = XINT (tem);
+ if (newhead + newtail > BUF_Z (buf) - BUF_BEG (buf))
+ {
+ newhead = 0;
+ newtail = 0;
+ }
+ BUF_BEGV (buf) = BUF_BEG (buf) + newhead;
+ SET_BUF_ZV (buf, BUF_Z (buf) - newtail);
+ clip_changed = 1;
+
+ /* If point is outside the new visible range, move it inside. */
+ SET_BUF_PT (buf,
+ clip_to_bounds (BUF_BEGV (buf), BUF_PT (buf), BUF_ZV (buf)));
+
+ return Qnil;
+}
+
+DEFUN ("save-restriction", Fsave_restriction, Ssave_restriction, 0, UNEVALLED, 0,
+ "Execute the body, undoing at the end any changes to current buffer's restrictions.\n\
+Changes to restrictions are made by narrow-to-region or by widen.\n\
+Thus, the restrictions are the same after this function as they were before it.\n\
+The value returned is that returned by the last form in the body.\n\
+\n\
+This function can be confused if, within the body, you widen\n\
+and then make changes outside the area within the saved restrictions.\n\
+\n\
+Note: if you are using both save-excursion and save-restriction,\n\
+use save-excursion outermost.")
+ (body)
+ Lisp_Object body;
+{
+ register Lisp_Object val;
+ int count = specpdl_ptr - specpdl;
+
+ record_unwind_protect (save_restriction_restore, save_restriction_save ());
+ val = Fprogn (body);
+ unbind_to (count);
+ return val;
+}
+
+DEFUN ("message", Fmessage, Smessage, 1, MANY, 0,
+ "Print a one-line message at the bottom of the screen.\n\
+The first argument is a control string.\n\
+It may contain %s or %d or %c to print successive following arguments.\n\
+%s means print an argument as a string, %d means print as number in decimal,\n\
+%c means print a number as a single character.\n\
+The argument used by %s must be a string or a symbol;\n\
+the argument used by %d or %c must be a number.")
+ (nargs, args)
+ int nargs;
+ Lisp_Object *args;
+{
+ register Lisp_Object val;
+
+ val = Fformat (nargs, args);
+ message ("%s", XSTRING (val)->data);
+ return val;
+}
+
+DEFUN ("format", Fformat, Sformat, 1, MANY, 0,
+ "Format a string out of a control-string and arguments.\n\
+The first argument is a control string.\n\
+It, and subsequent arguments substituted into it, become the value, which is a string.\n\
+It may contain %s or %d or %c to substitute successive following arguments.\n\
+%s means print an argument as a string, %d means print as number in decimal,\n\
+%c means print a number as a single character.\n\
+The argument used by %s must be a string or a symbol;\n\
+the argument used by %d, %b, %o, %x or %c must be a number.")
+ (nargs, args)
+ int nargs;
+ register Lisp_Object *args;
+{
+ register int n;
+ register int total = 5;
+ char *buf;
+ register unsigned char *format;
+ register unsigned char **strings;
+ extern char *index ();
+ /* It should not be necessary to GCPRO ARGS, because
+ the caller in the interpreter should take care of that. */
+
+ CHECK_STRING (args[0], 0);
+ format = XSTRING (args[0])->data;
+
+ /* We have to do so much work in order to prepare to call doprnt
+ that we might as well do all of it ourself... (Which would also
+ circumvent C asciz cretinism by allowing ascii 000 chars to appear)
+ */
+ n = 0;
+ while (format = (unsigned char *) index (format, '%'))
+ {
+ format++;
+ while ((*format >= '0' && *format <= '9')
+ || *format == '-' || *format == ' ')
+ format++;
+ if (*format == '%')
+ format++;
+ else if (++n >= nargs)
+ ;
+ else if (XTYPE (args[n]) == Lisp_Symbol)
+ {
+ XSET (args[n], Lisp_String, XSYMBOL (args[n])->name);
+ goto string;
+ }
+ else if (XTYPE (args[n]) == Lisp_String)
+ {
+ string:
+ total += XSTRING (args[n])->size;
+ }
+ /* would get MPV otherwise, since Lisp_Int's `point' to low memory */
+ else if (XTYPE (args[n]) == Lisp_Int && *format != 's')
+ total += 10;
+ else
+ {
+ register Lisp_Object tem;
+ tem = Fprin1_to_string (args[n]);
+ args[n] = tem;
+ goto string;
+ }
+ }
+
+ strings = (unsigned char **) alloca ((n + 1) * sizeof (unsigned char *));
+ for (; n >= 0; n--)
+ {
+ if (n >= nargs)
+ strings[n] = (unsigned char *) "";
+ else if (XTYPE (args[n]) == Lisp_Int)
+ /* We checked above that the correspondiong format effector
+ isn't %s, which would cause MPV */
+ strings[n] = (unsigned char *) XINT (args[n]);
+ else
+ strings[n] = XSTRING (args[n])->data;
+ }
+
+ /* Format it in bigger and bigger buf's until it all fits. */
+ while (1)
+ {
+ buf = (char *) alloca (total + 1);
+ buf[total - 1] = 0;
+
+ doprnt (buf, total + 1, strings[0], nargs, strings + 1);
+ if (buf[total - 1] == 0)
+ break;
+
+ total *= 2;
+ }
+
+/* UNGCPRO; */
+ return build_string (buf);
+}
+
+/* VARARGS 1 */
+Lisp_Object
+#ifdef NO_ARG_ARRAY
+format1 (string1, arg0, arg1, arg2, arg3, arg4)
+ int arg0, arg1, arg2, arg3, arg4;
+#else
+format1 (string1)
+#endif
+ char *string1;
+{
+ char buf[100];
+#ifdef NO_ARG_ARRAY
+ int args[5];
+ args[0] = arg0;
+ args[1] = arg1;
+ args[2] = arg2;
+ args[3] = arg3;
+ args[4] = arg4;
+ doprnt (buf, sizeof buf, string1, 5, args);
+#else
+ doprnt (buf, sizeof buf, string1, 5, &string1 + 1);
+#endif
+ return build_string (buf);
+}
+
+DEFUN ("char-equal", Fchar_equal, Schar_equal, 2, 2, 0,
+ "T if args (both characters (numbers)) match. May ignore case.\n\
+Case is ignored if the current buffer specifies to do so.")
+ (c1, c2)
+ register Lisp_Object c1, c2;
+{
+ CHECK_NUMBER (c1, 0);
+ CHECK_NUMBER (c2, 1);
+
+ if (!NULL (current_buffer->case_fold_search)
+ ? downcase_table[0xff & XFASTINT (c1)] == downcase_table[0xff & XFASTINT (c2)]
+ : XINT (c1) == XINT (c2))
+ return Qt;
+ return Qnil;
+}
+
+#ifndef MAINTAIN_ENVIRONMENT /* it is done in environ.c in that case */
+DEFUN ("getenv", Fgetenv, Sgetenv, 1, 2, 0,
+ "Return the value of environment variable VAR, as a string.\n\
+VAR should be a string. If the environment variable VAR is not defined,\n\
+the value is nil.")
+ (str)
+ Lisp_Object str;
+{
+ register char *val;
+ CHECK_STRING (str, 0);
+ val = (char *) egetenv (XSTRING (str)->data);
+ if (!val)
+ return Qnil;
+ return build_string (val);
+}
+#endif MAINTAIN_ENVIRONMENT
+
+void
+syms_of_editfns ()
+{
+ staticpro (&Vsystem_name);
+ staticpro (&Vuser_name);
+ staticpro (&Vuser_full_name);
+ staticpro (&Vuser_real_name);
+
+ defsubr (&Schar_equal);
+ defsubr (&Sgoto_char);
+ defsubr (&Sstring_to_char);
+ defsubr (&Schar_to_string);
+ defsubr (&Sbuffer_substring);
+ defsubr (&Sbuffer_string);
+
+ defsubr (&Spoint_marker);
+ defsubr (&Smark_marker);
+ defsubr (&Spoint);
+ defsubr (&Sregion_beginning);
+ defsubr (&Sregion_end);
+/* defsubr (&Smark); */
+/* defsubr (&Sset_mark); */
+ defsubr (&Ssave_excursion);
+
+ defsubr (&Sbufsize);
+ defsubr (&Spoint_max);
+ defsubr (&Spoint_min);
+ defsubr (&Spoint_min_marker);
+ defsubr (&Spoint_max_marker);
+
+ defsubr (&Sbobp);
+ defsubr (&Seobp);
+ defsubr (&Sbolp);
+ defsubr (&Seolp);
+ defsubr (&Sfollchar);
+ defsubr (&Sprevchar);
+ defsubr (&Schar_after);
+ defsubr (&Sinsert);
+ defsubr (&Sinsert_before_markers);
+ defsubr (&Sinsert_char);
+
+ defsubr (&Suser_login_name);
+ defsubr (&Suser_real_login_name);
+ defsubr (&Suser_uid);
+ defsubr (&Suser_real_uid);
+ defsubr (&Suser_full_name);
+ defsubr (&Scurrent_time_string);
+ defsubr (&Ssystem_name);
+ defsubr (&Smessage);
+ defsubr (&Sformat);
+#ifndef MAINTAIN_ENVIRONMENT /* in environ.c */
+ defsubr (&Sgetenv);
+#endif
+
+ defsubr (&Sinsert_buffer_substring);
+ defsubr (&Ssubst_char_in_region);
+ defsubr (&Sdelete_region);
+ defsubr (&Swiden);
+ defsubr (&Snarrow_to_region);
+ defsubr (&Ssave_restriction);
+}
diff --git a/src/emacs.c b/src/emacs.c
new file mode 100644
index 00000000000..49f7110e6be
--- /dev/null
+++ b/src/emacs.c
@@ -0,0 +1,779 @@
+/* Fully extensible Emacs, running on Unix, intended for GNU.
+ Copyright (C) 1985, 1986, 1987, 1990 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* This must precede sys/signal.h on certain machines. */
+#include <sys/types.h>
+#include <signal.h>
+#include <errno.h>
+
+#include "config.h"
+#ifdef NULL
+#undef NULL
+#endif
+#include "lisp.h"
+#undef NULL
+#include "commands.h"
+
+/* Get FIONREAD, if it is available,
+ just to help decide whether SIGIO should be defined. */
+#ifdef USG
+#include <termio.h>
+#include <fcntl.h>
+#else /* not USG */
+#ifndef VMS
+#include <sys/ioctl.h>
+#endif /* not VMS */
+#endif /* not USG */
+
+/* Allow m- file to inhibit use of FIONREAD. */
+#ifdef BROKEN_FIONREAD
+#undef FIONREAD
+#endif
+
+/* We are unable to use interrupts if FIONREAD is not available,
+ so flush SIGIO so we won't try. */
+#ifndef FIONREAD
+#ifdef SIGIO
+#undef SIGIO
+#endif
+#endif
+
+#include <stdio.h>
+#include <sys/file.h>
+
+#ifdef VMS
+#include <ssdef.h>
+#endif
+
+#if 0 /* fcntl.h was included above. */
+#ifdef USG5
+#include <fcntl.h>
+#endif
+#endif
+
+#ifdef BSD
+#include <sys/ioctl.h>
+#endif
+
+#ifdef APOLLO
+#ifndef APOLLO_SR10
+#include <default_acl.h>
+#endif
+#endif
+
+#ifndef O_RDWR
+#define O_RDWR 2
+#endif
+
+#define PRIO_PROCESS 0
+
+/* Command line args from shell, as list of strings */
+Lisp_Object Vcommand_line_args;
+
+/* Hook run by `kill-emacs' before it does really anything. */
+Lisp_Object Vkill_emacs_hook;
+
+/* Set nonzero after Emacs has started up the first time.
+ Prevents reinitialization of the Lisp world and keymaps
+ on subsequent starts. */
+int initialized;
+
+/* Variable whose value is symbol giving operating system type */
+Lisp_Object Vsystem_type;
+
+/* If non-zero, emacs should not attempt to use an window-specific code,
+ but instead should use the virtual terminal under which it was started */
+int inhibit_window_system;
+
+#ifdef HAVE_X_WINDOWS
+/* If -d option is used, this variable points to the name of
+ the display to use. */
+char *alternate_display;
+char **xargv;
+int xargc;
+#endif /* HAVE_X_WINDOWS */
+
+#ifdef USG_SHARED_LIBRARIES
+/* If nonzero, this is the place to put the end of the writable segment
+ at startup. */
+
+unsigned int bss_end = 0;
+#endif
+
+/* Nonzero means running Emacs without interactive terminal. */
+
+int noninteractive;
+
+/* Value of Lisp variable `noninteractive'.
+ Normally same as C variable `noninteractive'
+ but nothing terrible happens if user sets this one. */
+
+int noninteractive1;
+
+/* Signal code for the fatal signal that was received */
+int fatal_error_code;
+
+/* Nonzero if handling a fatal error already */
+int fatal_error_in_progress;
+
+/* Handle bus errors, illegal instruction, etc. */
+fatal_error_signal (sig)
+ int sig;
+{
+#ifdef BSD
+ int tpgrp;
+#endif /* BSD */
+
+ fatal_error_code = sig;
+ signal (sig, SIG_DFL);
+
+ /* If fatal error occurs in code below, avoid infinite recursion. */
+ if (fatal_error_in_progress)
+ kill (getpid (), fatal_error_code);
+
+ fatal_error_in_progress = 1;
+
+ /* If we are controlling the terminal, reset terminal modes */
+#ifdef BSD
+ if (ioctl(0, TIOCGPGRP, &tpgrp) == 0
+ && tpgrp == getpgrp (0))
+#endif /* BSD */
+ {
+ reset_sys_modes ();
+ if (sig != SIGTERM)
+ fprintf (stderr, "Fatal error (%d).", sig);
+ }
+
+ /* Clean up */
+#ifdef subprocesses
+ kill_buffer_processes (Qnil);
+#endif
+ Fdo_auto_save (Qt);
+
+#ifdef CLASH_DETECTION
+ unlock_all_files ();
+#endif /* CLASH_DETECTION */
+
+#ifdef VMS
+ kill_vms_processes ();
+ LIB$STOP (SS$_ABORT);
+#else
+ /* Signal the same code; this time it will really be fatal. */
+ kill (getpid (), fatal_error_code);
+#endif /* not VMS */
+}
+
+/* Code for dealing with Lisp access to the Unix command line */
+
+static
+init_cmdargs (argc, argv, skip_args)
+ int argc;
+ char **argv;
+ int skip_args;
+{
+ register int i;
+
+ Vcommand_line_args = Qnil;
+
+ for (i = argc - 1; i >= 0; i--)
+ {
+ if (i == 0 || i > skip_args)
+ Vcommand_line_args
+ = Fcons (build_string (argv[i]), Vcommand_line_args);
+ }
+}
+
+#ifdef VMS
+#ifdef LINK_CRTL_SHARE
+#ifdef SHAREABLE_LIB_BUG
+#ifdef __GNUC__
+#define environ $$PsectAttributes_NOSHR$$environ
+extern char **environ;
+#else
+extern noshare char **environ;
+#endif
+#endif /* SHAREABLE_LIB_BUG */
+#endif /* LINK_CRTL_SHARE */
+#endif /* VMS */
+
+/* We don't include crtbegin.o and crtend.o in the link,
+ so these functions and variables might be missed.
+ Provide dummy definitions to avoid error.
+ (We don't have any real constructors or destructors.) */
+#ifdef __GNUC__
+#ifndef ORDINARY_LINK
+__do_clobal_ctors ()
+{}
+__do_clobal_ctors_aux ()
+{}
+__do_global_dtors ()
+{}
+char * __CTOR_LIST__[2] = { (char *) (-1), 0 };
+char * __DTOR_LIST__[2] = { (char *) (-1), 0 };
+__main ()
+{}
+#endif /* not ORDINARY_LINK */
+#endif /* __GNUC__ */
+
+/* ARGSUSED */
+main (argc, argv, envp)
+ int argc;
+ char **argv;
+ char **envp;
+{
+ int skip_args = 0;
+ extern int errno;
+ extern void malloc_warning ();
+
+/* Map in shared memory, if we are using that. */
+#ifdef HAVE_SHM
+ if (argc > 1 && !strcmp (argv[1], "-nl"))
+ {
+ map_in_data (0);
+ /* The shared memory was just restored, which clobbered this. */
+ skip_args = 1;
+ }
+ else
+ {
+ map_in_data (1);
+ /* The shared memory was just restored, which clobbered this. */
+ skip_args = 0;
+ }
+#endif
+
+#ifdef VMS
+ /* If -map specified, map the data file in */
+ if (argc > 2 && ! strcmp (argv[1], "-map"))
+ {
+ skip_args = 2;
+ mapin_data (argv[2]);
+ }
+
+#ifdef LINK_CRTL_SHARE
+#ifdef SHAREABLE_LIB_BUG
+ /* Bletcherous shared libraries! */
+ if (!stdin)
+ stdin = fdopen (0, "r");
+ if (!stdout)
+ stdout = fdopen (1, "w");
+ if (!stderr)
+ stderr = fdopen (2, "w");
+ if (!environ)
+ environ = envp;
+#endif /* SHAREABLE_LIB_BUG */
+#endif /* LINK_CRTL_SHARE */
+#endif /* VMS */
+
+#ifdef USG_SHARED_LIBRARIES
+ if (bss_end)
+ brk (bss_end);
+#endif
+
+#ifdef NeXT
+ extern int malloc_cookie;
+
+ /* This helps out unexnext.c. */
+ if (initialized)
+ if (malloc_jumpstart (malloc_cookie) != 0)
+ printf ("malloc jumpstart failed!\n");
+#endif /* NeXT */
+
+ clearerr (stdin);
+
+#ifdef APOLLO
+#ifndef APOLLO_SR10
+ /* If USE_DOMAIN_ACLS environment variable exists,
+ use ACLs rather than UNIX modes. */
+ if (egetenv ("USE_DOMAIN_ACLS"))
+ default_acl (USE_DEFACL);
+#endif
+#endif /* APOLLO */
+
+#ifndef SYSTEM_MALLOC
+ /* Arrange for warnings when nearly out of space. */
+ malloc_init (0, malloc_warning);
+#endif
+
+#ifdef HIGHPRI
+ setpriority (PRIO_PROCESS, getpid (), HIGHPRI);
+ setuid (getuid ());
+#endif HIGHPRI
+
+ inhibit_window_system = 0;
+
+#ifdef HAVE_X_WINDOWS
+ xargv = argv;
+ xargc = argc;
+#endif
+
+/* Handle the -t switch, which specifies filename to use as terminal */
+ if (skip_args + 2 < argc && !strcmp (argv[skip_args + 1], "-t"))
+ {
+ skip_args += 2;
+ close (0);
+ close (1);
+ open (argv[skip_args], O_RDWR, 2 );
+ dup (0);
+ fprintf (stderr, "Using %s\n", argv[skip_args]);
+#ifdef HAVE_X_WINDOWS
+ inhibit_window_system = 1; /* -t => -nw */
+#endif
+ }
+#ifdef HAVE_X_WINDOWS
+/* Handle the -d switch, which means use a different display for X */
+ if (skip_args + 2 < argc && (!strcmp (argv[skip_args + 1], "-d") ||
+ !strcmp (argv[skip_args + 1], "-display")))
+ {
+ skip_args += 2;
+ alternate_display = argv[skip_args];
+ }
+ else
+ alternate_display = 0;
+#endif /* HAVE_X_WINDOWS */
+
+ if (skip_args + 1 < argc
+ && (!strcmp (argv[skip_args + 1], "-nw")))
+ {
+ skip_args += 1;
+ inhibit_window_system = 1;
+ }
+
+/* Handle the -batch switch, which means don't do interactive display. */
+ noninteractive = 0;
+ if (skip_args + 1 < argc && !strcmp (argv[skip_args + 1], "-batch"))
+ {
+ skip_args += 1;
+ noninteractive = 1;
+ }
+
+#ifdef POSIX_SIGNALS
+ init_signals ();
+#endif
+
+#ifdef HAVE_TZSET
+ /* Reinitialize the time zone if it was initialized before dumping Emacs. */
+ if (initialized)
+ tzset ();
+#endif
+
+ if (
+#ifndef CANNOT_DUMP
+ ! noninteractive || initialized
+#else
+ 1
+#endif
+ )
+ {
+ /* Don't catch these signals in batch mode if not initialized.
+ On some machines, this sets static data that would make
+ signal fail to work right when the dumped Emacs is run. */
+ signal (SIGHUP, fatal_error_signal);
+ signal (SIGQUIT, fatal_error_signal);
+ signal (SIGILL, fatal_error_signal);
+ signal (SIGTRAP, fatal_error_signal);
+ signal (SIGIOT, fatal_error_signal);
+#ifdef SIGEMT
+ signal (SIGEMT, fatal_error_signal);
+#endif
+ signal (SIGFPE, fatal_error_signal);
+ signal (SIGBUS, fatal_error_signal);
+ signal (SIGSEGV, fatal_error_signal);
+ signal (SIGSYS, fatal_error_signal);
+ signal (SIGTERM, fatal_error_signal);
+#ifdef SIGXCPU
+ signal (SIGXCPU, fatal_error_signal);
+#endif
+#ifdef SIGXFSZ
+ signal (SIGXFSZ, fatal_error_signal);
+#endif SIGXFSZ
+
+#ifdef AIX
+ /* This used to run fatal_error_signal,
+ but it isn't fatal. There's nothing Emacs can usefully do.
+ Might as well let the system kill us if it insists. */
+ signal (SIGDANGER, SIG_IGN);
+ signal (20, fatal_error_signal);
+ signal (21, fatal_error_signal);
+ signal (22, fatal_error_signal);
+ signal (23, fatal_error_signal);
+ signal (24, fatal_error_signal);
+#ifdef SIGIO
+ signal (SIGAIO, fatal_error_signal);
+ signal (SIGPTY, fatal_error_signal);
+#endif
+#ifdef SIGURG
+ /* Note that SIGIOINT is the same as SIGIO on some machines,
+ and the same as SIGURG on others. It seems ore reliable to use the
+ name with a uniform meaning. */
+ signal (SIGURG, fatal_error_signal);
+#endif
+ signal (SIGGRANT, fatal_error_signal);
+ signal (SIGRETRACT, fatal_error_signal);
+ signal (SIGSOUND, fatal_error_signal);
+ signal (SIGMSG, fatal_error_signal);
+#endif /* AIX */
+ }
+
+ noninteractive1 = noninteractive;
+
+/* Perform basic initializations (not merely interning symbols) */
+
+ if (!initialized)
+ {
+ init_alloc_once ();
+ init_obarray ();
+ init_eval_once ();
+ init_syntax_once (); /* Create standard syntax table. */
+ /* Must be done before init_buffer */
+ init_buffer_once (); /* Create buffer table and some buffers */
+ init_minibuf_once (); /* Create list of minibuffers */
+ /* Must precede init_window_once */
+ init_window_once (); /* Init the window system */
+ }
+
+ init_alloc ();
+#ifdef MAINTAIN_ENVIRONMENT
+ init_environ ();
+#endif
+ init_eval ();
+ init_data ();
+ init_read ();
+
+ init_cmdargs (argc, argv, skip_args); /* Create list Vcommand_line_args */
+ init_buffer (); /* Init default directory of main buffer */
+ if (!noninteractive)
+ {
+#ifdef VMS
+ init_vms_input ();/* init_display calls get_screen_size, that needs this */
+#endif /* VMS */
+ init_display (); /* Determine terminal type. init_sys_modes uses results */
+ }
+ init_keyboard (); /* This too must precede init_sys_modes */
+ init_callproc (); /* And this too. */
+ init_sys_modes (); /* Init system terminal modes (RAW or CBREAK, etc.) */
+ init_xdisp ();
+ init_macros ();
+ init_editfns ();
+#ifdef VMS
+ init_vmsfns ();
+#endif /* VMS */
+#ifdef subprocesses
+ init_process ();
+#endif /* subprocesses */
+
+/* Intern the names of all standard functions and variables; define standard keys */
+
+ if (!initialized)
+ {
+ /* The basic levels of Lisp must come first */
+ /* And data must come first of all
+ for the sake of symbols like error-message */
+ syms_of_data ();
+ syms_of_alloc ();
+#ifdef MAINTAIN_ENVIRONMENT
+ syms_of_environ ();
+#endif MAINTAIN_ENVIRONMENT
+ syms_of_read ();
+ syms_of_print ();
+ syms_of_eval ();
+ syms_of_fns ();
+
+ syms_of_abbrev ();
+ syms_of_buffer ();
+ syms_of_bytecode ();
+ syms_of_callint ();
+ syms_of_casefiddle ();
+ syms_of_callproc ();
+ syms_of_cmds ();
+#ifndef NO_DIR_LIBRARY
+ syms_of_dired ();
+#endif /* not NO_DIR_LIBRARY */
+ syms_of_display ();
+ syms_of_doc ();
+ syms_of_editfns ();
+ syms_of_emacs ();
+ syms_of_fileio ();
+#ifdef CLASH_DETECTION
+ syms_of_filelock ();
+#endif /* CLASH_DETECTION */
+ syms_of_indent ();
+ syms_of_keyboard ();
+ syms_of_keymap ();
+ syms_of_macros ();
+ syms_of_marker ();
+ syms_of_minibuf ();
+ syms_of_mocklisp ();
+#ifdef subprocesses
+ syms_of_process ();
+#endif /* subprocesses */
+ syms_of_search ();
+ syms_of_syntax ();
+ syms_of_undo ();
+ syms_of_window ();
+ syms_of_xdisp ();
+#ifdef HAVE_X_WINDOWS
+ syms_of_xfns ();
+#ifdef HAVE_X_MENU
+ syms_of_xmenu ();
+#endif /* HAVE_X_MENU */
+#endif /* HAVE_X_WINDOWS */
+
+#ifdef SYMS_SYSTEM
+ SYMS_SYSTEM;
+#endif
+
+#ifdef SYMS_MACHINE
+ SYMS_MACHINE;
+#endif
+
+ keys_of_casefiddle ();
+ keys_of_cmds ();
+ keys_of_buffer ();
+ keys_of_keyboard ();
+ keys_of_keymap ();
+ keys_of_macros ();
+ keys_of_minibuf ();
+ keys_of_window ();
+ }
+
+ if (!initialized)
+ {
+ /* Handle -l loadup-and-dump, args passed by Makefile. */
+ if (argc > 2 + skip_args && !strcmp (argv[1 + skip_args], "-l"))
+ Vtop_level = Fcons (intern ("load"),
+ Fcons (build_string (argv[2 + skip_args]), Qnil));
+#ifdef CANNOT_DUMP
+ /* Unless next switch is -nl, load "loadup.el" first thing. */
+ if (!(argc > 1 + skip_args && !strcmp (argv[1 + skip_args], "-nl")))
+ Vtop_level = Fcons (intern ("load"),
+ Fcons (build_string ("loadup.el"), Qnil));
+#endif /* CANNOT_DUMP */
+ }
+
+ initialized = 1;
+
+ /* Enter editor command loop. This never returns. */
+ Frecursive_edit ();
+ /* NOTREACHED */
+}
+
+DEFUN ("kill-emacs", Fkill_emacs, Skill_emacs, 0, 1, "P",
+ "Exit the Emacs job and kill it. ARG means no query.\n\
+If emacs is running noninteractively and ARG is an integer,\n\
+return ARG as the exit program code.")
+ (arg)
+ Lisp_Object arg;
+{
+ Lisp_Object answer;
+ int i;
+ struct gcpro gcpro1;
+
+ GCPRO1 (arg);
+
+ if (!EQ (Vkill_emacs_hook, Qnil))
+ call0 (Vkill_emacs_hook);
+
+ if (feof (stdin))
+ arg = Qt;
+
+#ifdef subprocesses
+ kill_buffer_processes (Qnil);
+#endif /* subprocesses */
+
+#ifdef VMS
+ kill_vms_processes ();
+#endif /* VMS */
+
+ Fdo_auto_save (Qt);
+
+#ifdef CLASH_DETECTION
+ unlock_all_files ();
+#endif /* CLASH_DETECTION */
+
+ fflush (stdout);
+ reset_sys_modes ();
+ UNGCPRO;
+
+/* Is it really necessary to do this deassign
+ when we are going to exit anyway? */
+/* #ifdef VMS
+ stop_vms_input ();
+ #endif */
+ stuff_buffered_input (arg);
+#ifdef SIGIO
+ /* There is a tendency for a SIGIO signal to arrive within exit,
+ and cause a SIGHUP because the input descriptor is already closed. */
+ unrequest_sigio ();
+ signal (SIGIO, SIG_IGN);
+#endif
+ exit ((XTYPE (arg) == Lisp_Int) ? XINT (arg)
+#ifdef VMS
+ : 1
+#else
+ : 0
+#endif
+ );
+ /* NOTREACHED */
+}
+
+#ifndef CANNOT_DUMP
+/* Nothing like this can be implemented on an Apollo.
+ What a loss! */
+
+#ifdef HAVE_SHM
+
+DEFUN ("dump-emacs-data", Fdump_emacs_data, Sdump_emacs_data, 1, 1, 0,
+ "Dump current state of Emacs into data file FILENAME.\n\
+This function exists on systems that use HAVE_SHM.")
+ (intoname)
+ Lisp_Object intoname;
+{
+ extern int my_edata;
+ Lisp_Object tem;
+ extern void malloc_warning ();
+
+ CHECK_STRING (intoname, 0);
+ intoname = Fexpand_file_name (intoname, Qnil);
+
+ tem = Vpurify_flag;
+ Vpurify_flag = Qnil;
+
+ fflush (stdout);
+ /* Tell malloc where start of impure now is */
+ /* Also arrange for warnings when nearly out of space. */
+#ifndef SYSTEM_MALLOC
+ malloc_init (&my_edata, malloc_warning);
+#endif
+ map_out_data (XSTRING (intoname)->data);
+
+ Vpurify_flag = tem;
+
+ return Qnil;
+}
+
+#else /* not HAVE_SHM */
+
+DEFUN ("dump-emacs", Fdump_emacs, Sdump_emacs, 2, 2, 0,
+ "Dump current state of Emacs into executable file FILENAME.\n\
+Take symbols from SYMFILE (presumably the file you executed to run Emacs).")
+ (intoname, symname)
+ Lisp_Object intoname, symname;
+{
+ extern int my_edata;
+ Lisp_Object tem;
+ extern void malloc_warning ();
+
+ CHECK_STRING (intoname, 0);
+ intoname = Fexpand_file_name (intoname, Qnil);
+ if (!EQ (symname, Qnil))
+ {
+ CHECK_STRING (symname, 0);
+ if (XSTRING (symname)->size)
+ symname = Fexpand_file_name (symname, Qnil);
+ }
+
+ tem = Vpurify_flag;
+ Vpurify_flag = Qnil;
+
+ fflush (stdout);
+#ifdef VMS
+ mapout_data (XSTRING (intoname)->data);
+#else
+ /* Tell malloc where start of impure now is */
+ /* Also arrange for warnings when nearly out of space. */
+#ifndef SYSTEM_MALLOC
+ malloc_init (&my_edata, malloc_warning);
+#endif
+ unexec (XSTRING (intoname)->data,
+ !EQ (symname, Qnil) ? XSTRING (symname)->data : 0, &my_edata, 0, 0);
+#endif /* not VMS */
+
+ Vpurify_flag = tem;
+
+ return Qnil;
+}
+
+#endif /* not HAVE_SHM */
+
+#endif /* not CANNOT_DUMP */
+
+#ifdef VMS
+#define SEPCHAR ','
+#else
+#define SEPCHAR ':'
+#endif
+
+Lisp_Object
+decode_env_path (evarname, defalt)
+ char *evarname, *defalt;
+{
+ register char *path, *p;
+ extern char *index ();
+
+ Lisp_Object lpath;
+
+ if (evarname != 0)
+ path = (char *) egetenv (evarname);
+ else
+ path = 0;
+ if (!path)
+ path = defalt;
+ lpath = Qnil;
+ while (1)
+ {
+ p = index (path, SEPCHAR);
+ if (!p) p = path + strlen (path);
+ lpath = Fcons (p - path ? make_string (path, p - path) : Qnil,
+ lpath);
+ if (*p)
+ path = p + 1;
+ else
+ break;
+ }
+ return Fnreverse (lpath);
+}
+
+syms_of_emacs ()
+{
+#ifndef CANNOT_DUMP
+#ifdef HAVE_SHM
+ defsubr (&Sdump_emacs_data);
+#else
+ defsubr (&Sdump_emacs);
+#endif
+#endif /* not CANNOT_DUMP */
+
+ defsubr (&Skill_emacs);
+
+ DEFVAR_LISP ("command-line-args", &Vcommand_line_args,
+ "Args passed by shell to Emacs, as a list of strings.");
+
+ DEFVAR_LISP ("system-type", &Vsystem_type,
+ "Symbol indicating type of operating system you are using.");
+ Vsystem_type = intern (SYSTEM_TYPE);
+
+ DEFVAR_BOOL ("noninteractive", &noninteractive1,
+ "Non-nil means Emacs is running without interactive terminal.");
+
+ Vkill_emacs_hook = Qnil;
+
+ DEFVAR_LISP ("kill-emacs-hook", &Vkill_emacs_hook,
+ "Function called, if non-nil, whenever kill-emacs is called.");
+}
diff --git a/src/emacssignal.h b/src/emacssignal.h
new file mode 100644
index 00000000000..f65a7bb53da
--- /dev/null
+++ b/src/emacssignal.h
@@ -0,0 +1,57 @@
+#ifdef POSIX_SIGNALS
+
+#define SIGMASKTYPE sigset_t
+#define SIGEMPTYMASK (signal_empty_mask)
+#define SIGFULLMASK (signal_full_mask)
+extern sigset_t signal_empty_mask, signal_full_mask;
+
+#ifdef sigmask
+#undef sigmask
+#endif
+#define sigmask(SIG) \
+(_mask = SIGEMPTYMASK, sigaddset (&_mask, SIG), _mask)
+
+/* Local mask is used to avoid problems if code using any of the macros
+ below could be reentered due to a signal occurring.
+ This can't happen in Emacs 18.58, but just to be safe... - DJB
+ These macros require GCC. */
+#define sigpause(SIG) ({ sigset_t _mask; sys_sigpause(SIG); })
+#define sigblock(SIG) ({ sigset_t _mask; sys_sigblock(SIG); })
+#define sigunblock(SIG) ({ sigset_t _mask; sys_sigunblock(SIG); })
+#define sigsetmask(SIG) ({ sigset_t _mask; sys_sigsetmask(SIG); })
+#define sighold(SIG) ONLY_USED_IN_BSD_4_1
+#define sigrelse(SIG) ONLY_USED_IN_BSD_4_1
+
+int (*sys_signal (int signal_number, int (*action)())) ();
+int sys_sigpause (sigset_t new_mask);
+sigset_t sys_sigblock (sigset_t new_mask);
+sigset_t sys_sigunblock (sigset_t new_mask);
+sigset_t sys_sigsetmask (sigset_t new_mask);
+
+#define sys_sigdel(MASK,SIG) sigdelset(&MASK,SIG)
+#endif /* POSIX_SIGNALS */
+
+#ifndef SIGMASKTYPE
+#define SIGMASKTYPE int
+#endif
+
+#ifndef SIGEMPTYMASK
+#define SIGEMPTYMASK 0
+#endif
+
+#ifndef SIGFULLMASK
+#define SIGFULLMASK 0xffffffff
+#endif
+
+#ifndef sigmask
+#define sigmask(no) (1L << ((no) - 1))
+#endif
+
+#ifndef sigunblock
+#define sigunblock(SIG) \
+{ SIGMASKTYPE omask = sigblock (SIGFULLMASK); sigsetmask (omask & ~SIG); }
+#endif
+
+#ifndef sys_sigdel
+#define sys_sigdel(MASK,SIG) MASK &= ~(1 << SIG)
+#endif
diff --git a/src/environ.c b/src/environ.c
index 863f40ccd2a..7cd8e20f38c 100644
--- a/src/environ.c
+++ b/src/environ.c
@@ -283,8 +283,9 @@ VAR is a string, the name of the variable,\n\
DEFUN ("setenv", Fsetenv, Ssetenv, 1, 2,
"sEnvironment variable: \nsSet %s to value: ",
- "Set the value of environment variable VAR to VALUE.\n\
-Both args must be strings. Returns VALUE.")
+ "Return the value of environment variable VAR, as a string.\n\
+When invoked interactively, print the value in the echo area.\n\
+VAR is a string, the name of the variable.")
(str, val)
Lisp_Object str;
Lisp_Object val;
diff --git a/src/eval.c b/src/eval.c
new file mode 100644
index 00000000000..65eb612bbcd
--- /dev/null
+++ b/src/eval.c
@@ -0,0 +1,2222 @@
+/* Evaluator for GNU Emacs Lisp interpreter.
+ Copyright (C) 1985, 1986, 1987, 1990 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#include "config.h"
+#include "lisp.h"
+
+#ifndef standalone
+#include "commands.h"
+#else
+#define FROM_KBD 1
+#endif
+
+#include <setjmp.h>
+
+/* This definition is duplicated in alloc.c and keyboard.c */
+/* Putting it in lisp.h makes cc bomb out! */
+
+struct backtrace
+ {
+ struct backtrace *next;
+ Lisp_Object *function;
+ Lisp_Object *args; /* Points to vector of args. */
+ int nargs; /* length of vector */
+ /* if nargs is UNEVALLED, args points to slot holding list of unevalled args */
+ char evalargs;
+ /* Nonzero means call value of debugger when done with this operation. */
+ char debug_on_exit;
+ };
+
+struct backtrace *backtrace_list;
+
+struct catchtag
+ {
+ Lisp_Object tag;
+ Lisp_Object val;
+ struct catchtag *next;
+ struct gcpro *gcpro;
+ jmp_buf jmp;
+ struct backtrace *backlist;
+ struct handler *handlerlist;
+ int lisp_eval_depth;
+ int pdlcount;
+ int poll_suppress_count;
+ };
+
+struct catchtag *catchlist;
+
+Lisp_Object Qautoload, Qmacro, Qexit, Qinteractive, Qcommandp, Qdefun;
+Lisp_Object Vquit_flag, Vinhibit_quit, Qinhibit_quit;
+Lisp_Object Qmocklisp_arguments, Vmocklisp_arguments, Qmocklisp;
+Lisp_Object Qand_rest, Qand_optional;
+
+/* Non-nil means record all fset's and provide's, to be undone
+ if the file being autoloaded is not fully loaded.
+ They are recorded by being consed onto the front of Vautoload_queue:
+ (FUN . ODEF) for a defun, (OFEATURES . nil) for a provide. */
+
+Lisp_Object Vautoload_queue;
+
+/* Current number of specbindings allocated in specpdl. */
+
+int specpdl_size;
+
+/* Pointer to beginning of specpdl. */
+
+struct specbinding *specpdl;
+
+/* Pointer to first unused element in specpdl. */
+
+struct specbinding *specpdl_ptr;
+
+/* Maximum size allowed for specpdl allocation */
+
+int max_specpdl_size;
+
+/* Depth in Lisp evaluations and function calls. */
+
+int lisp_eval_depth;
+
+/* Maximum allowed depth in Lisp evaluations and function calls. */
+
+int max_lisp_eval_depth;
+
+/* Nonzero means enter debugger before next function call */
+int debug_on_next_call;
+
+/* Nonzero means display a backtrace if an error
+ is handled by the command loop's error handler. */
+int stack_trace_on_error;
+
+/* Nonzero means enter debugger if an error
+ is handled by the command loop's error handler. */
+int debug_on_error;
+
+/* Nonzero means enter debugger if a quit signal
+ is handled by the command loop's error handler. */
+int debug_on_quit;
+
+Lisp_Object Vdebugger;
+
+void specbind (), unbind_to (), record_unwind_protect ();
+
+Lisp_Object funcall_lambda ();
+extern Lisp_Object ml_apply (); /* Apply a mocklisp function to unevaluated argument list */
+
+init_eval_once ()
+{
+ specpdl_size = 50;
+ specpdl = (struct specbinding *) malloc (specpdl_size * sizeof (struct specbinding));
+ max_specpdl_size = 600;
+ max_lisp_eval_depth = 200;
+}
+
+init_eval ()
+{
+ specpdl_ptr = specpdl;
+ catchlist = 0;
+ handlerlist = 0;
+ backtrace_list = 0;
+ Vquit_flag = Qnil;
+ debug_on_next_call = 0;
+ lisp_eval_depth = 0;
+}
+
+Lisp_Object
+call_debugger (arg)
+ Lisp_Object arg;
+{
+ if (lisp_eval_depth + 20 > max_lisp_eval_depth)
+ max_lisp_eval_depth = lisp_eval_depth + 20;
+ if (specpdl_size + 40 > max_specpdl_size)
+ max_specpdl_size = specpdl_size + 40;
+ debug_on_next_call = 0;
+ return apply1 (Vdebugger, arg);
+}
+
+do_debug_on_call (code)
+ Lisp_Object code;
+{
+ debug_on_next_call = 0;
+ backtrace_list->debug_on_exit = 1;
+ call_debugger (Fcons (code, Qnil));
+}
+
+/* NOTE!!! Every function that can call EVAL must protect its args
+ and temporaries from garbage collection while it needs them.
+ The definition of `For' shows what you have to do. */
+
+DEFUN ("or", For, Sor, 0, UNEVALLED, 0,
+ "Eval args until one of them yields non-NIL, then return that value.\n\
+The remaining args are not evalled at all.\n\
+If all args return NIL, return NIL.")
+ (args)
+ Lisp_Object args;
+{
+ register Lisp_Object val;
+ Lisp_Object args_left;
+ struct gcpro gcpro1;
+
+ if (NULL(args))
+ return Qnil;
+
+ args_left = args;
+ GCPRO1 (args_left);
+
+ do
+ {
+ val = Feval (Fcar (args_left));
+ if (!NULL (val))
+ break;
+ args_left = Fcdr (args_left);
+ }
+ while (!NULL(args_left));
+
+ UNGCPRO;
+ return val;
+}
+
+DEFUN ("and", Fand, Sand, 0, UNEVALLED, 0,
+ "Eval args until one of them yields NIL, then return NIL.\n\
+The remaining args are not evalled at all.\n\
+If no arg yields NIL, return the last arg's value.")
+ (args)
+ Lisp_Object args;
+{
+ register Lisp_Object val;
+ Lisp_Object args_left;
+ struct gcpro gcpro1;
+
+ if (NULL(args))
+ return Qt;
+
+ args_left = args;
+ GCPRO1 (args_left);
+
+ do
+ {
+ val = Feval (Fcar (args_left));
+ if (NULL (val))
+ break;
+ args_left = Fcdr (args_left);
+ }
+ while (!NULL(args_left));
+
+ UNGCPRO;
+ return val;
+}
+
+DEFUN ("if", Fif, Sif, 2, UNEVALLED, 0,
+ "(if C T E...) if C yields non-NIL do T, else do E...\n\
+Returns the value of T or the value of the last of the E's.\n\
+There may be no E's; then if C yields NIL, the value is NIL.")
+ (args)
+ Lisp_Object args;
+{
+ register Lisp_Object cond;
+ struct gcpro gcpro1;
+
+ GCPRO1 (args);
+ cond = Feval (Fcar (args));
+ UNGCPRO;
+
+ if (!NULL (cond))
+ return Feval (Fcar (Fcdr (args)));
+ return Fprogn (Fcdr (Fcdr (args)));
+}
+
+DEFUN ("cond", Fcond, Scond, 0, UNEVALLED, 0,
+ "(cond CLAUSES...) tries each clause until one succeeds.\n\
+Each clause looks like (C BODY...). C is evaluated\n\
+and, if the value is non-nil, this clause succeeds:\n\
+then the expressions in BODY are evaluated and the last one's\n\
+value is the value of the cond expression.\n\
+If a clause looks like (C), C's value if non-nil is returned from cond.\n\
+If no clause succeeds, cond returns nil.")
+ (args)
+ Lisp_Object args;
+{
+ register Lisp_Object clause, val;
+ struct gcpro gcpro1;
+
+ GCPRO1 (args);
+ while (!NULL (args))
+ {
+ clause = Fcar (args);
+ val = Feval (Fcar (clause));
+ if (!NULL (val))
+ {
+ if (!EQ (XCONS (clause)->cdr, Qnil))
+ val = Fprogn (XCONS (clause)->cdr);
+ break;
+ }
+ args = XCONS (args)->cdr;
+ }
+ UNGCPRO;
+
+ return val;
+}
+
+DEFUN ("progn", Fprogn, Sprogn, 0, UNEVALLED, 0,
+ "Eval arguments in sequence, and return the value of the last one.")
+ (args)
+ Lisp_Object args;
+{
+ register Lisp_Object val, tem;
+ Lisp_Object args_left;
+ struct gcpro gcpro1;
+
+ /* In Mocklisp code, symbols at the front of the progn arglist
+ are to be bound to zero. */
+ if (!EQ (Vmocklisp_arguments, Qt))
+ {
+ val = make_number (0);
+ while (!NULL (args) && (tem = Fcar (args), XTYPE (tem) == Lisp_Symbol))
+ {
+ QUIT;
+ specbind (tem, val), args = Fcdr (args);
+ }
+ }
+
+ if (NULL(args))
+ return Qnil;
+
+ args_left = args;
+ GCPRO1 (args_left);
+
+ do
+ {
+ val = Feval (Fcar (args_left));
+ args_left = Fcdr (args_left);
+ }
+ while (!NULL(args_left));
+
+ UNGCPRO;
+ return val;
+}
+
+DEFUN ("prog1", Fprog1, Sprog1, 1, UNEVALLED, 0,
+ "Eval arguments in sequence, then return the FIRST arg's value.\n\
+This value is saved during the evaluation of the remaining args,\n\
+whose values are discarded.")
+ (args)
+ Lisp_Object args;
+{
+ Lisp_Object val;
+ register Lisp_Object args_left;
+ struct gcpro gcpro1, gcpro2;
+ register int argnum = 0;
+
+ if (NULL(args))
+ return Qnil;
+
+ args_left = args;
+ val = Qnil;
+ GCPRO2 (args, val);
+
+ do
+ {
+ if (!(argnum++))
+ val = Feval (Fcar (args_left));
+ else
+ Feval (Fcar (args_left));
+ args_left = Fcdr (args_left);
+ }
+ while (!NULL(args_left));
+
+ UNGCPRO;
+ return val;
+}
+
+DEFUN ("prog2", Fprog2, Sprog2, 2, UNEVALLED, 0,
+ "Eval arguments in sequence, then return the SECOND arg's value.\n\
+This value is saved during the evaluation of the remaining args,\n\
+whose values are discarded.")
+ (args)
+ Lisp_Object args;
+{
+ Lisp_Object val;
+ register Lisp_Object args_left;
+ struct gcpro gcpro1, gcpro2;
+ register int argnum = -1;
+
+ val = Qnil;
+
+ if (NULL(args))
+ return Qnil;
+
+ args_left = args;
+ val = Qnil;
+ GCPRO2 (args, val);
+
+ do
+ {
+ if (!(argnum++))
+ val = Feval (Fcar (args_left));
+ else
+ Feval (Fcar (args_left));
+ args_left = Fcdr (args_left);
+ }
+ while (!NULL(args_left));
+
+ UNGCPRO;
+ return val;
+}
+
+DEFUN ("setq", Fsetq, Ssetq, 0, UNEVALLED, 0,
+ "(setq SYM VAL SYM VAL ...) sets each SYM to the value of its VAL.\n\
+The SYMs are not evaluated. Thus (setq x y) sets x to the value of y.\n\
+Each SYM is set before the next VAL is computed.")
+ (args)
+ Lisp_Object args;
+{
+ register Lisp_Object args_left;
+ register Lisp_Object val, sym;
+ struct gcpro gcpro1;
+
+ if (NULL(args))
+ return Qnil;
+
+ args_left = args;
+ GCPRO1 (args);
+
+ do
+ {
+ val = Feval (Fcar (Fcdr (args_left)));
+ sym = Fcar (args_left);
+ Fset (sym, val);
+ args_left = Fcdr (Fcdr (args_left));
+ }
+ while (!NULL(args_left));
+
+ UNGCPRO;
+ return val;
+}
+
+DEFUN ("quote", Fquote, Squote, 1, UNEVALLED, 0,
+ "Return the argument, without evaluating it. (quote x) yields x.")
+ (args)
+ Lisp_Object args;
+{
+ return Fcar (args);
+}
+
+DEFUN ("function", Ffunction, Sfunction, 1, UNEVALLED, 0,
+ "Quote a function object.\n\
+Equivalent to the quote function in the interpreter,\n\
+but causes the compiler to compile the argument as a function\n\
+if it is not a symbol.")
+ (args)
+ Lisp_Object args;
+{
+ return Fcar (args);
+}
+
+DEFUN ("interactive-p", Finteractive_p, Sinteractive_p, 0, 0, 0,
+ "Return t if function in which this appears was called interactively.\n\
+This means that the function was called with call-interactively (which\n\
+includes being called as the binding of a key)\n\
+and input is currently coming from the keyboard (not in keyboard macro).")
+ ()
+{
+ register struct backtrace *btp;
+ register Lisp_Object fun;
+
+ if (!FROM_KBD)
+ return Qnil;
+ /* Skip the frame of interactive-p itself (if interpreted)
+ or the frame of byte-code (if called from compiled function). */
+ for (btp = backtrace_list->next;
+ btp && (btp->nargs == UNEVALLED
+ || EQ (*btp->function, Qbytecode));
+ btp = btp->next)
+ {}
+ /* btp now points at the frame of the innermost function
+ that DOES eval its args.
+ If it is a built-in function (such as load or eval-region)
+ return nil. */
+ fun = *btp->function;
+ while (XTYPE (fun) == Lisp_Symbol)
+ {
+ QUIT;
+ fun = Fsymbol_function (fun);
+ }
+ if (XTYPE (fun) == Lisp_Subr)
+ return Qnil;
+ /* btp points to the frame of a Lisp function that called interactive-p.
+ Return t if that function was called interactively. */
+ if (btp && btp->next && EQ (*btp->next->function, Qcall_interactively))
+ return Qt;
+ return Qnil;
+}
+
+DEFUN ("defun", Fdefun, Sdefun, 2, UNEVALLED, 0,
+ "(defun NAME ARGLIST [DOCSTRING] BODY...) defines NAME as a function.\n\
+The definition is (lambda ARGLIST [DOCSTRING] BODY...).\n\
+See also the function interactive .")
+ (args)
+ Lisp_Object args;
+{
+ register Lisp_Object fn_name;
+ register Lisp_Object defn;
+
+ fn_name = Fcar (args);
+ defn = Fcons (Qlambda, Fcdr (args));
+ if (!NULL (Vpurify_flag))
+ defn = Fpurecopy (defn);
+ Ffset (fn_name, defn);
+ return fn_name;
+}
+
+DEFUN ("defmacro", Fdefmacro, Sdefmacro, 2, UNEVALLED, 0,
+ "(defmacro NAME ARGLIST [DOCSTRING] BODY...) defines NAME as a macro.\n\
+The definition is (macro lambda ARGLIST [DOCSTRING] BODY...).\n\
+When the macro is called, as in (NAME ARGS...),\n\
+the function (lambda ARGLIST BODY...) is applied to\n\
+the list ARGS... as it appears in the expression,\n\
+and the result should be a form to be evaluated instead of the original.")
+ (args)
+ Lisp_Object args;
+{
+ register Lisp_Object fn_name;
+ register Lisp_Object defn;
+
+ fn_name = Fcar (args);
+ defn = Fcons (Qmacro, Fcons (Qlambda, Fcdr (args)));
+ if (!NULL (Vpurify_flag))
+ defn = Fpurecopy (defn);
+ Ffset (fn_name, defn);
+ return fn_name;
+}
+
+DEFUN ("defvar", Fdefvar, Sdefvar, 1, UNEVALLED, 0,
+ "(defvar SYMBOL INITVALUE DOCSTRING) defines SYMBOL as an advertised variable.\n\
+INITVALUE is evaluated, and used to set SYMBOL, only if SYMBOL's value is void.\n\
+INITVALUE and DOCSTRING are optional.\n\
+If DOCSTRING starts with *, this variable is identified as a user option.\n\
+ This means that M-x set-variable and M-x edit-options recognize it.\n\
+If INITVALUE is missing, SYMBOL's value is not set.")
+ (args)
+ Lisp_Object args;
+{
+ register Lisp_Object sym, tem;
+
+ sym = Fcar (args);
+ tem = Fcdr (args);
+ if (!NULL (tem))
+ {
+ tem = Fboundp (sym);
+ if (NULL (tem))
+ Fset (sym, Feval (Fcar (Fcdr (args))));
+ }
+ tem = Fcar (Fcdr (Fcdr (args)));
+ if (!NULL (tem))
+ {
+ if (!NULL (Vpurify_flag))
+ tem = Fpurecopy (tem);
+ Fput (sym, Qvariable_documentation, tem);
+ }
+ return sym;
+}
+
+DEFUN ("defconst", Fdefconst, Sdefconst, 2, UNEVALLED, 0,
+ "(defconst SYMBOL INITVALUE DOCSTRING) defines SYMBOL as a constant variable.\n\
+The intent is that programs do not change this value (but users may).\n\
+Always sets the value of SYMBOL to the result of evalling INITVALUE.\n\
+DOCSTRING is optional.\n\
+If DOCSTRING starts with *, this variable is identified as a user option.\n\
+ This means that M-x set-variable and M-x edit-options recognize it.")
+ (args)
+ Lisp_Object args;
+{
+ register Lisp_Object sym, tem;
+
+ sym = Fcar (args);
+ Fset (sym, Feval (Fcar (Fcdr (args))));
+ tem = Fcar (Fcdr (Fcdr (args)));
+ if (!NULL (tem))
+ {
+ if (!NULL (Vpurify_flag))
+ tem = Fpurecopy (tem);
+ Fput (sym, Qvariable_documentation, tem);
+ }
+ return sym;
+}
+
+DEFUN ("user-variable-p", Fuser_variable_p, Suser_variable_p, 1, 1, 0,
+ "Returns t if VARIABLE is intended to be set and modified by users,\n\
+as opposed to by programs.\n\
+Determined by whether the first character of the documentation\n\
+for the variable is \"*\"")
+ (variable)
+ Lisp_Object variable;
+{
+ Lisp_Object documentation;
+
+ documentation = Fget (variable, Qvariable_documentation);
+ if (XTYPE (documentation) == Lisp_Int && XINT (documentation) < 0)
+ return Qt;
+ if ((XTYPE (documentation) == Lisp_String) &&
+ ((unsigned char) XSTRING (documentation)->data[0] == '*'))
+ return Qt;
+ return Qnil;
+}
+
+DEFUN ("let*", FletX, SletX, 1, UNEVALLED, 0,
+ "(let* VARLIST BODY...) binds variables according to VARLIST then executes BODY.\n\
+The value of the last form in BODY is returned.\n\
+Each element of VARLIST is a symbol (which is bound to NIL)\n\
+or a list (SYMBOL VALUEFORM) (which binds SYMBOL to the value of VALUEFORM).\n\
+Each VALUEFORM can refer to the symbols already bound by this VARLIST.")
+ (args)
+ Lisp_Object args;
+{
+ Lisp_Object varlist, val, elt;
+ int count = specpdl_ptr - specpdl;
+ struct gcpro gcpro1, gcpro2, gcpro3;
+
+ GCPRO3 (args, elt, varlist);
+
+ varlist = Fcar (args);
+ while (!NULL (varlist))
+ {
+ QUIT;
+ elt = Fcar (varlist);
+ if (XTYPE (elt) == Lisp_Symbol)
+ specbind (elt, Qnil);
+ else
+ {
+ val = Feval (Fcar (Fcdr (elt)));
+ specbind (Fcar (elt), val);
+ }
+ varlist = Fcdr (varlist);
+ }
+ UNGCPRO;
+ val = Fprogn (Fcdr (args));
+ unbind_to (count);
+ return val;
+}
+
+DEFUN ("let", Flet, Slet, 1, UNEVALLED, 0,
+ "(let VARLIST BODY...) binds variables according to VARLIST then executes BODY.\n\
+The value of the last form in BODY is returned.\n\
+Each element of VARLIST is a symbol (which is bound to NIL)\n\
+or a list (SYMBOL VALUEFORM) (which binds SYMBOL to the value of VALUEFORM).\n\
+All the VALUEFORMs are evalled before any symbols are bound.")
+ (args)
+ Lisp_Object args;
+{
+ Lisp_Object *temps, tem;
+ register Lisp_Object elt, varlist;
+ int count = specpdl_ptr - specpdl;
+ register int argnum;
+ struct gcpro gcpro1, gcpro2;
+
+ varlist = Fcar (args);
+
+ /* Make space to hold the values to give the bound variables */
+ elt = Flength (varlist);
+ temps = (Lisp_Object *) alloca (XFASTINT (elt) * sizeof (Lisp_Object));
+
+ /* Compute the values and store them in `temps' */
+
+ GCPRO2 (args, *temps);
+ gcpro2.nvars = 0;
+
+ for (argnum = 0; !NULL (varlist); varlist = Fcdr (varlist))
+ {
+ QUIT;
+ elt = Fcar (varlist);
+ if (XTYPE (elt) == Lisp_Symbol)
+ temps [argnum++] = Qnil;
+ else
+ temps [argnum++] = Feval (Fcar (Fcdr (elt)));
+ gcpro2.nvars = argnum;
+ }
+ UNGCPRO;
+
+ varlist = Fcar (args);
+ for (argnum = 0; !NULL (varlist); varlist = Fcdr (varlist))
+ {
+ elt = Fcar (varlist);
+ tem = temps[argnum++];
+ if (XTYPE (elt) == Lisp_Symbol)
+ specbind (elt, tem);
+ else
+ specbind (Fcar (elt), tem);
+ }
+
+ elt = Fprogn (Fcdr (args));
+ unbind_to (count);
+ return elt;
+}
+
+DEFUN ("while", Fwhile, Swhile, 1, UNEVALLED, 0,
+ "(while TEST BODY...) if TEST yields non-NIL, execute the BODY forms and repeat.")
+ (args)
+ Lisp_Object args;
+{
+ Lisp_Object test, body, tem;
+ struct gcpro gcpro1, gcpro2;
+
+ GCPRO2 (test, body);
+
+ test = Fcar (args);
+ body = Fcdr (args);
+ while (tem = Feval (test), !NULL (tem))
+ {
+ QUIT;
+ Fprogn (body);
+ }
+
+ UNGCPRO;
+ return Qnil;
+}
+
+DEFUN ("macroexpand", Fmacroexpand, Smacroexpand, 1, 2, 0,
+ "If FORM is a macro call, expand it.\n\
+If the result of expansion is another macro call, expand it, etc.\n\
+Return the ultimate expansion.\n\
+The second optional arg ENVIRONMENT species an environment of macro\n\
+definitions to shadow the loaded ones for use in file byte-compilation.")
+ (form, env)
+ register Lisp_Object form;
+ Lisp_Object env;
+{
+ register Lisp_Object expander, sym, def, tem;
+
+ while (1)
+ {
+ /* Come back here each time we expand a macro call,
+ in case it expands into another macro call. */
+ if (XTYPE (form) != Lisp_Cons)
+ break;
+ sym = XCONS (form)->car;
+ if (XTYPE (sym) != Lisp_Symbol)
+ break;
+ /* Trace symbols aliases to other symbols
+ until we get a symbol that is not an alias. */
+ while (1)
+ {
+ QUIT;
+ tem = Fassq (sym, env);
+ if (NULL (tem))
+ {
+ def = XSYMBOL (sym)->function;
+ if (XTYPE (def) == Lisp_Symbol && !EQ (def, Qunbound))
+ sym = def;
+ else
+ break;
+ }
+ else
+ {
+ if (XTYPE (tem) == Lisp_Cons
+ && XTYPE (XCONS (tem)->cdr) == Lisp_Symbol)
+ sym = XCONS (tem)->cdr;
+ else
+ break;
+ }
+ }
+ /* Right now TEM is the result from SYM in ENV,
+ and if TEM is nil then DEF is SYM's function definition. */
+ if (NULL (tem))
+ {
+ /* SYM is not mentioned in ENV.
+ Look at its function definition. */
+ if (EQ (def, Qunbound)
+ || XTYPE (def) != Lisp_Cons)
+ /* Not defined or definition not suitable */
+ break;
+ if (EQ (XCONS (def)->car, Qautoload))
+ {
+ /* Autoloading function: will it be a macro when loaded? */
+ tem = Fcar (Fnthcdr (make_number (4), def));
+ if (NULL (tem))
+ break;
+ /* Yes, load it and try again. */
+ do_autoload (def, sym);
+ continue;
+ }
+ else if (!EQ (XCONS (def)->car, Qmacro))
+ break;
+ else expander = XCONS (def)->cdr;
+ }
+ else
+ {
+ expander = XCONS (tem)->cdr;
+ if (NULL (expander))
+ break;
+ }
+ form = apply1 (expander, XCONS (form)->cdr);
+ }
+ return form;
+}
+
+DEFUN ("catch", Fcatch, Scatch, 1, UNEVALLED, 0,
+ "(catch TAG BODY...) perform BODY allowing nonlocal exits using (throw TAG).\n\
+TAG is evalled to get the tag to use. throw to that tag exits this catch.\n\
+Then the BODY is executed. If no throw happens, the value of the last BODY\n\
+form is returned from catch. If a throw happens, it specifies the value to\n\
+return from catch.")
+ (args)
+ Lisp_Object args;
+{
+ register Lisp_Object tag;
+ struct gcpro gcpro1;
+
+ GCPRO1 (args);
+ tag = Feval (Fcar (args));
+ UNGCPRO;
+ return internal_catch (tag, Fprogn, Fcdr (args));
+}
+
+/* Set up a catch, then call C function FUNC on argument ARG.
+ FUNC should return a Lisp_Object.
+ This is how catches are done from within C code. */
+
+Lisp_Object
+internal_catch (tag, func, arg)
+ Lisp_Object tag;
+ Lisp_Object (*func) ();
+ Lisp_Object arg;
+{
+ /* This structure is made part of the chain `catchlist'. */
+ struct catchtag c;
+
+ /* Fill in the components of c, and put it on the list. */
+ c.next = catchlist;
+ c.tag = tag;
+ c.val = Qnil;
+ c.backlist = backtrace_list;
+ c.handlerlist = handlerlist;
+ c.lisp_eval_depth = lisp_eval_depth;
+ c.poll_suppress_count = poll_suppress_count;
+ c.pdlcount = specpdl_ptr - specpdl;
+ c.gcpro = gcprolist;
+ catchlist = &c;
+
+ /* Call FUNC. */
+ if (! _setjmp (c.jmp))
+ c.val = (*func) (arg);
+
+ /* Throw works by a longjmp that comes right here. */
+ catchlist = c.next;
+ return c.val;
+}
+
+/* Discard from the catchlist all catch tags back through CATCH.
+ Before each catch is discarded, unbind all special bindings
+ made within that catch. Also, when discarding a catch that
+ corresponds to a condition handler, discard that handler.
+
+ At the end, restore some static info saved in CATCH.
+
+ This is used for correct unwinding in Fthrow and Fsignal,
+ before doing the longjmp that actually destroys the stack frames
+ in which these handlers and catches reside. */
+
+static void
+unbind_catch (catch)
+ struct catchtag *catch;
+{
+ register int last_time;
+
+ do
+ {
+ last_time = catchlist == catch;
+ unbind_to (catchlist->pdlcount);
+ handlerlist = catchlist->handlerlist;
+ catchlist = catchlist->next;
+ }
+ while (! last_time);
+
+ gcprolist = catch->gcpro;
+ backtrace_list = catch->backlist;
+ lisp_eval_depth = catch->lisp_eval_depth;
+}
+
+DEFUN ("throw", Fthrow, Sthrow, 2, 2, 0,
+ "(throw TAG VALUE): throw to the catch for TAG and return VALUE from it.\n\
+Both TAG and VALUE are evalled.")
+ (tag, val)
+ register Lisp_Object tag, val;
+{
+ register struct catchtag *c;
+
+ while (1)
+ {
+ if (!NULL (tag))
+ for (c = catchlist; c; c = c->next)
+ {
+ if (EQ (c->tag, tag))
+ {
+ /* Restore the polling-suppression count. */
+ if (c->poll_suppress_count > poll_suppress_count)
+ abort ();
+ while (c->poll_suppress_count < poll_suppress_count)
+ start_polling ();
+ c->val = val;
+ unbind_catch (c);
+ _longjmp (c->jmp, 1);
+ }
+ }
+ tag = Fsignal (Qno_catch, Fcons (tag, Fcons (val, Qnil)));
+ }
+}
+
+
+DEFUN ("unwind-protect", Funwind_protect, Sunwind_protect, 1, UNEVALLED, 0,
+ "Do BODYFORM, protecting with UNWINDFORMS.\n\
+Usage looks like (unwind-protect BODYFORM UNWINDFORMS...) \n\
+If BODYFORM completes normally, its value is returned\n\
+after executing the UNWINDFORMS.\n\
+If BODYFORM exits nonlocally, the UNWINDFORMS are executed anyway.")
+ (args)
+ Lisp_Object args;
+{
+ Lisp_Object val;
+ int count = specpdl_ptr - specpdl;
+ struct gcpro gcpro1;
+
+ record_unwind_protect (0, Fcdr (args));
+ val = Feval (Fcar (args));
+ GCPRO1 (val);
+ unbind_to (count);
+ UNGCPRO;
+ return val;
+}
+
+/* Chain of condition handlers currently in effect.
+ The elements of this chain are contained in the stack frames
+ of Fcondition_case and internal_condition_case.
+ When an error is signaled (by calling Fsignal, below),
+ this chain is searched for an element that applies. */
+
+struct handler *handlerlist;
+
+DEFUN ("condition-case", Fcondition_case, Scondition_case, 2, UNEVALLED, 0,
+ "Regain control when an error is signaled.\n\
+ (condition-case VAR BODYFORM HANDLERS...)\n\
+executes BODYFORM and returns its value if no error happens.\n\
+Each element of HANDLERS looks like (CONDITION-NAME BODY...)\n\
+where the BODY is made of Lisp expressions.\n\
+The handler is applicable to an error\n\
+if CONDITION-NAME is one of the error's condition names.\n\
+When a handler handles an error,\n\
+control returns to the condition-case and the handler BODY... is executed\n\
+with VAR bound to (SIGNALED-CONDITIONS . SIGNAL-DATA).\n\
+The value of the last BODY form is returned from the condition-case.\n\
+See SIGNAL for more info.")
+ (args)
+ Lisp_Object args;
+{
+ Lisp_Object val;
+ struct catchtag c;
+ struct handler h;
+ register Lisp_Object tem;
+
+ tem = Fcar (args);
+ CHECK_SYMBOL (tem, 0);
+
+ c.tag = Qnil;
+ c.val = Qnil;
+ c.backlist = backtrace_list;
+ c.handlerlist = handlerlist;
+ c.lisp_eval_depth = lisp_eval_depth;
+ c.poll_suppress_count = poll_suppress_count;
+ c.pdlcount = specpdl_ptr - specpdl;
+ c.gcpro = gcprolist;
+ if (_setjmp (c.jmp))
+ {
+ if (!NULL (h.var))
+ specbind (h.var, Fcdr (c.val));
+ val = Fprogn (Fcdr (Fcar (c.val)));
+ unbind_to (c.pdlcount);
+ return val;
+ }
+ c.next = catchlist;
+ catchlist = &c;
+ h.var = Fcar (args);
+ h.handler = Fcdr (Fcdr (args));
+
+ for (val = h.handler; ! NULL (val); val = Fcdr (val))
+ {
+ tem = Fcar (val);
+ if ((!NULL (tem)) &&
+ (!CONSP (tem) || (XTYPE (XCONS (tem)->car) != Lisp_Symbol)))
+ error ("Invalid condition handler", tem);
+ }
+
+ h.next = handlerlist;
+ h.poll_suppress_count = poll_suppress_count;
+ h.tag = &c;
+ handlerlist = &h;
+
+ val = Feval (Fcar (Fcdr (args)));
+ catchlist = c.next;
+ handlerlist = h.next;
+ return val;
+}
+
+Lisp_Object
+internal_condition_case (bfun, handlers, hfun)
+ Lisp_Object (*bfun) ();
+ Lisp_Object handlers;
+ Lisp_Object (*hfun) ();
+{
+ Lisp_Object val;
+ struct catchtag c;
+ struct handler h;
+
+ c.tag = Qnil;
+ c.val = Qnil;
+ c.backlist = backtrace_list;
+ c.handlerlist = handlerlist;
+ c.lisp_eval_depth = lisp_eval_depth;
+ c.poll_suppress_count = poll_suppress_count;
+ c.pdlcount = specpdl_ptr - specpdl;
+ c.gcpro = gcprolist;
+ if (_setjmp (c.jmp))
+ {
+ return (*hfun) (Fcdr (c.val));
+ }
+ c.next = catchlist;
+ catchlist = &c;
+ h.handler = handlers;
+ h.var = Qnil;
+ h.poll_suppress_count = poll_suppress_count;
+ h.next = handlerlist;
+ h.tag = &c;
+ handlerlist = &h;
+
+ val = (*bfun) ();
+ catchlist = c.next;
+ handlerlist = h.next;
+ return val;
+}
+
+static Lisp_Object find_handler_clause ();
+
+DEFUN ("signal", Fsignal, Ssignal, 2, 2, 0,
+ "Signal an error. Args are SIGNAL-NAME, and associated DATA.\n\
+A signal name is a symbol with an error-conditions property\n\
+that is a list of condition names.\n\
+A handler for any of those names will get to handle this signal.\n\
+The symbol error should always be one of them.\n\
+\n\
+DATA should be a list. Its elements are printed as part of the error message.\n\
+If the signal is handled, DATA is made available to the handler.\n\
+See condition-case.")
+ (sig, data)
+ Lisp_Object sig, data;
+{
+ register struct handler *allhandlers = handlerlist;
+ Lisp_Object conditions;
+ extern int gc_in_progress;
+ extern int waiting_for_input;
+ Lisp_Object debugger_value;
+
+ quit_error_check ();
+ immediate_quit = 0;
+ if (gc_in_progress || waiting_for_input)
+ abort ();
+
+ conditions = Fget (sig, Qerror_conditions);
+
+ for (; handlerlist; handlerlist = handlerlist->next)
+ {
+ register Lisp_Object clause;
+ clause = find_handler_clause (handlerlist->handler, conditions,
+ sig, data, &debugger_value);
+
+ /* If have called debugger and user wants to continue,
+ just return nil. */
+ if (EQ (clause, Qlambda))
+ return debugger_value;
+
+ if (!NULL (clause))
+ {
+ struct handler *h = handlerlist;
+ /* Restore the polling-suppression count. */
+ if (h->poll_suppress_count > poll_suppress_count)
+ abort ();
+ while (h->poll_suppress_count < poll_suppress_count)
+ start_polling ();
+ handlerlist = allhandlers;
+ unbind_catch (h->tag);
+ h->tag->val = Fcons (clause, Fcons (sig, data));
+ _longjmp (h->tag->jmp, 1);
+ }
+ }
+
+ handlerlist = allhandlers;
+ /* If no handler is present now, try to run the debugger,
+ and if that fails, throw to top level. */
+ find_handler_clause (Qerror, conditions, sig, data, &debugger_value);
+ Fthrow (Qtop_level, Qt);
+}
+
+/* Value of Qlambda means we have called debugger and
+ user has continued. Store value returned fromdebugger
+ into *debugger_value_ptr */
+
+static Lisp_Object
+find_handler_clause (handlers, conditions, sig, data, debugger_value_ptr)
+ Lisp_Object handlers, conditions, sig, data;
+ Lisp_Object *debugger_value_ptr;
+{
+ register Lisp_Object h;
+ register Lisp_Object tem;
+ register Lisp_Object tem1;
+
+ if (EQ (handlers, Qt)) /* t is used by handlers for all conditions, set up by C code. */
+ return Qt;
+ if (EQ (handlers, Qerror)) /* error is used similarly, but means display a backtrace too */
+ {
+ if (stack_trace_on_error)
+ internal_with_output_to_temp_buffer ("*Backtrace*", Fbacktrace, Qnil);
+ if (EQ (sig, Qquit) ? debug_on_quit : debug_on_error)
+ {
+ *debugger_value_ptr =
+ call_debugger (Fcons (Qerror,
+ Fcons (Fcons (sig, data),
+ Qnil)));
+ return Qlambda;
+ }
+ return Qt;
+ }
+ for (h = handlers; CONSP (h); h = Fcdr (h))
+ {
+ tem1 = Fcar (h);
+ if (!CONSP (tem1))
+ continue;
+ tem = Fmemq (Fcar (tem1), conditions);
+ if (!NULL (tem))
+ return tem1;
+ }
+ return Qnil;
+}
+
+/* dump an error message; called like printf */
+
+/* VARARGS 1 */
+void
+error (m, a1, a2, a3)
+ char *m;
+{
+ char buf[200];
+ sprintf (buf, m, a1, a2, a3);
+ while (1)
+ Fsignal (Qerror, Fcons (build_string (buf), Qnil));
+}
+
+DEFUN ("commandp", Fcommandp, Scommandp, 1, 1, 0,
+ "T if FUNCTION makes provisions for interactive calling.\n\
+This means it contains a description for how to read arguments to give it.\n\
+The value is nil for an invalid function or a symbol with no function definition.\n\
+\n\
+Interactively callable functions include strings (treated as keyboard macros),\n\
+lambda-expressions that contain a top-level call to interactive ,\n\
+autoload definitions made by autoload with non-nil fourth argument,\n\
+and some of the built-in functions of Lisp.\n\
+\n\
+Also, a symbol is commandp if its function definition is commandp.")
+ (function)
+ Lisp_Object function;
+{
+ register Lisp_Object fun;
+ register Lisp_Object funcar;
+ register Lisp_Object tem;
+ register int i = 0;
+
+ fun = function;
+ while (XTYPE (fun) == Lisp_Symbol)
+ {
+ if (++i > 10) return Qnil;
+ tem = Ffboundp (fun);
+ if (NULL (tem)) return Qnil;
+ fun = Fsymbol_function (fun);
+ }
+ if (XTYPE (fun) == Lisp_Subr)
+ if (XSUBR (fun)->prompt)
+ return Qt;
+ else
+ return Qnil;
+ if (XTYPE (fun) == Lisp_Vector || XTYPE (fun) == Lisp_String)
+ return Qt;
+ if (!CONSP (fun))
+ return Qnil;
+ funcar = Fcar (fun);
+ if (XTYPE (funcar) != Lisp_Symbol)
+ return Fsignal (Qinvalid_function, Fcons (fun, Qnil));
+ if (EQ (funcar, Qlambda))
+ return Fassq (Qinteractive, Fcdr (Fcdr (fun)));
+ if (EQ (funcar, Qmocklisp))
+ return Qt; /* All mocklisp functions can be called interactively */
+ if (EQ (funcar, Qautoload))
+ return Fcar (Fcdr (Fcdr (Fcdr (fun))));
+ else
+ return Qnil;
+}
+
+/* ARGSUSED */
+DEFUN ("autoload", Fautoload, Sautoload, 2, 5, 0,
+ "Define FUNCTION to autoload from FILE.\n\
+FUNCTION is a symbol; FILE is a file name string to pass to load.\n\
+Third arg DOCSTRING is documentation for the function.\n\
+Fourth arg FROM_KBD if non-nil says function can be called interactively.\n\
+Fifth arg MACRO if non-nil says the function is really a macro.\n\
+Third through fifth args give info about the real definition.\n\
+They default to nil.\n\
+If FUNCTION is already defined other than as an autoload,\n\
+this does nothing and returns nil.")
+ (function, file, docstring, interactive, macro)
+ Lisp_Object function, file, docstring, interactive, macro;
+{
+#ifdef NO_ARG_ARRAY
+ Lisp_Object args[4];
+#endif
+
+ CHECK_SYMBOL (function, 0);
+ CHECK_STRING (file, 1);
+
+ /* If function is defined and not as an autoload, don't override */
+ if (!EQ (XSYMBOL (function)->function, Qunbound)
+ && !(XTYPE (XSYMBOL (function)->function) == Lisp_Cons
+ && EQ (XCONS (XSYMBOL (function)->function)->car, Qautoload)))
+ return Qnil;
+
+#ifdef NO_ARG_ARRAY
+ args[0] = file;
+ args[1] = docstring;
+ args[2] = interactive;
+ args[3] = macro;
+
+ return Ffset (function, Fcons (Qautoload, Flist (4, &args[0])));
+#else /* NO_ARG_ARRAY */
+ return Ffset (function, Fcons (Qautoload, Flist (4, &file)));
+#endif /* not NO_ARG_ARRAY */
+}
+
+Lisp_Object
+un_autoload (oldqueue)
+ Lisp_Object oldqueue;
+{
+ register Lisp_Object queue, first, second;
+
+ /* Queue to unwind is current value of Vautoload_queue.
+ oldqueue is the shadowed value to leave in Vautoload_queue. */
+ queue = Vautoload_queue;
+ Vautoload_queue = oldqueue;
+ while (CONSP (queue))
+ {
+ first = Fcar (queue);
+ second = Fcdr (first);
+ first = Fcar (first);
+ if (EQ (second, Qnil))
+ Vfeatures = first;
+ else
+ Ffset (first, second);
+ queue = Fcdr (queue);
+ }
+ return Qnil;
+}
+
+do_autoload (fundef, funname)
+ Lisp_Object fundef, funname;
+{
+ int count = specpdl_ptr - specpdl;
+ Lisp_Object fun, val;
+
+ fun = funname;
+
+ /* Value saved here is to be restored into Vautoload_queue */
+ record_unwind_protect (un_autoload, Vautoload_queue);
+ Vautoload_queue = Qt;
+ Fload (Fcar (Fcdr (fundef)), Qnil, noninteractive ? Qt : Qnil, Qnil);
+ /* Once loading finishes, don't undo it. */
+ Vautoload_queue = Qt;
+ unbind_to (count);
+
+ while (XTYPE (fun) == Lisp_Symbol)
+ {
+ QUIT;
+ val = XSYMBOL (fun)->function;
+ if (EQ (val, Qunbound))
+ Fsymbol_function (fun); /* Get the right kind of error! */
+ fun = val;
+ }
+ if (XTYPE (fun) == Lisp_Cons
+ && EQ (XCONS (fun)->car, Qautoload))
+ error ("Autoloading failed to define function %s",
+ XSYMBOL (funname)->name->data);
+}
+
+DEFUN ("eval", Feval, Seval, 1, 1, 0,
+ "Evaluate FORM and return its value.")
+ (form)
+ Lisp_Object form;
+{
+ Lisp_Object fun, val, original_fun, original_args;
+ Lisp_Object funcar;
+ struct backtrace backtrace;
+ struct gcpro gcpro1, gcpro2, gcpro3;
+
+ if (XTYPE (form) == Lisp_Symbol)
+ {
+ if (EQ (Vmocklisp_arguments, Qt))
+ return Fsymbol_value (form);
+ val = Fsymbol_value (form);
+ if (NULL (val))
+ XFASTINT (val) = 0;
+ else if (EQ (val, Qt))
+ XFASTINT (val) = 1;
+ return val;
+ }
+ if (!CONSP (form))
+ return form;
+
+ QUIT;
+ if (consing_since_gc > gc_cons_threshold)
+ {
+ GCPRO1 (form);
+ Fgarbage_collect ();
+ UNGCPRO;
+ }
+
+ if (++lisp_eval_depth > max_lisp_eval_depth)
+ {
+ if (max_lisp_eval_depth < 100)
+ max_lisp_eval_depth = 100;
+ if (lisp_eval_depth > max_lisp_eval_depth)
+ error ("Lisp nesting exceeds max-lisp-eval-depth");
+ }
+
+ original_fun = Fcar (form);
+ original_args = Fcdr (form);
+
+ backtrace.next = backtrace_list;
+ backtrace_list = &backtrace;
+ backtrace.function = &original_fun; /* This also protects them from gc */
+ backtrace.args = &original_args;
+ backtrace.nargs = UNEVALLED;
+ backtrace.evalargs = 1;
+ backtrace.debug_on_exit = 0;
+
+ if (debug_on_next_call)
+ do_debug_on_call (Qt);
+
+ /* At this point, only original_fun and original_args
+ have values that will be used below */
+ retry:
+ fun = original_fun;
+ while (XTYPE (fun) == Lisp_Symbol)
+ {
+ QUIT;
+ val = XSYMBOL (fun)->function;
+ if (EQ (val, Qunbound))
+ Fsymbol_function (fun); /* Get the right kind of error! */
+ fun = val;
+ }
+
+ if (XTYPE (fun) == Lisp_Subr)
+ {
+ Lisp_Object numargs;
+ Lisp_Object argvals[5];
+ Lisp_Object args_left;
+ register int i, maxargs;
+
+ args_left = original_args;
+ numargs = Flength (args_left);
+
+ if (XINT (numargs) < XSUBR (fun)->min_args ||
+ (XSUBR (fun)->max_args >= 0 && XSUBR (fun)->max_args < XINT (numargs)))
+ {
+ val = Fsignal (Qwrong_number_of_arguments,
+ Fcons (fun, Fcons (numargs, Qnil)));
+ goto done;
+ }
+
+ if (XSUBR (fun)->max_args == UNEVALLED)
+ {
+ backtrace.evalargs = 0;
+ val = (*XSUBR (fun)->function) (args_left);
+ goto done;
+ }
+
+ if (XSUBR (fun)->max_args == MANY)
+ {
+ /* Pass a vector of evaluated arguments */
+ Lisp_Object *vals;
+ register int argnum = 0;
+
+ vals = (Lisp_Object *) alloca (XINT (numargs) * sizeof (Lisp_Object));
+
+ GCPRO3 (args_left, fun, fun);
+ gcpro3.var = vals;
+ gcpro3.nvars = 0;
+
+ while (!NULL (args_left))
+ {
+ vals[argnum++] = Feval (Fcar (args_left));
+ args_left = Fcdr (args_left);
+ gcpro3.nvars = argnum;
+ }
+
+ backtrace.args = vals;
+ backtrace.nargs = XINT (numargs);
+
+ val = (*XSUBR (fun)->function) (XINT (numargs), vals);
+ UNGCPRO;
+ goto done;
+ }
+
+ GCPRO3 (args_left, fun, fun);
+ gcpro3.var = argvals;
+ gcpro3.nvars = 0;
+
+ maxargs = XSUBR (fun)->max_args;
+ for (i = 0; i < maxargs; args_left = Fcdr (args_left))
+ {
+ argvals[i] = Feval (Fcar (args_left));
+ gcpro3.nvars = ++i;
+ }
+
+ UNGCPRO;
+
+ backtrace.args = argvals;
+ backtrace.nargs = XINT (numargs);
+
+ switch (i)
+ {
+ case 0:
+ val = (*XSUBR (fun)->function) ();
+ goto done;
+ case 1:
+ val = (*XSUBR (fun)->function) (argvals[0]);
+ goto done;
+ case 2:
+ val = (*XSUBR (fun)->function) (argvals[0], argvals[1]);
+ goto done;
+ case 3:
+ val = (*XSUBR (fun)->function) (argvals[0], argvals[1],
+ argvals[2]);
+ goto done;
+ case 4:
+ val = (*XSUBR (fun)->function) (argvals[0], argvals[1],
+ argvals[2], argvals[3]);
+ goto done;
+ case 5:
+ val = (*XSUBR (fun)->function) (argvals[0], argvals[1], argvals[2],
+ argvals[3], argvals[4]);
+ goto done;
+ }
+ }
+ if (!CONSP (fun))
+ {
+ val = Fsignal (Qinvalid_function, Fcons (fun, Qnil));
+ goto done;
+ }
+ funcar = Fcar (fun);
+ if (XTYPE (funcar) != Lisp_Symbol)
+ val = Fsignal (Qinvalid_function, Fcons (fun, Qnil));
+ else if (EQ (funcar, Qautoload))
+ {
+ do_autoload (fun, original_fun);
+ goto retry;
+ }
+ else if (EQ (funcar, Qmacro))
+ val = Feval (apply1 (Fcdr (fun), original_args));
+ else if (EQ (funcar, Qlambda))
+ val = apply_lambda (fun, original_args, 1);
+ else if (EQ (funcar, Qmocklisp))
+ val = ml_apply (fun, original_args);
+ else
+ val = Fsignal (Qinvalid_function, Fcons (fun, Qnil));
+
+ done:
+ if (!EQ (Vmocklisp_arguments, Qt))
+ {
+ if (NULL (val))
+ XFASTINT (val) = 0;
+ else if (EQ (val, Qt))
+ XFASTINT (val) = 1;
+ }
+ lisp_eval_depth--;
+ if (backtrace.debug_on_exit)
+ val = call_debugger (Fcons (Qexit, Fcons (val, Qnil)));
+ backtrace_list = backtrace.next;
+ return val;
+}
+
+DEFUN ("apply", Fapply, Sapply, 2, MANY, 0,
+ "Call FUNCTION, passing remaining arguments to it. The last argument\n\
+is a list of arguments to pass.\n\
+Thus, (apply '+ 1 2 '(3 4)) returns 10.")
+ (nargs, args)
+ int nargs;
+ Lisp_Object *args;
+{
+ register int i, numargs;
+ register Lisp_Object spread_arg;
+ register Lisp_Object *funcall_args;
+ Lisp_Object fun, val;
+ struct gcpro gcpro1;
+
+ fun = args [0];
+ funcall_args = 0;
+ spread_arg = args [nargs - 1];
+ CHECK_LIST (spread_arg, nargs);
+
+ numargs = XINT (Flength (spread_arg));
+
+ if (numargs == 0)
+ return Ffuncall (nargs - 1, args);
+ else if (numargs == 1)
+ {
+ args [nargs - 1] = XCONS (spread_arg)->car;
+ return Ffuncall (nargs, args);
+ }
+
+ numargs = nargs - 2 + numargs;
+
+ while (XTYPE (fun) == Lisp_Symbol)
+ {
+ QUIT;
+ fun = XSYMBOL (fun)->function;
+ if (EQ (fun, Qunbound))
+ {
+ /* Let funcall get the error */
+ fun = args[0];
+ goto funcall;
+ }
+ }
+
+ if (XTYPE (fun) == Lisp_Subr)
+ if (numargs < XSUBR (fun)->min_args ||
+ (XSUBR (fun)->max_args >= 0 && XSUBR (fun)->max_args < numargs))
+ goto funcall; /* Let funcall get the error */
+ else if (XSUBR (fun)->max_args > numargs)
+ {
+ /* Avoid making funcall cons up a yet another new vector of arguments
+ by explicitly supplying nil's for optional values */
+ funcall_args = (Lisp_Object *) alloca ((1 + XSUBR (fun)->max_args)
+ * sizeof (Lisp_Object));
+ for (i = numargs; i < XSUBR (fun)->max_args;)
+ funcall_args[++i] = Qnil;
+ GCPRO1 (*funcall_args);
+ gcpro1.nvars = 1 + XSUBR (fun)->max_args;
+ }
+ funcall:
+ /* We add 1 to numargs because funcall_args includes the
+ function itself as well as its arguments. */
+ if (!funcall_args)
+ {
+ funcall_args = (Lisp_Object *) alloca ((1 + numargs)
+ * sizeof (Lisp_Object));
+ GCPRO1 (*funcall_args);
+ gcpro1.nvars = 1 + numargs;
+ }
+
+ bcopy (args, funcall_args, nargs * sizeof (Lisp_Object));
+ /* Spread the last arg we got. Its first element goes in
+ the slot that it used to occupy, hence this value of I. */
+ i = nargs - 1;
+ while (!NULL (spread_arg))
+ {
+ funcall_args [i++] = XCONS (spread_arg)->car;
+ spread_arg = XCONS (spread_arg)->cdr;
+ }
+
+ val = Ffuncall (gcpro1.nvars, funcall_args);
+ UNGCPRO;
+ return val;
+}
+
+/* Apply fn to arg */
+Lisp_Object
+apply1 (fn, arg)
+ Lisp_Object fn, arg;
+{
+ register Lisp_Object val;
+ struct gcpro gcpro1;
+ if (NULL (arg))
+ /* No need to protect if all we have is the function. */
+ return Ffuncall (1, &fn);
+ /* We must protect the vector given to Fapply.
+ If ARG is a list of 1 element, that same vector is passed
+ on to Ffuncall. */
+#ifdef NO_ARG_ARRAY
+ {
+ Lisp_Object args[2];
+ args[0] = fn;
+ args[1] = arg;
+ GCPRO1 (fn);
+ gcpro1.var = args;
+ gcpro1.nvars = 2;
+ val = Fapply (2, args);
+ UNGCPRO;
+ }
+#else /* not NO_ARG_ARRAY */
+ GCPRO1 (fn);
+ gcpro1.nvars = 2;
+ val = Fapply (2, &fn);
+ UNGCPRO;
+#endif /* not NO_ARG_ARRAY */
+ return val;
+}
+
+/* Call function fn on no arguments */
+Lisp_Object
+call0 (fn)
+ Lisp_Object fn;
+{
+ return Ffuncall (1, &fn);
+}
+
+/* Call function fn with argument arg */
+/* ARGSUSED */
+Lisp_Object
+call1 (fn, arg)
+ Lisp_Object fn, arg;
+{
+ Lisp_Object val;
+ struct gcpro gcpro1;
+#ifdef NO_ARG_ARRAY
+ Lisp_Object args[2];
+#endif
+ GCPRO1 (fn);
+ gcpro1.nvars = 2;
+#ifdef NO_ARG_ARRAY
+ args[0] = fn;
+ args[1] = arg;
+ gcpro1.var = args;
+ val = Ffuncall (2, args);
+#else /* not NO_ARG_ARRAY */
+ val = Ffuncall (2, &fn);
+#endif /* not NO_ARG_ARRAY */
+ UNGCPRO;
+ return val;
+}
+
+/* Call function fn with arguments arg, arg1 */
+/* ARGSUSED */
+Lisp_Object
+call2 (fn, arg, arg1)
+ Lisp_Object fn, arg, arg1;
+{
+ Lisp_Object val;
+ struct gcpro gcpro1;
+#ifdef NO_ARG_ARRAY
+ Lisp_Object args[3];
+#endif
+ GCPRO1 (fn);
+ gcpro1.nvars = 3;
+#ifdef NO_ARG_ARRAY
+ args[0] = fn;
+ args[1] = arg;
+ args[2] = arg1;
+ gcpro1.var = args;
+ val = Ffuncall (3, args);
+#else /* not NO_ARG_ARRAY */
+ val = Ffuncall (3, &fn);
+#endif /* not NO_ARG_ARRAY */
+ UNGCPRO;
+ return val;
+}
+
+/* Call function fn with arguments arg, arg1, arg2 */
+/* ARGSUSED */
+Lisp_Object
+call3 (fn, arg, arg1, arg2)
+ Lisp_Object fn, arg, arg1, arg2;
+{
+ Lisp_Object val;
+ struct gcpro gcpro1;
+#ifdef NO_ARG_ARRAY
+ Lisp_Object args[4];
+#endif
+ GCPRO1 (fn);
+ gcpro1.nvars = 4;
+#ifdef NO_ARG_ARRAY
+ args[0] = fn;
+ args[1] = arg;
+ args[2] = arg1;
+ args[3] = arg2;
+ gcpro1.var = args;
+ val = Ffuncall (4, args);
+#else /* not NO_ARG_ARRAY */
+ val = Ffuncall (4, &fn);
+#endif /* not NO_ARG_ARRAY */
+ UNGCPRO;
+ return val;
+}
+
+DEFUN ("funcall", Ffuncall, Sfuncall, 1, MANY, 0,
+ "Call first argument as a function, passing remaining arguments to it.\n\
+Thus, (funcall 'cons 'x 'y) returns (x . y).")
+ (nargs, args)
+ int nargs;
+ Lisp_Object *args;
+{
+ Lisp_Object fun;
+ Lisp_Object funcar;
+ int numargs = nargs - 1;
+ Lisp_Object lisp_numargs;
+ Lisp_Object val;
+ struct backtrace backtrace;
+ register Lisp_Object *internal_args;
+ register int i;
+
+ QUIT;
+ if (consing_since_gc > gc_cons_threshold)
+ Fgarbage_collect ();
+
+ if (++lisp_eval_depth > max_lisp_eval_depth)
+ {
+ if (max_lisp_eval_depth < 100)
+ max_lisp_eval_depth = 100;
+ if (lisp_eval_depth > max_lisp_eval_depth)
+ error ("Lisp nesting exceeds max-lisp-eval-depth");
+ }
+
+ backtrace.next = backtrace_list;
+ backtrace_list = &backtrace;
+ backtrace.function = &args[0];
+ backtrace.args = &args[1];
+ backtrace.nargs = nargs - 1;
+ backtrace.evalargs = 0;
+ backtrace.debug_on_exit = 0;
+
+ if (debug_on_next_call)
+ do_debug_on_call (Qlambda);
+
+ retry:
+
+ fun = args[0];
+ while (XTYPE (fun) == Lisp_Symbol)
+ {
+ QUIT;
+ val = XSYMBOL (fun)->function;
+ if (EQ (val, Qunbound))
+ Fsymbol_function (fun); /* Get the right kind of error! */
+ fun = val;
+ }
+
+ if (XTYPE (fun) == Lisp_Subr)
+ {
+ if (numargs < XSUBR (fun)->min_args ||
+ (XSUBR (fun)->max_args >= 0 && XSUBR (fun)->max_args < numargs))
+ {
+ XFASTINT (lisp_numargs) = numargs;
+ val = Fsignal (Qwrong_number_of_arguments,
+ Fcons (fun, Fcons (lisp_numargs, Qnil)));
+ goto done;
+ }
+
+ if (XSUBR (fun)->max_args == UNEVALLED)
+ {
+ val = Fsignal (Qinvalid_function, Fcons (fun, Qnil));
+ goto done;
+ }
+
+ if (XSUBR (fun)->max_args == MANY)
+ {
+ val = (*XSUBR (fun)->function) (numargs, args + 1);
+ goto done;
+ }
+
+ if (XSUBR (fun)->max_args > numargs)
+ {
+ internal_args = (Lisp_Object *) alloca (XSUBR (fun)->max_args * sizeof (Lisp_Object));
+ bcopy (args + 1, internal_args, numargs * sizeof (Lisp_Object));
+ for (i = numargs; i < XSUBR (fun)->max_args; i++)
+ internal_args[i] = Qnil;
+ }
+ else
+ internal_args = args + 1;
+ switch (XSUBR (fun)->max_args)
+ {
+ case 0:
+ val = (*XSUBR (fun)->function) ();
+ goto done;
+ case 1:
+ val = (*XSUBR (fun)->function) (internal_args[0]);
+ goto done;
+ case 2:
+ val = (*XSUBR (fun)->function) (internal_args[0], internal_args[1]);
+ goto done;
+ case 3:
+ val = (*XSUBR (fun)->function) (internal_args[0], internal_args[1],
+ internal_args[2]);
+ goto done;
+ case 4:
+ val = (*XSUBR (fun)->function) (internal_args[0], internal_args[1],
+ internal_args[2],
+ internal_args[3]);
+ goto done;
+ case 5:
+ val = (*XSUBR (fun)->function) (internal_args[0], internal_args[1],
+ internal_args[2], internal_args[3],
+ internal_args[4]);
+ goto done;
+ }
+ }
+ if (!CONSP (fun))
+ {
+ val = Fsignal (Qinvalid_function, Fcons (fun, Qnil));
+ goto done;
+ }
+ funcar = Fcar (fun);
+ if (XTYPE (funcar) != Lisp_Symbol)
+ val = Fsignal (Qinvalid_function, Fcons (fun, Qnil));
+ else if (EQ (funcar, Qlambda))
+ val = funcall_lambda (fun, numargs, args + 1);
+ else if (EQ (funcar, Qmocklisp))
+ val = ml_apply (fun, Flist (numargs, args + 1));
+ else if (EQ (funcar, Qautoload))
+ {
+ do_autoload (fun, args[0]);
+ goto retry;
+ }
+ else
+ val = Fsignal (Qinvalid_function, Fcons (fun, Qnil));
+
+ done:
+ lisp_eval_depth--;
+ if (backtrace.debug_on_exit)
+ val = call_debugger (Fcons (Qexit, Fcons (val, Qnil)));
+ backtrace_list = backtrace.next;
+ return val;
+}
+
+Lisp_Object
+apply_lambda (fun, args, eval_flag)
+ Lisp_Object fun, args;
+ int eval_flag;
+{
+ Lisp_Object args_left;
+ Lisp_Object numargs;
+ register Lisp_Object *arg_vector;
+ struct gcpro gcpro1, gcpro2, gcpro3;
+ register int i;
+ register Lisp_Object tem;
+
+ numargs = Flength (args);
+ arg_vector = (Lisp_Object *) alloca (XINT (numargs) * sizeof (Lisp_Object));
+ args_left = args;
+
+ GCPRO3 (*arg_vector, args_left, fun);
+ gcpro1.nvars = 0;
+
+ for (i = 0; i < XINT (numargs);)
+ {
+ tem = Fcar (args_left), args_left = Fcdr (args_left);
+ if (eval_flag) tem = Feval (tem);
+ arg_vector[i++] = tem;
+ gcpro1.nvars = i;
+ }
+
+ UNGCPRO;
+
+ if (eval_flag)
+ {
+ backtrace_list->args = arg_vector;
+ backtrace_list->nargs = i;
+ }
+ backtrace_list->evalargs = 0;
+ tem = funcall_lambda (fun, XINT (numargs), arg_vector);
+
+ /* Do the debug-on-exit now, while arg_vector still exists. */
+ if (backtrace_list->debug_on_exit)
+ tem = call_debugger (Fcons (Qexit, Fcons (tem, Qnil)));
+ /* Don't do it again when we return to eval. */
+ backtrace_list->debug_on_exit = 0;
+ return tem;
+}
+
+Lisp_Object
+funcall_lambda (fun, nargs, arg_vector)
+ Lisp_Object fun;
+ int nargs;
+ register Lisp_Object *arg_vector;
+{
+ Lisp_Object val, tem;
+ register Lisp_Object syms_left;
+ Lisp_Object numargs;
+ register Lisp_Object next;
+ int count = specpdl_ptr - specpdl;
+ register int i;
+ int optional = 0, rest = 0;
+
+ specbind (Qmocklisp_arguments, Qt); /* t means NOT mocklisp! */
+
+ XFASTINT (numargs) = nargs;
+
+ i = 0;
+ for (syms_left = Fcar (Fcdr (fun)); !NULL (syms_left); syms_left = Fcdr (syms_left))
+ {
+ QUIT;
+ next = Fcar (syms_left);
+ while (XTYPE (next) != Lisp_Symbol)
+ next = Fsignal (Qinvalid_function, Fcons (fun, Qnil));
+ if (EQ (next, Qand_rest))
+ rest = 1;
+ else if (EQ (next, Qand_optional))
+ optional = 1;
+ else if (rest)
+ {
+ specbind (next, Flist (nargs - i, &arg_vector[i]));
+ i = nargs;
+ }
+ else if (i < nargs)
+ {
+ tem = arg_vector[i++];
+ specbind (next, tem);
+ }
+ else if (!optional)
+ return Fsignal (Qwrong_number_of_arguments, Fcons (fun, Fcons (numargs, Qnil)));
+ else
+ specbind (next, Qnil);
+ }
+
+ if (i < nargs)
+ return Fsignal (Qwrong_number_of_arguments, Fcons (fun, Fcons (numargs, Qnil)));
+
+ val = Fprogn (Fcdr (Fcdr (fun)));
+ unbind_to (count);
+ return val;
+}
+
+void
+grow_specpdl ()
+{
+ register int count = specpdl_ptr - specpdl;
+ if (specpdl_size >= max_specpdl_size)
+ {
+ if (max_specpdl_size < 400)
+ max_specpdl_size = 400;
+ if (specpdl_size >= max_specpdl_size)
+ {
+ Fsignal (Qerror,
+ Fcons (build_string ("Variable binding depth exceeds max-specpdl-size"), Qnil));
+ max_specpdl_size *= 2;
+ }
+ }
+ specpdl_size *= 2;
+ if (specpdl_size > max_specpdl_size)
+ specpdl_size = max_specpdl_size;
+ specpdl = (struct specbinding *) xrealloc (specpdl, specpdl_size * sizeof (struct specbinding));
+ specpdl_ptr = specpdl + count;
+}
+
+void
+specbind (symbol, value)
+ Lisp_Object symbol, value;
+{
+ extern void store_symval_forwarding (); /* in eval.c */
+ Lisp_Object ovalue;
+
+ CHECK_SYMBOL (symbol, 0);
+
+ if (specpdl_ptr == specpdl + specpdl_size)
+ grow_specpdl ();
+ specpdl_ptr->symbol = symbol;
+ specpdl_ptr->func = 0;
+ ovalue = XSYMBOL (symbol)->value;
+ specpdl_ptr->old_value = EQ (ovalue, Qunbound) ? Qunbound : Fsymbol_value (symbol);
+ specpdl_ptr++;
+ if (XTYPE (ovalue) == Lisp_Buffer_Objfwd)
+ store_symval_forwarding (symbol, ovalue, value);
+ else
+ Fset (symbol, value);
+}
+
+void
+record_unwind_protect (function, arg)
+ Lisp_Object (*function)();
+ Lisp_Object arg;
+{
+ if (specpdl_ptr == specpdl + specpdl_size)
+ grow_specpdl ();
+ specpdl_ptr->func = function;
+ specpdl_ptr->symbol = Qnil;
+ specpdl_ptr->old_value = arg;
+ specpdl_ptr++;
+}
+
+void
+unbind_to (count)
+ int count;
+{
+ int quitf = !NULL (Vquit_flag);
+
+ Vquit_flag = Qnil;
+
+ while (specpdl_ptr != specpdl + count)
+ {
+ --specpdl_ptr;
+ if (specpdl_ptr->func != 0)
+ (*specpdl_ptr->func) (specpdl_ptr->old_value);
+ /* Note that a "binding" of nil is really an unwind protect,
+ so in that case the "old value" is a list of forms to evaluate. */
+ else if (NULL (specpdl_ptr->symbol))
+ Fprogn (specpdl_ptr->old_value);
+ else
+ Fset (specpdl_ptr->symbol, specpdl_ptr->old_value);
+ }
+ if (NULL (Vquit_flag) && quitf) Vquit_flag = Qt;
+}
+
+#if 0
+
+/* Get the value of symbol's global binding, even if that binding
+ is not now dynamically visible. */
+
+Lisp_Object
+top_level_value (symbol)
+ Lisp_Object symbol;
+{
+ register struct specbinding *ptr = specpdl;
+
+ CHECK_SYMBOL (symbol, 0);
+ for (; ptr != specpdl_ptr; ptr++)
+ {
+ if (EQ (ptr->symbol, symbol))
+ return ptr->old_value;
+ }
+ return Fsymbol_value (symbol);
+}
+
+Lisp_Object
+top_level_set (symbol, newval)
+ Lisp_Object symbol, newval;
+{
+ register struct specbinding *ptr = specpdl;
+
+ CHECK_SYMBOL (symbol, 0);
+ for (; ptr != specpdl_ptr; ptr++)
+ {
+ if (EQ (ptr->symbol, symbol))
+ {
+ ptr->old_value = newval;
+ return newval;
+ }
+ }
+ return Fset (symbol, newval);
+}
+
+#endif /* 0 */
+
+DEFUN ("backtrace-debug", Fbacktrace_debug, Sbacktrace_debug, 2, 2, 0,
+ "Set the debug-on-exit flag of eval frame LEVEL levels down to FLAG.\n\
+The debugger is entered when that frame exits, if the flag is non-nil.")
+ (level, flag)
+ Lisp_Object level, flag;
+{
+ register struct backtrace *backlist = backtrace_list;
+ register int i;
+
+ CHECK_NUMBER (level, 0);
+
+ for (i = 0; backlist && i < XINT (level); i++)
+ {
+ backlist = backlist->next;
+ }
+
+ if (backlist)
+ backlist->debug_on_exit = !NULL (flag);
+
+ return flag;
+}
+
+DEFUN ("backtrace", Fbacktrace, Sbacktrace, 0, 0, "",
+ "Print a trace of Lisp function calls currently active.\n\
+Output stream used is value of standard-output.")
+ ()
+{
+ register struct backtrace *backlist = backtrace_list;
+ register int i;
+ Lisp_Object tail;
+ Lisp_Object tem;
+ struct gcpro gcpro1;
+
+ tail = Qnil;
+ GCPRO1 (tail);
+
+ while (backlist)
+ {
+ write_string (backlist->debug_on_exit ? "* " : " ", 2);
+ if (backlist->nargs == UNEVALLED)
+ write_string ("(", -1);
+ tem = *backlist->function;
+ Fprin1 (tem, Qnil); /* This can QUIT */
+ if (backlist->nargs == UNEVALLED)
+ {
+ if (backlist->evalargs)
+ write_string (" ...computing arguments...", -1);
+ else
+ write_string (" ...", -1);
+ }
+ else if (backlist->nargs == MANY)
+ {
+ write_string ("(", -1);
+ for (tail = *backlist->args, i = 0; !NULL (tail); tail = Fcdr (tail), i++)
+ {
+ if (i) write_string (" ", -1);
+ Fprin1 (Fcar (tail), Qnil);
+ }
+ }
+ else
+ {
+ write_string ("(", -1);
+ for (i = 0; i < backlist->nargs; i++)
+ {
+ if (i) write_string (" ", -1);
+ Fprin1 (backlist->args[i], Qnil);
+ }
+ }
+ write_string (")\n", -1);
+ backlist = backlist->next;
+ }
+
+ UNGCPRO;
+ return Qnil;
+}
+
+syms_of_eval ()
+{
+ DEFVAR_INT ("max-specpdl-size", &max_specpdl_size,
+ "Limit on number of Lisp variable bindings & unwind-protects before error.");
+
+ DEFVAR_INT ("max-lisp-eval-depth", &max_lisp_eval_depth,
+ "Limit on depth in eval, apply and funcall before error.");
+
+ DEFVAR_LISP ("quit-flag", &Vquit_flag,
+ "Non-nil causes eval to abort, unless inhibit-quit is non-nil.\n\
+Typing C-G sets quit-flag non-nil, regardless of inhibit-quit.");
+ Vquit_flag = Qnil;
+
+ Qinhibit_quit = intern ("inhibit-quit");
+ staticpro (&Qinhibit_quit);
+ DEFVAR_LISP ("inhibit-quit", &Vinhibit_quit,
+ "Non-nil inhibits C-g quitting from happening immediately.\n\
+Note that quit-flag will still be set by typing C-g,\n\
+so a quit will be signalled as soon as inhibit-quit is nil.\n\
+To prevent this happening, set quit-flag to nil\n\
+before making inhibit-quit nil.");
+ Vinhibit_quit = Qnil;
+
+ Qautoload = intern ("autoload");
+ staticpro (&Qautoload);
+
+ Qmacro = intern ("macro");
+ staticpro (&Qmacro);
+
+ /* Note that the process handling also uses Qexit, but we don't want
+ to staticpro it twice, so we just do it here. */
+ Qexit = intern ("exit");
+ staticpro (&Qexit);
+
+ Qinteractive = intern ("interactive");
+ staticpro (&Qinteractive);
+
+ Qcommandp = intern ("commandp");
+ staticpro (&Qcommandp);
+
+ Qdefun = intern ("defun");
+ staticpro (&Qdefun);
+
+ Qand_rest = intern ("&rest");
+ staticpro (&Qand_rest);
+
+ Qand_optional = intern ("&optional");
+ staticpro (&Qand_optional);
+
+ DEFVAR_BOOL ("stack-trace-on-error", &stack_trace_on_error,
+ "*Non-nil means automatically display a backtrace buffer\n\
+after any error that is handled by the editor command loop.");
+ stack_trace_on_error = 0;
+
+ DEFVAR_BOOL ("debug-on-error", &debug_on_error,
+ "*Non-nil means enter debugger if an error is signaled.\n\
+Does not apply to errors handled by condition-case.\n\
+See also variable debug-on-quit.");
+ debug_on_error = 0;
+
+ DEFVAR_BOOL ("debug-on-quit", &debug_on_quit,
+ "*Non-nil means enter debugger if quit is signaled (C-G, for example).\n\
+Does not apply if quit is handled by a condition-case.");
+ debug_on_quit = 0;
+
+ DEFVAR_BOOL ("debug-on-next-call", &debug_on_next_call,
+ "Non-nil means enter debugger before next eval, apply or funcall.");
+
+ DEFVAR_LISP ("debugger", &Vdebugger,
+ "Function to call to invoke debugger.\n\
+If due to frame exit, args are 'exit and value being returned;\n\
+ this function's value will be returned instead of that.\n\
+If due to error, args are 'error and list of signal's args.\n\
+If due to apply or funcall entry, one arg, 'lambda.\n\
+If due to eval entry, one arg, 't.");
+ Vdebugger = Qnil;
+
+ Qmocklisp_arguments = intern ("mocklisp-arguments");
+ staticpro (&Qmocklisp_arguments);
+ DEFVAR_LISP ("mocklisp-arguments", &Vmocklisp_arguments,
+ "While in a mocklisp function, the list of its unevaluated args.");
+ Vmocklisp_arguments = Qt;
+
+ staticpro (&Vautoload_queue);
+ Vautoload_queue = Qnil;
+
+ defsubr (&Sor);
+ defsubr (&Sand);
+ defsubr (&Sif);
+ defsubr (&Scond);
+ defsubr (&Sprogn);
+ defsubr (&Sprog1);
+ defsubr (&Sprog2);
+ defsubr (&Ssetq);
+ defsubr (&Squote);
+ defsubr (&Sfunction);
+ defsubr (&Sdefun);
+ defsubr (&Sdefmacro);
+ defsubr (&Sdefvar);
+ defsubr (&Sdefconst);
+ defsubr (&Suser_variable_p);
+ defsubr (&Slet);
+ defsubr (&SletX);
+ defsubr (&Swhile);
+ defsubr (&Smacroexpand);
+ defsubr (&Scatch);
+ defsubr (&Sthrow);
+ defsubr (&Sunwind_protect);
+ defsubr (&Scondition_case);
+ defsubr (&Ssignal);
+ defsubr (&Sinteractive_p);
+ defsubr (&Scommandp);
+ defsubr (&Sautoload);
+ defsubr (&Seval);
+ defsubr (&Sapply);
+ defsubr (&Sfuncall);
+ defsubr (&Sbacktrace_debug);
+ defsubr (&Sbacktrace);
+}
diff --git a/src/fileio.c b/src/fileio.c
index 7727448feb4..55d01996507 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -1,5 +1,5 @@
/* File IO for GNU Emacs.
- Copyright (C) 1985, 1986, 1987, 1988 Free Software Foundation, Inc.
+ Copyright (C) 1985, 1986, 1987, 1988, 1990 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -17,15 +17,33 @@ You should have received a copy of the GNU General Public License
along with GNU Emacs; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+#include "config.h"
#include <sys/types.h>
+#ifdef hpux
+/* needed by <pwd.h> */
+#include <stdio.h>
+#undef NULL
+#endif
#include <sys/stat.h>
+
+#ifdef VMS
+#include "vms-pwd.h"
+#else
#include <pwd.h>
+#endif
+
#include <ctype.h>
-#include <sys/dir.h>
+
+#ifdef VMS
+#include "dir.h"
+#include <perror.h>
+#include <stddef.h>
+#include <string.h>
+#endif
#include <errno.h>
-#ifndef VMS
+#ifndef vax11c
extern int errno;
extern char *sys_errlist[];
extern int sys_nerr;
@@ -37,34 +55,37 @@ extern int sys_nerr;
#include <sys/time.h>
#endif
-#ifdef NULL
-#undef NULL
-#endif
-#include "config.h"
-#include "lisp.h"
-#include "buffer.h"
-#include "window.h"
-
#ifdef VMS
-#include <perror.h>
#include <file.h>
#include <rmsdef.h>
#include <fab.h>
#include <nam.h>
+extern unsigned char vms_file_written[]; /* set in rename_sans_version */
#endif
-#ifdef NEED_TIME_H
-#include <time.h>
-#else /* not NEED_TIME_H */
#ifdef HAVE_TIMEVAL
+#ifdef HPUX
+#include <time.h>
+#else
#include <sys/time.h>
-#endif /* HAVE_TIMEVAL */
-#endif /* not NEED_TIME_H */
+#endif
+#endif
-#ifdef HPUX
+#ifdef HPUX_NET
#include <netio.h>
+#ifndef HPUX8
#include <errnet.h>
#endif
+#endif
+
+#ifdef NULL
+#undef NULL
+#endif
+#include "lisp.h"
+#include "buffer.h"
+#include "window.h"
+
+#include "filetypes.h"
#ifndef O_WRONLY
#define O_WRONLY 1
@@ -76,10 +97,6 @@ extern int sys_nerr;
/* Nonzero during writing of auto-save files */
int auto_saving;
-/* Set by auto_save_1 to mode of original file so Fwrite_region will create
- a new file with the same mode as the original */
-int auto_save_mode_bits;
-
/* Nonzero means, when reading a filename in the minibuffer,
start out by inserting the default directory into the minibuffer. */
int insert_default_directory;
@@ -115,9 +132,9 @@ DEFUN ("file-name-directory", Ffile_name_directory, Sfile_name_directory,
1, 1, 0,
"Return the directory component in file name NAME.\n\
Return nil if NAME does not include a directory.\n\
-Otherwise return a directory spec.\n\
+Otherwise returns a directory spec.\n\
Given a Unix syntax file name, returns a string ending in slash;\n\
-on VMS, perhaps instead a string ending in `:', `]' or `>'.")
+on VMS, perhaps instead a string ending in :, ] or >.")
(file)
Lisp_Object file;
{
@@ -215,7 +232,8 @@ file_name_as_directory (out, in)
brack = ']';
strcpy (out, "[.");
}
- if (dot = index (p, '.'))
+ dot = (char *) index (p, '.');
+ if (dot)
{
/* blindly remove any extension */
size = strlen (out) + (dot - p);
@@ -240,10 +258,8 @@ file_name_as_directory (out, in)
DEFUN ("file-name-as-directory", Ffile_name_as_directory,
Sfile_name_as_directory, 1, 1, 0,
"Return a string representing file FILENAME interpreted as a directory.\n\
-This operation exists because a directory is also a file, but its name as\n\
-a directory is different from its name as a file.\n\
-The result can be used as the value of `default-directory'\n\
-or passed as second argument to `expand-file-name'.\n\
+This string can be used as the value of default-directory\n\
+or passed as second argument to expand-file-name.\n\
For a Unix-syntax file name, just appends a slash.\n\
On VMS, converts \"[X]FOO.DIR\" to \"[X.FOO]\", etc.")
(file)
@@ -281,16 +297,14 @@ directory_file_name (src, dst)
char esa[NAM$C_MAXRSS];
#endif /* VMS */
- slen = strlen (src);
+ slen = strlen (src) - 1;
#ifdef VMS
if (! index (src, '/')
- && (src[slen - 1] == ']'
- || src[slen - 1] == ':'
- || src[slen - 1] == '>'))
+ && (src[slen] == ']' || src[slen] == ':' || src[slen] == '>'))
{
/* VMS style - convert [x.y.z] to [x.y]z, [x] to [000000]x */
fab.fab$l_fna = src;
- fab.fab$b_fns = slen;
+ fab.fab$b_fns = slen + 1;
fab.fab$l_nam = &nam;
fab.fab$l_fop = FAB$M_NAM;
@@ -301,16 +315,16 @@ directory_file_name (src, dst)
/* We call SYS$PARSE to handle such things as [--] for us. */
if (SYS$PARSE(&fab, 0, 0) == RMS$_NORMAL)
{
- slen = nam.nam$b_esl;
- if (esa[slen - 1] == ';' && esa[slen - 2] == '.')
+ slen = nam.nam$b_esl - 1;
+ if (esa[slen] == ';' && esa[slen - 1] == '.')
slen -= 2;
- esa[slen] = '\0';
+ esa[slen + 1] = '\0';
src = esa;
}
- if (src[slen - 1] != ']' && src[slen - 1] != '>')
+ if (src[slen] != ']' && src[slen] != '>')
{
/* what about when we have logical_name:???? */
- if (src[slen - 1] == ':')
+ if (src[slen] == ':')
{ /* Xlate logical name and see what we get */
ptr = strcpy (dst, src); /* upper case for getenv */
while (*ptr)
@@ -319,7 +333,7 @@ directory_file_name (src, dst)
*ptr -= 040;
ptr++;
}
- dst[slen - 1] = 0; /* remove colon */
+ dst[slen] = 0; /* remove colon */
if (!(src = egetenv (dst)))
return 0;
/* should we jump to the beginning of this procedure?
@@ -329,8 +343,8 @@ directory_file_name (src, dst)
name...
For now, I'll punt and always expect VMS names, and hope for
the best! */
- slen = strlen (src);
- if (src[slen - 1] != ']' && src[slen - 1] != '>')
+ slen = strlen (src) - 1;
+ if (src[slen] != ']' && src[slen] != '>')
{ /* no recursion here! */
strcpy (dst, src);
return 0;
@@ -342,16 +356,14 @@ directory_file_name (src, dst)
return 0;
}
}
- bracket = src[slen - 1];
-
- /* If bracket is ']' or '>', bracket - 2 is the corresponding
- opening bracket. */
- if (!(ptr = index (src, bracket - 2)))
+ bracket = src[slen];
+ ptr = (char *) index (src, bracket - 2);
+ if (ptr == 0)
{ /* no opening bracket */
strcpy (dst, src);
return 0;
}
- if (!(rptr = rindex (src, '.')))
+ if (!(rptr = (char *) rindex (src, '.')))
rptr = ptr;
slen = rptr - src;
strncpy (dst, src, slen);
@@ -375,9 +387,11 @@ directory_file_name (src, dst)
&& (ptr[rlen] == ']' || ptr[rlen] == '>')
&& ptr[rlen - 1] == '.')
{
- ptr[rlen - 1] = ']';
- ptr[rlen] = '\0';
- return directory_file_name (ptr, dst);
+ char * buf = (char *) alloca (strlen (ptr) + 1);
+ strcpy (buf, ptr);
+ buf[rlen - 1] = ']';
+ buf[rlen] = '\0';
+ return directory_file_name (buf, dst);
}
else
dst[slen - 1] = ':';
@@ -396,8 +410,8 @@ directory_file_name (src, dst)
/* Process as Unix format: just remove any final slash.
But leave "/" unchanged; do not change it to "". */
strcpy (dst, src);
- if (dst[slen - 1] == '/' && slen > 1)
- dst[slen - 1] = 0;
+ if (slen > 0 && dst[slen] == '/')
+ dst[slen] = 0;
return 1;
}
@@ -405,11 +419,9 @@ DEFUN ("directory-file-name", Fdirectory_file_name, Sdirectory_file_name,
1, 1, 0,
"Returns the file name of the directory named DIR.\n\
This is the name of the file that holds the data for the directory DIR.\n\
-This operation exists because a directory is also a file, but its name as\n\
-a directory is different from its name as a file.\n\
-In Unix-syntax, this function just removes the final slash.\n\
+In Unix-syntax, this just removes the final slash.\n\
On VMS, given a VMS-syntax directory name such as \"[X.Y]\",\n\
-it returns a file name such as \"[X]Y.DIR.1\".")
+returns a file name such as \"[X]Y.DIR.1\".")
(directory)
Lisp_Object directory;
{
@@ -432,9 +444,7 @@ it returns a file name such as \"[X]Y.DIR.1\".")
}
DEFUN ("make-temp-name", Fmake_temp_name, Smake_temp_name, 1, 1, 0,
- "Generate temporary file name (string) starting with PREFIX (a string).\n\
-The Emacs process number forms part of the result,\n\
-so there is no danger of generating a name being used by another process.")
+ "Generate temporary name (string) starting with PREFIX (a string).")
(prefix)
Lisp_Object prefix;
{
@@ -449,9 +459,8 @@ DEFUN ("expand-file-name", Fexpand_file_name, Sexpand_file_name, 1, 2, 0,
Second arg DEFAULT is directory to start with if FILENAME is relative\n\
(does not start with slash); if DEFAULT is nil or missing,\n\
the current buffer's value of default-directory is used.\n\
-Filenames containing `.' or `..' as components are simplified;\n\
-initial `~/' expands to your home directory.\n\
-See also the function `substitute-in-file-name'.")
+Filenames containing . or .. as components are simplified;\n\
+initial ~ is expanded. See also the function substitute-in-file-name.")
(name, defalt)
Lisp_Object name, defalt;
{
@@ -593,367 +602,58 @@ See also the function `substitute-in-file-name'.")
}
}
- /* Now determine directory to start with and put it in newdir */
+ /* Now determine directory to start with and put it in NEWDIR. */
newdir = 0;
- if (nm[0] == '~') /* prefix ~ */
- if (nm[1] == '/'
-#ifdef VMS
- || nm[1] == ':'
-#endif /* VMS */
- || nm[1] == 0)/* ~/filename */
- {
- if (!(newdir = (unsigned char *) egetenv ("HOME")))
- newdir = (unsigned char *) "";
- nm++;
-#ifdef VMS
- nm++; /* Don't leave the slash in nm. */
-#endif /* VMS */
- }
- else /* ~user/filename */
- {
- for (p = nm; *p && (*p != '/'
-#ifdef VMS
- && *p != ':'
-#endif /* VMS */
- ); p++);
- o = (unsigned char *) alloca (p - nm + 1);
- bcopy ((char *) nm, o, p - nm);
- o [p - nm] = 0;
-
- pw = (struct passwd *) getpwnam (o + 1);
- if (!pw)
- error ("\"%s\" isn't a registered user", o + 1);
-
-#ifdef VMS
- nm = p + 1; /* skip the terminator */
-#else
- nm = p;
-#endif /* VMS */
- newdir = (unsigned char *) pw -> pw_dir;
- }
-
- if (nm[0] != '/'
-#ifdef VMS
- && !index (nm, ':')
-#endif /* not VMS */
- && !newdir)
- {
- if (NULL (defalt))
- defalt = current_buffer->directory;
- CHECK_STRING (defalt, 1);
- newdir = XSTRING (defalt)->data;
- }
-
- /* Now concatenate the directory and name to new space in the stack frame */
-
- tlen = (newdir ? strlen (newdir) + 1 : 0) + strlen (nm) + 1;
- target = (unsigned char *) alloca (tlen);
- *target = 0;
-
- if (newdir)
+ if (nm[0] == '~')
{
-#ifndef VMS
- if (nm[0] == 0 || nm[0] == '/')
- strcpy (target, newdir);
- else
-#endif
- file_name_as_directory (target, newdir);
- }
-
- strcat (target, nm);
+ if (nm[1] == '/'
#ifdef VMS
- if (index (target, '/'))
- strcpy (target, sys_translate_unix (target));
+ || nm[1] == ':'
#endif /* VMS */
-
- /* Now canonicalize by removing /. and /foo/.. if they appear */
-
- p = target;
- o = target;
-
- while (*p)
- {
-#ifdef VMS
- if (*p != ']' && *p != '>' && *p != '-')
+ || nm[1] == 0)
{
- if (*p == '\\')
- p++;
- *o++ = *p++;
- }
- else if ((p[0] == ']' || p[0] == '>') && p[0] == p[1] + 2)
- /* brackets are offset from each other by 2 */
- {
- p += 2;
- if (*p != '.' && *p != '-' && o[-1] != '.')
- /* convert [foo][bar] to [bar] */
- while (o[-1] != '[' && o[-1] != '<')
- o--;
- else if (*p == '-' && *o != '.')
- *--p = '.';
- }
- else if (p[0] == '-' && o[-1] == '.' &&
- (p[1] == '.' || p[1] == ']' || p[1] == '>'))
- /* flush .foo.- ; leave - if stopped by '[' or '<' */
- {
- do
- o--;
- while (o[-1] != '.' && o[-1] != '[' && o[-1] != '<');
- if (p[1] == '.') /* foo.-.bar ==> bar*/
- p += 2;
- else if (o[-1] == '.') /* '.foo.-]' ==> ']' */
- p++, o--;
- /* else [foo.-] ==> [-] */
+ /* Handle ~ on its own. */
+ newdir = (unsigned char *) egetenv ("HOME");
}
else
{
-#ifndef VMS4_4
- if (*p == '-' &&
- o[-1] != '[' && o[-1] != '<' && o[-1] != '.' &&
- p[1] != ']' && p[1] != '>' && p[1] != '.')
- *p = '_';
-#endif /* VMS4_4 */
- *o++ = *p++;
- }
-#else /* not VMS */
- if (*p != '/')
- {
- *o++ = *p++;
- }
- else if (!strncmp (p, "//", 2)
-#ifdef APOLLO
- /* // at start of filename is meaningful in Apollo system */
- && o != target
-#endif /* APOLLO */
- )
- {
- o = target;
- p++;
- }
- else if (p[0] == '/' && p[1] == '.' &&
- (p[2] == '/' || p[2] == 0))
- p += 2;
- else if (!strncmp (p, "/..", 3)
- /* `/../' is the "superroot" on certain file systems. */
- && o != target
- && (p[3] == '/' || p[3] == 0))
- {
- while (o != target && *--o != '/')
- ;
-#ifdef APOLLO
- if (o == target + 1 && o[-1] == '/' && o[0] == '/')
- ++o;
- else
-#endif /* APOLLO */
- if (o == target && *o == '/')
- ++o;
- p += 3;
- }
- else
- {
- *o++ = *p++;
- }
-#endif /* not VMS */
- }
-
- return make_string (target, o - target);
-}
-#if 0
-DEFUN ("expand-file-name", Fexpand_file_name, Sexpand_file_name, 1, 2, 0,
- "Convert FILENAME to absolute, and canonicalize it.\n\
-Second arg DEFAULT is directory to start with if FILENAME is relative\n\
- (does not start with slash); if DEFAULT is nil or missing,\n\
-the current buffer's value of default-directory is used.\n\
-Filenames containing `.' or `..' as components are simplified;\n\
-initial `~/' expands to your home directory.\n\
-See also the function `substitute-in-file-name'.")
- (name, defalt)
- Lisp_Object name, defalt;
-{
- unsigned char *nm;
-
- register unsigned char *newdir, *p, *o;
- int tlen;
- unsigned char *target;
- struct passwd *pw;
- int lose;
+ /* Handle ~ followed by user name. */
+ unsigned char *user = nm + 1;
+ /* Find end of name. */
+ unsigned char *ptr = (unsigned char *) index (user, '/');
+ int len = ptr ? ptr - user : strlen (user);
#ifdef VMS
- unsigned char * colon = 0;
- unsigned char * close = 0;
- unsigned char * slash = 0;
- unsigned char * brack = 0;
- int lbrack = 0, rbrack = 0;
- int dots = 0;
+ unsigned char *ptr1 = (unsigned char *) index (user, ':');
+ if (ptr1 != 0 && ptr1 - user < len)
+ len = ptr1 - user;
#endif /* VMS */
-
- CHECK_STRING (name, 0);
-
-#ifdef VMS
- /* Filenames on VMS are always upper case. */
- name = Fupcase (name);
-#endif
-
- nm = XSTRING (name)->data;
-
- /* If nm is absolute, flush ...// and detect /./ and /../.
- If no /./ or /../ we can return right away. */
- if (
- nm[0] == '/'
-#ifdef VMS
- || index (nm, ':')
-#endif /* VMS */
- )
- {
- p = nm;
- lose = 0;
- while (*p)
- {
- if (p[0] == '/' && p[1] == '/'
-#ifdef APOLLO
- /* // at start of filename is meaningful on Apollo system */
- && nm != p
-#endif /* APOLLO */
- )
- nm = p + 1;
- if (p[0] == '/' && p[1] == '~')
- nm = p + 1, lose = 1;
- if (p[0] == '/' && p[1] == '.'
- && (p[2] == '/' || p[2] == 0
- || (p[2] == '.' && (p[3] == '/' || p[3] == 0))))
- lose = 1;
-#ifdef VMS
- if (p[0] == '\\')
- lose = 1;
- if (p[0] == '/') {
- /* if dev:[dir]/, move nm to / */
- if (!slash && p > nm && (brack || colon)) {
- nm = (brack ? brack + 1 : colon + 1);
- lbrack = rbrack = 0;
- brack = 0;
- colon = 0;
- }
- slash = p;
- }
- if (p[0] == '-')
-#ifndef VMS4_4
- /* VMS pre V4.4,convert '-'s in filenames. */
- if (lbrack == rbrack)
- {
- if (dots < 2) /* this is to allow negative version numbers */
- p[0] = '_';
- }
- else
-#endif /* VMS4_4 */
- if (lbrack > rbrack &&
- ((p[-1] == '.' || p[-1] == '[' || p[-1] == '<') &&
- (p[1] == '.' || p[1] == ']' || p[1] == '>')))
- lose = 1;
-#ifndef VMS4_4
- else
- p[0] = '_';
-#endif /* VMS4_4 */
- /* count open brackets, reset close bracket pointer */
- if (p[0] == '[' || p[0] == '<')
- lbrack++, brack = 0;
- /* count close brackets, set close bracket pointer */
- if (p[0] == ']' || p[0] == '>')
- rbrack++, brack = p;
- /* detect ][ or >< */
- if ((p[0] == ']' || p[0] == '>') && (p[1] == '[' || p[1] == '<'))
- lose = 1;
- if ((p[0] == ':' || p[0] == ']' || p[0] == '>') && p[1] == '~')
- nm = p + 1, lose = 1;
- if (p[0] == ':' && (colon || slash))
- /* if dev1:[dir]dev2:, move nm to dev2: */
- if (brack)
- {
- nm = brack + 1;
- brack = 0;
- }
- /* if /pathname/dev:, move nm to dev: */
- else if (slash)
- nm = slash + 1;
- /* if node::dev:, move colon following dev */
- else if (colon && colon[-1] == ':')
- colon = p;
- /* if dev1:dev2:, move nm to dev2: */
- else if (colon && colon[-1] != ':')
- {
- nm = colon + 1;
- colon = 0;
- }
- if (p[0] == ':' && !colon)
- {
- if (p[1] == ':')
- p++;
- colon = p;
- }
- if (lbrack == rbrack)
- if (p[0] == ';')
- dots = 2;
- else if (p[0] == '.')
- dots++;
-#endif /* VMS */
- p++;
- }
- if (!lose)
- {
-#ifdef VMS
- if (index (nm, '/'))
- return build_string (sys_translate_unix (nm));
-#endif /* VMS */
- if (nm == XSTRING (name)->data)
- return name;
- return build_string (nm);
+ /* Copy the user name into temp storage. */
+ o = (unsigned char *) alloca (len + 1);
+ bcopy ((char *) user, o, len);
+ o[len] = 0;
+
+ /* Look up the user name. */
+ pw = (struct passwd *) getpwnam (o);
+ if (!pw)
+ error ("User \"%s\" is not known", o);
+ newdir = (unsigned char *) pw->pw_dir;
+
+ /* Discard the user name from NM. */
+ nm += len;
}
- }
-
- /* Now determine directory to start with and put it in NEWDIR */
-
- newdir = 0;
- if (nm[0] == '~') /* prefix ~ */
- if (nm[1] == '/'
-#ifdef VMS
- || nm[1] == ':'
-#endif /* VMS */
- || nm[1] == 0)/* ~/filename */
- {
- if (!(newdir = (unsigned char *) egetenv ("HOME")))
- newdir = (unsigned char *) "";
- nm++;
+ /* Discard the ~ from NM. */
+ nm++;
#ifdef VMS
+ if (*nm != 0)
nm++; /* Don't leave the slash in nm. */
#endif /* VMS */
- }
- else /* ~user/filename */
- {
- /* Get past ~ to user */
- unsigned char *user = nm + 1;
- /* Find end of name. */
- unsigned char *ptr = (unsigned char *) index (user, '/');
- int len = ptr ? ptr - user : strlen (user);
-#ifdef VMS
- unsigned char *ptr1 = index (user, ':');
- if (ptr1 != 0 && ptr1 - user < len)
- len = ptr1 - user;
-#endif /* VMS */
- /* Copy the user name into temp storage. */
- o = (unsigned char *) alloca (len + 1);
- bcopy ((char *) user, o, len);
- o[len] = 0;
-
- /* Look up the user name. */
- pw = (struct passwd *) getpwnam (o + 1);
- if (!pw)
- error ("\"%s\" isn't a registered user", o + 1);
-
- newdir = (unsigned char *) pw->pw_dir;
-
- /* Discard the user name from NM. */
- nm += len;
- }
+
+ if (newdir == 0)
+ newdir = (unsigned char *) "";
+ }
if (nm[0] != '/'
#ifdef VMS
@@ -967,9 +667,25 @@ See also the function `substitute-in-file-name'.")
newdir = XSTRING (defalt)->data;
}
+ if (newdir != 0)
+ {
+ /* Get rid of any slash at the end of newdir. */
+ int length = strlen (newdir);
+ if (length > 1 && newdir[length - 1] == '/')
+ {
+ unsigned char *temp = (unsigned char *) alloca (length);
+ bcopy (newdir, temp, length - 1);
+ temp[length - 1] = 0;
+ newdir = temp;
+ }
+ tlen = length + 1;
+ }
+ else
+ tlen = 0;
+
/* Now concatenate the directory and name to new space in the stack frame */
- tlen = (newdir ? strlen (newdir) + 1 : 0) + strlen (nm) + 1;
+ tlen += strlen (nm) + 1;
target = (unsigned char *) alloca (tlen);
*target = 0;
@@ -1066,7 +782,7 @@ See also the function `substitute-in-file-name'.")
if (o == target + 1 && o[-1] == '/' && o[0] == '/')
++o;
else
-#endif /* APOLLO */
+#endif APOLLO
if (o == target && *o == '/')
++o;
p += 3;
@@ -1080,18 +796,15 @@ See also the function `substitute-in-file-name'.")
return make_string (target, o - target);
}
-#endif
DEFUN ("substitute-in-file-name", Fsubstitute_in_file_name,
Ssubstitute_in_file_name, 1, 1, 0,
- "Substitute environment variables referred to in FILENAME.\n\
-`$FOO' where FOO is an environment variable name means to substitute\n\
-the value of that variable. The variable name should be terminated\n\
-with a character not a letter, digit or underscore; otherwise, enclose\n\
-the entire variable name in braces.\n\
-If `/~' appears, all of FILENAME through that `/' is discarded.\n\n\
-On VMS, `$' substitution is not done; this function does little and only\n\
-duplicates what `expand-file-name' does.")
+ "Substitute environment variables referred to in STRING.\n\
+A $ begins a request to substitute; the env variable name is the alphanumeric\n\
+characters and underscores after the $, or is surrounded by braces.\n\
+If a ~ appears following a /, everything through that / is discarded.\n\
+On VMS, $ substitution is not done; this function does little and only\n\
+duplicates what expand-file-name does.")
(string)
Lisp_Object string;
{
@@ -1318,8 +1031,8 @@ barf_or_query_if_file_exists (absname, querystring, interactive)
Fcons (build_string ("File already exists"),
Fcons (absname, Qnil)));
GCPRO1 (absname);
- tem = do_yes_or_no_p (format1 ("File %s already exists; %s anyway? ",
- XSTRING (absname)->data, querystring));
+ tem = Fyes_or_no_p (format1 ("File %s already exists; %s anyway? ",
+ XSTRING (absname)->data, querystring));
UNGCPRO;
if (NULL (tem))
Fsignal (Qfile_already_exists,
@@ -1331,8 +1044,8 @@ barf_or_query_if_file_exists (absname, querystring, interactive)
DEFUN ("copy-file", Fcopy_file, Scopy_file, 2, 4,
"fCopy file: \nFCopy %s to file: \np",
- "Copy FILE to NEWNAME. Both args must be strings.\n\
-Signals a `file-already-exists' error if file NEWNAME already exists,\n\
+ "Copy FILE to NEWNAME. Both args strings.\n\
+Signals a file-already-exists error if NEWNAME already exists,\n\
unless a third argument OK-IF-ALREADY-EXISTS is supplied and non-nil.\n\
A number as third arg means request confirmation if NEWNAME already exists.\n\
This is what happens in interactive use with M-x.\n\
@@ -1419,40 +1132,6 @@ that the old one has. (This works on only some systems.)")
return Qnil;
}
-DEFUN ("make-directory", Fmake_directory, Smake_directory, 1, 1, "FMake directory: ",
- "Create a directory. One argument, a file name string.")
- (dirname)
- Lisp_Object dirname;
-{
- unsigned char *dir;
-
- CHECK_STRING (dirname, 0);
- dirname = Fexpand_file_name (dirname, Qnil);
- dir = XSTRING (dirname)->data;
-
- if (mkdir (dir, 0777) != 0)
- report_file_error ("Creating directory", Flist (1, &dirname));
-
- return Qnil;
-}
-
-DEFUN ("remove-directory", Fremove_directory, Sremove_directory, 1, 1, "FRemove directory: ",
- "Remove a directory. One argument, a file name string.")
- (dirname)
- Lisp_Object dirname;
-{
- unsigned char *dir;
-
- CHECK_STRING (dirname, 0);
- dirname = Fexpand_file_name (dirname, Qnil);
- dir = XSTRING (dirname)->data;
-
- if (rmdir (dir) != 0)
- report_file_error ("Removing directory", Flist (1, &dirname));
-
- return Qnil;
-}
-
DEFUN ("delete-file", Fdelete_file, Sdelete_file, 1, 1, "fDelete file: ",
"Delete specified file. One argument, a file name string.\n\
If file has multiple names, it continues to exist with the other names.")
@@ -1470,7 +1149,7 @@ DEFUN ("rename-file", Frename_file, Srename_file, 2, 3,
"fRename file: \nFRename %s to file: \np",
"Rename FILE as NEWNAME. Both args strings.\n\
If file has names other than FILE, it continues to have those names.\n\
-Signals a `file-already-exists' error if a file NEWNAME already exists\n\
+Signals a file-already-exists error if NEWNAME already exists\n\
unless optional third argument OK-IF-ALREADY-EXISTS is non-nil.\n\
A number as third arg means request confirmation if NEWNAME already exists.\n\
This is what happens in interactive use with M-x.")
@@ -1521,7 +1200,7 @@ This is what happens in interactive use with M-x.")
DEFUN ("add-name-to-file", Fadd_name_to_file, Sadd_name_to_file, 2, 3,
"fAdd name to file: \nFName to add to %s: \np",
"Give FILE additional name NEWNAME. Both args strings.\n\
-Signals a `file-already-exists' error if a file NEWNAME already exists\n\
+Signals a file-already-exists error if NEWNAME already exists\n\
unless optional third argument OK-IF-ALREADY-EXISTS is non-nil.\n\
A number as third arg means request confirmation if NEWNAME already exists.\n\
This is what happens in interactive use with M-x.")
@@ -1560,11 +1239,13 @@ This is what happens in interactive use with M-x.")
#ifdef S_IFLNK
DEFUN ("make-symbolic-link", Fmake_symbolic_link, Smake_symbolic_link, 2, 3,
- "FMake symbolic link to file: \nFMake symbolic link to file %s: \np",
- "Make a symbolic link to FILENAME, named LINKNAME. Both args strings.\n\
-Signals a `file-already-exists' error if a file NEWNAME already exists\n\
+ "sMake symbolic link to file: \nFMake symbolic link to file %s: \np",
+ "Make a symbolic link to TARGET, named LINKNAME. Both args strings.\n\
+There is no completion for LINKNAME, because it is read simply as a string;\n\
+this is to enable you to make a link to a relative file name.\n\n\
+Signals a file-already-exists error if LINKNAME already exists\n\
unless optional third argument OK-IF-ALREADY-EXISTS is non-nil.\n\
-A number as third arg means request confirmation if NEWNAME already exists.\n\
+A number as third arg means request confirmation if LINKNAME already exists.\n\
This happens for interactive use with M-x.")
(filename, newname, ok_if_already_exists)
Lisp_Object filename, newname, ok_if_already_exists;
@@ -1587,21 +1268,26 @@ This happens for interactive use with M-x.")
XTYPE (ok_if_already_exists) == Lisp_Int);
if (0 > symlink (XSTRING (filename)->data, XSTRING (newname)->data))
{
- /* If we didn't complain already, silently delete existing file. */
+ int failure = 1;
+ /* If we failed because the link name already exists,
+ try deleting it. */
if (errno == EEXIST)
{
- unlink (XSTRING (filename)->data);
- if (0 <= symlink (XSTRING (filename)->data, XSTRING (newname)->data))
- return Qnil;
+ unlink (XSTRING (newname)->data);
+ failure = 0 > symlink (XSTRING (filename)->data,
+ XSTRING (newname)->data);
}
-
+ /* If we have not started to win, report the error. */
+ if (failure)
+ {
#ifdef NO_ARG_ARRAY
- args[0] = filename;
- args[1] = newname;
- report_file_error ("Making symbolic link", Flist (2, args));
+ args[0] = filename;
+ args[1] = newname;
+ report_file_error ("Making symbolic link", Flist (2, args));
#else
- report_file_error ("Making symbolic link", Flist (2, &filename));
+ report_file_error ("Making symbolic link", Flist (2, &filename));
#endif
+ }
}
UNGCPRO;
return Qnil;
@@ -1611,8 +1297,9 @@ This happens for interactive use with M-x.")
#ifdef VMS
DEFUN ("define-logical-name", Fdefine_logical_name, Sdefine_logical_name,
- 2, 2, "sDefine logical name: \nsDefine logical name %s as: ",
- "Define the job-wide logical name NAME to have the value STRING.\n\
+ 2, 2,
+ "sDefine logical name: \nsDefine logical name %s as: ",
+ "Define the job-wide logical name NAME to have the value STRING.\n\
If STRING is nil or a null string, the logical name NAME is deleted.")
(varname, string)
Lisp_Object varname;
@@ -1658,8 +1345,7 @@ DEFUN ("sysnetunam", Fsysnetunam, Ssysnetunam, 2, 2, 0,
DEFUN ("file-name-absolute-p", Ffile_name_absolute_p, Sfile_name_absolute_p,
1, 1, 0,
- "Return t if file FILENAME specifies an absolute path name.\n\
-On Unix, this is a name starting with a `/' or a `~'.")
+ "Return t if file FILENAME specifies an absolute path name.")
(filename)
Lisp_Object filename;
{
@@ -1682,34 +1368,25 @@ On Unix, this is a name starting with a `/' or a `~'.")
DEFUN ("file-exists-p", Ffile_exists_p, Sfile_exists_p, 1, 1, 0,
"Return t if file FILENAME exists. (This does not mean you can read it.)\n\
-See also `file-readable-p' and `file-attributes'.")
+See also file-readable-p and file-attributes.")
(filename)
Lisp_Object filename;
{
Lisp_Object abspath;
+ struct stat sb;
CHECK_STRING (filename, 0);
abspath = Fexpand_file_name (filename, Qnil);
- return (access (XSTRING (abspath)->data, 0) >= 0) ? Qt : Qnil;
-}
-
-DEFUN ("file-executable-p", Ffile_executable_p, Sfile_executable_p, 1, 1, 0,
- "Return t if FILENAME can be executed by you.\n\
-For directories this means you can change to that directory.")
- (filename)
- Lisp_Object filename;
-
-{
- Lisp_Object abspath;
-
- CHECK_STRING (filename, 0);
- abspath = Fexpand_file_name (filename, Qnil);
- return (access (XSTRING (abspath)->data, 1) >= 0) ? Qt : Qnil;
+#ifdef S_IFLNK
+ return (lstat (XSTRING (abspath)->data, &sb) >= 0) ? Qt : Qnil;
+#else
+ return (stat (XSTRING (abspath)->data, &sb) >= 0) ? Qt : Qnil;
+#endif
}
DEFUN ("file-readable-p", Ffile_readable_p, Sfile_readable_p, 1, 1, 0,
"Return t if file FILENAME exists and you can read it.\n\
-See also `file-exists-p' and `file-attributes'.")
+See also file-exists-p and file-attributes.")
(filename)
Lisp_Object filename;
{
@@ -1908,10 +1585,10 @@ before the error is signaled.")
struct stat st;
register int fd;
register int inserted = 0;
- register int how_much;
+ register int i = 0;
int count = specpdl_ptr - specpdl;
struct gcpro gcpro1;
-
+
GCPRO1 (filename);
if (!NULL (current_buffer->read_only))
Fbarf_if_buffer_read_only();
@@ -1923,7 +1600,11 @@ before the error is signaled.")
#ifndef APOLLO
if (stat (XSTRING (filename)->data, &st) < 0
- || (fd = open (XSTRING (filename)->data, 0)) < 0)
+#if defined (AIX) && defined (S_ISMPX)
+ /* Don't let emacs open /dev/pts, as it causes kernel confusion. */
+ || S_ISMPX (st.st_mode)
+#endif
+ || (fd = open (XSTRING (filename)->data, 0)) < 0)
#else
if ((fd = open (XSTRING (filename)->data, 0)) < 0
|| fstat (fd, &st) < 0)
@@ -1933,12 +1614,18 @@ before the error is signaled.")
if (NULL (visit))
report_file_error ("Opening input file", Fcons (filename, Qnil));
st.st_mtime = -1;
- how_much = 0;
goto notfound;
}
record_unwind_protect (close_file_unwind, make_number (fd));
+#ifdef VMS
+ /* VAXCRTL adds implied carriage control to certain record types. */
+ if (st.st_fab_rfm == FAB$C_FIX
+ && (st.st_fab_rat & (FAB$M_FTN | FAB$M_CR) != 0))
+ st.st_size += st.st_size / st.st_fab_mrs;
+#endif
+
/* Supposedly happens on VMS. */
if (st.st_size < 0)
error ("File size is negative");
@@ -1952,7 +1639,7 @@ before the error is signaled.")
}
if (NULL (visit))
- prepare_to_modify_buffer (point, point);
+ prepare_to_modify_buffer ();
move_gap (point);
if (GAP_SIZE < st.st_size)
@@ -1965,7 +1652,7 @@ before the error is signaled.")
if (this <= 0)
{
- how_much = this;
+ i = this;
break;
}
@@ -1985,7 +1672,7 @@ before the error is signaled.")
/* Discard the unwind protect */
specpdl_ptr = specpdl + count;
- if (how_much < 0)
+ if (i < 0)
error ("IO error reading %s: %s",
XSTRING (filename)->data, err_str (errno));
@@ -2012,15 +1699,8 @@ before the error is signaled.")
report_file_error ("Opening input file", Fcons (filename, Qnil));
}
- signal_after_change (point, 0, inserted);
-
- {
- Lisp_Object result = Fcons (filename,
- Fcons (make_number (inserted),
- Qnil));
- UNGCPRO;
- return result;
- }
+ UNGCPRO;
+ return Fcons (filename, Fcons (make_number (inserted), Qnil));
}
DEFUN ("write-region", Fwrite_region, Swrite_region, 3, 5,
@@ -2031,12 +1711,10 @@ START, END and FILENAME. START and END are buffer positions.\n\
Optional fourth argument APPEND if non-nil means\n\
append to existing file contents (if any).\n\
Optional fifth argument VISIT if t means\n\
- set the last-save-file-modtime of buffer to this file's modtime\n\
+ set last-save-file-modtime of buffer to this file's modtime\n\
and mark buffer not modified.\n\
If VISIT is neither t nor nil, it means do not print\n\
- the \"Wrote file\" message.\n\
-Kludgy feature: if START is a string, then that string is written\n\
-to the file, instead of any buffer contents, and END is ignored.")
+ the \"Wrote file\" message.")
(start, end, filename, append, visit)
Lisp_Object start, end, filename, append, visit;
{
@@ -2057,7 +1735,7 @@ to the file, instead of any buffer contents, and END is ignored.")
XFASTINT (start) = BEG;
XFASTINT (end) = Z;
}
- else if (XTYPE (start) != Lisp_String)
+ else
validate_region (&start, &end);
filename = Fexpand_file_name (filename, Qnil);
@@ -2080,8 +1758,8 @@ to the file, instead of any buffer contents, and END is ignored.")
desc = open (fn, O_RDWR);
if (desc < 0)
desc = creat_copy_attrs (XTYPE (current_buffer->filename) == Lisp_String
- ? XSTRING (current_buffer->filename)->data : 0,
- fn);
+ ? XSTRING (current_buffer->filename)->data : 0,
+ fn);
}
else /* Write to temporary name and rename if no errors */
{
@@ -2103,8 +1781,7 @@ to the file, instead of any buffer contents, and END is ignored.")
fn = fname;
fname = 0;
desc = creat (fn, 0666);
-#if 0 /* This can clobber an existing file and fail to replace it,
- if the user runs out of space. */
+#if 0
if (desc < 0)
{
/* We can't make a new version;
@@ -2119,7 +1796,7 @@ to the file, instead of any buffer contents, and END is ignored.")
desc = creat (fn, 0666);
}
#else /* not VMS */
- desc = creat (fn, auto_saving ? auto_save_mode_bits : 0666);
+ desc = creat (fn, 0666);
#endif /* not VMS */
if (desc < 0)
@@ -2164,15 +1841,7 @@ to the file, instead of any buffer contents, and END is ignored.")
#endif
failure = 0;
- immediate_quit = 1;
-
- if (XTYPE (start) == Lisp_String)
- {
- failure = 0 > e_write (desc, XSTRING (start)->data,
- XSTRING (start)->size);
- save_errno = errno;
- }
- else if (XINT (start) != XINT (end))
+ if (XINT (start) != XINT (end))
{
if (XINT (start) < GPT)
{
@@ -2192,13 +1861,9 @@ to the file, instead of any buffer contents, and END is ignored.")
}
}
- immediate_quit = 0;
-
#ifndef USG
#ifndef VMS
#ifndef BSD4_1
-#ifndef alliant /* trinkle@cs.purdue.edu says fsync can return EBUSY
- on alliant, for no visible reason. */
/* Note fsync appears to change the modtime on BSD4.2 (both vax and sun).
Disk full in NFS may be reported here. */
if (fsync (desc) < 0)
@@ -2206,15 +1871,11 @@ to the file, instead of any buffer contents, and END is ignored.")
#endif
#endif
#endif
-#endif
-
- /* Spurious "file has changed on disk" warnings have been
- observed on Suns as well.
- It seems that `close' can change the modtime, under nfs.
- (This has supposedly been fixed in Sunos 4,
- but who knows about all the other machines with NFS?) */
#if 0
+ /* Spurious "file has changed on disk" warnings have been
+ observed on Sun 3 as well. Maybe close changes the modtime
+ with nfs as well. */
/* On VMS and APOLLO, must do the stat after the close
since closing changes the modtime. */
@@ -2225,7 +1886,7 @@ to the file, instead of any buffer contents, and END is ignored.")
fstat (desc, &st);
#endif
#endif
-#endif
+#endif /* 0 */
/* NFS can report a write failure now. */
if (close (desc) < 0)
@@ -2236,8 +1897,8 @@ to the file, instead of any buffer contents, and END is ignored.")
if (fname)
{
if (!failure)
- failure = (rename (fn, fname) != 0), save_errno = errno;
- fn = fname;
+ failure = (rename_sans_version (fn, fname) != 0), save_errno = errno;
+ fn = vms_file_written; /* this is filled by rename_sans_version */
}
#endif /* VMS */
@@ -2353,31 +2014,13 @@ Next attempt to save will certainly not complain of a discrepancy.")
current_buffer->modtime = 0;
return Qnil;
}
-
-DEFUN ("set-visited-file-modtime", Fset_visited_file_modtime,
- Sset_visited_file_modtime, 0, 0, 0,
- "Update buffer's recorded modification time from the visited file's time.\n\
-Useful if the buffer was not read from the file normally\n\
-or if the file itself has been changed for some known benign reason.")
- ()
-{
- register Lisp_Object filename;
- struct stat st;
-
- filename = Fexpand_file_name (current_buffer->filename, Qnil);
-
- if (stat (XSTRING (filename)->data, &st) >= 0)
- current_buffer->modtime = st.st_mtime;
-
- return Qnil;
-}
Lisp_Object
auto_save_error ()
{
unsigned char *name = XSTRING (current_buffer->name)->data;
- ring_bell ();
+ bell ();
message ("Autosaving...error for %s", name);
Fsleep_for (make_number (1));
message ("Autosaving...error!for %s", name);
@@ -2390,40 +2033,28 @@ auto_save_error ()
Lisp_Object
auto_save_1 ()
{
- unsigned char *fn;
- struct stat st;
-
- /* Get visited file's mode to become the auto save file's mode. */
- if (stat (XSTRING (current_buffer->filename)->data, &st) >= 0)
- /* But make sure we can overwrite it later! */
- auto_save_mode_bits = st.st_mode | 0600;
- else
- auto_save_mode_bits = 0666;
-
return
Fwrite_region (Qnil, Qnil,
current_buffer->auto_save_file_name,
Qnil, Qlambda);
}
-DEFUN ("do-auto-save", Fdo_auto_save, Sdo_auto_save, 0, 2, "",
+DEFUN ("do-auto-save", Fdo_auto_save, Sdo_auto_save, 0, 1, "",
"Auto-save all buffers that need it.\n\
This is all buffers that have auto-saving enabled\n\
and are changed since last auto-saved.\n\
Auto-saving writes the buffer into a file\n\
so that your editing is not lost if the system crashes.\n\
This file is not the file you visited; that changes only when you save.\n\n\
-Non-nil first argument means do not print any message if successful.\n\
-Non-nil second argumet means save only current buffer.")
+Non-nil argument means do not print any message if successful.")
(nomsg)
Lisp_Object nomsg;
{
struct buffer *old = current_buffer, *b;
Lisp_Object tail, buf;
int auto_saved = 0;
- char *omessage = echo_area_glyphs;
- extern minibuf_level;
-
+ int tried = 0;
+ char *omessage = echo_area_contents;
/* No GCPRO needed, because (when it matters) all Lisp_Object variables
point to non-strings reached from Vbuffer_alist. */
@@ -2431,11 +2062,6 @@ Non-nil second argumet means save only current buffer.")
if (minibuf_level)
nomsg = Qt;
- /* Vrun_hooks is nil before emacs is dumped, and inc-vers.el will
- eventually call do-auto-save, so don't err here in that case. */
- if (!NULL (Vrun_hooks))
- call1 (Vrun_hooks, intern ("auto-save-hook"));
-
for (tail = Vbuffer_alist; XGCTYPE (tail) == Lisp_Cons;
tail = XCONS (tail)->cdr)
{
@@ -2448,6 +2074,9 @@ Non-nil second argumet means save only current buffer.")
&& b->save_modified < BUF_MODIFF (b)
&& b->auto_save_modified < BUF_MODIFF (b))
{
+ /* If we at least consider a buffer for auto-saving,
+ don't try again for a suitable time. */
+ tried++;
if ((XFASTINT (b->save_length) * 10
> (BUF_Z (b) - BUF_BEG (b)) * 13)
/* A short file is likely to change a large fraction;
@@ -2456,13 +2085,9 @@ Non-nil second argumet means save only current buffer.")
/* These messages are frequent and annoying for `*mail*'. */
&& !EQ (b->filename, Qnil))
{
- /* It has shrunk too much; turn off auto-saving here. */
- message ("Buffer %s has shrunk a lot; auto save turned off there",
+ /* It has shrunk too much; don't checkpoint. */
+ message ("Buffer %s has shrunk a lot; not autosaving it",
XSTRING (b->name)->data);
- /* User can reenable saving with M-x auto-save. */
- b->auto_save_file_name = Qnil;
- /* Prevent warning from repeating if user does so. */
- XFASTINT (b->save_length) = 0;
Fsleep_for (make_number (1));
continue;
}
@@ -2477,7 +2102,7 @@ Non-nil second argumet means save only current buffer.")
}
}
- if (auto_saved)
+ if (tried)
record_auto_save ();
if (auto_saved && NULL (nomsg))
@@ -2517,11 +2142,9 @@ DEFUN ("read-file-name-internal", Fread_file_name_internal, Sread_file_name_inte
/* action is nil for complete, t for return list of completions,
lambda for verify final value */
{
- Lisp_Object name, specdir, realdir, val, orig_string;
-
+ Lisp_Object name, specdir, realdir, val;
if (XSTRING (string)->size == 0)
{
- orig_string = Qnil;
name = string;
realdir = dir;
if (EQ (action, Qlambda))
@@ -2529,7 +2152,6 @@ DEFUN ("read-file-name-internal", Fread_file_name_internal, Sread_file_name_inte
}
else
{
- orig_string = string;
string = Fsubstitute_in_file_name (string);
name = Ffile_name_nondirectory (string);
realdir = Ffile_name_directory (string);
@@ -2544,11 +2166,7 @@ DEFUN ("read-file-name-internal", Fread_file_name_internal, Sread_file_name_inte
specdir = Ffile_name_directory (string);
val = Ffile_name_completion (name, realdir);
if (XTYPE (val) != Lisp_String)
- {
- if (NULL (Fstring_equal (string, orig_string)))
- return string;
- return (val);
- }
+ return (val);
if (!NULL (specdir))
val = concat2 (specdir, val);
@@ -2594,96 +2212,15 @@ DEFUN ("read-file-name-internal", Fread_file_name_internal, Sread_file_name_inte
return Ffile_exists_p (string);
}
-DEFUN ("read-file-name", Fread_file_name, Sread_file_name, 1, 5, 0,
- "Read file name, prompting with PROMPT and completing in directory DIR.\n\
-Value is not expanded---you must call `expand-file-name' yourself.\n\
-Default name to DEFAULT if user enters a null string.\n\
- (If DEFAULT is omitted, the visited file name is used.)\n\
-Fourth arg MUSTMATCH non-nil means require existing file's name.\n\
- Non-nil and non-t means also require confirmation after completion.\n\
-Fifth arg INITIAL specifies text to start with.\n\
-DIR defaults to current buffer's directory default.")
- (prompt, dir, defalt, mustmatch, initial)
- Lisp_Object prompt, dir, defalt, mustmatch, initial;
-{
- Lisp_Object val, insdef, tem, backup_n;
- struct gcpro gcpro1, gcpro2;
- register char *homedir;
- int count;
-
- if (NULL (dir))
- dir = current_buffer->directory;
- if (NULL (defalt))
- defalt = current_buffer->filename;
-
- /* If dir starts with user's homedir, change that to ~. */
- homedir = (char *) egetenv ("HOME");
- if (homedir != 0
- && XTYPE (dir) == Lisp_String
- && !strncmp (homedir, XSTRING (dir)->data, strlen (homedir))
- && XSTRING (dir)->data[strlen (homedir)] == '/')
- {
- dir = make_string (XSTRING (dir)->data + strlen (homedir) - 1,
- XSTRING (dir)->size - strlen (homedir) + 1);
- XSTRING (dir)->data[0] = '~';
- }
-
- if (insert_default_directory)
- {
- insdef = dir;
- if (!NULL (initial))
- {
- Lisp_Object args[2];
-
- args[0] = insdef;
- args[1] = initial;
- insdef = Fconcat (2, args);
- backup_n = make_number (- (XSTRING (initial)->size));
- }
- else
- backup_n = Qnil;
- }
- else
- {
- insdef = build_string ("");
- backup_n = Qnil;
- }
-
-#ifdef VMS
- count = specpdl_ptr - specpdl;
- specbind (intern ("completion-ignore-case"), Qt);
-#endif
-
- GCPRO2 (insdef, defalt);
- val = Fcompleting_read (prompt, intern ("read-file-name-internal"),
- dir, mustmatch,
- insert_default_directory ? insdef : Qnil, backup_n);
-
-#ifdef VMS
- unbind_to (count, Qnil);
-#endif
-
- UNGCPRO;
- if (NULL (val))
- error ("No file name specified");
- tem = Fstring_equal (val, insdef);
- if (!NULL (tem) && !NULL (defalt))
- return defalt;
- return Fsubstitute_in_file_name (val);
-}
-
-#if 0 /* Old version */
-DEFUN ("read-file-name", Fread_file_name, Sread_file_name, 1, 5, 0,
+DEFUN ("read-file-name", Fread_file_name, Sread_file_name, 1, 4, 0,
"Read file name, prompting with PROMPT and completing in directory DIR.\n\
-Value is not expanded---you must call `expand-file-name' yourself.\n\
+Value is not expanded! You must call expand-file-name yourself.\n\
Default name to DEFAULT if user enters a null string.\n\
- (If DEFAULT is omitted, the visited file name is used.)\n\
Fourth arg MUSTMATCH non-nil means require existing file's name.\n\
Non-nil and non-t means also require confirmation after completion.\n\
-Fifth arg INITIAL specifies text to start with.\n\
DIR defaults to current buffer's directory default.")
- (prompt, dir, defalt, mustmatch, initial)
- Lisp_Object prompt, dir, defalt, mustmatch, initial;
+ (prompt, dir, defalt, mustmatch)
+ Lisp_Object prompt, dir, defalt, mustmatch;
{
Lisp_Object val, insdef, tem;
struct gcpro gcpro1, gcpro2;
@@ -2707,9 +2244,7 @@ DIR defaults to current buffer's directory default.")
XSTRING (dir)->data[0] = '~';
}
- if (!NULL (initial))
- insdef = initial;
- else if (insert_default_directory)
+ if (insert_default_directory)
insdef = dir;
else
insdef = build_string ("");
@@ -2722,10 +2257,10 @@ DIR defaults to current buffer's directory default.")
GCPRO2 (insdef, defalt);
val = Fcompleting_read (prompt, intern ("read-file-name-internal"),
dir, mustmatch,
- insert_default_directory ? insdef : Qnil, Qnil);
+ insert_default_directory ? insdef : Qnil);
#ifdef VMS
- unbind_to (count, Qnil);
+ unbind_to (count);
#endif
UNGCPRO;
@@ -2736,7 +2271,6 @@ DIR defaults to current buffer's directory default.")
return defalt;
return Fsubstitute_in_file_name (val);
}
-#endif /* Old version */
syms_of_fileio ()
{
@@ -2773,8 +2307,6 @@ nil means use format `var'. This variable is meaningful only on VMS.");
defsubr (&Sexpand_file_name);
defsubr (&Ssubstitute_in_file_name);
defsubr (&Scopy_file);
- defsubr (&Smake_directory);
- defsubr (&Sremove_directory);
defsubr (&Sdelete_file);
defsubr (&Srename_file);
defsubr (&Sadd_name_to_file);
@@ -2789,7 +2321,6 @@ nil means use format `var'. This variable is meaningful only on VMS.");
#endif /* HPUX_NET */
defsubr (&Sfile_name_absolute_p);
defsubr (&Sfile_exists_p);
- defsubr (&Sfile_executable_p);
defsubr (&Sfile_readable_p);
defsubr (&Sfile_writable_p);
defsubr (&Sfile_symlink_p);
@@ -2801,7 +2332,6 @@ nil means use format `var'. This variable is meaningful only on VMS.");
defsubr (&Swrite_region);
defsubr (&Sverify_visited_file_modtime);
defsubr (&Sclear_visited_file_modtime);
- defsubr (&Sset_visited_file_modtime);
defsubr (&Sdo_auto_save);
defsubr (&Sset_buffer_auto_saved);
defsubr (&Srecent_auto_save_p);
diff --git a/src/filelock.c b/src/filelock.c
index 81e72432c06..3850a527f14 100644
--- a/src/filelock.c
+++ b/src/filelock.c
@@ -20,20 +20,36 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <sys/types.h>
#include <sys/stat.h>
#include "config.h"
+#ifdef hpux
+/* needed by <pwd.h> */
+#include <stdio.h>
+#undef NULL
+#endif
+#include "lisp.h"
+#include "paths.h"
+#include "buffer.h"
+
+#ifdef VMS
+#include "vms-pwd.h"
+#else
#include <pwd.h>
+#endif
+
#include <errno.h>
#include <sys/file.h>
#ifdef USG
#include <fcntl.h>
#endif /* USG */
-#undef NULL
-#include "lisp.h"
-#include "paths.h"
-#include "buffer.h"
+#include "filetypes.h"
extern int errno;
+#ifdef VMS
+/* Prevent the file from being totally empty. */
+static dummy () {}
+#endif
+
#ifdef CLASH_DETECTION
/* If system does not have symbolic links, it does not have lstat.
@@ -78,6 +94,27 @@ lock_file_owner_name (lfname)
and put in the Emacs lock directory. */
/* (ie., /ka/king/junk.tex -> /!/!ka!king!junk.tex). */
+/* If SHORT_FILE_NAMES is defined, the lock file name is the hex
+ representation of a 14-bytes CRC generated from the file name
+ and put in the Emacs lock directory (not very nice, but it works).
+ (ie., /ka/king/junk.tex -> /!/ec92d3ed24a8f0). */
+
+#ifdef SHORT_FILE_NAMES
+
+# define CREATE_LOCK_FILE_NAME(lfname, fn) \
+ { lfname = (char *) alloca (14 + strlen (PATH_LOCK) + 1); \
+ fill_in_lock_short_file_name (lfname, fn); }
+
+#else
+
+# define CREATE_LOCK_FILE_NAME(lfname, fn) \
+ { lfname = (char *) alloca (XSTRING (fn)->size + strlen (PATH_LOCK) + 1); \
+ fill_in_lock_file_name (lfname, fn); }
+
+#endif
+
+
+
void
lock_file (fn)
register Lisp_Object fn;
@@ -86,8 +123,7 @@ lock_file (fn)
register char *lfname;
/* Create the name of the lock-file for file fn */
- lfname = (char *) alloca (XSTRING (fn)->size + strlen (PATH_LOCK) + 1);
- fill_in_lock_file_name (lfname, fn);
+ CREATE_LOCK_FILE_NAME (lfname, fn);
/* See if this file is visited and has changed on disk since it was visited. */
{
@@ -136,6 +172,41 @@ fill_in_lock_file_name (lockfile, fn)
}
}
+#ifdef SHORT_FILE_NAMES
+fill_in_lock_short_file_name (lockfile, fn)
+ register char *lockfile;
+ register Lisp_Object fn;
+{
+ register union
+ {
+ unsigned int word [2];
+ unsigned char byte [8];
+ } crc;
+ register unsigned char *p, new;
+
+ /* 7-bytes cyclic code for burst correction on byte-by-byte basis.
+ the used polynomial is D^7 + D^6 + D^3 +1. pot@fdt.CNUCE.CNR.IT */
+
+ crc.word[0] = crc.word[1] = 0;
+
+ for (p = XSTRING (fn)->data; new = *p++; )
+ {
+ new += crc.byte[7];
+ crc.byte[7] = crc.byte[6];
+ crc.byte[6] = crc.byte[5] + new;
+ crc.byte[5] = crc.byte[4];
+ crc.byte[4] = crc.byte[3];
+ crc.byte[3] = crc.byte[2] + new;
+ crc.byte[2] = crc.byte[1];
+ crc.byte[1] = crc.byte[0];
+ crc.byte[0] = new;
+ }
+ sprintf (lockfile, "%s%.2x%.2x%.2x%.2x%.2x%.2x%.2x", PATH_LOCK,
+ crc.byte[0], crc.byte[1], crc.byte[2], crc.byte[3],
+ crc.byte[4], crc.byte[5], crc.byte[6]);
+}
+#endif /* SHORT_FILE_NAMES */
+
/* Lock the lock file named LFNAME.
If MODE is O_WRONLY, we do so even if it is already locked.
If MODE is O_WRONLY | O_EXCL | O_CREAT, we do so only if it is free.
@@ -150,7 +221,7 @@ lock_file_1 (lfname, mode)
if ((fd = open (lfname, mode, 0666)) >= 0)
{
-#ifdef USG
+#ifdef NO_FCHMOD
chmod (lfname, 0666);
#else
fchmod (fd, 0666);
@@ -231,8 +302,7 @@ unlock_file (fn)
{
register char *lfname;
- lfname = (char *) alloca (XSTRING (fn)->size + strlen (PATH_LOCK) + 1);
- fill_in_lock_file_name (lfname, fn);
+ CREATE_LOCK_FILE_NAME (lfname, fn);
lock_superlock (lfname);
@@ -257,7 +327,7 @@ lock_superlock (lfname)
}
if (fd >= 0)
{
-#ifdef USG
+#ifdef NO_FCHMOD
chmod (PATH_SUPERLOCK, 0666);
#else
fchmod (fd, 0666);
@@ -286,7 +356,7 @@ unlock_all_files ()
DEFUN ("lock-buffer", Flock_buffer, Slock_buffer,
0, 1, 0,
- "Lock FILE, if current buffer is modified.\n\
+ "Locks FILE, if current buffer is modified.\n\
FILE defaults to current buffer's visited file,\n\
or else nothing is done if current buffer isn't visiting a file.")
(fn)
@@ -304,7 +374,7 @@ or else nothing is done if current buffer isn't visiting a file.")
DEFUN ("unlock-buffer", Funlock_buffer, Sunlock_buffer,
0, 0, 0,
- "Unlock the file visited in the current buffer,\n\
+ "Unlocks the file visited in the current buffer,\n\
if it should normally be locked.")
()
{
@@ -320,13 +390,13 @@ if it should normally be locked.")
unlock_buffer (buffer)
struct buffer *buffer;
{
- if (buffer->save_modified < BUF_MODIFF (buffer) &&
- XTYPE (buffer->filename) == Lisp_String)
+ if (buffer->save_modified < BUF_MODIFF (buffer)
+ && XTYPE (buffer->filename) == Lisp_String)
unlock_file (buffer->filename);
}
DEFUN ("file-locked-p", Ffile_locked_p, Sfile_locked_p, 0, 1, 0,
- "Return nil if the FILENAME is not locked,\n\
+ "Returns nil if the FILENAME is not locked,\n\
t if it is locked by you, else a string of the name of the locker.")
(fn)
Lisp_Object fn;
@@ -337,8 +407,7 @@ t if it is locked by you, else a string of the name of the locker.")
fn = Fexpand_file_name (fn, Qnil);
/* Create the name of the lock-file for file filename */
- lfname = (char *) alloca (XSTRING (fn)->size + strlen (PATH_LOCK) + 1);
- fill_in_lock_file_name (lfname, fn);
+ CREATE_LOCK_FILE_NAME (lfname, fn);
owner = current_lock_owner (lfname);
if (owner <= 0)
diff --git a/src/filemode.c b/src/filemode.c
new file mode 100644
index 00000000000..fd5988049f1
--- /dev/null
+++ b/src/filemode.c
@@ -0,0 +1,196 @@
+/* Examine the result of stat and make a string describing file modes.
+ Copyright (C) 1985 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+In other words, you are welcome to use, share and improve this program.
+You are forbidden to forbid anyone else to use, share and improve
+what you give them. Help stamp out software-hoarding! */
+
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "filetypes.h"
+
+/* filemodestring - set file attribute data
+
+*** WARNING! FILE STRUCTURE DEPENDENT ***
+
+ Filemodestring converts the data in the st_mode field of file status
+block `s' to a 10 character attribute string, which it stores in
+the block that `a' points to.
+This attribute string is modelled after the string produced by the Berkeley ls.
+
+As usual under Unix, the elements of the string are numbered
+from 0. Their meanings are:
+
+ 0 File type. 'd' for directory, 'c' for character
+ special, 'b' for block special, 'm' for multiplex,
+ 'l' for symbolic link, 's' for socket, 'p' for fifo,
+ '-' for any other file type
+
+ 1 'r' if the owner may read, '-' otherwise.
+
+ 2 'w' if the owner may write, '-' otherwise.
+
+ 3 'x' if the owner may execute, 's' if the file is
+ set-user-id, '-' otherwise.
+ 'S' if the file is set-user-id, but the execute
+ bit isn't set. (sys v `feature' which helps to
+ catch screw case.)
+
+ 4 'r' if group members may read, '-' otherwise.
+
+ 5 'w' if group members may write, '-' otherwise.
+
+ 6 'x' if group members may execute, 's' if the file is
+ set-group-id, '-' otherwise.
+ 'S' if it is set-group-id but not executable.
+
+ 7 'r' if any user may read, '-' otherwise.
+
+ 8 'w' if any user may write, '-' otherwise.
+
+ 9 'x' if any user may execute, 't' if the file is "sticky"
+ (will be retained in swap space after execution), '-'
+ otherwise.
+
+ */
+
+#define VOID void
+
+static char ftypelet ();
+static VOID rwx (), setst ();
+
+VOID
+filemodestring (s,a)
+ struct stat *s;
+ char *a;
+{
+ a[0] = ftypelet (s);
+ /* Aren't there symbolic names for these byte-fields? */
+ rwx ((s->st_mode & 0700) << 0, &(a[1]));
+ rwx ((s->st_mode & 0070) << 3, &(a[4]));
+ rwx ((s->st_mode & 0007) << 6, &(a[7]));
+ setst (s->st_mode, a);
+}
+
+/* ftypelet - file type letter
+
+*** WARNING! FILE STRUCTURE DEPENDENT ***
+
+ Ftypelet accepts a file status block and returns a character
+code describing the type of the file. 'd' is returned for
+directories, 'b' for block special files, 'c' for character
+special files, 'm' for multiplexor files, 'l' for symbolic link,
+'s' for socket, 'p' for fifo, '-' for any other file type
+ */
+
+static char
+ftypelet(s)
+ struct stat *s;
+{
+ switch (s->st_mode & S_IFMT)
+ {
+ default:
+ return '-';
+ case S_IFDIR:
+ return 'd';
+#ifdef S_IFLNK
+ case S_IFLNK:
+ return 'l';
+#endif
+#ifdef S_IFCHR
+ case S_IFCHR:
+ return 'c';
+#endif
+#ifdef S_IFBLK
+ case S_IFBLK:
+ return 'b';
+#endif
+#ifdef S_IFMPC
+/* These do not seem to exist */
+ case S_IFMPC:
+ case S_IFMPB:
+ return 'm';
+#endif
+#ifdef S_IFSOCK
+ case S_IFSOCK:
+ return 's';
+#endif
+#ifdef S_IFIFO
+#if S_IFIFO != S_IFSOCK
+ case S_IFIFO:
+ return 'p';
+#endif
+#endif
+#ifdef S_IFNWK /* hp-ux hack */
+ case S_IFNWK:
+ return 'n';
+#endif
+ }
+}
+
+
+/* rwx - look at read, write, and execute bits and set character
+flags accordingly
+
+*** WARNING! FILE STRUCTURE DEPENDENT ***
+
+ */
+
+static VOID
+rwx (bits, chars)
+ unsigned short bits;
+ char chars[];
+{
+ chars[0] = (bits & S_IREAD) ? 'r' : '-';
+ chars[1] = (bits & S_IWRITE) ? 'w' : '-';
+ chars[2] = (bits & S_IEXEC) ? 'x' : '-';
+}
+
+
+/* setst - set s & t flags in a file attributes string */
+/* *** WARNING! FILE STRUCTURE DEPENDENT *** */
+static VOID
+setst (bits, chars)
+ unsigned short bits;
+ char chars[];
+{
+#ifdef S_ISUID
+ if (bits & S_ISUID)
+ {
+ if (chars[3] != 'x')
+ /* Screw case: set-uid, but not executable. */
+ chars[3] = 'S';
+ else
+ chars[3] = 's';
+ }
+#endif
+#ifdef S_ISGID
+ if (bits & S_ISGID)
+ {
+ if (chars[6] != 'x')
+ /* Screw case: set-gid, but not executable. */
+ chars[6] = 'S';
+ else
+ chars[6] = 's';
+ }
+#endif
+#ifdef S_ISVTX
+ if (bits & S_ISVTX)
+ chars[9] = 't';
+#endif
+}
diff --git a/src/filetypes.h b/src/filetypes.h
new file mode 100644
index 00000000000..ab924b92768
--- /dev/null
+++ b/src/filetypes.h
@@ -0,0 +1,13 @@
+/* Define the symbols for various file types.
+ These are not included in POSIX. */
+
+#ifndef S_IFMT
+#define S_IFMT 0170000 /* type of file */
+#define S_IFDIR 0040000 /* directory */
+#define S_IFCHR 0020000 /* character special */
+#define S_IFBLK 0060000 /* block special */
+#define S_IFREG 0100000 /* regular */
+#define S_IFIFO 0010000 /* fifo */
+#define S_IFNAM 0050000 /* special named file */
+#endif /* not S_IFMT */
+
diff --git a/src/floatfns.c b/src/floatfns.c
deleted file mode 100644
index 1cf132d5f5c..00000000000
--- a/src/floatfns.c
+++ /dev/null
@@ -1,558 +0,0 @@
-/* Primitive operations on floating point for GNU Emacs Lisp interpreter.
- Copyright (C) 1988 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 1, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-
-#include <signal.h>
-
-#include "config.h"
-#include "lisp.h"
-
-Lisp_Object Qarith_error;
-
-#ifdef LISP_FLOAT_TYPE
-#include <math.h>
-
-/* Nonzero while executing in floating point.
- This tells float_error what to do. */
-
-static int in_float;
-
-/* If an argument is out of range for a mathematical function,
- that is detected with a signal. Here is the actual argument
- value to use in the error message. */
-
-static Lisp_Object float_error_arg;
-
-#define IN_FLOAT(d, num) \
-(in_float = 1, float_error_arg = num, (d), in_float = 0)
-
-/* Extract a Lisp number as a `double', or signal an error. */
-
-double
-extract_float (num)
- Lisp_Object num;
-{
- CHECK_NUMBER_OR_FLOAT (num, 0);
-
- if (XTYPE (num) == Lisp_Float)
- return XFLOAT (num)->data;
- return (double) XINT (num);
-}
-
-DEFUN ("acos", Facos, Sacos, 1, 1, 0,
- "Return the inverse cosine of ARG.")
- (num)
- register Lisp_Object num;
-{
- double d = extract_float (num);
- IN_FLOAT (d = acos (d), num);
- return make_float (d);
-}
-
-DEFUN ("acosh", Facosh, Sacosh, 1, 1, 0,
- "Return the inverse hyperbolic cosine of ARG.")
- (num)
- register Lisp_Object num;
-{
- double d = extract_float (num);
- IN_FLOAT (d = acosh (d), num);
- return make_float (d);
-}
-
-DEFUN ("asin", Fasin, Sasin, 1, 1, 0,
- "Return the inverse sine of ARG.")
- (num)
- register Lisp_Object num;
-{
- double d = extract_float (num);
- IN_FLOAT (d = asin (d), num);
- return make_float (d);
-}
-
-DEFUN ("asinh", Fasinh, Sasinh, 1, 1, 0,
- "Return the inverse hyperbolic sine of ARG.")
- (num)
- register Lisp_Object num;
-{
- double d = extract_float (num);
- IN_FLOAT (d = asinh (d), num);
- return make_float (d);
-}
-
-DEFUN ("atan", Fatan, Satan, 1, 1, 0,
- "Return the inverse tangent of ARG.")
- (num)
- register Lisp_Object num;
-{
- double d = extract_float (num);
- IN_FLOAT (d = atan (d), num);
- return make_float (d);
-}
-
-DEFUN ("atanh", Fatanh, Satanh, 1, 1, 0,
- "Return the inverse hyperbolic tangent of ARG.")
- (num)
- register Lisp_Object num;
-{
- double d = extract_float (num);
- IN_FLOAT (d = atanh (d), num);
- return make_float (d);
-}
-
-DEFUN ("bessel-j0", Fbessel_j0, Sbessel_j0, 1, 1, 0,
- "Return the bessel function j0 of ARG.")
- (num)
- register Lisp_Object num;
-{
- double d = extract_float (num);
- IN_FLOAT (d = j0 (d), num);
- return make_float (d);
-}
-
-DEFUN ("bessel-j1", Fbessel_j1, Sbessel_j1, 1, 1, 0,
- "Return the bessel function j1 of ARG.")
- (num)
- register Lisp_Object num;
-{
- double d = extract_float (num);
- IN_FLOAT (d = j1 (d), num);
- return make_float (d);
-}
-
-DEFUN ("bessel-jn", Fbessel_jn, Sbessel_jn, 2, 2, 0,
- "Return the order N bessel function output jn of ARG.\n\
-The first arg (the order) is truncated to an integer.")
- (num1, num2)
- register Lisp_Object num1, num2;
-{
- int i1 = extract_float (num1);
- double f2 = extract_float (num2);
-
- IN_FLOAT (f2 = jn (i1, f2), num1);
- return make_float (f2);
-}
-
-DEFUN ("bessel-y0", Fbessel_y0, Sbessel_y0, 1, 1, 0,
- "Return the bessel function y0 of ARG.")
- (num)
- register Lisp_Object num;
-{
- double d = extract_float (num);
- IN_FLOAT (d = y0 (d), num);
- return make_float (d);
-}
-
-DEFUN ("bessel-y1", Fbessel_y1, Sbessel_y1, 1, 1, 0,
- "Return the bessel function y1 of ARG.")
- (num)
- register Lisp_Object num;
-{
- double d = extract_float (num);
- IN_FLOAT (d = y1 (d), num);
- return make_float (d);
-}
-
-DEFUN ("bessel-yn", Fbessel_yn, Sbessel_yn, 2, 2, 0,
- "Return the order N bessel function output yn of ARG.\n\
-The first arg (the order) is truncated to an integer.")
- (num1, num2)
- register Lisp_Object num1, num2;
-{
- int i1 = extract_float (num1);
- double f2 = extract_float (num2);
-
- IN_FLOAT (f2 = yn (i1, f2), num1);
- return make_float (f2);
-}
-
-DEFUN ("cube-root", Fcube_root, Scube_root, 1, 1, 0,
- "Return the cube root of ARG.")
- (num)
- register Lisp_Object num;
-{
- double d = extract_float (num);
- IN_FLOAT (d = cbrt (d), num);
- return make_float (d);
-}
-
-DEFUN ("cos", Fcos, Scos, 1, 1, 0,
- "Return the cosine of ARG.")
- (num)
- register Lisp_Object num;
-{
- double d = extract_float (num);
- IN_FLOAT (d = cos (d), num);
- return make_float (d);
-}
-
-DEFUN ("cosh", Fcosh, Scosh, 1, 1, 0,
- "Return the hyperbolic cosine of ARG.")
- (num)
- register Lisp_Object num;
-{
- double d = extract_float (num);
- IN_FLOAT (d = cosh (d), num);
- return make_float (d);
-}
-
-DEFUN ("erf", Ferf, Serf, 1, 1, 0,
- "Return the mathematical error function of ARG.")
- (num)
- register Lisp_Object num;
-{
- double d = extract_float (num);
- IN_FLOAT (d = erf (d), num);
- return make_float (d);
-}
-
-DEFUN ("erfc", Ferfc, Serfc, 1, 1, 0,
- "Return the complementary error function of ARG.")
- (num)
- register Lisp_Object num;
-{
- double d = extract_float (num);
- IN_FLOAT (d = erfc (d), num);
- return make_float (d);
-}
-
-DEFUN ("exp", Fexp, Sexp, 1, 1, 0,
- "Return the exponential base e of ARG.")
- (num)
- register Lisp_Object num;
-{
- double d = extract_float (num);
- IN_FLOAT (d = exp (d), num);
- return make_float (d);
-}
-
-DEFUN ("expm1", Fexpm1, Sexpm1, 1, 1, 0,
- "Return the exp (x)-1 of ARG.")
- (num)
- register Lisp_Object num;
-{
- double d = extract_float (num);
- IN_FLOAT (d = expm1 (d), num);
- return make_float (d);
-}
-
-DEFUN ("log-gamma", Flog_gamma, Slog_gamma, 1, 1, 0,
- "Return the log gamma of ARG.")
- (num)
- register Lisp_Object num;
-{
- double d = extract_float (num);
- IN_FLOAT (d = lgamma (d), num);
- return make_float (d);
-}
-
-DEFUN ("log", Flog, Slog, 1, 1, 0,
- "Return the natural logarithm of ARG.")
- (num)
- register Lisp_Object num;
-{
- double d = extract_float (num);
- IN_FLOAT (d = log (d), num);
- return make_float (d);
-}
-
-DEFUN ("log10", Flog10, Slog10, 1, 1, 0,
- "Return the logarithm base 10 of ARG.")
- (num)
- register Lisp_Object num;
-{
- double d = extract_float (num);
- IN_FLOAT (d = log10 (d), num);
- return make_float (d);
-}
-
-DEFUN ("log1p", Flog1p, Slog1p, 1, 1, 0,
- "Return the log (1+x) of ARG.")
- (num)
- register Lisp_Object num;
-{
- double d = extract_float (num);
- IN_FLOAT (d = log1p (d), num);
- return make_float (d);
-}
-
-DEFUN ("expt", Fexpt, Sexpt, 2, 2, 0,
- "Return the exponential x ** y.")
- (num1, num2)
- register Lisp_Object num1, num2;
-{
- double f1, f2;
-
- CHECK_NUMBER_OR_FLOAT (num1, 0);
- CHECK_NUMBER_OR_FLOAT (num2, 0);
- if ((XTYPE (num1) == Lisp_Int) && /* common lisp spec */
- (XTYPE (num2) == Lisp_Int)) /* don't promote, if both are ints */
- { /* this can be improved by pre-calculating */
- int acc, x, y; /* some binary powers of x then acumulating */
- /* these, therby saving some time. -wsr */
- x = XINT (num1);
- y = XINT (num2);
- acc = 1;
-
- if (y < 0)
- {
- for (; y < 0; y++)
- acc /= x;
- }
- else
- {
- for (; y > 0; y--)
- acc *= x;
- }
- return XSET (x, Lisp_Int, acc);
- }
- f1 = (XTYPE (num1) == Lisp_Float) ? XFLOAT (num1)->data : XINT (num1);
- f2 = (XTYPE (num2) == Lisp_Float) ? XFLOAT (num2)->data : XINT (num2);
- IN_FLOAT (f1 = pow (f1, f2), num1);
- return make_float (f1);
-}
-
-DEFUN ("sin", Fsin, Ssin, 1, 1, 0,
- "Return the sine of ARG.")
- (num)
- register Lisp_Object num;
-{
- double d = extract_float (num);
- IN_FLOAT (d = sin (d), num);
- return make_float (d);
-}
-
-DEFUN ("sinh", Fsinh, Ssinh, 1, 1, 0,
- "Return the hyperbolic sine of ARG.")
- (num)
- register Lisp_Object num;
-{
- double d = extract_float (num);
- IN_FLOAT (d = sinh (d), num);
- return make_float (d);
-}
-
-DEFUN ("sqrt", Fsqrt, Ssqrt, 1, 1, 0,
- "Return the square root of ARG.")
- (num)
- register Lisp_Object num;
-{
- double d = extract_float (num);
- IN_FLOAT (d = sqrt (d), num);
- return make_float (d);
-}
-
-DEFUN ("tan", Ftan, Stan, 1, 1, 0,
- "Return the tangent of ARG.")
- (num)
- register Lisp_Object num;
-{
- double d = extract_float (num);
- IN_FLOAT (d = tan (d), num);
- return make_float (d);
-}
-
-DEFUN ("tanh", Ftanh, Stanh, 1, 1, 0,
- "Return the hyperbolic tangent of ARG.")
- (num)
- register Lisp_Object num;
-{
- double d = extract_float (num);
- IN_FLOAT (d = tanh (d), num);
- return make_float (d);
-}
-
-DEFUN ("abs", Fabs, Sabs, 1, 1, 0,
- "Return the absolute value of ARG.")
- (num)
- register Lisp_Object num;
-{
- CHECK_NUMBER_OR_FLOAT (num, 0);
-
- if (XTYPE (num) == Lisp_Float)
- IN_FLOAT (num = make_float (fabs (XFLOAT (num)->data)), num);
- else if (XINT (num) < 0)
- XSETINT (num, - XFASTINT (num));
-
- return num;
-}
-
-DEFUN ("float", Ffloat, Sfloat, 1, 1, 0,
- "Return the floating point number equal to ARG.")
- (num)
- register Lisp_Object num;
-{
- CHECK_NUMBER_OR_FLOAT (num, 0);
-
- if (XTYPE (num) == Lisp_Int)
- return make_float ((double) XINT (num));
- else /* give 'em the same float back */
- return num;
-}
-
-DEFUN ("logb", Flogb, Slogb, 1, 1, 0,
- "Returns the integer that is the base 2 log of ARG.\n\
-This is the same as the exponent of a float.")
- (num)
-Lisp_Object num;
-{
- Lisp_Object val;
- double f;
-
- CHECK_NUMBER_OR_FLOAT (num, 0);
- f = (XTYPE (num) == Lisp_Float) ? XFLOAT (num)->data : XINT (num);
- IN_FLOAT (val = logb (f), num);
- XSET (val, Lisp_Int, val);
- return val;
-}
-
-/* the rounding functions */
-
-DEFUN ("ceiling", Fceiling, Sceiling, 1, 1, 0,
- "Return the smallest integer no less than ARG. (Round toward +inf.)")
- (num)
- register Lisp_Object num;
-{
- CHECK_NUMBER_OR_FLOAT (num, 0);
-
- if (XTYPE (num) == Lisp_Float)
- IN_FLOAT (XSET (num, Lisp_Int, ceil (XFLOAT (num)->data)), num);
-
- return num;
-}
-
-DEFUN ("floor", Ffloor, Sfloor, 1, 1, 0,
- "Return the largest integer no greater than ARG. (Round towards -inf.)")
- (num)
- register Lisp_Object num;
-{
- CHECK_NUMBER_OR_FLOAT (num, 0);
-
- if (XTYPE (num) == Lisp_Float)
- IN_FLOAT (XSET (num, Lisp_Int, floor (XFLOAT (num)->data)), num);
-
- return num;
-}
-
-DEFUN ("round", Fround, Sround, 1, 1, 0,
- "Return the nearest integer to ARG.")
- (num)
- register Lisp_Object num;
-{
- CHECK_NUMBER_OR_FLOAT (num, 0);
-
- if (XTYPE (num) == Lisp_Float)
- IN_FLOAT (XSET (num, Lisp_Int, rint (XFLOAT (num)->data)), num);
-
- return num;
-}
-
-DEFUN ("truncate", Ftruncate, Struncate, 1, 1, 0,
- "Truncate a floating point number to an int.\n\
-Rounds the value toward zero.")
- (num)
- register Lisp_Object num;
-{
- CHECK_NUMBER_OR_FLOAT (num, 0);
-
- if (XTYPE (num) == Lisp_Float)
- XSET (num, Lisp_Int, (int) XFLOAT (num)->data);
-
- return num;
-}
-
-#ifdef BSD
-static
-float_error (signo)
- int signo;
-{
- if (! in_float)
- fatal_error_signal (signo);
-
-#ifdef BSD4_1
- sigrelse (SIGILL);
-#else /* not BSD4_1 */
- sigsetmask (0);
-#endif /* not BSD4_1 */
-
- in_float = 0;
-
- Fsignal (Qarith_error, Fcons (float_error_arg, Qnil));
-}
-
-/* Another idea was to replace the library function `infnan'
- where SIGILL is signaled. */
-
-#endif /* BSD */
-
-init_floatfns ()
-{
- signal (SIGILL, float_error);
- in_float = 0;
-}
-
-syms_of_floatfns ()
-{
- defsubr (&Sacos);
- defsubr (&Sacosh);
- defsubr (&Sasin);
- defsubr (&Sasinh);
- defsubr (&Satan);
- defsubr (&Satanh);
- defsubr (&Sbessel_y0);
- defsubr (&Sbessel_y1);
- defsubr (&Sbessel_yn);
- defsubr (&Sbessel_j0);
- defsubr (&Sbessel_j1);
- defsubr (&Sbessel_jn);
- defsubr (&Scube_root);
- defsubr (&Scos);
- defsubr (&Scosh);
- defsubr (&Serf);
- defsubr (&Serfc);
- defsubr (&Sexp);
- defsubr (&Sexpm1);
- defsubr (&Slog_gamma);
- defsubr (&Slog);
- defsubr (&Slog10);
- defsubr (&Slog1p);
- defsubr (&Sexpt);
- defsubr (&Ssin);
- defsubr (&Ssinh);
- defsubr (&Ssqrt);
- defsubr (&Stan);
- defsubr (&Stanh);
-
- defsubr (&Sabs);
- defsubr (&Sfloat);
- defsubr (&Slogb);
- defsubr (&Sceiling);
- defsubr (&Sfloor);
- defsubr (&Sround);
- defsubr (&Struncate);
-}
-
-#else /* not LISP_FLOAT_TYPE */
-
-init_floatfns ()
-{}
-
-syms_of_floatfns ()
-{}
-
-#endif /* not LISP_FLOAT_TYPE */
diff --git a/src/fns.c b/src/fns.c
index 649bddd7142..556eb87306a 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -51,6 +51,10 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#endif /* not VMS */
#endif /* LOAD_AVE_TYPE */
+#ifdef DGUX
+#include <sys/dg_sys_info.h> /* for load average info - DJB */
+#endif
+
/* Note on some machines this defines `vector' as a typedef,
so make sure we don't use that name in this file. */
#undef vector
@@ -62,11 +66,9 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "lisp.h"
#include "commands.h"
-#ifdef MULTI_SCREEN
-#include "screen.h"
-#endif
-
+#ifdef lint
#include "buffer.h"
+#endif /* lint */
Lisp_Object Qstring_lessp;
@@ -82,38 +84,25 @@ DEFUN ("random", Frandom, Srandom, 0, 1, 0,
"Return a pseudo-random number.\n\
On most systems all integers representable in Lisp are equally likely.\n\
This is 24 bits' worth.\n\
-With argument N, return random number in interval [0,N).\n\
-With argument t, set the random number seed from the current time and pid.")
+On some systems, absolute value of result never exceeds 2 to the 14.\n\
+If optional argument is supplied as t,\n\
+ the random number seed is set based on the current time and pid.")
(arg)
Lisp_Object arg;
{
- int val;
extern long random ();
extern srandom ();
extern long time ();
if (EQ (arg, Qt))
srandom (getpid () + time (0));
- val = random ();
- if (XTYPE (arg) == Lisp_Int && XINT (arg) != 0)
- {
- /* Try to take our random number from the higher bits of VAL,
- not the lower, since (says Gentzel) the low bits of `random'
- are less random than the higher ones. */
- val &= 0xfffffff; /* Ensure positive. */
- val >>= 5;
- if (XINT (arg) < 10000)
- val >>= 6;
- val %= XINT (arg);
- }
- return make_number (val);
+ return make_number ((int) random ());
}
/* Random data-structure functions */
DEFUN ("length", Flength, Slength, 1, 1, 0,
- "Return the length of vector, list or string SEQUENCE.\n\
-A byte-code function object is also allowed.")
+ "Return the length of vector, list or string SEQUENCE.")
(obj)
register Lisp_Object obj;
{
@@ -121,8 +110,7 @@ A byte-code function object is also allowed.")
register int i;
retry:
- if (XTYPE (obj) == Lisp_Vector || XTYPE (obj) == Lisp_String
- || XTYPE (obj) == Lisp_Compiled)
+ if (XTYPE (obj) == Lisp_Vector || XTYPE (obj) == Lisp_String)
return Farray_length (obj);
else if (CONSP (obj))
{
@@ -149,7 +137,6 @@ A byte-code function object is also allowed.")
DEFUN ("string-equal", Fstring_equal, Sstring_equal, 2, 2, 0,
"T if two strings have identical contents.\n\
-Case is significant.\n\
Symbols are also allowed; their print names are used instead.")
(s1, s2)
register Lisp_Object s1, s2;
@@ -169,7 +156,6 @@ Symbols are also allowed; their print names are used instead.")
DEFUN ("string-lessp", Fstring_lessp, Sstring_lessp, 2, 2, 0,
"T if first arg string is less than second in lexicographic order.\n\
-Case is significant.\n\
Symbols are also allowed; their print names are used instead.")
(s1, s2)
register Lisp_Object s1, s2;
@@ -217,10 +203,9 @@ concat2 (s1, s2)
}
DEFUN ("append", Fappend, Sappend, 0, MANY, 0,
- "Concatenate all the arguments and make the result a list.\n\
+ "Concatenate arguments and make the result a list.\n\
The result is a list whose elements are the elements of all the arguments.\n\
-Each argument may be a list, vector or string.\n\
-The last argument is not copied if it is a list.")
+Each argument may be a list, vector or string.")
(nargs, args)
int nargs;
Lisp_Object *args;
@@ -229,7 +214,7 @@ The last argument is not copied if it is a list.")
}
DEFUN ("concat", Fconcat, Sconcat, 0, MANY, 0,
- "Concatenate all the arguments and make the result a string.\n\
+ "Concatenate arguments and make the result a string.\n\
The result is a string whose elements are the elements of all the arguments.\n\
Each argument may be a string, a list of numbers, or a vector of numbers.")
(nargs, args)
@@ -240,7 +225,7 @@ Each argument may be a string, a list of numbers, or a vector of numbers.")
}
DEFUN ("vconcat", Fvconcat, Svconcat, 0, MANY, 0,
- "Concatenate all the arguments and make the result a vector.\n\
+ "Concatenate arguments and make the result a vector.\n\
The result is a vector whose elements are the elements of all the arguments.\n\
Each argument may be a list, vector or string.")
(nargs, args)
@@ -251,9 +236,7 @@ Each argument may be a list, vector or string.")
}
DEFUN ("copy-sequence", Fcopy_sequence, Scopy_sequence, 1, 1, 0,
- "Return a copy of a list, vector or string.\n\
-The elements of a list or vector are not copied; they are shared\n\
-with the original.")
+ "Return a copy of a list, vector or string.")
(arg)
Lisp_Object arg;
{
@@ -293,8 +276,7 @@ concat (nargs, args, target_type, last_special)
{
this = args[argnum];
if (!(CONSP (this) || NULL (this)
- || XTYPE (this) == Lisp_Vector || XTYPE (this) == Lisp_String
- || XTYPE (this) == Lisp_Compiled))
+ || XTYPE (this) == Lisp_Vector || XTYPE (this) == Lisp_String))
{
if (XTYPE (this) == Lisp_Int)
args[argnum] = Fint_to_string (this);
@@ -391,11 +373,10 @@ concat (nargs, args, target_type, last_special)
DEFUN ("copy-alist", Fcopy_alist, Scopy_alist, 1, 1, 0,
"Return a copy of ALIST.\n\
-This is an alist which represents the same mapping from objects to objects,\n\
-but does not share the alist structure with ALIST.\n\
+This is a new alist which represents the same mapping\n\
+from objects to objects, but does not share the alist structure with ALIST.\n\
The objects mapped (cars and cdrs of elements of the alist)\n\
-are shared, however.\n\
-Elements of ALIST that are not conses are also shared.")
+are shared, however.")
(alist)
Lisp_Object alist;
{
@@ -444,7 +425,7 @@ If FROM or TO is negative, it counts from the end.")
}
DEFUN ("nthcdr", Fnthcdr, Snthcdr, 2, 2, 0,
- "Take cdr N times on LIST, returns the result.")
+ "Takes cdr N times on LIST, returns the result.")
(n, list)
Lisp_Object n;
register Lisp_Object list;
@@ -461,7 +442,7 @@ DEFUN ("nthcdr", Fnthcdr, Snthcdr, 2, 2, 0,
}
DEFUN ("nth", Fnth, Snth, 2, 2, 0,
- "Return the Nth element of LIST.\n\
+ "Returns the Nth element of LIST.\n\
N counts from zero. If LIST is not that long, nil is returned.")
(n, list)
Lisp_Object n, list;
@@ -470,7 +451,7 @@ N counts from zero. If LIST is not that long, nil is returned.")
}
DEFUN ("elt", Felt, Selt, 2, 2, 0,
- "Return element of SEQUENCE at index N.")
+ "Returns element of SEQUENCE at index N.")
(seq, n)
register Lisp_Object seq, n;
{
@@ -487,27 +468,8 @@ DEFUN ("elt", Felt, Selt, 2, 2, 0,
}
}
-DEFUN ("member", Fmember, Smember, 2, 2, 0,
- "Return non-nil if ELT is an element of LIST. Comparison done with EQUAL.\n\
-The value is actually the tail of LIST whose car is ELT.")
- (elt, list)
- register Lisp_Object elt;
- Lisp_Object list;
-{
- register Lisp_Object tail;
- for (tail = list; !NULL (tail); tail = Fcdr (tail))
- {
- register Lisp_Object tem;
- tem = Fcar (tail);
- if (! NULL (Fequal (elt, tem)))
- return tail;
- QUIT;
- }
- return Qnil;
-}
-
DEFUN ("memq", Fmemq, Smemq, 2, 2, 0,
- "Return non-nil if ELT is an element of LIST. Comparison done with EQ.\n\
+ "Returns non-nil if ELT is an element of LIST. Comparison done with EQ.\n\
The value is actually the tail of LIST whose car is ELT.")
(elt, list)
register Lisp_Object elt;
@@ -525,9 +487,8 @@ The value is actually the tail of LIST whose car is ELT.")
}
DEFUN ("assq", Fassq, Sassq, 2, 2, 0,
- "Return non-nil if ELT is `eq' to the car of an element of LIST.\n\
-The value is actually the element of LIST whose car is ELT.\n\
-Elements of LIST that are not conses are ignored.")
+ "Returns non-nil if ELT is the car of an element of LIST. Comparison done with eq.\n\
+The value is actually the element of LIST whose car is ELT.")
(key, list)
register Lisp_Object key;
Lisp_Object list;
@@ -566,7 +527,7 @@ assq_no_quit (key, list)
}
DEFUN ("assoc", Fassoc, Sassoc, 2, 2, 0,
- "Return non-nil if ELT is `equal' to the car of an element of LIST.\n\
+ "Returns non-nil if ELT is the car of an element of LIST. Comparison done with equal.\n\
The value is actually the element of LIST whose car is ELT.")
(key, list)
register Lisp_Object key;
@@ -586,7 +547,7 @@ The value is actually the element of LIST whose car is ELT.")
}
DEFUN ("rassq", Frassq, Srassq, 2, 2, 0,
- "Return non-nil if ELT is `eq' to the cdr of an element of LIST.\n\
+ "Returns non-nil if ELT is the cdr of an element of LIST. Comparison done with EQ.\n\
The value is actually the element of LIST whose cdr is ELT.")
(key, list)
register Lisp_Object key;
@@ -606,11 +567,10 @@ The value is actually the element of LIST whose cdr is ELT.")
}
DEFUN ("delq", Fdelq, Sdelq, 2, 2, 0,
- "Delete by side effect any occurrences of ELT as a member of LIST.\n\
-The modified LIST is returned. Comparison is done with `eq'.\n\
+ "Deletes by side effect any occurrences of ELT as a member of LIST.\n\
+The modified LIST is returned.\n\
If the first member of LIST is ELT, there is no way to remove it by side effect;\n\
-therefore, write `(setq foo (delq element foo))'\n\
-to be sure of changing the value of `foo'.")
+therefore, write (setq foo (delq element foo)) to be sure of changing foo.")
(elt, list)
register Lisp_Object elt;
Lisp_Object list;
@@ -639,8 +599,7 @@ to be sure of changing the value of `foo'.")
}
DEFUN ("nreverse", Fnreverse, Snreverse, 1, 1, 0,
- "Reverse LIST by modifying cdr pointers.\n\
-Returns the beginning of the reversed list.")
+ "Reverses LIST by modifying cdr pointers. Returns the beginning of the reversed list.")
(list)
Lisp_Object list;
{
@@ -661,8 +620,8 @@ Returns the beginning of the reversed list.")
}
DEFUN ("reverse", Freverse, Sreverse, 1, 1, 0,
- "Reverse LIST, copying. Returns the beginning of the reversed list.\n\
-See also the function `nreverse', which is used more often.")
+ "Reverses LIST, copying. Returns the beginning of the reversed list.\n\
+See also the function nreverse, which is used more often.")
(list)
Lisp_Object list;
{
@@ -774,7 +733,7 @@ merge (org_l1, org_l2, pred)
DEFUN ("get", Fget, Sget, 2, 2, 0,
"Return the value of SYMBOL's PROPNAME property.\n\
-This is the last VALUE stored with `(put SYMBOL PROPNAME VALUE)'.")
+This is the last VALUE stored with (put SYMBOL PROPNAME VALUE).")
(sym, prop)
Lisp_Object sym;
register Lisp_Object prop;
@@ -792,7 +751,7 @@ This is the last VALUE stored with `(put SYMBOL PROPNAME VALUE)'.")
DEFUN ("put", Fput, Sput, 3, 3, 0,
"Store SYMBOL's PROPNAME property with value VALUE.\n\
-It can be retrieved with `(get SYMBOL PROPNAME)'.")
+It can be retrieved with (get SYMBOL PROPNAME).")
(sym, prop, val)
Lisp_Object sym;
register Lisp_Object prop;
@@ -1025,6 +984,7 @@ Thus, \" \" as SEP results in spaces between the values return by FN.")
int nargs;
register Lisp_Object *args;
register int i;
+ int j;
struct gcpro gcpro1;
len = Flength (seq);
@@ -1038,9 +998,10 @@ Thus, \" \" as SEP results in spaces between the values return by FN.")
mapcar1 (leni, args, fn, seq);
UNGCPRO;
- for (i = leni - 1; i >= 0; i--)
- args[i + i] = args[i];
-
+ /* Broken Xenix/386 compiler can't use a register variable here */
+ for (j = leni - 1; j > 0; j--)
+ args[j + j] = args[j];
+
for (i = 1; i < nargs; i += 2)
args[i] = sep;
@@ -1048,9 +1009,8 @@ Thus, \" \" as SEP results in spaces between the values return by FN.")
}
DEFUN ("mapcar", Fmapcar, Smapcar, 2, 2, 0,
- "Apply FUNCTION to each element of SEQUENCE, and make a list of the results.\n\
-The result is a list just as long as SEQUENCE.\n\
-SEQUENCE may be a list, a vector or a string.")
+ "Apply FUNCTION to each element of LIST, and make a list of the results.\n\
+The result is a list just as long as LIST.")
(fn, seq)
Lisp_Object fn, seq;
{
@@ -1071,12 +1031,13 @@ SEQUENCE may be a list, a vector or a string.")
DEFUN ("y-or-n-p", Fy_or_n_p, Sy_or_n_p, 1, 1, 0,
"Ask user a \"y or n\" question. Return t if answer is \"y\".\n\
+Takes one argument, which is the string to display to ask the question.\n\
+It should end in a space; `y-or-n-p' adds `(y or n) ' to it.\n\
No confirmation of the answer is requested; a single character is enough.\n\
Also accepts Space to mean yes, or Delete to mean no.")
(prompt)
Lisp_Object prompt;
{
- register Lisp_Object obj;
register int ans;
Lisp_Object xprompt;
Lisp_Object args[2];
@@ -1091,19 +1052,10 @@ Also accepts Space to mean yes, or Delete to mean no.")
{
message ("%s(y or n) ", XSTRING (xprompt)->data);
cursor_in_echo_area = 1;
-
- obj = read_char (0);
- if (XTYPE (obj) == Lisp_Int)
- ans = XINT (obj);
- else
- continue;
-
+ ans = read_command_char (0);
cursor_in_echo_area = -1;
message ("%s(y or n) %c", XSTRING (xprompt)->data, ans);
cursor_in_echo_area = ocech;
- /* Accept a C-g or C-] (abort-recursive-edit) as quit requests. */
- if (ans == 7 || ans == '\035')
- Vquit_flag = Qt;
QUIT;
if (ans >= 0)
ans = DOWNCASE (ans);
@@ -1124,25 +1076,15 @@ Also accepts Space to mean yes, or Delete to mean no.")
UNGCPRO;
return (ans == 'y' ? Qt : Qnil);
}
-
-/* This is how C code calls `yes-or-no-p' and allows the user
- to redefined it.
-
- Anything that calls this function must protect from GC! */
-
-Lisp_Object
-do_yes_or_no_p (prompt)
- Lisp_Object prompt;
-{
- return call1 (intern ("yes-or-no-p"), prompt);
-}
/* Anything that calls this function must protect from GC! */
DEFUN ("yes-or-no-p", Fyes_or_no_p, Syes_or_no_p, 1, 1, 0,
- "Ask user a yes or no question. Return t if answer is yes.\n\
-The user must confirm the answer with a newline,\n\
-and can rub it out if not confirmed.")
+ "Ask user a yes-or-no question. Return t if answer is yes.\n\
+Takes one argument, which is the string to display to ask the question.\n\
+It should end in a space; `yes-or-no-p' adds `(yes or no) ' to it.\n\
+The user must confirm the answer with RET,\n\
+and can edit it until it as been confirmed.")
(prompt)
Lisp_Object prompt;
{
@@ -1160,7 +1102,7 @@ and can rub it out if not confirmed.")
while (1)
{
ans = Fdowncase (read_minibuf (Vminibuffer_local_map,
- Qnil, prompt, Qnil, 0));
+ Qnil, prompt, 0));
if (XSTRING (ans)->size == 3 && !strcmp (XSTRING (ans)->data, "yes"))
{
UNGCPRO;
@@ -1177,10 +1119,14 @@ and can rub it out if not confirmed.")
message ("Please answer yes or no.");
Fsleep_for (make_number (2));
}
- UNGCPRO;
}
/* Avoid static vars inside a function since in HPUX they dump as pure. */
+#ifdef DGUX
+static struct dg_sys_info_load_info load_info; /* what-a-mouthful! */
+
+#else /* Not DGUX */
+
static int ldav_initialized;
static int ldav_channel;
#ifdef LOAD_AVE_TYPE
@@ -1192,13 +1138,27 @@ static struct nlist ldav_nl[2];
#define channel ldav_channel
#define initialized ldav_initialized
#define nl ldav_nl
+#endif /* Not DGUX */
DEFUN ("load-average", Fload_average, Sload_average, 0, 0, 0,
- "Return list of 1 minute, 5 minute and 15 minute load averages.\n\
-Each of the three load averages is multiplied by 100,\n\
-then converted to integer.")
+ "Return the current 1 minute, 5 minute and 15 minute load averages\n\
+in a list (all floating point load average values are multiplied by 100\n\
+and then turned into integers).")
()
{
+#ifdef DGUX
+ /* perhaps there should be a "sys_load_avg" call in sysdep.c?! - DJB */
+ load_info.one_minute = 0.0; /* just in case there is an error */
+ load_info.five_minute = 0.0;
+ load_info.fifteen_minute = 0.0;
+ dg_sys_info (&load_info, DG_SYS_INFO_LOAD_INFO_TYPE,
+ DG_SYS_INFO_LOAD_VERSION_0);
+
+ return Fcons (make_number ((int)(load_info.one_minute * 100.0)),
+ Fcons (make_number ((int)(load_info.five_minute * 100.0)),
+ Fcons (make_number ((int)(load_info.fifteen_minute * 100.0)),
+ Qnil)));
+#else /* not DGUX */
#ifndef LOAD_AVE_TYPE
error ("load-average not implemented for this operating system");
@@ -1268,19 +1228,29 @@ then converted to integer.")
strcpy (nl[0].n_name, LDAV_SYMBOL);
nl[1].n_zeroes = 0;
#else /* NLIST_STRUCT */
-#ifdef convex
+#if defined (convex) || defined (NeXT)
nl[0].n_un.n_name = LDAV_SYMBOL;
nl[1].n_un.n_name = 0;
-#else /* not convex */
+#else /* not convex or NeXT */
nl[0].n_name = LDAV_SYMBOL;
nl[1].n_name = 0;
-#endif /* not convex */
+#endif /* not convex of NeXT */
#endif /* NLIST_STRUCT */
+#ifdef IRIS_4D
+ {
+#include <sys/types.h>
+#include <sys/sysmp.h>
+ nl[0].n_value = sysmp(MP_KERNADDR, MPKA_AVENRUN);
+ nl[0].n_value &= 0x7fffffff;
+ }
+#else
nlist (KERNEL_FILE, nl);
+#endif /* IRIS */
#ifdef FIXUP_KERNEL_SYMBOL_ADDR
- FIXUP_KERNEL_SYMBOL_ADDR (nl);
+ if ((nl[0].n_type & N_TYPE) != N_ABS)
+ nl[0].n_value = (nlp->n_value >> 2) | 0xc0000000;
#endif /* FIXUP_KERNEL_SYMBOL_ADDR */
}
/*
@@ -1320,6 +1290,7 @@ then converted to integer.")
Fcons (make_number (LOAD_AVE_CVT (load_ave[2])),
Qnil)));
#endif /* LOAD_AVE_TYPE */
+#endif /* not DGUX */
}
#undef channel
@@ -1332,8 +1303,8 @@ DEFUN ("featurep", Ffeaturep, Sfeaturep, 1, 1, 0,
"Returns t if FEATURE is present in this Emacs.\n\
Use this to conditionalize execution of lisp code based on the presence or\n\
absence of emacs or environment extensions.\n\
-Use `provide' to declare that a feature is available.\n\
-This function looks at the value of the variable `features'.")
+Use provide to declare that a feature is available.\n\
+This function looks at the value of the variable features.")
(feature)
Lisp_Object feature;
{
@@ -1359,10 +1330,8 @@ DEFUN ("provide", Fprovide, Sprovide, 1, 1, 0,
}
DEFUN ("require", Frequire, Srequire, 1, 2, 0,
- "If feature FEATURE is not loaded, load it from FILENAME.\n\
-If FEATURE is not a member of the list `features', then the feature\n\
-is not loaded; so load the file FILENAME.\n\
-If FILENAME is omitted, the printname of FEATURE is used as the file name.")
+ "If FEATURE is not present in Emacs (ie (featurep FEATURE) is false),\n\
+load FILENAME. FILENAME is optional and defaults to FEATURE.")
(feature, file_name)
Lisp_Object feature, file_name;
{
@@ -1387,7 +1356,7 @@ If FILENAME is omitted, the printname of FEATURE is used as the file name.")
/* Once loading finishes, don't undo it. */
Vautoload_queue = Qt;
- feature = unbind_to (count, feature);
+ unbind_to (count);
}
return feature;
}
@@ -1399,7 +1368,7 @@ syms_of_fns ()
DEFVAR_LISP ("features", &Vfeatures,
"A list of symbols which are the features of the executing emacs.\n\
-Used by `featurep' and `require', and altered by `provide'.");
+Used by featurep and require, and altered by provide.");
Vfeatures = Qnil;
defsubr (&Sidentity);
@@ -1416,7 +1385,6 @@ Used by `featurep' and `require', and altered by `provide'.");
defsubr (&Snthcdr);
defsubr (&Snth);
defsubr (&Selt);
- defsubr (&Smember);
defsubr (&Smemq);
defsubr (&Sassq);
defsubr (&Sassoc);
diff --git a/src/getpagesize.h b/src/getpagesize.h
new file mode 100644
index 00000000000..9a3db63213b
--- /dev/null
+++ b/src/getpagesize.h
@@ -0,0 +1,34 @@
+#ifdef BSD
+#ifndef BSD4_1
+#define HAVE_GETPAGESIZE
+#endif
+#endif
+
+#ifndef HAVE_GETPAGESIZE
+
+#ifdef VMS
+#include "param.h"
+#else
+#include <sys/param.h>
+#endif
+
+#ifdef POSIX
+#include <unistd.h>
+#define getpagesize() sysconf (_SC_PAGESIZE)
+#else /* not POSIX */
+#ifdef EXEC_PAGESIZE
+#define getpagesize() EXEC_PAGESIZE
+#else /* no EXEC_PAGESIZE */
+#ifdef NBPG
+#define getpagesize() NBPG * CLSIZE
+#ifndef CLSIZE
+#define CLSIZE 1
+#endif /* no CLSIZE */
+#else /* no NBPG */
+#define getpagesize() NBPC
+#endif /* no NBPG */
+#endif /* no EXEC_PAGESIZE */
+#endif /* not POSIX */
+
+#endif /* not HAVE_GETPAGESIZE */
+
diff --git a/src/gettime.h b/src/gettime.h
new file mode 100644
index 00000000000..7478fb51754
--- /dev/null
+++ b/src/gettime.h
@@ -0,0 +1,36 @@
+/* Include the appropriate header files for things related to time.
+ The caller should include sys/socket.h before this file,
+ if the system has sockets. */
+
+#ifdef IRIS
+#include <sys/sysmacros.h> /* for "minor" */
+#include <sys/time.h>
+#else
+#ifdef UNIPLUS
+#include <sys/time.h>
+
+#else /* not IRIS, not UNIPLUS */
+#ifdef HAVE_TIMEVAL
+/* _h_BSDTYPES is checked because on ISC unix, socket.h includes
+ both time.h and sys/time.h, and the latter file is protected
+ from repeated inclusion. */
+#if defined(USG) && !defined(AIX) && !defined(_h_BSDTYPES) && !defined(USG_SYS_TIME) && !defined(uts)
+#include <time.h>
+#else /* AIX or USG_SYS_TIME, or not USG */
+#include <sys/time.h>
+#endif /* AIX or USG_SYS_TIME, or not USG */
+#endif /* HAVE_TIMEVAL */
+#endif /* not UNIPLUS */
+#endif /* not IRIS */
+
+#ifdef BAT68K
+#include <sys/time.h> /* In addition to time.h. */
+#endif
+
+#ifdef AIX
+#include <sys/time.h> /* In addition to time.h. */
+#endif
+
+#ifdef DPX2
+#include <sys/time.h>
+#endif
diff --git a/src/hftctl.c b/src/hftctl.c
index 3e3788aa709..ff2bec4d1dd 100644
--- a/src/hftctl.c
+++ b/src/hftctl.c
@@ -9,8 +9,8 @@
/* #include <sys/hft.h> */
/* */
/* int hftctl(fildes, request, arg ) */
-/* int fildes, request ; */
-/* char *arg ; */
+/* int fildes, request; */
+/* char *arg; */
/* */
/* Description: */
/* */
@@ -49,222 +49,242 @@
#include <sys/ioctl.h>
#include <sys/signal.h>
#include <sys/devinfo.h>
+#include <termios.h>
#include <termio.h>
#include <sys/hft.h>
-#include <termios.h>
+#include <sys/uio.h>
#include <sys/tty.h>
/* #include <sys/pty.h> */
#define REMOTE 0x01
#undef ioctl
-static char SCCSid[] = "com/gnuemacs/src,3.1,9021-90/05/03-5/3/90" ;
+static char SCCSid[] = "com/gnuemacs/src,3.1,9021-90/05/03-5/3/90";
/*************** LOCAL DEFINES **********************************/
-typedef int (*FUNC)() ; /* pointer to a function */
+typedef int (*FUNC)(); /* pointer to a function */
#define QDEV ((HFQPDEVCH<<8)|HFQPDEVCL)
#define QLOC ((HFQLOCCH<<8)|HFQLOCCL)
#define QPS ((HFQPRESCH<<8)|HFQPRESCL)
+#ifndef TCGETS
+#define TCGETS TCGETA
+#endif
+#ifndef TCSETS
+#define TCSETS TCSETA
+#endif
+
/*************** EXTERNAL / GLOBAL DATA AREA ********************/
- int hfqry() ;
- int hfskbd() ;
- char *malloc() ;
+static int hfqry();
+static int hfskbd();
+ char *malloc();
-extern int errno ;
-static jmp_buf hftenv ;
-static int is_ack_vtd ;
-static FUNC sav_alrm ;
+extern int errno;
+static jmp_buf hftenv;
+static int is_ack_vtd;
+static FUNC sav_alrm;
static struct hfctlreq req =
{ 0x1b,'[','x',0,0,0,21,HFCTLREQCH,HFCTLREQCL};
static struct hfctlack ACK =
{ 0x1b,'[','x',0,0,0,21,HFCTLACKCH,HFCTLACKCL};
- /* FUNC signal() ; */
+ /* FUNC signal(); */
/*************** LOCAL MACROS ***********************************/
#define HFTYPE(p) ((p->hf_typehi<<8)|(p->hf_typelo))
-#define BYTE4(p) ( (p)[0]<<24 | (p)[1]<<16 | (p)[2]<<8 | (p)[3] )
+#define BYTE4(p) ((p)[0]<<24 | (p)[1]<<16 | (p)[2]<<8 | (p)[3])
/* read a buffer */
#define RD_BUF(f,p,l) \
- while ( (l) ) \
- if ( ( j = read((f),(p),(l)) ) < 0 ) \
- if ( errno != EINTR ) return (-1) ; \
- else continue ; \
- else { (l)-=j ; (p)+=j ; }
+ while ((l)) \
+ if ((j = read((f),(p),(l))) < 0) \
+ if (errno != EINTR) return (-1); \
+ else continue; \
+ else { (l) -= j; (p) += j; }
+
+/*************** function prototypes ***************************/
+#ifdef __STDC__
+static GT_ACK (int fd, int req, char *buf);
+static WR_REQ (int fd, int request, int cmdlen, char *cmd, int resplen);
+static hft_alrm(int sig);
+#else
+static GT_ACK ();
+static WR_REQ ();
+static hft_alrm ();
+#endif
/*************** HFTCTL FUNCTION *******************************/
-hftctl( fd, request, arg )
- int fd ;
- int request ;
- union {
- struct hfintro *intro ;
- struct hfquery *query ;
- char *c ;
- } arg ;
+hftctl (fd, request, arg)
+ int fd;
+ int request;
+ union {
+ struct hfintro *intro;
+ struct hfquery *query;
+ char *c;
+ } arg;
{
- int i ;
- int fd_flag ; /* fcntl flags */
-register union {
- struct hfintro *cmd ; /* p.cmd - intro des. */
- struct hfqphdevc *ph ; /* p.ph - physical dev.*/
- char *c ; /* p.c - char ptr */
- } p ; /* general pointer */
- int pty_new ; /* pty modes */
- int pty_old ;
- int retcode ;
- struct termios term_new ; /* terminal attributes */
- struct termios term_old ;
- struct devinfo devInfo ; /* defined in sys/devinfo.h */
-
-
-if ( ioctl( fd, IOCINFO, &devInfo ) == -1 ) return(-1) ;
-
-if ( devInfo.devtype != DD_PSEU ) /* is it a pty? */
- return (ioctl(fd, request, arg) ) ; /* no, do IOCTL */
-
- /******* START PTY **************/
- /** Pty found, possible HFT */
- /** set new file des as raw */
- /** as you can. */
- /********************************/
-
- /* Get current state of file */
- /* descriptor & save */
-if ( ( fd_flag = fcntl( fd, F_GETFL, 0 ) ) == -1 ) return (-1) ;
-if ( ioctl( fd, TCGETS, &term_old ) == -1 ) return (-1) ;
- /* set terminal attr to raw */
- /* and to delay on read */
-pty_new = pty_old | REMOTE ;
-memcpy( &term_new, &term_old, sizeof( term_new ) ) ;
-term_new.c_iflag = 0 ;
-term_new.c_oflag = 0 ;
-term_new.c_lflag = 0 ;
-/* term_new.c_line = 0 ; */
-for ( i = 1 ; i <= 5 ; i++ )
-term_new.c_cc[i] = 0 ;
-term_new.c_cc[0] = -1 ;
-ioctl( fd, TCSETS, &term_new ) ;
-if ( fcntl( fd, F_SETFL, fd_flag & ~O_NDELAY ) == -1 )
- return(-1) ;
- /* call spacific function */
-if ( request == HFSKBD )
- retcode = hfskbd( fd, request, arg.c) ;
-else /* assume HFQUERY */
- retcode = hfqry( fd, request, arg.c) ;
-
-fcntl( fd, F_SETFL, fd_flag ) ; /* reset terminal to original */
-ioctl( fd, TCSETS, &term_old ) ;
-
-
-return( retcode ) ; /* return error */
+ int i;
+ int fd_flag; /* fcntl flags */
+ register union {
+ struct hfintro *cmd; /* p.cmd - intro des. */
+ struct hfqphdevc *ph; /* p.ph - physical dev.*/
+ char *c; /* p.c - char ptr */
+ } p; /* general pointer */
+ int pty_new; /* pty modes */
+ int pty_old;
+ int retcode;
+ struct termios term_new; /* terminal attributes */
+ struct termios term_old;
+ struct devinfo devInfo; /* defined in sys/devinfo.h */
+
+
+ if (ioctl (fd, IOCINFO, &devInfo) == -1) return(-1);
+
+ if (devInfo.devtype != DD_PSEU) /* is it a pty? */
+ return (ioctl(fd, request, arg)); /* no, do IOCTL */
+
+ /******* START PTY **************/
+ /** Pty found, possible HFT */
+ /** set new file des as raw */
+ /** as you can. */
+ /********************************/
+
+ /* Get current state of file */
+ /* descriptor & save */
+ if ((fd_flag = fcntl (fd, F_GETFL, 0)) == -1) return (-1);
+ if (ioctl (fd, TCGETS, &term_old) == -1) return (-1);
+ /* set terminal attr to raw */
+ /* and to delay on read */
+ pty_new = pty_old | REMOTE;
+ memcpy (&term_new, &term_old, sizeof (term_new));
+ term_new.c_iflag = 0;
+ term_new.c_oflag = 0;
+ term_new.c_lflag = 0;
+ /* term_new.c_line = 0; */
+ for (i = 1; i <= 5; i++)
+ term_new.c_cc[i] = 0;
+ term_new.c_cc[0] = -1;
+ ioctl (fd, TCSETS, &term_new);
+ if (fcntl (fd, F_SETFL, fd_flag & ~O_NDELAY) == -1)
+ return(-1);
+ /* call spacific function */
+ if (request == HFSKBD)
+ retcode = hfskbd (fd, request, arg.c);
+ else /* assume HFQUERY */
+ retcode = hfqry (fd, request, arg.c);
+
+ fcntl (fd, F_SETFL, fd_flag); /* reset terminal to original */
+ ioctl (fd, TCSETS, &term_old);
+
+
+ return (retcode); /* return error */
}
/*************** HFSKBD FUNCTION ******************************/
-static hfskbd(fd, request, arg )
- int fd ;
- int request ;
- struct hfbuf *arg ;
+static int
+hfskbd (fd, request, arg)
+ int fd;
+ int request;
+ struct hfbuf *arg;
{
-WR_REQ(fd, request, arg->hf_buflen, arg->hf_bufp,0) ;
-return( GT_ACK(fd, request, arg->hf_bufp) ) ;
+ WR_REQ(fd, request, arg->hf_buflen, arg->hf_bufp,0);
+ return (GT_ACK(fd, request, arg->hf_bufp));
}
/*************** HFQUERY FUNCTION ******************************/
-static hfqry(fd, request, arg )
- int fd ;
- int request ;
- struct hfquery *arg ;
+static int
+hfqry (fd, request, arg)
+ int fd;
+ int request;
+ struct hfquery *arg;
{
-WR_REQ(fd, request, arg->hf_cmdlen, arg->hf_cmd, arg->hf_resplen ) ;
-return( GT_ACK(fd, request, arg->hf_resp ) ) ;
+ WR_REQ(fd, request, arg->hf_cmdlen, arg->hf_cmd, arg->hf_resplen);
+ return (GT_ACK(fd, request, arg->hf_resp));
}
/*************** GT_ACK FUNCTION ******************************/
-static GT_ACK(fd, req, buf )
- int fd ;
- int req ;
- char *buf ;
+static int
+GT_ACK (fd, req, buf)
+ int fd;
+ int req;
+ char *buf;
{
-
- struct hfctlack ack ;
- int i = sizeof( ack ) ;
- int j = 0 ;
- union {
- char *c ;
- struct hfctlack *ack ;
- } p ;
-
- int hft_alrm() ;
-
-is_ack_vtd = 0 ; /* flag no ACT VTD yet */
-
-if ( setjmp( hftenv ) ) /* set environment in case */
- { /* of time out */
- errno=ENODEV ; /* if time out, set errno */
- return( -1 ) ; /* flag error */
- }
-
-alarm(3) ; /* time out in 3 secs */
-sav_alrm = signal( SIGALRM, hft_alrm ) ;/* prepare to catch time out */
-
-p.ack = &ack ;
-while ( ! is_ack_vtd ) /* do until valid ACK VTD */
- {
- RD_BUF(fd, p.c, i ) ; /* read until a ACK VTD is fill*/
-
- if ( ! memcmp( &ack, &ACK, sizeof( HFINTROSZ ) ) /* the ACK intro & */
- && ( ack.hf_request == req ) ) /* is it the response we want ?*/
- { /* yes, ACK VTD found */
- is_ack_vtd = 1 ; /* quickly, flag it */
- break ; /* get the %$%#@ out of here */
- }
-
- p.ack = &ack ; /* no, then skip 1st */
- ++p.c ; /* char and start over */
- i = sizeof( ack ) - 1 ; /* one less ESC to cry over */
-
- while( ( *p.c != 0x1b ) && i ) /* scan for next ESC */
- { ++p.c ; --i ; } /* if any */
-
- ( i ? memcpy( &ack, p.c, i ) : 0 ) ; /* if any left over, then move */
- p.ack = &ack ; /* ESC to front of ack struct */
- p.c += i ; /* skip over whats been read */
- i = sizeof( ack ) - i ; /* set whats left to be read */
- } /***** TRY AGAIN */
-
-alarm(0) ; /* ACK VTD received, reset alrm*/
-signal( SIGALRM, sav_alrm ) ; /* reset signal */
-
-if ( i = ack.hf_arg_len ) /* any data following ? */
- { /* yes, */
- RD_BUF(fd,buf,i) ; /* read until it is received */
- }
-
-if ( errno = ack.hf_retcode ) /* set errno based on returned */
- return (-1) ; /* code, if 0, then no error */
-else
- return (0) ; /* if set, then error returned */
+ struct hfctlack ack;
+ int i = sizeof (ack);
+ int j = 0;
+ union {
+ char *c;
+ struct hfctlack *ack;
+ } p;
+
+ is_ack_vtd = 0; /* flag no ACT VTD yet */
+
+ if (setjmp (hftenv)) /* set environment in case */
+ { /* of time out */
+ errno = ENODEV; /* if time out, set errno */
+ return (-1); /* flag error */
+ }
+
+ alarm(3); /* time out in 3 secs */
+ sav_alrm = (FUNC) signal (SIGALRM, (void(*)())hft_alrm); /* prepare to catch time out */
+
+ p.ack = &ack;
+ while (! is_ack_vtd) /* do until valid ACK VTD */
+ {
+ RD_BUF(fd, p.c, i); /* read until a ACK VTD is fill*/
+
+ if (! memcmp (&ack, &ACK, sizeof (HFINTROSZ)) /* the ACK intro & */
+ && (ack.hf_request == req)) /* is it the response we want ?*/
+ { /* yes, ACK VTD found */
+ is_ack_vtd = 1; /* quickly, flag it */
+ break; /* get the %$%#@ out of here */
+ }
+
+ p.ack = &ack; /* no, then skip 1st */
+ ++p.c; /* char and start over */
+ i = sizeof (ack) - 1; /* one less ESC to cry over */
+
+ while ((*p.c != 0x1b) && i) /* scan for next ESC */
+ { ++p.c; --i; } /* if any */
+
+ (i ? memcpy (&ack, p.c, i) : 0); /* if any left over, then move */
+ p.ack = &ack; /* ESC to front of ack struct */
+ p.c += i; /* skip over whats been read */
+ i = sizeof (ack) - i; /* set whats left to be read */
+ } /***** TRY AGAIN */
+
+ alarm(0); /* ACK VTD received, reset alrm*/
+ signal (SIGALRM, (void(*)())sav_alrm); /* reset signal */
+
+ if (i = ack.hf_arg_len) /* any data following ? */
+ { /* yes, */
+ RD_BUF(fd,buf,i); /* read until it is received */
+ }
+
+ if (errno = ack.hf_retcode) /* set errno based on returned */
+ return (-1); /* code, if 0, then no error */
+ else
+ return (0); /* if set, then error returned */
}
/*************** HFT_ALRM FUNCTION ******************************/
-static hft_alrm(sig) /* Function hft_alrm - handle */
- int sig ; /* alarm signal */
+static int
+hft_alrm (sig) /* Function hft_alrm - handle */
+ int sig; /* alarm signal */
{
-signal( SIGALRM, sav_alrm ) ; /* reset to previous */
+ signal (SIGALRM, (void(*)())sav_alrm); /* reset to previous */
-if ( is_ack_vtd ) /* has ack vtd arrived ? */
- return(0) ; /* yes, then continue */
-else /* no, then return with error */
- longjmp( hftenv, -1 ) ;
+ if (is_ack_vtd) /* has ack vtd arrived ? */
+ return(0); /* yes, then continue */
+ else /* no, then return with error */
+ longjmp (hftenv, -1);
}
@@ -278,42 +298,43 @@ else /* no, then return with error */
/*** ***/
/*********************************************************************/
-static WR_REQ(fd, request, cmdlen, cmd, resplen )
- int fd ;
- int request ;
- int cmdlen ;
- char *cmd ;
- int resplen ;
+static int
+WR_REQ (fd, request, cmdlen, cmd, resplen)
+ int fd;
+ int request;
+ int cmdlen;
+ char *cmd;
+ int resplen;
{
- struct {
- char *c ;
- struct hfctlreq *req ;
- } p ;
- int size ;
-
- req.hf_request = request ;
- req.hf_arg_len = cmdlen ;
- req.hf_rsp_len = resplen ;
-
-if ( cmdlen ) /* if arg structure to pass */
- {
- size = sizeof( struct hfctlreq ) + cmdlen ;
- if ( ( p.c = malloc(size) ) == NULL ) /* malloc one area */
- return( -1 ) ;
-
- memcpy( p.c, &req, sizeof( req ) ) ; /* copy CTL REQ struct */
- memcpy( p.c + sizeof( req ), cmd, cmdlen ) ; /* copy arg struct */
- }
-else
- {
- p.req = &req ; /* otherwise use only CTL REQ */
- size = sizeof( req ) ;
- }
-
- /* write request to terminal */
-if ( write(fd,p.c,size) == -1 ) return (-1) ;
-if ( p.req != &req ) /* free if allocated */
- free( p.c ) ;
-return (0) ;
+ struct {
+ char *c;
+ struct hfctlreq *req;
+ } p;
+ int size;
+
+ req.hf_request = request;
+ req.hf_arg_len = cmdlen;
+ req.hf_rsp_len = resplen;
+
+ if (cmdlen) /* if arg structure to pass */
+ {
+ size = sizeof (struct hfctlreq) + cmdlen;
+ if ((p.c = malloc(size)) == NULL) /* malloc one area */
+ return (-1);
+
+ memcpy (p.c, &req, sizeof (req)); /* copy CTL REQ struct */
+ memcpy (p.c + sizeof (req), cmd, cmdlen); /* copy arg struct */
+ }
+ else
+ {
+ p.req = &req; /* otherwise use only CTL REQ */
+ size = sizeof (req);
+ }
+
+ /* write request to terminal */
+ if (write(fd,p.c,size) == -1) return (-1);
+ if (p.req != &req) /* free if allocated */
+ free (p.c);
+ return (0);
}
diff --git a/src/indent.c b/src/indent.c
index 9561927167d..641805c2eaa 100644
--- a/src/indent.c
+++ b/src/indent.c
@@ -1,5 +1,5 @@
/* Indentation functions.
- Copyright (C) 1985, 1986, 1987, 1988 Free Software Foundation, Inc.
+ Copyright (C) 1985, 1986, 1987, 1988, 1990 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -22,11 +22,11 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "lisp.h"
#include "buffer.h"
#include "indent.h"
-#include "screen.h"
#include "window.h"
#include "termchar.h"
#include "termopts.h"
-#include "disptab.h"
+
+#define CR '\015'
/* Indentation can insert tabs if this is non-zero;
otherwise always uses spaces */
@@ -35,8 +35,6 @@ int indent_tabs_mode;
#define min(a, b) ((a) < (b) ? (a) : (b))
#define max(a, b) ((a) > (b) ? (a) : (b))
-#define CR 015
-
/* These three values memoize the current column to avoid recalculation */
/* Some things in set last_known_column_point to -1
to mark the memoized value as invalid */
@@ -48,23 +46,6 @@ int last_known_column_point;
int last_known_column_modified;
extern int minibuf_prompt_width;
-
-/* Get the display table to use for the current buffer. */
-
-struct Lisp_Vector *
-buffer_display_table ()
-{
- Lisp_Object thisbuf;
-
- thisbuf = current_buffer->display_table;
- if (XTYPE (thisbuf) == Lisp_Vector
- && XVECTOR (thisbuf)->size == DISP_TABLE_SIZE)
- return XVECTOR (thisbuf);
- if (XTYPE (Vstandard_display_table) == Lisp_Vector
- && XVECTOR (Vstandard_display_table)->size == DISP_TABLE_SIZE)
- return XVECTOR (Vstandard_display_table);
- return 0;
-}
DEFUN ("current-column", Fcurrent_column, Scurrent_column, 0, 0, 0,
"Return the horizontal position of point. Beginning of line is column 0.\n\
@@ -74,8 +55,7 @@ and point. (eg control characters will have a width of 2 or 4, tabs\n\
will have a variable width)\n\
Ignores finite width of screen, which means that this function may return\n\
values greater than (screen-width).\n\
-Whether the line is visible (if `selective-display' is t) has no effect;\n\
-however, ^M is treated as end of line when `selective-display' is t.")
+Whether the line is visible (if `selective-display' is t) has no effect.")
()
{
Lisp_Object temp;
@@ -83,18 +63,22 @@ however, ^M is treated as end of line when `selective-display' is t.")
return temp;
}
+/* Cancel any recorded value of the horizontal position. */
+
+invalidate_current_column ()
+{
+ last_known_column_point = 0;
+}
+
int
current_column ()
{
register int col;
- register unsigned char *ptr, *stop;
+ register unsigned char *ptr, *stop, c;
register int tab_seen;
- int post_tab;
- register int c;
+ register int post_tab;
register int tab_width = XINT (current_buffer->tab_width);
int ctl_arrow = !NULL (current_buffer->ctl_arrow);
- register struct Lisp_Vector *dp = buffer_display_table ();
- int stopchar;
if (point == last_known_column_point
&& MODIFF == last_known_column_modified)
@@ -131,8 +115,7 @@ current_column ()
}
c = *--ptr;
- if (c >= 040 && c < 0177
- && (dp == 0 || XTYPE (DISP_CHAR_ROPE (dp, c)) != Lisp_String))
+ if (c >= 040 && c < 0177)
{
col++;
}
@@ -149,8 +132,6 @@ current_column ()
col = 0;
tab_seen = 1;
}
- else if (dp != 0 && XTYPE (DISP_CHAR_ROPE (dp, c)) == Lisp_String)
- col += XSTRING (DISP_CHAR_ROPE (dp, c))->size / sizeof (GLYPH);
else
col += (ctl_arrow && c < 0200) ? 2 : 4;
}
@@ -168,11 +149,45 @@ current_column ()
return col;
}
+ToCol (col)
+ int col;
+{
+ register int fromcol = current_column ();
+ register int n;
+ register int tab_width = XINT (current_buffer->tab_width);
+
+ if (fromcol > col)
+ return;
+
+ if (tab_width <= 0 || tab_width > 20) tab_width = 8;
+
+ if (indent_tabs_mode)
+ {
+ n = col / tab_width - fromcol / tab_width;
+ if (n)
+ {
+ while (n-- > 0)
+ insert ("\t", 1);
+
+ fromcol = (col / tab_width) * tab_width;
+ }
+ }
+
+ while (fromcol < col)
+ {
+ insert (" ", min (8, col - fromcol));
+ fromcol += min (8, col - fromcol);
+ }
+
+ last_known_column = col;
+ last_known_column_point = point;
+ last_known_column_modified = MODIFF;
+}
DEFUN ("indent-to", Findent_to, Sindent_to, 1, 2, "NIndent to column: ",
"Indent from point with tabs and spaces until COLUMN is reached.\n\
-Optional second argument MIN says always do at least MIN spaces\n\
-even if that goes past COLUMN; by default, MIN is zero.")
+Always do at least MIN spaces even if that goes past COLUMN;\n\
+by default, MIN is zero.")
(col, minimum)
Lisp_Object col, minimum;
{
@@ -190,7 +205,7 @@ even if that goes past COLUMN; by default, MIN is zero.")
if (mincol < XINT (col)) mincol = XINT (col);
if (fromcol == mincol)
- return make_number (mincol);
+ return make_number (fromcol);
if (tab_width <= 0 || tab_width > 20) tab_width = 8;
@@ -237,10 +252,10 @@ position_indentation (pos)
register int tab_width = XINT (current_buffer->tab_width);
register unsigned char *p;
register unsigned char *stop;
-
+
if (tab_width <= 0 || tab_width > 20) tab_width = 8;
-
- stop = &FETCH_CHAR (BUFFER_CEILING_OF (pos)) + 1;
+
+ stop = &FETCH_CHAR (BufferSafeCeiling (pos)) + 1;
p = &FETCH_CHAR (pos);
while (1)
{
@@ -250,7 +265,7 @@ position_indentation (pos)
return column;
pos += p - &FETCH_CHAR (pos);
p = &FETCH_CHAR (pos);
- stop = &FETCH_CHAR (BUFFER_CEILING_OF (pos)) + 1;
+ stop = &FETCH_CHAR (BufferSafeCeiling (pos)) + 1;
}
switch (*p++)
{
@@ -266,43 +281,29 @@ position_indentation (pos)
}
}
-DEFUN ("move-to-column", Fmove_to_column, Smove_to_column, 1, 2, 0,
+DEFUN ("move-to-column", Fmove_to_column, Smove_to_column, 1, 1, 0,
"Move point to column COLUMN in the current line.\n\
-The column of a character is calculated by adding together the widths\n\
-as displayed of the previous characters in the line.\n\
-This function ignores line-continuation;\n\
-there is no upper limit on the column number a character can have\n\
-and horizontal scrolling has no effect.\n\n\
-If specified column is within a character, point goes after that character.\n\
-If it's past end of line, point goes to end of line.\n\n\
-A non-nil second (optional) argument FORCE means, if the line\n\
-is too short to reach column COLUMN then add spaces/tabs to get there,\n\
-and if COLUMN is in the middle of a tab character, change it to spaces.")
- (column, force)
- Lisp_Object column, force;
+COLUMN is calculated by adding together the widths of all the displayed\n\
+representations of the character between the start of the previous line\n\
+and point. (eg control characters will have a width of 2 or 4, tabs\n\
+will have a variable width)\n\
+Ignores finite width of screen, which means that this function may be\n\
+passed values greater than (screen-width)")
+ (column)
+ Lisp_Object column;
{
- register int pos;
+ register int pos = point;
register int col = current_column ();
register int goal;
- register int end;
+ register int end = ZV;
register int tab_width = XINT (current_buffer->tab_width);
register int ctl_arrow = !NULL (current_buffer->ctl_arrow);
- register struct Lisp_Vector *dp = buffer_display_table ();
Lisp_Object val;
- int prev_col;
- int c;
if (tab_width <= 0 || tab_width > 20) tab_width = 8;
- CHECK_NATNUM (column, 0);
+ CHECK_NUMBER (column, 0);
goal = XINT (column);
-
- retry:
- pos = point;
- end = ZV;
-
- /* If we're starting past the desired column,
- back up to beginning of line and scan from there. */
if (col > goal)
{
pos = find_next_newline (pos, -1);
@@ -311,44 +312,26 @@ and if COLUMN is in the middle of a tab character, change it to spaces.")
while (col < goal && pos < end)
{
- c = FETCH_CHAR (pos);
+ int c = FETCH_CHAR (pos);
if (c == '\n')
break;
if (c == '\r' && EQ (current_buffer->selective_display, Qt))
break;
pos++;
+ col++;
if (c == '\t')
{
- prev_col = col;
- col += tab_width;
+ col += tab_width - 1;
col = col / tab_width * tab_width;
}
- else if (dp != 0 && XTYPE (DISP_CHAR_ROPE (dp, c)) == Lisp_String)
- col += XSTRING (DISP_CHAR_ROPE (dp, c))->size / sizeof (GLYPH);
else if (ctl_arrow && (c < 040 || c == 0177))
col++;
else if (c < 040 || c >= 0177)
col += 3;
- else
- col++;
}
SET_PT (pos);
- /* If a tab char made us overshoot, change it to spaces
- and scan through it again. */
- if (!NULL (force) && col > goal && c == '\t' && prev_col < goal)
- {
- del_range (point - 1, point);
- Findent_to (make_number (col - 1));
- insert_char (' ');
- goto retry;
- }
-
- /* If line ends prematurely, add space to the end. */
- if (col < goal && !NULL (force))
- Findent_to (make_number (col = goal));
-
last_known_column = col;
last_known_column_point = point;
last_known_column_modified = MODIFF;
@@ -359,102 +342,47 @@ and if COLUMN is in the middle of a tab character, change it to spaces.")
struct position val_compute_motion;
-/* Scan the current buffer forward from offset FROM, pretending that
- this is at line FROMVPOS, column FROMHPOS, until reaching buffer
- offset TO or line TOVPOS, column TOHPOS (whichever comes first),
- and return the ending buffer position and screen location.
-
- WIDTH is the number of columns available to display text;
- compute_motion uses this to handle continuation lines and such.
- HSCROLL is the number of columns not being displayed at the left
- margin; this is usually taken from a window's hscroll member.
- TAB_OFFSET is a mysterious value, perhaps the number of columns of
- the first tab that aren't being displayed, perhaps because of a
- continuation line or something.
-
- compute_motion returns a pointer to a struct position. The bufpos
- member gives the buffer position at the end of the scan, and hpos
- and vpos give its cartesian location. I'm not clear on what the
- other members are.
-
- For example, to find the buffer position of column COL of line LINE
- of a certain window, pass the window's starting location as FROM
- and the window's upper-left coordinates as FROMVPOS and FROMHPOS.
- Pass the buffer's ZV as TO, to limit the scan to the end of the
- visible section of the buffer, and pass LINE and COL as TOVPOS and
- TOHPOS.
-
- When displaying in window w, a typical formula for WIDTH is:
-
- window_width - 1
- - (window_width + window_left != screen_width)
-
- where
- window_width is XFASTINT (w->width),
- window_left is XFASTINT (w->left),
- and screen_width = SCREEN_WIDTH (XSCREEN (window->screen))
-
- This accounts for the continuation-line backslashes, and the window
- borders if the window is split vertically. */
-
struct position *
compute_motion (from, fromvpos, fromhpos, to, tovpos, tohpos, width, hscroll, tab_offset)
int from, fromvpos, fromhpos, to, tovpos, tohpos;
register int width;
int hscroll, tab_offset;
{
-/* Note that `cpos' is CURRENT_VPOS << SHORTBITS + CURRENT_HPOS,
- and that CURRENT_HPOS may be negative. Use these macros
- to extract the hpos or the vpos from cpos or anything like it.
- */
-#ifndef SHORT_CAST_BUG
-#define HPOS(VAR) (short) (VAR)
-#else
-#define HPOS(VAR) (((VAR) & (1 << (SHORTBITS - 1)) \
- ? ~((1 << SHORTBITS) - 1) : 0) \
- | (VAR) & ((1 << SHORTBITS) - 1))
-/* #define HPOS(VAR) (((VAR) & 0x8000 ? 0xffff0000 : 0) | ((VAR) & 0xffff)) */
-#endif /* SHORT_CAST_BUG */
-
-#define VPOS(VAR) (((VAR) >> SHORTBITS) + (HPOS (VAR) < 0))
-
-
-#ifndef TAHOE_REGISTER_BUG
- register
-#endif /* TAHOE_REGISTER_BUG */
- int cpos = fromhpos + (fromvpos << SHORTBITS);
- register int target = tohpos + (tovpos << SHORTBITS);
+ register int hpos = fromhpos;
+ register int vpos = fromvpos;
+
register int pos;
register int c;
register int tab_width = XFASTINT (current_buffer->tab_width);
register int ctl_arrow = !NULL (current_buffer->ctl_arrow);
- register struct Lisp_Vector *dp = buffer_display_table ();
int selective
= XTYPE (current_buffer->selective_display) == Lisp_Int
? XINT (current_buffer->selective_display)
: !NULL (current_buffer->selective_display) ? -1 : 0;
- int prevpos;
- int selective_rlen
- = (selective && dp && XTYPE (DISP_INVIS_ROPE (dp)) == Lisp_String
- ? XSTRING (DISP_INVIS_ROPE (dp))->size / sizeof (GLYPH) : 0);
+ int prev_vpos, prev_hpos;
if (tab_width <= 0 || tab_width > 20) tab_width = 8;
- for (pos = from; pos < to && cpos < target; pos++)
+ for (pos = from; pos < to; pos++)
{
- prevpos = cpos;
+ /* Stop if past the target screen position. */
+ if (vpos > tovpos
+ || (vpos == tovpos && hpos >= tohpos))
+ break;
+
+ prev_vpos = vpos;
+ prev_hpos = hpos;
+
c = FETCH_CHAR (pos);
- if (c >= 040 && c < 0177
- && (dp == 0 || XTYPE (DISP_CHAR_ROPE (dp, c)) != Lisp_String))
- cpos++;
+ if (c >= 040 && c < 0177)
+ hpos++;
else if (c == '\t')
{
- cpos += tab_width
- - HPOS (cpos + tab_offset + hscroll - (hscroll > 0)
- /* Add tab_width here to make sure positive.
- cpos can be negative after continuation
- but can't be less than -tab_width. */
- + tab_width)
- % tab_width;
+ hpos += tab_width - ((hpos + tab_offset + hscroll - (hscroll > 0)
+ /* Add tab_width here to make sure positive.
+ hpos can be negative after continuation
+ but can't be less than -tab_width. */
+ + tab_width)
+ % tab_width);
}
else if (c == '\n')
{
@@ -463,61 +391,72 @@ compute_motion (from, fromvpos, fromhpos, to, tovpos, tohpos, width, hscroll, ta
/* Skip any number of invisible lines all at once */
do
{
- while (++pos < to && FETCH_CHAR(pos) != '\n');
+ while (++pos < to && FETCH_CHAR (pos) != '\n');
}
- while (selective > 0 && position_indentation (pos + 1) >= selective);
+ while (pos < to && position_indentation (pos + 1) >= selective);
pos--;
/* Allow for the " ..." that is displayed for them. */
- if (selective_rlen)
+ if (!NULL (current_buffer->selective_display_ellipses))
{
- cpos += selective_rlen;
- if (HPOS (cpos) >= width)
- cpos -= HPOS (cpos) - width;
+ hpos += 4;
+ if (hpos >= width)
+ hpos = width;
}
+ /* We have skipped the invis text, but not the newline after. */
}
else
- cpos += (1 << SHORTBITS) - HPOS (cpos);
- cpos -= hscroll;
- if (hscroll > 0) cpos++; /* Count the ! on column 0 */
- tab_offset = 0;
+ {
+ /* A visible line follows.
+ Skip this newline and advance to next line. */
+ vpos++;
+ hpos = 0;
+ hpos -= hscroll;
+ if (hscroll > 0) hpos++; /* Count the ! on column 0 */
+ tab_offset = 0;
+ }
}
else if (c == CR && selective < 0)
{
/* In selective display mode,
everything from a ^M to the end of the line is invisible */
- while (pos < to && FETCH_CHAR(pos) != '\n') pos++;
+ while (pos < to && FETCH_CHAR (pos) != '\n') pos++;
+ /* Stop *before* the real newline. */
pos--;
/* Allow for the " ..." that is displayed for them. */
- if (selective_rlen)
+ if (!NULL (current_buffer->selective_display_ellipses))
{
- cpos += selective_rlen;
- if (HPOS (cpos) >= width)
- cpos -= HPOS (cpos) - width;
+ hpos += 4;
+ if (hpos >= width)
+ hpos = width;
}
}
- else if (dp != 0 && XTYPE (DISP_CHAR_ROPE (dp, c)) == Lisp_String)
- cpos += XSTRING (DISP_CHAR_ROPE (dp, c))->size / sizeof (GLYPH);
else
- cpos += (ctl_arrow && c < 0200) ? 2 : 4;
+ hpos += (ctl_arrow && c < 0200) ? 2 : 4;
- if (HPOS (cpos) >= width
- && (HPOS (cpos) > width
- || (pos < (ZV - 1)
+ /* Handle right margin. */
+ if (hpos >= width
+ && (hpos > width
+ || (pos < ZV - 1
&& FETCH_CHAR (pos + 1) != '\n')))
{
- if (cpos >= target)
+ if (vpos > tovpos
+ || (vpos == tovpos && hpos >= tohpos))
break;
if (hscroll
|| (truncate_partial_width_windows
- && width + 1 < SCREEN_WIDTH (selected_screen))
+ && width + 1 < screen_width)
|| !NULL (current_buffer->truncate_lines))
{
- while (pos < to && FETCH_CHAR(pos) != '\n') pos++;
+ /* Truncating: skip to newline. */
+ while (pos < to && FETCH_CHAR (pos) != '\n') pos++;
pos--;
+ hpos = width;
}
else
{
- cpos += (1 << SHORTBITS) - width;
+ /* Continuing. */
+ vpos++;
+ hpos -= width;
tab_offset += width;
}
@@ -525,44 +464,35 @@ compute_motion (from, fromvpos, fromhpos, to, tovpos, tohpos, width, hscroll, ta
}
val_compute_motion.bufpos = pos;
- val_compute_motion.hpos = HPOS (cpos);
- val_compute_motion.vpos = VPOS (cpos);
- val_compute_motion.prevhpos = HPOS (prevpos);
+ val_compute_motion.hpos = hpos;
+ val_compute_motion.vpos = vpos;
+ val_compute_motion.prevhpos = prev_hpos;
/* Nonzero if have just continued a line */
val_compute_motion.contin
- = pos != from
- && (val_compute_motion.vpos != VPOS (prevpos))
- && c != '\n';
+ = (pos != from
+ && (val_compute_motion.vpos != prev_vpos)
+ && c != '\n');
return &val_compute_motion;
}
-#undef HPOS
-#undef VPOS
-
-/* Return the column of position POS in window W's buffer,
- rounded down to a multiple of the internal width of W.
- This is the amount of indentation of position POS
- that is not visible in its horizontal position in the window. */
-
-int
pos_tab_offset (w, pos)
struct window *w;
register int pos;
{
int opoint = point;
int col;
- int width = XFASTINT (w->width) - 1
- - (XFASTINT (w->width) + XFASTINT (w->left)
- != SCREEN_WIDTH (XSCREEN (w->screen)));
if (pos == BEGV || FETCH_CHAR (pos - 1) == '\n')
return 0;
SET_PT (pos);
col = current_column ();
SET_PT (opoint);
- return col - (col % width);
+ return (col
+ - (col % (XFASTINT (w->width) - 1
+ - (XFASTINT (w->width) + XFASTINT (w->left)
+ != screen_width))));
}
/* start_hpos is the hpos of the first character of the buffer:
@@ -603,7 +533,7 @@ vmotion (from, vtarget, width, hscroll, window)
prevline = find_next_newline (prevline - 1, -1);
pos = *compute_motion (prevline, 0,
lmargin + (prevline == 1 ? start_hpos : 0),
- from, 10000, 10000,
+ from, 1 << (INTBITS - 2), 0,
width, hscroll, 0);
}
else
@@ -612,7 +542,7 @@ vmotion (from, vtarget, width, hscroll, window)
pos.vpos = 0;
}
return compute_motion (from, vpos, pos.hpos,
- ZV, vtarget, - (1 << (SHORTBITS - 1)),
+ ZV, vtarget, - (1 << (INTBITS - 2)),
width, hscroll, pos.vpos * width);
}
@@ -634,7 +564,7 @@ vmotion (from, vtarget, width, hscroll, window)
}
pos = *compute_motion (prevline, 0,
lmargin + (prevline == 1 ? start_hpos : 0),
- from, 10000, 10000,
+ from, 1 << (INTBITS - 2), 0,
width, hscroll, 0);
vpos -= pos.vpos;
first = 0;
@@ -670,13 +600,13 @@ Returns number of lines moved; may be closer to zero than LINES\n\
{
struct position pos;
register struct window *w = XWINDOW (selected_window);
- int width = XFASTINT (w->width) - 1
- - (XFASTINT (w->width) + XFASTINT (w->left)
- != SCREEN_WIDTH (XSCREEN (w->screen)));
CHECK_NUMBER (lines, 0);
- pos = *vmotion (point, XINT (lines), width,
+ pos = *vmotion (point, XINT (lines),
+ XFASTINT (w->width) - 1
+ - (XFASTINT (w->width) + XFASTINT (w->left)
+ != XFASTINT (XWINDOW (minibuf_window)->width)),
/* Not XFASTINT since perhaps could be negative */
XINT (w->hscroll), selected_window);
diff --git a/src/mocklisp.h b/src/indent.h
index e381bb23f8b..c11b13bb654 100644
--- a/src/mocklisp.h
+++ b/src/indent.h
@@ -1,5 +1,5 @@
-/* Fundamental definitions for emulating mocklisp.
- Copyright (C) 1985, 1986, 1987 Free Software Foundation, Inc.
+/* Definitions for interface to indent.c
+ Copyright (C) 1985, 1986 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -17,15 +17,15 @@ You should have received a copy of the GNU General Public License
along with GNU Emacs; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-/* This is the main entry point to mocklisp execution.
- When eval sees a mocklisp function being called, it calls here
- with the unevaluated argument list */
-extern Lisp_Object ml_apply ();
-extern Lisp_Object Fml_if ();
-extern Lisp_Object Fml_nargs ();
-extern Lisp_Object Fml_arg ();
-extern Lisp_Object Fml_interactive ();
-extern Lisp_Object Fml_provide_prefix_argument ();
-extern Lisp_Object Fml_prefix_argument_loop ();
-extern Lisp_Object FInsStr ();
+struct position
+ {
+ int bufpos;
+ int hpos;
+ int vpos;
+ int prevhpos;
+ int contin;
+ };
+
+struct position *compute_motion ();
+struct position *vmotion ();
diff --git a/src/insdel.c b/src/insdel.c
index 2de7744522e..a3eb061ee99 100644
--- a/src/insdel.c
+++ b/src/insdel.c
@@ -1,5 +1,5 @@
/* Buffer insertion/deletion and gap motion for GNU Emacs.
- Copyright (C) 1985, 1986 Free Software Foundation, Inc.
+ Copyright (C) 1985, 1986, 1990 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -23,10 +23,6 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "buffer.h"
#include "window.h"
-/* Nonzero means don't allow protected fields to be modified. */
-
-extern int check_protected_fields;
-
/* Move gap to position `pos'.
Note that this can quit! */
@@ -92,28 +88,9 @@ gap_left (pos, newgap)
/* Move at most 32000 chars before checking again for a quit. */
if (i > 32000)
i = 32000;
-#ifdef GAP_USE_BCOPY
- if (i >= 128
- /* bcopy is safe if the two areas of memory do not overlap
- or on systems where bcopy is always safe for moving upward. */
- && (BCOPY_UPWARD_SAFE
- || to - from >= 128))
- {
- /* If overlap is not safe, avoid it by not moving too many
- characters at once. */
- if (!BCOPY_UPWARD_SAFE && i > to - from)
- i = to - from;
- new_s1 -= i;
- from -= i, to -= i;
- bcopy (from, to, i);
- }
- else
-#endif
- {
- new_s1 -= i;
- while (--i >= 0)
- *--to = *--from;
- }
+ new_s1 -= i;
+ while (--i >= 0)
+ *--to = *--from;
}
/* Adjust markers, and buffer data structure, to put the gap at POS.
@@ -170,28 +147,9 @@ gap_right (pos)
/* Move at most 32000 chars before checking again for a quit. */
if (i > 32000)
i = 32000;
-#ifdef GAP_USE_BCOPY
- if (i >= 128
- /* bcopy is safe if the two areas of memory do not overlap
- or on systems where bcopy is always safe for moving downward. */
- && (BCOPY_DOWNWARD_SAFE
- || from - to >= 128))
- {
- /* If overlap is not safe, avoid it by not moving too many
- characters at once. */
- if (!BCOPY_DOWNWARD_SAFE && i > from - to)
- i = from - to;
- new_s1 += i;
- bcopy (from, to, i);
- from += i, to += i;
- }
- else
-#endif
- {
- new_s1 += i;
- while (--i >= 0)
- *to++ = *from++;
- }
+ new_s1 += i;
+ while (--i >= 0)
+ *to++ = *from++;
}
adjust_markers (GPT + GAP_SIZE, pos + 1 + GAP_SIZE, - GAP_SIZE);
@@ -240,7 +198,7 @@ adjust_markers (from, to, amount)
make_gap (increment)
int increment;
{
- unsigned char *result;
+ unsigned char *memory;
Lisp_Object tem;
int real_gap_loc;
int old_gap_size;
@@ -248,10 +206,11 @@ make_gap (increment)
/* If we have to get more space, get enough to last a while. */
increment += 2000;
- result = BUFFER_REALLOC (BEG_ADDR, (Z - BEG + GAP_SIZE + increment));
- if (result == 0)
+ memory = (unsigned char *) realloc (BEG_ADDR,
+ Z - BEG + GAP_SIZE + increment);
+ if (memory == 0)
memory_full ();
- BEG_ADDR = result;
+ BEG_ADDR = memory;
/* Prevent quitting in move_gap. */
tem = Vinhibit_quit;
@@ -259,15 +218,12 @@ make_gap (increment)
real_gap_loc = GPT;
old_gap_size = GAP_SIZE;
-
/* Call the newly allocated space a gap at the end of the whole space. */
GPT = Z + GAP_SIZE;
GAP_SIZE = increment;
-
/* Move the new gap down to be consecutive with the end of the old one.
This adjusts the markers properly too. */
gap_left (real_gap_loc + old_gap_size, 1);
-
/* Now combine the two into one large gap. */
GAP_SIZE += old_gap_size;
GPT = real_gap_loc;
@@ -275,6 +231,22 @@ make_gap (increment)
Vinhibit_quit = tem;
}
+/* Insert the character c before point */
+
+insert_char (c)
+ unsigned char c;
+{
+ insert (&c, 1);
+}
+
+/* Insert the null-terminated string s before point */
+
+InsStr (s)
+ char *s;
+{
+ insert (s, strlen (s));
+}
+
/* Insert a string of specified length before point.
DO NOT use this for the contents of a Lisp string!
prepare_to_modify_buffer could relocate the string. */
@@ -293,7 +265,7 @@ insert (string, length)
if (length + Z != XINT (temp))
error ("maximum buffer size exceeded");
- prepare_to_modify_buffer (point, point);
+ prepare_to_modify_buffer ();
if (point != GPT)
move_gap (point);
@@ -309,15 +281,14 @@ insert (string, length)
GPT += length;
ZV += length;
Z += length;
- SET_PT (point + length);
-
- signal_after_change (point-length, 0, length);
+ point += length;
}
-/* Function to insert part of the text of a string (STRING)
- consisting of LENGTH characters at position POS.
- It does not work to use `insert' for this. */
-
+/* Function to insert part of the text of a string (STRING) consisting
+ of LENGTH characters at position POS.
+ It does not work to use `insert' for this, becase a GC could happen
+ before we bcopy the stuff into the buffer, and relocate the string
+ without insert noticing. */
insert_from_string (string, pos, length)
Lisp_Object string;
register int pos, length;
@@ -334,7 +305,7 @@ insert_from_string (string, pos, length)
error ("maximum buffer size exceeded");
GCPRO1 (string);
- prepare_to_modify_buffer (point, point);
+ prepare_to_modify_buffer ();
if (point != GPT)
move_gap (point);
@@ -352,26 +323,6 @@ insert_from_string (string, pos, length)
ZV += length;
Z += length;
point += length;
-
- signal_after_change (point-length, 0, length);
-}
-
-/* Insert the character C before point */
-
-void
-insert_char (c)
- unsigned char c;
-{
- insert (&c, 1);
-}
-
-/* Insert the null-terminated string S before point */
-
-void
-insert_string (s)
- char *s;
-{
- insert (s, strlen (s));
}
/* Like `insert' except that all markers pointing at the place where
@@ -400,7 +351,7 @@ insert_from_string_before_markers (string, pos, length)
}
/* Delete characters in current buffer
- from FROM up to (but not including) TO. */
+ from `from' up to (but not incl) `to' */
del_range (from, to)
register int from, to;
@@ -416,26 +367,25 @@ del_range (from, to)
if ((numdel = to - from) <= 0)
return;
- /* Make sure the gap is somewhere in or next to what we are deleting. */
+ /* Make sure the gap is somewhere in or next to what we are deleting */
if (from > GPT)
gap_right (from);
if (to < GPT)
gap_left (to, 0);
- prepare_to_modify_buffer (from, to);
+ prepare_to_modify_buffer ();
+ record_delete (from, numdel);
+ MODIFF++;
/* Relocate point as if it were a marker. */
if (from < point)
{
if (point < to)
- SET_PT (from);
+ point = from;
else
- SET_PT (point - numdel);
+ point -= numdel;
}
- record_delete (from, numdel);
- MODIFF++;
-
/* Relocate all markers pointing into the new, larger gap
to point at the end of the text before the gap. */
adjust_markers (to + GAP_SIZE, to + GAP_SIZE, - numdel - GAP_SIZE);
@@ -449,15 +399,12 @@ del_range (from, to)
beg_unchanged = GPT - BEG;
if (Z - GPT < end_unchanged)
end_unchanged = Z - GPT;
-
- signal_after_change (from, numdel, 0);
}
modify_region (start, end)
int start, end;
{
- prepare_to_modify_buffer (start, end);
-
+ prepare_to_modify_buffer ();
if (start - 1 < beg_unchanged || unchanged_modified == MODIFF)
beg_unchanged = start - 1;
if (Z - end < end_unchanged
@@ -466,17 +413,10 @@ modify_region (start, end)
MODIFF++;
}
-/* Check that it is okay to modify the buffer between START and END.
- Run the before-change-function, if any. */
-
-prepare_to_modify_buffer (start, end)
- Lisp_Object start, end;
+prepare_to_modify_buffer ()
{
if (!NULL (current_buffer->read_only))
- Fbarf_if_buffer_read_only ();
-
- if (check_protected_fields)
- Fregion_fields (start, end, Qnil, Qt);
+ Fbarf_if_buffer_read_only();
#ifdef CLASH_DETECTION
if (!NULL (current_buffer->filename)
@@ -491,80 +431,4 @@ prepare_to_modify_buffer (start, end)
call1 (intern ("ask-user-about-supersession-threat"),
current_buffer->filename);
#endif /* not CLASH_DETECTION */
-
- signal_before_change (start, end);
-}
-
-static Lisp_Object
-before_change_function_restore (value)
- Lisp_Object value;
-{
- Vbefore_change_function = value;
-}
-
-static Lisp_Object
-after_change_function_restore (value)
- Lisp_Object value;
-{
- Vafter_change_function = value;
-}
-
-/* Signal a change to the buffer immediatly before it happens.
- START and END are the bounds of the text to be changed,
- as Lisp objects. */
-
-signal_before_change (start, end)
- Lisp_Object start, end;
-{
- /* If buffer is unmodified, run a special hook for that case. */
- if (current_buffer->save_modified >= MODIFF
- && !NULL (Vfirst_change_function))
- {
- call0 (Vfirst_change_function);
- }
- /* Now in any case run the before-change-function if any. */
- if (!NULL (Vbefore_change_function))
- {
- int count = specpdl_ptr - specpdl;
- Lisp_Object function;
-
- function = Vbefore_change_function;
- record_unwind_protect (after_change_function_restore,
- Vafter_change_function);
- record_unwind_protect (before_change_function_restore,
- Vbefore_change_function);
- Vafter_change_function = Qnil;
- Vbefore_change_function = Qnil;
-
- call2 (function, start, end);
- unbind_to (count, Qnil);
- }
-}
-
-/* Signal a change immediatly after it happens.
- POS is the address of the start of the changed text.
- LENDEL is the number of characters of the text before the change.
- (Not the whole buffer; just the part that was changed.)
- LENINS is the number of characters in the changed text. */
-
-signal_after_change (pos, lendel, lenins)
- int pos, lendel, lenins;
-{
- if (!NULL (Vafter_change_function))
- {
- int count = specpdl_ptr - specpdl;
- Lisp_Object function;
- function = Vafter_change_function;
-
- record_unwind_protect (after_change_function_restore,
- Vafter_change_function);
- record_unwind_protect (before_change_function_restore,
- Vbefore_change_function);
- Vafter_change_function = Qnil;
- Vbefore_change_function = Qnil;
-
- call3 (function, make_number (pos), make_number (pos + lenins),
- make_number (lendel));
- unbind_to (count, Qnil);
- }
}
diff --git a/src/ioctl.h b/src/ioctl.h
new file mode 100644
index 00000000000..0366f6d6bd5
--- /dev/null
+++ b/src/ioctl.h
@@ -0,0 +1 @@
+/* Emacs ioctl emulation for VMS */
diff --git a/src/keyboard.c b/src/keyboard.c
new file mode 100644
index 00000000000..a27354d0454
--- /dev/null
+++ b/src/keyboard.c
@@ -0,0 +1,2288 @@
+/* Keyboard input; editor command loop.
+ Copyright (C) 1985, 1986, 1987, 1988, 1990 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*** For version 19, can simplify this by making interrupt_input 1 on VMS. */
+
+/* This must precede sys/signal.h on certain machines. */
+#include <sys/types.h>
+/* Allow config.h to undefine symbols found here. */
+#include <signal.h>
+
+#include "config.h"
+#include <stdio.h>
+#undef NULL
+#include "termchar.h"
+#include "termopts.h"
+#include "termhooks.h"
+#include "lisp.h"
+#include "macros.h"
+#include "window.h"
+#include "commands.h"
+#include "buffer.h"
+#include <setjmp.h>
+#include <errno.h>
+
+extern int errno;
+
+/* Get FIONREAD, if it is available. */
+#ifdef USG
+#include <termio.h>
+#include <fcntl.h>
+#else /* not USG */
+#ifndef VMS
+#include <sys/ioctl.h>
+#endif /* not VMS */
+#endif /* not USG */
+
+#include "emacssignal.h"
+
+/* Allow m- file to inhibit use of FIONREAD. */
+#ifdef BROKEN_FIONREAD
+#undef FIONREAD
+#endif
+
+/* Make all keyboard buffers much bigger when using X windows. */
+#ifdef HAVE_X_WINDOWS
+#define BUFFER_SIZE_FACTOR 16
+#else
+#define BUFFER_SIZE_FACTOR 1
+#endif
+
+/* Following definition copied from eval.c */
+
+struct backtrace
+ {
+ struct backtrace *next;
+ Lisp_Object *function;
+ Lisp_Object *args; /* Points to vector of args. */
+ int nargs; /* length of vector */
+ /* if nargs is UNEVALLED, args points to slot holding list of unevalled args */
+ char evalargs;
+ };
+
+/* Non-nil disable property on a command means
+ do not execute it; call disabled-command-hook's value instead. */
+Lisp_Object Qdisabled, Vdisabled_command_hook;
+
+int recent_keys_index; /* Index for storing next element into recent_keys */
+int total_keys; /* Total number of elements stored into recent_keys */
+char recent_keys[100]; /* Holds last 100 keystrokes */
+
+/* Buffer holding the key that invoked the current command. */
+unsigned char *this_command_keys;
+int this_command_key_count; /* Size in use. */
+int this_command_keys_size; /* Size allocated. */
+
+extern struct backtrace *backtrace_list;
+
+static jmp_buf getcjmp; /* for longjmp to where kbd input is being done. */
+
+int waiting_for_input; /* True while doing kbd input */
+
+/* True while displaying for echoing. Delays C-g throwing. */
+static int echoing;
+
+int immediate_quit; /* Nonzero means C-G should cause immediate error-signal. */
+
+int help_char; /* Character to recognize as the help char. */
+
+Lisp_Object Vhelp_form; /* Form to execute when help char is typed. */
+
+/* Character that causes a quit. Normally C-g. */
+
+int quit_char;
+
+extern Lisp_Object global_map;
+
+/* Current depth in recursive edits. */
+
+int command_loop_level;
+
+/* Last input character read as a command. */
+
+int last_command_char;
+
+/* Last input character read for any purpose. */
+
+int last_input_char;
+
+/* If not -1, a character to be read as the next command input */
+
+int unread_command_char;
+
+/* Char to use as prefix when a meta character is typed in.
+ This is bound on entry to minibuffer in case Esc is changed there. */
+
+int meta_prefix_char;
+
+/* Total number of times read_command_char has returned. */
+
+int num_input_chars;
+
+/* Auto-save automatically when this many characters have been typed
+ since the last time. */
+
+static int auto_save_interval;
+
+/* Value of num_input_chars as of last auto save. */
+
+int last_auto_save;
+
+/* Last command executed by the editor command loop, not counting
+ commands that set the prefix argument. */
+
+Lisp_Object last_command;
+
+/* The command being executed by the command loop.
+ Commands may set this, and the value set will be copied into last_command
+ instead of the actual command. */
+Lisp_Object this_command;
+
+Lisp_Object Qself_insert_command;
+Lisp_Object Qforward_char;
+Lisp_Object Qbackward_char;
+
+/* read_key_sequence stores here the command definition of the
+ key sequence that it reads. */
+Lisp_Object read_key_sequence_cmd;
+
+/* Form to evaluate (if non-nil) when Emacs is started */
+Lisp_Object Vtop_level;
+
+/* User-supplied string to translate input characters through */
+Lisp_Object Vkeyboard_translate_table;
+
+FILE *dribble; /* File in which we write all commands we read */
+
+/* Nonzero if input is available */
+int input_pending;
+
+/* Nonzero if should obey 0200 bit in input chars as "Meta" */
+int meta_key;
+
+extern char *pending_malloc_warning;
+
+/* Buffer for pre-read keyboard input */
+unsigned char kbd_buffer [256 * BUFFER_SIZE_FACTOR];
+
+/* Number of characters available in kbd_buffer. */
+int kbd_count;
+
+/* Pointer to next available character in kbd_buffer. */
+unsigned char *kbd_ptr;
+
+/* Address (if not 0) of word to zero out
+ if a SIGIO interrupt happens */
+long *input_available_clear_word;
+
+/* Nonzero means use SIGIO interrupts; zero means use CBREAK mode.
+ Default is 1 if INTERRUPT_INPUT is defined. */
+
+int interrupt_input;
+
+/* Nonzero while interrupts are temporarily deferred during redisplay. */
+
+int interrupts_deferred;
+
+/* nonzero means use ^S/^Q for flow control. */
+
+int flow_control;
+
+#ifndef BSD4_1
+#define sigfree() sigsetmask (SIGEMPTYMASK)
+#define sigholdx(sig) sigsetmask (sigmask (sig))
+#define sigblockx(sig) sigblock (sigmask (sig))
+#define sigunblockx(sig) sigblock (SIGEMPTYMASK)
+#define sigpausex(sig) sigpause (0)
+#endif /* not BSD4_1 */
+
+#ifdef BSD4_1
+#define SIGIO SIGTINT
+/* sigfree and sigholdx are in sysdep.c */
+#define sigblockx(sig) sighold (sig)
+#define sigunblockx(sig) sigrelse (sig)
+#define sigpausex(sig) sigpause (sig)
+#endif /* BSD4_1 */
+
+/* We are unable to use interrupts if FIONREAD is not available,
+ so flush SIGIO so we won't try. */
+#ifndef FIONREAD
+#ifdef SIGIO
+#undef SIGIO
+#endif
+#endif
+
+/* If we support X Windows, and won't get an interrupt when input
+ arrives from the server, poll periodically so we can detect C-g. */
+#ifdef HAVE_X_WINDOWS
+#ifndef SIGIO
+#define POLL_FOR_INPUT
+#endif
+#endif
+
+/* Function for init_keyboard to call with no args (if nonzero). */
+void (*keyboard_init_hook) ();
+
+static void read_avail_input ();
+static void get_input_pending ();
+
+/* Non-zero tells input_available_signal to call read_socket_hook
+ even if FIONREAD returns zero. */
+static int force_input;
+
+static int echo_keystrokes; /* > 0 if we are to echo keystrokes */
+
+/* Nonzero means echo each character as typed. */
+static int immediate_echo;
+
+#define min(a,b) ((a)<(b)?(a):(b))
+#define max(a,b) ((a)>(b)?(a):(b))
+
+static char echobuf[100];
+static char *echoptr;
+
+/* Install the string STR as the beginning of the string of echoing,
+ so that it serves as a prompt for the next character.
+ Also start echoing. */
+
+echo_prompt (str)
+ char *str;
+{
+ int len = strlen (str);
+ if (len > sizeof echobuf - 4)
+ len = sizeof echobuf - 4;
+ bcopy (str, echobuf, len + 1);
+ echoptr = echobuf + len;
+
+ echo ();
+}
+
+/* Add the character C to the echo string,
+ if echoing is going on. */
+
+echo_char (c)
+ int c;
+{
+ extern char *push_key_description ();
+
+ if (immediate_echo)
+ {
+ char *ptr = echoptr;
+
+ if (ptr - echobuf > sizeof echobuf - 6)
+ return;
+
+ if (echoptr != echobuf)
+ *ptr++ = ' ';
+
+ ptr = push_key_description (c, ptr);
+ if (echoptr == echobuf && c == help_char)
+ {
+ strcpy (ptr, " (Type ? for further options)");
+ ptr += strlen (ptr);
+ }
+
+ *ptr = 0;
+ echoptr = ptr;
+
+ echo ();
+ }
+}
+
+/* Temporarily add a dash to the end of the echo string,
+ so that it serves as a mini-prompt for the very next character. */
+
+echo_dash ()
+{
+ if (!immediate_echo && echoptr == echobuf)
+ return;
+
+ /* Put a dash at the end of the buffer temporarily,
+ but make it go away when the next character is added. */
+ echoptr[0] = '-';
+ echoptr[1] = 0;
+
+ echo ();
+}
+
+/* Display the current echo string, and begin echoing if not already
+ doing so. */
+
+echo ()
+{
+ if (!immediate_echo)
+ {
+ int i;
+ immediate_echo = 1;
+
+ for (i = 0; i < this_command_key_count; i++)
+ echo_char (this_command_keys[i]);
+ echo_dash ();
+ }
+
+ echoing = 1;
+ message1 (echobuf);
+ echoing = 0;
+
+ if (waiting_for_input && !NULL (Vquit_flag))
+ quit_throw_to_read_command_char ();
+}
+
+/* Turn off echoing, for the start of a new command. */
+
+cancel_echoing ()
+{
+ immediate_echo = 0;
+ echoptr = echobuf;
+}
+
+/* When an auto-save happens, record the "time", and don't do again soon. */
+record_auto_save ()
+{
+ last_auto_save = num_input_chars;
+}
+
+Lisp_Object recursive_edit_unwind (), command_loop ();
+
+DEFUN ("recursive-edit", Frecursive_edit, Srecursive_edit, 0, 0, "",
+ "Invoke the editor command loop recursively.\n\
+Do (throw 'exit nil) within the command loop to make this function return,\n\
+or (throw 'exit t) to make this function signal an error.\n\
+This function is called by the editor initialization\n\
+to begin editing.")
+ ()
+{
+ int count = specpdl_ptr - specpdl;
+
+ command_loop_level++;
+ update_mode_lines = 1;
+
+ record_unwind_protect (recursive_edit_unwind,
+ (current_buffer != XBUFFER (XWINDOW (selected_window)->buffer)
+ ? Fcurrent_buffer ()
+ : Qnil));
+
+ recursive_edit_1 ();
+
+ unbind_to (count);
+ return Qnil;
+}
+
+Lisp_Object
+recursive_edit_1 ()
+{
+ int count = specpdl_ptr - specpdl;
+ Lisp_Object val;
+
+ if (command_loop_level > 0)
+ {
+ specbind (Qstandard_output, Qt);
+ specbind (Qstandard_input, Qt);
+ }
+
+ val = command_loop ();
+ if (EQ (val, Qt))
+ Fsignal (Qquit, Qnil);
+
+ unbind_to (count);
+ return Qnil;
+}
+
+Lisp_Object
+recursive_edit_unwind (buffer)
+ Lisp_Object buffer;
+{
+ if (!NULL (buffer))
+ Fset_buffer (buffer);
+ command_loop_level--;
+ update_mode_lines = 1;
+ return Qnil;
+}
+
+Lisp_Object
+cmd_error (data)
+ Lisp_Object data;
+{
+ Lisp_Object errmsg, tail, errname, file_error;
+ struct gcpro gcpro1;
+ int i;
+
+ Vquit_flag = Qnil;
+ Vinhibit_quit = Qt;
+ Vstandard_output = Qt;
+ Vstandard_input = Qt;
+ Vexecuting_macro = Qnil;
+ echo_area_contents = 0;
+
+ Fdiscard_input ();
+ bell ();
+
+ errname = Fcar (data);
+
+ if (EQ (errname, Qerror))
+ {
+ data = Fcdr (data);
+ if (!CONSP (data)) data = Qnil;
+ errmsg = Fcar (data);
+ file_error = Qnil;
+ }
+ else
+ {
+ errmsg = Fget (errname, Qerror_message);
+ file_error = Fmemq (Qfile_error,
+ Fget (errname, Qerror_conditions));
+ }
+
+ /* Print an error message including the data items.
+ This is done by printing it into a scratch buffer
+ and then making a copy of the text in the buffer. */
+
+ if (!CONSP (data)) data = Qnil;
+ tail = Fcdr (data);
+ GCPRO1 (tail);
+
+ /* For file-error, make error message by concatenating
+ all the data items. They are all strings. */
+ if (!NULL (file_error))
+ errmsg = XCONS (tail)->car, tail = XCONS (tail)->cdr;
+
+ if (XTYPE (errmsg) == Lisp_String)
+ Fprinc (errmsg, Qt);
+ else
+ write_string_1 ("peculiar error", -1, Qt);
+
+ for (i = 0; CONSP (tail); tail = Fcdr (tail), i++)
+ {
+ write_string_1 (i ? ", " : ": ", 2, Qt);
+ if (!NULL (file_error))
+ Fprinc (Fcar (tail), Qt);
+ else
+ Fprin1 (Fcar (tail), Qt);
+ }
+ UNGCPRO;
+
+ /* In -batch mode, force out the error message and newlines after it
+ and then die. */
+ if (noninteractive)
+ {
+ message ("");
+ Fkill_emacs (make_number (-1));
+ }
+
+ Vquit_flag = Qnil;
+
+ Vinhibit_quit = Qnil;
+ return make_number (0);
+}
+
+Lisp_Object command_loop_1 ();
+Lisp_Object command_loop_2 ();
+Lisp_Object cmd_error ();
+Lisp_Object top_level_1 ();
+
+/* Entry to editor-command-loop.
+ This level has the catches for exiting/returning to editor command loop.
+ It returns nil to exit recursive edit, t to abort it. */
+
+Lisp_Object
+command_loop ()
+{
+ if (command_loop_level > 0 || minibuf_level > 0)
+ {
+ return internal_catch (Qexit, command_loop_2, Qnil);
+ }
+ else
+ while (1)
+ {
+ internal_catch (Qtop_level, top_level_1, Qnil);
+ internal_catch (Qtop_level, command_loop_2, Qnil);
+ /* End of file in -batch run causes exit here. */
+ if (noninteractive)
+ Fkill_emacs (Qt);
+ }
+}
+
+/* Here we catch errors in execution of commands within the
+ editing loop, and reenter the editing loop.
+ When there is an error, cmd_error runs and returns a non-nil
+ value to us. A value of nil means that cmd_loop_1 itself
+ returned due to end of file (or end of kbd macro). */
+
+Lisp_Object
+command_loop_2 ()
+{
+ register Lisp_Object val;
+ do
+ val = internal_condition_case (command_loop_1, Qerror, cmd_error);
+ while (!NULL (val));
+ return Qnil;
+}
+
+Lisp_Object
+top_level_2 ()
+{
+ return Feval (Vtop_level);
+}
+
+Lisp_Object
+top_level_1 ()
+{
+ /* On entry to the outer level, run the startup file */
+ if (!NULL (Vtop_level))
+ internal_condition_case (top_level_2, Qerror, cmd_error);
+ else if (!NULL (Vpurify_flag))
+ message ("Bare impure Emacs (standard Lisp code not loaded)");
+ else
+ message ("Bare Emacs (standard Lisp code not loaded)");
+ return Qnil;
+}
+
+DEFUN ("top-level", Ftop_level, Stop_level, 0, 0, "",
+ "Exit all recursive editing levels.")
+ ()
+{
+ Fthrow (Qtop_level, Qnil);
+}
+
+DEFUN ("exit-recursive-edit", Fexit_recursive_edit, Sexit_recursive_edit, 0, 0, "",
+ "Exit from the innermost recursive edit or minibuffer.")
+ ()
+{
+ if (command_loop_level > 0 || minibuf_level > 0)
+ Fthrow (Qexit, Qnil);
+ error ("No recursive edit is in progress");
+}
+
+DEFUN ("abort-recursive-edit", Fabort_recursive_edit, Sabort_recursive_edit, 0, 0, "",
+ "Abort the command that requested this recursive edit or minibuffer input.")
+ ()
+{
+ if (command_loop_level > 0 || minibuf_level > 0)
+ Fthrow (Qexit, Qt);
+ error ("No recursive edit is in progress");
+}
+
+/* This is the actual command reading loop,
+ sans error-handling encapsulation */
+
+Lisp_Object Fcommand_execute ();
+
+Lisp_Object
+command_loop_1 ()
+{
+ Lisp_Object cmd;
+ int lose;
+ int nonundocount;
+ char keybuf[30];
+ int i;
+ int no_redisplay;
+ int no_direct;
+
+ Vprefix_arg = Qnil;
+ waiting_for_input = 0;
+ cancel_echoing ();
+
+ /* Don't clear out last_command at the beginning of a macro. */
+ if (NULL (Vexecuting_macro)
+ || XTYPE (Vexecuting_macro) != Lisp_String)
+ last_command = Qt;
+ nonundocount = 0;
+ no_redisplay = 0;
+ this_command_key_count = 0;
+
+ while (1)
+ {
+ /* Install chars successfully executed in kbd macro */
+ if (defining_kbd_macro && NULL (Vprefix_arg))
+ finalize_kbd_macro_chars ();
+
+ /* Make sure current window's buffer is selected. */
+
+ if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
+ set_buffer_internal (XBUFFER (XWINDOW (selected_window)->buffer));
+
+ /* Display any malloc warning that just came out.
+ Use while because displaying one warning can cause another. */
+ while (pending_malloc_warning)
+ display_malloc_warning ();
+
+ no_direct = 0;
+
+ /* If minibuffer on and echo area in use,
+ wait 2 sec and redraw minibufer. */
+
+ if (minibuf_level && echo_area_contents)
+ {
+ int count = specpdl_ptr - specpdl;
+ specbind (Qinhibit_quit, Qt);
+ Fsit_for (make_number (2), Qnil);
+ unbind_to (count);
+
+ echo_area_contents = 0;
+ no_direct = 1;
+ if (!NULL (Vquit_flag))
+ {
+ Vquit_flag = Qnil;
+ unread_command_char = quit_char;
+ }
+ }
+
+ i = 0;
+#if 0
+ /* If prev. command was directly displayed, we don't need
+ redisplay. Try shortcut for reading single-char key sequence. */
+ if (no_redisplay)
+ i = fast_read_one_key (keybuf);
+#endif /* 0 */
+ /* Shortcut not applicable or found a prefix key.
+ Take full precautions and read key sequence the hard way. */
+ if (i == 0)
+ {
+#ifdef C_ALLOCA
+ alloca (0); /* Cause a garbage collection now */
+ /* Since we can free the most stuff here. */
+#endif /* C_ALLOCA */
+
+ /* Read next key sequence; i gets its length. */
+
+ i = read_key_sequence (keybuf, sizeof keybuf, 0,
+ no_redisplay && buffer_shared <= 1);
+ }
+
+ /* Now we have read a key sequence of length I,
+ or else I is 0 and we found end of file. */
+
+ if (i == 0) /* End of file -- happens only in */
+ return Qnil; /* a kbd macro, at the end */
+
+ last_command_char = keybuf[i - 1];
+
+ cmd = read_key_sequence_cmd;
+ if (!NULL (Vexecuting_macro))
+ {
+ if (!NULL (Vquit_flag))
+ {
+ Vexecuting_macro = Qt;
+ QUIT; /* Make some noise. */
+ /* Will return since macro now empty. */
+ }
+ }
+
+ /* Do redisplay processing after this command except in special
+ cases identified below that set no_redisplay to 1. */
+ no_redisplay = 0;
+
+ /* Execute the command. */
+
+ if (NULL (cmd))
+ {
+ /* nil means key is undefined. */
+ bell ();
+ defining_kbd_macro = 0;
+ update_mode_lines++;
+ Vprefix_arg = Qnil;
+ }
+ else
+ {
+ this_command = cmd;
+ if (NULL (Vprefix_arg) && ! no_direct)
+ {
+ if (EQ (cmd, Qforward_char) && point < ZV)
+ {
+ lose = FETCH_CHAR (point);
+ SET_PT (point + 1);
+ if (lose >= ' ' && lose < 0177
+ && (XFASTINT (XWINDOW (selected_window)->last_modified)
+ >= MODIFF)
+ && (XFASTINT (XWINDOW (selected_window)->last_point)
+ == point)
+ && !windows_or_buffers_changed
+ && EQ (current_buffer->selective_display, Qnil)
+ && !detect_input_pending ()
+ && NULL (Vexecuting_macro))
+ no_redisplay = direct_output_forward_char (1);
+ goto directly_done;
+ }
+ else if (EQ (cmd, Qbackward_char) && point > BEGV)
+ {
+ SET_PT (point - 1);
+ lose = FETCH_CHAR (point);
+ if (lose >= ' ' && lose < 0177
+ && (XFASTINT (XWINDOW (selected_window)->last_modified)
+ >= MODIFF)
+ && (XFASTINT (XWINDOW (selected_window)->last_point)
+ == point)
+ && !windows_or_buffers_changed
+ && EQ (current_buffer->selective_display, Qnil)
+ && !detect_input_pending ()
+ && NULL (Vexecuting_macro))
+ no_redisplay = direct_output_forward_char (-1);
+ goto directly_done;
+ }
+ else if (EQ (cmd, Qself_insert_command))
+ {
+ if (NULL (Vexecuting_macro) &&
+ !EQ (minibuf_window, selected_window))
+ {
+ if (!nonundocount || nonundocount >= 20)
+ {
+ Fundo_boundary ();
+ nonundocount = 0;
+ }
+ nonundocount++;
+ }
+ lose = (XFASTINT (XWINDOW (selected_window)->last_modified)
+ < MODIFF)
+ || (XFASTINT (XWINDOW (selected_window)->last_point)
+ != point)
+ || MODIFF <= current_buffer->save_modified
+ || windows_or_buffers_changed
+ || !EQ (current_buffer->selective_display, Qnil)
+ || detect_input_pending ()
+ || !NULL (Vexecuting_macro);
+ if (self_insert_internal (last_command_char, 0))
+ {
+ lose = 1;
+ nonundocount = 0;
+ }
+ if (!lose
+ && (point == ZV || FETCH_CHAR (point) == '\n')
+ && last_command_char >= ' '
+ && last_command_char < 0177)
+ no_redisplay
+ = direct_output_for_insert (last_command_char);
+ goto directly_done;
+ }
+ }
+
+ /* Here for a command that isn't executed directly */
+
+ nonundocount = 0;
+ if (NULL (Vprefix_arg))
+ Fundo_boundary ();
+ Fcommand_execute (cmd, Qnil);
+ }
+ /* This label logically belongs inside the above group,
+ but moving it is said to avoid a compiler bug on SCO V.3.2v2. */
+ directly_done: ;
+
+ if (NULL (Vprefix_arg))
+ {
+ last_command = this_command;
+ this_command_key_count = 0;
+ cancel_echoing ();
+ }
+ }
+}
+
+/* Input of single characters from keyboard */
+
+Lisp_Object print_help ();
+
+int echo_flag;
+int echo_now;
+
+/* Alarm interrupt calls this and requests echoing at earliest safe time. */
+request_echo ()
+{
+ int old_errno = errno;
+
+ /* Note: no need to reestablish handler on USG systems
+ because it is established, if approriate, each time an alarm is requested. */
+#ifdef subprocesses
+#ifdef BSD4_1
+ extern int select_alarmed;
+ if (select_alarmed == 0)
+ {
+ select_alarmed = 1;
+ sigrelse (SIGALRM);
+ return;
+ }
+#endif
+#endif
+
+#ifdef BSD4_1
+ sigisheld (SIGALRM);
+#endif
+
+ if (echo_now)
+ echo ();
+ else
+ echo_flag = 1;
+
+#ifdef BSD4_1
+ sigunhold (SIGALRM);
+#endif
+
+ errno = old_errno;
+}
+
+/* Nonzero means polling for input is temporarily suppresed. */
+int poll_suppress_count;
+
+/* Number of seconds between polling for input. */
+int polling_period;
+
+#ifdef POLL_FOR_INPUT
+int polling_for_input;
+
+/* Handle an alarm once each second and read pending input
+ so as to handle a C-g if it comces in. */
+
+input_poll_signal ()
+{
+ int junk;
+
+ if (!waiting_for_input)
+ read_avail_input (&junk);
+ signal (SIGALRM, input_poll_signal);
+ alarm (polling_period);
+}
+
+#endif
+
+/* Begin signals to poll for input, if they are appropriate.
+ This function is called unconditionally from various places. */
+
+start_polling ()
+{
+#ifdef POLL_FOR_INPUT
+ if (read_socket_hook)
+ {
+ poll_suppress_count--;
+ if (poll_suppress_count == 0)
+ {
+ signal (SIGALRM, input_poll_signal);
+ polling_for_input = 1;
+ alarm (polling_period);
+ }
+ }
+#endif
+}
+
+/* Turn off polling. */
+
+stop_polling ()
+{
+#ifdef POLL_FOR_INPUT
+ if (read_socket_hook)
+ {
+ if (poll_suppress_count == 0)
+ {
+ polling_for_input = 0;
+ alarm (0);
+ }
+ poll_suppress_count++;
+ }
+#endif
+}
+
+/* read a character from the keyboard; call the redisplay if needed */
+/* commandflag 0 means do not do auto-saving, but do do redisplay.
+ -1 means do not do redisplay, but do do autosaving.
+ 1 means do both. */
+
+read_command_char (commandflag)
+ int commandflag;
+{
+ register int c;
+ int alarmtime;
+ int count;
+ Lisp_Object tem;
+ jmp_buf save_jump;
+ extern request_echo ();
+
+ if (unread_command_char >= 0)
+ {
+ c = unread_command_char;
+ unread_command_char = -1;
+ if (this_command_key_count == 0)
+ goto reread_first;
+ goto reread;
+ }
+
+ if (!NULL (Vexecuting_macro))
+ {
+ if (XTYPE (Vexecuting_macro) != Lisp_String
+ || XSTRING (Vexecuting_macro)->size <= executing_macro_index)
+ return -1;
+ QUIT;
+ c = XSTRING (Vexecuting_macro)->data[executing_macro_index++];
+ goto from_macro;
+ }
+
+ /* Save outer setjmp data, in case called recursively. */
+ bcopy (getcjmp, save_jump, sizeof getcjmp);
+
+ stop_polling ();
+
+ if (commandflag >= 0 && !detect_input_pending ())
+ redisplay ();
+
+ if (commandflag != 0
+ && auto_save_interval > 0
+ && num_input_chars - last_auto_save > max (auto_save_interval, 20)
+ && !detect_input_pending ())
+ Fdo_auto_save (Qnil);
+
+ if (_setjmp (getcjmp))
+ {
+ c = quit_char;
+ waiting_for_input = 0;
+ input_available_clear_word = 0;
+
+ goto non_reread;
+ }
+
+ /* Message turns off echoing unless more keystrokes turn it on again. */
+ if (echo_area_contents && *echo_area_contents && echo_area_contents != echobuf)
+ cancel_echoing ();
+ else
+ /* If already echoing, continue, and prompt. */
+ echo_dash ();
+
+ /* If in middle of key sequence and minibuffer not active,
+ start echoing if enough time elapses. */
+ if (minibuf_level == 0 && !immediate_echo && this_command_key_count > 0
+ && echo_keystrokes > 0
+ && (echo_area_contents == 0 || *echo_area_contents == 0))
+ {
+ /* Else start echoing if user waits more than `alarmtime' seconds. */
+ /* This interrupt either calls echo right away
+ or sets echo_flag, which causes echo to be called
+ by set_waiting_for_input's next invocation. */
+ signal (SIGALRM, request_echo);
+ echo_flag = 0;
+ echo_now = 0;
+ alarmtime = echo_keystrokes;
+ alarm ((unsigned) alarmtime);
+ }
+
+ c = kbd_buffer_read_command_char ();
+
+ /* Terminate Emacs in batch mode if at eof. */
+ if (noninteractive && c < 0)
+ Fkill_emacs (make_number (1));
+
+ non_reread:
+
+ bcopy (save_jump, getcjmp, sizeof getcjmp);
+
+ /* Cancel alarm if it was set and has not already gone off. */
+ if (alarmtime > 0) alarm (0);
+
+ echo_area_contents = 0;
+
+ if (c < 0) return -1;
+
+ c &= meta_key ? 0377 : 0177;
+
+ if (XTYPE (Vkeyboard_translate_table) == Lisp_String
+ && XSTRING (Vkeyboard_translate_table)->size > c)
+ c = XSTRING (Vkeyboard_translate_table)->data[c];
+
+ total_keys++;
+ recent_keys[recent_keys_index] = c;
+ recent_keys_index = (recent_keys_index + 1) % sizeof recent_keys;
+
+ if (dribble)
+ {
+ putc (c, dribble);
+ fflush (dribble);
+ }
+
+ store_kbd_macro_char (c);
+
+ start_polling ();
+
+ from_macro:
+ reread_first: /* Rereading a char and it is the first in a command. */
+
+ echo_char (c);
+
+ /* Record this character as part of the current key. */
+ if (this_command_key_count == this_command_keys_size)
+ {
+ this_command_keys_size *= 2;
+ this_command_keys
+ = (unsigned char *) xrealloc (this_command_keys,
+ this_command_keys_size);
+ }
+ this_command_keys[this_command_key_count++] = c;
+
+ /* Rereading in the middle of a command. */
+ reread:
+
+ last_input_char = c;
+
+ num_input_chars++;
+
+ /* Process the help character specially if enabled */
+ if (c == help_char && !NULL (Vhelp_form))
+ {
+ count = specpdl_ptr - specpdl;
+
+ record_unwind_protect (Fset_window_configuration,
+ Fcurrent_window_configuration ());
+
+ tem = Feval (Vhelp_form);
+ if (XTYPE (tem) == Lisp_String)
+ internal_with_output_to_temp_buffer ("*Help*", print_help, tem);
+
+ cancel_echoing ();
+ c = read_command_char (0);
+ /* Remove the help from the screen */
+ unbind_to (count);
+ redisplay ();
+ if (c == 040)
+ {
+ cancel_echoing ();
+ c = read_command_char (0);
+ }
+ }
+
+ return c;
+}
+
+Lisp_Object
+print_help (object)
+ Lisp_Object object;
+{
+ Fprinc (object, Qnil);
+ return Qnil;
+}
+
+/* Low level keyboard input.
+ Read characters into kbd_buffer
+ from which they are obtained by kbd_buffer_read_command_char. */
+
+/* Set this for debugging, to have a way to get out */
+int stop_character;
+
+/* Store a character obtained at interrupt level into kbd_buffer, fifo */
+kbd_buffer_store_char (c)
+ register int c;
+{
+ c &= 0377;
+
+ if (c == quit_char
+ || ((c == (0200 | quit_char)) && !meta_key))
+ {
+ interrupt_signal ();
+ return;
+ }
+
+ if (c && c == stop_character)
+ {
+ sys_suspend ();
+ return;
+ }
+
+ if (kbd_ptr != kbd_buffer)
+ {
+ bcopy (kbd_ptr, kbd_buffer, kbd_count);
+ kbd_ptr = kbd_buffer;
+ }
+
+ if (kbd_count < sizeof kbd_buffer)
+ {
+ kbd_buffer[kbd_count++] = c;
+ }
+}
+
+kbd_buffer_read_command_char ()
+{
+ register int c;
+
+ if (noninteractive)
+ {
+ c = getchar ();
+ return c;
+ }
+
+ /* Either ordinary input buffer or C-g buffered means we can return. */
+ while (!kbd_count)
+ {
+ if (!NULL (Vquit_flag))
+ quit_throw_to_read_command_char ();
+
+ /* One way or another, wait until input is available; then, if
+ interrupt handlers have not read it, read it now. */
+
+#ifdef VMS
+ wait_for_kbd_input ();
+#else
+/* Note SIGIO has been undef'd if FIONREAD is missing. */
+#ifdef SIGIO
+ gobble_input ();
+#endif /* SIGIO */
+ if (!kbd_count)
+ {
+#ifdef subprocesses
+ wait_reading_process_input (0, -1, 1);
+#else
+/* Note SIGIO has been undef'd if FIONREAD is missing. */
+#ifdef SIGIO
+ if (interrupt_input)
+ {
+ sigblockx (SIGIO);
+ set_waiting_for_input (0);
+ while (!kbd_count)
+ sigpausex (SIGIO);
+ clear_waiting_for_input ();
+ sigunblockx (SIGIO);
+ }
+#else
+ interrupt_input = 0;
+#endif /* not SIGIO */
+#endif /* subprocesses */
+
+ if (!interrupt_input && !kbd_count)
+ {
+ read_avail_input (0);
+ }
+ }
+#endif /* not VMS */
+ }
+
+ input_pending = --kbd_count > 0;
+ c = *kbd_ptr; /* *kbd_ptr++ would have a timing error. */
+ kbd_ptr++; /* See kbd_buffer_store_char. */
+ return (c & (meta_key ? 0377 : 0177)); /* Clean up if sign was extended. */
+}
+
+/* Force an attempt to read input regardless of what FIONREAD says. */
+
+force_input_read ()
+{
+ force_input = 1;
+ detect_input_pending ();
+ force_input = 0;
+}
+
+/* Store into *addr the number of terminal input chars available.
+ Equivalent to ioctl (0, FIONREAD, addr) but works
+ even if FIONREAD does not exist. */
+
+static void
+get_input_pending (addr)
+ int *addr;
+{
+#ifdef VMS
+ /* On VMS, we always have something in the buffer
+ if any input is available. */
+ /*** It might be simpler to make interrupt_input 1 on VMS ***/
+ *addr = kbd_count | !NULL (Vquit_flag);
+#else
+ /* First of all, have we already counted some input? */
+ *addr = kbd_count | !NULL (Vquit_flag);
+ /* If input is being read as it arrives, and we have none, there is none. */
+ if (*addr > 0 || (interrupt_input && ! interrupts_deferred && ! force_input))
+ return;
+#ifdef FIONREAD
+ if (! force_input)
+ {
+ /* If we can count the input without reading it, do so. */
+ if (ioctl (0, FIONREAD, addr) < 0)
+ *addr = 0;
+ if (*addr == 0 || read_socket_hook == 0)
+ return;
+ /* If the input consists of window-events, not all of them
+ are necessarily kbd chars. So process all the input
+ and see how many kbd chars we got. */
+ }
+#endif
+#ifdef SIGIO
+ {
+ /* It seems there is a timing error such that a SIGIO can be handled here
+ and cause kbd_count to become nonzero even though raising of SIGIO
+ has already been turned off. */
+ SIGMASKTYPE mask = sigblock (sigmask (SIGIO));
+ if (kbd_count == 0)
+ read_avail_input (*addr);
+ sigsetmask (mask);
+ }
+#else
+ /* If we can't count the input, read it (if any) and see what we got. */
+ read_avail_input (*addr);
+#endif
+ *addr = kbd_count | !NULL (Vquit_flag);
+#endif
+}
+
+/* Read pending any input out of the system and into Emacs. */
+
+/* This function is temporary in Emacs 18. It is used only
+ with X windows. X windows always turns on interrupt input
+ if possible, so this function has nothing to do except
+ on systems that don't have SIGIO. And they also don't have FIONREAD. */
+void
+consume_available_input ()
+{
+#ifdef SIGIO
+ if (!interrupt_input || interrupts_deferred)
+#endif
+ read_avail_input (0);
+}
+
+/* Read any terminal input already buffered up by the system
+ into the kbd_buffer, assuming the buffer is currently empty.
+ Never waits.
+
+ If NREAD is nonzero, assume it contains # chars of raw data waiting.
+ If it is zero, we determine that datum.
+
+ Input gets into the kbd_buffer either through this function
+ (at main program level) or at interrupt level if input
+ is interrupt-driven. */
+
+static void
+read_avail_input (nread)
+ int nread;
+{
+ /* This function is not used on VMS. */
+#ifndef VMS
+ char buf[256 * BUFFER_SIZE_FACTOR];
+ register int i;
+
+#ifdef FIONREAD
+ if (! force_input)
+ {
+ if (nread == 0)
+ get_input_pending (&nread);
+ if (nread == 0)
+ return;
+ }
+ if (nread > sizeof buf)
+ nread = sizeof buf;
+
+ /* Read what is waiting. */
+ if (read_socket_hook)
+ nread = (*read_socket_hook) (0, buf, nread);
+ else
+ nread = read (0, buf, nread);
+
+#else /* no FIONREAD */
+#ifdef USG
+#ifdef SYSV_STREAMS
+ /* When talking to Xwindows using streams, something gets screwed up
+ if Emacs alters this flag in the descriptor. */
+ if (!read_socket_hook)
+#endif
+ fcntl (fileno (stdin), F_SETFL, O_NDELAY);
+ if (read_socket_hook)
+ {
+ nread = (*read_socket_hook) (0, buf, sizeof buf);
+ }
+ else
+ {
+ nread = read (fileno (stdin), buf, sizeof buf);
+ }
+#ifdef AIX
+ /* The kernel sometimes fails to deliver SIGHUP for ptys.
+ This looks incorrect, but it isn't, because _BSD causes
+ O_NDELAY to be defined in fcntl.h as O_NONBLOCK,
+ and that causes a value other than 0 when there is no input. */
+ if (nread == 0)
+ kill (SIGHUP, 0);
+#endif
+#ifdef EBADSLT
+ if (nread == -1 && (errno == EAGAIN || errno == EBADSLT))
+#else
+ if (nread == -1 && errno == EAGAIN)
+#endif
+ nread = 0;
+#ifdef SYSV_STREAMS
+ if (!read_socket_hook)
+#endif
+ fcntl (fileno (stdin), F_SETFL, 0);
+#else /* not USG */
+ you lose
+#endif /* not USG */
+#endif /* no FIONREAD */
+
+ /* Scan the chars for C-g and store them in kbd_buffer. */
+ if (kbd_count == 0)
+ kbd_ptr = kbd_buffer;
+
+ for (i = 0; i < nread; i++)
+ {
+ kbd_buffer_store_char (buf[i]);
+ /* Don't look at input that follows a C-g too closely.
+ This reduces lossage due to autorepeat on C-g. */
+ if (buf[i] == quit_char)
+ break;
+ }
+#endif /* not VMS */
+}
+
+#ifdef SIGIO /* for entire page */
+/* Note SIGIO has been undef'd if FIONREAD is missing. */
+
+/* If using interrupt input and some input chars snuck into the
+ buffer before we enabled interrupts, fake an interrupt for them. */
+
+gobble_input ()
+{
+ int nread;
+ if (interrupt_input)
+ {
+ if (ioctl (0, FIONREAD, &nread) < 0)
+ nread = 0;
+ if (nread)
+ {
+ sigholdx (SIGIO);
+ input_available_signal (SIGIO);
+ sigfree ();
+ }
+ }
+}
+
+input_available_signal (signo)
+ int signo;
+{
+ unsigned char buf[256 * BUFFER_SIZE_FACTOR];
+ int nread;
+ register int i;
+ /* Must preserve main program's value of errno. */
+ int old_errno = errno;
+#ifdef BSD4_1
+ extern int select_alarmed;
+#endif
+
+#ifdef USG
+ /* USG systems forget handlers when they are used;
+ must reestablish each time */
+ signal (signo, input_available_signal);
+#endif /* USG */
+
+#ifdef BSD4_1
+ sigisheld (SIGIO);
+#endif
+
+ if (input_available_clear_word)
+ *input_available_clear_word = 0;
+
+ while (1)
+ {
+ if (ioctl (0, FIONREAD, &nread) < 0)
+ /* Formerly simply exited the loop, but that sometimes led to
+ a failure of Emacs to terminate.
+ SIGHUP seems appropriate if we can't reach the terminal. */
+ kill (getpid (), SIGHUP);
+ if (nread <= 0)
+ break;
+#ifdef BSD4_1
+ select_alarmed = 1; /* Force the select emulator back to life */
+#endif
+ if (read_socket_hook)
+ {
+ nread = (*read_socket_hook) (0, buf, sizeof buf);
+ if (!nread)
+ continue;
+ }
+ else
+ {
+ if (nread > sizeof buf)
+ nread = sizeof buf;
+ nread = read (0, buf, nread);
+ }
+
+ for (i = 0; i < nread; i++)
+ {
+ kbd_buffer_store_char (buf[i]);
+ /* Don't look at input that follows a C-g too closely.
+ This reduces lossage due to autorepeat on C-g. */
+ if (buf[i] == quit_char)
+ break;
+ }
+ }
+#ifdef BSD4_1
+ sigfree ();
+#endif
+ errno = old_errno;
+}
+#endif /* SIGIO */
+
+#if 0
+/* This is turned off because it didn't produce much speedup. */
+
+/* Read a single-char key sequence. Do not redisplay.
+ Return 1 if successful, or 0 if what follows is not
+ a single-char key. (In that case, a char has been unread.)
+ This is used instead of read_key_sequence as an optimization
+ just after a direct-updating command is done, since at such
+ times we know that no redisplay is required. */
+
+int
+fast_read_one_key (keybuf)
+ char *keybuf;
+{
+ register Lisp_Object map;
+ register int c;
+ register Lisp_Object tem;
+
+ keys_prompt = 0;
+ /* Read a character, and do not redisplay. */
+ c = read_command_char (-1);
+ Vquit_flag = Qnil;
+
+ /* Assume until further notice that we are unlucky
+ and will return zero, so this char will be
+ reread by read_key_sequence. */
+
+ unread_command_char = c;
+
+ if (c < 0 || c >= 0200)
+ return 0;
+
+ map = current_buffer->keymap;
+ if (!EQ (map, Qnil))
+ {
+ tem = get_keyelt (access_keymap (map, c));
+ if (!EQ (tem, Qnil))
+ return 0;
+ }
+
+ XSET (map, Lisp_Vector, global_map);
+ tem = !NULL (map)
+ ? get_keyelt (access_keymap (map, c))
+ : Qnil;
+
+ read_key_sequence_cmd = tem;
+
+ /* trace symbols to their function definitions */
+
+ while (XTYPE (tem) == Lisp_Symbol && !NULL (tem)
+ && !EQ (tem, Qunbound))
+ tem = XSYMBOL (tem)->function;
+
+ /* Is the definition a prefix character? */
+
+ if (XTYPE (tem) == Lisp_Vector ||
+ (CONSP (tem) && EQ (XCONS (tem)->car, Qkeymap)))
+ return 0;
+
+ unread_command_char = -1;
+ keybuf[0] = c;
+ return 1;
+}
+
+#endif /* 0 */
+
+/* Read a sequence of keys that ends with a non prefix character,
+ and store them in KEYBUF, a buffer of size BUFSIZE.
+ Prompt with PROMPT. Echo starting immediately unless `prompt' is 0.
+ Return the length of the key sequence stored.
+ NODISPLAY nonzero means don't do redisplay before the first character
+ (just for speedup). */
+
+int
+read_key_sequence (keybuf, bufsize, prompt, nodisplay)
+ char *keybuf;
+ int bufsize;
+ unsigned char *prompt;
+ int nodisplay;
+{
+ register int i;
+ Lisp_Object nextlocal, nextglobal;
+ register int c, nextc;
+ Lisp_Object local, global;
+
+ if (FROM_KBD)
+ {
+ if (prompt)
+ echo_prompt (prompt);
+ else if (cursor_in_echo_area)
+ echo_dash ();
+ }
+
+ nextc = read_command_char (nodisplay ? -1 : !prompt);
+ nextlocal = current_buffer->keymap;
+ XSET (nextglobal, Lisp_Vector, global_map);
+
+ i = 0;
+ while (!NULL (nextlocal) || !NULL (nextglobal))
+ {
+ if (i == bufsize)
+ error ("key sequence too long");
+
+ if (nextc >= 0)
+ {
+ c = nextc;
+ nextc = -1;
+ }
+ else
+ c = read_command_char (!prompt);
+ Vquit_flag = Qnil;
+ nodisplay = 0;
+
+ if (c < 0)
+ return 0;
+ if (c >= 0200)
+ {
+ nextc = c & 0177;
+ c = meta_prefix_char;
+ }
+
+ keybuf[i] = c;
+
+ global = !NULL (nextglobal)
+ ? get_keyelt (access_keymap (nextglobal, c))
+ : Qnil;
+
+ local = !NULL (nextlocal)
+ ? get_keyelt (access_keymap (nextlocal, c))
+ : Qnil;
+
+ /* If C is not defined in either keymap
+ and it is an uppercase letter, try corresponding lowercase. */
+
+ if (NULL (global) && NULL (local) && UPPERCASEP (c))
+ {
+ global = !NULL (nextglobal)
+ ? get_keyelt (access_keymap (nextglobal, DOWNCASE (c)))
+ : Qnil;
+
+ local = !NULL (nextlocal)
+ ? get_keyelt (access_keymap (nextlocal, DOWNCASE (c)))
+ : Qnil;
+
+ /* If that has worked better that the original char,
+ downcase it permanently. */
+
+ if (!NULL (global) || !NULL (local))
+ {
+ keybuf[i] = c = DOWNCASE (c);
+ }
+ }
+
+ i++;
+
+ nextlocal = Qnil;
+ nextglobal = Qnil;
+
+ read_key_sequence_cmd = !NULL (local) ? local : global;
+
+ /* trace symbols to their function definitions */
+
+ while (XTYPE (global) == Lisp_Symbol && !NULL (global)
+ && !EQ (global, Qunbound))
+ global = XSYMBOL (global)->function;
+ while (XTYPE (local) == Lisp_Symbol && !NULL (local)
+ && !EQ (local, Qunbound))
+ local = XSYMBOL (local)->function;
+
+ /* Are the definitions prefix characters? */
+
+ if (XTYPE (local) == Lisp_Vector ||
+ (CONSP (local) && EQ (XCONS (local)->car, Qkeymap))
+ ||
+ /* If nextc is set, we are processing a prefix char
+ that represents a meta-bit.
+ Let a global prefix definition override a local non-prefix.
+ This is for minibuffers that redefine Escape for completion.
+ A real Escape gets completion, but Meta bits get ESC-prefix. */
+ ((NULL (local) || nextc >= 0)
+ && (XTYPE (global) == Lisp_Vector ||
+ (CONSP (global) && EQ (XCONS (global)->car, Qkeymap)))))
+ {
+ if (XTYPE (local) == Lisp_Vector ||
+ (CONSP (local) && EQ (XCONS (local)->car, Qkeymap)))
+ nextlocal = local;
+ else
+ nextlocal = Qnil;
+
+ if (XTYPE (global) == Lisp_Vector ||
+ (CONSP (global) && EQ (XCONS (global)->car, Qkeymap)))
+ nextglobal = global;
+ else
+ nextglobal = Qnil;
+ }
+ }
+
+ return i;
+}
+
+DEFUN ("read-key-sequence", Fread_key_sequence, Sread_key_sequence, 1, 1, 0,
+ "Read a sequence of keystrokes and return as a string.\n\
+The sequence is sufficient to specify a non-prefix command\n\
+starting from the current local and global keymaps.\n\
+A C-g typed while in this function is treated like\n\
+any other character, and quit-flag is not set.\n\
+One arg, PROMPT, a prompt string or nil, meaning do not prompt specially.")
+ (prompt)
+ Lisp_Object prompt;
+{
+ char keybuf[30];
+ register int i;
+
+ if (!NULL (prompt))
+ CHECK_STRING (prompt, 0);
+ QUIT;
+
+ this_command_key_count = 0;
+ i = read_key_sequence (keybuf, sizeof keybuf,
+ (NULL (prompt)) ? 0 : XSTRING (prompt)->data,
+ 0);
+ return make_string (keybuf, i);
+}
+
+DEFUN ("command-execute", Fcommand_execute, Scommand_execute, 1, 2, 0,
+ "Execute CMD as an editor command.\n\
+CMD must be a symbol that satisfies the `commandp' predicate.\n\
+Optional second arg RECORD-FLAG non-nil\n\
+means unconditionally put this command in the command-history.\n\
+Otherwise, this is done only if an arg is read using the minibuffer.")
+ (cmd, record)
+ Lisp_Object cmd, record;
+{
+ register Lisp_Object final;
+ register Lisp_Object tem;
+ Lisp_Object prefixarg;
+ struct backtrace backtrace;
+ extern int debug_on_next_call;
+
+ prefixarg = Vprefix_arg, Vprefix_arg = Qnil;
+ Vcurrent_prefix_arg = prefixarg;
+ debug_on_next_call = 0;
+
+ if (XTYPE (cmd) == Lisp_Symbol)
+ {
+ tem = Fget (cmd, Qdisabled);
+ if (!NULL (tem))
+ return call0 (Vdisabled_command_hook);
+ }
+
+ while (1)
+ {
+ final = cmd;
+ while (XTYPE (final) == Lisp_Symbol)
+ {
+ if (EQ (Qunbound, XSYMBOL (final)->function))
+ Fsymbol_function (final); /* Get an error! */
+ final = XSYMBOL (final)->function;
+ }
+
+ if (CONSP (final) && (tem = Fcar (final), EQ (tem, Qautoload)))
+ do_autoload (final, cmd);
+ else
+ break;
+ }
+
+ if (CONSP (final) || XTYPE (final) == Lisp_Subr)
+ {
+ backtrace.next = backtrace_list;
+ backtrace_list = &backtrace;
+ backtrace.function = &Qcall_interactively;
+ backtrace.args = &cmd;
+ backtrace.nargs = 1;
+ backtrace.evalargs = 0;
+
+ tem = Fcall_interactively (cmd, record);
+
+ backtrace_list = backtrace.next;
+ return tem;
+ }
+ if (XTYPE (final) == Lisp_String)
+ {
+ return Fexecute_kbd_macro (final, prefixarg);
+ }
+ return Qnil;
+}
+
+DEFUN ("execute-extended-command", Fexecute_extended_command, Sexecute_extended_command,
+ 1, 1, "P",
+ "Read function name, then read its arguments and call it.")
+ (prefixarg)
+ Lisp_Object prefixarg;
+{
+ Lisp_Object function;
+ char buf[40];
+ Lisp_Object saved_keys;
+ struct gcpro gcpro1;
+
+ saved_keys = Fthis_command_keys ();
+ GCPRO1 (saved_keys);
+
+ buf[0] = 0;
+
+ if (EQ (prefixarg, Qminus))
+ strcpy (buf, "- ");
+ else if (CONSP (prefixarg) && XINT (XCONS (prefixarg)->car) == 4)
+ strcpy (buf, "C-u ");
+ else if (CONSP (prefixarg) && XTYPE (XCONS (prefixarg)->car) == Lisp_Int)
+ sprintf (buf, "%d ", XINT (XCONS (prefixarg)->car));
+ else if (XTYPE (prefixarg) == Lisp_Int)
+ sprintf (buf, "%d ", XINT (prefixarg));
+
+ /* This isn't strictly correct if execute-extended-command
+ is bound to anything else */
+ strcat (buf, "M-x ");
+
+ function = Fcompleting_read (build_string (buf), Vobarray, Qcommandp, Qt, Qnil);
+
+ saved_keys = concat2 (saved_keys, function);
+ if (this_command_keys_size < XSTRING (saved_keys)->size)
+ {
+ /* This makes the buffer bigger than necessary, but that's okay. */
+ this_command_keys_size += XSTRING (saved_keys)->size;
+ this_command_keys = (unsigned char *) xrealloc (this_command_keys,
+ this_command_keys_size);
+ }
+ bcopy (XSTRING (saved_keys)->data, this_command_keys,
+ XSTRING (saved_keys)->size + 1);
+ this_command_key_count = XSTRING (saved_keys)->size;
+
+ UNGCPRO;
+
+ function = Fintern (function, Vobarray);
+ Vprefix_arg = prefixarg;
+ this_command = function;
+
+ return Fcommand_execute (function, Qt);
+}
+
+detect_input_pending ()
+{
+ if (!input_pending)
+ get_input_pending (&input_pending);
+
+ return input_pending;
+}
+
+/* This is called in some cases before a possible quit.
+ It cases the next call to detect_input_pending to recompute input_pending.
+ So calling this function unnecessarily can't do any harm. */
+clear_input_pending ()
+{
+ input_pending = 0;
+}
+
+DEFUN ("input-pending-p", Finput_pending_p, Sinput_pending_p, 0, 0, 0,
+ "T if command input is currently available with no waiting.\n\
+Actually, the value is NIL only if we can be sure that no input is available.")
+ ()
+{
+ if (unread_command_char >= 0) return Qt;
+
+ return detect_input_pending () ? Qt : Qnil;
+}
+
+DEFUN ("recent-keys", Frecent_keys, Srecent_keys, 0, 0, 0,
+ "Return string of last 100 chars read from terminal.")
+ ()
+{
+ Lisp_Object val;
+ if (total_keys < sizeof recent_keys)
+ return make_string (recent_keys, total_keys);
+
+ val = make_string (recent_keys, sizeof recent_keys);
+ bcopy (recent_keys + recent_keys_index,
+ XSTRING (val)->data,
+ sizeof recent_keys - recent_keys_index);
+ bcopy (recent_keys,
+ XSTRING (val)->data + sizeof recent_keys - recent_keys_index,
+ recent_keys_index);
+ return val;
+}
+
+DEFUN ("this-command-keys", Fthis_command_keys, Sthis_command_keys, 0, 0, 0,
+ "Return string of the keystrokes that invoked this command.")
+ ()
+{
+ return make_string (this_command_keys, this_command_key_count);
+}
+
+DEFUN ("recursion-depth", Frecursion_depth, Srecursion_depth, 0, 0, 0,
+ "Return the current depth in recursive edits.")
+ ()
+{
+ Lisp_Object temp;
+ XFASTINT (temp) = command_loop_level + minibuf_level;
+ return temp;
+}
+
+DEFUN ("open-dribble-file", Fopen_dribble_file, Sopen_dribble_file, 1, 1,
+ "FOpen dribble file: ",
+ "Start writing all keyboard characters to FILE.\n\
+Use nil as an argument to close the dribble file.")
+ (file)
+ Lisp_Object file;
+{
+ if (dribble != 0)
+ fclose (dribble);
+ dribble = 0;
+ if (!NULL (file))
+ {
+ file = Fexpand_file_name (file, Qnil);
+ dribble = fopen (XSTRING (file)->data, "w");
+ }
+ return Qnil;
+}
+
+DEFUN ("discard-input", Fdiscard_input, Sdiscard_input, 0, 0, 0,
+ "Discard the contents of the terminal input buffer.\n\
+Also flush any kbd macro definition in progress.")
+ ()
+{
+ defining_kbd_macro = 0;
+ update_mode_lines++;
+
+ unread_command_char = -1;
+ Vquit_flag = Qnil;
+ discard_tty_input ();
+
+ kbd_count = 0;
+ input_pending = 0;
+
+ return Qnil;
+}
+
+DEFUN ("suspend-emacs", Fsuspend_emacs, Ssuspend_emacs, 0, 1, "",
+ "Stop Emacs and return to superior process. You can resume.\n\
+If optional arg STUFFSTRING is non-nil, its characters are stuffed\n\
+to be read as terminal input by Emacs's superior shell.\n\
+Before suspending, if `suspend-hook' is bound and value is non-nil\n\
+call the value as a function of no args. Don't suspend if it returns non-nil.\n\
+Otherwise, suspend normally and after resumption call\n\
+`suspend-resume-hook' if that is bound and non-nil.")
+ (stuffstring)
+ Lisp_Object stuffstring;
+{
+ register Lisp_Object tem;
+ int count = specpdl_ptr - specpdl;
+ int old_height, old_width;
+ int width, height;
+ struct gcpro gcpro1;
+ extern init_sys_modes ();
+
+ if (!NULL (stuffstring))
+ CHECK_STRING (stuffstring, 0);
+ GCPRO1 (stuffstring);
+
+ /* Call value of suspend-hook
+ if it is bound and value is non-nil. */
+ tem = intern ("suspend-hook");
+ tem = XSYMBOL (tem)->value;
+ if (! EQ (tem, Qunbound) && ! EQ (tem, Qnil))
+ {
+ tem = call0 (tem);
+ if (!EQ (tem, Qnil)) return Qnil;
+ }
+
+ get_screen_size (&old_width, &old_height);
+ reset_sys_modes ();
+ /* sys_suspend can get an error if it tries to fork a subshell
+ and the system resources aren't available for that. */
+ record_unwind_protect (init_sys_modes, 0);
+ stuff_buffered_input (stuffstring);
+ sys_suspend ();
+ unbind_to (count);
+
+ /* Check if terminal/window size has changed.
+ Note that this is not useful when we are running directly
+ with a window system; but suspend should be disabled in that case. */
+ get_screen_size (&width, &height);
+ if (width != old_width || height != old_height)
+ change_screen_size (height, width, 0, 0, 0);
+
+ /* Call value of suspend-resume-hook
+ if it is bound and value is non-nil. */
+ tem = intern ("suspend-resume-hook");
+ tem = XSYMBOL (tem)->value;
+ if (! EQ (tem, Qunbound) && ! EQ (tem, Qnil))
+ call0 (tem);
+ UNGCPRO;
+ return Qnil;
+}
+
+/* If STUFFSTRING is a string, stuff its contents as pending terminal input.
+ Then in any case stuff anthing Emacs has read ahead and not used. */
+
+stuff_buffered_input (stuffstring)
+ Lisp_Object stuffstring;
+{
+ register unsigned char *p;
+
+/* stuff_char works only in BSD, versions 4.2 and up. */
+#ifdef BSD
+#ifndef BSD4_1
+ if (XTYPE (stuffstring) == Lisp_String)
+ {
+ register int count;
+
+ p = XSTRING (stuffstring)->data;
+ count = XSTRING (stuffstring)->size;
+ while (count-- > 0)
+ stuff_char (*p++);
+ stuff_char ('\n');
+ }
+ /* Anything we have read ahead, put back for the shell to read. */
+ while (kbd_count)
+ {
+ stuff_char (*kbd_ptr++);
+ kbd_count--;
+ }
+ input_pending = 0;
+#endif
+#endif /* BSD and not BSD4_1 */
+}
+
+set_waiting_for_input (word_to_clear)
+ long *word_to_clear;
+{
+ input_available_clear_word = word_to_clear;
+
+ /* Tell interrupt_signal to throw back to read_command_char, */
+ waiting_for_input = 1;
+
+ /* If interrupt_signal was called before and buffered a C-g,
+ make it run again now, to avoid timing error. */
+ if (!NULL (Vquit_flag))
+ quit_throw_to_read_command_char ();
+
+ /* Tell alarm signal to echo right away */
+ echo_now = 1;
+
+ /* If alarm has gone off already, echo now. */
+ if (echo_flag)
+ {
+ echo ();
+ echo_flag = 0;
+ }
+}
+
+clear_waiting_for_input ()
+{
+ /* Tell interrupt_signal not to throw back to read_command_char, */
+ waiting_for_input = 0;
+ echo_now = 0;
+ input_available_clear_word = 0;
+}
+
+/* This routine is called at interrupt level in response to C-G.
+ If interrupt_input, this is the handler for SIGINT.
+ Otherwise, it is called from kbd_buffer_store_char,
+ in handling SIGIO or SIGTINT.
+
+ If `waiting_for_input' is non zero, then unless `echoing' is nonzero,
+ immediately throw back to read_command_char.
+
+ Otherwise it sets the Lisp variable quit-flag not-nil.
+ This causes eval to throw, when it gets a chance.
+ If quit-flag is already non-nil, it stops the job right away. */
+
+interrupt_signal ()
+{
+ char c;
+ /* Must preserve main program's value of errno. */
+ int old_errno = errno;
+ extern Lisp_Object Vwindow_system;
+
+#ifdef USG
+ /* USG systems forget handlers when they are used;
+ must reestablish each time */
+ signal (SIGINT, interrupt_signal);
+ signal (SIGQUIT, interrupt_signal);
+#endif /* USG */
+
+ cancel_echoing ();
+
+ if (!NULL (Vquit_flag) && NULL (Vwindow_system))
+ {
+ fflush (stdout);
+ reset_sys_modes ();
+ sigfree ();
+#ifdef SIGTSTP /* Support possible in later USG versions */
+/*
+ * On systems which can suspend the current process and return to the original
+ * shell, this command causes the user to end up back at the shell.
+ * The "Auto-save" and "Abort" questions are not asked until
+ * the user elects to return to emacs, at which point he can save the current
+ * job and either dump core or continue.
+ */
+ sys_suspend ();
+#else
+#ifdef VMS
+ if (sys_suspend () == -1)
+ {
+ printf ("Not running as a subprocess;\n");
+ printf ("you can continue or abort.\n");
+ }
+#else /* not VMS */
+ /* Perhaps should really fork an inferior shell?
+ But that would not provide any way to get back
+ to the original shell, ever. */
+ printf ("No support for stopping a process on this operating system;\n");
+ printf ("you can continue or abort.\n");
+#endif /* not VMS */
+#endif /* not SIGTSTP */
+ printf ("Auto-save? (y or n) ");
+ fflush (stdout);
+ if (((c = getchar ()) & ~040) == 'Y')
+ Fdo_auto_save (Qnil);
+ while (c != '\n') c = getchar ();
+#ifdef VMS
+ printf ("Abort (and enter debugger)? (y or n) ");
+#else /* not VMS */
+ printf ("Abort (and dump core)? (y or n) ");
+#endif /* not VMS */
+ fflush (stdout);
+ if (((c = getchar ()) & ~040) == 'Y')
+ abort ();
+ while (c != '\n') c = getchar ();
+ printf ("Continuing...\n");
+ fflush (stdout);
+ init_sys_modes ();
+ }
+ else
+ {
+ /* If executing a function that wants to be interrupted out of
+ and the user has not deferred quitting by binding `inhibit-quit'
+ then quit right away. */
+ if (immediate_quit && NULL (Vinhibit_quit))
+ {
+ immediate_quit = 0;
+ sigfree ();
+ Fsignal (Qquit, Qnil);
+ }
+ else
+ /* Else request quit when it's safe */
+ Vquit_flag = Qt;
+ }
+
+ if (waiting_for_input && !echoing)
+ quit_throw_to_read_command_char ();
+
+ errno = old_errno;
+}
+
+/* Handle a C-g by making read_command_char return C-g. */
+
+quit_throw_to_read_command_char ()
+{
+ quit_error_check ();
+ sigfree ();
+ /* Prevent another signal from doing this before we finish. */
+ waiting_for_input = 0;
+ input_pending = 0;
+ unread_command_char = -1;
+#ifdef POLL_FOR_INPUT
+ if (poll_suppress_count != 1)
+ abort ();
+#endif
+ _longjmp (getcjmp, 1);
+}
+
+DEFUN ("set-input-mode", Fset_input_mode, Sset_input_mode, 2, 3, 0,
+ "Set mode of reading keyboard input.\n\
+First arg non-nil means use input interrupts; nil means use CBREAK mode.\n\
+Second arg non-nil means use ^S/^Q flow control for output to terminal\n\
+ (no effect except in CBREAK mode).\n\
+Optional third arg non-nil specifies character to use for quitting.\n\n\
+Note that the arguments will change incompatibly in version 19.")
+ (interrupt, flow, quit)
+ Lisp_Object interrupt, flow, quit;
+{
+ reset_sys_modes ();
+#ifdef SIGIO
+/* Note SIGIO has been undef'd if FIONREAD is missing. */
+#ifdef NO_SOCK_SIGIO
+ if (read_socket_hook)
+ interrupt_input = 0; /* No interrupts if reading from a socket. */
+ else
+#endif /* NO_SOCK_SIGIO */
+ interrupt_input = !NULL (interrupt);
+#else /* not SIGIO */
+ interrupt_input = 0;
+#endif /* not SIGIO */
+ flow_control = !NULL (flow);
+ if (!NULL (quit))
+ {
+ CHECK_NUMBER (quit, 2);
+ quit_char = XINT (quit);
+ /* Don't let this value be out of range. */
+ quit_char &= (meta_key ? 0377 : 0177);
+ }
+ init_sys_modes ();
+ return Qnil;
+}
+
+init_keyboard ()
+{
+ this_command_keys_size = 40;
+ this_command_keys = (unsigned char *) xmalloc (40);
+
+ command_loop_level = -1; /* Correct, before outermost invocation. */
+ quit_char = Ctl ('G');
+ immediate_quit = 0;
+ unread_command_char = -1;
+ recent_keys_index = 0;
+ total_keys = 0;
+ kbd_count = 0;
+ kbd_ptr = kbd_buffer;
+ input_pending = 0;
+ force_input = 0;
+ if (!noninteractive)
+ {
+ signal (SIGINT, interrupt_signal);
+#ifdef HAVE_TERMIO
+ /* On systems with TERMIO, C-g is set up for both SIGINT and SIGQUIT
+ and we can't tell which one it will give us. */
+ signal (SIGQUIT, interrupt_signal);
+#endif /* HAVE_TERMIO */
+/* Note SIGIO has been undef'd if FIONREAD is missing. */
+#ifdef SIGIO
+ signal (SIGIO, input_available_signal);
+#endif /* SIGIO */
+ }
+
+/* Use interrupt input by default, if it works and noninterrupt input
+ has deficiencies. */
+
+#ifdef INTERRUPT_INPUT
+ interrupt_input = 1;
+#else
+ interrupt_input = 0;
+#endif
+
+ sigfree ();
+ dribble = 0;
+
+ if (keyboard_init_hook)
+ (*keyboard_init_hook) ();
+
+ poll_suppress_count = 1;
+#ifdef POLL_FOR_INPUT
+ start_polling ();
+#endif
+}
+
+syms_of_keyboard ()
+{
+ Qself_insert_command = intern ("self-insert-command");
+ staticpro (&Qself_insert_command);
+
+ Qforward_char = intern ("forward-char");
+ staticpro (&Qforward_char);
+
+ Qbackward_char = intern ("backward-char");
+ staticpro (&Qbackward_char);
+
+ Qdisabled = intern ("disabled");
+ staticpro (&Qdisabled);
+
+ defsubr (&Sread_key_sequence);
+ defsubr (&Srecursive_edit);
+ defsubr (&Sinput_pending_p);
+ defsubr (&Scommand_execute);
+ defsubr (&Srecent_keys);
+ defsubr (&Sthis_command_keys);
+ defsubr (&Ssuspend_emacs);
+ defsubr (&Sabort_recursive_edit);
+ defsubr (&Sexit_recursive_edit);
+ defsubr (&Srecursion_depth);
+ defsubr (&Stop_level);
+ defsubr (&Sdiscard_input);
+ defsubr (&Sopen_dribble_file);
+ defsubr (&Sset_input_mode);
+ defsubr (&Sexecute_extended_command);
+
+ DEFVAR_LISP ("disabled-command-hook", &Vdisabled_command_hook,
+ "Value is called instead of any command that is disabled\n\
+\(has a non-nil disabled property).");
+
+ DEFVAR_BOOL ("meta-flag", &meta_key,
+ "*Non-nil means treat 0200 bit in terminal input as Meta bit.");
+
+ DEFVAR_INT ("last-command-char", &last_command_char,
+ "Last terminal input character that was part of a command, as an integer.");
+
+ DEFVAR_INT ("last-input-char", &last_input_char,
+ "Last terminal input character, as an integer.");
+
+ DEFVAR_INT ("unread-command-char", &unread_command_char,
+ "Character to be read as next input from command input stream, or -1 if none.");
+
+ DEFVAR_INT ("meta-prefix-char", &meta_prefix_char,
+ "Meta-prefix character code. Meta-foo as command input\n\
+turns into this character followed by foo.");
+ meta_prefix_char = 033;
+
+ DEFVAR_LISP ("last-command", &last_command,
+ "The last command executed. Normally a symbol with a function definition,\n\
+but can be whatever was found in the keymap, or whatever the variable\n\
+`this-command' was set to by that command.");
+ last_command = Qnil;
+
+ DEFVAR_LISP ("this-command", &this_command,
+ "The command now being executed.\n\
+The command can set this variable; whatever is put here\n\
+will be in last-command during the following command.");
+ this_command = Qnil;
+
+ DEFVAR_INT ("auto-save-interval", &auto_save_interval,
+ "*Number of keyboard input characters between auto-saves.\n\
+Zero means disable autosaving.");
+ auto_save_interval = 300;
+
+ DEFVAR_INT ("echo-keystrokes", &echo_keystrokes,
+ "*Nonzero means echo unfinished commands after this many seconds of pause.");
+ echo_keystrokes = 1;
+
+ DEFVAR_INT ("polling-period", &polling_period,
+ "*Interval between polling for input during Lisp execution.\n\
+The reason for polling is to make C-g work to stop a running program.\n\
+Polling is needed only when using X windows and SIGIO does not work.\n\
+Polling is automatically disabled in all other cases.");
+ polling_period = 2;
+
+ DEFVAR_INT ("help-char", &help_char,
+ "Character to recognize as meaning Help.\n\
+When it is read, do (eval help-form), and display result if it's a string.\n\
+If help-form's value is nil, this char can be read normally.");
+ help_char = Ctl ('H');
+
+ DEFVAR_LISP ("help-form", &Vhelp_form,
+ "Form to execute when character help-char is read.\n\
+If the form returns a string, that string is displayed.\n\
+If help-form is nil, the help char is not recognized.");
+ Vhelp_form = Qnil;
+
+ DEFVAR_LISP ("top-level", &Vtop_level,
+ "Form to evaluate when Emacs starts up.\n\
+Useful to set before you dump a modified Emacs.");
+ Vtop_level = Qnil;
+
+ DEFVAR_LISP ("keyboard-translate-table", &Vkeyboard_translate_table,
+ "String used as translate table for keyboard input, or nil.\n\
+Each character is looked up in this string and the contents used instead.\n\
+If string is of length N, character codes N and up are untranslated.");
+ Vkeyboard_translate_table = Qnil;
+}
+
+keys_of_keyboard ()
+{
+ ndefkey (Vglobal_map, Ctl ('Z'), "suspend-emacs");
+ ndefkey (Vctl_x_map, Ctl ('Z'), "suspend-emacs");
+ ndefkey (Vesc_map, Ctl ('C'), "exit-recursive-edit");
+ ndefkey (Vglobal_map, Ctl (']'), "abort-recursive-edit");
+ ndefkey (Vesc_map, 'x', "execute-extended-command");
+}
diff --git a/src/keymap.c b/src/keymap.c
new file mode 100644
index 00000000000..afa210defcd
--- /dev/null
+++ b/src/keymap.c
@@ -0,0 +1,1329 @@
+/* Manipulation of keymaps
+ Copyright (C) 1985, 1986, 1987, 1988, 1990 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#include "config.h"
+#include <stdio.h>
+#undef NULL
+#include "lisp.h"
+#include "commands.h"
+#include "buffer.h"
+
+#define min(a, b) ((a) < (b) ? (a) : (b))
+
+/* Actually allocate storage for these variables */
+
+#ifdef HAVE_X_WINDOWS
+Lisp_Object MouseMap; /* Keymap for mouse commands */
+#endif /* HAVE_X_WINDOWS */
+
+Lisp_Object global_map;
+
+Lisp_Object Vglobal_map;
+
+Lisp_Object Vesc_map;
+
+Lisp_Object Vctl_x_map;
+
+/* Keymap used for minibuffers with self-inserting space. */
+Lisp_Object Vminibuffer_local_map;
+
+/* Keymap used for minibuffers when space does not self insert. */
+Lisp_Object Vminibuffer_local_ns_map;
+
+/* Keymap used for minibuffers when doing completion */
+Lisp_Object Vminibuffer_local_completion_map;
+
+/* Keymap used for minibuffers when doing completion and require a match */
+Lisp_Object Vminibuffer_local_must_match_map;
+
+Lisp_Object Qkeymapp, Qkeymap;
+
+/* A char over 0200 in a key sequence
+ is equivalent to prefixing with this character. */
+
+extern int meta_prefix_char;
+
+static void insert_first_line ();
+
+DEFUN ("make-keymap", Fmake_keymap, Smake_keymap, 0, 0, 0,
+ "Construct and return a new keymap, a vector of length 128.\n\
+All entries in it are nil, meaning \"command undefined\".")
+ ()
+{
+ register Lisp_Object val;
+ XFASTINT (val) = 0200;
+ return Fmake_vector (val, Qnil);
+}
+
+DEFUN ("make-sparse-keymap", Fmake_sparse_keymap, Smake_sparse_keymap, 0, 0, 0,
+ "Construct and return a new sparse-keymap list.\n\
+Its car is 'keymap and its cdr is an alist of (CHAR . DEFINITION).\n\
+Initially the alist is nil.")
+ ()
+{
+ return Fcons (Qkeymap, Qnil);
+}
+
+/* Install a standard key binding at initialization time.
+ For example,
+ ndefkey (Vctl_x_map, Ctl ('X'), "exchange-point-and-mark"); */
+
+void
+ndefkey (keymap, key, defname)
+ Lisp_Object keymap;
+ int key;
+ char *defname;
+{
+ store_in_keymap (keymap, key, intern (defname));
+}
+
+/* Define character fromchar in map frommap as an alias for character tochar in map tomap.
+ Subsequent redefinitions of the latter WILL affect the former. */
+
+#ifdef NOTDEF
+void
+synkey (frommap, fromchar, tomap, tochar)
+ struct Lisp_Vector *frommap, *tomap;
+ int fromchar, tochar;
+{
+ Lisp_Object v, c;
+ XSET (v, Lisp_Vector, tomap);
+ XFASTINT (c) = tochar;
+ frommap->contents[fromchar] = Fcons (v, c);
+}
+#endif /* NOTDEF */
+
+DEFUN ("keymapp", Fkeymapp, Skeymapp, 1, 1, 0,
+ "Return t if ARG is a keymap.\n\
+A keymap is a vector of length 128, or a list (keymap . ALIST),\n\
+where alist elements look like (CHAR . DEFN).\n\
+A symbol whose function definition is a keymap is itself a keymap.")
+ (object)
+ Lisp_Object object;
+{
+ register Lisp_Object tem;
+ tem = object;
+ while (XTYPE (tem) == Lisp_Symbol)
+ {
+ tem = XSYMBOL (tem)->function;
+ if (EQ (tem, Qunbound))
+ return Qnil;
+ QUIT;
+ }
+
+ if ((XTYPE (tem) == Lisp_Vector && XVECTOR (tem)->size == 0200)
+ || (CONSP (tem) && EQ (XCONS (tem)->car, Qkeymap)))
+ return Qt;
+ return Qnil;
+}
+
+Lisp_Object
+get_keymap_1 (object, error)
+ Lisp_Object object;
+ int error;
+{
+ register Lisp_Object tem;
+
+ while (1)
+ {
+ tem = object;
+ while (XTYPE (tem) == Lisp_Symbol && !EQ (tem, Qunbound))
+ {
+ tem = XSYMBOL (tem)->function;
+ QUIT;
+ }
+ if ((XTYPE (tem) == Lisp_Vector && XVECTOR (tem)->size == 0200)
+ || (CONSP (tem) && EQ (XCONS (tem)->car, Qkeymap)))
+ return tem;
+ if (error)
+ object = wrong_type_argument (Qkeymapp, object);
+ else return Qnil;
+ }
+}
+
+Lisp_Object
+get_keymap (object)
+ Lisp_Object object;
+{
+ return get_keymap_1 (object, 1);
+}
+
+Lisp_Object
+get_keyelt (object)
+ register Lisp_Object object;
+{
+ register Lisp_Object map, tem;
+
+ while (map = get_keymap_1 (Fcar_safe (object), 0),
+ tem = Fkeymapp (map),
+ !NULL (tem))
+ /*(XTYPE (object) == Lisp_Cons && !EQ (XCONS (object)->car, Qkeymap))*/
+ {
+ object = Fcdr (object);
+ if (CONSP (map))
+ object = Fcdr (Fassq (object, Fcdr (map)));
+ else
+ object = Faref (map, object);
+ }
+ return object;
+}
+
+Lisp_Object
+access_keymap (map, idx)
+ Lisp_Object map;
+ register int idx;
+{
+ register Lisp_Object val;
+ if (idx < 0 || idx >= 0200)
+ error ("Command key out of range 0-127");
+
+ /* Get definition for character `idx' proper. */
+ if (CONSP (map))
+ val = Fcdr (Fassq (make_number (idx), Fcdr (map)));
+ else
+ val = XVECTOR (map)->contents[idx];
+
+ return val;
+}
+
+Lisp_Object
+store_in_keymap (keymap, idx, def)
+ Lisp_Object keymap;
+ register int idx;
+ register Lisp_Object def;
+{
+ register Lisp_Object tem;
+
+ if (idx < 0 || idx >= 0200)
+ error ("Command key out of range 0-127");
+
+ if (CONSP (keymap))
+ {
+ tem = Fassq (make_number (idx), Fcdr (keymap));
+ if (!NULL (tem))
+ Fsetcdr (tem, def);
+ else
+ Fsetcdr (keymap, Fcons (Fcons (make_number (idx), def),
+ Fcdr (keymap)));
+ }
+ else
+ XVECTOR (keymap)->contents[idx] = def;
+
+ return def;
+}
+
+DEFUN ("copy-keymap", Fcopy_keymap, Scopy_keymap, 1, 1, 0,
+ "Return a copy of the keymap KEYMAP.\n\
+The copy starts out with the same definitions of KEYMAP,\n\
+but changing either the copy or KEYMAP does not affect the other.\n\
+Any key definitions that are subkeymaps are recursively copied.\n\
+However, a key definition which is a symbol whose definition is a keymap\n\
+is not copied.")
+ (keymap)
+ Lisp_Object keymap;
+{
+ register Lisp_Object copy, tem;
+
+ keymap = get_keymap (keymap);
+ if (XTYPE (keymap) == Lisp_Vector)
+ {
+ register int i;
+ copy = Fcopy_sequence (keymap);
+ for (i = 0; i < XVECTOR (copy)->size; i++)
+ if (XTYPE (XVECTOR (copy)->contents[i]) != Lisp_Symbol)
+ if (tem = Fkeymapp (XVECTOR (copy)->contents[i]), !NULL (tem))
+ XVECTOR (copy)->contents[i]
+ = Fcopy_keymap (XVECTOR (copy)->contents[i]);
+ }
+ else
+ {
+ register Lisp_Object tail;
+ copy = Fcopy_alist (keymap);
+ for (tail = copy; CONSP (tail); tail = XCONS (tail)->cdr)
+ {
+ register Lisp_Object elt;
+ elt = XCONS (tail)->car;
+ if (CONSP (elt)
+ && XTYPE (XCONS (elt)->cdr) != Lisp_Symbol
+ && (tem = Fkeymapp (XCONS (elt)->cdr), !NULL (tem)))
+ XCONS (elt)->cdr = Fcopy_keymap (XCONS (elt)->cdr);
+ }
+ }
+ return copy;
+}
+
+DEFUN ("define-key", Fdefine_key, Sdefine_key, 3, 3, 0,
+ "Args KEYMAP, KEY, DEF. Define key sequence KEY, in KEYMAP, as DEF.\n\
+KEYMAP is a keymap. KEY is a string meaning a sequence of keystrokes.\n\
+DEF is anything that can be a key's definition:\n\
+ nil (means key is undefined in this keymap),\n\
+ a command (a Lisp function suitable for interactive calling)\n\
+ a string (treated as a keyboard macro),\n\
+ a keymap (to define a prefix key),\n\
+ a list (KEYMAP . CHAR), meaning use definition of CHAR in map KEYMAP,\n\
+ or a symbol. The symbol's function definition is used as the key's\n\
+definition, and may be any of the above (including another symbol).")
+ (keymap, key, def)
+ register Lisp_Object keymap;
+ Lisp_Object key;
+ Lisp_Object def;
+{
+ register int idx;
+ register int c;
+ register Lisp_Object tem;
+ register Lisp_Object cmd;
+ int metized = 0;
+
+ keymap = get_keymap (keymap);
+
+ CHECK_STRING (key, 1);
+ if (XSTRING (key)->size == 0)
+ return Qnil;
+
+ idx = 0;
+ while (1)
+ {
+ c = XSTRING (key)->data[idx];
+ if (c >= 0200 && !metized)
+ {
+ c = meta_prefix_char;
+ metized = 1;
+ }
+ else
+ {
+ c &= 0177;
+ metized = 0;
+ idx++;
+ }
+
+ if (idx == XSTRING (key)->size)
+ return store_in_keymap (keymap, c, def);
+
+ cmd = get_keyelt (access_keymap (keymap, c));
+ if (NULL (cmd))
+ {
+ cmd = Fmake_sparse_keymap ();
+ store_in_keymap (keymap, c, cmd);
+ }
+ tem = Fkeymapp (cmd);
+ if (NULL (tem))
+ error ("Key sequence %s uses invalid prefix characters",
+ XSTRING (key)->data);
+
+ keymap = get_keymap (cmd);
+ }
+}
+
+/* Value is number if KEY is too long; nil if valid but has no definition. */
+
+DEFUN ("lookup-key", Flookup_key, Slookup_key, 2, 2, 0,
+ "In keymap KEYMAP, look up key sequence KEY. Return the definition.\n\
+nil means undefined. See doc of define-key for kinds of definitions.\n\
+Number as value means KEY is \"too long\";\n\
+that is, characters in it except for the last one\n\
+fail to be a valid sequence of prefix characters in KEYMAP.\n\
+The number is how many characters at the front of KEY\n\
+it takes to reach a non-prefix command.")
+ (keymap, key)
+ register Lisp_Object keymap;
+ Lisp_Object key;
+{
+ register int idx;
+ register Lisp_Object tem;
+ register Lisp_Object cmd;
+ register int c;
+ int metized = 0;
+
+ keymap = get_keymap (keymap);
+
+ CHECK_STRING (key, 1);
+ if (XSTRING (key)->size == 0)
+ return Qnil;
+
+ idx = 0;
+ while (1)
+ {
+ c = XSTRING (key)->data[idx];
+ if (c >= 0200 && !metized)
+ {
+ c = meta_prefix_char;
+ metized = 1;
+ }
+ else
+ {
+ c &= 0177;
+ metized = 0;
+ idx++;
+ }
+
+ cmd = get_keyelt (access_keymap (keymap, c));
+ if (idx == XSTRING (key)->size)
+ return cmd;
+
+ tem = Fkeymapp (cmd);
+ if (NULL (tem))
+ return make_number (idx);
+
+ keymap = get_keymap (cmd);
+ QUIT;
+ }
+}
+
+DEFUN ("key-binding", Fkey_binding, Skey_binding, 1, 1, 0,
+ "Return the definition for command KEYS in current keymaps.\n\
+KEYS is a string, a sequence of keystrokes.\n\
+The definition is probably a symbol with a function definition.")
+ (keys)
+ Lisp_Object keys;
+{
+ register Lisp_Object map, value, value1;
+ map = current_buffer->keymap;
+ if (!NULL (map))
+ {
+ value = Flookup_key (map, keys);
+ if (NULL (value))
+ {
+ XSET (map, Lisp_Vector, global_map);
+ value1 = Flookup_key (map, keys);
+ if (XTYPE (value1) == Lisp_Int)
+ return Qnil;
+ return value1;
+ }
+ else if (XTYPE (value) != Lisp_Int)
+ return value;
+ }
+ XSET (map, Lisp_Vector, global_map);
+ return Flookup_key (map, keys);
+}
+
+DEFUN ("local-key-binding", Flocal_key_binding, Slocal_key_binding, 1, 1, 0,
+ "Return the definition for command KEYS in current local keymap only.\n\
+KEYS is a string, a sequence of keystrokes.\n\
+The definition is probably a symbol with a function definition.")
+ (keys)
+ Lisp_Object keys;
+{
+ register Lisp_Object map;
+ map = current_buffer->keymap;
+ if (NULL (map))
+ return Qnil;
+ return Flookup_key (map, keys);
+}
+
+DEFUN ("global-key-binding", Fglobal_key_binding, Sglobal_key_binding, 1, 1, 0,
+ "Return the definition for command KEYS in current global keymap only.\n\
+KEYS is a string, a sequence of keystrokes.\n\
+The definition is probably a symbol with a function definition.")
+ (keys)
+ Lisp_Object keys;
+{
+ register Lisp_Object map;
+ XSET (map, Lisp_Vector, global_map);
+ return Flookup_key (map, keys);
+}
+
+DEFUN ("global-set-key", Fglobal_set_key, Sglobal_set_key, 2, 2,
+ "kSet key globally: \nCSet key %s to command: ",
+ "Give KEY a definition of COMMAND.\n\
+COMMAND is a symbol naming an interactively-callable function.\n\
+KEY is a string representing a sequence of keystrokes.\n\
+Note that if KEY has a local definition in the current buffer\n\
+that local definition will continue to shadow any global definition.")
+ (keys, function)
+ Lisp_Object keys, function;
+{
+ register Lisp_Object map;
+ XSET (map, Lisp_Vector, global_map);
+ CHECK_STRING (keys, 1);
+ Fdefine_key (map, keys, function);
+ return Qnil;
+}
+
+DEFUN ("local-set-key", Flocal_set_key, Slocal_set_key, 2, 2,
+ "kSet key locally: \nCSet key %s locally to command: ",
+ "Give KEY a local definition of COMMAND.\n\
+COMMAND is a symbol naming an interactively-callable function.\n\
+KEY is a string representing a sequence of keystrokes.\n\
+The definition goes in the current buffer's local map,\n\
+which is shared with other buffers in the same major mode.")
+ (keys, function)
+ Lisp_Object keys, function;
+{
+ register Lisp_Object map;
+ map = current_buffer->keymap;
+ if (NULL (map))
+ {
+ map = Fmake_sparse_keymap ();
+ current_buffer->keymap = map;
+ }
+
+ CHECK_STRING (keys, 1);
+ Fdefine_key (map, keys, function);
+ return Qnil;
+}
+
+DEFUN ("global-unset-key", Fglobal_unset_key, Sglobal_unset_key,
+ 1, 1, "kUnset key globally: ",
+ "Remove global definition of KEY.\n\
+KEY is a string representing a sequence of keystrokes.")
+ (keys)
+ Lisp_Object keys;
+{
+ return Fglobal_set_key (keys, Qnil);
+}
+
+DEFUN ("local-unset-key", Flocal_unset_key, Slocal_unset_key, 1, 1,
+ "kUnset key locally: ",
+ "Remove local definition of KEY.\n\
+KEY is a string representing a sequence of keystrokes.")
+ (keys)
+ Lisp_Object keys;
+{
+ if (!NULL (current_buffer->keymap))
+ Flocal_set_key (keys, Qnil);
+ return Qnil;
+}
+
+DEFUN ("define-prefix-command", Fdefine_prefix_command, Sdefine_prefix_command, 1, 1, 0,
+ "Define SYMBOL as a prefix command.\n\
+A keymap is created and stored as SYMBOL's function definition.")
+ (name)
+ Lisp_Object name;
+{
+ Ffset (name, Fmake_keymap ());
+ return name;
+}
+
+DEFUN ("use-global-map", Fuse_global_map, Suse_global_map, 1, 1, 0,
+ "Selects KEYMAP as the global keymap.")
+ (keymap)
+ Lisp_Object keymap;
+{
+ keymap = get_keymap (keymap);
+ CHECK_VECTOR (keymap, 0);
+ global_map = keymap;
+ return Qnil;
+}
+
+DEFUN ("use-local-map", Fuse_local_map, Suse_local_map, 1, 1, 0,
+ "Selects KEYMAP as the local keymap.\n\
+nil for KEYMAP means no local keymap.")
+ (keymap)
+ Lisp_Object keymap;
+{
+ if (!NULL (keymap))
+ keymap = get_keymap (keymap);
+
+ current_buffer->keymap = keymap;
+
+ return Qnil;
+}
+
+DEFUN ("current-local-map", Fcurrent_local_map, Scurrent_local_map, 0, 0, 0,
+ "Return current buffer's local keymap, or nil if it has none.")
+ ()
+{
+ return current_buffer->keymap;
+}
+
+DEFUN ("current-global-map", Fcurrent_global_map, Scurrent_global_map, 0, 0, 0,
+ "Return the current global keymap.")
+ ()
+{
+ return global_map;
+}
+
+DEFUN ("accessible-keymaps", Faccessible_keymaps, Saccessible_keymaps,
+ 1, 1, 0,
+ "Find all keymaps accessible via prefix characters from KEYMAP.\n\
+Returns a list of elements of the form (KEYS . MAP), where the sequence\n\
+KEYS starting from KEYMAP gets you to MAP. These elements are ordered\n\
+so that the KEYS increase in length. The first element is (\"\" . KEYMAP).")
+ (startmap)
+ Lisp_Object startmap;
+{
+ Lisp_Object maps, tail;
+ register Lisp_Object thismap, thisseq;
+ register Lisp_Object dummy;
+ register Lisp_Object tem;
+ register Lisp_Object cmd;
+ register int i;
+
+ maps = Fcons (Fcons (build_string (""), get_keymap (startmap)), Qnil);
+ tail = maps;
+
+ /* For each map in the list maps,
+ look at any other maps it points to
+ and stick them at the end if they are not already in the list */
+
+ while (!NULL (tail))
+ {
+ thisseq = Fcar (Fcar (tail));
+ thismap = Fcdr (Fcar (tail));
+ for (i = 0; i < 0200; i++)
+ {
+ cmd = get_keyelt (access_keymap (thismap, i));
+ if (NULL (cmd)) continue;
+ tem = Fkeymapp (cmd);
+ if (!NULL (tem))
+ {
+ cmd = get_keymap (cmd);
+ tem = Frassq (cmd, maps);
+ if (NULL (tem))
+ {
+ XFASTINT (dummy) = i;
+ dummy = concat2 (thisseq, Fchar_to_string (dummy));
+ nconc2 (tail, Fcons (Fcons (dummy, cmd), Qnil));
+ }
+ }
+ }
+ tail = Fcdr (tail);
+ }
+
+ return maps;
+}
+
+Lisp_Object Qsingle_key_description, Qkey_description;
+
+DEFUN ("key-description", Fkey_description, Skey_description, 1, 1, 0,
+ "Return a pretty description of key-sequence KEYS.\n\
+Control characters turn into \"C-foo\" sequences, meta into \"M-foo\"\n\
+spaces are put between sequence elements, etc.")
+ (keys)
+ Lisp_Object keys;
+{
+ return Fmapconcat (Qsingle_key_description, keys, build_string (" "));
+}
+
+char *
+push_key_description (c, p)
+ register unsigned int c;
+ register char *p;
+{
+ if (c >= 0200)
+ {
+ *p++ = 'M';
+ *p++ = '-';
+ c -= 0200;
+ }
+ if (c < 040)
+ {
+ if (c == 033)
+ {
+ *p++ = 'E';
+ *p++ = 'S';
+ *p++ = 'C';
+ }
+ else if (c == Ctl('I'))
+ {
+ *p++ = 'T';
+ *p++ = 'A';
+ *p++ = 'B';
+ }
+ else if (c == Ctl('J'))
+ {
+ *p++ = 'L';
+ *p++ = 'F';
+ *p++ = 'D';
+ }
+ else if (c == Ctl('M'))
+ {
+ *p++ = 'R';
+ *p++ = 'E';
+ *p++ = 'T';
+ }
+ else
+ {
+ *p++ = 'C';
+ *p++ = '-';
+ if (c > 0 && c <= Ctl ('Z'))
+ *p++ = c + 0140;
+ else
+ *p++ = c + 0100;
+ }
+ }
+ else if (c == 0177)
+ {
+ *p++ = 'D';
+ *p++ = 'E';
+ *p++ = 'L';
+ }
+ else if (c == ' ')
+ {
+ *p++ = 'S';
+ *p++ = 'P';
+ *p++ = 'C';
+ }
+ else
+ *p++ = c;
+ return p;
+}
+
+DEFUN ("single-key-description", Fsingle_key_description, Ssingle_key_description, 1, 1, 0,
+ "Return a pretty description of command character KEY.\n\
+Control characters turn into C-whatever, etc.")
+ (key)
+ Lisp_Object key;
+{
+ register unsigned char c;
+ char tem[6];
+
+ CHECK_NUMBER (key, 0);
+ c = XINT (key) & 0377;
+
+ *push_key_description (c, tem) = 0;
+
+ return build_string (tem);
+}
+
+char *
+push_text_char_description (c, p)
+ register unsigned int c;
+ register char *p;
+{
+ if (c >= 0200)
+ {
+ *p++ = 'M';
+ *p++ = '-';
+ c -= 0200;
+ }
+ if (c < 040)
+ {
+ *p++ = '^';
+ *p++ = c + 64; /* 'A' - 1 */
+ }
+ else if (c == 0177)
+ {
+ *p++ = '^';
+ *p++ = '?';
+ }
+ else
+ *p++ = c;
+ return p;
+}
+
+DEFUN ("text-char-description", Ftext_char_description, Stext_char_description, 1, 1, 0,
+ "Return a pretty description of file-character CHAR.\n\
+Control characters turn into \"^char\", etc.")
+ (chr)
+ Lisp_Object chr;
+{
+ char tem[6];
+
+ CHECK_NUMBER (chr, 0);
+
+ *push_text_char_description (XINT (chr) & 0377, tem) = 0;
+
+ return build_string (tem);
+}
+
+DEFUN ("where-is-internal", Fwhere_is_internal, Swhere_is_internal, 1, 3, 0,
+ "Return list of key sequences that currently invoke command DEFINITION\n\
+in KEYMAP or (current-global-map). If KEYMAP is nil, only search for\n\
+keys in the global map.\n\
+\n\
+If FIRSTONLY is non-nil, returns a string representing the first key\n\
+sequence found, rather than a list of all possible key sequences.")
+ (definition, local_keymap, firstonly)
+ Lisp_Object definition, local_keymap, firstonly;
+{
+ Lisp_Object start1;
+ register Lisp_Object maps;
+ Lisp_Object found;
+
+ XSET (start1, Lisp_Vector, global_map);
+
+ if (!NULL (local_keymap))
+ maps = nconc2 (Faccessible_keymaps (get_keymap (local_keymap)),
+ Faccessible_keymaps (start1));
+ else
+ maps = Faccessible_keymaps (start1);
+
+ found = Qnil;
+
+ for (; !NULL (maps); maps = Fcdr (maps))
+ {
+ register this = Fcar (Fcar (maps)); /* Key sequence to reach map */
+ register map = Fcdr (Fcar (maps)); /* The map that it reaches */
+ register int i = 0;
+
+ if (CONSP (map))
+ map = Fcdr (map);
+
+ /* If the MAP is a vector, I increments and eventually reaches 0200.
+ Otherwise I remains 0; MAP is cdr'd and eventually becomes nil. */
+
+ while (!NULL (map) && i < 0200)
+ {
+ register Lisp_Object elt, dummy;
+
+ QUIT;
+ if (CONSP (map))
+ {
+ elt = Fcdr (Fcar (map));
+ dummy = Fcar (Fcar (map));
+ map = Fcdr (map);
+ }
+ else
+ {
+ elt = XVECTOR (map)->contents[i];
+ XFASTINT (dummy) = i;
+ i++;
+ }
+
+ if (XTYPE (definition) != Lisp_Cons)
+ elt = get_keyelt (elt);
+
+ /* End this iteration if this element does not match
+ the target. */
+
+ if (XTYPE (definition) == Lisp_Cons)
+ {
+ Lisp_Object tem;
+ tem = Fequal (elt, definition);
+ if (NULL (tem))
+ continue;
+ }
+ else
+ if (!EQ (elt, definition))
+ continue;
+
+ /* We have found a match.
+ Construct the key sequence where we found it. */
+
+ dummy = concat2 (this, Fchar_to_string (dummy));
+
+ /* Verify that this key binding is not shadowed
+ by another binding for the same key,
+ before we say it exists.
+ The mechanism: look for local definition of this key
+ and if it is defined and does not match what we found
+ then ignore this key.
+ Either nil or number as value from Flookup_key
+ means undefined. */
+
+ if (!NULL (local_keymap))
+ elt = Flookup_key (local_keymap, dummy);
+ if (!NULL (elt) && XTYPE (elt) != Lisp_Int)
+ {
+ if (XTYPE (definition) == Lisp_Cons)
+ {
+ Lisp_Object tem;
+ tem = Fequal (elt, definition);
+ if (NULL (tem))
+ continue;
+ }
+ else
+ if (!EQ (elt, definition))
+ continue;
+ }
+
+ /* It is a true unshadowed match Record it. */
+
+ if (!NULL (firstonly))
+ return dummy;
+ found = Fcons (dummy, found);
+ }
+ }
+ return Fnreverse (found);
+}
+
+DEFUN ("where-is", Fwhere_is, Swhere_is, 1, 1, "CWhere is command: ",
+ "Print message listing key sequences that invoke specified command.\n\
+Argument is a command definition, usually a symbol with a function definition.")
+ (definition)
+ Lisp_Object definition;
+{
+ register Lisp_Object tem;
+ CHECK_SYMBOL (definition, 0);
+ tem = Fmapconcat (Qkey_description,
+ Fwhere_is_internal (definition, current_buffer->keymap, Qnil),
+ build_string (", "));
+ if (XSTRING (tem)->size)
+ message ("%s is on %s", XSYMBOL (definition)->name->data, XSTRING (tem)->data);
+ else
+ message ("%s is not on any keys", XSYMBOL (definition)->name->data);
+ return Qnil;
+}
+
+Lisp_Object describe_buffer_bindings ();
+
+DEFUN ("describe-bindings", Fdescribe_bindings, Sdescribe_bindings, 0, 0, "",
+ "Show a list of all defined keys, and their definitions.\n\
+The list is put in a buffer, which is displayed.")
+ ()
+{
+ register Lisp_Object thisbuf;
+ XSET (thisbuf, Lisp_Buffer, current_buffer);
+ internal_with_output_to_temp_buffer ("*Help*", describe_buffer_bindings, thisbuf);
+ return Qnil;
+}
+
+Lisp_Object
+describe_buffer_bindings (descbuf)
+ Lisp_Object descbuf;
+{
+ register Lisp_Object start1;
+ char *heading = "key binding\n--- -------\n";
+
+ Fset_buffer (Vstandard_output);
+
+ start1 = XBUFFER (descbuf)->keymap;
+ if (!NULL (start1))
+ {
+ InsStr ("Local Bindings:\n");
+ InsStr (heading);
+ heading = 0;
+ describe_map_tree (start1, 0, Qnil);
+ InsStr ("\n");
+ }
+
+ InsStr ("Global Bindings:\n");
+ if (heading)
+ InsStr (heading);
+
+ XSET (start1, Lisp_Vector, global_map);
+ describe_map_tree (start1, 0, XBUFFER (descbuf)->keymap);
+
+ Fset_buffer (descbuf);
+ return Qnil;
+}
+
+/* Insert a desription of the key bindings in STARTMAP,
+ followed by those of all maps reachable through STARTMAP.
+ If PARTIAL is nonzero, omit certain "uninteresting" commands
+ (such as `undefined').
+ If SHADOW is non-nil, don't mention keys which would be shadowed by it */
+
+describe_map_tree (startmap, partial, shadow)
+ Lisp_Object startmap, shadow;
+ int partial;
+{
+ Lisp_Object maps;
+ register Lisp_Object elt, sh;
+ struct gcpro gcpro1;
+
+ maps = Faccessible_keymaps (startmap);
+ GCPRO1 (maps);
+
+ for (; !NULL (maps); maps = Fcdr (maps))
+ {
+ elt = Fcar (maps);
+ sh = Fcar (elt);
+ if (NULL (shadow))
+ sh = Qnil;
+ else if (XTYPE (sh) == Lisp_String &&
+ XSTRING (sh)->size == 0)
+ sh = shadow;
+ else
+ {
+ sh = Flookup_key (shadow, Fcar (elt));
+ if (XTYPE (sh) == Lisp_Int)
+ sh = Qnil;
+ }
+ if (NULL (sh) || !NULL (Fkeymapp (sh)))
+ describe_map (Fcdr (elt), Fcar (elt), partial, sh);
+ }
+
+ UNGCPRO;
+}
+
+describe_command (definition)
+ Lisp_Object definition;
+{
+ register Lisp_Object tem1;
+
+ Findent_to (make_number (16), make_number (1));
+
+ if (XTYPE (definition) == Lisp_Symbol)
+ {
+ XSET (tem1, Lisp_String, XSYMBOL (definition)->name);
+ insert1 (tem1);
+ InsStr ("\n");
+ }
+ else
+ {
+ tem1 = Fkeymapp (definition);
+ if (!NULL (tem1))
+ InsStr ("Prefix Command\n");
+ else
+ InsStr ("??\n");
+ }
+}
+
+/* Describe the contents of map MAP, assuming that this map
+ itself is reached by the sequence of prefix keys STRING (a string).
+ PARTIAL and SHADOW are the same as in `describe_map_tree' above. */
+
+describe_map (map, string, partial, shadow)
+ Lisp_Object map, string;
+ int partial;
+ Lisp_Object shadow;
+{
+ register Lisp_Object keysdesc;
+
+ if (!NULL (string) && XSTRING (string)->size > 0)
+ keysdesc = concat2 (Fkey_description (string), build_string (" "));
+ else
+ keysdesc = Qnil;
+
+ if (CONSP (map))
+ describe_alist (Fcdr (map), keysdesc, describe_command,
+ partial, shadow);
+ else
+ describe_vector (map, keysdesc, describe_command,
+ partial, shadow);
+}
+
+describe_alist (alist, elt_prefix, elt_describer, partial, shadow)
+ register Lisp_Object alist;
+ Lisp_Object elt_prefix;
+ int (*elt_describer) ();
+ int partial;
+ Lisp_Object shadow;
+{
+ Lisp_Object this;
+ Lisp_Object tem1, tem2;
+ Lisp_Object suppress;
+ Lisp_Object kludge = Qnil;
+ int first = 1;
+ struct gcpro gcpro1, gcpro2;
+
+ if (partial)
+ suppress = intern ("suppress-keymap");
+
+ for (; CONSP (alist); alist = Fcdr (alist))
+ {
+ QUIT;
+ tem1 = Fcar (Fcar (alist));
+ tem2 = get_keyelt (Fcdr (Fcar (alist)));
+ if (NULL (tem2)) continue;
+ if (XTYPE (tem2) == Lisp_Symbol && partial)
+ {
+ this = Fget (tem2, suppress);
+ if (!NULL (this))
+ continue;
+ }
+
+ if (!NULL (shadow))
+ {
+ Lisp_Object tem;
+ if (NULL (kludge)) kludge = build_string ("x");
+ XSTRING (kludge)->data[0] = XINT (tem1);
+ tem = Flookup_key (shadow, kludge);
+ if (!NULL (tem)) continue;
+ }
+
+ if (first)
+ {
+ insert ("\n", 1);
+ first = 0;
+ }
+
+ GCPRO2 (elt_prefix, tem2);
+ if (!NULL (elt_prefix))
+ insert1 (elt_prefix);
+
+ insert1 (Fsingle_key_description (tem1));
+
+ (*elt_describer) (tem2);
+ UNGCPRO;
+ }
+}
+
+describe_vector (vector, elt_prefix, elt_describer, partial, shadow)
+ register Lisp_Object vector;
+ Lisp_Object elt_prefix;
+ int (*elt_describer) ();
+ int partial;
+ Lisp_Object shadow;
+{
+ Lisp_Object this;
+ Lisp_Object dummy;
+ Lisp_Object tem1, tem2;
+ register int i, size = XVECTOR (vector)->size;
+ Lisp_Object suppress;
+ Lisp_Object kludge;
+ int first = 1;
+ struct gcpro gcpro1, gcpro2;
+
+ tem1 = Qnil;
+ kludge = Qnil;
+ GCPRO2 (elt_prefix, tem1);
+
+ if (partial)
+ suppress = intern ("suppress-keymap");
+
+ for (i = 0; i < size; i++)
+ {
+ QUIT;
+ tem1 = get_keyelt (XVECTOR (vector)->contents[i]);
+ if (NULL (tem1)) continue;
+ if (XTYPE (tem1) == Lisp_Symbol && partial)
+ {
+ this = Fget (tem1, suppress);
+ if (!NULL (this))
+ continue;
+ }
+
+ if (!NULL (shadow))
+ {
+ Lisp_Object tem;
+ if (NULL (kludge)) kludge = build_string ("x");
+ XSTRING (kludge)->data[0] = XINT (i);
+ tem = Flookup_key (shadow, kludge);
+ if (!NULL (tem)) continue;
+ }
+
+ if (first)
+ {
+ insert ("\n", 1);
+ first = 0;
+ }
+
+ if (!NULL (elt_prefix))
+ insert1 (elt_prefix);
+
+ XFASTINT (dummy) = i;
+ insert1 (Fsingle_key_description (dummy));
+
+ while (i + 1 < size
+ && (tem2 = get_keyelt (XVECTOR (vector)->contents[i+1]),
+ EQ (tem2, tem1)))
+ i++;
+
+ if (i != XINT (dummy))
+ {
+ insert (" .. ", 4);
+ if (!NULL (elt_prefix))
+ insert1 (elt_prefix);
+
+ XFASTINT (dummy) = i;
+ insert1 (Fsingle_key_description (dummy));
+ }
+
+ (*elt_describer) (tem1);
+ }
+
+ UNGCPRO;
+}
+
+/* Apropos */
+Lisp_Object apropos_predicate;
+Lisp_Object apropos_accumulate;
+
+static
+apropos_accum (symbol, string)
+ Lisp_Object symbol, string;
+{
+ register Lisp_Object tem;
+
+ tem = Fstring_match (string, Fsymbol_name (symbol), Qnil);
+ if (!NULL (tem) && !NULL (apropos_predicate))
+ tem = call1 (apropos_predicate, symbol);
+ if (!NULL (tem))
+ apropos_accumulate = Fcons (symbol, apropos_accumulate);
+}
+
+static Lisp_Object
+apropos1 (list)
+ register Lisp_Object list;
+{
+ struct buffer *old = current_buffer;
+ register Lisp_Object symbol, col, tem;
+
+ while (!NULL (list))
+ {
+ Lisp_Object min_cols;
+
+ QUIT;
+
+ symbol = Fcar (list);
+ list = Fcdr (list);
+
+ tem = Fwhere_is_internal (symbol, current_buffer->keymap, Qnil);
+ tem = Fmapconcat (Qkey_description, tem, build_string (", "));
+ XFASTINT (col) = 30;
+
+ set_buffer_internal (XBUFFER (Vstandard_output));
+ Fprin1 (symbol, Qnil);
+ XFASTINT (min_cols) = 1;
+ Findent_to (col, min_cols);
+ Fprinc (tem, Qnil);
+ Fterpri (Qnil);
+ tem = Ffboundp (symbol);
+ if (!NULL (tem))
+ tem = Fdocumentation (symbol);
+ if (XTYPE (tem) == Lisp_String)
+ insert_first_line (" Function: ", tem);
+ tem = Fdocumentation_property (symbol, Qvariable_documentation);
+ if (XTYPE (tem) == Lisp_String)
+ insert_first_line (" Variable: ", tem);
+ set_buffer_internal (old);
+ }
+ return Qnil;
+}
+
+static void
+insert_first_line (prefix, str)
+ char *prefix;
+ Lisp_Object str;
+{
+ extern char *index ();
+ register unsigned char *p;
+ register unsigned char *p1;
+ register unsigned char *p2;
+ struct gcpro gcpro1;
+
+ GCPRO1 (str);
+ InsStr (prefix);
+
+ retry:
+ p = XSTRING (str)->data;
+ p1 = (unsigned char *) index (p, '\n');
+
+ for (p2 = p; *p2 && p2 != p1; p2++)
+ if (p2[0] == '\\' && p2[1] == '[')
+ {
+ str = Fsubstitute_command_keys (str);
+ goto retry;
+ }
+
+ insert (p, p1 ? p1 - p : strlen (p));
+ insert ("\n", 1);
+ UNGCPRO;
+}
+
+DEFUN ("apropos", Fapropos, Sapropos, 1, 3, "sApropos: ",
+ "Show all symbols whose names contain match for REGEXP.\n\
+If optional arg PRED is non-nil, (funcall PRED SYM) is done\n\
+for each symbol and a symbol is mentioned if that returns non-nil.\n\
+Returns list of symbols found; if third arg NOPRINT is non-nil,\n\
+does not display them, just returns the list.")
+ (string, pred, noprint)
+ Lisp_Object string, pred, noprint;
+{
+ struct gcpro gcpro1, gcpro2;
+ CHECK_STRING (string, 0);
+ apropos_predicate = pred;
+ GCPRO2 (apropos_predicate, apropos_accumulate);
+ apropos_accumulate = Qnil;
+ map_obarray (Vobarray, apropos_accum, string);
+ apropos_accumulate = Fsort (apropos_accumulate, Qstring_lessp);
+ if (NULL (noprint))
+ internal_with_output_to_temp_buffer ("*Help*", apropos1,
+ apropos_accumulate);
+ UNGCPRO;
+ return apropos_accumulate;
+}
+
+syms_of_keymap ()
+{
+ Lisp_Object tem;
+
+ Qkeymap = intern ("keymap");
+ staticpro (&Qkeymap);
+
+/* Initialize the keymaps standardly used.
+ Each one is the value of a Lisp variable, and is also
+ pointed to by a C variable */
+
+#ifdef HAVE_X_WINDOWS
+ tem = Fmake_keymap ();
+ MouseMap = tem;
+ Fset (intern ("mouse-map"), tem);
+#endif /* HAVE_X_WINDOWS */
+
+ tem = Fmake_keymap ();
+ Vglobal_map = tem;
+ Fset (intern ("global-map"), tem);
+
+ tem = Fmake_keymap ();
+ Vesc_map = tem;
+ Fset (intern ("esc-map"), tem);
+ Ffset (intern ("ESC-prefix"), tem);
+
+ tem = Fmake_keymap ();
+ Vctl_x_map = tem;
+ Fset (intern ("ctl-x-map"), tem);
+ Ffset (intern ("Control-X-prefix"), tem);
+
+ DEFVAR_LISP ("minibuffer-local-map", &Vminibuffer_local_map,
+ "Default keymap to use when reading from the minibuffer.");
+ Vminibuffer_local_map = Fmake_sparse_keymap ();
+
+ DEFVAR_LISP ("minibuffer-local-ns-map", &Vminibuffer_local_ns_map,
+ "The keymap used by the minibuf for local bindings when spaces are not\n\
+to be allowed in input string.");
+ Vminibuffer_local_ns_map = Fmake_sparse_keymap ();
+
+ DEFVAR_LISP ("minibuffer-local-completion-map", &Vminibuffer_local_completion_map,
+ "Keymap to use when reading from the minibuffer with completion.");
+ Vminibuffer_local_completion_map = Fmake_sparse_keymap ();
+
+ DEFVAR_LISP ("minibuffer-local-must-match-map", &Vminibuffer_local_must_match_map,
+ "Keymap to use when reading from the minibuffer with completion and\n\
+an exact match of one of the completions is required.");
+ Vminibuffer_local_must_match_map = Fmake_sparse_keymap ();
+
+ global_map = Vglobal_map;
+
+ Qsingle_key_description = intern ("single-key-description");
+ staticpro (&Qsingle_key_description);
+
+ Qkey_description = intern ("key-description");
+ staticpro (&Qkey_description);
+
+ Qkeymapp = intern ("keymapp");
+ staticpro (&Qkeymapp);
+
+ defsubr (&Skeymapp);
+ defsubr (&Smake_keymap);
+ defsubr (&Smake_sparse_keymap);
+ defsubr (&Scopy_keymap);
+ defsubr (&Skey_binding);
+ defsubr (&Slocal_key_binding);
+ defsubr (&Sglobal_key_binding);
+ defsubr (&Sglobal_set_key);
+ defsubr (&Slocal_set_key);
+ defsubr (&Sdefine_key);
+ defsubr (&Slookup_key);
+ defsubr (&Sglobal_unset_key);
+ defsubr (&Slocal_unset_key);
+ defsubr (&Sdefine_prefix_command);
+ defsubr (&Suse_global_map);
+ defsubr (&Suse_local_map);
+ defsubr (&Scurrent_local_map);
+ defsubr (&Scurrent_global_map);
+ defsubr (&Saccessible_keymaps);
+ defsubr (&Skey_description);
+ defsubr (&Ssingle_key_description);
+ defsubr (&Stext_char_description);
+ defsubr (&Swhere_is_internal);
+ defsubr (&Swhere_is);
+ defsubr (&Sdescribe_bindings);
+ defsubr (&Sapropos);
+}
+
+keys_of_keymap ()
+{
+ ndefkey (Vglobal_map, 033, "ESC-prefix");
+ ndefkey (Vglobal_map, Ctl ('X'), "Control-X-prefix");
+}
diff --git a/src/lastfile.c b/src/lastfile.c
new file mode 100644
index 00000000000..34afbf4aa43
--- /dev/null
+++ b/src/lastfile.c
@@ -0,0 +1,43 @@
+/* Mark end of data space to dump as pure, for GNU Emacs.
+ Copyright (C) 1985 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* How this works:
+
+ Fdump_emacs dumps everything up to my_edata as text space (pure).
+
+ The files of Emacs are written so as to have no initialized
+ data that can ever need to be altered except at the first startup.
+ This is so that those words can be dumped as sharable text.
+
+ It is not possible to exercise such control over library files.
+ So it is necessary to refrain from making their data areas shared.
+ Therefore, this file is loaded following all the files of Emacs
+ but before library files.
+ As a result, the symbol my_edata indicates the point
+ in data space between data coming from Emacs and data
+ coming from libraries.
+*/
+
+#ifdef VMS
+/* Prevent the file from being totally empty. */
+static dummy () {}
+#endif
+
+char my_edata = 0;
diff --git a/src/link.com b/src/link.com
new file mode 100644
index 00000000000..6ef2398e48b
--- /dev/null
+++ b/src/link.com
@@ -0,0 +1,7 @@
+$ ! VMS command file to link the .OBJ files of Emacs,
+$ ! using `temacs.opt' and producing `temacs.exe'.
+$ if "''CC'".nes."" .and. f$extract(0,3,"''cc'").eqs."GCC" then goto link_gcc
+$ link temacs/opt
+$ exit
+$link_gcc:
+$ link temacs/opt+gnu_cc:[000000]gcclib/lib
diff --git a/src/lisp.h b/src/lisp.h
new file mode 100644
index 00000000000..a3d30d103b4
--- /dev/null
+++ b/src/lisp.h
@@ -0,0 +1,993 @@
+/* Fundamental definitions for GNU Emacs Lisp interpreter.
+ Copyright (C) 1985, 1986, 1987 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* Define the fundamental Lisp data structures */
+
+/* This is the set of Lisp data types */
+
+enum Lisp_Type
+ {
+ /* Integer. object.v.integer is the integer value. */
+ Lisp_Int,
+
+ /* Symbol. object.v.symbol points to a struct Lisp_Symbol. */
+ Lisp_Symbol,
+
+ /* Marker (editor pointer). object.v.marker points to a struct Lisp_Marker. */
+ Lisp_Marker,
+
+ /* String. object.v.string points to a struct Lisp_String.
+ The length of the string, and its contents, are stored therein. */
+ Lisp_String,
+
+ /* Vector of Lisp objects. object.v.vector points to a struct Lisp_Vector.
+ The length of the vector, and its contents, are stored therein. */
+ Lisp_Vector,
+
+ /* Cons. object.v.cons points to a struct Lisp_Cons. */
+ Lisp_Cons,
+
+ /* >>> No longer used */
+ Lisp_Object_Unused_1,
+#if 0
+ was...
+ /* Treated like vector in GC, except do not set its mark bit.
+ Used for internal data blocks that will be explicitly freed
+ but which, while active, are reached by GC mark exactly once
+ and should be marked through like a vector. */
+ Lisp_Temp_Vector,
+#endif /* 0 */
+
+ /* Editor buffer. obj.v.buffer points to a struct buffer.
+ No buffer is ever truly freed; they can be "killed", but this
+ just marks them as dead. */
+ Lisp_Buffer,
+
+ /* Built-in function. obj.v.subr points to a struct Lisp_Subr
+ which describes how to call the function, and its documentation,
+ as well as pointing to the code. */
+ Lisp_Subr,
+
+ /* Internal value return by subroutines of read.
+ The user never sees this data type.
+ Its value is just a number. */
+ Lisp_Internal,
+
+ /* Forwarding pointer to an int variable.
+ This is allowed only in the value cell of a symbol,
+ and it means that the symbol's value really lives in the
+ specified int variable.
+ obj.v.intptr points to the int variable. */
+ Lisp_Intfwd,
+
+ /* Boolean forwarding pointer to an int variable.
+ This is like Lisp_Intfwd except that the ostensible "value" of the symbol
+ is t if the int variable is nonzero, nil if it is zero.
+ obj.v.intptr points to the int variable. */
+ Lisp_Boolfwd,
+
+ /* Object describing a connection to a subprocess.
+ It points to storage of type struct Lisp_Process */
+ Lisp_Process,
+
+ /* Forwarding pointer to a Lisp_Object variable.
+ This is allowed only in the value cell of a symbol,
+ and it means that the symbol's value really lives in the
+ specified variable.
+ obj.v.objfwd points to the Lisp_Object variable. */
+ Lisp_Objfwd,
+
+ /* was Lisp_Internal */
+ Lisp_Object_Unused_2,
+
+ /* Used when a FILE * value needs to be passed
+ in an argument of type Lisp_Object.
+ You must do (FILE *) obj.v.integer to get the value.
+ The user will never see this data type. */
+ Lisp_Internal_Stream,
+
+ /* Used in a symbol value cell when the symbol's value is per-buffer.
+ The actual contents are a cons cell which starts a list like this:
+ (REALVALUE BUFFER CURRENT-ALIST-ELEMENT . DEFAULT-VALUE)).
+
+ BUFFER is the last buffer for which this symbol's value was
+ made up to date.
+
+ CURRENT-ALIST-ELEMENT is a pointer to an element of BUFFER's
+ b_local_var_alist, that being the element whose car is this variable.
+ Or it can be a pointer to the (CURRENT-ALIST-ELEMENT . DEFAULT-VALUE), if BUFFER
+ does not have an element in its alist for this variable
+ (that is, if BUFFER sees the default value of this variable).
+
+ If we want to examine or set the value and BUFFER is current,
+ we just examine or set REALVALUE.
+ If BUFFER is not current, we store the current REALVALUE value into
+ CURRENT-ALIST-ELEMENT, then find the appropriate alist element for
+ the buffer now current and set up CURRENT-ALIST-ELEMENT.
+ Then we set REALVALUE out of that element, and store into BUFFER.
+
+ If we are setting the variable and the current buffer does not have
+ an alist entry for this variable, an alist entry is created.
+
+ Note that REALVALUE can be a forwarding pointer.
+ Each time it is examined or set, forwarding must be done. */
+ Lisp_Buffer_Local_Value,
+
+ /* Like Lisp_Buffer_Local_Value with one difference:
+ merely setting the variable while some buffer is current
+ does not cause that buffer to have its own local value of this variable.
+ Only make-local-variable does that. */
+ Lisp_Some_Buffer_Local_Value,
+
+
+ /* Like Lisp_Objfwd except that value lives in a slot
+ in the current buffer. Value is byte index of slot within buffer */
+ Lisp_Buffer_Objfwd,
+
+ /* In symbol value cell, means var is unbound.
+ In symbol function cell, means function name is undefined. */
+ Lisp_Void,
+
+ /* Window used for Emacs display.
+ Data inside looks like a Lisp_Vector. */
+ Lisp_Window,
+
+ /* Used by save,set,restore-window-configuration */
+ Lisp_Window_Configuration
+ };
+
+#ifndef NO_UNION_TYPE
+
+#ifndef BIG_ENDIAN
+
+/* Definition of Lisp_Object for little-endian machines. */
+
+typedef
+union Lisp_Object
+ {
+ /* Used for comparing two Lisp_Objects;
+ also, positive integers can be accessed fast this way. */
+ int i;
+
+ struct
+ {
+ int val: 24;
+ char type;
+ } s;
+ struct
+ {
+ unsigned int val: 24;
+ char type;
+ } u;
+ struct
+ {
+ unsigned int val: 24;
+ enum Lisp_Type type: 7;
+ /* The markbit is not really part of the value of a Lisp_Object,
+ and is always zero except during garbage collection. */
+ unsigned int markbit: 1;
+ } gu;
+ }
+Lisp_Object;
+
+#else /* If BIG_ENDIAN */
+
+typedef
+union Lisp_Object
+ {
+ /* Used for comparing two Lisp_Objects;
+ also, positive integers can be accessed fast this way. */
+ int i;
+
+ struct
+ {
+ char type;
+ int val: 24;
+ } s;
+ struct
+ {
+ char type;
+ unsigned int val: 24;
+ } u;
+ struct
+ {
+ /* The markbit is not really part of the value of a Lisp_Object,
+ and is always zero except during garbage collection. */
+ unsigned int markbit: 1;
+ enum Lisp_Type type: 7;
+ unsigned int val: 24;
+ } gu;
+ }
+Lisp_Object;
+
+#endif /* BIG_ENDIAN */
+
+#endif /* NO_UNION_TYPE */
+
+
+/* If union type is not wanted, define Lisp_Object as just a number
+ and define the macros below to extract fields by shifting */
+
+#ifdef NO_UNION_TYPE
+
+#define Lisp_Object int
+
+/* These values are overridden by the m- file on some machines. */
+#ifndef VALBITS
+#define VALBITS 24
+#endif
+
+#ifndef GCTYPEBITS
+#define GCTYPEBITS 7
+#endif
+
+#ifndef VALMASK
+#define VALMASK ((1<<VALBITS) - 1)
+#endif
+#define GCTYPEMASK ((1<<GCTYPEBITS) - 1)
+#define MARKBIT (1 << (VALBITS + GCTYPEBITS))
+
+#endif /* NO_UNION_TYPE */
+
+/* These macros extract various sorts of values from a Lisp_Object.
+ For example, if tem is a Lisp_Object whose type is Lisp_Cons,
+ XCONS (tem) is the struct Lisp_Cons * pointing to the memory for that cons. */
+
+#ifdef NO_UNION_TYPE
+
+/* One need to override this if there must be high bits set in data space
+ (doing the result of the below & ((1 << (GCTYPE + 1)) - 1) would work
+ on all machines, but would penalise machines which don't need it)
+ */
+#ifndef XTYPE
+#define XTYPE(a) ((enum Lisp_Type) ((a) >> VALBITS))
+#endif
+
+#ifndef XSETTYPE
+#define XSETTYPE(a, b) ((a) = XUINT (a) | ((int)(b) << VALBITS))
+#endif
+
+/* Use XFASTINT for fast retrieval and storage of integers known
+ to be positive. This takes advantage of the fact that Lisp_Int is 0. */
+#define XFASTINT(a) (a)
+
+/* Extract the value of a Lisp_Object as a signed integer. */
+
+#ifndef XINT /* Some machines need to do this differently. */
+#define XINT(a) (((a) << (INTBITS-VALBITS)) >> (INTBITS-VALBITS))
+#endif
+
+/* Extract the value as an unsigned integer. This is a basis
+ for exctacting it as a pointer to a structure in storage. */
+
+#ifndef XUINT
+#define XUINT(a) ((a) & VALMASK)
+#endif
+
+#ifdef HAVE_SHM
+/* In this representation, data is found in two widely separated segments. */
+#define XPNTR(a) \
+ (XUINT (a) | (XUINT (a) > PURESIZE ? DATA_SEG_BITS : PURE_SEG_BITS))
+#else /* not HAVE_SHM */
+#ifdef DATA_SEG_BITS
+/* This case is used for the rt-pc.
+ In the diffs I was given, it checked for ptr = 0
+ and did not adjust it in that case.
+ But I don't think that zero should ever be found
+ in a Lisp object whose data type says it points to something. */
+#define XPNTR(a) (XUINT (a) | DATA_SEG_BITS)
+#else /* not DATA_SEG_BITS */
+#define XPNTR(a) XUINT (a)
+#endif
+#endif /* not HAVE_SHM */
+
+#ifndef XSETINT
+#define XSETINT(a, b) ((a) = ((a) & ~VALMASK) | ((b) & VALMASK))
+#endif
+
+#ifndef XSETUINT
+#define XSETUINT(a, b) XSETINT (a, b)
+#endif
+
+#ifndef XSETPNTR
+#define XSETPNTR(a, b) XSETINT (a, b)
+#endif
+
+#ifndef XSET
+#define XSET(var, type, ptr) \
+ ((var) = ((int)(type) << VALBITS) + ((int) (ptr) & VALMASK))
+#endif
+
+/* During garbage collection, XGCTYPE must be used for extracting types
+ so that the mark bit is ignored. XMARKBIT access the markbit.
+ Markbits are used only in particular slots of particular structure types.
+ Other markbits are always zero.
+ Outside of garbage collection, all mark bits are always zero. */
+
+#ifndef XGCTYPE
+#define XGCTYPE(a) ((enum Lisp_Type) (((a) >> VALBITS) & GCTYPEMASK))
+#endif
+
+/* In version 19, try
+#if VALBITS + GCTYPEBITS == INTBITS - 1
+#define XMARKBIT(a) ((a) < 0)
+#define XSETMARKBIT(a,b) ((a) = ((a) & ~MARKBIT) | ((b) ? MARKBIT : 0))
+*/
+
+#ifndef XMARKBIT
+#define XMARKBIT(a) ((a) & MARKBIT)
+#endif
+
+#ifndef XSETMARKBIT
+#define XSETMARKBIT(a,b) ((a) = ((a) & ~MARKBIT) | (b))
+#endif
+
+#ifndef XMARK
+#define XMARK(a) ((a) |= MARKBIT)
+#endif
+
+#ifndef XUNMARK
+#define XUNMARK(a) ((a) &= ~MARKBIT)
+#endif
+
+#endif /* NO_UNION_TYPE */
+
+#ifndef NO_UNION_TYPE
+
+#define XTYPE(a) ((enum Lisp_Type) (a).u.type)
+#define XSETTYPE(a, b) ((a).u.type = (char) (b))
+
+/* Use XFASTINT for fast retrieval and storage of integers known
+ to be positive. This takes advantage of the fact that Lisp_Int is 0. */
+#define XFASTINT(a) ((a).i)
+
+#ifdef EXPLICIT_SIGN_EXTEND
+/* Make sure we sign-extend; compilers have been known to fail to do so. */
+#define XINT(a) (((a).i << 8) >> 8)
+#else
+#define XINT(a) ((a).s.val)
+#endif /* EXPLICIT_SIGN_EXTEND */
+
+#define XUINT(a) ((a).u.val)
+#define XPNTR(a) ((a).u.val)
+#define XSETINT(a, b) ((a).s.val = (int) (b))
+#define XSETUINT(a, b) ((a).s.val = (int) (b))
+#define XSETPNTR(a, b) ((a).s.val = (int) (b))
+
+#define XSET(var, vartype, ptr) \
+ (((var).s.type = ((char) (vartype))), ((var).s.val = ((int) (ptr))))
+
+/* During garbage collection, XGCTYPE must be used for extracting types
+ so that the mark bit is ignored. XMARKBIT access the markbit.
+ Markbits are used only in particular slots of particular structure types.
+ Other markbits are always zero.
+ Outside of garbage collection, all mark bits are always zero. */
+
+#define XGCTYPE(a) ((a).gu.type)
+#define XMARKBIT(a) ((a).gu.markbit)
+#define XSETMARKBIT(a,b) (XMARKBIT(a) = (b))
+#define XMARK(a) (XMARKBIT(a) = 1)
+#define XUNMARK(a) (XMARKBIT(a) = 0)
+
+#endif /* NO_UNION_TYPE */
+
+
+#define XCONS(a) ((struct Lisp_Cons *) XPNTR(a))
+#define XBUFFER(a) ((struct buffer *) XPNTR(a))
+#define XVECTOR(a) ((struct Lisp_Vector *) XPNTR(a))
+#define XSUBR(a) ((struct Lisp_Subr *) XPNTR(a))
+#define XSTRING(a) ((struct Lisp_String *) XPNTR(a))
+#define XSYMBOL(a) ((struct Lisp_Symbol *) XPNTR(a))
+#define XFUNCTION(a) ((Lisp_Object (*)()) XPNTR(a))
+#define XMARKER(a) ((struct Lisp_Marker *) XPNTR(a))
+#define XOBJFWD(a) ((Lisp_Object *) XPNTR(a))
+#define XINTPTR(a) ((int *) XPNTR(a))
+#define XWINDOW(a) ((struct window *) XPNTR(a))
+#define XPROCESS(a) ((struct Lisp_Process *) XPNTR(a))
+
+#define XSETCONS(a, b) XSETPNTR(a, (int) (b))
+#define XSETBUFFER(a, b) XSETPNTR(a, (int) (b))
+#define XSETVECTOR(a, b) XSETPNTR(a, (int) (b))
+#define XSETSUBR(a, b) XSETPNTR(a, (int) (b))
+#define XSETSTRING(a, b) XSETPNTR(a, (int) (b))
+#define XSETSYMBOL(a, b) XSETPNTR(a, (int) (b))
+#define XSETFUNCTION(a, b) XSETPNTR(a, (int) (b))
+#define XSETMARKER(a, b) XSETPNTR(a, (int) (b))
+#define XSETOBJFWD(a, b) XSETPNTR(a, (int) (b))
+#define XSETINTPTR(a, b) XSETPNTR(a, (int) (b))
+#define XSETWINDOW(a, b) XSETPNTR(a, (int) (b))
+#define XSETPROCESS(a, b) XSETPNTR(a, (int) (b))
+
+/* In a cons, the markbit of the car is the gc mark bit */
+
+struct Lisp_Cons
+ {
+ Lisp_Object car, cdr;
+ };
+
+/* Like a cons, but records info on where the text lives that it was read from */
+/* This is not really in use now */
+
+struct Lisp_Buffer_Cons
+ {
+ Lisp_Object car, cdr;
+ struct buffer *buffer;
+ int bufpos;
+ };
+
+/* In a string or vector, the sign bit of the `size' is the gc mark bit */
+
+struct Lisp_String
+ {
+ int size;
+ unsigned char data[1];
+ };
+
+struct Lisp_Vector
+ {
+ int size;
+ struct Lisp_Vector *next;
+ Lisp_Object contents[1];
+ };
+
+/* In a symbol, the markbit of the plist is used as the gc mark bit */
+
+struct Lisp_Symbol
+ {
+ struct Lisp_String *name;
+ Lisp_Object value;
+ Lisp_Object function;
+ Lisp_Object plist;
+ struct Lisp_Symbol *next; /* -> next symbol in this obarray bucket */
+ };
+
+struct Lisp_Subr
+ {
+ Lisp_Object (*function) ();
+ short min_args, max_args;
+ char *symbol_name;
+ char *prompt;
+ char *doc;
+ };
+
+/* In a marker, the markbit of the chain field is used as the gc mark bit */
+
+struct Lisp_Marker
+ {
+ struct buffer *buffer;
+ Lisp_Object chain;
+ int bufpos;
+ };
+
+/* Data type checking */
+
+#ifdef NULL
+#undef NULL
+#endif
+#define NULL(x) (XFASTINT (x) == XFASTINT (Qnil))
+/* #define LISTP(x) (XTYPE ((x)) == Lisp_Cons)*/
+#define CONSP(x) (XTYPE ((x)) == Lisp_Cons)
+#define EQ(x, y) (XFASTINT (x) == XFASTINT (y))
+
+#define CHECK_LIST(x, i) \
+ { if ((XTYPE ((x)) != Lisp_Cons) && !NULL (x)) x = wrong_type_argument (Qlistp, (x)); }
+
+#define CHECK_STRING(x, i) \
+ { if (XTYPE ((x)) != Lisp_String) x = wrong_type_argument (Qstringp, (x)); }
+
+#define CHECK_CONS(x, i) \
+ { if (XTYPE ((x)) != Lisp_Cons) x = wrong_type_argument (Qconsp, (x)); }
+
+#define CHECK_SYMBOL(x, i) \
+ { if (XTYPE ((x)) != Lisp_Symbol) x = wrong_type_argument (Qsymbolp, (x)); }
+
+#define CHECK_VECTOR(x, i) \
+ { if (XTYPE ((x)) != Lisp_Vector) x = wrong_type_argument (Qvectorp, (x)); }
+
+#define CHECK_BUFFER(x, i) \
+ { if (XTYPE ((x)) != Lisp_Buffer) x = wrong_type_argument (Qbufferp, (x)); }
+
+#define CHECK_WINDOW(x, i) \
+ { if (XTYPE ((x)) != Lisp_Window) x = wrong_type_argument (Qwindowp, (x)); }
+
+#define CHECK_PROCESS(x, i) \
+ { if (XTYPE ((x)) != Lisp_Process) x = wrong_type_argument (Qprocessp, (x)); }
+
+#define CHECK_NUMBER(x, i) \
+ { if (XTYPE ((x)) != Lisp_Int) x = wrong_type_argument (Qintegerp, (x)); }
+
+#define CHECK_MARKER(x, i) \
+ { if (XTYPE ((x)) != Lisp_Marker) x = wrong_type_argument (Qmarkerp, (x)); }
+
+#define CHECK_NUMBER_COERCE_MARKER(x, i) \
+ { if (XTYPE ((x)) == Lisp_Marker) XFASTINT (x) = marker_position (x); \
+ else if (XTYPE ((x)) != Lisp_Int) x = wrong_type_argument (Qinteger_or_marker_p, (x)); }
+
+#ifdef VIRT_ADDR_VARIES
+
+/* For machines like APOLLO where text and data can go anywhere
+ in virtual memory. */
+#define CHECK_IMPURE(obj) \
+ { extern int pure[]; \
+ if ((PNTR_COMPARISON_TYPE) XPNTR (obj) < (PNTR_COMPARISON_TYPE) ((char *) pure + PURESIZE) \
+ && (PNTR_COMPARISON_TYPE) XPNTR (obj) >= (PNTR_COMPARISON_TYPE) pure) \
+ pure_write_error (); }
+
+#else /* not VIRT_ADDR_VARIES */
+#ifdef PNTR_COMPARISON_TYPE
+
+/* when PNTR_COMPARISON_TYPE is not the default (unsigned int) */
+#define CHECK_IMPURE(obj) \
+ { extern int my_edata; \
+ if ((PNTR_COMPARISON_TYPE) XPNTR (obj) < (PNTR_COMPARISON_TYPE) &my_edata) \
+ pure_write_error (); }
+
+#else /* not VIRT_ADDRESS_VARIES, not PNTR_COMPARISON_TYPE */
+
+#define CHECK_IMPURE(obj) \
+ { extern int my_edata; \
+ if (XPNTR (obj) < (unsigned int) &my_edata) \
+ pure_write_error (); }
+
+#endif /* PNTR_COMPARISON_TYPE */
+#endif /* VIRT_ADDRESS_VARIES */
+
+/* Cast pointers to this type to compare them. Some machines want int. */
+#ifndef PNTR_COMPARISON_TYPE
+#define PNTR_COMPARISON_TYPE unsigned int
+#endif
+
+/* Define a built-in function for calling from Lisp.
+ `lname' should be the name to give the function in Lisp,
+ as a null-terminated C string.
+ `fnname' should be the name of the function in C.
+ By convention, it starts with F.
+ `sname' should be the name for the C constant structure
+ that records information on this function for internal use.
+ By convention, it should be the same as `fnname' but with S instead of F.
+ It's too bad that C macros can't compute this from `fnname'.
+ `minargs' should be a number, the minimum number of arguments allowed.
+ `maxargs' should be a number, the maximum number of arguments allowed,
+ or else MANY or UNEVALLED.
+ MANY means pass a vector of evaluated arguments,
+ in the form of an integer number-of-arguments
+ followed by the address of a vector of Lisp_Objects
+ which contains the argument values.
+ UNEVALLED means pass the list of unevaluated arguments
+ `prompt' says how to read arguments for an interactive call.
+ This can be zero or a C string.
+ Zero means that interactive calls are not allowed.
+ A string is interpreted in a hairy way:
+ it should contain one line for each argument to be read, terminated by \n.
+ The first character of the line controls the type of parsing:
+ s -- read a string.
+ S -- read a symbol.
+ k -- read a key sequence and return it as a string.
+ a -- read a function name (symbol) with completion.
+ C -- read a command name (symbol) with completion.
+ v -- read a variable name (symbol) with completion.
+ b -- read a buffer name (a string) with completion.
+ B -- buffer name, may be existing buffer or may not be.
+ f -- read a file name, file must exist.
+ F -- read a file name, file need not exist.
+ n -- read a number.
+ c -- read a character and return it as a number.
+ p -- use the numeric value of the prefix argument.
+ P -- use raw value of prefix - can be nil, -, (NUMBER) or NUMBER.
+ x -- read a Lisp object from the minibuffer.
+ X -- read a Lisp form from the minibuffer and use its value.
+ A null string means call interactively with no arguments.
+ `doc' is documentation for the user.
+*/
+
+#define DEFUN(lname, fnname, sname, minargs, maxargs, prompt, doc) \
+ Lisp_Object fnname (); \
+ struct Lisp_Subr sname = {fnname, minargs, maxargs, lname, prompt, 0}; \
+ Lisp_Object fnname
+
+/* defsubr (Sname);
+ is how we define the symbol for function `name' at start-up time. */
+extern void defsubr ();
+
+#define MANY -2
+#define UNEVALLED -1
+
+/* Macros we use to define forwarded Lisp variables.
+ These are used in the syms_of_FILENAME functions. */
+
+#define DEFVARLISP(lname, vname, doc) defvar_lisp (lname, vname)
+#define DEFVARBOOL(lname, vname, doc) defvar_bool (lname, vname)
+#define DEFVARINT(lname, vname, doc) defvar_int (lname, vname)
+#define DEFVARPERBUFFER(lname, vname, doc) \
+ defvar_per_buffer (lname, vname, 0)
+
+#define DEFVAR_LISP(lname, vname, doc) defvar_lisp (lname, vname)
+#define DEFVAR_LISP_NOPRO(lname, vname, doc) defvar_lisp_nopro (lname, vname)
+#define DEFVAR_BOOL(lname, vname, doc) defvar_bool (lname, vname)
+#define DEFVAR_INT(lname, vname, doc) defvar_int (lname, vname)
+#define DEFVAR_PER_BUFFER(lname, vname, doc) \
+ defvar_per_buffer (lname, vname, 0)
+
+/* Structure for recording Lisp call stack for backtrace purposes */
+
+struct specbinding
+ {
+ Lisp_Object symbol, old_value;
+ Lisp_Object (*func) ();
+ Lisp_Object unused; /* Dividing by 16 is faster than by 12 */
+ };
+
+extern struct specbinding *specpdl;
+extern struct specbinding *specpdl_ptr;
+extern int specpdl_size;
+
+struct handler
+ {
+ Lisp_Object handler;
+ Lisp_Object var;
+ int poll_suppress_count; /* No error should exit a piece of code
+ in which polling is suppressed. */
+ struct catchtag *tag;
+ struct handler *next;
+ };
+
+extern struct handler *handlerlist;
+
+/* Check quit-flag and quit if it is non-nil. */
+
+#define QUIT \
+ if (!NULL (Vquit_flag) && NULL (Vinhibit_quit)) \
+ { Vquit_flag = Qnil; Fsignal (Qquit, Qnil); }
+
+/* Nonzero if ought to quit now. */
+
+#define QUITP (!NULL (Vquit_flag) && NULL (Vinhibit_quit))
+
+/* 1 if CH is upper case. */
+
+#define UPPERCASEP(CH) (downcase_table[CH] != (CH))
+
+/* 1 if CH is lower case. */
+
+#define LOWERCASEP(CH) \
+ (downcase_table[CH] == (CH) && downcase_table[0400 + (CH)] != (CH))
+
+/* 1 if CH is neither upper nor lower case. */
+
+#define NOCASEP(CH) (downcase_table[0400 + (CH)] == (CH))
+
+/* Upcase a character, or make no change if that cannot be done. */
+
+#define UPCASE(CH) (downcase_table[CH] == (CH) ? UPCASE1 (CH) : (CH))
+
+/* Upcase a character known to be not upper case. */
+
+#define UPCASE1(CH) downcase_table[0400 + (CH)]
+
+/* Downcase a character, or make no change if that cannot be done. */
+
+#define DOWNCASE(CH) downcase_table[CH]
+
+/* number of bytes of structure consed since last GC */
+
+extern int consing_since_gc;
+
+/* threshold for doing another gc */
+
+extern int gc_cons_threshold;
+
+/* value of consing_since_gc when undos were last truncated. */
+
+extern int consing_at_last_truncate;
+
+/* Structure for recording stack slots that need marking */
+
+/* This is a chain of structures, each of which points at a Lisp_Object variable
+ whose value should be marked in garbage collection.
+ Normally every link of the chain is an automatic variable of a function,
+ and its `val' points to some argument or local variable of the function.
+ On exit to the function, the chain is set back to the value it had on entry.
+ This way, no link remains in the chain when the stack frame containing the link disappears.
+
+ Every function that can call Feval must protect in this fashion all
+ Lisp_Object variables whose contents will be used again. */
+
+extern struct gcpro *gcprolist;
+
+struct gcpro
+ {
+ struct gcpro *next;
+ Lisp_Object *var; /* Address of first protected variable */
+ int nvars; /* Number of consecutive protected variables */
+ };
+
+#define GCPRO1(varname) \
+ {gcpro1.next = gcprolist; gcpro1.var = &varname; gcpro1.nvars = 1; \
+ gcprolist = &gcpro1; }
+
+#define GCPRO2(varname1, varname2) \
+ {gcpro1.next = gcprolist; gcpro1.var = &varname1; gcpro1.nvars = 1; \
+ gcpro2.next = &gcpro1; gcpro2.var = &varname2; gcpro2.nvars = 1; \
+ gcprolist = &gcpro2; }
+
+#define GCPRO3(varname1, varname2, varname3) \
+ {gcpro1.next = gcprolist; gcpro1.var = &varname1; gcpro1.nvars = 1; \
+ gcpro2.next = &gcpro1; gcpro2.var = &varname2; gcpro2.nvars = 1; \
+ gcpro3.next = &gcpro2; gcpro3.var = &varname3; gcpro3.nvars = 1; \
+ gcprolist = &gcpro3; }
+
+#define GCPRO4(varname1, varname2, varname3, varname4) \
+ {gcpro1.next = gcprolist; gcpro1.var = &varname1; gcpro1.nvars = 1; \
+ gcpro2.next = &gcpro1; gcpro2.var = &varname2; gcpro2.nvars = 1; \
+ gcpro3.next = &gcpro2; gcpro3.var = &varname3; gcpro3.nvars = 1; \
+ gcpro4.next = &gcpro3; gcpro4.var = &varname4; gcpro4.nvars = 1; \
+ gcprolist = &gcpro4; }
+
+/* Call staticpro (&var) to protect static variable `var'. */
+
+void staticpro();
+
+#define UNGCPRO (gcprolist = gcpro1.next)
+
+/* Defined in data.c */
+extern Lisp_Object Qnil, Qt, Qquote, Qlambda, Qsubr, Qunbound;
+extern Lisp_Object Qerror_conditions, Qerror_message, Qtop_level;
+extern Lisp_Object Qerror, Qquit, Qwrong_type_argument, Qargs_out_of_range;
+extern Lisp_Object Qvoid_variable, Qvoid_function;
+extern Lisp_Object Qsetting_constant, Qinvalid_read_syntax;
+extern Lisp_Object Qinvalid_function, Qwrong_number_of_arguments, Qno_catch;
+extern Lisp_Object Qend_of_file, Qarith_error;
+extern Lisp_Object Qbeginning_of_buffer, Qend_of_buffer, Qbuffer_read_only;
+
+extern Lisp_Object Qintegerp, Qnatnump, Qsymbolp, Qlistp, Qconsp;
+extern Lisp_Object Qstringp, Qarrayp, Qsequencep, Qbufferp;
+extern Lisp_Object Qchar_or_string_p, Qmarkerp, Qvectorp;
+extern Lisp_Object Qinteger_or_marker_p, Qboundp, Qfboundp;
+extern Lisp_Object Qcdr;
+
+extern Lisp_Object Feq (), Fnull (), Flistp (), Fconsp (), Fatom (), Fnlistp ();
+extern Lisp_Object Fintegerp (), Fnatnump (), Fsymbolp ();
+extern Lisp_Object Fvectorp (), Fstringp (), Farrayp (), Fsequencep ();
+extern Lisp_Object Fbufferp (), Fmarkerp (), Fsubrp (), Fchar_or_string_p ();
+extern Lisp_Object Finteger_or_marker_p ();
+
+extern Lisp_Object Fcar (), Fcar_safe(), Fcdr (), Fcdr_safe();
+extern Lisp_Object Fsetcar (), Fsetcdr ();
+extern Lisp_Object Fboundp (), Ffboundp (), Fmakunbound (), Ffmakunbound ();
+extern Lisp_Object Fsymbol_function (), Fsymbol_plist (), Fsymbol_name ();
+extern Lisp_Object Ffset (), Fsetplist ();
+extern Lisp_Object Fsymbol_value (), Fset ();
+extern Lisp_Object Fdefault_value (), Fset_default ();
+
+extern Lisp_Object Faref (), Faset (), Farray_length ();
+
+extern Lisp_Object Fstring_to_int (), Fint_to_string ();
+extern Lisp_Object Feqlsign (), Fgtr (), Flss (), Fgeq (), Fleq (), Fneq (), Fzerop ();
+extern Lisp_Object Fplus (), Fminus (), Ftimes (), Fquo (), Frem (), Fmax (), Fmin ();
+extern Lisp_Object Flogand (), Flogior (), Flogxor (), Flognot (), Flsh (), Fash ();
+extern Lisp_Object Fadd1 (), Fsub1 ();
+
+extern Lisp_Object make_number ();
+extern void args_out_of_range ();
+extern void args_out_of_range_3 ();
+extern Lisp_Object wrong_type_argument ();
+
+/* Defined in fns.c */
+extern Lisp_Object Qstring_lessp;
+extern Lisp_Object Vfeatures;
+extern Lisp_Object Fidentity (), Frandom ();
+extern Lisp_Object Flength ();
+extern Lisp_Object Fappend (), Fconcat (), Fvconcat (), Fcopy_sequence ();
+extern Lisp_Object Fsubstring ();
+extern Lisp_Object Fnthcdr (), Fmemq (), Fassq (), Fassoc ();
+extern Lisp_Object Frassq (), Fdelq (), Fsort ();
+extern Lisp_Object Freverse (), Fnreverse (), Fget (), Fput (), Fequal ();
+extern Lisp_Object Ffillarray (), Fnconc (), Fmapcar (), Fmapconcat ();
+extern Lisp_Object Fy_or_n_p (), Fyes_or_no_p ();
+extern Lisp_Object Ffeaturep (), Frequire () , Fprovide ();
+extern Lisp_Object concat2 (), nconc2 ();
+extern Lisp_Object assq_no_quit ();
+
+/* Defined in alloc.c */
+extern Lisp_Object Vpurify_flag;
+extern Lisp_Object Fcons (), Flist(), Fmake_list ();
+extern Lisp_Object Fmake_vector (), Fvector (), Fmake_symbol (), Fmake_marker ();
+extern Lisp_Object Fmake_string (), build_string (), make_string();
+extern Lisp_Object Fpurecopy (), make_pure_string ();
+extern Lisp_Object pure_cons (), make_pure_vector ();
+extern Lisp_Object Fgarbage_collect ();
+
+/* Defined in print.c */
+extern Lisp_Object Vprin1_to_string_buffer;
+extern Lisp_Object Fprin1 (), Fprin1_to_string (), Fprinc ();
+extern Lisp_Object Fterpri (), Fprint ();
+extern Lisp_Object Vstandard_output, Qstandard_output;
+extern temp_output_buffer_setup (), temp_output_buffer_show ();
+
+/* Defined in lread.c */
+extern Lisp_Object Qvariable_documentation, Qstandard_input;
+extern Lisp_Object Vobarray, Vstandard_input;
+extern Lisp_Object Fread (), Fread_from_string ();
+extern Lisp_Object Fintern (), Fintern_soft (), Fload ();
+extern Lisp_Object Fget_file_char (), Fread_char ();
+extern Lisp_Object Feval_current_buffer (), Feval_region ();
+extern Lisp_Object intern (), oblookup ();
+
+/* Defined in eval.c */
+extern Lisp_Object Qautoload, Qexit, Qinteractive, Qcommandp, Qdefun, Qmacro;
+extern Lisp_Object Vinhibit_quit, Vquit_flag, Qinhibit_quit;
+extern Lisp_Object Vmocklisp_arguments, Qmocklisp, Qmocklisp_arguments;
+extern Lisp_Object Vautoload_queue;
+extern Lisp_Object Fand (), For (), Fif (), Fprogn (), Fprog1 (), Fprog2 ();
+extern Lisp_Object Fsetq (), Fquote ();
+extern Lisp_Object Fuser_variable_p (), Finteractive_p ();
+extern Lisp_Object Fdefun (), Flet (), FletX (), Fwhile ();
+extern Lisp_Object Fcatch (), Fthrow (), Funwind_protect ();
+extern Lisp_Object Fcondition_case (), Fsignal ();
+extern Lisp_Object Ffunction_type (), Fautoload (), Fcommandp ();
+extern Lisp_Object Feval (), Fapply (), Ffuncall ();
+extern Lisp_Object Fglobal_set (), Fglobal_value (), Fbacktrace ();
+extern Lisp_Object apply1 (), call0 (), call1 (), call2 (), call3 ();
+extern Lisp_Object apply_lambda ();
+extern Lisp_Object internal_catch ();
+extern Lisp_Object internal_condition_case ();
+extern void unbind_to ();
+extern void error ();
+extern Lisp_Object un_autoload ();
+
+/* Defined in editfns.c */
+extern Lisp_Object Vprefix_arg, Qminus, Vcurrent_prefix_arg;
+extern Lisp_Object Fgoto_char ();
+extern Lisp_Object Fpoint_min_marker (), Fpoint_max_marker ();
+extern Lisp_Object Fpoint_min (), Fpoint_max ();
+extern Lisp_Object Fpoint (), Fpoint_marker (), Fmark_marker ();
+extern Lisp_Object Ffollchar (), Fprevchar (), Fchar_after (), Finsert ();
+extern Lisp_Object Feolp (), Feobp (), Fbolp (), Fbobp ();
+extern Lisp_Object Fformat (), format1 ();
+extern Lisp_Object Fbuffer_substring (), Fbuffer_string ();
+extern Lisp_Object Fstring_equal (), Fstring_lessp (), Fbuffer_substring_lessp ();
+extern Lisp_Object save_excursion_save (), save_restriction_save ();
+extern Lisp_Object save_excursion_restore (), save_restriction_restore ();
+extern Lisp_Object Fchar_to_string ();
+
+/* defined in buffer.c */
+extern Lisp_Object Vbuffer_alist;
+extern Lisp_Object Fget_buffer (), Fget_buffer_create (), Fset_buffer ();
+extern Lisp_Object Fbarf_if_buffer_read_only ();
+extern Lisp_Object Fcurrent_buffer (), Fswitch_to_buffer (), Fpop_to_buffer ();
+extern Lisp_Object Fother_buffer ();
+extern struct buffer *all_buffers;
+
+/* defined in marker.c */
+
+extern Lisp_Object Fmarker_position (), Fmarker_buffer ();
+extern Lisp_Object Fcopy_marker ();
+
+/* Defined in fileio.c */
+
+extern Lisp_Object Qfile_error;
+extern Lisp_Object Ffile_name_as_directory ();
+extern Lisp_Object Fexpand_file_name (), Ffile_name_nondirectory ();
+extern Lisp_Object Fsubstitute_in_file_name ();
+extern Lisp_Object Ffile_symlink_p ();
+
+/* Defined in abbrev.c */
+
+extern Lisp_Object Vfundamental_mode_abbrev_table;
+
+/* defined in search.c */
+extern unsigned char downcase_table[];
+extern Lisp_Object Fstring_match ();
+extern Lisp_Object Fscan_buffer ();
+
+/* defined in minibuf.c */
+
+extern Lisp_Object last_minibuf_string, Vminibuffer_list;
+extern Lisp_Object read_minibuf (), Fcompleting_read ();
+extern Lisp_Object Fread_from_minibuffer ();
+extern Lisp_Object Fread_variable ();
+extern Lisp_Object Fread_minibuffer (), Feval_minibuffer ();
+extern Lisp_Object Fread_string (), Fread_file_name ();
+extern Lisp_Object Fread_no_blanks_input ();
+
+/* Defined in callint.c */
+
+extern Lisp_Object Vcommand_history;
+extern Lisp_Object Qcall_interactively;
+extern Lisp_Object Fcall_interactively ();
+extern Lisp_Object Fprefix_numeric_value ();
+
+/* defined in casefiddle.c */
+
+extern Lisp_Object Fdowncase (), Fupcase (), Fcapitalize ();
+
+/* defined in keyboard.c */
+
+extern Lisp_Object Vhelp_form, Vtop_level;
+extern Lisp_Object Fdiscard_input (), Frecursive_edit ();
+extern Lisp_Object Fcommand_execute (), Finput_pending_p ();
+extern int poll_suppress_count;
+
+/* defined in keymap.c */
+
+extern Lisp_Object Qkeymap;
+extern Lisp_Object Fkey_description (), Fsingle_key_description ();
+extern Lisp_Object Fwhere_is_internal ();
+extern Lisp_Object access_keymap (), store_in_keymap ();
+extern Lisp_Object get_keyelt (), get_keymap();
+
+/* defined in indent.c */
+extern Lisp_Object Fvertical_motion (), Findent_to (), Fcurrent_column ();
+
+/* defined in window.c */
+extern Lisp_Object Qwindowp;
+extern Lisp_Object Fget_buffer_window ();
+extern Lisp_Object Fsave_window_excursion ();
+extern Lisp_Object Fset_window_configuration (), Fcurrent_window_configuration ();
+
+/* defined in emacs.c */
+extern Lisp_Object decode_env_path ();
+/* Nonzero means don't do interactive redisplay and don't change tty modes */
+extern int noninteractive;
+/* Nonzero means don't do use window-system-specific display code */
+extern int inhibit_window_system;
+
+/* defined in process.c */
+extern Lisp_Object Fget_process (), Fget_buffer_process (), Fprocessp ();
+extern Lisp_Object Fprocess_status (), Fkill_process ();
+
+/* defined in callproc.c */
+extern Lisp_Object Vexec_path, Vexec_directory;
+
+#ifdef MAINTAIN_ENVIRONMENT
+/* defined in environ.c */
+extern int size_of_current_environ ();
+extern void get_current_environ ();
+/* extern void current_environ (); */
+extern Lisp_Object Fgetenv ();
+#endif /* MAINTAIN_ENVIRONMENT */
+
+/* defined in doc.c */
+extern Lisp_Object Vdoc_file_name;
+extern Lisp_Object Fsubstitute_command_keys ();
+extern Lisp_Object Fdocumentation (), Fdocumentation_property ();
+
+/* defined in bytecode.c */
+extern Lisp_Object Qbytecode;
+
+/* defined in macros.c */
+extern Lisp_Object Fexecute_kbd_macro ();
+
+/* Nonzero means Emacs has already been initialized.
+ Used during startup to detect startup of dumped Emacs. */
+extern int initialized;
+
+extern int immediate_quit; /* Nonzero means ^G can quit instantly */
+
+extern void debugger ();
+
+extern char *malloc (), *realloc (), *getenv (), *ctime (), *getwd ();
+extern long *xmalloc (), *xrealloc ();
+
+#ifdef MAINTAIN_ENVIRONMENT
+extern unsigned char *egetenv ();
+#else
+#define egetenv getenv
+#endif
diff --git a/src/lread.c b/src/lread.c
new file mode 100644
index 00000000000..0c9bc8fe913
--- /dev/null
+++ b/src/lread.c
@@ -0,0 +1,1328 @@
+/* Lisp parsing and input streams.
+ Copyright (C) 1985, 1986, 1987 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#undef NULL
+#include "config.h"
+#include "lisp.h"
+
+#ifndef standalone
+#include "buffer.h"
+#include "paths.h"
+#endif
+
+#ifdef lint
+#include <sys/inode.h>
+#endif /* lint */
+
+#include "filetypes.h"
+
+#ifndef X_OK
+#define X_OK 01
+#endif
+
+Lisp_Object Qread_char, Qget_file_char, Qstandard_input;
+Lisp_Object Qvariable_documentation, Vvalues, Vstandard_input;
+
+/* non-zero if inside `load' */
+int load_in_progress;
+
+/* Search path for files to be loaded. */
+Lisp_Object Vload_path;
+
+/* File for get_file_char to read from. Use by load */
+static FILE *instream;
+
+/* When nonzero, read conses in pure space */
+static int read_pure;
+
+/* For use within read-from-string (this reader is non-reentrant!!) */
+static int read_from_string_index;
+static int read_from_string_limit;
+
+/* Handle unreading and rereading of characters.
+ Write READCHAR to read a character, UNREAD(c) to unread c to be read again. */
+
+static int unrch;
+
+static int readchar (readcharfun)
+ Lisp_Object readcharfun;
+{
+ Lisp_Object tem;
+ register struct buffer *inbuffer;
+ register int c, mpos;
+
+ if (unrch >= 0)
+ {
+ c = unrch;
+ unrch = -1;
+ return c;
+ }
+ if (XTYPE (readcharfun) == Lisp_Buffer)
+ {
+ inbuffer = XBUFFER (readcharfun);
+
+ if (BUF_PT (inbuffer) >= BUF_ZV (inbuffer))
+ return -1;
+ c = *(unsigned char *) BUF_CHAR_ADDRESS (inbuffer, BUF_PT (inbuffer));
+ SET_BUF_PT (inbuffer, BUF_PT (inbuffer) + 1);
+ return c;
+ }
+ if (XTYPE (readcharfun) == Lisp_Marker)
+ {
+ inbuffer = XMARKER (readcharfun)->buffer;
+ mpos = marker_position (readcharfun);
+
+ if (mpos > BUF_ZV (inbuffer) - 1)
+ return -1;
+ c = *(unsigned char *) BUF_CHAR_ADDRESS (inbuffer, mpos);
+ if (mpos != BUF_GPT (inbuffer))
+ XMARKER (readcharfun)->bufpos++;
+ else
+ Fset_marker (readcharfun, make_number (mpos + 1),
+ Fmarker_buffer (readcharfun));
+ return c;
+ }
+ if (EQ (readcharfun, Qget_file_char))
+ return getc (instream);
+
+ if (XTYPE (readcharfun) == Lisp_String)
+ {
+ register int c;
+ /* This used to be return of a conditional expression,
+ but that truncated -1 to a char on VMS. */
+ if (read_from_string_index < read_from_string_limit)
+ c = XSTRING (readcharfun)->data[read_from_string_index++];
+ else
+ c = -1;
+ return c;
+ }
+
+ tem = call0 (readcharfun);
+
+ if (NULL (tem))
+ return -1;
+ return XINT (tem);
+}
+
+#define READCHAR readchar(readcharfun)
+#define UNREAD(c) (unrch = c)
+
+static Lisp_Object read0 (), read1 (), read_list (), read_vector ();
+static int read_escape ();
+
+/* get a character from the tty */
+
+DEFUN ("read-char", Fread_char, Sread_char, 0, 0, 0,
+ "Read a character from the command input (keyboard or macro).\n\
+It is returned as a number.")
+ ()
+{
+ register Lisp_Object val;
+
+#ifndef standalone
+ XSET (val, Lisp_Int, read_command_char (0));
+#else
+ XSET (val, Lisp_Int, getchar ());
+#endif
+
+ return val;
+}
+
+DEFUN ("get-file-char", Fget_file_char, Sget_file_char, 0, 0, 0,
+ "Don't use this yourself.")
+ ()
+{
+ register Lisp_Object val;
+ XSET (val, Lisp_Int, getc (instream));
+ return val;
+}
+
+static void readevalloop ();
+static Lisp_Object load_unwind ();
+
+DEFUN ("load", Fload, Sload, 1, 4, 0,
+ "Execute a file of Lisp code named FILE.\n\
+First tries FILE with .elc appended, then tries with .el,\n\
+ then tries FILE unmodified. Searches directories in load-path.\n\
+If optional second arg NOERROR is non-nil,\n\
+ report no error if FILE doesn't exist.\n\
+Print messages at start and end of loading unless\n\
+ optional third arg NOMESSAGE is non-nil.\n\
+If optional fourth arg NOSUFFIX is non-nil, don't try adding\n\
+ suffixes .elc or .el to the specified name FILE.\n\
+Return t if file exists.")
+ (str, noerror, nomessage, nosuffix)
+ Lisp_Object str, noerror, nomessage, nosuffix;
+{
+ register FILE *stream;
+ register int fd = -1;
+ register Lisp_Object lispstream;
+ register FILE **ptr;
+ int count = specpdl_ptr - specpdl;
+ struct gcpro gcpro1;
+
+ CHECK_STRING (str, 0);
+ str = Fsubstitute_in_file_name (str);
+
+ /* Avoid weird lossage with null string as arg,
+ since it would try to load a directory as a Lisp file */
+ if (XSTRING (str)->size > 0)
+ {
+ fd = openp (Vload_path, str, !NULL (nosuffix) ? "" : ".elc:.el:", 0, 0);
+ }
+
+ if (fd < 0)
+ if (NULL (noerror))
+ while (1)
+ Fsignal (Qfile_error, Fcons (build_string ("Cannot open load file"),
+ Fcons (str, Qnil)));
+ else return Qnil;
+
+ stream = fdopen (fd, "r");
+ if (stream == 0)
+ {
+ close (fd);
+ error ("Failure to create stdio stream for %s", XSTRING (str)->data);
+ }
+
+ if (NULL (nomessage))
+ message ("Loading %s...", XSTRING (str)->data);
+
+ GCPRO1 (str);
+ ptr = (FILE **) xmalloc (sizeof (FILE *));
+ *ptr = stream;
+ XSET (lispstream, Lisp_Internal_Stream, (int) ptr);
+ record_unwind_protect (load_unwind, lispstream);
+ load_in_progress++;
+ readevalloop (Qget_file_char, stream, Feval, 0);
+ unbind_to (count);
+ UNGCPRO;
+
+ if (!noninteractive && NULL (nomessage))
+ message ("Loading %s...done", XSTRING (str)->data);
+ return Qt;
+}
+
+static Lisp_Object
+load_unwind (stream) /* used as unwind-protect function in load */
+ Lisp_Object stream;
+{
+ fclose (*(FILE **) XSTRING (stream));
+ free (XPNTR (stream));
+ if (--load_in_progress < 0) load_in_progress = 0;
+ return Qnil;
+}
+
+
+static int
+absolute_filename_p (pathname)
+ Lisp_Object pathname;
+{
+ register unsigned char *s = XSTRING (pathname)->data;
+ return (*s == '~' || *s == '/'
+#ifdef VMS
+ || index (s, ':')
+#endif /* VMS */
+ );
+}
+
+/* Search for a file whose name is STR, looking in directories
+ in the Lisp list PATH, and trying suffixes from SUFFIX.
+ SUFFIX is a string containing possible suffixes separated by colons.
+ On success, returns a file descriptor. On failure, returns -1.
+
+ EXEC_ONLY nonzero means don't open the files,
+ just look for one that is executable. In this case,
+ returns 1 on success.
+
+ If STOREPTR is nonzero, 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. */
+
+int
+openp (path, str, suffix, storeptr, exec_only)
+ Lisp_Object path, str;
+ char *suffix;
+ Lisp_Object *storeptr;
+ int exec_only;
+{
+ register int fd;
+ int fn_size = 100;
+ char buf[100];
+ register char *fn = buf;
+ int absolute = 0;
+ int want_size;
+ register Lisp_Object filename;
+ struct stat st;
+
+ if (storeptr)
+ *storeptr = Qnil;
+
+ if (absolute_filename_p (str))
+ absolute = 1;
+
+ for (; !NULL (path); path = Fcdr (path))
+ {
+ char *nsuffix;
+
+ filename = Fexpand_file_name (str, Fcar (path));
+ if (!absolute_filename_p (filename))
+ /* If there are non-absolute elts in PATH (eg ".") */
+ /* Of course, this could conceivably lose if luser sets
+ default-directory to be something non-absolute... */
+ {
+ filename = Fexpand_file_name (filename, current_buffer->directory);
+ if (!absolute_filename_p (filename))
+ /* Give up on this path element! */
+ continue;
+ }
+
+ /* Calculate maximum size of any filename made from
+ this path element/specified file name and any possible suffix. */
+ want_size = strlen (suffix) + XSTRING (filename)->size + 1;
+ if (fn_size < want_size)
+ fn = (char *) alloca (fn_size = 100 + want_size);
+
+ nsuffix = suffix;
+
+ /* Loop over suffixes. */
+ while (1)
+ {
+ char *esuffix = (char *) index (nsuffix, ':');
+ int lsuffix = esuffix ? esuffix - nsuffix : strlen (nsuffix);
+
+ /* Concatenate path element/specified name with the suffix. */
+ strncpy (fn, XSTRING (filename)->data, XSTRING (filename)->size);
+ fn[XSTRING (filename)->size] = 0;
+ if (lsuffix != 0) /* Bug happens on CCI if lsuffix is 0. */
+ strncat (fn, nsuffix, lsuffix);
+
+ /* Ignore file if it's a directory. */
+ if (stat (fn, &st) >= 0
+ && (st.st_mode & S_IFMT) != S_IFDIR)
+ {
+ /* Check that we can access or open it. */
+ if (exec_only)
+ fd = !access (fn, X_OK) ? 1 : -1;
+ else
+ fd = open (fn, 0, 0);
+
+ if (fd >= 0)
+ {
+ /* We succeeded; return this descriptor and filename. */
+ if (storeptr)
+ *storeptr = build_string (fn);
+ return fd;
+ }
+ }
+
+ /* Advance to next suffix. */
+ if (esuffix == 0)
+ break;
+ nsuffix += lsuffix + 1;
+ }
+ if (absolute) return -1;
+ }
+
+ return -1;
+}
+
+
+Lisp_Object
+unreadpure () /* Used as unwind-protect function in readevalloop */
+{
+ read_pure = 0;
+ return Qnil;
+}
+
+static void
+readevalloop (readcharfun, stream, evalfun, printflag)
+ Lisp_Object readcharfun;
+ FILE *stream;
+ Lisp_Object (*evalfun) ();
+ int printflag;
+{
+ register int c;
+ register Lisp_Object val;
+ register int xunrch;
+ int count = specpdl_ptr - specpdl;
+
+ specbind (Qstandard_input, readcharfun);
+
+ unrch = -1;
+
+ while (1)
+ {
+ instream = stream;
+ c = READCHAR;
+ if (c == ';')
+ {
+ while ((c = READCHAR) != '\n' && c != -1);
+ continue;
+ }
+ if (c < 0) break;
+ if (c == ' ' || c == '\t' || c == '\n' || c == '\f') continue;
+
+ if (!NULL (Vpurify_flag) && c == '(')
+ {
+ record_unwind_protect (unreadpure, Qnil);
+ val = read_list (-1, readcharfun);
+ unbind_to (count + 1);
+ }
+ else
+ {
+ UNREAD (c);
+ val = read0 (readcharfun);
+ }
+
+ xunrch = unrch;
+ unrch = -1;
+ val = (*evalfun) (val);
+ if (printflag)
+ {
+ Vvalues = Fcons (val, Vvalues);
+ if (EQ (Vstandard_output, Qt))
+ Fprin1 (val, Qnil);
+ else
+ Fprint (val, Qnil);
+ }
+ unrch = xunrch;
+ }
+
+ unbind_to (count);
+}
+
+#ifndef standalone
+
+DEFUN ("eval-current-buffer", Feval_current_buffer, Seval_current_buffer, 0, 1, "",
+ "Execute the current buffer as Lisp code.\n\
+Programs can pass argument PRINTFLAG which controls printing of output:\n\
+nil means discard it; anything else is stream for print.")
+ (printflag)
+ Lisp_Object printflag;
+{
+ int count = specpdl_ptr - specpdl;
+ Lisp_Object tem;
+ if (NULL (printflag))
+ tem = Qsymbolp;
+ else
+ tem = printflag;
+ specbind (Qstandard_output, tem);
+ record_unwind_protect (save_excursion_restore, save_excursion_save ());
+ SET_PT (BEGV);
+ readevalloop (Fcurrent_buffer (), 0, Feval, !NULL (printflag));
+ unbind_to (count);
+ return Qnil;
+}
+
+DEFUN ("eval-region", Feval_region, Seval_region, 2, 3, "r",
+ "Execute the region as Lisp code.\n\
+When called from programs, expects two arguments,\n\
+giving starting and ending indices in the current buffer\n\
+of the text to be executed.\n\
+Programs can pass third argument PRINTFLAG which controls printing of output:\n\
+nil means discard it; anything else is stream for print.")
+ (b, e, printflag)
+ Lisp_Object b, e, printflag;
+{
+ int count = specpdl_ptr - specpdl;
+ Lisp_Object tem;
+
+ if (NULL (printflag))
+ tem = Qsymbolp;
+ else
+ tem = printflag;
+ specbind (Qstandard_output, tem);
+ if (NULL (printflag))
+ record_unwind_protect (save_excursion_restore, save_excursion_save ());
+ record_unwind_protect (save_restriction_restore, save_restriction_save ());
+ /* This both uses b and checks its type. */
+ Fgoto_char (b);
+ Fnarrow_to_region (make_number (BEGV), e);
+ readevalloop (Fcurrent_buffer (), 0, Feval, !NULL (printflag));
+ unbind_to (count);
+ return Qnil;
+}
+
+#endif standalone
+
+DEFUN ("read", Fread, Sread, 0, 1, 0,
+ "Read one Lisp expression as text from STREAM, return as Lisp object.\n\
+If STREAM is nil, use the value of standard-input (which see).\n\
+STREAM or standard-input may be:\n\
+ a buffer (read from point and advance it)\n\
+ a marker (read from where it points and advance it)\n\
+ a function (call it with no arguments for each character)\n\
+ a string (takes text from string, starting at the beginning)\n\
+ t (read text line using minibuffer and use it).")
+ (readcharfun)
+ Lisp_Object readcharfun;
+{
+ extern Lisp_Object Fread_minibuffer ();
+
+ unrch = -1; /* Allow buffering-back only within a read. */
+
+ if (NULL (readcharfun))
+ readcharfun = Vstandard_input;
+ if (EQ (readcharfun, Qt))
+ readcharfun = Qread_char;
+
+#ifndef standalone
+ if (EQ (readcharfun, Qread_char))
+ return Fread_minibuffer (build_string ("Lisp expression: "), Qnil);
+#endif
+
+ if (XTYPE (readcharfun) == Lisp_String)
+ return Fcar (Fread_from_string (readcharfun, Qnil, Qnil));
+
+ return read0 (readcharfun);
+}
+
+DEFUN ("read-from-string", Fread_from_string, Sread_from_string, 1, 3, 0,
+ "Read one Lisp expression which is represented as text by STRING.\n\
+Returns a cons: (OBJECT-READ . FINAL-STRING-INDEX).\n\
+START and END optionally delimit a substring of STRING from which to read;\n\
+ they default to 0 and (length STRING) respectively.")
+ (string, start, end)
+ Lisp_Object string, start, end;
+{
+ int startval, endval;
+ Lisp_Object tem;
+
+ CHECK_STRING (string,0);
+
+ if (NULL (end))
+ endval = XSTRING (string)->size;
+ else
+ { CHECK_NUMBER (end,2);
+ endval = XINT (end);
+ if (endval < 0 || endval > XSTRING (string)->size)
+ args_out_of_range (string, end);
+ }
+
+ if (NULL (start))
+ startval = 0;
+ else
+ { CHECK_NUMBER (start,1);
+ startval = XINT (start);
+ if (startval < 0 || startval > endval)
+ args_out_of_range (string, start);
+ }
+
+ read_from_string_index = startval;
+ read_from_string_limit = endval;
+
+ unrch = -1; /* Allow buffering-back only within a read. */
+
+ tem = read0 (string);
+ return Fcons (tem, make_number (read_from_string_index));
+}
+
+/* Use this for recursive reads, in contexts where internal tokens are not allowed. */
+
+static Lisp_Object
+read0 (readcharfun)
+ Lisp_Object readcharfun;
+{
+ register Lisp_Object val;
+ char c;
+
+ val = read1 (readcharfun);
+ if (XTYPE (val) == Lisp_Internal)
+ {
+ c = XINT (val);
+ return Fsignal (Qinvalid_read_syntax, Fcons (make_string (&c, 1), Qnil));
+ }
+
+ return val;
+}
+
+static int read_buffer_size;
+static char *read_buffer;
+
+static Lisp_Object
+read1 (readcharfun)
+ register Lisp_Object readcharfun;
+{
+ register int c;
+
+ retry:
+
+ c = READCHAR;
+ if (c < 0) return Fsignal (Qend_of_file, Qnil);
+
+ switch (c)
+ {
+ case '(':
+ return read_list (0, readcharfun);
+
+ case '[':
+ return read_vector (readcharfun);
+
+ case ')':
+ case ']':
+ case '.':
+ {
+ register Lisp_Object val;
+ XSET (val, Lisp_Internal, c);
+ return val;
+ }
+
+ case '#':
+ return Fsignal (Qinvalid_read_syntax, Fcons (make_string ("#", 1), Qnil));
+
+ case ';':
+ while ((c = READCHAR) >= 0 && c != '\n');
+ goto retry;
+
+ case '\'':
+ {
+ return Fcons (Qquote, Fcons (read0 (readcharfun), Qnil));
+ }
+
+ case '?':
+ {
+ register Lisp_Object val;
+
+ XSET (val, Lisp_Int, READCHAR);
+ if (XFASTINT (val) == '\\')
+ XSETINT (val, read_escape (readcharfun));
+
+ return val;
+ }
+
+ case '\"':
+ {
+ register char *p = read_buffer;
+ register char *end = read_buffer + read_buffer_size;
+ register int c;
+ int cancel = 0;
+
+ while ((c = READCHAR) >= 0 &&
+ (c != '\"' || (c = READCHAR) == '\"'))
+ {
+ if (p == end)
+ {
+ char *new = (char *) xrealloc (read_buffer, read_buffer_size *= 2);
+ p += new - read_buffer;
+ read_buffer += new - read_buffer;
+ end = read_buffer + read_buffer_size;
+ }
+ if (c == '\\')
+ c = read_escape (readcharfun);
+ /* c is -1 if \ newline has just been seen */
+ if (c < 0)
+ {
+ if (p == read_buffer)
+ cancel = 1;
+ }
+ else
+ *p++ = c;
+ }
+
+ UNREAD (c);
+ /* If purifying, and string starts with \ newline,
+ return zero instead. This is for doc strings
+ that we are really going to find in etc/DOC.nn.nn */
+ if (!NULL (Vpurify_flag) && NULL (Vdoc_file_name) && cancel)
+ return make_number (0);
+
+ if (read_pure)
+ return make_pure_string (read_buffer, p - read_buffer);
+ else
+ return make_string (read_buffer, p - read_buffer);
+ }
+
+ default:
+ if (c <= 040)
+ goto retry;
+
+ {
+ int quoted = 0;
+ register char *p = read_buffer;
+
+ {
+ register char *end = read_buffer + read_buffer_size;
+
+ while (c > 040 &&
+ !(c == '\"' || c == '\'' || c == ';' || c == '?'
+ || c == '(' || c == ')' || c =='.'
+ || c == '[' || c == ']' || c == '#'
+ ))
+ {
+ if (p == end)
+ {
+ register char *new = (char *) xrealloc (read_buffer, read_buffer_size *= 2);
+ p += new - read_buffer;
+ read_buffer += new - read_buffer;
+ end = read_buffer + read_buffer_size;
+ }
+ if (c == '\\')
+ {
+ quoted = 1;
+ c = READCHAR;
+ }
+ *p++ = c;
+ c = READCHAR;
+ }
+
+ if (p == end)
+ {
+ char *new = (char *) xrealloc (read_buffer, read_buffer_size *= 2);
+ p += new - read_buffer;
+ read_buffer += new - read_buffer;
+/* end = read_buffer + read_buffer_size; */
+ }
+ *p = 0;
+ UNREAD (c);
+ }
+
+ /* Is it an integer? */
+ {
+ register char *p1;
+ register Lisp_Object val;
+ p1 = read_buffer;
+ if (*p1 == '+' || *p1 == '-') p1++;
+ if (p1 != p && !quoted)
+ {
+ while (p1 != p && (c = *p1) >= '0' && c <= '9') p1++;
+ if (p1 == p)
+ /* It is. */
+ {
+ XSET (val, Lisp_Int, atoi (read_buffer));
+ return val;
+ }
+ }
+ }
+
+ return intern (read_buffer);
+ }
+ }
+}
+
+static Lisp_Object
+read_vector (readcharfun)
+ Lisp_Object readcharfun;
+{
+ register int i;
+ register int size;
+ register Lisp_Object *ptr;
+ register Lisp_Object tem, vector;
+ register struct Lisp_Cons *otem;
+ Lisp_Object len;
+
+ tem = read_list (1, readcharfun);
+ len = Flength (tem);
+ vector = (read_pure ? make_pure_vector (XINT (len)) : Fmake_vector (len, Qnil));
+
+
+ size = XVECTOR (vector)->size;
+ ptr = XVECTOR (vector)->contents;
+ for (i = 0; i < size; i++)
+ {
+ ptr[i] = read_pure ? Fpurecopy (Fcar (tem)) : Fcar (tem);
+ otem = XCONS (tem);
+ tem = Fcdr (tem);
+ free_cons (otem);
+ }
+ return vector;
+}
+
+/* flag = 1 means check for ] to terminate rather than ) and .
+ flag = -1 means check for starting with defun
+ and make structure pure. */
+
+static Lisp_Object
+read_list (flag, readcharfun)
+ int flag;
+ register Lisp_Object readcharfun;
+{
+ /* -1 means check next element for defun,
+ 0 means don't check,
+ 1 means already checked and found defun. */
+ int defunflag = flag < 0 ? -1 : 0;
+ Lisp_Object val, tail;
+ register Lisp_Object elt, tem;
+ struct gcpro gcpro1, gcpro2;
+
+ val = Qnil;
+ tail = Qnil;
+
+ while (1)
+ {
+ GCPRO2 (val, tail);
+ elt = read1 (readcharfun);
+ UNGCPRO;
+ if (XTYPE (elt) == Lisp_Internal)
+ {
+ if (flag > 0)
+ {
+ if (XINT (elt) == ']')
+ return val;
+ return Fsignal (Qinvalid_read_syntax, Fcons (make_string (") or . in a vector", 18), Qnil));
+ }
+ if (XINT (elt) == ')')
+ return val;
+ if (XINT (elt) == '.')
+ {
+ GCPRO2 (val, tail);
+ if (!NULL (tail))
+ XCONS (tail)->cdr = read0 (readcharfun);
+ else
+ val = read0 (readcharfun);
+ elt = read1 (readcharfun);
+ UNGCPRO;
+ if (XTYPE (elt) == Lisp_Internal && XINT (elt) == ')')
+ return val;
+ return Fsignal (Qinvalid_read_syntax, Fcons (make_string (". in wrong context", 18), Qnil));
+ }
+ return Fsignal (Qinvalid_read_syntax, Fcons (make_string ("] in a list", 11), Qnil));
+ }
+ tem = (read_pure && flag <= 0
+ ? pure_cons (elt, Qnil)
+ : Fcons (elt, Qnil));
+ if (!NULL (tail))
+ XCONS (tail)->cdr = tem;
+ else
+ val = tem;
+ tail = tem;
+ if (defunflag < 0)
+ defunflag = EQ (elt, Qdefun);
+ else if (defunflag > 0)
+ read_pure = 1;
+ }
+}
+
+static int
+read_escape (readcharfun)
+ Lisp_Object readcharfun;
+{
+ register int c = READCHAR;
+ switch (c)
+ {
+ case 'a':
+ return 007;
+ case 'b':
+ return '\b';
+ case 'e':
+ return 033;
+ case 'f':
+ return '\f';
+ case 'n':
+ return '\n';
+ case 'r':
+ return '\r';
+ case 't':
+ return '\t';
+ case 'v':
+ return '\v';
+ case '\n':
+ return -1;
+
+ case 'M':
+ c = READCHAR;
+ if (c != '-')
+ error ("Invalid escape character syntax");
+ c = READCHAR;
+ if (c == '\\')
+ c = read_escape (readcharfun);
+ return c | 0200;
+
+ case 'C':
+ c = READCHAR;
+ if (c != '-')
+ error ("Invalid escape character syntax");
+ case '^':
+ c = READCHAR;
+ if (c == '\\')
+ c = read_escape (readcharfun);
+ if (c == '?')
+ return 0177;
+ return (c & 0200) | (c & 037);
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ {
+ register int i = c - '0';
+ register int count = 0;
+ while (++count < 3)
+ {
+ if ((c = READCHAR) >= '0' && c <= '7')
+ {
+ i *= 8;
+ i += c - '0';
+ }
+ else
+ {
+ UNREAD (c);
+ break;
+ }
+ }
+ return i;
+ }
+ default:
+ return c;
+ }
+}
+
+Lisp_Object Vobarray;
+Lisp_Object initial_obarray;
+
+Lisp_Object
+check_obarray (obarray)
+ Lisp_Object obarray;
+{
+ while (XTYPE (obarray) != Lisp_Vector || XVECTOR (obarray)->size == 0)
+ {
+ /* If Vobarray is now invalid, force it to be valid. */
+ if (EQ (Vobarray, obarray)) Vobarray = initial_obarray;
+
+ obarray = wrong_type_argument (Qvectorp, obarray);
+ }
+ return obarray;
+}
+
+static int hash_string ();
+Lisp_Object oblookup ();
+
+Lisp_Object
+intern (str)
+ char *str;
+{
+ Lisp_Object tem;
+ int len = strlen (str);
+ Lisp_Object obarray = Vobarray;
+ if (XTYPE (obarray) != Lisp_Vector || XVECTOR (obarray)->size == 0)
+ obarray = check_obarray (obarray);
+ tem = oblookup (obarray, str, len);
+ if (XTYPE (tem) == Lisp_Symbol)
+ return tem;
+ return Fintern ((!NULL (Vpurify_flag)
+ ? make_pure_string (str, len)
+ : make_string (str, len)),
+ obarray);
+}
+
+DEFUN ("intern", Fintern, Sintern, 1, 2, 0,
+ "Return the symbol whose name is STRING.\n\
+A second optional argument specifies the obarray to use;\n\
+it defaults to the value of obarray.")
+ (str, obarray)
+ Lisp_Object str, obarray;
+{
+ register Lisp_Object tem, sym, *ptr;
+
+ if (NULL (obarray)) obarray = Vobarray;
+ obarray = check_obarray (obarray);
+
+ CHECK_STRING (str, 0);
+
+ tem = oblookup (obarray, XSTRING (str)->data, XSTRING (str)->size);
+ if (XTYPE (tem) != Lisp_Int)
+ return tem;
+
+ if (!NULL (Vpurify_flag))
+ str = Fpurecopy (str);
+ sym = Fmake_symbol (str);
+
+ ptr = &XVECTOR (obarray)->contents[XINT (tem)];
+ if (XTYPE (*ptr) == Lisp_Symbol)
+ XSYMBOL (sym)->next = XSYMBOL (*ptr);
+ else
+ XSYMBOL (sym)->next = 0;
+ *ptr = sym;
+ return sym;
+}
+
+DEFUN ("intern-soft", Fintern_soft, Sintern_soft, 1, 2, 0,
+ "Return the symbol whose name is STRING, or nil if none exists yet.\n\
+A second optional argument specifies the obarray to use;\n\
+it defaults to the value of obarray.")
+ (str, obarray)
+ Lisp_Object str, obarray;
+{
+ register Lisp_Object tem;
+
+ if (NULL (obarray)) obarray = Vobarray;
+ obarray = check_obarray (obarray);
+
+ CHECK_STRING (str, 0);
+
+ tem = oblookup (obarray, XSTRING (str)->data, XSTRING (str)->size);
+ if (XTYPE (tem) != Lisp_Int)
+ return tem;
+ return Qnil;
+}
+
+Lisp_Object
+oblookup (obarray, ptr, size)
+ Lisp_Object obarray;
+ register char *ptr;
+ register int size;
+{
+ int hash, obsize;
+ register Lisp_Object tail;
+ Lisp_Object bucket, tem;
+
+ if (XTYPE (obarray) != Lisp_Vector ||
+ (obsize = XVECTOR (obarray)->size) == 0)
+ {
+ obarray = check_obarray (obarray);
+ obsize = XVECTOR (obarray)->size;
+ }
+ /* Combining next two lines breaks VMS C 2.3. */
+ hash = hash_string (ptr, size);
+ hash %= obsize;
+ bucket = XVECTOR (obarray)->contents[hash];
+ if (XFASTINT (bucket) == 0)
+ ;
+ else if (XTYPE (bucket) != Lisp_Symbol)
+ error ("Bad data in guts of obarray"); /* Like CADR error message */
+ else for (tail = bucket; ; XSET (tail, Lisp_Symbol, XSYMBOL (tail)->next))
+ {
+ if (XSYMBOL (tail)->name->size == size &&
+ !bcmp (XSYMBOL (tail)->name->data, ptr, size))
+ return tail;
+ else if (XSYMBOL (tail)->next == 0)
+ break;
+ }
+ XSET (tem, Lisp_Int, hash);
+ return tem;
+}
+
+static int
+hash_string (ptr, len)
+ unsigned char *ptr;
+ int len;
+{
+ register unsigned char *p = ptr;
+ register unsigned char *end = p + len;
+ register unsigned char c;
+ register int hash = 0;
+
+ while (p != end)
+ {
+ c = *p++;
+ if (c >= 0140) c -= 40;
+ hash = ((hash<<3) + (hash>>28) + c);
+ }
+ return hash & 07777777777;
+}
+
+void
+map_obarray (obarray, fn, arg)
+ Lisp_Object obarray;
+ int (*fn) ();
+ Lisp_Object arg;
+{
+ register int i;
+ register Lisp_Object tail;
+ CHECK_VECTOR (obarray, 1);
+ for (i = XVECTOR (obarray)->size - 1; i >= 0; i--)
+ {
+ tail = XVECTOR (obarray)->contents[i];
+ if (XFASTINT (tail) != 0 && XTYPE (tail) == Lisp_Symbol)
+ while (1)
+ {
+ (*fn) (tail, arg);
+ if (XSYMBOL (tail)->next == 0)
+ break;
+ XSET (tail, Lisp_Symbol, XSYMBOL (tail)->next);
+ }
+ }
+}
+
+mapatoms_1 (sym, function)
+ Lisp_Object sym, function;
+{
+ call1 (function, sym);
+}
+
+DEFUN ("mapatoms", Fmapatoms, Smapatoms, 1, 2, 0,
+ "Call FUNCTION on every symbol in OBARRAY.\n\
+OBARRAY defaults to the value of obarray.")
+ (function, obarray)
+ Lisp_Object function, obarray;
+{
+ Lisp_Object tem;
+
+ if (NULL (obarray)) obarray = Vobarray;
+ obarray = check_obarray (obarray);
+
+ map_obarray (obarray, mapatoms_1, function);
+ return Qnil;
+}
+
+#define OBARRAY_SIZE 511
+
+void
+init_obarray ()
+{
+ Lisp_Object oblength;
+ int hash;
+ Lisp_Object *tem;
+
+ XFASTINT (oblength) = OBARRAY_SIZE;
+
+ Qnil = Fmake_symbol (make_pure_string ("nil", 3));
+ Vobarray = Fmake_vector (oblength, make_number (0));
+ initial_obarray = Vobarray;
+ staticpro (&initial_obarray);
+ /* Intern nil in the obarray */
+ /* These locals are to kludge around a pyramid compiler bug. */
+ hash = hash_string ("nil", 3);
+ /* Separate statement here to avoid VAXC bug. */
+ hash %= OBARRAY_SIZE;
+ tem = &XVECTOR (Vobarray)->contents[hash];
+ *tem = Qnil;
+
+ Qunbound = Fmake_symbol (make_pure_string ("unbound", 7));
+ XSYMBOL (Qnil)->function = Qunbound;
+ XSYMBOL (Qunbound)->value = Qunbound;
+ XSYMBOL (Qunbound)->function = Qunbound;
+
+ Qt = intern ("t");
+ XSYMBOL (Qnil)->value = Qnil;
+ XSYMBOL (Qnil)->plist = Qnil;
+ XSYMBOL (Qt)->value = Qt;
+
+ /* Qt is correct even if CANNOT_DUMP. loadup.el will set to nil at end. */
+ Vpurify_flag = Qt;
+
+ Qvariable_documentation = intern ("variable-documentation");
+
+ read_buffer_size = 100;
+ read_buffer = (char *) malloc (read_buffer_size);
+}
+
+void
+defsubr (sname)
+ struct Lisp_Subr *sname;
+{
+ Lisp_Object sym;
+ sym = intern (sname->symbol_name);
+ XSET (XSYMBOL (sym)->function, Lisp_Subr, sname);
+}
+
+#ifdef NOTDEF /* use fset in subr.el now */
+void
+defalias (sname, string)
+ struct Lisp_Subr *sname;
+ char *string;
+{
+ Lisp_Object sym;
+ sym = intern (string);
+ XSET (XSYMBOL (sym)->function, Lisp_Subr, sname);
+}
+#endif NOTDEF
+
+/* New replacement for DefIntVar; it ignores the doc string argument
+ on the assumption that make-docfile will handle that. */
+/* Define an "integer variable"; a symbol whose value is forwarded
+ to a C variable of type int. Sample call: */
+ /* DEFVARINT ("indent-tabs-mode", &indent_tabs_mode, "Documentation"); */
+
+void
+defvar_int (namestring, address, doc)
+ char *namestring;
+ int *address;
+ char *doc;
+{
+ Lisp_Object sym;
+ sym = intern (namestring);
+ XSET (XSYMBOL (sym)->value, Lisp_Intfwd, address);
+}
+
+/* Similar but define a variable whose value is T if address contains 1,
+ NIL if address contains 0 */
+
+void
+defvar_bool (namestring, address, doc)
+ char *namestring;
+ int *address;
+ char *doc;
+{
+ Lisp_Object sym;
+ sym = intern (namestring);
+ XSET (XSYMBOL (sym)->value, Lisp_Boolfwd, address);
+}
+
+/* Similar but define a variable whose value is the Lisp Object stored at address. */
+
+void
+defvar_lisp (namestring, address, doc)
+ char *namestring;
+ Lisp_Object *address;
+ char *doc;
+{
+ Lisp_Object sym;
+ sym = intern (namestring);
+ XSET (XSYMBOL (sym)->value, Lisp_Objfwd, address);
+ staticpro (address);
+}
+
+/* Similar but don't request gc-marking of the C variable.
+ Used when that variable will be gc-marked for some other reason,
+ since marking the same slot twice can cause trouble with strings. */
+
+void
+defvar_lisp_nopro (namestring, address, doc)
+ char *namestring;
+ Lisp_Object *address;
+ char *doc;
+{
+ Lisp_Object sym;
+ sym = intern (namestring);
+ XSET (XSYMBOL (sym)->value, Lisp_Objfwd, address);
+}
+
+#ifndef standalone
+
+/* Similar but define a variable whose value is the Lisp Object stored in
+ the current buffer. address is the address of the slot in the buffer that is current now. */
+
+void
+defvar_per_buffer (namestring, address, doc)
+ char *namestring;
+ Lisp_Object *address;
+ char *doc;
+{
+ Lisp_Object sym;
+ int offset;
+ extern struct buffer buffer_local_symbols;
+
+ sym = intern (namestring);
+ offset = (char *)address - (char *)current_buffer;
+
+ XSET (XSYMBOL (sym)->value, Lisp_Buffer_Objfwd,
+ (Lisp_Object *) offset);
+ *(Lisp_Object *)(offset + (char *)&buffer_local_symbols) = sym;
+ if (*(int *)(offset + (char *)&buffer_local_flags) == 0)
+ /* Did a DEFVAR_PER_BUFFER without initializing the corresponding
+ slot of buffer_local_flags */
+ abort ();
+}
+
+#endif standalone
+
+init_read ()
+{
+ char *normal = PATH_LOADSEARCH;
+ Lisp_Object normal_path;
+
+ /* Compute the default load-path. */
+#ifndef CANNOT_DUMP
+ /* If running a dumped Emacs in which load-path was set before dumping
+ to a nonstandard value, use that value. */
+ if (initialized
+ && !(XTYPE (Vload_path) == Lisp_Cons
+ && XTYPE (XCONS (Vload_path)->car) == Lisp_String
+ && !strcmp (XSTRING (XCONS (Vload_path)->car)->data, "../lisp")))
+ normal_path = Vload_path;
+ else
+#endif
+ normal_path = decode_env_path (0, normal);
+
+ Vload_path = normal_path;
+
+ /* Warn if dirs in the *standard* path don't exist. */
+ for (; !NULL (normal_path); normal_path = XCONS (normal_path)->cdr)
+ {
+ Lisp_Object dirfile;
+ dirfile = Fcar (normal_path);
+ if (!NULL (dirfile))
+ {
+ dirfile = Fdirectory_file_name (dirfile);
+ if (access (XSTRING (dirfile)->data, 0) < 0)
+ printf ("Warning: lisp library (%s) does not exist.\n",
+ XSTRING (Fcar (normal_path))->data);
+ }
+ }
+
+ if (egetenv ("EMACSLOADPATH"))
+ Vload_path = decode_env_path ("EMACSLOADPATH", normal);
+#ifndef CANNOT_DUMP
+ if (!NULL (Vpurify_flag))
+ Vload_path = Fcons (build_string ("../lisp"), Vload_path);
+#endif /* not CANNOT_DUMP */
+
+ Vvalues = Qnil;
+
+ load_in_progress = 0;
+}
+
+void
+syms_of_read ()
+{
+ defsubr (&Sread);
+ defsubr (&Sread_from_string);
+ defsubr (&Sintern);
+ defsubr (&Sintern_soft);
+ defsubr (&Sload);
+ defsubr (&Seval_current_buffer);
+ defsubr (&Seval_region);
+ defsubr (&Sread_char);
+ defsubr (&Sget_file_char);
+ defsubr (&Smapatoms);
+
+ DEFVAR_LISP ("obarray", &Vobarray,
+ "Symbol table for use by intern and read.\n\
+It is a vector whose length ought to be prime for best results.\n\
+Each element is a list of all interned symbols whose names hash in that bucket.");
+
+ DEFVAR_LISP ("values", &Vvalues,
+ "List of values of all expressions which were read, evaluated and printed.\n\
+Order is reverse chronological.");
+
+ DEFVAR_LISP ("standard-input", &Vstandard_input,
+ "Stream for read to get input from.\n\
+See documentation of read for possible values.");
+ Vstandard_input = Qt;
+
+ DEFVAR_LISP ("load-path", &Vload_path,
+ "*List of directories to search for files to load.\n\
+Each element is a string (directory name) or nil (try default directory).\n\
+Initialized based on EMACSLOADPATH environment variable, if any,\n\
+otherwise to default specified in by file paths.h when emacs was built.");
+
+ DEFVAR_BOOL ("load-in-progress", &load_in_progress,
+ "Non-nil iff inside of load.");
+
+ Qstandard_input = intern ("standard-input");
+ staticpro (&Qstandard_input);
+
+ Qread_char = intern ("read-char");
+ staticpro (&Qread_char);
+
+ Qget_file_char = intern ("get-file-char");
+ staticpro (&Qget_file_char);
+
+ unrch = -1;
+}
diff --git a/src/m-7300.h b/src/m-7300.h
new file mode 100644
index 00000000000..cb16a9f8545
--- /dev/null
+++ b/src/m-7300.h
@@ -0,0 +1,87 @@
+/* m- file for AT&T UNIX PC model 7300
+ Copyright (C) 1986 Free Software Foundation, Inc.
+ Modified for this machine by mtxinu!rtech!gonzo!daveb
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* This machine does not have flexnames. Yuk */
+
+/* # define SHORTNAMES */
+
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+#define SHORTBITS 16 /* Number of bits in a short */
+
+#define INTBITS 32 /* Number of bits in an int */
+
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* Define BIG_ENDIAN iff lowest-numbered byte in a word
+ is the most significant byte. */
+
+#define BIG_ENDIAN
+
+/* XINT must explicitly sign-extend */
+
+#define EXPLICIT_SIGN_EXTEND
+
+/* Define how to take a char and sign-extend into an int.
+ On machines where char is signed, this is a no-op. */
+
+#define SIGN_EXTEND_CHAR(c) (c)
+
+/* Use type int rather than a union, to represent Lisp_Object */
+
+#define NO_UNION_TYPE
+
+/* Now define a symbol for the cpu type, if your compiler
+ does not define it automatically:
+ vax, m68000, ns16000 are the ones defined so far. */
+
+# ifndef mc68k
+# define mc68k
+# endif
+#ifndef m68k
+#define m68k
+#endif
+
+/* Cause crt0.c to define errno. */
+
+#define NEED_ERRNO
+
+/* Data type of load average, as read out of kmem. */
+/* These are commented out since it is not supported by this machine. */
+
+/* #define LOAD_AVE_TYPE long */
+
+/* Convert that into an integer that is 100 for a load average of 1.0 */
+
+/* #define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0) */
+
+#define SWITCH_ENUM_BUG
+
+/* These three lines were new in 18.50. They were said to permit
+ a demand-paged executable, but someone else says they don't work.
+ Someone else says they do. They didn't work because errno was an
+ initialized variable in crt0.c, and because of %splimit (also therein),
+ both of which have been fixed now. */
+#define SECTION_ALIGNMENT 0x03ff
+#define SEGMENT_MASK 0xffff
+#define LD_SWITCH_MACHINE -z
diff --git a/src/m-all2800.h b/src/m-all2800.h
new file mode 100644
index 00000000000..9f6ede44a76
--- /dev/null
+++ b/src/m-all2800.h
@@ -0,0 +1,146 @@
+/* m-alliant-2800.h Alliant FX/2800 machine running Concentrix 2800.
+ Copyright (C) 1990 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY. No author or distributor
+accepts responsibility to anyone for the consequences of using it
+or for whether it serves any particular purpose or works at all,
+unless he says so in writing. Refer to the GNU Emacs General Public
+License for full details.
+
+Everyone is granted permission to copy, modify and redistribute
+GNU Emacs, but only under the conditions described in the
+GNU Emacs General Public License. A copy of this license is
+supposed to have been given to you along with GNU Emacs so you
+can know your rights and responsibilities. It should be in a
+file named COPYING. Among other things, the copyright notice
+and this notice must be preserved on all copies. */
+
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+#define SHORTBITS 16 /* Number of bits in a short */
+
+#define INTBITS 32 /* Number of bits in an int */
+
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* Define BIG_ENDIAN iff lowest-numbered byte in a word
+ is the most significant byte. */
+
+#undef BIG_ENDIAN
+
+/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
+ * group of arguments and treat it as an array of the arguments. */
+
+#define NO_ARG_ARRAY
+
+/* Define WORD_MACHINE if addresses and such have
+ * to be corrected before they can be used as byte counts. */
+
+#undef WORD_MACHINE
+
+/* Define how to take a char and sign-extend into an int.
+ On machines where char is signed, this is a no-op. */
+
+#define SIGN_EXTEND_CHAR(c) (c)
+
+/* Now define a symbol for the cpu type, if your compiler
+ does not define it automatically:
+ vax, m68000, ns16000, pyramid, orion, tahoe and APOLLO
+ are the ones defined so far. */
+
+#define ALLIANT
+#define ALLIANT_2800
+#define sun /* Use X support for Sun keyboard stuff. */
+#define C_OPTIMIZE_SWITCH -Og /* No concurrent code allowed here. */
+#define VALBITS 26
+#define GCTYPEBITS 5
+
+/* Use type int rather than a union, to represent Lisp_Object */
+/* This is desirable for most machines. */
+
+#define NO_UNION_TYPE
+
+/* Define EXPLICIT_SIGN_EXTEND if XINT must explicitly sign-extend
+ the 24-bit bit field into an int. In other words, if bit fields
+ are always unsigned.
+
+ If you use NO_UNION_TYPE, this flag does not matter. */
+/* On Alliants, bitfields are unsigned. */
+
+#define EXPLICIT_SIGN_EXTEND
+
+/* Concentrix uses a different kernel symbol for load average. */
+
+#undef LDAV_SYMBOL /* Undo definition in s-bsd4-2.h */
+#define LDAV_SYMBOL "_Loadavg"
+
+/* Data type of load average, as read out of kmem. */
+
+#define LOAD_AVE_TYPE long
+
+/* Convert that into an integer that is 100 for a load average of 1.0 */
+
+#define LOAD_AVE_CVT(x) (x * 100 / LOADAVG_SCALE)
+
+/* include <sys/param.h> for the definition of LOADAVG_SCALE, and also
+ LOADAVG_SIZE, the number of items in the Loadavg array. */
+
+/* Define CANNOT_DUMP on machines where unexec does not work.
+ Then the function dump-emacs will not be defined
+ and temacs will do (load "loadup") automatically unless told otherwise. */
+
+/* #define CANNOT_DUMP */
+#define UNEXEC unexfx2800.o
+#define LIBS_MACHINE -lalliant
+
+/* Define VIRT_ADDR_VARIES if the virtual addresses of
+ pure and impure space as loaded can vary, and even their
+ relative order cannot be relied on.
+
+ Otherwise Emacs assumes that text space precedes data space,
+ numerically. */
+
+#undef VIRT_ADDR_VARIES
+
+/* Define C_ALLOCA if this machine does not support a true alloca
+ and the one written in C should be used instead.
+ Define HAVE_ALLOCA to say that the system provides a properly
+ working alloca function and it should be used.
+ Define neither one if an assembler-language alloca
+ in the file alloca.s should be used. */
+
+#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
+ code will not be sharable; but that's better than failing completely. */
+/* Actually, Alliant CONCENTRIX does paging "right":
+ data pages are copy-on-write, which means that the pure data areas
+ are shared automatically and remapping is not necessary. */
+
+#define NO_REMAP
+
+/* Alliant needs special crt0.o because system version is not reentrant */
+
+#define START_FILES crt0.o
+
+/* Alliant dependent code for dumping executing image.
+ See crt0.c code for alliant. */
+
+#define ADJUST_EXEC_HEADER {\
+extern int _curbrk, _setbrk;\
+_setbrk = _curbrk;\
+hdr.a_bss_addr = bss_start;\
+unexec_text_start = hdr.a_text_addr;}
+
+/* POSIX Compatibility */
+/* Use System V.4 style getdents/readdir <dirent.h> for 2.2 and up. */
+#define SYSV_SYSTEM_DIR
+#define HAVE_CLOSEDIR
diff --git a/src/m-alliant.h b/src/m-alliant.h
new file mode 100644
index 00000000000..d7644738bb9
--- /dev/null
+++ b/src/m-alliant.h
@@ -0,0 +1,144 @@
+/* m-alliant.h Alliant machine running system version 2 or 3.
+ Copyright (C) 1985, 1986, 1987 Free Software Foundation, Inc.
+ Note that for version 1 of the Alliant system
+ you should use m-alliant1.h instead of this file.
+ Use m-alliant4.h for version 4.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+#define SHORTBITS 16 /* Number of bits in a short */
+
+#define INTBITS 32 /* Number of bits in an int */
+
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* Define BIG_ENDIAN iff lowest-numbered byte in a word
+ is the most significant byte. */
+
+#define BIG_ENDIAN
+
+/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
+ * group of arguments and treat it as an array of the arguments. */
+
+#ifdef ALLIANT_1
+#define NO_ARG_ARRAY
+#endif
+
+/* Define WORD_MACHINE if addresses and such have
+ * to be corrected before they can be used as byte counts. */
+
+#undef WORD_MACHINE
+
+/* Define how to take a char and sign-extend into an int.
+ On machines where char is signed, this is a no-op. */
+
+#define SIGN_EXTEND_CHAR(c) (c)
+
+/* Now define a symbol for the cpu type, if your compiler
+ does not define it automatically:
+ vax, m68000, ns16000, pyramid, orion, tahoe and APOLLO
+ are the ones defined so far. */
+
+#define ALLIANT
+
+/* Use type int rather than a union, to represent Lisp_Object */
+/* This is desirable for most machines. */
+
+#define NO_UNION_TYPE
+
+/* Define EXPLICIT_SIGN_EXTEND if XINT must explicitly sign-extend
+ the 24-bit bit field into an int. In other words, if bit fields
+ are always unsigned.
+
+ If you use NO_UNION_TYPE, this flag does not matter. */
+/* On Alliants, bitfields are unsigned. */
+
+#define EXPLICIT_SIGN_EXTEND
+
+/* No load average information available for Alliants. */
+
+#undef LOAD_AVE_TYPE
+#undef LOAD_AVE_CVT
+
+/* Define CANNOT_DUMP on machines where unexec does not work.
+ Then the function dump-emacs will not be defined
+ and temacs will do (load "loadup") automatically unless told otherwise. */
+
+#undef CANNOT_DUMP
+
+/* Define VIRT_ADDR_VARIES if the virtual addresses of
+ pure and impure space as loaded can vary, and even their
+ relative order cannot be relied on.
+
+ Otherwise Emacs assumes that text space precedes data space,
+ numerically. */
+
+#undef VIRT_ADDR_VARIES
+
+/* Define C_ALLOCA if this machine does not support a true alloca
+ and the one written in C should be used instead.
+ Define HAVE_ALLOCA to say that the system provides a properly
+ working alloca function and it should be used.
+ Define neither one if an assembler-language alloca
+ in the file alloca.s should be used. */
+
+#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
+ code will not be sharable; but that's better than failing completely. */
+/* Actually, Alliant CONCENTRIX does paging "right":
+ data pages are copy-on-write, which means that the pure data areas
+ are shared automatically and remapping is not necessary. */
+
+#define NO_REMAP
+
+/* Alliant needs special crt0.o because system version is not reentrant */
+
+#define START_FILES crt0.o
+
+/* Alliant dependent code for dumping executing image.
+ See crt0.c code for alliant. */
+
+#define ADJUST_EXEC_HEADER {\
+extern int _curbrk, _setbrk;\
+_setbrk = _curbrk;\
+hdr.a_bss_addr = bss_start;\
+unexec_text_start = hdr.a_text_addr;}
+
+/* cc screws up on long names. Try making cpp replace them. */
+
+#ifdef ALLIANT_1
+#define Finsert_abbrev_table_description Finsert_abbrev_table_descrip
+#define internal_with_output_to_temp_buffer internal_with_output_to_tem
+#endif
+
+/* "vector" is a typedef in /usr/include/machine/reg.h, so its use as
+ a variable name causes errors when compiling under ANSI C. */
+
+#define vector xxvector
diff --git a/src/m-alliant1.h b/src/m-alliant1.h
new file mode 100644
index 00000000000..5c084bea2d4
--- /dev/null
+++ b/src/m-alliant1.h
@@ -0,0 +1,5 @@
+/* config.h should include this file for version 1 of Alliant's
+ operating system. */
+
+#define ALLIANT_1
+#include "m-alliant.h"
diff --git a/src/m-alliant4.h b/src/m-alliant4.h
new file mode 100644
index 00000000000..2ac3008cecb
--- /dev/null
+++ b/src/m-alliant4.h
@@ -0,0 +1,20 @@
+/* m-file for Alliant Concentrix 4.0 or later.
+ Use m-alliant.h for versions 2 and 3. */
+
+#include "m-alliant.h"
+
+/* Concentrix uses a different kernel symbol for load average. */
+
+#undef LDAV_SYMBOL /* Undo definition in s-bsd4-2.h */
+#define LDAV_SYMBOL "_Loadavg"
+
+/* Data type of load average, as read out of kmem. */
+
+#define LOAD_AVE_TYPE long
+
+/* Convert that into an integer that is 100 for a load average of 1.0 */
+
+#define LOAD_AVE_CVT(x) (x * 100 / LOADAVG_SCALE)
+
+/* include <sys/param.h> for the definition of LOADAVG_SCALE, and also
+ LOADAVG_SIZE, the number of items in the Loadavg array. */
diff --git a/src/m-altos.h b/src/m-altos.h
new file mode 100644
index 00000000000..72a4f60e824
--- /dev/null
+++ b/src/m-altos.h
@@ -0,0 +1,58 @@
+/* m-altos Altos 3068 Unix System V Release 2
+ Copyright (C) 1985, 1986 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+#define SHORTBITS 16 /* Number of bits in a short */
+
+#define INTBITS 32 /* Number of bits in an int */
+
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* Vax is not big-endian: lowest numbered byte is least significant,
+ but 68000's are. */
+
+#define BIG_ENDIAN
+
+/* Define how to take a char and sign-extend into an int.
+ On machines where char is signed, this is a no-op. */
+
+#define SIGN_EXTEND_CHAR(c) (c)
+
+#define EXPLICIT_SIGN_EXTEND
+
+/* Use type int rather than a union, to represent Lisp_Object */
+
+#define NO_UNION_TYPE
+
+#define LIB_STANDARD -lc
+#define C_ALLOCA /* we have -lPW and alloca but it's broken!
+ <vsedev!ron> */
+#define SWITCH_ENUM_BUG
+
+#define NO_REMAP
+#define STACK_DIRECTION -1
+
+#define TERMINFO
+
+#undef CANNOT_DUMP
+#undef SHORTNAMES
+#undef TERMCAP
diff --git a/src/m-amdahl.h b/src/m-amdahl.h
new file mode 100644
index 00000000000..a3066e66e94
--- /dev/null
+++ b/src/m-amdahl.h
@@ -0,0 +1,202 @@
+/* m-amdahl.h file, used with s-usg5-3.h.
+ Copyright (C) 1987 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+This file for amdahl_uts created by modifying the m-template.h
+by Jishnu Mukerji 3/1/87
+
+This file works with the Amdahl uts native C compiler. The 5.2u370
+compiler is so brain damaged that it is not even worth trying to use it.
+*/
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+#define SHORTBITS 16 /* Number of bits in a short */
+
+#define INTBITS 32 /* Number of bits in an int */
+
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* Define BIG_ENDIAN iff lowest-numbered byte in a word
+ is the most significant byte. */
+
+#define BIG_ENDIAN
+
+/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
+ * group of arguments and treat it as an array of the arguments. */
+
+#undef NO_ARG_ARRAY
+
+/* Define WORD_MACHINE if addresses and such have
+ * to be corrected before they can be used as byte counts. */
+
+#define WORD_MACHINE /* not actually used anywhere yet! */
+
+/* Define how to take a char and sign-extend into an int.
+ On machines where char is signed, this is a no-op. */
+
+#define SIGN_EXTEND_CHAR(c) (((sign_extend_temp=(c)) & 0x80) \
+ ? (sign_extend_temp | 0xFFFFFF00) \
+ : (sign_extend_temp))
+
+/* Now define a symbol for the cpu type, if your compiler
+ does not define it automatically:
+ vax, m68000, ns16000, pyramid, orion, tahoe and APOLLO
+ are the ones defined so far. */
+
+/* uts gets defined automatically */
+/* However for clarity define amdahl_uts */
+#define amdahl_uts
+
+/* Use type int rather than a union, to represent Lisp_Object */
+/* This is desirable for most machines. */
+
+#define NO_UNION_TYPE
+
+/* Define EXPLICIT_SIGN_EXTEND if XINT must explicitly sign-extend
+ the 24-bit bit field into an int. In other words, if bit fields
+ are always unsigned.
+
+ If you use NO_UNION_TYPE, this flag does not matter. */
+
+#define EXPLICIT_SIGN_EXTEND
+
+/* Data type of load average, as read out of kmem. */
+
+/* #define LOAD_AVE_TYPE long*/
+
+/* Convert that into an integer that is 100 for a load average of 1.0 */
+
+/*#define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0)*/
+
+/* Define CANNOT_DUMP on machines where unexec does not work.
+ Then the function dump-emacs will not be defined
+ and temacs will do (load "loadup") automatically unless told otherwise. */
+
+/* #define CANNOT_DUMP
+
+/* Define VIRT_ADDR_VARIES if the virtual addresses of
+ pure and impure space as loaded can vary, and even their
+ relative order cannot be relied on.
+
+ Otherwise Emacs assumes that text space precedes data space,
+ numerically. */
+
+/* #define VIRT_ADDR_VARIES*/
+
+/* Define C_ALLOCA if this machine does not support a true alloca
+ and the one written in C should be used instead.
+ Define HAVE_ALLOCA to say that the system provides a properly
+ working alloca function and it should be used.
+ Define neither one if an assembler-language alloca
+ in the file alloca.s should be used. */
+
+#define C_ALLOCA
+/*#define HAVE_ALLOCA */
+
+#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
+ code will not be sharable; but that's better than failing completely. */
+
+/*#define NO_REMAP*/
+
+#define TERMINFO
+
+/* The usual definition of XINT, which involves shifting, does not
+ sign-extend properly on this machine. */
+
+#define XINT(i) (((sign_extend_temp=(i)) & 0x00800000) \
+ ? (sign_extend_temp | 0xFF000000) \
+ : (sign_extend_temp & 0x00FFFFFF))
+
+#ifdef emacs /* Don't do this when making xmakefile! */
+extern int sign_extend_temp;
+#endif
+
+/* The following needed to load the proper crt0.o and to get the
+ proper declaration of data_start in the #undef NO_REMAP case */
+
+#ifndef NO_REMAP
+#define START_FILES pre-crt0.o /lib/crt0.o
+#endif
+
+/* Perhaps this means that the optimizer isn't safe to use. */
+
+#ifndef C_OPTIMIZE_SWITCH
+#define C_OPTIMIZE_SWITCH
+#endif
+
+/* Put text and data on non-segment boundary; makes image smaller */
+
+#define LD_SWITCH_MACHINE -N
+
+/* When writing the 'xemacs' file, make text segment ro */
+#define EXEC_MAGIC 0410
+
+/* Mask for address bits within a memory segment */
+#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
+#define NSIG 20
+#endif
+
+#define NO_SIOCTL_H
+
+/* Amdahl has features not in ordinary sys v.3. */
+
+#define HAVE_TIMEVAL
+
+/* With HAVE_TIMEVAL defined, Emacs expects to use `utimes'.
+ But UTS does not have one. */
+
+#define MISSING_UTIMES
+
+#define HAVE_SELECT
+
+#define HAVE_PTYS
+
+#define HAVE_SOCKETS
+
+/* Define this symbol if your system has the functions bcopy, etc. */
+
+#define BSTRING
+
+#if 0 /* This is turned off because BROKEN_TIOCGETC is probably harmless. */
+#undef BROKEN_TIOCGETC
+#endif
+
+/* X needs to talk on the network, so search the network library. */
+
+#undef LIBX11_SYSTEM /* What s-usg5-3.h does is not needed. */
+#define LIBX11_MACHINE -lsocket -lbsd
+
+/* SIGIO is defined but does not work. Prevent using it. */
+#define BROKEN_FIONREAD
diff --git a/src/m-apollo.h b/src/m-apollo.h
new file mode 100644
index 00000000000..619d935f721
--- /dev/null
+++ b/src/m-apollo.h
@@ -0,0 +1,97 @@
+/* m- file for Apollo machine.
+ Copyright (C) 1985, 1986 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+#define SHORTBITS 16 /* Number of bits in a short */
+
+#define INTBITS 32 /* Number of bits in an int */
+
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* 68000 has lowest-numbered byte as most significant */
+
+#define BIG_ENDIAN
+
+/* Define how to take a char and sign-extend into an int.
+ On machines where char is signed, this is a no-op. */
+
+#define SIGN_EXTEND_CHAR(c) (c)
+
+/* Say this machine is a 68000 */
+
+/* #define m68000 */ /* Done by the C compiler */
+
+#define APOLLO
+
+/* Assume we use s-bsd4-3.h for system version 10. */
+
+#ifdef BSD4_3
+#define APOLLO_SR10
+#endif
+
+/* Use type int rather than a union, to represent Lisp_Object */
+
+#define NO_UNION_TYPE
+
+/* Do not define LOAD_AVE_TYPE or LOAD_AVE_CVT
+ since there is no /dev/kmem */
+
+/* Define CANNOT_DUMP because it is impossible to dump. */
+
+#define CANNOT_DUMP
+
+/* Define VIRT_ADDR_VARIES because the virtual addresses of
+ pure and impure space as loaded can vary, and even their
+ relative order cannot be relied on. */
+
+#define VIRT_ADDR_VARIES
+
+/* Define HAVE_ALLOCA because we use the system's version of alloca. */
+
+#define HAVE_ALLOCA
+
+/* DN460 has a 28 bit virtual address space, and 26 bits are often used */
+
+#define VALBITS 26
+#define GCTYPEBITS 5
+
+/* Prevent -lg from being used for debugging. Not needed. */
+
+#define LIBS_DEBUG
+
+/* Must use the system's termcap. It does special things. */
+
+#define LIBS_TERMCAP -ltermcap
+
+/* Must use the system's malloc and alloca. */
+
+#define SYSTEM_MALLOC
+
+/* No crt0 is needed, but control where environ is allocated. */
+
+#define START_FILES pre-crt0.o
+
+/* Apollo's bcopy said to lose on more than 16k bytes in SR9.5. */
+
+#ifndef APOLLO_SR10
+#undef BSTRING
+#endif
diff --git a/src/m-att3b.h b/src/m-att3b.h
new file mode 100644
index 00000000000..cec4f808e65
--- /dev/null
+++ b/src/m-att3b.h
@@ -0,0 +1,160 @@
+/* Machine-dependent configuration for GNU Emacs for AT&T 3b machines.
+ Copyright (C) 1986 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+#define SHORTBITS 16 /* Number of bits in a short */
+
+#define INTBITS 32 /* Number of bits in an int */
+
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* Define BIG_ENDIAN iff lowest-numbered byte in a word
+ is the most significant byte. */
+
+#define BIG_ENDIAN
+
+/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
+ * group of arguments and treat it as an array of the arguments. */
+
+/* #define NO_ARG_ARRAY */
+
+/* Define WORD_MACHINE if addresses and such have
+ * to be corrected before they can be used as byte counts. */
+
+/* #define WORD_MACHINE */
+
+/* Define how to take a char and sign-extend into an int.
+ On machines where char is signed, this is a no-op. */
+/* The 3b20 doesn't sign extend characters OR ints, so
+ right shifting an int loses the sign bit */
+#define SIGN_EXTEND_CHAR(c) (((sign_extend_temp=(c)) & 0x80) \
+ ? (sign_extend_temp | 0xFFFFFF00) \
+ : (sign_extend_temp))
+
+/* Now define a symbol for the cpu type, if your compiler
+ does not define it automatically */
+#define ATT3B
+
+/* Use type int rather than a union, to represent Lisp_Object */
+/* This is desirable for most machines. */
+
+#define NO_UNION_TYPE
+
+/* Define EXPLICIT_SIGN_EXTEND if XINT must explicitly sign-extend
+ the 24-bit bit field into an int. In other words, if bit fields
+ are always unsigned.
+
+ If you use NO_UNION_TYPE, this flag does not matter. */
+
+#define EXPLICIT_SIGN_EXTEND
+
+/* Data type of load average, as read out of kmem. */
+/* #define LOAD_AVE_TYPE long */
+
+/* Convert that into an integer that is 100 for a load average of 1.0 */
+
+/* #define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0 / FSCALE) */
+
+/* Define CANNOT_DUMP on machines where unexec does not work.
+ Then the function dump-emacs will not be defined
+ and temacs will do (load "loadup") automatically unless told otherwise. */
+/* #define CANNOT_DUMP */
+
+/* Define VIRT_ADDR_VARIES if the virtual addresses of
+ pure and impure space as loaded can vary, and even their
+ relative order cannot be relied on.
+
+ Otherwise Emacs assumes that text space precedes data space,
+ numerically. */
+
+/* #define VIRT_ADDR_VARIES */ /* Karl Kleinpaste says this isn't needed. */
+
+/* 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
+ 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 LD_SWITCH_MACHINE -N */
+
+/* Use Terminfo, not Termcap. */
+
+#define TERMINFO
+
+/* -O has been observed to make correct C code in Emacs not work.
+ So don't try to use it. */
+
+#if u3b2 || u3b5 || u3b15
+#define C_OPTIMIZE_SWITCH
+#endif
+
+/* Define our page size. */
+
+#define NBPC 2048
+
+/* The usual definition of XINT, which involves shifting, does not
+ sign-extend properly on this machine. */
+
+#define XINT(i) (((sign_extend_temp=(i)) & 0x00800000) \
+ ? (sign_extend_temp | 0xFF000000) \
+ : (sign_extend_temp & 0x00FFFFFF))
+
+#ifdef emacs /* Don't do this when makeing xmakefile! */
+extern int sign_extend_temp;
+#endif
+
+#if u3b2 || u3b5 || u3b15
+
+/* On 3b2/5/15, data space has high order bit on. */
+#define VALMASK (((1<<VALBITS) - 1) | (1 << 31))
+#define XTYPE(a) ((enum Lisp_Type) (((a) >> VALBITS) & 0x7F))
+#define GCTYPEBITS 5
+#define XADDRFIX(a) ((a) |= 0X80000000) /* Because of high order */
+
+#endif /* 3b2, 3b5 or 3b15 */
+
+#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
+
+/* 3B2s with WIN/3B have winsize defined in ptem.h */
+#if u3b2
+#define NEED_PTEM_H
+#endif /* u3b2 */
diff --git a/src/m-aviion.h b/src/m-aviion.h
new file mode 100644
index 00000000000..c634a67139d
--- /dev/null
+++ b/src/m-aviion.h
@@ -0,0 +1,150 @@
+/* m- file for Data General AViiON.
+ Copyright (C) 1985, 1986, 1991 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+#define SHORTBITS 16 /* Number of bits in a short */
+
+#define INTBITS 32 /* Number of bits in an int */
+
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* Define BIG_ENDIAN iff lowest-numbered byte in a word
+ is the most significant byte. */
+
+#define BIG_ENDIAN
+
+/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
+ * group of arguments and treat it as an array of the arguments. */
+
+#define NO_ARG_ARRAY
+
+/* Define WORD_MACHINE if addresses and such have
+ * to be corrected before they can be used as byte counts. */
+
+#define WORD_MACHINE
+
+/* Define how to take a char and sign-extend into an int.
+ On machines where char is signed, this is a no-op. */
+
+#define SIGN_EXTEND_CHAR(c) (c)
+
+/* Define DATA_SEG_BITS if pointers need to be corrected with
+ a segment field. */
+
+#ifdef FIX_ADDRESS
+#define DATA_SEG_BITS 0xef000000
+#endif
+
+/* Now define a symbol for the cpu type, if your compiler
+ does not define it automatically:
+ Ones defined so far include vax, m68000, ns16000, pyramid,
+ orion, tahoe, APOLLO and many others */
+
+#ifndef m88k
+#define m88k
+#endif
+
+/* Use type int rather than a union, to represent Lisp_Object */
+/* This is desirable for most machines. */
+
+#define NO_UNION_TYPE
+
+/* Define EXPLICIT_SIGN_EXTEND if XINT must explicitly sign-extend
+ the 24-bit bit field into an int. In other words, if bit fields
+ are always unsigned.
+
+ If you use NO_UNION_TYPE, this flag does not matter. */
+
+#define EXPLICIT_SIGN_EXTEND
+
+/* Data type of load average, as read out of kmem. */
+
+/* #define LOAD_AVE_TYPE long */
+
+/* Convert that into an integer that is 100 for a load average of 1.0 */
+
+/* #define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0 / FSCALE) */
+
+/* Define CANNOT_DUMP on machines where unexec does not work.
+ Then the function dump-emacs will not be defined
+ and temacs will do (load "loadup") automatically unless told otherwise. */
+
+/* #define CANNOT_DUMP */
+
+/* Define VIRT_ADDR_VARIES if the virtual addresses of
+ pure and impure space as loaded can vary, and even their
+ relative order cannot be relied on.
+
+ Otherwise Emacs assumes that text space precedes data space,
+ numerically. */
+
+/* #define VIRT_ADDR_VARIES */
+
+/* Define C_ALLOCA if this machine does not support a true alloca
+ and the one written in C should be used instead.
+ Define HAVE_ALLOCA to say that the system provides a properly
+ working alloca function and it should be used.
+ Define neither one if an assembler-language alloca
+ in the file alloca.s should be used. */
+
+/* #define C_ALLOCA */
+#define HAVE_ALLOCA
+#define 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
+ code will not be sharable; but that's better than failing completely. */
+
+#define NO_REMAP
+
+/* Use 26 bits instead of 24 for internal pointer values */
+
+#define VALBITS 26
+#define GCTYPEBITS 5
+
+/* Define ADDR_CORRECT(ADDR) to be a macro to correct an int which is
+ the bit pattern of a pointer to a byte into an int which is the
+ number of a byte.
+
+ This macro has a default definition which is usually right.
+ This default definition is a no-op on most machines (where a
+ pointer looks like an int) but not on all machines. */
+
+#define ADDR_CORRECT(ADDR) ((int)ADDR)
+
+/* Cast pointers to this type to compare them. */
+
+#define PNTR_COMPARISON_TYPE void *
+
+/* Some machines that use COFF executables require that each section
+ start on a certain boundary *in the COFF file*. Such machines should
+ define SECTION_ALIGNMENT to a mask of the low-order bits that must be
+ zero on such a boundary. This mask is used to control padding between
+ segments in the COFF file.
+
+ If SECTION_ALIGNMENT is not defined, the segments are written
+ consecutively with no attempt at alignment. This is right for
+ unmodified system V. */
+
+#define SECTION_ALIGNMENT 0x7
+
diff --git a/src/m-bullx20.h b/src/m-bullx20.h
new file mode 100644
index 00000000000..132a947f8f2
--- /dev/null
+++ b/src/m-bullx20.h
@@ -0,0 +1,125 @@
+/* m- file for Honeywell Bull X20, 68020 with SysV 2.2
+ by lele@idea.sublink.org (Lele Gaifax)
+ Copyright (C) 1991 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY. No author or distributor
+accepts responsibility to anyone for the consequences of using it
+or for whether it serves any particular purpose or works at all,
+unless he says so in writing. Refer to the GNU Emacs General Public
+License for full details.
+
+Everyone is granted permission to copy, modify and redistribute
+GNU Emacs, but only under the conditions described in the
+GNU Emacs General Public License. A copy of this license is
+supposed to have been given to you along with GNU Emacs so you
+can know your rights and responsibilities. It should be in a
+file named COPYING. Among other things, the copyright notice
+and this notice must be preserved on all copies. */
+
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+#define SHORTBITS 16 /* Number of bits in a short */
+
+#define INTBITS 32 /* Number of bits in an int */
+
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* Define BIG_ENDIAN iff lowest-numbered byte in a word
+ is the most significant byte. */
+
+#define BIG_ENDIAN
+
+/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
+ * group of arguments and treat it as an array of the arguments. */
+
+#define NO_ARG_ARRAY
+
+/* Define WORD_MACHINE if addresses and such have
+ * to be corrected before they can be used as byte counts. */
+
+#define WORD_MACHINE
+
+/* Define how to take a char and sign-extend into an int.
+ On machines where char is signed, this is a no-op. */
+
+#define SIGN_EXTEND_CHAR(c) (c)
+
+/* Now define a symbol for the cpu type, if your compiler
+ does not define it automatically:
+ Ones defined so far include vax, m68000, ns16000, pyramid,
+ orion, tahoe, APOLLO and many others */
+#define m68k
+
+/* Use type int rather than a union, to represent Lisp_Object */
+/* This is desirable for most machines. */
+
+#define NO_UNION_TYPE
+
+/* Define EXPLICIT_SIGN_EXTEND if XINT must explicitly sign-extend
+ the 24-bit bit field into an int. In other words, if bit fields
+ are always unsigned.
+
+ If you use NO_UNION_TYPE, this flag does not matter. */
+
+#define EXPLICIT_SIGN_EXTEND
+
+/* Data type of load average, as read out of kmem. */
+
+#undef LOAD_AVE_TYPE
+
+/* Convert that into an integer that is 100 for a load average of 1.0 */
+
+#undef LOAD_AVE_CVT
+
+/* Define CANNOT_DUMP on machines where unexec does not work.
+ Then the function dump-emacs will not be defined
+ and temacs will do (load "loadup") automatically unless told otherwise. */
+
+#undef CANNOT_DUMP
+
+/* Define VIRT_ADDR_VARIES if the virtual addresses of
+ pure and impure space as loaded can vary, and even their
+ relative order cannot be relied on.
+
+ Otherwise Emacs assumes that text space precedes data space,
+ numerically. */
+
+/* #define VIRT_ADDR_VARIES */
+
+/* Define C_ALLOCA if this machine does not support a true alloca
+ and the one written in C should be used instead.
+ Define HAVE_ALLOCA to say that the system provides a properly
+ working alloca function and it should be used.
+ Define neither one if an assembler-language alloca
+ in the file alloca.s should be used. */
+
+/* Define 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. */
+
+#undef NO_REMAP
+
+#define bcopy(a,b,s) memcpy((b), (a), (s))
+#define bzero(a,s) memset((a), 0, (s))
+#define bcmp memcmp
+#define index strchr
+#define rindex strrchr
+#define BSTRING
+#define DIRENT
+
+#define LD_SWITCH_MACHINE -e _start
+#define SECTION_ALIGNMENT 0x03ff
+#define SEGMENT_MASK 0xffff
+
+#undef HAVE_PTY
+#ifdef HAVE_PTY
+#define PTY_ITERATION for(i=0; i<=8; i++)
+#define PTY_NAME_SPRINTF sprintf(ptyname, "/dev/ptyp%x", i);
+#define PTY_TTY_NAME_SPRINTF sprintf(ptyname, "/dev/ttyp%x", i);
+#endif
diff --git a/src/m-celerity.h b/src/m-celerity.h
new file mode 100644
index 00000000000..0aefb71744a
--- /dev/null
+++ b/src/m-celerity.h
@@ -0,0 +1,69 @@
+/* m- file for Celerity.
+ Copyright (C) 1985, 1986 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+#define SHORTBITS 16 /* Number of bits in a short */
+
+#define INTBITS 32 /* Number of bits in an int */
+
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* Define BIG_ENDIAN iff lowest-numbered byte in a word
+ is the most significant byte. */
+
+#define BIG_ENDIAN
+
+/* XINT must explicitly sign extend */
+
+#define EXPLICIT_SIGN_EXTEND
+
+/* Define how to take a char and sign-extend into an int.
+ On machines where char is signed, this is a no-op. */
+
+#define SIGN_EXTEND_CHAR(c) (c)
+
+/* celerity preprocessor defines "accel", however the following is clearer */
+#define celerity
+
+/* #define NO_UNION_TYPE would be preferable,
+ but it does not work, and the reason is not yet known. */
+
+#define NO_UNION_TYPE
+
+/* Data type of load average, as read out of kmem. */
+
+#define LOAD_AVE_TYPE double
+
+/* Convert that into an integer that is 100 for a load average of 1.0 */
+
+#define LOAD_AVE_CVT(x) ((int) ((x) * 100.0))
+
+/* A machine-specific loader switch is needed. */
+
+#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 --git a/src/m-convex.h b/src/m-convex.h
new file mode 100644
index 00000000000..f958276d0fc
--- /dev/null
+++ b/src/m-convex.h
@@ -0,0 +1,172 @@
+/* m- file for convex C1-C3.
+ Copyright (C) 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+#define SHORTBITS 16 /* Number of bits in a short */
+
+#define INTBITS 32 /* Number of bits in an int */
+
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* Define BIG_ENDIAN iff lowest-numbered byte in a word
+ is the most significant byte. */
+
+#define BIG_ENDIAN
+
+/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
+ * group of arguments and treat it as an array of the arguments. */
+
+/* #define NO_ARG_ARRAY */
+
+/* Define WORD_MACHINE if addresses and such have
+ * to be corrected before they can be used as byte counts. */
+
+/* #define WORD_MACHINE */
+
+/* Define how to take a char and sign-extend into an int.
+ On machines where char is signed, this is a no-op. */
+
+#define SIGN_EXTEND_CHAR(c) (c)
+
+/* Now define a symbol for the cpu type, if your compiler
+ does not define it automatically. */
+
+/* convex already defined... */
+
+/* Use type int rather than a union, to represent Lisp_Object */
+/* This is desirable for most machines. */
+
+#define NO_UNION_TYPE
+
+/* crt0.c should use the vax-bsd style of entry, with no dummy args. */
+
+#define CRT0_DUMMIES
+
+/* crt0.c should define a symbol `start' and do .globl with a dot. */
+
+#define DOT_GLOBAL_START
+
+/* Data type of load average, as read out of kmem. */
+
+#define LOAD_AVE_TYPE double
+
+/* Convert that into an integer that is 100 for a load average of 1.0 */
+
+#define LOAD_AVE_CVT(x) (int) ((x) * 100.0)
+
+/* Define CANNOT_DUMP on machines where unexec does not work.
+ Then the function dump-emacs will not be defined
+ and temacs will do (load "loadup") automatically unless told otherwise. */
+
+/* #define CANNOT_DUMP */
+
+/* Define VIRT_ADDR_VARIES if the virtual addresses of
+ pure and impure space as loaded can vary, and even their
+ relative order cannot be relied on.
+
+ Otherwise Emacs assumes that text space precedes data space,
+ numerically. */
+
+/* #define VIRT_ADDR_VARIES */
+
+/* Define C_ALLOCA if this machine does not support a true alloca
+ and the one written in C should be used instead.
+ Define HAVE_ALLOCA to say that the system provides a properly
+ working alloca function and it should be used.
+ Define neither one if an assembler-language alloca
+ in the file alloca.s should be used. */
+
+/* #define C_ALLOCA */
+#define HAVE_ALLOCA
+
+#ifdef __GNUC__
+#define alloca __builtin_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
+ code will not be sharable; but that's better than failing completely. */
+
+/* #define NO_REMAP */
+
+/* Addresses on the Convex have the high bit set. */
+
+#define DATA_SEG_BITS 0x80000000
+
+/* Right shift is logical shift, so use this to sign-extend a lisp int. */
+
+#define VSIGNBIT (1 << (VALBITS - 1))
+#define VALLBITS ((1 << VALBITS) - 1)
+#define XINT(a) ((int) ((((a) & VALLBITS) ^ VSIGNBIT) - VSIGNBIT))
+
+/* Convex uses a special version of unexec. */
+
+#define UNEXEC unexconvex.o
+
+/* you gotta define 'COFF' for post 6.1 unexec. */
+
+#define COFF
+#define TEXT_START 0x80001000
+
+/* Posix stuff for Convex OS 8.1 and up. */
+
+#define C_SWITCH_MACHINE -pcc
+#define LD_SWITCH_MACHINE \
+ -e__start -L /usr/lib \
+ '-A__iob=___ap$$iob' '-A_use_libc_sema=___ap$$use_libc_sema'
+
+/* Use setsid when starting up inferiors. */
+#define HAVE_SETSID
+
+/* Use <dirent.h>. */
+#define SYSV_SYSTEM_DIR
+#define HAVE_CLOSEDIR
+
+#ifdef _POSIX_SOURCE
+
+/* These symbols have been undefined to advance the state of the art. */
+
+#define S_IFMT _S_IFMT
+#define S_IFDIR _S_IFDIR
+
+#define S_IREAD _S_IREAD
+#define S_IWRITE _S_IWRITE
+#define S_IEXEC _S_IEXEC
+
+#endif
+
+/* Ptys may start below ptyp0; call a routine to hunt for where. */
+
+#undef FIRST_PTY_LETTER
+#define FIRST_PTY_LETTER first_pty_letter()
+
+#if 0
+/*
+ * Force a K&R compilation and libraries with the Convex V 4.0 C compiler
+ */
+#define C_SWITCH_MACHINE -pcc
+#define LIB_STANDARD -lc_old
+#define LIBS_MACHINE -lC2_old
+#define LD_SWITCH_MACHINE -X -NL -fn -Enoposix -A__iob=___ap\$$iob \
+ -A_use_libc_sema=___ap\$$use_libc_sema -L /usr/lib
+#endif
diff --git a/src/m-cydra5.h b/src/m-cydra5.h
new file mode 100644
index 00000000000..9f9e559b3c9
--- /dev/null
+++ b/src/m-cydra5.h
@@ -0,0 +1,135 @@
+/* m- file for Cydrome's CYDRA 5 mini super computer
+ Copyright (C) 1988 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+#define SHORTBITS 16 /* Number of bits in a short */
+
+#define INTBITS 32 /* Number of bits in an int */
+
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* Define BIG_ENDIAN iff lowest-numbered byte in a word
+ is the most significant byte. */
+
+#define BIG_ENDIAN
+
+/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
+ * group of arguments and treat it as an array of the arguments. */
+
+#undef NO_ARG_ARRAY
+
+/* Define WORD_MACHINE if addresses and such have
+ * to be corrected before they can be used as byte counts. */
+
+#undef WORD_MACHINE
+
+/* Define how to take a char and sign-extend into an int.
+ On machines where char is signed, this is a no-op. */
+
+#define SIGN_EXTEND_CHAR(c) (c)
+
+/* Now define a symbol for the cpu type, if your compiler
+ does not define it automatically:
+ Ones defined so far include vax, m68000, ns16000, pyramid,
+ orion, tahoe, APOLLO and many others */
+
+/* Use type int rather than a union, to represent Lisp_Object */
+/* This is desirable for most machines. */
+
+#define NO_UNION_TYPE
+
+/* Define EXPLICIT_SIGN_EXTEND if XINT must explicitly sign-extend
+ the 24-bit bit field into an int. In other words, if bit fields
+ are always unsigned.
+
+ If you use NO_UNION_TYPE, this flag does not matter. */
+
+#define EXPLICIT_SIGN_EXTEND
+
+/* Data type of load average, as read out of kmem. */
+
+#define LOAD_AVE_TYPE long
+
+/* Convert that into an integer that is 100 for a load average of 1.0 */
+
+#define LOAD_AVE_CVT(x) x
+
+/* Define CANNOT_DUMP on machines where unexec does not work.
+ Then the function dump-emacs will not be defined
+ and temacs will do (load "loadup") automatically unless told otherwise. */
+
+/*#define CANNOT_DUMP*/
+
+/* Define VIRT_ADDR_VARIES if the virtual addresses of
+ pure and impure space as loaded can vary, and even their
+ relative order cannot be relied on.
+
+ Otherwise Emacs assumes that data space precedes text space,
+ numerically. */
+
+#undef VIRT_ADDR_VARIES
+
+/* Define C_ALLOCA if this machine does not support a true alloca
+ and the one written in C should be used instead.
+ Define HAVE_ALLOCA to say that the system provides a properly
+ working alloca function and it should be used.
+ Define neither one if an assembler-language alloca
+ in the file alloca.s should be used. */
+
+#define C_ALLOCA
+#undef HAVE_ALLOCA
+
+/* The data segment in this machine always starts at address 0x10000000.
+ An address of data cannot be stored correctly in a Lisp object;
+ we always lose the high bits. We must tell XPNTR to add them back. */
+
+#define DATA_SEG_BITS 0x20000000
+#define DATA_START 0x20000000
+
+/* 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 BROKEN_FIONREAD /* We son't even have it */
+#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
+
+/* Compiler won't allow switch (x) when x is an enum. */
+#define SWITCH_ENUM_BUG
+
+
+/* Explain how pty filenames work. */
+
+#define PTY_ITERATION for (i = 47; i >= 0; i--)
+#define PTY_NAME_SPRINTF sprintf (pty_name, "/dev/pty%03x", i);
+#define PTY_TTY_NAME_SPRINTF sprintf (pty_name, "/dev/ptm%03x", i);
+
+/* We can't do interrupt-driven input, so don't let user try. */
+
+#undef SIGIO
diff --git a/src/m-delta.h b/src/m-delta.h
new file mode 100644
index 00000000000..aeaf27a40e0
--- /dev/null
+++ b/src/m-delta.h
@@ -0,0 +1,164 @@
+/* m- file for the Motorola delta running System V.3.
+ tested on sysV68 (mvme147 - based system). Use with s-usg5-3.h.
+ Copyright (C) 1986 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define mot_delta
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+#define SHORTBITS 16 /* Number of bits in a short */
+
+#define INTBITS 32 /* Number of bits in an int */
+
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* Define BIG_ENDIAN iff lowest-numbered byte in a word
+ is the most significant byte. */
+
+#define BIG_ENDIAN
+
+/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
+ * group of arguments and treat it as an array of the arguments. */
+
+/* #define NO_ARG_ARRAY */
+
+/* Define WORD_MACHINE if addresses and such have
+ * to be corrected before they can be used as byte counts. */
+
+/* #define WORD_MACHINE */
+
+/* Define how to take a char and sign-extend into an int.
+ On machines where char is signed, this is a no-op. */
+
+#define SIGN_EXTEND_CHAR(c) (c)
+
+/* Now define a symbol for the cpu type, if your compiler
+ does not define it automatically:
+ vax, m68000, ns16000, pyramid, orion, tahoe and APOLLO
+ are the ones defined so far. */
+#define m68000
+#define mot_delta
+
+/* Don't try to dump part of data space as pure. */
+
+#define NO_REMAP
+
+/* We have system V ipc. */
+
+#define HAVE_SYSVIPC
+
+/* We have ptys. */
+
+#define HAVE_PTYS
+#define SYSV_PTYS
+
+/* Use type int rather than a union, to represent Lisp_Object */
+/* This is desirable for most machines. */
+
+#define NO_UNION_TYPE
+#define SWITCH_ENUM_BUG
+/* Define EXPLICIT_SIGN_EXTEND if XINT must explicitly sign-extend
+ the 24-bit bit field into an int. In other words, if bit fields
+ are always unsigned.
+
+ If you use NO_UNION_TYPE, this flag does not matter. */
+
+#define EXPLICIT_SIGN_EXTEND
+
+/* Data type of load average, as read out of kmem. */
+
+/* #define LOAD_AVE_TYPE long */
+
+/* Convert that into an integer that is 100 for a load average of 1.0 */
+
+/* #define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0 / FSCALE) */
+
+/* Define CANNOT_DUMP on machines where unexec does not work.
+ Then the function dump-emacs will not be defined
+ and temacs will do (load "loadup") automatically unless told otherwise. */
+
+/* #define CANNOT_DUMP */
+
+/* Define VIRT_ADDR_VARIES if the virtual addresses of
+ pure and impure space as loaded can vary, and even their
+ relative order cannot be relied on.
+
+ Otherwise Emacs assumes that text space precedes data space,
+ numerically. */
+
+/* #define VIRT_ADDR_VARIES */
+
+#define USG_SYS_TIME
+#define SYSV_SYSTEM_DIR
+#define BSTRING
+#define CLASH_DETECTION /* starting from emacs 18.59 */
+
+#undef KERNEL_FILE
+#define KERNEL_FILE "/sysV68"
+#undef LOAD_AVE_TYPE
+#define HAVE_DUP2
+
+/* -lbsd gets sigblock and sigsetmask. */
+#define LIBS_SYSTEM -lbsd
+#undef sigsetmask
+
+/* 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__
+/* easy. use builtin one. also be sure that no other ones are tried out. */
+# define alloca __builtin_alloca
+# define HAVE_ALLOCA
+# undef C_ALLOCA
+#else /* not __GNUC__, use the one in alloca.s. */
+/* the alloca in -lPW is broken, at least until R3V6
+ -riku@field.fi
+ -pot@cnuce.cnr.IT */
+#undef HAVE_ALLOCA
+#undef C_ALLOCA
+#endif /* __GNUC__ */
+
+#define LIBS_TERMCAP -lcurses
+
+#define HAVE_TIMEVAL
+#define HAVE_GETTIMEOFDAY
+
+#define HAVE_SELECT
+#define HAVE_SOCKETS /***** only if NSE has been installed *****/
+
+#define USE_UTIME
+
+/* Required only for use with Green Hills compiler:
+ -ga because alloca relies on stack frames. This option forces
+ the Green Hills compiler to create stack frames even for
+ functions with few local variables. */
+
+/* #define C_SWITCH_MACHINE -ga */
+
+/* People used to say this was necessary. Maybe it no longer is,
+ because the system may not define FIONREAD. But this can't hurt. */
+#define BROKEN_FIONREAD
+
+/* Send signals to subprocesses by typing interrupt characters at them. */
+#define SIGNALS_VIA_CHARACTERS
diff --git a/src/m-delta88.h b/src/m-delta88.h
new file mode 100644
index 00000000000..c90bec199e5
--- /dev/null
+++ b/src/m-delta88.h
@@ -0,0 +1,168 @@
+/* m- file for Motorola System V/88 machines
+ Copyright (C) 1985 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY. No author or distributor
+accepts responsibility to anyone for the consequences of using it
+or for whether it serves any particular purpose or works at all,
+unless he says so in writing. Refer to the GNU Emacs General Public
+License for full details.
+
+Everyone is granted permission to copy, modify and redistribute
+GNU Emacs, but only under the conditions described in the
+GNU Emacs General Public License. A copy of this license is
+supposed to have been given to you along with GNU Emacs so you
+can know your rights and responsibilities. It should be in a
+file named COPYING. Among other things, the copyright notice
+and this notice must be preserved on all copies. */
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+
+#define SHORTBITS 16 /* Number of bits in a short */
+
+#define INTBITS 32 /* Number of bits in an int */
+
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* Define BIG_ENDIAN iff lowest-numbered byte in a word
+ is the most significant byte. */
+
+#define BIG_ENDIAN
+
+/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
+ * group of arguments and treat it as an array of the arguments. */
+
+#define NO_ARG_ARRAY
+
+/* Define WORD_MACHINE if addresses and such have
+ * to be corrected before they can be used as byte counts. */
+
+/* #define WORD_MACHINE */
+
+/* Now define a symbol for the cpu type, if your compiler
+ does not define it automatically:
+ Ones defined so far include vax, m68000, ns16000, pyramid,
+ orion, tahoe, APOLLO and many others */
+
+#ifndef m88000 /* Some 88k C compilers already define this */
+#define m88000
+#endif
+
+/* Define how to take a char and sign-extend into an int.
+ On machines where char is signed, this is a no-op. */
+
+#define SIGN_EXTEND_CHAR(c) (c)
+
+/* Now define a symbol for the cpu type, if your compiler
+ does not define it automatically. */
+
+
+/* Use type int rather than a union, to represent Lisp_Object */
+/* This is desirable for most machines. */
+
+#define NO_UNION_TYPE
+
+/* Define EXPLICIT_SIGN_EXTEND if XINT must explicitly sign-extend
+ the 24-bit bit field into an int. In other words, if bit fields
+ are always unsigned.
+
+ If you use NO_UNION_TYPE, this flag does not matter. */
+
+/* #define EXPLICIT_SIGN_EXTEND */
+
+/* Data type of load average, as read out of kmem. */
+/* No load average on Motorola machines. */
+/* #define LOAD_AVE_TYPE double */
+
+/* Convert that into an integer that is 100 for a load average of 1.0 */
+/* #define LOAD_AVE_CVT(x) ((int) ((x) * 100.0)) */
+
+/* Define CANNOT_DUMP on machines where unexec does not work.
+ Then the function dump-emacs will not be defined
+ and temacs will do (load "loadup") automatically unless told otherwise. */
+
+/* #define CANNOT_DUMP */
+
+/* Define VIRT_ADDR_VARIES if the virtual addresses of
+ pure and impure space as loaded can vary, and even their
+ relative order cannot be relied on.
+
+ Otherwise Emacs assumes that text space precedes data space,
+ numerically. */
+
+/* #define VIRT_ADDR_VARIES */
+
+/* Define 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 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. */
+
+#define C_ALLOCA
+#define STACK_DIRECTION -1 /* grows towards lower addresses. */
+
+/* Motorola SysV has PTYs. Not all usg3-5 systems do, so this is defined
+ here. */
+
+#define HAVE_PTYS
+#define SYSV_PTYS
+
+/* Ditto for IPC. */
+
+
+/*
+ * we now have job control in R32V1
+ */
+#undef NOMULTIPLEJOBS
+
+/*
+ * we have bcopy, bzero, bcmp in libc.a (what isn't in libc.a?)
+ */
+#define BSTRING
+
+/*
+ * sockets are in R32V1
+ */
+#define HAVE_SOCKETS
+
+/*
+ * we have the wrong name for networking libs
+ */
+#undef LIBX11_SYSTEM
+#define LIBX11_SYSTEM -lnsl -lbsd
+
+/*
+ * we have Berkeley style <sys/time.h>
+ */
+#define HAVE_TIMEVAL
+#define HAVE_GETTIMEOFDAY
+
+/* SysV88 has select(). */
+#define HAVE_SELECT
+#define BROKEN_FIONREAD
+
+/*
+ * don't use utimes, we ain't got one - use utime() instead
+ */
+#define USE_UTIME
+
+#define LIBS_SYSTEM -lbsd -lg
+
+#define NEED_TERMIOS
+
+#define NO_SIOCTL_H
diff --git a/src/m-dpx2-200.h b/src/m-dpx2-200.h
new file mode 100644
index 00000000000..72e82102064
--- /dev/null
+++ b/src/m-dpx2-200.h
@@ -0,0 +1,4 @@
+/* m-dpx2-200.h for DPX/2 models 210, 220, etc. */
+
+#define ncl_el
+#include "m-dpx2.h"
diff --git a/src/m-dpx2-300.h b/src/m-dpx2-300.h
new file mode 100644
index 00000000000..9ea4024db2b
--- /dev/null
+++ b/src/m-dpx2-300.h
@@ -0,0 +1,4 @@
+/* m-dpx2-300.h for DPX/2 models 320, 340, and maybe others. */
+
+#define ncl_mr 1
+#include "m-dpx2.h"
diff --git a/src/m-dpx2.h b/src/m-dpx2.h
new file mode 100644
index 00000000000..442bca70455
--- /dev/null
+++ b/src/m-dpx2.h
@@ -0,0 +1,286 @@
+/* NAME:
+ * m-dpx2.h - machine description for Bull DPX/2 range
+ *
+ * SYNOPSIS:
+ * #include "s-usg5-3.h"
+ * #include "m-dpx2.h"
+ *
+ * DESCRIPTION:
+ * This header is part of GNU Emacs, and therefore
+ * falls under the FSF GPL. There should be a copy of it
+ * somewhere on your system (see below).
+ *
+ * This header file, and a _minor_ change to
+ * config.h-dist are all that are needed to build GNU
+ * Emacs-18.58 on a Bull DPX/2 model 200 or 300.
+ * The DPX/2 500 should probably use a mips based config.
+ *
+ * The only change _needed_ to config.h (copied from
+ * config.h-dist) is to define the appropriate ncl_{el,mr}
+ * pre-processor constant. Hopefully in a future release
+ * the C compiler will define this automagically :-)
+ *
+ * If you have INET and X11 loaded, define HAVE_X_WINDOWS
+ * before you include this file. If you have INET but not
+ * X11 loaded define HAVE_SOCKETS in config.h before you
+ * include this file.
+ *
+ * If you make changes to this file, please be sure to send
+ * an update to me: <sjg@melb.bull.oz.au>
+ *
+ * Please read through this file before attempting to build
+ * Emacs. You may need to set SRC_COMPAT=_SYSV in your
+ * environment or in Makefile.
+ *
+ *
+ * AMENDED:
+ * 92/02/06 12:53:06 (sjg)
+ *
+ * RELEASED:
+ * 92/02/06 12:53:07 v1.7
+ *
+ * BUGS:
+ * There is a problem when running Emacs with its own X
+ * window in that if the invoking process terminates,
+ * Emacs will terminate shortly afterwards. The following
+ * exercises the bug:
+ * $ ksh
+ * $ emacs &
+ * $ exit
+ * The emacs process will die within a few minutes of the
+ * invoking ksh's termination. Solution? Don't do the
+ * above :-)
+ *
+ * SCCSID:
+ * @(#)m-dpx2.h 1.7 92/02/06 12:53:06 (sjg)
+ */
+
+/*
+ Copyright (C) 1985, 1986 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ * You need to either un-comment one of these lines, or copy one
+ * of them to config.h before you include this file.
+ * Note that some simply define a constant and others set a value.
+ */
+
+/* #define ncl_el /* DPX/2 210,220 etc */
+/* #define ncl_mr 1 /* DPX/2 320,340 (and 360,380 ?) */
+
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+#define SHORTBITS 16 /* Number of bits in a short */
+
+#define INTBITS 32 /* Number of bits in an int */
+
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* Define BIG_ENDIAN iff lowest-numbered byte in a word
+ is the most significant byte. */
+
+#define BIG_ENDIAN
+
+/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
+ * group of arguments and treat it as an array of the arguments. */
+
+#define NO_ARG_ARRAY
+
+/* Define WORD_MACHINE if addresses and such have
+ * to be corrected before they can be used as byte counts. */
+
+/* #define WORD_MACHINE /**/
+
+/* Define how to take a char and sign-extend into an int.
+ On machines where char is signed, this is a no-op. */
+
+#define SIGN_EXTEND_CHAR(c) (c)
+
+/* Now define a symbol for the cpu type, if your compiler
+ does not define it automatically:
+ Ones defined so far include vax, m68000, ns16000, pyramid,
+ orion, tahoe, APOLLO and many others */
+
+/* /bin/cc on ncl_el and ncl_mr define m68k and mc68000 */
+
+/* Use type int rather than a union, to represent Lisp_Object */
+/* This is desirable for most machines. */
+
+#define NO_UNION_TYPE
+
+/* Define EXPLICIT_SIGN_EXTEND if XINT must explicitly sign-extend
+ the 24-bit bit field into an int. In other words, if bit fields
+ are always unsigned.
+
+ If you use NO_UNION_TYPE, this flag does not matter. */
+
+#define EXPLICIT_SIGN_EXTEND
+
+/* Data type of load average, as read out of kmem. */
+
+#define LOAD_AVE_TYPE long
+
+/* Convert that into an integer that is 100 for a load average of 1.0 */
+
+#define FSCALE 1000.0
+#define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0 / FSCALE)
+
+/* Define CANNOT_DUMP on machines where unexec does not work.
+ Then the function dump-emacs will not be defined
+ and temacs will do (load "loadup") automatically unless told otherwise. */
+
+/* #define CANNOT_DUMP /**/
+
+/* Define VIRT_ADDR_VARIES if the virtual addresses of
+ pure and impure space as loaded can vary, and even their
+ relative order cannot be relied on.
+
+ Otherwise Emacs assumes that text space precedes data space,
+ numerically. */
+
+/* #define VIRT_ADDR_VARIES /**/
+
+/* Define C_ALLOCA if this machine does not support a true alloca
+ and the one written in C should be used instead.
+ Define HAVE_ALLOCA to say that the system provides a properly
+ working alloca function and it should be used.
+ Define neither one if an assembler-language alloca
+ in the file alloca.s should be used. */
+
+#define C_ALLOCA
+/* #define HAVE_ALLOCA /**/
+
+/* Define NO_REMAP if memory segmentation makes it not work well
+ to change the boundary between the text section and data section
+ when Emacs is dumped. If you define this, the preloaded Lisp
+ code will not be sharable; but that's better than failing completely. */
+
+#define NO_REMAP
+
+/*
+ * end of the standard macro's
+ */
+
+/*
+ * a neat identifier to handle source mods (if needed)
+ */
+#define DPX2
+
+/*
+ * if we use X11, libX11.a has these...
+ */
+#ifdef HAVE_X_WINDOWS
+# undef LIBX11_SYSTEM
+# define LIBX11_SYSTEM -lnsl
+# define BSTRING
+# define HAVE_GETWD
+# define HAVE_GETTIMEOFDAY
+/*
+ * Bull's X11R3 and X11R4 libs contain random and friends.
+ * The MIT X11R5 lib does not.
+ */
+# define HAVE_RANDOM
+/*
+ * we must have INET loaded so we have sockets
+ */
+# define HAVE_SOCKETS
+#endif /* HAVE_X_WINDOWS */
+
+/*
+ * useful if you have INET loaded
+ */
+#ifdef HAVE_SOCKETS
+# define LIBS_MACHINE -linet
+#endif
+
+
+#if (defined(ncl_mr) || defined(ncl_el)) && !defined (NBPC)
+# define NBPC 4096
+#endif
+
+/*
+ * if SIGIO is defined, much of the emacs
+ * code assumes we are BSD !!
+ */
+#ifdef SIGIO
+# undef SIGIO
+#endif
+
+/*
+ * a good idea on multi-user systems :-)
+ */
+#define CLASH_DETECTION /* probably a good idea */
+#define NO_FCHMOD /* Use chmod instead. */
+
+
+#ifdef SIGTSTP
+/*
+ * sysdep.c(sys_suspend) works fine with emacs-18.58
+ * and BOS 02.00.45, if you have an earler version
+ * of Emacs and/or BOS, or have problems, or just prefer
+ * to start a sub-shell rather than suspend-emacs,
+ * un-comment out the next line.
+ */
+/* # undef SIGTSTP /* make suspend-emacs spawn a sub-shell */
+# ifdef NOMULTIPLEJOBS
+# undef NOMULTIPLEJOBS
+# endif
+#endif
+/*
+ * no we don't want this at all
+ */
+#ifdef USG_JOBCTRL
+# undef USG_JOBCTRL
+#endif
+
+
+/*
+ * X support _needs_ this
+ */
+#define HAVE_SELECT
+/*
+ * and select requires these
+ */
+#define HAVE_TIMEVAL
+#define USE_UTIME
+
+/* select also needs this header file--but not in ymakefile. */
+#ifndef NO_SHORTNAMES
+#include <sys/types.h>
+#include <sys/select.h>
+#endif
+
+#define TEXT_START 0
+/*
+ * Define the direction of stack growth.
+ */
+#define STACK_DIRECTION -1
+
+/*
+ * define _SYSV
+ * this is needed by a lot of the B.O.S include files so that
+ * what emacs wants is really included.
+ * Causes the POSIX stuff to be skipped.
+ */
+#ifndef _SYSV
+# define _SYSV
+#endif
+
+/* end of m-dpx2.h */
diff --git a/src/m-dual.h b/src/m-dual.h
new file mode 100644
index 00000000000..037da6268d7
--- /dev/null
+++ b/src/m-dual.h
@@ -0,0 +1,67 @@
+/* m- file for Dual machines using unisoft port.
+ Copyright (C) 1985 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+#define SHORTBITS 16 /* Number of bits in a short */
+
+#define INTBITS 32 /* Number of bits in an int */
+
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* Define BIG_ENDIAN iff lowest-numbered byte in a word
+ is the most significant byte. */
+
+#define BIG_ENDIAN
+
+/* XINT must explicitly sign-extend */
+
+#define EXPLICIT_SIGN_EXTEND
+
+/* Define how to take a char and sign-extend into an int.
+ On machines where char is signed, this is a no-op. */
+
+#define SIGN_EXTEND_CHAR(c) (c)
+
+/* Use type int rather than a union, to represent Lisp_Object */
+
+#define NO_UNION_TYPE
+
+/* Now define a symbol for the cpu type, if your compiler
+ does not define it automatically:
+ vax, m68000, ns16000 are the ones defined so far. */
+
+#ifndef m68000
+#define m68000
+#endif
+
+/* Data type of load average, as read out of kmem. */
+/* These are commented out since it does not really work in uniplus */
+
+/* #define LOAD_AVE_TYPE long */
+
+/* Convert that into an integer that is 100 for a load average of 1.0 */
+
+/* #define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0) */
+
+/* Change some things to avoid bugs in compiler */
+
+#define SWITCH_ENUM_BUG 1
diff --git a/src/m-elxsi.h b/src/m-elxsi.h
new file mode 100644
index 00000000000..0a27207aeb3
--- /dev/null
+++ b/src/m-elxsi.h
@@ -0,0 +1,132 @@
+/* m- file for Elxsi machine (running enix).
+ Copyright (C) 1986 Free Software Foundation, Inc.
+ Adapted by John Salmon
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+#define SHORTBITS 16 /* Number of bits in a short */
+
+#define INTBITS 32 /* Number of bits in an int */
+
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* Define BIG_ENDIAN iff lowest-numbered byte in a word
+ is the most significant byte. */
+
+/*#define BIG_ENDIAN*/
+
+/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
+ * group of arguments and treat it as an array of the arguments. */
+
+/*#define NO_ARG_ARRAY */
+
+/* Define WORD_MACHINE if addresses and such have
+ * to be corrected before they can be used as byte counts. */
+
+#define WORD_MACHINE
+
+/* Define how to take a char and sign-extend into an int.
+ On machines where char is signed, this is a no-op. */
+
+#define SIGN_EXTEND_CHAR(c) ((int)c)
+
+/* Now define a symbol for the cpu type, if your compiler
+ does not define it automatically:
+ vax, m68000, ns16000, pyramid, orion, tahoe and APOLLO
+ are the ones defined so far. */
+
+#ifndef elxsi
+#define elxsi
+#endif
+
+/* Use type int rather than a union, to represent Lisp_Object */
+/* This is desirable for most machines. */
+
+#define NO_UNION_TYPE
+
+/* Define EXPLICIT_SIGN_EXTEND if XINT must explicitly sign-extend
+ the 24-bit bit field into an int. In other words, if bit fields
+ are always unsigned.
+
+ If you use NO_UNION_TYPE, this flag does not matter. */
+
+#define EXPLICIT_SIGN_EXTEND
+
+/* Data type of load average, as read out of kmem. */
+
+/*#define LOAD_AVE_TYPE long */
+
+/* Convert that into an integer that is 100 for a load average of 1.0 */
+
+/*#define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0 / FSCALE) */
+
+/* Define CANNOT_DUMP on machines where unexec does not work.
+ Then the function dump-emacs will not be defined
+ and temacs will do (load "loadup") automatically unless told otherwise.
+
+ The Elxsi can in principle dump, but the necessary changes to
+ unexec, which involve byte-swapping, were too ugly to install.
+ If someone submits simple code that supports dumping on the Elxsi,
+ it can be installed and CANNOT_DUMP can be turned off. */
+
+#define CANNOT_DUMP
+
+/* Define VIRT_ADDR_VARIES if the virtual addresses of
+ pure and impure space as loaded can vary, and even their
+ relative order cannot be relied on.
+
+ Otherwise Emacs assumes that text space precedes data space,
+ numerically. */
+
+/* #define VIRT_ADDR_VARIES */
+
+/* Define C_ALLOCA if this machine does not support a true alloca
+ and the one written in C should be used instead.
+ Define HAVE_ALLOCA to say that the system provides a properly
+ working alloca function and it should be used.
+ Define neither one if an assembler-language alloca
+ in the file alloca.s should be used. */
+
+#define C_ALLOCA
+/*#define HAVE_ALLOCA */
+
+/* Define NO_REMAP if memory segmentation makes it not work well
+ to change the boundary between the text section and data section
+ when Emacs is dumped. If you define this, the preloaded Lisp
+ code will not be sharable; but that's better than failing completely. */
+/*#define NO_REMAP*/
+
+/* This is a guess for an alternate solution to whatever
+ problem motivated defining _sobuf in sysdep,c with extern char *_sobuf. */
+#define _sobuf xsobuf
+
+/* Address of start of text segment as loaded. */
+
+#define TEXT_START 0x800
+
+/* Tell crt0.c not to define environ. */
+
+#define DONT_NEED_ENVIRON
+
+/* The elxsi has no debugger, so might as well optimize instead
+ of trying to make a symbol table. */
+
+#define C_DEBUG_SWITCH -O
diff --git a/src/m-gec63.h b/src/m-gec63.h
new file mode 100644
index 00000000000..53ac916a191
--- /dev/null
+++ b/src/m-gec63.h
@@ -0,0 +1,79 @@
+/* m- file for gec63
+ Copyright (C) 1986 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+#define SHORTBITS 16 /* Number of bits in a short */
+
+#define INTBITS 32 /* Number of bits in an int */
+
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* GEC63 is big-endian: lowest numbered byte is most significant. */
+
+#define BIG_ENDIAN
+
+/* Define how to take a char and sign-extend into an int.
+ On machines where char is signed, this is a no-op. */
+
+#define SIGN_EXTEND_CHAR(c) (((c)<<24)>>24)
+
+/* Say this machine is a 68000 */
+
+#define gec63
+
+/* Use an int to represent Lisp_Object */
+
+#define NO_UNION_TYPE
+
+/* GEC63 has alloca in the PW/ux63 library. */
+#define LIB_STANDARD -lPW -lc
+#define HAVE_ALLOCA
+
+/* Do not define LOAD_AVE_TYPE or LOAD_AVE_CVT
+ since there is no /dev/kmem */
+
+#undef ADDR_CORRECT(x)
+#define NO_ARG_ARRAY
+
+#undef TERMCAP
+#define TERMINFO
+
+/* Define sizes of portions of a Lisp_Object. */
+#define VALBITS 22
+#define GCTYPEBITS 5
+
+#define VALAMASK (((1<<VALBITS) - 1)| 0xF0000000L)
+
+#define XTYPE(a) ((enum Lisp_Type) (((a) >> VALBITS) & GCTYPEMASK))
+#define XSETTYPE(a, b) ((a) = ((a) & VALAMASK) + ((int)(b) << VALBITS))
+
+#define XPNTR(a) ((a) & VALAMASK)
+#define XSETPNTR(a, b) ((a) = ((a) & ~VALAMASK) + ((b) & VALAMASK))
+
+#define XSET(var, type, ptr) \
+ ((var) = ((int)(type) << VALBITS) + ((int) (ptr) & VALAMASK))
+
+/* Move some garbage-collector flag bits to different bit positions. */
+#define ARRAY_MARK_FLAG (1 << 27)
+#define DONT_COPY_FLAG (1 << 26)
+
+#define NO_REMAP
diff --git a/src/m-gould.h b/src/m-gould.h
new file mode 100644
index 00000000000..9c86a492ef2
--- /dev/null
+++ b/src/m-gould.h
@@ -0,0 +1,127 @@
+/* m- file for Gould with UTX/32 2.0. (See MACHINES for older versions.)
+ Copyright (C) 1986 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+#define SHORTBITS 16 /* Number of bits in a short */
+
+#define INTBITS 32 /* Number of bits in an int */
+
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* Define BIG_ENDIAN iff lowest-numbered byte in a word
+ is the most significant byte. */
+
+#define BIG_ENDIAN
+
+/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
+ * group of arguments and treat it as an array of the arguments. */
+
+#define NO_ARG_ARRAY
+
+/* Define WORD_MACHINE if addresses and such have
+ * to be corrected before they can be used as byte counts. */
+
+/* #define WORD_MACHINE */
+
+/* Define how to take a char and sign-extend into an int.
+ On machines where char is signed, this is a no-op. */
+
+#define SIGN_EXTEND_CHAR(c) (c)
+
+/* Now define a symbol for the cpu type, if your compiler
+ does not define it automatically */
+
+#ifndef GOULD
+#define GOULD
+#endif
+
+/* Use type int rather than a union, to represent Lisp_Object */
+/* This is desirable for most machines. */
+
+#define NO_UNION_TYPE
+
+/* Define EXPLICIT_SIGN_EXTEND if XINT must explicitly sign-extend
+ the 24-bit bit field into an int. In other words, if bit fields
+ are always unsigned.
+
+ If you use NO_UNION_TYPE, this flag does not matter. */
+
+#define EXPLICIT_SIGN_EXTEND
+
+/* Data type of load average, as read out of kmem. */
+
+#define LOAD_AVE_TYPE double
+
+/* Convert that into an integer that is 100 for a load average of 1.0 */
+
+#define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0)
+
+/* Define CANNOT_DUMP on machines where unexec does not work.
+ Then the function dump-emacs will not be defined
+ and temacs will do (load "loadup") automatically unless told otherwise. */
+
+/* #define CANNOT_DUMP */
+
+/* Define VIRT_ADDR_VARIES if the virtual addresses of
+ pure and impure space as loaded can vary, and even their
+ relative order cannot be relied on.
+
+ Otherwise Emacs assumes that text space precedes data space,
+ numerically. */
+
+#define VIRT_ADDR_VARIES
+
+/* Define C_ALLOCA if this machine does not support a true alloca
+ and the one written in C should be used instead.
+ Define HAVE_ALLOCA to say that the system provides a properly
+ working alloca function and it should be used.
+ Define neither one if an assembler-language alloca
+ in the file alloca.s should be used. */
+
+#define C_ALLOCA
+#define STACK_DIRECTION -1 /* grows towards lower addresses on Gould UTX/32 */
+
+/* No need to extend the user stack. */
+
+/* #define LD_SWITCH_MACHINE */
+
+/* -g is broken on the Gould. */
+
+#define C_DEBUG_SWITCH
+
+/* Comparing pointers as unsigned ints tickles a bug in older compilers. */
+
+#define PNTR_COMPARISON_TYPE int
+
+/* The GOULD machine counts the a.out file header as part of the text. */
+
+#define A_TEXT_OFFSET(HDR) sizeof (HDR)
+
+/* Machine-dependent action when about to dump an executable file. */
+
+#define ADJUST_EXEC_HEADER \
+ unexec_text_start = hdr.a_txbase + sizeof (hdr);
+
+/* We use the system's crt0.o. Somehow it avoids losing
+ with `environ' the way most standard crt0.o's do. */
+
+#define START_FILES pre-crt0.o /lib/crt0.o
diff --git a/src/m-hp9000s300.h b/src/m-hp9000s300.h
new file mode 100644
index 00000000000..ed0bb4e502f
--- /dev/null
+++ b/src/m-hp9000s300.h
@@ -0,0 +1,202 @@
+/* m- file for hp9000 series 200 or 300
+ Copyright (C) 1985 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+
+/* Define NOMULTIPLEJOBS on versions of HPUX before 6.5. */
+
+/* #define NOMULTIPLEJOBS */
+
+/* Define this symbol if you are running a version of HP-UX
+ which predates version 6.01 */
+
+/* #define HPUX_5 */
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+#define SHORTBITS 16 /* Number of bits in a short */
+
+#define INTBITS 32 /* Number of bits in an int */
+
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* Define BIG_ENDIAN iff lowest-numbered byte in a word
+ is the most significant byte. */
+
+#define BIG_ENDIAN
+
+/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
+ * group of arguments and treat it as an array of the arguments. */
+
+/* #define NO_ARG_ARRAY */
+
+/* Define WORD_MACHINE if addresses and such have
+ * to be corrected before they can be used as byte counts. */
+
+/* #define WORD_MACHINE */
+
+/* Define how to take a char and sign-extend into an int.
+ On machines where char is signed, this is a no-op. */
+
+#define SIGN_EXTEND_CHAR(c) (c)
+
+/* Now define a symbol for the cpu type, if your compiler
+ does not define it automatically. */
+
+#ifndef hp9000s300
+#define hp9000s300
+#endif
+
+/* Use type int rather than a union, to represent Lisp_Object */
+/* This is desirable for most machines. */
+
+#define NO_UNION_TYPE
+
+/* Define EXPLICIT_SIGN_EXTEND if XINT must explicitly sign-extend
+ the 24-bit bit field into an int. In other words, if bit fields
+ are always unsigned.
+
+ If you use NO_UNION_TYPE, this flag does not matter. */
+
+#define EXPLICIT_SIGN_EXTEND
+
+/* Data type of load average, as read out of kmem. */
+
+#define LOAD_AVE_TYPE double
+
+/* Convert that into an integer that is 100 for a load average of 1.0 */
+
+#define LOAD_AVE_CVT(x) ((int) ((x) * 100.0))
+
+/* Define CANNOT_DUMP on machines where unexec does not work.
+ Then the function dump-emacs will not be defined
+ and temacs will do (load "loadup") automatically unless told otherwise. */
+
+/* #define CANNOT_DUMP */
+
+/* Define VIRT_ADDR_VARIES if the virtual addresses of
+ pure and impure space as loaded can vary, and even their
+ relative order cannot be relied on.
+
+ Otherwise Emacs assumes that text space precedes data space,
+ numerically. */
+
+/* #define VIRT_ADDR_VARIES */
+
+/* For University of Utah 4.3bsd implemetation on HP300s.
+ The #ifndef __GNUC__ definitions are required for the "standard" cc,
+ a very old, brain-dead version of PCC. */
+
+#ifdef BSD4_3
+/* Tell crt0.c that this is an ordinary 68020. */
+#undef hp9000s300
+#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 */
+#endif
+
+#undef LOAD_AVE_TYPE
+#undef LOAD_AVE_CVT
+#define LOAD_AVE_TYPE long
+#define LOAD_AVE_CVT(x) ((int) (((double) (x)) / 2048.0 * 100.0))
+
+#endif /* BSD4_3 */
+
+#ifndef BSD4_3
+/* The following definitions are for HPUX only. */
+
+/* The symbol in the kernel where the load average is found
+ is named _avenrun on this machine. */
+
+#define LDAV_SYMBOL "_avenrun"
+
+/* This library is needed with -g, on the 200/300 only. */
+
+#if !defined(__GNUC__) || defined(__HPUX_ASM__)
+#define LIBS_DEBUG /usr/lib/end.o
+#endif
+
+/* The symbol FIONREAD is defined, but the feature does not work
+ on the 200/300. */
+
+#define BROKEN_FIONREAD
+
+/* In older versions of hpux, for unknown reasons, S_IFLNK is defined
+ even though symbolic links do not exist.
+ Make sure our conditionals based on S_IFLNK are not confused.
+
+ Here we assume that stat.h is included before config.h
+ so that we can override it here.
+
+ Version 6 of HP-UX has symbolic links. */
+
+#ifdef HPUX_5
+#undef S_IFLNK
+#endif
+
+/* Define the BSTRING functions in terms of the sysV functions.
+ Version 6 of HP-UX supplies these in the BSD library,
+ but that library has reported bugs in `signal'. */
+
+/* #ifdef HPUX_5 */
+#define bcopy(a,b,s) memcpy (b,a,s)
+#define bzero(a,s) memset (a,0,s)
+#define bcmp memcmp
+/* #endif */
+
+/* On USG systems these have different names.
+ Version 6 of HP-UX supplies these in the BSD library,
+ which we currently want to avoid using. */
+
+/* #ifdef HPUX_5 */
+#define index strchr
+#define rindex strrchr
+/* #endif */
+
+/* Define C_SWITCH_MACHINE to be +X if you want the s200/300
+ * Emacs to run on both 68010 and 68020 based hp-ux's.
+ *
+ * Define OLD_HP_ASSEMBLER if you have an ancient assembler
+ *
+ * Define HPUX_68010 if you are using the new assembler but
+ * compiling for a s200 (upgraded) or s310. 68010 based
+ * processor without 68881.
+ */
+
+/* These switches increase the size of some internal C compiler tables.
+ They are required for compiling the X11 interface files. */
+
+#ifndef HPUX_5
+#ifndef __GNUC__
+#define C_SWITCH_MACHINE -Wc,-Nd4000,-Ns3000
+#endif
+#endif
+
+/* Define NEED_BSDTTY if you have such. */
+
+#ifndef NOMULTIPLEJOBS
+#define NEED_BSDTTY
+#endif
+
+#endif /* not BSD4_3 */
diff --git a/src/m-hp9000s800.h b/src/m-hp9000s800.h
new file mode 100644
index 00000000000..a56051ac659
--- /dev/null
+++ b/src/m-hp9000s800.h
@@ -0,0 +1,189 @@
+/* m- file for hp9000 series 800 machines.
+ Copyright (C) 1987 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+#define SHORTBITS 16 /* Number of bits in a short */
+
+#define INTBITS 32 /* Number of bits in an int */
+
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* Define BIG_ENDIAN iff lowest-numbered byte in a word
+ is the most significant byte. */
+
+#define BIG_ENDIAN
+
+/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
+ * group of arguments and treat it as an array of the arguments. */
+
+#define NO_ARG_ARRAY
+
+/* Define WORD_MACHINE if addresses and such have
+ * to be corrected before they can be used as byte counts. */
+
+#undef WORD_MACHINE
+
+/* Define how to take a char and sign-extend into an int.
+ On machines where char is signed, this is a no-op. */
+
+#define SIGN_EXTEND_CHAR(c) (c)
+
+/* Now define a symbol for the cpu type, if your compiler
+ does not define it automatically:
+ Ones defined so far include vax, m68000, ns16000, pyramid,
+ orion, tahoe, APOLLO and many others */
+#ifndef hp9000s800
+# define hp9000s800
+#endif
+
+/* Use type int rather than a union, to represent Lisp_Object */
+/* This is desirable for most machines. */
+
+#define NO_UNION_TYPE
+
+/* Define EXPLICIT_SIGN_EXTEND if XINT must explicitly sign-extend
+ the 24-bit bit field into an int. In other words, if bit fields
+ are always unsigned.
+
+ If you use NO_UNION_TYPE, this flag does not matter. */
+
+#define EXPLICIT_SIGN_EXTEND
+
+/* Data type of load average, as read out of kmem. */
+
+#define LOAD_AVE_TYPE double
+
+/* Convert that into an integer that is 100 for a load average of 1.0 */
+
+#define LOAD_AVE_CVT(x) ((int) (x * 100.0))
+
+
+/* Define CANNOT_DUMP on machines where unexec does not work.
+ Then the function dump-emacs will not be defined
+ and temacs will do (load "loadup") automatically unless told otherwise. */
+
+#undef CANNOT_DUMP
+
+/* Define VIRT_ADDR_VARIES if the virtual addresses of
+ pure and impure space as loaded can vary, and even their
+ relative order cannot be relied on.
+
+ Otherwise Emacs assumes that text space precedes data space,
+ numerically. */
+
+#define VIRT_ADDR_VARIES
+
+/* Define C_ALLOCA if this machine does not support a true alloca
+ and the one written in C should be used instead.
+ Define HAVE_ALLOCA to say that the system provides a properly
+ working alloca function and it should be used.
+ Define neither one if an assembler-language alloca
+ in the file alloca.s should be used. */
+
+#define C_ALLOCA
+/* #define HAVE_ALLOCA */
+
+/* the data segment on this machine always starts at address 0x40000000. */
+
+#define DATA_SEG_BITS 0x40000000
+
+#define VALBITS 26
+#define GCTYPEBITS 5
+
+#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
+ code will not be sharable; but that's better than failing completely. */
+
+#define NO_REMAP
+
+/* This machine requires completely different unexec code
+ which lives in a separate file. Specify the file name. */
+
+#define UNEXEC unexhp9k800.o
+
+#define LIBS_MACHINE
+#define LIBS_DEBUG
+
+/* Define NEED_BSDTTY if you have such. */
+
+#define NEED_BSDTTY
+
+/* The standard definitions of these macros would work ok,
+ but these are faster because the constants are short. */
+
+
+#define XUINT(a) (((unsigned)(a) << INTBITS-VALBITS) >> INTBITS-VALBITS)
+
+#define XSET(var, type, ptr) \
+ ((var) = ((int)(type) << VALBITS) + (((unsigned) (ptr) << INTBITS-VALBITS) >> INTBITS-VALBITS))
+
+#define XSETINT(a, b) XSET(a, XTYPE(a), b)
+#define XSETUINT(a, b) XSET(a, XTYPE(a), b)
+#define XSETPNTR(a, b) XSET(a, XTYPE(a), b)
+#define XMARKBIT(a) ((a) < 0)
+#define XSETMARKBIT(a,b) ((a) = ((b) ? (a)|MARKBIT : (a) & ~MARKBIT))
+
+#if 0 /* Loses when sign bit of type field is set. */
+#define XUNMARK(a) ((a) = (((a) << INTBITS-GCTYPEBITS-VALBITS) >> INTBITS-GCTYPEBITS-VALBITS))
+#endif
+
+/* The symbol in the kernel where the load average is found
+ is named _avenrun. At this time there are two major flavors
+ of hp-ux (there is the s800 and s300 (s200) flavors). The
+ differences are thusly moved to the corresponding m- file.
+*/
+
+/* no underscore please */
+#define LDAV_SYMBOL "avenrun"
+#define CPTIME_SYMBOL "cp_time"
+#define DKXFER_SYMBOL "dk_xfer"
+
+#if 0 /* No longer true in HPUX 7.0 */
+/* In hpux, for unknown reasons, S_IFLNK is defined even though
+ symbolic links do not exist.
+ Make sure our conditionals based on S_IFLNK are not confused.
+
+ Here we assume that stat.h is included before config.h
+ so that we can override it here. */
+
+#undef S_IFLNK
+#endif
+
+/* Define the BSTRING functions in terms of the sysV functions. */
+
+#define bcopy(a,b,s) memcpy (b,a,s)
+#define bzero(a,s) memset (a,0,s)
+#define bcmp memcmp
+
+/* On USG systems these have different names. */
+
+#define index strchr
+#define rindex strrchr
+
+/* Include the file bsdtty.h, since job control exists. */
+#define NEED_BSDTTY
diff --git a/src/m-ibmps2-aix.h b/src/m-ibmps2-aix.h
new file mode 100644
index 00000000000..1fff0429753
--- /dev/null
+++ b/src/m-ibmps2-aix.h
@@ -0,0 +1,235 @@
+/* m- file for ibm ps/2 aix386.
+ Copyright (C) 1989 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+#define SHORTBITS 16 /* Number of bits in a short */
+
+#define INTBITS 32 /* Number of bits in an int */
+
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* i386 is not big-endian: lowest numbered byte is least significant. */
+
+/* #undef BIG_ENDIAN */
+
+/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
+ * group of arguments and treat it as an array of the arguments. */
+
+/* #define NO_ARG_ARRAY */
+
+/* Define WORD_MACHINE if addresses and such have
+ * to be corrected before they can be used as byte counts. */
+
+/* #define WORD_MACHINE */
+
+/* Define how to take a char and sign-extend into an int.
+ On machines where char is signed, this is a no-op. */
+
+#define SIGN_EXTEND_CHAR(c) ((signed char)(c))
+
+/* Now define a symbol for the cpu type, if your compiler
+ does not define it automatically:
+ Ones defined so far include vax, m68000, ns16000, pyramid,
+ orion, tahoe, APOLLO and many others */
+
+#define INTEL386
+#define aix386
+#undef SYSTEM_TYPE
+#define SYSTEM_TYPE "ibm-aix-386"
+
+/* Use type int rather than a union, to represent Lisp_Object */
+
+#define NO_UNION_TYPE
+
+/* crt0.c, if it is used, should use the i386-bsd style of entry.
+ with no extra dummy args. On USG and XENIX,
+ NO_REMAP says this isn't used. */
+
+#define CRT0_DUMMIES bogus_fp,
+
+/* crt0.c should define a symbol `start' and do .globl with a dot. */
+
+#define DOT_GLOBAL_START
+
+/* USG systems do not actually support the load average,
+so disable it for them. */
+
+/* Define CANNOT_DUMP on machines where unexec does not work.
+ Then the function dump-emacs will not be defined
+ and temacs will do (load "loadup") automatically unless told otherwise. */
+
+/* #define CANNOT_DUMP */
+
+/* Define VIRT_ADDR_VARIES if the virtual addresses of
+ pure and impure space as loaded can vary, and even their
+ relative order cannot be relied on.
+
+ Otherwise Emacs assumes that text space precedes data space,
+ numerically. */
+
+/* #define VIRT_ADDR_VARIES */
+
+/* Define addresses, macros, change some setup for dump */
+
+#define NO_REMAP
+#undef static
+ /* Since NO_REMAP, problem with statics doesn't exist */
+
+#ifdef USG5_3
+#define TEXT_START 0x00000000
+#else
+#define TEXT_START 0x00400000
+#define TEXT_END 0
+#define DATA_START 0x00800000
+#define DATA_END 0
+
+/* The data segment in this machine always starts at address 0x00800000.
+ An address of data cannot be stored correctly in a Lisp object;
+ we always lose the high bits. We must tell XPNTR to add them back. */
+
+#define DATA_SEG_BITS 0x00800000
+#endif
+
+#if 0 /* I refuse to promulgate a recommendation that would make
+ users unable to debug - RMS. */
+/* delete the following line to foil optimization, enable debugging */
+#define C_DEBUG_SWITCH -O
+#endif
+
+#define BSTRING
+#define HAVE_DUP2
+#define HAVE_GETTIMEOFDAY
+#define HAVE_SELECT
+#define HAVE_TIMEVAL
+#define HAVE_VFORK
+#define HAVE_SETSID
+#define HAVE_TCATTR
+
+/*
+ * Define SYSV_SYSTEM_DIR to use the V.3 getdents/readir
+ * library functions. Almost, but not quite the same as
+ * the 4.2 functions
+ */
+#define SYSV_SYSTEM_DIR
+#define HAVE_CLOSEDIR /* This system, unlike ordinary SYSV, has closedir. */
+
+/*
+ * Define NONSYSTEM_DIR_LIBRARY to make Emacs emulate
+ * The 4.2 opendir, etc., library functions.
+ */
+#undef NONSYSTEM_DIR_LIBRARY
+
+/* But don't use utimes() -- it causes SIGSEGV! Use utime() instead. */
+#define USE_UTIME
+
+/* AIX defines FIONREAD, but it does not work. */
+#define BROKEN_FIONREAD
+
+/* This page was added in June 1990. It may be incorrect for some versions
+ of aix, so delete it if it causes trouble. */
+
+/* AIX has sigsetmask() */
+#undef sigsetmask
+
+/* AIX386 has BSD4.3 PTYs */
+
+#define HAVE_PTYS
+
+/* AIX has IPC. It also has sockets, and either can be used for client/server.
+ I would suggest the client/server code be changed to use HAVE_SOCKETS rather
+ than BSD as the conditional if sockets provide any advantages. */
+
+#define HAVE_SYSVIPC
+
+/* AIX has sockets */
+
+#define HAVE_SOCKETS
+/* #define SKTPAIR */ /* SKTPAIR works, but what is advantage over pipes? */
+
+/* Specify the font for X to use. */
+
+#define X_DEFAULT_FONT "8x13"
+
+/* AIX has a wait.h. */
+
+#define HAVE_WAIT_HEADER
+
+/* Data type of load average, as read out of kmem. */
+
+#define LOAD_AVE_TYPE long /* For AIX (sysV) */
+
+/* Convert that into an integer that is 100 for a load average of 1.0 */
+
+#define LOAD_AVE_CVT(x) (int) (((double) (x)/65535.0) * 100.0)
+
+/* 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 -lc
+#endif
+/* -g fails to work, so it is omitted. */
+/* tranle says that -fstrength-reduce does not help. */
+#define C_DEBUG_SWITCH -O
+#else
+#define C_ALLOCA
+#define STACK_DIRECTION -1 /* tell alloca.c which way it grows */
+#define LIBS_MACHINE -lbsd -lrts
+#endif
+
+#define OBJECTS_MACHINE hftctl.o
+#define LD_SWITCH_MACHINE -T0x00400000 -K -e start
+
+#ifdef USG5_3
+#define XICCC
+#define HAVE_GETWD
+#define HAVE_RENAME
+#undef LD_SWITCH_MACHINE
+#define LD_SWITCH_MACHINE -T0x0 -K -e start
+
+/* Things defined in s-usg5-3.h that need to be overridden. */
+#undef NOMULTIPLEJOBS
+#undef BROKEN_TIOCGETC
+#undef LIBX10_SYSTEM
+#undef LIBX11_SYSTEM
+#endif
+
+/* Shared libraries are supported in a patch release of ps/2 1.2.1.
+ If the system has them, the user can turn them on, and this code
+ will make them work. */
+#ifdef USG_SHARED_LIBRARIES
+#define ORDINARY_LINK
+#undef LIB_STANDARD
+#undef LD_SWITCH_MACHINE
+#if __GNUC__ > 1
+#define LD_SWITCH_MACHINE -shlib
+#endif
+#endif
diff --git a/src/m-ibmrs6000.h b/src/m-ibmrs6000.h
new file mode 100644
index 00000000000..7994f925be7
--- /dev/null
+++ b/src/m-ibmrs6000.h
@@ -0,0 +1,151 @@
+/* R2 AIX machine/system dependent defines
+ Copyright (C) 1988 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+#define SHORTBITS 16 /* Number of bits in a short */
+
+#define INTBITS 32 /* Number of bits in an int */
+
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* Define BIG_ENDIAN iff lowest-numbered byte in a word
+ is the most significant byte. */
+
+#define BIG_ENDIAN 4321
+
+/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
+ * group of arguments and treat it as an array of the arguments. */
+
+#define NO_ARG_ARRAY
+
+/* Define how to take a char and sign-extend into an int.
+ On machines where char is signed, this is a no-op. */
+
+#define SIGN_EXTEND_CHAR(c) ((((int) (c)) << 24) >> 24)
+
+/* Now define a symbol for the cpu type, if your compiler
+ does not define it automatically. */
+
+#define IBMR2AIX
+
+/* Use type int rather than a union, to represent Lisp_Object */
+/* This is desirable for most machines. */
+
+#define NO_UNION_TYPE
+
+/* Define CANNOT_DUMP on machines where unexec does not work.
+ Then the function dump-emacs will not be defined
+ and temacs will do (load "loadup") automatically unless told otherwise. */
+/* #define CANNOT_DUMP */
+
+#define UNEXEC unexaix.o
+
+/* Define addresses, macros, change some setup for dump */
+
+#define NO_REMAP
+
+#define TEXT_START 0x10000000
+#define TEXT_END 0
+#define DATA_START 0x20000000
+#define DATA_END 0
+
+/* The data segment in this machine always starts at address 0x20000000.
+ An address of data cannot be stored correctly in a Lisp object;
+ we always lose the high bits. We must tell XPNTR to add them back. */
+
+#define DATA_SEG_BITS 0x20000000
+
+#ifdef CANNOT_DUMP
+/* Define shared memory segment symbols */
+
+#define PURE_SEG_BITS 0x30000000
+
+/* Use shared memory. */
+/* This is turned off because it does not always work. See etc/AIX.DUMP. */
+/* #define HAVE_SHM */
+#define SHMKEY 5305035 /* used for shared memory code segments */
+#endif /* CANNOT_DUMP */
+
+#define N_BADMAG(x) BADMAG(x)
+#define N_TXTOFF(x) A_TEXTPOS(x)
+#define N_SYMOFF(x) A_SYMPOS(x)
+#define A_TEXT_OFFSET(HDR) sizeof(HDR)
+/* #define ADJUST_EXEC_HEADER \
+ unexec_text_start += sizeof(hdr); \
+ unexec_data_start = ohdr.a_dbase
+*/
+#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 C_ALLOCA
+#define STACK_DIRECTION -1 /* tell alloca.c which way it grows */
+
+/* Specify the font for X to use. */
+
+#define X_DEFAULT_FONT "Rom14.500"
+
+/* Here override various assumptions in ymakefile */
+
+#define OBJECTS_MACHINE hftctl.o
+/* C_SWITCH_MACHINE used to have -D_BSD, but chip@tct.com says no need. */
+#define C_SWITCH_MACHINE
+#define LIBS_MACHINE -lrts
+#define START_FILES
+#define HAVE_DUP2
+#define HAVE_GETTIMEOFDAY
+#define HAVE_SYSVIPC
+#define HAVE_SETSID
+#define HAVE_GETWD
+/*** BUILD 9008 - FIONREAD problem still exists in X-Windows. ***/
+#define BROKEN_FIONREAD
+#define NO_SIOCTL_H
+
+#undef LINKER
+#define LINKER cc -Wl,-bnso,-bnodelcsect,-bI:/lib/syscalls.exp
+
+/* The header files seem to be from X11R4, but the library is not.
+ So don don't use the r4 library features. */
+
+#ifndef SPECIFY_X11R4
+#define SPECIFY_X11R4 0
+#endif
+
+#ifdef __STDC__
+#ifndef DONT_DEFINE_SIGNAL
+/* Cast the function argument to avoid warnings. */
+#define signal(sig, func) (signal (sig, (void (*) (int)) (func)))
+#endif
+#endif
+
+#if 0 /* s-aix3-1.h seems to do this. */
+/* Special way to find a pty. */
+#define PTY_ITERATION for (i = 0; i < 4; ++i)
+#define PTY_NAME_SPRINTF strcpy (pty_name, "/dev/ptc");
+#define PTY_TTY_NAME_SPRINTF strcpy (pty_name, ttyname (fd));
+#endif
diff --git a/src/m-ibmrt-aix.h b/src/m-ibmrt-aix.h
new file mode 100644
index 00000000000..4ac66567094
--- /dev/null
+++ b/src/m-ibmrt-aix.h
@@ -0,0 +1,196 @@
+/* RTPC AIX machine/system dependent defines
+ Copyright (C) 1988 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+#define SHORTBITS 16 /* Number of bits in a short */
+
+#define INTBITS 32 /* Number of bits in an int */
+
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* Define BIG_ENDIAN iff lowest-numbered byte in a word
+ is the most significant byte. */
+
+#define BIG_ENDIAN
+
+/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
+ * group of arguments and treat it as an array of the arguments. */
+
+#define NO_ARG_ARRAY
+
+/* Define how to take a char and sign-extend into an int.
+ On machines where char is signed, this is a no-op. */
+
+#define SIGN_EXTEND_CHAR(c) ((((int) (c)) << 24) >> 24)
+
+/* Now define a symbol for the cpu type, if your compiler
+ does not define it automatically. */
+
+#define IBMRTAIX
+
+#ifndef AIX
+#define AIX
+#endif
+
+/* Use type int rather than a union, to represent Lisp_Object */
+/* This is desirable for most machines. */
+
+#define NO_UNION_TYPE
+
+/* No load average information appears in the AIX kernel. VRM has this
+ info, and if anyone desires they should fix fns.c to get it out of VRM */
+
+/* Define CANNOT_DUMP on machines where unexec does not work.
+ Then the function dump-emacs will not be defined
+ and temacs will do (load "loadup") automatically unless told otherwise. */
+
+/* #define CANNOT_DUMP */
+
+/* Define addresses, macros, change some setup for dump */
+
+#undef COFF
+#define NO_REMAP
+#undef static
+ /* Since NO_REMAP, problem with statics doesn't exist */
+
+#define TEXT_START 0x10000000
+#define TEXT_END 0
+#define DATA_START 0x20000000
+#define DATA_END 0
+
+/* The data segment in this machine always starts at address 0x20000000.
+ An address of data cannot be stored correctly in a Lisp object;
+ we always lose the high bits. We must tell XPNTR to add them back. */
+
+#define DATA_SEG_BITS 0x20000000
+
+#define N_BADMAG(x) BADMAG(x)
+#define N_TXTOFF(x) A_TEXTPOS(x)
+#define N_SYMOFF(x) A_SYMPOS(x)
+#define A_TEXT_OFFSET(HDR) sizeof(HDR)
+#define ADJUST_EXEC_HEADER \
+ unexec_text_start += sizeof(hdr); \
+ unexec_data_start = ohdr.a_dbase
+#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 C_ALLOCA
+#define STACK_DIRECTION -1 /* tell alloca.c which way it grows */
+
+
+/* AIX has PTYs, so define here, along with defines needed to make them work. */
+/* AIX has one problem related to PTYs though: SIGHUP is seen by the parent */
+/* along with SIGCHLD when the child dies. Thus we need to ignore SIGHUP */
+/* once a process is begun on a PTY. EMACS may not go away when its tty */
+/* goes away because of this -- if this is a problem, either comment out the */
+/* def of HAVE_PTYS below, or set process-connection-type to nil in .emacs. */
+
+#define HAVE_PTYS
+#define PTY_ITERATION for (i=0; i<256; i++)
+#define PTY_NAME_SPRINTF sprintf (pty_name, "/dev/ptc%d", i);
+#define PTY_TTY_NAME_SPRINTF \
+ /* Check that server side not already open */ \
+ if ((ioctl(fd, PTYSTATUS, 0) & 0xFFFF) != 0) { \
+ close(fd); \
+ continue; \
+ } \
+ sprintf (pty_name, "/dev/pts%d", i);
+
+/* TIOCNOTTY isn't needed on AIX, but the rest of the conditionalized code
+ in process.c does properly begin a new process group if we fake this out.
+ On AIX 2.2 TIOCNOTTY is defined in termio.h, and this will be overriden
+ by that definition appropriately. */
+
+#define TIOCNOTTY IOCTYPE
+
+/* AIX has IPC. It also has sockets, and either can be used for client/server.
+ I would suggest the client/server code be changed to use HAVE_SOCKETS rather
+ than BSD as the conditional if sockets provide any advantages. */
+
+#define HAVE_SYSVIPC
+
+/* AIX has sockets */
+
+#define HAVE_SOCKETS
+/* #define SKTPAIR */ /* SKTPAIR works, but what is advantage over pipes? */
+
+/* Specify the font for X to use. */
+
+#define X_DEFAULT_FONT "Rom14.500"
+
+/* Here override various assumptions in ymakefile */
+
+/* On AIX 2.2.1, use these definitions instead
+#define C_SWITCH_MACHINE -I/usr/include -Nn2000
+#define LIBS_MACHINE -lrts
+#define LIBX10_MACHINE -lrts
+#define LIBX11_MACHINE -lrts
+*/
+
+#define C_SWITCH_MACHINE -I/usr/include -I/usr/include/bsd -Nn2000
+/* need to duplicate -lsock -lbsd -lrts so refs in libX can be resolved */
+/* order of lib specs in ymakefile should probably be changed. */
+#define LIBS_MACHINE -lsock -lbsd -lrts
+#define LIBX10_MACHINE -lsock -lbsd -lrts
+#define LIBX11_MACHINE -lsock -lbsd -lrts
+
+#define OBJECTS_MACHINE hftctl.o
+#define START_FILES /lib/crt0.o
+#define LD_SWITCH_MACHINE -n -T0x10000000 -K -e start
+
+#if 0 /* I refuse to promulgate a recommendation that would make
+ users unable to debug - RMS. */
+/* delete the following line to foil optimization, enable debugging */
+#define C_DEBUG_SWITCH -O
+#endif
+
+
+/* Setup to do some things BSD way - these won't work previous to AIX 2.1.2 */
+
+#define bzero(t,s) (memset((t),(0),(s)))
+#define bcmp(f,t,s) (memcmp((t),(f),(s)))
+#define vfork fork
+#define killpg( pgrp, sig ) (kill( -(pgrp), (sig) ))
+
+#define BSTRING
+#define HAVE_DUP2
+#define HAVE_GETTIMEOFDAY
+#define HAVE_SELECT
+#define HAVE_TIMEVAL
+#define HAVE_VFORK
+
+/* But don't use utimes() -- it causes SIGSEGV! Use utime() instead. */
+#define USE_UTIME
+
+/* getwd is in same object module as getcwd in AIX 2.2, but doesn't exist */
+/* at all in 2.1.2. So, for compatibility, avoid name collision on 2.2 */
+#define getwd AIX_getwd
+
+/* AIX defines FIONREAD, but it does not work. */
+#define BROKEN_FIONREAD
diff --git a/src/m-ibmrt.h b/src/m-ibmrt.h
new file mode 100644
index 00000000000..b8b4cc365a7
--- /dev/null
+++ b/src/m-ibmrt.h
@@ -0,0 +1,135 @@
+/* RTPC machine dependent defines
+ Copyright (C) 1986 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+#define SHORTBITS 16 /* Number of bits in a short */
+
+#define INTBITS 32 /* Number of bits in an int */
+
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* Define BIG_ENDIAN iff lowest-numbered byte in a word
+ is the most significant byte. */
+
+#define BIG_ENDIAN
+
+/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
+ * group of arguments and treat it as an array of the arguments. */
+
+#define NO_ARG_ARRAY
+
+/* Define WORD_MACHINE if addresses and such have
+ * to be corrected before they can be used as byte counts. */
+
+#define WORD_MACHINE
+
+/* Define how to take a char and sign-extend into an int.
+ On machines where char is signed, this is a no-op. */
+
+#define SIGN_EXTEND_CHAR(c) ((signed char)(c))
+
+/* Now define a symbol for the cpu type, if your compiler
+ does not define it automatically. */
+
+#define ibmrt
+#define romp /* unfortunately old include files are hanging around. */
+
+/* Use type int rather than a union, to represent Lisp_Object */
+/* This is desirable for most machines. */
+
+#define NO_UNION_TYPE
+
+/* Define EXPLICIT_SIGN_EXTEND if XINT must explicitly sign-extend
+ the 24-bit bit field into an int. In other words, if bit fields
+ are always unsigned.
+
+ If you use NO_UNION_TYPE, this flag does not matter. */
+
+#define EXPLICIT_SIGN_EXTEND
+
+/* Data type of load average, as read out of kmem. */
+
+#define LOAD_AVE_TYPE double /* For AIS (sysV) */
+
+/* Convert that into an integer that is 100 for a load average of 1.0 */
+
+#define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0)
+
+/* Define CANNOT_DUMP on machines where unexec does not work.
+ Then the function dump-emacs will not be defined
+ and temacs will do (load "loadup") automatically unless told otherwise. */
+
+/* #define CANNOT_DUMP */
+
+/* Define VIRT_ADDR_VARIES if the virtual addresses of
+ pure and impure space as loaded can vary, and even their
+ relative order cannot be relied on.
+
+ Otherwise Emacs assumes that text space precedes data space,
+ numerically. */
+
+#undef VIRT_ADDR_VARIES
+
+/* Define C_ALLOCA if this machine does not support a true alloca
+ and the one written in C should be used instead.
+ Define HAVE_ALLOCA to say that the system provides a properly
+ working alloca function and it should be used.
+ Define neither one if an assembler-language alloca
+ in the file alloca.s should be used. */
+
+#define HAVE_ALLOCA
+
+/* The data segment in this machine starts at a fixed address.
+ An address of data cannot be stored correctly in a Lisp object;
+ we always lose the high bits. We must tell XPNTR to add them back. */
+
+#define DATA_SEG_BITS 0x10000000
+#define DATA_START 0x10000000
+
+/* The text segment always starts at a fixed address.
+ This way we don't need to have a label _start defined. */
+#define TEXT_START 0
+
+#define VALBITS 26
+#define GCTYPEBITS 5
+
+/* Taking a pointer to a char casting it as int pointer */
+/* and then taking the int which the int pointer points to */
+/* is practically guaranteed to give erroneous results */
+
+#define NEED_ERRNO
+
+#define SKTPAIR
+
+/* BSD has BSTRING. */
+
+#define BSTRING
+
+/* Special switches to give the C compiler. */
+
+#define C_SWITCH_MACHINE -Dalloca=_Alloca
+
+/* Don't attempt to relabel some of the data as text when dumping.
+ It does not work because their virtual addresses are not consecutive.
+ This enables us to use the standard crt0.o. */
+
+#define NO_REMAP
diff --git a/src/m-intel386.h b/src/m-intel386.h
new file mode 100644
index 00000000000..62f795bb596
--- /dev/null
+++ b/src/m-intel386.h
@@ -0,0 +1,184 @@
+/* m- file for intel 386.
+ Copyright (C) 1987 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+#define SHORTBITS 16 /* Number of bits in a short */
+
+#define INTBITS 32 /* Number of bits in an int */
+
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* i386 is not big-endian: lowest numbered byte is least significant. */
+
+/* #undef BIG_ENDIAN */
+
+/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
+ * group of arguments and treat it as an array of the arguments. */
+
+/* #define NO_ARG_ARRAY */
+
+/* Define WORD_MACHINE if addresses and such have
+ * to be corrected before they can be used as byte counts. */
+
+/* #define WORD_MACHINE */
+
+/* Define how to take a char and sign-extend into an int.
+ On machines where char is signed, this is a no-op. */
+
+#define SIGN_EXTEND_CHAR(c) (c)
+
+/* Now define a symbol for the cpu type, if your compiler
+ does not define it automatically:
+ Ones defined so far include vax, m68000, ns16000, pyramid,
+ orion, tahoe, APOLLO and many others */
+
+#define INTEL386
+
+/* Use type int rather than a union, to represent Lisp_Object */
+
+#define NO_UNION_TYPE
+
+/* crt0.c, if it is used, should use the i386-bsd style of entry.
+ with no extra dummy args. On USG and XENIX,
+ NO_REMAP says this isn't used. */
+
+#define CRT0_DUMMIES bogus_fp,
+
+/* crt0.c should define a symbol `start' and do .globl with a dot. */
+
+#define DOT_GLOBAL_START
+
+#ifdef XENIX
+/* Data type of load average, as read out of kmem. */
+#define LOAD_AVE_TYPE short
+
+/* Convert that into an integer that is 100 for a load average of 1.0 */
+#define LOAD_AVE_CVT(x) (((double) (x)) * 100.0 / FSCALE)
+
+#define FSCALE 256.0 /* determined by experimentation... */
+#endif
+
+#ifdef USG5_4 /* Older USG systems do not support the load average. */
+/* Data type of load average, as read out of kmem. */
+
+#define LOAD_AVE_TYPE long
+
+/* Convert that into an integer that is 100 for a load average of 1.0 */
+/* This is totally uncalibrated. */
+
+#define LOAD_AVE_CVT(x) ((int) (((double) (x)) * 100.0 / FSCALE))
+#define FSCALE 256.0
+#endif
+
+#ifdef J386BSD
+/* Data type of load average, as read out of kmem. */
+
+#define LOAD_AVE_TYPE unsigned long
+
+/* Convert that into an integer that is 100 for a load average of 1.0. */
+#define LOAD_AVE_CVT(x) ((int) (((double) (x)) * 100.0 / FSCALE))
+
+#endif /* J386BSD */
+
+/* Define CANNOT_DUMP on machines where unexec does not work.
+ Then the function dump-emacs will not be defined
+ and temacs will do (load "loadup") automatically unless told otherwise. */
+
+/* #define CANNOT_DUMP */
+
+/* Define VIRT_ADDR_VARIES if the virtual addresses of
+ pure and impure space as loaded can vary, and even their
+ relative order cannot be relied on.
+
+ Otherwise Emacs assumes that text space precedes data space,
+ numerically. */
+
+/* #define VIRT_ADDR_VARIES */
+
+#ifdef XENIX
+#define VALBITS 26
+#define GCTYPEBITS 5
+
+/* 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
+
+/* Since cannot purify, use standard Xenix 386 startup code. */
+
+#define START_FILES /lib/386/Sseg.o pre-crt0.o /lib/386/Scrt0.o
+
+/* These really use terminfo. */
+
+#define LIBS_TERMCAP /lib/386/Slibcurses.a \
+ /lib/386/Slibtinfo.a /lib/386/Slibx.a
+
+/* Standard libraries for this machine. Since `-l' doesn't work in `ld'. */
+/* '__fltused' is unresolved w/o Slibcfp.a */
+#define LIB_STANDARD /lib/386/Slibcfp.a /lib/386/Slibc.a
+#else /* not XENIX */
+
+#ifdef USG
+#ifdef USG5_4
+#define C_ALLOCA
+#endif /* USG5_4 */
+#ifndef LIB_STANDARD
+#if defined (__GNUC__) || defined (C_ALLOCA)
+#define LIB_STANDARD -lc
+#else
+#define LIB_STANDARD -lPW -lc
+#endif
+#endif /* no LIB_STANDARD */
+#ifndef C_ALLOCA
+#define HAVE_ALLOCA
+#endif
+#define NO_REMAP
+#define TEXT_START 0
+#endif /* USG */
+#endif /* not XENIX */
+
+#ifdef BSD
+#define HAVE_ALLOCA
+#endif /* BSD */
+
+/* If compiling with GCC, let GCC implement alloca. */
+#if defined(__GNUC__) && !defined(alloca)
+#define alloca(n) __builtin_alloca(n)
+#define HAVE_ALLOCA
+#endif
+
+#ifdef USG
+#ifdef __STDC__
+#ifndef DONT_DEFINE_SIGNAL
+/* Cast the function argument to avoid warnings. */
+#define signal(sig, func) (signal (sig, (void (*) (int)) (func)))
+#endif
+#endif
+#endif
+
+#ifdef USG5_4
+#define DATA_SEG_BITS 0x08000000
+#endif
diff --git a/src/m-intel860.h b/src/m-intel860.h
new file mode 100644
index 00000000000..c35c8319a3c
--- /dev/null
+++ b/src/m-intel860.h
@@ -0,0 +1,116 @@
+/* m- file for intel 860.
+ Copyright (C) 1987 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+#define SHORTBITS 16 /* Number of bits in a short */
+
+#define INTBITS 32 /* Number of bits in an int */
+
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* i860 is not big-endian: lowest numbered byte is least significant. */
+
+/* #undef BIG_ENDIAN */
+
+/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
+ * group of arguments and treat it as an array of the arguments. */
+
+#define NO_ARG_ARRAY
+
+/* Define WORD_MACHINE if addresses and such have
+ * to be corrected before they can be used as byte counts. */
+
+/* #define WORD_MACHINE */
+
+/* Define how to take a char and sign-extend into an int.
+ On machines where char is signed, this is a no-op. */
+
+#define SIGN_EXTEND_CHAR(c) (c)
+
+/* Now define a symbol for the cpu type, if your compiler
+ does not define it automatically:
+ Ones defined so far include vax, m68000, ns16000, pyramid,
+ orion, tahoe, APOLLO and many others */
+
+#define INTEL860
+
+#undef DATA_SEG_BITS
+
+/* Use type int rather than a union, to represent Lisp_Object */
+
+#define NO_UNION_TYPE
+
+/* crt0.c, if it is used, should use the i386-bsd style of entry.
+ with no extra dummy args. On USG and XENIX,
+ NO_REMAP says this isn't used. */
+
+#define CRT0_DUMMIES bogus_fp,
+
+/* crt0.c should define a symbol `start' and do .globl with a dot. */
+
+#define DOT_GLOBAL_START
+
+/* These things for load average are right for USG V.4. */
+
+/* Data type of load average, as read out of kmem. */
+#define LOAD_AVE_TYPE long
+/* Convert that into an integer that is 100 for a load average of 1.0 */
+#define LOAD_AVE_CVT(x) ((int) (((double) (x)) * 100.0 / FSCALE))
+#define FSCALE 256.0 /* determined by experimentation... */
+
+/* Define CANNOT_DUMP on machines where unexec does not work.
+ Then the function dump-emacs will not be defined
+ and temacs will do (load "loadup") automatically unless told otherwise. */
+
+/* #define CANNOT_DUMP */
+
+/* Define VIRT_ADDR_VARIES if the virtual addresses of
+ pure and impure space as loaded can vary, and even their
+ relative order cannot be relied on.
+
+ Otherwise Emacs assumes that text space precedes data space,
+ numerically. */
+
+/* #define VIRT_ADDR_VARIES */
+
+
+#ifdef USG
+
+#ifndef LIB_STANDARD
+#define LIB_STANDARD -lPW -lc
+#endif
+
+#define C_ALLOCA
+/* #define HAVE_ALLOCA */
+#define NO_REMAP
+#define TEXT_START 0
+#endif /* USG */
+
+#ifdef BSD
+#define HAVE_ALLOCA
+#endif /* BSD */
+
+/* If compiling with GCC, let GCC implement alloca. */
+#if defined(__GNUC__) && !defined(alloca)
+#define alloca(n) __builtin_alloca(n)
+#define HAVE_ALLOCA
+#endif
diff --git a/src/m-iris4d.h b/src/m-iris4d.h
new file mode 100644
index 00000000000..61c827b404e
--- /dev/null
+++ b/src/m-iris4d.h
@@ -0,0 +1,190 @@
+/* m- file for Iris-4D machines. Use with s-irix3-3.h.
+ Copyright (C) 1987 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+#define SHORTBITS 16 /* Number of bits in a short */
+
+#define INTBITS 32 /* Number of bits in an int */
+
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* Define BIG_ENDIAN iff lowest-numbered byte in a word
+ is the most significant byte. */
+
+#define BIG_ENDIAN
+
+/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
+ * group of arguments and treat it as an array of the arguments. */
+
+#define NO_ARG_ARRAY
+
+/* Define WORD_MACHINE if addresses and such have
+ * to be corrected before they can be used as byte counts. */
+
+#undef WORD_MACHINE
+
+/* Define how to take a char and sign-extend into an int.
+ On machines where char is signed, this is a no-op. */
+
+#define SIGN_EXTEND_CHAR(c) ((signed char)(c))
+
+/* Now define a symbol for the cpu type, if your compiler
+ does not define it automatically:
+ Ones defined so far include vax, m68000, ns16000, pyramid,
+ orion, tahoe, APOLLO and many others */
+
+#ifndef mips
+#define mips
+#endif
+
+#ifndef IRIS_4D
+#define IRIS_4D
+#endif
+
+/* Use type int rather than a union, to represent Lisp_Object */
+/* This is desirable for most machines. */
+
+#define NO_UNION_TYPE
+
+/* Define EXPLICIT_SIGN_EXTEND if XINT must explicitly sign-extend
+ the 24-bit bit field into an int. In other words, if bit fields
+ are always unsigned.
+
+ If you use NO_UNION_TYPE, this flag does not matter. */
+
+#define EXPLICIT_SIGN_EXTEND
+
+/* Data type of load average, as read out of kmem. */
+
+#define LOAD_AVE_TYPE long /* This doesn't quite work on the 4D */
+
+/* Convert that into an integer that is 100 for a load average of 1.0 */
+
+#define LOAD_AVE_CVT(x) (int)(((double)(x)*100)/1024.0)
+
+#undef KERNEL_FILE
+#define KERNEL_FILE "/unix"
+
+/* Define CANNOT_DUMP on machines where unexec does not work.
+ Then the function dump-emacs will not be defined
+ and temacs will do (load "loadup") automatically unless told otherwise. */
+
+#undef CANNOT_DUMP
+
+/* Define VIRT_ADDR_VARIES if the virtual addresses of
+ pure and impure space as loaded can vary, and even their
+ relative order cannot be relied on.
+
+ Otherwise Emacs assumes that text space precedes data space,
+ numerically. */
+
+/* #define VIRT_ADDR_VARIES */
+
+/* Define C_ALLOCA if this machine does not support a true alloca
+ and the one written in C should be used instead.
+ Define HAVE_ALLOCA to say that the system provides a properly
+ working alloca function and it should be used.
+ Define neither one if an assembler-language alloca
+ in the file alloca.s should be used. */
+
+#define C_ALLOCA
+/* #define HAVE_ALLOCA */
+
+/* Define NO_REMAP if memory segmentation makes it not work well
+ to change the boundary between the text section and data section
+ when Emacs is dumped. If you define this, the preloaded Lisp
+ code will not be sharable; but that's better than failing completely. */
+
+#define NO_REMAP
+
+/* This machine requires completely different unexec code
+ which lives in a separate file. Specify the file name. */
+
+#define UNEXEC unexmips.o
+
+#define TEXT_START 0x400000
+
+/*
+ * DATA_SEG_BITS forces that bit to be or'd in with any pointers which
+ * are trying to access pure strings (as gnu-emacs only allows 24 bits
+ * for the value field of a LISP_OBJECT).
+ */
+
+#define DATA_START 0x10000000
+#define DATA_SEG_BITS 0x10000000
+
+#undef LIBS_MACHINE
+/* -lsun in case using Yellow Pages for passwords. */
+#define LIBS_MACHINE -lsun -lmld
+#define LIBS_DEBUG
+
+/* Define this if you have a fairly recent system,
+ in which crt1.o and crt1.n should be used. */
+#define HAVE_CRTN
+
+#ifdef HAVE_CRTN
+/* Must define START-FILES so that the linker can find /usr/lib/crt0.o. */
+#define START_FILES pre-crt0.o /usr/lib/crt1.o
+#define LIB_STANDARD -lbsd -lc /usr/lib/crtn.o
+#else
+#define START_FILES pre-crt0.o /usr/lib/crt0.o
+/* The entry-point label (start of text segment) is `start', not `__start'. */
+#define DEFAULT_ENTRY_ADDRESS start
+#define LIB_STANDARD -lbsd -lc
+#endif
+
+/* Use terminfo instead of termcap. */
+
+#define TERMINFO
+
+/* Letter to use in finding device name of first pty,
+ if system supports pty's. 'a' means it is /dev/ptya0 */
+
+#undef FIRST_PTY_LETTER
+#define FIRST_PTY_LETTER 'q'
+
+/* Define STACK_DIRECTION for alloca.c */
+
+#define STACK_DIRECTION -1
+
+/* The standard definitions of these macros would work ok,
+ but these are faster because the constants are short. */
+
+#define XUINT(a) (((unsigned)(a) << (INTBITS-VALBITS)) >> INTBITS-VALBITS)
+
+#define XSET(var, type, ptr) \
+ ((var) = ((int)(type) << VALBITS) + (((unsigned) (ptr) << (INTBITS-VALBITS)) >> (INTBITS-VALBITS)))
+
+#define XSETINT(a, b) XSET(a, XTYPE(a), b)
+#define XSETUINT(a, b) XSET(a, XTYPE(a), b)
+#define XSETPNTR(a, b) XSET(a, XTYPE(a), b)
+
+#define XMARKBIT(a) ((a) < 0)
+#define XSETMARKBIT(a,b) ((a) = ((a) & ~MARKBIT) | ((b) ? MARKBIT : 0))
+#define XUNMARK(a) ((a) = (((unsigned)(a) << (INTBITS-GCTYPEBITS-VALBITS)) >> (INTBITS-GCTYPEBITS-VALBITS)))
+
+#if 0 /* This was a mistake. It is needed only on irix 4.0,
+ but s-irix4-0.h already does it. */
+/* Turn off some "helpful" error checks for type mismatches
+ that we can't fix without breaking other machines. */
+#define C_SWITCH_MACHINE -cckr
+#endif
diff --git a/src/m-irist.h b/src/m-irist.h
new file mode 100644
index 00000000000..083d29b5b16
--- /dev/null
+++ b/src/m-irist.h
@@ -0,0 +1,147 @@
+/* m- file for Silicon Graphics Iris 2500 Turbos;
+ also possibly for non-turbo Irises with system release 2.5.
+ Copyright (C) 1985, 1986 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#if 0
+ Message-Id: <8705050653.AA20004@orville.arpa>
+ Subject: gnu emacs 18.41 on iris [23].5 machines
+ Date: 04 May 87 23:53:11 PDT (Mon)
+ From: raible@orville.arpa
+
+ Aside from the SIGIOT, I know of only one bug, a real strange one:
+ I wrote a utimes interface, which copies elements from timevals
+ to utimbufs. This code is known good. The problem is that in
+ emacs, the utime doesn't seem to take effect (i.e. doesn't change the
+ dates at all) unless I call report_file_error *after* the utime returns!
+
+ if (utime (name, &utb) < 0)
+ return;
+ else
+ /* XXX XXX XXX */
+ /* For some reason, if this is taken out, then the utime above breaks! */
+ /* (i.e. it doesn't set the time. This just makes no sense... */
+ /* Eric - May 4, 1987 */
+ report_file_error ("Worked just find\n", Qnil);
+
+ Without any sort of debugger that works on emacs (I know... but I don't have
+ *time* right now to start with gdb), it was quite time consuming to track
+ it down to this.
+
+ But since this code is only used for an optional 4th argument to one command
+ (copy-file), it would say that it is non-critical...
+#endif /* 0 */
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+#define SHORTBITS 16 /* Number of bits in a short */
+
+#define INTBITS 32 /* Number of bits in an int */
+
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* Define BIG_ENDIAN iff lowest-numbered byte in a word
+ is the most significant byte. */
+
+#define BIG_ENDIAN
+
+/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
+ * group of arguments and treat it as an array of the arguments. */
+
+/* #define NO_ARG_ARRAY */
+
+/* Define WORD_MACHINE if addresses and such have
+ * to be corrected before they can be used as byte counts. */
+
+/* #define WORD_MACHINE */
+
+/* Define how to take a char and sign-extend into an int.
+ On machines where char is signed, this is a no-op. */
+
+#define SIGN_EXTEND_CHAR(c) (c)
+
+/* Now define a symbol for the cpu type, if your compiler
+ does not define it automatically:
+ Ones defined so far include vax, m68000, ns16000, pyramid,
+ orion, tahoe, APOLLO and many others */
+
+#ifndef m68000
+#define m68000
+#endif
+
+/* Use type int rather than a union, to represent Lisp_Object */
+/* This is desirable for most machines. */
+
+#define NO_UNION_TYPE
+
+/* Define EXPLICIT_SIGN_EXTEND if XINT must explicitly sign-extend
+ the 24-bit bit field into an int. In other words, if bit fields
+ are always unsigned.
+
+ If you use NO_UNION_TYPE, this flag does not matter. */
+
+#define EXPLICIT_SIGN_EXTEND
+
+/* Data type of load average, as read out of kmem. */
+
+#define LOAD_AVE_TYPE long
+
+/* Convert that into an integer that is 100 for a load average of 1.0 */
+
+#define FSCALE 1.0
+#define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0 / FSCALE)
+
+/* Define CANNOT_DUMP on machines where unexec does not work.
+ Then the function dump-emacs will not be defined
+ and temacs will do (load "loadup") automatically unless told otherwise. */
+
+/* #define CANNOT_DUMP */
+
+/* Define VIRT_ADDR_VARIES if the virtual addresses of
+ pure and impure space as loaded can vary, and even their
+ relative order cannot be relied on.
+
+ Otherwise Emacs assumes that text space precedes data space,
+ numerically. */
+
+/* #define VIRT_ADDR_VARIES */
+
+/* Define C_ALLOCA if this machine does not support a true alloca
+ and the one written in C should be used instead.
+ Define HAVE_ALLOCA to say that the system provides a properly
+ working alloca function and it should be used.
+ Define neither one if an assembler-language alloca
+ in the file alloca.s should be used. */
+
+/* #define C_ALLOCA */
+#define HAVE_ALLOCA
+
+/* Define NO_REMAP if memory segmentation makes it not work well
+ to change the boundary between the text section and data section
+ when Emacs is dumped. If you define this, the preloaded Lisp
+ code will not be sharable; but that's better than failing completely. */
+
+/* #define NO_REMAP */
+
+/* There is an inconsistency between the sgi assembler, linker which barfs
+ on these. */
+
+#define internal_with_output_to_temp_buffer stupid_long_name1
+#define Finsert_abbrev_table_description stupid_long_name2
diff --git a/src/m-is386.h b/src/m-is386.h
new file mode 100644
index 00000000000..12c8af20e21
--- /dev/null
+++ b/src/m-is386.h
@@ -0,0 +1,12 @@
+/* m- file for Integrated Solutions 386 machine. */
+
+#include "m-intel386.h"
+
+#define LIBX10_MACHINE -lnsl_s
+#define LIBX11_MACHINE -lnsl_s
+
+#undef HAVE_PTYS
+#undef SYSV_PTYS
+#undef HAVE_SOCKETS
+
+#define LIBS_DEBUG -lg
diff --git a/src/m-isi-ov.h b/src/m-isi-ov.h
new file mode 100644
index 00000000000..ae41b8b499f
--- /dev/null
+++ b/src/m-isi-ov.h
@@ -0,0 +1,97 @@
+/* m- file for ISI 68000's
+ Copyright (C) 1985, 1986 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#define ISI68K
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+#define SHORTBITS 16 /* Number of bits in a short */
+
+#define INTBITS 32 /* Number of bits in an int */
+
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* 68000 has lowest-numbered byte as most significant */
+
+#define BIG_ENDIAN
+
+/* Define how to take a char and sign-extend into an int.
+ On machines where char is signed, this is a no-op. */
+
+#define SIGN_EXTEND_CHAR(c) (c)
+
+/* Say this machine is a 68000 */
+
+#define m68000
+
+/* Use type int rather than a union, to represent Lisp_Object */
+
+#define NO_UNION_TYPE
+
+/* XINT must explicitly sign-extend */
+
+#define EXPLICIT_SIGN_EXTEND
+
+/* Data type of load average, as read out of kmem. */
+
+#ifdef BSD4_3
+#define LOAD_AVE_TYPE long
+#else
+#define LOAD_AVE_TYPE double
+#endif BSD4_3
+
+/* Convert that into an integer that is 100 for a load average of 1.0 */
+
+#ifdef BSD4_3
+#define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0 / FSCALE)
+#else
+#define LOAD_AVE_CVT(x) ((int) ((x) * 100.0))
+#endif
+
+/* Mask for address bits within a memory segment */
+
+#define SEGMENT_MASK 0x1ffff
+
+/* use the -20 switch to get the 68020 code */
+/* #define C_SWITCH_MACHINE -20 */
+
+/* Use the version of the library for the 68020
+ because the standard library requires some special hacks in crt0
+ which the GNU crt0 does not have. */
+
+#define LIB_STANDARD -lmc
+
+/* macros to make unexec work right */
+
+#define A_TEXT_OFFSET(HDR) sizeof(HDR)
+#define A_TEXT_SEEK(HDR) sizeof(HDR)
+
+/* A few changes for the newer systems. */
+
+#ifdef BSD4_3
+#define HAVE_ALLOCA
+/* The following line affects crt0.c. */
+#undef m68k
+
+#undef LIB_STANDARD
+#define LIB_STANDARD -lmc -lc
+#define C_DEBUG_SWITCH -20 -O -X23
+#endif
diff --git a/src/m-masscomp.h b/src/m-masscomp.h
new file mode 100644
index 00000000000..6c5d33a70cd
--- /dev/null
+++ b/src/m-masscomp.h
@@ -0,0 +1,146 @@
+/* m- file for Masscomp 5000 series running RTU, ucb universe.
+ Copyright (C) 1986 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+#define SHORTBITS 16 /* Number of bits in a short */
+
+#define INTBITS 32 /* Number of bits in an int */
+
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* Define BIG_ENDIAN iff lowest-numbered byte in a word
+ is the most significant byte. */
+
+#define BIG_ENDIAN
+
+/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
+ * group of arguments and treat it as an array of the arguments. */
+
+#undef NO_ARG_ARRAY
+
+/* Define WORD_MACHINE if addresses and such have
+ * to be corrected before they can be used as byte counts. */
+
+#undef WORD_MACHINE
+
+/* Define how to take a char and sign-extend into an int.
+ On machines where char is signed, this is a no-op. */
+
+#define SIGN_EXTEND_CHAR(c) (c)
+
+/* Now define a symbol for the cpu type, if your compiler
+ does not define it automatically:
+ vax, m68000, ns16000, pyramid, orion, tahoe and APOLLO
+ are the ones defined so far. */
+/* Masscomp predefines mc68000. */
+#define m68000 mc68000
+
+/* Use type int rather than a union, to represent Lisp_Object */
+/* This is desirable for most machines. */
+
+#define NO_UNION_TYPE
+
+/* Define EXPLICIT_SIGN_EXTEND if XINT must explicitly sign-extend
+ the 24-bit bit field into an int. In other words, if bit fields
+ are always unsigned.
+
+ If you use NO_UNION_TYPE, this flag does not matter. */
+
+#undef EXPLICIT_SIGN_EXTEND
+
+/* Data type of load average, as read out of kmem. */
+
+#define LOAD_AVE_TYPE double
+
+/* Convert that into an integer that is 100 for a load average of 1.0 */
+
+#define LOAD_AVE_CVT(x) ((int) ((x) * 100.0))
+
+/* Define CANNOT_DUMP on machines where unexec does not work.
+ Then the function dump-emacs will not be defined
+ and temacs will do (load "loadup") automatically unless told otherwise. */
+
+#undef CANNOT_DUMP
+
+/* Define VIRT_ADDR_VARIES if the virtual addresses of
+ pure and impure space as loaded can vary, and even their
+ relative order cannot be relied on.
+
+ Otherwise Emacs assumes that text space precedes data space,
+ numerically. */
+
+#undef VIRT_ADDR_VARIES
+
+/* Define C_ALLOCA if this machine does not support a true alloca
+ and the one written in C should be used instead.
+ Define HAVE_ALLOCA to say that the system provides a properly
+ working alloca function and it should be used.
+ Define neither one if an assembler-language alloca
+ in the file alloca.s should be used. */
+
+/* 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
+ code will not be sharable; but that's better than failing completely. */
+
+#undef NO_REMAP
+
+/* crt0.c should use the vax-bsd style of entry, with a dummy arg. */
+
+#define CRT0_DUMMIES bogus_fp,
+
+/* Name of file the to look in
+ for the kernel symbol table (for load average) */
+
+#define KERNEL_FILE "/unix"
+
+/* This triggers some stuff to avoid a compiler bug */
+
+#define MASSC_REGISTER_BUG
+
+/* Prevent -lg from being used for debugging. Not implemented? */
+
+#define LIBS_DEBUG
+
+/*
+ * Define HAVE_TERMIO if the system provides sysV-style ioctls
+ * for terminal control.
+ */
+
+#define HAVE_TERMIO
+
+/* Adjust a header field for the executable file about to be dumped. */
+
+#define ADJUST_EXEC_HEADER \
+ hdr.a_stamp = STAMP13; /* really want the latest stamp, whatever it is */
diff --git a/src/m-mega68.h b/src/m-mega68.h
new file mode 100644
index 00000000000..60b2d8ab977
--- /dev/null
+++ b/src/m-mega68.h
@@ -0,0 +1,57 @@
+/* m- file for Megatest 68000's.
+ Copyright (C) 1985 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+#define SHORTBITS 16 /* Number of bits in a short */
+
+#define INTBITS 32 /* Number of bits in an int */
+
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* 68000 has lowest-numbered byte as most significant */
+
+#define BIG_ENDIAN
+
+/* XINT must explicitly sign-extend */
+
+#define EXPLICIT_SIGN_EXTEND
+
+/* Define how to take a char and sign-extend into an int.
+ On machines where char is signed, this is a no-op. */
+
+#define SIGN_EXTEND_CHAR(c) (c)
+
+/* Say this machine is a 68000 */
+
+#define m68000
+
+/* Use type int rather than a union, to represent Lisp_Object */
+
+#define NO_UNION_TYPE
+
+/* Data type of load average, as read out of kmem. */
+
+#define LOAD_AVE_TYPE double
+
+/* Convert that into an integer that is 100 for a load average of 1.0 */
+
+#define LOAD_AVE_CVT(x) ((int) ((x) * 100.0))
diff --git a/src/m-mg1.h b/src/m-mg1.h
new file mode 100644
index 00000000000..999147b3db2
--- /dev/null
+++ b/src/m-mg1.h
@@ -0,0 +1,113 @@
+/* m- file for Whitechapel Computer Works MG1 (ns16000 based).
+ Copyright (C) 1985 Free Software Foundation, Inc.
+ MG-1 version by L.M.McLoughlin
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+#define SHORTBITS 16 /* Number of bits in a short */
+
+#define INTBITS 32 /* Number of bits in an int */
+
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* Define BIG_ENDIAN iff lowest-numbered byte in a word
+ is the most significant byte. */
+/* ns16000 is not big-endian: lowest numbered byte is least significant. */
+#undef BIG_ENDIAN
+
+/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
+ * group of arguments and treat it as an array of the arguments. */
+/* ns16000 call sequence used on mg1 means that &arg = the args as an array */
+#undef NO_ARG_ARRAY
+
+/* Define WORD_MACHINE if addresses and such have
+ * to be corrected before they can be used as byte counts. */
+/* ns16000 addresses are byte addresses */
+#undef WORD_MACHINE
+
+/* Define how to take a char and sign-extend into an int.
+ On machines where char is signed, this is a no-op. */
+
+#define SIGN_EXTEND_CHAR(c) (c)
+
+/* Now define a symbol for the cpu type, if your compiler
+ does not define it automatically:
+ vax, m68000, ns16000, pyramid, orion, tahoe and APOLLO
+ are the ones defined so far. */
+/* Say this machine is a 16000 and an mg1, cpp says its a 32000 */
+#define ns16000
+#define mg1
+
+/* Use type int rather than a union, to represent Lisp_Object */
+/* This is desirable for most machines. */
+/* Not sure on mg-1 but this shouldn't hurt! */
+#define NO_UNION_TYPE
+
+/* Define EXPLICIT_SIGN_EXTEND if XINT must explicitly sign-extend
+ the 24-bit bit field into an int. In other words, if bit fields
+ are always unsigned.
+
+ If you use NO_UNION_TYPE, this flag does not matter. */
+
+#define EXPLICIT_SIGN_EXTEND
+
+/* Data type of load average, as read out of kmem. */
+/* mg1 its an unsigned long */
+#define LOAD_AVE_TYPE unsigned long
+
+/* Convert that into an integer that is 100 for a load average of 1.0 */
+#define FSCALE 1000.0
+#define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0 / FSCALE)
+
+/* Define CANNOT_DUMP on machines where unexec does not work.
+ Then the function dump-emacs will not be defined
+ and temacs will do (load "loadup") automatically unless told otherwise. */
+/* ns16000's have an unexec, so should the mg-1 */
+#undef CANNOT_DUMP
+
+/* Define VIRT_ADDR_VARIES if the virtual addresses of
+ pure and impure space as loaded can vary, and even their
+ relative order cannot be relied on.
+
+ Otherwise Emacs assumes that text space precedes data space,
+ numerically. */
+/* hmmmm... not sure. copied m-sequent.h */
+#undef VIRT_ADDR_VARIES
+
+/* Define C_ALLOCA if this machine does not support a true alloca
+ and the one written in C should be used instead.
+ Define HAVE_ALLOCA to say that the system provides a properly
+ working alloca function and it should be used.
+ Define neither one if an assembler-language alloca
+ in the file alloca.s should be used. */
+/* hmmmm... again not sure. so copied m-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
+ code will not be sharable; but that's better than failing completely. */
+/* mapping seems screwy */
+#define NO_REMAP
+
+/* Avoids a compiler bug */
+/* borrowed from m-sequent.h */
diff --git a/src/m-mips.h b/src/m-mips.h
new file mode 100644
index 00000000000..85120e178eb
--- /dev/null
+++ b/src/m-mips.h
@@ -0,0 +1,241 @@
+/* m- file for Mips machines.
+ Copyright (C) 1987 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+#define SHORTBITS 16 /* Number of bits in a short */
+
+#define INTBITS 32 /* Number of bits in an int */
+
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* Define BIG_ENDIAN iff lowest-numbered byte in a word
+ is the most significant byte. */
+
+#define BIG_ENDIAN
+
+/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
+ * group of arguments and treat it as an array of the arguments. */
+
+#define NO_ARG_ARRAY
+
+/* Define WORD_MACHINE if addresses and such have
+ * to be corrected before they can be used as byte counts. */
+
+#undef WORD_MACHINE
+
+/* Define how to take a char and sign-extend into an int.
+ On machines where char is signed, this is a no-op. */
+
+#define SIGN_EXTEND_CHAR(c) ((signed char)(c))
+
+/* Now define a symbol for the cpu type, if your compiler
+ does not define it automatically:
+ Ones defined so far include vax, m68000, ns16000, pyramid,
+ orion, tahoe, APOLLO and many others */
+#ifndef mips
+# define mips
+#endif
+
+/* Use type int rather than a union, to represent Lisp_Object */
+/* This is desirable for most machines. */
+
+#define NO_UNION_TYPE
+
+/* Define EXPLICIT_SIGN_EXTEND if XINT must explicitly sign-extend
+ the 24-bit bit field into an int. In other words, if bit fields
+ are always unsigned.
+
+ If you use NO_UNION_TYPE, this flag does not matter. */
+
+#define EXPLICIT_SIGN_EXTEND
+
+/* Data type of load average, as read out of kmem. */
+
+#define LOAD_AVE_TYPE long
+
+/* Convert that into an integer that is 100 for a load average of 1.0 */
+
+#define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0 / 256.0)
+
+/* Define CANNOT_DUMP on machines where unexec does not work.
+ Then the function dump-emacs will not be defined
+ and temacs will do (load "loadup") automatically unless told otherwise. */
+
+#undef CANNOT_DUMP
+
+/* Define VIRT_ADDR_VARIES if the virtual addresses of
+ pure and impure space as loaded can vary, and even their
+ relative order cannot be relied on.
+
+ Otherwise Emacs assumes that text space precedes data space,
+ numerically. */
+
+/* #define VIRT_ADDR_VARIES */
+
+/* Define C_ALLOCA if this machine does not support a true alloca
+ and the one written in C should be used instead.
+ Define HAVE_ALLOCA to say that the system provides a properly
+ working alloca function and it should be used.
+ Define neither one if an assembler-language alloca
+ in the file alloca.s should be used. */
+
+#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
+ code will not be sharable; but that's better than failing completely. */
+
+#define NO_REMAP
+
+/* This machine requires completely different unexec code
+ which lives in a separate file. Specify the file name. */
+
+#define UNEXEC unexmips.o
+
+/* Describe layout of the address space in an executing process. */
+
+#define TEXT_START 0x400000
+#define DATA_START 0x800000
+
+/* Alter some of the options used when linking. */
+
+#ifdef BSD
+
+/* Supposedly the dec machine doesn't have this library.
+ #define LIBS_MACHINE -lmld */
+
+#define LD_SWITCH_MACHINE -D 800000
+#define LIBS_DEBUG
+
+#define LINKER /bsd43/bin/ld
+
+#else /* not BSD */
+#ifdef NEWSOS5
+
+#define LIBS_MACHINE -lmld
+#define START_FILES pre-crt0.o /usr/ccs/lib/crt1.o
+#define LIB_STANDARD -lsocket -lnsl -lc /usr/ccs/lib/crtn.o /usr/ccs/lib/values-Xt.o
+
+#ifdef __GNUC__
+#define C_DEBUG_SWITCH -g
+#define C_OPTIMIZE_SWITCH -g -O
+#define LD_SWITCH_MACHINE -g -Xlinker -D -Xlinker 800000
+#else
+#define C_DEBUG_SWITCH -g3
+#define C_OPTIMIZE_SWITCH -g3
+#define LD_SWITCH_MACHINE -g3 -D 800000
+#endif
+
+#else /* not NEWSOS5 */
+
+#define LIBS_MACHINE -lmld
+#define LD_SWITCH_MACHINE -D 800000 -g3
+#define START_FILES pre-crt0.o /usr/lib/crt1.o
+#define LIB_STANDARD -lbsd -lc /usr/lib/crtn.o
+#define LIBS_TERMCAP -lcurses
+
+#define C_SWITCH_MACHINE -I/usr/include/bsd
+#define C_DEBUG_SWITCH -O -g3
+
+#if defined(HAVE_X_WINDOWS) && defined(HAVE_X11)
+#define HAVE_VFORK /* Graciously provided by libX.a */
+#endif
+
+#endif /* not NEWSOS5 */
+#endif /* not BSD */
+
+/* The standard definitions of these macros would work ok,
+ but these are faster because the constants are short. */
+
+#define XUINT(a) (((unsigned)(a) << (INTBITS-VALBITS)) >> (INTBITS-VALBITS))
+
+#define XSET(var, type, ptr) \
+ ((var) = \
+ ((int)(type) << VALBITS) \
+ + (((unsigned) (ptr) << (INTBITS-VALBITS)) >> (INTBITS-VALBITS)))
+
+#define XSETINT(a, b) XSET(a, XTYPE(a), b)
+#define XSETUINT(a, b) XSET(a, XTYPE(a), b)
+#define XSETPNTR(a, b) XSET(a, XTYPE(a), b)
+
+#define XUNMARK(a) \
+ ((a) = \
+ (((unsigned)(a) << (INTBITS-GCTYPEBITS-VALBITS)) \
+ >> (INTBITS-GCTYPEBITS-VALBITS)))
+
+#ifndef NEWSOS5
+#ifdef USG
+
+/* Cancel certain parts of standard sysV support. */
+#undef NONSYSTEM_DIR_LIBRARY
+#define SYSV_SYSTEM_DIR
+#undef static
+
+/* Don't try to use SIGIO or FIONREAD even though they are defined. */
+#undef SIGIO
+#define BROKEN_FIONREAD
+
+/* Describe special kernel features. */
+
+#define HAVE_SYSVIPC
+
+#define HAVE_TIMEVAL
+#if defined(emacs) && !defined(INHIBIT_BSD_TIME)
+#include <bsd/sys/time.h>
+#endif
+
+/* #define HAVE_SELECT
+ The `select' in the system won't work for pipes,
+ so don't use it. */
+
+#define HAVE_DUP2
+#define HAVE_GETWD
+#define HAVE_GETTIMEOFDAY
+
+#define HAVE_PTYS
+#define HAVE_SOCKETS
+
+#undef NOMULTIPLEJOBS
+#define utimes utime /* Someone should check this. */
+
+/* ??? */
+#define IRIS
+
+#endif /* USG */
+
+#ifdef BSD
+#define COFF
+#define TERMINFO
+#undef MAIL_USE_FLOCK /* Someone should check this. */
+#undef HAVE_UNION_WAIT
+#endif /* BSD */
+
+#endif /* not NEWSOS5 */
+
+/* Load average requires special crocks. Version 19 has them.
+ For now, this avoids a bug. */
+#undef LOAD_AVE_TYPE
diff --git a/src/m-mips4.h b/src/m-mips4.h
new file mode 100644
index 00000000000..2abaa3b73ee
--- /dev/null
+++ b/src/m-mips4.h
@@ -0,0 +1,34 @@
+/* m- file for Mips running RISCOS version 4. */
+
+#include "m-mips.h"
+
+/* Define MIPS2 if you have an R6000 or R4000. */
+/* #define MIPS2 */
+
+#ifdef __GNUC__
+#define C_DEBUG_SWITCH -g -O
+#else
+#ifdef MIPS2
+#define C_DEBUG_SWITCH -systype bsd43 -O -Olimit 791 -g3 -mips2
+#else
+#define C_DEBUG_SWITCH -systype bsd43 -O -Olimit 791 -g3
+#endif
+#endif
+
+#ifdef TERMINFO
+#undef TERMINFO
+#endif
+
+#define START_FILES pre-crt0.o /lib/crt1.o
+#define LIB_STANDARD -lmld -lc /lib/crtn.o
+
+
+#define COFF
+#undef LD_SWITCH_MACHINE
+
+#ifdef __GNUC__
+#undef LINKER
+#define LD_SWITCH_MACHINE -g -Xlinker -D -Xlinker 800000
+#else
+#define LD_SWITCH_MACHINE -systype bsd43 -g3 -D 800000
+#endif
diff --git a/src/m-news-risc.h b/src/m-news-risc.h
new file mode 100644
index 00000000000..8247e127dfd
--- /dev/null
+++ b/src/m-news-risc.h
@@ -0,0 +1,74 @@
+/* m-news-risc.h is for the "RISC News". */
+
+/* Override s-usg5-4.h. */
+#ifdef USG
+#undef UNEXEC
+#undef LIBX11_SYSTEM
+#undef LOAD_AVE_CVT
+#define INHIBIT_BSD_TIME
+#undef START_FILES
+#undef LIB_STANDARD
+#endif
+
+#define COFF
+
+#include "m-mips.h"
+
+#undef LIBS_MACHINE
+#define LIBS_MACHINE -lmld
+
+#define C_OPTIMIZE_SWITCH -O
+
+#undef LD_SWITCH_MACHINE
+
+#ifndef USG
+#undef TERMINFO
+
+#undef LINKER /* Override m-mips.h. */
+
+#define LD_SWITCH_MACHINE -x -D 800000
+
+#undef C_DEBUG_SWITCH
+#define C_DEBUG_SWITCH -g3
+#endif
+
+#ifdef USG
+#undef LIB_STANDARD
+#define LIB_STANDARD GNULIB -lsocket -lnsl -lc /usr/ccs/lib/crtn.o
+
+#undef LIBS_TERMCAP
+#define LIBS_TERMCAP -ltermlib
+
+#undef C_SWITCH_SYSTEM
+
+#undef C_DEBUG_SWITCH
+#define C_DEBUG_SWITCH -g
+
+#undef LD_SWITCH_MACHINE
+#define LD_SWITCH_MACHINE -D 10000000 -g3
+
+#undef USG_SHARED_LIBRARIES
+
+#undef START_FILES
+#define START_FILES pre-crt0.o /usr/ccs/lib/crt1.o /usr/ccs/lib/values-Xt.o
+
+#undef TEXT_START
+#define TEXT_START 0x400000
+#undef DATA_START
+#define DATA_START 0x10000000
+
+#undef DATA_SEG_BITS
+#define DATA_SEG_BITS 0x10000000
+
+#undef C_ALLOCA
+#define HAVE_ALLOCA
+#if defined(__GNUC__) && !defined(alloca)
+#define alloca(n) __builtin_alloca(n)
+#endif
+
+/* replace bsd getwd() with SysV getcwd() */
+#undef HAVE_GETWD
+#undef HAVE_GETTIMEOFDAY
+
+#define LOAD_AVE_TYPE long
+#endif
diff --git a/src/m-news.h b/src/m-news.h
new file mode 100644
index 00000000000..735eb80c3da
--- /dev/null
+++ b/src/m-news.h
@@ -0,0 +1,68 @@
+/* m- file for Sony's NEWS workstations, NEWS-OS 3.0.
+ Copyright (C) 1985, 1986, 1989 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* Say this machine is a 68000 */
+
+#ifndef m68000
+#define m68000
+#endif
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+#define SHORTBITS 16 /* Number of bits in a short */
+
+#define INTBITS 32 /* Number of bits in an int */
+
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* 68000 has lowest-numbered byte as most significant */
+
+#define BIG_ENDIAN
+
+/* One CRT0 Dummy variable */
+
+#define CRT0_DUMMIES one_dummy,
+
+/* Define how to take a char and sign-extend into an int.
+ On machines where char is signed, this is a no-op. */
+
+#define SIGN_EXTEND_CHAR(c) (c)
+
+/* Use type int rather than a union, to represent Lisp_Object */
+
+#define NO_UNION_TYPE
+
+/* The News machine has alloca. */
+
+#define HAVE_ALLOCA
+
+/* Data type of load average, as read out of kmem. */
+
+#define LOAD_AVE_TYPE double
+
+/* Convert that into an integer that is 100 for a load average of 1.0 */
+
+#define LOAD_AVE_CVT(x) ((int) ((x) * 100.0))
+
+/* Must use the system's termcap. It does special things. */
+
+#define LIBS_TERMCAP -ltermcap
+
diff --git a/src/m-next.h b/src/m-next.h
new file mode 100644
index 00000000000..779622f7c4a
--- /dev/null
+++ b/src/m-next.h
@@ -0,0 +1,125 @@
+/* Configuration file for NeXT machine.
+ Copyright (C) 1990 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Say this machine is a next if not previously defined */
+
+#ifndef NeXT
+#define NeXT
+#endif
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+#define SHORTBITS 16 /* Number of bits in a short */
+
+#define INTBITS 32 /* Number of bits in an int */
+
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* Let the compiler tell us what byte order architecture we're compiling for */
+
+#ifdef __BIG_ENDIAN__
+#define BIG_ENDIAN
+#endif
+
+/* Define how to take a char and sign-extend into an int.
+ On machines where char is signed, this is a no-op. */
+
+#define SIGN_EXTEND_CHAR(c) (c)
+
+/* Use type int rather than a union, to represent Lisp_Object */
+
+#define NO_UNION_TYPE
+
+/* XINT must explicitly sign-extend */
+
+#define EXPLICIT_SIGN_EXTEND
+
+/* Data type of load average, as read out of kmem. */
+
+#define LOAD_AVE_TYPE long
+
+/* Convert that into an integer that is 100 for a load average of 1.0 */
+
+#define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0 / FSCALE)
+
+/* Say that the text segment of a.out includes the header;
+ the header actually occupies the first few bytes of the text segment
+ and is counted in hdr.a_text. */
+
+#define A_TEXT_OFFSET(HDR) sizeof (HDR)
+
+/* Use dk.h, not dkstat.h, in loadst.c. */
+
+#define DK_HEADER_FILE
+
+/* Mask for address bits within a memory segment */
+
+#define SEGSIZ 0x20000
+#define SEGMENT_MASK (SEGSIZ - 1)
+
+#define HAVE_ALLOCA
+
+#define SYSTEM_MALLOC
+
+#define HAVE_UNIX_DOMAIN
+
+#define LIB_X11_LIB -L/usr/lib/X11 -lX11
+
+/* Conflicts in process.c between ioctl.h & tty.h use of t_foo fields */
+
+#define NO_T_CHARS_DEFINES
+
+/* Use our own unexec routines */
+
+#define UNEXEC unexnext.o
+
+/* We don't use _start, etext, or edata */
+
+#define TEXT_START NULL /* wrong: but nobody uses it anyway */
+#define TEXT_END get_etext()
+#define DATA_END get_edata()
+
+/* We don't have a g library either, so override the -lg LIBS_DEBUG switch */
+
+#define LIBS_DEBUG
+
+/* We don't have a libgcc.a, so we can't let LIB_GCC default to -lgcc */
+
+#define LIB_GCC
+
+/* Compile "strict bsd" to avoid warnings from include files */
+
+#define C_SWITCH_MACHINE -bsd
+
+/* Link this program just by running cc. */
+#define ORDINARY_LINK
+
+/* This was needed before we used ORDINARY_LINK. */
+#if 0
+/* Use our own crt0 routine */
+#define NO_REMAP
+
+/* Standard library is libsys_s, not libc */
+
+#define LIB_STANDARD -lsys_s
+#endif
+
+/* Where to find the kernel, for load average. */
+#define KERNEL_FILE "/mach"
diff --git a/src/m-ns16000.h b/src/m-ns16000.h
new file mode 100644
index 00000000000..8bc086b599d
--- /dev/null
+++ b/src/m-ns16000.h
@@ -0,0 +1,53 @@
+/* m- file for ns16000.
+ Copyright (C) 1985 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+#define SHORTBITS 16 /* Number of bits in a short */
+
+#define INTBITS 32 /* Number of bits in an int */
+
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* 16000 is little-endian (lowest-numbered byte is least significant) */
+
+/* #define BIG_ENDIAN */ /* So don't define this. */
+
+/* Define how to take a char and sign-extend into an int.
+ On machines where char is signed, this is a no-op. */
+
+#define SIGN_EXTEND_CHAR(c) (c)
+
+/* Say this machine is a 16000 */
+
+#define ns16000 1
+
+/* Use type int rather than a union, to represent Lisp_Object */
+
+#define NO_UNION_TYPE
+
+/* Data type of load average, as read out of kmem. */
+
+#define LOAD_AVE_TYPE double
+
+/* Convert that into an integer that is 100 for a load average of 1.0 */
+
+#define LOAD_AVE_CVT(x) ((int) ((x) * 100.0))
diff --git a/src/m-ns32000.h b/src/m-ns32000.h
new file mode 100644
index 00000000000..5dd91a868f4
--- /dev/null
+++ b/src/m-ns32000.h
@@ -0,0 +1,116 @@
+/* m- file for Netional Semiconductor 32000, running Genix.
+ Copyright (C) 1985, 1986 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+#define SHORTBITS 16 /* Number of bits in a short */
+
+#define INTBITS 32 /* Number of bits in an int */
+
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* Define BIG_ENDIAN iff lowest-numbered byte in a word
+ is the most significant byte. */
+
+/* #define BIG_ENDIAN */
+
+/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
+ * group of arguments and treat it as an array of the arguments. */
+
+/* #define NO_ARG_ARRAY */
+
+/* Define WORD_MACHINE if addresses and such have
+ * to be corrected before they can be used as byte counts. */
+
+/* #define WORD_MACHINE */
+
+/* Define how to take a char and sign-extend into an int.
+ On machines where char is signed, this is a no-op. */
+
+#define SIGN_EXTEND_CHAR(c) (c)
+
+/* Now define a symbol for the cpu type, if your compiler
+ does not define it automatically:
+ Ones defined so far include vax, m68000, ns16000, pyramid,
+ orion, tahoe, APOLLO and many others */
+
+/* Use type int rather than a union, to represent Lisp_Object */
+/* This is desirable for most machines. */
+
+#define NO_UNION_TYPE
+
+/* Define EXPLICIT_SIGN_EXTEND if XINT must explicitly sign-extend
+ the 24-bit bit field into an int. In other words, if bit fields
+ are always unsigned.
+
+ If you use NO_UNION_TYPE, this flag does not matter. */
+
+#define EXPLICIT_SIGN_EXTEND
+
+/* Data type of load average, as read out of kmem. */
+
+/* #define LOAD_AVE_TYPE long */
+
+/* Convert that into an integer that is 100 for a load average of 1.0 */
+
+/* #define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0 / FSCALE) */
+
+/* Define CANNOT_DUMP on machines where unexec does not work.
+ Then the function dump-emacs will not be defined
+ and temacs will do (load "loadup") automatically unless told otherwise. */
+
+/* #define CANNOT_DUMP */
+
+/* Define VIRT_ADDR_VARIES if the virtual addresses of
+ pure and impure space as loaded can vary, and even their
+ relative order cannot be relied on.
+
+ Otherwise Emacs assumes that text space precedes data space,
+ numerically. */
+
+/* #define VIRT_ADDR_VARIES */
+
+/* Define C_ALLOCA if this machine does not support a true alloca
+ and the one written in C should be used instead.
+ Define HAVE_ALLOCA to say that the system provides a properly
+ working alloca function and it should be used.
+ Define neither one if an assembler-language alloca
+ in the file alloca.s should be used. */
+
+/* #define C_ALLOCA */
+/* #define HAVE_ALLOCA */
+
+/* Define NO_REMAP if memory segmentation makes it not work well
+ to change the boundary between the text section and data section
+ when Emacs is dumped. If you define this, the preloaded Lisp
+ code will not be sharable; but that's better than failing completely. */
+
+/* #define NO_REMAP */
+
+#define TEXT_START 0
+
+#define STACK_DIRECTION -1
+
+#define EXEC_MAGIC 0410
+
+#define PURESIZE 140000
+
+#define START_FILES pre-crt0.o /lib/crt0.o
diff --git a/src/m-nu.h b/src/m-nu.h
new file mode 100644
index 00000000000..9e8cdd216bd
--- /dev/null
+++ b/src/m-nu.h
@@ -0,0 +1,80 @@
+/* m- file for TI Nu machines using system V.
+ Copyright (C) 1986 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+#define SHORTBITS 16 /* Number of bits in a short */
+
+#define INTBITS 32 /* Number of bits in an int */
+
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* Define BIG_ENDIAN iff lowest-numbered byte in a word
+ is the most significant byte. */
+
+#define BIG_ENDIAN
+
+/* XINT must explicitly sign-extend */
+
+#define EXPLICIT_SIGN_EXTEND
+
+/* Define how to take a char and sign-extend into an int.
+ On machines where char is signed, this is a no-op. */
+
+#define SIGN_EXTEND_CHAR(c) (c)
+
+/* Use type int rather than a union, to represent Lisp_Object */
+
+#define NO_UNION_TYPE
+
+/* Now define a symbol for the cpu type, if your compiler
+ does not define it automatically:
+ vax, m68000, ns16000 are the ones defined so far. */
+
+#ifndef m68000
+#define m68000
+#endif
+
+#ifndef NU
+#define NU
+#endif
+
+/* Data type of load average, as read out of kmem. */
+/* These are commented out since it does not really work in uniplus */
+
+/* #define LOAD_AVE_TYPE long */
+
+/* Convert that into an integer that is 100 for a load average of 1.0 */
+
+/* #define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0) */
+
+/* Change some things to avoid bugs in compiler */
+
+#define SWITCH_ENUM_BUG 1
+
+/* The NU machine has a compiler that can handle long names. */
+
+#undef SHORTNAMES
+
+/* Specify alignment requirement for start of text and data sections
+ in the executable file. */
+
+#define SECTION_ALIGNMENT pagemask
diff --git a/src/m-orion.h b/src/m-orion.h
new file mode 100644
index 00000000000..d558c0abfda
--- /dev/null
+++ b/src/m-orion.h
@@ -0,0 +1,80 @@
+/* m- file for HLH Orion.
+ Copyright (C) 1985 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+#define SHORTBITS 16 /* Number of bits in a short */
+
+#define INTBITS 32 /* Number of bits in an int */
+
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* Define BIG_ENDIAN iff lowest-numbered byte in a word
+ is the most significant byte. */
+
+#undef BIG_ENDIAN
+
+/* Now define a symbol for the cpu type, if your compiler
+ does not define it automatically. */
+
+#ifndef orion
+#define orion
+#endif
+
+/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
+ * group of arguments and treat it as an array of the arguments. */
+
+#define NO_ARG_ARRAY
+
+/* Define WORD_MACHINE if addresses and such have
+ * to be corrected before they can be used as byte counts. */
+
+#define WORD_MACHINE
+
+/* Define how to take a char and sign-extend into an int.
+ On machines where char is signed, this is a no-op. */
+
+#define SIGN_EXTEND_CHAR(c) ((((int) (c)) << 24) >> 24)
+
+/* Use type int rather than a union, to represent Lisp_Object */
+/* This is desirable for most machines. */
+
+#define NO_UNION_TYPE
+
+/* Define EXPLICIT_SIGN_EXTEND if XINT must explicitly sign-extend */
+
+#define EXPLICIT_SIGN_EXTEND
+
+/* Data type of load average, as read out of kmem. */
+
+#define LOAD_AVE_TYPE double
+
+/* Convert that into an integer that is 100 for a load average of 1.0 */
+
+#ifndef FSCALE
+#define FSCALE 1.0
+#endif
+#define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0 / FSCALE)
+
+/* It is necessary to use the portable imitation of alloca,
+ since a true stack-allocating one is impossible. */
+
+#define C_ALLOCA
diff --git a/src/m-orion105.h b/src/m-orion105.h
new file mode 100644
index 00000000000..ed6ed2ff982
--- /dev/null
+++ b/src/m-orion105.h
@@ -0,0 +1,76 @@
+/* m- file for HLH Orion 1/05 (Clipper).
+ Copyright (C) 1985 Free Software Foundation, Inc.
+ Lee McLoughlin <lmjm%doc.imperial.ac.uk@nss.cs.ucl.ac.uk>
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+#define SHORTBITS 16 /* Number of bits in a short */
+
+#define INTBITS 32 /* Number of bits in an int */
+
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* Define BIG_ENDIAN iff lowest-numbered byte in a word
+ is the most significant byte. */
+
+#undef BIG_ENDIAN
+
+/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
+ * group of arguments and treat it as an array of the arguments. */
+
+#define NO_ARG_ARRAY
+
+/* Define WORD_MACHINE if addresses and such have
+ * to be corrected before they can be used as byte counts. */
+
+#define SIGN_EXTEND_CHAR(c) ((int)(c))
+
+/* Use type int rather than a union, to represent Lisp_Object */
+/* This is desirable for most machines. */
+
+#define NO_UNION_TYPE
+
+/* Data type of load average, as read out of kmem. */
+/* This used to be `double'. */
+
+#define LOAD_AVE_TYPE long
+
+/* Convert that into an integer that is 100 for a load average of 1.0 */
+
+/* This used to be 1.0. */
+#ifndef FSCALE
+#define FSCALE 256
+#endif
+#define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0 / FSCALE)
+
+/* HLH have a SIGWINCH defined (but unimplemented) so we need a sigmask */
+#ifndef sigmask
+#define sigmask(m) (1 << ((m) - 1))
+#endif
+
+#define HAVE_ALLOCA
+
+/* Here is where programs actually start running */
+#define TEXT_START 0x8000
+#define LD_TEXT_START_ADDR 8000
+
+/* Arguments to ignore before argc in crt0.c. */
+#define DUMMIES dummy1, dummy2,
diff --git a/src/m-pfa50.h b/src/m-pfa50.h
new file mode 100644
index 00000000000..f0f03cd0c69
--- /dev/null
+++ b/src/m-pfa50.h
@@ -0,0 +1,117 @@
+/* m- file for PFU A-series.
+ Copyright (C) 1988 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY. No author or distributor
+accepts responsibility to anyone for the consequences of using it
+or for whether it serves any particular purpose or works at all,
+unless he says so in writing. Refer to the GNU Emacs General Public
+License for full details.
+
+Everyone is granted permission to copy, modify and redistribute
+GNU Emacs, but only under the conditions described in the
+GNU Emacs General Public License. A copy of this license is
+supposed to have been given to you along with GNU Emacs so you
+can know your rights and responsibilities. It should be in a
+file named COPYING. Among other things, the copyright notice
+and this notice must be preserved on all copies. */
+
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+#define SHORTBITS 16 /* Number of bits in a short */
+
+#define INTBITS 32 /* Number of bits in an int */
+
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* 68000 has lowest-numbered byte as most significant */
+
+#define BIG_ENDIAN
+
+/* Define how to take a char and sign-extend into an int.
+ On machines where char is signed, this is a no-op. */
+
+#define SIGN_EXTEND_CHAR(c) ((((int) (c)) << 24) >> 24)
+
+/* Say this machine is a 68000 */
+
+#define m68000
+#define mc68000 1
+
+/* Use type int rather than a union, to represent Lisp_Object */
+
+#define NO_UNION_TYPE
+
+/* XINT must explicitly sign-extend */
+
+#define EXPLICIT_SIGN_EXTEND
+
+/* The symbol FIONREAD is defined, but the feature does not work. */
+
+#define BROKEN_FIONREAD
+
+/* 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 TEXT_START_ADDR if your linker don't set execute point to _start.
+ If it needed, temacs always CORE-DUMP. */
+
+#define TEXT_START_ADDR __start
+
+/* Define START_FILES if your machine used _start.
+ */
+
+#define START_FILES crt0.o
+
+/* Define LD_SWITCH_MACHINE if your linker need it.
+ */
+
+#define LD_SWITCH_MACHINE -e __start
+
+#if pfa50 || pfa70
+
+/* On A-50/60/70/80, data space has high order byte use. */
+#define VALMASK (((1<<VALBITS) - 1) | 0x60000000)
+#define XTYPE(a) ((enum Lisp_Type) (((a) >> VALBITS) & 0x1f))
+#define XGCTYPE(a) ((enum Lisp_Type) (((a) >> VALBITS) & 0x1f))
+
+#endif /* pfa50, pfa70 */
+
+/* SX/A has alloca in the PW library. */
+
+#define LIB_STANDARD -lPW -lc
+#define HAVE_ALLOCA
+
+/* SX/A uses terminfo and lib/curses */
+
+#define TERMINFO
+
+#define HAVE_TIMEVAL
+#define HAVE_SELECT
+#define HAVE_PTYS
+#define HAVE_SOCKETS
+#define HAVE_RENAME
+
+/* SX/A use SystemV style getdents/readdir. */
+#define HAVE_CLOSEDIR
+
+/* SX/A does not have sigpause. */
+#undef HAVE_SYSV_SIGPAUSE
+
+/* SX/A does not have sigblock. */
+#define sigblock(mask) (0)
+
+#define USG_SYS_TIME
+#define USE_UTIME
+
+#define NO_SIOCTL_H
+
+#undef SIGIO
diff --git a/src/m-plexus.h b/src/m-plexus.h
new file mode 100644
index 00000000000..da939b0d7e2
--- /dev/null
+++ b/src/m-plexus.h
@@ -0,0 +1,124 @@
+/* m- file for the Plexus running System V.2.
+ Copyright (C) 1986 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+#define SHORTBITS 16 /* Number of bits in a short */
+
+#define INTBITS 32 /* Number of bits in an int */
+
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* Define BIG_ENDIAN iff lowest-numbered byte in a word
+ is the most significant byte. */
+
+#define BIG_ENDIAN
+
+/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
+ * group of arguments and treat it as an array of the arguments. */
+
+#undef NO_ARG_ARRAY
+
+/* Define WORD_MACHINE if addresses and such have
+ * to be corrected before they can be used as byte counts. */
+
+#undef WORD_MACHINE
+
+/* Define how to take a char and sign-extend into an int.
+ On machines where char is signed, this is a no-op. */
+
+#define SIGN_EXTEND_CHAR(c) (c)
+
+/* Now define a symbol for the cpu type, if your compiler
+ does not define it automatically:
+ vax, m68000, ns16000, pyramid, orion, tahoe and APOLLO
+ are the ones defined so far. */
+/* Plexus predefines m68 instead of m68000. */
+#define m68000 m68
+
+/* Use type int rather than a union, to represent Lisp_Object */
+/* This is desirable for most machines. */
+
+#define NO_UNION_TYPE
+
+/* Define EXPLICIT_SIGN_EXTEND if XINT must explicitly sign-extend
+ the 24-bit bit field into an int. In other words, if bit fields
+ are always unsigned.
+
+ If you use NO_UNION_TYPE, this flag does not matter. */
+
+#undef EXPLICIT_SIGN_EXTEND
+
+/* Data type of load average, as read out of kmem. */
+
+#undef LOAD_AVE_TYPE
+
+/* Convert that into an integer that is 100 for a load average of 1.0 */
+
+#undef LOAD_AVE_CVT
+
+/* Define CANNOT_DUMP on machines where unexec does not work.
+ Then the function dump-emacs will not be defined
+ and temacs will do (load "loadup") automatically unless told otherwise. */
+
+#undef CANNOT_DUMP
+
+/* Define VIRT_ADDR_VARIES if the virtual addresses of
+ pure and impure space as loaded can vary, and even their
+ relative order cannot be relied on.
+
+ Otherwise Emacs assumes that text space precedes data space,
+ numerically. */
+
+#undef VIRT_ADDR_VARIES
+
+/* Define C_ALLOCA if this machine does not support a true alloca
+ and the one written in C should be used instead.
+ Define HAVE_ALLOCA to say that the system provides a properly
+ working alloca function and it should be used.
+ Define neither one if an assembler-language alloca
+ in the file alloca.s should be used. */
+
+#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
+ code will not be sharable; but that's better than failing completely. */
+
+#undef NO_REMAP
+
+/* Use the following on ld so we can use the gnu crt0
+ The plexus ld looks for start */
+#define LD_SWITCH_MACHINE -e __start
+
+/* Use the PW library, which contains alloca. */
+
+#define LIB_STANDARD -lPW -lc
+
+/* crt0.c should use the vax-bsd style of entry, with no dummy args. */
+
+#define CRT0_DUMMIES zero1, zero2,
+
+/* This triggers some stuff to avoid a compiler bug */
+
+#define TAHOE_REGISTER_BUG
diff --git a/src/m-pmax.h b/src/m-pmax.h
new file mode 100644
index 00000000000..542b26b3044
--- /dev/null
+++ b/src/m-pmax.h
@@ -0,0 +1,36 @@
+#include "m-mips.h"
+#undef LIBS_MACHINE
+#undef BIG_ENDIAN
+#undef LIB_STANDARD
+#undef START_FILES
+#undef COFF
+#undef TERMINFO
+#define MAIL_USE_FLOCK
+#define HAVE_UNION_WAIT
+
+/* This line starts being needed with ultrix 4.0. */
+/* You must delete it for version 3.1. */
+#define START_FILES pre-crt0.o /usr/lib/cmplrs/cc/crt0.o
+
+/* Supposedly the following will overcome a kernel bug. */
+#undef LD_SWITCH_MACHINE
+#undef DATA_START
+#define DATA_START 0x10000000
+#define DATA_SEG_BITS 0x10000000
+
+/* In Ultrix 4.1, XvmsAlloc.o in libX11.a seems to insist
+ on defining malloc itself. This should avoid conflicting with it. */
+#define SYSTEM_MALLOC
+
+/* Override what m-mips.h says about this. */
+#undef LINKER
+
+/* Ultrix 4.2 (perhaps also 4.1) implements O_NONBLOCK
+ but it doesn't work right;
+ and it causes hanging in read_process_output. */
+#define BROKEN_O_NONBLOCK
+
+#ifdef OSF1
+#undef C_ALLOCA
+#define HAVE_ALLOCA
+#endif
diff --git a/src/m-pyramid.h b/src/m-pyramid.h
new file mode 100644
index 00000000000..1deb31b67de
--- /dev/null
+++ b/src/m-pyramid.h
@@ -0,0 +1,72 @@
+/* m- file for pyramid.
+ Copyright (C) 1985, 1986 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+#define SHORTBITS 16 /* Number of bits in a short */
+
+#define INTBITS 32 /* Number of bits in an int */
+
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* Define BIG_ENDIAN iff lowest-numbered byte in a word
+ is the most significant byte. */
+
+#define BIG_ENDIAN
+
+/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
+ * group of arguments and treat it as an array of the arguments. */
+
+#ifdef __GNUC__
+#define NO_ARG_ARRAY
+#endif
+
+/* XINT must explicitly sign extend */
+
+#define EXPLICIT_SIGN_EXTEND
+
+/* Define how to take a char and sign-extend into an int.
+ On machines where char is signed, this is a no-op. */
+
+#define SIGN_EXTEND_CHAR(c) (c)
+
+/* pyramid preprocessor defines "pyr", however the following is clearer */
+#define pyramid
+
+/* Don't use the union types any more. They were used until Emacs 17.45. */
+
+#define NO_UNION_TYPE
+
+/* Data type of load average, as read out of kmem. */
+
+#define LOAD_AVE_TYPE double
+
+/* Convert that into an integer that is 100 for a load average of 1.0 */
+
+#define LOAD_AVE_CVT(x) ((int) ((x) * 100.0))
+
+/* Don't use the ordinary -g for debugging in cc */
+
+#define C_DEBUG_SWITCH -gx
+
+/* Reenable this #define for old versions of the Pyramid system. */
+
+/* #define PYRAMID_OLD */
diff --git a/src/m-pyrmips.h b/src/m-pyrmips.h
new file mode 100644
index 00000000000..facfa09752e
--- /dev/null
+++ b/src/m-pyrmips.h
@@ -0,0 +1,123 @@
+/* m- file for pyramid with mips processor
+ Copyright (C) 1985, 1986 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+#define SHORTBITS 16 /* Number of bits in a short */
+
+#define INTBITS 32 /* Number of bits in an int */
+
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* Define BIG_ENDIAN iff lowest-numbered byte in a word
+ is the most significant byte. */
+
+#define BIG_ENDIAN
+
+/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
+ * group of arguments and treat it as an array of the arguments. */
+
+
+#define NO_ARG_ARRAY
+
+#undef WORD_MACHINE
+
+
+/* XINT must explicitly sign extend */
+
+#define EXPLICIT_SIGN_EXTEND
+
+/* Define how to take a char and sign-extend into an int.
+ On machines where char is signed, this is a no-op. */
+
+
+#define SIGN_EXTEND_CHAR(c) ((signed char)(c))
+
+
+/* pyramid preprocessor defines "pyr", however the following is clearer */
+#define pyramid
+
+/* Don't use the union types any more. They were used until Emacs 17.45. */
+
+#define NO_UNION_TYPE
+
+/* Data type of load average, as read out of kmem. */
+
+#define LOAD_AVE_TYPE double /* might be long TODO */
+
+/* Convert that into an integer that is 100 for a load average of 1.0 */
+
+#define LOAD_AVE_CVT(x) ((int) ((x) * 100.0))
+
+/* Don't use the ordinary -g for debugging in cc */
+/* Define CANNOT_DUMP on machines where unexec does not work.
+ Then the function dump-emacs will not be defined
+ and temacs will do (load "loadup") automatically unless told otherwise. */
+
+#define CANNOT_DUMP
+
+/* Define 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. */
+
+/* these are needed! */
+#define HAVE_ALLOCA
+#define SYSTEM_MALLOC
+
+/*
+ * most of the rest is from m-mips.h
+ * but there was too much in that that we didn't want
+ */
+/* #define NO_REMAP /* don't adjust data_start */
+
+
+/* The standard definitions of these macros would work ok,
+ but these are faster because the constants are short. */
+
+#define XUINT(a) (((unsigned)(a) << INTBITS-VALBITS) >> INTBITS-VALBITS)
+
+#define XSET(var, type, ptr) \
+ ((var) = ((int)(type) << VALBITS) + (((unsigned) (ptr) << INTBITS-VALBITS) >> INTBITS-VALBITS))
+
+#define XSETINT(a, b) XSET(a, XTYPE(a), b)
+#define XSETUINT(a, b) XSET(a, XTYPE(a), b)
+#define XSETPNTR(a, b) XSET(a, XTYPE(a), b)
+
+#define XUNMARK(a) ((a) = (((unsigned)(a) << INTBITS-GCTYPEBITS-VALBITS) >> INTBITS-GCTYPEBITS-VALBITS))
+
+/* Cancel certain parts of standard sysV support. */
+#undef NONSYSTEM_DIR_LIBRARY
+#define SYSV_SYSTEM_DIR
+#undef static
+
+/* Don't try to use SIGIO or FIONREAD even though they are defined. */
+#undef SIGIO
+#define BROKEN_FIONREAD
+
+/* Describe special kernel features. */
+
+#define HAVE_SYSVIPC
+
+#define C_DEBUG_SWITCH -gx
+
diff --git a/src/m-seq386.h b/src/m-seq386.h
new file mode 100644
index 00000000000..2b1b089569b
--- /dev/null
+++ b/src/m-seq386.h
@@ -0,0 +1,11 @@
+#include "m-sequent.h"
+
+#if 0 /* This is probably not necessary in GCC 2.2 and up. */
+/* When compiling with GCC and not optimizing,
+ start has to skip one extra dummy word on the stack. */
+
+#if defined (__GNUC__) && !defined (__OPTIMIZE__)
+#undef CRT0_DUMMIES
+#define CRT0_DUMMIES dummy1, dummy2,
+#endif
+#endif /* 0 */
diff --git a/src/m-sequent.h b/src/m-sequent.h
new file mode 100644
index 00000000000..5337088ac92
--- /dev/null
+++ b/src/m-sequent.h
@@ -0,0 +1,176 @@
+/* m- file for SEQUENT BALANCE machines
+ Copyright (C) 1985, 1986 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* NOTE: this file works for DYNIX release 2.0
+ (not tested on 1.3) on NS32000's */
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+#define SHORTBITS 16 /* Number of bits in a short */
+
+#define INTBITS 32 /* Number of bits in an int */
+
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* Define BIG_ENDIAN iff lowest-numbered byte in a word
+ is the most significant byte. */
+
+/* #define BIG_ENDIAN */
+
+/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
+ * group of arguments and treat it as an array of the arguments. */
+
+/* #define NO_ARG_ARRAY */
+
+/* Define WORD_MACHINE if addresses and such have
+ * to be corrected before they can be used as byte counts. */
+
+/* #define WORD_MACHINE */
+
+/* Define how to take a char and sign-extend into an int.
+ On machines where char is signed, this is a no-op. */
+
+#define SIGN_EXTEND_CHAR(c) (c)
+
+/* Now define a symbol for the cpu type, if your compiler
+ does not define it automatically:
+ vax, m68000, ns16000, pyramid, orion, tahoe and APOLLO
+ are the ones defined so far. */
+
+/* BTW: DYNIX defines sequent, ns32000, and ns16000 (GENIX compatibility) */
+#ifndef sequent /* pre DYNIX 2.1 releases */
+# define sequent
+#endif
+
+/* Use type int rather than a union, to represent Lisp_Object */
+/* This is desirable for most machines. */
+
+#define NO_UNION_TYPE
+
+/* crt0.c should use the vax-bsd style of entry, with these dummy args. */
+
+#define CRT0_DUMMIES bogus_fp,
+
+/* crt0.c should define a symbol `start' and do .globl with a dot. */
+
+#define DOT_GLOBAL_START
+
+/* Define EXPLICIT_SIGN_EXTEND if XINT must explicitly sign-extend
+ the 24-bit bit field into an int. In other words, if bit fields
+ are always unsigned.
+
+ If you use NO_UNION_TYPE, this flag does not matter. */
+
+#define EXPLICIT_SIGN_EXTEND
+
+/* Data type of load average, as read out of kmem. */
+
+#define LOAD_AVE_TYPE unsigned long
+
+/* Convert that into an integer that is 100 for a load average of 1.0 */
+
+#define FSCALE 1000.0
+#define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0 / FSCALE)
+
+/* Define CANNOT_DUMP on machines where unexec does not work.
+ Then the function dump-emacs will not be defined
+ and temacs will do (load "loadup") automatically unless told otherwise. */
+
+/* #define CANNOT_DUMP */
+
+/* Define VIRT_ADDR_VARIES if the virtual addresses of
+ pure and impure space as loaded can vary, and even their
+ relative order cannot be relied on.
+
+ Otherwise Emacs assumes that text space precedes data space,
+ numerically. */
+
+/* #define VIRT_ADDR_VARIES */
+
+/* Define C_ALLOCA if this machine does not support a true alloca
+ and the one written in C should be used instead.
+ Define HAVE_ALLOCA to say that the system provides a properly
+ working alloca function and it should be used.
+ Define neither one if an assembler-language alloca
+ in the file alloca.s should be used. */
+
+/* #define C_ALLOCA */
+#define HAVE_ALLOCA
+
+/* Name of file the to look in
+ for the kernel symbol table (for load average) */
+
+#undef KERNEL_FILE
+#define KERNEL_FILE "/dynix"
+
+/* Avoids a compiler bug */
+
+#define TAHOE_REGISTER_BUG
+
+/* Say that the text segment of a.out includes the header;
+ the header actually occupies the first few bytes of the text segment
+ and is counted in hdr.a_text. Furthermore, the value written
+ in the a_text in the file must have N_ADDRADJ added to it. */
+
+#define A_TEXT_OFFSET(HDR) (sizeof (HDR) + N_ADDRADJ (HDR))
+
+/* (short) negative-int doesn't sign-extend correctly */
+#define SHORT_CAST_BUG
+
+/* Cause compilations to be done in parallel in ymakefile. */
+#define MAKE_PARALLEL &
+
+/* Say that mailer interlocking uses flock. */
+#define MAIL_USE_FLOCK
+
+/* On many 4.2-based systems, there's a rather tricky bug
+ * with the interpretation of the pid/pgrp value given to
+ * the F_SETOWN fcntl() call. It works as documented EXCEPT
+ * when applied to filedescriptors for sockets, in which case
+ * the sign must be reversed. If your emacs subprocesses get
+ * SIGIO's when they shouldn't, while running on a socket
+ * (e.g. under X windows), you should probably define this.
+ */
+
+#define F_SETOWN_SOCK_NEG
+
+/* Some really obscure 4.2-based systems (like Sequent DYNIX)
+ * do not support asynchronous I/O (using SIGIO) on sockets,
+ * even though it works fine on tty's. If you have one of
+ * these systems, define the following, and then use it in
+ * config.h (or elsewhere) to decide when (not) to use SIGIO.
+ */
+
+#define NO_SOCK_SIGIO
+
+/* Define how to search all pty names.
+ This is for Dynix 3.0; delete next 5 definitions for older systems. */
+
+#define PTY_MAJOR "pqrstuvwPQRSTUVW"
+#define PTY_MINOR "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+#define PTY_ITERATION \
+ register int ma, mi; \
+ for (ma = 0; ma < sizeof(PTY_MAJOR) - 1; ma++) \
+ for (mi = 0; mi < sizeof(PTY_MINOR) - 1; mi++)
+#define PTY_NAME_SPRINTF \
+ sprintf (pty_name, "/dev/pty%c%c", PTY_MAJOR[ma], PTY_MINOR[mi]);
+#define PTY_TTY_NAME_SPRINTF \
+ sprintf (pty_name, "/dev/tty%c%c", PTY_MAJOR[ma], PTY_MINOR[mi]);
diff --git a/src/m-sgi3000.h b/src/m-sgi3000.h
new file mode 100644
index 00000000000..5f394c6ad9b
--- /dev/null
+++ b/src/m-sgi3000.h
@@ -0,0 +1 @@
+#include "m-irist.h"
diff --git a/src/m-sparc.h b/src/m-sparc.h
new file mode 100644
index 00000000000..663206a77e1
--- /dev/null
+++ b/src/m-sparc.h
@@ -0,0 +1,113 @@
+/* m- file for Sun 4 SPARC.
+ Copyright (C) 1987 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+#define SHORTBITS 16 /* Number of bits in a short */
+
+#define INTBITS 32 /* Number of bits in an int */
+
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* SPARC has lowest-numbered byte as most significant */
+
+#define BIG_ENDIAN
+
+/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
+ * group of arguments and treat it as an array of the arguments. */
+
+#define NO_ARG_ARRAY
+
+/* Define how to take a char and sign-extend into an int.
+ On machines where char is signed, this is a no-op. */
+
+#define SIGN_EXTEND_CHAR(c) (c)
+
+/* Say this machine is a sparc */
+
+#ifndef sparc
+#define sparc
+#endif
+
+/* This level of optimization is reported to work. */
+
+#ifdef __GNUC__
+# define C_OPTIMIZE_SWITCH -O
+#else
+ /* This level of optimization is reported to work. */
+# define C_OPTIMIZE_SWITCH -O2
+#endif
+
+/* Use type int rather than a union, to represent Lisp_Object */
+
+#define NO_UNION_TYPE
+
+/* XINT must explicitly sign-extend */
+
+#define EXPLICIT_SIGN_EXTEND
+
+/* Data type of load average, as read out of kmem. */
+
+#define LOAD_AVE_TYPE long
+
+/* Convert that into an integer that is 100 for a load average of 1.0 */
+
+#define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0 / FSCALE)
+
+/* Define 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
+#include <alloca.h>
+
+/* Must use the system's termcap. It does special things. */
+
+#define LIBS_TERMCAP -ltermcap
+
+/* Mask for address bits within a memory segment */
+
+#define SEGMENT_MASK (SEGSIZ - 1)
+
+/* Arrange to link with sun windows, if requested. */
+/* For details on emacstool and sunfns, see etc/SUN-SUPPORT */
+/* These programs require Sun UNIX 4.2 Release 3.2 or greater */
+
+#ifdef HAVE_SUN_WINDOWS
+#ifndef NO_SUNVIEW
+#define OTHER_FILES ${etcdir}emacstool
+#define LIBS_MACHINE -lsuntool -lsunwindow -lpixrect
+#else
+#define OTHER_FILES ${etcdir}xvetool
+#endif
+#define OBJECTS_MACHINE sunfns.o
+#define SYMS_MACHINE syms_of_sunfns ()
+#define PURESIZE 130000
+#endif
+
+/* Say that the text segment of a.out includes the header;
+ the header actually occupies the first few bytes of the text segment
+ and is counted in hdr.a_text. */
+
+#define A_TEXT_OFFSET(HDR) sizeof (HDR)
diff --git a/src/m-stride.h b/src/m-stride.h
new file mode 100644
index 00000000000..c8e706a4b66
--- /dev/null
+++ b/src/m-stride.h
@@ -0,0 +1,130 @@
+/* Definitions file for GNU Emacs running on Stride Micro System-V.2.2
+ Copyright (C) 1985, 1986 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+#define SHORTBITS 16 /* Number of bits in a short */
+
+#define INTBITS 32 /* Number of bits in an int */
+
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* 68000 has lowest-numbered byte as most significant */
+
+#define BIG_ENDIAN
+
+/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
+ * group of arguments and treat it as an array of the arguments. */
+
+#undef NO_ARG_ARRAY
+
+/* Define WORD_MACHINE if addresses and such have
+ * to be corrected before they can be used as byte counts. */
+
+#undef WORD_MACHINE
+
+/* Define how to take a char and sign-extend into an int.
+ On machines where char is signed, this is a no-op. */
+
+#define SIGN_EXTEND_CHAR(c) (c)
+
+/* Now define a symbol for the cpu type, if your compiler
+ does not define it automatically:
+ vax, m68000, ns16000, pyramid, orion, tahoe, APOLLO and STRIDE
+ are the ones defined so far. */
+
+#define m68000 /* because the SGS compiler defines "m68k" */
+#ifndef STRIDE
+#define STRIDE
+#endif
+
+/* Use type int rather than a union, to represent Lisp_Object */
+/* This is desirable for most machines. */
+
+#define NO_UNION_TYPE
+
+/* Define EXPLICIT_SIGN_EXTEND if XINT must explicitly sign-extend
+ the 24-bit bit field into an int. In other words, if bit fields
+ are always unsigned.
+
+ If you use NO_UNION_TYPE, this flag does not matter. */
+
+#define EXPLICIT_SIGN_EXTEND
+
+/* Data type of load average, as read out of kmem. */
+
+#define LOAD_AVE_TYPE double
+
+/* Convert that into an integer that is 100 for a load average of 1.0 */
+
+#define LOAD_AVE_CVT(x) ((int) ((x) * 100.0))
+
+/* Define CANNOT_DUMP on machines where unexec does not work.
+ Then the function dump-emacs will not be defined
+ and temacs will do (load "loadup") automatically unless told otherwise. */
+
+#undef CANNOT_DUMP
+
+/* Define VIRT_ADDR_VARIES if the virtual addresses of
+ pure and impure space as loaded can vary, and even their
+ relative order cannot be relied on.
+
+ Otherwise Emacs assumes that text space precedes data space,
+ numerically. */
+
+#undef VIRT_ADDR_VARIES
+
+/* The STRIDE system is more powerful than standard USG5. */
+
+#define HAVE_PTYS
+#define HAVE_TIMEVAL
+#define HAVE_SELECT
+#define HAVE_GETTIMEOFDAY
+#define BSTRING
+#define SKTPAIR
+#define HAVE_SOCKETS
+
+#define MAIL_USE_FLOCK
+#undef TERMINFO
+#define EXEC_MAGIC 0413
+
+/* USG wins again: Foo! I can't get SIGIO to work properly on the Stride, because I'm
+ running a System V variant, and don't have a reliable way to block SIGIO
+ signals without losing them. So, I've gone back to non-SIGIO mode, so
+ please append this line to the file "m-stride.h":
+ */
+#undef SIGIO
+
+/* Specify alignment requirement for start of text and data sections
+ in the executable file. */
+
+#define SECTION_ALIGNMENT (getpagesize() - 1)
+
+/*
+ * UniStride has this in /lib/libc.a.
+ */
+#undef NONSYSTEM_DIR_LIBRARY
+
+/* UniStride defines getwd. */
+
+#define HAVE_GETWD
+
+
diff --git a/src/m-sun1.h b/src/m-sun1.h
new file mode 100644
index 00000000000..529e40eb7b9
--- /dev/null
+++ b/src/m-sun1.h
@@ -0,0 +1,68 @@
+/* m- file for Sun 68000's
+ Copyright (C) 1985, 1986 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+#define SHORTBITS 16 /* Number of bits in a short */
+
+#define INTBITS 32 /* Number of bits in an int */
+
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* 68000 has lowest-numbered byte as most significant */
+
+#define BIG_ENDIAN
+
+/* Define how to take a char and sign-extend into an int.
+ On machines where char is signed, this is a no-op. */
+
+#define SIGN_EXTEND_CHAR(c) (c)
+
+/* Say this machine is a 68000 */
+
+#define m68000
+
+/* Use type int rather than a union, to represent Lisp_Object */
+
+#define NO_UNION_TYPE
+
+/* Sun can't write competant compilers */
+#define COMPILER_REGISTER_BUG
+
+/* XINT must explicitly sign-extend */
+
+#define EXPLICIT_SIGN_EXTEND
+
+/* Data type of load average, as read out of kmem. */
+
+#define LOAD_AVE_TYPE long
+
+/* Convert that into an integer that is 100 for a load average of 1.0 */
+
+#define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0 / FSCALE)
+
+/* Must use the system's termcap. It does special things. */
+
+#define LIBS_TERMCAP -ltermcap
+
+/* Mask for address bits within a memory segment */
+
+#define SEGMENT_MASK (SEGSIZ - 1)
diff --git a/src/m-sun2.h b/src/m-sun2.h
new file mode 100644
index 00000000000..fd0cdb38a28
--- /dev/null
+++ b/src/m-sun2.h
@@ -0,0 +1,89 @@
+/* m- file for Sun 68000's OPERATING SYSTEM version 2.
+ Note that "m-sun2.h" refers to the operating system version, not the
+ CPU model number. See the MACHINES file for details.
+ Copyright (C) 1985, 1986 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+#define SHORTBITS 16 /* Number of bits in a short */
+
+#define INTBITS 32 /* Number of bits in an int */
+
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* 68000 has lowest-numbered byte as most significant */
+
+#define BIG_ENDIAN
+
+/* Define how to take a char and sign-extend into an int.
+ On machines where char is signed, this is a no-op. */
+
+#define SIGN_EXTEND_CHAR(c) (c)
+
+/* Say this machine is a 68000 */
+
+#ifndef m68000
+#define m68000
+#endif
+
+/* Use type int rather than a union, to represent Lisp_Object */
+
+#define NO_UNION_TYPE
+
+/* Sun can't write competent compilers */
+#define COMPILER_REGISTER_BUG
+
+/* XINT must explicitly sign-extend */
+
+#define EXPLICIT_SIGN_EXTEND
+
+/* Data type of load average, as read out of kmem. */
+
+#define LOAD_AVE_TYPE long
+
+/* Convert that into an integer that is 100 for a load average of 1.0 */
+
+#define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0 / FSCALE)
+
+/* Say that this is a Sun 2; must check for and maybe reinitialize
+ the "sky" board. */
+
+#define sun2
+
+/* Must use the system's termcap. It does special things. */
+
+#define LIBS_TERMCAP -ltermcap
+
+/* Mask for address bits within a memory segment */
+
+#define SEGMENT_MASK (SEGSIZ - 1)
+
+/* Arrange to link with sun windows, if requested. */
+/* For details on emacstool and sunfns, see etc/SUN-SUPPORT */
+/* These programs require Sun UNIX 4.2 Release 3.2 or greater */
+
+#ifdef HAVE_SUN_WINDOWS
+#define OTHER_FILES ${etcdir}emacstool
+#define LIBS_MACHINE -lsuntool -lsunwindow -lpixrect
+#define OBJECTS_MACHINE sunfns.o
+#define SYMS_MACHINE syms_of_sunfns ()
+#define PURESIZE 132000
+#endif
diff --git a/src/m-sun3.h b/src/m-sun3.h
new file mode 100644
index 00000000000..d4e732e2dc5
--- /dev/null
+++ b/src/m-sun3.h
@@ -0,0 +1,26 @@
+/* m- file for Sun 68000's OPERATING SYSTEM version 3
+ (for either 68000 or 68020 systems). */
+
+#include "m-sun2.h"
+#undef sun2
+#ifndef sun3
+#define sun3
+#endif
+
+/* Say that the text segment of a.out includes the header;
+ the header actually occupies the first few bytes of the text segment
+ and is counted in hdr.a_text. */
+
+#define A_TEXT_OFFSET(HDR) sizeof (HDR)
+
+/* In case we are using floating point, work together with crt0.c. */
+
+#ifndef __GNUC__
+#define C_SWITCH_MACHINE -fsoft
+#endif
+
+/* This line is needed if you are linking with X windows
+ and the library xlib was compiled to use the 68881.
+ For maximum cleanliness, don't edit this file;
+ instead, insert this line in config.h. */
+/* #define START_FILES crt0.o /usr/lib/Mcrt1.o */
diff --git a/src/m-sun386.h b/src/m-sun386.h
new file mode 100644
index 00000000000..e3fd584068b
--- /dev/null
+++ b/src/m-sun386.h
@@ -0,0 +1,63 @@
+/* m- file for Sun's 386-based RoadRunner. This file borrows heavily from
+ "m-sun2.h", but since that file is heavily cpu-specific, it was easier
+ not to include it.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Say this machine is a bird */
+#ifndef roadrunner
+#define roadrunner
+#endif
+
+/* Actual cpu-specific defs */
+#include "m-intel386.h"
+
+/* Data type of load average, as read out of kmem. */
+
+#define LOAD_AVE_TYPE long
+
+/* Convert that into an integer that is 100 for a load average of 1.0 */
+
+#define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0 / FSCALE)
+
+/* Underscores are not prepended to C symbols on this machine. */
+#undef LDAV_SYMBOL
+#define LDAV_SYMBOL "avenrun"
+
+/* Must use the system's termcap. It does special things. */
+
+#define LIBS_TERMCAP -ltermcap
+
+/* Arrange to link with sun windows, if requested. */
+/* For details on emacstool and sunfns, see etc/SUN-SUPPORT */
+/* These programs require Sun UNIX 4.2 Release 3.2 or greater */
+
+#ifdef HAVE_SUN_WINDOWS
+#define OTHER_FILES ${etcdir}emacstool
+#define LIBS_MACHINE -lsuntool -lsunwindow -lpixrect
+#define OBJECTS_MACHINE sunfns.o
+#define SYMS_MACHINE syms_of_sunfns ()
+#define PURESIZE 132000
+#endif
+
+/* Roadrunner uses 'COFF' format */
+#define COFF
+
+#define C_SWITCH_MACHINE -Bstatic /* avoid dynamic linking */
+#define LD_SWITCH_MACHINE -n -Bstatic
+/* Get rid of the -e __start that s-sunos4.h does. */
+#undef LD_SWITCH_SYSTEM
diff --git a/src/m-tad68k.h b/src/m-tad68k.h
new file mode 100644
index 00000000000..58ea419ec81
--- /dev/null
+++ b/src/m-tad68k.h
@@ -0,0 +1,134 @@
+/* Machine-dependent configuration for GNU Emacs for Tadpole 68k machines
+ Copyright (C) 1986 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+#define SHORTBITS 16 /* Number of bits in a short */
+
+#define INTBITS 32 /* Number of bits in an int */
+
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* Define BIG_ENDIAN iff lowest-numbered byte in a word
+ is the most significant byte. */
+
+#define BIG_ENDIAN
+
+/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
+ * group of arguments and treat it as an array of the arguments. */
+
+/* #define NO_ARG_ARRAY */
+
+/* Define WORD_MACHINE if addresses and such have
+ * to be corrected before they can be used as byte counts. */
+
+/* #define WORD_MACHINE */
+
+/* Define how to take a char and sign-extend into an int.
+ On machines where char is signed, this is a no-op. */
+
+#define SIGN_EXTEND_CHAR(c) (c)
+
+/* Now define a symbol for the cpu type, if your compiler
+ does not define it automatically */
+
+/* Use type int rather than a union, to represent Lisp_Object */
+/* This is desirable for most machines. */
+
+#define NO_UNION_TYPE
+
+/* Define EXPLICIT_SIGN_EXTEND if XINT must explicitly sign-extend
+ the 24-bit bit field into an int. In other words, if bit fields
+ are always unsigned.
+
+ If you use NO_UNION_TYPE, this flag does not matter. */
+
+/* #define EXPLICIT_SIGN_EXTEND */
+
+/* Data type of load average, as read out of kmem. */
+/* #define LOAD_AVE_TYPE long */
+
+/* Convert that into an integer that is 100 for a load average of 1.0 */
+
+/* #define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0 / FSCALE) */
+
+/* Define CANNOT_DUMP on machines where unexec does not work.
+ Then the function dump-emacs will not be defined
+ and temacs will do (load "loadup") automatically unless told otherwise. */
+/* #define CANNOT_DUMP */
+
+/* Define VIRT_ADDR_VARIES if the virtual addresses of
+ pure and impure space as loaded can vary, and even their
+ relative order cannot be relied on.
+
+ Otherwise Emacs assumes that text space precedes data space,
+ numerically. */
+
+/* #define VIRT_ADDR_VARIES */ /* Karl Kleinpaste says this isn't needed. */
+
+/* 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
+ 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 */
+
+/* Use Terminfo, not Termcap. */
+
+#define TERMINFO
+
+/* TPIX extras */
+
+#define TPIX /* used in various source files */
+#define BSTRING /* we do have the BSTRING functions */
+#define CLASH_DETECTION /* we want to know about clashes */
+#undef ADDR_CORRECT /* don't need this bug fix */
+#define fchmod /* we don't have fchmod() */
+#define SECTION_ALIGNMENT (256*1024-1) /* TP-IX 1.3 needs 256k align.
+ In older versions, 2k was enuf. */
+#define SEGMENT_MASK (128*1024-1) /* 128k offsets required in unexec */
+#define C_DEBUG_SWITCH -O /* build with -O (TPIX has GCC 1.34) */
+
+#define BROKEN_TIOCGWINSZ /* Don't try to use TIOCGWINSZ. */
+
+/* omit next four lines if no TCP installed */
+
+#define select gnu_select /* avoid select() name clash */
+#define HAVE_PTYS /* we do have PTYs if we have TCP */
+#define HAVE_SOCKETS /* we do have sockets if we have TCP */
+#define LIBS_SYSTEM -lsocket /* get TCP networking functions */
+
+#define HAVE_RANDOM
+
+/* Needed for getpagesize.h. */
+#define NBPC 4096
diff --git a/src/m-tahoe.h b/src/m-tahoe.h
new file mode 100644
index 00000000000..147c19f321a
--- /dev/null
+++ b/src/m-tahoe.h
@@ -0,0 +1,83 @@
+/* m- file for tahoe.
+ Copyright (C) 1985 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+#define SHORTBITS 16 /* Number of bits in a short */
+
+#define INTBITS 32 /* Number of bits in an int */
+
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* lowest-numbered byte is most significant */
+
+#define BIG_ENDIAN
+
+/* XINT must explicitly sign-extend */
+
+#define EXPLICIT_SIGN_EXTEND
+
+/* Define how to take a char and sign-extend into an int.
+ On machines where char is signed, this is a no-op. */
+
+#define SIGN_EXTEND_CHAR(c) (c)
+
+/* Say this machine is a tahoe */
+
+#ifndef tahoe
+#define tahoe
+#endif /* not tahoe */
+
+/* Use type int rather than a union, to represent Lisp_Object */
+
+#define NO_UNION_TYPE
+
+/* crt0.c should use the vax-bsd style of entry, with no dummy args. */
+
+#define CRT0_DUMMIES
+
+/* crt0.c should define a symbol `start' and do .globl with a dot. */
+
+#define DOT_GLOBAL_START
+
+/* Data type of load average, as read out of kmem. */
+
+#define LOAD_AVE_TYPE double
+
+/* Convert that into an integer that is 100 for a load average of 1.0 */
+
+#define LOAD_AVE_CVT(x) ((int) ((x) * 100.0))
+
+/* This triggers some stuff to avoid a compiler bug */
+
+#define TAHOE_REGISTER_BUG
+
+/* System provides alloca. */
+
+#define HAVE_ALLOCA
+
+/* Control header files used by loadst.c.
+ Some users report machines have dkstat.h while others report dk.h,
+ so it's hard to tell what this should say. */
+
+#ifdef BSD
+#define DKSTAT_HEADER_FILE
+#endif
diff --git a/src/m-tandem-s2.h b/src/m-tandem-s2.h
new file mode 100644
index 00000000000..f91fdb13ec2
--- /dev/null
+++ b/src/m-tandem-s2.h
@@ -0,0 +1,90 @@
+/* m- file for the Tandem Integrity S2. */
+
+#include "m-mips.h"
+
+/* This overrides some of the usual support for the mips and system V.3. */
+
+/* Comment this out if using NonStop-UX OS rev. below A10. */
+#define A10
+
+/* If not using X11R4, then comment out. /usr/lib/libX11.a has */
+ /* globally define bcopy, bcmp, bzero, random & srandom that conflicts */
+ /* with GNU's. You won't need this for X11R3 .*/
+#define USE_X11R4
+
+/* START_FILES and LIB_STANDARD are located in different places for
+ 'C' version 2.10 */
+#ifdef A10
+#ifdef START_FILES
+#undef START_FILES
+#define START_FILES pre-crt0.o /lib/crt1.o
+#endif
+
+#ifdef LIB_STANDARD
+#undef LIB_STANDARD
+#define LIB_STANDARD -lc /lib/crtn.o
+#endif
+#else /* Revision below A10 */
+#ifdef START_FILES
+#undef START_FILES
+#define START_FILES pre-crt0.o /usr/lib/crt1.o
+#endif
+
+#ifdef LIB_STANDARD
+#undef LIB_STANDARD
+#define LIB_STANDARD -lc /usr/lib/crtn.o
+#endif
+#endif /* End #ifdef A10 vs not */
+
+/* Use X11R4's bcopy, bmem,bzero, random & srandom rather than GNU's */
+ /* which causes multiply-defined problems when -lX11 is loaded. */
+#ifdef USE_X11R4
+#define HAVE_RANDOM /* Use X's random */
+#define BSTRING /* Use X's bcopy, bmem and bzero */
+#endif
+
+/* The S2 does not know about utimes() */
+#define USE_UTIME
+
+/* The operating system apparently defines TIOCGETC
+ but it doesn't work. */
+#undef BROKEN_TIOCGETC
+
+/* Change LIBS_TERMCAP (from m-mips.h) to ensure that libbsd.a is loaded
+ before libcurses.a. The curses library has its own version of select(2)
+ which does not work with GNU Emacs; libbsd.a has the right version.
+
+ We also use the malloc(3X) package in place of both malloc(3C) in libc.a
+ and GNU malloc. The GNU malloc is not working correctly for large files
+ (2MB and up), and malloc(3X) handles this better than malloc(3C). */
+#ifdef LIBS_TERMCAP
+#undef LIBS_TERMCAP
+#define LIBS_TERMCAP -lmalloc -lbsd -lcurses
+#endif
+
+#define SYSTEM_MALLOC
+
+/* Note that src/ymakefile should also be changed to load LIBS_TERMCAP _after_
+ $(LIBX), since libX11.a has its own version of writev which should override
+ the version in libbsd.a. */
+
+/* Emacs can use the NonStop-UX select(2) to support subprocesses and X11.
+ Note that the correct version of select(2) is in libbsd.a; see above. */
+#define HAVE_SELECT
+
+/* Subprocesses now work because we are using the correct select(2) call.
+ The reason it didn't work before was because curses with its select call
+ was being loaded before the correct select(2) which is in libbsd.a. */
+#ifndef subprocesses
+#define subprocesses
+#endif
+
+/* The gettimeofday(2) routine is present in libbsd.a but is not supported
+ or documented. */
+#undef HAVE_GETTIMEOFDAY
+
+/* Remove definition of LIBX11_SYSTEM (from s-usg5-3.h). It references
+ a library -lnsl_s that is not present and not required on the S2. */
+#ifdef LIBX11_SYSTEM
+#undef LIBX11_SYSTEM
+#endif
diff --git a/src/m-targon31.h b/src/m-targon31.h
new file mode 100644
index 00000000000..d229ec0a5ee
--- /dev/null
+++ b/src/m-targon31.h
@@ -0,0 +1,119 @@
+/* m-targon31 file template.
+ Copyright (C) 1985, 1986 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+#define SHORTBITS 16 /* Number of bits in a short */
+
+#define INTBITS 32 /* Number of bits in an int */
+
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* Define BIG_ENDIAN iff lowest-numbered byte in a word
+ is the most significant byte. */
+
+#define BIG_ENDIAN
+
+/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
+ * group of arguments and treat it as an array of the arguments. */
+
+/* #define NO_ARG_ARRAY */
+
+/* Define WORD_MACHINE if addresses and such have
+ * to be corrected before they can be used as byte counts. */
+
+#define WORD_MACHINE
+
+/* Define how to take a char and sign-extend into an int.
+ On machines where char is signed, this is a no-op. */
+
+#define SIGN_EXTEND_CHAR(c) (c)
+
+/* Now define a symbol for the cpu type, if your compiler
+ does not define it automatically:
+ vax, m68000, ns16000, pyramid, orion, tahoe and APOLLO
+ are the ones defined so far. */
+
+/* #define m68k is defined by the Compiler */
+/* #define m68000 */
+
+/* Use type int rather than a union, to represent Lisp_Object */
+/* This is desirable for most machines. */
+
+#define NO_UNION_TYPE
+
+/* Define EXPLICIT_SIGN_EXTEND if XINT must explicitly sign-extend
+ the 24-bit bit field into an int. In other words, if bit fields
+ are always unsigned.
+
+ If you use NO_UNION_TYPE, this flag does not matter. */
+
+#define EXPLICIT_SIGN_EXTEND
+
+/* Data type of load average, as read out of kmem. */
+
+/* #define LOAD_AVE_TYPE double */
+
+/* Convert that into an integer that is 100 for a load average of 1.0 */
+
+#define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0)
+
+/* Define CANNOT_DUMP on machines where unexec does not work.
+ Then the function dump-emacs will not be defined
+ and temacs will do (load "loadup") automatically unless told otherwise. */
+
+/* #define CANNOT_DUMP */
+
+/* Define VIRT_ADDR_VARIES if the virtual addresses of
+ pure and impure space as loaded can vary, and even their
+ relative order cannot be relied on.
+
+ Otherwise Emacs assumes that text space precedes data space,
+ numerically. */
+
+/* #define VIRT_ADDR_VARIES */
+
+/* Define C_ALLOCA if this machine does not support a true alloca
+ and the one written in C should be used instead.
+ Define HAVE_ALLOCA to say that the system provides a properly
+ working alloca function and it should be used.
+ Define neither one if an assembler-language alloca
+ in the file alloca.s should be used. */
+
+/* #define C_ALLOCA */
+/* #define HAVE_ALLOCA */
+#ifdef __GNUC__
+#define SYSTEM_MALLOC
+#define HAVE_ALLOCA
+#define alloca(a) __builtin_alloca(a)
+#endif
+
+#define SWITCH_ENUM_BUG 1
+
+/* #define NO_REMAP */
+/* NO_REMAP was an alternative to defining SEGMENT_MASK. */
+#define SEGMENT_MASK 0xffff
+
+/* Some additional system facilities. */
+#define HAVE_SYSVIPC
+#define HAVE_PTYS
+#define HAVE_SOCKETS
+#define BSTRING
diff --git a/src/m-tek4300.h b/src/m-tek4300.h
new file mode 100644
index 00000000000..157d461a54b
--- /dev/null
+++ b/src/m-tek4300.h
@@ -0,0 +1,96 @@
+/* m- file for tek4300.
+ Copyright (C) 1988 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+#define SHORTBITS 16 /* Number of bits in a short */
+
+#define INTBITS 32 /* Number of bits in an int */
+
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* 68000 has lowest-numbered byte as most significant */
+
+#define BIG_ENDIAN
+
+/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
+ * group of arguments and treat it as an array of the arguments. */
+
+#undef NO_ARG_ARRAY
+
+/* Define WORD_MACHINE if addresses and such have
+ * to be corrected before they can be used as byte counts. */
+
+#undef WORD_MACHINE
+
+/* Define how to take a char and sign-extend into an int.
+ On machines where char is signed, this is a no-op. */
+
+#define SIGN_EXTEND_CHAR(c) (c)
+
+/* Now define a symbol for the cpu type, if your compiler
+ does not define it automatically. */
+
+#ifndef tek4300
+#define tek4300
+#endif
+
+/* Use type int rather than a union, to represent Lisp_Object */
+
+#define NO_UNION_TYPE
+
+/* Data type of load average, as read out of kmem. */
+
+#define LOAD_AVE_TYPE long
+
+/* Convert that into an integer that is 100 for a load average of 1.0 */
+
+#define LOAD_AVE_CVT(x) (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
+ 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 C_ALLOCA
+
+/* setjmp and longjmp can safely replace _setjmp and _longjmp, */
+
+#define _longjmp longjmp
+#define _setjmp setjmp
+
+/* The text segment always starts at a fixed address.
+ This way we don't need to have a label _start defined. */
+
+#define TEXT_START 0
+
+/* The Tektronix exec struct for ZMAGIC files is struct zexec */
+
+#define EXEC_HDR_TYPE struct zexec
+
+/* The entry-point label (start of text segment) is `start', not `__start'. */
+
+#define DEFAULT_ENTRY_ADDRESS start
diff --git a/src/m-template.h b/src/m-template.h
new file mode 100644
index 00000000000..493d7032e6d
--- /dev/null
+++ b/src/m-template.h
@@ -0,0 +1,106 @@
+/* m- file template.
+ Copyright (C) 1985, 1986 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+#define SHORTBITS 16 /* Number of bits in a short */
+
+#define INTBITS 32 /* Number of bits in an int */
+
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* Define BIG_ENDIAN iff lowest-numbered byte in a word
+ is the most significant byte. */
+
+#define BIG_ENDIAN
+
+/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
+ * group of arguments and treat it as an array of the arguments. */
+
+#define NO_ARG_ARRAY
+
+/* Define WORD_MACHINE if addresses and such have
+ * to be corrected before they can be used as byte counts. */
+
+#define WORD_MACHINE
+
+/* Define how to take a char and sign-extend into an int.
+ On machines where char is signed, this is a no-op. */
+
+#define SIGN_EXTEND_CHAR(c) (c)
+
+/* Now define a symbol for the cpu type, if your compiler
+ does not define it automatically:
+ Ones defined so far include vax, m68000, ns16000, pyramid,
+ orion, tahoe, APOLLO and many others */
+
+/* Use type int rather than a union, to represent Lisp_Object */
+/* This is desirable for most machines. */
+
+#define NO_UNION_TYPE
+
+/* Define EXPLICIT_SIGN_EXTEND if XINT must explicitly sign-extend
+ the 24-bit bit field into an int. In other words, if bit fields
+ are always unsigned.
+
+ If you use NO_UNION_TYPE, this flag does not matter. */
+
+#define EXPLICIT_SIGN_EXTEND
+
+/* Data type of load average, as read out of kmem. */
+
+#define LOAD_AVE_TYPE long
+
+/* Convert that into an integer that is 100 for a load average of 1.0 */
+
+#define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0 / FSCALE)
+
+/* Define CANNOT_DUMP on machines where unexec does not work.
+ Then the function dump-emacs will not be defined
+ and temacs will do (load "loadup") automatically unless told otherwise. */
+
+#define CANNOT_DUMP
+
+/* Define VIRT_ADDR_VARIES if the virtual addresses of
+ pure and impure space as loaded can vary, and even their
+ relative order cannot be relied on.
+
+ Otherwise Emacs assumes that text space precedes data space,
+ numerically. */
+
+#define VIRT_ADDR_VARIES
+
+/* Define C_ALLOCA if this machine does not support a true alloca
+ and the one written in C should be used instead.
+ Define HAVE_ALLOCA to say that the system provides a properly
+ working alloca function and it should be used.
+ Define neither one if an assembler-language alloca
+ in the file alloca.s should be used. */
+
+#define C_ALLOCA
+#define HAVE_ALLOCA
+
+/* Define NO_REMAP if memory segmentation makes it not work well
+ to change the boundary between the text section and data section
+ when Emacs is dumped. If you define this, the preloaded Lisp
+ code will not be sharable; but that's better than failing completely. */
+
+#define NO_REMAP
diff --git a/src/m-tower32.h b/src/m-tower32.h
new file mode 100644
index 00000000000..d3551b12c85
--- /dev/null
+++ b/src/m-tower32.h
@@ -0,0 +1,130 @@
+/* m- file for the NCR Tower 32 running System V.2.
+ Copyright (C) 1986 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+#define SHORTBITS 16 /* Number of bits in a short */
+
+#define INTBITS 32 /* Number of bits in an int */
+
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* Define BIG_ENDIAN iff lowest-numbered byte in a word
+ is the most significant byte. */
+
+#define BIG_ENDIAN
+
+/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
+ * group of arguments and treat it as an array of the arguments. */
+
+/* #define NO_ARG_ARRAY */
+
+/* Define WORD_MACHINE if addresses and such have
+ * to be corrected before they can be used as byte counts. */
+
+/* #define WORD_MACHINE */
+
+/* Define how to take a char and sign-extend into an int.
+ On machines where char is signed, this is a no-op. */
+
+#define SIGN_EXTEND_CHAR(c) (c)
+
+/* Now define a symbol for the cpu type, if your compiler
+ does not define it automatically:
+ vax, m68000, ns16000, pyramid, orion, tahoe and APOLLO
+ are the ones defined so far. */
+#define m68000
+
+/* Use type int rather than a union, to represent Lisp_Object */
+/* This is desirable for most machines. */
+
+#define NO_UNION_TYPE
+
+/* Define EXPLICIT_SIGN_EXTEND if XINT must explicitly sign-extend
+ the 24-bit bit field into an int. In other words, if bit fields
+ are always unsigned.
+
+ If you use NO_UNION_TYPE, this flag does not matter. */
+
+#define EXPLICIT_SIGN_EXTEND
+
+/* Data type of load average, as read out of kmem. */
+
+/* #define LOAD_AVE_TYPE long */
+
+/* Convert that into an integer that is 100 for a load average of 1.0 */
+
+/* #define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0 / FSCALE) */
+
+/* Define CANNOT_DUMP on machines where unexec does not work.
+ Then the function dump-emacs will not be defined
+ and temacs will do (load "loadup") automatically unless told otherwise. */
+
+/* #define CANNOT_DUMP */
+
+/* Define VIRT_ADDR_VARIES if the virtual addresses of
+ pure and impure space as loaded can vary, and even their
+ relative order cannot be relied on.
+
+ Otherwise Emacs assumes that text space precedes data space,
+ numerically. */
+
+/* #define VIRT_ADDR_VARIES */
+
+/* Define C_ALLOCA if this machine does not support a true alloca
+ and the one written in C should be used instead.
+ Define HAVE_ALLOCA to say that the system provides a properly
+ working alloca function and it should be used.
+ Define neither one if an assembler-language alloca
+ in the file alloca.s should be used. */
+
+/* #define C_ALLOCA */
+#define HAVE_ALLOCA
+
+/* Change some things to avoid bugs in compiler */
+
+#define SWITCH_ENUM_BUG 1
+
+/* The standard C library is -lcieee, not -lc.
+ Also use the PW library, which contains alloca. */
+
+#define LIB_STANDARD -lPW -lcieee
+
+/* crt0.c should use the vax-bsd style of entry. Beware that if you have
+ OS release 2.00.00 or later, *and* change src/ymakefile so that CFLAGS
+ includes C_OPTIMIZE_SWITCH rather than C_DEBUG_SWITCH, you need to
+ uncomment CRT0_DUMMIES and C_OPTIMIZE_SWITCH below. */
+
+/* With the optimizer OFF */
+
+#define CRT0_DUMMIES zero, bogus_fp,
+
+/* With the optimizer ON */
+
+/* #define CRT0_DUMMIES */
+/* #define C_OPTIMIZE_SWITCH -O2 */
+
+/* emacs's magic number isn't temacs's;
+ temacs is writeable text (the default!). */
+
+#include <asld.h>
+#define EXEC_MAGIC AOUT1MAGIC
+#define EXEC_PAGESIZE DATACLICK
diff --git a/src/m-tower32v3.h b/src/m-tower32v3.h
new file mode 100644
index 00000000000..6d541d94bd6
--- /dev/null
+++ b/src/m-tower32v3.h
@@ -0,0 +1,134 @@
+/* m- file for the NCR Tower 32 running System V.3.
+ Copyright (C) 1986 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+#define SHORTBITS 16 /* Number of bits in a short */
+
+#define INTBITS 32 /* Number of bits in an int */
+
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* Define BIG_ENDIAN iff lowest-numbered byte in a word
+ is the most significant byte. */
+
+#define BIG_ENDIAN
+
+/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
+ * group of arguments and treat it as an array of the arguments. */
+
+/* #define NO_ARG_ARRAY */
+
+/* Define WORD_MACHINE if addresses and such have
+ * to be corrected before they can be used as byte counts. */
+
+/* #define WORD_MACHINE */
+
+/* Define how to take a char and sign-extend into an int.
+ On machines where char is signed, this is a no-op. */
+
+#define SIGN_EXTEND_CHAR(c) (c)
+
+/* Now define a symbol for the cpu type, if your compiler
+ does not define it automatically:
+ vax, m68000, ns16000, pyramid, orion, tahoe and APOLLO
+ are the ones defined so far. */
+#define m68000
+
+/* Use type int rather than a union, to represent Lisp_Object */
+/* This is desirable for most machines. */
+
+#define NO_UNION_TYPE
+
+/* Define EXPLICIT_SIGN_EXTEND if XINT must explicitly sign-extend
+ the 24-bit bit field into an int. In other words, if bit fields
+ are always unsigned.
+
+ If you use NO_UNION_TYPE, this flag does not matter. */
+
+#define EXPLICIT_SIGN_EXTEND
+
+/* Data type of load average, as read out of kmem. */
+
+/* #define LOAD_AVE_TYPE long */
+
+/* Convert that into an integer that is 100 for a load average of 1.0 */
+
+/* #define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0 / FSCALE) */
+
+/* Define CANNOT_DUMP on machines where unexec does not work.
+ Then the function dump-emacs will not be defined
+ and temacs will do (load "loadup") automatically unless told otherwise. */
+
+/* #define CANNOT_DUMP */
+
+/* Define VIRT_ADDR_VARIES if the virtual addresses of
+ pure and impure space as loaded can vary, and even their
+ relative order cannot be relied on.
+
+ Otherwise Emacs assumes that text space precedes data space,
+ numerically. */
+
+/* #define VIRT_ADDR_VARIES */
+
+/* Define C_ALLOCA if this machine does not support a true alloca
+ and the one written in C should be used instead.
+ Define HAVE_ALLOCA to say that the system provides a properly
+ working alloca function and it should be used.
+ Define neither one if an assembler-language alloca
+ in the file alloca.s should be used. */
+
+#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 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
+
+/* The OS maps the data section far away from the text section. */
+#define NO_REMAP
+#define TEXT_START 0
+#undef static
+#define START_FILES pre-crt0.o /lib/crt1.o
+
+/* This is needed since many Tower models start the data/bss segment at
+ an address as large as 0x2000000. */
+#define VALBITS 26
+#define GCTYPEBITS 5
+
+/* The OS has an implementation of symlinks that is semantically different
+ from BSD, but for some silly reason it partly has the same syntax. */
+#undef S_IFLNK
+
+/* The OS needs stream.h+ptem.h included in sysdep.c. */
+#define NO_SIOCTL_H
+#define NEED_PTEM_H
diff --git a/src/m-triton88.h b/src/m-triton88.h
new file mode 100644
index 00000000000..d15b202c07d
--- /dev/null
+++ b/src/m-triton88.h
@@ -0,0 +1,51 @@
+/* m- file for Motorola System V/88 machines
+ Copyright (C) 1985 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "m-delta88.h"
+
+#ifndef TRITON88
+#define TRITON88
+#endif /* TRITON88 */
+
+/* I don't think Trinto88 needs this. */
+
+#ifdef BROKEN_FIONREAD
+#undef BROKEN_FIONREAD
+#endif /* BROKEN_FIONREAD */
+
+/* Need this to prevent Ctrl-Z from suspending Emacs before suspend-emacs
+ have been called. */
+
+#define HAVE_TCATTR
+
+/* libc defines the following functions. */
+
+#define HAVE_RENAME
+#define HAVE_CLOSEDIR
+#define HAVE_DUP2
+#define HAVE_SETSID
+
+/* Have to this because of the brain damaged malloc in libc on Triton88
+ machines. */
+
+#define C_SWITCH_SYSTEM -Dmalloc=_malloc -Dfree=_free -Drealloc=_realloc -Dcalloc=_calloc
+
+/* There is no termio.h. */
+
+#define NO_TERMIO
diff --git a/src/m-ustation.h b/src/m-ustation.h
new file mode 100644
index 00000000000..fa7e9c44c27
--- /dev/null
+++ b/src/m-ustation.h
@@ -0,0 +1,137 @@
+/* m- file for Ustation E30.
+ Copyright (C) 1988 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+#define SHORTBITS 16 /* Number of bits in a short */
+
+#define INTBITS 32 /* Number of bits in an int */
+
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* Define BIG_ENDIAN iff lowest-numbered byte in a word
+ is the most significant byte. */
+
+#define BIG_ENDIAN
+
+/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
+ * group of arguments and treat it as an array of the arguments. */
+
+/* #define NO_ARG_ARRAY */
+
+/* Define WORD_MACHINE if addresses and such have
+ * to be corrected before they can be used as byte counts. */
+
+/* #define WORD_MACHINE */
+
+/* Define how to take a char and sign-extend into an int.
+ On machines where char is signed, this is a no-op. */
+
+#define SIGN_EXTEND_CHAR(c) (c)
+
+/* Now define a symbol for the cpu type, if your compiler
+ does not define it automatically:
+ Ones defined so far include vax, m68000, ns16000, pyramid,
+ orion, tahoe, APOLLO and many others */
+
+#define m68000
+
+/* Use type int rather than a union, to represent Lisp_Object */
+/* This is desirable for most machines. */
+
+#define NO_UNION_TYPE
+
+/* Define EXPLICIT_SIGN_EXTEND if XINT must explicitly sign-extend
+ the 24-bit bit field into an int. In other words, if bit fields
+ are always unsigned.
+
+ If you use NO_UNION_TYPE, this flag does not matter. */
+
+/* #define EXPLICIT_SIGN_EXTEND */
+
+/* Data type of load average, as read out of kmem. */
+
+#define LOAD_AVE_TYPE double
+
+/* Convert that into an integer that is 100 for a load average of 1.0 */
+
+#define LOAD_AVE_CVT(x) ((int) ((x) * 100.0))
+
+/* Define CANNOT_DUMP on machines where unexec does not work.
+ Then the function dump-emacs will not be defined
+ and temacs will do (load "loadup") automatically unless told otherwise. */
+
+/* #define CANNOT_DUMP */
+
+/* Define VIRT_ADDR_VARIES if the virtual addresses of
+ pure and impure space as loaded can vary, and even their
+ relative order cannot be relied on.
+
+ Otherwise Emacs assumes that data space precedes text space,
+ numerically. */
+
+/* #define VIRT_ADDR_VARIES */
+
+/* Define C_ALLOCA if this machine does not support a true alloca
+ and the one written in C should be used instead.
+ Define HAVE_ALLOCA to say that the system provides a properly
+ working alloca function and it should be used.
+ Define neither one if an assembler-language alloca
+ in the file alloca.s should be used. */
+
+#define C_ALLOCA
+
+/* #define HAVE_ALLOCA */
+
+/* Define NO_REMAP if memory segmentation makes it not work well
+ to change the boundary between the text section and data section
+ when Emacs is dumped. If you define this, the preloaded Lisp
+ code will not be sharable; but that's better than failing completely. */
+
+/* #define NO_REMAP */
+
+/* Prevent -lg from being used for debugging. Not implemented? */
+
+#define LIBS_DEBUG
+
+/* -lnet is not standard library */
+
+#undef HAVE_SELECT
+#undef LIBS_SYSTEM
+
+/* Compiler's bug */
+
+#define SWITCH_ENUM_BUG
+
+/* Termcap is available */
+
+#define LIBS_TERMCAP -ltermcap
+
+/* */
+
+#define EXEC_PAGESIZE 1024
+#define PURESIZE 130000
+
+#undef HAVE_TIMEVAL
+#undef NONSYSTEM_DIR_LIBRARY
+
+#undef SIGIO
+#undef SIGTSTP
diff --git a/src/m-vax.h b/src/m-vax.h
new file mode 100644
index 00000000000..f929b9ccd26
--- /dev/null
+++ b/src/m-vax.h
@@ -0,0 +1,104 @@
+/* m- file for vax.
+ Copyright (C) 1985, 1986 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+#define SHORTBITS 16 /* Number of bits in a short */
+
+#define INTBITS 32 /* Number of bits in an int */
+
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* Vax is not big-endian: lowest numbered byte is least significant. */
+
+/* #undef BIG_ENDIAN */
+
+/* Define how to take a char and sign-extend into an int.
+ On machines where char is signed, this is a no-op. */
+
+#define SIGN_EXTEND_CHAR(c) (c)
+
+/* #define vax -- appears to be done automatically */
+
+/* Use type int rather than a union, to represent Lisp_Object */
+
+#define NO_UNION_TYPE
+
+/* crt0.c should use the vax-bsd style of entry, with no dummy args. */
+
+#define CRT0_DUMMIES
+
+/* crt0.c should define a symbol `start' and do .globl with a dot. */
+
+#define DOT_GLOBAL_START
+
+#ifdef BSD
+/* USG systems I know of running on Vaxes do not actually
+ support the load average, so disable it for them. */
+
+/* Data type of load average, as read out of kmem. */
+
+#define LOAD_AVE_TYPE double
+
+/* Convert that into an integer that is 100 for a load average of 1.0 */
+
+#define LOAD_AVE_CVT(x) ((int) ((x) * 100.0))
+
+#endif /* BSD */
+
+#ifdef VMS
+
+/* Data type of load average, as read out of driver. */
+
+#define LOAD_AVE_TYPE float
+
+/* Convert that into an integer that is 100 for a load average of 1.0 */
+
+#define LOAD_AVE_CVT(x) ((int) ((x) * 100.0))
+
+#endif /* VMS */
+
+/* Vax sysV has alloca in the PW library. */
+
+#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. */
+#ifndef USG5_0
+#define NO_REMAP
+#endif /* USG 5_0 */
+
+#define TEXT_START 0
+#endif /* USG */
+
+#ifdef BSD
+#define HAVE_ALLOCA
+#endif /* BSD */
+
+#ifdef VMS
+#define C_ALLOCA
+#endif
+
+#ifdef ultrix
+#define BROKEN_O_NONBLOCK
+#endif
diff --git a/src/m-wicat.h b/src/m-wicat.h
new file mode 100644
index 00000000000..3669d967328
--- /dev/null
+++ b/src/m-wicat.h
@@ -0,0 +1,164 @@
+/* m- file for WICAT machines.
+ Copyright (C) 1986 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* The following three symbols give information on
+ the size of various data types. */
+
+#define SHORTBITS 16 /* Number of bits in a short */
+
+#define INTBITS 32 /* Number of bits in an int */
+
+#define LONGBITS 32 /* Number of bits in a long */
+
+/* Define BIG_ENDIAN iff lowest-numbered byte in a word
+ is the most significant byte. */
+
+#define BIG_ENDIAN
+
+/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
+ * group of arguments and treat it as an array of the arguments. */
+
+#undef NO_ARG_ARRAY
+
+/* Define WORD_MACHINE if addresses and such have
+ * to be corrected before they can be used as byte counts. */
+
+#undef WORD_MACHINE
+
+/* Define how to take a char and sign-extend into an int.
+ On machines where char is signed, this is a no-op. */
+
+#define SIGN_EXTEND_CHAR(c) (c)
+
+/* Now define a symbol for the cpu type, if your compiler
+ does not define it automatically:
+ vax, m68000, ns16000 are the ones defined so far. */
+
+#ifndef m68000
+#define m68000
+#endif
+
+/* This flag is used only in alloca.s. */
+#define WICAT
+
+/* Use type int rather than a union, to represent Lisp_Object */
+
+#define NO_UNION_TYPE
+
+/* XINT must explicitly sign-extend */
+
+#define EXPLICIT_SIGN_EXTEND
+
+/* Data type of load average, as read out of kmem. */
+
+#undef LOAD_AVE_TYPE
+
+/* Convert that into an integer that is 100 for a load average of 1.0 */
+
+#undef LOAD_AVE_CVT
+
+/* Define CANNOT_DUMP on machines where unexec does not work.
+ Then the function dump-emacs will not be defined
+ and temacs will do (load "loadup") automatically unless told otherwise. */
+
+#undef CANNOT_DUMP
+
+/* Define VIRT_ADDR_VARIES if the virtual addresses of
+ pure and impure space as loaded can vary, and even their
+ relative order cannot be relied on.
+
+ Otherwise Emacs assumes that text space precedes data space,
+ numerically. */
+
+#undef VIRT_ADDR_VARIES
+
+/* Define C_ALLOCA if this machine does not support a true alloca
+ and the one written in C should be used instead.
+ Define HAVE_ALLOCA to say that the system provides a properly
+ working alloca function and it should be used.
+ Define neither one if an assembler-language alloca
+ in the file alloca.s should be used. */
+
+/* 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
+ code will not be sharable; but that's better than failing completely. */
+
+#undef NO_REMAP
+
+/* For WICAT, define TAHOE_REGISTER_BUG if you have a pre-4.2 C compiler */
+
+#define TAHOE_REGISTER_BUG
+
+/* pagesize definition */
+
+#define EXEC_PAGESIZE 0x1000
+
+/* Delete this for WICAT sys V releases before 2.0. */
+
+#define LIB_STANDARD -lc-nofp
+
+/* Special magic number */
+
+#define EXEC_MAGIC MC68ROMAGIC
+
+/* Special switches to give to ld. */
+
+#define LD_SWITCH_MACHINE -e __start -N
+
+/* Sigh...cannot define this for WICAT cuz 0 length memcpy blows chunks */
+
+#undef BSTRING
+
+#ifdef BSTRING
+#undef bcopy
+#undef bzero
+#undef bcmp
+
+#define bcopy(a,b,s) memcpy(b,a,s)
+#define bzero(a,s) memset(a,0,s)
+#define bcmp memcmp
+#endif
+
+/*
+ * Define optimflags if you want to optimize.
+ * - Set to null string for pre-4.2 C compiler
+ * - Set to "-O -Wopt,-O-f" for 4.2
+ */
+
+#define C_OPTIMIZE_SWITCH /* -O -Wopt,-O-f */
+
+/* For WICAT version supporting PTYs and select (currently internal only) */
+
+#ifdef HAVE_PTYS
+#undef FIRST_PTY_LETTER
+#define FIRST_PTY_LETTER 'q'
+#endif
+
+/* there is a select() in libcurses.a that causes a conflict so use termlib */
+#ifdef HAVE_SELECT
+#undef TERMINFO
+#define LIBS_TERMCAP select.o -ltermlib
+#endif
diff --git a/src/m/next.h b/src/m/next.h
deleted file mode 100644
index d8d3d76ab15..00000000000
--- a/src/m/next.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/* Configuration file for the NeXT machine. */
-/* Copyright (C) 1985, 1986 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY. No author or distributor
-accepts responsibility to anyone for the consequences of using it
-or for whether it serves any particular purpose or works at all,
-unless he says so in writing. Refer to the GNU Emacs General Public
-License for full details.
-
-Everyone is granted permission to copy, modify and redistribute
-GNU Emacs, but only under the conditions described in the
-GNU Emacs General Public License. A copy of this license is
-supposed to have been given to you along with GNU Emacs so you
-can know your rights and responsibilities. It should be in a
-file named COPYING. Among other things, the copyright notice
-and this notice must be preserved on all copies. */
-
-
-
-
-
-
-
-/* The following three symbols give information on
- the size of various data types. */
-
-#define SHORTBITS 16 /* Number of bits in a short */
-
-#define INTBITS 32 /* Number of bits in an int */
-
-#define LONGBITS 32 /* Number of bits in a long */
-
-/* 68000 has lowest-numbered byte as most significant */
-
-#define BIG_ENDIAN
-
-/* Define how to take a char and sign-extend into an int.
- On machines where char is signed, this is a no-op. */
-
-#define SIGN_EXTEND_CHAR(c) (c)
-
-/* Say this machine is a 68000 */
-
-#ifndef m68000
-#define m68000
-#endif
-
-/* Use type int rather than a union, to represent Lisp_Object */
-
-#define NO_UNION_TYPE
-
-/* Sun can't write competent compilers */
-#define COMPILER_REGISTER_BUG
-
-/* XINT must explicitly sign-extend */
-
-#define EXPLICIT_SIGN_EXTEND
-
-/* Data type of load average, as read out of kmem. */
-
-#define LOAD_AVE_TYPE long
-
-/* Convert that into an integer that is 100 for a load average of 1.0 */
-
-#define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0 / FSCALE)
-
-/* Say that the text segment of a.out includes the header;
- the header actually occupies the first few bytes of the text segment
- and is counted in hdr.a_text. */
-
-#define A_TEXT_OFFSET(HDR) sizeof (HDR)
-
-/* #define _setjmp setjmp */
-/* #define _longjmp longjmp */
-
-/* Use dk.h, not dkstat.h, in loadst.c. */
-
-#define DK_HEADER_FILE
-/* Mask for address bits within a memory segment */
-
-#define SEGSIZ 0x20000
-#define SEGMENT_MASK (SEGSIZ - 1)
-
-#define HAVE_ALLOCA
-
-#define SYSTEM_MALLOC
-
-#define HAVE_UNIX_DOMAIN
-
diff --git a/src/macros.c b/src/macros.c
new file mode 100644
index 00000000000..e4e0a168ebb
--- /dev/null
+++ b/src/macros.c
@@ -0,0 +1,243 @@
+/* Keyboard macros.
+ Copyright (C) 1985, 1986 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#include "config.h"
+#include "lisp.h"
+#include "macros.h"
+#include "commands.h"
+#include "buffer.h"
+#include "window.h"
+
+int defining_kbd_macro;
+
+char *kbd_macro_buffer;
+char *kbd_macro_ptr;
+char *kbd_macro_end;
+int kbd_macro_bufsize;
+Lisp_Object Vlast_kbd_macro;
+
+Lisp_Object Vexecuting_macro;
+int executing_macro_index;
+
+Lisp_Object Fexecute_kbd_macro ();
+
+DEFUN ("start-kbd-macro", Fstart_kbd_macro, Sstart_kbd_macro, 1, 1, "P",
+ "Record subsequent keyboard input, defining a keyboard macro.\n\
+The commands are recorded even as they are executed.\n\
+Use \\[end-kbd-macro] to finish recording and make the macro available.\n\
+Use \\[name-last-kbd-macro] to give it a permanent name.\n\
+Non-nil arg (prefix arg) means append to last macro defined;\n\
+ This begins by re-executing that macro as if you typed it again.")
+ (append)
+ Lisp_Object append;
+{
+ if (defining_kbd_macro)
+ error ("Already defining kbd macro");
+
+ update_mode_lines++;
+ if (NULL (append))
+ {
+ kbd_macro_ptr = kbd_macro_buffer;
+ kbd_macro_end = kbd_macro_buffer;
+ message("Defining kbd macro...");
+ }
+ else
+ {
+ message("Appending to kbd macro...");
+ kbd_macro_ptr = kbd_macro_end;
+ Fexecute_kbd_macro (Vlast_kbd_macro, make_number (1));
+ }
+ defining_kbd_macro = 1;
+
+ return Qnil;
+}
+
+DEFUN ("end-kbd-macro", Fend_kbd_macro, Send_kbd_macro, 0, 1, "p",
+ "Finish defining a keyboard macro.\n\
+The definition was started by \\[start-kbd-macro].\n\
+The macro is now available for use via \\[call-last-kbd-macro],\n\
+or it can be given a name with \\[name-last-kbd-macro] and then invoked\n\
+under that name.\n\
+With numeric arg, repeat macro now that many times,\n\
+counting the definition just completed as the first repetition.")
+ (arg)
+ Lisp_Object arg;
+{
+ if (!defining_kbd_macro)
+ error ("Not defining kbd macro.");
+
+ if (NULL (arg))
+ XFASTINT (arg) = 1;
+ else
+ CHECK_NUMBER (arg, 0);
+
+ if (defining_kbd_macro)
+ {
+ defining_kbd_macro = 0;
+ update_mode_lines++;
+ Vlast_kbd_macro = make_string (kbd_macro_buffer,
+ kbd_macro_end - kbd_macro_buffer);
+ message("Keyboard macro defined");
+ }
+
+ if (XFASTINT (arg) == 0)
+ Fexecute_kbd_macro (Vlast_kbd_macro, arg);
+ else
+ {
+ XFASTINT (arg)--;
+ if (XFASTINT (arg) > 0)
+ Fexecute_kbd_macro (Vlast_kbd_macro, arg);
+ }
+ return Qnil;
+}
+
+/* Store character c into kbd macro being defined */
+
+store_kbd_macro_char (c)
+ unsigned char c;
+{
+ if (defining_kbd_macro)
+ {
+ if (kbd_macro_ptr - kbd_macro_buffer == kbd_macro_bufsize)
+ {
+ register char *new = (char *) xrealloc (kbd_macro_buffer, kbd_macro_bufsize *= 2);
+ kbd_macro_ptr += new - kbd_macro_buffer;
+ kbd_macro_end = new + kbd_macro_bufsize;
+ kbd_macro_buffer = new;
+ }
+ *kbd_macro_ptr++ = c;
+ }
+}
+
+/* Declare that all chars stored so far in the kbd macro being defined
+ really belong to it. This is done in between editor commands. */
+
+finalize_kbd_macro_chars ()
+{
+ kbd_macro_end = kbd_macro_ptr;
+}
+
+DEFUN ("call-last-kbd-macro", Fcall_last_kbd_macro, Scall_last_kbd_macro,
+ 0, 1, "p",
+ "Call the last keyboard macro that you defined with \\[start-kbd-macro].\n\
+To make a macro permanent so you can call it even after\n\
+defining others, use \\[name-last-kbd-macro].")
+ (prefix)
+ Lisp_Object prefix;
+{
+ if (defining_kbd_macro)
+ error ("Can't execute anonymous macro while defining one");
+ else if (NULL (Vlast_kbd_macro))
+ error ("No kbd macro has been defined");
+ else
+ Fexecute_kbd_macro (Vlast_kbd_macro, prefix);
+ return Qnil;
+}
+
+static Lisp_Object
+pop_kbd_macro (info)
+ Lisp_Object info;
+{
+ Lisp_Object tem;
+ Vexecuting_macro = Fcar (info);
+ tem = Fcdr (info);
+ executing_macro_index = XINT (tem);
+ return Qnil;
+}
+
+DEFUN ("execute-kbd-macro", Fexecute_kbd_macro, Sexecute_kbd_macro, 1, 2, 0,
+ "Execute MACRO as string of editor command characters.\n\
+If MACRO is a symbol, its function definition is used.\n\
+COUNT is a repeat count, or nil for once, or 0 for infinite loop.")
+ (macro, prefixarg)
+ Lisp_Object macro, prefixarg;
+{
+ Lisp_Object final;
+ Lisp_Object tem;
+ int count = specpdl_ptr - specpdl;
+ int repeat = 1;
+ struct gcpro gcpro1;
+
+ if (!NULL (prefixarg))
+ prefixarg = Fprefix_numeric_value (prefixarg),
+ repeat = XINT (prefixarg);
+
+ final = macro;
+ while (XTYPE (final) == Lisp_Symbol && !EQ (final, Qunbound))
+ final = XSYMBOL (final)->function;
+ CHECK_STRING (final, 0);
+
+ XFASTINT (tem) = executing_macro_index;
+ tem = Fcons (Vexecuting_macro, tem);
+ record_unwind_protect (pop_kbd_macro, tem);
+
+ GCPRO1 (final);
+ do
+ {
+ Vexecuting_macro = final;
+ executing_macro_index = 0;
+
+ command_loop_1 ();
+ }
+ while (--repeat && XTYPE (Vexecuting_macro) == Lisp_String);
+
+ UNGCPRO;
+ unbind_to (count);
+
+ return Qnil;
+}
+
+init_macros ()
+{
+ Vlast_kbd_macro = Qnil;
+ defining_kbd_macro = 0;
+
+ Vexecuting_macro = Qnil;
+}
+
+syms_of_macros ()
+{
+ kbd_macro_bufsize = 100;
+ kbd_macro_buffer = (char *) malloc (kbd_macro_bufsize);
+
+ defsubr (&Sstart_kbd_macro);
+ defsubr (&Send_kbd_macro);
+ defsubr (&Scall_last_kbd_macro);
+ defsubr (&Sexecute_kbd_macro);
+
+ DEFVAR_BOOL ("defining-kbd-macro", &defining_kbd_macro,
+ "Non-nil means store keyboard input into kbd macro being defined.");
+
+ DEFVAR_LISP ("executing-macro", &Vexecuting_macro,
+ "Currently executing keyboard macro (a string); nil if none executing.");
+
+ DEFVAR_LISP_NOPRO ("executing-kbd-macro", &Vexecuting_macro,
+ "Currently executing keyboard macro (a string); nil if none executing.");
+
+ DEFVAR_LISP ("last-kbd-macro", &Vlast_kbd_macro,
+ "Last kbd macro defined, as a string; nil if none defined.");
+}
+
+keys_of_macros ()
+{
+ ndefkey (Vctl_x_map, ('e'), "call-last-kbd-macro");
+ ndefkey (Vctl_x_map, ('('), "start-kbd-macro");
+ ndefkey (Vctl_x_map, (')'), "end-kbd-macro");
+}
diff --git a/src/macros.h b/src/macros.h
new file mode 100644
index 00000000000..36d66898c46
--- /dev/null
+++ b/src/macros.h
@@ -0,0 +1,31 @@
+/* Definitions for keyboard macro interpretation in GNU Emacs.
+ Copyright (C) 1985 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* Kbd macro currently being executed (a string) */
+
+extern Lisp_Object Vexecuting_macro;
+
+/* Index of next character to fetch from that macro */
+
+extern int executing_macro_index;
+
+/* Nonzero while defining a kbd macro */
+
+extern int defining_kbd_macro;
diff --git a/src/malloc.c b/src/malloc.c
new file mode 100644
index 00000000000..5f6a430cae9
--- /dev/null
+++ b/src/malloc.c
@@ -0,0 +1,856 @@
+/* dynamic memory allocation for GNU.
+ Copyright (C) 1985, 1987 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+In other words, you are welcome to use, share and improve this program.
+You are forbidden to forbid anyone else to use, share and improve
+what you give them. Help stamp out software-hoarding! */
+
+
+/*
+ * @(#)nmalloc.c 1 (Caltech) 2/21/82
+ *
+ * U of M Modified: 20 Jun 1983 ACT: strange hacks for Emacs
+ *
+ * Nov 1983, Mike@BRL, Added support for 4.1C/4.2 BSD.
+ *
+ * This is a very fast storage allocator. It allocates blocks of a small
+ * number of different sizes, and keeps free lists of each size. Blocks
+ * that don't exactly fit are passed up to the next larger size. In this
+ * implementation, the available sizes are (2^n)-4 (or -16) bytes long.
+ * This is designed for use in a program that uses vast quantities of
+ * memory, but bombs when it runs out. To make it a little better, it
+ * warns the user when he starts to get near the end.
+ *
+ * June 84, ACT: modified rcheck code to check the range given to malloc,
+ * rather than the range determined by the 2-power used.
+ *
+ * Jan 85, RMS: calls malloc_warning to issue warning on nearly full.
+ * No longer Emacs-specific; can serve as all-purpose malloc for GNU.
+ * You should call malloc_init to reinitialize after loading dumped Emacs.
+ * Call malloc_stats to get info on memory stats if MSTATS turned on.
+ * realloc knows how to return same block given, just changing its size,
+ * if the power of 2 is correct.
+ */
+
+/*
+ * nextf[i] is the pointer to the next free block of size 2^(i+3). The
+ * smallest allocatable block is 8 bytes. The overhead information will
+ * go in the first int of the block, and the returned pointer will point
+ * to the second.
+ *
+#ifdef MSTATS
+ * nmalloc[i] is the difference between the number of mallocs and frees
+ * for a given block size.
+#endif MSTATS
+ */
+
+#ifdef emacs
+/* config.h specifies which kind of system this is. */
+#include "config.h"
+
+/* This must precede sys/signal.h on certain machines. */
+#include <sys/types.h>
+#include <signal.h>
+#else
+
+/* Determine which kind of system this is. */
+/* This must precede sys/signal.h on certain machines. */
+#include <sys/types.h>
+#include <signal.h>
+#ifndef SIGTSTP
+#ifndef VMS
+#ifndef USG
+#define USG
+#endif
+#endif /* not VMS */
+#else /* SIGTSTP */
+#ifdef SIGIO
+#define BSD4_2
+#endif /* SIGIO */
+#endif /* SIGTSTP */
+
+#endif /* not emacs */
+
+/* Define getpagesize () if the system does not. */
+#include "getpagesize.h"
+
+#ifdef BSD
+#ifdef BSD4_1
+#include <sys/vlimit.h> /* warn the user when near the end */
+#else /* if 4.2 or newer */
+#include <sys/time.h>
+#include <sys/resource.h>
+#endif /* if 4.2 or newer */
+#endif
+
+#ifdef VMS
+#include "vlimit.h"
+#endif
+
+extern char *start_of_data ();
+
+#ifdef BSD
+#ifndef DATA_SEG_BITS
+#define start_of_data() &etext
+#endif
+#endif
+
+#ifndef emacs
+#define start_of_data() &etext
+#endif
+
+#define ISALLOC ((char) 0xf7) /* magic byte that implies allocation */
+#define ISFREE ((char) 0x54) /* magic byte that implies free block */
+ /* this is for error checking only */
+#define ISMEMALIGN ((char) 0xd6) /* Stored before the value returned by
+ memalign, with the rest of the word
+ being the distance to the true
+ beginning of the block. */
+
+extern char etext;
+
+/* These two are for user programs to look at, when they are interested. */
+
+unsigned int malloc_sbrk_used; /* amount of data space used now */
+unsigned int malloc_sbrk_unused; /* amount more we can have */
+
+/* start of data space; can be changed by calling init_malloc */
+static char *data_space_start;
+
+#ifdef MSTATS
+static int nmalloc[30];
+static int nmal, nfre;
+#endif /* MSTATS */
+
+/* If range checking is not turned on, all we have is a flag indicating
+ whether memory is allocated, an index in nextf[], and a size field; to
+ realloc() memory we copy either size bytes or 1<<(index+3) bytes depending
+ on whether the former can hold the exact size (given the value of
+ 'index'). If range checking is on, we always need to know how much space
+ is allocated, so the 'size' field is never used. */
+
+struct mhead {
+ char mh_alloc; /* ISALLOC or ISFREE */
+ char mh_index; /* index in nextf[] */
+/* Remainder are valid only when block is allocated */
+ unsigned short mh_size; /* size, if < 0x10000 */
+#ifdef rcheck
+ unsigned mh_nbytes; /* number of bytes allocated */
+ int mh_magic4; /* should be == MAGIC4 */
+#endif /* rcheck */
+};
+
+/* Access free-list pointer of a block.
+ It is stored at block + 4.
+ This is not a field in the mhead structure
+ because we want sizeof (struct mhead)
+ to describe the overhead for when the block is in use,
+ and we do not want the free-list pointer to count in that. */
+
+#define CHAIN(a) \
+ (*(struct mhead **) (sizeof (char *) + (char *) (a)))
+
+#ifdef rcheck
+
+/* To implement range checking, we write magic values in at the beginning and
+ end of each allocated block, and make sure they are undisturbed whenever a
+ free or a realloc occurs. */
+/* Written in each of the 4 bytes following the block's real space */
+#define MAGIC1 0x55
+/* Written in the 4 bytes before the block's real space */
+#define MAGIC4 0x55555555
+#define ASSERT(p) if (!(p)) botch("p"); else
+#define EXTRA 4 /* 4 bytes extra for MAGIC1s */
+#else
+#define ASSERT(p) if (!(p)) abort (); else
+#define EXTRA 0
+#endif /* rcheck */
+
+
+/* nextf[i] is free list of blocks of size 2**(i + 3) */
+
+static struct mhead *nextf[30];
+
+/* busy[i] is nonzero while allocation of block size i is in progress. */
+
+static char busy[30];
+
+/* Number of bytes of writable memory we can expect to be able to get */
+static unsigned int lim_data;
+
+/* Level number of warnings already issued.
+ 0 -- no warnings issued.
+ 1 -- 75% warning already issued.
+ 2 -- 85% warning already issued.
+*/
+static int warnlevel;
+
+/* Function to call to issue a warning;
+ 0 means don't issue them. */
+static void (*warnfunction) ();
+
+/* nonzero once initial bunch of free blocks made */
+static int gotpool;
+
+char *_malloc_base;
+
+static void getpool ();
+
+char *malloc ();
+
+/* Cause reinitialization based on job parameters;
+ also declare where the end of pure storage is. */
+void
+malloc_init (start, warnfun)
+ char *start;
+ void (*warnfun) ();
+{
+ if (start)
+ data_space_start = start;
+ lim_data = 0;
+ warnlevel = 0;
+ warnfunction = warnfun;
+}
+
+/* Return the maximum size to which MEM can be realloc'd
+ without actually requiring copying. */
+
+int
+malloc_usable_size (mem)
+ char *mem;
+{
+ struct mhead *p
+ = (struct mhead *) (mem - ((sizeof (struct mhead) + 7) & ~7));
+ int blocksize = 8 << p->mh_index;
+
+ return blocksize - sizeof (struct mhead) - EXTRA;
+}
+
+static void
+morecore (nu) /* ask system for more memory */
+ register int nu; /* size index to get more of */
+{
+ char *sbrk ();
+ register char *cp;
+ register int nblks;
+ register unsigned int siz;
+ int oldmask;
+
+#ifdef BSD
+#ifndef BSD4_1
+ int newmask = -1;
+ /* Blocking these signals interferes with debugging, at least on BSD on
+ the HP 9000/300. */
+#ifdef SIGTRAP
+ newmask &= ~(1 << SIGTRAP);
+#endif
+#ifdef SIGILL
+ newmask &= ~(1 << SIGILL);
+#endif
+#ifdef SIGTSTP
+ newmask &= ~(1 << SIGTSTP);
+#endif
+#ifdef SIGSTOP
+ newmask &= ~(1 << SIGSTOP);
+#endif
+ oldmask = sigsetmask (newmask);
+#endif
+#endif
+
+ if (!data_space_start)
+ {
+ data_space_start = start_of_data ();
+ }
+
+ if (lim_data == 0)
+ get_lim_data ();
+
+ /* On initial startup, get two blocks of each size up to 1k bytes */
+ if (!gotpool)
+ { getpool (); getpool (); gotpool = 1; }
+
+ /* Find current end of memory and issue warning if getting near max */
+
+#ifndef VMS
+ /* Maximum virtual memory on VMS is difficult to calculate since it
+ * depends on several dynmacially changing things. Also, alignment
+ * isn't that important. That is why much of the code here is ifdef'ed
+ * out for VMS systems.
+ */
+ cp = sbrk (0);
+ siz = cp - data_space_start;
+
+ if (warnfunction)
+ switch (warnlevel)
+ {
+ case 0:
+ if (siz > (lim_data / 4) * 3)
+ {
+ warnlevel++;
+ (*warnfunction) ("Warning: past 75% of memory limit");
+ }
+ break;
+ case 1:
+ if (siz > (lim_data / 20) * 17)
+ {
+ warnlevel++;
+ (*warnfunction) ("Warning: past 85% of memory limit");
+ }
+ break;
+ case 2:
+ if (siz > (lim_data / 20) * 19)
+ {
+ warnlevel++;
+ (*warnfunction) ("Warning: past 95% of memory limit");
+ }
+ break;
+ }
+
+ if ((int) cp & 0x3ff) /* land on 1K boundaries */
+ sbrk (1024 - ((int) cp & 0x3ff));
+#endif /* not VMS */
+
+ /* Take at least 2k, and figure out how many blocks of the desired size
+ we're about to get */
+ nblks = 1;
+ if ((siz = nu) < 8)
+ nblks = 1 << ((siz = 8) - nu);
+
+ if ((cp = sbrk (1 << (siz + 3))) == (char *) -1)
+ {
+#ifdef BSD
+#ifndef BSD4_1
+ sigsetmask (oldmask);
+#endif
+#endif
+ return; /* no more room! */
+ }
+ malloc_sbrk_used = siz;
+ malloc_sbrk_unused = lim_data - siz;
+
+#ifndef VMS
+ if ((int) cp & 7)
+ { /* shouldn't happen, but just in case */
+ cp = (char *) (((int) cp + 8) & ~7);
+ nblks--;
+ }
+#endif /* not VMS */
+
+ /* save new header and link the nblks blocks together */
+ nextf[nu] = (struct mhead *) cp;
+ siz = 1 << (nu + 3);
+ while (1)
+ {
+ ((struct mhead *) cp) -> mh_alloc = ISFREE;
+ ((struct mhead *) cp) -> mh_index = nu;
+ if (--nblks <= 0) break;
+ CHAIN ((struct mhead *) cp) = (struct mhead *) (cp + siz);
+ cp += siz;
+ }
+ CHAIN ((struct mhead *) cp) = 0;
+
+#ifdef BSD
+#ifndef BSD4_1
+ sigsetmask (oldmask);
+#endif
+#endif
+}
+
+static void
+getpool ()
+{
+ register int nu;
+ char * sbrk ();
+ register char *cp = sbrk (0);
+
+ if ((int) cp & 0x3ff) /* land on 1K boundaries */
+ sbrk (1024 - ((int) cp & 0x3ff));
+
+ /* Record address of start of space allocated by malloc. */
+ if (_malloc_base == 0)
+ _malloc_base = cp;
+
+ /* Get 2k of storage */
+
+ cp = sbrk (04000);
+ if (cp == (char *) -1)
+ return;
+
+ /* Divide it into an initial 8-word block
+ plus one block of size 2**nu for nu = 3 ... 10. */
+
+ CHAIN (cp) = nextf[0];
+ nextf[0] = (struct mhead *) cp;
+ ((struct mhead *) cp) -> mh_alloc = ISFREE;
+ ((struct mhead *) cp) -> mh_index = 0;
+ cp += 8;
+
+ for (nu = 0; nu < 7; nu++)
+ {
+ CHAIN (cp) = nextf[nu];
+ nextf[nu] = (struct mhead *) cp;
+ ((struct mhead *) cp) -> mh_alloc = ISFREE;
+ ((struct mhead *) cp) -> mh_index = nu;
+ cp += 8 << nu;
+ }
+}
+
+char *
+malloc (n) /* get a block */
+ unsigned n;
+{
+ register struct mhead *p;
+ register unsigned int nbytes;
+ register int nunits = 0;
+
+ /* Figure out how many bytes are required, rounding up to the nearest
+ multiple of 8, then figure out which nestf[] area to use.
+ Both the beginning of the header and the beginning of the
+ block should be on an eight byte boundary. */
+#ifdef SUNOS_LOCALTIME_BUG
+ if (n < 16)
+ n = 16;
+#endif
+ nbytes = (n + ((sizeof *p + 7) & ~7) + EXTRA + 7) & ~7;
+ {
+ register unsigned int shiftr = (nbytes - 1) >> 2;
+
+ while (shiftr >>= 1)
+ nunits++;
+ }
+
+ /* In case this is reentrant use of malloc from signal handler,
+ pick a block size that no other malloc level is currently
+ trying to allocate. That's the easiest harmless way not to
+ interfere with the other level of execution. */
+ while (busy[nunits]) nunits++;
+ busy[nunits] = 1;
+
+ /* If there are no blocks of the appropriate size, go get some */
+ /* COULD SPLIT UP A LARGER BLOCK HERE ... ACT */
+ if (nextf[nunits] == 0)
+ morecore (nunits);
+
+ /* Get one block off the list, and set the new list head */
+ if ((p = nextf[nunits]) == 0)
+ {
+ busy[nunits] = 0;
+ return 0;
+ }
+ nextf[nunits] = CHAIN (p);
+ busy[nunits] = 0;
+
+ /* Check for free block clobbered */
+ /* If not for this check, we would gobble a clobbered free chain ptr */
+ /* and bomb out on the NEXT allocate of this size block */
+ if (p -> mh_alloc != ISFREE || p -> mh_index != nunits)
+#ifdef rcheck
+ botch ("block on free list clobbered");
+#else /* not rcheck */
+ abort ();
+#endif /* not rcheck */
+
+ /* Fill in the info, and if range checking, set up the magic numbers */
+ p -> mh_alloc = ISALLOC;
+#ifdef rcheck
+ p -> mh_nbytes = n;
+ p -> mh_magic4 = MAGIC4;
+ {
+ /* Get the location n after the beginning of the user's space. */
+ register char *m = (char *) p + ((sizeof *p + 7) & ~7) + n;
+
+ *m++ = MAGIC1, *m++ = MAGIC1, *m++ = MAGIC1, *m = MAGIC1;
+ }
+#else /* not rcheck */
+ p -> mh_size = n;
+#endif /* not rcheck */
+#ifdef MSTATS
+ nmalloc[nunits]++;
+ nmal++;
+#endif /* MSTATS */
+ return (char *) p + ((sizeof *p + 7) & ~7);
+}
+
+free (mem)
+ char *mem;
+{
+ register struct mhead *p;
+ {
+ register char *ap = mem;
+
+ if (ap == 0)
+ return;
+
+ p = (struct mhead *) (ap - ((sizeof *p + 7) & ~7));
+ if (p -> mh_alloc == ISMEMALIGN)
+ {
+ ap -= p->mh_size;
+ p = (struct mhead *) (ap - ((sizeof *p + 7) & ~7));
+ }
+
+#ifndef rcheck
+ if (p -> mh_alloc != ISALLOC)
+ abort ();
+
+#else rcheck
+ if (p -> mh_alloc != ISALLOC)
+ {
+ if (p -> mh_alloc == ISFREE)
+ botch ("free: Called with already freed block argument\n");
+ else
+ botch ("free: Called with bad argument\n");
+ }
+
+ ASSERT (p -> mh_magic4 == MAGIC4);
+ ap += p -> mh_nbytes;
+ ASSERT (*ap++ == MAGIC1); ASSERT (*ap++ == MAGIC1);
+ ASSERT (*ap++ == MAGIC1); ASSERT (*ap == MAGIC1);
+#endif /* rcheck */
+ }
+ {
+ register int nunits = p -> mh_index;
+
+ ASSERT (nunits <= 29);
+ p -> mh_alloc = ISFREE;
+
+ /* Protect against signal handlers calling malloc. */
+ busy[nunits] = 1;
+ /* Put this block on the free list. */
+ CHAIN (p) = nextf[nunits];
+ nextf[nunits] = p;
+ busy[nunits] = 0;
+
+#ifdef MSTATS
+ nmalloc[nunits]--;
+ nfre++;
+#endif /* MSTATS */
+ }
+}
+
+char *
+realloc (mem, n)
+ char *mem;
+ register unsigned n;
+{
+ register struct mhead *p;
+ register unsigned int tocopy;
+ register unsigned int nbytes;
+ register int nunits;
+
+ if (mem == 0)
+ return malloc (n);
+ p = (struct mhead *) (mem - ((sizeof *p + 7) & ~7));
+ nunits = p -> mh_index;
+ ASSERT (p -> mh_alloc == ISALLOC);
+#ifdef rcheck
+ ASSERT (p -> mh_magic4 == MAGIC4);
+ {
+ register char *m = mem + (tocopy = p -> mh_nbytes);
+ ASSERT (*m++ == MAGIC1); ASSERT (*m++ == MAGIC1);
+ ASSERT (*m++ == MAGIC1); ASSERT (*m == MAGIC1);
+ }
+#else /* not rcheck */
+ if (p -> mh_index >= 13)
+ tocopy = (1 << (p -> mh_index + 3)) - ((sizeof *p + 7) & ~7);
+ else
+ tocopy = p -> mh_size;
+#endif /* not rcheck */
+
+ /* See if desired size rounds to same power of 2 as actual size. */
+ nbytes = (n + ((sizeof *p + 7) & ~7) + EXTRA + 7) & ~7;
+
+ /* If ok, use the same block, just marking its size as changed. */
+ if (nbytes > (4 << nunits) && nbytes <= (8 << nunits))
+ {
+#ifdef rcheck
+ register char *m = mem + tocopy;
+ *m++ = 0; *m++ = 0; *m++ = 0; *m++ = 0;
+ p-> mh_nbytes = n;
+ m = mem + n;
+ *m++ = MAGIC1; *m++ = MAGIC1; *m++ = MAGIC1; *m++ = MAGIC1;
+#else /* not rcheck */
+ p -> mh_size = n;
+#endif /* not rcheck */
+ return mem;
+ }
+
+ if (n < tocopy)
+ tocopy = n;
+ {
+ register char *new;
+
+ if ((new = malloc (n)) == 0)
+ return 0;
+ bcopy (mem, new, tocopy);
+ free (mem);
+ return new;
+ }
+}
+
+/* This is in case something linked with Emacs calls calloc. */
+
+char *
+calloc (num, size)
+ unsigned num, size;
+{
+ register char *mem;
+
+ num *= size;
+ mem = malloc (num);
+ if (mem != 0)
+ bzero (mem, num);
+ return mem;
+}
+
+/* This is in case something linked with Emacs calls cfree. */
+
+cfree (mem)
+ char *mem;
+{
+ return free (mem);
+}
+
+#ifndef VMS
+
+char *
+memalign (alignment, size)
+ unsigned alignment, size;
+{
+ register char *ptr = malloc (size + alignment);
+ register char *aligned;
+ register struct mhead *p;
+
+ if (ptr == 0)
+ return 0;
+ /* If entire block has the desired alignment, just accept it. */
+ if (((int) ptr & (alignment - 1)) == 0)
+ return ptr;
+ /* Otherwise, get address of byte in the block that has that alignment. */
+ aligned = (char *) (((int) ptr + alignment - 1) & -alignment);
+
+ /* Store a suitable indication of how to free the block,
+ so that free can find the true beginning of it. */
+ p = (struct mhead *) (aligned - ((7 + sizeof (struct mhead)) & ~7));
+ p -> mh_size = aligned - ptr;
+ p -> mh_alloc = ISMEMALIGN;
+ return aligned;
+}
+
+#ifndef HPUX
+/* This runs into trouble with getpagesize on HPUX.
+ Patching out seems cleaner than the ugly fix needed. */
+char *
+valloc (size)
+{
+ return memalign (getpagesize (), size);
+}
+#endif /* not HPUX */
+#endif /* not VMS */
+
+#ifdef MSTATS
+/* Return statistics describing allocation of blocks of size 2**n. */
+
+struct mstats_value
+ {
+ int blocksize;
+ int nfree;
+ int nused;
+ };
+
+struct mstats_value
+malloc_stats (size)
+ int size;
+{
+ struct mstats_value v;
+ register int i;
+ register struct mhead *p;
+
+ v.nfree = 0;
+
+ if (size < 0 || size >= 30)
+ {
+ v.blocksize = 0;
+ v.nused = 0;
+ return v;
+ }
+
+ v.blocksize = 1 << (size + 3);
+ v.nused = nmalloc[size];
+
+ for (p = nextf[size]; p; p = CHAIN (p))
+ v.nfree++;
+
+ return v;
+}
+int
+malloc_mem_used ()
+{
+ int i;
+ int size_used;
+
+ size_used = 0;
+
+ for (i = 0; i < 30; i++)
+ {
+ int allocation_size = 1 << (i + 3);
+ struct mhead *p;
+
+ size_used += nmalloc[i] * allocation_size;
+ }
+
+ return size_used;
+}
+
+int
+malloc_mem_free ()
+{
+ int i;
+ int size_unused;
+
+ size_unused = 0;
+
+ for (i = 0; i < 30; i++)
+ {
+ int allocation_size = 1 << (i + 3);
+ struct mhead *p;
+
+ for (p = nextf[i]; p ; p = CHAIN (p))
+ size_unused += allocation_size;
+ }
+
+ return size_unused;
+}
+#endif /* MSTATS */
+
+/*
+ * This function returns the total number of bytes that the process
+ * will be allowed to allocate via the sbrk(2) system call. On
+ * BSD systems this is the total space allocatable to stack and
+ * data. On USG systems this is the data space only.
+ */
+
+#ifdef USG
+
+get_lim_data ()
+{
+ extern long ulimit ();
+
+#ifdef ULIMIT_BREAK_VALUE
+ lim_data = ULIMIT_BREAK_VALUE;
+#else
+ lim_data = ulimit (3, 0);
+#endif
+
+ lim_data -= (long) data_space_start;
+}
+
+#else /* not USG */
+#if defined (BSD4_1) || defined (VMS)
+
+get_lim_data ()
+{
+ lim_data = vlimit (LIM_DATA, -1);
+}
+
+#else /* not BSD4_1 and not VMS */
+
+get_lim_data ()
+{
+ struct rlimit XXrlimit;
+
+ getrlimit (RLIMIT_DATA, &XXrlimit);
+#ifdef RLIM_INFINITY
+ lim_data = XXrlimit.rlim_cur & RLIM_INFINITY; /* soft limit */
+#else
+ lim_data = XXrlimit.rlim_cur; /* soft limit */
+#endif
+}
+
+#endif /* not BSD4_1 and not VMS */
+#endif /* not USG */
+
+#ifdef VMS
+/* There is a problem when dumping and restoring things on VMS. Calls
+ * to SBRK don't necessarily result in contiguous allocation. Dumping
+ * doesn't work when it isn't. Therefore, we make the initial
+ * allocation contiguous by allocating a big chunk, and do SBRKs from
+ * there. Once Emacs has dumped there is no reason to continue
+ * contiguous allocation, malloc doesn't depend on it.
+ *
+ * There is a further problem of using brk and sbrk while using VMS C
+ * run time library routines malloc, calloc, etc. The documentation
+ * says that this is a no-no, although I'm not sure why this would be
+ * a problem. In any case, we remove the necessity to call brk and
+ * sbrk, by calling calloc (to assure zero filled data) rather than
+ * sbrk.
+ *
+ * VMS_ALLOCATION_SIZE is the size of the allocation array. This
+ * should be larger than the malloc size before dumping. Making this
+ * too large will result in the startup procedure slowing down since
+ * it will require more space and time to map it in.
+ *
+ * The value for VMS_ALLOCATION_SIZE in the following define was determined
+ * by running emacs linked (and a large allocation) with the debugger and
+ * looking to see how much storage was used. The allocation was 201 pages,
+ * so I rounded it up to a power of two.
+ */
+#ifndef VMS_ALLOCATION_SIZE
+#define VMS_ALLOCATION_SIZE (512*256)
+#endif
+
+/* Use VMS RTL definitions */
+#undef sbrk
+#undef brk
+#undef malloc
+int vms_out_initial = 0;
+char vms_initial_buffer[VMS_ALLOCATION_SIZE];
+static char *vms_current_brk = vms_initial_buffer;
+static char *vms_end_brk = &vms_initial_buffer[VMS_ALLOCATION_SIZE-1];
+
+#include <stdio.h>
+
+char *
+sys_sbrk (incr)
+ int incr;
+{
+ char *sbrk(), *temp, *ptr;
+
+ if (vms_out_initial)
+ {
+ /* out of initial allocation... */
+ if (!(temp = (char*) malloc (incr)))
+ temp = (char *) -1;
+ }
+ else
+ {
+ /* otherwise, go out of our area */
+ ptr = vms_current_brk + incr; /* new current_brk */
+ if (ptr <= vms_end_brk)
+ {
+ temp = vms_current_brk;
+ vms_current_brk = ptr;
+ }
+ else
+ {
+ vms_out_initial = 1; /* mark as out of initial allocation */
+ if (!(temp = (char*) malloc (incr)))
+ temp = (char *) -1;
+ }
+ }
+ return temp;
+}
+#endif /* VMS */
diff --git a/src/marker.c b/src/marker.c
index d8c0a89819a..7174b19b4da 100644
--- a/src/marker.c
+++ b/src/marker.c
@@ -87,10 +87,11 @@ Returns MARKER.")
CHECK_MARKER (marker, 0);
/* If position is nil or a marker that points nowhere,
make this marker point nowhere. */
- if (NULL (pos)
- || (XTYPE (pos) == Lisp_Marker && !XMARKER (pos)->buffer))
+ if (NULL (pos) ||
+ (XTYPE (pos) == Lisp_Marker && !XMARKER (pos)->buffer))
{
- unchain_marker (marker);
+ if (XMARKER (marker)->buffer)
+ unchain_marker (marker);
return marker;
}
@@ -104,7 +105,8 @@ Returns MARKER.")
/* If buffer is dead, set marker to point nowhere. */
if (EQ (b->name, Qnil))
{
- unchain_marker (marker);
+ if (XMARKER (marker)->buffer)
+ unchain_marker (marker);
return marker;
}
}
@@ -121,7 +123,8 @@ Returns MARKER.")
if (m->buffer != b)
{
- unchain_marker (marker);
+ if (m->buffer != 0)
+ unchain_marker (marker);
m->chain = b->markers;
b->markers = marker;
m->buffer = b;
@@ -130,9 +133,7 @@ Returns MARKER.")
return marker;
}
-/* This version of Fset_marker won't let the position
- be outside the visible part. */
-
+/* This version of Fset_marker won't let the position be outside the visible part. */
Lisp_Object
set_marker_restricted (marker, pos, buffer)
Lisp_Object marker, pos, buffer;
@@ -147,7 +148,8 @@ set_marker_restricted (marker, pos, buffer)
if (NULL (pos) ||
(XTYPE (pos) == Lisp_Marker && !XMARKER (pos)->buffer))
{
- unchain_marker (marker);
+ if (XMARKER (marker)->buffer)
+ unchain_marker (marker);
return marker;
}
@@ -161,7 +163,8 @@ set_marker_restricted (marker, pos, buffer)
/* If buffer is dead, set marker to point nowhere. */
if (EQ (b->name, Qnil))
{
- unchain_marker (marker);
+ if (XMARKER (marker)->buffer)
+ unchain_marker (marker);
return marker;
}
}
@@ -179,7 +182,8 @@ set_marker_restricted (marker, pos, buffer)
if (m->buffer != b)
{
- unchain_marker (marker);
+ if (m->buffer != 0)
+ unchain_marker (marker);
m->chain = b->markers;
b->markers = marker;
m->buffer = b;
@@ -189,8 +193,8 @@ set_marker_restricted (marker, pos, buffer)
}
/* This is called during garbage collection,
- so we must be careful to ignore and preserve mark bits,
- including those in chain fields of markers. */
+ so we must be careful to ignore and preserve mark bits,
+ including those in chain fields of markers. */
unchain_marker (marker)
register Lisp_Object marker;
@@ -200,8 +204,6 @@ unchain_marker (marker)
register struct buffer *b;
b = XMARKER (marker)->buffer;
- if (b == 0)
- return;
if (EQ (b->name, Qnil))
abort ();
@@ -271,8 +273,8 @@ at that position in the current buffer.")
while (1)
{
- if (XTYPE (marker) == Lisp_Int
- || XTYPE (marker) == Lisp_Marker)
+ if (XTYPE (marker) == Lisp_Int ||
+ XTYPE (marker) == Lisp_Marker)
{
new = Fmake_marker ();
Fset_marker (new, marker,
diff --git a/src/minibuf.c b/src/minibuf.c
new file mode 100644
index 00000000000..83bf6522b1f
--- /dev/null
+++ b/src/minibuf.c
@@ -0,0 +1,1181 @@
+/* Minibuffer input and completion.
+ Copyright (C) 1985, 1986, 1990 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#include "config.h"
+#include "lisp.h"
+#include "commands.h"
+#include "buffer.h"
+#include "window.h"
+#include "syntax.h"
+#include "dispextern.h"
+
+#define min(a, b) ((a) < (b) ? (a) : (b))
+
+/* List of buffers for use as minibuffers.
+ The first element of the list is used for the outermost minibuffer invocation,
+ the next element is used for a recursive minibuffer invocation, etc.
+ The list is extended at the end as deeped minibuffer recursions are encountered. */
+Lisp_Object Vminibuffer_list;
+
+struct minibuf_save_data
+ {
+ char *prompt;
+ int prompt_width;
+ Lisp_Object help_form;
+ Lisp_Object current_prefix_arg;
+ };
+
+int minibuf_save_vector_size;
+struct minibuf_save_data *minibuf_save_vector;
+
+/* Depth in minibuffer invocations. */
+int minibuf_level;
+
+/* Nonzero means display completion help for invalid input. */
+int completion_auto_help;
+
+/* Fread_minibuffer leaves the input, as a string, here. */
+Lisp_Object last_minibuf_string;
+
+/* Nonzero means let functions called when within a minibuffer
+ invoke recursive minibuffers (to read arguments, or whatever). */
+int enable_recursive_minibuffers;
+
+/* help-form is bound to this while in the minibuffer. */
+Lisp_Object Vminibuffer_help_form;
+
+/* Nonzero means completion ignores case. */
+int completion_ignore_case;
+
+Lisp_Object Quser_variable_p;
+
+/* Width in columns of current minibuffer prompt. */
+extern int minibuf_prompt_width;
+
+/* Actual minibuffer invocation. */
+
+void read_minibuf_unwind ();
+Lisp_Object get_minibuffer ();
+Lisp_Object read_minibuf ();
+
+Lisp_Object
+read_minibuf (map, initial, prompt, expflag)
+ Lisp_Object map;
+ Lisp_Object initial;
+ Lisp_Object prompt;
+ int expflag;
+{
+ register Lisp_Object val;
+ int count = specpdl_ptr - specpdl;
+ struct gcpro gcpro1, gcpro2;
+
+ if (XTYPE (prompt) != Lisp_String)
+ prompt = build_string ("");
+
+ /* Emacs in -batch mode calls minibuffer: print the prompt. */
+ if (noninteractive)
+ printf ("%s", XSTRING (prompt)->data);
+
+ if (!enable_recursive_minibuffers &&
+ (EQ (selected_window, minibuf_window)))
+ error ("Command attempted to use minibuffer while in minibuffer");
+
+ if (minibuf_level == minibuf_save_vector_size)
+ minibuf_save_vector =
+ (struct minibuf_save_data *) xrealloc (minibuf_save_vector,
+ (minibuf_save_vector_size *= 2) * sizeof (struct minibuf_save_data));
+ minibuf_save_vector[minibuf_level].prompt = minibuf_prompt;
+ minibuf_save_vector[minibuf_level].prompt_width = minibuf_prompt_width;
+ minibuf_prompt_width = 0;
+ /* >> Why is this done this way rather than binding these variables? */
+ minibuf_save_vector[minibuf_level].help_form = Vhelp_form;
+ minibuf_save_vector[minibuf_level].current_prefix_arg = Vcurrent_prefix_arg;
+ GCPRO2 (minibuf_save_vector[minibuf_level].help_form,
+ minibuf_save_vector[minibuf_level].current_prefix_arg);
+
+
+ record_unwind_protect (Fset_window_configuration,
+ Fcurrent_window_configuration ());
+
+ val = current_buffer->directory;
+ Fset_buffer (get_minibuffer (minibuf_level));
+ current_buffer->directory = val;
+
+ Fset_window_buffer (minibuf_window, Fcurrent_buffer ());
+ Fselect_window (minibuf_window);
+ XFASTINT (XWINDOW (minibuf_window)->hscroll) = 0;
+
+ Ferase_buffer ();
+ minibuf_level++;
+ record_unwind_protect (read_minibuf_unwind, Qnil);
+ Vminibuf_scroll_window = Qnil;
+
+ if (!NULL (initial))
+ Finsert (1, &initial);
+
+ minibuf_prompt = (char *) alloca (XSTRING (prompt)->size + 1);
+ bcopy (XSTRING (prompt)->data, minibuf_prompt, XSTRING (prompt)->size + 1);
+ echo_area_contents = 0;
+
+ Vhelp_form = Vminibuffer_help_form;
+ current_buffer->keymap = map;
+ recursive_edit_1 ();
+
+ /* If cursor is on the minibuffer line,
+ show the user we have exited by putting it in column 0. */
+ if (cursor_vpos >= XFASTINT (XWINDOW (minibuf_window)->top)
+ && !noninteractive)
+ {
+ cursor_hpos = 0;
+ update_screen (1, 1);
+ }
+
+ /* Make minibuffer contents into a string */
+ val = make_string (BEG_ADDR, Z - BEG);
+ bcopy (GAP_END_ADDR, XSTRING (val)->data + GPT - BEG, Z - GPT);
+ unbind_to (count);
+ UNGCPRO;
+
+ /* VAL is the string of minibuffer text. */
+
+ last_minibuf_string = val;
+
+ /* If Lisp form desired instead of string, parse it */
+ if (expflag)
+ val = Fread (val);
+
+ return val;
+}
+
+/* Return a buffer to be used as the minibuffer at depth `depth'.
+ depth = 0 is the lowest allowed argument, and that is the value
+ used for nonrecursive minibuffer invocations */
+
+Lisp_Object
+get_minibuffer (depth)
+ int depth;
+{
+ Lisp_Object tail, num, buf;
+ char name[14];
+ extern Lisp_Object nconc2 ();
+
+ XFASTINT (num) = depth;
+ tail = Fnthcdr (num, Vminibuffer_list);
+ if (NULL (tail))
+ {
+ tail = Fcons (Qnil, Qnil);
+ Vminibuffer_list = nconc2 (Vminibuffer_list, tail);
+ }
+ buf = Fcar (tail);
+ if (NULL (buf) || NULL (XBUFFER (buf)->name))
+ {
+ sprintf (name, " *Minibuf-%d*", depth);
+ buf = Fget_buffer_create (build_string (name));
+ XCONS (tail)->car = buf;
+ }
+ else
+ reset_buffer (XBUFFER (buf));
+ return buf;
+}
+
+/* This function is called on exiting minibuffer, whether normally or not,
+ and it restores the current window, buffer, etc. */
+
+void
+read_minibuf_unwind ()
+{
+ /* Erase the minibuffer we were using at this level. */
+ Fset_buffer (XWINDOW (minibuf_window)->buffer);
+ /* Prevent error if user has done something strange. */
+ current_buffer->read_only = Qnil;
+ Ferase_buffer ();
+
+ /* If this was a recursive minibuffer,
+ tie the minibuffer window back to the outer level minibuffer buffer */
+ minibuf_level--;
+ /* Make sure minibuffer window is erased, not ignored */
+ windows_or_buffers_changed++;
+ XFASTINT (XWINDOW (minibuf_window)->last_modified) = 0;
+
+ /* Restore prompt from outer minibuffer */
+ minibuf_prompt = minibuf_save_vector[minibuf_level].prompt;
+ minibuf_prompt_width = minibuf_save_vector[minibuf_level].prompt_width;
+ Vhelp_form = minibuf_save_vector[minibuf_level].help_form;
+ Vcurrent_prefix_arg = minibuf_save_vector[minibuf_level].current_prefix_arg;
+}
+
+DEFUN ("read-from-minibuffer", Fread_from_minibuffer, Sread_from_minibuffer, 1, 4, 0,
+ "Read a string from the minibuffer, prompting with string PROMPT.\n\
+If optional second arg INITIAL-CONTENTS is non-nil, it is a string\n\
+ to be inserted into the minibuffer before reading input.\n\
+Third arg KEYMAP is a keymap to use whilst reading; the default is\n\
+ minibuffer-local-map.\n\
+If fourth arg READ is non-nil, then interpret the result as a lisp object\n\
+ and return that object (ie (car (read-from-string <input-string>)))")
+ (prompt, initial_input, keymap, read)
+ Lisp_Object prompt, initial_input, keymap, read;
+{
+ CHECK_STRING (prompt, 0);
+ if (!NULL (initial_input))
+ CHECK_STRING (initial_input, 1);
+ if (NULL (keymap))
+ keymap = Vminibuffer_local_map;
+ else
+ keymap = get_keymap (keymap,2);
+ return read_minibuf (keymap, initial_input, prompt, !NULL(read));
+}
+
+DEFUN ("read-minibuffer", Fread_minibuffer, Sread_minibuffer, 1, 2, 0,
+ "Return a Lisp object read using the minibuffer.\n\
+Prompt with PROMPT. If non-nil, optional second arg INITIAL-CONTENTS\n\
+is a string to insert in the minibuffer before reading.")
+ (prompt, initial_contents)
+ Lisp_Object prompt, initial_contents;
+{
+ CHECK_STRING (prompt, 0);
+ if (!NULL (initial_contents))
+ CHECK_STRING (initial_contents, 1)
+ return read_minibuf (Vminibuffer_local_map, initial_contents, prompt, 1);
+}
+
+DEFUN ("eval-minibuffer", Feval_minibuffer, Seval_minibuffer, 1, 2, 0,
+ "Return value of Lisp expression read using the minibuffer.\n\
+Prompt with PROMPT. If non-nil, optional second arg INITIAL-CONTENTS\n\
+is a string to insert in the minibuffer before reading.")
+ (prompt, initial_contents)
+ Lisp_Object prompt, initial_contents;
+{
+ return Feval (Fread_minibuffer (prompt, initial_contents));
+}
+
+/* Functions that use the minibuffer to read various things. */
+
+DEFUN ("read-string", Fread_string, Sread_string, 1, 2, 0,
+ "Read a string from the minibuffer, prompting with string PROMPT.\n\
+If non-nil second arg INITIAL-INPUT is a string to insert before reading.")
+ (prompt, initial_input)
+ Lisp_Object prompt, initial_input;
+{
+ return Fread_from_minibuffer (prompt, initial_input, Qnil, Qnil);
+}
+
+DEFUN ("read-no-blanks-input", Fread_no_blanks_input, Sread_no_blanks_input, 2, 2, 0,
+ "Args PROMPT and INIT, strings. Read a string from the terminal, not allowing blanks.\n\
+Prompt with PROMPT, and provide INIT as an initial value of the input string.")
+ (prompt, init)
+ Lisp_Object prompt, init;
+{
+ CHECK_STRING (prompt, 0);
+ CHECK_STRING (init, 1);
+
+ return read_minibuf (Vminibuffer_local_ns_map, init, prompt, 0);
+}
+
+DEFUN ("read-command", Fread_command, Sread_command, 1, 1, 0,
+ "One arg PROMPT, a string. Read the name of a command and return as a symbol.\n\
+Prompts with PROMPT.")
+ (prompt)
+ Lisp_Object prompt;
+{
+ return Fintern (Fcompleting_read (prompt, Vobarray, Qcommandp, Qt, Qnil),
+ Qnil);
+}
+
+#ifdef NOTDEF
+DEFUN ("read-function", Fread_function, Sread_function, 1, 1, 0,
+ "One arg PROMPT, a string. Read the name of a function and return as a symbol.\n\
+Prompts with PROMPT.")
+ (prompt)
+ Lisp_Object prompt;
+{
+ return Fintern (Fcompleting_read (prompt, Vobarray, Qfboundp, Qt, Qnil),
+ Qnil);
+}
+#endif /* NOTDEF */
+
+DEFUN ("read-variable", Fread_variable, Sread_variable, 1, 1, 0,
+ "One arg PROMPT, a string. Read the name of a user variable and return\n\
+it as a symbol. Prompts with PROMPT.\n\
+A user variable is one whose documentation starts with a \"*\" character.")
+ (prompt)
+ Lisp_Object prompt;
+{
+ return Fintern (Fcompleting_read (prompt, Vobarray,
+ Quser_variable_p, Qt, Qnil),
+ Qnil);
+}
+
+DEFUN ("read-buffer", Fread_buffer, Sread_buffer, 1, 3, 0,
+ "One arg PROMPT, a string. Read the name of a buffer and return as a string.\n\
+Prompts with PROMPT.\n\
+Optional second arg is value to return if user enters an empty line.\n\
+If optional third arg REQUIRE-MATCH is non-nil, only existing buffer names are allowed.")
+ (prompt, def, require_match)
+ Lisp_Object prompt, def, require_match;
+{
+ Lisp_Object tem;
+ Lisp_Object args[3];
+ struct gcpro gcpro1;
+
+ if (XTYPE (def) == Lisp_Buffer)
+ def = XBUFFER (def)->name;
+ if (!NULL (def))
+ {
+ args[0] = build_string ("%s(default %s) ");
+ args[1] = prompt;
+ args[2] = def;
+ prompt = Fformat (3, args);
+ }
+ GCPRO1 (def);
+ tem = Fcompleting_read (prompt, Vbuffer_alist, Qnil, require_match, Qnil);
+ UNGCPRO;
+ if (XSTRING (tem)->size)
+ return tem;
+ return def;
+}
+
+DEFUN ("try-completion", Ftry_completion, Stry_completion, 2, 3, 0,
+ "Return common substring of all completions of STRING in ALIST.\n\
+Each car of each element of ALIST is tested to see if it begins with STRING.\n\
+All that match are compared together; the longest initial sequence\n\
+common to all matches is returned as a string.\n\
+If there is no match at all, nil is returned.\n\
+For an exact match, t is returned.\n\
+\n\
+ALIST can be an obarray instead of an alist.\n\
+Then the print names of all symbols in the obarray are the possible matches.\n\
+\n\
+If optional third argument PREDICATE is non-nil,\n\
+it is used to test each possible match.\n\
+The match is a candidate only if PREDICATE returns non-nil.\n\
+The argument given to PREDICATE is the alist element or the symbol from the obarray.")
+ (string, alist, pred)
+ Lisp_Object string, alist, pred;
+{
+ Lisp_Object bestmatch, tail, elt, eltstring;
+ int bestmatchsize;
+ int compare, matchsize;
+ int list = CONSP (alist) || NULL (alist);
+ int index, obsize;
+ int matchcount = 0;
+ Lisp_Object bucket, zero, end, tem;
+ struct gcpro gcpro1, gcpro2, gcpro3;
+
+ CHECK_STRING (string, 0);
+ if (!list && XTYPE (alist) != Lisp_Vector)
+ return call3 (alist, string, pred, Qnil);
+
+ bestmatch = Qnil;
+
+ if (list)
+ tail = alist;
+ else
+ {
+ index = 0;
+ obsize = XVECTOR (alist)->size;
+ bucket = XVECTOR (alist)->contents[index];
+ }
+
+ while (1)
+ {
+ /* Get the next element of the alist or obarray. */
+ /* Exit the loop if the elements are all used up. */
+ /* elt gets the alist element or symbol.
+ eltstring gets the name to check as a completion. */
+
+ if (list)
+ {
+ if (NULL (tail))
+ break;
+ elt = Fcar (tail);
+ eltstring = Fcar (elt);
+ tail = Fcdr (tail);
+ }
+ else
+ {
+ if (XFASTINT (bucket) != 0)
+ {
+ elt = bucket;
+ eltstring = Fsymbol_name (elt);
+ if (XSYMBOL (bucket)->next)
+ XSETSYMBOL (bucket, XSYMBOL (bucket)->next);
+ else
+ XFASTINT (bucket) = 0;
+ }
+ else if (++index >= obsize)
+ break;
+ else
+ {
+ bucket = XVECTOR (alist)->contents[index];
+ continue;
+ }
+ }
+
+ /* Is this element a possible completion? */
+
+ if (XTYPE (eltstring) == Lisp_String &&
+ XSTRING (string)->size <= XSTRING (eltstring)->size &&
+ 0 > scmp (XSTRING (eltstring)->data, XSTRING (string)->data,
+ XSTRING (string)->size))
+ {
+ /* Yes. */
+ /* Ignore this element if there is a predicate
+ and the predicate doesn't like it. */
+
+ if (!NULL (pred))
+ {
+ if (EQ (pred, Qcommandp))
+ tem = Fcommandp (elt);
+ else
+ {
+ GCPRO3 (string, eltstring, bestmatch);
+ tem = call1 (pred, elt);
+ UNGCPRO;
+ }
+ if (NULL (tem)) continue;
+ }
+
+ /* Update computation of how much all possible completions match */
+
+ matchcount++;
+ if (NULL (bestmatch))
+ bestmatch = eltstring, bestmatchsize = XSTRING (eltstring)->size;
+ else
+ {
+ compare = min (bestmatchsize, XSTRING (eltstring)->size);
+ matchsize = scmp (XSTRING (bestmatch)->data,
+ XSTRING (eltstring)->data,
+ compare);
+ if (matchsize < 0)
+ matchsize = compare;
+ if (completion_ignore_case)
+ {
+ /* If this is an exact match except for case,
+ use it as the best match rather than one that is not an
+ exact match. This way, we get the case pattern
+ of the actual match. */
+ if ((matchsize == XSTRING (eltstring)->size
+ && matchsize < XSTRING (bestmatch)->size)
+ ||
+ /* If there is no exact match ignoring case,
+ prefer a match that does not change the case
+ of the input. */
+ (((matchsize == XSTRING (eltstring)->size)
+ ==
+ (matchsize == XSTRING (bestmatch)->size))
+ /* If there is more than one exact match ignoring case,
+ and one of them is exact including case,
+ prefer that one. */
+ && !bcmp (XSTRING (eltstring)->data,
+ XSTRING (string)->data,
+ XSTRING (string)->size)
+ && bcmp (XSTRING (bestmatch)->data,
+ XSTRING (string)->data,
+ XSTRING (string)->size)))
+ bestmatch = eltstring;
+ }
+ bestmatchsize = matchsize;
+ }
+ }
+ }
+
+ if (NULL (bestmatch))
+ return Qnil; /* No completions found */
+ /* If we are ignoring case, and there is no exact match,
+ and no additional text was supplied,
+ don't change the case of what the user typed. */
+ if (completion_ignore_case && bestmatchsize == XSTRING (string)->size
+ && XSTRING (bestmatch)->size > bestmatchsize)
+ return string;
+
+ /* Return t if the supplied string is an exact match (counting case);
+ it does not require any change to be made. */
+ if (matchcount == 1 && bestmatchsize == XSTRING (string)->size
+ && !bcmp (XSTRING (bestmatch)->data, XSTRING (string)->data,
+ bestmatchsize))
+ return Qt;
+
+ XFASTINT (zero) = 0; /* Else extract the part in which */
+ XFASTINT (end) = bestmatchsize; /* all completions agree */
+ return Fsubstring (bestmatch, zero, end);
+}
+
+/* Compare exactly LEN chars of strings at S1 and S2,
+ ignoring case if appropriate.
+ Return -1 if strings match,
+ else number of chars that match at the beginning. */
+
+scmp (s1, s2, len)
+ register char *s1, *s2;
+ int len;
+{
+ register int l = len;
+
+ if (completion_ignore_case)
+ {
+ while (l && downcase_table[*s1++] == downcase_table[*s2++])
+ l--;
+ }
+ else
+ {
+ while (l && *s1++ == *s2++)
+ l--;
+ }
+ if (l == 0)
+ return -1;
+ else return len - l;
+}
+
+DEFUN ("all-completions", Fall_completions, Sall_completions, 2, 3, 0,
+ "Search for partial matches to STRING in ALIST.\n\
+Each car of each element of ALIST is tested to see if it begins with STRING.\n\
+The value is a list of all the strings from ALIST that match.\n\
+ALIST can be an obarray instead of an alist.\n\
+Then the print names of all symbols in the obarray are the possible matches.\n\
+\n\
+If optional third argument PREDICATE is non-nil,\n\
+it is used to test each possible match.\n\
+The match is a candidate only if PREDICATE returns non-nil.\n\
+The argument given to PREDICATE is the alist element or the symbol from the obarray.")
+ (string, alist, pred)
+ Lisp_Object string, alist, pred;
+{
+ Lisp_Object tail, elt, eltstring;
+ Lisp_Object allmatches;
+ int list = CONSP (alist) || NULL (alist);
+ int index, obsize;
+ Lisp_Object bucket, tem;
+ struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
+
+ CHECK_STRING (string, 0);
+ if (!list && XTYPE (alist) != Lisp_Vector)
+ {
+ return call3 (alist, string, pred, Qt);
+ }
+ allmatches = Qnil;
+
+ /* If ALIST is not a list, set TAIL just for gc pro. */
+ tail = alist;
+ if (! list)
+ {
+ index = 0;
+ obsize = XVECTOR (alist)->size;
+ bucket = XVECTOR (alist)->contents[index];
+ }
+
+ while (1)
+ {
+ /* Get the next element of the alist or obarray. */
+ /* Exit the loop if the elements are all used up. */
+ /* elt gets the alist element or symbol.
+ eltstring gets the name to check as a completion. */
+
+ if (list)
+ {
+ if (NULL (tail))
+ break;
+ elt = Fcar (tail);
+ eltstring = Fcar (elt);
+ tail = Fcdr (tail);
+ }
+ else
+ {
+ if (XFASTINT (bucket) != 0)
+ {
+ elt = bucket;
+ eltstring = Fsymbol_name (elt);
+ if (XSYMBOL (bucket)->next)
+ XSETSYMBOL (bucket, XSYMBOL (bucket)->next);
+ else
+ XFASTINT (bucket) = 0;
+ }
+ else if (++index >= obsize)
+ break;
+ else
+ {
+ bucket = XVECTOR (alist)->contents[index];
+ continue;
+ }
+ }
+
+ /* Is this element a possible completion? */
+
+ if (XTYPE (eltstring) == Lisp_String &&
+ XSTRING (string)->size <= XSTRING (eltstring)->size &&
+ XSTRING (eltstring)->data[0] != ' ' &&
+ 0 > scmp (XSTRING (eltstring)->data, XSTRING (string)->data,
+ XSTRING (string)->size))
+ {
+ /* Yes. */
+ /* Ignore this element if there is a predicate
+ and the predicate doesn't like it. */
+
+ if (!NULL (pred))
+ {
+ if (EQ (pred, Qcommandp))
+ tem = Fcommandp (elt);
+ else
+ {
+ GCPRO4 (tail, eltstring, allmatches, string);
+ tem = call1 (pred, elt);
+ UNGCPRO;
+ }
+ if (NULL (tem)) continue;
+ }
+ /* Ok => put it on the list. */
+ allmatches = Fcons (eltstring, allmatches);
+ }
+ }
+
+ return Fnreverse (allmatches);
+}
+
+Lisp_Object Vminibuffer_completion_table, Qminibuffer_completion_table;
+Lisp_Object Vminibuffer_completion_predicate, Qminibuffer_completion_predicate;
+Lisp_Object Vminibuffer_completion_confirm, Qminibuffer_completion_confirm;
+
+DEFUN ("completing-read", Fcompleting_read, Scompleting_read, 2, 5, 0,
+ "Read a string in the minibuffer, with completion.\n\
+Args are PROMPT, TABLE, PREDICATE, REQUIRE-MATCH and INITIAL-INPUT.\n\
+PROMPT is a string to prompt with; normally it ends in a colon and a space.\n\
+TABLE is an alist whose elements' cars are strings, or an obarray (see try-completion).\n\
+PREDICATE limits completion to a subset of TABLE; see try-completion for details.\n\
+If REQUIRE-MATCH is non-nil, the user is not allowed to exit unless\n\
+ the input is (or completes to) an element of TABLE.\n\
+ If it is also not t, Return does not exit if it does non-null completion.\n\
+If INITIAL-INPUT is non-nil, insert it in the minibuffer initially.\n\
+Case is ignored if ambient value of completion-ignore-case is non-nil.")
+ (prompt, table, pred, require_match, init)
+ Lisp_Object prompt, table, pred, require_match, init;
+{
+ Lisp_Object val;
+ int count = specpdl_ptr - specpdl;
+ specbind (Qminibuffer_completion_table, table);
+ specbind (Qminibuffer_completion_predicate, pred);
+ specbind (Qminibuffer_completion_confirm,
+ EQ (require_match, Qt) ? Qnil : Qt);
+ val = read_minibuf (NULL (require_match)
+ ? Vminibuffer_local_completion_map
+ : Vminibuffer_local_must_match_map,
+ init, prompt, 0);
+ unbind_to (count);
+ return val;
+}
+
+temp_echo_area_contents (m)
+ char *m;
+{
+ int osize = ZV;
+ Lisp_Object oinhibit;
+ oinhibit = Vinhibit_quit;
+
+ SET_PT (osize);
+ InsStr (m);
+ SET_PT (osize);
+ Vinhibit_quit = Qt;
+ Fsit_for (make_number (2), Qnil);
+ del_range (point, ZV);
+ if (!NULL (Vquit_flag))
+ {
+ Vquit_flag = Qnil;
+ unread_command_char = quit_char;
+ }
+ Vinhibit_quit = oinhibit;
+}
+
+Lisp_Object Fminibuffer_completion_help ();
+Lisp_Object assoc_for_completion ();
+
+/* returns:
+ * 0 no possible completion
+ * 1 was already an exact and unique completion
+ * 3 was already an exact completion
+ * 4 completed to an exact completion
+ * 5 some completion happened
+ * 6 no completion happened
+ */
+int
+do_completion ()
+{
+ Lisp_Object completion, tem;
+ int completedp;
+
+ completion = Ftry_completion (Fbuffer_string (), Vminibuffer_completion_table,
+ Vminibuffer_completion_predicate);
+ if (NULL (completion))
+ {
+ bell ();
+ /* Clearing this prevents sit-for from leaving the message up. */
+ prev_echo_area_contents = 0;
+ temp_echo_area_contents (" [No match]");
+ return 0;
+ }
+
+ if (EQ (completion, Qt)) /* exact and unique match */
+ return 1;
+
+ /* compiler bug */
+ tem = Fstring_equal (completion, Fbuffer_string());
+ if (completedp = NULL (tem))
+ {
+ Ferase_buffer (); /* Some completion happened */
+ Finsert (1, &completion);
+ }
+
+ /* It did find a match. Do we match some possibility exactly now? */
+ if (CONSP (Vminibuffer_completion_table)
+ || NULL (Vminibuffer_completion_table))
+ tem = assoc_for_completion (Fbuffer_string (), Vminibuffer_completion_table);
+ else if (XTYPE (Vminibuffer_completion_table) == Lisp_Vector)
+ {
+ /* the primitive used by Fintern_soft */
+ extern Lisp_Object oblookup ();
+
+ tem = Fbuffer_string ();
+ /* Bypass intern-soft as that loses for nil */
+ tem = oblookup (Vminibuffer_completion_table,
+ XSTRING (tem)->data, XSTRING (tem)->size);
+ if (XTYPE (tem) != Lisp_Symbol)
+ tem = Qnil;
+ else if (!NULL (Vminibuffer_completion_predicate))
+ tem = call1 (Vminibuffer_completion_predicate, tem);
+ else
+ tem = Qt;
+ }
+ else
+ tem = call3 (Vminibuffer_completion_table,
+ Fbuffer_string (),
+ Vminibuffer_completion_predicate,
+ Qlambda);
+
+ if (NULL (tem))
+ { /* not an exact match */
+ if (completedp)
+ return 5;
+ else if (completion_auto_help)
+ Fminibuffer_completion_help ();
+ else
+ temp_echo_area_contents (" [Next char not unique]");
+ return 6;
+ }
+ else
+ return (completedp ? 4 : 3);
+}
+
+/* Like assoc but assumes KEY is a string, and ignores case if appropriate. */
+
+Lisp_Object
+assoc_for_completion (key, list)
+ register Lisp_Object key;
+ Lisp_Object list;
+{
+ register Lisp_Object tail;
+
+ if (completion_ignore_case)
+ key = Fupcase (key);
+
+ for (tail = list; !NULL (tail); tail = Fcdr (tail))
+ {
+ register Lisp_Object elt, tem, thiscar;
+ elt = Fcar (tail);
+ if (!CONSP (elt)) continue;
+ thiscar = Fcar (elt);
+ if (XTYPE (thiscar) != Lisp_String)
+ continue;
+ if (completion_ignore_case)
+ thiscar = Fupcase (thiscar);
+ tem = Fequal (thiscar, key);
+ if (!NULL (tem)) return elt;
+ QUIT;
+ }
+ return Qnil;
+}
+
+DEFUN ("minibuffer-complete", Fminibuffer_complete, Sminibuffer_complete, 0, 0, "",
+ "Complete the minibuffer contents as far as possible.")
+ ()
+{
+ register int i = do_completion ();
+ switch (i)
+ {
+ case 0:
+ return Qnil;
+
+ case 1:
+ temp_echo_area_contents(" [Sole completion]");
+ break;
+
+ case 3:
+ temp_echo_area_contents(" [Complete, but not unique]");
+ break;
+ }
+ return Qt;
+}
+
+DEFUN ("minibuffer-complete-and-exit", Fminibuffer_complete_and_exit,
+ Sminibuffer_complete_and_exit, 0, 0, "",
+ "Complete the minibuffer contents, and maybe exit.\n\
+Exit if the name is valid with no completion needed.\n\
+If name was completed to a valid match,\n\
+a repetition of this command will exit.")
+ ()
+{
+ register int i;
+
+ /* Allow user to specify null string */
+ if (BEGV == ZV)
+ goto exit;
+
+ i = do_completion ();
+ switch (i)
+ {
+ case 1:
+ case 3:
+ goto exit;
+
+ case 4:
+ if (!NULL (Vminibuffer_completion_confirm))
+ {
+ temp_echo_area_contents(" [Confirm]");
+ return Qnil;
+ }
+ else
+ goto exit;
+
+ default:
+ return Qnil;
+ }
+ exit:
+ Fthrow (Qexit, Qnil);
+ /* NOTREACHED */
+}
+
+DEFUN ("minibuffer-complete-word", Fminibuffer_complete_word, Sminibuffer_complete_word,
+ 0, 0, "",
+ "Complete the minibuffer contents at most a single word.")
+ ()
+{
+ Lisp_Object completion, tem;
+ register int i;
+ register unsigned char *completion_string;
+ /* We keep calling Fbuffer_string
+ rather than arrange for GC to hold onto a pointer to
+ one of the strings thus made. */
+
+ completion = Ftry_completion (Fbuffer_string (),
+ Vminibuffer_completion_table,
+ Vminibuffer_completion_predicate);
+ if (NULL (completion))
+ {
+ bell ();
+ temp_echo_area_contents (" [No match]");
+ return Qnil;
+ }
+ if (EQ (completion, Qt))
+ return Qnil;
+
+#if 0 /* How the below code used to look, for reference */
+ tem = Fbuffer_string ();
+ b = XSTRING (tem)->data;
+ i = ZV - 1 - XSTRING (completion)->size;
+ p = XSTRING (completion)->data;
+ if (i > 0 ||
+ 0 <= scmp (b, p, ZV - 1))
+ {
+ i = 1;
+ /* Set buffer to longest match of buffer tail and completion head. */
+ while (0 <= scmp (b + i, p, ZV - 1 - i))
+ i++;
+ del_range (1, i + 1);
+ SET_PT (ZV);
+ }
+#else /* Rewritten code */
+ {
+ register unsigned char *buffer_string;
+ int buffer_length, completion_length;
+
+ tem = Fbuffer_string ();
+ buffer_string = XSTRING (tem)->data;
+ completion_string = XSTRING (completion)->data;
+ buffer_length = XSTRING (tem)->size; /* ie ZV - BEGV */
+ completion_length = XSTRING (completion)->size;
+ i = buffer_length - completion_length;
+ /* Mly: I don't understand what this is supposed to do AT ALL */
+ if (i > 0 ||
+ 0 <= scmp (buffer_string, completion_string, buffer_length))
+ {
+ /* Set buffer to longest match of buffer tail and completion head. */
+ if (i <= 0) i = 1;
+ buffer_string += i;
+ buffer_length -= i;
+ while (0 <= scmp (buffer_string++, completion_string, buffer_length--))
+ i++;
+ del_range (1, i + 1);
+ SET_PT (ZV);
+ }
+ }
+#endif /* Rewritten code */
+ i = ZV - BEGV;
+
+ /* If completion finds next char not unique,
+ consider adding a space or a hyphen */
+ if (i == XSTRING (completion)->size)
+ {
+ tem = Ftry_completion (concat2 (Fbuffer_string (), build_string (" ")),
+ Vminibuffer_completion_table,
+ Vminibuffer_completion_predicate);
+ if (XTYPE (tem) == Lisp_String)
+ completion = tem;
+ else
+ {
+ tem = Ftry_completion (concat2 (Fbuffer_string (), build_string ("-")),
+ Vminibuffer_completion_table,
+ Vminibuffer_completion_predicate);
+ if (XTYPE (tem) == Lisp_String)
+ completion = tem;
+ }
+ }
+
+ /* Now find first word-break in the stuff found by completion.
+ i gets index in string of where to stop completing. */
+ completion_string = XSTRING (completion)->data;
+
+ for (; i < XSTRING (completion)->size; i++)
+ if (SYNTAX (completion_string[i]) != Sword) break;
+ if (i < XSTRING (completion)->size)
+ i = i + 1;
+
+ /* If got no characters, print help for user. */
+
+ if (i == ZV - BEGV)
+ {
+ if (completion_auto_help)
+ Fminibuffer_completion_help ();
+ return Qnil;
+ }
+
+ /* Otherwise insert in minibuffer the chars we got */
+
+ Ferase_buffer ();
+ insert (completion_string, i);
+ return Qt;
+}
+
+DEFUN ("display-completion-list", Fdisplay_completion_list, Sdisplay_completion_list,
+ 1, 1, 0,
+ "Display in a buffer the list of completions, COMPLETIONS.\n\
+Each element may be just a symbol or string\n\
+or may be a list of two strings to be printed as if concatenated.")
+ (completions)
+ Lisp_Object completions;
+{
+ register Lisp_Object tail, elt;
+ register int i;
+ struct buffer *old = current_buffer;
+ /* No GCPRO needed, since (when it matters) every variable
+ points to a non-string that is pointed to by COMPLETIONS. */
+
+ set_buffer_internal (XBUFFER (Vstandard_output));
+
+ if (NULL (completions))
+ InsStr ("There are no possible completions of what you have typed.");
+ else
+ {
+ InsStr ("Possible completions are:");
+ for (tail = completions, i = 0; !NULL (tail); tail = Fcdr (tail), i++)
+ {
+ /* this needs fixing for the case of long completions
+ and/or narrow windows */
+ /* Sadly, the window it will appear in is not known
+ until after the text has been made. */
+ if (i & 1)
+ Findent_to (make_number (35), make_number (1));
+ else
+ Fterpri (Qnil);
+ elt = Fcar (tail);
+ if (CONSP (elt))
+ {
+ Fprinc (Fcar (elt), Qnil);
+ Fprinc (Fcar (Fcdr (elt)), Qnil);
+ }
+ else
+ Fprinc (elt, Qnil);
+ }
+ }
+ set_buffer_internal (old);
+ return Qnil;
+}
+
+DEFUN ("minibuffer-completion-help", Fminibuffer_completion_help, Sminibuffer_completion_help,
+ 0, 0, "",
+ "Display a list of possible completions of the current minibuffer contents.")
+ ()
+{
+ Lisp_Object completions;
+ message ("Making completion list...");
+ completions = Fall_completions (Fbuffer_string (), Vminibuffer_completion_table,
+ Vminibuffer_completion_predicate);
+ echo_area_contents = 0;
+ if (NULL (completions))
+ {
+ bell ();
+ temp_echo_area_contents (" [No completions]");
+ }
+ else
+ internal_with_output_to_temp_buffer (" *Completions*",
+ Fdisplay_completion_list,
+ Fsort (completions, Qstring_lessp));
+ return Qnil;
+}
+
+DEFUN ("self-insert-and-exit", Fself_insert_and_exit, Sself_insert_and_exit, 0, 0, "",
+ "Terminate minibuffer input.")
+ ()
+{
+ self_insert_internal (last_command_char, 0);
+ Fthrow (Qexit, Qnil);
+}
+
+DEFUN ("exit-minibuffer", Fexit_minibuffer, Sexit_minibuffer, 0, 0, "",
+ "Terminate this minibuffer argument.")
+ ()
+{
+ Fthrow (Qexit, Qnil);
+}
+
+DEFUN ("minibuffer-depth", Fminibuffer_depth, Sminibuffer_depth, 0, 0, 0,
+ "Return current depth of activations of minibuffer, a nonnegative integer.")
+ ()
+{
+ return make_number (minibuf_level);
+}
+
+
+init_minibuf_once ()
+{
+ Vminibuffer_list = Qnil;
+ staticpro (&Vminibuffer_list);
+}
+
+syms_of_minibuf ()
+{
+ minibuf_level = 0;
+ minibuf_prompt = 0;
+ minibuf_save_vector_size = 5;
+ minibuf_save_vector = (struct minibuf_save_data *) malloc (5 * sizeof (struct minibuf_save_data));
+
+ Qminibuffer_completion_table = intern ("minibuffer-completion-table");
+ staticpro (&Qminibuffer_completion_table);
+
+ Qminibuffer_completion_confirm = intern ("minibuffer-completion-confirm");
+ staticpro (&Qminibuffer_completion_confirm);
+
+ Qminibuffer_completion_predicate = intern ("minibuffer-completion-predicate");
+ staticpro (&Qminibuffer_completion_predicate);
+
+ staticpro (&last_minibuf_string);
+ last_minibuf_string = Qnil;
+
+ Quser_variable_p = intern ("user-variable-p");
+ staticpro (&Quser_variable_p);
+
+
+
+ DEFVAR_BOOL ("completion-auto-help", &completion_auto_help,
+ "*Non-nil means automatically provide help for invalid completion input.");
+ completion_auto_help = 1;
+
+ DEFVAR_BOOL ("completion-ignore-case", &completion_ignore_case,
+ "Non-nil means don't consider case significant in completion.");
+ completion_ignore_case = 0;
+
+ DEFVAR_BOOL ("enable-recursive-minibuffers", &enable_recursive_minibuffers,
+ "*Non-nil means to allow minibuffers to invoke commands which use\n\
+recursive minibuffers.");
+ enable_recursive_minibuffers = 0;
+
+ DEFVAR_LISP ("minibuffer-completion-table", &Vminibuffer_completion_table,
+ "Alist or obarray used for completion in the minibuffer.");
+ Vminibuffer_completion_table = Qnil;
+
+ DEFVAR_LISP ("minibuffer-completion-predicate", &Vminibuffer_completion_predicate,
+ "Holds PREDICATE argument to completing-read.");
+ Vminibuffer_completion_predicate = Qnil;
+
+ DEFVAR_LISP ("minibuffer-completion-confirm", &Vminibuffer_completion_confirm,
+ "Non-nil => demand confirmation of completion before exiting minibuffer.");
+ Vminibuffer_completion_confirm = Qnil;
+
+ DEFVAR_LISP ("minibuffer-help-form", &Vminibuffer_help_form,
+ "Value that help-form takes on inside the minibuffer.");
+ Vminibuffer_help_form = Qnil;
+
+ defsubr (&Sread_from_minibuffer);
+ defsubr (&Seval_minibuffer);
+ defsubr (&Sread_minibuffer);
+ defsubr (&Sread_string);
+ defsubr (&Sread_command);
+ defsubr (&Sread_variable);
+ defsubr (&Sread_buffer);
+ defsubr (&Sread_no_blanks_input);
+ defsubr (&Sminibuffer_depth);
+
+ defsubr (&Stry_completion);
+ defsubr (&Sall_completions);
+ defsubr (&Scompleting_read);
+ defsubr (&Sminibuffer_complete);
+ defsubr (&Sminibuffer_complete_word);
+ defsubr (&Sminibuffer_complete_and_exit);
+ defsubr (&Sdisplay_completion_list);
+ defsubr (&Sminibuffer_completion_help);
+
+ defsubr (&Sself_insert_and_exit);
+ defsubr (&Sexit_minibuffer);
+
+}
+
+keys_of_minibuf ()
+{
+ ndefkey (Vminibuffer_local_map, Ctl ('g'), "abort-recursive-edit");
+ ndefkey (Vminibuffer_local_map, Ctl ('m'), "exit-minibuffer");
+ ndefkey (Vminibuffer_local_map, Ctl ('j'), "exit-minibuffer");
+
+ ndefkey (Vminibuffer_local_ns_map, Ctl ('g'), "abort-recursive-edit");
+ ndefkey (Vminibuffer_local_ns_map, Ctl ('m'), "exit-minibuffer");
+ ndefkey (Vminibuffer_local_ns_map, Ctl ('j'), "exit-minibuffer");
+
+ ndefkey (Vminibuffer_local_ns_map, ' ', "exit-minibuffer");
+ ndefkey (Vminibuffer_local_ns_map, '\t', "exit-minibuffer");
+ ndefkey (Vminibuffer_local_ns_map, '?', "self-insert-and-exit");
+
+ ndefkey (Vminibuffer_local_completion_map, Ctl ('g'), "abort-recursive-edit");
+ ndefkey (Vminibuffer_local_completion_map, Ctl ('m'), "exit-minibuffer");
+ ndefkey (Vminibuffer_local_completion_map, Ctl ('j'), "exit-minibuffer");
+ ndefkey (Vminibuffer_local_completion_map, '\t', "minibuffer-complete");
+ ndefkey (Vminibuffer_local_completion_map, ' ', "minibuffer-complete-word");
+ ndefkey (Vminibuffer_local_completion_map, '?', "minibuffer-completion-help");
+
+ ndefkey (Vminibuffer_local_must_match_map, Ctl ('g'), "abort-recursive-edit");
+ ndefkey (Vminibuffer_local_must_match_map, Ctl ('m'), "minibuffer-complete-and-exit");
+ ndefkey (Vminibuffer_local_must_match_map, Ctl ('j'), "minibuffer-complete-and-exit");
+ ndefkey (Vminibuffer_local_must_match_map, '\t', "minibuffer-complete");
+ ndefkey (Vminibuffer_local_must_match_map, ' ', "minibuffer-complete-word");
+ ndefkey (Vminibuffer_local_must_match_map, '?', "minibuffer-completion-help");
+}
diff --git a/src/mocklisp.c b/src/mocklisp.c
index 5fb34ae74cc..b58e77ec2f4 100644
--- a/src/mocklisp.c
+++ b/src/mocklisp.c
@@ -42,7 +42,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
* }
*/
-DEFUN ("ml-if", Fml_if, Sml_if, 0, UNEVALLED, 0, "Mocklisp version of `if'.")
+DEFUN ("ml-if", Fml_if, Sml_if, 0, UNEVALLED, 0, "if for mocklisp programs")
(args)
Lisp_Object args;
{
@@ -101,11 +101,11 @@ ml_apply (function, args)
specbind (Qmocklisp_arguments, args);
val = Fprogn (Fcdr (function));
- return unbind_to (count, val);
+ unbind_to (count);
+ return val;
}
-DEFUN ("ml-nargs", Fml_nargs, Sml_nargs, 0, 0, 0,
- "Number of arguments to currently executing mocklisp function.")
+DEFUN ("ml-nargs", Fml_nargs, Sml_nargs, 0, 0, 0, "# arguments to this mocklisp function")
()
{
if (EQ (Vmocklisp_arguments, Qinteractive))
@@ -113,8 +113,7 @@ DEFUN ("ml-nargs", Fml_nargs, Sml_nargs, 0, 0, 0,
return Flength (Vmocklisp_arguments);
}
-DEFUN ("ml-arg", Fml_arg, Sml_arg, 1, 2, 0,
- "Argument number N to currently executing mocklisp function.")
+DEFUN ("ml-arg", Fml_arg, Sml_arg, 1, 2, 0, "Argument #N to this mocklisp function.")
(n, prompt)
Lisp_Object n, prompt;
{
@@ -126,7 +125,7 @@ DEFUN ("ml-arg", Fml_arg, Sml_arg, 1, 2, 0,
}
DEFUN ("ml-interactive", Fml_interactive, Sml_interactive, 0, 0, 0,
- "True if currently executing mocklisp function was called interactively.")
+ "True if this mocklisp function was called interactively.")
()
{
return (EQ (Vmocklisp_arguments, Qinteractive)) ? Qt : Qnil;
@@ -175,7 +174,7 @@ DEFUN ("ml-prefix-argument-loop", Fml_prefix_argument_loop, Sml_prefix_argument_
return Qnil;
}
-#if 0 /* Now in mlsupport.el */
+#ifdef NOTDEF /* Now in mlsupport.el */
DEFUN ("ml-substr", Fml_substr, Sml_substr, 3, 3, 0,
"Return a substring of STRING, starting at index FROM and of length LENGTH.\n\
@@ -213,7 +212,9 @@ is converted into a string by expressing it in decimal.")
if (XTYPE (tem) == Lisp_Int)
tem = Fint_to_string (tem);
if (XTYPE (tem) == Lisp_String)
- insert1 (tem);
+ {
+ insert (XSTRING (tem)->data, XSTRING (tem)->size);
+ }
else
{
tem = wrong_type_argument (Qstringp, tem);
diff --git a/src/ndir.h b/src/ndir.h
new file mode 100644
index 00000000000..438d5c20a12
--- /dev/null
+++ b/src/ndir.h
@@ -0,0 +1,51 @@
+/*
+ <dir.h> -- definitions for 4.2BSD-compatible directory access
+
+ last edit: 09-Jul-1983 D A Gwyn
+*/
+
+#ifdef VMS
+#ifndef FAB$C_BID
+#include <fab.h>
+#endif
+#ifndef NAM$C_BID
+#include <nam.h>
+#endif
+#ifndef RMS$_SUC
+#include <rmsdef.h>
+#endif
+#include "dir.h"
+#endif /* VMS */
+
+#define DIRBLKSIZ 512 /* size of directory block */
+#ifdef VMS
+#define MAXNAMLEN (DIR$S_NAME + 7) /* 80 plus room for version #. */
+#define MAXFULLSPEC NAM$C_MAXRSS /* Maximum full spec */
+#else
+#define MAXNAMLEN 15 /* maximum filename length */
+#endif /* VMS */
+ /* NOTE: MAXNAMLEN must be one less than a multiple of 4 */
+
+struct direct /* data from readdir() */
+ {
+ long d_ino; /* inode number of entry */
+ unsigned short d_reclen; /* length of this record */
+ unsigned short d_namlen; /* length of string in d_name */
+ char d_name[MAXNAMLEN+1]; /* name of file */
+ };
+
+typedef struct
+ {
+ int dd_fd; /* file descriptor */
+ int dd_loc; /* offset in block */
+ int dd_size; /* amount of valid data */
+ char dd_buf[DIRBLKSIZ]; /* directory block */
+ } DIR; /* stream data from opendir() */
+
+extern DIR *opendir();
+extern struct direct *readdir();
+extern long telldir();
+extern void seekdir();
+extern void closedir();
+
+#define rewinddir( dirp ) seekdir( dirp, 0L )
diff --git a/src/old-ralloc.c b/src/old-ralloc.c
deleted file mode 100644
index 28562994e9a..00000000000
--- a/src/old-ralloc.c
+++ /dev/null
@@ -1,1069 +0,0 @@
-/* Block-relocating memory allocator.
- Copyright (C) 1990 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 1, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-/* This package works by allocating blocks from a zone of memory
- above that used by malloc (). When malloc needs more space that
- would enter our zone, we relocate blocks upward. The bottom of
- our zone is kept in the variable `virtual_break_value'. The top
- of our zone is indicated by `real_break_value'.
-
- As blocks are freed, a free list is maintained and we attempt
- to satisfy further requests for space using a first-fit policy.
- If there are holes, but none fit, memory is compacted and a new
- block is obtained at the top of the zone.
-
- NOTE that our blocks are always rounded to page boundaries. */
-
-/*
- NOTES:
-
- Once this is stable, I can speed things up by intially leaving a large
- gap between real_break_value and true_break_value, or maybe making
- a large hole before the first block.
-
- If we also kept track of size_wanted, we could gain some
- extra space upon compactification.
-
- Perhaps we should just note a hole when malloc does doing sbrk(-n)?
-
- Relocating downward upon freeing the first block would simplify
- other things.
-
- When r_alloc places a block in a hole, we could easily check if there's
- much more than required, and leave a hole.
- */
-
-#include "mem_limits.h"
-
-static POINTER r_alloc_sbrk ();
-static POINTER sbrk ();
-static POINTER brk ();
-
-/* Variable `malloc' uses for the function which gets more space
- from the system. */
-extern POINTER (*__morecore) ();
-
-/* List of variables which point into the associated data block. */
-struct other_pointer
-{
- POINTER *location;
- struct other_pointer *next;
-};
-
-/* List describing all the user's pointers to relocatable blocks. */
-typedef struct rel_pointers
-{
- struct rel_pointers *next;
- struct rel_pointers *prev;
- struct other_pointer *others; /* Other variables which use this block. */
- POINTER *location; /* Location of the block's pointer. */
- POINTER block; /* Address of the actual data. */
- int size; /* The size of the block. */
-} relocatable_pointer;
-
-#define REL_NIL ((struct rel_pointers *) 0)
-
-static relocatable_pointer *pointer_list;
-static relocatable_pointer *last_pointer;
-
-#define MAX_HOLES 2
-
-/* Vector of available holes among allocated blocks. This can include
- a hole at the beginning of the list, but never the end. */
-typedef struct
-{
- POINTER address;
- unsigned int size;
-} hole_descriptor;
-
-static hole_descriptor r_alloc_holes[MAX_HOLES];
-
-/* Number of holes currently available. */
-static int holes;
-
-/* The process break value (i.e., curbrk) */
-static POINTER real_break_value;
-
-/* The REAL (i.e., page aligned) break value. */
-static POINTER true_break_value;
-
-/* Address of start of data space in use by relocatable blocks.
- This is what `malloc' thinks is the process break value. */
-static POINTER virtual_break_value;
-
-/* Nonzero if we have told `malloc' to start using `r_alloc_sbrk'
- instead of calling `sbrk' directly. */
-int r_alloc_in_use;
-
-#define PAGE (getpagesize ())
-#define ALIGNED(addr) (((unsigned int) (addr) & (PAGE - 1)) == 0)
-#define ROUNDUP(size) (((unsigned int) (size) + PAGE) & ~(PAGE - 1))
-
-/*
- Level number of warnings already issued.
- 0 -- no warnings issued.
- 1 -- 75% warning already issued.
- 2 -- 85% warning already issued.
-*/
-static int warnlevel;
-
-/* Function to call to issue a warning;
- 0 means don't issue them. */
-static void (*warnfunction) ();
-
-/* Call this to start things off. It determines the current process
- break value, as well as the `true' break value--because the system
- allocates memory in page increments, if the break value is not page
- aligned it means that space up to the next page boundary is actually
- available. */
-
-void
-malloc_init (start, warn_func)
- POINTER start;
- void (*warn_func) ();
-{
- r_alloc_in_use = 1;
- __morecore = r_alloc_sbrk;
-
- virtual_break_value = real_break_value = sbrk (0);
- if (ALIGNED (real_break_value))
- true_break_value = real_break_value;
- else
- true_break_value = (POINTER) ROUNDUP (real_break_value);
-
- if (start)
- data_space_start = start;
- lim_data = 0;
- warnlevel = 0;
- warnfunction = warn_func;
-
- get_lim_data ();
-}
-
-/* Get more space for us to use. Return a pointer to SIZE more
- bytes of space. SIZE is internally rounded up to a page boundary,
- and requests for integral pages prefetch an extra page. */
-
-static POINTER
-get_more_space (size)
- unsigned int size;
-{
- unsigned int margin = true_break_value - real_break_value;
- unsigned int get;
- POINTER old_break = real_break_value;
-
- if (size == 0)
- return real_break_value;
-
- if (size <= margin)
- {
- real_break_value += size;
- return old_break;
- }
-
- get = ROUNDUP (size - margin);
- if (sbrk (get) < (POINTER) 0)
- return NULL;
-
- true_break_value += get;
- real_break_value = (old_break + size);
-
- return old_break;
-}
-
-/* Relinquish size bytes of space to the system. Space is only returned
- in page increments. If successful, return real_break_value. */
-
-static POINTER
-return_space (size)
- unsigned int size;
-{
- unsigned int margin = (true_break_value - real_break_value) + size;
- unsigned int to_return = (margin / PAGE) * PAGE;
- unsigned new_margin = margin % PAGE;
-
- true_break_value -= to_return;
- if (! brk (true_break_value))
- return NULL;
-
- real_break_value = true_break_value - new_margin;
- return real_break_value;
-}
-
-/* Record a new hole in memory beginning at ADDRESS of size SIZE.
- Holes are ordered by location. Adjacent holes are merged.
- Holes are zero filled before being noted. */
-
-static void
-note_hole (address, size)
- POINTER address;
- int size;
-{
- register int this_hole = holes - 1; /* Start at the last hole. */
- register POINTER end = address + size; /* End of the hole. */
- register int i;
-
- if (holes)
- {
- /* Find the hole which should precede this new one. */
- while (this_hole >= 0 && r_alloc_holes[this_hole].address > address)
- this_hole--;
-
- /* Can we merge with preceding? */
- if (this_hole >= 0
- && r_alloc_holes[this_hole].address + r_alloc_holes[this_hole].size
- == address)
- {
- r_alloc_holes[this_hole].size += size;
-
- if (this_hole == holes - 1)
- return;
-
- /* Can we also merge with following? */
- if (end == r_alloc_holes[this_hole + 1].address)
- {
- r_alloc_holes[this_hole].size
- += r_alloc_holes[this_hole + 1].size;
-
- for (i = this_hole + 1; i < holes - 1; i++)
- r_alloc_holes[i] = r_alloc_holes[i + 1];
- holes--;
- }
-
- return;
- }
-
- if (this_hole < holes - 1) /* there are following holes */
- {
- register int next_hole = this_hole + 1;
-
- /* Can we merge with the next hole? */
- if (end == r_alloc_holes[next_hole].address)
- {
- r_alloc_holes[next_hole].address = address;
- r_alloc_holes[next_hole].size += size;
- return;
- }
-
- /* Can't merge, so insert. */
- for (i = holes; i > next_hole; i--)
- r_alloc_holes[i] = r_alloc_holes[i - 1];
- r_alloc_holes[next_hole].address = address;
- r_alloc_holes[next_hole].size = size;
- holes++;
-
- return;
- }
- else /* Simply add this hole at the end. */
- {
- r_alloc_holes[holes].address = address;
- r_alloc_holes[holes].size = size;
- holes++;
-
- return;
- }
-
- abort ();
- }
- else /* Make the first hole. */
- {
- holes = 1;
- r_alloc_holes[0].address = address;
- r_alloc_holes[0].size = size;
- }
-}
-
-/* Mark hole HOLE as no longer available by re-organizing the vector.
- HOLE is the Nth hole, beginning with 0. This doesn *not* affect memory
- organization. */
-
-static void
-delete_hole (hole)
- int hole;
-{
- register int i;
-
- for (i = hole; i < holes - 1; i++)
- r_alloc_holes[i] = r_alloc_holes[i + 1];
-
- holes--;
-}
-
-/* Insert a newly allocated pointer, NEW_PTR, at the appropriate
- place in our list. */
-
-static void
-insert (new_ptr)
- register relocatable_pointer *new_ptr;
-{
- register relocatable_pointer *this_ptr = pointer_list;
-
- while (this_ptr != REL_NIL && this_ptr->block < new_ptr->block)
- this_ptr = this_ptr->next;
-
- if (this_ptr == REL_NIL)
- abort (); /* Use `attach' for appending. */
-
- new_ptr->next = this_ptr;
- new_ptr->prev = this_ptr->prev;
- this_ptr->prev = new_ptr;
-
- if (this_ptr == pointer_list)
- pointer_list = new_ptr;
- else
- new_ptr->prev->next = new_ptr;
-}
-
-/* Attach a newly allocated pointer, NEW_PTR, to the end of our list. */
-
-static void
-attach (new_ptr)
- relocatable_pointer *new_ptr;
-{
- if (pointer_list == REL_NIL)
- {
- pointer_list = new_ptr;
- last_pointer = new_ptr;
- new_ptr->next = new_ptr->prev = REL_NIL;
- }
- else
- {
- new_ptr->next = REL_NIL;
- last_pointer->next = new_ptr;
- new_ptr->prev = last_pointer;
- last_pointer = new_ptr;
- }
-}
-
-static relocatable_pointer *
-find_block (block)
- POINTER block;
-{
- register relocatable_pointer *this_ptr = pointer_list;
-
- while (this_ptr != REL_NIL && this_ptr->block != block)
- this_ptr = this_ptr->next;
-
- return this_ptr;
-}
-
-static relocatable_pointer *
-find_location (address)
- POINTER *address;
-{
- register relocatable_pointer *this_ptr = pointer_list;
-
- while (this_ptr != REL_NIL && this_ptr->location != address)
- {
- struct other_pointer *op = this_ptr->others;
-
- while (op != (struct other_pointer *) 0)
- {
- if (op->location == address)
- return this_ptr;
-
- op = op->next;
- }
-
- this_ptr = this_ptr->next;
- }
-
- return this_ptr;
-}
-
-
-static void compactify ();
-
-/* Record of last new block allocated. */
-static relocatable_pointer *last_record;
-
-/* Allocate a block of size SIZE and record that PTR points to it.
- If successful, store the address of the block in *PTR and return
- it as well. Otherwise return NULL. */
-
-POINTER
-r_alloc (ptr, size)
- POINTER *ptr;
- int size;
-{
- register relocatable_pointer *record
- = (relocatable_pointer *) malloc (sizeof (relocatable_pointer));
- register POINTER block;
-
- /* If we can't get space to record this pointer, fail. */
- if (record == 0)
- return NULL;
-
- last_record = record;
-
- if (holes) /* Search for a hole the right size. */
- {
- int i;
-
- for (i = 0; i < holes; i++)
- if (r_alloc_holes[i].size >= size)
- {
- record->location = ptr;
- record->others = (struct other_pointer *) 0;
- record->block = *ptr = r_alloc_holes[i].address;
- if (r_alloc_holes[i].size > ROUNDUP (size))
- {
- record->size = ROUNDUP (size);
- r_alloc_holes[i].size -= ROUNDUP (size);
- r_alloc_holes[i].address += ROUNDUP (size);
- }
- else
- {
- record->size = r_alloc_holes[i].size;
- delete_hole (i);
- }
- insert (record);
-
- *ptr = record->block;
- return record->block;
- }
-
- /* No holes large enough. Burp. */
- compactify ();
- }
-
- /* No holes: grow the process. */
- block = get_more_space (size);
- if (block == NULL)
- {
- free (record);
- return NULL;
- }
-
- /* Return the address of the block. */
- *ptr = block;
-
- /* Record and append this pointer to our list. */
- record->location = ptr;
- record->others = (struct other_pointer *) 0;
- record->block = block;
- record->size = size;
- attach (record);
-
- return block;
-}
-
-/* Declare VAR to be a pointer which points into the block of r_alloc'd
- memory at BLOCK.
-
- If VAR is already delcared for this block, simply return.
- If VAR currently points to some other block, remove that declaration
- of it, then install the new one.
-
- Return 0 if successful, -1 otherwise. */
-
-int
-r_alloc_declare (var, block)
- POINTER *var;
- register POINTER block;
-{
- register relocatable_pointer *block_ptr = find_block (block);
- relocatable_pointer *var_ptr = find_location (var);
- register struct other_pointer *other;
-
- if (block_ptr == REL_NIL)
- abort ();
-
- if (var_ptr != REL_NIL) /* Var already declared somewhere. */
- {
- register struct other_pointer *po;
-
- if (var_ptr == block_ptr) /* Var already points to this block. */
- return 0;
-
- po = (struct other_pointer *) 0;
- other = var_ptr->others;
- while (other && other->location != var)
- {
- po = other;
- other = other->next;
- }
-
- if (!other) /* This only happens if the location is */
- abort (); /* the main pointer and not an `other' */
-
- if (po) /* In the chain */
- {
- po->next = other->next;
- free (other);
- }
- else /* Only element of the chain */
- {
- free (var_ptr->others);
- var_ptr->others = (struct other_pointer *) 0;
- }
- }
-
- /* Install this variable as an `other' element */
-
- other = (struct other_pointer *) malloc (sizeof (struct other_pointer));
-
- if (other == 0)
- return -1;
-
- /* If the malloc relocated this data block, adjust this variable. */
- if (block != block_ptr->block)
- {
- int offset = block_ptr->block - block;
-
- *var += offset;
- }
-
- other->location = var;
- other->next = (struct other_pointer *) 0;
-
- if (block_ptr->others == (struct other_pointer *) 0)
- block_ptr->others = other;
- else
- {
- register struct other_pointer *op = block_ptr->others;
-
- while (op->next != (struct other_pointer *) 0)
- op = op->next;
- op->next = other;
- }
-
- return 0;
-}
-
-/* Recursively free the linked list of `other' pointers to a block. */
-
-static void
-free_others (another)
- struct other_pointer *another;
-{
- if (another == (struct other_pointer *) 0)
- return;
-
- free_others (another->next);
- free (another);
-}
-
-/* Remove the element pointed to by PTR from the doubly linked list.
- Record the newly freed space in `holes', unless it was at the end,
- in which case return that space to the system. Return 0 if successful,
- -1 otherwise. */
-
-int
-r_alloc_free (ptr)
- register POINTER *ptr;
-{
- register relocatable_pointer *this_ptr = find_block (*ptr);
-
- if (this_ptr == REL_NIL)
- return -1;
- else
- {
- register relocatable_pointer *prev = this_ptr->prev;
- register relocatable_pointer *next = this_ptr->next;
- if (next && prev) /* Somewhere in the middle */
- {
- next->prev = prev;
- prev->next = next;
- }
- else if (prev) /* Last block */
- {
- prev->next = REL_NIL;
- last_pointer = prev;
- return_space (this_ptr->size);
- free_others (this_ptr->others);
- free (this_ptr);
-
- return 0;
- }
- else if (next) /* First block */
- {
- next->prev = REL_NIL;
- pointer_list = next;
- }
- else if (this_ptr = pointer_list) /* ONLY block */
- {
- pointer_list = REL_NIL;
- last_pointer = REL_NIL;
- if (holes) /* A hole precedes this block. */
- {
- holes = 0;
- return_space (real_break_value - virtual_break_value);
- }
- else
- return_space (this_ptr->size);
-
- if (real_break_value != virtual_break_value)
- abort ();
-
- free_others (this_ptr->others);
- free (this_ptr);
- /* Turn off r_alloc_in_use? */
-
- return 0;
- }
- else
- abort (); /* Weird shit */
-
- free_others (this_ptr->others);
- free (this_ptr);
- bzero (this_ptr->block, this_ptr->size);
- note_hole (this_ptr->block, this_ptr->size);
-
- if (holes == MAX_HOLES)
- compactify ();
- }
-
- return 0;
-}
-
-/* Change the size of the block pointed to by the thing in PTR.
- If neccessary, r_alloc a new block and copy the data there.
- Return a pointer to the block if successfull, NULL otherwise.
-
- Note that if the size requested is less than the actual bloc size,
- nothing is done and the pointer is simply returned. */
-
-POINTER
-r_re_alloc (ptr, size)
- POINTER *ptr;
- int size;
-{
- register relocatable_pointer *this_ptr = find_block (*ptr);
- POINTER block;
-
- if (! this_ptr)
- return NULL;
-
- if (this_ptr->size >= size) /* Already have enough space. */
- return *ptr;
-
- /* Here we could try relocating the blocks just above... */
- block = r_alloc (ptr, size);
- if (block)
- {
- bcopy (this_ptr->block, block, this_ptr->size);
- if (this_ptr->others)
- last_record->others = this_ptr->others;
-
- if (! r_alloc_free (this_ptr->block))
- abort ();
-
- *ptr = block;
- return block;
- }
-
- return NULL;
-}
-
-
-/* Move and relocate all blocks from FIRST_PTR to LAST_PTR, inclusive,
- downwards to space starting at ADDRESS. */
-
-static int
-move_blocks_downward (first_ptr, last_ptr, address)
- relocatable_pointer *first_ptr, *last_ptr;
- POINTER address;
-{
- int size = (last_ptr->block + last_ptr->size) - first_ptr->block;
- register relocatable_pointer *this_ptr = first_ptr;
- register offset = first_ptr->block - address;
- register struct other_pointer *op;
-
- /* Move all the data. */
- bcopy (first_ptr->block, address, size);
-
- /* Now relocate all the pointers to those blocks. */
- while (1)
- {
- this_ptr->block -= offset;
- *this_ptr->location = this_ptr->block;
-
- op = this_ptr->others;
- while (op != (struct other_pointer *) 0)
- {
- *op->location -= offset;
- op = op->next;
- }
-
- if (this_ptr == last_ptr)
- return;
- else
- this_ptr = this_ptr->next;
- }
-
- return size;
-}
-
-/* Burp our memory zone. */
-
-static void
-compactify ()
-{
- register relocatable_pointer *this_ptr = pointer_list;
- relocatable_pointer *first_to_move;
- register relocatable_pointer *last_to_move;
- hole_descriptor *this_hole = &r_alloc_holes[0];
- register hole_descriptor *next_hole;
- register POINTER end; /* First address after hole */
- unsigned int space_regained = 0;
-
- while (holes) /* While there are holes */
- {
- /* Find the first block after this hole. */
- end = this_hole->address + this_hole->size;
- while (this_ptr && this_ptr->block != end)
- this_ptr = this_ptr->next;
-
- if (! this_ptr)
- abort ();
-
- next_hole = this_hole + 1;
- last_to_move = first_to_move = this_ptr;
- this_ptr = this_ptr->next;
-
- /* Note all blocks located before the next hole. */
- while (this_ptr && this_ptr->block < next_hole->address)
- {
- last_to_move = this_ptr;
- this_ptr = this_ptr->next;
- }
- space_regained +=
- move_blocks_downward (first_to_move, last_to_move, this_hole->address);
-
- holes--;
- this_hole = next_hole;
- }
-
- return_space (space_regained);
-}
-
-/* Relocate the list elements from the beginning of the list up to and
- including UP_TO_THIS_PTR to the area beginning at FREE_SPACE, which is
- after all current blocks.
-
- First copy all the data, then adjust the pointers and reorganize
- the list. NOTE that this *only* works for contiguous blocks. */
-
-static unsigned int
-relocate_to_end (up_to_this_ptr, free_space)
- register relocatable_pointer *up_to_this_ptr;
- POINTER free_space;
-{
- register relocatable_pointer *this_ptr;
- POINTER block_start = pointer_list->block;
- POINTER block_end = up_to_this_ptr->block + up_to_this_ptr->size;
- unsigned int total_size = block_end - block_start;
- unsigned int offset = (int) (free_space - block_start);
-
- bcopy (block_start, free_space, total_size);
- for (this_ptr = up_to_this_ptr; this_ptr; this_ptr = this_ptr->prev)
- {
- struct other_pointer *op = this_ptr->others;
-
- *this_ptr->location += offset;
- this_ptr->block += offset;
-
- while (op != (struct other_pointer *) 0)
- {
- *op->location += offset;
- op = op->next;
- }
- }
-
- /* Connect the head to the tail. */
- last_pointer->next = pointer_list;
- pointer_list->prev = last_pointer;
-
- /* Disconnect */
- up_to_this_ptr->next->prev = REL_NIL;
- pointer_list = up_to_this_ptr->next;
- up_to_this_ptr->next = REL_NIL;
- last_pointer = up_to_this_ptr;
-
- return total_size; /* of space relocated. */
-}
-
-/* Relocate the list elements from FROM_THIS_PTR to (and including)
- the last to the zone beginning at FREE_SPACE, which is located
- before any blocks.
-
- First copy all the data, then adjust the pointers and reorganize
- the list. NOTE that this *only* works for contiguous blocks. */
-
-static unsigned int
-relocate_to_beginning (from_this_ptr, free_space)
- register relocatable_pointer *from_this_ptr;
- POINTER free_space;
-{
- POINTER block_start = from_this_ptr->block;
- POINTER block_end = last_pointer->block + last_pointer->size;
- unsigned int total_size = (int) (block_end - block_start);
- unsigned int offset = (int) (from_this_ptr->block - free_space);
- register relocatable_pointer *this_ptr;
-
- bcopy (block_start, free_space, total_size);
- for (this_ptr = from_this_ptr; this_ptr; this_ptr = this_ptr->next)
- {
- struct other_pointer *op = this_ptr->others;
-
- *this_ptr->location -= offset;
- this_ptr->block -= offset;
-
- while (op != (struct other_pointer *) 0)
- {
- *op->location -= offset;
- op = op->next;
- }
- }
-
- /* Connect the end to the beginning. */
- last_pointer->next = pointer_list;
- pointer_list->prev = last_pointer;
-
- /* Disconnect and reset first and last. */
- from_this_ptr->prev->next = REL_NIL;
- last_pointer = from_this_ptr->prev;
- pointer_list = from_this_ptr;
- pointer_list->prev = REL_NIL;
-
- return total_size; /* of space moved. */
-}
-
-/* Relocate any blocks neccessary, either upwards or downwards,
- to obtain a space of SIZE bytes. Assumes we have at least one block. */
-
-static unsigned int
-relocate (size)
- register int size;
-{
- register relocatable_pointer *ptr;
- register int got = 0;
-
- if (size > 0) /* Up: Relocate enough blocs to get SIZE. */
- {
- register POINTER new_space;
-
- for (ptr = pointer_list; got < size && ptr; ptr = ptr->next)
- got += ptr->size;
-
- if (ptr == REL_NIL)
- ptr = last_pointer;
-
- new_space = get_more_space (size);
- if (!new_space)
- return 0;
-
- return (relocate_to_end (ptr, pointer_list->block + size));
- }
-
- if (size < 0) /* Down: relocate as many blocs as will
- fit in SIZE bytes of space. */
- {
- register POINTER to_zone;
- unsigned int moved;
-
- for (ptr = last_pointer; got >= size && ptr; ptr = ptr->prev)
- got -= ptr->size;
-
- if (ptr == REL_NIL)
- ptr = pointer_list;
- else
- {
- /* Back off one block to be <= size */
- got += ptr->size;
- ptr = ptr->next;
- }
-
- if (got >= size)
- {
- to_zone = virtual_break_value - size + got;
- moved = relocate_to_beginning (ptr, to_zone);
- if (moved)
- return_space (moved);
-
- return moved;
- }
-
- return 0;
- }
-
- abort ();
-}
-
-/* This function encapsulates `sbrk' to preserve the relocatable blocks.
- It is called just like `sbrk'. When relocatable blocks are in use,
- `malloc' must use this function instead of `sbrk'. */
-
-POINTER
-r_alloc_sbrk (size)
- unsigned int size;
-{
- POINTER new_zone; /* Start of the zone we will return. */
-
-#if 0
- if (! r_alloc_in_use)
- return (POINTER) sbrk (size);
-#endif
-
- if (size == 0)
- return virtual_break_value;
-
- if (size > 0) /* Get more space */
- {
- register unsigned int space;
-
- if (pointer_list == REL_NIL)
- {
- POINTER space = get_more_space (size);
-
- virtual_break_value = real_break_value;
- return space;
- }
-
- new_zone = virtual_break_value;
-
- /* Check if there is a hole just before the buffer zone. */
- if (holes && r_alloc_holes[0].address == virtual_break_value)
- {
- if (r_alloc_holes[0].size > size)
- {
- /* Adjust the hole size. */
- r_alloc_holes[0].size -= size;
- r_alloc_holes[0].address += size;
- virtual_break_value += size;
-
- return new_zone;
- }
-
- if (r_alloc_holes[0].size == size)
- {
- virtual_break_value += size;
- delete_hole (0);
-
- return new_zone;
- }
-
- /* Adjust the size requested by space
- already available in this hole. */
- size -= r_alloc_holes[0].size;
- virtual_break_value += r_alloc_holes[0].size;
- delete_hole (0);
- }
-
- space = relocate (size);
- if (!space)
- return (POINTER) -1;
-
-#ifdef REL_ALLOC_SAVE_SPACE
- move_blocks_downward
-#else
- bzero (new_zone, space);
- if (space > size)
- note_hole (new_zone + size, space - size);
-#endif /* REL_ALLOC_SAVE_SPACE */
-
- virtual_break_value += size;
- return new_zone;
- }
- else /* Return space to system */
- {
- int moved;
- int left_over;
- POINTER old_break_value;
-
- if (pointer_list == REL_NIL)
- {
- POINTER space = return_space (-size);
- virtual_break_value = real_break_value;
-
- return space;
- }
-
- if (holes && r_alloc_holes[0].address == virtual_break_value)
- {
- size -= r_alloc_holes[0].size;
- delete_hole (0);
- }
-
- moved = relocate (size);
- old_break_value = virtual_break_value;
-
- if (!moved)
- return (POINTER) -1;
-
- left_over = moved + size;
- virtual_break_value += size;
-
- if (left_over)
- {
-#ifdef REL_ALLOC_SAVE_SPACE
- move_blocks_downward
-#else
- bzero (virtual_break_value, left_over);
- note_hole (virtual_break_value, left_over);
-#endif /* not REL_ALLOC_SAVE_SPACE */
- }
-
- return old_break_value;
- }
-}
-
-/* For debugging */
-
-#include <stdio.h>
-
-void
-memory_trace ()
-{
- relocatable_pointer *ptr;
- int i;
-
- fprintf (stderr, "virtual: 0x%x\n real: 0x%x\n true: 0x%x\n\n",
- virtual_break_value, real_break_value, true_break_value);
- fprintf (stderr, "Blocks:\n");
- for (ptr = pointer_list; ptr; ptr = ptr->next)
- {
- fprintf (stderr, " address: 0x%x\n", ptr->block);
- fprintf (stderr, " size: 0x%x\n", ptr->size);
- if (ptr->others)
- {
- struct other_pointer *op = ptr->others;
- fprintf (stderr, " others:", ptr->size);
- while (op)
- {
- fprintf (stderr, " 0x%x", op->location);
- op = op->next;
- }
- fprintf (stderr, "\n");
- }
- }
-
- if (holes)
- {
- fprintf (stderr, "\nHoles:\n");
- for (i = 0; i < holes; i++)
- {
- fprintf (stderr, " address: 0x%x\n", r_alloc_holes[i].address);
- fprintf (stderr, " size: 0x%x\n", r_alloc_holes[i].size);
- }
- }
-
- fprintf (stderr, "\n\n");
-}
diff --git a/src/param.h b/src/param.h
new file mode 100644
index 00000000000..1b27b50a276
--- /dev/null
+++ b/src/param.h
@@ -0,0 +1,2 @@
+/* This is so that Emacs can run on VMS... */
+#define EXEC_PAGESIZE 512
diff --git a/src/paths.h-dist b/src/paths.h-dist
new file mode 100644
index 00000000000..4ecb446dd92
--- /dev/null
+++ b/src/paths.h-dist
@@ -0,0 +1,19 @@
+/* The default search path for Lisp function "load".
+ This sets load-path. */
+#define PATH_LOADSEARCH "/usr/local/emacs/lisp"
+
+/* the extra search path for programs to invoke.
+ This is appended to whatever the PATH environment variable says
+ to set the Lisp variable exec-path and the first file namein it
+ sets the Lisp variable exec-directory. */
+#define PATH_EXEC "/usr/local/emacs/etc"
+
+/* the name of the directory that contains lock files
+ with which we record what files are being modified in Emacs.
+ This directory should be writable by everyone.
+ THE STRING MUST END WITH A SLASH!!! */
+#define PATH_LOCK "/usr/local/emacs/lock/"
+
+/* the name of the file !!!SuperLock!!! in the directory
+ specified by PATH_LOCK. Yes, this is redundant. */
+#define PATH_SUPERLOCK "/usr/local/emacs/lock/!!!SuperLock!!!"
diff --git a/src/pre-crt0.c b/src/pre-crt0.c
new file mode 100644
index 00000000000..67fd31cd6ac
--- /dev/null
+++ b/src/pre-crt0.c
@@ -0,0 +1,9 @@
+/* This file is loaded before crt0.o on machines where we do not
+ remap part of the data space into text space in unexec.
+ On these machines, there is no problem with standard crt0.o's
+ that make environ an initialized variable. However, we do
+ need to make sure the label data_start exists anyway. */
+
+/* Create a label to appear at the beginning of data space. */
+
+int data_start = 0;
diff --git a/src/precomp.com b/src/precomp.com
new file mode 100644
index 00000000000..aaca1d68e16
--- /dev/null
+++ b/src/precomp.com
@@ -0,0 +1,6 @@
+$ ! VMS command file to define the `ccom' command
+$ ! that is the only way to compile Emacs C source files.
+$
+$ define /nolog vaxc$include sys$library, sys$disk:[]
+$ define /nolog sys vaxc$include
+$ ccom :== @ccom
diff --git a/src/print.c b/src/print.c
new file mode 100644
index 00000000000..7144941b643
--- /dev/null
+++ b/src/print.c
@@ -0,0 +1,706 @@
+/* Lisp object printing and output streams.
+ Copyright (C) 1985, 1986, 1990 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#include "config.h"
+#include <stdio.h>
+#undef NULL
+#include "lisp.h"
+
+#ifndef standalone
+#include "buffer.h"
+#include "window.h"
+#include "process.h"
+#include "dispextern.h"
+#include "termchar.h"
+#endif /* not standalone */
+
+Lisp_Object Vstandard_output, Qstandard_output;
+
+/* Avoid actual stack overflow in print. */
+int print_depth;
+
+/* Maximum length of list to print in full; noninteger means
+ effectively infinity */
+
+Lisp_Object Vprint_length;
+
+/* Nonzero means print newlines in strings as \n. */
+
+int print_escape_newlines;
+
+/* Nonzero means print newline before next minibuffer message.
+ Defined in xdisp.c */
+
+extern int noninteractive_need_newline;
+#ifdef MAX_PRINT_CHARS
+static int print_chars;
+static int max_print;
+#endif /* MAX_PRINT_CHARS */
+
+/* Low level output routines for charaters and strings */
+
+/* Lisp functions to do output using a stream
+ must have the stream in a variable called printcharfun
+ and must start with PRINTPREPARE and end with PRINTFINISH.
+ Use PRINTCHAR to output one character,
+ or call strout to output a block of characters.
+ Also, each one must have the declarations
+ struct buffer *old = current_buffer;
+ int old_point = -1, start_point;
+ Lisp_Object original;
+*/
+
+#define PRINTPREPARE \
+ original = printcharfun; \
+ if (NULL (printcharfun)) printcharfun = Qt; \
+ if (XTYPE (printcharfun) == Lisp_Buffer) \
+ { if (XBUFFER (printcharfun) != current_buffer) Fset_buffer (printcharfun); \
+ printcharfun = Qnil;}\
+ if (XTYPE (printcharfun) == Lisp_Marker) \
+ { if (XMARKER (original)->buffer != current_buffer) \
+ set_buffer_internal (XMARKER (original)->buffer); \
+ old_point = point; \
+ SET_PT (marker_position (printcharfun)); \
+ start_point = point; \
+ printcharfun = Qnil;}
+
+#define PRINTFINISH \
+ if (XTYPE (original) == Lisp_Marker) \
+ Fset_marker (original, make_number (point), Qnil); \
+ if (old_point >= 0) \
+ SET_PT ((old_point >= start_point ? point - start_point : 0) + old_point); \
+ if (old != current_buffer) \
+ set_buffer_internal (old)
+
+#define PRINTCHAR(ch) printchar (ch, printcharfun)
+
+/* Index of first unused element of message_buf. */
+static int printbufidx;
+
+static void
+printchar (ch, fun)
+ unsigned char ch;
+ Lisp_Object fun;
+{
+ Lisp_Object ch1;
+
+#ifdef MAX_PRINT_CHARS
+ if (max_print)
+ print_chars++;
+#endif /* MAX_PRINT_CHARS */
+#ifndef standalone
+ if (EQ (fun, Qnil))
+ {
+ QUIT;
+ insert (&ch, 1);
+ return;
+ }
+ if (EQ (fun, Qt))
+ {
+ if (noninteractive)
+ {
+ putchar (ch);
+ noninteractive_need_newline = 1;
+ return;
+ }
+ if (echo_area_contents != message_buf || !message_buf_print)
+ {
+ echo_area_contents = message_buf;
+ printbufidx = 0;
+ message_buf_print = 1;
+ }
+ if (printbufidx < screen_width)
+ message_buf[printbufidx++] = ch;
+ message_buf[printbufidx] = 0;
+ return;
+ }
+#endif /* not standalone */
+
+ XFASTINT (ch1) = ch;
+ call1 (fun, ch1);
+}
+
+static void
+strout (ptr, size, printcharfun)
+ char *ptr;
+ int size;
+ Lisp_Object printcharfun;
+{
+ int i = 0;
+
+ if (EQ (printcharfun, Qnil))
+ {
+ insert (ptr, size >= 0 ? size : strlen (ptr));
+#ifdef MAX_PRINT_CHARS
+ if (max_print)
+ print_chars += size >= 0 ? size : strlen(ptr);
+#endif /* MAX_PRINT_CHARS */
+ return;
+ }
+ if (EQ (printcharfun, Qt))
+ {
+ i = size >= 0 ? size : strlen (ptr);
+#ifdef MAX_PRINT_CHARS
+ if (max_print)
+ print_chars += i;
+#endif /* MAX_PRINT_CHARS */
+ if (noninteractive)
+ {
+ fwrite (ptr, 1, i, stdout);
+ noninteractive_need_newline = 1;
+ return;
+ }
+ if (echo_area_contents != message_buf || !message_buf_print)
+ {
+ echo_area_contents = message_buf;
+ printbufidx = 0;
+ message_buf_print = 1;
+ }
+ if (i > screen_width - printbufidx)
+ i = screen_width - printbufidx;
+ bcopy (ptr, &message_buf[printbufidx], i);
+ printbufidx += i;
+ message_buf[printbufidx] = 0;
+ return;
+ }
+ if (size >= 0)
+ while (i < size)
+ PRINTCHAR (ptr[i++]);
+ else
+ while (ptr[i])
+ PRINTCHAR (ptr[i++]);
+}
+
+DEFUN ("write-char", Fwrite_char, Swrite_char, 1, 2, 0,
+ "Output character CHAR to stream STREAM.\n\
+STREAM defaults to the value of `standard-output' (which see).")
+ (ch, printcharfun)
+ Lisp_Object ch, printcharfun;
+{
+ struct buffer *old = current_buffer;
+ int old_point = -1;
+ int start_point;
+ Lisp_Object original;
+
+ if (NULL (printcharfun))
+ printcharfun = Vstandard_output;
+ CHECK_NUMBER (ch, 0);
+ PRINTPREPARE;
+ PRINTCHAR (XINT (ch));
+ PRINTFINISH;
+ return ch;
+}
+
+write_string (data, size)
+ char *data;
+ int size;
+{
+ struct buffer *old = current_buffer;
+ Lisp_Object printcharfun;
+ int old_point = -1;
+ int start_point;
+ Lisp_Object original;
+
+ printcharfun = Vstandard_output;
+
+ PRINTPREPARE;
+ strout (data, size, printcharfun);
+ PRINTFINISH;
+}
+
+write_string_1 (data, size, printcharfun)
+ char *data;
+ int size;
+ Lisp_Object printcharfun;
+{
+ struct buffer *old = current_buffer;
+ int old_point = -1;
+ int start_point;
+ Lisp_Object original;
+
+ PRINTPREPARE;
+ strout (data, size, printcharfun);
+ PRINTFINISH;
+}
+
+
+#ifndef standalone
+
+temp_output_buffer_setup (bufname)
+ char *bufname;
+{
+ register struct buffer *old = current_buffer;
+ register Lisp_Object buf;
+
+ Fset_buffer (Fget_buffer_create (build_string (bufname)));
+
+ current_buffer->read_only = Qnil;
+ Ferase_buffer ();
+
+ XSET (buf, Lisp_Buffer, current_buffer);
+ specbind (Qstandard_output, buf);
+
+ set_buffer_internal (old);
+}
+
+Lisp_Object
+internal_with_output_to_temp_buffer (bufname, function, args)
+ char *bufname;
+ Lisp_Object (*function) ();
+ Lisp_Object args;
+{
+ int count = specpdl_ptr - specpdl;
+ Lisp_Object buf, val;
+
+ record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
+ temp_output_buffer_setup (bufname);
+ buf = Vstandard_output;
+
+ val = (*function) (args);
+
+ temp_output_buffer_show (buf);
+
+ unbind_to (count);
+ return val;
+}
+
+DEFUN ("with-output-to-temp-buffer", Fwith_output_to_temp_buffer, Swith_output_to_temp_buffer,
+ 1, UNEVALLED, 0,
+ "Binding `standard-output' to buffer named BUFNAME, execute BODY then display that buffer.\n\
+The buffer is cleared out initially, and marked as unmodified when done.\n\
+All output done by BODY is inserted in that buffer by default.\n\
+It is displayed in another window, but not selected.\n\
+The value of the last form in BODY is returned.\n\
+If variable `temp-buffer-show-hook' is non-nil, call it at the end\n\
+to get the buffer displayed. It gets one argument, the buffer to display.")
+ (args)
+ Lisp_Object args;
+{
+ struct gcpro gcpro1;
+ Lisp_Object name;
+ int count = specpdl_ptr - specpdl;
+ Lisp_Object buf, val;
+
+ GCPRO1(args);
+ name = Feval (Fcar (args));
+ UNGCPRO;
+
+ CHECK_STRING (name, 0);
+ temp_output_buffer_setup (XSTRING (name)->data);
+ buf = Vstandard_output;
+
+ val = Fprogn (Fcdr (args));
+
+ temp_output_buffer_show (buf);
+
+ unbind_to (count);
+ return val;
+}
+#endif /* not standalone */
+
+static void print ();
+
+DEFUN ("terpri", Fterpri, Sterpri, 0, 1, 0,
+ "Output a newline to STREAM (or value of standard-output).")
+ (printcharfun)
+ Lisp_Object printcharfun;
+{
+ struct buffer *old = current_buffer;
+ int old_point = -1;
+ int start_point;
+ Lisp_Object original;
+
+ if (NULL (printcharfun))
+ printcharfun = Vstandard_output;
+ PRINTPREPARE;
+ PRINTCHAR ('\n');
+ PRINTFINISH;
+ return Qt;
+}
+
+DEFUN ("prin1", Fprin1, Sprin1, 1, 2, 0,
+ "Output the printed representation of OBJECT, any Lisp object.\n\
+Quoting characters are printed when needed to make output that `read'\n\
+can handle, whenever this is possible.\n\
+Output stream is STREAM, or value of `standard-output' (which see).")
+ (obj, printcharfun)
+ Lisp_Object obj, printcharfun;
+{
+ struct buffer *old = current_buffer;
+ int old_point = -1;
+ int start_point;
+ Lisp_Object original;
+
+#ifdef MAX_PRINT_CHARS
+ max_print = 0;
+#endif /* MAX_PRINT_CHARS */
+ if (NULL (printcharfun))
+ printcharfun = Vstandard_output;
+ PRINTPREPARE;
+ print_depth = 0;
+ print (obj, printcharfun, 1);
+ PRINTFINISH;
+ return obj;
+}
+
+/* a buffer which is used to hold output being built by prin1-to-string */
+Lisp_Object Vprin1_to_string_buffer;
+
+DEFUN ("prin1-to-string", Fprin1_to_string, Sprin1_to_string, 1, 1, 0,
+ "Return a string containing the printed representation of OBJECT,\n\
+any Lisp object. Quoting characters are used when needed to make output\n\
+that `read' can handle, whenever this is possible.")
+ (obj)
+ Lisp_Object obj;
+{
+ struct buffer *old = current_buffer;
+ int old_point = -1;
+ int start_point;
+ Lisp_Object original, printcharfun;
+ struct gcpro gcpro1;
+
+ printcharfun = Vprin1_to_string_buffer;
+ PRINTPREPARE;
+ print_depth = 0;
+ print (obj, printcharfun, 1);
+ /* Make Vprin1_to_string_buffer be the default buffer after PRINTFINSH */
+ PRINTFINISH;
+ set_buffer_internal (XBUFFER (Vprin1_to_string_buffer));
+ obj = Fbuffer_string ();
+ GCPRO1 (obj);
+ Ferase_buffer ();
+ set_buffer_internal (old);
+ UNGCPRO;
+ return obj;
+}
+
+DEFUN ("princ", Fprinc, Sprinc, 1, 2, 0,
+ "Output the printed representation of OBJECT, any Lisp object.\n\
+No quoting characters are used; no delimiters are printed around\n\
+the contents of strings.\n\
+Output stream is STREAM, or value of standard-output (which see).")
+ (obj, printcharfun)
+ Lisp_Object obj, printcharfun;
+{
+ struct buffer *old = current_buffer;
+ int old_point = -1;
+ int start_point;
+ Lisp_Object original;
+
+ if (NULL (printcharfun))
+ printcharfun = Vstandard_output;
+ PRINTPREPARE;
+ print_depth = 0;
+ print (obj, printcharfun, 0);
+ PRINTFINISH;
+ return obj;
+}
+
+DEFUN ("print", Fprint, Sprint, 1, 2, 0,
+ "Output the printed representation of OBJECT, with newlines around it.\n\
+Quoting characters are printed when needed to make output that `read'\n\
+can handle, whenever this is possible.\n\
+Output stream is STREAM, or value of `standard-output' (which see).")
+ (obj, printcharfun)
+ Lisp_Object obj, printcharfun;
+{
+ struct buffer *old = current_buffer;
+ int old_point = -1;
+ int start_point;
+ Lisp_Object original;
+ struct gcpro gcpro1;
+
+#ifdef MAX_PRINT_CHARS
+ print_chars = 0;
+ max_print = MAX_PRINT_CHARS;
+#endif /* MAX_PRINT_CHARS */
+ if (NULL (printcharfun))
+ printcharfun = Vstandard_output;
+ GCPRO1 (obj);
+ PRINTPREPARE;
+ print_depth = 0;
+ PRINTCHAR ('\n');
+ print (obj, printcharfun, 1);
+ PRINTCHAR ('\n');
+ PRINTFINISH;
+#ifdef MAX_PRINT_CHARS
+ max_print = 0;
+ print_chars = 0;
+#endif /* MAX_PRINT_CHARS */
+ UNGCPRO;
+ return obj;
+}
+
+static void
+print (obj, printcharfun, escapeflag)
+#ifndef RTPC_REGISTER_BUG
+ register Lisp_Object obj;
+#else
+ Lisp_Object obj;
+#endif
+ register Lisp_Object printcharfun;
+ int escapeflag;
+{
+ char buf[30];
+
+ QUIT;
+
+ print_depth++;
+ if (print_depth > 200)
+ error ("Apparently circular structure being printed");
+#ifdef MAX_PRINT_CHARS
+ if (max_print && print_chars > max_print)
+ {
+ PRINTCHAR ('\n');
+ print_chars = 0;
+ }
+#endif /* MAX_PRINT_CHARS */
+
+#ifdef SWITCH_ENUM_BUG
+ switch ((int) XTYPE (obj))
+#else
+ switch (XTYPE (obj))
+#endif
+ {
+ default:
+ /* We're in trouble if this happens!
+ Probably should just abort () */
+ strout ("#<EMACS BUG: INVALID DATATYPE ", -1, printcharfun);
+ sprintf (buf, "(#o%3o)", (int) XTYPE (obj));
+ strout (buf, -1, printcharfun);
+ strout (" Save your buffers immediately and please report this bug>",
+ -1, printcharfun);
+ break;
+
+ case Lisp_Int:
+ sprintf (buf, "%d", XINT (obj));
+ strout (buf, -1, printcharfun);
+ break;
+
+ case Lisp_String:
+ if (!escapeflag)
+ strout (XSTRING (obj)->data, XSTRING (obj)->size, printcharfun);
+ else
+ {
+ register int i;
+ register unsigned char *p = XSTRING (obj)->data;
+ register unsigned char c;
+
+ PRINTCHAR ('\"');
+ for (i = XSTRING (obj)->size; i > 0; i--)
+ {
+ QUIT;
+ c = *p++;
+ if (c == '\n' && print_escape_newlines)
+ {
+ PRINTCHAR ('\\');
+ PRINTCHAR ('n');
+ }
+ else
+ {
+ if (c == '\"' || c == '\\')
+ PRINTCHAR ('\\');
+ PRINTCHAR (c);
+ }
+ }
+ PRINTCHAR ('\"');
+ }
+ break;
+
+ case Lisp_Symbol:
+ {
+ register int confusing;
+ register unsigned char *p = XSYMBOL (obj)->name->data;
+ register unsigned char *end = p + XSYMBOL (obj)->name->size;
+ register unsigned char c;
+
+ if (p != end && (*p == '-' || *p == '+')) p++;
+ if (p == end)
+ confusing = 0;
+ else
+ {
+ while (p != end && *p >= '0' && *p <= '9')
+ p++;
+ confusing = (end == p);
+ }
+
+ p = XSYMBOL (obj)->name->data;
+ while (p != end)
+ {
+ QUIT;
+ c = *p++;
+ if (escapeflag)
+ {
+ if (c == '\"' || c == '\\' || c == '\'' || c == ';' || c == '#' ||
+ c == '(' || c == ')' || c == ',' || c =='.' || c == '`' ||
+ c == '[' || c == ']' || c == '?' || c <= 040 || confusing)
+ PRINTCHAR ('\\'), confusing = 0;
+ }
+ PRINTCHAR (c);
+ }
+ }
+ break;
+
+ case Lisp_Cons:
+ PRINTCHAR ('(');
+ {
+ register int i = 0;
+ register int max = 0;
+
+ if (XTYPE (Vprint_length) == Lisp_Int)
+ max = XINT (Vprint_length);
+ while (CONSP (obj))
+ {
+ if (i++)
+ PRINTCHAR (' ');
+ if (max && i > max)
+ {
+ strout ("...", 3, printcharfun);
+ break;
+ }
+ print (Fcar (obj), printcharfun, escapeflag);
+ obj = Fcdr (obj);
+ }
+ }
+ if (!NULL (obj) && !CONSP (obj))
+ {
+ strout (" . ", 3, printcharfun);
+ print (obj, printcharfun, escapeflag);
+ }
+ PRINTCHAR (')');
+ break;
+
+ case Lisp_Vector:
+ PRINTCHAR ('[');
+ {
+ register int i;
+ register Lisp_Object tem;
+ for (i = 0; i < XVECTOR (obj)->size; i++)
+ {
+ if (i) PRINTCHAR (' ');
+ tem = XVECTOR (obj)->contents[i];
+ print (tem, printcharfun, escapeflag);
+ }
+ }
+ PRINTCHAR (']');
+ break;
+
+#ifndef standalone
+ case Lisp_Buffer:
+ if (NULL (XBUFFER (obj)->name))
+ strout ("#<killed buffer>", -1, printcharfun);
+ else if (escapeflag)
+ {
+ strout ("#<buffer ", -1, printcharfun);
+ strout (XSTRING (XBUFFER (obj)->name)->data, -1, printcharfun);
+ PRINTCHAR ('>');
+ }
+ else
+ strout (XSTRING (XBUFFER (obj)->name)->data, -1, printcharfun);
+ break;
+
+ case Lisp_Process:
+ if (escapeflag)
+ {
+ strout ("#<process ", -1, printcharfun);
+ strout (XSTRING (XPROCESS (obj)->name)->data, -1, printcharfun);
+ PRINTCHAR ('>');
+ }
+ else
+ strout (XSTRING (XPROCESS (obj)->name)->data, -1, printcharfun);
+ break;
+
+ case Lisp_Window:
+ strout ("#<window ", -1, printcharfun);
+ sprintf (buf, "%d", XFASTINT (XWINDOW (obj)->sequence_number));
+ strout (buf, -1, printcharfun);
+ if (!NULL (XWINDOW (obj)->buffer))
+ {
+ unsigned char *p = XSTRING (XBUFFER (XWINDOW (obj)->buffer)->name)->data;
+ strout (" on ", -1, printcharfun);
+ strout (p, -1, printcharfun);
+ }
+ PRINTCHAR ('>');
+ break;
+
+ case Lisp_Window_Configuration:
+ strout ("#<window-configuration>", -1, printcharfun);
+ break;
+
+ case Lisp_Marker:
+ strout ("#<marker ", -1, printcharfun);
+ if (!(XMARKER (obj)->buffer))
+ strout ("in no buffer", -1, printcharfun);
+ else
+ {
+ sprintf (buf, "at %d", marker_position (obj));
+ strout (buf, -1, printcharfun);
+ strout (" in ", -1, printcharfun);
+ strout (XSTRING (XMARKER (obj)->buffer->name)->data, -1, printcharfun);
+ }
+ PRINTCHAR ('>');
+ break;
+#endif /* standalone */
+
+ case Lisp_Subr:
+ strout ("#<subr ", -1, printcharfun);
+ strout (XSUBR (obj)->symbol_name, -1, printcharfun);
+ PRINTCHAR ('>');
+ break;
+ }
+
+ print_depth--;
+}
+
+void
+syms_of_print ()
+{
+ DEFVAR_LISP ("standard-output", &Vstandard_output,
+ "Function print uses by default for outputting a character.\n\
+This may be any function of one argument.\n\
+It may also be a buffer (output is inserted before point)\n\
+or a marker (output is inserted and the marker is advanced)\n\
+or the symbol t (output appears in the minibuffer line).");
+ Vstandard_output = Qt;
+ Qstandard_output = intern ("standard-output");
+ staticpro (&Qstandard_output);
+
+ DEFVAR_LISP ("print-length", &Vprint_length,
+ "Maximum length of list to print before abbreviating.\
+`nil' means no limit.");
+ Vprint_length = Qnil;
+
+ DEFVAR_BOOL ("print-escape-newlines", &print_escape_newlines,
+ "Non-nil means print newlines in strings as backslash-n.");
+ print_escape_newlines = 0;
+
+ /* prin1_to_string_buffer initialized in init_buffer_once in buffer.c */
+ staticpro (&Vprin1_to_string_buffer);
+
+ defsubr (&Sprin1);
+ defsubr (&Sprin1_to_string);
+ defsubr (&Sprinc);
+ defsubr (&Sprint);
+ defsubr (&Sterpri);
+ defsubr (&Swrite_char);
+#ifndef standalone
+ defsubr (&Swith_output_to_temp_buffer);
+#endif /* not standalone */
+}
diff --git a/src/process.c b/src/process.c
new file mode 100644
index 00000000000..d968d5aa589
--- /dev/null
+++ b/src/process.c
@@ -0,0 +1,2769 @@
+/* Asynchronous subprocess control for GNU Emacs.
+ Copyright (C) 1985, 1986, 1987, 1988, 1990 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* This must precede sys/signal.h on certain machines. */
+#include <sys/types.h>
+#include <signal.h>
+
+#include "config.h"
+
+#ifdef VMS
+/* Prevent the file from being totally empty. */
+static dummy () {}
+#endif
+
+#ifdef subprocesses
+/* The entire file is within this conditional */
+
+#include <stdio.h>
+#include <errno.h>
+#include <setjmp.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+
+#ifdef HAVE_SOCKETS /* TCP connection support, if kernel can do it */
+#include <sys/socket.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#endif /* HAVE_SOCKETS */
+
+#if defined(BSD) || defined(STRIDE)
+#include <sys/ioctl.h>
+#if !defined (O_NDELAY) && defined (HAVE_PTYS)
+#include <fcntl.h>
+#endif /* HAVE_PTYS and no O_NDELAY */
+#endif /* BSD or STRIDE */
+#ifdef USG
+#ifndef NO_TERMIO
+#include <termio.h>
+#endif
+#include <fcntl.h>
+#endif /* USG */
+
+#ifdef NEED_BSDTTY
+#include <sys/bsdtty.h>
+#endif
+
+#ifdef NEED_TERMIOS
+#include <sys/termios.h>
+#endif
+
+#ifdef TRITON88 /* To make emacs send C-c correctly in shell */
+#define TIOCGPGRP FIOGETOWN
+#endif
+
+#ifdef HPUX
+#undef TIOCGPGRP
+#endif
+
+/* Include time.h or sys/time.h or both. */
+#include "gettime.h"
+
+#if defined (HPUX) && defined (HAVE_PTYS)
+#include <sys/ptyio.h>
+#endif
+
+#ifdef AIX
+#include <sys/pty.h>
+#include <unistd.h>
+#endif /* AIX */
+
+#ifdef SYSV_PTYS
+#include <sys/tty.h>
+#include <sys/pty.h>
+#endif
+
+#ifdef XENIX
+#undef TIOCGETC /* Avoid confusing some conditionals that test this. */
+#endif
+
+#ifdef BROKEN_TIOCGETC
+#undef TIOCGETC
+#endif
+
+#ifdef BROKEN_O_NONBLOCK
+#undef O_NONBLOCK
+#endif
+
+#undef NULL
+#include "lisp.h"
+#include "window.h"
+#include "buffer.h"
+#include "process.h"
+#include "termhooks.h"
+#include "termopts.h"
+#include "commands.h"
+#include "dispextern.h"
+
+Lisp_Object Qrun, Qstop, Qsignal, Qopen, Qclosed;
+extern Lisp_Object Qexit;
+
+/* a process object is a network connection when its childp field is neither
+ Qt nor Qnil but is instead a string (name of foreign host we
+ are connected to + name of port we are connected to) */
+
+#ifdef HAVE_SOCKETS
+#define NETCONN_P(p) (XGCTYPE (XPROCESS (p)->childp) == Lisp_String)
+#else
+#define NETCONN_P(p) 0
+#endif /* HAVE_SOCKETS */
+
+/* Define SIGCHLD as an alias for SIGCLD. There are many conditionals
+ testing SIGCHLD. */
+
+#if !defined (SIGCHLD) && defined (SIGCLD)
+#define SIGCHLD SIGCLD
+#endif /* SIGCLD */
+
+#include "emacssignal.h"
+
+/* Define the structure that the wait system call stores.
+ On many systems, there is a structure defined for this.
+ But on vanilla-ish USG systems there is not. */
+
+#ifndef WAITTYPE
+#if !defined (BSD) && !defined (UNIPLUS) && !defined (STRIDE) && !(defined (HPUX) && !defined (NOMULTIPLEJOBS)) && !defined (HAVE_WAIT_HEADER)
+#define WAITTYPE int
+#define WIFSTOPPED(w) ((w&0377) == 0177)
+#define WIFSIGNALED(w) ((w&0377) != 0177 && (w&~0377) == 0)
+#define WIFEXITED(w) ((w&0377) == 0)
+#define WRETCODE(w) (w >> 8)
+#define WSTOPSIG(w) (w >> 8)
+#define WTERMSIG(w) (w & 0377)
+#ifndef WCOREDUMP
+#define WCOREDUMP(w) ((w&0200) != 0)
+#endif
+#else
+#ifdef BSD4_1
+#include <wait.h>
+#else
+#include <sys/wait.h>
+#endif /* not BSD 4.1 */
+
+#define WAITTYPE union wait
+#define WRETCODE(w) w.w_retcode
+#define WCOREDUMP(w) w.w_coredump
+
+#ifdef HPUX
+/* HPUX version 7 has broken definitions of these. */
+#undef WTERMSIG
+#undef WSTOPSIG
+#undef WIFSTOPPED
+#undef WIFSIGNALED
+#undef WIFEXITED
+#endif
+
+#ifndef WTERMSIG
+#define WTERMSIG(w) w.w_termsig
+#endif
+#ifndef WSTOPSIG
+#define WSTOPSIG(w) w.w_stopsig
+#endif
+#ifndef WIFSTOPPED
+#define WIFSTOPPED(w) (WTERMSIG (w) == 0177)
+#endif
+#ifndef WIFSIGNALED
+#define WIFSIGNALED(w) (WTERMSIG (w) != 0177 && (WSTOPSIG (w)) == 0)
+#endif
+#ifndef WIFEXITED
+#define WIFEXITED(w) (WTERMSIG (w) == 0)
+#endif
+#endif /* BSD or UNIPLUS or STRIDE */
+#endif /* no WAITTYPE */
+
+extern errno;
+extern sys_nerr;
+extern char *sys_errlist[];
+
+#ifndef BSD4_1
+extern char *sys_siglist[];
+#else
+char *sys_siglist[] =
+ {
+ "bum signal!!",
+ "hangup",
+ "interrupt",
+ "quit",
+ "illegal instruction",
+ "trace trap",
+ "iot instruction",
+ "emt instruction",
+ "floating point exception",
+ "kill",
+ "bus error",
+ "segmentation violation",
+ "bad argument to system call",
+ "write on a pipe with no one to read it",
+ "alarm clock",
+ "software termination signal from kill",
+ "status signal",
+ "sendable stop signal not from tty",
+ "stop signal from tty",
+ "continue a stopped process",
+ "child status has changed",
+ "background read attempted from control tty",
+ "background write attempted from control tty",
+ "input record available at control tty",
+ "exceeded CPU time limit",
+ "exceeded file size limit"
+ };
+#endif
+
+#ifdef vipc
+
+#include "vipc.h"
+extern int comm_server;
+extern int net_listen_address;
+#endif /* vipc */
+
+/* Communicate exit status of synch process to callproc.c. */
+extern int synch_process_retcode;
+extern char *synch_process_death;
+
+/* t means use pty, nil means use a pipe,
+ maybe other values to come. */
+Lisp_Object Vprocess_connection_type;
+
+#ifdef SKTPAIR
+#ifndef HAVE_SOCKETS
+#include <sys/socket.h>
+#endif
+#endif /* SKTPAIR */
+
+/* Number of events of change of status of a process. */
+int process_tick;
+
+/* Number of events for which the user or sentinel has been notified. */
+int update_tick;
+
+int delete_exited_processes;
+
+#ifdef FD_SET
+/* We could get this from param.h, but better not to depend on finding that.
+ And better not to risk that it might define other symbols used in this
+ file. */
+#define MAXDESC 64
+#define SELECT_TYPE fd_set
+#else /* no FD_SET */
+#define MAXDESC 32
+#define SELECT_TYPE int
+
+/* Define the macros to access a single-int bitmap of descriptors. */
+#define FD_SET(n, p) (*(p) |= (1 << (n)))
+#define FD_CLR(n, p) (*(p) &= ~(1 << (n)))
+#define FD_ISSET(n, p) (*(p) & (1 << (n)))
+#define FD_ZERO(p) (*(p) = 0)
+#endif /* no FD_SET */
+
+/* Mask of bits indicating the descriptors that we wait for input on */
+
+SELECT_TYPE input_wait_mask;
+
+/* Indexed by descriptor, gives the process (if any) for that descriptor */
+Lisp_Object chan_process[MAXDESC];
+
+/* Alist of elements (NAME . PROCESS) */
+Lisp_Object Vprocess_alist;
+
+Lisp_Object Qprocessp;
+
+Lisp_Object get_process ();
+
+/* Buffered-ahead input char from process, indexed by channel.
+ -1 means empty (no char is buffered).
+ Used on sys V where the only way to tell if there is any
+ output from the process is to read at least one char.
+ Always -1 on systems that support FIONREAD. */
+
+int proc_buffered_char[MAXDESC];
+
+/* These variables hold the filter about to be run, and its args,
+ between read_process_output and run_filter.
+ Also used in exec_sentinel for sentinels. */
+Lisp_Object this_filter;
+Lisp_Object filter_process, filter_string;
+
+/* Compute the Lisp form of the process status, p->status,
+ from the numeric status that was returned by `wait'. */
+
+update_status (p)
+ struct Lisp_Process *p;
+{
+ union { int i; WAITTYPE wt; } u;
+ u.i = XFASTINT (p->raw_status_low) + (XFASTINT (p->raw_status_high) << 16);
+ p->status = status_convert (u.wt);
+ p->raw_status_low = Qnil;
+ p->raw_status_high = Qnil;
+}
+
+/* Convert a process status word in Unix format
+ to the list that we use internally. */
+
+Lisp_Object
+status_convert (w)
+ WAITTYPE w;
+{
+ if (WIFSTOPPED (w))
+ return Fcons (Qstop, Fcons (make_number (WSTOPSIG (w)), Qnil));
+ else if (WIFEXITED (w))
+ return Fcons (Qexit, Fcons (make_number (WRETCODE (w)),
+ WCOREDUMP (w) ? Qt : Qnil));
+ else if (WIFSIGNALED (w))
+ return Fcons (Qsignal, Fcons (make_number (WTERMSIG (w)),
+ WCOREDUMP (w) ? Qt : Qnil));
+ else
+ return Qrun;
+}
+
+/* Given a status-list, extract the three pieces of information
+ and store them individually through the three pointers. */
+
+void
+decode_status (l, symbol, code, coredump)
+ Lisp_Object l;
+ Lisp_Object *symbol;
+ int *code;
+ int *coredump;
+{
+ Lisp_Object tem;
+
+ if (XTYPE (l) == Lisp_Symbol)
+ {
+ *symbol = l;
+ *code = 0;
+ *coredump = 0;
+ }
+ else
+ {
+ *symbol = XCONS (l)->car;
+ tem = XCONS (l)->cdr;
+ *code = XFASTINT (XCONS (tem)->car);
+ tem = XFASTINT (XCONS (tem)->cdr);
+ *coredump = !NULL (tem);
+ }
+}
+
+/* Return a string describing a process status list. */
+
+Lisp_Object
+status_message (status)
+ Lisp_Object status;
+{
+ Lisp_Object symbol;
+ int code, coredump;
+ Lisp_Object string, string2;
+
+ decode_status (status, &symbol, &code, &coredump);
+
+ if (EQ (symbol, Qsignal) || EQ (symbol, Qstop))
+ {
+ string = build_string (code < NSIG ? sys_siglist[code] : "unknown");
+ string2 = build_string (coredump ? " (core dumped)\n" : "\n");
+ XSTRING (string)->data[0] = DOWNCASE (XSTRING (string)->data[0]);
+ return concat2 (string, string2);
+ }
+ else if (EQ (symbol, Qexit))
+ {
+ if (code == 0)
+ return build_string ("finished\n");
+ string = Fint_to_string (make_number (code));
+ string2 = build_string (coredump ? " (core dumped)\n" : "\n");
+ return concat2 (build_string ("exited abnormally with code "),
+ concat2 (string, string2));
+ }
+ else
+ return Fcopy_sequence (Fsymbol_name (symbol));
+}
+
+#ifdef HAVE_PTYS
+
+/* Open an available pty, returning a file descriptor.
+ Return -1 on failure.
+ The file name of the terminal corresponding to the pty
+ is left in the variable pty_name. */
+
+char pty_name[24];
+
+int
+allocate_pty ()
+{
+ struct stat stb;
+ register c, i;
+ int fd;
+
+ /* Some systems name their pseudoterminals so that there are gaps in
+ the usual sequence - for example, on HP9000/S700 systems, there
+ are no pseudoterminals with names ending in 'f'. So we wait for
+ three failures in a row before deciding that we've reached the
+ end of the ptys. */
+ int failed_count = 0;
+
+#ifdef PTY_ITERATION
+ PTY_ITERATION
+#else
+ for (c = FIRST_PTY_LETTER; c <= 'z'; c++)
+ for (i = 0; i < 16; i++)
+#endif
+ {
+#ifdef PTY_NAME_SPRINTF
+ PTY_NAME_SPRINTF
+#else
+#ifdef HPUX
+ sprintf (pty_name, "/dev/ptym/pty%c%x", c, i);
+#else
+#ifdef RTU
+ sprintf (pty_name, "/dev/pty%x", i);
+#else
+ sprintf (pty_name, "/dev/pty%c%x", c, i);
+#endif /* not RTU */
+#endif /* not HPUX */
+#endif /* no PTY_NAME_SPRINTF */
+
+#ifdef PTY_OPEN
+ PTY_OPEN;
+#else /* no PTY_OPEN */
+#ifndef IRIS
+ if (stat (pty_name, &stb) < 0)
+ {
+ failed_count++;
+ if (failed_count >= 3)
+ return -1;
+ }
+ else
+ failed_count = 0;
+#ifdef O_NONBLOCK
+ fd = open (pty_name, O_RDWR | O_NONBLOCK, 0);
+#else
+ fd = open (pty_name, O_RDWR | O_NDELAY, 0);
+#endif
+#else /* Unusual IRIS code */
+ fd = open ("/dev/ptc", O_RDWR | O_NDELAY, 0);
+ if (fd < 0)
+ return -1;
+ if (fstat (fd, &stb) < 0)
+ return -1;
+#endif /* IRIS */
+#endif /* no PTY_OPEN */
+
+ if (fd >= 0)
+ {
+ /* check to make certain that both sides are available
+ this avoids a nasty yet stupid bug in rlogins */
+#ifdef PTY_TTY_NAME_SPRINTF
+ PTY_TTY_NAME_SPRINTF
+#else
+ /* In version 19, make these special cases use the macro above. */
+#ifdef HPUX
+ sprintf (pty_name, "/dev/pty/tty%c%x", c, i);
+#else
+#ifdef RTU
+ sprintf (pty_name, "/dev/ttyp%x", i);
+#else
+#ifdef IRIS
+ sprintf (pty_name, "/dev/ttyq%d", minor (stb.st_rdev));
+#else
+ sprintf (pty_name, "/dev/tty%c%x", c, i);
+#endif /* not IRIS */
+#endif /* not RTU */
+#endif /* not HPUX */
+#endif /* no PTY_TTY_NAME_SPRINTF */
+#ifndef UNIPLUS
+ if (access (pty_name, 6) != 0)
+ {
+ close (fd);
+#ifndef IRIS
+ continue;
+#else
+ return -1;
+#endif /* IRIS */
+ }
+#endif /* not UNIPLUS */
+ setup_pty (fd);
+ return fd;
+ }
+ }
+ return -1;
+}
+#endif /* HAVE_PTYS */
+
+Lisp_Object
+make_process (name)
+ Lisp_Object name;
+{
+ register Lisp_Object val, tem, name1;
+ register struct Lisp_Process *p;
+ char suffix[10];
+ register int i;
+
+ /* size of process structure includes the vector header,
+ so deduct for that. But struct Lisp_Vector includes the first
+ element, thus deducts too much, so add it back. */
+ val = Fmake_vector (make_number ((sizeof (struct Lisp_Process)
+ - sizeof (struct Lisp_Vector)
+ + sizeof (Lisp_Object))
+ / sizeof (Lisp_Object)),
+ Qnil);
+ XSETTYPE (val, Lisp_Process);
+
+ p = XPROCESS (val);
+ XFASTINT (p->infd) = 0;
+ XFASTINT (p->outfd) = 0;
+ XFASTINT (p->pid) = 0;
+ XFASTINT (p->tick) = 0;
+ XFASTINT (p->update_tick) = 0;
+ p->raw_status_low = Qnil;
+ p->raw_status_high = Qnil;
+ p->status = Qrun;
+ p->mark = Fmake_marker ();
+
+ /* If name is already in use, modify it until it is unused. */
+
+ name1 = name;
+ for (i = 1; ; i++)
+ {
+ tem = Fget_process (name1);
+ if (NULL (tem)) break;
+ sprintf (suffix, "<%d>", i);
+ name1 = concat2 (name, build_string (suffix));
+ }
+ name = name1;
+ p->name = name;
+ Vprocess_alist = Fcons (Fcons (name, val), Vprocess_alist);
+ return val;
+}
+
+remove_process (proc)
+ register Lisp_Object proc;
+{
+ register Lisp_Object pair;
+
+ pair = Frassq (proc, Vprocess_alist);
+ Vprocess_alist = Fdelq (pair, Vprocess_alist);
+ Fset_marker (XPROCESS (proc)->mark, Qnil, Qnil);
+
+ deactivate_process (proc);
+}
+
+DEFUN ("processp", Fprocessp, Sprocessp, 1, 1, 0,
+ "Return t if OBJECT is a process.")
+ (obj)
+ Lisp_Object obj;
+{
+ return XTYPE (obj) == Lisp_Process ? Qt : Qnil;
+}
+
+DEFUN ("get-process", Fget_process, Sget_process, 1, 1, 0,
+ "Return the process named NAME, or nil if there is none.")
+ (name)
+ register Lisp_Object name;
+{
+ if (XTYPE (name) == Lisp_Process)
+ return name;
+ CHECK_STRING (name, 0);
+ return Fcdr (Fassoc (name, Vprocess_alist));
+}
+
+DEFUN ("get-buffer-process", Fget_buffer_process, Sget_buffer_process, 1, 1, 0,
+ "Return the (or, a) process associated with BUFFER.\n\
+BUFFER may be a buffer or the name of one.")
+ (name)
+ register Lisp_Object name;
+{
+ register Lisp_Object buf, tail, proc;
+
+ if (NULL (name)) return Qnil;
+ buf = Fget_buffer (name);
+ if (NULL (buf)) return Qnil;
+
+ for (tail = Vprocess_alist; !NULL (tail); tail = Fcdr (tail))
+ {
+ proc = Fcdr (Fcar (tail));
+ if (XTYPE (proc) == Lisp_Process && EQ (XPROCESS (proc)->buffer, buf))
+ return proc;
+ }
+ return Qnil;
+}
+
+/* This is how commands for the user decode process arguments */
+
+Lisp_Object
+get_process (name)
+ register Lisp_Object name;
+{
+ register Lisp_Object proc;
+ if (NULL (name))
+ proc = Fget_buffer_process (Fcurrent_buffer ());
+ else
+ {
+ proc = Fget_process (name);
+ if (NULL (proc))
+ proc = Fget_buffer_process (Fget_buffer (name));
+ }
+
+ if (!NULL (proc))
+ return proc;
+
+ if (NULL (name))
+ error ("Current buffer has no process");
+ else
+ error ("Process %s does not exist", XSTRING (name)->data);
+ /* NOTREACHED */
+}
+
+DEFUN ("delete-process", Fdelete_process, Sdelete_process, 1, 1, 0,
+ "Delete PROCESS: kill it and forget about it immediately.\n\
+PROCESS may be a process or the name of one, or a buffer name.")
+ (proc)
+ register Lisp_Object proc;
+{
+ proc = get_process (proc);
+ XPROCESS (proc)->raw_status_low = Qnil;
+ XPROCESS (proc)->raw_status_high = Qnil;
+ if (NETCONN_P (proc))
+ {
+ XPROCESS (proc)->status = Fcons (Qexit, Fcons (make_number (0), Qnil));
+ XSETINT (XPROCESS (proc)->tick, ++process_tick);
+ }
+ else if (XFASTINT (XPROCESS (proc)->infd))
+ {
+ Fkill_process (proc, Qnil);
+ /* Do this now, since remove_process will make sigchld_handler do nothing. */
+ XPROCESS (proc)->status
+ = Fcons (Qsignal, Fcons (make_number (SIGKILL), Qnil));
+ XSETINT (XPROCESS (proc)->tick, ++process_tick);
+ status_notify ();
+ }
+ remove_process (proc);
+ return Qnil;
+}
+
+DEFUN ("process-status", Fprocess_status, Sprocess_status, 1, 1, 0,
+ "Return the status of PROCESS: a symbol, one of these:\n\
+run -- for a process that is running.\n\
+stop -- for a process stopped but continuable.\n\
+exit -- for a process that has exited.\n\
+signal -- for a process that has got a fatal signal.\n\
+open -- for a network stream connection that is open.\n\
+closed -- for a network stream connection that is closed.\n\
+nil -- if arg is a process name and no such process exists.")
+/* command -- for a command channel opened to Emacs by another process.\n\
+ external -- for an i/o channel opened to Emacs by another process.\n\ */
+ (proc)
+ register Lisp_Object proc;
+{
+ register struct Lisp_Process *p;
+ register Lisp_Object status;
+ proc = Fget_process (proc);
+ if (NULL (proc))
+ return proc;
+ p = XPROCESS (proc);
+ if (!NULL (p->raw_status_low))
+ update_status (p);
+ status = p->status;
+ if (XTYPE (status) == Lisp_Cons)
+ status = XCONS (status)->car;
+ if (NETCONN_P (proc))
+ {
+ if (EQ (status, Qrun))
+ status = Qopen;
+ else if (EQ (status, Qexit))
+ status = Qclosed;
+ }
+ return status;
+}
+
+DEFUN ("process-exit-status", Fprocess_exit_status, Sprocess_exit_status,
+ 1, 1, 0,
+ "Return the exit status of PROCESS or the signal number that killed it.\n\
+If PROCESS has not yet exited or died, return 0.\n\
+If PROCESS is a net connection that was closed remotely, return 256.")
+ (proc)
+ register Lisp_Object proc;
+{
+ CHECK_PROCESS (proc, 0);
+ if (!NULL (XPROCESS (proc)->raw_status_low))
+ update_status (XPROCESS (proc));
+ if (XTYPE (XPROCESS (proc)->status) == Lisp_Cons)
+ return XCONS (XCONS (XPROCESS (proc)->status)->cdr)->car;
+ return make_number (0);
+}
+
+DEFUN ("process-id", Fprocess_id, Sprocess_id, 1, 1, 0,
+ "Return the process id of PROCESS.\n\
+This is the pid of the Unix process which PROCESS uses or talks to.\n\
+For a network connection, this value is nil.")
+ (proc)
+ register Lisp_Object proc;
+{
+ CHECK_PROCESS (proc, 0);
+ return XPROCESS (proc)->pid;
+}
+
+DEFUN ("process-name", Fprocess_name, Sprocess_name, 1, 1, 0,
+ "Return the name of PROCESS, as a string.\n\
+This is the name of the program invoked in PROCESS,\n\
+possibly modified to make it unique among process names.")
+ (proc)
+ register Lisp_Object proc;
+{
+ CHECK_PROCESS (proc, 0);
+ return XPROCESS (proc)->name;
+}
+
+DEFUN ("process-command", Fprocess_command, Sprocess_command, 1, 1, 0,
+ "Return the command that was executed to start PROCESS.\n\
+This is a list of strings, the first string being the program executed\n\
+and the rest of the strings being the arguments given to it.\n\
+For a non-child channel, this is nil.")
+ (proc)
+ register Lisp_Object proc;
+{
+ CHECK_PROCESS (proc, 0);
+ return XPROCESS (proc)->command;
+}
+
+DEFUN ("set-process-buffer", Fset_process_buffer, Sset_process_buffer,
+ 2, 2, 0,
+ "Set buffer associated with PROCESS to BUFFER (a buffer, or nil).")
+ (proc, buffer)
+ register Lisp_Object proc, buffer;
+{
+ CHECK_PROCESS (proc, 0);
+ if (!NULL (buffer))
+ CHECK_BUFFER (buffer, 1);
+ XPROCESS (proc)->buffer = buffer;
+ return buffer;
+}
+
+DEFUN ("process-buffer", Fprocess_buffer, Sprocess_buffer,
+ 1, 1, 0,
+ "Return the buffer PROCESS is associated with.\n\
+Output from PROCESS is inserted in this buffer\n\
+unless PROCESS has a filter.")
+ (proc)
+ register Lisp_Object proc;
+{
+ CHECK_PROCESS (proc, 0);
+ return XPROCESS (proc)->buffer;
+}
+
+DEFUN ("process-mark", Fprocess_mark, Sprocess_mark,
+ 1, 1, 0,
+ "Return the marker for the end of the last output from PROCESS.")
+ (proc)
+ register Lisp_Object proc;
+{
+ CHECK_PROCESS (proc, 0);
+ return XPROCESS (proc)->mark;
+}
+
+DEFUN ("set-process-filter", Fset_process_filter, Sset_process_filter,
+ 2, 2, 0,
+ "Give PROCESS the filter function FILTER; nil means no filter.\n\
+When a process has a filter, each time it does output\n\
+the entire string of output is passed to the filter.\n\
+The filter gets two arguments: the process and the string of output.\n\
+If the process has a filter, its buffer is not used for output.")
+ (proc, filter)
+ register Lisp_Object proc, filter;
+{
+ CHECK_PROCESS (proc, 0);
+ XPROCESS (proc)->filter = filter;
+ return filter;
+}
+
+DEFUN ("process-filter", Fprocess_filter, Sprocess_filter,
+ 1, 1, 0,
+ "Returns the filter function of PROCESS; nil if none.\n\
+See set-process-filter for more info on filter functions.")
+ (proc)
+ register Lisp_Object proc;
+{
+ CHECK_PROCESS (proc, 0);
+ return XPROCESS (proc)->filter;
+}
+
+DEFUN ("set-process-sentinel", Fset_process_sentinel, Sset_process_sentinel,
+ 2, 2, 0,
+ "Give PROCESS the sentinel SENTINEL; nil for none.\n\
+The sentinel is called as a function when the process changes state.\n\
+It gets two arguments: the process, and a string describing the change.")
+ (proc, sentinel)
+ register Lisp_Object proc, sentinel;
+{
+ CHECK_PROCESS (proc, 0);
+ XPROCESS (proc)->sentinel = sentinel;
+ return sentinel;
+}
+
+DEFUN ("process-sentinel", Fprocess_sentinel, Sprocess_sentinel,
+ 1, 1, 0,
+ "Return the sentinel of PROCESS; nil if none.\n\
+See set-process-sentinel for more info on sentinels.")
+ (proc)
+ register Lisp_Object proc;
+{
+ CHECK_PROCESS (proc, 0);
+ return XPROCESS (proc)->sentinel;
+}
+
+DEFUN ("process-kill-without-query", Fprocess_kill_without_query,
+ Sprocess_kill_without_query, 1, 2, 0,
+ "Say no query needed if PROCESS is running when Emacs is exited.\n\
+Optional second argument if non-nil says to require a query.\n\
+Value is t if a query was formerly required.")
+ (proc, value)
+ register Lisp_Object proc, value;
+{
+ Lisp_Object tem;
+ CHECK_PROCESS (proc, 0);
+ tem = XPROCESS (proc)->kill_without_query;
+ XPROCESS (proc)->kill_without_query = Fnull (value);
+ return Fnull (tem);
+}
+
+Lisp_Object
+list_processes_1 ()
+{
+ register Lisp_Object tail, tem;
+ Lisp_Object proc, minspace, tem1;
+ register struct buffer *old = current_buffer;
+ register struct Lisp_Process *p;
+ register int state;
+ char tembuf[80];
+
+ XFASTINT (minspace) = 1;
+
+ set_buffer_internal (XBUFFER (Vstandard_output));
+ Fbuffer_flush_undo (Vstandard_output);
+
+ current_buffer->truncate_lines = Qt;
+
+ write_string ("\
+Proc Status Buffer Command\n\
+---- ------ ------ -------\n", -1);
+
+ for (tail = Vprocess_alist; !NULL (tail); tail = Fcdr (tail))
+ {
+ Lisp_Object symbol;
+
+ proc = Fcdr (Fcar (tail));
+ p = XPROCESS (proc);
+ if (NULL (p->childp))
+ continue;
+
+ Finsert (1, &p->name);
+ Findent_to (make_number (13), minspace);
+
+ if (!NULL (p->raw_status_low))
+ update_status (p);
+ symbol = p->status;
+ if (XTYPE (p->status) == Lisp_Cons)
+ symbol = XCONS (p->status)->car;
+
+ if (EQ (symbol, Qsignal))
+ {
+ Lisp_Object tem;
+ tem = Fcar (Fcdr (p->status));
+ if (XINT (tem) < NSIG)
+ write_string (sys_siglist [XINT (tem)], -1);
+ else
+ Fprinc (symbol, Qnil);
+ }
+ else if (NETCONN_P (proc))
+ {
+ if (EQ (symbol, Qrun))
+ write_string ("open", -1);
+ else if (EQ (symbol, Qexit))
+ write_string ("closed", -1);
+ else
+ Fprinc (symbol, Qnil);
+ }
+ else
+ Fprinc (symbol, Qnil);
+
+ if (EQ (symbol, Qexit))
+ {
+ Lisp_Object tem;
+ tem = Fcar (Fcdr (p->status));
+ if (XFASTINT (tem))
+ {
+ sprintf (tembuf, " %d", XFASTINT (tem));
+ write_string (tembuf, -1);
+ }
+ }
+
+ if (EQ (symbol, Qsignal) || EQ (symbol, Qexit))
+ remove_process (proc);
+
+ Findent_to (make_number (22), minspace);
+ if (NULL (p->buffer))
+ InsStr ("(none)");
+ else if (NULL (XBUFFER (p->buffer)->name))
+ InsStr ("(Killed)");
+ else
+ Finsert (1, &XBUFFER (p->buffer)->name);
+
+ Findent_to (make_number (37), minspace);
+
+ if (NETCONN_P (proc))
+ {
+ sprintf (tembuf, "(network stream connection to %s)\n",
+ XSTRING (p->childp)->data);
+ InsStr (tembuf);
+ }
+ else
+ {
+ tem = p->command;
+ while (1)
+ {
+ tem1 = Fcar (tem);
+ Finsert (1, &tem1);
+ tem = Fcdr (tem);
+ if (NULL (tem))
+ break;
+ InsStr (" ");
+ }
+ InsStr ("\n");
+ }
+ }
+
+ return Qnil;
+}
+
+DEFUN ("list-processes", Flist_processes, Slist_processes, 0, 0, "",
+ "Display a list of all processes.\n\
+\(Any processes listed as Exited or Signaled are actually eliminated\n\
+after the listing is made.)")
+ ()
+{
+ internal_with_output_to_temp_buffer ("*Process List*",
+ list_processes_1, Qnil);
+ return Qnil;
+}
+
+DEFUN ("process-list", Fprocess_list, Sprocess_list, 0, 0, 0,
+ "Return a list of all processes.")
+ ()
+{
+ return Fmapcar (Qcdr, Vprocess_alist);
+}
+
+DEFUN ("start-process", Fstart_process, Sstart_process, 3, MANY, 0,
+ "Start a program in a subprocess. Return the process object for it.\n\
+Args are NAME BUFFER PROGRAM &rest PROGRAM-ARGS\n\
+NAME is name for process. It is modified if necessary to make it unique.\n\
+BUFFER is the buffer or (buffer-name) to associate with the process.\n\
+ Process output goes at end of that buffer, unless you specify\n\
+ an output stream or filter function to handle the output.\n\
+ BUFFER may be also nil, meaning that this process is not associated\n\
+ with any buffer\n\
+Third arg is program file name. It is searched for as in the shell.\n\
+Remaining arguments are strings to give program as arguments.")
+ (nargs, args)
+ int nargs;
+ register Lisp_Object *args;
+{
+ Lisp_Object buffer, name, program, proc, tem;
+ register unsigned char **new_argv;
+ register int i;
+
+ buffer = args[1];
+ if (!NULL (buffer))
+ buffer = Fget_buffer_create (buffer);
+
+ name = args[0];
+ CHECK_STRING (name, 0);
+
+ program = args[2];
+
+ CHECK_STRING (program, 2);
+
+ new_argv = (unsigned char **) alloca ((nargs - 1) * sizeof (char *));
+
+ for (i = 3; i < nargs; i++)
+ {
+ tem = args[i];
+ CHECK_STRING (tem, i);
+ new_argv[i - 2] = XSTRING (tem)->data;
+ }
+ new_argv[i - 2] = 0;
+ new_argv[0] = XSTRING (program)->data;
+
+ /* If program file name is not absolute, search our path for it */
+ if (new_argv[0][0] != '/')
+ {
+ tem = Qnil;
+ openp (Vexec_path, program, "", &tem, 1);
+ if (NULL (tem))
+ report_file_error ("Searching for program", Fcons (program, Qnil));
+ new_argv[0] = XSTRING (tem)->data;
+ }
+
+ proc = make_process (name);
+
+ XPROCESS (proc)->childp = Qt;
+ XPROCESS (proc)->command_channel_p = Qnil;
+ XPROCESS (proc)->buffer = buffer;
+ XPROCESS (proc)->sentinel = Qnil;
+ XPROCESS (proc)->filter = Qnil;
+ XPROCESS (proc)->command = Flist (nargs - 2, args + 2);
+
+ create_process (proc, new_argv);
+
+ return proc;
+}
+
+create_process_1 (signo)
+ int signo;
+{
+#ifdef USG
+ /* USG systems forget handlers when they are used;
+ must reestablish each time */
+ signal (signo, create_process_1);
+#endif /* USG */
+}
+
+#if 0 /* This doesn't work; see the note before sigchld_handler. */
+#ifdef USG
+#ifdef SIGCHLD
+/* Mimic blocking of signals on system V, which doesn't really have it. */
+
+/* Nonzero means we got a SIGCHLD when it was supposed to be blocked. */
+int sigchld_deferred;
+
+create_process_sigchld ()
+{
+ signal (SIGCHLD, create_process_sigchld);
+
+ sigchld_deferred = 1;
+}
+#endif
+#endif
+#endif
+
+create_process (process, new_argv)
+ Lisp_Object process;
+ char **new_argv;
+{
+ int pid, inchannel, outchannel, forkin, forkout;
+ int sv[2];
+#ifdef SIGCHLD
+ int (*sigchld)();
+#endif
+ char **env;
+ int pty_flag = 0;
+ extern char **environ;
+
+#ifdef MAINTAIN_ENVIRONMENT
+ env = (char **) alloca (size_of_current_environ ());
+ get_current_environ (env);
+#else
+ env = environ;
+#endif /* MAINTAIN_ENVIRONMENT */
+
+ inchannel = outchannel = -1;
+
+#ifdef HAVE_PTYS
+ if (EQ (Vprocess_connection_type, Qt))
+ outchannel = inchannel = allocate_pty ();
+
+ if (inchannel >= 0)
+ {
+#ifndef USG
+ /* On USG systems it does not work to open
+ the pty's tty here and then close and reopen it in the child. */
+#ifdef O_NOCTTY
+ /* Don't let this terminal become our controlling terminal
+ (in case we don't have one). */
+ forkout = forkin = open (pty_name, O_RDWR | O_NOCTTY, 0);
+#else
+ forkout = forkin = open (pty_name, O_RDWR, 0);
+#endif
+ if (forkin < 0)
+ report_file_error ("Opening pty", Qnil);
+#else
+ forkin = forkout = -1;
+#endif
+ pty_flag = 1;
+ }
+ else
+#endif /* HAVE_PTYS */
+#ifdef SKTPAIR
+ {
+ if (socketpair (AF_UNIX, SOCK_STREAM, 0, sv) < 0)
+ report_file_error ("Opening socketpair", Qnil);
+ outchannel = inchannel = sv[0];
+ forkout = forkin = sv[1];
+ }
+#else /* not SKTPAIR */
+ {
+ int temp;
+ temp = pipe (sv);
+ if (temp < 0) goto io_failure;
+ inchannel = sv[0];
+ forkout = sv[1];
+ temp = pipe (sv);
+ if (temp < 0) goto io_failure;
+ outchannel = sv[1];
+ forkin = sv[0];
+ }
+#endif /* not SKTPAIR */
+
+#if 0
+ /* Replaced by close_process_descs */
+ set_exclusive_use (inchannel);
+ set_exclusive_use (outchannel);
+#endif
+
+/* Stride people say it's a mystery why this is needed
+ as well as the O_NDELAY, but that it fails without this. */
+#if defined (STRIDE) || (defined (pfa) && defined (HAVE_PTYS))
+ {
+ int one = 1;
+ ioctl (inchannel, FIONBIO, &one);
+ }
+#endif
+
+#ifdef O_NONBLOCK
+ fcntl (inchannel, F_SETFL, O_NONBLOCK);
+#else
+#ifdef O_NDELAY
+ fcntl (inchannel, F_SETFL, O_NDELAY);
+#endif
+#endif
+
+ XFASTINT (XPROCESS (process)->infd) = inchannel;
+ XFASTINT (XPROCESS (process)->outfd) = outchannel;
+ /* Record the tty descriptor used in the subprocess. */
+#ifdef SYSV4_PTYS
+ /* On system V.4, if using a pty, we need to keep a descriptor
+ for the tty that the inferior uses, in order to get the pgrp.
+ If this uses too many descriptors, we could instead save the tty name
+ and reopen it to send signals. */
+ if (pty_flag)
+ {
+ int temp = dup (forkin);
+ if (temp < 0) goto io_failure;
+ XFASTINT (XPROCESS (process)->subtty) = temp;
+ }
+ else
+#endif
+ XPROCESS (process)->subtty = Qnil;
+ XPROCESS (process)->pty_flag = (pty_flag ? Qt : Qnil);
+ XPROCESS (process)->status = Qrun;
+ /* Record this as an active process, with its channels.
+ As a result, child_setup will close Emacs's side of the pipes. */
+ chan_process[inchannel] = process;
+
+ /* Delay interrupts until we have a chance to store
+ the new fork's pid in its process structure */
+#ifdef SIGCHLD
+#ifdef BSD4_1
+ sighold (SIGCHLD);
+#else /* not BSD4_1 */
+#ifdef HPUX
+ sigsetmask (sigmask (SIGCHLD));
+#else /* not HPUX */
+#if defined (BSD) || defined (UNIPLUS)
+ sigsetmask (sigmask (SIGCHLD));
+#else /* ordinary USG */
+#if 0
+ sigchld_deferred = 0;
+ sigchld = (int (*)()) signal (SIGCHLD, create_process_sigchld);
+#endif
+#endif /* ordinary USG */
+#endif /* not HPUX */
+#endif /* not BSD4_1 */
+#endif /* SIGCHLD */
+
+ /* Until we store the proper pid, enable sigchld_handler
+ to recognize an unknown pid as standing for this process. */
+ XSETINT (XPROCESS (process)->pid, -1);
+ /* Turn on the bit for our input from this process now,
+ so that even if the process terminates very soon,
+ we can clear the bit properly on termination.
+ If fork fails, remove_process will clear the bit. */
+ FD_SET (inchannel, &input_wait_mask);
+
+ {
+ /* child_setup must clobber environ on systems with true vfork.
+ Protect it from permanent change. */
+ char **save_environ = environ;
+
+ pid = vfork ();
+ if (pid == 0)
+ {
+ int xforkin = forkin;
+ int xforkout = forkout;
+
+#if 0 /* This was probably a mistake--it duplicates code later on,
+ but fails to handle all the cases. */
+ /* Make SIGCHLD work again in the child. */
+ sigsetmask (SIGEMPTYMASK);
+#endif
+
+ /* Make the pty be the controlling terminal of the process. */
+#ifdef HAVE_PTYS
+ /* First, disconnect its current controlling terminal. */
+#ifdef HAVE_SETSID
+ setsid ();
+#ifdef TIOCSCTTY
+ /* Make the pty's terminal the controlling terminal. */
+ if (pty_flag && (ioctl (xforkin, TIOCSCTTY, 0) < 0))
+ abort ();
+#endif
+#else /* not HAVE_SETSID */
+#ifdef USG
+ /* It's very important to call setpgrp() here and no time
+ afterwards. Otherwise, we lose our controlling tty which
+ is set when we open the pty. */
+ setpgrp ();
+#endif /* USG */
+#endif /* not HAVE_SETSID */
+#ifdef TIOCNOTTY
+ /* In 4.3BSD, the TIOCSPGRP bug has been fixed, and now you
+ can do TIOCSPGRP only to the process's controlling tty. */
+ if (pty_flag)
+ {
+ /* I wonder: would just ioctl (0, TIOCNOTTY, 0) work here?
+ I can't test it since I don't have 4.3. */
+ int j = open ("/dev/tty", O_RDWR, 0);
+ ioctl (j, TIOCNOTTY, 0);
+ close (j);
+#ifndef USG
+ /* In order to get a controlling terminal on some versions
+ of BSD, it is necessary to put the process in pgrp 0
+ before it opens the terminal. */
+ setpgrp (0, 0);
+#endif
+ }
+#endif /* TIOCNOTTY */
+
+#if !defined (RTU) && !defined (UNIPLUS)
+/*** There is a suggestion that this ought to be a
+ conditional on TIOCSPGRP. */
+ /* Now close the pty (if we had it open) and reopen it.
+ This makes the pty the controlling terminal of the subprocess. */
+ if (pty_flag)
+ {
+ /* I wonder if close (open (pty_name, ...)) would work? */
+ if (xforkin >= 0)
+ close (xforkin);
+ xforkout = xforkin = open (pty_name, O_RDWR, 0);
+
+ if (xforkin < 0)
+ abort ();
+ }
+#endif /* not UNIPLUS and not RTU */
+#ifdef SETUP_SLAVE_PTY
+ if (pty_flag)
+ {
+ SETUP_SLAVE_PTY;
+ }
+#endif /* SETUP_SLAVE_PTY */
+#ifdef AIX
+ /* On AIX, we've disabled SIGHUP above once we start a child on a pty.
+ Now reenable it in the child, so it will die when we want it to. */
+ if (pty_flag)
+ signal (SIGHUP, SIG_DFL);
+#endif
+#endif /* HAVE_PTYS */
+#ifdef SIGCHLD
+#ifdef BSD4_1
+ sigrelse (SIGCHLD);
+#else /* not BSD4_1 */
+#if defined (BSD) || defined (UNIPLUS) || defined (HPUX)
+ sigsetmask (SIGEMPTYMASK);
+#else /* ordinary USG */
+#if 0
+ signal (SIGCHLD, sigchld);
+#endif
+#endif /* ordinary USG */
+#endif /* not BSD4_1 */
+#endif /* SIGCHLD */
+ if (pty_flag)
+ child_setup_tty (xforkout);
+ child_setup (xforkin, xforkout, xforkout, new_argv, env);
+ }
+ environ = save_environ;
+ }
+
+ if (pid < 0)
+ {
+ remove_process (process);
+ report_file_error ("Doing vfork", Qnil);
+ }
+
+ XFASTINT (XPROCESS (process)->pid) = pid;
+
+ /* If the subfork execv fails, and it exits,
+ this close hangs. I don't know why.
+ So have an interrupt jar it loose. */
+ stop_polling ();
+ signal (SIGALRM, create_process_1);
+ alarm (1);
+ if (forkin >= 0)
+ close (forkin);
+ alarm (0);
+ start_polling ();
+ if (forkin != forkout && forkout >= 0)
+ close (forkout);
+
+#ifdef SIGCHLD
+#ifdef BSD4_1
+ sigrelse (SIGCHLD);
+#else /* not BSD4_1 */
+#if defined (BSD) || defined (UNIPLUS) || defined (HPUX)
+ sigsetmask (SIGEMPTYMASK);
+#else /* ordinary USG */
+#if 0
+ signal (SIGCHLD, sigchld);
+ /* Now really handle any of these signals
+ that came in during this function. */
+ if (sigchld_deferred)
+ kill (getpid (), SIGCHLD);
+#endif
+#endif /* ordinary USG */
+#endif /* not BSD4_1 */
+#endif /* SIGCHLD */
+ return;
+
+io_failure:
+ {
+ int temp = errno;
+ close (forkin);
+ close (forkout);
+ close (inchannel);
+ close (outchannel);
+ errno = temp;
+ report_file_error ("Opening pty or pipe", Qnil);
+ }
+}
+
+#ifdef HAVE_SOCKETS
+
+/* open a TCP network connection to a given HOST/SERVICE. Treated
+ exactly like a normal process when reading and writing. Only
+ differences are in status display and process deletion. A network
+ connection has no PID; you cannot signal it. All you can do is
+ deactivate and close it via delete-process */
+
+DEFUN ("open-network-stream", Fopen_network_stream, Sopen_network_stream,
+ 4, 4, 0,
+ "Open a TCP connection for a service to a host.\n\
+Returns a subprocess-object to represent the connection.\n\
+Input and output work as for subprocesses; `delete-process' closes it.\n\
+Args are NAME BUFFER HOST SERVICE.\n\
+NAME is name for process. It is modified if necessary to make it unique.\n\
+BUFFER is the buffer (or buffer-name) to associate with the process.\n\
+ Process output goes at end of that buffer, unless you specify\n\
+ an output stream or filter function to handle the output.\n\
+ BUFFER may be also nil, meaning that this process is not associated\n\
+ with any buffer\n\
+Third arg is name of the host to connect to.\n\
+Fourth arg SERVICE is name of the service desired, or an integer\n\
+ specifying a port number to connect to.")
+ (name, buffer, host, service)
+ Lisp_Object name, buffer, host, service;
+{
+ Lisp_Object proc;
+ register int i;
+ struct sockaddr_in address;
+ struct servent *svc_info;
+ struct hostent *host_info;
+ int s, outch, inch;
+ char errstring[80];
+ int port;
+ struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
+
+ GCPRO4 (name, buffer, host, service);
+ CHECK_STRING (name, 0);
+ CHECK_STRING (host, 0);
+ if (XTYPE (service) == Lisp_Int)
+ port = htons ((unsigned short) XINT (service));
+ else
+ {
+ CHECK_STRING (service, 0);
+ svc_info = getservbyname (XSTRING (service)->data, "tcp");
+ if (svc_info == 0)
+ error ("Unknown service \"%s\"", XSTRING (service)->data);
+ port = svc_info->s_port;
+ }
+
+ bzero (&address, sizeof address);
+ address.sin_addr.s_addr = inet_addr (XSTRING (host)->data);
+ if (address.sin_addr.s_addr != -1)
+ address.sin_family = AF_INET;
+ else
+ {
+ host_info = gethostbyname (XSTRING (host)->data);
+ if (host_info == 0)
+ error ("Unknown host \"%s\"", XSTRING (host)->data);
+ bcopy (host_info->h_addr, (char *) &address.sin_addr, host_info->h_length);
+ address.sin_family = host_info->h_addrtype;
+ }
+ address.sin_port = port;
+
+ s = socket (address.sin_family, SOCK_STREAM, 0);
+ if (s < 0)
+ report_file_error ("error creating socket", Fcons (name, Qnil));
+
+ /* Kernel bugs (on Ultrix at least) cause lossage (not just EINTR)
+ when connect is interrupted. So let's not let it get interrupted. */
+ if (interrupt_input)
+ unrequest_sigio ();
+ stop_polling ();
+
+ while (1)
+ {
+ int value = connect (s, &address, sizeof address);
+ /* Continue if successeful. */
+ if (value != -1)
+ break;
+ /* Report a "real" error. */
+ if (errno != EINTR)
+ {
+ close (s);
+ error ("Host \"%s\" not responding", XSTRING (host)->data);
+ }
+ /* Loop around after temporary error. */
+ }
+
+ if (interrupt_input)
+ request_sigio ();
+ start_polling ();
+
+ inch = s;
+ outch = dup (s);
+ if (outch < 0)
+ report_file_error ("error duplicating socket", Fcons (name, Qnil));
+
+ if (!NULL (buffer))
+ buffer = Fget_buffer_create (buffer);
+ proc = make_process (name);
+
+ chan_process[inch] = proc;
+
+#ifdef O_NONBLOCK
+ fcntl (inch, F_SETFL, O_NONBLOCK);
+#else
+#ifdef O_NDELAY
+ fcntl (inch, F_SETFL, O_NDELAY);
+#endif
+#endif
+
+ XPROCESS (proc)->childp = host;
+ XPROCESS (proc)->command_channel_p = Qnil;
+ XPROCESS (proc)->buffer = buffer;
+ XPROCESS (proc)->sentinel = Qnil;
+ XPROCESS (proc)->filter = Qnil;
+ XPROCESS (proc)->command = Qnil;
+ XPROCESS (proc)->pid = Qnil;
+ XPROCESS (proc)->kill_without_query = Qt;
+ XFASTINT (XPROCESS (proc)->infd) = s;
+ XFASTINT (XPROCESS (proc)->outfd) = outch;
+ XPROCESS (proc)->status = Qrun;
+ FD_SET (inch, &input_wait_mask);
+
+ UNGCPRO;
+ return proc;
+}
+#endif /* HAVE_SOCKETS */
+
+deactivate_process (proc)
+ Lisp_Object proc;
+{
+ register int inchannel, outchannel;
+ register struct Lisp_Process *p = XPROCESS (proc);
+
+ inchannel = XFASTINT (p->infd);
+ outchannel = XFASTINT (p->outfd);
+
+ if (inchannel)
+ {
+ /* Beware SIGCHLD hereabouts. */
+ flush_pending_output (inchannel);
+ close (inchannel);
+ if (outchannel && outchannel != inchannel)
+ close (outchannel);
+
+ XFASTINT (p->infd) = 0;
+ XFASTINT (p->outfd) = 0;
+ chan_process[inchannel] = Qnil;
+ FD_CLR (inchannel, &input_wait_mask);
+ }
+}
+
+/* Close all descriptors currently in use for communication
+ with subprocess. This is used in a newly-forked subprocess
+ to get rid of irrelevant descriptors. */
+
+close_process_descs ()
+{
+ int i;
+ for (i = 0; i < MAXDESC; i++)
+ {
+ Lisp_Object process;
+ process = chan_process[i];
+ if (!NULL (process))
+ {
+ int in = XFASTINT (XPROCESS (process)->infd);
+ int out = XFASTINT (XPROCESS (process)->outfd);
+
+ if (in != 0)
+ close (in);
+ if (out != 0 && out != in)
+ close (out);
+ if (!NULL (XPROCESS (process)->subtty))
+ close (XFASTINT (XPROCESS (process)->subtty));
+ }
+ }
+}
+
+DEFUN ("accept-process-output", Faccept_process_output, Saccept_process_output,
+ 0, 1, 0,
+ "Allow any pending output from subprocesses to be read by Emacs.\n\
+It is read into the process' buffers or given to their filter functions.\n\
+Non-nil arg PROCESS means do not return until some output has been received\n\
+from PROCESS.")
+ (proc)
+ register Lisp_Object proc;
+{
+ if (NULL (proc))
+ wait_reading_process_input (-1, 0, 0);
+ else
+ {
+ proc = get_process (proc);
+ wait_reading_process_input (0, XPROCESS (proc), 0);
+ }
+ return Qnil;
+}
+
+/* This variable is different from waiting_for_input in keyboard.c.
+ It is used to communicate to a lisp process-filter/sentinel (via the
+ function Fwaiting_for_user_input_p below) whether emacs was waiting
+ for user-input when that process-filter was called.
+ waiting_for_input cannot be used as that is by definition 0 when
+ lisp code is being evalled */
+static int waiting_for_user_input_p;
+
+/* Read and dispose of subprocess output
+ while waiting for timeout to elapse and/or keyboard input to be available.
+
+ time_limit is the timeout in seconds, or zero for no limit.
+ -1 means gobble data available immediately but don't wait for any.
+
+ read_kbd is 1 to return when input is available.
+ -1 means caller will actually read the input.
+ A pointer to a struct Lisp_Process means wait until
+ something arrives from that process.
+
+ do_display means redisplay should be done to show
+ subprocess output that arrives. */
+
+wait_reading_process_input (time_limit, read_kbd, do_display)
+ int time_limit, read_kbd, do_display;
+{
+ register int channel, nfds, m;
+ SELECT_TYPE Available;
+ SELECT_TYPE Exception;
+ int xerrno;
+ Lisp_Object proc;
+#ifdef HAVE_TIMEVAL
+ struct timeval timeout, end_time, garbage;
+#else
+ long timeout, end_time, temp;
+#endif /* not HAVE_TIMEVAL */
+ SELECT_TYPE Atemp;
+ int wait_channel = 0;
+ struct Lisp_Process *wait_proc = 0;
+ extern kbd_count;
+
+ /* Detect when read_kbd is really the address of a Lisp_Process. */
+ if (read_kbd > 10 || read_kbd < -1)
+ {
+ wait_proc = (struct Lisp_Process *) read_kbd;
+ wait_channel = XFASTINT (wait_proc->infd);
+ read_kbd = 0;
+ }
+ waiting_for_user_input_p = read_kbd;
+
+ /* Since we may need to wait several times,
+ compute the absolute time to return at. */
+ if (time_limit)
+ {
+#ifdef HAVE_TIMEVAL
+ gettimeofday (&end_time, &garbage);
+ end_time.tv_sec += time_limit;
+#else /* not HAVE_TIMEVAL */
+ time (&end_time);
+ end_time += time_limit;
+#endif /* not HAVE_TIMEVAL */
+ }
+
+#if 0 /* Select emulator claims to preserve alarms.
+ And there are many ways to get out of this function by longjmp. */
+ /* Turn off periodic alarms (in case they are in use)
+ because the select emulator uses alarms. */
+ stop_polling ();
+#endif
+
+ while (1)
+ {
+ /* If calling from keyboard input, do not quit
+ since we want to return C-g as an input character.
+ Otherwise, do pending quit if requested. */
+ if (read_kbd >= 0)
+ {
+#if 0
+ /* This is the same condition tested by QUIT.
+ We need to resume polling if we are going to quit. */
+ if (!NULL (Vquit_flag) && NULL (Vinhibit_quit))
+ {
+ start_polling ();
+ QUIT;
+ }
+#endif
+ QUIT;
+ }
+
+ /* If status of something has changed, and no input is available,
+ notify the user of the change right away */
+ if (update_tick != process_tick && do_display)
+ {
+ Atemp = input_wait_mask;
+#ifdef HAVE_TIMEVAL
+ timeout.tv_sec=0; timeout.tv_usec=0;
+#else /* not HAVE_TIMEVAL */
+ timeout = 0;
+#endif /* not HAVE_TIMEVAL */
+ if (select (MAXDESC, &Atemp, 0, 0, &timeout) <= 0)
+ status_notify ();
+ }
+
+ /* Don't wait for output from a non-running process. */
+ if (wait_proc != 0 && !NULL (wait_proc->raw_status_low))
+ update_status (wait_proc);
+ if (wait_proc != 0
+ && ! EQ (wait_proc->status, Qrun))
+ break;
+
+ if (fix_screen_hook)
+ (*fix_screen_hook) ();
+
+ /* Compute time from now till when time limit is up */
+ /* Exit if already run out */
+ if (time_limit == -1)
+ {
+ /* -1 specified for timeout means
+ gobble output available now
+ but don't wait at all. */
+#ifdef HAVE_TIMEVAL
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 0;
+#else
+ timeout = 0;
+#endif /* not HAVE_TIMEVAL */
+ }
+ else if (time_limit)
+ {
+#ifdef HAVE_TIMEVAL
+ gettimeofday (&timeout, &garbage);
+
+ /* In effect, timeout = end_time - timeout.
+ Break if result would be negative. */
+ if (timeval_subtract (&timeout, end_time, timeout))
+ break;
+#else /* not HAVE_TIMEVAL */
+ time (&temp);
+ timeout = end_time - temp;
+ if (timeout < 0)
+ break;
+#endif /* not HAVE_TIMEVAL */
+ }
+ else
+ {
+#ifdef HAVE_TIMEVAL
+ /* If no real timeout, loop sleeping with a big timeout
+ so that input interrupt can wake us up by zeroing it */
+ timeout.tv_sec = 100;
+ timeout.tv_usec = 0;
+#else /* not HAVE_TIMEVAL */
+ timeout = 100000; /* 100000 recognized by the select emulator */
+#endif /* not HAVE_TIMEVAL */
+ }
+
+ /* Cause quitting and alarm signals to take immediate action,
+ and cause input available signals to zero out timeout */
+ if (read_kbd < 0)
+ set_waiting_for_input (&timeout);
+
+ /* Wait till there is something to do */
+
+ Available = Exception = input_wait_mask;
+ if (!read_kbd)
+ FD_CLR (0, &Available);
+
+ if (read_kbd && kbd_count)
+ nfds = 0;
+ else
+ /* Since we don't do anything abt Exceptions,
+ let's notw wake up for them. */
+ nfds = select (MAXDESC, &Available, 0, 0, &timeout);
+#if 0
+#ifdef IBMRTAIX
+ nfds = select (MAXDESC, &Available, 0, 0, &timeout);
+#else
+#ifdef HPUX
+ nfds = select (MAXDESC, &Available, 0, 0, &timeout);
+#else
+ nfds = select (MAXDESC, &Available, 0, &Exception, &timeout);
+#endif
+#endif
+#endif /* 0 */
+ xerrno = errno;
+
+ if (fix_screen_hook)
+ (*fix_screen_hook) ();
+
+ /* Make C-g and alarm signals set flags again */
+ clear_waiting_for_input ();
+
+ /* If we woke up due to SIGWINCH, actually change size now. */
+ if (read_kbd)
+ do_pending_window_change ();
+
+ if (time_limit && nfds == 0) /* timeout elapsed */
+ break;
+ if (nfds < 0)
+ {
+ if (xerrno == EINTR)
+ FD_ZERO (&Available);
+#ifdef ALLIANT
+ /* This happens for no known reason on ALLIANT.
+ I am guessing that this is the right response. -- RMS. */
+ else if (xerrno == EFAULT)
+ FD_ZERO (&Available);
+#endif
+ else if (xerrno == EBADF)
+#ifdef AIX
+ /* AIX will return EBADF on a call to select involving a ptc if the
+ associated pts isn't open. Since this will only happen just as
+ a child is dying, just ignore the situation -- SIGCHLD will come
+ along quite quickly, and after cleanup the ptc will no longer be
+ checked, so this error will stop recurring. */
+ FD_ZERO (&Available); /* Cannot depend on values returned. */
+#else /* not AIX */
+ abort ();
+#endif /* not AIX */
+ else
+ error("select error: %s", sys_errlist[xerrno]);
+ }
+#ifdef SIGIO
+#if defined (sun) || defined (APOLLO)
+ else if (nfds > 0 && FD_ISSET (0, &Available) && interrupt_input)
+ /* System sometimes fails to deliver SIGIO. */
+ kill (getpid (), SIGIO);
+#endif
+#endif
+
+ /* Check for keyboard input */
+ /* If there is any, return immediately
+ to give it higher priority than subprocesses */
+
+ if (read_kbd && detect_input_pending ())
+ break;
+
+ /* If checking input just got us a size-change event from X,
+ obey it now if we should. */
+ if (read_kbd)
+ do_pending_window_change ();
+
+ /* If screen size has changed, redisplay now
+ for either sit-for or keyboard input. */
+ if (read_kbd && screen_garbaged)
+ redisplay_preserve_echo_area ();
+
+#ifdef vipc
+ /* Check for connection from other process */
+
+ if (FD_ISSET (comm_server, &Available))
+ {
+ FD_CLR (comm_server, &Available);
+ create_commchan ();
+ }
+#endif /* vipc */
+
+ /* Check for data from a process or a command channel */
+
+ for (channel = 3; channel < MAXDESC; channel++)
+ {
+ if (FD_ISSET (channel, &Available))
+ {
+ int nread;
+
+ FD_CLR (channel, &Available);
+ /* If waiting for this channel,
+ arrange to return as soon as no more input
+ to be processed. No more waiting. */
+ if (wait_channel == channel)
+ {
+ wait_channel = 0;
+ time_limit = -1;
+ }
+ proc = chan_process[channel];
+ if (NULL (proc))
+ continue;
+
+#ifdef vipc
+ /* It's a command channel */
+ if (!NULL (XPROCESS (proc)->command_channel_p))
+ {
+ ProcessCommChan (channel, proc);
+ if (NULL (XPROCESS (proc)->command_channel_p))
+ {
+ /* It has ceased to be a command channel! */
+ int bytes_available;
+ if (ioctl (channel, FIONREAD, &bytes_available) < 0)
+ bytes_available = 0;
+ if (bytes_available)
+ FD_SET (channel, &Available);
+ }
+ continue;
+ }
+#endif /* vipc */
+
+ /* Read data from the process, starting with our
+ buffered-ahead character if we have one. */
+
+ nread = read_process_output (proc, channel);
+ if (nread > 0)
+ {
+ /* Since read_process_output can run a filter,
+ which can call accept-process-output,
+ don't try to read from any other processes
+ before doing the select again. */
+ FD_ZERO (&Available);
+
+ if (do_display)
+ redisplay_preserve_echo_area ();
+ }
+#ifdef EWOULDBLOCK
+ else if (nread == -1 && errno == EWOULDBLOCK)
+ ;
+#else
+#ifdef O_NONBLOCK
+ else if (nread == -1 && errno == EAGAIN)
+ ;
+#else
+#ifdef O_NDELAY
+ else if (nread == -1 && errno == EAGAIN)
+ ;
+ /* Note that we cannot distinguish between no input
+ available now and a closed pipe.
+ With luck, a closed pipe will be accompanied by
+ subprocess termination and SIGCHLD. */
+ else if (nread == 0 && !NETCONN_P (proc))
+ ;
+#endif /* O_NDELAY */
+#endif /* O_NONBLOCK */
+#endif /* EWOULDBLOCK */
+#ifdef HAVE_PTYS
+ /* On some OSs with ptys, when the process on one end of
+ a pty exits, the other end gets an error reading with
+ errno = EIO instead of getting an EOF (0 bytes read).
+ Therefore, if we get an error reading and errno =
+ EIO, just continue, because the child process has
+ exited and should clean itself up soon (e.g. when we
+ get a SIGCHLD). */
+ else if (nread == -1 && errno == EIO && !NETCONN_P (proc))
+ ;
+#endif /* HAVE_PTYS */
+/* If we can detect process termination, don't consider the process
+ gone just because its pipe is closed. */
+#ifdef SIGCHLD
+ else if (nread == 0 && !NETCONN_P (proc))
+ ;
+#endif
+ else
+ {
+ /* Preserve status of processes already terminated. */
+ XSETINT (XPROCESS (proc)->tick, ++process_tick);
+ deactivate_process (proc);
+ if (!NULL (XPROCESS (proc)->raw_status_low))
+ update_status (XPROCESS (proc));
+ if (EQ (XPROCESS (proc)->status, Qrun))
+ XPROCESS (proc)->status
+ = Fcons (Qexit, Fcons (make_number (256), Qnil));
+ }
+ }
+ } /* end for */
+ } /* end while */
+
+ /* If calling from keyboard input, do not quit
+ since we want to return C-g as an input character.
+ Otherwise, do pending quit if requested. */
+ if (read_kbd >= 0)
+ {
+ /* Prevent input_pending from remaining set if we quit. */
+ clear_input_pending ();
+ QUIT;
+ }
+}
+
+/* Actually call the filter. This gets the information via variables
+ because internal_condition_case won't pass arguments. */
+
+Lisp_Object
+run_filter ()
+{
+ return call2 (this_filter, filter_process, filter_string);
+}
+
+/* Read pending output from the process channel,
+ starting with our buffered-ahead character if we have one.
+ Yield number of characters read.
+
+ This function reads at most 1024 characters.
+ If you want to read all available subprocess output,
+ you must call it repeatedly until it returns zero. */
+
+read_process_output (proc, channel)
+ Lisp_Object proc;
+ register int channel;
+{
+ register int nchars;
+ char chars[1024];
+ register Lisp_Object outstream;
+ register struct buffer *old = current_buffer;
+ register struct Lisp_Process *p = XPROCESS (proc);
+ register int opoint;
+
+ if (proc_buffered_char[channel] < 0)
+ nchars = read (channel, chars, sizeof chars);
+ else
+ {
+ chars[0] = proc_buffered_char[channel];
+ proc_buffered_char[channel] = -1;
+ nchars = read (channel, chars + 1, sizeof chars - 1);
+ if (nchars < 0)
+ nchars = 1;
+ else
+ nchars = nchars + 1;
+ }
+
+ if (nchars <= 0) return nchars;
+
+ outstream = p->filter;
+ if (!NULL (outstream))
+ {
+ int count = specpdl_ptr - specpdl;
+ specbind (Qinhibit_quit, Qt);
+ this_filter = outstream;
+ filter_process = proc;
+ filter_string = make_string (chars, nchars);
+ call2 (this_filter, filter_process, filter_string);
+ /* internal_condition_case (run_filter, Qerror, Fidentity); */
+ unbind_to (count);
+ return nchars;
+ }
+
+ /* If no filter, write into buffer if it isn't dead. */
+ if (!NULL (p->buffer) && !NULL (XBUFFER (p->buffer)->name))
+ {
+ Lisp_Object tem;
+
+ Fset_buffer (p->buffer);
+ opoint = point;
+
+ /* Insert new output into buffer
+ at the current end-of-output marker,
+ thus preserving logical ordering of input and output. */
+ if (XMARKER (p->mark)->buffer)
+ SET_PT (marker_position (p->mark));
+ else
+ SET_PT (ZV);
+ if (point <= opoint)
+ opoint += nchars;
+
+ tem = current_buffer->read_only;
+ current_buffer->read_only = Qnil;
+ insert (chars, nchars);
+ current_buffer->read_only = tem;
+ Fset_marker (p->mark, make_number (point), p->buffer);
+ update_mode_lines++;
+
+ SET_PT (opoint);
+ set_buffer_internal (old);
+ }
+ return nchars;
+}
+
+DEFUN ("waiting-for-user-input-p", Fwaiting_for_user_input_p, Swaiting_for_user_input_p,
+ 0, 0, 0,
+ "Returns non-NIL if emacs is waiting for input from the user.\n\
+This is intended for use by asynchronous process output filters and sentinels.")
+ ()
+{
+ return ((waiting_for_user_input_p) ? Qt : Qnil);
+}
+
+/* Sending data to subprocess */
+
+jmp_buf send_process_frame;
+
+send_process_trap ()
+{
+#ifdef BSD4_1
+ sigrelse (SIGPIPE);
+ sigrelse (SIGALRM);
+#endif /* BSD4_1 */
+ longjmp (send_process_frame, 1);
+}
+
+send_process (proc, buf, len)
+ Lisp_Object proc;
+ char *buf;
+ int len;
+{
+ /* Don't use register vars; longjmp can lose them. */
+ int rv;
+ unsigned char *procname = XSTRING (XPROCESS (proc)->name)->data;
+
+ if (!NULL (XPROCESS (proc)->raw_status_low))
+ update_status (XPROCESS (proc));
+ if (! EQ (XPROCESS (proc)->status, Qrun))
+ error ("Process %s not running", procname);
+
+ if (!setjmp (send_process_frame))
+ while (len > 0)
+ {
+ signal (SIGPIPE, send_process_trap);
+ rv = write (XFASTINT (XPROCESS (proc)->outfd), buf, len);
+ signal (SIGPIPE, SIG_DFL);
+ if (rv < 0)
+ {
+ if (0
+#ifdef EWOULDBLOCK
+ || errno == EWOULDBLOCK
+#endif
+#ifdef EAGAIN
+ || errno == EAGAIN
+#endif
+ )
+ {
+ /* It would be nice to accept process output here,
+ but that is difficult. For example, it could
+ garbage what we are sending if that is from a buffer. */
+ immediate_quit = 1;
+ QUIT;
+ sleep (1);
+ immediate_quit = 0;
+ continue;
+ }
+ report_file_error ("writing to process", Fcons (proc, Qnil));
+ }
+ buf += rv;
+ len -= rv;
+ }
+ else
+ {
+ XPROCESS (proc)->raw_status_low = Qnil;
+ XPROCESS (proc)->raw_status_high = Qnil;
+ XPROCESS (proc)->status = Fcons (Qexit, Fcons (make_number (256), Qnil));
+ XSETINT (XPROCESS (proc)->tick, ++process_tick);
+ deactivate_process (proc);
+ error ("SIGPIPE raised on process %s; closed it", procname);
+ }
+}
+
+DEFUN ("process-send-region", Fprocess_send_region, Sprocess_send_region,
+ 3, 3, 0,
+ "Send current contents of region as input to PROCESS.\n\
+PROCESS may be a process name.\n\
+Called from program, takes three arguments, PROCESS, START and END.")
+ (process, start, end)
+ Lisp_Object process, start, end;
+{
+ Lisp_Object proc;
+ int start1;
+
+ proc = get_process (process);
+ validate_region (&start, &end);
+
+ if (XINT (start) < GPT && XINT (end) > GPT)
+ move_gap (start);
+
+ start1 = XINT (start);
+ send_process (proc, &FETCH_CHAR (start1), XINT (end) - XINT (start));
+
+ return Qnil;
+}
+
+DEFUN ("process-send-string", Fprocess_send_string, Sprocess_send_string,
+ 2, 2, 0,
+ "Send PROCESS the contents of STRING as input.\n\
+PROCESS may be a process name.")
+ (process, string)
+ Lisp_Object process, string;
+{
+ Lisp_Object proc;
+ CHECK_STRING (string, 1);
+ proc = get_process (process);
+ send_process (proc, XSTRING (string)->data, XSTRING (string)->size);
+ return Qnil;
+}
+
+/* send a signal number SIGNO to PROCESS.
+ CURRENT_GROUP means send to the process group that currently owns
+ the terminal being used to communicate with PROCESS.
+ This is used for various commands in shell mode.
+ If NOMSG is zero, insert signal-announcements into process's buffers
+ right away. */
+
+process_send_signal (process, signo, current_group, nomsg)
+ Lisp_Object process;
+ int signo;
+ Lisp_Object current_group;
+ int nomsg;
+{
+ Lisp_Object proc;
+ register struct Lisp_Process *p;
+ int gid;
+ int no_pgrp = 0;
+
+ proc = get_process (process);
+ p = XPROCESS (proc);
+
+ if (!EQ (p->childp, Qt))
+ error ("Process %s is not a subprocess",
+ XSTRING (p->name)->data);
+ if (!XFASTINT (p->infd))
+ error ("Process %s is not active",
+ XSTRING (p->name)->data);
+
+ if (NULL (p->pty_flag))
+ current_group = Qnil;
+
+#ifdef TIOCGPGRP /* Not sure about this! (fnf) */
+ /* If we are using pgrps, get a pgrp number and make it negative. */
+ if (!NULL (current_group))
+ {
+ /* If possible, send signals to the entire pgrp
+ by sending an input character to it. */
+#ifndef SIGNALS_VIA_CHARACTERS
+#if defined (TIOCGLTC) && defined (TIOCGETC)
+ struct tchars c;
+ struct ltchars lc;
+
+ switch (signo)
+ {
+ case SIGINT:
+ ioctl (XFASTINT (p->infd), TIOCGETC, &c);
+ send_process (proc, &c.t_intrc, 1);
+ return Qnil;
+ case SIGQUIT:
+ ioctl (XFASTINT (p->infd), TIOCGETC, &c);
+ send_process (proc, &c.t_quitc, 1);
+ return Qnil;
+#ifdef SIGTSTP
+ case SIGTSTP:
+ ioctl (XFASTINT (p->infd), TIOCGLTC, &lc);
+ send_process (proc, &lc.t_suspc, 1);
+ return Qnil;
+#endif
+ }
+#endif /* have TIOCGLTC and have TIOCGETC */
+#endif /* not SIGNALS_VIA_CHARACTERS */
+ /* It is possible that the following code would work
+ on other kinds of USG systems, not just on the IRIS.
+ This should be tried in Emacs 19. */
+#ifdef SIGNALS_VIA_CHARACTERS
+ struct termio t;
+ switch (signo)
+ {
+ case SIGINT:
+ ioctl (XFASTINT (p->infd), TCGETA, &t);
+ send_process (proc, &t.c_cc[VINTR], 1);
+ return Qnil;
+ case SIGQUIT:
+ ioctl (XFASTINT (p->infd), TCGETA, &t);
+ send_process (proc, &t.c_cc[VQUIT], 1);
+ return Qnil;
+#ifdef SIGTSTP
+ case SIGTSTP:
+ ioctl (XFASTINT (p->infd), TCGETA, &t);
+ send_process (proc, &t.c_cc[VSWTCH], 1);
+ return Qnil;
+#endif
+ }
+#endif /* SIGNALS_VIA_CHARACTERS */
+
+ /* Get the pgrp using the tty itself, if we have that.
+ Otherwise, use the pty to get the pgrp. */
+#if defined (pfa)
+ /* TICGPGRP symbol defined in sys/ioctl.h at E50.
+ But, TIOCGPGRP does not work on E50.
+ This way, we will use -1, since the ioctl won't change it.
+ (saka@pfu.fujitsu.co.JP.) */
+ gid = -1;
+#endif
+ if (!NULL (p->subtty))
+ ioctl (XFASTINT (p->subtty), TIOCGPGRP, &gid);
+ else
+ ioctl (XFASTINT (p->infd), TIOCGPGRP, &gid);
+ if (gid == -1)
+ no_pgrp = 1;
+ else
+ gid = - gid;
+ }
+ else
+ gid = - XFASTINT (p->pid);
+#else /* not using pgrps */
+ /* Can't select pgrps on this system, so we know that
+ the child itself heads the pgrp. */
+ gid = - XFASTINT (p->pid);
+#endif /* not using pgrps */
+
+ switch (signo)
+ {
+#ifdef SIGCONT
+ case SIGCONT:
+ p->raw_status_low = Qnil;
+ p->raw_status_high = Qnil;
+ p->status = Qrun;
+ XSETINT (p->tick, ++process_tick);
+ if (!nomsg)
+ status_notify ();
+ break;
+#endif
+ case SIGINT:
+ case SIGQUIT:
+ case SIGKILL:
+ flush_pending_output (XFASTINT (p->infd));
+ break;
+ }
+
+ /* If we don't have process groups, send the signal to the immediate subprocess.
+ That isn't really right, but it's better than any obvious alternative. */
+ if (no_pgrp)
+ {
+ kill (XFASTINT (p->pid), signo);
+ return;
+ }
+
+ /* gid may be a pid, or minus a pgrp's number */
+#ifdef TIOCSIGSEND
+ if (!NULL (current_group))
+ ioctl (XFASTINT (p->infd), TIOCSIGSEND, signo);
+ else
+ {
+ gid = - XFASTINT (p->pid);
+ kill (gid, signo);
+ }
+#else /* no TIOCSIGSEND */
+#ifdef BSD
+ /* On bsd, [man says] kill does not accept a negative number to kill a pgrp.
+ Must do that differently. */
+ killpg (-gid, signo);
+#else /* Not BSD. */
+ kill (gid, signo);
+#endif /* Not BSD. */
+#endif /* no TIOCSIGSEND */
+}
+
+DEFUN ("interrupt-process", Finterrupt_process, Sinterrupt_process, 0, 2, 0,
+ "Interrupt process PROCESS. May be process or name of one.\n\
+Nil or no arg means current buffer's process.\n\
+Second arg CURRENT-GROUP non-nil means send signal to\n\
+the current process-group of the process's controlling terminal\n\
+rather than to the process's own process group.\n\
+If the process is a shell, this means interrupt current subjob\n\
+rather than the shell.")
+ (process, current_group)
+ Lisp_Object process, current_group;
+{
+ process_send_signal (process, SIGINT, current_group, 0);
+ return process;
+}
+
+DEFUN ("kill-process", Fkill_process, Skill_process, 0, 2, 0,
+ "Kill process PROCESS. May be process or name of one.\n\
+See function interrupt-process for more details on usage.")
+ (process, current_group)
+ Lisp_Object process, current_group;
+{
+ process_send_signal (process, SIGKILL, current_group, 0);
+ return process;
+}
+
+DEFUN ("quit-process", Fquit_process, Squit_process, 0, 2, 0,
+ "Send QUIT signal to process PROCESS. May be process or name of one.\n\
+See function interrupt-process for more details on usage.")
+ (process, current_group)
+ Lisp_Object process, current_group;
+{
+ process_send_signal (process, SIGQUIT, current_group, 0);
+ return process;
+}
+
+DEFUN ("stop-process", Fstop_process, Sstop_process, 0, 2, 0,
+ "Stop process PROCESS. May be process or name of one.\n\
+See function interrupt-process for more details on usage.")
+ (process, current_group)
+ Lisp_Object process, current_group;
+{
+#ifndef SIGTSTP
+ error ("no SIGTSTP support");
+#else
+ process_send_signal (process, SIGTSTP, current_group, 0);
+#endif
+ return process;
+}
+
+DEFUN ("continue-process", Fcontinue_process, Scontinue_process, 0, 2, 0,
+ "Continue process PROCESS. May be process or name of one.\n\
+See function interrupt-process for more details on usage.")
+ (process, current_group)
+ Lisp_Object process, current_group;
+{
+#ifdef SIGCONT
+ process_send_signal (process, SIGCONT, current_group, 0);
+#else
+ error ("no SIGCONT support");
+#endif
+ return process;
+}
+
+DEFUN ("process-send-eof", Fprocess_send_eof, Sprocess_send_eof, 0, 1, 0,
+ "Make PROCESS see end-of-file in its input.\n\
+Eof comes after any text already sent to it.\n\
+nil or no arg means current buffer's process.")
+ (process)
+ Lisp_Object process;
+{
+ Lisp_Object proc;
+
+ proc = get_process (process);
+ /* Sending a zero-length record is supposed to mean eof
+ when TIOCREMOTE is turned on. */
+#ifdef DID_REMOTE
+ {
+ char buf[1];
+ write (XFASTINT (XPROCESS (proc)->outfd), buf, 0);
+ }
+#else /* did not do TOICREMOTE */
+ if (!NULL (XPROCESS (proc)->pty_flag))
+ send_process (proc, "\004", 1);
+ else
+ {
+ close (XPROCESS (proc)->outfd);
+ XFASTINT (XPROCESS (proc)->outfd) = open ("/dev/null", O_WRONLY);
+ }
+
+#endif /* did not do TOICREMOTE */
+ return process;
+}
+
+/* Kill all processes associated with `buffer'.
+ If `buffer' is nil, kill all processes */
+
+kill_buffer_processes (buffer)
+ Lisp_Object buffer;
+{
+ Lisp_Object tail, proc;
+
+ for (tail = Vprocess_alist; XGCTYPE (tail) == Lisp_Cons;
+ tail = XCONS (tail)->cdr)
+ {
+ proc = XCONS (XCONS (tail)->car)->cdr;
+ if (XGCTYPE (proc) == Lisp_Process
+ && (NULL (buffer) || EQ (XPROCESS (proc)->buffer, buffer)))
+ {
+ if (NETCONN_P (proc))
+ deactivate_process (proc);
+ else if (XFASTINT (XPROCESS (proc)->infd))
+ process_send_signal (proc, SIGHUP, Qnil, 1);
+ }
+ }
+}
+
+/* On receipt of a signal that a child status has changed,
+ loop asking about children with changed statuses until
+ the system says there are no more.
+ All we do is change the status;
+ we do not run sentinels or print notifications.
+ That is saved for the next time keyboard input is done,
+ in order to avoid timing errors. */
+
+/** WARNING: this can be called during garbage collection.
+ Therefore, it must not be fooled by the presence of mark bits in
+ Lisp objects. */
+
+/** USG WARNING: Although it is not obvious from the documentation
+ in signal(2), on a USG system the SIGCLD handler MUST NOT call
+ signal() before executing at least one wait(), otherwise the handler
+ will be called again, resulting in an infinite loop. The relevant
+ portion of the documentation reads "SIGCLD signals will be queued
+ and the signal-catching function will be continually reentered until
+ the queue is empty". Invoking signal() causes the kernel to reexamine
+ the SIGCLD queue. Fred Fish, UniSoft Systems Inc. */
+
+sigchld_handler (signo)
+ int signo;
+{
+ int old_errno = errno;
+ Lisp_Object proc;
+ register struct Lisp_Process *p;
+
+#ifdef BSD4_1
+ extern int synch_process_pid;
+ extern int sigheld;
+ sigheld |= sigbit (SIGCHLD);
+#endif
+
+ while (1)
+ {
+ register int pid;
+ WAITTYPE w;
+ Lisp_Object tail;
+
+#ifdef WNOHANG
+#ifndef WUNTRACED
+#define WUNTRACED 0
+#endif /* no WUNTRACED */
+ /* Keep trying to get a status until we get a definitive result. */
+ do
+ {
+ errno = 0;
+ pid = wait3 (&w, WNOHANG | WUNTRACED, 0);
+ }
+ while (pid <= 0 && errno == EINTR);
+
+ if (pid <= 0)
+ {
+ /* A real failure. We have done all our job, so return. */
+
+ /* USG systems forget handlers when they are used;
+ must reestablish each time */
+#ifdef USG
+ signal (signo, sigchld_handler); /* WARNING - must come after wait3() */
+#endif
+#ifdef BSD4_1
+ sigheld &= ~sigbit (SIGCHLD);
+ sigrelse (SIGCHLD);
+#endif
+ errno = old_errno;
+ return;
+ }
+#else
+ pid = wait (&w);
+#endif /* no WNOHANG */
+
+#ifdef BSD4_1
+ if (synch_process_pid == pid)
+ synch_process_pid = 0; /* Zero it to show process has died. */
+#endif
+
+ /* Find the process that signaled us, and record its status. */
+
+ p = 0;
+ for (tail = Vprocess_alist; XSYMBOL (tail) != XSYMBOL (Qnil); tail = XCONS (tail)->cdr)
+ {
+ proc = XCONS (XCONS (tail)->car)->cdr;
+ p = XPROCESS (proc);
+ if (EQ (p->childp, Qt) && XFASTINT (p->pid) == pid)
+ break;
+ p = 0;
+ }
+
+ /* If we don't recognize the pid number,
+ look for a process being created. */
+
+ if (p == 0)
+ for (tail = Vprocess_alist; XSYMBOL (tail) != XSYMBOL (Qnil); tail = XCONS (tail)->cdr)
+ {
+ proc = XCONS (XCONS (tail)->car)->cdr;
+ p = XPROCESS (proc);
+ if (XINT (p->pid) == -1)
+ break;
+ p = 0;
+ }
+
+ /* Change the status of the process that was found. */
+
+ if (p != 0)
+ {
+ union { int i; WAITTYPE wt; } u;
+
+ XSETINT (p->tick, ++process_tick);
+ u.wt = w;
+ XFASTINT (p->raw_status_low) = u.i & 0xffff;
+ XFASTINT (p->raw_status_high) = u.i >> 16;
+
+ /* If process has terminated, stop waiting for its output. */
+ if (WIFSIGNALED (w) || WIFEXITED (w))
+ if (p->infd)
+ FD_CLR (p->infd, &input_wait_mask);
+ }
+ else
+ {
+ /* Report the status of the synchronous process. */
+ if (WIFEXITED (w))
+ synch_process_retcode = WRETCODE (w);
+ else if (WIFSIGNALED (w))
+ synch_process_death = sys_siglist[WTERMSIG (w)];
+ }
+
+ /* On some systems, we must return right away.
+ If any more processes want to signal us, we will
+ get another signal.
+ Otherwise (on systems that have WNOHANG), loop around
+ to use up all the processes that have something to tell us. */
+#if defined (USG) && ! (defined (HPUX) && defined (WNOHANG))
+#ifdef USG
+ signal (signo, sigchld_handler);
+#endif
+ errno = old_errno;
+ return;
+#endif /* USG, but not HPUX with WNOHANG */
+ }
+}
+
+/* Report all recent events of a change in process status
+ (either run the sentinel or output a message).
+ This is done while Emacs is waiting for keyboard input. */
+
+status_notify ()
+{
+ register Lisp_Object proc, buffer;
+ Lisp_Object tail = Qnil;
+ Lisp_Object msg = Qnil;
+ struct gcpro gcpro1, gcpro2;
+
+ /* We need to gcpro tail; if read_process_output calls a filter
+ which deletes a process and removes the cons to which tail points
+ from Vprocess_alist, tail becomes an unprotected reference. */
+ GCPRO2 (tail, msg);
+
+ for (tail = Vprocess_alist; !NULL (tail); tail = Fcdr (tail))
+ {
+ Lisp_Object symbol;
+ register struct Lisp_Process *p;
+
+ proc = Fcdr (Fcar (tail));
+ p = XPROCESS (proc);
+
+ if (XINT (p->tick) != XINT (p->update_tick))
+ {
+ XSETINT (p->update_tick, XINT (p->tick));
+
+ /* If process is still active, read any output that remains. */
+ if (XFASTINT (p->infd))
+ while (read_process_output (proc, XFASTINT (p->infd)) > 0);
+
+ buffer = p->buffer;
+
+ /* Get the text to use for the message. */
+ if (!NULL (p->raw_status_low))
+ update_status (p);
+ msg = status_message (p->status);
+
+ /* If process is terminated, deactivate it or delete it. */
+ symbol = p->status;
+ if (XTYPE (p->status) == Lisp_Cons)
+ symbol = XCONS (p->status)->car;
+
+ if (EQ (symbol, Qsignal) || EQ (symbol, Qexit)
+ || EQ (symbol, Qclosed))
+ {
+ if (delete_exited_processes)
+ remove_process (proc);
+ else
+ deactivate_process (proc);
+ }
+
+ /* Now output the message suitably. */
+ if (!NULL (p->sentinel))
+ exec_sentinel (proc, msg);
+ /* Don't bother with a message in the buffer
+ when a process becomes runnable. */
+ else if (!EQ (symbol, Qrun) && !NULL (buffer))
+ {
+ Lisp_Object ro = XBUFFER (buffer)->read_only;
+ Lisp_Object tem;
+ struct buffer *old = current_buffer;
+ int opoint;
+
+ /* Avoid error if buffer is deleted
+ (probably that's why the process is dead, too) */
+ if (NULL (XBUFFER (buffer)->name))
+ continue;
+ Fset_buffer (buffer);
+ opoint = point;
+ /* Insert new output into buffer
+ at the current end-of-output marker,
+ thus preserving logical ordering of input and output. */
+ if (XMARKER (p->mark)->buffer)
+ SET_PT (marker_position (p->mark));
+ else
+ SET_PT (ZV);
+ if (point <= opoint)
+ opoint += XSTRING (msg)->size + XSTRING (p->name)->size + 10;
+
+ tem = current_buffer->read_only;
+ current_buffer->read_only = Qnil;
+ InsStr ("\nProcess ");
+ Finsert (1, &p->name);
+ InsStr (" ");
+ Finsert (1, &msg);
+ current_buffer->read_only = tem;
+ Fset_marker (p->mark, make_number (point), p->buffer);
+
+ SET_PT (opoint);
+ set_buffer_internal (old);
+ }
+ }
+ } /* end for */
+
+ update_mode_lines++; /* in case buffers use %s in mode-line-format */
+ redisplay_preserve_echo_area ();
+
+ update_tick = process_tick;
+
+ UNGCPRO;
+}
+
+exec_sentinel (proc, reason)
+ Lisp_Object proc, reason;
+{
+ Lisp_Object sentinel;
+ register struct Lisp_Process *p = XPROCESS (proc);
+ int count = specpdl_ptr - specpdl;
+
+ sentinel = p->sentinel;
+ if (NULL (sentinel))
+ return;
+
+ p->sentinel = Qnil;
+ specbind (Qinhibit_quit, Qt);
+ this_filter = sentinel;
+ filter_process = proc;
+ filter_string = reason;
+ call2 (this_filter, filter_process, filter_string);
+/* internal_condition_case (run_filter, Qerror, Fidentity); */
+ unbind_to (count);
+ p->sentinel = sentinel;
+}
+
+init_process ()
+{
+ register int i;
+
+#ifdef SIGCHLD
+#ifndef CANNOT_DUMP
+ if (! noninteractive || initialized)
+#endif
+ signal (SIGCHLD, sigchld_handler);
+#endif
+
+ FD_ZERO (&input_wait_mask);
+ FD_SET (0, &input_wait_mask);
+ Vprocess_alist = Qnil;
+ for (i = 0; i < MAXDESC; i++)
+ {
+ chan_process[i] = Qnil;
+ proc_buffered_char[i] = -1;
+ }
+}
+
+syms_of_process ()
+{
+ Qprocessp = intern ("processp");
+ staticpro (&Qprocessp);
+ Qrun = intern ("run");
+ staticpro (&Qrun);
+ Qstop = intern ("stop");
+ staticpro (&Qstop);
+ Qsignal = intern ("signal");
+ staticpro (&Qsignal);
+
+ /* Qexit is already staticpro'd by syms_of_eval; don't staticpro it
+ here again.
+
+ Qexit = intern ("exit");
+ staticpro (&Qexit); */
+
+ Qopen = intern ("open");
+ staticpro (&Qopen);
+ Qclosed = intern ("closed");
+ staticpro (&Qclosed);
+
+ staticpro (&Vprocess_alist);
+
+ DEFVAR_BOOL ("delete-exited-processes", &delete_exited_processes,
+ "*Non-nil means delete processes immediately when they exit.\n\
+nil means don't delete them until `list-processes' is run.");
+
+ delete_exited_processes = 1;
+
+ DEFVAR_LISP ("process-connection-type", &Vprocess_connection_type,
+ "Control type of device used to communicate with subprocesses.\n\
+Values are nil to use a pipe, t for a pty (or pipe if ptys not supported).\n\
+Value takes effect when `start-process' is called.");
+ Vprocess_connection_type = Qt;
+
+ defsubr (&Sprocessp);
+ defsubr (&Sget_process);
+ defsubr (&Sget_buffer_process);
+ defsubr (&Sdelete_process);
+ defsubr (&Sprocess_status);
+ defsubr (&Sprocess_exit_status);
+ defsubr (&Sprocess_id);
+ defsubr (&Sprocess_name);
+ defsubr (&Sprocess_command);
+ defsubr (&Sset_process_buffer);
+ defsubr (&Sprocess_buffer);
+ defsubr (&Sprocess_mark);
+ defsubr (&Sset_process_filter);
+ defsubr (&Sprocess_filter);
+ defsubr (&Sset_process_sentinel);
+ defsubr (&Sprocess_sentinel);
+ defsubr (&Sprocess_kill_without_query);
+ defsubr (&Slist_processes);
+ defsubr (&Sprocess_list);
+ defsubr (&Sstart_process);
+#ifdef HAVE_SOCKETS
+ defsubr (&Sopen_network_stream);
+#endif /* HAVE_SOCKETS */
+ defsubr (&Saccept_process_output);
+ defsubr (&Sprocess_send_region);
+ defsubr (&Sprocess_send_string);
+ defsubr (&Sinterrupt_process);
+ defsubr (&Skill_process);
+ defsubr (&Squit_process);
+ defsubr (&Sstop_process);
+ defsubr (&Scontinue_process);
+ defsubr (&Sprocess_send_eof);
+ defsubr (&Swaiting_for_user_input_p);
+}
+
+#endif /* subprocesses */
diff --git a/src/process.h b/src/process.h
new file mode 100644
index 00000000000..5474e61b6dc
--- /dev/null
+++ b/src/process.h
@@ -0,0 +1,76 @@
+/* Definitions for asynchronous process control in GNU Emacs.
+ Copyright (C) 1985, 1990 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/*
+ * Structure records pertinent information about open channels.
+ * There is one channel associated with each process.
+ */
+
+struct Lisp_Process
+ {
+ int size;
+ struct Lisp_Vector *v_next;
+ /* Descriptor by which we read from this process */
+ Lisp_Object infd;
+ /* Descriptor by which we write to this process */
+ Lisp_Object outfd;
+ /* Descriptor for the tty which this process is using.
+ nil if we didn't record it (on some systems, there's no need). */
+ Lisp_Object subtty;
+ /* Name of this process */
+ Lisp_Object name;
+ /* List of command arguments that this process was run with */
+ Lisp_Object command;
+ /* (funcall FILTER PROC STRING) (if FILTER is non-nil)
+ to dispose of a bunch of chars from the process all at once */
+ Lisp_Object filter;
+ /* (funcall SENTINEL PROCESS) when process state changes */
+ Lisp_Object sentinel;
+ /* Buffer that output is going to */
+ Lisp_Object buffer;
+ /* Number of this process */
+ Lisp_Object pid;
+ /* Non-nil if this is really a command channel */
+ Lisp_Object command_channel_p;
+ /* Non-nil if this is really a child process */
+ Lisp_Object childp;
+ /* Marker set to end of last buffer-inserted output from this process */
+ Lisp_Object mark;
+ /* Non-nil means kill silently if Emacs is exited. */
+ Lisp_Object kill_without_query;
+ /* Record the process status in the raw form in which it comes from `wait'.
+ This is to avoid consing in a signal handler. */
+ Lisp_Object raw_status_low;
+ Lisp_Object raw_status_high;
+ /* Symbol indicating status of process.
+ This may be a symbol: run, open, or closed.
+ Or it may be a list, whose car is stop, exit or signal
+ and whose cdr is a pair (EXIT_CODE . COREDUMP_FLAG)
+ or (SIGNAL_NUMBER . COREDUMP_FLAG). */
+ Lisp_Object status;
+ /* Non-nil if communicating through a pty. */
+ Lisp_Object pty_flag;
+ /* Event-count of last event in which this process changed status. */
+ Lisp_Object tick;
+ /* Event-count of last such event reported. */
+ Lisp_Object update_tick;
+};
+
+#define ChannelMask(n) (1<<(n))
diff --git a/src/ralloc.c b/src/ralloc.c
deleted file mode 100644
index 1f92b51be88..00000000000
--- a/src/ralloc.c
+++ /dev/null
@@ -1,426 +0,0 @@
-/* Block-relocating memory allocator.
- Copyright (C) 1990 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 1, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-/* NOTES:
-
- Only relocate the blocs neccessary for SIZE in r_alloc_sbrk,
- rather than all of them. This means allowing for a possible
- hole between the first bloc and the end of malloc storage. */
-
-#include "config.h"
-#include "lisp.h" /* Needed for xterm.h */
-#undef NULL
-#include "mem_limits.h"
-#include "xterm.h" /* Needed for BLOCK_INPUT */
-
-#define NIL ((POINTER) 0)
-
-
-/* System call to set the break value. */
-extern POINTER sbrk ();
-
-/* The break value, as seen by malloc (). */
-static POINTER virtual_break_value;
-
-/* The break value, viewed by the relocatable blocs. */
-static POINTER break_value;
-
-/* The REAL (i.e., page aligned) break value of the process. */
-static POINTER page_break_value;
-
-/* Macros for rounding. Note that rounding to any value is possible
- by changing the definition of PAGE. */
-#define PAGE (getpagesize ())
-#define ALIGNED(addr) (((unsigned int) (addr) & (PAGE - 1)) == 0)
-#define ROUNDUP(size) (((unsigned int) (size) + PAGE) & ~(PAGE - 1))
-#define ROUND_TO_PAGE(addr) (addr & (~(PAGE - 1)))
-#define EXCEEDS_ELISP_PTR(ptr) ((unsigned int) (ptr) >> VALBITS)
-
-/* Level of warnings issued. */
-static int warnlevel;
-
-/* Function to call to issue a warning;
- 0 means don't issue them. */
-static void (*warnfunction) ();
-
-static void
-check_memory_limits (address)
- POINTER address;
-{
- SIZE data_size = address - data_space_start;
-
- switch (warnlevel)
- {
- case 0:
- if (data_size > (lim_data / 4) * 3)
- {
- warnlevel++;
- (*warnfunction) ("Warning: past 75% of memory limit");
- }
- break;
-
- case 1:
- if (data_size > (lim_data / 20) * 17)
- {
- warnlevel++;
- (*warnfunction) ("Warning: past 85% of memory limit");
- }
- break;
-
- case 2:
- if (data_size > (lim_data / 20) * 19)
- {
- warnlevel++;
- (*warnfunction) ("Warning: past 95% of memory limit");
- }
- break;
-
- default:
- (*warnfunction) ("Warning: past acceptable memory limits");
- break;
- }
-
- if (EXCEEDS_ELISP_PTR (address))
- (*warnfunction) ("Warning: memory in use exceeds lisp pointer size");
-}
-
-/* Obtain SIZE bytes of space. If enough space is not presently available
- in our process reserve, (i.e., (page_break_value - break_value)),
- this means getting more page-aligned space from the system. */
-
-static void
-obtain (size)
- SIZE size;
-{
- SIZE already_available = page_break_value - break_value;
-
- if (already_available < size)
- {
- SIZE get = ROUNDUP (size);
-
- if (warnfunction)
- check_memory_limits (page_break_value);
-
- if (((int) sbrk (get)) < 0)
- abort ();
-
- page_break_value += get;
- }
-
- break_value += size;
-}
-
-/* Obtain SIZE bytes of space and return a pointer to the new area. */
-
-static POINTER
-get_more_space (size)
- SIZE size;
-{
- POINTER ptr = break_value;
- obtain (size);
- return ptr;
-}
-
-/* Note that SIZE bytes of space have been relinquished by the process.
- If SIZE is more than a page, return the space the system. */
-
-static void
-relinquish (size)
- SIZE size;
-{
- SIZE page_part = ROUND_TO_PAGE (size);
-
- if (page_part)
- {
- if (((int) (sbrk (- page_part))) < 0)
- abort ();
-
- page_break_value -= page_part;
- }
-
- break_value -= size;
- bzero (break_value, (size - page_part));
-}
-
-typedef struct bp
-{
- struct bp *next;
- struct bp *prev;
- POINTER *variable;
- POINTER data;
- SIZE size;
-} *bloc_ptr;
-
-#define NIL_BLOC ((bloc_ptr) 0)
-#define BLOC_PTR_SIZE (sizeof (struct bp))
-
-/* Head and tail of the list of relocatable blocs. */
-static bloc_ptr first_bloc, last_bloc;
-
-/* Declared in dispnew.c, this version dosen't fuck up if regions overlap. */
-extern void safe_bcopy ();
-
-/* Find the bloc reference by the address in PTR. Returns a pointer
- to that block. */
-
-static bloc_ptr
-find_bloc (ptr)
- POINTER *ptr;
-{
- register bloc_ptr p = first_bloc;
-
- while (p != NIL_BLOC)
- {
- if (p->variable == ptr && p->data == *ptr)
- return p;
-
- p = p->next;
- }
-
- return p;
-}
-
-/* Allocate a bloc of SIZE bytes and append it to the chain of blocs.
- Returns a pointer to the new bloc. */
-
-static bloc_ptr
-get_bloc (size)
- SIZE size;
-{
- register bloc_ptr new_bloc = (bloc_ptr) malloc (BLOC_PTR_SIZE);
-
- new_bloc->data = get_more_space (size);
- new_bloc->size = size;
- new_bloc->next = NIL_BLOC;
- new_bloc->variable = NIL;
-
- if (first_bloc)
- {
- new_bloc->prev = last_bloc;
- last_bloc->next = new_bloc;
- last_bloc = new_bloc;
- }
- else
- {
- first_bloc = last_bloc = new_bloc;
- new_bloc->prev = NIL_BLOC;
- }
-
- return new_bloc;
-}
-
-/* Relocate all blocs from BLOC on upward in the list to the zone
- indicated by ADDRESS. Direction of relocation is determined by
- the position of ADDRESS relative to BLOC->data.
-
- Note that ordering of blocs is not affected by this function. */
-
-static void
-relocate_some_blocs (bloc, address)
- bloc_ptr bloc;
- POINTER address;
-{
- register bloc_ptr b;
- POINTER data_zone = bloc->data;
- register SIZE data_zone_size = 0;
- register SIZE offset = bloc->data - address;
- POINTER new_data_zone = data_zone - offset;
-
- for (b = bloc; b != NIL_BLOC; b = b->next)
- {
- data_zone_size += b->size;
- b->data -= offset;
- *b->variable = b->data;
- }
-
- safe_bcopy (data_zone, new_data_zone, data_zone_size);
-}
-
-/* Free BLOC from the chain of blocs, relocating any blocs above it
- and returning BLOC->size bytes to the free area. */
-
-static void
-free_bloc (bloc)
- bloc_ptr bloc;
-{
- if (bloc == first_bloc && bloc == last_bloc)
- {
- first_bloc = last_bloc = NIL_BLOC;
- }
- else if (bloc == last_bloc)
- {
- last_bloc = bloc->prev;
- last_bloc->next = NIL_BLOC;
- }
- else if (bloc == first_bloc)
- {
- first_bloc = bloc->next;
- first_bloc->prev = NIL_BLOC;
- relocate_some_blocs (bloc->next, bloc->data);
- }
- else
- {
- bloc->next->prev = bloc->prev;
- bloc->prev->next = bloc->next;
- relocate_some_blocs (bloc->next, bloc->data);
- }
-
- relinquish (bloc->size);
- free (bloc);
-}
-
-static int use_relocatable_buffers;
-
-/* Obtain SIZE bytes of storage from the free pool, or the system,
- as neccessary. If relocatable blocs are in use, this means
- relocating them. */
-
-POINTER
-r_alloc_sbrk (size)
- long size;
-{
- POINTER ptr;
-
- if (! use_relocatable_buffers)
- return sbrk (size);
-
- if (size > 0)
- {
- obtain (size);
- if (first_bloc)
- {
- relocate_some_blocs (first_bloc, first_bloc->data + size);
- bzero (virtual_break_value, size);
- }
- }
- else if (size < 0)
- {
- if (first_bloc)
- relocate_some_blocs (first_bloc, first_bloc->data + size);
- relinquish (- size);
- }
-
- ptr = virtual_break_value;
- virtual_break_value += size;
- return ptr;
-}
-
-/* Allocate a relocatable bloc of storage of size SIZE. A pointer to
- the data is returned in *PTR. PTR is thus the address of some variable
- which will use the data area. */
-
-POINTER
-r_alloc (ptr, size)
- POINTER *ptr;
- SIZE size;
-{
- register bloc_ptr new_bloc;
-
- BLOCK_INPUT;
- new_bloc = get_bloc (size);
- new_bloc->variable = ptr;
- *ptr = new_bloc->data;
- UNBLOCK_INPUT;
-
- return *ptr;
-}
-
-/* Free a bloc of relocatable storage whose data is pointed to by PTR. */
-
-void
-r_alloc_free (ptr)
- register POINTER *ptr;
-{
- register bloc_ptr dead_bloc;
-
- BLOCK_INPUT;
- dead_bloc = find_bloc (ptr);
- if (dead_bloc == NIL_BLOC)
- abort ();
-
- free_bloc (dead_bloc);
- UNBLOCK_INPUT;
-}
-
-/* Given a pointer at address PTR to relocatable data, resize it
- to SIZE. This is done by obtaining a new block and freeing the
- old, unless SIZE is less than or equal to the current bloc size,
- in which case nothing happens and the current value is returned.
-
- The contents of PTR is changed to reflect the new bloc, and this
- value is returned. */
-
-POINTER
-r_re_alloc (ptr, size)
- POINTER *ptr;
- SIZE size;
-{
- register bloc_ptr old_bloc, new_bloc;
-
- BLOCK_INPUT;
- old_bloc = find_bloc (ptr);
- if (old_bloc == NIL_BLOC)
- abort ();
-
- if (size <= old_bloc->size)
- return *ptr;
-
- new_bloc = get_bloc (size);
- new_bloc->variable = ptr;
- safe_bcopy (old_bloc->data, new_bloc->data, old_bloc->size);
- *ptr = new_bloc->data;
-
- free_bloc (old_bloc);
- UNBLOCK_INPUT;
-
- return *ptr;
-}
-
-/* The hook `malloc' uses for the function which gets more space
- from the system. */
-extern POINTER (*__morecore) ();
-
-/* Intialize various things for memory allocation. */
-
-void
-malloc_init (start, warn_func)
- POINTER start;
- void (*warn_func) ();
-{
- static int malloc_initialized = 0;
-
- if (start)
- data_space_start = start;
-
- if (malloc_initialized)
- return;
-
- malloc_initialized = 1;
- __morecore = r_alloc_sbrk;
- virtual_break_value = break_value = sbrk (0);
- page_break_value = (POINTER) ROUNDUP (break_value);
- bzero (break_value, (page_break_value - break_value));
- use_relocatable_buffers = 1;
-
- lim_data = 0;
- warnlevel = 0;
- warnfunction = warn_func;
-
- get_lim_data ();
-}
diff --git a/src/recomp.com b/src/recomp.com
new file mode 100644
index 00000000000..3743f536b9b
--- /dev/null
+++ b/src/recomp.com
@@ -0,0 +1,21 @@
+$ ! VMS command file to recompile a .C file which needs recompilation.
+$ ! This is a .C files that has no .OBJ file or that is newer
+$ ! than the corresponding .OBJ file. This file is self contained
+$ ! and does not require you to do anything before running it.
+$
+$ file = f$search(f$parse(p1, ".C"), 1)
+$ cmd = p2
+$ if cmd .nes. "" then goto havcmd
+$ if "''ccom'" .eqs. "" then @precomp
+$ cmd = "ccom"
+$havcmd:
+$ name = f$parse(file,,,"NAME")
+$ obj = name + ".OBJ"
+$ if f$search(obj) .eqs. "" then goto docmd
+$ if f$cvtime(f$file(file, "RDT")) .les. f$cvtime(f$file(obj, "RDT")) then -
+ exit
+$ docmd:
+$ write sys$output "Compiling ''name'..."
+$ 'cmd' 'file'
+$ purge /nolog 'obj'
+$ write sys$output "---------------"
diff --git a/src/regex.c b/src/regex.c
new file mode 100644
index 00000000000..327d9e7bccd
--- /dev/null
+++ b/src/regex.c
@@ -0,0 +1,1725 @@
+/* Extended regular expression matching and search.
+ Copyright (C) 1985 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+In other words, you are welcome to use, share and improve this program.
+You are forbidden to forbid anyone else to use, share and improve
+what you give them. Help stamp out software-hoarding! */
+
+
+/* To test, compile with -Dtest.
+ This Dtestable feature turns this into a self-contained program
+ which reads a pattern, describes how it compiles,
+ then reads a string and searches for it. */
+
+
+#ifdef emacs
+
+/* The `emacs' switch turns on certain special matching commands
+ that make sense only in emacs. */
+
+#include "config.h"
+#include "lisp.h"
+#include "buffer.h"
+#include "syntax.h"
+
+#else /* not emacs */
+
+/*
+ * Define the syntax stuff, so we can do the \<...\> things.
+ */
+
+#ifndef Sword /* must be non-zero in some of the tests below... */
+#define Sword 1
+#endif
+
+#define SYNTAX(c) re_syntax_table[c]
+
+#ifdef SYNTAX_TABLE
+
+char *re_syntax_table;
+
+#else
+
+static char re_syntax_table[256];
+
+static void
+init_syntax_once ()
+{
+ register int c;
+ static int done = 0;
+
+ if (done)
+ return;
+
+ bzero (re_syntax_table, sizeof re_syntax_table);
+
+ for (c = 'a'; c <= 'z'; c++)
+ re_syntax_table[c] = Sword;
+
+ for (c = 'A'; c <= 'Z'; c++)
+ re_syntax_table[c] = Sword;
+
+ for (c = '0'; c <= '9'; c++)
+ re_syntax_table[c] = Sword;
+
+ done = 1;
+}
+
+#endif /* SYNTAX_TABLE */
+#endif /* not emacs */
+
+#include "regex.h"
+
+/* Number of failure points to allocate space for initially,
+ when matching. If this number is exceeded, more space is allocated,
+ so it is not a hard limit. */
+
+#ifndef NFAILURES
+#define NFAILURES 80
+#endif NFAILURES
+
+/* width of a byte in bits */
+
+#define BYTEWIDTH 8
+
+#ifndef SIGN_EXTEND_CHAR
+#define SIGN_EXTEND_CHAR(x) (x)
+#endif
+
+static int obscure_syntax = 0;
+
+/* Specify the precise syntax of regexp for compilation.
+ This provides for compatibility for various utilities
+ which historically have different, incompatible syntaxes.
+
+ The argument SYNTAX is a bit-mask containing the two bits
+ RE_NO_BK_PARENS and RE_NO_BK_VBAR. */
+
+int
+re_set_syntax (syntax)
+{
+ int ret;
+
+ ret = obscure_syntax;
+ obscure_syntax = syntax;
+ return ret;
+}
+
+/* re_compile_pattern takes a regular-expression string
+ and converts it into a buffer full of byte commands for matching.
+
+ PATTERN is the address of the pattern string
+ SIZE is the length of it.
+ BUFP is a struct re_pattern_buffer * which points to the info
+ on where to store the byte commands.
+ This structure contains a char * which points to the
+ actual space, which should have been obtained with malloc.
+ re_compile_pattern may use realloc to grow the buffer space.
+
+ The number of bytes of commands can be found out by looking in
+ the struct re_pattern_buffer that bufp pointed to,
+ after re_compile_pattern returns.
+*/
+
+#define PATPUSH(ch) (*b++ = (char) (ch))
+
+#define PATFETCH(c) \
+ {if (p == pend) goto end_of_pattern; \
+ c = * (unsigned char *) p++; \
+ if (translate) c = translate[c]; }
+
+#define PATFETCH_RAW(c) \
+ {if (p == pend) goto end_of_pattern; \
+ c = * (unsigned char *) p++; }
+
+#define PATUNFETCH p--
+
+#define EXTEND_BUFFER \
+ { char *old_buffer = bufp->buffer; \
+ if (bufp->allocated == (1<<16)) goto too_big; \
+ bufp->allocated *= 2; \
+ if (bufp->allocated > (1<<16)) bufp->allocated = (1<<16); \
+ if (!(bufp->buffer = (char *) realloc (bufp->buffer, bufp->allocated))) \
+ goto memory_exhausted; \
+ c = bufp->buffer - old_buffer; \
+ b += c; \
+ if (fixup_jump) \
+ fixup_jump += c; \
+ if (laststart) \
+ laststart += c; \
+ begalt += c; \
+ if (pending_exact) \
+ pending_exact += c; \
+ }
+
+static int store_jump (), insert_jump ();
+
+char *
+re_compile_pattern (pattern, size, bufp)
+ char *pattern;
+ int size;
+ struct re_pattern_buffer *bufp;
+{
+ register char *b = bufp->buffer;
+ register char *p = pattern;
+ char *pend = pattern + size;
+ register unsigned c, c1;
+ char *p1;
+ unsigned char *translate = (unsigned char *) bufp->translate;
+
+ /* address of the count-byte of the most recently inserted "exactn" command.
+ This makes it possible to tell whether a new exact-match character
+ can be added to that command or requires a new "exactn" command. */
+
+ char *pending_exact = 0;
+
+ /* address of the place where a forward-jump should go
+ to the end of the containing expression.
+ Each alternative of an "or", except the last, ends with a forward-jump
+ of this sort. */
+
+ char *fixup_jump = 0;
+
+ /* address of start of the most recently finished expression.
+ This tells postfix * where to find the start of its operand. */
+
+ char *laststart = 0;
+
+ /* In processing a repeat, 1 means zero matches is allowed */
+
+ char zero_times_ok;
+
+ /* In processing a repeat, 1 means many matches is allowed */
+
+ char many_times_ok;
+
+ /* address of beginning of regexp, or inside of last \( */
+
+ char *begalt = b;
+
+ /* Stack of information saved by \( and restored by \).
+ Four stack elements are pushed by each \(:
+ First, the value of b.
+ Second, the value of fixup_jump.
+ Third, the value of regnum.
+ Fourth, the value of begalt. */
+
+ int stackb[40];
+ int *stackp = stackb;
+ int *stacke = stackb + 40;
+ int *stackt;
+
+ /* Counts \('s as they are encountered. Remembered for the matching \),
+ where it becomes the "register number" to put in the stop_memory command */
+
+ int regnum = 1;
+
+ bufp->fastmap_accurate = 0;
+
+#ifndef emacs
+#ifndef SYNTAX_TABLE
+ /*
+ * Initialize the syntax table.
+ */
+ init_syntax_once();
+#endif
+#endif
+
+ if (bufp->allocated == 0)
+ {
+ bufp->allocated = 28;
+ if (bufp->buffer)
+ /* EXTEND_BUFFER loses when bufp->allocated is 0 */
+ bufp->buffer = (char *) realloc (bufp->buffer, 28);
+ else
+ /* Caller did not allocate a buffer. Do it for him */
+ bufp->buffer = (char *) malloc (28);
+ if (!bufp->buffer) goto memory_exhausted;
+ begalt = b = bufp->buffer;
+ }
+
+ while (p != pend)
+ {
+ if (b - bufp->buffer > bufp->allocated - 10)
+ /* Note that EXTEND_BUFFER clobbers c */
+ EXTEND_BUFFER;
+
+ PATFETCH (c);
+
+ switch (c)
+ {
+ case '$':
+ if (obscure_syntax & RE_TIGHT_VBAR)
+ {
+ if (! (obscure_syntax & RE_CONTEXT_INDEP_OPS) && p != pend)
+ goto normal_char;
+ /* Make operand of last vbar end before this `$'. */
+ if (fixup_jump)
+ store_jump (fixup_jump, jump, b);
+ fixup_jump = 0;
+ PATPUSH (endline);
+ break;
+ }
+
+ /* $ means succeed if at end of line, but only in special contexts.
+ If randomly in the middle of a pattern, it is a normal character. */
+ if (p == pend || *p == '\n'
+ || (obscure_syntax & RE_CONTEXT_INDEP_OPS)
+ || (obscure_syntax & RE_NO_BK_PARENS
+ ? *p == ')'
+ : *p == '\\' && p[1] == ')')
+ || (obscure_syntax & RE_NO_BK_VBAR
+ ? *p == '|'
+ : *p == '\\' && p[1] == '|'))
+ {
+ PATPUSH (endline);
+ break;
+ }
+ goto normal_char;
+
+ case '^':
+ /* ^ means succeed if at beg of line, but only if no preceding pattern. */
+
+ if (laststart && p[-2] != '\n'
+ && ! (obscure_syntax & RE_CONTEXT_INDEP_OPS))
+ goto normal_char;
+ if (obscure_syntax & RE_TIGHT_VBAR)
+ {
+ if (p != pattern + 1
+ && ! (obscure_syntax & RE_CONTEXT_INDEP_OPS))
+ goto normal_char;
+ PATPUSH (begline);
+ begalt = b;
+ }
+ else
+ PATPUSH (begline);
+ break;
+
+ case '+':
+ case '?':
+ if (obscure_syntax & RE_BK_PLUS_QM)
+ goto normal_char;
+ handle_plus:
+ case '*':
+ /* If there is no previous pattern, char not special. */
+ if (!laststart && ! (obscure_syntax & RE_CONTEXT_INDEP_OPS))
+ goto normal_char;
+ /* If there is a sequence of repetition chars,
+ collapse it down to equivalent to just one. */
+ zero_times_ok = 0;
+ many_times_ok = 0;
+ while (1)
+ {
+ zero_times_ok |= c != '+';
+ many_times_ok |= c != '?';
+ if (p == pend)
+ break;
+ PATFETCH (c);
+ if (c == '*')
+ ;
+ else if (!(obscure_syntax & RE_BK_PLUS_QM)
+ && (c == '+' || c == '?'))
+ ;
+ else if ((obscure_syntax & RE_BK_PLUS_QM)
+ && c == '\\')
+ {
+ int c1;
+ PATFETCH (c1);
+ if (!(c1 == '+' || c1 == '?'))
+ {
+ PATUNFETCH;
+ PATUNFETCH;
+ break;
+ }
+ c = c1;
+ }
+ else
+ {
+ PATUNFETCH;
+ break;
+ }
+ }
+
+ /* Star, etc. applied to an empty pattern is equivalent
+ to an empty pattern. */
+ if (!laststart)
+ break;
+
+ /* Now we know whether 0 matches is allowed,
+ and whether 2 or more matches is allowed. */
+ if (many_times_ok)
+ {
+ /* If more than one repetition is allowed,
+ put in a backward jump at the end. */
+ store_jump (b, maybe_finalize_jump, laststart - 3);
+ b += 3;
+ }
+ insert_jump (on_failure_jump, laststart, b + 3, b);
+ pending_exact = 0;
+ b += 3;
+ if (!zero_times_ok)
+ {
+ /* At least one repetition required: insert before the loop
+ a skip over the initial on-failure-jump instruction */
+ insert_jump (dummy_failure_jump, laststart, laststart + 6, b);
+ b += 3;
+ }
+ break;
+
+ case '.':
+ laststart = b;
+ PATPUSH (anychar);
+ break;
+
+ case '[':
+ while (b - bufp->buffer
+ > bufp->allocated - 3 - (1 << BYTEWIDTH) / BYTEWIDTH)
+ /* Note that EXTEND_BUFFER clobbers c */
+ EXTEND_BUFFER;
+
+ laststart = b;
+ if (*p == '^')
+ PATPUSH (charset_not), p++;
+ else
+ PATPUSH (charset);
+ p1 = p;
+
+ PATPUSH ((1 << BYTEWIDTH) / BYTEWIDTH);
+ /* Clear the whole map */
+ bzero (b, (1 << BYTEWIDTH) / BYTEWIDTH);
+ /* Read in characters and ranges, setting map bits */
+ while (1)
+ {
+ PATFETCH (c);
+ if (c == ']' && p != p1 + 1) break;
+ if (*p == '-' && p[1] != ']')
+ {
+ PATFETCH (c1);
+ PATFETCH (c1);
+ if (translate)
+ while (c <= c1)
+ {
+ register unsigned char mapped_c = translate[c];
+ b[mapped_c / BYTEWIDTH] |= 1 << (mapped_c % BYTEWIDTH);
+ c++;
+ }
+ else
+ while (c <= c1)
+ b[c / BYTEWIDTH] |= 1 << (c % BYTEWIDTH), c++;
+ }
+ else
+ {
+ if (translate)
+ c = translate[c];
+ b[c / BYTEWIDTH] |= 1 << (c % BYTEWIDTH);
+ }
+ }
+ /* Discard any bitmap bytes that are all 0 at the end of the map.
+ Decrement the map-length byte too. */
+ while ((int) b[-1] > 0 && b[b[-1] - 1] == 0)
+ b[-1]--;
+ b += b[-1];
+ break;
+
+ case '(':
+ if (! (obscure_syntax & RE_NO_BK_PARENS))
+ goto normal_char;
+ else
+ goto handle_open;
+
+ case ')':
+ if (! (obscure_syntax & RE_NO_BK_PARENS))
+ goto normal_char;
+ else
+ goto handle_close;
+
+ case '\n':
+ if (! (obscure_syntax & RE_NEWLINE_OR))
+ goto normal_char;
+ else
+ goto handle_bar;
+
+ case '|':
+ if (! (obscure_syntax & RE_NO_BK_VBAR))
+ goto normal_char;
+ else
+ goto handle_bar;
+
+ case '\\':
+ if (p == pend) goto invalid_pattern;
+ PATFETCH_RAW (c);
+ switch (c)
+ {
+ case '(':
+ if (obscure_syntax & RE_NO_BK_PARENS)
+ goto normal_backsl;
+ handle_open:
+ if (stackp == stacke) goto nesting_too_deep;
+ if (regnum < RE_NREGS)
+ {
+ PATPUSH (start_memory);
+ PATPUSH (regnum);
+ }
+ *stackp++ = b - bufp->buffer;
+ *stackp++ = fixup_jump ? fixup_jump - bufp->buffer + 1 : 0;
+ *stackp++ = regnum++;
+ *stackp++ = begalt - bufp->buffer;
+ fixup_jump = 0;
+ laststart = 0;
+ begalt = b;
+ break;
+
+ case ')':
+ if (obscure_syntax & RE_NO_BK_PARENS)
+ goto normal_backsl;
+ handle_close:
+ if (stackp == stackb) goto unmatched_close;
+ begalt = *--stackp + bufp->buffer;
+ if (fixup_jump)
+ store_jump (fixup_jump, jump, b);
+ if (stackp[-1] < RE_NREGS)
+ {
+ PATPUSH (stop_memory);
+ PATPUSH (stackp[-1]);
+ }
+ stackp -= 2;
+ fixup_jump = 0;
+ if (*stackp)
+ fixup_jump = *stackp + bufp->buffer - 1;
+ laststart = *--stackp + bufp->buffer;
+ break;
+
+ case '|':
+ if (obscure_syntax & RE_NO_BK_VBAR)
+ goto normal_backsl;
+ handle_bar:
+ insert_jump (on_failure_jump, begalt, b + 6, b);
+ pending_exact = 0;
+ b += 3;
+ if (fixup_jump)
+ store_jump (fixup_jump, jump, b);
+ fixup_jump = b;
+ b += 3;
+ laststart = 0;
+ begalt = b;
+ break;
+
+#ifdef emacs
+ case '=':
+ PATPUSH (at_dot);
+ break;
+
+ case 's':
+ laststart = b;
+ PATPUSH (syntaxspec);
+ PATFETCH (c);
+ PATPUSH (syntax_spec_code[c]);
+ break;
+
+ case 'S':
+ laststart = b;
+ PATPUSH (notsyntaxspec);
+ PATFETCH (c);
+ PATPUSH (syntax_spec_code[c]);
+ break;
+#endif emacs
+
+ case 'w':
+ laststart = b;
+ PATPUSH (wordchar);
+ break;
+
+ case 'W':
+ laststart = b;
+ PATPUSH (notwordchar);
+ break;
+
+ case '<':
+ PATPUSH (wordbeg);
+ break;
+
+ case '>':
+ PATPUSH (wordend);
+ break;
+
+ case 'b':
+ PATPUSH (wordbound);
+ break;
+
+ case 'B':
+ PATPUSH (notwordbound);
+ break;
+
+ case '`':
+ PATPUSH (begbuf);
+ break;
+
+ case '\'':
+ PATPUSH (endbuf);
+ break;
+
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ c1 = c - '0';
+ if (c1 >= regnum)
+ goto normal_char;
+ for (stackt = stackp - 2; stackt > stackb; stackt -= 4)
+ if (*stackt == c1)
+ goto normal_char;
+ laststart = b;
+ PATPUSH (duplicate);
+ PATPUSH (c1);
+ break;
+
+ case '+':
+ case '?':
+ if (obscure_syntax & RE_BK_PLUS_QM)
+ goto handle_plus;
+
+ default:
+ normal_backsl:
+ /* You might think it would be useful for \ to mean
+ not to translate; but if we don't translate it
+ it will never match anything. */
+ if (translate) c = translate[c];
+ goto normal_char;
+ }
+ break;
+
+ default:
+ normal_char:
+ if (!pending_exact || pending_exact + *pending_exact + 1 != b
+ || *pending_exact == 0177 || *p == '*' || *p == '^'
+ || ((obscure_syntax & RE_BK_PLUS_QM)
+ ? *p == '\\' && (p[1] == '+' || p[1] == '?')
+ : (*p == '+' || *p == '?')))
+ {
+ laststart = b;
+ PATPUSH (exactn);
+ pending_exact = b;
+ PATPUSH (0);
+ }
+ PATPUSH (c);
+ (*pending_exact)++;
+ }
+ }
+
+ if (fixup_jump)
+ store_jump (fixup_jump, jump, b);
+
+ if (stackp != stackb) goto unmatched_open;
+
+ bufp->used = b - bufp->buffer;
+ return 0;
+
+ invalid_pattern:
+ return "Invalid regular expression";
+
+ unmatched_open:
+ return "Unmatched \\(";
+
+ unmatched_close:
+ return "Unmatched \\)";
+
+ end_of_pattern:
+ return "Premature end of regular expression";
+
+ nesting_too_deep:
+ return "Nesting too deep";
+
+ too_big:
+ return "Regular expression too big";
+
+ memory_exhausted:
+ return "Memory exhausted";
+}
+
+/* Store where `from' points a jump operation to jump to where `to' points.
+ `opcode' is the opcode to store. */
+
+static int
+store_jump (from, opcode, to)
+ char *from, *to;
+ char opcode;
+{
+ from[0] = opcode;
+ from[1] = (to - (from + 3)) & 0377;
+ from[2] = (to - (from + 3)) >> 8;
+}
+
+/* Open up space at char FROM, and insert there a jump to TO.
+ CURRENT_END gives te end of the storage no in use,
+ so we know how much data to copy up.
+ OP is the opcode of the jump to insert.
+
+ If you call this function, you must zero out pending_exact. */
+
+static int
+insert_jump (op, from, to, current_end)
+ char op;
+ char *from, *to, *current_end;
+{
+ register char *pto = current_end + 3;
+ register char *pfrom = current_end;
+ while (pfrom != from)
+ *--pto = *--pfrom;
+ store_jump (from, op, to);
+}
+
+/* Given a pattern, compute a fastmap from it.
+ The fastmap records which of the (1 << BYTEWIDTH) possible characters
+ can start a string that matches the pattern.
+ This fastmap is used by re_search to skip quickly over totally implausible text.
+
+ The caller must supply the address of a (1 << BYTEWIDTH)-byte data area
+ as bufp->fastmap.
+ The other components of bufp describe the pattern to be used. */
+
+void
+re_compile_fastmap (bufp)
+ struct re_pattern_buffer *bufp;
+{
+ unsigned char *pattern = (unsigned char *) bufp->buffer;
+ int size = bufp->used;
+ register char *fastmap = bufp->fastmap;
+ register unsigned char *p = pattern;
+ register unsigned char *pend = pattern + size;
+ register int j, k;
+ unsigned char *translate = (unsigned char *) bufp->translate;
+
+ unsigned char *stackb[NFAILURES];
+ unsigned char **stackp = stackb;
+
+ bzero (fastmap, (1 << BYTEWIDTH));
+ bufp->fastmap_accurate = 1;
+ bufp->can_be_null = 0;
+
+ while (p)
+ {
+ if (p == pend)
+ {
+ bufp->can_be_null = 1;
+ break;
+ }
+#ifdef SWITCH_ENUM_BUG
+ switch ((int) ((enum regexpcode) *p++))
+#else
+ switch ((enum regexpcode) *p++)
+#endif
+ {
+ case exactn:
+ if (translate)
+ fastmap[translate[p[1]]] = 1;
+ else
+ fastmap[p[1]] = 1;
+ break;
+
+ case begline:
+ case before_dot:
+ case at_dot:
+ case after_dot:
+ case begbuf:
+ case endbuf:
+ case wordbound:
+ case notwordbound:
+ case wordbeg:
+ case wordend:
+ continue;
+
+ case endline:
+ if (translate)
+ fastmap[translate['\n']] = 1;
+ else
+ fastmap['\n'] = 1;
+ if (bufp->can_be_null != 1)
+ bufp->can_be_null = 2;
+ break;
+
+ case finalize_jump:
+ case maybe_finalize_jump:
+ case jump:
+ case dummy_failure_jump:
+ bufp->can_be_null = 1;
+ j = *p++ & 0377;
+ j += SIGN_EXTEND_CHAR (*(char *)p) << 8;
+ p += j + 1; /* The 1 compensates for missing ++ above */
+ if (j > 0)
+ continue;
+ /* Jump backward reached implies we just went through
+ the body of a loop and matched nothing.
+ Opcode jumped to should be an on_failure_jump.
+ Just treat it like an ordinary jump.
+ For a * loop, it has pushed its failure point already;
+ if so, discard that as redundant. */
+ if ((enum regexpcode) *p != on_failure_jump)
+ continue;
+ p++;
+ j = *p++ & 0377;
+ j += SIGN_EXTEND_CHAR (*(char *)p) << 8;
+ p += j + 1; /* The 1 compensates for missing ++ above */
+ if (stackp != stackb && *stackp == p)
+ stackp--;
+ continue;
+
+ case on_failure_jump:
+ j = *p++ & 0377;
+ j += SIGN_EXTEND_CHAR (*(char *)p) << 8;
+ p++;
+ *++stackp = p + j;
+ continue;
+
+ case start_memory:
+ case stop_memory:
+ p++;
+ continue;
+
+ case duplicate:
+ bufp->can_be_null = 1;
+ fastmap['\n'] = 1;
+ case anychar:
+ for (j = 0; j < (1 << BYTEWIDTH); j++)
+ if (j != '\n')
+ fastmap[j] = 1;
+ if (bufp->can_be_null)
+ return;
+ /* Don't return; check the alternative paths
+ so we can set can_be_null if appropriate. */
+ break;
+
+ case wordchar:
+ for (j = 0; j < (1 << BYTEWIDTH); j++)
+ if (SYNTAX (j) == Sword)
+ fastmap[j] = 1;
+ break;
+
+ case notwordchar:
+ for (j = 0; j < (1 << BYTEWIDTH); j++)
+ if (SYNTAX (j) != Sword)
+ fastmap[j] = 1;
+ break;
+
+#ifdef emacs
+ case syntaxspec:
+ k = *p++;
+ for (j = 0; j < (1 << BYTEWIDTH); j++)
+ if (SYNTAX (j) == (enum syntaxcode) k)
+ fastmap[j] = 1;
+ break;
+
+ case notsyntaxspec:
+ k = *p++;
+ for (j = 0; j < (1 << BYTEWIDTH); j++)
+ if (SYNTAX (j) != (enum syntaxcode) k)
+ fastmap[j] = 1;
+ break;
+#endif emacs
+
+ case charset:
+ for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--)
+ if (p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH)))
+ {
+ if (translate)
+ fastmap[translate[j]] = 1;
+ else
+ fastmap[j] = 1;
+ }
+ break;
+
+ case charset_not:
+ /* Chars beyond end of map must be allowed */
+ for (j = *p * BYTEWIDTH; j < (1 << BYTEWIDTH); j++)
+ if (translate)
+ fastmap[translate[j]] = 1;
+ else
+ fastmap[j] = 1;
+
+ for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--)
+ if (!(p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH))))
+ {
+ if (translate)
+ fastmap[translate[j]] = 1;
+ else
+ fastmap[j] = 1;
+ }
+ break;
+ }
+
+ /* Get here means we have successfully found the possible starting characters
+ of one path of the pattern. We need not follow this path any farther.
+ Instead, look at the next alternative remembered in the stack. */
+ if (stackp != stackb)
+ p = *stackp--;
+ else
+ break;
+ }
+}
+
+/* Like re_search_2, below, but only one string is specified. */
+
+int
+re_search (pbufp, string, size, startpos, range, regs)
+ struct re_pattern_buffer *pbufp;
+ char *string;
+ int size, startpos, range;
+ struct re_registers *regs;
+{
+ return re_search_2 (pbufp, 0, 0, string, size, startpos, range, regs, size);
+}
+
+/* Like re_match_2 but tries first a match starting at index STARTPOS,
+ then at STARTPOS + 1, and so on.
+ RANGE is the number of places to try before giving up.
+ If RANGE is negative, the starting positions tried are
+ STARTPOS, STARTPOS - 1, etc.
+ It is up to the caller to make sure that range is not so large
+ as to take the starting position outside of the input strings.
+
+The value returned is the position at which the match was found,
+ or -1 if no match was found,
+ or -2 if error (such as failure stack overflow). */
+
+int
+re_search_2 (pbufp, string1, size1, string2, size2, startpos, range, regs, mstop)
+ struct re_pattern_buffer *pbufp;
+ char *string1, *string2;
+ int size1, size2;
+ int startpos;
+ register int range;
+ struct re_registers *regs;
+ int mstop;
+{
+ register char *fastmap = pbufp->fastmap;
+ register unsigned char *translate = (unsigned char *) pbufp->translate;
+ int total = size1 + size2;
+ int val;
+
+ /* Update the fastmap now if not correct already */
+ if (fastmap && !pbufp->fastmap_accurate)
+ re_compile_fastmap (pbufp);
+
+ /* Don't waste time in a long search for a pattern
+ that says it is anchored. */
+ if (pbufp->used > 0 && (enum regexpcode) pbufp->buffer[0] == begbuf
+ && range > 0)
+ {
+ if (startpos > 0)
+ return -1;
+ else
+ range = 1;
+ }
+
+ while (1)
+ {
+ /* If a fastmap is supplied, skip quickly over characters
+ that cannot possibly be the start of a match.
+ Note, however, that if the pattern can possibly match
+ the null string, we must test it at each starting point
+ so that we take the first null string we get. */
+
+ if (fastmap && startpos < total && pbufp->can_be_null != 1)
+ {
+ if (range > 0)
+ {
+ register int lim = 0;
+ register unsigned char *p;
+ int irange = range;
+ if (startpos < size1 && startpos + range >= size1)
+ lim = range - (size1 - startpos);
+
+ p = ((unsigned char *)
+ &(startpos >= size1 ? string2 - size1 : string1)[startpos]);
+
+ if (translate)
+ {
+ while (range > lim && !fastmap[translate[*p++]])
+ range--;
+ }
+ else
+ {
+ while (range > lim && !fastmap[*p++])
+ range--;
+ }
+ startpos += irange - range;
+ }
+ else
+ {
+ register unsigned char c;
+ if (startpos >= size1)
+ c = string2[startpos - size1];
+ else
+ c = string1[startpos];
+ c &= 0xff;
+ if (translate ? !fastmap[translate[c]] : !fastmap[c])
+ goto advance;
+ }
+ }
+
+ if (range >= 0 && startpos == total
+ && fastmap && pbufp->can_be_null == 0)
+ return -1;
+
+ val = re_match_2 (pbufp, string1, size1, string2, size2, startpos, regs,
+ mstop);
+ /* Propagate error indication if worse than mere failure. */
+ if (val == -2)
+ return -2;
+ /* Return position on success. */
+ if (0 <= val)
+ return startpos;
+
+#ifdef C_ALLOCA
+ alloca (0);
+#endif /* C_ALLOCA */
+
+ advance:
+ if (!range) break;
+ if (range > 0) range--, startpos++; else range++, startpos--;
+ }
+ return -1;
+}
+
+#ifndef emacs /* emacs never uses this */
+int
+re_match (pbufp, string, size, pos, regs)
+ struct re_pattern_buffer *pbufp;
+ char *string;
+ int size, pos;
+ struct re_registers *regs;
+{
+ return re_match_2 (pbufp, 0, 0, string, size, pos, regs, size);
+}
+#endif /* emacs */
+
+/* Maximum size of failure stack. Beyond this, overflow is an error. */
+
+int re_max_failures = 2000;
+
+static int bcmp_translate();
+/* Match the pattern described by PBUFP
+ against data which is the virtual concatenation of STRING1 and STRING2.
+ SIZE1 and SIZE2 are the sizes of the two data strings.
+ Start the match at position POS.
+ Do not consider matching past the position MSTOP.
+
+ If pbufp->fastmap is nonzero, then it had better be up to date.
+
+ The reason that the data to match are specified as two components
+ which are to be regarded as concatenated
+ is so this function can be used directly on the contents of an Emacs buffer.
+
+ -1 is returned if there is no match. -2 is returned if there is
+ an error (such as match stack overflow). Otherwise the value is the length
+ of the substring which was matched. */
+
+int
+re_match_2 (pbufp, string1, size1, string2, size2, pos, regs, mstop)
+ struct re_pattern_buffer *pbufp;
+ unsigned char *string1, *string2;
+ int size1, size2;
+ int pos;
+ struct re_registers *regs;
+ int mstop;
+{
+ register unsigned char *p = (unsigned char *) pbufp->buffer;
+ register unsigned char *pend = p + pbufp->used;
+ /* End of first string */
+ unsigned char *end1;
+ /* End of second string */
+ unsigned char *end2;
+ /* Pointer just past last char to consider matching */
+ unsigned char *end_match_1, *end_match_2;
+ register unsigned char *d, *dend;
+ register int mcnt;
+ unsigned char *translate = (unsigned char *) pbufp->translate;
+
+ /* Failure point stack. Each place that can handle a failure further down the line
+ pushes a failure point on this stack. It consists of two char *'s.
+ The first one pushed is where to resume scanning the pattern;
+ the second pushed is where to resume scanning the strings.
+ If the latter is zero, the failure point is a "dummy".
+ If a failure happens and the innermost failure point is dormant,
+ it discards that failure point and tries the next one. */
+
+ unsigned char *initial_stack[2 * NFAILURES];
+ unsigned char **stackb = initial_stack;
+ unsigned char **stackp = stackb, **stacke = &stackb[2 * NFAILURES];
+
+ /* Information on the "contents" of registers.
+ These are pointers into the input strings; they record
+ just what was matched (on this attempt) by some part of the pattern.
+ The start_memory command stores the start of a register's contents
+ and the stop_memory command stores the end.
+
+ At that point, regstart[regnum] points to the first character in the register,
+ regend[regnum] points to the first character beyond the end of the register,
+ regstart_seg1[regnum] is true iff regstart[regnum] points into string1,
+ and regend_seg1[regnum] is true iff regend[regnum] points into string1. */
+
+ unsigned char *regstart[RE_NREGS];
+ unsigned char *regend[RE_NREGS];
+ unsigned char regstart_seg1[RE_NREGS], regend_seg1[RE_NREGS];
+
+ /* Set up pointers to ends of strings.
+ Don't allow the second string to be empty unless both are empty. */
+ if (!size2)
+ {
+ string2 = string1;
+ size2 = size1;
+ string1 = 0;
+ size1 = 0;
+ }
+ end1 = string1 + size1;
+ end2 = string2 + size2;
+
+ /* Compute where to stop matching, within the two strings */
+ if (mstop <= size1)
+ {
+ end_match_1 = string1 + mstop;
+ end_match_2 = string2;
+ }
+ else
+ {
+ end_match_1 = end1;
+ end_match_2 = string2 + mstop - size1;
+ }
+
+ /* Initialize \) text positions to -1
+ to mark ones that no \( or \) has been seen for. */
+
+ for (mcnt = 0; mcnt < sizeof (regend) / sizeof (*regend); mcnt++)
+ regend[mcnt] = (unsigned char *) -1;
+
+ /* `p' scans through the pattern as `d' scans through the data.
+ `dend' is the end of the input string that `d' points within.
+ `d' is advanced into the following input string whenever necessary,
+ but this happens before fetching;
+ therefore, at the beginning of the loop,
+ `d' can be pointing at the end of a string,
+ but it cannot equal string2. */
+
+ if (pos <= size1)
+ d = string1 + pos, dend = end_match_1;
+ else
+ d = string2 + pos - size1, dend = end_match_2;
+
+/* Write PREFETCH; just before fetching a character with *d. */
+#define PREFETCH \
+ while (d == dend) \
+ { if (dend == end_match_2) goto fail; /* end of string2 => failure */ \
+ d = string2; /* end of string1 => advance to string2. */ \
+ dend = end_match_2; }
+
+ /* This loop loops over pattern commands.
+ It exits by returning from the function if match is complete,
+ or it drops through if match fails at this starting point in the input data. */
+
+ while (1)
+ {
+ if (p == pend)
+ /* End of pattern means we have succeeded! */
+ {
+ /* If caller wants register contents data back, convert it to indices */
+ if (regs)
+ {
+ regs->start[0] = pos;
+ if (dend == end_match_1)
+ regs->end[0] = d - string1;
+ else
+ regs->end[0] = d - string2 + size1;
+ for (mcnt = 1; mcnt < RE_NREGS; mcnt++)
+ {
+ if (regend[mcnt] == (unsigned char *) -1)
+ {
+ regs->start[mcnt] = -1;
+ regs->end[mcnt] = -1;
+ continue;
+ }
+ if (regstart_seg1[mcnt])
+ regs->start[mcnt] = regstart[mcnt] - string1;
+ else
+ regs->start[mcnt] = regstart[mcnt] - string2 + size1;
+ if (regend_seg1[mcnt])
+ regs->end[mcnt] = regend[mcnt] - string1;
+ else
+ regs->end[mcnt] = regend[mcnt] - string2 + size1;
+ }
+ }
+ if (dend == end_match_1)
+ return (d - string1 - pos);
+ else
+ return d - string2 + size1 - pos;
+ }
+
+ /* Otherwise match next pattern command */
+#ifdef SWITCH_ENUM_BUG
+ switch ((int) ((enum regexpcode) *p++))
+#else
+ switch ((enum regexpcode) *p++)
+#endif
+ {
+
+ /* \( is represented by a start_memory, \) by a stop_memory.
+ Both of those commands contain a "register number" argument.
+ The text matched within the \( and \) is recorded under that number.
+ Then, \<digit> turns into a `duplicate' command which
+ is followed by the numeric value of <digit> as the register number. */
+
+ case start_memory:
+ regstart[*p] = d;
+ regstart_seg1[*p++] = (dend == end_match_1);
+ break;
+
+ case stop_memory:
+ regend[*p] = d;
+ regend_seg1[*p++] = (dend == end_match_1);
+ break;
+
+ case duplicate:
+ {
+ int regno = *p++; /* Get which register to match against */
+ register unsigned char *d2, *dend2;
+
+ /* Don't allow matching a register that hasn't been used.
+ This isn't fully reliable in the current version,
+ but it is better than crashing. */
+ if ((int) regend[regno] == -1)
+ goto fail;
+
+ d2 = regstart[regno];
+ dend2 = ((regstart_seg1[regno] == regend_seg1[regno])
+ ? regend[regno] : end_match_1);
+ while (1)
+ {
+ /* Advance to next segment in register contents, if necessary */
+ while (d2 == dend2)
+ {
+ if (dend2 == end_match_2) break;
+ if (dend2 == regend[regno]) break;
+ d2 = string2, dend2 = regend[regno]; /* end of string1 => advance to string2. */
+ }
+ /* At end of register contents => success */
+ if (d2 == dend2) break;
+
+ /* Advance to next segment in data being matched, if necessary */
+ PREFETCH;
+
+ /* mcnt gets # consecutive chars to compare */
+ mcnt = dend - d;
+ if (mcnt > dend2 - d2)
+ mcnt = dend2 - d2;
+ /* Compare that many; failure if mismatch, else skip them. */
+ if (translate ? bcmp_translate (d, d2, mcnt, translate) : bcmp (d, d2, mcnt))
+ goto fail;
+ d += mcnt, d2 += mcnt;
+ }
+ }
+ break;
+
+ case anychar:
+ /* fetch a data character */
+ PREFETCH;
+ /* Match anything but a newline. */
+ if ((translate ? translate[*d++] : *d++) == '\n')
+ goto fail;
+ break;
+
+ case charset:
+ case charset_not:
+ {
+ /* Nonzero for charset_not */
+ int not = 0;
+ register int c;
+ if (*(p - 1) == (unsigned char) charset_not)
+ not = 1;
+
+ /* fetch a data character */
+ PREFETCH;
+
+ if (translate)
+ c = translate [*d];
+ else
+ c = *d;
+
+ if (c < *p * BYTEWIDTH
+ && p[1 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH)))
+ not = !not;
+
+ p += 1 + *p;
+
+ if (!not) goto fail;
+ d++;
+ break;
+ }
+
+ case begline:
+ if (d == string1 || d[-1] == '\n')
+ break;
+ goto fail;
+
+ case endline:
+ if (d == end2
+ || (d == end1 ? (size2 == 0 || *string2 == '\n') : *d == '\n'))
+ break;
+ goto fail;
+
+ /* "or" constructs ("|") are handled by starting each alternative
+ with an on_failure_jump that points to the start of the next alternative.
+ Each alternative except the last ends with a jump to the joining point.
+ (Actually, each jump except for the last one really jumps
+ to the following jump, because tensioning the jumps is a hassle.) */
+
+ /* The start of a stupid repeat has an on_failure_jump that points
+ past the end of the repeat text.
+ This makes a failure point so that, on failure to match a repetition,
+ matching restarts past as many repetitions have been found
+ with no way to fail and look for another one. */
+
+ /* A smart repeat is similar but loops back to the on_failure_jump
+ so that each repetition makes another failure point. */
+
+ case on_failure_jump:
+ if (stackp == stacke)
+ {
+ unsigned char **stackx;
+ if (stacke - stackb > re_max_failures)
+ return -2;
+ stackx = (unsigned char **) alloca (2 * (stacke - stackb)
+ * sizeof (char *));
+ bcopy (stackb, stackx, (stacke - stackb) * sizeof (char *));
+ stackp = stackx + (stackp - stackb);
+ stacke = stackx + 2 * (stacke - stackb);
+ stackb = stackx;
+ }
+ mcnt = *p++ & 0377;
+ mcnt += SIGN_EXTEND_CHAR (*(char *)p) << 8;
+ p++;
+ *stackp++ = mcnt + p;
+ *stackp++ = d;
+ break;
+
+ /* The end of a smart repeat has an maybe_finalize_jump back.
+ Change it either to a finalize_jump or an ordinary jump. */
+
+ case maybe_finalize_jump:
+ mcnt = *p++ & 0377;
+ mcnt += SIGN_EXTEND_CHAR (*(char *)p) << 8;
+ p++;
+ /* Compare what follows with the begining of the repeat.
+ If we can establish that there is nothing that they would
+ both match, we can change to finalize_jump */
+ if (p == pend)
+ p[-3] = (unsigned char) finalize_jump;
+ else if (*p == (unsigned char) exactn
+ || *p == (unsigned char) endline)
+ {
+ register int c = *p == (unsigned char) endline ? '\n' : p[2];
+ register unsigned char *p1 = p + mcnt;
+ /* p1[0] ... p1[2] are an on_failure_jump.
+ Examine what follows that */
+ if (p1[3] == (unsigned char) exactn && p1[5] != c)
+ p[-3] = (unsigned char) finalize_jump;
+ else if (p1[3] == (unsigned char) charset
+ || p1[3] == (unsigned char) charset_not)
+ {
+ int not = p1[3] == (unsigned char) charset_not;
+ if (c < p1[4] * BYTEWIDTH
+ && p1[5 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH)))
+ not = !not;
+ /* not is 1 if c would match */
+ /* That means it is not safe to finalize */
+ if (!not)
+ p[-3] = (unsigned char) finalize_jump;
+ }
+ }
+ p -= 2;
+ if (p[-1] != (unsigned char) finalize_jump)
+ {
+ p[-1] = (unsigned char) jump;
+ goto nofinalize;
+ }
+
+ /* The end of a stupid repeat has a finalize-jump
+ back to the start, where another failure point will be made
+ which will point after all the repetitions found so far. */
+
+ case finalize_jump:
+ stackp -= 2;
+
+ case jump:
+ nofinalize:
+ mcnt = *p++ & 0377;
+ mcnt += SIGN_EXTEND_CHAR (*(char *)p) << 8;
+ p += mcnt + 1; /* The 1 compensates for missing ++ above */
+ break;
+
+ case dummy_failure_jump:
+ if (stackp == stacke)
+ {
+ unsigned char **stackx
+ = (unsigned char **) alloca (2 * (stacke - stackb)
+ * sizeof (char *));
+ bcopy (stackb, stackx, (stacke - stackb) * sizeof (char *));
+ stackp = stackx + (stackp - stackb);
+ stacke = stackx + 2 * (stacke - stackb);
+ stackb = stackx;
+ }
+ *stackp++ = 0;
+ *stackp++ = 0;
+ goto nofinalize;
+
+ case wordbound:
+ if (d == string1 /* Points to first char */
+ || d == end2 /* Points to end */
+ || (d == end1 && size2 == 0)) /* Points to end */
+ break;
+ if ((SYNTAX (d[-1]) == Sword)
+ != (SYNTAX (d == end1 ? *string2 : *d) == Sword))
+ break;
+ goto fail;
+
+ case notwordbound:
+ if (d == string1 /* Points to first char */
+ || d == end2 /* Points to end */
+ || (d == end1 && size2 == 0)) /* Points to end */
+ goto fail;
+ if ((SYNTAX (d[-1]) == Sword)
+ != (SYNTAX (d == end1 ? *string2 : *d) == Sword))
+ goto fail;
+ break;
+
+ case wordbeg:
+ if (d == end2 /* Points to end */
+ || (d == end1 && size2 == 0) /* Points to end */
+ || SYNTAX (* (d == end1 ? string2 : d)) != Sword) /* Next char not a letter */
+ goto fail;
+ if (d == string1 /* Points to first char */
+ || SYNTAX (d[-1]) != Sword) /* prev char not letter */
+ break;
+ goto fail;
+
+ case wordend:
+ if (d == string1 /* Points to first char */
+ || SYNTAX (d[-1]) != Sword) /* prev char not letter */
+ goto fail;
+ if (d == end2 /* Points to end */
+ || (d == end1 && size2 == 0) /* Points to end */
+ || SYNTAX (d == end1 ? *string2 : *d) != Sword) /* Next char not a letter */
+ break;
+ goto fail;
+
+#ifdef emacs
+ case before_dot:
+ if (PTR_CHAR_POS (d) + 1 >= point)
+ goto fail;
+ break;
+
+ case at_dot:
+ if (PTR_CHAR_POS (d) + 1 != point)
+ goto fail;
+ break;
+
+ case after_dot:
+ if (PTR_CHAR_POS (d) + 1 <= point)
+ goto fail;
+ break;
+
+ case wordchar:
+ mcnt = (int) Sword;
+ goto matchsyntax;
+
+ case syntaxspec:
+ mcnt = *p++;
+ matchsyntax:
+ PREFETCH;
+ if (SYNTAX (*d++) != (enum syntaxcode) mcnt) goto fail;
+ break;
+
+ case notwordchar:
+ mcnt = (int) Sword;
+ goto matchnotsyntax;
+
+ case notsyntaxspec:
+ mcnt = *p++;
+ matchnotsyntax:
+ PREFETCH;
+ if (SYNTAX (*d++) == (enum syntaxcode) mcnt) goto fail;
+ break;
+#else
+ case wordchar:
+ PREFETCH;
+ if (SYNTAX (*d++) == 0) goto fail;
+ break;
+
+ case notwordchar:
+ PREFETCH;
+ if (SYNTAX (*d++) != 0) goto fail;
+ break;
+#endif not emacs
+
+ case begbuf:
+ if (d == string1) /* Note, d cannot equal string2 */
+ break; /* unless string1 == string2. */
+ goto fail;
+
+ case endbuf:
+ if (d == end2 || (d == end1 && size2 == 0))
+ break;
+ goto fail;
+
+ case exactn:
+ /* Match the next few pattern characters exactly.
+ mcnt is how many characters to match. */
+ mcnt = *p++;
+ if (translate)
+ {
+ do
+ {
+ PREFETCH;
+ if (translate[*d++] != *p++) goto fail;
+ }
+ while (--mcnt);
+ }
+ else
+ {
+ do
+ {
+ PREFETCH;
+ if (*d++ != *p++) goto fail;
+ }
+ while (--mcnt);
+ }
+ break;
+ }
+ continue; /* Successfully matched one pattern command; keep matching */
+
+ /* Jump here if any matching operation fails. */
+ fail:
+ if (stackp != stackb)
+ /* A restart point is known. Restart there and pop it. */
+ {
+ if (!stackp[-2])
+ { /* If innermost failure point is dormant, flush it and keep looking */
+ stackp -= 2;
+ goto fail;
+ }
+ d = *--stackp;
+ p = *--stackp;
+ if (d >= string1 && d <= end1)
+ dend = end_match_1;
+ }
+ else break; /* Matching at this starting point really fails! */
+ }
+ return -1; /* Failure to match */
+}
+
+static int
+bcmp_translate (s1, s2, len, translate)
+ unsigned char *s1, *s2;
+ register int len;
+ unsigned char *translate;
+{
+ register unsigned char *p1 = s1, *p2 = s2;
+ while (len)
+ {
+ if (translate [*p1++] != translate [*p2++]) return 1;
+ len--;
+ }
+ return 0;
+}
+
+/* Entry points compatible with bsd4.2 regex library */
+
+#ifndef emacs
+
+static struct re_pattern_buffer re_comp_buf;
+
+char *
+re_comp (s)
+ char *s;
+{
+ if (!s)
+ {
+ if (!re_comp_buf.buffer)
+ return "No previous regular expression";
+ return 0;
+ }
+
+ if (!re_comp_buf.buffer)
+ {
+ if (!(re_comp_buf.buffer = (char *) malloc (200)))
+ return "Memory exhausted";
+ re_comp_buf.allocated = 200;
+ if (!(re_comp_buf.fastmap = (char *) malloc (1 << BYTEWIDTH)))
+ return "Memory exhausted";
+ }
+ return re_compile_pattern (s, strlen (s), &re_comp_buf);
+}
+
+int
+re_exec (s)
+ char *s;
+{
+ int len = strlen (s);
+ return 0 <= re_search (&re_comp_buf, s, len, 0, len, 0);
+}
+
+#endif /* emacs */
+
+#ifdef test
+
+#include <stdio.h>
+
+/* Indexed by a character, gives the upper case equivalent of the character */
+
+static char upcase[0400] =
+ { 000, 001, 002, 003, 004, 005, 006, 007,
+ 010, 011, 012, 013, 014, 015, 016, 017,
+ 020, 021, 022, 023, 024, 025, 026, 027,
+ 030, 031, 032, 033, 034, 035, 036, 037,
+ 040, 041, 042, 043, 044, 045, 046, 047,
+ 050, 051, 052, 053, 054, 055, 056, 057,
+ 060, 061, 062, 063, 064, 065, 066, 067,
+ 070, 071, 072, 073, 074, 075, 076, 077,
+ 0100, 0101, 0102, 0103, 0104, 0105, 0106, 0107,
+ 0110, 0111, 0112, 0113, 0114, 0115, 0116, 0117,
+ 0120, 0121, 0122, 0123, 0124, 0125, 0126, 0127,
+ 0130, 0131, 0132, 0133, 0134, 0135, 0136, 0137,
+ 0140, 0101, 0102, 0103, 0104, 0105, 0106, 0107,
+ 0110, 0111, 0112, 0113, 0114, 0115, 0116, 0117,
+ 0120, 0121, 0122, 0123, 0124, 0125, 0126, 0127,
+ 0130, 0131, 0132, 0173, 0174, 0175, 0176, 0177,
+ 0200, 0201, 0202, 0203, 0204, 0205, 0206, 0207,
+ 0210, 0211, 0212, 0213, 0214, 0215, 0216, 0217,
+ 0220, 0221, 0222, 0223, 0224, 0225, 0226, 0227,
+ 0230, 0231, 0232, 0233, 0234, 0235, 0236, 0237,
+ 0240, 0241, 0242, 0243, 0244, 0245, 0246, 0247,
+ 0250, 0251, 0252, 0253, 0254, 0255, 0256, 0257,
+ 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267,
+ 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277,
+ 0300, 0301, 0302, 0303, 0304, 0305, 0306, 0307,
+ 0310, 0311, 0312, 0313, 0314, 0315, 0316, 0317,
+ 0320, 0321, 0322, 0323, 0324, 0325, 0326, 0327,
+ 0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337,
+ 0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347,
+ 0350, 0351, 0352, 0353, 0354, 0355, 0356, 0357,
+ 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367,
+ 0370, 0371, 0372, 0373, 0374, 0375, 0376, 0377
+ };
+
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ char pat[80];
+ struct re_pattern_buffer buf;
+ int i;
+ char c;
+ char fastmap[(1 << BYTEWIDTH)];
+
+ /* Allow a command argument to specify the style of syntax. */
+ if (argc > 1)
+ obscure_syntax = atoi (argv[1]);
+
+ buf.allocated = 40;
+ buf.buffer = (char *) malloc (buf.allocated);
+ buf.fastmap = fastmap;
+ buf.translate = upcase;
+
+ while (1)
+ {
+ gets (pat);
+
+ if (*pat)
+ {
+ re_compile_pattern (pat, strlen(pat), &buf);
+
+ for (i = 0; i < buf.used; i++)
+ printchar (buf.buffer[i]);
+
+ putchar ('\n');
+
+ printf ("%d allocated, %d used.\n", buf.allocated, buf.used);
+
+ re_compile_fastmap (&buf);
+ printf ("Allowed by fastmap: ");
+ for (i = 0; i < (1 << BYTEWIDTH); i++)
+ if (fastmap[i]) printchar (i);
+ putchar ('\n');
+ }
+
+ gets (pat); /* Now read the string to match against */
+
+ i = re_match (&buf, pat, strlen (pat), 0, 0);
+ printf ("Match value %d.\n", i);
+ }
+}
+
+#ifdef NOTDEF
+print_buf (bufp)
+ struct re_pattern_buffer *bufp;
+{
+ int i;
+
+ printf ("buf is :\n----------------\n");
+ for (i = 0; i < bufp->used; i++)
+ printchar (bufp->buffer[i]);
+
+ printf ("\n%d allocated, %d used.\n", bufp->allocated, bufp->used);
+
+ printf ("Allowed by fastmap: ");
+ for (i = 0; i < (1 << BYTEWIDTH); i++)
+ if (bufp->fastmap[i])
+ printchar (i);
+ printf ("\nAllowed by translate: ");
+ if (bufp->translate)
+ for (i = 0; i < (1 << BYTEWIDTH); i++)
+ if (bufp->translate[i])
+ printchar (i);
+ printf ("\nfastmap is%s accurate\n", bufp->fastmap_accurate ? "" : "n't");
+ printf ("can %s be null\n----------", bufp->can_be_null ? "" : "not");
+}
+#endif
+
+printchar (c)
+ char c;
+{
+ if (c < 041 || c >= 0177)
+ {
+ putchar ('\\');
+ putchar (((c >> 6) & 3) + '0');
+ putchar (((c >> 3) & 7) + '0');
+ putchar ((c & 7) + '0');
+ }
+ else
+ putchar (c);
+}
+
+error (string)
+ char *string;
+{
+ puts (string);
+ exit (1);
+}
+
+#endif test
diff --git a/src/regex.h b/src/regex.h
new file mode 100644
index 00000000000..7462e51d821
--- /dev/null
+++ b/src/regex.h
@@ -0,0 +1,184 @@
+/* Definitions for data structures callers pass the regex library.
+ Copyright (C) 1985 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+In other words, you are welcome to use, share and improve this program.
+You are forbidden to forbid anyone else to use, share and improve
+what you give them. Help stamp out software-hoarding! */
+
+
+/* Define number of parens for which we record the beginnings and ends.
+ This affects how much space the `struct re_registers' type takes up. */
+#ifndef RE_NREGS
+#define RE_NREGS 10
+#endif
+
+/* These bits are used in the obscure_syntax variable to choose among
+ alternative regexp syntaxes. */
+
+/* 1 means plain parentheses serve as grouping, and backslash
+ parentheses are needed for literal searching.
+ 0 means backslash-parentheses are grouping, and plain parentheses
+ are for literal searching. */
+#define RE_NO_BK_PARENS 1
+
+/* 1 means plain | serves as the "or"-operator, and \| is a literal.
+ 0 means \| serves as the "or"-operator, and | is a literal. */
+#define RE_NO_BK_VBAR 2
+
+/* 0 means plain + or ? serves as an operator, and \+, \? are literals.
+ 1 means \+, \? are operators and plain +, ? are literals. */
+#define RE_BK_PLUS_QM 4
+
+/* 1 means | binds tighter than ^ or $.
+ 0 means the contrary. */
+#define RE_TIGHT_VBAR 8
+
+/* 1 means treat \n as an _OR operator
+ 0 means treat it as a normal character */
+#define RE_NEWLINE_OR 16
+
+/* 0 means that a special characters (such as *, ^, and $) always have
+ their special meaning regardless of the surrounding context.
+ 1 means that special characters may act as normal characters in some
+ contexts. Specifically, this applies to:
+ ^ - only special at the beginning, or after ( or |
+ $ - only special at the end, or before ) or |
+ *, +, ? - only special when not after the beginning, (, or | */
+#define RE_CONTEXT_INDEP_OPS 32
+
+/* Now define combinations of bits for the standard possibilities. */
+#define RE_SYNTAX_AWK (RE_NO_BK_PARENS | RE_NO_BK_VBAR | RE_CONTEXT_INDEP_OPS)
+#define RE_SYNTAX_EGREP (RE_SYNTAX_AWK | RE_NEWLINE_OR)
+#define RE_SYNTAX_GREP (RE_BK_PLUS_QM | RE_NEWLINE_OR)
+#define RE_SYNTAX_EMACS 0
+
+/* This data structure is used to represent a compiled pattern. */
+
+struct re_pattern_buffer
+ {
+ char *buffer; /* Space holding the compiled pattern commands. */
+ int allocated; /* Size of space that buffer points to */
+ int used; /* Length of portion of buffer actually occupied */
+ char *fastmap; /* Pointer to fastmap, if any, or zero if none. */
+ /* re_search uses the fastmap, if there is one,
+ to skip quickly over totally implausible characters */
+ char *translate; /* Translate table to apply to all characters before comparing.
+ Or zero for no translation.
+ The translation is applied to a pattern when it is compiled
+ and to data when it is matched. */
+ char fastmap_accurate;
+ /* Set to zero when a new pattern is stored,
+ set to one when the fastmap is updated from it. */
+ char can_be_null; /* Set to one by compiling fastmap
+ if this pattern might match the null string.
+ It does not necessarily match the null string
+ in that case, but if this is zero, it cannot.
+ 2 as value means can match null string
+ but at end of range or before a character
+ listed in the fastmap. */
+ };
+
+/* Structure to store "register" contents data in.
+
+ Pass the address of such a structure as an argument to re_match, etc.,
+ if you want this information back.
+
+ start[i] and end[i] record the string matched by \( ... \) grouping i,
+ for i from 1 to RE_NREGS - 1.
+ start[0] and end[0] record the entire string matched. */
+
+struct re_registers
+ {
+ int start[RE_NREGS];
+ int end[RE_NREGS];
+ };
+
+/* These are the command codes that appear in compiled regular expressions, one per byte.
+ Some command codes are followed by argument bytes.
+ A command code can specify any interpretation whatever for its arguments.
+ Zero-bytes may appear in the compiled regular expression. */
+
+enum regexpcode
+ {
+ unused,
+ exactn, /* followed by one byte giving n, and then by n literal bytes */
+ begline, /* fails unless at beginning of line */
+ endline, /* fails unless at end of line */
+ jump, /* followed by two bytes giving relative address to jump to */
+ on_failure_jump, /* followed by two bytes giving relative address of place
+ to resume at in case of failure. */
+ finalize_jump, /* Throw away latest failure point and then jump to address. */
+ maybe_finalize_jump, /* Like jump but finalize if safe to do so.
+ This is used to jump back to the beginning
+ of a repeat. If the command that follows
+ this jump is clearly incompatible with the
+ one at the beginning of the repeat, such that
+ we can be sure that there is no use backtracking
+ out of repetitions already completed,
+ then we finalize. */
+ dummy_failure_jump, /* jump, and push a dummy failure point.
+ This failure point will be thrown away
+ if an attempt is made to use it for a failure.
+ A + construct makes this before the first repeat. */
+ anychar, /* matches any one character */
+ charset, /* matches any one char belonging to specified set.
+ First following byte is # bitmap bytes.
+ Then come bytes for a bit-map saying which chars are in.
+ Bits in each byte are ordered low-bit-first.
+ A character is in the set if its bit is 1.
+ A character too large to have a bit in the map
+ is automatically not in the set */
+ charset_not, /* similar but match any character that is NOT one of those specified */
+ start_memory, /* starts remembering the text that is matched
+ and stores it in a memory register.
+ followed by one byte containing the register number.
+ Register numbers must be in the range 0 through NREGS. */
+ stop_memory, /* stops remembering the text that is matched
+ and stores it in a memory register.
+ followed by one byte containing the register number.
+ Register numbers must be in the range 0 through NREGS. */
+ duplicate, /* match a duplicate of something remembered.
+ Followed by one byte containing the index of the memory register. */
+ before_dot, /* Succeeds if before dot */
+ at_dot, /* Succeeds if at dot */
+ after_dot, /* Succeeds if after dot */
+ begbuf, /* Succeeds if at beginning of buffer */
+ endbuf, /* Succeeds if at end of buffer */
+ wordchar, /* Matches any word-constituent character */
+ notwordchar, /* Matches any char that is not a word-constituent */
+ wordbeg, /* Succeeds if at word beginning */
+ wordend, /* Succeeds if at word end */
+ wordbound, /* Succeeds if at a word boundary */
+ notwordbound, /* Succeeds if not at a word boundary */
+ syntaxspec, /* Matches any character whose syntax is specified.
+ followed by a byte which contains a syntax code, Sword or such like */
+ notsyntaxspec /* Matches any character whose syntax differs from the specified. */
+ };
+
+extern char *re_compile_pattern ();
+/* Is this really advertised? */
+extern void re_compile_fastmap ();
+extern int re_search (), re_search_2 ();
+extern int re_match (), re_match_2 ();
+
+/* 4.2 bsd compatibility (yuck) */
+extern char *re_comp ();
+extern int re_exec ();
+
+#ifdef SYNTAX_TABLE
+extern char *re_syntax_table;
+#endif
diff --git a/src/s-386bsd.h b/src/s-386bsd.h
new file mode 100644
index 00000000000..4fefb86f8ce
--- /dev/null
+++ b/src/s-386bsd.h
@@ -0,0 +1,48 @@
+/* Definitions file for GNU emacs running on 386BSD. */
+
+#include "s-bsd4-3.h"
+
+/*
+ * Define symbols to identify the version of Unix this is.
+ * BSD and BSD4_3 are defined in s-bsd4-3.h. There are some
+ * differences between 386BSD and BSD 4.3 so we need an extra
+ * symbol to identify it (the J stands for Jolitz).
+ */
+
+#ifndef J386BSD
+#define J386BSD
+#endif /* J386BSD */
+
+/* Under 386BSD the file containing the kernel's symbol
+ table is named /386bsd. */
+
+#undef KERNEL_FILE
+#define KERNEL_FILE "/386bsd"
+
+/* The symbol in the kernel where the load average is found
+ is named _averunnable. */
+
+#undef LDAV_SYMBOL
+#define LDAV_SYMBOL "_averunnable"
+
+/* This macro determines the number of bytes waiting to be written
+ in a FILE buffer. */
+
+#define PENDING_OUTPUT_COUNT(FILE) ((FILE)->_p - (FILE)->_bf._base)
+
+/* 386BSD uses GNU C. */
+
+#define C_COMPILER gcc -traditional
+
+/* 386BSD stores the termcap database in /usr/share/misc rather than
+ /etc. We use the system termcap library to avoid putting a #ifdef
+ in termcap.c or forcing the user to use the TERMCAP environment
+ variable. */
+
+#define LIBS_TERMCAP -ltermcap
+
+/* 386BSD is nominally a POSIX.1 OS and has setsid. */
+
+#ifndef HAVE_SETSID
+#define HAVE_SETSID
+#endif /* HAVE_SETSID */
diff --git a/src/s-386ix.h b/src/s-386ix.h
new file mode 100644
index 00000000000..689ff084999
--- /dev/null
+++ b/src/s-386ix.h
@@ -0,0 +1,22 @@
+#include "s-usg5-3.h"
+
+#ifndef ISC
+#define ISC
+#endif
+
+#define NO_SIOCTL_H
+
+#define BROKEN_TIOCGETC
+
+/* There are some reports that the following is needed
+ with some version of this system.
+#undef LIBX11_SYSTEM
+#define LIBX11_SYSTEM -linet
+
+#define HAVE_TIMEVAL
+#define USE_UTIME
+*/
+
+/* This is said to be needed as a result of having _insque rather
+ than insque in -loldX. This may not always be the right thing. */
+#define WRONG_NAME_INSQUE
diff --git a/src/s-aix3-1.h b/src/s-aix3-1.h
new file mode 100644
index 00000000000..ef48854044c
--- /dev/null
+++ b/src/s-aix3-1.h
@@ -0,0 +1,233 @@
+/* Definitions file for GNU Emacs running on IBM AIX version 3.1
+ Copyright (C) 1985, 1986, 1990 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/*
+ * Define symbols to identify the version of Unix this is.
+ * Define all the symbols that apply correctly.
+ */
+
+#define USG /* System III, System V, etc */
+#define USG5
+
+/* Specify IBM AIX version of system */
+
+#ifndef AIX
+#define AIX
+#endif
+
+/* turn off c prototypes */
+#ifndef _NO_PROTO
+#define _NO_PROTO
+#endif
+
+/* This symbol should be defined on AIX Version 3 ??????? */
+#ifndef _AIX
+#define _AIX
+#endif
+
+/* Specify "_BSD" to invoke Berkeley compatibility in header files */
+/*#ifndef _BSD
+#define _BSD
+#endif
+*/
+
+/* SYSTEM_TYPE should indicate the kind of system you are using.
+ It sets the Lisp variable system-type. */
+
+#define SYSTEM_TYPE "aix-v3"
+
+
+/* nomultiplejobs should be defined if your system's shell
+ does not have "job control" (the ability to stop a program,
+ run some other program, then continue the first one). */
+
+/* #define NOMULTIPLEJOBS */
+
+/* Default is to set interrupt_input to 0: don't do input buffering within Emacs */
+
+/* #define INTERRUPT_INPUT */
+
+/* In AIX, you allocate a pty by opening /dev/ptc to get the master side.
+ To get the name of the slave side, you just ttyname() the master side. */
+
+#define PTY_ITERATION for (c = 0; !c ; c++)
+#define PTY_NAME_SPRINTF strcpy (pty_name, "/dev/ptc");
+#define PTY_TTY_NAME_SPRINTF strcpy (pty_name, ttyname (fd));
+
+/*
+ * Define HAVE_TERMIO if the system provides sysV-style ioctls
+ * for terminal control.
+ */
+
+#define HAVE_TERMIO
+
+/*
+ * Define HAVE_TIMEVAL if the system supports the BSD style clock values.
+ * Look in <sys/time.h> for a timeval structure.
+ */
+
+#define HAVE_TIMEVAL
+
+/*
+ * Define HAVE_SELECT if the system supports the `select' system call.
+ */
+
+#define HAVE_SELECT
+
+/*
+ * Define HAVE_PTYS if the system supports pty devices.
+ */
+
+#define HAVE_PTYS
+
+/* Define HAVE_SOCKETS if system supports 4.2-compatible sockets. */
+
+#define HAVE_SOCKETS
+
+/*
+ * Define NONSYSTEM_DIR_LIBRARY to make Emacs emulate
+ * The 4.2 opendir, etc., library functions.
+ */
+
+/* #define NONSYSTEM_DIR_LIBRARY */
+
+/*
+ * Define SYSV_SYSTEM_DIR to use the V.3 getdents/readir
+ * library functions. Almost, but not quite the same as
+ * the 4.2 functions
+ */
+
+#define SYSV_SYSTEM_DIR
+
+/* Define this symbol if your system has the functions bcopy, etc. */
+
+#define BSTRING
+
+/* subprocesses should be defined if you want to
+ have code for asynchronous subprocesses
+ (as used in M-x compile and M-x shell).
+ This is supposed to work now on system V release 2. */
+
+#define subprocesses
+
+/* If your system uses COFF (Common Object File Format) then define the
+ preprocessor symbol "COFF". */
+
+/* #define COFF */
+
+/* define MAIL_USE_FLOCK if the mailer uses flock
+ to interlock access to /usr/spool/mail/$USER.
+ The alternative is that a lock file named
+ /usr/spool/mail/$USER.lock. */
+
+/* #define MAIL_USE_FLOCK */
+
+/* Define CLASH_DETECTION if you want lock files to be written
+ so that Emacs can tell instantly when you try to modify
+ a file that someone else has modified in his Emacs. */
+
+/* #define CLASH_DETECTION */
+
+/* Define SHORTNAMES if the C compiler can distinguish only
+ short names. It means that the stuff in ../shortnames
+ must be run to convert the long names to short ones. */
+
+/* #define SHORTNAMES */
+
+/* We do NOT use the Berkeley (and usg5.2.2) interface to nlist. */
+
+/* #define NLIST_STRUCT */
+
+/* The file containing the kernel's symbol table is called /unix. */
+
+#define KERNEL_FILE "/unix"
+
+/* The symbol in the kernel where the load average is found
+ is named avenrun. */
+
+#define LDAV_SYMBOL "avenrun"
+
+/* Special itemss needed to make Emacs run on this system. */
+
+/*
+ * Make the sigsetmask function go away. Don't know what the
+ * ramifications of this are, but doesn't seem possible to
+ * emulate it properly anyway at this point.
+ */
+
+#define sigsetmask(mask) /* Null expansion */
+
+/* setjmp and longjmp can safely replace _setjmp and _longjmp,
+ but they will run slower. */
+
+#define _setjmp setjmp
+#define _longjmp longjmp
+
+/* On USG systems the system calls are interruptable by signals
+ that the user program has elected to catch. Thus the system call
+ must be retried in these cases. To handle this without massive
+ changes in the source code, we remap the standard system call names
+ to names for our own functions in sysdep.c that do the system call
+ with retries. */
+
+#define read sys_read
+#define open sys_open
+#define write sys_write
+
+#define INTERRUPTABLE_OPEN
+#define INTERRUPTABLE_IO
+
+/* On USG systems these have different names */
+
+#define index strchr
+#define rindex strrchr
+
+/* USG systems tend to put everything declared static
+ into the initialized data area, which becomes pure after dumping Emacs.
+ Foil this. Emacs carefully avoids static vars inside functions. */
+
+#undef static
+
+/* Compiler bug bites on many systems when default ADDR_CORRECT is used. */
+
+/* #define ADDR_CORRECT(x) (x) */
+
+#define LINKER cc
+
+/* Prevent -lg from being used for debugging. Not needed. */
+
+#define LIBS_DEBUG
+
+/* No need to specify -lc when linking. */
+
+#define LIB_STANDARD
+
+/* Use terminfo instead of termcap. */
+
+#define TERMINFO
+
+/* The following definition seems to be needed in AIX version 3.1.6.8.
+ It may not have been needed in certain earlier versions. */
+#define HAVE_TCATTR
+
+#define SYSTEM_MALLOC
+
+/* Use the gethostname system call. */
+#define HAVE_GETHOSTNAME
diff --git a/src/s-aix3-2.h b/src/s-aix3-2.h
new file mode 100644
index 00000000000..acebe9ab798
--- /dev/null
+++ b/src/s-aix3-2.h
@@ -0,0 +1,11 @@
+/* s- file for building Emacs on AIX 3.2.
+ This is a guess, since AIX 3.2 hasn't been released yet. */
+
+#include "s-aix3-1.h"
+
+/* Stop m-ibmrs6000.h from defining this. */
+#define SPECIFY_X11R4 1
+
+/* These work in 3.2, and are optimized when string.h is used. */
+#undef index
+#undef rindex
diff --git a/src/s-bsd4-1.h b/src/s-bsd4-1.h
new file mode 100644
index 00000000000..7e9b52bd41c
--- /dev/null
+++ b/src/s-bsd4-1.h
@@ -0,0 +1,145 @@
+/* Definitions file for GNU Emacs running on bsd 4.1.
+ Copyright (C) 1985, 1986 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/*
+ * Define symbols to identify the version of Unix this is.
+ * Define all the symbols that apply correctly.
+ */
+
+#define BSD4_1
+
+#define BSD
+
+/* SYSTEM_TYPE should indicate the kind of system you are using.
+ It sets the Lisp variable system-type. */
+
+#define SYSTEM_TYPE "berkeley-unix"
+
+/* nomultiplejobs should be defined if your system's shell
+ does not have "job control" (the ability to stop a program,
+ run some other program, then continue the first one). */
+
+/* #define NOMULTIPLEJOBS */
+
+/* Default is to set interrupt_input to 1: do input buffering within Emacs */
+
+#define INTERRUPT_INPUT
+
+/* First pty name is /dev/ptyp0. */
+
+#define FIRST_PTY_LETTER 'p'
+
+/*
+ * Define HAVE_TIMEVAL if the system supports the BSD style clock values.
+ * Look in <sys/time.h> for a timeval structure.
+ */
+
+#undef HAVE_TIMEVAL
+
+/*
+ * Define HAVE_SELECT if the system supports the `select' system call.
+ */
+
+/* #define HAVE_SELECT */
+
+/*
+ * Define HAVE_PTYS if the system supports pty devices.
+ */
+
+/* #define HAVE_PTYS */
+
+/* Define HAVE_SOCKETS if system supports 4.2-compatible sockets. */
+
+/* #define HAVE_SOCKETS */
+
+/*
+ * Define NONSYSTEM_DIR_LIBRARY to make Emacs emulate
+ * The 4.2 opendir, etc., library functions.
+ */
+
+#define NONSYSTEM_DIR_LIBRARY
+
+/* Define this symbol if your system has the functions bcopy, etc. */
+
+/* #define BSTRING */
+
+/* subprocesses should be defined if you want to
+ have code for asynchronous subprocesses
+ (as used in M-x compile and M-x shell).
+ This is generally OS dependent, and not supported
+ under most USG systems. */
+
+#define subprocesses
+
+/* If your system uses COFF (Common Object File Format) then define the
+ preprocessor symbol "COFF". */
+
+/* #define COFF */
+
+/* define MAIL_USE_FLOCK if the mailer uses flock
+ to interlock access to /usr/spool/mail/$USER.
+ The alternative is that a lock file named
+ /usr/spool/mail/$USER.lock. */
+
+/* #define MAIL_USE_FLOCK */
+
+/* Define CLASH_DETECTION if you want lock files to be written
+ so that Emacs can tell instantly when you try to modify
+ a file that someone else has modified in his Emacs. */
+
+#undef CLASH_DETECTION /* Might work; not tried yet. */
+
+/* We use the Berkeley (and usg5.2.2) interface to nlist. */
+
+#define NLIST_STRUCT
+
+/* The file containing the kernel's symbol table is called /vmunix. */
+
+#define KERNEL_FILE "/vmunix"
+
+/* The symbol in the kernel where the load average is found
+ is named _avenrun. */
+
+#define LDAV_SYMBOL "_avenrun"
+
+/* Special hacks needed to make Emacs run on this system. */
+
+/* Make the function `signal' act as in 4.2. */
+
+#define signal sigset
+
+#define _longjmp longjmp
+#define _setjmp setjmp
+
+#define lstat stat
+
+/* sys_open handles the necessary 4.2 features for open. */
+
+#define open sys_open
+
+/* Names of flags for open. */
+#define O_RDONLY 0
+#define O_WRONLY 1
+#define O_RDWR 2
+#define O_EXCL 2000
+#define O_CREAT 1000
+
+/* Special library needed for linking for 4.1. */
+#define LIBS_SYSTEM -ljobs
diff --git a/src/s-bsd4-2.h b/src/s-bsd4-2.h
new file mode 100644
index 00000000000..9d3ed6e3703
--- /dev/null
+++ b/src/s-bsd4-2.h
@@ -0,0 +1,124 @@
+/* Definitions file for GNU Emacs running on bsd 4.2
+ Copyright (C) 1985, 1986 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/*
+ * Define symbols to identify the version of Unix this is.
+ * Define all the symbols that apply correctly.
+ */
+
+#ifndef BSD4_2
+#define BSD4_2
+#endif /* BSD4_2 */
+
+#ifndef BSD
+#define BSD
+#endif /* BSD */
+
+/* SYSTEM_TYPE should indicate the kind of system you are using.
+ It sets the Lisp variable system-type. */
+
+#define SYSTEM_TYPE "berkeley-unix"
+
+/* nomultiplejobs should be defined if your system's shell
+ does not have "job control" (the ability to stop a program,
+ run some other program, then continue the first one). */
+
+/* #define NOMULTIPLEJOBS */
+
+/* Default is to set interrupt_input to 1: do input buffering within Emacs */
+
+#define INTERRUPT_INPUT
+
+/* First pty name is /dev/ptyp0. */
+
+#define FIRST_PTY_LETTER 'p'
+
+/*
+ * Define HAVE_TIMEVAL if the system supports the BSD style clock values.
+ * Look in <sys/time.h> for a timeval structure.
+ */
+
+#define HAVE_TIMEVAL
+
+/*
+ * Define HAVE_SELECT if the system supports the `select' system call.
+ */
+
+#define HAVE_SELECT
+
+/*
+ * Define HAVE_PTYS if the system supports pty devices.
+ */
+
+#define HAVE_PTYS
+
+/* Define HAVE_SOCKETS if system supports 4.2-compatible sockets. */
+
+#define HAVE_SOCKETS
+
+/*
+ * Define NONSYSTEM_DIR_LIBRARY to make Emacs emulate
+ * The 4.2 opendir, etc., library functions.
+ */
+
+/* #define NONSYSTEM_DIR_LIBRARY */
+
+/* Define this symbol if your system has the functions bcopy, etc. */
+
+#define BSTRING
+
+/* subprocesses should be defined if you want to
+ have code for asynchronous subprocesses
+ (as used in M-x compile and M-x shell).
+ This is generally OS dependent, and not supported
+ under most USG systems. */
+
+#define subprocesses
+
+/* If your system uses COFF (Common Object File Format) then define the
+ preprocessor symbol "COFF". */
+
+/* #define COFF */
+
+/* define MAIL_USE_FLOCK if the mailer uses flock
+ to interlock access to /usr/spool/mail/$USER.
+ The alternative is that a lock file named
+ /usr/spool/mail/$USER.lock. */
+
+/* #define MAIL_USE_FLOCK */
+
+/* Define CLASH_DETECTION if you want lock files to be written
+ so that Emacs can tell instantly when you try to modify
+ a file that someone else has modified in his Emacs. */
+
+#define CLASH_DETECTION
+
+/* We use the Berkeley (and usg5.2.2) interface to nlist. */
+
+#define NLIST_STRUCT
+
+/* The file containing the kernel's symbol table is called /vmunix. */
+
+#define KERNEL_FILE "/vmunix"
+
+/* The symbol in the kernel where the load average is found
+ is named _avenrun. */
+
+#define LDAV_SYMBOL "_avenrun"
diff --git a/src/s-bsd4-3.h b/src/s-bsd4-3.h
new file mode 100644
index 00000000000..6d7c94bda58
--- /dev/null
+++ b/src/s-bsd4-3.h
@@ -0,0 +1,124 @@
+/* Definitions file for GNU Emacs running on bsd 4.3
+ Copyright (C) 1985, 1986 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/*
+ * Define symbols to identify the version of Unix this is.
+ * Define all the symbols that apply correctly.
+ */
+
+#ifndef BSD4_3
+#define BSD4_3
+#endif /* BSD4_3 */
+
+#ifndef BSD
+#define BSD
+#endif /* BSD */
+
+/* SYSTEM_TYPE should indicate the kind of system you are using.
+ It sets the Lisp variable system-type. */
+
+#define SYSTEM_TYPE "berkeley-unix"
+
+/* nomultiplejobs should be defined if your system's shell
+ does not have "job control" (the ability to stop a program,
+ run some other program, then continue the first one). */
+
+/* #define NOMULTIPLEJOBS */
+
+/* Do not use interrupt_input = 1 by default, because in 4.3
+ we can make noninterrupt input work properly. */
+
+#undef INTERRUPT_INPUT
+
+/* First pty name is /dev/ptyp0. */
+
+#define FIRST_PTY_LETTER 'p'
+/*
+ * Define HAVE_TIMEVAL if the system supports the BSD style clock values.
+ * Look in <sys/time.h> for a timeval structure.
+ */
+
+#define HAVE_TIMEVAL
+
+/*
+ * Define HAVE_SELECT if the system supports the `select' system call.
+ */
+
+#define HAVE_SELECT
+
+/*
+ * Define HAVE_PTYS if the system supports pty devices.
+ */
+
+#define HAVE_PTYS
+
+/* Define HAVE_SOCKETS if system supports 4.2-compatible sockets. */
+
+#define HAVE_SOCKETS
+
+/*
+ * Define NONSYSTEM_DIR_LIBRARY to make Emacs emulate
+ * The 4.2 opendir, etc., library functions.
+ */
+
+/* #define NONSYSTEM_DIR_LIBRARY */
+
+/* Define this symbol if your system has the functions bcopy, etc. */
+
+#define BSTRING
+
+/* subprocesses should be defined if you want to
+ have code for asynchronous subprocesses
+ (as used in M-x compile and M-x shell).
+ This is generally OS dependent, and not supported
+ under most USG systems. */
+
+#define subprocesses
+
+/* If your system uses COFF (Common Object File Format) then define the
+ preprocessor symbol "COFF". */
+
+/* #define COFF */
+
+/* define MAIL_USE_FLOCK if the mailer uses flock
+ to interlock access to /usr/spool/mail/$USER.
+ The alternative is that a lock file named
+ /usr/spool/mail/$USER.lock. */
+
+#define MAIL_USE_FLOCK
+
+/* Define CLASH_DETECTION if you want lock files to be written
+ so that Emacs can tell instantly when you try to modify
+ a file that someone else has modified in his Emacs. */
+
+#define CLASH_DETECTION
+
+/* We use the Berkeley (and usg5.2.2) interface to nlist. */
+
+#define NLIST_STRUCT
+
+/* The file containing the kernel's symbol table is called /vmunix. */
+
+#define KERNEL_FILE "/vmunix"
+
+/* The symbol in the kernel where the load average is found
+ is named _avenrun. */
+
+#define LDAV_SYMBOL "_avenrun"
diff --git a/src/s-dgux.h b/src/s-dgux.h
new file mode 100644
index 00000000000..72a385d3cd7
--- /dev/null
+++ b/src/s-dgux.h
@@ -0,0 +1,292 @@
+/* Definitions file for GNU Emacs running on Data General's DG/UX
+ version 4.32 and above.
+ Copyright (C) 1985, 1986, 1991 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/*
+ * Define symbols to identify the version of Unix this is.
+ * Define all the symbols that apply correctly.
+ */
+
+/* #define UNIPLUS */
+/* #define USG5 */
+/* #define USG */
+/* #define HPUX */
+/* #define UMAX */
+/* #define BSD4_1 */
+#define BSD4_2
+#define BSD4_3
+#define BSD
+/* #define VMS */
+
+/* SYSTEM_TYPE should indicate the kind of system you are using.
+ It sets the Lisp variable system-type. */
+
+#define SYSTEM_TYPE "dgux-unix"
+
+/* NOMULTIPLEJOBS should be defined if your system's shell
+ does not have "job control" (the ability to stop a program,
+ run some other program, then continue the first one). */
+
+/* #define NOMULTIPLEJOBS */
+
+/* Emacs can read input using SIGIO and buffering characters itself,
+ or using CBREAK mode and making C-g cause SIGINT.
+ The choice is controlled by the variable interrupt_input.
+ Define INTERRUPT_INPUT to make interrupt_input = 1 the default (use SIGIO)
+
+ SIGIO can be used only on systems that implement it (4.2 and 4.3).
+ CBREAK mode has two disadvatages
+ 1) At least in 4.2, it is impossible to handle the Meta key properly.
+ I hear that in system V this problem does not exist.
+ 2) Control-G causes output to be discarded.
+ I do not know whether this can be fixed in system V.
+
+ Another method of doing input is planned but not implemented.
+ It would have Emacs fork off a separate process
+ to read the input and send it to the true Emacs process
+ through a pipe.
+*/
+
+#define INTERRUPT_INPUT
+
+/* Letter to use in finding device name of first pty,
+ if system supports pty's. 'a' means it is /dev/ptya0 */
+
+#define FIRST_PTY_LETTER 'r'
+
+/*
+ * Define HAVE_TIMEVAL if the system supports the BSD style clock values.
+ * Look in <sys/time.h> for a timeval structure.
+ */
+
+#define HAVE_TIMEVAL
+
+/*
+ * Define HAVE_SELECT if the system supports the `select' system call.
+ */
+
+#define HAVE_SELECT
+
+/*
+ * Define HAVE_SOCKETS if the system supports sockets.
+ */
+
+#define HAVE_SOCKETS
+
+/*
+ * Define HAVE_PTYS if the system supports pty devices.
+ */
+
+#define HAVE_PTYS
+
+/*
+ * Define NONSYSTEM_DIR_LIBRARY to make Emacs emulate
+ * The 4.2 opendir, etc., library functions.
+ */
+
+/* #define NONSYSTEM_DIR_LIBRARY */
+
+/* Define this symbol if your system has the functions bcopy, etc. */
+
+#define BSTRING
+
+/* subprocesses should be defined if you want to
+ have code for asynchronous subprocesses
+ (as used in M-x compile and M-x shell).
+ This is generally OS dependent, and not supported
+ under most USG systems. */
+
+#define subprocesses
+
+/* If your system uses COFF (Common Object File Format) then define the
+ preprocessor symbol "COFF".
+
+ DGUX can use either COFF or ELF. To use ELF format, define ELF. */
+
+#ifndef ELF
+#define COFF
+#endif
+
+#ifndef COFF /* People will probably find this apparently unreliable
+ till the NFS dumping bug is fixed. */
+
+/* It is possible to undump to ELF with DG/UX 5.4, but for revisions below
+ 5.4.1 the undump MUST be done on a local file system, or the kernel will
+ panic. ELF executables have the advantage of using shared libraries,
+ while COFF executables will still work on 4.2x systems. */
+
+#define UNEXEC unexelf.o
+
+/* This makes sure that all segments in the executable are undumped,
+ not just text, data, and bss. In the case of Mxdb and shared
+ libraries, additional information is stored in other sections.
+ It does not hurt to have this defined if you don't use Mxdb or
+ shared libraries. In fact, it makes no difference. */
+
+/* Necessary for shared libraries and Mxdb debugging information. */
+#define USG_SHARED_LIBRARIES
+#endif
+
+/* define MAIL_USE_FLOCK if the mailer uses flock
+ to interlock access to /usr/spool/mail/$USER.
+ The alternative is that a lock file named
+ /usr/spool/mail/$USER.lock. */
+
+/* #define MAIL_USE_FLOCK */
+
+/* Define CLASH_DETECTION if you want lock files to be written
+ so that Emacs can tell instantly when you try to modify
+ a file that someone else has modified in his Emacs. */
+
+/* #define CLASH_DETECTION */
+
+/* Define a replacement for the baud rate switch, since DG/UX uses a different
+ from BSD. */
+
+#define BAUD_CONVERT { 0, 110, 134, 150, 300, 600, 1200, 1800, 2400, \
+ 4800, 9600, 19200, 38400 }
+
+/*
+ * Define HAVE_GETTIMEOFDAY if gettimeofday() system call is available.
+ */
+
+#define HAVE_GETTIMEOFDAY
+
+/*
+ * Define NLIST_STRUCT if the system has nlist.h
+ */
+
+#define NLIST_STRUCT
+
+/*
+ * Make WM Interface Compliant.
+ */
+
+#define XICCC
+
+/* Here, on a separate page, add any special hacks needed
+ to make Emacs work on this system. For example,
+ you might define certain system call names that don't
+ exist on your system, or that do different things on
+ your system and must be used only through an encapsulation
+ (Which you should place, by convention, in sysdep.c). */
+
+/* Some compilers tend to put everything declared static
+ into the initialized data area, which becomes pure after dumping Emacs.
+ On these systems, you must #define static as nothing to foil this.
+ Note that emacs carefully avoids static vars inside functions. */
+
+/* #define static */
+
+/* DG/UX SPECIFIC ADDITIONS TO TEMPLATE FOLLOW: */
+
+/* Use the Berkeley flavors of the library routines, instead of System V. */
+
+#define setpgrp(pid,pgrp) setpgrp2(pid,pgrp)
+#define getpgrp(pid) getpgrp2(pid)
+
+/* Act like Berkeley. */
+
+#define _setjmp(env) sigsetjmp(env,0)
+#define _longjmp(env,val) longjmp(env,val)
+
+/* Use TERMINFO instead of termcap */
+
+#define TERMINFO
+
+/*
+ * Define HAVE_TERMIO if the system provides sysV-style ioctls
+ * for terminal control.
+ * DG/UX has both BSD and AT&T style ioctl's. Bsd ioctl's don't
+ * seem to wait for the output to drain properly, so use System V.
+ */
+
+/* #define HAVE_TERMIO */
+
+/*
+ * DG/UX 4.10 needs the following to turn on berkeley ioctl's.
+ */
+
+#ifndef HAVE_TERMIO
+#ifndef _BSD_TTY_FLAVOR /* Already defined, in dgux 4.30. */
+#define _BSD_TTY_FLAVOR
+#endif
+#endif
+
+/*
+ * Use a Berkeley style sys/wait.h.
+ * This makes WIF* macros operate on structures instead of ints.
+ */
+
+#define _BSD_WAIT_FLAVOR
+
+/*
+ * Use BSD and POSIX-style signals. This is crucial!
+ */
+
+#define POSIX_SIGNALS
+
+/* Not worth converting the old GNU malloc to work with POSIX_SIGNALS. */
+#define SYSTEM_MALLOC
+
+/* Define this if you use System 5 Release 4 Streams */
+#define SYSV4_PTYS
+#define open sys_open
+#define close sys_close
+#define read sys_read
+#define write sys_write
+
+#define INTERRUPTABLE_OPEN
+#define INTERRUPTABLE_CLOSE
+/* can't hurt to define these, even though read/write should auto restart */
+#define INTERRUPTABLE_IO
+
+/* Can't use sys_signal because then etc/server.c would need sysdep.o. */
+#define signal(SIG,FUNC) berk_signal(SIG,FUNC)
+
+#define LD_SWITCH_SYSTEM
+/* Cannot depend on /lib/crt0.o because make does not understand an elink(1) */
+#define START_FILES pre-crt0.o
+#define LIBS_SYSTEM -ldgc /lib/crt0.o
+
+/* definitions for xmakefile production */
+#ifdef COFF
+
+#define C_COMPILER \
+ TARGET_BINARY_INTERFACE=m88kdguxcoff gcc -traditional
+
+#define LINKER \
+ TARGET_BINARY_INTERFACE=m88kdguxcoff ld
+
+#define MAKE_COMMAND \
+ TARGET_BINARY_INTERFACE=m88kdguxcoff make
+
+#else /* not COFF */
+
+#define C_COMPILER \
+ TARGET_BINARY_INTERFACE=m88kdguxelf gcc -traditional
+
+#define LINKER \
+ TARGET_BINARY_INTERFACE=m88kdguxelf ld
+
+#define MAKE_COMMAND \
+ TARGET_BINARY_INTERFACE=m88kdguxelf make
+
+#endif /* COFF */
diff --git a/src/s-dgux4-31.h b/src/s-dgux4-31.h
new file mode 100644
index 00000000000..b9b414a4b8e
--- /dev/null
+++ b/src/s-dgux4-31.h
@@ -0,0 +1,5 @@
+#include "s-dgux.h"
+
+/* No libdgc.a in dgux version 4.31. */
+#undef LIBS_SYSTEM
+#define LIBS_SYSTEM /lib/crt0.o
diff --git a/src/s-esix.h b/src/s-esix.h
new file mode 100644
index 00000000000..3cc8426ec3b
--- /dev/null
+++ b/src/s-esix.h
@@ -0,0 +1,29 @@
+/* Definitions for ESIX, a variant of v.5.3 for the 386. */
+/* These are based on reports for ESIX 5.3.2 D. */
+
+#include "s-usg5-3.h"
+
+#define HAVE_TIMEVAL
+
+/* Some versions of V.3 have this, but not all. ESIX does. */
+#define HAVE_PTYS
+#define SYSV_PTYS
+
+/* Have -lg be used for debugging. */
+#undef LIBS_DEBUG
+#define LIBS_DEBUG -lg
+
+/* If using Roell's X server, define X11R4 */
+#ifdef X11R4 /* Roell's X server */
+#define HAVE_GETTIMEOFDAY /* Thomas Roell's X11R4 lib defines gettimeofday */
+#define select sys_select /* Emacs select() not good enough? */
+#undef LIBX11_SYSTEM
+#define LIBX11_SYSTEM -lpt
+#endif /* X11R4 */
+
+/* ESIX does not need <sys/sioctl.h>, but needs <sys/ptem.h> */
+#define NO_SIOCTL_H
+#define NEED_PTEM_H
+#define USG_SYS_TIME
+#define USE_UTIME
+#define BROKEN_FIONREAD
diff --git a/src/s-esix5r4.h b/src/s-esix5r4.h
new file mode 100644
index 00000000000..95c5d9b6504
--- /dev/null
+++ b/src/s-esix5r4.h
@@ -0,0 +1,13 @@
+/* Definitions for ESIX System V 4.0.4, a variant of V.4 for the 386. */
+
+#include "s-usg5-4.h"
+
+#define LIB_X11_LIB -lsocket -lc -lX11
+#undef LIB_STANDARD
+#define LIB_STANDARD -lnsl -lns -lelf /usr/ucblib/libucb.a /usr/ccs/lib/crtn.o
+
+/* Resolve BSD string functions in X Window library from libucb.a. */
+#define BSTRING
+
+/* kelsey@mdd.comm.mot.com says this makes X windows work. */
+#define BROKEN_FIONREAD
diff --git a/src/s-hpux7.h b/src/s-hpux7.h
new file mode 100644
index 00000000000..fb07d9d1fe6
--- /dev/null
+++ b/src/s-hpux7.h
@@ -0,0 +1,268 @@
+/* Definitions file for GNU Emacs running on HPUX release 7.
+ Based on AT&T System V.2.
+ Copyright (C) 1985, 1986 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/*
+ * Define symbols to identify the version of Unix this is.
+ * Define all the symbols that apply correctly.
+ */
+
+#define USG /* System III, System V, etc */
+
+#define USG5
+
+#define HPUX
+
+/* SYSTEM_TYPE should indicate the kind of system you are using.
+ It sets the Lisp variable system-type. */
+
+#define SYSTEM_TYPE "hpux"
+
+/* `nomultiplejobs' should be defined if your system's shell
+ does not have "job control" (the ability to stop a program,
+ run some other program, then continue the first one).
+
+ On hpux this depends on the precise kind of machine in use,
+ so the m- file defines this symbol if appropriate. */
+
+/* Default is to set interrupt_input to 0: don't do input buffering within Emacs */
+
+/* #define INTERRUPT_INPUT */
+
+/* Letter to use in finding device name of first pty,
+ if system supports pty's. 'p' means it is /dev/ptym/ptyp0 */
+
+#define FIRST_PTY_LETTER 'p'
+
+/*
+ * Define HAVE_TERMIO if the system provides sysV-style ioctls
+ * for terminal control.
+ */
+
+#define HAVE_TERMIO
+
+/*
+ * Define HAVE_TIMEVAL if the system supports the BSD style clock values.
+ * Look in <sys/time.h> for a timeval structure.
+ */
+
+#define HAVE_TIMEVAL
+
+/* With HAVE_TIMEVAL define, Emacs expects to use `utimes'.
+ But HPUX does not have one. */
+
+#define MISSING_UTIMES
+
+/*
+ * Define HAVE_SELECT if the system supports the `select' system call.
+ */
+
+#define HAVE_SELECT
+
+/*
+ * Define HAVE_PTYS if the system supports pty devices.
+ */
+
+#define HAVE_PTYS
+
+/* Define HAVE_SOCKETS if system supports 4.2-compatible sockets. */
+
+#define HAVE_SOCKETS
+
+/*
+ * Define NONSYSTEM_DIR_LIBRARY to make Emacs emulate
+ * The 4.2 opendir, etc., library functions.
+ */
+
+/* #define NONSYSTEM_DIR_LIBRARY */
+
+/* Define this symbol if your system has the functions bcopy, etc.
+ * s800 and later versions of s300 (s200) kernels have equivilents
+ * of the BSTRING functions of BSD. If your s200 kernel doesn't have
+ * em comment out this section.
+ */
+
+#define BSTRING
+
+/* subprocesses should be defined if you want to
+ have code for asynchronous subprocesses
+ (as used in M-x compile and M-x shell).
+ This is generally OS dependent, and not supported
+ under most USG systems. */
+
+#define subprocesses
+
+/* If your system uses COFF (Common Object File Format) then define the
+ preprocessor symbol "COFF". */
+
+/* #define COFF */
+
+/* define MAIL_USE_FLOCK if the mailer uses flock
+ to interlock access to /usr/spool/mail/$USER.
+ The alternative is that a lock file named
+ /usr/spool/mail/$USER.lock. */
+
+/* #define MAIL_USE_FLOCK */
+
+/* Say we have the SYSV style of interprocess communication. */
+
+#define HAVE_SYSVIPC
+
+/* Define CLASH_DETECTION if you want lock files to be written
+ so that Emacs can tell instantly when you try to modify
+ a file that someone else has modified in his Emacs. */
+
+#define CLASH_DETECTION
+
+/* Define SHORTNAMES if the C compiler can distinguish only
+ short names. It means that the stuff in ../shortnames
+ must be run to convert the long names to short ones.
+
+ Some USG systems support long names.
+ If yours is one, DO NOT change this file!
+ Do #undef SHORTNAMES in the m- file or in config.h. */
+
+/* #define SHORTNAMES */
+
+/* We use the Berkeley (and usg5.2.2) interface to nlist. */
+
+#define NLIST_STRUCT
+
+/* The file containing the kernel's symbol table is called /hp-ux. */
+
+#define KERNEL_FILE "/hp-ux"
+
+/* The symbol in the kernel where the load average is found
+ depends on the cpu type, so we let the m- files define LDAV_SYMBOL. */
+
+/* Special hacks needed to make Emacs run on this system. */
+
+/*
+ * Make the sigsetmask function go away. Don't know what the
+ * ramifications of this are, but doesn't seem possible to
+ * emulate it properly anyway at this point.
+ */
+
+/* HPUX has sigsetmask */
+/* #define sigsetmask(mask) / * Null expansion * / */
+
+/* setjmp and longjmp can safely replace _setjmp and _longjmp,
+ but they will run slower. */
+
+/* HP-UX has _setjmp and _longjmp */
+/*
+#define _setjmp setjmp
+#define _longjmp longjmp
+*/
+
+/* On USG systems the system calls are interruptable by signals
+ that the user program has elected to catch. Thus the system call
+ must be retried in these cases. To handle this without massive
+ changes in the source code, we remap the standard system call names
+ to names for our own functions in sysdep.c that do the system call
+ with retries. */
+
+#define read sys_read
+#define open sys_open
+#define write sys_write
+
+#define INTERRUPTABLE_OPEN
+#define INTERRUPTABLE_IO
+
+/* Use the system provided termcap(3) library */
+#define TERMINFO
+
+/* The 48-bit versions are more winning for Emacs. */
+
+#define rand lrand48
+#define srand srand48
+
+/* In hpux, the symbol SIGIO is defined, but the feature
+ does not really exist.
+
+ Here we assume that signal.h is included before config.h
+ so that we can override it here. */
+
+#undef SIGIO
+
+/* USG systems tend to put everything declared static
+ into the initialized data area, which becomes pure after dumping Emacs.
+ Foil this. Emacs carefully avoids static vars inside functions. */
+
+#define static
+
+/* Define extra libraries to load.
+ This should have -lBSD, but that library is said to make
+ `signal' fail to work. */
+
+#ifdef HPUX_NET
+#define LIBS_SYSTEM -ln
+#else
+#define LIBS_SYSTEM
+#endif
+
+/* Some additional system facilities exist. */
+
+#define HAVE_DUP2
+#define HAVE_GETTIMEOFDAY
+#define HAVE_GETHOSTNAME
+#define HAVE_VFORK
+#define HAVE_RENAME
+
+/* The following maps shared exec file to demand loaded exec.
+ Don't do this as demand loaded exec is broken in hpux. */
+
+#if 0
+
+/* Adjust a header field for the executable file about to be dumped. */
+
+#define ADJUST_EXEC_HEADER \
+ hdr.a_magic = ((ohdr.a_magic.file_type == OLDMAGIC.file_type) ? \
+ NEWMAGIC : ohdr.a_magic);
+
+#endif
+
+/* Baud-rate values in tty status have nonstandard meanings. */
+
+#define BAUD_CONVERT \
+{ 0, 50, 75, 110, 135, 150, 200, 300, 600, 900, 1200, \
+ 1800, 2400, 3600, 4800, 7200, 9600, 19200, 38400 }
+
+/* This is needed for HPUX version 6.2; it may not be needed for 6.2.1. */
+#define SHORT_CAST_BUG
+
+/* Define killpg so that we have process group functionality under HP. */
+#define killpg(PGRP, KSIG) kill (-(PGRP), KSIG)
+
+#ifndef NOT_C_CODE
+#ifndef NO_SHORTNAMES
+#include <sys/wait.h>
+#define WAITTYPE int
+#endif
+#define WRETCODE(w) (((w) >> 8) & 0377)
+#endif
+
+#if 0 /* This is in s-hpux8.h. */
+/* Get rid of this for HP/UX versions before version 8. */
+#define LD_SWITCH_SYSTEM -a archive
+#endif
+
+/* This affects XInitWindow in x11term.c. */
+#define NO_X_DESTROY_DATABASE
diff --git a/src/s-hpux8.h b/src/s-hpux8.h
new file mode 100644
index 00000000000..8f8f0d566d4
--- /dev/null
+++ b/src/s-hpux8.h
@@ -0,0 +1,21 @@
+/* s- file for hpux version 8.
+ This contains changes that were suggested "for the hp700".
+ They were not needed for the 800.
+ Our conjecture that they are needed for hpux version 8,
+ which is what runs on the 700. */
+
+#include "s-hpux7.h"
+
+#define C_SWITCH_SYSTEM -I/usr/include/X11R4
+
+/* Don't use shared libraries. unexec doesn't handle them. */
+#define LD_SWITCH_SYSTEM -a archive -L/usr/lib/X11R4
+
+/* Some hpux 8 machines seem to have TIOCGWINSZ,
+ and none have sioctl.h, so might as well define this. */
+#define NO_SIOCTL_H
+
+/* Specify compiler options for compiling oldXMenu. */
+#define OLDXMENU_OPTIONS CFLAGS=-I/usr/include/X11R4
+
+#undef NO_X_DESTROY_DATABASE
diff --git a/src/s-iris3-5.h b/src/s-iris3-5.h
new file mode 100644
index 00000000000..b4028ebc49a
--- /dev/null
+++ b/src/s-iris3-5.h
@@ -0,0 +1,188 @@
+/* Definitions file for GNU Emacs running on Silicon Graphics 3.5
+ Copyright (C) 1987 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/*
+ * Define symbols to identify the version of Unix this is.
+ * Define all the symbols that apply correctly.
+ */
+
+#define USG
+#define USG5
+#define IRIS
+
+/* SYSTEM_TYPE should indicate the kind of system you are using.
+ It sets the Lisp variable system-type. */
+
+#define SYSTEM_TYPE "silicon-graphics-unix"
+
+/* nomultiplejobs should be defined if your system's shell
+ does not have "job control" (the ability to stop a program,
+ run some other program, then continue the first one). */
+
+#define NOMULTIPLEJOBS
+
+/* Default is to set interrupt_input to 0: don't do input buffering within Emacs */
+
+/* #define INTERRUPT_INPUT */
+
+/* Letter to use in finding device name of first pty,
+ if system supports pty's. 'a' means it is /dev/ptya0 */
+
+#define FIRST_PTY_LETTER 'a'
+
+/*
+ * Define HAVE_TERMIO if the system provides sysV-style ioctls
+ * for terminal control.
+ */
+
+#define HAVE_TERMIO
+
+/*
+ * Define HAVE_TIMEVAL if the system supports the BSD style clock values.
+ * Look in <sys/time.h> for a timeval structure.
+ */
+
+#define HAVE_TIMEVAL
+
+/*
+ * Define HAVE_SELECT if the system supports the `select' system call.
+ */
+
+#define HAVE_SELECT
+
+/*
+ * Define HAVE_PTYS if the system supports pty devices.
+ */
+
+#define HAVE_PTYS
+
+/* Define HAVE_SOCKETS if system supports 4.2-compatible sockets. */
+
+#define HAVE_SOCKETS
+
+/*
+ * Define NONSYSTEM_DIR_LIBRARY to make Emacs emulate
+ * The 4.2 opendir, etc., library functions.
+ */
+
+/* #define NONSYSTEM_DIR_LIBRARY */
+
+/* Define this symbol if your system has the functions bcopy, etc. */
+
+#define BSTRING
+
+/* subprocesses should be defined if you want to
+ have code for asynchronous subprocesses
+ (as used in M-x compile and M-x shell).
+ This is generally OS dependent, and not supported
+ under most USG systems. */
+
+#define subprocesses
+
+/* If your system uses COFF (Common Object File Format) then define the
+ preprocessor symbol "COFF". */
+
+/* #define COFF */
+
+/* define MAIL_USE_FLOCK if the mailer uses flock
+ to interlock access to /usr/spool/mail/$USER.
+ The alternative is that a lock file named
+ /usr/spool/mail/$USER.lock. */
+
+/* #define MAIL_USE_FLOCK */
+
+/* Define CLASH_DETECTION if you want lock files to be written
+ so that Emacs can tell instantly when you try to modify
+ a file that someone else has modified in his Emacs. */
+
+/* #define CLASH_DETECTION */
+
+/* We use the Berkeley (and usg5.2.2) interface to nlist. */
+
+#define NLIST_STRUCT
+
+/* The file containing the kernel's symbol table is called /vmunix. */
+
+#define KERNEL_FILE "/vmunix"
+
+/* The symbol in the kernel where the load average is found
+ is named _avenrun. */
+
+#define LDAV_SYMBOL "_avenrun"
+
+
+/* Special hacks needed to make Emacs run on this system. */
+
+/*
+ * Make the sigsetmask function go away. Don't know what the
+ * ramifications of this are, but doesn't seem possible to
+ * emulate it properly anyway at this point.
+ */
+
+#define sigsetmask(mask) /* Null expansion */
+
+/* The IRIS defines SIGIO in signal.h, but doesn't implement it. */
+#undef SIGIO
+
+#define LIBS_MACHINE -lbsd -ldbm -lPW
+#define C_SWITCH_MACHINE -I/usr/include/bsd
+
+/* setjmp and longjmp can safely replace _setjmp and _longjmp,
+ but they will run slower. */
+
+#define _setjmp setjmp
+#define _longjmp longjmp
+
+/* On USG systems the system calls are interruptable by signals
+ that the user program has elected to catch. Thus the system call
+ must be retried in these cases. To handle this without massive
+ changes in the source code, we remap the standard system call names
+ to names for our own functions in sysdep.c that do the system call
+ with retries. */
+
+#define read sys_read
+#define open sys_open
+#define write sys_write
+
+#define INTERRUPTABLE_OPEN
+#define INTERRUPTABLE_IO
+
+/* On USG systems these have different names */
+
+#define index strchr
+#define rindex strrchr
+
+/* USG systems tend to put everything declared static
+ into the initialized data area, which becomes pure after dumping Emacs.
+ Foil this. Emacs carefully avoids static vars inside functions. */
+
+/* #define static */
+
+/* Compiler bug bites on many systems when default ADDR_CORRECT is used. */
+
+#define ADDR_CORRECT(x) (int)((char *)(x) - (char*)0)
+
+/* some errno.h's don't actually allocate the variable itself */
+
+#define NEED_ERRNO
+
+/* The symbol FIONREAD is defined, but the feature does not work. */
+
+#define BROKEN_FIONREAD
diff --git a/src/s-iris3-6.h b/src/s-iris3-6.h
new file mode 100644
index 00000000000..4bd870eb68f
--- /dev/null
+++ b/src/s-iris3-6.h
@@ -0,0 +1,189 @@
+/* Definitions file for GNU Emacs running on Silicon Graphics system 3.6.
+ Copyright (C) 1987 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/*
+ * Define symbols to identify the version of Unix this is.
+ * Define all the symbols that apply correctly.
+ */
+
+#define USG
+#define USG5
+#define IRIS
+
+/* SYSTEM_TYPE should indicate the kind of system you are using.
+ It sets the Lisp variable system-type. */
+
+#define SYSTEM_TYPE "silicon-graphics-unix"
+
+/* nomultiplejobs should be defined if your system's shell
+ does not have "job control" (the ability to stop a program,
+ run some other program, then continue the first one). */
+
+#define NOMULTIPLEJOBS
+
+/* Default is to set interrupt_input to 0: don't do input buffering within Emacs */
+
+/* #define INTERRUPT_INPUT */
+
+/* Letter to use in finding device name of first pty,
+ if system supports pty's. 'a' means it is /dev/ptya0 */
+
+#define FIRST_PTY_LETTER 'a'
+
+/*
+ * Define HAVE_TERMIO if the system provides sysV-style ioctls
+ * for terminal control.
+ */
+
+#define HAVE_TERMIO
+
+/*
+ * Define HAVE_TIMEVAL if the system supports the BSD style clock values.
+ * Look in <sys/time.h> for a timeval structure.
+ */
+
+#define HAVE_TIMEVAL
+
+/* `utime' system call doesn't understand timevals. */
+
+#define IRIS_UTIME
+
+/*
+ * Define HAVE_SELECT if the system supports the `select' system call.
+ */
+
+#define HAVE_SELECT
+
+/*
+ * Define HAVE_PTYS if the system supports pty devices.
+ */
+
+#define HAVE_PTYS
+
+/* Define HAVE_SOCKETS if system supports 4.2-compatible sockets. */
+
+#define HAVE_SOCKETS
+
+/*
+ * Define NONSYSTEM_DIR_LIBRARY to make Emacs emulate
+ * The 4.2 opendir, etc., library functions.
+ */
+
+/* #define NONSYSTEM_DIR_LIBRARY */
+
+/* Define this symbol if your system has the functions bcopy, etc. */
+
+#define BSTRING
+
+/* subprocesses should be defined if you want to
+ have code for asynchronous subprocesses
+ (as used in M-x compile and M-x shell).
+ This is generally OS dependent, and not supported
+ under most USG systems. */
+
+#define subprocesses
+
+/* If your system uses COFF (Common Object File Format) then define the
+ preprocessor symbol "COFF". */
+
+/* #define COFF */
+
+/* define MAIL_USE_FLOCK if the mailer uses flock
+ to interlock access to /usr/spool/mail/$USER.
+ The alternative is that a lock file named
+ /usr/spool/mail/$USER.lock. */
+
+/* #define MAIL_USE_FLOCK */
+
+/* Define CLASH_DETECTION if you want lock files to be written
+ so that Emacs can tell instantly when you try to modify
+ a file that someone else has modified in his Emacs. */
+
+/* #define CLASH_DETECTION */
+
+/* We use the Berkeley (and usg5.2.2) interface to nlist. */
+
+#define NLIST_STRUCT
+
+/* The file containing the kernel's symbol table is called /vmunix. */
+
+#define KERNEL_FILE "/vmunix"
+
+/* The symbol in the kernel where the load average is found
+ is named _avenrun. */
+
+#define LDAV_SYMBOL "_avenrun"
+
+
+/* Special hacks needed to make Emacs run on this system. */
+
+/*
+ * Make the sigsetmask function go away. Don't know what the
+ * ramifications of this are, but doesn't seem possible to
+ * emulate it properly anyway at this point.
+ */
+
+#define sigsetmask(mask) /* Null expansion */
+#define sigblock(x) x
+
+/* The IRIS defines SIGIO in signal.h, but doesn't implement it. */
+#undef SIGIO
+
+#define LIBS_MACHINE -lbsd -ldbm -lPW
+#define C_SWITCH_MACHINE -I/usr/include/bsd
+
+/* setjmp and longjmp can safely replace _setjmp and _longjmp,
+ but they will run slower. */
+
+#define _setjmp setjmp
+#define _longjmp longjmp
+
+/* On USG systems the system calls are interruptable by signals
+ that the user program has elected to catch. Thus the system call
+ must be retried in these cases. To handle this without massive
+ changes in the source code, we remap the standard system call names
+ to names for our own functions in sysdep.c that do the system call
+ with retries. */
+
+#define read sys_read
+#define open sys_open
+#define write sys_write
+
+#define INTERRUPTABLE_OPEN
+#define INTERRUPTABLE_IO
+
+/* On USG systems these have different names */
+
+#define index strchr
+#define rindex strrchr
+
+/* USG systems tend to put everything declared static
+ into the initialized data area, which becomes pure after dumping Emacs.
+ Foil this. Emacs carefully avoids static vars inside functions. */
+
+/* #define static */
+
+/* Compiler bug bites on many systems when default ADDR_CORRECT is used. */
+
+#define ADDR_CORRECT(x) (int)((char *)(x) - (char*)0)
+
+/* some errno.h's don't actually allocate the variable itself */
+
+#define NEED_ERRNO
diff --git a/src/s-irix3-3.h b/src/s-irix3-3.h
new file mode 100644
index 00000000000..c76611bf13a
--- /dev/null
+++ b/src/s-irix3-3.h
@@ -0,0 +1,186 @@
+/* Definitions file for GNU Emacs running on Silicon Graphics Irix system 3.3.
+ Copyright (C) 1987,1990 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/*
+ * Define symbols to identify the version of Unix this is.
+ * Define all the symbols that apply correctly.
+ */
+
+#define USG
+#define USG5
+#define IRIS
+#ifndef IRIX
+#define IRIX
+#endif
+
+/* SYSTEM_TYPE should indicate the kind of system you are using.
+ It sets the Lisp variable system-type. */
+
+#define SYSTEM_TYPE "silicon-graphics-unix"
+
+/* nomultiplejobs should be defined if your system's shell
+ does not have "job control" (the ability to stop a program,
+ run some other program, then continue the first one). */
+
+#define NOMULTIPLEJOBS
+
+/* Default is to set interrupt_input to 0: don't do input buffering within Emacs */
+
+/* #define INTERRUPT_INPUT */
+
+/* Letter to use in finding device name of first pty,
+ if system supports pty's. 'a' means it is /dev/ptya0 */
+
+#define FIRST_PTY_LETTER 'a'
+
+/*
+ * Define HAVE_TERMIO if the system provides sysV-style ioctls
+ * for terminal control.
+ */
+
+#define HAVE_TERMIO
+
+/*
+ * Define HAVE_TIMEVAL if the system supports the BSD style clock values.
+ * Look in <sys/time.h> for a timeval structure.
+ */
+
+#define HAVE_TIMEVAL
+
+/* `utime' system call doesn't understand timevals. */
+
+#define IRIS_UTIME
+
+/*
+ * Define HAVE_SELECT if the system supports the `select' system call.
+ */
+
+#define HAVE_SELECT
+
+/*
+ * Define HAVE_PTYS if the system supports pty devices.
+ */
+
+#define HAVE_PTYS
+
+/* Define HAVE_SOCKETS if system supports 4.2-compatible sockets. */
+
+#define HAVE_SOCKETS
+
+/*
+ * Define NONSYSTEM_DIR_LIBRARY to make Emacs emulate
+ * The 4.2 opendir, etc., library functions.
+ */
+
+/* #define NONSYSTEM_DIR_LIBRARY */
+
+/* Define this symbol if your system has the functions bcopy, etc. */
+
+#define BSTRING
+
+/* subprocesses should be defined if you want to
+ have code for asynchronous subprocesses
+ (as used in M-x compile and M-x shell).
+ This is generally OS dependent, and not supported
+ under most USG systems. */
+
+#define subprocesses
+
+/* If your system uses COFF (Common Object File Format) then define the
+ preprocessor symbol "COFF". */
+
+/* #define COFF */
+
+/* define MAIL_USE_FLOCK if the mailer uses flock
+ to interlock access to /usr/spool/mail/$USER.
+ The alternative is that a lock file named
+ /usr/spool/mail/$USER.lock. */
+
+/* #define MAIL_USE_FLOCK */
+
+/* Define CLASH_DETECTION if you want lock files to be written
+ so that Emacs can tell instantly when you try to modify
+ a file that someone else has modified in his Emacs. */
+
+/* #define CLASH_DETECTION */
+
+/* We use the Berkeley (and usg5.2.2) interface to nlist. */
+
+#define NLIST_STRUCT
+
+/* The file containing the kernel's symbol table is called /unix. */
+
+#define KERNEL_FILE "/unix"
+
+/* The symbol in the kernel where the load average is found
+ is named _avenrun. (Actually, no such symbol is right;
+ sysmp must be used to find the address.) */
+
+#define LDAV_SYMBOL "avenrun"
+
+/* setjmp and longjmp can safely replace _setjmp and _longjmp,
+ but they will run slower. */
+
+#define _setjmp setjmp
+#define _longjmp longjmp
+
+/* On USG systems the system calls are interruptable by signals
+ that the user program has elected to catch. Thus the system call
+ must be retried in these cases. To handle this without massive
+ changes in the source code, we remap the standard system call names
+ to names for our own functions in sysdep.c that do the system call
+ with retries. */
+
+#define read sys_read
+#define open sys_open
+#define write sys_write
+
+#define INTERRUPTABLE_OPEN
+#define INTERRUPTABLE_IO
+
+/* On USG systems these have different names */
+
+#define index strchr
+#define rindex strrchr
+
+/* Use setsid to handle terminals for subprocesses. */
+#define HAVE_SETSID
+
+/* getwd is defined. */
+#define HAVE_GETWD
+
+/* Implementation of uname is broken on Irix as of version 3.3 */
+#define HAVE_GETHOSTNAME
+
+#define HAVE_SYSVIPC
+
+/* 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 */
+
+/* Send a signal to a subprocess by "typing" a signal character. */
+
+#define SIGNALS_VIA_CHARACTERS
diff --git a/src/s-irix4-0.h b/src/s-irix4-0.h
new file mode 100644
index 00000000000..36958530023
--- /dev/null
+++ b/src/s-irix4-0.h
@@ -0,0 +1,45 @@
+#include "s-irix3-3.h"
+
+#define USG5_3
+
+/* Define HAVE_ALLOCA to say that the system provides a properly
+ working alloca function and it should be used. */
+#define HAVE_ALLOCA
+#undef C_ALLOCA
+#define alloca __builtin_alloca
+
+/* use K&R C */
+#define C_SWITCH_MACHINE -cckr
+
+/* SGI has all the fancy wait stuff, but we can't include sys/wait.h
+ because it defines BIG_ENDIAN and LITTLE_ENDIAN (ugh!.) Instead
+ we'll just define WNOHANG right here.
+ (An implicit decl is good enough for wait3.) */
+
+#define WNOHANG 0x1
+
+/* No need to use sprintf to get the tty name--we get that from _getpty. */
+#define PTY_TTY_NAME_SPRINTF
+/* No need to get the pty name at all. */
+#define PTY_NAME_SPRINTF
+#ifdef emacs
+char *_get_pty();
+#endif
+/* We need only try once to open a pty. */
+#define PTY_ITERATION
+/* Here is how to do it. */
+/* It is necessary to prevent SIGCHLD signals within _getpty.
+ So we block them. */
+#define PTY_OPEN \
+{ \
+ int mask = sigblock (sigmask (SIGCHLD)); \
+ char *name = _getpty (&fd, O_RDWR | O_NDELAY, 0600, 0); \
+ sigsetmask(mask); \
+ if (name == 0) \
+ return -1; \
+ if (fd < 0) \
+ return -1; \
+ if (fstat (fd, &stb) < 0) \
+ return -1; \
+ strcpy (pty_name, name); \
+}
diff --git a/src/s-isc2-2.h b/src/s-isc2-2.h
new file mode 100644
index 00000000000..ce15b5162d9
--- /dev/null
+++ b/src/s-isc2-2.h
@@ -0,0 +1,51 @@
+/* s- file for Interactive (ISC) Unix version 2.2 on the 386. */
+
+#include "s-usg5-3.h"
+
+#define HAVE_SOCKETS
+#define HAVE_SELECT
+#define HAVE_PTYS
+#define HAVE_RENAME
+#define HAVE_CLOSEDIR
+#define MAXNAMLEN 512
+#define LIB_STANDARD -lPW -lcposix -lc
+#define O_NDELAY O_NONBLOCK
+#define MEMORY_IN_STRING_H
+
+/* ball@seal.witchcraft.com says suspending works ok in 18.58. */
+/* #undef SIGTSTP */
+
+/* This communicates with m-intel386.h. */
+#define DONT_DEFINE_SIGNAL
+
+/* May be needed to avoid undefined symbols
+ such as gethostname, inet_addr, gethostbyname, socket, connect... */
+/* ??? There is a suggestion that -lpt is needed here.
+ If you have trouble compiling wiht HAVE_X_WINDOWS, please try that. */
+#define LIBS_SYSTEM -linet
+
+/* This system has job control. */
+#undef NOMULTIPLEJOBS
+
+/* Send a signal to a subprocess by "typing" a signal character. */
+#define SIGNALS_VIA_CHARACTERS
+#define TIOCGPGRP (TIOC|21) /* From termio.h. */
+
+#if 0
+/* Some files need types.h to link properly. */
+#ifndef NO_SHORTNAMES /* Don't do this in ymakefile! */
+#include <sys/types.h>
+#endif
+#endif
+
+#if 0 /* These might be needed if you compile with `gcc -posix'.
+ It's not certain. */
+/* I'm not sure under what circumstances this file is needed, but both
+ gcc and cc link with it by default, so... */
+#define OBJECTS_SYSTEM /lib/crtn.o
+
+/* Link with POSIX runtime if we are compiling in the POSIX environment. */
+#ifdef _POSIX_SOURCE
+#define START_FILES pre-crt0.o /lib/crtp0.o
+#endif
+#endif
diff --git a/src/s-isc3-0.h b/src/s-isc3-0.h
new file mode 100644
index 00000000000..30a48bb5318
--- /dev/null
+++ b/src/s-isc3-0.h
@@ -0,0 +1,7 @@
+/* s- file for Interactive (ISC) Unix version 3.0 on the 386. */
+
+#include "s-isc2-2.h"
+
+/* These have been moved into s-isc2-2.h. */
+/* #define HAVE_SOCKETS
+#define HAVE_SELECT */
diff --git a/src/s-mach2.h b/src/s-mach2.h
new file mode 100644
index 00000000000..e12a8a9469d
--- /dev/null
+++ b/src/s-mach2.h
@@ -0,0 +1,53 @@
+/* Definitions for Emacs running on Mach version 2 (non-kernelized system).
+ Copyright (C) 1990 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+
+
+#include "s-bsd4-3.h"
+
+
+/* SYSTEM_TYPE should indicate the kind of system you are using.
+ It sets the Lisp variable system-type. We'll need to undo the bsd one. */
+
+#undef SYSTEM_TYPE
+#define SYSTEM_TYPE "next-mach"
+
+
+#define LD_SWITCH_SYSTEM -X -noseglinkedit
+
+
+#define LIB_STANDARD -lsys_s
+
+#define environ _environ
+
+#define NO_REMAP
+#define UNEXEC unexnext.o
+
+/* start_of_text isn't actually used, so make it compile without error. */
+#define TEXT_START 0
+/* This seems to be right for end_of_text, but it may not be used anyway. */
+#define TEXT_END get_etext ()
+/* This seems to be right for end_of_data, but it may not be used anyway. */
+#define DATA_END get_edata ()
+
+/* Defining KERNEL_FILE causes lossage because sys/file.h
+ stupidly gets confused by it. */
+#undef KERNEL_FILE
+
diff --git a/src/s-newsos5.h b/src/s-newsos5.h
new file mode 100644
index 00000000000..8a37cb0f68b
--- /dev/null
+++ b/src/s-newsos5.h
@@ -0,0 +1,37 @@
+/* Definitions file for GNU Emacs running on Sony's NEWS-OS 5.0.1
+ Copyright (C) 1992 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Use the SysVr4 file for at least base configuration. */
+
+#include "s-usg5-4.h"
+
+#define NEWSOS5
+
+/* These will be defined by "m-mips.h". */
+#undef START_FILES
+#undef LIB_STANDARD
+
+/* Disable use of "unexelf.c" and shared libraries,
+ because NEWS-OS on MIPS doesn't support ELF. */
+#undef UNEXEC
+#undef USG_SHARED_LIBRARIES
+
+#ifndef HAVE_SOCKETS
+#define HAVE_SOCKETS
+#endif
diff --git a/src/s-osf1.h b/src/s-osf1.h
new file mode 100644
index 00000000000..65e80861cc1
--- /dev/null
+++ b/src/s-osf1.h
@@ -0,0 +1,14 @@
+#include "s-bsd4-3.h"
+
+/* Identify OSF1 for the m- files. */
+
+#define OSF1
+
+/* Define _BSD to tell the inlcude files we're running under
+ the BSD universe and not the SYSV universe. */
+
+#define C_SWITCH_SYSTEM -D_BSD
+#define LIBS_SYSTEM -lbsd
+#define LD_SWITCH_SYSTEM -non_shared
+
+#define SYSV_SYSTEM_DIR
diff --git a/src/s-rtu.h b/src/s-rtu.h
new file mode 100644
index 00000000000..73bf9c98c5d
--- /dev/null
+++ b/src/s-rtu.h
@@ -0,0 +1,160 @@
+/* Definitions file for GNU Emacs running on RTU 3.0, ucb universe.
+ Copyright (C) 1986 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/*
+ * Define symbols to identify the version of Unix this is.
+ * Define all the symbols that apply correctly.
+ */
+
+#define BSD4_2
+#define BSD
+#define RTU
+
+/* SYSTEM_TYPE should indicate the kind of system you are using.
+ It sets the Lisp variable system-type. */
+
+#define SYSTEM_TYPE "rtu"
+
+/* NOMULTIPLEJOBS should be defined if your system's shell
+ does not have "job control" (the ability to stop a program,
+ run some other program, then continue the first one). */
+
+#define NOMULTIPLEJOBS
+
+/* Emacs can read input using SIGIO and buffering characters itself,
+ or using CBREAK mode and making C-g cause SIGINT.
+ The choice is controlled by the variable interrupt_input.
+ Define INTERRUPT_INPUT to make interrupt_input = 1 the default (use SIGIO)
+
+ SIGIO can be used only on systems that implement it (4.2 and 4.3).
+ CBREAK mode has two disadvatages
+ 1) At least in 4.2, it is impossible to handle the Meta key properly.
+ I hear that in system V this problem does not exist.
+ 2) Control-G causes output to be discarded.
+ I do not know whether this can be fixed in system V.
+
+ Another method of doing input is planned but not implemented.
+ It would have Emacs fork off a separate process
+ to read the input and send it to the true Emacs process
+ through a pipe.
+*/
+
+#undef INTERRUPT_INPUT
+
+/* Letter to use in finding device name of first pty,
+ if system supports pty's. 'a' means it is /dev/ptya0 */
+
+#define FIRST_PTY_LETTER 'z' /* i.e. no PTY_LETTERs */
+
+/*
+ * Define HAVE_TIMEVAL if the system supports the BSD style clock values.
+ * Look in <sys/time.h> for a timeval structure.
+ */
+
+#define HAVE_TIMEVAL
+
+/*
+ * Define HAVE_SELECT if the system supports the `select' system call.
+ */
+
+#define HAVE_SELECT
+
+/*
+ * Define HAVE_PTYS if the system supports pty devices.
+ */
+
+#define HAVE_PTYS
+
+/* Define HAVE_SOCKETS if system supports 4.2-compatible sockets. */
+
+#define HAVE_SOCKETS
+
+/*
+ * Define NONSYSTEM_DIR_LIBRARY to make Emacs emulate
+ * The 4.2 opendir, etc., library functions.
+ */
+
+#define NONSYSTEM_DIR_LIBRARY
+
+/* Define this symbol if your system has the functions bcopy, etc. */
+/* The system library bcopy() is broken in RTU. For one thing, it expects
+ the length to be less than 64k. */
+#undef BSTRING
+
+/* subprocesses should be defined if you want to
+ have code for asynchronous subprocesses
+ (as used in M-x compile and M-x shell).
+ This is generally OS dependent, and not supported
+ under most USG systems. */
+
+#define subprocesses
+
+/* If your system uses COFF (Common Object File Format) then define the
+ preprocessor symbol "COFF". */
+
+#undef COFF
+
+/* define MAIL_USE_FLOCK if the mailer uses flock
+ to interlock access to /usr/spool/mail/$USER.
+ The alternative is that a lock file named
+ /usr/spool/mail/$USER.lock. */
+
+#undef MAIL_USE_FLOCK
+
+/* Define CLASH_DETECTION if you want lock files to be written
+ so that Emacs can tell instantly when you try to modify
+ a file that someone else has modified in his Emacs. */
+
+#undef CLASH_DETECTION
+
+/* We use the Berkeley (and usg5.2.2) interface to nlist. */
+
+#define NLIST_STRUCT
+
+/* The symbol in the kernel where the load average is found
+ is named _avenrun. */
+
+#define LDAV_SYMBOL "_avenrun"
+
+/* Special hacks needed to make Emacs run on this system. */
+
+/* On RTU systems (like USG) the system calls are interruptable by signals
+ that the user program has elected to catch. Thus the system call
+ must be retried in these cases. To handle this without massive
+ changes in the source code, we remap the standard system call names
+ to names for our own functions in sysdep.c that do the system call
+ with retries. */
+
+#define read sys_read
+#define open sys_open
+#define write sys_write
+
+#define INTERRUPTABLE_OPEN
+#define INTERRUPTABLE_IO
+
+/* The "fsync" call on RTU versions 3.0 and 3.1 is badly broken!
+ This hack below isn't the best solution, but without it this
+ program will cause the whole system to hang! !@#$#%$ Masscomp! */
+
+#define fsync(x) 0 /* "Comment out" fsync calls */
+
+/* RTU has IPC instead of Unix-domain sockets. */
+
+#define HAVE_SYSVIPC
diff --git a/src/s-sco.h b/src/s-sco.h
new file mode 100644
index 00000000000..794dbac3c82
--- /dev/null
+++ b/src/s-sco.h
@@ -0,0 +1,98 @@
+/* Support SCO V 3.2.4 (also called Open Desk Top 2.0) */
+
+#include "s-usg5-3.h"
+
+/* Use termios instead of termio, to turn off C-z. */
+
+#define HAVE_TCATTR
+
+/* It's possible for Emcs to suspend itself. */
+
+#undef NOMULTIPLEJOBS
+
+/* The setsid system call exists. */
+
+#define HAVE_SETSID
+
+/* The rename system call exists. */
+
+#define HAVE_RENAME
+
+/* Include ptem.h, not sioctl.h. */
+
+#define NO_SIOCTL_H
+#define NEED_PTEM_H
+
+/* Inhibit macro definition of `signal' in m-intel386.h. */
+
+#define DONT_DEFINE_SIGNAL
+
+/* We cannot get alloca from -lPW because various other symbols
+ in that library conflict with symbols in GCC. */
+
+#ifdef __GNUC__
+#define alloca(x) __builtin_alloca (x)
+#else
+#define C_ALLOCA
+#undef HAVE_ALLOCA
+#define STACK_DIRECTION -1
+#endif /* __GNUC__ */
+
+/* TIOCWINSZ doesn't work on ptys. */
+#define BROKEN_TIOCGWINSZ
+
+/* jbc@cunixa.cc.columbia.edu says this causes compilation errors
+ on SCO V.3.2.2. */
+/* #define HAVE_TIMEVAL */
+
+#define HAVE_SELECT
+
+#define HAVE_PTYS
+
+/* chip@tct.com says ptys are numbered decimally. */
+#define PTY_NAME_SPRINTF \
+ sprintf (pty_name, "/dev/ptyp%d", ((c - FIRST_PTY_LETTER) * 16) + i);
+#define PTY_TTY_NAME_SPRINTF \
+ sprintf (pty_name, "/dev/ttyp%d", ((c - FIRST_PTY_LETTER) * 16) + i);
+
+/* Christoph Badura <bad@flatlin.ka.sub.org> says this one is ok. */
+#define USG_SYS_TIME
+
+/* Define SCO_SOCKETS if your machie has sockets installed.
+ It is an optional feature in the SCO system. */
+
+#ifdef SCO_SOCKETS
+#define HAVE_SOCKETS
+#define LIBS_SYSTEM -lsocket
+#define HAVE_GETTIMEOFDAY
+#define HAVE_TIMEVAL
+#define USE_UTIME
+#endif
+
+/* These have been suggested, but it's not certain they are right. */
+#if 0
+#define HAVE_RANDOM
+
+#define USE_UTIME
+#endif /* 0 */
+
+
+#ifdef HAVE_X11
+/* William Smith (wjs@wang.com) said these are needed. */
+#ifdef LIBS_SYSTEM /* undef if defined in SCO_SOCKETS */
+#undef LIBS_SYSTEM
+#endif
+#define LIB_X11_LIB /* kill internal libs (use one below) */
+#define LIBS_SYSTEM -lXm -lXt -lX11 -lsocket -lmalloc -lPW
+#define LIB_STANDARD -lc /* get libPW.a from above */
+
+#undef C_ALLOCA
+#define HAVE_ALLOCA
+
+#define BROKEN_FIONREAD
+#define SYSV_STREAMS
+
+#define select XSelect
+#define HAVE_RANDOM
+#define BSTRING
+#endif
diff --git a/src/s-sco3-2-1.h b/src/s-sco3-2-1.h
new file mode 100644
index 00000000000..26d4bab35e0
--- /dev/null
+++ b/src/s-sco3-2-1.h
@@ -0,0 +1,17 @@
+/* Support SCO V 3.2.1 (also called Open Desk Top 1.0) */
+/* For this to work,
+ you must also comment out the include of termios.h in sysdep.c.
+ Also, in time.el, change
+ (let ((process-connection-type nil))
+ to....
+ (let ((process-connection-type t)) */
+
+#include "s-sco3-2-2.h"
+
+#undef SIGTSTP /* make suspend-emacs spawn a sub-shell */
+
+#ifdef HAVE_X11
+#define bzero(a,s) memset(a,0,s)
+#define bcmp memcmp
+#define bcopy(a,b,s) memcpy(b,a,s)
+#endif /* HAVE_X11 */
diff --git a/src/s-sco3-2-2.h b/src/s-sco3-2-2.h
new file mode 100644
index 00000000000..4599f16fbca
--- /dev/null
+++ b/src/s-sco3-2-2.h
@@ -0,0 +1,18 @@
+/* Support SCO V 3.2.2 (also called Open Desk Top 1.1) */
+
+#include "s-sco.h"
+
+#ifdef HAVE_X11
+/* Use Xselect instead of XSelect. */
+#undef select
+#define select Xselect
+
+/* This version was before random and srandom were added to libX11.a. */
+#undef HAVE_RANDOM
+
+/* We don't have XrmDestroyDatabase in this version. */
+#define NO_X_DESTROY_DATABASE
+
+/* Note: on ODT version 1.0, you need #undef BSTRING. */
+
+#endif /* HAVE_X11 */
diff --git a/src/s-sco3-2-4.h b/src/s-sco3-2-4.h
new file mode 100644
index 00000000000..4fd33241e52
--- /dev/null
+++ b/src/s-sco3-2-4.h
@@ -0,0 +1,3 @@
+/* Support SCO V 3.2.4 (also called Open Desk Top 2.0) */
+
+#include "s-sco.h"
diff --git a/src/s-sol2.h b/src/s-sol2.h
new file mode 100644
index 00000000000..3e3ea3e5d03
--- /dev/null
+++ b/src/s-sol2.h
@@ -0,0 +1,18 @@
+#include "s-usg5-4.h"
+
+/* cracraft@ai.mit.edu says these work. */
+#define BROKEN_FIONREAD
+#undef SYSV_STREAMS
+
+#define POSIX
+
+/* Here is how to find X Windows. */
+#define LD_SWITCH_SYSTEM -L/usr/openwin/lib
+#define C_SWITCH_X_SYSTEM -I/usr/openwin/include
+
+/* Compile in non-ansi fashion to work around bugs in system header files. */
+#ifndef __GNUC__
+#define C_SWITCH_SYSTEM -Xs
+#else /* GCC */
+#define C_SWITCH_SYSTEM -traditional
+#endif /* GCC */
diff --git a/src/s-sunos4-0.h b/src/s-sunos4-0.h
new file mode 100644
index 00000000000..c5a7acbeb06
--- /dev/null
+++ b/src/s-sunos4-0.h
@@ -0,0 +1,12 @@
+#include "s-bsd4-2.h"
+
+#if 0 /* This may have been needed for an earlier version of Sun OS 4.
+ It seems to cause warnings in 4.0.3 and 4.1. */
+#define O_NDELAY FNDELAY /* Non-blocking I/O (4.2 style) */
+#endif
+
+#if __GNUC__ > 1
+#define LD_SWITCH_SYSTEM -e __start -static
+#else
+#define LD_SWITCH_SYSTEM -e __start -Bstatic
+#endif
diff --git a/src/s-sunos4-1.h b/src/s-sunos4-1.h
new file mode 100644
index 00000000000..bfa4dab721b
--- /dev/null
+++ b/src/s-sunos4-1.h
@@ -0,0 +1,34 @@
+#include "s-sunos4-0.h"
+
+/* 4.1.1 makes these system calls interruptable. */
+
+#define read sys_read
+#define write sys_write
+#define open sys_open
+#define close sys_close
+
+#define INTERRUPTABLE_OPEN
+#define INTERRUPTABLE_CLOSE
+#define INTERRUPTABLE_IO
+
+
+#define HAVE_TZSET
+
+/* Cause the compilation of oldxmenu to use the right -I option. */
+#define OLDXMENU_OPTIONS CFLAGS=C_SWITCH_SYSTEM
+
+/* The following is needed to work with the "Open Windows"
+ version of X windows. But it should do no harm if you don't have that. */
+#if 1 /* The -I and -L options should be harmless otherwise. */
+#undef LD_SWITCH_SYSTEM
+#if __GNUC__ > 1
+#define LD_SWITCH_SYSTEM -e __start -static -L/usr/openwin/lib
+#else
+#define LD_SWITCH_SYSTEM -e __start -Bstatic -L/usr/openwin/lib
+#endif
+
+#define C_SWITCH_SYSTEM -I/usr/openwin/include
+#endif
+
+/* Enable a fix in malloc. */
+#define SUNOS_LOCALTIME_BUG
diff --git a/src/s-template.h b/src/s-template.h
new file mode 100644
index 00000000000..98ec9670a35
--- /dev/null
+++ b/src/s-template.h
@@ -0,0 +1,142 @@
+/* Template for s- header files.
+ This file describes the parameters that s- files should define or not.
+ Copyright (C) 1985, 1986 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/*
+ * Define symbols to identify the version of Unix this is.
+ * Define all the symbols that apply correctly.
+ */
+
+/* #define UNIPLUS */
+/* #define USG5 */
+/* #define USG */
+/* #define HPUX */
+/* #define UMAX */
+/* #define BSD4_1 */
+/* #define BSD4_2 */
+/* #define BSD4_3 */
+/* #define BSD */
+/* #define VMS */
+
+/* SYSTEM_TYPE should indicate the kind of system you are using.
+ It sets the Lisp variable system-type. */
+
+#define SYSTEM_TYPE "berkeley-unix"
+
+/* NOMULTIPLEJOBS should be defined if your system's shell
+ does not have "job control" (the ability to stop a program,
+ run some other program, then continue the first one). */
+
+/* #define NOMULTIPLEJOBS */
+
+/* Emacs can read input using SIGIO and buffering characters itself,
+ or using CBREAK mode and making C-g cause SIGINT.
+ The choice is controlled by the variable interrupt_input.
+ Define INTERRUPT_INPUT to make interrupt_input = 1 the default (use SIGIO)
+
+ SIGIO can be used only on systems that implement it (4.2 and 4.3).
+ CBREAK mode has two disadvatages
+ 1) At least in 4.2, it is impossible to handle the Meta key properly.
+ I hear that in system V this problem does not exist.
+ 2) Control-G causes output to be discarded.
+ I do not know whether this can be fixed in system V.
+
+ Another method of doing input is planned but not implemented.
+ It would have Emacs fork off a separate process
+ to read the input and send it to the true Emacs process
+ through a pipe.
+*/
+
+#define INTERRUPT_INPUT
+
+/* Letter to use in finding device name of first pty,
+ if system supports pty's. 'a' means it is /dev/ptya0 */
+
+#define FIRST_PTY_LETTER 'a'
+
+/*
+ * Define HAVE_TIMEVAL if the system supports the BSD style clock values.
+ * Look in <sys/time.h> for a timeval structure.
+ */
+
+#define HAVE_TIMEVAL
+
+/*
+ * Define HAVE_SELECT if the system supports the `select' system call.
+ */
+
+/* #define HAVE_SELECT */
+
+/*
+ * Define HAVE_PTYS if the system supports pty devices.
+ */
+
+#define HAVE_PTYS
+
+/*
+ * Define NONSYSTEM_DIR_LIBRARY to make Emacs emulate
+ * The 4.2 opendir, etc., library functions.
+ */
+
+#define NONSYSTEM_DIR_LIBRARY
+
+/* Define this symbol if your system has the functions bcopy, etc. */
+
+#define BSTRING
+
+/* subprocesses should be defined if you want to
+ have code for asynchronous subprocesses
+ (as used in M-x compile and M-x shell).
+ This is generally OS dependent, and not supported
+ under most USG systems. */
+
+#define subprocesses
+
+/* If your system uses COFF (Common Object File Format) then define the
+ preprocessor symbol "COFF". */
+
+/* #define COFF */
+
+/* define MAIL_USE_FLOCK if the mailer uses flock
+ to interlock access to /usr/spool/mail/$USER.
+ The alternative is that a lock file named
+ /usr/spool/mail/$USER.lock. */
+
+#define MAIL_USE_FLOCK
+
+/* Define CLASH_DETECTION if you want lock files to be written
+ so that Emacs can tell instantly when you try to modify
+ a file that someone else has modified in his Emacs. */
+
+#define CLASH_DETECTION
+
+/* Here, on a separate page, add any special hacks needed
+ to make Emacs work on this system. For example,
+ you might define certain system call names that don't
+ exist on your system, or that do different things on
+ your system and must be used only through an encapsulation
+ (Which you should place, by convention, in sysdep.c). */
+
+/* Some compilers tend to put everything declared static
+ into the initialized data area, which becomes pure after dumping Emacs.
+ On these systems, you must #define static as nothing to foil this.
+ Note that emacs carefully avoids static vars inside functions. */
+
+/* #define static */
diff --git a/src/s-umax.h b/src/s-umax.h
new file mode 100644
index 00000000000..19e2eea4c82
--- /dev/null
+++ b/src/s-umax.h
@@ -0,0 +1,174 @@
+/* Definitions file for GNU Emacs running on UMAX 4.2
+ Copyright (C) 1985, 1986 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/*
+ * Define symbols to identify the version of Unix this is.
+ * Define all the symbols that apply correctly.
+ */
+
+/* #define UNIPLUS */
+/* #define USG5 */
+/* #define USG */
+/* #define BSD4_1 */
+#define BSD4_2
+/* #define BSD4_3 */
+#define BSD
+#define UMAX4_2
+#define UMAX
+/* #define VMS */
+
+/* SYSTEM_TYPE should indicate the kind of system you are using.
+ It sets the Lisp variable system-type. */
+
+#define SYSTEM_TYPE "berkeley-unix"
+
+/* NOMULTIPLEJOBS should be defined if your system's shell
+ does not have "job control" (the ability to stop a program,
+ run some other program, then continue the first one). */
+
+/* #define NOMULTIPLEJOBS */
+
+/* Emacs can read input using SIGIO and buffering characters itself,
+ or using CBREAK mode and making C-g cause SIGINT.
+ The choice is controlled by the variable interrupt_input.
+ Define INTERRUPT_INPUT to make interrupt_input = 1 the default (use SIGIO)
+
+ SIGIO can be used only on systems that implement it (4.2 and 4.3).
+ CBREAK mode has two disadvatages
+ 1) At least in 4.2, it is impossible to handle the Meta key properly.
+ I hear that in system V this problem does not exist.
+ 2) Control-G causes output to be discarded.
+ I do not know whether this can be fixed in system V.
+
+ Another method of doing input is planned but not implemented.
+ It would have Emacs fork off a separate process
+ to read the input and send it to the true Emacs process
+ through a pipe.
+*/
+
+#define INTERRUPT_INPUT
+
+/* Letter to use in finding device name of first pty,
+ if system supports pty's. 'a' means it is /dev/ptya0 */
+
+#define FIRST_PTY_LETTER 'p'
+
+/*
+ * Define HAVE_TIMEVAL if the system supports the BSD style clock values.
+ * Look in <sys/time.h> for a timeval structure.
+ */
+
+#define HAVE_TIMEVAL
+
+/*
+ * Define HAVE_SELECT if the system supports the `select' system call.
+ */
+
+#define HAVE_SELECT
+
+/*
+ * Define HAVE_PTYS if the system supports pty devices.
+ */
+
+#define HAVE_PTYS
+
+/* Define HAVE_SOCKETS if system supports 4.2-compatible sockets. */
+
+#define HAVE_SOCKETS
+
+/*
+ * Define NONSYSTEM_DIR_LIBRARY to make Emacs emulate
+ * The 4.2 opendir, etc., library functions.
+ */
+
+/* #define NONSYSTEM_DIR_LIBRARY */
+
+/* Define this symbol if your system has the functions bcopy, etc. */
+
+#define BSTRING
+
+/* subprocesses should be defined if you want to
+ have code for asynchronous subprocesses
+ (as used in M-x compile and M-x shell).
+ This is generally OS dependent, and not supported
+ under most USG systems. */
+
+#define subprocesses
+
+/* If your system uses COFF (Common Object File Format) then define the
+ preprocessor symbol "COFF". */
+
+#define COFF
+
+/* define MAIL_USE_FLOCK if the mailer uses flock
+ to interlock access to /usr/spool/mail/$USER.
+ The alternative is that a lock file named
+ /usr/spool/mail/$USER.lock. */
+
+#define MAIL_USE_FLOCK
+
+/* Define CLASH_DETECTION if you want lock files to be written
+ so that Emacs can tell instantly when you try to modify
+ a file that someone else has modified in his Emacs. */
+
+#define CLASH_DETECTION
+
+/* We use the Berkeley (and usg5.2.2) interface to nlist. */
+
+#define NLIST_STRUCT
+
+/* The file containing the kernel's symbol table is called /vmunix. */
+
+#define KERNEL_FILE "/vmunix"
+
+/* The symbol in the kernel where the load average is found
+ is named _avenrun. */
+
+#define LDAV_SYMBOL "_avenrun"
+
+/* Here, on a separate page, add any special hacks needed
+ to make Emacs work on this system. For example,
+ you might define certain system call names that don't
+ exist on your system, or that do different things on
+ your system and must be used only through an encapsulation
+ (Which you should place, by convention, in sysdep.c). */
+
+/* Specify alignment requirement for start of text and data sections
+ in the executable file. */
+
+#define SECTION_ALIGNMENT pagemask
+
+
+#define SEGMENT_MASK (64 * 1024 - 1)
+
+
+/* crt0.c needs this for compilation because it uses asm. */
+
+#define C_SWITCH_ASM -q nodirect_code
+
+/* Encore machines with APC processor boards align sections on 4M
+ boundaries, so it is not easy to remap the start of the text segment
+ in the unexec() routine. For them you need the following two lines.
+ For DPC processors you can enable these or not, as you wish, but
+ you will get better performance without them. */
+
+/* #define NO_REMAP
+ #define TEXT_START 0
+*/
diff --git a/src/s-unipl5-0.h b/src/s-unipl5-0.h
new file mode 100644
index 00000000000..fdb97909b82
--- /dev/null
+++ b/src/s-unipl5-0.h
@@ -0,0 +1,188 @@
+/* Definitions file for GNU Emacs running on UniSoft's UniPlus 5.0
+ Support for this system is not finished; don't expect this to work.
+ Copyright (C) 1985, 1986 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/*
+ * Define symbols to identify the version of Unix this is.
+ * Define all the symbols that apply correctly.
+ */
+
+#define USG /* System III, System V, etc */
+
+#define USG5
+
+#define UNIPLUS
+
+/* SYSTEM_TYPE should indicate the kind of system you are using.
+ It sets the Lisp variable system-type. */
+
+#define SYSTEM_TYPE "unisoft-unix"
+
+/* NOMULTIPLEJOBS should be defined if your system's shell
+ does not have "job control" (the ability to stop a program,
+ run some other program, then continue the first one). */
+
+/* #define NOMULTIPLEJOBS */
+
+/* Default is to set interrupt_input to 0: don't do input buffering within Emacs */
+
+/* #define INTERRUPT_INPUT */
+
+/* Letter to use in finding device name of first pty,
+ if system supports pty's. 'a' means it is /dev/ptya0 */
+
+/* #define FIRST_PTY_LETTER 'a' */
+
+/*
+ * Define HAVE_TERMIO if the system provides sysV-style ioctls
+ * for terminal control.
+ */
+
+#define HAVE_TERMIO
+
+/*
+ * Define HAVE_TIMEVAL if the system supports the BSD style clock values.
+ * Look in <sys/time.h> for a timeval structure.
+ */
+
+/* #define HAVE_TIMEVAL */
+
+/*
+ * Define HAVE_SELECT if the system supports the `select' system call.
+ */
+
+/* #define HAVE_SELECT */
+
+/*
+ * Define HAVE_PTYS if the system supports pty devices.
+ */
+
+/* #define HAVE_PTYS */
+
+/* Define HAVE_SOCKETS if system supports 4.2-compatible sockets. */
+
+/* #define HAVE_SOCKETS */
+
+/*
+ * Define NONSYSTEM_DIR_LIBRARY to make Emacs emulate
+ * The 4.2 opendir, etc., library functions.
+ */
+
+#define NONSYSTEM_DIR_LIBRARY
+
+/* Define this symbol if your system has the functions bcopy, etc. */
+
+/* #define BSTRING */
+
+/* subprocesses should be defined if you want to
+ have code for asynchronous subprocesses
+ (as used in M-x compile and M-x shell).
+ This is generally OS dependent, and not supported
+ under most USG systems. */
+
+/* #define subprocesses */
+
+/* If your system uses COFF (Common Object File Format) then define the
+ preprocessor symbol "COFF". */
+
+/* #define COFF */
+
+/* define MAIL_USE_FLOCK if the mailer uses flock
+ to interlock access to /usr/spool/mail/$USER.
+ The alternative is that a lock file named
+ /usr/spool/mail/$USER.lock. */
+
+/* #define MAIL_USE_FLOCK */
+
+/* Define CLASH_DETECTION if you want lock files to be written
+ so that Emacs can tell instantly when you try to modify
+ a file that someone else has modified in his Emacs. */
+
+/* #define CLASH_DETECTION */
+
+/* Define SHORTNAMES if the C compiler can distinguish only
+ short names. It means that the stuff in ../shortnames
+ must be run to convert the long names to short ones.
+
+ Some USG systems support long names.
+ If yours is one, DO NOT change this file!
+ Do #undef SHORTNAMES in the m- file or in config.h. */
+
+#define SHORTNAMES
+
+/* We do NOT use the Berkeley (and usg5.2.2) interface to nlist. */
+
+/* #define NLIST_STRUCT */
+
+/* The file containing the kernel's symbol table is called /unix. */
+
+#define KERNEL_FILE "/unix"
+
+/* The symbol in the kernel where the load average is found
+ is named avenrun. */
+
+#define LDAV_SYMBOL "avenrun"
+
+/* Special hacks needed to make Emacs run on this system. */
+
+/*
+ * Make the sigsetmask function go away. Don't know what the
+ * ramifications of this are, but doesn't seem possible to
+ * emulate it properly anyway at this point.
+ */
+
+#define sigsetmask(mask) /* Null expansion */
+
+/* setjmp and longjmp can safely replace _setjmp and _longjmp,
+ but they will run slower. */
+
+#define _setjmp setjmp
+#define _longjmp longjmp
+
+/* On USG systems the system calls are interruptable by signals
+ that the user program has elected to catch. Thus the system call
+ must be retried in these cases. To handle this without massive
+ changes in the source code, we remap the standard system call names
+ to names for our own functions in sysdep.c that do the system call
+ with retries. */
+
+#define read sys_read
+#define open sys_open
+#define write sys_write
+
+#define INTERRUPTABLE_OPEN
+#define INTERRUPTABLE_IO
+
+/* On USG systems these have different names */
+
+#define index strchr
+#define rindex strrchr
+
+/* Compiler bug bites when default ADDR_CORRECT is used. */
+
+#define ADDR_CORRECT(x) (x)
+
+/* Special library needed for linking for Uniplus */
+
+#define LIBS_SYSTEM -lnet
+
+/* A system-specific loader switch is needed. */
+
+#define LD_SWITCH_SYSTEM -N -L/lib/libg /usr/lib/unshared.ld
diff --git a/src/s-unipl5-2.h b/src/s-unipl5-2.h
new file mode 100644
index 00000000000..ae34ad7a7df
--- /dev/null
+++ b/src/s-unipl5-2.h
@@ -0,0 +1,182 @@
+/* Definitions file for GNU Emacs running on UniSoft's UniPlus 5.2
+ Copyright (C) 1985, 1986 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/*
+ * Define symbols to identify the version of Unix this is.
+ * Define all the symbols that apply correctly.
+ */
+
+#define USG /* System III, System V, etc */
+
+#define USG5
+
+#define UNIPLUS
+
+/* SYSTEM_TYPE should indicate the kind of system you are using.
+ It sets the Lisp variable system-type. */
+
+#define SYSTEM_TYPE "unisoft-unix"
+
+/* nomultiplejobs should be defined if your system's shell
+ does not have "job control" (the ability to stop a program,
+ run some other program, then continue the first one). */
+
+/* #define NOMULTIPLEJOBS */
+
+/* Default is to set interrupt_input to 0: don't do input buffering within Emacs */
+
+/* #define INTERRUPT_INPUT */
+
+/* Letter to use in finding device name of first pty,
+ if system supports pty's. 'p' means it is /dev/ptyp0 */
+
+#define FIRST_PTY_LETTER 'p'
+
+/*
+ * Define HAVE_TERMIO if the system provides sysV-style ioctls
+ * for terminal control.
+ */
+
+#define HAVE_TERMIO
+
+/*
+ * Define HAVE_TIMEVAL if the system supports the BSD style clock values.
+ * Look in <sys/time.h> for a timeval structure.
+ */
+
+#define HAVE_TIMEVAL
+
+/*
+ * Define HAVE_SELECT if the system supports the `select' system call.
+ */
+
+#define HAVE_SELECT
+
+/*
+ * Define HAVE_PTYS if the system supports pty devices.
+ */
+
+#define HAVE_PTYS
+
+/* Define HAVE_SOCKETS if system supports 4.2-compatible sockets. */
+
+/* #define HAVE_SOCKETS */
+
+/*
+ * Define NONSYSTEM_DIR_LIBRARY to make Emacs emulate
+ * The 4.2 opendir, etc., library functions.
+ */
+
+#define NONSYSTEM_DIR_LIBRARY
+
+/* Define this symbol if your system has the functions bcopy, etc. */
+
+/* #define BSTRING */
+
+/* subprocesses should be defined if you want to
+ have code for asynchronous subprocesses
+ (as used in M-x compile and M-x shell).
+ This is generally OS dependent, and not supported
+ under most USG systems. It is supported under UniPlus
+ System V Release 2. */
+
+#define subprocesses
+
+/* If your system uses COFF (Common Object File Format) then define the
+ preprocessor symbol "COFF". */
+
+#define COFF
+
+/* define MAIL_USE_FLOCK if the mailer uses flock
+ to interlock access to /usr/spool/mail/$USER.
+ The alternative is that a lock file named
+ /usr/spool/mail/$USER.lock. */
+
+/* #define MAIL_USE_FLOCK */
+
+/* Define CLASH_DETECTION if you want lock files to be written
+ so that Emacs can tell instantly when you try to modify
+ a file that someone else has modified in his Emacs. */
+
+/* #define CLASH_DETECTION */
+
+/* Uniplus 5.2 supports long names in C */
+
+/* #define SHORTNAMES */
+
+/* We do NOT use the Berkeley (and usg5.2.2) interface to nlist. */
+
+/* #define NLIST_STRUCT */
+
+/* The file containing the kernel's symbol table is called /unix. */
+
+#define KERNEL_FILE "/unix"
+
+/* The symbol in the kernel where the load average is found
+ is named avenrun. */
+
+#define LDAV_SYMBOL "avenrun"
+
+/* Special hacks needed to make Emacs run on this system. */
+
+/*
+ * Make the sigsetmask function go away. Don't know what the
+ * ramifications of this are, but doesn't seem possible to
+ * emulate it properly anyway at this point.
+ */
+
+#define sigsetmask(mask) /* Null expansion */
+
+/* setjmp and longjmp can safely replace _setjmp and _longjmp,
+ but they will run slower. */
+
+#define _setjmp setjmp
+#define _longjmp longjmp
+
+/* On USG systems the system calls are interruptable by signals
+ that the user program has elected to catch. Thus the system call
+ must be retried in these cases. To handle this without massive
+ changes in the source code, we remap the standard system call names
+ to names for our own functions in sysdep.c that do the system call
+ with retries. */
+
+#define read sys_read
+#define open sys_open
+#define write sys_write
+
+#define INTERRUPTABLE_OPEN
+#define INTERRUPTABLE_IO
+
+/* On USG systems these have different names */
+
+#define index strchr
+#define rindex strrchr
+
+/* Compiler bug bites when default ADDR_CORRECT is used. */
+
+#define ADDR_CORRECT(x) (x)
+
+/* Special library needed for linking for Uniplus */
+
+#define LIBS_SYSTEM -lnet
+
+/* A system-specific loader switch is needed. */
+
+#define LD_SWITCH_SYSTEM -N -L/lib/libg /usr/lib/unshared.ld
diff --git a/src/s-usg5-0.h b/src/s-usg5-0.h
new file mode 100644
index 00000000000..cab314a4c4d
--- /dev/null
+++ b/src/s-usg5-0.h
@@ -0,0 +1,183 @@
+/* Definitions file for GNU Emacs running on AT&T's System V.0
+ Copyright (C) 1985, 1986 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/*
+ * Define symbols to identify the version of Unix this is.
+ * Define all the symbols that apply correctly.
+ */
+
+#define USG /* System III, System V, etc */
+
+#define USG5
+#define USG5_0
+
+/* SYSTEM_TYPE should indicate the kind of system you are using.
+ It sets the Lisp variable system-type. */
+
+#define SYSTEM_TYPE "usg-unix-v"
+
+/* nomultiplejobs should be defined if your system's shell
+ does not have "job control" (the ability to stop a program,
+ run some other program, then continue the first one). */
+
+#define NOMULTIPLEJOBS
+
+/* Default is to set interrupt_input to 0: don't do input buffering within Emacs */
+
+/* #define INTERRUPT_INPUT */
+
+/* Letter to use in finding device name of first pty,
+ if system supports pty's. 'p' means it is /dev/ptyp0 */
+
+#define FIRST_PTY_LETTER 'p'
+
+/*
+ * Define HAVE_TERMIO if the system provides sysV-style ioctls
+ * for terminal control.
+ */
+
+#define HAVE_TERMIO
+
+/*
+ * Define HAVE_TIMEVAL if the system supports the BSD style clock values.
+ * Look in <sys/time.h> for a timeval structure.
+ */
+
+/* #define HAVE_TIMEVAL */
+
+/*
+ * Define HAVE_SELECT if the system supports the `select' system call.
+ */
+
+/* #define HAVE_SELECT */
+
+/*
+ * Define HAVE_PTYS if the system supports pty devices.
+ */
+
+/* #define HAVE_PTYS */
+
+/* Define HAVE_SOCKETS if system supports 4.2-compatible sockets. */
+
+/* #define HAVE_SOCKETS */
+
+/*
+ * Define NONSYSTEM_DIR_LIBRARY to make Emacs emulate
+ * The 4.2 opendir, etc., library functions.
+ */
+
+#define NONSYSTEM_DIR_LIBRARY
+
+/* Define this symbol if your system has the functions bcopy, etc. */
+
+/* #define BSTRING */
+
+/* subprocesses should be defined if you want to
+ have code for asynchronous subprocesses
+ (as used in M-x compile and M-x shell).
+ This is supposed to work now on system V release 2. */
+
+#define subprocesses
+
+/* If your system uses COFF (Common Object File Format) then define the
+ preprocessor symbol "COFF". */
+
+#define COFF
+
+/* define MAIL_USE_FLOCK if the mailer uses flock
+ to interlock access to /usr/spool/mail/$USER.
+ The alternative is that a lock file named
+ /usr/spool/mail/$USER.lock. */
+
+/* #define MAIL_USE_FLOCK */
+
+/* Define CLASH_DETECTION if you want lock files to be written
+ so that Emacs can tell instantly when you try to modify
+ a file that someone else has modified in his Emacs. */
+
+/* #define CLASH_DETECTION */
+
+/* Define SHORTNAMES if the C compiler can distinguish only
+ short names. It means that the stuff in ../shortnames
+ must be run to convert the long names to short ones. */
+
+#define SHORTNAMES
+
+/* We do NOT use the Berkeley (and usg5.2.2) interface to nlist. */
+
+/* #define NLIST_STRUCT */
+
+/* The file containing the kernel's symbol table is called /unix. */
+
+#define KERNEL_FILE "/unix"
+
+/* The symbol in the kernel where the load average is found
+ is named avenrun. */
+
+#define LDAV_SYMBOL "avenrun"
+
+/* Special hacks needed to make Emacs run on this system. */
+
+/*
+ * Make the sigsetmask function go away. Don't know what the
+ * ramifications of this are, but doesn't seem possible to
+ * emulate it properly anyway at this point.
+ */
+
+#define sigsetmask(mask) /* Null expansion */
+
+/* setjmp and longjmp can safely replace _setjmp and _longjmp,
+ but they will run slower. */
+
+#define _setjmp setjmp
+#define _longjmp longjmp
+
+/* On USG systems the system calls are interruptable by signals
+ that the user program has elected to catch. Thus the system call
+ must be retried in these cases. To handle this without massive
+ changes in the source code, we remap the standard system call names
+ to names for our own functions in sysdep.c that do the system call
+ with retries. */
+
+#define read sys_read
+#define open sys_open
+#define write sys_write
+
+#define INTERRUPTABLE_OPEN
+#define INTERRUPTABLE_IO
+
+/* On USG systems these have different names */
+
+#define index strchr
+#define rindex strrchr
+
+/* USG systems tend to put everything declared static
+ into the initialized data area, which becomes pure after dumping Emacs.
+ Foil this. Emacs carefully avoids static vars inside functions. */
+
+#define static
+
+/* Compiler bug bites on many systems when default ADDR_CORRECT is used. */
+
+#define ADDR_CORRECT(x) (x)
+
+/* Prevent -lg from being used for debugging. Not implemented? */
+
+#define LIBS_DEBUG
diff --git a/src/s-usg5-2-2.h b/src/s-usg5-2-2.h
new file mode 100644
index 00000000000..763c9f49ee1
--- /dev/null
+++ b/src/s-usg5-2-2.h
@@ -0,0 +1,186 @@
+/* Definitions file for GNU Emacs running on AT&T's System V Release 2.2
+ Copyright (C) 1985, 1986 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/*
+ * Define symbols to identify the version of Unix this is.
+ * Define all the symbols that apply correctly.
+ */
+
+#define USG /* System III, System V, etc */
+
+#define USG5
+
+/* SYSTEM_TYPE should indicate the kind of system you are using.
+ It sets the Lisp variable system-type. */
+
+#define SYSTEM_TYPE "usg-unix-v"
+
+/* nomultiplejobs should be defined if your system's shell
+ does not have "job control" (the ability to stop a program,
+ run some other program, then continue the first one). */
+
+#define NOMULTIPLEJOBS
+
+/* Default is to set interrupt_input to 0: don't do input buffering within Emacs */
+
+/* #define INTERRUPT_INPUT */
+
+/* Letter to use in finding device name of first pty,
+ if system supports pty's. 'p' means it is /dev/ptyp0 */
+
+#define FIRST_PTY_LETTER 'p'
+
+/*
+ * Define HAVE_TERMIO if the system provides sysV-style ioctls
+ * for terminal control.
+ */
+
+#define HAVE_TERMIO
+
+/*
+ * Define HAVE_TIMEVAL if the system supports the BSD style clock values.
+ * Look in <sys/time.h> for a timeval structure.
+ */
+
+/* #define HAVE_TIMEVAL */
+
+/*
+ * Define HAVE_SELECT if the system supports the `select' system call.
+ */
+
+/* #define HAVE_SELECT */
+
+/*
+ * Define HAVE_PTYS if the system supports pty devices.
+ */
+
+/* #define HAVE_PTYS */
+
+/* Define HAVE_SOCKETS if system supports 4.2-compatible sockets. */
+
+/* #define HAVE_SOCKETS */
+
+/*
+ * Define NONSYSTEM_DIR_LIBRARY to make Emacs emulate
+ * The 4.2 opendir, etc., library functions.
+ */
+
+#define NONSYSTEM_DIR_LIBRARY
+
+/* Define this symbol if your system has the functions bcopy, etc. */
+
+/* #define BSTRING */
+
+/* subprocesses should be defined if you want to
+ have code for asynchronous subprocesses
+ (as used in M-x compile and M-x shell).
+ This is supposed to work now on system V release 2. */
+
+#define subprocesses
+
+/* If your system uses COFF (Common Object File Format) then define the
+ preprocessor symbol "COFF". */
+
+#define COFF
+
+/* define MAIL_USE_FLOCK if the mailer uses flock
+ to interlock access to /usr/spool/mail/$USER.
+ The alternative is that a lock file named
+ /usr/spool/mail/$USER.lock. */
+
+/* #define MAIL_USE_FLOCK */
+
+/* Define CLASH_DETECTION if you want lock files to be written
+ so that Emacs can tell instantly when you try to modify
+ a file that someone else has modified in his Emacs. */
+
+/* #define CLASH_DETECTION */
+
+/* Define SHORTNAMES if the C compiler can distinguish only
+ short names. It means that the stuff in ../shortnames
+ must be run to convert the long names to short ones. */
+
+/* #define SHORTNAMES */
+
+/* We use the Berkeley (and usg5.2.2) interface to nlist. */
+
+#define NLIST_STRUCT
+
+/* The file containing the kernel's symbol table is called /unix. */
+
+#define KERNEL_FILE "/unix"
+
+/* The symbol in the kernel where the load average is found
+ is named avenrun. */
+
+#define LDAV_SYMBOL "avenrun"
+
+/* Special hacks needed to make Emacs run on this system. */
+
+/*
+ * Make the sigsetmask function go away. Don't know what the
+ * ramifications of this are, but doesn't seem possible to
+ * emulate it properly anyway at this point.
+ */
+
+#define sigsetmask(mask) /* Null expansion */
+
+/* setjmp and longjmp can safely replace _setjmp and _longjmp,
+ but they will run slower. */
+
+#define _setjmp setjmp
+#define _longjmp longjmp
+
+/* On USG systems the system calls are interruptable by signals
+ that the user program has elected to catch. Thus the system call
+ must be retried in these cases. To handle this without massive
+ changes in the source code, we remap the standard system call names
+ to names for our own functions in sysdep.c that do the system call
+ with retries. */
+
+#define read sys_read
+#define open sys_open
+#define write sys_write
+
+#define INTERRUPTABLE_OPEN
+#define INTERRUPTABLE_IO
+
+/* On USG systems these have different names */
+
+#define index strchr
+#define rindex strrchr
+
+/* USG systems tend to put everything declared static
+ into the initialized data area, which becomes pure after dumping Emacs.
+ Foil this. Emacs carefully avoids static vars inside functions. */
+
+#define static
+
+/* Compiler bug bites on many systems when default ADDR_CORRECT is used. */
+
+#define ADDR_CORRECT(x) (x)
+
+/* Prevent -lg from being used for debugging. Not implemented? */
+
+#define LIBS_DEBUG
+
+/* Use terminfo instead of termcap. */
+
+#define TERMINFO
diff --git a/src/s-usg5-2.h b/src/s-usg5-2.h
new file mode 100644
index 00000000000..6cffc5ed1ce
--- /dev/null
+++ b/src/s-usg5-2.h
@@ -0,0 +1,186 @@
+/* Definitions file for GNU Emacs running on AT&T's System V Release 2.0
+ Copyright (C) 1985, 1986 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/*
+ * Define symbols to identify the version of Unix this is.
+ * Define all the symbols that apply correctly.
+ */
+
+#define USG /* System III, System V, etc */
+
+#define USG5
+
+/* SYSTEM_TYPE should indicate the kind of system you are using.
+ It sets the Lisp variable system-type. */
+
+#define SYSTEM_TYPE "usg-unix-v"
+
+/* nomultiplejobs should be defined if your system's shell
+ does not have "job control" (the ability to stop a program,
+ run some other program, then continue the first one). */
+
+#define NOMULTIPLEJOBS
+
+/* Default is to set interrupt_input to 0: don't do input buffering within Emacs */
+
+/* #define INTERRUPT_INPUT */
+
+/* Letter to use in finding device name of first pty,
+ if system supports pty's. 'p' means it is /dev/ptyp0 */
+
+#define FIRST_PTY_LETTER 'p'
+
+/*
+ * Define HAVE_TERMIO if the system provides sysV-style ioctls
+ * for terminal control.
+ */
+
+#define HAVE_TERMIO
+
+/*
+ * Define HAVE_TIMEVAL if the system supports the BSD style clock values.
+ * Look in <sys/time.h> for a timeval structure.
+ */
+
+/* #define HAVE_TIMEVAL */
+
+/*
+ * Define HAVE_SELECT if the system supports the `select' system call.
+ */
+
+/* #define HAVE_SELECT */
+
+/*
+ * Define HAVE_PTYS if the system supports pty devices.
+ */
+
+/* #define HAVE_PTYS */
+
+/* Define HAVE_SOCKETS if system supports 4.2-compatible sockets. */
+
+/* #define HAVE_SOCKETS */
+
+/*
+ * Define NONSYSTEM_DIR_LIBRARY to make Emacs emulate
+ * The 4.2 opendir, etc., library functions.
+ */
+
+#define NONSYSTEM_DIR_LIBRARY
+
+/* Define this symbol if your system has the functions bcopy, etc. */
+
+/* #define BSTRING */
+
+/* subprocesses should be defined if you want to
+ have code for asynchronous subprocesses
+ (as used in M-x compile and M-x shell).
+ This is supposed to work now on system V release 2. */
+
+#define subprocesses
+
+/* If your system uses COFF (Common Object File Format) then define the
+ preprocessor symbol "COFF". */
+
+#define COFF
+
+/* define MAIL_USE_FLOCK if the mailer uses flock
+ to interlock access to /usr/spool/mail/$USER.
+ The alternative is that a lock file named
+ /usr/spool/mail/$USER.lock. */
+
+/* #define MAIL_USE_FLOCK */
+
+/* Define CLASH_DETECTION if you want lock files to be written
+ so that Emacs can tell instantly when you try to modify
+ a file that someone else has modified in his Emacs. */
+
+/* #define CLASH_DETECTION */
+
+/* Define SHORTNAMES if the C compiler can distinguish only
+ short names. It means that the stuff in ../shortnames
+ must be run to convert the long names to short ones. */
+
+/* #define SHORTNAMES */
+
+/* We do NOT use the Berkeley (and usg5.2.2) interface to nlist. */
+
+/* #define NLIST_STRUCT */
+
+/* The file containing the kernel's symbol table is called /unix. */
+
+#define KERNEL_FILE "/unix"
+
+/* The symbol in the kernel where the load average is found
+ is named avenrun. */
+
+#define LDAV_SYMBOL "avenrun"
+
+/* Special hacks needed to make Emacs run on this system. */
+
+/*
+ * Make the sigsetmask function go away. Don't know what the
+ * ramifications of this are, but doesn't seem possible to
+ * emulate it properly anyway at this point.
+ */
+
+#define sigsetmask(mask) /* Null expansion */
+
+/* setjmp and longjmp can safely replace _setjmp and _longjmp,
+ but they will run slower. */
+
+#define _setjmp setjmp
+#define _longjmp longjmp
+
+/* On USG systems the system calls are interruptable by signals
+ that the user program has elected to catch. Thus the system call
+ must be retried in these cases. To handle this without massive
+ changes in the source code, we remap the standard system call names
+ to names for our own functions in sysdep.c that do the system call
+ with retries. */
+
+#define read sys_read
+#define open sys_open
+#define write sys_write
+
+#define INTERRUPTABLE_OPEN
+#define INTERRUPTABLE_IO
+
+/* On USG systems these have different names */
+
+#define index strchr
+#define rindex strrchr
+
+/* USG systems tend to put everything declared static
+ into the initialized data area, which becomes pure after dumping Emacs.
+ Foil this. Emacs carefully avoids static vars inside functions. */
+
+#define static
+
+/* Compiler bug bites on many systems when default ADDR_CORRECT is used. */
+
+#define ADDR_CORRECT(x) (x)
+
+/* Prevent -lg from being used for debugging. Not implemented? */
+
+#define LIBS_DEBUG
+
+/* Use terminfo instead of termcap. */
+
+#define TERMINFO
diff --git a/src/s-usg5-3.h b/src/s-usg5-3.h
new file mode 100644
index 00000000000..2af396bd44a
--- /dev/null
+++ b/src/s-usg5-3.h
@@ -0,0 +1,220 @@
+/* Definitions file for GNU Emacs running on AT&T's System V Release 3
+ Copyright (C) 1987 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/*
+ * Define symbols to identify the version of Unix this is.
+ * Define all the symbols that apply correctly.
+ */
+
+#define USG /* System III, System V, etc */
+
+#define USG5
+
+#define USG5_3
+
+/* SYSTEM_TYPE should indicate the kind of system you are using.
+ It sets the Lisp variable system-type. */
+
+#define SYSTEM_TYPE "usg-unix-v"
+
+/* nomultiplejobs should be defined if your system's shell
+ does not have "job control" (the ability to stop a program,
+ run some other program, then continue the first one). */
+
+#define NOMULTIPLEJOBS
+
+/* Default is to set interrupt_input to 0: don't do input buffering within Emacs */
+
+/* #define INTERRUPT_INPUT */
+
+/* Letter to use in finding device name of first pty,
+ if system supports pty's. 'p' means it is /dev/ptyp0 */
+
+#define FIRST_PTY_LETTER 'p'
+
+/*
+ * Define HAVE_TERMIO if the system provides sysV-style ioctls
+ * for terminal control.
+ */
+
+#define HAVE_TERMIO
+
+/*
+ * Define HAVE_TIMEVAL if the system supports the BSD style clock values.
+ * Look in <sys/time.h> for a timeval structure.
+ */
+
+/* #define HAVE_TIMEVAL */
+
+/*
+ * Define HAVE_SELECT if the system supports the `select' system call.
+ */
+
+/* #define HAVE_SELECT */
+
+/*
+ * Define HAVE_PTYS if the system supports pty devices.
+ */
+
+/* Some versions of V.3 have this, but not all.
+ #define HAVE_PTYS
+ #define SYSV_PTYS */
+
+/* Define HAVE_SOCKETS if system supports 4.2-compatible sockets. */
+
+/* #define HAVE_SOCKETS */
+
+/*
+ * Define NONSYSTEM_DIR_LIBRARY to make Emacs emulate
+ * The 4.2 opendir, etc., library functions.
+ */
+
+/* #define NONSYSTEM_DIR_LIBRARY */
+
+/*
+ * Define SYSV_SYSTEM_DIR to use the V.3 getdents/readir
+ * library functions. Almost, but not quite the same as
+ * the 4.2 functions
+ */
+#define SYSV_SYSTEM_DIR
+
+/* Define this symbol if your system has the functions bcopy, etc. */
+
+/* #define BSTRING */
+
+/* subprocesses should be defined if you want to
+ have code for asynchronous subprocesses
+ (as used in M-x compile and M-x shell).
+ This is supposed to work now on system V release 2. */
+
+#define subprocesses
+
+/* If your system uses COFF (Common Object File Format) then define the
+ preprocessor symbol "COFF". */
+
+#define COFF
+
+/* define MAIL_USE_FLOCK if the mailer uses flock
+ to interlock access to /usr/spool/mail/$USER.
+ The alternative is that a lock file named
+ /usr/spool/mail/$USER.lock. */
+
+/* #define MAIL_USE_FLOCK */
+
+/* Define CLASH_DETECTION if you want lock files to be written
+ so that Emacs can tell instantly when you try to modify
+ a file that someone else has modified in his Emacs. */
+
+/* #define CLASH_DETECTION */
+
+/* Define SHORTNAMES if the C compiler can distinguish only
+ short names. It means that the stuff in ../shortnames
+ must be run to convert the long names to short ones. */
+
+/* #define SHORTNAMES */
+
+/* We use the Berkeley (and usg5.2.2) interface to nlist. */
+
+#define NLIST_STRUCT
+
+/* The file containing the kernel's symbol table is called /unix. */
+
+#define KERNEL_FILE "/unix"
+
+/* The symbol in the kernel where the load average is found
+ is named avenrun. */
+
+#define LDAV_SYMBOL "avenrun"
+
+/* Define this if system V IPC is available. */
+
+#define HAVE_SYSVIPC
+
+/* Special hacks needed to make Emacs run on this system. */
+
+/*
+ * Make the sigsetmask function go away. Don't know what the
+ * ramifications of this are, but doesn't seem possible to
+ * emulate it properly anyway at this point.
+ */
+
+#define sigsetmask(mask) /* Null expansion */
+
+/* setjmp and longjmp can safely replace _setjmp and _longjmp,
+ but they will run slower. */
+
+#define _setjmp setjmp
+#define _longjmp longjmp
+
+/* On USG systems the system calls are interruptable by signals
+ that the user program has elected to catch. Thus the system call
+ must be retried in these cases. To handle this without massive
+ changes in the source code, we remap the standard system call names
+ to names for our own functions in sysdep.c that do the system call
+ with retries. */
+
+#define read sys_read
+#define write sys_write
+#define open sys_open
+#define close sys_close
+
+#define INTERRUPTABLE_OPEN
+#define INTERRUPTABLE_CLOSE
+#define INTERRUPTABLE_IO
+
+/* On USG systems these have different names */
+
+#define index strchr
+#define rindex strrchr
+
+/* USG systems tend to put everything declared static
+ into the initialized data area, which becomes pure after dumping Emacs.
+ Foil this. Emacs carefully avoids static vars inside functions. */
+
+#define static
+
+/* Compiler bug bites on many systems when default ADDR_CORRECT is used. */
+
+#define ADDR_CORRECT(x) (x)
+
+/* Prevent -lg from being used for debugging. Not implemented? */
+
+#define LIBS_DEBUG
+
+/* Use terminfo instead of termcap. */
+
+#define TERMINFO
+
+/* Some variants have TIOCGETC, but the structures to go with it
+ are not declared. */
+
+#define BROKEN_TIOCGETC
+
+/* X needs to talk on the network, so search the network library. */
+
+#define LIBX10_SYSTEM -lnsl_s
+#define LIBX11_SYSTEM -lnsl_s
+/* eric@snark.thyrsus.com suggests the following is needed on version V.3.2.
+ Please tell rms@gnu.ai.mit.edu if you find that it is necessary. */
+/* #define LIBX11_SYSTEM -lX11_s -lnls -lnsl_s -lpt -lc_s */
+
+/* The docs for system V/386 suggest v.3 has sigpause,
+ so let's give it a try. */
+#define HAVE_SYSV_SIGPAUSE
diff --git a/src/s-usg5-4.h b/src/s-usg5-4.h
new file mode 100644
index 00000000000..f958e93fe41
--- /dev/null
+++ b/src/s-usg5-4.h
@@ -0,0 +1,171 @@
+/* Definitions file for GNU Emacs running on AT&T's System V Release 4
+ Copyright (C) 1987, 1990 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* This file written by James Van Artsdalen of Dell Computer Corporation.
+ * james@bigtex.cactus.org.
+ */
+
+/* Use the SysVr3 file for at least base configuration. */
+
+#include "s-usg5-3.h"
+
+#define USG5_4
+
+/* We do have multiple jobs. Handle ^Z. */
+
+#undef NOMULTIPLEJOBS
+
+#define LIBS_SYSTEM -lsocket -lnsl -lelf
+#define ORDINARY_LINK
+
+#if 0 /* These should be unnecessary now because of ORDINARY_LINK. */
+#define START_FILES pre-crt0.o /usr/ccs/lib/crt1.o /usr/ccs/lib/crti.o /usr/ccs/lib/values-Xt.o
+#define LIB_STANDARD -lc /usr/ucblib/libucb.a /usr/ccs/lib/crtn.o
+#endif
+
+/* No <sioctl.h> */
+
+#define NO_SIOCTL_H
+
+/* Undump with ELF */
+
+#undef COFF
+
+#define UNEXEC unexelf.o
+
+/* Get FIONREAD from <sys/filio.h>. Get <sys/ttold.h> to get struct
+ * tchars. But get <termio.h> first to make sure ttold.h doesn't
+ * interfere. And don't try to use SIGIO yet.
+ */
+
+#ifdef emacs
+#include <sys/filio.h>
+#include <termio.h>
+#include <sys/ttold.h>
+#include <signal.h>
+#include <sys/wait.h>
+#include <sys/stream.h>
+#include <sys/stropts.h>
+#include <sys/termios.h>
+#undef SIGIO
+#endif
+
+/* libc has this stuff, but not utimes. */
+
+#define HAVE_RENAME
+#define HAVE_SELECT
+#define HAVE_TIMEVAL
+#define HAVE_CLOSEDIR
+#define HAVE_GETTIMEOFDAY
+#define HAVE_DUP2
+
+#define USE_UTIME
+
+/* <sys/stat.h> *defines* stat(2) as a static function. If "static"
+ * is blank, then many files will have a public definition for stat(2).
+ */
+
+#undef static
+
+/* We need bss_end from emacs.c for undumping */
+
+#ifndef USG_SHARED_LIBRARIES
+#define USG_SHARED_LIBRARIES
+#endif
+
+/* We can support this */
+
+#define CLASH_DETECTION
+
+#define HAVE_PTYS
+#define HAVE_SETSID
+#define HAVE_TCATTR
+
+/* It is possible to receive SIGCHLD when there are no children
+ waiting, because a previous waitsys(2) cleaned up the carcass of child
+ without clearing the SIGCHLD pending info. So, use a non-blocking
+ wait3 instead, which maps to waitpid(2) in SysVr4. */
+
+#define HAVE_WAIT_HEADER
+#define WAITTYPE int
+#define wait3(status, options, rusage) \
+ waitpid((pid_t) -1, (status), (options))
+#define WRETCODE(w) (w >> 8)
+
+/* TIOCGPGRP is broken in SysVr4, so we can't send signals to PTY
+ subprocesses the usual way. But TIOCSIGNAL does work for PTYs, and
+ this is all we need. */
+
+#define TIOCSIGSEND TIOCSIGNAL
+
+/* This change means that we don't loop through allocate_pty too many
+ times in the (rare) event of a failure. */
+
+#undef FIRST_PTY_LETTER
+#define FIRST_PTY_LETTER 'z'
+
+/* This sets the name of the master side of the PTY. */
+
+#define PTY_NAME_SPRINTF strcpy (pty_name, "/dev/ptmx");
+
+/* This sets the name of the slave side of the PTY. On SysVr4,
+ grantpt(3) forks a subprocess, so keep sigchld_handler() from
+ intercepting that death. If any child but grantpt's should die
+ within, it should be caught after sigrelse(2). */
+
+#define PTY_TTY_NAME_SPRINTF \
+ { \
+ char *ptsname(), *ptyname; \
+ \
+ sighold(SIGCLD); \
+ if (grantpt(fd) == -1) \
+ fatal("could not grant slave pty"); \
+ sigrelse(SIGCLD); \
+ if (unlockpt(fd) == -1) \
+ fatal("could not unlock slave pty"); \
+ if (!(ptyname = ptsname(fd))) \
+ fatal ("could not enable slave pty"); \
+ strncpy(pty_name, ptyname, sizeof(pty_name)); \
+ pty_name[sizeof(pty_name) - 1] = 0; \
+ }
+
+/* Push various streams modules onto a PTY channel. */
+
+#define SETUP_SLAVE_PTY \
+ if (ioctl (xforkin, I_PUSH, "ptem") == -1) \
+ fatal ("ioctl I_PUSH ptem", errno); \
+ if (ioctl (xforkin, I_PUSH, "ldterm") == -1) \
+ fatal ("ioctl I_PUSH ldterm", errno); \
+ if (ioctl (xforkin, I_PUSH, "ttcompat") == -1) \
+ fatal ("ioctl I_PUSH ttcompat", errno);
+
+/* The definition of this in s-usg5-3.h is not needed in 5.4. */
+/* liblnsl_s should never be used. The _s suffix implies a shared
+ library, as opposed to a DLL. Share libraries were used in SVR3, and are
+ available only in order to allow SVR3 binaries to run. They should not be
+ linked in to new binaries. -- caraway!pinkas@caraway.intel.com. */
+#undef LIBX10_SYSTEM
+#undef LIBX11_SYSTEM
+
+/* Tell x11term.c and keyboard.c we have the system V streams feature. */
+#define SYSV_STREAMS
+
+/* This definition was suggested for next release.
+ So give it a try. */
+#define HAVE_SOCKETS
diff --git a/src/s-vms.h b/src/s-vms.h
new file mode 100644
index 00000000000..f9cf2e2fc9a
--- /dev/null
+++ b/src/s-vms.h
@@ -0,0 +1,251 @@
+/* s-header for VMS. Do not use this directly!
+ Use s-vms4-4.h (or s-vms4-0.h or s-vms4-2.h).
+ Copyright (C) 1986 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ * Define symbols to identify the version of Unix this is.
+ * Define all the symbols that apply correctly.
+ */
+
+#ifndef VMS /* Decus cpp doesn't define this but VAX C does */
+#define VMS
+#endif /* VMS */
+/* Note that this file is used indirectly via s-vms4-0.h, or some other
+ such file. These other files define a symbol VMS4_0, VMS4_2, etc. */
+
+/* SYSTEM_TYPE should indicate the kind of system you are using.
+ It sets the Lisp variable system-type. */
+
+#define SYSTEM_TYPE "vax-vms"
+
+/* NOMULTIPLEJOBS should be defined if your system's shell
+ does not have "job control" (the ability to stop a program,
+ run some other program, then continue the first one). */
+
+/* #define NOMULTIPLEJOBS */
+
+/* INTERRUPT_INPUT controls a default for Unix systems.
+ VMS uses a separate mechanism. */
+
+/* #define INTERRUPT_INPUT */
+
+/* Letter to use in finding device name of first pty,
+ if system supports pty's. 'a' means it is /dev/ptya0 */
+
+#define FIRST_PTY_LETTER 'a'
+
+/*
+ * Define HAVE_TIMEVAL if the system supports the BSD style clock values.
+ * Look in <sys/time.h> for a timeval structure.
+ */
+
+/* #define HAVE_TIMEVAL */
+
+/*
+ * Define HAVE_SELECT if the system supports the `select' system call.
+ */
+
+/* #define HAVE_SELECT */
+
+/*
+ * Define HAVE_PTYS if the system supports pty devices.
+ */
+
+/* #define HAVE_PTYS */
+
+/* Define HAVE_SOCKETS if system supports 4.2-compatible sockets. */
+
+/* #define HAVE_SOCKETS */
+
+/*
+ * Define NONSYSTEM_DIR_LIBRARY to make Emacs emulate
+ * The 4.2 opendir, etc., library functions.
+ */
+
+#define NONSYSTEM_DIR_LIBRARY
+
+/* Define this symbol if your system has the functions bcopy, etc. */
+
+/* #define BSTRING */
+
+/* subprocesses should be defined if you want to
+ have code for asynchronous subprocesses
+ (as used in M-x compile and M-x shell).
+ This is generally OS dependent, and not supported
+ under most USG systems. */
+
+/* #define subprocesses */
+
+/* If your system uses COFF (Common Object File Format) then define the
+ preprocessor symbol "COFF". */
+
+/* #define COFF */
+
+/* define MAIL_USE_FLOCK if the mailer uses flock
+ to interlock access to /usr/spool/mail/$USER.
+ The alternative is that a lock file named
+ /usr/spool/mail/$USER.lock. */
+
+/* #define MAIL_USE_FLOCK */
+
+/* Define CLASH_DETECTION if you want lock files to be written
+ so that Emacs can tell instantly when you try to modify
+ a file that someone else has modified in his Emacs. */
+
+/* #define CLASH_DETECTION */
+
+/* Define the maximum record length for print strings, if needed. */
+
+#define MAX_PRINT_CHARS 300
+
+
+/* Here, on a separate page, add any special hacks needed
+ to make Emacs work on this system. For example,
+ you might define certain system call names that don't
+ exist on your system, or that do different things on
+ your system and must be used only through an encapsulation
+ (Which you should place, by convention, in sysdep.c). */
+
+/* Do you have the shareable library bug? If you link with a shareable
+ library that contains psects with the NOSHR attribute and also refer to
+ those psects in your program, the linker give you a private version of
+ the psect which is not related to the version used by the shareable
+ library. The end result is that your references to variables in that
+ psect have absolutely nothing to do with library references to what is
+ supposed to be the same variable. If you intend to link with the standard
+ C library (NOT the shareable one) you don't need to define this. (This
+ is NOT fixed in V4.4...) */
+
+#define SHAREABLE_LIB_BUG
+
+/* Partially due to the above mentioned bug and also so that we don't need
+ to require that people have a shareable C library, the default for Emacs
+ is to link with the non-shared library. If you want to link with the
+ shared library, define this and remake xmakefile and fileio.c. This allows
+ us to ship a guaranteed executable image. */
+
+#define LINK_CRTL_SHARE
+
+/* Define this if you want to read the file SYS$SYSTEM:SYSUAF.DAT for user
+ information. If you do use this, you must either make SYSUAF.DAT world
+ readable or install Emacs with SYSPRV. */
+
+/* #define READ_SYSUAF */
+
+/* On VMS these have a different name */
+
+#define index strchr
+#define rindex strrchr
+#define unlink delete
+
+/* On later versions of VMS these exist in the C run time library, but
+ we are using our own implementations. Hide their names to avoid
+ linker errors */
+#define rename sys_rename
+#define execvp sys_execvp
+#define system sys_system
+
+/* Hide these names so that we don't get linker errors */
+#define malloc sys_malloc
+#define free sys_free
+#define cfree sys_cfree
+#define realloc sys_realloc
+#define calloc sys_calloc
+
+/* Don't use the standard brk and sbrk */
+#define sbrk sys_sbrk
+#define brk sys_brk
+
+/* On VMS we want to avoid reading and writing very large amounts of
+ data at once, so we redefine read and write here. */
+
+#define read sys_read
+#define write sys_write
+
+/* sys_creat just calls the real creat with additional args of
+ "rfm=var", "rat=cr" to get "normal" VMS files... */
+#define creat sys_creat
+
+/* fwrite forces an RMS PUT on every call. This is abysmally slow, so
+ we emulate fwrite with fputc, which forces buffering and is much
+ faster! */
+#define fwrite sys_fwrite
+
+/* getuid only returns the member number, which is not unique on most VMS
+ systems. We emulate it with (getgid()<<16 | getuid()). */
+#define getuid sys_getuid
+
+#define getppid sys_getppid
+
+/* If user asks for TERM, check first for EMACS_TERM. */
+#define getenv sys_getenv
+
+/* Standard C abort is less useful than it should be. */
+#define abort sys_abort
+
+/* Case conflicts with C library fread. */
+#define Fread F_read
+
+/* Case conflicts with C library srandom. */
+#define Srandom S_random
+
+/* Cause initialization of vmsfns.c to be run. */
+#define SYMS_SYSTEM syms_of_vmsfns ()
+
+/* VAXCRTL access doesn't deal with SYSPRV very well (among other oddites...)
+ Here, we use $CHKPRO to really determine access. */
+#define access sys_access
+
+#define PAGESIZE 512
+
+#define _longjmp longjmp
+#define _setjmp setjmp
+
+#ifdef __GNUC__
+/* GAS uses up 7 of the available 30 characters in an external name
+ to distinguish the case of the letters.
+ So make these lower case, so we have all 30 for distinguishing. */
+#define Vminibuffer_completion_table vminibuffer_completion_table
+#define Qminibuffer_completion_table qminibuffer_completion_table
+#define Vminibuffer_completion_predicate vminibuffer_completion_predicate
+#define Qminibuffer_completion_predicate qminibuffer_completion_predicate
+#define Vminibuffer_completion_confirm vminibuffer_completion_confirm
+#define Qminibuffer_completion_confirm qminibuffer_completion_confirm
+#endif
+
+#ifdef __GNUC__
+extern char sdata[] asm("_$$PsectAttributes_NOOVR$$$D$ATA") ;
+#define DATA_START (((int) sdata + 8191) & ~511)
+#else
+globalref char sdata[];
+#define DATA_START (((int) sdata + 511) & ~511)
+#endif
+#define TEXT_START 512
+
+/* Baud-rate values from tty status are not standard. */
+
+#define BAUD_CONVERT \
+{ 0, 50, 75, 110, 134, 150, 300, 600, 1200, 1800, \
+ 2000, 2400, 3600, 4800, 7200, 9600, 19200 }
+
+#define PURESIZE 132000
+
+/* Stdio FILE type has extra indirect on VMS, so must alter this macro. */
+
+#define PENDING_OUTPUT_COUNT(FILE) ((*(FILE))->_ptr - (*(FILE))->_base)
diff --git a/src/s-vms4-0.h b/src/s-vms4-0.h
new file mode 100644
index 00000000000..d07878f3cc3
--- /dev/null
+++ b/src/s-vms4-0.h
@@ -0,0 +1,2 @@
+#include "s-vms.h"
+#define VMS4_0
diff --git a/src/s-vms4-2.h b/src/s-vms4-2.h
new file mode 100644
index 00000000000..7955c048d9f
--- /dev/null
+++ b/src/s-vms4-2.h
@@ -0,0 +1,3 @@
+#include "s-vms.h"
+#define VMS4_2
+
diff --git a/src/s-vms4-4.h b/src/s-vms4-4.h
new file mode 100644
index 00000000000..1cf8ea3576e
--- /dev/null
+++ b/src/s-vms4-4.h
@@ -0,0 +1,3 @@
+#include "s-vms.h"
+#define VMS4_4
+
diff --git a/src/s-vms5-5.h b/src/s-vms5-5.h
new file mode 100644
index 00000000000..cda1b306dca
--- /dev/null
+++ b/src/s-vms5-5.h
@@ -0,0 +1,8 @@
+#include "s-vms.h"
+#define VMS5_5
+#define VMS4_4
+
+/* The bug that SHAREABLE_LIB_BUG fixes is gone in version 5.5 of VMS.
+ And defining it causes lossage because sys_errlist has a different
+ number of elements. */
+#undef SHAREABLE_LIB_BUG
diff --git a/src/s-xenix.h b/src/s-xenix.h
new file mode 100644
index 00000000000..828ddf1342e
--- /dev/null
+++ b/src/s-xenix.h
@@ -0,0 +1,233 @@
+/* Definitions file for GNU Emacs running SCO Xenix 386 Release 2.2
+ Copyright (C) 1988 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ * Define symbols to identify the version of Unix this is.
+ * Define all the symbols that apply correctly.
+ */
+
+/* #define UNIPLUS */
+#define XENIX
+#define USG5
+#define USG
+/* #define HPUX */
+/* #define UMAX */
+/* #define BSD4_1 */
+/* #define BSD4_2 */
+/* #define BSD4_3 */
+/* #define BSD */
+/* #define VMS */
+
+/* SYSTEM_TYPE should indicate the kind of system you are using.
+ It sets the Lisp variable system-type. */
+
+#define SYSTEM_TYPE "xenix"
+
+/* NOMULTIPLEJOBS should be defined if your system's shell
+ does not have "job control" (the ability to stop a program,
+ run some other program, then continue the first one). */
+
+#define NOMULTIPLEJOBS
+
+/* Emacs can read input using SIGIO and buffering characters itself,
+ or using CBREAK mode and making C-g cause SIGINT.
+ The choice is controlled by the variable interrupt_input.
+ Define INTERRUPT_INPUT to make interrupt_input = 1 the default (use SIGIO)
+
+ SIGIO can be used only on systems that implement it (4.2 and 4.3).
+ CBREAK mode has two disadvatages
+ 1) At least in 4.2, it is impossible to handle the Meta key properly.
+ I hear that in system V this problem does not exist.
+ 2) Control-G causes output to be discarded.
+ I do not know whether this can be fixed in system V.
+
+ Another method of doing input is planned but not implemented.
+ It would have Emacs fork off a separate process
+ to read the input and send it to the true Emacs process
+ through a pipe.
+*/
+
+/* #define INTERRUPT_INPUT */
+
+/* Letter to use in finding device name of first pty,
+ if system supports pty's. 'p' means it is /dev/ptyp0 */
+
+/* #define FIRST_PTY_LETTER 'p' */
+
+/*
+ * Define HAVE_TERMIO if the system provides sysV-style ioctls
+ * for terminal control.
+ */
+
+#define HAVE_TERMIO
+
+/*
+ * Define HAVE_TIMEVAL if the system supports the BSD style clock values.
+ * Look in <sys/time.h> for a timeval structure.
+ */
+
+/* #define HAVE_TIMEVAL */
+
+/*
+ * Define HAVE_SELECT if the system supports the `select' system call.
+ */
+
+/* #define HAVE_SELECT */
+
+/*
+ * Define HAVE_PTYS if the system supports pty devices.
+ */
+
+/* #define HAVE_PTYS */
+
+/* Define HAVE_SOCKETS if system supports 4.2-compatible sockets. */
+
+/* #define HAVE_SOCKETS */
+
+/*
+ * Define NONSYSTEM_DIR_LIBRARY to make Emacs emulate
+ * The 4.2 opendir, etc., library functions.
+ */
+
+#define NONSYSTEM_DIR_LIBRARY
+
+/* Define this symbol if your system has the functions bcopy, etc. */
+
+/* #define BSTRING */
+
+/* subprocesses should be defined if you want to
+ have code for asynchronous subprocesses
+ (as used in M-x compile and M-x shell).
+ This is supposed to work now on system V release 2. */
+
+#define subprocesses
+
+/* If your system uses COFF (Common Object File Format) then define the
+ preprocessor symbol "COFF". */
+
+/* #define COFF */
+
+/* Xenix requires completely different unexec code
+ which lives in a separate file. Specify the file name. */
+
+#define UNEXEC unexenix.o
+
+/* define MAIL_USE_FLOCK if the mailer uses flock
+ to interlock access to /usr/spool/mail/$USER.
+ The alternative is that a lock file named
+ /usr/spool/mail/$USER.lock. */
+
+#define MAIL_USE_FLOCK
+
+/* Define CLASH_DETECTION if you want lock files to be written
+ so that Emacs can tell instantly when you try to modify
+ a file that someone else has modified in his Emacs. */
+
+/* The way this is implemented requires long filenames... */
+/* #define CLASH_DETECTION */
+
+/* Define SHORTNAMES if the C compiler can distinguish only
+ short names. It means that the stuff in ../shortnames
+ must be run to convert the long names to short ones. */
+
+/* #define SHORTNAMES */
+
+/* We do not use the Berkeley (and usg5.2.2) interface to nlist. */
+
+/* #define NLIST_STRUCT */
+
+/* Compensate for one incompatibility between Xenix and V.0. */
+#define n_zeroes n_name[0]
+
+/* The file containing the kernel's symbol table is called /xenix. */
+
+#define KERNEL_FILE "/xenix"
+
+/* The symbol in the kernel where the load average is found
+ is named avenrun. */
+
+#define LDAV_SYMBOL "_avenrun"
+
+/* Special hacks needed to make Emacs run on this system. */
+
+/*
+ * Make the sigsetmask function go away. Don't know what the
+ * ramifications of this are, but doesn't seem possible to
+ * emulate it properly anyway at this point.
+ */
+
+#define sigsetmask(mask) /* Null expansion */
+
+/* setjmp and longjmp can safely replace _setjmp and _longjmp,
+ but they will run slower. */
+
+#define _setjmp setjmp
+#define _longjmp longjmp
+
+/* On USG systems the system calls are interruptable by signals
+ that the user program has elected to catch. Thus the system call
+ must be retried in these cases. To handle this without massive
+ changes in the source code, we remap the standard system call names
+ to names for our own functions in sysdep.c that do the system call
+ with retries. */
+
+#define read sys_read
+#define open sys_open
+#define write sys_write
+
+#define INTERRUPTABLE_OPEN
+#define INTERRUPTABLE_IO
+
+/* On USG systems these have different names */
+
+#define index strchr
+#define rindex strrchr
+
+/* Compiler bug bites on many systems when default ADDR_CORRECT is used. */
+
+#define ADDR_CORRECT(x) (x)
+
+/* Prevent -lg from being used for debugging. Not implemented? */
+
+#define LIBS_DEBUG
+
+/* Switches for linking temacs. */
+
+#define LD_SWITCH_SYSTEM -i
+
+/* Xenix implements sysV style IPC. */
+
+#define HAVE_SYSVIPC
+
+/* Use terminfo instead of termcap. */
+
+/* Tell Emacs to use Terminfo. */
+
+#define TERMINFO
+
+/* Tell Xenix curses to BE Terminfo. */
+#define M_TERMINFO
+
+/* Control program name for etc/fakemail to run. */
+
+#ifdef SMAIL
+#define MAIL_PROGRAM_NAME "/usr/bin/smail -q0"
+#else
+#define MAIL_PROGRAM_NAME "/usr/lib/mail/execmail"
+#endif
diff --git a/src/scroll.c b/src/scroll.c
index df40d33c5e5..9e776f91c55 100644
--- a/src/scroll.c
+++ b/src/scroll.c
@@ -1,4 +1,4 @@
-/* Calculate what line insertion or deletion to do, and do it,
+/* Calculate what ins/del line to do, and do it, for Emacs redisplay.
Copyright (C) 1985, 1986, 1990 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -18,34 +18,26 @@ along with GNU Emacs; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+#include <stdio.h>
#include "config.h"
#include "termchar.h"
-#include "lisp.h"
+#include "termhooks.h"
#include "dispextern.h"
-#include "screen.h"
-
-extern struct display_line **ophys_lines;
#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
-/* All costs measured in characters.
- So no cost can exceed the area of a screen, measured in characters.
- Let's hope this is never more than 15000 characters. */
-
-#define INFINITY 15000
-
struct matrix_elt
{
/* Cost of outputting through this line
if no insert/delete is done just above it. */
- short writecost;
+ int writecost;
/* Cost of outputting through this line
if an insert is done just above it. */
- short insertcost;
+ int insertcost;
/* Cost of outputting through this line
if a delete is done just above it. */
- short deletecost;
+ int deletecost;
/* Number of inserts so far in this run of inserts,
for the cost in insertcost. */
char insertcount;
@@ -54,15 +46,32 @@ struct matrix_elt
char deletecount;
};
-/* See do_line_insertion_deletion_costs for info on these arrays. */
+/* This exceeds the sum of any reasonable number of INFINITY's. */
+#define SUPER_INFINITY (1000 * INFINITY)
-#ifndef MULTI_SCREEN
-static int *insert_line_cost;
-static int *delete_line_cost;
-static int *insert_n_lines_cost;
-static int *delete_n_lines_cost;
-#endif
+/* See CalcIDCosts for on the arrays below */
+int *ILcost;
+int *DLcost;
+int *ILncost;
+int *DLncost;
+
+scrolling_1 (window_size, unchanged_at_top, unchanged_at_bottom,
+ draw_cost, old_hash, new_hash, free_at_end)
+ int window_size, unchanged_at_top, unchanged_at_bottom;
+ int *draw_cost;
+ int *old_hash;
+ int *new_hash;
+ int free_at_end;
+{
+ struct matrix_elt *matrix;
+ matrix = ((struct matrix_elt *)
+ alloca ((window_size + 1) * (window_size + 1) * sizeof *matrix));
+ calculate_scrolling (matrix, window_size, unchanged_at_bottom,
+ draw_cost, old_hash, new_hash,
+ free_at_end);
+ do_scrolling (matrix, window_size, unchanged_at_top);
+}
/* Determine, in matrix[i,j], the cost of updating the first j old lines
into the first i new lines.
@@ -81,11 +90,9 @@ static int *delete_n_lines_cost;
to the place at which the first mismatch between old and
new contents appears. */
-static void
-calculate_scrolling (screen, matrix, window_size, lines_below,
+calculate_scrolling (matrix, window_size, lines_below,
draw_cost, old_hash, new_hash,
free_at_end)
- SCREEN_PTR screen;
/* matrix is of size window_size + 1 on each side. */
struct matrix_elt *matrix;
int window_size;
@@ -95,32 +102,21 @@ calculate_scrolling (screen, matrix, window_size, lines_below,
int free_at_end;
{
register int i, j;
- int screen_height = SCREEN_HEIGHT (screen);
register struct matrix_elt *p, *p1;
register int cost, cost1;
int lines_moved = window_size + (scroll_region_ok ? 0 : lines_below);
- /* first_insert_cost[I] is the cost of doing the first insert-line
- at the I'th line of the lines we are considering,
- where I is origin 1 (as it is below). */
- int *first_insert_cost
- = &SCREEN_INSERT_COST (screen)[screen_height - 1 - lines_moved];
- int *first_delete_cost
- = &SCREEN_DELETE_COST (screen)[screen_height - 1 - lines_moved];
- int *next_insert_cost
- = &SCREEN_INSERTN_COST (screen)[screen_height - 1 - lines_moved];
- int *next_delete_cost
- = &SCREEN_DELETEN_COST (screen)[screen_height - 1 - lines_moved];
-
- /* Discourage long scrolls on fast lines.
- Don't scroll nearly a full screen height unless it saves
- at least 1/4 second. */
- int extra_cost = baud_rate / (10 * 4 * SCREEN_HEIGHT (screen));
+ /* We subtract 1 to compensate for the fact that i and j have values
+ starting with 1. */
+ int *first_insert_cost = &ILcost[screen_height - lines_moved - 1];
+ int *first_delete_cost = &DLcost[screen_height - lines_moved - 1];
+ int *next_insert_cost = &ILncost[screen_height - lines_moved - 1];
+ int *next_delete_cost = &DLncost[screen_height - lines_moved - 1];
/* initialize the top left corner of the matrix */
matrix->writecost = 0;
- matrix->insertcost = INFINITY;
- matrix->deletecost = INFINITY;
+ matrix->insertcost = SUPER_INFINITY;
+ matrix->deletecost = SUPER_INFINITY;
matrix->insertcount = 0;
matrix->deletecount = 0;
@@ -129,10 +125,10 @@ calculate_scrolling (screen, matrix, window_size, lines_below,
for (i = 1; i <= window_size; i++)
{
p = matrix + i * (window_size + 1);
- cost += draw_cost[i] + next_insert_cost[i] + extra_cost;
+ cost += draw_cost[i] + next_insert_cost[i];
p->insertcost = cost;
- p->writecost = INFINITY;
- p->deletecost = INFINITY;
+ p->writecost = SUPER_INFINITY;
+ p->deletecost = SUPER_INFINITY;
p->insertcount = i;
p->deletecount = 0;
}
@@ -143,8 +139,8 @@ calculate_scrolling (screen, matrix, window_size, lines_below,
{
cost += next_delete_cost[j];
matrix[j].deletecost = cost;
- matrix[j].writecost = INFINITY;
- matrix[j].insertcost = INFINITY;
+ matrix[j].writecost = SUPER_INFINITY;
+ matrix[j].insertcost = SUPER_INFINITY;
matrix[j].deletecount = j;
matrix[j].insertcount = 0;
}
@@ -195,7 +191,7 @@ calculate_scrolling (screen, matrix, window_size, lines_below,
abort ();
cost1 = p1->insertcost + next_insert_cost[i - p1->insertcount];
}
- p->insertcost = min (cost, cost1) + draw_cost[i] + extra_cost;
+ p->insertcost = min (cost, cost1) + draw_cost[i];
p->insertcount = (cost < cost1) ? 1 : p1->insertcount + 1;
if (p->insertcount > i)
abort ();
@@ -225,19 +221,15 @@ calculate_scrolling (screen, matrix, window_size, lines_below,
/* Perform insert-lines and delete-lines operations
according to the costs in the matrix.
- Updates the contents of the screen to record what was done. */
+ Updates the contents of current_screen to record what was done. */
-static void
-do_scrolling (screen, matrix, window_size, unchanged_at_top)
- SCREEN_PTR screen;
+do_scrolling (matrix, window_size, unchanged_at_top)
struct matrix_elt *matrix;
int window_size;
int unchanged_at_top;
{
register struct matrix_elt *p;
register int i, j;
- register struct screen_glyphs *current_screen;
- register struct screen_glyphs *temp_screen;
struct queue { int count, pos; } *queue;
int offset = unchanged_at_top;
int qi = 0;
@@ -245,39 +237,18 @@ do_scrolling (screen, matrix, window_size, unchanged_at_top)
register int tem;
int next;
- queue = (struct queue *) alloca (SCREEN_HEIGHT (screen)
- * sizeof (struct queue));
-
- current_screen = SCREEN_CURRENT_GLYPHS (screen);
- temp_screen = SCREEN_TEMP_GLYPHS (screen);
+ queue = (struct queue *) alloca (screen_height * sizeof (struct queue));
- bcopy (current_screen->glyphs, temp_screen->glyphs,
- current_screen->height * sizeof (GLYPH *));
+ bcopy (current_screen->contents, temp_screen->contents,
+ current_screen->height * sizeof (char *));
bcopy (current_screen->used, temp_screen->used,
current_screen->height * sizeof (int));
bcopy (current_screen->highlight, temp_screen->highlight,
- current_screen->height * sizeof (char));
- bzero (temp_screen->enable, temp_screen->height * sizeof (char));
- bcopy (current_screen->bufp, temp_screen->bufp,
- current_screen->height * sizeof (int));
+ current_screen->height);
+ bzero (temp_screen->enable, temp_screen->height);
-#ifdef HAVE_X_WINDOWS
- if (SCREEN_IS_X (screen))
- {
- bcopy (current_screen->nruns, temp_screen->nruns,
- current_screen->height * sizeof (int));
- bcopy (current_screen->face_list, temp_screen->face_list,
- current_screen->height * sizeof (struct run *));
- bcopy (current_screen->top_left_x, temp_screen->top_left_x,
- current_screen->height * sizeof (short));
- bcopy (current_screen->top_left_y, temp_screen->top_left_y,
- current_screen->height * sizeof (short));
- bcopy (current_screen->pix_width, temp_screen->pix_width,
- current_screen->height * sizeof (short));
- bcopy (current_screen->pix_height, temp_screen->pix_height,
- current_screen->height * sizeof (short));
- }
-#endif
+/* First do all deletions of lines; queue up insertions.
+ Also move lines to correct slots in current_screen. */
i = j = window_size;
@@ -308,8 +279,8 @@ do_scrolling (screen, matrix, window_size, unchanged_at_top)
{
/* Best thing done here is no insert or delete */
/* Old line at vpos j-1 ends up at vpos i-1 */
- current_screen->glyphs[i + offset - 1]
- = temp_screen->glyphs[j + offset - 1];
+ current_screen->contents[i + offset - 1]
+ = temp_screen->contents[j + offset - 1];
current_screen->used[i + offset - 1]
= temp_screen->used[j + offset - 1];
current_screen->highlight[i + offset - 1]
@@ -333,18 +304,16 @@ do_scrolling (screen, matrix, window_size, unchanged_at_top)
for (i = qi - 1; i >= 0; i--)
{
ins_del_lines (queue[i].pos, queue[i].count);
-
/* Mark the inserted lines as clear,
and put into them the line-contents strings
that were discarded during the deletions.
Those are the ones for which temp_screen->enable was not set. */
tem = queue[i].pos;
- for (j = tem + queue[i].count - 1; j > tem; j--)
+ for (j = tem + queue[i].count - 1; j >= tem; j--)
{
current_screen->enable[j] = 0;
- while (temp_screen->enable[next])
- next++;
- current_screen->glyphs[j] = temp_screen->glyphs[next++];
+ while (temp_screen->enable[next]) next++;
+ current_screen->contents[j] = temp_screen->contents[next++];
}
}
@@ -352,30 +321,10 @@ do_scrolling (screen, matrix, window_size, unchanged_at_top)
set_terminal_window (0);
}
-void
-scrolling_1 (screen, window_size, unchanged_at_top, unchanged_at_bottom,
- draw_cost, old_hash, new_hash, free_at_end)
- SCREEN_PTR screen;
- int window_size, unchanged_at_top, unchanged_at_bottom;
- int *draw_cost;
- int *old_hash;
- int *new_hash;
- int free_at_end;
-{
- struct matrix_elt *matrix;
- matrix = ((struct matrix_elt *)
- alloca ((window_size + 1) * (window_size + 1) * sizeof *matrix));
-
- calculate_scrolling (screen, matrix, window_size, unchanged_at_bottom,
- draw_cost, old_hash, new_hash,
- free_at_end);
- do_scrolling (screen, matrix, window_size, unchanged_at_top);
-}
-
-/* Return number of lines in common between current and desired screen contents
- described to us only as vectors of hash codes OLDHASH and NEWHASH.
- Consider only vpos range START to END (not including END).
- Ignore short lines on the assumption that
+/* Return number of lines in common between current screen contents
+ and the text to be displayed,
+ considering only vpos range START to END (not including END).
+ Ignores short lines (length < 20) on the assumption that
avoiding redrawing such a line will have little weight. */
int
@@ -386,27 +335,13 @@ scrolling_max_lines_saved (start, end, oldhash, newhash, cost)
struct { int hash; int count; } lines[01000];
register int i, h;
register int matchcount = 0;
- int avg_length = 0;
- int threshold;
-
- /* Compute a threshold which is 1/4 of average length of these lines. */
-
- for (i = start; i < end; i++)
- avg_length += cost[i];
-
- avg_length /= end - start;
- threshold = avg_length / 4;
bzero (lines, sizeof lines);
- /* Put new lines' hash codes in hash table.
- Ignore lines shorter than the threshold.
- Thus, if the lines that are in common
- are mainly the ones that are short,
- they won't count. */
+ /* Put new lines' hash codes in hash table. */
for (i = start; i < end; i++)
{
- if (cost[i] > threshold)
+ if (cost[i] > 20)
{
h = newhash[i] & 0777;
lines[h].hash = newhash[i];
@@ -437,20 +372,14 @@ scrolling_max_lines_saved (start, end, oldhash, newhash, cost)
These are the same arguments that might be given to
scroll_screen_lines to perform this scrolling. */
-scroll_cost (screen, from, to, amount)
- SCREEN_PTR screen;
+scroll_cost (from, to, amount)
int from, to, amount;
{
/* Compute how many lines, at bottom of screen,
will not be involved in actual motion. */
- int limit = to;
- int offset;
- int height = SCREEN_HEIGHT (screen);
-
- if (amount > 0)
- limit += amount;
- if (! scroll_region_ok)
- limit = height;
+ int ok_below = screen_height - to;
+ if (amount > 0) ok_below -= amount;
+ if (! scroll_region_ok) ok_below = 0;
if (amount == 0)
return 0;
@@ -463,71 +392,14 @@ scroll_cost (screen, from, to, amount)
amount = - amount;
}
- offset = height - limit;
+ from += ok_below;
+ to += ok_below;
- return
- (SCREEN_INSERT_COST (screen)[offset + from]
- + (amount - 1) * SCREEN_INSERTN_COST (screen)[offset + from]
- + SCREEN_DELETEN_COST (screen)[offset + to]
- + (amount - 1) * SCREEN_DELETE_COST (screen)[offset + to]);
+ return (ILcost[from] + (amount - 1) * ILncost[from]
+ + DLcost[to] + (amount - 1) * DLncost[to]);
}
-/* Calculate the line insertion/deletion
- overhead and multiply factor values */
-
-static void
-line_ins_del (screen, ov1, pf1, ovn, pfn, ov, mf)
- SCREEN_PTR screen;
- int ov1, ovn;
- int pf1, pfn;
- register int *ov, *mf;
-{
- register int i;
- register int screen_height = SCREEN_HEIGHT (screen);
- register int insert_overhead = ov1 * 10;
- register int next_insert_cost = ovn * 10;
-
- for (i = 0; i <= screen_height; i++)
- {
- mf[screen_height - i] = next_insert_cost / 10;
- next_insert_cost += pfn;
- ov[screen_height - i] = (insert_overhead + next_insert_cost) / 10;
- insert_overhead += pf1;
- }
-}
-
-static void
-ins_del_costs (screen,
- one_line_string, multi_string,
- setup_string, cleanup_string,
- costvec, ncostvec, coefficient)
- SCREEN_PTR screen;
- char *one_line_string, *multi_string;
- char *setup_string, *cleanup_string;
- int *costvec, *ncostvec;
- int coefficient;
-{
- if (multi_string)
- line_ins_del (screen,
- string_cost (multi_string) * coefficient,
- per_line_cost (multi_string) * coefficient,
- 0, 0, costvec, ncostvec);
- else if (one_line_string)
- line_ins_del (screen,
- string_cost (setup_string) + string_cost (cleanup_string), 0,
- string_cost (one_line_string),
- per_line_cost (one_line_string),
- costvec, ncostvec);
- else
- line_ins_del (screen,
- 9999, 0, 9999, 0,
- costvec, ncostvec);
-}
-
/* Calculate the insert and delete line costs.
- Note that this is done even when running with a window system
- because we want to know how long scrolling takes (and avoid it).
- This must be redone whenever the screen height changes.
We keep the ID costs in a precomputed array based on the position
at which the I or D is performed. Also, there are two kinds of ID
@@ -545,62 +417,91 @@ ins_del_costs (screen,
The first bracketed expression above is the overhead; the second is
the multiply factor. Both are dependent only on the position at
- which the insert is performed. We store the overhead in
- SCREEN_INSERT_COST (screen) and the multiply factor in
- SCREEN_INSERTN_COST (screen). Note however that any insertion
+ which the insert is performed. We store the overhead in ILcost and
+ the multiply factor in ILncost. Note however that any insertion
must include at least one multiply factor. Rather than compute this
- as SCREEN_INSERT_COST (screen)[line]+SCREEN_INSERTN_COST (screen)[line],
- we add SCREEN_INSERTN_COST (screen) into SCREEN_INSERT_COST (screen).
- This is reasonable because of the particular algorithm used in calcM.
+ as ILcost[line]+ILncost[line], we add ILncost into ILcost. This is
+ reasonable because of the particular algorithm used in calcM.
Deletion is essentially the same as insertion.
*/
-do_line_insertion_deletion_costs (screen,
- ins_line_string, multi_ins_string,
- del_line_string, multi_del_string,
- setup_string, cleanup_string, coefficient)
- SCREEN_PTR screen;
+CalcIDCosts (ins_line_string, multi_ins_string,
+ del_line_string, multi_del_string,
+ setup_string, cleanup_string)
char *ins_line_string, *multi_ins_string;
char *del_line_string, *multi_del_string;
char *setup_string, *cleanup_string;
- int coefficient;
{
- if (SCREEN_INSERT_COST (screen) != 0)
+ /* Discourage long scrolls slightly on fast lines.
+ This says that scrolling nearly the full length of the screen
+ is not worth it if reprinting takes less than 1/4 second. */
+ int extra = baud_rate / (10 * 4 * screen_height);
+
+ if (ILcost != 0)
{
- SCREEN_INSERT_COST (screen)
- = (int *) xrealloc (SCREEN_INSERT_COST (screen),
- SCREEN_HEIGHT (screen) * sizeof (int));
- SCREEN_DELETEN_COST (screen)
- = (int *) xrealloc (SCREEN_DELETEN_COST (screen),
- SCREEN_HEIGHT (screen) * sizeof (int));
- SCREEN_INSERTN_COST (screen)
- = (int *) xrealloc (SCREEN_INSERTN_COST (screen),
- SCREEN_HEIGHT (screen) * sizeof (int));
- SCREEN_DELETE_COST (screen)
- = (int *) xrealloc (SCREEN_DELETE_COST (screen),
- SCREEN_HEIGHT (screen) * sizeof (int));
+ ILcost = (int *) xrealloc (ILcost, screen_height * sizeof (int));
+ DLcost = (int *) xrealloc (DLcost, screen_height * sizeof (int));
+ ILncost = (int *) xrealloc (ILncost, screen_height * sizeof (int));
+ DLncost = (int *) xrealloc (DLncost, screen_height * sizeof (int));
}
else
{
- SCREEN_INSERT_COST (screen)
- = (int *) xmalloc (SCREEN_HEIGHT (screen) * sizeof (int));
- SCREEN_DELETEN_COST (screen)
- = (int *) xmalloc (SCREEN_HEIGHT (screen) * sizeof (int));
- SCREEN_INSERTN_COST (screen)
- = (int *) xmalloc (SCREEN_HEIGHT (screen) * sizeof (int));
- SCREEN_DELETE_COST (screen)
- = (int *) xmalloc (SCREEN_HEIGHT (screen) * sizeof (int));
+ ILcost = (int *) xmalloc (screen_height * sizeof (int));
+ DLcost = (int *) xmalloc (screen_height * sizeof (int));
+ ILncost = (int *) xmalloc (screen_height * sizeof (int));
+ DLncost = (int *) xmalloc (screen_height * sizeof (int));
}
- ins_del_costs (screen,
- ins_line_string, multi_ins_string,
- setup_string, cleanup_string,
- SCREEN_INSERT_COST (screen), SCREEN_INSERTN_COST (screen),
- coefficient);
- ins_del_costs (screen,
- del_line_string, multi_del_string,
- setup_string, cleanup_string,
- SCREEN_DELETEN_COST (screen), SCREEN_DELETE_COST (screen),
- coefficient);
+ CalcIDCosts1 (ins_line_string, multi_ins_string,
+ setup_string, cleanup_string,
+ ILcost, ILncost, extra);
+ CalcIDCosts1 (del_line_string, multi_del_string,
+ setup_string, cleanup_string,
+ DLcost, DLncost, 0);
+}
+
+CalcIDCosts1 (one_line_string, multi_string,
+ setup_string, cleanup_string,
+ costvec, ncostvec, extra)
+ char *one_line_string, *multi_string;
+ char *setup_string, *cleanup_string;
+ int *costvec, *ncostvec;
+ int extra;
+{
+ if (calculate_costs_hook)
+ (*calculate_costs_hook) (extra, costvec, ncostvec);
+ else if (dont_calculate_costs)
+ CalcLID (0, 0, 0, 0, costvec, ncostvec);
+ else if (multi_string)
+ CalcLID (string_cost (multi_string),
+ per_line_cost (multi_string),
+ extra, 0, costvec, ncostvec);
+ else if (one_line_string)
+ CalcLID (string_cost (setup_string) + string_cost (cleanup_string), 0,
+ string_cost (one_line_string) + extra,
+ per_line_cost (one_line_string),
+ costvec, ncostvec);
+ else
+ CalcLID (9999, 0, 9999, 0,
+ costvec, ncostvec);
+}
+
+/* Calculate the line ID overhead and multiply factor values */
+CalcLID (ov1, pf1, ovn, pfn, ov, mf)
+ int ov1, ovn;
+ int pf1, pfn;
+ register int *ov, *mf;
+{
+ register int i;
+ register int insert_overhead = ov1 * 10 + screen_height * pf1;
+ register int next_insert_cost = ovn * 10 + screen_height * pfn;
+
+ for (i = 0; i < screen_height; i++)
+ {
+ *mf++ = next_insert_cost / 10;
+ next_insert_cost -= pfn;
+ *ov++ = (insert_overhead + next_insert_cost) / 10;
+ insert_overhead -= pf1;
+ }
}
diff --git a/src/search.c b/src/search.c
new file mode 100644
index 00000000000..d128739328e
--- /dev/null
+++ b/src/search.c
@@ -0,0 +1,1329 @@
+/* String search routines for GNU Emacs.
+ Copyright (C) 1985, 1986, 1987 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#include "config.h"
+#include "lisp.h"
+#include "syntax.h"
+#include "buffer.h"
+#include "commands.h"
+#include "regex.h"
+
+#define max(a, b) ((a) > (b) ? (a) : (b))
+#define min(a, b) ((a) < (b) ? (a) : (b))
+
+unsigned char downcase_table[01000] = {0}; /* folds upper to lower case */
+ /* A WHEEL WILL FALL OFF IF, IN A trt, CHARACTER A */
+ /* TRANSLATES INTO CHARACTER B AND CHARACTER B DOES NOT */
+ /* ALSO TRANSLATE INTO CHARACTER B. */
+/* If that constraint is met, compute_trt_inverse will follow a */
+ /* translation table with its inverse. The inverse of a table */
+ /* follows the table at table[0400]. The form of this is that if */
+ /* table[a]=b then the chain starting at table[0400+b], linked by */
+ /* link(x)=table[0400+x] and ended by b must include a. */
+
+/* At present compute_trt_inverse is blinded and the inverse for this */
+ /* particular table is created by a single-purpose loop. */
+ /* compute_trt_inverse has been tested on the following cases: */
+ /* trt[x]=x, trt[x]=(+ 3 (logand x, 0370)), trt[x]='a', and the */
+ /* downcase table. */
+
+/* We compile regexps into this buffer and then use it for searching. */
+
+struct re_pattern_buffer searchbuf;
+
+extern int re_max_failures;
+
+char search_fastmap[0400];
+
+/* Last regexp we compiled */
+
+Lisp_Object last_regexp;
+
+/* Every call to re_match, etc., must pass &search_regs as the regs argument
+ unless you can show it is unnecessary (i.e., if re_match is certainly going
+ to be called again before region-around-match can be called). */
+
+static struct re_registers search_regs;
+
+/* error condition signalled when regexp compile_pattern fails */
+
+Lisp_Object Qinvalid_regexp;
+
+/* Compile a regexp and signal a Lisp error if anything goes wrong. */
+
+compile_pattern (pattern, bufp, translate)
+ Lisp_Object pattern;
+ struct re_pattern_buffer *bufp;
+ char *translate;
+{
+ char *val;
+ Lisp_Object dummy;
+
+ if (EQ (pattern, last_regexp)
+ && translate == bufp->translate)
+ return;
+
+ last_regexp = Qnil;
+ bufp->translate = translate;
+ val = re_compile_pattern (XSTRING (pattern)->data,
+ XSTRING (pattern)->size,
+ bufp);
+ if (val)
+ {
+ dummy = build_string (val);
+ while (1)
+ Fsignal (Qinvalid_regexp, Fcons (dummy, Qnil));
+ }
+ last_regexp = pattern;
+ return;
+}
+
+/* Error condition used for failing searches */
+Lisp_Object Qsearch_failed;
+
+Lisp_Object
+signal_failure (arg)
+ Lisp_Object arg;
+{
+ Fsignal (Qsearch_failed, Fcons (arg, Qnil));
+ return Qnil;
+}
+
+DEFUN ("looking-at", Flooking_at, Slooking_at, 1, 1, 0,
+ "t if text after point matches regular expression PAT.")
+ (string)
+ Lisp_Object string;
+{
+ Lisp_Object val;
+ unsigned char *p1, *p2;
+ int s1, s2;
+ register int i;
+
+ CHECK_STRING (string, 0);
+ compile_pattern (string, &searchbuf,
+ !NULL (current_buffer->case_fold_search) ? (char *) downcase_table : 0);
+
+ immediate_quit = 1;
+ QUIT; /* Do a pending quit right away, to avoid paradoxical behavior */
+
+ /* Get pointers and sizes of the two strings
+ that make up the visible portion of the buffer. */
+
+ p1 = BEGV_ADDR;
+ s1 = GPT - BEGV;
+ p2 = GAP_END_ADDR;
+ s2 = ZV - GPT;
+ if (s1 < 0)
+ {
+ p2 = p1;
+ s2 = ZV - BEGV;
+ s1 = 0;
+ }
+ if (s2 < 0)
+ {
+ s1 = ZV - BEGV;
+ s2 = 0;
+ }
+
+ val = (0 <= re_match_2 (&searchbuf, p1, s1, p2, s2,
+ point - BEGV, &search_regs, ZV - BEGV)
+ ? Qt : Qnil);
+ for (i = 0; i < RE_NREGS; i++)
+ if (search_regs.start[i] >= 0)
+ {
+ search_regs.start[i] += BEGV;
+ search_regs.end[i] += BEGV;
+ }
+ immediate_quit = 0;
+ return val;
+}
+
+DEFUN ("string-match", Fstring_match, Sstring_match, 2, 3, 0,
+ "Return index of start of first match for REGEXP in STRING, or nil.\n\
+If third arg START is non-nil, start search at that index in STRING.\n\
+For index of first char beyond the match, do (match-end 0).\n\
+match-end and match-beginning also give indices of substrings\n\
+matched by parenthesis constructs in the pattern.")
+ (regexp, string, start)
+ Lisp_Object regexp, string, start;
+{
+ int val;
+ int s;
+
+ CHECK_STRING (regexp, 0);
+ CHECK_STRING (string, 1);
+
+ if (NULL (start))
+ s = 0;
+ else
+ {
+ int len = XSTRING (string)->size;
+
+ CHECK_NUMBER (start, 2);
+ s = XINT (start);
+ if (s < 0 && -s <= len)
+ s = len - s;
+ else if (0 > s || s > len)
+ args_out_of_range (string, start);
+ }
+
+ compile_pattern (regexp, &searchbuf,
+ !NULL (current_buffer->case_fold_search) ? (char *) downcase_table : 0);
+ immediate_quit = 1;
+ val = re_search (&searchbuf, XSTRING (string)->data, XSTRING (string)->size,
+ s, XSTRING (string)->size - s, &search_regs);
+ immediate_quit = 0;
+ if (val == -2)
+ error ("Overflow in regular expression matching");
+ if (val < 0) return Qnil;
+ return make_number (val);
+}
+
+scan_buffer (target, pos, cnt, shortage)
+ int *shortage, pos;
+ register int cnt, target;
+{
+ int lim = ((cnt > 0) ? ZV - 1 : BEGV);
+ int direction = ((cnt > 0) ? 1 : -1);
+ register int lim0;
+ unsigned char *base;
+ register unsigned char *cursor, *limit;
+
+ if (shortage != 0)
+ *shortage = 0;
+
+ immediate_quit = 1;
+
+ if (cnt > 0)
+ while (pos != lim + 1)
+ {
+ lim0 = BufferSafeCeiling (pos);
+ lim0 = min (lim, lim0);
+ limit = &FETCH_CHAR (lim0) + 1;
+ base = (cursor = &FETCH_CHAR (pos));
+ while (1)
+ {
+ while (*cursor != target && ++cursor != limit)
+ ;
+ if (cursor != limit)
+ {
+ if (--cnt == 0)
+ {
+ immediate_quit = 0;
+ return (pos + cursor - base + 1);
+ }
+ else
+ if (++cursor == limit)
+ break;
+ }
+ else
+ break;
+ }
+ pos += cursor - base;
+ }
+ else
+ {
+ pos--; /* first character we scan */
+ while (pos > lim - 1)
+ { /* we WILL scan under pos */
+ lim0 = BufferSafeFloor (pos);
+ lim0 = max (lim, lim0);
+ limit = &FETCH_CHAR (lim0) - 1;
+ base = (cursor = &FETCH_CHAR (pos));
+ cursor++;
+ while (1)
+ {
+ while (--cursor != limit && *cursor != target)
+ ;
+ if (cursor != limit)
+ {
+ if (++cnt == 0)
+ {
+ immediate_quit = 0;
+ return (pos + cursor - base + 1);
+ }
+ }
+ else
+ break;
+ }
+ pos += cursor - base;
+ }
+ }
+ immediate_quit = 0;
+ if (shortage != 0)
+ *shortage = cnt * direction;
+ return (pos + ((direction == 1 ? 0 : 1)));
+}
+
+int
+find_next_newline (from, cnt)
+ register int from, cnt;
+{
+ return (scan_buffer ('\n', from, cnt, (int *) 0));
+}
+
+DEFUN ("skip-chars-forward", Fskip_chars_forward, Sskip_chars_forward, 1, 2, 0,
+ "Move point forward, stopping before a char not in CHARS, or at position LIM.\n\
+CHARS is like the inside of a [...] in a regular expression\n\
+except that ] is never special and \\ quotes ^, - or \\.\n\
+Thus, with arg \"a-zA-Z\", this skips letters stopping before first nonletter.\n\
+With arg \"^a-zA-Z\", skips nonletters stopping before first letter.")
+ (string, lim)
+ Lisp_Object string, lim;
+{
+ skip_chars (1, string, lim);
+ return Qnil;
+}
+
+DEFUN ("skip-chars-backward", Fskip_chars_backward, Sskip_chars_backward, 1, 2, 0,
+ "Move point backward, stopping after a char not in CHARS, or at position LIM.\n\
+See skip-chars-forward for details.")
+ (string, lim)
+ Lisp_Object string, lim;
+{
+ skip_chars (0, string, lim);
+ return Qnil;
+}
+
+skip_chars (forwardp, string, lim)
+ int forwardp;
+ Lisp_Object string, lim;
+{
+ register unsigned char *p, *pend;
+ register unsigned char c;
+ unsigned char fastmap[0400];
+ int negate = 0;
+ register int i;
+
+ CHECK_STRING (string, 0);
+
+ if (NULL (lim))
+ XFASTINT (lim) = forwardp ? ZV : BEGV;
+ else
+ CHECK_NUMBER_COERCE_MARKER (lim, 1);
+
+ /* In any case, don't allow scan outside bounds of buffer. */
+ if (XFASTINT (lim) > ZV)
+ XFASTINT (lim) = ZV;
+ if (XFASTINT (lim) < BEGV)
+ XFASTINT (lim) = BEGV;
+
+ p = XSTRING (string)->data;
+ pend = p + XSTRING (string)->size;
+ bzero (fastmap, sizeof fastmap);
+
+ if (p != pend && *p == '^')
+ {
+ negate = 1; p++;
+ }
+
+ /* Find the characters specified and set their elements of fastmap. */
+
+ while (p != pend)
+ {
+ c = *p++;
+ if (c == '\\')
+ {
+ if (p == pend) break;
+ c = *p++;
+ }
+ if (p != pend && *p == '-')
+ {
+ p++;
+ if (p == pend) break;
+ while (c <= *p)
+ {
+ fastmap[c] = 1;
+ c++;
+ }
+ p++;
+ }
+ else
+ fastmap[c] = 1;
+ }
+
+ /* If ^ was the first character, complement the fastmap. */
+
+ if (negate)
+ for (i = 0; i < sizeof fastmap; i++)
+ fastmap[i] ^= 1;
+
+ immediate_quit = 1;
+ if (forwardp)
+ {
+ while (point < XINT (lim) && fastmap[FETCH_CHAR (point)])
+ SET_PT (point + 1);
+ }
+ else
+ {
+ while (point > XINT (lim) && fastmap[FETCH_CHAR (point - 1)])
+ SET_PT (point - 1);
+ }
+ immediate_quit = 0;
+}
+
+/* Subroutines of Lisp buffer search functions. */
+
+static Lisp_Object
+search_command (string, bound, noerror, count, direction, RE)
+ Lisp_Object string, bound, noerror, count;
+ int direction;
+ int RE;
+{
+ register int np;
+ int lim;
+ int n = direction;
+
+ if (!NULL (count))
+ {
+ CHECK_NUMBER (count, 3);
+ n *= XINT (count);
+ }
+
+ CHECK_STRING (string, 0);
+ if (NULL (bound))
+ lim = n > 0 ? ZV : BEGV;
+ else
+ {
+ CHECK_NUMBER_COERCE_MARKER (bound, 1);
+ lim = XINT (bound);
+ if (n > 0 ? lim < point : lim > point)
+ error ("Invalid search bound (wrong side of point)");
+ if (lim > ZV)
+ lim = ZV;
+ if (lim < BEGV)
+ lim = BEGV;
+ }
+
+ np = search_buffer (string, point, lim, n, RE,
+ !NULL (current_buffer->case_fold_search) ? downcase_table : 0);
+ if (np <= 0)
+ {
+ if (NULL (noerror))
+ return signal_failure (string);
+ if (!EQ (noerror, Qt))
+ {
+ if (lim < BEGV || lim > ZV)
+ abort ();
+ SET_PT (lim);
+ }
+ return Qnil;
+ }
+
+ if (np < BEGV || np > ZV)
+ abort ();
+
+ SET_PT (np);
+
+ return Qt;
+}
+
+/* search for the n'th occurrence of `string' in the current buffer,
+ starting at position `from' and stopping at position `lim',
+ treating `pat' as a literal string if `RE' is false or as
+ a regular expression if `RE' is true.
+
+ If `n' is positive, searching is forward and `lim' must be greater than `from'.
+ If `n' is negative, searching is backward and `lim' must be less than `from'.
+
+ Returns -x if only `n'-x occurrences found (x > 0),
+ or else the position at the beginning of the `n'th occurrence (if searching backward)
+ or the end (if searching forward). */
+
+/* INTERFACE CHANGE ALERT!!!! search_buffer now returns -x if only */
+/* n-x occurences are found. */
+
+search_buffer (string, pos, lim, n, RE, trt)
+ Lisp_Object string;
+ int pos;
+ int lim;
+ int n;
+ int RE;
+ register unsigned char *trt;
+{
+ int len = XSTRING (string)->size;
+ unsigned char *base_pat = XSTRING (string)->data;
+ register int *BM_tab;
+ int *BM_tab_base;
+ register int direction = ((n > 0) ? 1 : -1);
+ register int dirlen;
+ int infinity, limit, k, stride_for_teases;
+ register unsigned char *pat, *cursor, *p_limit;
+ register int i, j;
+ unsigned char *p1, *p2;
+ int s1, s2;
+
+
+ if (!len)
+ return (0);
+
+ if (RE)
+ compile_pattern (string, &searchbuf, (char *) trt);
+
+ if (RE /* Here we detect whether the */
+ /* generality of an RE search is */
+ /* really needed. */
+ && *(searchbuf.buffer) == (char) exactn /* first item is "exact match" */
+ && searchbuf.buffer[1] + 2 == searchbuf.used) /*first is ONLY item */
+ {
+ RE = 0; /* can do straight (non RE) search */
+ pat = (base_pat = (unsigned char *) searchbuf.buffer + 2);
+ /* trt already applied */
+ len = searchbuf.used - 2;
+ }
+ else if (!RE)
+ {
+ pat = (unsigned char *) alloca (len);
+
+ for (i = len; i--;) /* Copy the pattern; apply trt */
+ *pat++ = (((int) trt) ? trt [*base_pat++] : *base_pat++);
+ pat -= len; base_pat = pat;
+ }
+
+ if (RE)
+ {
+ immediate_quit = 1; /* Quit immediately if user types ^G,
+ because letting this function finish
+ can take too long. */
+ QUIT; /* Do a pending quit right away,
+ to avoid paradoxical behavior */
+ /* Get pointers and sizes of the two strings
+ that make up the visible portion of the buffer. */
+
+ p1 = BEGV_ADDR;
+ s1 = GPT - BEGV;
+ p2 = GAP_END_ADDR;
+ s2 = ZV - GPT;
+ if (s1 < 0)
+ {
+ p2 = p1;
+ s2 = ZV - BEGV;
+ s1 = 0;
+ }
+ if (s2 < 0)
+ {
+ s1 = ZV - BEGV;
+ s2 = 0;
+ }
+ while (n < 0)
+ {
+ int value = re_search_2 (&searchbuf, p1, s1, p2, s2,
+ pos - BEGV, lim - pos, &search_regs,
+ /* Don't allow match past current point */
+ pos - BEGV);
+ if (value == -2)
+ error ("Overflow in regular expression matching");
+
+ if (value >= 0)
+ {
+ j = BEGV;
+ for (i = 0; i < RE_NREGS; i++)
+ if (search_regs.start[i] >= 0)
+ {
+ search_regs.start[i] += j;
+ search_regs.end[i] += j;
+ }
+ /* Set pos to the new position. */
+ pos = search_regs.start[0];
+ }
+ else
+ {
+ immediate_quit = 0;
+ return (n);
+ }
+ n++;
+ }
+ while (n > 0)
+ {
+ int value = re_search_2 (&searchbuf, p1, s1, p2, s2,
+ pos - BEGV, lim - pos, &search_regs,
+ lim - BEGV);
+ if (value == -2)
+ error ("Overflow in regular expression matching");
+
+ if (value >= 0)
+ {
+ j = BEGV;
+ for (i = 0; i < RE_NREGS; i++)
+ if (search_regs.start[i] >= 0)
+ {
+ search_regs.start[i] += j;
+ search_regs.end[i] += j;
+ }
+ pos = search_regs.end[0];
+ }
+ else
+ {
+ immediate_quit = 0;
+ return (0 - n);
+ }
+ n--;
+ }
+ immediate_quit = 0;
+ return (pos);
+ }
+ else /* non-RE case */
+ {
+#ifdef C_ALLOCA
+ int BM_tab_space[0400];
+ BM_tab = &BM_tab_space[0];
+#else
+ BM_tab = (int *) alloca (0400 * sizeof (int));
+#endif
+ /* The general approach is that we are going to maintain that we know */
+ /* the first (closest to the present position, in whatever direction */
+ /* we're searching) character that could possibly be the last */
+ /* (furthest from present position) character of a valid match. We */
+ /* advance the state of our knowledge by looking at that character */
+ /* and seeing whether it indeed matches the last character of the */
+ /* pattern. If it does, we take a closer look. If it does not, we */
+ /* move our pointer (to putative last characters) as far as is */
+ /* logically possible. This amount of movement, which I call a */
+ /* stride, will be the length of the pattern if the actual character */
+ /* appears nowhere in the pattern, otherwise it will be the distance */
+ /* from the last occurrence of that character to the end of the */
+ /* pattern. */
+ /* As a coding trick, an enormous stride is coded into the table for */
+ /* characters that match the last character. This allows use of only */
+ /* a single test, a test for having gone past the end of the */
+ /* permissible match region, to test for both possible matches (when */
+ /* the stride goes past the end immediately) and failure to */
+ /* match (where you get nudged past the end one stride at a time). */
+
+ /* Here we make a "mickey mouse" BM table. The stride of the search */
+ /* is determined only by the last character of the putative match. */
+ /* If that character does not match, we will stride the proper */
+ /* distance to propose a match that superimposes it on the last */
+ /* instance of a character that matches it (per trt), or misses */
+ /* it entirely if there is none. */
+
+ dirlen = len * direction;
+ infinity = dirlen - (lim + pos + len + len) * direction;
+ if (direction < 0)
+ pat = (base_pat += len - 1);
+ BM_tab_base = BM_tab;
+ BM_tab += 0400;
+ j = dirlen; /* to get it in a register */
+ /* A character that does not appear in the pattern induces a */
+ /* stride equal to the pattern length. */
+ while (BM_tab_base != BM_tab)
+ {
+ *--BM_tab = j;
+ *--BM_tab = j;
+ *--BM_tab = j;
+ *--BM_tab = j;
+ }
+ i = 0;
+ while (i != infinity)
+ {
+ j = pat[i]; i += direction;
+ if (i == dirlen) i = infinity;
+ if ((int) trt)
+ {
+ k = (j = trt[j]);
+ if (i == infinity)
+ stride_for_teases = BM_tab[j];
+ BM_tab[j] = dirlen - i;
+ /* A translation table is followed by its inverse -- see */
+ /* comment following downcase_table for details */
+
+ while ((j = trt[0400+j]) != k)
+ BM_tab[j] = dirlen - i;
+ }
+ else
+ {
+ if (i == infinity)
+ stride_for_teases = BM_tab[j];
+ BM_tab[j] = dirlen - i;
+ }
+ /* stride_for_teases tells how much to stride if we get a */
+ /* match on the far character but are subsequently */
+ /* disappointed, by recording what the stride would have been */
+ /* for that character if the last character had been */
+ /* different. */
+ }
+ infinity = dirlen - infinity;
+ pos += dirlen - ((direction > 0) ? direction : 0);
+ /* loop invariant - pos points at where last char (first char if reverse)
+ of pattern would align in a possible match. */
+ while (n != 0)
+ {
+ if ((lim - pos - (direction > 0)) * direction < 0)
+ return (n * (0 - direction));
+ /* First we do the part we can by pointers (maybe nothing) */
+ QUIT;
+ pat = base_pat;
+ limit = pos - dirlen + direction;
+ limit = ((direction > 0)
+ ? BufferSafeCeiling (limit)
+ : BufferSafeFloor (limit));
+ /* LIMIT is now the last (not beyond-last!) value
+ POS can take on without hitting edge of buffer or the gap. */
+ limit = ((direction > 0)
+ ? min (lim - 1, min (limit, pos + 20000))
+ : max (lim, max (limit, pos - 20000)));
+ if ((limit - pos) * direction > 20)
+ {
+ p_limit = &FETCH_CHAR (limit);
+ p2 = (cursor = &FETCH_CHAR (pos));
+ /* In this loop, pos + cursor - p2 is the surrogate for pos */
+ while (1) /* use one cursor setting as long as i can */
+ {
+ if (direction > 0) /* worth duplicating */
+ {
+ /* Use signed comparison if appropriate
+ to make cursor+infinity sure to be > p_limit.
+ Assuming that the buffer lies in a range of addresses
+ that are all "positive" (as ints) or all "negative",
+ either kind of comparison will work as long
+ as we don't step by infinity. So pick the kind
+ that works when we do step by infinity. */
+ if ((int) (p_limit + infinity) > (int) p_limit)
+ while ((int) cursor <= (int) p_limit)
+ cursor += BM_tab[*cursor];
+ else
+ while ((unsigned int) cursor <= (unsigned int) p_limit)
+ cursor += BM_tab[*cursor];
+ }
+ else
+ {
+ if ((int) (p_limit + infinity) < (int) p_limit)
+ while ((int) cursor >= (int) p_limit)
+ cursor += BM_tab[*cursor];
+ else
+ while ((unsigned int) cursor >= (unsigned int) p_limit)
+ cursor += BM_tab[*cursor];
+ }
+/* If you are here, cursor is beyond the end of the searched region. */
+ /* This can happen if you match on the far character of the pattern, */
+ /* because the "stride" of that character is infinity, a number able */
+ /* to throw you well beyond the end of the search. It can also */
+ /* happen if you fail to match within the permitted region and would */
+ /* otherwise try a character beyond that region */
+ if ((cursor - p_limit) * direction <= len)
+ break; /* a small overrun is genuine */
+ cursor -= infinity; /* large overrun = hit */
+ i = dirlen - direction;
+ if ((int) trt)
+ {
+ while ((i -= direction) + direction != 0)
+ if (pat[i] != trt[*(cursor -= direction)])
+ break;
+ }
+ else
+ {
+ while ((i -= direction) + direction != 0)
+ if (pat[i] != *(cursor -= direction))
+ break;
+ }
+ cursor += dirlen - i - direction; /* fix cursor */
+ if (i + direction == 0)
+ {
+ cursor -= direction;
+ search_regs.start[0]
+ = pos + cursor - p2 + ((direction > 0)
+ ? 1 - len : 0);
+ search_regs.end[0] = len + search_regs.start[0];
+ if ((n -= direction) != 0)
+ cursor += dirlen; /* to resume search */
+ else
+ return ((direction > 0)
+ ? search_regs.end[0] : search_regs.start[0]);
+ }
+ else
+ cursor += stride_for_teases; /* <sigh> we lose - */
+ }
+ pos += cursor - p2;
+ }
+ else
+ /* Now we'll pick up a clump that has to be done the hard */
+ /* way because it covers a discontinuity */
+ {
+ limit = ((direction > 0)
+ ? BufferSafeCeiling (pos - dirlen + 1)
+ : BufferSafeFloor (pos - dirlen - 1));
+ limit = ((direction > 0)
+ ? min (limit + len, lim - 1)
+ : max (limit - len, lim));
+ /* LIMIT is now the last value POS can have
+ and still be valid for a possible match. */
+ while (1)
+ {
+ /* This loop can be coded for space rather than */
+ /* speed because it will usually run only once. */
+ /* (the reach is at most len + 21, and typically */
+ /* does not exceed len) */
+ while ((limit - pos) * direction >= 0)
+ pos += BM_tab[FETCH_CHAR(pos)];
+ /* now run the same tests to distinguish going off the */
+ /* end, a match or a phoney match. */
+ if ((pos - limit) * direction <= len)
+ break; /* ran off the end */
+ /* Found what might be a match.
+ Set POS back to last (first if reverse) char pos. */
+ pos -= infinity;
+ i = dirlen - direction;
+ while ((i -= direction) + direction != 0)
+ {
+ pos -= direction;
+ if (pat[i] != (((int) trt)
+ ? trt[FETCH_CHAR(pos)]
+ : FETCH_CHAR (pos)))
+ break;
+ }
+ /* Above loop has moved POS part or all the way
+ back to the first char pos (last char pos if reverse).
+ Set it once again at the last (first if reverse) char. */
+ pos += dirlen - i- direction;
+ if (i + direction == 0)
+ {
+ pos -= direction;
+ search_regs.start[0]
+ = pos + ((direction > 0) ? 1 - len : 0);
+ search_regs.end[0] = len + search_regs.start[0];
+ if ((n -= direction) != 0)
+ pos += dirlen; /* to resume search */
+ else
+ return ((direction > 0)
+ ? search_regs.end[0] : search_regs.start[0]);
+ }
+ else
+ pos += stride_for_teases;
+ }
+ }
+ /* We have done one clump. Can we continue? */
+ if ((lim - pos) * direction < 0)
+ return ((0 - n) * direction);
+ }
+ return pos;
+ }
+}
+
+/* Given a string of words separated by word delimiters,
+ compute a regexp that matches those exact words
+ separated by arbitrary punctuation. */
+
+static Lisp_Object
+wordify (string)
+ Lisp_Object string;
+{
+ register unsigned char *p, *o;
+ register int i, len, punct_count = 0, word_count = 0;
+ Lisp_Object val;
+
+ CHECK_STRING (string, 0);
+ p = XSTRING (string)->data;
+ len = XSTRING (string)->size;
+
+ for (i = 0; i < len; i++)
+ if (SYNTAX (p[i]) != Sword)
+ {
+ punct_count++;
+ if (i > 0 && SYNTAX (p[i-1]) == Sword) word_count++;
+ }
+ if (SYNTAX (p[len-1]) == Sword) word_count++;
+ if (!word_count) return build_string ("");
+
+ val = make_string (p, len - punct_count + 5 * (word_count - 1) + 4);
+
+ o = XSTRING (val)->data;
+ *o++ = '\\';
+ *o++ = 'b';
+
+ for (i = 0; i < len; i++)
+ if (SYNTAX (p[i]) == Sword)
+ *o++ = p[i];
+ else if (i > 0 && SYNTAX (p[i-1]) == Sword && --word_count)
+ {
+ *o++ = '\\';
+ *o++ = 'W';
+ *o++ = '\\';
+ *o++ = 'W';
+ *o++ = '*';
+ }
+
+ *o++ = '\\';
+ *o++ = 'b';
+
+ return val;
+}
+
+DEFUN ("search-backward", Fsearch_backward, Ssearch_backward, 1, 4,
+ "sSearch backward: ",
+ "Search backward from point for STRING.\n\
+Set point to the beginning of the occurrence found, and return t.\n\
+An optional second argument bounds the search; it is a buffer position.\n\
+The match found must not extend before that position.\n\
+Optional third argument, if t, means if fail just return nil (no error).\n\
+ If not nil and not t, position at limit of search and return nil.\n\
+Optional fourth argument is repeat count--search for successive occurrences.\n\
+See also the functions match-beginning and match-end and replace-match.")
+ (string, bound, noerror, count)
+ Lisp_Object string, bound, noerror, count;
+{
+ return search_command (string, bound, noerror, count, -1, 0);
+}
+
+DEFUN ("search-forward", Fsearch_forward, Ssearch_forward, 1, 4, "sSearch: ",
+ "Search forward from point for STRING.\n\
+Set point to the end of the occurrence found, and return t.\n\
+An optional second argument bounds the search; it is a buffer position.\n\
+The match found must not extend after that position.\n\
+Optional third argument, if t, means if fail just return nil (no error).\n\
+ If not nil and not t, move to limit of search and return nil.\n\
+Optional fourth argument is repeat count--search for successive occurrences.\n\
+See also the functions match-beginning and match-end and replace-match.")
+ (string, bound, noerror, count)
+ Lisp_Object string, bound, noerror, count;
+{
+ return search_command (string, bound, noerror, count, 1, 0);
+}
+
+DEFUN ("word-search-backward", Fword_search_backward, Sword_search_backward, 1, 4,
+ "sWord search backward: ",
+ "Search backward from point for STRING, ignoring differences in punctuation.\n\
+Set point to the beginning of the occurrence found, and return t.\n\
+An optional second argument bounds the search; it is a buffer position.\n\
+The match found must not extend before that position.\n\
+Optional third argument, if t, means if fail just return nil (no error).\n\
+ If not nil and not t, move to limit of search and return nil.\n\
+Optional fourth argument is repeat count--search for successive occurrences.")
+ (string, bound, noerror, count)
+ Lisp_Object string, bound, noerror, count;
+{
+ return search_command (wordify (string), bound, noerror, count, -1, 1);
+}
+
+DEFUN ("word-search-forward", Fword_search_forward, Sword_search_forward, 1, 4,
+ "sWord search: ",
+ "Search forward from point for STRING, ignoring differences in punctuation.\n\
+Set point to the end of the occurrence found, and return t.\n\
+An optional second argument bounds the search; it is a buffer position.\n\
+The match found must not extend after that position.\n\
+Optional third argument, if t, means if fail just return nil (no error).\n\
+ If not nil and not t, move to limit of search and return nil.\n\
+Optional fourth argument is repeat count--search for successive occurrences.")
+ (string, bound, noerror, count)
+ Lisp_Object string, bound, noerror, count;
+{
+ return search_command (wordify (string), bound, noerror, count, 1, 1);
+}
+
+DEFUN ("re-search-backward", Fre_search_backward, Sre_search_backward, 1, 4,
+ "sRE search backward: ",
+ "Search backward from point for match for regular expression REGEXP.\n\
+Set point to the beginning of the match, and return t.\n\
+The match found is the one starting last in the buffer\n\
+and yet ending before the place the origin of the search.\n\
+An optional second argument bounds the search; it is a buffer position.\n\
+The match found must start at or after that position.\n\
+Optional third argument, if t, means if fail just return nil (no error).\n\
+ If not nil and not t, move to limit of search and return nil.\n\
+Optional fourth argument is repeat count--search for successive occurrences.\n\
+See also the functions match-beginning and match-end and replace-match.")
+ (string, bound, noerror, count)
+ Lisp_Object string, bound, noerror, count;
+{
+ return search_command (string, bound, noerror, count, -1, 1);
+}
+
+DEFUN ("re-search-forward", Fre_search_forward, Sre_search_forward, 1, 4,
+ "sRE search: ",
+ "Search forward from point for regular expression REGEXP.\n\
+Set point to the end of the occurrence found, and return t.\n\
+An optional second argument bounds the search; it is a buffer position.\n\
+The match found must not extend after that position.\n\
+Optional third argument, if t, means if fail just return nil (no error).\n\
+ If not nil and not t, move to limit of search and return nil.\n\
+Optional fourth argument is repeat count--search for successive occurrences.\n\
+See also the functions match-beginning and match-end and replace-match.")
+ (string, bound, noerror, count)
+ Lisp_Object string, bound, noerror, count;
+{
+ return search_command (string, bound, noerror, count, 1, 1);
+}
+
+DEFUN ("replace-match", Freplace_match, Sreplace_match, 1, 3, 0,
+ "Replace text matched by last search with NEWTEXT.\n\
+If second arg FIXEDCASE is non-nil, do not alter case of replacement text.\n\
+Otherwise convert to all caps or cap initials, like replaced text.\n\
+If third arg LITERAL is non-nil, insert NEWTEXT literally.\n\
+Otherwise treat \\ as special:\n\
+ \\& in NEWTEXT means substitute original matched text,\n\
+ \\N means substitute match for \\(...\\) number N,\n\
+ \\\\ means insert one \\.\n\
+Leaves point at end of replacement text.")
+ (string, fixedcase, literal)
+ Lisp_Object string, fixedcase, literal;
+{
+ enum { nochange, all_caps, cap_initial } case_action;
+ register int pos, last;
+ int some_multiletter_word;
+ int some_letter = 0;
+ register int c, prevc;
+ int inslen;
+
+ CHECK_STRING (string, 0);
+
+ case_action = nochange; /* We tried an initialization */
+ /* but some C compilers blew it */
+ if (search_regs.start[0] < BEGV
+ || search_regs.start[0] > search_regs.end[0]
+ || search_regs.end[0] > ZV)
+ args_out_of_range(make_number (search_regs.start[0]),
+ make_number (search_regs.end[0]));
+
+ if (NULL (fixedcase))
+ {
+ /* Decide how to casify by examining the matched text. */
+
+ last = search_regs.end[0];
+ prevc = '\n';
+ case_action = all_caps;
+
+ /* some_multiletter_word is set nonzero if any original word
+ is more than one letter long. */
+ some_multiletter_word = 0;
+
+ for (pos = search_regs.start[0]; pos < last; pos++)
+ {
+ c = FETCH_CHAR (pos);
+ if (LOWERCASEP (c))
+ {
+ /* Cannot be all caps if any original char is lower case */
+
+ case_action = cap_initial;
+ if (SYNTAX (prevc) != Sword)
+ {
+ /* Cannot even be cap initials
+ if some original initial is lower case */
+ case_action = nochange;
+ break;
+ }
+ else
+ some_multiletter_word = 1;
+ }
+ else if (!NOCASEP (c))
+ {
+ some_letter = 1;
+ if (!some_multiletter_word && SYNTAX (prevc) == Sword)
+ some_multiletter_word = 1;
+ }
+
+ prevc = c;
+ }
+
+ /* Do not make new text all caps
+ if the original text contained only single letter words. */
+ if (case_action == all_caps && !some_multiletter_word)
+ case_action = cap_initial;
+
+ if (!some_letter) case_action = nochange;
+ }
+
+ SET_PT (search_regs.end[0]);
+ if (!NULL (literal))
+ Finsert (1, &string);
+ else
+ {
+ struct gcpro gcpro1;
+ GCPRO1 (string);
+ for (pos = 0; pos < XSTRING (string)->size; pos++)
+ {
+ c = XSTRING (string)->data[pos];
+ if (c == '\\')
+ {
+ c = XSTRING (string)->data[++pos];
+ if (c == '&')
+ Finsert_buffer_substring (Fcurrent_buffer (),
+ make_number (search_regs.start[0]),
+ make_number (search_regs.end[0]));
+ else if (c >= '1' && c <= RE_NREGS + '0')
+ {
+ if (search_regs.start[c - '0'] >= 1)
+ Finsert_buffer_substring (Fcurrent_buffer (),
+ make_number (search_regs.start[c - '0']),
+ make_number (search_regs.end[c - '0']));
+ }
+ else
+ insert_char (c);
+ }
+ else
+ insert_char (c);
+ }
+ UNGCPRO;
+ }
+
+ inslen = point - (search_regs.end[0]);
+ del_range (search_regs.start[0], search_regs.end[0]);
+
+ if (case_action == all_caps)
+ Fupcase_region (make_number (point - inslen), make_number (point));
+ else if (case_action == cap_initial)
+ upcase_initials_region (make_number (point - inslen), make_number (point));
+ return Qnil;
+}
+
+static Lisp_Object
+match_limit (num, beginningp)
+ Lisp_Object num;
+ int beginningp;
+{
+ register int n;
+
+ CHECK_NUMBER (num, 0);
+ n = XINT (num);
+ if (n < 0 || n >= RE_NREGS)
+ args_out_of_range (num, make_number (RE_NREGS));
+ if (search_regs.start[n] < 0)
+ return Qnil;
+ return (make_number ((beginningp) ? search_regs.start[n]
+ : search_regs.end[n]));
+}
+
+DEFUN ("match-beginning", Fmatch_beginning, Smatch_beginning, 1, 1, 0,
+ "Return the character number of start of text matched by last search.\n\
+ARG, a number, specifies which parenthesized expression in the last regexp.\n\
+ Value is nil if ARGth pair didn't match, or there were less than ARG pairs.\n\
+Zero means the entire text matched by the whole regexp or whole string.")
+ (num)
+ Lisp_Object num;
+{
+ return match_limit (num, 1);
+}
+
+DEFUN ("match-end", Fmatch_end, Smatch_end, 1, 1, 0,
+ "Return the character number of end of text matched by last search.\n\
+ARG, a number, specifies which parenthesized expression in the last regexp.\n\
+ Value is nil if ARGth pair didn't match, or there were less than ARG pairs.\n\
+Zero means the entire text matched by the whole regexp or whole string.")
+ (num)
+ Lisp_Object num;
+{
+ return match_limit (num, 0);
+}
+
+DEFUN ("match-data", Fmatch_data, Smatch_data, 0, 0, 0,
+ "Return list containing all info on what the last search matched.\n\
+Element 2N is (match-beginning N); element 2N + 1 is (match-end N).\n\
+All the elements are normally markers, or nil if the Nth pair didn't match.\n\
+0 is also possible, when matching was done with `string-match',\n\
+if a match began at index 0 in the string.")
+ ()
+{
+ Lisp_Object data[2 * RE_NREGS];
+ int i, len;
+
+ len = -1;
+ for (i = 0; i < RE_NREGS; i++)
+ {
+ int start = search_regs.start[i];
+ if (start >= 0)
+ {
+ /* Use an integer if the value is out of range for the
+ size of the current buffer. */
+ if (start < BEG || start > Z)
+ XFASTINT (data[2 * i]) = start;
+ else
+ {
+ data[2 * i] = Fmake_marker ();
+ Fset_marker (data[2 * i], make_number (start), Qnil);
+ }
+
+ if (search_regs.end[i] < BEG || search_regs.end[i] > Z)
+ XFASTINT (data[2 * i + 1]) = search_regs.end[i];
+ else
+ {
+ data[2 * i + 1] = Fmake_marker ();
+ Fset_marker (data[2 * i + 1],
+ make_number (search_regs.end[i]), Qnil);
+ }
+ len = i;
+ }
+ else
+ data[2 * i] = data [2 * i + 1] = Qnil;
+ }
+ return Flist (2 * len + 2, data);
+}
+
+
+DEFUN ("store-match-data", Fstore_match_data, Sstore_match_data, 1, 1, 0,
+ "Set internal data on last search match from elements of LIST.\n\
+LIST should have been created by calling match-data previously.")
+ (list)
+ register Lisp_Object list;
+{
+ register int i;
+ register Lisp_Object marker;
+
+ if (!CONSP (list) && !NULL (list))
+ list = wrong_type_argument (Qconsp, list, 0);
+
+ for (i = 0; i < RE_NREGS; i++)
+ {
+ marker = Fcar (list);
+ if (NULL (marker))
+ {
+ search_regs.start[i] = -1;
+ list = Fcdr (list);
+ }
+ else
+ {
+ if (XTYPE (marker) == Lisp_Marker
+ && XMARKER (marker)->buffer == 0)
+ XFASTINT (marker) = 0;
+
+ CHECK_NUMBER_COERCE_MARKER (marker, 0);
+ search_regs.start[i] = XINT (marker);
+ list = Fcdr (list);
+
+ marker = Fcar (list);
+ if (XTYPE (marker) == Lisp_Marker
+ && XMARKER (marker)->buffer == 0)
+ XFASTINT (marker) = 0;
+
+ CHECK_NUMBER_COERCE_MARKER (marker, 0);
+ search_regs.end[i] = XINT (marker);
+ }
+ list = Fcdr (list);
+ }
+
+ return Qnil;
+}
+
+/* Quote a string to inactivate reg-expr chars */
+
+DEFUN ("regexp-quote", Fregexp_quote, Sregexp_quote, 1, 1, 0,
+ "Return a regexp string which matches exactly STRING and nothing else.")
+ (str)
+ Lisp_Object str;
+{
+ register unsigned char *in, *out, *end;
+ register unsigned char *temp;
+
+ CHECK_STRING (str, 0);
+
+ temp = (unsigned char *) alloca (XSTRING (str)->size * 2);
+
+ /* Now copy the data into the new string, inserting escapes. */
+
+ in = XSTRING (str)->data;
+ end = in + XSTRING (str)->size;
+ out = temp;
+
+ for (; in != end; in++)
+ {
+ if (*in == '[' || *in == ']'
+ || *in == '*' || *in == '.' || *in == '\\'
+ || *in == '?' || *in == '+'
+ || *in == '^' || *in == '$')
+ *out++ = '\\';
+ *out++ = *in;
+ }
+
+ return make_string (temp, out - temp);
+}
+
+/* This code should be unzapped when there comes to be multiple */
+ /* translation tables. It has been certified on various cases. */
+/*
+void
+compute_trt_inverse (trt)
+ register unsigned char *trt;
+{
+ register int i = 0400;
+ register unsigned char c, q;
+
+ while (i--)
+ trt[0400+i] = i;
+ i = 0400;
+ while (i--)
+ {
+ if ((q = trt[i]) != (unsigned char) i)
+ {
+ c = trt[q + 0400];
+ trt[q + 0400] = i;
+ trt[0400 + i] = c;
+ }
+ }
+}
+*/
+
+syms_of_search ()
+{
+ register int i;
+
+ /* Avoid running out of regexp stack quite so soon. */
+ re_max_failures = 10000;
+
+ for (i = 0; i < 0400; i++)
+ {
+ downcase_table[i] = (i >= 'A' && i <= 'Z') ? i + 040 : i;
+/* We do this instead of using compute_trt_inverse to save space. */
+ /* Does it? */
+ downcase_table[0400+i]
+ = ((i >= 'A' && i <= 'Z')
+ ? i + ('a' - 'A')
+ : ((i >= 'a' && i <= 'z')
+ ? i + ('A' - 'a')
+ : i));
+ }
+/* Use this instead when there come to be multiple translation tables.
+ compute_trt_inverse (downcase_table); */
+
+ searchbuf.allocated = 100;
+ searchbuf.buffer = (char *) malloc (searchbuf.allocated);
+ searchbuf.fastmap = search_fastmap;
+
+ Qsearch_failed = intern ("search-failed");
+ staticpro (&Qsearch_failed);
+ Qinvalid_regexp = intern ("invalid-regexp");
+ staticpro (&Qinvalid_regexp);
+
+ Fput (Qsearch_failed, Qerror_conditions,
+ Fcons (Qsearch_failed, Fcons (Qerror, Qnil)));
+ Fput (Qsearch_failed, Qerror_message,
+ build_string ("Search failed"));
+
+ Fput (Qinvalid_regexp, Qerror_conditions,
+ Fcons (Qinvalid_regexp, Fcons (Qerror, Qnil)));
+ Fput (Qinvalid_regexp, Qerror_message,
+ build_string ("Invalid regexp"));
+
+ last_regexp = Qnil;
+ staticpro (&last_regexp);
+
+ defsubr (&Sstring_match);
+ defsubr (&Slooking_at);
+ defsubr (&Sskip_chars_forward);
+ defsubr (&Sskip_chars_backward);
+ defsubr (&Ssearch_forward);
+ defsubr (&Ssearch_backward);
+ defsubr (&Sword_search_forward);
+ defsubr (&Sword_search_backward);
+ defsubr (&Sre_search_forward);
+ defsubr (&Sre_search_backward);
+ defsubr (&Sreplace_match);
+ defsubr (&Smatch_beginning);
+ defsubr (&Smatch_end);
+ defsubr (&Smatch_data);
+ defsubr (&Sstore_match_data);
+ defsubr (&Sregexp_quote);
+}
diff --git a/src/sink.h b/src/sink.h
new file mode 100644
index 00000000000..ea16fbb3d44
--- /dev/null
+++ b/src/sink.h
@@ -0,0 +1,39 @@
+#define sink_width 48
+#define sink_height 48
+short sink_bits[] = {
+ 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0x9f80, 0xffff, 0xffff,
+ 0x9f9f, 0xffff, 0xffff, 0x8000,
+ 0xffff, 0x7fff, 0xbffe, 0xffff,
+ 0x7fff, 0xa003, 0xffff, 0x7fff,
+ 0xaffd, 0xffff, 0x3fff, 0xaff9,
+ 0xffff, 0xffff, 0xafff, 0xffff,
+ 0xffff, 0xaffc, 0xffff, 0x7fff,
+ 0xaff8, 0xffff, 0xffff, 0xaffc,
+ 0xffff, 0xffff, 0xafff, 0xffff,
+ 0xbfff, 0xaff7, 0xffff, 0x3fff,
+ 0xaff3, 0xffff, 0xffff, 0xaffc,
+ 0x003f, 0x0000, 0x2000, 0x007f,
+ 0x0000, 0xe000, 0xf8df, 0xffff,
+ 0x07ff, 0xf9cf, 0xff0f, 0xe7ff,
+ 0xf9cf, 0xfff7, 0xe7ff, 0xf9ff,
+ 0x63f7, 0xe7fb, 0xf9ff, 0x5a37,
+ 0xe7fb, 0xf9cf, 0x5af7, 0xe7fb,
+ 0xf9cf, 0x5af7, 0xe7f9, 0xf9ef,
+ 0xdb0f, 0xe7fa, 0xf9ff, 0xffff,
+ 0xe7ff, 0xf9df, 0xffff, 0xe7ff,
+ 0x19cf, 0xfffc, 0xe7ff, 0xd9cf,
+ 0xffff, 0xe7ff, 0xd9ff, 0xce47,
+ 0xe673, 0x19ff, 0xb5b6, 0xe7ad,
+ 0xd9cf, 0xb5b7, 0xe67d, 0xd9c7,
+ 0xb5b7, 0xe5ed, 0x19ef, 0x4db4,
+ 0xe673, 0xf1ff, 0xffff, 0xe3ff,
+ 0x03ff, 0x0380, 0xf000, 0x07ef,
+ 0x0100, 0xf800, 0xffc7, 0xf93f,
+ 0xffff, 0xffe7, 0xfd7f, 0xffe0,
+ 0xffff, 0x7d7f, 0xffdf, 0xffff,
+ 0xbd7f, 0xffb1, 0xffff, 0xbb7f,
+ 0xffae, 0xffef, 0xdaff, 0xffae,
+ 0xffc7, 0x66ff, 0xffaf, 0xffe7,
+ 0xbdff, 0xffaf, 0xffff, 0xc3ff,
+ 0xffaf, 0xffff, 0xffff, 0xffaf};
diff --git a/src/sink11.h b/src/sink11.h
new file mode 100644
index 00000000000..57044c91c38
--- /dev/null
+++ b/src/sink11.h
@@ -0,0 +1,51 @@
+#define sink_width 48
+#define sink_height 48
+static unsigned char sink_bits[] = {
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x80, 0x9f,
+ 0xff, 0xff, 0xff, 0xff, 0x9f, 0x9f,
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0x80,
+ 0xff, 0xff, 0xff, 0x7f, 0xfe, 0xbf,
+ 0xff, 0xff, 0xff, 0x7f, 0x03, 0xa0,
+ 0xff, 0xff, 0xff, 0x7f, 0xfd, 0xaf,
+ 0xff, 0xff, 0xff, 0x3f, 0xf9, 0xaf,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xaf,
+ 0xff, 0xff, 0xff, 0xff, 0xfc, 0xaf,
+ 0xff, 0xff, 0xff, 0x7f, 0xf8, 0xaf,
+ 0xff, 0xff, 0xff, 0xff, 0xfc, 0xaf,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xaf,
+ 0xff, 0xff, 0xff, 0xbf, 0xf7, 0xaf,
+ 0xff, 0xff, 0xff, 0x3f, 0xf3, 0xaf,
+ 0xff, 0xff, 0xff, 0xff, 0xfc, 0xaf,
+ 0x3f, 0x00, 0x00, 0x00, 0x00, 0x20,
+ 0x7f, 0x00, 0x00, 0x00, 0x00, 0xe0,
+ 0xdf, 0xf8, 0xff, 0xff, 0xff, 0x07,
+ 0xcf, 0xf9, 0x0f, 0xff, 0xff, 0xe7,
+ 0xcf, 0xf9, 0xf7, 0xff, 0xff, 0xe7,
+ 0xff, 0xf9, 0xf7, 0x63, 0xfb, 0xe7,
+ 0xff, 0xf9, 0x37, 0x5a, 0xfb, 0xe7,
+ 0xcf, 0xf9, 0xf7, 0x5a, 0xfb, 0xe7,
+ 0xcf, 0xf9, 0xf7, 0x5a, 0xf9, 0xe7,
+ 0xef, 0xf9, 0x0f, 0xdb, 0xfa, 0xe7,
+ 0xff, 0xf9, 0xff, 0xff, 0xff, 0xe7,
+ 0xdf, 0xf9, 0xff, 0xff, 0xff, 0xe7,
+ 0xcf, 0x19, 0xfc, 0xff, 0xff, 0xe7,
+ 0xcf, 0xd9, 0xff, 0xff, 0xff, 0xe7,
+ 0xff, 0xd9, 0x47, 0xce, 0x73, 0xe6,
+ 0xff, 0x19, 0xb6, 0xb5, 0xad, 0xe7,
+ 0xcf, 0xd9, 0xb7, 0xb5, 0x7d, 0xe6,
+ 0xc7, 0xd9, 0xb7, 0xb5, 0xed, 0xe5,
+ 0xef, 0x19, 0xb4, 0x4d, 0x73, 0xe6,
+ 0xff, 0xf1, 0xff, 0xff, 0xff, 0xe3,
+ 0xff, 0x03, 0x80, 0x03, 0x00, 0xf0,
+ 0xef, 0x07, 0x00, 0x01, 0x00, 0xf8,
+ 0xc7, 0xff, 0x3f, 0xf9, 0xff, 0xff,
+ 0xe7, 0xff, 0x7f, 0xfd, 0xe0, 0xff,
+ 0xff, 0xff, 0x7f, 0x7d, 0xdf, 0xff,
+ 0xff, 0xff, 0x7f, 0xbd, 0xb1, 0xff,
+ 0xff, 0xff, 0x7f, 0xbb, 0xae, 0xff,
+ 0xef, 0xff, 0xff, 0xda, 0xae, 0xff,
+ 0xc7, 0xff, 0xff, 0x66, 0xaf, 0xff,
+ 0xe7, 0xff, 0xff, 0xbd, 0xaf, 0xff,
+ 0xff, 0xff, 0xff, 0xc3, 0xaf, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xaf, 0xff};
diff --git a/src/sink11mask.h b/src/sink11mask.h
new file mode 100644
index 00000000000..790d8f4a0e2
--- /dev/null
+++ b/src/sink11mask.h
@@ -0,0 +1,51 @@
+#define sink_mask_width 48
+#define sink_mask_height 48
+static unsigned char sink_mask_bits[] = {
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
diff --git a/src/sinkmask.h b/src/sinkmask.h
new file mode 100644
index 00000000000..d086c9249a1
--- /dev/null
+++ b/src/sinkmask.h
@@ -0,0 +1,39 @@
+#define sink_mask_width 48
+#define sink_mask_height 48
+short sink_mask_bits[] = {
+ 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff};
diff --git a/src/sunfns.c b/src/sunfns.c
index 8fcf8bd507e..dc2c69f618e 100644
--- a/src/sunfns.c
+++ b/src/sunfns.c
@@ -15,13 +15,19 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
Author: Jeff Peck, Sun Microsystems, Inc. <peck@sun.com>
+ This file provides selection and menu support in SunView
+ [also a function to change the sunview cursor]
+
Original ideas by David Kastan and Eric Negaard, SRI International
Major help from: Steve Greenbaum, Reasoning Systems, Inc.
<froud@kestrel.arpa>
who first discovered the Menu_Base_Kludge.
+ Modified 12/91 Jeff Peck to compile without sunview libraries:
+ #define NO_SUNVIEW
+ disables SunView support leaving just sit-for-millisecs, sleep-for-millisecs
*/
/*
@@ -32,13 +38,17 @@ who first discovered the Menu_Base_Kludge.
#include <stdio.h>
#include <errno.h>
#include <signal.h>
+
+#ifndef NO_SUNVIEW
#include <sunwindow/window_hs.h>
#include <suntool/selection.h>
#include <suntool/menu.h>
#include <suntool/walkmenu.h>
#include <suntool/frame.h>
#include <suntool/window.h>
+#endif /* NO_SUNVIEW */
+#include <sys/time.h> /* for tv_sec, tv_usec */
#include <fcntl.h>
#undef NULL /* We don't need sunview's idea of NULL */
#include "lisp.h"
@@ -46,6 +56,7 @@ who first discovered the Menu_Base_Kludge.
#include "buffer.h"
#include "termhooks.h"
+#ifndef NO_SUNVIEW
/* conversion to/from character & screen coordinates */
/* From Gosling Emacs SunWindow driver by Chris Torek */
@@ -57,8 +68,10 @@ who first discovered the Menu_Base_Kludge.
#define StoCX(sx) ((sx) / Sun_Font_Xsize)
#define StoCY(sy) ((sy) / Sun_Font_Ysize)
+#endif /* NO_SUNVIEW */
#define CHECK_GFX(x) if((win_fd<0)&&(Fsun_window_init(),(win_fd<0)))return(x)
int win_fd = -1;
+#ifndef NO_SUNVIEW
struct pixfont *Sun_Font; /* The font */
int Sun_Font_Xsize; /* Width of font */
int Sun_Font_Ysize; /* Height of font */
@@ -68,7 +81,7 @@ int Sun_Font_Ysize; /* Height of font */
static Frame Menu_Base_Frame;
static int Menu_Base_fd;
static Lisp_Object sm_kludge_string;
-#endif
+#endif /* Menu_Base_Kludge */
struct cursor CurrentCursor; /* The current cursor */
static short CursorData[16]; /* Build cursor here */
@@ -91,22 +104,30 @@ static short ArrowCursorData[16] = {
0xD800,0x9800,0x0C00,0x0C00,0x0600,0x0600,0x0300,0x0300};
static mpr_static(ArrowCursorMpr, 16, 16, 1, ArrowCursorData);
struct cursor DefaultCursor = {0, 0, PIX_SRC ^ PIX_DST, &ArrowCursorMpr};
-#endif
+#endif /* RIGHT_ARROW_CURSOR */
+#endif /* NO_SUNVIEW */
/*
* Initialize window
*/
DEFUN ("sun-window-init", Fsun_window_init, Ssun_window_init, 0, 1, 0,
+#ifndef NO_SUNVIEW
"One time setup for using Sun Windows with mouse.\n\
Unless optional argument FORCE is non-nil, is a noop after its first call.\n\
Returns a number representing the file descriptor of the open Sun Window,\n\
-or -1 if can not open it.")
+or -1 if can not open it."
+#else
+ "One time setup for using Sun Windows with mouse.\n\
+Unless optional argument FORCE is non-nil, is a noop after its first call.\n\
+Dummy version, compiled with NO_SUNWINDOW, returns -1."
+#endif /* NO_SUNVIEW */
+ )
(force)
Lisp_Object force;
{
char *cp;
static int already_initialized = 0;
-
+#ifndef NO_SUNVIEW
if ((! already_initialized) || (!NULL(force))) {
cp = getenv("WINDOW_GFX");
if (cp != 0) win_fd = open(cp, 2);
@@ -127,9 +148,10 @@ or -1 if can not open it.")
FRAME_NO_CONFIRM, 1,
0);
Menu_Base_fd = (int) window_get(Menu_Base_Frame, WIN_FD);
-#endif
+#endif /* Menu_Base_Kludge */
}
}
+#endif /* NO_SUNVIEW */
return(make_number(win_fd));
}
@@ -137,7 +159,9 @@ or -1 if can not open it.")
* Mouse sit-for (allows a shorter interval than the regular sit-for
* and can be interrupted by the mouse)
*/
-DEFUN ("sit-for-millisecs", Fsit_for_millisecs, Ssit_for_millisecs, 1, 1, 0,
+DEFUN ("sit-for-millisecs",
+ Fsit_for_millisecs,
+ Ssit_for_millisecs, 1, 1, 0,
"Like sit-for, but ARG is milliseconds. \n\
Perform redisplay, then wait for ARG milliseconds or until\n\
input is available. Returns t if wait completed with no input.\n\
@@ -153,7 +177,7 @@ Redisplay does not happen if input is available before it starts.")
Timeout.tv_usec = (XINT(n) - (Timeout.tv_sec * 1000)) * 1000;
if (detect_input_pending()) return(Qnil);
- redisplay_preserve_echo_area ();
+ redisplay ();
/*
* Check for queued keyboard input/mouse hits again
* (A bit screen update can take some time!)
@@ -189,8 +213,8 @@ DEFUN ("update-display", Fupdate_display, Supdate_display, 0, 0, 0,
redisplay_preserve_echo_area ();
return(Qt);
}
-
+#ifndef NO_SUNVIEW
/*
* Change the Sun mouse icon
*/
@@ -451,7 +475,7 @@ as a menu label.")
xpos += XINT (XCONS (Pair)->cdr);
ypos += XINT (XCONS (Pair)->car);
}
-#endif
+#endif /* Menu_Base_Kludge */
button = XINT(Button);
if(button == 4) button = 3;
@@ -472,30 +496,34 @@ as a menu label.")
* Right button gets lost, and event sequencing or delivery gets mixed up
* So, until that gets fixed, we use this <Menu_Base_Frame> kludge:
*/
-#endif
+#endif /* Menu_Base_Kludge */
menu_destroy (menu);
return ((int)Value ? Value : Qnil);
}
-
+#endif /* NO_SUNVIEW */
/*
* Define everything
*/
syms_of_sunfns()
{
+#ifndef NO_SUNVIEW
#ifdef Menu_Base_Kludge
/* i'm just too lazy to re-write this into C code */
/* so we will call this elisp function from C */
sm_kludge_string = make_pure_string ("sm::menu-kludge", 15);
-#endif /* Menu_Base_Kludge */
+#endif /* Menu_Base_Kludge */
+#endif /* NO_SUNVIEW */
defsubr(&Ssun_window_init);
defsubr(&Ssit_for_millisecs);
defsubr(&Ssleep_for_millisecs);
defsubr(&Supdate_display);
+#ifndef NO_SUNVIEW
defsubr(&Ssun_change_cursor_icon);
defsubr(&Ssun_set_selection);
defsubr(&Ssun_get_selection);
defsubr(&Ssun_menu_internal);
+#endif /* NO_SUNVIEW */
}
diff --git a/src/syntax.c b/src/syntax.c
index f90ed5cf8f0..3f71377f56a 100644
--- a/src/syntax.c
+++ b/src/syntax.c
@@ -1,5 +1,5 @@
/* GNU Emacs routines to deal with syntax tables; also word and list parsing.
- Copyright (C) 1985, 1987 Free Software Foundation, Inc.
+ Copyright (C) 1985, 1987, 1990 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -27,8 +27,6 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
Lisp_Object Qsyntax_table_p;
-int words_include_escapes;
-
DEFUN ("syntax-table-p", Fsyntax_table_p, Ssyntax_table_p, 1, 1, 0,
"Return t if ARG is a syntax table.\n\
Any vector of 256 elements will do.")
@@ -139,9 +137,9 @@ char syntax_code_spec[13] =
DEFUN ("char-syntax", Fchar_syntax, Schar_syntax, 1, 1, 0,
"Return the syntax code of CHAR, described by a character.\n\
-For example, if CHAR is a word constituent, the character `?w' is returned.\n\
+For example, if CHAR is a word constituent, ?w is returned.\n\
The characters that correspond to various syntax codes\n\
-are listed in the documentation of `modify-syntax-entry'.")
+are listed in the documentation of modify-syntax-entry.")
(ch)
Lisp_Object ch;
{
@@ -158,25 +156,23 @@ DEFUN ("modify-syntax-entry", foo, bar, 0, 0, 0,
The syntax is changed only for table TABLE, which defaults to\n\
the current buffer's syntax table.\n\
The first character of S should be one of the following:\n\
- Space whitespace syntax. w word constituent.\n\
- _ symbol constituent. . punctuation.\n\
- ( open-parenthesis. ) close-parenthesis.\n\
- \" string quote. \\ character-quote.\n\
- $ paired delimiter. ' expression quote or prefix operator.\n\
- < comment starter. > comment ender.\n\
+ Space or - whitespace syntax. w word constituent.\n\
+ _ symbol constituent. . punctuation.\n\
+ ( open-parenthesis. ) close-parenthesis.\n\
+ \" string quote. \\ escape character.\n\
+ $ paired delimiter. ' expression prefix operator.\n\
+ < comment starter. > comment ender.\n\
+ / character quote.\n\
Only single-character comment start and end sequences are represented thus.\n\
Two-character sequences are represented as described below.\n\
The second character of S is the matching parenthesis,\n\
- used only if the first character is `(' or `)'.\n\
+ used only if the first character is ( or ).\n\
Any additional characters are flags.\n\
-Defined flags are the characters 1, 2, 3, 4, and p.\n\
+Defined flags are the characters 1, 2, 3 and 4.\n\
1 means C is the start of a two-char comment start sequence.\n\
2 means C is the second character of such a sequence.\n\
3 means C is the start of a two-char comment end sequence.\n\
- 4 means C is the second character of such a sequence.\n\
- p means C is a prefix character for `backward-prefix-chars';
- such characters are treated as whitespace when they occur
- between expressions.")
+ 4 means C is the second character of such a sequence.")
*/
@@ -228,10 +224,6 @@ DEFUN ("modify-syntax-entry", Fmodify_syntax_entry, Smodify_syntax_entry, 2, 3,
case '4':
XFASTINT (val) |= 1 << 19;
break;
-
- case 'p':
- XFASTINT (val) |= 1 << 20;
- break;
}
XVECTOR (syntax_table)->contents[0xFF & XINT (c)] = val;
@@ -245,14 +237,14 @@ describe_syntax (value)
Lisp_Object value;
{
register enum syntaxcode code;
- char desc, match, start1, start2, end1, end2, prefix;
+ char desc, match, start1, start2, end1, end2;
char str[2];
Findent_to (make_number (16), make_number (1));
if (XTYPE (value) != Lisp_Int)
{
- insert_string ("invalid");
+ InsStr ("invalid");
return;
}
@@ -262,11 +254,10 @@ describe_syntax (value)
start2 = (XINT (value) >> 17) & 1;
end1 = (XINT (value) >> 18) & 1;
end2 = (XINT (value) >> 19) & 1;
- prefix = (XINT (value) >> 20) & 1;
if ((int) code < 0 || (int) code >= (int) Smax)
{
- insert_string ("invalid");
+ InsStr ("invalid");
return;
}
desc = syntax_code_spec[(int) code];
@@ -288,10 +279,7 @@ describe_syntax (value)
if (end2)
insert ("4", 1);
- if (prefix)
- insert ("p", 1);
-
- insert_string ("\twhich means: ");
+ InsStr ("\twhich means: ");
#ifdef SWITCH_ENUM_BUG
switch ((int) code)
@@ -300,57 +288,55 @@ describe_syntax (value)
#endif
{
case Swhitespace:
- insert_string ("whitespace"); break;
+ InsStr ("whitespace"); break;
case Spunct:
- insert_string ("punctuation"); break;
+ InsStr ("punctuation"); break;
case Sword:
- insert_string ("word"); break;
+ InsStr ("word"); break;
case Ssymbol:
- insert_string ("symbol"); break;
+ InsStr ("symbol"); break;
case Sopen:
- insert_string ("open"); break;
+ InsStr ("open"); break;
case Sclose:
- insert_string ("close"); break;
+ InsStr ("close"); break;
case Squote:
- insert_string ("quote"); break;
+ InsStr ("quote"); break;
case Sstring:
- insert_string ("string"); break;
+ InsStr ("string"); break;
case Smath:
- insert_string ("math"); break;
+ InsStr ("math"); break;
case Sescape:
- insert_string ("escape"); break;
+ InsStr ("escape"); break;
case Scharquote:
- insert_string ("charquote"); break;
+ InsStr ("charquote"); break;
case Scomment:
- insert_string ("comment"); break;
+ InsStr ("comment"); break;
case Sendcomment:
- insert_string ("endcomment"); break;
+ InsStr ("endcomment"); break;
default:
- insert_string ("invalid");
+ InsStr ("invalid");
return;
}
if (match)
{
- insert_string (", matches ");
+ InsStr (", matches ");
str[0] = match, str[1] = 0;
insert (str, 1);
}
if (start1)
- insert_string (",\n\t is the first character of a comment-start sequence");
+ InsStr (",\n\t is the first character of a comment-start sequence");
if (start2)
- insert_string (",\n\t is the second character of a comment-start sequence");
+ InsStr (",\n\t is the second character of a comment-start sequence");
if (end1)
- insert_string (",\n\t is the first character of a comment-end sequence");
+ InsStr (",\n\t is the first character of a comment-end sequence");
if (end2)
- insert_string (",\n\t is the second character of a comment-end sequence");
- if (prefix)
- insert_string (",\n\t is a prefix character for `backward-prefix-chars'");
+ InsStr (",\n\t is the second character of a comment-end sequence");
- insert_string ("\n");
+ InsStr ("\n");
}
Lisp_Object
@@ -359,14 +345,14 @@ describe_syntax_1 (vector)
{
struct buffer *old = current_buffer;
set_buffer_internal (XBUFFER (Vstandard_output));
- describe_vector (vector, Qnil, describe_syntax, 0, Qnil, Qnil);
+ describe_vector (vector, Qnil, describe_syntax, 0, Qnil);
set_buffer_internal (old);
return Qnil;
}
DEFUN ("describe-syntax", Fdescribe_syntax, Sdescribe_syntax, 0, 0, "",
"Describe the syntax specifications in the syntax table.\n\
-The descriptions are inserted in a buffer, which is then displayed.")
+The descriptions are inserted in a buffer, which is selected so you can see it.")
()
{
internal_with_output_to_temp_buffer
@@ -375,16 +361,15 @@ The descriptions are inserted in a buffer, which is then displayed.")
return Qnil;
}
-/* Return the position across COUNT words from FROM.
+/* Return the position across `count' words from `from'.
If that many words cannot be found before the end of the buffer, return 0.
- COUNT negative means scan backward and stop at word beginning. */
+ `count' negative means scan backward and stop at word beginning. */
scan_words (from, count)
register int from, count;
{
register int beg = BEGV;
register int end = ZV;
- register int code;
immediate_quit = 1;
QUIT;
@@ -398,22 +383,15 @@ scan_words (from, count)
immediate_quit = 0;
return 0;
}
- code = SYNTAX (FETCH_CHAR (from));
- if (words_include_escapes
- && (code == Sescape || code == Scharquote))
- break;
- if (code == Sword)
+ if (SYNTAX(FETCH_CHAR (from)) == Sword)
break;
from++;
}
while (1)
{
if (from == end) break;
- code = SYNTAX (FETCH_CHAR (from));
- if (!(words_include_escapes
- && (code == Sescape || code == Scharquote)))
- if (code != Sword)
- break;
+ if (SYNTAX(FETCH_CHAR (from)) != Sword)
+ break;
from++;
}
count--;
@@ -427,22 +405,15 @@ scan_words (from, count)
immediate_quit = 0;
return 0;
}
- code = SYNTAX (FETCH_CHAR (from - 1));
- if (words_include_escapes
- && (code == Sescape || code == Scharquote))
- break;
- if (code == Sword)
+ if (SYNTAX(FETCH_CHAR (from - 1)) == Sword)
break;
from--;
}
while (1)
{
if (from == beg) break;
- code = SYNTAX (FETCH_CHAR (from - 1));
- if (!(words_include_escapes
- && (code == Sescape || code == Scharquote)))
- if (code != Sword)
- break;
+ if (SYNTAX(FETCH_CHAR (from - 1)) != Sword)
+ break;
from--;
}
count++;
@@ -506,8 +477,6 @@ scan_lists (from, count, depth, sexpflag)
&& SYNTAX_COMSTART_SECOND (FETCH_CHAR (from))
&& parse_sexp_ignore_comments)
code = Scomment, from++;
- if (SYNTAX_PREFIX (c))
- continue;
#ifdef SWITCH_ENUM_BUG
switch ((int) code)
@@ -635,8 +604,6 @@ scan_lists (from, count, depth, sexpflag)
&& !char_quoted (from - 1)
&& parse_sexp_ignore_comments)
code = Sendcomment, from--;
- if (SYNTAX_PREFIX (c))
- continue;
#ifdef SWITCH_ENUM_BUG
switch ((int) (quoted ? Sword : code))
@@ -650,12 +617,11 @@ scan_lists (from, count, depth, sexpflag)
/* This word counts as a sexp; count object finished after passing it. */
while (from > stop)
{
- quoted = char_quoted (from - 1);
- if (quoted)
+ if (quoted = char_quoted (from - 1))
from--;
- if (! (quoted || SYNTAX(FETCH_CHAR (from - 1)) == Sword
- || SYNTAX(FETCH_CHAR (from - 1)) == Ssymbol
- || SYNTAX(FETCH_CHAR (from - 1)) == Squote))
+ if (! (quoted || SYNTAX(FETCH_CHAR (from - 1)) == Sword ||
+ SYNTAX(FETCH_CHAR (from - 1)) == Ssymbol ||
+ SYNTAX(FETCH_CHAR (from - 1)) == Squote))
goto done2;
from--;
}
@@ -685,63 +651,19 @@ scan_lists (from, count, depth, sexpflag)
break;
case Sendcomment:
- if (!parse_sexp_ignore_comments)
- break;
- /* Look back, counting the parity of string-quotes,
- and recording the comment-starters seen.
- When we reach a safe place, assume that's not in a string;
- then step the main scan to the earliest comment-starter seen
- an even number of string quotes away from the safe place.
-
- OFROM[I] is position of the earliest comment-starter seen
- which is I+2X quotes from the comment-end.
- PARITY is current parity of quotes from the comment end. */
- {
- int ofrom[2];
- int parity = 0;
-
- ofrom[0] = ofrom[1] = from;
-
- /* At beginning of range to scan, we're outside of strings;
- that determines quote parity to the comment-end. */
- while (from != stop)
- {
- /* Move back and examine a character. */
- from--;
-
- c = FETCH_CHAR (from);
- code = SYNTAX (c);
-
- /* If this char is the second of a 2-char comment sequence,
- back up and give the pair the appropriate syntax. */
- if (from > stop && SYNTAX_COMEND_SECOND (c)
- && SYNTAX_COMEND_FIRST (FETCH_CHAR (from - 1)))
- code = Sendcomment, from--;
- else if (from > stop && SYNTAX_COMSTART_SECOND (c)
- && SYNTAX_COMSTART_FIRST (FETCH_CHAR (from - 1)))
- code = Scomment, from--;
-
- /* Ignore escaped characters. */
- if (char_quoted (from))
- continue;
-
- /* Track parity of quotes between here and comment-end. */
- if (code == Sstring)
- parity ^= 1;
-
- /* Record comment-starters according to that
- quote-parity to the comment-end. */
- if (code == Scomment)
- ofrom[parity] = from;
-
- /* If we come to another comment-end,
- assume it's not inside a string.
- That determines the quote parity to the comment-end. */
- if (code == Sendcomment)
- break;
- }
- from = ofrom[parity];
- }
+ if (!parse_sexp_ignore_comments) break;
+ if (from != stop) from--;
+ while (1)
+ {
+ if (SYNTAX (c = FETCH_CHAR (from)) == Scomment)
+ break;
+ if (from == stop) goto done;
+ from--;
+ if (SYNTAX_COMSTART_SECOND (c)
+ && SYNTAX_COMSTART_FIRST (FETCH_CHAR (from))
+ && !char_quoted (from))
+ break;
+ }
break;
case Sstring:
@@ -787,9 +709,9 @@ char_quoted (pos)
register int beg = BEGV;
register int quoted = 0;
- while (pos > beg
- && ((code = SYNTAX (FETCH_CHAR (pos - 1))) == Scharquote
- || code == Sescape))
+ while (pos > beg &&
+ ((code = SYNTAX (FETCH_CHAR (pos - 1))) == Scharquote
+ || code == Sescape))
pos--, quoted = !quoted;
return quoted;
}
@@ -803,9 +725,9 @@ only places where the depth in parentheses becomes zero\n\
are candidates for stopping; COUNT such places are counted.\n\
Thus, a positive value for DEPTH means go out levels.\n\
\n\
-Comments are ignored if `parse-sexp-ignore-comments' is non-nil.\n\
+Comments are ignored if parse-sexp-ignore-comments is non-nil.\n\
\n\
-If the beginning or end of (the accessible part of) the buffer is reached\n\
+If the beginning or end of (the visible part of) the buffer is reached\n\
and the depth is wrong, an error is signaled.\n\
If the depth is right but the count is not used up, nil is returned.")
(from, count, depth)
@@ -820,15 +742,14 @@ If the depth is right but the count is not used up, nil is returned.")
DEFUN ("scan-sexps", Fscan_sexps, Sscan_sexps, 2, 2, 0,
"Scan from character number FROM by COUNT balanced expressions.\n\
-If COUNT is negative, scan backwards.\n\
Returns the character number of the position thus found.\n\
\n\
-Comments are ignored if `parse-sexp-ignore-comments' is non-nil.\n\
+Comments are ignored if parse-sexp-ignore-comments is non-nil.\n\
\n\
-If the beginning or end of (the accessible part of) the buffer is reached\n\
+If the beginning or end of (the visible part of) the buffer is reached\n\
in the middle of a parenthetical grouping, an error is signaled.\n\
-If the beginning or end is reached between groupings\n\
-but before count is used up, nil is returned.")
+If the beginning or end is reached between groupings but before count is used up,\n\
+nil is returned.")
(from, count)
Lisp_Object from, count;
{
@@ -840,16 +761,13 @@ but before count is used up, nil is returned.")
DEFUN ("backward-prefix-chars", Fbackward_prefix_chars, Sbackward_prefix_chars,
0, 0, 0,
- "Move point backward over any number of chars with prefix syntax.\n\
-This includes chars with \"quote\" or \"prefix\" syntax (' or p).")
+ "Move point backward over any number of chars with syntax \"prefix\".")
()
{
int beg = BEGV;
int pos = point;
- while (pos > beg && !char_quoted (pos - 1)
- && (SYNTAX (FETCH_CHAR (pos - 1)) == Squote
- || SYNTAX_PREFIX (FETCH_CHAR (pos - 1))))
+ while (pos > beg && !char_quoted (pos - 1) && SYNTAX (FETCH_CHAR (pos - 1)) == Squote)
pos--;
SET_PT (pos);
@@ -950,8 +868,6 @@ scan_sexps_forward (from, end, targetdepth, stopbefore, oldstate)
if (from < end && SYNTAX_COMSTART_FIRST (FETCH_CHAR (from - 1))
&& SYNTAX_COMSTART_SECOND (FETCH_CHAR (from)))
code = Scomment, from++;
- if (SYNTAX_PREFIX (FETCH_CHAR (from - 1)))
- continue;
#ifdef SWITCH_ENUM_BUG
switch ((int) code)
#else
@@ -1192,11 +1108,11 @@ syms_of_syntax ()
staticpro (&Qsyntax_table_p);
DEFVAR_BOOL ("parse-sexp-ignore-comments", &parse_sexp_ignore_comments,
- "Non-nil means `forward-sexp', etc., should treat comments as whitespace.");
-
- words_include_escapes = 0;
- DEFVAR_BOOL ("words-include-escapes", &words_include_escapes,
- "Non-nil means `forward-word', etc., should treat escape chars part of words.");
+ "Non-nil means forward-sexp, etc., should treat comments as whitespace.\n\
+Non-nil works only when the comment terminator is something like *\/,\n\
+and appears only when it ends a comment.\n\
+If comments are terminated by newlines,\n\
+you must make this variable nil.");
defsubr (&Ssyntax_table_p);
defsubr (&Ssyntax_table);
diff --git a/src/syntax.h b/src/syntax.h
new file mode 100644
index 00000000000..b1862d7859f
--- /dev/null
+++ b/src/syntax.h
@@ -0,0 +1,84 @@
+/* Declarations having to do with GNU Emacs syntax tables.
+ Copyright (C) 1985 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+extern Lisp_Object Qsyntax_table_p;
+extern Lisp_Object Fsyntax_table_p (), Fsyntax_table (), Fset_syntax_table ();
+
+/* The standard syntax table is stored where it will automatically
+ be used in all new buffers. */
+#define Vstandard_syntax_table buffer_defaults.syntax_table
+
+/* A syntax table is a Lisp vector of length 0400, whose elements are integers.
+
+The low 8 bits of the integer is a code, as follows:
+*/
+
+enum syntaxcode
+ {
+ Swhitespace, /* for a whitespace character */
+ Spunct, /* for random punctuation characters */
+ Sword, /* for a word constituent */
+ Ssymbol, /* symbol constituent but not word constituent */
+ Sopen, /* for a beginning delimiter */
+ Sclose, /* for an ending delimiter */
+ Squote, /* for a prefix character like Lisp ' */
+ Sstring, /* for a string-grouping character like Lisp " */
+ Smath, /* for delimiters like $ in Tex. */
+ Sescape, /* for a character that begins a C-style escape */
+ Scharquote, /* for a character that quotes the following character */
+ Scomment, /* for a comment-starting character */
+ Sendcomment, /* for a comment-ending character */
+ Smax /* Upper bound on codes that are meaningful */
+ };
+
+#define SYNTAX(c) \
+ ((enum syntaxcode) (XINT (XVECTOR (current_buffer->syntax_table)->contents[(unsigned char) (c)]) & 0377))
+
+/* The next 8 bits of the number is a character,
+ the matching delimiter in the case of Sopen or Sclose. */
+
+#define SYNTAX_MATCH(c) \
+ ((XINT (XVECTOR (current_buffer->syntax_table)->contents[(unsigned char) (c)]) >> 8) & 0377)
+
+/* Then there are four single-bit flags that have the following meanings:
+ 1. This character is the first of a two-character comment-start sequence.
+ 2. This character is the second of a two-character comment-start sequence.
+ 3. This character is the first of a two-character comment-end sequence.
+ 4. This character is the second of a two-character comment-end sequence.
+ Note that any two-character sequence whose first character has flag 1
+ and whose second character has flag 2 will be interpreted as a comment start. */
+
+#define SYNTAX_COMSTART_FIRST(c) \
+ ((XINT (XVECTOR (current_buffer->syntax_table)->contents[(unsigned char) (c)]) >> 16) & 1)
+
+#define SYNTAX_COMSTART_SECOND(c) \
+ ((XINT (XVECTOR (current_buffer->syntax_table)->contents[(unsigned char) (c)]) >> 17) & 1)
+
+#define SYNTAX_COMEND_FIRST(c) \
+ ((XINT (XVECTOR (current_buffer->syntax_table)->contents[(unsigned char) (c)]) >> 18) & 1)
+
+#define SYNTAX_COMEND_SECOND(c) \
+ ((XINT (XVECTOR (current_buffer->syntax_table)->contents[(unsigned char) (c)]) >> 19) & 1)
+
+/* This array, indexed by a character, contains the syntax code which that
+ character signifies (as a char). For example,
+ (enum syntaxcode) syntax_spec_code['w'] is Sword. */
+
+extern unsigned char syntax_spec_code[0400];
diff --git a/src/sysdep.c b/src/sysdep.c
new file mode 100644
index 00000000000..9dca7457722
--- /dev/null
+++ b/src/sysdep.c
@@ -0,0 +1,4300 @@
+/* Interfaces to system-dependent kernel and library entries.
+ Copyright (C) 1985, 1986, 1987, 1988, 1990 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* This must precede sys/signal.h on certain machines. */
+#include <sys/types.h>
+#include <signal.h>
+#include <setjmp.h>
+
+#include "config.h"
+#include "lisp.h"
+#undef NULL
+
+#define min(x,y) ((x) > (y) ? (y) : (x))
+
+/* In this file, open, read and write refer to the system calls,
+ not our sugared interfaces sys_open, sys_read and sys_write.
+ Contrariwise, for systems where we use the system calls directly,
+ define sys_read, etc. here as aliases for them. */
+#ifndef read
+#define sys_read read
+#define sys_write write
+#endif /* `read' is not a macro */
+
+#undef read
+#undef write
+
+#ifndef close
+#define sys_close close
+#else
+#undef close
+#endif
+
+#ifndef open
+#define sys_open open
+#else /* `open' is a macro */
+#undef open
+#endif /* `open' is a macro */
+
+#include <stdio.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+extern int errno;
+#ifndef VMS
+extern char *sys_errlist[];
+#endif
+
+#ifdef VMS
+#include <rms.h>
+#include <ttdef.h>
+#include <tt2def.h>
+#include <iodef.h>
+#include <ssdef.h>
+#include <descrip.h>
+#include <fibdef.h>
+#include <atrdef.h>
+#include <ctype.h>
+#include <string.h>
+#ifdef __GNUC__
+#include <sys/file.h>
+#else
+#include <file.h>
+#endif
+#undef F_SETFL
+#ifndef RAB$C_BID
+#include <rab.h>
+#endif
+#define MAXIOSIZE ( 32 * PAGESIZE ) /* Don't I/O more than 32 blocks at a time */
+#endif /* VMS */
+
+#ifndef BSD4_1
+#ifdef BSD /* this is done this way to avoid defined (BSD) || defined (USG)
+ because the vms compiler doesn't grok `defined' */
+#include <fcntl.h>
+#endif
+#ifdef USG
+#include <fcntl.h>
+#endif
+#endif /* not 4.1 bsd */
+
+/* Get DGUX definition for FASYNC - DJB */
+#ifdef DGUX
+#include <sys/file.h>
+#endif /* DGUX */
+
+#ifdef BSD
+#include <sys/ioctl.h>
+#ifdef BSD4_1
+#include <wait.h>
+#else /* not 4.1 */
+#include <sys/wait.h>
+#endif /* not 4.1 */
+#endif /* BSD */
+
+#ifdef STRIDE
+#include <sys/ioctl.h>
+#endif
+
+#ifdef NEED_TERMIOS
+#include <sys/termios.h>
+#endif
+
+#ifdef mips
+#include <sys/ioctl.h>
+#endif
+
+#ifdef _SEQUENT_
+#include <sys/stropts.h>
+#endif /* _SEQUENT_ */
+
+#ifdef AIX
+/* Get files for keyboard remapping */
+#define HFNKEYS 2
+#include <sys/hft.h>
+#include <sys/devinfo.h>
+#endif
+
+/* Get rid of LLITOUT in 4.1, since it is said to stimulate kernel bugs. */
+#ifdef BSD4_1
+#undef LLITOUT
+#define LLITOUT 0
+#endif /* 4.1 */
+
+#ifdef HAVE_TERMIO
+#if defined(AIX) && defined(i386)
+#include <termios.h> /* needs to be before termio.h for aix ps/2 */
+#endif
+#ifndef NO_TERMIO
+#include <termio.h>
+#endif
+#ifdef HAVE_TCATTR
+#define TERMINAL struct termios
+#else /* not HAVE_TCATTR */
+#define TERMINAL struct termio
+#endif /* not HAVE_TCATTR */
+
+#ifdef IBMR2AIX
+#include <termios.h>
+#ifdef TIOCGETP
+#undef TIOCGETP
+#endif /* no TIOCGETP */
+#define TIOCGETP TCGETS
+#undef TIOCSETN
+#define TIOCSETN TCSETSW
+#undef TIOCSETP
+#define TIOCSETP TCSETSF
+#undef TCSETAW
+#define TCSETAW TCSETS
+#else /* not IBMR2AIX */
+#ifdef HAVE_TCATTR
+#include <termios.h>
+#endif /* HAVE_TCATTR */
+#undef TIOCGETP
+#define TIOCGETP TCGETA
+#undef TIOCSETN
+#define TIOCSETN TCSETAW
+#undef TIOCSETP
+#define TIOCSETP TCSETAF
+#endif /* not IBMR2AIX */
+
+/* Try to establish the correct character to disable terminal functions
+ in a system-independent manner. Note that USG (at least) define
+ _POSIX_VDISABLE as 0! */
+#ifdef _POSIX_VDISABLE
+#define CDISABLE _POSIX_VDISABLE
+#else /* not _POSIX_VDISABLE */
+#ifdef CDEL
+#define CDISABLE CDEL
+#else /* not CDEL */
+#define CDISABLE 255
+#endif /* not CDEL */
+#endif /* not _POSIX_VDISABLE */
+
+#ifndef OSPEED
+#define OSPEED(str) (str.c_cflag & CBAUD)
+#endif
+#ifndef SETOSPEED
+#define SETOSPEED(str,new) (str.c_cflag = (str.c_cflag & ~CBAUD) | (new))
+#endif
+#define TABS_OK(str) ((str.c_oflag & TABDLY) != TAB3)
+#endif /* HAVE_TERMIO */
+
+#ifndef HAVE_TCATTR /* If HAVE_TCATTR, this is a primitive. */
+#define tcgetattr(fd, addr) ioctl (fd, TIOCGETP, addr)
+#endif
+
+#ifdef XENIX
+#undef TIOCGETC /* Avoid confusing some conditionals that test this. */
+#endif
+
+#ifdef BROKEN_TIOCGETC
+#undef TIOCGETC
+#endif
+
+#ifdef BROKEN_TIOCGWINSZ
+#undef TIOCGWINSZ
+#endif
+
+#ifndef HAVE_TERMIO
+#ifndef VMS
+#if defined(DGUX) && defined(_BSD_TTY_FLAVOR)
+#undef _BSD_TTY_FLAVOR
+ /* DGUX 4.3 has it's own definition in sgtty.h, and it's different
+ than the one in s-dgux.h */
+#endif
+#include <sgtty.h>
+#define TERMINAL struct sgttyb
+#ifndef OSPEED
+#define OSPEED(str) str.sg_ospeed
+#endif
+#ifndef SETOSPEED
+#define SETOSPEED(str,new) (str.sg_ospeed = (new))
+#endif
+#define TABS_OK(str) ((str.sg_flags & XTABS) != XTABS)
+#undef TCSETAW
+#define TCSETAW TIOCSETN
+#endif /* not VMS */
+#endif /* not HAVE_TERMIO */
+
+#ifdef USG
+#include <sys/utsname.h>
+#include <string.h>
+#ifndef MEMORY_IN_STRING_H
+#include <memory.h>
+#endif
+#ifdef TIOCGWINSZ
+#ifndef IRIS_4D
+#ifndef mips
+#ifndef aix386
+#ifndef NO_SIOCTL_H
+/* Some USG systems with TIOCGWINSZ need this file; some don't have it.
+ We don't know how to distinguish them.
+ If this #include gets an error, just delete it. */
+#include <sys/sioctl.h>
+#endif
+#ifdef NEED_PTEM_H
+#include <sys/stream.h>
+#include <sys/ptem.h>
+#endif
+#endif /* not aix386 */
+#endif /* not mips */
+#endif /* not IRIS_4D */
+#endif /* TIOCGWINSZ */
+#ifdef HAVE_TIMEVAL
+#ifdef HPUX
+#include <time.h>
+#else
+#include <sys/time.h>
+#endif
+#endif /* HAVE_TIMEVAL */
+#endif /* USG */
+
+#ifdef VMS
+#include "window.h"
+#endif
+
+#ifdef NEED_BSDTTY
+#include <sys/bsdtty.h>
+#endif
+
+#if defined (HPUX) && defined (HAVE_PTYS)
+#include <sys/ptyio.h>
+#endif
+
+#ifdef AIX
+#include <sys/pty.h>
+#include <unistd.h>
+#endif /* AIX */
+
+#ifdef SYSV_PTYS
+#include <sys/tty.h>
+#include <sys/pty.h>
+#endif
+
+#include "filetypes.h"
+
+/* FASYNC defined in this file. But, FASYNC don't working.
+ so no problem, because unrequest_sigio only need. */
+#if defined (pfa)
+#include <sys/file.h>
+#endif
+
+#ifdef BROKEN_FIONREAD
+#undef FIONREAD
+#undef FASYNC
+#endif
+
+extern int quit_char;
+
+#include "termhooks.h"
+#include "termchar.h"
+#include "termopts.h"
+#include "dispextern.h"
+
+#ifdef NONSYSTEM_DIR_LIBRARY
+#include "ndir.h"
+#endif /* NONSYSTEM_DIR_LIBRARY */
+
+#include "emacssignal.h"
+
+/* Define SIGCHLD as an alias for SIGCLD. There are many conditionals
+ testing SIGCHLD. */
+
+#ifndef VMS
+#ifdef SIGCLD
+#ifndef SIGCHLD
+#define SIGCHLD SIGCLD
+#endif /* not SIGCHLD */
+#endif /* SIGCLD */
+#endif /* not VMS */
+
+static int baud_convert[] =
+#ifdef BAUD_CONVERT
+ BAUD_CONVERT;
+#else
+ {
+ 0, 50, 75, 110, 135, 150, 200, 300, 600, 1200,
+ 1800, 2400, 4800, 9600, 19200, 38400
+ };
+#endif
+
+extern short ospeed;
+
+#ifdef VMS
+static struct iosb
+{
+ short status;
+ short offset;
+ short termlen;
+ short term;
+} input_iosb;
+
+int kbd_input_ast ();
+
+int waiting_for_ast;
+int stop_input;
+int input_ef = 0;
+int timer_ef = 0;
+int process_ef = 0;
+int input_eflist;
+int timer_eflist;
+
+static int input_chan;
+static $DESCRIPTOR (input_dsc, "TT");
+static int terminator_mask[2] = { 0, 0 };
+
+static struct sensemode {
+ short status;
+ unsigned char xmit_baud;
+ unsigned char rcv_baud;
+ unsigned char crfill;
+ unsigned char lffill;
+ unsigned char parity;
+ unsigned char unused;
+ char class;
+ char type;
+ short scr_wid;
+ unsigned long tt_char : 24, scr_len : 8;
+ unsigned long tt2_char;
+} sensemode_iosb;
+#define TERMINAL struct sensemode
+#define OSPEED(str) (str.xmit_baud)
+#define TABS_OK(str) ((str.tt_char & TT$M_MECHTAB) != 0)
+#endif /* VMS */
+
+discard_tty_input ()
+{
+ TERMINAL buf;
+
+ if (noninteractive)
+ return;
+
+ /* Discarding input is not safe when the input could contain
+ replies from the X server. So don't do it. */
+ if (read_socket_hook)
+ return;
+
+#ifdef VMS
+ end_kbd_input ();
+ SYS$QIOW (0, input_chan, IO$_READVBLK|IO$M_PURGE, input_iosb, 0, 0,
+ &buf, 0, 0, terminator_mask, 0, 0);
+ queue_kbd_input ();
+#else /* not VMS */
+#ifdef APOLLO
+ {
+ int zero = 0;
+ ioctl (0, TIOCFLUSH, &zero);
+ }
+#else /* not Apollo */
+ tcgetattr (0, &buf);
+#ifndef HAVE_TCATTR
+ ioctl (0, TIOCSETP, &buf);
+#else
+ tcsetattr (0, TCSAFLUSH, &buf);
+#endif
+#endif /* not Apollo */
+#endif /* not VMS */
+}
+
+#ifdef SIGTSTP
+
+stuff_char (c)
+ char c;
+{
+/* Should perhaps error if in batch mode */
+#ifdef TIOCSTI
+ ioctl (0, TIOCSTI, &c);
+#else /* no TIOCSTI */
+ error ("Cannot stuff terminal input characters in this version of Unix.");
+#endif /* no TIOCSTI */
+}
+
+#endif /* SIGTSTP */
+
+init_baud_rate ()
+{
+ TERMINAL sg;
+
+ if (noninteractive)
+ ospeed = 0;
+ else
+ {
+#ifdef VMS
+ SYS$QIOW (0, input_chan, IO$_SENSEMODE, &sg, 0, 0,
+ &sg.class, 12, 0, 0, 0, 0 );
+#else
+ SETOSPEED (sg, B9600);
+ tcgetattr (0, &sg);
+#endif /* not VMS */
+ ospeed = OSPEED (sg);
+ }
+
+ baud_rate = (ospeed < sizeof baud_convert / sizeof baud_convert[0]
+ ? baud_convert[ospeed] : 9600);
+ if (baud_rate == 0)
+ baud_rate = 1200;
+}
+
+/*ARGSUSED*/
+set_exclusive_use (fd)
+ int fd;
+{
+#ifdef FIOCLEX
+ ioctl (fd, FIOCLEX, 0);
+#endif
+ /* Ok to do nothing if this feature does not exist */
+}
+
+#ifndef subprocesses
+
+wait_without_blocking ()
+{
+#ifdef BSD
+ wait3 (0, WNOHANG | WUNTRACED, 0);
+#else
+ croak ("wait_without_blocking");
+#endif
+}
+
+#endif /* not subprocesses */
+
+int wait_debugging; /* Set nonzero to make following function work under dbx
+ (at least for bsd). */
+
+/* Wait for subprocess with process id `pid' to terminate and
+ make sure it will get eliminated (not remain forever as a zombie) */
+
+wait_for_termination (pid)
+ int pid;
+{
+ while (1)
+ {
+#ifdef subprocesses
+#if defined (BSD) || (defined (HPUX) && !defined (HPUX_5))
+ /* Note that kill returns -1 even if the process is just a zombie now.
+ But inevitably a SIGCHLD interrupt should be generated
+ and child_sig will do wait3 and make the process go away. */
+ /* There is some indication that there is a bug involved with
+ termination of subprocesses, perhaps involving a kernel bug too,
+ but no idea what it is. Just as a hunch we signal SIGCHLD to see
+ if that causes the problem to go away or get worse. */
+#ifdef BSD4_1
+ extern int synch_process_pid;
+ sighold (SIGCHLD);
+ if (synch_process_pid == 0)
+ {
+ sigrelse (SIGCHLD);
+ break;
+ }
+ if (wait_debugging)
+ sleep (1);
+ else
+ sigpause (SIGCHLD);
+#else /* not BSD4_1 */
+ sigsetmask (sigmask (SIGCHLD));
+ if (0 > kill (pid, 0))
+ {
+ sigsetmask (SIGEMPTYMASK);
+ kill (getpid (), SIGCHLD);
+ break;
+ }
+ if (wait_debugging)
+ sleep (1);
+ else
+ sigpause (SIGEMPTYMASK);
+#endif /* not BSD4_1 */
+#else /* not BSD, and not HPUX version >= 6 */
+#ifdef UNIPLUS
+ if (0 > kill (pid, 0))
+ break;
+ wait (0);
+#else /* neither BSD nor UNIPLUS: random sysV */
+#ifdef HAVE_SYSV_SIGPAUSE
+ sighold (SIGCHLD);
+ if (0 > kill (pid, 0))
+ {
+ sigrelse (SIGCHLD);
+ break;
+ }
+ sigpause (SIGCHLD);
+#else /* not HAVE_SYSV_SIGPAUSE */
+ if (0 > kill (pid, 0))
+ break;
+ /* Using sleep instead of pause avoids timing error.
+ If the inferior dies just before the sleep,
+ we lose just one second. */
+ sleep (1);
+#endif /* not HAVE_SYSV_SIGPAUSE */
+#endif /* not UNIPLUS */
+#endif /* not BSD, and not HPUX version >= 6 */
+#else /* not subprocesses */
+#ifndef BSD4_1
+ if (0 > kill (pid, 0))
+ break;
+ sleep (1);
+#else /* BSD4_1 */
+ int status;
+ status = wait (0);
+ if (status == pid || status == -1)
+ break;
+#endif /* BSD4_1 */
+#endif /* not subprocesses */
+ }
+}
+
+#ifdef subprocesses
+
+/*
+ * flush any pending output
+ * (may flush input as well; it does not matter the way we use it)
+ */
+
+flush_pending_output (channel)
+ int channel;
+{
+#ifdef TCFLSH
+ ioctl (channel, TCFLSH, 1);
+#else
+#ifdef TIOCFLUSH
+ int zero = 0;
+ /* 3rd arg should be ignored
+ but some 4.2 kernels actually want the address of an int
+ and nonzero means something different. */
+ ioctl (channel, TIOCFLUSH, &zero);
+#endif
+#endif
+}
+
+/* Set up the terminal at the other end of a pseudo-terminal that
+ we will be controlling an inferior through.
+ It should not echo or do line-editing, since that is done
+ in Emacs. No padding needed for insertion into an Emacs buffer. */
+
+child_setup_tty (out)
+ int out;
+{
+ TERMINAL s;
+
+ tcgetattr (out, &s);
+#ifdef HAVE_TERMIO
+ s.c_oflag |= OPOST; /* Enable output postprocessing */
+ s.c_oflag &= ~ONLCR; /* Disable map of NL to CR-NL on output */
+ s.c_oflag &= ~(NLDLY|CRDLY|TABDLY|BSDLY|VTDLY|FFDLY); /* No output delays */
+ s.c_lflag &= ~ECHO; /* Disable echo */
+ s.c_lflag |= ISIG; /* Enable signals */
+ s.c_iflag &= ~IUCLC; /* Disable map of upper case to lower on input */
+ s.c_oflag &= ~OLCUC; /* Disable map of lower case to upper on output */
+/* said to be unnecesary
+ s.c_cc[VMIN] = 1; /* minimum number of characters to accept
+ s.c_cc[VTIME] = 0; /* wait forever for at least 1 character
+*/
+ s.c_lflag |= ICANON; /* Enable erase/kill and eof processing */
+ s.c_cc[VEOF] = 04; /* insure that EOF is Control-D */
+ s.c_cc[VERASE] = 0377; /* disable erase processing */
+ s.c_cc[VKILL] = 0377; /* disable kill processing */
+#ifdef IRIS_4D /* This is needed for the sake of process_send_signal.
+ Probably a wide class of systems need something like this,
+ but in 18.58, let's be cautious. */
+ s.c_cc[VSWTCH] = 032;
+#endif
+#ifdef HPUX
+ s.c_cflag = (s.c_cflag & ~CBAUD) | B9600; /* baud rate sanity */
+#endif /* HPUX */
+
+#ifdef AIX
+/* AIX enhanced edit loses NULs, so disable it */
+#ifndef IBMR2AIX
+ s.c_line = 0;
+ s.c_iflag &= ~ASCEDIT;
+#endif
+ /* Also, PTY overloads NUL and BREAK.
+ don't ignore break, but don't signal either, so it looks like NUL. */
+ s.c_iflag &= ~IGNBRK;
+ s.c_iflag &= ~BRKINT;
+#if defined(TIOCGPGRP) && defined(TIOCGLTC) && defined(TIOCGETC)
+ /* the QUIT and INTR character are used in process_send_signal
+ so set them here to something useful. */
+ if (s.c_cc[VQUIT] == 0377)
+ s.c_cc[VQUIT] = '\\'&037; /* Control-\ */
+ if (s.c_cc[VINTR] == 0377)
+ s.c_cc[VINTR] = 'C'&037; /* Control-C */
+#else /* no TIOCGPGRP or no TIOCGLTC or no TIOCGETC */
+ /* QUIT and INTR are sent using system calls, so disable character forms. */
+ s.c_cc[VQUIT] = 0377;
+ s.c_cc[VINTR] = 0377;
+ s.c_lflag &= ~ISIG;
+#endif /* no TIOCGPGRP or no TIOCGLTC or no TIOCGETC */
+ s.c_cc[VEOL] = 0377;
+ s.c_cflag = (s.c_cflag & ~CBAUD) | B9600; /* baud rate sanity */
+#endif /* AIX */
+
+#else /* not HAVE_TERMIO */
+ s.sg_flags &= ~(ECHO | CRMOD | ANYP | ALLDELAY | RAW | LCASE | CBREAK | TANDEM);
+ s.sg_erase = 0377;
+ s.sg_kill = 0377;
+#endif /* not HAVE_TERMIO */
+
+#ifndef HAVE_TCATTR
+ ioctl (out, TIOCSETN, &s);
+#else
+ tcsetattr (out, TCSADRAIN, &s);
+#endif
+
+#ifdef BSD4_1
+ if (interrupt_input)
+ reset_sigio ();
+#endif /* BSD4_1 */
+#ifdef RTU
+ {
+ int zero = 0;
+ ioctl (out, FIOASYNC, &zero);
+ }
+#endif /* RTU */
+}
+
+#endif /* subprocesses */
+
+/*ARGSUSED*/
+setpgrp_of_tty (pid)
+ int pid;
+{
+#ifdef IBMR2AIX
+ tcsetpgrp ( 0, pid);
+#else
+#ifdef TIOCSPGRP
+ ioctl (0, TIOCSPGRP, &pid);
+#else
+ /* Just ignore this for now and hope for the best */
+#endif
+#endif
+}
+
+/* Record a signal code and the handler for it. */
+struct save_signal
+{
+ int code;
+ int (*handler) ();
+};
+
+/* Suspend the Emacs process; give terminal to its superior. */
+
+sys_suspend ()
+{
+#ifdef VMS
+ unsigned long parent_id;
+
+ parent_id = getppid ();
+ if (parent_id && parent_id != 0xffffffff)
+ {
+ int oldsig = (int) signal (SIGINT, SIG_IGN);
+ int status = LIB$ATTACH (&parent_id) & 1;
+ signal (SIGINT, oldsig);
+ return status;
+ }
+ return -1;
+#else
+#ifdef SIGTSTP
+#ifdef BSD
+ killpg (getpgrp (0), SIGTSTP);
+#else
+ kill (-getpgrp (0), SIGTSTP);
+#endif
+
+#else
+#ifdef USG_JOBCTRL /* If you don't know what this is don't mess with it */
+ ptrace (0, 0, 0, 0); /* set for ptrace - caught by csh */
+ kill (getpid (), SIGQUIT);
+
+#else
+
+/* On a system where suspending is not implemented,
+ instead fork a subshell and let it talk directly to the terminal
+ while we wait. */
+ int pid = fork ();
+ struct save_signal saved_handlers[5];
+
+ saved_handlers[0].code = SIGINT;
+ saved_handlers[1].code = SIGQUIT;
+ saved_handlers[2].code = SIGTERM;
+#ifdef SIGIO
+ saved_handlers[3].code = SIGIO;
+ saved_handlers[4].code = 0;
+#else
+ saved_handlers[3].code = 0;
+#endif
+
+ if (pid == -1)
+ error ("Can't spawn subshell");
+ if (pid == 0)
+ {
+ char *sh;
+
+ sh = (char *) egetenv ("SHELL");
+ if (sh == 0)
+ sh = "sh";
+ /* Use our buffer's default directory for the subshell. */
+ {
+ Lisp_Object dir;
+ unsigned char *str;
+ int len;
+
+ /* mentioning current_buffer->buffer would mean including buffer.h,
+ which somehow wedges the hp compiler. So instead... */
+
+ dir = intern ("default-directory");
+ /* Can't use NULL */
+ if (XFASTINT (Fboundp (dir)) == XFASTINT (Qnil))
+ goto xyzzy;
+ dir = Fsymbol_value (dir);
+ if (XTYPE (dir) != Lisp_String)
+ goto xyzzy;
+
+ str = (unsigned char *) alloca (XSTRING (dir)->size + 2);
+ len = XSTRING (dir)->size;
+ bcopy (XSTRING (dir)->data, str, len);
+ if (str[len - 1] != '/') str[len++] = '/';
+ str[len] = 0;
+ chdir (str);
+ }
+ xyzzy:
+#ifdef subprocesses
+ close_process_descs (); /* Close Emacs's pipes/ptys */
+#endif
+ execlp (sh, sh, 0);
+ write (1, "Can't execute subshell", 22);
+ _exit (1);
+ }
+ save_signal_handlers (saved_handlers);
+ wait_for_termination (pid);
+ restore_signal_handlers (saved_handlers);
+#endif /* no USG_JOBCTRL */
+#endif /* no SIGTSTP */
+#endif /* not VMS */
+}
+
+save_signal_handlers (saved_handlers)
+ struct save_signal *saved_handlers;
+{
+ while (saved_handlers->code)
+ {
+ saved_handlers->handler
+ = (int (*) ()) signal (saved_handlers->code, SIG_IGN);
+ saved_handlers++;
+ }
+}
+
+restore_signal_handlers (saved_handlers)
+ struct save_signal *saved_handlers;
+{
+ while (saved_handlers->code)
+ {
+ signal (saved_handlers->code, saved_handlers->handler);
+ saved_handlers++;
+ }
+}
+
+#ifdef F_SETFL
+
+int old_fcntl_flags;
+
+init_sigio ()
+{
+#ifdef FASYNC
+ old_fcntl_flags = fcntl (0, F_GETFL, 0) & ~FASYNC;
+#endif
+ request_sigio ();
+}
+
+reset_sigio ()
+{
+ unrequest_sigio ();
+}
+
+#ifdef FASYNC /* F_SETFL does not imply existance of FASYNC */
+
+request_sigio ()
+{
+#ifdef SIGWINCH
+ sigunblock (sigmask (SIGWINCH));
+#endif
+ fcntl (0, F_SETFL, old_fcntl_flags | FASYNC);
+
+ interrupts_deferred = 0;
+}
+
+unrequest_sigio ()
+{
+#ifdef SIGWINCH
+ sigblock (sigmask (SIGWINCH));
+#endif
+ fcntl (0, F_SETFL, old_fcntl_flags);
+ interrupts_deferred = 1;
+}
+
+#else /* no FASYNC */
+#ifdef STRIDE /* Stride doesn't have FASYNC - use FIOASYNC */
+
+request_sigio ()
+{
+ int on = 1;
+ ioctl (0, FIOASYNC, &on);
+ interrupts_deferred = 0;
+}
+
+unrequest_sigio ()
+{
+ int off = 0;
+
+ ioctl (0, FIOASYNC, &off);
+ interrupts_deferred = 1;
+}
+
+#else /* not FASYNC, not STRIDE */
+
+request_sigio ()
+{
+ croak ("request_sigio");
+}
+
+unrequest_sigio ()
+{
+ croak ("unrequest_sigio");
+}
+
+#endif /* STRIDE */
+#endif /* FASYNC */
+#endif /* F_SETFL */
+
+TERMINAL old_gtty; /* The initial tty mode bits */
+
+int term_initted; /* 1 if outer tty status has been recorded */
+
+#ifdef F_SETOWN
+int old_fcntl_owner;
+#endif /* F_SETOWN */
+
+#ifdef TIOCGLTC
+struct ltchars old_ltchars;
+#endif /* TIOCGLTC */
+
+#ifdef TIOCGETC
+struct tchars old_tchars;
+int old_lmode;
+
+int lmode; /* Current lmode value. */
+ /* Needed as global for 4.1 */
+#endif /* TIOCGETC */
+
+/* This may also be defined in stdio,
+ but if so, this does no harm,
+ and using the same name avoids wasting the other one's space. */
+
+#if defined (USG) || defined (DGUX)
+unsigned char _sobuf[BUFSIZ+8];
+#else
+char _sobuf[BUFSIZ];
+#endif
+
+#ifdef TIOCGLTC
+static struct ltchars new_ltchars = {-1,-1,-1,-1,-1,-1};
+#endif
+#ifdef TIOCGETC
+ static struct tchars new_tchars = {-1,-1,-1,-1,-1,-1};
+#endif
+
+init_sys_modes ()
+{
+ TERMINAL tty;
+#ifdef TIOCGETC
+ struct tchars tchars;
+#endif
+#ifdef VMS
+#if 0
+ static int oob_chars[2] = {0, 1 << 7}; /* catch C-g's */
+ extern int (*interrupt_signal) ();
+#endif
+#endif
+
+ if (noninteractive)
+ return;
+
+#ifdef VMS
+ if (!input_ef)
+ LIB$GET_EF (&input_ef);
+ SYS$CLREF (input_ef);
+ waiting_for_ast = 0;
+ if (!timer_ef)
+ LIB$GET_EF (&timer_ef);
+ SYS$CLREF (timer_ef);
+ if (!process_ef)
+ {
+ LIB$GET_EF (&process_ef);
+ SYS$CLREF (process_ef);
+ }
+ if (input_ef / 32 != process_ef / 32)
+ croak ("Input and process event flags in different clusters.");
+ if (input_ef / 32 != timer_ef / 32)
+ croak ("Input and process event flags in different clusters.");
+ input_eflist = ((unsigned) 1 << (input_ef % 32)) |
+ ((unsigned) 1 << (process_ef % 32));
+ timer_eflist = ((unsigned) 1 << (input_ef % 32)) |
+ ((unsigned) 1 << (timer_ef % 32));
+ SYS$QIOW (0, input_chan, IO$_SENSEMODE, &old_gtty, 0, 0,
+ &old_gtty.class, 12, 0, 0, 0, 0);
+#ifndef VMS4_4
+ sys_access_reinit ();
+#endif
+#else /* not VMS */
+ tcgetattr (0, &old_gtty);
+#endif /* not VMS */
+ if (!read_socket_hook)
+ {
+ tty = old_gtty;
+
+#ifdef HAVE_TERMIO
+ tty.c_iflag |= (IGNBRK); /* Ignore break condition */
+ tty.c_iflag &= ~ICRNL; /* Disable map of CR to NL on input */
+#ifdef ISTRIP
+ tty.c_iflag &= ~ISTRIP; /* don't strip 8th bit on input */
+#endif
+ tty.c_lflag &= ~ECHO; /* Disable echo */
+ tty.c_lflag &= ~ICANON; /* Disable erase/kill processing */
+#ifdef IEXTEN
+ tty.c_iflag &= ~IEXTEN; /* Disable other editing characters. */
+#endif
+ tty.c_lflag |= ISIG; /* Enable signals */
+ if (flow_control)
+ {
+ tty.c_iflag |= IXON; /* Enable start/stop output control */
+#ifdef IXANY
+ tty.c_iflag &= ~IXANY;
+#endif /* IXANY */
+ }
+ else
+ tty.c_iflag &= ~IXON; /* Disable start/stop output control */
+ tty.c_oflag &= ~ONLCR; /* Disable map of NL to CR-NL on output */
+ tty.c_oflag &= ~TAB3; /* Disable tab expansion */
+#ifdef CS8
+ tty.c_cflag |= CS8; /* allow 8th bit on input */
+ tty.c_cflag &= ~PARENB; /* Don't check parity */
+#endif
+ tty.c_cc[VINTR] = quit_char; /* ^G gives SIGINT */
+ /* Set up C-g (usually) for both SIGQUIT and SIGINT.
+ We don't know which we will get, but we handle both alike
+ so which one it really gives us does not matter. */
+ tty.c_cc[VQUIT] = quit_char;
+ tty.c_cc[VMIN] = 1; /* Input should wait for at least 1 char */
+ tty.c_cc[VTIME] = 0; /* no matter how long that takes. */
+#ifdef VSWTCH
+ tty.c_cc[VSWTCH] = CDISABLE; /* Turn off shell layering use of C-z */
+#endif /* VSWTCH */
+#if defined (mips) || defined (HAVE_TCATTR)
+#ifdef VSUSP
+ tty.c_cc[VSUSP] = CDISABLE; /* Turn off mips handling of C-z. */
+#endif /* VSUSP */
+#ifdef V_DSUSP
+ tty.c_cc[V_DSUSP] = CDISABLE; /* Turn off mips handling of C-y. */
+#endif /* V_DSUSP */
+#ifdef VDSUSP /* Some systems use VDSUSP instead of VD_SUSP. */
+ tty.c_cc[VDSUSP] = CDISABLE;
+#endif /* VDSUSP */
+#endif /* mips or HAVE_TCATTR */
+
+#ifdef AIX
+#ifndef IBMR2AIX
+ /* AIX enhanced edit loses NULs, so disable it */
+ tty.c_line = 0;
+ tty.c_iflag &= ~ASCEDIT;
+#else
+ tty.c_cc[VSTRT] = 255;
+ tty.c_cc[VSTOP] = 255;
+ tty.c_cc[VSUSP] = 255;
+ tty.c_cc[VDSUSP] = 255;
+#endif /* IBMR2AIX */
+ /* Also, PTY overloads NUL and BREAK.
+ don't ignore break, but don't signal either, so it looks like NUL.
+ This really serves a purpose only if running in an XTERM window
+ or via TELNET or the like, but does no harm elsewhere. */
+ tty.c_iflag &= ~IGNBRK;
+ tty.c_iflag &= ~BRKINT;
+#endif /* AIX */
+
+#else /* if not HAVE_TERMIO */
+#ifdef VMS
+ tty.tt_char |= TT$M_NOECHO | TT$M_EIGHTBIT;
+ if (flow_control)
+ tty.tt_char |= TT$M_TTSYNC;
+ else
+ tty.tt_char &= ~TT$M_TTSYNC;
+ tty.tt2_char |= TT2$M_PASTHRU | TT2$M_XON;
+#else /* not VMS (BSD, that is) */
+ tty.sg_flags &= ~(ECHO | CRMOD | XTABS);
+ tty.sg_flags |= ANYP;
+ tty.sg_flags |= interrupt_input ? RAW : CBREAK;
+#endif /* not VMS (BSD, that is) */
+#endif /* not HAVE_TERMIO */
+
+#ifdef VMS
+ SYS$QIOW (0, input_chan, IO$_SETMODE, &input_iosb, 0, 0,
+ &tty.class, 12, 0, 0, 0, 0);
+#else
+#ifndef HAVE_TCATTR
+ ioctl (0, TIOCSETN, &tty);
+#else
+ tcsetattr (0, TCSADRAIN, &tty);
+#endif
+#endif /* not VMS */
+
+ /* This code added to insure that, if flow-control is not to be used,
+ we have an unlocked screen at the start. */
+#ifdef TCXONC
+ if (!flow_control) ioctl (0, TCXONC, 1);
+#endif
+#ifndef APOLLO
+#ifdef TIOCSTART
+ if (!flow_control) ioctl (0, TIOCSTART, 0);
+#endif
+#endif
+
+#ifdef AIX
+ hft_init ();
+#ifdef IBMR2AIX
+ {
+ /* IBM's HFT device usually thinks a ^J should be LF/CR. We need it
+ to be only LF. This is the way that is done. */
+ struct termio tty;
+
+ if (ioctl (1, HFTGETID, &tty) != -1)
+ write (1, "\033[20l", 5);
+ }
+#endif
+#endif
+
+#ifdef F_SETFL
+#ifdef F_GETOWN /* F_SETFL does not imply existance of F_GETOWN */
+ if (interrupt_input)
+ {
+ old_fcntl_owner = fcntl (0, F_GETOWN, 0);
+ fcntl (0, F_SETOWN, getpid ());
+ init_sigio ();
+ }
+#endif /* F_GETOWN */
+#endif /* F_SETFL */
+
+ /* If going to use CBREAK mode, we must request C-g to interrupt
+ and turn off start and stop chars, etc.
+ If not going to use CBREAK mode, do this anyway
+ so as to turn off local flow control for user coming over
+ network on 4.2; in this case, only t_stopc and t_startc really matter. */
+#ifdef TIOCGLTC
+ ioctl (0, TIOCGLTC, &old_ltchars);
+#endif /* TIOCGLTC */
+#ifndef HAVE_TERMIO
+#ifdef TIOCGETC
+ ioctl (0, TIOCGETC, &old_tchars);
+ ioctl (0, TIOCLGET, &old_lmode);
+
+ /* Note: if not using CBREAK mode, it makes no difference how we set this */
+ tchars = new_tchars;
+ tchars.t_intrc = quit_char;
+ if (flow_control)
+ {
+ tchars.t_startc = '\021';
+ tchars.t_stopc = '\023';
+ }
+/* LPASS8 is new in 4.3, and makes cbreak mode provide all 8 bits. */
+#ifndef LPASS8
+#define LPASS8 0
+#endif
+
+#ifdef BSD4_1
+#define LNOFLSH 0100000
+#endif
+
+ lmode = LDECCTQ | LLITOUT | LPASS8 | LNOFLSH | old_lmode;
+
+ ioctl (0, TIOCSETC, &tchars);
+ ioctl (0, TIOCLSET, &lmode);
+#endif /* TIOCGETC */
+#endif /* not HAVE_TERMIO */
+#ifdef TIOCGLTC
+ ioctl (0, TIOCSLTC, &new_ltchars);
+#endif /* TIOCGLTC */
+
+#ifdef BSD4_1
+ if (interrupt_input)
+ init_sigio ();
+#endif
+#ifdef VMS
+/* Appears to do nothing when in PASTHRU mode.
+ SYS$QIOW (0, input_chan, IO$_SETMODE|IO$M_OUTBAND, 0, 0, 0,
+ interrupt_signal, oob_chars, 0, 0, 0, 0);
+*/
+ queue_kbd_input (0);
+#endif /* VMS */
+ }
+#ifdef VMS /* VMS sometimes has this symbol but lacks setvbuf. */
+#undef _IOFBF
+#endif
+#ifdef _IOFBF
+ /* This symbol is defined on recent USG systems.
+ Someone says without this call USG won't really buffer the file
+ even with a call to setbuf. */
+ setvbuf (stdout, _sobuf, _IOFBF, sizeof _sobuf);
+#else
+ setbuf (stdout, _sobuf);
+#endif
+ set_terminal_modes ();
+ if (term_initted && no_redraw_on_reenter)
+ {
+ if (display_completed)
+ direct_output_forward_char (0);
+ }
+ else
+ screen_garbaged = 1;
+ term_initted = 1;
+}
+
+/* Return nonzero if safe to use tabs in output.
+ At the time this is called, init_sys_modes has not been done yet. */
+
+tabs_safe_p ()
+{
+ TERMINAL tty;
+ if (noninteractive)
+ return 1;
+#ifdef VMS
+ SYS$QIOW (0, input_chan, IO$_SENSEMODE, &tty, 0, 0,
+ &tty.class, 12, 0, 0, 0, 0);
+#else
+ tcgetattr (0, &tty);
+#endif /* not VMS */
+ return (TABS_OK (tty));
+}
+
+/* Get terminal size from system.
+ Store number of lines into *heightp and width into *widthp.
+ If zero or a negative number is stored, the value is not valid. */
+
+get_screen_size (widthp, heightp)
+ int *widthp, *heightp;
+{
+/* Define the 4.3 names in terms of the Sun names
+ if the latter exist and the former do not. */
+#ifdef TIOCGSIZE
+#ifndef TIOCGWINSZ
+#define TIOCGWINSZ TIOCGSIZE
+#define winsize ttysize
+#define ws_row ts_lines
+#define ws_col ts_cols
+#endif
+#endif /* Sun */
+
+/* Do it using the 4.3 names if possible. */
+#ifdef TIOCGWINSZ
+ struct winsize size;
+ *widthp = 0;
+ *heightp = 0;
+ if (ioctl (0, TIOCGWINSZ, &size) < 0)
+ return;
+ *widthp = size.ws_col;
+ *heightp = size.ws_row;
+#else /* not TIOCGWNSIZ */
+#ifdef VMS
+ TERMINAL tty;
+ SYS$QIOW (0, input_chan, IO$_SENSEMODE, &tty, 0, 0,
+ &tty.class, 12, 0, 0, 0, 0);
+ *widthp = tty.scr_wid;
+ *heightp = tty.scr_len;
+#else /* system doesn't know size */
+ *widthp = 0;
+ *heightp = 0;
+#endif /* system does not know size */
+#endif /* not TIOCGWINSZ */
+}
+
+reset_sys_modes ()
+{
+ if (noninteractive)
+ {
+ fflush (stdout);
+ return;
+ }
+ if (!term_initted)
+ return;
+ if (read_socket_hook)
+ return;
+ move_cursor (screen_height - 1, 0);
+ clear_end_of_line (screen_width);
+ /* clear_end_of_line may move the cursor */
+ move_cursor (screen_height - 1, 0);
+ /* Output raw CR so kernel can track the cursor hpos. */
+ cmputc ('\r');
+#ifdef IBMR2AIX
+ {
+ /* HFT devices normally use ^J as a LF/CR. We forced it to
+ do the LF only. Now, we need to reset it. */
+ struct termio tty;
+
+ if (ioctl (1, HFTGETID, &tty) != -1)
+ write (1, "\033[20h", 5);
+ }
+#endif
+
+ reset_terminal_modes ();
+ fflush (stdout);
+#ifdef BSD
+#ifndef BSD4_1
+ /* Avoid possible loss of output when changing terminal modes. */
+ fsync (fileno (stdout));
+#endif
+#endif
+#ifdef TIOCGLTC
+ ioctl (0, TIOCSLTC, &old_ltchars);
+#endif /* TIOCGLTC */
+#ifndef HAVE_TERMIO
+#ifdef TIOCGETC
+ ioctl (0, TIOCSETC, &old_tchars);
+ ioctl (0, TIOCLSET, &old_lmode);
+#endif /* TIOCGETC */
+#endif /* not HAVE_TERMIO */
+#ifdef F_SETFL
+#ifdef F_SETOWN /* F_SETFL does not imply existance of F_SETOWN */
+ if (interrupt_input)
+ {
+ reset_sigio ();
+ fcntl (0, F_SETOWN, old_fcntl_owner);
+ }
+#endif /* F_SETOWN */
+#endif /* F_SETFL */
+#ifdef BSD4_1
+ if (interrupt_input)
+ reset_sigio ();
+#endif /* BSD4_1 */
+#ifdef VMS
+ end_kbd_input ();
+ SYS$QIOW (0, input_chan, IO$_SETMODE, &input_iosb, 0, 0,
+ &old_gtty.class, 12, 0, 0, 0, 0);
+#else /* not VMS */
+#ifndef HAVE_TCATTR
+ while (ioctl (0, TCSETAW, &old_gtty) < 0 && errno == EINTR);
+#else
+ while (tcsetattr (0, TCSADRAIN, &old_gtty) < 0 && errno == EINTR);
+#endif
+#endif /* not VMS */
+
+#ifdef AIX
+ hft_reset ();
+#endif
+}
+
+#ifdef HAVE_PTYS
+
+/* Set up the proper status flags for use of a pty. */
+
+setup_pty (fd)
+ int fd;
+{
+ /* I'm told that TOICREMOTE does not mean control chars
+ "can't be sent" but rather that they don't have
+ input-editing or signaling effects.
+ That should be good, because we have other ways
+ to do those things in Emacs.
+ However, telnet mode seems not to work on 4.2.
+ So TIOCREMOTE is turned off now. */
+
+ /* Under hp-ux, if TIOCREMOTE is turned on, some calls
+ will hang. In particular, the "timeout" feature (which
+ causes a read to return if there is no data available)
+ does this. Also it is known that telnet mode will hang
+ in such a way that Emacs must be stopped (perhaps this
+ is the same problem).
+
+ If TIOCREMOTE is turned off, then there is a bug in
+ hp-ux which sometimes loses data. Apparently the
+ code which blocks the master process when the internal
+ buffer fills up does not work. Other than this,
+ though, everything else seems to work fine.
+
+ Since the latter lossage is more benign, we may as well
+ lose that way. -- cph */
+#ifdef FIONBIO
+#ifdef SYSV_PTYS
+ {
+ int on = 1;
+ ioctl (fd, FIONBIO, &on);
+ }
+#endif
+#endif
+#ifdef IBMRTAIX
+ /* On AIX, the parent gets SIGHUP when a pty attached child dies. So, we */
+ /* ignore SIGHUP once we've started a child on a pty. Note that this may */
+ /* cause EMACS not to die when it should, i.e., when its own controlling */
+ /* tty goes away. I've complained to the AIX developers, and they may */
+ /* change this behavior, but I'm not going to hold my breath. */
+ signal (SIGHUP, SIG_IGN);
+#endif
+}
+#endif /* HAVE_PTYS */
+
+#ifdef VMS
+
+/* Assigning an input channel is done at the start of Emacs execution.
+ This is called each time Emacs is resumed, also, but does nothing
+ because input_chain is no longer zero. */
+
+init_vms_input ()
+{
+ int status;
+
+ if (input_chan == 0)
+ {
+ status = SYS$ASSIGN (&input_dsc, &input_chan, 0, 0);
+ if (! (status & 1))
+ LIB$STOP (status);
+ }
+}
+
+/* Deassigning the input channel is done before exiting. */
+
+stop_vms_input ()
+{
+ return SYS$DASSGN (input_chan);
+}
+
+short input_buffer;
+
+/* Request reading one character into the keyboard buffer.
+ This is done as soon as the buffer becomes empty. */
+
+queue_kbd_input ()
+{
+ int status;
+ waiting_for_ast = 0;
+ stop_input = 0;
+ status = SYS$QIO (0, input_chan, IO$_READVBLK,
+ &input_iosb, kbd_input_ast, 1,
+ &input_buffer, 1, 0, terminator_mask, 0, 0);
+}
+
+int input_count;
+
+/* Ast routine that is called when keyboard input comes in
+ in accord with the SYS$QIO above. */
+
+kbd_input_ast ()
+{
+ register int c = -1;
+ int old_errno = errno;
+
+ if (waiting_for_ast)
+ SYS$SETEF (input_ef);
+ waiting_for_ast = 0;
+ input_count++;
+#ifdef ASTDEBUG
+ if (input_count == 25)
+ exit (1);
+ printf ("Ast # %d,", input_count);
+ printf (" iosb = %x, %x, %x, %x",
+ input_iosb.offset, input_iosb.status, input_iosb.termlen,
+ input_iosb.term);
+#endif
+ if (input_iosb.offset)
+ {
+ c = input_buffer;
+#ifdef ASTDEBUG
+ printf (", char = 0%o", c);
+#endif
+ }
+#ifdef ASTDEBUG
+ printf ("\n");
+ fflush (stdout);
+ sleep (1);
+#endif
+ if (! stop_input)
+ queue_kbd_input ();
+ if (c >= 0)
+ kbd_buffer_store_char (c);
+
+ errno = old_errno;
+}
+
+/* Wait until there is something in kbd_buffer. */
+
+wait_for_kbd_input ()
+{
+ extern int have_process_input, process_exited;
+
+ /* If already something, avoid doing system calls. */
+ if (detect_input_pending ())
+ {
+ return;
+ }
+ /* Clear a flag, and tell ast routine above to set it. */
+ SYS$CLREF (input_ef);
+ waiting_for_ast = 1;
+ /* Check for timing error: ast happened while we were doing that. */
+ if (!detect_input_pending ())
+ {
+ /* No timing error: wait for flag to be set. */
+ set_waiting_for_input (0);
+ SYS$WFLOR (input_ef, input_eflist);
+ clear_waiting_for_input (0);
+ if (!detect_input_pending ())
+ /* Check for subprocess input availability */
+ {
+ int dsp = have_process_input || process_exited;
+
+ sys$clref (process_ef);
+ if (have_process_input)
+ process_command_input ();
+ if (process_exited)
+ process_exit ();
+ if (dsp)
+ {
+ update_mode_lines++;
+ redisplay_preserve_echo_area ();
+ }
+ }
+ }
+ waiting_for_ast = 0;
+}
+
+/* Get rid of any pending QIO, when we are about to suspend
+ or when we want to throw away pending input.
+ We wait for a positive sign that the AST routine has run
+ and therefore there is no I/O request queued when we return.
+ SYS$SETAST is used to avoid a timing error. */
+
+end_kbd_input ()
+{
+#ifdef ASTDEBUG
+ printf ("At end_kbd_input.\n");
+ fflush (stdout);
+ sleep (1);
+#endif
+ if (LIB$AST_IN_PROG ()) /* Don't wait if suspending from kbd_buffer_store_char! */
+ {
+ SYS$CANCEL (input_chan);
+ return;
+ }
+
+ SYS$SETAST (0);
+ /* Clear a flag, and tell ast routine above to set it. */
+ SYS$CLREF (input_ef);
+ waiting_for_ast = 1;
+ stop_input = 1;
+ SYS$CANCEL (input_chan);
+ SYS$SETAST (1);
+ SYS$WAITFR (input_ef);
+ waiting_for_ast = 0;
+}
+
+/* Wait for either input available or time interval expiry. */
+
+input_wait_timeout (timeval)
+ int timeval; /* Time to wait, in seconds */
+{
+ int time [2];
+ static int zero = 0;
+ static int large = -10000000;
+
+ LIB$EMUL (&timeval, &large, &zero, time); /* Convert to VMS format */
+
+ /* If already something, avoid doing system calls. */
+ if (detect_input_pending ())
+ {
+ return;
+ }
+ /* Clear a flag, and tell ast routine above to set it. */
+ SYS$CLREF (input_ef);
+ waiting_for_ast = 1;
+ /* Check for timing error: ast happened while we were doing that. */
+ if (!detect_input_pending ())
+ {
+ /* No timing error: wait for flag to be set. */
+ SYS$CANTIM (1, 0);
+ if (SYS$SETIMR (timer_ef, time, 0, 1) & 1) /* Set timer */
+ SYS$WFLOR (timer_ef, timer_eflist); /* Wait for timer expiry or input */
+ }
+ waiting_for_ast = 0;
+}
+
+/* The standard `sleep' routine works some other way
+ and it stops working if you have ever quit out of it.
+ This one continues to work. */
+
+sys_sleep (timeval)
+ int timeval;
+{
+ int time [2];
+ static int zero = 0;
+ static int large = -10000000;
+
+ LIB$EMUL (&timeval, &large, &zero, time); /* Convert to VMS format */
+
+ SYS$CANTIM (1, 0);
+ if (SYS$SETIMR (timer_ef, time, 0, 1) & 1) /* Set timer */
+ SYS$WAITFR (timer_ef); /* Wait for timer expiry only */
+}
+
+init_sigio ()
+{
+ request_sigio ();
+}
+
+reset_sigio ()
+{
+ unrequest_sigio ();
+}
+
+request_sigio ()
+{
+ croak ("request sigio");
+}
+
+unrequest_sigio ()
+{
+ croak ("unrequest sigio");
+}
+
+#endif /* VMS */
+
+/* Note that VMS compiler won't accept defined (CANNOT_DUMP). */
+#ifndef CANNOT_DUMP
+#define NEED_STARTS
+#endif
+
+#ifndef SYSTEM_MALLOC
+#ifndef NEED_STARTS
+#define NEED_STARTS
+#endif
+#endif
+
+#ifdef NEED_STARTS
+/* Some systems that cannot dump also cannot implement these. */
+
+/*
+ * Return the address of the start of the text segment prior to
+ * doing an unexec. After unexec the return value is undefined.
+ * See crt0.c for further explanation and _start.
+ *
+ */
+
+#ifndef CANNOT_UNEXEC
+char *
+start_of_text ()
+{
+#ifdef TEXT_START
+ return ((char *) TEXT_START);
+#else
+#ifdef GOULD
+ extern csrt ();
+ return ((char *) csrt);
+#else /* not GOULD */
+ extern int _start ();
+ return ((char *) _start);
+#endif /* GOULD */
+#endif /* TEXT_START */
+}
+#endif /* not CANNOT_UNEXEC */
+
+/*
+ * Return the address of the start of the data segment prior to
+ * doing an unexec. After unexec the return value is undefined.
+ * See crt0.c for further information and definition of data_start.
+ *
+ * Apparently, on BSD systems this is etext at startup. On
+ * USG systems (swapping) this is highly mmu dependent and
+ * is also dependent on whether or not the program is running
+ * with shared text. Generally there is a (possibly large)
+ * gap between end of text and start of data with shared text.
+ *
+ * On Uniplus+ systems with shared text, data starts at a
+ * fixed address. Each port (from a given oem) is generally
+ * different, and the specific value of the start of data can
+ * be obtained via the UniPlus+ specific "uvar" system call,
+ * however the method outlined in crt0.c seems to be more portable.
+ *
+ * Probably what will have to happen when a USG unexec is available,
+ * at least on UniPlus, is temacs will have to be made unshared so
+ * that text and data are contiguous. Then once loadup is complete,
+ * unexec will produce a shared executable where the data can be
+ * at the normal shared text boundry and the startofdata variable
+ * will be patched by unexec to the correct value.
+ *
+ */
+
+char *
+start_of_data ()
+{
+#ifdef DATA_START
+ return ((char *) DATA_START);
+#else
+ extern int data_start;
+ return ((char *) &data_start);
+#endif
+}
+#endif /* NEED_STARTS (not CANNOT_DUMP or not SYSTEM_MALLOC) */
+
+#ifndef CANNOT_DUMP
+/* Some systems that cannot dump also cannot implement these. */
+
+/*
+ * Return the address of the end of the text segment prior to
+ * doing an unexec. After unexec the return value is undefined.
+ */
+
+char *
+end_of_text ()
+{
+#ifdef TEXT_END
+ return ((char *) TEXT_END);
+#else
+ extern int etext;
+ return ((char *) &etext);
+#endif
+}
+
+/*
+ * Return the address of the end of the data segment prior to
+ * doing an unexec. After unexec the return value is undefined.
+ */
+
+char *
+end_of_data ()
+{
+#ifdef DATA_END
+ return ((char *) DATA_END);
+#else
+ extern int edata;
+ return ((char *) &edata);
+#endif
+}
+
+#endif /* not CANNOT_DUMP */
+
+/* Get_system_name returns as its value
+ a string for the Lisp function system-name to return. */
+
+#ifdef BSD4_1
+#include <whoami.h>
+#endif
+
+/* Can't have this within the function since `static' is #defined to
+ * nothing for some USG systems.
+ */
+#ifdef USG
+#ifdef HAVE_GETHOSTNAME
+static char get_system_name_name[256];
+#else /* not HAVE_GETHOSTNAME */
+static struct utsname get_system_name_name;
+#endif /* not HAVE_GETHOSTNAME */
+#endif /* USG */
+
+char *
+get_system_name ()
+{
+#ifdef USG
+#ifdef HAVE_GETHOSTNAME
+ gethostname (get_system_name_name, sizeof (get_system_name_name));
+ return get_system_name_name;
+#else /* not HAVE_GETHOSTNAME */
+ uname (&get_system_name_name);
+ return (get_system_name_name.nodename);
+#endif /* not HAVE_GETHOSTNAME */
+#else /* Not USG */
+#ifdef BSD4_1
+ return sysname;
+#else /* not USG, not 4.1 */
+ static char system_name_saved[32];
+#ifdef VMS
+ char *sp;
+ if ((sp = egetenv ("SYS$NODE")) == 0)
+ sp = "vax-vms";
+ else
+ {
+ char *end;
+
+ if ((end = index (sp, ':')) != 0)
+ *end = '\0';
+ }
+ strcpy (system_name_saved, sp);
+#else /* not VMS */
+ gethostname (system_name_saved, sizeof (system_name_saved));
+#endif /* not VMS */
+ return system_name_saved;
+#endif /* not USG, not 4.1 */
+#endif /* not USG */
+}
+
+#ifndef HAVE_SELECT
+
+/* Emulate as much as select as is possible under 4.1 and needed by Gnu Emacs
+ * Only checks read descriptors.
+ */
+/* How long to wait between checking fds in select */
+#define SELECT_PAUSE 1
+int select_alarmed;
+
+/* For longjmp'ing back to read_input_waiting. */
+
+jmp_buf read_alarm_throw;
+
+/* Nonzero if the alarm signal should throw back to read_input_waiting.
+ The read_socket_hook function sets this to 1 while it is waiting. */
+
+int read_alarm_should_throw;
+
+select_alarm ()
+{
+ select_alarmed = 1;
+#ifdef BSD4_1
+ sigrelse (SIGALRM);
+#else /* not BSD4_1 */
+ signal (SIGALRM, SIG_IGN);
+#endif /* not BSD4_1 */
+ if (read_alarm_should_throw)
+ longjmp (read_alarm_throw, 1);
+}
+
+/* Only rfds are checked. */
+int
+select (nfds, rfds, wfds, efds, timeout)
+ int nfds;
+ int *rfds, *wfds, *efds, *timeout;
+{
+ int ravail = 0, orfds = 0, old_alarm;
+ int timeoutval = timeout ? *timeout : 100000;
+ int *local_timeout = &timeoutval;
+ extern int kbd_count;
+ extern int proc_buffered_char[];
+#ifndef subprocesses
+ int process_tick = 0, update_tick = 0;
+#else
+ extern int process_tick, update_tick;
+#endif
+ int (*old_trap) ();
+ char buf;
+
+ if (rfds)
+ {
+ orfds = *rfds;
+ *rfds = 0;
+ }
+ if (wfds)
+ *wfds = 0;
+ if (efds)
+ *efds = 0;
+
+ /* If we are looking only for the terminal, with no timeout,
+ just read it and wait -- that's more efficient. */
+ if (orfds == 1 && (!timeout || *timeout == 100000)
+ && process_tick == update_tick)
+ {
+ if (!kbd_count)
+ read_input_waiting ();
+ *rfds = 1;
+ return 1;
+ }
+
+ /* Once a second, till the timer expires, check all the flagged read
+ * descriptors to see if any input is available. If there is some then
+ * set the corresponding bit in the return copy of rfds.
+ */
+ while (1)
+ {
+ register int to_check, bit, fd;
+
+ if (rfds)
+ {
+ for (to_check = nfds, bit = 1, fd = 0; --to_check >= 0; bit <<= 1, fd++)
+ {
+ if (orfds & bit)
+ {
+ int avail = 0, status = 0;
+
+ if (bit == 1)
+ avail = detect_input_pending (); /* Special keyboard handler */
+ else
+ {
+#ifdef FIONREAD
+ status = ioctl (fd, FIONREAD, &avail);
+#else /* no FIONREAD */
+ /* Hoping it will return -1 if nothing available
+ or 0 if all 0 chars requested are read. */
+ if (proc_buffered_char[fd] >= 0)
+ avail = 1;
+ else
+ {
+ avail = read (fd, &buf, 1);
+ if (avail > 0)
+ proc_buffered_char[fd] = buf;
+ }
+#endif /* no FIONREAD */
+ }
+ if (status >= 0 && avail > 0)
+ {
+ (*rfds) |= bit;
+ ravail++;
+ }
+ }
+ }
+ }
+ if (*local_timeout == 0 || ravail != 0 || process_tick != update_tick)
+ break;
+ old_alarm = alarm (0);
+ old_trap = (int (*)()) signal (SIGALRM, select_alarm);
+ select_alarmed = 0;
+ alarm (SELECT_PAUSE);
+ /* Wait for a SIGALRM (or maybe a SIGTINT) */
+ while (select_alarmed == 0 && *local_timeout != 0
+ && process_tick == update_tick)
+ {
+ /* If we are interested in terminal input,
+ wait by reading the terminal.
+ That makes instant wakeup for terminal input at least. */
+ if (orfds & 1)
+ {
+ read_input_waiting ();
+ if (kbd_count)
+ select_alarmed = 1;
+ }
+ else
+ pause ();
+ }
+ (*local_timeout) -= SELECT_PAUSE;
+ /* Reset the old alarm if there was one */
+ alarm (0);
+ signal (SIGALRM, old_trap);
+ if (old_alarm != 0)
+ {
+ /* Reset or forge an interrupt for the original handler. */
+ old_alarm -= SELECT_PAUSE;
+ if (old_alarm <= 0)
+ kill (getpid (), SIGALRM); /* Fake an alarm with the orig' handler */
+ else
+ alarm (old_alarm);
+ }
+ if (*local_timeout == 0) /* Stop on timer being cleared */
+ break;
+ }
+ return ravail;
+}
+
+/* Read keyboard input into the standard buffer,
+ waiting for at least one character. */
+
+/* Make all keyboard buffers much bigger when using X windows. */
+#ifdef HAVE_X_WINDOWS
+#define BUFFER_SIZE_FACTOR 16
+#else
+#define BUFFER_SIZE_FACTOR 1
+#endif
+
+read_input_waiting ()
+{
+ extern int kbd_count;
+ extern unsigned char kbd_buffer[];
+ extern unsigned char *kbd_ptr;
+ int val;
+
+ if (read_socket_hook)
+ {
+ read_alarm_should_throw = 0;
+ if (! setjmp (read_alarm_throw))
+ val = (*read_socket_hook) (0, kbd_buffer, 256 * BUFFER_SIZE_FACTOR);
+ else
+ val = -1;
+ }
+ else
+ val = read (fileno (stdin), kbd_buffer, 1);
+
+ if (val > 0)
+ {
+ kbd_ptr = kbd_buffer;
+ kbd_count = val;
+ }
+}
+
+#endif /* not HAVE_SELECT */
+
+#ifdef BSD4_1
+/* VARARGS */
+setpriority ()
+{
+ return 0;
+}
+
+/*
+ * Partially emulate 4.2 open call.
+ * open is defined as this in 4.1.
+ *
+ * - added by Michael Bloom @ Citicorp/TTI
+ *
+ */
+
+int
+sys_open (path, oflag, mode)
+ char *path;
+ int oflag, mode;
+{
+ if (oflag & O_CREAT)
+ return creat (path, mode);
+ else
+ return open (path, oflag);
+}
+
+init_sigio ()
+{
+ if (noninteractive)
+ return;
+ lmode = LINTRUP | lmode;
+ ioctl (0, TIOCLSET, &lmode);
+}
+
+reset_sigio ()
+{
+ if (noninteractive)
+ return;
+ lmode = ~LINTRUP & lmode;
+ ioctl (0, TIOCLSET, &lmode);
+}
+
+request_sigio ()
+{
+ sigrelse (SIGTINT);
+
+ interrupts_deferred = 0;
+}
+
+unrequest_sigio ()
+{
+ sighold (SIGTINT);
+
+ interrupts_deferred = 1;
+}
+
+/* still inside #ifdef BSD4_1 */
+#ifdef subprocesses
+
+int sigheld; /* Mask of held signals */
+
+sigholdx (signum)
+ int signum;
+{
+ sigheld |= sigbit (signum);
+ sighold (signum);
+}
+
+sigisheld (signum)
+ int signum;
+{
+ sigheld |= sigbit (signum);
+}
+
+sigunhold (signum)
+ int signum;
+{
+ sigheld &= ~sigbit (signum);
+ sigrelse (signum);
+}
+
+sigfree () /* Free all held signals */
+{
+ int i;
+ for (i = 0; i < NSIG; i++)
+ if (sigheld & sigbit (i))
+ sigrelse (i);
+ sigheld = 0;
+}
+
+sigbit (i)
+{
+ return 1 << (i - 1);
+}
+#endif /* subprocesses */
+#endif /* BSD4_1 */
+
+/* POSIX signals support - DJB */
+/* Anyone with POSIX signals should have ANSI C declarations */
+
+#ifdef POSIX_SIGNALS
+
+sigset_t signal_empty_mask, signal_full_mask;
+static struct sigaction new_action, old_action;
+
+init_signals ()
+{
+#ifdef POSIX_SIGNALS
+ sigemptyset (&signal_empty_mask);
+ sigfillset (&signal_full_mask);
+#endif
+}
+
+typedef int (*signal_handler_t) ();
+
+signal_handler_t
+sys_signal (int signal_number, signal_handler_t action)
+{
+#ifdef DGUX
+ /* This gets us restartable system calls for efficiency.
+ The "else" code will works as well. */
+ return (berk_signal (signal_number, action));
+#else
+ sigemptyset (&new_action.sa_mask);
+ new_action.sa_handler = action;
+ new_action.sa_flags = NULL;
+ sigaction (signal_number, &new_action, &old_action);
+ return (old_action.sa_handler);
+#endif /* DGUX */
+}
+
+int
+sys_sigpause (sigset_t new_mask)
+{
+ /* pause emulating berk sigpause... */
+ sigsuspend (&new_mask);
+ return (EINTR);
+}
+
+/* I'd like to have these guys return pointers to the mask storage in here,
+ but there'd be trouble if the code was saving multiple masks. I'll be
+ safe and pass the structure. It normally won't be more than 2 bytes
+ anyhow. - DJB */
+
+sigset_t
+sys_sigblock (sigset_t new_mask)
+{
+ sigset_t old_mask;
+ sigprocmask (SIG_BLOCK, &new_mask, &old_mask);
+ return (old_mask);
+}
+
+sigset_t
+sys_sigunblock (sigset_t new_mask)
+{
+ sigset_t old_mask;
+ sigprocmask (SIG_UNBLOCK, &new_mask, &old_mask);
+ return (old_mask);
+}
+
+sigset_t
+sys_sigsetmask (sigset_t new_mask)
+{
+ sigset_t old_mask;
+ sigprocmask (SIG_SETMASK, &new_mask, &old_mask);
+ return (old_mask);
+}
+
+#endif /* POSIX_SIGNALS */
+
+#ifndef BSTRING
+
+void
+bzero (b, length)
+ register char *b;
+ register int length;
+{
+#ifdef VMS
+ short zero = 0;
+ long max_str = 65535;
+
+ while (length > max_str) {
+ (void) LIB$MOVC5 (&zero, &zero, &zero, &max_str, b);
+ length -= max_str;
+ b += max_str;
+ }
+ max_str = length;
+ (void) LIB$MOVC5 (&zero, &zero, &zero, &max_str, b);
+#else
+ while (length-- > 0)
+ *b++ = 0;
+#endif /* not VMS */
+}
+
+/* Saying `void' requires a declaration, above, where bcopy is used
+ and that declaration causes pain for systems where bcopy is a macro. */
+bcopy (b1, b2, length)
+ register char *b1;
+ register char *b2;
+ register int length;
+{
+#ifdef VMS
+ long max_str = 65535;
+
+ while (length > max_str) {
+ (void) LIB$MOVC3 (&max_str, b1, b2);
+ length -= max_str;
+ b1 += max_str;
+ b2 += max_str;
+ }
+ max_str = length;
+ (void) LIB$MOVC3 (&max_str, b1, b2);
+#else
+ while (length-- > 0)
+ *b2++ = *b1++;
+#endif /* not VMS */
+}
+
+int
+bcmp (b1, b2, length) /* This could be a macro! */
+ register char *b1;
+ register char *b2;
+ register int length;
+{
+#ifdef VMS
+ struct dsc$descriptor_s src1 = {length, DSC$K_DTYPE_T, DSC$K_CLASS_S, b1};
+ struct dsc$descriptor_s src2 = {length, DSC$K_DTYPE_T, DSC$K_CLASS_S, b2};
+
+ return STR$COMPARE (&src1, &src2);
+#else
+ while (length-- > 0)
+ if (*b1++ != *b2++)
+ return 1;
+
+ return 0;
+#endif /* not VMS */
+}
+#endif /* not BSTRING */
+
+#ifdef BSD4_1
+long random ()
+{
+ return (rand ());
+}
+
+srandom (arg)
+ int arg;
+{
+ srand (arg);
+}
+#endif /* BSD4_1 */
+
+#ifdef HPUX
+#ifdef X11
+#define HAVE_RANDOM
+#endif
+#endif
+
+#ifdef USG
+#ifndef HAVE_RANDOM
+/*
+ * The BSD random returns numbers in the range of
+ * 0 to 2e31 - 1. The USG rand(3C) returns numbers in the
+ * range of 0 to 2e15 - 1. This is probably not significant
+ * in this usage.
+ */
+
+long
+random ()
+{
+ /* Arrange to return a range centered on zero. */
+ return rand () - (1 << 14);
+}
+
+srandom (arg)
+ int arg;
+{
+ srand (arg);
+}
+
+#endif /* HAVE_RANDOM */
+#endif /* USG */
+
+
+#ifdef VMS
+
+#ifdef getenv
+/* If any place else asks for the TERM variable,
+ allow it to be overridden with the EMACS_TERM variable
+ before attempting to translate the logical name TERM. As a last
+ resort, ask for VAX C's special idea of the TERM variable. */
+#undef getenv
+char *
+sys_getenv (name)
+ char *name;
+{
+ register char *val;
+ static char buf[256];
+ static struct dsc$descriptor_s equiv
+ = {sizeof (buf), DSC$K_DTYPE_T, DSC$K_CLASS_S, buf};
+ static struct dsc$descriptor_s d_name
+ = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0};
+ short eqlen;
+
+ if (!strcmp (name, "TERM"))
+ {
+ val = (char *) getenv ("EMACS_TERM");
+ if (val)
+ return val;
+ }
+
+ d_name.dsc$w_length = strlen (name);
+ d_name.dsc$a_pointer = name;
+ if (lib$sys_trnlog (&d_name, &eqlen, &equiv) == 1)
+ {
+ char *str = (char *) xmalloc (eqlen + 1);
+ bcopy (buf, str, eqlen);
+ str[eqlen] = '\0';
+ /* This is a storage leak, but a pain to fix. With luck,
+ no one will ever notice. */
+ return str;
+ }
+ return (char *) getenv (name);
+}
+#endif /* getenv */
+
+#ifdef abort
+/* Since VMS doesn't believe in core dumps, the only way to debug this beast is
+ to force a call on the debugger from within the image. */
+#undef abort
+sys_abort ()
+{
+ reset_sys_modes ();
+ LIB$SIGNAL (SS$_DEBUG);
+}
+#endif /* abort */
+#endif /* VMS */
+
+#ifdef VMS
+#ifdef LINK_CRTL_SHARE
+#ifdef SHAREABLE_LIB_BUG
+/* Variables declared noshare and initialized in shareable libraries
+ cannot be shared. The VMS linker incorrectly forces you to use a private
+ version which is uninitialized... If not for this "feature", we
+ could use the C library definition of sys_nerr and sys_errlist. */
+int sys_nerr = 35;
+char *sys_errlist[] =
+ {
+ "error 0",
+ "not owner",
+ "no such file or directory",
+ "no such process",
+ "interrupted system call",
+ "i/o error",
+ "no such device or address",
+ "argument list too long",
+ "exec format error",
+ "bad file number",
+ "no child process",
+ "no more processes",
+ "not enough memory",
+ "permission denied",
+ "bad address",
+ "block device required",
+ "mount devices busy",
+ "file exists",
+ "cross-device link",
+ "no such device",
+ "not a directory",
+ "is a directory",
+ "invalid argument",
+ "file table overflow",
+ "too many open files",
+ "not a typewriter",
+ "text file busy",
+ "file too big",
+ "no space left on device",
+ "illegal seek",
+ "read-only file system",
+ "too many links",
+ "broken pipe",
+ "math argument",
+ "result too large",
+ "I/O stream empty",
+ "vax/vms specific error code nontranslatable error"
+ };
+#endif /* SHAREABLE_LIB_BUG */
+#endif /* LINK_CRTL_SHARE */
+#endif /* VMS */
+
+#ifdef INTERRUPTABLE_OPEN
+
+int
+/* VARARGS 2 */
+sys_open (path, oflag, mode)
+ char *path;
+ int oflag, mode;
+{
+ register int rtnval;
+
+ while ((rtnval = open (path, oflag, mode)) == -1
+ && (errno == EINTR));
+ return (rtnval);
+}
+
+#endif /* INTERRUPTABLE_OPEN */
+
+#ifdef INTERRUPTABLE_CLOSE
+
+sys_close (fd)
+ int fd;
+{
+ register int rtnval;
+
+ while ((rtnval = close (fd)) == -1
+ && (errno == EINTR));
+ return rtnval;
+}
+
+#endif /* INTERRUPTABLE_CLOSE */
+
+#ifdef INTERRUPTABLE_IO
+
+int
+sys_read (fildes, buf, nbyte)
+ int fildes;
+ char *buf;
+ unsigned int nbyte;
+{
+ register int rtnval;
+
+ while ((rtnval = read (fildes, buf, nbyte)) == -1
+ && (errno == EINTR));
+ return (rtnval);
+}
+
+int
+sys_write (fildes, buf, nbyte)
+ int fildes;
+ char *buf;
+ unsigned int nbyte;
+{
+ register int rtnval;
+
+ while ((rtnval = write (fildes, buf, nbyte)) == -1
+ && (errno == EINTR));
+ return (rtnval);
+}
+
+#endif /* INTERRUPTABLE_IO */
+
+#ifdef USG
+/*
+ * All of the following are for USG.
+ *
+ * On USG systems the system calls are interruptable by signals
+ * that the user program has elected to catch. Thus the system call
+ * must be retried in these cases. To handle this without massive
+ * changes in the source code, we remap the standard system call names
+ * to names for our own functions in sysdep.c that do the system call
+ * with retries. Actually, for portability reasons, it is good
+ * programming practice, as this example shows, to limit all actual
+ * system calls to a single occurance in the source. Sure, this
+ * adds an extra level of function call overhead but it is almost
+ * always negligible. Fred Fish, Unisoft Systems Inc.
+ */
+
+char *sys_siglist[NSIG + 1] =
+{
+#ifdef AIX
+/* AIX has changed the signals a bit */
+ "bogus signal", /* 0 */
+ "hangup", /* 1 SIGHUP */
+ "interrupt", /* 2 SIGINT */
+ "quit", /* 3 SIGQUIT */
+ "illegal instruction", /* 4 SIGILL */
+ "trace trap", /* 5 SIGTRAP */
+ "IOT instruction", /* 6 SIGIOT */
+ "crash likely", /* 7 SIGDANGER */
+ "floating point exception", /* 8 SIGFPE */
+ "kill", /* 9 SIGKILL */
+ "bus error", /* 10 SIGBUS */
+ "segmentation violation", /* 11 SIGSEGV */
+ "bad argument to system call", /* 12 SIGSYS */
+ "write on a pipe with no one to read it", /* 13 SIGPIPE */
+ "alarm clock", /* 14 SIGALRM */
+ "software termination signum", /* 15 SIGTERM */
+ "user defined signal 1", /* 16 SIGUSR1 */
+ "user defined signal 2", /* 17 SIGUSR2 */
+ "death of a child", /* 18 SIGCLD */
+ "power-fail restart", /* 19 SIGPWR */
+ "bogus signal", /* 20 */
+ "bogus signal", /* 21 */
+ "bogus signal", /* 22 */
+ "bogus signal", /* 23 */
+ "bogus signal", /* 24 */
+ "LAN I/O interrupt", /* 25 SIGAIO */
+ "PTY I/O interrupt", /* 26 SIGPTY */
+ "I/O intervention required", /* 27 SIGIOINT */
+ "HFT grant", /* 28 SIGGRANT */
+ "HFT retract", /* 29 SIGRETRACT */
+ "HFT sound done", /* 30 SIGSOUND */
+ "HFT input ready", /* 31 SIGMSG */
+#else /* not AIX */
+ "bogus signal", /* 0 */
+ "hangup", /* 1 SIGHUP */
+ "interrupt", /* 2 SIGINT */
+ "quit", /* 3 SIGQUIT */
+ "illegal instruction", /* 4 SIGILL */
+ "trace trap", /* 5 SIGTRAP */
+ "IOT instruction", /* 6 SIGIOT */
+ "EMT instruction", /* 7 SIGEMT */
+ "floating point exception", /* 8 SIGFPE */
+ "kill", /* 9 SIGKILL */
+ "bus error", /* 10 SIGBUS */
+ "segmentation violation", /* 11 SIGSEGV */
+ "bad argument to system call", /* 12 SIGSYS */
+ "write on a pipe with no one to read it", /* 13 SIGPIPE */
+ "alarm clock", /* 14 SIGALRM */
+ "software termination signum", /* 15 SIGTERM */
+ "user defined signal 1", /* 16 SIGUSR1 */
+ "user defined signal 2", /* 17 SIGUSR2 */
+ "death of a child", /* 18 SIGCLD */
+ "power-fail restart", /* 19 SIGPWR */
+#endif /* not AIX */
+ 0
+ };
+
+/*
+ * Warning, this function may not duplicate 4.2 action properly
+ * under error conditions.
+ */
+
+#ifndef MAXPATHLEN
+/* In 4.1, param.h fails to define this. */
+#define MAXPATHLEN 1024
+#endif
+
+#ifndef HAVE_GETWD
+
+char *
+getwd (pathname)
+ char *pathname;
+{
+ char *npath, *spath;
+ extern char *getcwd ();
+
+ spath = npath = getcwd ((char *) 0, MAXPATHLEN);
+ /* On Altos 3068, getcwd can return @hostname/dir, so discard
+ up to first slash. Should be harmless on other systems. */
+ while (*npath && *npath != '/')
+ npath++;
+ strcpy (pathname, npath);
+ free (spath); /* getcwd uses malloc */
+ return pathname;
+}
+
+#endif /* not HAVE_GETWD */
+
+#ifndef HAVE_RENAME
+
+/*
+ * Emulate rename using unlink/link. Note that this is
+ * only partially correct. Also, doesn't enforce restriction
+ * that files be of same type (regular->regular, dir->dir, etc).
+ */
+
+rename (from, to)
+#ifdef __STDC__ /* Avoid error if system has proper ANSI prototype. */
+ const char *from;
+ const char *to;
+#else
+ char *from;
+ char *to;
+#endif
+{
+ if (access (from, 0) == 0)
+ {
+ unlink (to);
+ if (link (from, to) == 0)
+ if (unlink (from) == 0)
+ return (0);
+ }
+ return (-1);
+}
+#endif /* not HAVE_RENAME */
+
+/* VARARGS */
+setpriority ()
+{
+ return (0);
+}
+
+#ifndef HAVE_VFORK
+
+/*
+ * Substitute fork(2) for vfork(2) on USG flavors.
+ */
+
+vfork ()
+{
+ return (fork ());
+}
+
+#endif /* not HAVE_VFORK */
+
+#ifdef MISSING_UTIMES
+
+/* HPUX (among others) sets HAVE_TIMEVAL but does not implement utimes. */
+
+utimes ()
+{
+}
+#endif
+
+#ifdef IRIS_UTIME
+
+/* The IRIS (3.5) has timevals, but uses sys V utime, and doesn't have the
+ utimbuf structure defined anywhere but in the man page. */
+
+struct utimbuf
+ {
+ long actime;
+ long modtime;
+ };
+
+utimes (name, tvp)
+ char *name;
+ struct timeval tvp[];
+{
+ struct utimbuf utb;
+ utb.actime = tvp[0].tv_sec;
+ utb.modtime = tvp[1].tv_sec;
+ utime (name, &utb);
+}
+#endif /* IRIS_UTIME */
+
+
+#if 0
+#ifdef HPUX
+
+/* HPUX curses library references perror, but as far as we know
+ it won't be called. Anyway this definition will do for now. */
+
+perror ()
+{
+}
+
+#endif /* HPUX */
+#endif /* 0 */
+
+#ifndef HAVE_DUP2
+
+/*
+ * Emulate BSD dup2(2). First close newd if it already exists.
+ * Then, attempt to dup oldd. If not successful, call dup2 recursively
+ * until we are, then close the unsuccessful ones.
+ */
+
+dup2 (oldd, newd)
+ int oldd;
+ int newd;
+{
+ register int fd, ret;
+
+ sys_close (newd);
+
+#ifdef F_DUPFD
+ fd = fcntl (oldd, F_DUPFD, newd);
+ if (fd != newd)
+ error ("cant dup2 (%i,%i) : %s", oldd, newd, sys_errlist[errno]);
+#else
+ fd = dup (old);
+ if (fd == -1)
+ return -1;
+ if (fd == new)
+ return new;
+ ret = dup2 (old,new);
+ sys_close (fd);
+ return ret;
+#endif
+}
+
+#endif /* not HAVE_DUP2 */
+
+/*
+ * Gettimeofday. Simulate as much as possible. Only accurate
+ * to nearest second. Emacs doesn't use tzp so ignore it for now.
+ * Only needed when subprocesses are defined.
+ */
+
+#ifdef subprocesses
+#ifndef HAVE_GETTIMEOFDAY
+#ifdef HAVE_TIMEVAL
+
+/* ARGSUSED */
+gettimeofday (tp, tzp)
+ struct timeval *tp;
+ struct timezone *tzp;
+{
+ extern long time ();
+
+ tp->tv_sec = time ((long *)0);
+ tp->tv_usec = 0;
+}
+
+#endif
+#endif
+#endif /* subprocess && !HAVE_GETTIMEOFDAY && HAVE_TIMEVAL */
+
+/*
+ * This function will go away as soon as all the stubs fixed. (fnf)
+ */
+
+croak (badfunc)
+ char *badfunc;
+{
+ printf ("%s not yet implemented\r\n", badfunc);
+ reset_sys_modes ();
+ exit (1);
+}
+
+#endif /* USG */
+
+#ifdef DGUX
+
+char *sys_siglist[NSIG + 1] =
+{
+ "null signal", /* 0 SIGNULL */
+ "hangup", /* 1 SIGHUP */
+ "interrupt", /* 2 SIGINT */
+ "quit", /* 3 SIGQUIT */
+ "illegal instruction", /* 4 SIGILL */
+ "trace trap", /* 5 SIGTRAP */
+ "abort termination", /* 6 SIGABRT */
+ "SIGEMT", /* 7 SIGEMT */
+ "floating point exception", /* 8 SIGFPE */
+ "kill", /* 9 SIGKILL */
+ "bus error", /* 10 SIGBUS */
+ "segmentation violation", /* 11 SIGSEGV */
+ "bad argument to system call", /* 12 SIGSYS */
+ "write on a pipe with no reader", /* 13 SIGPIPE */
+ "alarm clock", /* 14 SIGALRM */
+ "software termination signal", /* 15 SIGTERM */
+ "user defined signal 1", /* 16 SIGUSR1 */
+ "user defined signal 2", /* 17 SIGUSR2 */
+ "child stopped or terminated", /* 18 SIGCLD */
+ "power-fail restart", /* 19 SIGPWR */
+ "window size changed", /* 20 SIGWINCH */
+ "undefined", /* 21 */
+ "pollable event occured", /* 22 SIGPOLL */
+ "sendable stop signal not from tty", /* 23 SIGSTOP */
+ "stop signal from tty", /* 24 SIGSTP */
+ "continue a stopped process", /* 25 SIGCONT */
+ "attempted background tty read", /* 26 SIGTTIN */
+ "attempted background tty write", /* 27 SIGTTOU */
+ "undefined", /* 28 */
+ "undefined", /* 29 */
+ "undefined", /* 30 */
+ "undefined", /* 31 */
+ "undefined", /* 32 */
+ "socket (TCP/IP) urgent data arrival", /* 33 SIGURG */
+ "I/O is possible", /* 34 SIGIO */
+ "exceeded cpu time limit", /* 35 SIGXCPU */
+ "exceeded file size limit", /* 36 SIGXFSZ */
+ "virtual time alarm", /* 37 SIGVTALRM */
+ "profiling time alarm", /* 38 SIGPROF */
+ "undefined", /* 39 */
+ "file record locks revoked", /* 40 SIGLOST */
+ "undefined", /* 41 */
+ "undefined", /* 42 */
+ "undefined", /* 43 */
+ "undefined", /* 44 */
+ "undefined", /* 45 */
+ "undefined", /* 46 */
+ "undefined", /* 47 */
+ "undefined", /* 48 */
+ "undefined", /* 49 */
+ "undefined", /* 50 */
+ "undefined", /* 51 */
+ "undefined", /* 52 */
+ "undefined", /* 53 */
+ "undefined", /* 54 */
+ "undefined", /* 55 */
+ "undefined", /* 56 */
+ "undefined", /* 57 */
+ "undefined", /* 58 */
+ "undefined", /* 59 */
+ "undefined", /* 60 */
+ "undefined", /* 61 */
+ "undefined", /* 62 */
+ "undefined", /* 63 */
+ "notification message in mess. queue", /* 64 SIGDGNOTIFY */
+ 0
+};
+
+#endif /* DGUX */
+
+/* Directory routines for systems that don't have them. */
+
+#ifdef SYSV_SYSTEM_DIR
+
+#include <dirent.h>
+
+#ifndef HAVE_CLOSEDIR
+int
+closedir (dirp)
+ register DIR *dirp; /* stream from opendir */
+{
+ sys_close (dirp->dd_fd);
+ free ((char *) dirp->dd_buf); /* directory block defined in <dirent.h> */
+ free ((char *) dirp);
+}
+#endif /* not HAVE_CLOSEDIR */
+
+#endif /* SYSV_SYSTEM_DIR */
+
+#ifdef NONSYSTEM_DIR_LIBRARY
+
+DIR *
+opendir (filename)
+ char *filename; /* name of directory */
+{
+ register DIR *dirp; /* -> malloc'ed storage */
+ register int fd; /* file descriptor for read */
+ struct stat sbuf; /* result of fstat() */
+
+ fd = sys_open (filename, 0);
+ if (fd < 0)
+ return 0;
+
+ if (fstat (fd, &sbuf) < 0
+ || (sbuf.st_mode & S_IFMT) != S_IFDIR
+ || (dirp = (DIR *) malloc (sizeof (DIR))) == 0)
+ {
+ sys_close (fd);
+ return 0; /* bad luck today */
+ }
+
+ dirp->dd_fd = fd;
+ dirp->dd_loc = dirp->dd_size = 0; /* refill needed */
+
+ return dirp;
+}
+
+void
+closedir (dirp)
+ register DIR *dirp; /* stream from opendir() */
+{
+ sys_close (dirp->dd_fd);
+ free ((char *) dirp);
+}
+
+
+#ifndef VMS
+#define DIRSIZ 14
+struct olddir
+ {
+ ino_t od_ino; /* inode */
+ char od_name[DIRSIZ]; /* filename */
+ };
+#endif /* not VMS */
+
+struct direct dir_static; /* simulated directory contents */
+
+/* ARGUSED */
+struct direct *
+readdir (dirp)
+ register DIR *dirp; /* stream from opendir() */
+{
+#ifndef VMS
+ register struct olddir *dp; /* -> directory data */
+#else /* VMS */
+ register struct dir$_name *dp; /* -> directory data */
+ register struct dir$_version *dv; /* -> version data */
+#endif /* VMS */
+
+ for (; ;)
+ {
+ if (dirp->dd_loc >= dirp->dd_size)
+ dirp->dd_loc = dirp->dd_size = 0;
+
+ if (dirp->dd_size == 0 /* refill buffer */
+ && (dirp->dd_size = sys_read (dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ)) <= 0)
+ return 0;
+
+#ifndef VMS
+ dp = (struct olddir *) &dirp->dd_buf[dirp->dd_loc];
+ dirp->dd_loc += sizeof (struct olddir);
+
+ if (dp->od_ino != 0) /* not deleted entry */
+ {
+ dir_static.d_ino = dp->od_ino;
+ strncpy (dir_static.d_name, dp->od_name, DIRSIZ);
+ dir_static.d_name[DIRSIZ] = '\0';
+ dir_static.d_namlen = strlen (dir_static.d_name);
+ dir_static.d_reclen = sizeof (struct direct)
+ - MAXNAMLEN + 3
+ + dir_static.d_namlen - dir_static.d_namlen % 4;
+ return &dir_static; /* -> simulated structure */
+ }
+#else /* VMS */
+ dp = (struct dir$_name *) dirp->dd_buf;
+ if (dirp->dd_loc == 0)
+ dirp->dd_loc = (dp->dir$b_namecount&1) ? dp->dir$b_namecount + 1
+ : dp->dir$b_namecount;
+ dv = (struct dir$_version *)&dp->dir$t_name[dirp->dd_loc];
+ dir_static.d_ino = dv->dir$w_fid_num;
+ dir_static.d_namlen = dp->dir$b_namecount;
+ dir_static.d_reclen = sizeof (struct direct)
+ - MAXNAMLEN + 3
+ + dir_static.d_namlen - dir_static.d_namlen % 4;
+ strncpy (dir_static.d_name, dp->dir$t_name, dp->dir$b_namecount);
+ dir_static.d_name[dir_static.d_namlen] = '\0';
+ dirp->dd_loc = dirp->dd_size; /* only one record at a time */
+ return &dir_static;
+#endif /* VMS */
+ }
+}
+
+#ifdef VMS
+/* readdirver is just like readdir except it returns all versions of a file
+ as separate entries. */
+
+/* ARGUSED */
+struct direct *
+readdirver (dirp)
+ register DIR *dirp; /* stream from opendir() */
+{
+ register struct dir$_name *dp; /* -> directory data */
+ register struct dir$_version *dv; /* -> version data */
+
+ if (dirp->dd_loc >= dirp->dd_size - sizeof (struct dir$_name))
+ dirp->dd_loc = dirp->dd_size = 0;
+
+ if (dirp->dd_size == 0 /* refill buffer */
+ && (dirp->dd_size = sys_read (dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ)) <= 0)
+ return 0;
+
+ dp = (struct dir$_name *) dirp->dd_buf;
+ if (dirp->dd_loc == 0)
+ dirp->dd_loc = (dp->dir$b_namecount & 1) ? dp->dir$b_namecount + 1
+ : dp->dir$b_namecount;
+ dv = (struct dir$_version *) &dp->dir$t_name[dirp->dd_loc];
+ strncpy (dir_static.d_name, dp->dir$t_name, dp->dir$b_namecount);
+ sprintf (&dir_static.d_name[dp->dir$b_namecount], ";%d", dv->dir$w_version);
+ dir_static.d_namlen = strlen (dir_static.d_name);
+ dir_static.d_ino = dv->dir$w_fid_num;
+ dir_static.d_reclen = sizeof (struct direct) - MAXNAMLEN + 3
+ + dir_static.d_namlen - dir_static.d_namlen % 4;
+ dirp->dd_loc = ((char *) (++dv) - dp->dir$t_name);
+ return &dir_static;
+}
+
+#endif /* VMS */
+
+#endif /* NONSYSTEM_DIR_LIBRARY */
+
+/* Functions for VMS */
+#ifdef VMS
+#include "vms-pwd.h"
+#include <acldef.h>
+#include <chpdef.h>
+#include <jpidef.h>
+
+/* Return as a string the VMS error string pertaining to STATUS.
+ Reuses the same static buffer each time it is called. */
+
+char *
+vmserrstr (status)
+ int status; /* VMS status code */
+{
+ int bufadr[2];
+ short len;
+ static char buf[257];
+
+ bufadr[0] = sizeof buf - 1;
+ bufadr[1] = (int) buf;
+ if (! (SYS$GETMSG (status, &len, bufadr, 0x1, 0) & 1))
+ return "untranslatable VMS error status";
+ buf[len] = '\0';
+ return buf;
+}
+
+#ifdef access
+#undef access
+
+/* The following is necessary because 'access' emulation by VMS C (2.0) does
+ * not work correctly. (It also doesn't work well in version 2.3.)
+ */
+
+#ifdef VMS4_4
+
+#define DESCRIPTOR(name,string) struct dsc$descriptor_s name = \
+ { strlen (string), DSC$K_DTYPE_T, DSC$K_CLASS_S, string }
+
+typedef union {
+ struct {
+ unsigned short s_buflen;
+ unsigned short s_code;
+ char *s_bufadr;
+ unsigned short *s_retlenadr;
+ } s;
+ int end;
+} item;
+
+#define ITEMSETUP(CODE,VAR,RETLEN) \
+ itemlst[cnt].s.s_buflen = sizeof (VAR); \
+ itemlst[cnt].s.s_code = CODE; \
+ itemlst[cnt].s.s_bufadr = (char *) &VAR; \
+ itemlst[cnt++].s.s_retlenadr = (unsigned short *) &RETLEN
+
+#define R_OK 4 /* test for read permission */
+#define W_OK 2 /* test for write permission */
+#define X_OK 1 /* test for execute (search) permission */
+#define F_OK 0 /* test for presence of file */
+
+int
+sys_access (path, mode)
+ char *path;
+ int mode;
+{
+ static char *user = NULL;
+ char dir_fn[512];
+
+ /* translate possible directory spec into .DIR file name, so brain-dead
+ * access() can treat the directory like a file. */
+ if (directory_file_name (path, dir_fn))
+ path = dir_fn;
+
+ if (mode == F_OK)
+ return access (path, mode);
+ if (user == NULL && (user = (char *) getenv ("USER")) == NULL)
+ return -1;
+ {
+ int stat;
+ int flags;
+ int acces;
+ int dummy;
+ int cnt;
+ int prvmask[2];
+ item itemlst[8];
+ struct FAB fab;
+ struct XABPRO xab;
+ char *aclbuf;
+
+ flags = 0;
+ acces = 0;
+ if ((mode & X_OK) && ((stat = access(path, mode)) < 0 || mode == X_OK))
+ return stat;
+ if (mode & R_OK)
+ flags |= CHP$M_READ;
+ if (mode & W_OK)
+ flags |= CHP$M_WRITE;
+
+ acces = flags;
+
+ /* Find privilege bits */
+ stat = sys$setprv (0, 0, 0, prvmask);
+
+ /* Open the file, and find the particulars. */
+ fab = cc$rms_fab;
+ fab.fab$b_fac = FAB$M_GET;
+ fab.fab$l_fna = path;
+ fab.fab$b_fns = strlen (path);
+ fab.fab$l_xab = (char*) &xab;
+ xab = cc$rms_xabpro;
+ xab.xab$l_aclbuf = (char*) alloca(60); /* Use 60 initially */;
+ xab.xab$w_aclsiz = 60;
+ stat = sys$open (&fab, 0, 0);
+ if (! (stat & 1))
+ return -1;
+ /* If ACL was not empty (2512) and error occurred, then deny access. */
+ if ((xab.xab$l_aclsts != 2512) && (! (xab.xab$l_aclsts & 1)))
+ return -1;
+ sys$close (&fab, 0, 0);
+
+ /* See if we allocated enough space for the ACL. If not, create a larger
+ buffer (now that we now know the actual size), and do it again. */
+
+ if(xab.xab$w_acllen > xab.xab$w_aclsiz){
+ xab.xab$l_aclbuf = (char *) alloca(xab.xab$w_acllen);
+ xab.xab$w_aclsiz = xab.xab$w_acllen;
+ xab.xab$l_aclctx = 0;
+ stat = sys$open (&fab, 0, 0);
+ if (! (stat & 1))
+ return -1;
+ sys$close (&fab, 0, 0);
+ };
+ cnt=0;
+ ITEMSETUP(CHP$_OWNER,xab.xab$l_uic,dummy);
+ ITEMSETUP(CHP$_PROT,xab.xab$w_pro,dummy);
+ ITEMSETUP(CHP$_ACCESS,acces,dummy);
+ ITEMSETUP(CHP$_FLAGS,flags,dummy);
+
+ if (xab.xab$w_acllen != 0)
+ {
+ itemlst[cnt].s.s_buflen = xab.xab$w_acllen;
+ itemlst[cnt].s.s_code = CHP$_ACL;
+ itemlst[cnt].s.s_bufadr = xab.xab$l_aclbuf;
+ itemlst[cnt++].s.s_retlenadr = (unsigned short *) &dummy;
+ };
+
+ ITEMSETUP(CHP$_PRIV,prvmask,dummy);
+ /* ITEMSETUP(CHP$_PRIVUSED,pused,pusedl); For diagnostic purposes only */
+ itemlst[cnt].s.s_buflen = 0;
+ itemlst[cnt].s.s_code = CHP$_END;
+
+ /* SYS$CHECK_ACCESS can get privileges wrong. SYS$CHKPRO will not. */
+ stat = SYS$CHKPRO(itemlst);
+ return stat == SS$_NORMAL ? 0 : -1;
+ }
+}
+
+#else /* not VMS4_4 */
+
+#include <prvdef.h>
+#define ACE$M_WRITE 2
+#define ACE$C_KEYID 1
+
+static unsigned short memid, grpid;
+static unsigned int uic;
+
+/* Called from init_sys_modes, so it happens not very often
+ but at least each time Emacs is loaded. */
+sys_access_reinit ()
+{
+ uic = 0;
+}
+
+int
+sys_access (filename, type)
+ char * filename;
+ int type;
+{
+ struct FAB fab;
+ struct XABPRO xab;
+ int status, size, i, typecode, acl_controlled;
+ unsigned int *aclptr, *aclend, aclbuf[60];
+ union prvdef prvmask;
+
+ /* Get UIC and GRP values for protection checking. */
+ if (uic == 0)
+ {
+ status = LIB$GETJPI (&JPI$_UIC, 0, 0, &uic, 0, 0);
+ if (! (status & 1))
+ return -1;
+ memid = uic & 0xFFFF;
+ grpid = uic >> 16;
+ }
+
+ if (type != 2) /* not checking write access */
+ return access (filename, type);
+
+ /* Check write protection. */
+
+#define CHECKPRIV(bit) (prvmask.bit)
+#define WRITEABLE(field) (! ((xab.xab$w_pro >> field) & XAB$M_NOWRITE))
+
+ /* Find privilege bits */
+ status = sys$setprv (0, 0, 0, prvmask);
+ if (! (status & 1))
+ error ("Unable to find privileges: %s", vmserrstr (status));
+ if (CHECKPRIV (PRV$V_BYPASS))
+ return 0; /* BYPASS enabled */
+ fab = cc$rms_fab;
+ fab.fab$b_fac = FAB$M_GET;
+ fab.fab$l_fna = filename;
+ fab.fab$b_fns = strlen (filename);
+ fab.fab$l_xab = &xab;
+ xab = cc$rms_xabpro;
+ xab.xab$l_aclbuf = aclbuf;
+ xab.xab$w_aclsiz = sizeof (aclbuf);
+ status = sys$open (&fab, 0, 0);
+ if (! (status & 1))
+ return -1;
+ sys$close (&fab, 0, 0);
+ /* Check system access */
+ if (CHECKPRIV (PRV$V_SYSPRV) && WRITEABLE (XAB$V_SYS))
+ return 0;
+ /* Check ACL entries, if any */
+ acl_controlled = 0;
+ if (xab.xab$w_acllen > 0)
+ {
+ aclptr = aclbuf;
+ aclend = &aclbuf[xab.xab$w_acllen / 4];
+ while (*aclptr && aclptr < aclend)
+ {
+ size = (*aclptr & 0xff) / 4;
+ typecode = (*aclptr >> 8) & 0xff;
+ if (typecode == ACE$C_KEYID)
+ for (i = size - 1; i > 1; i--)
+ if (aclptr[i] == uic)
+ {
+ acl_controlled = 1;
+ if (aclptr[1] & ACE$M_WRITE)
+ return 0; /* Write access through ACL */
+ }
+ aclptr = &aclptr[size];
+ }
+ if (acl_controlled) /* ACL specified, prohibits write access */
+ return -1;
+ }
+ /* No ACL entries specified, check normal protection */
+ if (WRITEABLE (XAB$V_WLD)) /* World writeable */
+ return 0;
+ if (WRITEABLE (XAB$V_GRP) &&
+ (unsigned short) (xab.xab$l_uic >> 16) == grpid)
+ return 0; /* Group writeable */
+ if (WRITEABLE (XAB$V_OWN) &&
+ (xab.xab$l_uic & 0xFFFF) == memid)
+ return 0; /* Owner writeable */
+
+ return -1; /* Not writeable */
+}
+#endif /* not VMS4_4 */
+#endif /* access */
+
+static char vtbuf[NAM$C_MAXRSS+1];
+
+/* translate a vms file spec to a unix path */
+char *
+sys_translate_vms (vfile)
+ char * vfile;
+{
+ char * p;
+ char * targ;
+
+ if (!vfile)
+ return 0;
+
+ targ = vtbuf;
+
+ /* leading device or logical name is a root directory */
+ if (p = strchr (vfile, ':'))
+ {
+ *targ++ = '/';
+ while (vfile < p)
+ *targ++ = *vfile++;
+ vfile++;
+ *targ++ = '/';
+ }
+ p = vfile;
+ if (*p == '[' || *p == '<')
+ {
+ while (*++vfile != *p + 2)
+ switch (*vfile)
+ {
+ case '.':
+ if (vfile[-1] == *p)
+ *targ++ = '.';
+ *targ++ = '/';
+ break;
+
+ case '-':
+ *targ++ = '.';
+ *targ++ = '.';
+ break;
+
+ default:
+ *targ++ = *vfile;
+ break;
+ }
+ vfile++;
+ *targ++ = '/';
+ }
+ while (*vfile)
+ *targ++ = *vfile++;
+
+ return vtbuf;
+}
+
+static char utbuf[NAM$C_MAXRSS+1];
+
+/* translate a unix path to a VMS file spec */
+char *
+sys_translate_unix (ufile)
+ char * ufile;
+{
+ int slash_seen = 0;
+ char *p;
+ char * targ;
+
+ if (!ufile)
+ return 0;
+
+ targ = utbuf;
+
+ if (*ufile == '/')
+ {
+ ufile++;
+ }
+
+ while (*ufile)
+ {
+ switch (*ufile)
+ {
+ case '/':
+ if (slash_seen)
+ if (index (&ufile[1], '/'))
+ *targ++ = '.';
+ else
+ *targ++ = ']';
+ else
+ {
+ *targ++ = ':';
+ if (index (&ufile[1], '/'))
+ *targ++ = '[';
+ slash_seen = 1;
+ }
+ break;
+
+ case '.':
+ if (strncmp (ufile, "./", 2) == 0)
+ {
+ if (!slash_seen)
+ {
+ *targ++ = '[';
+ slash_seen = 1;
+ }
+ ufile++; /* skip the dot */
+ if (index (&ufile[1], '/'))
+ *targ++ = '.';
+ else
+ *targ++ = ']';
+ }
+ else if (strncmp (ufile, "../", 3) == 0)
+ {
+ if (!slash_seen)
+ {
+ *targ++ = '[';
+ slash_seen = 1;
+ }
+ *targ++ = '-';
+ ufile += 2; /* skip the dots */
+ if (index (&ufile[1], '/'))
+ *targ++ = '.';
+ else
+ *targ++ = ']';
+ }
+ else
+ *targ++ = *ufile;
+ break;
+
+ default:
+ *targ++ = *ufile;
+ break;
+ }
+ ufile++;
+ }
+ *targ = '\0';
+
+ return utbuf;
+}
+
+char *
+getwd (pathname)
+ char *pathname;
+{
+ char *ptr;
+ strcpy (pathname, egetenv ("PATH"));
+
+ ptr = pathname;
+ while (*ptr)
+ {
+ if ('a' <= *ptr && *ptr <= 'z')
+ *ptr -= 040;
+ ptr++;
+ }
+ return pathname;
+}
+
+getppid ()
+{
+ long item_code = JPI$_OWNER;
+ unsigned long parent_id;
+ int status;
+
+ if (((status = LIB$GETJPI (&item_code, 0, 0, &parent_id)) & 1) == 0)
+ {
+ errno = EVMSERR;
+ vaxc$errno = status;
+ return -1;
+ }
+ return parent_id;
+}
+
+#undef getuid
+unsigned
+sys_getuid ()
+{
+ return (getgid () << 16) | getuid ();
+}
+
+int
+sys_read (fildes, buf, nbyte)
+ int fildes;
+ char *buf;
+ unsigned int nbyte;
+{
+ return read (fildes, buf, (nbyte < MAXIOSIZE ? nbyte : MAXIOSIZE));
+}
+
+#if 0
+int
+sys_write (fildes, buf, nbyte)
+ int fildes;
+ char *buf;
+ unsigned int nbyte;
+{
+ register int nwrote, rtnval = 0;
+
+ while (nbyte > MAXIOSIZE && (nwrote = write (fildes, buf, MAXIOSIZE)) > 0) {
+ nbyte -= nwrote;
+ buf += nwrote;
+ rtnval += nwrote;
+ }
+ if (nwrote < 0)
+ return rtnval ? rtnval : -1;
+ if ((nwrote = write (fildes, buf, nbyte)) < 0)
+ return rtnval ? rtnval : -1;
+ return (rtnval + nwrote);
+}
+#endif /* 0 */
+
+/*
+ * VAX/VMS VAX C RTL really loses. It insists that records
+ * end with a newline (carriage return) character, and if they
+ * don't it adds one (nice of it isn't it!)
+ *
+ * Thus we do this stupidity below.
+ */
+
+int
+sys_write (fildes, buf, nbytes)
+ int fildes;
+ char *buf;
+ unsigned int nbytes;
+{
+ register char *p;
+ register char *e;
+ int sum = 0;
+ struct stat st;
+
+ fstat (fildes, &st);
+ p = buf;
+ while (nbytes > 0)
+ {
+ int len, retval;
+
+ /* Handle fixed-length files with carriage control. */
+ if (st.st_fab_rfm == FAB$C_FIX
+ && ((st.st_fab_rat & (FAB$M_FTN | FAB$M_CR)) != 0))
+ {
+ len = st.st_fab_mrs;
+ retval = write (fildes, p, min (len, nbytes));
+ if (retval != len)
+ return -1;
+ retval++; /* This skips the implied carriage control */
+ }
+ else
+ {
+ e = p + min (MAXIOSIZE, nbytes) - 1;
+ while (*e != '\n' && e > p) e--;
+ if (p == e) /* Ok.. so here we add a newline... sigh. */
+ e = p + min (MAXIOSIZE, nbytes) - 1;
+ len = e + 1 - p;
+ retval = write (fildes, p, len);
+ if (retval != len)
+ return -1;
+ }
+ p += retval;
+ sum += retval;
+ nbytes -= retval;
+ }
+ return sum;
+}
+
+/* Create file NEW copying its attributes from file OLD. If
+ OLD is 0 or does not exist, create based on the value of
+ vms_stmlf_recfm. */
+
+/* Protection value the file should ultimately have.
+ Set by create_copy_attrs, and use by rename_sansversions. */
+static unsigned short int fab_final_pro;
+
+int
+creat_copy_attrs (old, new)
+ char *old, *new;
+{
+ struct FAB fab = cc$rms_fab;
+ struct XABPRO xabpro;
+ char aclbuf[256]; /* Choice of size is arbitrary. See below. */
+ extern int vms_stmlf_recfm;
+
+ if (old)
+ {
+ fab.fab$b_fac = FAB$M_GET;
+ fab.fab$l_fna = old;
+ fab.fab$b_fns = strlen (old);
+ fab.fab$l_xab = (char *) &xabpro;
+ xabpro = cc$rms_xabpro;
+ xabpro.xab$l_aclbuf = aclbuf;
+ xabpro.xab$w_aclsiz = sizeof aclbuf;
+ /* Call $OPEN to fill in the fab & xabpro fields. */
+ if (sys$open (&fab, 0, 0) & 1)
+ {
+ sys$close (&fab, 0, 0);
+ fab.fab$l_alq = 0; /* zero the allocation quantity */
+ if (xabpro.xab$w_acllen > 0)
+ {
+ if (xabpro.xab$w_acllen > sizeof aclbuf)
+ /* If the acl buffer was too short, redo open with longer one.
+ Wouldn't need to do this if there were some system imposed
+ limit on the size of an ACL, but I can't find any such. */
+ {
+ xabpro.xab$l_aclbuf = (char *) alloca (xabpro.xab$w_acllen);
+ xabpro.xab$w_aclsiz = xabpro.xab$w_acllen;
+ if (sys$open (&fab, 0, 0) & 1)
+ sys$close (&fab, 0, 0);
+ else
+ old = 0;
+ }
+ }
+ else
+ xabpro.xab$l_aclbuf = 0;
+ }
+ else
+ old = 0;
+ }
+ fab.fab$l_fna = new;
+ fab.fab$b_fns = strlen (new);
+ if (!old)
+ {
+ fab.fab$l_xab = 0;
+ fab.fab$b_rfm = vms_stmlf_recfm ? FAB$C_STMLF : FAB$C_VAR;
+ fab.fab$b_rat = FAB$M_CR;
+ }
+ /* Set the file protections such that we will be able to manipulate
+ this file. Once we are done writing and renaming it, we will set
+ the protections back. */
+ if (old)
+ fab_final_pro = xabpro.xab$w_pro;
+ else
+ sys$setdfprot (0, &fab_final_pro);
+ xabpro.xab$w_pro &= 0xff0f; /* set O:rewd for now. This is set back later. */
+ /* Create the new file with either default attrs or attrs copied
+ from old file. */
+ if (!(SYS$CREATE (&fab, 0, 0) & 1))
+ return -1;
+ sys$close (&fab, 0, 0);
+ /* As this is a "replacement" for creat, return a file descriptor
+ opened for writing. */
+ return open (new, O_WRONLY);
+}
+
+#ifdef creat
+#undef creat
+#include <varargs.h>
+#ifdef __GNUC__
+#ifndef va_count
+#define va_count(X) ((X) = *(((int *) &(va_alist)) - 1))
+#endif
+#endif
+
+sys_creat (va_alist)
+ va_dcl
+{
+ va_list list_incrementor;
+ char *name;
+ int mode;
+ int rfd; /* related file descriptor */
+ int fd; /* Our new file descriptor */
+ int count;
+ struct stat st_buf;
+ char rfm[12];
+ char rat[15];
+ char mrs[13];
+ char fsz[13];
+ extern int vms_stmlf_recfm;
+
+ va_count (count);
+ va_start (list_incrementor);
+ name = va_arg (list_incrementor, char *);
+ mode = va_arg (list_incrementor, int);
+ if (count > 2)
+ rfd = va_arg (list_incrementor, int);
+ va_end (list_incrementor);
+ if (count > 2)
+ {
+ /* Use information from the related file descriptor to set record
+ format of the newly created file. */
+ fstat (rfd, &st_buf);
+ switch (st_buf.st_fab_rfm)
+ {
+ case FAB$C_FIX:
+ strcpy (rfm, "rfm = fix");
+ sprintf (mrs, "mrs = %d", st_buf.st_fab_mrs);
+ strcpy (rat, "rat = ");
+ if (st_buf.st_fab_rat & FAB$M_CR)
+ strcat (rat, "cr");
+ else if (st_buf.st_fab_rat & FAB$M_FTN)
+ strcat (rat, "ftn");
+ else if (st_buf.st_fab_rat & FAB$M_PRN)
+ strcat (rat, "prn");
+ if (st_buf.st_fab_rat & FAB$M_BLK)
+ if (st_buf.st_fab_rat & (FAB$M_CR|FAB$M_FTN|FAB$M_PRN))
+ strcat (rat, ", blk");
+ else
+ strcat (rat, "blk");
+ return creat (name, 0, rfm, rat, mrs);
+
+ case FAB$C_VFC:
+ strcpy (rfm, "rfm = vfc");
+ sprintf (fsz, "fsz = %d", st_buf.st_fab_fsz);
+ strcpy (rat, "rat = ");
+ if (st_buf.st_fab_rat & FAB$M_CR)
+ strcat (rat, "cr");
+ else if (st_buf.st_fab_rat & FAB$M_FTN)
+ strcat (rat, "ftn");
+ else if (st_buf.st_fab_rat & FAB$M_PRN)
+ strcat (rat, "prn");
+ if (st_buf.st_fab_rat & FAB$M_BLK)
+ if (st_buf.st_fab_rat & (FAB$M_CR|FAB$M_FTN|FAB$M_PRN))
+ strcat (rat, ", blk");
+ else
+ strcat (rat, "blk");
+ return creat (name, 0, rfm, rat, fsz);
+
+ case FAB$C_STM:
+ strcpy (rfm, "rfm = stm");
+ break;
+
+ case FAB$C_STMCR:
+ strcpy (rfm, "rfm = stmcr");
+ break;
+
+ case FAB$C_STMLF:
+ strcpy (rfm, "rfm = stmlf");
+ break;
+
+ case FAB$C_UDF:
+ strcpy (rfm, "rfm = udf");
+ break;
+
+ case FAB$C_VAR:
+ strcpy (rfm, "rfm = var");
+ break;
+ }
+ strcpy (rat, "rat = ");
+ if (st_buf.st_fab_rat & FAB$M_CR)
+ strcat (rat, "cr");
+ else if (st_buf.st_fab_rat & FAB$M_FTN)
+ strcat (rat, "ftn");
+ else if (st_buf.st_fab_rat & FAB$M_PRN)
+ strcat (rat, "prn");
+ if (st_buf.st_fab_rat & FAB$M_BLK)
+ if (st_buf.st_fab_rat & (FAB$M_CR|FAB$M_FTN|FAB$M_PRN))
+ strcat (rat, ", blk");
+ else
+ strcat (rat, "blk");
+ }
+ else
+ {
+ strcpy (rfm, vms_stmlf_recfm ? "rfm = stmlf" : "rfm=var");
+ strcpy (rat, "rat=cr");
+ }
+ /* Until the VAX C RTL fixes the many bugs with modes, always use
+ mode 0 to get the user's default protection. */
+ fd = creat (name, 0, rfm, rat);
+ if (fd < 0 && errno == EEXIST)
+ {
+ if (unlink (name) < 0)
+ report_file_error ("delete", build_string (name));
+ fd = creat (name, 0, rfm, rat);
+ }
+ return fd;
+}
+#endif /* creat */
+
+/* fwrite to stdout is S L O W. Speed it up by using fputc...*/
+sys_fwrite (ptr, size, num, fp)
+ register char * ptr;
+ FILE * fp;
+{
+ register int tot = num * size;
+
+ while (tot--)
+ fputc (*ptr++, fp);
+}
+
+/*
+ * The VMS C library routine creat() actually creates a new version of an
+ * existing file rather than truncating the old version. There are times
+ * when this is not the desired behavior, for instance, when writing an
+ * auto save file (you only want one version), or when you don't have
+ * write permission in the directory containing the file (but the file
+ * itself is writable). Hence this routine, which is equivalent to
+ * "close (creat (fn, 0));" on Unix if fn already exists.
+ */
+int
+vms_truncate (fn)
+ char *fn;
+{
+ struct FAB xfab = cc$rms_fab;
+ struct RAB xrab = cc$rms_rab;
+ int status;
+
+ xfab.fab$l_fop = FAB$M_TEF; /* free allocated but unused blocks on close */
+ xfab.fab$b_fac = FAB$M_TRN | FAB$M_GET; /* allow truncate and get access */
+ xfab.fab$b_shr = FAB$M_NIL; /* allow no sharing - file must be locked */
+ xfab.fab$l_fna = fn;
+ xfab.fab$b_fns = strlen (fn);
+ xfab.fab$l_dna = ";0"; /* default to latest version of the file */
+ xfab.fab$b_dns = 2;
+ xrab.rab$l_fab = &xfab;
+
+ /* This gibberish opens the file, positions to the first record, and
+ deletes all records from there until the end of file. */
+ if ((sys$open (&xfab) & 01) == 01)
+ {
+ if ((sys$connect (&xrab) & 01) == 01 &&
+ (sys$find (&xrab) & 01) == 01 &&
+ (sys$truncate (&xrab) & 01) == 01)
+ status = 0;
+ else
+ status = -1;
+ }
+ else
+ status = -1;
+ sys$close (&xfab);
+ return status;
+}
+
+/* Define this symbol to actually read SYSUAF.DAT. This requires either
+ SYSPRV or a readable SYSUAF.DAT. */
+
+#ifdef READ_SYSUAF
+/*
+ * getuaf.c
+ *
+ * Routine to read the VMS User Authorization File and return
+ * a specific user's record.
+ */
+
+static struct UAF retuaf;
+
+struct UAF *
+get_uaf_name (uname)
+ char * uname;
+{
+ register status;
+ struct FAB uaf_fab;
+ struct RAB uaf_rab;
+
+ uaf_fab = cc$rms_fab;
+ uaf_rab = cc$rms_rab;
+ /* initialize fab fields */
+ uaf_fab.fab$l_fna = "SYS$SYSTEM:SYSUAF.DAT";
+ uaf_fab.fab$b_fns = 21;
+ uaf_fab.fab$b_fac = FAB$M_GET;
+ uaf_fab.fab$b_org = FAB$C_IDX;
+ uaf_fab.fab$b_shr = FAB$M_GET|FAB$M_PUT|FAB$M_UPD|FAB$M_DEL;
+ /* initialize rab fields */
+ uaf_rab.rab$l_fab = &uaf_fab;
+ /* open the User Authorization File */
+ status = sys$open (&uaf_fab);
+ if (!(status&1))
+ {
+ errno = EVMSERR;
+ vaxc$errno = status;
+ return 0;
+ }
+ status = sys$connect (&uaf_rab);
+ if (!(status&1))
+ {
+ errno = EVMSERR;
+ vaxc$errno = status;
+ return 0;
+ }
+ /* read the requested record - index is in uname */
+ uaf_rab.rab$l_kbf = uname;
+ uaf_rab.rab$b_ksz = strlen (uname);
+ uaf_rab.rab$b_rac = RAB$C_KEY;
+ uaf_rab.rab$l_ubf = (char *)&retuaf;
+ uaf_rab.rab$w_usz = sizeof retuaf;
+ status = sys$get (&uaf_rab);
+ if (!(status&1))
+ {
+ errno = EVMSERR;
+ vaxc$errno = status;
+ return 0;
+ }
+ /* close the User Authorization File */
+ status = sys$disconnect (&uaf_rab);
+ if (!(status&1))
+ {
+ errno = EVMSERR;
+ vaxc$errno = status;
+ return 0;
+ }
+ status = sys$close (&uaf_fab);
+ if (!(status&1))
+ {
+ errno = EVMSERR;
+ vaxc$errno = status;
+ return 0;
+ }
+ return &retuaf;
+}
+
+struct UAF *
+get_uaf_uic (uic)
+ unsigned long uic;
+{
+ register status;
+ struct FAB uaf_fab;
+ struct RAB uaf_rab;
+
+ uaf_fab = cc$rms_fab;
+ uaf_rab = cc$rms_rab;
+ /* initialize fab fields */
+ uaf_fab.fab$l_fna = "SYS$SYSTEM:SYSUAF.DAT";
+ uaf_fab.fab$b_fns = 21;
+ uaf_fab.fab$b_fac = FAB$M_GET;
+ uaf_fab.fab$b_org = FAB$C_IDX;
+ uaf_fab.fab$b_shr = FAB$M_GET|FAB$M_PUT|FAB$M_UPD|FAB$M_DEL;
+ /* initialize rab fields */
+ uaf_rab.rab$l_fab = &uaf_fab;
+ /* open the User Authorization File */
+ status = sys$open (&uaf_fab);
+ if (!(status&1))
+ {
+ errno = EVMSERR;
+ vaxc$errno = status;
+ return 0;
+ }
+ status = sys$connect (&uaf_rab);
+ if (!(status&1))
+ {
+ errno = EVMSERR;
+ vaxc$errno = status;
+ return 0;
+ }
+ /* read the requested record - index is in uic */
+ uaf_rab.rab$b_krf = 1; /* 1st alternate key */
+ uaf_rab.rab$l_kbf = (char *) &uic;
+ uaf_rab.rab$b_ksz = sizeof uic;
+ uaf_rab.rab$b_rac = RAB$C_KEY;
+ uaf_rab.rab$l_ubf = (char *)&retuaf;
+ uaf_rab.rab$w_usz = sizeof retuaf;
+ status = sys$get (&uaf_rab);
+ if (!(status&1))
+ {
+ errno = EVMSERR;
+ vaxc$errno = status;
+ return 0;
+ }
+ /* close the User Authorization File */
+ status = sys$disconnect (&uaf_rab);
+ if (!(status&1))
+ {
+ errno = EVMSERR;
+ vaxc$errno = status;
+ return 0;
+ }
+ status = sys$close (&uaf_fab);
+ if (!(status&1))
+ {
+ errno = EVMSERR;
+ vaxc$errno = status;
+ return 0;
+ }
+ return &retuaf;
+}
+
+static struct passwd retpw;
+
+struct passwd *
+cnv_uaf_pw (up)
+ struct UAF * up;
+{
+ char * ptr;
+
+ /* copy these out first because if the username is 32 chars, the next
+ section will overwrite the first byte of the UIC */
+ retpw.pw_uid = up->uaf$w_mem;
+ retpw.pw_gid = up->uaf$w_grp;
+
+ /* I suppose this is not the best sytle, to possibly overwrite one
+ byte beyond the end of the field, but what the heck... */
+ ptr = &up->uaf$t_username[UAF$S_USERNAME];
+ while (ptr[-1] == ' ')
+ ptr--;
+ *ptr = '\0';
+ strcpy (retpw.pw_name, up->uaf$t_username);
+
+ /* the rest of these are counted ascii strings */
+ strncpy (retpw.pw_gecos, &up->uaf$t_owner[1], up->uaf$t_owner[0]);
+ retpw.pw_gecos[up->uaf$t_owner[0]] = '\0';
+ strncpy (retpw.pw_dir, &up->uaf$t_defdev[1], up->uaf$t_defdev[0]);
+ retpw.pw_dir[up->uaf$t_defdev[0]] = '\0';
+ strncat (retpw.pw_dir, &up->uaf$t_defdir[1], up->uaf$t_defdir[0]);
+ retpw.pw_dir[up->uaf$t_defdev[0] + up->uaf$t_defdir[0]] = '\0';
+ strncpy (retpw.pw_shell, &up->uaf$t_defcli[1], up->uaf$t_defcli[0]);
+ retpw.pw_shell[up->uaf$t_defcli[0]] = '\0';
+
+ return &retpw;
+}
+#else /* not READ_SYSUAF */
+static struct passwd retpw;
+#endif /* not READ_SYSUAF */
+
+struct passwd *
+getpwnam (name)
+ char * name;
+{
+#ifdef READ_SYSUAF
+ struct UAF *up;
+#else
+ char * user;
+ char * dir;
+ unsigned char * full;
+#endif /* READ_SYSUAF */
+ char *ptr = name;
+
+ while (*ptr)
+ {
+ if ('a' <= *ptr && *ptr <= 'z')
+ *ptr -= 040;
+ ptr++;
+ }
+#ifdef READ_SYSUAF
+ if (!(up = get_uaf_name (name)))
+ return 0;
+ return cnv_uaf_pw (up);
+#else
+ if (strcmp (name, getenv ("USER")) == 0)
+ {
+ retpw.pw_uid = getuid ();
+ retpw.pw_gid = getgid ();
+ strcpy (retpw.pw_name, name);
+ if (full = (unsigned char*) egetenv ("FULLNAME"))
+ strcpy (retpw.pw_gecos, full);
+ else
+ *retpw.pw_gecos = '\0';
+ strcpy (retpw.pw_dir, egetenv ("HOME"));
+ *retpw.pw_shell = '\0';
+ return &retpw;
+ }
+ else
+ return 0;
+#endif /* not READ_SYSUAF */
+}
+
+struct passwd *
+getpwuid (uid)
+ unsigned long uid;
+{
+#ifdef READ_SYSUAF
+ struct UAF * up;
+
+ if (!(up = get_uaf_uic (uid)))
+ return 0;
+ return cnv_uaf_pw (up);
+#else
+ if (uid == sys_getuid ())
+ return getpwnam (egetenv ("USER"));
+ else
+ return 0;
+#endif /* not READ_SYSUAF */
+}
+
+/* return total address space available to the current process. This is
+ the sum of the current p0 size, p1 size and free page table entries
+ available. */
+vlimit ()
+{
+ int item_code;
+ unsigned long free_pages;
+ unsigned long frep0va;
+ unsigned long frep1va;
+ register status;
+
+ item_code = JPI$_FREPTECNT;
+ if (((status = LIB$GETJPI (&item_code, 0, 0, &free_pages)) & 1) == 0)
+ {
+ errno = EVMSERR;
+ vaxc$errno = status;
+ return -1;
+ }
+ free_pages *= 512;
+
+ item_code = JPI$_FREP0VA;
+ if (((status = LIB$GETJPI (&item_code, 0, 0, &frep0va)) & 1) == 0)
+ {
+ errno = EVMSERR;
+ vaxc$errno = status;
+ return -1;
+ }
+ item_code = JPI$_FREP1VA;
+ if (((status = LIB$GETJPI (&item_code, 0, 0, &frep1va)) & 1) == 0)
+ {
+ errno = EVMSERR;
+ vaxc$errno = status;
+ return -1;
+ }
+
+ return free_pages + frep0va + (0x7fffffff - frep1va);
+}
+
+define_logical_name (varname, string)
+ char *varname;
+ char *string;
+{
+ struct dsc$descriptor_s strdsc =
+ {strlen (string), DSC$K_DTYPE_T, DSC$K_CLASS_S, string};
+ struct dsc$descriptor_s envdsc =
+ {strlen (varname), DSC$K_DTYPE_T, DSC$K_CLASS_S, varname};
+ struct dsc$descriptor_s lnmdsc =
+ {7, DSC$K_DTYPE_T, DSC$K_CLASS_S, "LNM$JOB"};
+
+ return LIB$SET_LOGICAL (&envdsc, &strdsc, &lnmdsc, 0, 0);
+}
+
+delete_logical_name (varname)
+ char *varname;
+{
+ struct dsc$descriptor_s envdsc =
+ {strlen (varname), DSC$K_DTYPE_T, DSC$K_CLASS_S, varname};
+ struct dsc$descriptor_s lnmdsc =
+ {7, DSC$K_DTYPE_T, DSC$K_CLASS_S, "LNM$JOB"};
+
+ return LIB$DELETE_LOGICAL (&envdsc, &lnmdsc);
+}
+
+ulimit ()
+{}
+
+setpriority ()
+{}
+
+setpgrp ()
+{}
+
+execvp ()
+{
+ error ("execvp system call not implemented");
+}
+
+int
+rename (from, to)
+ char *from, *to;
+{
+ int status;
+ struct FAB from_fab = cc$rms_fab, to_fab = cc$rms_fab;
+ struct NAM from_nam = cc$rms_nam, to_nam = cc$rms_nam;
+ char from_esn[NAM$C_MAXRSS];
+ char to_esn[NAM$C_MAXRSS];
+
+ from_fab.fab$l_fna = from;
+ from_fab.fab$b_fns = strlen (from);
+ from_fab.fab$l_nam = &from_nam;
+ from_fab.fab$l_fop = FAB$M_NAM;
+
+ from_nam.nam$l_esa = from_esn;
+ from_nam.nam$b_ess = sizeof from_esn;
+
+ to_fab.fab$l_fna = to;
+ to_fab.fab$b_fns = strlen (to);
+ to_fab.fab$l_nam = &to_nam;
+ to_fab.fab$l_fop = FAB$M_NAM;
+
+ to_nam.nam$l_esa = to_esn;
+ to_nam.nam$b_ess = sizeof to_esn;
+
+ status = SYS$RENAME (&from_fab, 0, 0, &to_fab);
+
+ if (status & 1)
+ return 0;
+ else
+ {
+ if (status == RMS$_DEV)
+ errno = EXDEV;
+ else
+ errno = EVMSERR;
+ vaxc$errno = status;
+ return -1;
+ }
+}
+
+/* This function renames a file like `rename', but it strips
+ the version number from the "to" filename, such that the "to" file is
+ will always be a new version. It also sets the file protection once it is
+ finished. The protection that we will use is stored in fab_final_pro,
+ and was set when we did a creat_copy_attrs to create the file that we
+ are renaming.
+
+ We could use the chmod function, but Eunichs uses 3 bits per user category
+ to describe the protection, and VMS uses 4 (write and delete are seperate
+ bits). To maintain portability, the VMS implementation of `chmod' wires
+ the W and D bits together. */
+
+
+static struct fibdef fib; /* We need this initialized to zero */
+char vms_file_written[NAM$C_MAXRSS];
+
+int
+rename_sans_version (from,to)
+ char *from, *to;
+{
+ short int chan;
+ int stat;
+ short int iosb[4];
+ int status;
+ struct FAB to_fab = cc$rms_fab;
+ struct NAM to_nam = cc$rms_nam;
+ struct dsc$descriptor fib_d ={sizeof (fib),0,0,(char*) &fib};
+ struct dsc$descriptor fib_attr[2]
+ = {{sizeof (fab_final_pro),ATR$C_FPRO,0,(char*) &fab_final_pro},{0,0,0,0}};
+ char to_esn[NAM$C_MAXRSS];
+
+ $DESCRIPTOR (disk,to_esn);
+
+ to_fab.fab$l_fna = to;
+ to_fab.fab$b_fns = strlen (to);
+ to_fab.fab$l_nam = &to_nam;
+ to_fab.fab$l_fop = FAB$M_NAM;
+
+ to_nam.nam$l_esa = to_esn;
+ to_nam.nam$b_ess = sizeof to_esn;
+
+ status = SYS$PARSE (&to_fab, 0, 0); /* figure out the full file name */
+
+ if (to_nam.nam$l_fnb && NAM$M_EXP_VER)
+ *(to_nam.nam$l_ver) = '\0';
+
+ stat = rename (from, to_esn);
+ if (stat < 0)
+ return stat;
+
+ strcpy (vms_file_written, to_esn);
+
+ to_fab.fab$l_fna = vms_file_written; /* this points to the versionless name */
+ to_fab.fab$b_fns = strlen (vms_file_written);
+
+ /* Now set the file protection to the correct value */
+ sys$open (&to_fab, 0, 0); /* This fills in the nam$w_fid fields */
+
+ /* Copy these fields into the fib */
+ fib.fib$r_fid_overlay.fib$w_fid[0] = to_nam.nam$w_fid[0];
+ fib.fib$r_fid_overlay.fib$w_fid[1] = to_nam.nam$w_fid[1];
+ fib.fib$r_fid_overlay.fib$w_fid[2] = to_nam.nam$w_fid[2];
+
+ sys$close (&to_fab, 0, 0);
+
+ stat = sys$assign (&disk, &chan, 0, 0); /* open a channel to the disk */
+ if (!stat)
+ lib$signal (stat);
+ stat = sys$qiow (0, chan, IO$_MODIFY, iosb, 0, 0, &fib_d,
+ 0, 0, 0, &fib_attr, 0);
+ if (!stat)
+ lib$signal (stat);
+ stat = sys$dassgn (chan);
+ if (!stat)
+ lib$signal (stat);
+ strcpy (vms_file_written, to_esn); /* We will write this to the screen*/
+ return 0;
+}
+
+link (file, new)
+ char * file, * new;
+{
+ register status;
+ struct FAB fab;
+ struct NAM nam;
+ unsigned short fid[3];
+ char esa[NAM$C_MAXRSS];
+
+ fab = cc$rms_fab;
+ fab.fab$l_fop = FAB$M_OFP;
+ fab.fab$l_fna = file;
+ fab.fab$b_fns = strlen (file);
+ fab.fab$l_nam = &nam;
+
+ nam = cc$rms_nam;
+ nam.nam$l_esa = esa;
+ nam.nam$b_ess = NAM$C_MAXRSS;
+
+ status = SYS$PARSE (&fab);
+ if ((status & 1) == 0)
+ {
+ errno = EVMSERR;
+ vaxc$errno = status;
+ return -1;
+ }
+ status = SYS$SEARCH (&fab);
+ if ((status & 1) == 0)
+ {
+ errno = EVMSERR;
+ vaxc$errno = status;
+ return -1;
+ }
+
+ fid[0] = nam.nam$w_fid[0];
+ fid[1] = nam.nam$w_fid[1];
+ fid[2] = nam.nam$w_fid[2];
+
+ fab.fab$l_fna = new;
+ fab.fab$b_fns = strlen (new);
+
+ status = SYS$PARSE (&fab);
+ if ((status & 1) == 0)
+ {
+ errno = EVMSERR;
+ vaxc$errno = status;
+ return -1;
+ }
+
+ nam.nam$w_fid[0] = fid[0];
+ nam.nam$w_fid[1] = fid[1];
+ nam.nam$w_fid[2] = fid[2];
+
+ nam.nam$l_esa = nam.nam$l_name;
+ nam.nam$b_esl = nam.nam$b_name + nam.nam$b_type + nam.nam$b_ver;
+
+ status = SYS$ENTER (&fab);
+ if ((status & 1) == 0)
+ {
+ errno = EVMSERR;
+ vaxc$errno = status;
+ return -1;
+ }
+
+ return 0;
+}
+
+croak (badfunc)
+ char *badfunc;
+{
+ printf ("%s not yet implemented\r\n", badfunc);
+ reset_sys_modes ();
+ exit (1);
+}
+
+long
+random ()
+{
+ /* Arrange to return a range centered on zero. */
+ return rand () - (1 << 30);
+}
+
+srandom (seed)
+{
+ srand (seed);
+}
+#endif /* VMS */
+
+#ifdef WRONG_NAME_INSQUE
+
+insque(q,p)
+ caddr_t q,p;
+{
+ _insque(q,p);
+}
+
+#endif
+
+#ifdef AIX
+
+/* Called from init_sys_modes. */
+hft_init ()
+{
+ int junk;
+
+ /* If we're not on an HFT we shouldn't do any of this. We determine
+ if we are on an HFT by trying to get an HFT error code. If this
+ call fails, we're not on an HFT. */
+#ifdef IBMR2AIX
+ if (ioctl (0, HFQERROR, &junk) < 0)
+ return;
+#else /* not IBMR2AIX */
+ if (ioctl (0, HFQEIO, 0) < 0)
+ return;
+#endif /* not IBMR2AIX */
+
+ /* On AIX the default hft keyboard mapping uses backspace rather than delete
+ as the rubout key's ASCII code. Here this is changed. The bug is that
+ there's no way to determine the old mapping, so in reset_sys_modes
+ we need to assume that the normal map had been present. Of course, this
+ code also doesn't help if on a terminal emulator which doesn't understand
+ HFT VTD's. */
+ {
+ struct hfbuf buf;
+ struct hfkeymap keymap;
+
+ buf.hf_bufp = (char *)&keymap;
+ buf.hf_buflen = sizeof (keymap);
+ keymap.hf_nkeys = 2;
+ keymap.hfkey[0].hf_kpos = 15;
+ keymap.hfkey[0].hf_kstate = HFMAPCHAR | HFSHFNONE;
+#ifdef IBMR2AIX
+ keymap.hfkey[0].hf_keyidh = '<';
+#else /* not IBMR2AIX */
+ keymap.hfkey[0].hf_page = '<';
+#endif /* not IBMR2AIX */
+ keymap.hfkey[0].hf_char = 127;
+ keymap.hfkey[1].hf_kpos = 15;
+ keymap.hfkey[1].hf_kstate = HFMAPCHAR | HFSHFSHFT;
+#ifdef IBMR2AIX
+ keymap.hfkey[1].hf_keyidh = '<';
+#else /* not IBMR2AIX */
+ keymap.hfkey[1].hf_page = '<';
+#endif /* not IBMR2AIX */
+ keymap.hfkey[1].hf_char = 127;
+ hftctl (0, HFSKBD, &buf);
+ }
+ /* The HFT system on AIX doesn't optimize for scrolling, so it's really ugly
+ at times. */
+ line_ins_del_ok = char_ins_del_ok = 0;
+}
+
+/* Reset the rubout key to backspace. */
+
+hft_reset ()
+{
+ struct hfbuf buf;
+ struct hfkeymap keymap;
+ int junk;
+
+#ifdef IBMR2AIX
+ if (ioctl (0, HFQERROR, &junk) < 0)
+ return;
+#else /* not IBMR2AIX */
+ if (ioctl (0, HFQEIO, 0) < 0)
+ return;
+#endif /* not IBMR2AIX */
+
+ buf.hf_bufp = (char *)&keymap;
+ buf.hf_buflen = sizeof (keymap);
+ keymap.hf_nkeys = 2;
+ keymap.hfkey[0].hf_kpos = 15;
+ keymap.hfkey[0].hf_kstate = HFMAPCHAR | HFSHFNONE;
+#ifdef IBMR2AIX
+ keymap.hfkey[0].hf_keyidh = '<';
+#else /* not IBMR2AIX */
+ keymap.hfkey[0].hf_page = '<';
+#endif /* not IBMR2AIX */
+ keymap.hfkey[0].hf_char = 8;
+ keymap.hfkey[1].hf_kpos = 15;
+ keymap.hfkey[1].hf_kstate = HFMAPCHAR | HFSHFSHFT;
+#ifdef IBMR2AIX
+ keymap.hfkey[1].hf_keyidh = '<';
+#else /* not IBMR2AIX */
+ keymap.hfkey[1].hf_page = '<';
+#endif /* not IBMR2AIX */
+ keymap.hfkey[1].hf_char = 8;
+ hftctl (0, HFSKBD, &buf);
+}
+
+#endif /* AIX */
diff --git a/src/temacs.opt b/src/temacs.opt
new file mode 100644
index 00000000000..a140ddd4ac4
--- /dev/null
+++ b/src/temacs.opt
@@ -0,0 +1,59 @@
+cluster=emacs,,,-
+DISPNEW.OBJ,-
+SCROLL.OBJ,-
+XDISP.OBJ,-
+WINDOW.OBJ,-
+TERM.OBJ,-
+CM.OBJ,-
+EMACS.OBJ,-
+KEYBOARD.OBJ,-
+MACROS.OBJ,-
+KEYMAP.OBJ,-
+SYSDEP.OBJ,-
+BUFFER.OBJ,-
+FILELOCK.OBJ,-
+INSDEL.OBJ,-
+MARKER.OBJ,-
+MINIBUF.OBJ,-
+FILEIO.OBJ,-
+DIRED.OBJ,-
+FILEMODE.OBJ,-
+CMDS.OBJ,-
+CASEFIDDLE.OBJ,-
+INDENT.OBJ,-
+SEARCH.OBJ,-
+REGEX.OBJ,-
+UNDO.OBJ,-
+ALLOC.OBJ,-
+DATA.OBJ,-
+DOC.OBJ,-
+EDITFNS.OBJ,-
+CALLINT.OBJ,-
+EVAL.OBJ,-
+FNS.OBJ,-
+PRINT.OBJ,-
+LREAD.OBJ,-
+ABBREV.OBJ,-
+SYNTAX.OBJ,-
+MOCKLISP.OBJ,-
+BYTECODE.OBJ,-
+PROCESS.OBJ,-
+CALLPROC.OBJ,-
+VMSFNS.OBJ,-
+DOPRNT.OBJ,-
+vmsmap.obj,-
+termcap.obj,-
+tparam.obj,-
+lastfile.obj,-
+alloca.obj,-
+malloc.obj
+collect=non_saved_data,-
+stdin,-
+stdout,-
+stderr,-
+errno,-
+vaxc$errno,-
+sys_errlist,-
+sys_nerr,-
+environ
+sys$library:vaxcrtl/library
diff --git a/src/term.c b/src/term.c
new file mode 100644
index 00000000000..c8a1ed0659a
--- /dev/null
+++ b/src/term.c
@@ -0,0 +1,1240 @@
+/* terminal control module for terminals described by TERMCAP
+ Copyright (C) 1985, 1986, 1987 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#include <stdio.h>
+#include <ctype.h>
+#include "config.h"
+#include "termhooks.h"
+#include "termchar.h"
+#include "termopts.h"
+#include "cm.h"
+
+#define max(a, b) ((a) > (b) ? (a) : (b))
+#define min(a, b) ((a) < (b) ? (a) : (b))
+
+#define OUTPUT(a) tputs (a, screen_height - curY, cmputc)
+#define OUTPUT1(a) tputs (a, 1, cmputc)
+#define OUTPUTL(a, lines) tputs (a, lines, cmputc)
+#define OUTPUT_IF(a) { if (a) tputs (a, screen_height - curY, cmputc); }
+#define OUTPUT1_IF(a) { if (a) tputs (a, 1, cmputc); }
+
+/* Terminal charateristics that higher levels want to look at.
+ These are all extern'd in termchar.h */
+
+int screen_width; /* Number of usable columns */
+int screen_height; /* Number of lines */
+int must_write_spaces; /* Nonzero means spaces in the text
+ must actually be output; can't just skip
+ over some columns to leave them blank. */
+int min_padding_speed; /* Speed below which no padding necessary */
+
+int line_ins_del_ok; /* Terminal can insert and delete lines */
+int char_ins_del_ok; /* Terminal can insert and delete chars */
+int scroll_region_ok; /* Terminal supports setting the scroll window */
+int memory_below_screen; /* Terminal remembers lines scrolled off bottom */
+int fast_clear_end_of_line; /* Terminal has a `ce' string */
+
+int dont_calculate_costs; /* Nonzero means don't bother computing */
+ /* various cost tables; we won't use them. */
+
+/* Nonzero means no need to redraw the entire screen on resuming
+ a suspended Emacs. This is useful on terminals with multiple pages,
+ where one page is used for Emacs and another for all else. */
+int no_redraw_on_reenter;
+
+/* DCICcost[n] is cost of inserting N characters.
+ DCICcost[-n] is cost of deleting N characters. */
+
+#define DCICcost (&DC_ICcost[screen_width])
+int *DC_ICcost;
+
+/* Hook functions that you can set to snap out the functions in this file.
+ These are all extern'd in termhooks.h */
+
+int (*move_cursor_hook) ();
+int (*raw_move_cursor_hook) ();
+
+int (*clear_to_end_hook) ();
+int (*clear_screen_hook) ();
+int (*clear_end_of_line_hook) ();
+
+int (*ins_del_lines_hook) ();
+
+int (*change_line_highlight_hook) ();
+int (*reassert_line_highlight_hook) ();
+
+int (*insert_chars_hook) ();
+int (*output_chars_hook) ();
+int (*delete_chars_hook) ();
+
+int (*ring_bell_hook) ();
+
+int (*reset_terminal_modes_hook) ();
+int (*set_terminal_modes_hook) ();
+int (*update_begin_hook) ();
+int (*update_end_hook) ();
+int (*set_terminal_window_hook) ();
+
+int (*read_socket_hook) ();
+int (*fix_screen_hook) ();
+int (*calculate_costs_hook) ();
+
+/* Strings, numbers and flags taken from the termcap entry. */
+
+char *TS_ins_line; /* termcap "al" */
+char *TS_ins_multi_lines; /* "AL" (one parameter, # lines to insert) */
+char *TS_bell; /* "bl" */
+char *TS_clr_to_bottom; /* "cd" */
+char *TS_clr_line; /* "ce", clear to end of line */
+char *TS_clr_screen; /* "cl" */
+char *TS_set_scroll_region; /* "cs" (2 params, first line and last line) */
+char *TS_set_scroll_region_1; /* "cS" (4 params: total lines,
+ lines above scroll region, lines below it,
+ total lines again) */
+char *TS_del_char; /* "dc" */
+char *TS_del_multi_chars; /* "DC" (one parameter, # chars to delete) */
+char *TS_del_line; /* "dl" */
+char *TS_del_multi_lines; /* "DL" (one parameter, # lines to delete) */
+char *TS_delete_mode; /* "dm", enter character-delete mode */
+char *TS_end_delete_mode; /* "ed", leave character-delete mode */
+char *TS_end_insert_mode; /* "ei", leave character-insert mode */
+char *TS_ins_char; /* "ic" */
+char *TS_ins_multi_chars; /* "IC" (one parameter, # chars to insert) */
+char *TS_insert_mode; /* "im", enter character-insert mode */
+char *TS_pad_inserted_char; /* "ip". Just padding, no commands. */
+char *TS_end_keypad_mode; /* "ke" */
+char *TS_keypad_mode; /* "ks" */
+char *TS_pad_char; /* "pc", char to use as padding */
+char *TS_repeat; /* "rp" (2 params, # times to repeat
+ and character to be repeated) */
+char *TS_end_standout_mode; /* "se" */
+char *TS_fwd_scroll; /* "sf" */
+char *TS_standout_mode; /* "so" */
+char *TS_rev_scroll; /* "sr" */
+char *TS_end_termcap_modes; /* "te" */
+char *TS_termcap_modes; /* "ti" */
+char *TS_visible_bell; /* "vb" */
+char *TS_end_visual_mode; /* "ve" */
+char *TS_visual_mode; /* "vi" */
+char *TS_set_window; /* "wi" (4 params, start and end of window,
+ each as vpos and hpos) */
+
+int TF_hazeltine; /* termcap hz flag. */
+int TF_insmode_motion; /* termcap mi flag: can move while in insert mode. */
+int TF_standout_motion; /* termcap mi flag: can move while in standout mode. */
+int TF_underscore; /* termcap ul flag: _ underlines if overstruck on
+ nonblank position. Must clear before writing _. */
+int TF_teleray; /* termcap xt flag: many weird consequences. For t1061. */
+
+int TF_xs; /* Nonzero for "xs". If set together with
+ TN_standout_width == 0, it means don't bother
+ to write any end-standout cookies. */
+
+int TN_standout_width; /* termcap sg number: width occupied by standout markers */
+
+static int RPov; /* # chars to start a TS_repeat */
+
+static int delete_in_insert_mode; /* delete mode == insert mode */
+
+static int se_is_so; /* 1 if same string both enters and leaves standout mode */
+
+/* internal state */
+
+/* Number of chars of space used for standout marker at beginning of line,
+ or'd with 0100. Zero if no standout marker at all. */
+/* used iff TN_standout_width >= 0. */
+char *chars_wasted;
+static char *copybuf;
+
+/* nonzero means supposed to write text in standout mode. */
+int standout_requested;
+
+int insert_mode; /* Nonzero when in insert mode. */
+int standout_mode; /* Nonzero when in standout mode. */
+
+/* Size of window specified by higher levels.
+ This is the number of lines, starting from top of screen,
+ to participate in ins/del line operations.
+ Effectively it excludes the bottom
+ screen_height - specified_window_size
+ lines from those operations. */
+
+int specified_window;
+
+char *tparam ();
+
+ring_bell ()
+{
+ if (ring_bell_hook)
+ {
+ (*ring_bell_hook) ();
+ return;
+ }
+ OUTPUT (TS_visible_bell && visible_bell ? TS_visible_bell : TS_bell);
+}
+
+set_terminal_modes ()
+{
+ if (set_terminal_modes_hook)
+ {
+ (*set_terminal_modes_hook) ();
+ return;
+ }
+ OUTPUT_IF (TS_termcap_modes);
+ OUTPUT_IF (TS_visual_mode);
+ OUTPUT_IF (TS_keypad_mode);
+ losecursor ();
+}
+
+reset_terminal_modes ()
+{
+ if (reset_terminal_modes_hook)
+ {
+ (*reset_terminal_modes_hook) ();
+ return;
+ }
+ if (TN_standout_width < 0)
+ turn_off_highlight ();
+ turn_off_insert ();
+ OUTPUT_IF (TS_end_keypad_mode);
+ OUTPUT_IF (TS_end_visual_mode);
+ OUTPUT_IF (TS_end_termcap_modes);
+}
+
+update_begin ()
+{
+ if (update_begin_hook)
+ (*update_begin_hook) ();
+}
+
+update_end ()
+{
+ if (update_end_hook)
+ {
+ (*update_end_hook) ();
+ return;
+ }
+ turn_off_insert ();
+ background_highlight ();
+ standout_requested = 0;
+}
+
+set_terminal_window (size)
+ int size;
+{
+ if (set_terminal_window_hook)
+ {
+ (*set_terminal_window_hook) (size);
+ return;
+ }
+ specified_window = size ? size : screen_height;
+ if (!scroll_region_ok)
+ return;
+ set_scroll_region (0, specified_window);
+}
+
+set_scroll_region (start, stop)
+ int start, stop;
+{
+ char *buf;
+ if (TS_set_scroll_region)
+ {
+ buf = tparam (TS_set_scroll_region, 0, 0, start, stop - 1);
+ }
+ else if (TS_set_scroll_region_1)
+ {
+ buf = tparam (TS_set_scroll_region_1, 0, 0,
+ screen_height, start, screen_height - stop, screen_height);
+ }
+ else
+ {
+ buf = tparam (TS_set_window, 0, 0, start, 0, stop, screen_width);
+ }
+ OUTPUT (buf);
+ free (buf);
+ losecursor ();
+}
+
+turn_on_insert ()
+{
+ if (!insert_mode)
+ OUTPUT (TS_insert_mode);
+ insert_mode = 1;
+}
+
+turn_off_insert ()
+{
+ if (insert_mode)
+ OUTPUT (TS_end_insert_mode);
+ insert_mode = 0;
+}
+
+/* Handle highlighting when TN_standout_width (termcap sg) is not specified.
+ In these terminals, output is affected by the value of standout
+ mode when the output is written.
+
+ These functions are called on all terminals, but do nothing
+ on terminals whose standout mode does not work that way. */
+
+turn_off_highlight ()
+{
+ if (TN_standout_width < 0)
+ {
+ if (standout_mode)
+ OUTPUT_IF (TS_end_standout_mode);
+ standout_mode = 0;
+ }
+}
+
+turn_on_highlight ()
+{
+ if (TN_standout_width < 0)
+ {
+ if (!standout_mode)
+ OUTPUT_IF (TS_standout_mode);
+ standout_mode = 1;
+ }
+}
+
+/* Set standout mode to the state it should be in for
+ empty space inside windows. What this is,
+ depends on the user option inverse-video. */
+
+background_highlight ()
+{
+ if (TN_standout_width >= 0)
+ return;
+ if (inverse_video)
+ turn_on_highlight ();
+ else
+ turn_off_highlight ();
+}
+
+/* Set standout mode to the mode specified for the text to be output. */
+
+static
+highlight_if_desired ()
+{
+ if (TN_standout_width >= 0)
+ return;
+ if (!inverse_video == !standout_requested)
+ turn_off_highlight ();
+ else
+ turn_on_highlight ();
+}
+
+/* Handle standout mode for terminals in which TN_standout_width >= 0.
+ On these terminals, standout is controlled by markers that
+ live inside the screen memory. TN_standout_width is the width
+ that the marker occupies in memory. Standout runs from the marker
+ to the end of the line on some terminals, or to the next
+ turn-off-standout marker (TS_end_standout_mode) string
+ on other terminals. */
+
+/* Write a standout marker or end-standout marker at the front of the line
+ at vertical position vpos. */
+
+write_standout_marker (flag, vpos)
+ int flag, vpos;
+{
+ if (flag || (TS_end_standout_mode && !TF_teleray && !se_is_so
+ && !(TF_xs && TN_standout_width == 0)))
+ {
+ cmgoto (vpos, 0);
+ cmplus (TN_standout_width);
+ OUTPUT (flag ? TS_standout_mode : TS_end_standout_mode);
+ chars_wasted[curY] = TN_standout_width | 0100;
+ }
+}
+
+/* External interface to control of standout mode.
+ Call this when about to modify line at position VPOS
+ and not change whether it is highlighted. */
+
+reassert_line_highlight (highlight, vpos)
+ int highlight;
+ int vpos;
+{
+ if (reassert_line_highlight_hook)
+ {
+ (*reassert_line_highlight_hook) (highlight, vpos);
+ return;
+ }
+ if (TN_standout_width < 0)
+ /* Handle terminals where standout takes affect at output time */
+ standout_requested = highlight;
+ else if (chars_wasted[vpos] == 0)
+ /* For terminals with standout markers, write one on this line
+ if there isn't one already. */
+ write_standout_marker (highlight, vpos);
+}
+
+/* Call this when about to modify line at position VPOS
+ and change whether it is highlighted. */
+
+change_line_highlight (new_highlight, vpos, first_unused_hpos)
+ int new_highlight, vpos, first_unused_hpos;
+{
+ standout_requested = new_highlight;
+ if (change_line_highlight_hook)
+ {
+ (*change_line_highlight_hook) (new_highlight, vpos, first_unused_hpos);
+ return;
+ }
+
+ move_cursor (vpos, 0);
+
+ if (TN_standout_width < 0)
+ background_highlight ();
+ /* If line starts with a marker, delete the marker */
+ else if (TS_clr_line && chars_wasted[curY])
+ {
+ turn_off_insert ();
+ /* On Teleray, make sure to erase the SO marker. */
+ if (TF_teleray)
+ {
+ cmgoto (curY - 1, screen_width - 4);
+ OUTPUT ("\033S");
+ curY++; /* ESC S moves to next line where the TS_standout_mode was */
+ curX = 0;
+ }
+ else
+ cmgoto (curY, 0); /* reposition to kill standout marker */
+ }
+ clear_end_of_line_raw (first_unused_hpos);
+ reassert_line_highlight (new_highlight, curY);
+}
+
+/* Move to absolute position, specified origin 0 */
+
+move_cursor (row, col)
+{
+ col += chars_wasted[row] & 077;
+ if (move_cursor_hook)
+ {
+ (*move_cursor_hook) (row, col);
+ return;
+ }
+ if (curY == row && curX == col)
+ return;
+ if (!TF_standout_motion)
+ background_highlight ();
+ if (!TF_insmode_motion)
+ turn_off_insert ();
+ cmgoto (row, col);
+}
+
+/* Similar but don't take any account of the wasted characters. */
+
+raw_move_cursor (row, col)
+{
+ if (raw_move_cursor_hook)
+ {
+ (*raw_move_cursor_hook) (row, col);
+ return;
+ }
+ if (curY == row && curX == col)
+ return;
+ if (!TF_standout_motion)
+ background_highlight ();
+ if (!TF_insmode_motion)
+ turn_off_insert ();
+ cmgoto (row, col);
+}
+
+/* Erase operations */
+
+/* clear from cursor to end of screen */
+clear_to_end ()
+{
+ register int i;
+
+ if (clear_to_end_hook)
+ {
+ (*clear_to_end_hook) ();
+ return;
+ }
+ if (TS_clr_to_bottom)
+ {
+ background_highlight ();
+ OUTPUT (TS_clr_to_bottom);
+ bzero (chars_wasted + curY, screen_height - curY);
+ }
+ else
+ {
+ for (i = curY; i < screen_height; i++)
+ {
+ move_cursor (i, 0);
+ clear_end_of_line_raw (screen_width);
+ }
+ }
+}
+
+/* Clear entire screen */
+
+clear_screen ()
+{
+ if (clear_screen_hook)
+ {
+ (*clear_screen_hook) ();
+ return;
+ }
+ if (TS_clr_screen)
+ {
+ background_highlight ();
+ OUTPUT (TS_clr_screen);
+ bzero (chars_wasted, screen_height);
+ cmat (0, 0);
+ }
+ else
+ {
+ move_cursor (0, 0);
+ clear_to_end ();
+ }
+}
+
+/* Clear to end of line, but do not clear any standout marker.
+ Assumes that the cursor is positioned at a character of real text,
+ which implies it cannot be before a standout marker
+ unless the marker has zero width.
+
+ Note that the cursor may be moved. */
+
+clear_end_of_line (first_unused_hpos)
+ int first_unused_hpos;
+{
+ if (TN_standout_width == 0 && curX == 0 && chars_wasted[curY] != 0)
+ output_chars (" ", 1);
+ clear_end_of_line_raw (first_unused_hpos);
+}
+
+/* Clear from cursor to end of line.
+ Assume that the line is already clear starting at column first_unused_hpos.
+ If the cursor is at a standout marker, erase the marker.
+
+ Note that the cursor may be moved, on terminals lacking a `ce' string. */
+
+clear_end_of_line_raw (first_unused_hpos)
+ int first_unused_hpos;
+{
+ register int i;
+ first_unused_hpos += chars_wasted[curY] & 077;
+ if (clear_end_of_line_hook)
+ {
+ (*clear_end_of_line_hook) (first_unused_hpos);
+ return;
+ }
+ if (curX >= first_unused_hpos)
+ return;
+ /* Notice if we are erasing a magic cookie */
+ if (curX == 0)
+ chars_wasted[curY] = 0;
+ background_highlight ();
+ if (TS_clr_line)
+ {
+ OUTPUT1 (TS_clr_line);
+ }
+ else
+ { /* have to do it the hard way */
+ turn_off_insert ();
+ for (i = curX; i < first_unused_hpos; i++)
+ {
+ if (termscript)
+ fputc (' ', termscript);
+ putchar (' ');
+ }
+ cmplus (first_unused_hpos - curX);
+ }
+}
+
+output_chars (string, len)
+ register char *string;
+ int len;
+{
+ register char *p;
+ register int n;
+ register char *buf;
+ register int c;
+ char *first_check;
+
+ if (output_chars_hook)
+ {
+ (*output_chars_hook) (string, len);
+ return;
+ }
+ highlight_if_desired ();
+ turn_off_insert ();
+
+ /* Don't dare write in last column of bottom line, if AutoWrap,
+ since that would scroll the whole screen on some terminals. */
+
+ if (AutoWrap && curY + 1 == screen_height
+ && curX + len - (chars_wasted[curY] & 077) == screen_width)
+ len --;
+
+ cmplus (len);
+
+ first_check = string;
+
+ if (RPov > len && !TF_underscore && !TF_hazeltine)
+ {
+ fwrite (string, 1, len, stdout);
+ if (ferror (stdout))
+ clearerr (stdout);
+ if (termscript)
+ fwrite (string, 1, len, termscript);
+ }
+ else
+ while (--len >= 0)
+ {
+ c = *string;
+ if (RPov + 1 < len && string >= first_check)
+ {
+ int repeat_count;
+
+ p = string + 1;
+
+ /* Now, len is number of chars left starting at p */
+ while (*p++ == c);
+ p--;
+
+ repeat_count = p - string;
+ if (repeat_count > RPov)
+ {
+ buf = tparam (TS_repeat, 0, 0, *string, repeat_count);
+ tputs (buf, repeat_count, cmputc);
+ free (buf);
+ string = p;
+ len -= repeat_count - 1;
+ continue;
+ }
+ else
+ /* If all N identical chars are too few,
+ don't even consider the last N-1, the last N-2,... */
+ first_check = p;
+ }
+ if (c == '_' && TF_underscore)
+ {
+ if (termscript)
+ fputc (' ', termscript);
+ putchar (' ');
+ OUTPUT (Left);
+ }
+ if (TF_hazeltine && c == '~')
+ c = '`';
+ if (termscript)
+ fputc (c, termscript);
+ putchar (c);
+ string++;
+ }
+}
+
+/* If start is zero, insert blanks instead of a string at start */
+
+insert_chars (start, len)
+ register char *start;
+ int len;
+{
+ register char *buf;
+ register int c;
+
+ if (insert_chars_hook)
+ {
+ (*insert_chars_hook) (start, len);
+ return;
+ }
+ highlight_if_desired ();
+
+ if (TS_ins_multi_chars)
+ {
+ buf = tparam (TS_ins_multi_chars, 0, 0, len);
+ OUTPUT1 (buf);
+ free (buf);
+ if (start)
+ output_chars (start, len);
+ return;
+ }
+
+ turn_on_insert ();
+ cmplus (len);
+
+ if (!TF_underscore && !TF_hazeltine && start
+ && TS_pad_inserted_char == 0 && TS_ins_char == 0)
+ {
+ fwrite (start, 1, len, stdout);
+ if (termscript)
+ fwrite (start, 1, len, termscript);
+ }
+ else
+ while (--len >= 0)
+ {
+ OUTPUT1_IF (TS_ins_char);
+ if (!start)
+ c = ' ';
+ else
+ {
+ c = *start++;
+ if (TF_hazeltine && c == '~')
+ c = '`';
+ }
+ if (termscript)
+ fputc (c, termscript);
+ putchar (c);
+ OUTPUT1_IF (TS_pad_inserted_char);
+ }
+}
+
+delete_chars (n)
+ register int n;
+{
+ char *buf;
+ register int i;
+
+ if (delete_chars_hook)
+ {
+ (*delete_chars_hook) (n);
+ return;
+ }
+
+ if (delete_in_insert_mode)
+ {
+ turn_on_insert ();
+ }
+ else
+ {
+ turn_off_insert ();
+ OUTPUT_IF (TS_delete_mode);
+ }
+
+ if (TS_del_multi_chars)
+ {
+ buf = tparam (TS_del_multi_chars, 0, 0, n);
+ OUTPUT1 (buf);
+ free (buf);
+ }
+ else
+ for (i = 0; i < n; i++)
+ OUTPUT1 (TS_del_char);
+ if (!delete_in_insert_mode)
+ OUTPUT_IF (TS_end_delete_mode);
+}
+
+/* Insert N lines at vpos VPOS. If N is negative, delete -N lines. */
+
+ins_del_lines (vpos, n)
+ int vpos, n;
+{
+ char *multi = n > 0 ? TS_ins_multi_lines : TS_del_multi_lines;
+ char *single = n > 0 ? TS_ins_line : TS_del_line;
+ char *scroll = n > 0 ? TS_rev_scroll : TS_fwd_scroll;
+
+ register int i = n > 0 ? n : -n;
+ register char *buf;
+
+ if (ins_del_lines_hook)
+ {
+ (*ins_del_lines_hook) (vpos, n);
+ return;
+ }
+
+ /* If the lines below the insertion are being pushed
+ into the end of the window, this is the same as clearing;
+ and we know the lines are already clear, since the matching
+ deletion has already been done. So can ignore this. */
+ /* If the lines below the deletion are blank lines coming
+ out of the end of the window, don't bother,
+ as there will be a matching inslines later that will flush them. */
+ if (scroll_region_ok && vpos + i >= specified_window)
+ return;
+ if (!memory_below_screen && vpos + i >= screen_height)
+ return;
+
+ if (multi)
+ {
+ raw_move_cursor (vpos, 0);
+ background_highlight ();
+ buf = tparam (multi, 0, 0, i);
+ OUTPUT (buf);
+ free (buf);
+ }
+ else if (single)
+ {
+ raw_move_cursor (vpos, 0);
+ background_highlight ();
+ while (--i >= 0)
+ OUTPUT (single);
+ if (TF_teleray)
+ curX = 0;
+ }
+ else
+ {
+ set_scroll_region (vpos, specified_window);
+ if (n < 0)
+ raw_move_cursor (specified_window - 1, 0);
+ else
+ raw_move_cursor (vpos, 0);
+ background_highlight ();
+ while (--i >= 0)
+ OUTPUTL (scroll, specified_window - vpos);
+ set_scroll_region (0, specified_window);
+ }
+
+ if (TN_standout_width >= 0)
+ {
+ register lower_limit
+ = scroll_region_ok ? specified_window : screen_height;
+ if (n < 0)
+ {
+ bcopy (&chars_wasted[vpos - n], &chars_wasted[vpos],
+ lower_limit - vpos + n);
+ bzero (&chars_wasted[lower_limit + n], - n);
+ }
+ else
+ {
+ bcopy (&chars_wasted[vpos], &copybuf[vpos], lower_limit - vpos - n);
+ bcopy (&copybuf[vpos], &chars_wasted[vpos + n],
+ lower_limit - vpos - n);
+ bzero (&chars_wasted[vpos], n);
+ }
+ }
+ if (!scroll_region_ok && memory_below_screen && n < 0)
+ {
+ move_cursor (screen_height + n, 0);
+ clear_to_end ();
+ }
+}
+
+extern int cost; /* In cm.c */
+extern evalcost ();
+
+/* Compute cost of sending "str", in characters,
+ not counting any line-dependent padding. */
+string_cost (str)
+ char *str;
+{
+ cost = 0;
+ if (str)
+ tputs (str, 0, evalcost);
+ return cost;
+}
+
+/* Compute cost of sending "str", in characters,
+ counting any line-dependent padding at one line. */
+string_cost_one_line (str)
+ char *str;
+{
+ cost = 0;
+ if (str)
+ tputs (str, 1, evalcost);
+ return cost;
+}
+
+/* Compute per line amount of line-dependent padding,
+ in tenths of characters. */
+per_line_cost (str)
+ register char *str;
+{
+ cost = 0;
+ if (str)
+ tputs (str, 0, evalcost);
+ cost = - cost;
+ if (str)
+ tputs (str, 10, evalcost);
+ return cost;
+}
+
+/* ARGSUSED */
+calculate_ins_del_char_costs ()
+{
+ int ins_startup_cost, del_startup_cost;
+ int ins_cost_per_char, del_cost_per_char;
+ register int i;
+ register int *p;
+
+ if (TS_ins_multi_chars)
+ {
+ ins_cost_per_char = 0;
+ ins_startup_cost = string_cost_one_line (TS_ins_multi_chars);
+ }
+ else if (TS_ins_char || TS_pad_inserted_char
+ || (TS_insert_mode && TS_end_insert_mode))
+ {
+ ins_startup_cost = (30 * (string_cost (TS_insert_mode) + string_cost (TS_end_insert_mode))) / 100;
+ ins_cost_per_char = (string_cost_one_line (TS_ins_char)
+ + string_cost_one_line (TS_pad_inserted_char));
+ }
+ else
+ {
+ ins_startup_cost = 9999;
+ ins_cost_per_char = 0;
+ }
+
+ if (TS_del_multi_chars)
+ {
+ del_cost_per_char = 0;
+ del_startup_cost = string_cost_one_line (TS_del_multi_chars);
+ }
+ else if (TS_del_char)
+ {
+ del_startup_cost = (string_cost (TS_delete_mode)
+ + string_cost (TS_end_delete_mode));
+ if (delete_in_insert_mode)
+ del_startup_cost /= 2;
+ del_cost_per_char = string_cost_one_line (TS_del_char);
+ }
+ else
+ {
+ del_startup_cost = 9999;
+ del_cost_per_char = 0;
+ }
+
+ /* Delete costs are at negative offsets */
+ p = &DCICcost[0];
+ for (i = screen_width; --i >= 0;)
+ *--p = (del_startup_cost += del_cost_per_char);
+
+ /* Doing nothing is free */
+ p = &DCICcost[0];
+ *p++ = 0;
+
+ /* Insert costs are at positive offsets */
+ for (i = screen_width; --i >= 0;)
+ *p++ = (ins_startup_cost += ins_cost_per_char);
+}
+
+calculate_costs ()
+{
+ register char *s
+ = TS_set_scroll_region ? TS_set_scroll_region : TS_set_scroll_region_1;
+
+ if (chars_wasted != 0)
+ chars_wasted = (char *) xrealloc (chars_wasted, screen_height);
+ else
+ chars_wasted = (char *) xmalloc (screen_height);
+ bzero (chars_wasted, screen_height);
+
+ if (copybuf != 0)
+ copybuf = (char *) xrealloc (copybuf, screen_height);
+ else
+ copybuf = (char *) xmalloc (screen_height);
+
+ if (DC_ICcost != 0)
+ DC_ICcost = (int *) xrealloc (DC_ICcost,
+ (2 * screen_width + 1) * sizeof (int));
+ else
+ DC_ICcost = (int *) xmalloc ((2 * screen_width + 1) * sizeof (int));
+
+ /* Always call CalcIDCosts because it allocates some vectors.
+ That function handles dont_calculate_costs. */
+ if (s && (!TS_ins_line && !TS_del_line))
+ CalcIDCosts (TS_rev_scroll, TS_ins_multi_lines,
+ TS_fwd_scroll, TS_del_multi_lines,
+ s, s);
+ else
+ CalcIDCosts (TS_ins_line, TS_ins_multi_lines,
+ TS_del_line, TS_del_multi_lines,
+ 0, 0);
+
+ if (dont_calculate_costs)
+ {
+ bzero (DC_ICcost, 2 * screen_width * sizeof (int));
+ return;
+ }
+
+ calculate_ins_del_char_costs ();
+
+ /* Don't use TS_repeat if its padding is worse than sending the chars */
+ if (TS_repeat && per_line_cost (TS_repeat) * baud_rate < 9000)
+ RPov = string_cost (TS_repeat);
+ else
+ RPov = screen_width * 2;
+
+ cmcostinit (); /* set up cursor motion costs */
+}
+
+term_init (terminal_type)
+ char *terminal_type;
+{
+ char *area;
+ char **address = &area;
+ char buffer[4092];
+ register char *p;
+ int status;
+
+ extern char *tgetstr ();
+
+ Wcm_clear ();
+ dont_calculate_costs = 0;
+
+ status = tgetent (buffer, terminal_type);
+ if (status < 0)
+ fatal ("Cannot open termcap database file.\n");
+ if (status == 0)
+ fatal ("Terminal type %s is not defined.\n", terminal_type);
+
+#ifdef TERMINFO
+ area = (char *) malloc (4092);
+#else
+ area = (char *) malloc (strlen (buffer));
+#endif /* not TERMINFO */
+ if (area == 0)
+ abort ();
+
+ TS_ins_line = tgetstr ("al", address);
+ TS_ins_multi_lines = tgetstr ("AL", address);
+ TS_bell = tgetstr ("bl", address);
+ TS_clr_to_bottom = tgetstr ("cd", address);
+ TS_clr_line = tgetstr ("ce", address);
+ TS_clr_screen = tgetstr ("cl", address);
+ ColPosition = tgetstr ("ch", address);
+ AbsPosition = tgetstr ("cm", address);
+ CR = tgetstr ("cr", address);
+ TS_set_scroll_region = tgetstr ("cs", address);
+ TS_set_scroll_region_1 = tgetstr ("cS", address);
+ RowPosition = tgetstr ("cv", address);
+ TS_del_char = tgetstr ("dc", address);
+ TS_del_multi_chars = tgetstr ("DC", address);
+ TS_del_line = tgetstr ("dl", address);
+ TS_del_multi_lines = tgetstr ("DL", address);
+ TS_delete_mode = tgetstr ("dm", address);
+ TS_end_delete_mode = tgetstr ("ed", address);
+ TS_end_insert_mode = tgetstr ("ei", address);
+ Home = tgetstr ("ho", address);
+ TS_ins_char = tgetstr ("ic", address);
+ TS_ins_multi_chars = tgetstr ("IC", address);
+ TS_insert_mode = tgetstr ("im", address);
+ TS_pad_inserted_char = tgetstr ("ip", address);
+ TS_end_keypad_mode = tgetstr ("ke", address);
+ TS_keypad_mode = tgetstr ("ks", address);
+ LastLine = tgetstr ("ll", address);
+ Right = tgetstr ("nd", address);
+ Down = tgetstr ("do", address);
+ if (!Down)
+ Down = tgetstr ("nl", address); /* Obsolete name for "do" */
+#ifdef VMS
+ /* VMS puts a carriage return before each linefeed,
+ so it is not safe to use linefeeds. */
+ if (Down && Down[0] == '\n' && Down[1] == '\0')
+ Down = 0;
+#endif /* VMS */
+ if (tgetflag ("bs"))
+ Left = "\b"; /* can't possibly be longer! */
+ else /* (Actually, "bs" is obsolete...) */
+ Left = tgetstr ("le", address);
+ if (!Left)
+ Left = tgetstr ("bc", address); /* Obsolete name for "le" */
+ TS_pad_char = tgetstr ("pc", address);
+ TS_repeat = tgetstr ("rp", address);
+ TS_end_standout_mode = tgetstr ("se", address);
+ TS_fwd_scroll = tgetstr ("sf", address);
+ TS_standout_mode = tgetstr ("so", address);
+ TS_rev_scroll = tgetstr ("sr", address);
+ Wcm.cm_tab = tgetstr ("ta", address);
+ TS_end_termcap_modes = tgetstr ("te", address);
+ TS_termcap_modes = tgetstr ("ti", address);
+ Up = tgetstr ("up", address);
+ TS_visible_bell = tgetstr ("vb", address);
+ TS_end_visual_mode = tgetstr ("ve", address);
+ TS_visual_mode = tgetstr ("vs", address);
+ TS_set_window = tgetstr ("wi", address);
+
+ AutoWrap = tgetflag ("am");
+ memory_below_screen = tgetflag ("db");
+ TF_hazeltine = tgetflag ("hz");
+ must_write_spaces = tgetflag ("in");
+ meta_key = tgetflag ("km") || tgetflag ("MT");
+ TF_insmode_motion = tgetflag ("mi");
+ TF_standout_motion = tgetflag ("ms");
+ TF_underscore = tgetflag ("ul");
+ MagicWrap = tgetflag ("xn");
+ TF_xs = tgetflag ("xs");
+ TF_teleray = tgetflag ("xt");
+
+ /* Get screen size from system, or else from termcap. */
+ get_screen_size (&screen_width, &screen_height);
+ if (screen_width <= 0)
+ screen_width = tgetnum ("co");
+ if (screen_height <= 0)
+ screen_height = tgetnum ("li");
+
+ min_padding_speed = tgetnum ("pb");
+ TN_standout_width = tgetnum ("sg");
+ TabWidth = tgetnum ("tw");
+
+#ifdef VMS
+ /* These capabilities commonly use ^J.
+ I don't know why, but sending them on VMS does not work;
+ it causes following spaces to be lost, sometimes.
+ For now, the simplest fix is to avoid using these capabilities ever. */
+ if (Down && Down[0] == '\n')
+ Down = 0;
+#endif /* VMS */
+
+ if (!TS_bell)
+ TS_bell = "\07";
+
+ if (!TS_fwd_scroll)
+ TS_fwd_scroll = Down;
+
+ PC = TS_pad_char ? *TS_pad_char : 0;
+
+ if (TabWidth < 0)
+ TabWidth = 8;
+
+/* Turned off since /etc/termcap seems to have :ta= for most terminals
+ and newer termcap doc does not seem to say there is a default.
+ if (!Wcm.cm_tab)
+ Wcm.cm_tab = "\t";
+*/
+
+ if (TS_standout_mode == 0)
+ {
+ TN_standout_width = tgetnum ("ug");
+ TS_end_standout_mode = tgetstr ("ue", address);
+ TS_standout_mode = tgetstr ("us", address);
+ }
+
+ if (TF_teleray)
+ {
+ Wcm.cm_tab = 0;
+ /* Teleray: most programs want a space in front of TS_standout_mode,
+ but Emacs can do without it (and give one extra column). */
+ TS_standout_mode = "\033RD";
+ TN_standout_width = 1;
+ /* But that means we cannot rely on ^M to go to column zero! */
+ CR = 0;
+ /* LF can't be trusted either -- can alter hpos */
+ /* if move at column 0 thru a line with TS_standout_mode */
+ Down = 0;
+ }
+
+ /* Special handling for certain terminal types known to need it */
+
+ if (!strcmp (terminal_type, "supdup"))
+ {
+ memory_below_screen = 1;
+ Wcm.cm_losewrap = 1;
+ }
+ if (!strncmp (terminal_type, "c10", 3)
+ || !strcmp (terminal_type, "perq"))
+ {
+ /* Supply a makeshift :wi string.
+ This string is not valid in general since it works only
+ for windows starting at the upper left corner;
+ but that is all Emacs uses.
+
+ This string works only if the screen is using
+ the top of the video memory, because addressing is memory-relative.
+ So first check the :ti string to see if that is true.
+
+ It would be simpler if the :wi string could go in the termcap
+ entry, but it can't because it is not fully valid.
+ If it were in the termcap entry, it would confuse other programs. */
+ if (!TS_set_window)
+ {
+ p = TS_termcap_modes;
+ while (*p && strcmp (p, "\033v "))
+ p++;
+ if (*p)
+ TS_set_window = "\033v%C %C %C %C ";
+ }
+ /* Termcap entry often fails to have :in: flag */
+ must_write_spaces = 1;
+ /* :ti string typically fails to have \E^G! in it */
+ /* This limits scope of insert-char to one line. */
+ strcpy (area, TS_termcap_modes);
+ strcat (area, "\033\007!");
+ TS_termcap_modes = area;
+ area += strlen (area) + 1;
+ p = AbsPosition;
+ /* Change all %+ parameters to %C, to handle
+ values above 96 correctly for the C100. */
+ while (*p)
+ {
+ if (p[0] == '%' && p[1] == '+')
+ p[1] = 'C';
+ p++;
+ }
+ }
+
+ ScreenRows = screen_height;
+ ScreenCols = screen_width;
+ specified_window = screen_height;
+
+ if (Wcm_init ()) /* can't do cursor motion */
+#ifdef VMS
+ fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
+It lacks the ability to position the cursor.\n\
+If that is not the actual type of terminal you have, use either the\n\
+DCL command `SET TERMINAL/DEVICE= ...' for DEC-compatible terminals,\n\
+or `define EMACS_TERM \"terminal type\"' for non-DEC terminals.\n",
+ terminal_type);
+#else
+ fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
+It lacks the ability to position the cursor.\n\
+If that is not the actual type of terminal you have,\n\
+use the C-shell command `setenv TERM ...' to specify the correct type.\n\
+It may be necessary to do `unsetenv TERMCAP' as well.\n",
+ terminal_type);
+#endif
+
+ delete_in_insert_mode
+ = TS_delete_mode && TS_insert_mode
+ && !strcmp (TS_delete_mode, TS_insert_mode);
+
+ se_is_so = TS_standout_mode && TS_end_standout_mode
+ && !strcmp (TS_standout_mode, TS_end_standout_mode);
+
+ /* Remove width of standout marker from usable width of line */
+ if (TN_standout_width > 0)
+ screen_width -= TN_standout_width;
+
+ UseTabs = tabs_safe_p () && TabWidth == 8;
+
+ scroll_region_ok = TS_set_window || TS_set_scroll_region
+ || TS_set_scroll_region_1;
+
+ line_ins_del_ok = (((TS_ins_line || TS_ins_multi_lines)
+ && (TS_del_line || TS_del_multi_lines))
+ || (scroll_region_ok
+ && TS_fwd_scroll
+ && TS_rev_scroll));
+
+ char_ins_del_ok = ((TS_ins_char || TS_insert_mode ||
+ TS_pad_inserted_char || TS_ins_multi_chars)
+ && (TS_del_char || TS_del_multi_chars));
+
+ fast_clear_end_of_line = TS_clr_line != 0;
+
+ init_baud_rate ();
+ if (read_socket_hook) /* Baudrate is somewhat */
+ /* meaningless in this case */
+ baud_rate = 9600;
+}
+
+/* VARARGS 1 */
+fatal (str, arg1, arg2)
+ char *str;
+{
+ fprintf (stderr, "emacs: ");
+ fprintf (stderr, str, arg1, arg2);
+ fflush (stderr);
+ exit (1);
+}
diff --git a/src/termcap.c b/src/termcap.c
new file mode 100644
index 00000000000..8cfba607b78
--- /dev/null
+++ b/src/termcap.c
@@ -0,0 +1,661 @@
+/* Work-alike for termcap, plus extra features.
+ Copyright (C) 1985, 1986 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+In other words, you are welcome to use, share and improve this program.
+You are forbidden to forbid anyone else to use, share and improve
+what you give them. Help stamp out software-hoarding! */
+
+
+
+/* BUFSIZE is the initial size allocated for the buffer
+ for reading the termcap file.
+ It is not a limit.
+ Make it large normally for speed.
+ Make it variable when debugging, so can exercise
+ increasing the space dynamically. */
+
+#ifdef emacs
+#include "config.h"
+#endif
+
+#ifndef BUFSIZE
+#ifdef DEBUG
+#define BUFSIZE bufsize
+
+int bufsize = 128;
+#else
+#define BUFSIZE 2048
+#endif
+#endif
+
+#ifndef emacs
+static
+memory_out ()
+{
+ write (2, "Virtual memory exhausted\n", 25);
+ exit (1);
+}
+
+static int
+xmalloc (size)
+ int size;
+{
+ register tem = malloc (size);
+ if (!tem)
+ memory_out ();
+ return tem;
+}
+
+static int
+xrealloc (ptr, size)
+ int ptr;
+ int size;
+{
+ register tem = realloc (ptr, size);
+ if (!tem)
+ memory_out ();
+ return tem;
+}
+#endif /* not emacs */
+
+/* Looking up capabilities in the entry already found */
+
+/* The pointer to the data made by tgetent is left here
+ for tgetnum, tgetflag and tgetstr to find. */
+
+static char *term_entry;
+
+static char *tgetst1 ();
+
+/* This is the main subroutine that is used to search
+ an entry for a particular capability */
+
+static char *
+find_capability (bp, cap)
+ register char *bp, *cap;
+{
+ for (; *bp; bp++)
+ if (bp[0] == ':'
+ && bp[1] == cap[0]
+ && bp[2] == cap[1])
+ return &bp[4];
+ return 0;
+}
+
+int
+tgetnum (cap)
+ char *cap;
+{
+ register char *ptr = find_capability (term_entry, cap);
+ if (!ptr || ptr[-1] != '#')
+ return -1;
+ return atoi (ptr);
+}
+
+int
+tgetflag (cap)
+ char *cap;
+{
+ register char *ptr = find_capability (term_entry, cap);
+ return 0 != ptr && ptr[-1] == ':';
+}
+
+/* Look up a string-valued capability `cap'.
+ If `area' is nonzero, it points to a pointer to a block in which
+ to store the string. That pointer is advanced over the space used.
+ If `area' is zero, space is allocated with `malloc'. */
+
+char *
+tgetstr (cap, area)
+ char *cap;
+ char **area;
+{
+ register char *ptr = find_capability (term_entry, cap);
+ if (!ptr || (ptr[-1] != '=' && ptr[-1] != '~'))
+ return 0;
+ return tgetst1 (ptr, area);
+}
+
+/* Table, indexed by a character in range 0100 to 0140 with 0100 subtracted,
+ gives meaning of character following \, or a space if no special meaning.
+ Eight characters per line within the string. */
+
+static char esctab[]
+ = " \007\010 \033\014 \
+ \012 \
+ \015 \011 \013 \
+ ";
+
+/* Given a pointer to a string value inside a termcap entry (`ptr'),
+ copy the value and process \ and ^ abbreviations.
+ Copy into block that *area points to,
+ or to newly allocated storage if area is 0. */
+
+static char *
+tgetst1 (ptr, area)
+ char *ptr;
+ char **area;
+{
+ register char *p, *r;
+ register int c;
+ register int size;
+ char *ret;
+ register int c1;
+
+ if (!ptr)
+ return 0;
+
+ /* `ret' gets address of where to store the string */
+ if (!area)
+ {
+ /* Compute size of block needed (may overestimate) */
+ p = ptr;
+ while ((c = *p++) && c != ':' && c != '\n');
+ ret = (char *) xmalloc (p - ptr + 1);
+ }
+ else
+ ret = *area;
+
+ /* Copy the string value, stopping at null or colon. */
+ /* Also process ^ and \ abbreviations. */
+ p = ptr;
+ r = ret;
+ while ((c = *p++) && c != ':' && c != '\n')
+ {
+ if (c == '^')
+ c = *p++ & 037;
+ else if (c == '\\')
+ {
+ c = *p++;
+ if (c >= '0' && c <= '7')
+ {
+ c -= '0';
+ size = 0;
+
+ while (++size < 3 && (c1 = *p) >= '0' && c1 <= '7')
+ {
+ c *= 8;
+ c += c1 - '0';
+ p++;
+ }
+ }
+ else if (c >= 0100 && c < 0200)
+ {
+ c1 = esctab[(c & ~040) - 0100];
+ if (c1 != ' ')
+ c = c1;
+ }
+ }
+ *r++ = c;
+ }
+ *r = 0;
+ /* Update *area */
+ if (area)
+ *area = r + 1;
+ return ret;
+}
+
+/* Outputting a string with padding */
+
+short ospeed;
+char PC;
+
+/* Actual baud rate if positive;
+ - baud rate / 100 if negative. */
+
+static short speeds[] =
+ {
+#ifdef VMS
+ 0, 50, 75, 110, 134, 150, -3, -6, -12, -18,
+ -20, -24, -36, -48, -72, -96, -192
+#else /* not VMS */
+ 0, 50, 75, 110, 135, 150, -2, -3, -6, -12,
+ -18, -24, -48, -96, -192, -384
+#endif /* not VMS */
+ };
+
+tputs (string, nlines, outfun)
+ register char *string;
+ int nlines;
+ register int (*outfun) ();
+{
+ register int padcount = 0;
+
+ if (string == (char *) 0)
+ return;
+ while (*string >= '0' && *string <= '9')
+ {
+ padcount += *string++ - '0';
+ padcount *= 10;
+ }
+ if (*string == '.')
+ {
+ string++;
+ padcount += *string++ - '0';
+ }
+ if (*string == '*')
+ {
+ string++;
+ padcount *= nlines;
+ }
+ while (*string)
+ (*outfun) (*string++);
+
+ /* padcount is now in units of tenths of msec. */
+ padcount *= speeds[ospeed];
+ padcount += 500;
+ padcount /= 1000;
+ if (speeds[ospeed] < 0)
+ padcount = -padcount;
+ else
+ {
+ padcount += 50;
+ padcount /= 100;
+ }
+
+ while (padcount-- > 0)
+ (*outfun) (PC);
+}
+
+/* Finding the termcap entry in the termcap data base */
+
+struct buffer
+ {
+ char *beg;
+ int size;
+ char *ptr;
+ int ateof;
+ int full;
+ };
+
+/* Forward declarations of static functions */
+
+static int scan_file ();
+static char *gobble_line ();
+static int compare_contin ();
+static int name_match ();
+
+#ifdef VMS
+
+#include <rmsdef.h>
+#include <fab.h>
+#include <nam.h>
+
+static int
+legal_filename_p (fn)
+ char *fn;
+{
+ struct FAB fab = cc$rms_fab;
+ struct NAM nam = cc$rms_nam;
+ char esa[NAM$C_MAXRSS];
+
+ fab.fab$l_fna = fn;
+ fab.fab$b_fns = strlen(fn);
+ fab.fab$l_nam = &nam;
+ fab.fab$l_fop = FAB$M_NAM;
+
+ nam.nam$l_esa = esa;
+ nam.nam$b_ess = sizeof esa;
+
+ return SYS$PARSE(&fab, 0, 0) == RMS$_NORMAL;
+}
+
+#endif /* VMS */
+
+/* Find the termcap entry data for terminal type `name'
+ and store it in the block that `bp' points to.
+ Record its address for future use.
+
+ If `bp' is zero, space is dynamically allocated. */
+
+int
+tgetent (bp, name)
+ char *bp, *name;
+{
+ register char *tem;
+ register int fd;
+ struct buffer buf;
+ register char *bp1;
+ char *bp2;
+ char *term;
+ int malloc_size = 0;
+ register int c;
+ char *tcenv; /* TERMCAP value, if it contais :tc=. */
+ char *indirect = 0; /* Terminal type in :tc= in TERMCAP value. */
+ int filep;
+
+ tem = (char *) getenv ("TERMCAP");
+ if (tem && *tem == 0) tem = 0;
+
+#ifdef VMS
+ filep = tem && legal_filename_p (tem);
+#else
+ filep = tem && (*tem == '/');
+#endif /* VMS */
+
+ /* If tem is non-null and starts with / (in the un*x case, that is),
+ it is a file name to use instead of /etc/termcap.
+ If it is non-null and does not start with /,
+ it is the entry itself, but only if
+ the name the caller requested matches the TERM variable. */
+
+ if (tem && !filep && !strcmp (name, getenv ("TERM")))
+ {
+ indirect = tgetst1 (find_capability (tem, "tc"), 0);
+ if (!indirect)
+ {
+ if (!bp)
+ bp = tem;
+ else
+ strcpy (bp, tem);
+ goto ret;
+ }
+ else
+ { /* we will need to read /etc/termcap */
+ tcenv = tem;
+ tem = 0;
+ }
+ }
+ else
+ indirect = (char *) 0;
+
+ if (!tem)
+#ifdef VMS
+ tem = "emacs_library:[etc]termcap.dat";
+#else
+ tem = "/etc/termcap";
+#endif
+
+ /* Here we know we must search a file and tem has its name. */
+
+ fd = open (tem, 0, 0);
+ if (fd < 0)
+ return -1;
+
+ buf.size = BUFSIZE;
+ /* Add 1 to size to ensure room for terminating null. */
+ buf.beg = (char *) xmalloc (buf.size + 1);
+ term = indirect ? indirect : name;
+
+ if (!bp)
+ {
+ malloc_size = indirect ? strlen (tcenv) + 1 : buf.size;
+ bp = (char *) xmalloc (malloc_size);
+ }
+ bp1 = bp;
+
+ if (indirect) /* copy the data from the environment variable */
+ {
+ strcpy (bp, tcenv);
+ bp1 += strlen (tcenv);
+ }
+
+ while (term)
+ {
+ /* Scan file, reading it via buf, till find start of main entry */
+ if (scan_file (term, fd, &buf) == 0)
+ return 0;
+
+ /* Free old `term' if appropriate. */
+ if (term != name)
+ free (term);
+
+ /* If `bp' is malloc'd by us, make sure it is big enough. */
+ if (malloc_size)
+ {
+ malloc_size = bp1 - bp + buf.size;
+ tem = (char *) xrealloc (bp, malloc_size);
+ bp1 += tem - bp;
+ bp = tem;
+ }
+
+ bp2 = bp1;
+
+ /* Copy the line of the entry from buf into bp. */
+ tem = buf.ptr;
+ while ((*bp1++ = c = *tem++) && c != '\n')
+ /* Drop out any \ newline sequence. */
+ if (c == '\\' && *tem == '\n')
+ {
+ bp1--;
+ tem++;
+ }
+ *bp1 = 0;
+
+ /* Does this entry refer to another terminal type's entry? */
+ /* If something is found, copy it into heap and null-terminate it */
+ term = tgetst1 (find_capability (bp2, "tc"), 0);
+ }
+
+ close (fd);
+ free (buf.beg);
+
+ if (malloc_size)
+ {
+ bp = (char *) xrealloc (bp, bp1 - bp + 1);
+ }
+
+ ret:
+ term_entry = bp;
+ if (malloc_size)
+ return (int) bp;
+ return 1;
+}
+
+/* Given file open on `fd' and buffer `bufp',
+ scan the file from the beginning until a line is found
+ that starts the entry for terminal type `string'.
+ Returns 1 if successful, with that line in `bufp',
+ or returns 0 if no entry found in the file. */
+
+static int
+scan_file (string, fd, bufp)
+ char *string;
+ int fd;
+ register struct buffer *bufp;
+{
+ register char *tem;
+ register char *end;
+
+ bufp->ptr = bufp->beg;
+ bufp->full = 0;
+ bufp->ateof = 0;
+ *bufp->ptr = 0;
+
+ lseek (fd, 0L, 0);
+
+ while (!bufp->ateof)
+ {
+ /* Read a line into the buffer */
+ end = 0;
+ do
+ {
+ /* if it is continued, append another line to it,
+ until a non-continued line ends */
+ end = gobble_line (fd, bufp, end);
+ }
+ while (!bufp->ateof && end[-2] == '\\');
+
+ if (*bufp->ptr != '#'
+ && name_match (bufp->ptr, string))
+ return 1;
+
+ /* Discard the line just processed */
+ bufp->ptr = end;
+ }
+ return 0;
+}
+
+/* Return nonzero if NAME is one of the names specified
+ by termcap entry LINE. */
+
+static int
+name_match (line, name)
+ char *line, *name;
+{
+ register char *tem;
+
+ if (!compare_contin (line, name))
+ return 1;
+ /* This line starts an entry. Is it the right one? */
+ for (tem = line; *tem && *tem != '\n' && *tem != ':'; tem++)
+ if (*tem == '|' && !compare_contin (tem + 1, name))
+ return 1;
+
+ return 0;
+}
+
+static int
+compare_contin (str1, str2)
+ register char *str1, *str2;
+{
+ register int c1, c2;
+ while (1)
+ {
+ c1 = *str1++;
+ c2 = *str2++;
+ while (c1 == '\\' && *str1 == '\n')
+ {
+ str1++;
+ while ((c1 = *str1++) == ' ' || c1 == '\t');
+ }
+ if (c2 == '\0') /* end of type being looked up */
+ {
+ if (c1 == '|' || c1 == ':') /* If end of name in data base, */
+ return 0; /* we win. */
+ else
+ return 1;
+ }
+ else if (c1 != c2)
+ return 1;
+ }
+}
+
+/* Make sure that the buffer <- `bufp' contains a full line
+ of the file open on `fd', starting at the place `bufp->ptr'
+ points to. Can read more of the file, discard stuff before
+ `bufp->ptr', or make the buffer bigger.
+
+ Returns the pointer to after the newline ending the line,
+ or to the end of the file, if there is no newline to end it.
+
+ Can also merge on continuation lines. If `append_end' is
+ nonzero, it points past the newline of a line that is
+ continued; we add another line onto it and regard the whole
+ thing as one line. The caller decides when a line is continued. */
+
+static char *
+gobble_line (fd, bufp, append_end)
+ int fd;
+ register struct buffer *bufp;
+ char *append_end;
+{
+ register char *end;
+ register int nread;
+ register char *buf = bufp->beg;
+ register char *tem;
+
+ if (append_end == 0)
+ append_end = bufp->ptr;
+
+ while (1)
+ {
+ end = append_end;
+ while (*end && *end != '\n') end++;
+ if (*end)
+ break;
+ if (bufp->ateof)
+ return buf + bufp->full;
+ if (bufp->ptr == buf)
+ {
+ if (bufp->full == bufp->size)
+ {
+ bufp->size *= 2;
+ /* Add 1 to size to ensure room for terminating null. */
+ tem = (char *) xrealloc (buf, bufp->size + 1);
+ bufp->ptr = (bufp->ptr - buf) + tem;
+ append_end = (append_end - buf) + tem;
+ bufp->beg = buf = tem;
+ }
+ }
+ else
+ {
+ append_end -= bufp->ptr - buf;
+ bcopy (bufp->ptr, buf, bufp->full -= bufp->ptr - buf);
+ bufp->ptr = buf;
+ }
+ if (!(nread = read (fd, buf + bufp->full, bufp->size - bufp->full)))
+ bufp->ateof = 1;
+ bufp->full += nread;
+ buf[bufp->full] = 0;
+ }
+ return end + 1;
+}
+
+#ifdef TEST
+
+#include <stdio.h>
+
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ char *term;
+ char *buf;
+
+ term = argv[1];
+ printf ("TERM: %s\n", term);
+
+ buf = (char *) tgetent (0, term);
+ if ((int) buf <= 0)
+ {
+ printf ("No entry.\n");
+ return 0;
+ }
+
+ printf ("Entry: %s\n", buf);
+
+ tprint ("cm");
+ tprint ("AL");
+
+ printf ("co: %d\n", tgetnum ("co"));
+ printf ("am: %d\n", tgetflag ("am"));
+}
+
+tprint (cap)
+ char *cap;
+{
+ char *x = tgetstr (cap, 0);
+ register char *y;
+
+ printf ("%s: ", cap);
+ if (x)
+ {
+ for (y = x; *y; y++)
+ if (*y <= ' ' || *y == 0177)
+ printf ("\\%0o", *y);
+ else
+ putchar (*y);
+ free (x);
+ }
+ else
+ printf ("none");
+ putchar ('\n');
+}
+
+#endif /* TEST */
+
diff --git a/src/termchar.h b/src/termchar.h
new file mode 100644
index 00000000000..8125ca2715a
--- /dev/null
+++ b/src/termchar.h
@@ -0,0 +1,48 @@
+/* Flags and parameters describing terminal's characteristics.
+ Copyright (C) 1985, 1986 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+extern int baud_rate; /* Output speed in baud */
+extern int screen_width; /* Number of usable columns */
+extern int screen_height; /* Number of lines */
+extern int must_write_spaces; /* Nonzero means spaces in the text
+ must actually be output; can't just skip
+ over some columns to leave them blank. */
+extern int min_padding_speed; /* Speed below which no padding necessary */
+extern int fast_clear_end_of_line; /* Nonzero means terminal has command for this */
+
+extern int line_ins_del_ok; /* Terminal can insert and delete lines */
+extern int char_ins_del_ok; /* Terminal can insert and delete chars */
+extern int scroll_region_ok; /* Terminal supports setting the scroll window */
+extern int memory_below_screen; /* Terminal remembers lines scrolled off bottom */
+extern int fast_clear_end_of_line; /* Terminal has a `ce' string */
+
+extern int dont_calculate_costs; /* Nonzero means don't bother computing */
+ /* various cost tables; we won't use them. */
+
+/* Nonzero means no need to redraw the entire screen on resuming
+ a suspended Emacs. This is useful on terminals with multiple pages,
+ where one page is used for Emacs and another for all else. */
+extern int no_redraw_on_reenter;
+
+/* DCICcost[n] is cost of inserting N characters.
+ DCICcost[-n] is cost of deleting N characters. */
+
+#define DCICcost (&DC_ICcost[screen_width])
+extern int *DC_ICcost;
diff --git a/src/termhooks.h b/src/termhooks.h
new file mode 100644
index 00000000000..bec2c3aa119
--- /dev/null
+++ b/src/termhooks.h
@@ -0,0 +1,53 @@
+/* Hooks by which low level terminal operations
+ can be made to call other routines.
+ Copyright (C) 1985, 1986 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+extern int (*move_cursor_hook) ();
+extern int (*raw_move_cursor_hook) ();
+
+extern int (*clear_to_end_hook) ();
+extern int (*clear_screen_hook) ();
+extern int (*clear_end_of_line_hook) ();
+
+extern int (*ins_del_lines_hook) ();
+
+extern int (*change_line_highlight_hook) ();
+extern int (*reassert_line_highlight_hook) ();
+
+extern int (*insert_chars_hook) ();
+extern int (*output_chars_hook) ();
+extern int (*delete_chars_hook) ();
+
+extern int (*ring_bell_hook) ();
+
+extern int (*reset_terminal_modes_hook) ();
+extern int (*set_terminal_modes_hook) ();
+extern int (*update_begin_hook) ();
+extern int (*update_end_hook) ();
+extern int (*set_terminal_window_hook) ();
+
+extern int (*read_socket_hook) ();
+extern int (*fix_screen_hook) ();
+extern int (*calculate_costs_hook) ();
+
+/* If nonzero, send all terminal output characters to this stream also. */
+
+extern FILE *termscript;
+
diff --git a/src/terminfo.c b/src/terminfo.c
new file mode 100644
index 00000000000..af057133e50
--- /dev/null
+++ b/src/terminfo.c
@@ -0,0 +1,50 @@
+/* Interface from Emacs to terminfo.
+ Copyright (C) 1985, 1986 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Define these variables that serve as global parameters to termcap,
+ so that we do not need to conditionalize the places in Emacs
+ that set them. */
+
+char *UP, *BC, PC;
+short ospeed;
+
+static buffer[512];
+
+/* Interface to curses/terminfo library.
+ Turns out that all of the terminfo-level routines look
+ like their termcap counterparts except for tparm, which replaces
+ tgoto. Not only is the calling sequence different, but the string
+ format is different too.
+*/
+
+char *
+tparam (string, outstring, len, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9)
+ char *string;
+ char *outstring;
+ int arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9;
+{
+ char *temp;
+ extern char *tparm();
+
+ temp = tparm (string, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
+ if (outstring == 0)
+ outstring = ((char *) (malloc ((strlen (temp)) + 1)));
+ strcpy (outstring, temp);
+ return outstring;
+}
diff --git a/src/termopts.h b/src/termopts.h
new file mode 100644
index 00000000000..6237baaee09
--- /dev/null
+++ b/src/termopts.h
@@ -0,0 +1,47 @@
+/* Flags and paramaters describing user options for handling the terminal.
+ Copyright (C) 1985, 1986 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* Nonzero means flash the screen instead of ringing the bell. */
+
+extern int visible_bell;
+
+/* Nonzero means invert white and black for the entire screen. */
+
+extern int inverse_video;
+
+/* Nonzero means use ^S/^Q as cretinous flow control. */
+
+extern int flow_control;
+
+/* Nonzero means use interrupt-driven input. */
+
+extern int interrupt_input;
+
+/* Nonzero while interrupts are temporarily deferred during redisplay. */
+
+extern int interrupts_deferred;
+
+/* Nonzero if terminal has a meta key. */
+
+extern int meta_key;
+
+/* Nonzero means truncate lines in all windows less wide than the screen */
+
+extern int truncate_partial_width_windows;
diff --git a/src/testemacs.com b/src/testemacs.com
new file mode 100644
index 00000000000..6cb458adebc
--- /dev/null
+++ b/src/testemacs.com
@@ -0,0 +1,4 @@
+$ ! VMS command file to make definitions so that you can run
+$ ! `temacs.exe' with the data file just dumped by build.com.
+$
+$ runtemacs :== $sys$disk:[]temacs -map temacs.dump
diff --git a/src/tparam.c b/src/tparam.c
new file mode 100644
index 00000000000..f573e95a23c
--- /dev/null
+++ b/src/tparam.c
@@ -0,0 +1,277 @@
+/* Merge parameters into a termcap entry string.
+ Copyright (C) 1985, 1987 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+In other words, you are welcome to use, share and improve this program.
+You are forbidden to forbid anyone else to use, share and improve
+what you give them. Help stamp out software-hoarding! */
+
+
+/* config.h may rename various library functions such as malloc. */
+#ifdef emacs
+#include "config.h"
+#endif
+
+/* Assuming STRING is the value of a termcap string entry
+ containing `%' constructs to expand parameters,
+ merge in parameter values and store result in block OUTSTRING points to.
+ LEN is the length of OUTSTRING. If more space is needed,
+ a block is allocated with `malloc'.
+
+ The value returned is the address of the resulting string.
+ This may be OUTSTRING or may be the address of a block got with `malloc'.
+ In the latter case, the caller must free the block.
+
+ The fourth and following args to tparam serve as the parameter values. */
+
+static char *tparam1 ();
+
+/* VARARGS 2 */
+char *
+tparam (string, outstring, len, arg0, arg1, arg2, arg3)
+ char *string;
+ char *outstring;
+ int len;
+ int arg0, arg1, arg2, arg3;
+{
+#ifdef NO_ARG_ARRAY
+ int arg[4];
+ arg[0] = arg0;
+ arg[1] = arg1;
+ arg[2] = arg2;
+ arg[3] = arg3;
+ return tparam1 (string, outstring, len, 0, 0, arg);
+#else
+ return tparam1 (string, outstring, len, 0, 0, &arg0);
+#endif
+}
+
+char *BC;
+char *UP;
+
+static char tgoto_buf[50];
+
+char *
+tgoto (cm, hpos, vpos)
+ char *cm;
+ int hpos, vpos;
+{
+ int args[2];
+ if (!cm)
+ return 0;
+ args[0] = vpos;
+ args[1] = hpos;
+ return tparam1 (cm, tgoto_buf, 50, UP, BC, args);
+}
+
+static char *
+tparam1 (string, outstring, len, up, left, argp)
+ char *string;
+ char *outstring;
+ int len;
+ char *up, *left;
+ register int *argp;
+{
+ register int c;
+ register char *p = string;
+ register char *op = outstring;
+ char *outend;
+ int outlen = 0;
+
+ register int tem;
+ int *oargp = argp;
+ int doleft = 0;
+ int doup = 0;
+
+ outend = outstring + len;
+
+ while (1)
+ {
+ /* If the buffer might be too short, make it bigger. */
+ if (op + 5 >= outend)
+ {
+ register char *new;
+ if (outlen == 0)
+ {
+ new = (char *) malloc (outlen = 40 + len);
+ outend += 40;
+ bcopy (outstring, new, op - outstring);
+ }
+ else
+ {
+ outend += outlen;
+ new = (char *) realloc (outstring, outlen *= 2);
+ }
+ op += new - outstring;
+ outend += new - outstring;
+ outstring = new;
+ }
+ if (!(c = *p++))
+ break;
+ if (c == '%')
+ {
+ c = *p++;
+ tem = *argp;
+ switch (c)
+ {
+ case 'd': /* %d means output in decimal */
+ if (tem < 10)
+ goto onedigit;
+ if (tem < 100)
+ goto twodigit;
+ case '3': /* %3 means output in decimal, 3 digits. */
+ if (tem > 999)
+ {
+ *op++ = tem / 1000 + '0';
+ tem %= 1000;
+ }
+ *op++ = tem / 100 + '0';
+ case '2': /* %2 means output in decimal, 2 digits. */
+ twodigit:
+ tem %= 100;
+ *op++ = tem / 10 + '0';
+ onedigit:
+ *op++ = tem % 10 + '0';
+ argp++;
+ break;
+
+ case 'C':
+ /* For c-100: print quotient of value by 96, if nonzero,
+ then do like %+ */
+ if (tem >= 96)
+ {
+ *op++ = tem / 96;
+ tem %= 96;
+ }
+ case '+': /* %+x means add character code of char x */
+ tem += *p++;
+ case '.': /* %. means output as character */
+ if (left)
+ {
+ /* If want to forbid output of 0 and \n and \t,
+ and this is one of them, increment it. */
+ while (tem == 0 || tem == '\n' || tem == '\t')
+ {
+ tem++;
+ if (argp == oargp)
+ doup++, outend -= strlen (up);
+ else
+ doleft++, outend -= strlen (left);
+ }
+ }
+ *op++ = tem | 0200;
+ case 'f': /* %f means discard next arg */
+ argp++;
+ break;
+
+ case 'b': /* %b means back up one arg (and re-use it) */
+ argp--;
+ break;
+
+ case 'r': /* %r means interchange following two args */
+ argp[0] = argp[1];
+ argp[1] = tem;
+ oargp++;
+ break;
+
+ case '>': /* %>xy means if arg is > char code of x, */
+ if (argp[0] > *p++) /* then add char code of y to the arg, */
+ argp[0] += *p; /* and in any case don't output. */
+ p++; /* Leave the arg to be output later. */
+ break;
+
+ case 'a': /* %a means arithmetic */
+ /* Next character says what operation.
+ Add or subtract either a constant or some other arg */
+ /* First following character is + to add or - to subtract
+ or = to assign. */
+ /* Next following char is 'p' and an arg spec
+ (0100 plus position of that arg relative to this one)
+ or 'c' and a constant stored in a character */
+ tem = p[2] & 0177;
+ if (p[1] == 'p')
+ tem = argp[tem - 0100];
+ if (p[0] == '-')
+ argp[0] -= tem;
+ else if (p[0] == '+')
+ argp[0] += tem;
+ else if (p[0] == '*')
+ argp[0] *= tem;
+ else if (p[0] == '/')
+ argp[0] /= tem;
+ else
+ argp[0] = tem;
+
+ p += 3;
+ break;
+
+ case 'i': /* %i means add one to arg, */
+ argp[0] ++; /* and leave it to be output later. */
+ argp[1] ++; /* Increment the following arg, too! */
+ break;
+
+ case '%': /* %% means output %; no arg. */
+ goto ordinary;
+
+ case 'n': /* %n means xor each of next two args with 140 */
+ argp[0] ^= 0140;
+ argp[1] ^= 0140;
+ break;
+
+ case 'm': /* %m means xor each of next two args with 177 */
+ argp[0] ^= 0177;
+ argp[1] ^= 0177;
+ break;
+
+ case 'B': /* %B means express arg as BCD char code. */
+ argp[0] += 6 * (tem / 10);
+ break;
+
+ case 'D': /* %D means weird Delta Data transformation */
+ argp[0] -= 2 * (tem % 16);
+ break;
+ }
+ }
+ else
+ /* Ordinary character in the argument string. */
+ ordinary:
+ *op++ = c;
+ }
+ *op = 0;
+ while (doup-- > 0)
+ strcat (op, up);
+ while (doleft-- > 0)
+ strcat (op, left);
+ return outstring;
+}
+
+#ifdef DEBUG
+
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ char buf[50];
+ int args[3];
+ args[0] = atoi (argv[2]);
+ args[1] = atoi (argv[3]);
+ args[2] = atoi (argv[4]);
+ tparam1 (argv[1], buf, "LEFT", "UP", args);
+ printf ("%s\n", buf);
+ return 0;
+}
+
+#endif /* DEBUG */
diff --git a/src/uaf.h b/src/uaf.h
index 2b351a2738b..2c9387e8942 100644
--- a/src/uaf.h
+++ b/src/uaf.h
@@ -3,20 +3,19 @@
This file is part of GNU Emacs.
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY. No author or distributor
-accepts responsibility to anyone for the consequences of using it
-or for whether it serves any particular purpose or works at all,
-unless he says so in writing. Refer to the GNU Emacs General Public
-License for full details.
+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.
-Everyone is granted permission to copy, modify and redistribute
-GNU Emacs, but only under the conditions described in the
-GNU Emacs General Public License. A copy of this license is
-supposed to have been given to you along with GNU Emacs so you
-can know your rights and responsibilities. It should be in a
-file named COPYING. Among other things, the copyright notice
-and this notice must be preserved on all copies. */
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/*
* User Authorization File record formats
diff --git a/src/undo.c b/src/undo.c
index 02c89f3779d..4e1ec3b3d2c 100644
--- a/src/undo.c
+++ b/src/undo.c
@@ -3,20 +3,19 @@
This file is part of GNU Emacs.
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY. No author or distributor
-accepts responsibility to anyone for the consequences of using it
-or for whether it serves any particular purpose or works at all,
-unless he says so in writing. Refer to the GNU Emacs General Public
-License for full details.
+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.
-Everyone is granted permission to copy, modify and redistribute
-GNU Emacs, but only under the conditions described in the
-GNU Emacs General Public License. A copy of this license is
-supposed to have been given to you along with GNU Emacs so you
-can know your rights and responsibilities. It should be in a
-file named COPYING. Among other things, the copyright notice
-and this notice must be preserved on all copies. */
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "config.h"
@@ -72,7 +71,7 @@ record_insert (beg, length)
record_delete (beg, length)
int beg, length;
{
- Lisp_Object lbeg, lend, sbeg;
+ Lisp_Object lbeg, llength, lend, sbeg;
if (current_buffer != XBUFFER (last_undo_buffer))
Fundo_boundary ();
@@ -88,10 +87,10 @@ record_delete (beg, length)
else
XFASTINT (sbeg) = beg;
XFASTINT (lbeg) = beg;
+ XFASTINT (llength) = length;
XFASTINT (lend) = beg + length;
- current_buffer->undo_list
- = Fcons (Fcons (Fbuffer_substring (lbeg, lend), sbeg),
- current_buffer->undo_list);
+ current_buffer->undo_list = Fcons (Fcons (Fbuffer_substring (lbeg, lend), sbeg),
+ current_buffer->undo_list);
}
/* Record that a replacement is about to take place,
@@ -143,47 +142,12 @@ truncate_undo_list (list, minsize, maxsize)
Lisp_Object list;
int minsize, maxsize;
{
- Lisp_Object prev, next, last_boundary;
+ Lisp_Object prev, next, save_prev;
int size_so_far = 0;
prev = Qnil;
next = list;
- last_boundary = Qnil;
-
- /* Always preserve at least the most recent undo record.
- If the first element is an undo boundary, skip past it. */
- if (XTYPE (next) == Lisp_Cons
- && XCONS (next)->car == Qnil)
- {
- /* Add in the space occupied by this element and its chain link. */
- size_so_far += sizeof (struct Lisp_Cons);
-
- /* Advance to next element. */
- prev = next;
- next = XCONS (next)->cdr;
- }
- while (XTYPE (next) == Lisp_Cons
- && XCONS (next)->car != Qnil)
- {
- Lisp_Object elt;
- elt = XCONS (next)->car;
-
- /* Add in the space occupied by this element and its chain link. */
- size_so_far += sizeof (struct Lisp_Cons);
- if (XTYPE (elt) == Lisp_Cons)
- {
- size_so_far += sizeof (struct Lisp_Cons);
- if (XTYPE (XCONS (elt)->car) == Lisp_String)
- size_so_far += (sizeof (struct Lisp_String) - 1
- + XSTRING (XCONS (elt)->car)->size);
- }
-
- /* Advance to next element. */
- prev = next;
- next = XCONS (next)->cdr;
- }
- if (XTYPE (next) == Lisp_Cons)
- last_boundary = prev;
+ save_prev = Qnil;
while (XTYPE (next) == Lisp_Cons)
{
@@ -198,19 +162,18 @@ truncate_undo_list (list, minsize, maxsize)
{
if (size_so_far > maxsize)
break;
- last_boundary = prev;
+ save_prev = prev;
if (size_so_far > minsize)
break;
}
/* Add in the space occupied by this element and its chain link. */
- size_so_far += sizeof (struct Lisp_Cons);
+ size_so_far += 8;
if (XTYPE (elt) == Lisp_Cons)
{
- size_so_far += sizeof (struct Lisp_Cons);
+ size_so_far += 8;
if (XTYPE (XCONS (elt)->car) == Lisp_String)
- size_so_far += (sizeof (struct Lisp_String) - 1
- + XSTRING (XCONS (elt)->car)->size);
+ size_so_far += 6 + XSTRING (XCONS (elt)->car)->size;
}
/* Advance to next element. */
@@ -223,9 +186,9 @@ truncate_undo_list (list, minsize, maxsize)
return list;
/* Truncate at the boundary where we decided to truncate. */
- if (!NULL (last_boundary))
+ if (!NULL (save_prev))
{
- XCONS (last_boundary)->cdr = Qnil;
+ XCONS (save_prev)->cdr = Qnil;
return list;
}
else
@@ -304,7 +267,9 @@ Return what remains of the list.")
if (pos < BEGV || pos > ZV)
error ("Changes to be undone are outside visible portion of buffer");
SET_PT (pos);
- Finsert (1, &membuf);
+ /* The idea here is to leave mark after this text,
+ which will be the desirable thing if undoing C-w. */
+ Finsert_before_markers (1, &membuf);
SET_PT (pos);
}
}
diff --git a/src/unexaix.c b/src/unexaix.c
index a1adff12ec9..1add166a74b 100644
--- a/src/unexaix.c
+++ b/src/unexaix.c
@@ -1,285 +1,870 @@
-/*
- This file is not used because it occasionally fails to work. This
- happens because the bss address when Emacs is run is not always the
- same. If it happens to be different from what it was
- when Emacs was dumped, the dumped data won't work.
- No one has been able to prevent the address from varying.
-
- The following comments should be in etc/MACHINES if this dumping
- is ever made to work:
-
- Note that Emacs can store the pure Lisp data in a shared segment on
- this machine, but only if you put this command in one of the boot
- scripts
-
- emacs -batch -q
-
- so that it is run as root when the machine is booted. This command
- creates a read-only shared segment owned by root. Otherwise the
- pure data is not shared. The pure data size is around 100K, which
- may not be enough to matter for most users of this machine.
+/* Modified by Andrew.Vignaux@comp.vuw.ac.nz to get it to work :-) */
+
+/* Copyright (C) 1985, 1986, 1987, 1988 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+In other words, you are welcome to use, share and improve this program.
+You are forbidden to forbid anyone else to use, share and improve
+what you give them. Help stamp out software-hoarding! */
+
+
+/*
+ * unexec.c - Convert a running program into an a.out file.
+ *
+ * Author: Spencer W. Thomas
+ * Computer Science Dept.
+ * University of Utah
+ * Date: Tue Mar 2 1982
+ * Modified heavily since then.
+ *
+ * Synopsis:
+ * unexec (new_name, a_name, data_start, bss_start, entry_address)
+ * char *new_name, *a_name;
+ * unsigned data_start, bss_start, entry_address;
+ *
+ * Takes a snapshot of the program and makes an a.out format file in the
+ * file named by the string argument new_name.
+ * If a_name is non-NULL, the symbol table will be taken from the given file.
+ * On some machines, an existing a_name file is required.
+ *
+ * The boundaries within the a.out file may be adjusted with the data_start
+ * and bss_start arguments. Either or both may be given as 0 for defaults.
+ *
+ * Data_start gives the boundary between the text segment and the data
+ * segment of the program. The text segment can contain shared, read-only
+ * program code and literal data, while the data segment is always unshared
+ * and unprotected. Data_start gives the lowest unprotected address.
+ * The value you specify may be rounded down to a suitable boundary
+ * as required by the machine you are using.
+ *
+ * Specifying zero for data_start means the boundary between text and data
+ * should not be the same as when the program was loaded.
+ * If NO_REMAP is defined, the argument data_start is ignored and the
+ * segment boundaries are never changed.
+ *
+ * Bss_start indicates how much of the data segment is to be saved in the
+ * a.out file and restored when the program is executed. It gives the lowest
+ * unsaved address, and is rounded up to a page boundary. The default when 0
+ * is given assumes that the entire data segment is to be stored, including
+ * the previous data and bss as well as any additional storage allocated with
+ * break (2).
+ *
+ * The new file is set up to start at entry_address.
+ *
+ * If you make improvements I'd like to get them too.
+ * harpo!utah-cs!thomas, thomas@Utah-20
+ *
+ */
+
+/* There are several compilation parameters affecting unexec:
+
+* COFF
+
+Define this if your system uses COFF for executables.
+Otherwise we assume you use Berkeley format.
+
+* NO_REMAP
+
+Define this if you do not want to try to save Emacs's pure data areas
+as part of the text segment.
+
+Saving them as text is good because it allows users to share more.
+
+However, on machines that locate the text area far from the data area,
+the boundary cannot feasibly be moved. Such machines require
+NO_REMAP.
+
+Also, remapping can cause trouble with the built-in startup routine
+/lib/crt0.o, which defines `environ' as an initialized variable.
+Dumping `environ' as pure does not work! So, to use remapping,
+you must write a startup routine for your machine in Emacs's crt0.c.
+If NO_REMAP is defined, Emacs uses the system's crt0.o.
+
+* SECTION_ALIGNMENT
+
+Some machines that use COFF executables require that each section
+start on a certain boundary *in the COFF file*. Such machines should
+define SECTION_ALIGNMENT to a mask of the low-order bits that must be
+zero on such a boundary. This mask is used to control padding between
+segments in the COFF file.
+
+If SECTION_ALIGNMENT is not defined, the segments are written
+consecutively with no attempt at alignment. This is right for
+unmodified system V.
+
+* SEGMENT_MASK
+
+Some machines require that the beginnings and ends of segments
+*in core* be on certain boundaries. For most machines, a page
+boundary is sufficient. That is the default. When a larger
+boundary is needed, define SEGMENT_MASK to a mask of
+the bits that must be zero on such a boundary.
+
+* A_TEXT_OFFSET(HDR)
+
+Some machines count the a.out header as part of the size of the text
+segment (a_text); they may actually load the header into core as the
+first data in the text segment. Some have additional padding between
+the header and the real text of the program that is counted in a_text.
+
+For these machines, define A_TEXT_OFFSET(HDR) to examine the header
+structure HDR and return the number of bytes to add to `a_text'
+before writing it (above and beyond the number of bytes of actual
+program text). HDR's standard fields are already correct, except that
+this adjustment to the `a_text' field has not yet been made;
+thus, the amount of offset can depend on the data in the file.
+
+* A_TEXT_SEEK(HDR)
+
+If defined, this macro specifies the number of bytes to seek into the
+a.out file before starting to write the text segment.a
+
+* EXEC_MAGIC
+
+For machines using COFF, this macro, if defined, is a value stored
+into the magic number field of the output file.
+
+* ADJUST_EXEC_HEADER
+
+This macro can be used to generate statements to adjust or
+initialize nonstandard fields in the file header
+
+* ADDR_CORRECT(ADDR)
+
+Macro to correct an int which is the bit pattern of a pointer to a byte
+into an int which is the number of a byte.
+
+This macro has a default definition which is usually right.
+This default definition is a no-op on most machines (where a
+pointer looks like an int) but not on all machines.
+
*/
-/* Dumping and loading data areas, for Emacs under AIX.
- (It may also work on other kinds of system V.)
- Copyright (C) 1990 Free Software Foundation, Inc.
+#define XCOFF
+#define COFF
+#define NO_REMAP
-This file is part of GNU Emacs.
+#ifndef emacs
+#define PERROR(arg) perror (arg); return -1
+#else
+#include "config.h"
+#define PERROR(file) report_error (file, new)
+#endif
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 1, or (at your option)
-any later version.
+#ifndef CANNOT_DUMP /* all rest of file! */
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+#ifndef CANNOT_UNEXEC /* most of rest of file */
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+#include <a.out.h>
+/* Define getpagesize () if the system does not.
+ Note that this may depend on symbols defined in a.out.h
+ */
+#include "getpagesize.h"
-/* This is based on a public domain program written by IBM. */
+#ifndef makedev /* Try to detect types.h already loaded */
+#include <sys/types.h>
+#endif
+#include <stdio.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+static int make_hdr ();
+static mark_x ();
+static int copy_text_and_data (), copy_sym ();
+
+extern char *start_of_text (); /* Start of text */
+extern char *start_of_data (); /* Start of initialized data */
+
+extern int _data;
+extern int _edata;
+extern int _text;
+extern int _etext;
+extern int _end;
+#ifdef COFF
+#ifndef USG
+#ifndef STRIDE
+#ifndef UMAX
+#ifndef sun386
+/* I have a suspicion that these are turned off on all systems
+ and can be deleted. Try it in version 19. */
+#include <filehdr.h>
+#include <aouthdr.h>
+#include <scnhdr.h>
+#include <syms.h>
+#endif /* not sun386 */
+#endif /* not UMAX */
+#endif /* Not STRIDE */
+#endif /* not USG */
+static long block_copy_start; /* Old executable start point */
+static struct filehdr f_hdr; /* File header */
+static struct aouthdr f_ohdr; /* Optional file header (a.out) */
+long bias; /* Bias to add for growth */
+long lnnoptr; /* Pointer to line-number info within file */
+#define SYMS_START block_copy_start
+
+static long text_scnptr;
+static long data_scnptr;
+#ifdef XCOFF
+static long load_scnptr;
+static long orig_load_scnptr;
+static long orig_data_scnptr;
+#endif
+static long data_st;
+
+#ifndef MAX_SECTIONS
+#define MAX_SECTIONS 10
+#endif
+
+#endif /* COFF */
+
+static int pagemask;
+
+/* Correct an int which is the bit pattern of a pointer to a byte
+ into an int which is the number of a byte.
+ This is a no-op on ordinary machines, but not on all. */
+
+#ifndef ADDR_CORRECT /* Let m-*.h files override this definition */
+#define ADDR_CORRECT(x) ((char *)(x) - (char*)0)
+#endif
+
+#ifdef emacs
+
+static
+report_error (file, fd)
+ char *file;
+ int fd;
+{
+ if (fd)
+ close (fd);
+ error ("Failure operating on %s", file);
+}
+#endif /* emacs */
-/*************** SYSTEM DEFINES *********************************/
+#define ERROR0(msg) report_error_1 (new, msg, 0, 0); return -1
+#define ERROR1(msg,x) report_error_1 (new, msg, x, 0); return -1
+#define ERROR2(msg,x,y) report_error_1 (new, msg, x, y); return -1
-#include "config.h"
-#include "paths.h"
-#include <sys/types.h>
-#include <sys/files.h>
-#include <fcntl.h>
-#include <sys/mode.h>
-#include <sys/ipc.h>
-#include <sys/shm.h>
-#include <malloc.h>
-#include <stdio.h> /* MWW */
-#include "lisp.h"
-
-/*************** LOCAL DEFINES **********************************/
-
-struct data_header /* saved data header */
+static
+report_error_1 (fd, msg, a1, a2)
+ int fd;
+ char *msg;
+ int a1, a2;
{
- char *start; /* dump _data addr */
- char *end; /* dump _end addr */
- char *sbrk1; /* dump original sbrk addr */
- char *sbrk2; /* dump final sbrk addr */
- int puresize; /* size of pure data dumped */
-};
-
-#define EMACSSHMKEY "EMACSSHMKEY"
-#define EMACS_DATA_FILE "EMACS-DATA"
-#define NEW_SHMGET_FLAGS (IPC_CREAT | S_IWUSR | S_IRUSR \
- | S_IWGRP | S_IRGRP | S_IWOTH | S_IROTH)
-#define OLD_SHMAT_FLAGS SHM_RDONLY
-#define OLD_SHMGET_FLAGS (S_IRUSR | S_IRGRP | S_IROTH)
-#define OLD_OPEN_FLAGS O_RDONLY
-#define NEW_OPEN_FLAGS (O_RDWR | O_CREAT | O_TRUNC)
-
-/*************** EXTERNAL / GLOBAL DATA AREA ********************/
-
-extern char _data; /* start of data addr */
-extern char _end; /* end of all data + 1 addr */
-static char *original_sbrk; /* sbrk when dump first run */
-
-void
-map_in_data (use_dumped_data)
- int use_dumped_data;
+ close (fd);
+#ifdef emacs
+ error (msg, a1, a2);
+#else
+ fprintf (stderr, msg, a1, a2);
+ fprintf (stderr, "\n");
+#endif
+}
+
+/* ****************************************************************
+ * unexec
+ *
+ * driving logic.
+ */
+unexec (new_name, a_name, data_start, bss_start, entry_address)
+ char *new_name, *a_name;
+ unsigned data_start, bss_start, entry_address;
{
- int bufsize; /* malloc buffer size */
- struct data_header dh; /* saved data header */
- int fd; /* saved data file descriptor */
- char *finaladdr; /* last addr in bucket */
- char *ipckey = getenv (EMACSSHMKEY); /* env ipc key string */
- int length; /* dumped data lengths */
- char *newaddr; /* new malloc buffer addr */
- int numblks; /* number of remaining mallocs */
- int shmid; /* shared memory id */
- key_t shmkey; /* shared memory key */
- /* Note that using malloc here may not be safe. */
- char name[sizeof (PATH_EXEC) + sizeof (EMACS_DATA_FILE) + 2];
-
- /* Consume remaining malloc space without increasing */
- /* the end of data space */
- original_sbrk = sbrk (0);
- for (bufsize = 16; bufsize < getpagesize (); bufsize *= 2)
+ int new, a_out = -1;
+
+ if (a_name && (a_out = open (a_name, 0)) < 0)
+ {
+ PERROR (a_name);
+ }
+ if ((new = creat (new_name, 0666)) < 0)
{
- while ((newaddr = (char *)malloc (bufsize - 8)) < original_sbrk)
- ;
- for (numblks = (getpagesize () / bufsize) - 1; numblks > 0; numblks--)
- malloc (bufsize - 8);
- finaladdr = sbrk (0);
+ PERROR (new_name);
+ }
+ if (make_hdr (new,a_out,data_start,bss_start,entry_address,a_name,new_name) < 0
+ || copy_text_and_data (new) < 0
+ || copy_sym (new, a_out, a_name, new_name) < 0
+#ifdef COFF
+ || adjust_lnnoptrs (new, a_out, new_name) < 0
+#endif
+#ifdef XCOFF
+ || unrelocate_symbols (new, a_out, a_name, new_name) < 0
+#endif
+ )
+ {
+ close (new);
+ /* unlink (new_name); /* Failed, unlink new a.out */
+ return -1;
}
- original_sbrk = sbrk (0);
- /* If we don't want the dumped data, get an unshared segment. */
- if (!use_dumped_data)
+ close (new);
+ if (a_out >= 0)
+ close (a_out);
+ mark_x (new_name);
+ return 0;
+}
+
+/* ****************************************************************
+ * make_hdr
+ *
+ * Make the header in the new a.out from the header in core.
+ * Modify the text and data sizes.
+ */
+static int
+make_hdr (new, a_out, data_start, bss_start, entry_address, a_name, new_name)
+ int new, a_out;
+ unsigned data_start, bss_start, entry_address;
+ char *a_name;
+ char *new_name;
+{
+ register int scns;
+ unsigned int bss_end;
+
+ struct scnhdr section[MAX_SECTIONS];
+ struct scnhdr * f_thdr; /* Text section header */
+ struct scnhdr * f_dhdr; /* Data section header */
+ struct scnhdr * f_bhdr; /* Bss section header */
+ struct scnhdr * f_lhdr; /* Loader section header */
+ struct scnhdr * f_tchdr; /* Typechk section header */
+ struct scnhdr * f_dbhdr; /* Debug section header */
+ struct scnhdr * f_xhdr; /* Except section header */
+
+ load_scnptr = orig_load_scnptr = lnnoptr = 0;
+ pagemask = getpagesize () - 1;
+
+ /* Adjust text/data boundary. */
+#ifdef NO_REMAP
+ data_start = (long) start_of_data ();
+#endif /* NO_REMAP */
+ data_start = ADDR_CORRECT (data_start);
+
+#ifdef SEGMENT_MASK
+ data_start = data_start & ~SEGMENT_MASK; /* (Down) to segment boundary. */
+#else
+ data_start = data_start & ~pagemask; /* (Down) to page boundary. */
+#endif
+
+
+ bss_end = ADDR_CORRECT (sbrk (0)) + pagemask;
+ bss_end &= ~ pagemask;
+ /* Adjust data/bss boundary. */
+ if (bss_start != 0)
{
- shmid = shmget (IPC_PRIVATE, PURESIZE, NEW_SHMGET_FLAGS);
- if (shmid == -1
- || shmat (shmid, (char *)PURE_SEG_BITS, 0) == -1)
+ bss_start = (ADDR_CORRECT (bss_start) + pagemask);
+ /* (Up) to page bdry. */
+ bss_start &= ~ pagemask;
+ if (bss_start > bss_end)
{
- fprintf (stderr, "emacs: failure obtaining new unshared memory segment.\n");
- exit (1);
+ ERROR1 ("unexec: Specified bss_start (%u) is past end of program",
+ bss_start);
}
- return;
}
+ else
+ bss_start = bss_end;
- /* Compute the file name with the dumped data. */
- strcpy (name, PATH_EXEC);
- strcat (name, "/");
- strcat (name, EMACS_DATA_FILE);
+ if (data_start > bss_start) /* Can't have negative data size. */
+ {
+ ERROR2 ("unexec: data_start (%u) can't be greater than bss_start (%u)",
+ data_start, bss_start);
+ }
- /* Open the file and make sure the addresses have not changed. */
- fd = open (name, OLD_OPEN_FLAGS, 0);
- if (fd < 0)
+#ifdef COFF
+ /* Salvage as much info from the existing file as possible */
+ block_copy_start = 0;
+ f_thdr = NULL; f_dhdr = NULL; f_bhdr = NULL;
+ f_lhdr = NULL; f_tchdr = NULL; f_dbhdr = NULL; f_xhdr = NULL;
+ if (a_out >= 0)
{
- fprintf (stderr, "emacs: failure opening `%s'\n", name);
- exit (1);
+ if (read (a_out, &f_hdr, sizeof (f_hdr)) != sizeof (f_hdr))
+ {
+ PERROR (a_name);
+ }
+ block_copy_start += sizeof (f_hdr);
+ if (f_hdr.f_opthdr > 0)
+ {
+ if (read (a_out, &f_ohdr, sizeof (f_ohdr)) != sizeof (f_ohdr))
+ {
+ PERROR (a_name);
+ }
+ block_copy_start += sizeof (f_ohdr);
+ }
+ if (f_hdr.f_nscns > MAX_SECTIONS)
+ {
+ ERROR0 ("unexec: too many section headers -- increase MAX_SECTIONS");
+ }
+ /* Loop through section headers */
+ for (scns = 0; scns < f_hdr.f_nscns; scns++) {
+ struct scnhdr *s = &section[scns];
+ if (read (a_out, s, sizeof (*s)) != sizeof (*s))
+ {
+ PERROR (a_name);
+ }
+ if (s->s_scnptr > 0L)
+ {
+ if (block_copy_start < s->s_scnptr + s->s_size)
+ block_copy_start = s->s_scnptr + s->s_size;
+ }
+
+#define CHECK_SCNHDR(ptr, name, flags) \
+ if (strcmp(s->s_name, name) == 0) { \
+ if (s->s_flags != flags) { \
+ fprintf(stderr, "unexec: %x flags where %x expected in %s section.\n", \
+ s->s_flags, flags, name); \
+ } \
+ if (ptr) { \
+ fprintf(stderr, "unexec: duplicate section header for section %s.\n", \
+ name); \
+ } \
+ ptr = s; \
+ }
+ CHECK_SCNHDR(f_thdr, _TEXT, STYP_TEXT);
+ CHECK_SCNHDR(f_dhdr, _DATA, STYP_DATA);
+ CHECK_SCNHDR(f_bhdr, _BSS, STYP_BSS);
+ CHECK_SCNHDR(f_lhdr, _LOADER, STYP_LOADER);
+ CHECK_SCNHDR(f_dbhdr, _DEBUG, STYP_DEBUG);
+ CHECK_SCNHDR(f_tchdr, _TYPCHK, STYP_TYPCHK);
+ CHECK_SCNHDR(f_xhdr, _EXCEPT, STYP_EXCEPT);
+ }
+
+ if (f_thdr == 0)
+ {
+ ERROR1 ("unexec: couldn't find \"%s\" section", _TEXT);
+ }
+ if (f_dhdr == 0)
+ {
+ ERROR1 ("unexec: couldn't find \"%s\" section", _DATA);
+ }
+ if (f_bhdr == 0)
+ {
+ ERROR1 ("unexec: couldn't find \"%s\" section", _BSS);
+ }
}
- if (read (fd, (char *)&dh, sizeof (dh)) != sizeof (dh)
- || dh.start != &_data
- || dh.end != &_end
- || dh.sbrk1 != original_sbrk
- || dh.puresize != PURESIZE)
+ else
{
- fprintf (stderr, "emacs: header mismatch in `%s'\n", name);
- exit (1);
+ ERROR0 ("can't build a COFF file from scratch yet");
+ }
+ orig_data_scnptr = f_dhdr->s_scnptr;
+ orig_load_scnptr = f_lhdr ? f_lhdr->s_scnptr : 0;
+
+ /* Now we alter the contents of all the f_*hdr variables
+ to correspond to what we want to dump. */
+ f_hdr.f_flags |= (F_RELFLG | F_EXEC); /* Why? */
+#ifdef EXEC_MAGIC
+ f_ohdr.magic = EXEC_MAGIC;
+#endif
+#ifndef NO_REMAP
+ f_ohdr.tsize = data_start - f_ohdr.text_start;
+ f_ohdr.text_start = (long) start_of_text ();
+#endif
+ f_ohdr.dsize = bss_start - ((unsigned) &_data);
+ f_ohdr.bsize = bss_end - bss_start;
+
+ f_dhdr->s_size = f_ohdr.dsize;
+ f_bhdr->s_size = f_ohdr.bsize;
+ f_bhdr->s_paddr = f_ohdr.dsize;
+ f_bhdr->s_vaddr = f_ohdr.dsize;
+
+ /* fix scnptr's */
+ {
+ long ptr;
+
+ for (scns = 0; scns < f_hdr.f_nscns; scns++) {
+ struct scnhdr *s = &section[scns];
+ if (scns == 0)
+ ptr = s->s_scnptr;
+
+ if (s->s_scnptr != 0)
+ {
+ s->s_scnptr = ptr;
+ }
+
+ if ((s->s_flags & 0xffff) == STYP_PAD)
+ {
+ /*
+ * the text_start should probably be o_algntext but that doesn't
+ * seem to change
+ */
+ if (f_ohdr.text_start != 0) /* && scns != 0 */
+ {
+ s->s_size = 512 - (s->s_scnptr % 512);
+ if (s->s_size == 512)
+ s->s_size = 0;
+ }
+ }
+
+ ptr = ptr + s->s_size;
}
- /* Load in the unshared contents. */
- if (!(length = dh.end - dh.start)
- || read (fd, (char *)&_data, length) != length
- || !(length = dh.sbrk2 - dh.sbrk1)
- || brk (dh.sbrk2) == -1
- || read (fd, dh.sbrk1, length) != length)
+ bias = ptr - block_copy_start;
+ }
+
+ /* fix other pointers */
+ for (scns = 0; scns < f_hdr.f_nscns; scns++) {
+ struct scnhdr *s = &section[scns];
+
+ if (s->s_relptr != 0)
+ {
+ s->s_relptr += bias;
+ }
+ if (s->s_lnnoptr != 0)
+ {
+ if (lnnoptr == 0) lnnoptr = s->s_lnnoptr;
+ s->s_lnnoptr += bias;
+ }
+ }
+
+ if (f_hdr.f_symptr > 0L)
{
- fprintf (stderr, "emacs: failure loading unshared data.\n");
- exit (1);
+ f_hdr.f_symptr += bias;
}
- /* Determine ipc key from environment or default */
- if (ipckey && *ipckey)
- shmkey = atoi (ipckey);
- else
- shmkey = SHMKEY;
+ data_st = data_start;
+ text_scnptr = f_thdr->s_scnptr;
+ data_scnptr = f_dhdr->s_scnptr;
+ load_scnptr = f_lhdr ? f_lhdr->s_scnptr : 0;
+ block_copy_start = orig_load_scnptr;
- /* Attach to "pure data" shared memory segment */
- if ((shmid = shmget (shmkey, 0, 0)) == -1
- || (newaddr = shmat (shmid, (char *)PURE_SEG_BITS, OLD_SHMAT_FLAGS)) == -1)
- {
- /* We were unable to open an existing segment. Make a new one. */
- struct shmid_ds buf;
+#ifdef ADJUST_EXEC_HEADER
+ ADJUST_EXEC_HEADER
+#endif /* ADJUST_EXEC_HEADER */
- /* First get rid of the one we tried to get. */
- shmdt ((char *)PURE_SEG_BITS);
- shmctl (shmid, IPC_RMID, 0);
+ if (write (new, &f_hdr, sizeof (f_hdr)) != sizeof (f_hdr))
+ {
+ PERROR (new_name);
+ }
- /* If we could not write the data file,
- don't make a shared segment that we could write.
- Make an unshared segment instead. */
- if (access (name, W_OK) == 0)
+ if (f_hdr.f_opthdr > 0)
+ {
+ if (write (new, &f_ohdr, sizeof (f_ohdr)) != sizeof (f_ohdr))
{
- shmid = shmget (IPC_PRIVATE, PURESIZE, NEW_SHMGET_FLAGS);
- if (shmid == -1
- || shmat (shmid, (char *)PURE_SEG_BITS, 0) == -1)
- {
- fprintf (stderr, "emacs: failure obtaining new unshared memory segment.\n");
- exit (1);
- }
+ PERROR (new_name);
+ }
+ }
- /* Load the proper data into it. */
- if (read (fd, PURE_SEG_BITS, PURESIZE) != PURESIZE)
- {
- fprintf (stderr, "emacs: failure loading shared memory data.\n");
- shmdt ((char *)PURE_SEG_BITS);
- shmctl (shmid, IPC_RMID, 0);
- exit (1);
- }
+ for (scns = 0; scns < f_hdr.f_nscns; scns++) {
+ struct scnhdr *s = &section[scns];
+ if (write (new, s, sizeof (*s)) != sizeof (*s))
+ {
+ PERROR (new_name);
+ }
+ }
- close (fd);
- return;
- }
+ return (0);
- /* Allocate the new shared segment and arrange to write it. */
- if ((shmid = shmget (shmkey, PURESIZE, NEW_SHMGET_FLAGS)) == -1
- || shmat (shmid, (char *)PURE_SEG_BITS, 0) == -1)
+#endif /* COFF */
+}
+
+/* ****************************************************************
+
+ *
+ * Copy the text and data segments from memory to the new a.out
+ */
+static int
+copy_text_and_data (new)
+ int new;
+{
+ register char *end;
+ register char *ptr;
+
+ lseek (new, (long) text_scnptr, 0);
+ ptr = start_of_text () + text_scnptr;
+ end = ptr + f_ohdr.tsize;
+ write_segment (new, ptr, end);
+
+ lseek (new, (long) data_scnptr, 0);
+ ptr = (char *) &_data;
+ end = ptr + f_ohdr.dsize;
+ write_segment (new, ptr, end);
+
+ return 0;
+}
+
+write_segment (new, ptr, end)
+ int new;
+ register char *ptr, *end;
+{
+ register int i, nwrite, ret;
+ char buf[80];
+ extern int errno;
+ char zeros[128];
+
+ bzero (zeros, sizeof zeros);
+
+ for (i = 0; ptr < end;)
+ {
+ /* distance to next multiple of 128. */
+ nwrite = (((int) ptr + 128) & -128) - (int) ptr;
+ /* But not beyond specified end. */
+ if (nwrite > end - ptr) nwrite = end - ptr;
+ ret = write (new, ptr, nwrite);
+ /* If write gets a page fault, it means we reached
+ a gap between the old text segment and the old data segment.
+ This gap has probably been remapped into part of the text segment.
+ So write zeros for it. */
+ if (ret == -1 && errno == EFAULT)
{
- fprintf (stderr, "emacs: failure obtaining new shared memory segment.\n");
- shmdt ((char *)PURE_SEG_BITS);
- shmctl (shmid, IPC_RMID, 0);
- exit (1);
+ write (new, zeros, nwrite);
}
-
- /* Load the proper data into it. */
- if (read (fd, PURE_SEG_BITS, PURESIZE) != PURESIZE)
+ else if (nwrite != ret)
{
- fprintf (stderr, "emacs: failure loading shared memory data.\n");
- shmdt ((char *)PURE_SEG_BITS);
- shmctl (shmid, IPC_RMID, 0);
- exit (1);
+ sprintf (buf,
+ "unexec write failure: addr 0x%x, fileno %d, size 0x%x, wrote 0x%x, errno %d",
+ ptr, new, nwrite, ret, errno);
+ PERROR (buf);
}
+ i += nwrite;
+ ptr += nwrite;
+ }
+}
+
+/* ****************************************************************
+ * copy_sym
+ *
+ * Copy the relocation information and symbol table from the a.out to the new
+ */
+static int
+copy_sym (new, a_out, a_name, new_name)
+ int new, a_out;
+ char *a_name, *new_name;
+{
+ char page[1024];
+ int n;
+
+ if (a_out < 0)
+ return 0;
- /* Detach from the segment and bring it back readonly. */
- shmdt ((char *)PURE_SEG_BITS);
+ if (SYMS_START == 0L)
+ return 0;
- shmctl (shmid, IPC_STAT, &buf);
- buf.shm_perm.mode = OLD_SHMGET_FLAGS;
- shmctl (shmid, IPC_SET, &buf);
+ if (lnnoptr && lnnoptr < SYMS_START) /* if there is line number info */
+ lseek (a_out, lnnoptr, 0); /* start copying from there */
+ else
+ lseek (a_out, SYMS_START, 0); /* Position a.out to symtab. */
- newaddr = shmat (shmid, (char *)PURE_SEG_BITS, OLD_SHMAT_FLAGS);
- if (newaddr == -1)
+ while ((n = read (a_out, page, sizeof page)) > 0)
+ {
+ if (write (new, page, n) != n)
{
- fprintf (stderr, "emacs: failure reattaching shared memory segment.\n");
- shmctl (shmid, IPC_RMID, 0);
- exit (1);
+ PERROR (new_name);
}
}
+ if (n < 0)
+ {
+ PERROR (a_name);
+ }
+ return 0;
+}
+
+/* ****************************************************************
+ * mark_x
+ *
+ * After succesfully building the new a.out, mark it executable
+ */
+static
+mark_x (name)
+ char *name;
+{
+ struct stat sbuf;
+ int um;
+ int new = 0; /* for PERROR */
- close (fd);
+ um = umask (777);
+ umask (um);
+ if (stat (name, &sbuf) == -1)
+ {
+ PERROR (name);
+ }
+ sbuf.st_mode |= 0111 & ~um;
+ if (chmod (name, sbuf.st_mode) == -1)
+ PERROR (name);
}
+
+/*
+ * If the COFF file contains a symbol table and a line number section,
+ * then any auxiliary entries that have values for x_lnnoptr must
+ * be adjusted by the amount that the line number section has moved
+ * in the file (bias computed in make_hdr). The #@$%&* designers of
+ * the auxiliary entry structures used the absolute file offsets for
+ * the line number entry rather than an offset from the start of the
+ * line number section!
+ *
+ * When I figure out how to scan through the symbol table and pick out
+ * the auxiliary entries that need adjustment, this routine will
+ * be fixed. As it is now, all such entries are wrong and sdb
+ * will complain. Fred Fish, UniSoft Systems Inc.
+ */
+
+#ifdef COFF
+
+/* This function is probably very slow. Instead of reopening the new
+ file for input and output it should copy from the old to the new
+ using the two descriptors already open (WRITEDESC and READDESC).
+ Instead of reading one small structure at a time it should use
+ a reasonable size buffer. But I don't have time to work on such
+ things, so I am installing it as submitted to me. -- RMS. */
+
+adjust_lnnoptrs (writedesc, readdesc, new_name)
+ int writedesc;
+ int readdesc;
+ char *new_name;
+{
+ register int nsyms;
+ register int new;
+#ifdef amdahl_uts
+ SYMENT symentry;
+ AUXENT auxentry;
+#else
+ struct syment symentry;
+ union auxent auxentry;
+#endif
+
+ if (!lnnoptr || !f_hdr.f_symptr)
+ return 0;
+
+ if ((new = open (new_name, 2)) < 0)
+ {
+ PERROR (new_name);
+ return -1;
+ }
-/* Dump the appropriate parts of memory into a file named NEW
- from which the shared segment can be initialized. */
+ lseek (new, f_hdr.f_symptr, 0);
+ for (nsyms = 0; nsyms < f_hdr.f_nsyms; nsyms++)
+ {
+ read (new, &symentry, SYMESZ);
+ if (symentry.n_numaux)
+ {
+ read (new, &auxentry, AUXESZ);
+ nsyms++;
+ if (ISFCN (symentry.n_type)) {
+ auxentry.x_sym.x_fcnary.x_fcn.x_lnnoptr += bias;
+ lseek (new, -AUXESZ, 1);
+ write (new, &auxentry, AUXESZ);
+ }
+ }
+ }
+ close (new);
+}
+
+#endif /* COFF */
+
+#ifdef XCOFF
-void
-map_out_data (new)
- char *new;
+/* It is probably a false economy to optimise this routine (it used to
+ read one LDREL and do do two lseeks per iteration) but the wrath of
+ RMS (see above :-) would be too much to bear */
+
+unrelocate_symbols (new, a_out, a_name, new_name)
+ int new, a_out;
+ char *a_name, *new_name;
{
- struct data_header dh; /* saved data header */
- int fd; /* saved data file descriptor */
- int length; /* dumped data length; */
-
-
- /* Create "saved data" file header */
- dh.start = &_data;
- dh.end = &_end;
- dh.sbrk1 = original_sbrk;
- dh.sbrk2 = sbrk (0);
- dh.puresize = PURESIZE;
-
- /* Create new "saved data" dump file */
- unlink (new);
- fd = open (new, NEW_OPEN_FLAGS, 0666);
- if (fd < 0)
- report_file_error ("Opening dump file", Fcons (build_string (new), Qnil));
-
- /* Write saved header and data */
- length = sizeof (dh);
- if (write (fd, (char *)&dh, length) != length)
- report_file_error ("Writing dump file header",
- Fcons (build_string (new), Qnil));
- length = dh.end - dh.start;
- if (write (fd, dh.start, length) != length)
- report_file_error ("Writing low core in dump file",
- Fcons (build_string (new), Qnil));
- length = dh.sbrk2 - dh.sbrk1;
- if (write (fd, dh.sbrk1, length) != length)
- report_file_error ("Writing heap in dump file",
- Fcons (build_string (new), Qnil));
- length = PURESIZE;
- if (write (fd, PURE_SEG_BITS, length) != length)
- report_file_error ("Writing pure data in dump file",
- Fcons (build_string (new), Qnil));
- close (fd);
+ register int i;
+ register int l;
+ register LDREL *ldrel;
+ LDHDR ldhdr;
+ LDREL ldrel_buf [20];
+ ulong t_start = (ulong) &_text;
+ ulong d_start = (ulong) &_data;
+ int * p;
+ int dirty;
+
+ if (load_scnptr == 0)
+ return 0;
+
+ lseek (a_out, orig_load_scnptr, 0);
+ if (read (a_out, &ldhdr, sizeof (ldhdr)) != sizeof (ldhdr))
+ {
+ PERROR (new_name);
+ }
+
+#define SYMNDX_TEXT 0
+#define SYMNDX_DATA 1
+#define SYMNDX_BSS 2
+ l = 0;
+ for (i = 0; i < ldhdr.l_nreloc; i++, l--, ldrel++)
+ {
+ if (l == 0) {
+ lseek (a_out,
+ orig_load_scnptr + LDHDRSZ + LDSYMSZ*ldhdr.l_nsyms + LDRELSZ*i,
+ 0);
+
+ l = ldhdr.l_nreloc - i;
+ if (l > sizeof (ldrel_buf) / LDRELSZ)
+ l = sizeof (ldrel_buf) / LDRELSZ;
+
+ if (read (a_out, ldrel_buf, l * LDRELSZ) != l * LDRELSZ)
+ {
+ PERROR (a_name);
+ }
+ ldrel = ldrel_buf;
+ }
+ dirty = 0;
+
+ /* this code may not be necessary */
+ /* I originally had == in the "assignment" and it still unrelocated */
+
+ /* move the BSS loader symbols to the DATA segment */
+ if (ldrel->l_rsecnm == f_ohdr.o_snbss)
+ ldrel->l_rsecnm = f_ohdr.o_sndata, dirty++;
+
+ if (ldrel->l_symndx == SYMNDX_BSS)
+ ldrel->l_symndx = SYMNDX_DATA, dirty++;
+
+ if (dirty)
+ {
+ lseek (new,
+ load_scnptr + LDHDRSZ + LDSYMSZ*ldhdr.l_nsyms + LDRELSZ*i,
+ 0);
+
+ if (write (new, ldrel, LDRELSZ) != LDRELSZ)
+ {
+ PERROR (new_name);
+ }
+ }
+
+ if (ldrel->l_rsecnm == f_ohdr.o_sndata)
+ {
+ int orig_int;
+
+ lseek (a_out, orig_data_scnptr + ldrel->l_vaddr, 0);
+
+ if (read (a_out, (void *) &orig_int, sizeof (orig_int)) != sizeof (orig_int))
+ {
+ PERROR (a_name);
+ }
+
+ switch (ldrel->l_symndx) {
+ case SYMNDX_TEXT:
+ p = (int *) (d_start + ldrel->l_vaddr);
+ orig_int = * p - (t_start - f_ohdr.text_start);
+ break;
+
+ case SYMNDX_DATA:
+ case SYMNDX_BSS:
+ p = (int *) (d_start + ldrel->l_vaddr);
+ orig_int = * p - (d_start - f_ohdr.data_start);
+ break;
+ }
+
+ lseek (new, data_scnptr + ldrel->l_vaddr, 0);
+ if (write (new, (void *) &orig_int, sizeof (orig_int)) != sizeof (orig_int))
+ {
+ PERROR (new_name);
+ }
+ }
+ }
}
+#endif /* XCOFF */
+
+#endif /* not CANNOT_UNEXEC */
+
+#endif /* not CANNOT_DUMP */
diff --git a/src/unexconvex.c b/src/unexconvex.c
new file mode 100644
index 00000000000..0d9f22e720f
--- /dev/null
+++ b/src/unexconvex.c
@@ -0,0 +1,603 @@
+/* Modified version of unexec for convex machines.
+ Copyright (C) 1985, 1986, 1988 Free Software Foundation, Inc.
+
+ Note that the GNU project considers support for the peculiarities
+ of the Convex operating system a peripheral activity which should
+ not be allowed to divert effort from development of the GNU system.
+ Changes in this code will be installed when Convex system
+ maintainers send them in, but aside from that we don't plan to
+ think about it, or about whether other Emacs maintenance might
+ break it.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+In other words, you are welcome to use, share and improve this program.
+You are forbidden to forbid anyone else to use, share and improve
+what you give them. Help stamp out software-hoarding! */
+
+
+/* modifyed for C-1 arch by jthomp@convex 871103 */
+/* Corrected to support convex SOFF object file formats and thread specific
+ * regions. streepy@convex 890302
+*/
+
+/*
+ * unexec.c - Convert a running program into an a.out file.
+ *
+ * Author: Spencer W. Thomas
+ * Computer Science Dept.
+ * University of Utah
+ * Date: Tue Mar 2 1982
+ * Modified heavily since then.
+ *
+ * Synopsis:
+ * unexec (new_name, a_name, data_start, bss_start, entry_address)
+ * char *new_name, *a_name;
+ * unsigned data_start, bss_start, entry_address;
+ *
+ * Takes a snapshot of the program and makes an a.out format file in the
+ * file named by the string argument new_name.
+ * If a_name is non-NULL, the symbol table will be taken from the given file.
+ * On some machines, an existing a_name file is required.
+ *
+ * The boundaries within the a.out file may be adjusted with the data_start
+ * and bss_start arguments. Either or both may be given as 0 for defaults.
+ *
+ * Data_start gives the boundary between the text segment and the data
+ * segment of the program. The text segment can contain shared, read-only
+ * program code and literal data, while the data segment is always unshared
+ * and unprotected. Data_start gives the lowest unprotected address.
+ * The value you specify may be rounded down to a suitable boundary
+ * as required by the machine you are using.
+ *
+ * Specifying zero for data_start means the boundary between text and data
+ * should not be the same as when the program was loaded.
+ * If NO_REMAP is defined, the argument data_start is ignored and the
+ * segment boundaries are never changed.
+ *
+ * Bss_start indicates how much of the data segment is to be saved in the
+ * a.out file and restored when the program is executed. It gives the lowest
+ * unsaved address, and is rounded up to a page boundary. The default when 0
+ * is given assumes that the entire data segment is to be stored, including
+ * the previous data and bss as well as any additional storage allocated with
+ * break (2).
+ *
+ * The new file is set up to start at entry_address.
+ *
+ * If you make improvements I'd like to get them too.
+ * harpo!utah-cs!thomas, thomas@Utah-20
+ *
+ */
+
+/* There are several compilation parameters affecting unexec:
+
+* COFF
+
+Define this if your system uses COFF for executables.
+Otherwise we assume you use Berkeley format.
+
+* NO_REMAP
+
+Define this if you do not want to try to save Emacs's pure data areas
+as part of the text segment.
+
+Saving them as text is good because it allows users to share more.
+
+However, on machines that locate the text area far from the data area,
+the boundary cannot feasibly be moved. Such machines require
+NO_REMAP.
+
+Also, remapping can cause trouble with the built-in startup routine
+/lib/crt0.o, which defines `environ' as an initialized variable.
+Dumping `environ' as pure does not work! So, to use remapping,
+you must write a startup routine for your machine in Emacs's crt0.c.
+If NO_REMAP is defined, Emacs uses the system's crt0.o.
+
+* SECTION_ALIGNMENT
+
+Some machines that use COFF executables require that each section
+start on a certain boundary *in the COFF file*. Such machines should
+define SECTION_ALIGNMENT to a mask of the low-order bits that must be
+zero on such a boundary. This mask is used to control padding between
+segments in the COFF file.
+
+If SECTION_ALIGNMENT is not defined, the segments are written
+consecutively with no attempt at alignment. This is right for
+unmodified system V.
+
+* SEGMENT_MASK
+
+Some machines require that the beginnings and ends of segments
+*in core* be on certain boundaries. For most machines, a page
+boundary is sufficient. That is the default. When a larger
+boundary is needed, define SEGMENT_MASK to a mask of
+the bits that must be zero on such a boundary.
+
+* A_TEXT_OFFSET(HDR)
+
+Some machines count the a.out header as part of the size of the text
+segment (a_text); they may actually load the header into core as the
+first data in the text segment. Some have additional padding between
+the header and the real text of the program that is counted in a_text.
+
+For these machines, define A_TEXT_OFFSET(HDR) to examine the header
+structure HDR and return the number of bytes to add to `a_text'
+before writing it (above and beyond the number of bytes of actual
+program text). HDR's standard fields are already correct, except that
+this adjustment to the `a_text' field has not yet been made;
+thus, the amount of offset can depend on the data in the file.
+
+* A_TEXT_SEEK(HDR)
+
+If defined, this macro specifies the number of bytes to seek into the
+a.out file before starting to write the text segment.a
+
+* EXEC_MAGIC
+
+For machines using COFF, this macro, if defined, is a value stored
+into the magic number field of the output file.
+
+* ADJUST_EXEC_HEADER
+
+This macro can be used to generate statements to adjust or
+initialize nonstandard fields in the file header
+
+* ADDR_CORRECT(ADDR)
+
+Macro to correct an int which is the bit pattern of a pointer to a byte
+into an int which is the number of a byte.
+
+This macro has a default definition which is usually right.
+This default definition is a no-op on most machines (where a
+pointer looks like an int) but not on all machines.
+
+*/
+
+#include "config.h"
+#define PERROR(file) report_error (file, new)
+
+#include <a.out.h>
+/* Define getpagesize () if the system does not.
+ Note that this may depend on symbols defined in a.out.h
+ */
+#include "getpagesize.h"
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+extern char *start_of_text (); /* Start of text */
+extern char *start_of_data (); /* Start of initialized data */
+
+#include <machine/filehdr.h>
+#include <machine/opthdr.h>
+#include <machine/scnhdr.h>
+#include <machine/pte.h>
+
+static long block_copy_start; /* Old executable start point */
+static struct filehdr f_hdr; /* File header */
+static struct opthdr f_ohdr; /* Optional file header (a.out) */
+long bias; /* Bias to add for growth */
+#define SYMS_START block_copy_start
+
+static long text_scnptr;
+static long data_scnptr;
+
+static int pagemask;
+static int pagesz;
+
+static
+report_error (file, fd)
+ char *file;
+ int fd;
+{
+ if (fd)
+ close (fd);
+ error ("Failure operating on %s", file);
+}
+
+#define ERROR0(msg) report_error_1 (new, msg, 0, 0); return -1
+#define ERROR1(msg,x) report_error_1 (new, msg, x, 0); return -1
+#define ERROR2(msg,x,y) report_error_1 (new, msg, x, y); return -1
+
+static
+report_error_1 (fd, msg, a1, a2)
+int fd;
+char *msg;
+int a1, a2;
+{
+ close (fd);
+ error (msg, a1, a2);
+}
+
+/* ****************************************************************
+ * unexec
+ *
+ * driving logic.
+ */
+unexec (new_name, a_name, data_start, bss_start, entry_address)
+char *new_name, *a_name;
+unsigned data_start, bss_start, entry_address;
+{
+ int new, a_out = -1;
+
+ if (a_name && (a_out = open (a_name, 0)) < 0) {
+ PERROR (a_name);
+ }
+ if ((new = creat (new_name, 0666)) < 0) {
+ PERROR (new_name);
+ }
+
+ if (make_hdr (new, a_out, data_start, bss_start, entry_address, a_name, new_name) < 0
+ || copy_text_and_data (new) < 0
+ || copy_sym (new, a_out, a_name, new_name) < 0 ) {
+ close (new);
+ return -1;
+ }
+
+ close (new);
+ if (a_out >= 0)
+ close (a_out);
+ mark_x (new_name);
+ return 0;
+}
+
+/* ****************************************************************
+ * make_hdr
+ *
+ * Make the header in the new a.out from the header in core.
+ * Modify the text and data sizes.
+ */
+
+ struct scnhdr *stbl; /* Table of all scnhdr's */
+ struct scnhdr *f_thdr; /* Text section header */
+ struct scnhdr *f_dhdr; /* Data section header */
+ struct scnhdr *f_tdhdr; /* Thread Data section header */
+ struct scnhdr *f_bhdr; /* Bss section header */
+ struct scnhdr *f_tbhdr; /* Thread Bss section header */
+
+static int
+make_hdr (new, a_out, data_start, bss_start, entry_address, a_name, new_name)
+ int new, a_out;
+ unsigned data_start, bss_start, entry_address;
+ char *a_name;
+ char *new_name;
+{
+ register int scns;
+ unsigned int bss_end;
+ unsigned int eo_data; /* End of initialized data in new exec file */
+ int scntype; /* Section type */
+ int i; /* Var for sorting by vaddr */
+ struct scnhdr scntemp; /* For swapping entries in sort */
+ extern char *start_of_data();
+
+ pagemask = (pagesz = getpagesize()) - 1;
+
+ /* Adjust text/data boundary. */
+ if (!data_start)
+ data_start = (unsigned) start_of_data ();
+
+ data_start = data_start & ~pagemask; /* (Down) to page boundary. */
+
+ bss_end = (sbrk(0) + pagemask) & ~pagemask;
+
+ /* Adjust data/bss boundary. */
+ if (bss_start != 0) {
+ bss_start = (bss_start + pagemask) & ~pagemask;/* (Up) to page bdry. */
+ if (bss_start > bss_end) {
+ ERROR1 ("unexec: Specified bss_start (%x) is past end of program",
+ bss_start);
+ }
+ } else
+ bss_start = bss_end;
+
+ if (data_start > bss_start) { /* Can't have negative data size. */
+ ERROR2 ("unexec: data_start (%x) can't be greater than bss_start (%x)",
+ data_start, bss_start);
+ }
+
+ /* Salvage as much info from the existing file as possible */
+ if (a_out < 0) {
+ ERROR0 ("can't build a COFF file from scratch yet");
+ /*NOTREACHED*/
+ }
+
+ if (read (a_out, &f_hdr, sizeof (f_hdr)) != sizeof (f_hdr)) {
+ PERROR (a_name);
+ }
+ block_copy_start += sizeof (f_hdr);
+ if (f_hdr.h_opthdr > 0) {
+ if (read (a_out, &f_ohdr, sizeof (f_ohdr)) != sizeof (f_ohdr)) {
+ PERROR (a_name);
+ }
+ block_copy_start += sizeof (f_ohdr);
+ }
+
+ /* Allocate room for scn headers */
+ stbl = (struct scnhdr *)malloc( sizeof(struct scnhdr) * f_hdr.h_nscns );
+ if( stbl == NULL ) {
+ ERROR0( "unexec: malloc of stbl failed" );
+ }
+
+ f_tdhdr = f_tbhdr = NULL;
+
+ /* Loop through section headers, copying them in */
+ for (scns = 0; scns < f_hdr.h_nscns; scns++) {
+
+ if( read( a_out, &stbl[scns], sizeof(*stbl)) != sizeof(*stbl)) {
+ PERROR (a_name);
+ }
+
+ scntype = stbl[scns].s_flags & S_TYPMASK; /* What type of section */
+
+ if( stbl[scns].s_scnptr > 0L) {
+ if( block_copy_start < stbl[scns].s_scnptr + stbl[scns].s_size )
+ block_copy_start = stbl[scns].s_scnptr + stbl[scns].s_size;
+ }
+
+ if( scntype == S_TEXT) {
+ f_thdr = &stbl[scns];
+ } else if( scntype == S_DATA) {
+ f_dhdr = &stbl[scns];
+#ifdef S_TDATA
+ } else if( scntype == S_TDATA ) {
+ f_tdhdr = &stbl[scns];
+ } else if( scntype == S_TBSS ) {
+ f_tbhdr = &stbl[scns];
+#endif /* S_TDATA (thread stuff) */
+
+ } else if( scntype == S_BSS) {
+ f_bhdr = &stbl[scns];
+ }
+
+ }
+
+ /* We will now convert TEXT and DATA into TEXT, BSS into DATA, and leave
+ * all thread stuff alone.
+ */
+
+ /* Now we alter the contents of all the f_*hdr variables
+ to correspond to what we want to dump. */
+
+ f_thdr->s_vaddr = (long) start_of_text ();
+ f_thdr->s_size = data_start - f_thdr->s_vaddr;
+ f_thdr->s_scnptr = pagesz;
+ f_thdr->s_relptr = 0;
+ f_thdr->s_nrel = 0;
+
+ eo_data = f_thdr->s_scnptr + f_thdr->s_size;
+
+ if( f_tdhdr ) { /* Process thread data */
+
+ f_tdhdr->s_vaddr = data_start;
+ f_tdhdr->s_size += f_dhdr->s_size - (data_start - f_dhdr->s_vaddr);
+ f_tdhdr->s_scnptr = eo_data;
+ f_tdhdr->s_relptr = 0;
+ f_tdhdr->s_nrel = 0;
+
+ eo_data += f_tdhdr->s_size;
+
+ /* And now for DATA */
+
+ f_dhdr->s_vaddr = f_bhdr->s_vaddr; /* Take BSS start address */
+ f_dhdr->s_size = bss_end - f_bhdr->s_vaddr;
+ f_dhdr->s_scnptr = eo_data;
+ f_dhdr->s_relptr = 0;
+ f_dhdr->s_nrel = 0;
+
+ eo_data += f_dhdr->s_size;
+
+ } else {
+
+ f_dhdr->s_vaddr = data_start;
+ f_dhdr->s_size = bss_start - data_start;
+ f_dhdr->s_scnptr = eo_data;
+ f_dhdr->s_relptr = 0;
+ f_dhdr->s_nrel = 0;
+
+ eo_data += f_dhdr->s_size;
+
+ }
+
+ f_bhdr->s_vaddr = bss_start;
+ f_bhdr->s_size = bss_end - bss_start + pagesz /* fudge */;
+ f_bhdr->s_scnptr = 0;
+ f_bhdr->s_relptr = 0;
+ f_bhdr->s_nrel = 0;
+
+ text_scnptr = f_thdr->s_scnptr;
+ data_scnptr = f_dhdr->s_scnptr;
+ bias = eo_data - block_copy_start;
+
+ if (f_ohdr.o_symptr > 0L) {
+ f_ohdr.o_symptr += bias;
+ }
+
+ if (f_hdr.h_strptr > 0) {
+ f_hdr.h_strptr += bias;
+ }
+
+ if (write (new, &f_hdr, sizeof (f_hdr)) != sizeof (f_hdr)) {
+ PERROR (new_name);
+ }
+
+ if (write (new, &f_ohdr, sizeof (f_ohdr)) != sizeof (f_ohdr)) {
+ PERROR (new_name);
+ }
+
+ for( scns = 0; scns < f_hdr.h_nscns; scns++ ) {
+
+ /* This is a cheesey little loop to write out the section headers
+ * in order of increasing virtual address. Dull but effective.
+ */
+
+ for( i = scns+1; i < f_hdr.h_nscns; i++ ) {
+ if( stbl[i].s_vaddr < stbl[scns].s_vaddr ) { /* Swap */
+ scntemp = stbl[i];
+ stbl[i] = stbl[scns];
+ stbl[scns] = scntemp;
+ }
+ }
+
+ }
+
+ for( scns = 0; scns < f_hdr.h_nscns; scns++ ) {
+
+ if( write( new, &stbl[scns], sizeof(*stbl)) != sizeof(*stbl)) {
+ PERROR (new_name);
+ }
+
+ }
+
+ return (0);
+
+}
+
+/* ****************************************************************
+ * copy_text_and_data
+ *
+ * Copy the text and data segments from memory to the new a.out
+ */
+static int
+copy_text_and_data (new)
+int new;
+{
+ register int scns;
+
+ for( scns = 0; scns < f_hdr.h_nscns; scns++ )
+ write_segment( new, &stbl[scns] );
+
+ return 0;
+}
+
+write_segment( new, sptr )
+int new;
+struct scnhdr *sptr;
+{
+ register char *ptr, *end;
+ register int nwrite, ret;
+ char buf[80];
+ extern int errno;
+ char zeros[128];
+
+ if( sptr->s_scnptr == 0 )
+ return; /* Nothing to do */
+
+ if( lseek( new, (long) sptr->s_scnptr, 0 ) == -1 )
+ PERROR( "unexecing" );
+
+ bzero (zeros, sizeof zeros);
+
+ ptr = (char *) sptr->s_vaddr;
+ end = ptr + sptr->s_size;
+
+ while( ptr < end ) {
+
+ /* distance to next multiple of 128. */
+ nwrite = (((int) ptr + 128) & -128) - (int) ptr;
+ /* But not beyond specified end. */
+ if (nwrite > end - ptr) nwrite = end - ptr;
+ ret = write (new, ptr, nwrite);
+ /* If write gets a page fault, it means we reached
+ a gap between the old text segment and the old data segment.
+ This gap has probably been remapped into part of the text segment.
+ So write zeros for it. */
+ if (ret == -1 && errno == EFAULT)
+ write (new, zeros, nwrite);
+ else if (nwrite != ret) {
+ sprintf (buf,
+ "unexec write failure: addr 0x%x, fileno %d, size 0x%x, wrote 0x%x, errno %d",
+ ptr, new, nwrite, ret, errno);
+ PERROR (buf);
+ }
+ ptr += nwrite;
+ }
+}
+
+/* ****************************************************************
+ * copy_sym
+ *
+ * Copy the relocation information and symbol table from the a.out to the new
+ */
+static int
+copy_sym (new, a_out, a_name, new_name)
+ int new, a_out;
+ char *a_name, *new_name;
+{
+ char page[1024];
+ int n;
+
+ if (a_out < 0)
+ return 0;
+
+ if (SYMS_START == 0L)
+ return 0;
+
+ lseek (a_out, SYMS_START, 0); /* Position a.out to symtab. */
+ lseek( new, (long)f_ohdr.o_symptr, 0 );
+
+ while ((n = read (a_out, page, sizeof page)) > 0) {
+ if (write (new, page, n) != n) {
+ PERROR (new_name);
+ }
+ }
+ if (n < 0) {
+ PERROR (a_name);
+ }
+ return 0;
+}
+
+/* ****************************************************************
+ * mark_x
+ *
+ * After succesfully building the new a.out, mark it executable
+ */
+static
+mark_x (name)
+char *name;
+{
+ struct stat sbuf;
+ int um;
+ int new = 0; /* for PERROR */
+
+ um = umask (777);
+ umask (um);
+ if (stat (name, &sbuf) == -1) {
+ PERROR (name);
+ }
+ sbuf.st_mode |= 0111 & ~um;
+ if (chmod (name, sbuf.st_mode) == -1)
+ PERROR (name);
+}
+
+/* Find the first pty letter. This is usually 'p', as in ptyp0, but
+ is sometimes configured down to 'm', 'n', or 'o' for some reason. */
+
+first_pty_letter ()
+{
+ struct stat buf;
+ char pty_name[16];
+ char c;
+
+ for (c = 'o'; c >= 'a'; c--)
+ {
+ sprintf (pty_name, "/dev/pty%c0", c);
+ if (stat (pty_name, &buf) < 0)
+ return c + 1;
+ }
+ return 'a';
+}
+
diff --git a/src/unexec.c b/src/unexec.c
index ccd67451203..eeae9c6a229 100644
--- a/src/unexec.c
+++ b/src/unexec.c
@@ -1,20 +1,22 @@
/* Copyright (C) 1985, 1986, 1987, 1988 Free Software Foundation, Inc.
-This file is part of GNU Emacs.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 1, or (at your option)
-any later version.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+In other words, you are welcome to use, share and improve this program.
+You are forbidden to forbid anyone else to use, share and improve
+what you give them. Help stamp out software-hoarding! */
/*
@@ -156,7 +158,6 @@ pointer looks like an int) but not on all machines.
#ifndef emacs
#define PERROR(arg) perror (arg); return -1
#else
-#define IN_UNEXEC
#include "config.h"
#define PERROR(file) report_error (file, new)
#endif
@@ -181,7 +182,24 @@ pointer looks like an int) but not on all machines.
extern char *start_of_text (); /* Start of text */
extern char *start_of_data (); /* Start of initialized data */
+static int make_hdr (), copy_text_and_data (), copy_sym ();
+static int mark_x ();
+
#ifdef COFF
+#ifndef USG
+#ifndef STRIDE
+#ifndef UMAX
+#ifndef sun386
+/* I have a suspicion that these are turned off on all systems
+ and can be deleted. Try it in version 19. */
+#include <filehdr.h>
+#include <aouthdr.h>
+#include <scnhdr.h>
+#include <syms.h>
+#endif /* not sun386 */
+#endif /* not UMAX */
+#endif /* Not STRIDE */
+#endif /* not USG */
static long block_copy_start; /* Old executable start point */
static struct filehdr f_hdr; /* File header */
static struct aouthdr f_ohdr; /* Optional file header (a.out) */
@@ -194,8 +212,6 @@ static long data_scnptr;
#else /* not COFF */
-extern char *sbrk ();
-
#define SYMS_START ((long) N_SYMOFF (ohdr))
/* Some machines override the structure name for an a.out header. */
@@ -218,7 +234,9 @@ static EXEC_HDR_TYPE hdr, ohdr;
#else /* not HPUX */
-#if defined (USG) && !defined (IBMAIX) && !defined (IRIS)
+extern char *sbrk ();
+
+#if defined (USG) && !defined (IBMRTAIX) && !defined (IRIS)
static struct bhdr hdr, ohdr;
#define a_magic fmagic
#define a_text tsize
@@ -232,10 +250,10 @@ static struct bhdr hdr, ohdr;
(((x).fmagic)!=OMAGIC && ((x).fmagic)!=NMAGIC &&\
((x).fmagic)!=FMAGIC && ((x).fmagic)!=IMAGIC)
#define NEWMAGIC FMAGIC
-#else /* IRIS or IBMAIX or not USG */
+#else /* IRIS or IBMRTAIX or not USG */
static EXEC_HDR_TYPE hdr, ohdr;
#define NEWMAGIC ZMAGIC
-#endif /* IRIS or IBMAIX not USG */
+#endif /* IRIS or IBMRTAIX not USG */
#endif /* not HPUX */
static int unexec_text_start;
@@ -262,7 +280,7 @@ report_error (file, fd)
{
if (fd)
close (fd);
- error ("Failure operating on %s\n", file);
+ error ("Failure operating on %s", file);
}
#endif /* emacs */
@@ -285,11 +303,6 @@ report_error_1 (fd, msg, a1, a2)
#endif
}
-static int make_hdr ();
-static int copy_text_and_data ();
-static int copy_sym ();
-static void mark_x ();
-
/* ****************************************************************
* unexec
*
@@ -314,10 +327,8 @@ unexec (new_name, a_name, data_start, bss_start, entry_address)
|| copy_text_and_data (new, a_out) < 0
|| copy_sym (new, a_out, a_name, new_name) < 0
#ifdef COFF
-#ifndef COFF_BSD_SYMBOLS
|| adjust_lnnoptrs (new, a_out, new_name) < 0
#endif
-#endif
)
{
close (new);
@@ -328,8 +339,7 @@ unexec (new_name, a_name, data_start, bss_start, entry_address)
close (new);
if (a_out >= 0)
close (a_out);
- mark_x (new_name);
- return 0;
+ return mark_x (new_name);
}
/* ****************************************************************
@@ -475,17 +485,9 @@ make_hdr (new, a_out, data_start, bss_start, entry_address, a_name, new_name)
#endif /* NO_REMAP */
f_ohdr.dsize = bss_start - f_ohdr.data_start;
f_ohdr.bsize = bss_end - bss_start;
-#ifndef KEEP_OLD_TEXT_SCNPTR
- /* On some machines, the old values are right.
- ??? Maybe on all machines with NO_REMAP. */
f_thdr.s_size = f_ohdr.tsize;
f_thdr.s_scnptr = sizeof (f_hdr) + sizeof (f_ohdr);
f_thdr.s_scnptr += (f_hdr.f_nscns) * (sizeof (f_thdr));
-#endif /* KEEP_OLD_TEXT_SCNPTR */
-#ifdef ADJUST_TEXT_SCNHDR_SIZE
- /* On some machines, `text size' includes all headers. */
- f_thdr.s_size -= f_thdr.s_scnptr;
-#endif /* ADJUST_TEST_SCNHDR_SIZE */
lnnoptr = f_thdr.s_lnnoptr;
#ifdef SECTION_ALIGNMENT
/* Some systems require special alignment
@@ -497,12 +499,7 @@ make_hdr (new, a_out, data_start, bss_start, entry_address, a_name, new_name)
f_thdr.s_scnptr = 0xd0;
#endif
text_scnptr = f_thdr.s_scnptr;
-#ifdef ADJUST_TEXTBASE
- text_scnptr = sizeof (f_hdr) + sizeof (f_ohdr) + (f_hdr.f_nscns) * (sizeof (f_thdr));
-#endif
-#ifndef KEEP_OLD_PADDR
f_dhdr.s_paddr = f_ohdr.data_start;
-#endif /* KEEP_OLD_PADDR */
f_dhdr.s_vaddr = f_ohdr.data_start;
f_dhdr.s_size = f_ohdr.dsize;
f_dhdr.s_scnptr = f_thdr.s_scnptr + f_thdr.s_size;
@@ -519,9 +516,7 @@ make_hdr (new, a_out, data_start, bss_start, entry_address, a_name, new_name)
= (f_dhdr.s_scnptr + DATA_SECTION_ALIGNMENT) & ~DATA_SECTION_ALIGNMENT;
#endif /* DATA_SECTION_ALIGNMENT */
data_scnptr = f_dhdr.s_scnptr;
-#ifndef KEEP_OLD_PADDR
f_bhdr.s_paddr = f_ohdr.data_start + f_ohdr.dsize;
-#endif /* KEEP_OLD_PADDR */
f_bhdr.s_vaddr = f_ohdr.data_start + f_ohdr.dsize;
f_bhdr.s_size = f_ohdr.bsize;
f_bhdr.s_scnptr = 0L;
@@ -540,7 +535,7 @@ make_hdr (new, a_out, data_start, bss_start, entry_address, a_name, new_name)
}
#ifdef ADJUST_EXEC_HEADER
- ADJUST_EXEC_HEADER;
+ ADJUST_EXEC_HEADER
#endif /* ADJUST_EXEC_HEADER */
if (write (new, &f_hdr, sizeof (f_hdr)) != sizeof (f_hdr))
@@ -753,10 +748,6 @@ copy_text_and_data (new, a_out)
lseek (new, (long) text_scnptr, 0);
ptr = (char *) f_ohdr.text_start;
-#ifdef HEADER_INCL_IN_TEXT
- /* For Gould UTX/32, text starts after headers */
- ptr = (char *) (ptr + text_scnptr);
-#endif /* HEADER_INCL_IN_TEXT */
end = ptr + f_ohdr.tsize;
write_segment (new, ptr, end);
@@ -780,7 +771,15 @@ copy_text_and_data (new, a_out)
#ifdef A_TEXT_SEEK
lseek (new, (long) A_TEXT_SEEK (hdr), 0);
#else
+#ifdef A_TEXT_OFFSET
+ /* Note that on the Sequent machine A_TEXT_OFFSET != sizeof (hdr)
+ and sizeof (hdr) is the correct amount to add here. */
+ /* In version 19, eliminate this case and use A_TEXT_SEEK whenever
+ N_TXTOFF is not right. */
+ lseek (new, (long) N_TXTOFF (hdr) + sizeof (hdr), 0);
+#else
lseek (new, (long) N_TXTOFF (hdr), 0);
+#endif /* no A_TEXT_OFFSET */
#endif /* no A_TEXT_SEEK */
ptr = (char *) unexec_text_start;
@@ -883,7 +882,7 @@ copy_sym (new, a_out, a_name, new_name)
*
* After succesfully building the new a.out, mark it executable
*/
-static void
+static int
mark_x (name)
char *name;
{
@@ -900,11 +899,9 @@ mark_x (name)
sbuf.st_mode |= 0111 & ~um;
if (chmod (name, sbuf.st_mode) == -1)
PERROR (name);
+ return 0;
}
-#ifdef COFF
-#ifndef COFF_BSD_SYMBOLS
-
/*
* If the COFF file contains a symbol table and a line number section,
* then any auxiliary entries that have values for x_lnnoptr must
@@ -920,6 +917,8 @@ mark_x (name)
* will complain. Fred Fish, UniSoft Systems Inc.
*/
+#ifdef COFF
+
/* This function is probably very slow. Instead of reopening the new
file for input and output it should copy from the old to the new
using the two descriptors already open (WRITEDESC and READDESC).
@@ -934,7 +933,7 @@ adjust_lnnoptrs (writedesc, readdesc, new_name)
{
register int nsyms;
register int new;
-#ifdef amdahl_uts
+#if defined (amdahl_uts) || defined (pfa)
SYMENT symentry;
AUXENT auxentry;
#else
@@ -969,8 +968,6 @@ adjust_lnnoptrs (writedesc, readdesc, new_name)
close (new);
}
-#endif /* COFF_BSD_SYMBOLS */
-
#endif /* COFF */
#endif /* not CANNOT_UNEXEC */
diff --git a/src/unexelf.c b/src/unexelf.c
new file mode 100644
index 00000000000..519101a95b9
--- /dev/null
+++ b/src/unexelf.c
@@ -0,0 +1,639 @@
+/* Copyright (C) 1985, 1986, 1987, 1988 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+In other words, you are welcome to use, share and improve this program.
+You are forbidden to forbid anyone else to use, share and improve
+what you give them. Help stamp out software-hoarding! */
+
+
+/*
+ * unexec.c - Convert a running program into an a.out file.
+ *
+ * Author: Spencer W. Thomas
+ * Computer Science Dept.
+ * University of Utah
+ * Date: Tue Mar 2 1982
+ * Modified heavily since then.
+ *
+ * Synopsis:
+ * unexec (new_name, a_name, data_start, bss_start, entry_address)
+ * char *new_name, *a_name;
+ * unsigned data_start, bss_start, entry_address;
+ *
+ * Takes a snapshot of the program and makes an a.out format file in the
+ * file named by the string argument new_name.
+ * If a_name is non-NULL, the symbol table will be taken from the given file.
+ * On some machines, an existing a_name file is required.
+ *
+ * The boundaries within the a.out file may be adjusted with the data_start
+ * and bss_start arguments. Either or both may be given as 0 for defaults.
+ *
+ * Data_start gives the boundary between the text segment and the data
+ * segment of the program. The text segment can contain shared, read-only
+ * program code and literal data, while the data segment is always unshared
+ * and unprotected. Data_start gives the lowest unprotected address.
+ * The value you specify may be rounded down to a suitable boundary
+ * as required by the machine you are using.
+ *
+ * Specifying zero for data_start means the boundary between text and data
+ * should not be the same as when the program was loaded.
+ * If NO_REMAP is defined, the argument data_start is ignored and the
+ * segment boundaries are never changed.
+ *
+ * Bss_start indicates how much of the data segment is to be saved in the
+ * a.out file and restored when the program is executed. It gives the lowest
+ * unsaved address, and is rounded up to a page boundary. The default when 0
+ * is given assumes that the entire data segment is to be stored, including
+ * the previous data and bss as well as any additional storage allocated with
+ * break (2).
+ *
+ * The new file is set up to start at entry_address.
+ *
+ * If you make improvements I'd like to get them too.
+ * harpo!utah-cs!thomas, thomas@Utah-20
+ *
+ */
+
+/* Even more heavily modified by james@bigtex.cactus.org of Dell Computer Co.
+ * ELF support added.
+ *
+ * Basic theory: the data space of the running process needs to be
+ * dumped to the output file. Normally we would just enlarge the size
+ * of .data, scooting everything down. But we can't do that in ELF,
+ * because there is often something between the .data space and the
+ * .bss space.
+ *
+ * In the temacs dump below, notice that the Global Offset Table
+ * (.got) and the Dynamic link data (.dynamic) come between .data1 and
+ * .bss. It does not work to overlap .data with these fields.
+ *
+ * The solution is to create a new .data segment. This segment is
+ * filled with data from the current process. Since the contents of
+ * various sections refer to sections by index, the new .data segment
+ * is made the last in the table to avoid changing any existing index.
+
+ * This is an example of how the section headers are changed. "Addr"
+ * is a process virtual address. "Offset" is a file offset.
+
+raid:/nfs/raid/src/dist-18.56/src> dump -h temacs
+
+temacs:
+
+ **** SECTION HEADER TABLE ****
+[No] Type Flags Addr Offset Size Name
+ Link Info Adralgn Entsize
+
+[1] 1 2 0x80480d4 0xd4 0x13 .interp
+ 0 0 0x1 0
+
+[2] 5 2 0x80480e8 0xe8 0x388 .hash
+ 3 0 0x4 0x4
+
+[3] 11 2 0x8048470 0x470 0x7f0 .dynsym
+ 4 1 0x4 0x10
+
+[4] 3 2 0x8048c60 0xc60 0x3ad .dynstr
+ 0 0 0x1 0
+
+[5] 9 2 0x8049010 0x1010 0x338 .rel.plt
+ 3 7 0x4 0x8
+
+[6] 1 6 0x8049348 0x1348 0x3 .init
+ 0 0 0x4 0
+
+[7] 1 6 0x804934c 0x134c 0x680 .plt
+ 0 0 0x4 0x4
+
+[8] 1 6 0x80499cc 0x19cc 0x3c56f .text
+ 0 0 0x4 0
+
+[9] 1 6 0x8085f3c 0x3df3c 0x3 .fini
+ 0 0 0x4 0
+
+[10] 1 2 0x8085f40 0x3df40 0x69c .rodata
+ 0 0 0x4 0
+
+[11] 1 2 0x80865dc 0x3e5dc 0xd51 .rodata1
+ 0 0 0x4 0
+
+[12] 1 3 0x8088330 0x3f330 0x20afc .data
+ 0 0 0x4 0
+
+[13] 1 3 0x80a8e2c 0x5fe2c 0x89d .data1
+ 0 0 0x4 0
+
+[14] 1 3 0x80a96cc 0x606cc 0x1a8 .got
+ 0 0 0x4 0x4
+
+[15] 6 3 0x80a9874 0x60874 0x80 .dynamic
+ 4 0 0x4 0x8
+
+[16] 8 3 0x80a98f4 0x608f4 0x449c .bss
+ 0 0 0x4 0
+
+[17] 2 0 0 0x608f4 0x9b90 .symtab
+ 18 371 0x4 0x10
+
+[18] 3 0 0 0x6a484 0x8526 .strtab
+ 0 0 0x1 0
+
+[19] 3 0 0 0x729aa 0x93 .shstrtab
+ 0 0 0x1 0
+
+[20] 1 0 0 0x72a3d 0x68b7 .comment
+ 0 0 0x1 0
+
+raid:/nfs/raid/src/dist-18.56/src> dump -h xemacs
+
+xemacs:
+
+ **** SECTION HEADER TABLE ****
+[No] Type Flags Addr Offset Size Name
+ Link Info Adralgn Entsize
+
+[1] 1 2 0x80480d4 0xd4 0x13 .interp
+ 0 0 0x1 0
+
+[2] 5 2 0x80480e8 0xe8 0x388 .hash
+ 3 0 0x4 0x4
+
+[3] 11 2 0x8048470 0x470 0x7f0 .dynsym
+ 4 1 0x4 0x10
+
+[4] 3 2 0x8048c60 0xc60 0x3ad .dynstr
+ 0 0 0x1 0
+
+[5] 9 2 0x8049010 0x1010 0x338 .rel.plt
+ 3 7 0x4 0x8
+
+[6] 1 6 0x8049348 0x1348 0x3 .init
+ 0 0 0x4 0
+
+[7] 1 6 0x804934c 0x134c 0x680 .plt
+ 0 0 0x4 0x4
+
+[8] 1 6 0x80499cc 0x19cc 0x3c56f .text
+ 0 0 0x4 0
+
+[9] 1 6 0x8085f3c 0x3df3c 0x3 .fini
+ 0 0 0x4 0
+
+[10] 1 2 0x8085f40 0x3df40 0x69c .rodata
+ 0 0 0x4 0
+
+[11] 1 2 0x80865dc 0x3e5dc 0xd51 .rodata1
+ 0 0 0x4 0
+
+[12] 1 3 0x8088330 0x3f330 0x20afc .data
+ 0 0 0x4 0
+
+[13] 1 3 0x80a8e2c 0x5fe2c 0x89d .data1
+ 0 0 0x4 0
+
+[14] 1 3 0x80a96cc 0x606cc 0x1a8 .got
+ 0 0 0x4 0x4
+
+[15] 6 3 0x80a9874 0x60874 0x80 .dynamic
+ 4 0 0x4 0x8
+
+[16] 8 3 0x80c6800 0x7d800 0 .bss
+ 0 0 0x4 0
+
+[17] 2 0 0 0x7d800 0x9b90 .symtab
+ 18 371 0x4 0x10
+
+[18] 3 0 0 0x87390 0x8526 .strtab
+ 0 0 0x1 0
+
+[19] 3 0 0 0x8f8b6 0x93 .shstrtab
+ 0 0 0x1 0
+
+[20] 1 0 0 0x8f949 0x68b7 .comment
+ 0 0 0x1 0
+
+[21] 1 3 0x80a98f4 0x608f4 0x1cf0c .data
+ 0 0 0x4 0
+
+ * This is an example of how the file header is changed. "Shoff" is
+ * the section header offset within the file. Since that table is
+ * after the new .data section, it is moved. "Shnum" is the number of
+ * sections, which we increment.
+ *
+ * "Phoff" is the file offset to the program header. "Phentsize" and
+ * "Shentsz" are the program and section header entries sizes respectively.
+ * These can be larger than the apparent struct sizes.
+
+raid:/nfs/raid/src/dist-18.56/src> dump -f temacs
+
+temacs:
+
+ **** ELF HEADER ****
+Class Data Type Machine Version
+Entry Phoff Shoff Flags Ehsize
+Phentsize Phnum Shentsz Shnum Shstrndx
+
+1 1 2 3 1
+0x80499cc 0x34 0x792f4 0 0x34
+0x20 5 0x28 21 19
+
+raid:/nfs/raid/src/dist-18.56/src> dump -f xemacs
+
+xemacs:
+
+ **** ELF HEADER ****
+Class Data Type Machine Version
+Entry Phoff Shoff Flags Ehsize
+Phentsize Phnum Shentsz Shnum Shstrndx
+
+1 1 2 3 1
+0x80499cc 0x34 0x96200 0 0x34
+0x20 5 0x28 22 19
+
+ * These are the program headers. "Offset" is the file offset to the
+ * segment. "Vaddr" is the memory load address. "Filesz" is the
+ * segment size as it appears in the file, and "Memsz" is the size in
+ * memory. Below, the third segment is the code and the fourth is the
+ * data: the difference between Filesz and Memsz is .bss
+
+raid:/nfs/raid/src/dist-18.56/src> dump -o temacs
+
+temacs:
+ ***** PROGRAM EXECUTION HEADER *****
+Type Offset Vaddr Paddr
+Filesz Memsz Flags Align
+
+6 0x34 0x8048034 0
+0xa0 0xa0 5 0
+
+3 0xd4 0 0
+0x13 0 4 0
+
+1 0x34 0x8048034 0
+0x3f2f9 0x3f2f9 5 0x1000
+
+1 0x3f330 0x8088330 0
+0x215c4 0x25a60 7 0x1000
+
+2 0x60874 0x80a9874 0
+0x80 0 7 0
+
+raid:/nfs/raid/src/dist-18.56/src> dump -o xemacs
+
+xemacs:
+ ***** PROGRAM EXECUTION HEADER *****
+Type Offset Vaddr Paddr
+Filesz Memsz Flags Align
+
+6 0x34 0x8048034 0
+0xa0 0xa0 5 0
+
+3 0xd4 0 0
+0x13 0 4 0
+
+1 0x34 0x8048034 0
+0x3f2f9 0x3f2f9 5 0x1000
+
+1 0x3f330 0x8088330 0
+0x3e4d0 0x3e4d0 7 0x1000
+
+2 0x60874 0x80a9874 0
+0x80 0 7 0
+
+
+ */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <memory.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <elf.h>
+#include <sys/mman.h>
+
+#ifndef emacs
+#define fatal(a, b, c) fprintf(stderr, a, b, c), exit(1)
+#else
+extern void fatal(char *, ...);
+#endif
+
+/* Get the address of a particular section or program header entry,
+ * accounting for the size of the entries.
+ */
+
+#define OLD_SECTION_H(n) \
+ (*(Elf32_Shdr *) ((byte *) old_section_h + old_file_h->e_shentsize * (n)))
+#define NEW_SECTION_H(n) \
+ (*(Elf32_Shdr *) ((byte *) new_section_h + new_file_h->e_shentsize * (n)))
+#define OLD_PROGRAM_H(n) \
+ (*(Elf32_Phdr *) ((byte *) old_program_h + old_file_h->e_phentsize * (n)))
+#define NEW_PROGRAM_H(n) \
+ (*(Elf32_Phdr *) ((byte *) new_program_h + new_file_h->e_phentsize * (n)))
+
+typedef unsigned char byte;
+
+/* Round X up to a multiple of Y. */
+
+int
+round_up (x, y)
+ int x, y;
+{
+ int rem = x % y;
+ if (rem == 0)
+ return x;
+ return x - rem + y;
+}
+
+/* ****************************************************************
+ * unexec
+ *
+ * driving logic.
+ *
+ * In ELF, this works by replacing the old .bss section with a new
+ * .data section, and inserting an empty .bss immediately afterwards.
+ *
+ */
+void
+unexec (new_name, old_name, data_start, bss_start, entry_address)
+ char *new_name, *old_name;
+ unsigned data_start, bss_start, entry_address;
+{
+ extern unsigned int bss_end;
+ int new_file, old_file, new_file_size;
+
+ /* Pointers to the base of the image of the two files. */
+ caddr_t old_base, new_base;
+
+ /* Pointers to the file, program and section headers for the old and new
+ * files.
+ */
+ Elf32_Ehdr *old_file_h, *new_file_h;
+ Elf32_Phdr *old_program_h, *new_program_h;
+ Elf32_Shdr *old_section_h, *new_section_h;
+
+ /* Point to the section name table in the old file */
+ char *old_section_names;
+
+ Elf32_Addr old_bss_addr, new_bss_addr;
+ Elf32_Word old_bss_size, new_data2_size;
+ Elf32_Off new_data2_offset;
+ Elf32_Addr new_data2_addr;
+
+ int n, old_bss_index, old_data_index, new_data2_index;
+ struct stat stat_buf;
+
+ /* Open the old file & map it into the address space. */
+
+ old_file = open (old_name, O_RDONLY);
+
+ if (old_file < 0)
+ fatal ("Can't open %s for reading: errno %d\n", old_name, errno);
+
+ if (fstat (old_file, &stat_buf) == -1)
+ fatal ("Can't fstat(%s): errno %d\n", old_name, errno);
+
+ old_base = mmap (0, stat_buf.st_size, PROT_READ, MAP_SHARED, old_file, 0);
+
+ if (old_base == (caddr_t) -1)
+ fatal ("Can't mmap(%s): errno %d\n", old_name, errno);
+
+#ifdef DEBUG
+ fprintf (stderr, "mmap(%s, %x) -> %x\n", old_name, stat_buf.st_size,
+ old_base);
+#endif
+
+ /* Get pointers to headers & section names */
+
+ old_file_h = (Elf32_Ehdr *) old_base;
+ old_program_h = (Elf32_Phdr *) ((byte *) old_base + old_file_h->e_phoff);
+ old_section_h = (Elf32_Shdr *) ((byte *) old_base + old_file_h->e_shoff);
+ old_section_names = (char *) old_base
+ + OLD_SECTION_H(old_file_h->e_shstrndx).sh_offset;
+
+ /* Find the old .bss section. Figure out parameters of the new
+ * data2 and bss sections.
+ */
+
+ for (old_bss_index = 1; old_bss_index < old_file_h->e_shnum; old_bss_index++)
+ {
+#ifdef DEBUG
+ fprintf (stderr, "Looking for .bss - found %s\n",
+ old_section_names + OLD_SECTION_H(old_bss_index).sh_name);
+#endif
+ if (!strcmp (old_section_names + OLD_SECTION_H(old_bss_index).sh_name,
+ ".bss"))
+ break;
+ }
+ if (old_bss_index == old_file_h->e_shnum)
+ fatal ("Can't find .bss in %s.\n", old_name, 0);
+
+ old_bss_addr = OLD_SECTION_H(old_bss_index).sh_addr;
+ old_bss_size = OLD_SECTION_H(old_bss_index).sh_size;
+#if defined(emacs) || !defined(DEBUG)
+ bss_end = (unsigned int) sbrk (0);
+ new_bss_addr = (Elf32_Addr) bss_end;
+#else
+ new_bss_addr = old_bss_addr + old_bss_size + 0x1234;
+#endif
+ new_data2_addr = old_bss_addr;
+ new_data2_size = new_bss_addr - old_bss_addr;
+ new_data2_offset = OLD_SECTION_H(old_bss_index).sh_offset;
+
+#ifdef DEBUG
+ fprintf (stderr, "old_bss_index %d\n", old_bss_index);
+ fprintf (stderr, "old_bss_addr %x\n", old_bss_addr);
+ fprintf (stderr, "old_bss_size %x\n", old_bss_size);
+ fprintf (stderr, "new_bss_addr %x\n", new_bss_addr);
+ fprintf (stderr, "new_data2_addr %x\n", new_data2_addr);
+ fprintf (stderr, "new_data2_size %x\n", new_data2_size);
+ fprintf (stderr, "new_data2_offset %x\n", new_data2_offset);
+#endif
+
+ if ((unsigned) new_bss_addr < (unsigned) old_bss_addr + old_bss_size)
+ fatal (".bss shrank when undumping???\n", 0, 0);
+
+ /* Set the output file to the right size and mmap(2) it. Set
+ * pointers to various interesting objects. stat_buf still has
+ * old_file data.
+ */
+
+ new_file = open (new_name, O_RDWR | O_CREAT, 0666);
+ if (new_file < 0)
+ fatal ("Can't creat(%s): errno %d\n", new_name, errno);
+
+ new_file_size = stat_buf.st_size + old_file_h->e_shentsize + new_data2_size;
+
+ if (ftruncate (new_file, new_file_size))
+ fatal ("Can't ftruncate(%s): errno %d\n", new_name, errno);
+
+ new_base = mmap (0, new_file_size, PROT_READ | PROT_WRITE, MAP_SHARED,
+ new_file, 0);
+
+ if (new_base == (caddr_t) -1)
+ fatal ("Can't mmap(%s): errno %d\n", new_name, errno);
+
+ new_file_h = (Elf32_Ehdr *) new_base;
+ new_program_h = (Elf32_Phdr *) ((byte *) new_base + old_file_h->e_phoff);
+ new_section_h = (Elf32_Shdr *)
+ ((byte *) new_base + old_file_h->e_shoff + new_data2_size);
+
+ /* Make our new file, program and section headers as copies of the
+ * originals.
+ */
+
+ memcpy (new_file_h, old_file_h, old_file_h->e_ehsize);
+ memcpy (new_program_h, old_program_h,
+ old_file_h->e_phnum * old_file_h->e_phentsize);
+ memcpy (new_section_h, old_section_h,
+ old_file_h->e_shnum * old_file_h->e_shentsize);
+
+ /* Fix up file header. We'll add one section. Section header is
+ * further away now.
+ */
+
+ new_file_h->e_shoff += new_data2_size;
+ new_file_h->e_shnum += 1;
+
+#ifdef DEBUG
+ fprintf (stderr, "Old section offset %x\n", old_file_h->e_shoff);
+ fprintf (stderr, "Old section count %d\n", old_file_h->e_shnum);
+ fprintf (stderr, "New section offset %x\n", new_file_h->e_shoff);
+ fprintf (stderr, "New section count %d\n", new_file_h->e_shnum);
+#endif
+
+ /* Fix up a new program header. Extend the writable data segment so
+ * that the bss area is covered too. Find that segment by looking
+ * for a segment that ends just before the .bss area. Make sure
+ * that no segments are above the new .data2. Put a loop at the end
+ * to adjust the offset and address of any segment that is above
+ * data2, just in case we decide to allow this later.
+ */
+
+ for (n = new_file_h->e_phnum - 1; n >= 0; n--)
+ {
+ /* Compute maximum of all requirements for alignment of section. */
+ int alignment = (NEW_PROGRAM_H (n)).p_align;
+ if ((OLD_SECTION_H (old_bss_index)).sh_addralign > alignment)
+ alignment = OLD_SECTION_H (old_bss_index).sh_addralign;
+
+ if (NEW_PROGRAM_H(n).p_vaddr + NEW_PROGRAM_H(n).p_filesz > old_bss_addr)
+ fatal ("Program segment above .bss in %s\n", old_name, 0);
+
+ if (NEW_PROGRAM_H(n).p_type == PT_LOAD
+ && (round_up ((NEW_PROGRAM_H (n)).p_vaddr
+ + (NEW_PROGRAM_H (n)).p_filesz,
+ alignment)
+ == round_up (old_bss_addr, alignment)))
+ break;
+ }
+ if (n < 0)
+ fatal ("Couldn't find segment next to .bss in %s\n", old_name, 0);
+
+ NEW_PROGRAM_H(n).p_filesz += new_data2_size;
+ NEW_PROGRAM_H(n).p_memsz = NEW_PROGRAM_H(n).p_filesz;
+
+#if 0 /* Maybe allow section after data2 - does this ever happen? */
+ for (n = new_file_h->e_phnum - 1; n >= 0; n--)
+ {
+ if (NEW_PROGRAM_H(n).p_vaddr
+ && NEW_PROGRAM_H(n).p_vaddr >= new_data2_addr)
+ NEW_PROGRAM_H(n).p_vaddr += new_data2_size - old_bss_size;
+
+ if (NEW_PROGRAM_H(n).p_offset >= new_data2_offset)
+ NEW_PROGRAM_H(n).p_offset += new_data2_size;
+ }
+#endif
+
+ /* Fix up section headers based on new .data2 section. Any section
+ * whose offset or virtual address is after the new .data2 section
+ * gets its value adjusted. .bss size becomes zero and new address
+ * is set. data2 section header gets added by copying the existing
+ * .data header and modifying the offset, address and size.
+ */
+
+ for (n = 1; n < new_file_h->e_shnum; n++)
+ {
+ if (NEW_SECTION_H(n).sh_offset >= new_data2_offset)
+ NEW_SECTION_H(n).sh_offset += new_data2_size;
+
+ if (NEW_SECTION_H(n).sh_addr
+ && NEW_SECTION_H(n).sh_addr >= new_data2_addr)
+ NEW_SECTION_H(n).sh_addr += new_data2_size - old_bss_size;
+ }
+
+ new_data2_index = old_file_h->e_shnum;
+
+ for (old_data_index = 1; old_data_index < old_file_h->e_shnum;
+ old_data_index++)
+ if (!strcmp (old_section_names + OLD_SECTION_H(old_data_index).sh_name,
+ ".data"))
+ break;
+ if (old_data_index == old_file_h->e_shnum)
+ fatal ("Can't find .data in %s.\n", old_name, 0);
+
+ memcpy (&NEW_SECTION_H(new_data2_index), &OLD_SECTION_H(old_data_index),
+ new_file_h->e_shentsize);
+
+ NEW_SECTION_H(new_data2_index).sh_addr = new_data2_addr;
+ NEW_SECTION_H(new_data2_index).sh_offset = new_data2_offset;
+ NEW_SECTION_H(new_data2_index).sh_size = new_data2_size;
+
+ NEW_SECTION_H(old_bss_index).sh_size = 0;
+ NEW_SECTION_H(old_bss_index).sh_addr = new_data2_addr + new_data2_size;
+
+ /* Write out the sections. .data and .data1 (and data2, called
+ * ".data" in the strings table) get copied from the current process
+ * instead of the old file.
+ */
+
+ for (n = new_file_h->e_shnum - 1; n; n--)
+ {
+ caddr_t src;
+
+ if (NEW_SECTION_H(n).sh_type == SHT_NULL
+ || NEW_SECTION_H(n).sh_type == SHT_NOBITS)
+ continue;
+
+ if (!strcmp (old_section_names + NEW_SECTION_H(n).sh_name, ".data")
+ || !strcmp ((old_section_names + NEW_SECTION_H(n).sh_name),
+ ".data1"))
+ src = (caddr_t) NEW_SECTION_H(n).sh_addr;
+ else
+ src = old_base + OLD_SECTION_H(n).sh_offset;
+
+ memcpy (NEW_SECTION_H(n).sh_offset + new_base, src,
+ NEW_SECTION_H(n).sh_size);
+ }
+
+ /* Close the files and make the new file executable */
+
+ if (close (old_file))
+ fatal ("Can't close(%s): errno %d\n", old_name, errno);
+
+ if (close (new_file))
+ fatal ("Can't close(%s): errno %d\n", new_name, errno);
+
+ if (stat (new_name, &stat_buf) == -1)
+ fatal ("Can't stat(%s): errno %d\n", new_name, errno);
+
+ n = umask (777);
+ umask (n);
+ stat_buf.st_mode |= 0111 & ~n;
+ if (chmod (new_name, stat_buf.st_mode) == -1)
+ fatal ("Can't chmod(%s): errno %d\n", new_name, errno);
+}
diff --git a/src/unexenix.c b/src/unexenix.c
new file mode 100644
index 00000000000..1ab0b57bfc2
--- /dev/null
+++ b/src/unexenix.c
@@ -0,0 +1,263 @@
+/* Unexec for Xenix.
+ Copyright (C) 1988 Free Software Foundation, Inc.
+
+ Note that the GNU project considers support for Xenix operation
+ a peripheral activity which should not be allowed to divert effort
+ from development of the GNU system. Changes in this code will be
+ installed when Xenix users send them in, but aside from that
+ we don't plan to think about it, or about whether other Emacs
+ maintenance might break it.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+In other words, you are welcome to use, share and improve this program.
+You are forbidden to forbid anyone else to use, share and improve
+what you give them. Help stamp out software-hoarding! */
+
+
+/*
+ On 80386 Xenix, segmentation screws prevent us from modifying the text
+ segment at all. We basically just plug a new value for "data segment
+ size" into the countless headers and copy the other records straight
+ through. The data segment is ORG'ed at the xs_rbase value of the data
+ segment's xseg record (always @ 0x1880000, thanks to the "sophisticated
+ memory management hardware" of the chip) and extends to sbrk(0), exactly.
+ This code is afraid to malloc (should it be?), and alloca has to be the
+ wimpy, malloc-based version; consequently, data is usually copied in
+ smallish chunks.
+
+ gb@entity.com
+*/
+
+#include "config.h"
+#include <sys/types.h>
+#include <fcntl.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <varargs.h>
+#include <a.out.h>
+
+static void fatal_unexec ();
+
+#define READ(_fd, _buffer, _size, _error_message, _error_arg) \
+ errno = EEOF; \
+ if (read(_fd, _buffer, _size) != _size) \
+ fatal_unexec(_error_message, _error_arg);
+
+#define WRITE(_fd, _buffer, _size, _error_message, _error_arg) \
+ if (write(_fd, _buffer, _size) != _size) \
+ fatal_unexec(_error_message, _error_arg);
+
+#define SEEK(_fd, _position, _error_message, _error_arg) \
+ errno = EEOF; \
+ if (lseek(_fd, _position, L_SET) != _position) \
+ fatal_unexec(_error_message, _error_arg);
+
+extern int errno;
+extern int sys_nerr;
+extern char *sys_errlist[];
+#define EEOF -1
+
+#ifndef L_SET
+#define L_SET 0
+#endif
+
+/* Should check the magic number of the old executable;
+ not yet written. */
+check_exec (x)
+ struct xexec *x;
+{
+}
+
+
+unexec (new_name, a_name, data_start, bss_start, entry_address)
+ char *new_name, *a_name;
+ unsigned data_start, bss_start, entry_address;
+{
+ char *sbrk (), *datalim = sbrk (0), *data_org;
+ long segpos, textseen, textpos, textlen, datapos, datadiff, datalen;
+
+ struct xexec u_xexec, /* a.out header */
+ *u_xexecp = &u_xexec;
+ struct xext u_xext, /* extended header */
+ *u_xextp = &u_xext;
+ struct xseg u_xseg, /* segment table entry */
+ *u_xsegp = &u_xseg;
+ int i, nsegs, isdata = 0, infd, outfd;
+
+ infd = open (a_name, O_RDONLY, 0);
+ if (infd < 0) fatal_unexec ("opening %s", a_name);
+
+ outfd = creat (new_name, 0666);
+ if (outfd < 0) fatal_unexec ("creating %s", new_name);
+
+ READ (infd, u_xexecp, sizeof (struct xexec),
+ "error reading %s", a_name);
+ check_exec (u_xexecp);
+ READ (infd, u_xextp, sizeof (struct xext),
+ "error reading %s", a_name);
+ segpos = u_xextp->xe_segpos;
+ nsegs = u_xextp->xe_segsize / sizeof (struct xseg);
+ SEEK (infd, segpos, "seek error on %s", a_name);
+ for (i = 0; i < nsegs; i ++)
+ {
+ READ (infd, u_xsegp, sizeof (struct xseg),
+ "error reading %s", a_name);
+ switch (u_xsegp->xs_type)
+ {
+ case XS_TTEXT:
+ {
+ if (i == 0)
+ {
+ textpos = u_xsegp->xs_filpos;
+ textlen = u_xsegp->xs_psize;
+ break;
+ }
+ fatal_unexec ("invalid text segment in %s", a_name);
+ }
+ case XS_TDATA:
+ {
+ if (i == 1)
+ {
+ datapos = u_xsegp->xs_filpos;
+ datalen = datalim - (data_org = (char *)(u_xsegp->xs_rbase));
+ datadiff = datalen - u_xsegp->xs_psize;
+ break;
+ }
+ fatal_unexec ("invalid data segment in %s", a_name);
+ }
+ default:
+ {
+ if (i > 1) break;
+ fatal_unexec ("invalid segment record in %s", a_name);
+ }
+ }
+ }
+ u_xexecp->x_data = datalen;
+ u_xexecp->x_bss = 0;
+ WRITE (outfd, u_xexecp, sizeof (struct xexec),
+ "error writing %s", new_name);
+ WRITE (outfd, u_xextp, sizeof (struct xext),
+ "error writing %s", new_name);
+ SEEK (infd, segpos, "seek error on %s", a_name);
+ SEEK (outfd, segpos, "seek error on %s", new_name);
+
+ /* Copy the text segment record verbatim. */
+
+ copyrec (infd, outfd, sizeof (struct xseg), a_name, new_name);
+
+ /* Read, modify, write the data segment record. */
+
+ READ (infd, u_xsegp, sizeof (struct xseg),
+ "error reading %s", a_name);
+ u_xsegp->xs_psize = u_xsegp->xs_vsize = datalen;
+ u_xsegp->xs_attr &= (~XS_AITER & ~XS_ABSS);
+ WRITE (outfd, u_xsegp, sizeof (struct xseg),
+ "error writing %s", new_name);
+
+ /* Now copy any additional segment records, adjusting their
+ file position field */
+
+ for (i = 2; i < nsegs; i++)
+ {
+ READ (infd, u_xsegp, sizeof (struct xseg),
+ "error reading %s", a_name);
+ u_xsegp->xs_filpos += datadiff;
+ WRITE (outfd, u_xsegp, sizeof (struct xseg),
+ "error writing %s", new_name);
+ }
+
+ SEEK (infd, textpos, "seek error on %s", a_name);
+ SEEK (outfd, textpos, "seek error on %s", new_name);
+ copyrec (infd, outfd, textlen, a_name, new_name);
+
+ SEEK (outfd, datapos, "seek error on %s", new_name);
+ WRITE (outfd, data_org, datalen,
+ "write error on %s", new_name);
+
+ for (i = 2, segpos += (2 * sizeof (struct xseg));
+ i < nsegs;
+ i++, segpos += sizeof (struct xseg))
+ {
+ SEEK (infd, segpos, "seek error on %s", a_name);
+ READ (infd, u_xsegp, sizeof (struct xseg),
+ "read error on %s", a_name);
+ SEEK (infd, u_xsegp->xs_filpos, "seek error on %s", a_name);
+ /* We should be at eof in the output file here, but we must seek
+ because the xs_filpos and xs_psize fields in symbol table
+ segments are inconsistent. */
+ SEEK (outfd, u_xsegp->xs_filpos + datadiff, "seek error on %s", new_name);
+ copyrec (infd, outfd, u_xsegp->xs_psize, a_name, new_name);
+ }
+ close (infd);
+ close (outfd);
+ mark_x (new_name);
+ return 0;
+}
+
+copyrec (infd, outfd, len, in_name, out_name)
+ int infd, outfd, len;
+ char *in_name, *out_name;
+{
+ char buf[BUFSIZ];
+ int chunk;
+
+ while (len)
+ {
+ chunk = BUFSIZ;
+ if (chunk > len)
+ chunk = len;
+ READ (infd, buf, chunk, "error reading %s", in_name);
+ WRITE (outfd, buf, chunk, "error writing %s", out_name);
+ len -= chunk;
+ }
+}
+
+/*
+ * mark_x
+ *
+ * After succesfully building the new a.out, mark it executable
+ */
+static
+mark_x (name)
+ char *name;
+{
+ struct stat sbuf;
+ int um = umask (777);
+ umask (um);
+ if (stat (name, &sbuf) < 0)
+ fatal_unexec ("getting protection on %s", name);
+ sbuf.st_mode |= 0111 & ~um;
+ if (chmod (name, sbuf.st_mode) < 0)
+ fatal_unexec ("setting protection on %s", name);
+}
+
+static void
+fatal_unexec (s, va_alist)
+ va_dcl
+{
+ va_list ap;
+ if (errno == EEOF)
+ fputs ("unexec: unexpected end of file, ", stderr);
+ else if (errno < sys_nerr)
+ fprintf (stderr, "unexec: %s, ", sys_errlist[errno]);
+ else
+ fprintf (stderr, "unexec: error code %d, ", errno);
+ va_start (ap);
+ _doprnt (s, ap, stderr);
+ fputs (".\n", stderr);
+ exit (1);
+}
diff --git a/src/unexfx2800.c b/src/unexfx2800.c
new file mode 100644
index 00000000000..89e14e678d8
--- /dev/null
+++ b/src/unexfx2800.c
@@ -0,0 +1,16 @@
+/* Unexec for the Alliant FX/2800. */
+
+#include <stdio.h>
+
+unexec (new_name, a_name, data_start, bss_start, entry_address)
+ char *new_name, *a_name;
+ unsigned data_start, bss_start, entry_address;
+{
+ int stat;
+
+ stat = elf_write_modified_data (a_name, new_name);
+ if (stat < 0)
+ perror ("emacs: elf_write_modified_data");
+ else if (stat > 0)
+ fprintf (stderr, "Unspecified error from elf_write_modified_data.\n");
+}
diff --git a/src/unexhp9k800.c b/src/unexhp9k800.c
index 259b9318514..8d34a3a3d7a 100644
--- a/src/unexhp9k800.c
+++ b/src/unexhp9k800.c
@@ -60,6 +60,7 @@ unexec(new_name, old_name, new_end_of_text, dummy1, dummy2)
int old_size, new_size;
struct header hdr;
struct som_exec_auxhdr auxhdr;
+ long i;
/* For the greatest flexibility, should create a temporary file in
the same directory as the new file. When everything is complete,
@@ -81,7 +82,10 @@ unexec(new_name, old_name, new_end_of_text, dummy1, dummy2)
/* Decide how large the new and old data areas are */
old_size = auxhdr.exec_dsize;
- new_size = sbrk(0) - auxhdr.exec_dmem;
+ /* I suspect these two statements are separate
+ to avoid a compiler bug in hpux version 8. */
+ i = sbrk (0);
+ new_size = i - auxhdr.exec_dmem;
/* Copy the old file to the new, up to the data space */
lseek(old, 0, 0);
diff --git a/src/unexmips.c b/src/unexmips.c
new file mode 100644
index 00000000000..9d1638d653a
--- /dev/null
+++ b/src/unexmips.c
@@ -0,0 +1,317 @@
+/* Unexec for MIPS (including IRIS4D).
+ Copyright (C) 1988 Free Software Foundation, Inc.
+
+ Note that the GNU project considers support for MIPS operation
+ a peripheral activity which should not be allowed to divert effort
+ from development of the GNU system. Changes in this code will be
+ installed when users send them in, but aside from that
+ we don't plan to think about it, or about whether other Emacs
+ maintenance might break it.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+In other words, you are welcome to use, share and improve this program.
+You are forbidden to forbid anyone else to use, share and improve
+what you give them. Help stamp out software-hoarding! */
+
+#include "config.h"
+#include <sys/types.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <varargs.h>
+#include <filehdr.h>
+#include <aouthdr.h>
+#include <scnhdr.h>
+#include <sym.h>
+
+#if defined (IRIS_4D) || defined (sony)
+#include "getpagesize.h"
+#include <fcntl.h>
+#endif
+
+static void fatal_unexec ();
+static int mark_x ();
+
+#define READ(_fd, _buffer, _size, _error_message, _error_arg) \
+ errno = EEOF; \
+ if (read (_fd, _buffer, _size) != _size) \
+ fatal_unexec (_error_message, _error_arg);
+
+#define WRITE(_fd, _buffer, _size, _error_message, _error_arg) \
+ if (write (_fd, _buffer, _size) != _size) \
+ fatal_unexec (_error_message, _error_arg);
+
+#define SEEK(_fd, _position, _error_message, _error_arg) \
+ errno = EEOF; \
+ if (lseek (_fd, _position, L_SET) != _position) \
+ fatal_unexec (_error_message, _error_arg);
+
+extern int errno;
+extern int sys_nerr;
+extern char *sys_errlist[];
+#define EEOF -1
+
+static struct scnhdr *text_section;
+static struct scnhdr *init_section;
+static struct scnhdr *finit_section;
+static struct scnhdr *rdata_section;
+static struct scnhdr *data_section;
+static struct scnhdr *lit8_section;
+static struct scnhdr *lit4_section;
+static struct scnhdr *sdata_section;
+static struct scnhdr *sbss_section;
+static struct scnhdr *bss_section;
+
+struct headers {
+ struct filehdr fhdr;
+ struct aouthdr aout;
+ struct scnhdr section[10];
+};
+
+/* Define name of label for entry point for the dumped executable. */
+
+#ifndef DEFAULT_ENTRY_ADDRESS
+#define DEFAULT_ENTRY_ADDRESS __start
+#endif
+
+unexec (new_name, a_name, data_start, bss_start, entry_address)
+ char *new_name, *a_name;
+ unsigned data_start, bss_start, entry_address;
+{
+ int new, old;
+ int pagesize, brk;
+ int newsyms, symrel;
+ int nread;
+ struct headers hdr;
+ int i;
+ int vaddr, scnptr;
+#define BUFSIZE 8192
+ char buffer[BUFSIZE];
+
+ old = open (a_name, O_RDONLY, 0);
+ if (old < 0) fatal_unexec ("opening %s", a_name);
+
+ new = creat (new_name, 0666);
+ if (new < 0) fatal_unexec ("creating %s", new_name);
+
+ hdr = *((struct headers *)TEXT_START);
+#ifdef MIPS2
+ if (hdr.fhdr.f_magic != MIPSELMAGIC
+ && hdr.fhdr.f_magic != MIPSEBMAGIC
+ && hdr.fhdr.f_magic != (MIPSELMAGIC | 1)
+ && hdr.fhdr.f_magic != (MIPSEBMAGIC | 1))
+ {
+ fprintf (stderr,
+ "unexec: input file magic number is %x, not %x, %x, %x or %x.\n",
+ hdr.fhdr.f_magic,
+ MIPSELMAGIC, MIPSEBMAGIC,
+ MIPSELMAGIC | 1, MIPSEBMAGIC | 1);
+ exit (1);
+ }
+#else /* not MIPS2 */
+ if (hdr.fhdr.f_magic != MIPSELMAGIC
+ && hdr.fhdr.f_magic != MIPSEBMAGIC)
+ {
+ fprintf (stderr, "unexec: input file magic number is %x, not %x or %x.\n",
+ hdr.fhdr.f_magic, MIPSELMAGIC, MIPSEBMAGIC);
+ exit (1);
+ }
+#endif /* not MIPS2 */
+ if (hdr.fhdr.f_opthdr != sizeof (hdr.aout))
+ {
+ fprintf (stderr, "unexec: input a.out header is %d bytes, not %d.\n",
+ hdr.fhdr.f_opthdr, sizeof (hdr.aout));
+ exit (1);
+ }
+ if (hdr.aout.magic != ZMAGIC)
+ {
+ fprintf (stderr, "unexec: input file a.out magic number is %o, not %o.\n",
+ hdr.aout.magic, ZMAGIC);
+ exit (1);
+ }
+
+#define CHECK_SCNHDR(ptr, name, flags) \
+ ptr = NULL; \
+ for (i = 0; i < hdr.fhdr.f_nscns && !ptr; i++) \
+ if (strcmp (hdr.section[i].s_name, name) == 0) { \
+ if (hdr.section[i].s_flags != flags) { \
+ fprintf (stderr, "unexec: %x flags where %x expected in %s section.\n", \
+ hdr.section[i].s_flags, flags, name); \
+ } \
+ ptr = hdr.section + i; \
+ }
+
+ CHECK_SCNHDR (text_section, _TEXT, STYP_TEXT);
+ CHECK_SCNHDR (init_section, _INIT, STYP_INIT);
+ CHECK_SCNHDR (rdata_section, _RDATA, STYP_RDATA);
+ CHECK_SCNHDR (data_section, _DATA, STYP_DATA);
+#ifdef _LIT8
+ CHECK_SCNHDR (lit8_section, _LIT8, STYP_LIT8);
+ CHECK_SCNHDR (lit4_section, _LIT4, STYP_LIT4);
+#endif /* _LIT8 */
+ CHECK_SCNHDR (sdata_section, _SDATA, STYP_SDATA);
+ CHECK_SCNHDR (sbss_section, _SBSS, STYP_SBSS);
+ CHECK_SCNHDR (bss_section, _BSS, STYP_BSS);
+#if 0 /* Apparently this error check goes off on irix 3.3,
+ but it doesn't indicate a real problem. */
+ if (i != hdr.fhdr.f_nscns)
+ fprintf (stderr, "unexec: %d sections found instead of %d.\n",
+ i, hdr.fhdr.f_nscns);
+#endif
+
+ text_section->s_scnptr = 0;
+
+ pagesize = getpagesize ();
+ brk = (sbrk (0) + pagesize - 1) & (-pagesize);
+ hdr.aout.dsize = brk - DATA_START;
+ hdr.aout.bsize = 0;
+ if (entry_address == 0)
+ {
+ extern DEFAULT_ENTRY_ADDRESS ();
+ hdr.aout.entry = (unsigned)DEFAULT_ENTRY_ADDRESS;
+ }
+ else
+ hdr.aout.entry = entry_address;
+
+ hdr.aout.bss_start = hdr.aout.data_start + hdr.aout.dsize;
+ rdata_section->s_size = data_start - DATA_START;
+
+ /* Adjust start and virtual addresses of rdata_section, too. */
+ rdata_section->s_vaddr = DATA_START;
+ rdata_section->s_paddr = DATA_START;
+ rdata_section->s_scnptr = text_section->s_scnptr + hdr.aout.tsize;
+
+ data_section->s_vaddr = data_start;
+ data_section->s_paddr = data_start;
+ data_section->s_size = brk - data_start;
+ data_section->s_scnptr = rdata_section->s_scnptr + rdata_section->s_size;
+ vaddr = data_section->s_vaddr + data_section->s_size;
+ scnptr = data_section->s_scnptr + data_section->s_size;
+ if (lit8_section != NULL)
+ {
+ lit8_section->s_vaddr = vaddr;
+ lit8_section->s_paddr = vaddr;
+ lit8_section->s_size = 0;
+ lit8_section->s_scnptr = scnptr;
+ }
+ if (lit4_section != NULL)
+ {
+ lit4_section->s_vaddr = vaddr;
+ lit4_section->s_paddr = vaddr;
+ lit4_section->s_size = 0;
+ lit4_section->s_scnptr = scnptr;
+ }
+ if (sdata_section != NULL)
+ {
+ sdata_section->s_vaddr = vaddr;
+ sdata_section->s_paddr = vaddr;
+ sdata_section->s_size = 0;
+ sdata_section->s_scnptr = scnptr;
+ }
+ if (sbss_section != NULL)
+ {
+ sbss_section->s_vaddr = vaddr;
+ sbss_section->s_paddr = vaddr;
+ sbss_section->s_size = 0;
+ sbss_section->s_scnptr = scnptr;
+ }
+ if (bss_section != NULL)
+ {
+ bss_section->s_vaddr = vaddr;
+ bss_section->s_paddr = vaddr;
+ bss_section->s_size = 0;
+ bss_section->s_scnptr = scnptr;
+ }
+
+ WRITE (new, TEXT_START, hdr.aout.tsize,
+ "writing text section to %s", new_name);
+ WRITE (new, DATA_START, hdr.aout.dsize,
+ "writing text section to %s", new_name);
+
+ SEEK (old, hdr.fhdr.f_symptr, "seeking to start of symbols in %s", a_name);
+ errno = EEOF;
+ nread = read (old, buffer, BUFSIZE);
+ if (nread < sizeof (HDRR)) fatal_unexec ("reading symbols from %s", a_name);
+#define symhdr ((pHDRR)buffer)
+ newsyms = hdr.aout.tsize + hdr.aout.dsize;
+ symrel = newsyms - hdr.fhdr.f_symptr;
+ hdr.fhdr.f_symptr = newsyms;
+ symhdr->cbLineOffset += symrel;
+ symhdr->cbDnOffset += symrel;
+ symhdr->cbPdOffset += symrel;
+ symhdr->cbSymOffset += symrel;
+ symhdr->cbOptOffset += symrel;
+ symhdr->cbAuxOffset += symrel;
+ symhdr->cbSsOffset += symrel;
+ symhdr->cbSsExtOffset += symrel;
+ symhdr->cbFdOffset += symrel;
+ symhdr->cbRfdOffset += symrel;
+ symhdr->cbExtOffset += symrel;
+#undef symhdr
+ do
+ {
+ if (write (new, buffer, nread) != nread)
+ fatal_unexec ("writing symbols to %s", new_name);
+ nread = read (old, buffer, BUFSIZE);
+ if (nread < 0) fatal_unexec ("reading symbols from %s", a_name);
+#undef BUFSIZE
+ } while (nread != 0);
+
+ SEEK (new, 0, "seeking to start of header in %s", new_name);
+ WRITE (new, &hdr, sizeof (hdr),
+ "writing header of %s", new_name);
+
+ close (old);
+ close (new);
+ mark_x (new_name);
+}
+
+/*
+ * mark_x
+ *
+ * After succesfully building the new a.out, mark it executable
+ */
+
+static int
+mark_x (name)
+ char *name;
+{
+ struct stat sbuf;
+ int um = umask (777);
+ umask (um);
+ if (stat (name, &sbuf) < 0)
+ fatal_unexec ("getting protection on %s", name);
+ sbuf.st_mode |= 0111 & ~um;
+ if (chmod (name, sbuf.st_mode) < 0)
+ fatal_unexec ("setting protection on %s", name);
+}
+
+static void
+fatal_unexec (s, va_alist)
+ va_dcl
+{
+ va_list ap;
+ if (errno == EEOF)
+ fputs ("unexec: unexpected end of file, ", stderr);
+ else if (errno < sys_nerr)
+ fprintf (stderr, "unexec: %s, ", sys_errlist[errno]);
+ else
+ fprintf (stderr, "unexec: error code %d, ", errno);
+ va_start (ap);
+ _doprnt (s, ap, stderr);
+ fputs (".\n", stderr);
+ exit (1);
+}
diff --git a/src/unexnext.c b/src/unexnext.c
new file mode 100644
index 00000000000..993f76752f2
--- /dev/null
+++ b/src/unexnext.c
@@ -0,0 +1,432 @@
+/* Dump Emacs in macho format.
+ Copyright (C) 1990 Free Software Foundation, Inc.
+ Written by Bradley Taylor (btaylor@next.com).
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#undef __STRICT_BSD__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <mach/mach.h>
+#include <mach-o/loader.h>
+#include <mach-o/fat.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <libc.h>
+
+int malloc_cookie;
+
+/*
+ * Kludge: we don't expect any program data beyond VM_HIGHDATA
+ * What is really needed is a way to find out from malloc() which
+ * pages it vm_allocated and write only those out into the data segment.
+ *
+ * This kludge may break when we stop using fixed virtual address
+ * shared libraries. Actually, emacs will probably continue working, but be
+ * much larger on disk than it needs to be (because non-malloced data will
+ * be in the file).
+ */
+static const unsigned VM_HIGHDATA = 0x2000000;
+
+typedef struct region_t {
+ vm_address_t address;
+ vm_size_t size;
+ vm_prot_t protection;
+ vm_prot_t max_protection;
+ vm_inherit_t inheritance;
+ boolean_t shared;
+ port_t object_name;
+ vm_offset_t offset;
+} region_t;
+
+
+static void
+grow(
+ struct load_command ***the_commands,
+ unsigned *the_commands_len
+ )
+{
+ if (*the_commands == NULL) {
+ *the_commands_len = 1;
+ *the_commands = malloc(sizeof(*the_commands));
+ } else {
+ (*the_commands_len)++;
+ *the_commands = realloc(*the_commands,
+ (*the_commands_len *
+ sizeof(**the_commands)));
+ }
+}
+
+
+static void
+save_command(
+ struct load_command *command,
+ struct load_command ***the_commands,
+ unsigned *the_commands_len
+ )
+{
+ struct load_command **tmp;
+
+ grow(the_commands, the_commands_len);
+ tmp = &(*the_commands)[*the_commands_len - 1];
+ *tmp = malloc(command->cmdsize);
+ bcopy(command, *tmp, command->cmdsize);
+}
+
+static void
+fatal_unexec(char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ fprintf(stderr, "unexec: ");
+ vfprintf(stderr, format, ap);
+ fprintf(stderr, "\n");
+ va_end(ap);
+}
+
+static int
+read_macho(
+ int fd,
+ struct mach_header *the_header,
+ struct load_command ***the_commands,
+ unsigned *the_commands_len
+ )
+{
+ struct load_command command;
+ struct load_command *buf;
+ int i;
+ int size;
+
+ if (read(fd, the_header, sizeof(*the_header)) != sizeof(*the_header)) {
+ fatal_unexec("cannot read macho header");
+ return (0);
+ }
+ /* the mach header should already be in native form */
+ if (the_header->magic != MH_MAGIC) {
+ fatal_unexec("wrong magic in macho header");
+ }
+ for (i = 0; i < the_header->ncmds; i++) {
+ if (read(fd, &command, sizeof(struct load_command)) !=
+ sizeof(struct load_command)) {
+ fatal_unexec("cannot read macho load command header");
+ return (0);
+ }
+ size = command.cmdsize - sizeof(struct load_command);
+ if (size < 0) {
+ fatal_unexec("bogus load command size");
+ return (0);
+ }
+ buf = malloc(command.cmdsize);
+ buf->cmd = command.cmd;
+ buf->cmdsize = command.cmdsize;
+ if (read(fd, ((char *)buf +
+ sizeof(struct load_command)),
+ size) != size) {
+ fatal_unexec("cannot read load command data");
+ return (0);
+ }
+ save_command(buf, the_commands, the_commands_len);
+ }
+ /* Leave the file pointer at the beginning of the text segment */
+ return (1);
+}
+
+static int
+filldatagap(
+ vm_address_t start_address,
+ vm_size_t *size,
+ vm_address_t end_address
+ )
+{
+ vm_address_t address;
+ vm_size_t gapsize;
+
+ address = (start_address + *size);
+ gapsize = end_address - address;
+ *size += gapsize;
+ if (vm_allocate(task_self(), &address, gapsize,
+ FALSE) != KERN_SUCCESS) {
+ fatal_unexec("cannot vm_allocate");
+ return (0);
+ }
+ return (1);
+}
+
+static int
+get_data_region(
+ vm_address_t *address,
+ vm_size_t *size
+ )
+{
+ region_t region;
+ kern_return_t ret;
+ const struct section *sect;
+
+ sect = getsectbyname(SEG_DATA, SECT_DATA);
+ region.address = 0;
+ *address = 0;
+ for (;;) {
+ ret = vm_region(task_self(),
+ &region.address,
+ &region.size,
+ &region.protection,
+ &region.max_protection,
+ &region.inheritance,
+ &region.shared,
+ &region.object_name,
+ &region.offset);
+ if (ret != KERN_SUCCESS || region.address >= VM_HIGHDATA) {
+ break;
+ }
+ if (*address != 0) {
+ if (region.address > *address + *size) {
+ if (!filldatagap(*address, size,
+ region.address)) {
+ return (0);
+ }
+ }
+ *size += region.size;
+ } else {
+ if (region.address == sect->addr) {
+ *address = region.address;
+ *size = region.size;
+ }
+ }
+ region.address += region.size;
+ }
+ return (1);
+}
+
+static char *
+my_malloc(
+ vm_size_t size
+ )
+{
+ vm_address_t address;
+
+ if (vm_allocate(task_self(), &address, size, TRUE) != KERN_SUCCESS) {
+ return (NULL);
+ }
+ return ((char *)address);
+}
+
+static void
+my_free(
+ char *buf,
+ vm_size_t size
+ )
+{
+ vm_deallocate(task_self(), (vm_address_t)buf, size);
+}
+
+static int
+unexec_doit(
+ int infd,
+ int outfd
+ )
+{
+ int i;
+ struct load_command **the_commands = NULL;
+ unsigned the_commands_len;
+ struct mach_header the_header;
+ int fgrowth;
+ int fdatastart;
+ int fdatasize;
+ int size;
+ struct stat st;
+ char *buf;
+ vm_address_t data_address;
+ vm_size_t data_size;
+
+ struct segment_command *segment;
+
+ if (!read_macho(infd, &the_header, &the_commands, &the_commands_len)) {
+ return (0);
+ }
+
+ malloc_cookie = malloc_freezedry();
+
+ if (!get_data_region(&data_address, &data_size)) {
+ return (0);
+ }
+
+
+ /*
+ * DO NOT USE MALLOC IN THIS SECTION
+ */
+ {
+ /*
+ * Fix offsets
+ */
+ for (i = 0; i < the_commands_len; i++) {
+ switch (the_commands[i]->cmd) {
+ case LC_SEGMENT:
+ segment = ((struct segment_command *)
+ the_commands[i]);
+ if (strcmp(segment->segname, SEG_DATA) == 0) {
+ fdatastart = segment->fileoff;
+ fdatasize = segment->filesize;
+ fgrowth = (data_size -
+ segment->filesize);
+ segment->vmsize = data_size;
+ segment->filesize = data_size;
+ }
+ break;
+ case LC_SYMTAB:
+ ((struct symtab_command *)
+ the_commands[i])->symoff += fgrowth;
+ ((struct symtab_command *)
+ the_commands[i])->stroff += fgrowth;
+ break;
+ case LC_SYMSEG:
+ ((struct symseg_command *)
+ the_commands[i])->offset += fgrowth;
+ break;
+ default:
+ break;
+ }
+ }
+
+ /*
+ * Write header
+ */
+ if (write(outfd, &the_header,
+ sizeof(the_header)) != sizeof(the_header)) {
+ fatal_unexec("cannot write output file");
+ return (0);
+ }
+
+ /*
+ * Write commands
+ */
+ for (i = 0; i < the_commands_len; i++) {
+ if (write(outfd, the_commands[i],
+ the_commands[i]->cmdsize) !=
+ the_commands[i]->cmdsize) {
+ fatal_unexec("cannot write output file");
+ return (0);
+ }
+ }
+
+ /*
+ * Write original text
+ * We're already positioned at the beginning of the text
+ * segment, so all we need to do is to copy the bytes.
+ */
+ size = fdatastart - (sizeof(the_header) +
+ the_header.sizeofcmds);
+ buf = my_malloc(size);
+ if (read(infd, buf, size) != size) {
+ my_free(buf, size);
+ fatal_unexec("cannot read input file");
+ }
+ if (write(outfd, buf, size) != size) {
+ my_free(buf, size);
+ fatal_unexec("cannot write output file");
+ return (0);
+ }
+ my_free(buf, size);
+
+
+ /*
+ * Write new data
+ */
+ if (write(outfd, (char *)data_address,
+ data_size) != data_size) {
+ fatal_unexec("cannot write output file");
+ return (0);
+ }
+
+ }
+
+ /*
+ * OKAY TO USE MALLOC NOW
+ */
+
+ /*
+ * Write rest of file
+ */
+ fstat(infd, &st);
+ if (lseek(infd, fdatasize, L_INCR) < 0) {
+ fatal_unexec("cannot seek input file");
+ return (0);
+ }
+ size = st.st_size - lseek(infd, 0, L_INCR);
+
+ buf = malloc(size);
+ if (read(infd, buf, size) != size) {
+ free(buf);
+ fatal_unexec("cannot read input file");
+ return (0);
+ }
+ if (write(outfd, buf, size) != size) {
+ free(buf);
+ fatal_unexec("cannot write output file");
+ return (0);
+ }
+ free(buf);
+ return (1);
+}
+
+void
+unexec(
+ char *outfile,
+ char *infile
+ )
+{
+ int infd;
+ int outfd;
+ char tmpbuf[L_tmpnam];
+ char *tmpfile;
+
+ infd = open(infile, O_RDONLY, 0);
+ if (infd < 0) {
+ fatal_unexec("cannot open input file `%s'", infile);
+ exit(1);
+ }
+
+ tmpnam(tmpbuf);
+ tmpfile = rindex(tmpbuf, '/');
+ if (tmpfile == NULL) {
+ tmpfile = tmpbuf;
+ } else {
+ tmpfile++;
+ }
+ outfd = open(tmpfile, O_WRONLY|O_TRUNC|O_CREAT, 0755);
+ if (outfd < 0) {
+ close(infd);
+ fatal_unexec("cannot open tmp file `%s'", tmpfile);
+ exit(1);
+ }
+ if (!unexec_doit(infd, outfd)) {
+ close(infd);
+ close(outfd);
+ unlink(tmpfile);
+ exit(1);
+ }
+ close(infd);
+ close(outfd);
+ if (rename(tmpfile, outfile) < 0) {
+ unlink(tmpfile);
+ fatal_unexec("cannot rename `%s' to `%s'", tmpfile, outfile);
+ exit(1);
+ }
+}
diff --git a/src/unexshm.c b/src/unexshm.c
new file mode 100644
index 00000000000..538a095f3d8
--- /dev/null
+++ b/src/unexshm.c
@@ -0,0 +1,285 @@
+/* Attempted unexec for AIX.
+ Copyright (c) 1990 Free Software Foundation, Inc.
+
+ This file is not used because it occasionally fails to work. This
+ happens because the bss address when Emacs is run is not always the
+ same. If it happens to be different from what it was
+ when Emacs was dumped, the dumped data won't work.
+ No one has been able to prevent the address from varying.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* This is based on a public domain program written by IBM. */
+
+/*************** SYSTEM DEFINES *********************************/
+
+#include "config.h"
+#include "paths.h"
+#include <sys/types.h>
+#include <sys/file.h>
+#include <fcntl.h>
+#include <sys/mode.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <malloc.h>
+#include <stdio.h> /* MWW */
+#include "lisp.h"
+
+/*************** LOCAL DEFINES **********************************/
+
+struct data_header /* saved data header */
+{
+ char *start; /* dump _data addr */
+ char *end; /* dump _end addr */
+ char *sbrk1; /* dump original sbrk addr */
+ char *sbrk2; /* dump final sbrk addr */
+ int puresize; /* size of pure data dumped */
+};
+
+#define EMACSSHMKEY "EMACSSHMKEY"
+#define EMACS_DATA_FILE "EMACS-DATA"
+#define NEW_SHMGET_FLAGS (IPC_CREAT | S_IWUSR | S_IRUSR \
+ | S_IWGRP | S_IRGRP | S_IWOTH | S_IROTH)
+#define OLD_SHMAT_FLAGS SHM_RDONLY
+#define OLD_SHMGET_FLAGS (S_IRUSR | S_IRGRP | S_IROTH)
+#define OLD_OPEN_FLAGS O_RDONLY
+#define NEW_OPEN_FLAGS (O_RDWR | O_CREAT | O_TRUNC)
+
+/*************** EXTERNAL / GLOBAL DATA AREA ********************/
+
+extern char _data; /* start of data addr */
+extern char _end; /* end of all data + 1 addr */
+static char *original_sbrk; /* sbrk when dump first run */
+
+void
+map_in_data (use_dumped_data)
+ int use_dumped_data;
+{
+ int bufsize; /* malloc buffer size */
+ struct data_header dh; /* saved data header */
+ int fd; /* saved data file descriptor */
+ char *finaladdr; /* last addr in bucket */
+ char *ipckey = getenv (EMACSSHMKEY); /* env ipc key string */
+ int length; /* dumped data lengths */
+ char *newaddr; /* new malloc buffer addr */
+ int numblks; /* number of remaining mallocs */
+ int shmid; /* shared memory id */
+ key_t shmkey; /* shared memory key */
+ /* Note that using malloc here may not be safe. */
+ char name[sizeof (PATH_EXEC) + sizeof (EMACS_DATA_FILE) + 2];
+
+ /* Consume remaining malloc space without increasing */
+ /* the end of data space */
+ original_sbrk = sbrk (0);
+ for (bufsize = 16; bufsize < getpagesize (); bufsize *= 2)
+ {
+ while ((newaddr = (char *)malloc (bufsize - 8)) < original_sbrk)
+ ;
+ for (numblks = (getpagesize () / bufsize) - 1; numblks > 0; numblks--)
+ malloc (bufsize - 8);
+ finaladdr = sbrk (0);
+ }
+ original_sbrk = sbrk (0);
+
+ /* Determine ipc key from environment or default */
+ if (ipckey && *ipckey)
+ shmkey = atoi (ipckey);
+ else
+ shmkey = SHMKEY;
+
+ /* If we don't want the dumped data, get an unshared segment. */
+ if (!use_dumped_data)
+ {
+ shmid = shmget (IPC_PRIVATE, PURESIZE, NEW_SHMGET_FLAGS);
+ if (shmid == -1
+ || shmat (shmid, (char *)PURE_SEG_BITS, 0) == -1)
+ {
+ fprintf (stderr, "emacs: failure obtaining new unshared memory segment.\n");
+ exit (1);
+ }
+ return;
+ }
+
+ /* Compute the file name with the dumped data. */
+ strcpy (name, PATH_EXEC);
+ strcat (name, "/");
+ strcat (name, EMACS_DATA_FILE);
+
+ /* Open the file and make sure the addresses have not changed. */
+ fd = open (name, OLD_OPEN_FLAGS, 0);
+ if (fd < 0)
+ {
+ fprintf (stderr, "emacs: failure opening `%s'\n", name);
+ exit (1);
+ }
+ if (read (fd, (char *)&dh, sizeof (dh)) != sizeof (dh)
+ || dh.start != &_data
+ || dh.end != &_end
+ || dh.sbrk1 != original_sbrk
+ || dh.puresize != PURESIZE)
+ {
+ fprintf (stderr, "emacs: header mismatch in `%s'\n", name);
+ exit (1);
+ }
+
+ /* Load in the unshared contents. */
+ if (!(length = dh.end - dh.start)
+ || read (fd, (char *)&_data, length) != length
+ || !(length = dh.sbrk2 - dh.sbrk1)
+ || brk (dh.sbrk2) == -1
+ || read (fd, dh.sbrk1, length) != length)
+ {
+ fprintf (stderr, "emacs: failure loading unshared data.\n");
+ exit (1);
+ }
+
+ /* Attach to "pure data" shared memory segment */
+ if ((shmid = shmget (shmkey, 0, 0)) == -1
+ || (newaddr = shmat (shmid, (char *)PURE_SEG_BITS, OLD_SHMAT_FLAGS)) == -1)
+ {
+ /* We were unable to open an existing segment. Make a new one. */
+ struct shmid_ds buf;
+
+ /* First get rid of the one we tried to get. */
+ shmdt ((char *)PURE_SEG_BITS);
+ shmctl (shmid, IPC_RMID, 0);
+
+ /* If we could not write the data file,
+ don't make a shared segment that we could write.
+ Make an unshared segment instead. */
+ if (access (name, W_OK) != 0)
+ {
+ shmid = shmget (IPC_PRIVATE, PURESIZE, NEW_SHMGET_FLAGS);
+ if (shmid == -1
+ || shmat (shmid, (char *)PURE_SEG_BITS, 0) == -1)
+ {
+ fprintf (stderr, "emacs: failure obtaining new unshared memory segment.\n");
+ exit (1);
+ }
+
+ /* Load the proper data into it. */
+ if (read (fd, PURE_SEG_BITS, PURESIZE) != PURESIZE)
+ {
+ fprintf (stderr, "emacs: failure loading shared memory data.\n");
+ shmdt ((char *)PURE_SEG_BITS);
+ shmctl (shmid, IPC_RMID, 0);
+ exit (1);
+ }
+
+ close (fd);
+ return;
+ }
+
+ /* Allocate the new shared segment and arrange to write it. */
+ if ((shmid = shmget (shmkey, PURESIZE, NEW_SHMGET_FLAGS)) == -1
+ || shmat (shmid, (char *)PURE_SEG_BITS, 0) == -1)
+ {
+ fprintf (stderr, "emacs: failure obtaining new shared memory segment.\n");
+ shmdt ((char *)PURE_SEG_BITS);
+ shmctl (shmid, IPC_RMID, 0);
+ exit (1);
+ }
+
+ /* Load the proper data into it. */
+ if (read (fd, PURE_SEG_BITS, PURESIZE) != PURESIZE)
+ {
+ fprintf (stderr, "emacs: failure loading shared memory data.\n");
+ shmdt ((char *)PURE_SEG_BITS);
+ shmctl (shmid, IPC_RMID, 0);
+ exit (1);
+ }
+
+ /* Detach from the segment and bring it back readonly. */
+ shmdt ((char *)PURE_SEG_BITS);
+
+ shmctl (shmid, IPC_STAT, &buf);
+ buf.shm_perm.mode = OLD_SHMGET_FLAGS;
+ shmctl (shmid, IPC_SET, &buf);
+
+ newaddr = shmat (shmid, (char *)PURE_SEG_BITS, OLD_SHMAT_FLAGS);
+ if (newaddr == -1)
+ {
+ fprintf (stderr, "emacs: failure reattaching shared memory segment.\n");
+ shmctl (shmid, IPC_RMID, 0);
+ exit (1);
+ }
+ }
+
+ close (fd);
+}
+
+/* Dump the appropriate parts of memory into a file named NEW
+ from which the shared segment can be initialized. */
+
+void
+map_out_data (new)
+ char *new;
+{
+ struct data_header dh; /* saved data header */
+ int fd; /* saved data file descriptor */
+ int length; /* dumped data length; */
+ int shmid;
+ key_t shmkey; /* shared memory key */
+ char *ipckey = getenv (EMACSSHMKEY); /* env ipc key string */
+
+ /* Determine ipc key from environment or default */
+ if (ipckey && *ipckey)
+ shmkey = atoi (ipckey);
+ else
+ shmkey = SHMKEY;
+
+ /* Create "saved data" file header */
+ dh.start = &_data;
+ dh.end = &_end;
+ dh.sbrk1 = original_sbrk;
+ dh.sbrk2 = sbrk (0);
+ dh.puresize = PURESIZE;
+
+ /* Create new "saved data" dump file */
+ unlink (new);
+ fd = open (new, NEW_OPEN_FLAGS, 0666);
+ if (fd < 0)
+ report_file_error ("Opening dump file", Fcons (build_string (new), Qnil));
+
+ /* Delete obsolete shared segment. */
+ shmid = shmget (shmkey, 0, 0);
+ if (shmid != -1)
+ {
+ if (shmctl (shmid, IPC_RMID, 0) == 0)
+ fprintf (stderr, "Destroying existing shared segment\n");
+ }
+
+
+ /* Write saved header and data */
+ length = sizeof (dh);
+ if (write (fd, (char *)&dh, length) != length)
+ report_file_error ("Writing dump file header",
+ Fcons (build_string (new), Qnil));
+ length = dh.end - dh.start;
+ if (write (fd, dh.start, length) != length)
+ report_file_error ("Writing low core in dump file",
+ Fcons (build_string (new), Qnil));
+ length = dh.sbrk2 - dh.sbrk1;
+ if (write (fd, dh.sbrk1, length) != length)
+ report_file_error ("Writing heap in dump file",
+ Fcons (build_string (new), Qnil));
+ length = PURESIZE;
+ if (write (fd, PURE_SEG_BITS, length) != length)
+ report_file_error ("Writing pure data in dump file",
+ Fcons (build_string (new), Qnil));
+ close (fd);
+}
diff --git a/src/vlimit.h b/src/vlimit.h
new file mode 100644
index 00000000000..c347dc74df6
--- /dev/null
+++ b/src/vlimit.h
@@ -0,0 +1,2 @@
+/* Dummy for Emacs so that we can run on VMS... */
+#define LIM_DATA 0
diff --git a/src/vms-pp.c b/src/vms-pp.c
index fdfcd9c46a1..88ac75d4de5 100644
--- a/src/vms-pp.c
+++ b/src/vms-pp.c
@@ -2,7 +2,7 @@
* compiled on VMS without warnings.
* Copyright (C) 1986 Free Software Foundation, Inc.
- This file is part of GNU Emacs.
+This file is part of GNU Emacs.
GNU Emacs is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -16,7 +16,7 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Usage:
diff --git a/src/vms-pp.trans b/src/vms-pp.trans
new file mode 100644
index 00000000000..cab69d7da07
--- /dev/null
+++ b/src/vms-pp.trans
@@ -0,0 +1,10 @@
+! translations for extra long variable names
+!234567890123456789012345678901 1234567890123456789012345678901
+Vminibuffer_local_completion_map Vminibuf_local_completion_map
+Vminibuffer_local_must_match_map Vminibuf_local_must_match
+Finsert_abbrev_table_description Finsert_abbrev_table_descrip
+Sinsert_abbrev_table_description Sinsert_abbrev_table_descrip
+internal_with_output_to_temp_buffer internal_with_out_to_temp_buf
+Vminibuffer_completion_predicate Vminibuf_completion_predicate
+Qminibuffer_completion_predicate Qminibuf_completion_predicate
+
diff --git a/src/vms-pwd.h b/src/vms-pwd.h
new file mode 100644
index 00000000000..6c29197a47a
--- /dev/null
+++ b/src/vms-pwd.h
@@ -0,0 +1,34 @@
+/* GNU Emacs password definition file.
+ Copyright (C) 1986 Free Software Foundation.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifdef VMS
+/* On VMS, we read the UAF file and emulate some of the necessary
+ fields for Emacs. */
+#include "uaf.h"
+
+struct passwd {
+ char pw_name[UAF$S_USERNAME+1];
+ char pw_passwd[UAF$S_PWD];
+ short pw_uid;
+ short pw_gid;
+ char pw_gecos[UAF$S_OWNER+1];
+ char pw_dir[UAF$S_DEFDEV+UAF$S_DEFDIR+1];
+ char pw_shell[UAF$S_DEFCLI+1];
+};
+#endif /* VMS */
diff --git a/src/vmsfns.c b/src/vmsfns.c
index 512ab21679a..07b7b0491bb 100644
--- a/src/vmsfns.c
+++ b/src/vmsfns.c
@@ -64,21 +64,36 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <descrip.h>
#include <dvidef.h>
#include <prvdef.h>
-/* #include <clidef.h> */
+#include <clidef.h>
#include <iodef.h>
#include <ssdef.h>
#include <errno.h>
+/* GCC does not carry this header file. Doesn't matter, we define the symbol
+ we need below, if not already defined. */
+#ifndef __GNUC__
+#include <syidef.h>
+#endif
+
#ifdef VMS4_4 /* I am being cautious; perhaps this exists in older versions */
#include <jpidef.h>
#endif
-/* #include <syidef.h> */
-
+#ifndef CLI$M_NOWAIT
#define CLI$M_NOWAIT 1 /* clidef.h is missing from C library */
+#endif
+
+#ifndef SYI$_VERSION
#define SYI$_VERSION 4096 /* syidef.h is missing from C library */
+#endif
+
+#ifndef JPI$_CLINAME
#define JPI$_CLINAME 522 /* JPI$_CLINAME is missing from jpidef.h */
+#endif
+
+#ifndef JPI$_MASTER_PID
#define JPI$_MASTER_PID 805 /* JPI$_MASTER_PID missing from jpidef.h */
+#endif
#define LIB$_NOSUCHSYM 1409892 /* libclidef.h missing */
#define MSGSIZE 160 /* Maximum size for mailbox operations */
@@ -274,12 +289,12 @@ DEFUN ("default-subprocess-input-handler",
Lisp_Object name, input;
{
/* Just insert in current buffer */
- insert1 (input);
+ insert (XSTRING (input)->data, XSTRING (input)->size);
insert ("\n", 1);
}
DEFUN ("spawn-subprocess", Fspawn_subprocess, Sspawn_subprocess, 1, 3, 0,
- "Spawn an asynchronous VMS suprocess for command processing.")
+ "Spawns an asynchronous VMS suprocess for command processing.")
(name, input_handler, exit_handler)
Lisp_Object name, input_handler, exit_handler;
{
@@ -287,6 +302,7 @@ DEFUN ("spawn-subprocess", Fspawn_subprocess, Sspawn_subprocess, 1, 3, 0,
char output_mbx_name[20];
struct dsc$descriptor_s output_mbx_dsc;
struct process_list *ptr, *p, *prev;
+ static int dummy = CLI$M_NOWAIT;
CHECK_NUMBER (name, 0);
if (! input_mbx_chan)
@@ -321,7 +337,8 @@ DEFUN ("spawn-subprocess", Fspawn_subprocess, Sspawn_subprocess, 1, 3, 0,
ptr = next;
}
if (! ptr)
- ptr = xmalloc (sizeof (struct process_list));
+ ptr = (struct process_list *) xmalloc (sizeof (struct process_list));
+
if (! create_mbx (&output_mbx_dsc, output_mbx_name, &ptr->mbx_chan, 2))
{
free (ptr);
@@ -332,7 +349,7 @@ DEFUN ("spawn-subprocess", Fspawn_subprocess, Sspawn_subprocess, 1, 3, 0,
ptr->input_handler = input_handler;
ptr->exit_handler = exit_handler;
message ("Creating subprocess...");
- status = lib$spawn (0, &output_mbx_dsc, &input_mbx_dsc, &CLI$M_NOWAIT, 0,
+ status = lib$spawn (0, &output_mbx_dsc, &input_mbx_dsc, &dummy, 0,
&ptr->process_id, 0, 0, exit_ast, &ptr->process_active);
if (! (status & 1))
{
@@ -516,6 +533,7 @@ create_mbx (dsc, buf, chan, buffer_factor)
{
int strval[2];
int status;
+ static int dummy = DVI$_DEVNAM;
status = sys$crembx (0, chan, MSGSIZE, MSGSIZE * buffer_factor, 0, 0, 0);
if (! (status & 1))
@@ -524,8 +542,8 @@ create_mbx (dsc, buf, chan, buffer_factor)
return 0;
}
strval[0] = 16;
- strval[1] = buf;
- status = lib$getdvi (&DVI$_DEVNAM, chan, 0, 0, strval,
+ strval[1] = (int) buf;
+ status = lib$getdvi (&dummy, chan, 0, 0, strval,
&dsc->dsc$w_length);
if (! (status & 1))
return 0;
@@ -578,7 +596,7 @@ or nil depending upon whether the privilege is already enabled.")
Lisp_Object priv, value, getprv;
{
int prvmask[2], prvlen, newmask[2];
- char * prvname;
+ unsigned char * prvname;
int found, i;
struct privilege_list * ptr;
@@ -650,7 +668,7 @@ These are the possibilities for the first arg (upper or lower case ok):\n\
Lisp_Object type, arg1, arg2;
{
int i, typelen;
- char * typename;
+ unsigned char * typename;
struct vms_objlist * ptr;
CHECK_STRING (type, 0);
@@ -676,8 +694,9 @@ translate_id (pid, owner)
* flag is 0, return self. */
{
int status, code, id, i, numeric, size;
- char * p;
+ unsigned char * p;
int prcnam[2];
+ static int dummy = JPI$_PID;
if (NULL (pid)
|| XTYPE (pid) == Lisp_String && XSTRING (pid)->size == 0
@@ -716,8 +735,8 @@ translate_id (pid, owner)
if (numeric)
return (id);
prcnam[0] = XSTRING (pid)->size;
- prcnam[1] = XSTRING (pid)->data;
- status = lib$getjpi (&JPI$_PID, 0, prcnam, &id);
+ prcnam[1] = (int) XSTRING (pid)->data;
+ status = lib$getjpi (&dummy, 0, prcnam, &id);
if (! (status & 1))
error ("Cannot find process id: %s",
vmserrstr (status));
@@ -734,7 +753,7 @@ getjpi (jpicode, arg, numeric)
{
int id, status, numval;
char str[128];
- int strdsc[2] = { sizeof (str), str };
+ int strdsc[2] = { sizeof (str), (int) str };
short strlen;
id = translate_id (arg, 0);
@@ -835,12 +854,13 @@ static Lisp_Object
vms_version_fn (arg1, arg2)
Lisp_Object arg1, arg2;
{
- char str[40];
+ char str[256]; /* Max logical translation is 255 bytes. */
int status;
- int strdsc[2] = { sizeof (str), str };
+ int strdsc[2] = { sizeof (str), (int) str };
short strlen;
+ static int dummy = SYI$_VERSION;
- status = lib$getsyi (&SYI$_VERSION, 0, strdsc, &strlen, 0, 0);
+ status = lib$getsyi (&dummy, 0, strdsc, &strlen, 0, 0);
if (! (status & 1))
error ("Unable to obtain version: %s", vmserrstr (status));
return (make_string (str, strlen));
@@ -850,14 +870,14 @@ static Lisp_Object
vms_trnlog (arg1, arg2)
Lisp_Object arg1, arg2;
{
- char str[256]; /* Max logical translation is 255 bytes. */
+ char str[1025]; /* Max symbol translation is 1024 bytes. */
int status, symdsc[2];
- int strdsc[2] = { sizeof (str), str };
+ int strdsc[2] = { sizeof (str), (int) str };
short length, level;
CHECK_STRING (arg1, 0);
symdsc[0] = XSTRING (arg1)->size;
- symdsc[1] = XSTRING (arg1)->data;
+ symdsc[1] = (int) XSTRING (arg1)->data;
status = lib$sys_trnlog (symdsc, &length, strdsc);
if (! (status & 1))
error ("Unable to translate logical name: %s", vmserrstr (status));
@@ -870,14 +890,14 @@ static Lisp_Object
vms_symbol (arg1, arg2)
Lisp_Object arg1, arg2;
{
- char str[1025]; /* Max symbol translation is 1024 bytes. */
+ char str[100];
int status, symdsc[2];
- int strdsc[2] = { sizeof (str), str };
+ int strdsc[2] = { sizeof (str), (int) str };
short length, level;
CHECK_STRING (arg1, 0);
symdsc[0] = XSTRING (arg1)->size;
- symdsc[1] = XSTRING (arg1)->data;
+ symdsc[1] = (int) XSTRING (arg1)->data;
status = lib$get_symbol (symdsc, strdsc, &length, &level);
if (! (status & 1)) {
if (status == LIB$_NOSUCHSYM)
@@ -894,12 +914,13 @@ vms_proclist (arg1, arg2)
{
Lisp_Object retval;
int id, status, pid;
+ static int dummy = JPI$_PID;
retval = Qnil;
pid = -1;
for (;;)
{
- status = lib$getjpi (&JPI$_PID, &pid, 0, &id);
+ status = lib$getjpi (&dummy, &pid, 0, &id);
if (status == SS$_NOMOREPROC)
break;
if (! (status & 1))
diff --git a/src/vmsmap.c b/src/vmsmap.c
new file mode 100644
index 00000000000..6b768354277
--- /dev/null
+++ b/src/vmsmap.c
@@ -0,0 +1,235 @@
+/* VMS mapping of data and alloc arena for GNU Emacs.
+ Copyright (C) 1986, 1987 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Written by Mukesh Prasad. */
+
+#ifdef VMS
+
+#include "config.h"
+#include "lisp.h"
+#include <rab.h>
+#include <fab.h>
+#include <rmsdef.h>
+#include <secdef.h>
+
+/* RMS block size */
+#define BLOCKSIZE 512
+
+/* Maximum number of bytes to be written in one RMS write.
+ * Must be a multiple of BLOCKSIZE.
+ */
+#define MAXWRITE (BLOCKSIZE * 30)
+
+/* This funniness is to ensure that sdata occurs alphabetically BEFORE the
+ $DATA psect and that edata occurs after ALL Emacs psects. This is
+ because the VMS linker sorts all psects in a cluster alphabetically
+ during the linking, unless you use the cluster_psect command. Emacs
+ uses the cluster command to group all Emacs psects into one cluster;
+ this keeps the dumped data separate from any loaded libraries. */
+
+#ifdef __GNUC__
+/* We need a large sdata array because otherwise the impure storage will end up
+ in low memory, and this will screw up garbage collection (Emacs will not
+ be able to tell the difference between a string length and an address).
+ This array guarantees that the impure storage is at a sufficiently high
+ address so that this problem will not occur. */
+char sdata[8192] asm("_$$PsectAttributes_NOOVR$$$D$ATA") ;
+char edata[512] asm("_$$PsectAttributes_NOOVR$$__DATA") ;
+#else
+globaldef {"$D$ATA"} char sdata[512]; /* Start of saved data area */
+globaldef {"__DATA"} char edata[512]; /* End of saved data area */
+#endif
+
+/* Structure to write into first block of map file.
+ */
+
+struct map_data
+{
+ char * sdata; /* Start of data area */
+ char * edata; /* End of data area */
+ int datablk; /* Block in file to map data area from/to */
+};
+
+static void fill_fab (), fill_rab ();
+static int write_data ();
+
+extern char *start_of_data ();
+extern int vms_out_initial; /* Defined in malloc.c */
+
+/* Maps in the data and alloc area from the map file.
+ */
+
+int
+mapin_data (name)
+ char * name;
+{
+ struct FAB fab;
+ struct RAB rab;
+ int status, size;
+ int inadr[2];
+ struct map_data map_data;
+
+
+ /* Open map file. */
+ fab = cc$rms_fab;
+ fab.fab$b_fac = FAB$M_BIO|FAB$M_GET;
+ fab.fab$l_fna = name;
+ fab.fab$b_fns = strlen (name);
+ status = sys$open (&fab);
+ if (status != RMS$_NORMAL)
+ {
+ printf ("Map file not available, running bare Emacs....\n");
+ return 0; /* Map file not available */
+ }
+ /* Connect the RAB block */
+ rab = cc$rms_rab;
+ rab.rab$l_fab = &fab;
+ rab.rab$b_rac = RAB$C_SEQ;
+ rab.rab$l_rop = RAB$M_BIO;
+ status = sys$connect (&rab);
+ if (status != RMS$_NORMAL)
+ lib$stop (status);
+ /* Read the header data */
+ rab.rab$l_ubf = (char *) &map_data;
+ rab.rab$w_usz = sizeof (map_data);
+ rab.rab$l_bkt = 0;
+ status = sys$read (&rab);
+ if (status != RMS$_NORMAL)
+ lib$stop (status);
+ status = sys$close (&fab);
+ if (status != RMS$_NORMAL)
+ lib$stop (status);
+ if (map_data.sdata != start_of_data ())
+ {
+ printf ("Start of data area has moved: cannot map in data.\n");
+ return 0;
+ }
+ if (map_data.edata != edata)
+ {
+ printf ("End of data area has moved: cannot map in data.\n");
+ return 0;
+ }
+ fab.fab$l_fop |= FAB$M_UFO;
+ status = sys$open (&fab);
+ if (status != RMS$_NORMAL)
+ lib$stop (status);
+ /* Map data area. */
+ inadr[0] = (int) map_data.sdata;
+ inadr[1] = (int) map_data.edata;
+ status = sys$crmpsc (inadr, 0, 0, SEC$M_CRF | SEC$M_WRT, 0, 0, 0,
+ fab.fab$l_stv, 0, map_data.datablk, 0, 0);
+ if (! (status & 1))
+ lib$stop (status);
+}
+
+/* Writes the data and alloc area to the map file.
+ */
+mapout_data (into)
+ char * into;
+{
+ struct FAB fab;
+ struct RAB rab;
+ int status;
+ struct map_data map_data;
+ int datasize, msize;
+
+ if (vms_out_initial)
+ {
+ error ("Out of initial allocation. Must rebuild emacs with more memory (VMS_ALLOCATION_SIZE).");
+ return 0;
+ }
+ map_data.sdata = start_of_data ();
+ map_data.edata = edata;
+ datasize = map_data.edata - map_data.sdata + 1;
+ map_data.datablk = 2 + (sizeof (map_data) + BLOCKSIZE - 1) / BLOCKSIZE;
+ /* Create map file. */
+ fab = cc$rms_fab;
+ fab.fab$b_fac = FAB$M_BIO|FAB$M_PUT;
+ fab.fab$l_fna = into;
+ fab.fab$b_fns = strlen (into);
+ fab.fab$l_fop = FAB$M_CBT;
+ fab.fab$b_org = FAB$C_SEQ;
+ fab.fab$b_rat = 0;
+ fab.fab$b_rfm = FAB$C_VAR;
+ fab.fab$l_alq = 1 + map_data.datablk +
+ ((datasize + BLOCKSIZE - 1) / BLOCKSIZE);
+ status = sys$create (&fab);
+ if (status != RMS$_NORMAL)
+ {
+ error ("Could not create map file");
+ return 0;
+ }
+ /* Connect the RAB block */
+ rab = cc$rms_rab;
+ rab.rab$l_fab = &fab;
+ rab.rab$b_rac = RAB$C_SEQ;
+ rab.rab$l_rop = RAB$M_BIO;
+ status = sys$connect (&rab);
+ if (status != RMS$_NORMAL)
+ {
+ error ("RMS connect to map file failed");
+ return 0;
+ }
+ /* Write the header */
+ rab.rab$l_rbf = (char *) &map_data;
+ rab.rab$w_rsz = sizeof (map_data);
+ status = sys$write (&rab);
+ if (status != RMS$_NORMAL)
+ {
+ error ("RMS write (header) to map file failed");
+ return 0;
+ }
+ if (! write_data (&rab, map_data.datablk, map_data.sdata, datasize))
+ return 0;
+ status = sys$close (&fab);
+ if (status != RMS$_NORMAL)
+ {
+ error ("RMS close on map file failed");
+ return 0;
+ }
+ return 1;
+}
+
+static int
+write_data (rab, firstblock, data, length)
+ struct RAB * rab;
+ char * data;
+{
+ int status;
+
+ rab->rab$l_bkt = firstblock;
+ while (length > 0)
+ {
+ rab->rab$l_rbf = data;
+ rab->rab$w_rsz = length > MAXWRITE ? MAXWRITE : length;
+ status = sys$write (rab, 0, 0);
+ if (status != RMS$_NORMAL)
+ {
+ error ("RMS write to map file failed");
+ return 0;
+ }
+ data = &data[MAXWRITE];
+ length -= MAXWRITE;
+ rab->rab$l_bkt = 0;
+ }
+ return 1;
+} /* write_data */
+
+#endif /* VMS */
+
diff --git a/src/vmspaths.h b/src/vmspaths.h
new file mode 100644
index 00000000000..ac16c07b0d0
--- /dev/null
+++ b/src/vmspaths.h
@@ -0,0 +1,15 @@
+/* the default search path for Lisp function "load" */
+#define PATH_LOADSEARCH "EMACS_LIBRARY:[LISP]"
+
+/* the extra search path for programs to invoke.
+ This is appended to whatever the PATH environment variable says. */
+#define PATH_EXEC "EMACS_LIBRARY:[ETC]"
+
+/* the name of the directory that contains lock files
+ with which we record what files are being modified in Emacs.
+ This directory should be writable by everyone. */
+#define PATH_LOCK "EMACS_LIBRARY:[LOCK]"
+
+/* the name of the file !!!SuperLock!!! in the directory
+ specified by PATH_LOCK. Yes, this is redundant. */
+#define PATH_SUPERLOCK "EMACS_LIBRARY:[LOCK]$$$SUPERLOCK$$$."
diff --git a/src/vmsproc.c b/src/vmsproc.c
deleted file mode 100644
index ec9678f78a4..00000000000
--- a/src/vmsproc.c
+++ /dev/null
@@ -1,784 +0,0 @@
-/* Interfaces to subprocesses on VMS.
- Copyright (C) 1988 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 1, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-
-/*
- Event flag and `select' emulation
-
- 0 is never used
- 1 is the terminal
- 23 is the timer event flag
- 24-31 are reserved by VMS
-*/
-#include <ssdef.h>
-#include <iodef.h>
-#include <dvidef.h>
-#include <clidef.h>
-#include "vmsproc.h"
-
-#define KEYBOARD_EVENT_FLAG 1
-#define TIMER_EVENT_FLAG 23
-
-static VMS_PROC_STUFF procList[MAX_EVENT_FLAGS+1];
-
-get_kbd_event_flag ()
-{
- /*
- Return the first event flag for keyboard input.
- */
- VMS_PROC_STUFF *vs = &procList[KEYBOARD_EVENT_FLAG];
-
- vs->busy = 1;
- vs->pid = 0;
- return (vs->eventFlag);
-}
-
-get_timer_event_flag ()
-{
- /*
- Return the last event flag for use by timeouts
- */
- VMS_PROC_STUFF *vs = &procList[TIMER_EVENT_FLAG];
-
- vs->busy = 1;
- vs->pid = 0;
- return (vs->eventFlag);
-}
-
-VMS_PROC_STUFF *
-get_vms_process_stuff ()
-{
- /*
- Return a process_stuff structure
-
- We use 1-23 as our event flags to simplify implementing
- a VMS `select' call.
- */
- int i;
- VMS_PROC_STUFF *vs;
-
- for (i=1, vs = procList; i<MAX_EVENT_FLAGS; i++, vs++)
- {
- if (!vs->busy)
- {
- vs->busy = 1;
- vs->inputChan = 0;
- vs->pid = 0;
- sys$clref (vs->eventFlag);
- return (vs);
- }
- }
- return ((VMS_PROC_STUFF *)0);
-}
-
-give_back_vms_process_stuff (vs)
- VMS_PROC_STUFF *vs;
-{
- /*
- Return an event flag to our pool
- */
- vs->busy = 0;
- vs->inputChan = 0;
- vs->pid = 0;
-}
-
-VMS_PROC_STUFF *
-get_vms_process_pointer (pid)
- int pid;
-{
- /*
- Given a pid, return the VMS_STUFF pointer
- */
- int i;
- VMS_PROC_STUFF *vs;
-
- /* Don't search the last one */
- for (i=0, vs=procList; i<MAX_EVENT_FLAGS; i++, vs++)
- {
- if (vs->busy && vs->pid == pid)
- return (vs);
- }
- return ((VMS_PROC_STUFF *)0);
-}
-
-start_vms_process_read (vs)
- VMS_PROC_STUFF *vs;
-{
- /*
- Start an asynchronous read on a VMS process
- We will catch up with the output sooner or later
- */
- int status;
- int ProcAst ();
-
- status = sys$qio (vs->eventFlag, vs->outputChan, IO$_READVBLK,
- vs->iosb, 0, vs,
- vs->inputBuffer, sizeof (vs->inputBuffer), 0, 0, 0, 0);
- if (status != SS$_NORMAL)
- return (0);
- else
- return (1);
-}
-
-extern int waiting_for_ast; /* in sysdep.c */
-extern int timer_ef;
-extern int input_ef;
-
-select (nDesc, rdsc, wdsc, edsc, timeOut)
- int nDesc;
- int *rdsc;
- int *wdsc;
- int *edsc;
- int *timeOut;
-{
- /* Emulate a select call
-
- We know that we only use event flags 1-23
-
- timeout == 100000 & bit 0 set means wait on keyboard input until
- something shows up. If timeout == 0, we just read the event
- flags and return what we find. */
-
- int nfds = 0;
- int status;
- int time[2];
- int delta = -10000000;
- int zero = 0;
- int timeout = *timeOut;
- unsigned long mask, readMask, waitMask;
-
- if (rdsc)
- readMask = *rdsc << 1; /* Unix mask is shifted over 1 */
- else
- readMask = 0; /* Must be a wait call */
-
- sys$clref (KEYBOARD_EVENT_FLAG);
- sys$setast (0); /* Block interrupts */
- sys$readef (KEYBOARD_EVENT_FLAG, &mask); /* See what is set */
- mask &= readMask; /* Just examine what we need */
- if (mask == 0)
- { /* Nothing set, we must wait */
- if (timeout != 0)
- { /* Not just inspecting... */
- if (!(timeout == 100000 &&
- readMask == (1 << KEYBOARD_EVENT_FLAG)))
- {
- lib$emul (&timeout, &delta, &zero, time);
- sys$setimr (TIMER_EVENT_FLAG, time, 0, 1);
- waitMask = readMask | (1 << TIMER_EVENT_FLAG);
- }
- else
- waitMask = readMask;
- if (waitMask & (1 << KEYBOARD_EVENT_FLAG))
- {
- sys$clref (KEYBOARD_EVENT_FLAG);
- waiting_for_ast = 1; /* Only if reading from 0 */
- }
- sys$setast (1);
- sys$wflor (KEYBOARD_EVENT_FLAG, waitMask);
- sys$cantim (1, 0);
- sys$readef (KEYBOARD_EVENT_FLAG, &mask);
- if (readMask & (1 << KEYBOARD_EVENT_FLAG))
- waiting_for_ast = 0;
- }
- }
- sys$setast (1);
-
- /*
- Count number of descriptors that are ready
- */
- mask &= readMask;
- if (rdsc)
- *rdsc = (mask >> 1); /* Back to Unix format */
- for (nfds = 0; mask; mask >>= 1)
- {
- if (mask & 1)
- nfds++;
- }
- return (nfds);
-}
-
-#define MAX_BUFF 1024
-
-write_to_vms_process (vs, buf, len)
- VMS_PROC_STUFF *vs;
- char *buf;
- int len;
-{
- /*
- Write something to a VMS process.
-
- We have to map newlines to carriage returns for VMS.
- */
- char ourBuff[MAX_BUFF];
- short iosb[4];
- int status;
- int in, out;
-
- while (len > 0)
- {
- out = map_nl_to_cr (buf, ourBuff, len, MAX_BUFF);
- status = sys$qiow (0, vs->inputChan, IO$_WRITEVBLK|IO$M_NOFORMAT,
- iosb, 0, 0, ourBuff, out, 0, 0, 0, 0);
- if (status != SS$_NORMAL || (status = iosb[0]) != SS$_NORMAL)
- {
- error ("Could not write to subprocess: %x", status);
- return (0);
- }
- len =- out;
- }
- return (1);
-}
-
-static
-map_nl_to_cr (in, out, maxIn, maxOut)
- char *in;
- char *out;
- int maxIn;
- int maxOut;
-{
- /*
- Copy `in' to `out' remapping `\n' to `\r'
- */
- int c;
- int o;
-
- for (o=0; maxIn-- > 0 && o < maxOut; o++)
- {
- c = *in++;
- *out++ = (c == '\n') ? '\r' : c;
- }
- return (o);
-}
-
-clean_vms_buffer (buf, len)
- char *buf;
- int len;
-{
- /*
- Sanitize output from a VMS subprocess
- Strip CR's and NULLs
- */
- char *oBuf = buf;
- char c;
- int l = 0;
-
- while (len-- > 0)
- {
- c = *buf++;
- if (c == '\r' || c == '\0')
- ;
- else
- {
- *oBuf++ = c;
- l++;
- }
- }
- return (l);
-}
-
-/*
- For the CMU PTY driver
-*/
-#define PTYNAME "PYA0:"
-
-get_pty_channel (inDevName, outDevName, inChannel, outChannel)
- char *inDevName;
- char *outDevName;
- int *inChannel;
- int *outChannel;
-{
- int PartnerUnitNumber;
- int status;
- struct {
- int l;
- char *a;
- } d;
- struct {
- short BufLen;
- short ItemCode;
- int *BufAddress;
- int *ItemLength;
- } g[2];
-
- d.l = strlen (PTYNAME);
- d.a = PTYNAME;
- *inChannel = 0; /* Should be `short' on VMS */
- *outChannel = 0;
- *inDevName = *outDevName = '\0';
- status = sys$assign (&d, inChannel, 0, 0);
- if (status == SS$_NORMAL)
- {
- *outChannel = *inChannel;
- g[0].BufLen = sizeof (PartnerUnitNumber);
- g[0].ItemCode = DVI$_UNIT;
- g[0].BufAddress = &PartnerUnitNumber;
- g[0].ItemLength = (int *)0;
- g[1].BufLen = g[1].ItemCode = 0;
- status = sys$getdviw (0, *inChannel, 0, &g, 0, 0, 0, 0);
- if (status == SS$_NORMAL)
- {
- sprintf (inDevName, "_TPA%d:", PartnerUnitNumber);
- strcpy (outDevName, inDevName);
- }
- }
- return (status);
-}
-
-VMSgetwd (buf)
- char *buf;
-{
- /*
- Return the current directory
- */
- char curdir[256];
- char *getenv ();
- char *s;
- short len;
- int status;
- struct
- {
- int l;
- char *a;
- } d;
-
- s = getenv ("SYS$DISK");
- if (s)
- strcpy (buf, s);
- else
- *buf = '\0';
-
- d.l = 255;
- d.a = curdir;
- status = sys$setddir (0, &len, &d);
- if (status & 1)
- {
- curdir[len] = '\0';
- strcat (buf, curdir);
- }
-}
-
-static
-call_process_ast (vs)
- VMS_PROC_STUFF *vs;
-{
- sys$setef (vs->eventFlag);
-}
-
-void
-child_setup (in, out, err, new_argv, env)
- int in, out, err;
- register char **new_argv;
- char **env;
-{
- /* ??? I suspect that maybe this shouldn't be done on VMS. */
-#ifdef subprocesses
- /* Close Emacs's descriptors that this process should not have. */
- close_process_descs ();
-#endif
-
- if (XTYPE (current_buffer->directory) == Lisp_String)
- chdir (XSTRING (current_buffer->directory)->data);
-}
-
-DEFUN ("call-process", Fcall_process, Scall_process, 1, MANY, 0,
- "Call PROGRAM synchronously in a separate process.\n\
-Program's input comes from file INFILE (nil means null device, `NLA0:').\n\
-Insert output in BUFFER before point; t means current buffer;\n\
- nil for BUFFER means discard it; 0 means discard and don't wait.\n\
-Fourth arg DISPLAY non-nil means redisplay buffer as output is inserted.\n\
-Remaining arguments are strings passed as command arguments to PROGRAM.\n\
-This function waits for PROGRAM to terminate, unless BUFFER is 0;\n\
-if you quit, the process is killed.")
- (nargs, args)
- int nargs;
- register Lisp_Object *args;
-{
- Lisp_Object display, buffer, path;
- char oldDir[512];
- int inchannel, outchannel;
- int len;
- int call_process_ast ();
- struct
- {
- int l;
- char *a;
- } dcmd, din, dout;
- char inDevName[65];
- char outDevName[65];
- short iosb[4];
- int status;
- int SpawnFlags = CLI$M_NOWAIT;
- VMS_PROC_STUFF *vs;
- VMS_PROC_STUFF *get_vms_process_stuff ();
- int fd[2];
- int filefd;
- register int pid;
- char buf[1024];
- int count = specpdl_ptr - specpdl;
- register unsigned char **new_argv;
- struct buffer *old = current_buffer;
-
- CHECK_STRING (args[0], 0);
-
- if (nargs <= 1 || NULL (args[1]))
- args[1] = build_string ("NLA0:");
- else
- args[1] = Fexpand_file_name (args[1], current_buffer->directory);
-
- CHECK_STRING (args[1], 1);
-
- {
- register Lisp_Object tem;
- buffer = tem = args[2];
- if (nargs <= 2)
- buffer = Qnil;
- else if (!(EQ (tem, Qnil) || EQ (tem, Qt)
- || XFASTINT (tem) == 0))
- {
- buffer = Fget_buffer (tem);
- CHECK_BUFFER (buffer, 2);
- }
- }
-
- display = nargs >= 3 ? args[3] : Qnil;
-
- {
- /*
- if (args[0] == "*dcl*" then we need to skip pas the "-c",
- else args[0] is the program to run.
- */
- register int i;
- int arg0;
- int firstArg;
-
- if (strcmp (XSTRING (args[0])->data, "*dcl*") == 0)
- {
- arg0 = 5;
- firstArg = 6;
- }
- else
- {
- arg0 = 0;
- firstArg = 4;
- }
- len = XSTRING (args[arg0])->size + 1;
- for (i = firstArg; i < nargs; i++)
- {
- CHECK_STRING (args[i], i);
- len += XSTRING (args[i])->size + 1;
- }
- new_argv = alloca (len);
- strcpy (new_argv, XSTRING (args[arg0])->data);
- for (i = firstArg; i < nargs; i++)
- {
- strcat (new_argv, " ");
- strcat (new_argv, XSTRING (args[i])->data);
- }
- dcmd.l = len-1;
- dcmd.a = new_argv;
-
- status = get_pty_channel (inDevName, outDevName, &inchannel, &outchannel);
- if (!(status & 1))
- error ("Error getting PTY channel: %x", status);
- if (XTYPE (buffer) == Lisp_Int)
- {
- dout.l = strlen ("NLA0:");
- dout.a = "NLA0:";
- }
- else
- {
- dout.l = strlen (outDevName);
- dout.a = outDevName;
- }
-
- vs = get_vms_process_stuff ();
- if (!vs)
- {
- sys$dassgn (inchannel);
- sys$dassgn (outchannel);
- error ("Too many VMS processes");
- }
- vs->inputChan = inchannel;
- vs->outputChan = outchannel;
- }
-
- filefd = open (XSTRING (args[1])->data, O_RDONLY, 0);
- if (filefd < 0)
- {
- sys$dassgn (inchannel);
- sys$dassgn (outchannel);
- give_back_vms_process_stuff (vs);
- report_file_error ("Opening process input file", Fcons (args[1], Qnil));
- }
- else
- close (filefd);
-
- din.l = XSTRING (args[1])->size;
- din.a = XSTRING (args[1])->data;
-
- /*
- Start a read on the process channel
- */
- if (XTYPE (buffer) != Lisp_Int)
- {
- start_vms_process_read (vs);
- SpawnFlags = CLI$M_NOWAIT;
- }
- else
- SpawnFlags = 0;
-
- /*
- On VMS we need to change the current directory
- of the parent process before forking so that
- the child inherit that directory. We remember
- where we were before changing.
- */
- VMSgetwd (oldDir);
- child_setup (0, 0, 0, 0, 0);
- status = lib$spawn (&dcmd, &din, &dout, &SpawnFlags, 0, &vs->pid,
- &vs->exitStatus, 0, call_process_ast, vs);
- chdir (oldDir);
-
- if (status != SS$_NORMAL)
- {
- sys$dassgn (inchannel);
- sys$dassgn (outchannel);
- give_back_vms_process_stuff (vs);
- error ("Error calling LIB$SPAWN: %x", status);
- }
- pid = vs->pid;
-
- if (XTYPE (buffer) == Lisp_Int)
- {
-#ifndef subprocesses
- wait_without_blocking ();
-#endif subprocesses
- return Qnil;
- }
-
- record_unwind_protect (call_process_cleanup,
- Fcons (make_number (fd[0]), make_number (pid)));
-
-
- if (XTYPE (buffer) == Lisp_Buffer)
- Fset_buffer (buffer);
-
- immediate_quit = 1;
- QUIT;
-
- while (1)
- {
- sys$waitfr (vs->eventFlag);
- if (vs->iosb[0] & 1)
- {
- immediate_quit = 0;
- if (!NULL (buffer))
- {
- vs->iosb[1] = clean_vms_buffer (vs->inputBuffer, vs->iosb[1]);
- InsCStr (vs->inputBuffer, vs->iosb[1]);
- }
- if (!NULL (display) && INTERACTIVE)
- redisplay_preserve_echo_area ();
- immediate_quit = 1;
- QUIT;
- if (!start_vms_process_read (vs))
- break; /* The other side went away */
- }
- else
- break;
- }
- sys$dassgn (inchannel);
- sys$dassgn (outchannel);
- give_back_vms_process_stuff (vs);
-
- /* Wait for it to terminate, unless it already has. */
- wait_for_termination (pid);
-
- immediate_quit = 0;
-
- set_current_buffer (old);
-
- return unbind_to (count, Qnil);
-}
-
-create_process (process, new_argv)
- Lisp_Object process;
- char *new_argv;
-{
- int pid, inchannel, outchannel, forkin, forkout;
- char old_dir[512];
- char in_dev_name[65];
- char out_dev_name[65];
- short iosb[4];
- int status;
- int spawn_flags = CLI$M_NOWAIT;
- int child_sig ();
- struct {
- int l;
- char *a;
- } din, dout, dprompt, dcmd;
- VMS_PROC_STUFF *vs;
- VMS_PROC_STUFF *get_vms_process_stuff ();
-
- status = get_pty_channel (in_dev_name, out_dev_name, &inchannel, &outchannel);
- if (!(status & 1))
- {
- remove_process (process);
- error ("Error getting PTY channel: %x", status);
- }
- dout.l = strlen (out_dev_name);
- dout.a = out_dev_name;
- dprompt.l = strlen (DCL_PROMPT);
- dprompt.a = DCL_PROMPT;
-
- if (strcmp (new_argv, "*dcl*") == 0)
- {
- din.l = strlen (in_dev_name);
- din.a = in_dev_name;
- dcmd.l = 0;
- dcmd.a = (char *)0;
- }
- else
- {
- din.l = strlen ("NLA0:");
- din.a = "NLA0:";
- dcmd.l = strlen (new_argv);
- dcmd.a = new_argv;
- }
-
- /* Delay interrupts until we have a chance to store
- the new fork's pid in its process structure */
- sys$setast (0);
-
- vs = get_vms_process_stuff ();
- if (vs == 0)
- {
- sys$setast (1);
- remove_process (process);
- error ("Too many VMS processes");
- }
- vs->inputChan = inchannel;
- vs->outputChan = outchannel;
-
- /* Start a read on the process channel */
- start_vms_process_read (vs);
-
- /* Switch current directory so that the child inherits it. */
- VMSgetwd (old_dir);
- child_setup (0, 0, 0, 0, 0);
-
- status = lib$spawn (&dcmd, &din, &dout, &spawn_flags, 0, &vs->pid,
- &vs->exitStatus, 0, child_sig, vs, &dprompt);
- chdir (old_dir);
-
- if (status != SS$_NORMAL)
- {
- sys$setast (1);
- remove_process (process);
- error ("Error calling LIB$SPAWN: %x", status);
- }
- vs->pid &= 0xffff; /* It needs to fit in a FASTINT,
- we don't need the rest of the bits */
- pid = vs->pid;
-
- /*
- ON VMS process->infd holds the (event flag-1)
- that we use for doing I/O on that process.
- `input_wait_mask' is the cluster of event flags
- we can wait on.
-
- Event flags returned start at 1 for the keyboard.
- Since Unix expects descriptor 0 for the keyboard,
- we substract one from the event flag.
- */
- inchannel = vs->eventFlag-1;
-
- /* Record this as an active process, with its channels.
- As a result, child_setup will close Emacs's side of the pipes. */
- chan_process[inchannel] = process;
- XFASTINT (XPROCESS (process)->infd) = inchannel;
- XFASTINT (XPROCESS (process)->outfd) = outchannel;
- XFASTINT (XPROCESS (process)->flags) = RUNNING;
-
- /* Delay interrupts until we have a chance to store
- the new fork's pid in its process structure */
-
-#define NO_ECHO "set term/noecho\r"
- sys$setast (0);
- /*
- Send a command to the process to not echo input
-
- The CMU PTY driver does not support SETMODEs.
- */
- write_to_vms_process (vs, NO_ECHO, strlen (NO_ECHO));
-
- XFASTINT (XPROCESS (process)->pid) = pid;
- sys$setast (1);
-}
-
-child_sig (vs)
- VMS_PROC_STUFF *vs;
-{
- register int pid;
- Lisp_Object tail, proc;
- register struct Lisp_Process *p;
- int old_errno = errno;
-
- pid = vs->pid;
- sys$setef (vs->eventFlag);
-
- for (tail = Vprocess_alist; XSYMBOL (tail) != XSYMBOL (Qnil); tail = XCONS (tail)->cdr)
- {
- proc = XCONS (XCONS (tail)->car)->cdr;
- p = XPROCESS (proc);
- if (EQ (p->childp, Qt) && XFASTINT (p->pid) == pid)
- break;
- }
-
- if (XSYMBOL (tail) == XSYMBOL (Qnil))
- return;
-
- child_changed++;
- XFASTINT (p->flags) = EXITED | CHANGED;
- /* Truncate the exit status to 24 bits so that it fits in a FASTINT */
- XFASTINT (p->reason) = (vs->exitStatus) & 0xffffff;
-}
-
-syms_of_vmsproc ()
-{
- defsubr (&Scall_process);
-}
-
-init_vmsproc ()
-{
- char *malloc ();
- int i;
- VMS_PROC_STUFF *vs;
-
- for (vs=procList, i=0; i<MAX_EVENT_FLAGS+1; i++, vs++)
- {
- vs->busy = 0;
- vs->eventFlag = i;
- sys$clref (i);
- vs->inputChan = 0;
- vs->pid = 0;
- }
- procList[0].busy = 1; /* Zero is reserved */
-}
diff --git a/src/window.c b/src/window.c
new file mode 100644
index 00000000000..eb21b89292d
--- /dev/null
+++ b/src/window.c
@@ -0,0 +1,2063 @@
+/* Window creation, deletion and examination for GNU Emacs.
+ Does not include redisplay.
+ Copyright (C) 1985, 1986, 1987, 1990 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#include "config.h"
+#include "lisp.h"
+#include "buffer.h"
+#include "window.h"
+#include "commands.h"
+#include "indent.h"
+#include "termchar.h"
+
+Lisp_Object Qwindowp;
+
+Lisp_Object Fnext_window (), Fdelete_window (), Fselect_window ();
+Lisp_Object Fset_window_buffer (), Fsplit_window (), Frecenter ();
+
+static void replace_window (), unshow_buffer ();
+static int save_window_save ();
+
+extern int minibuf_prompt_width;
+
+/* This is the window which displays the minibuffer.
+It is always the same window. */
+
+Lisp_Object minibuf_window;
+
+/* This is the window in which the terminal's cursor should
+ be left when nothing is being done with it. This must
+ always be a leaf window, and its buffer is selected by
+ the top level editing loop at the end of each command. */
+
+Lisp_Object selected_window;
+
+/* Non-nil means it is the window for C-M-v to scroll
+ when the minibuffer is selected. */
+
+Lisp_Object Vminibuf_scroll_window;
+
+/* Non-nil means it's function to call to display temp buffers. */
+
+Lisp_Object Vtemp_buffer_show_hook;
+
+/* If a window gets smaller than either of these, it is removed. */
+
+int window_min_height;
+int window_min_width;
+
+/* Nonzero implies pop_to_buffer should create windows. */
+
+int pop_up_windows;
+
+/* display-buffer always splits the largest window
+ if that window is more than this high */
+
+int split_height_threshold;
+
+/* Number of lines of continuity in scrolling by screenfuls. */
+
+int next_screen_context_lines;
+
+/* Incremented for each window created. */
+
+static int sequence_number;
+
+DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0,
+ "Returns t if OBJ is a window.")
+ (obj)
+ Lisp_Object obj;
+{
+ return XTYPE (obj) == Lisp_Window ? Qt : Qnil;
+}
+
+static Lisp_Object
+make_window ()
+{
+ register Lisp_Object val;
+ register struct window *p;
+
+ /* Add sizeof (Lisp_Object) here because sizeof (struct Lisp_Vector)
+ includes the first element. */
+ val = Fmake_vector (
+ make_number ((sizeof (struct window) - sizeof (struct Lisp_Vector)
+ + sizeof (Lisp_Object))
+ / sizeof (Lisp_Object)),
+ Qnil);
+ XSETTYPE (val, Lisp_Window);
+ p = XWINDOW (val);
+ XFASTINT (p->sequence_number) = ++sequence_number;
+ XFASTINT (p->left) = XFASTINT (p->top)
+ = XFASTINT (p->height) = XFASTINT (p->width)
+ = XFASTINT (p->hscroll) = 0;
+ XFASTINT (p->last_point_x) = XFASTINT (p->last_point_y) = 0;
+ p->start = Fmake_marker ();
+ p->pointm = Fmake_marker ();
+ XFASTINT (p->use_time) = 0;
+ return val;
+}
+
+DEFUN ("selected-window", Fselected_window, Sselected_window, 0, 0, 0,
+ "Return the window that the cursor now appears in and commands apply to.")
+ ()
+{
+ return selected_window;
+}
+
+DEFUN ("minibuffer-window", Fminibuffer_window, Sminibuffer_window, 0, 0, 0,
+ "Return the window used for minibuffers.")
+ ()
+{
+ return minibuf_window;
+}
+
+DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p,
+ Spos_visible_in_window_p, 0, 2, 0,
+ "Return t if position POS is currently on the screen in WINDOW.\n\
+Returns nil if that position is scrolled vertically out of view.\n\
+POS defaults to point; WINDOW, to the selected window.")
+ (pos, window)
+ Lisp_Object pos, window;
+{
+ register struct window *w;
+ register int top;
+ register int height;
+ register int posint;
+ register struct buffer *buf;
+ struct position posval;
+
+ if (NULL (pos))
+ posint = point;
+ else
+ {
+ CHECK_NUMBER_COERCE_MARKER (pos, 0);
+ posint = XINT (pos);
+ }
+
+ if (NULL (window))
+ window = selected_window;
+ else
+ CHECK_WINDOW (window, 1);
+ w = XWINDOW (window);
+ top = marker_position (w->start);
+
+ if (posint < top)
+ return Qnil;
+
+ height = XFASTINT (w->height) - !EQ (window, minibuf_window);
+
+ buf = XBUFFER (w->buffer);
+ if (XFASTINT (w->last_modified) >= BUF_MODIFF (buf))
+ {
+ /* If screen is up to date,
+ use the info recorded about how much text fit on it. */
+ if (posint < BUF_Z (buf) - XFASTINT (w->window_end_pos)
+ || (XFASTINT (w->window_end_vpos) < height))
+ return Qt;
+ return Qnil;
+ }
+ else
+ {
+ if (posint > BUF_Z (buf))
+ return Qnil;
+ /* If that info is not correct, calculate afresh */
+ posval = *compute_motion (top, 0, 0,
+ posint, height, 0,
+ XFASTINT (w->width) - 1
+ - (XFASTINT (w->width) + XFASTINT (w->left) != XFASTINT (XWINDOW (minibuf_window)->width)),
+
+ XINT (w->hscroll), 0);
+ return posval.vpos < height ? Qt : Qnil;
+ }
+}
+
+static struct window *
+decode_window (window)
+ register Lisp_Object window;
+{
+ if (NULL (window))
+ return XWINDOW (selected_window);
+
+ CHECK_WINDOW (window, 0);
+ return XWINDOW (window);
+}
+
+DEFUN ("window-buffer", Fwindow_buffer, Swindow_buffer, 0, 1, 0,
+ "Return the buffer that WINDOW is displaying.")
+ (window)
+ Lisp_Object window;
+{
+ return decode_window (window)->buffer;
+}
+
+DEFUN ("window-height", Fwindow_height, Swindow_height, 0, 1, 0,
+ "Return the number of lines in WINDOW (including its mode line).")
+ (window)
+ Lisp_Object window;
+{
+ return decode_window (window)->height;
+}
+
+DEFUN ("window-width", Fwindow_width, Swindow_width, 0, 1, 0,
+ "Return the number of columns in WINDOW.")
+ (window)
+ Lisp_Object window;
+{
+ register int w = decode_window (window)->width;
+ /* If this window does not end at the right margin,
+ must deduct one column for the border */
+ if (w + decode_window (window)->left == screen_width)
+ return w;
+ return w - 1;
+}
+
+DEFUN ("window-hscroll", Fwindow_hscroll, Swindow_hscroll, 0, 1, 0,
+ "Return the number of columns by which WINDOW is scrolled from left margin.")
+ (window)
+ Lisp_Object window;
+{
+ return decode_window (window)->hscroll;
+}
+
+DEFUN ("set-window-hscroll", Fset_window_hscroll, Sset_window_hscroll, 2, 2, 0,
+ "Set number of columns WINDOW is scrolled from left margin to NCOL.\n\
+NCOL should be zero or positive.")
+ (window, ncol)
+ register Lisp_Object window, ncol;
+{
+ register struct window *w;
+
+ CHECK_NUMBER (ncol, 1);
+ if (XINT (ncol) < 0) XFASTINT (ncol) = 0;
+ if (XFASTINT (ncol) >= (1 << (SHORTBITS - 1)))
+ args_out_of_range (ncol, Qnil);
+ w = decode_window (window);
+ if (w->hscroll != ncol)
+ clip_changed = 1; /* Prevent redisplay shortcuts */
+ w->hscroll = ncol;
+ return ncol;
+}
+
+DEFUN ("window-edges", Fwindow_edges, Swindow_edges, 0, 1, 0,
+ "Return a list of the edge coordinates of WINDOW.\n\
+\(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of screen.\n\
+RIGHT is one more than the rightmost column used by WINDOW,\n\
+and BOTTOM is one more than the bottommost row used by WINDOW\n\
+ and its mode-line.")
+ (window)
+ Lisp_Object window;
+{
+ register struct window *w = decode_window (window);
+
+ return Fcons (w->left, Fcons (w->top,
+ Fcons (make_number (XFASTINT (w->left) + XFASTINT (w->width)),
+ Fcons (make_number (XFASTINT (w->top)
+ + XFASTINT (w->height)),
+ Qnil))));
+}
+
+DEFUN ("window-point", Fwindow_point, Swindow_point, 0, 1, 0,
+ "Return current value of point in WINDOW.\n\
+For a nonselected window, this is the value point would have\n\
+if that window were selected.\n\
+\n\
+Note that, when WINDOW is the selected window and its buffer\n\
+is also currently selected, the value returned is the same as (point).\n\
+It would be more strictly correct to return the `top-level' value\n\
+of point, outside of any save-excursion forms.\n\
+But that is hard to define.")
+ (window)
+ Lisp_Object window;
+{
+ register struct window *w = decode_window (window);
+
+ if (w == XWINDOW (selected_window)
+ && current_buffer == XBUFFER (w->buffer))
+ return Fpoint ();
+ return Fmarker_position (w->pointm);
+}
+
+DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 1, 0,
+ "Return position at which display currently starts in WINDOW.")
+ (window)
+ Lisp_Object window;
+{
+ return Fmarker_position (decode_window (window)->start);
+}
+
+DEFUN ("set-window-point", Fset_window_point, Sset_window_point, 2, 2, 0,
+ "Make point value in WINDOW be at position POS in WINDOW's buffer.")
+ (window, pos)
+ Lisp_Object window, pos;
+{
+ register struct window *w = decode_window (window);
+
+ CHECK_NUMBER_COERCE_MARKER (pos, 1);
+ if (w == XWINDOW (selected_window))
+ Fgoto_char (pos);
+ else
+ set_marker_restricted (w->pointm, pos, w->buffer);
+ return pos;
+}
+
+DEFUN ("set-window-start", Fset_window_start, Sset_window_start, 2, 3, 0,
+ "Make display in WINDOW start at position POS in WINDOW's buffer.\n\
+Optional third arg NOFORCE non-nil inhibits next redisplay\n\
+from overriding motion of point in order to display at this exact start.")
+ (window, pos, noforce)
+ Lisp_Object window, pos, noforce;
+{
+ register struct window *w = decode_window (window);
+
+ CHECK_NUMBER_COERCE_MARKER (pos, 1);
+ set_marker_restricted (w->start, pos, w->buffer);
+ /* this is not right, but much easier than doing what is right. */
+ w->start_at_line_beg = Qnil;
+ if (NULL (noforce))
+ w->force_start = Qt;
+ w->update_mode_line = Qt;
+ XFASTINT (w->last_modified) = 0;
+ return pos;
+}
+
+DEFUN ("delete-window", Fdelete_window, Sdelete_window, 0, 1, "",
+ "Remove WINDOW from the display. Default is selected window.")
+ (window)
+ register Lisp_Object window;
+{
+ int osize;
+ register Lisp_Object tem, parent;
+ register struct window *p;
+ register struct window *par;
+
+ if (NULL (window))
+ window = selected_window;
+ else
+ CHECK_WINDOW (window, 0);
+
+ p = XWINDOW (window);
+ parent = p->parent;
+ if (NULL (parent))
+ error ("Attempt to delete minibuffer or sole ordinary window");
+ par=XWINDOW (parent);
+
+ windows_or_buffers_changed++;
+
+ if (EQ (window, selected_window))
+ Fselect_window (Fnext_window (window, Qnil));
+
+ tem = p->buffer;
+ /* tem is null for dummy parent windows
+ (which have inferiors but not any contents themselves) */
+ if (!NULL (tem))
+ {
+ unshow_buffer (p);
+ unchain_marker (p->pointm);
+ unchain_marker (p->start);
+ }
+
+ tem = p->next;
+ if (!NULL (tem))
+ XWINDOW (tem)->prev = p->prev;
+
+ tem = p->prev;
+ if (!NULL (tem))
+ XWINDOW (tem)->next = p->next;
+
+ if (EQ (window, par->hchild))
+ par->hchild = p->next;
+ if (EQ (window, par->vchild))
+ par->vchild = p->next;
+
+ /* Stretch the siblings to use all the available space */
+ if (!NULL (par->vchild))
+ {
+ /* It's a vertical combination */
+ osize = XFASTINT (par->height);
+ XFASTINT (par->height)
+ -= XFASTINT (p->height);
+ set_window_height (parent, osize, 1);
+ }
+ if (!NULL (par->hchild))
+ {
+ /* It's a horizontal combination */
+ osize = XFASTINT (par->width);
+ XFASTINT (par->width)
+ -= XFASTINT (p->width);
+ set_window_width (parent, osize, 1);
+ }
+
+ /* If parent now has only one child,
+ put the child into the parent's place. */
+
+ tem = par->hchild;
+ if (NULL (tem))
+ tem = par->vchild;
+ if (NULL (XWINDOW (tem)->next))
+ replace_window (parent, tem);
+ return Qnil;
+}
+
+/* Put replacement into the window structure in place of old. */
+static void
+replace_window (old, replacement)
+ Lisp_Object old, replacement;
+{
+ register Lisp_Object tem;
+ register struct window *o = XWINDOW (old), *p = XWINDOW (replacement);
+
+ p->left = o->left;
+ p->top = o->top;
+ p->width = o->width;
+ p->height = o->height;
+
+ p->next = tem = o->next;
+ if (!NULL (tem))
+ XWINDOW (tem)->prev = replacement;
+
+ p->prev = tem = o->prev;
+ if (!NULL (tem))
+ XWINDOW (tem)->next = replacement;
+
+ p->parent = tem = o->parent;
+ if (!NULL (tem))
+ {
+ if (EQ (XWINDOW (tem)->vchild, old))
+ XWINDOW (tem)->vchild = replacement;
+ if (EQ (XWINDOW (tem)->hchild, old))
+ XWINDOW (tem)->hchild = replacement;
+ }
+
+/*** Here, if replacement is a vertical combination
+and so is its new parent, we should make replacement's
+children be children of that parent instead. ***/
+}
+
+DEFUN ("next-window", Fnext_window, Snext_window, 0, 2, 0,
+ "Return next window after WINDOW in canonical ordering of windows.\n\
+Optional second arg MINIBUF t means count the minibuffer window\n\
+even if not active. If MINIBUF is neither t nor nil it means\n\
+not to count the minibuffer even if it is active.")
+ (window, mini)
+ register Lisp_Object window, mini;
+{
+ register Lisp_Object tem;
+ if (NULL (window))
+ window = selected_window;
+ else
+ CHECK_WINDOW (window, 0);
+ do
+ {
+ while (tem = XWINDOW (window)->next, NULL (tem))
+ if (tem = XWINDOW (window)->parent, !NULL (tem))
+ window = tem;
+ else /* window must be minibuf_window now */
+ {
+ tem = XWINDOW (window)->prev;
+ break;
+ }
+ window = tem;
+ while (1)
+ {
+ if (!NULL (XWINDOW (window)->hchild))
+ window = XWINDOW (window)->hchild;
+ else if (!NULL (XWINDOW (window)->vchild))
+ window = XWINDOW (window)->vchild;
+ else break;
+ }
+ }
+ while (EQ (window, minibuf_window) && !EQ (mini, Qt)
+ && (!NULL (mini) || minibuf_level == 0));
+ return window;
+}
+
+DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 1, 0,
+ "Return previous window before WINDOW in canonical ordering of windows.")
+ (window)
+ register Lisp_Object window;
+{
+ register Lisp_Object tem;
+ if (NULL (window))
+ window = selected_window;
+ else
+ CHECK_WINDOW (window, 0);
+ do /* at least once, and until not the minibuffer */
+ {
+ while (tem = XWINDOW (window)->prev, NULL (tem))
+ if (tem = XWINDOW (window)->parent, !NULL (tem))
+ window = tem;
+ else /* window must be the root window now */
+ {
+ tem = minibuf_window;
+ break;
+ }
+ window = tem;
+ while (1)
+ {
+ if (!NULL (XWINDOW (window)->hchild))
+ window = XWINDOW (window)->hchild;
+ else if (!NULL (XWINDOW (window)->vchild))
+ window = XWINDOW (window)->vchild;
+ else break;
+ while (tem = XWINDOW (window)->next, !NULL (tem))
+ window = tem;
+ }
+ }
+ while (EQ (window, minibuf_window) && minibuf_level == 0);
+ return window;
+}
+
+DEFUN ("other-window", Fother_window, Sother_window, 1, 1, "p",
+ "Select the ARG'th different window.")
+ (n)
+ register Lisp_Object n;
+{
+ register int i;
+ register Lisp_Object w;
+
+ CHECK_NUMBER (n, 0);
+ w = selected_window;
+ i = XINT (n);
+
+ while (i > 0)
+ {
+ w = Fnext_window (w, Qnil);
+ i--;
+ }
+ while (i < 0)
+ {
+ w = Fprevious_window (w);
+ i++;
+ }
+ Fselect_window (w);
+ return Qnil;
+}
+
+static Lisp_Object
+window_loop (type, obj)
+ int type;
+ register Lisp_Object obj;
+{
+ register Lisp_Object w, tem, ret_w;
+ Lisp_Object w1, start_w;
+ register struct window *p, *q;
+
+ w = minibuf_window;
+ ret_w = Qnil;
+ while (1)
+ {
+ p = XWINDOW (w);
+ w1 = Fnext_window (w, Qt);
+ if (!EQ (w, minibuf_window))
+ switch (type)
+ {
+ case 1:
+ if (XBUFFER (p->buffer) == XBUFFER (obj))
+ return w;
+ break;
+
+ case 2:
+ /* t as arg means consider only full-width windows */
+ if (!NULL (obj) && XFASTINT (p->width) != screen_width)
+ break;
+ if (NULL (ret_w) ||
+ XFASTINT (XWINDOW (ret_w)->use_time) > XFASTINT (p->use_time))
+ ret_w = w;
+ break;
+
+ case 3:
+ if (p != XWINDOW (obj))
+ Fdelete_window (w);
+ break;
+
+ case 4:
+ if (EQ (p->buffer, obj))
+ {
+ if (NULL (p->parent))
+ {
+ tem = Fother_buffer (obj);
+ if (NULL (tem))
+ tem = Fget_buffer_create (build_string ("*scratch*"));
+ Fset_window_buffer (w, tem);
+ Fset_buffer (p->buffer);
+ }
+ else
+ Fdelete_window (w);
+ }
+ break;
+
+ case 5:
+ q = XWINDOW (ret_w);
+ if (NULL (ret_w) ||
+ (XFASTINT (p->height) * XFASTINT (p->width))
+ >
+ (XFASTINT (q->height) * XFASTINT (q->width)))
+ ret_w = w;
+ break;
+
+ case 6:
+ if (EQ (p->buffer, obj))
+ {
+ tem = Fother_buffer (obj);
+ if (NULL (tem))
+ tem = Fget_buffer_create (build_string ("*scratch*"));
+ Fset_window_buffer (w, tem);
+ }
+ break;
+ }
+ w = w1;
+ if (EQ (w, minibuf_window))
+ return ret_w;
+ }
+}
+
+DEFUN ("get-lru-window", Fget_lru_window, Sget_lru_window, 0, 0, 0,
+ "Return the window least recently selected or used for display.")
+ ()
+{
+ register Lisp_Object w;
+ /* First try for a window that is full-width */
+ w = window_loop (2, Qt);
+ if (!NULL (w) && !EQ (w, selected_window))
+ return w;
+ /* If none of them, try the rest */
+ return window_loop (2, Qnil);
+}
+
+DEFUN ("get-largest-window", Fget_largest_window, Sget_largest_window, 0, 0, 0,
+ "Return the largest window in area.")
+ ()
+{
+ return window_loop (5, Qnil);
+}
+
+DEFUN ("get-buffer-window", Fget_buffer_window, Sget_buffer_window, 1, 1, 0,
+ "Return a window currently displaying BUFFER, or nil if none.")
+ (buffer)
+ Lisp_Object buffer;
+{
+ buffer = Fget_buffer (buffer);
+ if (XTYPE (buffer) == Lisp_Buffer)
+ return window_loop (1, buffer);
+ else return Qnil;
+}
+
+DEFUN ("delete-other-windows", Fdelete_other_windows, Sdelete_other_windows,
+ 0, 1, "",
+ "Make WINDOW (or the selected window) fill the screen.")
+ (w)
+ Lisp_Object w;
+{
+ window_loop (3, !NULL (w) ? w : selected_window);
+ return Qnil;
+}
+
+DEFUN ("delete-windows-on", Fdelete_windows_on, Sdelete_windows_on,
+ 1, 1, "bDelete windows on (buffer): ",
+ "Delete all windows showing BUFFER.")
+ (buffer)
+ Lisp_Object buffer;
+{
+ if (!NULL (buffer))
+ {
+ buffer = Fget_buffer (buffer);
+ CHECK_BUFFER (buffer, 0);
+ window_loop (4, buffer);
+ }
+ return Qnil;
+}
+
+DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows,
+ Sreplace_buffer_in_windows,
+ 1, 1, "bReplace buffer in windows: ",
+ "Replace BUFFER with some other buffer in all windows showing it.")
+ (buffer)
+ Lisp_Object buffer;
+{
+ if (!NULL (buffer))
+ {
+ buffer = Fget_buffer (buffer);
+ CHECK_BUFFER (buffer, 0);
+ window_loop (6, buffer);
+ }
+ return Qnil;
+}
+
+/* Set the height of WINDOW and all its inferiors. */
+/* Normally the window is deleted if it gets too small.
+ nodelete nonzero means do not do this.
+ (The caller should check later and do so if appropriate) */
+
+set_window_height (window, height, nodelete)
+ Lisp_Object window;
+ int height;
+ int nodelete;
+{
+ register struct window *w = XWINDOW (window);
+ register struct window *c;
+ int oheight = XFASTINT (w->height);
+ int top, pos, lastbot, opos, lastobot;
+ Lisp_Object child;
+
+ if (window_min_height < 2)
+ window_min_height = 2;
+
+ if (!nodelete
+ && ! NULL (w->parent)
+ && height < (EQ(window, minibuf_window) ? 1 : window_min_height))
+ {
+ Fdelete_window (window);
+ return;
+ }
+
+ XFASTINT (w->last_modified) = 0;
+ windows_or_buffers_changed++;
+ XFASTINT (w->height) = height;
+ if (!NULL (w->hchild))
+ {
+ for (child = w->hchild; !NULL (child); child = XWINDOW (child)->next)
+ {
+ XWINDOW (child)->top = w->top;
+ set_window_height (child, height, nodelete);
+ }
+ }
+ else if (!NULL (w->vchild))
+ {
+ lastbot = top = XFASTINT (w->top);
+ lastobot = 0;
+ for (child = w->vchild; !NULL (child); child = c->next)
+ {
+ c = XWINDOW (child);
+
+ opos = lastobot + XFASTINT (c->height);
+
+ XFASTINT (c->top) = lastbot;
+
+ pos = (((opos * height) << 1) + oheight) / (oheight << 1);
+
+ /* Avoid confusion: inhibit deletion of child if becomes too small */
+ set_window_height (child, pos + top - lastbot, 1);
+
+ /* Now advance child to next window,
+ and set lastbot if child was not just deleted. */
+ lastbot = pos + top, lastobot = opos;
+ }
+ /* Now delete any children that became too small. */
+ if (!nodelete)
+ for (child = w->vchild; !NULL (child); child = XWINDOW (child)->next)
+ {
+ set_window_height (child, XINT (XWINDOW (child)->height), 0);
+ }
+ }
+}
+
+/* Recursively set width of WINDOW and its inferiors. */
+
+set_window_width (window, width, nodelete)
+ Lisp_Object window;
+ int width;
+ int nodelete;
+{
+ register struct window *w = XWINDOW (window);
+ register struct window *c;
+ int owidth = XFASTINT (w->width);
+ int left, pos, lastright, opos, lastoright;
+ Lisp_Object child;
+
+ if (!nodelete
+ && ! NULL (w->parent)
+ && width < window_min_width)
+ {
+ Fdelete_window (window);
+ return;
+ }
+
+ XFASTINT (w->last_modified) = 0;
+ windows_or_buffers_changed++;
+ XFASTINT (w->width) = width;
+ if (!NULL (w->vchild))
+ {
+ for (child = w->vchild; !NULL (child); child = XWINDOW (child)->next)
+ {
+ XWINDOW (child)->left = w->left;
+ set_window_width (child, width, nodelete);
+ }
+ }
+ else if (!NULL (w->hchild))
+ {
+ lastright = left = XFASTINT (w->left);
+ lastoright = 0;
+ for (child = w->hchild; !NULL (child); child = c->next)
+ {
+ c = XWINDOW (child);
+
+ opos = lastoright + XFASTINT (c->width);
+
+ XFASTINT (c->left) = lastright;
+
+ pos = (((opos * width) << 1) + owidth) / (owidth << 1);
+
+ /* Inhibit deletion for becoming too small */
+ set_window_width (child, pos + left - lastright, 1);
+
+ /* Now advance child to next window,
+ and set lastright if child was not just deleted. */
+ lastright = pos + left, lastoright = opos;
+ }
+ /* Delete children that became too small */
+ if (!nodelete)
+ for (child = w->hchild; !NULL (child); child = XWINDOW (child)->next)
+ {
+ set_window_width (child, XINT (XWINDOW (child)->width), 0);
+ }
+ }
+}
+
+static int window_select_count;
+
+DEFUN ("set-window-buffer", Fset_window_buffer, Sset_window_buffer, 2, 2, 0,
+ "Make WINDOW display BUFFER as its contents.\n\
+BUFFER can be a buffer or buffer name.")
+ (window, buffer)
+ register Lisp_Object window, buffer;
+{
+ register Lisp_Object tem;
+ register struct window *w = decode_window (window);
+
+ buffer = Fget_buffer (buffer);
+ CHECK_BUFFER (buffer, 1);
+
+ if (NULL (XBUFFER (buffer)->name))
+ error ("Attempt to display deleted buffer");
+
+ tem = w->buffer;
+ if (!NULL (tem))
+ unshow_buffer (w);
+
+ w->buffer = buffer;
+ Fset_marker (w->pointm,
+ make_number (BUF_PT (XBUFFER (buffer))),
+ buffer);
+ set_marker_restricted (w->start,
+ make_number (XBUFFER (buffer)->last_window_start),
+ buffer);
+ w->start_at_line_beg = Qnil;
+ XFASTINT (w->last_modified) = 0;
+ windows_or_buffers_changed++;
+ if (EQ (window, selected_window))
+ Fset_buffer (buffer);
+
+ return Qnil;
+}
+
+/* Record info on buffer window w is displaying
+ when it is about to cease to display that buffer. */
+static void
+unshow_buffer (w)
+ register struct window *w;
+{
+ register Lisp_Object buf;
+ buf = w->buffer;
+
+ if (XBUFFER (buf) != XMARKER (w->pointm)->buffer)
+ abort ();
+
+ if (w == XWINDOW (selected_window)
+ || ! EQ (buf, XWINDOW (selected_window)->buffer))
+ /* Do this except when the selected window's buffer
+ is being removed from some other window. */
+ XBUFFER (buf)->last_window_start = marker_position (w->start);
+
+ /* Point in the selected window's buffer
+ is actually stored in that buffer, and the window's pointm isn't used.
+ So don't clobber point in that buffer. */
+ if (! EQ (buf, XWINDOW (selected_window)->buffer))
+ BUF_PT (XBUFFER (buf))
+ = clip_to_bounds (BUF_BEGV (XBUFFER (buf)),
+ marker_position (w->pointm),
+ BUF_ZV (XBUFFER (buf)));
+}
+
+DEFUN ("select-window", Fselect_window, Sselect_window, 1, 1, 0,
+ "Select WINDOW. Most editing will apply to WINDOW's buffer.\n\
+That buffer is made current right away.\n\n\
+The main editor command loop, before each command,\n\
+selects the buffer of the selected window.")
+ (window)
+ register Lisp_Object window;
+{
+ register struct window *w;
+ register struct window *ow = XWINDOW (selected_window);
+
+ CHECK_WINDOW (window, 0);
+
+ w = XWINDOW (window);
+
+ if (NULL (w->buffer))
+ error ("Trying to select window with no buffer");
+
+ XFASTINT (w->use_time) = ++window_select_count;
+ if (EQ (window, selected_window))
+ return window;
+
+ Fset_marker (ow->pointm, make_number (BUF_PT (XBUFFER (ow->buffer))),
+ ow->buffer);
+
+ selected_window = window;
+
+ record_buffer (w->buffer);
+ Fset_buffer (w->buffer);
+
+ /* Go to the point recorded in the window.
+ This is important when the buffer is in more
+ than one window. It also matters when
+ redisplay_window has altered point after scrolling,
+ because it makes the change only in the window. */
+ SET_PT (marker_position (w->pointm));
+ if (point < BEGV)
+ point = BEGV;
+ if (point > ZV)
+ point = ZV;
+
+ windows_or_buffers_changed++;
+
+ return window;
+}
+
+DEFUN ("display-buffer", Fdisplay_buffer, Sdisplay_buffer, 1, 2, 0,
+ "Make BUFFER appear in some window but don't select it.\n\
+BUFFER can be a buffer or a buffer name.\n\
+If BUFFER is shown already in some window, just uses that one,\n\
+unless the window is the selected window and NOTTHISWINDOW is non-nil.\n\
+Returns the window displaying BUFFER.")
+ (buffer, notthiswindow)
+ register Lisp_Object buffer, notthiswindow;
+{
+ register Lisp_Object window;
+
+ buffer = Fget_buffer (buffer);
+ CHECK_BUFFER (buffer, 0);
+
+ if (NULL (notthiswindow)
+ && XBUFFER (XWINDOW (selected_window)->buffer) == XBUFFER (buffer))
+ return selected_window;
+
+ window = Fget_buffer_window (buffer);
+ if (!NULL (window)
+ && (NULL (notthiswindow) || !EQ (window, selected_window)))
+ return window;
+
+ if (pop_up_windows)
+ {
+ /* Don't try to create a window if would get an error */
+ if (window_min_height < 2)
+ window_min_height = 2;
+ if (split_height_threshold < window_min_height << 1)
+ split_height_threshold = window_min_height << 1;
+
+ window = Fget_largest_window ();
+ if (window_height (window) >= split_height_threshold
+ &&
+ XFASTINT (XWINDOW (window)->width) == screen_width)
+ window = Fsplit_window (window, Qnil, Qnil);
+ else
+ {
+ window = Fget_lru_window ();
+ if ((EQ (window, selected_window)
+ || (EQ (selected_window, minibuf_window)
+ && EQ (window, XWINDOW (minibuf_window)->prev)))
+ && window_height (window) >= window_min_height << 1)
+ window = Fsplit_window (window, Qnil, Qnil);
+ }
+ }
+ else
+ window = Fget_lru_window ();
+
+ Fset_window_buffer (window, buffer);
+ return window;
+}
+
+temp_output_buffer_show (buf)
+ register Lisp_Object buf;
+{
+ register struct buffer *old = current_buffer;
+ register Lisp_Object window;
+ register struct window *w;
+
+ Fset_buffer (buf);
+ XBUFFER (buf)->save_modified = MODIFF;
+ BEGV = BEG;
+ ZV = Z;
+ SET_PT (BEG);
+ clip_changed = 1;
+ set_buffer_internal (old);
+
+ if (!EQ (Vtemp_buffer_show_hook, Qnil))
+ call1 (Vtemp_buffer_show_hook, buf);
+ else
+ {
+ window = Fdisplay_buffer (buf, Qnil);
+ Vminibuf_scroll_window = window;
+ w = XWINDOW (window);
+ XFASTINT (w->hscroll) = 0;
+ set_marker_restricted (w->start, make_number (1), buf);
+ set_marker_restricted (w->pointm, make_number (1), buf);
+ }
+}
+
+static
+make_dummy_parent (window)
+ Lisp_Object window;
+{
+ register Lisp_Object old, new;
+ register struct window *o, *p;
+
+ old = window;
+ XSETTYPE (old, Lisp_Vector);
+ new = Fcopy_sequence (old);
+ XSETTYPE (new, Lisp_Window);
+
+ o = XWINDOW (old);
+ p = XWINDOW (new);
+ XFASTINT (p->sequence_number) = ++sequence_number;
+
+ /* Put new into window structure in place of window */
+ replace_window (window, new);
+
+ o->next = Qnil;
+ o->prev = Qnil;
+ o->vchild = Qnil;
+ o->hchild = Qnil;
+ o->parent = new;
+
+ p->start = Qnil;
+ p->pointm = Qnil;
+ p->buffer = Qnil;
+}
+
+DEFUN ("split-window", Fsplit_window, Ssplit_window, 0, 3, "",
+ "Split WINDOW, putting SIZE lines in the first of the pair.\n\
+WINDOW defaults to selected one and SIZE to half its size.\n\
+If optional third arg HOR-FLAG is non-nil, split side by side\n\
+and put SIZE columns in the first of the pair.")
+ (window, chsize, horflag)
+ Lisp_Object window, chsize, horflag;
+{
+ register Lisp_Object new;
+ register struct window *o, *p;
+ register int size;
+
+ if (NULL (window))
+ window = selected_window;
+ else
+ CHECK_WINDOW (window, 0);
+
+ o = XWINDOW (window);
+
+ if (NULL (chsize))
+ {
+ if (!NULL (horflag))
+ /* Add 1 so we round up rather than down.
+ This puts an excess column into the left-hand window,
+ which is the one that certainly contains a border line. */
+ size = (1 + XFASTINT (o->width)) >> 1;
+ else
+ size = XFASTINT (o->height) >> 1;
+ }
+ else
+ {
+ CHECK_NUMBER (chsize, 1);
+ size = XINT (chsize);
+ }
+
+ if (EQ (window, minibuf_window))
+ error ("Attempt to split minibuffer window");
+
+ if (NULL (horflag))
+ {
+ if (window_min_height < 2)
+ window_min_height = 2;
+
+ if (size < window_min_height ||
+ size + window_min_height > XFASTINT (o->height))
+ args_out_of_range_3 (window, chsize, horflag);
+ if (NULL (o->parent) ||
+ NULL (XWINDOW (o->parent)->vchild))
+ {
+ make_dummy_parent (window);
+ new = o->parent;
+ XWINDOW (new)->vchild = window;
+ }
+ }
+ else
+ {
+ if (size < window_min_width ||
+ size + window_min_width > XFASTINT (o->width))
+ args_out_of_range_3 (window, chsize, horflag);
+ if (NULL (o->parent) ||
+ NULL (XWINDOW (o->parent)->hchild))
+ {
+ make_dummy_parent (window);
+ new = o->parent;
+ XWINDOW (new)->hchild = window;
+ }
+ }
+
+ /* Now we know that window's parent is a vertical combination
+ if we are dividing vertically, or a horizontal combination
+ if we are making side-by-side windows */
+
+ windows_or_buffers_changed++;
+ new = make_window ();
+ p = XWINDOW (new);
+
+ p->next = o->next;
+ if (!NULL (p->next))
+ XWINDOW (p->next)->prev = new;
+ p->prev = window;
+ o->next = new;
+ p->parent = o->parent;
+
+ Fset_window_buffer (new, o->buffer);
+
+ /* Apportion the available screen space among the two new windows */
+
+ if (!NULL (horflag))
+ {
+ p->height = o->height;
+ p->top = o->top;
+ XFASTINT (p->width) = XFASTINT (o->width) - size;
+ XFASTINT (o->width) = size;
+ XFASTINT (p->left) = XFASTINT (o->left) + size;
+ }
+ else
+ {
+ p->left = o->left;
+ p->width = o->width;
+ XFASTINT (p->height) = XFASTINT (o->height) - size;
+ XFASTINT (o->height) = size;
+ XFASTINT (p->top) = XFASTINT (o->top) + size;
+ }
+
+ return new;
+}
+
+DEFUN ("enlarge-window", Fenlarge_window, Senlarge_window, 1, 2, "p",
+ "Make current window ARG lines bigger.\n\
+From program, optional second arg non-nil means grow sideways ARG columns.")
+ (n, side)
+ register Lisp_Object n, side;
+{
+ CHECK_NUMBER (n, 0);
+ change_window_height (XINT (n), !NULL (side));
+ return Qnil;
+}
+
+DEFUN ("shrink-window", Fshrink_window, Sshrink_window, 1, 2, "p",
+ "Make current window ARG lines smaller.\n\
+From program, optional second arg non-nil means shrink sideways ARG columns.")
+ (n, side)
+ register Lisp_Object n, side;
+{
+ CHECK_NUMBER (n, 0);
+ change_window_height (-XINT (n), !NULL (side));
+ return Qnil;
+}
+
+int
+window_height (window)
+ Lisp_Object window;
+{
+ register struct window *p = XWINDOW (window);
+ return XFASTINT (p->height);
+}
+
+int
+window_width (window)
+ Lisp_Object window;
+{
+ register struct window *p = XWINDOW (window);
+ return XFASTINT (p->width);
+}
+
+#define MINSIZE(window) \
+ (widthflag ? window_min_width \
+ : (EQ (window, minibuf_window) ? 1 : window_min_height))
+
+#define CURBEG(w) \
+ *(widthflag ? (int *) &w->left : (int *) &w->top)
+
+#define CURSIZE(w) \
+ *(widthflag ? (int *) &w->width : (int *) &w->height)
+
+/* Unlike set_window_height, this function
+ also changes the heights of the siblings so as to
+ keep everything consistent. */
+
+change_window_height (delta, widthflag)
+ register int delta;
+ int widthflag;
+{
+ register Lisp_Object parent;
+ Lisp_Object window;
+ register struct window *p;
+ int *sizep;
+ int (*sizefun) () = widthflag ? window_width : window_height;
+ register int (*setsizefun) () = widthflag ? set_window_width : set_window_height;
+
+ if (window_min_height < 2)
+ window_min_height = 2;
+
+ window = selected_window;
+ while (1)
+ {
+ p = XWINDOW (window);
+ parent = p->parent;
+ if (NULL (parent))
+ {
+ if (widthflag)
+ error ("No other window to side of this one");
+ break;
+ }
+ if (widthflag ? !NULL (XWINDOW (parent)->hchild)
+ : !NULL (XWINDOW (parent)->vchild))
+ break;
+ window = parent;
+ }
+
+ sizep = &CURSIZE (p);
+
+ if (*sizep + delta < MINSIZE (window))
+ {
+ Fdelete_window (window);
+ return;
+ }
+
+ {
+ register int maxdelta;
+ register Lisp_Object tem;
+
+ maxdelta = (!NULL (parent) ? (*sizefun) (parent) - *sizep
+ : (tem = (!NULL (p->next) ? p->next : p->prev),
+ (*sizefun) (tem) - MINSIZE (tem)));
+
+ if (delta > maxdelta)
+ /* This case traps trying to make the minibuffer
+ the full screen, or make the only window aside from the
+ minibuffer the full screen. */
+ delta = maxdelta;
+ }
+
+ if (!NULL (p->next) &&
+ (*sizefun) (p->next) - delta >= MINSIZE (p->next))
+ {
+ (*setsizefun) (p->next, (*sizefun) (p->next) - delta, 0);
+ (*setsizefun) (window, *sizep + delta, 0);
+ CURBEG (XWINDOW (p->next)) += delta;
+ /* This does not change size of p->next,
+ but it propagates the new top edge to its children */
+ (*setsizefun) (p->next, (*sizefun) (p->next), 0);
+ }
+ else if (!NULL (p->prev) &&
+ (*sizefun) (p->prev) - delta >= MINSIZE (p->prev))
+ {
+ (*setsizefun) (p->prev, (*sizefun) (p->prev) - delta, 0);
+ CURBEG (p) -= delta;
+ (*setsizefun) (window, *sizep + delta, 0);
+ }
+ else
+ {
+ register int delta1;
+ register int opht = (*sizefun) (parent);
+
+ /* If trying to grow this window to or beyond size of the parent,
+ make delta1 so big that, on shrinking back down,
+ all the siblings end up with less than one line and are deleted. */
+ if (opht <= *sizep + delta)
+ delta1 = opht * opht * 2;
+ /* Otherwise, make delta1 just right so that if we add delta1
+ lines to this window and to the parent, and then shrink
+ the parent back to its original size, the new proportional
+ size of this window will increase by delta. */
+ else
+ delta1 = (delta * opht * 100) / ((opht - *sizep - delta) * 100);
+
+ /* Add delta1 lines or columns to this window, and to the parent,
+ keeping things consistent while not affecting siblings. */
+ CURSIZE (XWINDOW (parent)) = opht + delta1;
+ (*setsizefun) (window, *sizep + delta1, 0);
+
+ /* Squeeze out delta1 lines or columns from our parent,
+ shriking this window and siblings proportionately.
+ This brings parent back to correct size.
+ Delta1 was calculated so this makes this window the desired size,
+ taking it all out of the siblings. */
+ (*setsizefun) (parent, opht, 0);
+ }
+
+ XFASTINT (p->last_modified) = 0;
+}
+#undef MINSIZE
+#undef CURBEG
+#undef CURSIZE
+
+
+/* Scroll window WINDOW (a Lisp object) by N lines.
+ If NOERROR is 0, signal an error if that can't be done.
+ If NOERROR is nonzero, return Qnil if successful
+ and an error name otherwise. */
+
+static Lisp_Object
+window_scroll (window, n, noerror)
+ Lisp_Object window;
+ int n;
+ int noerror;
+{
+ register struct window *w = XWINDOW (window);
+ register int opoint = point;
+ register int ht, pos;
+ register Lisp_Object tem;
+ int lose;
+ Lisp_Object bolp;
+
+ ht = XFASTINT (w->height) - !EQ (window, minibuf_window);
+
+ XFASTINT (tem) = point;
+ tem = Fpos_visible_in_window_p (tem, window);
+
+ if (NULL (tem))
+ {
+ Fvertical_motion (make_number (- ht / 2));
+ XFASTINT (tem) = point;
+ Fset_marker (w->start, tem, w->buffer);
+ w->force_start = Qt;
+ }
+
+ SET_PT (marker_position (w->start));
+ lose = n < 0 && point == BEGV;
+ Fvertical_motion (make_number (n));
+ pos = point;
+ bolp = Fbolp ();
+ SET_PT (opoint);
+
+ if (lose)
+ {
+ if (noerror)
+ return Qbeginning_of_buffer;
+ Fsignal (Qbeginning_of_buffer, Qnil);
+ }
+
+ if (pos < ZV)
+ {
+ set_marker_restricted (w->start, make_number (pos), w->buffer);
+ w->start_at_line_beg = bolp;
+ w->update_mode_line = Qt;
+ XFASTINT (w->last_modified) = 0;
+ if (pos > opoint)
+ SET_PT (pos);
+ if (n < 0)
+ {
+ SET_PT (pos);
+ tem = Fvertical_motion (make_number (ht));
+ if (point > opoint || XFASTINT (tem) < ht)
+ SET_PT (opoint);
+ else
+ Fvertical_motion (make_number (-1));
+ }
+ return Qnil;
+ }
+ else
+ {
+ if (!noerror)
+ Fsignal (Qend_of_buffer, Qnil);
+ return Qend_of_buffer;
+ }
+}
+
+scroll_command (n, direction)
+ register Lisp_Object n;
+ int direction;
+{
+ register int defalt = (window_height (selected_window) - 1
+ - next_screen_context_lines);
+
+ if (defalt < 1)
+ defalt = 1;
+ defalt *= direction;
+
+ if (NULL (n))
+ window_scroll (selected_window, defalt, 0);
+ else if (EQ (n, Qminus))
+ window_scroll (selected_window, - defalt, 0);
+ else
+ {
+ n = Fprefix_numeric_value (n);
+ window_scroll (selected_window, XINT (n) * direction, 0);
+ }
+}
+
+DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "P",
+ "Scroll text of current window upward ARG lines; or near full screen if no ARG.\n\
+When calling from a program, supply a number as argument or nil.")
+ (n)
+ Lisp_Object n;
+{
+ scroll_command (n, 1);
+ return Qnil;
+}
+
+DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "P",
+ "Scroll text of current window downward ARG lines; or near full screen if no ARG.\n\
+When calling from a program, supply a number as argument or nil.")
+ (n)
+ Lisp_Object n;
+{
+ scroll_command (n, -1);
+ return Qnil;
+}
+
+DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 1, 1, "P",
+ "Scroll selected window display ARG columns left.\n\
+Default for ARG is window width minus 2.")
+ (arg)
+ register Lisp_Object arg;
+{
+ if (NULL (arg))
+ XFASTINT (arg) = XFASTINT (XWINDOW (selected_window)->width) - 2;
+ else
+ arg = Fprefix_numeric_value (arg);
+
+ return Fset_window_hscroll (selected_window,
+ make_number (XINT (XWINDOW (selected_window)->hscroll)
+ + XINT (arg)));
+}
+
+DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 1, 1, "P",
+ "Scroll selected window display ARG columns right.\n\
+Default for ARG is window width minus 2.")
+ (arg)
+ register Lisp_Object arg;
+{
+ if (NULL (arg))
+ XFASTINT (arg) = XFASTINT (XWINDOW (selected_window)->width) - 2;
+ else
+ arg = Fprefix_numeric_value (arg);
+
+ return Fset_window_hscroll (selected_window,
+ make_number (XINT (XWINDOW (selected_window)->hscroll)
+ - XINT (arg)));
+}
+
+DEFUN ("scroll-other-window", Fscroll_other_window, Sscroll_other_window, 0, 1, "P",
+ "Scroll text of next window upward ARG lines; or near full screen if no ARG.\n\
+The next window is the one below the current one; or the one at the top\n\
+if the current one is at the bottom.\n\
+When calling from a program, supply a number as argument or nil.")
+ (n)
+ register Lisp_Object n;
+{
+ register Lisp_Object window;
+ struct buffer *old = current_buffer;
+ register int ht;
+ register int opoint = point;
+ register struct window *w;
+ Lisp_Object result;
+
+ if (EQ (selected_window, minibuf_window)
+ && !NULL (Vminibuf_scroll_window))
+ window = Vminibuf_scroll_window;
+ else
+ window = Fnext_window (selected_window, Qnil);
+ CHECK_WINDOW (window, 0);
+ ht = window_height (window) - 1;
+
+ if (EQ (window, selected_window))
+ error ("There is no other window");
+
+ w = XWINDOW (window);
+ Fset_buffer (w->buffer);
+ SET_PT (marker_position (w->pointm));
+
+ if (NULL (n))
+ result = window_scroll (window, ht - next_screen_context_lines, 1);
+ else if (EQ (n, Qminus))
+ result = window_scroll (window, next_screen_context_lines - ht, 1);
+ else
+ {
+ if (XTYPE (n) == Lisp_Cons)
+ n = Fcar (n);
+ CHECK_NUMBER (n, 0);
+ result = window_scroll (window, XINT (n), 1);
+ }
+
+ Fset_marker (w->pointm, make_number (point), Qnil);
+ set_buffer_internal (old);
+ SET_PT (opoint);
+ if (!EQ (result, Qnil))
+ Fsignal (result, Qnil);
+ return Qnil;
+}
+
+DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
+ "Center point in window and redisplay screen. With ARG, put point on line ARG.\n\
+The desired position of point is always relative to the current window.\n\
+Just C-u as prefix means put point in the center of the screen.\n\
+No arg (i.e., it is nil) erases the entire screen and then\n\
+redraws with point in the center.")
+ (n)
+ register Lisp_Object n;
+{
+ register int ht = window_height (selected_window)
+ - !EQ (selected_window, minibuf_window);
+ register struct window *w = XWINDOW (selected_window);
+ register int opoint = point;
+
+ if (NULL (n))
+ {
+ extern int screen_garbaged;
+ screen_garbaged++;
+ XFASTINT (n) = ht / 2;
+ }
+ else if (XTYPE (n) == Lisp_Cons) /* Just C-u. */
+ {
+ XFASTINT (n) = ht / 2;
+ }
+ else
+ {
+ n = Fprefix_numeric_value (n);
+ CHECK_NUMBER (n, 0);
+ }
+
+ if (XINT (n) < 0)
+ XSETINT (n, XINT (n) + ht);
+
+ XSETINT (n, - XINT (n));
+
+ Fvertical_motion (n);
+ Fset_marker (w->start, make_number (point), w->buffer);
+ w->start_at_line_beg = Fbolp ();
+
+ SET_PT (opoint);
+ w->force_start = Qt;
+
+ return Qnil;
+}
+
+DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
+ 1, 1, "P",
+ "Position point relative to window.\n\
+With no argument, position at text at center of window.\n\
+An argument specifies screen line; zero means top of window,\n\
+negative means relative to bottom of window.")
+ (arg)
+ register Lisp_Object arg;
+{
+ register struct window *w = XWINDOW (selected_window);
+ register int height = XFASTINT (w->height);
+ register int start;
+
+ if (!EQ (selected_window, minibuf_window)) height--;
+
+ if (NULL (arg))
+ XFASTINT (arg) = height / 2;
+ else
+ {
+ arg = Fprefix_numeric_value (arg);
+ if (XINT (arg) < 0)
+ XSETINT (arg, XINT (arg) + height);
+ }
+
+ start = marker_position (w->start);
+ if (start < BEGV || start > ZV)
+ {
+ Fvertical_motion (make_number (- height / 2));
+ Fset_marker (w->start, make_number (point), w->buffer);
+ w->start_at_line_beg = Fbolp ();
+ w->force_start = Qt;
+ }
+ else
+ SET_PT (start);
+
+ return Fvertical_motion (arg);
+}
+
+struct save_window_data
+ {
+ int size_from_Lisp_Vector_struct;
+ struct Lisp_Vector *next_from_Lisp_Vector_struct;
+ Lisp_Object screen_width, screen_height;
+ Lisp_Object current_window;
+ Lisp_Object current_buffer;
+ Lisp_Object minibuf_scroll_window;
+ /* A vector, interpreted as a struct saved_window */
+ Lisp_Object saved_windows;
+ };
+#define SAVE_WINDOW_DATA_SIZE 6 /* Arg to Fmake_vector */
+
+/* This is saved as a Lisp_Vector */
+struct saved_window
+ {
+ /* these first two must agree with struct Lisp_Vector in lisp.h */
+ int size_from_Lisp_Vector_struct;
+ struct Lisp_Vector *next_from_Lisp_Vector_struct;
+
+ Lisp_Object window;
+ Lisp_Object buffer, start, pointm, mark;
+ Lisp_Object left, top, width, height, hscroll;
+ Lisp_Object parent, prev;
+ Lisp_Object start_at_line_beg;
+ };
+#define SAVED_WINDOW_VECTOR_SIZE 13 /* Arg to Fmake_vector */
+
+#define SAVED_WINDOW_N(swv,n) \
+ ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
+
+DEFUN ("set-window-configuration",
+ Fset_window_configuration, Sset_window_configuration,
+ 1, 1, 0,
+ "Restore the configuration of Emacs' windows and buffers to\n\
+the state specified by CONFIGURATION. CONFIGURATION must be a value\n\
+retrned by current-window-configuration -- see the documentation of that\n\
+function for more information.")
+ (arg)
+ Lisp_Object arg;
+{
+ register struct window *w;
+ register struct save_window_data *data;
+ struct Lisp_Vector *saved_windows;
+ register struct saved_window *p;
+ register Lisp_Object tem;
+ Lisp_Object new_current_buffer;
+ int k;
+
+ /* Save screen height here so we can go back to it at the end. */
+ int previous_screen_height = screen_height;
+ int previous_screen_width = screen_width;
+ int screen_size_change = 0;
+
+ while (XTYPE (arg) != Lisp_Window_Configuration)
+ {
+ /* the function window-configuration-p isn't actually defined
+ at present --- is there a need for it? */
+ arg = wrong_type_argument (intern ("window-configuration-p"), arg);
+ }
+
+ data = (struct save_window_data *) XVECTOR (arg);
+ saved_windows = XVECTOR (data->saved_windows);
+
+ /* Set the screen height to the value it had at save time. */
+ if (XFASTINT (data->screen_height) != screen_height
+ || XFASTINT (data->screen_width) != screen_width)
+ {
+ change_screen_size (data->screen_height, data->screen_width, 0, 0, 0);
+ screen_size_change = 1;
+ }
+
+ windows_or_buffers_changed++;
+ new_current_buffer = data->current_buffer;
+ if (NULL (XBUFFER (new_current_buffer)->name))
+ new_current_buffer = Qnil;
+
+ for (k = 0; k < saved_windows->size; k++)
+ {
+ p = SAVED_WINDOW_N (saved_windows, k);
+ w = XWINDOW (p->window);
+ w->next = Qnil;
+
+ if (!NULL (p->parent))
+ w->parent = SAVED_WINDOW_N (saved_windows, XFASTINT (p->parent))->window;
+ else
+ w->parent = Qnil;
+
+ if (!NULL (p->prev))
+ {
+ w->prev = SAVED_WINDOW_N (saved_windows, XFASTINT (p->prev))->window;
+ XWINDOW (w->prev)->next = p->window;
+ }
+ else
+ {
+ w->prev = Qnil;
+ if (!NULL (w->parent))
+ {
+ if (EQ (p->width, XWINDOW (w->parent)->width))
+ {
+ XWINDOW (w->parent)->vchild = p->window;
+ XWINDOW (w->parent)->hchild = Qnil;
+ }
+ else
+ {
+ XWINDOW (w->parent)->hchild = p->window;
+ XWINDOW (w->parent)->vchild = Qnil;
+ }
+ }
+ }
+ w->left = p->left;
+ w->top = p->top;
+ w->width = p->width;
+ w->height = p->height;
+ w->hscroll = p->hscroll;
+ XFASTINT (w->last_modified) = 0;
+
+ /* Reinstall the saved buffer and pointers into it. */
+ if (NULL (p->buffer))
+ w->buffer = p->buffer;
+ else
+ {
+ if (!NULL (XBUFFER (p->buffer)->name))
+ /* If saved buffer is alive, install it. */
+ {
+ w->buffer = p->buffer;
+ w->start_at_line_beg = p->start_at_line_beg;
+ set_marker_restricted (w->start,
+ Fmarker_position (p->start), w->buffer);
+ set_marker_restricted (w->pointm,
+ Fmarker_position (p->pointm), w->buffer);
+ Fset_marker (XBUFFER (w->buffer)->mark,
+ Fmarker_position (p->mark), w->buffer);
+
+ if (!EQ (p->buffer, new_current_buffer) &&
+ XBUFFER (p->buffer) == current_buffer)
+ Fgoto_char (w->pointm);
+ }
+ else if (NULL (XBUFFER (w->buffer)->name))
+ /* Else if window's old buffer is dead too, get a live one. */
+ {
+ w->buffer = Fcdr (Fcar (Vbuffer_alist));
+ /* Set window markers at start of buffer.
+ Rely on set_marker_restricted to put them
+ within the restriction. */
+ set_marker_restricted (w->start, make_number (0), w->buffer);
+ set_marker_restricted (w->pointm, make_number (0), w->buffer);
+ w->start_at_line_beg = Qt;
+ }
+ else
+ /* Keeping window's old buffer; make sure the markers are real. */
+ /* Else if window's old buffer is dead too, get a live one. */
+ {
+ /* Set window markers at start of buffer.
+ Rely on set_marker_restricted to put them within the restriction. */
+ if (XMARKER (w->start)->buffer == 0)
+ set_marker_restricted (w->start, make_number (0), w->buffer);
+ if (XMARKER (w->pointm)->buffer == 0)
+ set_marker_restricted (w->pointm,
+ make_number (BUF_PT (XBUFFER (w->buffer))),
+ w->buffer);
+ w->start_at_line_beg = Qt;
+ }
+ }
+ }
+
+ /* Set the screen height to the value it had before this function. */
+ if (screen_size_change)
+ change_screen_size (previous_screen_height, previous_screen_width, 0, 0, 0);
+
+ Fselect_window (data->current_window);
+ if (!NULL (new_current_buffer))
+ Fset_buffer (new_current_buffer);
+ else
+ Fset_buffer (XWINDOW (selected_window)->buffer);
+ Vminibuf_scroll_window = data->minibuf_scroll_window;
+ return (Qnil);
+}
+
+
+static int
+count_windows (window)
+ register struct window *window;
+{
+ register int count = 1;
+ if (!NULL (window->next))
+ count += count_windows (XWINDOW (window->next));
+ if (!NULL (window->vchild))
+ count += count_windows (XWINDOW (window->vchild));
+ if (!NULL (window->hchild))
+ count += count_windows (XWINDOW (window->hchild));
+ return count;
+}
+
+DEFUN ("current-window-configuration",
+ Fcurrent_window_configuration, Scurrent_window_configuration, 0, 0, 0,
+ "Return an object representing Emacs' current window configuration,\n\
+namely the number of windows, their sizes and current buffers, and for\n\
+each displayed buffer, where display starts, and the positions of\n\
+point and mark. An exception is made for point in (current-buffer) --\n\
+its value is -not- saved.")
+ ()
+{
+ register Lisp_Object tem;
+ register int n_windows;
+ register struct save_window_data *data;
+ register int i;
+
+ n_windows = count_windows (XWINDOW (XWINDOW (minibuf_window)->prev));
+ data = (struct save_window_data *)
+ XVECTOR (Fmake_vector (make_number (SAVE_WINDOW_DATA_SIZE),
+ Qnil));
+ XFASTINT (data->screen_width) = screen_width;
+ XFASTINT (data->screen_height) = screen_height;
+ data->current_window = selected_window;
+ XSET (data->current_buffer, Lisp_Buffer, current_buffer);
+ data->minibuf_scroll_window = Vminibuf_scroll_window;
+ tem = Fmake_vector (make_number (n_windows), Qnil);
+ data->saved_windows = tem;
+ for (i = 0; i < n_windows; i++)
+ XVECTOR (tem)->contents[i]
+ = Fmake_vector (make_number (SAVED_WINDOW_VECTOR_SIZE), Qnil);
+ save_window_save (XWINDOW (minibuf_window)->prev,
+ XVECTOR (tem),
+ 0, n_windows);
+ XSET (tem, Lisp_Window_Configuration, data);
+ return (tem);
+}
+
+static int
+save_window_save (window, vector, i, maxwindow)
+ Lisp_Object window;
+ struct Lisp_Vector *vector;
+ int i;
+ int maxwindow;
+{
+ register struct saved_window *p;
+ register struct window *w;
+ register Lisp_Object tem;
+
+ for (;!NULL (window); window = w->next)
+ {
+ /* If you get a crash here, you may be seeing a very weird bug.
+ When it happened to me, it seems that count_windows returned
+ a value that was too small--only two, when there were two
+ visible windows, a parent, and the minibuffer (inactive).
+ If this starts happening for you, please run under a debugger
+ with a breakpoint at the abort, so that you can at least try calling
+ count_windows again to see if it will lose again.
+ If it does, you can find the bug. */
+ if (i == maxwindow)
+ abort ();
+
+ p = SAVED_WINDOW_N (vector, i);
+ w = XWINDOW (window);
+
+ XFASTINT (w->temslot) = i++;
+
+ p->window = window;
+ p->buffer = w->buffer;
+ p->left = w->left;
+ p->top = w->top;
+ p->width = w->width;
+ p->height = w->height;
+ p->hscroll = w->hscroll;
+ if (!NULL (w->buffer))
+ {
+ /* Save w's value of point in the window configuration.
+ If w is the selected window, then get the value of point
+ from the buffer; pointm is garbage in the selected window. */
+ if (EQ (window, selected_window))
+ {
+ p->pointm = Fmake_marker ();
+ Fset_marker (p->pointm, BUF_PT (XBUFFER (w->buffer)),
+ w->buffer);
+ }
+ else
+ p->pointm = Fcopy_marker (w->pointm);
+
+ p->start = Fcopy_marker (w->start);
+ p->start_at_line_beg = w->start_at_line_beg;
+
+ tem = XBUFFER (w->buffer)->mark;
+ p->mark = Fcopy_marker (tem);
+ }
+ else
+ {
+ p->pointm = Qnil;
+ p->start = Qnil;
+ p->mark = Qnil;
+ p->start_at_line_beg = Qnil;
+ }
+
+ if (NULL (w->parent))
+ p->parent = Qnil;
+ else
+ p->parent = XWINDOW (w->parent)->temslot;
+
+ if (NULL (w->prev))
+ p->prev = Qnil;
+ else
+ p->prev = XWINDOW (w->prev)->temslot;
+
+ if (!NULL (w->vchild))
+ i = save_window_save (w->vchild, vector, i, maxwindow);
+ if (!NULL (w->hchild))
+ i = save_window_save (w->hchild, vector, i, maxwindow);
+ }
+
+ return i;
+}
+
+DEFUN ("save-window-excursion", Fsave_window_excursion, Ssave_window_excursion,
+ 0, UNEVALLED, 0,
+ "Execute body, preserving window sizes and contents.\n\
+Restores which buffer appears in which window, where display starts,\n\
+as well as the current buffer.\n\
+Does not restore the value of point in current buffer.")
+ (args)
+ Lisp_Object args;
+{
+ register Lisp_Object val;
+ register int count = specpdl_ptr - specpdl;
+
+ record_unwind_protect (Fset_window_configuration,
+ Fcurrent_window_configuration ());
+ val = Fprogn (args);
+ unbind_to (count);
+ return val;
+}
+
+init_window_once ()
+{
+ extern Lisp_Object get_minibuffer ();
+ register Lisp_Object root_window;
+
+ root_window = make_window ();
+ minibuf_window = make_window ();
+
+ XWINDOW (root_window)->next = minibuf_window;
+ XWINDOW (minibuf_window)->prev = root_window;
+
+ /* These values 9 and 10 are arbitrary,
+ just so that there is "something there."
+ Correct values are put in in init_xdisp */
+
+ XFASTINT (XWINDOW (root_window)->width) = 10;
+ XFASTINT (XWINDOW (minibuf_window)->width) = 10;
+
+ XFASTINT (XWINDOW (root_window)->height) = 9;
+ XFASTINT (XWINDOW (minibuf_window)->top) = 9;
+ XFASTINT (XWINDOW (minibuf_window)->height) = 1;
+
+ Fset_window_buffer (root_window, Fcurrent_buffer ());
+ Fset_window_buffer (minibuf_window, get_minibuffer (0));
+
+ selected_window = root_window;
+ /* Make sure this window seems more recently used than
+ a newly-created, never-selected window. */
+ XFASTINT (XWINDOW (selected_window)->use_time) = ++window_select_count;
+}
+
+syms_of_window ()
+{
+ Qwindowp = intern ("windowp");
+ staticpro (&Qwindowp);
+
+ /* Make sure all windows get marked */
+ staticpro (&minibuf_window);
+
+ DEFVAR_INT ("minibuffer-prompt-width", &minibuf_prompt_width,
+ "Width of the prompt appearing at the start of the minibuffer window.\n\
+The value is meaningless when the minibuffer is not visible.");
+
+ DEFVAR_LISP ("temp-buffer-show-hook", &Vtemp_buffer_show_hook,
+ "Non-nil means call as function to display a help buffer.\n\
+Used by with-output-to-temp-buffer.");
+ Vtemp_buffer_show_hook = Qnil;
+
+ DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window,
+ "Non-nil means it is the window that C-M-v in minibuffer should scroll.");
+ Vminibuf_scroll_window = Qnil;
+
+ DEFVAR_BOOL ("pop-up-windows", &pop_up_windows,
+ "*Non-nil means display-buffer should make new windows.");
+ pop_up_windows = 1;
+
+ DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines,
+ "*Number of lines of continuity when scrolling by screenfuls.");
+ next_screen_context_lines = 2;
+
+ DEFVAR_INT ("split-height-threshold", &split_height_threshold,
+ "*display-buffer would prefer to split the largest window if this large.\n\
+If there is only one window, it is split regardless of this value.");
+ split_height_threshold = 500;
+
+ DEFVAR_INT ("window-min-height", &window_min_height,
+ "*Delete any window less than this tall (including its mode line).");
+ window_min_height = 4;
+
+ DEFVAR_INT ("window-min-width", &window_min_width,
+ "*Delete any window less than this wide.");
+ window_min_width = 10;
+
+ defsubr (&Sselected_window);
+ defsubr (&Sminibuffer_window);
+ defsubr (&Swindowp);
+ defsubr (&Spos_visible_in_window_p);
+ defsubr (&Swindow_buffer);
+ defsubr (&Swindow_height);
+ defsubr (&Swindow_width);
+ defsubr (&Swindow_hscroll);
+ defsubr (&Sset_window_hscroll);
+ defsubr (&Swindow_edges);
+ defsubr (&Swindow_point);
+ defsubr (&Swindow_start);
+ defsubr (&Sset_window_point);
+ defsubr (&Sset_window_start);
+ defsubr (&Snext_window);
+ defsubr (&Sprevious_window);
+ defsubr (&Sother_window);
+ defsubr (&Sget_lru_window);
+ defsubr (&Sget_largest_window);
+ defsubr (&Sget_buffer_window);
+ defsubr (&Sdelete_other_windows);
+ defsubr (&Sdelete_windows_on);
+ defsubr (&Sreplace_buffer_in_windows);
+ defsubr (&Sdelete_window);
+ defsubr (&Sset_window_buffer);
+ defsubr (&Sselect_window);
+ defsubr (&Sdisplay_buffer);
+ defsubr (&Ssplit_window);
+ defsubr (&Senlarge_window);
+ defsubr (&Sshrink_window);
+ defsubr (&Sscroll_up);
+ defsubr (&Sscroll_down);
+ defsubr (&Sscroll_left);
+ defsubr (&Sscroll_right);
+ defsubr (&Sscroll_other_window);
+ defsubr (&Srecenter);
+ defsubr (&Smove_to_window_line);
+ defsubr (&Sset_window_configuration);
+ defsubr (&Scurrent_window_configuration);
+ defsubr (&Ssave_window_excursion);
+}
+
+keys_of_window ()
+{
+ ndefkey (Vctl_x_map, '1', "delete-other-windows");
+ ndefkey (Vctl_x_map, '2', "split-window");
+ ndefkey (Vctl_x_map, '0', "delete-window");
+ ndefkey (Vctl_x_map, 'o', "other-window");
+ ndefkey (Vctl_x_map, '^', "enlarge-window");
+ ndefkey (Vctl_x_map, '<', "scroll-left");
+ ndefkey (Vctl_x_map, '>', "scroll-right");
+
+ ndefkey (Vglobal_map, Ctl ('V'), "scroll-up");
+ ndefkey (Vesc_map, Ctl ('V'), "scroll-other-window");
+ ndefkey (Vesc_map, 'v', "scroll-down");
+
+ ndefkey (Vglobal_map, Ctl('L'), "recenter");
+ ndefkey (Vesc_map, 'r', "move-to-window-line");
+}
diff --git a/src/window.h b/src/window.h
new file mode 100644
index 00000000000..18cc318ad2c
--- /dev/null
+++ b/src/window.h
@@ -0,0 +1,204 @@
+/* Window definitions for GNU Emacs.
+ Copyright (C) 1985, 1986 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* Windows are allocated as if they were vectors, but then the
+Lisp data type is changed to Lisp_Window. They are garbage
+collected along with the vectors.
+
+All windows in use are arranged into a tree, with pointers up and down.
+
+Windows that are leaves of the tree are actually displayed
+and show the contents of buffers. Windows that are not leaves
+are used for representing the way groups of leaf windows are
+arranged on the screen. Leaf windows never become non-leaves.
+They are deleted only by calling delete-window on them (but
+this can be done implicitly). Combination windows can be created
+and deleted at any time.
+
+A leaf window has a non-nil buffer field, and also
+ has markers in its start and pointm fields. Non-leaf windows
+ have nil in these fields.
+
+Non-leaf windows are either vertical or horizontal combinations.
+
+A vertical combination window has children that are arranged
+one above the next. Its vchild field points to the uppermost child.
+The parent field of each of the children points to the vertical
+combination window. The next field of each child points to the
+child below it, or is nil for the lowest child. The prev field
+or each child points to the child above it, or is nil for the highest child.
+
+A horizontal combination window has children that are side by side.
+Its hchild field points to the leftmost child. In each child
+the next field points to the child to the right and the prev field
+points to the child to the left.
+
+The children of a vertical combination window may be leaf windows
+or horizontal combination windows. The children of a horizontal
+combination window may be leaf windows or vertical combination windows.
+
+At the top of the tree are two windows which have nil as parent.
+The second of these is minibuf_window. The first one manages all
+the screen area that is not minibuffer, and is called the root window.
+Different windows can be the root at different times;
+initially the root window is a leaf window, but if more windows
+are created then that leaf window ceases to be root and a newly
+made combination window becomes root instead.
+
+In any case, prev of the minibuf window is the root window and
+next of the root window is the minibuf window. To find the
+root window at any time, do XWINDOW (minibuf_window)->prev.
+
+*/
+
+struct window
+ {
+ /* The first two fields are really the header of a vector */
+ /* The window code does not refer to them. */
+ int size;
+ struct Lisp_Vector *vec_next;
+ /* Following child (to right or down) at same level of tree */
+ Lisp_Object next;
+ /* Preceding child (to left or up) at same level of tree */
+ Lisp_Object prev;
+ /* First child of this window. */
+ /* vchild is used if this is a vertical combination,
+ hchild if this is a horizontal combination. */
+ Lisp_Object hchild, vchild;
+ /* The window this one is a child of. */
+ Lisp_Object parent;
+ /* The upper left corner coordinates of this window,
+ as integers relative to upper left corner of screen = 0, 0 */
+ Lisp_Object left;
+ Lisp_Object top;
+ /* The size of the window */
+ Lisp_Object height;
+ Lisp_Object width;
+ /* The buffer displayed in this window */
+ /* Of the fields vchild, hchild and buffer, only one is non-nil. */
+ Lisp_Object buffer;
+ /* A marker pointing to where in the text to start displaying */
+ Lisp_Object start;
+ /* A marker pointing to where in the text point is in this window,
+ used only when the window is not selected.
+ This exists so that when multiple windows show one buffer
+ each one can have its own value of point. */
+ Lisp_Object pointm;
+ /* Non-nil means next redisplay must use the value of start
+ set up for it in advance. Set by scrolling commands. */
+ Lisp_Object force_start;
+ /* Number of columns display within the window is scrolled to the left. */
+ Lisp_Object hscroll;
+ /* Number saying how recently window was selected */
+ Lisp_Object use_time;
+ /* Unique number of window assigned when it was created */
+ Lisp_Object sequence_number;
+ /* No permanent meaning; used by save-window-excursion's bookkeeping */
+ Lisp_Object temslot;
+ /* text.modified of displayed buffer as of last time display completed */
+ Lisp_Object last_modified;
+ /* Value of point at that time */
+ Lisp_Object last_point;
+/* The rest are currently not used or only half used */
+ /* Screen coords of point at that time */
+ Lisp_Object last_point_x;
+ Lisp_Object last_point_y;
+ /* Screen coords of mark as of last time display completed */
+ /* May be nil if mark does not exist or was not on screen */
+ Lisp_Object last_mark_x;
+ Lisp_Object last_mark_y;
+ /* Number of characters in buffer past bottom of window,
+ as of last redisplay that finished. */
+ Lisp_Object window_end_pos;
+ /* t if window_end_pos is truly valid.
+ This is nil if nontrivial redisplay is preempted
+ since in that case the screen image that window_end_pos
+ did not get onto the screen. */
+ Lisp_Object window_end_valid;
+ /* Vertical position (relative to window top) of that buffer position
+ of the first of those characters */
+ Lisp_Object window_end_vpos;
+ /* Non-nil means must regenerate mode line of this window */
+ Lisp_Object update_mode_line;
+ /* Non-nil means current value of `start'
+ was the beginning of a line when it was chosen. */
+ Lisp_Object start_at_line_beg;
+ };
+
+/* This is the window which displays the minibuffer.
+ It is always the same window. */
+
+extern Lisp_Object minibuf_window;
+
+/* This is the window in which the terminal's cursor should
+ be left when nothing is being done with it. This must
+ always be a leaf window, and its buffer is selected by
+ the top level editing loop at the end of each command. */
+
+extern Lisp_Object selected_window;
+
+/* Non-nil => window to for C-M-v to scroll
+ when the minibuffer is selected. */
+extern Lisp_Object Vminibuf_scroll_window;
+
+extern Lisp_Object Fnext_window ();
+extern Lisp_Object Fselect_window ();
+extern Lisp_Object Fdisplay_buffer ();
+extern Lisp_Object Fset_window_buffer ();
+
+/* Prompt to display in front of the minibuffer contents. */
+extern char *minibuf_prompt;
+
+/* Message to display instead of minibuffer contents. */
+extern char *echo_area_contents;
+
+/* Last message that was displayed in the echo area. */
+extern char *prev_echo_area_contents;
+
+/* Depth in minibuffer invocations. */
+extern int minibuf_level;
+
+/* Nonzero means redisplay all mode lines. */
+extern int update_mode_lines;
+
+/* Minimum value of GPT since last redisplay that finished. */
+
+extern int beg_unchanged;
+
+/* Minimum value of Z-GPT since last redisplay that finished. */
+
+extern int end_unchanged;
+
+/* MODIFF as of last redisplay that finished;
+ if it matches MODIFF, beg_unchanged and end_unchanged
+ contain no useful information */
+extern int unchanged_modified;
+
+/* Nonzero if BEGV-BEG or Z-ZV of current buffer has changed
+ since last redisplay that finished */
+extern int clip_changed;
+
+/* Nonzero if window sizes or contents have changed
+ since last redisplay that finished */
+extern int windows_or_buffers_changed;
+
+/* Number of windows displaying the selected buffer.
+ Normally this is 1, but it can be more. */
+extern int buffer_shared;
diff --git a/src/x11fns.c b/src/x11fns.c
new file mode 100644
index 00000000000..e7ff4f8e174
--- /dev/null
+++ b/src/x11fns.c
@@ -0,0 +1,1019 @@
+/* Functions for the X window system.
+ Copyright (C) 1988, 1990, 1992 Free Software Foundation.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Written by Yakim Martillo; rearranged by Richard Stallman. */
+/* Color and other features added by Robert Krawitz*/
+/* Converted to X11 by Robert French */
+
+#include <stdio.h>
+#include <signal.h>
+#include "config.h"
+
+/* Get FIONREAD, if it is available. */
+#ifdef USG
+#include <termio.h>
+#endif /* USG */
+#include <fcntl.h>
+
+#ifndef VMS
+#include <sys/ioctl.h>
+#endif /* not VMS */
+
+/* Allow m- file to inhibit use of interrupt-driven input. */
+#ifdef BROKEN_FIONREAD
+#undef FIONREAD
+#endif
+
+/* We are unable to use interrupts if FIONREAD is not available,
+ so flush SIGIO so we won't try. */
+#ifndef FIONREAD
+#ifdef SIGIO
+#undef SIGIO
+#endif
+#endif
+
+#include "x11term.h"
+#include "dispextern.h"
+#include "termchar.h"
+
+#ifdef HAVE_SOCKETS
+#include <sys/socket.h> /* Must be done before gettime.h. */
+#endif
+/* Include time.h or sys/time.h or both. */
+#include "gettime.h"
+#include <setjmp.h>
+
+/* Prepare for lisp.h definition of NULL.
+ Sometimes x11term.h includes stddef.h. */
+#ifdef NULL
+#undef NULL
+#endif
+
+#include "lisp.h"
+#include "window.h"
+
+#ifdef HAVE_X_WINDOWS
+
+#define abs(x) ((x < 0) ? ((x)) : (x))
+#define sgn(x) ((x < 0) ? (-1) : (1))
+#define min(a,b) ((a) < (b) ? (a) : (b))
+#define max(a,b) ((a) > (b) ? (a) : (b))
+
+/* Non-nil if Emacs is running with an X window for display.
+ Nil if Emacs is run on an ordinary terminal. */
+
+Lisp_Object Vxterm;
+
+Lisp_Object Vx_mouse_pos;
+Lisp_Object Vx_mouse_abs_pos;
+
+Lisp_Object Vx_mouse_item;
+
+/* These are standard "white" and "black" strings, used in the
+ *_color variables when the color was not specially allocated for them. */
+char *white_color = "white";
+char *black_color = "black";
+
+extern Lisp_Object MouseMap;
+
+extern Lisp_Object minibuf_window;
+extern int minibuf_prompt_width;
+
+extern XEvent *XXm_queue[XMOUSEBUFSIZE];
+extern int XXm_queue_num;
+extern int XXm_queue_in;
+extern int XXm_queue_out;
+extern char *fore_color;
+extern char *back_color;
+extern char *brdr_color;
+extern char *mous_color;
+extern char *curs_color;
+
+extern unsigned long fore;
+extern unsigned long back;
+extern unsigned long brdr;
+extern unsigned long curs;
+
+extern int XXborder;
+extern int XXInternalBorder;
+
+extern char *progname;
+
+extern XFontStruct *fontinfo;
+extern Font XXfid;
+extern GC XXgc_norm,XXgc_rev,XXgc_curs,XXgc_temp,XXgc_curs_rev;
+extern XGCValues XXgcv;
+extern int XXfontw,XXfonth,XXbase,XXisColor;
+extern Colormap XXColorMap;
+
+extern int PendingExposure;
+extern char *default_window;
+extern char *desiredwindow;
+
+extern int XXscreen;
+extern Window XXwindow;
+extern Cursor EmacsCursor;
+extern short MouseCursor[], MouseMask[];
+extern char *XXcurrentfont;
+extern int informflag;
+
+extern int WindowMapped;
+extern int CurHL;
+extern int pixelwidth, pixelheight;
+extern int XXpid;
+
+extern char *XXidentity;
+
+extern Display *XXdisplay;
+extern int bitblt, CursorExists, VisibleX, VisibleY;
+
+check_xterm ()
+{
+ if (NULL (Vxterm))
+ error ("Terminal does not understand X protocol.");
+}
+
+DEFUN ("x-set-bell", Fx_set_bell, Sx_set_bell, 1, 1, "P",
+ "For X window system, set audible vs visible bell.\n\
+With non-nil argument (prefix arg), use visible bell; otherwise, audible bell.")
+ (arg)
+ Lisp_Object arg;
+{
+ BLOCK_INPUT_DECLARE ();
+
+ check_xterm ();
+ BLOCK_INPUT ();
+ if (!NULL (arg))
+ XSetFlash ();
+ else
+ XSetFeep ();
+ UNBLOCK_INPUT ();
+ return arg;
+}
+
+DEFUN ("x-flip-color", Fx_flip_color, Sx_flip_color, 0, 0, "",
+ "Toggle the background and foreground colors")
+ ()
+{
+ check_xterm ();
+ XFlipColor ();
+ return Qt;
+}
+
+DEFUN ("x-set-foreground-color", Fx_set_foreground_color,
+ Sx_set_foreground_color, 1, 1, "sSet foreground color: ",
+ "Set foreground (text) color to COLOR.")
+ (arg)
+ Lisp_Object arg;
+{
+ XColor cdef;
+ BLOCK_INPUT_DECLARE ();
+ char *save_color;
+ unsigned long save;
+
+ save_color = fore_color;
+ save = fore;
+ check_xterm ();
+ CHECK_STRING (arg,1);
+ fore_color = (char *) xmalloc (XSTRING (arg)->size + 1);
+ bcopy (XSTRING (arg)->data, fore_color, XSTRING (arg)->size + 1);
+
+ BLOCK_INPUT ();
+
+ if (fore_color && XXisColor &&
+ XParseColor (XXdisplay, XXColorMap, fore_color, &cdef) &&
+ XAllocColor(XXdisplay, XXColorMap, &cdef))
+ fore = cdef.pixel;
+ else if (fore_color && !strcmp (fore_color, "white"))
+ fore = WhitePixel (XXdisplay, XXscreen), fore_color = white_color;
+ else if (fore_color && !strcmp (fore_color, "black"))
+ fore = BlackPixel (XXdisplay, XXscreen), fore_color = black_color;
+ else
+ fore_color = save_color;
+
+ /* Now free the old background color
+ if it was specially allocated and we are not still using it. */
+ if (save_color != white_color && save_color != black_color
+ && save_color != fore_color)
+ {
+ XFreeColors (XXdisplay, XXColorMap, &save, 1, 0);
+ free (save_color);
+ }
+
+ XSetForeground(XXdisplay, XXgc_norm, fore);
+ XSetBackground(XXdisplay, XXgc_rev, fore);
+
+ Fredraw_display ();
+ UNBLOCK_INPUT ();
+
+ XFlush (XXdisplay);
+ return Qt;
+}
+
+DEFUN ("x-set-background-color", Fx_set_background_color,
+ Sx_set_background_color, 1, 1, "sSet background color: ",
+ "Set background color to COLOR.")
+ (arg)
+ Lisp_Object arg;
+{
+ XColor cdef;
+ BLOCK_INPUT_DECLARE ();
+ char *save_color;
+ unsigned long save;
+
+ check_xterm ();
+ CHECK_STRING (arg,1);
+ save_color = back_color;
+ save = back;
+ back_color = (char *) xmalloc (XSTRING (arg)->size + 1);
+ bcopy (XSTRING (arg)->data, back_color, XSTRING (arg)->size + 1);
+
+ BLOCK_INPUT ();
+
+ if (back_color && XXisColor &&
+ XParseColor (XXdisplay, XXColorMap, back_color, &cdef) &&
+ XAllocColor(XXdisplay, XXColorMap, &cdef))
+ back = cdef.pixel;
+ else if (back_color && !strcmp (back_color, "white"))
+ back = WhitePixel (XXdisplay, XXscreen), back_color = white_color;
+ else if (back_color && !strcmp (back_color, "black"))
+ back = BlackPixel (XXdisplay, XXscreen), back_color = black_color;
+ else
+ back_color = save_color;
+
+ /* Now free the old background color
+ if it was specially allocated and we are not still using it. */
+ if (save_color != white_color && save_color != black_color
+ && save_color != back_color)
+ {
+ XFreeColors (XXdisplay, XXColorMap, &save, 1, 0);
+ free (save_color);
+ }
+
+ XSetBackground (XXdisplay, XXgc_norm, back);
+ XSetForeground (XXdisplay, XXgc_rev, back);
+ XSetForeground (XXdisplay, XXgc_curs, back);
+ XSetBackground (XXdisplay, XXgc_curs_rev, back);
+ XSetWindowBackground(XXdisplay, XXwindow, back);
+ XClearArea (XXdisplay, XXwindow, 0, 0,
+ screen_width*XXfontw+2*XXInternalBorder,
+ screen_height*XXfonth+2*XXInternalBorder, 0);
+
+ UNBLOCK_INPUT ();
+ Fredraw_display ();
+
+ XFlush (XXdisplay);
+ return Qt;
+}
+
+DEFUN ("x-set-border-color", Fx_set_border_color, Sx_set_border_color, 1, 1,
+ "sSet border color: ",
+ "Set border color to COLOR.")
+ (arg)
+ Lisp_Object arg;
+{
+ XColor cdef;
+ BLOCK_INPUT_DECLARE ();
+ unsigned long save;
+ char *save_color;
+
+ check_xterm ();
+ CHECK_STRING (arg,1);
+ brdr_color= (char *) xmalloc (XSTRING (arg)->size + 1);
+ save = brdr;
+ save_color = brdr_color;
+ bcopy (XSTRING (arg)->data, brdr_color, XSTRING (arg)->size + 1);
+
+ BLOCK_INPUT ();
+
+ if (brdr_color && XXisColor &&
+ XParseColor (XXdisplay, XXColorMap, brdr_color, &cdef) &&
+ XAllocColor(XXdisplay, XXColorMap, &cdef))
+ brdr = cdef.pixel;
+ else
+ {
+ if (brdr_color && !strcmp (brdr_color, "black"))
+ {
+ brdr = BlackPixel (XXdisplay, XXscreen);
+ brdr_color = black_color;
+ }
+ else
+ if (brdr_color && !strcmp (brdr_color, "white"))
+ {
+ brdr = WhitePixel (XXdisplay, XXscreen);
+ brdr_color = white_color;
+ }
+ else {
+ brdr_color = black_color;
+ brdr = BlackPixel (XXdisplay, XXscreen);
+ }
+ }
+
+ /* Now free the old background color
+ if it was specially allocated and we are not still using it. */
+ if (save_color != white_color && save_color != black_color
+ && save_color != brdr_color)
+ {
+ XFreeColors (XXdisplay, XXColorMap, &save, 1, 0);
+ free (save_color);
+ }
+
+ if (XXborder) {
+ XSetWindowBorder(XXdisplay, XXwindow, brdr);
+ XFlush (XXdisplay);
+ }
+
+ UNBLOCK_INPUT ();
+
+ return Qt;
+}
+
+DEFUN ("x-set-cursor-color", Fx_set_cursor_color, Sx_set_cursor_color, 1, 1,
+ "sSet text cursor color: ",
+ "Set text cursor color to COLOR.")
+ (arg)
+ Lisp_Object arg;
+{
+ XColor cdef;
+ BLOCK_INPUT_DECLARE ();
+ char *save_color;
+ unsigned long save;
+
+ check_xterm ();
+ CHECK_STRING (arg,1);
+ save_color = curs_color;
+ save = curs;
+ curs_color = (char *) xmalloc (XSTRING (arg)->size + 1);
+ bcopy (XSTRING (arg)->data, curs_color, XSTRING (arg)->size + 1);
+
+ BLOCK_INPUT ();
+
+ if (curs_color && XXisColor &&
+ XParseColor (XXdisplay, XXColorMap, curs_color, &cdef) &&
+ XAllocColor(XXdisplay, XXColorMap, &cdef))
+ curs = cdef.pixel;
+ else if (curs_color && !strcmp (curs_color, "white"))
+ curs = WhitePixel (XXdisplay, XXscreen), curs_color = white_color;
+ else if (curs_color && !strcmp (curs_color, "black"))
+ curs = BlackPixel (XXdisplay, XXscreen), curs_color = black_color;
+ else
+ curs_color = save_color;
+
+ /* Now free the old background color
+ if it was specially allocated and we are not still using it. */
+ if (save_color != white_color && save_color != black_color
+ && save_color != curs_color)
+ {
+ XFreeColors (XXdisplay, XXColorMap, &save, 1, 0);
+ free (save_color);
+ }
+
+ XSetBackground(XXdisplay, XXgc_curs, curs);
+ XSetForeground(XXdisplay, XXgc_curs_rev, curs);
+
+ CursorToggle ();
+ CursorToggle ();
+
+ UNBLOCK_INPUT ();
+ return Qt;
+}
+
+DEFUN ("x-set-mouse-color", Fx_set_mouse_color, Sx_set_mouse_color, 1, 1,
+ "sSet mouse cursor color: ",
+ "Set mouse cursor color to COLOR.")
+ (arg)
+ Lisp_Object arg;
+{
+ BLOCK_INPUT_DECLARE ();
+ char *save_color;
+
+ check_xterm ();
+ CHECK_STRING (arg,1);
+ save_color = mous_color;
+ mous_color = (char *) xmalloc (XSTRING (arg)->size + 1);
+ bcopy (XSTRING (arg)->data, mous_color, XSTRING (arg)->size + 1);
+
+ BLOCK_INPUT ();
+
+ if (! x_set_cursor_colors ())
+ mous_color = save_color;
+ else if (save_color != white_color && save_color != black_color
+ && save_color != mous_color)
+ free (save_color);
+
+ XFlush (XXdisplay);
+
+ UNBLOCK_INPUT ();
+ return Qt;
+}
+
+/* Set the actual X cursor colors from `mous_color' and `back_color'. */
+
+int
+x_set_cursor_colors ()
+{
+ XColor forec, backc;
+
+ char *useback;
+
+ /* USEBACK is the background color, but on monochrome screens
+ changed if necessary not to match the mouse. */
+
+ useback = back_color;
+
+ if (!XXisColor && !strcmp (mous_color, back_color))
+ {
+ if (strcmp (back_color, "white"))
+ useback = white_color;
+ else
+ useback = black_color;
+ }
+
+ if (XXisColor && mous_color
+ && XParseColor (XXdisplay, XXColorMap, mous_color, &forec)
+ && XParseColor (XXdisplay, XXColorMap, useback, &backc))
+ {
+ XRecolorCursor (XXdisplay, EmacsCursor, &forec, &backc);
+ return 1;
+ }
+ else return 0;
+}
+
+DEFUN ("x-color-p", Fx_color_p, Sx_color_p, 0, 0, 0,
+ "Returns t if the display is a color X terminal.")
+ ()
+{
+ check_xterm ();
+
+ if (XXisColor)
+ return Qt;
+ else
+ return Qnil;
+}
+
+DEFUN ("x-get-foreground-color", Fx_get_foreground_color,
+ Sx_get_foreground_color, 0, 0, 0,
+ "Returns the color of the foreground, as a string.")
+ ()
+{
+ Lisp_Object string;
+
+ check_xterm ();
+ string = build_string (fore_color);
+ return string;
+}
+
+DEFUN ("x-get-background-color", Fx_get_background_color,
+ Sx_get_background_color, 0, 0, 0,
+ "Returns the color of the background, as a string.")
+ ()
+{
+ Lisp_Object string;
+
+ check_xterm ();
+ string = build_string (back_color);
+ return string;
+}
+
+DEFUN ("x-get-border-color", Fx_get_border_color,
+ Sx_get_border_color, 0, 0, 0,
+ "Returns the color of the border, as a string.")
+ ()
+{
+ Lisp_Object string;
+
+ check_xterm ();
+ string = build_string (brdr_color);
+ return string;
+}
+
+DEFUN ("x-get-cursor-color", Fx_get_cursor_color,
+ Sx_get_cursor_color, 0, 0, 0,
+ "Returns the color of the cursor, as a string.")
+ ()
+{
+ Lisp_Object string;
+
+ check_xterm ();
+ string = build_string (curs_color);
+ return string;
+}
+
+DEFUN ("x-get-mouse-color", Fx_get_mouse_color,
+ Sx_get_mouse_color, 0, 0, 0,
+ "Returns the color of the mouse cursor, as a string.")
+ ()
+{
+ Lisp_Object string;
+
+ check_xterm ();
+ string = build_string (mous_color);
+ return string;
+}
+
+DEFUN ("x-get-default", Fx_get_default, Sx_get_default, 1, 1, 0,
+ "Get default for X-window attribute ATTRIBUTE from the system.\n\
+ATTRIBUTE must be a string.\n\
+Returns nil if attribute default isn't specified.")
+ (arg)
+ Lisp_Object arg;
+{
+ char *default_name, *value;
+
+ check_xterm ();
+ CHECK_STRING (arg, 1);
+ default_name = (char *) XSTRING (arg)->data;
+
+#ifdef XBACKWARDS
+ /* Some versions of X11R4, at least, have the args backwards. */
+ if (XXidentity && *XXidentity)
+ value = XGetDefault (XXdisplay, default_name, XXidentity);
+ else
+ value = XGetDefault (XXdisplay, default_name, CLASS);
+#else
+ if (XXidentity && *XXidentity)
+ value = XGetDefault (XXdisplay, XXidentity, default_name);
+ else
+ value = XGetDefault (XXdisplay, CLASS, default_name);
+#endif
+
+ if (value)
+ return build_string (value);
+ return (Qnil);
+}
+
+DEFUN ("x-set-font", Fx_set_font, Sx_set_font, 1, 1, "sFont Name: ",
+ "Sets the font to be used for the X window.")
+ (arg)
+ Lisp_Object arg;
+{
+ register char *newfontname;
+
+ CHECK_STRING (arg, 1);
+ check_xterm ();
+
+ newfontname = (char *) xmalloc (XSTRING (arg)->size + 1);
+ bcopy (XSTRING (arg)->data, newfontname, XSTRING (arg)->size + 1);
+ if (XSTRING (arg)->size == 0)
+ goto badfont;
+
+ if (!XNewFont (newfontname)) {
+ free (XXcurrentfont);
+ XXcurrentfont = newfontname;
+ return Qt;
+ }
+badfont:
+ error ("Font \"%s\" is not defined", newfontname);
+ free (newfontname);
+
+ return Qnil;
+}
+
+DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,
+ Scoordinates_in_window_p, 2, 2, 0,
+ "Return non-nil if POSITIONS (a list, (SCREEN-X SCREEN-Y)) is in WINDOW.\n\
+Returned value is list of positions expressed\n\
+relative to window upper left corner.")
+ (coordinate, window)
+ register Lisp_Object coordinate, window;
+{
+ register Lisp_Object xcoord, ycoord;
+ int height;
+
+ if (!CONSP (coordinate))
+ wrong_type_argument (Qlistp, coordinate);
+
+ CHECK_WINDOW (window, 2);
+ xcoord = Fcar (coordinate);
+ ycoord = Fcar (Fcdr (coordinate));
+ CHECK_NUMBER (xcoord, 0);
+ CHECK_NUMBER (ycoord, 1);
+ if ((XINT (xcoord) < XINT (XWINDOW (window)->left)) ||
+ (XINT (xcoord) >= (XINT (XWINDOW (window)->left) +
+ XINT (XWINDOW (window)->width))))
+ return Qnil;
+
+ XFASTINT (xcoord) -= XFASTINT (XWINDOW (window)->left);
+
+ height = XINT (XWINDOW (window)->height);
+
+ if (window != minibuf_window)
+ height --;
+
+ if ((XINT (ycoord) < XINT (XWINDOW (window)->top)) ||
+ (XINT (ycoord) >= XINT (XWINDOW (window)->top) + height))
+ return Qnil;
+
+ XFASTINT (ycoord) -= XFASTINT (XWINDOW (window)->top);
+ return Fcons (xcoord, Fcons (ycoord, Qnil));
+}
+
+DEFUN ("x-mouse-events", Fx_mouse_events, Sx_mouse_events, 0, 0, 0,
+ "Return number of pending mouse events from X window system.")
+ ()
+{
+ register Lisp_Object tem;
+
+ check_xterm ();
+
+ XSET (tem, Lisp_Int, XXm_queue_num);
+
+ return tem;
+}
+
+DEFUN ("x-proc-mouse-event", Fx_proc_mouse_event, Sx_proc_mouse_event,
+ 0, 0, 0,
+ "Pulls a mouse event out of the mouse event buffer and dispatches\n\
+the appropriate function to act upon this event.")
+ ()
+{
+ XEvent event;
+ register Lisp_Object mouse_cmd;
+ register char com_letter;
+ register char key_mask;
+ register Lisp_Object tempx;
+ register Lisp_Object tempy;
+ extern Lisp_Object get_keyelt ();
+ extern int meta_prefix_char;
+
+ check_xterm ();
+
+ if (XXm_queue_num) {
+ event = *XXm_queue[XXm_queue_out];
+ free (XXm_queue[XXm_queue_out]);
+ XXm_queue_out = (XXm_queue_out + 1) % XMOUSEBUFSIZE;
+ XXm_queue_num--;
+ com_letter = 3-(event.xbutton.button & 3);
+ key_mask = (event.xbutton.state & 15) << 4;
+ /* Get rid of the shift-lock bit. */
+ key_mask &= ~0x20;
+ /* Report meta in 2 bit, not in 8 bit. */
+ if (key_mask & 0x80)
+ {
+ key_mask |= 0x20;
+ key_mask &= ~0x80;
+ }
+ com_letter |= key_mask;
+ if (event.type == ButtonRelease)
+ com_letter |= 0x04;
+ XSET (tempx, Lisp_Int,
+ min (screen_width-1,
+ max (0, (event.xbutton.x-XXInternalBorder)/
+ XXfontw)));
+ XSET (tempy, Lisp_Int,
+ min (screen_height-1,
+ max (0, (event.xbutton.y-XXInternalBorder)/
+ XXfonth)));
+ Vx_mouse_pos = Fcons (tempx, Fcons (tempy, Qnil));
+ XSET (tempx, Lisp_Int, event.xbutton.x_root);
+ XSET (tempy, Lisp_Int, event.xbutton.y_root);
+ Vx_mouse_abs_pos = Fcons (tempx, Fcons (tempy, Qnil));
+ Vx_mouse_item = make_number (com_letter);
+ mouse_cmd
+ = get_keyelt (access_keymap (MouseMap, com_letter));
+ if (NULL (mouse_cmd)) {
+ if (event.type != ButtonRelease)
+ bell ();
+ Vx_mouse_pos = Qnil;
+ }
+ else
+ return call1 (mouse_cmd, Vx_mouse_pos);
+ }
+ return Qnil;
+}
+
+DEFUN ("x-get-mouse-event", Fx_get_mouse_event, Sx_get_mouse_event,
+ 1, 1, 0,
+ "Get next mouse event out of mouse event buffer (com-letter (x y)).\n\
+ARG non-nil means return nil immediately if no pending event;\n\
+otherwise, wait for an event.")
+ (arg)
+ Lisp_Object arg;
+{
+ XEvent event;
+ register char com_letter;
+ register char key_mask;
+
+ register Lisp_Object tempx;
+ register Lisp_Object tempy;
+
+ check_xterm ();
+
+ if (NULL (arg))
+ while (!XXm_queue_num)
+ {
+ consume_available_input ();
+ Fsleep_for (make_number (1));
+ }
+ /*** ??? Surely you don't mean to busy wait??? */
+
+ if (XXm_queue_num) {
+ event = *XXm_queue[XXm_queue_out];
+ free (XXm_queue[XXm_queue_out]);
+ XXm_queue_out = (XXm_queue_out + 1) % XMOUSEBUFSIZE;
+ XXm_queue_num--;
+ com_letter = 3-(event.xbutton.button & 3);
+ key_mask = (event.xbutton.state & 15) << 4;
+ /* Report meta in 2 bit, not in 8 bit. */
+ if (key_mask & 0x80)
+ {
+ key_mask |= 0x20;
+ key_mask &= ~0x80;
+ }
+ com_letter |= key_mask;
+ if (event.type == ButtonRelease)
+ com_letter |= 0x04;
+ XSET (tempx, Lisp_Int,
+ min (screen_width-1,
+ max (0, (event.xbutton.x-XXInternalBorder)/
+ XXfontw)));
+ XSET (tempy, Lisp_Int,
+ min (screen_height-1,
+ max (0, (event.xbutton.y-XXInternalBorder)/
+ XXfonth)));
+ Vx_mouse_pos = Fcons (tempx, Fcons (tempy, Qnil));
+ XSET (tempx, Lisp_Int, event.xbutton.x_root);
+ XSET (tempy, Lisp_Int, event.xbutton.y_root);
+ Vx_mouse_abs_pos = Fcons (tempx, Fcons (tempy, Qnil));
+ Vx_mouse_item = make_number (com_letter);
+ return Fcons (com_letter, Fcons (Vx_mouse_pos, Qnil));
+ }
+ return Qnil;
+}
+
+DEFUN ("x-store-cut-buffer", Fx_store_cut_buffer, Sx_store_cut_buffer,
+ 1, 1, "sSend string to X:",
+ "Store contents of STRING into the cut buffer of the X window system.")
+ (string)
+ register Lisp_Object string;
+{
+ BLOCK_INPUT_DECLARE ();
+
+ CHECK_STRING (string, 1);
+ check_xterm ();
+
+ BLOCK_INPUT ();
+ XStoreBytes (XXdisplay, (char *) XSTRING (string)->data,
+ XSTRING (string)->size);
+ /* Clear the selection owner, so that other applications
+ will use the cut buffer rather than a selection. */
+ XSetSelectionOwner (XXdisplay, XA_PRIMARY, None, CurrentTime);
+ UNBLOCK_INPUT ();
+
+ return Qnil;
+}
+
+DEFUN ("x-get-cut-buffer", Fx_get_cut_buffer, Sx_get_cut_buffer, 0, 0, 0,
+ "Return contents of cut buffer of the X window system, as a string.")
+ ()
+{
+ int len;
+ register Lisp_Object string;
+ BLOCK_INPUT_DECLARE ();
+ register char *d;
+
+ check_xterm ();
+ BLOCK_INPUT ();
+ d = XFetchBytes (XXdisplay, &len);
+ string = make_string (d, len);
+ UNBLOCK_INPUT ();
+
+ return string;
+}
+
+DEFUN ("x-set-border-width", Fx_set_border_width, Sx_set_border_width,
+ 1, 1, "nBorder width: ",
+ "Set width of border to WIDTH, in the X window system.")
+ (borderwidth)
+ register Lisp_Object borderwidth;
+{
+ BLOCK_INPUT_DECLARE ();
+
+ CHECK_NUMBER (borderwidth, 0);
+
+ check_xterm ();
+
+ if (XINT (borderwidth) < 0)
+ XSETINT (borderwidth, 0);
+
+ BLOCK_INPUT ();
+ XSetWindowBorderWidth(XXdisplay, XXwindow, XINT(borderwidth));
+ XFlush(XXdisplay);
+ UNBLOCK_INPUT ();
+
+ return Qt;
+}
+
+
+DEFUN ("x-set-internal-border-width", Fx_set_internal_border_width,
+ Sx_set_internal_border_width, 1, 1, "nInternal border width: ",
+ "Set width of internal border to WIDTH, in the X window system.")
+ (internalborderwidth)
+ register Lisp_Object internalborderwidth;
+{
+ BLOCK_INPUT_DECLARE ();
+
+ CHECK_NUMBER (internalborderwidth, 0);
+
+ check_xterm ();
+
+ if (XINT (internalborderwidth) < 0)
+ XSETINT (internalborderwidth, 0);
+
+ BLOCK_INPUT ();
+ XXInternalBorder = XINT(internalborderwidth);
+ XSetWindowSize(screen_height,screen_width);
+ UNBLOCK_INPUT ();
+
+ return Qt;
+}
+
+#ifdef foobar
+DEFUN ("x-rebind-key", Fx_rebind_key, Sx_rebind_key, 3, 3, 0,
+ "Rebind KEYCODE, with shift bits SHIFT-MASK, to new string NEWSTRING.\n\
+KEYCODE and SHIFT-MASK should be numbers representing the X keyboard code\n\
+and shift mask respectively. NEWSTRING is an arbitrary string of keystrokes.\n\
+If SHIFT-MASK is nil, then KEYCODE's key will be bound to NEWSTRING for\n\
+all shift combinations.\n\
+Shift Lock 1 Shift 2\n\
+Meta 4 Control 8\n\
+\n\
+For values of KEYCODE, see /usr/lib/Xkeymap.txt (remember that the codes\n\
+in that file are in octal!)\n")
+
+ (keycode, shift_mask, newstring)
+ register Lisp_Object keycode;
+ register Lisp_Object shift_mask;
+ register Lisp_Object newstring;
+{
+#ifdef notdef
+ char *rawstring;
+ int rawkey, rawshift;
+ int i;
+ int strsize;
+
+ CHECK_NUMBER (keycode, 1);
+ if (!NULL (shift_mask))
+ CHECK_NUMBER (shift_mask, 2);
+ CHECK_STRING (newstring, 3);
+ strsize = XSTRING (newstring) ->size;
+ rawstring = (char *) xmalloc (strsize);
+ bcopy (XSTRING (newstring)->data, rawstring, strsize);
+ rawkey = ((unsigned) (XINT (keycode))) & 255;
+ if (NULL (shift_mask))
+ for (i = 0; i <= 15; i++)
+ XRebindCode (rawkey, i<<11, rawstring, strsize);
+ else
+ {
+ rawshift = (((unsigned) (XINT (shift_mask))) & 15) << 11;
+ XRebindCode (rawkey, rawshift, rawstring, strsize);
+ }
+#endif notdef
+ return Qnil;
+}
+
+DEFUN ("x-rebind-keys", Fx_rebind_keys, Sx_rebind_keys, 2, 2, 0,
+ "Rebind KEYCODE to list of strings STRINGS.\n\
+STRINGS should be a list of 16 elements, one for each all shift combination.\n\
+nil as element means don't change.\n\
+See the documentation of x-rebind-key for more information.")
+ (keycode, strings)
+ register Lisp_Object keycode;
+ register Lisp_Object strings;
+{
+#ifdef notdef
+ register Lisp_Object item;
+ register char *rawstring;
+ int rawkey, strsize;
+ register unsigned i;
+
+ CHECK_NUMBER (keycode, 1);
+ CHECK_CONS (strings, 2);
+ rawkey = ((unsigned) (XINT (keycode))) & 255;
+ for (i = 0; i <= 15; strings = Fcdr (strings), i++)
+ {
+ item = Fcar (strings);
+ if (!NULL (item))
+ {
+ CHECK_STRING (item, 2);
+ strsize = XSTRING (item)->size;
+ rawstring = (char *) xmalloc (strsize);
+ bcopy (XSTRING (item)->data, rawstring, strsize);
+ XRebindCode (rawkey, i << 11, rawstring, strsize);
+ }
+ }
+#endif notdef
+ return Qnil;
+}
+
+#endif foobar
+
+XExitWithCoreDump ()
+{
+ XCleanUp ();
+ abort ();
+}
+
+DEFUN ("x-debug", Fx_debug, Sx_debug, 1, 1, 0,
+ "ARG non-nil means that X errors should generate a coredump.")
+ (arg)
+ register Lisp_Object arg;
+{
+ int (*handler)();
+
+ check_xterm ();
+ if (!NULL (arg))
+ handler = XExitWithCoreDump;
+ else
+ {
+ extern int XIgnoreError ();
+ handler = XIgnoreError;
+ }
+ XSetErrorHandler(handler);
+ XSetIOErrorHandler(handler);
+ return (Qnil);
+}
+
+XRedrawDisplay ()
+{
+ Fredraw_display ();
+}
+
+XCleanUp ()
+{
+ Fdo_auto_save (Qt);
+
+#ifdef subprocesses
+ kill_buffer_processes (Qnil);
+#endif /* subprocesses */
+}
+
+syms_of_xfns ()
+{
+ /* If not dumping, init_display ran before us, so don't override it. */
+#ifdef CANNOT_DUMP
+ if (noninteractive)
+#endif
+ Vxterm = Qnil;
+
+ DEFVAR_LISP ("x-mouse-item", &Vx_mouse_item,
+ "Encoded representation of last mouse click, corresponding to\n\
+numerical entries in x-mouse-map.");
+ Vx_mouse_item = Qnil;
+ DEFVAR_LISP ("x-mouse-pos", &Vx_mouse_pos,
+ "Current x-y position of mouse by row, column as specified by font.");
+ Vx_mouse_pos = Qnil;
+ DEFVAR_LISP ("x-mouse-abs-pos", &Vx_mouse_abs_pos,
+ "Current x-y position of mouse relative to root window.");
+ Vx_mouse_abs_pos = Qnil;
+
+ defsubr (&Sx_set_bell);
+ defsubr (&Sx_flip_color);
+ defsubr (&Sx_set_font);
+#ifdef notdef
+ defsubr (&Sx_set_icon);
+#endif notdef
+ defsubr (&Scoordinates_in_window_p);
+ defsubr (&Sx_mouse_events);
+ defsubr (&Sx_proc_mouse_event);
+ defsubr (&Sx_get_mouse_event);
+ defsubr (&Sx_store_cut_buffer);
+ defsubr (&Sx_get_cut_buffer);
+ defsubr (&Sx_set_border_width);
+ defsubr (&Sx_set_internal_border_width);
+ defsubr (&Sx_set_foreground_color);
+ defsubr (&Sx_set_background_color);
+ defsubr (&Sx_set_border_color);
+ defsubr (&Sx_set_cursor_color);
+ defsubr (&Sx_set_mouse_color);
+ defsubr (&Sx_get_foreground_color);
+ defsubr (&Sx_get_background_color);
+ defsubr (&Sx_get_border_color);
+ defsubr (&Sx_get_cursor_color);
+ defsubr (&Sx_get_mouse_color);
+ defsubr (&Sx_color_p);
+ defsubr (&Sx_get_default);
+#ifdef notdef
+ defsubr (&Sx_rebind_key);
+ defsubr (&Sx_rebind_keys);
+#endif notdef
+ defsubr (&Sx_debug);
+}
+
+#endif /* HAVE_X_WINDOWS */
diff --git a/src/x11term.c b/src/x11term.c
new file mode 100644
index 00000000000..7d784e78473
--- /dev/null
+++ b/src/x11term.c
@@ -0,0 +1,2709 @@
+/* X Communication module for terminals which understand the X protocol.
+ Copyright (C) 1988, 1990 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Written by Yakim Martillo, mods and things by Robert Krawitz */
+/* Redone for X11 by Robert French */
+/* Thanks to Mark Biggers for all of the Window Manager support */
+
+/*
+ * $Source: /mit/emacs/src/RCS/11xterm.c,v $
+ * $Author: rfrench $
+ * $Locker: $
+ * $Header: x11term.c,v 1.12 88/02/29 14:11:07 rfrench Exp $
+ */
+
+#ifndef lint
+static char *rcsid_xterm_c = "$Header: x11term.c,v 1.12 88/02/29 14:11:07 rfrench Exp $";
+#endif lint
+
+/* On 4.3 this loses if it comes after x11term.h.
+ On hp-ux it loses if it comes after config.h. */
+#include <signal.h>
+#include <sys/ioctl.h>
+
+/* Load sys/types.h if not already loaded.
+ In some systems loading it twice is suicidal. */
+#ifndef makedev
+#include <sys/types.h>
+#endif
+
+#include "config.h"
+
+#ifdef HAVE_X_WINDOWS
+
+/* Get FIONREAD, if it is available.
+ It would be logical to include <sys/ioctl.h> here,
+ but it was moved up above to avoid problems. */
+#ifdef USG
+#include <termio.h>
+#endif /* USG */
+#include <fcntl.h>
+
+#include "lisp.h"
+#undef NULL
+
+/* Allow m- file to inhibit use of interrupt-driven input. */
+#ifdef BROKEN_FIONREAD
+#undef FIONREAD
+#endif
+
+/* We are unable to use interrupts if FIONREAD is not available,
+ so flush SIGIO so we won't try. */
+#ifndef FIONREAD
+#ifdef SIGIO
+#undef SIGIO
+#endif
+#endif
+
+/* This may include sys/types.h, and that somehow loses
+ if this is not done before the other system files.
+ However, perhaps the problem has been avoided by loading types.h above. */
+
+#include "x11term.h"
+
+#include "X11/Xresource.h"
+
+/* Allow the config file to specify whether we can assume X11R4. */
+#ifdef SPECIFY_X11R4
+#if SPECIFY_X11R4 > 0
+#define X11R4
+#endif
+#else /* not SPECIFY_X11R4 */
+/* Try to guess whether this is release 4 or newer. */
+#ifdef PBaseSize
+#define X11R4
+#endif
+#endif /* not SPECIFY_X11R4 */
+
+#ifdef HAVE_SOCKETS
+#include <sys/socket.h> /* Must be done before gettime.h. */
+#endif
+/* Include time.h, sys/time.h, or both. */
+#include "gettime.h"
+
+#ifdef AIX
+static KeySym XMOD_Alt[] = { XK_Alt_L };
+static KeySym XMOD_Shift[] = { XK_Shift_L };
+static KeySym XMOD_ShiftAlt[] = { XK_Alt_L, XK_Shift_L };
+static KeySym XMOD_CtrlAlt[] = { XK_Control_L, XK_Alt_L };
+static KeySym XMOD_Ctrl[] = { XK_Control_L };
+static KeySym XMOD_CtrlShift[] = { XK_Control_L, XK_Shift_L };
+static KeySym XMOD_ShiftCtrlAlt[] = { XK_Control_L, XK_Alt_L, XK_Shift_L };
+#endif
+
+#if 0 /* On some machines, stdio.h doesn't define NULL
+ if stddef.h has been included already! */
+#ifdef NULL /* Sometimes various definitions conflict here. */
+#undef NULL
+#endif
+#endif
+#include <stdio.h>
+#include <ctype.h>
+#include <errno.h>
+#ifdef BSD
+#include <strings.h>
+#endif
+#include <sys/stat.h>
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#include "dispextern.h"
+#include "termhooks.h"
+#include "termopts.h"
+#include "termchar.h"
+
+#include "sink11.h"
+#include "sink11mask.h"
+
+#define min(a,b) ((a)<(b) ? (a) : (b))
+#define max(a,b) ((a)>(b) ? (a) : (b))
+
+extern int errno;
+
+#define sigunblockx(sig) sigblock (SIGEMPTYMASK)
+#define sigblockx(sig) sigblock (sigmask ((sig)))
+
+#define METABIT 0200
+#define MINWIDTH 12 /* In pixels */
+#define MINHEIGHT 5 /* In pixels */
+#define MAXHEIGHT 300 /* In lines */
+
+int pixelwidth,pixelheight;
+char *progname;
+
+XEvent *XXm_queue[XMOUSEBUFSIZE];
+int XXm_queue_num, XXm_queue_in, XXm_queue_out;
+
+char *XXcurrentfont;
+XFontStruct *fontinfo;
+Font XXfid;
+int XXfontw, XXfonth, XXbase, XXisColor;
+
+/* Nonzero means Emacs has explicit keyboard focus. */
+int x_focus_flag;
+
+Colormap XXColorMap;
+char *default_window;
+extern int initialized;
+extern int screen_width, screen_height;
+extern int delayed_size_change;
+
+/* Function for init_keyboard to call with no args (if nonzero). */
+extern void (*keyboard_init_hook) ();
+
+extern char *alternate_display;
+extern int xargc;
+extern char **xargv;
+
+int XXdebug;
+int XXpid;
+
+int WindowMapped;
+
+char *XXidentity; /* Resource name of this invocation of Emacs */
+static char *XXicon_name; /* user-supplied icon info */
+static int XXicon_usebitmap; /* Use bitmap or not */
+static char *XXheader; /* user-supplied window header info */
+
+static int flexlines; /* last line affected by dellines or
+ * inslines functions */
+int VisibleX, VisibleY; /* genuine location of cursor on screen
+ * if it is there */
+
+/* Last cursor position specified by move_cursor.
+ During an update, this does not display a cursor on the screen;
+ But it controls the position that is output. */
+static int local_cursor_hpos;
+static int local_cursor_vpos;
+
+static int SavedX, SavedY; /* Where the cursor was before update
+ * started */
+
+
+int CursorExists; /* during updates cursor is turned off */
+int CursorOutline; /* when the pointer is not in the Emacs
+ * widow the cursor should be drawn in
+ * outline form a la xterm */
+static int InUpdate; /* many of functions here may be invoked
+ * even if no update in progress; when
+ * no update is in progress the action
+ * can be slightly different */
+
+Display *XXdisplay;
+int XXscreen;
+Window XXwindow;
+GC XXgc_norm,XXgc_rev,XXgc_curs,XXgc_temp,XXgc_curs_rev;
+XGCValues XXgcv;
+Cursor EmacsCursor;
+Pixmap SinkPixmap, SinkMaskPixmap;
+
+static XrmDatabase db, db2;
+
+char *fore_color; /* Variables to store color names */
+char *back_color;
+char *brdr_color;
+char *curs_color;
+char *mous_color;
+
+unsigned long fore; /* Variables to store pixel values */
+unsigned long back;
+unsigned long brdr;
+unsigned long curs;
+
+char *desiredwindow;
+
+int CurHL; /* Current Highlighting (ala mode line) */
+
+int XXborder; /* Window border width */
+int XXInternalBorder; /* Internal border width */
+int updated[MAXHEIGHT];
+
+static char *temp_font; /* needed because of loading hacks */
+static char *temp_reverseVideo;
+static char *temp_borderWidth;
+static char *temp_internalBorder;
+static char *temp_useBitmap;
+
+struct _xdeftab
+{
+ char *iname; /* instance name */
+ char *cname; /* class name (fake it) */
+ char **varp; /* variable to set */
+};
+
+static struct _xdeftab xDefaultsValueTable[]
+ = {
+ { "reverseVideo", "ReverseVideo", &temp_reverseVideo },
+ { "borderWidth", "BorderWidth", &temp_borderWidth },
+ { "internalBorder","BorderWidth", &temp_internalBorder },
+ { "bitmapIcon", "BitmapIcon", &temp_useBitmap },
+ { "borderColor", "BorderColor", &brdr_color },
+ { "background", "Background", &back_color },
+ { "foreground", "Foreground", &fore_color },
+ { "pointerColor", "Foreground", &mous_color },
+ { "cursorColor", "Foreground", &curs_color },
+ { "font", "Font", &temp_font },
+ { "geometry", "Geometry", &desiredwindow },
+ { "title", "Title", &XXheader },
+ { "iconName", "Title", &XXicon_name },
+ { NULL, NULL, NULL }
+ };
+
+
+int (*handler)();
+
+static void x_init_1 ();
+static int XInitWindow ();
+
+char *rindex();
+
+/* HLmode -- Changes the GX function for output strings. Could be used to
+ * change font. Check an XText library function call.
+ */
+
+HLmode (new)
+ int new;
+{
+ extern Lisp_Object inverse_video;
+
+ CurHL = new;
+}
+
+/* External interface to control of standout mode.
+ Call this when about to modify line at position VPOS
+ and not change whether it is highlighted. */
+
+XTreassert_line_highlight (highlight, vpos)
+ int highlight, vpos;
+{
+ HLmode (highlight);
+}
+
+/* Call this when about to modify line at position VPOS
+ and change whether it is highlighted. */
+
+XTchange_line_highlight (new_highlight, vpos, first_unused_hpos)
+ int new_highlight, vpos, first_unused_hpos;
+{
+ HLmode (new_highlight);
+ XTmove_cursor (vpos, 0);
+ x_clear_end_of_line (0);
+}
+
+
+/* Used for starting or restarting (after suspension) the X window. Puts the
+ * cursor in a known place, update does not begin with this routine but only
+ * with a call to redisplay.
+ */
+
+XTset_terminal_modes ()
+{
+ int stuffpending;
+#ifdef XDEBUG
+ fprintf (stderr, "XTset_terminal_modes\n");
+#endif
+
+ InUpdate = 0;
+ stuffpending = 0;
+ if (!initialized) {
+ CursorExists = 0;
+ CursorOutline = 1;
+ VisibleX = 0;
+ VisibleY = 0;
+ }
+ XTclear_screen ();
+}
+
+/* XTmove_cursor moves the cursor to the correct location and checks whether an
+ * update is in progress in order to toggle it on.
+ */
+
+XTmove_cursor (row, col)
+ register int row, col;
+{
+ BLOCK_INPUT_DECLARE ();
+#ifdef XDEBUG
+ fprintf (stderr, "XTmove_cursor (X %d, Y %d)\n",col,row);
+#endif
+
+ BLOCK_INPUT ();
+ local_cursor_hpos = col;
+ local_cursor_vpos = row;
+
+ if (InUpdate) {
+ if (CursorExists)
+ CursorToggle ();
+ UNBLOCK_INPUT ();
+ return;
+ /* Generally, XTmove_cursor will be invoked */
+ /* when InUpdate with !CursorExists */
+ /* so that wasteful XFlush is not called */
+ }
+ if ((row == VisibleY) && (col == VisibleX)) {
+ if (!CursorExists)
+ CursorToggle ();
+ XFlush (XXdisplay);
+ UNBLOCK_INPUT ();
+ return;
+ }
+ if (CursorExists)
+ CursorToggle ();
+ VisibleX = col;
+ VisibleY = row;
+ if (!CursorExists)
+ CursorToggle ();
+ XFlush (XXdisplay);
+ UNBLOCK_INPUT ();
+}
+
+/* Used to get the terminal back to a known state after resets. Usually
+ * used when restarting suspended or waiting emacs
+ */
+
+cleanup ()
+{
+ inverse_video = 0;
+ HLmode (0);
+}
+
+/* Erase current line from current column to column END.
+ Leave cursor at END. */
+
+XTclear_end_of_line (end)
+ register int end;
+{
+ register int numcols;
+ BLOCK_INPUT_DECLARE ();
+
+#ifdef XDEBUG
+ fprintf (stderr, "XTclear_end_of_line (to %d)\n",end);
+#endif
+
+ if (local_cursor_vpos < 0 || local_cursor_vpos >= screen_height)
+ return;
+
+ if (end <= local_cursor_hpos)
+ return;
+ if (end >= screen_width)
+ end = screen_width;
+
+ numcols = end - local_cursor_hpos;
+ BLOCK_INPUT ();
+ if (local_cursor_vpos == VisibleY && VisibleX >= local_cursor_hpos && VisibleX < end)
+ if (CursorExists) CursorToggle ();
+ if (CurHL)
+ XFillRectangle (XXdisplay, XXwindow, XXgc_norm,
+ local_cursor_hpos*XXfontw+XXInternalBorder,
+ local_cursor_vpos*XXfonth+XXInternalBorder,
+ XXfontw*numcols,
+ XXfonth);
+ else
+ XClearArea (XXdisplay, XXwindow,
+ local_cursor_hpos*XXfontw+XXInternalBorder,
+ local_cursor_vpos*XXfonth+XXInternalBorder,
+ XXfontw*numcols,
+ XXfonth,
+ 0);
+ XTmove_cursor (local_cursor_vpos, end);
+ UNBLOCK_INPUT ();
+}
+
+/* Erase current line from column START to right margin.
+ Leave cursor at START. */
+
+x_clear_end_of_line (start)
+ register int start;
+{
+ register int numcols;
+ BLOCK_INPUT_DECLARE ();
+
+#ifdef XDEBUG
+ fprintf (stderr, "x_clear_end_of_line (start %d)\n", start);
+#endif
+
+ if (local_cursor_vpos < 0 || local_cursor_vpos >= screen_height)
+ return;
+
+ if (start >= screen_width)
+ return;
+ if (start < 0)
+ start = 0;
+
+ numcols = screen_width - start;
+ BLOCK_INPUT ();
+ if (local_cursor_vpos == VisibleY && VisibleX >= start)
+ if (CursorExists) CursorToggle ();
+ if (CurHL)
+ XFillRectangle (XXdisplay, XXwindow, XXgc_norm,
+ start*XXfontw+XXInternalBorder,
+ local_cursor_vpos*XXfonth+XXInternalBorder,
+ XXfontw*numcols,
+ XXfonth);
+ else
+ XClearArea (XXdisplay, XXwindow,
+ start*XXfontw+XXInternalBorder,
+ local_cursor_vpos*XXfonth+XXInternalBorder,
+ XXfontw*numcols,
+ XXfonth,
+ 0);
+ XTmove_cursor (local_cursor_vpos, start);
+ UNBLOCK_INPUT ();
+}
+
+XTreset_terminal_modes ()
+{
+#ifdef XDEBUG
+ fprintf (stderr, "XTreset_terminal_modes\n");
+#endif
+
+ XTclear_screen ();
+}
+
+XTclear_screen ()
+{
+ BLOCK_INPUT_DECLARE ();
+
+#ifdef XDEBUG
+ fprintf (stderr, "XTclear_screen\n");
+#endif
+
+ BLOCK_INPUT ();
+ HLmode (0);
+ CursorExists = 0;
+
+ local_cursor_hpos = 0;
+ local_cursor_vpos = 0;
+ SavedX = 0;
+ SavedY = 0;
+ VisibleX = 0;
+ VisibleY = 0;
+ XClearWindow(XXdisplay, XXwindow);
+ CursorToggle ();
+ if (!InUpdate)
+ XFlush (XXdisplay);
+ UNBLOCK_INPUT ();
+}
+
+/* used by dumprectangle which is usually invoked upon Expose
+ * events which come from bit blt's or moving an obscuring opaque window
+ */
+
+dumpchars (active_screen, numcols, tempX, tempY, tempHL)
+ register struct matrix *active_screen;
+ register int numcols;
+ register int tempX, tempY, tempHL;
+{
+ if (numcols <= 0)
+ return;
+
+ if (numcols-1+tempX > screen_width)
+ numcols = screen_width-tempX+1;
+
+ if (tempX < 0 || tempX >= screen_width ||
+ tempY < 0 || tempY >= screen_height)
+ return;
+
+ XDrawImageString(XXdisplay, XXwindow, tempHL ? XXgc_rev : XXgc_norm,
+ tempX*XXfontw+XXInternalBorder,
+ tempY*XXfonth+XXInternalBorder+XXbase,
+ (char *) &active_screen->contents[tempY][tempX],
+ numcols);
+}
+
+/* When a line has been changed this function is called. Due to various
+ * bits of braindamage on the parts of both X11 and Emacs, the new
+ * version of the line is simply output if this function is invoked while
+ * in UpDate. Sometimes writechars can be invoked when not in update if
+ * text is to be output at the end of the line. In this case the whole
+ * line is not output. Simply the new text at the current cursor
+ * position given by VisibleX,Y. The cursor is moved to the end of the
+ * new text.
+ */
+
+updateline (first)
+ int first;
+{
+ register int temp_length;
+ BLOCK_INPUT_DECLARE ();
+
+#ifdef XDEBUG
+ fprintf(stderr, "updateline\n");
+#endif /* XDEBUG */
+
+ BLOCK_INPUT ();
+ if ((local_cursor_vpos < 0) || (local_cursor_vpos >= screen_height)
+ || updated[local_cursor_vpos]) {
+ UNBLOCK_INPUT ();
+ return;
+ }
+ if (!first)
+ updated[local_cursor_vpos] = 1;
+ if (CursorExists)
+ CursorToggle ();
+ if (new_screen->enable[local_cursor_vpos])
+ temp_length = new_screen->used[local_cursor_vpos]-first;
+ else
+ temp_length = 0;
+ if (temp_length > 0) {
+ XDrawImageString (XXdisplay, XXwindow,
+ CurHL ? XXgc_rev : XXgc_norm,
+ first*XXfontw+XXInternalBorder,
+ local_cursor_vpos*XXfonth+XXInternalBorder+XXbase,
+ (char *) &new_screen->contents[local_cursor_vpos][first],
+ temp_length);
+ if (temp_length < screen_width)
+ x_clear_end_of_line (temp_length);
+ XTmove_cursor (local_cursor_vpos, temp_length);
+ }
+ else {
+ x_clear_end_of_line (0);
+ XTmove_cursor (local_cursor_vpos, 0);
+ }
+ UNBLOCK_INPUT ();
+}
+
+writechars (start, end)
+ register char *start, *end;
+{
+ BLOCK_INPUT_DECLARE ();
+
+#ifdef XDEBUG
+ fprintf(stderr, "writechars (local_cursor_hpos %d temp_len %d InUpd %d)\n",
+ local_cursor_hpos, end-start+1, InUpdate);
+#endif /* XDEBUG */
+
+ BLOCK_INPUT ();
+
+ if ((local_cursor_vpos < 0) || (local_cursor_vpos >= screen_height))
+ {
+ UNBLOCK_INPUT ();
+ return;
+ }
+
+ if (CursorExists)
+ CursorToggle ();
+
+
+ if (InUpdate)
+ {
+ XDrawImageString (XXdisplay, XXwindow,
+ CurHL ? XXgc_rev : XXgc_norm,
+ local_cursor_hpos*XXfontw+XXInternalBorder,
+ local_cursor_vpos*XXfonth+XXInternalBorder+XXbase,
+ start,
+ (end - start) + 1);
+ XTmove_cursor (local_cursor_vpos, (end - start) + 1);
+
+ UNBLOCK_INPUT ();
+ return;
+ }
+
+ if ((VisibleX < 0) || (VisibleX >= screen_width)) {
+ UNBLOCK_INPUT ();
+ return;
+ }
+ if ((VisibleY < 0) || (VisibleY >= screen_height)) {
+ UNBLOCK_INPUT ();
+ return;
+ }
+ if (((end - start) + VisibleX) >= screen_width)
+ end = start + (screen_width - (VisibleX + 1));
+ if (end >= start) {
+ XDrawImageString (XXdisplay, XXwindow,
+ CurHL ? XXgc_rev : XXgc_norm,
+ (VisibleX * XXfontw+XXInternalBorder),
+ VisibleY * XXfonth+XXInternalBorder+XXbase,
+ start,
+ ((end - start) + 1));
+ VisibleX = VisibleX + (end - start) + 1;
+ }
+ if (!CursorExists)
+ CursorToggle ();
+ UNBLOCK_INPUT ();
+}
+
+static
+XToutput_chars (start, len)
+ register char *start;
+ register int len;
+{
+#ifdef XDEBUG
+ fprintf (stderr, "XToutput_chars (len %d)\n",len);
+#endif
+
+ writechars (start, start+len-1);
+}
+
+XTflash ()
+{
+#ifdef HAVE_TIMEVAL
+#ifdef HAVE_SELECT
+ XGCValues gcv_temp;
+ struct timeval wakeup, now;
+ BLOCK_INPUT_DECLARE ();
+
+#ifdef XDEBUG
+ fprintf (stderr, "XTflash\n");
+#endif
+
+ BLOCK_INPUT ();
+ XXgc_temp = XCreateGC(XXdisplay, XXwindow, 0, &gcv_temp);
+ XSetState(XXdisplay, XXgc_temp, WhitePixel (XXdisplay, XXscreen),
+ BlackPixel(XXdisplay, XXscreen), GXinvert,
+ AllPlanes);
+
+ /* For speed, flash just 1/4 of the window's area, a rectangle in
+ the center. */
+ XFillRectangle (XXdisplay, XXwindow, XXgc_temp,
+ screen_width*XXfontw/4, screen_height*XXfonth/4,
+ screen_width*XXfontw/2, screen_height*XXfonth/2);
+ XFlush (XXdisplay);
+
+ UNBLOCK_INPUT ();
+
+ gettimeofday (&wakeup, (struct timezone *)0);
+
+ /* Compute time to wait until, propagating carry from usecs. */
+ wakeup.tv_usec += 150000;
+ wakeup.tv_sec += (wakeup.tv_usec / 1000000);
+ wakeup.tv_usec %= 1000000;
+
+ /* Keep waiting until past the time wakeup. */
+ while (1)
+ {
+ struct timeval timeout;
+
+ gettimeofday (&timeout, (struct timezone *)0);
+
+ /* In effect, timeout = wakeup - timeout.
+ Break if result would be negative. */
+ if (timeval_subtract (&timeout, wakeup, timeout))
+ break;
+
+ /* Try to wait that long--but we might wake up sooner. */
+ select (0, 0, 0, 0, &timeout);
+ }
+
+ BLOCK_INPUT ();
+
+ XFillRectangle (XXdisplay, XXwindow, XXgc_temp,
+ screen_width*XXfontw/4, screen_height*XXfonth/4,
+ screen_width*XXfontw/2, screen_height*XXfonth/2);
+
+ XFreeGC(XXdisplay, XXgc_temp);
+ XFlush (XXdisplay);
+
+ UNBLOCK_INPUT ();
+#endif
+#endif
+}
+
+XTfeep ()
+{
+ BLOCK_INPUT_DECLARE ();
+#ifdef XDEBUG
+ fprintf (stderr, "XTfeep\n");
+#endif
+ BLOCK_INPUT ();
+ XBell (XXdisplay, 0);
+ XFlush (XXdisplay);
+ UNBLOCK_INPUT ();
+}
+
+/* Artificially creating a cursor is hard, the actual position on the
+ * screen (either where it is or last was) is tracked with VisibleX,Y.
+ * Gnu Emacs code tends to assume a cursor exists in hardward at local_cursor_hpos,Y
+ * and that output text will appear there. During updates, the cursor is
+ * supposed to be blinked out and will only reappear after the update
+ * finishes.
+ */
+
+CursorToggle ()
+{
+ register struct matrix *active_screen;
+
+ if (!WindowMapped) {
+ CursorExists = 0;
+ CursorOutline = 1;
+ return 0;
+ /* Currently the return values are not */
+ /* used, but I could anticipate using */
+ /* them in the future. */
+ }
+
+ if (VisibleX < 0 || VisibleX >= screen_width ||
+ VisibleY < 0 || VisibleY >= screen_height) {
+ /* Not much can be done */
+ XFlush (XXdisplay);
+ CursorExists = 0;
+ return 0;
+ }
+
+ active_screen = current_screen;
+
+ if (active_screen->highlight[VisibleY])
+ /* If the cursor is in the modeline, it means display was preempted.
+ Don't actually display the cursor there, just say we did.
+ The code below doesn't display it right, and nobody wants
+ to see it anyway. */
+ ;
+ else if (active_screen->enable[VisibleY]
+ && VisibleX < active_screen->used[VisibleY]) {
+ if (CursorExists)
+ XDrawImageString(XXdisplay, XXwindow, XXgc_norm,
+ VisibleX*XXfontw+XXInternalBorder,
+ VisibleY*XXfonth+XXInternalBorder+XXbase,
+ (char *) &active_screen->contents[VisibleY][VisibleX],
+ 1);
+ else if (CursorOutline) {
+ XDrawImageString(XXdisplay, XXwindow, XXgc_norm,
+ VisibleX*XXfontw+XXInternalBorder,
+ VisibleY*XXfonth+XXInternalBorder+XXbase,
+ (char *) &active_screen->contents[VisibleY][VisibleX],
+ 1);
+ XDrawRectangle (XXdisplay, XXwindow, XXgc_curs_rev,
+ VisibleX*XXfontw+XXInternalBorder,
+ VisibleY*XXfonth+XXInternalBorder,
+ XXfontw - 1, XXfonth - 1);
+ } else
+ XDrawImageString(XXdisplay, XXwindow, XXgc_curs,
+ VisibleX*XXfontw+XXInternalBorder,
+ VisibleY*XXfonth+XXInternalBorder+XXbase,
+ (char *) &active_screen->contents[VisibleY][VisibleX],
+ 1);
+ }
+ else {
+ if (CursorExists)
+ XClearArea (XXdisplay, XXwindow,
+ VisibleX*XXfontw+XXInternalBorder,
+ VisibleY*XXfonth+XXInternalBorder,
+ XXfontw, XXfonth, 0);
+ else if (CursorOutline)
+ XDrawRectangle (XXdisplay, XXwindow, XXgc_curs_rev,
+ VisibleX*XXfontw+XXInternalBorder,
+ VisibleY*XXfonth+XXInternalBorder,
+ XXfontw - 1, XXfonth - 1);
+ else
+ XDrawImageString(XXdisplay, XXwindow, XXgc_curs,
+ VisibleX*XXfontw+XXInternalBorder,
+ VisibleY*XXfonth+XXInternalBorder+XXbase,
+ " ", 1);
+ }
+
+ CursorExists = !CursorExists;
+
+ if (!InUpdate)
+ XFlush (XXdisplay);
+
+ return 1;
+}
+
+/* This routine is used by routines which are called to paint regions */
+/* designated by Expose events. If the cursor may be in the exposed */
+/* region, this routine makes sure it is gone so that dumprectangle can */
+/* toggle it back into existance if dumprectangle is invoked when not in */
+/* the midst of a screen update. */
+
+static
+ClearCursor ()
+{
+ BLOCK_INPUT_DECLARE ();
+
+ BLOCK_INPUT ();
+ if (!WindowMapped) {
+ CursorExists = 0;
+ CursorOutline = 1;
+ UNBLOCK_INPUT ();
+ return;
+ }
+
+ if (VisibleX < 0 || VisibleX >= screen_width ||
+ VisibleY < 0 || VisibleY >= screen_height) {
+ /* Not much can be done */
+ CursorExists = 0;
+ UNBLOCK_INPUT ();
+ return;
+ }
+
+ XClearArea (XXdisplay, XXwindow,
+ VisibleX*XXfontw+XXInternalBorder,
+ VisibleY*XXfonth+XXInternalBorder,
+ XXfontw, XXfonth, 0);
+
+ CursorExists = 0;
+ UNBLOCK_INPUT ();
+}
+
+XTupdate_begin ()
+{
+ BLOCK_INPUT_DECLARE ();
+ register int i;
+
+#ifdef XDEBUG
+ fprintf (stderr, "XTupdate_begin\n");
+#endif
+
+ BLOCK_INPUT ();
+ InUpdate = 1;
+ if (CursorExists)
+ CursorToggle ();
+
+ for (i=0;i<MAXHEIGHT;i++)
+ updated[i] = 0;
+
+ SavedX = local_cursor_hpos;
+ SavedY = local_cursor_vpos;
+ /* Thw initial "hardware" cursor position is */
+ /* saved because that is where gnu emacs */
+ /* expects the cursor to be at the end of */
+ /* the update */
+
+ UNBLOCK_INPUT ();
+}
+
+XTupdate_end ()
+{
+ BLOCK_INPUT_DECLARE ();
+
+#ifdef XDEBUG
+ fprintf (stderr, "XTupdate_end\n");
+#endif
+
+ BLOCK_INPUT ();
+ if (CursorExists)
+ CursorToggle ();
+
+ InUpdate = 0;
+ /* Display cursor at last place requested. */
+ XTmove_cursor (local_cursor_vpos, local_cursor_hpos);
+ XFlush (XXdisplay);
+ UNBLOCK_INPUT ();
+}
+
+/* Used for Expose events. Have to get the text
+ * back into the newly blank areas.
+ */
+
+dumprectangle (top, left, rows, cols)
+ register int top, left, rows, cols;
+{
+ register struct matrix *active_screen;
+ register int ourindex;
+ int localX, localY, localHL;
+
+ if (top < 0)
+ top = 0;
+ if (left < 0)
+ left = 0;
+ rows += top;
+ cols += left;
+ top /= XXfonth;
+ /* Get row and col containing up and */
+ /* left borders of exposed region -- */
+ /* round down here*/
+ left /= XXfontw;
+ rows += XXfonth-1;
+ cols += XXfontw-1;
+ rows /= XXfonth;
+ /* Get row and col containing bottom and */
+ /* right borders -- round up here */
+ rows -= top;
+ cols /= XXfontw;
+ cols -= left;
+
+ if (rows < 0)
+ return;
+ if (cols < 0)
+ return;
+ if (top > screen_height - 1)
+ return;
+ if (left > screen_width - 1)
+ return;
+ if (VisibleX >= left && VisibleX < left + cols &&
+ VisibleY >= top && VisibleY < top + rows)
+ ClearCursor ();
+
+ if (InUpdate)
+ active_screen = new_screen;
+ else
+ /* When queue is dumped in update this */
+ active_screen = current_screen;
+
+ for (localY = top, ourindex = 0;
+ ourindex < rows && localY < screen_height;
+ ++ourindex, ++localY) {
+ if (localY < 0 || localY >= screen_height ||
+ !active_screen->enable[localY] ||
+ left+1 > active_screen->used[localY])
+ continue;
+ localX = left;
+ localHL = active_screen->highlight[localY];
+ dumpchars (active_screen,
+ min (cols,
+ active_screen->used[localY]-localX),
+ localX, localY, localHL);
+ }
+ if (!InUpdate && !CursorExists)
+ CursorToggle ();
+ /* Routine usually called */
+ /* when not in update */
+}
+
+/* What sections of the window will be modified from the UpdateDisplay
+ * routine is totally under software control. Any line with Y coordinate
+ * greater than flexlines will not change during an update. This is really
+ * used only during dellines and inslines routines (scraplines and stufflines)
+ */
+
+XTset_terminal_window (n)
+ register int n;
+{
+#ifdef XDEBUG
+ fprintf (stderr, "XTset_terminal_window\n");
+#endif
+
+ if (n <= 0 || n > screen_height)
+ flexlines = screen_height;
+ else
+ flexlines = n;
+}
+
+XTins_del_lines (vpos, n)
+ int vpos, n;
+{
+#ifdef XDEBUG
+ fprintf (stderr, "XTins_del_lines\n");
+#endif
+
+ XTmove_cursor (vpos, 0);
+ if (n >= 0)
+ stufflines (n);
+ else
+ scraplines (-n);
+}
+
+/* Estimate the cost of scrolling as equal to drawing one fifth
+ of the character cells copied if black and white,
+ or half of those characters if color. */
+
+static
+XTcalculate_costs (extra, costvec, ncostvec)
+ int extra;
+ int *costvec, *ncostvec;
+{
+ int color_p = DisplayCells (XXdisplay, XXscreen) > 2;
+
+ CalcLID (0, screen_width / (color_p ? 2 : 5), 0, 0, costvec, ncostvec);
+}
+
+static
+XTinsert_chars (start, len)
+ register char *start;
+ register int len;
+{
+#ifdef XDEBUG
+ fprintf (stderr, "XTinsert_chars\n");
+#endif
+
+ updateline (0);
+}
+
+static
+XTdelete_chars (n)
+ register int n;
+{
+ char *msg = "Major foobars! This shouldn't show up!";
+
+#ifdef XDEBUG
+ fprintf (stderr, "XTdelete_chars (num %d local_cursor_hpos %d)\n",n,local_cursor_hpos);
+#endif
+
+ updateline (0);
+}
+
+stufflines (n)
+ register int n;
+{
+ register int topregion, bottomregion;
+ register int length, newtop;
+ BLOCK_INPUT_DECLARE ();
+
+ if (local_cursor_vpos >= flexlines)
+ return;
+
+ BLOCK_INPUT ();
+
+ if (CursorExists)
+ CursorToggle ();
+
+ topregion = local_cursor_vpos;
+ bottomregion = flexlines-(n+1);
+ newtop = local_cursor_vpos+n;
+ length = bottomregion-topregion+1;
+
+ if (length > 0 && newtop <= flexlines) {
+ XCopyArea (XXdisplay, XXwindow, XXwindow, XXgc_norm,
+ XXInternalBorder,
+ topregion*XXfonth+XXInternalBorder,
+ screen_width*XXfontw,
+ length*XXfonth,
+ XXInternalBorder, newtop*XXfonth+XXInternalBorder);
+ }
+
+ newtop = min (newtop, flexlines-1);
+ length = newtop-topregion;
+ if (length > 0)
+ XClearArea (XXdisplay, XXwindow,
+ XXInternalBorder,
+ topregion*XXfonth+XXInternalBorder,
+ screen_width*XXfontw,
+ n*XXfonth, 0);
+ UNBLOCK_INPUT ();
+}
+
+scraplines (n)
+ register int n;
+{
+ BLOCK_INPUT_DECLARE ();
+
+ if (local_cursor_vpos >= flexlines)
+ return;
+
+ BLOCK_INPUT ();
+
+ if (CursorExists)
+ CursorToggle ();
+
+ if (local_cursor_vpos+n >= flexlines) {
+ if (flexlines >= (local_cursor_vpos + 1))
+ XClearArea (XXdisplay, XXwindow,
+ XXInternalBorder,
+ local_cursor_vpos*XXfonth+XXInternalBorder,
+ screen_width*XXfontw,
+ (flexlines-local_cursor_vpos) * XXfonth,
+ 0);
+ UNBLOCK_INPUT ();
+ }
+ else {
+ XCopyArea (XXdisplay, XXwindow, XXwindow, XXgc_norm,
+ XXInternalBorder,
+ (local_cursor_vpos+n)*XXfonth+XXInternalBorder,
+ screen_width*XXfontw,
+ (flexlines-local_cursor_vpos-n)*XXfonth,
+ XXInternalBorder, local_cursor_vpos*XXfonth+XXInternalBorder);
+
+ XClearArea (XXdisplay, XXwindow, XXInternalBorder,
+ (flexlines-n)*XXfonth+XXInternalBorder,
+ screen_width*XXfontw,
+ n*XXfonth, 0);
+ UNBLOCK_INPUT ();
+ }
+}
+
+/* Substitutes for standard read routine. Under X not interested in individual
+ * bytes but rather individual packets.
+ */
+
+XTread_socket (sd, bufp, numchars)
+ register int sd;
+ register char *bufp;
+ register int numchars;
+{
+#ifdef XDEBUG
+ fprintf(stderr,"XTread_socket\n");
+#endif
+
+ return (internal_socket_read (bufp, numchars));
+}
+
+/*
+ * Interpreting incoming keycodes. Should have table modifiable as needed
+ * from elisp.
+ */
+
+#ifdef sun
+char *stringFuncVal(keycode)
+ KeySym keycode;
+{
+ switch (keycode) {
+ case XK_L1:
+ return("192");
+ case XK_L2:
+ return("193");
+ case XK_L3:
+ return("194");
+ case XK_L4:
+ return("195");
+ case XK_L5:
+ return("196");
+ case XK_L6:
+ return("197");
+ case XK_L7:
+ return("198");
+ case XK_L8:
+ return("199");
+ case XK_L9:
+ return("200");
+ case XK_L10:
+ return("201");
+
+ case XK_R1:
+ return("208");
+ case XK_R2:
+ return("209");
+ case XK_R3:
+ return("210");
+ case XK_R4:
+ return("211");
+ case XK_R5:
+ return("212");
+ case XK_R6:
+ return("213");
+ case XK_R7:
+ return("214");
+ case XK_R8:
+ return("215");
+ case XK_R9:
+ return("216");
+ case XK_R10:
+ return("217");
+ case XK_R11:
+ return("218");
+ case XK_R12:
+ return("219");
+ case XK_R13:
+ return("220");
+ case XK_R14:
+ return("221");
+ case XK_R15:
+ return("222");
+
+ case XK_Break: /* Sun3 "Alternate" key */
+ return("223");
+
+ case XK_F1:
+ return("224");
+ case XK_F2:
+ return("225");
+ case XK_F3:
+ return("226");
+ case XK_F4:
+ return("227");
+ case XK_F5:
+ return("228");
+ case XK_F6:
+ return("229");
+ case XK_F7:
+ return("230");
+ case XK_F8:
+ return("231");
+ case XK_F9:
+ return("232");
+ case XK_F10:
+ return("233");
+
+ default:
+ return("-1");
+ }
+}
+#else
+#ifndef AIX
+char *stringFuncVal(keycode)
+ KeySym keycode;
+{
+ switch (keycode) {
+ case XK_F1:
+ return("11");
+ case XK_F2:
+ return("12");
+ case XK_F3:
+ return("13");
+ case XK_F4:
+ return("14");
+ case XK_F5:
+ return("15");
+ case XK_F6:
+ return("17");
+ case XK_F7:
+ return("18");
+ case XK_F8:
+ return("19");
+ case XK_F9:
+ return("20");
+ case XK_F10:
+ return("21");
+ case XK_F11:
+ return("23");
+ case XK_F12:
+ return("24");
+ case XK_F13:
+ return("25");
+ case XK_F14:
+ return("26");
+ case XK_F15:
+ return("28");
+ case XK_Help:
+ return("28");
+ case XK_F16:
+ return("29");
+ case XK_Menu:
+ return("29");
+ case XK_F17:
+ return("31");
+ case XK_F18:
+ return("32");
+ case XK_F19:
+ return("33");
+ case XK_F20:
+ return("34");
+
+ case XK_Find :
+ return("1");
+ case XK_Insert:
+ return("2");
+ case XK_Delete:
+ return("3");
+ case XK_Select:
+ return("4");
+ case XK_Prior:
+ return("5");
+ case XK_Next:
+ return("6");
+ default:
+ return("-1");
+ }
+}
+#endif /* not AIX */
+#endif /* not sun */
+
+internal_socket_read(bufp, numchars)
+ register unsigned char *bufp;
+ register int numchars;
+{
+ /* Number of keyboard chars we have produced so far. */
+ int count = 0;
+ int nbytes;
+ char mapping_buf[20];
+ BLOCK_INPUT_DECLARE ();
+ XEvent event;
+ /* Must be static since data is saved between calls. */
+ static XComposeStatus status;
+ KeySym keysym;
+ SIGMASKTYPE oldmask;
+
+ BLOCK_INPUT ();
+#ifdef BSD
+#ifndef BSD4_1
+ oldmask = sigblock (sigmask (SIGALRM));
+#endif
+#endif
+#ifdef FIOSNBIO
+ /* If available, Xlib uses FIOSNBIO to make the socket
+ non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set, FIOSNBIO is
+ ignored, and instead of signalling EWOULDBLOCK, a read returns
+ 0, which Xlib interprets as equivalent to EPIPE. */
+ fcntl (fileno (stdin), F_SETFL, 0);
+#endif
+#ifndef HAVE_SELECT
+ if (! (fcntl (fileno (stdin), F_GETFL, 0) & O_NDELAY))
+ {
+ extern int read_alarm_should_throw;
+ read_alarm_should_throw = 1;
+ XPeekEvent (XXdisplay,&event);
+ read_alarm_should_throw = 0;
+ }
+#endif
+ while (XPending (XXdisplay)) {
+ XNextEvent (XXdisplay,&event);
+ event.type &= 0177; /* Mask out XSendEvent indication */
+
+ switch (event.type) {
+
+ default:
+ break;
+
+ case MappingNotify:
+ XRefreshKeyboardMapping(&event.xmapping);
+ break;
+
+ case MapNotify:
+ WindowMapped = 1;
+ break;
+
+ case UnmapNotify:
+ WindowMapped = 0;
+ break;
+
+ case ConfigureNotify:
+ if (abs(pixelheight-event.xconfigure.height) >= XXfonth
+ || abs(pixelwidth-event.xconfigure.width) >= XXfontw)
+ {
+ int rows, cols;
+
+ rows = (event.xconfigure.height-2*XXInternalBorder)/XXfonth;
+ cols = (event.xconfigure.width-2*XXInternalBorder)/XXfontw;
+ pixelwidth = cols*XXfontw+2*XXInternalBorder;
+ pixelheight = rows*XXfonth+2*XXInternalBorder;
+
+ /* This is absolutely, amazingly gross. However, without
+ it, emacs will core dump if the window gets too small.
+ And uwm is too brain-damaged to handle large minimum size
+ windows. */
+ if (cols > 11 && rows > 4)
+ /* Delay the change unless Emacs is waiting for input. */
+ change_screen_size (rows, cols, 0, !waiting_for_input, 1);
+ }
+ break;
+
+ case Expose:
+ if (!delayed_size_change)
+ dumprectangle (event.xexpose.y-XXInternalBorder,
+ event.xexpose.x-XXInternalBorder,
+ event.xexpose.height,
+ event.xexpose.width);
+ break;
+
+ case GraphicsExpose:
+ if (!delayed_size_change)
+ dumprectangle (event.xgraphicsexpose.y-XXInternalBorder,
+ event.xgraphicsexpose.x-XXInternalBorder,
+ event.xgraphicsexpose.height,
+ event.xgraphicsexpose.width);
+ break;
+
+ case NoExpose:
+ break;
+
+#if 0
+ case FocusIn:
+ case FocusOut:
+ case EnterNotify:
+ case LeaveNotify:
+ {
+ int cursor = -1; /* 0=on, 1=off, -1=no change */
+
+ if (event.type == FocusIn) cursor = 0;
+ else if (event.type == FocusOut) cursor = 1;
+ else
+ {
+ Window focus;
+ int revert_to; /* dummy return val */
+ XGetInputFocus (XXdisplay, &focus, &revert_to);
+ if (focus == PointerRoot)
+ cursor = (event.type == LeaveNotify) ? 1 : 0;
+ }
+ if (cursor == -1) break;
+ CursorToggle();
+ CursorOutline = cursor;
+ CursorToggle();
+ }
+#endif
+ case FocusIn:
+ /* kenc@viewlogic.com says adding the following line fixes the
+ problems with grabbing and twm. */
+ if (event.xfocus.mode == NotifyNormal)
+ x_focus_flag = 1;
+ case EnterNotify:
+ if (event.type == FocusIn || (!x_focus_flag && event.xcrossing.focus))
+ {
+ CursorToggle ();
+ CursorOutline = 0;
+ CursorToggle ();
+ }
+ break;
+
+ case FocusOut:
+ x_focus_flag = 0;
+ case LeaveNotify:
+ if (event.type == FocusOut || (!x_focus_flag && event.xcrossing.focus))
+ {
+ CursorToggle ();
+ CursorOutline = 1;
+ CursorToggle ();
+ }
+ break;
+
+ case KeyPress:
+ nbytes = XLookupString (&event.xkey,
+ mapping_buf, 20, &keysym,
+ 0);
+
+#ifndef AIX
+ /* Someday this will be unnecessary as we will
+ be able to use XRebindKeysym so XLookupString
+ will have already given us the string we want. */
+ if (IsFunctionKey(keysym)
+ || IsMiscFunctionKey(keysym)
+ || keysym == XK_Prior
+ || keysym == XK_Next) {
+ strcpy(mapping_buf,"[");
+ strcat(mapping_buf,stringFuncVal(keysym));
+#ifdef sun
+ strcat(mapping_buf,"z");
+#else
+ strcat(mapping_buf,"~");
+#endif /* sun */
+ nbytes = strlen(mapping_buf);
+ }
+ else {
+#endif /* not AIX */
+ switch (keysym) {
+ case XK_Left:
+ strcpy(mapping_buf,"\002");
+ nbytes = 1;
+ break;
+ case XK_Right:
+ strcpy(mapping_buf,"\006");
+ nbytes = 1;
+ break;
+ case XK_Up:
+ strcpy(mapping_buf,"\020");
+ nbytes = 1;
+ break;
+ case XK_Down:
+ strcpy(mapping_buf,"\016");
+ nbytes = 1;
+ break;
+ }
+#ifndef AIX
+ }
+#endif /* not AIX */
+ if (nbytes) {
+ if ((nbytes == 1) && (event.xkey.state & Mod1Mask))
+ *mapping_buf |= METABIT;
+ if ((nbytes == 1) && (event.xkey.state & ControlMask))
+ *mapping_buf &= 0x9F; /* mask off bits 1 and 2 */
+ if (numchars-nbytes > 0) {
+ bcopy (mapping_buf, bufp, nbytes);
+ bufp += nbytes;
+ count += nbytes;
+ numchars -= nbytes;
+ }
+ }
+ break;
+
+ case ButtonPress:
+ case ButtonRelease:
+ *bufp++ = (char) 'X' & 037;
+ ++count;
+ --numchars;
+ *bufp++ = (char) '@' & 037;
+ ++count;
+ --numchars;
+ if (XXm_queue_num == XMOUSEBUFSIZE)
+ break;
+ XXm_queue[XXm_queue_in] = (XEvent *) malloc (sizeof(XEvent));
+ *XXm_queue[XXm_queue_in] = event;
+ XXm_queue_num++;
+ XXm_queue_in = (XXm_queue_in + 1) % XMOUSEBUFSIZE;
+ break;
+ }
+ }
+
+ if (CursorExists)
+ xfixscreen ();
+
+#ifdef BSD
+#ifndef BSD4_1
+ sigsetmask (oldmask);
+#endif
+#endif
+ UNBLOCK_INPUT ();
+ return count;
+}
+
+/* Exit gracefully from gnuemacs, doing an autosave and giving a status.
+ */
+
+XExitGracefully ()
+{
+ XCleanUp();
+ exit (70);
+}
+
+XIgnoreError ()
+{
+ return 0;
+}
+
+static int server_ping_timer;
+
+xfixscreen ()
+{
+ BLOCK_INPUT_DECLARE ();
+
+ if (server_ping_timer > 0)
+ server_ping_timer--;
+ else
+ {
+ server_ping_timer = 100;
+
+ /* Yes, this is really what I mean -- Check to see if we've
+ * lost our connection */
+
+ BLOCK_INPUT ();
+ XSetErrorHandler(0);
+ XSetIOErrorHandler(0);
+ XNoOp (XXdisplay);
+ XFlush (XXdisplay);
+ XSetErrorHandler(handler);
+ XSetIOErrorHandler(handler);
+ if (!InUpdate && !CursorExists)
+ CursorToggle ();
+
+ UNBLOCK_INPUT ();
+ }
+}
+
+
+/* ------------------------------------------------------------
+ */
+static int reversevideo;
+
+static int
+XT_GetDefaults (class)
+ char *class;
+{
+ register struct _xdeftab *entry;
+ char *iname, *cname;
+
+ char *disp = 0, *scrn = 0;
+
+ int len = strlen (CLASS);
+ if (strlen (class) > len)
+ len = strlen (class);
+
+ /* 100 is bigger than any of the resource names in our fixed set. */
+ iname = (char *) alloca (len + 100);
+ cname = (char *) alloca (len + 100);
+
+ XrmInitialize ();
+
+ /* Merge all databases on root window. */
+
+ disp = XResourceManagerString (XXdisplay);
+ if (disp) db = XrmGetStringDatabase (disp);
+
+#if (XlibSpecificationRelease >= 5)
+ scrn = XScreenResourceString (ScreenOfDisplay (XXdisplay, XXscreen));
+ if (scrn) db2 = XrmGetStringDatabase (scrn);
+
+ /* Screen database takes precedence over global database. */
+ XrmMergeDatabases (db2, &db);
+#endif
+
+ /*
+ * Walk the table reading in the resources. Instance names supersede
+ * class names.
+ */
+
+ for (entry = xDefaultsValueTable; entry->iname; entry++)
+ {
+ /* Build the instance name and class name of resource. */
+ XrmValue value;
+ char *dummy;
+ register char *option;
+
+ strcpy (iname, class);
+ strcat (iname, ".");
+ strcat (iname, entry->iname);
+ strcpy (cname, CLASS);
+ strcat (cname, ".");
+ strcat (cname, entry->cname);
+
+ if (XrmGetResource (db, iname, cname, &dummy, &value))
+ {
+ if (entry->varp)
+ *entry->varp = (char*)value.addr;
+ }
+ else
+ {
+#ifdef XBACKWARDS
+ if (!(option = XGetDefault (XXdisplay, entry->iname, class)))
+ if (!(option = XGetDefault (XXdisplay, entry->iname, CLASS)))
+ if (!(option = XGetDefault (XXdisplay, entry->cname, class)))
+ option = XGetDefault (XXdisplay, entry->cname, CLASS);
+#else
+ if (!(option = XGetDefault (XXdisplay, class, entry->iname)))
+ if (!(option = XGetDefault (XXdisplay, CLASS, entry->iname)))
+ if (!(option = XGetDefault (XXdisplay, class, entry->cname)))
+ option = XGetDefault (XXdisplay, CLASS, entry->cname);
+#endif
+ if (option && entry->varp)
+ *entry->varp = option;
+ }
+ }
+
+ /*
+ * Now set global variables that aren't character strings; yes it would
+ * be nice to do this automatically as part of the scanning step, but this
+ * is less likely to screw up. The real answer is to use the resource
+ * manager.
+ */
+
+ if (temp_reverseVideo)
+ {
+ if (strcmp (temp_reverseVideo, "on") == 0)
+ reversevideo = 1;
+ else if (strcmp (temp_reverseVideo, "off") == 0)
+ reversevideo = 0;
+ }
+
+ if (temp_borderWidth)
+ XXborder = atoi (temp_borderWidth);
+
+ if (temp_internalBorder)
+ XXInternalBorder = atoi (temp_internalBorder);
+
+ if (temp_useBitmap)
+ {
+ if (strcmp (temp_useBitmap, "on") == 0)
+ XXicon_usebitmap = 1;
+ else if (strcmp (temp_useBitmap, "off") == 0)
+ XXicon_usebitmap = 0;
+ }
+
+ return 0;
+}
+
+x_error_handler (disp, event)
+ Display *disp;
+ XErrorEvent *event;
+{
+ char msg[200];
+ XGetErrorText (disp, event->error_code, msg, 200);
+ fprintf (stderr, "Fatal X-windows error: %s\n", msg);
+ Fkill_emacs (make_number (70));
+}
+
+x_io_error_handler ()
+{
+ int save_errno = errno;
+ if (errno == EPIPE)
+ kill (0, SIGHUP);
+ Fdo_auto_save ();
+ errno = save_errno;
+ perror ("Fatal X-windows I/O error");
+ kill (0, SIGILL);
+}
+
+x_term_init ()
+{
+ register char *vardisplay;
+ register int xxargc;
+ register char **xxargv;
+ char *ptr;
+ XColor cdef;
+
+ extern char *getenv ();
+ extern XTinterrupt_signal ();
+ extern char *malloc ();
+ extern Lisp_Object Vxterm, Vxterm1, Qt;
+ extern int XIgnoreError();
+ int ix;
+
+
+ vardisplay = (alternate_display ? alternate_display : "");
+ if (!vardisplay) {
+ fprintf (stderr, "DISPLAY environment variable must be set\n");
+ exit (-200);
+ }
+
+ XXdisplay = XOpenDisplay (vardisplay);
+ if (XXdisplay == (Display *) 0) {
+ fprintf (stderr, "X server not responding. Check your DISPLAY environment variable.\n");
+ exit (-99);
+ }
+
+ XXscreen = DefaultScreen (XXdisplay);
+ XXisColor = DisplayCells (XXdisplay, XXscreen) > 2;
+ XXColorMap = DefaultColormap (XXdisplay, XXscreen);
+
+ XSetErrorHandler (x_error_handler);
+ XSetIOErrorHandler (x_io_error_handler);
+ signal (SIGPIPE, x_io_error_handler);
+
+ WindowMapped = 0;
+ baud_rate = 9600;
+ min_padding_speed = 10000;
+ must_write_spaces = 1;
+ meta_key = 1;
+ visible_bell = 1;
+ inverse_video = 0;
+
+ fix_screen_hook = xfixscreen;
+ clear_screen_hook = XTclear_screen;
+ clear_end_of_line_hook = XTclear_end_of_line;
+ ins_del_lines_hook = XTins_del_lines;
+ change_line_highlight_hook = XTchange_line_highlight;
+ insert_chars_hook = XTinsert_chars;
+ output_chars_hook = XToutput_chars;
+ delete_chars_hook = XTdelete_chars;
+ ring_bell_hook = XTfeep;
+ reset_terminal_modes_hook = XTreset_terminal_modes;
+ set_terminal_modes_hook = XTset_terminal_modes;
+ update_begin_hook = XTupdate_begin;
+ update_end_hook = XTupdate_end;
+ set_terminal_window_hook = XTset_terminal_window;
+ read_socket_hook = XTread_socket;
+ move_cursor_hook = XTmove_cursor;
+ reassert_line_highlight_hook = XTreassert_line_highlight;
+ scroll_region_ok = 1; /* we'll scroll partial screens */
+ char_ins_del_ok = 0;
+ line_ins_del_ok = 1; /* we'll just blt 'em */
+ fast_clear_end_of_line = 1; /* X does this well */
+ memory_below_screen = 0; /* we don't remember what scrolls
+ * off the bottom */
+ dont_calculate_costs = 1;
+ calculate_costs_hook = XTcalculate_costs;
+
+ /* New options section */
+ XXborder = 1;
+ XXInternalBorder = 1;
+ screen_width = 80;
+ screen_height = 66;
+
+ reversevideo = 0;
+
+ XXdebug = 0;
+ XXm_queue_num = 0;
+ XXm_queue_in = 0;
+ XXm_queue_out = 0;
+
+#if 0
+ handler = XIgnoreError;
+ XSetErrorHandler (handler);
+ XSetIOErrorHandler (handler);
+#endif
+
+ desiredwindow =
+ XXcurrentfont =
+ XXidentity =
+ XXicon_name =
+ XXheader = (char *) NULL;
+
+ XXicon_usebitmap = 0;
+
+#ifdef X_DEFAULT_FONT
+ temp_font = X_DEFAULT_FONT;
+#else
+ temp_font = "fixed";
+#endif
+ progname = xargv[0];
+ if (ptr = rindex(progname, '/'))
+ progname = ptr+1;
+ XXpid = getpid ();
+ default_window = "=80x24+0+0";
+
+#if 0
+ handler = XIgnoreError;
+ XSetErrorHandler (handler);
+ XSetIOErrorHandler (handler);
+#endif
+
+ /* Get resource name and its defaults, it it exists...
+ */
+ for (ix = 1; ix < xargc && xargv[ix][0] == '-'; ix++)
+ {
+ int valx;
+
+ if (strcmp(xargv[ix], "-rn") == 0 &&
+ (valx = ix + 1) < xargc)
+ {
+ XXidentity = (char *) xmalloc (strlen(xargv[valx]) + 1 );
+ (void) strcpy(XXidentity, xargv[valx]);
+
+ break;
+ }
+ }
+
+ if (!XXidentity)
+ {
+ char *t;
+
+ if ( (t = getenv("WM_RES_NAME")) != (char *) NULL )
+ XXidentity = t;
+
+ if (!XXidentity)
+ {
+ XXidentity = progname;
+ }
+ }
+
+ if (XXidentity)
+ XT_GetDefaults(XXidentity);
+ else
+ XT_GetDefaults(CLASS);
+
+ XXpid = getpid ();
+ default_window = "=80x24+0+0";
+
+ /* Process X command line args...*/
+ xxargc = xargc;
+ xxargv = xargv;
+ xxargv++;
+ xxargc--;
+ while (xxargc) {
+ int sargc;
+ sargc = xxargc;
+ if (xxargc && !strcmp (*xxargv, "-r")) {
+ reversevideo = !reversevideo;
+ xxargc--;
+ xxargv++;
+ }
+ if ((xxargc > 1) && (!strcmp (*xxargv, "-font") ||
+ !strcmp (*xxargv, "-fn"))) {
+ xxargc--;
+ xxargv++;
+ if (XXcurrentfont != NULL)
+ free(XXcurrentfont);
+ XXcurrentfont = (char *) xmalloc (strlen (*xxargv)+1);
+ strcpy (XXcurrentfont, *xxargv);
+ xxargc--;
+ xxargv++;
+ }
+ if ((xxargc > 1) && !strcmp (*xxargv, "-wn")) {
+ xxargc--;
+ xxargv++;
+ XXheader = (char *) xmalloc (strlen (*xxargv)+1);
+ strcpy (XXheader, *xxargv);
+ xxargc--;
+ xxargv++;
+ }
+ if ((xxargc > 1) && !strcmp (*xxargv, "-in")) {
+ xxargc--;
+ xxargv++;
+ XXicon_name = (char *) xmalloc (strlen (*xxargv)+1);
+ strcpy (XXicon_name, *xxargv);
+ xxargc--;
+ xxargv++;
+ }
+ if (xxargc && !strcmp (*xxargv, "-i")) {
+ xxargc--;
+ xxargv++;
+ XXicon_usebitmap = 1;
+ }
+ if ((xxargc > 1) && !strcmp (*xxargv, "-b")) {
+ xxargc--;
+ xxargv++;
+ XXborder = atoi (*xxargv);
+ xxargc--;
+ xxargv++;
+ }
+ if ((xxargc > 1) && !strcmp (*xxargv, "-ib")) {
+ xxargc--;
+ xxargv++;
+ XXInternalBorder = atoi (*xxargv);
+ xxargc--;
+ xxargv++;
+ }
+ if ((xxargc > 1) && (!strcmp (*xxargv, "-w") ||
+ !strcmp (*xxargv, "-geometry"))) {
+ xxargc--;
+ xxargv++;
+ desiredwindow = (char *) xmalloc (strlen (*xxargv)+1);
+ strcpy (desiredwindow, *xxargv);
+ xxargc--;
+ xxargv++;
+ }
+ if (XXisColor) {
+ if ((xxargc > 1 && !strcmp (*xxargv, "-fg"))) {
+ xxargc--;
+ xxargv++;
+
+ fore_color =
+ (char *) xmalloc (strlen (*xxargv)+1);
+ strcpy (fore_color, *xxargv);
+
+ xxargc--;
+ xxargv++;
+ }
+ if ((xxargc > 1 && !strcmp (*xxargv, "-bg"))) {
+ xxargc--;
+ xxargv++;
+
+ back_color =
+ (char *) xmalloc (strlen (*xxargv)+1);
+ strcpy (back_color, *xxargv);
+
+ xxargc--;
+ xxargv++;
+ }
+ if ((xxargc > 1 && !strcmp (*xxargv, "-bd"))) {
+ xxargc--;
+ xxargv++;
+
+ brdr_color =
+ (char *) xmalloc (strlen (*xxargv)+1);
+ strcpy (brdr_color, *xxargv);
+
+ xxargc--;
+ xxargv++;
+ }
+ if ((xxargc > 1 && !strcmp (*xxargv, "-cr"))) {
+ xxargc--;
+ xxargv++;
+
+ curs_color =
+ (char *) xmalloc (strlen (*xxargv)+1);
+ strcpy (curs_color, *xxargv);
+
+ xxargc--;
+ xxargv++;
+ }
+ if ((xxargc > 1 && !strcmp (*xxargv, "-ms"))) {
+ xxargc--;
+ xxargv++;
+
+ mous_color =
+ (char *) xmalloc (strlen (*xxargv)+1);
+ strcpy (mous_color, *xxargv);
+
+ xxargc--;
+ xxargv++;
+ }
+ }
+ if (sargc == xxargc) {
+ xxargc--;
+ xxargv++;
+ }
+ }
+
+ /* Now, actually Parse and Set colors...
+ */
+ if (XXisColor) {
+ if (fore_color || back_color)
+ reversevideo = 0;
+ if (fore_color &&
+ XParseColor (XXdisplay, XXColorMap, fore_color, &cdef) &&
+ XAllocColor (XXdisplay, XXColorMap, &cdef))
+ fore = cdef.pixel;
+ else {
+ fore_color = black_color;
+ fore = BlackPixel (XXdisplay, XXscreen);
+ }
+
+ if (back_color &&
+ XParseColor (XXdisplay, XXColorMap, back_color, &cdef) &&
+ XAllocColor (XXdisplay, XXColorMap, &cdef))
+ back = cdef.pixel;
+ else {
+ back_color = white_color;
+ back = WhitePixel (XXdisplay, XXscreen);
+ }
+
+ if (curs_color &&
+ XParseColor (XXdisplay, XXColorMap, curs_color, &cdef) &&
+ XAllocColor (XXdisplay, XXColorMap, &cdef))
+ curs = cdef.pixel;
+ else {
+ curs_color = black_color;
+ curs = BlackPixel (XXdisplay, XXscreen);
+ }
+
+ if (mous_color &&
+ XParseColor (XXdisplay, XXColorMap, mous_color, &cdef) &&
+ XAllocColor (XXdisplay, XXColorMap, &cdef))
+ ;
+ else mous_color = black_color;
+
+ if (brdr_color &&
+ XParseColor (XXdisplay, XXColorMap, brdr_color, &cdef) &&
+ XAllocColor (XXdisplay, XXColorMap, &cdef))
+ brdr = cdef.pixel;
+ else {
+ brdr_color = black_color;
+ brdr = BlackPixel (XXdisplay, XXscreen);
+ }
+ }
+ else {
+ fore_color = curs_color = mous_color = brdr_color
+ = black_color;
+ fore = curs = brdr = BlackPixel (XXdisplay, XXscreen);
+ back_color = white_color;
+ back = WhitePixel (XXdisplay, XXscreen);
+ }
+
+
+ if (reversevideo) {
+ int tempcolor;
+ char *tempname;
+ brdr = back;
+ brdr_color = back_color;
+ tempcolor = fore;
+ fore = back;
+ back = tempcolor;
+ tempname = fore_color;
+ fore_color = back_color;
+ back_color = tempname;
+ if (!strcmp (mous_color, back_color))
+ mous_color = fore_color;
+ else if (!strcmp (mous_color, fore_color))
+ mous_color = back_color;
+ if (!strcmp (curs_color, back_color))
+ curs_color = fore_color, curs = fore;
+ else if (!strcmp (curs_color, fore_color))
+ curs_color = back_color, curs = back;
+ }
+
+
+ if (!XXcurrentfont)
+ {
+ XXcurrentfont = (char *) xmalloc (strlen (temp_font) + 1);
+
+ if (!XXcurrentfont) {
+ fprintf (stderr, "Memory allocation failure.\n");
+ exit (-150);
+ }
+
+ strcpy (XXcurrentfont, temp_font);
+ }
+
+
+
+ signal (SIGPIPE, XExitGracefully);
+
+#ifndef CANNOT_DUMP
+ if (initialized)
+#endif /* CANNOT_DUMP */
+ Vxterm = Qt;
+
+ Fset (intern ("window-system-version"), make_number (11));
+
+ XInitWindow ();
+
+ keyboard_init_hook = x_init_1;
+}
+
+/* Initialize for keyboard input using X.
+ This is called by init_keyboard via keyboard_init_hook. */
+
+static void
+x_init_1 ()
+{
+#ifdef F_SETOWN
+ extern int old_fcntl_owner;
+#endif
+
+ dup2 (ConnectionNumber(XXdisplay), 0);
+#ifndef SYSV_STREAMS
+ /* Streams somehow keeps track of which descriptor number
+ is being used to talk to X. So it is not safe to substitute
+ descriptor 0. But it is safe to make descriptor 0 a copy of it. */
+ close (ConnectionNumber(XXdisplay));
+ ConnectionNumber(XXdisplay) = 0; /* Looks a little strange?
+ * check the def of the macro;
+ * it is a genuine lvalue */
+#endif
+
+#ifdef USG
+ setpgrp (); /* No arguments but equivalent in this case */
+#else
+ setpgrp (0, getpid ());
+#endif /* USG */
+
+#ifdef F_SETOWN
+ old_fcntl_owner = fcntl (0, F_GETOWN, 0);
+#ifdef F_SETOWN_SOCK_NEG
+ fcntl (0, F_SETOWN, -getpid ()); /* stdin is a socket here */
+#else
+ fcntl (0, F_SETOWN, getpid ());
+#endif /* F_SETOWN_SOCK_NEG */
+#endif /* F_SETOWN */
+
+ /* Enable interrupt_input because otherwise we cannot asynchronously
+ detect C-g sent as a keystroke event from the X server. */
+ Fset_input_mode (Qt, Qnil, Qnil);
+}
+
+XSetFlash ()
+{
+ ring_bell_hook = XTflash;
+}
+
+XSetFeep ()
+{
+ ring_bell_hook = XTfeep;
+}
+
+
+/* ------------------------------------------------------------
+ * Load a font by name. Return the font pointer, or NULL if
+ * it can't be loaded. Do all appropriate calculations.
+ */
+static XFontStruct *
+XT_CalcForFont(fontname)
+ char *fontname;
+{
+ XFontStruct *fontp;
+
+
+ if ( (fontp = XLoadQueryFont(XXdisplay, fontname)) == (XFontStruct *) 0 )
+ {
+ return (XFontStruct *) NULL;
+ }
+
+ XXfid = fontp->fid;
+ XXfonth = fontp->ascent + fontp->descent;
+ XXfontw = fontp->max_bounds.width;
+ XXbase = fontp->ascent;
+
+ return fontp;
+}
+
+
+/* ------------------------------------------------------------
+ */
+XNewFont (newname)
+ register char *newname;
+{
+ XFontStruct *temp;
+ BLOCK_INPUT_DECLARE ();
+
+ BLOCK_INPUT ();
+ XFlush (XXdisplay);
+
+
+ temp = XT_CalcForFont(newname);
+
+ if (temp == (XFontStruct *) NULL)
+ {
+ UNBLOCK_INPUT ();
+ return -1;
+ }
+
+ XSetFont (XXdisplay, XXgc_norm, XXfid);
+ XSetFont (XXdisplay, XXgc_rev, XXfid);
+ XSetFont (XXdisplay, XXgc_curs, XXfid);
+ XSetFont (XXdisplay, XXgc_curs_rev, XXfid);
+
+ XFreeFont (XXdisplay, fontinfo);
+ fontinfo = temp;
+
+
+ XSetWindowSize(screen_height, screen_width);
+
+
+ UNBLOCK_INPUT ();
+ return 0;
+}
+
+/* Flip foreground/background colors */
+
+XFlipColor ()
+{
+ int tempcolor;
+ char *tempname;
+ XColor forec, backc;
+ BLOCK_INPUT_DECLARE ();
+
+ BLOCK_INPUT ();
+ CursorToggle ();
+ XSetWindowBackground(XXdisplay, XXwindow, fore);
+ if (XXborder)
+ XSetWindowBorder(XXdisplay, XXwindow, back);
+
+ brdr = back;
+ brdr_color = back_color;
+ tempcolor = fore;
+ fore = back;
+ back = tempcolor;
+ tempname = fore_color;
+ fore_color = back_color;
+ back_color = tempname;
+ XClearArea (XXdisplay, XXwindow, 0, 0,
+ screen_width*XXfontw+2*XXInternalBorder,
+ screen_height*XXfonth+2*XXInternalBorder, 0);
+
+ XXgc_temp = XXgc_norm;
+ XXgc_norm = XXgc_rev;
+ XXgc_rev = XXgc_temp;
+
+ if (!strcmp (mous_color, back_color))
+ mous_color = fore_color;
+ else if (!strcmp (mous_color, fore_color))
+ mous_color = back_color;
+
+ x_set_cursor_colors ();
+
+ XRedrawDisplay ();
+ if (!strcmp (curs_color, back_color))
+ curs_color = fore_color, curs = fore;
+ else if (!strcmp (curs_color, fore_color))
+ curs_color = back_color, curs = back;
+
+ XSetState (XXdisplay, XXgc_curs, back, curs, GXcopy, AllPlanes);
+ XSetState (XXdisplay, XXgc_curs_rev, curs, back, GXcopy, AllPlanes);
+
+ CursorToggle ();
+ XFlush (XXdisplay);
+ UNBLOCK_INPUT ();
+}
+
+/* ------------------------------------------------------------
+ */
+
+#define NO_MANAGER 1
+
+
+/* ------------------------------------------------------------
+ */
+static XClassHint class_hint;
+
+
+static int
+XT_Set_Class_Hints(w)
+ Window w;
+{
+ extern char *getenv();
+
+
+ if (XXidentity == (char *) NULL)
+ XXidentity = ""; /* XSCH() doesn't like NULL pointers! */
+
+ class_hint.res_name = XXidentity;
+ class_hint.res_class = CLASS;
+
+
+ XSetClassHint(XXdisplay, w, &class_hint);
+}
+
+
+/* ------------------------------------------------------------
+ */
+static int
+XT_Set_Command_Line(w)
+ Window w;
+{
+
+ XSetCommand(XXdisplay, w, xargv, xargc);
+}
+
+
+/* ------------------------------------------------------------
+ */
+static char hostname[100];
+
+static int
+XT_Set_Host(w)
+ Window w;
+{
+
+ gethostname(hostname, 100);
+ hostname[99] = '\0';
+
+ XChangeProperty(XXdisplay, w, XA_WM_CLIENT_MACHINE, XA_STRING, 8,
+ PropModeReplace,
+ (unsigned char *) hostname, strlen(hostname));
+}
+
+
+/* ------------------------------------------------------------
+ * Set header title to window-name (from '-wn'), or if none,
+ * "optional-id: class-of-appl @ host"
+ */
+static int
+XT_Set_Title(w)
+ Window w;
+{
+ char header_info[200];
+
+
+ if (XXheader != (char *) NULL)
+ {
+ strcpy(header_info, XXheader);
+ }
+ else
+ {
+ char *next;
+
+ next = header_info;
+
+ if (strlen(class_hint.res_name) != 0)
+ {
+ sprintf(header_info, "%s: ",
+ class_hint.res_name);
+
+ next += strlen(header_info);
+ }
+
+ sprintf(next, "%s @ %s",
+ class_hint.res_class,
+ hostname);
+ }
+
+
+ XStoreName(XXdisplay, w, header_info);
+}
+
+
+/* ------------------------------------------------------------
+ * Set icon title to icon-name (from '-in'),
+ * or if none, to "invocation-or-class @ host".
+ *
+ */
+static int
+XT_Set_Icon_Title(w)
+ Window w;
+{
+ char title_info[100];
+
+ if (XXicon_name != (char *) NULL)
+ {
+ strcpy(title_info, XXicon_name);
+ }
+ else
+ {
+ if (strlen(class_hint.res_name) != 0)
+ {
+ sprintf(title_info, "%s@", class_hint.res_name);
+ }
+ else
+ {
+ sprintf(title_info, "%s@", class_hint.res_class);
+ }
+
+ strcat(title_info, hostname);
+ }
+
+
+ XChangeProperty(XXdisplay, w, XA_WM_ICON_NAME, XA_STRING, 8,
+ PropModeReplace,
+ (unsigned char *) title_info, strlen(title_info));
+}
+
+
+/* Arg PR carries value returned by XGeometry at startup, or 0. */
+
+static int
+XT_Set_Size_Hints(w, x, y, width, height, do_resize, pr)
+ int x, y; /* only used at Startup: do_resize == FALSE */
+ int width, height;
+ Window w;
+ Bool do_resize;
+ int pr;
+{
+#ifndef X11R4
+ XSizeHints sizehints;
+
+ sizehints.flags = (pr & (WidthValue | HeightValue)) ? USSize : PSize;
+
+ if (!do_resize)
+ sizehints.flags |= (pr & (XValue | YValue)) ? USPosition : PPosition;
+
+ sizehints.flags |= PResizeInc|PMinSize;
+
+
+ sizehints.x = x;
+ sizehints.y = y;
+ sizehints.width = width*XXfontw + 2 * XXInternalBorder;
+ sizehints.height = height*XXfonth + 2 * XXInternalBorder;
+
+ pixelwidth = sizehints.width;
+ pixelheight = sizehints.height;
+ flexlines = height;
+
+
+ change_screen_size (height, width, 0 - (do_resize == False), 0, 0);
+
+ sizehints.width_inc = XXfontw;
+ sizehints.height_inc = XXfonth;
+
+ sizehints.min_width = XXfontw*MINWIDTH+2*XXInternalBorder;
+ sizehints.min_height = XXfonth*MINHEIGHT+2*XXInternalBorder;
+
+#if 0
+ /* old, broken versions */
+ sizehints.min_width = 3 * XXInternalBorder;
+ sizehints.min_height = 3 * XXInternalBorder;
+#endif
+
+ XSetNormalHints(XXdisplay, w, &sizehints);
+
+ if (do_resize)
+ {
+ XResizeWindow(XXdisplay, XXwindow, pixelwidth, pixelheight);
+ XFlush(XXdisplay);
+ }
+#else /* not X11R4 */
+ XSizeHints sizehints;
+ XWindowChanges changes;
+ unsigned int change_mask = 0;
+
+ sizehints.flags = 0;
+
+ if (! do_resize) {
+ changes.x = x;
+ changes.y = y;
+ sizehints.flags |= (pr & (XValue | YValue)) ? USPosition : PPosition;
+ change_mask |= CWX | CWY;
+ }
+
+ sizehints.base_width = 2 * XXInternalBorder;
+ sizehints.base_height = 2 * XXInternalBorder;
+ changes.width = sizehints.base_width + width * XXfontw;
+ changes.height = sizehints.base_height + height * XXfonth;
+ sizehints.flags |= ((pr & (WidthValue | HeightValue)) ? USSize : PSize) |
+ PBaseSize;
+
+ /* If user has specified precise position, ... */
+ if ((pr & XValue) || (pr & YValue))
+ {
+ sizehints.flags |= USSize | USPosition | PWinGravity;
+ /* Tell window manager which corner to keep fixed. */
+ switch (pr & (XNegative | YNegative))
+ {
+ case 0:
+ sizehints.win_gravity = NorthWestGravity;
+ break;
+ case XNegative:
+ sizehints.win_gravity = NorthEastGravity;
+ break;
+ case YNegative:
+ sizehints.win_gravity = SouthWestGravity;
+ break;
+ default:
+ sizehints.win_gravity = SouthEastGravity;
+ break;
+ }
+ }
+
+ change_mask |= CWWidth | CWHeight;
+
+ /*
+ * NOTE: The sizehints.x, sizehints.y, sizehints.width and
+ * sizehints.height fields are OBSOLETE according to the ICCC, and
+ * no window manager should be considering them, even if USSize/PSize
+ * and/or USPosition/PPosition are set. Unfortunately, many
+ * window managers consider them anyway, and programs like xprop
+ * display their values when fetching the normal hints property
+ * from the window. Therefore, I set them here just to make
+ * things a little bit more robust.
+ */
+ if (! do_resize) {
+ sizehints.x = x;
+ sizehints.y = y;
+ }
+ sizehints.width = changes.width;
+ sizehints.height = changes.height;
+
+ pixelwidth = sizehints.base_width;
+ pixelheight = sizehints.base_height;
+ flexlines = height;
+
+ change_screen_size (height, width, 0 - (do_resize == False), 0, 0);
+
+ sizehints.min_width = XXfontw * MINWIDTH + 2 * XXInternalBorder;
+ sizehints.min_height = XXfonth * MINHEIGHT + 2 * XXInternalBorder;
+ sizehints.flags |= PMinSize;
+
+ sizehints.width_inc = XXfontw;
+ sizehints.height_inc = XXfonth;
+ sizehints.flags |= PResizeInc;
+
+ XSetWMNormalHints(XXdisplay, w, &sizehints);
+ XConfigureWindow(XXdisplay, w, change_mask, &changes);
+#endif /* not X11R4 */
+}
+
+
+/* ------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+XT_Set_Zoom_Sizes(w)
+ Window w;
+{
+}
+
+
+/* ------------------------------------------------------------
+ * Set our state and icon parameters.
+ */
+static int
+XT_Set_WM_Hints(w)
+ Window w;
+{
+ XWMHints wmhints;
+
+ wmhints.flags = InputHint | StateHint;
+ if (XXicon_usebitmap)
+ wmhints.flags |= IconPixmapHint | IconMaskHint;
+
+ wmhints.input = True;
+ wmhints.initial_state = NormalState;
+
+ SinkPixmap = XCreateBitmapFromData (XXdisplay, w,
+ sink_bits, sink_width,
+ sink_height);
+
+ SinkMaskPixmap = XCreateBitmapFromData (XXdisplay, w,
+ sink_mask_bits,
+ sink_mask_width,
+ sink_mask_height);
+
+ if (XXicon_usebitmap) {
+ wmhints.icon_pixmap = SinkPixmap;
+ wmhints.icon_mask = SinkMaskPixmap;
+ }
+ else {
+ wmhints.icon_pixmap = 0;
+ wmhints.icon_mask = 0;
+ }
+
+ XSetWMHints(XXdisplay, w, &wmhints);
+}
+
+
+/* ------------------------------------------------------------
+ * Change just the size of the window.
+ */
+XSetWindowSize(rows, cols)
+ int rows, cols;
+{
+ XT_Set_Size_Hints(XXwindow, 0, 0, cols, rows, NO_MANAGER, 0);
+}
+
+
+/* ------------------------------------------------------------
+ */
+static int
+XInitWindow ()
+{
+ extern int xargc;
+ extern char **xargv;
+ int x, y, width, height, pr;
+ char *dp;
+ Window desktop;
+ XColor forec, backc;
+
+
+ retry:
+ fontinfo = XT_CalcForFont(XXcurrentfont);
+ if (fontinfo == (XFontStruct *) NULL)
+ {
+ if (strcmp (XXcurrentfont, "fixed"))
+ {
+ free (XXcurrentfont);
+ XXcurrentfont = (char *) xmalloc (6);
+ strcpy (XXcurrentfont, "fixed");
+ goto retry;
+ }
+ fatal ("X server unable to find requested font `%s'\n",
+ (XXcurrentfont == NULL) ? "(null)" : XXcurrentfont);
+ }
+
+ pr = XGeometry (XXdisplay, 0, desiredwindow, default_window,
+ XXborder, XXfontw, XXfonth,
+ XXInternalBorder*2, XXInternalBorder*2,
+ &x, &y, &width, &height);
+
+ /* Which desktop do we start up on?
+ */
+ if ( (dp = getenv("WM_DESKTOP")) != (char *) NULL )
+ {
+ desktop = atoi(dp);
+ }
+ else
+ {
+ desktop = RootWindow(XXdisplay, DefaultScreen(XXdisplay));
+ }
+
+ XXwindow = XCreateSimpleWindow(XXdisplay, desktop,
+ x, y,
+ width*XXfontw + 2*XXInternalBorder,
+ height*XXfonth + 2*XXInternalBorder,
+ XXborder, brdr, back);
+ if (!XXwindow)
+ {
+ fprintf (stderr, "Could not create X window!\n");
+ fflush (stderr);
+ exit (-97);
+ }
+
+ XXgcv.font = XXfid;
+ XXgcv.foreground = fore;
+ XXgcv.background = back;
+ XXgc_norm = XCreateGC(XXdisplay, XXwindow,
+ GCFont|GCForeground|GCBackground,
+ &XXgcv);
+ XXgcv.foreground = back;
+ XXgcv.background = fore;
+ XXgc_rev = XCreateGC(XXdisplay, XXwindow,
+ GCFont|GCForeground|GCBackground,
+ &XXgcv);
+ XXgcv.foreground = back;
+ XXgcv.background = curs;
+ XXgc_curs = XCreateGC(XXdisplay, XXwindow,
+ GCFont|GCForeground|GCBackground,
+ &XXgcv);
+ XXgcv.foreground = curs;
+ XXgcv.background = back;
+ XXgc_curs_rev = XCreateGC(XXdisplay, XXwindow,
+ GCFont|GCForeground|GCBackground,
+ &XXgcv);
+
+ EmacsCursor = XCreateFontCursor(XXdisplay, XC_left_ptr);
+
+ x_set_cursor_colors ();
+
+ XDefineCursor (XXdisplay, XXwindow, EmacsCursor);
+
+ CursorExists = 0;
+ CursorOutline = 1;
+ VisibleX = 0;
+ VisibleY = 0;
+
+
+ XT_Set_Class_Hints(XXwindow);
+ XT_Set_Command_Line(XXwindow);
+ XT_Set_Host(XXwindow);
+ XT_Set_Title(XXwindow);
+ XT_Set_Icon_Title(XXwindow);
+ XT_Set_Size_Hints(XXwindow, x, y, width, height, False, pr);
+ XT_Set_Zoom_Sizes(XXwindow);
+ XT_Set_WM_Hints(XXwindow);
+
+ XSelectInput(XXdisplay, XXwindow, KeyPressMask |
+ ExposureMask | ButtonPressMask | ButtonReleaseMask |
+ EnterWindowMask | LeaveWindowMask | FocusChangeMask |
+ StructureNotifyMask);
+
+ XMapWindow (XXdisplay, XXwindow);
+ XFlush (XXdisplay);
+
+#ifdef AIX
+#include "xkeys-aix.h"
+#endif /* AIX */
+
+ /* Free XrmGetStringDatabase */
+
+#ifndef NO_X_DESTROY_DATABASE
+ XrmDestroyDatabase (db);
+#if (XlibSpecificationRelease >= 5)
+ XrmDestroyDatabase (db2);
+#endif
+#endif
+}
+
+#endif /* HAVE_X_WINDOWS */
+
+/*#include "xundebug.h"*/
diff --git a/src/x11term.h b/src/x11term.h
new file mode 100644
index 00000000000..46731d99e87
--- /dev/null
+++ b/src/x11term.h
@@ -0,0 +1,22 @@
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <X11/keysym.h>
+#include <X11/cursorfont.h>
+#include <X11/Xutil.h>
+#include "emacssignal.h"
+
+#define XMOUSEBUFSIZE 64
+
+#define BLOCK_INPUT_DECLARE() SIGMASKTYPE BLOCK_INPUT_mask
+#ifdef SIGIO
+#define BLOCK_INPUT() BLOCK_INPUT_mask = sigblock (sigmask (SIGIO))
+#define UNBLOCK_INPUT() sigsetmask (BLOCK_INPUT_mask)
+#else /* not SIGIO */
+#define BLOCK_INPUT() stop_polling ()
+#define UNBLOCK_INPUT() start_polling ()
+#endif /* SIGIO */
+
+#define CLASS "Emacs" /* class id for GNU Emacs, used in .Xdefaults, etc. */
+
+extern char *black_color;
+extern char *white_color;
diff --git a/src/xdisp.c b/src/xdisp.c
new file mode 100644
index 00000000000..17c030aa0b9
--- /dev/null
+++ b/src/xdisp.c
@@ -0,0 +1,2131 @@
+/* Display generation from window structure and buffer text.
+ Copyright (C) 1985, 1986, 1987, 1988, 1990 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#include "config.h"
+#include <stdio.h>
+/*#include <ctype.h>*/
+#undef NULL
+#include "lisp.h"
+#include "window.h"
+#include "termchar.h"
+#include "dispextern.h"
+#include "buffer.h"
+#include "indent.h"
+#include "commands.h"
+#include "macros.h"
+
+extern int interrupt_input;
+extern int command_loop_level;
+
+/* Nonzero means print newline before next minibuffer message. */
+
+int noninteractive_need_newline;
+
+#define min(a, b) ((a) < (b) ? (a) : (b))
+#define max(a, b) ((a) > (b) ? (a) : (b))
+
+/* The buffer position of the first character appearing
+ entirely or partially on the current screen line.
+ Or zero, which disables the optimization for the current screen line. */
+static int this_line_bufpos;
+
+/* Number of characters past the end of this line,
+ including the terminating newline */
+static int this_line_endpos;
+
+/* The vertical position of this screen line. */
+static int this_line_vpos;
+
+/* Hpos value for start of display on this screen line.
+ Usually zero, but negative if first character really began
+ on previous line */
+static int this_line_start_hpos;
+
+/* Buffer that this_line variables are describing. */
+static struct buffer *this_line_buffer;
+
+/* Value of echo_area_contents when it was last acted on.
+ If this is nonzero, there is a message on the screen
+ in the minibuffer and it should be erased as soon
+ as it is no longer requested to appear. */
+char *prev_echo_area_contents;
+
+/* Nonzero means truncate lines in all windows less wide than the screen */
+int truncate_partial_width_windows;
+
+Lisp_Object Vglobal_mode_string;
+
+/* Marker for where to display an arrow on top of the buffer text. */
+Lisp_Object Voverlay_arrow_position;
+
+/* String to display for the arrow. */
+Lisp_Object Voverlay_arrow_string;
+
+/* Values of those variables at last redisplay. */
+Lisp_Object last_arrow_position, last_arrow_string;
+
+/* If cursor motion alone moves point off screen,
+ Try scrolling this many lines up or down if that will bring it back. */
+int scroll_step;
+
+/* Nonzero means send various TERMCAP strings when screen is cleared. */
+int reset_terminal_on_clear;
+
+/* Nonzero if try_window_id has made blank lines at window bottom
+ since the last redisplay that paused */
+static int blank_end_of_window;
+
+/* Number of windows showing the buffer of the selected window.
+ keyboard.c refers to this. */
+int buffer_shared;
+
+/* display_text_line sets these to the screen position (origin 0) of point,
+ whether the window is selected or not.
+ Set one to -1 first to determine whether point was found afterwards. */
+
+static int point_vpos;
+static int point_hpos;
+
+int debug_end_pos;
+
+/* Nonzero means display mode line highlighted */
+int mode_line_inverse_video;
+
+struct position *display_text_line ();
+
+/* Prompt to display in front of the minibuffer contents */
+char *minibuf_prompt;
+
+/* Width in columns of current minibuffer prompt. */
+int minibuf_prompt_width;
+
+/* Message to display instead of minibuffer contents
+ This is what the functions error and message make,
+ and command echoing uses it as well.
+ It overrides the minibuf_prompt as well as the buffer. */
+char *echo_area_contents;
+
+/* True iff we should redraw the mode lines on the next redisplay */
+int update_mode_lines;
+
+/* Smallest number of characters before the gap
+ at any time since last redisplay that finished.
+ Valid for current buffer when try_window_id can be called. */
+int beg_unchanged;
+
+/* Smallest number of characters after the gap
+ at any time since last redisplay that finished.
+ Valid for current buffer when try_window_id can be called. */
+int end_unchanged;
+
+/* MODIFF as of last redisplay that finished;
+ if it matches MODIFF, beg_unchanged and end_unchanged
+ contain no useful information */
+int unchanged_modified;
+
+/* Nonzero if head_clip or tail_clip of current buffer has changed
+ since last redisplay that finished */
+int clip_changed;
+
+/* Nonzero if window sizes or contents have changed
+ since last redisplay that finished */
+int windows_or_buffers_changed;
+
+char *decode_mode_spec ();
+
+DEFUN ("redraw-display", Fredraw_display, Sredraw_display, 0, 0, "",
+ "Clear the screen and output again what is supposed to appear on it.")
+ ()
+{
+ if (screen_height == 0) abort (); /* Some bug zeros some core */
+ if (reset_terminal_on_clear)
+ set_terminal_modes ();
+ clear_screen ();
+ fflush (stdout);
+ clear_screen_records ();
+ if (screen_height == 0) abort (); /* Some bug zeros some core */
+ windows_or_buffers_changed++;
+ /* Mark all windows as INaccurate,
+ so that every window will have its redisplay done. */
+ mark_window_display_accurate (XWINDOW (minibuf_window)->prev, 0);
+ if (screen_height == 0) abort (); /* Some bug zeros some core */
+ return Qnil;
+}
+
+/* Buffer used for messages formatted by `message', and by print. */
+char *message_buf;
+
+/* Nonzero if message_buf is being used by print;
+ zero if being used by message. */
+int message_buf_print;
+
+/* dump an informative message to the minibuf */
+/* VARARGS 1 */
+message (m, a1, a2, a3)
+ char *m;
+{
+ if (noninteractive)
+ {
+ if (noninteractive_need_newline)
+ putchar ('\n');
+ noninteractive_need_newline = 0;
+ printf (m, a1, a2, a3);
+ printf ("\n");
+ fflush (stdout);
+ }
+ else if (FROM_KBD)
+ {
+#ifdef NO_ARG_ARRAY
+ int a[3];
+ a[0] = a1;
+ a[1] = a2;
+ a[2] = a3;
+
+ doprnt (message_buf, screen_width, m, 3, a);
+#else
+ doprnt (message_buf, screen_width, m, 3, &a1);
+#endif /* NO_ARG_ARRAY */
+ echo_area_contents = message_buf;
+ message_buf_print = 0;
+ do {
+ do_pending_window_change ();
+ display_echo_area_contents ();
+ update_screen (1, 1);
+ do_pending_window_change ();
+ } while (screen_garbaged);
+ }
+}
+
+/* Specify m, a string, as a message in the minibuf. */
+message1 (m)
+ char *m;
+{
+ if (noninteractive)
+ {
+ if (noninteractive_need_newline)
+ putchar ('\n');
+ noninteractive_need_newline = 0;
+ printf ("%s\n", m);
+ fflush (stdout);
+ }
+ else if (FROM_KBD)
+ {
+ echo_area_contents = m;
+ do {
+ do_pending_window_change ();
+ display_echo_area_contents ();
+ update_screen (1, 1);
+ do_pending_window_change ();
+ } while (screen_garbaged);
+ }
+}
+
+display_echo_area_contents ()
+{
+ register int vpos;
+
+ if (screen_garbaged)
+ {
+ Fredraw_display ();
+ screen_garbaged = 0;
+ }
+
+ if (echo_area_contents || minibuf_level == 0)
+ {
+ vpos = XFASTINT (XWINDOW (minibuf_window)->top);
+ get_display_line (vpos, 0);
+ display_string (XWINDOW (minibuf_window), vpos,
+ echo_area_contents ? echo_area_contents : "",
+ 0, 0, 0, screen_width);
+
+ /* If desired cursor location is on this line, put it at end of text */
+ if (cursor_vpos == vpos)
+ cursor_hpos = new_screen->used[vpos];
+
+ /* Fill the rest of the minibuffer window with blank lines. */
+ {
+ int i;
+
+ for (i = vpos + 1; i < vpos + XWINDOW (minibuf_window)->height; i++)
+ {
+ get_display_line (i, 0);
+ display_string (XWINDOW (minibuf_window), vpos,
+ "", 0, 0, 0, screen_width);
+ }
+ }
+ }
+ else if (!EQ (minibuf_window, selected_window))
+ windows_or_buffers_changed++;
+
+ if (EQ (minibuf_window, selected_window))
+ this_line_bufpos = 0;
+
+ prev_echo_area_contents = echo_area_contents;
+}
+
+/* Do a screen update, taking possible shortcuts into account.
+ This is the main external entry point for redisplay.
+
+ If the last redisplay displayed an echo area message and that
+ message is no longer requested, we clear the echo area
+ or bring back the minibuffer if that is in use.
+
+ Everyone would like to have a hook here to call eval,
+ but that cannot be done safely without a lot of changes elsewhere.
+ This can be called from signal handlers; with alarms set up;
+ or with synchronous processes running.
+ See the function `echo' in keyboard.c.
+ See Fcall_process; if you called it from here, it could be
+ entered recursively. */
+
+redisplay ()
+{
+ register struct window *w = XWINDOW (selected_window);
+ register int pause;
+ int inhibit_hairy_id = 0;
+ int must_finish = 0;
+ int all_windows;
+ register int tlbufpos, tlendpos;
+ struct position pos;
+ extern int input_pending;
+
+ if (noninteractive)
+ return;
+
+ /* Notice any pending interrupt request to change screen size. */
+ do_pending_window_change ();
+
+ if (screen_garbaged)
+ {
+ Fredraw_display ();
+ screen_garbaged = 0;
+ }
+
+ /* Initially we have nothing to update on the screen. */
+ bzero (new_screen->enable, new_screen->height);
+
+ if (echo_area_contents != 0 || prev_echo_area_contents != 0)
+ {
+ display_echo_area_contents ();
+ must_finish = 1;
+ }
+
+ if (clip_changed || windows_or_buffers_changed)
+ update_mode_lines++;
+
+ /* Detect case that we need to write a star in the mode line. */
+ if (XFASTINT (w->last_modified) < MODIFF
+ && XFASTINT (w->last_modified) <= current_buffer->save_modified)
+ {
+ w->update_mode_line = Qt;
+ if (buffer_shared > 1)
+ update_mode_lines++;
+ }
+
+ all_windows = update_mode_lines || buffer_shared > 1;
+
+ /* If specs for an arrow have changed, do thorough redisplay
+ to ensure we remove any arrow that should no longer exist. */
+ if (Voverlay_arrow_position != last_arrow_position
+ || Voverlay_arrow_string != last_arrow_string)
+ all_windows = 1, clip_changed = 1;
+
+ tlbufpos = this_line_bufpos;
+ tlendpos = this_line_endpos;
+ if (!all_windows && tlbufpos > 0 && NULL (w->update_mode_line)
+ /* Make sure recorded data applies to current buffer, etc */
+ && this_line_buffer == current_buffer
+ && current_buffer == XBUFFER (w->buffer)
+ && NULL (w->force_start)
+ /* Point must be on the line that we have info recorded about */
+ && point >= tlbufpos
+ && point <= Z - tlendpos
+ /* All text outside that line, including its final newline,
+ must be unchanged */
+ && (XFASTINT (w->last_modified) >= MODIFF
+ || (beg_unchanged >= tlbufpos - 1
+ && GPT >= tlbufpos
+ /* If selective display, can't optimize
+ if the changes start at the beginning of the line. */
+ && ((XTYPE (current_buffer->selective_display) == Lisp_Int
+ && XINT (current_buffer->selective_display) > 0
+ ? (beg_unchanged >= tlbufpos
+ && GPT > tlbufpos)
+ : 1))
+ && end_unchanged >= tlendpos
+ && Z - GPT >= tlendpos)))
+ {
+ if (tlbufpos > BEGV && FETCH_CHAR (tlbufpos - 1) != '\n'
+ && (tlbufpos == ZV
+ || FETCH_CHAR (tlbufpos) == '\n'))
+ /* Former continuation line has disappeared by becoming empty */
+ goto cancel;
+ else if (XFASTINT (w->last_modified) < MODIFF
+ || EQ (selected_window, minibuf_window))
+ {
+ point_vpos = -1;
+ display_text_line (w, tlbufpos, this_line_vpos, this_line_start_hpos,
+ pos_tab_offset (w, tlbufpos));
+ /* If line contains point, is not continued,
+ and ends at same distance from eob as before, we win */
+ if (point_vpos >= 0 && this_line_bufpos
+ && this_line_endpos == tlendpos)
+ {
+ /* Done by display_text_line
+ cursor_hpos = point_hpos;
+ cursor_vpos = this_line_vpos;
+ */
+ if (XFASTINT (w->width) != screen_width)
+ preserve_other_columns (w);
+ goto update;
+ }
+ else
+ goto cancel;
+ }
+ else if (point == XFASTINT (w->last_point))
+ {
+ if (!must_finish)
+ return;
+ goto update;
+ }
+ else
+ {
+ pos = *compute_motion (tlbufpos, 0,
+ XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0,
+ point, 2, - (1 << (SHORTBITS - 1)),
+ XFASTINT (w->width) - 1
+ - (XFASTINT (w->width) + XFASTINT (w->left) != screen_width),
+ XINT (w->hscroll),
+ pos_tab_offset (w, tlbufpos));
+ if (pos.vpos < 1)
+ {
+ cursor_hpos = max (XFASTINT (w->left), pos.hpos);
+ cursor_vpos = this_line_vpos;
+ goto update;
+ }
+ else
+ goto cancel;
+ }
+ cancel:
+ /* Text changed drastically or point moved off of line */
+ cancel_line (this_line_vpos);
+ }
+
+ this_line_bufpos = 0;
+
+ if (all_windows)
+ redisplay_all_windows ();
+ else
+ {
+ redisplay_window (selected_window, 1);
+ if (XFASTINT (w->width) != screen_width)
+ preserve_other_columns (w);
+ }
+
+update:
+ /* Prevent various kinds of signals during display update.
+ stdio is not robust about handling signals,
+ which can cause an apparent I/O error. */
+ if (interrupt_input)
+ unrequest_sigio ();
+ stop_polling ();
+
+ pause = update_screen (0, 0);
+
+ /* If screen does not match, prevent doing single-line-update next time.
+ Also, don't forget to check every line to update the arrow. */
+ if (pause)
+ {
+ this_line_bufpos = 0;
+ if (!NULL (last_arrow_position))
+ {
+ last_arrow_position = Qt;
+ last_arrow_string = Qt;
+ }
+ /* If we pause after scrolling, some lines in PhysScreen may be null
+ and then preserve_other_columns won't be able to preserve all
+ the vertical-bar separators. So avoid using it in that case. */
+ if (XFASTINT (w->width) != screen_width)
+ update_mode_lines = 1;
+ }
+
+ /* Now text on screen agrees with windows, so
+ put info into the windows for partial redisplay to follow */
+
+ if (!pause)
+ {
+ struct buffer *b = XBUFFER (w->buffer);
+
+ blank_end_of_window = 0;
+ clip_changed = 0;
+ unchanged_modified = BUF_MODIFF (b);
+ beg_unchanged = BUF_GPT (b) - BUF_BEG (b);
+ end_unchanged = BUF_Z (b) - BUF_GPT (b);
+
+ XFASTINT (w->last_point) = BUF_PT (b);
+ XFASTINT (w->last_point_x) = cursor_hpos;
+ XFASTINT (w->last_point_y) = cursor_vpos;
+
+ if (all_windows)
+ mark_window_display_accurate (XWINDOW (minibuf_window)->prev, 1);
+ else
+ {
+ w->update_mode_line = Qnil;
+ XFASTINT (w->last_modified) = BUF_MODIFF (b);
+ w->window_end_valid = Qt;
+ last_arrow_position = Voverlay_arrow_position;
+ last_arrow_string = Voverlay_arrow_string;
+ }
+ update_mode_lines = 0;
+ windows_or_buffers_changed = 0;
+ }
+
+ /* Start SIGIO interrupts coming again.
+ Having them off during the code above
+ makes it less likely one will discard output,
+ but not impossible, since there might be stuff
+ in the system buffer here.
+ But it is much hairier to try to do anything about that. */
+
+ if (interrupt_input)
+ request_sigio ();
+ start_polling ();
+
+ do_pending_window_change ();
+
+ if (screen_garbaged)
+ redisplay ();
+}
+
+/* Redisplay, but leave alone any recent echo area message
+ unless another message has been requested in its place. */
+
+redisplay_preserve_echo_area ()
+{
+ if (echo_area_contents == 0 && prev_echo_area_contents != 0)
+ {
+ echo_area_contents = prev_echo_area_contents;
+ redisplay ();
+ echo_area_contents = 0;
+ }
+ else
+ redisplay ();
+}
+
+mark_window_display_accurate (window, flag)
+ Lisp_Object window;
+ int flag;
+{
+ register struct window *w;
+
+ for (;!NULL (window); window = w->next)
+ {
+ w = XWINDOW (window);
+
+ if (!NULL (w->buffer))
+ XFASTINT (w->last_modified)
+ = !flag ? 0 : BUF_MODIFF (XBUFFER (w->buffer));
+ w->window_end_valid = Qt;
+ w->update_mode_line = Qnil;
+
+ if (!NULL (w->vchild))
+ mark_window_display_accurate (w->vchild, flag);
+ if (!NULL (w->hchild))
+ mark_window_display_accurate (w->hchild, flag);
+ }
+
+ if (flag)
+ {
+ last_arrow_position = Voverlay_arrow_position;
+ last_arrow_string = Voverlay_arrow_string;
+ }
+ else
+ {
+ /* t is unequal to any useful value of Voverlay_arrow_... */
+ last_arrow_position = Qt;
+ last_arrow_string = Qt;
+ }
+}
+
+int do_id = 1;
+
+/* Do full redisplay of one or all windows.
+ This does not include updating the screen;
+ just generating lines to pass to update_screen. */
+
+/* Entry point to redisplay all windows */
+
+redisplay_all_windows ()
+{
+ buffer_shared = 0;
+
+ redisplay_windows (XWINDOW (minibuf_window)->prev);
+}
+
+redisplay_windows (window)
+ Lisp_Object window;
+{
+ for (; !NULL (window); window = XWINDOW (window)->next)
+ redisplay_window (window, 0);
+}
+
+redisplay_window (window, just_this_one)
+ Lisp_Object window;
+ int just_this_one;
+{
+ register struct window *w = XWINDOW (window);
+ int height;
+ struct buffer *old = current_buffer;
+ register int width = XFASTINT (w->width) - 1
+ - (XFASTINT (w->width) + XFASTINT (w->left) != screen_width);
+ register int startp;
+ register int hscroll = XINT (w->hscroll);
+ struct position pos;
+ int opoint;
+ int tem;
+
+ if (screen_height == 0) abort (); /* Some bug zeros some core */
+
+ /* If this is a combination window, do its children; that's all. */
+
+ if (!NULL (w->vchild))
+ {
+ redisplay_windows (w->vchild);
+ return;
+ }
+ if (!NULL (w->hchild))
+ {
+ redisplay_windows (w->hchild);
+ return;
+ }
+ if (NULL (w->buffer))
+ abort ();
+
+ if (update_mode_lines)
+ w->update_mode_line = Qt;
+
+ /* Otherwise set up data on this window; select its buffer and point value */
+
+ height = XFASTINT (w->height);
+ if (w != XWINDOW (minibuf_window))
+ height--;
+ else if (echo_area_contents)
+ return 0;
+
+ current_buffer = XBUFFER (w->buffer);
+
+ if (!just_this_one
+ && current_buffer == XBUFFER (XWINDOW (selected_window)->buffer))
+ buffer_shared++;
+
+ /* Go temporarily to where point is in the window being displayed.
+ We will restore point at the end. */
+ opoint = point;
+ if (!EQ (window, selected_window))
+ {
+ SET_PT (marker_position (w->pointm));
+ if (point < BEGV)
+ point = BEGV;
+ else if (point > ZV)
+ point = ZV;
+ }
+
+ /* If window-start is screwed up, choose a new one. */
+
+ if (XMARKER (w->start)->buffer != current_buffer)
+ goto recenter;
+
+ startp = marker_position (w->start);
+
+ /* Handle case where place to start displaying has been specified */
+
+ if (!NULL (w->force_start))
+ {
+ w->update_mode_line = Qt;
+ w->force_start = Qnil;
+ XFASTINT (w->last_modified) = 0;
+
+ /* Constrain the starting position to be within the visible range. */
+ startp = clip_to_bounds (BEGV, startp, ZV);
+
+ try_window (window, startp);
+ if (point_vpos < 0)
+ {
+ /* If point does not appear, move point so it does appear */
+ pos = *compute_motion (startp, 0,
+ ((EQ (window, minibuf_window) && startp == 1)
+ ? minibuf_prompt_width : 0)
+ +
+ (hscroll ? 1 - hscroll : 0),
+ ZV, height / 2,
+ - (1 << (SHORTBITS - 1)),
+ width, hscroll, pos_tab_offset (w, startp));
+ SET_PT (pos.bufpos);
+ if (w != XWINDOW (selected_window))
+ Fset_marker (w->pointm, make_number (point), Qnil);
+ else
+ /* We want to change point permanently,
+ so don't restore the old value. */
+ opoint = point;
+
+ if (EQ (window, selected_window))
+ {
+ cursor_hpos = max (0, pos.hpos) + XFASTINT (w->left);
+ cursor_vpos = pos.vpos + XFASTINT (w->top);
+ }
+ }
+ goto done;
+ }
+
+ /* Handle case where text has not changed, only point,
+ and it has not moved off the screen */
+
+ /* This code is not used for minibuffer for the sake of
+ the case of redisplaying to replace an echo area message;
+ since in that case the minibuffer contents per se are usually unchanged.
+ This code is of no real use in the minibuffer since
+ the handling of this_line_bufpos, etc.,
+ in redisplay handles the same cases. */
+
+ if (XFASTINT (w->last_modified) >= MODIFF
+ && point >= startp && !clip_changed
+ && (just_this_one || XFASTINT (w->width) == screen_width)
+ && !EQ (window, minibuf_window))
+ {
+ pos = *compute_motion (startp, 0, (hscroll ? 1 - hscroll : 0),
+ point, height + 1, 10000, width, hscroll,
+ pos_tab_offset (w, startp));
+
+ if (pos.vpos < height)
+ {
+ /* Ok, point is still on screen */
+ if (w == XWINDOW (selected_window))
+ {
+ /* These variables are supposed to be origin 1 */
+ cursor_hpos = max (0, pos.hpos) + XFASTINT (w->left);
+ cursor_vpos = pos.vpos + XFASTINT (w->top);
+ }
+/* This doesn't do the trick, because if a window to the right of
+ this one must be redisplayed, this does nothing because there
+ is nothing in DesiredScreen yet, and then the other window is
+ redisplayed, making likes that are empty in this window's columns.
+ if (XFASTINT (w->width) != screen_width)
+ preserve_my_columns (w);
+*/
+ goto done;
+ }
+ /* Don't bother trying redisplay with same start;
+ we already know it will lose */
+ }
+ /* If current starting point was originally the beginning of a line
+ but no longer is, find a new starting point. */
+ else if (!NULL (w->start_at_line_beg)
+ && !(startp == BEGV
+ || FETCH_CHAR (startp - 1) == '\n'))
+ {
+ goto recenter;
+ }
+ else if (just_this_one && !EQ (window, minibuf_window)
+ && point >= startp
+ && XFASTINT (w->last_modified)
+ && ! EQ (w->window_end_valid, Qnil)
+ && do_id && !clip_changed
+ && !blank_end_of_window
+ && XFASTINT (w->width) == screen_width
+ && EQ (last_arrow_position, Voverlay_arrow_position)
+ && EQ (last_arrow_string, Voverlay_arrow_string)
+ && (tem = try_window_id (selected_window))
+ && tem != -2)
+ {
+ /* tem > 0 means success. tem == -1 means choose new start.
+ tem == -2 means try again with same start,
+ and nothing but whitespace follows the changed stuff.
+ tem == 0 means try again with same start. */
+ if (tem > 0)
+ {
+ goto done;
+ }
+ }
+ else if (startp >= BEGV && startp <= ZV
+ /* Avoid starting display at end of buffer! */
+ && (startp < ZV || startp == BEGV
+ || (XFASTINT (w->last_modified) >= MODIFF)))
+ {
+ /* Try to redisplay starting at same place as before */
+ /* If point has not moved off screen, accept the results */
+ try_window (window, startp);
+ if (point_vpos >= 0)
+ goto done;
+ else
+ cancel_my_columns (w);
+ }
+
+ XFASTINT (w->last_modified) = 0;
+ w->update_mode_line = Qt;
+
+ /* Try to scroll by specified few lines */
+
+ if (scroll_step && !clip_changed)
+ {
+ if (point > startp)
+ {
+ pos = *vmotion (Z - XFASTINT (w->window_end_pos),
+ scroll_step, width, hscroll, window);
+ if (pos.vpos >= height)
+ goto scroll_fail;
+ }
+
+ pos = *vmotion (startp, point < startp ? - scroll_step : scroll_step,
+ width, hscroll, window);
+
+ if (point >= pos.bufpos)
+ {
+ try_window (window, pos.bufpos);
+ if (point_vpos >= 0)
+ goto done;
+ else
+ cancel_my_columns (w);
+ }
+ scroll_fail: ;
+ }
+
+ /* Finally, just choose place to start which centers point */
+
+recenter:
+ pos = *vmotion (point, - height / 2, width, hscroll, window);
+ try_window (window, pos.bufpos);
+
+ startp = marker_position (w->start);
+ w->start_at_line_beg =
+ (startp == BEGV || FETCH_CHAR (startp - 1) == '\n') ? Qt : Qnil;
+
+done:
+ /* If window not full width, must redo its mode line
+ if the window to its side is being redone */
+ if ((!NULL (w->update_mode_line)
+ || (!just_this_one && width < screen_width - 1))
+ && !EQ (window, minibuf_window))
+ display_mode_line (w);
+
+ SET_PT (opoint);
+ current_buffer = old;
+}
+
+/* Do full redisplay on one window,
+ starting at position `pos'. */
+
+try_window (window, pos)
+ Lisp_Object window;
+ register int pos;
+{
+ register struct window *w = XWINDOW (window);
+ register int height = XFASTINT (w->height) - !EQ (window, minibuf_window);
+ register int vpos = XFASTINT (w->top);
+ register int last_text_vpos = vpos;
+ int tab_offset = pos_tab_offset (w, pos);
+
+ struct position val;
+
+ Fset_marker (w->start, make_number (pos), Qnil);
+
+ point_vpos = -1;
+ val.hpos = XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0;
+
+ while (--height >= 0)
+ {
+ val = *display_text_line (w, pos, vpos, val.hpos, tab_offset);
+ tab_offset += (XFASTINT (w->width) - 1
+ - (XFASTINT (w->width) + XFASTINT (w->left)
+ != screen_width));
+ if (val.vpos) tab_offset = 0;
+ vpos++;
+ if (pos != val.bufpos)
+ last_text_vpos
+ /* Next line, unless prev line ended in end of buffer with no cr */
+ = vpos - (val.vpos && FETCH_CHAR (val.bufpos - 1) != '\n');
+ pos = val.bufpos;
+ }
+
+ /* If last line is continued in middle of character,
+ include the split character in the text considered on the screen */
+ if (val.hpos < (XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0))
+ pos++;
+
+ /* Say where last char on screen will be, once redisplay is finished. */
+ XFASTINT (w->window_end_pos) = Z - pos;
+ XFASTINT (w->window_end_vpos) = last_text_vpos - XFASTINT (w->top);
+ /* But that is not valid info until redisplay finishes. */
+ w->window_end_valid = Qnil;
+}
+
+/* Try to redisplay when buffer is modified locally,
+ computing insert/delete line to preserve text outside
+ the bounds of the changes.
+ Return 1 if successful, 0 if if cannot tell what to do,
+ or -1 to tell caller to find a new window start,
+ or -2 to tell caller to do normal redisplay with same window start. */
+
+static struct position debug_bp, debug_ep, debug_xp, debug_pp;
+static int debug_start_vpos, debug_stop_vpos, debug_scroll_amount;
+static int debug_dont_scroll;
+
+try_window_id (window)
+ Lisp_Object window;
+{
+ int pos;
+ register struct window *w = XWINDOW (window);
+ register int height = XFASTINT (w->height) - !EQ (window, minibuf_window);
+ int top = XFASTINT (w->top);
+ int start = marker_position (w->start);
+ int width = XFASTINT (w->width) - 1
+ - (XFASTINT (w->width) + XFASTINT (w->left) != screen_width);
+ int hscroll = XINT (w->hscroll);
+ int lmargin = hscroll > 0 ? 1 - hscroll : 0;
+ register int vpos;
+ register int i, tem;
+ int last_text_vpos = 0;
+ int stop_vpos;
+
+ struct position val, bp, ep, xp, pp;
+ int scroll_amount = 0;
+ int delta;
+ int tab_offset, epto;
+
+ if (GPT - BEG < beg_unchanged)
+ beg_unchanged = GPT - BEG;
+ if (Z - GPT < end_unchanged)
+ end_unchanged = Z - GPT;
+
+ if (beg_unchanged + 1 < start)
+ return 0; /* Give up if changes go above top of window */
+
+ /* Find position before which nothing is changed. */
+ bp = *compute_motion (start, 0, lmargin,
+ beg_unchanged + 1, height + 1, 0, width, hscroll,
+ pos_tab_offset (w, start));
+ if (bp.vpos >= height)
+ {
+ if (point < bp.bufpos && !bp.contin)
+ {
+ /* All changes are below the screen, and point is on the screen.
+ We don't need to change the screen at all.
+ But we need to update window_end_pos to account for
+ any change in buffer size. */
+ bp = *compute_motion (start, 0, lmargin,
+ Z, height, 0,
+ width, hscroll, pos_tab_offset (w, start));
+ XFASTINT (w->window_end_vpos) = height;
+ XFASTINT (w->window_end_pos) = Z - bp.bufpos;
+ return 1;
+ }
+ return 0;
+ }
+
+ vpos = bp.vpos;
+
+ /* Find beginning of that screen line. Must display from there. */
+ bp = *vmotion (bp.bufpos, 0, width, hscroll, window);
+
+ pos = bp.bufpos;
+ val.hpos = lmargin;
+ if (pos < start)
+ return -1;
+
+ /* If about to start displaying at the beginning of a continuation line,
+ really start with previous screen line, in case it was not
+ continued when last redisplayed */
+ if ((bp.contin && bp.bufpos - 1 == beg_unchanged && vpos > 0)
+ ||
+ /* Likewise if we have to worry about selective display. */
+ (XTYPE (current_buffer->selective_display) == Lisp_Int
+ && XINT (current_buffer->selective_display) > 0
+ && bp.bufpos - 1 == beg_unchanged && vpos > 0))
+ {
+ bp = *vmotion (bp.bufpos, -1, width, hscroll, window);
+ --vpos;
+ pos = bp.bufpos;
+ }
+
+ if (bp.contin && bp.hpos != lmargin)
+ {
+ val.hpos = bp.prevhpos - width + lmargin;
+ pos--;
+ }
+
+ bp.vpos = vpos;
+
+ /* Find first visible newline after which no more is changed. */
+ tem = find_next_newline (Z - max (end_unchanged, Z - ZV),
+ 1);
+ if (XTYPE (current_buffer->selective_display) == Lisp_Int
+ && XINT (current_buffer->selective_display) > 0)
+ while (tem < ZV - 1
+ && (position_indentation (tem)
+ >= XINT (current_buffer->selective_display)))
+ tem = find_next_newline (tem, 1);
+
+ /* Compute the cursor position after that newline. */
+ ep = *compute_motion (pos, vpos, val.hpos, tem,
+ height, - (1 << (SHORTBITS - 1)),
+ width, hscroll, pos_tab_offset (w, bp.bufpos));
+
+ /* If changes reach past the text available on the screen,
+ just display rest of screen. */
+ if (ep.bufpos > Z - XFASTINT (w->window_end_pos))
+ stop_vpos = height;
+ else
+ stop_vpos = ep.vpos;
+
+ /* If no newline before ep, the line ep is on includes some changes
+ that must be displayed. Make sure we don't stop before it. */
+ /* Also, if changes reach all the way until ep.bufpos,
+ it is possible that something was deleted after the
+ newline before it, so the following line must be redrawn. */
+ if (stop_vpos == ep.vpos
+ && (ep.bufpos == BEGV
+ || FETCH_CHAR (ep.bufpos - 1) != '\n'
+ || ep.bufpos == Z - end_unchanged))
+ stop_vpos = ep.vpos + 1;
+
+ point_vpos = -1;
+ debug_dont_scroll = 0;
+
+ /* If changes do not reach to bottom of window,
+ figure out how much to scroll the rest of the window */
+ if (stop_vpos < height)
+ {
+ /* Now determine how far up or down the rest of the window has moved */
+ epto = pos_tab_offset (w, ep.bufpos);
+ xp = *compute_motion (ep.bufpos, ep.vpos, ep.hpos,
+ Z - XFASTINT (w->window_end_pos),
+ 10000, 0, width, hscroll, epto);
+ scroll_amount = xp.vpos - XFASTINT (w->window_end_vpos);
+
+ /* Is everything on screen below the changes whitespace?
+ If so, no scrolling is really necessary. */
+ for (i = ep.bufpos; i < xp.bufpos; i++)
+ {
+ tem = FETCH_CHAR (i);
+ if (tem != ' ' && tem != '\n' && tem != '\t')
+ break;
+ }
+ if (i == xp.bufpos)
+ return -2;
+
+ XFASTINT (w->window_end_vpos) += scroll_amount;
+
+ /* Before doing any scrolling, verify that point will be on screen. */
+ if (point > ep.bufpos && !(point <= xp.bufpos && xp.bufpos < height))
+ {
+ if (point <= xp.bufpos)
+ {
+ pp = *compute_motion (ep.bufpos, ep.vpos, ep.hpos,
+ point, height, - (1 << (SHORTBITS - 1)),
+ width, hscroll, epto);
+ }
+ else
+ {
+ pp = *compute_motion (xp.bufpos, xp.vpos, xp.hpos,
+ point, height, - (1 << (SHORTBITS - 1)),
+ width, hscroll, pos_tab_offset (w, xp.bufpos));
+ }
+ if (pp.bufpos < point || pp.vpos == height)
+ return 0;
+ point_vpos = pp.vpos + top;
+ point_hpos = pp.hpos + XFASTINT (w->left);
+ }
+
+ if (stop_vpos - scroll_amount >= height
+ || ep.bufpos == xp.bufpos)
+ {
+ if (scroll_amount < 0)
+ stop_vpos -= scroll_amount;
+ scroll_amount = 0;
+ debug_dont_scroll = 1;
+ /* In this path, we have altered window_end_vpos
+ and not left it negative.
+ We must make sure that, in case display is preempted
+ before the screen changes to reflect what we do here,
+ further updates will not come to try_window_id
+ and assume the screen and window_end_vpos match. */
+ blank_end_of_window = 1;
+ }
+ else if (!scroll_amount)
+ {}
+ else if (bp.bufpos == Z - end_unchanged)
+ {
+ /* If reprinting everything is nearly as fast as scrolling,
+ don't bother scrolling. Can happen if lines are short. */
+ if (scroll_cost (bp.vpos + top - scroll_amount,
+ top + height - max (0, scroll_amount),
+ scroll_amount)
+ > xp.bufpos - bp.bufpos - 20)
+ /* Return "try normal display with same window-start."
+ Too bad we can't prevent further scroll-thinking. */
+ return -2;
+ /* If pure deletion, scroll up as many lines as possible.
+ In common case of killing a line, this can save the
+ following line from being overwritten by scrolling
+ and therefore having to be redrawn. */
+ tem = scroll_screen_lines (bp.vpos + top - scroll_amount,
+ top + height - max (0, scroll_amount),
+ scroll_amount);
+ if (!tem) stop_vpos = height;
+ }
+ else if (scroll_amount)
+ {
+ /* If reprinting everything is nearly as fast as scrolling,
+ don't bother scrolling. Can happen if lines are short. */
+ /* Note that if scroll_amount > 0, xp.bufpos - bp.bufpos is an
+ overestimate of cost of reprinting, since xp.bufpos
+ would end up below the bottom of the window. */
+ if (scroll_cost (ep.vpos + top - scroll_amount,
+ top + height - max (0, scroll_amount),
+ scroll_amount)
+ > xp.bufpos - ep.bufpos - 20)
+ /* Return "try normal display with same window-start."
+ Too bad we can't prevent further scroll-thinking. */
+ return -2;
+ tem = scroll_screen_lines (ep.vpos + top - scroll_amount,
+ top + height - max (0, scroll_amount),
+ scroll_amount);
+ if (!tem) stop_vpos = height;
+ }
+ }
+
+ debug_scroll_amount = scroll_amount;
+ debug_bp = bp;
+ debug_ep = ep;
+ debug_xp = xp;
+ debug_pp = pp;
+
+ /* In any case, do not display past bottom of window */
+ if (stop_vpos >= height)
+ {
+ stop_vpos = height;
+ scroll_amount = 0;
+ }
+
+ debug_stop_vpos = stop_vpos;
+ debug_start_vpos = vpos;
+
+ /* Handle case where pos is before w->start --
+ can happen if part of line had been clipped and is not clipped now */
+ if (vpos == 0 && pos < marker_position (w->start))
+ Fset_marker (w->start, make_number (pos), Qnil);
+
+ /* Redisplay the lines where the text was changed */
+ last_text_vpos = vpos;
+ tab_offset = pos_tab_offset (w, pos);
+ if (val.hpos + hscroll - (hscroll > 0) < 0)
+ tab_offset += (XFASTINT (w->width) - 1
+ - (XFASTINT (w->width) + XFASTINT (w->left)
+ != screen_width));
+ while (vpos < stop_vpos)
+ {
+ val = *display_text_line (w, pos, top + vpos++, val.hpos, tab_offset);
+ tab_offset += (XFASTINT (w->width) - 1
+ - (XFASTINT (w->width) + XFASTINT (w->left)
+ != screen_width));
+ if (val.vpos) tab_offset = 0;
+ if (pos != val.bufpos)
+ last_text_vpos
+ /* Next line, unless prev line ended in end of buffer with no cr */
+ = vpos - (val.vpos && FETCH_CHAR (val.bufpos - 1) != '\n');
+ pos = val.bufpos;
+ }
+
+ /* There are two cases:
+ 1) we have displayed down to the bottom of the window
+ 2) we have scrolled lines below stop_vpos by scroll_amount */
+
+ if (vpos == height)
+ {
+ /* If last line is continued in middle of character,
+ include the split character in the text considered on the screen */
+ if (val.hpos < lmargin)
+ val.bufpos++;
+ XFASTINT (w->window_end_vpos) = last_text_vpos;
+ XFASTINT (w->window_end_pos) = Z - val.bufpos;
+ }
+
+ /* If scrolling made blank lines at window bottom,
+ redisplay to fill those lines */
+ if (scroll_amount < 0)
+ {
+ vpos = xp.vpos;
+ pos = xp.bufpos;
+ val.hpos = lmargin;
+ if (pos == ZV)
+ vpos = height + scroll_amount;
+ else if (xp.contin && xp.hpos != lmargin)
+ {
+ val.hpos = xp.prevhpos - width + lmargin;
+ pos--;
+ }
+
+ blank_end_of_window = 1;
+ tab_offset = pos_tab_offset (w, pos);
+ if (val.hpos < 0)
+ tab_offset += (XFASTINT (w->width) - 1
+ - (XFASTINT (w->width) + XFASTINT (w->left)
+ != screen_width));
+
+ while (vpos < height)
+ {
+ val = *display_text_line (w, pos, top + vpos++, val.hpos, tab_offset);
+ tab_offset += (XFASTINT (w->width) - 1
+ - (XFASTINT (w->width) + XFASTINT (w->left)
+ != screen_width));
+ if (val.vpos) tab_offset = 0;
+ pos = val.bufpos;
+ }
+
+ /* Here is a case where display_text_line sets point_vpos wrong.
+ Make it be fixed up, below. */
+ if (xp.bufpos == ZV
+ && xp.bufpos == point)
+ point_vpos = -1;
+ }
+
+ /* Attempt to adjust end-of-text positions to new bottom line */
+ if (scroll_amount)
+ {
+ delta = height - xp.vpos;
+ if (delta < 0
+ || (delta > 0 && xp.bufpos < ZV)
+ || (delta == 0 && xp.hpos))
+ {
+ val = *vmotion (Z - XFASTINT (w->window_end_pos),
+ delta, width, hscroll, window);
+ XFASTINT (w->window_end_pos) = Z - val.bufpos;
+ XFASTINT (w->window_end_vpos) += val.vpos;
+ }
+ }
+
+ w->window_end_valid = Qnil;
+
+ /* If point was not in a line that was displayed, find it */
+ if (point_vpos < 0)
+ {
+ val = *compute_motion (start, 0, lmargin, point, 10000, 10000,
+ width, hscroll, pos_tab_offset (w, start));
+ /* Admit failure if point is off screen now */
+ if (val.vpos >= height)
+ {
+ for (vpos = 0; vpos < height; vpos++)
+ cancel_line (vpos + top);
+ return 0;
+ }
+ point_vpos = val.vpos + top;
+ point_hpos = val.hpos + XFASTINT (w->left);
+ }
+
+ cursor_hpos = max (0, point_hpos);
+ cursor_vpos = point_vpos;
+
+ if (debug_end_pos)
+ {
+ val = *compute_motion (start, 0, lmargin, ZV,
+ height, - (1 << (SHORTBITS - 1)),
+ width, hscroll, pos_tab_offset (w, start));
+ if (val.vpos != XFASTINT (w->window_end_vpos))
+ abort ();
+ if (XFASTINT (w->window_end_pos) != Z - val.bufpos)
+ abort ();
+ }
+
+ return 1;
+}
+
+/* Display one line of window w, starting at position `start' in w's buffer.
+ Display starting at horizontal position `hpos',
+ which is normally zero or negative.
+ A negative value causes output up to hpos = 0 to be discarded.
+ This is done for negative hscroll, or when this is a continuation line
+ and the continuation occurred in the middle of a multi-column character.
+
+ `taboffset' is an offset for ostensible hpos, used in tab stop calculations.
+
+ Display on position `vpos' on the screen. (origin 0).
+
+ Returns a `struct position' giving character to start next line with
+ and where to display it, including a zero or negative hpos.
+ The vpos field is not really a vpos; it is 1 unless the line is continued */
+
+struct position val_display_text_line;
+
+struct position *
+display_text_line (w, start, vpos, hpos, taboffset)
+ struct window *w;
+ int start;
+ int vpos;
+ int hpos;
+ int taboffset;
+{
+ register int pos = start;
+ register int c;
+ register unsigned char *p1;
+ int end;
+ register int pause;
+ register unsigned char *p;
+ unsigned char *endp;
+ register unsigned char *startp;
+ register unsigned char *p1prev = 0;
+ int tab_width = XINT (current_buffer->tab_width);
+ int ctl_arrow = !NULL (current_buffer->ctl_arrow);
+ int width = XFASTINT (w->width) - 1
+ - (XFASTINT (w->width) + XFASTINT (w->left) != screen_width);
+ struct position val;
+ int lastpos;
+ int invis;
+ int hscroll = XINT (w->hscroll);
+ int truncate = hscroll
+ || (truncate_partial_width_windows
+ && XFASTINT (w->width) < screen_width)
+ || !NULL (current_buffer->truncate_lines);
+ int selective
+ = XTYPE (current_buffer->selective_display) == Lisp_Int
+ ? XINT (current_buffer->selective_display)
+ : !NULL (current_buffer->selective_display) ? -1 : 0;
+ int selective_e = selective && !NULL (current_buffer->selective_display_ellipses);
+
+ hpos += XFASTINT (w->left);
+ get_display_line (vpos, XFASTINT (w->left));
+ if (tab_width <= 0 || tab_width > 20) tab_width = 8;
+
+ if (w == XWINDOW (minibuf_window) && start == 1
+ && vpos == XFASTINT (w->top))
+ {
+ if (minibuf_prompt)
+ hpos = display_string (w, vpos, minibuf_prompt, hpos,
+ !truncate ? '\\' : '$', -1, -1);
+ minibuf_prompt_width = hpos;
+ }
+
+ p1 = new_screen->contents[vpos] + hpos;
+
+ end = ZV;
+
+ startp = new_screen->contents[vpos] + XFASTINT (w->left);
+ endp = startp + width;
+
+ /* Loop generating characters.
+ Stop at end of buffer, before newline,
+ or if reach or pass continuation column. */
+
+ pause = pos;
+ while (p1 < endp)
+ {
+ p1prev = p1;
+ if (pos == pause)
+ {
+ if (pos == end)
+ break;
+ if (pos == point && point_vpos < 0)
+ {
+ point_vpos = vpos;
+ point_hpos = p1 - startp;
+ }
+
+ pause = end;
+ if (pos < point && point < pause)
+ pause = point;
+ if (pos < GPT && GPT < pause)
+ pause = GPT;
+
+ p = &FETCH_CHAR (pos);
+ }
+ c = *p++;
+ if (c >= 040 && c < 0177)
+ {
+ if (p1 >= startp)
+ *p1 = c;
+ p1++;
+ }
+ else if (c == '\n')
+ {
+ invis = 0;
+ while (pos < end
+ && selective > 0
+ && position_indentation (pos + 1) >= selective)
+ {
+ invis = 1;
+ pos = find_next_newline (pos + 1, 1);
+ if (FETCH_CHAR (pos - 1) == '\n')
+ pos--;
+ }
+ if (invis && selective_e)
+ {
+ p1 += 4;
+ if (p1 - startp > width)
+ p1 = endp;
+ if (p1prev >= startp)
+ strncpy (p1prev, " ...", p1 - p1prev);
+ }
+ break;
+ }
+ else if (c == '\t')
+ {
+ do
+ {
+ if (p1 >= startp && p1 < endp)
+ *p1 = ' ';
+ p1++;
+ }
+ while ((p1 - startp + taboffset + hscroll - (hscroll > 0))
+ % tab_width);
+ }
+ else if (c == Ctl ('M') && selective == -1)
+ {
+ pos = find_next_newline (pos, 1);
+ if (FETCH_CHAR (pos - 1) == '\n')
+ pos--;
+ if (selective_e)
+ {
+ p1 += 4;
+ if (p1 - startp > width)
+ p1 = endp;
+ if (p1prev >= startp)
+ strncpy (p1prev, " ...", p1 - p1prev);
+ }
+ break;
+ }
+ else if (c < 0200 && ctl_arrow)
+ {
+ if (p1 >= startp)
+ *p1 = '^';
+ p1++;
+ if (p1 >= startp && p1 < endp)
+ *p1 = c ^ 0100;
+ p1++;
+ }
+ else
+ {
+ if (p1 >= startp)
+ *p1 = '\\';
+ p1++;
+ if (p1 >= startp && p1 < endp)
+ *p1 = (c >> 6) + '0';
+ p1++;
+ if (p1 >= startp && p1 < endp)
+ *p1 = (7 & (c >> 3)) + '0';
+ p1++;
+ if (p1 >= startp && p1 < endp)
+ *p1 = (7 & c) + '0';
+ p1++;
+ }
+ pos++;
+ }
+
+ val.hpos = - XINT (w->hscroll);
+ if (val.hpos)
+ val.hpos++;
+
+ val.vpos = 1;
+
+ lastpos = pos;
+
+ /* Handle continuation in middle of a character */
+ /* by backing up over it */
+ if (p1 > endp)
+ {
+ if (p1prev)
+ {
+ /* Start the next line with that same character */
+ pos--;
+ /* but at negative hpos, to skip the columns output on this line. */
+ val.hpos += p1prev - endp;
+ }
+
+ /* Keep in this line everything up to the continuation column. */
+ p1 = endp;
+ }
+
+ /* Finish deciding which character to start the next line on,
+ and what hpos to start it at.
+ Also set `lastpos' to the last position which counts as "on this line"
+ for cursor-positioning. */
+
+ if (pos < ZV)
+ {
+ if (FETCH_CHAR (pos) == '\n')
+ /* If stopped due to a newline, start next line after it */
+ pos++;
+ else
+ /* Stopped due to right margin of window */
+ {
+ if (truncate)
+ {
+ *p1++ = '$';
+ /* Truncating => start next line after next newline,
+ and point is on this line if it is before the newline,
+ and skip none of first char of next line */
+ pos = find_next_newline (pos, 1);
+ val.hpos = XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0;
+
+ lastpos = pos - (FETCH_CHAR (pos - 1) == '\n');
+ }
+ else
+ {
+ *p1++ = '\\';
+ val.vpos = 0;
+ lastpos--;
+ }
+ }
+ }
+
+ /* If point is at eol or in invisible text at eol,
+ record its screen location now. */
+
+ if (start <= point && point <= lastpos && point_vpos < 0)
+ {
+ point_vpos = vpos;
+ point_hpos = p1 - startp;
+ }
+
+ if (point_vpos == vpos)
+ {
+ if (point_hpos < 0) point_hpos = 0;
+ if (point_hpos > width) point_hpos = width;
+ point_hpos += XFASTINT (w->left);
+ if (w == XWINDOW (selected_window))
+ {
+ cursor_vpos = point_vpos;
+ cursor_hpos = point_hpos;
+
+ /* Line is not continued and did not start in middle of character */
+ if (hpos == (XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0)
+ && val.vpos)
+ {
+ this_line_bufpos = start;
+ this_line_buffer = current_buffer;
+ this_line_vpos = point_vpos;
+ this_line_start_hpos = hpos;
+ this_line_endpos = Z - lastpos;
+ }
+ else
+ this_line_bufpos = 0;
+ }
+ }
+
+ /* If hscroll and line not empty, insert truncation-at-left marker */
+ if (hscroll && lastpos != start)
+ {
+ *startp = '$';
+ if (p1 <= startp)
+ p1 = startp + 1;
+ }
+
+ if (XFASTINT (w->width) + XFASTINT (w->left) != screen_width)
+ {
+ endp++;
+ if (p1 < startp) p1 = startp;
+ while (p1 < endp) *p1++ = ' ';
+ *p1++ = '|';
+ }
+ new_screen->used[vpos] = max (new_screen->used[vpos],
+ p1 - new_screen->contents[vpos]);
+ new_screen->contents[vpos][new_screen->used[vpos]] = 0;
+
+ /* If the start of this line is the overlay arrow-position,
+ then put the arrow string into the display-line. */
+
+ if (XTYPE (Voverlay_arrow_position) == Lisp_Marker
+ && current_buffer == XMARKER (Voverlay_arrow_position)->buffer
+ && start == marker_position (Voverlay_arrow_position)
+ && XTYPE (Voverlay_arrow_string) == Lisp_String)
+ {
+ unsigned char *p = XSTRING (Voverlay_arrow_string)->data;
+ int len = XSTRING (Voverlay_arrow_string)->size;
+ int minlen = (XFASTINT (w->width) - 1
+ - (XFASTINT (w->width) + XFASTINT (w->left)
+ != screen_width));
+
+ if (len > minlen)
+ len = minlen;
+ bcopy (p, startp, len);
+ if (new_screen->used[vpos] < len + startp - new_screen->contents[vpos])
+ new_screen->used[vpos] = len + startp - new_screen->contents[vpos];
+ }
+
+ val.bufpos = pos;
+ val_display_text_line = val;
+ return &val_display_text_line;
+}
+
+/* Display the mode line for window w */
+
+display_mode_line (w)
+ struct window *w;
+{
+ register int vpos = XFASTINT (w->height) + XFASTINT (w->top) - 1;
+ register int left = XFASTINT (w->left);
+ register int right = XFASTINT (w->width) + left;
+ get_display_line (vpos, left);
+
+ display_mode_element (w, vpos, left, 0, right, right,
+ current_buffer->mode_line_format);
+
+ /* Make the mode line inverse video if the entire line
+ is made of mode lines.
+ I.e. if this window is full width,
+ or if it is the child of a full width window
+ (which implies that that window is split side-by-side
+ and the rest of this line is mode lines of the sibling windows). */
+ if (XFASTINT (w->width) == screen_width ||
+ XFASTINT (XWINDOW (w->parent)->width) == screen_width)
+ new_screen->highlight[vpos] = mode_line_inverse_video;
+
+}
+
+/* Contribute ELT to the mode line for window W.
+ How it translates into text depends on its data type.
+
+ LINE is the display-line that the mode line is being displayed in.
+
+ HPOS is the position (absolute on screen) where this element's text
+ should start. The output is truncated automatically at the right
+ edge of window W.
+
+ DEPTH is the depth in recursion. It is used to prevent
+ infinite recursion here.
+
+ MINENDCOL is the hpos before which the element may not end.
+ The element is padded at the right with spaces if nec
+ to reach this column.
+
+ MAXENDCOL is the hpos past which this element may not extend.
+ If MINENDCOL is > MAXENDCOL, MINENDCOL takes priority.
+ (This is necessary to make nested padding and truncation work.)
+
+ Returns the hpos of the end of the text generated by ELT.
+ The next element will receive that value as its HPOS arg,
+ so as to concatenate the elements. */
+
+int
+display_mode_element (w, vpos, hpos, depth, minendcol, maxendcol, elt)
+ struct window *w;
+ int vpos;
+ register int hpos;
+ int depth;
+ int minendcol;
+ register int maxendcol;
+ register Lisp_Object elt;
+{
+ tail_recurse:
+ if (depth > 10)
+ goto invalid;
+
+ depth++;
+
+#ifdef SWITCH_ENUM_BUG
+ switch ((int) XTYPE (elt))
+#else
+ switch (XTYPE (elt))
+#endif
+ {
+ case Lisp_String:
+ {
+ /* A string: output it and check for %-constructs within it. */
+ register unsigned char c;
+ register unsigned char *this = XSTRING (elt)->data;
+
+ while (hpos < maxendcol && *this)
+ {
+ unsigned char *last = this;
+ while ((c = *this++) != '\0' && c != '%')
+ ;
+ if (this - 1 != last)
+ {
+ register int lim = --this - last + hpos;
+ hpos = display_string (w, vpos, last, hpos, 0, hpos,
+ min (lim, maxendcol));
+ }
+ else /* c == '%' */
+ {
+ register int spec_width = 0;
+
+ /* We can't allow -ve args due to the "%-" construct */
+ /* Argument specifies minwidth but not maxwidth
+ (maxwidth can be specified by
+ (<negative-number> . <stuff>) mode-line elements) */
+
+ while ((c = *this++) >= '0' && c <= '9')
+ {
+ spec_width = spec_width * 10 + (c - '0');
+ }
+
+ spec_width += hpos;
+ if (spec_width > maxendcol)
+ spec_width = maxendcol;
+
+ if (c == 'M')
+ hpos = display_mode_element (w, vpos, hpos, depth,
+ spec_width, maxendcol,
+ Vglobal_mode_string);
+ else if (c != 0)
+ hpos = display_string (w, vpos,
+ decode_mode_spec (w, c,
+ spec_width - hpos),
+ hpos, 0, spec_width, maxendcol);
+ }
+ }
+ }
+ break;
+
+ case Lisp_Symbol:
+ /* A symbol: process the value of the symbol recursively
+ as if it appeared here directly. Avoid error if symbol void.
+ Special case: if value of symbol is a string, output the string
+ literally. */
+ {
+ register Lisp_Object tem;
+ tem = Fboundp (elt);
+ if (!NULL (tem))
+ {
+ tem = Fsymbol_value (elt);
+ /* If value is a string, output that string literally:
+ don't check for % within it. */
+ if (XTYPE (tem) == Lisp_String)
+ hpos = display_string (w, vpos, XSTRING (tem)->data,
+ hpos, 0, minendcol, maxendcol);
+ /* Give up right away for nil or t. */
+ else if (!EQ (tem, elt))
+ { elt = tem; goto tail_recurse; }
+ }
+ }
+ break;
+
+ case Lisp_Cons:
+ {
+ register Lisp_Object car, tem;
+
+ /* A cons cell: three distinct cases.
+ If first element is a string or a cons, process all the elements
+ and effectively concatenate them.
+ If first element is a negative number, truncate displaying cdr to
+ at most that many characters. If positive, pad (with spaces)
+ to at least that many characters.
+ If first element is a symbol, process the cadr or caddr recursively
+ according to whether the symbol's value is non-nil or nil. */
+ car = XCONS (elt)->car;
+ if (XTYPE (car) == Lisp_Symbol)
+ {
+ tem = Fboundp (car);
+ elt = XCONS (elt)->cdr;
+ if (XTYPE (elt) != Lisp_Cons)
+ goto invalid;
+ /* elt is now the cdr, and we know it is a cons cell.
+ Use its car if CAR has a non-nil value. */
+ if (!NULL (tem))
+ {
+ tem = Fsymbol_value (car);
+ if (!NULL (tem))
+ { elt = XCONS (elt)->car; goto tail_recurse; }
+ }
+ /* Symbol's value is nil (or symbol is unbound)
+ Get the cddr of the original list
+ and if possible find the caddr and use that. */
+ elt = XCONS (elt)->cdr;
+ if (NULL (elt))
+ break;
+ else if (XTYPE (elt) != Lisp_Cons)
+ goto invalid;
+ elt = XCONS (elt)->car;
+ goto tail_recurse;
+ }
+ else if (XTYPE (car) == Lisp_Int)
+ {
+ register int lim = XINT (car);
+ elt = XCONS (elt)->cdr;
+ if (lim < 0)
+ /* Negative int means reduce maximum width.
+ DO NOT change MINENDCOL here!
+ (20 -10 . foo) should truncate foo to 10 col
+ and then pad to 20. */
+ maxendcol = min (maxendcol, hpos - lim);
+ else if (lim > 0)
+ {
+ /* Padding specified. Don't let it be more than
+ current maximum. */
+ lim += hpos;
+ if (lim > maxendcol)
+ lim = maxendcol;
+ /* If that's more padding than already wanted, queue it.
+ But don't reduce padding already specified even if
+ that is beyond the current truncation point. */
+ if (lim > minendcol)
+ minendcol = lim;
+ }
+ goto tail_recurse;
+ }
+ else if (XTYPE (car) == Lisp_String || XTYPE (car) == Lisp_Cons)
+ {
+ register int limit = 50;
+ /* LIMIT is to protect against circular lists. */
+ while (XTYPE (elt) == Lisp_Cons && --limit > 0
+ && hpos < maxendcol)
+ {
+ hpos = display_mode_element (w, vpos, hpos, depth,
+ hpos, maxendcol,
+ XCONS (elt)->car);
+ elt = XCONS (elt)->cdr;
+ }
+ }
+ }
+ break;
+
+ default:
+ invalid:
+ return (display_string (w, vpos, "*invalid*", hpos, 0,
+ minendcol, maxendcol));
+ }
+
+ end:
+ if (minendcol > hpos)
+ hpos = display_string (w, vpos, "", hpos, 0, minendcol, -1);
+ return hpos;
+}
+
+/* Return a string for the output of a mode line %-spec
+ for window W, generated by character C and width MAXWIDTH. */
+
+char *
+decode_mode_spec (w, c, maxwidth)
+ struct window *w;
+ register char c;
+ register int maxwidth;
+{
+ Lisp_Object obj = Qnil;
+ char *decode_mode_spec_buf = (char *) temp_screen->total_contents;
+
+ switch (c)
+ {
+ case 'b':
+ obj = current_buffer->name;
+#if 0
+ if (maxwidth >= 3 && XSTRING (obj)->size > maxwidth)
+ {
+ bcopy (XSTRING (obj)->data, decode_mode_spec_buf, maxwidth - 1);
+ decode_mode_spec_buf[maxwidth - 1] = '\\';
+ decode_mode_spec_buf[maxwidth] = '\0';
+ return decode_mode_spec_buf;
+ }
+#endif
+ break;
+
+ case 'f':
+ obj = current_buffer->filename;
+#if 0
+ if (XTYPE (obj) == Lisp_String && XSTRING (obj)->size > maxwidth)
+ {
+ bcopy ("...", decode_mode_spec_buf, 3);
+ bcopy (XSTRING (obj)->data + XSTRING (obj)->size - maxwidth + 3,
+ decode_mode_spec_buf + 3, maxwidth - 3);
+ return decode_mode_spec_buf;
+ }
+#endif
+ break;
+
+ case 'm':
+ obj = current_buffer->mode_name;
+ break;
+
+ case 'n':
+ if (BEGV > BEG || ZV < Z)
+ return " Narrow";
+ break;
+
+ case '*':
+ if (!NULL (current_buffer->read_only))
+ return "%";
+ if (MODIFF > current_buffer->save_modified)
+ return "*";
+ return "-";
+
+ case 's':
+ /* status of process */
+#ifdef subprocesses
+ obj = Fget_buffer_process (Fcurrent_buffer ());
+ if (NULL (obj))
+ return "no process";
+ obj = Fsymbol_name (Fprocess_status (obj));
+ break;
+#else
+ return "no processes";
+#endif /* subprocesses */
+
+ case 'p':
+ {
+ int pos = marker_position (w->start);
+ int total = ZV - BEGV;
+
+ if (XFASTINT (w->window_end_pos) <= Z - ZV)
+ {
+ if (pos <= BEGV)
+ return "All";
+ else
+ return "Bottom";
+ }
+ else if (pos <= BEGV)
+ return "Top";
+ else
+ {
+ total = ((pos - BEGV) * 100 + total - 1) / total;
+ /* We can't normally display a 3-digit number,
+ so get us a 2-digit number that is close. */
+ if (total == 100)
+ total = 99;
+ sprintf (decode_mode_spec_buf, "%2d%%", total);
+ return decode_mode_spec_buf;
+ }
+ }
+
+ case '[':
+ {
+ int i;
+ char *p;
+ if (command_loop_level > 5)
+ return "[[[... ";
+ p = decode_mode_spec_buf;
+ for (i = 0; i < command_loop_level; i++)
+ *p++ = '[';
+ *p = 0;
+ return decode_mode_spec_buf;
+ }
+
+ case '%':
+ return "%";
+
+ case ']':
+ {
+ int i;
+ char *p;
+ if (command_loop_level > 5)
+ return " ...]]]";
+ p = decode_mode_spec_buf;
+ for (i = 0; i < command_loop_level; i++)
+ *p++ = ']';
+ *p = 0;
+ return decode_mode_spec_buf;
+ }
+
+ case '-':
+ {
+ int i;
+ if (maxwidth < 140)
+ return "--------------------------------------------------------------------------------------------------------------------------------------------";
+ for (i = 0; i < maxwidth; i++)
+ decode_mode_spec_buf[i] = '-';
+ return decode_mode_spec_buf;
+ }
+ }
+
+ if (XTYPE (obj) == Lisp_String)
+ return (char *) XSTRING (obj)->data;
+ else
+ return "";
+}
+
+/* Display STRING on one line of window W, starting at HPOS.
+ Display at position VPOS. Caller should do get_display_line first.
+
+ TRUNCATE is character to display at end if truncated. Zero for none.
+
+ MINCOL is the first column ok to end at. (Pad with spaces to this col.)
+ MAXCOL is the last column ok to end at. Truncate here.
+ -1 for MINCOL or MAXCOL means no explicit minimum or maximum.
+ Both count from the left edge of the screen, as does HPOS.
+ The right edge of W is an implicit maximum.
+ If TRUNCATE is nonzero, the implicit maximum is one column before the edge.
+
+ Returns ending hpos */
+
+display_string (w, vpos, string, hpos, truncate, mincol, maxcol)
+ struct window *w;
+ int vpos;
+ unsigned char *string;
+ int hpos;
+ char truncate;
+ int mincol, maxcol;
+{
+ register int c;
+ register unsigned char *p1;
+ int hscroll = XINT (w->hscroll);
+ int tab_width = XINT (current_buffer->tab_width);
+ register unsigned char *start;
+ register unsigned char *end;
+ unsigned char *p1start = new_screen->contents[vpos] + hpos;
+ int window_width = XFASTINT (w->width);
+
+ if (tab_width <= 0 || tab_width > 20) tab_width = 8;
+
+ p1 = p1start;
+ start = new_screen->contents[vpos] + XFASTINT (w->left);
+ end = start + window_width - (truncate != 0);
+
+ if ((window_width + XFASTINT (w->left)) != screen_width)
+ *end-- = '|';
+
+ if (maxcol >= 0 && end - new_screen->contents[vpos] > maxcol)
+ end = new_screen->contents[vpos] + maxcol;
+ if (maxcol >= 0 && mincol > maxcol)
+ mincol = maxcol;
+
+ while (p1 < end)
+ {
+ c = *string++;
+ if (!c) break;
+ if (c >= 040 && c < 0177)
+ {
+ if (p1 >= start)
+ *p1 = c;
+ p1++;
+ }
+ else if (c == '\t')
+ {
+ do
+ {
+ if (p1 >= start && p1 < end)
+ *p1 = ' ';
+ p1++;
+ }
+ while ((p1 - start + hscroll - (hscroll > 0)) % tab_width);
+ }
+ else if (c < 0200 && buffer_defaults.ctl_arrow)
+ {
+ if (p1 >= start)
+ *p1 = '^';
+ p1++;
+ if (p1 >= start && p1 < end)
+ *p1 = c ^ 0100;
+ p1++;
+ }
+ else
+ {
+ if (p1 >= start)
+ *p1 = '\\';
+ p1++;
+ if (p1 >= start && p1 < end)
+ *p1 = (c >> 6) + '0';
+ p1++;
+ if (p1 >= start && p1 < end)
+ *p1 = (7 & (c >> 3)) + '0';
+ p1++;
+ if (p1 >= start && p1 < end)
+ *p1 = (7 & c) + '0';
+ p1++;
+ }
+ }
+
+ if (c)
+ {
+ p1 = end;
+ if (truncate) *p1++ = truncate;
+ }
+ else if (mincol >= 0)
+ {
+ end = new_screen->contents[vpos] + mincol;
+ while (p1 < end)
+ *p1++ = ' ';
+ }
+
+ {
+ register int len = p1 - new_screen->contents[vpos];
+ if (len > new_screen->used[vpos])
+ new_screen->used[vpos] = len;
+ new_screen->contents[vpos][new_screen->used[vpos]] = 0;
+ return len;
+ }
+}
+
+syms_of_xdisp ()
+{
+ staticpro (&last_arrow_position);
+ staticpro (&last_arrow_string);
+ last_arrow_position = Qnil;
+ last_arrow_string = Qnil;
+
+ DEFVAR_LISP ("global-mode-string", &Vglobal_mode_string,
+ "String displayed by mode-line-format's \"%m\" specifiation.");
+ Vglobal_mode_string = Qnil;
+
+ DEFVAR_LISP ("overlay-arrow-position", &Voverlay_arrow_position,
+ "Marker for where to display an arrow on top of the buffer text.\n\
+This must be the beginning of a line in order to work.\n\
+See also overlay-arrow-string.");
+ Voverlay_arrow_position = Qnil;
+
+ DEFVAR_LISP ("overlay-arrow-string", &Voverlay_arrow_string,
+ "String to display as an arrow. See also overlay-arrow-position.");
+ Voverlay_arrow_string = Qnil;
+
+ DEFVAR_INT ("scroll-step", &scroll_step,
+ "*The number of lines to try scrolling a window by when point moves out.\n\
+If that fails to bring point back on screen, point is centered instead.\n\
+If this is zero, point is always centered after it moves off screen.");
+
+ DEFVAR_BOOL ("reset-terminal-on-clear", &reset_terminal_on_clear,
+ "Non-nil means re-init terminal modes for clear screen as on entry to Emacs.");
+ reset_terminal_on_clear = 1;
+
+ DEFVAR_INT ("debug-end-pos", &debug_end_pos, "Don't ask");
+
+ DEFVAR_BOOL ("truncate-partial-width-windows",
+ &truncate_partial_width_windows,
+ "*Non-nil means truncate lines in all windows less than full screen wide.");
+ truncate_partial_width_windows = 1;
+
+ DEFVAR_BOOL ("mode-line-inverse-video", &mode_line_inverse_video,
+ "*Non-nil means use inverse video, or other suitable display mode, for the mode line.");
+ mode_line_inverse_video = 1;
+
+ defsubr (&Sredraw_display);
+}
+
+/* initialize the window system */
+init_xdisp ()
+{
+ Lisp_Object root_window;
+#ifndef COMPILER_REGISTER_BUG
+ register
+#endif COMPILER_REGISTER_BUG
+ struct window *mini_w;
+
+ this_line_bufpos = 0;
+
+ mini_w = XWINDOW (minibuf_window);
+ root_window = mini_w->prev;
+
+ echo_area_contents = 0;
+ prev_echo_area_contents = 0;
+
+ if (!noninteractive)
+ {
+ XFASTINT (XWINDOW (root_window)->top) = 0;
+ set_window_height (root_window, screen_height - 1, 0);
+ XFASTINT (mini_w->top) = screen_height - 1;
+ set_window_height (minibuf_window, 1, 0);
+
+ XFASTINT (XWINDOW (root_window)->width) = screen_width;
+ XFASTINT (mini_w->width) = screen_width;
+ }
+}
diff --git a/src/xfns.c b/src/xfns.c
new file mode 100644
index 00000000000..c1e6b3479b8
--- /dev/null
+++ b/src/xfns.c
@@ -0,0 +1,1400 @@
+/* Functions for the X window system.
+ Copyright (C) 1985, 1986, 1987 Free Software Foundation.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Written by Yakim Martillo; rearranged by Richard Stallman. */
+/* Color and other features added by Robert Krawitz*/
+
+/*#include <stdio.h>*/
+#include <signal.h>
+#include "config.h"
+#include "lisp.h"
+#include "window.h"
+#include "xterm.h"
+#include "dispextern.h"
+#include "termchar.h"
+#include <fcntl.h>
+#include <setjmp.h>
+
+#ifdef HAVE_TIMEVAL
+#ifndef USG
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif /* USG */
+#endif
+
+#ifdef HAVE_X_WINDOWS
+
+#define abs(x) ((x < 0) ? ((x)) : (x))
+#define sgn(x) ((x < 0) ? (-1) : (1))
+#define min(a,b) ((a) < (b) ? (a) : (b))
+#define max(a,b) ((a) > (b) ? (a) : (b))
+
+#define CROSS_WIDTH 16
+#define CROSS_HEIGHT 16
+
+static short cross_bits[] =
+ {
+ 0x0000, 0x0180, 0x0180, 0x0180,
+ 0x0180, 0x0180, 0x0180, 0x7ffe,
+ 0x7ffe, 0x0180, 0x0180, 0x0180,
+ 0x0180, 0x0180, 0x0180, 0x0000,
+ };
+
+static short gray_bits[] = {
+ 0xaaaa, 0x5555, 0xaaaa, 0x5555,
+ 0xaaaa, 0x5555, 0xaaaa, 0x5555,
+ 0xaaaa, 0x5555, 0xaaaa, 0x5555,
+ 0xaaaa, 0x5555, 0xaaaa, 0x5555};
+
+#define CROSS_MASK_WIDTH 16
+#define CROSS_MASK_HEIGHT 16
+static short cross_mask_bits[] =
+ {
+ 0x03c0, 0x03c0, 0x03c0, 0x03c0,
+ 0x03c0, 0x03c0, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0x03c0, 0x03c0,
+ 0x03c0, 0x03c0, 0x03c0, 0x03c0,
+ };
+
+extern short sink_bits[];
+extern short sink_mask_bits[];
+#define sink_width 48
+#define sink_height 48
+#define sink_mask_width 48
+#define sink_mask_height 48
+
+extern XREPBUFFER Xxrepbuffer;
+
+/* Non-nil if Emacs is running with an X window for display.
+ Nil if Emacs is run on an ordinary terminal.
+ Initialized in dispnew.c. */
+
+Lisp_Object Vxterm;
+
+Lisp_Object Vx_mouse_pos, Vx_mouse_abs_pos;
+
+Lisp_Object Vx_mouse_item;
+
+extern struct Lisp_Vector *MouseMap;
+
+extern char *fore_color;
+extern char *back_color;
+extern char *brdr_color;
+extern char *mous_color;
+extern char *curs_color;
+
+extern int fore;
+extern int back;
+extern int brdr;
+extern int mous;
+extern int curs;
+
+extern int XXborder;
+extern int XXInternalBorder;
+
+extern int (*handler) ();
+
+extern FontInfo *fontinfo;
+
+extern int PendingExposure;
+extern char *default_window;
+
+extern Window XXwindow;
+extern Cursor EmacsCursor;
+extern short MouseCursor[], MouseMask[];
+extern char *XXcurrentfont;
+extern int informflag;
+
+extern int WindowMapped;
+extern char iconidentity[];
+extern int CurHL;
+extern int pixelwidth, pixelheight;
+extern int XXxoffset, XXyoffset;
+extern int XXpid;
+
+extern Display *XXdisplay;
+extern Window XXIconWindow;
+extern int IconWindow;
+extern Bitmap XXIconMask;
+extern int bitblt, CursorExists, VisibleX, VisibleY;
+extern WindowInfo rootwindowinfo;
+
+extern void x_init_1 ();
+
+/* Nonzero if x-set-window-edges has been called
+ or x-rubber-band has been called.
+ If it is zero when x-pop-up-window is called,
+ x-rubber-band is called at that point. */
+
+int x_edges_specified;
+
+check_xterm ()
+{
+ if (NULL (Vxterm))
+ error ("Terminal does not understand X protocol.");
+}
+
+DEFUN ("x-pop-up-window", Fx_pop_up_window, Sx_pop_up_window, 0, 0, 0,
+ "Make the X window appear on the screen.")
+ ()
+{
+ check_xterm ();
+ XPopUpWindow ();
+ return Qnil;
+}
+
+DEFUN ("x-set-bell", Fx_set_bell, Sx_set_bell, 1, 1, "P",
+ "For X window system, set audible vs visible bell.\n\
+With non-nil argument (prefix arg), use visible bell; otherwise, audible bell.")
+ (arg)
+ Lisp_Object arg;
+{
+ BLOCK_INPUT_DECLARE ()
+
+ check_xterm ();
+ BLOCK_INPUT ();
+ if (!NULL (arg))
+ XSetFlash ();
+ else
+ XSetFeep ();
+ UNBLOCK_INPUT ();
+ return arg;
+}
+
+DEFUN ("x-flip-color", Fx_flip_color, Sx_flip_color, 0, 0, "",
+ "Toggle the background and foreground colors")
+ ()
+{
+ check_xterm ();
+ XFlipColor ();
+ return Qt;
+}
+
+DEFUN ("x-set-foreground-color", Fx_set_foreground_color,
+ Sx_set_foreground_color, 1, 1, "sSet foregroud color: ",
+ "Set foreground (text) color to COLOR.")
+ (arg)
+ Lisp_Object arg;
+{
+ Color cdef;
+ BLOCK_INPUT_DECLARE ()
+ char *save_color;
+
+ save_color = fore_color;
+ check_xterm ();
+ CHECK_STRING (arg,1);
+ fore_color = (char *) xmalloc (XSTRING (arg)->size + 1);
+ BLOCK_INPUT ();
+ bcopy (XSTRING (arg)->data, fore_color, XSTRING (arg)->size + 1);
+ if (fore_color && DisplayCells () > 2 &&
+ XParseColor (fore_color, &cdef) && XGetHardwareColor (&cdef))
+ {
+ fore = cdef.pixel;
+ }
+ else if (fore_color && strcmp (fore_color, "black") == 0)
+ {
+ fore = BlackPixel;
+ }
+ else if (fore_color && strcmp (fore_color, "white") == 0)
+ {
+ fore = WhitePixel;
+ }
+ else
+ {
+ fore_color = save_color;
+ }
+ /* XPixFill (XXwindow, 0, 0, screen_width * fontinfo->width,
+ screen_height * fontinfo->height, back, ClipModeClipped,
+ GXcopy, AllPlanes);*/
+ Fredraw_display ();
+ /* dumprectangle (0, 0, screen_height * fontinfo->height,
+ screen_width * fontinfo -> width);*/
+ /* PendingExposure = 1;
+ xfixscreen ();*/
+ UNBLOCK_INPUT ();
+ XFlush ();
+ return Qt;
+}
+
+DEFUN ("x-set-background-color", Fx_set_background_color,
+ Sx_set_background_color, 1, 1, "sSet background color: ",
+ "Set background color to COLOR.")
+ (arg)
+ Lisp_Object arg;
+{
+ Color cdef;
+ Pixmap temp;
+ BLOCK_INPUT_DECLARE ()
+ char *save_color;
+
+ check_xterm ();
+ CHECK_STRING (arg,1);
+ save_color = back_color;
+ back_color = (char *) xmalloc (XSTRING (arg)->size + 1);
+ bcopy (XSTRING (arg)->data, back_color, XSTRING (arg)->size + 1);
+ BLOCK_INPUT ();
+ if (back_color && DisplayCells () > 2 &&
+ XParseColor (back_color, &cdef) && XGetHardwareColor (&cdef))
+ {
+ back = cdef.pixel;
+ }
+ else if (back_color && strcmp (back_color, "white") == 0)
+ {
+ back = WhitePixel;
+ }
+ else if (back_color && strcmp (back_color, "black") == 0)
+ {
+ back = BlackPixel;
+ }
+ else
+ {
+ back_color = save_color;
+ }
+ temp = XMakeTile (back);
+ XChangeBackground (XXwindow, temp);
+ /* XPixFill (XXwindow, 0, 0, screen_width * fontinfo->width,
+ screen_height * fontinfo->height, back, ClipModeClipped,
+ GXcopy, AllPlanes);*/
+ UNBLOCK_INPUT ();
+ Fredraw_display ();
+ /* dumprectangle (0, 0, screen_height * fontinfo->height,
+ screen_width * fontinfo -> width);*/
+ /* PendingExposure = 1;
+ xfixscreen ();*/
+ XFlush ();
+ XFreePixmap (temp);
+ return Qt;
+}
+
+DEFUN ("x-set-border-color", Fx_set_border_color, Sx_set_border_color, 1, 1,
+ "sSet border color: ",
+ "Set border color to COLOR.")
+ (arg)
+ Lisp_Object arg;
+{
+ Color cdef;
+ Pixmap temp;
+ BLOCK_INPUT_DECLARE ()
+
+ check_xterm ();
+ CHECK_STRING (arg,1);
+ brdr_color= (char *) xmalloc (XSTRING (arg)->size + 1);
+ bcopy (XSTRING (arg)->data, brdr_color, XSTRING (arg)->size + 1);
+ BLOCK_INPUT ();
+ if (brdr_color && DisplayCells () > 2 &&
+ XParseColor (brdr_color, &cdef) && XGetHardwareColor (&cdef))
+ {
+ temp = XMakeTile (cdef.pixel);
+ brdr = cdef.pixel;
+ }
+ else if (brdr_color && strcmp (brdr_color, "black") == 0)
+ {
+ temp = BlackPixmap;
+ brdr = BlackPixel;
+ }
+ else if (brdr_color && strcmp (brdr_color, "white") == 0)
+ {
+ temp = WhitePixmap;
+ brdr = WhitePixel;
+ }
+ else
+ {
+ temp = XMakePixmap ((Bitmap) XStoreBitmap (16, 16, gray_bits),
+ BlackPixel, WhitePixel);
+ brdr = BlackPixel;
+ brdr_color = "gray";
+ }
+ if (XXborder)
+ XChangeBorder (XXwindow, temp);
+ UNBLOCK_INPUT ();
+ XFreePixmap (temp);
+ return Qt;
+}
+
+DEFUN ("x-set-cursor-color", Fx_set_cursor_color, Sx_set_cursor_color, 1, 1,
+ "sSet text cursor color: ",
+ "Set text cursor color to COLOR.")
+ (arg)
+ Lisp_Object arg;
+{
+ Color cdef;
+ BLOCK_INPUT_DECLARE ()
+ char *save_color;
+
+ check_xterm ();
+ CHECK_STRING (arg,1);
+ save_color = curs_color;
+ curs_color = (char *) xmalloc (XSTRING (arg)->size + 1);
+ BLOCK_INPUT ();
+ bcopy (XSTRING (arg)->data, curs_color, XSTRING (arg)->size + 1);
+ if (curs_color && DisplayCells () > 2 &&
+ XParseColor (curs_color, &cdef) && XGetHardwareColor (&cdef))
+ {
+ curs = cdef.pixel;
+ }
+ else if (curs_color && strcmp (curs_color, "black") == 0)
+ {
+ curs = BlackPixel;
+ }
+ else if (curs_color && strcmp (curs_color, "white") == 0)
+ {
+ curs = WhitePixel;
+ }
+ else
+ {
+ curs_color = save_color;
+ }
+ CursorToggle ();
+ CursorToggle ();
+ UNBLOCK_INPUT ();
+ return Qt;
+}
+
+DEFUN ("x-set-mouse-color", Fx_set_mouse_color, Sx_set_mouse_color, 1, 1,
+ "sSet mouse cursor color: ",
+ "Set mouse cursor color to COLOR.")
+ (arg)
+ Lisp_Object arg;
+{
+ Cursor temp;
+ BLOCK_INPUT_DECLARE ()
+ Color cdef;
+ char *save_color;
+
+ check_xterm ();
+ CHECK_STRING (arg,1);
+ save_color = mous_color;
+ mous_color = (char *) xmalloc (XSTRING (arg)->size + 1);
+ BLOCK_INPUT ();
+ bcopy (XSTRING (arg)->data, mous_color, XSTRING (arg)->size + 1);
+
+ if (mous_color && DisplayCells () > 2
+ && XParseColor (mous_color, &cdef) && XGetHardwareColor (&cdef))
+ {
+ mous = cdef.pixel;
+ }
+ else if (mous_color && strcmp (mous_color, "black") == 0)
+ {
+ mous = BlackPixel;
+ }
+ else if (mous_color && strcmp (mous_color, "white") == 0)
+ {
+ mous = WhitePixel;
+ }
+ else
+ {
+ mous_color = save_color;
+ }
+ temp = XCreateCursor (16, 16, MouseCursor, MouseMask, 0, 0,
+ mous, back, GXcopy);
+ XDefineCursor (XXwindow, temp);
+ XFreeCursor (EmacsCursor);
+ UNBLOCK_INPUT ();
+ bcopy (&temp, &EmacsCursor, sizeof (Cursor));
+ return Qt;
+}
+
+DEFUN ("x-color-p", Fx_color_p, Sx_color_p, 0, 0, 0,
+ "Returns t if the display is a color X terminal.")
+ ()
+{
+ check_xterm ();
+ if (DisplayCells () > 2)
+ return Qt;
+ else
+ return Qnil;
+}
+
+DEFUN ("x-get-foreground-color", Fx_get_foreground_color,
+ Sx_get_foreground_color, 0, 0, 0,
+ "Returns the color of the foreground, as a string.")
+ ()
+{
+ Lisp_Object string;
+ string = build_string (fore_color);
+ return string;
+}
+
+DEFUN ("x-get-background-color", Fx_get_background_color,
+ Sx_get_background_color, 0, 0, 0,
+ "Returns the color of the background, as a string.")
+ ()
+{
+ Lisp_Object string;
+ string = build_string (back_color);
+ return string;
+}
+
+DEFUN ("x-get-border-color", Fx_get_border_color,
+ Sx_get_border_color, 0, 0, 0,
+ "Returns the color of the border, as a string.")
+ ()
+{
+ Lisp_Object string;
+ string = build_string (brdr_color);
+ return string;
+}
+
+DEFUN ("x-get-cursor-color", Fx_get_cursor_color,
+ Sx_get_cursor_color, 0, 0, 0,
+ "Returns the color of the cursor, as a string.")
+ ()
+{
+ Lisp_Object string;
+ string = build_string (curs_color);
+ return string;
+}
+
+DEFUN ("x-get-mouse-color", Fx_get_mouse_color,
+ Sx_get_mouse_color, 0, 0, 0,
+ "Returns the color of the mouse cursor, as a string.")
+ ()
+{
+ Lisp_Object string;
+ string = build_string (mous_color);
+ return string;
+}
+
+DEFUN ("x-get-default", Fx_get_default, Sx_get_default, 1, 1, 0,
+ "Get X default ATTRIBUTE from the system. Returns nil if\n\
+attribute does not exist.")
+ (arg)
+ Lisp_Object arg;
+{
+ unsigned char *default_name, *value;
+
+ CHECK_STRING (arg, 1);
+ default_name = XSTRING (arg)->data;
+
+ value = (unsigned char *) XGetDefault ("emacs", default_name);
+ /* if (value == 0)
+ value = XGetDefault ("", default_name); */
+ if (value)
+ return build_string (value);
+ else
+ return (Qnil);
+}
+
+DEFUN ("x-set-icon", Fx_set_icon, Sx_set_icon, 1, 1, "P",
+ "Set type of icon used by X for Emacs's window.\n\
+ARG non-nil means use kitchen-sink icon;\n\
+nil means use generic window manager icon.")
+ (arg)
+ Lisp_Object arg;
+{
+ check_xterm ();
+ if (NULL (arg))
+ XTextIcon ();
+ else
+ XBitmapIcon ();
+ return arg;
+}
+
+DEFUN ("x-set-font", Fx_set_font, Sx_set_font, 1, 1, "sFont Name: ",
+ "At initialization sets the font to be used for the X window.")
+ (arg)
+ Lisp_Object arg;
+{
+ register char *newfontname;
+
+ CHECK_STRING (arg, 1);
+ check_xterm ();
+
+ newfontname = (char *) xmalloc (XSTRING (arg)->size + 1);
+ bcopy (XSTRING (arg)->data, newfontname, XSTRING (arg)->size + 1);
+ if (XSTRING (arg)->size == 0)
+ /* XOpenFont ("") gets a badarg error rather than a badfont error.
+ I believe this is an X bug.
+ In emacs, badarg errors cause emacs to die, whilst badfont errors
+ are caught. This kludge prevents us from dying.
+ */
+ goto badfont;
+
+ if (!XNewFont (newfontname))
+ {
+ free (XXcurrentfont);
+ XXcurrentfont = newfontname;
+ return Qt;
+ }
+ else
+ {
+ badfont:
+ error ("Font \"%s\" is not defined", newfontname);
+ free (newfontname);
+ }
+
+ return Qnil;
+}
+
+DEFUN ("x-set-window-edges", Fx_set_window_edges, Sx_set_window_edges, 4, 4,
+ "nNumber of Columns: \nnNumber of Rows: \nnX Offset in Pixels: \n\
+nY Offset in Pixels: ",
+ "Sets X window size/position: size COLS by ROWS, positions XOFF and YOFF.\n\
+To get \"minus zero\" for XOFF or YOFF, supply -1.")
+ (cols, rows, xoffset, yoffset)
+ Lisp_Object rows, cols, xoffset, yoffset;
+{
+ BLOCK_INPUT_DECLARE ()
+
+ CHECK_NUMBER (rows, 1);
+ CHECK_NUMBER (cols, 2);
+ CHECK_NUMBER (xoffset, 3);
+ CHECK_NUMBER (yoffset, 4);
+ check_xterm ();
+
+ BLOCK_INPUT ();
+ x_edges_specified = 1;
+ if (XINT (rows) != screen_width || XINT (cols) != screen_height)
+ {
+ XSetWindowSize (XINT (rows), XINT (cols));
+ }
+ XSetOffset (XINT (xoffset), XINT (yoffset));
+ XFlush ();
+ UNBLOCK_INPUT ();
+ return Qt;
+}
+
+DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,
+ Scoordinates_in_window_p, 2, 2, 0,
+ "Return non-nil if POSITIONS (a list, (SCREEN-X SCREEN-Y)) is in WINDOW.\n\
+Returned value is list of positions expressed\n\
+relative to window upper left corner.")
+ (coordinate, window)
+ register Lisp_Object coordinate, window;
+{
+ register Lisp_Object xcoord, ycoord;
+
+ if (!CONSP (coordinate)) wrong_type_argument (Qlistp, coordinate);
+ CHECK_WINDOW (window, 2);
+ xcoord = Fcar (coordinate);
+ ycoord = Fcar (Fcdr (coordinate));
+ CHECK_NUMBER (xcoord, 0);
+ CHECK_NUMBER (ycoord, 1);
+ if ((XINT (xcoord) < XINT (XWINDOW (window)->left)) ||
+ (XINT (xcoord) >= (XINT (XWINDOW (window)->left) +
+ XINT (XWINDOW (window)->width))))
+ {
+ return Qnil;
+ }
+ XFASTINT (xcoord) -= XFASTINT (XWINDOW (window)->left);
+ if (XINT (ycoord) == (screen_height - 1))
+ return Qnil;
+ if ((XINT (ycoord) < XINT (XWINDOW (window)->top)) ||
+ (XINT (ycoord) >= (XINT (XWINDOW (window)->top) +
+ XINT (XWINDOW (window)->height)) - 1))
+ {
+ return Qnil;
+ }
+ XFASTINT (ycoord) -= XFASTINT (XWINDOW (window)->top);
+ return Fcons (xcoord, Fcons (ycoord, Qnil));
+}
+
+DEFUN ("x-mouse-events", Fx_mouse_events, Sx_mouse_events, 0, 0, 0,
+ "Return number of pending mouse events from X window system.")
+ ()
+{
+ register Lisp_Object tem;
+ register int windex, rindex, mindex;
+
+ check_xterm ();
+ windex = Xxrepbuffer.windex;
+ rindex = Xxrepbuffer.rindex;
+ mindex = Xxrepbuffer.mindex;
+
+ if (windex >= rindex)
+ {
+ XSET (tem, Lisp_Int, windex - rindex);
+ }
+ else
+ {
+ XSET (tem, Lisp_Int, mindex + 1 - (rindex - windex));
+ }
+ return tem;
+}
+
+DEFUN ("x-proc-mouse-event", Fx_proc_mouse_event, Sx_proc_mouse_event,
+ 0, 0, 0,
+ "Pulls a mouse event out of the mouse event buffer and dispatches\n\
+the appropriate function to act upon this event.")
+ ()
+{
+ XButtonEvent xrep;
+ register Lisp_Object Mouse_Cmd;
+ register char com_letter;
+ register char key_mask;
+ register Lisp_Object tempx;
+ register Lisp_Object tempy;
+ extern Lisp_Object get_keyelt ();
+
+ check_xterm ();
+ if (unloadxrepbuffer (&xrep, &Xxrepbuffer) == 0)
+ {
+ com_letter = xrep.detail & 3;
+ key_mask = (xrep.detail >> 8) & 0xf0;
+ com_letter |= key_mask;
+#ifndef HPUX
+ if (xrep.type == ButtonReleased) com_letter |= 0x04;
+#endif
+ XSET (tempx, Lisp_Int, min (screen_width-1, max (0, (xrep.x - XXInternalBorder)/fontinfo->width)));
+ XSET (tempy, Lisp_Int, min (screen_height-1, max (0, (xrep.y - XXInternalBorder)/fontinfo->height)));
+ Vx_mouse_pos = Fcons (tempx, Fcons (tempy, Qnil));
+ XSET (tempx, Lisp_Int, xrep.x + XXxoffset);
+ XSET (tempy, Lisp_Int, xrep.y + XXyoffset);
+ Vx_mouse_abs_pos = Fcons (tempx, Fcons (tempy, Qnil));
+ Vx_mouse_item = make_number (com_letter);
+ Mouse_Cmd = get_keyelt (access_keymap (MouseMap, com_letter));
+ if (NULL (Mouse_Cmd))
+ {
+#ifndef HPUX
+ if (xrep.type != ButtonReleased)
+ bell ();
+#endif
+ Vx_mouse_pos = Qnil;
+ Vx_mouse_abs_pos = Qnil;
+ }
+ else
+ {
+ return call1 (Mouse_Cmd, Vx_mouse_pos);
+ }
+ }
+ return Qnil;
+}
+
+DEFUN ("x-get-mouse-event", Fx_get_mouse_event, Sx_get_mouse_event,
+ 1, 1, 0,
+ "Get next mouse event out of mouse event buffer (com-letter (x y)).\n\
+ARG non-nil means return nil immediately if no pending event;\n\
+otherwise, wait for an event.")
+ (arg)
+ Lisp_Object arg;
+{
+ XButtonEvent xrep;
+ register Lisp_Object Mouse_Cmd;
+ register char com_letter;
+ register char key_mask;
+
+ register Lisp_Object tempx;
+ register Lisp_Object tempy;
+ extern Lisp_Object get_keyelt ();
+
+ check_xterm ();
+
+ if (NULL (arg))
+ while (Xxrepbuffer.windex == Xxrepbuffer.rindex);
+/*** ??? Surely you don't mean to busy wait??? */
+ if (unloadxrepbuffer (&xrep, &Xxrepbuffer) == 0)
+ {
+ com_letter = *((char *)&xrep.detail);
+ com_letter &= 3;
+ key_mask = *((char *)&xrep.detail + 1);
+ key_mask &= 0xf0;
+ com_letter |= key_mask;
+#ifndef HPUX
+ if (xrep.type == ButtonReleased) com_letter |= 0x04;
+#endif
+ XSET (tempx, Lisp_Int, min (screen_width, max (0, (xrep.x - XXInternalBorder)/fontinfo->width)));
+ XSET (tempy, Lisp_Int, min (screen_height, max (0, (xrep.y - XXInternalBorder)/fontinfo->height)));
+ Vx_mouse_pos = Fcons (tempx, Fcons (tempy, Qnil));
+ XSET (tempx, Lisp_Int, xrep.x + XXxoffset);
+ XSET (tempy, Lisp_Int, xrep.y + XXyoffset);
+ Vx_mouse_abs_pos = Fcons (tempx, Fcons (tempy, Qnil));
+ return Fcons (com_letter, Fcons (Vx_mouse_pos, Qnil));
+ }
+ return Qnil;
+}
+
+DEFUN ("x-set-keyboard-enable", Fx_set_keyboard_enable,
+ Sx_set_keyboard_enable, 1, 1, 0,
+ "In the X window system, set the flag that permite keyboard input.\n\
+Permit input if ARG is non-nil.")
+ (arg)
+ Lisp_Object arg;
+{
+ BLOCK_INPUT_DECLARE ()
+
+ check_xterm ();
+
+ BLOCK_INPUT ();
+ XSelectInput (XXwindow,
+ ExposeWindow | ButtonPressed
+#ifndef HPUX
+ | ButtonReleased
+#endif
+ | ExposeRegion | ExposeCopy | (!NULL (arg) ? KeyPressed : 0));
+ UNBLOCK_INPUT ();
+ return arg;
+}
+
+DEFUN ("x-set-mouse-inform-flag", Fx_set_mouse_inform_flag,
+ Sx_set_mouse_inform_flag, 1, 1, 0,
+ "Set inform-of-mouse-events flag in X window system on if ARG is non-nil.")
+ (arg)
+ Lisp_Object arg;
+{
+ informflag = !NULL (arg);
+ return arg;
+}
+
+DEFUN ("x-store-cut-buffer", Fx_store_cut_buffer, Sx_store_cut_buffer,
+ 1, 1, "sSend string to X:",
+ "Store contents of STRING into the cut buffer of the X window system.")
+ (string)
+ register Lisp_Object string;
+{
+ BLOCK_INPUT_DECLARE ()
+
+ CHECK_STRING (string, 1);
+ check_xterm ();
+
+ BLOCK_INPUT ();
+ XStoreBytes (XSTRING (string)->data, XSTRING (string)->size);
+ UNBLOCK_INPUT ();
+
+ return Qnil;
+}
+
+DEFUN ("x-get-cut-buffer", Fx_get_cut_buffer, Sx_get_cut_buffer, 0, 0, 0,
+ "Return contents of cut buffer of the X window system, as a string.")
+ ()
+{
+ int len;
+ register Lisp_Object string;
+ BLOCK_INPUT_DECLARE ()
+ register char *d;
+
+ BLOCK_INPUT ();
+ d = XFetchBytes (&len);
+ string = make_string (d, len);
+ UNBLOCK_INPUT ();
+ return string;
+}
+
+DEFUN ("x-rubber-band", Fx_rubber_band, Sx_rubber_band, 0, 0, "",
+ "Ask user to specify Emacs window position and size with mouse.\n\
+This is done automatically if the data has not been specified\n\
+when Emacs needs the window to be displayed.")
+ ()
+{
+ int x, y, width, height;
+ BLOCK_INPUT_DECLARE ()
+
+ x_edges_specified = 1;
+
+ check_xterm ();
+ BLOCK_INPUT ();
+ window_fetch (fontinfo->id, &x, &y, &width, &height, "", default_window,
+ XXborder, "GNU Emacs");
+ XSetWindowSize (height, width);
+ XSetOffset (x, y);
+ XFlush ();
+ ++screen_garbaged;
+ UNBLOCK_INPUT ();
+ return Qnil;
+}
+
+DEFUN ("x-create-x-window", Fx_create_x_window, Sx_create_x_window,
+ 1, 1, 0,
+ "Create window for GNU Emacs from a valid GEOMETRY specification.")
+ (arg)
+ Lisp_Object arg;
+{
+ int x, y, width, height;
+ char *geometry;
+ BLOCK_INPUT_DECLARE ()
+
+ x_edges_specified = 1;
+
+ check_xterm ();
+ CHECK_STRING (arg, 1);
+ geometry= (char *) xmalloc (XSTRING (arg)->size + 1);
+ bcopy (XSTRING (arg)->data, geometry, XSTRING (arg)->size + 1);
+ BLOCK_INPUT ();
+ window_fetch (fontinfo->id, &x, &y, &width, &height, geometry,
+ default_window, XXborder, "GNU Emacs");
+ XSetWindowSize (height, width);
+/* XSetWindowSize ((height - (2 * XXborder))/fontinfo -> height,
+ (width - (2 * XXborder))/fontinfo -> width);*/
+ XSetOffset (x, y);
+ XMapWindow (XXwindow);
+ XFlush ();
+ UNBLOCK_INPUT ();
+ return Qnil;
+}
+
+
+static int
+grey_p (colour)
+ char *colour;
+{
+ return (!strcmp (colour, "grey") || !strcmp (colour, "Grey") ||
+ !strcmp (colour, "gray") || !strcmp (colour, "Gray"));
+}
+
+DEFUN ("x-set-border-width", Fx_set_border_width, Sx_set_border_width,
+ 1, 1, "NSet border width: ",
+ "Set width of border to WIDTH, in the X window system.")
+ (borderwidth)
+ register Lisp_Object borderwidth;
+{
+ WindowInfo WinInfo;
+ BLOCK_INPUT_DECLARE ()
+ Window tempwindow;
+ register int temppixelwidth;
+ register int temppixelheight;
+ register int tempx;
+ register int tempy;
+ Pixmap temp_brdr, temp_back;
+
+ CHECK_NUMBER (borderwidth, 0);
+
+ check_xterm ();
+
+ if (XINT (borderwidth) < 0) XSETINT (borderwidth, 0);
+
+ temppixelwidth = screen_width * fontinfo->width + 2 * XXInternalBorder;
+ temppixelheight = screen_height * fontinfo->height + 2 * XXInternalBorder;
+ BLOCK_INPUT ();
+ XQueryWindow (XXwindow, &WinInfo);
+ tempx = WinInfo.x;
+ tempy = WinInfo.y;
+ if (grey_p (brdr_color))
+ temp_brdr = XMakePixmap ((Bitmap) XStoreBitmap (16, 16, gray_bits),
+ BlackPixel, WhitePixel);
+ else
+ temp_brdr = XMakeTile (brdr);
+ temp_back = XMakeTile (back);
+ tempwindow = XCreateWindow (RootWindow,
+ tempx /* Absolute horizontal offset */,
+ tempy /* Absolute Vertical offset */,
+ temppixelwidth, temppixelheight,
+ XINT (borderwidth),
+ temp_brdr, temp_back);
+ if (tempwindow)
+ {
+ XDestroyWindow (XXwindow);
+ XXwindow = tempwindow;
+ pixelwidth = temppixelwidth;
+ pixelheight = temppixelheight;
+ XXborder = XINT (borderwidth);
+ XSelectInput (XXwindow, NoEvent);
+ XSetResizeHint (XXwindow, 2 * XXInternalBorder, 2 * XXInternalBorder,
+ /* fontinfo->width * 1, fontinfo->height * 1, */
+ fontinfo->width, fontinfo->height);
+ XStoreName (XXwindow, &iconidentity[0]);
+ XDefineCursor (XXwindow, EmacsCursor);
+ XFreePixmap (temp_brdr);
+ XFreePixmap (temp_back);
+ UNBLOCK_INPUT_RESIGNAL ();
+ if (WindowMapped)
+ {
+ XMapWindow (XXwindow);
+ XSelectInput (XXwindow, KeyPressed | ExposeWindow | ButtonPressed
+#ifndef HPUX
+ | ButtonReleased
+#endif
+ | ExposeRegion | ExposeCopy);
+ ++screen_garbaged;
+ XFlush ();
+ }
+ return Qt;
+ }
+ else
+ {
+ UNBLOCK_INPUT_RESIGNAL ();
+ message ("Could not recreate window.");
+ return Qnil;
+ }
+}
+
+
+DEFUN ("x-set-internal-border-width", Fx_set_internal_border_width,
+ Sx_set_internal_border_width, 1, 1, "NSet internal border width: ",
+ "Set width of internal border to WIDTH, in the X window system.")
+ (internalborderwidth)
+ register Lisp_Object internalborderwidth;
+{
+ WindowInfo WinInfo;
+ BLOCK_INPUT_DECLARE ()
+ Window tempwindow;
+ register int temppixelwidth;
+ register int temppixelheight;
+ register int tempx;
+ register int tempy;
+ register int intbord;
+ Pixmap temp_brdr, temp_back;
+
+ CHECK_NUMBER (internalborderwidth, 0);
+
+ check_xterm ();
+
+ if (XINT (internalborderwidth) < 0) XSETINT (internalborderwidth, 0);
+ intbord = XINT (internalborderwidth);
+ temppixelwidth = screen_width * fontinfo->width + 2 * intbord;
+ temppixelheight = screen_height * fontinfo->height + 2 * intbord;
+ BLOCK_INPUT ();
+ XQueryWindow (XXwindow, &WinInfo);
+ tempx = WinInfo.x;
+ tempy = WinInfo.y;
+ if (grey_p (brdr_color))
+ temp_brdr = XMakePixmap ((Bitmap) XStoreBitmap (16, 16, gray_bits),
+ BlackPixel, WhitePixel);
+ else
+ temp_brdr = XMakeTile (brdr);
+ temp_back = XMakeTile (back);
+ tempwindow = XCreateWindow (RootWindow,
+ tempx /* Absolute horizontal offset */,
+ tempy /* Absolute Vertical offset */,
+ temppixelwidth, temppixelheight,
+ XXborder,
+ temp_brdr, temp_back);
+ if (tempwindow)
+ {
+ XDestroyWindow (XXwindow);
+ XXwindow = tempwindow;
+ pixelwidth = temppixelwidth;
+ pixelheight = temppixelheight;
+ XXInternalBorder = intbord;
+ XSelectInput (XXwindow, NoEvent);
+ XSetResizeHint (XXwindow, 2 * XXInternalBorder, 2 * XXInternalBorder,
+ /* fontinfo->width * 1, fontinfo->height * 1, */
+ fontinfo->width, fontinfo->height);
+ XStoreName (XXwindow, &iconidentity[0]);
+ XDefineCursor (XXwindow, EmacsCursor);
+ XFreePixmap (temp_brdr);
+ XFreePixmap (temp_back);
+ UNBLOCK_INPUT_RESIGNAL ();
+ if (WindowMapped)
+ {
+ XMapWindow (XXwindow);
+ XSelectInput (XXwindow, KeyPressed | ExposeWindow | ButtonPressed
+#ifndef HPUX
+ | ButtonReleased
+#endif
+ | ExposeRegion | ExposeCopy);
+ ++screen_garbaged;
+ XFlush ();
+ }
+ return Qt;
+ }
+ else
+ {
+ UNBLOCK_INPUT_RESIGNAL ();
+ message ("Could not recreate window.");
+ return Qnil;
+ }
+}
+
+jmp_buf dispenv;
+Display *OldDisplay;
+FontInfo *OldFontInfo;
+Window OldWindow;
+
+XRestoreDisplay ()
+{
+ longjmp (dispenv, "Unable to access display (probably)");
+}
+
+DEFUN ("x-change-display", Fx_change_display, Sx_change_display, 1, 1,
+ "sNew display name: ",
+ "This function takes one argument, the display where you wish to\n\
+continue your editing session. Your current window will be unmapped and\n\
+the current display will be closed. The new X display will be opened and\n\
+the rubber-band outline of the new window will appear on the new X display.\n\
+This function does not look at your .Xdefaults file, so you should use the\n\
+function x-new-display instead.")
+ (new_display)
+ register Lisp_Object new_display;
+{
+ Cursor OldEmacsCursor;
+ BLOCK_INPUT_DECLARE ()
+ register int (*pipefunc) ();
+ register char *newdisplayname = 0;
+ int x, y, width, height;
+ int temp_icon;
+ int XRestoreDisplay ();
+ Pixmap temp_brdr, temp_back;
+ register char *XXerrorcode;
+
+ CHECK_STRING (new_display, 1);
+ check_xterm ();
+
+/* newdisplayname = xmalloc (XSTRING (new_display)->size + 1); */
+/* bcopy (XSTRING (new_display)->data, newdisplayname, */
+/* XSTRING (new_display)->size + 1); */
+ /* Since this was freed at the end, why not just use the original? */
+ newdisplayname = (char *) XSTRING (new_display)->data;
+ BLOCK_INPUT ();
+ XIOErrorHandler (XRestoreDisplay);
+ if (XXerrorcode = (char *) setjmp (dispenv))
+ {
+ /* free (&newdisplayname[0]); */
+ if (fontinfo)
+ XCloseFont (fontinfo);
+ if (XXwindow)
+ XDestroyWindow (XXwindow);
+ if (XXdisplay)
+ XCloseDisplay (XXdisplay);
+ XXdisplay = OldDisplay;
+ fontinfo = OldFontInfo;
+ XXwindow = OldWindow;
+ EmacsCursor = OldEmacsCursor;
+ XIOErrorHandler (handler);
+ XSetDisplay (XXdisplay);
+ UNBLOCK_INPUT_RESIGNAL ();
+ error ("Display change problem: %s", XXerrorcode);
+ }
+ else
+ {
+ OldEmacsCursor = EmacsCursor;
+ OldDisplay = XXdisplay;
+ OldFontInfo = fontinfo;
+ OldWindow = XXwindow;
+ XXwindow = 0;
+ fontinfo = 0;
+ XXdisplay = 0;
+ }
+ XXdisplay = XOpenDisplay (newdisplayname);
+ if (!XXdisplay)
+ {
+ longjmp (dispenv, "Probably nonexistant display");
+ }
+ XQueryWindow (RootWindow, &rootwindowinfo);
+ fontinfo = XOpenFont (XXcurrentfont);
+ if (!fontinfo)
+ {
+ longjmp (dispenv, "Bad font");
+ }
+ /* pixelwidth and pixelheight are correct*/
+ XXwindow = XCreateWindow (RootWindow,
+ XXxoffset,
+ XXyoffset,
+ pixelwidth, pixelheight,
+ XXborder, BlackPixmap, WhitePixmap);
+ if (!XXwindow)
+ {
+ longjmp (dispenv, "Could not create window");
+ }
+ fore = BlackPixel;
+ back = WhitePixel;
+ brdr = BlackPixel;
+ mous = BlackPixel;
+ curs = BlackPixel;
+
+ fore_color = "black";
+ back_color = "white";
+ brdr_color = "black";
+ mous_color = "black";
+ curs_color = "black";
+
+ XSelectInput (XXwindow, NoEvent);
+ EmacsCursor = XCreateCursor (16, 16, MouseCursor, MouseMask,
+ 0, 0, mous, back, GXcopy);
+ XDefineCursor (XXwindow, EmacsCursor);
+ XSetResizeHint (XXwindow, 2 * XXInternalBorder, 2 * XXInternalBorder,
+ /* fontinfo->width * 1, fontinfo->height * 1, */
+ fontinfo->width, fontinfo->height);
+ XStoreName (XXwindow, iconidentity);
+/* WindowMapped = 0;*/
+ x_edges_specified = 0;
+ bitblt = 0;
+ CursorExists = 0;
+ VisibleX = 0;
+ VisibleY = 0;
+ XSetDisplay (XXdisplay);
+/* XQueryWindow (RootWindow, &rootwindowinfo);*/
+/* if (WindowMapped)
+ {*/
+ XXIconWindow = XCreateWindow (RootWindow, 0, 0, sink_width, sink_height,
+ 2, WhitePixmap, BlackPixmap);
+ XXIconMask = XStoreBitmap (sink_mask_width, sink_mask_height, sink_mask_bits);
+ WindowMapped = 0;
+ XPopUpWindow ();
+/* }*/
+ WindowMapped = 1;
+ XSetDisplay (OldDisplay);
+ XCloseFont (OldFontInfo);
+ XFreeCursor (OldEmacsCursor);
+ XDestroyWindow (OldWindow);
+ XSetDisplay (XXdisplay);
+ XCloseDisplay (OldDisplay);
+
+ x_init_1 (0);
+ UNBLOCK_INPUT_RESIGNAL ();
+/* free (newdisplayname); */
+/* x_edges_specified = 0;*/
+ ++screen_garbaged;
+ Fredraw_display ();
+ return Qt;
+}
+
+/*
+ Grabs mouse, outlines a window, etc.
+ if left button pressed, sizes a wd x hd window (in characters)
+ if right button pressed, sizes wd x what will fit window (in characters)
+ if middle button pressed, allows user to size window in font increments
+ (+ border * 2 for inner border);
+ While sizing, dimensions of window are displayed in upper left of root.
+ str is also displayed there.
+ In all cases, x and y are the desired coordinates for the upper lefthand
+ corner, *width = width desired, *height = height desired
+ (min for both is 1 font char).
+
+ */
+/*
+ This routine is a total crock. It makes a window using XCreateTerm
+ purely for return value, destroying the temporary window created in
+ the process. If XCreateTerm were broken into smaller, more easily
+ digestible pieces, it would be useful. As such, the constraints of
+ time, emacs, and X conventions force me into this crock. --rlk
+ */
+
+window_fetch (font, x, y, width, height, geo, deflt, border, str)
+ Font font;
+ int *x, *y, *width, *height;
+ char *geo, *deflt;
+ int border;
+ char *str;
+{
+ OpaqueFrame frame;
+ Window tempwindow;
+ WindowInfo WinInfo;
+ register int temppixelwidth;
+ register int temppixelheight;
+ Pixmap temp_brdr, temp_back;
+
+ temp_brdr = XMakeTile (brdr);
+ temp_back = XMakeTile (back);
+ frame.bdrwidth = border;
+ if (grey_p (brdr_color))
+ frame.border = XMakePixmap ((Bitmap) XStoreBitmap (16, 16, gray_bits),
+ BlackPixel, WhitePixel);
+ else
+ frame.border = XMakeTile (brdr);
+ frame.background = XMakeTile (back);
+ tempwindow = XCreateTerm (str, "emacs", geo, deflt, &frame, 10, 5,
+ 2 * XXInternalBorder, 2 * XXInternalBorder,
+ width, height, fontinfo, fontinfo->width,
+ fontinfo->height);
+ if (tempwindow)
+ {
+ XDestroyWindow (XXwindow);
+ XXwindow = tempwindow;
+ XSelectInput (XXwindow, NoEvent);
+ XSetResizeHint (XXwindow, 2 * XXInternalBorder, 2 * XXInternalBorder,
+ /* fontinfo->width * 1, fontinfo->height * 1, */
+ fontinfo->width, fontinfo->height);
+ XStoreName (XXwindow, &iconidentity[0]);
+ XDefineCursor (XXwindow, EmacsCursor);
+ XQueryWindow (XXwindow, &WinInfo);
+ *x = WinInfo.x;
+ *y = WinInfo.y;
+ XFreePixmap (temp_brdr);
+ XFreePixmap (temp_back);
+ RESIGNAL_INPUT ();
+ if (WindowMapped)
+ {
+ XMapWindow (XXwindow);
+ XSelectInput (XXwindow, KeyPressed | ExposeWindow | ButtonPressed
+#ifndef HPUX
+ | ButtonReleased
+#endif
+ | ExposeRegion | ExposeCopy);
+ ++screen_garbaged;
+ XFlush ();
+ }
+ return Qt;
+ }
+ else
+ {
+ RESIGNAL_INPUT ();
+ message ("Could not recreate window.");
+ return Qnil;
+ }
+}
+
+DEFUN ("x-rebind-key", Fx_rebind_key, Sx_rebind_key, 3, 3, 0,
+ "Rebind KEYCODE, with shift bits SHIFT-MASK, to new string NEWSTRING.\n\
+KEYCODE and SHIFT-MASK should be numbers representing the X keyboard code\n\
+and shift mask respectively. NEWSTRING is an arbitrary string of keystrokes.\n\
+If SHIFT-MASK is nil, then KEYCODE's key will be bound to NEWSTRING for\n\
+all shift combinations.\n\
+Shift Lock 1 Shift 2\n\
+Meta 4 Control 8\n\
+\n\
+For values of KEYCODE, see /usr/lib/Xkeymap.txt (remember that the codes\n\
+in that file are in octal!)\n\
+\n\
+NOTE: due to an X bug, this function will not take effect unless one has\n\
+a ~/.Xkeymap file. (See the documentation for the \"keycomp\" program.)\n\
+This problem will be fixed in X version 11.")
+
+ (keycode, shift_mask, newstring)
+ register Lisp_Object keycode;
+ register Lisp_Object shift_mask;
+ register Lisp_Object newstring;
+{
+ char *rawstring;
+ int rawkey, rawshift;
+ int i;
+ int strsize;
+
+ CHECK_NUMBER (keycode, 1);
+ if (!NULL (shift_mask))
+ CHECK_NUMBER (shift_mask, 2);
+ CHECK_STRING (newstring, 3);
+ strsize = XSTRING (newstring) ->size;
+ rawstring = (char *) xmalloc (strsize);
+ bcopy (XSTRING (newstring)->data, rawstring, strsize);
+ rawkey = ((unsigned) (XINT (keycode))) & 255;
+ if (NULL (shift_mask))
+ for (i = 0; i <= 15; i++)
+ XRebindCode (rawkey, i<<11, rawstring, strsize);
+ else
+ {
+ rawshift = (((unsigned) (XINT (shift_mask))) & 15) << 11;
+ XRebindCode (rawkey, rawshift, rawstring, strsize);
+ }
+ return Qnil;
+}
+
+DEFUN ("x-rebind-keys", Fx_rebind_keys, Sx_rebind_keys, 2, 2, 0,
+ "Rebind KEYCODE to list of strings STRINGS.\n\
+STRINGS should be a list of 16 elements, one for each all shift combination.\n\
+nil as element means don't change.\n\
+See the documentation of x-rebind-key for more information.")
+ (keycode, strings)
+ register Lisp_Object keycode;
+ register Lisp_Object strings;
+{
+ register Lisp_Object item;
+ register char *rawstring;
+ int rawkey, strsize;
+ register unsigned i;
+
+ CHECK_NUMBER (keycode, 1);
+ CHECK_CONS (strings, 2);
+ rawkey = ((unsigned) (XINT (keycode))) & 255;
+ for (i = 0; i <= 15; strings = Fcdr (strings), i++)
+ {
+ item = Fcar (strings);
+ if (!NULL (item))
+ {
+ CHECK_STRING (item, 2);
+ strsize = XSTRING (item)->size;
+ rawstring = (char *) xmalloc (strsize);
+ bcopy (XSTRING (item)->data, rawstring, strsize);
+ XRebindCode (rawkey, i << 11, rawstring, strsize);
+ }
+ }
+ return Qnil;
+}
+
+XExitWithCoreDump (Disp, Event)
+ Display *Disp;
+ XErrorEvent *Event;
+{
+ XCleanUp ();
+ abort ();
+}
+
+DEFUN ("x-debug", Fx_debug, Sx_debug, 1, 1, 0,
+ "ARG non-nil means that X errors should generate a coredump.")
+ (arg)
+ register Lisp_Object arg;
+{
+ if (!NULL (arg))
+ handler = XExitWithCoreDump;
+ else
+ {
+ extern int XExitGracefully ();
+ handler = XExitGracefully;
+ }
+ XErrorHandler (handler);
+ XIOErrorHandler (handler);
+ return (Qnil);
+}
+
+XRedrawDisplay ()
+{
+ Fredraw_display ();
+}
+
+XCleanUp ()
+{
+ Fdo_auto_save (Qt);
+#ifdef subprocesses
+ kill_buffer_processes (Qnil);
+#endif /* subprocesses */
+}
+
+
+syms_of_xfns ()
+{
+ x_edges_specified = 0;
+
+ DEFVAR_LISP ("x-mouse-item", &Vx_mouse_item,
+ "Encoded representation of last mouse click, corresponding to\n\
+numerical entries in x-mouse-map.");
+ Vx_mouse_item = Qnil;
+ DEFVAR_LISP ("x-mouse-pos", &Vx_mouse_pos,
+ "Current x-y position of mouse by row, column as specified by font.");
+ Vx_mouse_pos = Qnil;
+ DEFVAR_LISP ("x-mouse-abs-pos", &Vx_mouse_abs_pos,
+ "Current x-y position of mouse by row, column in pixels, wrt root window.");
+ Vx_mouse_abs_pos = Qnil;
+
+ defsubr (&Sx_pop_up_window);
+ defsubr (&Sx_set_bell);
+ defsubr (&Sx_flip_color);
+ defsubr (&Sx_set_icon);
+ defsubr (&Sx_set_font);
+ defsubr (&Sx_set_window_edges);
+ defsubr (&Scoordinates_in_window_p);
+ defsubr (&Sx_mouse_events);
+ defsubr (&Sx_proc_mouse_event);
+ defsubr (&Sx_get_mouse_event);
+ defsubr (&Sx_set_keyboard_enable);
+ defsubr (&Sx_set_mouse_inform_flag);
+ defsubr (&Sx_store_cut_buffer);
+ defsubr (&Sx_get_cut_buffer);
+ defsubr (&Sx_rubber_band);
+ defsubr (&Sx_create_x_window);
+ defsubr (&Sx_set_border_width);
+ defsubr (&Sx_set_internal_border_width);
+ defsubr (&Sx_change_display);
+ defsubr (&Sx_set_foreground_color);
+ defsubr (&Sx_set_background_color);
+ defsubr (&Sx_set_border_color);
+ defsubr (&Sx_set_cursor_color);
+ defsubr (&Sx_set_mouse_color);
+ defsubr (&Sx_get_foreground_color);
+ defsubr (&Sx_get_background_color);
+ defsubr (&Sx_get_border_color);
+ defsubr (&Sx_get_cursor_color);
+ defsubr (&Sx_get_mouse_color);
+ defsubr (&Sx_color_p);
+ defsubr (&Sx_get_default);
+ defsubr (&Sx_rebind_key);
+ defsubr (&Sx_rebind_keys);
+ defsubr (&Sx_debug);
+}
+
+#endif /* HAVE_X_WINDOWS */
+
diff --git a/src/xkeys-aix.h b/src/xkeys-aix.h
new file mode 100644
index 00000000000..20a5b927151
--- /dev/null
+++ b/src/xkeys-aix.h
@@ -0,0 +1,163 @@
+/* This file is included by x11term.c. It provides a workable keymapping */
+/* for X windows under AIX. */
+
+
+/*-------------------------------------------------------------------------*/
+/*---------------------------- shift --------------------------------------*/
+/* Turned on in 18.58 because backspace might as well work. */
+#if 1
+ XRebindKeysym(XXdisplay, XK_BackSpace, XMOD_Shift, 1, "\177", 1);
+#endif
+
+ XRebindKeysym(XXdisplay, XK_F1, XMOD_Shift, 1, "\033[013q", 6);
+ XRebindKeysym(XXdisplay, XK_F2, XMOD_Shift, 1, "\033[014q", 6);
+ XRebindKeysym(XXdisplay, XK_F3, XMOD_Shift, 1, "\033[015q", 6);
+ XRebindKeysym(XXdisplay, XK_F4, XMOD_Shift, 1, "\033[016q", 6);
+ XRebindKeysym(XXdisplay, XK_F5, XMOD_Shift, 1, "\033[017q", 6);
+ XRebindKeysym(XXdisplay, XK_F6, XMOD_Shift, 1, "\033[018q", 6);
+ XRebindKeysym(XXdisplay, XK_F7, XMOD_Shift, 1, "\033[019q", 6);
+ XRebindKeysym(XXdisplay, XK_F8, XMOD_Shift, 1, "\033[020q", 6);
+ XRebindKeysym(XXdisplay, XK_F9, XMOD_Shift, 1, "\033[021q", 6);
+ XRebindKeysym(XXdisplay, XK_F10, XMOD_Shift, 1, "\033[022q", 6);
+ XRebindKeysym(XXdisplay, XK_F11, XMOD_Shift, 1, "\033[023q", 6);
+ XRebindKeysym(XXdisplay, XK_F12, XMOD_Shift, 1, "\033[024q", 6);
+
+ XRebindKeysym(XXdisplay, XK_Print, XMOD_Shift, 1, "\033[210q", 6);
+ XRebindKeysym(XXdisplay, XK_Cancel, XMOD_Shift, 1, "\033[214q", 6);
+ XRebindKeysym(XXdisplay, XK_Pause, XMOD_Shift, 1, "\033[218q", 6);
+
+ XRebindKeysym(XXdisplay, XK_Home, XMOD_Shift, 1, "\033[143q", 6);
+ XRebindKeysym(XXdisplay, XK_Prior, XMOD_Shift, 1, "\033[151q", 6);
+ XRebindKeysym(XXdisplay, XK_End, XMOD_Shift, 1, "\033[147q", 6);
+ XRebindKeysym(XXdisplay, XK_Next, XMOD_Shift, 1, "\033[155q", 6);
+
+ XRebindKeysym(XXdisplay, XK_Up, XMOD_Shift, 1, "\033[161q", 6);
+ XRebindKeysym(XXdisplay, XK_Left, XMOD_Shift, 1, "\033[158q", 6);
+ XRebindKeysym(XXdisplay, XK_Down, XMOD_Shift, 1, "\033[164q", 6);
+ XRebindKeysym(XXdisplay, XK_Right, XMOD_Shift, 1, "\033[167q", 6);
+
+/*-------------------------------------------------------------------------*/
+/*---------------------------- control ------------------------------------*/
+#if 0
+ XRebindKeysym(XXdisplay, XK_BackSpace, XMOD_Ctrl, 1, "\177", 1);
+#endif
+
+ XRebindKeysym(XXdisplay, XK_minus, XMOD_Ctrl, 1, "\037", 1);
+ XRebindKeysym(XXdisplay, XK_2, XMOD_Ctrl, 1, "\000", 1);
+ XRebindKeysym(XXdisplay, XK_space, XMOD_Ctrl, 1, "\000", 1);
+
+ XRebindKeysym(XXdisplay, XK_F1, XMOD_Ctrl, 1, "\033[025q", 6);
+ XRebindKeysym(XXdisplay, XK_F2, XMOD_Ctrl, 1, "\033[026q", 6);
+ XRebindKeysym(XXdisplay, XK_F3, XMOD_Ctrl, 1, "\033[027q", 6);
+ XRebindKeysym(XXdisplay, XK_F4, XMOD_Ctrl, 1, "\033[028q", 6);
+ XRebindKeysym(XXdisplay, XK_F5, XMOD_Ctrl, 1, "\033[029q", 6);
+ XRebindKeysym(XXdisplay, XK_F6, XMOD_Ctrl, 1, "\033[030q", 6);
+ XRebindKeysym(XXdisplay, XK_F7, XMOD_Ctrl, 1, "\033[031q", 6);
+ XRebindKeysym(XXdisplay, XK_F8, XMOD_Ctrl, 1, "\033[032q", 6);
+ XRebindKeysym(XXdisplay, XK_F9, XMOD_Ctrl, 1, "\033[033q", 6);
+ XRebindKeysym(XXdisplay, XK_F10, XMOD_Ctrl, 1, "\033[034q", 6);
+ XRebindKeysym(XXdisplay, XK_F11, XMOD_Ctrl, 1, "\033[035q", 6);
+ XRebindKeysym(XXdisplay, XK_F12, XMOD_Ctrl, 1, "\033[036q", 6);
+
+ XRebindKeysym(XXdisplay, XK_Print, XMOD_Ctrl, 1, "\033[211q", 6);
+ XRebindKeysym(XXdisplay, XK_Cancel, XMOD_Ctrl, 1, "\033[215q", 6);
+
+ XRebindKeysym(XXdisplay, XK_Insert, XMOD_Ctrl, 1, "\033[140q", 6);
+ XRebindKeysym(XXdisplay, XK_Home, XMOD_Ctrl, 1, "\033[144q", 6);
+ XRebindKeysym(XXdisplay, XK_Prior, XMOD_Ctrl, 1, "\033[152q", 6);
+
+#if 0
+ XRebindKeysym(XXdisplay, XK_Delete, XMOD_Ctrl, 1, "\033[142q", 6);
+#endif
+
+ XRebindKeysym(XXdisplay, XK_End, XMOD_Ctrl, 1, "\033[148q", 6);
+ XRebindKeysym(XXdisplay, XK_Next, XMOD_Ctrl, 1, "\033[156q", 6);
+
+ XRebindKeysym(XXdisplay, XK_Up, XMOD_Ctrl, 1, "\033[162q", 6);
+ XRebindKeysym(XXdisplay, XK_Left, XMOD_Ctrl, 1, "\033[159q", 6);
+ XRebindKeysym(XXdisplay, XK_Down, XMOD_Ctrl, 1, "\033[165q", 6);
+ XRebindKeysym(XXdisplay, XK_Right, XMOD_Ctrl, 1, "\033[168q", 6);
+
+/*-------------------------------------------------------------------------*/
+/*---------------------------- alternate ----------------------------------*/
+#if 0
+ XRebindKeysym(XXdisplay, XK_BackSpace, XMOD_Alt, 1, "\177", 1);
+#endif
+
+ XRebindKeysym(XXdisplay, XK_F1, XMOD_Alt, 1, "\033[037q", 6);
+ XRebindKeysym(XXdisplay, XK_F2, XMOD_Alt, 1, "\033[038q", 6);
+ XRebindKeysym(XXdisplay, XK_F3, XMOD_Alt, 1, "\033[039q", 6);
+ XRebindKeysym(XXdisplay, XK_F4, XMOD_Alt, 1, "\033[040q", 6);
+ XRebindKeysym(XXdisplay, XK_F5, XMOD_Alt, 1, "\033[041q", 6);
+ XRebindKeysym(XXdisplay, XK_F6, XMOD_Alt, 1, "\033[042q", 6);
+ XRebindKeysym(XXdisplay, XK_F7, XMOD_Alt, 1, "\033[043q", 6);
+ XRebindKeysym(XXdisplay, XK_F8, XMOD_Alt, 1, "\033[044q", 6);
+ XRebindKeysym(XXdisplay, XK_F9, XMOD_Alt, 1, "\033[045q", 6);
+ XRebindKeysym(XXdisplay, XK_F10, XMOD_Alt, 1, "\033[046q", 6);
+ XRebindKeysym(XXdisplay, XK_F11, XMOD_Alt, 1, "\033[047q", 6);
+ XRebindKeysym(XXdisplay, XK_F12, XMOD_Alt, 1, "\033[048q", 6);
+
+ XRebindKeysym(XXdisplay, XK_Print, XMOD_Alt, 1, "\033[212q", 6);
+ XRebindKeysym(XXdisplay, XK_Cancel, XMOD_Alt, 1, "\033[216q", 6);
+
+ XRebindKeysym(XXdisplay, XK_Insert, XMOD_Alt, 1, "\033[141q", 6);
+ XRebindKeysym(XXdisplay, XK_Home, XMOD_Alt, 1, "\033[145q", 6);
+ XRebindKeysym(XXdisplay, XK_Prior, XMOD_Alt, 1, "\033[153q", 6);
+
+#if 0
+ XRebindKeysym(XXdisplay, XK_Delete, XMOD_Alt, 1, "\033[M", 3);
+#endif
+
+ XRebindKeysym(XXdisplay, XK_End, XMOD_Alt, 1, "\033[149q", 6);
+ XRebindKeysym(XXdisplay, XK_Next, XMOD_Alt, 1, "\033[157q", 6);
+
+ XRebindKeysym(XXdisplay, XK_Up, XMOD_Alt, 1, "\033[163q", 6);
+ XRebindKeysym(XXdisplay, XK_Left, XMOD_Alt, 1, "\033[160q", 6);
+ XRebindKeysym(XXdisplay, XK_Down, XMOD_Alt, 1, "\033[166q", 6);
+ XRebindKeysym(XXdisplay, XK_Right, XMOD_Alt, 1, "\033[169q", 6);
+
+/*-------------------------------------------------------------------------*/
+/*---------------------------- normal -------------------------------------*/
+/* These come last because some versions of AIX fail to
+ pay attention to the specified modifier keys.
+ At least this way the unmodified keys will work right. */
+
+#if 0
+ XRebindKeysym(XXdisplay, XK_BackSpace, 0, 0, "\177", 1);
+#endif
+
+ XRebindKeysym(XXdisplay, XK_F1, 0, 0, "\033[001q", 6);
+ XRebindKeysym(XXdisplay, XK_F2, 0, 0, "\033[002q", 6);
+ XRebindKeysym(XXdisplay, XK_F3, 0, 0, "\033[003q", 6);
+ XRebindKeysym(XXdisplay, XK_F4, 0, 0, "\033[004q", 6);
+ XRebindKeysym(XXdisplay, XK_F5, 0, 0, "\033[005q", 6);
+ XRebindKeysym(XXdisplay, XK_F6, 0, 0, "\033[006q", 6);
+ XRebindKeysym(XXdisplay, XK_F7, 0, 0, "\033[007q", 6);
+ XRebindKeysym(XXdisplay, XK_F8, 0, 0, "\033[008q", 6);
+ XRebindKeysym(XXdisplay, XK_F9, 0, 0, "\033[009q", 6);
+ XRebindKeysym(XXdisplay, XK_F10, 0, 0, "\033[010q", 6);
+ XRebindKeysym(XXdisplay, XK_F11, 0, 0, "\033[011q", 6);
+ XRebindKeysym(XXdisplay, XK_F12, 0, 0, "\033[012q", 6);
+
+ XRebindKeysym(XXdisplay, XK_Print, 0, 0, "\033[209q", 6);
+ XRebindKeysym(XXdisplay, XK_Cancel, 0, 0, "\033[213q", 6);
+ XRebindKeysym(XXdisplay, XK_Pause, 0, 0, "\033[217q", 6);
+
+ XRebindKeysym(XXdisplay, XK_Insert, 0, 0, "\033[139q", 6);
+ XRebindKeysym(XXdisplay, XK_Home, 0, 0, "\033[H", 3);
+ XRebindKeysym(XXdisplay, XK_Prior, 0, 0, "\033[150q", 6);
+
+#if 0
+ XRebindKeysym(XXdisplay, XK_Delete, 0, 0, "\033[P", 3);
+#endif
+
+ XRebindKeysym(XXdisplay, XK_End, 0, 0, "\033[146q", 6);
+ XRebindKeysym(XXdisplay, XK_Next, 0, 0, "\033[154q", 6);
+
+ XRebindKeysym(XXdisplay, XK_Up, 0, 0, "\033[A", 3);
+ XRebindKeysym(XXdisplay, XK_Left, 0, 0, "\033[D", 3);
+ XRebindKeysym(XXdisplay, XK_Down, 0, 0, "\033[B", 3);
+ XRebindKeysym(XXdisplay, XK_Right, 0, 0, "\033[C", 3);
+
+ XRebindKeysym(XXdisplay, XK_Execute, 0, 0, "\033[114q", 6);
+
diff --git a/src/xmenu.c b/src/xmenu.c
index 553e5b35a7a..ff82793f24d 100644
--- a/src/xmenu.c
+++ b/src/xmenu.c
@@ -15,9 +15,9 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-/* X pop-up deck-of-cards menu facility for gnuemacs.
+ * X pop-up deck-of-cards menu facility for gnuemacs.
*
* Written by Jon Arnold and Roman Budzianowski
* Mods and rewrite by Robert Krawitz
@@ -34,20 +34,28 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef lint
static char *rcsid_GXMenu_c = "$Header: xmenu.c,v 1.6 86/08/26 17:23:26 rlk Exp $";
#endif lint
-#ifdef XDEBUG
-#include <stdio.h>
-#endif
/* On 4.3 this loses if it comes after xterm.h. */
#include <signal.h>
#include "config.h"
-#include "lisp.h"
-#include "screen.h"
-#include "window.h"
/* This may include sys/types.h, and that somehow loses
if this is not done before the other system files. */
+#ifdef X11
+#include "x11term.h"
+/* #include <X11/X10.h> */
+#else
#include "xterm.h"
+#endif
+
+/* Prepare for lisp.h definition of NULL.
+ Sometimes x11term.h includes stddef.h. */
+#ifdef NULL
+#undef NULL
+#endif
+
+#include "lisp.h"
+#include "window.h"
/* Load sys/types.h if not already loaded.
In some systems loading it twice is suicidal. */
@@ -57,12 +65,16 @@ static char *rcsid_GXMenu_c = "$Header: xmenu.c,v 1.6 86/08/26 17:23:26 rlk Exp
#include "dispextern.h"
-#ifdef HAVE_X11
+#ifdef X11
#include "../oldXMenu/XMenu.h"
+#define X11ONLY(arg) arg,
#else
#include <X/XMenu.h>
+#define X11ONLY(arg)
#endif
+#include "termopts.h"
+
#define min(x,y) (((x) < (y)) ? (x) : (y))
#define max(x,y) (((x) > (y)) ? (x) : (y))
@@ -73,43 +85,48 @@ static char *rcsid_GXMenu_c = "$Header: xmenu.c,v 1.6 86/08/26 17:23:26 rlk Exp
#define FALSE 0
#endif TRUE
-#ifdef HAVE_X11
-extern Display *x_current_display;
+#ifdef X11
+extern XFontStruct *fontinfo;
+extern Display *XXdisplay;
+extern Window XXwindow;
+extern int XXfontw;
+extern int XXfonth;
+int XXscreen;
#else
+extern int XXxoffset,XXyoffset;
+extern FontInfo *fontinfo;
#define ButtonReleaseMask ButtonReleased
-#endif /* not HAVE_X11 */
+#endif /* not X11 */
-Lisp_Object xmenu_show ();
-extern int x_error_handler ();
+extern int (*handler)();
/*************************************************************/
-#if 0
/* Ignoring the args is easiest. */
-xmenu_quit ()
+XMenuQuit ()
{
- error ("Unknown XMenu error");
+ error("Unknown XMenu error");
}
-#endif
DEFUN ("x-popup-menu",Fx_popup_menu, Sx_popup_menu, 1, 2, 0,
- "Pop up a deck-of-cards menu and return user's selection.\n\
-ARG is a position specification: a list ((XOFFSET YOFFSET) WINDOW)\n\
-where XOFFSET and YOFFSET are positions in characters from the top left\n\
-corner of WINDOW's screen. A mouse-event list will serve for this.\n\
-This controls the position of the center of the first line\n\
-in the first pane of the menu, not the top left of the menu as a whole.\n\
+ "Interface to XMenu library; permits creation and use of\n\
+deck-of-cards pop-up menus.\n\
+\n\
+ARG is a position specification; it is a list of (Xoffset, Yoffset)\n\
+from the top-left corner of the editor window. Note that this offset\n\
+is relative to the center of the first line in the first pane of the\n\
+menu, not the top left of the menu as a whole.\n\
\n\
MENU is a specifier for a menu. It is a list of the form\n\
-\(TITLE PANE1 PANE2...), and each pane is a list of form\n\
-\(TITLE (LINE ITEM)...). Each line should be a string, and item should\n\
-be the return value for that line (i.e. if it is selected.")
- (arg, menu)
- Lisp_Object arg, menu;
+(title pane1 pane2...), and each pane is a list of form\n\
+(title (line item)...). Each line should be a string, and item should\n\
+be the return value for that line (i. e. if it is selected.")
+ (arg,menu)
+ Lisp_Object arg,menu;
{
int number_of_panes;
Lisp_Object XMenu_return;
- int XMenu_xpos, XMenu_ypos;
+ int XMenu_xpos,XMenu_ypos;
char **menus;
char ***names;
Lisp_Object **obj_list;
@@ -117,43 +134,66 @@ be the return value for that line (i.e. if it is selected.")
char *title;
char *error_name;
Lisp_Object ltitle, selection;
+ Lisp_Object XEmacsMenu();
int i, j;
- SCREEN_PTR s;
- Lisp_Object x, y, window;
-
- window = Fcar (Fcdr (arg));
- x = Fcar (Fcar (arg));
- y = Fcar (Fcdr (Fcar (arg)));
- CHECK_WINDOW (window, 0);
- CHECK_NUMBER (x, 0);
- CHECK_NUMBER (y, 0);
- s = XSCREEN (WINDOW_SCREEN (XWINDOW (window)));
-
- XMenu_xpos = FONT_WIDTH (s->display.x->font) * XINT (x);
- XMenu_ypos = FONT_HEIGHT (s->display.x->font) * XINT (y);
- XMenu_xpos += s->display.x->left_pos;
- XMenu_ypos += s->display.x->top_pos;
-
- ltitle = Fcar (menu);
- CHECK_STRING (ltitle, 1);
- title = (char *) XSTRING (ltitle)->data;
- number_of_panes=list_of_panes (&obj_list, &menus, &names, &items, Fcdr (menu));
+#ifdef X11
+ Window root_window, wjunk;
+ int ijunk;
+ extern Lisp_Object Vx_mouse_abs_pos;
+#endif
+ BLOCK_INPUT_DECLARE ();
+
+ check_xterm();
+#ifdef X11
+#if 0
+ if (interrupt_input)
+ unrequest_sigio ();
+#endif
+ BLOCK_INPUT ();
+ root_window = RootWindow (XXdisplay, DefaultScreen(XXdisplay));
+ UNBLOCK_INPUT ();
+ XMenu_xpos = Fcar (Vx_mouse_abs_pos);
+ XMenu_ypos = Fcar (Fcdr (Vx_mouse_abs_pos));
+#if 0
+ if (interrupt_input)
+ request_sigio ();
+#endif
+#else
+ XMenu_xpos = fontinfo->width * XINT(Fcar(arg));
+ XMenu_ypos = fontinfo->height * XINT(Fcar(Fcdr (arg)));
+ XMenu_xpos += XXxoffset;
+ XMenu_ypos += XXyoffset;
+#endif
+ ltitle = Fcar(menu);
+ CHECK_STRING(ltitle,1);
+ title = (char *) XSTRING(ltitle)->data;
+ number_of_panes=list_of_panes(&obj_list, &menus, &names, &items, Fcdr(menu));
#ifdef XDEBUG
- fprintf (stderr, "Panes= %d\n", number_of_panes);
- for (i=0; i < number_of_panes; i++)
+ fprintf(stderr,"Panes= %d\n", number_of_panes);
+ for(i=0; i < number_of_panes; i++)
{
- fprintf (stderr, "Pane %d lines %d title %s\n", i, items[i], menus[i]);
+ fprintf (stderr,"Pane %d lines %d title %s\n", i, items[i], menus[i]);
for (j=0; j < items[i]; j++)
{
- fprintf (stderr, " Item %d %s\n", j, names[i][j]);
+ fprintf (stderr," Item %d %s\n", j, names[i][j]);
}
}
#endif
- BLOCK_INPUT;
- selection = xmenu_show (ROOT_WINDOW, XMenu_xpos, XMenu_ypos, names, menus,
- items, number_of_panes, obj_list, title, &error_name);
- UNBLOCK_INPUT;
- /** fprintf (stderr, "selection = %x\n", selection); **/
+ BLOCK_INPUT ();
+#ifdef X11
+ XSetErrorHandler(XMenuQuit);
+ selection = XEmacsMenu(root_window, XMenu_xpos, XMenu_ypos, names, menus,
+ items, number_of_panes, obj_list ,title, &error_name);
+ XSetErrorHandler(handler);
+#else
+ XErrorHandler(XMenuQuit);
+ selection = XEmacsMenu(RootWindow, XMenu_xpos, XMenu_ypos, names, menus,
+ items, number_of_panes, obj_list ,title, &error_name);
+ XErrorHandler(handler);
+#endif
+ UNBLOCK_INPUT ();
+ force_input_read ();
+ /** fprintf(stderr,"selection = %x\n",selection); **/
if (selection != NUL)
{ /* selected something */
XMenu_return = selection;
@@ -165,15 +205,15 @@ be the return value for that line (i.e. if it is selected.")
/* now free up the strings */
for (i=0; i < number_of_panes; i++)
{
- free (names[i]);
- free (obj_list[i]);
+ free(names[i]);
+ free(obj_list[i]);
}
- free (menus);
- free (obj_list);
- free (names);
- free (items);
- /* free (title); */
- if (error_name) error (error_name);
+ free(menus);
+ free(obj_list);
+ free(names);
+ free(items);
+ /* free(title); */
+ if (error_name) error(error_name);
return XMenu_return;
}
@@ -183,8 +223,8 @@ struct indices {
};
Lisp_Object
-xmenu_show (parent, startx, starty, line_list, pane_list, line_cnt,
- pane_cnt, item_list, title, error)
+XEmacsMenu(parent, startx, starty, line_list, pane_list, line_cnt,
+ pane_cnt, item_list, title, error)
Window parent;
int startx, starty; /* upper left corner position BROKEN */
char **line_list[]; /* list of strings for items */
@@ -201,60 +241,66 @@ xmenu_show (parent, startx, starty, line_list, pane_list, line_cnt,
Lisp_Object entry;
/* struct indices *datap, *datap_save; */
char *datap;
- int ulx, uly, width, height;
+ int ulx = 0, uly = 0, width, height;
int dispwidth, dispheight;
*error = (char *) 0; /* Initialize error pointer to null */
- GXMenu = XMenuCreate (XDISPLAY parent, "emacs");
- if (GXMenu == NUL)
+ if ((GXMenu = XMenuCreate( X11ONLY (XXdisplay) parent, "emacs" )) == NUL )
{
*error = "Can't create menu";
- return (0);
+ /* error("Can't create menu"); */
+ return(0);
}
- for (panes=0, lines=0; panes < pane_cnt; lines += line_cnt[panes], panes++)
+ for (panes=0, lines=0; panes < pane_cnt; lines += line_cnt[panes], panes++ )
;
- /* datap = (struct indices *) xmalloc (lines * sizeof (struct indices)); */
- /*datap = (char *) xmalloc (lines * sizeof (char));
+ /* datap = (struct indices *) xmalloc (lines * sizeof(struct indices)); */
+ /*datap = (char *) xmalloc(lines * sizeof(char));
datap_save = datap;*/
- for (panes = 0, sofar=0;panes < pane_cnt;sofar +=line_cnt[panes], panes++)
+ for (panes = 0, sofar=0;panes < pane_cnt;sofar +=line_cnt[panes], panes++ )
{
/* create all the necessary panes */
- lpane = XMenuAddPane (XDISPLAY GXMenu, pane_list[panes], TRUE);
- if (lpane == XM_FAILURE)
+ if ((lpane= XMenuAddPane( X11ONLY (XXdisplay) GXMenu, pane_list[panes] , TRUE ))
+ == XM_FAILURE)
{
- XMenuDestroy (XDISPLAY GXMenu);
+ XMenuDestroy(X11ONLY (XXdisplay) GXMenu);
*error = "Can't create pane";
- return (0);
+ /* error("Can't create pane"); */
+ /* free(datap); */
+ return(0);
}
- for (selidx = 0; selidx < line_cnt[panes] ; selidx++)
+ for ( selidx = 0; selidx < line_cnt[panes] ; selidx++ )
{
/* add the selection stuff to the menus */
/* datap[selidx+sofar].pane = panes;
datap[selidx+sofar].line = selidx; */
- if (XMenuAddSelection (XDISPLAY GXMenu, lpane, 0,
- line_list[panes][selidx], TRUE)
+ if (XMenuAddSelection(X11ONLY (XXdisplay) GXMenu, lpane, 0, line_list[panes][selidx], TRUE)
== XM_FAILURE)
{
- XMenuDestroy (XDISPLAY GXMenu);
- /* free (datap); */
+ XMenuDestroy(X11ONLY (XXdisplay) GXMenu);
+ /* free(datap); */
*error = "Can't add selection to menu";
/* error ("Can't add selection to menu"); */
- return (0);
+ return(0);
}
}
}
/* all set and ready to fly */
- XMenuRecompute (XDISPLAY GXMenu);
- dispwidth = DisplayWidth (x_current_display, XDefaultScreen (x_current_display));
- dispheight = DisplayHeight (x_current_display, XDefaultScreen (x_current_display));
- startx = min (startx, dispwidth);
- starty = min (starty, dispheight);
- startx = max (startx, 1);
- starty = max (starty, 1);
- XMenuLocate (XDISPLAY GXMenu, 0, 0, startx, starty,
- &ulx, &uly, &width, &height);
+ XMenuRecompute(X11ONLY (XXdisplay) GXMenu);
+#ifdef X11
+ XXscreen = DefaultScreen(XXdisplay);
+ dispwidth = DisplayWidth(XXdisplay, XXscreen);
+ dispheight = DisplayHeight(XXdisplay, XXscreen);
+#else
+ dispwidth = DisplayWidth();
+ dispheight = DisplayHeight();
+#endif
+ startx = min(startx, dispwidth);
+ starty = min(starty, dispheight);
+ startx = max(startx, 1);
+ starty = max(starty, 1);
+ XMenuLocate(X11ONLY (XXdisplay) GXMenu, 0, 0, startx, starty, &ulx, &uly, &width, &height);
if (ulx+width > dispwidth)
{
startx -= (ulx + width) - dispwidth;
@@ -268,32 +314,31 @@ xmenu_show (parent, startx, starty, line_list, pane_list, line_cnt,
if (ulx < 0) startx -= ulx;
if (uly < 0) starty -= uly;
- XMenuSetFreeze (GXMenu, TRUE);
+ XMenuSetFreeze(GXMenu, TRUE);
panes = selidx = 0;
- status = XMenuActivate (XDISPLAY GXMenu, &panes, &selidx,
- startx, starty, ButtonReleaseMask, &datap);
- switch (status)
- {
- case XM_SUCCESS:
+ status = XMenuActivate(X11ONLY (XXdisplay) GXMenu, &panes, &selidx,
+ startx, starty, ButtonReleaseMask, &datap);
+ switch (status ) {
+ case XM_SUCCESS:
#ifdef XDEBUG
- fprintf (stderr, "pane= %d line = %d\n", panes, selidx);
+ fprintf (stderr, "pane= %d line = %d\n", panes, selidx);
#endif
- entry = item_list[panes][selidx];
- break;
- case XM_FAILURE:
- /*free (datap_save); */
- XMenuDestroy (XDISPLAY GXMenu);
- *error = "Can't activate menu";
- /* error ("Can't activate menu"); */
- case XM_IA_SELECT:
- case XM_NO_SELECT:
- entry = Qnil;
- break;
- }
- XMenuDestroy (XDISPLAY GXMenu);
- /*free (datap_save);*/
- return (entry);
+ entry = item_list[panes][selidx];
+ break;
+ case XM_FAILURE:
+ /*free (datap_save); */
+ XMenuDestroy(X11ONLY (XXdisplay) GXMenu);
+ *error = "Can't activate menu";
+ /* error("Can't activate menu"); */
+ case XM_IA_SELECT:
+ case XM_NO_SELECT:
+ entry = Qnil;
+ break;
+ }
+ XMenuDestroy(X11ONLY (XXdisplay) GXMenu);
+ /*free(datap_save);*/
+ return(entry);
}
syms_of_xmenu ()
@@ -311,39 +356,39 @@ list_of_panes (vector, panes, names, items, menu)
Lisp_Object tail, item, item1;
int i;
- if (XTYPE (menu) != Lisp_Cons) menu = wrong_type_argument (Qlistp, menu);
-
- i= XFASTINT (Flength (menu, 1));
+ if (XTYPE (menu) != Lisp_Cons) menu = wrong_type_argument(Qlistp, menu);
+
+ i= XFASTINT(Flength(menu,1));
- *vector = (Lisp_Object **) xmalloc (i * sizeof (Lisp_Object *));
- *panes = (char **) xmalloc (i * sizeof (char *));
- *items = (int *) xmalloc (i * sizeof (int));
- *names = (char ***) xmalloc (i * sizeof (char **));
+ *vector = (Lisp_Object **) xmalloc(i * sizeof (Lisp_Object *));
+ *panes = (char **) xmalloc(i * sizeof (char *));
+ *items = (int *) xmalloc(i * sizeof (int));
+ *names = (char ***) xmalloc(i * sizeof (char **));
- for (i=0, tail = menu; !NULL (tail); tail = Fcdr (tail), i++)
+ for (i=0,tail = menu; !NULL (tail); tail = Fcdr (tail), i++)
{
- item = Fcdr (Fcar (tail));
- if (XTYPE (item) != Lisp_Cons) (void) wrong_type_argument (Qlistp, item);
+ item = Fcdr(Fcar(tail));
+ if (XTYPE (item) != Lisp_Cons) (void) wrong_type_argument(Qlistp, item);
#ifdef XDEBUG
fprintf (stderr, "list_of_panes check tail, i=%d\n", i);
#endif
- item1 = Fcar (Fcar (tail));
+ item1 = Fcar(Fcar(tail));
CHECK_STRING (item1, 1);
#ifdef XDEBUG
fprintf (stderr, "list_of_panes check pane, i=%d%s\n", i,
- XSTRING (item1)->data);
+ XSTRING(item1)->data);
#endif
- (*panes)[i] = (char *) XSTRING (item1)->data;
+ (*panes)[i] = (char *) XSTRING(item1)->data;
(*items)[i] = list_of_items ((*vector)+i, (*names)+i, item);
- /* (*panes)[i] = (char *) xmalloc ((XSTRING (item1)->size)+1);
- bcopy (XSTRING (item1)->data, (*panes)[i], XSTRING (item1)->size + 1)
+ /* (*panes)[i] = (char *) xmalloc((XSTRING(item1)->size)+1);
+ bcopy (XSTRING (item1)->data, (*panes)[i], XSTRING(item1)->size + 1)
; */
}
return i;
}
-list_of_items (vector, names, pane) /* get list from emacs and put to vector */
+list_of_items (vector,names,pane) /* get list from emacs and put to vector */
Lisp_Object **vector; /* RETURN menu "objects" */
char ***names; /* RETURN line names */
Lisp_Object pane;
@@ -351,28 +396,31 @@ list_of_items (vector, names, pane) /* get list from emacs and put to vector */
Lisp_Object tail, item, item1;
int i;
- if (XTYPE (pane) != Lisp_Cons) pane = wrong_type_argument (Qlistp, pane);
-
- i= XFASTINT (Flength (pane, 1));
+ if (XTYPE (pane) != Lisp_Cons) pane = wrong_type_argument(Qlistp, pane);
+
+ i= XFASTINT(Flength(pane,1));
- *vector = (Lisp_Object *) xmalloc (i * sizeof (Lisp_Object));
- *names = (char **) xmalloc (i * sizeof (char *));
+ *vector = (Lisp_Object *) xmalloc(i * sizeof (Lisp_Object));
+ *names = (char **) xmalloc(i * sizeof (char *));
- for (i=0, tail = pane; !NULL (tail); tail = Fcdr (tail), i++)
+ for (i=0,tail = pane; !NULL (tail); tail = Fcdr (tail), i++)
{
- item = Fcar (tail);
- if (XTYPE (item) != Lisp_Cons) (void) wrong_type_argument (Qlistp, item);
+ item = Fcar(tail);
+ if (XTYPE (item) != Lisp_Cons) (void) wrong_type_argument(Qlistp, item);
#ifdef XDEBUG
fprintf (stderr, "list_of_items check tail, i=%d\n", i);
#endif
(*vector)[i] = Fcdr (item);
- item1 = Fcar (item);
+ item1 = Fcar(item);
CHECK_STRING (item1, 1);
#ifdef XDEBUG
fprintf (stderr, "list_of_items check item, i=%d%s\n", i,
- XSTRING (item1)->data);
+ XSTRING(item1)->data);
#endif
- (*names)[i] = (char *) XSTRING (item1)->data;
+ (*names)[i] = (char *) XSTRING(item1)->data;
+ /* (*names)[i] = (char *) xmalloc((XSTRING(item1)->size)+1);
+ bcopy (XSTRING (item1)->data, (*names)[i], XSTRING(item1)->size + 1); */
}
return i;
}
+
diff --git a/src/xrdb.c b/src/xrdb.c
deleted file mode 100644
index 930b4d54d43..00000000000
--- a/src/xrdb.c
+++ /dev/null
@@ -1,477 +0,0 @@
-/* Deal with the X Resource Manager.
- Copyright (C) 1990 Free Software Foundation.
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 1, or (at your option)
-any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-/* Written by jla, 4/90 */
-
-#include <X11/Xlib.h>
-#include <X11/Xatom.h>
-#include <X11/Xos.h>
-#include <X11/X.h>
-#include <X11/Xutil.h>
-#include <X11/Xresource.h>
-#include <sys/param.h>
-#include <pwd.h>
-#include <sys/stat.h>
-
-#ifdef emacs
-#include "config.h"
-#endif
-
-extern char *getenv ();
-extern int getuid ();
-extern struct passwd *getpwuid ();
-extern struct passwd *getpwnam ();
-
-static char *
-gethomedir (dirname)
- char *dirname;
-{
- int uid;
- struct passwd *pw;
- char *ptr;
-
- if ((ptr = getenv ("HOME")) == NULL)
- {
- if ((ptr = getenv ("USER")) != NULL)
- pw = getpwnam (ptr);
- else
- {
- uid = getuid ();
- pw = getpwuid (uid);
- }
- if (pw)
- ptr = pw->pw_dir;
- else
- {
- ptr = NULL;
- *dirname = '\0';
- }
- }
-
- if (ptr != NULL)
- strcpy (dirname, ptr);
-
- dirname += strlen (dirname);
- *dirname = '/';
- dirname++;
- *dirname = '\0';
-
- return dirname;
-}
-
-static int
-file_p (path)
- char *path;
-{
- struct stat status;
-
- return (access (path, R_OK) == 0 /* exists and is readable */
- && stat (path, &status) == 0 /* get the status */
- && (status.st_mode & S_IFDIR) == 0); /* not a directory */
-}
-
-#if 0
-#define X_DEFAULT_SEARCH_PATH "/usr/lib/X11/"
-#endif
-
-/* Isn't this just disgusting? */
-
-#define X_DEFAULT_SEARCH_PATH "/usr/lib/X11/%L/%T/%N%S:/usr/lib/X11/%l/%T/%N%S:/usr/lib/X11/%T/%N%S"
-
-static int
-decode_magic (string, file, return_path)
- char *string, *file, *return_path;
-{
- char *p = string;
- char *t = return_path;
-
- while (*p)
- {
- if (*p == '%')
- switch (*++p)
- {
- case '%':
- *t++ = '%';
- p++;
- break;
-
- case 'N':
- case 'T':
- case 'S':
- case 'L':
- case 'l':
- case 't':
- case 'c':
- default:
- p++;
- if (*t == '/' && *p == '/')
- p++;
- break;
- }
- else
- *t++ = *p++;
- }
- *t = '\0';
- strcat (return_path, file);
-
- if (file_p (return_path))
- return 1;
-
- return_path[0] = '\0';
- return 0;
-}
-
-static int
-magic_searchpath_decoder (incantation_string, file, return_path)
- char *incantation_string, *return_path, *file;
-{
- register char *s = incantation_string;
- register char *p;
- register char string[MAXPATHLEN];
-
- while (*s)
- {
- p = s;
-
- while (*p && *p != ':')
- p++;
-
- if (*p == ':' && *(p + 1) == ':')
- {
- bcopy ("%N%S", string, 5);
- if (decode_magic (string, file, return_path))
- return 1;
-
- s = p + 1;
- continue;
- }
-
- if (p > s)
- {
- int len = p - s;
-
- bcopy (s, string, len);
- string[len + 1] = '\0';
- if (decode_magic (string, file, return_path))
- return 1;
- }
-
- if (p)
- s = p + 1;
- else
- return 0;
- }
-
- return 0;
-}
-
-static XrmDatabase
-get_system_app (class)
- char *class;
-{
- XrmDatabase db;
- char path[MAXPATHLEN];
- char *p;
-
- if ((p = getenv ("XFILESEARCHPATH")) == NULL)
- p = X_DEFAULT_SEARCH_PATH;
-
- if (! magic_searchpath_decoder (p, class, path))
- return NULL;
-
- db = XrmGetFileDatabase (path);
- return db;
-}
-
-static XrmDatabase
-get_fallback (display)
- Display *display;
-{
- XrmDatabase db;
-
- return NULL;
-}
-
-static XrmDatabase
-get_user_app (class)
- char *class;
-{
- XrmDatabase db;
- char *magic_path;
- char path[MAXPATHLEN];
-
- if ((magic_path = getenv ("XUSERFILESEARCHPATH")) == NULL)
- {
- char homedir[MAXPATHLEN];
- char *default_magic;
- char *p;
-
- gethomedir (homedir);
-
- if ((p = getenv ("XAPPLRESDIR")) == NULL)
- {
- default_magic = "%s/%%L/%%N:%s/%%l/%%N:%s/%%N";
- magic_path = (char *) alloca ((3 * strlen (homedir))
- + strlen (default_magic));
- sprintf (magic_path, default_magic, homedir, homedir, homedir);
- }
- else
- {
- default_magic = "%s/%%L/%%N:%s/%%l/%%N:%s/%%N:%s/%%N";
- magic_path = (char *) alloca ((3 * strlen (p))
- + strlen (default_magic)
- + strlen (homedir));
- sprintf (magic_path, default_magic, p, p, p, homedir);
- }
- }
-
- if (! magic_searchpath_decoder (magic_path, class, path))
- return NULL;
-
- db = XrmGetFileDatabase (path);
- return db;
-}
-
-static XrmDatabase
-get_user_db (display)
- Display *display;
-{
- XrmDatabase db;
- char *xdefs;
-
- xdefs = XResourceManagerString (display);
- if (xdefs != NULL)
- db = XrmGetStringDatabase (xdefs);
- else
- {
- char xdefault[MAXPATHLEN];
-
- gethomedir (xdefault);
- strcat (xdefault, ".Xdefaults");
- db = XrmGetFileDatabase (xdefault);
- }
-
- return db;
-}
-
-static XrmDatabase
-get_environ_db ()
-{
- XrmDatabase db;
- char *p;
- char path[MAXPATHLEN];
-
- if ((p = getenv ("XENVIRONMENT")) == NULL)
- {
- gethomedir (path);
- strcat (path, ".Xdefaults-");
- gethostname (path + strlen (path), MAXPATHLEN - strlen (path));
- p = path;
- }
-
- db = XrmGetFileDatabase (p);
- return db;
-}
-
-/* Types of values that we can find in a database */
-
-#define XrmStringType "String" /* String representation */
-XrmRepresentation x_rm_string; /* Quark representation */
-
-/* Load X resources based on the display and a possible -xrm option. */
-
-XrmDatabase
-x_load_resources (display, xrm_string, myclass)
- Display *display;
- char *xrm_string, *myclass;
-{
- char *xdefs;
- XrmDatabase rdb;
- XrmDatabase db;
-
- x_rm_string = XrmStringToQuark (XrmStringType);
- XrmInitialize ();
- rdb = XrmGetStringDatabase ("");
-
- /* Get application system defaults */
- db = get_system_app (myclass);
- if (db != NULL)
- XrmMergeDatabases (db, &rdb);
-
- /* Get Fallback resources */
- db = get_fallback (display);
- if (db != NULL)
- XrmMergeDatabases (db, &rdb);
-
- /* Get application user defaults */
- db = get_user_app (myclass);
- if (db != NULL)
- XrmMergeDatabases (db, &rdb);
-
- /* get User defaults */
- db = get_user_db (display);
- if (db != NULL)
- XrmMergeDatabases (db, &rdb);
-
- /* Get Environment defaults. */
- db = get_environ_db ();
- if (db != NULL)
- XrmMergeDatabases (db, &rdb);
-
- /* Last, merge in any specification from the command line. */
- if (xrm_string != NULL)
- {
- db = XrmGetStringDatabase (xrm_string);
- if (db != NULL)
- XrmMergeDatabases (db, &rdb);
- }
-
- return rdb;
-}
-
-/* Retrieve the value of the resource specified by NAME with class CLASS
- and of type TYPE from database RDB. The value is returned in RET_VALUE. */
-
-int
-x_get_resource (rdb, name, class, expected_type, ret_value)
- XrmDatabase rdb;
- char *name, *class;
- XrmRepresentation expected_type;
- XrmValue *ret_value;
-{
- XrmValue value;
- XrmName namelist[100];
- XrmClass classlist[100];
- XrmRepresentation type;
-
- XrmStringToNameList(name, namelist);
- XrmStringToClassList(class, classlist);
-
- if (XrmQGetResource (rdb, namelist, classlist, &type, &value) == True
- && (type == expected_type))
- {
- if (type == x_rm_string)
- (char *) ret_value->addr = value.addr;
- else
- bcopy (value.addr, ret_value->addr, ret_value->size);
-
- return value.size;
- }
-
- return 0;
-}
-
-/* Retrieve the string resource specified by NAME with CLASS from
- database RDB. */
-
-char *
-x_get_string_resource (rdb, name, class)
- XrmDatabase rdb;
- char *name, *class;
-{
- XrmValue value;
-
- if (x_get_resource (rdb, name, class, x_rm_string, &value))
- return (char *) value.addr;
-
- return (char *) 0;
-}
-
-#ifdef TESTRM
-#include <stdio.h>
-#include "arg-list.h"
-
-static void
-fatal (msg, prog, x1, x2, x3, x4, x5)
- char *msg, *prog;
- int x1, x2, x3, x4, x5;
-{
- extern int errno;
-
- if (errno)
- perror (prog);
-
- (void) fprintf (stderr, msg, prog, x1, x2, x3, x4, x5);
- exit (1);
-}
-
-main (argc, argv)
- int argc;
- char **argv;
-{
- Display *display;
- char *displayname, *resource_string, *class;
- XrmDatabase xdb;
- List *arg_list, *lp;
-
- arg_list = arg_listify (argc, argv);
-
- lp = member ("-d", arg_list);
- if (!NIL (lp))
- displayname = car (cdr (lp));
- else
- displayname = "localhost:0.0";
-
- lp = member ("-xrm", arg_list);
- if (! NIL (lp))
- resource_string = car (cdr (lp));
- else
- resource_string = (char *) 0;
-
- lp = member ("-c", arg_list);
- if (! NIL (lp))
- class = car (cdr (lp));
- else
- class = "Emacs";
-
- free_arglist (arg_list);
-
-
-
- if (!(display = XOpenDisplay (displayname)))
- fatal ("Can't open display '%s'\n", XDisplayName (displayname));
-
- xdb = x_load_resources (display, resource_string, class);
-
-#if 0
- /* In a real program, you'd want to also do this: */
- display->db = xdb;
-#endif
-
- while (1)
- {
- char line[90];
-
- printf ("String: ");
- gets (line);
- if (strlen (line))
- {
- char *value = x_get_string_resource (xdb, line, class);
-
- if (value != NULL)
- printf ("\t%s: %s\n\n", line, value);
- else
- printf ("\tNo Value.\n\n");
- }
- else
- break;
- }
- printf ("\tExit.\n\n");
-
- XCloseDisplay (display);
-}
-#endif /* TESTRM */
diff --git a/src/xselect.c.old b/src/xselect.c.old
deleted file mode 100644
index 8d3e3d12fc4..00000000000
--- a/src/xselect.c.old
+++ /dev/null
@@ -1,666 +0,0 @@
-/* X Selection processing for emacs
- Copyright (C) 1990 Free Software Foundation.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 1, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-#include "config.h"
-#include "lisp.h"
-#include "xterm.h"
-#include "screen.h"
-
-#ifdef HAVE_X11
-
-/* Macros for X Selections */
-#define MAX_SELECTION(dpy) (((dpy)->max_request_size << 3) - 100)
-#define SELECTION_LENGTH(len,format) ((len) * ((format) >> 3))
-
-/* The last 23 bits of the timestamp of the last mouse button event. */
-extern Time mouse_timestamp;
-
-/* t if a mouse button is depressed. */
-
-extern Lisp_Object Vmouse_grabbed;
-
-/* When emacs became the PRIMARY selection owner. */
-Time x_begin_selection_own;
-
-/* When emacs became the CLIPBOARD selection owner. */
-Time x_begin_clipboard_own;
-
-/* The value of the current CLIPBOARD selection. */
-Lisp_Object Vx_clipboard_value;
-
-/* The value of the current PRIMARY selection. */
-Lisp_Object Vx_selection_value;
-
-/* Emacs' selection property identifier. */
-Atom Xatom_emacs_selection;
-
-/* Clipboard selection atom. */
-Atom Xatom_clipboard_selection;
-
-/* Clipboard atom. */
-Atom Xatom_clipboard;
-
-/* Atom for indicating incremental selection transfer. */
-Atom Xatom_incremental;
-
-/* Atom for indicating multiple selection request list */
-Atom Xatom_multiple;
-
-/* Atom for what targets emacs handles. */
-Atom Xatom_targets;
-
-/* Atom for indicating timstamp selection request */
-Atom Xatom_timestamp;
-
-/* Atom requesting we delete our selection. */
-Atom Xatom_delete;
-
-/* Selection magic. */
-Atom Xatom_insert_selection;
-
-/* Type of property for INSERT_SELECTION. */
-Atom Xatom_pair;
-
-/* More selection magic. */
-Atom Xatom_insert_property;
-
-/* Atom for indicating property type TEXT */
-Atom Xatom_text;
-
-/* These are to handle incremental selection transfer. */
-Window incr_requestor;
-Atom incr_property;
-int incr_nbytes;
-unsigned char *incr_value;
-unsigned char *incr_ptr;
-
-/* SELECTION OWNER CODE */
-
-/* Become the selection owner and make our data the selection value.
- If we are already the owner, merely change data and timestamp values.
- This avoids generating SelectionClear events for ourselves. */
-
-DEFUN ("x-own-selection", Fx_own_selection, Sx_own_selection,
- 1, 1, "sStore text for pasting: ",
- "Stores string STRING for pasting in another X window.\n\
-This is done with the X11 selection mechanism.")
- (string)
- register Lisp_Object string;
-{
- Window owner_window, selecting_window;
- Time event_time;
-
- CHECK_STRING (string, 0);
-
- BLOCK_INPUT;
- selecting_window = selected_screen->display.x->window_desc;
-
- if (EQ (Qnil, Vx_selection_value)) /* We are not the owner. */
- {
- event_time = mouse_timestamp;
- XSetSelectionOwner (x_current_display, XA_PRIMARY,
- selecting_window, event_time);
- owner_window = XGetSelectionOwner (x_current_display, XA_PRIMARY);
-
- if (owner_window != selecting_window)
- {
- UNBLOCK_INPUT;
- error ("X error: could not acquire selection ownership");
- }
- }
-
- x_begin_selection_own = event_time;
- Vx_selection_value = string;
- UNBLOCK_INPUT;
-
- return Qnil;
-}
-
-/* CLIPBOARD OWNERSHIP */
-
-DEFUN ("x-own-clipboard", Fx_own_clipboard, Sx_own_clipboard,
- 1, 1, "sCLIPBOARD string: ",
- "Assert X clipboard ownership with value STRING.")
- (string)
- register Lisp_Object string;
-{
- Window owner_window, selecting_window;
- Time event_time;
-
- CHECK_STRING (string, 0);
-
- BLOCK_INPUT;
- selecting_window = selected_screen->display.x->window_desc;
-
- if (EQ (Qnil, Vx_clipboard_value))
- {
- event_time = mouse_timestamp;
- XSetSelectionOwner (x_current_display, Xatom_clipboard,
- selecting_window, event_time);
- owner_window = XGetSelectionOwner (x_current_display, Xatom_clipboard);
-
- if (owner_window != selecting_window)
- {
- UNBLOCK_INPUT;
- error ("X error: could not acquire selection ownership");
- }
- }
-
- x_begin_clipboard_own = event_time;
- Vx_clipboard_value = string;
- UNBLOCK_INPUT;
-
- return Qnil;
-}
-
-/* Clear our selection ownership data, as some other client has
- become the owner. */
-
-void
-x_disown_selection (old_owner, selection, changed_owner_time)
- Window *old_owner;
- Atom selection;
- Time changed_owner_time;
-{
- struct screen *s = x_window_to_screen (old_owner);
-
- if (s) /* We are the owner */
- {
- if (selection == XA_PRIMARY)
- {
- x_begin_selection_own = 0;
- Vx_selection_value = Qnil;
- }
- else if (selection == Xatom_clipboard)
- {
- x_begin_clipboard_own = 0;
- Vx_clipboard_value = Qnil;
- }
- else
- abort ();
- }
- else
- abort (); /* Inconsistent state. */
-}
-
-int x_selection_alloc_error;
-int x_converting_selection;
-
-/* Reply to some client's request for our selection data. Data is
- placed in a propery supplied by the requesting window.
-
- If the data exceeds the maximum amount the server can send,
- then prepare to send it incrementally, and reply to the client with
- the total size of the data.
-
- But first, check for all the other crufty stuff we could get. */
-
-void
-x_answer_selection_request (event)
- XSelectionRequestEvent event;
-{
- Time emacs_own_time;
- Lisp_Object selection_value;
- XSelectionEvent evt;
- int format = 8; /* We have only byte sized (text) data. */
-
- evt.type = SelectionNotify; /* Construct reply event */
- evt.display = event.display;
- evt.requestor = event.requestor;
- evt.selection = event.selection;
- evt.time = event.time;
- evt.target = event.target;
-
- if (event.selection == XA_PRIMARY)
- {
- emacs_own_time = x_begin_selection_own;
- selection_value = Vx_selection_value;
- }
- else if (event.selection == Xatom_clipboard)
- {
- emacs_own_time = x_begin_clipboard_own;
- selection_value = Vx_clipboard_value;
- }
- else
- abort ();
-
- if (event.time != CurrentTime
- && event.time < emacs_own_time)
- evt.property = None;
- else
- {
- if (event.property == None) /* obsolete client */
- evt.property = event.target;
- else
- evt.property = event.property;
- }
-
- if (event.target == Xatom_targets) /* Send List of target atoms */
- {
- }
- else if (event.target == Xatom_multiple) /* Recvd list: <target, prop> */
- {
- Atom type;
- int return_format;
- unsigned long items, bytes_left;
- unsigned char *data;
- int result, i;
-
- if (event.property == 0 /* 0 == NULL */
- || event.property == None)
- return;
-
- result = XGetWindowProperty (event.display, event.requestor,
- event.property, 0L, 10000000L,
- True, Xatom_pair, &type, &return_format,
- &items, &bytes_left, &data);
-
- if (result == Success && type == Xatom_pair)
- for (i = items; i > 0; i--)
- {
- /* Convert each element of the list. */
- }
-
- (void) XSendEvent (x_current_display, evt.requestor, False,
- 0L, (XEvent *) &evt);
- return;
- }
- else if (event.target == Xatom_timestamp) /* Send ownership timestamp */
- {
- if (! emacs_own_time)
- abort ();
-
- format = 32;
- XChangeProperty (evt.display, evt.requestor, evt.property,
- evt.target, format, PropModeReplace,
- (unsigned char *) &emacs_own_time, format);
- return;
- }
- else if (event.target == Xatom_delete) /* Delete our selection. */
- {
- if (EQ (Qnil, selection_value))
- abort ();
-
- x_disown_selection (event.owner, event.selection, event.time);
-
- /* Now return property of type NULL, length 0. */
- XChangeProperty (event.display, event.requestor, event.property,
- 0, format, PropModeReplace, (unsigned char *) 0, 0);
- return;
- }
- else if (event.target == Xatom_insert_selection)
- {
- Atom type;
- int return_format;
- unsigned long items, bytes_left;
- unsigned char *data;
- int result = XGetWindowProperty (event.display, event.requestor,
- event.property, 0L, 10000000L,
- True, Xatom_pair, &type, &return_format,
- &items, &bytes_left, &data);
- if (result == Success && type == Xatom_pair)
- {
- /* Convert the first atom to (a selection) to the target
- indicated by the second atom. */
- }
- }
- else if (event.target == Xatom_insert_property)
- {
- Atom type;
- int return_format;
- unsigned long items, bytes_left;
- unsigned char *data;
- int result = XGetWindowProperty (event.display, event.requestor,
- event.property, 0L, 10000000L,
- True, XA_STRING, &type, &return_format,
- &items, &bytes_left, &data);
-
- if (result == Success && type == XA_STRING && return_format == 8)
- {
- if (event.selection == Xatom_emacs_selection)
- Vx_selection_value = make_string (data);
- else if (event.selection == Xatom_clipboard_selection)
- Vx_clipboard_value = make_string (data);
- else
- abort ();
- }
-
- return;
- }
- else if ((event.target == Xatom_text
- || event.target == XA_STRING))
- {
- int size = XSTRING (selection_value)->size;
- unsigned char *data = XSTRING (selection_value)->data;
-
- if (EQ (Qnil, selection_value))
- abort ();
-
- /* Place data on requestor window's property. */
- if (SELECTION_LENGTH (size, format)
- <= MAX_SELECTION (x_current_display))
- {
- x_converting_selection = 1;
- XChangeProperty (evt.display, evt.requestor, evt.property,
- evt.target, format, PropModeReplace,
- data, size);
- if (x_selection_alloc_error)
- {
- x_selection_alloc_error = 0;
- abort ();
- }
- x_converting_selection = 0;
- }
- else /* Send incrementally */
- {
- evt.target = Xatom_incremental;
- incr_requestor = evt.requestor;
- incr_property = evt.property;
- x_converting_selection = 1;
-
- /* Need to handle Alloc errors on these requests. */
- XChangeProperty (evt.display, incr_requestor, incr_property,
- Xatom_incremental, 32,
- PropModeReplace,
- (unsigned char *) &size, 1);
- if (x_selection_alloc_error)
- {
- x_selection_alloc_error = 0;
- x_converting_selection = 0;
- abort ();
- /* Now abort the send. */
- }
-
- incr_nbytes = size;
- incr_value = data;
- incr_ptr = data;
-
- /* Ask for notification when requestor deletes property. */
- XSelectInput (x_current_display, incr_requestor, PropertyChangeMask);
-
- /* If we're sending incrementally, perhaps block here
- until all sent? */
- }
- }
- else
- evt.property = None;
-
- /* Don't do this if there was an Alloc error: abort the transfer
- by sending None. */
- (void) XSendEvent (x_current_display, evt.requestor, False,
- 0L, (XEvent *) &evt);
-}
-
-/* Send an increment of selection data in response to a PropertyNotify event.
- The increment is placed in a property on the requestor's window.
- When the requestor has processed the increment, it deletes the property,
- which sends us another PropertyNotify event.
-
- When there is no more data to send, we send a zero-length increment. */
-
-void
-x_send_incremental (event)
- XPropertyEvent event;
-{
- if (incr_requestor
- && incr_requestor == event.window
- && incr_property == event.atom
- && event.state == PropertyDelete)
- {
- int format = 8;
- int length = MAX_SELECTION (x_current_display);
- int bytes_left = (incr_nbytes - (incr_ptr - incr_value));
-
- if (length > bytes_left) /* Also sends 0 len when finished. */
- length = bytes_left;
- XChangeProperty (x_current_display, incr_requestor,
- incr_property, XA_STRING, format,
- PropModeAppend, incr_ptr, length);
- if (x_selection_alloc_error)
- {
- x_selection_alloc_error = 0;
- x_converting_selection = 0;
- /* Abandon the transmission. */
- abort ();
- }
- if (length > 0)
- incr_ptr += length;
- else
- { /* Everything's sent */
- XSelectInput (x_current_display, incr_requestor, 0L);
- incr_requestor = (Window) 0;
- incr_property = (Atom) 0;
- incr_nbytes = 0;
- incr_value = (unsigned char *) 0;
- incr_ptr = (unsigned char *) 0;
- x_converting_selection = 0;
- }
- }
-}
-
-/* SELECTION REQUESTOR CODE */
-
-/* Predicate function used to match a requested event. */
-
-Bool
-XCheckSelectionEvent (dpy, event, window)
- Display *dpy;
- XEvent *event;
- char *window;
-{
- if (event->type == SelectionNotify)
- if (event->xselection.requestor == (Window) window)
- return True;
-
- return False;
-}
-
-/* Request the selection value from the owner. If we are the owner,
- simply return our selection value. If we are not the owner, this
- will block until all of the data has arrived. */
-
-DEFUN ("x-get-selection", Fx_get_selection, Sx_get_selection, 0, 0, 0,
- "Return text selected from some X window.\n\
-This is done with the X11 selection mechanism.")
- ()
-{
- XEvent event;
- Lisp_Object val;
- Time requestor_time; /* Timestamp of selection request. */
- Window requestor_window;
-
- if (!EQ (Qnil, Vx_selection_value)) /* We are the owner */
- return Vx_selection_value;
-
- BLOCK_INPUT;
- requestor_time = mouse_timestamp;
- requestor_window = selected_screen->display.x->window_desc;
- XConvertSelection (x_current_display, XA_PRIMARY, XA_STRING,
- Xatom_emacs_selection, requestor_window, requestor_time);
- XIfEvent (x_current_display,
- &event,
- XCheckSelectionEvent,
- (char *) requestor_window);
- val = x_selection_arrival (&event, requestor_window, requestor_time);
- UNBLOCK_INPUT;
-
- return val;
-}
-
-/* Request the clipboard contents from its owner. If we are the owner,
- simply return the clipboard string. */
-
-DEFUN ("x-get-clipboard", Fx_get_clipboard, Sx_get_clipboard, 0, 0, 0,
- "Return text pasted to the clipboard.\n\
-This is done with the X11 selection mechanism.")
- ()
-{
- XEvent event;
- Lisp_Object val;
- Time requestor_time; /* Timestamp of selection request. */
- Window requestor_window;
-
- if (!EQ (Qnil, Vx_clipboard_value)) /* We are the owner */
- return Vx_selection_value;
-
- BLOCK_INPUT;
- requestor_time = mouse_timestamp;
- requestor_window = selected_screen->display.x->window_desc;
- XConvertSelection (x_current_display, Xatom_clipboard, XA_STRING,
- Xatom_clipboard_selection,
- requestor_window, requestor_time);
- XIfEvent (x_current_display,
- &event,
- XCheckSelectionEvent,
- (char *) requestor_window);
- val = x_selection_arrival (&event, requestor_window, requestor_time);
- UNBLOCK_INPUT;
-
- return val;
-}
-
-Lisp_Object
-x_selection_arrival (event, requestor_window, requestor_time)
- register XSelectionEvent *event;
- Window requestor_window;
- Time requestor_time;
-{
- int result;
- Atom type, selection;
- int format;
- unsigned long items;
- unsigned long bytes_left;
- unsigned char *data = 0;
- int offset = 0;
-
- if (event->selection == XA_PRIMARY)
- selection = Xatom_emacs_selection;
- else if (event->selection == Xatom_clipboard)
- selection = Xatom_clipboard_selection;
- else
- abort ();
-
- if (event->requestor == requestor_window
- && event->time == requestor_time
- && event->property != None)
- if (event->target != Xatom_incremental)
- {
- unsigned char *return_string =
- (unsigned char *) alloca (MAX_SELECTION (x_current_display));
-
- do
- {
- result = XGetWindowProperty (x_current_display,
- requestor_window,
- event->property, 0L,
- 10000000L, True, XA_STRING,
- &type, &format, &items,
- &bytes_left, &data);
- if (result == Success && type == XA_STRING && format == 8
- && offset < MAX_SELECTION (x_current_display))
- {
- bcopy (data, return_string + offset, items);
- offset += items;
- }
- XFree ((char *) data);
- }
- while (bytes_left);
-
- return make_string (return_string, offset);
- }
- else /* Prepare incremental transfer. */
- {
- unsigned char *increment_value;
- unsigned char *increment_ptr;
- int total_size;
- int *increment_nbytes = 0;
-
- result = XGetWindowProperty (x_current_display, requestor_window,
- selection, 0L, 10000000L, False,
- event->property, &type, &format,
- &items, &bytes_left,
- (unsigned char **) &increment_nbytes);
- if (result == Success)
- {
- XPropertyEvent property_event;
-
- total_size = *increment_nbytes;
- increment_value = (unsigned char *) alloca (total_size);
- increment_ptr = increment_value;
-
- XDeleteProperty (x_current_display, event->requestor,
- event->property);
- XFlush (x_current_display);
- XFree ((char *) increment_nbytes);
-
- do
- { /* NOTE: this blocks. */
- XWindowEvent (x_current_display, requestor_window,
- PropertyChangeMask,
- (XEvent *) &property_event);
-
- if (property_event.atom == selection
- && property_event.state == PropertyNewValue)
- do
- {
- result = XGetWindowProperty (x_current_display,
- requestor_window,
- selection, 0L,
- 10000000L, True,
- AnyPropertyType,
- &type, &format,
- &items, &bytes_left,
- &data);
- if (result == Success && type == XA_STRING
- && format == 8)
- {
- bcopy (data, increment_ptr, items);
- increment_ptr += items;
- }
- }
- while (bytes_left);
-
- }
- while (increment_ptr < (increment_value + total_size));
-
- return make_string (increment_value,
- (increment_ptr - increment_value));
- }
- }
-
- return Qnil;
-}
-
-void
-syms_of_xselect ()
-{
- DEFVAR_LISP ("x-selection-value", &Vx_selection_value,
- "The value of emacs' last cut-string.");
- Vx_selection_value = Qnil;
-
- DEFVAR_LISP ("x-clipboard-value", &Vx_clipboard_value,
- "The string emacs last sent to the clipboard.");
- Vx_clipboard_value = Qnil;
-
- defsubr (&Sx_own_selection);
- defsubr (&Sx_get_selection);
- defsubr (&Sx_own_clipboard);
- defsubr (&Sx_get_clipboard);
-}
-#endif /* X11 */
diff --git a/src/xterm.c b/src/xterm.c
new file mode 100644
index 00000000000..7d946a76a76
--- /dev/null
+++ b/src/xterm.c
@@ -0,0 +1,1933 @@
+/* X Communication module for terminals which understand the X protocol.
+ Copyright (C) 1985, 1986, 1987, 1988 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Written by Yakim Martillo, mods and things by Robert Krawitz */
+
+/*
+ * $Source: /u2/third_party/gnuemacs.chow/src/RCS/xterm.c,v $
+ * $Author: rlk $
+ * $Locker: $
+ * $Header: xterm.c,v 1.28 86/08/27 13:30:57 rlk Exp $
+ */
+
+#ifndef lint
+static char *rcsid_TrmXTERM_c = "$Header: xterm.c,v 1.28 86/08/27 13:30:57 rlk Exp $";
+#endif lint
+
+/* On 4.3 this loses if it comes after xterm.h. */
+#include <signal.h>
+#include "config.h"
+
+#ifdef HAVE_X_WINDOWS
+
+#include "lisp.h"
+#undef NULL
+
+/* This may include sys/types.h, and that somehow loses
+ if this is not done before the other system files. */
+#include "xterm.h"
+
+/* Load sys/types.h if not already loaded.
+ In some systems loading it twice is suicidal. */
+#ifndef makedev
+#include <sys/types.h>
+#endif
+
+#if !defined(USG) || defined(IBMRTAIX)
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif /* USG and not IBMRTAIX */
+
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <errno.h>
+#ifdef BSD
+#include <strings.h>
+#endif
+#include <sys/stat.h>
+
+#include "dispextern.h"
+#include "termhooks.h"
+#include "termopts.h"
+#include "termchar.h"
+#include "sink.h"
+#include "sinkmask.h"
+#include <X/Xkeyboard.h>
+/*#include <X/Xproto.h> */
+
+/* Allow m- file to inhibit use of FIONREAD. */
+#ifdef BROKEN_FIONREAD
+#undef FIONREAD
+#endif
+
+/* We are unable to use interrupts if FIONREAD is not available,
+ so flush SIGIO so we won't try. */
+#ifndef FIONREAD
+#ifdef SIGIO
+#undef SIGIO
+#endif
+#endif
+
+/* Allow config to specify default font. */
+#ifndef X_DEFAULT_FONT
+#define X_DEFAULT_FONT "vtsingle"
+#endif
+
+#define min(a,b) ((a)<(b) ? (a) : (b))
+#define max(a,b) ((a)>(b) ? (a) : (b))
+#define sigunblockx(sig) sigblock (0)
+#define sigblockx(sig) sigblock (1 << ((sig) - 1))
+XREPBUFFER Xxrepbuffer;
+int pixelwidth;
+int pixelheight;
+int PendingExposure;
+int PendingIconExposure;
+#define MAXICID 80
+char iconidentity[MAXICID];
+#define ICONTAG "emacs@"
+#define METABIT 0x80
+Window XXIconWindow;
+Bitmap XXIconMask;
+
+char *XXcurrentfont;
+char *default_window;
+int informflag;
+extern int initialized;
+
+extern char *alternate_display;
+
+int XXdebug;
+int XXpid;
+extern int screen_garbaged;
+int XXxoffset, XXyoffset;
+int IconWindow;
+
+int WindowMapped;
+int CurHL;
+
+static int flexlines; /* last line affect by dellines or */
+ /* inslines functions */
+extern int errno;
+int VisibleX, VisibleY; /* genuine location of cursor on screen */
+ /* if it is there */
+static int SavedX, SavedY; /* Where the cursor was before update */
+ /* started */
+
+int bitblt; /* Used to track bit blt events */
+int CursorExists; /* during updates cursor is turned off */
+static int InUpdate; /* many of functions here may be invoked */
+ /* even if no update in progress, when */
+ /* no update is in progress the action */
+ /* can be slightly different */
+
+short MouseCursor[] = {
+ 0x0000, 0x0008, 0x0018, 0x0038,
+ 0x0078, 0x00f8, 0x01f8, 0x03f8,
+ 0x07f8, 0x00f8, 0x00d8, 0x0188,
+ 0x0180, 0x0300, 0x0300, 0x0000};
+
+short MouseMask[] = {
+ 0x000c, 0x001c, 0x003c, 0x007c,
+ 0x00fc, 0x01fc, 0x03fc, 0x07fc,
+ 0x0ffc, 0x0ffc, 0x01fc, 0x03dc,
+ 0x03cc, 0x0780, 0x0780, 0x0300};
+
+Display *XXdisplay;
+FontInfo *fontinfo;
+Window XXwindow;
+Cursor EmacsCursor;
+
+char *fore_color; /* Variables to store colors */
+char *back_color;
+char *brdr_color;
+char *curs_color;
+char *mous_color;
+
+int fore;
+int back;
+int brdr;
+int curs;
+int mous;
+
+static WindowInfo windowinfo;
+WindowInfo rootwindowinfo;
+
+
+
+static XKeyPressedEvent XXEvent; /* as X messages are read in they are */
+ /* stored here */
+static XREPBUFFER XXqueue;/* Used for storing up ExposeRegion */
+ /* replies, so that the SIGIO inter- */
+ /* rupt serving routines do almost */
+ /* no writes to the X socket */
+/*int CurHL; /* Current Highlighting actually being */
+ /* being used for bold font right now*/
+
+int XXborder;
+int XXInternalBorder;
+
+int (*handler)();
+
+extern Display *XOpenDisplay ();
+extern Window XCreateWindow ();
+extern Cursor XDefineCursor ();
+extern Cursor XCreateCursor ();
+extern FontInfo *XOpenFont ();
+
+static int flashback ();
+
+
+/* HLmode -- Changes the GX function for output strings. Could be used to
+ * change font. Check an XText library function call.
+ */
+
+static
+HLmode (new)
+ int new;
+{
+ CurHL = new;
+}
+
+
+/* External interface to control of standout mode.
+ Call this when about to modify line at position VPOS
+ and not change whether it is highlighted. */
+
+XTreassert_line_highlight (highlight, vpos)
+ int highlight, vpos;
+{
+ HLmode (highlight);
+}
+
+/* Call this when about to modify line at position VPOS
+ and change whether it is highlighted. */
+
+static
+XTchange_line_highlight (new_highlight, vpos, first_unused_hpos)
+ int new_highlight, vpos, first_unused_hpos;
+{
+ HLmode (new_highlight);
+ XTmove_cursor (vpos, 0);
+ x_clear_end_of_line (0);
+}
+
+
+/* Used for starting or restarting (after suspension) the X window. Puts the
+ * cursor in a known place, update does not begin with this routine but only
+ * with a call to redisplay. The mouse cursor is warped into the window and
+ * then the cursor is turned on.
+ */
+
+
+
+static
+XTset_terminal_modes ()
+{
+ int stuffpending;
+#ifdef XDEBUG
+ fprintf (stderr, "XTset_terminal_modes\n");
+#endif
+ InUpdate = 0;
+ stuffpending = 0;
+ if (!initialized)
+ {
+ CursorExists = 0;
+ VisibleX = 0;
+ VisibleY = 0;
+ }
+ XTclear_screen ();
+#ifdef FIONREAD
+ ioctl (0, FIONREAD, &stuffpending);
+ if (stuffpending)
+ SIGNAL_INPUT ();
+#endif
+}
+
+/* XTmove_cursor moves the cursor to the correct location and checks whether an update
+ * is in progress in order to toggle it on.
+ */
+
+static
+XTmove_cursor (row, col)
+ register int row, col;
+{
+ BLOCK_INPUT_DECLARE ()
+
+ BLOCK_INPUT ();
+#ifdef XDEBUG
+ fprintf (stderr, "XTmove_cursor\n");
+#endif
+ cursor_hpos = col;
+ cursor_vpos = row;
+ if (InUpdate)
+ {
+ if (CursorExists)
+ {
+ CursorToggle ();
+ }
+ UNBLOCK_INPUT ();
+ return; /* Generally, XTmove_cursor will be invoked */
+ /* when InUpdate with !CursorExists */
+ /* so that wasteful XFlush is not called */
+ }
+ if ((row == VisibleY) && (col == VisibleX))
+ {
+ if (!CursorExists)
+ {
+ CursorToggle ();
+ }
+ XFlush ();
+ UNBLOCK_INPUT ();
+ return;
+ }
+ if (CursorExists) CursorToggle ();
+ VisibleX = col;
+ VisibleY = row;
+ if (!CursorExists) CursorToggle ();
+ XFlush ();
+ UNBLOCK_INPUT ();
+}
+
+/* Used to get the terminal back to a known state after resets. Usually
+ * used when restarting suspended or waiting emacs
+ */
+
+static
+cleanup ()
+{
+ inverse_video = 0;
+ HLmode (0);
+}
+
+/* Erase current line from column cursor_hpos to column END.
+ Leave cursor at END. */
+
+static
+XTclear_end_of_line (end)
+ register int end;
+{
+ register int numcols;
+
+#ifdef XDEBUG
+ fprintf (stderr, "XTclear_end_of_line\n");
+
+#endif
+ if (cursor_vpos < 0 || cursor_vpos >= screen_height)
+ {
+ return;
+ }
+
+ if (end >= screen_width)
+ end = screen_width;
+ if (end <= cursor_hpos)
+ return;
+
+ numcols = end - cursor_hpos;
+ {
+ BLOCK_INPUT_DECLARE ()
+
+ BLOCK_INPUT ();
+ if (cursor_vpos == VisibleY && VisibleX >= cursor_hpos && VisibleX < end)
+ {
+ if (CursorExists) CursorToggle ();
+ }
+ XPixSet (XXwindow,
+ cursor_hpos * fontinfo->width + XXInternalBorder,
+ cursor_vpos * fontinfo->height+XXInternalBorder,
+ fontinfo->width * numcols,
+ fontinfo->height,
+ back);
+ XTmove_cursor (cursor_vpos, end);
+ UNBLOCK_INPUT ();
+ }
+}
+
+/* Erase current line from column START to right margin.
+ Leave cursor at START. */
+
+static
+x_clear_end_of_line (start)
+ register int start;
+{
+ register int numcols;
+
+#ifdef XDEBUG
+ fprintf (stderr, "x_clear_end_of_line\n");
+
+#endif
+ if (cursor_vpos < 0 || cursor_vpos >= screen_height)
+ {
+ return;
+ }
+
+ if (start < 0)
+ start = 0;
+ if (start >= screen_width)
+ return;
+
+ numcols = screen_width - start;
+ {
+ BLOCK_INPUT_DECLARE ()
+
+ BLOCK_INPUT ();
+ if (cursor_vpos == VisibleY && VisibleX >= start)
+ {
+ if (CursorExists) CursorToggle ();
+ }
+ XPixSet (XXwindow,
+ start * fontinfo->width + XXInternalBorder,
+ cursor_vpos * fontinfo->height+XXInternalBorder,
+ fontinfo->width * numcols,
+ fontinfo->height,
+ back);
+ XTmove_cursor (cursor_vpos, start);
+ UNBLOCK_INPUT ();
+ }
+}
+
+static
+XTreset_terminal_modes ()
+{
+#ifdef XDEBUG
+ fprintf (stderr, "XTreset_terminal_modes\n");
+#endif
+ XTclear_screen ();
+}
+
+static
+XTclear_screen ()
+{
+#ifdef XDEBUG
+ fprintf (stderr, "XTclear_screen\n");
+#endif
+ HLmode (0);
+ CursorExists = 0;
+
+ cursor_hpos = 0;
+ cursor_vpos = 0;
+ SavedX = 0;
+ SavedY = 0;
+ VisibleX = 0;
+ VisibleY = 0;
+ {
+ BLOCK_INPUT_DECLARE ()
+
+ BLOCK_INPUT ();
+ XClear (XXwindow);
+ CursorToggle ();
+ if (!InUpdate)
+ XFlush ();
+ UNBLOCK_INPUT ();
+ }
+}
+
+/* used by dumprectangle which is usually invoked upon ExposeRegion
+ * events which come from bit blt's or moving an obscuring opaque window
+ */
+
+static
+dumpchars (current_screen, numcols, tempX, tempY, tempHL)
+ register struct matrix *current_screen;
+ register int numcols;
+ register int tempX, tempY, tempHL;
+{
+ if (numcols <= 0) return;
+ if (((numcols - 1) + tempX) > screen_width)
+ {
+ numcols = (screen_width - tempX) + 1;
+ }
+ if ((tempX < 0) || (tempX >= screen_width) ||
+ (tempY < 0) || (tempY >= screen_height))
+ {
+ return;
+ }
+ XText (XXwindow,
+ (tempX * fontinfo->width+XXInternalBorder),
+ (tempY * fontinfo->height+XXInternalBorder),
+ &current_screen->contents[tempY][tempX],
+ numcols,
+ fontinfo->id,
+ (tempHL ? back : fore),
+ (tempHL ? fore : back));
+}
+
+/* When a line has been changed this function is called. X is so fast
+ * that the actual sequence is ignore. Rather, the new version of the
+ * line is simply output if this function is invoked while in UpDate.
+ * Sometimes writechars can be invoked when not in update if text is to
+ * be output at the end of the line. In this case the whole line is not
+ * output. Simply the new text at the current cursor position given
+ * by VisibleX,Y. The cursor is moved to the end of the new text.
+ */
+static
+writechars (start, end)
+ register char *start, *end;
+{
+ register int temp_length;
+ BLOCK_INPUT_DECLARE ()
+
+ BLOCK_INPUT ();
+
+ if ((cursor_vpos < 0) || (cursor_vpos >= screen_height))
+ {
+ UNBLOCK_INPUT ();
+ return;
+ }
+ if (CursorExists)
+ {
+ CursorToggle ();
+ }
+ if (InUpdate)
+ {
+ if (end != start - 1)
+ {
+ XText (XXwindow,
+ (cursor_hpos * fontinfo->width+XXInternalBorder),
+ (cursor_vpos * fontinfo->height+XXInternalBorder),
+ start,
+ end + 1 - start,
+ fontinfo->id,
+ (CurHL ? back : fore),
+ (CurHL ? fore : back));
+ XTmove_cursor (cursor_vpos, cursor_hpos + end - start + 1);
+ }
+ }
+ else
+ {
+ if ((VisibleX < 0) || (VisibleX >= screen_width))
+ {
+ UNBLOCK_INPUT ();
+ return;
+ }
+ if ((VisibleY < 0) || (VisibleY >= screen_height))
+ {
+ UNBLOCK_INPUT ();
+ return;
+ }
+ if (((end - start) + VisibleX) >= screen_width)
+ {
+ end = start + (screen_width - (VisibleX + 1));
+ }
+ if (end >= start)
+ {
+ XText (XXwindow,
+ (VisibleX * fontinfo->width+XXInternalBorder),
+ (VisibleY * fontinfo->height+XXInternalBorder),
+ start,
+ ((end - start) + 1),
+ fontinfo->id,
+ (CurHL ? back : fore),
+ (CurHL ? fore : back));
+ VisibleX = VisibleX + (end - start) + 1;
+ }
+ if (!CursorExists) CursorToggle ();
+ }
+ UNBLOCK_INPUT ();
+}
+
+
+static
+XToutput_chars (start, len)
+ register char *start;
+ register int len;
+{
+#ifdef XDEBUG
+ fprintf (stderr, "XToutput_chars\n");
+#endif
+ writechars (start, start + len - 1);
+}
+
+/* The following routine is for the deaf or for the pervert who prefers
+ * that his terminal flash at him rather than beep at him.
+ */
+
+static int flashedback;
+
+static
+XTflash ()
+{
+#ifdef ITIMER_REAL
+ struct itimerval itimer;
+
+#ifdef XDEBUG
+ fprintf (stderr, "XTflash\n");
+#endif
+
+ stop_polling ();
+ signal (SIGALRM, flashback);
+ getitimer (ITIMER_REAL, &itimer);
+ itimer.it_value.tv_usec += 250000;
+ itimer.it_interval.tv_sec = 0;
+ itimer.it_interval.tv_usec = 0;
+ flashedback = 0;
+ setitimer (ITIMER_REAL, &itimer, 0);
+ {
+ BLOCK_INPUT_DECLARE ()
+
+ BLOCK_INPUT ();
+ XPixFill (XXwindow, 0, 0, screen_width*fontinfo->width+2*XXInternalBorder,
+ screen_height * fontinfo->height+2*XXInternalBorder, WhitePixel,
+ ClipModeClipped, GXinvert, AllPlanes);
+ XFlush ();
+ UNBLOCK_INPUT ();
+ }
+ while (!flashedback) pause ();
+#endif /* have ITIMER_REAL */
+}
+
+static
+flashback ()
+{
+#ifdef ITIMER_REAL
+#ifdef SIGIO
+ int mask = sigblock (sigmask (SIGIO) | sigmask (SIGALRM));
+#else
+ int mask = sigblock (sigmask (SIGALRM));
+#endif
+ XPixFill (XXwindow, 0, 0, screen_width * fontinfo->width+2*XXInternalBorder,
+ screen_height * fontinfo->height+2*XXInternalBorder, WhitePixel,
+ ClipModeClipped, GXinvert, AllPlanes);
+ XFlush ();
+ flashedback = 1;
+ sigsetmask (mask);
+ start_polling ();
+#endif /* have ITIMER_REAL */
+}
+
+/* A kludge to get a bell */
+
+static
+XTfeep ()
+{
+ BLOCK_INPUT_DECLARE ()
+
+ BLOCK_INPUT ();
+#ifdef XDEBUG
+ fprintf (stderr, "XTfeep\n");
+#endif
+ XFeep (0);
+ UNBLOCK_INPUT ();
+}
+
+/* Artificially creating a cursor is hard, the actual position on the
+ * screen (either where it is or last was) is tracked with VisibleX,Y.
+ * Gnu Emacs code tends to assume a cursor exists in hardward at cursor_hpos,Y
+ * and that output text will appear there. During updates, the cursor is
+ * supposed to be blinked out and will only reappear after the update
+ * finishes.
+ */
+
+CursorToggle ()
+{
+ if (!WindowMapped)
+ {
+ CursorExists = 0;
+ return 0;
+ }
+ if ((VisibleX < 0) || (VisibleX >= screen_width) ||
+ (VisibleY < 0) || (VisibleY >= screen_height))
+ { /* Current Cursor position trash */
+ /* Not much can be done */
+ XFlush ();
+ CursorExists = 0;
+ return 0;
+ /* Currently the return values are not */
+ /* used, but I could anticipate using */
+ /* them in the future. */
+ }
+
+ if (current_screen->enable[VisibleY] &&
+ (VisibleX < current_screen->used[VisibleY]))
+ {
+ if (CursorExists)
+ {
+ XText (XXwindow,
+ VisibleX * fontinfo->width+XXInternalBorder,
+ VisibleY * fontinfo->height+XXInternalBorder,
+ &current_screen->contents[VisibleY][VisibleX], 1,
+ fontinfo->id,
+ fore, back);
+ }
+ else
+ {
+ XText (XXwindow,
+ VisibleX * fontinfo->width+XXInternalBorder,
+ VisibleY * fontinfo->height+XXInternalBorder,
+ &current_screen->contents[VisibleY][VisibleX], 1,
+ fontinfo->id,
+ back, curs);
+ }
+ }
+ else if (CursorExists)
+ {
+ XPixSet (XXwindow,
+ VisibleX * fontinfo->width+XXInternalBorder,
+ VisibleY * fontinfo->height+XXInternalBorder,
+ fontinfo->width, fontinfo->height, back);
+ }
+ else
+ {
+ XPixSet (XXwindow,
+ VisibleX * fontinfo->width+XXInternalBorder,
+ VisibleY * fontinfo->height+XXInternalBorder,
+ fontinfo->width, fontinfo->height, curs);
+ }
+ CursorExists = !CursorExists;
+ /* Cursor has either been blinked in */
+ /* or out */
+ if (!InUpdate)
+ {
+ XFlush ();
+ }
+ return 1;
+}
+
+/* This routine is used by routines which are called to paint regions */
+/* designated by ExposeRegion events. If the cursor may be in the exposed */
+/* region, this routine makes sure it is gone so that dumprectangle can */
+/* toggle it back into existance if dumprectangle is invoked when not in */
+/* the midst of a screen update. */
+static
+ClearCursor ()
+{
+ BLOCK_INPUT_DECLARE ()
+
+ BLOCK_INPUT ();
+ if (!WindowMapped)
+ {
+ CursorExists = 0;
+ UNBLOCK_INPUT ();
+ return;
+ }
+ if ((VisibleX < 0) || (VisibleX >= screen_width)
+ || (VisibleY < 0) || (VisibleY >= screen_height))
+ { /* Current Cursor position trash */
+ /* Not much can be done */
+ CursorExists = 0;
+ UNBLOCK_INPUT ();
+ return;
+ }
+ XPixSet (XXwindow,
+ VisibleX * fontinfo->width+XXInternalBorder,
+ VisibleY * fontinfo->height+XXInternalBorder,
+ fontinfo->width, fontinfo->height,
+ back);
+ CursorExists = 0;
+ UNBLOCK_INPUT ();
+}
+
+static
+XTupdate_begin ()
+{
+ BLOCK_INPUT_DECLARE ()
+
+ BLOCK_INPUT ();
+#ifdef XDEBUG
+ fprintf (stderr, "XTupdate_begin\n");
+#endif
+
+ InUpdate = 1;
+ if (CursorExists)
+ {
+ CursorToggle ();
+ }
+ SavedX = cursor_hpos; /* The initial"hardware" cursor position is */
+ /* saved because that is where gnu emacs */
+ /* expects the cursor to be at the end of*/
+ /* the update */
+ SavedY = cursor_vpos;
+ dumpqueue ();
+ UNBLOCK_INPUT ();
+}
+
+
+static
+XTupdate_end ()
+{
+ BLOCK_INPUT_DECLARE ()
+
+ BLOCK_INPUT ();
+#ifdef XDEBUG
+ fprintf (stderr, "XTupdate_end\n");
+#endif
+ if (CursorExists)
+ CursorToggle ();
+ InUpdate = 0;
+ dumpqueue ();
+ XTmove_cursor (SavedY, SavedX); /* XTmove_cursor invokes cursor toggle */
+ UNBLOCK_INPUT ();
+}
+
+/* Used for expose region and expose copy events. Have to get the text
+ * back into the newly blank areas.
+ */
+
+dumprectangle (top, left, rows, cols)
+ register int top, left, rows, cols;
+{
+ register int index;
+ int localX, localY, localHL;
+ rows += top;
+ cols += left;
+ top /= fontinfo->height;
+ /* Get row and col containing up and */
+ /* left borders of exposed region -- */
+ /* round down here*/
+ left /= fontinfo->width;
+ rows += (fontinfo->height - 1);
+ cols += (fontinfo->width - 1);
+ rows /= fontinfo->height;
+ /* Get row and col containing bottom and */
+ /* right borders -- round up here */
+ rows -= top;
+ cols /= fontinfo->width;
+ cols -= left;
+ if (rows < 0) return;
+ if (cols < 0) return;
+ if (top > (screen_height - 1)) return;
+ if (left > (screen_width - 1)) return;
+ if ((VisibleX >= left) && (VisibleX < (left + cols)) &&
+ (VisibleY >= top) && (VisibleY < (top + rows)))
+ {
+ ClearCursor ();
+ }
+
+ /* should perhaps be DesiredScreen */
+ /* but PhysScreen is guaranteed to contain*/
+ /* date which was good for every line on */
+ /* screen. For desired screen only for */
+ /* lines which are changing. Emacs does */
+ /* not consider a line within a newly */
+ /* exposed region necessarily to have */
+ /* been changed. Emacs knows nothing */
+ /* about ExposeRegion events.*/
+ for (localY = top, index = 0;
+ (index < rows) && (localY < screen_height);
+ ++index, ++localY)
+ {
+ if ((localY < 0) || (localY >= screen_height)) continue;
+ if (!current_screen->enable[localY]) continue;
+ if ((left + 1) > current_screen->used[localY]) continue;
+ localX = left;
+ localHL = current_screen->highlight[localY];
+ dumpchars (current_screen,
+ min (cols,
+ current_screen->used[localY]
+ - localX),
+ localX, localY, localHL);
+ }
+ if (!InUpdate && !CursorExists) CursorToggle ();
+ /* Routine usually called */
+ /* when not in update */
+}
+
+/* What sections of the window will be modified from the UpdateDisplay
+ * routine is totally under software control. Any line with Y coordinate
+ * greater than flexlines will not change during an update. This is really
+ * used only during dellines and inslines routines (scraplines and stufflines)
+ */
+static
+XTset_terminal_window (n)
+ register int n;
+{
+#ifdef XDEBUG
+ fprintf (stderr, "XTset_terminal_window\n");
+#endif
+ if ((n <= 0) || (n > screen_height))
+ flexlines = screen_height;
+ else
+ flexlines = n;
+}
+
+XTins_del_lines (vpos, n)
+ int vpos, n;
+{
+#ifdef XDEBUG
+ fprintf (stderr, "XTins_del_lines\n");
+#endif
+ XTmove_cursor (vpos, 0);
+ if (n >= 0) stufflines (n);
+ else scraplines (-n);
+}
+
+static
+XTinsert_chars (start, len)
+ register char *start;
+ register int len;
+{
+#ifdef XDEBUG
+ fprintf (stderr, "XTinsert_chars\n");
+#endif
+ writechars (start, start + len - 1);
+}
+
+static
+XTdelete_chars (n)
+ register int n;
+{
+ char *msg = "***Delete Chars Called Outside of Update!!!***";
+#ifdef XDEBUG
+ fprintf (stderr, "XTdelete_chars\n");
+#endif
+ writechars (msg, msg + strlen (msg) - 1);
+}
+
+static
+stufflines (n)
+ register int n;
+{
+ register int topregion, bottomregion;
+ register int length, newtop;
+ BLOCK_INPUT_DECLARE ()
+
+ if (cursor_vpos >= flexlines)
+ return;
+
+ if (!WindowMapped)
+ {
+ bitblt = 0;
+ return;
+ }
+ BLOCK_INPUT ();
+ if (CursorExists) CursorToggle ();
+ dumpqueue ();
+ UNBLOCK_INPUT ();
+ topregion = cursor_vpos;
+ bottomregion = flexlines - (n + 1);
+ newtop = cursor_vpos + n;
+ length = (bottomregion - topregion) + 1;
+ if ((length > 0) && (newtop <= flexlines))
+ {
+ BLOCK_INPUT ();
+ /* Should already have cleared */
+ /* queue of events associated */
+ /* with old bitblts */
+ XMoveArea (XXwindow, XXInternalBorder,
+ topregion * fontinfo->height+XXInternalBorder,
+ XXInternalBorder, newtop * fontinfo->height+XXInternalBorder,
+ screen_width * fontinfo->width,
+ length * fontinfo->height);
+ if (WindowMapped)
+ bitblt = 1;
+ XFlush ();
+ UNBLOCK_INPUT ();
+ SIGNAL_INPUT_WHILE (bitblt);
+ XFlush ();
+ }
+ newtop = min (newtop, (flexlines - 1));
+ length = newtop - topregion;
+ if (length > 0)
+ {
+ XPixSet (XXwindow,
+ XXInternalBorder,
+ topregion * fontinfo->height+XXInternalBorder,
+ screen_width * fontinfo->width,
+ n * fontinfo->height,
+ back);
+ }
+ /* if (!InUpdate) CursorToggle (); */
+}
+
+static
+scraplines (n)
+ register int n;
+{
+ BLOCK_INPUT_DECLARE ()
+ if (!WindowMapped)
+ {
+ bitblt = 0;
+ return;
+ }
+
+ if (cursor_vpos >= flexlines)
+ return;
+ BLOCK_INPUT ();
+ if (CursorExists) CursorToggle ();
+ dumpqueue ();
+ if ((cursor_vpos + n) >= flexlines)
+ {
+ if (flexlines >= (cursor_vpos + 1))
+ {
+ XPixSet (XXwindow,
+ XXInternalBorder, cursor_vpos * fontinfo->height+XXInternalBorder,
+ screen_width * fontinfo->width,
+ (flexlines - cursor_vpos) * fontinfo->height,
+ back);
+ }
+ UNBLOCK_INPUT ();
+ }
+ else
+ {
+ XMoveArea (XXwindow,
+ XXInternalBorder,
+ (cursor_vpos + n) * fontinfo->height+XXInternalBorder,
+ XXInternalBorder, cursor_vpos * fontinfo->height+XXInternalBorder,
+ screen_width * fontinfo->width,
+ (flexlines - (cursor_vpos + n)) * fontinfo->height);
+ if (WindowMapped)
+ bitblt = 1;
+ XFlush ();
+ UNBLOCK_INPUT ();
+ SIGNAL_INPUT_WHILE (bitblt);
+ BLOCK_INPUT ();
+ XFlush ();
+ XPixSet (XXwindow, XXInternalBorder,
+ (flexlines - n) * fontinfo->height+XXInternalBorder,
+ screen_width * fontinfo->width,
+ n * fontinfo->height, back);
+ UNBLOCK_INPUT ();
+ }
+ /* if (!InUpdate) CursorToggle (); */
+}
+
+/* Substitutes for standard read routine. Under X not interested in individual
+ * bytes but rather individual packets.
+ */
+
+XTread_socket (sd, bufp, numchars)
+ register int sd;
+ register char *bufp;
+ register int numchars;
+{
+
+ int count;
+ char *where_mapping;
+ int nbytes;
+ int stuffpending;
+ int temp_width, temp_height;
+ BLOCK_INPUT_DECLARE ()
+ /* XKeyPressedEvent event; */
+ /* typedef struct reply {XEvent event; struct reply *next} Reply;
+ Reply *replies = NULL;*/
+
+ BLOCK_INPUT ();
+ count = 0;
+ if (numchars <= 0)
+ { /* To keep from overflowing read buffer */
+ numchars = 1;
+ --bufp;
+ }
+#ifdef SIGIO
+ while (bitblt || XPending () != 0)
+#else
+#ifndef HAVE_SELECT
+ if (! (fcntl (fileno (stdin), F_GETFL, 0) & O_NDELAY))
+ {
+ extern int read_alarm_should_throw;
+ if (CursorExists)
+ xfixscreen ();
+ read_alarm_should_throw = 1;
+ XPeekEvent (&XXEvent);
+ read_alarm_should_throw = 0;
+ }
+#endif
+ while (XPending () != 0)
+#endif
+ {
+ /* while there are more events*/
+ XNextEvent (&XXEvent);
+ switch (XXEvent.type)
+ {
+/* case X_Reply:
+ {
+ extern char *malloc ();
+ Reply *reply = (Reply *) malloc (sizeof (Reply));
+ reply->next = replies;
+ reply->event = XXEvent;
+ replies = reply;
+ break;
+ }*/
+ default:
+ break;
+ case ExposeWindow:
+ if (((XExposeEvent *)&XXEvent)->window == XXIconWindow)
+ {
+ PendingIconExposure = 1;
+ }
+ else
+ PendingExposure = 1;/* No reason to repeat */
+ /* this if several */
+ /* ExposeWindow events */
+ /* come in quick succes-*/
+ /* ion */
+ break;
+ case ExposeRegion:
+ if (PendingExposure)
+ { /* Don't bother with */
+ /* region events when */
+ /* full window event */
+ /* is pending */
+ break;
+ }
+ loadxrepbuffer (&XXEvent, &XXqueue);
+ if (XXqueue.rindex == XXqueue.windex)
+ {
+ PendingExposure = 1;
+ }
+ if ((XXqueue.rindex > XXqueue.mindex) ||
+ (XXqueue.windex > XXqueue.mindex) ||
+ (XXqueue.rindex < 0) ||
+ (XXqueue.windex < 0))
+ {
+ PendingExposure = 1;
+ }
+ break;
+ case ExposeCopy: /* For ExposeCopy sync */
+ /* will block all outgoing */
+ /* requests until this is */
+ /* decremented */
+ if (WindowMapped) bitblt = 0;
+ break;
+ case KeyPressed:
+ /* bcopy (XXEvent, event, sizeof (XKeyPressedEvent)); */
+ where_mapping = XLookupMapping (&XXEvent, &nbytes);
+ /* Nasty fix for arrow keys */
+ if (!nbytes && IsCursorKey (XXEvent.detail & 0xff))
+ {
+ switch (XXEvent.detail & 0xff)
+ {
+ case KC_CURSOR_LEFT:
+ where_mapping = "\002";
+ break;
+ case KC_CURSOR_RIGHT:
+ where_mapping = "\006";
+ break;
+ case KC_CURSOR_UP:
+ where_mapping = "\020";
+ break;
+ case KC_CURSOR_DOWN:
+ where_mapping = "\016";
+ break;
+ }
+ nbytes = 1;
+ }
+ if (numchars - nbytes > 0)
+ {
+ bcopy (where_mapping, bufp, nbytes);
+ bufp += nbytes;
+ count += nbytes;
+ numchars -= nbytes;
+ }
+/* else
+ {
+ bcopy (where_mapping, bufp, numchars);
+ bufp += numchars;
+ count += numchars;
+ numchars = 0;
+ *(bufp-1) = *(where_mapping + nbytes - 1);
+ }*/
+ break;
+ case ButtonPressed:
+ case ButtonReleased:
+ switch (spacecheck (Xxrepbuffer.mindex,
+ Xxrepbuffer.rindex,
+ Xxrepbuffer.windex, 0))
+ {
+ case 0:
+ loadxrepbuffer (&XXEvent,
+ &Xxrepbuffer);
+ if (informflag && (numchars > 1))
+ {
+ *bufp++ = (char) 'X' & 037; /* C-x */
+ ++count;
+ --numchars;
+ *bufp++ = (char) 0; /* C-@ */
+ ++count;
+ --numchars;
+ }
+ break;
+ case -1:
+ break;
+ case -2:
+ default:
+ fixxrepbuffer ();
+ break;
+ }
+ break;
+ }
+ }
+/* while (replies) {
+ Reply *reply = replies;
+ XPutBackEvent (&reply->event);
+ replies = reply->next;
+ free (reply);
+ }*/
+ if (count < 0)
+ count = 0;
+#ifdef HAVE_SELECT
+ if (CursorExists
+#ifdef O_NDELAY
+#ifdef F_GETFL
+ && (! (fcntl (fileno (stdin), F_GETFL, 0) & O_NDELAY))
+#endif
+#endif
+ )
+ xfixscreen ();
+#endif
+ UNBLOCK_INPUT ();
+ return count;
+}
+
+/* refresh bitmap kitchen sink icon */
+refreshicon ()
+{
+ BLOCK_INPUT_DECLARE ()
+
+ BLOCK_INPUT ();
+ if (XXIconWindow)
+ XBitmapBitsPut (XXIconWindow, 0, 0, sink_width, sink_height,
+ sink_bits, BlackPixel, WhitePixel,
+ XXIconMask, GXcopy, AllPlanes);
+ XFlush ();
+ UNBLOCK_INPUT ();
+}
+
+XBitmapIcon ()
+{
+ BLOCK_INPUT_DECLARE ()
+
+ BLOCK_INPUT ();
+ if (!IconWindow)
+ {
+ XSetIconWindow (XXwindow,XXIconWindow);
+ XSelectInput (XXIconWindow, ExposeWindow);
+ IconWindow = !IconWindow;
+ }
+ UNBLOCK_INPUT ();
+}
+
+XTextIcon ()
+{
+ BLOCK_INPUT_DECLARE ()
+
+ BLOCK_INPUT ();
+ if (IconWindow)
+ {
+ XClearIconWindow (XXwindow);
+ XSelectInput (XXIconWindow, NoEvent);
+ IconWindow = !IconWindow;
+ }
+ UNBLOCK_INPUT ();
+}
+
+/* Interpreting incoming keycodes. Should have table modifiable as needed
+ * from elisp.
+ */
+
+/* Exit gracefully from gnuemacs, doing an autosave and giving a status.
+ */
+
+XExitGracefully (disp, event)
+ Display *disp;
+ XErrorEvent *event;
+{
+ XCleanUp ();
+ exit (70);
+}
+
+x_io_error (disp)
+ Display *disp;
+{
+ XCleanUp ();
+ exit (71);
+}
+
+#if 0
+/* This kludge overcomes the failure to handle EAGAIN and EINTR
+ in a certain version of X for 386 running system V. */
+
+x_io_error (disp, a, b, c, nwrite)
+ Display *disp;
+{
+ extern _XSend ();
+ unsigned int pc = ((unsigned int *)&disp)[-1];
+ if (pc - (unsigned int)&_XSend - 100 < 100
+ && (errno == EAGAIN || errno == EINTR))
+ {
+ /* We were called by `writedata' erroneously.
+ Modify a local variable which `writedata'
+ will subtract from the number of bytes to be written. */
+ nwrite = 0;
+ return;
+ }
+ abort ();
+}
+#endif
+
+xfixscreen ()
+{
+ register int temp_width, temp_height;
+ BLOCK_INPUT_DECLARE ()
+ /* register int temp_x, temp_y; */
+
+ BLOCK_INPUT ();
+ dumpqueue ();
+ /* Check that the connection is in fact open. This works by doing a nop */
+ /* (well, almost) write operation. If there is an XIOerror or a */
+ /* SIGPIPE, exit gracefully. This fixes the loop-on-logout bug.*/
+ /* XIOErrorHandler (XExitGracefully); */
+ XPixFill (XXwindow, 0, 0, 1, 1, back, ClipModeClipped, GXnoop, AllPlanes);
+ XFlush ();
+ /* XIOErrorHandler (0); */
+ if (PendingIconExposure)
+ {
+ refreshicon ();
+ PendingIconExposure = 0;
+ }
+ if (PendingExposure)
+ {
+ PendingExposure = 0;
+ ClearCursor ();
+ XXqueue.rindex = 0;
+ XXqueue.windex = 0;
+ XQueryWindow (XXwindow, &windowinfo); /* Dangerous to do */
+ /* writes here but */
+ /* otherwise would */
+ /* have to alter */
+ /* gnu emacs display */
+ /* routines to query */
+ /* when screen garbaged */
+ temp_width = (windowinfo.width - 2 * XXInternalBorder) / fontinfo->width;
+ temp_height = (windowinfo.height- 2*XXInternalBorder) / fontinfo->height;
+ if (temp_width != screen_width || temp_height != screen_height)
+ change_screen_size (max (5, temp_height), max (10, temp_width),
+ 0, 0, 0);
+ XXxoffset= windowinfo.x;
+ XXyoffset = windowinfo.y;
+ /*if (temp_x != XXxoffset || temp_y != XXyoffset)
+ XSetOffset (temp_x, temp_y);*/
+ dumprectangle (0, 0,
+ screen_height * fontinfo->height + 2 * XXInternalBorder,
+ screen_width * fontinfo->width + 2 * XXInternalBorder);
+ }
+ if (!InUpdate)
+ if (!CursorExists)
+ CursorToggle ();
+ XFlush ();
+ UNBLOCK_INPUT ();
+ SIGNAL_INPUT ();
+}
+
+x_term_init ()
+{
+ char *vardisplay;
+ char *temp_font;
+ register char *option;
+ extern XTinterrupt_signal ();
+ int reversevideo;
+ Color cdef;
+ char *progname;
+
+ Fset (intern ("window-system-version"), make_number (10));
+
+ vardisplay = (alternate_display ? alternate_display
+ : (char *) egetenv ("DISPLAY"));
+ if (!vardisplay || *vardisplay == '\0')
+ {
+ fprintf (stderr, "DISPLAY environment variable must be set\n");
+ exit (-200);
+ }
+
+ XXdisplay = XOpenDisplay (vardisplay);
+ if (XXdisplay == (Display *) 0)
+ {
+ fprintf (stderr, "X server not responding. Check your DISPLAY environment variable.\n");
+ exit (-200);
+ }
+ x_init_1 (1);
+ Xxrepbuffer.mindex = XREPBUFSIZE - 1;
+ Xxrepbuffer.windex = 0;
+ Xxrepbuffer.rindex = 0;
+ XXqueue.mindex = XREPBUFSIZE - 1;
+ XXqueue.windex = 0;
+ XXqueue.rindex = 0;
+ WindowMapped = 0;
+ baud_rate = 9600;
+ min_padding_speed = 10000;
+ must_write_spaces = 1;
+ informflag = 1;
+ meta_key = 1;
+ visible_bell = 1;
+#ifdef SIGIO
+ interrupt_input = 1;
+#endif
+ inverse_video = 1;
+ bitblt = 0;
+ PendingExposure = 0;
+
+ fix_screen_hook = xfixscreen;
+ clear_screen_hook = XTclear_screen;
+ clear_end_of_line_hook = XTclear_end_of_line;
+ ins_del_lines_hook = XTins_del_lines;
+ change_line_highlight_hook = XTchange_line_highlight;
+ insert_chars_hook = XTinsert_chars;
+ output_chars_hook = XToutput_chars;
+ delete_chars_hook = XTdelete_chars;
+ ring_bell_hook = XTfeep;
+ reset_terminal_modes_hook = XTreset_terminal_modes;
+ set_terminal_modes_hook = XTset_terminal_modes;
+ update_begin_hook = XTupdate_begin;
+ update_end_hook = XTupdate_end;
+ set_terminal_window_hook = XTset_terminal_window;
+ read_socket_hook = XTread_socket;
+ move_cursor_hook = XTmove_cursor;
+ /* raw_move_cursor_hook = XTraw_move_cursor; */
+ reassert_line_highlight_hook = XTreassert_line_highlight;
+ scroll_region_ok = 1; /* we'll scroll partial screens */
+ char_ins_del_ok = 0; /* just as fast to write the line */
+ line_ins_del_ok = 1; /* we'll just blt 'em */
+ fast_clear_end_of_line = 1; /* X does this well */
+ memory_below_screen = 0; /* we don't remember what scrolls
+ off the bottom */
+ dont_calculate_costs = 1;
+
+ /* New options section */
+ IconWindow = 0;
+ XXborder = 1;
+ XXInternalBorder = 1;
+ screen_width = 80;
+ screen_height = 66;
+ reversevideo = 0;
+ XXxoffset = 0;
+ XXyoffset = 0;
+ XXdebug = 0;
+
+ XErrorHandler (XExitGracefully);
+ XIOErrorHandler (x_io_error);
+
+ progname = "emacs";
+ if (option = XGetDefault (progname,"ReverseVideo"))
+ if (strcmp (option,"on") == 0) reversevideo = 1;
+ if (option = XGetDefault (progname, "BitmapIcon"))
+ if (strcmp (option, "on") == 0) IconWindow = 1;
+
+ if (option = XGetDefault (progname,"BorderWidth"))
+ XXborder = atoi (option);
+ if (option = XGetDefault (progname,"InternalBorder"))
+ XXInternalBorder = atoi (option);
+
+ brdr_color = XGetDefault (progname,"Border");
+ if (!brdr_color) brdr_color = XGetDefault (progname, "BorderColor");
+ back_color = XGetDefault (progname,"Background");
+ fore_color = XGetDefault (progname,"Foreground");
+ mous_color = XGetDefault (progname,"Mouse");
+ curs_color = XGetDefault (progname,"Cursor");
+
+ temp_font = XGetDefault (progname,"BodyFont");
+ if (temp_font == 0) temp_font = X_DEFAULT_FONT;
+ XXcurrentfont = (char *) xmalloc (strlen (temp_font) + 1);
+ strcpy (XXcurrentfont, temp_font);
+
+ /* If user has specified a special keymap for use with Emacs, use it. */
+ {
+ char *temp = XGetDefault (progname, "KeyMap");
+ if (temp) XUseKeymap (temp);
+ }
+
+ if (DisplayCells () > 2)
+ {
+
+ if (fore_color && XParseColor (fore_color, &cdef) &&
+ XGetHardwareColor (&cdef))
+ fore = cdef.pixel;
+ else
+ {
+ fore_color = "black";
+ fore = BlackPixel;
+ }
+
+ if (back_color && XParseColor (back_color, &cdef) &&
+ XGetHardwareColor (&cdef))
+ back = cdef.pixel;
+ else
+ {
+ back_color = "white";
+ back = WhitePixel;
+ }
+
+ if (curs_color && XParseColor (curs_color, &cdef) &&
+ XGetHardwareColor (&cdef))
+ curs = cdef.pixel;
+ else
+ {
+ curs_color = "black";
+ curs = BlackPixel;
+ }
+
+ if (mous_color && XParseColor (mous_color, &cdef) &&
+ XGetHardwareColor (&cdef))
+ mous = cdef.pixel;
+ else
+ {
+ mous_color = "black";
+ mous = BlackPixel;
+ }
+
+ if (brdr_color && XParseColor (brdr_color, &cdef) &&
+ XGetHardwareColor (&cdef))
+ brdr = cdef.pixel;
+ else
+ {
+ brdr_color = "black";
+ brdr = BlackPixel;
+ }
+ }
+ else
+ {
+ fore_color = curs_color = mous_color = brdr_color = "black";
+ fore = curs = mous = brdr = BlackPixel;
+ back_color = "white";
+ back = WhitePixel;
+ }
+
+ /*
+ if (fore_color && DisplayCells () > 2 &&
+ XParseColor (fore_color, &cdef) && XGetHardwareColor (&cdef))
+ fore = cdef.pixel;
+ else if (fore_color && strcmp (fore_color, "black") == 0)
+ fore = BlackPixel;
+ else if (fore_color && strcmp (fore_color, "white") == 0)
+ fore = WhitePixel;
+ else
+ {
+ fore_color = "black";
+ fore = BlackPixel;
+ }
+
+ if (back_color && DisplayCells () > 2 &&
+ XParseColor (back_color, &cdef) && XGetHardwareColor (&cdef))
+ back = cdef.pixel;
+ else if (back_color && strcmp (back_color, "white") == 0)
+ back = WhitePixel;
+ else if (back_color && strcmp (back_color, "black") == 0)
+ back = BlackPixel;
+ else
+ {
+ back_color = "white";
+ back = WhitePixel;
+ }
+
+ if (brdr_color && DisplayCells () > 2 &&
+ XParseColor (brdr_color, &cdef) && XGetHardwareColor (&cdef))
+ brdr = cdef.pixel;
+ else if (brdr_color && (!strcmp (brdr_color, "gray") ||
+ !strcmp (brdr_color, "grey") ||
+ !strcmp (brdr_color, "Gray") ||
+ !strcmp (brdr_color, "Grey")))
+ brdr = BlackPixel;
+ else if (brdr_color && strcmp (brdr_color, "white") == 0)
+ brdr = WhitePixel;
+ else
+ {
+ brdr_color = "black";
+ brdr = BlackPixel;
+ }
+
+ if (curs_color && DisplayCells () > 2 &&
+ XParseColor (curs_color, &cdef) && XGetHardwareColor (&cdef))
+ curs = cdef.pixel;
+ else if (curs_color && strcmp (curs_color, "black") == 0)
+ curs = BlackPixel;
+ else if (curs_color && strcmp (curs_color, "white") == 0)
+ curs = WhitePixel;
+ else
+ {
+ curs_color = "black";
+ curs = BlackPixel;
+ }
+
+ if (mous_color && DisplayCells () > 2 &&
+ XParseColor (mous_color, &cdef) && XGetHardwareColor (&cdef))
+ mous = cdef.pixel;
+ else if (mous_color && strcmp (mous_color, "black") == 0)
+ mous = BlackPixel;
+ else if (mous_color && strcmp (mous_color, "white") == 0)
+ mous = WhitePixel;
+ else
+ {
+ mous_color = "black";
+ mous = BlackPixel;
+ }
+ */
+
+ XXpid = getpid ();
+ if (XXcurrentfont == (char *) 0)
+ {
+ fprintf (stderr, "Memory allocation failure.\n");
+ exit (-150);
+ }
+ default_window = "=80x24+0+0";
+/* RMS: XTread_socket does not have an interface suitable
+ for being a signal handler. In any case, the SIGIO handler is
+ set up in init_keyboard and X uses the same one as usual. */
+/* signal (SIGIO, XTread_socket); */
+ signal (SIGPIPE, XExitGracefully);
+ XQueryWindow (RootWindow, &rootwindowinfo);
+ strncpy (iconidentity, ICONTAG, MAXICID);
+ fontinfo = XOpenFont (XXcurrentfont);
+ if (fontinfo == (FontInfo *) 0)
+ {
+ fprintf (stderr, "No font\n");
+ exit (-98);
+ }
+ pixelwidth = screen_width * fontinfo->width + 2 * XXInternalBorder;
+ pixelheight = screen_height * fontinfo->height + 2 * XXInternalBorder;
+ XXwindow = XCreateWindow (RootWindow,
+ XXxoffset /* Absolute horizontal offset */,
+ XXyoffset /* Absolute Vertical offset */,
+ pixelwidth, pixelheight,
+ XXborder, BlackPixmap, WhitePixmap);
+ if (!XXwindow)
+ {
+ fprintf (stderr, "Unable to create window.\n");
+ exit (-97);
+ }
+
+ XXIconWindow = XCreateWindow (RootWindow, 0, 0, sink_width, sink_height,
+ 2, WhitePixmap, (Pixmap) NULL);
+
+ if (!XXIconWindow)
+ {
+ fprintf (stderr, "Unable to create icon window.\n");
+ fflush (stderr);
+ exit (-97);
+ }
+ XSelectInput (XXIconWindow, NoEvent);
+ XXIconMask = XStoreBitmap (sink_mask_width, sink_mask_height, sink_mask_bits);
+
+ XSelectInput (XXwindow, NoEvent);
+ XSetResizeHint (XXwindow, 2 * XXInternalBorder, 2 * XXInternalBorder,
+ /* fontinfo->width * 1, fontinfo->height * 1, */
+ fontinfo->width, fontinfo->height);
+
+#if defined (BSD) || defined (HPUX) || defined (IBMRTAIX)
+ if (gethostname (&iconidentity[sizeof (ICONTAG) - 1],
+ (MAXICID - 1) - sizeof (ICONTAG)))
+#endif
+ {
+ iconidentity[sizeof (ICONTAG) - 2] = '\0';
+ }
+ XStoreName (XXwindow, &iconidentity[0]);
+
+ EmacsCursor = XCreateCursor (16, 16, MouseCursor, MouseMask,
+ 0, 0, mous, back, GXcopy);
+ XDefineCursor (XXwindow, EmacsCursor);
+ flexlines = screen_height;
+#if 0
+/* Do not call XPopUpWindow here! This is too early.
+ It is supposed ot be called via the term-setup-hook
+ and not until after lisp/term/x-win.el has had a chance
+ to process the user's switches.
+ I am not sure that there are any circumstances under which
+ this should be done here -- RMS. */
+ XPopUpWindow (); /* This looks at Vxterm */
+#endif /* 0 */
+ if (reversevideo) XFlipColor ();
+}
+
+x_init_1 (unrequest)
+{
+#ifdef F_SETOWN
+ extern int old_fcntl_owner;
+#endif
+#ifndef USG
+ extern void init_sigio (), request_sigio (), unrequest_sigio ();
+#endif
+
+ dup2 (dpyno (), 0);
+ close (dpyno ());
+ dpyno () = 0; /* Looks a little strange?
+ check the def of the macro;
+ it is a genuine lvalue */
+#ifndef USG
+ init_sigio ();
+ request_sigio ();
+#endif /* USG */
+#ifdef F_SETOWN
+ old_fcntl_owner = fcntl (0, F_GETOWN, 0);
+#ifdef F_SETOWN_SOCK_NEG
+ fcntl (0, F_SETOWN, -getpid ()); /* stdin is a socket here */
+#else
+ fcntl (0, F_SETOWN, getpid ());
+#endif /* F_SETOWN_SOCK_NEG */
+#endif /* F_SETOWN */
+#ifndef USG
+ if (unrequest) unrequest_sigio ();
+#endif
+}
+
+/* Process all queued ExposeRegion events. */
+static
+dumpqueue ()
+{
+ register int i;
+ XExposeRegionEvent r;
+ if ((XXqueue.rindex > XXqueue.mindex) ||
+ (XXqueue.windex > XXqueue.mindex) ||
+ (XXqueue.rindex < 0) ||
+ (XXqueue.windex < 0))
+ {
+ PendingExposure = 1;
+ }
+ else
+ while (XXqueue.rindex != XXqueue.windex)
+ {
+ if (CursorExists)
+ CursorToggle ();
+ unloadxrepbuffer (&r, &XXqueue);
+ dumprectangle (r.y - XXInternalBorder, r.x - XXInternalBorder,
+ r.height, r.width);
+ }
+}
+
+XSetFlash ()
+{
+ ring_bell_hook = XTflash;
+}
+
+XSetFeep ()
+{
+ ring_bell_hook = XTfeep;
+}
+
+XNewFont (newname)
+ register char *newname;
+{
+ FontInfo *temp;
+ BLOCK_INPUT_DECLARE ()
+
+ BLOCK_INPUT ();
+ XFlush ();
+ if (XXdebug)
+ fprintf (stderr, "Request id is %d\n", XXdisplay->request);
+ temp = XOpenFont (newname);
+ if (temp == (FontInfo *) 0)
+ {
+ UNBLOCK_INPUT_RESIGNAL ();
+ return -1;
+ }
+ XCloseFont (fontinfo);
+ fontinfo = temp;
+ XSetResizeHint (XXwindow, 2*XXInternalBorder, 2*XXInternalBorder,
+ /* fontinfo->width * 1, fontinfo->height * 1, */
+ fontinfo->width, fontinfo->height);
+ XSetWindowSize (screen_height, screen_width);
+ UNBLOCK_INPUT_RESIGNAL ();
+ return 0;
+}
+
+XFlipColor ()
+{
+ Pixmap temp;
+ int tempcolor;
+ char *tempname;
+ Cursor temp_curs;
+ BLOCK_INPUT_DECLARE ()
+
+ BLOCK_INPUT ();
+ CursorToggle ();
+ temp = XMakeTile (fore);
+ XChangeBackground (XXwindow, temp);
+ XFreePixmap (temp);
+ temp = XMakeTile (back);
+ if (XXborder)
+ XChangeBorder (XXwindow, temp);
+ XFreePixmap (temp);
+ brdr = back;
+ brdr_color = back_color;
+ tempcolor = fore;
+ fore = back;
+ back = tempcolor;
+ tempname = fore_color ;
+ fore_color = back_color;
+ back_color = tempname;
+/* XPixFill (XXwindow, 0, 0, screen_width * fontinfo->width,
+ screen_height * fontinfo->height, back, ClipModeClipped,
+ GXcopy, AllPlanes);
+ dumprectangle (0, 0, screen_height * fontinfo->height + 2 * XXInternalBorder,
+ screen_width * fontinfo -> width + 2 * XXInternalBorder);*/
+ XRedrawDisplay ();
+ if (curs == WhitePixel)
+ {
+ curs = BlackPixel;
+ curs_color = "black";
+ }
+ else if (curs == BlackPixel)
+ {
+ curs = WhitePixel;
+ curs_color = "white";
+ }
+ if (mous == WhitePixel)
+ {
+ mous = BlackPixel;
+ mous_color = "black";
+ }
+ else if (mous == BlackPixel)
+ {
+ mous = WhitePixel;
+ mous_color = "white";
+ }
+ temp_curs = XCreateCursor (16, 16, MouseCursor, MouseMask, 0, 0,
+ mous, back, GXcopy);
+ XUndefineCursor (XXwindow);
+ XDefineCursor (XXwindow, temp_curs);
+ XFreeCursor (EmacsCursor);
+ bcopy (&temp_curs, &EmacsCursor, sizeof (Cursor));
+ CursorToggle ();
+ XFlush ();
+ UNBLOCK_INPUT ();
+}
+
+XSetOffset (xoff, yoff)
+ register int xoff, yoff;
+{
+ BLOCK_INPUT_DECLARE ()
+
+ BLOCK_INPUT ();
+ if (xoff < 0)
+ {
+ XXxoffset = rootwindowinfo.width + (++xoff) - pixelwidth - 4;
+ }
+ else
+ {
+ XXxoffset = xoff;
+ }
+ if (yoff < 0)
+ {
+ XXyoffset
+ = rootwindowinfo.height + (++yoff) - pixelheight - 4;
+ }
+ else
+ {
+ XXyoffset = yoff;
+ }
+ XMoveWindow (XXwindow, XXxoffset, XXyoffset);
+ UNBLOCK_INPUT ();
+ /* XWarpMouse (XXwindow, pixelwidth >> 1, pixelheight >> 1); */
+}
+
+XSetWindowSize (rows, cols)
+ register int rows, cols;
+{
+ /* if (rows < 3) rows = 24;
+ if (cols < 1) cols = 80; */
+ pixelwidth = cols * fontinfo->width + 2 * XXInternalBorder;
+ pixelheight = rows * fontinfo->height + 2 * XXInternalBorder;
+ XChangeWindow (XXwindow, pixelwidth, pixelheight);
+ XFlush ();
+ change_screen_size (rows, cols, 0, 0, 0);
+ PendingExposure = 0;
+}
+
+XPopUpWindow ()
+{
+ BLOCK_INPUT_DECLARE ()
+ if (WindowMapped)
+ return;
+ BLOCK_INPUT ();
+ if (!x_edges_specified)
+ Fx_rubber_band ();
+ bitblt = 0;
+ CursorExists = 0;
+ VisibleX = 0;
+ VisibleY = 0;
+ WindowMapped = 1;
+ XMapWindow (XXwindow);
+ dumprectangle (0, 0,
+ screen_height * fontinfo->height + 2 * XXInternalBorder,
+ screen_width * fontinfo->width + 2 * XXInternalBorder);
+ XSelectInput (XXwindow, KeyPressed | ExposeWindow | ButtonPressed
+ | ButtonReleased
+ | ExposeRegion | ExposeCopy);
+ /* XWarpMouse (XXwindow, pixelwidth >> 1, pixelheight >> 1);*/
+ XTmove_cursor (0, 0);
+ if (IconWindow)
+ {
+ XSetIconWindow (XXwindow,XXIconWindow);
+ XSelectInput (XXIconWindow, ExposeWindow);
+ }
+ else
+ {
+ XClearIconWindow (XXwindow);
+ XSelectInput (XXIconWindow, NoEvent);
+ }
+ /* XRedrawDisplay ();*/
+ XFlush ();
+ UNBLOCK_INPUT ();
+}
+
+spacecheck (mindex, rindex, windex, minfreespace)
+ register int mindex, rindex, windex, minfreespace;
+{
+ if ((rindex > mindex) || (windex > mindex))
+ {
+ /* fprintf (stderr, "Fatal Mouse Buffer Error.\n");
+ fprintf (stderr, "%d = mindex, %d = rindex, %d = windex\n",
+ mindex, rindex, windex); */
+ return -2;
+ }
+ if (windex >= rindex)
+ {
+ if ((mindex - (windex - rindex)) > minfreespace)
+ return 0;
+ }
+ else
+ {
+ if (((rindex - windex) - 1) > minfreespace)
+ return 0;
+ }
+ return -1;
+}
+
+loadxrepbuffer (p_xrep, p_buffer)
+ register XEvent *p_xrep;
+ register XREPBUFFER *p_buffer;
+{
+ p_buffer->xrep[p_buffer->windex] = *p_xrep;
+ if (p_buffer->windex == p_buffer->mindex)
+ p_buffer->windex = 0;
+ else
+ p_buffer->windex++;
+}
+
+unloadxrepbuffer (p_xrep, p_buffer)
+ register XEvent *p_xrep;
+ register XREPBUFFER *p_buffer;
+{
+ if (p_buffer->windex == p_buffer->rindex)
+ return -1;
+ *p_xrep = p_buffer->xrep[p_buffer->rindex];
+ if (p_buffer->rindex == p_buffer->mindex)
+ p_buffer->rindex = 0;
+ else
+ p_buffer->rindex++;
+ return 0;
+}
+
+fixxrepbuffer ()
+{
+ Xxrepbuffer.mindex = XREPBUFSIZE - 1;
+ Xxrepbuffer.windex = 0;
+ Xxrepbuffer.rindex = 0;
+}
+
+#endif /* HAVE_X_WINDOWS */
diff --git a/src/xterm.h b/src/xterm.h
new file mode 100644
index 00000000000..34e8496813b
--- /dev/null
+++ b/src/xterm.h
@@ -0,0 +1,58 @@
+#include <X/Xlib.h>
+
+#define XREPBUFSIZE 64
+
+typedef struct
+ {
+ int rindex;
+ int windex;
+ int mindex;
+ XEvent xrep[XREPBUFSIZE];
+ }
+XREPBUFFER;
+
+extern int x_edges_specified;
+
+#ifndef sigmask
+#define sigmask(no) (1L << ((no) - 1))
+#endif
+
+#ifdef SIGIO
+
+#define BLOCK_INPUT_DECLARE() int BLOCK_INPUT_mask;
+#define BLOCK_INPUT() BLOCK_INPUT_mask = sigblock (sigmask (SIGIO))
+#define UNBLOCK_INPUT() sigsetmask (BLOCK_INPUT_mask)
+#define SIGNAL_INPUT() kill (XXpid, SIGIO)
+
+#define RESIGNAL_INPUT() \
+do \
+{ \
+ if (QLength () > 0) \
+ SIGNAL_INPUT (); \
+} while (0)
+
+#define SIGNAL_INPUT_WHILE(flag) \
+do \
+{ \
+ while (flag) \
+ SIGNAL_INPUT (); \
+} while (0)
+
+#define UNBLOCK_INPUT_RESIGNAL() \
+do \
+{ \
+ UNBLOCK_INPUT (); \
+ RESIGNAL_INPUT (); \
+} while (0)
+
+#else /* SIGIO undefined */
+
+#define BLOCK_INPUT_DECLARE()
+#define BLOCK_INPUT()
+#define UNBLOCK_INPUT()
+#define SIGNAL_INPUT() /* input_available_signal (0) */
+#define RESIGNAL_INPUT()
+#define SIGNAL_INPUT_WHILE(bitblt) /* input_available_signal (0) */
+#define UNBLOCK_INPUT_RESIGNAL()
+
+#endif /* SIGIO */
diff --git a/src/ymakefile b/src/ymakefile
new file mode 100644
index 00000000000..fa1f171af3c
--- /dev/null
+++ b/src/ymakefile
@@ -0,0 +1,535 @@
+/* Makefile for GNU Emacs.
+ Copyright (C) 1985, 1987, 1988, 1990 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+dot = .
+/* on Xenix, replace double-dot below with $(dot)$(dot) */
+lispdir = $(dot)$(dot)/lisp/
+etcdir = $(dot)$(dot)/etc/
+shortnamesdir = $(dot)$(dot)/shortnames/
+cppdir = $(dot)$(dot)/cpp/
+oldXMenudir = $(dot)$(dot)/oldXMenu/
+
+/* Just to avoid uncertainty. */
+SHELL = /bin/sh
+
+#define NO_SHORTNAMES
+#include "config.h"
+
+/* Use HAVE_X11 as an alias for X11 in this file
+ to avoid problems with X11 as a subdirectory name
+ in -I and other such options which pass through this file. */
+
+#ifdef X11
+#define HAVE_X11
+#undef X11
+#endif
+
+/* On some machines #define register is done in config;
+ don't let it interfere with this file. */
+#undef register
+
+/* On some systems we may not to use the system make command. */
+#ifdef MAKE_COMMAND
+MAKE = MAKE_COMMAND
+#else
+MAKE=make
+#endif
+
+#ifdef C_COMPILER
+CC = C_COMPILER
+#endif
+
+/* Some machines don't find the standard C libraries in the usual place. */
+#ifndef ORDINARY_LINK
+#ifndef LIB_STANDARD
+#define LIB_STANDARD -lc
+#endif
+#else
+#ifndef LIB_STANDARD
+#define LIB_STANDARD
+#endif
+#endif
+
+/* Unless inhibited or changed, use -lg to link for debugging. */
+#ifndef LIBS_DEBUG
+#define LIBS_DEBUG -lg
+#endif
+
+/* Some s- files define this to request special libraries. */
+#ifndef LIBS_SYSTEM
+#define LIBS_SYSTEM
+#endif
+
+/* Some m- files define this to request special libraries. */
+#ifndef LIBS_MACHINE
+#define LIBS_MACHINE
+#endif
+
+/* Some s- files define this to request special switches in ld. */
+#ifndef LD_SWITCH_SYSTEM
+#if defined (BSD) && !defined (COFF) && !defined (__GNUC__)
+#define LD_SWITCH_SYSTEM -X
+#else
+#define LD_SWITCH_SYSTEM
+#endif /* COFF, or not BSD */
+#endif
+
+/* Some m- files define this to request special switches in ld. */
+#ifndef LD_SWITCH_MACHINE
+#define LD_SWITCH_MACHINE
+#endif
+
+/* Some m- files define this to request special switches in cc. */
+#ifndef C_SWITCH_MACHINE
+#define C_SWITCH_MACHINE
+#endif
+
+#ifndef C_SWITCH_SYSTEM
+#define C_SWITCH_SYSTEM
+#endif
+
+#ifndef C_SWITCH_X_MACHINE
+#define C_SWITCH_X_MACHINE
+#endif
+
+#ifndef C_SWITCH_X_SYSTEM
+#define C_SWITCH_X_SYSTEM
+#endif
+
+#ifndef ORDINARY_LINK
+#ifndef START_FILES
+#ifdef NO_REMAP
+#define START_FILES pre-crt0.o /lib/crt0.o
+#else
+#define START_FILES crt0.o
+#endif
+#endif /* have START_FILES */
+STARTFILES = START_FILES
+#else /* ORDINARY_LINK */
+STARTFILES = pre-crt0.o
+#endif /* ORDINARY_LINK */
+
+/* This macro says how to compile for debugging.
+ If you want to optimize, DON'T change this macro.
+ Instead, replace C_DEBUG_SWITCH with C_OPTIMIZE_SWITCH
+ where CFLAGS is set. */
+#ifndef C_DEBUG_SWITCH
+#define C_DEBUG_SWITCH -g
+#endif
+
+/* If user wants to optimize, this is how. */
+#ifndef C_OPTIMIZE_SWITCH
+#define C_OPTIMIZE_SWITCH -O
+#endif
+
+/* cc switches needed to make `asm' keyword work.
+ Nothing special needed on most machines. */
+#ifndef C_SWITCH_ASM
+#define C_SWITCH_ASM
+#endif
+
+/* Specify address for ld to start loading at,
+ if requested by configuration. */
+
+#ifdef LD_TEXT_START_ADDR
+STARTFLAGS = -T LD_TEXT_START_ADDR -e __start
+#endif
+
+#ifndef LINKER
+#ifdef ORDINARY_LINK
+LD = $(CC)
+#else /* not ORDINARY_LINK */
+#if __GNUC__ > 1
+/* Search the proper places so that we can find -lgcc. */
+#define LINKER gcc -nostdlib
+#else
+#define LINKER ld
+#endif
+#endif /* not ORDINARY_LINK */
+#endif /* no LINKER */
+
+#ifdef LINKER
+LD = LINKER
+#endif
+LDFLAGS = LD_SWITCH_SYSTEM LD_SWITCH_MACHINE
+
+/* Figure out whether the system cpp can handle long names.
+ Do it by testing it right now.
+ If it loses, arrange to use the GNU cpp. */
+
+#define LONGNAMEBBBFOOX
+#ifdef LONGNAMEBBBARFOOX
+/* Installed cpp fails to distinguish those names! */
+/* Arrange to compile the GNU cpp later on */
+#define NEED_CPP
+/* Cause cc to invoke the cpp that comes with Emacs,
+ which will be in a file named localcpp. */
+MYCPPFLAG= -Blocal
+/* LOCALCPP is the local one or nothing.
+ CPP is the local one or the standardone. */
+LOCALCPP= localcpp
+#endif /* NEED_CPP */
+
+#ifdef SHORTNAMES
+SHORT= shortnames
+#endif /* SHORTNAMES */
+
+CFLAGS= C_DEBUG_SWITCH -Demacs $(MYCPPFLAG) C_SWITCH_MACHINE C_SWITCH_SYSTEM C_SWITCH_X_MACHINE C_SWITCH_X_SYSTEM
+/* DO NOT use -R. There is a special hack described in lastfile.c
+ which is used instead. Some initialized data areas are modified
+ at initial startup, then labeled as part of the text area when
+ Emacs is dumped for the first time, and never changed again. */
+
+/* You may replace C_DEBUG_SWITCH with C_OPTIMIZE_SWITCH
+ if you don't believe in debugging. */
+
+/* -Demacs is needed to make some files produce the
+ correct version for use in Emacs. */
+
+#ifndef LIBX10_MACHINE
+#define LIBX10_MACHINE
+#endif
+
+#ifndef LIBX11_MACHINE
+#define LIBX11_MACHINE
+#endif
+
+#ifndef LIBX10_SYSTEM
+#define LIBX10_SYSTEM
+#endif
+
+#ifndef LIBX11_SYSTEM
+#define LIBX11_SYSTEM
+#endif
+
+#ifndef LIB_X11_LIB
+#define LIB_X11_LIB -lX11
+#endif
+
+#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_X11
+#ifdef HAVE_X_MENU
+OLDXMENU = libXMenu11.a
+XOBJ = x11term.o x11fns.o xmenu.o
+LIBX = $(OLDXMENU) LIB_X11_LIB LIBX11_MACHINE LIBX11_SYSTEM
+#else
+XOBJ = x11term.o x11fns.o
+LIBX = LIB_X11_LIB LIBX11_MACHINE LIBX11_SYSTEM
+#endif
+#else /* not HAVE_X11 */
+#ifdef HAVE_X_MENU
+XOBJ= xterm.o xfns.o xmenu.o
+LIBX= -lXMenu -lX LIBX10_MACHINE LIBX10_SYSTEM
+#else
+XOBJ= xterm.o xfns.o
+LIBX= -lX LIBX10_MACHINE LIBX10_SYSTEM
+#endif /* not HAVE_X_MENU */
+#endif /* not HAVE_X11 */
+#endif /* HAVE_X_WINDOWS */
+
+/* Fix linking if compiled with GCC. */
+#ifdef __GNUC__
+#if __GNUC__ > 1
+#ifndef LIB_GCC
+#define LIB_GCC -lgcc
+#endif
+GNULIB_VAR = LIB_GCC
+#else /* __GNUC__ <= 1 */
+#ifndef LIB_GCC
+#define LIB_GCC /usr/local/lib/gcc-gnulib
+#endif
+GNULIB_VAR = `if [ -f LIB_GCC ] ; then echo LIB_GCC; else echo; fi`
+#endif /* __GNUC__ <= 1 */
+#else
+GNULIB_VAR =
+#endif
+
+#ifdef MAINTAIN_ENVIRONMENT
+environobj = environ.o
+#endif /* MAINTAIN_ENVIRONMENT */
+
+/* Allow config.h to specify a replacement file for unexec.c. */
+#ifndef UNEXEC
+#define UNEXEC unexec.o
+#endif
+
+/* lastfile must follow all files
+ whose initialized data areas should be dumped as pure by dump-emacs. */
+obj= dispnew.o scroll.o xdisp.o window.o \
+ term.o cm.o $(XOBJ) \
+ emacs.o keyboard.o macros.o keymap.o sysdep.o \
+ buffer.o filelock.o insdel.o marker.o \
+ minibuf.o fileio.o dired.o filemode.o \
+ cmds.o casefiddle.o indent.o search.o regex.o undo.o \
+ alloc.o data.o doc.o editfns.o callint.o \
+ eval.o fns.o print.o lread.o \
+ abbrev.o syntax.o UNEXEC mocklisp.o bytecode.o \
+ process.o callproc.o $(environobj) \
+ doprnt.o
+
+#ifdef TERMINFO
+/* Used to be -ltermcap here. If your machine needs that,
+ define LIBS_TERMCAP in the m- file. */
+#ifndef LIBS_TERMCAP
+#define LIBS_TERMCAP -lcurses
+#endif
+termcapobj = terminfo.o
+#else
+#ifndef LIBS_TERMCAP
+#define LIBS_TERMCAP
+termcapobj = termcap.o tparam.o
+#else
+termcapobj = tparam.o
+#endif
+#endif
+
+#ifndef SYSTEM_MALLOC
+#ifdef HAVE_ALLOCA
+mallocobj = malloc.o
+#else
+mallocobj = alloca.o malloc.o
+#endif
+#else /* SYSTEM_MALLOC */
+#ifndef HAVE_ALLOCA
+mallocobj = alloca.o
+#endif
+#endif
+
+/* define otherobj as list of object files that make-docfile
+ should not be told about. */
+otherobj= $(termcapobj) lastfile.o $(mallocobj)
+
+/* List of Lisp files loaded into the dumped Emacs. */
+lisp= ${lispdir}simple.elc ${lispdir}help.elc \
+ ${lispdir}files.elc ${lispdir}window.elc \
+ ${lispdir}indent.elc ${lispdir}loaddefs.el ${lispdir}paths.el \
+ ${lispdir}startup.elc ${lispdir}lisp.elc \
+ ${lispdir}page.elc ${lispdir}register.elc \
+ ${lispdir}paragraphs.elc ${lispdir}lisp-mode.elc \
+ ${lispdir}text-mode.elc ${lispdir}fill.elc \
+ ${lispdir}c-mode.elc ${lispdir}isearch.elc \
+ ${lispdir}replace.elc ${lispdir}abbrev.elc \
+ ${lispdir}buff-menu.elc ${lispdir}subr.elc
+
+/* just to be sure the sh is used */
+SHELL=/bin/sh
+
+/* Construct full set of libraries to be linked. */
+LIBES = LIBS_TERMCAP $(LIBX) LIBS_SYSTEM LIBS_MACHINE LIBS_DEBUG $(GNULIB_VAR) LIB_STANDARD
+
+/* Enable recompilation of certain other files depending on system type. */
+
+#ifndef OTHER_FILES
+#define OTHER_FILES
+#endif
+
+/* Enable inclusion of object files in temacs depending on system type. */
+#ifndef OBJECTS_SYSTEM
+#define OBJECTS_SYSTEM
+#endif
+
+#ifndef OBJECTS_MACHINE
+#define OBJECTS_MACHINE
+#endif
+
+all: xemacs OTHER_FILES
+
+xemacs: temacs ${etcdir}DOC ${lisp}
+#ifdef HAVE_SHM
+ ./temacs -nl -batch -l inc-vers
+ ./temacs -nl -batch -l loadup dump
+ ln temacs xemacs
+#else
+#ifdef CANNOT_DUMP
+ mv temacs xemacs
+#else
+ ./temacs -batch -l inc-vers
+ ./temacs -batch -l loadup.el dump
+#endif /* not CANNOT_DUMP */
+#endif /* not HAVE_SHM */
+
+${etcdir}DOC: ${etcdir}make-docfile ${obj} ${lisp}
+ rm -f ${etcdir}DOC
+ ${etcdir}make-docfile ${obj} ${lisp} ${lispdir}version.el > ${etcdir}DOC
+
+${etcdir}make-docfile:
+ cd ${etcdir}; ${MAKE} ${MFLAGS} make-docfile
+
+/* Some systems define this to cause parallel Make-ing. */
+#ifndef MAKE_PARALLEL
+#define MAKE_PARALLEL
+#endif
+
+temacs: MAKE_PARALLEL $(LOCALCPP) $(SHORT) $(STARTFILES) $(OLDXMENU) ${obj} ${otherobj} OBJECTS_SYSTEM OBJECTS_MACHINE
+ $(LD) ${STARTFLAGS} ${LDFLAGS} -o temacs ${STARTFILES} ${obj} ${otherobj} OBJECTS_SYSTEM OBJECTS_MACHINE ${LIBES}
+
+/* These are needed for C compilation, on the systems that need them */
+#ifdef NEED_CPP
+CPP = ./localcpp
+localcpp:
+ cd ${cppdir}; ${MAKE} ${MFLAGS} EMACS=-DEMACS
+ ln ${cppdir}cpp localcpp /* Name where CFLAGS will refer to it */
+/* cc appears to be cretinous and require all of these to exist
+ if -B is specified -- we can't use one local pass and let the
+ others be the standard ones. What a loser.
+ We can't even use ln, since they are probably
+ on different disks. */
+ cp /lib/ccom localccom
+ -cp /lib/optim localoptim
+ -cp /lib/c2 localc2
+ cp /bin/as localas
+#else /* not NEED_CPP */
+CPP = $(CC) -E
+#endif /* need NEED_CPP */
+
+#ifdef SHORTNAMES
+shortnames:
+ cd ${shortnamesdir}; ${MAKE} ${MFLAGS}
+#endif /* SHORTNAMES */
+
+/* Don't lose if this was not defined. */
+#ifndef OLDXMENU_OPTIONS
+#define OLDXMENU_OPTIONS
+#endif
+
+#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_X_MENU
+#ifdef HAVE_X11
+$(OLDXMENU):
+ cd ${oldXMenudir}; ${MAKE} ${MFLAGS} OLDXMENU_OPTIONS
+ ln ${oldXMenudir}libXMenu11.a $(OLDXMENU) || cp ${oldXMenudir}libXMenu11.a $(OLDXMENU)
+#endif /* HAVE_X11 */
+#endif /* HAVE_X_MENU */
+#endif /* HAVE_X_WINDOWS */
+
+paths.h: paths.h-dist
+ echo paths.h needs to be set up from paths.h-dist
+ exit 1
+
+config.h: config.h-dist
+ echo config.h needs to be set up from config.h-dist
+ exit 1
+
+/* Some machines have alloca built-in.
+ They should define HAVE_ALLOCA, or may just let alloca.s
+ be used but generate no code.
+ Some have it written in assembler in alloca.s.
+ Some use the C version in alloca.c (these define C_ALLOCA in config.h).
+ */
+
+#ifdef C_ALLOCA
+alloca.o : alloca.c
+#else
+#ifndef HAVE_ALLOCA
+alloca.o : alloca.s config.h
+/* $(CPP) is cc -E, which may get confused by filenames
+ that do not end in .c. So copy file to a safe name. */
+ cp alloca.s allocatem.c
+/* remove any ^L, blank lines, and preprocessor comments,
+ since some assemblers barf on them */
+ $(CPP) allocatem.c | \
+ sed -e 's/ //' -e 's/^#.*//' | \
+ sed -n -e '/^..*$$/p' > allocatem.s
+ -rm -f alloca.o
+/* Xenix, in particular, needs to run assembler via cc. */
+ cc -c allocatem.s
+ mv allocatem.o alloca.o
+ rm allocatem.s allocatem.c
+#endif /* HAVE_ALLOCA */
+#endif /* not C_ALLOCA */
+
+/* Nearly all the following files depend on lisp.h,
+ but it is not included as a dependency because
+ it is so often changed in ways that do not require any recompilation
+ and so rarely changed in ways that do require any. */
+
+abbrev.o : abbrev.c buffer.h commands.h config.h
+buffer.o : buffer.c syntax.h buffer.h commands.h window.h config.h
+callint.o : callint.c window.h commands.h buffer.h config.h
+callproc.o : callproc.c paths.h buffer.h commands.h config.h
+casefiddle.o : casefiddle.c syntax.h commands.h buffer.h config.h
+cm.o : cm.c cm.h termhooks.h config.h
+cmds.o : cmds.c syntax.h buffer.h commands.h config.h
+crt0.o : crt0.c config.h
+ $(CC) -c $(CFLAGS) C_SWITCH_ASM crt0.c
+dired.o : dired.c commands.h buffer.h config.h regex.h
+dispnew.o : dispnew.c commands.h window.h buffer.h dispextern.h termchar.h termopts.h cm.h config.h lisp.h
+doc.o : doc.c buffer.h config.h paths.h
+doprnt.o : doprnt.c
+editfns.o : editfns.c window.h buffer.h config.h
+emacs.o : emacs.c commands.h config.h
+#ifdef MAINTAIN_ENVIRONMENT
+environ.o : environ.c buffer.h commands.h config.h
+#endif /* MAINTAIN_ENVIRONMENT */
+fileio.o : fileio.c window.h buffer.h config.h
+filelock.o : filelock.c buffer.h paths.h config.h
+filemode.o : filemode.c
+indent.o : indent.c window.h indent.h buffer.h config.h termchar.h termopts.h
+insdel.o : insdel.c window.h buffer.h config.h
+keyboard.o : keyboard.c termchar.h termhooks.h termopts.h buffer.h commands.h window.h macros.h config.h
+keymap.o : keymap.c buffer.h commands.h config.h
+lastfile.o : lastfile.c
+macros.o : macros.c window.h buffer.h commands.h macros.h config.h
+malloc.o : malloc.c config.h
+marker.o : marker.c buffer.h config.h
+minibuf.o : minibuf.c syntax.h window.h buffer.h commands.h config.h
+mocklisp.o : mocklisp.c buffer.h config.h
+process.o : process.c process.h buffer.h window.h termhooks.h termopts.h commands.h dispextern.h config.h
+regex.o : regex.c syntax.h buffer.h config.h regex.h
+scroll.o : scroll.c termchar.h config.h dispextern.h termhooks.h
+search.o : search.c regex.h commands.h buffer.h syntax.h config.h
+syntax.o : syntax.c syntax.h buffer.h commands.h config.h
+sysdep.o : sysdep.c config.h dispextern.h termhooks.h termchar.h termopts.h window.h
+term.o : term.c termchar.h termhooks.h termopts.h config.h cm.h
+termcap.o : termcap.c config.h
+terminfo.o : terminfo.c config.h
+tparam.o : tparam.c config.h
+undo.o : undo.c buffer.h commands.h config.h
+UNEXEC : config.h getpagesize.h
+window.o : window.c indent.h commands.h window.h buffer.h config.h termchar.h
+xdisp.o : xdisp.c macros.h commands.h indent.h buffer.h dispextern.h termchar.h window.h config.h
+xfns.o : xfns.c xterm.h window.h config.h
+xmenu.o : xmenu.c xterm.h window.h config.h
+xterm.o : xterm.c xterm.h termhooks.h termopts.h termchar.h \
+ dispextern.h config.h sink.h sinkmask.h
+
+x11fns.o : x11fns.c window.h x11term.h dispextern.h termchar.h config.h
+x11term.o : x11term.c x11term.h termhooks.h termopts.h termchar.h \
+ dispextern.h config.h sink11.h sink11mask.h lisp.h gettime.h emacssignal.h \
+ xkeys-aix.h
+
+/* The files of Lisp proper */
+
+alloc.o : alloc.c window.h buffer.h config.h
+bytecode.o : bytecode.c buffer.h config.h
+data.o : data.c buffer.h config.h
+eval.o : eval.c commands.h config.h
+fns.o : fns.c buffer.h commands.h config.h
+print.o : print.c process.h window.h buffer.h dispextern.h termchar.h config.h
+lread.o : lread.c buffer.h paths.h config.h
+
+/* System-specific programs to be made.
+ OTHER_FILES, OBJECTS_SYSTEM and OBJECTS_MACHINE
+ select which of these should be compiled. */
+
+sunfns.o : sunfns.c buffer.h config.h
+
+${etcdir}emacstool: ${etcdir}emacstool.c
+ cd ${etcdir}; ${MAKE} ${MFLAGS} emacstool
diff --git a/vmsdist.com b/vmsdist.com
new file mode 100644
index 00000000000..999c3b8ecff
--- /dev/null
+++ b/vmsdist.com
@@ -0,0 +1,87 @@
+$ ! Command file to build Emacs on VMS and create a backup saveset.
+$ ! rms, 16 May 1988
+$
+$ ! We assume that the files have been read in to a directory
+$ ! $disk1:[rms.dist.emacs]; you should replace `$disk1:[rms.dist'
+$ ! with the actual name of the superior directory of [.emacs].
+$ ! This replacement needs to be done in a few places.
+$
+$ ! You should be in that directory when you run this command file.
+$
+$ ! We also assume that the tar-tape reader has changed all `-' to `_'
+$ ! in filenames. If this is not so, delete the first `@allrename' command.
+$
+$ ! You must also edit the mag tape device name
+$ ! And the Emacs version that appears in the saveset name.
+$
+$ ! Change to vms 4.4 filenames.
+$ @allrename [...] "_" "-"
+$
+$ ! Set up logical devices so we can compile and run Emacs.
+$
+$ edit/edt/nocommand emacs.com
+s/sys$sysdevice:[emacs.]/$disk1:[rms.dist_18.emacs.]/w
+exit
+$ @emacs
+$ ! Delete the modified emacs.com so we leave the source files clean.
+$ ! emacs.com must be edited for real when Emacs is installed
+$ ! on another machine. This version wouldn't be right anyway.
+$ delete emacs.com;0
+$
+$ ! Edit the configuration files.
+$
+$ set def [.src]
+$ copy vmspaths.h paths.h
+$ copy config.h-dist config.h
+$ edit/edt/nocommand config.h
+s/s-bsd4-2.h/s-vms5-5.h/w
+exit
+$
+$ ! Compile, link and dump Emacs.
+$
+$ @compile
+$ @link
+$ @[-.etc]complink
+$ @[-.etc]makedoc
+$ @build
+$
+$ ! Move the executable and image to the appropriate place.
+$
+$ rename temacs.exe [-]emacs.exe
+$ rename temacs.dump [-]emacs.dump
+$ ! No longer necessary since VMS systems come with this file.
+$ ! copy sys$library:vaxcrtl.olb vaxcrtl.olb
+$
+$ ! Recompile a few files for vms version 4.2.
+$ ! Call these object files for 4.2 `.jbo'.
+$
+$ edit/edt/nocommand config.h
+s/vms4-4/vms4-2/w
+exit
+$ rename doc.obj doc.obx
+$ rename fileio.obj fileio.obx
+$ rename sysdep.obj sysdep.obx
+$ rename vmsfns.obj vmsfns.obx
+$ @recomp doc
+$ @recomp fileio
+$ @recomp sysdep
+$ @recomp vmsfns
+$ rename doc.obj doc.jbo
+$ rename fileio.obj fileio.jbo
+$ rename sysdep.obj sysdep.jbo
+$ rename vmsfns.obj vmsfns.jbo
+$ rename *.obx *.obj
+$ delete config.h;0
+$
+$ ! Change all files back to the names that VMS 4.2 can read in.
+$
+$ set def [-]
+$ @allrename [...] "-" "_"
+$
+$ ! Dump onto tape
+$
+$ mount /foreign mua0:
+$ define /translation=concealed dumping $disk1:[rms.dist_18.]
+$ set def dumping:[emacs]
+$ backup /interchange /verify /list [...] mua0:emacs18.51
+$ dismount mua0: